From: Dillon Varone Dillon.Varone@amd.com
[ Upstream commit 54980f3c63ed3e5cca3d251416581193c90eae76 ]
[WHY&HOW] dc_post_update_surfaces_to_stream needs to be called after a full update completes in order to optimize clocks and watermarks for power. Add missing calls before idle entry is requested to ensure optimal power.
Reviewed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Dillon Varone Dillon.Varone@amd.com Signed-off-by: Ivan Lipski ivan.lipski@amd.com Tested-by: Dan Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
YES — ensures AMD DC runs the pending post-flip optimization step after full updates so idle power isn’t stuck at high clocks.
- **Bug Fix**: `update_planes_and_stream_adapter()` now always calls `dc_post_update_surfaces_to_stream()` (`drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:421`). That helper clears `dc->optimized_required`, disables unused pipes, and re- optimizes clocks/watermarks (`drivers/gpu/drm/amd/display/dc/core/dc.c:2546-2579`), which otherwise stay elevated and even block DRR timing adjustments while the flag remains set (`drivers/gpu/drm/amd/display/dc/core/dc.c:463-468`). - **Idle Paths**: The idle and vblank workers invoke the same hook before allowing idle entry (`drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c:221-223` and `:278-280`), guaranteeing that power-saving transitions don’t occur while bandwidth optimizations are still pending. - **Scope & Risk**: Only adds calls to an existing guard-checked helper; when no optimization is required it returns immediately, so the change is contained, architecture-neutral, and low risk. - **Backport Fit**: Fixes a user-visible power regression (excess clocks after full flips/PSR), touches only AMD display code, and stays well within stable backport guidelines.
Next step: 1) Verify on target hardware that idle clocks drop after full-screen updates or PSR transitions.
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 8 ++++++-- 2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 57b46572fba27..d66c9609efd8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -427,8 +427,7 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc, /* * Previous frame finished and HW is ready for optimization. */ - if (update_type == UPDATE_TYPE_FAST) - dc_post_update_surfaces_to_stream(dc); + dc_post_update_surfaces_to_stream(dc);
return dc_update_planes_and_stream(dc, array_of_surface_update, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 466dccb355d7b..1ec9d03ad7474 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -218,8 +218,10 @@ static void amdgpu_dm_idle_worker(struct work_struct *work) break; }
- if (idle_work->enable) + if (idle_work->enable) { + dc_post_update_surfaces_to_stream(idle_work->dm->dc); dc_allow_idle_optimizations(idle_work->dm->dc, true); + } mutex_unlock(&idle_work->dm->dc_lock); } idle_work->dm->idle_workqueue->running = false; @@ -273,8 +275,10 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work) vblank_work->acrtc->dm_irq_params.allow_sr_entry); }
- if (dm->active_vblank_irq_count == 0) + if (dm->active_vblank_irq_count == 0) { + dc_post_update_surfaces_to_stream(dm->dc); dc_allow_idle_optimizations(dm->dc, true); + }
mutex_unlock(&dm->dc_lock);