Re: [PATCH 22/23] drm/i915/dp: Compute and include coasting vtotal for AS SDP

Nautiyal, Ankit K
2026-04-07T10:55:08Z

On 4/2/2026 4:40 PM, Ville Syrjälä wrote:
> On Thu, Apr 02, 2026 at 01:34:22PM +0530, 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.
>>
>> Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
>> ---
>> 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 a0e7ef2574b2..747dd3112d66 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -4914,7 +4914,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 902c09e0780f..de6f88a5400d 100644
>> --- a/drivers/gpu/drm/i915/display/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
>> @@ -5123,6 +5123,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;
>> }
>>
>> @@ -5306,6 +5309,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;
>> }
>> @@ -7383,6 +7387,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;
> Seems reasonable.
>
> Is this always under our control or could the hardware overwrite
> this with the current vtotal at the time of PR entry? Assuming
> we can enter PR before the vtotal goes back to vmax on its own
> anyway.

What I understand from Bspec in this regard is:

Do not write Adaptive Sync SDP Transmission Disable in PR Active State
i.e. DB[2], instead use PR_ALPM_CTL[ AS SDP Transmission in Active
Disable ] bit.

HW will sample the PR_ALPM_CTL bit only when PR is active, and it will
get reflected in AS SDP payload in an 'appropriate' time.

HW will ignore this bit when PR is Inactive and always send AS SDP.

So I think HW will not touch the coasting vtotal DBs.

Driver should set appropriate coasting Vtotal and set the PR_ALPM_CTL[AS
SDP Transmission in Active disable] bit.

During PR active Driver will set the DB[2] bit in payload which will
trigger the sink to use Coasting Vtotal.

(Unless we start writing : DPCD 00B1[0] ie.
PANEL_REPLAY_CONFIG2[PANEL_REPLAY_SINK_REFRESH_RATE_UNLOCK_GRANTED], in
which sink starts using its own logic).

Regards,

Ankit

>
>> }
>>
>> static
>> --
>> 2.45.2