From 1da5dab029c08e178784a0750203365ea7c3b4f4 Mon Sep 17 00:00:00 2001 From: David Zhang Date: Fri, 29 Apr 2022 15:55:16 -0400 Subject: [PATCH] drm/amd/display: combine dirty rectangles in DMUB FW [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 Acked-by: Leo Li Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 54 ++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_stream.h | 5 +++ 2 files changed, 59 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e3e3b27..d4173be 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" @@ -2824,6 +2827,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, @@ -2911,6 +2963,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_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 772b4a6..f8f6679 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -550,4 +550,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.7.4