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

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
...@@ -1324,6 +1324,72 @@ bool optc1_is_optc_underflow_occurred(struct timing_generator *optc) ...@@ -1324,6 +1324,72 @@ bool optc1_is_optc_underflow_occurred(struct timing_generator *optc)
return (underflow_occurred == 1); 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 = { static const struct timing_generator_funcs dcn10_tg_funcs = {
.validate_timing = optc1_validate_timing, .validate_timing = optc1_validate_timing,
.program_timing = optc1_program_timing, .program_timing = optc1_program_timing,
...@@ -1360,6 +1426,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { ...@@ -1360,6 +1426,8 @@ static const struct timing_generator_funcs dcn10_tg_funcs = {
.is_tg_enabled = optc1_is_tg_enabled, .is_tg_enabled = optc1_is_tg_enabled,
.is_optc_underflow_occurred = optc1_is_optc_underflow_occurred, .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
.clear_optc_underflow = optc1_clear_optc_underflow, .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) void dcn10_timing_generator_init(struct optc *optc1)
......
...@@ -75,7 +75,14 @@ ...@@ -75,7 +75,14 @@
SRI(CONTROL, VTG, inst),\ SRI(CONTROL, VTG, inst),\
SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\ SRI(OTG_VERT_SYNC_CONTROL, OTG, inst),\
SRI(OTG_MASTER_UPDATE_MODE, 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) \ #define TG_COMMON_REG_LIST_DCN1_0(inst) \
TG_COMMON_REG_LIST_DCN(inst),\ TG_COMMON_REG_LIST_DCN(inst),\
...@@ -138,6 +145,13 @@ struct dcn_optc_registers { ...@@ -138,6 +145,13 @@ struct dcn_optc_registers {
uint32_t OTG_GSL_WINDOW_X; uint32_t OTG_GSL_WINDOW_X;
uint32_t OTG_GSL_WINDOW_Y; uint32_t OTG_GSL_WINDOW_Y;
uint32_t OTG_VUPDATE_KEEPOUT; 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)\ #define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\
...@@ -232,7 +246,21 @@ struct dcn_optc_registers { ...@@ -232,7 +246,21 @@ struct dcn_optc_registers {
SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\ 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_MASTER_EN, mask_sh),\
SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, 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)\ #define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\
...@@ -363,7 +391,22 @@ struct dcn_optc_registers { ...@@ -363,7 +391,22 @@ struct dcn_optc_registers {
type OTG_MASTER_UPDATE_LOCK_GSL_EN;\ type OTG_MASTER_UPDATE_LOCK_GSL_EN;\
type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\ type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET;\
type MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_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) \ #define TG_REG_FIELD_LIST(type) \
TG_REG_FIELD_LIST_DCN1_0(type) TG_REG_FIELD_LIST_DCN1_0(type)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment