Sometimes the VCE PLL times out while we are programming it.
When it happens, the VCE still works, but much slower.
Observed on some Tahiti boards, but not all:
- FirePro W9000 has the issue
- Radeon R9 280X not affected
- Radeon HD 7990 not affected

Continue the complete VCE PLL programming sequence even when
it timed out. With this, the VCE will work fine and faster
after the timeout happened.

Signed-off-by: Timur Kristóf <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/si.c       |  6 +-----
 drivers/gpu/drm/amd/amdgpu/vce_v1_0.c | 10 +++++++++-
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index f7b35b860ba3..ed3d4f9bf9d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -1902,7 +1902,7 @@ static int si_vce_send_vcepll_ctlreq(struct amdgpu_device 
*adev)
        WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
 
        if (i == SI_MAX_CTLACKS_ASSERTION_WAIT) {
-               DRM_ERROR("Timeout setting VCE clocks!\n");
+               DRM_WARN("Timeout setting VCE clocks!\n");
                return -ETIMEDOUT;
        }
 
@@ -1954,8 +1954,6 @@ static int si_set_vce_clocks(struct amdgpu_device *adev, 
u32 evclk, u32 ecclk)
        mdelay(1);
 
        r = si_vce_send_vcepll_ctlreq(adev);
-       if (r)
-               return r;
 
        /* Assert VCEPLL_RESET again */
        WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, VCEPLL_RESET_MASK, 
~VCEPLL_RESET_MASK);
@@ -1988,8 +1986,6 @@ static int si_set_vce_clocks(struct amdgpu_device *adev, 
u32 evclk, u32 ecclk)
        WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL, 0, ~VCEPLL_BYPASS_EN_MASK);
 
        r = si_vce_send_vcepll_ctlreq(adev);
-       if (r)
-               return r;
 
        /* Switch VCLK and DCLK selection */
        WREG32_SMC_P(CG_VCEPLL_FUNC_CNTL_2,
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v1_0.c 
b/drivers/gpu/drm/amd/amdgpu/vce_v1_0.c
index 27f70146293d..fdc455797258 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v1_0.c
@@ -401,7 +401,7 @@ static int vce_v1_0_wait_for_idle(struct amdgpu_ip_block 
*ip_block)
 static int vce_v1_0_start(struct amdgpu_device *adev)
 {
        struct amdgpu_ring *ring;
-       int r;
+       int r, i;
 
        WREG32_P(mmVCE_STATUS, 1, ~1);
 
@@ -443,6 +443,14 @@ static int vce_v1_0_start(struct amdgpu_device *adev)
        /* Clear VCE_STATUS, otherwise SRBM thinks VCE1 is busy. */
        WREG32(mmVCE_STATUS, 0);
 
+       /* Wait for VCE_STATUS to actually clear.
+        * This helps when there was a timeout setting the VCE clocks.
+        */
+       for (i = 0; i < adev->usec_timeout && RREG32(mmVCE_STATUS); ++i) {
+               udelay(1);
+               WREG32(mmVCE_STATUS, 0);
+       }
+
        if (r) {
                dev_err(adev->dev, "VCE not responding, giving up!!!\n");
                return r;
-- 
2.51.0

Reply via email to