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
237static void read_gamut_remap(struct dcn20_dpp *dpp,
238			     uint16_t *regval,
239			     enum dcn20_gamut_remap_select *select)
240{
241	struct color_matrices_reg gam_regs;
242	uint32_t selection;
243
244	IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
245		   CM_TEST_DEBUG_DATA_STATUS_IDX,
246		   CM_TEST_DEBUG_DATA_GAMUT_REMAP_MODE, &selection);
247
248	*select = selection;
249
250	gam_regs.shifts.csc_c11 = dpp->tf_shift->CM_GAMUT_REMAP_C11;
251	gam_regs.masks.csc_c11  = dpp->tf_mask->CM_GAMUT_REMAP_C11;
252	gam_regs.shifts.csc_c12 = dpp->tf_shift->CM_GAMUT_REMAP_C12;
253	gam_regs.masks.csc_c12 = dpp->tf_mask->CM_GAMUT_REMAP_C12;
254
255	if (*select == DCN2_GAMUT_REMAP_COEF_A) {
256		gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_C11_C12);
257		gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_C33_C34);
258
259		cm_helper_read_color_matrices(dpp->base.ctx,
260					      regval,
261					      &gam_regs);
262
263	} else if (*select == DCN2_GAMUT_REMAP_COEF_B) {
264		gam_regs.csc_c11_c12 = REG(CM_GAMUT_REMAP_B_C11_C12);
265		gam_regs.csc_c33_c34 = REG(CM_GAMUT_REMAP_B_C33_C34);
266
267		cm_helper_read_color_matrices(dpp->base.ctx,
268					      regval,
269					      &gam_regs);
270	}
271}
272
273void dpp2_cm_get_gamut_remap(struct dpp *dpp_base,
274			     struct dpp_grph_csc_adjustment *adjust)
275{
276	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
277	uint16_t arr_reg_val[12];
278	enum dcn20_gamut_remap_select select;
279
280	read_gamut_remap(dpp, arr_reg_val, &select);
281
282	if (select == DCN2_GAMUT_REMAP_BYPASS) {
283		adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
284		return;
285	}
286
287	adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
288	convert_hw_matrix(adjust->temperature_matrix,
289			  arr_reg_val, ARRAY_SIZE(arr_reg_val));
290}
291
292void dpp2_program_input_csc(
293		struct dpp *dpp_base,
294		enum dc_color_space color_space,
295		enum dcn20_input_csc_select input_select,
296		const struct out_csc_color_matrix *tbl_entry)
297{
298	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
299	int i;
300	int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
301	const uint16_t *regval = NULL;
302	uint32_t cur_select = 0;
303	enum dcn20_input_csc_select select;
304	struct color_matrices_reg icsc_regs;
305
306	if (input_select == DCN2_ICSC_SELECT_BYPASS) {
307		REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
308		return;
309	}
310
311	if (tbl_entry == NULL) {
312		for (i = 0; i < arr_size; i++)
313			if (dpp_input_csc_matrix[i].color_space == color_space) {
314				regval = dpp_input_csc_matrix[i].regval;
315				break;
316			}
317
318		if (regval == NULL) {
319			BREAK_TO_DEBUGGER();
320			return;
321		}
322	} else {
323		regval = tbl_entry->regval;
324	}
325
326	/* determine which CSC coefficients (A or B) we are using
327	 * currently.  select the alternate set to double buffer
328	 * the CSC update so CSC is updated on frame boundary
329	 */
330	IX_REG_GET(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
331					CM_TEST_DEBUG_DATA_STATUS_IDX,
332					CM_TEST_DEBUG_DATA_ICSC_MODE, &cur_select);
333
334	if (cur_select != DCN2_ICSC_SELECT_ICSC_A)
335		select = DCN2_ICSC_SELECT_ICSC_A;
336	else
337		select = DCN2_ICSC_SELECT_ICSC_B;
338
339	icsc_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11;
340	icsc_regs.masks.csc_c11  = dpp->tf_mask->CM_ICSC_C11;
341	icsc_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12;
342	icsc_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12;
343
344	if (select == DCN2_ICSC_SELECT_ICSC_A) {
345
346		icsc_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12);
347		icsc_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34);
348
349	} else {
350
351		icsc_regs.csc_c11_c12 = REG(CM_ICSC_B_C11_C12);
352		icsc_regs.csc_c33_c34 = REG(CM_ICSC_B_C33_C34);
353
354	}
355
356	cm_helper_program_color_matrices(
357			dpp->base.ctx,
358			regval,
359			&icsc_regs);
360
361	REG_SET(CM_ICSC_CONTROL, 0,
362				CM_ICSC_MODE, select);
363}
364
365static void dpp20_power_on_blnd_lut(
366	struct dpp *dpp_base,
367	bool power_on)
368{
369	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
370
371	REG_SET(CM_MEM_PWR_CTRL, 0,
372			BLNDGAM_MEM_PWR_FORCE, power_on == true ? 0:1);
373
374}
375
376static void dpp20_configure_blnd_lut(
377		struct dpp *dpp_base,
378		bool is_ram_a)
379{
380	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
381
382	REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
383			CM_BLNDGAM_LUT_WRITE_EN_MASK, 7);
384	REG_UPDATE(CM_BLNDGAM_LUT_WRITE_EN_MASK,
385			CM_BLNDGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
386	REG_SET(CM_BLNDGAM_LUT_INDEX, 0, CM_BLNDGAM_LUT_INDEX, 0);
387}
388
389static void dpp20_program_blnd_pwl(
390		struct dpp *dpp_base,
391		const struct pwl_result_data *rgb,
392		uint32_t num)
393{
394	uint32_t i;
395	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
396
397	for (i = 0 ; i < num; i++) {
398		REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].red_reg);
399		REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].green_reg);
400		REG_SET(CM_BLNDGAM_LUT_DATA, 0, CM_BLNDGAM_LUT_DATA, rgb[i].blue_reg);
401
402		REG_SET(CM_BLNDGAM_LUT_DATA, 0,
403				CM_BLNDGAM_LUT_DATA, rgb[i].delta_red_reg);
404		REG_SET(CM_BLNDGAM_LUT_DATA, 0,
405				CM_BLNDGAM_LUT_DATA, rgb[i].delta_green_reg);
406		REG_SET(CM_BLNDGAM_LUT_DATA, 0,
407				CM_BLNDGAM_LUT_DATA, rgb[i].delta_blue_reg);
408
409	}
410
411}
412
413static void dcn20_dpp_cm_get_reg_field(
414		struct dcn20_dpp *dpp,
415		struct xfer_func_reg *reg)
416{
417	reg->shifts.exp_region0_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
418	reg->masks.exp_region0_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_LUT_OFFSET;
419	reg->shifts.exp_region0_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
420	reg->masks.exp_region0_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION0_NUM_SEGMENTS;
421	reg->shifts.exp_region1_lut_offset = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
422	reg->masks.exp_region1_lut_offset = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_LUT_OFFSET;
423	reg->shifts.exp_region1_num_segments = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
424	reg->masks.exp_region1_num_segments = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION1_NUM_SEGMENTS;
425
426	reg->shifts.field_region_end = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
427	reg->masks.field_region_end = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_B;
428	reg->shifts.field_region_end_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
429	reg->masks.field_region_end_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_SLOPE_B;
430	reg->shifts.field_region_end_base = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
431	reg->masks.field_region_end_base = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_END_BASE_B;
432	reg->shifts.field_region_linear_slope = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
433	reg->masks.field_region_linear_slope = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B;
434	reg->shifts.exp_region_start = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
435	reg->masks.exp_region_start = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_B;
436	reg->shifts.exp_resion_start_segment = dpp->tf_shift->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
437	reg->masks.exp_resion_start_segment = dpp->tf_mask->CM_BLNDGAM_RAMA_EXP_REGION_START_SEGMENT_B;
438}
439
440/*program blnd lut RAM A*/
441static void dpp20_program_blnd_luta_settings(
442		struct dpp *dpp_base,
443		const struct pwl_params *params)
444{
445	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
446	struct xfer_func_reg gam_regs;
447
448	dcn20_dpp_cm_get_reg_field(dpp, &gam_regs);
449
450	gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMA_START_CNTL_B);
451	gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMA_START_CNTL_G);
452	gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMA_START_CNTL_R);
453	gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_B);
454	gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_G);
455	gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMA_SLOPE_CNTL_R);
456	gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMA_END_CNTL1_B);
457	gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMA_END_CNTL2_B);
458	gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMA_END_CNTL1_G);
459	gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMA_END_CNTL2_G);
460	gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMA_END_CNTL1_R);
461	gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMA_END_CNTL2_R);
462	gam_regs.region_start = REG(CM_BLNDGAM_RAMA_REGION_0_1);
463	gam_regs.region_end = REG(CM_BLNDGAM_RAMA_REGION_32_33);
464
465	cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
466}
467
468/*program blnd lut RAM B*/
469static void dpp20_program_blnd_lutb_settings(
470		struct dpp *dpp_base,
471		const struct pwl_params *params)
472{
473	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
474	struct xfer_func_reg gam_regs;
475
476	dcn20_dpp_cm_get_reg_field(dpp, &gam_regs);
477
478	gam_regs.start_cntl_b = REG(CM_BLNDGAM_RAMB_START_CNTL_B);
479	gam_regs.start_cntl_g = REG(CM_BLNDGAM_RAMB_START_CNTL_G);
480	gam_regs.start_cntl_r = REG(CM_BLNDGAM_RAMB_START_CNTL_R);
481	gam_regs.start_slope_cntl_b = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_B);
482	gam_regs.start_slope_cntl_g = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_G);
483	gam_regs.start_slope_cntl_r = REG(CM_BLNDGAM_RAMB_SLOPE_CNTL_R);
484	gam_regs.start_end_cntl1_b = REG(CM_BLNDGAM_RAMB_END_CNTL1_B);
485	gam_regs.start_end_cntl2_b = REG(CM_BLNDGAM_RAMB_END_CNTL2_B);
486	gam_regs.start_end_cntl1_g = REG(CM_BLNDGAM_RAMB_END_CNTL1_G);
487	gam_regs.start_end_cntl2_g = REG(CM_BLNDGAM_RAMB_END_CNTL2_G);
488	gam_regs.start_end_cntl1_r = REG(CM_BLNDGAM_RAMB_END_CNTL1_R);
489	gam_regs.start_end_cntl2_r = REG(CM_BLNDGAM_RAMB_END_CNTL2_R);
490	gam_regs.region_start = REG(CM_BLNDGAM_RAMB_REGION_0_1);
491	gam_regs.region_end = REG(CM_BLNDGAM_RAMB_REGION_32_33);
492
493	cm_helper_program_xfer_func(dpp->base.ctx, params, &gam_regs);
494}
495
496static enum dc_lut_mode dpp20_get_blndgam_current(struct dpp *dpp_base)
497{
498	enum dc_lut_mode mode;
499	uint32_t state_mode;
500	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
501
502	REG_GET(CM_BLNDGAM_LUT_WRITE_EN_MASK, CM_BLNDGAM_CONFIG_STATUS, &state_mode);
503
504	switch (state_mode) {
505	case 0:
506		mode = LUT_BYPASS;
507		break;
508	case 1:
509		mode = LUT_RAM_A;
510		break;
511	case 2:
512		mode = LUT_RAM_B;
513		break;
514	default:
515		mode = LUT_BYPASS;
516		break;
517	}
518
519	return mode;
520}
521
522bool dpp20_program_blnd_lut(
523	struct dpp *dpp_base, const struct pwl_params *params)
524{
525	enum dc_lut_mode current_mode;
526	enum dc_lut_mode next_mode;
527	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
528
529	if (params == NULL) {
530		REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE, 0);
531		return false;
532	}
533	current_mode = dpp20_get_blndgam_current(dpp_base);
534	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
535		next_mode = LUT_RAM_B;
536	else
537		next_mode = LUT_RAM_A;
538
539	dpp20_power_on_blnd_lut(dpp_base, true);
540	dpp20_configure_blnd_lut(dpp_base, next_mode == LUT_RAM_A);
541
542	if (next_mode == LUT_RAM_A)
543		dpp20_program_blnd_luta_settings(dpp_base, params);
544	else
545		dpp20_program_blnd_lutb_settings(dpp_base, params);
546
547	dpp20_program_blnd_pwl(
548			dpp_base, params->rgb_resulted, params->hw_points_num);
549
550	REG_SET(CM_BLNDGAM_CONTROL, 0, CM_BLNDGAM_LUT_MODE,
551			next_mode == LUT_RAM_A ? 1:2);
552
553	return true;
554}
555
556
557static void dpp20_program_shaper_lut(
558		struct dpp *dpp_base,
559		const struct pwl_result_data *rgb,
560		uint32_t num)
561{
562	uint32_t i, red, green, blue;
563	uint32_t  red_delta, green_delta, blue_delta;
564	uint32_t  red_value, green_value, blue_value;
565
566	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
567
568	for (i = 0 ; i < num; i++) {
569
570		red   = rgb[i].red_reg;
571		green = rgb[i].green_reg;
572		blue  = rgb[i].blue_reg;
573
574		red_delta   = rgb[i].delta_red_reg;
575		green_delta = rgb[i].delta_green_reg;
576		blue_delta  = rgb[i].delta_blue_reg;
577
578		red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
579		green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
580		blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
581
582		REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, red_value);
583		REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, green_value);
584		REG_SET(CM_SHAPER_LUT_DATA, 0, CM_SHAPER_LUT_DATA, blue_value);
585	}
586
587}
588
589static enum dc_lut_mode dpp20_get_shaper_current(struct dpp *dpp_base)
590{
591	enum dc_lut_mode mode;
592	uint32_t state_mode;
593	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
594
595	REG_GET(CM_SHAPER_LUT_WRITE_EN_MASK, CM_SHAPER_CONFIG_STATUS, &state_mode);
596
597	switch (state_mode) {
598	case 0:
599		mode = LUT_BYPASS;
600		break;
601	case 1:
602		mode = LUT_RAM_A;
603		break;
604	case 2:
605		mode = LUT_RAM_B;
606		break;
607	default:
608		mode = LUT_BYPASS;
609		break;
610	}
611
612	return mode;
613}
614
615static void dpp20_configure_shaper_lut(
616		struct dpp *dpp_base,
617		bool is_ram_a)
618{
619	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
620
621	REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
622			CM_SHAPER_LUT_WRITE_EN_MASK, 7);
623	REG_UPDATE(CM_SHAPER_LUT_WRITE_EN_MASK,
624			CM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
625	REG_SET(CM_SHAPER_LUT_INDEX, 0, CM_SHAPER_LUT_INDEX, 0);
626}
627
628/*program shaper RAM A*/
629
630static void dpp20_program_shaper_luta_settings(
631		struct dpp *dpp_base,
632		const struct pwl_params *params)
633{
634	const struct gamma_curve *curve;
635	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
636
637	REG_SET_2(CM_SHAPER_RAMA_START_CNTL_B, 0,
638		CM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
639		CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
640	REG_SET_2(CM_SHAPER_RAMA_START_CNTL_G, 0,
641		CM_SHAPER_RAMA_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
642		CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, 0);
643	REG_SET_2(CM_SHAPER_RAMA_START_CNTL_R, 0,
644		CM_SHAPER_RAMA_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
645		CM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, 0);
646
647	REG_SET_2(CM_SHAPER_RAMA_END_CNTL_B, 0,
648		CM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
649		CM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
650
651	REG_SET_2(CM_SHAPER_RAMA_END_CNTL_G, 0,
652		CM_SHAPER_RAMA_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
653		CM_SHAPER_RAMA_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
654
655	REG_SET_2(CM_SHAPER_RAMA_END_CNTL_R, 0,
656		CM_SHAPER_RAMA_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
657		CM_SHAPER_RAMA_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
658
659	curve = params->arr_curve_points;
660	REG_SET_4(CM_SHAPER_RAMA_REGION_0_1, 0,
661		CM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
662		CM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
663		CM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
664		CM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
665
666	curve += 2;
667	REG_SET_4(CM_SHAPER_RAMA_REGION_2_3, 0,
668		CM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset,
669		CM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
670		CM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset,
671		CM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
672
673	curve += 2;
674	REG_SET_4(CM_SHAPER_RAMA_REGION_4_5, 0,
675		CM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset,
676		CM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
677		CM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset,
678		CM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
679
680	curve += 2;
681	REG_SET_4(CM_SHAPER_RAMA_REGION_6_7, 0,
682		CM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset,
683		CM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
684		CM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset,
685		CM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
686
687	curve += 2;
688	REG_SET_4(CM_SHAPER_RAMA_REGION_8_9, 0,
689		CM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset,
690		CM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
691		CM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset,
692		CM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
693
694	curve += 2;
695	REG_SET_4(CM_SHAPER_RAMA_REGION_10_11, 0,
696		CM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset,
697		CM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
698		CM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset,
699		CM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
700
701	curve += 2;
702	REG_SET_4(CM_SHAPER_RAMA_REGION_12_13, 0,
703		CM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset,
704		CM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
705		CM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset,
706		CM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
707
708	curve += 2;
709	REG_SET_4(CM_SHAPER_RAMA_REGION_14_15, 0,
710		CM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset,
711		CM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
712		CM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset,
713		CM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
714
715	curve += 2;
716	REG_SET_4(CM_SHAPER_RAMA_REGION_16_17, 0,
717		CM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset,
718		CM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
719		CM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset,
720		CM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
721
722	curve += 2;
723	REG_SET_4(CM_SHAPER_RAMA_REGION_18_19, 0,
724		CM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset,
725		CM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
726		CM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset,
727		CM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
728
729	curve += 2;
730	REG_SET_4(CM_SHAPER_RAMA_REGION_20_21, 0,
731		CM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset,
732		CM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
733		CM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset,
734		CM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
735
736	curve += 2;
737	REG_SET_4(CM_SHAPER_RAMA_REGION_22_23, 0,
738		CM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset,
739		CM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
740		CM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset,
741		CM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
742
743	curve += 2;
744	REG_SET_4(CM_SHAPER_RAMA_REGION_24_25, 0,
745		CM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset,
746		CM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
747		CM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset,
748		CM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
749
750	curve += 2;
751	REG_SET_4(CM_SHAPER_RAMA_REGION_26_27, 0,
752		CM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset,
753		CM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
754		CM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset,
755		CM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
756
757	curve += 2;
758	REG_SET_4(CM_SHAPER_RAMA_REGION_28_29, 0,
759		CM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset,
760		CM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
761		CM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset,
762		CM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
763
764	curve += 2;
765	REG_SET_4(CM_SHAPER_RAMA_REGION_30_31, 0,
766		CM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset,
767		CM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
768		CM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset,
769		CM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
770
771	curve += 2;
772	REG_SET_4(CM_SHAPER_RAMA_REGION_32_33, 0,
773		CM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset,
774		CM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
775		CM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset,
776		CM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
777}
778
779/*program shaper RAM B*/
780static void dpp20_program_shaper_lutb_settings(
781		struct dpp *dpp_base,
782		const struct pwl_params *params)
783{
784	const struct gamma_curve *curve;
785	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
786
787	REG_SET_2(CM_SHAPER_RAMB_START_CNTL_B, 0,
788		CM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
789		CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
790	REG_SET_2(CM_SHAPER_RAMB_START_CNTL_G, 0,
791		CM_SHAPER_RAMB_EXP_REGION_START_G, params->corner_points[0].green.custom_float_x,
792		CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, 0);
793	REG_SET_2(CM_SHAPER_RAMB_START_CNTL_R, 0,
794		CM_SHAPER_RAMB_EXP_REGION_START_R, params->corner_points[0].red.custom_float_x,
795		CM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, 0);
796
797	REG_SET_2(CM_SHAPER_RAMB_END_CNTL_B, 0,
798		CM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
799		CM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
800
801	REG_SET_2(CM_SHAPER_RAMB_END_CNTL_G, 0,
802		CM_SHAPER_RAMB_EXP_REGION_END_G, params->corner_points[1].green.custom_float_x,
803		CM_SHAPER_RAMB_EXP_REGION_END_BASE_G, params->corner_points[1].green.custom_float_y);
804
805	REG_SET_2(CM_SHAPER_RAMB_END_CNTL_R, 0,
806		CM_SHAPER_RAMB_EXP_REGION_END_R, params->corner_points[1].red.custom_float_x,
807		CM_SHAPER_RAMB_EXP_REGION_END_BASE_R, params->corner_points[1].red.custom_float_y);
808
809	curve = params->arr_curve_points;
810	REG_SET_4(CM_SHAPER_RAMB_REGION_0_1, 0,
811		CM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
812		CM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
813		CM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
814		CM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
815
816	curve += 2;
817	REG_SET_4(CM_SHAPER_RAMB_REGION_2_3, 0,
818		CM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset,
819		CM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
820		CM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset,
821		CM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
822
823	curve += 2;
824	REG_SET_4(CM_SHAPER_RAMB_REGION_4_5, 0,
825		CM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset,
826		CM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
827		CM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset,
828		CM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
829
830	curve += 2;
831	REG_SET_4(CM_SHAPER_RAMB_REGION_6_7, 0,
832		CM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset,
833		CM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
834		CM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset,
835		CM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
836
837	curve += 2;
838	REG_SET_4(CM_SHAPER_RAMB_REGION_8_9, 0,
839		CM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset,
840		CM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
841		CM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset,
842		CM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
843
844	curve += 2;
845	REG_SET_4(CM_SHAPER_RAMB_REGION_10_11, 0,
846		CM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset,
847		CM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
848		CM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset,
849		CM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
850
851	curve += 2;
852	REG_SET_4(CM_SHAPER_RAMB_REGION_12_13, 0,
853		CM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset,
854		CM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
855		CM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset,
856		CM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
857
858	curve += 2;
859	REG_SET_4(CM_SHAPER_RAMB_REGION_14_15, 0,
860		CM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset,
861		CM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
862		CM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset,
863		CM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
864
865	curve += 2;
866	REG_SET_4(CM_SHAPER_RAMB_REGION_16_17, 0,
867		CM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset,
868		CM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
869		CM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset,
870		CM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
871
872	curve += 2;
873	REG_SET_4(CM_SHAPER_RAMB_REGION_18_19, 0,
874		CM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset,
875		CM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
876		CM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset,
877		CM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
878
879	curve += 2;
880	REG_SET_4(CM_SHAPER_RAMB_REGION_20_21, 0,
881		CM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset,
882		CM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
883		CM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset,
884		CM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
885
886	curve += 2;
887	REG_SET_4(CM_SHAPER_RAMB_REGION_22_23, 0,
888		CM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset,
889		CM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
890		CM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset,
891		CM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
892
893	curve += 2;
894	REG_SET_4(CM_SHAPER_RAMB_REGION_24_25, 0,
895		CM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset,
896		CM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
897		CM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset,
898		CM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
899
900	curve += 2;
901	REG_SET_4(CM_SHAPER_RAMB_REGION_26_27, 0,
902		CM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset,
903		CM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
904		CM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset,
905		CM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
906
907	curve += 2;
908	REG_SET_4(CM_SHAPER_RAMB_REGION_28_29, 0,
909		CM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset,
910		CM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
911		CM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset,
912		CM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
913
914	curve += 2;
915	REG_SET_4(CM_SHAPER_RAMB_REGION_30_31, 0,
916		CM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset,
917		CM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
918		CM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset,
919		CM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
920
921	curve += 2;
922	REG_SET_4(CM_SHAPER_RAMB_REGION_32_33, 0,
923		CM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset,
924		CM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
925		CM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset,
926		CM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
927
928}
929
930
931bool dpp20_program_shaper(
932		struct dpp *dpp_base,
933		const struct pwl_params *params)
934{
935	enum dc_lut_mode current_mode;
936	enum dc_lut_mode next_mode;
937
938	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
939
940	if (params == NULL) {
941		REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, 0);
942		return false;
943	}
944	current_mode = dpp20_get_shaper_current(dpp_base);
945
946	if (current_mode == LUT_BYPASS || current_mode == LUT_RAM_A)
947		next_mode = LUT_RAM_B;
948	else
949		next_mode = LUT_RAM_A;
950
951	dpp20_configure_shaper_lut(dpp_base, next_mode == LUT_RAM_A);
952
953	if (next_mode == LUT_RAM_A)
954		dpp20_program_shaper_luta_settings(dpp_base, params);
955	else
956		dpp20_program_shaper_lutb_settings(dpp_base, params);
957
958	dpp20_program_shaper_lut(
959			dpp_base, params->rgb_resulted, params->hw_points_num);
960
961	REG_SET(CM_SHAPER_CONTROL, 0, CM_SHAPER_LUT_MODE, next_mode == LUT_RAM_A ? 1:2);
962
963	return true;
964
965}
966
967static enum dc_lut_mode get3dlut_config(
968			struct dpp *dpp_base,
969			bool *is_17x17x17,
970			bool *is_12bits_color_channel)
971{
972	uint32_t i_mode, i_enable_10bits, lut_size;
973	enum dc_lut_mode mode;
974	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
975
976	REG_GET_2(CM_3DLUT_READ_WRITE_CONTROL,
977			CM_3DLUT_CONFIG_STATUS, &i_mode,
978			CM_3DLUT_30BIT_EN, &i_enable_10bits);
979
980	switch (i_mode) {
981	case 0:
982		mode = LUT_BYPASS;
983		break;
984	case 1:
985		mode = LUT_RAM_A;
986		break;
987	case 2:
988		mode = LUT_RAM_B;
989		break;
990	default:
991		mode = LUT_BYPASS;
992		break;
993	}
994	if (i_enable_10bits > 0)
995		*is_12bits_color_channel = false;
996	else
997		*is_12bits_color_channel = true;
998
999	REG_GET(CM_3DLUT_MODE, CM_3DLUT_SIZE, &lut_size);
1000
1001	if (lut_size == 0)
1002		*is_17x17x17 = true;
1003	else
1004		*is_17x17x17 = false;
1005
1006	return mode;
1007}
1008/*
1009 * select ramA or ramB, or bypass
1010 * select color channel size 10 or 12 bits
1011 * select 3dlut size 17x17x17 or 9x9x9
1012 */
1013static void dpp20_set_3dlut_mode(
1014		struct dpp *dpp_base,
1015		enum dc_lut_mode mode,
1016		bool is_color_channel_12bits,
1017		bool is_lut_size17x17x17)
1018{
1019	uint32_t lut_mode;
1020	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1021
1022	if (mode == LUT_BYPASS)
1023		lut_mode = 0;
1024	else if (mode == LUT_RAM_A)
1025		lut_mode = 1;
1026	else
1027		lut_mode = 2;
1028
1029	REG_UPDATE_2(CM_3DLUT_MODE,
1030			CM_3DLUT_MODE, lut_mode,
1031			CM_3DLUT_SIZE, is_lut_size17x17x17 == true ? 0 : 1);
1032}
1033
1034static void dpp20_select_3dlut_ram(
1035		struct dpp *dpp_base,
1036		enum dc_lut_mode mode,
1037		bool is_color_channel_12bits)
1038{
1039	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1040
1041	REG_UPDATE_2(CM_3DLUT_READ_WRITE_CONTROL,
1042			CM_3DLUT_RAM_SEL, mode == LUT_RAM_A ? 0 : 1,
1043			CM_3DLUT_30BIT_EN,
1044			is_color_channel_12bits == true ? 0:1);
1045}
1046
1047
1048
1049static void dpp20_set3dlut_ram12(
1050		struct dpp *dpp_base,
1051		const struct dc_rgb *lut,
1052		uint32_t entries)
1053{
1054	uint32_t i, red, green, blue, red1, green1, blue1;
1055	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1056
1057	for (i = 0 ; i < entries; i += 2) {
1058		red   = lut[i].red<<4;
1059		green = lut[i].green<<4;
1060		blue  = lut[i].blue<<4;
1061		red1   = lut[i+1].red<<4;
1062		green1 = lut[i+1].green<<4;
1063		blue1  = lut[i+1].blue<<4;
1064
1065		REG_SET_2(CM_3DLUT_DATA, 0,
1066				CM_3DLUT_DATA0, red,
1067				CM_3DLUT_DATA1, red1);
1068
1069		REG_SET_2(CM_3DLUT_DATA, 0,
1070				CM_3DLUT_DATA0, green,
1071				CM_3DLUT_DATA1, green1);
1072
1073		REG_SET_2(CM_3DLUT_DATA, 0,
1074				CM_3DLUT_DATA0, blue,
1075				CM_3DLUT_DATA1, blue1);
1076
1077	}
1078}
1079
1080/*
1081 * load selected lut with 10 bits color channels
1082 */
1083static void dpp20_set3dlut_ram10(
1084		struct dpp *dpp_base,
1085		const struct dc_rgb *lut,
1086		uint32_t entries)
1087{
1088	uint32_t i, red, green, blue, value;
1089	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1090
1091	for (i = 0; i < entries; i++) {
1092		red   = lut[i].red;
1093		green = lut[i].green;
1094		blue  = lut[i].blue;
1095
1096		value = (red<<20) | (green<<10) | blue;
1097
1098		REG_SET(CM_3DLUT_DATA_30BIT, 0, CM_3DLUT_DATA_30BIT, value);
1099	}
1100
1101}
1102
1103
1104static void dpp20_select_3dlut_ram_mask(
1105		struct dpp *dpp_base,
1106		uint32_t ram_selection_mask)
1107{
1108	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1109
1110	REG_UPDATE(CM_3DLUT_READ_WRITE_CONTROL, CM_3DLUT_WRITE_EN_MASK,
1111			ram_selection_mask);
1112	REG_SET(CM_3DLUT_INDEX, 0, CM_3DLUT_INDEX, 0);
1113}
1114
1115bool dpp20_program_3dlut(
1116		struct dpp *dpp_base,
1117		struct tetrahedral_params *params)
1118{
1119	enum dc_lut_mode mode;
1120	bool is_17x17x17;
1121	bool is_12bits_color_channel;
1122	struct dc_rgb *lut0;
1123	struct dc_rgb *lut1;
1124	struct dc_rgb *lut2;
1125	struct dc_rgb *lut3;
1126	int lut_size0;
1127	int lut_size;
1128
1129	if (params == NULL) {
1130		dpp20_set_3dlut_mode(dpp_base, LUT_BYPASS, false, false);
1131		return false;
1132	}
1133	mode = get3dlut_config(dpp_base, &is_17x17x17, &is_12bits_color_channel);
1134
1135	if (mode == LUT_BYPASS || mode == LUT_RAM_B)
1136		mode = LUT_RAM_A;
1137	else
1138		mode = LUT_RAM_B;
1139
1140	is_17x17x17 = !params->use_tetrahedral_9;
1141	is_12bits_color_channel = params->use_12bits;
1142	if (is_17x17x17) {
1143		lut0 = params->tetrahedral_17.lut0;
1144		lut1 = params->tetrahedral_17.lut1;
1145		lut2 = params->tetrahedral_17.lut2;
1146		lut3 = params->tetrahedral_17.lut3;
1147		lut_size0 = sizeof(params->tetrahedral_17.lut0)/
1148					sizeof(params->tetrahedral_17.lut0[0]);
1149		lut_size  = sizeof(params->tetrahedral_17.lut1)/
1150					sizeof(params->tetrahedral_17.lut1[0]);
1151	} else {
1152		lut0 = params->tetrahedral_9.lut0;
1153		lut1 = params->tetrahedral_9.lut1;
1154		lut2 = params->tetrahedral_9.lut2;
1155		lut3 = params->tetrahedral_9.lut3;
1156		lut_size0 = sizeof(params->tetrahedral_9.lut0)/
1157				sizeof(params->tetrahedral_9.lut0[0]);
1158		lut_size  = sizeof(params->tetrahedral_9.lut1)/
1159				sizeof(params->tetrahedral_9.lut1[0]);
1160		}
1161
1162	dpp20_select_3dlut_ram(dpp_base, mode,
1163				is_12bits_color_channel);
1164	dpp20_select_3dlut_ram_mask(dpp_base, 0x1);
1165	if (is_12bits_color_channel)
1166		dpp20_set3dlut_ram12(dpp_base, lut0, lut_size0);
1167	else
1168		dpp20_set3dlut_ram10(dpp_base, lut0, lut_size0);
1169
1170	dpp20_select_3dlut_ram_mask(dpp_base, 0x2);
1171	if (is_12bits_color_channel)
1172		dpp20_set3dlut_ram12(dpp_base, lut1, lut_size);
1173	else
1174		dpp20_set3dlut_ram10(dpp_base, lut1, lut_size);
1175
1176	dpp20_select_3dlut_ram_mask(dpp_base, 0x4);
1177	if (is_12bits_color_channel)
1178		dpp20_set3dlut_ram12(dpp_base, lut2, lut_size);
1179	else
1180		dpp20_set3dlut_ram10(dpp_base, lut2, lut_size);
1181
1182	dpp20_select_3dlut_ram_mask(dpp_base, 0x8);
1183	if (is_12bits_color_channel)
1184		dpp20_set3dlut_ram12(dpp_base, lut3, lut_size);
1185	else
1186		dpp20_set3dlut_ram10(dpp_base, lut3, lut_size);
1187
1188
1189	dpp20_set_3dlut_mode(dpp_base, mode, is_12bits_color_channel,
1190					is_17x17x17);
1191
1192	return true;
1193}
1194
1195void dpp2_set_hdr_multiplier(
1196		struct dpp *dpp_base,
1197		uint32_t multiplier)
1198{
1199	struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
1200
1201	REG_UPDATE(CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, multiplier);
1202}
1203