aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmy Zhang <Amy.Zhang@amd.com>2017-01-05 17:12:20 -0500
committerAlex Deucher <alexander.deucher@amd.com>2017-09-26 17:09:48 -0400
commitfcd2f4bf8bbe73ac860d1be275a22a54a8d8d385 (patch)
tree30a5335d72e4447205c7cef07e0c6a0a411edf43
parent457b74cb3773a1950e49c2d4826d1b295c59bdf1 (diff)
drm/amd/display: Output Transfer Function Regamma Refactor
- Create translation function to translate logical format to hw format - Refactor to use transfer function in dc instead of input gamma Signed-off-by: Amy Zhang <Amy.Zhang@amd.com> Acked-by: Harry Wentland <Harry.Wentland@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/calcs/Makefile2
-rw-r--r--drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c1481
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c440
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h20
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/opp.h2
-rw-r--r--drivers/gpu/drm/amd/display/include/fixed31_32.h8
9 files changed, 466 insertions, 1517 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
index 5a6e46843502..546ed67c6f83 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
@@ -246,6 +246,15 @@ struct fixed31_32 dal_fixed31_32_add(
246 return res; 246 return res;
247} 247}
248 248
249struct fixed31_32 dal_fixed31_32_add_int(
250 struct fixed31_32 arg1,
251 int32_t arg2)
252{
253 return dal_fixed31_32_add(
254 arg1,
255 dal_fixed31_32_from_int(arg2));
256}
257
249struct fixed31_32 dal_fixed31_32_sub_int( 258struct fixed31_32 dal_fixed31_32_sub_int(
250 struct fixed31_32 arg1, 259 struct fixed31_32 arg1,
251 int32_t arg2) 260 int32_t arg2)
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile
index 4001933e7808..4bb08aea6a03 100644
--- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile
@@ -3,7 +3,7 @@
3# It calculates Bandwidth and Watermarks values for HW programming 3# It calculates Bandwidth and Watermarks values for HW programming
4# 4#
5 5
6BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o 6BW_CALCS = bandwidth_calcs.o bw_fixed.o
7 7
8AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) 8AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
9 9
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
deleted file mode 100644
index fd300db833c7..000000000000
--- a/drivers/gpu/drm/amd/display/dc/calcs/gamma_calcs.c
+++ /dev/null
@@ -1,1481 +0,0 @@
1/*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26#include "dm_services.h"
27#include "gamma_calcs.h"
28
29struct curve_config {
30 uint32_t offset;
31 int8_t segments[16];
32 int8_t begin;
33};
34
35static bool build_custom_float(
36 struct fixed31_32 value,
37 const struct custom_float_format *format,
38 bool *negative,
39 uint32_t *mantissa,
40 uint32_t *exponenta)
41{
42 uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
43
44 const struct fixed31_32 mantissa_constant_plus_max_fraction =
45 dal_fixed31_32_from_fraction(
46 (1LL << (format->mantissa_bits + 1)) - 1,
47 1LL << format->mantissa_bits);
48
49 struct fixed31_32 mantiss;
50
51 if (dal_fixed31_32_eq(
52 value,
53 dal_fixed31_32_zero)) {
54 *negative = false;
55 *mantissa = 0;
56 *exponenta = 0;
57 return true;
58 }
59
60 if (dal_fixed31_32_lt(
61 value,
62 dal_fixed31_32_zero)) {
63 *negative = format->sign;
64 value = dal_fixed31_32_neg(value);
65 } else {
66 *negative = false;
67 }
68
69 if (dal_fixed31_32_lt(
70 value,
71 dal_fixed31_32_one)) {
72 uint32_t i = 1;
73
74 do {
75 value = dal_fixed31_32_shl(value, 1);
76 ++i;
77 } while (dal_fixed31_32_lt(
78 value,
79 dal_fixed31_32_one));
80
81 --i;
82
83 if (exp_offset <= i) {
84 *mantissa = 0;
85 *exponenta = 0;
86 return true;
87 }
88
89 *exponenta = exp_offset - i;
90 } else if (dal_fixed31_32_le(
91 mantissa_constant_plus_max_fraction,
92 value)) {
93 uint32_t i = 1;
94
95 do {
96 value = dal_fixed31_32_shr(value, 1);
97 ++i;
98 } while (dal_fixed31_32_lt(
99 mantissa_constant_plus_max_fraction,
100 value));
101
102 *exponenta = exp_offset + i - 1;
103 } else {
104 *exponenta = exp_offset;
105 }
106
107 mantiss = dal_fixed31_32_sub(
108 value,
109 dal_fixed31_32_one);
110
111 if (dal_fixed31_32_lt(
112 mantiss,
113 dal_fixed31_32_zero) ||
114 dal_fixed31_32_lt(
115 dal_fixed31_32_one,
116 mantiss))
117 mantiss = dal_fixed31_32_zero;
118 else
119 mantiss = dal_fixed31_32_shl(
120 mantiss,
121 format->mantissa_bits);
122
123 *mantissa = dal_fixed31_32_floor(mantiss);
124
125 return true;
126}
127
128static bool setup_custom_float(
129 const struct custom_float_format *format,
130 bool negative,
131 uint32_t mantissa,
132 uint32_t exponenta,
133 uint32_t *result)
134{
135 uint32_t i = 0;
136 uint32_t j = 0;
137
138 uint32_t value = 0;
139
140 /* verification code:
141 * once calculation is ok we can remove it
142 */
143
144 const uint32_t mantissa_mask =
145 (1 << (format->mantissa_bits + 1)) - 1;
146
147 const uint32_t exponenta_mask =
148 (1 << (format->exponenta_bits + 1)) - 1;
149
150 if (mantissa & ~mantissa_mask) {
151 BREAK_TO_DEBUGGER();
152 mantissa = mantissa_mask;
153 }
154
155 if (exponenta & ~exponenta_mask) {
156 BREAK_TO_DEBUGGER();
157 exponenta = exponenta_mask;
158 }
159
160 /* end of verification code */
161
162 while (i < format->mantissa_bits) {
163 uint32_t mask = 1 << i;
164
165 if (mantissa & mask)
166 value |= mask;
167
168 ++i;
169 }
170
171 while (j < format->exponenta_bits) {
172 uint32_t mask = 1 << j;
173
174 if (exponenta & mask)
175 value |= mask << i;
176
177 ++j;
178 }
179
180 if (negative && format->sign)
181 value |= 1 << (i + j);
182
183 *result = value;
184
185 return true;
186}
187
188static bool build_hw_curve_configuration(
189 const struct curve_config *curve_config,
190 struct gamma_curve *gamma_curve,
191 struct curve_points *curve_points,
192 struct hw_x_point *points,
193 uint32_t *number_of_points)
194{
195 const int8_t max_regions_number = ARRAY_SIZE(curve_config->segments);
196
197 int8_t i;
198
199 uint8_t segments_calculation[8] = { 0 };
200
201 struct fixed31_32 region1 = dal_fixed31_32_zero;
202 struct fixed31_32 region2;
203 struct fixed31_32 increment;
204
205 uint32_t index = 0;
206 uint32_t segments = 0;
207 uint32_t max_number;
208
209 int8_t num_regions = 0;
210
211 bool result = false;
212
213 if (!number_of_points) {
214 BREAK_TO_DEBUGGER();
215 return false;
216 }
217
218 max_number = *number_of_points;
219
220 i = 0;
221
222 while (i != max_regions_number) {
223 gamma_curve[i].offset = 0;
224 gamma_curve[i].segments_num = 0;
225
226 ++i;
227 }
228
229 i = 0;
230
231 while (i != max_regions_number) {
232 /* number should go in uninterruptible sequence */
233 if (curve_config->segments[i] == -1)
234 break;
235
236 ASSERT(curve_config->segments[i] >= 0);
237
238 segments += (1 << curve_config->segments[i]);
239 ++num_regions;
240
241 ++i;
242 }
243
244 if (segments > max_number) {
245 BREAK_TO_DEBUGGER();
246 } else {
247 int32_t divisor;
248 uint32_t offset = 0;
249 int8_t begin = curve_config->begin;
250 int32_t region_number = 0;
251
252 i = begin;
253
254 while ((index < max_number) &&
255 (region_number < max_regions_number) &&
256 (i < (begin + num_regions))) {
257 int32_t j = 0;
258
259 segments = curve_config->segments[region_number];
260 divisor = 1 << segments;
261
262 if (segments == -1) {
263 if (i > 0) {
264 region1 = dal_fixed31_32_shl(
265 dal_fixed31_32_one,
266 i - 1);
267 region2 = dal_fixed31_32_shl(
268 dal_fixed31_32_one,
269 i);
270 } else {
271 region1 = dal_fixed31_32_shr(
272 dal_fixed31_32_one,
273 -(i - 1));
274 region2 = dal_fixed31_32_shr(
275 dal_fixed31_32_one,
276 -i);
277 }
278
279 break;
280 }
281
282 if (i > -1) {
283 region1 = dal_fixed31_32_shl(
284 dal_fixed31_32_one,
285 i);
286 region2 = dal_fixed31_32_shl(
287 dal_fixed31_32_one,
288 i + 1);
289 } else {
290 region1 = dal_fixed31_32_shr(
291 dal_fixed31_32_one,
292 -i);
293 region2 = dal_fixed31_32_shr(
294 dal_fixed31_32_one,
295 -(i + 1));
296 }
297
298 gamma_curve[region_number].offset = offset;
299 gamma_curve[region_number].segments_num = segments;
300
301 offset += divisor;
302
303 ++segments_calculation[segments];
304
305 increment = dal_fixed31_32_div_int(
306 dal_fixed31_32_sub(
307 region2,
308 region1),
309 divisor);
310
311 points[index].x = region1;
312 points[index].adjusted_x = region1;
313
314 ++index;
315 ++region_number;
316
317 while ((index < max_number) && (j < divisor - 1)) {
318 region1 = dal_fixed31_32_add(
319 region1,
320 increment);
321
322 points[index].x = region1;
323 points[index].adjusted_x = region1;
324
325 ++index;
326 ++j;
327 }
328
329 ++i;
330 }
331
332 points[index].x = region1;
333 points[index].adjusted_x = region1;
334
335 *number_of_points = index;
336
337 result = true;
338 }
339
340 curve_points[0].x = points[0].adjusted_x;
341 curve_points[0].offset = dal_fixed31_32_zero;
342
343 curve_points[1].x = points[index - 1].adjusted_x;
344 curve_points[1].offset = dal_fixed31_32_zero;
345
346 curve_points[2].x = points[index].adjusted_x;
347 curve_points[2].offset = dal_fixed31_32_zero;
348
349 return result;
350}
351
352static bool setup_distribution_points_pq(
353 struct gamma_curve *arr_curve_points,
354 struct curve_points *arr_points,
355 uint32_t *hw_points_num,
356 struct hw_x_point *coordinates_x,
357 enum surface_pixel_format format)
358{
359 struct curve_config cfg;
360
361 cfg.offset = 0;
362 cfg.segments[0] = 2;
363 cfg.segments[1] = 2;
364 cfg.segments[2] = 2;
365 cfg.segments[3] = 2;
366 cfg.segments[4] = 2;
367 cfg.segments[5] = 2;
368 cfg.segments[6] = 3;
369 cfg.segments[7] = 4;
370 cfg.segments[8] = 4;
371 cfg.segments[9] = 4;
372 cfg.segments[10] = 4;
373 cfg.segments[11] = 5;
374 cfg.segments[12] = 5;
375 cfg.segments[13] = 5;
376 cfg.segments[14] = 5;
377 cfg.segments[15] = 5;
378
379 if (format == SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F ||
380 format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F)
381 cfg.begin = -11;
382 else
383 cfg.begin = -16;
384
385 if (!build_hw_curve_configuration(
386 &cfg, arr_curve_points,
387 arr_points,
388 coordinates_x, hw_points_num)) {
389 ASSERT_CRITICAL(false);
390 return false;
391 }
392 return true;
393}
394
395static bool setup_distribution_points(
396 struct gamma_curve *arr_curve_points,
397 struct curve_points *arr_points,
398 uint32_t *hw_points_num,
399 struct hw_x_point *coordinates_x)
400{
401 struct curve_config cfg;
402
403 cfg.offset = 0;
404 cfg.segments[0] = 3;
405 cfg.segments[1] = 4;
406 cfg.segments[2] = 4;
407 cfg.segments[3] = 4;
408 cfg.segments[4] = 4;
409 cfg.segments[5] = 4;
410 cfg.segments[6] = 4;
411 cfg.segments[7] = 4;
412 cfg.segments[8] = 5;
413 cfg.segments[9] = 5;
414 cfg.segments[10] = 0;
415 cfg.segments[11] = -1;
416 cfg.segments[12] = -1;
417 cfg.segments[13] = -1;
418 cfg.segments[14] = -1;
419 cfg.segments[15] = -1;
420
421 cfg.begin = -10;
422
423 if (!build_hw_curve_configuration(
424 &cfg, arr_curve_points,
425 arr_points,
426 coordinates_x, hw_points_num)) {
427 ASSERT_CRITICAL(false);
428 return false;
429 }
430 return true;
431}
432
433struct dividers {
434 struct fixed31_32 divider1;
435 struct fixed31_32 divider2;
436 struct fixed31_32 divider3;
437};
438
439static void build_regamma_coefficients(struct gamma_coefficients *coefficients)
440{
441 /* sRGB should apply 2.4 */
442 static const int32_t numerator01[3] = { 31308, 31308, 31308 };
443 static const int32_t numerator02[3] = { 12920, 12920, 12920 };
444 static const int32_t numerator03[3] = { 55, 55, 55 };
445 static const int32_t numerator04[3] = { 55, 55, 55 };
446 static const int32_t numerator05[3] = { 2400, 2400, 2400 };
447
448 const int32_t *numerator1;
449 const int32_t *numerator2;
450 const int32_t *numerator3;
451 const int32_t *numerator4;
452 const int32_t *numerator5;
453
454 uint32_t i = 0;
455
456 numerator1 = numerator01;
457 numerator2 = numerator02;
458 numerator3 = numerator03;
459 numerator4 = numerator04;
460 numerator5 = numerator05;
461
462 do {
463 coefficients->a0[i] = dal_fixed31_32_from_fraction(
464 numerator1[i], 10000000);
465 coefficients->a1[i] = dal_fixed31_32_from_fraction(
466 numerator2[i], 1000);
467 coefficients->a2[i] = dal_fixed31_32_from_fraction(
468 numerator3[i], 1000);
469 coefficients->a3[i] = dal_fixed31_32_from_fraction(
470 numerator4[i], 1000);
471 coefficients->user_gamma[i] = dal_fixed31_32_from_fraction(
472 numerator5[i], 1000);
473
474 ++i;
475 } while (i != ARRAY_SIZE(coefficients->a0));
476}
477
478static struct fixed31_32 translate_from_linear_space(
479 struct fixed31_32 arg,
480 struct fixed31_32 a0,
481 struct fixed31_32 a1,
482 struct fixed31_32 a2,
483 struct fixed31_32 a3,
484 struct fixed31_32 gamma)
485{
486 const struct fixed31_32 one = dal_fixed31_32_from_int(1);
487
488 if (dal_fixed31_32_le(arg, dal_fixed31_32_neg(a0)))
489 return dal_fixed31_32_sub(
490 a2,
491 dal_fixed31_32_mul(
492 dal_fixed31_32_add(
493 one,
494 a3),
495 dal_fixed31_32_pow(
496 dal_fixed31_32_neg(arg),
497 dal_fixed31_32_recip(gamma))));
498 else if (dal_fixed31_32_le(a0, arg))
499 return dal_fixed31_32_sub(
500 dal_fixed31_32_mul(
501 dal_fixed31_32_add(
502 one,
503 a3),
504 dal_fixed31_32_pow(
505 arg,
506 dal_fixed31_32_recip(gamma))),
507 a2);
508 else
509 return dal_fixed31_32_mul(
510 arg,
511 a1);
512}
513
514static inline struct fixed31_32 translate_from_linear_space_ex(
515 struct fixed31_32 arg,
516 struct gamma_coefficients *coeff,
517 uint32_t color_index)
518{
519 return translate_from_linear_space(
520 arg,
521 coeff->a0[color_index],
522 coeff->a1[color_index],
523 coeff->a2[color_index],
524 coeff->a3[color_index],
525 coeff->user_gamma[color_index]);
526}
527
528static bool find_software_points(
529 const struct gamma_pixel *axis_x_256,
530 struct fixed31_32 hw_point,
531 enum channel_name channel,
532 uint32_t *index_to_start,
533 uint32_t *index_left,
534 uint32_t *index_right,
535 enum hw_point_position *pos)
536{
537 const uint32_t max_number = INPUT_LUT_ENTRIES + 3;
538
539 struct fixed31_32 left, right;
540
541 uint32_t i = *index_to_start;
542
543 while (i < max_number) {
544 if (channel == CHANNEL_NAME_RED) {
545 left = axis_x_256[i].r;
546
547 if (i < max_number - 1)
548 right = axis_x_256[i + 1].r;
549 else
550 right = axis_x_256[max_number - 1].r;
551 } else if (channel == CHANNEL_NAME_GREEN) {
552 left = axis_x_256[i].g;
553
554 if (i < max_number - 1)
555 right = axis_x_256[i + 1].g;
556 else
557 right = axis_x_256[max_number - 1].g;
558 } else {
559 left = axis_x_256[i].b;
560
561 if (i < max_number - 1)
562 right = axis_x_256[i + 1].b;
563 else
564 right = axis_x_256[max_number - 1].b;
565 }
566
567 if (dal_fixed31_32_le(left, hw_point) &&
568 dal_fixed31_32_le(hw_point, right)) {
569 *index_to_start = i;
570 *index_left = i;
571
572 if (i < max_number - 1)
573 *index_right = i + 1;
574 else
575 *index_right = max_number - 1;
576
577 *pos = HW_POINT_POSITION_MIDDLE;
578
579 return true;
580 } else if ((i == *index_to_start) &&
581 dal_fixed31_32_le(hw_point, left)) {
582 *index_to_start = i;
583 *index_left = i;
584 *index_right = i;
585
586 *pos = HW_POINT_POSITION_LEFT;
587
588 return true;
589 } else if ((i == max_number - 1) &&
590 dal_fixed31_32_le(right, hw_point)) {
591 *index_to_start = i;
592 *index_left = i;
593 *index_right = i;
594
595 *pos = HW_POINT_POSITION_RIGHT;
596
597 return true;
598 }
599
600 ++i;
601 }
602
603 return false;
604}
605
606static bool build_custom_gamma_mapping_coefficients_worker(
607 struct pixel_gamma_point *coeff,
608 const struct hw_x_point *coordinates_x,
609 const struct gamma_pixel *axis_x_256,
610 enum channel_name channel,
611 uint32_t number_of_points,
612 enum surface_pixel_format pixel_format)
613{
614 uint32_t i = 0;
615
616 while (i <= number_of_points) {
617 struct fixed31_32 coord_x;
618
619 uint32_t index_to_start = 0;
620 uint32_t index_left = 0;
621 uint32_t index_right = 0;
622
623 enum hw_point_position hw_pos;
624
625 struct gamma_point *point;
626
627 struct fixed31_32 left_pos;
628 struct fixed31_32 right_pos;
629
630 /*
631 * TODO: confirm enum in surface_pixel_format
632 * if (pixel_format == PIXEL_FORMAT_FP16)
633 *coord_x = coordinates_x[i].adjusted_x;
634 *else
635 */
636 if (channel == CHANNEL_NAME_RED)
637 coord_x = coordinates_x[i].regamma_y_red;
638 else if (channel == CHANNEL_NAME_GREEN)
639 coord_x = coordinates_x[i].regamma_y_green;
640 else
641 coord_x = coordinates_x[i].regamma_y_blue;
642
643 if (!find_software_points(
644 axis_x_256, coord_x, channel,
645 &index_to_start, &index_left, &index_right, &hw_pos)) {
646 BREAK_TO_DEBUGGER();
647 return false;
648 }
649
650 if (index_left >= INPUT_LUT_ENTRIES + 3) {
651 BREAK_TO_DEBUGGER();
652 return false;
653 }
654
655 if (index_right >= INPUT_LUT_ENTRIES + 3) {
656 BREAK_TO_DEBUGGER();
657 return false;
658 }
659
660 if (channel == CHANNEL_NAME_RED) {
661 point = &coeff[i].r;
662
663 left_pos = axis_x_256[index_left].r;
664 right_pos = axis_x_256[index_right].r;
665 } else if (channel == CHANNEL_NAME_GREEN) {
666 point = &coeff[i].g;
667
668 left_pos = axis_x_256[index_left].g;
669 right_pos = axis_x_256[index_right].g;
670 } else {
671 point = &coeff[i].b;
672
673 left_pos = axis_x_256[index_left].b;
674 right_pos = axis_x_256[index_right].b;
675 }
676
677 if (hw_pos == HW_POINT_POSITION_MIDDLE)
678 point->coeff = dal_fixed31_32_div(
679 dal_fixed31_32_sub(
680 coord_x,
681 left_pos),
682 dal_fixed31_32_sub(
683 right_pos,
684 left_pos));
685 else if (hw_pos == HW_POINT_POSITION_LEFT)
686 point->coeff = dal_fixed31_32_zero;
687 else if (hw_pos == HW_POINT_POSITION_RIGHT)
688 point->coeff = dal_fixed31_32_from_int(2);
689 else {
690 BREAK_TO_DEBUGGER();
691 return false;
692 }
693
694 point->left_index = index_left;
695 point->right_index = index_right;
696 point->pos = hw_pos;
697
698 ++i;
699 }
700
701 return true;
702}
703
704static inline bool build_oem_custom_gamma_mapping_coefficients(
705 struct pixel_gamma_point *coeff128_oem,
706 const struct hw_x_point *coordinates_x,
707 const struct gamma_pixel *axis_x_256,
708 uint32_t number_of_points,
709 enum surface_pixel_format pixel_format)
710{
711 int i;
712
713 for (i = 0; i < 3; i++) {
714 if (!build_custom_gamma_mapping_coefficients_worker(
715 coeff128_oem, coordinates_x, axis_x_256, i,
716 number_of_points, pixel_format))
717 return false;
718 }
719 return true;
720}
721
722static struct fixed31_32 calculate_mapped_value(
723 struct pwl_float_data *rgb,
724 const struct pixel_gamma_point *coeff,
725 enum channel_name channel,
726 uint32_t max_index)
727{
728 const struct gamma_point *point;
729
730 struct fixed31_32 result;
731
732 if (channel == CHANNEL_NAME_RED)
733 point = &coeff->r;
734 else if (channel == CHANNEL_NAME_GREEN)
735 point = &coeff->g;
736 else
737 point = &coeff->b;
738
739 if ((point->left_index < 0) || (point->left_index > max_index)) {
740 BREAK_TO_DEBUGGER();
741 return dal_fixed31_32_zero;
742 }
743
744 if ((point->right_index < 0) || (point->right_index > max_index)) {
745 BREAK_TO_DEBUGGER();
746 return dal_fixed31_32_zero;
747 }
748
749 if (point->pos == HW_POINT_POSITION_MIDDLE)
750 if (channel == CHANNEL_NAME_RED)
751 result = dal_fixed31_32_add(
752 dal_fixed31_32_mul(
753 point->coeff,
754 dal_fixed31_32_sub(
755 rgb[point->right_index].r,
756 rgb[point->left_index].r)),
757 rgb[point->left_index].r);
758 else if (channel == CHANNEL_NAME_GREEN)
759 result = dal_fixed31_32_add(
760 dal_fixed31_32_mul(
761 point->coeff,
762 dal_fixed31_32_sub(
763 rgb[point->right_index].g,
764 rgb[point->left_index].g)),
765 rgb[point->left_index].g);
766 else
767 result = dal_fixed31_32_add(
768 dal_fixed31_32_mul(
769 point->coeff,
770 dal_fixed31_32_sub(
771 rgb[point->right_index].b,
772 rgb[point->left_index].b)),
773 rgb[point->left_index].b);
774 else if (point->pos == HW_POINT_POSITION_LEFT) {
775 BREAK_TO_DEBUGGER();
776 result = dal_fixed31_32_zero;
777 } else {
778 BREAK_TO_DEBUGGER();
779 result = dal_fixed31_32_one;
780 }
781
782 return result;
783}
784
785static inline struct fixed31_32 calculate_oem_mapped_value(
786 struct pwl_float_data *rgb_oem,
787 const struct pixel_gamma_point *coeff,
788 uint32_t index,
789 enum channel_name channel,
790 uint32_t max_index)
791{
792 return calculate_mapped_value(
793 rgb_oem,
794 coeff + index,
795 channel,
796 max_index);
797}
798
799static void compute_pq(struct fixed31_32 in_x, struct fixed31_32 *out_y)
800{
801 /* consts for PQ gamma formula. */
802 const struct fixed31_32 m1 =
803 dal_fixed31_32_from_fraction(159301758, 1000000000);
804 const struct fixed31_32 m2 =
805 dal_fixed31_32_from_fraction(7884375, 100000);
806 const struct fixed31_32 c1 =
807 dal_fixed31_32_from_fraction(8359375, 10000000);
808 const struct fixed31_32 c2 =
809 dal_fixed31_32_from_fraction(188515625, 10000000);
810 const struct fixed31_32 c3 =
811 dal_fixed31_32_from_fraction(186875, 10000);
812
813 struct fixed31_32 l_pow_m1;
814 struct fixed31_32 base;
815
816 if (dal_fixed31_32_lt(in_x, dal_fixed31_32_zero))
817 in_x = dal_fixed31_32_zero;
818
819 l_pow_m1 = dal_fixed31_32_pow(in_x, m1);
820 base = dal_fixed31_32_div(
821 dal_fixed31_32_add(c1,
822 (dal_fixed31_32_mul(c2, l_pow_m1))),
823 dal_fixed31_32_add(dal_fixed31_32_one,
824 (dal_fixed31_32_mul(c3, l_pow_m1))));
825 *out_y = dal_fixed31_32_pow(base, m2);
826}
827
828static void build_regamma_curve_pq(struct pwl_float_data_ex *rgb_regamma,
829 struct pwl_float_data *rgb_oem,
830 struct pixel_gamma_point *coeff128_oem,
831 const struct core_gamma *ramp,
832 const struct core_surface *surface,
833 uint32_t hw_points_num,
834 const struct hw_x_point *coordinate_x,
835 const struct gamma_pixel *axis_x,
836 struct dividers dividers)
837{
838 uint32_t i;
839
840 struct pwl_float_data_ex *rgb = rgb_regamma;
841 const struct hw_x_point *coord_x = coordinate_x;
842 struct fixed31_32 x;
843 struct fixed31_32 output;
844 struct fixed31_32 scaling_factor =
845 dal_fixed31_32_from_fraction(8, 1000);
846
847 /* use coord_x to retrieve coordinates chosen base on given user curve
848 * the x values are exponentially distributed and currently it is hard
849 * coded, the user curve shape is ignored. Need to recalculate coord_x
850 * based on input curve, translation from 256/1025 to 128 PWL points.
851 */
852 for (i = 0; i <= hw_points_num; i++) {
853 /* Multiply 0.008 as regamma is 0-1 and FP16 input is 0-125.
854 * FP 1.0 = 80nits
855 */
856 x = dal_fixed31_32_mul(coord_x->adjusted_x, scaling_factor);
857
858 compute_pq(x, &output);
859
860 /* should really not happen? */
861 if (dal_fixed31_32_lt(output, dal_fixed31_32_zero))
862 output = dal_fixed31_32_zero;
863 else if (dal_fixed31_32_lt(dal_fixed31_32_one, output))
864 output = dal_fixed31_32_one;
865
866 rgb->r = output;
867 rgb->g = output;
868 rgb->b = output;
869
870 ++coord_x;
871 ++rgb;
872 }
873}
874
875static void build_regamma_curve(struct pwl_float_data_ex *rgb_regamma,
876 struct pwl_float_data *rgb_oem,
877 struct pixel_gamma_point *coeff128_oem,
878 const struct core_gamma *ramp,
879 const struct core_surface *surface,
880 uint32_t hw_points_num,
881 const struct hw_x_point *coordinate_x,
882 const struct gamma_pixel *axis_x,
883 struct dividers dividers)
884{
885 uint32_t i;
886
887 struct gamma_coefficients coeff;
888 struct pwl_float_data_ex *rgb = rgb_regamma;
889 const struct hw_x_point *coord_x = coordinate_x;
890
891 build_regamma_coefficients(&coeff);
892
893 /* Use opp110->regamma.coordinates_x to retrieve
894 * coordinates chosen base on given user curve (future task).
895 * The x values are exponentially distributed and currently
896 * it is hard-coded, the user curve shape is ignored.
897 * The future task is to recalculate opp110-
898 * regamma.coordinates_x based on input/user curve,
899 * translation from 256/1025 to 128 pwl points.
900 */
901
902 i = 0;
903
904 while (i != hw_points_num + 1) {
905 rgb->r = translate_from_linear_space_ex(
906 coord_x->adjusted_x, &coeff, 0);
907 rgb->g = translate_from_linear_space_ex(
908 coord_x->adjusted_x, &coeff, 1);
909 rgb->b = translate_from_linear_space_ex(
910 coord_x->adjusted_x, &coeff, 2);
911
912 ++coord_x;
913 ++rgb;
914 ++i;
915 }
916}
917
918static bool scale_gamma(struct pwl_float_data *pwl_rgb,
919 const struct core_gamma *ramp,
920 struct dividers dividers)
921{
922 const struct dc_gamma *gamma = &ramp->public;
923 const uint16_t max_driver = 0xFFFF;
924 const uint16_t max_os = 0xFF00;
925 uint16_t scaler = max_os;
926 uint32_t i = 0;
927 struct pwl_float_data *rgb = pwl_rgb;
928 struct pwl_float_data *rgb_last = rgb + INPUT_LUT_ENTRIES - 1;
929
930 do {
931 if ((gamma->red[i] > max_os) ||
932 (gamma->green[i] > max_os) ||
933 (gamma->blue[i] > max_os)) {
934 scaler = max_driver;
935 break;
936 }
937 ++i;
938 } while (i != INPUT_LUT_ENTRIES);
939
940 i = 0;
941
942 do {
943 rgb->r = dal_fixed31_32_from_fraction(
944 gamma->red[i], scaler);
945 rgb->g = dal_fixed31_32_from_fraction(
946 gamma->green[i], scaler);
947 rgb->b = dal_fixed31_32_from_fraction(
948 gamma->blue[i], scaler);
949
950 ++rgb;
951 ++i;
952 } while (i != INPUT_LUT_ENTRIES);
953
954 rgb->r = dal_fixed31_32_mul(rgb_last->r,
955 dividers.divider1);
956 rgb->g = dal_fixed31_32_mul(rgb_last->g,
957 dividers.divider1);
958 rgb->b = dal_fixed31_32_mul(rgb_last->b,
959 dividers.divider1);
960
961 ++rgb;
962
963 rgb->r = dal_fixed31_32_mul(rgb_last->r,
964 dividers.divider2);
965 rgb->g = dal_fixed31_32_mul(rgb_last->g,
966 dividers.divider2);
967 rgb->b = dal_fixed31_32_mul(rgb_last->b,
968 dividers.divider2);
969
970 ++rgb;
971
972 rgb->r = dal_fixed31_32_mul(rgb_last->r,
973 dividers.divider3);
974 rgb->g = dal_fixed31_32_mul(rgb_last->g,
975 dividers.divider3);
976 rgb->b = dal_fixed31_32_mul(rgb_last->b,
977 dividers.divider3);
978
979 return true;
980}
981
982static void build_evenly_distributed_points(
983 struct gamma_pixel *points,
984 uint32_t numberof_points,
985 struct fixed31_32 max_value,
986 struct dividers dividers)
987{
988 struct gamma_pixel *p = points;
989 struct gamma_pixel *p_last = p + numberof_points - 1;
990
991 uint32_t i = 0;
992
993 do {
994 struct fixed31_32 value = dal_fixed31_32_div_int(
995 dal_fixed31_32_mul_int(max_value, i),
996 numberof_points - 1);
997
998 p->r = value;
999 p->g = value;
1000 p->b = value;
1001
1002 ++p;
1003 ++i;
1004 } while (i != numberof_points);
1005
1006 p->r = dal_fixed31_32_div(p_last->r, dividers.divider1);
1007 p->g = dal_fixed31_32_div(p_last->g, dividers.divider1);
1008 p->b = dal_fixed31_32_div(p_last->b, dividers.divider1);
1009
1010 ++p;
1011
1012 p->r = dal_fixed31_32_div(p_last->r, dividers.divider2);
1013 p->g = dal_fixed31_32_div(p_last->g, dividers.divider2);
1014 p->b = dal_fixed31_32_div(p_last->b, dividers.divider2);
1015
1016 ++p;
1017
1018 p->r = dal_fixed31_32_div(p_last->r, dividers.divider3);
1019 p->g = dal_fixed31_32_div(p_last->g, dividers.divider3);
1020 p->b = dal_fixed31_32_div(p_last->b, dividers.divider3);
1021}
1022
1023static inline void copy_rgb_regamma_to_coordinates_x(
1024 struct hw_x_point *coordinates_x,
1025 uint32_t hw_points_num,
1026 const struct pwl_float_data_ex *rgb_ex)
1027{
1028 struct hw_x_point *coords = coordinates_x;
1029 uint32_t i = 0;
1030 const struct pwl_float_data_ex *rgb_regamma = rgb_ex;
1031
1032 while (i <= hw_points_num) {
1033 coords->regamma_y_red = rgb_regamma->r;
1034 coords->regamma_y_green = rgb_regamma->g;
1035 coords->regamma_y_blue = rgb_regamma->b;
1036
1037 ++coords;
1038 ++rgb_regamma;
1039 ++i;
1040 }
1041}
1042
1043static bool calculate_interpolated_hardware_curve(
1044 struct pwl_result_data *rgb,
1045 struct pixel_gamma_point *coeff128,
1046 struct pwl_float_data *rgb_user,
1047 const struct hw_x_point *coordinates_x,
1048 const struct gamma_pixel *axis_x_256,
1049 uint32_t number_of_points,
1050 enum surface_pixel_format pixel_format)
1051{
1052
1053 const struct pixel_gamma_point *coeff;
1054 struct pixel_gamma_point *coeff_128 = coeff128;
1055 uint32_t max_entries = 3 - 1;
1056 struct pwl_result_data *rgb_resulted = rgb;
1057
1058 uint32_t i = 0;
1059
1060 if (!build_oem_custom_gamma_mapping_coefficients(
1061 coeff_128, coordinates_x, axis_x_256,
1062 number_of_points,
1063 pixel_format))
1064 return false;
1065
1066 coeff = coeff128;
1067 max_entries += INPUT_LUT_ENTRIES;
1068
1069 /* TODO: float point case */
1070
1071 while (i <= number_of_points) {
1072 rgb_resulted->red = calculate_mapped_value(
1073 rgb_user, coeff, CHANNEL_NAME_RED, max_entries);
1074 rgb_resulted->green = calculate_mapped_value(
1075 rgb_user, coeff, CHANNEL_NAME_GREEN, max_entries);
1076 rgb_resulted->blue = calculate_mapped_value(
1077 rgb_user, coeff, CHANNEL_NAME_BLUE, max_entries);
1078
1079 ++coeff;
1080 ++rgb_resulted;
1081 ++i;
1082 }
1083
1084 return true;
1085}
1086
1087static bool map_regamma_hw_to_x_user(
1088 struct pixel_gamma_point *coeff128,
1089 struct pwl_float_data *rgb_oem,
1090 struct pwl_result_data *rgb_resulted,
1091 struct pwl_float_data *rgb_user,
1092 struct hw_x_point *coords_x,
1093 const struct gamma_pixel *axis_x,
1094 const struct dc_gamma *gamma,
1095 const struct pwl_float_data_ex *rgb_regamma,
1096 struct dividers dividers,
1097 uint32_t hw_points_num,
1098 const struct core_surface *surface)
1099{
1100 /* setup to spare calculated ideal regamma values */
1101
1102 struct pixel_gamma_point *coeff = coeff128;
1103
1104 struct hw_x_point *coords = coords_x;
1105
1106 copy_rgb_regamma_to_coordinates_x(coords, hw_points_num, rgb_regamma);
1107
1108 return calculate_interpolated_hardware_curve(
1109 rgb_resulted, coeff, rgb_user, coords, axis_x,
1110 hw_points_num, surface->public.format);
1111}
1112
1113static void build_new_custom_resulted_curve(
1114 struct pwl_result_data *rgb_resulted,
1115 uint32_t hw_points_num)
1116{
1117 struct pwl_result_data *rgb = rgb_resulted;
1118 struct pwl_result_data *rgb_plus_1 = rgb + 1;
1119
1120 uint32_t i;
1121
1122 i = 0;
1123
1124 while (i != hw_points_num + 1) {
1125 rgb->red = dal_fixed31_32_clamp(
1126 rgb->red, dal_fixed31_32_zero,
1127 dal_fixed31_32_one);
1128 rgb->green = dal_fixed31_32_clamp(
1129 rgb->green, dal_fixed31_32_zero,
1130 dal_fixed31_32_one);
1131 rgb->blue = dal_fixed31_32_clamp(
1132 rgb->blue, dal_fixed31_32_zero,
1133 dal_fixed31_32_one);
1134
1135 ++rgb;
1136 ++i;
1137 }
1138
1139 rgb = rgb_resulted;
1140
1141 i = 1;
1142
1143 while (i != hw_points_num + 1) {
1144 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
1145 rgb_plus_1->red = rgb->red;
1146 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
1147 rgb_plus_1->green = rgb->green;
1148 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
1149 rgb_plus_1->blue = rgb->blue;
1150
1151 rgb->delta_red = dal_fixed31_32_sub(
1152 rgb_plus_1->red,
1153 rgb->red);
1154 rgb->delta_green = dal_fixed31_32_sub(
1155 rgb_plus_1->green,
1156 rgb->green);
1157 rgb->delta_blue = dal_fixed31_32_sub(
1158 rgb_plus_1->blue,
1159 rgb->blue);
1160
1161 ++rgb_plus_1;
1162 ++rgb;
1163 ++i;
1164 }
1165}
1166
1167static void rebuild_curve_configuration_magic(
1168 struct curve_points *arr_points,
1169 struct pwl_result_data *rgb_resulted,
1170 const struct hw_x_point *coordinates_x,
1171 uint32_t hw_points_num,
1172 enum dc_transfer_func_predefined tf)
1173{
1174 struct fixed31_32 y_r;
1175 struct fixed31_32 y_g;
1176 struct fixed31_32 y_b;
1177
1178 struct fixed31_32 y1_min;
1179 struct fixed31_32 y3_max;
1180
1181 y_r = rgb_resulted[0].red;
1182 y_g = rgb_resulted[0].green;
1183 y_b = rgb_resulted[0].blue;
1184
1185 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
1186
1187 arr_points[0].x = coordinates_x[0].adjusted_x;
1188 arr_points[0].y = y1_min;
1189 arr_points[0].slope = dal_fixed31_32_div(
1190 arr_points[0].y,
1191 arr_points[0].x);
1192
1193 /* this should be cleaned up as it's confusing my understanding (KK) is
1194 * that REGAMMA_CNTLA_EXP_REGION_END is the X value for the region end
1195 * REGAMMA_CNTLA_EXP_REGION_END_BASE is Y value for the above X
1196 * REGAMMA_CNTLA_EXP_REGION_END_SLOPE is the slope beyond (X,Y) above
1197 * currently when programming REGION_END = m_arrPoints[1].x,
1198 * REGION_END_BASE = m_arrPoints[1].y, REGION_END_SLOPE=1
1199 * we don't use m_arrPoints[2] at all after this function,
1200 * and its purpose isn't clear to me
1201 */
1202 arr_points[1].x = coordinates_x[hw_points_num].adjusted_x;
1203 arr_points[2].x = coordinates_x[hw_points_num].adjusted_x;
1204
1205 y_r = rgb_resulted[hw_points_num].red;
1206 y_g = rgb_resulted[hw_points_num].green;
1207 y_b = rgb_resulted[hw_points_num].blue;
1208
1209 /* see comment above, m_arrPoints[1].y should be the Y value for the
1210 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
1211 */
1212 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
1213
1214 arr_points[1].y = y3_max;
1215 arr_points[2].y = y3_max;
1216
1217 arr_points[2].slope = dal_fixed31_32_zero;
1218
1219 /* for PQ, we want to have a straight line from last HW X point, and the
1220 * slope to be such that we hit 1.0 at 10000 nits.
1221 */
1222 if (tf == TRANSFER_FUNCTION_PQ) {
1223 const struct fixed31_32 end_value =
1224 dal_fixed31_32_from_int(125);
1225
1226 arr_points[2].slope = dal_fixed31_32_div(
1227 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
1228 dal_fixed31_32_sub(end_value, arr_points[1].x));
1229 }
1230}
1231
1232static bool convert_to_custom_float_format(
1233 struct fixed31_32 value,
1234 const struct custom_float_format *format,
1235 uint32_t *result)
1236{
1237 uint32_t mantissa;
1238 uint32_t exponenta;
1239 bool negative;
1240
1241 return build_custom_float(
1242 value, format, &negative, &mantissa, &exponenta) &&
1243 setup_custom_float(
1244 format, negative, mantissa, exponenta, result);
1245}
1246
1247static bool convert_to_custom_float(
1248 struct pwl_result_data *rgb_resulted,
1249 struct curve_points *arr_points,
1250 uint32_t hw_points_num)
1251{
1252 struct custom_float_format fmt;
1253
1254 struct pwl_result_data *rgb = rgb_resulted;
1255
1256 uint32_t i = 0;
1257
1258 fmt.exponenta_bits = 6;
1259 fmt.mantissa_bits = 12;
1260 fmt.sign = true;
1261
1262 if (!convert_to_custom_float_format(
1263 arr_points[0].x,
1264 &fmt,
1265 &arr_points[0].custom_float_x)) {
1266 BREAK_TO_DEBUGGER();
1267 return false;
1268 }
1269
1270 if (!convert_to_custom_float_format(
1271 arr_points[0].offset,
1272 &fmt,
1273 &arr_points[0].custom_float_offset)) {
1274 BREAK_TO_DEBUGGER();
1275 return false;
1276 }
1277
1278 if (!convert_to_custom_float_format(
1279 arr_points[0].slope,
1280 &fmt,
1281 &arr_points[0].custom_float_slope)) {
1282 BREAK_TO_DEBUGGER();
1283 return false;
1284 }
1285
1286 fmt.mantissa_bits = 10;
1287 fmt.sign = false;
1288
1289 if (!convert_to_custom_float_format(
1290 arr_points[1].x,
1291 &fmt,
1292 &arr_points[1].custom_float_x)) {
1293 BREAK_TO_DEBUGGER();
1294 return false;
1295 }
1296
1297 if (!convert_to_custom_float_format(
1298 arr_points[1].y,
1299 &fmt,
1300 &arr_points[1].custom_float_y)) {
1301 BREAK_TO_DEBUGGER();
1302 return false;
1303 }
1304
1305 if (!convert_to_custom_float_format(
1306 arr_points[2].slope,
1307 &fmt,
1308 &arr_points[2].custom_float_slope)) {
1309 BREAK_TO_DEBUGGER();
1310 return false;
1311 }
1312
1313 fmt.mantissa_bits = 12;
1314 fmt.sign = true;
1315
1316 while (i != hw_points_num) {
1317 if (!convert_to_custom_float_format(
1318 rgb->red,
1319 &fmt,
1320 &rgb->red_reg)) {
1321 BREAK_TO_DEBUGGER();
1322 return false;
1323 }
1324
1325 if (!convert_to_custom_float_format(
1326 rgb->green,
1327 &fmt,
1328 &rgb->green_reg)) {
1329 BREAK_TO_DEBUGGER();
1330 return false;
1331 }
1332
1333 if (!convert_to_custom_float_format(
1334 rgb->blue,
1335 &fmt,
1336 &rgb->blue_reg)) {
1337 BREAK_TO_DEBUGGER();
1338 return false;
1339 }
1340
1341 if (!convert_to_custom_float_format(
1342 rgb->delta_red,
1343 &fmt,
1344 &rgb->delta_red_reg)) {
1345 BREAK_TO_DEBUGGER();
1346 return false;
1347 }
1348
1349 if (!convert_to_custom_float_format(
1350 rgb->delta_green,
1351 &fmt,
1352 &rgb->delta_green_reg)) {
1353 BREAK_TO_DEBUGGER();
1354 return false;
1355 }
1356
1357 if (!convert_to_custom_float_format(
1358 rgb->delta_blue,
1359 &fmt,
1360 &rgb->delta_blue_reg)) {
1361 BREAK_TO_DEBUGGER();
1362 return false;
1363 }
1364
1365 ++rgb;
1366 ++i;
1367 }
1368
1369 return true;
1370}
1371
1372bool calculate_regamma_params(struct pwl_params *params,
1373 const struct core_gamma *ramp,
1374 const struct core_surface *surface,
1375 const struct core_stream *stream)
1376{
1377 struct gamma_curve *arr_curve_points = params->arr_curve_points;
1378 struct curve_points *arr_points = params->arr_points;
1379 struct pwl_result_data *rgb_resulted = params->rgb_resulted;
1380 struct dividers dividers;
1381
1382 struct hw_x_point *coordinates_x = NULL;
1383 struct pwl_float_data *rgb_user = NULL ;
1384 struct pwl_float_data_ex *rgb_regamma = NULL;
1385 struct pwl_float_data *rgb_oem = NULL;
1386 struct gamma_pixel *axix_x_256 = NULL;
1387 struct pixel_gamma_point *coeff128_oem = NULL;
1388 struct pixel_gamma_point *coeff128 = NULL;
1389
1390 enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB;
1391
1392 bool ret = false;
1393
1394 coordinates_x = dm_alloc(sizeof(*coordinates_x)*(256 + 3));
1395 if (!coordinates_x)
1396 goto coordinates_x_alloc_fail;
1397 rgb_user = dm_alloc(sizeof(*rgb_user) * (TRANSFER_FUNC_POINTS + 3));
1398 if (!rgb_user)
1399 goto rgb_user_alloc_fail;
1400 rgb_regamma = dm_alloc(sizeof(*rgb_regamma) * (256 + 3));
1401 if (!rgb_regamma)
1402 goto rgb_regamma_alloc_fail;
1403 rgb_oem = dm_alloc(sizeof(*rgb_oem) * (TRANSFER_FUNC_POINTS + 3));
1404 if (!rgb_oem)
1405 goto rgb_oem_alloc_fail;
1406 axix_x_256 = dm_alloc(sizeof(*axix_x_256) * (256 + 3));
1407 if (!axix_x_256)
1408 goto axix_x_256_alloc_fail;
1409 coeff128_oem = dm_alloc(sizeof(*coeff128_oem) * (256 + 3));
1410 if (!coeff128_oem)
1411 goto coeff128_oem_alloc_fail;
1412 coeff128 = dm_alloc(sizeof(*coeff128) * (256 + 3));
1413 if (!coeff128)
1414 goto coeff128_alloc_fail;
1415
1416 dividers.divider1 = dal_fixed31_32_from_fraction(3, 2);
1417 dividers.divider2 = dal_fixed31_32_from_int(2);
1418 dividers.divider3 = dal_fixed31_32_from_fraction(5, 2);
1419
1420 if (stream->public.out_transfer_func)
1421 tf = stream->public.out_transfer_func->tf;
1422
1423 build_evenly_distributed_points(
1424 axix_x_256,
1425 256,
1426 dal_fixed31_32_one,
1427 dividers);
1428
1429 scale_gamma(rgb_user, ramp, dividers);
1430
1431 if (tf == TRANSFER_FUNCTION_PQ) {
1432 setup_distribution_points_pq(arr_curve_points, arr_points,
1433 &params->hw_points_num, coordinates_x,
1434 surface->public.format);
1435 build_regamma_curve_pq(rgb_regamma, rgb_oem, coeff128_oem,
1436 ramp, surface, params->hw_points_num,
1437 coordinates_x, axix_x_256, dividers);
1438 } else {
1439 setup_distribution_points(arr_curve_points, arr_points,
1440 &params->hw_points_num, coordinates_x);
1441 build_regamma_curve(rgb_regamma, rgb_oem, coeff128_oem,
1442 ramp, surface, params->hw_points_num,
1443 coordinates_x, axix_x_256, dividers);
1444 }
1445
1446 map_regamma_hw_to_x_user(coeff128, rgb_oem, rgb_resulted, rgb_user,
1447 coordinates_x, axix_x_256, &ramp->public, rgb_regamma,
1448 dividers, params->hw_points_num, surface);
1449
1450 build_new_custom_resulted_curve(rgb_resulted, params->hw_points_num);
1451
1452 rebuild_curve_configuration_magic(
1453 arr_points,
1454 rgb_resulted,
1455 coordinates_x,
1456 params->hw_points_num,
1457 tf);
1458
1459 convert_to_custom_float(rgb_resulted, arr_points,
1460 params->hw_points_num);
1461
1462 ret = true;
1463
1464 dm_free(coeff128);
1465coeff128_alloc_fail:
1466 dm_free(coeff128_oem);
1467coeff128_oem_alloc_fail:
1468 dm_free(axix_x_256);
1469axix_x_256_alloc_fail:
1470 dm_free(rgb_oem);
1471rgb_oem_alloc_fail:
1472 dm_free(rgb_regamma);
1473rgb_regamma_alloc_fail:
1474 dm_free(rgb_user);
1475rgb_user_alloc_fail:
1476 dm_free(coordinates_x);
1477coordinates_x_alloc_fail:
1478 return ret;
1479
1480}
1481
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7d4299b9ee1f..948f82a56472 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1519,23 +1519,23 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda
1519 if (dc->debug.disable_color_module) 1519 if (dc->debug.disable_color_module)
1520 continue; /* skip below color updates */ 1520 continue; /* skip below color updates */
1521 1521
1522 if (updates[i].hdr_static_metadata) {
1523 resource_build_info_frame(pipe_ctx);
1524 core_dc->hwss.update_info_frame(pipe_ctx);
1525 }
1526 if (is_new_pipe_surface[j] || 1522 if (is_new_pipe_surface[j] ||
1527 updates[i].in_transfer_func) 1523 updates[i].in_transfer_func)
1528 core_dc->hwss.set_input_transfer_func( 1524 core_dc->hwss.set_input_transfer_func(
1529 pipe_ctx, pipe_ctx->surface); 1525 pipe_ctx, pipe_ctx->surface);
1530 1526
1531 if (is_new_pipe_surface[j] || 1527 if (is_new_pipe_surface[j] ||
1532 updates[i].gamma ||
1533 updates[i].out_transfer_func) 1528 updates[i].out_transfer_func)
1534 core_dc->hwss.set_output_transfer_func( 1529 core_dc->hwss.set_output_transfer_func(
1535 pipe_ctx, 1530 pipe_ctx,
1536 pipe_ctx->surface, 1531 pipe_ctx->surface,
1537 pipe_ctx->stream); 1532 pipe_ctx->stream);
1538 1533
1534 if (updates[i].hdr_static_metadata) {
1535 resource_build_info_frame(pipe_ctx);
1536 core_dc->hwss.update_info_frame(pipe_ctx);
1537 }
1538
1539 } 1539 }
1540 if (apply_ctx) { 1540 if (apply_ctx) {
1541 core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context); 1541 core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index b814e7b76bbc..f53b41339951 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -213,11 +213,14 @@ enum dc_transfer_func_type {
213}; 213};
214 214
215struct dc_transfer_func_distributed_points { 215struct dc_transfer_func_distributed_points {
216 uint16_t red[TRANSFER_FUNC_POINTS]; 216 struct fixed31_32 red[TRANSFER_FUNC_POINTS];
217 uint16_t green[TRANSFER_FUNC_POINTS]; 217 struct fixed31_32 green[TRANSFER_FUNC_POINTS];
218 uint16_t blue[TRANSFER_FUNC_POINTS]; 218 struct fixed31_32 blue[TRANSFER_FUNC_POINTS];
219
219 uint16_t end_exponent; 220 uint16_t end_exponent;
220 uint16_t x_point_at_y1; 221 uint16_t x_point_at_y1_red;
222 uint16_t x_point_at_y1_green;
223 uint16_t x_point_at_y1_blue;
221}; 224};
222 225
223enum dc_transfer_func_predefined { 226enum dc_transfer_func_predefined {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 415b12accd2c..6e70cf7b99ef 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -42,7 +42,6 @@
42#include "stream_encoder.h" 42#include "stream_encoder.h"
43#include "link_encoder.h" 43#include "link_encoder.h"
44#include "clock_source.h" 44#include "clock_source.h"
45#include "gamma_calcs.h"
46#include "audio.h" 45#include "audio.h"
47#include "dce/dce_hwseq.h" 46#include "dce/dce_hwseq.h"
48 47
@@ -286,6 +285,436 @@ static bool dce110_set_input_transfer_func(
286 return result; 285 return result;
287} 286}
288 287
288static bool build_custom_float(
289 struct fixed31_32 value,
290 const struct custom_float_format *format,
291 bool *negative,
292 uint32_t *mantissa,
293 uint32_t *exponenta)
294{
295 uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
296
297 const struct fixed31_32 mantissa_constant_plus_max_fraction =
298 dal_fixed31_32_from_fraction(
299 (1LL << (format->mantissa_bits + 1)) - 1,
300 1LL << format->mantissa_bits);
301
302 struct fixed31_32 mantiss;
303
304 if (dal_fixed31_32_eq(
305 value,
306 dal_fixed31_32_zero)) {
307 *negative = false;
308 *mantissa = 0;
309 *exponenta = 0;
310 return true;
311 }
312
313 if (dal_fixed31_32_lt(
314 value,
315 dal_fixed31_32_zero)) {
316 *negative = format->sign;
317 value = dal_fixed31_32_neg(value);
318 } else {
319 *negative = false;
320 }
321
322 if (dal_fixed31_32_lt(
323 value,
324 dal_fixed31_32_one)) {
325 uint32_t i = 1;
326
327 do {
328 value = dal_fixed31_32_shl(value, 1);
329 ++i;
330 } while (dal_fixed31_32_lt(
331 value,
332 dal_fixed31_32_one));
333
334 --i;
335
336 if (exp_offset <= i) {
337 *mantissa = 0;
338 *exponenta = 0;
339 return true;
340 }
341
342 *exponenta = exp_offset - i;
343 } else if (dal_fixed31_32_le(
344 mantissa_constant_plus_max_fraction,
345 value)) {
346 uint32_t i = 1;
347
348 do {
349 value = dal_fixed31_32_shr(value, 1);
350 ++i;
351 } while (dal_fixed31_32_lt(
352 mantissa_constant_plus_max_fraction,
353 value));
354
355 *exponenta = exp_offset + i - 1;
356 } else {
357 *exponenta = exp_offset;
358 }
359
360 mantiss = dal_fixed31_32_sub(
361 value,
362 dal_fixed31_32_one);
363
364 if (dal_fixed31_32_lt(
365 mantiss,
366 dal_fixed31_32_zero) ||
367 dal_fixed31_32_lt(
368 dal_fixed31_32_one,
369 mantiss))
370 mantiss = dal_fixed31_32_zero;
371 else
372 mantiss = dal_fixed31_32_shl(
373 mantiss,
374 format->mantissa_bits);
375
376 *mantissa = dal_fixed31_32_floor(mantiss);
377
378 return true;
379}
380
381static bool setup_custom_float(
382 const struct custom_float_format *format,
383 bool negative,
384 uint32_t mantissa,
385 uint32_t exponenta,
386 uint32_t *result)
387{
388 uint32_t i = 0;
389 uint32_t j = 0;
390
391 uint32_t value = 0;
392
393 /* verification code:
394 * once calculation is ok we can remove it
395 */
396
397 const uint32_t mantissa_mask =
398 (1 << (format->mantissa_bits + 1)) - 1;
399
400 const uint32_t exponenta_mask =
401 (1 << (format->exponenta_bits + 1)) - 1;
402
403 if (mantissa & ~mantissa_mask) {
404 BREAK_TO_DEBUGGER();
405 mantissa = mantissa_mask;
406 }
407
408 if (exponenta & ~exponenta_mask) {
409 BREAK_TO_DEBUGGER();
410 exponenta = exponenta_mask;
411 }
412
413 /* end of verification code */
414
415 while (i < format->mantissa_bits) {
416 uint32_t mask = 1 << i;
417
418 if (mantissa & mask)
419 value |= mask;
420
421 ++i;
422 }
423
424 while (j < format->exponenta_bits) {
425 uint32_t mask = 1 << j;
426
427 if (exponenta & mask)
428 value |= mask << i;
429
430 ++j;
431 }
432
433 if (negative && format->sign)
434 value |= 1 << (i + j);
435
436 *result = value;
437
438 return true;
439}
440
441static bool convert_to_custom_float_format(
442 struct fixed31_32 value,
443 const struct custom_float_format *format,
444 uint32_t *result)
445{
446 uint32_t mantissa;
447 uint32_t exponenta;
448 bool negative;
449
450 return build_custom_float(
451 value, format, &negative, &mantissa, &exponenta) &&
452 setup_custom_float(
453 format, negative, mantissa, exponenta, result);
454}
455
456static bool convert_to_custom_float(
457 struct pwl_result_data *rgb_resulted,
458 struct curve_points *arr_points,
459 uint32_t hw_points_num)
460{
461 struct custom_float_format fmt;
462
463 struct pwl_result_data *rgb = rgb_resulted;
464
465 uint32_t i = 0;
466
467 fmt.exponenta_bits = 6;
468 fmt.mantissa_bits = 12;
469 fmt.sign = true;
470
471 if (!convert_to_custom_float_format(
472 arr_points[0].x,
473 &fmt,
474 &arr_points[0].custom_float_x)) {
475 BREAK_TO_DEBUGGER();
476 return false;
477 }
478
479 if (!convert_to_custom_float_format(
480 arr_points[0].offset,
481 &fmt,
482 &arr_points[0].custom_float_offset)) {
483 BREAK_TO_DEBUGGER();
484 return false;
485 }
486
487 if (!convert_to_custom_float_format(
488 arr_points[0].slope,
489 &fmt,
490 &arr_points[0].custom_float_slope)) {
491 BREAK_TO_DEBUGGER();
492 return false;
493 }
494
495 fmt.mantissa_bits = 10;
496 fmt.sign = false;
497
498 if (!convert_to_custom_float_format(
499 arr_points[1].x,
500 &fmt,
501 &arr_points[1].custom_float_x)) {
502 BREAK_TO_DEBUGGER();
503 return false;
504 }
505
506 if (!convert_to_custom_float_format(
507 arr_points[1].y,
508 &fmt,
509 &arr_points[1].custom_float_y)) {
510 BREAK_TO_DEBUGGER();
511 return false;
512 }
513
514 if (!convert_to_custom_float_format(
515 arr_points[2].slope,
516 &fmt,
517 &arr_points[2].custom_float_slope)) {
518 BREAK_TO_DEBUGGER();
519 return false;
520 }
521
522 fmt.mantissa_bits = 12;
523 fmt.sign = true;
524
525 while (i != hw_points_num) {
526 if (!convert_to_custom_float_format(
527 rgb->red,
528 &fmt,
529 &rgb->red_reg)) {
530 BREAK_TO_DEBUGGER();
531 return false;
532 }
533
534 if (!convert_to_custom_float_format(
535 rgb->green,
536 &fmt,
537 &rgb->green_reg)) {
538 BREAK_TO_DEBUGGER();
539 return false;
540 }
541
542 if (!convert_to_custom_float_format(
543 rgb->blue,
544 &fmt,
545 &rgb->blue_reg)) {
546 BREAK_TO_DEBUGGER();
547 return false;
548 }
549
550 if (!convert_to_custom_float_format(
551 rgb->delta_red,
552 &fmt,
553 &rgb->delta_red_reg)) {
554 BREAK_TO_DEBUGGER();
555 return false;
556 }
557
558 if (!convert_to_custom_float_format(
559 rgb->delta_green,
560 &fmt,
561 &rgb->delta_green_reg)) {
562 BREAK_TO_DEBUGGER();
563 return false;
564 }
565
566 if (!convert_to_custom_float_format(
567 rgb->delta_blue,
568 &fmt,
569 &rgb->delta_blue_reg)) {
570 BREAK_TO_DEBUGGER();
571 return false;
572 }
573
574 ++rgb;
575 ++i;
576 }
577
578 return true;
579}
580
581static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func
582 *output_tf, struct pwl_params *regamma_params)
583{
584 if (output_tf == NULL || regamma_params == NULL)
585 return false;
586
587 struct gamma_curve *arr_curve_points = regamma_params->arr_curve_points;
588 struct curve_points *arr_points = regamma_params->arr_points;
589 struct pwl_result_data *rgb_resulted = regamma_params->rgb_resulted;
590 struct fixed31_32 y_r;
591 struct fixed31_32 y_g;
592 struct fixed31_32 y_b;
593 struct fixed31_32 y1_min;
594 struct fixed31_32 y3_max;
595
596 int32_t segment_start, segment_end;
597 uint32_t hw_points, start_index;
598 uint32_t i, j;
599
600 memset(regamma_params, 0, sizeof(struct pwl_params));
601
602 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
603 /* 16 segments x 16 points
604 * segments are from 2^-11 to 2^5
605 */
606 segment_start = -11;
607 segment_end = 5;
608
609 } else {
610 /* 10 segments x 16 points
611 * segment is from 2^-10 to 2^0
612 */
613 segment_start = -10;
614 segment_end = 0;
615 }
616
617 hw_points = (segment_end - segment_start) * 16;
618 j = 0;
619 /* (segment + 25) * 32, every 2nd point */
620 start_index = (segment_start + 25) * 32;
621 for (i = start_index; i <= 1025; i += 2) {
622 if (j > hw_points)
623 break;
624 rgb_resulted[j].red = output_tf->tf_pts.red[i];
625 rgb_resulted[j].green = output_tf->tf_pts.green[i];
626 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
627 j++;
628 }
629
630 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
631 dal_fixed31_32_from_int(segment_start));
632 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
633 dal_fixed31_32_from_int(segment_end));
634 arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
635 dal_fixed31_32_from_int(segment_end));
636
637 y_r = rgb_resulted[0].red;
638 y_g = rgb_resulted[0].green;
639 y_b = rgb_resulted[0].blue;
640
641 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
642
643 arr_points[0].y = y1_min;
644 arr_points[0].slope = dal_fixed31_32_div(
645 arr_points[0].y,
646 arr_points[0].x);
647
648 y_r = rgb_resulted[hw_points - 1].red;
649 y_g = rgb_resulted[hw_points - 1].green;
650 y_b = rgb_resulted[hw_points - 1].blue;
651
652 /* see comment above, m_arrPoints[1].y should be the Y value for the
653 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
654 */
655 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
656
657 arr_points[1].y = y3_max;
658 arr_points[2].y = y3_max;
659
660 arr_points[1].slope = dal_fixed31_32_zero;
661 arr_points[2].slope = dal_fixed31_32_zero;
662
663 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
664 /* for PQ, we want to have a straight line from last HW X point,
665 * and the slope to be such that we hit 1.0 at 10000 nits.
666 */
667 const struct fixed31_32 end_value =
668 dal_fixed31_32_from_int(125);
669
670 arr_points[1].slope = dal_fixed31_32_div(
671 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
672 dal_fixed31_32_sub(end_value, arr_points[1].x));
673 arr_points[2].slope = dal_fixed31_32_div(
674 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
675 dal_fixed31_32_sub(end_value, arr_points[1].x));
676 }
677
678 regamma_params->hw_points_num = hw_points;
679
680 for (i = 0; i < segment_end - segment_start; i++) {
681 regamma_params->arr_curve_points[i].offset = i * 16;
682 regamma_params->arr_curve_points[i].segments_num = 4;
683 }
684
685 struct pwl_result_data *rgb = rgb_resulted;
686 struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1;
687
688 i = 1;
689
690 while (i != hw_points + 1) {
691 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
692 rgb_plus_1->red = rgb->red;
693 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
694 rgb_plus_1->green = rgb->green;
695 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
696 rgb_plus_1->blue = rgb->blue;
697
698 rgb->delta_red = dal_fixed31_32_sub(
699 rgb_plus_1->red,
700 rgb->red);
701 rgb->delta_green = dal_fixed31_32_sub(
702 rgb_plus_1->green,
703 rgb->green);
704 rgb->delta_blue = dal_fixed31_32_sub(
705 rgb_plus_1->blue,
706 rgb->blue);
707
708 ++rgb_plus_1;
709 ++rgb;
710 ++i;
711 }
712
713 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
714
715 return true;
716}
717
289static bool dce110_set_output_transfer_func( 718static bool dce110_set_output_transfer_func(
290 struct pipe_ctx *pipe_ctx, 719 struct pipe_ctx *pipe_ctx,
291 const struct core_surface *surface, /* Surface - To be removed */ 720 const struct core_surface *surface, /* Surface - To be removed */
@@ -308,10 +737,13 @@ static bool dce110_set_output_transfer_func(
308 opp->funcs->opp_power_on_regamma_lut(opp, true); 737 opp->funcs->opp_power_on_regamma_lut(opp, true);
309 738
310 if (stream->public.out_transfer_func && 739 if (stream->public.out_transfer_func &&
311 stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED && 740 stream->public.out_transfer_func->type ==
312 stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { 741 TF_TYPE_PREDEFINED &&
742 stream->public.out_transfer_func->tf ==
743 TRANSFER_FUNCTION_SRGB) {
313 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB); 744 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
314 } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) { 745 } else if (dce110_translate_regamma_to_hw_format(
746 stream->public.out_transfer_func, regamma_params)) {
315 opp->funcs->opp_program_regamma_pwl(opp, regamma_params); 747 opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
316 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER); 748 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
317 } else { 749 } else {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
deleted file mode 100644
index 0712268856c2..000000000000
--- a/drivers/gpu/drm/amd/display/dc/inc/gamma_calcs.h
+++ /dev/null
@@ -1,20 +0,0 @@
1/*
2 * gamma_calcs.h
3 *
4 * Created on: Feb 9, 2016
5 * Author: yonsun
6 */
7
8#ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_
9#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_
10
11#include "opp.h"
12#include "core_types.h"
13#include "dc.h"
14
15bool calculate_regamma_params(struct pwl_params *params,
16 const struct core_gamma *ramp,
17 const struct core_surface *surface,
18 const struct core_stream *stream);
19
20#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_GAMMA_CALCS_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
index a1f31a4410a3..bef5e2cacbe3 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
@@ -138,9 +138,7 @@ struct custom_float_value {
138 138
139struct hw_x_point { 139struct hw_x_point {
140 uint32_t custom_float_x; 140 uint32_t custom_float_x;
141 uint32_t custom_float_x_adjusted;
142 struct fixed31_32 x; 141 struct fixed31_32 x;
143 struct fixed31_32 adjusted_x;
144 struct fixed31_32 regamma_y_red; 142 struct fixed31_32 regamma_y_red;
145 struct fixed31_32 regamma_y_green; 143 struct fixed31_32 regamma_y_green;
146 struct fixed31_32 regamma_y_blue; 144 struct fixed31_32 regamma_y_blue;
diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h
index c28de167250f..5a4364dfd2f7 100644
--- a/drivers/gpu/drm/amd/display/include/fixed31_32.h
+++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h
@@ -192,6 +192,14 @@ struct fixed31_32 dal_fixed31_32_add(
192 192
193/* 193/*
194 * @brief 194 * @brief
195 * result = arg1 + arg2
196 */
197struct fixed31_32 dal_fixed31_32_add_int(
198 struct fixed31_32 arg1,
199 int32_t arg2);
200
201/*
202 * @brief
195 * result = arg1 - arg2 203 * result = arg1 - arg2
196 */ 204 */
197struct fixed31_32 dal_fixed31_32_sub_int( 205struct fixed31_32 dal_fixed31_32_sub_int(