[PATCH 7/9] drm/i915/display: Allow PSR1 and seamless DRRS together
José Roberto de Souza
jose.souza at intel.com
Tue Apr 26 18:34:49 UTC 2022
There is nothing in specification preventing it at least
in display 9+ specification.
As PSR is only supported in display 9 we can enable both features
together.
But testing PSR2 + DRRS has shown issues with panel reporting
DP_PSR_LINK_CRC_ERROR error, so for now only enabling PSR1 with DRRS.
This will only bring an actual additional power-savings when
user-space is using seamless mode switch, otherwise at every flip
or frontbuffer write DRRS will go to high refresh mode and will
consume the same as PSR alone.
Just to avoid any pontential issue, here also calling
intel_drrs_invalidate() before intel_psr_invalidate() to not
switch refresh rate in the middle of PSR internal hardware sequences
and also to follow the drrs/psr_flush() order.
Cc: Sean Paul <seanpaul at chromium.org>
Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
Signed-off-by: José Roberto de Souza <jose.souza at intel.com>
---
.../drm/i915/display/intel_display_types.h | 1 +
drivers/gpu/drm/i915/display/intel_dp.c | 9 ++++----
drivers/gpu/drm/i915/display/intel_drrs.c | 21 +++++++++++++++++--
.../gpu/drm/i915/display/intel_frontbuffer.c | 2 +-
4 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 377d2231c6182..3cc8f5c834fbc 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1317,6 +1317,7 @@ struct intel_crtc {
enum transcoder cpu_transcoder;
struct intel_link_m_n m_n, m2_n2;
bool seamless_mode_switch_enabled;
+ bool psr_enabled;
} drrs;
int scanline_offset;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index c3301e1797100..e644cbf7e623d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1844,12 +1844,11 @@ static bool can_enable_drrs(struct intel_connector *connector,
return false;
/*
- * DRRS and PSR can't be enable together, so giving preference to PSR
- * as it allows more power-savings by complete shutting down display,
- * so to guarantee this, intel_drrs_compute_config() must be called
- * after intel_psr_compute_config().
+ * Specification don't have any restrictions about DRRS + PSR1 or PSR2
+ * but enabling DRRS with PSR2 causes DP_PSR_LINK_CRC_ERROR errors in
+ * panel side so for now only allowing DRRS + PSR1.
*/
- if (pipe_config->has_psr)
+ if (pipe_config->has_psr2)
return false;
/* FIXME missing FDI M2/N2 etc. */
diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c
index 748303556cb0a..cca32ea9d8328 100644
--- a/drivers/gpu/drm/i915/display/intel_drrs.c
+++ b/drivers/gpu/drm/i915/display/intel_drrs.c
@@ -177,6 +177,7 @@ void intel_drrs_activate(const struct intel_crtc_state *crtc_state)
crtc->drrs.m2_n2 = crtc_state->dp_m2_n2;
crtc->drrs.frontbuffer_bits = intel_drrs_frontbuffer_bits(crtc_state);
crtc->drrs.busy_frontbuffer_bits = 0;
+ crtc->drrs.psr_enabled = crtc_state->has_psr;
intel_drrs_schedule_work(crtc);
unlock:
@@ -222,6 +223,7 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state,
crtc->drrs.frontbuffer_bits = 0;
crtc->drrs.busy_frontbuffer_bits = 0;
crtc->drrs.seamless_mode_switch_enabled = false;
+ crtc->drrs.psr_enabled = false;
unlock:
mutex_unlock(&crtc->drrs.mutex);
@@ -235,10 +237,25 @@ static void intel_drrs_downclock_work(struct work_struct *work)
mutex_lock(&crtc->drrs.mutex);
- if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits &&
- !crtc->drrs.seamless_mode_switch_enabled)
+ if (crtc->drrs.seamless_mode_switch_enabled)
+ goto unlock;
+
+ /*
+ * When PSR+DRRS is enabled and seamless_mode_switch_enabled is not set,
+ * the DRRS downclock mode switch will only cause hardware to leave
+ * DC5/6(because of the write into display registers).
+ *
+ * There is only loss in power-savings in this case as after 1 second
+ * of display idleness PSR will already be active and would have turned
+ * link off, so here skipping the switch to low rate.
+ */
+ if (crtc->drrs.psr_enabled)
+ goto unlock;
+
+ if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits)
intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW);
+unlock:
mutex_unlock(&crtc->drrs.mutex);
}
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 791248f812aa7..a69c28549b7a4 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -179,8 +179,8 @@ void __intel_fb_invalidate(struct intel_frontbuffer *front,
trace_intel_frontbuffer_invalidate(frontbuffer_bits, origin);
might_sleep();
- intel_psr_invalidate(i915, frontbuffer_bits, origin);
intel_drrs_invalidate(i915, frontbuffer_bits);
+ intel_psr_invalidate(i915, frontbuffer_bits, origin);
intel_fbc_invalidate(i915, frontbuffer_bits, origin);
}
--
2.36.0
More information about the Intel-gfx-trybot
mailing list