[AMD Official Use Only - General]
Hi Chandan,
The dirty rectangle combination is implemented in DMUB firmware instead of DC/DM layer in kernel. The "max # of dirty RECTs of 3" is the limitation in DMUB FW.
regards
David
From: VURDIGERENATARAJ, CHANDAN <CHANDAN.VURDIGERENATARAJ@xxxxxxx>
Sent: Monday, May 9, 2022 4:12 AM To: Zhang, Dingchen (David) <Dingchen.Zhang@xxxxxxx>; amd-gfx@xxxxxxxxxxxxxxxxxxxxx <amd-gfx@xxxxxxxxxxxxxxxxxxxxx> Cc: Wang, Chao-kai (Stylon) <Stylon.Wang@xxxxxxx>; Li, Sun peng (Leo) <Sunpeng.Li@xxxxxxx>; Wentland, Harry <Harry.Wentland@xxxxxxx>; Zhuo, Qingqing (Lillian) <Qingqing.Zhuo@xxxxxxx>; Siqueira, Rodrigo <Rodrigo.Siqueira@xxxxxxx>; Li, Roman <Roman.Li@xxxxxxx>; Chiu, Solomon <Solomon.Chiu@xxxxxxx>; Zuo, Jerry <Jerry.Zuo@xxxxxxx>; Pillai, Aurabindo <Aurabindo.Pillai@xxxxxxx>; Lin, Wayne <Wayne.Lin@xxxxxxx>; Lakha, Bhawanpreet <Bhawanpreet.Lakha@xxxxxxx>; Gutierrez, Agustin <Agustin.Gutierrez@xxxxxxx>; Kotarac, Pavle <Pavle.Kotarac@xxxxxxx> Subject: RE: [PATCH 03/17] drm/amd/display: combine dirty rectangles in DMUB FW Hi,
Why is the DC_MAX_DIRTY_RECTS set to 3? What causes this limitation? >[why] >In PSR-SU design, the DMUB FW handles the combination of multiple dirty rectangles. > >[how] >- create DC dmub update dirty rectangle helper which sends the > dirty rectangles per pipe from DC to DMUB, and DMUB FW will > handle to combine the dirty RECTs >- call the helper from DC commit plane update function. > >Signed-off-by: David Zhang <dingchen.zhang@xxxxxxx> >--- > drivers/gpu/drm/amd/display/dc/core/dc.c | 54 ++++++++++++++++++++++ > drivers/gpu/drm/amd/display/dc/dc.h | 3 ++ > drivers/gpu/drm/amd/display/dc/dc_stream.h | 5 ++ > 3 files changed, 62 insertions(+) > >diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c >index c2fcd67bcc4d..0649d84b71b6 100644 >--- a/drivers/gpu/drm/amd/display/dc/core/dc.c >+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c >@@ -72,6 +72,9 @@ > #include "dmub/dmub_srv.h" > > #include "i2caux_interface.h" >+ >+#include "dce/dmub_psr.h" >+ > #include "dce/dmub_hw_lock_mgr.h" > > #include "dc_trace.h" >@@ -2842,6 +2845,55 @@ static void commit_planes_do_stream_update(struct dc *dc, > } > } > >+void dc_dmub_update_dirty_rect(struct dc *dc, >+ int surface_count, >+ struct dc_stream_state *stream, >+ struct dc_surface_update *srf_updates, >+ struct dc_state *context) >+{ >+ union dmub_rb_cmd cmd; >+ struct dc_context *dc_ctx = dc->ctx; >+ struct dmub_cmd_update_dirty_rect_data *update_dirty_rect; >+ unsigned int i, j; >+ >+ if (stream->link->psr_settings.psr_version != DC_PSR_VERSION_SU_1) >+ return; >+ >+ memset(&cmd, 0x0, sizeof(cmd)); >+ cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT; >+ cmd.update_dirty_rect.header.sub_type = 0; >+ cmd.update_dirty_rect.header.payload_bytes = >+ sizeof(cmd.update_dirty_rect) - >+ sizeof(cmd.update_dirty_rect.header); >+ update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data; >+ for (i = 0; i < surface_count; i++) { >+ struct dc_plane_state *plane_state = srf_updates[i].surface; >+ const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr; >+ >+ if (!srf_updates[i].surface || !flip_addr) >+ continue; >+ /* Do not send in immediate flip mode */ >+ if (srf_updates[i].surface->flip_immediate) >+ continue; >+ >+ update_dirty_rect->dirty_rect_count = flip_addr->dirty_rect_count; >+ memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects, >+ sizeof(flip_addr->dirty_rects)); >+ for (j = 0; j < dc->res_pool->pipe_count; j++) { >+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; >+ >+ if (pipe_ctx->stream != stream) >+ continue; >+ if (pipe_ctx->plane_state != plane_state) >+ continue; >+ >+ update_dirty_rect->pipe_idx = j; >+ dc_dmub_srv_cmd_queue(dc_ctx->dmub_srv, &cmd); >+ dc_dmub_srv_cmd_execute(dc_ctx->dmub_srv); >+ } >+ } >+} >+ > static void commit_planes_for_stream(struct dc *dc, > struct dc_surface_update *srf_updates, > int surface_count, >@@ -2934,6 +2986,8 @@ static void commit_planes_for_stream(struct dc *dc, > */ > dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true); > >+ dc_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, >+context); >+ > // Stream updates > if (stream_update) > commit_planes_do_stream_update(dc, stream, stream_update, update_type, context); diff --git >a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h >index 942bfb8fd851..85f3303e7843 100644 >--- a/drivers/gpu/drm/amd/display/dc/dc.h >+++ b/drivers/gpu/drm/amd/display/dc/dc.h >@@ -1134,12 +1134,15 @@ void dc_3dlut_func_retain(struct dc_3dlut *lut); > * in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such > * as frame durations and DCC format can also be set. > */ >+#define DC_MAX_DIRTY_RECTS 3 > struct dc_flip_addrs { > struct dc_plane_address address; > unsigned int flip_timestamp_in_us; > bool flip_immediate; > /* TODO: add flip duration for FreeSync */ > bool triplebuffer_flips; >+ unsigned int dirty_rect_count; >+ struct rect dirty_rects[DC_MAX_DIRTY_RECTS]; > }; > > void dc_post_update_surfaces_to_stream( >diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h >index 58941f4defb3..58036469c62a 100644 >--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h >+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h >@@ -529,4 +529,9 @@ bool dc_stream_get_crtc_position(struct dc *dc, > > struct pipe_ctx *dc_stream_get_pipe_ctx(struct dc_stream_state *stream); > >+void dc_dmub_update_dirty_rect(struct dc *dc, >+ int surface_count, >+ struct dc_stream_state *stream, >+ struct dc_surface_update *srf_updates, >+ struct dc_state *context); > #endif /* DC_STREAM_H_ */ >-- >2.25.1 |