drm/amd/display: Update Cursor request mode to the beginning prefetch always
authorZhikai Zhai <zhikai.zhai@amd.com>
Thu, 9 Jan 2025 08:11:48 +0000 (16:11 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 20 Apr 2025 08:15:23 +0000 (10:15 +0200)
[ Upstream commit 4a4077b4b63a8404efd6d37fc2926f03fb25bace ]

[Why]
The double buffer cursor registers is updated by the cursor
vupdate event. There is a gap between vupdate and cursor data
fetch if cursor fetch data reletive to cursor position.
Cursor corruption will happen if we update the cursor surface
in this gap.

[How]
Modify the cursor request mode to the beginning prefetch always
and avoid wraparound calculation issues.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Zhikai Zhai <zhikai.zhai@amd.com>
Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dc/hubp/dcn31/dcn31_hubp.c
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c

index a65a0ddee64672bca7ae4bfcef9ffe97ec6ca460..c671908ba7d06c1159821e41c00484b2c58aa0eb 100644 (file)
@@ -44,7 +44,7 @@ void hubp31_set_unbounded_requesting(struct hubp *hubp, bool enable)
        struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
 
        REG_UPDATE(DCHUBP_CNTL, HUBP_UNBOUNDED_REQ_MODE, enable);
-       REG_UPDATE(CURSOR_CONTROL, CURSOR_REQ_MODE, enable);
+       REG_UPDATE(CURSOR_CONTROL, CURSOR_REQ_MODE, 1);
 }
 
 void hubp31_soft_reset(struct hubp *hubp, bool reset)
index fd0530251c6e5a50c438d63041384abbf2a7e3b1..d725af14af371a4df8743f6eb332007569cd28f1 100644 (file)
@@ -1992,20 +1992,11 @@ static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
        dc->hwss.get_position(&pipe_ctx, 1, &position);
        vpos = position.vertical_count;
 
-       /* Avoid wraparound calculation issues */
-       vupdate_start += stream->timing.v_total;
-       vupdate_end += stream->timing.v_total;
-       vpos += stream->timing.v_total;
-
        if (vpos <= vupdate_start) {
                /* VPOS is in VACTIVE or back porch. */
                lines_to_vupdate = vupdate_start - vpos;
-       } else if (vpos > vupdate_end) {
-               /* VPOS is in the front porch. */
-               return;
        } else {
-               /* VPOS is in VUPDATE. */
-               lines_to_vupdate = 0;
+               lines_to_vupdate = stream->timing.v_total - vpos + vupdate_start;
        }
 
        /* Calculate time until VUPDATE in microseconds. */
@@ -2013,13 +2004,18 @@ static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
                stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz;
        us_to_vupdate = lines_to_vupdate * us_per_line;
 
+       /* Stall out until the cursor update completes. */
+       if (vupdate_end < vupdate_start)
+               vupdate_end += stream->timing.v_total;
+
+       /* Position is in the range of vupdate start and end*/
+       if (lines_to_vupdate > stream->timing.v_total - vupdate_end + vupdate_start)
+               us_to_vupdate = 0;
+
        /* 70 us is a conservative estimate of cursor update time*/
        if (us_to_vupdate > 70)
                return;
 
-       /* Stall out until the cursor update completes. */
-       if (vupdate_end < vupdate_start)
-               vupdate_end += stream->timing.v_total;
        us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line;
        udelay(us_to_vupdate + us_vupdate);
 }