diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 40 |
2 files changed, 49 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b6a58f720f9a..b2fa2a4c4454 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -245,6 +245,7 @@ | |||
245 | * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! | 245 | * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! |
246 | */ | 246 | */ |
247 | #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) | 247 | #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) |
248 | #define MI_STORE_REGISTER_MEM(x) MI_INSTR(0x24, 2*x-1) | ||
248 | #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ | 249 | #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ |
249 | #define MI_FLUSH_DW_STORE_INDEX (1<<21) | 250 | #define MI_FLUSH_DW_STORE_INDEX (1<<21) |
250 | #define MI_INVALIDATE_TLB (1<<18) | 251 | #define MI_INVALIDATE_TLB (1<<18) |
@@ -693,6 +694,23 @@ | |||
693 | #define FPGA_DBG_RM_NOCLAIM (1<<31) | 694 | #define FPGA_DBG_RM_NOCLAIM (1<<31) |
694 | 695 | ||
695 | #define DERRMR 0x44050 | 696 | #define DERRMR 0x44050 |
697 | #define DERRMR_PIPEA_SCANLINE (1<<0) | ||
698 | #define DERRMR_PIPEA_PRI_FLIP_DONE (1<<1) | ||
699 | #define DERRMR_PIPEA_SPR_FLIP_DONE (1<<2) | ||
700 | #define DERRMR_PIPEA_VBLANK (1<<3) | ||
701 | #define DERRMR_PIPEA_HBLANK (1<<5) | ||
702 | #define DERRMR_PIPEB_SCANLINE (1<<8) | ||
703 | #define DERRMR_PIPEB_PRI_FLIP_DONE (1<<9) | ||
704 | #define DERRMR_PIPEB_SPR_FLIP_DONE (1<<10) | ||
705 | #define DERRMR_PIPEB_VBLANK (1<<11) | ||
706 | #define DERRMR_PIPEB_HBLANK (1<<13) | ||
707 | /* Note that PIPEC is not a simple translation of PIPEA/PIPEB */ | ||
708 | #define DERRMR_PIPEC_SCANLINE (1<<14) | ||
709 | #define DERRMR_PIPEC_PRI_FLIP_DONE (1<<15) | ||
710 | #define DERRMR_PIPEC_SPR_FLIP_DONE (1<<20) | ||
711 | #define DERRMR_PIPEC_VBLANK (1<<21) | ||
712 | #define DERRMR_PIPEC_HBLANK (1<<22) | ||
713 | |||
696 | 714 | ||
697 | /* GM45+ chicken bits -- debug workaround bits that may be required | 715 | /* GM45+ chicken bits -- debug workaround bits that may be required |
698 | * for various sorts of correct behavior. The top 16 bits of each are | 716 | * for various sorts of correct behavior. The top 16 bits of each are |
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); |