diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2013-12-12 10:27:40 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-12-12 16:58:42 -0500 |
commit | 993495ae992c91e98ade8fbe977c57bfd81910c1 (patch) | |
tree | 8e0d931e3ecf6d667379df24c44d71659b5b50d4 | |
parent | fd70d52acc7abef6402e21e3e11950773af3d769 (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>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 34 |
2 files changed, 15 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 709b20e0e3f0..ae2c80c1981b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -372,7 +372,7 @@ struct dpll; | |||
372 | 372 | ||
373 | struct drm_i915_display_funcs { | 373 | struct drm_i915_display_funcs { |
374 | bool (*fbc_enabled)(struct drm_device *dev); | 374 | bool (*fbc_enabled)(struct drm_device *dev); |
375 | void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval); | 375 | void (*enable_fbc)(struct drm_crtc *crtc); |
376 | void (*disable_fbc)(struct drm_device *dev); | 376 | void (*disable_fbc)(struct drm_device *dev); |
377 | int (*get_display_clock_speed)(struct drm_device *dev); | 377 | int (*get_display_clock_speed)(struct drm_device *dev); |
378 | int (*get_fifo_size)(struct drm_device *dev, int plane); | 378 | int (*get_fifo_size)(struct drm_device *dev, int plane); |
@@ -695,7 +695,6 @@ struct i915_fbc { | |||
695 | struct delayed_work work; | 695 | struct delayed_work work; |
696 | struct drm_crtc *crtc; | 696 | struct drm_crtc *crtc; |
697 | struct drm_framebuffer *fb; | 697 | struct drm_framebuffer *fb; |
698 | int interval; | ||
699 | } *fbc_work; | 698 | } *fbc_work; |
700 | 699 | ||
701 | enum no_fbc_reason { | 700 | enum no_fbc_reason { |
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 | ||
91 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 91 | static 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 | ||
148 | static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 149 | static 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 | ||
222 | static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 219 | static 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 | ||
284 | static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 277 | static 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 | ||
379 | static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | 371 | static 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 | ||