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 "include/grph_object_id.h"
31 #include "include/fixed31_32.h"
32 #include "include/logger_interface.h"
33 
34 #include "reg_helper.h"
35 #include "dcn10_dpp.h"
36 #include "basics/conversion.h"
37 
38 #define NUM_PHASES    64
39 #define HORZ_MAX_TAPS 8
40 #define VERT_MAX_TAPS 8
41 
42 #define BLACK_OFFSET_RGB_Y 0x0
43 #define BLACK_OFFSET_CBCR  0x8000
44 
45 #define REG(reg)\
46 	xfm->tf_regs->reg
47 
48 #define CTX \
49 	xfm->base.ctx
50 
51 #undef FN
52 #define FN(reg_name, field_name) \
53 	xfm->tf_shift->field_name, xfm->tf_mask->field_name
54 
55 
56 enum dcn10_coef_filter_type_sel {
57 	SCL_COEF_LUMA_VERT_FILTER = 0,
58 	SCL_COEF_LUMA_HORZ_FILTER = 1,
59 	SCL_COEF_CHROMA_VERT_FILTER = 2,
60 	SCL_COEF_CHROMA_HORZ_FILTER = 3,
61 	SCL_COEF_ALPHA_VERT_FILTER = 4,
62 	SCL_COEF_ALPHA_HORZ_FILTER = 5
63 };
64 
65 enum lb_memory_config {
66 	/* Enable all 3 pieces of memory */
67 	LB_MEMORY_CONFIG_0 = 0,
68 
69 	/* Enable only the first piece of memory */
70 	LB_MEMORY_CONFIG_1 = 1,
71 
72 	/* Enable only the second piece of memory */
73 	LB_MEMORY_CONFIG_2 = 2,
74 
75 	/* Only applicable in 4:2:0 mode, enable all 3 pieces of memory and the
76 	 * last piece of chroma memory used for the luma storage
77 	 */
78 	LB_MEMORY_CONFIG_3 = 3
79 };
80 
81 enum dscl_autocal_mode {
82 	AUTOCAL_MODE_OFF = 0,
83 
84 	/* Autocal calculate the scaling ratio and initial phase and the
85 	 * DSCL_MODE_SEL must be set to 1
86 	 */
87 	AUTOCAL_MODE_AUTOSCALE = 1,
88 	/* Autocal perform auto centering without replication and the
89 	 * DSCL_MODE_SEL must be set to 0
90 	 */
91 	AUTOCAL_MODE_AUTOCENTER = 2,
92 	/* Autocal perform auto centering and auto replication and the
93 	 * DSCL_MODE_SEL must be set to 0
94 	 */
95 	AUTOCAL_MODE_AUTOREPLICATE = 3
96 };
97 
98 enum dscl_mode_sel {
99 	DSCL_MODE_SCALING_444_BYPASS = 0,
100 	DSCL_MODE_SCALING_444_RGB_ENABLE = 1,
101 	DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2,
102 	DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3,
103 	DSCL_MODE_SCALING_420_LUMA_BYPASS = 4,
104 	DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5,
105 	DSCL_MODE_DSCL_BYPASS = 6
106 };
107 
108 enum gamut_remap_select {
109 	GAMUT_REMAP_BYPASS = 0,
110 	GAMUT_REMAP_COEFF,
111 	GAMUT_REMAP_COMA_COEFF,
112 	GAMUT_REMAP_COMB_COEFF
113 };
114 
115 static void dpp_set_overscan(
116 	struct dcn10_dpp *xfm,
117 	const struct scaler_data *data)
118 {
119 	uint32_t left = data->recout.x;
120 	uint32_t top = data->recout.y;
121 
122 	int right = data->h_active - data->recout.x - data->recout.width;
123 	int bottom = data->v_active - data->recout.y - data->recout.height;
124 
125 	if (right < 0) {
126 		BREAK_TO_DEBUGGER();
127 		right = 0;
128 	}
129 	if (bottom < 0) {
130 		BREAK_TO_DEBUGGER();
131 		bottom = 0;
132 	}
133 
134 	REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0,
135 		EXT_OVERSCAN_LEFT, left,
136 		EXT_OVERSCAN_RIGHT, right);
137 
138 	REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0,
139 		EXT_OVERSCAN_BOTTOM, bottom,
140 		EXT_OVERSCAN_TOP, top);
141 }
142 
143 static void dpp_set_otg_blank(
144 		struct dcn10_dpp *xfm, const struct scaler_data *data)
145 {
146 	uint32_t h_blank_start = data->h_active;
147 	uint32_t h_blank_end = 0;
148 	uint32_t v_blank_start = data->v_active;
149 	uint32_t v_blank_end = 0;
150 
151 	REG_SET_2(OTG_H_BLANK, 0,
152 			OTG_H_BLANK_START, h_blank_start,
153 			OTG_H_BLANK_END, h_blank_end);
154 
155 	REG_SET_2(OTG_V_BLANK, 0,
156 			OTG_V_BLANK_START, v_blank_start,
157 			OTG_V_BLANK_END, v_blank_end);
158 }
159 
160 static enum dscl_mode_sel get_dscl_mode(
161 		const struct scaler_data *data, bool dbg_always_scale)
162 {
163 	const long long one = dal_fixed31_32_one.value;
164 	bool ycbcr = false;
165 	bool format420 = false;
166 
167 	if (data->format == PIXEL_FORMAT_FP16)
168 		return DSCL_MODE_DSCL_BYPASS;
169 
170 	if (data->format >= PIXEL_FORMAT_VIDEO_BEGIN
171 			&& data->format <= PIXEL_FORMAT_VIDEO_END)
172 		ycbcr = true;
173 
174 	if (data->format == PIXEL_FORMAT_420BPP8 ||
175 			data->format == PIXEL_FORMAT_420BPP10)
176 		format420 = true;
177 
178 	if (data->ratios.horz.value == one
179 			&& data->ratios.vert.value == one
180 			&& data->ratios.horz_c.value == one
181 			&& data->ratios.vert_c.value == one
182 			&& !dbg_always_scale)
183 		return DSCL_MODE_SCALING_444_BYPASS;
184 
185 	if (!format420) {
186 		if (ycbcr)
187 			return DSCL_MODE_SCALING_444_YCBCR_ENABLE;
188 		else
189 			return DSCL_MODE_SCALING_444_RGB_ENABLE;
190 	}
191 	if (data->ratios.horz.value == one && data->ratios.vert.value == one)
192 		return DSCL_MODE_SCALING_420_LUMA_BYPASS;
193 	if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
194 		return DSCL_MODE_SCALING_420_CHROMA_BYPASS;
195 
196 	return DSCL_MODE_SCALING_420_YCBCR_ENABLE;
197 }
198 
199 static int get_pixel_depth_val(enum lb_pixel_depth depth)
200 {
201 	if (depth == LB_PIXEL_DEPTH_30BPP)
202 		return 0; /* 10 bpc */
203 	else if (depth == LB_PIXEL_DEPTH_24BPP)
204 		return 1; /* 8 bpc */
205 	else if (depth == LB_PIXEL_DEPTH_18BPP)
206 		return 2; /* 6 bpc */
207 	else if (depth == LB_PIXEL_DEPTH_36BPP)
208 		return 3; /* 12 bpc */
209 	else {
210 		ASSERT(0);
211 		return -1; /* Unsupported */
212 	}
213 }
214 
215 static void dpp_set_lb(
216 	struct dcn10_dpp *xfm,
217 	const struct line_buffer_params *lb_params,
218 	enum lb_memory_config mem_size_config)
219 {
220 	uint32_t pixel_depth = get_pixel_depth_val(lb_params->depth);
221 	uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth;
222 	REG_SET_7(LB_DATA_FORMAT, 0,
223 		PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */
224 		PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */
225 		PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */
226 		DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */
227 		DITHER_EN, 0, /* Dithering enable: Disabled */
228 		INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
229 		ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
230 
231 	REG_SET_2(LB_MEMORY_CTRL, 0,
232 		MEMORY_CONFIG, mem_size_config,
233 		LB_MAX_PARTITIONS, 63);
234 }
235 
236 static void dpp_set_scaler_filter(
237 		struct dcn10_dpp *xfm,
238 		uint32_t taps,
239 		enum dcn10_coef_filter_type_sel filter_type,
240 		const uint16_t *filter)
241 {
242 	const int tap_pairs = (taps + 1) / 2;
243 	int phase;
244 	int pair;
245 	uint16_t odd_coef, even_coef;
246 
247 	REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0,
248 		SCL_COEF_RAM_TAP_PAIR_IDX, 0,
249 		SCL_COEF_RAM_PHASE, 0,
250 		SCL_COEF_RAM_FILTER_TYPE, filter_type);
251 
252 	for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
253 		for (pair = 0; pair < tap_pairs; pair++) {
254 			even_coef = filter[phase * taps + 2 * pair];
255 			if ((pair * 2 + 1) < taps)
256 				odd_coef = filter[phase * taps + 2 * pair + 1];
257 			else
258 				odd_coef = 0;
259 
260 			REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
261 				/* Even tap coefficient (bits 1:0 fixed to 0) */
262 				SCL_COEF_RAM_EVEN_TAP_COEF, even_coef,
263 				/* Write/read control for even coefficient */
264 				SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1,
265 				/* Odd tap coefficient (bits 1:0 fixed to 0) */
266 				SCL_COEF_RAM_ODD_TAP_COEF, odd_coef,
267 				/* Write/read control for odd coefficient */
268 				SCL_COEF_RAM_ODD_TAP_COEF_EN, 1);
269 		}
270 	}
271 
272 }
273 
274 #if 0
275 bool dpp_set_pixel_storage_depth(
276 	struct dpp *xfm,
277 	enum lb_pixel_depth depth,
278 	const struct bit_depth_reduction_params *bit_depth_params)
279 {
280 	struct dcn10_dpp *xfm110 = TO_DCN10_DPP(xfm);
281 	bool ret = true;
282 	uint32_t value;
283 	enum dc_color_depth color_depth;
284 
285 	value = dm_read_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT));
286 	switch (depth) {
287 	case LB_PIXEL_DEPTH_18BPP:
288 		color_depth = COLOR_DEPTH_666;
289 		set_reg_field_value(value, 2, LB_DATA_FORMAT, PIXEL_DEPTH);
290 		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
291 		break;
292 	case LB_PIXEL_DEPTH_24BPP:
293 		color_depth = COLOR_DEPTH_888;
294 		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_DEPTH);
295 		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
296 		break;
297 	case LB_PIXEL_DEPTH_30BPP:
298 		color_depth = COLOR_DEPTH_101010;
299 		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_DEPTH);
300 		set_reg_field_value(value, 1, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
301 		break;
302 	case LB_PIXEL_DEPTH_36BPP:
303 		color_depth = COLOR_DEPTH_121212;
304 		set_reg_field_value(value, 3, LB_DATA_FORMAT, PIXEL_DEPTH);
305 		set_reg_field_value(value, 0, LB_DATA_FORMAT, PIXEL_EXPAN_MODE);
306 		break;
307 	default:
308 		ret = false;
309 		break;
310 	}
311 
312 	if (ret == true) {
313 		set_denormalization(xfm110, color_depth);
314 		ret = program_bit_depth_reduction(xfm110, color_depth,
315 				bit_depth_params);
316 
317 		set_reg_field_value(value, 0, LB_DATA_FORMAT, ALPHA_EN);
318 		dm_write_reg(xfm->ctx, LB_REG(mmLB_DATA_FORMAT), value);
319 		if (!(xfm110->lb_pixel_depth_supported & depth)) {
320 			/* We should use unsupported capabilities
321 			 * unless it is required by w/a
322 			 */
323 			dm_logger_write(xfm->ctx->logger, LOG_WARNING,
324 				"%s: Capability not supported",
325 				__func__);
326 		}
327 	}
328 
329 	return ret;
330 }
331 #endif
332 
333 static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
334 {
335 	if (taps == 8)
336 		return get_filter_8tap_64p(ratio);
337 	else if (taps == 7)
338 		return get_filter_7tap_64p(ratio);
339 	else if (taps == 6)
340 		return get_filter_6tap_64p(ratio);
341 	else if (taps == 5)
342 		return get_filter_5tap_64p(ratio);
343 	else if (taps == 4)
344 		return get_filter_4tap_64p(ratio);
345 	else if (taps == 3)
346 		return get_filter_3tap_64p(ratio);
347 	else if (taps == 2)
348 		return filter_2tap_64p;
349 	else if (taps == 1)
350 		return NULL;
351 	else {
352 		/* should never happen, bug */
353 		BREAK_TO_DEBUGGER();
354 		return NULL;
355 	}
356 }
357 
358 static void dpp_set_scl_filter(
359 		struct dcn10_dpp *xfm,
360 		const struct scaler_data *scl_data,
361 		bool chroma_coef_mode)
362 {
363 	bool h_2tap_hardcode_coef_en = false;
364 	bool v_2tap_hardcode_coef_en = false;
365 	bool h_2tap_sharp_en = false;
366 	bool v_2tap_sharp_en = false;
367 	uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz;
368 	uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert;
369 	bool coef_ram_current;
370 	const uint16_t *filter_h = NULL;
371 	const uint16_t *filter_v = NULL;
372 	const uint16_t *filter_h_c = NULL;
373 	const uint16_t *filter_v_c = NULL;
374 
375 	h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3
376 					&& scl_data->taps.h_taps_c < 3
377 		&& (scl_data->taps.h_taps > 1 || scl_data->taps.h_taps_c > 1);
378 	v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3
379 					&& scl_data->taps.v_taps_c < 3
380 		&& (scl_data->taps.v_taps > 1 || scl_data->taps.v_taps_c > 1);
381 
382 	h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0;
383 	v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0;
384 
385 	REG_UPDATE_6(DSCL_2TAP_CONTROL,
386 		SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en,
387 		SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en,
388 		SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor,
389 		SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en,
390 		SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en,
391 		SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor);
392 
393 	if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) {
394 		bool filter_updated = false;
395 
396 		filter_h = get_filter_coeffs_64p(
397 				scl_data->taps.h_taps, scl_data->ratios.horz);
398 		filter_v = get_filter_coeffs_64p(
399 				scl_data->taps.v_taps, scl_data->ratios.vert);
400 
401 		filter_updated = (filter_h && (filter_h != xfm->filter_h))
402 				|| (filter_v && (filter_v != xfm->filter_v));
403 
404 		if (chroma_coef_mode) {
405 			filter_h_c = get_filter_coeffs_64p(
406 					scl_data->taps.h_taps_c, scl_data->ratios.horz_c);
407 			filter_v_c = get_filter_coeffs_64p(
408 					scl_data->taps.v_taps_c, scl_data->ratios.vert_c);
409 			filter_updated = filter_updated || (filter_h_c && (filter_h_c != xfm->filter_h_c))
410 							|| (filter_v_c && (filter_v_c != xfm->filter_v_c));
411 		}
412 
413 		if (filter_updated) {
414 			uint32_t scl_mode = REG_READ(SCL_MODE);
415 
416 			if (!h_2tap_hardcode_coef_en && filter_h) {
417 				dpp_set_scaler_filter(
418 					xfm, scl_data->taps.h_taps,
419 					SCL_COEF_LUMA_HORZ_FILTER, filter_h);
420 			}
421 			xfm->filter_h = filter_h;
422 			if (!v_2tap_hardcode_coef_en && filter_v) {
423 				dpp_set_scaler_filter(
424 					xfm, scl_data->taps.v_taps,
425 					SCL_COEF_LUMA_VERT_FILTER, filter_v);
426 			}
427 			xfm->filter_v = filter_v;
428 			if (chroma_coef_mode) {
429 				if (!h_2tap_hardcode_coef_en && filter_h_c) {
430 					dpp_set_scaler_filter(
431 						xfm, scl_data->taps.h_taps_c,
432 						SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c);
433 				}
434 				if (!v_2tap_hardcode_coef_en && filter_v_c) {
435 					dpp_set_scaler_filter(
436 						xfm, scl_data->taps.v_taps_c,
437 						SCL_COEF_CHROMA_VERT_FILTER, filter_v_c);
438 				}
439 			}
440 			xfm->filter_h_c = filter_h_c;
441 			xfm->filter_v_c = filter_v_c;
442 
443 			coef_ram_current = get_reg_field_value_ex(
444 				scl_mode, xfm->tf_mask->SCL_COEF_RAM_SELECT_CURRENT,
445 				xfm->tf_shift->SCL_COEF_RAM_SELECT_CURRENT);
446 
447 			/* Swap coefficient RAM and set chroma coefficient mode */
448 			REG_SET_2(SCL_MODE, scl_mode,
449 					SCL_COEF_RAM_SELECT, !coef_ram_current,
450 					SCL_CHROMA_COEF_MODE, chroma_coef_mode);
451 		}
452 	}
453 }
454 
455 
456 static int get_lb_depth_bpc(enum lb_pixel_depth depth)
457 {
458 	if (depth == LB_PIXEL_DEPTH_30BPP)
459 		return 10;
460 	else if (depth == LB_PIXEL_DEPTH_24BPP)
461 		return 8;
462 	else if (depth == LB_PIXEL_DEPTH_18BPP)
463 		return 6;
464 	else if (depth == LB_PIXEL_DEPTH_36BPP)
465 		return 12;
466 	else {
467 		BREAK_TO_DEBUGGER();
468 		return -1; /* Unsupported */
469 	}
470 }
471 
472 static void calc_lb_num_partitions(
473 		const struct scaler_data *scl_data,
474 		enum lb_memory_config lb_config,
475 		int *num_part_y,
476 		int *num_part_c)
477 {
478 	int line_size = scl_data->viewport.width < scl_data->recout.width ?
479 			scl_data->viewport.width : scl_data->recout.width;
480 	int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ?
481 			scl_data->viewport_c.width : scl_data->recout.width;
482 	int lb_bpc = get_lb_depth_bpc(scl_data->lb_params.depth);
483 	int memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */
484 	int memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */
485 	int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */
486 	int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a;
487 
488 	if (lb_config == LB_MEMORY_CONFIG_1) {
489 		lb_memory_size = 816;
490 		lb_memory_size_c = 816;
491 		lb_memory_size_a = 984;
492 	} else if (lb_config == LB_MEMORY_CONFIG_2) {
493 		lb_memory_size = 1088;
494 		lb_memory_size_c = 1088;
495 		lb_memory_size_a = 1312;
496 	} else if (lb_config == LB_MEMORY_CONFIG_3) {
497 		lb_memory_size = 816 + 1088 + 848 + 848 + 848;
498 		lb_memory_size_c = 816 + 1088;
499 		lb_memory_size_a = 984 + 1312 + 456;
500 	} else {
501 		lb_memory_size = 816 + 1088 + 848;
502 		lb_memory_size_c = 816 + 1088 + 848;
503 		lb_memory_size_a = 984 + 1312 + 456;
504 	}
505 	*num_part_y = lb_memory_size / memory_line_size_y;
506 	*num_part_c = lb_memory_size_c / memory_line_size_c;
507 	num_partitions_a = lb_memory_size_a / memory_line_size_a;
508 
509 	if (scl_data->lb_params.alpha_en
510 			&& (num_partitions_a < *num_part_y))
511 		*num_part_y = num_partitions_a;
512 
513 	if (*num_part_y > 64)
514 		*num_part_y = 64;
515 	if (*num_part_c > 64)
516 		*num_part_c = 64;
517 
518 }
519 
520 static bool is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps)
521 {
522 	if (ceil_vratio > 2)
523 		return vtaps <= (num_partitions - ceil_vratio + 2);
524 	else
525 		return vtaps <= num_partitions;
526 }
527 
528 /*find first match configuration which meets the min required lb size*/
529 static enum lb_memory_config find_lb_memory_config(const struct scaler_data *scl_data)
530 {
531 	int num_part_y, num_part_c;
532 	int vtaps = scl_data->taps.v_taps;
533 	int vtaps_c = scl_data->taps.v_taps_c;
534 	int ceil_vratio = dal_fixed31_32_ceil(scl_data->ratios.vert);
535 	int ceil_vratio_c = dal_fixed31_32_ceil(scl_data->ratios.vert_c);
536 
537 	calc_lb_num_partitions(
538 			scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
539 
540 	if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
541 			&& is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
542 		return LB_MEMORY_CONFIG_1;
543 
544 	calc_lb_num_partitions(
545 			scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c);
546 
547 	if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
548 			&& is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
549 		return LB_MEMORY_CONFIG_2;
550 
551 	if (scl_data->format == PIXEL_FORMAT_420BPP8
552 			|| scl_data->format == PIXEL_FORMAT_420BPP10) {
553 		calc_lb_num_partitions(
554 				scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c);
555 
556 		if (is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
557 				&& is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
558 			return LB_MEMORY_CONFIG_3;
559 	}
560 
561 	calc_lb_num_partitions(
562 			scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c);
563 
564 	/*Ensure we can support the requested number of vtaps*/
565 	ASSERT(is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
566 			&& is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c));
567 
568 	return LB_MEMORY_CONFIG_0;
569 }
570 
571 void dpp_set_scaler_auto_scale(
572 	struct transform *xfm_base,
573 	const struct scaler_data *scl_data)
574 {
575 	enum lb_memory_config lb_config;
576 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
577 	enum dscl_mode_sel dscl_mode = get_dscl_mode(
578 			scl_data, xfm_base->ctx->dc->debug.always_scale);
579 	bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
580 				&& scl_data->format <= PIXEL_FORMAT_VIDEO_END;
581 
582 	dpp_set_overscan(xfm, scl_data);
583 
584 	dpp_set_otg_blank(xfm, scl_data);
585 
586 	REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
587 
588 	if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
589 		return;
590 
591 	lb_config =  find_lb_memory_config(scl_data);
592 	dpp_set_lb(xfm, &scl_data->lb_params, lb_config);
593 
594 	if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
595 		return;
596 
597 	/* TODO: v_min */
598 	REG_SET_3(DSCL_AUTOCAL, 0,
599 		AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE,
600 		AUTOCAL_NUM_PIPE, 0,
601 		AUTOCAL_PIPE_ID, 0);
602 
603 	/* Black offsets */
604 	if (ycbcr)
605 		REG_SET_2(SCL_BLACK_OFFSET, 0,
606 				SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
607 				SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
608 	else
609 
610 		REG_SET_2(SCL_BLACK_OFFSET, 0,
611 				SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
612 				SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
613 
614 	REG_SET_4(SCL_TAP_CONTROL, 0,
615 		SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
616 		SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
617 		SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
618 		SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
619 
620 	dpp_set_scl_filter(xfm, scl_data, ycbcr);
621 }
622 
623 /* Program gamut remap in bypass mode */
624 void dpp_set_gamut_remap_bypass(struct dcn10_dpp *xfm)
625 {
626 	REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
627 			CM_GAMUT_REMAP_MODE, 0);
628 	/* Gamut remap in bypass */
629 }
630 
631 static void dpp_set_recout(
632 			struct dcn10_dpp *xfm, const struct rect *recout)
633 {
634 	REG_SET_2(RECOUT_START, 0,
635 		/* First pixel of RECOUT */
636 			 RECOUT_START_X, recout->x,
637 		/* First line of RECOUT */
638 			 RECOUT_START_Y, recout->y);
639 
640 	REG_SET_2(RECOUT_SIZE, 0,
641 		/* Number of RECOUT horizontal pixels */
642 			 RECOUT_WIDTH, recout->width,
643 		/* Number of RECOUT vertical lines */
644 			 RECOUT_HEIGHT, recout->height
645 			 - xfm->base.ctx->dc->debug.surface_visual_confirm * 4 *
646 			 (xfm->base.inst + 1));
647 }
648 
649 static void dpp_set_manual_ratio_init(
650 		struct dcn10_dpp *xfm, const struct scaler_data *data)
651 {
652 	uint32_t init_frac = 0;
653 	uint32_t init_int = 0;
654 
655 	REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
656 			SCL_H_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.horz) << 5);
657 
658 	REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
659 			SCL_V_SCALE_RATIO, dal_fixed31_32_u2d19(data->ratios.vert) << 5);
660 
661 	REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0,
662 			SCL_H_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.horz_c) << 5);
663 
664 	REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0,
665 			SCL_V_SCALE_RATIO_C, dal_fixed31_32_u2d19(data->ratios.vert_c) << 5);
666 
667 	/*
668 	 * 0.24 format for fraction, first five bits zeroed
669 	 */
670 	init_frac = dal_fixed31_32_u0d19(data->inits.h) << 5;
671 	init_int = dal_fixed31_32_floor(data->inits.h);
672 	REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
673 		SCL_H_INIT_FRAC, init_frac,
674 		SCL_H_INIT_INT, init_int);
675 
676 	init_frac = dal_fixed31_32_u0d19(data->inits.h_c) << 5;
677 	init_int = dal_fixed31_32_floor(data->inits.h_c);
678 	REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0,
679 		SCL_H_INIT_FRAC_C, init_frac,
680 		SCL_H_INIT_INT_C, init_int);
681 
682 	init_frac = dal_fixed31_32_u0d19(data->inits.v) << 5;
683 	init_int = dal_fixed31_32_floor(data->inits.v);
684 	REG_SET_2(SCL_VERT_FILTER_INIT, 0,
685 		SCL_V_INIT_FRAC, init_frac,
686 		SCL_V_INIT_INT, init_int);
687 
688 	init_frac = dal_fixed31_32_u0d19(data->inits.v_bot) << 5;
689 	init_int = dal_fixed31_32_floor(data->inits.v_bot);
690 	REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
691 		SCL_V_INIT_FRAC_BOT, init_frac,
692 		SCL_V_INIT_INT_BOT, init_int);
693 
694 	init_frac = dal_fixed31_32_u0d19(data->inits.v_c) << 5;
695 	init_int = dal_fixed31_32_floor(data->inits.v_c);
696 	REG_SET_2(SCL_VERT_FILTER_INIT_C, 0,
697 		SCL_V_INIT_FRAC_C, init_frac,
698 		SCL_V_INIT_INT_C, init_int);
699 
700 	init_frac = dal_fixed31_32_u0d19(data->inits.v_c_bot) << 5;
701 	init_int = dal_fixed31_32_floor(data->inits.v_c_bot);
702 	REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
703 		SCL_V_INIT_FRAC_BOT_C, init_frac,
704 		SCL_V_INIT_INT_BOT_C, init_int);
705 }
706 
707 /* Main function to program scaler and line buffer in manual scaling mode */
708 static void dpp_set_scaler_manual_scale(
709 	struct transform *xfm_base,
710 	const struct scaler_data *scl_data)
711 {
712 	enum lb_memory_config lb_config;
713 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
714 	enum dscl_mode_sel dscl_mode = get_dscl_mode(
715 			scl_data, xfm_base->ctx->dc->debug.always_scale);
716 	bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
717 				&& scl_data->format <= PIXEL_FORMAT_VIDEO_END;
718 
719 	/* Recout */
720 	dpp_set_recout(xfm, &scl_data->recout);
721 
722 	/* MPC Size */
723 	REG_SET_2(MPC_SIZE, 0,
724 		/* Number of horizontal pixels of MPC */
725 			 MPC_WIDTH, scl_data->h_active,
726 		/* Number of vertical lines of MPC */
727 			 MPC_HEIGHT, scl_data->v_active);
728 
729 	/* SCL mode */
730 	REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
731 
732 	if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
733 		return;
734 	/* LB */
735 	lb_config =  find_lb_memory_config(scl_data);
736 	dpp_set_lb(xfm, &scl_data->lb_params, lb_config);
737 
738 	if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
739 		return;
740 
741 	/* Autocal off */
742 	REG_SET_3(DSCL_AUTOCAL, 0,
743 		AUTOCAL_MODE, AUTOCAL_MODE_OFF,
744 		AUTOCAL_NUM_PIPE, 0,
745 		AUTOCAL_PIPE_ID, 0);
746 
747 	/* Black offsets */
748 	if (ycbcr)
749 		REG_SET_2(SCL_BLACK_OFFSET, 0,
750 				SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
751 				SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
752 	else
753 
754 		REG_SET_2(SCL_BLACK_OFFSET, 0,
755 				SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
756 				SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
757 
758 	/* Manually calculate scale ratio and init values */
759 	dpp_set_manual_ratio_init(xfm, scl_data);
760 
761 	/* HTaps/VTaps */
762 	REG_SET_4(SCL_TAP_CONTROL, 0,
763 		SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
764 		SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
765 		SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
766 		SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
767 
768 	dpp_set_scl_filter(xfm, scl_data, ycbcr);
769 }
770 
771 #define IDENTITY_RATIO(ratio) (dal_fixed31_32_u2d19(ratio) == (1 << 19))
772 
773 
774 static bool dpp_get_optimal_number_of_taps(
775 		struct transform *xfm,
776 		struct scaler_data *scl_data,
777 		const struct scaling_taps *in_taps)
778 {
779 	uint32_t pixel_width;
780 
781 	if (scl_data->viewport.width > scl_data->recout.width)
782 		pixel_width = scl_data->recout.width;
783 	else
784 		pixel_width = scl_data->viewport.width;
785 
786 	/* TODO: add lb check */
787 
788 	/* No support for programming ratio of 4, drop to 3.99999.. */
789 	if (scl_data->ratios.horz.value == (4ll << 32))
790 		scl_data->ratios.horz.value--;
791 	if (scl_data->ratios.vert.value == (4ll << 32))
792 		scl_data->ratios.vert.value--;
793 	if (scl_data->ratios.horz_c.value == (4ll << 32))
794 		scl_data->ratios.horz_c.value--;
795 	if (scl_data->ratios.vert_c.value == (4ll << 32))
796 		scl_data->ratios.vert_c.value--;
797 
798 	/* Set default taps if none are provided */
799 	if (in_taps->h_taps == 0)
800 		scl_data->taps.h_taps = 4;
801 	else
802 		scl_data->taps.h_taps = in_taps->h_taps;
803 	if (in_taps->v_taps == 0)
804 		scl_data->taps.v_taps = 4;
805 	else
806 		scl_data->taps.v_taps = in_taps->v_taps;
807 	if (in_taps->v_taps_c == 0)
808 		scl_data->taps.v_taps_c = 2;
809 	else
810 		scl_data->taps.v_taps_c = in_taps->v_taps_c;
811 	if (in_taps->h_taps_c == 0)
812 		scl_data->taps.h_taps_c = 2;
813 	/* Only 1 and even h_taps_c are supported by hw */
814 	else if ((in_taps->h_taps_c % 2) != 0 && in_taps->h_taps_c != 1)
815 		scl_data->taps.h_taps_c = in_taps->h_taps_c - 1;
816 	else
817 		scl_data->taps.h_taps_c = in_taps->h_taps_c;
818 
819 	if (!xfm->ctx->dc->debug.always_scale) {
820 		if (IDENTITY_RATIO(scl_data->ratios.horz))
821 			scl_data->taps.h_taps = 1;
822 		if (IDENTITY_RATIO(scl_data->ratios.vert))
823 			scl_data->taps.v_taps = 1;
824 		if (IDENTITY_RATIO(scl_data->ratios.horz_c))
825 			scl_data->taps.h_taps_c = 1;
826 		if (IDENTITY_RATIO(scl_data->ratios.vert_c))
827 			scl_data->taps.v_taps_c = 1;
828 	}
829 
830 	return true;
831 }
832 
833 static void dpp_reset(struct transform *xfm_base)
834 {
835 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
836 
837 	xfm->filter_h_c = NULL;
838 	xfm->filter_v_c = NULL;
839 	xfm->filter_h = NULL;
840 	xfm->filter_v = NULL;
841 
842 	/* set boundary mode to 0 */
843 	REG_SET(DSCL_CONTROL, 0, SCL_BOUNDARY_MODE, 0);
844 }
845 
846 static void program_gamut_remap(
847 		struct dcn10_dpp *xfm,
848 		const uint16_t *regval,
849 		enum gamut_remap_select select)
850 {
851 	 uint16_t selection = 0;
852 
853 	if (regval == NULL || select == GAMUT_REMAP_BYPASS) {
854 		REG_SET(CM_GAMUT_REMAP_CONTROL, 0,
855 				CM_GAMUT_REMAP_MODE, 0);
856 		return;
857 	}
858 	switch (select) {
859 	case GAMUT_REMAP_COEFF:
860 		selection = 1;
861 		break;
862 	case GAMUT_REMAP_COMA_COEFF:
863 		selection = 2;
864 		break;
865 	case GAMUT_REMAP_COMB_COEFF:
866 		selection = 3;
867 		break;
868 	default:
869 		break;
870 	}
871 
872 
873 	if (select == GAMUT_REMAP_COEFF) {
874 
875 		REG_SET_2(CM_GAMUT_REMAP_C11_C12, 0,
876 				CM_GAMUT_REMAP_C11, regval[0],
877 				CM_GAMUT_REMAP_C12, regval[1]);
878 		regval += 2;
879 		REG_SET_2(CM_GAMUT_REMAP_C13_C14, 0,
880 				CM_GAMUT_REMAP_C13, regval[0],
881 				CM_GAMUT_REMAP_C14, regval[1]);
882 		regval += 2;
883 		REG_SET_2(CM_GAMUT_REMAP_C21_C22, 0,
884 				CM_GAMUT_REMAP_C21, regval[0],
885 				CM_GAMUT_REMAP_C22, regval[1]);
886 		regval += 2;
887 		REG_SET_2(CM_GAMUT_REMAP_C23_C24, 0,
888 				CM_GAMUT_REMAP_C23, regval[0],
889 				CM_GAMUT_REMAP_C24, regval[1]);
890 		regval += 2;
891 		REG_SET_2(CM_GAMUT_REMAP_C31_C32, 0,
892 				CM_GAMUT_REMAP_C31, regval[0],
893 				CM_GAMUT_REMAP_C32, regval[1]);
894 		regval += 2;
895 		REG_SET_2(CM_GAMUT_REMAP_C33_C34, 0,
896 				CM_GAMUT_REMAP_C33, regval[0],
897 				CM_GAMUT_REMAP_C34, regval[1]);
898 
899 	} else  if (select == GAMUT_REMAP_COMA_COEFF) {
900 		REG_SET_2(CM_COMA_C11_C12, 0,
901 				CM_COMA_C11, regval[0],
902 				CM_COMA_C12, regval[1]);
903 		regval += 2;
904 		REG_SET_2(CM_COMA_C13_C14, 0,
905 				CM_COMA_C13, regval[0],
906 				CM_COMA_C14, regval[1]);
907 		regval += 2;
908 		REG_SET_2(CM_COMA_C21_C22, 0,
909 				CM_COMA_C21, regval[0],
910 				CM_COMA_C22, regval[1]);
911 		regval += 2;
912 		REG_SET_2(CM_COMA_C23_C24, 0,
913 				CM_COMA_C23, regval[0],
914 				CM_COMA_C24, regval[1]);
915 		regval += 2;
916 		REG_SET_2(CM_COMA_C31_C32, 0,
917 				CM_COMA_C31, regval[0],
918 				CM_COMA_C32, regval[1]);
919 		regval += 2;
920 		REG_SET_2(CM_COMA_C33_C34, 0,
921 				CM_COMA_C33, regval[0],
922 				CM_COMA_C34, regval[1]);
923 
924 	} else {
925 		REG_SET_2(CM_COMB_C11_C12, 0,
926 				CM_COMB_C11, regval[0],
927 				CM_COMB_C12, regval[1]);
928 		regval += 2;
929 		REG_SET_2(CM_COMB_C13_C14, 0,
930 				CM_COMB_C13, regval[0],
931 				CM_COMB_C14, regval[1]);
932 		regval += 2;
933 		REG_SET_2(CM_COMB_C21_C22, 0,
934 				CM_COMB_C21, regval[0],
935 				CM_COMB_C22, regval[1]);
936 		regval += 2;
937 		REG_SET_2(CM_COMB_C23_C24, 0,
938 				CM_COMB_C23, regval[0],
939 				CM_COMB_C24, regval[1]);
940 		regval += 2;
941 		REG_SET_2(CM_COMB_C31_C32, 0,
942 				CM_COMB_C31, regval[0],
943 				CM_COMB_C32, regval[1]);
944 		regval += 2;
945 		REG_SET_2(CM_COMB_C33_C34, 0,
946 				CM_COMB_C33, regval[0],
947 				CM_COMB_C34, regval[1]);
948 	}
949 
950 	REG_SET(
951 			CM_GAMUT_REMAP_CONTROL, 0,
952 			CM_GAMUT_REMAP_MODE, selection);
953 
954 }
955 
956 static void dcn_dpp_set_gamut_remap(
957 	struct transform *xfm,
958 	const struct xfm_grph_csc_adjustment *adjust)
959 {
960 	struct dcn10_dpp *dcn_xfm = TO_DCN10_DPP(xfm);
961 
962 	if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
963 		/* Bypass if type is bypass or hw */
964 		program_gamut_remap(dcn_xfm, NULL, GAMUT_REMAP_BYPASS);
965 	else {
966 		struct fixed31_32 arr_matrix[12];
967 		uint16_t arr_reg_val[12];
968 
969 		arr_matrix[0] = adjust->temperature_matrix[0];
970 		arr_matrix[1] = adjust->temperature_matrix[1];
971 		arr_matrix[2] = adjust->temperature_matrix[2];
972 		arr_matrix[3] = dal_fixed31_32_zero;
973 
974 		arr_matrix[4] = adjust->temperature_matrix[3];
975 		arr_matrix[5] = adjust->temperature_matrix[4];
976 		arr_matrix[6] = adjust->temperature_matrix[5];
977 		arr_matrix[7] = dal_fixed31_32_zero;
978 
979 		arr_matrix[8] = adjust->temperature_matrix[6];
980 		arr_matrix[9] = adjust->temperature_matrix[7];
981 		arr_matrix[10] = adjust->temperature_matrix[8];
982 		arr_matrix[11] = dal_fixed31_32_zero;
983 
984 		convert_float_matrix(
985 			arr_reg_val, arr_matrix, 12);
986 
987 		program_gamut_remap(dcn_xfm, arr_reg_val, GAMUT_REMAP_COEFF);
988 	}
989 }
990 
991 static void oppn10_set_output_csc_default(
992 		struct transform *xfm_base,
993 		const struct default_adjustment *default_adjust)
994 {
995 
996 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
997 	uint32_t ocsc_mode = 0;
998 
999 	if (default_adjust != NULL) {
1000 		switch (default_adjust->out_color_space) {
1001 		case COLOR_SPACE_SRGB:
1002 		case COLOR_SPACE_2020_RGB_FULLRANGE:
1003 			ocsc_mode = 0;
1004 			break;
1005 		case COLOR_SPACE_SRGB_LIMITED:
1006 		case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
1007 			ocsc_mode = 1;
1008 			break;
1009 		case COLOR_SPACE_YCBCR601:
1010 		case COLOR_SPACE_YCBCR601_LIMITED:
1011 			ocsc_mode = 2;
1012 			break;
1013 		case COLOR_SPACE_YCBCR709:
1014 		case COLOR_SPACE_YCBCR709_LIMITED:
1015 		case COLOR_SPACE_2020_YCBCR:
1016 			ocsc_mode = 3;
1017 			break;
1018 		case COLOR_SPACE_UNKNOWN:
1019 		default:
1020 			break;
1021 		}
1022 	}
1023 
1024 	REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode);
1025 
1026 }
1027 
1028 static void oppn10_program_color_matrix(
1029 		struct dcn10_dpp *xfm,
1030 		const struct out_csc_color_matrix *tbl_entry)
1031 {
1032 	uint32_t mode;
1033 
1034 	REG_GET(CM_OCSC_CONTROL, CM_OCSC_MODE, &mode);
1035 
1036 	if (tbl_entry == NULL) {
1037 		BREAK_TO_DEBUGGER();
1038 		return;
1039 	}
1040 
1041 	if (mode == 4) {
1042 		/*R*/
1043 		REG_SET_2(CM_OCSC_C11_C12, 0,
1044 			CM_OCSC_C11, tbl_entry->regval[0],
1045 			CM_OCSC_C12, tbl_entry->regval[1]);
1046 
1047 		REG_SET_2(CM_OCSC_C13_C14, 0,
1048 			CM_OCSC_C13, tbl_entry->regval[2],
1049 			CM_OCSC_C14, tbl_entry->regval[3]);
1050 
1051 		/*G*/
1052 		REG_SET_2(CM_OCSC_C21_C22, 0,
1053 			CM_OCSC_C21, tbl_entry->regval[4],
1054 			CM_OCSC_C22, tbl_entry->regval[5]);
1055 
1056 		REG_SET_2(CM_OCSC_C23_C24, 0,
1057 			CM_OCSC_C23, tbl_entry->regval[6],
1058 			CM_OCSC_C24, tbl_entry->regval[7]);
1059 
1060 		/*B*/
1061 		REG_SET_2(CM_OCSC_C31_C32, 0,
1062 			CM_OCSC_C31, tbl_entry->regval[8],
1063 			CM_OCSC_C32, tbl_entry->regval[9]);
1064 
1065 		REG_SET_2(CM_OCSC_C33_C34, 0,
1066 			CM_OCSC_C33, tbl_entry->regval[10],
1067 			CM_OCSC_C34, tbl_entry->regval[11]);
1068 	} else {
1069 		/*R*/
1070 		REG_SET_2(CM_COMB_C11_C12, 0,
1071 			CM_COMB_C11, tbl_entry->regval[0],
1072 			CM_COMB_C12, tbl_entry->regval[1]);
1073 
1074 		REG_SET_2(CM_COMB_C13_C14, 0,
1075 			CM_COMB_C13, tbl_entry->regval[2],
1076 			CM_COMB_C14, tbl_entry->regval[3]);
1077 
1078 		/*G*/
1079 		REG_SET_2(CM_COMB_C21_C22, 0,
1080 			CM_COMB_C21, tbl_entry->regval[4],
1081 			CM_COMB_C22, tbl_entry->regval[5]);
1082 
1083 		REG_SET_2(CM_COMB_C23_C24, 0,
1084 			CM_COMB_C23, tbl_entry->regval[6],
1085 			CM_COMB_C24, tbl_entry->regval[7]);
1086 
1087 		/*B*/
1088 		REG_SET_2(CM_COMB_C31_C32, 0,
1089 			CM_COMB_C31, tbl_entry->regval[8],
1090 			CM_COMB_C32, tbl_entry->regval[9]);
1091 
1092 		REG_SET_2(CM_COMB_C33_C34, 0,
1093 			CM_COMB_C33, tbl_entry->regval[10],
1094 			CM_COMB_C34, tbl_entry->regval[11]);
1095 	}
1096 }
1097 
1098 static void oppn10_set_output_csc_adjustment(
1099 		struct transform *xfm_base,
1100 		const struct out_csc_color_matrix *tbl_entry)
1101 {
1102 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1103 	//enum csc_color_mode config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1104 	uint32_t ocsc_mode = 4;
1105 
1106 	/**
1107 	*if (tbl_entry != NULL) {
1108 	*	switch (tbl_entry->color_space) {
1109 	*	case COLOR_SPACE_SRGB:
1110 	*	case COLOR_SPACE_2020_RGB_FULLRANGE:
1111 	*		ocsc_mode = 0;
1112 	*		break;
1113 	*	case COLOR_SPACE_SRGB_LIMITED:
1114 	*	case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
1115 	*		ocsc_mode = 1;
1116 	*		break;
1117 	*	case COLOR_SPACE_YCBCR601:
1118 	*	case COLOR_SPACE_YCBCR601_LIMITED:
1119 	*		ocsc_mode = 2;
1120 	*		break;
1121 	*	case COLOR_SPACE_YCBCR709:
1122 	*	case COLOR_SPACE_YCBCR709_LIMITED:
1123 	*	case COLOR_SPACE_2020_YCBCR:
1124 	*		ocsc_mode = 3;
1125 	*		break;
1126 	*	case COLOR_SPACE_UNKNOWN:
1127 	*	default:
1128 	*		break;
1129 	*	}
1130 	*}
1131 	*/
1132 
1133 	REG_SET(CM_OCSC_CONTROL, 0, CM_OCSC_MODE, ocsc_mode);
1134 	oppn10_program_color_matrix(xfm, tbl_entry);
1135 }
1136 
1137 static void oppn10_power_on_regamma_lut(
1138 	struct transform *xfm_base,
1139 	bool power_on)
1140 {
1141 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1142 	REG_SET(CM_MEM_PWR_CTRL, 0,
1143 			RGAM_MEM_PWR_FORCE, power_on == true ? 0:1);
1144 
1145 }
1146 
1147 static void opp_program_regamma_lut(
1148 		struct transform *xfm_base,
1149 		const struct pwl_result_data *rgb,
1150 		uint32_t num)
1151 {
1152 	uint32_t i;
1153 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1154 	for (i = 0 ; i < num; i++) {
1155 		REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].red_reg);
1156 		REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].green_reg);
1157 		REG_SET(CM_RGAM_LUT_DATA, 0, CM_RGAM_LUT_DATA, rgb[i].blue_reg);
1158 
1159 		REG_SET(CM_RGAM_LUT_DATA, 0,
1160 				CM_RGAM_LUT_DATA, rgb[i].delta_red_reg);
1161 		REG_SET(CM_RGAM_LUT_DATA, 0,
1162 				CM_RGAM_LUT_DATA, rgb[i].delta_green_reg);
1163 		REG_SET(CM_RGAM_LUT_DATA, 0,
1164 				CM_RGAM_LUT_DATA, rgb[i].delta_blue_reg);
1165 
1166 	}
1167 
1168 }
1169 
1170 static void opp_configure_regamma_lut(
1171 		struct transform *xfm_base,
1172 		bool is_ram_a)
1173 {
1174 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1175 
1176 	REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK,
1177 			CM_RGAM_LUT_WRITE_EN_MASK, 7);
1178 	REG_UPDATE(CM_RGAM_LUT_WRITE_EN_MASK,
1179 			CM_RGAM_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
1180 	REG_SET(CM_RGAM_LUT_INDEX, 0, CM_RGAM_LUT_INDEX, 0);
1181 }
1182 
1183 /*program re gamma RAM A*/
1184 static void opp_program_regamma_luta_settings(
1185 		struct transform *xfm_base,
1186 		const struct pwl_params *params)
1187 {
1188 	const struct gamma_curve *curve;
1189 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1190 
1191 	REG_SET_2(CM_RGAM_RAMA_START_CNTL_B, 0,
1192 		CM_RGAM_RAMA_EXP_REGION_START_B, params->arr_points[0].custom_float_x,
1193 		CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_B, 0);
1194 	REG_SET_2(CM_RGAM_RAMA_START_CNTL_G, 0,
1195 		CM_RGAM_RAMA_EXP_REGION_START_G, params->arr_points[0].custom_float_x,
1196 		CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_G, 0);
1197 	REG_SET_2(CM_RGAM_RAMA_START_CNTL_R, 0,
1198 		CM_RGAM_RAMA_EXP_REGION_START_R, params->arr_points[0].custom_float_x,
1199 		CM_RGAM_RAMA_EXP_REGION_START_SEGMENT_R, 0);
1200 
1201 	REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_B, 0,
1202 		CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope);
1203 	REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_G, 0,
1204 		CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope);
1205 	REG_SET(CM_RGAM_RAMA_SLOPE_CNTL_R, 0,
1206 		CM_RGAM_RAMA_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope);
1207 
1208 	REG_SET(CM_RGAM_RAMA_END_CNTL1_B, 0,
1209 		CM_RGAM_RAMA_EXP_REGION_END_B, params->arr_points[1].custom_float_x);
1210 	REG_SET_2(CM_RGAM_RAMA_END_CNTL2_B, 0,
1211 		CM_RGAM_RAMA_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope,
1212 		CM_RGAM_RAMA_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y);
1213 
1214 	REG_SET(CM_RGAM_RAMA_END_CNTL1_G, 0,
1215 		CM_RGAM_RAMA_EXP_REGION_END_G, params->arr_points[1].custom_float_x);
1216 	REG_SET_2(CM_RGAM_RAMA_END_CNTL2_G, 0,
1217 		CM_RGAM_RAMA_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope,
1218 		CM_RGAM_RAMA_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y);
1219 
1220 	REG_SET(CM_RGAM_RAMA_END_CNTL1_R, 0,
1221 		CM_RGAM_RAMA_EXP_REGION_END_R, params->arr_points[1].custom_float_x);
1222 	REG_SET_2(CM_RGAM_RAMA_END_CNTL2_R, 0,
1223 		CM_RGAM_RAMA_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope,
1224 		CM_RGAM_RAMA_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y);
1225 
1226 	curve = params->arr_curve_points;
1227 	REG_SET_4(CM_RGAM_RAMA_REGION_0_1, 0,
1228 		CM_RGAM_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1229 		CM_RGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1230 		CM_RGAM_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1231 		CM_RGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1232 
1233 	curve += 2;
1234 	REG_SET_4(CM_RGAM_RAMA_REGION_2_3, 0,
1235 		CM_RGAM_RAMA_EXP_REGION2_LUT_OFFSET, curve[0].offset,
1236 		CM_RGAM_RAMA_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
1237 		CM_RGAM_RAMA_EXP_REGION3_LUT_OFFSET, curve[1].offset,
1238 		CM_RGAM_RAMA_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
1239 
1240 	curve += 2;
1241 	REG_SET_4(CM_RGAM_RAMA_REGION_4_5, 0,
1242 		CM_RGAM_RAMA_EXP_REGION4_LUT_OFFSET, curve[0].offset,
1243 		CM_RGAM_RAMA_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
1244 		CM_RGAM_RAMA_EXP_REGION5_LUT_OFFSET, curve[1].offset,
1245 		CM_RGAM_RAMA_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
1246 
1247 	curve += 2;
1248 	REG_SET_4(CM_RGAM_RAMA_REGION_6_7, 0,
1249 		CM_RGAM_RAMA_EXP_REGION6_LUT_OFFSET, curve[0].offset,
1250 		CM_RGAM_RAMA_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
1251 		CM_RGAM_RAMA_EXP_REGION7_LUT_OFFSET, curve[1].offset,
1252 		CM_RGAM_RAMA_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
1253 
1254 	curve += 2;
1255 	REG_SET_4(CM_RGAM_RAMA_REGION_8_9, 0,
1256 		CM_RGAM_RAMA_EXP_REGION8_LUT_OFFSET, curve[0].offset,
1257 		CM_RGAM_RAMA_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
1258 		CM_RGAM_RAMA_EXP_REGION9_LUT_OFFSET, curve[1].offset,
1259 		CM_RGAM_RAMA_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
1260 
1261 	curve += 2;
1262 	REG_SET_4(CM_RGAM_RAMA_REGION_10_11, 0,
1263 		CM_RGAM_RAMA_EXP_REGION10_LUT_OFFSET, curve[0].offset,
1264 		CM_RGAM_RAMA_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
1265 		CM_RGAM_RAMA_EXP_REGION11_LUT_OFFSET, curve[1].offset,
1266 		CM_RGAM_RAMA_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
1267 
1268 	curve += 2;
1269 	REG_SET_4(CM_RGAM_RAMA_REGION_12_13, 0,
1270 		CM_RGAM_RAMA_EXP_REGION12_LUT_OFFSET, curve[0].offset,
1271 		CM_RGAM_RAMA_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
1272 		CM_RGAM_RAMA_EXP_REGION13_LUT_OFFSET, curve[1].offset,
1273 		CM_RGAM_RAMA_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
1274 
1275 	curve += 2;
1276 	REG_SET_4(CM_RGAM_RAMA_REGION_14_15, 0,
1277 		CM_RGAM_RAMA_EXP_REGION14_LUT_OFFSET, curve[0].offset,
1278 		CM_RGAM_RAMA_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
1279 		CM_RGAM_RAMA_EXP_REGION15_LUT_OFFSET, curve[1].offset,
1280 		CM_RGAM_RAMA_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
1281 
1282 	curve += 2;
1283 	REG_SET_4(CM_RGAM_RAMA_REGION_16_17, 0,
1284 		CM_RGAM_RAMA_EXP_REGION16_LUT_OFFSET, curve[0].offset,
1285 		CM_RGAM_RAMA_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
1286 		CM_RGAM_RAMA_EXP_REGION17_LUT_OFFSET, curve[1].offset,
1287 		CM_RGAM_RAMA_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
1288 
1289 	curve += 2;
1290 	REG_SET_4(CM_RGAM_RAMA_REGION_18_19, 0,
1291 		CM_RGAM_RAMA_EXP_REGION18_LUT_OFFSET, curve[0].offset,
1292 		CM_RGAM_RAMA_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
1293 		CM_RGAM_RAMA_EXP_REGION19_LUT_OFFSET, curve[1].offset,
1294 		CM_RGAM_RAMA_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
1295 
1296 	curve += 2;
1297 	REG_SET_4(CM_RGAM_RAMA_REGION_20_21, 0,
1298 		CM_RGAM_RAMA_EXP_REGION20_LUT_OFFSET, curve[0].offset,
1299 		CM_RGAM_RAMA_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
1300 		CM_RGAM_RAMA_EXP_REGION21_LUT_OFFSET, curve[1].offset,
1301 		CM_RGAM_RAMA_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
1302 
1303 	curve += 2;
1304 	REG_SET_4(CM_RGAM_RAMA_REGION_22_23, 0,
1305 		CM_RGAM_RAMA_EXP_REGION22_LUT_OFFSET, curve[0].offset,
1306 		CM_RGAM_RAMA_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
1307 		CM_RGAM_RAMA_EXP_REGION23_LUT_OFFSET, curve[1].offset,
1308 		CM_RGAM_RAMA_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
1309 
1310 	curve += 2;
1311 	REG_SET_4(CM_RGAM_RAMA_REGION_24_25, 0,
1312 		CM_RGAM_RAMA_EXP_REGION24_LUT_OFFSET, curve[0].offset,
1313 		CM_RGAM_RAMA_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
1314 		CM_RGAM_RAMA_EXP_REGION25_LUT_OFFSET, curve[1].offset,
1315 		CM_RGAM_RAMA_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
1316 
1317 	curve += 2;
1318 	REG_SET_4(CM_RGAM_RAMA_REGION_26_27, 0,
1319 		CM_RGAM_RAMA_EXP_REGION26_LUT_OFFSET, curve[0].offset,
1320 		CM_RGAM_RAMA_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
1321 		CM_RGAM_RAMA_EXP_REGION27_LUT_OFFSET, curve[1].offset,
1322 		CM_RGAM_RAMA_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
1323 
1324 	curve += 2;
1325 	REG_SET_4(CM_RGAM_RAMA_REGION_28_29, 0,
1326 		CM_RGAM_RAMA_EXP_REGION28_LUT_OFFSET, curve[0].offset,
1327 		CM_RGAM_RAMA_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
1328 		CM_RGAM_RAMA_EXP_REGION29_LUT_OFFSET, curve[1].offset,
1329 		CM_RGAM_RAMA_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
1330 
1331 	curve += 2;
1332 	REG_SET_4(CM_RGAM_RAMA_REGION_30_31, 0,
1333 		CM_RGAM_RAMA_EXP_REGION30_LUT_OFFSET, curve[0].offset,
1334 		CM_RGAM_RAMA_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
1335 		CM_RGAM_RAMA_EXP_REGION31_LUT_OFFSET, curve[1].offset,
1336 		CM_RGAM_RAMA_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
1337 
1338 	curve += 2;
1339 	REG_SET_4(CM_RGAM_RAMA_REGION_32_33, 0,
1340 		CM_RGAM_RAMA_EXP_REGION32_LUT_OFFSET, curve[0].offset,
1341 		CM_RGAM_RAMA_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
1342 		CM_RGAM_RAMA_EXP_REGION33_LUT_OFFSET, curve[1].offset,
1343 		CM_RGAM_RAMA_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
1344 }
1345 
1346 /*program re gamma RAM B*/
1347 static void opp_program_regamma_lutb_settings(
1348 		struct transform *xfm_base,
1349 		const struct pwl_params *params)
1350 {
1351 	const struct gamma_curve *curve;
1352 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1353 
1354 	REG_SET_2(CM_RGAM_RAMB_START_CNTL_B, 0,
1355 		CM_RGAM_RAMB_EXP_REGION_START_B, params->arr_points[0].custom_float_x,
1356 		CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_B, 0);
1357 	REG_SET_2(CM_RGAM_RAMB_START_CNTL_G, 0,
1358 		CM_RGAM_RAMB_EXP_REGION_START_G, params->arr_points[0].custom_float_x,
1359 		CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_G, 0);
1360 	REG_SET_2(CM_RGAM_RAMB_START_CNTL_R, 0,
1361 		CM_RGAM_RAMB_EXP_REGION_START_R, params->arr_points[0].custom_float_x,
1362 		CM_RGAM_RAMB_EXP_REGION_START_SEGMENT_R, 0);
1363 
1364 	REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_B, 0,
1365 		CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_B, params->arr_points[0].custom_float_slope);
1366 	REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_G, 0,
1367 		CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_G, params->arr_points[0].custom_float_slope);
1368 	REG_SET(CM_RGAM_RAMB_SLOPE_CNTL_R, 0,
1369 		CM_RGAM_RAMB_EXP_REGION_LINEAR_SLOPE_R, params->arr_points[0].custom_float_slope);
1370 
1371 	REG_SET(CM_RGAM_RAMB_END_CNTL1_B, 0,
1372 		CM_RGAM_RAMB_EXP_REGION_END_B, params->arr_points[1].custom_float_x);
1373 	REG_SET_2(CM_RGAM_RAMB_END_CNTL2_B, 0,
1374 		CM_RGAM_RAMB_EXP_REGION_END_SLOPE_B, params->arr_points[1].custom_float_slope,
1375 		CM_RGAM_RAMB_EXP_REGION_END_BASE_B, params->arr_points[1].custom_float_y);
1376 
1377 	REG_SET(CM_RGAM_RAMB_END_CNTL1_G, 0,
1378 		CM_RGAM_RAMB_EXP_REGION_END_G, params->arr_points[1].custom_float_x);
1379 	REG_SET_2(CM_RGAM_RAMB_END_CNTL2_G, 0,
1380 		CM_RGAM_RAMB_EXP_REGION_END_SLOPE_G, params->arr_points[1].custom_float_slope,
1381 		CM_RGAM_RAMB_EXP_REGION_END_BASE_G, params->arr_points[1].custom_float_y);
1382 
1383 	REG_SET(CM_RGAM_RAMB_END_CNTL1_R, 0,
1384 		CM_RGAM_RAMB_EXP_REGION_END_R, params->arr_points[1].custom_float_x);
1385 	REG_SET_2(CM_RGAM_RAMB_END_CNTL2_R, 0,
1386 		CM_RGAM_RAMB_EXP_REGION_END_SLOPE_R, params->arr_points[1].custom_float_slope,
1387 		CM_RGAM_RAMB_EXP_REGION_END_BASE_R, params->arr_points[1].custom_float_y);
1388 
1389 	curve = params->arr_curve_points;
1390 	REG_SET_4(CM_RGAM_RAMB_REGION_0_1, 0,
1391 		CM_RGAM_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1392 		CM_RGAM_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1393 		CM_RGAM_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1394 		CM_RGAM_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1395 
1396 	curve += 2;
1397 	REG_SET_4(CM_RGAM_RAMB_REGION_2_3, 0,
1398 		CM_RGAM_RAMB_EXP_REGION2_LUT_OFFSET, curve[0].offset,
1399 		CM_RGAM_RAMB_EXP_REGION2_NUM_SEGMENTS, curve[0].segments_num,
1400 		CM_RGAM_RAMB_EXP_REGION3_LUT_OFFSET, curve[1].offset,
1401 		CM_RGAM_RAMB_EXP_REGION3_NUM_SEGMENTS, curve[1].segments_num);
1402 
1403 	curve += 2;
1404 	REG_SET_4(CM_RGAM_RAMB_REGION_4_5, 0,
1405 		CM_RGAM_RAMB_EXP_REGION4_LUT_OFFSET, curve[0].offset,
1406 		CM_RGAM_RAMB_EXP_REGION4_NUM_SEGMENTS, curve[0].segments_num,
1407 		CM_RGAM_RAMB_EXP_REGION5_LUT_OFFSET, curve[1].offset,
1408 		CM_RGAM_RAMB_EXP_REGION5_NUM_SEGMENTS, curve[1].segments_num);
1409 
1410 	curve += 2;
1411 	REG_SET_4(CM_RGAM_RAMB_REGION_6_7, 0,
1412 		CM_RGAM_RAMB_EXP_REGION6_LUT_OFFSET, curve[0].offset,
1413 		CM_RGAM_RAMB_EXP_REGION6_NUM_SEGMENTS, curve[0].segments_num,
1414 		CM_RGAM_RAMB_EXP_REGION7_LUT_OFFSET, curve[1].offset,
1415 		CM_RGAM_RAMB_EXP_REGION7_NUM_SEGMENTS, curve[1].segments_num);
1416 
1417 	curve += 2;
1418 	REG_SET_4(CM_RGAM_RAMB_REGION_8_9, 0,
1419 		CM_RGAM_RAMB_EXP_REGION8_LUT_OFFSET, curve[0].offset,
1420 		CM_RGAM_RAMB_EXP_REGION8_NUM_SEGMENTS, curve[0].segments_num,
1421 		CM_RGAM_RAMB_EXP_REGION9_LUT_OFFSET, curve[1].offset,
1422 		CM_RGAM_RAMB_EXP_REGION9_NUM_SEGMENTS, curve[1].segments_num);
1423 
1424 	curve += 2;
1425 	REG_SET_4(CM_RGAM_RAMB_REGION_10_11, 0,
1426 		CM_RGAM_RAMB_EXP_REGION10_LUT_OFFSET, curve[0].offset,
1427 		CM_RGAM_RAMB_EXP_REGION10_NUM_SEGMENTS, curve[0].segments_num,
1428 		CM_RGAM_RAMB_EXP_REGION11_LUT_OFFSET, curve[1].offset,
1429 		CM_RGAM_RAMB_EXP_REGION11_NUM_SEGMENTS, curve[1].segments_num);
1430 
1431 	curve += 2;
1432 	REG_SET_4(CM_RGAM_RAMB_REGION_12_13, 0,
1433 		CM_RGAM_RAMB_EXP_REGION12_LUT_OFFSET, curve[0].offset,
1434 		CM_RGAM_RAMB_EXP_REGION12_NUM_SEGMENTS, curve[0].segments_num,
1435 		CM_RGAM_RAMB_EXP_REGION13_LUT_OFFSET, curve[1].offset,
1436 		CM_RGAM_RAMB_EXP_REGION13_NUM_SEGMENTS, curve[1].segments_num);
1437 
1438 	curve += 2;
1439 	REG_SET_4(CM_RGAM_RAMB_REGION_14_15, 0,
1440 		CM_RGAM_RAMB_EXP_REGION14_LUT_OFFSET, curve[0].offset,
1441 		CM_RGAM_RAMB_EXP_REGION14_NUM_SEGMENTS, curve[0].segments_num,
1442 		CM_RGAM_RAMB_EXP_REGION15_LUT_OFFSET, curve[1].offset,
1443 		CM_RGAM_RAMB_EXP_REGION15_NUM_SEGMENTS, curve[1].segments_num);
1444 
1445 	curve += 2;
1446 	REG_SET_4(CM_RGAM_RAMB_REGION_16_17, 0,
1447 		CM_RGAM_RAMB_EXP_REGION16_LUT_OFFSET, curve[0].offset,
1448 		CM_RGAM_RAMB_EXP_REGION16_NUM_SEGMENTS, curve[0].segments_num,
1449 		CM_RGAM_RAMB_EXP_REGION17_LUT_OFFSET, curve[1].offset,
1450 		CM_RGAM_RAMB_EXP_REGION17_NUM_SEGMENTS, curve[1].segments_num);
1451 
1452 	curve += 2;
1453 	REG_SET_4(CM_RGAM_RAMB_REGION_18_19, 0,
1454 		CM_RGAM_RAMB_EXP_REGION18_LUT_OFFSET, curve[0].offset,
1455 		CM_RGAM_RAMB_EXP_REGION18_NUM_SEGMENTS, curve[0].segments_num,
1456 		CM_RGAM_RAMB_EXP_REGION19_LUT_OFFSET, curve[1].offset,
1457 		CM_RGAM_RAMB_EXP_REGION19_NUM_SEGMENTS, curve[1].segments_num);
1458 
1459 	curve += 2;
1460 	REG_SET_4(CM_RGAM_RAMB_REGION_20_21, 0,
1461 		CM_RGAM_RAMB_EXP_REGION20_LUT_OFFSET, curve[0].offset,
1462 		CM_RGAM_RAMB_EXP_REGION20_NUM_SEGMENTS, curve[0].segments_num,
1463 		CM_RGAM_RAMB_EXP_REGION21_LUT_OFFSET, curve[1].offset,
1464 		CM_RGAM_RAMB_EXP_REGION21_NUM_SEGMENTS, curve[1].segments_num);
1465 
1466 	curve += 2;
1467 	REG_SET_4(CM_RGAM_RAMB_REGION_22_23, 0,
1468 		CM_RGAM_RAMB_EXP_REGION22_LUT_OFFSET, curve[0].offset,
1469 		CM_RGAM_RAMB_EXP_REGION22_NUM_SEGMENTS, curve[0].segments_num,
1470 		CM_RGAM_RAMB_EXP_REGION23_LUT_OFFSET, curve[1].offset,
1471 		CM_RGAM_RAMB_EXP_REGION23_NUM_SEGMENTS, curve[1].segments_num);
1472 
1473 	curve += 2;
1474 	REG_SET_4(CM_RGAM_RAMB_REGION_24_25, 0,
1475 		CM_RGAM_RAMB_EXP_REGION24_LUT_OFFSET, curve[0].offset,
1476 		CM_RGAM_RAMB_EXP_REGION24_NUM_SEGMENTS, curve[0].segments_num,
1477 		CM_RGAM_RAMB_EXP_REGION25_LUT_OFFSET, curve[1].offset,
1478 		CM_RGAM_RAMB_EXP_REGION25_NUM_SEGMENTS, curve[1].segments_num);
1479 
1480 	curve += 2;
1481 	REG_SET_4(CM_RGAM_RAMB_REGION_26_27, 0,
1482 		CM_RGAM_RAMB_EXP_REGION26_LUT_OFFSET, curve[0].offset,
1483 		CM_RGAM_RAMB_EXP_REGION26_NUM_SEGMENTS, curve[0].segments_num,
1484 		CM_RGAM_RAMB_EXP_REGION27_LUT_OFFSET, curve[1].offset,
1485 		CM_RGAM_RAMB_EXP_REGION27_NUM_SEGMENTS, curve[1].segments_num);
1486 
1487 	curve += 2;
1488 	REG_SET_4(CM_RGAM_RAMB_REGION_28_29, 0,
1489 		CM_RGAM_RAMB_EXP_REGION28_LUT_OFFSET, curve[0].offset,
1490 		CM_RGAM_RAMB_EXP_REGION28_NUM_SEGMENTS, curve[0].segments_num,
1491 		CM_RGAM_RAMB_EXP_REGION29_LUT_OFFSET, curve[1].offset,
1492 		CM_RGAM_RAMB_EXP_REGION29_NUM_SEGMENTS, curve[1].segments_num);
1493 
1494 	curve += 2;
1495 	REG_SET_4(CM_RGAM_RAMB_REGION_30_31, 0,
1496 		CM_RGAM_RAMB_EXP_REGION30_LUT_OFFSET, curve[0].offset,
1497 		CM_RGAM_RAMB_EXP_REGION30_NUM_SEGMENTS, curve[0].segments_num,
1498 		CM_RGAM_RAMB_EXP_REGION31_LUT_OFFSET, curve[1].offset,
1499 		CM_RGAM_RAMB_EXP_REGION31_NUM_SEGMENTS, curve[1].segments_num);
1500 
1501 	curve += 2;
1502 	REG_SET_4(CM_RGAM_RAMB_REGION_32_33, 0,
1503 		CM_RGAM_RAMB_EXP_REGION32_LUT_OFFSET, curve[0].offset,
1504 		CM_RGAM_RAMB_EXP_REGION32_NUM_SEGMENTS, curve[0].segments_num,
1505 		CM_RGAM_RAMB_EXP_REGION33_LUT_OFFSET, curve[1].offset,
1506 		CM_RGAM_RAMB_EXP_REGION33_NUM_SEGMENTS, curve[1].segments_num);
1507 
1508 }
1509 
1510 static bool oppn10_set_regamma_pwl(
1511 	struct transform *xfm_base, const struct pwl_params *params)
1512 {
1513 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1514 
1515 	oppn10_power_on_regamma_lut(xfm_base, true);
1516 	opp_configure_regamma_lut(xfm_base, xfm->is_write_to_ram_a_safe);
1517 
1518 	if (xfm->is_write_to_ram_a_safe)
1519 		opp_program_regamma_luta_settings(xfm_base, params);
1520 	else
1521 		opp_program_regamma_lutb_settings(xfm_base, params);
1522 
1523 	opp_program_regamma_lut(
1524 			xfm_base, params->rgb_resulted, params->hw_points_num);
1525 
1526 	return true;
1527 }
1528 
1529 static void oppn10_set_regamma_mode(
1530 	struct transform *xfm_base,
1531 	enum opp_regamma mode)
1532 {
1533 	struct dcn10_dpp *xfm = TO_DCN10_DPP(xfm_base);
1534 	uint32_t re_mode = 0;
1535 	uint32_t obuf_bypass = 0; /* need for pipe split */
1536 	uint32_t obuf_hupscale = 0;
1537 
1538 	switch (mode) {
1539 	case OPP_REGAMMA_BYPASS:
1540 		re_mode = 0;
1541 		break;
1542 	case OPP_REGAMMA_SRGB:
1543 		re_mode = 1;
1544 		break;
1545 	case OPP_REGAMMA_3_6:
1546 		re_mode = 2;
1547 		break;
1548 	case OPP_REGAMMA_USER:
1549 		re_mode = xfm->is_write_to_ram_a_safe ? 3 : 4;
1550 		xfm->is_write_to_ram_a_safe = !xfm->is_write_to_ram_a_safe;
1551 		break;
1552 	default:
1553 		break;
1554 	}
1555 
1556 	REG_SET(CM_RGAM_CONTROL, 0, CM_RGAM_LUT_MODE, re_mode);
1557 	REG_UPDATE_2(OBUF_CONTROL,
1558 			OBUF_BYPASS, obuf_bypass,
1559 			OBUF_H_2X_UPSCALE_EN, obuf_hupscale);
1560 }
1561 
1562 static struct transform_funcs dcn10_dpp_funcs = {
1563 		.transform_reset = dpp_reset,
1564 		.transform_set_scaler = dpp_set_scaler_manual_scale,
1565 		.transform_get_optimal_number_of_taps = dpp_get_optimal_number_of_taps,
1566 		.transform_set_gamut_remap = dcn_dpp_set_gamut_remap,
1567 		.opp_set_csc_adjustment = oppn10_set_output_csc_adjustment,
1568 		.opp_set_csc_default = oppn10_set_output_csc_default,
1569 		.opp_power_on_regamma_lut = oppn10_power_on_regamma_lut,
1570 		.opp_program_regamma_lut = opp_program_regamma_lut,
1571 		.opp_configure_regamma_lut = opp_configure_regamma_lut,
1572 		.opp_program_regamma_lutb_settings = opp_program_regamma_lutb_settings,
1573 		.opp_program_regamma_luta_settings = opp_program_regamma_luta_settings,
1574 		.opp_program_regamma_pwl = oppn10_set_regamma_pwl,
1575 		.opp_set_regamma_mode = oppn10_set_regamma_mode,
1576 };
1577 
1578 /*****************************************/
1579 /* Constructor, Destructor               */
1580 /*****************************************/
1581 
1582 bool dcn10_dpp_construct(
1583 	struct dcn10_dpp *xfm,
1584 	struct dc_context *ctx,
1585 	uint32_t inst,
1586 	const struct dcn_dpp_registers *tf_regs,
1587 	const struct dcn_dpp_shift *tf_shift,
1588 	const struct dcn_dpp_mask *tf_mask)
1589 {
1590 	xfm->base.ctx = ctx;
1591 
1592 	xfm->base.inst = inst;
1593 	xfm->base.funcs = &dcn10_dpp_funcs;
1594 
1595 	xfm->tf_regs = tf_regs;
1596 	xfm->tf_shift = tf_shift;
1597 	xfm->tf_mask = tf_mask;
1598 
1599 	xfm->lb_pixel_depth_supported =
1600 		LB_PIXEL_DEPTH_18BPP |
1601 		LB_PIXEL_DEPTH_24BPP |
1602 		LB_PIXEL_DEPTH_30BPP;
1603 
1604 	xfm->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1605 	xfm->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x1404*/
1606 
1607 	return true;
1608 }
1609