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 
cm_helper_program_gamcor_xfer_func(struct dc_context * ctx,const struct pwl_params * params,const struct dcn3_xfer_func_reg * reg)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 
cm3_helper_translate_curve_to_hw_format(const struct dc_transfer_func * output_tf,struct pwl_params * lut_params,bool fixpoint)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 
118 	int32_t region_start, region_end;
119 	int32_t i;
120 	uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
121 
122 	if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
123 		return false;
124 
125 	corner_points = lut_params->corner_points;
126 	rgb_resulted = lut_params->rgb_resulted;
127 	hw_points = 0;
128 
129 	memset(lut_params, 0, sizeof(struct pwl_params));
130 	memset(seg_distr, 0, sizeof(seg_distr));
131 
132 	if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22 ||
133 		output_tf->tf == TRANSFER_FUNCTION_HLG) {
134 		/* 32 segments
135 		 * segments are from 2^-25 to 2^7
136 		 */
137 		for (i = 0; i < NUMBER_REGIONS ; i++)
138 			seg_distr[i] = 3;
139 
140 		region_start = -MAX_LOW_POINT;
141 		region_end   = NUMBER_REGIONS - MAX_LOW_POINT;
142 	} else {
143 		/* 11 segments
144 		 * segment is from 2^-10 to 2^0
145 		 * There are less than 256 points, for optimization
146 		 */
147 		seg_distr[0] = 3;
148 		seg_distr[1] = 4;
149 		seg_distr[2] = 4;
150 		seg_distr[3] = 4;
151 		seg_distr[4] = 4;
152 		seg_distr[5] = 4;
153 		seg_distr[6] = 4;
154 		seg_distr[7] = 4;
155 		seg_distr[8] = 4;
156 		seg_distr[9] = 4;
157 		seg_distr[10] = 1;
158 
159 		region_start = -10;
160 		region_end = 1;
161 	}
162 
163 	for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
164 		seg_distr[i] = -1;
165 
166 	for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
167 		if (seg_distr[k] != -1)
168 			hw_points += (1 << seg_distr[k]);
169 	}
170 
171 	j = 0;
172 	for (k = 0; k < (region_end - region_start); k++) {
173 		increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
174 		start_index = (region_start + k + MAX_LOW_POINT) *
175 				NUMBER_SW_SEGMENTS;
176 		for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
177 				i += increment) {
178 			if (j == hw_points)
179 				break;
180 			rgb_resulted[j].red = output_tf->tf_pts.red[i];
181 			rgb_resulted[j].green = output_tf->tf_pts.green[i];
182 			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
183 			j++;
184 		}
185 	}
186 
187 	/* last point */
188 	start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
189 	rgb_resulted[hw_points].red = output_tf->tf_pts.red[start_index];
190 	rgb_resulted[hw_points].green = output_tf->tf_pts.green[start_index];
191 	rgb_resulted[hw_points].blue = output_tf->tf_pts.blue[start_index];
192 
193 	rgb_resulted[hw_points+1].red = rgb_resulted[hw_points].red;
194 	rgb_resulted[hw_points+1].green = rgb_resulted[hw_points].green;
195 	rgb_resulted[hw_points+1].blue = rgb_resulted[hw_points].blue;
196 
197 	// All 3 color channels have same x
198 	corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
199 					     dc_fixpt_from_int(region_start));
200 	corner_points[0].green.x = corner_points[0].red.x;
201 	corner_points[0].blue.x = corner_points[0].red.x;
202 
203 	corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
204 					     dc_fixpt_from_int(region_end));
205 	corner_points[1].green.x = corner_points[1].red.x;
206 	corner_points[1].blue.x = corner_points[1].red.x;
207 
208 	corner_points[0].red.y = rgb_resulted[0].red;
209 	corner_points[0].green.y = rgb_resulted[0].green;
210 	corner_points[0].blue.y = rgb_resulted[0].blue;
211 
212 	corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y,
213 			corner_points[0].red.x);
214 	corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y,
215 			corner_points[0].green.x);
216 	corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y,
217 			corner_points[0].blue.x);
218 
219 	/* see comment above, m_arrPoints[1].y should be the Y value for the
220 	 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
221 	 */
222 	corner_points[1].red.y = rgb_resulted[hw_points].red;
223 	corner_points[1].green.y = rgb_resulted[hw_points].green;
224 	corner_points[1].blue.y = rgb_resulted[hw_points].blue;
225 	corner_points[1].red.slope = dc_fixpt_zero;
226 	corner_points[1].green.slope = dc_fixpt_zero;
227 	corner_points[1].blue.slope = dc_fixpt_zero;
228 
229 	// DCN3+ have 257 pts in lieu of no separate slope registers
230 	// Prior HW had 256 base+slope pairs
231 	lut_params->hw_points_num = hw_points + 1;
232 
233 	k = 0;
234 	for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
235 		if (seg_distr[k] != -1) {
236 			lut_params->arr_curve_points[k].segments_num =
237 					seg_distr[k];
238 			lut_params->arr_curve_points[i].offset =
239 					lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
240 		}
241 		k++;
242 	}
243 
244 	if (seg_distr[k] != -1)
245 		lut_params->arr_curve_points[k].segments_num = seg_distr[k];
246 
247 	rgb = rgb_resulted;
248 	rgb_plus_1 = rgb_resulted + 1;
249 	rgb_minus_1 = rgb;
250 
251 	if (fixpoint == true) {
252 		i = 1;
253 		while (i != hw_points + 2) {
254 			if (i >= hw_points) {
255 				if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
256 					rgb_plus_1->red = dc_fixpt_add(rgb->red,
257 							rgb_minus_1->delta_red);
258 				if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
259 					rgb_plus_1->green = dc_fixpt_add(rgb->green,
260 							rgb_minus_1->delta_green);
261 				if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
262 					rgb_plus_1->blue = dc_fixpt_add(rgb->blue,
263 							rgb_minus_1->delta_blue);
264 			}
265 
266 			rgb->delta_red_reg   = dc_fixpt_clamp_u0d10(rgb->delta_red);
267 			rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
268 			rgb->delta_blue_reg  = dc_fixpt_clamp_u0d10(rgb->delta_blue);
269 			rgb->red_reg         = dc_fixpt_clamp_u0d14(rgb->red);
270 			rgb->green_reg       = dc_fixpt_clamp_u0d14(rgb->green);
271 			rgb->blue_reg        = dc_fixpt_clamp_u0d14(rgb->blue);
272 
273 			++rgb_plus_1;
274 			rgb_minus_1 = rgb;
275 			++rgb;
276 			++i;
277 		}
278 	}
279 	cm3_helper_convert_to_custom_float(rgb_resulted,
280 						lut_params->corner_points,
281 						hw_points+1, fixpoint);
282 
283 	return true;
284 }
285 
286 #define NUM_DEGAMMA_REGIONS    12
287 
288 
cm3_helper_translate_curve_to_degamma_hw_format(const struct dc_transfer_func * output_tf,struct pwl_params * lut_params)289 bool cm3_helper_translate_curve_to_degamma_hw_format(
290 				const struct dc_transfer_func *output_tf,
291 				struct pwl_params *lut_params)
292 {
293 	struct curve_points3 *corner_points;
294 	struct pwl_result_data *rgb_resulted;
295 	struct pwl_result_data *rgb;
296 	struct pwl_result_data *rgb_plus_1;
297 
298 	int32_t region_start, region_end;
299 	int32_t i;
300 	uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
301 
302 	if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
303 		return false;
304 
305 	corner_points = lut_params->corner_points;
306 	rgb_resulted = lut_params->rgb_resulted;
307 	hw_points = 0;
308 
309 	memset(lut_params, 0, sizeof(struct pwl_params));
310 	memset(seg_distr, 0, sizeof(seg_distr));
311 
312 	region_start = -NUM_DEGAMMA_REGIONS;
313 	region_end   = 0;
314 
315 
316 	for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
317 		seg_distr[i] = -1;
318 	/* 12 segments
319 	 * segments are from 2^-12 to 0
320 	 */
321 	for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
322 		seg_distr[i] = 4;
323 
324 	for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
325 		if (seg_distr[k] != -1)
326 			hw_points += (1 << seg_distr[k]);
327 	}
328 
329 	j = 0;
330 	for (k = 0; k < (region_end - region_start); k++) {
331 		increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
332 		start_index = (region_start + k + MAX_LOW_POINT) *
333 				NUMBER_SW_SEGMENTS;
334 		for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
335 				i += increment) {
336 			if (j == hw_points - 1)
337 				break;
338 			rgb_resulted[j].red = output_tf->tf_pts.red[i];
339 			rgb_resulted[j].green = output_tf->tf_pts.green[i];
340 			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
341 			j++;
342 		}
343 	}
344 
345 	/* last point */
346 	start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
347 	rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
348 	rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
349 	rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
350 
351 	corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
352 					     dc_fixpt_from_int(region_start));
353 	corner_points[0].green.x = corner_points[0].red.x;
354 	corner_points[0].blue.x = corner_points[0].red.x;
355 	corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
356 					     dc_fixpt_from_int(region_end));
357 	corner_points[1].green.x = corner_points[1].red.x;
358 	corner_points[1].blue.x = corner_points[1].red.x;
359 
360 	corner_points[0].red.y = rgb_resulted[0].red;
361 	corner_points[0].green.y = rgb_resulted[0].green;
362 	corner_points[0].blue.y = rgb_resulted[0].blue;
363 
364 	/* see comment above, m_arrPoints[1].y should be the Y value for the
365 	 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
366 	 */
367 	corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
368 	corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
369 	corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
370 	corner_points[1].red.slope = dc_fixpt_zero;
371 	corner_points[1].green.slope = dc_fixpt_zero;
372 	corner_points[1].blue.slope = dc_fixpt_zero;
373 
374 	if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
375 		/* for PQ, we want to have a straight line from last HW X point,
376 		 * and the slope to be such that we hit 1.0 at 10000 nits.
377 		 */
378 		const struct fixed31_32 end_value =
379 				dc_fixpt_from_int(125);
380 
381 		corner_points[1].red.slope = dc_fixpt_div(
382 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
383 			dc_fixpt_sub(end_value, corner_points[1].red.x));
384 		corner_points[1].green.slope = dc_fixpt_div(
385 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
386 			dc_fixpt_sub(end_value, corner_points[1].green.x));
387 		corner_points[1].blue.slope = dc_fixpt_div(
388 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
389 			dc_fixpt_sub(end_value, corner_points[1].blue.x));
390 	}
391 
392 	lut_params->hw_points_num = hw_points;
393 
394 	k = 0;
395 	for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
396 		if (seg_distr[k] != -1) {
397 			lut_params->arr_curve_points[k].segments_num =
398 					seg_distr[k];
399 			lut_params->arr_curve_points[i].offset =
400 					lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
401 		}
402 		k++;
403 	}
404 
405 	if (seg_distr[k] != -1)
406 		lut_params->arr_curve_points[k].segments_num = seg_distr[k];
407 
408 	rgb = rgb_resulted;
409 	rgb_plus_1 = rgb_resulted + 1;
410 
411 	i = 1;
412 	while (i != hw_points + 1) {
413 		if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
414 			rgb_plus_1->red = rgb->red;
415 		if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
416 			rgb_plus_1->green = rgb->green;
417 		if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
418 			rgb_plus_1->blue = rgb->blue;
419 
420 		rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
421 		rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
422 		rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
423 
424 		++rgb_plus_1;
425 		++rgb;
426 		++i;
427 	}
428 	cm3_helper_convert_to_custom_float(rgb_resulted,
429 						lut_params->corner_points,
430 						hw_points, false);
431 
432 	return true;
433 }
434 
cm3_helper_convert_to_custom_float(struct pwl_result_data * rgb_resulted,struct curve_points3 * corner_points,uint32_t hw_points_num,bool fixpoint)435 bool cm3_helper_convert_to_custom_float(
436 		struct pwl_result_data *rgb_resulted,
437 		struct curve_points3 *corner_points,
438 		uint32_t hw_points_num,
439 		bool fixpoint)
440 {
441 	struct custom_float_format fmt;
442 
443 	struct pwl_result_data *rgb = rgb_resulted;
444 
445 	uint32_t i = 0;
446 
447 	fmt.exponenta_bits = 6;
448 	fmt.mantissa_bits = 12;
449 	fmt.sign = false;
450 
451 	/* corner_points[0] - beginning base, slope offset for R,G,B
452 	 * corner_points[1] - end base, slope offset for R,G,B
453 	 */
454 	if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt,
455 				&corner_points[0].red.custom_float_x)) {
456 		BREAK_TO_DEBUGGER();
457 		return false;
458 	}
459 	if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt,
460 				&corner_points[0].green.custom_float_x)) {
461 		BREAK_TO_DEBUGGER();
462 		return false;
463 	}
464 	if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt,
465 				&corner_points[0].blue.custom_float_x)) {
466 		BREAK_TO_DEBUGGER();
467 		return false;
468 	}
469 
470 	if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt,
471 				&corner_points[0].red.custom_float_offset)) {
472 		BREAK_TO_DEBUGGER();
473 		return false;
474 	}
475 	if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt,
476 				&corner_points[0].green.custom_float_offset)) {
477 		BREAK_TO_DEBUGGER();
478 		return false;
479 	}
480 	if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt,
481 				&corner_points[0].blue.custom_float_offset)) {
482 		BREAK_TO_DEBUGGER();
483 		return false;
484 	}
485 
486 	if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt,
487 				&corner_points[0].red.custom_float_slope)) {
488 		BREAK_TO_DEBUGGER();
489 		return false;
490 	}
491 	if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt,
492 				&corner_points[0].green.custom_float_slope)) {
493 		BREAK_TO_DEBUGGER();
494 		return false;
495 	}
496 	if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt,
497 				&corner_points[0].blue.custom_float_slope)) {
498 		BREAK_TO_DEBUGGER();
499 		return false;
500 	}
501 
502 	if (fixpoint == true) {
503 		corner_points[1].red.custom_float_y =
504 				dc_fixpt_clamp_u0d14(corner_points[1].red.y);
505 		corner_points[1].green.custom_float_y =
506 				dc_fixpt_clamp_u0d14(corner_points[1].green.y);
507 		corner_points[1].blue.custom_float_y =
508 				dc_fixpt_clamp_u0d14(corner_points[1].blue.y);
509 	} else {
510 		if (!convert_to_custom_float_format(corner_points[1].red.y,
511 				&fmt, &corner_points[1].red.custom_float_y)) {
512 			BREAK_TO_DEBUGGER();
513 			return false;
514 		}
515 		if (!convert_to_custom_float_format(corner_points[1].green.y,
516 				&fmt, &corner_points[1].green.custom_float_y)) {
517 			BREAK_TO_DEBUGGER();
518 			return false;
519 		}
520 		if (!convert_to_custom_float_format(corner_points[1].blue.y,
521 				&fmt, &corner_points[1].blue.custom_float_y)) {
522 			BREAK_TO_DEBUGGER();
523 			return false;
524 		}
525 	}
526 
527 	fmt.mantissa_bits = 10;
528 	fmt.sign = false;
529 
530 	if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt,
531 				&corner_points[1].red.custom_float_x)) {
532 		BREAK_TO_DEBUGGER();
533 		return false;
534 	}
535 	if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt,
536 				&corner_points[1].green.custom_float_x)) {
537 		BREAK_TO_DEBUGGER();
538 		return false;
539 	}
540 	if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt,
541 				&corner_points[1].blue.custom_float_x)) {
542 		BREAK_TO_DEBUGGER();
543 		return false;
544 	}
545 
546 	if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt,
547 				&corner_points[1].red.custom_float_slope)) {
548 		BREAK_TO_DEBUGGER();
549 		return false;
550 	}
551 	if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt,
552 				&corner_points[1].green.custom_float_slope)) {
553 		BREAK_TO_DEBUGGER();
554 		return false;
555 	}
556 	if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt,
557 				&corner_points[1].blue.custom_float_slope)) {
558 		BREAK_TO_DEBUGGER();
559 		return false;
560 	}
561 
562 	if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true)
563 		return true;
564 
565 	fmt.mantissa_bits = 12;
566 
567 	while (i != hw_points_num) {
568 		if (!convert_to_custom_float_format(rgb->red, &fmt,
569 						    &rgb->red_reg)) {
570 			BREAK_TO_DEBUGGER();
571 			return false;
572 		}
573 
574 		if (!convert_to_custom_float_format(rgb->green, &fmt,
575 						    &rgb->green_reg)) {
576 			BREAK_TO_DEBUGGER();
577 			return false;
578 		}
579 
580 		if (!convert_to_custom_float_format(rgb->blue, &fmt,
581 						    &rgb->blue_reg)) {
582 			BREAK_TO_DEBUGGER();
583 			return false;
584 		}
585 
586 		++rgb;
587 		++i;
588 	}
589 
590 	return true;
591 }
592 
is_rgb_equal(const struct pwl_result_data * rgb,uint32_t num)593 bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num)
594 {
595 	uint32_t i;
596 	bool ret = true;
597 
598 	for (i = 0 ; i < num; i++) {
599 		if (rgb[i].red_reg != rgb[i].green_reg ||
600 		rgb[i].blue_reg != rgb[i].red_reg  ||
601 		rgb[i].blue_reg != rgb[i].green_reg) {
602 			ret = false;
603 			break;
604 		}
605 	}
606 	return ret;
607 }
608 
609