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-12 10:27:40 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-12-12 16:58:42 -0500
commit993495ae992c91e98ade8fbe977c57bfd81910c1 (patch)
tree8e0d931e3ecf6d667379df24c44d71659b5b50d4 /drivers/gpu/drm/i915/intel_pm.c
parentfd70d52acc7abef6402e21e3e11950773af3d769 (diff)
drm/i915: Rework the FBC interval/stall stuff a bit
Don't touch DPFC_RECOMP_CTL on FBC2, use RMW to update the FBC_CONTROL on FBC1 to make it easier for people to experiment with different numbers. Also fix the interval mask for FBC1. v2: Rebased Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.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.c34
1 files changed, 14 insertions, 20 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index d7cb6bf5712d..c68abf718825 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -88,7 +88,7 @@ static void i8xx_disable_fbc(struct drm_device *dev)
88 DRM_DEBUG_KMS("disabled FBC\n"); 88 DRM_DEBUG_KMS("disabled FBC\n");
89} 89}
90 90
91static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 91static void i8xx_enable_fbc(struct drm_crtc *crtc)
92{ 92{
93 struct drm_device *dev = crtc->dev; 93 struct drm_device *dev = crtc->dev;
94 struct drm_i915_private *dev_priv = dev->dev_private; 94 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -126,11 +126,12 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
126 } 126 }
127 127
128 /* enable it... */ 128 /* enable it... */
129 fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; 129 fbc_ctl = I915_READ(FBC_CONTROL);
130 fbc_ctl &= 0x3fff << FBC_CTL_INTERVAL_SHIFT;
131 fbc_ctl |= FBC_CTL_EN | FBC_CTL_PERIODIC;
130 if (IS_I945GM(dev)) 132 if (IS_I945GM(dev))
131 fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ 133 fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
132 fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; 134 fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
133 fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
134 fbc_ctl |= obj->fence_reg; 135 fbc_ctl |= obj->fence_reg;
135 I915_WRITE(FBC_CONTROL, fbc_ctl); 136 I915_WRITE(FBC_CONTROL, fbc_ctl);
136 137
@@ -145,7 +146,7 @@ static bool i8xx_fbc_enabled(struct drm_device *dev)
145 return I915_READ(FBC_CONTROL) & FBC_CTL_EN; 146 return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
146} 147}
147 148
148static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 149static void g4x_enable_fbc(struct drm_crtc *crtc)
149{ 150{
150 struct drm_device *dev = crtc->dev; 151 struct drm_device *dev = crtc->dev;
151 struct drm_i915_private *dev_priv = dev->dev_private; 152 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -154,16 +155,12 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
154 struct drm_i915_gem_object *obj = intel_fb->obj; 155 struct drm_i915_gem_object *obj = intel_fb->obj;
155 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 156 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
156 int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; 157 int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
157 unsigned long stall_watermark = 200;
158 u32 dpfc_ctl; 158 u32 dpfc_ctl;
159 159
160 dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; 160 dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
161 dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; 161 dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg;
162 I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); 162 I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
163 163
164 I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
165 (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
166 (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
167 I915_WRITE(DPFC_FENCE_YOFF, crtc->y); 164 I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
168 165
169 /* enable it... */ 166 /* enable it... */
@@ -219,7 +216,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
219 gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA); 216 gen6_gt_force_wake_put(dev_priv, FORCEWAKE_MEDIA);
220} 217}
221 218
222static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 219static void ironlake_enable_fbc(struct drm_crtc *crtc)
223{ 220{
224 struct drm_device *dev = crtc->dev; 221 struct drm_device *dev = crtc->dev;
225 struct drm_i915_private *dev_priv = dev->dev_private; 222 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -228,7 +225,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
228 struct drm_i915_gem_object *obj = intel_fb->obj; 225 struct drm_i915_gem_object *obj = intel_fb->obj;
229 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 226 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
230 int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; 227 int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB;
231 unsigned long stall_watermark = 200;
232 u32 dpfc_ctl; 228 u32 dpfc_ctl;
233 229
234 dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); 230 dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
@@ -241,9 +237,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
241 dpfc_ctl |= obj->fence_reg; 237 dpfc_ctl |= obj->fence_reg;
242 I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); 238 I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
243 239
244 I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
245 (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
246 (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
247 I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); 240 I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
248 I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); 241 I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID);
249 /* enable it... */ 242 /* enable it... */
@@ -281,7 +274,7 @@ static bool ironlake_fbc_enabled(struct drm_device *dev)
281 return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; 274 return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
282} 275}
283 276
284static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 277static void gen7_enable_fbc(struct drm_crtc *crtc)
285{ 278{
286 struct drm_device *dev = crtc->dev; 279 struct drm_device *dev = crtc->dev;
287 struct drm_i915_private *dev_priv = dev->dev_private; 280 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -338,8 +331,7 @@ static void intel_fbc_work_fn(struct work_struct *__work)
338 * the prior work. 331 * the prior work.
339 */ 332 */
340 if (work->crtc->fb == work->fb) { 333 if (work->crtc->fb == work->fb) {
341 dev_priv->display.enable_fbc(work->crtc, 334 dev_priv->display.enable_fbc(work->crtc);
342 work->interval);
343 335
344 dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane; 336 dev_priv->fbc.plane = to_intel_crtc(work->crtc)->plane;
345 dev_priv->fbc.fb_id = work->crtc->fb->base.id; 337 dev_priv->fbc.fb_id = work->crtc->fb->base.id;
@@ -376,7 +368,7 @@ static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv)
376 dev_priv->fbc.fbc_work = NULL; 368 dev_priv->fbc.fbc_work = NULL;
377} 369}
378 370
379static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) 371static void intel_enable_fbc(struct drm_crtc *crtc)
380{ 372{
381 struct intel_fbc_work *work; 373 struct intel_fbc_work *work;
382 struct drm_device *dev = crtc->dev; 374 struct drm_device *dev = crtc->dev;
@@ -390,13 +382,12 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
390 work = kzalloc(sizeof(*work), GFP_KERNEL); 382 work = kzalloc(sizeof(*work), GFP_KERNEL);
391 if (work == NULL) { 383 if (work == NULL) {
392 DRM_ERROR("Failed to allocate FBC work structure\n"); 384 DRM_ERROR("Failed to allocate FBC work structure\n");
393 dev_priv->display.enable_fbc(crtc, interval); 385 dev_priv->display.enable_fbc(crtc);
394 return; 386 return;
395 } 387 }
396 388
397 work->crtc = crtc; 389 work->crtc = crtc;
398 work->fb = crtc->fb; 390 work->fb = crtc->fb;
399 work->interval = interval;
400 INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); 391 INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn);
401 392
402 dev_priv->fbc.fbc_work = work; 393 dev_priv->fbc.fbc_work = work;
@@ -611,7 +602,7 @@ void intel_update_fbc(struct drm_device *dev)
611 intel_disable_fbc(dev); 602 intel_disable_fbc(dev);
612 } 603 }
613 604
614 intel_enable_fbc(crtc, 500); 605 intel_enable_fbc(crtc);
615 dev_priv->fbc.no_fbc_reason = FBC_OK; 606 dev_priv->fbc.no_fbc_reason = FBC_OK;
616 return; 607 return;
617 608
@@ -6073,6 +6064,9 @@ void intel_init_pm(struct drm_device *dev)
6073 dev_priv->display.fbc_enabled = i8xx_fbc_enabled; 6064 dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
6074 dev_priv->display.enable_fbc = i8xx_enable_fbc; 6065 dev_priv->display.enable_fbc = i8xx_enable_fbc;
6075 dev_priv->display.disable_fbc = i8xx_disable_fbc; 6066 dev_priv->display.disable_fbc = i8xx_disable_fbc;
6067
6068 /* This value was pulled out of someone's hat */
6069 I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
6076 } 6070 }
6077 } 6071 }
6078 6072