Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org> --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_display.c | 30 +++++++++++++++++++++--------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f5120d0..af9db2b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -273,7 +273,8 @@ struct drm_i915_display_funcs { void (*init_pch_clock_gating)(struct drm_device *dev); int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj); + struct drm_i915_gem_object *obj, + u32 flags); int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y); /* clock updates for mode set */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2dd880f..c9b49b7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -211,6 +211,7 @@ #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) +#define MI_DISPLAY_FLIP_ASYNC_IND (1 << 22) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) /* IVB has funny definitions for which plane to flip. */ #define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) @@ -219,6 +220,7 @@ #define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) #define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) #define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) +#define MI_DISPLAY_FLIP_ASYNC (1 << 0) /* in DW2 of the command */ #define MI_ARB_ON_OFF MI_INSTR(0x08, 0) #define MI_ARB_ENABLE (1<<0) #define MI_ARB_DISABLE (0<<0) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2c0c174..ed79892 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6878,7 +6878,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) static int intel_gen2_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + u32 flags) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -6920,7 +6921,8 @@ err: static int intel_gen3_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + u32 flags) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -6960,7 +6962,8 @@ err: static int intel_gen4_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + u32 flags) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -7006,7 +7009,8 @@ err: static int intel_gen6_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + u32 flags) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -7054,12 +7058,13 @@ err: static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + u32 flags) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; - uint32_t plane_bit = 0; + uint32_t plane_bit = 0, addr_bits = 0; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); @@ -7082,13 +7087,19 @@ static int intel_gen7_queue_flip(struct drm_device *dev, goto err_unpin; } + if (flags & DRM_MODE_PAGE_FLIP_ASYNC) { + plane_bit |= MI_DISPLAY_FLIP_ASYNC_IND; + addr_bits |= MI_DISPLAY_FLIP_ASYNC; + } + ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); - intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, (obj->gtt_offset + intel_crtc->dspaddr_offset) | + addr_bits); intel_ring_emit(ring, (MI_NOOP)); intel_ring_advance(ring); return 0; @@ -7102,7 +7113,8 @@ err: static int intel_default_queue_flip(struct drm_device *dev, struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + u32 flags) { return -ENODEV; } @@ -7183,7 +7195,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, */ atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); - ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); + ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, flags); if (ret) goto cleanup_pending; -- 1.7.9.5