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