public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
* [RFC PATCH] drm/i915/psr: Prevent DC entry during active vblank for Panel Replay
@ 2026-04-28 12:39 Dibin Moolakadan Subrahmanian
  2026-04-28 12:56 ` Hogander, Jouni
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-04-28 12:39 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: jouni.hogander

On PTL+ (display ver >= 30), hold the DMC wakelock while vblank is
enabled for Panel Replay. Older platforms rely on
intel_display_power_set_target_dc_state() for this.

The wakelock is acquired/released at two places:
1) Dynamically when vblank is enabled/disabled via
   intel_psr_notify_vblank_enable_disable().
2) In the PSR enable/disable path.

This handles the following ordering scenarios:
1) Panel Replay is enabled before vblank enable arrives.
2) Vblank enable arrives before Panel Replay is updated in
   intel_psr_post_plane_update().
---
 .../drm/i915/display/intel_display_types.h    |  2 +
 drivers/gpu/drm/i915/display/intel_psr.c      | 55 +++++++++++++++++--
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index c81916761850..f386d6dba9e5 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1775,6 +1775,8 @@ struct intel_psr {
 	bool source_panel_replay_support;
 	bool sink_panel_replay_support;
 	bool panel_replay_enabled;
+	bool panel_replay_wakelock;
+	bool vblank_enabled;
 	u32 dc3co_exitline;
 	u32 dc3co_exit_delay;
 	struct delayed_work dc3co_work;
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 63c19958a9e3..82bc63054906 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2192,6 +2192,34 @@ static bool psr_interrupt_error_check(struct intel_dp *intel_dp)
 	return true;
 }
 
+static void intel_panel_replay_get_wakelock_locked(struct intel_dp *intel_dp)
+{
+	struct intel_display *display = to_intel_display(intel_dp);
+
+	if (DISPLAY_VER(display) < 30)
+		return;
+
+	if (intel_dp->psr.panel_replay_wakelock)
+		return;
+
+	intel_dmc_wl_get_noreg(display);
+	intel_dp->psr.panel_replay_wakelock = true;
+}
+
+static void intel_panel_replay_put_wakelock_locked(struct intel_dp *intel_dp)
+{
+	struct intel_display *display = to_intel_display(intel_dp);
+
+	if (DISPLAY_VER(display) < 30)
+		return;
+
+	if (!intel_dp->psr.panel_replay_wakelock)
+		return;
+
+	intel_dmc_wl_put_noreg(display);
+	intel_dp->psr.panel_replay_wakelock = false;
+}
+
 static void intel_psr_enable_locked(struct intel_dp *intel_dp,
 				    const struct intel_crtc_state *crtc_state)
 {
@@ -2224,8 +2252,11 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
 	if (!psr_interrupt_error_check(intel_dp))
 		return;
 
-	if (intel_dp->psr.panel_replay_enabled)
+	if (intel_dp->psr.panel_replay_enabled) {
+		if (intel_dp->psr.vblank_enabled)
+			intel_panel_replay_get_wakelock_locked(intel_dp);
 		drm_dbg_kms(display->drm, "Enabling Panel Replay\n");
+	}
 	else
 		drm_dbg_kms(display->drm, "Enabling PSR%s\n",
 			    intel_dp->psr.sel_update_enabled ? "2" : "1");
@@ -2344,8 +2375,10 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
 	if (!intel_dp->psr.enabled)
 		return;
 
-	if (intel_dp->psr.panel_replay_enabled)
+	if (intel_dp->psr.panel_replay_enabled) {
+		intel_panel_replay_put_wakelock_locked(intel_dp);
 		drm_dbg_kms(display->drm, "Disabling Panel Replay\n");
+	}
 	else
 		drm_dbg_kms(display->drm, "Disabling PSR%s\n",
 			    intel_dp->psr.sel_update_enabled ? "2" : "1");
@@ -4143,9 +4176,24 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
 		mutex_lock(&intel_dp->psr.lock);
+		intel_dp->psr.vblank_enabled = enable;
 		if (intel_dp->psr.panel_replay_enabled) {
+			/*
+			 * wakelock handling for panel replay
+			 * for older platform rely on intel_display_power_set_target_dc_state().
+			 */
+			if (DISPLAY_VER(display) < 30) {
+				mutex_unlock(&intel_dp->psr.lock);
+				break;
+			}
+
+			if (enable)
+				intel_panel_replay_get_wakelock_locked(intel_dp);
+			else
+				intel_panel_replay_put_wakelock_locked(intel_dp);
+
 			mutex_unlock(&intel_dp->psr.lock);
-			break;
+			return;
 		}
 
 		if (intel_dp->psr.enabled && intel_dp->psr.pkg_c_latency_used)
@@ -4154,7 +4202,6 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
 		mutex_unlock(&intel_dp->psr.lock);
 		return;
 	}
-
 	/*
 	 * NOTE: intel_display_power_set_target_dc_state is used
 	 * only by PSR * code for DC3CO handling. DC3CO target
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-04-28 23:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 12:39 [RFC PATCH] drm/i915/psr: Prevent DC entry during active vblank for Panel Replay Dibin Moolakadan Subrahmanian
2026-04-28 12:56 ` Hogander, Jouni
2026-04-28 16:39   ` Dibin Moolakadan Subrahmanian
2026-04-28 14:43 ` ✓ i915.CI.BAT: success for " Patchwork
2026-04-28 23:56 ` ✓ i915.CI.Full: " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox