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);
>  

Reply via email to