[PATCH 4/4] drm/amd/display: Update HW_DONE_DEADLINE property value on modeset
Harry Wentland
harry.wentland at amd.com
Thu Jul 31 20:51:31 UTC 2025
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 <mdaenzer at redhat.com>
>
> Set it to the end of the front porch.
>
> Signed-off-by: Michel Dänzer <mdaenzer at 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);
>
More information about the dri-devel
mailing list