0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027 #include "core_types.h"
0028 #include "reg_helper.h"
0029 #include "dcn30_dpp.h"
0030 #include "basics/conversion.h"
0031 #include "dcn30_cm_common.h"
0032
0033 #define REG(reg)\
0034 dpp->tf_regs->reg
0035
0036 #define CTX \
0037 dpp->base.ctx
0038
0039 #undef FN
0040 #define FN(reg_name, field_name) \
0041 dpp->tf_shift->field_name, dpp->tf_mask->field_name
0042
0043 static void dpp3_enable_cm_block(
0044 struct dpp *dpp_base)
0045 {
0046 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0047
0048 unsigned int cm_bypass_mode = 0;
0049
0050
0051 if (dpp_base->ctx->dc->debug.cm_in_bypass)
0052 cm_bypass_mode = 1;
0053
0054 REG_UPDATE(CM_CONTROL, CM_BYPASS, cm_bypass_mode);
0055 }
0056
0057 static enum dc_lut_mode dpp30_get_gamcor_current(struct dpp *dpp_base)
0058 {
0059 enum dc_lut_mode mode;
0060 uint32_t state_mode;
0061 uint32_t lut_mode;
0062 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0063
0064 REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, &state_mode);
0065
0066 if (state_mode == 0)
0067 mode = LUT_BYPASS;
0068
0069 if (state_mode == 2) {
0070 REG_GET(CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, &lut_mode);
0071 if (lut_mode == 0)
0072 mode = LUT_RAM_A;
0073 else
0074 mode = LUT_RAM_B;
0075 }
0076
0077 return mode;
0078 }
0079
0080 static void dpp3_program_gammcor_lut(
0081 struct dpp *dpp_base,
0082 const struct pwl_result_data *rgb,
0083 uint32_t num,
0084 bool is_ram_a)
0085 {
0086 uint32_t i;
0087 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0088 uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
0089 uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
0090 uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
0091
0092
0093
0094
0095 if (is_rgb_equal(rgb, num)) {
0096 for (i = 0 ; i < num; i++)
0097 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].red_reg);
0098
0099 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_red);
0100
0101 } else {
0102 REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
0103 CM_GAMCOR_LUT_WRITE_COLOR_MASK, 4);
0104 for (i = 0 ; i < num; i++)
0105 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].red_reg);
0106
0107 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_red);
0108
0109 REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0);
0110
0111 REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
0112 CM_GAMCOR_LUT_WRITE_COLOR_MASK, 2);
0113 for (i = 0 ; i < num; i++)
0114 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].green_reg);
0115
0116 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_green);
0117
0118 REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0);
0119
0120 REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
0121 CM_GAMCOR_LUT_WRITE_COLOR_MASK, 1);
0122 for (i = 0 ; i < num; i++)
0123 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, rgb[i].blue_reg);
0124
0125 REG_SET(CM_GAMCOR_LUT_DATA, 0, CM_GAMCOR_LUT_DATA, last_base_value_blue);
0126 }
0127 }
0128
0129 static void dpp3_power_on_gamcor_lut(
0130 struct dpp *dpp_base,
0131 bool power_on)
0132 {
0133 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0134
0135 if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
0136 if (power_on) {
0137 REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0);
0138 REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5);
0139 } else {
0140 dpp_base->ctx->dc->optimized_required = true;
0141 dpp_base->deferred_reg_writes.bits.disable_gamcor = true;
0142 }
0143 } else
0144 REG_SET(CM_MEM_PWR_CTRL, 0,
0145 GAMCOR_MEM_PWR_DIS, power_on == true ? 0:1);
0146 }
0147
0148 void dpp3_program_cm_dealpha(
0149 struct dpp *dpp_base,
0150 uint32_t enable, uint32_t additive_blending)
0151 {
0152 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0153
0154 REG_SET_2(CM_DEALPHA, 0,
0155 CM_DEALPHA_EN, enable,
0156 CM_DEALPHA_ABLND, additive_blending);
0157 }
0158
0159 void dpp3_program_cm_bias(
0160 struct dpp *dpp_base,
0161 struct CM_bias_params *bias_params)
0162 {
0163 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0164
0165 REG_SET(CM_BIAS_CR_R, 0, CM_BIAS_CR_R, bias_params->cm_bias_cr_r);
0166 REG_SET_2(CM_BIAS_Y_G_CB_B, 0,
0167 CM_BIAS_Y_G, bias_params->cm_bias_y_g,
0168 CM_BIAS_CB_B, bias_params->cm_bias_cb_b);
0169 }
0170
0171 static void dpp3_gamcor_reg_field(
0172 struct dcn3_dpp *dpp,
0173 struct dcn3_xfer_func_reg *reg)
0174 {
0175
0176 reg->shifts.field_region_start_base = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B;
0177 reg->masks.field_region_start_base = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B;
0178 reg->shifts.field_offset = dpp->tf_shift->CM_GAMCOR_RAMA_OFFSET_B;
0179 reg->masks.field_offset = dpp->tf_mask->CM_GAMCOR_RAMA_OFFSET_B;
0180
0181 reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET;
0182 reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET;
0183 reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS;
0184 reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS;
0185 reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET;
0186 reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET;
0187 reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;
0188 reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS;
0189
0190 reg->shifts.field_region_end = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_B;
0191 reg->masks.field_region_end = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_B;
0192 reg->shifts.field_region_end_slope = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B;
0193 reg->masks.field_region_end_slope = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B;
0194 reg->shifts.field_region_end_base = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B;
0195 reg->masks.field_region_end_base = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B;
0196 reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B;
0197 reg->masks.field_region_linear_slope = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B;
0198 reg->shifts.exp_region_start = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_B;
0199 reg->masks.exp_region_start = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_B;
0200 reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B;
0201 reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B;
0202 }
0203
0204 static void dpp3_configure_gamcor_lut(
0205 struct dpp *dpp_base,
0206 bool is_ram_a)
0207 {
0208 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0209
0210 REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
0211 CM_GAMCOR_LUT_WRITE_COLOR_MASK, 7);
0212 REG_UPDATE(CM_GAMCOR_LUT_CONTROL,
0213 CM_GAMCOR_LUT_HOST_SEL, is_ram_a == true ? 0:1);
0214 REG_SET(CM_GAMCOR_LUT_INDEX, 0, CM_GAMCOR_LUT_INDEX, 0);
0215 }
0216
0217
0218 bool dpp3_program_gamcor_lut(
0219 struct dpp *dpp_base, const struct pwl_params *params)
0220 {
0221 enum dc_lut_mode current_mode;
0222 enum dc_lut_mode next_mode;
0223 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0224 struct dcn3_xfer_func_reg gam_regs;
0225
0226 dpp3_enable_cm_block(dpp_base);
0227
0228 if (params == NULL) {
0229 REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 0);
0230 if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm)
0231 dpp3_power_on_gamcor_lut(dpp_base, false);
0232 return false;
0233 }
0234 dpp3_power_on_gamcor_lut(dpp_base, true);
0235 REG_SET(CM_GAMCOR_CONTROL, 0, CM_GAMCOR_MODE, 2);
0236
0237 current_mode = dpp30_get_gamcor_current(dpp_base);
0238 if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
0239 next_mode = LUT_RAM_B;
0240 else
0241 next_mode = LUT_RAM_A;
0242
0243 dpp3_power_on_gamcor_lut(dpp_base, true);
0244 dpp3_configure_gamcor_lut(dpp_base, next_mode == LUT_RAM_A);
0245
0246 if (next_mode == LUT_RAM_B) {
0247 gam_regs.start_cntl_b = REG(CM_GAMCOR_RAMB_START_CNTL_B);
0248 gam_regs.start_cntl_g = REG(CM_GAMCOR_RAMB_START_CNTL_G);
0249 gam_regs.start_cntl_r = REG(CM_GAMCOR_RAMB_START_CNTL_R);
0250 gam_regs.start_slope_cntl_b = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B);
0251 gam_regs.start_slope_cntl_g = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G);
0252 gam_regs.start_slope_cntl_r = REG(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R);
0253 gam_regs.start_end_cntl1_b = REG(CM_GAMCOR_RAMB_END_CNTL1_B);
0254 gam_regs.start_end_cntl2_b = REG(CM_GAMCOR_RAMB_END_CNTL2_B);
0255 gam_regs.start_end_cntl1_g = REG(CM_GAMCOR_RAMB_END_CNTL1_G);
0256 gam_regs.start_end_cntl2_g = REG(CM_GAMCOR_RAMB_END_CNTL2_G);
0257 gam_regs.start_end_cntl1_r = REG(CM_GAMCOR_RAMB_END_CNTL1_R);
0258 gam_regs.start_end_cntl2_r = REG(CM_GAMCOR_RAMB_END_CNTL2_R);
0259 gam_regs.region_start = REG(CM_GAMCOR_RAMB_REGION_0_1);
0260 gam_regs.region_end = REG(CM_GAMCOR_RAMB_REGION_32_33);
0261
0262 gam_regs.offset_b = REG(CM_GAMCOR_RAMB_OFFSET_B);
0263 gam_regs.offset_g = REG(CM_GAMCOR_RAMB_OFFSET_G);
0264 gam_regs.offset_r = REG(CM_GAMCOR_RAMB_OFFSET_R);
0265 gam_regs.start_base_cntl_b = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_B);
0266 gam_regs.start_base_cntl_g = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_G);
0267 gam_regs.start_base_cntl_r = REG(CM_GAMCOR_RAMB_START_BASE_CNTL_R);
0268 } else {
0269 gam_regs.start_cntl_b = REG(CM_GAMCOR_RAMA_START_CNTL_B);
0270 gam_regs.start_cntl_g = REG(CM_GAMCOR_RAMA_START_CNTL_G);
0271 gam_regs.start_cntl_r = REG(CM_GAMCOR_RAMA_START_CNTL_R);
0272 gam_regs.start_slope_cntl_b = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B);
0273 gam_regs.start_slope_cntl_g = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G);
0274 gam_regs.start_slope_cntl_r = REG(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R);
0275 gam_regs.start_end_cntl1_b = REG(CM_GAMCOR_RAMA_END_CNTL1_B);
0276 gam_regs.start_end_cntl2_b = REG(CM_GAMCOR_RAMA_END_CNTL2_B);
0277 gam_regs.start_end_cntl1_g = REG(CM_GAMCOR_RAMA_END_CNTL1_G);
0278 gam_regs.start_end_cntl2_g = REG(CM_GAMCOR_RAMA_END_CNTL2_G);
0279 gam_regs.start_end_cntl1_r = REG(CM_GAMCOR_RAMA_END_CNTL1_R);
0280 gam_regs.start_end_cntl2_r = REG(CM_GAMCOR_RAMA_END_CNTL2_R);
0281 gam_regs.region_start = REG(CM_GAMCOR_RAMA_REGION_0_1);
0282 gam_regs.region_end = REG(CM_GAMCOR_RAMA_REGION_32_33);
0283
0284 gam_regs.offset_b = REG(CM_GAMCOR_RAMA_OFFSET_B);
0285 gam_regs.offset_g = REG(CM_GAMCOR_RAMA_OFFSET_G);
0286 gam_regs.offset_r = REG(CM_GAMCOR_RAMA_OFFSET_R);
0287 gam_regs.start_base_cntl_b = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_B);
0288 gam_regs.start_base_cntl_g = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_G);
0289 gam_regs.start_base_cntl_r = REG(CM_GAMCOR_RAMA_START_BASE_CNTL_R);
0290 }
0291
0292
0293 dpp3_gamcor_reg_field(dpp, &gam_regs);
0294
0295
0296 cm_helper_program_gamcor_xfer_func(dpp_base->ctx, params, &gam_regs);
0297
0298 dpp3_program_gammcor_lut(dpp_base, params->rgb_resulted, params->hw_points_num,
0299 next_mode == LUT_RAM_A);
0300
0301
0302 REG_UPDATE(CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, next_mode == LUT_RAM_A ? 0:1);
0303
0304 return true;
0305 }
0306
0307 void dpp3_set_hdr_multiplier(
0308 struct dpp *dpp_base,
0309 uint32_t multiplier)
0310 {
0311 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0312
0313 REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
0314 }
0315
0316
0317 static void program_gamut_remap(
0318 struct dcn3_dpp *dpp,
0319 const uint16_t *regval,
0320 int select)
0321 {
0322 uint16_t selection = 0;
0323 struct color_matrices_reg gam_regs;
0324
0325 if (regval == NULL || select == GAMUT_REMAP_BYPASS) {
0326 REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
0327 CM_GAMUT_REMAP_MODE, 0);
0328 return;
0329 }
0330 switch (select) {
0331 case GAMUT_REMAP_COEFF:
0332 selection = 1;
0333 break;
0334
0335
0336
0337 case GAMUT_REMAP_COMA_COEFF:
0338 selection = 2;
0339 break;
0340 default:
0341 break;
0342 }
0343
0344 gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
0345 gam_regs.masks.csc_c11 = dpp->tf_mask->CM_GAMUT_REMAP_C11;
0346 gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
0347 gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
0348
0349
0350 if (select == GAMUT_REMAP_COEFF) {
0351 gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
0352 gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
0353
0354 cm_helper_program_color_matrices(
0355 dpp->base.ctx,
0356 regval,
0357 &gam_regs);
0358
0359 } else if (select == GAMUT_REMAP_COMA_COEFF) {
0360
0361 gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
0362 gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
0363
0364 cm_helper_program_color_matrices(
0365 dpp->base.ctx,
0366 regval,
0367 &gam_regs);
0368
0369 }
0370
0371 REG_SET(
0372 CM_GAMUT_REMAP_CONTROL, 0,
0373 CM_GAMUT_REMAP_MODE, selection);
0374 }
0375
0376 void dpp3_cm_set_gamut_remap(
0377 struct dpp *dpp_base,
0378 const struct dpp_grph_csc_adjustment *adjust)
0379 {
0380 struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
0381 int i = 0;
0382 int gamut_mode;
0383
0384 if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
0385
0386 program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS);
0387 else {
0388 struct fixed31_32 arr_matrix[12];
0389 uint16_t arr_reg_val[12];
0390
0391 for (i = 0; i < 12; i++)
0392 arr_matrix[i] = adjust->temperature_matrix[i];
0393
0394 convert_float_matrix(
0395 arr_reg_val, arr_matrix, 12);
0396
0397
0398 REG_GET(CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE_CURRENT, &gamut_mode);
0399
0400 if (gamut_mode == 0)
0401 gamut_mode = 1;
0402 else if (gamut_mode == 1)
0403 gamut_mode = 2;
0404 else
0405 gamut_mode = 1;
0406
0407
0408 program_gamut_remap(dpp, arr_reg_val, gamut_mode);
0409 }
0410 }