1 /*
2  * Copyright 2012-15 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 #include "dce110_transform_v.h"
28 #include "basics/conversion.h"
29 
30 /* include DCE11 register header files */
31 #include "dce/dce_11_0_d.h"
32 #include "dce/dce_11_0_sh_mask.h"
33 #include "dce/dce_11_0_enum.h"
34 
35 enum {
36 	OUTPUT_CSC_MATRIX_SIZE = 12
37 };
38 
39 /* constrast:0 - 2.0, default 1.0 */
40 #define UNDERLAY_CONTRAST_DEFAULT 100
41 #define UNDERLAY_CONTRAST_MAX     200
42 #define UNDERLAY_CONTRAST_MIN       0
43 #define UNDERLAY_CONTRAST_STEP      1
44 #define UNDERLAY_CONTRAST_DIVIDER 100
45 
46 /* Saturation: 0 - 2.0; default 1.0 */
47 #define UNDERLAY_SATURATION_DEFAULT   100 /*1.00*/
48 #define UNDERLAY_SATURATION_MIN         0
49 #define UNDERLAY_SATURATION_MAX       200 /* 2.00 */
50 #define UNDERLAY_SATURATION_STEP        1 /* 0.01 */
51 /*actual max overlay saturation
52  * value = UNDERLAY_SATURATION_MAX /UNDERLAY_SATURATION_DIVIDER
53  */
54 
55 /* Hue */
56 #define  UNDERLAY_HUE_DEFAULT      0
57 #define  UNDERLAY_HUE_MIN       -300
58 #define  UNDERLAY_HUE_MAX        300
59 #define  UNDERLAY_HUE_STEP         5
60 #define  UNDERLAY_HUE_DIVIDER   10 /* HW range: -30 ~ +30 */
61 #define UNDERLAY_SATURATION_DIVIDER   100
62 
63 /* Brightness: in DAL usually -.25 ~ .25.
64  * In MMD is -100 to +100 in 16-235 range; which when scaled to full range is
65  *  ~-116 to +116. When normalized this is about 0.4566.
66  * With 100 divider this becomes 46, but we may use another for better precision
67  * The ideal one is 100/219 ((100/255)*(255/219)),
68  * i.e. min/max = +-100, divider = 219
69  * default 0.0
70  */
71 #define  UNDERLAY_BRIGHTNESS_DEFAULT    0
72 #define  UNDERLAY_BRIGHTNESS_MIN      -46 /* ~116/255 */
73 #define  UNDERLAY_BRIGHTNESS_MAX       46
74 #define  UNDERLAY_BRIGHTNESS_STEP       1 /*  .01 */
75 #define  UNDERLAY_BRIGHTNESS_DIVIDER  100
76 
77 static const struct out_csc_color_matrix global_color_matrix[] = {
78 { COLOR_SPACE_SRGB,
79 	{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
80 { COLOR_SPACE_SRGB_LIMITED,
81 	{ 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
82 { COLOR_SPACE_YCBCR601,
83 	{ 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
84 		0xF6B9, 0xE00, 0x1000} },
85 { COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
86 	0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
87 /* TODO: correct values below */
88 { COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
89 	0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
90 { COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
91 	0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
92 };
93 
94 enum csc_color_mode {
95 	/* 00 - BITS2:0 Bypass */
96 	CSC_COLOR_MODE_GRAPHICS_BYPASS,
97 	/* 01 - hard coded coefficient TV RGB */
98 	CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
99 	/* 04 - programmable OUTPUT CSC coefficient */
100 	CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
101 };
102 
103 enum grph_color_adjust_option {
104 	GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
105 	GRPH_COLOR_MATRIX_SW
106 };
107 
program_color_matrix_v(struct dce_transform * xfm_dce,const struct out_csc_color_matrix * tbl_entry,enum grph_color_adjust_option options)108 static void program_color_matrix_v(
109 	struct dce_transform *xfm_dce,
110 	const struct out_csc_color_matrix *tbl_entry,
111 	enum grph_color_adjust_option options)
112 {
113 	struct dc_context *ctx = xfm_dce->base.ctx;
114 	uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL);
115 	bool use_set_a = (get_reg_field_value(cntl_value,
116 			COL_MAN_OUTPUT_CSC_CONTROL,
117 			OUTPUT_CSC_MODE) != 4);
118 
119 	set_reg_field_value(
120 			cntl_value,
121 		0,
122 		COL_MAN_OUTPUT_CSC_CONTROL,
123 		OUTPUT_CSC_MODE);
124 
125 	if (use_set_a) {
126 		{
127 			uint32_t value = 0;
128 			uint32_t addr = mmOUTPUT_CSC_C11_C12_A;
129 			/* fixed S2.13 format */
130 			set_reg_field_value(
131 				value,
132 				tbl_entry->regval[0],
133 				OUTPUT_CSC_C11_C12_A,
134 				OUTPUT_CSC_C11_A);
135 
136 			set_reg_field_value(
137 				value,
138 				tbl_entry->regval[1],
139 				OUTPUT_CSC_C11_C12_A,
140 				OUTPUT_CSC_C12_A);
141 
142 			dm_write_reg(ctx, addr, value);
143 		}
144 		{
145 			uint32_t value = 0;
146 			uint32_t addr = mmOUTPUT_CSC_C13_C14_A;
147 			/* fixed S2.13 format */
148 			set_reg_field_value(
149 				value,
150 				tbl_entry->regval[2],
151 				OUTPUT_CSC_C13_C14_A,
152 				OUTPUT_CSC_C13_A);
153 			/* fixed S0.13 format */
154 			set_reg_field_value(
155 				value,
156 				tbl_entry->regval[3],
157 				OUTPUT_CSC_C13_C14_A,
158 				OUTPUT_CSC_C14_A);
159 
160 			dm_write_reg(ctx, addr, value);
161 		}
162 		{
163 			uint32_t value = 0;
164 			uint32_t addr = mmOUTPUT_CSC_C21_C22_A;
165 			/* fixed S2.13 format */
166 			set_reg_field_value(
167 				value,
168 				tbl_entry->regval[4],
169 				OUTPUT_CSC_C21_C22_A,
170 				OUTPUT_CSC_C21_A);
171 			/* fixed S2.13 format */
172 			set_reg_field_value(
173 				value,
174 				tbl_entry->regval[5],
175 				OUTPUT_CSC_C21_C22_A,
176 				OUTPUT_CSC_C22_A);
177 
178 			dm_write_reg(ctx, addr, value);
179 		}
180 		{
181 			uint32_t value = 0;
182 			uint32_t addr = mmOUTPUT_CSC_C23_C24_A;
183 			/* fixed S2.13 format */
184 			set_reg_field_value(
185 				value,
186 				tbl_entry->regval[6],
187 				OUTPUT_CSC_C23_C24_A,
188 				OUTPUT_CSC_C23_A);
189 			/* fixed S0.13 format */
190 			set_reg_field_value(
191 				value,
192 				tbl_entry->regval[7],
193 				OUTPUT_CSC_C23_C24_A,
194 				OUTPUT_CSC_C24_A);
195 
196 			dm_write_reg(ctx, addr, value);
197 		}
198 		{
199 			uint32_t value = 0;
200 			uint32_t addr = mmOUTPUT_CSC_C31_C32_A;
201 			/* fixed S2.13 format */
202 			set_reg_field_value(
203 				value,
204 				tbl_entry->regval[8],
205 				OUTPUT_CSC_C31_C32_A,
206 				OUTPUT_CSC_C31_A);
207 			/* fixed S0.13 format */
208 			set_reg_field_value(
209 				value,
210 				tbl_entry->regval[9],
211 				OUTPUT_CSC_C31_C32_A,
212 				OUTPUT_CSC_C32_A);
213 
214 			dm_write_reg(ctx, addr, value);
215 		}
216 		{
217 			uint32_t value = 0;
218 			uint32_t addr = mmOUTPUT_CSC_C33_C34_A;
219 			/* fixed S2.13 format */
220 			set_reg_field_value(
221 				value,
222 				tbl_entry->regval[10],
223 				OUTPUT_CSC_C33_C34_A,
224 				OUTPUT_CSC_C33_A);
225 			/* fixed S0.13 format */
226 			set_reg_field_value(
227 				value,
228 				tbl_entry->regval[11],
229 				OUTPUT_CSC_C33_C34_A,
230 				OUTPUT_CSC_C34_A);
231 
232 			dm_write_reg(ctx, addr, value);
233 		}
234 		set_reg_field_value(
235 			cntl_value,
236 			4,
237 			COL_MAN_OUTPUT_CSC_CONTROL,
238 			OUTPUT_CSC_MODE);
239 	} else {
240 		{
241 			uint32_t value = 0;
242 			uint32_t addr = mmOUTPUT_CSC_C11_C12_B;
243 			/* fixed S2.13 format */
244 			set_reg_field_value(
245 				value,
246 				tbl_entry->regval[0],
247 				OUTPUT_CSC_C11_C12_B,
248 				OUTPUT_CSC_C11_B);
249 
250 			set_reg_field_value(
251 				value,
252 				tbl_entry->regval[1],
253 				OUTPUT_CSC_C11_C12_B,
254 				OUTPUT_CSC_C12_B);
255 
256 			dm_write_reg(ctx, addr, value);
257 		}
258 		{
259 			uint32_t value = 0;
260 			uint32_t addr = mmOUTPUT_CSC_C13_C14_B;
261 			/* fixed S2.13 format */
262 			set_reg_field_value(
263 				value,
264 				tbl_entry->regval[2],
265 				OUTPUT_CSC_C13_C14_B,
266 				OUTPUT_CSC_C13_B);
267 			/* fixed S0.13 format */
268 			set_reg_field_value(
269 				value,
270 				tbl_entry->regval[3],
271 				OUTPUT_CSC_C13_C14_B,
272 				OUTPUT_CSC_C14_B);
273 
274 			dm_write_reg(ctx, addr, value);
275 		}
276 		{
277 			uint32_t value = 0;
278 			uint32_t addr = mmOUTPUT_CSC_C21_C22_B;
279 			/* fixed S2.13 format */
280 			set_reg_field_value(
281 				value,
282 				tbl_entry->regval[4],
283 				OUTPUT_CSC_C21_C22_B,
284 				OUTPUT_CSC_C21_B);
285 			/* fixed S2.13 format */
286 			set_reg_field_value(
287 				value,
288 				tbl_entry->regval[5],
289 				OUTPUT_CSC_C21_C22_B,
290 				OUTPUT_CSC_C22_B);
291 
292 			dm_write_reg(ctx, addr, value);
293 		}
294 		{
295 			uint32_t value = 0;
296 			uint32_t addr = mmOUTPUT_CSC_C23_C24_B;
297 			/* fixed S2.13 format */
298 			set_reg_field_value(
299 				value,
300 				tbl_entry->regval[6],
301 				OUTPUT_CSC_C23_C24_B,
302 				OUTPUT_CSC_C23_B);
303 			/* fixed S0.13 format */
304 			set_reg_field_value(
305 				value,
306 				tbl_entry->regval[7],
307 				OUTPUT_CSC_C23_C24_B,
308 				OUTPUT_CSC_C24_B);
309 
310 			dm_write_reg(ctx, addr, value);
311 		}
312 		{
313 			uint32_t value = 0;
314 			uint32_t addr = mmOUTPUT_CSC_C31_C32_B;
315 			/* fixed S2.13 format */
316 			set_reg_field_value(
317 				value,
318 				tbl_entry->regval[8],
319 				OUTPUT_CSC_C31_C32_B,
320 				OUTPUT_CSC_C31_B);
321 			/* fixed S0.13 format */
322 			set_reg_field_value(
323 				value,
324 				tbl_entry->regval[9],
325 				OUTPUT_CSC_C31_C32_B,
326 				OUTPUT_CSC_C32_B);
327 
328 			dm_write_reg(ctx, addr, value);
329 		}
330 		{
331 			uint32_t value = 0;
332 			uint32_t addr = mmOUTPUT_CSC_C33_C34_B;
333 			/* fixed S2.13 format */
334 			set_reg_field_value(
335 				value,
336 				tbl_entry->regval[10],
337 				OUTPUT_CSC_C33_C34_B,
338 				OUTPUT_CSC_C33_B);
339 			/* fixed S0.13 format */
340 			set_reg_field_value(
341 				value,
342 				tbl_entry->regval[11],
343 				OUTPUT_CSC_C33_C34_B,
344 				OUTPUT_CSC_C34_B);
345 
346 			dm_write_reg(ctx, addr, value);
347 		}
348 		set_reg_field_value(
349 			cntl_value,
350 			5,
351 			COL_MAN_OUTPUT_CSC_CONTROL,
352 			OUTPUT_CSC_MODE);
353 	}
354 
355 	dm_write_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL, cntl_value);
356 }
357 
configure_graphics_mode_v(struct dce_transform * xfm_dce,enum csc_color_mode config,enum graphics_csc_adjust_type csc_adjust_type,enum dc_color_space color_space)358 static bool configure_graphics_mode_v(
359 	struct dce_transform *xfm_dce,
360 	enum csc_color_mode config,
361 	enum graphics_csc_adjust_type csc_adjust_type,
362 	enum dc_color_space color_space)
363 {
364 	struct dc_context *ctx = xfm_dce->base.ctx;
365 	uint32_t addr = mmCOL_MAN_OUTPUT_CSC_CONTROL;
366 	uint32_t value = dm_read_reg(ctx, addr);
367 
368 	set_reg_field_value(
369 		value,
370 		0,
371 		COL_MAN_OUTPUT_CSC_CONTROL,
372 		OUTPUT_CSC_MODE);
373 
374 	if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
375 		if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC)
376 			return true;
377 
378 		switch (color_space) {
379 		case COLOR_SPACE_SRGB:
380 			/* by pass */
381 			set_reg_field_value(
382 				value,
383 				0,
384 				COL_MAN_OUTPUT_CSC_CONTROL,
385 				OUTPUT_CSC_MODE);
386 			break;
387 		case COLOR_SPACE_SRGB_LIMITED:
388 			/* not supported for underlay on CZ */
389 			return false;
390 
391 		case COLOR_SPACE_YCBCR601_LIMITED:
392 			/* YCbCr601 */
393 			set_reg_field_value(
394 				value,
395 				2,
396 				COL_MAN_OUTPUT_CSC_CONTROL,
397 				OUTPUT_CSC_MODE);
398 			break;
399 		case COLOR_SPACE_YCBCR709:
400 		case COLOR_SPACE_YCBCR709_LIMITED:
401 			/* YCbCr709 */
402 			set_reg_field_value(
403 				value,
404 				3,
405 				COL_MAN_OUTPUT_CSC_CONTROL,
406 				OUTPUT_CSC_MODE);
407 			break;
408 		default:
409 			return false;
410 		}
411 
412 	} else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
413 		switch (color_space) {
414 		case COLOR_SPACE_SRGB:
415 			/* by pass */
416 			set_reg_field_value(
417 				value,
418 				0,
419 				COL_MAN_OUTPUT_CSC_CONTROL,
420 				OUTPUT_CSC_MODE);
421 			break;
422 		case COLOR_SPACE_SRGB_LIMITED:
423 			/* not supported for underlay on CZ */
424 			return false;
425 		case COLOR_SPACE_YCBCR601:
426 		case COLOR_SPACE_YCBCR601_LIMITED:
427 			/* YCbCr601 */
428 			set_reg_field_value(
429 				value,
430 				2,
431 				COL_MAN_OUTPUT_CSC_CONTROL,
432 				OUTPUT_CSC_MODE);
433 			break;
434 		case COLOR_SPACE_YCBCR709:
435 		case COLOR_SPACE_YCBCR709_LIMITED:
436 			 /* YCbCr709 */
437 			set_reg_field_value(
438 				value,
439 				3,
440 				COL_MAN_OUTPUT_CSC_CONTROL,
441 				OUTPUT_CSC_MODE);
442 			break;
443 		default:
444 			return false;
445 		}
446 
447 	} else
448 		/* by pass */
449 		set_reg_field_value(
450 			value,
451 			0,
452 			COL_MAN_OUTPUT_CSC_CONTROL,
453 			OUTPUT_CSC_MODE);
454 
455 	addr = mmCOL_MAN_OUTPUT_CSC_CONTROL;
456 	dm_write_reg(ctx, addr, value);
457 
458 	return true;
459 }
460 
461 /*TODO: color depth is not correct when this is called*/
set_Denormalization(struct transform * xfm,enum dc_color_depth color_depth)462 static void set_Denormalization(struct transform *xfm,
463 		enum dc_color_depth color_depth)
464 {
465 	uint32_t value = dm_read_reg(xfm->ctx, mmDENORM_CLAMP_CONTROL);
466 
467 	switch (color_depth) {
468 	case COLOR_DEPTH_888:
469 		/* 255/256 for 8 bit output color depth */
470 		set_reg_field_value(
471 			value,
472 			1,
473 			DENORM_CLAMP_CONTROL,
474 			DENORM_MODE);
475 		break;
476 	case COLOR_DEPTH_101010:
477 		/* 1023/1024 for 10 bit output color depth */
478 		set_reg_field_value(
479 			value,
480 			2,
481 			DENORM_CLAMP_CONTROL,
482 			DENORM_MODE);
483 		break;
484 	case COLOR_DEPTH_121212:
485 		/* 4095/4096 for 12 bit output color depth */
486 		set_reg_field_value(
487 			value,
488 			3,
489 			DENORM_CLAMP_CONTROL,
490 			DENORM_MODE);
491 		break;
492 	default:
493 		/* not valid case */
494 		break;
495 	}
496 
497 	set_reg_field_value(
498 		value,
499 		1,
500 		DENORM_CLAMP_CONTROL,
501 		DENORM_10BIT_OUT);
502 
503 	dm_write_reg(xfm->ctx, mmDENORM_CLAMP_CONTROL, value);
504 }
505 
506 struct input_csc_matrix {
507 	enum dc_color_space color_space;
508 	uint32_t regval[12];
509 };
510 
511 static const struct input_csc_matrix input_csc_matrix[] = {
512 	{COLOR_SPACE_SRGB,
513 /*1_1   1_2   1_3   1_4   2_1   2_2   2_3   2_4   3_1   3_2   3_3   3_4 */
514 		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
515 	{COLOR_SPACE_SRGB_LIMITED,
516 		{0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
517 	{COLOR_SPACE_YCBCR601,
518 		{0x2cdd, 0x2000, 0x0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
519 						0x0, 0x2000, 0x38b4, 0xe3a6} },
520 	{COLOR_SPACE_YCBCR601_LIMITED,
521 		{0x3353, 0x2568, 0x0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
522 						0x0, 0x2568, 0x40de, 0xdd3a} },
523 	{COLOR_SPACE_YCBCR709,
524 		{0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
525 						0x2000, 0x3b61, 0xe24f} },
526 	{COLOR_SPACE_YCBCR709_LIMITED,
527 		{0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
528 						0x2568, 0x43ee, 0xdbb2} }
529 };
530 
program_input_csc(struct transform * xfm,enum dc_color_space color_space)531 static void program_input_csc(
532 		struct transform *xfm, enum dc_color_space color_space)
533 {
534 	int arr_size = sizeof(input_csc_matrix)/sizeof(struct input_csc_matrix);
535 	struct dc_context *ctx = xfm->ctx;
536 	const uint32_t *regval = NULL;
537 	bool use_set_a;
538 	uint32_t value;
539 	int i;
540 
541 	for (i = 0; i < arr_size; i++)
542 		if (input_csc_matrix[i].color_space == color_space) {
543 			regval = input_csc_matrix[i].regval;
544 			break;
545 		}
546 	if (regval == NULL) {
547 		BREAK_TO_DEBUGGER();
548 		return;
549 	}
550 
551 	/*
552 	 * 1 == set A, the logic is 'if currently we're not using set A,
553 	 * then use set A, otherwise use set B'
554 	 */
555 	value = dm_read_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL);
556 	use_set_a = get_reg_field_value(
557 		value, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_MODE) != 1;
558 
559 	if (use_set_a) {
560 		/* fixed S2.13 format */
561 		value = 0;
562 		set_reg_field_value(
563 			value, regval[0], INPUT_CSC_C11_C12_A, INPUT_CSC_C11_A);
564 		set_reg_field_value(
565 			value, regval[1], INPUT_CSC_C11_C12_A, INPUT_CSC_C12_A);
566 		dm_write_reg(ctx, mmINPUT_CSC_C11_C12_A, value);
567 
568 		value = 0;
569 		set_reg_field_value(
570 			value, regval[2], INPUT_CSC_C13_C14_A, INPUT_CSC_C13_A);
571 		set_reg_field_value(
572 			value, regval[3], INPUT_CSC_C13_C14_A, INPUT_CSC_C14_A);
573 		dm_write_reg(ctx, mmINPUT_CSC_C13_C14_A, value);
574 
575 		value = 0;
576 		set_reg_field_value(
577 			value, regval[4], INPUT_CSC_C21_C22_A, INPUT_CSC_C21_A);
578 		set_reg_field_value(
579 			value, regval[5], INPUT_CSC_C21_C22_A, INPUT_CSC_C22_A);
580 		dm_write_reg(ctx, mmINPUT_CSC_C21_C22_A, value);
581 
582 		value = 0;
583 		set_reg_field_value(
584 			value, regval[6], INPUT_CSC_C23_C24_A, INPUT_CSC_C23_A);
585 		set_reg_field_value(
586 			value, regval[7], INPUT_CSC_C23_C24_A, INPUT_CSC_C24_A);
587 		dm_write_reg(ctx, mmINPUT_CSC_C23_C24_A, value);
588 
589 		value = 0;
590 		set_reg_field_value(
591 			value, regval[8], INPUT_CSC_C31_C32_A, INPUT_CSC_C31_A);
592 		set_reg_field_value(
593 			value, regval[9], INPUT_CSC_C31_C32_A, INPUT_CSC_C32_A);
594 		dm_write_reg(ctx, mmINPUT_CSC_C31_C32_A, value);
595 
596 		value = 0;
597 		set_reg_field_value(
598 			value, regval[10], INPUT_CSC_C33_C34_A, INPUT_CSC_C33_A);
599 		set_reg_field_value(
600 			value, regval[11], INPUT_CSC_C33_C34_A, INPUT_CSC_C34_A);
601 		dm_write_reg(ctx, mmINPUT_CSC_C33_C34_A, value);
602 	} else {
603 		/* fixed S2.13 format */
604 		value = 0;
605 		set_reg_field_value(
606 			value, regval[0], INPUT_CSC_C11_C12_B, INPUT_CSC_C11_B);
607 		set_reg_field_value(
608 			value, regval[1], INPUT_CSC_C11_C12_B, INPUT_CSC_C12_B);
609 		dm_write_reg(ctx, mmINPUT_CSC_C11_C12_B, value);
610 
611 		value = 0;
612 		set_reg_field_value(
613 			value, regval[2], INPUT_CSC_C13_C14_B, INPUT_CSC_C13_B);
614 		set_reg_field_value(
615 			value, regval[3], INPUT_CSC_C13_C14_B, INPUT_CSC_C14_B);
616 		dm_write_reg(ctx, mmINPUT_CSC_C13_C14_B, value);
617 
618 		value = 0;
619 		set_reg_field_value(
620 			value, regval[4], INPUT_CSC_C21_C22_B, INPUT_CSC_C21_B);
621 		set_reg_field_value(
622 			value, regval[5], INPUT_CSC_C21_C22_B, INPUT_CSC_C22_B);
623 		dm_write_reg(ctx, mmINPUT_CSC_C21_C22_B, value);
624 
625 		value = 0;
626 		set_reg_field_value(
627 			value, regval[6], INPUT_CSC_C23_C24_B, INPUT_CSC_C23_B);
628 		set_reg_field_value(
629 			value, regval[7], INPUT_CSC_C23_C24_B, INPUT_CSC_C24_B);
630 		dm_write_reg(ctx, mmINPUT_CSC_C23_C24_B, value);
631 
632 		value = 0;
633 		set_reg_field_value(
634 			value, regval[8], INPUT_CSC_C31_C32_B, INPUT_CSC_C31_B);
635 		set_reg_field_value(
636 			value, regval[9], INPUT_CSC_C31_C32_B, INPUT_CSC_C32_B);
637 		dm_write_reg(ctx, mmINPUT_CSC_C31_C32_B, value);
638 
639 		value = 0;
640 		set_reg_field_value(
641 			value, regval[10], INPUT_CSC_C33_C34_B, INPUT_CSC_C33_B);
642 		set_reg_field_value(
643 			value, regval[11], INPUT_CSC_C33_C34_B, INPUT_CSC_C34_B);
644 		dm_write_reg(ctx, mmINPUT_CSC_C33_C34_B, value);
645 	}
646 
647 	/* KK: leave INPUT_CSC_CONVERSION_MODE at default */
648 	value = 0;
649 	/*
650 	 * select 8.4 input type instead of default 12.0. From the discussion
651 	 * with HW team, this format depends on the UNP surface format, so for
652 	 * 8-bit we should select 8.4 (4 bits truncated). For 10 it should be
653 	 * 10.2. For Carrizo we only support 8-bit surfaces on underlay pipe
654 	 * so we can always keep this at 8.4 (input_type=2). If the later asics
655 	 * start supporting 10+ bits, we will have a problem: surface
656 	 * programming including UNP_GRPH* is being done in DalISR after this,
657 	 * so either we pass surface format to here, or move this logic to ISR
658 	 */
659 
660 	set_reg_field_value(
661 		value, 2, COL_MAN_INPUT_CSC_CONTROL, INPUT_CSC_INPUT_TYPE);
662 	set_reg_field_value(
663 		value,
664 		use_set_a ? 1 : 2,
665 		COL_MAN_INPUT_CSC_CONTROL,
666 		INPUT_CSC_MODE);
667 
668 	dm_write_reg(ctx, mmCOL_MAN_INPUT_CSC_CONTROL, value);
669 }
670 
dce110_opp_v_set_csc_default(struct transform * xfm,const struct default_adjustment * default_adjust)671 void dce110_opp_v_set_csc_default(
672 	struct transform *xfm,
673 	const struct default_adjustment *default_adjust)
674 {
675 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
676 	enum csc_color_mode config =
677 			CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
678 
679 	if (default_adjust->force_hw_default == false) {
680 		const struct out_csc_color_matrix *elm;
681 		/* currently parameter not in use */
682 		enum grph_color_adjust_option option;
683 		uint32_t i;
684 		/*
685 		 * HW default false we program locally defined matrix
686 		 * HW default true  we use predefined hw matrix and we
687 		 * do not need to program matrix
688 		 * OEM wants the HW default via runtime parameter.
689 		 */
690 		option = GRPH_COLOR_MATRIX_SW;
691 
692 		for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
693 			elm = &global_color_matrix[i];
694 			if (elm->color_space != default_adjust->out_color_space)
695 				continue;
696 			/* program the matrix with default values from this
697 			 * file
698 			 */
699 			program_color_matrix_v(xfm_dce, elm, option);
700 			config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
701 			break;
702 		}
703 	}
704 
705 	program_input_csc(xfm, default_adjust->in_color_space);
706 
707 	/* configure the what we programmed :
708 	 * 1. Default values from this file
709 	 * 2. Use hardware default from ROM_A and we do not need to program
710 	 * matrix
711 	 */
712 
713 	configure_graphics_mode_v(xfm_dce, config,
714 		default_adjust->csc_adjust_type,
715 		default_adjust->out_color_space);
716 
717 	set_Denormalization(xfm, default_adjust->color_depth);
718 }
719 
dce110_opp_v_set_csc_adjustment(struct transform * xfm,const struct out_csc_color_matrix * tbl_entry)720 void dce110_opp_v_set_csc_adjustment(
721 	struct transform *xfm,
722 	const struct out_csc_color_matrix *tbl_entry)
723 {
724 	struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
725 	enum csc_color_mode config =
726 			CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
727 
728 	program_color_matrix_v(
729 			xfm_dce, tbl_entry, GRPH_COLOR_MATRIX_SW);
730 
731 	/*  We did everything ,now program DxOUTPUT_CSC_CONTROL */
732 	configure_graphics_mode_v(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
733 			tbl_entry->color_space);
734 
735 	/*TODO: Check if denormalization is needed*/
736 	/*set_Denormalization(opp, adjust->color_depth);*/
737 }
738