[RFC PATCH 4/4] drm/i915/psr: Implement Wa_14017110345 / Wa_14016945873

Jouni Högander jouni.hogander at intel.com
Tue Feb 14 08:36:50 UTC 2023


Bspec: 55378, 52890, 54369, 66624

Signed-off-by: Jouni Högander <jouni.hogander at intel.com>
---
 drivers/gpu/drm/i915/display/intel_cursor.c   |  26 +++-
 .../drm/i915/display/intel_display_types.h    |   2 +
 drivers/gpu/drm/i915/display/intel_psr.c      | 133 +++++++++++++++++-
 3 files changed, 155 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
index 902ca0fe3d2f..329a9834415c 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -496,24 +496,42 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_plane *plane,
 
 
 	intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), 0);
+
+	/*
+	 * Wa_14017110345
+	 * Wa_14016945873
+	 */
+	if (plane->cursor.wa_14016945873_allowed) {
+		intel_de_write_fw(dev_priv, CURCNTR(pipe), 0);
+		plane->cursor.needs_restore = true;
+	}
 }
 
 static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane,
 					     const struct intel_crtc_state *crtc_state,
 					     const struct intel_plane_state *plane_state)
 {
-	struct drm_i915_private *i915 = to_i915(plane->base.dev);
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum pipe pipe = plane->pipe;
 
 	if (!crtc_state->enable_psr2_sel_fetch)
 		return;
 
 
-	if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0)
-		intel_de_write_fw(i915, PLANE_SEL_FETCH_CTL(pipe, plane->id),
+	if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) {
+		intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id),
 				  plane_state->ctl);
-	else
+		/*
+		 * Wa_14017110345
+		 * Wa_14016945873
+		 */
+		if (plane->cursor.needs_restore) {
+			intel_de_write_fw(dev_priv, CURCNTR(pipe), plane->cursor.cntl);
+			plane->cursor.needs_restore = false;
+		}
+	} else {
 		i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state);
+	}
 }
 
 /* TODO: split into noarm+arm pair */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 9ccae7a46020..9659271461e3 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1451,6 +1451,8 @@ struct intel_plane {
 
 	struct {
 		u32 base, cntl, size;
+		/* Wa_14016945873 */
+		bool needs_restore, wa_14016945873_allowed;
 	} cursor;
 
 	struct intel_fbc *fbc;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 87a68f50e2ef..5f2abfde21a8 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1266,6 +1266,100 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
 	intel_psr_activate(intel_dp);
 }
 
+/*
+ * Wa_14017110345
+ * Wa_14016945873
+ */
+static void _wa_14016945873_cursor_restore(struct intel_crtc *intel_crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct intel_plane *intel_plane;
+
+	for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc,
+				     intel_plane) {
+		if (intel_plane->id != PLANE_CURSOR ||
+		    !intel_plane->cursor.needs_restore)
+			continue;
+
+		intel_de_write_fw(dev_priv, CURCNTR(intel_crtc->pipe),
+				  intel_plane->cursor.cntl);
+
+		intel_plane->cursor.needs_restore = false;
+	}
+}
+
+static void wa_14016945873_cursor_restore(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_crtc *intel_crtc;
+
+	for_each_intel_crtc(&dev_priv->drm, intel_crtc) {
+		if (intel_crtc->pipe != intel_dp->psr.pipe)
+			continue;
+
+		_wa_14016945873_cursor_restore(intel_crtc);
+	}
+}
+
+static void wa_14016945873_pre_planes(struct intel_crtc *intel_crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct intel_encoder *encoder;
+	struct intel_plane *intel_plane;
+
+	for_each_encoder_on_crtc(&dev_priv->drm, &intel_crtc->base, encoder) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+		u32 val;
+
+		if (!intel_encoder_can_psr(encoder))
+			continue;
+
+		val = intel_de_read(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder));
+		val &= ~EDP_PSR2_IDLE_FRAME_MASK;
+		intel_de_write_fw(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
+		val = intel_de_read(dev_priv, EDP_PSR2_STATUS(intel_dp->psr.transcoder));
+
+
+		if ((val & EDP_PSR2_STATUS_STATE_MASK) != EDP_PSR2_STATUS_STATE_DEEP_SLEEP)
+			continue;
+
+		_wa_14016945873_cursor_restore(intel_crtc);
+
+		for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc,
+					     intel_plane) {
+			if (intel_plane->id != PLANE_CURSOR)
+				continue;
+
+			intel_plane->cursor.wa_14016945873_allowed = false;
+		}
+	}
+}
+
+static void wa_14016945873_post_planes(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_crtc *intel_crtc;
+	struct intel_plane *intel_plane;
+	u32 val;
+
+	for_each_intel_crtc(&dev_priv->drm, intel_crtc) {
+		if (intel_crtc->pipe != intel_dp->psr.pipe)
+			continue;
+
+		for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc,
+					     intel_plane) {
+			if (intel_plane->id != PLANE_CURSOR)
+				continue;
+
+			intel_plane->cursor.wa_14016945873_allowed = true;
+		}
+	}
+
+	val = intel_de_read(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder));
+	val |= psr_compute_idle_frames(intel_dp) << EDP_PSR_IDLE_FRAME_SHIFT;
+	intel_de_write_fw(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
+}
+
 static void intel_psr_exit(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1287,6 +1381,12 @@ static void intel_psr_exit(struct intel_dp *intel_dp)
 
 	if (intel_dp->psr.psr2_enabled) {
 		tgl_disallow_dc3co_on_psr2_exit(intel_dp);
+
+		/*
+		 * Wa_14017110345
+		 * Wa_14016945873
+		 */
+		wa_14016945873_cursor_restore(intel_dp);
 		val = intel_de_read(dev_priv,
 				    EDP_PSR2_CTL(intel_dp->psr.transcoder));
 		drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR2_ENABLE));
@@ -1498,13 +1598,19 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
-	if (intel_dp->psr.psr2_sel_fetch_enabled)
+	if (intel_dp->psr.psr2_sel_fetch_enabled) {
+		/*
+		 * Wa_14017110345
+		 * Wa_14016945873
+		 */
+		wa_14016945873_cursor_restore(intel_dp);
 		intel_de_write(dev_priv,
 			       PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
 			       man_trk_ctl_enable_bit_get(dev_priv) |
 			       man_trk_ctl_partial_frame_bit_get(dev_priv) |
 			       man_trk_ctl_single_full_frame_bit_get(dev_priv) |
 			       man_trk_ctl_continuos_full_frame(dev_priv));
+	}
 
 	/*
 	 * Display WA #0884: skl+
@@ -1790,6 +1896,13 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
 			 */
 			if (drm_rect_height(&old_plane_state->psr2_sel_fetch_area) > 0)
 				crtc_state->update_planes |= BIT(plane->id);
+
+			/*
+			 * Wa_14017110345
+			 * Wa_14016945873
+			 */
+			if (plane->id == PLANE_CURSOR)
+				crtc_state->update_planes |= BIT(plane->id);
 			continue;
 		}
 
@@ -1822,6 +1935,13 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
 	}
 
 skip_sel_fetch_set_loop:
+	/*
+	 * Wa_14017110345
+	 * Wa_14016945873
+	 */
+	if (full_update)
+		crtc_state->update_planes |= BIT(PLANE_CURSOR);
+
 	psr2_man_trk_ctl_calc(crtc_state, &pipe_clip, full_update);
 	return 0;
 }
@@ -1847,6 +1967,8 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state,
 
 		mutex_lock(&psr->lock);
 
+		wa_14016945873_pre_planes(crtc);
+
 		/*
 		 * Reasons to disable:
 		 * - PSR disabled in new state
@@ -1887,7 +2009,9 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state,
 		drm_WARN_ON(&dev_priv->drm, psr->enabled && !crtc_state->active_planes);
 
 		/* Only enable if there is active planes */
-		if (!psr->enabled && crtc_state->active_planes)
+		if (psr->enabled)
+			wa_14016945873_post_planes(intel_dp);
+		else if (crtc_state->active_planes)
 			intel_psr_enable_locked(intel_dp, crtc_state);
 
 		/* Force a PSR exit when enabling CRC to avoid CRC timeouts */
@@ -2162,6 +2286,11 @@ static void _psr_invalidate_handle(struct intel_dp *intel_dp)
 			return;
 		}
 
+		/*
+		 * Wa_14017110345
+		 * Wa_14016945873
+		 */
+		wa_14016945873_cursor_restore(intel_dp);
 		val = man_trk_ctl_enable_bit_get(dev_priv) |
 		      man_trk_ctl_partial_frame_bit_get(dev_priv) |
 		      man_trk_ctl_continuos_full_frame(dev_priv);
-- 
2.34.1



More information about the Intel-gfx-trybot mailing list