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