| From 47a3a685e561f032c2892cad8a6a06e482af78fd Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 9 Jan 2025 16:11:48 +0800 |
| Subject: drm/amd/display: Update Cursor request mode to the beginning prefetch |
| always |
| |
| From: Zhikai Zhai <zhikai.zhai@amd.com> |
| |
| [ 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> |
| --- |
| .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 22 ++++++++----------- |
| .../gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c | 2 +- |
| 2 files changed, 10 insertions(+), 14 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c |
| index 416168c7dcc52..b120aa67d26c1 100644 |
| --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c |
| +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c |
| @@ -1947,20 +1947,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. */ |
| @@ -1968,13 +1959,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); |
| } |
| diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c |
| index 39a57bcd78667..576acf2ce10dd 100644 |
| --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c |
| +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c |
| @@ -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) |
| -- |
| 2.39.5 |
| |