From: Uma Shankar <uma.shankar@intel.com>
To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Cc: animesh.manna@intel.com, dibin.moolakadan.subrahmanian@intel.com,
Uma Shankar <uma.shankar@intel.com>
Subject: [PATCH 1/2] drm/i915/display: Enable AS SDP Skip Frames
Date: Tue, 4 Aug 2026 00:23:04 +0530 [thread overview]
Message-ID: <20260803185305.562609-2-uma.shankar@intel.com> (raw)
In-Reply-To: <20260803185305.562609-1-uma.shankar@intel.com>
When Panel Replay is active the transcoder timing generator runs at the
panel's maximum refresh rate, but content is often presented at a lower
rate. In that case the Adaptive-Sync SDP (AS SDP) only needs to reach the
panel often enough to satisfy its maximum frame time, so transmitting it
on every frame is redundant and shows up as repeated SDPs on the link.
Xe3LPD adds a HW skip-frame counter in PR_ALPM_CTL that lets the source
send a single AS SDP and then suppress it for a programmed number of
frames. Program this counter so that one AS SDP is followed by
(max_vrefresh / flip_rate - 1) idle frames, matching the effective
content rate and allowing the link to be driven down to as low as 1Hz
when the hardware supports it.
The maximum refresh rate is taken from the current mode's vertical
refresh (adjusted_mode), while the actual flip/content rate is derived
from the CMRR target (force_cmrr numerator in milli-Hz over the 1000 or
1001 denominator). If no CMRR target is programmed the skip counter is
left at zero, i.e. the feature is a no-op and AS SDP continues to be sent
on every frame.
ToDo: Currently using CMRR debugfs as an interface to get the flip rate
from userspace, this will be extended to a property interface to receive
actual content fps as follow up.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Uma Shankar <uma.shankar@intel.com>
---
drivers/gpu/drm/i915/display/intel_alpm.c | 45 +++++++++++++++++++
drivers/gpu/drm/i915/display/intel_psr_regs.h | 2 +
2 files changed, 47 insertions(+)
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index f1383764b702..0f98f02a1848 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -375,6 +375,46 @@ static u32 get_pr_alpm_as_sdp_transmission_time(const struct intel_crtc_state *c
}
}
+/*
+ * Periodic Adaptive-Sync SDP skip frames.
+ *
+ * While Panel Replay is active the transcoder timing generator runs at the
+ * panel's maximum refresh rate, but content may be presented at a lower rate.
+ * The Adaptive-Sync SDP only needs to reach the panel often enough to satisfy
+ * its maximum frame time, so transmitting it on every frame is unnecessary and
+ * shows up as repeated SDPs on the link. Program the HW skip counter so that a
+ * single AS SDP is followed by (max_vrefresh / flip_vrefresh - 1) idle frames,
+ * matching the effective content rate.
+ *
+ * ToDo: Actual flip rate is currently passed on by userspace through debugfs
+ * create for CMRRR, but will be extended later as a property interface.
+ */
+static u32 intel_pr_as_sdp_skip_frames(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ int max_vrefresh = drm_mode_vrefresh(&crtc_state->hw.adjusted_mode);
+ int flip_vrefresh;
+ u32 skip_frames;
+
+ /*
+ * Actual (flip) refresh rate comes from the CMRR target: numerator is
+ * in milli-Hz, denominator is 1000 (1:1) or 1001 (1000/1001 timing).
+ */
+ if (!crtc->force_cmrr.numerator || !crtc->force_cmrr.denominator)
+ return 0;
+
+ flip_vrefresh = DIV_ROUND_CLOSEST(crtc->force_cmrr.numerator,
+ crtc->force_cmrr.denominator);
+
+ if (max_vrefresh <= 0 || flip_vrefresh <= 0 || max_vrefresh <= flip_vrefresh)
+ return 0;
+
+ skip_frames = max_vrefresh / flip_vrefresh - 1;
+
+ return min_t(u32, skip_frames,
+ REG_FIELD_MAX(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK));
+}
+
static void lnl_alpm_configure(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
@@ -410,6 +450,11 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp,
else
pr_alpm_ctl &= ~PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL;
+ /* AS SDP skip frames field only exists on Xe3LPD+ */
+ if (DISPLAY_VER(display) >= 35)
+ pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(
+ intel_pr_as_sdp_skip_frames(crtc_state));
+
intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder),
pr_alpm_ctl);
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h
index 16a9e3af198d..bb577e7e3bbd 100644
--- a/drivers/gpu/drm/i915/display/intel_psr_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h
@@ -276,6 +276,8 @@
#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 0)
#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 1)
#define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 2)
+#define PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK REG_GENMASK(27, 16)
+#define PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(frames) REG_FIELD_PREP(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK, (frames))
#define _ALPM_CTL_A 0x60950
#define ALPM_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL_A)
--
2.50.1
next prev parent reply other threads:[~2026-08-03 18:33 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-03 18:53 [PATCH 0/2] drm/i915/display: Enable AS SDP Skip Frames Uma Shankar
2026-08-03 18:39 ` ✗ CI.checkpatch: warning for drm/i915/display: Enable AS SDP Skip Frames (rev2) Patchwork
2026-08-03 18:40 ` ✓ CI.KUnit: success " Patchwork
2026-08-03 18:53 ` Uma Shankar [this message]
2026-08-03 18:53 ` [PATCH 2/2] drm/i915/display: Keep AS SDP flowing when skip frames is enabled Uma Shankar
2026-08-04 7:21 ` Dibin Moolakadan Subrahmanian
2026-08-04 7:50 ` Shankar, Uma
2026-08-03 21:25 ` ✓ Xe.CI.FULL: success for drm/i915/display: Enable AS SDP Skip Frames (rev2) Patchwork
2026-08-04 12:03 ` ✗ CI.checkpatch: warning " Patchwork
2026-08-04 12:05 ` ✓ CI.KUnit: success " Patchwork
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=20260803185305.562609-2-uma.shankar@intel.com \
--to=uma.shankar@intel.com \
--cc=animesh.manna@intel.com \
--cc=dibin.moolakadan.subrahmanian@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
/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