diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2014-04-29 06:35:47 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-05-06 04:18:02 -0400 |
commit | 5b633d6b8e3aa1f3ba3daa568416e36e054a3bb1 (patch) | |
tree | a49a3ba4133cfae651ae1c62d352fc5c1033fed3 | |
parent | 8d7849db3eab7f560deba145dfed3cd4df97c975 (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.c | 94 |
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 | ||
123 | static 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 | |||
123 | static void | 134 | static void |
124 | vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | 135 | vlv_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 | ||
652 | static void | 681 | static void |
653 | intel_enable_primary(struct drm_crtc *crtc) | 682 | intel_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 | ||
684 | static void | 703 | static void |
685 | intel_disable_primary(struct drm_crtc *crtc) | 704 | intel_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 | ||
714 | static int | 724 | static 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) { |