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
40 enum {
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
82 static 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
99 enum 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
108 enum grph_color_adjust_option {
109 GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
110 GRPH_COLOR_MATRIX_SW
111 };
112
program_color_matrix_v(struct dce_transform * xfm_dce,const struct out_csc_color_matrix * tbl_entry,enum grph_color_adjust_option options)113 static 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
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)363 static 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*/
set_Denormalization(struct transform * xfm,enum dc_color_depth color_depth)467 static 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
511 struct input_csc_matrix {
512 enum dc_color_space color_space;
513 uint32_t regval[12];
514 };
515
516 static 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
program_input_csc(struct transform * xfm,enum dc_color_space color_space)536 static 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
dce110_opp_v_set_csc_default(struct transform * xfm,const struct default_adjustment * default_adjust)676 void 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
dce110_opp_v_set_csc_adjustment(struct transform * xfm,const struct out_csc_color_matrix * tbl_entry)726 void 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