]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
drm/amdgpu: add Sienna_Cichlid VCN PG and CG support (v2)
authorLeo Liu <leo.liu@amd.com>
Wed, 27 Nov 2019 16:03:39 +0000 (11:03 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Jul 2020 05:59:09 +0000 (01:59 -0400)
This is for static powergating and clockgating

v2: fix registers (Alex)

Signed-off-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: James Zhu <James.Zhu@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c

index 2833f06fb4bbc458c52293f2b54cee0ebdd8465c..011edbdd4e558793b9443c11593deb4ce0b90fe6 100644 (file)
@@ -381,6 +381,309 @@ static void vcn_v3_0_mc_resume(struct amdgpu_device *adev, int inst)
        WREG32_SOC15(VCN, inst, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
 }
 
+static void vcn_v3_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
+{
+       uint32_t data = 0;
+       int ret;
+
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
+               data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDIRL_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDATD_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT);
+
+               WREG32_SOC15(VCN, inst, mmUVD_PGFSM_CONFIG, data);
+               SOC15_WAIT_ON_RREG(VCN, inst, mmUVD_PGFSM_STATUS,
+                       UVD_PGFSM_STATUS__UVDM_UVDU_UVDLM_PWR_ON_3_0, 0x3F3FFFFF, ret);
+       } else {
+               data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDIRL_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDATD_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT
+                       | 1 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT);
+               WREG32_SOC15(VCN, inst, mmUVD_PGFSM_CONFIG, data);
+               SOC15_WAIT_ON_RREG(VCN, inst, mmUVD_PGFSM_STATUS, 0,  0x3F3FFFFF, ret);
+       }
+
+       data = RREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS);
+       data &= ~0x103;
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCN)
+               data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON |
+                       UVD_POWER_STATUS__UVD_PG_EN_MASK;
+
+       WREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS, data);
+}
+
+static void vcn_v3_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
+{
+       uint32_t data;
+       int ret;
+
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
+               /* Before power off, this indicator has to be turned on */
+               data = RREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS);
+               data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;
+               data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;
+               WREG32_SOC15(VCN, inst, mmUVD_POWER_STATUS, data);
+
+               data = (2 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDU_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDC_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDIRL_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDATD_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT
+                       | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT);
+               WREG32_SOC15(VCN, inst, mmUVD_PGFSM_CONFIG, data);
+
+               data = (2 << UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDU_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDC_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDIRL_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDLM_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDAB_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDATD_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDNA_PWR_STATUS__SHIFT
+                       | 2 << UVD_PGFSM_STATUS__UVDNB_PWR_STATUS__SHIFT);
+               SOC15_WAIT_ON_RREG(VCN, inst, mmUVD_PGFSM_STATUS, data, 0x3F3FFFFF, ret);
+       }
+}
+
+/**
+ * vcn_v3_0_disable_clock_gating - disable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Disable clock gating for VCN block
+ */
+static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
+{
+       uint32_t data;
+       int ret = 0;
+
+       /* VCN disable CGC */
+       data = RREG32_SOC15(VCN, inst, mmUVD_CGC_CTRL);
+       if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+               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(VCN, inst, mmUVD_CGC_CTRL, data);
+
+       data = RREG32_SOC15(VCN, inst, 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__MMSCH_MASK);
+
+       WREG32_SOC15(VCN, inst, mmUVD_CGC_GATE, data);
+
+       SOC15_WAIT_ON_RREG(VCN, inst, mmUVD_CGC_GATE, 0,  0xFFFFFFFF, ret);
+
+       data = RREG32_SOC15(VCN, inst, 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__MMSCH_MODE_MASK);
+       WREG32_SOC15(VCN, inst, mmUVD_CGC_CTRL, data);
+
+       data = RREG32_SOC15(VCN, inst, 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_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__ENT_MASK
+               | UVD_SUVD_CGC_GATE__IME_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
+               | UVD_SUVD_CGC_GATE__EFC_MASK
+               | UVD_SUVD_CGC_GATE__SAOE_MASK
+               | 0x08000000
+               | UVD_SUVD_CGC_GATE__FBC_PCLK_MASK
+               | UVD_SUVD_CGC_GATE__FBC_CCLK_MASK
+               | 0x40000000
+               | UVD_SUVD_CGC_GATE__SMPA_MASK);
+       WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE, data);
+
+       data = RREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE2);
+       data |= (UVD_SUVD_CGC_GATE2__MPBE0_MASK
+               | UVD_SUVD_CGC_GATE2__MPBE1_MASK
+               | 0x00000004
+               | 0x00000008
+               | UVD_SUVD_CGC_GATE2__MPC1_MASK);
+       WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE2, data);
+
+       data = RREG32_SOC15(VCN, inst, 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__ENT_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__EFC_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SAOE_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK
+               | 0x00008000
+               | 0x00010000
+               | UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK
+               | UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK);
+       WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data);
+}
+
+/**
+ * vcn_v3_0_enable_clock_gating - enable VCN clock gating
+ *
+ * @adev: amdgpu_device pointer
+ * @inst: instance number
+ *
+ * Enable clock gating for VCN block
+ */
+static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
+{
+       uint32_t data;
+
+       /* enable VCN CGC */
+       data = RREG32_SOC15(VCN, inst, mmUVD_CGC_CTRL);
+       if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
+               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(VCN, inst, mmUVD_CGC_CTRL, data);
+
+       data = RREG32_SOC15(VCN, inst, 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__MMSCH_MODE_MASK);
+       WREG32_SOC15(VCN, inst, mmUVD_CGC_CTRL, data);
+
+       data = RREG32_SOC15(VCN, inst, 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__ENT_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__EFC_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SAOE_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK
+               | 0x00008000
+               | 0x00010000
+               | UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK
+               | UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK
+               | UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK);
+       WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_CTRL, data);
+}
+
 static int vcn_v3_0_start(struct amdgpu_device *adev)
 {
        struct amdgpu_ring *ring;
@@ -394,10 +697,16 @@ static int vcn_v3_0_start(struct amdgpu_device *adev)
                if (adev->vcn.harvest_config & (1 << i))
                        continue;
 
+               /* disable VCN power gating */
+               vcn_v3_0_disable_static_power_gating(adev, i);
+
                /* set VCN status busy */
                tmp = RREG32_SOC15(VCN, i, mmUVD_STATUS) | UVD_STATUS__UVD_BUSY;
                WREG32_SOC15(VCN, i, mmUVD_STATUS, tmp);
 
+               /*SW clock gating */
+               vcn_v3_0_disable_clock_gating(adev, i);
+
                /* enable VCPU clock */
                WREG32_P(SOC15_REG_OFFSET(VCN, i, mmUVD_VCPU_CNTL),
                        UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
@@ -600,6 +909,12 @@ static int vcn_v3_0_stop(struct amdgpu_device *adev)
 
                /* clear status */
                WREG32_SOC15(VCN, i, mmUVD_STATUS, 0);
+
+               /* apply HW clock gating */
+               vcn_v3_0_enable_clock_gating(adev, i);
+
+               /* enable VCN power gating */
+               vcn_v3_0_enable_static_power_gating(adev, i);
        }
 
        if (adev->pm.dpm_enabled)
@@ -853,6 +1168,23 @@ static int vcn_v3_0_wait_for_idle(void *handle)
 static int vcn_v3_0_set_clockgating_state(void *handle,
                                          enum amd_clockgating_state state)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+       int i;
+
+       for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+               if (adev->vcn.harvest_config & (1 << i))
+                       continue;
+
+               if (enable) {
+                       if (RREG32_SOC15(VCN, i, mmUVD_STATUS) == UVD_STATUS__IDLE)
+                               return -EBUSY;
+                       vcn_v3_0_enable_clock_gating(adev, i);
+               } else {
+                       vcn_v3_0_disable_clock_gating(adev, i);
+               }
+       }
+
        return 0;
 }