Thanks for the series. It makes sense to me. Below are my thoughts on the deadline value on amdgpu.
On 2025-07-24 12:40, Michel Dänzer wrote: > From: Michel Dänzer <mdaen...@redhat.com> > > Set it to the end of the front porch. > > Signed-off-by: Michel Dänzer <mdaen...@redhat.com> > --- > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 +++++++++++++++++++ > 1 file changed, 22 insertions(+) > > 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 0b8ac9edc070..e78249b55345 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > @@ -10021,6 +10021,21 @@ static void dm_set_writeback(struct > amdgpu_display_manager *dm, > drm_writeback_queue_job(wb_conn, new_con_state); > } > > +static void > +update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state) > +{ > + struct dc_stream_state *stream = dm_new_crtc_state->stream; > + struct dc_crtc_timing *timing = &stream->timing; > + struct drm_crtc *crtc = dm_new_crtc_state->base.crtc; > + uint32_t deadline_lines, deadline_us; > + > + /* XXX: My guess, AMD display team to the rescue! */ > + deadline_lines = timing->v_total - timing->v_addressable - > timing->v_front_porch; This works on DCE. On DCN we'll need to take the offset into account. This diff on top of your changesshould do it, but it's not tested. The dc_stream changes probably fit in their own patch. 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 629fd21a611f..314074527216 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10082,11 +10082,19 @@ update_hw_done_deadline(struct dm_crtc_state *dm_new_crtc_state) struct dc_crtc_timing *timing = &stream->timing; struct drm_crtc *crtc = dm_new_crtc_state->base.crtc; uint32_t deadline_lines, deadline_us; + int vupdate_offset = dc_stream_get_vupdate_offset_from_vsync(stream); + + /* note: + * vupdate_offset is non-existant on DCE and function will return 0 + * vupdate_offset could be positive or negative on DCN + * vupdate_offset depends on timing and HW bandwidth requirements + */ + deadline_lines = timing->v_total - timing->v_addressable - + timing->v_front_porch - vupdate_offset; - /* XXX: My guess, AMD display team to the rescue! */ - deadline_lines = timing->v_total - timing->v_addressable - timing->v_front_porch; deadline_us = DIV_ROUND_UP(deadline_lines * stream->timing.h_total * 10000u, stream->timing.pix_clk_100hz); + drm_crtc_set_hw_done_deadline_property(crtc, deadline_us); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 4d6bc9fd4faa..ae8472a65247 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -1224,3 +1224,25 @@ bool dc_stream_can_clear_cursor_limit(struct dc *dc, struct dc_stream_state *str return can_clear_limit; } + +int dc_stream_get_vupdate_offset_from_vsync(const struct dc_stream_state *stream) +{ + struct dc *dc; + struct resource_context *res_ctx; + int i; + + if (!stream || !stream->ctx || !stream->ctx->dc) + return 0; + + dc = stream->ctx->dc; + res_ctx = &dc->current_state->res_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (pipe_ctx->stream == stream && dc->hwss.get_vupdate_offset_from_vsync) + return dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx); + } + + return 0; +} \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 5fc6fea211de..792a7e8b2ee7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -601,4 +601,6 @@ void dc_dmub_update_dirty_rect(struct dc *dc, bool dc_stream_is_cursor_limit_pending(struct dc *dc, struct dc_stream_state *stream); bool dc_stream_can_clear_cursor_limit(struct dc *dc, struct dc_stream_state *stream); +int dc_stream_get_vupdate_offset_from_vsync(const struct dc_stream_state *stream); + #endif /* DC_STREAM_H_ */ Harry > + deadline_us = DIV_ROUND_UP(deadline_lines * stream->timing.h_total * > 10000u, > + stream->timing.pix_clk_100hz); > + drm_crtc_set_hw_done_deadline_property(crtc, deadline_us); > +} > + > /** > * amdgpu_dm_atomic_commit_tail() - AMDgpu DM's commit tail implementation. > * @state: The atomic state to commit > @@ -10419,6 +10434,13 @@ static void amdgpu_dm_atomic_commit_tail(struct > drm_atomic_state *state) > /* Signal HW programming completion */ > drm_atomic_helper_commit_hw_done(state); > > + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, > new_crtc_state, i) { > + if (new_crtc_state->active && > + (!old_crtc_state->active || > + drm_atomic_crtc_needs_modeset(new_crtc_state))) > + > update_hw_done_deadline(to_dm_crtc_state(new_crtc_state)); > + } > + > if (wait_for_vblank) > drm_atomic_helper_wait_for_flip_done(dev, state); >