diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sprite.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b9fabf826f7d..716a3c9c0751 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -104,6 +104,12 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | |||
104 | break; | 104 | break; |
105 | } | 105 | } |
106 | 106 | ||
107 | /* | ||
108 | * Enable gamma to match primary/cursor plane behaviour. | ||
109 | * FIXME should be user controllable via propertiesa. | ||
110 | */ | ||
111 | sprctl |= SP_GAMMA_ENABLE; | ||
112 | |||
107 | if (obj->tiling_mode != I915_TILING_NONE) | 113 | if (obj->tiling_mode != I915_TILING_NONE) |
108 | sprctl |= SP_TILED; | 114 | sprctl |= SP_TILED; |
109 | 115 | ||
@@ -135,8 +141,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | |||
135 | 141 | ||
136 | I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); | 142 | I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); |
137 | I915_WRITE(SPCNTR(pipe, plane), sprctl); | 143 | I915_WRITE(SPCNTR(pipe, plane), sprctl); |
138 | I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + | 144 | I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + |
139 | sprsurf_offset); | 145 | sprsurf_offset); |
140 | POSTING_READ(SPSURF(pipe, plane)); | 146 | POSTING_READ(SPSURF(pipe, plane)); |
141 | } | 147 | } |
142 | 148 | ||
@@ -152,7 +158,7 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) | |||
152 | I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & | 158 | I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & |
153 | ~SP_ENABLE); | 159 | ~SP_ENABLE); |
154 | /* Activate double buffered register update */ | 160 | /* Activate double buffered register update */ |
155 | I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0); | 161 | I915_WRITE(SPSURF(pipe, plane), 0); |
156 | POSTING_READ(SPSURF(pipe, plane)); | 162 | POSTING_READ(SPSURF(pipe, plane)); |
157 | 163 | ||
158 | intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false); | 164 | intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false); |
@@ -224,7 +230,6 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
224 | u32 sprctl, sprscale = 0; | 230 | u32 sprctl, sprscale = 0; |
225 | unsigned long sprsurf_offset, linear_offset; | 231 | unsigned long sprsurf_offset, linear_offset; |
226 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | 232 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
227 | bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; | ||
228 | 233 | ||
229 | sprctl = I915_READ(SPRCTL(pipe)); | 234 | sprctl = I915_READ(SPRCTL(pipe)); |
230 | 235 | ||
@@ -257,6 +262,12 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
257 | BUG(); | 262 | BUG(); |
258 | } | 263 | } |
259 | 264 | ||
265 | /* | ||
266 | * Enable gamma to match primary/cursor plane behaviour. | ||
267 | * FIXME should be user controllable via propertiesa. | ||
268 | */ | ||
269 | sprctl |= SPRITE_GAMMA_ENABLE; | ||
270 | |||
260 | if (obj->tiling_mode != I915_TILING_NONE) | 271 | if (obj->tiling_mode != I915_TILING_NONE) |
261 | sprctl |= SPRITE_TILED; | 272 | sprctl |= SPRITE_TILED; |
262 | 273 | ||
@@ -279,21 +290,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
279 | crtc_w--; | 290 | crtc_w--; |
280 | crtc_h--; | 291 | crtc_h--; |
281 | 292 | ||
282 | /* | 293 | if (crtc_w != src_w || crtc_h != src_h) |
283 | * IVB workaround: must disable low power watermarks for at least | ||
284 | * one frame before enabling scaling. LP watermarks can be re-enabled | ||
285 | * when scaling is disabled. | ||
286 | */ | ||
287 | if (crtc_w != src_w || crtc_h != src_h) { | ||
288 | dev_priv->sprite_scaling_enabled |= 1 << pipe; | ||
289 | |||
290 | if (!scaling_was_enabled) { | ||
291 | intel_update_watermarks(crtc); | ||
292 | intel_wait_for_vblank(dev, pipe); | ||
293 | } | ||
294 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; | 294 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; |
295 | } else | ||
296 | dev_priv->sprite_scaling_enabled &= ~(1 << pipe); | ||
297 | 295 | ||
298 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); | 296 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); |
299 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); | 297 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); |
@@ -317,13 +315,9 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
317 | if (intel_plane->can_scale) | 315 | if (intel_plane->can_scale) |
318 | I915_WRITE(SPRSCALE(pipe), sprscale); | 316 | I915_WRITE(SPRSCALE(pipe), sprscale); |
319 | I915_WRITE(SPRCTL(pipe), sprctl); | 317 | I915_WRITE(SPRCTL(pipe), sprctl); |
320 | I915_MODIFY_DISPBASE(SPRSURF(pipe), | 318 | I915_WRITE(SPRSURF(pipe), |
321 | i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); | 319 | i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); |
322 | POSTING_READ(SPRSURF(pipe)); | 320 | POSTING_READ(SPRSURF(pipe)); |
323 | |||
324 | /* potentially re-enable LP watermarks */ | ||
325 | if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) | ||
326 | intel_update_watermarks(crtc); | ||
327 | } | 321 | } |
328 | 322 | ||
329 | static void | 323 | static void |
@@ -333,23 +327,22 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) | |||
333 | struct drm_i915_private *dev_priv = dev->dev_private; | 327 | struct drm_i915_private *dev_priv = dev->dev_private; |
334 | struct intel_plane *intel_plane = to_intel_plane(plane); | 328 | struct intel_plane *intel_plane = to_intel_plane(plane); |
335 | int pipe = intel_plane->pipe; | 329 | int pipe = intel_plane->pipe; |
336 | bool scaling_was_enabled = dev_priv->sprite_scaling_enabled; | ||
337 | 330 | ||
338 | I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); | 331 | I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); |
339 | /* Can't leave the scaler enabled... */ | 332 | /* Can't leave the scaler enabled... */ |
340 | if (intel_plane->can_scale) | 333 | if (intel_plane->can_scale) |
341 | I915_WRITE(SPRSCALE(pipe), 0); | 334 | I915_WRITE(SPRSCALE(pipe), 0); |
342 | /* Activate double buffered register update */ | 335 | /* Activate double buffered register update */ |
343 | I915_MODIFY_DISPBASE(SPRSURF(pipe), 0); | 336 | I915_WRITE(SPRSURF(pipe), 0); |
344 | POSTING_READ(SPRSURF(pipe)); | 337 | POSTING_READ(SPRSURF(pipe)); |
345 | 338 | ||
346 | dev_priv->sprite_scaling_enabled &= ~(1 << pipe); | 339 | /* |
340 | * Avoid underruns when disabling the sprite. | ||
341 | * FIXME remove once watermark updates are done properly. | ||
342 | */ | ||
343 | intel_wait_for_vblank(dev, pipe); | ||
347 | 344 | ||
348 | intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); | 345 | intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); |
349 | |||
350 | /* potentially re-enable LP watermarks */ | ||
351 | if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled) | ||
352 | intel_update_watermarks(crtc); | ||
353 | } | 346 | } |
354 | 347 | ||
355 | static int | 348 | static int |
@@ -453,6 +446,12 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
453 | BUG(); | 446 | BUG(); |
454 | } | 447 | } |
455 | 448 | ||
449 | /* | ||
450 | * Enable gamma to match primary/cursor plane behaviour. | ||
451 | * FIXME should be user controllable via propertiesa. | ||
452 | */ | ||
453 | dvscntr |= DVS_GAMMA_ENABLE; | ||
454 | |||
456 | if (obj->tiling_mode != I915_TILING_NONE) | 455 | if (obj->tiling_mode != I915_TILING_NONE) |
457 | dvscntr |= DVS_TILED; | 456 | dvscntr |= DVS_TILED; |
458 | 457 | ||
@@ -470,7 +469,7 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
470 | crtc_h--; | 469 | crtc_h--; |
471 | 470 | ||
472 | dvsscale = 0; | 471 | dvsscale = 0; |
473 | if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h) | 472 | if (crtc_w != src_w || crtc_h != src_h) |
474 | dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; | 473 | dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; |
475 | 474 | ||
476 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); | 475 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); |
@@ -490,8 +489,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
490 | I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); | 489 | I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); |
491 | I915_WRITE(DVSSCALE(pipe), dvsscale); | 490 | I915_WRITE(DVSSCALE(pipe), dvsscale); |
492 | I915_WRITE(DVSCNTR(pipe), dvscntr); | 491 | I915_WRITE(DVSCNTR(pipe), dvscntr); |
493 | I915_MODIFY_DISPBASE(DVSSURF(pipe), | 492 | I915_WRITE(DVSSURF(pipe), |
494 | i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); | 493 | i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); |
495 | POSTING_READ(DVSSURF(pipe)); | 494 | POSTING_READ(DVSSURF(pipe)); |
496 | } | 495 | } |
497 | 496 | ||
@@ -507,9 +506,15 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) | |||
507 | /* Disable the scaler */ | 506 | /* Disable the scaler */ |
508 | I915_WRITE(DVSSCALE(pipe), 0); | 507 | I915_WRITE(DVSSCALE(pipe), 0); |
509 | /* Flush double buffered register updates */ | 508 | /* Flush double buffered register updates */ |
510 | I915_MODIFY_DISPBASE(DVSSURF(pipe), 0); | 509 | I915_WRITE(DVSSURF(pipe), 0); |
511 | POSTING_READ(DVSSURF(pipe)); | 510 | POSTING_READ(DVSSURF(pipe)); |
512 | 511 | ||
512 | /* | ||
513 | * Avoid underruns when disabling the sprite. | ||
514 | * FIXME remove once watermark updates are done properly. | ||
515 | */ | ||
516 | intel_wait_for_vblank(dev, pipe); | ||
517 | |||
513 | intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); | 518 | intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false); |
514 | } | 519 | } |
515 | 520 | ||
@@ -643,6 +648,15 @@ format_is_yuv(uint32_t format) | |||
643 | } | 648 | } |
644 | } | 649 | } |
645 | 650 | ||
651 | static bool colorkey_enabled(struct intel_plane *intel_plane) | ||
652 | { | ||
653 | struct drm_intel_sprite_colorkey key; | ||
654 | |||
655 | intel_plane->get_colorkey(&intel_plane->base, &key); | ||
656 | |||
657 | return key.flags != I915_SET_COLORKEY_NONE; | ||
658 | } | ||
659 | |||
646 | static int | 660 | static int |
647 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | 661 | intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
648 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, | 662 | struct drm_framebuffer *fb, int crtc_x, int crtc_y, |
@@ -828,7 +842,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
828 | * If the sprite is completely covering the primary plane, | 842 | * If the sprite is completely covering the primary plane, |
829 | * we can disable the primary and save power. | 843 | * we can disable the primary and save power. |
830 | */ | 844 | */ |
831 | disable_primary = drm_rect_equals(&dst, &clip); | 845 | disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane); |
832 | WARN_ON(disable_primary && !visible && intel_crtc->active); | 846 | WARN_ON(disable_primary && !visible && intel_crtc->active); |
833 | 847 | ||
834 | mutex_lock(&dev->struct_mutex); | 848 | mutex_lock(&dev->struct_mutex); |