Commit b73353f7 authored by Max Tseng's avatar Max Tseng Committed by Alex Deucher
Browse files

drm/amd/display: Use the same cursor info across features



Since different features would need to update cursor registers, However,
they would use different approaches.

To unify varied methods, this refactor is implemented the same update
cursor info method for current varied features.

Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarMax Tseng <Max.Tseng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3867bbd4
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -276,6 +276,8 @@ static void program_cursor_attributes(
		}

		dc->hwss.set_cursor_attribute(pipe_ctx);

		dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
		if (dc->hwss.set_cursor_sdr_white_level)
			dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
	}
@@ -382,6 +384,8 @@ static void program_cursor_position(
		}

		dc->hwss.set_cursor_position(pipe_ctx);

		dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
	}

	if (pipe_to_program)
+145 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "dc_hw_types.h"
#include "core_types.h"
#include "../basics/conversion.h"
#include "cursor_reg_cache.h"

#define CTX dc_dmub_srv->ctx
#define DC_LOGGER CTX->logger
@@ -880,3 +881,147 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
		diag_data.is_cw0_enabled,
		diag_data.is_cw6_enabled);
}

static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx)
{
	if (pipe_ctx->plane_state != NULL) {
		if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
			return false;
	}

	if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 ||
		pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) &&
		pipe_ctx->stream->ctx->dce_version >= DCN_VERSION_3_1)
		return true;

	return false;
}

static void dc_build_cursor_update_payload0(
		struct pipe_ctx *pipe_ctx, uint8_t p_idx,
		struct dmub_cmd_update_cursor_payload0 *payload)
{
	struct hubp *hubp = pipe_ctx->plane_res.hubp;
	unsigned int panel_inst = 0;

	if (!dc_get_edp_link_panel_inst(hubp->ctx->dc,
		pipe_ctx->stream->link, &panel_inst))
		return;

	/* Payload: Cursor Rect is built from position & attribute
	 * x & y are obtained from postion
	 */
	payload->cursor_rect.x = hubp->cur_rect.x;
	payload->cursor_rect.y = hubp->cur_rect.y;
	/* w & h are obtained from attribute */
	payload->cursor_rect.width  = hubp->cur_rect.w;
	payload->cursor_rect.height = hubp->cur_rect.h;

	payload->enable      = hubp->pos.cur_ctl.bits.cur_enable;
	payload->pipe_idx    = p_idx;
	payload->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
	payload->panel_inst  = panel_inst;
}

static void dc_send_cmd_to_dmu(struct dc_dmub_srv *dmub_srv,
		union dmub_rb_cmd *cmd)
{
	dc_dmub_srv_cmd_queue(dmub_srv, cmd);
	dc_dmub_srv_cmd_execute(dmub_srv);
	dc_dmub_srv_wait_idle(dmub_srv);
}

static void dc_build_cursor_position_update_payload0(
		struct dmub_cmd_update_cursor_payload0 *pl, const uint8_t p_idx,
		const struct hubp *hubp, const struct dpp *dpp)
{
	/* Hubp */
	pl->position_cfg.pHubp.cur_ctl.raw  = hubp->pos.cur_ctl.raw;
	pl->position_cfg.pHubp.position.raw = hubp->pos.position.raw;
	pl->position_cfg.pHubp.hot_spot.raw = hubp->pos.hot_spot.raw;
	pl->position_cfg.pHubp.dst_offset.raw = hubp->pos.dst_offset.raw;

	/* dpp */
	pl->position_cfg.pDpp.cur0_ctl.raw = dpp->pos.cur0_ctl.raw;
	pl->position_cfg.pipe_idx = p_idx;
}

static void dc_build_cursor_attribute_update_payload1(
		struct dmub_cursor_attributes_cfg *pl_A, const uint8_t p_idx,
		const struct hubp *hubp, const struct dpp *dpp)
{
	/* Hubp */
	pl_A->aHubp.SURFACE_ADDR_HIGH = hubp->att.SURFACE_ADDR_HIGH;
	pl_A->aHubp.SURFACE_ADDR = hubp->att.SURFACE_ADDR;
	pl_A->aHubp.cur_ctl.raw  = hubp->att.cur_ctl.raw;
	pl_A->aHubp.size.raw     = hubp->att.size.raw;
	pl_A->aHubp.settings.raw = hubp->att.settings.raw;

	/* dpp */
	pl_A->aDpp.cur0_ctl.raw = dpp->att.cur0_ctl.raw;
}

/**
 * ***************************************************************************************
 * dc_send_update_cursor_info_to_dmu: Populate the DMCUB Cursor update info command
 *
 * This function would store the cursor related information and pass it into dmub
 *
 * @param [in] pCtx: pipe context
 * @param [in] pipe_idx: pipe index
 *
 * @return: void
 *
 * ***************************************************************************************
 */

void dc_send_update_cursor_info_to_dmu(
		struct pipe_ctx *pCtx, uint8_t pipe_idx)
{
	union dmub_rb_cmd cmd = { 0 };
	union dmub_cmd_update_cursor_info_data *update_cursor_info =
					&cmd.update_cursor_info.update_cursor_info_data;

	if (!dc_dmub_should_update_cursor_data(pCtx))
		return;
	/*
	 * Since we use multi_cmd_pending for dmub command, the 2nd command is
	 * only assigned to store cursor attributes info.
	 * 1st command can view as 2 parts, 1st is for PSR/Replay data, the other
	 * is to store cursor position info.
	 *
	 * Command heaer type must be the same type if using  multi_cmd_pending.
	 * Besides, while process 2nd command in DMU, the sub type is useless.
	 * So it's meanless to pass the sub type header with different type.
	 */

	{
		/* Build Payload#0 Header */
		cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
		cmd.update_cursor_info.header.payload_bytes =
				sizeof(cmd.update_cursor_info.update_cursor_info_data);
		cmd.update_cursor_info.header.multi_cmd_pending = 1; /* To combine multi dmu cmd, 1st cmd */

		/* Prepare Payload */
		dc_build_cursor_update_payload0(pCtx, pipe_idx, &update_cursor_info->payload0);

		dc_build_cursor_position_update_payload0(&update_cursor_info->payload0, pipe_idx,
				pCtx->plane_res.hubp, pCtx->plane_res.dpp);
		/* Send update_curosr_info to queue */
		dc_dmub_srv_cmd_queue(pCtx->stream->ctx->dmub_srv, &cmd);
	}
	{
		/* Build Payload#1 Header */
		memset(update_cursor_info, 0, sizeof(union dmub_cmd_update_cursor_info_data));
		cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
		cmd.update_cursor_info.header.payload_bytes = sizeof(struct cursor_attributes_cfg);
		cmd.update_cursor_info.header.multi_cmd_pending = 0; /* Indicate it's the last command. */

		dc_build_cursor_attribute_update_payload1(
				&cmd.update_cursor_info.update_cursor_info_data.payload1.attribute_cfg,
				pipe_idx, pCtx->plane_res.hubp, pCtx->plane_res.dpp);

		/* Combine 2nd cmds update_curosr_info to DMU */
		dc_send_cmd_to_dmu(pCtx->stream->ctx->dmub_srv, &cmd);
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -88,4 +88,5 @@ bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmu
void dc_dmub_setup_subvp_dmub_command(struct dc *dc, struct dc_state *context, bool enable);
void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv);

void dc_send_update_cursor_info_to_dmu(struct pipe_ctx *pCtx, uint8_t pipe_idx);
#endif /* _DMUB_DC_SRV_H_ */
+1 −0
Original line number Diff line number Diff line
@@ -469,6 +469,7 @@ void dpp1_set_cursor_position(
	REG_UPDATE(CURSOR0_CONTROL,
			CUR0_ENABLE, cur_en);

	dpp_base->pos.cur0_ctl.bits.cur0_enable = cur_en;
}

void dpp1_cnv_set_optional_cursor_attributes(
+0 −141
Original line number Diff line number Diff line
@@ -3372,127 +3372,6 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
	return false;
}

static bool dcn10_dmub_should_update_cursor_data(
		struct pipe_ctx *pipe_ctx,
		struct dc_debug_options *debug)
{
	if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
		return false;

	if (dcn10_can_pipe_disable_cursor(pipe_ctx))
		return false;

	if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
			&& pipe_ctx->stream->ctx->dce_version >= DCN_VERSION_3_1)
		return true;

	return false;
}

static void dcn10_dmub_update_cursor_data(
		struct pipe_ctx *pipe_ctx,
		struct hubp *hubp,
		const struct dc_cursor_mi_param *param,
		const struct dc_cursor_position *cur_pos,
		const struct dc_cursor_attributes *cur_attr)
{
	union dmub_rb_cmd cmd;
	struct dmub_cmd_update_cursor_info_data *update_cursor_info;
	const struct dc_cursor_position *pos;
	const struct dc_cursor_attributes *attr;
	int src_x_offset = 0;
	int src_y_offset = 0;
	int x_hotspot = 0;
	int cursor_height = 0;
	int cursor_width = 0;
	uint32_t cur_en = 0;
	unsigned int panel_inst = 0;

	struct dc_debug_options *debug = &hubp->ctx->dc->debug;

	if (!dcn10_dmub_should_update_cursor_data(pipe_ctx, debug))
		return;
	/**
	 * if cur_pos == NULL means the caller is from cursor_set_attribute
	 * then driver use previous cursor position data
	 * if cur_attr == NULL means the caller is from cursor_set_position
	 * then driver use previous cursor attribute
	 * if cur_pos or cur_attr is not NULL then update it
	 */
	if (cur_pos != NULL)
		pos = cur_pos;
	else
		pos = &hubp->curs_pos;

	if (cur_attr != NULL)
		attr = cur_attr;
	else
		attr = &hubp->curs_attr;

	if (!dc_get_edp_link_panel_inst(hubp->ctx->dc, pipe_ctx->stream->link, &panel_inst))
		return;

	src_x_offset = pos->x - pos->x_hotspot - param->viewport.x;
	src_y_offset = pos->y - pos->y_hotspot - param->viewport.y;
	x_hotspot = pos->x_hotspot;
	cursor_height = (int)attr->height;
	cursor_width = (int)attr->width;
	cur_en = pos->enable ? 1:0;

	// Rotated cursor width/height and hotspots tweaks for offset calculation
	if (param->rotation == ROTATION_ANGLE_90 || param->rotation == ROTATION_ANGLE_270) {
		swap(cursor_height, cursor_width);
		if (param->rotation == ROTATION_ANGLE_90) {
			src_x_offset = pos->x - pos->y_hotspot - param->viewport.x;
			src_y_offset = pos->y - pos->x_hotspot - param->viewport.y;
		}
	} else if (param->rotation == ROTATION_ANGLE_180) {
		src_x_offset = pos->x - param->viewport.x;
		src_y_offset = pos->y - param->viewport.y;
	}

	if (param->mirror) {
		x_hotspot = param->viewport.width - x_hotspot;
		src_x_offset = param->viewport.x + param->viewport.width - src_x_offset;
	}

	if (src_x_offset >= (int)param->viewport.width)
		cur_en = 0;  /* not visible beyond right edge*/

	if (src_x_offset + cursor_width <= 0)
		cur_en = 0;  /* not visible beyond left edge*/

	if (src_y_offset >= (int)param->viewport.height)
		cur_en = 0;  /* not visible beyond bottom edge*/

	if (src_y_offset + cursor_height <= 0)
		cur_en = 0;  /* not visible beyond top edge*/

	// Cursor bitmaps have different hotspot values
	// There's a possibility that the above logic returns a negative value, so we clamp them to 0
	if (src_x_offset < 0)
		src_x_offset = 0;
	if (src_y_offset < 0)
		src_y_offset = 0;

	memset(&cmd, 0x0, sizeof(cmd));
	cmd.update_cursor_info.header.type = DMUB_CMD__UPDATE_CURSOR_INFO;
	cmd.update_cursor_info.header.payload_bytes =
			sizeof(cmd.update_cursor_info.update_cursor_info_data);
	update_cursor_info = &cmd.update_cursor_info.update_cursor_info_data;
	update_cursor_info->cursor_rect.x = src_x_offset + param->viewport.x;
	update_cursor_info->cursor_rect.y = src_y_offset + param->viewport.y;
	update_cursor_info->cursor_rect.width = attr->width;
	update_cursor_info->cursor_rect.height = attr->height;
	update_cursor_info->enable = cur_en;
	update_cursor_info->pipe_idx = pipe_ctx->pipe_idx;
	update_cursor_info->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
	update_cursor_info->panel_inst = panel_inst;
	dc_dmub_srv_cmd_queue(pipe_ctx->stream->ctx->dmub_srv, &cmd);
	dc_dmub_srv_cmd_execute(pipe_ctx->stream->ctx->dmub_srv);
	dc_dmub_srv_wait_idle(pipe_ctx->stream->ctx->dmub_srv);
}

void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
{
	struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
@@ -3727,7 +3606,6 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
			pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
	}

	dcn10_dmub_update_cursor_data(pipe_ctx, hubp, &param, &pos_cpy, NULL);
	hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
	dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);
}
@@ -3735,25 +3613,6 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
{
	struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
	struct dc_cursor_mi_param param = { 0 };

	/**
	 * If enter PSR without cursor attribute update
	 * the cursor attribute of dmub_restore_plane
	 * are initial value. call dmub to exit PSR and
	 * restore plane then update cursor attribute to
	 * avoid override with initial value
	 */
	if (pipe_ctx->plane_state != NULL) {
		param.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
		param.ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz;
		param.viewport = pipe_ctx->plane_res.scl_data.viewport;
		param.h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz;
		param.v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert;
		param.rotation = pipe_ctx->plane_state->rotation;
		param.mirror = pipe_ctx->plane_state->horizontal_mirror;
		dcn10_dmub_update_cursor_data(pipe_ctx, pipe_ctx->plane_res.hubp, &param, NULL, attributes);
	}

	pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
			pipe_ctx->plane_res.hubp, attributes);
Loading