From: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Cc: ville.syrjala@linux.intel.com, jani.nikula@linux.intel.com,
navaremanasi@google.com,
Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Subject: [PATCH 6/6] drm/i915/intel_panel: Refine VRR fixed mode selection for DRRS panels
Date: Tue, 12 May 2026 19:02:49 +0530 [thread overview]
Message-ID: <20260512133249.2475882-7-ankit.k.nautiyal@intel.com> (raw)
In-Reply-To: <20260512133249.2475882-1-ankit.k.nautiyal@intel.com>
There are two kinds of VRR panels with fixed modes to consider:
Type 1: Modes with different clocks (e.g. 60Hz @ 347MHz, 120Hz @ 695MHz)
For such panels, it is not possible to seamlessly switch from a lower RR
mode to a higher RR mode, since at lower clock we cannot increase the
clock without a full modeset. But seamless switch from 120Hz to 60Hz can
be achieved by running at the same (higher) clock and just extending the
vtotal.
Type 2: Modes with same clock but different vtotal
Here the clock is the same, so we can go from higher RR to lower RR or
vice versa just by changing the vtotal. Seamless switching is possible
in both directions.
The previous change makes intel_panel_fixed_mode() always return the
highest refresh rate mode for all VRR panels. This works well for Type 2
panels since there is no clock advantage from picking a lower mode.
However for Type 1 (seamless DRRS) panels, if the user sets the
allow_modeset flag they really want a lower RR mode with a lower clock
to save power. So avoid selecting the highest RR mode when allow_modeset
is set for such panels.
Also, for seamless DRRS panels on platforms with double-buffered M/N
support, the clock can be changed on the fly, so we don't need the
highest RR + vtotal adjustment approach.
To understand the user requirement for full modeset/seamless switch, add
a nullable struct drm_atomic_commit state parameter to
intel_panel_fixed_mode() to check the allow_modeset flag.
Note: The mode_valid callers pass NULL since they have no atomic state.
In that case use the existing approach to select the closest-match to
avoid pruning valid modes.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
---
drivers/gpu/drm/i915/display/intel_panel.c | 35 ++++++++++++++++++----
drivers/gpu/drm/i915/display/intel_panel.h | 3 +-
drivers/gpu/drm/i915/display/intel_sdvo.c | 5 ++--
3 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 1c2a8cd454be..cc228ff81510 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -72,8 +72,10 @@ static bool is_best_fixed_mode(int vrefresh, int fixed_mode_vrefresh,
}
static bool need_higher_rr_mode(struct intel_connector *connector,
- const struct drm_display_mode *mode)
+ const struct drm_display_mode *mode,
+ const struct drm_atomic_commit *state)
{
+ struct intel_display *display = to_intel_display(connector);
int vrefresh = drm_mode_vrefresh(mode);
if (!intel_vrr_is_capable(connector))
@@ -82,12 +84,33 @@ static bool need_higher_rr_mode(struct intel_connector *connector,
if (!intel_vrr_is_in_range(connector, vrefresh))
return false;
- return true;
+ if (!state)
+ return false;
+
+ /*
+ * If Seamless switch requested, use highest RR mode + vtotal
+ * adjustment, unless DRRS with double-buffered M/N which
+ * can change the clock on the fly.
+ */
+ if (!state->allow_modeset) {
+ if (intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS &&
+ HAS_DOUBLE_BUFFERED_M_N(display))
+ return false;
+ return true;
+ }
+
+ /*
+ * If full modeset is allowed, then for DRRS panels, use nearest mode
+ * (lower clock saves power). For non-DRRS VRR panels, use highest RR
+ * mode (no clock advantage from picking a lower mode).
+ */
+ return intel_panel_drrs_type(connector) != DRRS_TYPE_SEAMLESS;
}
const struct drm_display_mode *
intel_panel_fixed_mode(struct intel_connector *connector,
- const struct drm_display_mode *mode)
+ const struct drm_display_mode *mode,
+ const struct drm_atomic_commit *state)
{
const struct drm_display_mode *fixed_mode, *best_mode = NULL;
int vrefresh = drm_mode_vrefresh(mode);
@@ -97,7 +120,7 @@ intel_panel_fixed_mode(struct intel_connector *connector,
* which we can then reduce to match the requested
* vrefresh by extending the vblank length.
*/
- if (need_higher_rr_mode(connector, mode))
+ if (need_higher_rr_mode(connector, mode, state))
return intel_panel_highest_vrefresh_mode(connector);
list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
@@ -229,7 +252,7 @@ int intel_panel_compute_config(struct intel_connector *connector,
{
struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
const struct drm_display_mode *fixed_mode =
- intel_panel_fixed_mode(connector, adjusted_mode);
+ intel_panel_fixed_mode(connector, adjusted_mode, state);
int vrefresh, fixed_mode_vrefresh;
bool is_vrr;
@@ -435,7 +458,7 @@ intel_panel_mode_valid(struct intel_connector *connector,
int *target_clock)
{
const struct drm_display_mode *fixed_mode =
- intel_panel_fixed_mode(connector, mode);
+ intel_panel_fixed_mode(connector, mode, NULL);
if (target_clock)
*target_clock = mode->clock;
diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h
index 3c4ff6735c21..c44323918768 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.h
+++ b/drivers/gpu/drm/i915/display/intel_panel.h
@@ -33,7 +33,8 @@ const struct drm_display_mode *
intel_panel_preferred_fixed_mode(struct intel_connector *connector);
const struct drm_display_mode *
intel_panel_fixed_mode(struct intel_connector *connector,
- const struct drm_display_mode *mode);
+ const struct drm_display_mode *mode,
+ const struct drm_atomic_commit *state);
const struct drm_display_mode *
intel_panel_downclock_mode(struct intel_connector *connector,
const struct drm_display_mode *adjusted_mode);
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index e11c1dfc602a..0574a027526a 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -797,7 +797,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
if (IS_LVDS(intel_sdvo_connector)) {
const struct drm_display_mode *fixed_mode =
-intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
+ intel_panel_fixed_mode(&intel_sdvo_connector->base, mode, NULL);
if (fixed_mode->hdisplay != args.width ||
fixed_mode->vdisplay != args.height)
@@ -1564,7 +1564,8 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state,
/* lvds has a special fixed output timing. */
if (IS_LVDS(intel_sdvo_connector)) {
const struct drm_display_mode *fixed_mode =
- intel_panel_fixed_mode(&intel_sdvo_connector->base, mode);
+ intel_panel_fixed_mode(&intel_sdvo_connector->base,
+ mode, conn_state->state);
intel_sdvo_get_dtd_from_mode(&output_dtd, fixed_mode);
} else {
--
2.45.2
next prev parent reply other threads:[~2026-05-12 13:47 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 13:32 [PATCH 0/6] drm/i915/intel_panel: Fix seamless VRR mode switching for DRRS panels Ankit Nautiyal
2026-05-12 13:32 ` [PATCH 1/6] drm/i915/display: Deprecate TRANS_VSYNC where VRR TG is always on Ankit Nautiyal
2026-05-19 14:56 ` Ville Syrjälä
2026-05-12 13:32 ` [PATCH 2/6] drm/i915/panel: Preserve Vtotal-Vsync distance while adjusting vtotal Ankit Nautiyal
2026-05-12 13:32 ` [PATCH 3/6] drm/i915/intel_panel: Add a helper to get the highest refresh rate mode Ankit Nautiyal
2026-05-12 13:32 ` [PATCH 4/6] drm/i915/intel_panel: Pass crtc_state to intel_panel_compute_config Ankit Nautiyal
2026-05-12 13:32 ` [PATCH 5/6] drm/i915/intel_panel: Use highest refresh rate mode for VRR panels Ankit Nautiyal
2026-05-12 13:32 ` Ankit Nautiyal [this message]
2026-05-12 22:21 ` ✗ CI.checkpatch: warning for drm/i915/intel_panel: Fix seamless VRR mode switching for DRRS panels (rev2) Patchwork
2026-05-12 22:22 ` ✓ CI.KUnit: success " Patchwork
2026-05-12 23:43 ` ✓ Xe.CI.BAT: " Patchwork
2026-05-13 16:21 ` ✗ Xe.CI.FULL: failure " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2026-05-22 13:25 [PATCH 0/6] drm/i915/intel_panel: Fix seamless VRR mode switching for DRRS panels Ankit Nautiyal
2026-05-22 13:25 ` [PATCH 6/6] drm/i915/intel_panel: Refine VRR fixed mode selection " Ankit Nautiyal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260512133249.2475882-7-ankit.k.nautiyal@intel.com \
--to=ankit.k.nautiyal@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
--cc=navaremanasi@google.com \
--cc=ville.syrjala@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).