Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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
 43void 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
108bool 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
289bool 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
435bool 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
593bool 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