On 5/18/2026 9:25 AM, Ankit Nautiyal wrote:
DP v2.1 allows the source to temporarily suspend Adaptive-Sync SDP
transmission while Panel Replay is active when the sink supports
asynchronous video timing.

In such cases, the sink relies on the last transmitted AS SDP timing
information to maintain the refresh rate. To support this behavior,
compute and populate the coasting vtotal field in the AS SDP payload.

Include coasting vtotal in AS SDP packing, unpacking, and comparison,
and set it during late AS SDP configuration for PR with Aux-less ALPM
when asynchronous video timing is supported.

Note:
The coasting vtotal value is fully under driver control i.e. the HW does
not overwrite these payload bytes. HW only samples the PR_ALPM_CTL[AS SDP
Transmission in Active Disable] bit during PR active state and reflects it
in the AS SDP payload at the appropriate time.

Signed-off-by: Ankit Nautiyal <[email protected]>
Reviewed-by: Ville Syrjälä <[email protected]>
---
  drivers/gpu/drm/i915/display/intel_display.c |  3 ++-
  drivers/gpu/drm/i915/display/intel_dp.c      | 19 +++++++++++++++++++
  2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 757a78c75bbf..043d1c667379 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -4889,7 +4889,8 @@ intel_compare_dp_as_sdp(const struct drm_dp_as_sdp *a,
                a->duration_incr_ms == b->duration_incr_ms &&
                a->duration_decr_ms == b->duration_decr_ms &&
                a->target_rr_divider == b->target_rr_divider &&
-               a->mode == b->mode;
+               a->mode == b->mode &&
+               a->coasting_vtotal == b->coasting_vtotal;
  }
static bool
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index c1c6f394eb0b..69eb474fede7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5181,6 +5181,9 @@ static ssize_t intel_dp_as_sdp_pack(const struct 
drm_dp_as_sdp *as_sdp,
        if (as_sdp->target_rr_divider)
                sdp->db[4] |= 0x20;
+ sdp->db[7] = as_sdp->coasting_vtotal & 0xFF;
+       sdp->db[8] = (as_sdp->coasting_vtotal >> 8) & 0xFF;
+
        return length;
  }
@@ -5365,6 +5368,7 @@ int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp,
        as_sdp->vtotal = (sdp->db[2] << 8) | sdp->db[1];
        as_sdp->target_rr = ((sdp->db[4] & 0x3) << 8) | sdp->db[3];
        as_sdp->target_rr_divider = sdp->db[4] & 0x20 ? true : false;
+       as_sdp->coasting_vtotal = (sdp->db[8] << 8) | sdp->db[7];
return 0;
  }
@@ -7471,6 +7475,21 @@ void intel_dp_as_sdp_compute_config_late(struct intel_dp 
*intel_dp,
        } else {
                as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL;
        }
+
+       /*
+        * For Panel Replay with Async Video Timing support, the source can
+        * disable sending the AS SDP during PR Active state. In that case,
+        * the sink needs the coasting vtotal value to maintain the refresh
+        * rate.
+        *
+        * #TODO:
+        * If we ever advertise support for coasting at other refresh targets,
+        * this logic could be revisited. For now, use the minimum refresh rate
+        * as the only safe coasting value.
+        */
+       if (intel_alpm_is_alpm_aux_less(intel_dp, crtc_state) &&
+           intel_psr_pr_async_video_timing_supported(intel_dp))
+               as_sdp->coasting_vtotal = crtc_state->vrr.vmax;

As suggested in previous patch, I will drop the condition and always populate coasting_vtotal with vrr.vmax for now.

Regards,
Ankit


  }
static

Reply via email to