Line data Source code
1 : /*
2 : * Copyright 2020 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 "core_types.h"
28 : #include "reg_helper.h"
29 : #include "dcn30_dpp.h"
30 : #include "basics/conversion.h"
31 : #include "dcn30_cm_common.h"
32 : #include "custom_float.h"
33 :
34 : #define REG(reg) reg
35 :
36 : #define CTX \
37 : ctx //dpp->base.ctx
38 :
39 : #undef FN
40 : #define FN(reg_name, field_name) \
41 : reg->shifts.field_name, reg->masks.field_name
42 :
43 0 : void cm_helper_program_gamcor_xfer_func(
44 : struct dc_context *ctx,
45 : const struct pwl_params *params,
46 : const struct dcn3_xfer_func_reg *reg)
47 : {
48 : uint32_t reg_region_cur;
49 0 : unsigned int i = 0;
50 :
51 0 : REG_SET_2(reg->start_cntl_b, 0,
52 : exp_region_start, params->corner_points[0].blue.custom_float_x,
53 : exp_resion_start_segment, 0);
54 0 : REG_SET_2(reg->start_cntl_g, 0,
55 : exp_region_start, params->corner_points[0].green.custom_float_x,
56 : exp_resion_start_segment, 0);
57 0 : REG_SET_2(reg->start_cntl_r, 0,
58 : exp_region_start, params->corner_points[0].red.custom_float_x,
59 : exp_resion_start_segment, 0);
60 :
61 0 : REG_SET(reg->start_slope_cntl_b, 0, //linear slope at start of curve
62 : field_region_linear_slope, params->corner_points[0].blue.custom_float_slope);
63 0 : REG_SET(reg->start_slope_cntl_g, 0,
64 : field_region_linear_slope, params->corner_points[0].green.custom_float_slope);
65 0 : REG_SET(reg->start_slope_cntl_r, 0,
66 : field_region_linear_slope, params->corner_points[0].red.custom_float_slope);
67 :
68 0 : REG_SET(reg->start_end_cntl1_b, 0,
69 : field_region_end_base, params->corner_points[1].blue.custom_float_y);
70 0 : REG_SET(reg->start_end_cntl1_g, 0,
71 : field_region_end_base, params->corner_points[1].green.custom_float_y);
72 0 : REG_SET(reg->start_end_cntl1_r, 0,
73 : field_region_end_base, params->corner_points[1].red.custom_float_y);
74 :
75 0 : REG_SET_2(reg->start_end_cntl2_b, 0,
76 : field_region_end_slope, params->corner_points[1].blue.custom_float_slope,
77 : field_region_end, params->corner_points[1].blue.custom_float_x);
78 0 : REG_SET_2(reg->start_end_cntl2_g, 0,
79 : field_region_end_slope, params->corner_points[1].green.custom_float_slope,
80 : field_region_end, params->corner_points[1].green.custom_float_x);
81 0 : REG_SET_2(reg->start_end_cntl2_r, 0,
82 : field_region_end_slope, params->corner_points[1].red.custom_float_slope,
83 : field_region_end, params->corner_points[1].red.custom_float_x);
84 :
85 0 : for (reg_region_cur = reg->region_start;
86 0 : reg_region_cur <= reg->region_end;
87 0 : reg_region_cur++) {
88 :
89 0 : const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]);
90 0 : const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]);
91 :
92 0 : REG_SET_4(reg_region_cur, 0,
93 : exp_region0_lut_offset, curve0->offset,
94 : exp_region0_num_segments, curve0->segments_num,
95 : exp_region1_lut_offset, curve1->offset,
96 : exp_region1_num_segments, curve1->segments_num);
97 :
98 0 : i++;
99 : }
100 0 : }
101 :
102 : /* driver uses 32 regions or less, but DCN HW has 34, extra 2 are set to 0 */
103 : #define MAX_REGIONS_NUMBER 34
104 : #define MAX_LOW_POINT 25
105 : #define NUMBER_REGIONS 32
106 : #define NUMBER_SW_SEGMENTS 16
107 :
108 0 : bool cm3_helper_translate_curve_to_hw_format(
109 : const struct dc_transfer_func *output_tf,
110 : struct pwl_params *lut_params, bool fixpoint)
111 : {
112 : struct curve_points3 *corner_points;
113 : struct pwl_result_data *rgb_resulted;
114 : struct pwl_result_data *rgb;
115 : struct pwl_result_data *rgb_plus_1;
116 : struct pwl_result_data *rgb_minus_1;
117 : struct fixed31_32 end_value;
118 :
119 : int32_t region_start, region_end;
120 : int32_t i;
121 : uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
122 :
123 0 : if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
124 : return false;
125 :
126 0 : corner_points = lut_params->corner_points;
127 0 : rgb_resulted = lut_params->rgb_resulted;
128 0 : hw_points = 0;
129 :
130 0 : memset(lut_params, 0, sizeof(struct pwl_params));
131 0 : memset(seg_distr, 0, sizeof(seg_distr));
132 :
133 0 : if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22 ||
134 : output_tf->tf == TRANSFER_FUNCTION_HLG) {
135 : /* 32 segments
136 : * segments are from 2^-25 to 2^7
137 : */
138 0 : for (i = 0; i < NUMBER_REGIONS ; i++)
139 0 : seg_distr[i] = 3;
140 :
141 : region_start = -MAX_LOW_POINT;
142 : region_end = NUMBER_REGIONS - MAX_LOW_POINT;
143 : } else {
144 : /* 11 segments
145 : * segment is from 2^-10 to 2^0
146 : * There are less than 256 points, for optimization
147 : */
148 0 : seg_distr[0] = 3;
149 0 : seg_distr[1] = 4;
150 0 : seg_distr[2] = 4;
151 0 : seg_distr[3] = 4;
152 0 : seg_distr[4] = 4;
153 0 : seg_distr[5] = 4;
154 0 : seg_distr[6] = 4;
155 0 : seg_distr[7] = 4;
156 0 : seg_distr[8] = 4;
157 0 : seg_distr[9] = 4;
158 0 : seg_distr[10] = 1;
159 :
160 0 : region_start = -10;
161 0 : region_end = 1;
162 : }
163 :
164 0 : for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
165 0 : seg_distr[i] = -1;
166 :
167 0 : for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
168 0 : if (seg_distr[k] != -1)
169 0 : hw_points += (1 << seg_distr[k]);
170 : }
171 :
172 : j = 0;
173 0 : for (k = 0; k < (region_end - region_start); k++) {
174 0 : increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
175 0 : start_index = (region_start + k + MAX_LOW_POINT) *
176 : NUMBER_SW_SEGMENTS;
177 0 : for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
178 0 : i += increment) {
179 0 : if (j == hw_points - 1)
180 : break;
181 0 : rgb_resulted[j].red = output_tf->tf_pts.red[i];
182 0 : rgb_resulted[j].green = output_tf->tf_pts.green[i];
183 0 : rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
184 0 : j++;
185 : }
186 : }
187 :
188 : /* last point */
189 0 : start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
190 0 : rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
191 0 : rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
192 0 : rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
193 :
194 0 : rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
195 0 : rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
196 0 : rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
197 :
198 : // All 3 color channels have same x
199 0 : corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
200 : dc_fixpt_from_int(region_start));
201 0 : corner_points[0].green.x = corner_points[0].red.x;
202 0 : corner_points[0].blue.x = corner_points[0].red.x;
203 :
204 0 : corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
205 : dc_fixpt_from_int(region_end));
206 0 : corner_points[1].green.x = corner_points[1].red.x;
207 0 : corner_points[1].blue.x = corner_points[1].red.x;
208 :
209 0 : corner_points[0].red.y = rgb_resulted[0].red;
210 0 : corner_points[0].green.y = rgb_resulted[0].green;
211 0 : corner_points[0].blue.y = rgb_resulted[0].blue;
212 :
213 0 : corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y,
214 : corner_points[0].red.x);
215 0 : corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y,
216 : corner_points[0].green.x);
217 0 : corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y,
218 : corner_points[0].blue.x);
219 :
220 : /* see comment above, m_arrPoints[1].y should be the Y value for the
221 : * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
222 : */
223 0 : corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
224 0 : corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
225 0 : corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
226 0 : corner_points[1].red.slope = dc_fixpt_zero;
227 0 : corner_points[1].green.slope = dc_fixpt_zero;
228 0 : corner_points[1].blue.slope = dc_fixpt_zero;
229 :
230 0 : if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_HLG) {
231 : /* for PQ/HLG, we want to have a straight line from last HW X point,
232 : * and the slope to be such that we hit 1.0 at 10000/1000 nits.
233 : */
234 :
235 0 : if (output_tf->tf == TRANSFER_FUNCTION_PQ)
236 : end_value = dc_fixpt_from_int(125);
237 : else
238 0 : end_value = dc_fixpt_from_fraction(125, 10);
239 :
240 0 : corner_points[1].red.slope = dc_fixpt_div(
241 : dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
242 : dc_fixpt_sub(end_value, corner_points[1].red.x));
243 0 : corner_points[1].green.slope = dc_fixpt_div(
244 : dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
245 : dc_fixpt_sub(end_value, corner_points[1].green.x));
246 0 : corner_points[1].blue.slope = dc_fixpt_div(
247 : dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
248 : dc_fixpt_sub(end_value, corner_points[1].blue.x));
249 : }
250 0 : lut_params->hw_points_num = hw_points;
251 :
252 0 : k = 0;
253 0 : for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
254 0 : if (seg_distr[k] != -1) {
255 0 : lut_params->arr_curve_points[k].segments_num =
256 : seg_distr[k];
257 0 : lut_params->arr_curve_points[i].offset =
258 0 : lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
259 : }
260 0 : k++;
261 : }
262 :
263 0 : if (seg_distr[k] != -1)
264 0 : lut_params->arr_curve_points[k].segments_num = seg_distr[k];
265 :
266 0 : rgb = rgb_resulted;
267 0 : rgb_plus_1 = rgb_resulted + 1;
268 0 : rgb_minus_1 = rgb;
269 :
270 0 : i = 1;
271 0 : while (i != hw_points + 1) {
272 0 : if (i >= hw_points - 1) {
273 0 : if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
274 0 : rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);
275 0 : if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
276 0 : rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);
277 0 : if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
278 0 : rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);
279 : }
280 :
281 0 : rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
282 0 : rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
283 0 : rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
284 :
285 0 : if (fixpoint == true) {
286 0 : rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red);
287 0 : rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
288 0 : rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue);
289 0 : rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red);
290 0 : rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green);
291 0 : rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue);
292 : }
293 :
294 0 : ++rgb_plus_1;
295 0 : rgb_minus_1 = rgb;
296 0 : ++rgb;
297 0 : ++i;
298 : }
299 0 : cm3_helper_convert_to_custom_float(rgb_resulted,
300 : lut_params->corner_points,
301 : hw_points, fixpoint);
302 :
303 0 : return true;
304 : }
305 :
306 : #define NUM_DEGAMMA_REGIONS 12
307 :
308 :
309 0 : bool cm3_helper_translate_curve_to_degamma_hw_format(
310 : const struct dc_transfer_func *output_tf,
311 : struct pwl_params *lut_params)
312 : {
313 : struct curve_points3 *corner_points;
314 : struct pwl_result_data *rgb_resulted;
315 : struct pwl_result_data *rgb;
316 : struct pwl_result_data *rgb_plus_1;
317 :
318 : int32_t region_start, region_end;
319 : int32_t i;
320 : uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
321 :
322 0 : if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
323 : return false;
324 :
325 0 : corner_points = lut_params->corner_points;
326 0 : rgb_resulted = lut_params->rgb_resulted;
327 0 : hw_points = 0;
328 :
329 0 : memset(lut_params, 0, sizeof(struct pwl_params));
330 0 : memset(seg_distr, 0, sizeof(seg_distr));
331 :
332 0 : region_start = -NUM_DEGAMMA_REGIONS;
333 0 : region_end = 0;
334 :
335 :
336 0 : for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
337 0 : seg_distr[i] = -1;
338 : /* 12 segments
339 : * segments are from 2^-12 to 0
340 : */
341 0 : for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
342 0 : seg_distr[i] = 4;
343 :
344 0 : for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
345 0 : if (seg_distr[k] != -1)
346 0 : hw_points += (1 << seg_distr[k]);
347 : }
348 :
349 : j = 0;
350 0 : for (k = 0; k < (region_end - region_start); k++) {
351 0 : increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
352 0 : start_index = (region_start + k + MAX_LOW_POINT) *
353 : NUMBER_SW_SEGMENTS;
354 0 : for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
355 0 : i += increment) {
356 0 : if (j == hw_points - 1)
357 : break;
358 0 : rgb_resulted[j].red = output_tf->tf_pts.red[i];
359 0 : rgb_resulted[j].green = output_tf->tf_pts.green[i];
360 0 : rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
361 0 : j++;
362 : }
363 : }
364 :
365 : /* last point */
366 0 : start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
367 0 : rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
368 0 : rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
369 0 : rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
370 :
371 0 : corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
372 : dc_fixpt_from_int(region_start));
373 0 : corner_points[0].green.x = corner_points[0].red.x;
374 0 : corner_points[0].blue.x = corner_points[0].red.x;
375 0 : corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
376 : dc_fixpt_from_int(region_end));
377 0 : corner_points[1].green.x = corner_points[1].red.x;
378 0 : corner_points[1].blue.x = corner_points[1].red.x;
379 :
380 0 : corner_points[0].red.y = rgb_resulted[0].red;
381 0 : corner_points[0].green.y = rgb_resulted[0].green;
382 0 : corner_points[0].blue.y = rgb_resulted[0].blue;
383 :
384 : /* see comment above, m_arrPoints[1].y should be the Y value for the
385 : * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
386 : */
387 0 : corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
388 0 : corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
389 0 : corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
390 0 : corner_points[1].red.slope = dc_fixpt_zero;
391 0 : corner_points[1].green.slope = dc_fixpt_zero;
392 0 : corner_points[1].blue.slope = dc_fixpt_zero;
393 :
394 0 : if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
395 : /* for PQ, we want to have a straight line from last HW X point,
396 : * and the slope to be such that we hit 1.0 at 10000 nits.
397 : */
398 0 : const struct fixed31_32 end_value =
399 : dc_fixpt_from_int(125);
400 :
401 0 : corner_points[1].red.slope = dc_fixpt_div(
402 : dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
403 : dc_fixpt_sub(end_value, corner_points[1].red.x));
404 0 : corner_points[1].green.slope = dc_fixpt_div(
405 : dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
406 : dc_fixpt_sub(end_value, corner_points[1].green.x));
407 0 : corner_points[1].blue.slope = dc_fixpt_div(
408 : dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
409 : dc_fixpt_sub(end_value, corner_points[1].blue.x));
410 : }
411 :
412 0 : lut_params->hw_points_num = hw_points;
413 :
414 0 : k = 0;
415 0 : for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
416 0 : if (seg_distr[k] != -1) {
417 0 : lut_params->arr_curve_points[k].segments_num =
418 : seg_distr[k];
419 0 : lut_params->arr_curve_points[i].offset =
420 0 : lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
421 : }
422 0 : k++;
423 : }
424 :
425 0 : if (seg_distr[k] != -1)
426 0 : lut_params->arr_curve_points[k].segments_num = seg_distr[k];
427 :
428 0 : rgb = rgb_resulted;
429 0 : rgb_plus_1 = rgb_resulted + 1;
430 :
431 0 : i = 1;
432 0 : while (i != hw_points + 1) {
433 0 : if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
434 0 : rgb_plus_1->red = rgb->red;
435 0 : if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
436 0 : rgb_plus_1->green = rgb->green;
437 0 : if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
438 0 : rgb_plus_1->blue = rgb->blue;
439 :
440 0 : rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red);
441 0 : rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
442 0 : rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue);
443 :
444 0 : ++rgb_plus_1;
445 0 : ++rgb;
446 0 : ++i;
447 : }
448 0 : cm3_helper_convert_to_custom_float(rgb_resulted,
449 : lut_params->corner_points,
450 : hw_points, false);
451 :
452 0 : return true;
453 : }
454 :
455 0 : bool cm3_helper_convert_to_custom_float(
456 : struct pwl_result_data *rgb_resulted,
457 : struct curve_points3 *corner_points,
458 : uint32_t hw_points_num,
459 : bool fixpoint)
460 : {
461 : struct custom_float_format fmt;
462 :
463 0 : struct pwl_result_data *rgb = rgb_resulted;
464 :
465 0 : uint32_t i = 0;
466 :
467 0 : fmt.exponenta_bits = 6;
468 0 : fmt.mantissa_bits = 12;
469 0 : fmt.sign = false;
470 :
471 : /* corner_points[0] - beginning base, slope offset for R,G,B
472 : * corner_points[1] - end base, slope offset for R,G,B
473 : */
474 0 : if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt,
475 : &corner_points[0].red.custom_float_x)) {
476 0 : BREAK_TO_DEBUGGER();
477 0 : return false;
478 : }
479 0 : if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt,
480 : &corner_points[0].green.custom_float_x)) {
481 0 : BREAK_TO_DEBUGGER();
482 0 : return false;
483 : }
484 0 : if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt,
485 : &corner_points[0].blue.custom_float_x)) {
486 0 : BREAK_TO_DEBUGGER();
487 0 : return false;
488 : }
489 :
490 0 : if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt,
491 : &corner_points[0].red.custom_float_offset)) {
492 0 : BREAK_TO_DEBUGGER();
493 0 : return false;
494 : }
495 0 : if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt,
496 : &corner_points[0].green.custom_float_offset)) {
497 0 : BREAK_TO_DEBUGGER();
498 0 : return false;
499 : }
500 0 : if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt,
501 : &corner_points[0].blue.custom_float_offset)) {
502 0 : BREAK_TO_DEBUGGER();
503 0 : return false;
504 : }
505 :
506 0 : if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt,
507 : &corner_points[0].red.custom_float_slope)) {
508 0 : BREAK_TO_DEBUGGER();
509 0 : return false;
510 : }
511 0 : if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt,
512 : &corner_points[0].green.custom_float_slope)) {
513 0 : BREAK_TO_DEBUGGER();
514 0 : return false;
515 : }
516 0 : if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt,
517 : &corner_points[0].blue.custom_float_slope)) {
518 0 : BREAK_TO_DEBUGGER();
519 0 : return false;
520 : }
521 :
522 0 : if (fixpoint == true) {
523 0 : corner_points[1].red.custom_float_y =
524 0 : dc_fixpt_clamp_u0d14(corner_points[1].red.y);
525 0 : corner_points[1].green.custom_float_y =
526 0 : dc_fixpt_clamp_u0d14(corner_points[1].green.y);
527 0 : corner_points[1].blue.custom_float_y =
528 0 : dc_fixpt_clamp_u0d14(corner_points[1].blue.y);
529 : } else {
530 0 : if (!convert_to_custom_float_format(corner_points[1].red.y,
531 : &fmt, &corner_points[1].red.custom_float_y)) {
532 0 : BREAK_TO_DEBUGGER();
533 0 : return false;
534 : }
535 0 : if (!convert_to_custom_float_format(corner_points[1].green.y,
536 : &fmt, &corner_points[1].green.custom_float_y)) {
537 0 : BREAK_TO_DEBUGGER();
538 0 : return false;
539 : }
540 0 : if (!convert_to_custom_float_format(corner_points[1].blue.y,
541 : &fmt, &corner_points[1].blue.custom_float_y)) {
542 0 : BREAK_TO_DEBUGGER();
543 0 : return false;
544 : }
545 : }
546 :
547 0 : fmt.mantissa_bits = 10;
548 0 : fmt.sign = false;
549 :
550 0 : if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt,
551 : &corner_points[1].red.custom_float_x)) {
552 0 : BREAK_TO_DEBUGGER();
553 0 : return false;
554 : }
555 0 : if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt,
556 : &corner_points[1].green.custom_float_x)) {
557 0 : BREAK_TO_DEBUGGER();
558 0 : return false;
559 : }
560 0 : if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt,
561 : &corner_points[1].blue.custom_float_x)) {
562 0 : BREAK_TO_DEBUGGER();
563 0 : return false;
564 : }
565 :
566 0 : if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt,
567 : &corner_points[1].red.custom_float_slope)) {
568 0 : BREAK_TO_DEBUGGER();
569 0 : return false;
570 : }
571 0 : if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt,
572 : &corner_points[1].green.custom_float_slope)) {
573 0 : BREAK_TO_DEBUGGER();
574 0 : return false;
575 : }
576 0 : if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt,
577 : &corner_points[1].blue.custom_float_slope)) {
578 0 : BREAK_TO_DEBUGGER();
579 0 : return false;
580 : }
581 :
582 0 : if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true)
583 : return true;
584 :
585 0 : fmt.mantissa_bits = 12;
586 :
587 0 : while (i != hw_points_num) {
588 0 : if (!convert_to_custom_float_format(rgb->red, &fmt,
589 : &rgb->red_reg)) {
590 0 : BREAK_TO_DEBUGGER();
591 0 : return false;
592 : }
593 :
594 0 : if (!convert_to_custom_float_format(rgb->green, &fmt,
595 : &rgb->green_reg)) {
596 0 : BREAK_TO_DEBUGGER();
597 0 : return false;
598 : }
599 :
600 0 : if (!convert_to_custom_float_format(rgb->blue, &fmt,
601 : &rgb->blue_reg)) {
602 0 : BREAK_TO_DEBUGGER();
603 0 : return false;
604 : }
605 :
606 0 : if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
607 : &rgb->delta_red_reg)) {
608 0 : BREAK_TO_DEBUGGER();
609 0 : return false;
610 : }
611 :
612 0 : if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
613 : &rgb->delta_green_reg)) {
614 0 : BREAK_TO_DEBUGGER();
615 0 : return false;
616 : }
617 :
618 0 : if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
619 : &rgb->delta_blue_reg)) {
620 0 : BREAK_TO_DEBUGGER();
621 0 : return false;
622 : }
623 :
624 0 : ++rgb;
625 0 : ++i;
626 : }
627 :
628 : return true;
629 : }
630 :
631 0 : bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num)
632 : {
633 : uint32_t i;
634 0 : bool ret = true;
635 :
636 0 : for (i = 0 ; i < num; i++) {
637 0 : if (rgb[i].red_reg != rgb[i].green_reg ||
638 0 : rgb[i].blue_reg != rgb[i].red_reg ||
639 : rgb[i].blue_reg != rgb[i].green_reg) {
640 : ret = false;
641 : break;
642 : }
643 : }
644 0 : return ret;
645 : }
646 :
|