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 "reg_helper.h"
0027 #include "dcn30_mpc.h"
0028 #include "dcn30_cm_common.h"
0029 #include "basics/conversion.h"
0030 #include "dcn10/dcn10_cm_common.h"
0031 #include "dc.h"
0032 
0033 #define REG(reg)\
0034     mpc30->mpc_regs->reg
0035 
0036 #define CTX \
0037     mpc30->base.ctx
0038 
0039 #undef FN
0040 #define FN(reg_name, field_name) \
0041     mpc30->mpc_shift->field_name, mpc30->mpc_mask->field_name
0042 
0043 
0044 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
0045 
0046 
0047 bool mpc3_is_dwb_idle(
0048     struct mpc *mpc,
0049     int dwb_id)
0050 {
0051     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0052     unsigned int status;
0053 
0054     REG_GET(DWB_MUX[dwb_id], MPC_DWB0_MUX_STATUS, &status);
0055 
0056     if (status == 0xf)
0057         return true;
0058     else
0059         return false;
0060 }
0061 
0062 void mpc3_set_dwb_mux(
0063     struct mpc *mpc,
0064     int dwb_id,
0065     int mpcc_id)
0066 {
0067     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0068 
0069     REG_SET(DWB_MUX[dwb_id], 0,
0070         MPC_DWB0_MUX, mpcc_id);
0071 }
0072 
0073 void mpc3_disable_dwb_mux(
0074     struct mpc *mpc,
0075     int dwb_id)
0076 {
0077     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0078 
0079     REG_SET(DWB_MUX[dwb_id], 0,
0080         MPC_DWB0_MUX, 0xf);
0081 }
0082 
0083 void mpc3_set_out_rate_control(
0084     struct mpc *mpc,
0085     int opp_id,
0086     bool enable,
0087     bool rate_2x_mode,
0088     struct mpc_dwb_flow_control *flow_control)
0089 {
0090     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0091 
0092     REG_UPDATE_2(MUX[opp_id],
0093             MPC_OUT_RATE_CONTROL_DISABLE, !enable,
0094             MPC_OUT_RATE_CONTROL, rate_2x_mode);
0095 
0096     if (flow_control)
0097         REG_UPDATE_2(MUX[opp_id],
0098             MPC_OUT_FLOW_CONTROL_MODE, flow_control->flow_ctrl_mode,
0099             MPC_OUT_FLOW_CONTROL_COUNT, flow_control->flow_ctrl_cnt1);
0100 }
0101 
0102 enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
0103 {
0104     /*Contrary to DCN2 and DCN1 wherein a single status register field holds this info;
0105      *in DCN3/3AG, we need to read two separate fields to retrieve the same info
0106      */
0107     enum dc_lut_mode mode;
0108     uint32_t state_mode;
0109     uint32_t state_ram_lut_in_use;
0110     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0111 
0112     REG_GET_2(MPCC_OGAM_CONTROL[mpcc_id], MPCC_OGAM_MODE_CURRENT, &state_mode,
0113           MPCC_OGAM_SELECT_CURRENT, &state_ram_lut_in_use);
0114 
0115     switch (state_mode) {
0116     case 0:
0117         mode = LUT_BYPASS;
0118         break;
0119     case 2:
0120         switch (state_ram_lut_in_use) {
0121         case 0:
0122             mode = LUT_RAM_A;
0123             break;
0124         case 1:
0125             mode = LUT_RAM_B;
0126             break;
0127         default:
0128             mode = LUT_BYPASS;
0129             break;
0130         }
0131         break;
0132     default:
0133         mode = LUT_BYPASS;
0134         break;
0135     }
0136 
0137     return mode;
0138 }
0139 
0140 void mpc3_power_on_ogam_lut(
0141         struct mpc *mpc, int mpcc_id,
0142         bool power_on)
0143 {
0144     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0145 
0146     /*
0147      * Powering on: force memory active so the LUT can be updated.
0148      * Powering off: allow entering memory low power mode
0149      *
0150      * Memory low power mode is controlled during MPC OGAM LUT init.
0151      */
0152     REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id],
0153            MPCC_OGAM_MEM_PWR_DIS, power_on != 0);
0154 
0155     /* Wait for memory to be powered on - we won't be able to write to it otherwise. */
0156     if (power_on)
0157         REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10);
0158 }
0159 
0160 static void mpc3_configure_ogam_lut(
0161         struct mpc *mpc, int mpcc_id,
0162         bool is_ram_a)
0163 {
0164     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0165 
0166     REG_UPDATE_2(MPCC_OGAM_LUT_CONTROL[mpcc_id],
0167             MPCC_OGAM_LUT_WRITE_COLOR_MASK, 7,
0168             MPCC_OGAM_LUT_HOST_SEL, is_ram_a == true ? 0:1);
0169 
0170     REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
0171 }
0172 
0173 static void mpc3_ogam_get_reg_field(
0174         struct mpc *mpc,
0175         struct dcn3_xfer_func_reg *reg)
0176 {
0177     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0178 
0179     reg->shifts.field_region_start_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;
0180     reg->masks.field_region_start_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;
0181     reg->shifts.field_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_OFFSET_B;
0182     reg->masks.field_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_OFFSET_B;
0183 
0184     reg->shifts.exp_region0_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0185     reg->masks.exp_region0_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
0186     reg->shifts.exp_region0_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0187     reg->masks.exp_region0_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
0188     reg->shifts.exp_region1_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0189     reg->masks.exp_region1_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
0190     reg->shifts.exp_region1_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0191     reg->masks.exp_region1_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
0192 
0193     reg->shifts.field_region_end = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_B;
0194     reg->masks.field_region_end = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_B;
0195     reg->shifts.field_region_end_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
0196     reg->masks.field_region_end_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
0197     reg->shifts.field_region_end_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
0198     reg->masks.field_region_end_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
0199     reg->shifts.field_region_linear_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
0200     reg->masks.field_region_linear_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
0201     reg->shifts.exp_region_start = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_B;
0202     reg->masks.exp_region_start = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_B;
0203     reg->shifts.exp_resion_start_segment = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
0204     reg->masks.exp_resion_start_segment = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
0205 }
0206 
0207 static void mpc3_program_luta(struct mpc *mpc, int mpcc_id,
0208         const struct pwl_params *params)
0209 {
0210     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0211     struct dcn3_xfer_func_reg gam_regs;
0212 
0213     mpc3_ogam_get_reg_field(mpc, &gam_regs);
0214 
0215     gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMA_START_CNTL_B[mpcc_id]);
0216     gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMA_START_CNTL_G[mpcc_id]);
0217     gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMA_START_CNTL_R[mpcc_id]);
0218     gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B[mpcc_id]);
0219     gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G[mpcc_id]);
0220     gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R[mpcc_id]);
0221     gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMA_END_CNTL1_B[mpcc_id]);
0222     gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMA_END_CNTL2_B[mpcc_id]);
0223     gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMA_END_CNTL1_G[mpcc_id]);
0224     gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMA_END_CNTL2_G[mpcc_id]);
0225     gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMA_END_CNTL1_R[mpcc_id]);
0226     gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMA_END_CNTL2_R[mpcc_id]);
0227     gam_regs.region_start = REG(MPCC_OGAM_RAMA_REGION_0_1[mpcc_id]);
0228     gam_regs.region_end = REG(MPCC_OGAM_RAMA_REGION_32_33[mpcc_id]);
0229     //New registers in DCN3AG/DCN OGAM block
0230     gam_regs.offset_b =  REG(MPCC_OGAM_RAMA_OFFSET_B[mpcc_id]);
0231     gam_regs.offset_g =  REG(MPCC_OGAM_RAMA_OFFSET_G[mpcc_id]);
0232     gam_regs.offset_r =  REG(MPCC_OGAM_RAMA_OFFSET_R[mpcc_id]);
0233     gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_B[mpcc_id]);
0234     gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_G[mpcc_id]);
0235     gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_R[mpcc_id]);
0236 
0237     cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs);
0238 }
0239 
0240 static void mpc3_program_lutb(struct mpc *mpc, int mpcc_id,
0241         const struct pwl_params *params)
0242 {
0243     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0244     struct dcn3_xfer_func_reg gam_regs;
0245 
0246     mpc3_ogam_get_reg_field(mpc, &gam_regs);
0247 
0248     gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMB_START_CNTL_B[mpcc_id]);
0249     gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMB_START_CNTL_G[mpcc_id]);
0250     gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMB_START_CNTL_R[mpcc_id]);
0251     gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B[mpcc_id]);
0252     gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G[mpcc_id]);
0253     gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R[mpcc_id]);
0254     gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMB_END_CNTL1_B[mpcc_id]);
0255     gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMB_END_CNTL2_B[mpcc_id]);
0256     gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMB_END_CNTL1_G[mpcc_id]);
0257     gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMB_END_CNTL2_G[mpcc_id]);
0258     gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMB_END_CNTL1_R[mpcc_id]);
0259     gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMB_END_CNTL2_R[mpcc_id]);
0260     gam_regs.region_start = REG(MPCC_OGAM_RAMB_REGION_0_1[mpcc_id]);
0261     gam_regs.region_end = REG(MPCC_OGAM_RAMB_REGION_32_33[mpcc_id]);
0262     //New registers in DCN3AG/DCN OGAM block
0263     gam_regs.offset_b =  REG(MPCC_OGAM_RAMB_OFFSET_B[mpcc_id]);
0264     gam_regs.offset_g =  REG(MPCC_OGAM_RAMB_OFFSET_G[mpcc_id]);
0265     gam_regs.offset_r =  REG(MPCC_OGAM_RAMB_OFFSET_R[mpcc_id]);
0266     gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_B[mpcc_id]);
0267     gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_G[mpcc_id]);
0268     gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_R[mpcc_id]);
0269 
0270     cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs);
0271 }
0272 
0273 
0274 static void mpc3_program_ogam_pwl(
0275         struct mpc *mpc, int mpcc_id,
0276         const struct pwl_result_data *rgb,
0277         uint32_t num)
0278 {
0279     uint32_t i;
0280     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0281     uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
0282     uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
0283     uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
0284 
0285     /*the entries of DCN3AG gamma LUTs take 18bit base values as opposed to
0286      *38 base+delta values per entry in earlier DCN architectures
0287      *last base value for our lut is compute by adding the last base value
0288      *in our data + last delta
0289      */
0290 
0291     if (is_rgb_equal(rgb,  num)) {
0292         for (i = 0 ; i < num; i++)
0293             REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
0294 
0295         REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red);
0296 
0297     } else {
0298 
0299         REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
0300                 MPCC_OGAM_LUT_WRITE_COLOR_MASK, 4);
0301 
0302         for (i = 0 ; i < num; i++)
0303             REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
0304 
0305         REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red);
0306 
0307         REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
0308 
0309         REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
0310                 MPCC_OGAM_LUT_WRITE_COLOR_MASK, 2);
0311 
0312         for (i = 0 ; i < num; i++)
0313             REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg);
0314 
0315         REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_green);
0316 
0317         REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
0318 
0319         REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
0320                 MPCC_OGAM_LUT_WRITE_COLOR_MASK, 1);
0321 
0322         for (i = 0 ; i < num; i++)
0323             REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg);
0324 
0325         REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_blue);
0326     }
0327 
0328 }
0329 
0330 void mpc3_set_output_gamma(
0331         struct mpc *mpc,
0332         int mpcc_id,
0333         const struct pwl_params *params)
0334 {
0335     enum dc_lut_mode current_mode;
0336     enum dc_lut_mode next_mode;
0337     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0338 
0339     if (mpc->ctx->dc->debug.cm_in_bypass) {
0340         REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0);
0341         return;
0342     }
0343 
0344     if (params == NULL) { //disable OGAM
0345         REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 0);
0346         return;
0347     }
0348     //enable OGAM
0349     REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 2);
0350 
0351     current_mode = mpc3_get_ogam_current(mpc, mpcc_id);
0352     if (current_mode == LUT_BYPASS)
0353         next_mode = LUT_RAM_A;
0354     else if (current_mode == LUT_RAM_A)
0355         next_mode = LUT_RAM_B;
0356     else
0357         next_mode = LUT_RAM_A;
0358 
0359     mpc3_power_on_ogam_lut(mpc, mpcc_id, true);
0360     mpc3_configure_ogam_lut(mpc, mpcc_id, next_mode == LUT_RAM_A);
0361 
0362     if (next_mode == LUT_RAM_A)
0363         mpc3_program_luta(mpc, mpcc_id, params);
0364     else
0365         mpc3_program_lutb(mpc, mpcc_id, params);
0366 
0367     mpc3_program_ogam_pwl(
0368             mpc, mpcc_id, params->rgb_resulted, params->hw_points_num);
0369 
0370     /*we need to program 2 fields here as apposed to 1*/
0371     REG_UPDATE(MPCC_OGAM_CONTROL[mpcc_id],
0372             MPCC_OGAM_SELECT, next_mode == LUT_RAM_A ? 0:1);
0373 
0374     if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
0375         mpc3_power_on_ogam_lut(mpc, mpcc_id, false);
0376 }
0377 
0378 void mpc3_set_denorm(
0379         struct mpc *mpc,
0380         int opp_id,
0381         enum dc_color_depth output_depth)
0382 {
0383     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0384     /* De-normalize Fixed U1.13 color data to different target bit depths. 0 is bypass*/
0385     int denorm_mode = 0;
0386 
0387     switch (output_depth) {
0388     case COLOR_DEPTH_666:
0389         denorm_mode = 1;
0390         break;
0391     case COLOR_DEPTH_888:
0392         denorm_mode = 2;
0393         break;
0394     case COLOR_DEPTH_999:
0395         denorm_mode = 3;
0396         break;
0397     case COLOR_DEPTH_101010:
0398         denorm_mode = 4;
0399         break;
0400     case COLOR_DEPTH_111111:
0401         denorm_mode = 5;
0402         break;
0403     case COLOR_DEPTH_121212:
0404         denorm_mode = 6;
0405         break;
0406     case COLOR_DEPTH_141414:
0407     case COLOR_DEPTH_161616:
0408     default:
0409         /* not valid used case! */
0410         break;
0411     }
0412 
0413     REG_UPDATE(DENORM_CONTROL[opp_id],
0414             MPC_OUT_DENORM_MODE, denorm_mode);
0415 }
0416 
0417 void mpc3_set_denorm_clamp(
0418         struct mpc *mpc,
0419         int opp_id,
0420         struct mpc_denorm_clamp denorm_clamp)
0421 {
0422     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0423 
0424     /*program min and max clamp values for the pixel components*/
0425     REG_UPDATE_2(DENORM_CONTROL[opp_id],
0426             MPC_OUT_DENORM_CLAMP_MAX_R_CR, denorm_clamp.clamp_max_r_cr,
0427             MPC_OUT_DENORM_CLAMP_MIN_R_CR, denorm_clamp.clamp_min_r_cr);
0428     REG_UPDATE_2(DENORM_CLAMP_G_Y[opp_id],
0429             MPC_OUT_DENORM_CLAMP_MAX_G_Y, denorm_clamp.clamp_max_g_y,
0430             MPC_OUT_DENORM_CLAMP_MIN_G_Y, denorm_clamp.clamp_min_g_y);
0431     REG_UPDATE_2(DENORM_CLAMP_B_CB[opp_id],
0432             MPC_OUT_DENORM_CLAMP_MAX_B_CB, denorm_clamp.clamp_max_b_cb,
0433             MPC_OUT_DENORM_CLAMP_MIN_B_CB, denorm_clamp.clamp_min_b_cb);
0434 }
0435 
0436 static enum dc_lut_mode mpc3_get_shaper_current(struct mpc *mpc, uint32_t rmu_idx)
0437 {
0438     enum dc_lut_mode mode;
0439     uint32_t state_mode;
0440     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0441 
0442     REG_GET(SHAPER_CONTROL[rmu_idx], MPC_RMU_SHAPER_LUT_MODE_CURRENT, &state_mode);
0443 
0444     switch (state_mode) {
0445     case 0:
0446         mode = LUT_BYPASS;
0447         break;
0448     case 1:
0449         mode = LUT_RAM_A;
0450         break;
0451     case 2:
0452         mode = LUT_RAM_B;
0453         break;
0454     default:
0455         mode = LUT_BYPASS;
0456         break;
0457     }
0458 
0459     return mode;
0460 }
0461 
0462 static void mpc3_configure_shaper_lut(
0463         struct mpc *mpc,
0464         bool is_ram_a,
0465         uint32_t rmu_idx)
0466 {
0467     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0468 
0469     REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx],
0470             MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, 7);
0471     REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx],
0472             MPC_RMU_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
0473     REG_SET(SHAPER_LUT_INDEX[rmu_idx], 0, MPC_RMU_SHAPER_LUT_INDEX, 0);
0474 }
0475 
0476 static void mpc3_program_shaper_luta_settings(
0477         struct mpc *mpc,
0478         const struct pwl_params *params,
0479         uint32_t rmu_idx)
0480 {
0481     const struct gamma_curve *curve;
0482     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0483 
0484     REG_SET_2(SHAPER_RAMA_START_CNTL_B[rmu_idx], 0,
0485         MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
0486         MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0487     REG_SET_2(SHAPER_RAMA_START_CNTL_G[rmu_idx], 0,
0488             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
0489             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0490     REG_SET_2(SHAPER_RAMA_START_CNTL_R[rmu_idx], 0,
0491             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
0492             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0493 
0494     REG_SET_2(SHAPER_RAMA_END_CNTL_B[rmu_idx], 0,
0495             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
0496             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
0497     REG_SET_2(SHAPER_RAMA_END_CNTL_G[rmu_idx], 0,
0498             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
0499             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
0500     REG_SET_2(SHAPER_RAMA_END_CNTL_R[rmu_idx], 0,
0501             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
0502             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
0503 
0504     curve = params->arr_curve_points;
0505     REG_SET_4(SHAPER_RAMA_REGION_0_1[rmu_idx], 0,
0506         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0507         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0508         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0509         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0510 
0511     curve += 2;
0512     REG_SET_4(SHAPER_RAMA_REGION_2_3[rmu_idx], 0,
0513         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0514         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0515         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0516         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0517 
0518     curve += 2;
0519     REG_SET_4(SHAPER_RAMA_REGION_4_5[rmu_idx], 0,
0520         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0521         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0522         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0523         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0524 
0525     curve += 2;
0526     REG_SET_4(SHAPER_RAMA_REGION_6_7[rmu_idx], 0,
0527         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0528         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0529         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0530         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0531 
0532     curve += 2;
0533     REG_SET_4(SHAPER_RAMA_REGION_8_9[rmu_idx], 0,
0534         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0535         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0536         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0537         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0538 
0539     curve += 2;
0540     REG_SET_4(SHAPER_RAMA_REGION_10_11[rmu_idx], 0,
0541         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0542         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0543         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0544         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0545 
0546     curve += 2;
0547     REG_SET_4(SHAPER_RAMA_REGION_12_13[rmu_idx], 0,
0548         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0549         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0550         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0551         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0552 
0553     curve += 2;
0554     REG_SET_4(SHAPER_RAMA_REGION_14_15[rmu_idx], 0,
0555         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0556         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0557         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0558         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0559 
0560 
0561     curve += 2;
0562     REG_SET_4(SHAPER_RAMA_REGION_16_17[rmu_idx], 0,
0563         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0564         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0565         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0566         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0567 
0568     curve += 2;
0569     REG_SET_4(SHAPER_RAMA_REGION_18_19[rmu_idx], 0,
0570         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0571         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0572         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0573         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0574 
0575     curve += 2;
0576     REG_SET_4(SHAPER_RAMA_REGION_20_21[rmu_idx], 0,
0577         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0578         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0579         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0580         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0581 
0582     curve += 2;
0583     REG_SET_4(SHAPER_RAMA_REGION_22_23[rmu_idx], 0,
0584         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0585         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0586         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0587         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0588 
0589     curve += 2;
0590     REG_SET_4(SHAPER_RAMA_REGION_24_25[rmu_idx], 0,
0591         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0592         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0593         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0594         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0595 
0596     curve += 2;
0597     REG_SET_4(SHAPER_RAMA_REGION_26_27[rmu_idx], 0,
0598             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0599             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0600             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0601             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0602 
0603     curve += 2;
0604     REG_SET_4(SHAPER_RAMA_REGION_28_29[rmu_idx], 0,
0605         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0606         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0607         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0608         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0609 
0610     curve += 2;
0611     REG_SET_4(SHAPER_RAMA_REGION_30_31[rmu_idx], 0,
0612         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0613         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0614         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0615         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0616 
0617     curve += 2;
0618     REG_SET_4(SHAPER_RAMA_REGION_32_33[rmu_idx], 0,
0619         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0620         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0621         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0622         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0623 }
0624 
0625 static void mpc3_program_shaper_lutb_settings(
0626         struct mpc *mpc,
0627         const struct pwl_params *params,
0628         uint32_t rmu_idx)
0629 {
0630     const struct gamma_curve *curve;
0631     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0632 
0633     REG_SET_2(SHAPER_RAMB_START_CNTL_B[rmu_idx], 0,
0634         MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
0635         MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0636     REG_SET_2(SHAPER_RAMB_START_CNTL_G[rmu_idx], 0,
0637             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
0638             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0639     REG_SET_2(SHAPER_RAMB_START_CNTL_R[rmu_idx], 0,
0640             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
0641             MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
0642 
0643     REG_SET_2(SHAPER_RAMB_END_CNTL_B[rmu_idx], 0,
0644             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
0645             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
0646     REG_SET_2(SHAPER_RAMB_END_CNTL_G[rmu_idx], 0,
0647             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
0648             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
0649     REG_SET_2(SHAPER_RAMB_END_CNTL_R[rmu_idx], 0,
0650             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
0651             MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
0652 
0653     curve = params->arr_curve_points;
0654     REG_SET_4(SHAPER_RAMB_REGION_0_1[rmu_idx], 0,
0655         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0656         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0657         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0658         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0659 
0660     curve += 2;
0661     REG_SET_4(SHAPER_RAMB_REGION_2_3[rmu_idx], 0,
0662             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0663             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0664             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0665             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0666 
0667 
0668     curve += 2;
0669     REG_SET_4(SHAPER_RAMB_REGION_4_5[rmu_idx], 0,
0670             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0671             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0672             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0673             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0674 
0675     curve += 2;
0676     REG_SET_4(SHAPER_RAMB_REGION_6_7[rmu_idx], 0,
0677             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0678             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0679             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0680             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0681 
0682     curve += 2;
0683     REG_SET_4(SHAPER_RAMB_REGION_8_9[rmu_idx], 0,
0684         MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0685         MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0686         MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0687         MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0688 
0689     curve += 2;
0690     REG_SET_4(SHAPER_RAMB_REGION_10_11[rmu_idx], 0,
0691             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0692             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0693             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0694             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0695 
0696     curve += 2;
0697     REG_SET_4(SHAPER_RAMB_REGION_12_13[rmu_idx], 0,
0698             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0699             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0700             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0701             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0702 
0703     curve += 2;
0704     REG_SET_4(SHAPER_RAMB_REGION_14_15[rmu_idx], 0,
0705             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0706             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0707             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0708             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0709 
0710 
0711     curve += 2;
0712     REG_SET_4(SHAPER_RAMB_REGION_16_17[rmu_idx], 0,
0713             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0714             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0715             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0716             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0717 
0718     curve += 2;
0719     REG_SET_4(SHAPER_RAMB_REGION_18_19[rmu_idx], 0,
0720             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0721             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0722             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0723             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0724 
0725     curve += 2;
0726     REG_SET_4(SHAPER_RAMB_REGION_20_21[rmu_idx], 0,
0727             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0728             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0729             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0730             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0731 
0732     curve += 2;
0733     REG_SET_4(SHAPER_RAMB_REGION_22_23[rmu_idx], 0,
0734             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0735             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0736             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0737             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0738 
0739     curve += 2;
0740     REG_SET_4(SHAPER_RAMB_REGION_24_25[rmu_idx], 0,
0741             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0742             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0743             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0744             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0745 
0746     curve += 2;
0747     REG_SET_4(SHAPER_RAMB_REGION_26_27[rmu_idx], 0,
0748             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0749             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0750             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0751             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0752 
0753     curve += 2;
0754     REG_SET_4(SHAPER_RAMB_REGION_28_29[rmu_idx], 0,
0755             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0756             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0757             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0758             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0759 
0760     curve += 2;
0761     REG_SET_4(SHAPER_RAMB_REGION_30_31[rmu_idx], 0,
0762             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0763             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0764             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0765             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0766 
0767     curve += 2;
0768     REG_SET_4(SHAPER_RAMB_REGION_32_33[rmu_idx], 0,
0769             MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
0770             MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
0771             MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
0772             MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
0773 }
0774 
0775 
0776 static void mpc3_program_shaper_lut(
0777         struct mpc *mpc,
0778         const struct pwl_result_data *rgb,
0779         uint32_t num,
0780         uint32_t rmu_idx)
0781 {
0782     uint32_t i, red, green, blue;
0783     uint32_t  red_delta, green_delta, blue_delta;
0784     uint32_t  red_value, green_value, blue_value;
0785 
0786     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0787 
0788     for (i = 0 ; i < num; i++) {
0789 
0790         red   = rgb[i].red_reg;
0791         green = rgb[i].green_reg;
0792         blue  = rgb[i].blue_reg;
0793 
0794         red_delta   = rgb[i].delta_red_reg;
0795         green_delta = rgb[i].delta_green_reg;
0796         blue_delta  = rgb[i].delta_blue_reg;
0797 
0798         red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
0799         green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
0800         blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
0801 
0802         REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, red_value);
0803         REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, green_value);
0804         REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, blue_value);
0805     }
0806 
0807 }
0808 
0809 static void mpc3_power_on_shaper_3dlut(
0810         struct mpc *mpc,
0811         uint32_t rmu_idx,
0812     bool power_on)
0813 {
0814     uint32_t power_status_shaper = 2;
0815     uint32_t power_status_3dlut  = 2;
0816     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0817     int max_retries = 10;
0818 
0819     if (rmu_idx == 0) {
0820         REG_SET(MPC_RMU_MEM_PWR_CTRL, 0,
0821             MPC_RMU0_MEM_PWR_DIS, power_on == true ? 1:0);
0822         /* wait for memory to fully power up */
0823         if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
0824             REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
0825             REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
0826         }
0827 
0828         /*read status is not mandatory, it is just for debugging*/
0829         REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, &power_status_shaper);
0830         REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
0831     } else if (rmu_idx == 1) {
0832         REG_SET(MPC_RMU_MEM_PWR_CTRL, 0,
0833             MPC_RMU1_MEM_PWR_DIS, power_on == true ? 1:0);
0834         if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
0835             REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
0836             REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
0837         }
0838 
0839         REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, &power_status_shaper);
0840         REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
0841     }
0842     /*TODO Add rmu_idx == 2 for SIENNA_CICHLID */
0843     if (power_status_shaper != 0 && power_on == true)
0844         BREAK_TO_DEBUGGER();
0845 
0846     if (power_status_3dlut != 0 && power_on == true)
0847         BREAK_TO_DEBUGGER();
0848 }
0849 
0850 
0851 
0852 bool mpc3_program_shaper(
0853         struct mpc *mpc,
0854         const struct pwl_params *params,
0855         uint32_t rmu_idx)
0856 {
0857     enum dc_lut_mode current_mode;
0858     enum dc_lut_mode next_mode;
0859 
0860     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0861 
0862     if (params == NULL) {
0863         REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, 0);
0864         return false;
0865     }
0866 
0867     if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
0868         mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true);
0869 
0870     current_mode = mpc3_get_shaper_current(mpc, rmu_idx);
0871 
0872     if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
0873         next_mode = LUT_RAM_B;
0874     else
0875         next_mode = LUT_RAM_A;
0876 
0877     mpc3_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, rmu_idx);
0878 
0879     if (next_mode == LUT_RAM_A)
0880         mpc3_program_shaper_luta_settings(mpc, params, rmu_idx);
0881     else
0882         mpc3_program_shaper_lutb_settings(mpc, params, rmu_idx);
0883 
0884     mpc3_program_shaper_lut(
0885             mpc, params->rgb_resulted, params->hw_points_num, rmu_idx);
0886 
0887     REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
0888     mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false);
0889 
0890     return true;
0891 }
0892 
0893 static void mpc3_set_3dlut_mode(
0894         struct mpc *mpc,
0895         enum dc_lut_mode mode,
0896         bool is_color_channel_12bits,
0897         bool is_lut_size17x17x17,
0898         uint32_t rmu_idx)
0899 {
0900     uint32_t lut_mode;
0901     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0902 
0903     if (mode == LUT_BYPASS)
0904         lut_mode = 0;
0905     else if (mode == LUT_RAM_A)
0906         lut_mode = 1;
0907     else
0908         lut_mode = 2;
0909 
0910     REG_UPDATE_2(RMU_3DLUT_MODE[rmu_idx],
0911             MPC_RMU_3DLUT_MODE, lut_mode,
0912             MPC_RMU_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
0913 }
0914 
0915 static enum dc_lut_mode get3dlut_config(
0916             struct mpc *mpc,
0917             bool *is_17x17x17,
0918             bool *is_12bits_color_channel,
0919             int rmu_idx)
0920 {
0921     uint32_t i_mode, i_enable_10bits, lut_size;
0922     enum dc_lut_mode mode;
0923     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0924 
0925     REG_GET(RMU_3DLUT_MODE[rmu_idx],
0926             MPC_RMU_3DLUT_MODE_CURRENT,  &i_mode);
0927 
0928     REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx],
0929             MPC_RMU_3DLUT_30BIT_EN, &i_enable_10bits);
0930 
0931     switch (i_mode) {
0932     case 0:
0933         mode = LUT_BYPASS;
0934         break;
0935     case 1:
0936         mode = LUT_RAM_A;
0937         break;
0938     case 2:
0939         mode = LUT_RAM_B;
0940         break;
0941     default:
0942         mode = LUT_BYPASS;
0943         break;
0944     }
0945     if (i_enable_10bits > 0)
0946         *is_12bits_color_channel = false;
0947     else
0948         *is_12bits_color_channel = true;
0949 
0950     REG_GET(RMU_3DLUT_MODE[rmu_idx], MPC_RMU_3DLUT_SIZE, &lut_size);
0951 
0952     if (lut_size == 0)
0953         *is_17x17x17 = true;
0954     else
0955         *is_17x17x17 = false;
0956 
0957     return mode;
0958 }
0959 
0960 static void mpc3_select_3dlut_ram(
0961         struct mpc *mpc,
0962         enum dc_lut_mode mode,
0963         bool is_color_channel_12bits,
0964         uint32_t rmu_idx)
0965 {
0966     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0967 
0968     REG_UPDATE_2(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx],
0969         MPC_RMU_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
0970         MPC_RMU_3DLUT_30BIT_EN, is_color_channel_12bits == true ? 0:1);
0971 }
0972 
0973 static void mpc3_select_3dlut_ram_mask(
0974         struct mpc *mpc,
0975         uint32_t ram_selection_mask,
0976         uint32_t rmu_idx)
0977 {
0978     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0979 
0980     REG_UPDATE(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], MPC_RMU_3DLUT_WRITE_EN_MASK,
0981             ram_selection_mask);
0982     REG_SET(RMU_3DLUT_INDEX[rmu_idx], 0, MPC_RMU_3DLUT_INDEX, 0);
0983 }
0984 
0985 static void mpc3_set3dlut_ram12(
0986         struct mpc *mpc,
0987         const struct dc_rgb *lut,
0988         uint32_t entries,
0989         uint32_t rmu_idx)
0990 {
0991     uint32_t i, red, green, blue, red1, green1, blue1;
0992     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
0993 
0994     for (i = 0 ; i < entries; i += 2) {
0995         red   = lut[i].red<<4;
0996         green = lut[i].green<<4;
0997         blue  = lut[i].blue<<4;
0998         red1   = lut[i+1].red<<4;
0999         green1 = lut[i+1].green<<4;
1000         blue1  = lut[i+1].blue<<4;
1001 
1002         REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0,
1003                 MPC_RMU_3DLUT_DATA0, red,
1004                 MPC_RMU_3DLUT_DATA1, red1);
1005 
1006         REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0,
1007                 MPC_RMU_3DLUT_DATA0, green,
1008                 MPC_RMU_3DLUT_DATA1, green1);
1009 
1010         REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0,
1011                 MPC_RMU_3DLUT_DATA0, blue,
1012                 MPC_RMU_3DLUT_DATA1, blue1);
1013     }
1014 }
1015 
1016 static void mpc3_set3dlut_ram10(
1017         struct mpc *mpc,
1018         const struct dc_rgb *lut,
1019         uint32_t entries,
1020         uint32_t rmu_idx)
1021 {
1022     uint32_t i, red, green, blue, value;
1023     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1024 
1025     for (i = 0; i < entries; i++) {
1026         red   = lut[i].red;
1027         green = lut[i].green;
1028         blue  = lut[i].blue;
1029         //should we shift red 22bit and green 12? ask Nvenko
1030         value = (red<<20) | (green<<10) | blue;
1031 
1032         REG_SET(RMU_3DLUT_DATA_30BIT[rmu_idx], 0, MPC_RMU_3DLUT_DATA_30BIT, value);
1033     }
1034 
1035 }
1036 
1037 
1038 void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
1039 {
1040     mpcc->mpcc_id = mpcc_inst;
1041     mpcc->dpp_id = 0xf;
1042     mpcc->mpcc_bot = NULL;
1043     mpcc->blnd_cfg.overlap_only = false;
1044     mpcc->blnd_cfg.global_alpha = 0xff;
1045     mpcc->blnd_cfg.global_gain = 0xff;
1046     mpcc->blnd_cfg.background_color_bpc = 4;
1047     mpcc->blnd_cfg.bottom_gain_mode = 0;
1048     mpcc->blnd_cfg.top_gain = 0x1f000;
1049     mpcc->blnd_cfg.bottom_inside_gain = 0x1f000;
1050     mpcc->blnd_cfg.bottom_outside_gain = 0x1f000;
1051     mpcc->sm_cfg.enable = false;
1052     mpcc->shared_bottom = false;
1053 }
1054 
1055 static void program_gamut_remap(
1056         struct dcn30_mpc *mpc30,
1057         int mpcc_id,
1058         const uint16_t *regval,
1059         int select)
1060 {
1061     uint16_t selection = 0;
1062     struct color_matrices_reg gam_regs;
1063 
1064     if (regval == NULL || select == GAMUT_REMAP_BYPASS) {
1065         REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0,
1066                 MPCC_GAMUT_REMAP_MODE, GAMUT_REMAP_BYPASS);
1067         return;
1068     }
1069     switch (select) {
1070     case GAMUT_REMAP_COEFF:
1071         selection = 1;
1072         break;
1073         /*this corresponds to GAMUT_REMAP coefficients set B
1074          * we don't have common coefficient sets in dcn3ag/dcn3
1075          */
1076     case GAMUT_REMAP_COMA_COEFF:
1077         selection = 2;
1078         break;
1079     default:
1080         break;
1081     }
1082 
1083     gam_regs.shifts.csc_c11 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
1084     gam_regs.masks.csc_c11  = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
1085     gam_regs.shifts.csc_c12 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
1086     gam_regs.masks.csc_c12 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
1087 
1088 
1089     if (select == GAMUT_REMAP_COEFF) {
1090         gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_A[mpcc_id]);
1091         gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_A[mpcc_id]);
1092 
1093         cm_helper_program_color_matrices(
1094                 mpc30->base.ctx,
1095                 regval,
1096                 &gam_regs);
1097 
1098     } else  if (select == GAMUT_REMAP_COMA_COEFF) {
1099 
1100         gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_B[mpcc_id]);
1101         gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_B[mpcc_id]);
1102 
1103         cm_helper_program_color_matrices(
1104                 mpc30->base.ctx,
1105                 regval,
1106                 &gam_regs);
1107 
1108     }
1109     //select coefficient set to use
1110     REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0,
1111                     MPCC_GAMUT_REMAP_MODE, selection);
1112 }
1113 
1114 void mpc3_set_gamut_remap(
1115         struct mpc *mpc,
1116         int mpcc_id,
1117         const struct mpc_grph_gamut_adjustment *adjust)
1118 {
1119     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1120     int i = 0;
1121     int gamut_mode;
1122 
1123     if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
1124         program_gamut_remap(mpc30, mpcc_id, NULL, GAMUT_REMAP_BYPASS);
1125     else {
1126         struct fixed31_32 arr_matrix[12];
1127         uint16_t arr_reg_val[12];
1128 
1129         for (i = 0; i < 12; i++)
1130             arr_matrix[i] = adjust->temperature_matrix[i];
1131 
1132         convert_float_matrix(
1133             arr_reg_val, arr_matrix, 12);
1134 
1135         //current coefficient set in use
1136         REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id], MPCC_GAMUT_REMAP_MODE_CURRENT, &gamut_mode);
1137 
1138         if (gamut_mode == 0)
1139             gamut_mode = 1; //use coefficient set A
1140         else if (gamut_mode == 1)
1141             gamut_mode = 2;
1142         else
1143             gamut_mode = 1;
1144 
1145         program_gamut_remap(mpc30, mpcc_id, arr_reg_val, gamut_mode);
1146     }
1147 }
1148 
1149 bool mpc3_program_3dlut(
1150         struct mpc *mpc,
1151         const struct tetrahedral_params *params,
1152         int rmu_idx)
1153 {
1154     enum dc_lut_mode mode;
1155     bool is_17x17x17;
1156     bool is_12bits_color_channel;
1157     const struct dc_rgb *lut0;
1158     const struct dc_rgb *lut1;
1159     const struct dc_rgb *lut2;
1160     const struct dc_rgb *lut3;
1161     int lut_size0;
1162     int lut_size;
1163 
1164     if (params == NULL) {
1165         mpc3_set_3dlut_mode(mpc, LUT_BYPASS, false, false, rmu_idx);
1166         return false;
1167     }
1168     mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true);
1169 
1170     mode = get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, rmu_idx);
1171 
1172     if (mode == LUT_BYPASS || mode == LUT_RAM_B)
1173         mode = LUT_RAM_A;
1174     else
1175         mode = LUT_RAM_B;
1176 
1177     is_17x17x17 = !params->use_tetrahedral_9;
1178     is_12bits_color_channel = params->use_12bits;
1179     if (is_17x17x17) {
1180         lut0 = params->tetrahedral_17.lut0;
1181         lut1 = params->tetrahedral_17.lut1;
1182         lut2 = params->tetrahedral_17.lut2;
1183         lut3 = params->tetrahedral_17.lut3;
1184         lut_size0 = sizeof(params->tetrahedral_17.lut0)/
1185                     sizeof(params->tetrahedral_17.lut0[0]);
1186         lut_size  = sizeof(params->tetrahedral_17.lut1)/
1187                     sizeof(params->tetrahedral_17.lut1[0]);
1188     } else {
1189         lut0 = params->tetrahedral_9.lut0;
1190         lut1 = params->tetrahedral_9.lut1;
1191         lut2 = params->tetrahedral_9.lut2;
1192         lut3 = params->tetrahedral_9.lut3;
1193         lut_size0 = sizeof(params->tetrahedral_9.lut0)/
1194                 sizeof(params->tetrahedral_9.lut0[0]);
1195         lut_size  = sizeof(params->tetrahedral_9.lut1)/
1196                 sizeof(params->tetrahedral_9.lut1[0]);
1197         }
1198 
1199     mpc3_select_3dlut_ram(mpc, mode,
1200                 is_12bits_color_channel, rmu_idx);
1201     mpc3_select_3dlut_ram_mask(mpc, 0x1, rmu_idx);
1202     if (is_12bits_color_channel)
1203         mpc3_set3dlut_ram12(mpc, lut0, lut_size0, rmu_idx);
1204     else
1205         mpc3_set3dlut_ram10(mpc, lut0, lut_size0, rmu_idx);
1206 
1207     mpc3_select_3dlut_ram_mask(mpc, 0x2, rmu_idx);
1208     if (is_12bits_color_channel)
1209         mpc3_set3dlut_ram12(mpc, lut1, lut_size, rmu_idx);
1210     else
1211         mpc3_set3dlut_ram10(mpc, lut1, lut_size, rmu_idx);
1212 
1213     mpc3_select_3dlut_ram_mask(mpc, 0x4, rmu_idx);
1214     if (is_12bits_color_channel)
1215         mpc3_set3dlut_ram12(mpc, lut2, lut_size, rmu_idx);
1216     else
1217         mpc3_set3dlut_ram10(mpc, lut2, lut_size, rmu_idx);
1218 
1219     mpc3_select_3dlut_ram_mask(mpc, 0x8, rmu_idx);
1220     if (is_12bits_color_channel)
1221         mpc3_set3dlut_ram12(mpc, lut3, lut_size, rmu_idx);
1222     else
1223         mpc3_set3dlut_ram10(mpc, lut3, lut_size, rmu_idx);
1224 
1225     mpc3_set_3dlut_mode(mpc, mode, is_12bits_color_channel,
1226                     is_17x17x17, rmu_idx);
1227 
1228     if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
1229         mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false);
1230 
1231     return true;
1232 }
1233 
1234 void mpc3_set_output_csc(
1235         struct mpc *mpc,
1236         int opp_id,
1237         const uint16_t *regval,
1238         enum mpc_output_csc_mode ocsc_mode)
1239 {
1240     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1241     struct color_matrices_reg ocsc_regs;
1242 
1243     REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0);
1244 
1245     REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
1246 
1247     if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE)
1248         return;
1249 
1250     if (regval == NULL) {
1251         BREAK_TO_DEBUGGER();
1252         return;
1253     }
1254 
1255     ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A;
1256     ocsc_regs.masks.csc_c11  = mpc30->mpc_mask->MPC_OCSC_C11_A;
1257     ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A;
1258     ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A;
1259 
1260     if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) {
1261         ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]);
1262         ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]);
1263     } else {
1264         ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]);
1265         ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]);
1266     }
1267     cm_helper_program_color_matrices(
1268             mpc30->base.ctx,
1269             regval,
1270             &ocsc_regs);
1271 }
1272 
1273 void mpc3_set_ocsc_default(
1274         struct mpc *mpc,
1275         int opp_id,
1276         enum dc_color_space color_space,
1277         enum mpc_output_csc_mode ocsc_mode)
1278 {
1279     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1280     uint32_t arr_size;
1281     struct color_matrices_reg ocsc_regs;
1282     const uint16_t *regval = NULL;
1283 
1284     REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0);
1285 
1286     REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
1287     if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE)
1288         return;
1289 
1290     regval = find_color_matrix(color_space, &arr_size);
1291 
1292     if (regval == NULL) {
1293         BREAK_TO_DEBUGGER();
1294         return;
1295     }
1296 
1297     ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A;
1298     ocsc_regs.masks.csc_c11  = mpc30->mpc_mask->MPC_OCSC_C11_A;
1299     ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A;
1300     ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A;
1301 
1302 
1303     if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) {
1304         ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]);
1305         ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]);
1306     } else {
1307         ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]);
1308         ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]);
1309     }
1310 
1311     cm_helper_program_color_matrices(
1312             mpc30->base.ctx,
1313             regval,
1314             &ocsc_regs);
1315 }
1316 
1317 void mpc3_set_rmu_mux(
1318     struct mpc *mpc,
1319     int rmu_idx,
1320     int value)
1321 {
1322     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1323 
1324     if (rmu_idx == 0)
1325         REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU0_MUX, value);
1326     else if (rmu_idx == 1)
1327         REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU1_MUX, value);
1328 
1329 }
1330 
1331 uint32_t mpc3_get_rmu_mux_status(
1332     struct mpc *mpc,
1333     int rmu_idx)
1334 {
1335     uint32_t status = 0xf;
1336     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1337 
1338     if (rmu_idx == 0)
1339         REG_GET(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, &status);
1340     else if (rmu_idx == 1)
1341         REG_GET(MPC_RMU_CONTROL, MPC_RMU1_MUX_STATUS, &status);
1342 
1343     return status;
1344 }
1345 
1346 uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx)
1347 {
1348     uint32_t rmu_status;
1349 
1350     //determine if this mpcc is already multiplexed to an RMU unit
1351     rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx);
1352     if (rmu_status == mpcc_id)
1353         //return rmu_idx of pre_acquired rmu unit
1354         return rmu_idx;
1355 
1356     if (rmu_status == 0xf) {//rmu unit is disabled
1357         mpc3_set_rmu_mux(mpc, rmu_idx, mpcc_id);
1358         return rmu_idx;
1359     }
1360 
1361     //no vacant RMU units or invalid parameters acquire_post_bldn_3dlut
1362     return -1;
1363 }
1364 
1365 static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id)
1366 {
1367     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1368     int rmu_idx;
1369     uint32_t rmu_status;
1370     int released_rmu = -1;
1371 
1372     for (rmu_idx = 0; rmu_idx < mpc30->num_rmu; rmu_idx++) {
1373         rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx);
1374         if (rmu_status == mpcc_id) {
1375             mpc3_set_rmu_mux(mpc, rmu_idx, 0xf);
1376             released_rmu = rmu_idx;
1377             break;
1378         }
1379     }
1380     return released_rmu;
1381 
1382 }
1383 
1384 static void mpc3_set_mpc_mem_lp_mode(struct mpc *mpc)
1385 {
1386     struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1387     int mpcc_id;
1388 
1389     if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
1390         if (mpc30->mpc_mask->MPC_RMU0_MEM_LOW_PWR_MODE && mpc30->mpc_mask->MPC_RMU1_MEM_LOW_PWR_MODE) {
1391             REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, 3);
1392             REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_LOW_PWR_MODE, 3);
1393         }
1394 
1395         if (mpc30->mpc_mask->MPCC_OGAM_MEM_LOW_PWR_MODE) {
1396             for (mpcc_id = 0; mpcc_id < mpc30->num_mpcc; mpcc_id++)
1397                 REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_LOW_PWR_MODE, 3);
1398         }
1399     }
1400 }
1401 
1402 const struct mpc_funcs dcn30_mpc_funcs = {
1403     .read_mpcc_state = mpc1_read_mpcc_state,
1404     .insert_plane = mpc1_insert_plane,
1405     .remove_mpcc = mpc1_remove_mpcc,
1406     .mpc_init = mpc1_mpc_init,
1407     .mpc_init_single_inst = mpc1_mpc_init_single_inst,
1408     .update_blending = mpc2_update_blending,
1409     .cursor_lock = mpc1_cursor_lock,
1410     .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
1411     .wait_for_idle = mpc2_assert_idle_mpcc,
1412     .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
1413     .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
1414     .set_denorm =  mpc3_set_denorm,
1415     .set_denorm_clamp = mpc3_set_denorm_clamp,
1416     .set_output_csc = mpc3_set_output_csc,
1417     .set_ocsc_default = mpc3_set_ocsc_default,
1418     .set_output_gamma = mpc3_set_output_gamma,
1419     .insert_plane_to_secondary = NULL,
1420     .remove_mpcc_from_secondary =  NULL,
1421     .set_dwb_mux = mpc3_set_dwb_mux,
1422     .disable_dwb_mux = mpc3_disable_dwb_mux,
1423     .is_dwb_idle = mpc3_is_dwb_idle,
1424     .set_out_rate_control = mpc3_set_out_rate_control,
1425     .set_gamut_remap = mpc3_set_gamut_remap,
1426     .program_shaper = mpc3_program_shaper,
1427     .acquire_rmu = mpcc3_acquire_rmu,
1428     .program_3dlut = mpc3_program_3dlut,
1429     .release_rmu = mpcc3_release_rmu,
1430     .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
1431     .get_mpc_out_mux = mpc1_get_mpc_out_mux,
1432     .set_bg_color = mpc1_set_bg_color,
1433     .set_mpc_mem_lp_mode = mpc3_set_mpc_mem_lp_mode,
1434 };
1435 
1436 void dcn30_mpc_construct(struct dcn30_mpc *mpc30,
1437     struct dc_context *ctx,
1438     const struct dcn30_mpc_registers *mpc_regs,
1439     const struct dcn30_mpc_shift *mpc_shift,
1440     const struct dcn30_mpc_mask *mpc_mask,
1441     int num_mpcc,
1442     int num_rmu)
1443 {
1444     int i;
1445 
1446     mpc30->base.ctx = ctx;
1447 
1448     mpc30->base.funcs = &dcn30_mpc_funcs;
1449 
1450     mpc30->mpc_regs = mpc_regs;
1451     mpc30->mpc_shift = mpc_shift;
1452     mpc30->mpc_mask = mpc_mask;
1453 
1454     mpc30->mpcc_in_use_mask = 0;
1455     mpc30->num_mpcc = num_mpcc;
1456     mpc30->num_rmu = num_rmu;
1457 
1458     for (i = 0; i < MAX_MPCC; i++)
1459         mpc3_init_mpcc(&mpc30->base.mpcc_array[i], i);
1460 }
1461