brintos

brintos / linux-shallow public Read only

0
0
Text · 20.7 KiB · eaed5d1 Raw
689 lines · c
1/*2 * Copyright 2016 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25#include "dc.h"26#include "reg_helper.h"27#include "dcn10/dcn10_dpp.h"28 29#include "dcn10_cm_common.h"30#include "custom_float.h"31 32#define REG(reg) reg33 34#define CTX \35	ctx36 37#undef FN38#define FN(reg_name, field_name) \39	reg->shifts.field_name, reg->masks.field_name40 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_read_color_matrices(struct dc_context *ctx,66				   uint16_t *regval,67				   const struct color_matrices_reg *reg)68{69	uint32_t cur_csc_reg, regval0, regval1;70	unsigned int i = 0;71 72	for (cur_csc_reg = reg->csc_c11_c12;73	     cur_csc_reg <= reg->csc_c33_c34; cur_csc_reg++) {74		REG_GET_2(cur_csc_reg,75				csc_c11, &regval0,76				csc_c12, &regval1);77 78		regval[2 * i] = regval0;79		regval[(2 * i) + 1] = regval1;80 81		i++;82	}83}84 85void cm_helper_program_xfer_func(86		struct dc_context *ctx,87		const struct pwl_params *params,88		const struct xfer_func_reg *reg)89{90	uint32_t reg_region_cur;91	unsigned int i = 0;92 93	REG_SET_2(reg->start_cntl_b, 0,94			exp_region_start, params->corner_points[0].blue.custom_float_x,95			exp_resion_start_segment, 0);96	REG_SET_2(reg->start_cntl_g, 0,97			exp_region_start, params->corner_points[0].green.custom_float_x,98			exp_resion_start_segment, 0);99	REG_SET_2(reg->start_cntl_r, 0,100			exp_region_start, params->corner_points[0].red.custom_float_x,101			exp_resion_start_segment, 0);102 103	REG_SET(reg->start_slope_cntl_b, 0,104			field_region_linear_slope, params->corner_points[0].blue.custom_float_slope);105	REG_SET(reg->start_slope_cntl_g, 0,106			field_region_linear_slope, params->corner_points[0].green.custom_float_slope);107	REG_SET(reg->start_slope_cntl_r, 0,108			field_region_linear_slope, params->corner_points[0].red.custom_float_slope);109 110	REG_SET(reg->start_end_cntl1_b, 0,111			field_region_end, params->corner_points[1].blue.custom_float_x);112	REG_SET_2(reg->start_end_cntl2_b, 0,113			field_region_end_slope, params->corner_points[1].blue.custom_float_slope,114			field_region_end_base, params->corner_points[1].blue.custom_float_y);115 116	REG_SET(reg->start_end_cntl1_g, 0,117			field_region_end, params->corner_points[1].green.custom_float_x);118	REG_SET_2(reg->start_end_cntl2_g, 0,119			field_region_end_slope, params->corner_points[1].green.custom_float_slope,120		field_region_end_base, params->corner_points[1].green.custom_float_y);121 122	REG_SET(reg->start_end_cntl1_r, 0,123			field_region_end, params->corner_points[1].red.custom_float_x);124	REG_SET_2(reg->start_end_cntl2_r, 0,125			field_region_end_slope, params->corner_points[1].red.custom_float_slope,126		field_region_end_base, params->corner_points[1].red.custom_float_y);127 128	for (reg_region_cur = reg->region_start;129			reg_region_cur <= reg->region_end;130			reg_region_cur++) {131 132		const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]);133		const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]);134 135		REG_SET_4(reg_region_cur, 0,136				exp_region0_lut_offset, curve0->offset,137				exp_region0_num_segments, curve0->segments_num,138				exp_region1_lut_offset, curve1->offset,139				exp_region1_num_segments, curve1->segments_num);140 141		i++;142	}143 144}145 146 147 148bool cm_helper_convert_to_custom_float(149		struct pwl_result_data *rgb_resulted,150		struct curve_points3 *corner_points,151		uint32_t hw_points_num,152		bool fixpoint)153{154	struct custom_float_format fmt;155 156	struct pwl_result_data *rgb = rgb_resulted;157 158	uint32_t i = 0;159 160	fmt.exponenta_bits = 6;161	fmt.mantissa_bits = 12;162	fmt.sign = false;163 164	/* corner_points[0] - beginning base, slope offset for R,G,B165	 * corner_points[1] - end base, slope offset for R,G,B166	 */167	if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt,168				&corner_points[0].red.custom_float_x)) {169		BREAK_TO_DEBUGGER();170		return false;171	}172	if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt,173				&corner_points[0].green.custom_float_x)) {174		BREAK_TO_DEBUGGER();175		return false;176	}177	if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt,178				&corner_points[0].blue.custom_float_x)) {179		BREAK_TO_DEBUGGER();180		return false;181	}182 183	if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt,184				&corner_points[0].red.custom_float_offset)) {185		BREAK_TO_DEBUGGER();186		return false;187	}188	if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt,189				&corner_points[0].green.custom_float_offset)) {190		BREAK_TO_DEBUGGER();191		return false;192	}193	if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt,194				&corner_points[0].blue.custom_float_offset)) {195		BREAK_TO_DEBUGGER();196		return false;197	}198 199	if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt,200				&corner_points[0].red.custom_float_slope)) {201		BREAK_TO_DEBUGGER();202		return false;203	}204	if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt,205				&corner_points[0].green.custom_float_slope)) {206		BREAK_TO_DEBUGGER();207		return false;208	}209	if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt,210				&corner_points[0].blue.custom_float_slope)) {211		BREAK_TO_DEBUGGER();212		return false;213	}214 215	fmt.mantissa_bits = 10;216	fmt.sign = false;217 218	if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt,219				&corner_points[1].red.custom_float_x)) {220		BREAK_TO_DEBUGGER();221		return false;222	}223	if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt,224				&corner_points[1].green.custom_float_x)) {225		BREAK_TO_DEBUGGER();226		return false;227	}228	if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt,229				&corner_points[1].blue.custom_float_x)) {230		BREAK_TO_DEBUGGER();231		return false;232	}233 234	if (fixpoint == true) {235		corner_points[1].red.custom_float_y =236				dc_fixpt_clamp_u0d14(corner_points[1].red.y);237		corner_points[1].green.custom_float_y =238				dc_fixpt_clamp_u0d14(corner_points[1].green.y);239		corner_points[1].blue.custom_float_y =240				dc_fixpt_clamp_u0d14(corner_points[1].blue.y);241	} else {242		if (!convert_to_custom_float_format(corner_points[1].red.y,243				&fmt, &corner_points[1].red.custom_float_y)) {244			BREAK_TO_DEBUGGER();245			return false;246		}247		if (!convert_to_custom_float_format(corner_points[1].green.y,248				&fmt, &corner_points[1].green.custom_float_y)) {249			BREAK_TO_DEBUGGER();250			return false;251		}252		if (!convert_to_custom_float_format(corner_points[1].blue.y,253				&fmt, &corner_points[1].blue.custom_float_y)) {254			BREAK_TO_DEBUGGER();255			return false;256		}257	}258 259	if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt,260				&corner_points[1].red.custom_float_slope)) {261		BREAK_TO_DEBUGGER();262		return false;263	}264	if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt,265				&corner_points[1].green.custom_float_slope)) {266		BREAK_TO_DEBUGGER();267		return false;268	}269	if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt,270				&corner_points[1].blue.custom_float_slope)) {271		BREAK_TO_DEBUGGER();272		return false;273	}274 275	if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true)276		return true;277 278	fmt.mantissa_bits = 12;279	fmt.sign = true;280 281	while (i != hw_points_num) {282		if (!convert_to_custom_float_format(rgb->red, &fmt,283						    &rgb->red_reg)) {284			BREAK_TO_DEBUGGER();285			return false;286		}287 288		if (!convert_to_custom_float_format(rgb->green, &fmt,289						    &rgb->green_reg)) {290			BREAK_TO_DEBUGGER();291			return false;292		}293 294		if (!convert_to_custom_float_format(rgb->blue, &fmt,295						    &rgb->blue_reg)) {296			BREAK_TO_DEBUGGER();297			return false;298		}299 300		if (!convert_to_custom_float_format(rgb->delta_red, &fmt,301						    &rgb->delta_red_reg)) {302			BREAK_TO_DEBUGGER();303			return false;304		}305 306		if (!convert_to_custom_float_format(rgb->delta_green, &fmt,307						    &rgb->delta_green_reg)) {308			BREAK_TO_DEBUGGER();309			return false;310		}311 312		if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,313						    &rgb->delta_blue_reg)) {314			BREAK_TO_DEBUGGER();315			return false;316		}317 318		++rgb;319		++i;320	}321 322	return true;323}324 325/* driver uses 32 regions or less, but DCN HW has 34, extra 2 are set to 0 */326#define MAX_REGIONS_NUMBER 34327#define MAX_LOW_POINT      25328#define NUMBER_REGIONS     32329#define NUMBER_SW_SEGMENTS 16330 331#define DC_LOGGER \332		ctx->logger333 334bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx,335				const struct dc_transfer_func *output_tf,336				struct pwl_params *lut_params, bool fixpoint)337{338	struct curve_points3 *corner_points;339	struct pwl_result_data *rgb_resulted;340	struct pwl_result_data *rgb;341	struct pwl_result_data *rgb_plus_1;342	struct pwl_result_data *rgb_minus_1;343 344	int32_t region_start, region_end;345	int32_t i;346	uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;347 348	if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)349		return false;350 351	corner_points = lut_params->corner_points;352	rgb_resulted = lut_params->rgb_resulted;353	hw_points = 0;354 355	memset(lut_params, 0, sizeof(struct pwl_params));356	memset(seg_distr, 0, sizeof(seg_distr));357 358	if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22) {359		/* 32 segments360		 * segments are from 2^-25 to 2^7361		 */362		for (i = 0; i < NUMBER_REGIONS ; i++)363			seg_distr[i] = 3;364 365		region_start = -MAX_LOW_POINT;366		region_end   = NUMBER_REGIONS - MAX_LOW_POINT;367	} else {368		/* 11 segments369		 * segment is from 2^-10 to 2^1370		 * There are less than 256 points, for optimization371		 */372		seg_distr[0] = 3;373		seg_distr[1] = 4;374		seg_distr[2] = 4;375		seg_distr[3] = 4;376		seg_distr[4] = 4;377		seg_distr[5] = 4;378		seg_distr[6] = 4;379		seg_distr[7] = 4;380		seg_distr[8] = 4;381		seg_distr[9] = 4;382		seg_distr[10] = 1;383 384		region_start = -10;385		region_end = 1;386	}387 388	for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)389		seg_distr[i] = -1;390 391	for (k = 0; k < MAX_REGIONS_NUMBER; k++) {392		if (seg_distr[k] != -1)393			hw_points += (1 << seg_distr[k]);394	}395 396	j = 0;397	for (k = 0; k < (region_end - region_start); k++) {398		increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);399		start_index = (region_start + k + MAX_LOW_POINT) *400				NUMBER_SW_SEGMENTS;401		for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;402				i += increment) {403			if (j == hw_points - 1)404				break;405			if (i >= TRANSFER_FUNC_POINTS) {406				DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n",407					     i, TRANSFER_FUNC_POINTS);408				return false;409			}410			rgb_resulted[j].red = output_tf->tf_pts.red[i];411			rgb_resulted[j].green = output_tf->tf_pts.green[i];412			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];413			j++;414		}415	}416 417	/* last point */418	start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;419	rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];420	rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];421	rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];422 423	rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;424	rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;425	rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;426 427	// All 3 color channels have same x428	corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),429					     dc_fixpt_from_int(region_start));430	corner_points[0].green.x = corner_points[0].red.x;431	corner_points[0].blue.x = corner_points[0].red.x;432 433	corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),434					     dc_fixpt_from_int(region_end));435	corner_points[1].green.x = corner_points[1].red.x;436	corner_points[1].blue.x = corner_points[1].red.x;437 438	corner_points[0].red.y = rgb_resulted[0].red;439	corner_points[0].green.y = rgb_resulted[0].green;440	corner_points[0].blue.y = rgb_resulted[0].blue;441 442	corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y,443			corner_points[0].red.x);444	corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y,445			corner_points[0].green.x);446	corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y,447			corner_points[0].blue.x);448 449	/* see comment above, m_arrPoints[1].y should be the Y value for the450	 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)451	 */452	corner_points[1].red.y = rgb_resulted[hw_points - 1].red;453	corner_points[1].green.y = rgb_resulted[hw_points - 1].green;454	corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;455	corner_points[1].red.slope = dc_fixpt_zero;456	corner_points[1].green.slope = dc_fixpt_zero;457	corner_points[1].blue.slope = dc_fixpt_zero;458 459	if (output_tf->tf == TRANSFER_FUNCTION_PQ) {460		/* for PQ, we want to have a straight line from last HW X point,461		 * and the slope to be such that we hit 1.0 at 10000 nits.462		 */463		const struct fixed31_32 end_value =464				dc_fixpt_from_int(125);465 466		corner_points[1].red.slope = dc_fixpt_div(467			dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),468			dc_fixpt_sub(end_value, corner_points[1].red.x));469		corner_points[1].green.slope = dc_fixpt_div(470			dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),471			dc_fixpt_sub(end_value, corner_points[1].green.x));472		corner_points[1].blue.slope = dc_fixpt_div(473			dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),474			dc_fixpt_sub(end_value, corner_points[1].blue.x));475	}476 477	lut_params->hw_points_num = hw_points;478 479	k = 0;480	for (i = 1; i < MAX_REGIONS_NUMBER; i++) {481		if (seg_distr[k] != -1) {482			lut_params->arr_curve_points[k].segments_num =483					seg_distr[k];484			lut_params->arr_curve_points[i].offset =485					lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);486		}487		k++;488	}489 490	if (seg_distr[k] != -1)491		lut_params->arr_curve_points[k].segments_num = seg_distr[k];492 493	rgb = rgb_resulted;494	rgb_plus_1 = rgb_resulted + 1;495	rgb_minus_1 = rgb;496 497	i = 1;498	while (i != hw_points + 1) {499 500		if (i >= hw_points - 1) {501			if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))502				rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);503			if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))504				rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);505			if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))506				rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);507		}508 509		rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);510		rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);511		rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);512 513 514		if (fixpoint == true) {515			uint32_t red_clamp = dc_fixpt_clamp_u0d14(rgb->delta_red);516			uint32_t green_clamp = dc_fixpt_clamp_u0d14(rgb->delta_green);517			uint32_t blue_clamp = dc_fixpt_clamp_u0d14(rgb->delta_blue);518 519			if (red_clamp >> 10 || green_clamp >> 10 || blue_clamp >> 10)520				DC_LOG_WARNING("Losing delta precision while programming shaper LUT.");521 522			rgb->delta_red_reg   = red_clamp & 0x3ff;523			rgb->delta_green_reg = green_clamp & 0x3ff;524			rgb->delta_blue_reg  = blue_clamp & 0x3ff;525			rgb->red_reg         = dc_fixpt_clamp_u0d14(rgb->red);526			rgb->green_reg       = dc_fixpt_clamp_u0d14(rgb->green);527			rgb->blue_reg        = dc_fixpt_clamp_u0d14(rgb->blue);528		}529 530		++rgb_plus_1;531		rgb_minus_1 = rgb;532		++rgb;533		++i;534	}535	cm_helper_convert_to_custom_float(rgb_resulted,536						lut_params->corner_points,537						hw_points, fixpoint);538 539	return true;540}541 542#define NUM_DEGAMMA_REGIONS    12543 544 545bool cm_helper_translate_curve_to_degamma_hw_format(546				const struct dc_transfer_func *output_tf,547				struct pwl_params *lut_params)548{549	struct curve_points3 *corner_points;550	struct pwl_result_data *rgb_resulted;551	struct pwl_result_data *rgb;552	struct pwl_result_data *rgb_plus_1;553 554	int32_t region_start, region_end;555	int32_t i;556	uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;557 558	if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)559		return false;560 561	corner_points = lut_params->corner_points;562	rgb_resulted = lut_params->rgb_resulted;563	hw_points = 0;564 565	memset(lut_params, 0, sizeof(struct pwl_params));566	memset(seg_distr, 0, sizeof(seg_distr));567 568	region_start = -NUM_DEGAMMA_REGIONS;569	region_end   = 0;570 571 572	for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)573		seg_distr[i] = -1;574	/* 12 segments575	 * segments are from 2^-12 to 0576	 */577	for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)578		seg_distr[i] = 4;579 580	for (k = 0; k < MAX_REGIONS_NUMBER; k++) {581		if (seg_distr[k] != -1)582			hw_points += (1 << seg_distr[k]);583	}584 585	j = 0;586	for (k = 0; k < (region_end - region_start); k++) {587		increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);588		start_index = (region_start + k + MAX_LOW_POINT) *589				NUMBER_SW_SEGMENTS;590		for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;591				i += increment) {592			if (j == hw_points - 1)593				break;594			if (i >= TRANSFER_FUNC_POINTS)595				return false;596			rgb_resulted[j].red = output_tf->tf_pts.red[i];597			rgb_resulted[j].green = output_tf->tf_pts.green[i];598			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];599			j++;600		}601	}602 603	/* last point */604	start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;605	rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];606	rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];607	rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];608 609	rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;610	rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;611	rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;612 613	corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),614					     dc_fixpt_from_int(region_start));615	corner_points[0].green.x = corner_points[0].red.x;616	corner_points[0].blue.x = corner_points[0].red.x;617	corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),618					     dc_fixpt_from_int(region_end));619	corner_points[1].green.x = corner_points[1].red.x;620	corner_points[1].blue.x = corner_points[1].red.x;621 622	corner_points[0].red.y = rgb_resulted[0].red;623	corner_points[0].green.y = rgb_resulted[0].green;624	corner_points[0].blue.y = rgb_resulted[0].blue;625 626	/* see comment above, m_arrPoints[1].y should be the Y value for the627	 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)628	 */629	corner_points[1].red.y = rgb_resulted[hw_points - 1].red;630	corner_points[1].green.y = rgb_resulted[hw_points - 1].green;631	corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;632	corner_points[1].red.slope = dc_fixpt_zero;633	corner_points[1].green.slope = dc_fixpt_zero;634	corner_points[1].blue.slope = dc_fixpt_zero;635 636	if (output_tf->tf == TRANSFER_FUNCTION_PQ) {637		/* for PQ, we want to have a straight line from last HW X point,638		 * and the slope to be such that we hit 1.0 at 10000 nits.639		 */640		const struct fixed31_32 end_value =641				dc_fixpt_from_int(125);642 643		corner_points[1].red.slope = dc_fixpt_div(644			dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),645			dc_fixpt_sub(end_value, corner_points[1].red.x));646		corner_points[1].green.slope = dc_fixpt_div(647			dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),648			dc_fixpt_sub(end_value, corner_points[1].green.x));649		corner_points[1].blue.slope = dc_fixpt_div(650			dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),651			dc_fixpt_sub(end_value, corner_points[1].blue.x));652	}653 654	lut_params->hw_points_num = hw_points;655 656	k = 0;657	for (i = 1; i < MAX_REGIONS_NUMBER; i++) {658		if (seg_distr[k] != -1) {659			lut_params->arr_curve_points[k].segments_num =660					seg_distr[k];661			lut_params->arr_curve_points[i].offset =662					lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);663		}664		k++;665	}666 667	if (seg_distr[k] != -1)668		lut_params->arr_curve_points[k].segments_num = seg_distr[k];669 670	rgb = rgb_resulted;671	rgb_plus_1 = rgb_resulted + 1;672 673	i = 1;674	while (i != hw_points + 1) {675		rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);676		rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);677		rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);678 679		++rgb_plus_1;680		++rgb;681		++i;682	}683	cm_helper_convert_to_custom_float(rgb_resulted,684						lut_params->corner_points,685						hw_points, false);686 687	return true;688}689