Commit 5f9172bf authored by Ankit Nautiyal's avatar Ankit Nautiyal
Browse files

drm/i915/vrr: Clamp guardband as per hardware and timing constraints



The maximum guardband value is constrained by two factors:
- The actual vblank length minus set context latency (SCL)
- The hardware register field width:
  - 8 bits for ICL/TGL (VRR_CTL_PIPELINE_FULL_MASK -> max 255)
  - 16 bits for ADL+ (XELPD_VRR_CTL_VRR_GUARDBAND_MASK -> max 65535)

Remove the #FIXME and clamp the guardband to the maximum allowed value.

v2:
- Use REG_FIELD_MAX(). (Ville)
- Separate out functions for intel_vrr_max_guardband(),
  intel_vrr_max_vblank_guardband(). (Ville)

v3:
- Fix Typo: Add the missing adjusted_mode->crtc_vdisplay in guardband
  computation. (Ville)
- Refactor intel_vrr_max_hw_guardband() and use else for consistency.
  (Ville)

v4:
- Drop max_guardband from intel_vrr_max_hw_guardband(). (Ville)

Signed-off-by: default avatarAnkit Nautiyal <ankit.k.nautiyal@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> (#v2)
Link: https://lore.kernel.org/r/20250924141542.3122126-9-ankit.k.nautiyal@intel.com
parent 94da8e5e
Loading
Loading
Loading
Loading
+35 −12
Original line number Diff line number Diff line
@@ -409,31 +409,54 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
	}
}

void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
static int
intel_vrr_max_hw_guardband(const struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(crtc_state);
	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
	int max_pipeline_full = REG_FIELD_MAX(VRR_CTL_PIPELINE_FULL_MASK);

	if (!intel_vrr_possible(crtc_state))
		return;
	if (DISPLAY_VER(display) >= 13)
		return REG_FIELD_MAX(XELPD_VRR_CTL_VRR_GUARDBAND_MASK);
	else
		return intel_vrr_pipeline_full_to_guardband(crtc_state,
							    max_pipeline_full);
}

	crtc_state->vrr.guardband =
		crtc_state->vrr.vmin -
static int
intel_vrr_max_vblank_guardband(const struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(crtc_state);
	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;

	return crtc_state->vrr.vmin -
	       adjusted_mode->crtc_vdisplay -
	       crtc_state->set_context_latency -
	       intel_vrr_extra_vblank_delay(display);
}

	if (DISPLAY_VER(display) < 13) {
		/* FIXME handle the limit in a proper way */
		crtc_state->vrr.guardband =
			min(crtc_state->vrr.guardband,
			    intel_vrr_pipeline_full_to_guardband(crtc_state, 255));
static int
intel_vrr_max_guardband(struct intel_crtc_state *crtc_state)
{
	return min(intel_vrr_max_hw_guardband(crtc_state),
		   intel_vrr_max_vblank_guardband(crtc_state));
}

void intel_vrr_compute_config_late(struct intel_crtc_state *crtc_state)
{
	struct intel_display *display = to_intel_display(crtc_state);
	const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;

	if (!intel_vrr_possible(crtc_state))
		return;

	crtc_state->vrr.guardband = min(crtc_state->vrr.vmin - adjusted_mode->crtc_vdisplay,
					intel_vrr_max_guardband(crtc_state));

	if (DISPLAY_VER(display) < 13)
		crtc_state->vrr.pipeline_full =
			intel_vrr_guardband_to_pipeline_full(crtc_state,
							     crtc_state->vrr.guardband);
}
}

static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state)
{