Commit 2c1a180a authored by Noah Abradjian's avatar Noah Abradjian Committed by Alex Deucher

drm/amd/display: Double buffer dcn2 Gamut Remap

[Why]
When rapidly adjusting color temperature, screen tearing was observed.
This was due to overwritten values in gamut remap registers.
This issue was solved for OCSC and ICSC by alternating between "A" and
"B" registers to double buffer the writes.

[How]
Create new set_gamut_remap and program_gamut_remap for dcn20.
Alternate which registers are written to by switching modes each time.
Also fixes ICSC mode reg read to use proper data offset.
Signed-off-by: default avatarNoah Abradjian <noah.abradjian@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <harry.wentland@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4c1a1335
......@@ -458,7 +458,7 @@ static struct dpp_funcs dcn20_dpp_funcs = {
.dpp_reset = dpp_reset,
.dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale,
.dpp_get_optimal_number_of_taps = dpp1_get_optimal_number_of_taps,
.dpp_set_gamut_remap = dpp1_cm_set_gamut_remap,
.dpp_set_gamut_remap = dpp2_cm_set_gamut_remap,
.dpp_set_csc_adjustment = NULL,
.dpp_set_csc_default = NULL,
.dpp_program_regamma_pwl = oppn20_dummy_program_regamma_pwl,
......
......@@ -151,6 +151,12 @@
SRI(CM_SHAPER_LUT_INDEX, CM, id)
#define TF_REG_LIST_DCN20_COMMON_APPEND(id) \
SRI(CM_GAMUT_REMAP_B_C11_C12, CM, id),\
SRI(CM_GAMUT_REMAP_B_C13_C14, CM, id),\
SRI(CM_GAMUT_REMAP_B_C21_C22, CM, id),\
SRI(CM_GAMUT_REMAP_B_C23_C24, CM, id),\
SRI(CM_GAMUT_REMAP_B_C31_C32, CM, id),\
SRI(CM_GAMUT_REMAP_B_C33_C34, CM, id),\
SRI(CM_ICSC_B_C11_C12, CM, id), \
SRI(CM_ICSC_B_C33_C34, CM, id)
......@@ -579,11 +585,14 @@
/* DPP CM debug status register:
*
* Status index including current ICSC, Gamut Remap Mode is 9
* ICSC Mode: [5..4]
* ICSC Mode: [4..3]
* Gamut Remap Mode: [10..9]
*/
#define CM_TEST_DEBUG_DATA_STATUS_IDX 9
#define CM_TEST_DEBUG_DATA_ICSC_MODE_SH 4
#define CM_TEST_DEBUG_DATA_ICSC_MODE_SH 3
#define CM_TEST_DEBUG_DATA_ICSC_MODE_MASK 0x3
#define CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE_SH 9
#define CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE_MASK 0x3
#define TF_REG_FIELD_LIST_DCN2_0(type) \
TF_REG_FIELD_LIST(type) \
......@@ -646,6 +655,12 @@ struct dcn2_dpp_mask {
uint32_t DSCL_MEM_PWR_CTRL
#define DPP_DCN2_REG_VARIABLE_LIST_CM_APPEND \
uint32_t CM_GAMUT_REMAP_B_C11_C12; \
uint32_t CM_GAMUT_REMAP_B_C13_C14; \
uint32_t CM_GAMUT_REMAP_B_C21_C22; \
uint32_t CM_GAMUT_REMAP_B_C23_C24; \
uint32_t CM_GAMUT_REMAP_B_C31_C32; \
uint32_t CM_GAMUT_REMAP_B_C33_C34; \
uint32_t CM_ICSC_B_C11_C12; \
uint32_t CM_ICSC_B_C33_C34
......@@ -679,6 +694,12 @@ enum dcn20_input_csc_select {
DCN2_ICSC_SELECT_ICSC_B = 2
};
enum dcn20_gamut_remap_select {
DCN2_GAMUT_REMAP_BYPASS = 0,
DCN2_GAMUT_REMAP_COEF_A = 1,
DCN2_GAMUT_REMAP_COEF_B = 2
};
void dpp20_read_state(struct dpp *dpp_base,
struct dcn_dpp_state *s);
......@@ -690,6 +711,10 @@ void dpp2_set_degamma(
struct dpp *dpp_base,
enum ipp_degamma_mode mode);
void dpp2_cm_set_gamut_remap(
struct dpp *dpp_base,
const struct dpp_grph_csc_adjustment *adjust);
void dpp2_program_input_csc(
struct dpp *dpp_base,
enum dc_color_space color_space,
......
......@@ -158,6 +158,85 @@ void dpp2_set_degamma(
}
}
static void program_gamut_remap(
struct dcn20_dpp *dpp,
const uint16_t *regval,
enum dcn20_gamut_remap_select select)
{
uint32_t cur_select = 0;
struct color_matrices_reg gam_regs;
if (regval == NULL || select == DCN2_GAMUT_REMAP_BYPASS) {
REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
CM_GAMUT_REMAP_MODE, 0);
return;
}
/* determine which gamut_remap coefficients (A or B) we are using
* currently. select the alternate set to double buffer
* the update so gamut_remap is updated on frame boundary
*/
cur_select = IX_REG_READ(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
CM_TEST_DEBUG_DATA_STATUS_IDX);
/* IX_REG_READ reads whole reg, so isolate part we want [10..9] */
cur_select = (cur_select >> CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE_SH)
& CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE_MASK;
/* value stored in dbg reg will be 1 greater than mode we want */
if (cur_select != DCN2_GAMUT_REMAP_COEF_A)
select = DCN2_GAMUT_REMAP_COEF_A;
else
select = DCN2_GAMUT_REMAP_COEF_B;
gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11;
gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
if (select == DCN2_GAMUT_REMAP_COEF_A) {
gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
} else {
gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
}
cm_helper_program_color_matrices(
dpp->base.ctx,
regval,
&gam_regs);
REG_SET(
CM_GAMUT_REMAP_CONTROL, 0,
CM_GAMUT_REMAP_MODE, select);
}
void dpp2_cm_set_gamut_remap(
struct dpp *dpp_base,
const struct dpp_grph_csc_adjustment *adjust)
{
struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
int i = 0;
if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
/* Bypass if type is bypass or hw */
program_gamut_remap(dpp, NULL, DCN2_GAMUT_REMAP_BYPASS);
else {
struct fixed31_32 arr_matrix[12];
uint16_t arr_reg_val[12];
for (i = 0; i < 12; i++)
arr_matrix[i] = adjust->temperature_matrix[i];
convert_float_matrix(
arr_reg_val, arr_matrix, 12);
program_gamut_remap(dpp, arr_reg_val, DCN2_GAMUT_REMAP_COEF_A);
}
}
void dpp2_program_input_csc(
struct dpp *dpp_base,
enum dc_color_space color_space,
......@@ -199,12 +278,11 @@ void dpp2_program_input_csc(
cur_select = IX_REG_READ(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
CM_TEST_DEBUG_DATA_STATUS_IDX);
/* IX_REG_READ reads whole reg, so isolate part we want [5..4] */
/* IX_REG_READ reads whole reg, so isolate part we want [4..3] */
cur_select = (cur_select >> CM_TEST_DEBUG_DATA_ICSC_MODE_SH)
& CM_TEST_DEBUG_DATA_ICSC_MODE_MASK;
/* value stored in dbg reg will be 1 greater than mode we want */
if (cur_select - 1 != DCN2_ICSC_SELECT_ICSC_A)
if (cur_select != DCN2_ICSC_SELECT_ICSC_A)
select = DCN2_ICSC_SELECT_ICSC_A;
else
select = DCN2_ICSC_SELECT_ICSC_B;
......
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