@@ -15612,6 +15612,11 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_dbuf_pre_plane_update(state);
+ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+ if (new_crtc_state->uapi.async_flip)
+ skl_enable_flip_done(crtc);
+ }
+
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
dev_priv->display.commit_modeset_enables(state);
@@ -15633,6 +15638,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
drm_atomic_helper_wait_for_flip_done(dev, &state->base);
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+ if (new_crtc_state->uapi.async_flip)
+ skl_disable_flip_done(crtc);
+
if (new_crtc_state->hw.active &&
!needs_modeset(new_crtc_state) &&
!new_crtc_state->preload_luts &&
@@ -1245,6 +1245,23 @@ display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
u32 crc4) {}
#endif
+static void flip_done_handler(struct drm_i915_private *i915,
+ enum pipe pipe)
+{
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(i915, pipe);
+ struct drm_crtc_state *crtc_state = crtc->base.state;
+ struct drm_pending_vblank_event *e = crtc_state->event;
+ struct drm_device *dev = &i915->drm;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev->event_lock, irqflags);
+
+ crtc_state->event = NULL;
+
+ drm_crtc_send_vblank_event(&crtc->base, e);
+
+ spin_unlock_irqrestore(&dev->event_lock, irqflags);
+}
static void hsw_pipe_crc_irq_handler(struct drm_i915_private *dev_priv,
enum pipe pipe)
@@ -2329,6 +2346,9 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
if (iir & GEN8_PIPE_VBLANK)
intel_handle_vblank(dev_priv, pipe);
+ if (iir & GEN9_PIPE_PLANE1_FLIP_DONE)
+ flip_done_handler(dev_priv, pipe);
+
if (iir & GEN8_PIPE_CDCLK_CRC_DONE)
hsw_pipe_crc_irq_handler(dev_priv, pipe);
@@ -2650,6 +2670,19 @@ int bdw_enable_vblank(struct drm_crtc *crtc)
return 0;
}
+void skl_enable_flip_done(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&i915->irq_lock, irqflags);
+
+ bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE1_FLIP_DONE);
+
+ spin_unlock_irqrestore(&i915->irq_lock, irqflags);
+}
+
/* Called from drm generic code, passed 'crtc' which
* we use as a pipe index
*/
@@ -2710,6 +2743,19 @@ void bdw_disable_vblank(struct drm_crtc *crtc)
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
}
+void skl_disable_flip_done(struct intel_crtc *crtc)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ enum pipe pipe = crtc->pipe;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&i915->irq_lock, irqflags);
+
+ bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE1_FLIP_DONE);
+
+ spin_unlock_irqrestore(&i915->irq_lock, irqflags);
+}
+
static void ibx_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
@@ -2920,6 +2966,9 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN;
enum pipe pipe;
+ if (INTEL_GEN(dev_priv) >= 9)
+ extra_ier |= GEN9_PIPE_PLANE1_FLIP_DONE;
+
spin_lock_irq(&dev_priv->irq_lock);
if (!intel_irqs_enabled(dev_priv)) {
@@ -3403,6 +3452,9 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK |
GEN8_PIPE_FIFO_UNDERRUN;
+ if (INTEL_GEN(dev_priv) >= 9)
+ de_pipe_enables |= GEN9_PIPE_PLANE1_FLIP_DONE;
+
de_port_enables = de_port_masked;
if (IS_GEN9_LP(dev_priv))
de_port_enables |= BXT_DE_PORT_HOTPLUG_MASK;
@@ -118,6 +118,9 @@ void i965_disable_vblank(struct drm_crtc *crtc);
void ilk_disable_vblank(struct drm_crtc *crtc);
void bdw_disable_vblank(struct drm_crtc *crtc);
+void skl_enable_flip_done(struct intel_crtc *crtc);
+void skl_disable_flip_done(struct intel_crtc *crtc);
+
void gen2_irq_reset(struct intel_uncore *uncore);
void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
i915_reg_t iir, i915_reg_t ier);