Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amd/display: Increase vblank offdelay for PSR panels

[Why]

Depending on when the HW latching event (vupdate) of double-buffered
registers happen relative to the PSR SDP (signals panel psr enter/exit)
deadline, and how bad the Panel clock has drifted since the last ALPM
off event, there can be up to 3 frames of delay between sending the PSR
exit cmd to DMUB fw, and when the panel starts displaying live frames.
This can manifest as micro-stuttering when userspace commit patterns
cause rapid toggling of the DRM vblank counter, since PSR enter/exit is
hooked up to DRM vblank disable/enable respectively.

In the ideal world, the panel should present the live frame immediately
on PSR exit cmd. But due to HW design and PSR limitations, immediate
exit can only happen by chance, when:

1. PSR exit cmd is ack'd by FW before HW latching (vupdate) event, and
2. Panel's SDP deadline -- determined by it's PSR Start Delay in DPCD
71h -- is after the vupdate event. The PSR exit SDP can then be sent
immediately after HW latches. Otherwise, we have to wait 1 frame. And
3. There is negligible drift between the panel's clock and source clock.
Otherwise, there can be up to 1 frame of drift.

Note that this delay is not expected with Panel Replay.

[How]

Since PSR power savings can be quite substantial, and there are a lot of
systems in the wild with PSR panels, It'll be nice to have a middle
ground that balances user experience with power savings.

A simple way to achieve this is by extending the vblank offdelay, such
that additional PSR exit delays will be less perceivable.

We can set:

20/100 * offdelay_ms = 3_frames_ms
=> offdelay_ms = 5 * 3_frames_ms

This ensures that `3_frames_ms` will only be experienced as a 20% delay
on top how long the panel has been static, and thus make the delay
less perceivable.

If this ends up being too high of a percentage, it can be dropped
further in a future change.

Fixes: 537ef0f88897 ("drm/amd/display: use new vblank enable policy for DCN35+")
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org

authored by

Leo Li and committed by
Alex Deucher
f21e6d14 5f054dde

+32 -7
+32 -7
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 8707 8707 int offdelay; 8708 8708 8709 8709 if (acrtc_state) { 8710 - if (amdgpu_ip_version(adev, DCE_HWIP, 0) < 8711 - IP_VERSION(3, 5, 0) || 8712 - acrtc_state->stream->link->psr_settings.psr_version < 8713 - DC_PSR_VERSION_UNSUPPORTED || 8714 - !(adev->flags & AMD_IS_APU)) { 8715 - timing = &acrtc_state->stream->timing; 8710 + timing = &acrtc_state->stream->timing; 8716 8711 8717 - /* at least 2 frames */ 8712 + /* 8713 + * Depending on when the HW latching event of double-buffered 8714 + * registers happen relative to the PSR SDP deadline, and how 8715 + * bad the Panel clock has drifted since the last ALPM off 8716 + * event, there can be up to 3 frames of delay between sending 8717 + * the PSR exit cmd to DMUB fw, and when the panel starts 8718 + * displaying live frames. 8719 + * 8720 + * We can set: 8721 + * 8722 + * 20/100 * offdelay_ms = 3_frames_ms 8723 + * => offdelay_ms = 5 * 3_frames_ms 8724 + * 8725 + * This ensures that `3_frames_ms` will only be experienced as a 8726 + * 20% delay on top how long the display has been static, and 8727 + * thus make the delay less perceivable. 8728 + */ 8729 + if (acrtc_state->stream->link->psr_settings.psr_version < 8730 + DC_PSR_VERSION_UNSUPPORTED) { 8731 + offdelay = DIV64_U64_ROUND_UP((u64)5 * 3 * 10 * 8732 + timing->v_total * 8733 + timing->h_total, 8734 + timing->pix_clk_100hz); 8735 + config.offdelay_ms = offdelay ?: 30; 8736 + } else if (amdgpu_ip_version(adev, DCE_HWIP, 0) < 8737 + IP_VERSION(3, 5, 0) || 8738 + !(adev->flags & AMD_IS_APU)) { 8739 + /* 8740 + * Older HW and DGPU have issues with instant off; 8741 + * use a 2 frame offdelay. 8742 + */ 8718 8743 offdelay = DIV64_U64_ROUND_UP((u64)20 * 8719 8744 timing->v_total * 8720 8745 timing->h_total,