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

dcn10_cm_common.c (20245B)


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