]> www.infradead.org Git - users/hch/misc.git/commitdiff
drm/i915/psr: Underrun on idle PSR wa only when pkgc latency > delayed vblank
authorJouni Högander <jouni.hogander@intel.com>
Mon, 19 May 2025 07:52:23 +0000 (10:52 +0300)
committerJouni Högander <jouni.hogander@intel.com>
Wed, 20 Aug 2025 05:00:28 +0000 (08:00 +0300)
Underrun on idle PSR workaround (Wa_16025596647) is supposed to be
applied only when pkg c latency > delayed vblank. Currently we are
applying it always when other criterias are met.

Fix this by adding new boolean flag which is supposed to be set when
calculating watermark levels and pkgc latency > delayed vblank is
detected. currently this scenario is blocked but might be added
later. Due to this add also TODO comment into
skl_max_wm_level_for_vblank.

Bspec: 74151
Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Link: https://lore.kernel.org/r/20250519075223.443266-1-jouni.hogander@intel.com
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/display/skl_watermark.c

index 0d945d1fedd67b4fd30a5f9ef5fba9537d250664..fd9d2527889b482bf5db57abdff7f05737491d54 100644 (file)
@@ -1121,6 +1121,7 @@ struct intel_crtc_state {
        bool req_psr2_sdp_prior_scanline;
        bool has_panel_replay;
        bool wm_level_disabled;
+       bool pkg_c_latency_used;
        u32 dc3co_exitline;
        u16 su_y_granularity;
        u8 active_non_psr_pipes;
@@ -1683,6 +1684,7 @@ struct intel_psr {
        u8 entry_setup_frames;
 
        bool link_ok;
+       bool pkg_c_latency_used;
 
        u8 active_non_psr_pipes;
 };
index 8bea2b8188a71e80be07807ad68d43968c8fcf54..609df53f1ef1739fd614a8451c3a12d004a00601 100644 (file)
@@ -915,7 +915,7 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
        /* Wa_16025596647 */
        if ((DISPLAY_VER(display) == 20 ||
             IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
-           is_dc5_dc6_blocked(intel_dp))
+           is_dc5_dc6_blocked(intel_dp) && intel_dp->psr.pkg_c_latency_used)
                intel_dmc_start_pkgc_exit_at_start_of_undelayed_vblank(display,
                                                                       intel_dp->psr.pipe,
                                                                       true);
@@ -1005,7 +1005,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
        /* Wa_16025596647 */
        if ((DISPLAY_VER(display) == 20 ||
             IS_DISPLAY_VERx100_STEP(display, 3000, STEP_A0, STEP_B0)) &&
-           is_dc5_dc6_blocked(intel_dp))
+           is_dc5_dc6_blocked(intel_dp) && intel_dp->psr.pkg_c_latency_used)
                idle_frames = 0;
        else
                idle_frames = psr_compute_idle_frames(intel_dp);
@@ -2006,6 +2006,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
        intel_dp->psr.req_psr2_sdp_prior_scanline =
                crtc_state->req_psr2_sdp_prior_scanline;
        intel_dp->psr.active_non_psr_pipes = crtc_state->active_non_psr_pipes;
+       intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used;
 
        if (!psr_interrupt_error_check(intel_dp))
                return;
@@ -2186,6 +2187,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
        intel_dp->psr.su_region_et_enabled = false;
        intel_dp->psr.psr2_sel_fetch_cff_enabled = false;
        intel_dp->psr.active_non_psr_pipes = 0;
+       intel_dp->psr.pkg_c_latency_used = 0;
 }
 
 /**
@@ -3702,7 +3704,7 @@ static void intel_psr_apply_underrun_on_idle_wa_locked(struct intel_dp *intel_dp
        struct intel_display *display = to_intel_display(intel_dp);
        bool dc5_dc6_blocked;
 
-       if (!intel_dp->psr.active)
+       if (!intel_dp->psr.active || !intel_dp->psr.pkg_c_latency_used)
                return;
 
        dc5_dc6_blocked = is_dc5_dc6_blocked(intel_dp);
@@ -3727,7 +3729,8 @@ static void psr_dc5_dc6_wa_work(struct work_struct *work)
 
                mutex_lock(&intel_dp->psr.lock);
 
-               if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled)
+               if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled &&
+                   !intel_dp->psr.pkg_c_latency_used)
                        intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
 
                mutex_unlock(&intel_dp->psr.lock);
@@ -3805,7 +3808,8 @@ void intel_psr_notify_pipe_change(struct intel_atomic_state *state,
                        goto unlock;
 
                if ((enable && intel_dp->psr.active_non_psr_pipes) ||
-                   (!enable && !intel_dp->psr.active_non_psr_pipes)) {
+                   (!enable && !intel_dp->psr.active_non_psr_pipes) ||
+                   !intel_dp->psr.pkg_c_latency_used) {
                        intel_dp->psr.active_non_psr_pipes = active_non_psr_pipes;
                        goto unlock;
                }
@@ -3840,7 +3844,7 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
                        break;
                }
 
-               if (intel_dp->psr.enabled)
+               if (intel_dp->psr.enabled && intel_dp->psr.pkg_c_latency_used)
                        intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
 
                mutex_unlock(&intel_dp->psr.lock);
index def5150231a4c18c85df9f7f486ee72961239044..33885d619a97102596fbdaefc6dc4ad720e80cd2 100644 (file)
@@ -2272,6 +2272,11 @@ static int skl_max_wm0_lines(const struct intel_crtc_state *crtc_state)
        return wm0_lines;
 }
 
+/*
+ * TODO: In case we use PKG_C_LATENCY to allow C-states when the delayed vblank
+ * size is too small for the package C exit latency we need to notify PSR about
+ * the scenario to apply Wa_16025596647.
+ */
 static int skl_max_wm_level_for_vblank(struct intel_crtc_state *crtc_state,
                                       int wm0_lines)
 {