Merge tags 'ib-mfd-clk-gpio-regulator-rtc-v5.13', 'ib-mfd-extcon-v5.13', 'ib-mfd...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / display / dc / dcn30 / dcn30_cm_common.c
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 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         unsigned int i = 0;
50
51         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         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         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         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         REG_SET(reg->start_slope_cntl_g, 0,
64                 field_region_linear_slope, params->corner_points[0].green.custom_float_slope);
65         REG_SET(reg->start_slope_cntl_r, 0,
66                 field_region_linear_slope, params->corner_points[0].red.custom_float_slope);
67
68         REG_SET(reg->start_end_cntl1_b, 0,
69                 field_region_end_base, params->corner_points[1].blue.custom_float_y);
70         REG_SET(reg->start_end_cntl1_g, 0,
71                 field_region_end_base, params->corner_points[1].green.custom_float_y);
72         REG_SET(reg->start_end_cntl1_r, 0,
73                 field_region_end_base, params->corner_points[1].red.custom_float_y);
74
75         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         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         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         for (reg_region_cur = reg->region_start;
86                 reg_region_cur <= reg->region_end;
87                 reg_region_cur++) {
88
89                 const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]);
90                 const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]);
91
92                 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                 i++;
99         }
100 }
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 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         if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
124                 return false;
125
126         corner_points = lut_params->corner_points;
127         rgb_resulted = lut_params->rgb_resulted;
128         hw_points = 0;
129
130         memset(lut_params, 0, sizeof(struct pwl_params));
131         memset(seg_distr, 0, sizeof(seg_distr));
132
133         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                 for (i = 0; i < NUMBER_REGIONS ; i++)
139                         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                 seg_distr[0] = 3;
149                 seg_distr[1] = 4;
150                 seg_distr[2] = 4;
151                 seg_distr[3] = 4;
152                 seg_distr[4] = 4;
153                 seg_distr[5] = 4;
154                 seg_distr[6] = 4;
155                 seg_distr[7] = 4;
156                 seg_distr[8] = 4;
157                 seg_distr[9] = 4;
158                 seg_distr[10] = 1;
159
160                 region_start = -10;
161                 region_end = 1;
162         }
163
164         for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
165                 seg_distr[i] = -1;
166
167         for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
168                 if (seg_distr[k] != -1)
169                         hw_points += (1 << seg_distr[k]);
170         }
171
172         j = 0;
173         for (k = 0; k < (region_end - region_start); k++) {
174                 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
175                 start_index = (region_start + k + MAX_LOW_POINT) *
176                                 NUMBER_SW_SEGMENTS;
177                 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
178                                 i += increment) {
179                         if (j == hw_points - 1)
180                                 break;
181                         rgb_resulted[j].red = output_tf->tf_pts.red[i];
182                         rgb_resulted[j].green = output_tf->tf_pts.green[i];
183                         rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
184                         j++;
185                 }
186         }
187
188         /* last point */
189         start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
190         rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
191         rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
192         rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
193
194         rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
195         rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
196         rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
197
198         // All 3 color channels have same x
199         corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
200                                              dc_fixpt_from_int(region_start));
201         corner_points[0].green.x = corner_points[0].red.x;
202         corner_points[0].blue.x = corner_points[0].red.x;
203
204         corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
205                                              dc_fixpt_from_int(region_end));
206         corner_points[1].green.x = corner_points[1].red.x;
207         corner_points[1].blue.x = corner_points[1].red.x;
208
209         corner_points[0].red.y = rgb_resulted[0].red;
210         corner_points[0].green.y = rgb_resulted[0].green;
211         corner_points[0].blue.y = rgb_resulted[0].blue;
212
213         corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y,
214                         corner_points[0].red.x);
215         corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y,
216                         corner_points[0].green.x);
217         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         corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
224         corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
225         corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
226         corner_points[1].red.slope = dc_fixpt_zero;
227         corner_points[1].green.slope = dc_fixpt_zero;
228         corner_points[1].blue.slope = dc_fixpt_zero;
229
230         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                 if (output_tf->tf == TRANSFER_FUNCTION_PQ)
236                         end_value = dc_fixpt_from_int(125);
237                 else
238                         end_value = dc_fixpt_from_fraction(125, 10);
239
240                 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                 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                 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         lut_params->hw_points_num = hw_points;
251
252         k = 0;
253         for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
254                 if (seg_distr[k] != -1) {
255                         lut_params->arr_curve_points[k].segments_num =
256                                         seg_distr[k];
257                         lut_params->arr_curve_points[i].offset =
258                                         lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
259                 }
260                 k++;
261         }
262
263         if (seg_distr[k] != -1)
264                 lut_params->arr_curve_points[k].segments_num = seg_distr[k];
265
266         rgb = rgb_resulted;
267         rgb_plus_1 = rgb_resulted + 1;
268         rgb_minus_1 = rgb;
269
270         i = 1;
271         while (i != hw_points + 1) {
272                 if (i >= hw_points - 1) {
273                         if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
274                                 rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);
275                         if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
276                                 rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);
277                         if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
278                                 rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);
279                 }
280
281                 rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
282                 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
283                 rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
284
285                 if (fixpoint == true) {
286                         rgb->delta_red_reg   = dc_fixpt_clamp_u0d10(rgb->delta_red);
287                         rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
288                         rgb->delta_blue_reg  = dc_fixpt_clamp_u0d10(rgb->delta_blue);
289                         rgb->red_reg         = dc_fixpt_clamp_u0d14(rgb->red);
290                         rgb->green_reg       = dc_fixpt_clamp_u0d14(rgb->green);
291                         rgb->blue_reg        = dc_fixpt_clamp_u0d14(rgb->blue);
292                 }
293
294                 ++rgb_plus_1;
295                 rgb_minus_1 = rgb;
296                 ++rgb;
297                 ++i;
298         }
299         cm3_helper_convert_to_custom_float(rgb_resulted,
300                                                 lut_params->corner_points,
301                                                 hw_points, fixpoint);
302
303         return true;
304 }
305
306 #define NUM_DEGAMMA_REGIONS    12
307
308
309 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         if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
323                 return false;
324
325         corner_points = lut_params->corner_points;
326         rgb_resulted = lut_params->rgb_resulted;
327         hw_points = 0;
328
329         memset(lut_params, 0, sizeof(struct pwl_params));
330         memset(seg_distr, 0, sizeof(seg_distr));
331
332         region_start = -NUM_DEGAMMA_REGIONS;
333         region_end   = 0;
334
335
336         for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
337                 seg_distr[i] = -1;
338         /* 12 segments
339          * segments are from 2^-12 to 0
340          */
341         for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
342                 seg_distr[i] = 4;
343
344         for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
345                 if (seg_distr[k] != -1)
346                         hw_points += (1 << seg_distr[k]);
347         }
348
349         j = 0;
350         for (k = 0; k < (region_end - region_start); k++) {
351                 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
352                 start_index = (region_start + k + MAX_LOW_POINT) *
353                                 NUMBER_SW_SEGMENTS;
354                 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
355                                 i += increment) {
356                         if (j == hw_points - 1)
357                                 break;
358                         rgb_resulted[j].red = output_tf->tf_pts.red[i];
359                         rgb_resulted[j].green = output_tf->tf_pts.green[i];
360                         rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
361                         j++;
362                 }
363         }
364
365         /* last point */
366         start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
367         rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
368         rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
369         rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
370
371         corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
372                                              dc_fixpt_from_int(region_start));
373         corner_points[0].green.x = corner_points[0].red.x;
374         corner_points[0].blue.x = corner_points[0].red.x;
375         corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
376                                              dc_fixpt_from_int(region_end));
377         corner_points[1].green.x = corner_points[1].red.x;
378         corner_points[1].blue.x = corner_points[1].red.x;
379
380         corner_points[0].red.y = rgb_resulted[0].red;
381         corner_points[0].green.y = rgb_resulted[0].green;
382         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         corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
388         corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
389         corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
390         corner_points[1].red.slope = dc_fixpt_zero;
391         corner_points[1].green.slope = dc_fixpt_zero;
392         corner_points[1].blue.slope = dc_fixpt_zero;
393
394         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                 const struct fixed31_32 end_value =
399                                 dc_fixpt_from_int(125);
400
401                 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                 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                 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         lut_params->hw_points_num = hw_points;
413
414         k = 0;
415         for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
416                 if (seg_distr[k] != -1) {
417                         lut_params->arr_curve_points[k].segments_num =
418                                         seg_distr[k];
419                         lut_params->arr_curve_points[i].offset =
420                                         lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
421                 }
422                 k++;
423         }
424
425         if (seg_distr[k] != -1)
426                 lut_params->arr_curve_points[k].segments_num = seg_distr[k];
427
428         rgb = rgb_resulted;
429         rgb_plus_1 = rgb_resulted + 1;
430
431         i = 1;
432         while (i != hw_points + 1) {
433                 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
434                         rgb_plus_1->red = rgb->red;
435                 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
436                         rgb_plus_1->green = rgb->green;
437                 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
438                         rgb_plus_1->blue = rgb->blue;
439
440                 rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
441                 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
442                 rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
443
444                 ++rgb_plus_1;
445                 ++rgb;
446                 ++i;
447         }
448         cm3_helper_convert_to_custom_float(rgb_resulted,
449                                                 lut_params->corner_points,
450                                                 hw_points, false);
451
452         return true;
453 }
454
455 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         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 = 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         if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt,
475                                 &corner_points[0].red.custom_float_x)) {
476                 BREAK_TO_DEBUGGER();
477                 return false;
478         }
479         if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt,
480                                 &corner_points[0].green.custom_float_x)) {
481                 BREAK_TO_DEBUGGER();
482                 return false;
483         }
484         if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt,
485                                 &corner_points[0].blue.custom_float_x)) {
486                 BREAK_TO_DEBUGGER();
487                 return false;
488         }
489
490         if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt,
491                                 &corner_points[0].red.custom_float_offset)) {
492                 BREAK_TO_DEBUGGER();
493                 return false;
494         }
495         if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt,
496                                 &corner_points[0].green.custom_float_offset)) {
497                 BREAK_TO_DEBUGGER();
498                 return false;
499         }
500         if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt,
501                                 &corner_points[0].blue.custom_float_offset)) {
502                 BREAK_TO_DEBUGGER();
503                 return false;
504         }
505
506         if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt,
507                                 &corner_points[0].red.custom_float_slope)) {
508                 BREAK_TO_DEBUGGER();
509                 return false;
510         }
511         if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt,
512                                 &corner_points[0].green.custom_float_slope)) {
513                 BREAK_TO_DEBUGGER();
514                 return false;
515         }
516         if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt,
517                                 &corner_points[0].blue.custom_float_slope)) {
518                 BREAK_TO_DEBUGGER();
519                 return false;
520         }
521
522         if (fixpoint == true) {
523                 corner_points[1].red.custom_float_y =
524                                 dc_fixpt_clamp_u0d14(corner_points[1].red.y);
525                 corner_points[1].green.custom_float_y =
526                                 dc_fixpt_clamp_u0d14(corner_points[1].green.y);
527                 corner_points[1].blue.custom_float_y =
528                                 dc_fixpt_clamp_u0d14(corner_points[1].blue.y);
529         } else {
530                 if (!convert_to_custom_float_format(corner_points[1].red.y,
531                                 &fmt, &corner_points[1].red.custom_float_y)) {
532                         BREAK_TO_DEBUGGER();
533                         return false;
534                 }
535                 if (!convert_to_custom_float_format(corner_points[1].green.y,
536                                 &fmt, &corner_points[1].green.custom_float_y)) {
537                         BREAK_TO_DEBUGGER();
538                         return false;
539                 }
540                 if (!convert_to_custom_float_format(corner_points[1].blue.y,
541                                 &fmt, &corner_points[1].blue.custom_float_y)) {
542                         BREAK_TO_DEBUGGER();
543                         return false;
544                 }
545         }
546
547         fmt.mantissa_bits = 10;
548         fmt.sign = false;
549
550         if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt,
551                                 &corner_points[1].red.custom_float_x)) {
552                 BREAK_TO_DEBUGGER();
553                 return false;
554         }
555         if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt,
556                                 &corner_points[1].green.custom_float_x)) {
557                 BREAK_TO_DEBUGGER();
558                 return false;
559         }
560         if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt,
561                                 &corner_points[1].blue.custom_float_x)) {
562                 BREAK_TO_DEBUGGER();
563                 return false;
564         }
565
566         if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt,
567                                 &corner_points[1].red.custom_float_slope)) {
568                 BREAK_TO_DEBUGGER();
569                 return false;
570         }
571         if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt,
572                                 &corner_points[1].green.custom_float_slope)) {
573                 BREAK_TO_DEBUGGER();
574                 return false;
575         }
576         if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt,
577                                 &corner_points[1].blue.custom_float_slope)) {
578                 BREAK_TO_DEBUGGER();
579                 return false;
580         }
581
582         if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true)
583                 return true;
584
585         fmt.mantissa_bits = 12;
586
587         while (i != hw_points_num) {
588                 if (!convert_to_custom_float_format(rgb->red, &fmt,
589                                                     &rgb->red_reg)) {
590                         BREAK_TO_DEBUGGER();
591                         return false;
592                 }
593
594                 if (!convert_to_custom_float_format(rgb->green, &fmt,
595                                                     &rgb->green_reg)) {
596                         BREAK_TO_DEBUGGER();
597                         return false;
598                 }
599
600                 if (!convert_to_custom_float_format(rgb->blue, &fmt,
601                                                     &rgb->blue_reg)) {
602                         BREAK_TO_DEBUGGER();
603                         return false;
604                 }
605
606                 if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
607                                                     &rgb->delta_red_reg)) {
608                         BREAK_TO_DEBUGGER();
609                         return false;
610                 }
611
612                 if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
613                                                     &rgb->delta_green_reg)) {
614                         BREAK_TO_DEBUGGER();
615                         return false;
616                 }
617
618                 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
619                                                     &rgb->delta_blue_reg)) {
620                         BREAK_TO_DEBUGGER();
621                         return false;
622                 }
623
624                 ++rgb;
625                 ++i;
626         }
627
628         return true;
629 }
630
631 bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num)
632 {
633         uint32_t i;
634         bool ret = true;
635
636         for (i = 0 ; i < num; i++) {
637                 if (rgb[i].red_reg != rgb[i].green_reg ||
638                 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         return ret;
645 }
646