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