summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAric Cyr <Aric.Cyr@amd.com>2026-09-18 18:37:43 -0400
committerAlex Deucher <alexander.deucher@amd.com>2026-10-07 12:06:01 -0400
commitd07fc866c52dc759d823ecdbb026306c1273434c (patch)
tree36d155ba0b2ee73b783e0fc68810c58e7db8c1de
parente69156294e47185ba96f879d6ddf9d092a61b74d (diff)
drm/amd/display: only reprogram DRR when v_total values change
[Why] dc_stream_adjust_vmin_vmax() programmed the OTG on every call. FreeSync BTR calls it once per vblank, so identical v_total values were rewritten every frame, each one paying dc_exit_ips_for_hw_access() and, when FAMS is enabled, a blocking DMUB round trip from setup_manual_trigger(). [How] Return early when timing_adjust_pending is clear and every v_total field already matches the request, so hardware is only touched when the values change. stream->adjust is still updated on every path that continues, so a later commit programs the requested values. timing_adjust_pending is the existing "stream->adjust has not reached hardware" marker, so keep it accurate wherever hardware is left untouched: set_drr_and_clear_adjust_pending() now sets it when called with null params, which resets DRR in the OTG during pipe back-end teardown, and the max_v_total overflow path only clears it when set_long_vtotal() runs. Reviewed-by: Josip Pavic <josip.pavic@amd.com> Signed-off-by: Aric Cyr <Aric.Cyr@amd.com> Signed-off-by: Roman Li <roman.li@amd.com> Tested-by: Dan Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c3
2 files changed, 22 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 878856ee1dfe..4e3f04530013 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1341,6 +1341,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
struct dc_crtc_timing_adjust *adjust)
{
int i;
+ bool drr_unchanged;
/*
* Don't adjust DRR while there's bandwidth optimizations pending to
@@ -1355,6 +1356,19 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
}
}
+ /* timing_adjust_pending tracks whether stream->adjust still describes the
+ * OTG, so a cleared flag plus matching values means hw is already current.
+ */
+ drr_unchanged = !stream->adjust.timing_adjust_pending &&
+ stream->adjust.v_total_min == adjust->v_total_min &&
+ stream->adjust.v_total_max == adjust->v_total_max &&
+ stream->adjust.v_total_mid == adjust->v_total_mid &&
+ stream->adjust.v_total_mid_frame_num == adjust->v_total_mid_frame_num &&
+ stream->adjust.allow_otg_v_count_halt == adjust->allow_otg_v_count_halt;
+
+ if (drr_unchanged)
+ return true;
+
dc_exit_ips_for_hw_access(dc);
stream->adjust.v_total_max = adjust->v_total_max;
@@ -1365,11 +1379,13 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
if (dc->caps.max_v_total != 0 &&
(adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
- stream->adjust.timing_adjust_pending = false;
- if (adjust->allow_otg_v_count_halt)
+ if (adjust->allow_otg_v_count_halt) {
+ stream->adjust.timing_adjust_pending = false;
return set_long_vtotal(dc, stream, adjust);
- else
- return false;
+ }
+ /* Nothing reached hw, so stream->adjust no longer describes the OTG. */
+ stream->adjust.timing_adjust_pending = true;
+ return false;
}
for (i = 0; i < MAX_PIPES; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 21a62ca4c8dc..3d88c5c377fc 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -716,7 +716,8 @@ void set_drr_and_clear_adjust_pending(
pipe_ctx->stream_res.tg, params);
if (stream)
- stream->adjust.timing_adjust_pending = false;
+ /* A null params resets DRR in hw, leaving stream->adjust stale. */
+ stream->adjust.timing_adjust_pending = (params == NULL);
}
void get_fams2_visual_confirm_color(