aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-04-05 14:03:51 -0700
committerEric Anholt <eric@anholt.net>2010-06-18 17:59:48 -0700
commit83f7fd055eb3f1e843803cd906179d309553967b (patch)
tree86d17ba0c90eed7347f2a136c44a821b42c5798d /drivers/gpu/drm
parentbe26a10bd10271b4a810ece2e540c0cdd77881bc (diff)
drm/i915: don't queue flips during a flip pending event
Hardware will set the flip pending ISR bit as soon as it receives the flip instruction, and (supposedly) clear it once the flip completes (e.g. at the next vblank). If we try to send down a flip instruction while the ISR bit is set, the hardware can become very confused, and we may never receive the corresponding flip pending interrupt, effectively hanging the chip. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fdeff435372..dc65a1de5f0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4680,6 +4680,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
unsigned long flags;
int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
int ret, pipesrc;
+ u32 flip_mask;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
@@ -4733,6 +4734,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
atomic_inc(&obj_priv->pending_flip);
work->pending_flip_obj = obj;
+ if (intel_crtc->plane)
+ flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
+ else
+ flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
+
+ /* Wait for any previous flip to finish */
+ if (IS_GEN3(dev))
+ while (I915_READ(ISR) & flip_mask)
+ ;
+
BEGIN_LP_RING(4);
OUT_RING(MI_DISPLAY_FLIP |
MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));