From: Aric Cyr <[email protected]> [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 <[email protected]> Signed-off-by: Aric Cyr <[email protected]> Signed-off-by: Roman Li <[email protected]> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 +++++++++++++++---- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 3 ++- 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 17db12fe8022..254c2a9c1b04 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1342,6 +1342,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 @@ -1356,6 +1357,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; @@ -1366,11 +1380,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( -- 2.34.1
