[Intel-gfx] [PATCH v8 6/8] drm/i915: WA for platforms with double buffered adress update enable bit

Karthik B S karthik.b.s at intel.com
Mon Sep 14 05:56:31 UTC 2020


In Gen 9 and Gen 10 platforms, async address update enable bit is
double buffered. Due to this, during the transition from async flip
to sync flip we have to wait until this bit is updated before continuing
with the normal commit for sync flip.

Signed-off-by: Karthik B S <karthik.b.s at intel.com>
Signed-off-by: Vandita Kulkarni <vandita.kulkarni at intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 44 ++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index a0c17d94daf3..b7e24dff0772 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -15360,6 +15360,42 @@ static void intel_enable_crtc(struct intel_atomic_state *state,
 	intel_crtc_enable_pipe_crc(crtc);
 }
 
+static void skl_toggle_async_sync(struct intel_atomic_state *state,
+				  struct intel_crtc *crtc,
+				  struct intel_crtc_state *new_crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+	struct intel_plane *plane;
+	struct intel_plane_state *new_plane_state;
+	u32 update_mask = new_crtc_state->update_planes;
+	u32 plane_ctl, surf_addr;
+	enum plane_id plane_id;
+	unsigned long irqflags;
+	enum pipe pipe;
+	int i;
+
+	for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
+		if (crtc->pipe != plane->pipe ||
+		    !(update_mask & BIT(plane->id)))
+			continue;
+
+		plane_id = plane->id;
+		pipe = plane->pipe;
+
+		plane_ctl = intel_de_read_fw(dev_priv, PLANE_CTL(pipe, plane_id));
+		surf_addr = intel_de_read_fw(dev_priv, PLANE_SURF(pipe, plane_id));
+
+		plane_ctl &= ~PLANE_CTL_ASYNC_FLIP;
+
+		spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+		intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
+		intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), surf_addr);
+		spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+	}
+
+	intel_wait_for_vblank(dev_priv, crtc->pipe);
+}
+
 static void intel_update_crtc(struct intel_atomic_state *state,
 			      struct intel_crtc *crtc)
 {
@@ -15387,6 +15423,14 @@ static void intel_update_crtc(struct intel_atomic_state *state,
 	else
 		intel_fbc_enable(state, crtc);
 
+	/* WA for older platforms where async address update enable bit
+	 * is double buffered.
+	 */
+	if (old_crtc_state->uapi.async_flip &&
+	    !new_crtc_state->uapi.async_flip &&
+	    INTEL_GEN(dev_priv) <= 10 && INTEL_GEN(dev_priv) >= 9)
+		skl_toggle_async_sync(state, crtc, new_crtc_state);
+
 	/* Perform vblank evasion around commit operation */
 	intel_pipe_update_start(new_crtc_state);
 
-- 
2.22.0



More information about the Intel-gfx mailing list