linux/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2020 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 *
  24 */
  25
  26#include "reg_helper.h"
  27#include "dcn30_mpc.h"
  28#include "dcn30_cm_common.h"
  29#include "basics/conversion.h"
  30#include "dcn10/dcn10_cm_common.h"
  31#include "dc.h"
  32
  33#define REG(reg)\
  34        mpc30->mpc_regs->reg
  35
  36#define CTX \
  37        mpc30->base.ctx
  38
  39#undef FN
  40#define FN(reg_name, field_name) \
  41        mpc30->mpc_shift->field_name, mpc30->mpc_mask->field_name
  42
  43
  44#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
  45
  46
  47static bool mpc3_is_dwb_idle(
  48        struct mpc *mpc,
  49        int dwb_id)
  50{
  51        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
  52        unsigned int status;
  53
  54        REG_GET(DWB_MUX[dwb_id], MPC_DWB0_MUX_STATUS, &status);
  55
  56        if (status == 0xf)
  57                return true;
  58        else
  59                return false;
  60}
  61
  62static void mpc3_set_dwb_mux(
  63        struct mpc *mpc,
  64        int dwb_id,
  65        int mpcc_id)
  66{
  67        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
  68
  69        REG_SET(DWB_MUX[dwb_id], 0,
  70                MPC_DWB0_MUX, mpcc_id);
  71}
  72
  73static void mpc3_disable_dwb_mux(
  74        struct mpc *mpc,
  75        int dwb_id)
  76{
  77        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
  78
  79        REG_SET(DWB_MUX[dwb_id], 0,
  80                MPC_DWB0_MUX, 0xf);
  81}
  82
  83static void mpc3_set_out_rate_control(
  84        struct mpc *mpc,
  85        int opp_id,
  86        bool enable,
  87        bool rate_2x_mode,
  88        struct mpc_dwb_flow_control *flow_control)
  89{
  90        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
  91
  92        REG_UPDATE_2(MUX[opp_id],
  93                        MPC_OUT_RATE_CONTROL_DISABLE, !enable,
  94                        MPC_OUT_RATE_CONTROL, rate_2x_mode);
  95
  96        if (flow_control)
  97                REG_UPDATE_2(MUX[opp_id],
  98                        MPC_OUT_FLOW_CONTROL_MODE, flow_control->flow_ctrl_mode,
  99                        MPC_OUT_FLOW_CONTROL_COUNT, flow_control->flow_ctrl_cnt1);
 100}
 101
 102static enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
 103{
 104        /*Contrary to DCN2 and DCN1 wherein a single status register field holds this info;
 105         *in DCN3/3AG, we need to read two separate fields to retrieve the same info
 106         */
 107        enum dc_lut_mode mode;
 108        uint32_t state_mode;
 109        uint32_t state_ram_lut_in_use;
 110        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 111
 112        REG_GET_2(MPCC_OGAM_CONTROL[mpcc_id],
 113                        MPCC_OGAM_MODE_CURRENT, &state_mode,
 114                        MPCC_OGAM_SELECT_CURRENT, &state_ram_lut_in_use);
 115
 116                switch (state_mode) {
 117                case 0:
 118                        mode = LUT_BYPASS;
 119                        break;
 120                case 2:
 121                        switch (state_ram_lut_in_use) {
 122                        case 0:
 123                                mode = LUT_RAM_A;
 124                                break;
 125                        case 1:
 126                                mode = LUT_RAM_B;
 127                                break;
 128                        default:
 129                                mode = LUT_BYPASS;
 130                                break;
 131                        }
 132                        break;
 133                default:
 134                        mode = LUT_BYPASS;
 135                        break;
 136                }
 137                return mode;
 138}
 139
 140static void mpc3_power_on_ogam_lut(
 141                struct mpc *mpc, int mpcc_id,
 142                bool power_on)
 143{
 144        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 145
 146        /*
 147         * Powering on: force memory active so the LUT can be updated.
 148         * Powering off: allow entering memory low power mode
 149         *
 150         * Memory low power mode is controlled during MPC OGAM LUT init.
 151         */
 152        REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id],
 153                   MPCC_OGAM_MEM_PWR_DIS, power_on != 0);
 154
 155        /* Wait for memory to be powered on - we won't be able to write to it otherwise. */
 156        if (power_on)
 157                REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10);
 158}
 159
 160static void mpc3_configure_ogam_lut(
 161                struct mpc *mpc, int mpcc_id,
 162                bool is_ram_a)
 163{
 164        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 165
 166        REG_UPDATE_2(MPCC_OGAM_LUT_CONTROL[mpcc_id],
 167                        MPCC_OGAM_LUT_WRITE_COLOR_MASK, 7,
 168                        MPCC_OGAM_LUT_HOST_SEL, is_ram_a == true ? 0:1);
 169
 170        REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
 171}
 172
 173static void mpc3_ogam_get_reg_field(
 174                struct mpc *mpc,
 175                struct dcn3_xfer_func_reg *reg)
 176{
 177        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 178
 179        reg->shifts.field_region_start_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;
 180        reg->masks.field_region_start_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;
 181        reg->shifts.field_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_OFFSET_B;
 182        reg->masks.field_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_OFFSET_B;
 183
 184        reg->shifts.exp_region0_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
 185        reg->masks.exp_region0_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
 186        reg->shifts.exp_region0_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
 187        reg->masks.exp_region0_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
 188        reg->shifts.exp_region1_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
 189        reg->masks.exp_region1_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
 190        reg->shifts.exp_region1_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
 191        reg->masks.exp_region1_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
 192
 193        reg->shifts.field_region_end = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_B;
 194        reg->masks.field_region_end = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_B;
 195        reg->shifts.field_region_end_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
 196        reg->masks.field_region_end_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
 197        reg->shifts.field_region_end_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
 198        reg->masks.field_region_end_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
 199        reg->shifts.field_region_linear_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
 200        reg->masks.field_region_linear_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
 201        reg->shifts.exp_region_start = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_B;
 202        reg->masks.exp_region_start = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_B;
 203        reg->shifts.exp_resion_start_segment = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
 204        reg->masks.exp_resion_start_segment = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
 205}
 206
 207static void mpc3_program_luta(struct mpc *mpc, int mpcc_id,
 208                const struct pwl_params *params)
 209{
 210        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 211        struct dcn3_xfer_func_reg gam_regs;
 212
 213        mpc3_ogam_get_reg_field(mpc, &gam_regs);
 214
 215        gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMA_START_CNTL_B[mpcc_id]);
 216        gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMA_START_CNTL_G[mpcc_id]);
 217        gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMA_START_CNTL_R[mpcc_id]);
 218        gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B[mpcc_id]);
 219        gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G[mpcc_id]);
 220        gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R[mpcc_id]);
 221        gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMA_END_CNTL1_B[mpcc_id]);
 222        gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMA_END_CNTL2_B[mpcc_id]);
 223        gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMA_END_CNTL1_G[mpcc_id]);
 224        gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMA_END_CNTL2_G[mpcc_id]);
 225        gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMA_END_CNTL1_R[mpcc_id]);
 226        gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMA_END_CNTL2_R[mpcc_id]);
 227        gam_regs.region_start = REG(MPCC_OGAM_RAMA_REGION_0_1[mpcc_id]);
 228        gam_regs.region_end = REG(MPCC_OGAM_RAMA_REGION_32_33[mpcc_id]);
 229        //New registers in DCN3AG/DCN OGAM block
 230        gam_regs.offset_b =  REG(MPCC_OGAM_RAMA_OFFSET_B[mpcc_id]);
 231        gam_regs.offset_g =  REG(MPCC_OGAM_RAMA_OFFSET_G[mpcc_id]);
 232        gam_regs.offset_r =  REG(MPCC_OGAM_RAMA_OFFSET_R[mpcc_id]);
 233        gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_B[mpcc_id]);
 234        gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_G[mpcc_id]);
 235        gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_R[mpcc_id]);
 236
 237        cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs);
 238}
 239
 240static void mpc3_program_lutb(struct mpc *mpc, int mpcc_id,
 241                const struct pwl_params *params)
 242{
 243        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 244        struct dcn3_xfer_func_reg gam_regs;
 245
 246        mpc3_ogam_get_reg_field(mpc, &gam_regs);
 247
 248        gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMB_START_CNTL_B[mpcc_id]);
 249        gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMB_START_CNTL_G[mpcc_id]);
 250        gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMB_START_CNTL_R[mpcc_id]);
 251        gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B[mpcc_id]);
 252        gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G[mpcc_id]);
 253        gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R[mpcc_id]);
 254        gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMB_END_CNTL1_B[mpcc_id]);
 255        gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMB_END_CNTL2_B[mpcc_id]);
 256        gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMB_END_CNTL1_G[mpcc_id]);
 257        gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMB_END_CNTL2_G[mpcc_id]);
 258        gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMB_END_CNTL1_R[mpcc_id]);
 259        gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMB_END_CNTL2_R[mpcc_id]);
 260        gam_regs.region_start = REG(MPCC_OGAM_RAMB_REGION_0_1[mpcc_id]);
 261        gam_regs.region_end = REG(MPCC_OGAM_RAMB_REGION_32_33[mpcc_id]);
 262        //New registers in DCN3AG/DCN OGAM block
 263        gam_regs.offset_b =  REG(MPCC_OGAM_RAMB_OFFSET_B[mpcc_id]);
 264        gam_regs.offset_g =  REG(MPCC_OGAM_RAMB_OFFSET_G[mpcc_id]);
 265        gam_regs.offset_r =  REG(MPCC_OGAM_RAMB_OFFSET_R[mpcc_id]);
 266        gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_B[mpcc_id]);
 267        gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_G[mpcc_id]);
 268        gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_R[mpcc_id]);
 269
 270        cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs);
 271}
 272
 273
 274static void mpc3_program_ogam_pwl(
 275                struct mpc *mpc, int mpcc_id,
 276                const struct pwl_result_data *rgb,
 277                uint32_t num)
 278{
 279        uint32_t i;
 280        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 281        uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
 282        uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg;
 283        uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg;
 284
 285        /*the entries of DCN3AG gamma LUTs take 18bit base values as opposed to
 286         *38 base+delta values per entry in earlier DCN architectures
 287         *last base value for our lut is compute by adding the last base value
 288         *in our data + last delta
 289         */
 290
 291        if (is_rgb_equal(rgb,  num)) {
 292                for (i = 0 ; i < num; i++)
 293                        REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
 294
 295                REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red);
 296
 297        } else {
 298
 299                REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
 300                                MPCC_OGAM_LUT_WRITE_COLOR_MASK, 4);
 301
 302                for (i = 0 ; i < num; i++)
 303                        REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
 304
 305                REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red);
 306
 307                REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
 308
 309                REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
 310                                MPCC_OGAM_LUT_WRITE_COLOR_MASK, 2);
 311
 312                for (i = 0 ; i < num; i++)
 313                        REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg);
 314
 315                REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_green);
 316
 317                REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
 318
 319                REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
 320                                MPCC_OGAM_LUT_WRITE_COLOR_MASK, 1);
 321
 322                for (i = 0 ; i < num; i++)
 323                        REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg);
 324
 325                REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_blue);
 326        }
 327
 328}
 329
 330void mpc3_set_output_gamma(
 331                struct mpc *mpc,
 332                int mpcc_id,
 333                const struct pwl_params *params)
 334{
 335        enum dc_lut_mode current_mode;
 336        enum dc_lut_mode next_mode;
 337        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 338
 339        if (mpc->ctx->dc->debug.cm_in_bypass) {
 340                REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0);
 341                return;
 342        }
 343
 344        if (params == NULL) { //disable OGAM
 345                REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 0);
 346                return;
 347        }
 348        //enable OGAM
 349        REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 2);
 350
 351        current_mode = mpc3_get_ogam_current(mpc, mpcc_id);
 352        if (current_mode == LUT_BYPASS)
 353                next_mode = LUT_RAM_A;
 354        else if (current_mode == LUT_RAM_A)
 355                next_mode = LUT_RAM_B;
 356        else
 357                next_mode = LUT_RAM_A;
 358
 359        mpc3_power_on_ogam_lut(mpc, mpcc_id, true);
 360        mpc3_configure_ogam_lut(mpc, mpcc_id, next_mode == LUT_RAM_A);
 361
 362        if (next_mode == LUT_RAM_A)
 363                mpc3_program_luta(mpc, mpcc_id, params);
 364        else
 365                mpc3_program_lutb(mpc, mpcc_id, params);
 366
 367        mpc3_program_ogam_pwl(
 368                        mpc, mpcc_id, params->rgb_resulted, params->hw_points_num);
 369
 370        /*we need to program 2 fields here as apposed to 1*/
 371        REG_UPDATE(MPCC_OGAM_CONTROL[mpcc_id],
 372                        MPCC_OGAM_SELECT, next_mode == LUT_RAM_A ? 0:1);
 373
 374        if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
 375                mpc3_power_on_ogam_lut(mpc, mpcc_id, false);
 376}
 377
 378void mpc3_set_denorm(
 379                struct mpc *mpc,
 380                int opp_id,
 381                enum dc_color_depth output_depth)
 382{
 383        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 384        /* De-normalize Fixed U1.13 color data to different target bit depths. 0 is bypass*/
 385        int denorm_mode = 0;
 386
 387        switch (output_depth) {
 388        case COLOR_DEPTH_666:
 389                denorm_mode = 1;
 390                break;
 391        case COLOR_DEPTH_888:
 392                denorm_mode = 2;
 393                break;
 394        case COLOR_DEPTH_999:
 395                denorm_mode = 3;
 396                break;
 397        case COLOR_DEPTH_101010:
 398                denorm_mode = 4;
 399                break;
 400        case COLOR_DEPTH_111111:
 401                denorm_mode = 5;
 402                break;
 403        case COLOR_DEPTH_121212:
 404                denorm_mode = 6;
 405                break;
 406        case COLOR_DEPTH_141414:
 407        case COLOR_DEPTH_161616:
 408        default:
 409                /* not valid used case! */
 410                break;
 411        }
 412
 413        REG_UPDATE(DENORM_CONTROL[opp_id],
 414                        MPC_OUT_DENORM_MODE, denorm_mode);
 415}
 416
 417void mpc3_set_denorm_clamp(
 418                struct mpc *mpc,
 419                int opp_id,
 420                struct mpc_denorm_clamp denorm_clamp)
 421{
 422        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 423
 424        /*program min and max clamp values for the pixel components*/
 425        REG_UPDATE_2(DENORM_CONTROL[opp_id],
 426                        MPC_OUT_DENORM_CLAMP_MAX_R_CR, denorm_clamp.clamp_max_r_cr,
 427                        MPC_OUT_DENORM_CLAMP_MIN_R_CR, denorm_clamp.clamp_min_r_cr);
 428        REG_UPDATE_2(DENORM_CLAMP_G_Y[opp_id],
 429                        MPC_OUT_DENORM_CLAMP_MAX_G_Y, denorm_clamp.clamp_max_g_y,
 430                        MPC_OUT_DENORM_CLAMP_MIN_G_Y, denorm_clamp.clamp_min_g_y);
 431        REG_UPDATE_2(DENORM_CLAMP_B_CB[opp_id],
 432                        MPC_OUT_DENORM_CLAMP_MAX_B_CB, denorm_clamp.clamp_max_b_cb,
 433                        MPC_OUT_DENORM_CLAMP_MIN_B_CB, denorm_clamp.clamp_min_b_cb);
 434}
 435
 436static enum dc_lut_mode mpc3_get_shaper_current(struct mpc *mpc, uint32_t rmu_idx)
 437{
 438        enum dc_lut_mode mode;
 439        uint32_t state_mode;
 440        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 441
 442        REG_GET(SHAPER_CONTROL[rmu_idx],
 443                        MPC_RMU_SHAPER_LUT_MODE_CURRENT, &state_mode);
 444
 445                switch (state_mode) {
 446                case 0:
 447                        mode = LUT_BYPASS;
 448                        break;
 449                case 1:
 450                        mode = LUT_RAM_A;
 451                        break;
 452                case 2:
 453                        mode = LUT_RAM_B;
 454                        break;
 455                default:
 456                        mode = LUT_BYPASS;
 457                        break;
 458                }
 459                return mode;
 460}
 461
 462static void mpc3_configure_shaper_lut(
 463                struct mpc *mpc,
 464                bool is_ram_a,
 465                uint32_t rmu_idx)
 466{
 467        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 468
 469        REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx],
 470                        MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, 7);
 471        REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx],
 472                        MPC_RMU_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
 473        REG_SET(SHAPER_LUT_INDEX[rmu_idx], 0, MPC_RMU_SHAPER_LUT_INDEX, 0);
 474}
 475
 476static void mpc3_program_shaper_luta_settings(
 477                struct mpc *mpc,
 478                const struct pwl_params *params,
 479                uint32_t rmu_idx)
 480{
 481        const struct gamma_curve *curve;
 482        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 483
 484        REG_SET_2(SHAPER_RAMA_START_CNTL_B[rmu_idx], 0,
 485                MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
 486                MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
 487        REG_SET_2(SHAPER_RAMA_START_CNTL_G[rmu_idx], 0,
 488                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
 489                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
 490        REG_SET_2(SHAPER_RAMA_START_CNTL_R[rmu_idx], 0,
 491                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
 492                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
 493
 494        REG_SET_2(SHAPER_RAMA_END_CNTL_B[rmu_idx], 0,
 495                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
 496                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
 497        REG_SET_2(SHAPER_RAMA_END_CNTL_G[rmu_idx], 0,
 498                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
 499                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
 500        REG_SET_2(SHAPER_RAMA_END_CNTL_R[rmu_idx], 0,
 501                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
 502                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
 503
 504        curve = params->arr_curve_points;
 505        REG_SET_4(SHAPER_RAMA_REGION_0_1[rmu_idx], 0,
 506                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 507                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 508                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 509                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 510
 511        curve += 2;
 512        REG_SET_4(SHAPER_RAMA_REGION_2_3[rmu_idx], 0,
 513                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 514                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 515                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 516                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 517
 518        curve += 2;
 519        REG_SET_4(SHAPER_RAMA_REGION_4_5[rmu_idx], 0,
 520                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 521                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 522                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 523                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 524
 525        curve += 2;
 526        REG_SET_4(SHAPER_RAMA_REGION_6_7[rmu_idx], 0,
 527                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 528                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 529                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 530                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 531
 532        curve += 2;
 533        REG_SET_4(SHAPER_RAMA_REGION_8_9[rmu_idx], 0,
 534                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 535                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 536                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 537                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 538
 539        curve += 2;
 540        REG_SET_4(SHAPER_RAMA_REGION_10_11[rmu_idx], 0,
 541                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 542                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 543                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 544                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 545
 546        curve += 2;
 547        REG_SET_4(SHAPER_RAMA_REGION_12_13[rmu_idx], 0,
 548                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 549                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 550                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 551                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 552
 553        curve += 2;
 554        REG_SET_4(SHAPER_RAMA_REGION_14_15[rmu_idx], 0,
 555                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 556                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 557                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 558                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 559
 560
 561        curve += 2;
 562        REG_SET_4(SHAPER_RAMA_REGION_16_17[rmu_idx], 0,
 563                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 564                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 565                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 566                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 567
 568        curve += 2;
 569        REG_SET_4(SHAPER_RAMA_REGION_18_19[rmu_idx], 0,
 570                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 571                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 572                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 573                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 574
 575        curve += 2;
 576        REG_SET_4(SHAPER_RAMA_REGION_20_21[rmu_idx], 0,
 577                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 578                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 579                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 580                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 581
 582        curve += 2;
 583        REG_SET_4(SHAPER_RAMA_REGION_22_23[rmu_idx], 0,
 584                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 585                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 586                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 587                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 588
 589        curve += 2;
 590        REG_SET_4(SHAPER_RAMA_REGION_24_25[rmu_idx], 0,
 591                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 592                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 593                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 594                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 595
 596        curve += 2;
 597        REG_SET_4(SHAPER_RAMA_REGION_26_27[rmu_idx], 0,
 598                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 599                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 600                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 601                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 602
 603        curve += 2;
 604        REG_SET_4(SHAPER_RAMA_REGION_28_29[rmu_idx], 0,
 605                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 606                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 607                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 608                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 609
 610        curve += 2;
 611        REG_SET_4(SHAPER_RAMA_REGION_30_31[rmu_idx], 0,
 612                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 613                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 614                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 615                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 616
 617        curve += 2;
 618        REG_SET_4(SHAPER_RAMA_REGION_32_33[rmu_idx], 0,
 619                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 620                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 621                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 622                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 623}
 624
 625static void mpc3_program_shaper_lutb_settings(
 626                struct mpc *mpc,
 627                const struct pwl_params *params,
 628                uint32_t rmu_idx)
 629{
 630        const struct gamma_curve *curve;
 631        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 632
 633        REG_SET_2(SHAPER_RAMB_START_CNTL_B[rmu_idx], 0,
 634                MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
 635                MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
 636        REG_SET_2(SHAPER_RAMB_START_CNTL_G[rmu_idx], 0,
 637                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
 638                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
 639        REG_SET_2(SHAPER_RAMB_START_CNTL_R[rmu_idx], 0,
 640                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
 641                        MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
 642
 643        REG_SET_2(SHAPER_RAMB_END_CNTL_B[rmu_idx], 0,
 644                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
 645                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
 646        REG_SET_2(SHAPER_RAMB_END_CNTL_G[rmu_idx], 0,
 647                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
 648                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
 649        REG_SET_2(SHAPER_RAMB_END_CNTL_R[rmu_idx], 0,
 650                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
 651                        MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
 652
 653        curve = params->arr_curve_points;
 654        REG_SET_4(SHAPER_RAMB_REGION_0_1[rmu_idx], 0,
 655                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 656                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 657                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 658                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 659
 660        curve += 2;
 661        REG_SET_4(SHAPER_RAMB_REGION_2_3[rmu_idx], 0,
 662                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 663                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 664                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 665                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 666
 667
 668        curve += 2;
 669        REG_SET_4(SHAPER_RAMB_REGION_4_5[rmu_idx], 0,
 670                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 671                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 672                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 673                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 674
 675        curve += 2;
 676        REG_SET_4(SHAPER_RAMB_REGION_6_7[rmu_idx], 0,
 677                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 678                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 679                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 680                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 681
 682        curve += 2;
 683        REG_SET_4(SHAPER_RAMB_REGION_8_9[rmu_idx], 0,
 684                MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 685                MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 686                MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 687                MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 688
 689        curve += 2;
 690        REG_SET_4(SHAPER_RAMB_REGION_10_11[rmu_idx], 0,
 691                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 692                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 693                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 694                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 695
 696        curve += 2;
 697        REG_SET_4(SHAPER_RAMB_REGION_12_13[rmu_idx], 0,
 698                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 699                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 700                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 701                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 702
 703        curve += 2;
 704        REG_SET_4(SHAPER_RAMB_REGION_14_15[rmu_idx], 0,
 705                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 706                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 707                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 708                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 709
 710
 711        curve += 2;
 712        REG_SET_4(SHAPER_RAMB_REGION_16_17[rmu_idx], 0,
 713                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 714                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 715                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 716                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 717
 718        curve += 2;
 719        REG_SET_4(SHAPER_RAMB_REGION_18_19[rmu_idx], 0,
 720                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 721                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 722                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 723                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 724
 725        curve += 2;
 726        REG_SET_4(SHAPER_RAMB_REGION_20_21[rmu_idx], 0,
 727                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 728                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 729                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 730                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 731
 732        curve += 2;
 733        REG_SET_4(SHAPER_RAMB_REGION_22_23[rmu_idx], 0,
 734                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 735                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 736                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 737                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 738
 739        curve += 2;
 740        REG_SET_4(SHAPER_RAMB_REGION_24_25[rmu_idx], 0,
 741                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 742                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 743                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 744                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 745
 746        curve += 2;
 747        REG_SET_4(SHAPER_RAMB_REGION_26_27[rmu_idx], 0,
 748                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 749                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 750                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 751                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 752
 753        curve += 2;
 754        REG_SET_4(SHAPER_RAMB_REGION_28_29[rmu_idx], 0,
 755                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 756                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 757                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 758                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 759
 760        curve += 2;
 761        REG_SET_4(SHAPER_RAMB_REGION_30_31[rmu_idx], 0,
 762                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 763                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 764                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 765                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 766
 767        curve += 2;
 768        REG_SET_4(SHAPER_RAMB_REGION_32_33[rmu_idx], 0,
 769                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
 770                        MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
 771                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
 772                        MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
 773}
 774
 775
 776static void mpc3_program_shaper_lut(
 777                struct mpc *mpc,
 778                const struct pwl_result_data *rgb,
 779                uint32_t num,
 780                uint32_t rmu_idx)
 781{
 782        uint32_t i, red, green, blue;
 783        uint32_t  red_delta, green_delta, blue_delta;
 784        uint32_t  red_value, green_value, blue_value;
 785
 786        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 787
 788        for (i = 0 ; i < num; i++) {
 789
 790                red   = rgb[i].red_reg;
 791                green = rgb[i].green_reg;
 792                blue  = rgb[i].blue_reg;
 793
 794                red_delta   = rgb[i].delta_red_reg;
 795                green_delta = rgb[i].delta_green_reg;
 796                blue_delta  = rgb[i].delta_blue_reg;
 797
 798                red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
 799                green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
 800                blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
 801
 802                REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, red_value);
 803                REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, green_value);
 804                REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, blue_value);
 805        }
 806
 807}
 808
 809static void mpc3_power_on_shaper_3dlut(
 810                struct mpc *mpc,
 811                uint32_t rmu_idx,
 812        bool power_on)
 813{
 814        uint32_t power_status_shaper = 2;
 815        uint32_t power_status_3dlut  = 2;
 816        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 817        int max_retries = 10;
 818
 819        if (rmu_idx == 0) {
 820                REG_SET(MPC_RMU_MEM_PWR_CTRL, 0,
 821                        MPC_RMU0_MEM_PWR_DIS, power_on == true ? 1:0);
 822                /* wait for memory to fully power up */
 823                if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
 824                        REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
 825                        REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
 826                }
 827
 828                /*read status is not mandatory, it is just for debugging*/
 829                REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, &power_status_shaper);
 830                REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
 831        } else if (rmu_idx == 1) {
 832                REG_SET(MPC_RMU_MEM_PWR_CTRL, 0,
 833                        MPC_RMU1_MEM_PWR_DIS, power_on == true ? 1:0);
 834                if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
 835                        REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
 836                        REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
 837                }
 838
 839                REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, &power_status_shaper);
 840                REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
 841        }
 842        /*TODO Add rmu_idx == 2 for SIENNA_CICHLID */
 843        if (power_status_shaper != 0 && power_on == true)
 844                BREAK_TO_DEBUGGER();
 845
 846        if (power_status_3dlut != 0 && power_on == true)
 847                BREAK_TO_DEBUGGER();
 848}
 849
 850
 851
 852bool mpc3_program_shaper(
 853                struct mpc *mpc,
 854                const struct pwl_params *params,
 855                uint32_t rmu_idx)
 856{
 857        enum dc_lut_mode current_mode;
 858        enum dc_lut_mode next_mode;
 859
 860        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 861
 862        if (params == NULL) {
 863                REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, 0);
 864                return false;
 865        }
 866
 867        if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
 868                mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true);
 869
 870        current_mode = mpc3_get_shaper_current(mpc, rmu_idx);
 871
 872        if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
 873                next_mode = LUT_RAM_B;
 874        else
 875                next_mode = LUT_RAM_A;
 876
 877        mpc3_configure_shaper_lut(mpc, next_mode == LUT_RAM_A ? true:false, rmu_idx);
 878
 879        if (next_mode == LUT_RAM_A)
 880                mpc3_program_shaper_luta_settings(mpc, params, rmu_idx);
 881        else
 882                mpc3_program_shaper_lutb_settings(mpc, params, rmu_idx);
 883
 884        mpc3_program_shaper_lut(
 885                        mpc, params->rgb_resulted, params->hw_points_num, rmu_idx);
 886
 887        REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
 888        mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false);
 889
 890        return true;
 891}
 892
 893static void mpc3_set_3dlut_mode(
 894                struct mpc *mpc,
 895                enum dc_lut_mode mode,
 896                bool is_color_channel_12bits,
 897                bool is_lut_size17x17x17,
 898                uint32_t rmu_idx)
 899{
 900        uint32_t lut_mode;
 901        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 902
 903        if (mode == LUT_BYPASS)
 904                lut_mode = 0;
 905        else if (mode == LUT_RAM_A)
 906                lut_mode = 1;
 907        else
 908                lut_mode = 2;
 909
 910        REG_UPDATE_2(RMU_3DLUT_MODE[rmu_idx],
 911                        MPC_RMU_3DLUT_MODE, lut_mode,
 912                        MPC_RMU_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
 913}
 914
 915static enum dc_lut_mode get3dlut_config(
 916                        struct mpc *mpc,
 917                        bool *is_17x17x17,
 918                        bool *is_12bits_color_channel,
 919                        int rmu_idx)
 920{
 921        uint32_t i_mode, i_enable_10bits, lut_size;
 922        enum dc_lut_mode mode;
 923        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 924
 925        REG_GET(RMU_3DLUT_MODE[rmu_idx],
 926                        MPC_RMU_3DLUT_MODE_CURRENT,  &i_mode);
 927
 928        REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx],
 929                        MPC_RMU_3DLUT_30BIT_EN, &i_enable_10bits);
 930
 931        switch (i_mode) {
 932        case 0:
 933                mode = LUT_BYPASS;
 934                break;
 935        case 1:
 936                mode = LUT_RAM_A;
 937                break;
 938        case 2:
 939                mode = LUT_RAM_B;
 940                break;
 941        default:
 942                mode = LUT_BYPASS;
 943                break;
 944        }
 945        if (i_enable_10bits > 0)
 946                *is_12bits_color_channel = false;
 947        else
 948                *is_12bits_color_channel = true;
 949
 950        REG_GET(RMU_3DLUT_MODE[rmu_idx], MPC_RMU_3DLUT_SIZE, &lut_size);
 951
 952        if (lut_size == 0)
 953                *is_17x17x17 = true;
 954        else
 955                *is_17x17x17 = false;
 956
 957        return mode;
 958}
 959
 960static void mpc3_select_3dlut_ram(
 961                struct mpc *mpc,
 962                enum dc_lut_mode mode,
 963                bool is_color_channel_12bits,
 964                uint32_t rmu_idx)
 965{
 966        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 967
 968        REG_UPDATE_2(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx],
 969                MPC_RMU_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
 970                MPC_RMU_3DLUT_30BIT_EN, is_color_channel_12bits == true ? 0:1);
 971}
 972
 973static void mpc3_select_3dlut_ram_mask(
 974                struct mpc *mpc,
 975                uint32_t ram_selection_mask,
 976                uint32_t rmu_idx)
 977{
 978        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 979
 980        REG_UPDATE(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], MPC_RMU_3DLUT_WRITE_EN_MASK,
 981                        ram_selection_mask);
 982        REG_SET(RMU_3DLUT_INDEX[rmu_idx], 0, MPC_RMU_3DLUT_INDEX, 0);
 983}
 984
 985static void mpc3_set3dlut_ram12(
 986                struct mpc *mpc,
 987                const struct dc_rgb *lut,
 988                uint32_t entries,
 989                uint32_t rmu_idx)
 990{
 991        uint32_t i, red, green, blue, red1, green1, blue1;
 992        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
 993
 994        for (i = 0 ; i < entries; i += 2) {
 995                red   = lut[i].red<<4;
 996                green = lut[i].green<<4;
 997                blue  = lut[i].blue<<4;
 998                red1   = lut[i+1].red<<4;
 999                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
1016static 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
1038static 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
1055static 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
1114void 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
1149bool 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
1234void 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
1273void 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
1317void 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
1331uint32_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
1346uint32_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
1365int 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
1384static void mpc3_mpc_init(struct mpc *mpc)
1385{
1386        struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1387        int mpcc_id;
1388
1389        mpc1_mpc_init(mpc);
1390
1391        if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
1392                if (mpc30->mpc_mask->MPC_RMU0_MEM_LOW_PWR_MODE && mpc30->mpc_mask->MPC_RMU1_MEM_LOW_PWR_MODE) {
1393                        REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, 3);
1394                        REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_LOW_PWR_MODE, 3);
1395                }
1396
1397                if (mpc30->mpc_mask->MPCC_OGAM_MEM_LOW_PWR_MODE) {
1398                        for (mpcc_id = 0; mpcc_id < mpc30->num_mpcc; mpcc_id++)
1399                                REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_LOW_PWR_MODE, 3);
1400                }
1401        }
1402}
1403
1404const struct mpc_funcs dcn30_mpc_funcs = {
1405        .read_mpcc_state = mpc1_read_mpcc_state,
1406        .insert_plane = mpc1_insert_plane,
1407        .remove_mpcc = mpc1_remove_mpcc,
1408        .mpc_init = mpc3_mpc_init,
1409        .mpc_init_single_inst = mpc1_mpc_init_single_inst,
1410        .update_blending = mpc2_update_blending,
1411        .cursor_lock = mpc1_cursor_lock,
1412        .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
1413        .wait_for_idle = mpc2_assert_idle_mpcc,
1414        .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
1415        .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
1416        .set_denorm =  mpc3_set_denorm,
1417        .set_denorm_clamp = mpc3_set_denorm_clamp,
1418        .set_output_csc = mpc3_set_output_csc,
1419        .set_ocsc_default = mpc3_set_ocsc_default,
1420        .set_output_gamma = mpc3_set_output_gamma,
1421        .insert_plane_to_secondary = NULL,
1422        .remove_mpcc_from_secondary =  NULL,
1423        .set_dwb_mux = mpc3_set_dwb_mux,
1424        .disable_dwb_mux = mpc3_disable_dwb_mux,
1425        .is_dwb_idle = mpc3_is_dwb_idle,
1426        .set_out_rate_control = mpc3_set_out_rate_control,
1427        .set_gamut_remap = mpc3_set_gamut_remap,
1428        .program_shaper = mpc3_program_shaper,
1429        .acquire_rmu = mpcc3_acquire_rmu,
1430        .program_3dlut = mpc3_program_3dlut,
1431        .release_rmu = mpcc3_release_rmu,
1432        .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
1433        .get_mpc_out_mux = mpc1_get_mpc_out_mux,
1434
1435};
1436
1437void dcn30_mpc_construct(struct dcn30_mpc *mpc30,
1438        struct dc_context *ctx,
1439        const struct dcn30_mpc_registers *mpc_regs,
1440        const struct dcn30_mpc_shift *mpc_shift,
1441        const struct dcn30_mpc_mask *mpc_mask,
1442        int num_mpcc,
1443        int num_rmu)
1444{
1445        int i;
1446
1447        mpc30->base.ctx = ctx;
1448
1449        mpc30->base.funcs = &dcn30_mpc_funcs;
1450
1451        mpc30->mpc_regs = mpc_regs;
1452        mpc30->mpc_shift = mpc_shift;
1453        mpc30->mpc_mask = mpc_mask;
1454
1455        mpc30->mpcc_in_use_mask = 0;
1456        mpc30->num_mpcc = num_mpcc;
1457        mpc30->num_rmu = num_rmu;
1458
1459        for (i = 0; i < MAX_MPCC; i++)
1460                mpc3_init_mpcc(&mpc30->base.mpcc_array[i], i);
1461}
1462
1463