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
47void mpc3_mpc_init(struct mpc *mpc)
48{
49	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
50	int opp_id;
51
52	mpc1_mpc_init(mpc);
53
54	for (opp_id = 0; opp_id < MAX_OPP; opp_id++) {
55		if (REG(MUX[opp_id]))
56			/* disable mpc out rate and flow control */
57			REG_UPDATE_2(MUX[opp_id], MPC_OUT_RATE_CONTROL_DISABLE,
58					1, MPC_OUT_FLOW_CONTROL_COUNT, 0);
59	}
60}
61
62void mpc3_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
63{
64	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
65
66	mpc1_mpc_init_single_inst(mpc, mpcc_id);
67
68	/* assuming mpc out mux is connected to opp with the same index at this
69	 * point in time (e.g. transitioning from vbios to driver)
70	 */
71	if (mpcc_id < MAX_OPP && REG(MUX[mpcc_id]))
72		/* disable mpc out rate and flow control */
73		REG_UPDATE_2(MUX[mpcc_id], MPC_OUT_RATE_CONTROL_DISABLE,
74				1, MPC_OUT_FLOW_CONTROL_COUNT, 0);
75}
76
77bool mpc3_is_dwb_idle(
78	struct mpc *mpc,
79	int dwb_id)
80{
81	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
82	unsigned int status;
83
84	REG_GET(DWB_MUX[dwb_id], MPC_DWB0_MUX_STATUS, &status);
85
86	if (status == 0xf)
87		return true;
88	else
89		return false;
90}
91
92void mpc3_set_dwb_mux(
93	struct mpc *mpc,
94	int dwb_id,
95	int mpcc_id)
96{
97	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
98
99	REG_SET(DWB_MUX[dwb_id], 0,
100		MPC_DWB0_MUX, mpcc_id);
101}
102
103void mpc3_disable_dwb_mux(
104	struct mpc *mpc,
105	int dwb_id)
106{
107	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
108
109	REG_SET(DWB_MUX[dwb_id], 0,
110		MPC_DWB0_MUX, 0xf);
111}
112
113enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
114{
115	/*Contrary to DCN2 and DCN1 wherein a single status register field holds this info;
116	 *in DCN3/3AG, we need to read two separate fields to retrieve the same info
117	 */
118	enum dc_lut_mode mode;
119	uint32_t state_mode;
120	uint32_t state_ram_lut_in_use;
121	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
122
123	REG_GET_2(MPCC_OGAM_CONTROL[mpcc_id], MPCC_OGAM_MODE_CURRENT, &state_mode,
124		  MPCC_OGAM_SELECT_CURRENT, &state_ram_lut_in_use);
125
126	switch (state_mode) {
127	case 0:
128		mode = LUT_BYPASS;
129		break;
130	case 2:
131		switch (state_ram_lut_in_use) {
132		case 0:
133			mode = LUT_RAM_A;
134			break;
135		case 1:
136			mode = LUT_RAM_B;
137			break;
138		default:
139			mode = LUT_BYPASS;
140			break;
141		}
142		break;
143	default:
144		mode = LUT_BYPASS;
145		break;
146	}
147
148	return mode;
149}
150
151void mpc3_power_on_ogam_lut(
152		struct mpc *mpc, int mpcc_id,
153		bool power_on)
154{
155	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
156
157	/*
158	 * Powering on: force memory active so the LUT can be updated.
159	 * Powering off: allow entering memory low power mode
160	 *
161	 * Memory low power mode is controlled during MPC OGAM LUT init.
162	 */
163	REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id],
164		   MPCC_OGAM_MEM_PWR_DIS, power_on != 0);
165
166	/* Wait for memory to be powered on - we won't be able to write to it otherwise. */
167	if (power_on)
168		REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10);
169}
170
171static void mpc3_configure_ogam_lut(
172		struct mpc *mpc, int mpcc_id,
173		bool is_ram_a)
174{
175	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
176
177	REG_UPDATE_2(MPCC_OGAM_LUT_CONTROL[mpcc_id],
178			MPCC_OGAM_LUT_WRITE_COLOR_MASK, 7,
179			MPCC_OGAM_LUT_HOST_SEL, is_ram_a == true ? 0:1);
180
181	REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
182}
183
184static void mpc3_ogam_get_reg_field(
185		struct mpc *mpc,
186		struct dcn3_xfer_func_reg *reg)
187{
188	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
189
190	reg->shifts.field_region_start_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;
191	reg->masks.field_region_start_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;
192	reg->shifts.field_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_OFFSET_B;
193	reg->masks.field_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_OFFSET_B;
194
195	reg->shifts.exp_region0_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
196	reg->masks.exp_region0_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET;
197	reg->shifts.exp_region0_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
198	reg->masks.exp_region0_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
199	reg->shifts.exp_region1_lut_offset = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
200	reg->masks.exp_region1_lut_offset = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET;
201	reg->shifts.exp_region1_num_segments = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
202	reg->masks.exp_region1_num_segments = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
203
204	reg->shifts.field_region_end = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_B;
205	reg->masks.field_region_end = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_B;
206	reg->shifts.field_region_end_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
207	reg->masks.field_region_end_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B;
208	reg->shifts.field_region_end_base = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
209	reg->masks.field_region_end_base = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B;
210	reg->shifts.field_region_linear_slope = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
211	reg->masks.field_region_linear_slope = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B;
212	reg->shifts.exp_region_start = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_B;
213	reg->masks.exp_region_start = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_B;
214	reg->shifts.exp_resion_start_segment = mpc30->mpc_shift->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
215	reg->masks.exp_resion_start_segment = mpc30->mpc_mask->MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B;
216}
217
218static void mpc3_program_luta(struct mpc *mpc, int mpcc_id,
219		const struct pwl_params *params)
220{
221	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
222	struct dcn3_xfer_func_reg gam_regs;
223
224	mpc3_ogam_get_reg_field(mpc, &gam_regs);
225
226	gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMA_START_CNTL_B[mpcc_id]);
227	gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMA_START_CNTL_G[mpcc_id]);
228	gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMA_START_CNTL_R[mpcc_id]);
229	gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_B[mpcc_id]);
230	gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_G[mpcc_id]);
231	gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMA_START_SLOPE_CNTL_R[mpcc_id]);
232	gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMA_END_CNTL1_B[mpcc_id]);
233	gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMA_END_CNTL2_B[mpcc_id]);
234	gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMA_END_CNTL1_G[mpcc_id]);
235	gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMA_END_CNTL2_G[mpcc_id]);
236	gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMA_END_CNTL1_R[mpcc_id]);
237	gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMA_END_CNTL2_R[mpcc_id]);
238	gam_regs.region_start = REG(MPCC_OGAM_RAMA_REGION_0_1[mpcc_id]);
239	gam_regs.region_end = REG(MPCC_OGAM_RAMA_REGION_32_33[mpcc_id]);
240	//New registers in DCN3AG/DCN OGAM block
241	gam_regs.offset_b =  REG(MPCC_OGAM_RAMA_OFFSET_B[mpcc_id]);
242	gam_regs.offset_g =  REG(MPCC_OGAM_RAMA_OFFSET_G[mpcc_id]);
243	gam_regs.offset_r =  REG(MPCC_OGAM_RAMA_OFFSET_R[mpcc_id]);
244	gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_B[mpcc_id]);
245	gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_G[mpcc_id]);
246	gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMA_START_BASE_CNTL_R[mpcc_id]);
247
248	cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs);
249}
250
251static void mpc3_program_lutb(struct mpc *mpc, int mpcc_id,
252		const struct pwl_params *params)
253{
254	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
255	struct dcn3_xfer_func_reg gam_regs;
256
257	mpc3_ogam_get_reg_field(mpc, &gam_regs);
258
259	gam_regs.start_cntl_b = REG(MPCC_OGAM_RAMB_START_CNTL_B[mpcc_id]);
260	gam_regs.start_cntl_g = REG(MPCC_OGAM_RAMB_START_CNTL_G[mpcc_id]);
261	gam_regs.start_cntl_r = REG(MPCC_OGAM_RAMB_START_CNTL_R[mpcc_id]);
262	gam_regs.start_slope_cntl_b = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_B[mpcc_id]);
263	gam_regs.start_slope_cntl_g = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_G[mpcc_id]);
264	gam_regs.start_slope_cntl_r = REG(MPCC_OGAM_RAMB_START_SLOPE_CNTL_R[mpcc_id]);
265	gam_regs.start_end_cntl1_b = REG(MPCC_OGAM_RAMB_END_CNTL1_B[mpcc_id]);
266	gam_regs.start_end_cntl2_b = REG(MPCC_OGAM_RAMB_END_CNTL2_B[mpcc_id]);
267	gam_regs.start_end_cntl1_g = REG(MPCC_OGAM_RAMB_END_CNTL1_G[mpcc_id]);
268	gam_regs.start_end_cntl2_g = REG(MPCC_OGAM_RAMB_END_CNTL2_G[mpcc_id]);
269	gam_regs.start_end_cntl1_r = REG(MPCC_OGAM_RAMB_END_CNTL1_R[mpcc_id]);
270	gam_regs.start_end_cntl2_r = REG(MPCC_OGAM_RAMB_END_CNTL2_R[mpcc_id]);
271	gam_regs.region_start = REG(MPCC_OGAM_RAMB_REGION_0_1[mpcc_id]);
272	gam_regs.region_end = REG(MPCC_OGAM_RAMB_REGION_32_33[mpcc_id]);
273	//New registers in DCN3AG/DCN OGAM block
274	gam_regs.offset_b =  REG(MPCC_OGAM_RAMB_OFFSET_B[mpcc_id]);
275	gam_regs.offset_g =  REG(MPCC_OGAM_RAMB_OFFSET_G[mpcc_id]);
276	gam_regs.offset_r =  REG(MPCC_OGAM_RAMB_OFFSET_R[mpcc_id]);
277	gam_regs.start_base_cntl_b = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_B[mpcc_id]);
278	gam_regs.start_base_cntl_g = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_G[mpcc_id]);
279	gam_regs.start_base_cntl_r = REG(MPCC_OGAM_RAMB_START_BASE_CNTL_R[mpcc_id]);
280
281	cm_helper_program_gamcor_xfer_func(mpc30->base.ctx, params, &gam_regs);
282}
283
284
285static void mpc3_program_ogam_pwl(
286		struct mpc *mpc, int mpcc_id,
287		const struct pwl_result_data *rgb,
288		uint32_t num)
289{
290	uint32_t i;
291	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
292
293	if (is_rgb_equal(rgb,  num)) {
294		for (i = 0 ; i < num; i++)
295			REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
296	} else {
297
298		REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
299				MPCC_OGAM_LUT_WRITE_COLOR_MASK, 4);
300
301		for (i = 0 ; i < num; i++)
302			REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg);
303
304		REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
305
306		REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
307				MPCC_OGAM_LUT_WRITE_COLOR_MASK, 2);
308
309		for (i = 0 ; i < num; i++)
310			REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg);
311
312		REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0);
313
314		REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id],
315				MPCC_OGAM_LUT_WRITE_COLOR_MASK, 1);
316
317		for (i = 0 ; i < num; i++)
318			REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg);
319
320	}
321
322}
323
324void mpc3_set_output_gamma(
325		struct mpc *mpc,
326		int mpcc_id,
327		const struct pwl_params *params)
328{
329	enum dc_lut_mode current_mode;
330	enum dc_lut_mode next_mode;
331	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
332
333	if (mpc->ctx->dc->debug.cm_in_bypass) {
334		REG_SET(MPCC_OGAM_MODE[mpcc_id], 0, MPCC_OGAM_MODE, 0);
335		return;
336	}
337
338	if (params == NULL) { //disable OGAM
339		REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 0);
340		return;
341	}
342	//enable OGAM
343	REG_SET(MPCC_OGAM_CONTROL[mpcc_id], 0, MPCC_OGAM_MODE, 2);
344
345	current_mode = mpc3_get_ogam_current(mpc, mpcc_id);
346	if (current_mode == LUT_BYPASS)
347		next_mode = LUT_RAM_A;
348	else if (current_mode == LUT_RAM_A)
349		next_mode = LUT_RAM_B;
350	else
351		next_mode = LUT_RAM_A;
352
353	mpc3_power_on_ogam_lut(mpc, mpcc_id, true);
354	mpc3_configure_ogam_lut(mpc, mpcc_id, next_mode == LUT_RAM_A);
355
356	if (next_mode == LUT_RAM_A)
357		mpc3_program_luta(mpc, mpcc_id, params);
358	else
359		mpc3_program_lutb(mpc, mpcc_id, params);
360
361	mpc3_program_ogam_pwl(
362			mpc, mpcc_id, params->rgb_resulted, params->hw_points_num);
363
364	/*we need to program 2 fields here as apposed to 1*/
365	REG_UPDATE(MPCC_OGAM_CONTROL[mpcc_id],
366			MPCC_OGAM_SELECT, next_mode == LUT_RAM_A ? 0:1);
367
368	if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
369		mpc3_power_on_ogam_lut(mpc, mpcc_id, false);
370}
371
372void mpc3_set_denorm(
373		struct mpc *mpc,
374		int opp_id,
375		enum dc_color_depth output_depth)
376{
377	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
378	/* De-normalize Fixed U1.13 color data to different target bit depths. 0 is bypass*/
379	int denorm_mode = 0;
380
381	switch (output_depth) {
382	case COLOR_DEPTH_666:
383		denorm_mode = 1;
384		break;
385	case COLOR_DEPTH_888:
386		denorm_mode = 2;
387		break;
388	case COLOR_DEPTH_999:
389		denorm_mode = 3;
390		break;
391	case COLOR_DEPTH_101010:
392		denorm_mode = 4;
393		break;
394	case COLOR_DEPTH_111111:
395		denorm_mode = 5;
396		break;
397	case COLOR_DEPTH_121212:
398		denorm_mode = 6;
399		break;
400	case COLOR_DEPTH_141414:
401	case COLOR_DEPTH_161616:
402	default:
403		/* not valid used case! */
404		break;
405	}
406
407	REG_UPDATE(DENORM_CONTROL[opp_id],
408			MPC_OUT_DENORM_MODE, denorm_mode);
409}
410
411void mpc3_set_denorm_clamp(
412		struct mpc *mpc,
413		int opp_id,
414		struct mpc_denorm_clamp denorm_clamp)
415{
416	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
417
418	/*program min and max clamp values for the pixel components*/
419	REG_UPDATE_2(DENORM_CONTROL[opp_id],
420			MPC_OUT_DENORM_CLAMP_MAX_R_CR, denorm_clamp.clamp_max_r_cr,
421			MPC_OUT_DENORM_CLAMP_MIN_R_CR, denorm_clamp.clamp_min_r_cr);
422	REG_UPDATE_2(DENORM_CLAMP_G_Y[opp_id],
423			MPC_OUT_DENORM_CLAMP_MAX_G_Y, denorm_clamp.clamp_max_g_y,
424			MPC_OUT_DENORM_CLAMP_MIN_G_Y, denorm_clamp.clamp_min_g_y);
425	REG_UPDATE_2(DENORM_CLAMP_B_CB[opp_id],
426			MPC_OUT_DENORM_CLAMP_MAX_B_CB, denorm_clamp.clamp_max_b_cb,
427			MPC_OUT_DENORM_CLAMP_MIN_B_CB, denorm_clamp.clamp_min_b_cb);
428}
429
430static enum dc_lut_mode mpc3_get_shaper_current(struct mpc *mpc, uint32_t rmu_idx)
431{
432	enum dc_lut_mode mode;
433	uint32_t state_mode;
434	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
435
436	REG_GET(SHAPER_CONTROL[rmu_idx], MPC_RMU_SHAPER_LUT_MODE_CURRENT, &state_mode);
437
438	switch (state_mode) {
439	case 0:
440		mode = LUT_BYPASS;
441		break;
442	case 1:
443		mode = LUT_RAM_A;
444		break;
445	case 2:
446		mode = LUT_RAM_B;
447		break;
448	default:
449		mode = LUT_BYPASS;
450		break;
451	}
452
453	return mode;
454}
455
456static void mpc3_configure_shaper_lut(
457		struct mpc *mpc,
458		bool is_ram_a,
459		uint32_t rmu_idx)
460{
461	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
462
463	REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx],
464			MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, 7);
465	REG_UPDATE(SHAPER_LUT_WRITE_EN_MASK[rmu_idx],
466			MPC_RMU_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
467	REG_SET(SHAPER_LUT_INDEX[rmu_idx], 0, MPC_RMU_SHAPER_LUT_INDEX, 0);
468}
469
470static void mpc3_program_shaper_luta_settings(
471		struct mpc *mpc,
472		const struct pwl_params *params,
473		uint32_t rmu_idx)
474{
475	const struct gamma_curve *curve;
476	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
477
478	REG_SET_2(SHAPER_RAMA_START_CNTL_B[rmu_idx], 0,
479		MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
480		MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
481	REG_SET_2(SHAPER_RAMA_START_CNTL_G[rmu_idx], 0,
482			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
483			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
484	REG_SET_2(SHAPER_RAMA_START_CNTL_R[rmu_idx], 0,
485			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
486			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
487
488	REG_SET_2(SHAPER_RAMA_END_CNTL_B[rmu_idx], 0,
489			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
490			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
491	REG_SET_2(SHAPER_RAMA_END_CNTL_G[rmu_idx], 0,
492			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
493			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
494	REG_SET_2(SHAPER_RAMA_END_CNTL_R[rmu_idx], 0,
495			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
496			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
497
498	curve = params->arr_curve_points;
499	REG_SET_4(SHAPER_RAMA_REGION_0_1[rmu_idx], 0,
500		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
501		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
502		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
503		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
504
505	curve += 2;
506	REG_SET_4(SHAPER_RAMA_REGION_2_3[rmu_idx], 0,
507		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
508		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
509		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
510		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
511
512	curve += 2;
513	REG_SET_4(SHAPER_RAMA_REGION_4_5[rmu_idx], 0,
514		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
515		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
516		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
517		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
518
519	curve += 2;
520	REG_SET_4(SHAPER_RAMA_REGION_6_7[rmu_idx], 0,
521		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
522		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
523		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
524		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
525
526	curve += 2;
527	REG_SET_4(SHAPER_RAMA_REGION_8_9[rmu_idx], 0,
528		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
529		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
530		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
531		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
532
533	curve += 2;
534	REG_SET_4(SHAPER_RAMA_REGION_10_11[rmu_idx], 0,
535		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
536		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
537		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
538		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
539
540	curve += 2;
541	REG_SET_4(SHAPER_RAMA_REGION_12_13[rmu_idx], 0,
542		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
543		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
544		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
545		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
546
547	curve += 2;
548	REG_SET_4(SHAPER_RAMA_REGION_14_15[rmu_idx], 0,
549		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
550		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
551		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
552		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
553
554
555	curve += 2;
556	REG_SET_4(SHAPER_RAMA_REGION_16_17[rmu_idx], 0,
557		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
558		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
559		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
560		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
561
562	curve += 2;
563	REG_SET_4(SHAPER_RAMA_REGION_18_19[rmu_idx], 0,
564		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
565		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
566		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
567		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
568
569	curve += 2;
570	REG_SET_4(SHAPER_RAMA_REGION_20_21[rmu_idx], 0,
571		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
572		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
573		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
574		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
575
576	curve += 2;
577	REG_SET_4(SHAPER_RAMA_REGION_22_23[rmu_idx], 0,
578		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
579		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
580		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
581		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
582
583	curve += 2;
584	REG_SET_4(SHAPER_RAMA_REGION_24_25[rmu_idx], 0,
585		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
586		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
587		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
588		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
589
590	curve += 2;
591	REG_SET_4(SHAPER_RAMA_REGION_26_27[rmu_idx], 0,
592			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
593			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
594			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
595			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
596
597	curve += 2;
598	REG_SET_4(SHAPER_RAMA_REGION_28_29[rmu_idx], 0,
599		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
600		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
601		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
602		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
603
604	curve += 2;
605	REG_SET_4(SHAPER_RAMA_REGION_30_31[rmu_idx], 0,
606		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
607		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
608		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
609		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
610
611	curve += 2;
612	REG_SET_4(SHAPER_RAMA_REGION_32_33[rmu_idx], 0,
613		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
614		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
615		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
616		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
617}
618
619static void mpc3_program_shaper_lutb_settings(
620		struct mpc *mpc,
621		const struct pwl_params *params,
622		uint32_t rmu_idx)
623{
624	const struct gamma_curve *curve;
625	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
626
627	REG_SET_2(SHAPER_RAMB_START_CNTL_B[rmu_idx], 0,
628		MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
629		MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
630	REG_SET_2(SHAPER_RAMB_START_CNTL_G[rmu_idx], 0,
631			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
632			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
633	REG_SET_2(SHAPER_RAMB_START_CNTL_R[rmu_idx], 0,
634			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
635			MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
636
637	REG_SET_2(SHAPER_RAMB_END_CNTL_B[rmu_idx], 0,
638			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
639			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
640	REG_SET_2(SHAPER_RAMB_END_CNTL_G[rmu_idx], 0,
641			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
642			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
643	REG_SET_2(SHAPER_RAMB_END_CNTL_R[rmu_idx], 0,
644			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
645			MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
646
647	curve = params->arr_curve_points;
648	REG_SET_4(SHAPER_RAMB_REGION_0_1[rmu_idx], 0,
649		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
650		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
651		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
652		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
653
654	curve += 2;
655	REG_SET_4(SHAPER_RAMB_REGION_2_3[rmu_idx], 0,
656			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
657			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
658			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
659			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
660
661
662	curve += 2;
663	REG_SET_4(SHAPER_RAMB_REGION_4_5[rmu_idx], 0,
664			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
665			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
666			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
667			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
668
669	curve += 2;
670	REG_SET_4(SHAPER_RAMB_REGION_6_7[rmu_idx], 0,
671			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
672			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
673			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
674			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
675
676	curve += 2;
677	REG_SET_4(SHAPER_RAMB_REGION_8_9[rmu_idx], 0,
678		MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
679		MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
680		MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
681		MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
682
683	curve += 2;
684	REG_SET_4(SHAPER_RAMB_REGION_10_11[rmu_idx], 0,
685			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
686			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
687			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
688			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
689
690	curve += 2;
691	REG_SET_4(SHAPER_RAMB_REGION_12_13[rmu_idx], 0,
692			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
693			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
694			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
695			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
696
697	curve += 2;
698	REG_SET_4(SHAPER_RAMB_REGION_14_15[rmu_idx], 0,
699			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
700			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
701			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
702			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
703
704
705	curve += 2;
706	REG_SET_4(SHAPER_RAMB_REGION_16_17[rmu_idx], 0,
707			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
708			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
709			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
710			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
711
712	curve += 2;
713	REG_SET_4(SHAPER_RAMB_REGION_18_19[rmu_idx], 0,
714			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
715			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
716			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
717			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
718
719	curve += 2;
720	REG_SET_4(SHAPER_RAMB_REGION_20_21[rmu_idx], 0,
721			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
722			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
723			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
724			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
725
726	curve += 2;
727	REG_SET_4(SHAPER_RAMB_REGION_22_23[rmu_idx], 0,
728			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
729			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
730			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
731			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
732
733	curve += 2;
734	REG_SET_4(SHAPER_RAMB_REGION_24_25[rmu_idx], 0,
735			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
736			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
737			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
738			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
739
740	curve += 2;
741	REG_SET_4(SHAPER_RAMB_REGION_26_27[rmu_idx], 0,
742			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
743			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
744			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
745			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
746
747	curve += 2;
748	REG_SET_4(SHAPER_RAMB_REGION_28_29[rmu_idx], 0,
749			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
750			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
751			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
752			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
753
754	curve += 2;
755	REG_SET_4(SHAPER_RAMB_REGION_30_31[rmu_idx], 0,
756			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
757			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
758			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
759			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
760
761	curve += 2;
762	REG_SET_4(SHAPER_RAMB_REGION_32_33[rmu_idx], 0,
763			MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
764			MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
765			MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
766			MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
767}
768
769
770static void mpc3_program_shaper_lut(
771		struct mpc *mpc,
772		const struct pwl_result_data *rgb,
773		uint32_t num,
774		uint32_t rmu_idx)
775{
776	uint32_t i, red, green, blue;
777	uint32_t  red_delta, green_delta, blue_delta;
778	uint32_t  red_value, green_value, blue_value;
779
780	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
781
782	for (i = 0 ; i < num; i++) {
783
784		red   = rgb[i].red_reg;
785		green = rgb[i].green_reg;
786		blue  = rgb[i].blue_reg;
787
788		red_delta   = rgb[i].delta_red_reg;
789		green_delta = rgb[i].delta_green_reg;
790		blue_delta  = rgb[i].delta_blue_reg;
791
792		red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
793		green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
794		blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
795
796		REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, red_value);
797		REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, green_value);
798		REG_SET(SHAPER_LUT_DATA[rmu_idx], 0, MPC_RMU_SHAPER_LUT_DATA, blue_value);
799	}
800
801}
802
803static void mpc3_power_on_shaper_3dlut(
804		struct mpc *mpc,
805		uint32_t rmu_idx,
806	bool power_on)
807{
808	uint32_t power_status_shaper = 2;
809	uint32_t power_status_3dlut  = 2;
810	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
811	int max_retries = 10;
812
813	if (rmu_idx == 0) {
814		REG_SET(MPC_RMU_MEM_PWR_CTRL, 0,
815			MPC_RMU0_MEM_PWR_DIS, power_on == true ? 1:0);
816		/* wait for memory to fully power up */
817		if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
818			REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
819			REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
820		}
821
822		/*read status is not mandatory, it is just for debugging*/
823		REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, &power_status_shaper);
824		REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
825	} else if (rmu_idx == 1) {
826		REG_SET(MPC_RMU_MEM_PWR_CTRL, 0,
827			MPC_RMU1_MEM_PWR_DIS, power_on == true ? 1:0);
828		if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
829			REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
830			REG_WAIT(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
831		}
832
833		REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_SHAPER_MEM_PWR_STATE, &power_status_shaper);
834		REG_GET(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
835	}
836	/*TODO Add rmu_idx == 2 for SIENNA_CICHLID */
837	if (power_status_shaper != 0 && power_on == true)
838		BREAK_TO_DEBUGGER();
839
840	if (power_status_3dlut != 0 && power_on == true)
841		BREAK_TO_DEBUGGER();
842}
843
844
845
846bool mpc3_program_shaper(
847		struct mpc *mpc,
848		const struct pwl_params *params,
849		uint32_t rmu_idx)
850{
851	enum dc_lut_mode current_mode;
852	enum dc_lut_mode next_mode;
853
854	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
855
856	if (params == NULL) {
857		REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, 0);
858		return false;
859	}
860
861	if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
862		mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true);
863
864	current_mode = mpc3_get_shaper_current(mpc, rmu_idx);
865
866	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
867		next_mode = LUT_RAM_B;
868	else
869		next_mode = LUT_RAM_A;
870
871	mpc3_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, rmu_idx);
872
873	if (next_mode == LUT_RAM_A)
874		mpc3_program_shaper_luta_settings(mpc, params, rmu_idx);
875	else
876		mpc3_program_shaper_lutb_settings(mpc, params, rmu_idx);
877
878	mpc3_program_shaper_lut(
879			mpc, params->rgb_resulted, params->hw_points_num, rmu_idx);
880
881	REG_SET(SHAPER_CONTROL[rmu_idx], 0, MPC_RMU_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
882	mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false);
883
884	return true;
885}
886
887static void mpc3_set_3dlut_mode(
888		struct mpc *mpc,
889		enum dc_lut_mode mode,
890		bool is_color_channel_12bits,
891		bool is_lut_size17x17x17,
892		uint32_t rmu_idx)
893{
894	uint32_t lut_mode;
895	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
896
897	if (mode == LUT_BYPASS)
898		lut_mode = 0;
899	else if (mode == LUT_RAM_A)
900		lut_mode = 1;
901	else
902		lut_mode = 2;
903
904	REG_UPDATE_2(RMU_3DLUT_MODE[rmu_idx],
905			MPC_RMU_3DLUT_MODE, lut_mode,
906			MPC_RMU_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
907}
908
909static enum dc_lut_mode get3dlut_config(
910			struct mpc *mpc,
911			bool *is_17x17x17,
912			bool *is_12bits_color_channel,
913			int rmu_idx)
914{
915	uint32_t i_mode, i_enable_10bits, lut_size;
916	enum dc_lut_mode mode;
917	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
918
919	REG_GET(RMU_3DLUT_MODE[rmu_idx],
920			MPC_RMU_3DLUT_MODE_CURRENT,  &i_mode);
921
922	REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx],
923			MPC_RMU_3DLUT_30BIT_EN, &i_enable_10bits);
924
925	switch (i_mode) {
926	case 0:
927		mode = LUT_BYPASS;
928		break;
929	case 1:
930		mode = LUT_RAM_A;
931		break;
932	case 2:
933		mode = LUT_RAM_B;
934		break;
935	default:
936		mode = LUT_BYPASS;
937		break;
938	}
939	if (i_enable_10bits > 0)
940		*is_12bits_color_channel = false;
941	else
942		*is_12bits_color_channel = true;
943
944	REG_GET(RMU_3DLUT_MODE[rmu_idx], MPC_RMU_3DLUT_SIZE, &lut_size);
945
946	if (lut_size == 0)
947		*is_17x17x17 = true;
948	else
949		*is_17x17x17 = false;
950
951	return mode;
952}
953
954static void mpc3_select_3dlut_ram(
955		struct mpc *mpc,
956		enum dc_lut_mode mode,
957		bool is_color_channel_12bits,
958		uint32_t rmu_idx)
959{
960	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
961
962	REG_UPDATE_2(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx],
963		MPC_RMU_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
964		MPC_RMU_3DLUT_30BIT_EN, is_color_channel_12bits == true ? 0:1);
965}
966
967static void mpc3_select_3dlut_ram_mask(
968		struct mpc *mpc,
969		uint32_t ram_selection_mask,
970		uint32_t rmu_idx)
971{
972	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
973
974	REG_UPDATE(RMU_3DLUT_READ_WRITE_CONTROL[rmu_idx], MPC_RMU_3DLUT_WRITE_EN_MASK,
975			ram_selection_mask);
976	REG_SET(RMU_3DLUT_INDEX[rmu_idx], 0, MPC_RMU_3DLUT_INDEX, 0);
977}
978
979static void mpc3_set3dlut_ram12(
980		struct mpc *mpc,
981		const struct dc_rgb *lut,
982		uint32_t entries,
983		uint32_t rmu_idx)
984{
985	uint32_t i, red, green, blue, red1, green1, blue1;
986	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
987
988	for (i = 0 ; i < entries; i += 2) {
989		red   = lut[i].red<<4;
990		green = lut[i].green<<4;
991		blue  = lut[i].blue<<4;
992		red1   = lut[i+1].red<<4;
993		green1 = lut[i+1].green<<4;
994		blue1  = lut[i+1].blue<<4;
995
996		REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0,
997				MPC_RMU_3DLUT_DATA0, red,
998				MPC_RMU_3DLUT_DATA1, red1);
999
1000		REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0,
1001				MPC_RMU_3DLUT_DATA0, green,
1002				MPC_RMU_3DLUT_DATA1, green1);
1003
1004		REG_SET_2(RMU_3DLUT_DATA[rmu_idx], 0,
1005				MPC_RMU_3DLUT_DATA0, blue,
1006				MPC_RMU_3DLUT_DATA1, blue1);
1007	}
1008}
1009
1010static void mpc3_set3dlut_ram10(
1011		struct mpc *mpc,
1012		const struct dc_rgb *lut,
1013		uint32_t entries,
1014		uint32_t rmu_idx)
1015{
1016	uint32_t i, red, green, blue, value;
1017	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1018
1019	for (i = 0; i < entries; i++) {
1020		red   = lut[i].red;
1021		green = lut[i].green;
1022		blue  = lut[i].blue;
1023		//should we shift red 22bit and green 12? ask Nvenko
1024		value = (red<<20) | (green<<10) | blue;
1025
1026		REG_SET(RMU_3DLUT_DATA_30BIT[rmu_idx], 0, MPC_RMU_3DLUT_DATA_30BIT, value);
1027	}
1028
1029}
1030
1031
1032void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
1033{
1034	mpcc->mpcc_id = mpcc_inst;
1035	mpcc->dpp_id = 0xf;
1036	mpcc->mpcc_bot = NULL;
1037	mpcc->blnd_cfg.overlap_only = false;
1038	mpcc->blnd_cfg.global_alpha = 0xff;
1039	mpcc->blnd_cfg.global_gain = 0xff;
1040	mpcc->blnd_cfg.background_color_bpc = 4;
1041	mpcc->blnd_cfg.bottom_gain_mode = 0;
1042	mpcc->blnd_cfg.top_gain = 0x1f000;
1043	mpcc->blnd_cfg.bottom_inside_gain = 0x1f000;
1044	mpcc->blnd_cfg.bottom_outside_gain = 0x1f000;
1045	mpcc->sm_cfg.enable = false;
1046	mpcc->shared_bottom = false;
1047}
1048
1049static void program_gamut_remap(
1050		struct dcn30_mpc *mpc30,
1051		int mpcc_id,
1052		const uint16_t *regval,
1053		int select)
1054{
1055	uint16_t selection = 0;
1056	struct color_matrices_reg gam_regs;
1057
1058	if (regval == NULL || select == GAMUT_REMAP_BYPASS) {
1059		REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0,
1060				MPCC_GAMUT_REMAP_MODE, GAMUT_REMAP_BYPASS);
1061		return;
1062	}
1063	switch (select) {
1064	case GAMUT_REMAP_COEFF:
1065		selection = 1;
1066		break;
1067		/*this corresponds to GAMUT_REMAP coefficients set B
1068		 * we don't have common coefficient sets in dcn3ag/dcn3
1069		 */
1070	case GAMUT_REMAP_COMA_COEFF:
1071		selection = 2;
1072		break;
1073	default:
1074		break;
1075	}
1076
1077	gam_regs.shifts.csc_c11 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
1078	gam_regs.masks.csc_c11  = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
1079	gam_regs.shifts.csc_c12 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
1080	gam_regs.masks.csc_c12 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
1081
1082
1083	if (select == GAMUT_REMAP_COEFF) {
1084		gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_A[mpcc_id]);
1085		gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_A[mpcc_id]);
1086
1087		cm_helper_program_color_matrices(
1088				mpc30->base.ctx,
1089				regval,
1090				&gam_regs);
1091
1092	} else  if (select == GAMUT_REMAP_COMA_COEFF) {
1093
1094		gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_B[mpcc_id]);
1095		gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_B[mpcc_id]);
1096
1097		cm_helper_program_color_matrices(
1098				mpc30->base.ctx,
1099				regval,
1100				&gam_regs);
1101
1102	}
1103	//select coefficient set to use
1104	REG_SET(MPCC_GAMUT_REMAP_MODE[mpcc_id], 0,
1105					MPCC_GAMUT_REMAP_MODE, selection);
1106}
1107
1108void mpc3_set_gamut_remap(
1109		struct mpc *mpc,
1110		int mpcc_id,
1111		const struct mpc_grph_gamut_adjustment *adjust)
1112{
1113	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1114	int i = 0;
1115	int gamut_mode;
1116
1117	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
1118		program_gamut_remap(mpc30, mpcc_id, NULL, GAMUT_REMAP_BYPASS);
1119	else {
1120		struct fixed31_32 arr_matrix[12];
1121		uint16_t arr_reg_val[12];
1122
1123		for (i = 0; i < 12; i++)
1124			arr_matrix[i] = adjust->temperature_matrix[i];
1125
1126		convert_float_matrix(
1127			arr_reg_val, arr_matrix, 12);
1128
1129		//current coefficient set in use
1130		REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id], MPCC_GAMUT_REMAP_MODE_CURRENT, &gamut_mode);
1131
1132		if (gamut_mode == 0)
1133			gamut_mode = 1; //use coefficient set A
1134		else if (gamut_mode == 1)
1135			gamut_mode = 2;
1136		else
1137			gamut_mode = 1;
1138
1139		program_gamut_remap(mpc30, mpcc_id, arr_reg_val, gamut_mode);
1140	}
1141}
1142
1143static void read_gamut_remap(struct dcn30_mpc *mpc30,
1144			     int mpcc_id,
1145			     uint16_t *regval,
1146			     uint32_t *select)
1147{
1148	struct color_matrices_reg gam_regs;
1149
1150	//current coefficient set in use
1151	REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id], MPCC_GAMUT_REMAP_MODE_CURRENT, select);
1152
1153	gam_regs.shifts.csc_c11 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
1154	gam_regs.masks.csc_c11  = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
1155	gam_regs.shifts.csc_c12 = mpc30->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
1156	gam_regs.masks.csc_c12 = mpc30->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
1157
1158	if (*select == GAMUT_REMAP_COEFF) {
1159		gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_A[mpcc_id]);
1160		gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_A[mpcc_id]);
1161
1162		cm_helper_read_color_matrices(
1163				mpc30->base.ctx,
1164				regval,
1165				&gam_regs);
1166
1167	} else  if (*select == GAMUT_REMAP_COMA_COEFF) {
1168
1169		gam_regs.csc_c11_c12 = REG(MPC_GAMUT_REMAP_C11_C12_B[mpcc_id]);
1170		gam_regs.csc_c33_c34 = REG(MPC_GAMUT_REMAP_C33_C34_B[mpcc_id]);
1171
1172		cm_helper_read_color_matrices(
1173				mpc30->base.ctx,
1174				regval,
1175				&gam_regs);
1176
1177	}
1178
1179}
1180
1181void mpc3_get_gamut_remap(struct mpc *mpc,
1182			  int mpcc_id,
1183			  struct mpc_grph_gamut_adjustment *adjust)
1184{
1185	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1186	uint16_t arr_reg_val[12];
1187	int select;
1188
1189	read_gamut_remap(mpc30, mpcc_id, arr_reg_val, &select);
1190
1191	if (select == GAMUT_REMAP_BYPASS) {
1192		adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1193		return;
1194	}
1195
1196	adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1197	convert_hw_matrix(adjust->temperature_matrix,
1198			  arr_reg_val, ARRAY_SIZE(arr_reg_val));
1199}
1200
1201bool mpc3_program_3dlut(
1202		struct mpc *mpc,
1203		const struct tetrahedral_params *params,
1204		int rmu_idx)
1205{
1206	enum dc_lut_mode mode;
1207	bool is_17x17x17;
1208	bool is_12bits_color_channel;
1209	const struct dc_rgb *lut0;
1210	const struct dc_rgb *lut1;
1211	const struct dc_rgb *lut2;
1212	const struct dc_rgb *lut3;
1213	int lut_size0;
1214	int lut_size;
1215
1216	if (params == NULL) {
1217		mpc3_set_3dlut_mode(mpc, LUT_BYPASS, false, false, rmu_idx);
1218		return false;
1219	}
1220	mpc3_power_on_shaper_3dlut(mpc, rmu_idx, true);
1221
1222	mode = get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, rmu_idx);
1223
1224	if (mode == LUT_BYPASS || mode == LUT_RAM_B)
1225		mode = LUT_RAM_A;
1226	else
1227		mode = LUT_RAM_B;
1228
1229	is_17x17x17 = !params->use_tetrahedral_9;
1230	is_12bits_color_channel = params->use_12bits;
1231	if (is_17x17x17) {
1232		lut0 = params->tetrahedral_17.lut0;
1233		lut1 = params->tetrahedral_17.lut1;
1234		lut2 = params->tetrahedral_17.lut2;
1235		lut3 = params->tetrahedral_17.lut3;
1236		lut_size0 = sizeof(params->tetrahedral_17.lut0)/
1237					sizeof(params->tetrahedral_17.lut0[0]);
1238		lut_size  = sizeof(params->tetrahedral_17.lut1)/
1239					sizeof(params->tetrahedral_17.lut1[0]);
1240	} else {
1241		lut0 = params->tetrahedral_9.lut0;
1242		lut1 = params->tetrahedral_9.lut1;
1243		lut2 = params->tetrahedral_9.lut2;
1244		lut3 = params->tetrahedral_9.lut3;
1245		lut_size0 = sizeof(params->tetrahedral_9.lut0)/
1246				sizeof(params->tetrahedral_9.lut0[0]);
1247		lut_size  = sizeof(params->tetrahedral_9.lut1)/
1248				sizeof(params->tetrahedral_9.lut1[0]);
1249		}
1250
1251	mpc3_select_3dlut_ram(mpc, mode,
1252				is_12bits_color_channel, rmu_idx);
1253	mpc3_select_3dlut_ram_mask(mpc, 0x1, rmu_idx);
1254	if (is_12bits_color_channel)
1255		mpc3_set3dlut_ram12(mpc, lut0, lut_size0, rmu_idx);
1256	else
1257		mpc3_set3dlut_ram10(mpc, lut0, lut_size0, rmu_idx);
1258
1259	mpc3_select_3dlut_ram_mask(mpc, 0x2, rmu_idx);
1260	if (is_12bits_color_channel)
1261		mpc3_set3dlut_ram12(mpc, lut1, lut_size, rmu_idx);
1262	else
1263		mpc3_set3dlut_ram10(mpc, lut1, lut_size, rmu_idx);
1264
1265	mpc3_select_3dlut_ram_mask(mpc, 0x4, rmu_idx);
1266	if (is_12bits_color_channel)
1267		mpc3_set3dlut_ram12(mpc, lut2, lut_size, rmu_idx);
1268	else
1269		mpc3_set3dlut_ram10(mpc, lut2, lut_size, rmu_idx);
1270
1271	mpc3_select_3dlut_ram_mask(mpc, 0x8, rmu_idx);
1272	if (is_12bits_color_channel)
1273		mpc3_set3dlut_ram12(mpc, lut3, lut_size, rmu_idx);
1274	else
1275		mpc3_set3dlut_ram10(mpc, lut3, lut_size, rmu_idx);
1276
1277	mpc3_set_3dlut_mode(mpc, mode, is_12bits_color_channel,
1278					is_17x17x17, rmu_idx);
1279
1280	if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
1281		mpc3_power_on_shaper_3dlut(mpc, rmu_idx, false);
1282
1283	return true;
1284}
1285
1286void mpc3_set_output_csc(
1287		struct mpc *mpc,
1288		int opp_id,
1289		const uint16_t *regval,
1290		enum mpc_output_csc_mode ocsc_mode)
1291{
1292	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1293	struct color_matrices_reg ocsc_regs;
1294
1295	REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0);
1296
1297	REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
1298
1299	if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE)
1300		return;
1301
1302	if (regval == NULL) {
1303		BREAK_TO_DEBUGGER();
1304		return;
1305	}
1306
1307	ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A;
1308	ocsc_regs.masks.csc_c11  = mpc30->mpc_mask->MPC_OCSC_C11_A;
1309	ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A;
1310	ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A;
1311
1312	if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) {
1313		ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]);
1314		ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]);
1315	} else {
1316		ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]);
1317		ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]);
1318	}
1319	cm_helper_program_color_matrices(
1320			mpc30->base.ctx,
1321			regval,
1322			&ocsc_regs);
1323}
1324
1325void mpc3_set_ocsc_default(
1326		struct mpc *mpc,
1327		int opp_id,
1328		enum dc_color_space color_space,
1329		enum mpc_output_csc_mode ocsc_mode)
1330{
1331	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1332	uint32_t arr_size;
1333	struct color_matrices_reg ocsc_regs;
1334	const uint16_t *regval = NULL;
1335
1336	REG_WRITE(MPC_OUT_CSC_COEF_FORMAT, 0);
1337
1338	REG_SET(CSC_MODE[opp_id], 0, MPC_OCSC_MODE, ocsc_mode);
1339	if (ocsc_mode == MPC_OUTPUT_CSC_DISABLE)
1340		return;
1341
1342	regval = find_color_matrix(color_space, &arr_size);
1343
1344	if (regval == NULL) {
1345		BREAK_TO_DEBUGGER();
1346		return;
1347	}
1348
1349	ocsc_regs.shifts.csc_c11 = mpc30->mpc_shift->MPC_OCSC_C11_A;
1350	ocsc_regs.masks.csc_c11  = mpc30->mpc_mask->MPC_OCSC_C11_A;
1351	ocsc_regs.shifts.csc_c12 = mpc30->mpc_shift->MPC_OCSC_C12_A;
1352	ocsc_regs.masks.csc_c12 = mpc30->mpc_mask->MPC_OCSC_C12_A;
1353
1354
1355	if (ocsc_mode == MPC_OUTPUT_CSC_COEF_A) {
1356		ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_A[opp_id]);
1357		ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_A[opp_id]);
1358	} else {
1359		ocsc_regs.csc_c11_c12 = REG(CSC_C11_C12_B[opp_id]);
1360		ocsc_regs.csc_c33_c34 = REG(CSC_C33_C34_B[opp_id]);
1361	}
1362
1363	cm_helper_program_color_matrices(
1364			mpc30->base.ctx,
1365			regval,
1366			&ocsc_regs);
1367}
1368
1369void mpc3_set_rmu_mux(
1370	struct mpc *mpc,
1371	int rmu_idx,
1372	int value)
1373{
1374	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1375
1376	if (rmu_idx == 0)
1377		REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU0_MUX, value);
1378	else if (rmu_idx == 1)
1379		REG_UPDATE(MPC_RMU_CONTROL, MPC_RMU1_MUX, value);
1380
1381}
1382
1383uint32_t mpc3_get_rmu_mux_status(
1384	struct mpc *mpc,
1385	int rmu_idx)
1386{
1387	uint32_t status = 0xf;
1388	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1389
1390	if (rmu_idx == 0)
1391		REG_GET(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, &status);
1392	else if (rmu_idx == 1)
1393		REG_GET(MPC_RMU_CONTROL, MPC_RMU1_MUX_STATUS, &status);
1394
1395	return status;
1396}
1397
1398uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx)
1399{
1400	uint32_t rmu_status;
1401
1402	//determine if this mpcc is already multiplexed to an RMU unit
1403	rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx);
1404	if (rmu_status == mpcc_id)
1405		//return rmu_idx of pre_acquired rmu unit
1406		return rmu_idx;
1407
1408	if (rmu_status == 0xf) {//rmu unit is disabled
1409		mpc3_set_rmu_mux(mpc, rmu_idx, mpcc_id);
1410		return rmu_idx;
1411	}
1412
1413	//no vacant RMU units or invalid parameters acquire_post_bldn_3dlut
1414	return -1;
1415}
1416
1417static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id)
1418{
1419	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1420	int rmu_idx;
1421	uint32_t rmu_status;
1422	int released_rmu = -1;
1423
1424	for (rmu_idx = 0; rmu_idx < mpc30->num_rmu; rmu_idx++) {
1425		rmu_status = mpc3_get_rmu_mux_status(mpc, rmu_idx);
1426		if (rmu_status == mpcc_id) {
1427			mpc3_set_rmu_mux(mpc, rmu_idx, 0xf);
1428			released_rmu = rmu_idx;
1429			break;
1430		}
1431	}
1432	return released_rmu;
1433
1434}
1435
1436static void mpc3_set_mpc_mem_lp_mode(struct mpc *mpc)
1437{
1438	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1439	int mpcc_id;
1440
1441	if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
1442		if (mpc30->mpc_mask->MPC_RMU0_MEM_LOW_PWR_MODE && mpc30->mpc_mask->MPC_RMU1_MEM_LOW_PWR_MODE) {
1443			REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, 3);
1444			REG_UPDATE(MPC_RMU_MEM_PWR_CTRL, MPC_RMU1_MEM_LOW_PWR_MODE, 3);
1445		}
1446
1447		if (mpc30->mpc_mask->MPCC_OGAM_MEM_LOW_PWR_MODE) {
1448			for (mpcc_id = 0; mpcc_id < mpc30->num_mpcc; mpcc_id++)
1449				REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_LOW_PWR_MODE, 3);
1450		}
1451	}
1452}
1453
1454static void mpc3_read_mpcc_state(
1455		struct mpc *mpc,
1456		int mpcc_inst,
1457		struct mpcc_state *s)
1458{
1459	struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
1460	uint32_t rmu_status = 0xf;
1461
1462	REG_GET(MPCC_OPP_ID[mpcc_inst], MPCC_OPP_ID, &s->opp_id);
1463	REG_GET(MPCC_TOP_SEL[mpcc_inst], MPCC_TOP_SEL, &s->dpp_id);
1464	REG_GET(MPCC_BOT_SEL[mpcc_inst], MPCC_BOT_SEL, &s->bot_mpcc_id);
1465	REG_GET_4(MPCC_CONTROL[mpcc_inst], MPCC_MODE, &s->mode,
1466			MPCC_ALPHA_BLND_MODE, &s->alpha_mode,
1467			MPCC_ALPHA_MULTIPLIED_MODE, &s->pre_multiplied_alpha,
1468			MPCC_BLND_ACTIVE_OVERLAP_ONLY, &s->overlap_only);
1469	REG_GET_2(MPCC_STATUS[mpcc_inst], MPCC_IDLE, &s->idle,
1470			MPCC_BUSY, &s->busy);
1471
1472	/* Color blocks state */
1473	REG_GET(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, &rmu_status);
1474
1475	if (rmu_status == mpcc_inst) {
1476		REG_GET(SHAPER_CONTROL[0],
1477			MPC_RMU_SHAPER_LUT_MODE_CURRENT, &s->shaper_lut_mode);
1478		REG_GET(RMU_3DLUT_MODE[0],
1479			MPC_RMU_3DLUT_MODE_CURRENT,  &s->lut3d_mode);
1480		REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[0],
1481			MPC_RMU_3DLUT_30BIT_EN, &s->lut3d_bit_depth);
1482		REG_GET(RMU_3DLUT_MODE[0],
1483			MPC_RMU_3DLUT_SIZE, &s->lut3d_size);
1484	} else {
1485		REG_GET(SHAPER_CONTROL[1],
1486			MPC_RMU_SHAPER_LUT_MODE_CURRENT, &s->shaper_lut_mode);
1487		REG_GET(RMU_3DLUT_MODE[1],
1488			MPC_RMU_3DLUT_MODE_CURRENT,  &s->lut3d_mode);
1489		REG_GET(RMU_3DLUT_READ_WRITE_CONTROL[1],
1490			MPC_RMU_3DLUT_30BIT_EN, &s->lut3d_bit_depth);
1491		REG_GET(RMU_3DLUT_MODE[1],
1492			MPC_RMU_3DLUT_SIZE, &s->lut3d_size);
1493	}
1494
1495        REG_GET_2(MPCC_OGAM_CONTROL[mpcc_inst],
1496		  MPCC_OGAM_MODE_CURRENT, &s->rgam_mode,
1497		  MPCC_OGAM_SELECT_CURRENT, &s->rgam_lut);
1498}
1499
1500static const struct mpc_funcs dcn30_mpc_funcs = {
1501	.read_mpcc_state = mpc3_read_mpcc_state,
1502	.insert_plane = mpc1_insert_plane,
1503	.remove_mpcc = mpc1_remove_mpcc,
1504	.mpc_init = mpc3_mpc_init,
1505	.mpc_init_single_inst = mpc3_mpc_init_single_inst,
1506	.update_blending = mpc2_update_blending,
1507	.cursor_lock = mpc1_cursor_lock,
1508	.get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
1509	.wait_for_idle = mpc2_assert_idle_mpcc,
1510	.assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
1511	.init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
1512	.set_denorm =  mpc3_set_denorm,
1513	.set_denorm_clamp = mpc3_set_denorm_clamp,
1514	.set_output_csc = mpc3_set_output_csc,
1515	.set_ocsc_default = mpc3_set_ocsc_default,
1516	.set_output_gamma = mpc3_set_output_gamma,
1517	.insert_plane_to_secondary = NULL,
1518	.remove_mpcc_from_secondary =  NULL,
1519	.set_dwb_mux = mpc3_set_dwb_mux,
1520	.disable_dwb_mux = mpc3_disable_dwb_mux,
1521	.is_dwb_idle = mpc3_is_dwb_idle,
1522	.set_gamut_remap = mpc3_set_gamut_remap,
1523	.program_shaper = mpc3_program_shaper,
1524	.acquire_rmu = mpcc3_acquire_rmu,
1525	.program_3dlut = mpc3_program_3dlut,
1526	.release_rmu = mpcc3_release_rmu,
1527	.power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
1528	.get_mpc_out_mux = mpc1_get_mpc_out_mux,
1529	.set_bg_color = mpc1_set_bg_color,
1530	.set_mpc_mem_lp_mode = mpc3_set_mpc_mem_lp_mode,
1531};
1532
1533void dcn30_mpc_construct(struct dcn30_mpc *mpc30,
1534	struct dc_context *ctx,
1535	const struct dcn30_mpc_registers *mpc_regs,
1536	const struct dcn30_mpc_shift *mpc_shift,
1537	const struct dcn30_mpc_mask *mpc_mask,
1538	int num_mpcc,
1539	int num_rmu)
1540{
1541	int i;
1542
1543	mpc30->base.ctx = ctx;
1544
1545	mpc30->base.funcs = &dcn30_mpc_funcs;
1546
1547	mpc30->mpc_regs = mpc_regs;
1548	mpc30->mpc_shift = mpc_shift;
1549	mpc30->mpc_mask = mpc_mask;
1550
1551	mpc30->mpcc_in_use_mask = 0;
1552	mpc30->num_mpcc = num_mpcc;
1553	mpc30->num_rmu = num_rmu;
1554
1555	for (i = 0; i < MAX_MPCC; i++)
1556		mpc3_init_mpcc(&mpc30->base.mpcc_array[i], i);
1557}
1558
1559