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, tbl_entry: elm, options: option);
700 config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
701 break;
702 }
703 }
704
705 program_input_csc(xfm, color_space: 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 csc_adjust_type: default_adjust->csc_adjust_type,
715 color_space: default_adjust->out_color_space);
716
717 set_Denormalization(xfm, color_depth: 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, options: GRPH_COLOR_MATRIX_SW);
730
731 /* We did everything ,now program DxOUTPUT_CSC_CONTROL */
732 configure_graphics_mode_v(xfm_dce, config, csc_adjust_type: GRAPHICS_CSC_ADJUST_TYPE_SW,
733 color_space: tbl_entry->color_space);
734
735 /*TODO: Check if denormalization is needed*/
736 /*set_Denormalization(opp, adjust->color_depth);*/
737}
738

source code of linux/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c