Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2016 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dm_services.h"
0027 
0028 #include "core_types.h"
0029 
0030 #include "reg_helper.h"
0031 #include "dcn10_dpp.h"
0032 #include "basics/conversion.h"
0033 #include "dcn10_cm_common.h"
0034 
0035 #define NUM_PHASES    64
0036 #define HORZ_MAX_TAPS 8
0037 #define VERT_MAX_TAPS 8
0038 
0039 #define BLACK_OFFSET_RGB_Y 0x0
0040 #define BLACK_OFFSET_CBCR  0x8000
0041 
0042 #define REG(reg)\
0043     dpp->tf_regs->reg
0044 
0045 #define CTX \
0046     dpp->base.ctx
0047 
0048 #undef FN
0049 #define FN(reg_name, field_name) \
0050     dpp->tf_shift->field_name, dpp->tf_mask->field_name
0051 
0052 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
0053 
0054 
0055 enum dcn10_coef_filter_type_sel {
0056     SCL_COEF_LUMA_VERT_FILTER = 0,
0057     SCL_COEF_LUMA_HORZ_FILTER = 1,
0058     SCL_COEF_CHROMA_VERT_FILTER = 2,
0059     SCL_COEF_CHROMA_HORZ_FILTER = 3,
0060     SCL_COEF_ALPHA_VERT_FILTER = 4,
0061     SCL_COEF_ALPHA_HORZ_FILTER = 5
0062 };
0063 
0064 enum dscl_autocal_mode {
0065     AUTOCAL_MODE_OFF = 0,
0066 
0067     /* Autocal calculate the scaling ratio and initial phase and the
0068      * DSCL_MODE_SEL must be set to 1
0069      */
0070     AUTOCAL_MODE_AUTOSCALE = 1,
0071     /* Autocal perform auto centering without replication and the
0072      * DSCL_MODE_SEL must be set to 0
0073      */
0074     AUTOCAL_MODE_AUTOCENTER = 2,
0075     /* Autocal perform auto centering and auto replication and the
0076      * DSCL_MODE_SEL must be set to 0
0077      */
0078     AUTOCAL_MODE_AUTOREPLICATE = 3
0079 };
0080 
0081 enum dscl_mode_sel {
0082     DSCL_MODE_SCALING_444_BYPASS = 0,
0083     DSCL_MODE_SCALING_444_RGB_ENABLE = 1,
0084     DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2,
0085     DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3,
0086     DSCL_MODE_SCALING_420_LUMA_BYPASS = 4,
0087     DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5,
0088     DSCL_MODE_DSCL_BYPASS = 6
0089 };
0090 
0091 static void program_gamut_remap(
0092         struct dcn10_dpp *dpp,
0093         const uint16_t *regval,
0094         enum gamut_remap_select select)
0095 {
0096     uint16_t selection = 0;
0097     struct color_matrices_reg gam_regs;
0098 
0099     if (regval == NULL || select == GAMUT_REMAP_BYPASS) {
0100         REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
0101                 CM_GAMUT_REMAP_MODE, 0);
0102         return;
0103     }
0104     switch (select) {
0105     case GAMUT_REMAP_COEFF:
0106         selection = 1;
0107         break;
0108     case GAMUT_REMAP_COMA_COEFF:
0109         selection = 2;
0110         break;
0111     case GAMUT_REMAP_COMB_COEFF:
0112         selection = 3;
0113         break;
0114     default:
0115         break;
0116     }
0117 
0118     gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
0119     gam_regs.masks.csc_c11  = dpp->tf_mask->CM_GAMUT_REMAP_C11;
0120     gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
0121     gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
0122 
0123 
0124     if (select == GAMUT_REMAP_COEFF) {
0125         gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
0126         gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
0127 
0128         cm_helper_program_color_matrices(
0129                 dpp->base.ctx,
0130                 regval,
0131                 &gam_regs);
0132 
0133     } else  if (select == GAMUT_REMAP_COMA_COEFF) {
0134 
0135         gam_regs.csc_c11_c12 = REG(CM_COMA_C11_C12);
0136         gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34);
0137 
0138         cm_helper_program_color_matrices(
0139                 dpp->base.ctx,
0140                 regval,
0141                 &gam_regs);
0142 
0143     } else {
0144 
0145         gam_regs.csc_c11_c12 = REG(CM_COMB_C11_C12);
0146         gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34);
0147 
0148         cm_helper_program_color_matrices(
0149                 dpp->base.ctx,
0150                 regval,
0151                 &gam_regs);
0152     }
0153 
0154     REG_SET(
0155             CM_GAMUT_REMAP_CONTROL, 0,
0156             CM_GAMUT_REMAP_MODE, selection);
0157 
0158 }
0159 
0160 void dpp1_cm_set_gamut_remap(
0161     struct dpp *dpp_base,
0162     const struct dpp_grph_csc_adjustment *adjust)
0163 {
0164     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0165     int i = 0;
0166 
0167     if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
0168         /* Bypass if type is bypass or hw */
0169         program_gamut_remap(dpp, NULL, GAMUT_REMAP_BYPASS);
0170     else {
0171         struct fixed31_32 arr_matrix[12];
0172         uint16_t arr_reg_val[12];
0173 
0174         for (i = 0; i < 12; i++)
0175             arr_matrix[i] = adjust->temperature_matrix[i];
0176 
0177         convert_float_matrix(
0178             arr_reg_val, arr_matrix, 12);
0179 
0180         program_gamut_remap(dpp, arr_reg_val, GAMUT_REMAP_COEFF);
0181     }
0182 }
0183 
0184 static void dpp1_cm_program_color_matrix(
0185         struct dcn10_dpp *dpp,
0186         const uint16_t *regval)
0187 {
0188     uint32_t ocsc_mode;
0189     uint32_t cur_mode;
0190     struct color_matrices_reg gam_regs;
0191 
0192     if (regval == NULL) {
0193         BREAK_TO_DEBUGGER();
0194         return;
0195     }
0196 
0197     /* determine which CSC matrix (ocsc or comb) we are using
0198      * currently.  select the alternate set to double buffer
0199      * the CSC update so CSC is updated on frame boundary
0200      */
0201     REG_SET(CM_TEST_DEBUG_INDEX, 0,
0202             CM_TEST_DEBUG_INDEX, 9);
0203 
0204     REG_GET(CM_TEST_DEBUG_DATA,
0205             CM_TEST_DEBUG_DATA_ID9_OCSC_MODE, &cur_mode);
0206 
0207     if (cur_mode != 4)
0208         ocsc_mode = 4;
0209     else
0210         ocsc_mode = 5;
0211 
0212 
0213     gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_OCSC_C11;
0214     gam_regs.masks.csc_c11  = dpp->tf_mask->CM_OCSC_C11;
0215     gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_OCSC_C12;
0216     gam_regs.masks.csc_c12 = dpp->tf_mask->CM_OCSC_C12;
0217 
0218     if (ocsc_mode == 4) {
0219 
0220         gam_regs.csc_c11_c12 = REG(CM_OCSC_C11_C12);
0221         gam_regs.csc_c33_c34 = REG(CM_OCSC_C33_C34);
0222 
0223     } else {
0224 
0225         gam_regs.csc_c11_c12 = REG(CM_COMB_C11_C12);
0226         gam_regs.csc_c33_c34 = REG(CM_COMB_C33_C34);
0227 
0228     }
0229 
0230     cm_helper_program_color_matrices(
0231             dpp->base.ctx,
0232             regval,
0233             &gam_regs);
0234 
0235     REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode);
0236 
0237 }
0238 
0239 void dpp1_cm_set_output_csc_default(
0240         struct dpp *dpp_base,
0241         enum dc_color_space colorspace)
0242 {
0243     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0244     const uint16_t *regval = NULL;
0245     int arr_size;
0246 
0247     regval = find_color_matrix(colorspace, &arr_size);
0248     if (regval == NULL) {
0249         BREAK_TO_DEBUGGER();
0250         return;
0251     }
0252 
0253     dpp1_cm_program_color_matrix(dpp, regval);
0254 }
0255 
0256 static void dpp1_cm_get_reg_field(
0257         struct dcn10_dpp *dpp,
0258         struct xfer_func_reg *reg)
0259 {
0260     reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0261     reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0262     reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0263     reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0264     reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0265     reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0266     reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0267     reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0268 
0269     reg->shifts.field_region_end = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_B;
0270     reg->masks.field_region_end = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_B;
0271     reg->shifts.field_region_end_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B;
0272     reg->masks.field_region_end_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B;
0273     reg->shifts.field_region_end_base = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_END_BASE_B;
0274     reg->masks.field_region_end_base = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_END_BASE_B;
0275     reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B;
0276     reg->masks.field_region_linear_slope = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B;
0277     reg->shifts.exp_region_start = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_B;
0278     reg->masks.exp_region_start = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_B;
0279     reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B;
0280     reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B;
0281 }
0282 
0283 static void dpp1_cm_get_degamma_reg_field(
0284         struct dcn10_dpp *dpp,
0285         struct xfer_func_reg *reg)
0286 {
0287     reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0288     reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0289     reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0290     reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0291     reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0292     reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0293     reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0294     reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_DGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0295 
0296     reg->shifts.field_region_end = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_END_B;
0297     reg->masks.field_region_end = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_END_B;
0298     reg->shifts.field_region_end_slope = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B;
0299     reg->masks.field_region_end_slope = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_END_SLOPE_B;
0300     reg->shifts.field_region_end_base = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_END_BASE_B;
0301     reg->masks.field_region_end_base = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_END_BASE_B;
0302     reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B;
0303     reg->masks.field_region_linear_slope = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B;
0304     reg->shifts.exp_region_start = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_START_B;
0305     reg->masks.exp_region_start = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_START_B;
0306     reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B;
0307     reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_DGAM_RAMB_EXP_REGION_START_SEGMENT_B;
0308 }
0309 void dpp1_cm_set_output_csc_adjustment(
0310         struct dpp *dpp_base,
0311         const uint16_t *regval)
0312 {
0313     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0314 
0315     dpp1_cm_program_color_matrix(dpp, regval);
0316 }
0317 
0318 void dpp1_cm_power_on_regamma_lut(struct dpp *dpp_base,
0319                   bool power_on)
0320 {
0321     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0322 
0323     REG_SET(CM_MEM_PWR_CTRL, 0,
0324         RGAM_MEM_PWR_FORCE, power_on == true ? 0:1);
0325 
0326 }
0327 
0328 void dpp1_cm_program_regamma_lut(struct dpp *dpp_base,
0329                  const struct pwl_result_data *rgb,
0330                  uint32_t num)
0331 {
0332     uint32_t i;
0333     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0334 
0335     REG_SEQ_START();
0336 
0337     for (i = 0 ; i < num; i++) {
0338         REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg);
0339         REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg);
0340         REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg);
0341 
0342         REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_red_reg);
0343         REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_green_reg);
0344         REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg);
0345 
0346     }
0347 
0348 }
0349 
0350 void dpp1_cm_configure_regamma_lut(
0351         struct dpp *dpp_base,
0352         bool is_ram_a)
0353 {
0354     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0355 
0356     REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK,
0357             CM_RGAM_LUT_WRITE_EN_MASK, 7);
0358     REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK,
0359             CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
0360     REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0);
0361 }
0362 
0363 /*program re gamma RAM A*/
0364 void dpp1_cm_program_regamma_luta_settings(
0365         struct dpp *dpp_base,
0366         const struct pwl_params *params)
0367 {
0368     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0369     struct xfer_func_reg gam_regs;
0370 
0371     dpp1_cm_get_reg_field(dpp, &gam_regs);
0372 
0373     gam_regs.start_cntl_b = REG(CM_RGAM_RAMA_START_CNTL_B);
0374     gam_regs.start_cntl_g = REG(CM_RGAM_RAMA_START_CNTL_G);
0375     gam_regs.start_cntl_r = REG(CM_RGAM_RAMA_START_CNTL_R);
0376     gam_regs.start_slope_cntl_b = REG(CM_RGAM_RAMA_SLOPE_CNTL_B);
0377     gam_regs.start_slope_cntl_g = REG(CM_RGAM_RAMA_SLOPE_CNTL_G);
0378     gam_regs.start_slope_cntl_r = REG(CM_RGAM_RAMA_SLOPE_CNTL_R);
0379     gam_regs.start_end_cntl1_b = REG(CM_RGAM_RAMA_END_CNTL1_B);
0380     gam_regs.start_end_cntl2_b = REG(CM_RGAM_RAMA_END_CNTL2_B);
0381     gam_regs.start_end_cntl1_g = REG(CM_RGAM_RAMA_END_CNTL1_G);
0382     gam_regs.start_end_cntl2_g = REG(CM_RGAM_RAMA_END_CNTL2_G);
0383     gam_regs.start_end_cntl1_r = REG(CM_RGAM_RAMA_END_CNTL1_R);
0384     gam_regs.start_end_cntl2_r = REG(CM_RGAM_RAMA_END_CNTL2_R);
0385     gam_regs.region_start = REG(CM_RGAM_RAMA_REGION_0_1);
0386     gam_regs.region_end = REG(CM_RGAM_RAMA_REGION_32_33);
0387 
0388     cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
0389 
0390 }
0391 
0392 /*program re gamma RAM B*/
0393 void dpp1_cm_program_regamma_lutb_settings(
0394         struct dpp *dpp_base,
0395         const struct pwl_params *params)
0396 {
0397     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0398     struct xfer_func_reg gam_regs;
0399 
0400     dpp1_cm_get_reg_field(dpp, &gam_regs);
0401 
0402     gam_regs.start_cntl_b = REG(CM_RGAM_RAMB_START_CNTL_B);
0403     gam_regs.start_cntl_g = REG(CM_RGAM_RAMB_START_CNTL_G);
0404     gam_regs.start_cntl_r = REG(CM_RGAM_RAMB_START_CNTL_R);
0405     gam_regs.start_slope_cntl_b = REG(CM_RGAM_RAMB_SLOPE_CNTL_B);
0406     gam_regs.start_slope_cntl_g = REG(CM_RGAM_RAMB_SLOPE_CNTL_G);
0407     gam_regs.start_slope_cntl_r = REG(CM_RGAM_RAMB_SLOPE_CNTL_R);
0408     gam_regs.start_end_cntl1_b = REG(CM_RGAM_RAMB_END_CNTL1_B);
0409     gam_regs.start_end_cntl2_b = REG(CM_RGAM_RAMB_END_CNTL2_B);
0410     gam_regs.start_end_cntl1_g = REG(CM_RGAM_RAMB_END_CNTL1_G);
0411     gam_regs.start_end_cntl2_g = REG(CM_RGAM_RAMB_END_CNTL2_G);
0412     gam_regs.start_end_cntl1_r = REG(CM_RGAM_RAMB_END_CNTL1_R);
0413     gam_regs.start_end_cntl2_r = REG(CM_RGAM_RAMB_END_CNTL2_R);
0414     gam_regs.region_start = REG(CM_RGAM_RAMB_REGION_0_1);
0415     gam_regs.region_end = REG(CM_RGAM_RAMB_REGION_32_33);
0416 
0417     cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
0418 }
0419 
0420 void dpp1_program_input_csc(
0421         struct dpp *dpp_base,
0422         enum dc_color_space color_space,
0423         enum dcn10_input_csc_select input_select,
0424         const struct out_csc_color_matrix *tbl_entry)
0425 {
0426     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0427     int i;
0428     int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
0429     const uint16_t *regval = NULL;
0430     uint32_t cur_select = 0;
0431     enum dcn10_input_csc_select select;
0432     struct color_matrices_reg gam_regs;
0433 
0434     if (input_select == INPUT_CSC_SELECT_BYPASS) {
0435         REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
0436         return;
0437     }
0438 
0439     if (tbl_entry == NULL) {
0440         for (i = 0; i < arr_size; i++)
0441             if (dpp_input_csc_matrix[i].color_space == color_space) {
0442                 regval = dpp_input_csc_matrix[i].regval;
0443                 break;
0444             }
0445 
0446         if (regval == NULL) {
0447             BREAK_TO_DEBUGGER();
0448             return;
0449         }
0450     } else {
0451         regval = tbl_entry->regval;
0452     }
0453 
0454     /* determine which CSC matrix (icsc or coma) we are using
0455      * currently.  select the alternate set to double buffer
0456      * the CSC update so CSC is updated on frame boundary
0457      */
0458     REG_SET(CM_TEST_DEBUG_INDEX, 0,
0459             CM_TEST_DEBUG_INDEX, 9);
0460 
0461     REG_GET(CM_TEST_DEBUG_DATA,
0462             CM_TEST_DEBUG_DATA_ID9_ICSC_MODE, &cur_select);
0463 
0464     if (cur_select != INPUT_CSC_SELECT_ICSC)
0465         select = INPUT_CSC_SELECT_ICSC;
0466     else
0467         select = INPUT_CSC_SELECT_COMA;
0468 
0469     gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11;
0470     gam_regs.masks.csc_c11  = dpp->tf_mask->CM_ICSC_C11;
0471     gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12;
0472     gam_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12;
0473 
0474     if (select == INPUT_CSC_SELECT_ICSC) {
0475 
0476         gam_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12);
0477         gam_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34);
0478 
0479     } else {
0480 
0481         gam_regs.csc_c11_c12 = REG(CM_COMA_C11_C12);
0482         gam_regs.csc_c33_c34 = REG(CM_COMA_C33_C34);
0483 
0484     }
0485 
0486     cm_helper_program_color_matrices(
0487             dpp->base.ctx,
0488             regval,
0489             &gam_regs);
0490 
0491     REG_SET(CM_ICSC_CONTROL, 0,
0492                 CM_ICSC_MODE, select);
0493 }
0494 
0495 //keep here for now, decide multi dce support later
0496 void dpp1_program_bias_and_scale(
0497     struct dpp *dpp_base,
0498     struct dc_bias_and_scale *params)
0499 {
0500     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0501 
0502     REG_SET_2(CM_BNS_VALUES_R, 0,
0503         CM_BNS_SCALE_R, params->scale_red,
0504         CM_BNS_BIAS_R, params->bias_red);
0505 
0506     REG_SET_2(CM_BNS_VALUES_G, 0,
0507         CM_BNS_SCALE_G, params->scale_green,
0508         CM_BNS_BIAS_G, params->bias_green);
0509 
0510     REG_SET_2(CM_BNS_VALUES_B, 0,
0511         CM_BNS_SCALE_B, params->scale_blue,
0512         CM_BNS_BIAS_B, params->bias_blue);
0513 
0514 }
0515 
0516 /*program de gamma RAM B*/
0517 void dpp1_program_degamma_lutb_settings(
0518         struct dpp *dpp_base,
0519         const struct pwl_params *params)
0520 {
0521     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0522     struct xfer_func_reg gam_regs;
0523 
0524     dpp1_cm_get_degamma_reg_field(dpp, &gam_regs);
0525 
0526     gam_regs.start_cntl_b = REG(CM_DGAM_RAMB_START_CNTL_B);
0527     gam_regs.start_cntl_g = REG(CM_DGAM_RAMB_START_CNTL_G);
0528     gam_regs.start_cntl_r = REG(CM_DGAM_RAMB_START_CNTL_R);
0529     gam_regs.start_slope_cntl_b = REG(CM_DGAM_RAMB_SLOPE_CNTL_B);
0530     gam_regs.start_slope_cntl_g = REG(CM_DGAM_RAMB_SLOPE_CNTL_G);
0531     gam_regs.start_slope_cntl_r = REG(CM_DGAM_RAMB_SLOPE_CNTL_R);
0532     gam_regs.start_end_cntl1_b = REG(CM_DGAM_RAMB_END_CNTL1_B);
0533     gam_regs.start_end_cntl2_b = REG(CM_DGAM_RAMB_END_CNTL2_B);
0534     gam_regs.start_end_cntl1_g = REG(CM_DGAM_RAMB_END_CNTL1_G);
0535     gam_regs.start_end_cntl2_g = REG(CM_DGAM_RAMB_END_CNTL2_G);
0536     gam_regs.start_end_cntl1_r = REG(CM_DGAM_RAMB_END_CNTL1_R);
0537     gam_regs.start_end_cntl2_r = REG(CM_DGAM_RAMB_END_CNTL2_R);
0538     gam_regs.region_start = REG(CM_DGAM_RAMB_REGION_0_1);
0539     gam_regs.region_end = REG(CM_DGAM_RAMB_REGION_14_15);
0540 
0541 
0542     cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
0543 }
0544 
0545 /*program de gamma RAM A*/
0546 void dpp1_program_degamma_luta_settings(
0547         struct dpp *dpp_base,
0548         const struct pwl_params *params)
0549 {
0550     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0551     struct xfer_func_reg gam_regs;
0552 
0553     dpp1_cm_get_degamma_reg_field(dpp, &gam_regs);
0554 
0555     gam_regs.start_cntl_b = REG(CM_DGAM_RAMA_START_CNTL_B);
0556     gam_regs.start_cntl_g = REG(CM_DGAM_RAMA_START_CNTL_G);
0557     gam_regs.start_cntl_r = REG(CM_DGAM_RAMA_START_CNTL_R);
0558     gam_regs.start_slope_cntl_b = REG(CM_DGAM_RAMA_SLOPE_CNTL_B);
0559     gam_regs.start_slope_cntl_g = REG(CM_DGAM_RAMA_SLOPE_CNTL_G);
0560     gam_regs.start_slope_cntl_r = REG(CM_DGAM_RAMA_SLOPE_CNTL_R);
0561     gam_regs.start_end_cntl1_b = REG(CM_DGAM_RAMA_END_CNTL1_B);
0562     gam_regs.start_end_cntl2_b = REG(CM_DGAM_RAMA_END_CNTL2_B);
0563     gam_regs.start_end_cntl1_g = REG(CM_DGAM_RAMA_END_CNTL1_G);
0564     gam_regs.start_end_cntl2_g = REG(CM_DGAM_RAMA_END_CNTL2_G);
0565     gam_regs.start_end_cntl1_r = REG(CM_DGAM_RAMA_END_CNTL1_R);
0566     gam_regs.start_end_cntl2_r = REG(CM_DGAM_RAMA_END_CNTL2_R);
0567     gam_regs.region_start = REG(CM_DGAM_RAMA_REGION_0_1);
0568     gam_regs.region_end = REG(CM_DGAM_RAMA_REGION_14_15);
0569 
0570     cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
0571 }
0572 
0573 void dpp1_power_on_degamma_lut(
0574         struct dpp *dpp_base,
0575     bool power_on)
0576 {
0577     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0578 
0579     REG_SET(CM_MEM_PWR_CTRL, 0,
0580             SHARED_MEM_PWR_DIS, power_on ? 0:1);
0581 
0582 }
0583 
0584 static void dpp1_enable_cm_block(
0585         struct dpp *dpp_base)
0586 {
0587     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0588 
0589     REG_UPDATE(CM_CMOUT_CONTROL, CM_CMOUT_ROUND_TRUNC_MODE, 8);
0590     REG_UPDATE(CM_CONTROL, CM_BYPASS_EN, 0);
0591 }
0592 
0593 void dpp1_set_degamma(
0594         struct dpp *dpp_base,
0595         enum ipp_degamma_mode mode)
0596 {
0597     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0598     dpp1_enable_cm_block(dpp_base);
0599 
0600     switch (mode) {
0601     case IPP_DEGAMMA_MODE_BYPASS:
0602         /* Setting de gamma bypass for now */
0603         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0);
0604         break;
0605     case IPP_DEGAMMA_MODE_HW_sRGB:
0606         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1);
0607         break;
0608     case IPP_DEGAMMA_MODE_HW_xvYCC:
0609         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2);
0610             break;
0611     case IPP_DEGAMMA_MODE_USER_PWL:
0612         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
0613         break;
0614     default:
0615         BREAK_TO_DEBUGGER();
0616         break;
0617     }
0618 
0619     REG_SEQ_SUBMIT();
0620     REG_SEQ_WAIT_DONE();
0621 }
0622 
0623 void dpp1_degamma_ram_select(
0624         struct dpp *dpp_base,
0625                             bool use_ram_a)
0626 {
0627     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0628 
0629     if (use_ram_a)
0630         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
0631     else
0632         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 4);
0633 
0634 }
0635 
0636 static bool dpp1_degamma_ram_inuse(
0637         struct dpp *dpp_base,
0638                             bool *ram_a_inuse)
0639 {
0640     bool ret = false;
0641     uint32_t status_reg = 0;
0642     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0643 
0644     REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
0645             &status_reg);
0646 
0647     if (status_reg == 9) {
0648         *ram_a_inuse = true;
0649         ret = true;
0650     } else if (status_reg == 10) {
0651         *ram_a_inuse = false;
0652         ret = true;
0653     }
0654     return ret;
0655 }
0656 
0657 void dpp1_program_degamma_lut(
0658         struct dpp *dpp_base,
0659         const struct pwl_result_data *rgb,
0660         uint32_t num,
0661         bool is_ram_a)
0662 {
0663     uint32_t i;
0664 
0665     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0666     REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_HOST_EN, 0);
0667     REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK,
0668                    CM_DGAM_LUT_WRITE_EN_MASK, 7);
0669     REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL,
0670                     is_ram_a == true ? 0:1);
0671 
0672     REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0);
0673     for (i = 0 ; i < num; i++) {
0674         REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg);
0675         REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg);
0676         REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg);
0677 
0678         REG_SET(CM_DGAM_LUT_DATA, 0,
0679                 CM_DGAM_LUT_DATA, rgb[i].delta_red_reg);
0680         REG_SET(CM_DGAM_LUT_DATA, 0,
0681                 CM_DGAM_LUT_DATA, rgb[i].delta_green_reg);
0682         REG_SET(CM_DGAM_LUT_DATA, 0,
0683                 CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg);
0684     }
0685 }
0686 
0687 void dpp1_set_degamma_pwl(struct dpp *dpp_base,
0688                                  const struct pwl_params *params)
0689 {
0690     bool is_ram_a = true;
0691 
0692     dpp1_power_on_degamma_lut(dpp_base, true);
0693     dpp1_enable_cm_block(dpp_base);
0694     dpp1_degamma_ram_inuse(dpp_base, &is_ram_a);
0695     if (is_ram_a == true)
0696         dpp1_program_degamma_lutb_settings(dpp_base, params);
0697     else
0698         dpp1_program_degamma_luta_settings(dpp_base, params);
0699 
0700     dpp1_program_degamma_lut(dpp_base, params->rgb_resulted,
0701                             params->hw_points_num, !is_ram_a);
0702     dpp1_degamma_ram_select(dpp_base, !is_ram_a);
0703 }
0704 
0705 void dpp1_full_bypass(struct dpp *dpp_base)
0706 {
0707     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0708 
0709     /* Input pixel format: ARGB8888 */
0710     REG_SET(CNVC_SURFACE_PIXEL_FORMAT, 0,
0711             CNVC_SURFACE_PIXEL_FORMAT, 0x8);
0712 
0713     /* Zero expansion */
0714     REG_SET_3(FORMAT_CONTROL, 0,
0715             CNVC_BYPASS, 0,
0716             FORMAT_CONTROL__ALPHA_EN, 0,
0717             FORMAT_EXPANSION_MODE, 0);
0718 
0719     /* COLOR_KEYER_CONTROL.COLOR_KEYER_EN = 0 this should be default */
0720     if (dpp->tf_mask->CM_BYPASS_EN)
0721         REG_SET(CM_CONTROL, 0, CM_BYPASS_EN, 1);
0722     else
0723         REG_SET(CM_CONTROL, 0, CM_BYPASS, 1);
0724 
0725     /* Setting degamma bypass for now */
0726     REG_SET(CM_DGAM_CONTROL, 0, CM_DGAM_LUT_MODE, 0);
0727 }
0728 
0729 static bool dpp1_ingamma_ram_inuse(struct dpp *dpp_base,
0730                             bool *ram_a_inuse)
0731 {
0732     bool in_use = false;
0733     uint32_t status_reg = 0;
0734     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0735 
0736     REG_GET(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_DGAM_CONFIG_STATUS,
0737                 &status_reg);
0738 
0739     // 1 => IGAM_RAMA, 3 => IGAM_RAMA & DGAM_ROMA, 4 => IGAM_RAMA & DGAM_ROMB
0740     if (status_reg == 1 || status_reg == 3 || status_reg == 4) {
0741         *ram_a_inuse = true;
0742         in_use = true;
0743     // 2 => IGAM_RAMB, 5 => IGAM_RAMB & DGAM_ROMA, 6 => IGAM_RAMB & DGAM_ROMB
0744     } else if (status_reg == 2 || status_reg == 5 || status_reg == 6) {
0745         *ram_a_inuse = false;
0746         in_use = true;
0747     }
0748     return in_use;
0749 }
0750 
0751 /*
0752  * Input gamma LUT currently supports 256 values only. This means input color
0753  * can have a maximum of 8 bits per channel (= 256 possible values) in order to
0754  * have a one-to-one mapping with the LUT. Truncation will occur with color
0755  * values greater than 8 bits.
0756  *
0757  * In the future, this function should support additional input gamma methods,
0758  * such as piecewise linear mapping, and input gamma bypass.
0759  */
0760 void dpp1_program_input_lut(
0761         struct dpp *dpp_base,
0762         const struct dc_gamma *gamma)
0763 {
0764     int i;
0765     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0766     bool rama_occupied = false;
0767     uint32_t ram_num;
0768     // Power on LUT memory.
0769     REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 1);
0770     dpp1_enable_cm_block(dpp_base);
0771     // Determine whether to use RAM A or RAM B
0772     dpp1_ingamma_ram_inuse(dpp_base, &rama_occupied);
0773     if (!rama_occupied)
0774         REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 0);
0775     else
0776         REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_SEL, 1);
0777     // RW mode is 256-entry LUT
0778     REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_RW_MODE, 0);
0779     // IGAM Input format should be 8 bits per channel.
0780     REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_INPUT_FORMAT, 0);
0781     // Do not mask any R,G,B values
0782     REG_UPDATE(CM_IGAM_LUT_RW_CONTROL, CM_IGAM_LUT_WRITE_EN_MASK, 7);
0783     // LUT-256, unsigned, integer, new u0.12 format
0784     REG_UPDATE_3(
0785         CM_IGAM_CONTROL,
0786         CM_IGAM_LUT_FORMAT_R, 3,
0787         CM_IGAM_LUT_FORMAT_G, 3,
0788         CM_IGAM_LUT_FORMAT_B, 3);
0789     // Start at index 0 of IGAM LUT
0790     REG_UPDATE(CM_IGAM_LUT_RW_INDEX, CM_IGAM_LUT_RW_INDEX, 0);
0791     for (i = 0; i < gamma->num_entries; i++) {
0792         REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
0793                 dc_fixpt_round(
0794                     gamma->entries.red[i]));
0795         REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
0796                 dc_fixpt_round(
0797                     gamma->entries.green[i]));
0798         REG_SET(CM_IGAM_LUT_SEQ_COLOR, 0, CM_IGAM_LUT_SEQ_COLOR,
0799                 dc_fixpt_round(
0800                     gamma->entries.blue[i]));
0801     }
0802     // Power off LUT memory
0803     REG_SET(CM_MEM_PWR_CTRL, 0, SHARED_MEM_PWR_DIS, 0);
0804     // Enable IGAM LUT on ram we just wrote to. 2 => RAMA, 3 => RAMB
0805     REG_UPDATE(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, rama_occupied ? 3 : 2);
0806     REG_GET(CM_IGAM_CONTROL, CM_IGAM_LUT_MODE, &ram_num);
0807 }
0808 
0809 void dpp1_set_hdr_multiplier(
0810         struct dpp *dpp_base,
0811         uint32_t multiplier)
0812 {
0813     struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
0814 
0815     REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
0816 }