Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2020 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 #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     // debug option: put CM in bypass mode
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) {//Programmable RAM LUT
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     /*fill in the LUT with all base values to be used by pwl module
0093      * HW auto increments the LUT index: back-to-back write
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) { //bypass if we have no pwl data
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         //New registers in DCN3AG/DCN GAMCOR block
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         //New registers in DCN3AG/DCN GAMCOR block
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     //get register fields
0293     dpp3_gamcor_reg_field(dpp, &gam_regs);
0294 
0295     //program register set for LUTA/LUTB
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     //select Gamma LUT to use for next frame
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         /*this corresponds to GAMUT_REMAP coefficients set B
0335          *we don't have common coefficient sets in dcn3ag/dcn3
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     //select coefficient set to use
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         /* Bypass if type is bypass or hw */
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         //current coefficient set in use
0398         REG_GET(CM_GAMUT_REMAP_CONTROL, CM_GAMUT_REMAP_MODE_CURRENT, &gamut_mode);
0399 
0400         if (gamut_mode == 0)
0401             gamut_mode = 1; //use coefficient set A
0402         else if (gamut_mode == 1)
0403             gamut_mode = 2;
0404         else
0405             gamut_mode = 1;
0406 
0407         //follow dcn2 approach for now - using only coefficient set A
0408         program_gamut_remap(dpp, arr_reg_val, gamut_mode);
0409     }
0410 }