aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-04-05 17:03:51 -0400
committerEric Anholt <eric@anholt.net>2010-06-18 20:59:48 -0400
commit83f7fd055eb3f1e843803cd906179d309553967b (patch)
tree86d17ba0c90eed7347f2a136c44a821b42c5798d /drivers
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')
-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 fdeff4353725..dc65a1de5f02 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,
4680 unsigned long flags; 4680 unsigned long flags;
4681 int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; 4681 int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
4682 int ret, pipesrc; 4682 int ret, pipesrc;
4683 u32 flip_mask;
4683 4684
4684 work = kzalloc(sizeof *work, GFP_KERNEL); 4685 work = kzalloc(sizeof *work, GFP_KERNEL);
4685 if (work == NULL) 4686 if (work == NULL)
@@ -4733,6 +4734,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
4733 atomic_inc(&obj_priv->pending_flip); 4734 atomic_inc(&obj_priv->pending_flip);
4734 work->pending_flip_obj = obj; 4735 work->pending_flip_obj = obj;
4735 4736
4737 if (intel_crtc->plane)
4738 flip_mask = I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
4739 else
4740 flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
4741
4742 /* Wait for any previous flip to finish */
4743 if (IS_GEN3(dev))
4744 while (I915_READ(ISR) & flip_mask)
4745 ;
4746
4736 BEGIN_LP_RING(4); 4747 BEGIN_LP_RING(4);
4737 OUT_RING(MI_DISPLAY_FLIP | 4748 OUT_RING(MI_DISPLAY_FLIP |
4738 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); 4749 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));