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