diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0111-drm-amd-amdgpu-add-vce3.0-clock-gating-support.-v2.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0111-drm-amd-amdgpu-add-vce3.0-clock-gating-support.-v2.patch | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0111-drm-amd-amdgpu-add-vce3.0-clock-gating-support.-v2.patch b/common/recipes-kernel/linux/files/0111-drm-amd-amdgpu-add-vce3.0-clock-gating-support.-v2.patch new file mode 100644 index 00000000..f85778d8 --- /dev/null +++ b/common/recipes-kernel/linux/files/0111-drm-amd-amdgpu-add-vce3.0-clock-gating-support.-v2.patch @@ -0,0 +1,203 @@ +From a6349c62e77d42be9211527c4acafb803431ef2b Mon Sep 17 00:00:00 2001 +From: Eric Huang <JinHuiEric.Huang@amd.com> +Date: Mon, 23 Nov 2015 16:57:53 -0500 +Subject: [PATCH 0111/1110] drm/amd/amdgpu: add vce3.0 clock gating support. + (v2) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +v2: fix grbm locking + +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Reviewed-by: Christian König <christian.koenig@amd.com> +Acked-by: Jammy Zhou <Jammy.Zhou@amd.com> +Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 149 +++++++++++++++++++++++++++++++++- + 1 file changed, 148 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +index 370c6c9..35f48ad 100644 +--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +@@ -103,6 +103,108 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) + WREG32(mmVCE_RB_WPTR2, ring->wptr); + } + ++static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) ++{ ++ u32 tmp, data; ++ ++ tmp = data = RREG32(mmVCE_RB_ARB_CTRL); ++ if (override) ++ data |= VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK; ++ else ++ data &= ~VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK; ++ ++ if (tmp != data) ++ WREG32(mmVCE_RB_ARB_CTRL, data); ++} ++ ++static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev, ++ bool gated) ++{ ++ u32 tmp, data; ++ /* Set Override to disable Clock Gating */ ++ vce_v3_0_override_vce_clock_gating(adev, true); ++ ++ if (!gated) { ++ /* Force CLOCK ON for VCE_CLOCK_GATING_B, ++ * {*_FORCE_ON, *_FORCE_OFF} = {1, 0} ++ * VREG can be FORCE ON or set to Dynamic, but can't be OFF ++ */ ++ tmp = data = RREG32(mmVCE_CLOCK_GATING_B); ++ data |= 0x1ff; ++ data &= ~0xef0000; ++ if (tmp != data) ++ WREG32(mmVCE_CLOCK_GATING_B, data); ++ ++ /* Force CLOCK ON for VCE_UENC_CLOCK_GATING, ++ * {*_FORCE_ON, *_FORCE_OFF} = {1, 0} ++ */ ++ tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING); ++ data |= 0x3ff000; ++ data &= ~0xffc00000; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_CLOCK_GATING, data); ++ ++ /* set VCE_UENC_CLOCK_GATING_2 */ ++ tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2); ++ data |= 0x2; ++ data &= ~0x2; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_CLOCK_GATING_2, data); ++ ++ /* Force CLOCK ON for VCE_UENC_REG_CLOCK_GATING */ ++ tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING); ++ data |= 0x37f; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_REG_CLOCK_GATING, data); ++ ++ /* Force VCE_UENC_DMA_DCLK_CTRL Clock ON */ ++ tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL); ++ data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK | ++ VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK | ++ VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK | ++ 0x8; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data); ++ } else { ++ /* Force CLOCK OFF for VCE_CLOCK_GATING_B, ++ * {*, *_FORCE_OFF} = {*, 1} ++ * set VREG to Dynamic, as it can't be OFF ++ */ ++ tmp = data = RREG32(mmVCE_CLOCK_GATING_B); ++ data &= ~0x80010; ++ data |= 0xe70008; ++ if (tmp != data) ++ WREG32(mmVCE_CLOCK_GATING_B, data); ++ /* Force CLOCK OFF for VCE_UENC_CLOCK_GATING, ++ * Force ClOCK OFF takes precedent over Force CLOCK ON setting. ++ * {*_FORCE_ON, *_FORCE_OFF} = {*, 1} ++ */ ++ tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING); ++ data |= 0xffc00000; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_CLOCK_GATING, data); ++ /* Set VCE_UENC_CLOCK_GATING_2 */ ++ tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2); ++ data |= 0x10000; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_CLOCK_GATING_2, data); ++ /* Set VCE_UENC_REG_CLOCK_GATING to dynamic */ ++ tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING); ++ data &= ~0xffc00000; ++ if (tmp != data) ++ WREG32(mmVCE_UENC_REG_CLOCK_GATING, data); ++ /* Set VCE_UENC_DMA_DCLK_CTRL CG always in dynamic mode */ ++ tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL); ++ data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK | ++ VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK | ++ VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK | ++ 0x8); ++ if (tmp != data) ++ WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data); ++ } ++ vce_v3_0_override_vce_clock_gating(adev, false); ++} ++ + /** + * vce_v3_0_start - start VCE block + * +@@ -121,7 +223,7 @@ static int vce_v3_0_start(struct amdgpu_device *adev) + if (adev->vce.harvest_config & (1 << idx)) + continue; + +- if(idx == 0) ++ if (idx == 0) + WREG32_P(mmGRBM_GFX_INDEX, 0, + ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); + else +@@ -174,6 +276,10 @@ static int vce_v3_0_start(struct amdgpu_device *adev) + /* clear BUSY flag */ + WREG32_P(mmVCE_STATUS, 0, ~1); + ++ /* Set Clock-Gating off */ ++ if (adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG) ++ vce_v3_0_set_vce_sw_clock_gating(adev, false); ++ + if (r) { + DRM_ERROR("VCE not responding, giving up!!!\n"); + mutex_unlock(&adev->grbm_idx_mutex); +@@ -609,6 +715,47 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, + static int vce_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; ++ ++ if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG)) ++ return 0; ++ ++ mutex_lock(&adev->grbm_idx_mutex); ++ for (i = 0; i < 2; i++) { ++ /* Program VCE Instance 0 or 1 if not harvested */ ++ if (adev->vce.harvest_config & (1 << i)) ++ continue; ++ ++ if (i == 0) ++ WREG32_P(mmGRBM_GFX_INDEX, 0, ++ ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); ++ else ++ WREG32_P(mmGRBM_GFX_INDEX, ++ GRBM_GFX_INDEX__VCE_INSTANCE_MASK, ++ ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); ++ ++ if (enable) { ++ /* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */ ++ uint32_t data = RREG32(mmVCE_CLOCK_GATING_A); ++ data &= ~(0xf | 0xff0); ++ data |= ((0x0 << 0) | (0x04 << 4)); ++ WREG32(mmVCE_CLOCK_GATING_A, data); ++ ++ /* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */ ++ data = RREG32(mmVCE_UENC_CLOCK_GATING); ++ data &= ~(0xf | 0xff0); ++ data |= ((0x0 << 0) | (0x04 << 4)); ++ WREG32(mmVCE_UENC_CLOCK_GATING, data); ++ } ++ ++ vce_v3_0_set_vce_sw_clock_gating(adev, enable); ++ } ++ ++ WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); ++ mutex_unlock(&adev->grbm_idx_mutex); ++ + return 0; + } + +-- +2.7.4 + |