aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2014-04-29 06:35:47 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-05-06 04:18:02 -0400
commit5b633d6b8e3aa1f3ba3daa568416e36e054a3bb1 (patch)
treea49a3ba4133cfae651ae1c62d352fc5c1033fed3
parent8d7849db3eab7f560deba145dfed3cd4df97c975 (diff)
drm/i915: Perform primary enable/disable atomically with sprite updates
Move the primary plane enable/disable to occur atomically with the sprite update that caused the primary plane visibility to change. FBC and IPS enable/disable is left to happen well before or after the primary plane change. v2: Pass intel_crtc instead of drm_crtc (Daniel) Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Reviewed-by: Sourab Gupta <sourabgupta@gmail.com> Reviewed-by: Akash Goel <akash.goels@gmail.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/intel_sprite.c94
1 files changed, 55 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index a3ed840aadbe..6192e586de5d 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -120,6 +120,17 @@ static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
120 pipe_name(pipe), start_vbl_count, end_vbl_count); 120 pipe_name(pipe), start_vbl_count, end_vbl_count);
121} 121}
122 122
123static void intel_update_primary_plane(struct intel_crtc *crtc)
124{
125 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
126 int reg = DSPCNTR(crtc->plane);
127
128 if (crtc->primary_enabled)
129 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
130 else
131 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
132}
133
123static void 134static void
124vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, 135vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
125 struct drm_framebuffer *fb, 136 struct drm_framebuffer *fb,
@@ -219,6 +230,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
219 230
220 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); 231 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
221 232
233 intel_update_primary_plane(intel_crtc);
234
222 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); 235 I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
223 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); 236 I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
224 237
@@ -231,7 +244,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
231 I915_WRITE(SPCNTR(pipe, plane), sprctl); 244 I915_WRITE(SPCNTR(pipe, plane), sprctl);
232 I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + 245 I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
233 sprsurf_offset); 246 sprsurf_offset);
234 POSTING_READ(SPSURF(pipe, plane)); 247
248 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
235 249
236 if (atomic_update) 250 if (atomic_update)
237 intel_pipe_update_end(intel_crtc, start_vbl_count); 251 intel_pipe_update_end(intel_crtc, start_vbl_count);
@@ -251,11 +265,14 @@ vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
251 265
252 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); 266 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
253 267
268 intel_update_primary_plane(intel_crtc);
269
254 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) & 270 I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
255 ~SP_ENABLE); 271 ~SP_ENABLE);
256 /* Activate double buffered register update */ 272 /* Activate double buffered register update */
257 I915_WRITE(SPSURF(pipe, plane), 0); 273 I915_WRITE(SPSURF(pipe, plane), 0);
258 POSTING_READ(SPSURF(pipe, plane)); 274
275 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
259 276
260 if (atomic_update) 277 if (atomic_update)
261 intel_pipe_update_end(intel_crtc, start_vbl_count); 278 intel_pipe_update_end(intel_crtc, start_vbl_count);
@@ -403,6 +420,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
403 420
404 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); 421 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
405 422
423 intel_update_primary_plane(intel_crtc);
424
406 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); 425 I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
407 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); 426 I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
408 427
@@ -421,7 +440,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
421 I915_WRITE(SPRCTL(pipe), sprctl); 440 I915_WRITE(SPRCTL(pipe), sprctl);
422 I915_WRITE(SPRSURF(pipe), 441 I915_WRITE(SPRSURF(pipe),
423 i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); 442 i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
424 POSTING_READ(SPRSURF(pipe)); 443
444 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
425 445
426 if (atomic_update) 446 if (atomic_update)
427 intel_pipe_update_end(intel_crtc, start_vbl_count); 447 intel_pipe_update_end(intel_crtc, start_vbl_count);
@@ -440,13 +460,16 @@ ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
440 460
441 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); 461 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
442 462
463 intel_update_primary_plane(intel_crtc);
464
443 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE); 465 I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
444 /* Can't leave the scaler enabled... */ 466 /* Can't leave the scaler enabled... */
445 if (intel_plane->can_scale) 467 if (intel_plane->can_scale)
446 I915_WRITE(SPRSCALE(pipe), 0); 468 I915_WRITE(SPRSCALE(pipe), 0);
447 /* Activate double buffered register update */ 469 /* Activate double buffered register update */
448 I915_WRITE(SPRSURF(pipe), 0); 470 I915_WRITE(SPRSURF(pipe), 0);
449 POSTING_READ(SPRSURF(pipe)); 471
472 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
450 473
451 if (atomic_update) 474 if (atomic_update)
452 intel_pipe_update_end(intel_crtc, start_vbl_count); 475 intel_pipe_update_end(intel_crtc, start_vbl_count);
@@ -598,6 +621,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
598 621
599 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); 622 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
600 623
624 intel_update_primary_plane(intel_crtc);
625
601 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); 626 I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
602 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); 627 I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
603 628
@@ -611,7 +636,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
611 I915_WRITE(DVSCNTR(pipe), dvscntr); 636 I915_WRITE(DVSCNTR(pipe), dvscntr);
612 I915_WRITE(DVSSURF(pipe), 637 I915_WRITE(DVSSURF(pipe),
613 i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); 638 i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
614 POSTING_READ(DVSSURF(pipe)); 639
640 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
615 641
616 if (atomic_update) 642 if (atomic_update)
617 intel_pipe_update_end(intel_crtc, start_vbl_count); 643 intel_pipe_update_end(intel_crtc, start_vbl_count);
@@ -630,12 +656,15 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
630 656
631 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count); 657 atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
632 658
659 intel_update_primary_plane(intel_crtc);
660
633 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE); 661 I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
634 /* Disable the scaler */ 662 /* Disable the scaler */
635 I915_WRITE(DVSSCALE(pipe), 0); 663 I915_WRITE(DVSSCALE(pipe), 0);
636 /* Flush double buffered register updates */ 664 /* Flush double buffered register updates */
637 I915_WRITE(DVSSURF(pipe), 0); 665 I915_WRITE(DVSSURF(pipe), 0);
638 POSTING_READ(DVSSURF(pipe)); 666
667 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
639 668
640 if (atomic_update) 669 if (atomic_update)
641 intel_pipe_update_end(intel_crtc, start_vbl_count); 670 intel_pipe_update_end(intel_crtc, start_vbl_count);
@@ -650,20 +679,10 @@ ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
650} 679}
651 680
652static void 681static void
653intel_enable_primary(struct drm_crtc *crtc) 682intel_post_enable_primary(struct drm_crtc *crtc)
654{ 683{
655 struct drm_device *dev = crtc->dev; 684 struct drm_device *dev = crtc->dev;
656 struct drm_i915_private *dev_priv = dev->dev_private;
657 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 685 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
658 int reg = DSPCNTR(intel_crtc->plane);
659
660 if (intel_crtc->primary_enabled)
661 return;
662
663 intel_crtc->primary_enabled = true;
664
665 I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
666 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
667 686
668 /* 687 /*
669 * FIXME IPS should be fine as long as one plane is 688 * FIXME IPS should be fine as long as one plane is
@@ -682,17 +701,11 @@ intel_enable_primary(struct drm_crtc *crtc)
682} 701}
683 702
684static void 703static void
685intel_disable_primary(struct drm_crtc *crtc) 704intel_pre_disable_primary(struct drm_crtc *crtc)
686{ 705{
687 struct drm_device *dev = crtc->dev; 706 struct drm_device *dev = crtc->dev;
688 struct drm_i915_private *dev_priv = dev->dev_private; 707 struct drm_i915_private *dev_priv = dev->dev_private;
689 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 708 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
690 int reg = DSPCNTR(intel_crtc->plane);
691
692 if (!intel_crtc->primary_enabled)
693 return;
694
695 intel_crtc->primary_enabled = false;
696 709
697 mutex_lock(&dev->struct_mutex); 710 mutex_lock(&dev->struct_mutex);
698 if (dev_priv->fbc.plane == intel_crtc->plane) 711 if (dev_priv->fbc.plane == intel_crtc->plane)
@@ -706,9 +719,6 @@ intel_disable_primary(struct drm_crtc *crtc)
706 * versa. 719 * versa.
707 */ 720 */
708 hsw_disable_ips(intel_crtc); 721 hsw_disable_ips(intel_crtc);
709
710 I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
711 intel_flush_primary_plane(dev_priv, intel_crtc->plane);
712} 722}
713 723
714static int 724static int
@@ -802,7 +812,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
802 struct drm_i915_gem_object *obj = intel_fb->obj; 812 struct drm_i915_gem_object *obj = intel_fb->obj;
803 struct drm_i915_gem_object *old_obj = intel_plane->obj; 813 struct drm_i915_gem_object *old_obj = intel_plane->obj;
804 int ret; 814 int ret;
805 bool disable_primary = false; 815 bool primary_enabled;
806 bool visible; 816 bool visible;
807 int hscale, vscale; 817 int hscale, vscale;
808 int max_scale, min_scale; 818 int max_scale, min_scale;
@@ -973,8 +983,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
973 * If the sprite is completely covering the primary plane, 983 * If the sprite is completely covering the primary plane,
974 * we can disable the primary and save power. 984 * we can disable the primary and save power.
975 */ 985 */
976 disable_primary = drm_rect_equals(&dst, &clip) && !colorkey_enabled(intel_plane); 986 primary_enabled = !drm_rect_equals(&dst, &clip) || colorkey_enabled(intel_plane);
977 WARN_ON(disable_primary && !visible && intel_crtc->active); 987 WARN_ON(!primary_enabled && !visible && intel_crtc->active);
978 988
979 mutex_lock(&dev->struct_mutex); 989 mutex_lock(&dev->struct_mutex);
980 990
@@ -1001,12 +1011,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
1001 intel_plane->obj = obj; 1011 intel_plane->obj = obj;
1002 1012
1003 if (intel_crtc->active) { 1013 if (intel_crtc->active) {
1004 /* 1014 bool primary_was_enabled = intel_crtc->primary_enabled;
1005 * Be sure to re-enable the primary before the sprite is no longer 1015
1006 * covering it fully. 1016 intel_crtc->primary_enabled = primary_enabled;
1007 */ 1017
1008 if (!disable_primary) 1018 if (primary_was_enabled && !primary_enabled)
1009 intel_enable_primary(crtc); 1019 intel_pre_disable_primary(crtc);
1010 1020
1011 if (visible) 1021 if (visible)
1012 intel_plane->update_plane(plane, crtc, fb, obj, 1022 intel_plane->update_plane(plane, crtc, fb, obj,
@@ -1015,8 +1025,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
1015 else 1025 else
1016 intel_plane->disable_plane(plane, crtc); 1026 intel_plane->disable_plane(plane, crtc);
1017 1027
1018 if (disable_primary) 1028 if (!primary_was_enabled && primary_enabled)
1019 intel_disable_primary(crtc); 1029 intel_post_enable_primary(crtc);
1020 } 1030 }
1021 1031
1022 /* Unpin old obj after new one is active to avoid ugliness */ 1032 /* Unpin old obj after new one is active to avoid ugliness */
@@ -1054,8 +1064,14 @@ intel_disable_plane(struct drm_plane *plane)
1054 intel_crtc = to_intel_crtc(plane->crtc); 1064 intel_crtc = to_intel_crtc(plane->crtc);
1055 1065
1056 if (intel_crtc->active) { 1066 if (intel_crtc->active) {
1057 intel_enable_primary(plane->crtc); 1067 bool primary_was_enabled = intel_crtc->primary_enabled;
1068
1069 intel_crtc->primary_enabled = true;
1070
1058 intel_plane->disable_plane(plane, plane->crtc); 1071 intel_plane->disable_plane(plane, plane->crtc);
1072
1073 if (!primary_was_enabled && intel_crtc->primary_enabled)
1074 intel_post_enable_primary(plane->crtc);
1059 } 1075 }
1060 1076
1061 if (intel_plane->obj) { 1077 if (intel_plane->obj) {