[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