aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0111-drm-amd-amdgpu-add-vce3.0-clock-gating-support.-v2.patch
diff options
context:
space:
mode:
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.patch203
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
+