Commit 1da5dab0 authored by David Zhang's avatar David Zhang Committed by Alex Deucher
Browse files

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: default avatarDavid Zhang <dingchen.zhang@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Reviewed-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b3d0c0f2
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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_ */