drm/amdgpu/vcn: add sw clock gating
authorHuang Rui <ray.huang@amd.com>
Thu, 20 Apr 2017 01:42:41 +0000 (09:42 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 24 May 2017 21:41:47 +0000 (17:41 -0400)
Add sw controlled clockgating for VCN.

Signed-off-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c

index 6f26a05..15a2c0f 100644 (file)
@@ -281,6 +281,207 @@ static void vcn_v1_0_mc_resume(struct amdgpu_device *adev)
 }
 
 /**
+ * vcn_v1_0_disable_clock_gating - disable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @sw: enable SW clock gating
+ *
+ * Disable clock gating for VCN block
+ */
+static void vcn_v1_0_disable_clock_gating(struct amdgpu_device *adev, bool sw)
+{
+       uint32_t data;
+
+       /* JPEG disable CGC */
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_CTRL));
+
+       if (sw)
+               data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+       else
+               data &= ~JPEG_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+
+       data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+       data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_CTRL), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_GATE));
+       data &= ~(JPEG_CGC_GATE__JPEG_MASK | JPEG_CGC_GATE__JPEG2_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_GATE), data);
+
+       /* UVD disable CGC */
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL));
+       if (sw)
+               data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+       else
+               data &= ~ UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+
+       data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+       data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_GATE));
+       data &= ~(UVD_CGC_GATE__SYS_MASK
+               | UVD_CGC_GATE__UDEC_MASK
+               | UVD_CGC_GATE__MPEG2_MASK
+               | UVD_CGC_GATE__REGS_MASK
+               | UVD_CGC_GATE__RBC_MASK
+               | UVD_CGC_GATE__LMI_MC_MASK
+               | UVD_CGC_GATE__LMI_UMC_MASK
+               | UVD_CGC_GATE__IDCT_MASK
+               | UVD_CGC_GATE__MPRD_MASK
+               | UVD_CGC_GATE__MPC_MASK
+               | UVD_CGC_GATE__LBSI_MASK
+               | UVD_CGC_GATE__LRBBM_MASK
+               | UVD_CGC_GATE__UDEC_RE_MASK
+               | UVD_CGC_GATE__UDEC_CM_MASK
+               | UVD_CGC_GATE__UDEC_IT_MASK
+               | UVD_CGC_GATE__UDEC_DB_MASK
+               | UVD_CGC_GATE__UDEC_MP_MASK
+               | UVD_CGC_GATE__WCB_MASK
+               | UVD_CGC_GATE__VCPU_MASK
+               | UVD_CGC_GATE__SCPU_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_GATE), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL));
+       data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
+               | UVD_CGC_CTRL__SYS_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_MODE_MASK
+               | UVD_CGC_CTRL__MPEG2_MODE_MASK
+               | UVD_CGC_CTRL__REGS_MODE_MASK
+               | UVD_CGC_CTRL__RBC_MODE_MASK
+               | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+               | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+               | UVD_CGC_CTRL__IDCT_MODE_MASK
+               | UVD_CGC_CTRL__MPRD_MODE_MASK
+               | UVD_CGC_CTRL__MPC_MODE_MASK
+               | UVD_CGC_CTRL__LBSI_MODE_MASK
+               | UVD_CGC_CTRL__LRBBM_MODE_MASK
+               | UVD_CGC_CTRL__WCB_MODE_MASK
+               | UVD_CGC_CTRL__VCPU_MODE_MASK
+               | UVD_CGC_CTRL__SCPU_MODE_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL), data);
+
+       /* turn on */
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_SUVD_CGC_GATE));
+       data |= (UVD_SUVD_CGC_GATE__SRE_MASK
+               | UVD_SUVD_CGC_GATE__SIT_MASK
+               | UVD_SUVD_CGC_GATE__SMP_MASK
+               | UVD_SUVD_CGC_GATE__SCM_MASK
+               | UVD_SUVD_CGC_GATE__SDB_MASK
+               | UVD_SUVD_CGC_GATE__SRE_H264_MASK
+               | UVD_SUVD_CGC_GATE__SRE_H264_MASK
+               | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
+               | UVD_SUVD_CGC_GATE__SIT_H264_MASK
+               | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
+               | UVD_SUVD_CGC_GATE__SCM_H264_MASK
+               | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
+               | UVD_SUVD_CGC_GATE__SDB_H264_MASK
+               | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
+               | UVD_SUVD_CGC_GATE__SCLR_MASK
+               | UVD_SUVD_CGC_GATE__UVD_SC_MASK
+               | UVD_SUVD_CGC_GATE__ENT_MASK
+               | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
+               | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
+               | UVD_SUVD_CGC_GATE__SITE_MASK
+               | UVD_SUVD_CGC_GATE__SRE_VP9_MASK
+               | UVD_SUVD_CGC_GATE__SCM_VP9_MASK
+               | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
+               | UVD_SUVD_CGC_GATE__SDB_VP9_MASK
+               | UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_SUVD_CGC_GATE), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_SUVD_CGC_CTRL));
+       data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_SUVD_CGC_CTRL), data);
+}
+
+/**
+ * vcn_v1_0_enable_clock_gating - enable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @sw: enable SW clock gating
+ *
+ * Enable clock gating for VCN block
+ */
+static void vcn_v1_0_enable_clock_gating(struct amdgpu_device *adev, bool sw)
+{
+       uint32_t data = 0;
+
+       /* enable JPEG CGC */
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_CTRL));
+       if (sw)
+               data |= 1 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+       else
+               data |= 0 << JPEG_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+       data |= 1 << JPEG_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+       data |= 4 << JPEG_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_CTRL), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_GATE));
+       data |= (JPEG_CGC_GATE__JPEG_MASK | JPEG_CGC_GATE__JPEG2_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmJPEG_CGC_GATE), data);
+
+       /* enable UVD CGC */
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL));
+       if (sw)
+               data |= 1 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+       else
+               data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
+       data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
+       data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL));
+       data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
+               | UVD_CGC_CTRL__SYS_MODE_MASK
+               | UVD_CGC_CTRL__UDEC_MODE_MASK
+               | UVD_CGC_CTRL__MPEG2_MODE_MASK
+               | UVD_CGC_CTRL__REGS_MODE_MASK
+               | UVD_CGC_CTRL__RBC_MODE_MASK
+               | UVD_CGC_CTRL__LMI_MC_MODE_MASK
+               | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
+               | UVD_CGC_CTRL__IDCT_MODE_MASK
+               | UVD_CGC_CTRL__MPRD_MODE_MASK
+               | UVD_CGC_CTRL__MPC_MODE_MASK
+               | UVD_CGC_CTRL__LBSI_MODE_MASK
+               | UVD_CGC_CTRL__LRBBM_MODE_MASK
+               | UVD_CGC_CTRL__WCB_MODE_MASK
+               | UVD_CGC_CTRL__VCPU_MODE_MASK
+               | UVD_CGC_CTRL__SCPU_MODE_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_CGC_CTRL), data);
+
+       data = RREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_SUVD_CGC_CTRL));
+       data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
+       WREG32(SOC15_REG_OFFSET(VCN, 0, mmUVD_SUVD_CGC_CTRL), data);
+}
+
+/**
  * vcn_v1_0_start - start VCN block
  *
  * @adev: amdgpu_device pointer
@@ -300,8 +501,7 @@ static int vcn_v1_0_start(struct amdgpu_device *adev)
        vcn_v1_0_mc_resume(adev);
 
        /* disable clock gating */
-       WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_CGC_CTRL), 0,
-                       ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK);
+       vcn_v1_0_disable_clock_gating(adev, false);
 
        /* disable interupt */
        WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), 0,
@@ -481,6 +681,9 @@ static int vcn_v1_0_stop(struct amdgpu_device *adev)
        WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2), 0,
                        ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
 
+       /* enable clock gating */
+       vcn_v1_0_enable_clock_gating(adev, false);
+
        return 0;
 }