[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