1/*
2 * Copyright 2016 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 "dm_services.h"
27
28#include "core_types.h"
29
30#include "reg_helper.h"
31#include "dcn20_dpp.h"
32#include "basics/conversion.h"
33
34#include "dcn10/dcn10_cm_common.h"
35
36#define REG(reg)\
37	dpp->tf_regs->reg
38
39#define IND_REG(index) \
40	(index)
41
42#define CTX \
43	dpp->base.ctx
44
45#undef FN
46#define FN(reg_name, field_name) \
47	dpp->tf_shift->field_name, dpp->tf_mask->field_name
48
49
50static void dpp2_enable_cm_block(
51		struct dpp *dpp_base)
52{
53	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
54
55	unsigned int cm_bypass_mode = 0;
56	//Temp, put CM in bypass mode
57	if (dpp_base->ctx->dc->debug.cm_in_bypass)
58		cm_bypass_mode = 1;
59
60	REG_UPDATE(CM_CONTROL, CM_BYPASS, cm_bypass_mode);
61}
62
63
64static bool dpp2_degamma_ram_inuse(
65		struct dpp *dpp_base,
66		bool *ram_a_inuse)
67{
68	bool ret = false;
69	uint32_t status_reg = 0;
70	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
71
72	REG_GET(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_CONFIG_STATUS,
73			&status_reg);
74
75	if (status_reg == 3) {
76		*ram_a_inuse = true;
77		ret = true;
78	} else if (status_reg == 4) {
79		*ram_a_inuse = false;
80		ret = true;
81	}
82	return ret;
83}
84
85static void dpp2_program_degamma_lut(
86		struct dpp *dpp_base,
87		const struct pwl_result_data *rgb,
88		uint32_t num,
89		bool is_ram_a)
90{
91	uint32_t i;
92
93	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
94	REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK,
95				CM_DGAM_LUT_WRITE_EN_MASK, 7);
96	REG_UPDATE(CM_DGAM_LUT_WRITE_EN_MASK, CM_DGAM_LUT_WRITE_SEL,
97					is_ram_a == true ? 0:1);
98
99	REG_SET(CM_DGAM_LUT_INDEX, 0, CM_DGAM_LUT_INDEX, 0);
100	for (i = 0 ; i < num; i++) {
101		REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].red_reg);
102		REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].green_reg);
103		REG_SET(CM_DGAM_LUT_DATA, 0, CM_DGAM_LUT_DATA, rgb[i].blue_reg);
104
105		REG_SET(CM_DGAM_LUT_DATA, 0,
106				CM_DGAM_LUT_DATA, rgb[i].delta_red_reg);
107		REG_SET(CM_DGAM_LUT_DATA, 0,
108				CM_DGAM_LUT_DATA, rgb[i].delta_green_reg);
109		REG_SET(CM_DGAM_LUT_DATA, 0,
110				CM_DGAM_LUT_DATA, rgb[i].delta_blue_reg);
111
112	}
113
114}
115
116void dpp2_set_degamma_pwl(
117		struct dpp *dpp_base,
118		const struct pwl_params *params)
119{
120	bool is_ram_a = true;
121
122	dpp1_power_on_degamma_lut(dpp_base, true);
123	dpp2_enable_cm_block(dpp_base);
124	dpp2_degamma_ram_inuse(dpp_base, &is_ram_a);
125	if (is_ram_a == true)
126		dpp1_program_degamma_lutb_settings(dpp_base, params);
127	else
128		dpp1_program_degamma_luta_settings(dpp_base, params);
129
130	dpp2_program_degamma_lut(dpp_base, params->rgb_resulted, params->hw_points_num, !is_ram_a);
131	dpp1_degamma_ram_select(dpp_base, !is_ram_a);
132}
133
134void dpp2_set_degamma(
135		struct dpp *dpp_base,
136		enum ipp_degamma_mode mode)
137{
138	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
139	dpp2_enable_cm_block(dpp_base);
140
141	switch (mode) {
142	case IPP_DEGAMMA_MODE_BYPASS:
143		/* Setting de gamma bypass for now */
144		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 0);
145		break;
146	case IPP_DEGAMMA_MODE_HW_sRGB:
147		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 1);
148		break;
149	case IPP_DEGAMMA_MODE_HW_xvYCC:
150		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 2);
151			break;
152	case IPP_DEGAMMA_MODE_USER_PWL:
153		REG_UPDATE(CM_DGAM_CONTROL, CM_DGAM_LUT_MODE, 3);
154		break;
155	default:
156		BREAK_TO_DEBUGGER();
157		break;
158	}
159}
160
161static void program_gamut_remap(
162		struct dcn20_dpp *dpp,
163		const uint16_t *regval,
164		enum dcn20_gamut_remap_select select)
165{
166	uint32_t cur_select = 0;
167	struct color_matrices_reg gam_regs;
168
169	if (regval == NULL || select == DCN2_GAMUT_REMAP_BYPASS) {
170		REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
171				CM_GAMUT_REMAP_MODE, 0);
172		return;
173	}
174
175	/* determine which gamut_remap coefficients (A or B) we are using
176	 * currently. select the alternate set to double buffer
177	 * the update so gamut_remap is updated on frame boundary
178	 */
179	IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
180					CM_TEST_DEBUG_DATA_STATUS_IDX,
181					CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE, &cur_select);
182
183	/* value stored in dbg reg will be 1 greater than mode we want */
184	if (cur_select != DCN2_GAMUT_REMAP_COEF_A)
185		select = DCN2_GAMUT_REMAP_COEF_A;
186	else
187		select = DCN2_GAMUT_REMAP_COEF_B;
188
189	gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
190	gam_regs.masks.csc_c11  = dpp->tf_mask->CM_GAMUT_REMAP_C11;
191	gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
192	gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
193
194	if (select == DCN2_GAMUT_REMAP_COEF_A) {
195		gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
196		gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
197	} else {
198		gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
199		gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
200	}
201
202	cm_helper_program_color_matrices(
203				dpp->base.ctx,
204				regval,
205				&gam_regs);
206
207	REG_SET(
208			CM_GAMUT_REMAP_CONTROL, 0,
209			CM_GAMUT_REMAP_MODE, select);
210
211}
212
213void dpp2_cm_set_gamut_remap(
214	struct dpp *dpp_base,
215	const struct dpp_grph_csc_adjustment *adjust)
216{
217	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
218	int i = 0;
219
220	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
221		/* Bypass if type is bypass or hw */
222		program_gamut_remap(dpp, NULL, DCN2_GAMUT_REMAP_BYPASS);
223	else {
224		struct fixed31_32 arr_matrix[12];
225		uint16_t arr_reg_val[12];
226
227		for (i = 0; i < 12; i++)
228			arr_matrix[i] = adjust->temperature_matrix[i];
229
230		convert_float_matrix(
231			arr_reg_val, arr_matrix, 12);
232
233		program_gamut_remap(dpp, arr_reg_val, DCN2_GAMUT_REMAP_COEF_A);
234	}
235}
236
237void dpp2_program_input_csc(
238		struct dpp *dpp_base,
239		enum dc_color_space color_space,
240		enum dcn20_input_csc_select input_select,
241		const struct out_csc_color_matrix *tbl_entry)
242{
243	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
244	int i;
245	int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
246	const uint16_t *regval = NULL;
247	uint32_t cur_select = 0;
248	enum dcn20_input_csc_select select;
249	struct color_matrices_reg icsc_regs;
250
251	if (input_select == DCN2_ICSC_SELECT_BYPASS) {
252		REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
253		return;
254	}
255
256	if (tbl_entry == NULL) {
257		for (i = 0; i < arr_size; i++)
258			if (dpp_input_csc_matrix[i].color_space == color_space) {
259				regval = dpp_input_csc_matrix[i].regval;
260				break;
261			}
262
263		if (regval == NULL) {
264			BREAK_TO_DEBUGGER();
265			return;
266		}
267	} else {
268		regval = tbl_entry->regval;
269	}
270
271	/* determine which CSC coefficients (A or B) we are using
272	 * currently.  select the alternate set to double buffer
273	 * the CSC update so CSC is updated on frame boundary
274	 */
275	IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
276					CM_TEST_DEBUG_DATA_STATUS_IDX,
277					CM_TEST_DEBUG_DATA_ICSC_MODE, &cur_select);
278
279	if (cur_select != DCN2_ICSC_SELECT_ICSC_A)
280		select = DCN2_ICSC_SELECT_ICSC_A;
281	else
282		select = DCN2_ICSC_SELECT_ICSC_B;
283
284	icsc_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11;
285	icsc_regs.masks.csc_c11  = dpp->tf_mask->CM_ICSC_C11;
286	icsc_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12;
287	icsc_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12;
288
289	if (select == DCN2_ICSC_SELECT_ICSC_A) {
290
291		icsc_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12);
292		icsc_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34);
293
294	} else {
295
296		icsc_regs.csc_c11_c12 = REG(CM_ICSC_B_C11_C12);
297		icsc_regs.csc_c33_c34 = REG(CM_ICSC_B_C33_C34);
298
299	}
300
301	cm_helper_program_color_matrices(
302			dpp->base.ctx,
303			regval,
304			&icsc_regs);
305
306	REG_SET(CM_ICSC_CONTROL, 0,
307				CM_ICSC_MODE, select);
308}
309
310static void dpp20_power_on_blnd_lut(
311	struct dpp *dpp_base,
312	bool power_on)
313{
314	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
315
316	REG_SET(CM_MEM_PWR_CTRL, 0,
317			BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0:1);
318
319}
320
321static void dpp20_configure_blnd_lut(
322		struct dpp *dpp_base,
323		bool is_ram_a)
324{
325	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
326
327	REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
328			CM_BLNDGAM_LUT_WRITE_EN_MASK, 7);
329	REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
330			CM_BLNDGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
331	REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
332}
333
334static void dpp20_program_blnd_pwl(
335		struct dpp *dpp_base,
336		const struct pwl_result_data *rgb,
337		uint32_t num)
338{
339	uint32_t i;
340	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
341
342	for (i = 0 ; i < num; i++) {
343		REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
344		REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg);
345		REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg);
346
347		REG_SET(CM_BLNDGAM_LUT_DATA, 0,
348				CM_BLNDGAM_LUT_DATA, rgb[i].delta_red_reg);
349		REG_SET(CM_BLNDGAM_LUT_DATA, 0,
350				CM_BLNDGAM_LUT_DATA, rgb[i].delta_green_reg);
351		REG_SET(CM_BLNDGAM_LUT_DATA, 0,
352				CM_BLNDGAM_LUT_DATA, rgb[i].delta_blue_reg);
353
354	}
355
356}
357
358static void dcn20_dpp_cm_get_reg_field(
359		struct dcn20_dpp *dpp,
360		struct xfer_func_reg *reg)
361{
362	reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
363	reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
364	reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
365	reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
366	reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
367	reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
368	reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
369	reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
370
371	reg->shifts.field_region_end = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
372	reg->masks.field_region_end = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
373	reg->shifts.field_region_end_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
374	reg->masks.field_region_end_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
375	reg->shifts.field_region_end_base = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
376	reg->masks.field_region_end_base = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
377	reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
378	reg->masks.field_region_linear_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
379	reg->shifts.exp_region_start = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
380	reg->masks.exp_region_start = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
381	reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
382	reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
383}
384
385/*program blnd lut RAM A*/
386static void dpp20_program_blnd_luta_settings(
387		struct dpp *dpp_base,
388		const struct pwl_params *params)
389{
390	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
391	struct xfer_func_reg gam_regs;
392
393	dcn20_dpp_cm_get_reg_field(dpp, &gam_regs);
394
395	gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMA_START_CNTL_B);
396	gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMA_START_CNTL_G);
397	gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMA_START_CNTL_R);
398	gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_B);
399	gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_G);
400	gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_R);
401	gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMA_END_CNTL1_B);
402	gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMA_END_CNTL2_B);
403	gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMA_END_CNTL1_G);
404	gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMA_END_CNTL2_G);
405	gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMA_END_CNTL1_R);
406	gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMA_END_CNTL2_R);
407	gam_regs.region_start = REG(CM_BLNDGAM_RAMA_REGION_0_1);
408	gam_regs.region_end = REG(CM_BLNDGAM_RAMA_REGION_32_33);
409
410	cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
411}
412
413/*program blnd lut RAM B*/
414static void dpp20_program_blnd_lutb_settings(
415		struct dpp *dpp_base,
416		const struct pwl_params *params)
417{
418	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
419	struct xfer_func_reg gam_regs;
420
421	dcn20_dpp_cm_get_reg_field(dpp, &gam_regs);
422
423	gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMB_START_CNTL_B);
424	gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMB_START_CNTL_G);
425	gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMB_START_CNTL_R);
426	gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_B);
427	gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_G);
428	gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_R);
429	gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMB_END_CNTL1_B);
430	gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMB_END_CNTL2_B);
431	gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMB_END_CNTL1_G);
432	gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMB_END_CNTL2_G);
433	gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMB_END_CNTL1_R);
434	gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMB_END_CNTL2_R);
435	gam_regs.region_start = REG(CM_BLNDGAM_RAMB_REGION_0_1);
436	gam_regs.region_end = REG(CM_BLNDGAM_RAMB_REGION_32_33);
437
438	cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
439}
440
441static enum dc_lut_mode dpp20_get_blndgam_current(struct dpp *dpp_base)
442{
443	enum dc_lut_mode mode;
444	uint32_t state_mode;
445	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
446
447	REG_GET(CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_CONFIG_STATUS, &state_mode);
448
449	switch (state_mode) {
450	case 0:
451		mode = LUT_BYPASS;
452		break;
453	case 1:
454		mode = LUT_RAM_A;
455		break;
456	case 2:
457		mode = LUT_RAM_B;
458		break;
459	default:
460		mode = LUT_BYPASS;
461		break;
462	}
463
464	return mode;
465}
466
467bool dpp20_program_blnd_lut(
468	struct dpp *dpp_base, const struct pwl_params *params)
469{
470	enum dc_lut_mode current_mode;
471	enum dc_lut_mode next_mode;
472	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
473
474	if (params == NULL) {
475		REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE, 0);
476		return false;
477	}
478	current_mode = dpp20_get_blndgam_current(dpp_base);
479	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
480		next_mode = LUT_RAM_B;
481	else
482		next_mode = LUT_RAM_A;
483
484	dpp20_power_on_blnd_lut(dpp_base, true);
485	dpp20_configure_blnd_lut(dpp_base, next_mode == LUT_RAM_A);
486
487	if (next_mode == LUT_RAM_A)
488		dpp20_program_blnd_luta_settings(dpp_base, params);
489	else
490		dpp20_program_blnd_lutb_settings(dpp_base, params);
491
492	dpp20_program_blnd_pwl(
493			dpp_base, params->rgb_resulted, params->hw_points_num);
494
495	REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE,
496			next_mode == LUT_RAM_A ? 1:2);
497
498	return true;
499}
500
501
502static void dpp20_program_shaper_lut(
503		struct dpp *dpp_base,
504		const struct pwl_result_data *rgb,
505		uint32_t num)
506{
507	uint32_t i, red, green, blue;
508	uint32_t  red_delta, green_delta, blue_delta;
509	uint32_t  red_value, green_value, blue_value;
510
511	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
512
513	for (i = 0 ; i < num; i++) {
514
515		red   = rgb[i].red_reg;
516		green = rgb[i].green_reg;
517		blue  = rgb[i].blue_reg;
518
519		red_delta   = rgb[i].delta_red_reg;
520		green_delta = rgb[i].delta_green_reg;
521		blue_delta  = rgb[i].delta_blue_reg;
522
523		red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
524		green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
525		blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
526
527		REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, red_value);
528		REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, green_value);
529		REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, blue_value);
530	}
531
532}
533
534static enum dc_lut_mode dpp20_get_shaper_current(struct dpp *dpp_base)
535{
536	enum dc_lut_mode mode;
537	uint32_t state_mode;
538	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
539
540	REG_GET(CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_CONFIG_STATUS, &state_mode);
541
542	switch (state_mode) {
543	case 0:
544		mode = LUT_BYPASS;
545		break;
546	case 1:
547		mode = LUT_RAM_A;
548		break;
549	case 2:
550		mode = LUT_RAM_B;
551		break;
552	default:
553		mode = LUT_BYPASS;
554		break;
555	}
556
557	return mode;
558}
559
560static void dpp20_configure_shaper_lut(
561		struct dpp *dpp_base,
562		bool is_ram_a)
563{
564	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
565
566	REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
567			CM_SHAPER_LUT_WRITE_EN_MASK, 7);
568	REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
569			CM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
570	REG_SET(CM_SHAPER_LUT_INDEX, 0, CM_SHAPER_LUT_INDEX, 0);
571}
572
573/*program shaper RAM A*/
574
575static void dpp20_program_shaper_luta_settings(
576		struct dpp *dpp_base,
577		const struct pwl_params *params)
578{
579	const struct gamma_curve *curve;
580	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
581
582	REG_SET_2(CM_SHAPER_RAMA_START_CNTL_B, 0,
583		CM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
584		CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
585	REG_SET_2(CM_SHAPER_RAMA_START_CNTL_G, 0,
586		CM_SHAPER_RAMA_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
587		CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, 0);
588	REG_SET_2(CM_SHAPER_RAMA_START_CNTL_R, 0,
589		CM_SHAPER_RAMA_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
590		CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, 0);
591
592	REG_SET_2(CM_SHAPER_RAMA_END_CNTL_B, 0,
593		CM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
594		CM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
595
596	REG_SET_2(CM_SHAPER_RAMA_END_CNTL_G, 0,
597		CM_SHAPER_RAMA_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
598		CM_SHAPER_RAMA_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
599
600	REG_SET_2(CM_SHAPER_RAMA_END_CNTL_R, 0,
601		CM_SHAPER_RAMA_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
602		CM_SHAPER_RAMA_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
603
604	curve = params->arr_curve_points;
605	REG_SET_4(CM_SHAPER_RAMA_REGION_0_1, 0,
606		CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
607		CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
608		CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
609		CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
610
611	curve += 2;
612	REG_SET_4(CM_SHAPER_RAMA_REGION_2_3, 0,
613		CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset,
614		CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
615		CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset,
616		CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
617
618	curve += 2;
619	REG_SET_4(CM_SHAPER_RAMA_REGION_4_5, 0,
620		CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset,
621		CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
622		CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset,
623		CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
624
625	curve += 2;
626	REG_SET_4(CM_SHAPER_RAMA_REGION_6_7, 0,
627		CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset,
628		CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
629		CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset,
630		CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
631
632	curve += 2;
633	REG_SET_4(CM_SHAPER_RAMA_REGION_8_9, 0,
634		CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset,
635		CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
636		CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset,
637		CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
638
639	curve += 2;
640	REG_SET_4(CM_SHAPER_RAMA_REGION_10_11, 0,
641		CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset,
642		CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
643		CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset,
644		CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
645
646	curve += 2;
647	REG_SET_4(CM_SHAPER_RAMA_REGION_12_13, 0,
648		CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset,
649		CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
650		CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset,
651		CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
652
653	curve += 2;
654	REG_SET_4(CM_SHAPER_RAMA_REGION_14_15, 0,
655		CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset,
656		CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
657		CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset,
658		CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
659
660	curve += 2;
661	REG_SET_4(CM_SHAPER_RAMA_REGION_16_17, 0,
662		CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset,
663		CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
664		CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset,
665		CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
666
667	curve += 2;
668	REG_SET_4(CM_SHAPER_RAMA_REGION_18_19, 0,
669		CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset,
670		CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
671		CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset,
672		CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
673
674	curve += 2;
675	REG_SET_4(CM_SHAPER_RAMA_REGION_20_21, 0,
676		CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset,
677		CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
678		CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset,
679		CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
680
681	curve += 2;
682	REG_SET_4(CM_SHAPER_RAMA_REGION_22_23, 0,
683		CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset,
684		CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
685		CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset,
686		CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
687
688	curve += 2;
689	REG_SET_4(CM_SHAPER_RAMA_REGION_24_25, 0,
690		CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset,
691		CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
692		CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset,
693		CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
694
695	curve += 2;
696	REG_SET_4(CM_SHAPER_RAMA_REGION_26_27, 0,
697		CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset,
698		CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
699		CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset,
700		CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
701
702	curve += 2;
703	REG_SET_4(CM_SHAPER_RAMA_REGION_28_29, 0,
704		CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset,
705		CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
706		CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset,
707		CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
708
709	curve += 2;
710	REG_SET_4(CM_SHAPER_RAMA_REGION_30_31, 0,
711		CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset,
712		CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
713		CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset,
714		CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
715
716	curve += 2;
717	REG_SET_4(CM_SHAPER_RAMA_REGION_32_33, 0,
718		CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset,
719		CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
720		CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset,
721		CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
722}
723
724/*program shaper RAM B*/
725static void dpp20_program_shaper_lutb_settings(
726		struct dpp *dpp_base,
727		const struct pwl_params *params)
728{
729	const struct gamma_curve *curve;
730	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
731
732	REG_SET_2(CM_SHAPER_RAMB_START_CNTL_B, 0,
733		CM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
734		CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
735	REG_SET_2(CM_SHAPER_RAMB_START_CNTL_G, 0,
736		CM_SHAPER_RAMB_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
737		CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, 0);
738	REG_SET_2(CM_SHAPER_RAMB_START_CNTL_R, 0,
739		CM_SHAPER_RAMB_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
740		CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, 0);
741
742	REG_SET_2(CM_SHAPER_RAMB_END_CNTL_B, 0,
743		CM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
744		CM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
745
746	REG_SET_2(CM_SHAPER_RAMB_END_CNTL_G, 0,
747		CM_SHAPER_RAMB_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
748		CM_SHAPER_RAMB_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
749
750	REG_SET_2(CM_SHAPER_RAMB_END_CNTL_R, 0,
751		CM_SHAPER_RAMB_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
752		CM_SHAPER_RAMB_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
753
754	curve = params->arr_curve_points;
755	REG_SET_4(CM_SHAPER_RAMB_REGION_0_1, 0,
756		CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
757		CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
758		CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
759		CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
760
761	curve += 2;
762	REG_SET_4(CM_SHAPER_RAMB_REGION_2_3, 0,
763		CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset,
764		CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
765		CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset,
766		CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
767
768	curve += 2;
769	REG_SET_4(CM_SHAPER_RAMB_REGION_4_5, 0,
770		CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset,
771		CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
772		CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset,
773		CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
774
775	curve += 2;
776	REG_SET_4(CM_SHAPER_RAMB_REGION_6_7, 0,
777		CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset,
778		CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
779		CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset,
780		CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
781
782	curve += 2;
783	REG_SET_4(CM_SHAPER_RAMB_REGION_8_9, 0,
784		CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset,
785		CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
786		CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset,
787		CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
788
789	curve += 2;
790	REG_SET_4(CM_SHAPER_RAMB_REGION_10_11, 0,
791		CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset,
792		CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
793		CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset,
794		CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
795
796	curve += 2;
797	REG_SET_4(CM_SHAPER_RAMB_REGION_12_13, 0,
798		CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset,
799		CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
800		CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset,
801		CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
802
803	curve += 2;
804	REG_SET_4(CM_SHAPER_RAMB_REGION_14_15, 0,
805		CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset,
806		CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
807		CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset,
808		CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
809
810	curve += 2;
811	REG_SET_4(CM_SHAPER_RAMB_REGION_16_17, 0,
812		CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset,
813		CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
814		CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset,
815		CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
816
817	curve += 2;
818	REG_SET_4(CM_SHAPER_RAMB_REGION_18_19, 0,
819		CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset,
820		CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
821		CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset,
822		CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
823
824	curve += 2;
825	REG_SET_4(CM_SHAPER_RAMB_REGION_20_21, 0,
826		CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset,
827		CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
828		CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset,
829		CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
830
831	curve += 2;
832	REG_SET_4(CM_SHAPER_RAMB_REGION_22_23, 0,
833		CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset,
834		CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
835		CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset,
836		CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
837
838	curve += 2;
839	REG_SET_4(CM_SHAPER_RAMB_REGION_24_25, 0,
840		CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset,
841		CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
842		CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset,
843		CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
844
845	curve += 2;
846	REG_SET_4(CM_SHAPER_RAMB_REGION_26_27, 0,
847		CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset,
848		CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
849		CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset,
850		CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
851
852	curve += 2;
853	REG_SET_4(CM_SHAPER_RAMB_REGION_28_29, 0,
854		CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset,
855		CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
856		CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset,
857		CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
858
859	curve += 2;
860	REG_SET_4(CM_SHAPER_RAMB_REGION_30_31, 0,
861		CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset,
862		CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
863		CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset,
864		CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
865
866	curve += 2;
867	REG_SET_4(CM_SHAPER_RAMB_REGION_32_33, 0,
868		CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset,
869		CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
870		CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset,
871		CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
872
873}
874
875
876bool dpp20_program_shaper(
877		struct dpp *dpp_base,
878		const struct pwl_params *params)
879{
880	enum dc_lut_mode current_mode;
881	enum dc_lut_mode next_mode;
882
883	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
884
885	if (params == NULL) {
886		REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, 0);
887		return false;
888	}
889	current_mode = dpp20_get_shaper_current(dpp_base);
890
891	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
892		next_mode = LUT_RAM_B;
893	else
894		next_mode = LUT_RAM_A;
895
896	dpp20_configure_shaper_lut(dpp_base, next_mode == LUT_RAM_A);
897
898	if (next_mode == LUT_RAM_A)
899		dpp20_program_shaper_luta_settings(dpp_base, params);
900	else
901		dpp20_program_shaper_lutb_settings(dpp_base, params);
902
903	dpp20_program_shaper_lut(
904			dpp_base, params->rgb_resulted, params->hw_points_num);
905
906	REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
907
908	return true;
909
910}
911
912static enum dc_lut_mode get3dlut_config(
913			struct dpp *dpp_base,
914			bool *is_17x17x17,
915			bool *is_12bits_color_channel)
916{
917	uint32_t i_mode, i_enable_10bits, lut_size;
918	enum dc_lut_mode mode;
919	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
920
921	REG_GET_2(CM_3DLUT_READ_WRITE_CONTROL,
922			CM_3DLUT_CONFIG_STATUS, &i_mode,
923			CM_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(CM_3DLUT_MODE, CM_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/*
954 * select ramA or ramB, or bypass
955 * select color channel size 10 or 12 bits
956 * select 3dlut size 17x17x17 or 9x9x9
957 */
958static void dpp20_set_3dlut_mode(
959		struct dpp *dpp_base,
960		enum dc_lut_mode mode,
961		bool is_color_channel_12bits,
962		bool is_lut_size17x17x17)
963{
964	uint32_t lut_mode;
965	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
966
967	if (mode == LUT_BYPASS)
968		lut_mode = 0;
969	else if (mode == LUT_RAM_A)
970		lut_mode = 1;
971	else
972		lut_mode = 2;
973
974	REG_UPDATE_2(CM_3DLUT_MODE,
975			CM_3DLUT_MODE, lut_mode,
976			CM_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
977}
978
979static void dpp20_select_3dlut_ram(
980		struct dpp *dpp_base,
981		enum dc_lut_mode mode,
982		bool is_color_channel_12bits)
983{
984	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
985
986	REG_UPDATE_2(CM_3DLUT_READ_WRITE_CONTROL,
987			CM_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
988			CM_3DLUT_30BIT_EN,
989			is_color_channel_12bits == true ? 0:1);
990}
991
992
993
994static void dpp20_set3dlut_ram12(
995		struct dpp *dpp_base,
996		const struct dc_rgb *lut,
997		uint32_t entries)
998{
999	uint32_t i, red, green, blue, red1, green1, blue1;
1000	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1001
1002	for (i = 0 ; i < entries; i += 2) {
1003		red   = lut[i].red<<4;
1004		green = lut[i].green<<4;
1005		blue  = lut[i].blue<<4;
1006		red1   = lut[i+1].red<<4;
1007		green1 = lut[i+1].green<<4;
1008		blue1  = lut[i+1].blue<<4;
1009
1010		REG_SET_2(CM_3DLUT_DATA, 0,
1011				CM_3DLUT_DATA0, red,
1012				CM_3DLUT_DATA1, red1);
1013
1014		REG_SET_2(CM_3DLUT_DATA, 0,
1015				CM_3DLUT_DATA0, green,
1016				CM_3DLUT_DATA1, green1);
1017
1018		REG_SET_2(CM_3DLUT_DATA, 0,
1019				CM_3DLUT_DATA0, blue,
1020				CM_3DLUT_DATA1, blue1);
1021
1022	}
1023}
1024
1025/*
1026 * load selected lut with 10 bits color channels
1027 */
1028static void dpp20_set3dlut_ram10(
1029		struct dpp *dpp_base,
1030		const struct dc_rgb *lut,
1031		uint32_t entries)
1032{
1033	uint32_t i, red, green, blue, value;
1034	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1035
1036	for (i = 0; i < entries; i++) {
1037		red   = lut[i].red;
1038		green = lut[i].green;
1039		blue  = lut[i].blue;
1040
1041		value = (red<<20) | (green<<10) | blue;
1042
1043		REG_SET(CM_3DLUT_DATA_30BIT, 0, CM_3DLUT_DATA_30BIT, value);
1044	}
1045
1046}
1047
1048
1049static void dpp20_select_3dlut_ram_mask(
1050		struct dpp *dpp_base,
1051		uint32_t ram_selection_mask)
1052{
1053	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1054
1055	REG_UPDATE(CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_WRITE_EN_MASK,
1056			ram_selection_mask);
1057	REG_SET(CM_3DLUT_INDEX, 0, CM_3DLUT_INDEX, 0);
1058}
1059
1060bool dpp20_program_3dlut(
1061		struct dpp *dpp_base,
1062		struct tetrahedral_params *params)
1063{
1064	enum dc_lut_mode mode;
1065	bool is_17x17x17;
1066	bool is_12bits_color_channel;
1067	struct dc_rgb *lut0;
1068	struct dc_rgb *lut1;
1069	struct dc_rgb *lut2;
1070	struct dc_rgb *lut3;
1071	int lut_size0;
1072	int lut_size;
1073
1074	if (params == NULL) {
1075		dpp20_set_3dlut_mode(dpp_base, LUT_BYPASS, false, false);
1076		return false;
1077	}
1078	mode = get3dlut_config(dpp_base, &is_17x17x17, &is_12bits_color_channel);
1079
1080	if (mode == LUT_BYPASS || mode == LUT_RAM_B)
1081		mode = LUT_RAM_A;
1082	else
1083		mode = LUT_RAM_B;
1084
1085	is_17x17x17 = !params->use_tetrahedral_9;
1086	is_12bits_color_channel = params->use_12bits;
1087	if (is_17x17x17) {
1088		lut0 = params->tetrahedral_17.lut0;
1089		lut1 = params->tetrahedral_17.lut1;
1090		lut2 = params->tetrahedral_17.lut2;
1091		lut3 = params->tetrahedral_17.lut3;
1092		lut_size0 = sizeof(params->tetrahedral_17.lut0)/
1093					sizeof(params->tetrahedral_17.lut0[0]);
1094		lut_size  = sizeof(params->tetrahedral_17.lut1)/
1095					sizeof(params->tetrahedral_17.lut1[0]);
1096	} else {
1097		lut0 = params->tetrahedral_9.lut0;
1098		lut1 = params->tetrahedral_9.lut1;
1099		lut2 = params->tetrahedral_9.lut2;
1100		lut3 = params->tetrahedral_9.lut3;
1101		lut_size0 = sizeof(params->tetrahedral_9.lut0)/
1102				sizeof(params->tetrahedral_9.lut0[0]);
1103		lut_size  = sizeof(params->tetrahedral_9.lut1)/
1104				sizeof(params->tetrahedral_9.lut1[0]);
1105		}
1106
1107	dpp20_select_3dlut_ram(dpp_base, mode,
1108				is_12bits_color_channel);
1109	dpp20_select_3dlut_ram_mask(dpp_base, 0x1);
1110	if (is_12bits_color_channel)
1111		dpp20_set3dlut_ram12(dpp_base, lut0, lut_size0);
1112	else
1113		dpp20_set3dlut_ram10(dpp_base, lut0, lut_size0);
1114
1115	dpp20_select_3dlut_ram_mask(dpp_base, 0x2);
1116	if (is_12bits_color_channel)
1117		dpp20_set3dlut_ram12(dpp_base, lut1, lut_size);
1118	else
1119		dpp20_set3dlut_ram10(dpp_base, lut1, lut_size);
1120
1121	dpp20_select_3dlut_ram_mask(dpp_base, 0x4);
1122	if (is_12bits_color_channel)
1123		dpp20_set3dlut_ram12(dpp_base, lut2, lut_size);
1124	else
1125		dpp20_set3dlut_ram10(dpp_base, lut2, lut_size);
1126
1127	dpp20_select_3dlut_ram_mask(dpp_base, 0x8);
1128	if (is_12bits_color_channel)
1129		dpp20_set3dlut_ram12(dpp_base, lut3, lut_size);
1130	else
1131		dpp20_set3dlut_ram10(dpp_base, lut3, lut_size);
1132
1133
1134	dpp20_set_3dlut_mode(dpp_base, mode, is_12bits_color_channel,
1135					is_17x17x17);
1136
1137	return true;
1138}
1139
1140void dpp2_set_hdr_multiplier(
1141		struct dpp *dpp_base,
1142		uint32_t multiplier)
1143{
1144	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1145
1146	REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
1147}
1148