Commit e00eb31a authored by Ankit Nautiyal's avatar Ankit Nautiyal
Browse files

drm/i915/psr: Consider SCL lines when validating vblank for wake latency



Panel Replay and PSR2 selective update require sufficient vblank duration
to accommodate wake latencies. However, the current
wake_lines_fit_into_vblank() logic does not account for the minimum
Set Context Latency (SCL) lines.

Separate out _intel_psr_min_set_context_latency() to compute the minimum
SCL requirement based on platform and feature usage.

The alpm_config_valid() helper is updated to pass the necessary context for
determining whether Panel Replay or PSR2 selective update is enabled.

v2: While calling alpm_config_valid() for selective_update use false flag
    instead of has_panel_replay. (Jouni)
v3: Correct ordering of the panel_replay, sel_update flags. (Jouni)

Signed-off-by: default avatarAnkit Nautiyal <ankit.k.nautiyal@intel.com>
Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: default avatarJouni Högander <jouni.hogander@intel.com>
Link: https://lore.kernel.org/r/20251016055415.2101347-6-ankit.k.nautiyal@intel.com
parent ca4edafa
Loading
Loading
Loading
Loading
+61 −41
Original line number Diff line number Diff line
@@ -1361,14 +1361,64 @@ static int intel_psr_entry_setup_frames(struct intel_dp *intel_dp,
	return entry_setup_frames;
}

static
int _intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state,
				       bool needs_panel_replay,
				       bool needs_sel_update)
{
	struct intel_display *display = to_intel_display(crtc_state);

	if (!crtc_state->has_psr)
		return 0;

	/* Wa_14015401596 */
	if (intel_vrr_possible(crtc_state) && IS_DISPLAY_VER(display, 13, 14))
		return 1;

	/* Rest is for SRD_STATUS needed on LunarLake and onwards */
	if (DISPLAY_VER(display) < 20)
		return 0;

	/*
	 * Comment on SRD_STATUS register in Bspec for LunarLake and onwards:
	 *
	 * To deterministically capture the transition of the state machine
	 * going from SRDOFFACK to IDLE, the delayed V. Blank should be at least
	 * one line after the non-delayed V. Blank.
	 *
	 * Legacy TG: TRANS_SET_CONTEXT_LATENCY > 0
	 * VRR TG: TRANS_VRR_CTL[ VRR Guardband ] < (TRANS_VRR_VMAX[ VRR Vmax ]
	 * - TRANS_VTOTAL[ Vertical Active ])
	 *
	 * SRD_STATUS is used only by PSR1 on PantherLake.
	 * SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake.
	 */

	if (DISPLAY_VER(display) >= 30 && (needs_panel_replay ||
					   needs_sel_update))
		return 0;
	else if (DISPLAY_VER(display) < 30 && (needs_sel_update ||
					       intel_crtc_has_type(crtc_state,
								   INTEL_OUTPUT_EDP)))
		return 0;
	else
		return 1;
}

static bool wake_lines_fit_into_vblank(struct intel_dp *intel_dp,
				       const struct intel_crtc_state *crtc_state,
				       bool aux_less)
				       bool aux_less,
				       bool needs_panel_replay,
				       bool needs_sel_update)
{
	struct intel_display *display = to_intel_display(intel_dp);
	int vblank = crtc_state->hw.adjusted_mode.crtc_vblank_end -
		crtc_state->hw.adjusted_mode.crtc_vblank_start;
	int wake_lines;
	int scl = _intel_psr_min_set_context_latency(crtc_state,
						     needs_panel_replay,
						     needs_sel_update);
	vblank -= scl;

	if (aux_less)
		wake_lines = crtc_state->alpm_state.aux_less_wake_lines;
@@ -1390,7 +1440,9 @@ static bool wake_lines_fit_into_vblank(struct intel_dp *intel_dp,

static bool alpm_config_valid(struct intel_dp *intel_dp,
			      struct intel_crtc_state *crtc_state,
			      bool aux_less)
			      bool aux_less,
			      bool needs_panel_replay,
			      bool needs_sel_update)
{
	struct intel_display *display = to_intel_display(intel_dp);

@@ -1400,7 +1452,8 @@ static bool alpm_config_valid(struct intel_dp *intel_dp,
		return false;
	}

	if (!wake_lines_fit_into_vblank(intel_dp, crtc_state, aux_less)) {
	if (!wake_lines_fit_into_vblank(intel_dp, crtc_state, aux_less,
					needs_panel_replay, needs_sel_update)) {
		drm_dbg_kms(display->drm,
			    "PSR2/Panel Replay not enabled, too short vblank time\n");
		return false;
@@ -1492,7 +1545,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
		return false;
	}

	if (!alpm_config_valid(intel_dp, crtc_state, false))
	if (!alpm_config_valid(intel_dp, crtc_state, false, false, true))
		return false;

	if (!crtc_state->enable_psr2_sel_fetch &&
@@ -1643,7 +1696,7 @@ _panel_replay_compute_config(struct intel_dp *intel_dp,
		return false;
	}

	if (!alpm_config_valid(intel_dp, crtc_state, true))
	if (!alpm_config_valid(intel_dp, crtc_state, true, true, false))
		return false;

	return true;
@@ -2371,43 +2424,10 @@ void intel_psr_trigger_frame_change_event(struct intel_dsb *dsb,
 */
int intel_psr_min_set_context_latency(const struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(crtc_state);

	if (!crtc_state->has_psr)
		return 0;

	/* Wa_14015401596 */
	if (intel_vrr_possible(crtc_state) && IS_DISPLAY_VER(display, 13, 14))
		return 1;

	/* Rest is for SRD_STATUS needed on LunarLake and onwards */
	if (DISPLAY_VER(display) < 20)
		return 0;

	/*
	 * Comment on SRD_STATUS register in Bspec for LunarLake and onwards:
	 *
	 * To deterministically capture the transition of the state machine
	 * going from SRDOFFACK to IDLE, the delayed V. Blank should be at least
	 * one line after the non-delayed V. Blank.
	 *
	 * Legacy TG: TRANS_SET_CONTEXT_LATENCY > 0
	 * VRR TG: TRANS_VRR_CTL[ VRR Guardband ] < (TRANS_VRR_VMAX[ VRR Vmax ]
	 * - TRANS_VTOTAL[ Vertical Active ])
	 *
	 * SRD_STATUS is used only by PSR1 on PantherLake.
	 * SRD_STATUS is used by PSR1 and Panel Replay DP on LunarLake.
	 */

	if (DISPLAY_VER(display) >= 30 && (crtc_state->has_panel_replay ||
					   crtc_state->has_sel_update))
		return 0;
	else if (DISPLAY_VER(display) < 30 && (crtc_state->has_sel_update ||
					       intel_crtc_has_type(crtc_state,
								   INTEL_OUTPUT_EDP)))
		return 0;
	else
		return 1;
	return _intel_psr_min_set_context_latency(crtc_state,
						  crtc_state->has_panel_replay,
						  crtc_state->has_sel_update);
}

static u32 man_trk_ctl_enable_bit_get(struct intel_display *display)