Commit 0d7e6dc0 authored by Wayne Lin's avatar Wayne Lin Committed by Alex Deucher
Browse files

drm/amd/display: Process crc window at DMCU



[Why & How]
Add additional MCP_SCP commands for starting/stopping updaing crc
window at DMCU

Signed-off-by: default avatarWayne Lin <Wayne.Lin@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Acked-by: default avatarEryk Brol <eryk.brol@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 86bc2219
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
@@ -347,6 +347,88 @@ bool dc_stream_get_crtc_position(struct dc *dc,
	return ret;
}

#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream,
			     struct crc_params *crc_window)
{
	int i;
	struct dmcu *dmcu = dc->res_pool->dmcu;
	struct pipe_ctx *pipe;
	struct crc_region tmp_win, *crc_win;
	struct otg_phy_mux mapping_tmp, *mux_mapping;

	/*crc window can't be null*/
	if (!crc_window)
		return false;

	if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
		crc_win = &tmp_win;
		mux_mapping = &mapping_tmp;
		/*set crc window*/
		tmp_win.x_start = crc_window->windowa_x_start;
		tmp_win.y_start = crc_window->windowa_y_start;
		tmp_win.x_end = crc_window->windowa_x_end;
		tmp_win.y_end = crc_window->windowa_y_end;

		for (i = 0; i < MAX_PIPES; i++) {
			pipe = &dc->current_state->res_ctx.pipe_ctx[i];
			if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
				break;
		}

		/* Stream not found */
		if (i == MAX_PIPES)
			return false;


		/*set mux routing info*/
		mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
		mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;

		dmcu->funcs->forward_crc_window(dmcu, crc_win, mux_mapping);
	} else {
		DC_LOG_DC("dmcu is not initialized");
		return false;
	}

	return true;
}

bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *stream)
{
	int i;
	struct dmcu *dmcu = dc->res_pool->dmcu;
	struct pipe_ctx *pipe;
	struct otg_phy_mux mapping_tmp, *mux_mapping;

	if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
		mux_mapping = &mapping_tmp;

		for (i = 0; i < MAX_PIPES; i++) {
			pipe = &dc->current_state->res_ctx.pipe_ctx[i];
			if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
				break;
		}

		/* Stream not found */
		if (i == MAX_PIPES)
			return false;


		/*set mux routing info*/
		mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
		mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;

		dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping);
	} else {
		DC_LOG_DC("dmcu is not initialized");
		return false;
	}

	return true;
}
#endif

/**
 * dc_stream_configure_crc() - Configure CRC capture for the given stream.
 * @dc: DC Object
+7 −0
Original line number Diff line number Diff line
@@ -453,6 +453,13 @@ bool dc_stream_get_crtc_position(struct dc *dc,
				 unsigned int *v_pos,
				 unsigned int *nom_v_pos);

#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream,
			     struct crc_params *crc_window);
bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc,
				 struct dc_stream_state *stream);
#endif

bool dc_stream_configure_crc(struct dc *dc,
			     struct dc_stream_state *stream,
			     struct crc_params *crc_window,
+84 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@
#define MCP_SYNC_PHY_LOCK 0x90
#define MCP_SYNC_PHY_UNLOCK 0x91
#define MCP_BL_SET_PWM_FRAC 0x6A  /* Enable or disable Fractional PWM */
#define CRC_WIN_NOTIFY 0x92
#define CRC_STOP_UPDATE 0x93
#define MCP_SEND_EDID_CEA 0xA0
#define EDID_CEA_CMD_ACK 1
#define EDID_CEA_CMD_NACK 2
@@ -930,6 +932,84 @@ static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset)

#endif //(CONFIG_DRM_AMD_DC_DCN)

#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
static void dcn10_forward_crc_window(struct dmcu *dmcu,
					struct crc_region *crc_win,
					struct otg_phy_mux *mux_mapping)
{
	struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
	unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
	unsigned int dmcu_wait_reg_ready_interval = 100;
	unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0;

	/* If microcontroller is not running, do nothing */
	if (dmcu->dmcu_state != DMCU_RUNNING)
		return;

	if (!crc_win)
		return;

	/* waitDMCUReadyForCmd */
	REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
				dmcu_wait_reg_ready_interval,
				dmcu_max_retry_on_wait_reg_ready);

	/* build up nitification data */
	crc_start = (((unsigned int) crc_win->x_start) << 16) | crc_win->y_start;
	crc_end = (((unsigned int) crc_win->x_end) << 16) | crc_win->y_end;
	otg_phy_mux =
		(((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;

	dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
					crc_start);

	dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2),
			crc_end);

	dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3),
			otg_phy_mux);

	/* setDMCUParam_Cmd */
	REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
				CRC_WIN_NOTIFY);

	/* notifyDMCUMsg */
	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
}

static void dcn10_stop_crc_win_update(struct dmcu *dmcu,
					struct otg_phy_mux *mux_mapping)
{
	struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
	unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
	unsigned int dmcu_wait_reg_ready_interval = 100;
	unsigned int otg_phy_mux = 0;

	/* If microcontroller is not running, do nothing */
	if (dmcu->dmcu_state != DMCU_RUNNING)
		return;

	/* waitDMCUReadyForCmd */
	REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
				dmcu_wait_reg_ready_interval,
				dmcu_max_retry_on_wait_reg_ready);

	/* build up nitification data */
	otg_phy_mux =
		(((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;

	dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
					otg_phy_mux);

	/* setDMCUParam_Cmd */
	REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
				CRC_STOP_UPDATE);

	/* notifyDMCUMsg */
	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
}
#endif

static const struct dmcu_funcs dce_funcs = {
	.dmcu_init = dce_dmcu_init,
	.load_iram = dce_dmcu_load_iram,
@@ -953,6 +1033,10 @@ static const struct dmcu_funcs dcn10_funcs = {
	.send_edid_cea = dcn10_send_edid_cea,
	.recv_amd_vsdb = dcn10_recv_amd_vsdb,
	.recv_edid_cea_ack = dcn10_recv_edid_cea_ack,
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
	.forward_crc_window = dcn10_forward_crc_window,
	.stop_crc_win_update = dcn10_stop_crc_win_update,
#endif
	.is_dmcu_initialized = dcn10_is_dmcu_initialized
};

+21 −0
Original line number Diff line number Diff line
@@ -56,6 +56,20 @@ struct dmcu {
	bool auto_load_dmcu;
};

#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
struct crc_region {
	uint16_t x_start;
	uint16_t y_start;
	uint16_t x_end;
	uint16_t y_end;
};

struct otg_phy_mux {
	uint8_t phy_output_num;
	uint8_t otg_output_num;
};
#endif

struct dmcu_funcs {
	bool (*dmcu_init)(struct dmcu *dmcu);
	bool (*load_iram)(struct dmcu *dmcu,
@@ -84,6 +98,13 @@ struct dmcu_funcs {
			int *min_frame_rate,
			int *max_frame_rate);
	bool (*recv_edid_cea_ack)(struct dmcu *dmcu, int *offset);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
	void (*forward_crc_window)(struct dmcu *dmcu,
			struct crc_region *crc_win,
			struct otg_phy_mux *mux_mapping);
	void (*stop_crc_win_update)(struct dmcu *dmcu,
			struct otg_phy_mux *mux_mapping);
#endif
};

#endif