aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2013-12-05 08:51:33 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-12-17 07:17:53 -0500
commitfacd619b8869b308e02104a200abf6f9d7cddcab (patch)
treed0dabad6f3bbdadfb893eb6a900761d5058c9641 /drivers/gpu/drm/i915/intel_pm.c
parent6cef2b8a5671dc6abbc0414a94be843590f93ede (diff)
drm/i915: Fix LP1+ watermark disabling ILK
On ILK disabling LP1+ watermarks must be done carefully to avoid underruns. If we just write 0 to the register in the middle of the scan cycle we often get an underrun. So instead we have to leave the actual watermark levels in the register intact, and just toggle the enable bit. Presumably the hardware takes a while to get out of low power mode, and so the watermark level need to stay valid until that time. We also have to be careful with the WM1S_LP_EN bit. It seems the hardware more or less treats it like the actual watermarks numbers, and so we must not toggle it too soon. Just leave it alone when disabling the LP1+ watermarks. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 232d8c3b1f10..c43cf138c871 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2896,16 +2896,23 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
2896 if (!dirty) 2896 if (!dirty)
2897 return; 2897 return;
2898 2898
2899 if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0) 2899 if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] & WM1_LP_SR_EN) {
2900 I915_WRITE(WM3_LP_ILK, 0); 2900 previous->wm_lp[2] &= ~WM1_LP_SR_EN;
2901 if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0) 2901 I915_WRITE(WM3_LP_ILK, previous->wm_lp[2]);
2902 I915_WRITE(WM2_LP_ILK, 0); 2902 }
2903 if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0) 2903 if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] & WM1_LP_SR_EN) {
2904 I915_WRITE(WM1_LP_ILK, 0); 2904 previous->wm_lp[1] &= ~WM1_LP_SR_EN;
2905 I915_WRITE(WM2_LP_ILK, previous->wm_lp[1]);
2906 }
2907 if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] & WM1_LP_SR_EN) {
2908 previous->wm_lp[0] &= ~WM1_LP_SR_EN;
2909 I915_WRITE(WM1_LP_ILK, previous->wm_lp[0]);
2910 }
2905 2911
2906 if (INTEL_INFO(dev)->gen <= 6 && 2912 /*
2907 dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != 0) 2913 * Don't touch WM1S_LP_EN here.
2908 I915_WRITE(WM1S_LP_ILK, 0); 2914 * Doing so could cause underruns.
2915 */
2909 2916
2910 if (dirty & WM_DIRTY_PIPE(PIPE_A)) 2917 if (dirty & WM_DIRTY_PIPE(PIPE_A))
2911 I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]); 2918 I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]);
@@ -2949,7 +2956,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
2949 } 2956 }
2950 2957
2951 if (INTEL_INFO(dev)->gen <= 6) { 2958 if (INTEL_INFO(dev)->gen <= 6) {
2952 if (dirty & WM_DIRTY_LP(1) && results->wm_lp_spr[0] != 0) 2959 if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
2953 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); 2960 I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
2954 } else { 2961 } else {
2955 if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) 2962 if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0])
@@ -2960,11 +2967,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv,
2960 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); 2967 I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]);
2961 } 2968 }
2962 2969
2963 if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) 2970 if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != results->wm_lp[0])
2964 I915_WRITE(WM1_LP_ILK, results->wm_lp[0]); 2971 I915_WRITE(WM1_LP_ILK, results->wm_lp[0]);
2965 if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0) 2972 if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != results->wm_lp[1])
2966 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]); 2973 I915_WRITE(WM2_LP_ILK, results->wm_lp[1]);
2967 if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0) 2974 if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != results->wm_lp[2])
2968 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]); 2975 I915_WRITE(WM3_LP_ILK, results->wm_lp[2]);
2969 2976
2970 dev_priv->wm.hw = *results; 2977 dev_priv->wm.hw = *results;