cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dcn30_cm_common.c (20417B)


      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	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
    309bool 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
    455bool 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
    631bool 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