[PATCH 5/7] drm/i915/display: Allow PSR1 and seamless DRRS together

José Roberto de Souza jose.souza at intel.com
Thu Apr 28 14:16:59 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>
---
 .../gpu/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         | 15 +++++++++++++++
 drivers/gpu/drm/i915/display/intel_frontbuffer.c  |  2 +-
 4 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 784691e98b4c7..15c4b3ff72914 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1315,6 +1315,7 @@ struct intel_crtc {
 		unsigned int busy_frontbuffer_bits;
 		enum transcoder cpu_transcoder;
 		struct intel_link_m_n m_n, m2_n2;
+		bool psr_enabled;
 
 		/* Only used to verify if programmed state matches */
 		unsigned int seamless_mode_switch_pixel_rate;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index d7d045bdf77af..58f56250b1663 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1843,12 +1843,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 8bea23c2fc35c..f920e13450ee1 100644
--- a/drivers/gpu/drm/i915/display/intel_drrs.c
+++ b/drivers/gpu/drm/i915/display/intel_drrs.c
@@ -163,6 +163,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);
 
@@ -197,6 +198,7 @@ void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state)
 	crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
 	crtc->drrs.frontbuffer_bits = 0;
 	crtc->drrs.busy_frontbuffer_bits = 0;
+	crtc->drrs.psr_enabled = false;
 
 	mutex_unlock(&crtc->drrs.mutex);
 
@@ -209,9 +211,22 @@ static void intel_drrs_downclock_work(struct work_struct *work)
 
 	mutex_lock(&crtc->drrs.mutex);
 
+	/*
+	 * 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