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
35enum {
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
77static 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
94enum 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
103enum grph_color_adjust_option {
104	GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
105	GRPH_COLOR_MATRIX_SW
106};
107
108static 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
358static 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*/
462static 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
506struct input_csc_matrix {
507	enum dc_color_space color_space;
508	uint32_t regval[12];
509};
510
511static 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
531static 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
671void 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
720void 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