Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99a100ae authored by David Francis's avatar David Francis Committed by Alex Deucher
Browse files

drm/amd/display: Add CRC support for DCN



[Why]
Regamma/CTM tests require CRC support

[How]
The CRC registers that were used in DCE exist under different
names in DCN.  The code was copied from DCE (in
dc/dce110/dce110_timing_generator.c) into DCN, and changed to
use the DCN register access helper functions.

Signed-off-by: default avatarDavid Francis <David.Francis@amd.com>
Reviewed-by: default avatarCharlene Liu <Charlene.Liu@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4e18814e
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -1324,6 +1324,72 @@ bool optc1_is_optc_underflow_occurred(struct timing_generator *optc)
	return (underflow_occurred == 1);
}

bool optc1_configure_crc(struct timing_generator *optc,
			  const struct crc_params *params)
{
	struct optc *optc1 = DCN10TG_FROM_TG(optc);

	/* Cannot configure crc on a CRTC that is disabled */
	if (!optc1_is_tg_enabled(optc))
		return false;

	REG_WRITE(OTG_CRC_CNTL, 0);

	if (!params->enable)
		return true;

	/* Program frame boundaries */
	/* Window A x axis start and end. */
	REG_UPDATE_2(OTG_CRC0_WINDOWA_X_CONTROL,
			OTG_CRC0_WINDOWA_X_START, params->windowa_x_start,
			OTG_CRC0_WINDOWA_X_END, params->windowa_x_end);

	/* Window A y axis start and end. */
	REG_UPDATE_2(OTG_CRC0_WINDOWA_Y_CONTROL,
			OTG_CRC0_WINDOWA_Y_START, params->windowa_y_start,
			OTG_CRC0_WINDOWA_Y_END, params->windowa_y_end);

	/* Window B x axis start and end. */
	REG_UPDATE_2(OTG_CRC0_WINDOWB_X_CONTROL,
			OTG_CRC0_WINDOWB_X_START, params->windowb_x_start,
			OTG_CRC0_WINDOWB_X_END, params->windowb_x_end);

	/* Window B y axis start and end. */
	REG_UPDATE_2(OTG_CRC0_WINDOWB_Y_CONTROL,
			OTG_CRC0_WINDOWB_Y_START, params->windowb_y_start,
			OTG_CRC0_WINDOWB_Y_END, params->windowb_y_end);

	/* Set crc mode and selection, and enable. Only using CRC0*/
	REG_UPDATE_3(OTG_CRC_CNTL,
			OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
			OTG_CRC0_SELECT, params->selection,
			OTG_CRC_EN, 1);

	return true;
}

bool optc1_get_crc(struct timing_generator *optc,
		    uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
{
	uint32_t field = 0;
	struct optc *optc1 = DCN10TG_FROM_TG(optc);

	REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);

	/* Early return if CRC is not enabled for this CRTC */
	if (!field)
		return false;

	REG_GET_2(OTG_CRC0_DATA_RG,
			CRC0_R_CR, r_cr,
			CRC0_G_Y, g_y);

	REG_GET(OTG_CRC0_DATA_B,
			CRC0_B_CB, b_cb);

	return true;
}

static const struct timing_generator_funcs dcn10_tg_funcs = {
		.validate_timing = optc1_validate_timing,
		.program_timing = optc1_program_timing,
@@ -1360,6 +1426,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
		.is_tg_enabled = optc1_is_tg_enabled,
		.is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
		.clear_optc_underflow = optc1_clear_optc_underflow,
		.get_crc = optc1_get_crc,
		.configure_crc = optc1_configure_crc,
};

void dcn10_timing_generator_init(struct optc *optc1)
+46 −3
Original line number Diff line number Diff line
@@ -75,7 +75,14 @@
	SRI(CONTROL, VTG, inst),\
	SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\
	SRI(OTG_MASTER_UPDATE_MODE, OTG, inst),\
	SRI(OTG_GSL_CONTROL, OTG, inst)
	SRI(OTG_GSL_CONTROL, OTG, inst),\
	SRI(OTG_CRC_CNTL, OTG, inst),\
	SRI(OTG_CRC0_DATA_RG, OTG, inst),\
	SRI(OTG_CRC0_DATA_B, OTG, inst),\
	SRI(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),\
	SRI(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),\
	SRI(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),\
	SRI(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst)

#define TG_COMMON_REG_LIST_DCN1_0(inst) \
	TG_COMMON_REG_LIST_DCN(inst),\
@@ -138,6 +145,13 @@ struct dcn_optc_registers {
	uint32_t OTG_GSL_WINDOW_X;
	uint32_t OTG_GSL_WINDOW_Y;
	uint32_t OTG_VUPDATE_KEEPOUT;
	uint32_t OTG_CRC_CNTL;
	uint32_t OTG_CRC0_DATA_RG;
	uint32_t OTG_CRC0_DATA_B;
	uint32_t OTG_CRC0_WINDOWA_X_CONTROL;
	uint32_t OTG_CRC0_WINDOWA_Y_CONTROL;
	uint32_t OTG_CRC0_WINDOWB_X_CONTROL;
	uint32_t OTG_CRC0_WINDOWB_Y_CONTROL;
};

#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\
@@ -232,7 +246,21 @@ struct dcn_optc_registers {
	SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\
	SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\
	SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\
	SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh)
	SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\
	SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\
	SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\
	SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\
	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\
	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\
	SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\
	SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh)


#define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
@@ -363,7 +391,22 @@ struct dcn_optc_registers {
	type OTG_MASTER_UPDATE_LOCK_GSL_EN;\
	type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\
	type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET;\
	type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN;
	type OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN;\
	type OTG_CRC_CONT_EN;\
	type OTG_CRC0_SELECT;\
	type OTG_CRC_EN;\
	type CRC0_R_CR;\
	type CRC0_G_Y;\
	type CRC0_B_CB;\
	type OTG_CRC0_WINDOWA_X_START;\
	type OTG_CRC0_WINDOWA_X_END;\
	type OTG_CRC0_WINDOWA_Y_START;\
	type OTG_CRC0_WINDOWA_Y_END;\
	type OTG_CRC0_WINDOWB_X_START;\
	type OTG_CRC0_WINDOWB_X_END;\
	type OTG_CRC0_WINDOWB_Y_START;\
	type OTG_CRC0_WINDOWB_Y_END;


#define TG_REG_FIELD_LIST(type) \
	TG_REG_FIELD_LIST_DCN1_0(type)