drm/amdgpu: refine code for VCE2.0 and related dpm code.
authorRex Zhu <Rex.Zhu@amd.com>
Thu, 26 Jan 2017 08:25:05 +0000 (16:25 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 8 Feb 2017 22:22:27 +0000 (17:22 -0500)
v2: clean up vce cg function.
    use sw cg when vce stoped.

1. implement vce_stop function.
2. not start vce when hw_init.
3. refine vce cg/pg code.
4. delete bypass mode.

Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/kv_dpm.c
drivers/gpu/drm/amd/amdgpu/vce_v2_0.c

index a61882ddc804ee08b465b3b9d9d907c5a5741db9..95e026a4a2deb598d883887dcbd47a4f6e2f995a 100644 (file)
@@ -1142,12 +1142,22 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
                        /* XXX select vce level based on ring/task */
                        adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
                        mutex_unlock(&adev->pm.mutex);
+                       amdgpu_pm_compute_clocks(adev);
+                       amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+                                                       AMD_PG_STATE_UNGATE);
+                       amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+                                                       AMD_CG_STATE_UNGATE);
                } else {
+                       amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+                                                       AMD_PG_STATE_GATE);
+                       amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
+                                                       AMD_CG_STATE_GATE);
                        mutex_lock(&adev->pm.mutex);
                        adev->pm.dpm.vce_active = false;
                        mutex_unlock(&adev->pm.mutex);
+                       amdgpu_pm_compute_clocks(adev);
                }
-               amdgpu_pm_compute_clocks(adev);
+
        }
 }
 
index a947022bfee81c289173cb8aac6f1c7a36671d1a..f97ecb49972e411cfb8c47cb661194bf0b378f67 100644 (file)
@@ -4256,12 +4256,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
 
        if (amdgpu_current_state->evclk != amdgpu_new_state->evclk) {
                if (amdgpu_new_state->evclk) {
-                       /* turn the clocks on when encoding */
-                       ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
-                                                           AMD_CG_STATE_UNGATE);
-                       if (ret)
-                               return ret;
-
                        pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(adev);
                        tmp = RREG32_SMC(ixDPM_TABLE_475);
                        tmp &= ~DPM_TABLE_475__VceBootLevel_MASK;
@@ -4273,9 +4267,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
                        ret = ci_enable_vce_dpm(adev, false);
                        if (ret)
                                return ret;
-                       /* turn the clocks off when not encoding */
-                       ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
-                                                           AMD_CG_STATE_GATE);
                }
        }
        return ret;
index 8159a2dbe4276f4bcd6ff852a1ff37e6c6409be1..f5a343cb00107ba5800362113c30ae2dae409bd8 100644 (file)
@@ -1550,11 +1550,6 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev,
 
        if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) {
                kv_dpm_powergate_vce(adev, false);
-               /* turn the clocks on when encoding */
-               ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
-                                                   AMD_CG_STATE_UNGATE);
-               if (ret)
-                       return ret;
                if (pi->caps_stable_p_state)
                        pi->vce_boot_level = table->count - 1;
                else
@@ -1573,15 +1568,9 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev,
                        amdgpu_kv_send_msg_to_smc_with_parameter(adev,
                                                          PPSMC_MSG_VCEDPM_SetEnabledMask,
                                                          (1 << pi->vce_boot_level));
-
                kv_enable_vce_dpm(adev, true);
        } else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) {
                kv_enable_vce_dpm(adev, false);
-               /* turn the clocks off when not encoding */
-               ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
-                                                   AMD_CG_STATE_GATE);
-               if (ret)
-                       return ret;
                kv_dpm_powergate_vce(adev, true);
        }
 
@@ -1713,32 +1702,19 @@ static void kv_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
 static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
 {
        struct kv_power_info *pi = kv_get_pi(adev);
-       int ret;
 
        if (pi->vce_power_gated == gate)
                return;
 
        pi->vce_power_gated = gate;
 
-       if (gate) {
-               if (pi->caps_vce_pg) {
-                       /* shutdown the VCE block */
-                       ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
-                                                           AMD_PG_STATE_GATE);
-                       /* XXX: check for errors */
-                       /* power off the VCE block */
-                       amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF);
-               }
-       } else {
-               if (pi->caps_vce_pg) {
-                       /* power on the VCE block */
-                       amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON);
-                       /* re-init the VCE block */
-                       ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
-                                                           AMD_PG_STATE_UNGATE);
-                       /* XXX: check for errors */
-               }
-       }
+       if (!pi->caps_vce_pg)
+               return;
+
+       if (gate)
+               amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF);
+       else
+               amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON);
 }
 
 static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate)
@@ -2996,7 +2972,6 @@ static int kv_dpm_late_init(void *handle)
 
        kv_dpm_powergate_acp(adev, true);
        kv_dpm_powergate_samu(adev, true);
-       kv_dpm_powergate_vce(adev, true);
 
        return 0;
 }
index 38ed903dd6f821bbdb20b098eee61ce820fe745f..13c794961073596e6940cde8ebc1485df4718dca 100644 (file)
@@ -46,6 +46,11 @@ static void vce_v2_0_mc_resume(struct amdgpu_device *adev);
 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev);
 static int vce_v2_0_wait_for_idle(void *handle);
+static void vce_v2_0_init_cg(struct amdgpu_device *adev);
+static void vce_v2_0_disable_cg(struct amdgpu_device *adev);
+static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable,
+                                                               bool sw_cg);
+
 /**
  * vce_v2_0_ring_get_rptr - get read pointer
  *
@@ -152,11 +157,14 @@ static int vce_v2_0_start(struct amdgpu_device *adev)
        struct amdgpu_ring *ring;
        int r;
 
-       vce_v2_0_mc_resume(adev);
-
        /* set BUSY flag */
        WREG32_P(mmVCE_STATUS, 1, ~1);
 
+       vce_v2_0_init_cg(adev);
+       vce_v2_0_disable_cg(adev);
+
+       vce_v2_0_mc_resume(adev);
+
        ring = &adev->vce.ring[0];
        WREG32(mmVCE_RB_RPTR, ring->wptr);
        WREG32(mmVCE_RB_WPTR, ring->wptr);
@@ -189,6 +197,54 @@ static int vce_v2_0_start(struct amdgpu_device *adev)
        return 0;
 }
 
+static int vce_v2_0_stop(struct amdgpu_device *adev)
+{
+       int i, j;
+       int status;
+
+       if (vce_v2_0_lmi_clean(adev)) {
+               DRM_INFO("vce is not idle \n");
+               return 0;
+       }
+/*
+       for (i = 0; i < 10; ++i) {
+               for (j = 0; j < 100; ++j) {
+                       status = RREG32(mmVCE_FW_REG_STATUS);
+                       if (!(status & 1))
+                               break;
+                       mdelay(1);
+               }
+               break;
+       }
+*/
+       if (vce_v2_0_wait_for_idle(adev)) {
+               DRM_INFO("VCE is busy, Can't set clock gateing");
+               return 0;
+       }
+
+       /* Stall UMC and register bus before resetting VCPU */
+       WREG32_P(mmVCE_LMI_CTRL2, 1 << 8, ~(1 << 8));
+
+       for (i = 0; i < 10; ++i) {
+               for (j = 0; j < 100; ++j) {
+                       status = RREG32(mmVCE_LMI_STATUS);
+                       if (status & 0x240)
+                               break;
+                       mdelay(1);
+               }
+               break;
+       }
+
+       WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x80001);
+
+       /* put LMI, VCPU, RBC etc... into reset */
+       WREG32_P(mmVCE_SOFT_RESET, 1, ~0x1);
+
+       WREG32(mmVCE_STATUS, 0);
+
+       return 0;
+}
+
 static int vce_v2_0_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -254,11 +310,8 @@ static int vce_v2_0_hw_init(void *handle)
        int r, i;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       r = vce_v2_0_start(adev);
-       /* this error mean vcpu not in running state, so just skip ring test, not stop driver initialize */
-       if (r)
-               return 0;
-
+       amdgpu_asic_set_vce_clocks(adev, 10000, 10000);
+       vce_v2_0_enable_mgcg(adev, true, false);
        for (i = 0; i < adev->vce.num_rings; i++)
                adev->vce.ring[i].ready = false;
 
@@ -349,50 +402,40 @@ static void vce_v2_0_set_sw_cg(struct amdgpu_device *adev, bool gated)
 
 static void vce_v2_0_set_dyn_cg(struct amdgpu_device *adev, bool gated)
 {
-       if (vce_v2_0_wait_for_idle(adev)) {
-               DRM_INFO("VCE is busy, Can't set clock gateing");
-               return;
-       }
-
-       WREG32_P(mmVCE_LMI_CTRL2, 0x100, ~0x100);
+       u32 orig, tmp;
 
-       if (vce_v2_0_lmi_clean(adev)) {
-               DRM_INFO("LMI is busy, Can't set clock gateing");
-               return;
-       }
-
-       WREG32_P(mmVCE_VCPU_CNTL, 0, ~VCE_VCPU_CNTL__CLK_EN_MASK);
-       WREG32_P(mmVCE_SOFT_RESET,
-                VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
-                ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
-       WREG32(mmVCE_STATUS, 0);
+/* LMI_MC/LMI_UMC always set in dynamic,
+ * set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0}
+ */
+       tmp = RREG32(mmVCE_CLOCK_GATING_B);
+       tmp &= ~0x00060006;
 
-       if (gated)
-               WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
-       /* LMI_MC/LMI_UMC always set in dynamic, set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0} */
+/* Exception for ECPU, IH, SEM, SYS blocks needs to be turned on/off by SW */
        if (gated) {
-               /* Force CLOCK OFF , set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {*, 1} */
-               WREG32(mmVCE_CLOCK_GATING_B, 0xe90010);
+               tmp |= 0xe10000;
+               WREG32(mmVCE_CLOCK_GATING_B, tmp);
        } else {
-               /* Force CLOCK ON, set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {1, 0} */
-               WREG32(mmVCE_CLOCK_GATING_B, 0x800f1);
+               tmp |= 0xe1;
+               tmp &= ~0xe10000;
+               WREG32(mmVCE_CLOCK_GATING_B, tmp);
        }
 
-       /* Set VCE_UENC_CLOCK_GATING always in dynamic mode {*_FORCE_ON, *_FORCE_OFF} = {0, 0}*/;
-       WREG32(mmVCE_UENC_CLOCK_GATING, 0x40);
+       orig = tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
+       tmp &= ~0x1fe000;
+       tmp &= ~0xff000000;
+       if (tmp != orig)
+               WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
+
+       orig = tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
+       tmp &= ~0x3fc;
+       if (tmp != orig)
+               WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
 
        /* set VCE_UENC_REG_CLOCK_GATING always in dynamic mode */
        WREG32(mmVCE_UENC_REG_CLOCK_GATING, 0x00);
 
-       WREG32_P(mmVCE_LMI_CTRL2, 0, ~0x100);
-       if(!gated) {
-               WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK);
-               mdelay(100);
-               WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
-
-               vce_v2_0_firmware_loaded(adev);
-               WREG32_P(mmVCE_STATUS, 0, ~VCE_STATUS__JOB_BUSY_MASK);
-       }
+       if(gated)
+               WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
 }
 
 static void vce_v2_0_disable_cg(struct amdgpu_device *adev)
@@ -400,10 +443,9 @@ static void vce_v2_0_disable_cg(struct amdgpu_device *adev)
        WREG32(mmVCE_CGTT_CLK_OVERRIDE, 7);
 }
 
-static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
+static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable,
+                                                               bool sw_cg)
 {
-       bool sw_cg = false;
-
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) {
                if (sw_cg)
                        vce_v2_0_set_sw_cg(adev, true);
@@ -473,8 +515,6 @@ static void vce_v2_0_mc_resume(struct amdgpu_device *adev)
 
        WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
        WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1);
-
-       vce_v2_0_init_cg(adev);
 }
 
 static bool vce_v2_0_is_idle(void *handle)
@@ -539,33 +579,20 @@ static int vce_v2_0_process_interrupt(struct amdgpu_device *adev,
        return 0;
 }
 
-static void vce_v2_0_set_bypass_mode(struct amdgpu_device *adev, bool enable)
-{
-       u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL);
-
-       if (enable)
-               tmp |= GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK;
-       else
-               tmp &= ~GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK;
-
-       WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp);
-}
-
-
 static int vce_v2_0_set_clockgating_state(void *handle,
                                          enum amd_clockgating_state state)
 {
        bool gate = false;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
-
+       bool sw_cg = false;
 
-       vce_v2_0_set_bypass_mode(adev, enable);
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (state == AMD_CG_STATE_GATE)
+       if (state == AMD_CG_STATE_GATE) {
                gate = true;
+               sw_cg = true;
+       }
 
-       vce_v2_0_enable_mgcg(adev, gate);
+       vce_v2_0_enable_mgcg(adev, gate, sw_cg);
 
        return 0;
 }
@@ -582,12 +609,8 @@ static int vce_v2_0_set_powergating_state(void *handle,
         */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
-               return 0;
-
        if (state == AMD_PG_STATE_GATE)
-               /* XXX do we need a vce_v2_0_stop()? */
-               return 0;
+               return vce_v2_0_stop(adev);
        else
                return vce_v2_0_start(adev);
 }