1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "dce_transform.h"
27#include "reg_helper.h"
28#include "opp.h"
29#include "basics/conversion.h"
30#include "dc.h"
31
32#define REG(reg) \
33 (xfm_dce->regs->reg)
34
35#undef FN
36#define FN(reg_name, field_name) \
37 xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name
38
39#define CTX \
40 xfm_dce->base.ctx
41#define DC_LOGGER \
42 xfm_dce->base.ctx->logger
43
44#define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
45#define GAMUT_MATRIX_SIZE 12
46#define SCL_PHASES 16
47
48enum dcp_out_trunc_round_mode {
49 DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE,
50 DCP_OUT_TRUNC_ROUND_MODE_ROUND
51};
52
53enum dcp_out_trunc_round_depth {
54 DCP_OUT_TRUNC_ROUND_DEPTH_14BIT,
55 DCP_OUT_TRUNC_ROUND_DEPTH_13BIT,
56 DCP_OUT_TRUNC_ROUND_DEPTH_12BIT,
57 DCP_OUT_TRUNC_ROUND_DEPTH_11BIT,
58 DCP_OUT_TRUNC_ROUND_DEPTH_10BIT,
59 DCP_OUT_TRUNC_ROUND_DEPTH_9BIT,
60 DCP_OUT_TRUNC_ROUND_DEPTH_8BIT
61};
62
63
64enum dcp_bit_depth_reduction_mode {
65 DCP_BIT_DEPTH_REDUCTION_MODE_DITHER,
66 DCP_BIT_DEPTH_REDUCTION_MODE_ROUND,
67 DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE,
68 DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED,
69 DCP_BIT_DEPTH_REDUCTION_MODE_INVALID
70};
71
72enum dcp_spatial_dither_mode {
73 DCP_SPATIAL_DITHER_MODE_AAAA,
74 DCP_SPATIAL_DITHER_MODE_A_AA_A,
75 DCP_SPATIAL_DITHER_MODE_AABBAABB,
76 DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC,
77 DCP_SPATIAL_DITHER_MODE_INVALID
78};
79
80enum dcp_spatial_dither_depth {
81 DCP_SPATIAL_DITHER_DEPTH_30BPP,
82 DCP_SPATIAL_DITHER_DEPTH_24BPP
83};
84
85enum csc_color_mode {
86
87 CSC_COLOR_MODE_GRAPHICS_BYPASS,
88
89 CSC_COLOR_MODE_GRAPHICS_PREDEFINED,
90
91 CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC,
92};
93
94enum grph_color_adjust_option {
95 GRPH_COLOR_MATRIX_HW_DEFAULT = 1,
96 GRPH_COLOR_MATRIX_SW
97};
98
99static const struct out_csc_color_matrix global_color_matrix[] = {
100{ COLOR_SPACE_SRGB,
101 { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
102{ COLOR_SPACE_SRGB_LIMITED,
103 { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} },
104{ COLOR_SPACE_YCBCR601,
105 { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47,
106 0xF6B9, 0xE00, 0x1000} },
107{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA,
108 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
109
110{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991,
111 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} },
112{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
113 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }
114};
115
116static bool setup_scaling_configuration(
117 struct dce_transform *xfm_dce,
118 const struct scaler_data *data)
119{
120 REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);
121
122 if (data->taps.h_taps + data->taps.v_taps <= 2) {
123
124 if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
125 REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0);
126 else
127 REG_UPDATE(SCL_MODE, SCL_MODE, 0);
128 return false;
129 }
130
131 REG_SET_2(SCL_TAP_CONTROL, 0,
132 SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
133 SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
134
135 if (data->format <= PIXEL_FORMAT_GRPH_END)
136 REG_UPDATE(SCL_MODE, SCL_MODE, 1);
137 else
138 REG_UPDATE(SCL_MODE, SCL_MODE, 2);
139
140 if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0)
141 REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1);
142
143
144 REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1);
145
146 return true;
147}
148
149#if defined(CONFIG_DRM_AMD_DC_SI)
150static bool dce60_setup_scaling_configuration(
151 struct dce_transform *xfm_dce,
152 const struct scaler_data *data)
153{
154 REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0);
155
156 if (data->taps.h_taps + data->taps.v_taps <= 2) {
157
158
159
160
161 return false;
162 }
163
164 REG_SET_2(SCL_TAP_CONTROL, 0,
165 SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1,
166 SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1);
167
168
169
170
171
172 return true;
173}
174#endif
175
176static void program_overscan(
177 struct dce_transform *xfm_dce,
178 const struct scaler_data *data)
179{
180 int overscan_right = data->h_active
181 - data->recout.x - data->recout.width;
182 int overscan_bottom = data->v_active
183 - data->recout.y - data->recout.height;
184
185 if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
186 overscan_bottom += 2;
187 overscan_right += 2;
188 }
189
190 if (overscan_right < 0) {
191 BREAK_TO_DEBUGGER();
192 overscan_right = 0;
193 }
194 if (overscan_bottom < 0) {
195 BREAK_TO_DEBUGGER();
196 overscan_bottom = 0;
197 }
198
199 REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0,
200 EXT_OVERSCAN_LEFT, data->recout.x,
201 EXT_OVERSCAN_RIGHT, overscan_right);
202 REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0,
203 EXT_OVERSCAN_TOP, data->recout.y,
204 EXT_OVERSCAN_BOTTOM, overscan_bottom);
205}
206
207static void program_multi_taps_filter(
208 struct dce_transform *xfm_dce,
209 int taps,
210 const uint16_t *coeffs,
211 enum ram_filter_type filter_type)
212{
213 int phase, pair;
214 int array_idx = 0;
215 int taps_pairs = (taps + 1) / 2;
216 int phases_to_program = SCL_PHASES / 2 + 1;
217
218 uint32_t power_ctl = 0;
219
220 if (!coeffs)
221 return;
222
223
224 if (REG(DCFE_MEM_PWR_CTRL)) {
225 power_ctl = REG_READ(DCFE_MEM_PWR_CTRL);
226 REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1);
227
228 REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10);
229 }
230 for (phase = 0; phase < phases_to_program; phase++) {
231
232
233 for (pair = 0; pair < taps_pairs; pair++) {
234 uint16_t odd_coeff = 0;
235 uint16_t even_coeff = coeffs[array_idx];
236
237 REG_SET_3(SCL_COEF_RAM_SELECT, 0,
238 SCL_C_RAM_FILTER_TYPE, filter_type,
239 SCL_C_RAM_PHASE, phase,
240 SCL_C_RAM_TAP_PAIR_IDX, pair);
241
242 if (taps % 2 && pair == taps_pairs - 1)
243 array_idx++;
244 else {
245 odd_coeff = coeffs[array_idx + 1];
246 array_idx += 2;
247 }
248
249 REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
250 SCL_C_RAM_EVEN_TAP_COEF_EN, 1,
251 SCL_C_RAM_EVEN_TAP_COEF, even_coeff,
252 SCL_C_RAM_ODD_TAP_COEF_EN, 1,
253 SCL_C_RAM_ODD_TAP_COEF, odd_coeff);
254 }
255 }
256
257
258 if (REG(DCFE_MEM_PWR_CTRL))
259 REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl);
260}
261
262static void program_viewport(
263 struct dce_transform *xfm_dce,
264 const struct rect *view_port)
265{
266 REG_SET_2(VIEWPORT_START, 0,
267 VIEWPORT_X_START, view_port->x,
268 VIEWPORT_Y_START, view_port->y);
269
270 REG_SET_2(VIEWPORT_SIZE, 0,
271 VIEWPORT_HEIGHT, view_port->height,
272 VIEWPORT_WIDTH, view_port->width);
273
274
275}
276
277static void calculate_inits(
278 struct dce_transform *xfm_dce,
279 const struct scaler_data *data,
280 struct scl_ratios_inits *inits)
281{
282 struct fixed31_32 h_init;
283 struct fixed31_32 v_init;
284
285 inits->h_int_scale_ratio =
286 dc_fixpt_u2d19(data->ratios.horz) << 5;
287 inits->v_int_scale_ratio =
288 dc_fixpt_u2d19(data->ratios.vert) << 5;
289
290 h_init =
291 dc_fixpt_div_int(
292 dc_fixpt_add(
293 data->ratios.horz,
294 dc_fixpt_from_int(data->taps.h_taps + 1)),
295 2);
296 inits->h_init.integer = dc_fixpt_floor(h_init);
297 inits->h_init.fraction = dc_fixpt_u0d19(h_init) << 5;
298
299 v_init =
300 dc_fixpt_div_int(
301 dc_fixpt_add(
302 data->ratios.vert,
303 dc_fixpt_from_int(data->taps.v_taps + 1)),
304 2);
305 inits->v_init.integer = dc_fixpt_floor(v_init);
306 inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5;
307}
308
309#if defined(CONFIG_DRM_AMD_DC_SI)
310static void dce60_calculate_inits(
311 struct dce_transform *xfm_dce,
312 const struct scaler_data *data,
313 struct sclh_ratios_inits *inits)
314{
315 struct fixed31_32 v_init;
316
317 inits->h_int_scale_ratio =
318 dc_fixpt_u2d19(data->ratios.horz) << 5;
319 inits->v_int_scale_ratio =
320 dc_fixpt_u2d19(data->ratios.vert) << 5;
321
322
323 inits->h_init_luma.integer = 1;
324
325
326 inits->h_init_chroma.integer = 1;
327
328 v_init =
329 dc_fixpt_div_int(
330 dc_fixpt_add(
331 data->ratios.vert,
332 dc_fixpt_from_int(data->taps.v_taps + 1)),
333 2);
334 inits->v_init.integer = dc_fixpt_floor(v_init);
335 inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5;
336}
337#endif
338
339static void program_scl_ratios_inits(
340 struct dce_transform *xfm_dce,
341 struct scl_ratios_inits *inits)
342{
343
344 REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
345 SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
346
347 REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
348 SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
349
350 REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
351 SCL_H_INIT_INT, inits->h_init.integer,
352 SCL_H_INIT_FRAC, inits->h_init.fraction);
353
354 REG_SET_2(SCL_VERT_FILTER_INIT, 0,
355 SCL_V_INIT_INT, inits->v_init.integer,
356 SCL_V_INIT_FRAC, inits->v_init.fraction);
357
358 REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
359}
360
361#if defined(CONFIG_DRM_AMD_DC_SI)
362static void dce60_program_scl_ratios_inits(
363 struct dce_transform *xfm_dce,
364 struct sclh_ratios_inits *inits)
365{
366
367 REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
368 SCL_H_SCALE_RATIO, inits->h_int_scale_ratio);
369
370 REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
371 SCL_V_SCALE_RATIO, inits->v_int_scale_ratio);
372
373
374 REG_SET_2(SCL_HORZ_FILTER_INIT_RGB_LUMA, 0,
375 SCL_H_INIT_INT_RGB_Y, inits->h_init_luma.integer,
376 SCL_H_INIT_FRAC_RGB_Y, inits->h_init_luma.fraction);
377
378
379 REG_SET_2(SCL_HORZ_FILTER_INIT_CHROMA, 0,
380 SCL_H_INIT_INT_CBCR, inits->h_init_chroma.integer,
381 SCL_H_INIT_FRAC_CBCR, inits->h_init_chroma.fraction);
382
383 REG_SET_2(SCL_VERT_FILTER_INIT, 0,
384 SCL_V_INIT_INT, inits->v_init.integer,
385 SCL_V_INIT_FRAC, inits->v_init.fraction);
386
387 REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0);
388}
389#endif
390
391static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio)
392{
393 if (taps == 4)
394 return get_filter_4tap_16p(ratio);
395 else if (taps == 3)
396 return get_filter_3tap_16p(ratio);
397 else if (taps == 2)
398 return get_filter_2tap_16p();
399 else if (taps == 1)
400 return NULL;
401 else {
402
403 BREAK_TO_DEBUGGER();
404 return NULL;
405 }
406}
407
408static void dce_transform_set_scaler(
409 struct transform *xfm,
410 const struct scaler_data *data)
411{
412 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
413 bool is_scaling_required;
414 bool filter_updated = false;
415 const uint16_t *coeffs_v, *coeffs_h;
416
417
418 REG_SET_2(LB_MEMORY_CTRL, 0,
419 LB_MEMORY_CONFIG, 0,
420 LB_MEMORY_SIZE, xfm_dce->lb_memory_size);
421
422
423 REG_WRITE(SCL_F_SHARP_CONTROL, 0);
424
425
426 program_overscan(xfm_dce, data);
427
428
429 is_scaling_required = setup_scaling_configuration(xfm_dce, data);
430
431 if (is_scaling_required) {
432
433 struct scl_ratios_inits inits = { 0 };
434
435 calculate_inits(xfm_dce, data, &inits);
436
437 program_scl_ratios_inits(xfm_dce, &inits);
438
439 coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
440 coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
441
442 if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
443
444 if (xfm_dce->filter_v == NULL)
445 REG_SET(SCL_VERT_FILTER_CONTROL, 0,
446 SCL_V_2TAP_HARDCODE_COEF_EN, 0);
447 program_multi_taps_filter(
448 xfm_dce,
449 data->taps.v_taps,
450 coeffs_v,
451 FILTER_TYPE_RGB_Y_VERTICAL);
452 program_multi_taps_filter(
453 xfm_dce,
454 data->taps.v_taps,
455 coeffs_v,
456 FILTER_TYPE_ALPHA_VERTICAL);
457
458
459 if (xfm_dce->filter_h == NULL)
460 REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
461 SCL_H_2TAP_HARDCODE_COEF_EN, 0);
462 program_multi_taps_filter(
463 xfm_dce,
464 data->taps.h_taps,
465 coeffs_h,
466 FILTER_TYPE_RGB_Y_HORIZONTAL);
467 program_multi_taps_filter(
468 xfm_dce,
469 data->taps.h_taps,
470 coeffs_h,
471 FILTER_TYPE_ALPHA_HORIZONTAL);
472
473 xfm_dce->filter_v = coeffs_v;
474 xfm_dce->filter_h = coeffs_h;
475 filter_updated = true;
476 }
477 }
478
479
480 program_viewport(xfm_dce, &data->viewport);
481
482
483 if (filter_updated)
484 REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1);
485
486 REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en);
487}
488
489#if defined(CONFIG_DRM_AMD_DC_SI)
490static void dce60_transform_set_scaler(
491 struct transform *xfm,
492 const struct scaler_data *data)
493{
494 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
495 bool is_scaling_required;
496 const uint16_t *coeffs_v, *coeffs_h;
497
498
499 REG_SET(DC_LB_MEMORY_SPLIT, 0,
500 DC_LB_MEMORY_CONFIG, 0);
501
502 REG_SET(DC_LB_MEM_SIZE, 0,
503 DC_LB_MEM_SIZE, xfm_dce->lb_memory_size);
504
505
506 REG_WRITE(SCL_F_SHARP_CONTROL, 0);
507
508
509 program_overscan(xfm_dce, data);
510
511
512 is_scaling_required = dce60_setup_scaling_configuration(xfm_dce, data);
513
514 if (is_scaling_required) {
515
516 struct sclh_ratios_inits inits = { 0 };
517
518
519 dce60_calculate_inits(xfm_dce, data, &inits);
520
521
522 dce60_program_scl_ratios_inits(xfm_dce, &inits);
523
524 coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert);
525 coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz);
526
527 if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) {
528
529 if (xfm_dce->filter_v == NULL)
530 REG_SET(SCL_VERT_FILTER_CONTROL, 0,
531 SCL_V_2TAP_HARDCODE_COEF_EN, 0);
532 program_multi_taps_filter(
533 xfm_dce,
534 data->taps.v_taps,
535 coeffs_v,
536 FILTER_TYPE_RGB_Y_VERTICAL);
537 program_multi_taps_filter(
538 xfm_dce,
539 data->taps.v_taps,
540 coeffs_v,
541 FILTER_TYPE_ALPHA_VERTICAL);
542
543
544 if (xfm_dce->filter_h == NULL)
545 REG_SET(SCL_HORZ_FILTER_CONTROL, 0,
546 SCL_H_2TAP_HARDCODE_COEF_EN, 0);
547 program_multi_taps_filter(
548 xfm_dce,
549 data->taps.h_taps,
550 coeffs_h,
551 FILTER_TYPE_RGB_Y_HORIZONTAL);
552 program_multi_taps_filter(
553 xfm_dce,
554 data->taps.h_taps,
555 coeffs_h,
556 FILTER_TYPE_ALPHA_HORIZONTAL);
557
558 xfm_dce->filter_v = coeffs_v;
559 xfm_dce->filter_h = coeffs_h;
560 }
561 }
562
563
564 program_viewport(xfm_dce, &data->viewport);
565
566
567
568
569}
570#endif
571
572
573
574
575
576
577
578
579
580
581static void set_clamp(
582 struct dce_transform *xfm_dce,
583 enum dc_color_depth depth)
584{
585 int clamp_max = 0;
586
587
588
589
590
591
592 switch (depth) {
593 case COLOR_DEPTH_666:
594
595 clamp_max = 0x3F00;
596 break;
597 case COLOR_DEPTH_888:
598
599 clamp_max = 0x3FC0;
600 break;
601 case COLOR_DEPTH_101010:
602
603 clamp_max = 0x3FF0;
604 break;
605 case COLOR_DEPTH_121212:
606
607 clamp_max = 0x3FFC;
608 break;
609 default:
610 clamp_max = 0x3FC0;
611 BREAK_TO_DEBUGGER();
612 }
613 REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0,
614 OUT_CLAMP_MIN_B_CB, 0,
615 OUT_CLAMP_MAX_B_CB, clamp_max);
616
617 REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0,
618 OUT_CLAMP_MIN_G_Y, 0,
619 OUT_CLAMP_MAX_G_Y, clamp_max);
620
621 REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0,
622 OUT_CLAMP_MIN_R_CR, 0,
623 OUT_CLAMP_MAX_R_CR, clamp_max);
624}
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658static void set_round(
659 struct dce_transform *xfm_dce,
660 enum dcp_out_trunc_round_mode mode,
661 enum dcp_out_trunc_round_depth depth)
662{
663 int depth_bits = 0;
664 int mode_bit = 0;
665
666
667 switch (depth) {
668 case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT:
669 depth_bits = 6;
670 break;
671 case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT:
672 depth_bits = 7;
673 break;
674 case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT:
675 depth_bits = 0;
676 break;
677 case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT:
678 depth_bits = 1;
679 break;
680 case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT:
681 depth_bits = 2;
682 break;
683 case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT:
684 depth_bits = 3;
685 break;
686 case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT:
687 depth_bits = 4;
688 break;
689 default:
690 depth_bits = 4;
691 BREAK_TO_DEBUGGER();
692 }
693
694
695 switch (mode) {
696 case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE:
697 mode_bit = 0;
698 break;
699 case DCP_OUT_TRUNC_ROUND_MODE_ROUND:
700 mode_bit = 1;
701 break;
702 default:
703 BREAK_TO_DEBUGGER();
704 }
705
706 depth_bits |= mode_bit << 3;
707
708 REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits);
709}
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726static void set_dither(
727 struct dce_transform *xfm_dce,
728 bool dither_enable,
729 enum dcp_spatial_dither_mode dither_mode,
730 enum dcp_spatial_dither_depth dither_depth,
731 bool frame_random_enable,
732 bool rgb_random_enable,
733 bool highpass_random_enable)
734{
735 int dither_depth_bits = 0;
736 int dither_mode_bits = 0;
737
738 switch (dither_mode) {
739 case DCP_SPATIAL_DITHER_MODE_AAAA:
740 dither_mode_bits = 0;
741 break;
742 case DCP_SPATIAL_DITHER_MODE_A_AA_A:
743 dither_mode_bits = 1;
744 break;
745 case DCP_SPATIAL_DITHER_MODE_AABBAABB:
746 dither_mode_bits = 2;
747 break;
748 case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC:
749 dither_mode_bits = 3;
750 break;
751 default:
752
753 BREAK_TO_DEBUGGER();
754 }
755
756 switch (dither_depth) {
757 case DCP_SPATIAL_DITHER_DEPTH_30BPP:
758 dither_depth_bits = 0;
759 break;
760 case DCP_SPATIAL_DITHER_DEPTH_24BPP:
761 dither_depth_bits = 1;
762 break;
763 default:
764
765 BREAK_TO_DEBUGGER();
766 }
767
768
769 REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0,
770 DCP_SPATIAL_DITHER_EN, dither_enable,
771 DCP_SPATIAL_DITHER_MODE, dither_mode_bits,
772 DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits,
773 DCP_FRAME_RANDOM_ENABLE, frame_random_enable,
774 DCP_RGB_RANDOM_ENABLE, rgb_random_enable,
775 DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable);
776}
777
778
779
780
781
782
783
784
785
786
787
788static void program_bit_depth_reduction(
789 struct dce_transform *xfm_dce,
790 enum dc_color_depth depth,
791 const struct bit_depth_reduction_params *bit_depth_params)
792{
793 enum dcp_out_trunc_round_depth trunc_round_depth;
794 enum dcp_out_trunc_round_mode trunc_mode;
795 bool spatial_dither_enable;
796
797 ASSERT(depth <= COLOR_DEPTH_121212);
798
799 spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED;
800
801 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
802 trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
803
804 if (bit_depth_params->flags.TRUNCATE_ENABLED) {
805
806 spatial_dither_enable = false;
807 trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ?
808 DCP_OUT_TRUNC_ROUND_MODE_ROUND :
809 DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
810
811 if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 ||
812 bit_depth_params->flags.TRUNCATE_DEPTH == 1)
813 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT;
814 else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2)
815 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT;
816 else {
817
818
819
820
821 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
822 BREAK_TO_DEBUGGER();
823 }
824 }
825
826 set_clamp(xfm_dce, depth);
827 set_round(xfm_dce, trunc_mode, trunc_round_depth);
828 set_dither(xfm_dce,
829 spatial_dither_enable,
830 DCP_SPATIAL_DITHER_MODE_A_AA_A,
831 DCP_SPATIAL_DITHER_DEPTH_30BPP,
832 bit_depth_params->flags.FRAME_RANDOM,
833 bit_depth_params->flags.RGB_RANDOM,
834 bit_depth_params->flags.HIGHPASS_RANDOM);
835}
836
837#if defined(CONFIG_DRM_AMD_DC_SI)
838
839
840
841
842
843
844
845
846
847
848static void dce60_program_bit_depth_reduction(
849 struct dce_transform *xfm_dce,
850 enum dc_color_depth depth,
851 const struct bit_depth_reduction_params *bit_depth_params)
852{
853 enum dcp_out_trunc_round_depth trunc_round_depth;
854 enum dcp_out_trunc_round_mode trunc_mode;
855 bool spatial_dither_enable;
856
857 ASSERT(depth <= COLOR_DEPTH_121212);
858
859 spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED;
860
861 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
862 trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
863
864 if (bit_depth_params->flags.TRUNCATE_ENABLED) {
865
866 spatial_dither_enable = false;
867 trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ?
868 DCP_OUT_TRUNC_ROUND_MODE_ROUND :
869 DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE;
870
871 if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 ||
872 bit_depth_params->flags.TRUNCATE_DEPTH == 1)
873 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT;
874 else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2)
875 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT;
876 else {
877
878
879
880
881 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT;
882 BREAK_TO_DEBUGGER();
883 }
884 }
885
886
887 set_round(xfm_dce, trunc_mode, trunc_round_depth);
888 set_dither(xfm_dce,
889 spatial_dither_enable,
890 DCP_SPATIAL_DITHER_MODE_A_AA_A,
891 DCP_SPATIAL_DITHER_DEPTH_30BPP,
892 bit_depth_params->flags.FRAME_RANDOM,
893 bit_depth_params->flags.RGB_RANDOM,
894 bit_depth_params->flags.HIGHPASS_RANDOM);
895}
896#endif
897
898static int dce_transform_get_max_num_of_supported_lines(
899 struct dce_transform *xfm_dce,
900 enum lb_pixel_depth depth,
901 int pixel_width)
902{
903 int pixels_per_entries = 0;
904 int max_pixels_supports = 0;
905
906 ASSERT(pixel_width);
907
908
909
910
911 switch (depth) {
912 case LB_PIXEL_DEPTH_18BPP:
913 pixels_per_entries = xfm_dce->lb_bits_per_entry / 18;
914 break;
915
916 case LB_PIXEL_DEPTH_24BPP:
917 pixels_per_entries = xfm_dce->lb_bits_per_entry / 24;
918 break;
919
920 case LB_PIXEL_DEPTH_30BPP:
921 pixels_per_entries = xfm_dce->lb_bits_per_entry / 30;
922 break;
923
924 case LB_PIXEL_DEPTH_36BPP:
925 pixels_per_entries = xfm_dce->lb_bits_per_entry / 36;
926 break;
927
928 default:
929 DC_LOG_WARNING("%s: Invalid LB pixel depth",
930 __func__);
931 BREAK_TO_DEBUGGER();
932 break;
933 }
934
935 ASSERT(pixels_per_entries);
936
937 max_pixels_supports =
938 pixels_per_entries *
939 xfm_dce->lb_memory_size;
940
941 return (max_pixels_supports / pixel_width);
942}
943
944static void set_denormalization(
945 struct dce_transform *xfm_dce,
946 enum dc_color_depth depth)
947{
948 int denorm_mode = 0;
949
950 switch (depth) {
951 case COLOR_DEPTH_666:
952
953 denorm_mode = 1;
954 break;
955 case COLOR_DEPTH_888:
956
957
958 denorm_mode = 0;
959 break;
960 case COLOR_DEPTH_101010:
961
962 denorm_mode = 3;
963 break;
964 case COLOR_DEPTH_121212:
965
966 denorm_mode = 5;
967 break;
968 case COLOR_DEPTH_141414:
969 case COLOR_DEPTH_161616:
970 default:
971
972 break;
973 }
974
975 REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode);
976}
977
978static void dce_transform_set_pixel_storage_depth(
979 struct transform *xfm,
980 enum lb_pixel_depth depth,
981 const struct bit_depth_reduction_params *bit_depth_params)
982{
983 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
984 int pixel_depth, expan_mode;
985 enum dc_color_depth color_depth;
986
987 switch (depth) {
988 case LB_PIXEL_DEPTH_18BPP:
989 color_depth = COLOR_DEPTH_666;
990 pixel_depth = 2;
991 expan_mode = 1;
992 break;
993 case LB_PIXEL_DEPTH_24BPP:
994 color_depth = COLOR_DEPTH_888;
995 pixel_depth = 1;
996 expan_mode = 1;
997 break;
998 case LB_PIXEL_DEPTH_30BPP:
999 color_depth = COLOR_DEPTH_101010;
1000 pixel_depth = 0;
1001 expan_mode = 1;
1002 break;
1003 case LB_PIXEL_DEPTH_36BPP:
1004 color_depth = COLOR_DEPTH_121212;
1005 pixel_depth = 3;
1006 expan_mode = 0;
1007 break;
1008 default:
1009 color_depth = COLOR_DEPTH_101010;
1010 pixel_depth = 0;
1011 expan_mode = 1;
1012 BREAK_TO_DEBUGGER();
1013 break;
1014 }
1015
1016 set_denormalization(xfm_dce, color_depth);
1017 program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
1018
1019 REG_UPDATE_2(LB_DATA_FORMAT,
1020 PIXEL_DEPTH, pixel_depth,
1021 PIXEL_EXPAN_MODE, expan_mode);
1022
1023 if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
1024
1025
1026 DC_LOG_WARNING("%s: Capability not supported",
1027 __func__);
1028 }
1029}
1030
1031#if defined(CONFIG_DRM_AMD_DC_SI)
1032static void dce60_transform_set_pixel_storage_depth(
1033 struct transform *xfm,
1034 enum lb_pixel_depth depth,
1035 const struct bit_depth_reduction_params *bit_depth_params)
1036{
1037 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1038 enum dc_color_depth color_depth;
1039
1040 switch (depth) {
1041 case LB_PIXEL_DEPTH_18BPP:
1042 color_depth = COLOR_DEPTH_666;
1043 break;
1044 case LB_PIXEL_DEPTH_24BPP:
1045 color_depth = COLOR_DEPTH_888;
1046 break;
1047 case LB_PIXEL_DEPTH_30BPP:
1048 color_depth = COLOR_DEPTH_101010;
1049 break;
1050 case LB_PIXEL_DEPTH_36BPP:
1051 color_depth = COLOR_DEPTH_121212;
1052 break;
1053 default:
1054 color_depth = COLOR_DEPTH_101010;
1055 BREAK_TO_DEBUGGER();
1056 break;
1057 }
1058
1059 set_denormalization(xfm_dce, color_depth);
1060 dce60_program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params);
1061
1062
1063
1064 if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
1065
1066
1067 DC_LOG_WARNING("%s: Capability not supported",
1068 __func__);
1069 }
1070}
1071#endif
1072
1073static void program_gamut_remap(
1074 struct dce_transform *xfm_dce,
1075 const uint16_t *reg_val)
1076{
1077 if (reg_val) {
1078 REG_SET_2(GAMUT_REMAP_C11_C12, 0,
1079 GAMUT_REMAP_C11, reg_val[0],
1080 GAMUT_REMAP_C12, reg_val[1]);
1081 REG_SET_2(GAMUT_REMAP_C13_C14, 0,
1082 GAMUT_REMAP_C13, reg_val[2],
1083 GAMUT_REMAP_C14, reg_val[3]);
1084 REG_SET_2(GAMUT_REMAP_C21_C22, 0,
1085 GAMUT_REMAP_C21, reg_val[4],
1086 GAMUT_REMAP_C22, reg_val[5]);
1087 REG_SET_2(GAMUT_REMAP_C23_C24, 0,
1088 GAMUT_REMAP_C23, reg_val[6],
1089 GAMUT_REMAP_C24, reg_val[7]);
1090 REG_SET_2(GAMUT_REMAP_C31_C32, 0,
1091 GAMUT_REMAP_C31, reg_val[8],
1092 GAMUT_REMAP_C32, reg_val[9]);
1093 REG_SET_2(GAMUT_REMAP_C33_C34, 0,
1094 GAMUT_REMAP_C33, reg_val[10],
1095 GAMUT_REMAP_C34, reg_val[11]);
1096
1097 REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1);
1098 } else
1099 REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0);
1100
1101}
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118static void dce_transform_set_gamut_remap(
1119 struct transform *xfm,
1120 const struct xfm_grph_csc_adjustment *adjust)
1121{
1122 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1123 int i = 0;
1124
1125 if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW)
1126
1127 program_gamut_remap(xfm_dce, NULL);
1128 else {
1129 struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE];
1130 uint16_t arr_reg_val[GAMUT_MATRIX_SIZE];
1131
1132 for (i = 0; i < GAMUT_MATRIX_SIZE; i++)
1133 arr_matrix[i] = adjust->temperature_matrix[i];
1134
1135 convert_float_matrix(
1136 arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE);
1137
1138 program_gamut_remap(xfm_dce, arr_reg_val);
1139 }
1140}
1141
1142static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma)
1143{
1144 uint32_t taps;
1145
1146 if (IDENTITY_RATIO(ratio)) {
1147 return 1;
1148 } else if (in_taps != 0) {
1149 taps = in_taps;
1150 } else {
1151 taps = 4;
1152 }
1153
1154 if (chroma) {
1155 taps /= 2;
1156 if (taps < 2)
1157 taps = 2;
1158 }
1159
1160 return taps;
1161}
1162
1163
1164bool dce_transform_get_optimal_number_of_taps(
1165 struct transform *xfm,
1166 struct scaler_data *scl_data,
1167 const struct scaling_taps *in_taps)
1168{
1169 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1170 int pixel_width = scl_data->viewport.width;
1171 int max_num_of_lines;
1172
1173 if (xfm_dce->prescaler_on &&
1174 (scl_data->viewport.width > scl_data->recout.width))
1175 pixel_width = scl_data->recout.width;
1176
1177 max_num_of_lines = dce_transform_get_max_num_of_supported_lines(
1178 xfm_dce,
1179 scl_data->lb_params.depth,
1180 pixel_width);
1181
1182
1183 if (in_taps->v_taps >= max_num_of_lines)
1184 return false;
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195 scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false);
1196 scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false);
1197 scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true);
1198 scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true);
1199
1200 if (!IDENTITY_RATIO(scl_data->ratios.vert)) {
1201
1202 if (in_taps->v_taps == 0
1203 && max_num_of_lines <= scl_data->taps.v_taps
1204 && scl_data->taps.v_taps > 1) {
1205 scl_data->taps.v_taps = max_num_of_lines - 1;
1206 }
1207
1208 if (scl_data->taps.v_taps <= 1)
1209 return false;
1210 }
1211
1212 if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) {
1213
1214 if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) {
1215 scl_data->taps.v_taps_c = max_num_of_lines - 1;
1216 }
1217
1218 if (scl_data->taps.v_taps_c <= 1)
1219 return false;
1220 }
1221
1222
1223 return true;
1224}
1225
1226static void dce_transform_reset(struct transform *xfm)
1227{
1228 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1229
1230 xfm_dce->filter_h = NULL;
1231 xfm_dce->filter_v = NULL;
1232}
1233
1234static void program_color_matrix(
1235 struct dce_transform *xfm_dce,
1236 const struct out_csc_color_matrix *tbl_entry,
1237 enum grph_color_adjust_option options)
1238{
1239 {
1240 REG_SET_2(OUTPUT_CSC_C11_C12, 0,
1241 OUTPUT_CSC_C11, tbl_entry->regval[0],
1242 OUTPUT_CSC_C12, tbl_entry->regval[1]);
1243 }
1244 {
1245 REG_SET_2(OUTPUT_CSC_C13_C14, 0,
1246 OUTPUT_CSC_C11, tbl_entry->regval[2],
1247 OUTPUT_CSC_C12, tbl_entry->regval[3]);
1248 }
1249 {
1250 REG_SET_2(OUTPUT_CSC_C21_C22, 0,
1251 OUTPUT_CSC_C11, tbl_entry->regval[4],
1252 OUTPUT_CSC_C12, tbl_entry->regval[5]);
1253 }
1254 {
1255 REG_SET_2(OUTPUT_CSC_C23_C24, 0,
1256 OUTPUT_CSC_C11, tbl_entry->regval[6],
1257 OUTPUT_CSC_C12, tbl_entry->regval[7]);
1258 }
1259 {
1260 REG_SET_2(OUTPUT_CSC_C31_C32, 0,
1261 OUTPUT_CSC_C11, tbl_entry->regval[8],
1262 OUTPUT_CSC_C12, tbl_entry->regval[9]);
1263 }
1264 {
1265 REG_SET_2(OUTPUT_CSC_C33_C34, 0,
1266 OUTPUT_CSC_C11, tbl_entry->regval[10],
1267 OUTPUT_CSC_C12, tbl_entry->regval[11]);
1268 }
1269}
1270
1271static bool configure_graphics_mode(
1272 struct dce_transform *xfm_dce,
1273 enum csc_color_mode config,
1274 enum graphics_csc_adjust_type csc_adjust_type,
1275 enum dc_color_space color_space)
1276{
1277 REG_SET(OUTPUT_CSC_CONTROL, 0,
1278 OUTPUT_CSC_GRPH_MODE, 0);
1279
1280 if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) {
1281 if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) {
1282 REG_SET(OUTPUT_CSC_CONTROL, 0,
1283 OUTPUT_CSC_GRPH_MODE, 4);
1284 } else {
1285
1286 switch (color_space) {
1287 case COLOR_SPACE_SRGB:
1288
1289 REG_SET(OUTPUT_CSC_CONTROL, 0,
1290 OUTPUT_CSC_GRPH_MODE, 0);
1291 break;
1292 case COLOR_SPACE_SRGB_LIMITED:
1293
1294 REG_SET(OUTPUT_CSC_CONTROL, 0,
1295 OUTPUT_CSC_GRPH_MODE, 1);
1296 break;
1297 case COLOR_SPACE_YCBCR601:
1298 case COLOR_SPACE_YCBCR601_LIMITED:
1299
1300 REG_SET(OUTPUT_CSC_CONTROL, 0,
1301 OUTPUT_CSC_GRPH_MODE, 2);
1302 break;
1303 case COLOR_SPACE_YCBCR709:
1304 case COLOR_SPACE_YCBCR709_LIMITED:
1305
1306 REG_SET(OUTPUT_CSC_CONTROL, 0,
1307 OUTPUT_CSC_GRPH_MODE, 3);
1308 break;
1309 default:
1310 return false;
1311 }
1312 }
1313 } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) {
1314 switch (color_space) {
1315 case COLOR_SPACE_SRGB:
1316
1317 REG_SET(OUTPUT_CSC_CONTROL, 0,
1318 OUTPUT_CSC_GRPH_MODE, 0);
1319 break;
1320 case COLOR_SPACE_SRGB_LIMITED:
1321
1322 REG_SET(OUTPUT_CSC_CONTROL, 0,
1323 OUTPUT_CSC_GRPH_MODE, 1);
1324 break;
1325 case COLOR_SPACE_YCBCR601:
1326 case COLOR_SPACE_YCBCR601_LIMITED:
1327
1328 REG_SET(OUTPUT_CSC_CONTROL, 0,
1329 OUTPUT_CSC_GRPH_MODE, 2);
1330 break;
1331 case COLOR_SPACE_YCBCR709:
1332 case COLOR_SPACE_YCBCR709_LIMITED:
1333
1334 REG_SET(OUTPUT_CSC_CONTROL, 0,
1335 OUTPUT_CSC_GRPH_MODE, 3);
1336 break;
1337 default:
1338 return false;
1339 }
1340
1341 } else
1342
1343 REG_SET(OUTPUT_CSC_CONTROL, 0,
1344 OUTPUT_CSC_GRPH_MODE, 0);
1345
1346 return true;
1347}
1348
1349void dce110_opp_set_csc_adjustment(
1350 struct transform *xfm,
1351 const struct out_csc_color_matrix *tbl_entry)
1352{
1353 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1354 enum csc_color_mode config =
1355 CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1356
1357 program_color_matrix(
1358 xfm_dce, tbl_entry, GRPH_COLOR_MATRIX_SW);
1359
1360
1361 configure_graphics_mode(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW,
1362 tbl_entry->color_space);
1363}
1364
1365void dce110_opp_set_csc_default(
1366 struct transform *xfm,
1367 const struct default_adjustment *default_adjust)
1368{
1369 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1370 enum csc_color_mode config =
1371 CSC_COLOR_MODE_GRAPHICS_PREDEFINED;
1372
1373 if (default_adjust->force_hw_default == false) {
1374 const struct out_csc_color_matrix *elm;
1375
1376 enum grph_color_adjust_option option =
1377 GRPH_COLOR_MATRIX_HW_DEFAULT;
1378 uint32_t i;
1379
1380
1381
1382
1383
1384
1385 option = GRPH_COLOR_MATRIX_SW;
1386
1387 for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) {
1388 elm = &global_color_matrix[i];
1389 if (elm->color_space != default_adjust->out_color_space)
1390 continue;
1391
1392
1393 program_color_matrix(xfm_dce, elm, option);
1394 config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC;
1395 break;
1396 }
1397 }
1398
1399
1400
1401
1402
1403
1404 configure_graphics_mode(xfm_dce, config,
1405 default_adjust->csc_adjust_type,
1406 default_adjust->out_color_space);
1407}
1408
1409static void program_pwl(struct dce_transform *xfm_dce,
1410 const struct pwl_params *params)
1411{
1412 int retval;
1413 uint8_t max_tries = 10;
1414 uint8_t counter = 0;
1415 uint32_t i = 0;
1416 const struct pwl_result_data *rgb = params->rgb_resulted;
1417
1418
1419 if (REG(DCFE_MEM_PWR_CTRL))
1420 REG_UPDATE(DCFE_MEM_PWR_CTRL,
1421 DCP_REGAMMA_MEM_PWR_DIS, 1);
1422 else
1423 REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
1424 REGAMMA_LUT_LIGHT_SLEEP_DIS, 1);
1425
1426 while (counter < max_tries) {
1427 if (REG(DCFE_MEM_PWR_STATUS)) {
1428 REG_GET(DCFE_MEM_PWR_STATUS,
1429 DCP_REGAMMA_MEM_PWR_STATE,
1430 &retval);
1431
1432 if (retval == 0)
1433 break;
1434 ++counter;
1435 } else {
1436 REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL,
1437 REGAMMA_LUT_MEM_PWR_STATE,
1438 &retval);
1439
1440 if (retval == 0)
1441 break;
1442 ++counter;
1443 }
1444 }
1445
1446 if (counter == max_tries) {
1447 DC_LOG_WARNING("%s: regamma lut was not powered on "
1448 "in a timely manner,"
1449 " programming still proceeds\n",
1450 __func__);
1451 }
1452
1453 REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK,
1454 REGAMMA_LUT_WRITE_EN_MASK, 7);
1455
1456 REG_WRITE(REGAMMA_LUT_INDEX, 0);
1457
1458
1459 while (i != params->hw_points_num) {
1460
1461 REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg);
1462 REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg);
1463 REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg);
1464 REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg);
1465 REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg);
1466 REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg);
1467
1468 ++rgb;
1469 ++i;
1470 }
1471
1472
1473 if (REG(DCFE_MEM_PWR_CTRL))
1474 REG_UPDATE(DCFE_MEM_PWR_CTRL,
1475 DCP_REGAMMA_MEM_PWR_DIS, 0);
1476 else
1477 REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL,
1478 REGAMMA_LUT_LIGHT_SLEEP_DIS, 0);
1479}
1480
1481static void regamma_config_regions_and_segments(struct dce_transform *xfm_dce,
1482 const struct pwl_params *params)
1483{
1484 const struct gamma_curve *curve;
1485
1486 REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0,
1487 REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x,
1488 REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0);
1489
1490 REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0,
1491 REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope);
1492
1493 REG_SET(REGAMMA_CNTLA_END_CNTL1, 0,
1494 REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x);
1495
1496 REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0,
1497 REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y,
1498 REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_slope);
1499
1500 curve = params->arr_curve_points;
1501
1502 REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0,
1503 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1504 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1505 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1506 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1507 curve += 2;
1508
1509 REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0,
1510 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1511 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1512 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1513 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1514 curve += 2;
1515
1516 REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0,
1517 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1518 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1519 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1520 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1521 curve += 2;
1522
1523 REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0,
1524 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1525 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1526 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1527 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1528 curve += 2;
1529
1530 REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0,
1531 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1532 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1533 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1534 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1535 curve += 2;
1536
1537 REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0,
1538 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1539 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1540 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1541 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1542 curve += 2;
1543
1544 REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0,
1545 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1546 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1547 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1548 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1549 curve += 2;
1550
1551 REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0,
1552 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
1553 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
1554 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
1555 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
1556}
1557
1558
1559
1560void dce110_opp_program_regamma_pwl(struct transform *xfm,
1561 const struct pwl_params *params)
1562{
1563 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1564
1565
1566 regamma_config_regions_and_segments(xfm_dce, params);
1567
1568
1569 program_pwl(xfm_dce, params);
1570}
1571
1572void dce110_opp_power_on_regamma_lut(struct transform *xfm,
1573 bool power_on)
1574{
1575 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1576
1577 if (REG(DCFE_MEM_PWR_CTRL))
1578 REG_UPDATE_2(DCFE_MEM_PWR_CTRL,
1579 DCP_REGAMMA_MEM_PWR_DIS, power_on,
1580 DCP_LUT_MEM_PWR_DIS, power_on);
1581 else
1582 REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL,
1583 REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on,
1584 DCP_LUT_LIGHT_SLEEP_DIS, power_on);
1585
1586}
1587
1588void dce110_opp_set_regamma_mode(struct transform *xfm,
1589 enum opp_regamma mode)
1590{
1591 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
1592
1593 REG_SET(REGAMMA_CONTROL, 0,
1594 GRPH_REGAMMA_MODE, mode);
1595}
1596
1597static const struct transform_funcs dce_transform_funcs = {
1598 .transform_reset = dce_transform_reset,
1599 .transform_set_scaler = dce_transform_set_scaler,
1600 .transform_set_gamut_remap = dce_transform_set_gamut_remap,
1601 .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
1602 .opp_set_csc_default = dce110_opp_set_csc_default,
1603 .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
1604 .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
1605 .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
1606 .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth,
1607 .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps
1608};
1609
1610#if defined(CONFIG_DRM_AMD_DC_SI)
1611static const struct transform_funcs dce60_transform_funcs = {
1612 .transform_reset = dce_transform_reset,
1613 .transform_set_scaler = dce60_transform_set_scaler,
1614 .transform_set_gamut_remap = dce_transform_set_gamut_remap,
1615 .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment,
1616 .opp_set_csc_default = dce110_opp_set_csc_default,
1617 .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut,
1618 .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl,
1619 .opp_set_regamma_mode = dce110_opp_set_regamma_mode,
1620 .transform_set_pixel_storage_depth = dce60_transform_set_pixel_storage_depth,
1621 .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps
1622};
1623#endif
1624
1625
1626
1627
1628
1629void dce_transform_construct(
1630 struct dce_transform *xfm_dce,
1631 struct dc_context *ctx,
1632 uint32_t inst,
1633 const struct dce_transform_registers *regs,
1634 const struct dce_transform_shift *xfm_shift,
1635 const struct dce_transform_mask *xfm_mask)
1636{
1637 xfm_dce->base.ctx = ctx;
1638
1639 xfm_dce->base.inst = inst;
1640 xfm_dce->base.funcs = &dce_transform_funcs;
1641
1642 xfm_dce->regs = regs;
1643 xfm_dce->xfm_shift = xfm_shift;
1644 xfm_dce->xfm_mask = xfm_mask;
1645
1646 xfm_dce->prescaler_on = true;
1647 xfm_dce->lb_pixel_depth_supported =
1648 LB_PIXEL_DEPTH_18BPP |
1649 LB_PIXEL_DEPTH_24BPP |
1650 LB_PIXEL_DEPTH_30BPP |
1651 LB_PIXEL_DEPTH_36BPP;
1652
1653 xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1654 xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES;
1655}
1656
1657#if defined(CONFIG_DRM_AMD_DC_SI)
1658void dce60_transform_construct(
1659 struct dce_transform *xfm_dce,
1660 struct dc_context *ctx,
1661 uint32_t inst,
1662 const struct dce_transform_registers *regs,
1663 const struct dce_transform_shift *xfm_shift,
1664 const struct dce_transform_mask *xfm_mask)
1665{
1666 xfm_dce->base.ctx = ctx;
1667
1668 xfm_dce->base.inst = inst;
1669 xfm_dce->base.funcs = &dce60_transform_funcs;
1670
1671 xfm_dce->regs = regs;
1672 xfm_dce->xfm_shift = xfm_shift;
1673 xfm_dce->xfm_mask = xfm_mask;
1674
1675 xfm_dce->prescaler_on = true;
1676 xfm_dce->lb_pixel_depth_supported =
1677 LB_PIXEL_DEPTH_18BPP |
1678 LB_PIXEL_DEPTH_24BPP |
1679 LB_PIXEL_DEPTH_30BPP |
1680 LB_PIXEL_DEPTH_36BPP;
1681
1682 xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY;
1683 xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES;
1684}
1685#endif
1686