cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dcn30_mpc.c (48639B)


      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, 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
   1365static 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
   1384static 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
   1402const 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
   1436void 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