[Intel-gfx] [PATCH 4/4] drm/i915: Use atomic helper for pageflips
Matt Roper
matthew.d.roper at intel.com
Fri Jan 30 16:22:39 PST 2015
Now that we have asynchronous nuclear pageflip, we should be able to
push our legacy pageflip ioctl through the atomic helper and rip out a
bunch of i915-specific pageflip code.
This patch is actually pretty conservative; I think there's a lot more
flip-related infrastructure that should be ripped out now that we're
never doing command streamer flips and always letting the DRM core
handle the flip logic.
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 6 -
drivers/gpu/drm/i915/i915_params.c | 5 -
drivers/gpu/drm/i915/intel_display.c | 719 +----------------------------------
drivers/gpu/drm/i915/intel_lrc.c | 3 +-
4 files changed, 3 insertions(+), 730 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c7a520a..f13f109 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -556,11 +556,6 @@ struct drm_i915_display_funcs {
void (*audio_codec_disable)(struct intel_encoder *encoder);
void (*fdi_link_train)(struct drm_crtc *crtc);
void (*init_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 intel_engine_cs *ring,
- uint32_t flags);
void (*update_primary_plane)(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int x, int y);
@@ -2526,7 +2521,6 @@ struct i915_params {
bool reset;
bool disable_display;
bool disable_vtd_wa;
- int use_mmio_flip;
bool mmio_debug;
bool verbose_state_checks;
bool nuclear_pageflip;
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index 44f2262..794811f 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -49,7 +49,6 @@ struct i915_params i915 __read_mostly = {
.disable_display = 0,
.enable_cmd_parser = 1,
.disable_vtd_wa = 0,
- .use_mmio_flip = 0,
.mmio_debug = 0,
.verbose_state_checks = 1,
.nuclear_pageflip = 0,
@@ -167,10 +166,6 @@ module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
MODULE_PARM_DESC(enable_cmd_parser,
"Enable command parsing (1=enabled [default], 0=disabled)");
-module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600);
-MODULE_PARM_DESC(use_mmio_flip,
- "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)");
-
module_param_named(mmio_debug, i915.mmio_debug, bool, 0600);
MODULE_PARM_DESC(mmio_debug,
"Enable the MMIO debug code (default: false). This may negatively "
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ebf973c..706bb3f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2934,17 +2934,12 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- bool pending;
if (i915_reset_in_progress(&dev_priv->gpu_error) ||
intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
return false;
- spin_lock_irq(&dev->event_lock);
- pending = to_intel_crtc(crtc)->unpin_work != NULL;
- spin_unlock_irq(&dev->event_lock);
-
- return pending;
+ return 0;
}
static void intel_update_pipe_size(struct intel_crtc *crtc)
@@ -9047,32 +9042,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
kfree(intel_crtc);
}
-static void intel_unpin_work_fn(struct work_struct *__work)
-{
- struct intel_unpin_work *work =
- container_of(__work, struct intel_unpin_work, work);
- struct drm_device *dev = work->crtc->dev;
- enum pipe pipe = to_intel_crtc(work->crtc)->pipe;
-
- mutex_lock(&dev->struct_mutex);
- intel_unpin_fb_obj(work->old_fb_obj);
- drm_gem_object_unreference(&work->pending_flip_obj->base);
- drm_gem_object_unreference(&work->old_fb_obj->base);
-
- intel_fbc_update(dev);
-
- if (work->flip_queued_req)
- i915_gem_request_assign(&work->flip_queued_req, NULL);
- mutex_unlock(&dev->struct_mutex);
-
- intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
-
- BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
- atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
-
- kfree(work);
-}
-
static void do_intel_finish_page_flip(struct drm_device *dev,
struct drm_crtc *crtc)
{
@@ -9188,473 +9157,6 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
spin_unlock_irqrestore(&dev->event_lock, flags);
}
-static inline void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
-{
- /* Ensure that the work item is consistent when activating it ... */
- smp_wmb();
- atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
- /* and that it is marked active as soon as the irq could fire. */
- smp_wmb();
-}
-
-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 intel_engine_cs *ring,
- uint32_t flags)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- u32 flip_mask;
- int ret;
-
- ret = intel_ring_begin(ring, 6);
- if (ret)
- return ret;
-
- /* Can't queue multiple flips, so wait for the previous
- * one to finish before executing the next.
- */
- if (intel_crtc->plane)
- flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
- else
- flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
- intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_emit(ring, MI_DISPLAY_FLIP |
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
- intel_ring_emit(ring, fb->pitches[0]);
- intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
- intel_ring_emit(ring, 0); /* aux display base address, unused */
-
- intel_mark_page_flip_active(intel_crtc);
- __intel_ring_advance(ring);
- return 0;
-}
-
-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 intel_engine_cs *ring,
- uint32_t flags)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- u32 flip_mask;
- int ret;
-
- ret = intel_ring_begin(ring, 6);
- if (ret)
- return ret;
-
- if (intel_crtc->plane)
- flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
- else
- flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
- intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
- intel_ring_emit(ring, MI_NOOP);
- intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
- intel_ring_emit(ring, fb->pitches[0]);
- intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
- intel_ring_emit(ring, MI_NOOP);
-
- intel_mark_page_flip_active(intel_crtc);
- __intel_ring_advance(ring);
- return 0;
-}
-
-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 intel_engine_cs *ring,
- uint32_t flags)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t pf, pipesrc;
- int ret;
-
- ret = intel_ring_begin(ring, 4);
- if (ret)
- return ret;
-
- /* i965+ uses the linear or tiled offsets from the
- * Display Registers (which do not change across a page-flip)
- * so we need only reprogram the base address.
- */
- intel_ring_emit(ring, MI_DISPLAY_FLIP |
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
- intel_ring_emit(ring, fb->pitches[0]);
- intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset |
- obj->tiling_mode);
-
- /* XXX Enabling the panel-fitter across page-flip is so far
- * untested on non-native modes, so ignore it for now.
- * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
- */
- pf = 0;
- pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
- intel_ring_emit(ring, pf | pipesrc);
-
- intel_mark_page_flip_active(intel_crtc);
- __intel_ring_advance(ring);
- return 0;
-}
-
-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 intel_engine_cs *ring,
- uint32_t flags)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t pf, pipesrc;
- int ret;
-
- ret = intel_ring_begin(ring, 4);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, MI_DISPLAY_FLIP |
- MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
- intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
- intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-
- /* Contrary to the suggestions in the documentation,
- * "Enable Panel Fitter" does not seem to be required when page
- * flipping with a non-native mode, and worse causes a normal
- * modeset to fail.
- * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
- */
- pf = 0;
- pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
- intel_ring_emit(ring, pf | pipesrc);
-
- intel_mark_page_flip_active(intel_crtc);
- __intel_ring_advance(ring);
- return 0;
-}
-
-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 intel_engine_cs *ring,
- uint32_t flags)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t plane_bit = 0;
- int len, ret;
-
- switch (intel_crtc->plane) {
- case PLANE_A:
- plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A;
- break;
- case PLANE_B:
- plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B;
- break;
- case PLANE_C:
- plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C;
- break;
- default:
- WARN_ONCE(1, "unknown plane in flip command\n");
- return -ENODEV;
- }
-
- len = 4;
- if (ring->id == RCS) {
- len += 6;
- /*
- * On Gen 8, SRM is now taking an extra dword to accommodate
- * 48bits addresses, and we need a NOOP for the batch size to
- * stay even.
- */
- if (IS_GEN8(dev))
- len += 2;
- }
-
- /*
- * BSpec MI_DISPLAY_FLIP for IVB:
- * "The full packet must be contained within the same cache line."
- *
- * Currently the LRI+SRM+MI_DISPLAY_FLIP all fit within the same
- * cacheline, if we ever start emitting more commands before
- * the MI_DISPLAY_FLIP we may need to first emit everything else,
- * then do the cacheline alignment, and finally emit the
- * MI_DISPLAY_FLIP.
- */
- ret = intel_ring_cacheline_align(ring);
- if (ret)
- return ret;
-
- ret = intel_ring_begin(ring, len);
- if (ret)
- return ret;
-
- /* Unmask the flip-done completion message. Note that the bspec says that
- * we should do this for both the BCS and RCS, and that we must not unmask
- * more than one flip event at any time (or ensure that one flip message
- * can be sent by waiting for flip-done prior to queueing new flips).
- * Experimentation says that BCS works despite DERRMR masking all
- * flip-done completion events and that unmasking all planes at once
- * for the RCS also doesn't appear to drop events. Setting the DERRMR
- * to zero does lead to lockups within MI_DISPLAY_FLIP.
- */
- if (ring->id == RCS) {
- intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, DERRMR);
- intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
- DERRMR_PIPEB_PRI_FLIP_DONE |
- DERRMR_PIPEC_PRI_FLIP_DONE));
- if (IS_GEN8(dev))
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) |
- MI_SRM_LRM_GLOBAL_GTT);
- else
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM(1) |
- MI_SRM_LRM_GLOBAL_GTT);
- intel_ring_emit(ring, DERRMR);
- intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
- if (IS_GEN8(dev)) {
- intel_ring_emit(ring, 0);
- intel_ring_emit(ring, MI_NOOP);
- }
- }
-
- intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
- intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
- intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
- intel_ring_emit(ring, (MI_NOOP));
-
- intel_mark_page_flip_active(intel_crtc);
- __intel_ring_advance(ring);
- return 0;
-}
-
-static bool use_mmio_flip(struct intel_engine_cs *ring,
- struct drm_i915_gem_object *obj)
-{
- /*
- * This is not being used for older platforms, because
- * non-availability of flip done interrupt forces us to use
- * CS flips. Older platforms derive flip done using some clever
- * tricks involving the flip_pending status bits and vblank irqs.
- * So using MMIO flips there would disrupt this mechanism.
- */
-
- if (ring == NULL)
- return true;
-
- if (INTEL_INFO(ring->dev)->gen < 5)
- return false;
-
- if (i915.use_mmio_flip < 0)
- return false;
- else if (i915.use_mmio_flip > 0)
- return true;
- else if (i915.enable_execlists)
- return true;
- else
- return ring != i915_gem_request_get_ring(obj->last_read_req);
-}
-
-static void skl_do_mmio_flip(struct intel_crtc *intel_crtc)
-{
- struct drm_device *dev = intel_crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
- struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
- const enum pipe pipe = intel_crtc->pipe;
- u32 ctl, stride;
-
- ctl = I915_READ(PLANE_CTL(pipe, 0));
- ctl &= ~PLANE_CTL_TILED_MASK;
- if (obj->tiling_mode == I915_TILING_X)
- ctl |= PLANE_CTL_TILED_X;
-
- /*
- * The stride is either expressed as a multiple of 64 bytes chunks for
- * linear buffers or in number of tiles for tiled buffers.
- */
- stride = fb->pitches[0] >> 6;
- if (obj->tiling_mode == I915_TILING_X)
- stride = fb->pitches[0] >> 9; /* X tiles are 512 bytes wide */
-
- /*
- * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
- * PLANE_SURF updates, the update is then guaranteed to be atomic.
- */
- I915_WRITE(PLANE_CTL(pipe, 0), ctl);
- I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
-
- I915_WRITE(PLANE_SURF(pipe, 0), intel_crtc->unpin_work->gtt_offset);
- POSTING_READ(PLANE_SURF(pipe, 0));
-}
-
-static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc)
-{
- struct drm_device *dev = intel_crtc->base.dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct intel_framebuffer *intel_fb =
- to_intel_framebuffer(intel_crtc->base.primary->fb);
- struct drm_i915_gem_object *obj = intel_fb->obj;
- u32 dspcntr;
- u32 reg;
-
- reg = DSPCNTR(intel_crtc->plane);
- dspcntr = I915_READ(reg);
-
- if (obj->tiling_mode != I915_TILING_NONE)
- dspcntr |= DISPPLANE_TILED;
- else
- dspcntr &= ~DISPPLANE_TILED;
-
- I915_WRITE(reg, dspcntr);
-
- I915_WRITE(DSPSURF(intel_crtc->plane),
- intel_crtc->unpin_work->gtt_offset);
- POSTING_READ(DSPSURF(intel_crtc->plane));
-
-}
-
-/*
- * XXX: This is the temporary way to update the plane registers until we get
- * around to using the usual plane update functions for MMIO flips
- */
-static void intel_do_mmio_flip(struct intel_crtc *intel_crtc)
-{
- struct drm_device *dev = intel_crtc->base.dev;
- bool atomic_update;
- u32 start_vbl_count;
-
- intel_mark_page_flip_active(intel_crtc);
-
- atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
-
- if (INTEL_INFO(dev)->gen >= 9)
- skl_do_mmio_flip(intel_crtc);
- else
- /* use_mmio_flip() retricts MMIO flips to ilk+ */
- ilk_do_mmio_flip(intel_crtc);
-
- if (atomic_update)
- intel_pipe_update_end(intel_crtc, start_vbl_count);
-}
-
-static void intel_mmio_flip_work_func(struct work_struct *work)
-{
- struct intel_crtc *crtc =
- container_of(work, struct intel_crtc, mmio_flip.work);
- struct intel_mmio_flip *mmio_flip;
-
- mmio_flip = &crtc->mmio_flip;
- if (mmio_flip->req)
- WARN_ON(__i915_wait_request(mmio_flip->req,
- crtc->reset_counter,
- false, NULL, NULL) != 0);
-
- intel_do_mmio_flip(crtc);
- if (mmio_flip->req) {
- mutex_lock(&crtc->base.dev->struct_mutex);
- i915_gem_request_assign(&mmio_flip->req, NULL);
- mutex_unlock(&crtc->base.dev->struct_mutex);
- }
-}
-
-static int intel_queue_mmio_flip(struct drm_device *dev,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_i915_gem_object *obj,
- struct intel_engine_cs *ring,
- uint32_t flags)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
- i915_gem_request_assign(&intel_crtc->mmio_flip.req,
- obj->last_write_req);
-
- schedule_work(&intel_crtc->mmio_flip.work);
-
- return 0;
-}
-
-static int intel_gen9_queue_flip(struct drm_device *dev,
- struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_i915_gem_object *obj,
- struct intel_engine_cs *ring,
- uint32_t flags)
-{
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- uint32_t plane = 0, stride;
- int ret;
-
- switch(intel_crtc->pipe) {
- case PIPE_A:
- plane = MI_DISPLAY_FLIP_SKL_PLANE_1_A;
- break;
- case PIPE_B:
- plane = MI_DISPLAY_FLIP_SKL_PLANE_1_B;
- break;
- case PIPE_C:
- plane = MI_DISPLAY_FLIP_SKL_PLANE_1_C;
- break;
- default:
- WARN_ONCE(1, "unknown plane in flip command\n");
- return -ENODEV;
- }
-
- switch (obj->tiling_mode) {
- case I915_TILING_NONE:
- stride = fb->pitches[0] >> 6;
- break;
- case I915_TILING_X:
- stride = fb->pitches[0] >> 9;
- break;
- default:
- WARN_ONCE(1, "unknown tiling in flip command\n");
- return -ENODEV;
- }
-
- ret = intel_ring_begin(ring, 10);
- if (ret)
- return ret;
-
- intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
- intel_ring_emit(ring, DERRMR);
- intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
- DERRMR_PIPEB_PRI_FLIP_DONE |
- DERRMR_PIPEC_PRI_FLIP_DONE));
- intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) |
- MI_SRM_LRM_GLOBAL_GTT);
- intel_ring_emit(ring, DERRMR);
- intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
- intel_ring_emit(ring, 0);
-
- intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane);
- intel_ring_emit(ring, stride << 6 | obj->tiling_mode);
- intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-
- intel_mark_page_flip_active(intel_crtc);
- __intel_ring_advance(ring);
-
- return 0;
-}
-
-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 intel_engine_cs *ring,
- uint32_t flags)
-{
- return -ENODEV;
-}
-
static bool __intel_pageflip_stall_check(struct drm_device *dev,
struct drm_crtc *crtc)
{
@@ -9714,192 +9216,6 @@ void intel_check_page_flip(struct drm_device *dev, int pipe)
spin_unlock(&dev->event_lock);
}
-static int intel_crtc_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags)
-{
- struct drm_device *dev = crtc->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_framebuffer *old_fb = crtc->primary->fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
- struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct drm_plane *primary = crtc->primary;
- enum pipe pipe = intel_crtc->pipe;
- struct intel_unpin_work *work;
- struct intel_engine_cs *ring;
- int ret;
-
- /*
- * drm_mode_page_flip_ioctl() should already catch this, but double
- * check to be safe. In the future we may enable pageflipping from
- * a disabled primary plane.
- */
- if (WARN_ON(intel_fb_obj(old_fb) == NULL))
- return -EBUSY;
-
- /* Can't change pixel format via MI display flips. */
- if (fb->pixel_format != crtc->primary->fb->pixel_format)
- return -EINVAL;
-
- /*
- * TILEOFF/LINOFF registers can't be changed via MI display flips.
- * Note that pitch changes could also affect these register.
- */
- if (INTEL_INFO(dev)->gen > 3 &&
- (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
- fb->pitches[0] != crtc->primary->fb->pitches[0]))
- return -EINVAL;
-
- if (i915_terminally_wedged(&dev_priv->gpu_error))
- goto out_hang;
-
- work = kzalloc(sizeof(*work), GFP_KERNEL);
- if (work == NULL)
- return -ENOMEM;
-
- work->event = event;
- work->crtc = crtc;
- work->old_fb_obj = intel_fb_obj(old_fb);
- INIT_WORK(&work->work, intel_unpin_work_fn);
-
- ret = drm_crtc_vblank_get(crtc);
- if (ret)
- goto free_work;
-
- /* We borrow the event spin lock for protecting unpin_work */
- spin_lock_irq(&dev->event_lock);
- if (intel_crtc->unpin_work) {
- /* Before declaring the flip queue wedged, check if
- * the hardware completed the operation behind our backs.
- */
- if (__intel_pageflip_stall_check(dev, crtc)) {
- DRM_DEBUG_DRIVER("flip queue: previous flip completed, continuing\n");
- page_flip_completed(intel_crtc);
- } else {
- DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
- spin_unlock_irq(&dev->event_lock);
-
- drm_crtc_vblank_put(crtc);
- kfree(work);
- return -EBUSY;
- }
- }
- intel_crtc->unpin_work = work;
- spin_unlock_irq(&dev->event_lock);
-
- if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
- flush_workqueue(dev_priv->wq);
-
- ret = i915_mutex_lock_interruptible(dev);
- if (ret)
- goto cleanup;
-
- /* Reference the objects for the scheduled work. */
- drm_gem_object_reference(&work->old_fb_obj->base);
- drm_gem_object_reference(&obj->base);
-
- crtc->primary->fb = fb;
-
- /* Keep state structure in sync */
- if (crtc->primary->state->fb)
- drm_framebuffer_unreference(crtc->primary->state->fb);
- crtc->primary->state->fb = fb;
- if (crtc->primary->state->fb)
- drm_framebuffer_reference(crtc->primary->state->fb);
-
- work->pending_flip_obj = obj;
-
- atomic_inc(&intel_crtc->unpin_work_count);
- intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
-
- if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
- work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(pipe)) + 1;
-
- if (IS_VALLEYVIEW(dev)) {
- ring = &dev_priv->ring[BCS];
- if (obj->tiling_mode != work->old_fb_obj->tiling_mode)
- /* vlv: DISPLAY_FLIP fails to change tiling */
- ring = NULL;
- } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
- ring = &dev_priv->ring[BCS];
- } else if (INTEL_INFO(dev)->gen >= 7) {
- ring = i915_gem_request_get_ring(obj->last_read_req);
- if (ring == NULL || ring->id != RCS)
- ring = &dev_priv->ring[BCS];
- } else {
- ring = &dev_priv->ring[RCS];
- }
-
- ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, ring);
- if (ret)
- goto cleanup_pending;
-
- work->gtt_offset =
- i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
-
- if (use_mmio_flip(ring, obj)) {
- ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
- page_flip_flags);
- if (ret)
- goto cleanup_unpin;
-
- i915_gem_request_assign(&work->flip_queued_req,
- obj->last_write_req);
- } else {
- ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring,
- page_flip_flags);
- if (ret)
- goto cleanup_unpin;
-
- i915_gem_request_assign(&work->flip_queued_req,
- intel_ring_get_request(ring));
- }
-
- work->flip_queued_vblank = drm_vblank_count(dev, intel_crtc->pipe);
- work->enable_stall_check = true;
-
- i915_gem_track_fb(work->old_fb_obj, obj,
- INTEL_FRONTBUFFER_PRIMARY(pipe));
-
- intel_fbc_disable(dev);
- intel_frontbuffer_flip_prepare(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
- mutex_unlock(&dev->struct_mutex);
-
- trace_i915_flip_request(intel_crtc->plane, obj);
-
- return 0;
-
-cleanup_unpin:
- intel_unpin_fb_obj(obj);
-cleanup_pending:
- atomic_dec(&intel_crtc->unpin_work_count);
- crtc->primary->fb = old_fb;
- drm_gem_object_unreference(&work->old_fb_obj->base);
- drm_gem_object_unreference(&obj->base);
- mutex_unlock(&dev->struct_mutex);
-
-cleanup:
- spin_lock_irq(&dev->event_lock);
- intel_crtc->unpin_work = NULL;
- spin_unlock_irq(&dev->event_lock);
-
- drm_crtc_vblank_put(crtc);
-free_work:
- kfree(work);
-
- if (ret == -EIO) {
-out_hang:
- ret = intel_plane_restore(primary);
- if (ret == 0 && event) {
- spin_lock_irq(&dev->event_lock);
- drm_send_vblank_event(dev, pipe, event);
- spin_unlock_irq(&dev->event_lock);
- }
- }
- return ret;
-}
-
static struct drm_crtc_helper_funcs intel_helper_funcs = {
.mode_set_base_atomic = intel_pipe_set_base_atomic,
.load_lut = intel_crtc_load_lut,
@@ -11675,7 +10991,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
.gamma_set = intel_crtc_gamma_set,
.set_config = intel_crtc_set_config,
.destroy = intel_crtc_destroy,
- .page_flip = intel_crtc_page_flip,
+ .page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = intel_crtc_duplicate_state,
.atomic_destroy_state = intel_crtc_destroy_state,
};
@@ -12357,8 +11673,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
- INIT_WORK(&intel_crtc->mmio_flip.work, intel_mmio_flip_work_func);
-
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
@@ -12930,35 +12244,6 @@ static void intel_init_display(struct drm_device *dev)
valleyview_modeset_global_resources;
}
- /* Default just returns -ENODEV to indicate unsupported */
- dev_priv->display.queue_flip = intel_default_queue_flip;
-
- switch (INTEL_INFO(dev)->gen) {
- case 2:
- dev_priv->display.queue_flip = intel_gen2_queue_flip;
- break;
-
- case 3:
- dev_priv->display.queue_flip = intel_gen3_queue_flip;
- break;
-
- case 4:
- case 5:
- dev_priv->display.queue_flip = intel_gen4_queue_flip;
- break;
-
- case 6:
- dev_priv->display.queue_flip = intel_gen6_queue_flip;
- break;
- case 7:
- case 8: /* FIXME(BDW): Check that the gen8 RCS flip works. */
- dev_priv->display.queue_flip = intel_gen7_queue_flip;
- break;
- case 9:
- dev_priv->display.queue_flip = intel_gen9_queue_flip;
- break;
- }
-
intel_panel_init_backlight_funcs(dev);
mutex_init(&dev_priv->pps_mutex);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index a94346f..ceec373 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -226,8 +226,7 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists
if (enable_execlists == 0)
return 0;
- if (HAS_LOGICAL_RING_CONTEXTS(dev) && USES_PPGTT(dev) &&
- i915.use_mmio_flip >= 0)
+ if (HAS_LOGICAL_RING_CONTEXTS(dev) && USES_PPGTT(dev))
return 1;
return 0;
--
1.8.5.1
More information about the Intel-gfx
mailing list