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 "dcn20_dpp.h"
0032 #include "basics/conversion.h"
0033 
0034 #include "dcn10/dcn10_cm_common.h"
0035 
0036 #define REG(reg)\
0037     dpp->tf_regs->reg
0038 
0039 #define IND_REG(index) \
0040     (index)
0041 
0042 #define CTX \
0043     dpp->base.ctx
0044 
0045 #undef FN
0046 #define FN(reg_name, field_name) \
0047     dpp->tf_shift->field_name, dpp->tf_mask->field_name
0048 
0049 
0050 static void dpp2_enable_cm_block(
0051         struct dpp *dpp_base)
0052 {
0053     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0054 
0055     unsigned int cm_bypass_mode = 0;
0056     //Temp, put CM in bypass mode
0057     if (dpp_base->ctx->dc->debug.cm_in_bypass)
0058         cm_bypass_mode = 1;
0059 
0060     REG_UPDATE(CM_CONTROL, CM_BYPASS, cm_bypass_mode);
0061 }
0062 
0063 
0064 static bool dpp2_degamma_ram_inuse(
0065         struct dpp *dpp_base,
0066         bool *ram_a_inuse)
0067 {
0068     bool ret = false;
0069     uint32_t status_reg = 0;
0070     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0071 
0072     REG_GET(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_CONFIG_STATUS,
0073             &status_reg);
0074 
0075     if (status_reg == 3) {
0076         *ram_a_inuse = true;
0077         ret = true;
0078     } else if (status_reg == 4) {
0079         *ram_a_inuse = false;
0080         ret = true;
0081     }
0082     return ret;
0083 }
0084 
0085 static void dpp2_program_degamma_lut(
0086         struct dpp *dpp_base,
0087         const struct pwl_result_data *rgb,
0088         uint32_t num,
0089         bool is_ram_a)
0090 {
0091     uint32_t i;
0092 
0093     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0094     REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK,
0095                 CM_DGAM_LUT_WRITE_EN_MASK, 7);
0096     REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL,
0097                     is_ram_a == true ? 0:1);
0098 
0099     REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0);
0100     for (i = 0 ; i < num; i++) {
0101         REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg);
0102         REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg);
0103         REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg);
0104 
0105         REG_SET(CM_DGAM_LUT_DATA, 0,
0106                 CM_DGAM_LUT_DATA, rgb[i].delta_red_reg);
0107         REG_SET(CM_DGAM_LUT_DATA, 0,
0108                 CM_DGAM_LUT_DATA, rgb[i].delta_green_reg);
0109         REG_SET(CM_DGAM_LUT_DATA, 0,
0110                 CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg);
0111 
0112     }
0113 
0114 }
0115 
0116 void dpp2_set_degamma_pwl(
0117         struct dpp *dpp_base,
0118         const struct pwl_params *params)
0119 {
0120     bool is_ram_a = true;
0121 
0122     dpp1_power_on_degamma_lut(dpp_base, true);
0123     dpp2_enable_cm_block(dpp_base);
0124     dpp2_degamma_ram_inuse(dpp_base, &is_ram_a);
0125     if (is_ram_a == true)
0126         dpp1_program_degamma_lutb_settings(dpp_base, params);
0127     else
0128         dpp1_program_degamma_luta_settings(dpp_base, params);
0129 
0130     dpp2_program_degamma_lut(dpp_base, params->rgb_resulted, params->hw_points_num, !is_ram_a);
0131     dpp1_degamma_ram_select(dpp_base, !is_ram_a);
0132 }
0133 
0134 void dpp2_set_degamma(
0135         struct dpp *dpp_base,
0136         enum ipp_degamma_mode mode)
0137 {
0138     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0139     dpp2_enable_cm_block(dpp_base);
0140 
0141     switch (mode) {
0142     case IPP_DEGAMMA_MODE_BYPASS:
0143         /* Setting de gamma bypass for now */
0144         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0);
0145         break;
0146     case IPP_DEGAMMA_MODE_HW_sRGB:
0147         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1);
0148         break;
0149     case IPP_DEGAMMA_MODE_HW_xvYCC:
0150         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2);
0151             break;
0152     case IPP_DEGAMMA_MODE_USER_PWL:
0153         REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
0154         break;
0155     default:
0156         BREAK_TO_DEBUGGER();
0157         break;
0158     }
0159 }
0160 
0161 static void program_gamut_remap(
0162         struct dcn20_dpp *dpp,
0163         const uint16_t *regval,
0164         enum dcn20_gamut_remap_select select)
0165 {
0166     uint32_t cur_select = 0;
0167     struct color_matrices_reg gam_regs;
0168 
0169     if (regval == NULL || select == DCN2_GAMUT_REMAP_BYPASS) {
0170         REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
0171                 CM_GAMUT_REMAP_MODE, 0);
0172         return;
0173     }
0174 
0175     /* determine which gamut_remap coefficients (A or B) we are using
0176      * currently. select the alternate set to double buffer
0177      * the update so gamut_remap is updated on frame boundary
0178      */
0179     IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
0180                     CM_TEST_DEBUG_DATA_STATUS_IDX,
0181                     CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE, &cur_select);
0182 
0183     /* value stored in dbg reg will be 1 greater than mode we want */
0184     if (cur_select != DCN2_GAMUT_REMAP_COEF_A)
0185         select = DCN2_GAMUT_REMAP_COEF_A;
0186     else
0187         select = DCN2_GAMUT_REMAP_COEF_B;
0188 
0189     gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
0190     gam_regs.masks.csc_c11  = dpp->tf_mask->CM_GAMUT_REMAP_C11;
0191     gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
0192     gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
0193 
0194     if (select == DCN2_GAMUT_REMAP_COEF_A) {
0195         gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
0196         gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
0197     } else {
0198         gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
0199         gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
0200     }
0201 
0202     cm_helper_program_color_matrices(
0203                 dpp->base.ctx,
0204                 regval,
0205                 &gam_regs);
0206 
0207     REG_SET(
0208             CM_GAMUT_REMAP_CONTROL, 0,
0209             CM_GAMUT_REMAP_MODE, select);
0210 
0211 }
0212 
0213 void dpp2_cm_set_gamut_remap(
0214     struct dpp *dpp_base,
0215     const struct dpp_grph_csc_adjustment *adjust)
0216 {
0217     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0218     int i = 0;
0219 
0220     if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
0221         /* Bypass if type is bypass or hw */
0222         program_gamut_remap(dpp, NULL, DCN2_GAMUT_REMAP_BYPASS);
0223     else {
0224         struct fixed31_32 arr_matrix[12];
0225         uint16_t arr_reg_val[12];
0226 
0227         for (i = 0; i < 12; i++)
0228             arr_matrix[i] = adjust->temperature_matrix[i];
0229 
0230         convert_float_matrix(
0231             arr_reg_val, arr_matrix, 12);
0232 
0233         program_gamut_remap(dpp, arr_reg_val, DCN2_GAMUT_REMAP_COEF_A);
0234     }
0235 }
0236 
0237 void dpp2_program_input_csc(
0238         struct dpp *dpp_base,
0239         enum dc_color_space color_space,
0240         enum dcn20_input_csc_select input_select,
0241         const struct out_csc_color_matrix *tbl_entry)
0242 {
0243     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0244     int i;
0245     int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
0246     const uint16_t *regval = NULL;
0247     uint32_t cur_select = 0;
0248     enum dcn20_input_csc_select select;
0249     struct color_matrices_reg icsc_regs;
0250 
0251     if (input_select == DCN2_ICSC_SELECT_BYPASS) {
0252         REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
0253         return;
0254     }
0255 
0256     if (tbl_entry == NULL) {
0257         for (i = 0; i < arr_size; i++)
0258             if (dpp_input_csc_matrix[i].color_space == color_space) {
0259                 regval = dpp_input_csc_matrix[i].regval;
0260                 break;
0261             }
0262 
0263         if (regval == NULL) {
0264             BREAK_TO_DEBUGGER();
0265             return;
0266         }
0267     } else {
0268         regval = tbl_entry->regval;
0269     }
0270 
0271     /* determine which CSC coefficients (A or B) we are using
0272      * currently.  select the alternate set to double buffer
0273      * the CSC update so CSC is updated on frame boundary
0274      */
0275     IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
0276                     CM_TEST_DEBUG_DATA_STATUS_IDX,
0277                     CM_TEST_DEBUG_DATA_ICSC_MODE, &cur_select);
0278 
0279     if (cur_select != DCN2_ICSC_SELECT_ICSC_A)
0280         select = DCN2_ICSC_SELECT_ICSC_A;
0281     else
0282         select = DCN2_ICSC_SELECT_ICSC_B;
0283 
0284     icsc_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11;
0285     icsc_regs.masks.csc_c11  = dpp->tf_mask->CM_ICSC_C11;
0286     icsc_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12;
0287     icsc_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12;
0288 
0289     if (select == DCN2_ICSC_SELECT_ICSC_A) {
0290 
0291         icsc_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12);
0292         icsc_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34);
0293 
0294     } else {
0295 
0296         icsc_regs.csc_c11_c12 = REG(CM_ICSC_B_C11_C12);
0297         icsc_regs.csc_c33_c34 = REG(CM_ICSC_B_C33_C34);
0298 
0299     }
0300 
0301     cm_helper_program_color_matrices(
0302             dpp->base.ctx,
0303             regval,
0304             &icsc_regs);
0305 
0306     REG_SET(CM_ICSC_CONTROL, 0,
0307                 CM_ICSC_MODE, select);
0308 }
0309 
0310 static void dpp20_power_on_blnd_lut(
0311     struct dpp *dpp_base,
0312     bool power_on)
0313 {
0314     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0315 
0316     REG_SET(CM_MEM_PWR_CTRL, 0,
0317             BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0:1);
0318 
0319 }
0320 
0321 static void dpp20_configure_blnd_lut(
0322         struct dpp *dpp_base,
0323         bool is_ram_a)
0324 {
0325     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0326 
0327     REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
0328             CM_BLNDGAM_LUT_WRITE_EN_MASK, 7);
0329     REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
0330             CM_BLNDGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
0331     REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
0332 }
0333 
0334 static void dpp20_program_blnd_pwl(
0335         struct dpp *dpp_base,
0336         const struct pwl_result_data *rgb,
0337         uint32_t num)
0338 {
0339     uint32_t i;
0340     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0341 
0342     for (i = 0 ; i < num; i++) {
0343         REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
0344         REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg);
0345         REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg);
0346 
0347         REG_SET(CM_BLNDGAM_LUT_DATA, 0,
0348                 CM_BLNDGAM_LUT_DATA, rgb[i].delta_red_reg);
0349         REG_SET(CM_BLNDGAM_LUT_DATA, 0,
0350                 CM_BLNDGAM_LUT_DATA, rgb[i].delta_green_reg);
0351         REG_SET(CM_BLNDGAM_LUT_DATA, 0,
0352                 CM_BLNDGAM_LUT_DATA, rgb[i].delta_blue_reg);
0353 
0354     }
0355 
0356 }
0357 
0358 static void dcn20_dpp_cm_get_reg_field(
0359         struct dcn20_dpp *dpp,
0360         struct xfer_func_reg *reg)
0361 {
0362     reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0363     reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0364     reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0365     reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0366     reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0367     reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0368     reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0369     reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0370 
0371     reg->shifts.field_region_end = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
0372     reg->masks.field_region_end = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
0373     reg->shifts.field_region_end_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
0374     reg->masks.field_region_end_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
0375     reg->shifts.field_region_end_base = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
0376     reg->masks.field_region_end_base = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
0377     reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
0378     reg->masks.field_region_linear_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
0379     reg->shifts.exp_region_start = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
0380     reg->masks.exp_region_start = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
0381     reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
0382     reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
0383 }
0384 
0385 /*program blnd lut RAM A*/
0386 static void dpp20_program_blnd_luta_settings(
0387         struct dpp *dpp_base,
0388         const struct pwl_params *params)
0389 {
0390     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0391     struct xfer_func_reg gam_regs;
0392 
0393     dcn20_dpp_cm_get_reg_field(dpp, &gam_regs);
0394 
0395     gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMA_START_CNTL_B);
0396     gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMA_START_CNTL_G);
0397     gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMA_START_CNTL_R);
0398     gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_B);
0399     gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_G);
0400     gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_R);
0401     gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMA_END_CNTL1_B);
0402     gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMA_END_CNTL2_B);
0403     gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMA_END_CNTL1_G);
0404     gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMA_END_CNTL2_G);
0405     gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMA_END_CNTL1_R);
0406     gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMA_END_CNTL2_R);
0407     gam_regs.region_start = REG(CM_BLNDGAM_RAMA_REGION_0_1);
0408     gam_regs.region_end = REG(CM_BLNDGAM_RAMA_REGION_32_33);
0409 
0410     cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
0411 }
0412 
0413 /*program blnd lut RAM B*/
0414 static void dpp20_program_blnd_lutb_settings(
0415         struct dpp *dpp_base,
0416         const struct pwl_params *params)
0417 {
0418     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0419     struct xfer_func_reg gam_regs;
0420 
0421     dcn20_dpp_cm_get_reg_field(dpp, &gam_regs);
0422 
0423     gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMB_START_CNTL_B);
0424     gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMB_START_CNTL_G);
0425     gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMB_START_CNTL_R);
0426     gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_B);
0427     gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_G);
0428     gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_R);
0429     gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMB_END_CNTL1_B);
0430     gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMB_END_CNTL2_B);
0431     gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMB_END_CNTL1_G);
0432     gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMB_END_CNTL2_G);
0433     gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMB_END_CNTL1_R);
0434     gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMB_END_CNTL2_R);
0435     gam_regs.region_start = REG(CM_BLNDGAM_RAMB_REGION_0_1);
0436     gam_regs.region_end = REG(CM_BLNDGAM_RAMB_REGION_32_33);
0437 
0438     cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
0439 }
0440 
0441 static enum dc_lut_mode dpp20_get_blndgam_current(struct dpp *dpp_base)
0442 {
0443     enum dc_lut_mode mode;
0444     uint32_t state_mode;
0445     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0446 
0447     REG_GET(CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_CONFIG_STATUS, &state_mode);
0448 
0449     switch (state_mode) {
0450     case 0:
0451         mode = LUT_BYPASS;
0452         break;
0453     case 1:
0454         mode = LUT_RAM_A;
0455         break;
0456     case 2:
0457         mode = LUT_RAM_B;
0458         break;
0459     default:
0460         mode = LUT_BYPASS;
0461         break;
0462     }
0463 
0464     return mode;
0465 }
0466 
0467 bool dpp20_program_blnd_lut(
0468     struct dpp *dpp_base, const struct pwl_params *params)
0469 {
0470     enum dc_lut_mode current_mode;
0471     enum dc_lut_mode next_mode;
0472     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0473 
0474     if (params == NULL) {
0475         REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE, 0);
0476         return false;
0477     }
0478     current_mode = dpp20_get_blndgam_current(dpp_base);
0479     if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
0480         next_mode = LUT_RAM_B;
0481     else
0482         next_mode = LUT_RAM_A;
0483 
0484     dpp20_power_on_blnd_lut(dpp_base, true);
0485     dpp20_configure_blnd_lut(dpp_base, next_mode == LUT_RAM_A);
0486 
0487     if (next_mode == LUT_RAM_A)
0488         dpp20_program_blnd_luta_settings(dpp_base, params);
0489     else
0490         dpp20_program_blnd_lutb_settings(dpp_base, params);
0491 
0492     dpp20_program_blnd_pwl(
0493             dpp_base, params->rgb_resulted, params->hw_points_num);
0494 
0495     REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE,
0496             next_mode == LUT_RAM_A ? 1:2);
0497 
0498     return true;
0499 }
0500 
0501 
0502 static void dpp20_program_shaper_lut(
0503         struct dpp *dpp_base,
0504         const struct pwl_result_data *rgb,
0505         uint32_t num)
0506 {
0507     uint32_t i, red, green, blue;
0508     uint32_t  red_delta, green_delta, blue_delta;
0509     uint32_t  red_value, green_value, blue_value;
0510 
0511     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0512 
0513     for (i = 0 ; i < num; i++) {
0514 
0515         red   = rgb[i].red_reg;
0516         green = rgb[i].green_reg;
0517         blue  = rgb[i].blue_reg;
0518 
0519         red_delta   = rgb[i].delta_red_reg;
0520         green_delta = rgb[i].delta_green_reg;
0521         blue_delta  = rgb[i].delta_blue_reg;
0522 
0523         red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
0524         green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
0525         blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
0526 
0527         REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, red_value);
0528         REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, green_value);
0529         REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, blue_value);
0530     }
0531 
0532 }
0533 
0534 static enum dc_lut_mode dpp20_get_shaper_current(struct dpp *dpp_base)
0535 {
0536     enum dc_lut_mode mode;
0537     uint32_t state_mode;
0538     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0539 
0540     REG_GET(CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_CONFIG_STATUS, &state_mode);
0541 
0542     switch (state_mode) {
0543     case 0:
0544         mode = LUT_BYPASS;
0545         break;
0546     case 1:
0547         mode = LUT_RAM_A;
0548         break;
0549     case 2:
0550         mode = LUT_RAM_B;
0551         break;
0552     default:
0553         mode = LUT_BYPASS;
0554         break;
0555     }
0556 
0557     return mode;
0558 }
0559 
0560 static void dpp20_configure_shaper_lut(
0561         struct dpp *dpp_base,
0562         bool is_ram_a)
0563 {
0564     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0565 
0566     REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
0567             CM_SHAPER_LUT_WRITE_EN_MASK, 7);
0568     REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
0569             CM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
0570     REG_SET(CM_SHAPER_LUT_INDEX, 0, CM_SHAPER_LUT_INDEX, 0);
0571 }
0572 
0573 /*program shaper RAM A*/
0574 
0575 static void dpp20_program_shaper_luta_settings(
0576         struct dpp *dpp_base,
0577         const struct pwl_params *params)
0578 {
0579     const struct gamma_curve *curve;
0580     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0581 
0582     REG_SET_2(CM_SHAPER_RAMA_START_CNTL_B, 0,
0583         CM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
0584         CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0585     REG_SET_2(CM_SHAPER_RAMA_START_CNTL_G, 0,
0586         CM_SHAPER_RAMA_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
0587         CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, 0);
0588     REG_SET_2(CM_SHAPER_RAMA_START_CNTL_R, 0,
0589         CM_SHAPER_RAMA_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
0590         CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, 0);
0591 
0592     REG_SET_2(CM_SHAPER_RAMA_END_CNTL_B, 0,
0593         CM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
0594         CM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
0595 
0596     REG_SET_2(CM_SHAPER_RAMA_END_CNTL_G, 0,
0597         CM_SHAPER_RAMA_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
0598         CM_SHAPER_RAMA_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
0599 
0600     REG_SET_2(CM_SHAPER_RAMA_END_CNTL_R, 0,
0601         CM_SHAPER_RAMA_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
0602         CM_SHAPER_RAMA_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
0603 
0604     curve = params->arr_curve_points;
0605     REG_SET_4(CM_SHAPER_RAMA_REGION_0_1, 0,
0606         CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0607         CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0608         CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0609         CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0610 
0611     curve += 2;
0612     REG_SET_4(CM_SHAPER_RAMA_REGION_2_3, 0,
0613         CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset,
0614         CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
0615         CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset,
0616         CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
0617 
0618     curve += 2;
0619     REG_SET_4(CM_SHAPER_RAMA_REGION_4_5, 0,
0620         CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset,
0621         CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
0622         CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset,
0623         CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
0624 
0625     curve += 2;
0626     REG_SET_4(CM_SHAPER_RAMA_REGION_6_7, 0,
0627         CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset,
0628         CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
0629         CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset,
0630         CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
0631 
0632     curve += 2;
0633     REG_SET_4(CM_SHAPER_RAMA_REGION_8_9, 0,
0634         CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset,
0635         CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
0636         CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset,
0637         CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
0638 
0639     curve += 2;
0640     REG_SET_4(CM_SHAPER_RAMA_REGION_10_11, 0,
0641         CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset,
0642         CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
0643         CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset,
0644         CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
0645 
0646     curve += 2;
0647     REG_SET_4(CM_SHAPER_RAMA_REGION_12_13, 0,
0648         CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset,
0649         CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
0650         CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset,
0651         CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
0652 
0653     curve += 2;
0654     REG_SET_4(CM_SHAPER_RAMA_REGION_14_15, 0,
0655         CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset,
0656         CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
0657         CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset,
0658         CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
0659 
0660     curve += 2;
0661     REG_SET_4(CM_SHAPER_RAMA_REGION_16_17, 0,
0662         CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset,
0663         CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
0664         CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset,
0665         CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
0666 
0667     curve += 2;
0668     REG_SET_4(CM_SHAPER_RAMA_REGION_18_19, 0,
0669         CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset,
0670         CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
0671         CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset,
0672         CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
0673 
0674     curve += 2;
0675     REG_SET_4(CM_SHAPER_RAMA_REGION_20_21, 0,
0676         CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset,
0677         CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
0678         CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset,
0679         CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
0680 
0681     curve += 2;
0682     REG_SET_4(CM_SHAPER_RAMA_REGION_22_23, 0,
0683         CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset,
0684         CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
0685         CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset,
0686         CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
0687 
0688     curve += 2;
0689     REG_SET_4(CM_SHAPER_RAMA_REGION_24_25, 0,
0690         CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset,
0691         CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
0692         CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset,
0693         CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
0694 
0695     curve += 2;
0696     REG_SET_4(CM_SHAPER_RAMA_REGION_26_27, 0,
0697         CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset,
0698         CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
0699         CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset,
0700         CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
0701 
0702     curve += 2;
0703     REG_SET_4(CM_SHAPER_RAMA_REGION_28_29, 0,
0704         CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset,
0705         CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
0706         CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset,
0707         CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
0708 
0709     curve += 2;
0710     REG_SET_4(CM_SHAPER_RAMA_REGION_30_31, 0,
0711         CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset,
0712         CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
0713         CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset,
0714         CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
0715 
0716     curve += 2;
0717     REG_SET_4(CM_SHAPER_RAMA_REGION_32_33, 0,
0718         CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset,
0719         CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
0720         CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset,
0721         CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
0722 }
0723 
0724 /*program shaper RAM B*/
0725 static void dpp20_program_shaper_lutb_settings(
0726         struct dpp *dpp_base,
0727         const struct pwl_params *params)
0728 {
0729     const struct gamma_curve *curve;
0730     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0731 
0732     REG_SET_2(CM_SHAPER_RAMB_START_CNTL_B, 0,
0733         CM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
0734         CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
0735     REG_SET_2(CM_SHAPER_RAMB_START_CNTL_G, 0,
0736         CM_SHAPER_RAMB_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
0737         CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, 0);
0738     REG_SET_2(CM_SHAPER_RAMB_START_CNTL_R, 0,
0739         CM_SHAPER_RAMB_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
0740         CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, 0);
0741 
0742     REG_SET_2(CM_SHAPER_RAMB_END_CNTL_B, 0,
0743         CM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
0744         CM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
0745 
0746     REG_SET_2(CM_SHAPER_RAMB_END_CNTL_G, 0,
0747         CM_SHAPER_RAMB_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
0748         CM_SHAPER_RAMB_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
0749 
0750     REG_SET_2(CM_SHAPER_RAMB_END_CNTL_R, 0,
0751         CM_SHAPER_RAMB_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
0752         CM_SHAPER_RAMB_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
0753 
0754     curve = params->arr_curve_points;
0755     REG_SET_4(CM_SHAPER_RAMB_REGION_0_1, 0,
0756         CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0757         CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0758         CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0759         CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0760 
0761     curve += 2;
0762     REG_SET_4(CM_SHAPER_RAMB_REGION_2_3, 0,
0763         CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset,
0764         CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
0765         CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset,
0766         CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
0767 
0768     curve += 2;
0769     REG_SET_4(CM_SHAPER_RAMB_REGION_4_5, 0,
0770         CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset,
0771         CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
0772         CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset,
0773         CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
0774 
0775     curve += 2;
0776     REG_SET_4(CM_SHAPER_RAMB_REGION_6_7, 0,
0777         CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset,
0778         CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
0779         CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset,
0780         CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
0781 
0782     curve += 2;
0783     REG_SET_4(CM_SHAPER_RAMB_REGION_8_9, 0,
0784         CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset,
0785         CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
0786         CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset,
0787         CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
0788 
0789     curve += 2;
0790     REG_SET_4(CM_SHAPER_RAMB_REGION_10_11, 0,
0791         CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset,
0792         CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
0793         CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset,
0794         CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
0795 
0796     curve += 2;
0797     REG_SET_4(CM_SHAPER_RAMB_REGION_12_13, 0,
0798         CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset,
0799         CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
0800         CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset,
0801         CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
0802 
0803     curve += 2;
0804     REG_SET_4(CM_SHAPER_RAMB_REGION_14_15, 0,
0805         CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset,
0806         CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
0807         CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset,
0808         CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
0809 
0810     curve += 2;
0811     REG_SET_4(CM_SHAPER_RAMB_REGION_16_17, 0,
0812         CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset,
0813         CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
0814         CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset,
0815         CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
0816 
0817     curve += 2;
0818     REG_SET_4(CM_SHAPER_RAMB_REGION_18_19, 0,
0819         CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset,
0820         CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
0821         CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset,
0822         CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
0823 
0824     curve += 2;
0825     REG_SET_4(CM_SHAPER_RAMB_REGION_20_21, 0,
0826         CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset,
0827         CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
0828         CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset,
0829         CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
0830 
0831     curve += 2;
0832     REG_SET_4(CM_SHAPER_RAMB_REGION_22_23, 0,
0833         CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset,
0834         CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
0835         CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset,
0836         CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
0837 
0838     curve += 2;
0839     REG_SET_4(CM_SHAPER_RAMB_REGION_24_25, 0,
0840         CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset,
0841         CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
0842         CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset,
0843         CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
0844 
0845     curve += 2;
0846     REG_SET_4(CM_SHAPER_RAMB_REGION_26_27, 0,
0847         CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset,
0848         CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
0849         CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset,
0850         CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
0851 
0852     curve += 2;
0853     REG_SET_4(CM_SHAPER_RAMB_REGION_28_29, 0,
0854         CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset,
0855         CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
0856         CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset,
0857         CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
0858 
0859     curve += 2;
0860     REG_SET_4(CM_SHAPER_RAMB_REGION_30_31, 0,
0861         CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset,
0862         CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
0863         CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset,
0864         CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
0865 
0866     curve += 2;
0867     REG_SET_4(CM_SHAPER_RAMB_REGION_32_33, 0,
0868         CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset,
0869         CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
0870         CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset,
0871         CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
0872 
0873 }
0874 
0875 
0876 bool dpp20_program_shaper(
0877         struct dpp *dpp_base,
0878         const struct pwl_params *params)
0879 {
0880     enum dc_lut_mode current_mode;
0881     enum dc_lut_mode next_mode;
0882 
0883     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0884 
0885     if (params == NULL) {
0886         REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, 0);
0887         return false;
0888     }
0889     current_mode = dpp20_get_shaper_current(dpp_base);
0890 
0891     if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
0892         next_mode = LUT_RAM_B;
0893     else
0894         next_mode = LUT_RAM_A;
0895 
0896     dpp20_configure_shaper_lut(dpp_base, next_mode == LUT_RAM_A);
0897 
0898     if (next_mode == LUT_RAM_A)
0899         dpp20_program_shaper_luta_settings(dpp_base, params);
0900     else
0901         dpp20_program_shaper_lutb_settings(dpp_base, params);
0902 
0903     dpp20_program_shaper_lut(
0904             dpp_base, params->rgb_resulted, params->hw_points_num);
0905 
0906     REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
0907 
0908     return true;
0909 
0910 }
0911 
0912 static enum dc_lut_mode get3dlut_config(
0913             struct dpp *dpp_base,
0914             bool *is_17x17x17,
0915             bool *is_12bits_color_channel)
0916 {
0917     uint32_t i_mode, i_enable_10bits, lut_size;
0918     enum dc_lut_mode mode;
0919     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0920 
0921     REG_GET_2(CM_3DLUT_READ_WRITE_CONTROL,
0922             CM_3DLUT_CONFIG_STATUS, &i_mode,
0923             CM_3DLUT_30BIT_EN, &i_enable_10bits);
0924 
0925     switch (i_mode) {
0926     case 0:
0927         mode = LUT_BYPASS;
0928         break;
0929     case 1:
0930         mode = LUT_RAM_A;
0931         break;
0932     case 2:
0933         mode = LUT_RAM_B;
0934         break;
0935     default:
0936         mode = LUT_BYPASS;
0937         break;
0938     }
0939     if (i_enable_10bits > 0)
0940         *is_12bits_color_channel = false;
0941     else
0942         *is_12bits_color_channel = true;
0943 
0944     REG_GET(CM_3DLUT_MODE, CM_3DLUT_SIZE, &lut_size);
0945 
0946     if (lut_size == 0)
0947         *is_17x17x17 = true;
0948     else
0949         *is_17x17x17 = false;
0950 
0951     return mode;
0952 }
0953 /*
0954  * select ramA or ramB, or bypass
0955  * select color channel size 10 or 12 bits
0956  * select 3dlut size 17x17x17 or 9x9x9
0957  */
0958 static void dpp20_set_3dlut_mode(
0959         struct dpp *dpp_base,
0960         enum dc_lut_mode mode,
0961         bool is_color_channel_12bits,
0962         bool is_lut_size17x17x17)
0963 {
0964     uint32_t lut_mode;
0965     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0966 
0967     if (mode == LUT_BYPASS)
0968         lut_mode = 0;
0969     else if (mode == LUT_RAM_A)
0970         lut_mode = 1;
0971     else
0972         lut_mode = 2;
0973 
0974     REG_UPDATE_2(CM_3DLUT_MODE,
0975             CM_3DLUT_MODE, lut_mode,
0976             CM_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
0977 }
0978 
0979 static void dpp20_select_3dlut_ram(
0980         struct dpp *dpp_base,
0981         enum dc_lut_mode mode,
0982         bool is_color_channel_12bits)
0983 {
0984     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
0985 
0986     REG_UPDATE_2(CM_3DLUT_READ_WRITE_CONTROL,
0987             CM_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
0988             CM_3DLUT_30BIT_EN,
0989             is_color_channel_12bits == true ? 0:1);
0990 }
0991 
0992 
0993 
0994 static void dpp20_set3dlut_ram12(
0995         struct dpp *dpp_base,
0996         const struct dc_rgb *lut,
0997         uint32_t entries)
0998 {
0999     uint32_t i, red, green, blue, red1, green1, blue1;
1000     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1001 
1002     for (i = 0 ; i < entries; i += 2) {
1003         red   = lut[i].red<<4;
1004         green = lut[i].green<<4;
1005         blue  = lut[i].blue<<4;
1006         red1   = lut[i+1].red<<4;
1007         green1 = lut[i+1].green<<4;
1008         blue1  = lut[i+1].blue<<4;
1009 
1010         REG_SET_2(CM_3DLUT_DATA, 0,
1011                 CM_3DLUT_DATA0, red,
1012                 CM_3DLUT_DATA1, red1);
1013 
1014         REG_SET_2(CM_3DLUT_DATA, 0,
1015                 CM_3DLUT_DATA0, green,
1016                 CM_3DLUT_DATA1, green1);
1017 
1018         REG_SET_2(CM_3DLUT_DATA, 0,
1019                 CM_3DLUT_DATA0, blue,
1020                 CM_3DLUT_DATA1, blue1);
1021 
1022     }
1023 }
1024 
1025 /*
1026  * load selected lut with 10 bits color channels
1027  */
1028 static void dpp20_set3dlut_ram10(
1029         struct dpp *dpp_base,
1030         const struct dc_rgb *lut,
1031         uint32_t entries)
1032 {
1033     uint32_t i, red, green, blue, value;
1034     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1035 
1036     for (i = 0; i < entries; i++) {
1037         red   = lut[i].red;
1038         green = lut[i].green;
1039         blue  = lut[i].blue;
1040 
1041         value = (red<<20) | (green<<10) | blue;
1042 
1043         REG_SET(CM_3DLUT_DATA_30BIT, 0, CM_3DLUT_DATA_30BIT, value);
1044     }
1045 
1046 }
1047 
1048 
1049 static void dpp20_select_3dlut_ram_mask(
1050         struct dpp *dpp_base,
1051         uint32_t ram_selection_mask)
1052 {
1053     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1054 
1055     REG_UPDATE(CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_WRITE_EN_MASK,
1056             ram_selection_mask);
1057     REG_SET(CM_3DLUT_INDEX, 0, CM_3DLUT_INDEX, 0);
1058 }
1059 
1060 bool dpp20_program_3dlut(
1061         struct dpp *dpp_base,
1062         struct tetrahedral_params *params)
1063 {
1064     enum dc_lut_mode mode;
1065     bool is_17x17x17;
1066     bool is_12bits_color_channel;
1067     struct dc_rgb *lut0;
1068     struct dc_rgb *lut1;
1069     struct dc_rgb *lut2;
1070     struct dc_rgb *lut3;
1071     int lut_size0;
1072     int lut_size;
1073 
1074     if (params == NULL) {
1075         dpp20_set_3dlut_mode(dpp_base, LUT_BYPASS, false, false);
1076         return false;
1077     }
1078     mode = get3dlut_config(dpp_base, &is_17x17x17, &is_12bits_color_channel);
1079 
1080     if (mode == LUT_BYPASS || mode == LUT_RAM_B)
1081         mode = LUT_RAM_A;
1082     else
1083         mode = LUT_RAM_B;
1084 
1085     is_17x17x17 = !params->use_tetrahedral_9;
1086     is_12bits_color_channel = params->use_12bits;
1087     if (is_17x17x17) {
1088         lut0 = params->tetrahedral_17.lut0;
1089         lut1 = params->tetrahedral_17.lut1;
1090         lut2 = params->tetrahedral_17.lut2;
1091         lut3 = params->tetrahedral_17.lut3;
1092         lut_size0 = sizeof(params->tetrahedral_17.lut0)/
1093                     sizeof(params->tetrahedral_17.lut0[0]);
1094         lut_size  = sizeof(params->tetrahedral_17.lut1)/
1095                     sizeof(params->tetrahedral_17.lut1[0]);
1096     } else {
1097         lut0 = params->tetrahedral_9.lut0;
1098         lut1 = params->tetrahedral_9.lut1;
1099         lut2 = params->tetrahedral_9.lut2;
1100         lut3 = params->tetrahedral_9.lut3;
1101         lut_size0 = sizeof(params->tetrahedral_9.lut0)/
1102                 sizeof(params->tetrahedral_9.lut0[0]);
1103         lut_size  = sizeof(params->tetrahedral_9.lut1)/
1104                 sizeof(params->tetrahedral_9.lut1[0]);
1105         }
1106 
1107     dpp20_select_3dlut_ram(dpp_base, mode,
1108                 is_12bits_color_channel);
1109     dpp20_select_3dlut_ram_mask(dpp_base, 0x1);
1110     if (is_12bits_color_channel)
1111         dpp20_set3dlut_ram12(dpp_base, lut0, lut_size0);
1112     else
1113         dpp20_set3dlut_ram10(dpp_base, lut0, lut_size0);
1114 
1115     dpp20_select_3dlut_ram_mask(dpp_base, 0x2);
1116     if (is_12bits_color_channel)
1117         dpp20_set3dlut_ram12(dpp_base, lut1, lut_size);
1118     else
1119         dpp20_set3dlut_ram10(dpp_base, lut1, lut_size);
1120 
1121     dpp20_select_3dlut_ram_mask(dpp_base, 0x4);
1122     if (is_12bits_color_channel)
1123         dpp20_set3dlut_ram12(dpp_base, lut2, lut_size);
1124     else
1125         dpp20_set3dlut_ram10(dpp_base, lut2, lut_size);
1126 
1127     dpp20_select_3dlut_ram_mask(dpp_base, 0x8);
1128     if (is_12bits_color_channel)
1129         dpp20_set3dlut_ram12(dpp_base, lut3, lut_size);
1130     else
1131         dpp20_set3dlut_ram10(dpp_base, lut3, lut_size);
1132 
1133 
1134     dpp20_set_3dlut_mode(dpp_base, mode, is_12bits_color_channel,
1135                     is_17x17x17);
1136 
1137     return true;
1138 }
1139 
1140 void dpp2_set_hdr_multiplier(
1141         struct dpp *dpp_base,
1142         uint32_t multiplier)
1143 {
1144     struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1145 
1146     REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
1147 }