diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-26 15:58:12 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-09-03 13:17:55 -0400 |
commit | ffe74d75502e3a9b0791240b5562bcbecc6ab8dc (patch) | |
tree | ce91b82d07449c92532c1077775dcd7dcaf51808 /drivers/gpu/drm/i915/intel_display.c | |
parent | 0d1aacac36530fce058d7a0db3da7befd5765417 (diff) |
drm/i915: Use RCS flips on Ivybridge+
RCS flips do work on Iybridge+ so long as we can unmask the messages
through DERRMR. However, there are quite a few workarounds mentioned
regarding unmasking more than one event or triggering more than one
message through DERRMR. Those workarounds in principle prevent us from
performing pipelined flips (and asynchronous flips across multiple
planes) and equally apply to the "known good" BCS ring. Given that it
already appears to work, and also appears to work with unmasking all 3
planes at once (and queuing flips across multiple planes), be brave.
Bugzlla: https://bugs.freedesktop.org/show_bug.cgi?id=67600
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Lightly-tested-by: Stephane Marchesin <marchesin@icps.u-strasbg.fr>
Cc: Stephane Marchesin <marchesin@icps.u-strasbg.fr>
Cc: Ben Widawsky <ben@bwidawsk.net>
Tested-by: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 38452d82ac7d..a98392f9894e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -7828,12 +7828,6 @@ err: | |||
7828 | return ret; | 7828 | return ret; |
7829 | } | 7829 | } |
7830 | 7830 | ||
7831 | /* | ||
7832 | * On gen7 we currently use the blit ring because (in early silicon at least) | ||
7833 | * the render ring doesn't give us interrpts for page flip completion, which | ||
7834 | * means clients will hang after the first flip is queued. Fortunately the | ||
7835 | * blit ring generates interrupts properly, so use it instead. | ||
7836 | */ | ||
7837 | static int intel_gen7_queue_flip(struct drm_device *dev, | 7831 | static int intel_gen7_queue_flip(struct drm_device *dev, |
7838 | struct drm_crtc *crtc, | 7832 | struct drm_crtc *crtc, |
7839 | struct drm_framebuffer *fb, | 7833 | struct drm_framebuffer *fb, |
@@ -7842,9 +7836,13 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
7842 | { | 7836 | { |
7843 | struct drm_i915_private *dev_priv = dev->dev_private; | 7837 | struct drm_i915_private *dev_priv = dev->dev_private; |
7844 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 7838 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
7845 | struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; | 7839 | struct intel_ring_buffer *ring; |
7846 | uint32_t plane_bit = 0; | 7840 | uint32_t plane_bit = 0; |
7847 | int ret; | 7841 | int len, ret; |
7842 | |||
7843 | ring = obj->ring; | ||
7844 | if (ring == NULL || ring->id != RCS) | ||
7845 | ring = &dev_priv->ring[BCS]; | ||
7848 | 7846 | ||
7849 | ret = intel_pin_and_fence_fb_obj(dev, obj, ring); | 7847 | ret = intel_pin_and_fence_fb_obj(dev, obj, ring); |
7850 | if (ret) | 7848 | if (ret) |
@@ -7866,10 +7864,34 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
7866 | goto err_unpin; | 7864 | goto err_unpin; |
7867 | } | 7865 | } |
7868 | 7866 | ||
7869 | ret = intel_ring_begin(ring, 4); | 7867 | len = 4; |
7868 | if (ring->id == RCS) | ||
7869 | len += 6; | ||
7870 | |||
7871 | ret = intel_ring_begin(ring, len); | ||
7870 | if (ret) | 7872 | if (ret) |
7871 | goto err_unpin; | 7873 | goto err_unpin; |
7872 | 7874 | ||
7875 | /* Unmask the flip-done completion message. Note that the bspec says that | ||
7876 | * we should do this for both the BCS and RCS, and that we must not unmask | ||
7877 | * more than one flip event at any time (or ensure that one flip message | ||
7878 | * can be sent by waiting for flip-done prior to queueing new flips). | ||
7879 | * Experimentation says that BCS works despite DERRMR masking all | ||
7880 | * flip-done completion events and that unmasking all planes at once | ||
7881 | * for the RCS also doesn't appear to drop events. Setting the DERRMR | ||
7882 | * to zero does lead to lockups within MI_DISPLAY_FLIP. | ||
7883 | */ | ||
7884 | if (ring->id == RCS) { | ||
7885 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); | ||
7886 | intel_ring_emit(ring, DERRMR); | ||
7887 | intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | | ||
7888 | DERRMR_PIPEB_PRI_FLIP_DONE | | ||
7889 | DERRMR_PIPEC_PRI_FLIP_DONE)); | ||
7890 | intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1)); | ||
7891 | intel_ring_emit(ring, DERRMR); | ||
7892 | intel_ring_emit(ring, ring->scratch.gtt_offset + 256); | ||
7893 | } | ||
7894 | |||
7873 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); | 7895 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); |
7874 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); | 7896 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); |
7875 | intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); | 7897 | intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset); |