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 | |
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 | |
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*/ |
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 | |
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 | |
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, 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 | |
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, 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 | |