diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2021-01-11 17:37:08 +0100 |
---|---|---|
committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2021-01-29 18:00:34 +0100 |
commit | cda195f13abd77fe024bbe1a2cb9ac99b9915270 (patch) | |
tree | 598bbd5bccc92b256b56789f0d11ba69e8e0981a /drivers/gpu/drm/i915/display/i9xx_plane.c | |
parent | drm/i915: Limit plane stride to below TILEOFF.x limit (diff) | |
download | linux-cda195f13abd77fe024bbe1a2cb9ac99b9915270.tar.xz linux-cda195f13abd77fe024bbe1a2cb9ac99b9915270.zip |
drm/i915: Implement async flips for bdw
Implement async flip support for BDW. The implementation is
similar to the skl+ code. And just like skl/bxt/glk bdw also
needs the disable w/a, thus we need to plumb the desired state
of the async flip all the way down to i9xx_plane_ctl_crtc().
According to the spec we do need to bump the surface alignment
to 256KiB for this. Async flips require an X-tiled buffer so
we don't have to worry about linear.
Cc: Karthik B S <karthik.b.s@intel.com>
Cc: Vandita Kulkarni <vandita.kulkarni@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210111163711.12913-9-ville.syrjala@linux.intel.com
Reviewed-by: Karthik B S <karthik.b.s@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/display/i9xx_plane.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/i9xx_plane.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index 7d968ca890da..44004558ebbd 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -495,6 +495,50 @@ static void i9xx_disable_plane(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } +static void +g4x_primary_async_flip(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state, + bool async_flip) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state); + u32 dspaddr_offset = plane_state->color_plane[0].offset; + enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; + unsigned long irqflags; + + if (async_flip) + dspcntr |= DISPPLANE_ASYNC_FLIP; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), + intel_plane_ggtt_offset(plane_state) + dspaddr_offset); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +bdw_primary_enable_flip_done(struct intel_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + enum pipe pipe = plane->pipe; + + spin_lock_irq(&i915->irq_lock); + bdw_enable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE); + spin_unlock_irq(&i915->irq_lock); +} + +static void +bdw_primary_disable_flip_done(struct intel_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + enum pipe pipe = plane->pipe; + + spin_lock_irq(&i915->irq_lock); + bdw_disable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE); + spin_unlock_irq(&i915->irq_lock); +} + static bool i9xx_plane_get_hw_state(struct intel_plane *plane, enum pipe *pipe) { @@ -708,6 +752,13 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) plane->get_hw_state = i9xx_plane_get_hw_state; plane->check_plane = i9xx_plane_check; + if (IS_BROADWELL(dev_priv)) { + plane->need_async_flip_disable_wa = true; + plane->async_flip = g4x_primary_async_flip; + plane->enable_flip_done = bdw_primary_enable_flip_done; + plane->disable_flip_done = bdw_primary_disable_flip_done; + } + if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 0, plane_funcs, |