drm/i915/psr: Underrun on idle PSR wa only when pkgc latency > delayed vblank

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
pull/1354/merge
Jouni Högander 2025-05-19 10:52:23 +03:00
parent 0492e13eb8
commit 9b1795e9b0
3 changed files with 17 additions and 6 deletions

View 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;
};

View 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);

View 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)
{