1024f0607SYue Hin Lau /*
2024f0607SYue Hin Lau  * Copyright 2016 Advanced Micro Devices, Inc.
3024f0607SYue Hin Lau  *
4024f0607SYue Hin Lau  * Permission is hereby granted, free of charge, to any person obtaining a
5024f0607SYue Hin Lau  * copy of this software and associated documentation files (the "Software"),
6024f0607SYue Hin Lau  * to deal in the Software without restriction, including without limitation
7024f0607SYue Hin Lau  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8024f0607SYue Hin Lau  * and/or sell copies of the Software, and to permit persons to whom the
9024f0607SYue Hin Lau  * Software is furnished to do so, subject to the following conditions:
10024f0607SYue Hin Lau  *
11024f0607SYue Hin Lau  * The above copyright notice and this permission notice shall be included in
12024f0607SYue Hin Lau  * all copies or substantial portions of the Software.
13024f0607SYue Hin Lau  *
14024f0607SYue Hin Lau  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15024f0607SYue Hin Lau  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16024f0607SYue Hin Lau  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17024f0607SYue Hin Lau  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18024f0607SYue Hin Lau  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19024f0607SYue Hin Lau  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20024f0607SYue Hin Lau  * OTHER DEALINGS IN THE SOFTWARE.
21024f0607SYue Hin Lau  *
22024f0607SYue Hin Lau  * Authors: AMD
23024f0607SYue Hin Lau  *
24024f0607SYue Hin Lau  */
25b6295960SVitaly Prosyak #include "dc.h"
26024f0607SYue Hin Lau #include "reg_helper.h"
27024f0607SYue Hin Lau #include "dcn10_dpp.h"
28024f0607SYue Hin Lau 
29024f0607SYue Hin Lau #include "dcn10_cm_common.h"
30b6295960SVitaly Prosyak #include "custom_float.h"
31024f0607SYue Hin Lau 
32024f0607SYue Hin Lau #define REG(reg) reg
33024f0607SYue Hin Lau 
34024f0607SYue Hin Lau #define CTX \
35024f0607SYue Hin Lau 	ctx
36024f0607SYue Hin Lau 
37024f0607SYue Hin Lau #undef FN
38024f0607SYue Hin Lau #define FN(reg_name, field_name) \
39024f0607SYue Hin Lau 	reg->shifts.field_name, reg->masks.field_name
40024f0607SYue Hin Lau 
cm_helper_program_color_matrices(struct dc_context * ctx,const uint16_t * regval,const struct color_matrices_reg * reg)41024f0607SYue Hin Lau void cm_helper_program_color_matrices(
42024f0607SYue Hin Lau 		struct dc_context *ctx,
43024f0607SYue Hin Lau 		const uint16_t *regval,
44024f0607SYue Hin Lau 		const struct color_matrices_reg *reg)
45024f0607SYue Hin Lau {
46024f0607SYue Hin Lau 	uint32_t cur_csc_reg;
47024f0607SYue Hin Lau 	unsigned int i = 0;
48024f0607SYue Hin Lau 
49024f0607SYue Hin Lau 	for (cur_csc_reg = reg->csc_c11_c12;
50024f0607SYue Hin Lau 			cur_csc_reg <= reg->csc_c33_c34;
51024f0607SYue Hin Lau 			cur_csc_reg++) {
52024f0607SYue Hin Lau 
53024f0607SYue Hin Lau 		const uint16_t *regval0 = &(regval[2 * i]);
54024f0607SYue Hin Lau 		const uint16_t *regval1 = &(regval[(2 * i) + 1]);
55024f0607SYue Hin Lau 
56024f0607SYue Hin Lau 		REG_SET_2(cur_csc_reg, 0,
57024f0607SYue Hin Lau 				csc_c11, *regval0,
58024f0607SYue Hin Lau 				csc_c12, *regval1);
59024f0607SYue Hin Lau 
60024f0607SYue Hin Lau 		i++;
61024f0607SYue Hin Lau 	}
62024f0607SYue Hin Lau 
63024f0607SYue Hin Lau }
64024f0607SYue Hin Lau 
cm_helper_program_xfer_func(struct dc_context * ctx,const struct pwl_params * params,const struct xfer_func_reg * reg)65024f0607SYue Hin Lau void cm_helper_program_xfer_func(
66024f0607SYue Hin Lau 		struct dc_context *ctx,
67024f0607SYue Hin Lau 		const struct pwl_params *params,
68024f0607SYue Hin Lau 		const struct xfer_func_reg *reg)
69024f0607SYue Hin Lau {
70024f0607SYue Hin Lau 	uint32_t reg_region_cur;
71024f0607SYue Hin Lau 	unsigned int i = 0;
72024f0607SYue Hin Lau 
73024f0607SYue Hin Lau 	REG_SET_2(reg->start_cntl_b, 0,
7409757809SKrunoslav Kovac 			exp_region_start, params->corner_points[0].blue.custom_float_x,
75024f0607SYue Hin Lau 			exp_resion_start_segment, 0);
76024f0607SYue Hin Lau 	REG_SET_2(reg->start_cntl_g, 0,
7709757809SKrunoslav Kovac 			exp_region_start, params->corner_points[0].green.custom_float_x,
78024f0607SYue Hin Lau 			exp_resion_start_segment, 0);
79024f0607SYue Hin Lau 	REG_SET_2(reg->start_cntl_r, 0,
8009757809SKrunoslav Kovac 			exp_region_start, params->corner_points[0].red.custom_float_x,
81024f0607SYue Hin Lau 			exp_resion_start_segment, 0);
82024f0607SYue Hin Lau 
83024f0607SYue Hin Lau 	REG_SET(reg->start_slope_cntl_b, 0,
8409757809SKrunoslav Kovac 			field_region_linear_slope, params->corner_points[0].blue.custom_float_slope);
85024f0607SYue Hin Lau 	REG_SET(reg->start_slope_cntl_g, 0,
8609757809SKrunoslav Kovac 			field_region_linear_slope, params->corner_points[0].green.custom_float_slope);
87024f0607SYue Hin Lau 	REG_SET(reg->start_slope_cntl_r, 0,
8809757809SKrunoslav Kovac 			field_region_linear_slope, params->corner_points[0].red.custom_float_slope);
89024f0607SYue Hin Lau 
90024f0607SYue Hin Lau 	REG_SET(reg->start_end_cntl1_b, 0,
9109757809SKrunoslav Kovac 			field_region_end, params->corner_points[1].blue.custom_float_x);
92024f0607SYue Hin Lau 	REG_SET_2(reg->start_end_cntl2_b, 0,
9309757809SKrunoslav Kovac 			field_region_end_slope, params->corner_points[1].blue.custom_float_slope,
9409757809SKrunoslav Kovac 			field_region_end_base, params->corner_points[1].blue.custom_float_y);
95024f0607SYue Hin Lau 
96024f0607SYue Hin Lau 	REG_SET(reg->start_end_cntl1_g, 0,
9709757809SKrunoslav Kovac 			field_region_end, params->corner_points[1].green.custom_float_x);
98024f0607SYue Hin Lau 	REG_SET_2(reg->start_end_cntl2_g, 0,
9909757809SKrunoslav Kovac 			field_region_end_slope, params->corner_points[1].green.custom_float_slope,
10009757809SKrunoslav Kovac 		field_region_end_base, params->corner_points[1].green.custom_float_y);
101024f0607SYue Hin Lau 
102024f0607SYue Hin Lau 	REG_SET(reg->start_end_cntl1_r, 0,
10309757809SKrunoslav Kovac 			field_region_end, params->corner_points[1].red.custom_float_x);
104024f0607SYue Hin Lau 	REG_SET_2(reg->start_end_cntl2_r, 0,
10509757809SKrunoslav Kovac 			field_region_end_slope, params->corner_points[1].red.custom_float_slope,
10609757809SKrunoslav Kovac 		field_region_end_base, params->corner_points[1].red.custom_float_y);
107024f0607SYue Hin Lau 
108024f0607SYue Hin Lau 	for (reg_region_cur = reg->region_start;
109024f0607SYue Hin Lau 			reg_region_cur <= reg->region_end;
110024f0607SYue Hin Lau 			reg_region_cur++) {
111024f0607SYue Hin Lau 
112024f0607SYue Hin Lau 		const struct gamma_curve *curve0 = &(params->arr_curve_points[2 * i]);
113024f0607SYue Hin Lau 		const struct gamma_curve *curve1 = &(params->arr_curve_points[(2 * i) + 1]);
114024f0607SYue Hin Lau 
115024f0607SYue Hin Lau 		REG_SET_4(reg_region_cur, 0,
116024f0607SYue Hin Lau 				exp_region0_lut_offset, curve0->offset,
117024f0607SYue Hin Lau 				exp_region0_num_segments, curve0->segments_num,
118024f0607SYue Hin Lau 				exp_region1_lut_offset, curve1->offset,
119024f0607SYue Hin Lau 				exp_region1_num_segments, curve1->segments_num);
120024f0607SYue Hin Lau 
121024f0607SYue Hin Lau 		i++;
122024f0607SYue Hin Lau 	}
123024f0607SYue Hin Lau 
124024f0607SYue Hin Lau }
125b6295960SVitaly Prosyak 
126b6295960SVitaly Prosyak 
127b6295960SVitaly Prosyak 
cm_helper_convert_to_custom_float(struct pwl_result_data * rgb_resulted,struct curve_points3 * corner_points,uint32_t hw_points_num,bool fixpoint)128b6295960SVitaly Prosyak bool cm_helper_convert_to_custom_float(
129b6295960SVitaly Prosyak 		struct pwl_result_data *rgb_resulted,
13009757809SKrunoslav Kovac 		struct curve_points3 *corner_points,
131b6295960SVitaly Prosyak 		uint32_t hw_points_num,
132b6295960SVitaly Prosyak 		bool fixpoint)
133b6295960SVitaly Prosyak {
134b6295960SVitaly Prosyak 	struct custom_float_format fmt;
135b6295960SVitaly Prosyak 
136b6295960SVitaly Prosyak 	struct pwl_result_data *rgb = rgb_resulted;
137b6295960SVitaly Prosyak 
138b6295960SVitaly Prosyak 	uint32_t i = 0;
139b6295960SVitaly Prosyak 
140b6295960SVitaly Prosyak 	fmt.exponenta_bits = 6;
141b6295960SVitaly Prosyak 	fmt.mantissa_bits = 12;
142b6295960SVitaly Prosyak 	fmt.sign = false;
143b6295960SVitaly Prosyak 
14409757809SKrunoslav Kovac 	/* corner_points[0] - beginning base, slope offset for R,G,B
14509757809SKrunoslav Kovac 	 * corner_points[1] - end base, slope offset for R,G,B
14609757809SKrunoslav Kovac 	 */
14709757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt,
14809757809SKrunoslav Kovac 				&corner_points[0].red.custom_float_x)) {
14909757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
15009757809SKrunoslav Kovac 		return false;
15109757809SKrunoslav Kovac 	}
15209757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt,
15309757809SKrunoslav Kovac 				&corner_points[0].green.custom_float_x)) {
15409757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
15509757809SKrunoslav Kovac 		return false;
15609757809SKrunoslav Kovac 	}
15709757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt,
15809757809SKrunoslav Kovac 				&corner_points[0].blue.custom_float_x)) {
159b6295960SVitaly Prosyak 		BREAK_TO_DEBUGGER();
160b6295960SVitaly Prosyak 		return false;
161b6295960SVitaly Prosyak 	}
162b6295960SVitaly Prosyak 
16309757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt,
16409757809SKrunoslav Kovac 				&corner_points[0].red.custom_float_offset)) {
16509757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
16609757809SKrunoslav Kovac 		return false;
16709757809SKrunoslav Kovac 	}
16809757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt,
16909757809SKrunoslav Kovac 				&corner_points[0].green.custom_float_offset)) {
17009757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
17109757809SKrunoslav Kovac 		return false;
17209757809SKrunoslav Kovac 	}
17309757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt,
17409757809SKrunoslav Kovac 				&corner_points[0].blue.custom_float_offset)) {
175b6295960SVitaly Prosyak 		BREAK_TO_DEBUGGER();
176b6295960SVitaly Prosyak 		return false;
177b6295960SVitaly Prosyak 	}
178b6295960SVitaly Prosyak 
17909757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt,
18009757809SKrunoslav Kovac 				&corner_points[0].red.custom_float_slope)) {
18109757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
18209757809SKrunoslav Kovac 		return false;
18309757809SKrunoslav Kovac 	}
18409757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt,
18509757809SKrunoslav Kovac 				&corner_points[0].green.custom_float_slope)) {
18609757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
18709757809SKrunoslav Kovac 		return false;
18809757809SKrunoslav Kovac 	}
18909757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt,
19009757809SKrunoslav Kovac 				&corner_points[0].blue.custom_float_slope)) {
191b6295960SVitaly Prosyak 		BREAK_TO_DEBUGGER();
192b6295960SVitaly Prosyak 		return false;
193b6295960SVitaly Prosyak 	}
194b6295960SVitaly Prosyak 
195b6295960SVitaly Prosyak 	fmt.mantissa_bits = 10;
196b6295960SVitaly Prosyak 	fmt.sign = false;
197b6295960SVitaly Prosyak 
19809757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt,
19909757809SKrunoslav Kovac 				&corner_points[1].red.custom_float_x)) {
20009757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
20109757809SKrunoslav Kovac 		return false;
20209757809SKrunoslav Kovac 	}
20309757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt,
20409757809SKrunoslav Kovac 				&corner_points[1].green.custom_float_x)) {
20509757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
20609757809SKrunoslav Kovac 		return false;
20709757809SKrunoslav Kovac 	}
20809757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt,
20909757809SKrunoslav Kovac 				&corner_points[1].blue.custom_float_x)) {
210b6295960SVitaly Prosyak 		BREAK_TO_DEBUGGER();
211b6295960SVitaly Prosyak 		return false;
212b6295960SVitaly Prosyak 	}
213b6295960SVitaly Prosyak 
21409757809SKrunoslav Kovac 	if (fixpoint == true) {
21509757809SKrunoslav Kovac 		corner_points[1].red.custom_float_y =
21609757809SKrunoslav Kovac 				dc_fixpt_clamp_u0d14(corner_points[1].red.y);
21709757809SKrunoslav Kovac 		corner_points[1].green.custom_float_y =
21809757809SKrunoslav Kovac 				dc_fixpt_clamp_u0d14(corner_points[1].green.y);
21909757809SKrunoslav Kovac 		corner_points[1].blue.custom_float_y =
22009757809SKrunoslav Kovac 				dc_fixpt_clamp_u0d14(corner_points[1].blue.y);
22109757809SKrunoslav Kovac 	} else {
22209757809SKrunoslav Kovac 		if (!convert_to_custom_float_format(corner_points[1].red.y,
22309757809SKrunoslav Kovac 				&fmt, &corner_points[1].red.custom_float_y)) {
224b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
225b6295960SVitaly Prosyak 			return false;
226b6295960SVitaly Prosyak 		}
22709757809SKrunoslav Kovac 		if (!convert_to_custom_float_format(corner_points[1].green.y,
22809757809SKrunoslav Kovac 				&fmt, &corner_points[1].green.custom_float_y)) {
22909757809SKrunoslav Kovac 			BREAK_TO_DEBUGGER();
23009757809SKrunoslav Kovac 			return false;
23109757809SKrunoslav Kovac 		}
23209757809SKrunoslav Kovac 		if (!convert_to_custom_float_format(corner_points[1].blue.y,
23309757809SKrunoslav Kovac 				&fmt, &corner_points[1].blue.custom_float_y)) {
23409757809SKrunoslav Kovac 			BREAK_TO_DEBUGGER();
23509757809SKrunoslav Kovac 			return false;
23609757809SKrunoslav Kovac 		}
23709757809SKrunoslav Kovac 	}
238b6295960SVitaly Prosyak 
23909757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt,
24009757809SKrunoslav Kovac 				&corner_points[1].red.custom_float_slope)) {
24109757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
24209757809SKrunoslav Kovac 		return false;
24309757809SKrunoslav Kovac 	}
24409757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt,
24509757809SKrunoslav Kovac 				&corner_points[1].green.custom_float_slope)) {
24609757809SKrunoslav Kovac 		BREAK_TO_DEBUGGER();
24709757809SKrunoslav Kovac 		return false;
24809757809SKrunoslav Kovac 	}
24909757809SKrunoslav Kovac 	if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt,
25009757809SKrunoslav Kovac 				&corner_points[1].blue.custom_float_slope)) {
251b6295960SVitaly Prosyak 		BREAK_TO_DEBUGGER();
252b6295960SVitaly Prosyak 		return false;
253b6295960SVitaly Prosyak 	}
254b6295960SVitaly Prosyak 
255b6295960SVitaly Prosyak 	if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true)
256b6295960SVitaly Prosyak 		return true;
257b6295960SVitaly Prosyak 
258b6295960SVitaly Prosyak 	fmt.mantissa_bits = 12;
259b6295960SVitaly Prosyak 	fmt.sign = true;
260b6295960SVitaly Prosyak 
261b6295960SVitaly Prosyak 	while (i != hw_points_num) {
262b6295960SVitaly Prosyak 		if (!convert_to_custom_float_format(rgb->red, &fmt,
263b6295960SVitaly Prosyak 						    &rgb->red_reg)) {
264b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
265b6295960SVitaly Prosyak 			return false;
266b6295960SVitaly Prosyak 		}
267b6295960SVitaly Prosyak 
268b6295960SVitaly Prosyak 		if (!convert_to_custom_float_format(rgb->green, &fmt,
269b6295960SVitaly Prosyak 						    &rgb->green_reg)) {
270b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
271b6295960SVitaly Prosyak 			return false;
272b6295960SVitaly Prosyak 		}
273b6295960SVitaly Prosyak 
274b6295960SVitaly Prosyak 		if (!convert_to_custom_float_format(rgb->blue, &fmt,
275b6295960SVitaly Prosyak 						    &rgb->blue_reg)) {
276b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
277b6295960SVitaly Prosyak 			return false;
278b6295960SVitaly Prosyak 		}
279b6295960SVitaly Prosyak 
280b6295960SVitaly Prosyak 		if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
281b6295960SVitaly Prosyak 						    &rgb->delta_red_reg)) {
282b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
283b6295960SVitaly Prosyak 			return false;
284b6295960SVitaly Prosyak 		}
285b6295960SVitaly Prosyak 
286b6295960SVitaly Prosyak 		if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
287b6295960SVitaly Prosyak 						    &rgb->delta_green_reg)) {
288b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
289b6295960SVitaly Prosyak 			return false;
290b6295960SVitaly Prosyak 		}
291b6295960SVitaly Prosyak 
292b6295960SVitaly Prosyak 		if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
293b6295960SVitaly Prosyak 						    &rgb->delta_blue_reg)) {
294b6295960SVitaly Prosyak 			BREAK_TO_DEBUGGER();
295b6295960SVitaly Prosyak 			return false;
296b6295960SVitaly Prosyak 		}
297b6295960SVitaly Prosyak 
298b6295960SVitaly Prosyak 		++rgb;
299b6295960SVitaly Prosyak 		++i;
300b6295960SVitaly Prosyak 	}
301b6295960SVitaly Prosyak 
302b6295960SVitaly Prosyak 	return true;
303b6295960SVitaly Prosyak }
304b6295960SVitaly Prosyak 
3058f8372c7SKrunoslav Kovac /* driver uses 32 regions or less, but DCN HW has 34, extra 2 are set to 0 */
306b6295960SVitaly Prosyak #define MAX_REGIONS_NUMBER 34
307b6295960SVitaly Prosyak #define MAX_LOW_POINT      25
3088f8372c7SKrunoslav Kovac #define NUMBER_REGIONS     32
3098f8372c7SKrunoslav Kovac #define NUMBER_SW_SEGMENTS 16
310b6295960SVitaly Prosyak 
31127fc10d1SHarry Wentland #define DC_LOGGER \
31227fc10d1SHarry Wentland 		ctx->logger
31327fc10d1SHarry Wentland 
cm_helper_translate_curve_to_hw_format(struct dc_context * ctx,const struct dc_transfer_func * output_tf,struct pwl_params * lut_params,bool fixpoint)31427fc10d1SHarry Wentland bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx,
315b6295960SVitaly Prosyak 				const struct dc_transfer_func *output_tf,
316b6295960SVitaly Prosyak 				struct pwl_params *lut_params, bool fixpoint)
317b6295960SVitaly Prosyak {
31809757809SKrunoslav Kovac 	struct curve_points3 *corner_points;
319b6295960SVitaly Prosyak 	struct pwl_result_data *rgb_resulted;
320b6295960SVitaly Prosyak 	struct pwl_result_data *rgb;
321b6295960SVitaly Prosyak 	struct pwl_result_data *rgb_plus_1;
322c11e57f0SVladimir Stempen 	struct pwl_result_data *rgb_minus_1;
323b6295960SVitaly Prosyak 
3248f8372c7SKrunoslav Kovac 	int32_t region_start, region_end;
325b6295960SVitaly Prosyak 	int32_t i;
326b6295960SVitaly Prosyak 	uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
327b6295960SVitaly Prosyak 
328b6295960SVitaly Prosyak 	if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
329b6295960SVitaly Prosyak 		return false;
330b6295960SVitaly Prosyak 
33109757809SKrunoslav Kovac 	corner_points = lut_params->corner_points;
332b6295960SVitaly Prosyak 	rgb_resulted = lut_params->rgb_resulted;
333b6295960SVitaly Prosyak 	hw_points = 0;
334b6295960SVitaly Prosyak 
335b6295960SVitaly Prosyak 	memset(lut_params, 0, sizeof(struct pwl_params));
336b6295960SVitaly Prosyak 	memset(seg_distr, 0, sizeof(seg_distr));
337b6295960SVitaly Prosyak 
338e1e8a020SSivapiriyanKumarasamy 	if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22) {
339b6295960SVitaly Prosyak 		/* 32 segments
340b6295960SVitaly Prosyak 		 * segments are from 2^-25 to 2^7
341b6295960SVitaly Prosyak 		 */
3428f8372c7SKrunoslav Kovac 		for (i = 0; i < NUMBER_REGIONS ; i++)
343b6295960SVitaly Prosyak 			seg_distr[i] = 3;
344b6295960SVitaly Prosyak 
3458f8372c7SKrunoslav Kovac 		region_start = -MAX_LOW_POINT;
3468f8372c7SKrunoslav Kovac 		region_end   = NUMBER_REGIONS - MAX_LOW_POINT;
347b6295960SVitaly Prosyak 	} else {
3488221b6eaSWyatt Wood 		/* 11 segments
3498221b6eaSWyatt Wood 		 * segment is from 2^-10 to 2^1
350b6295960SVitaly Prosyak 		 * There are less than 256 points, for optimization
351b6295960SVitaly Prosyak 		 */
352b6295960SVitaly Prosyak 		seg_distr[0] = 3;
353b6295960SVitaly Prosyak 		seg_distr[1] = 4;
354b6295960SVitaly Prosyak 		seg_distr[2] = 4;
355b6295960SVitaly Prosyak 		seg_distr[3] = 4;
356b6295960SVitaly Prosyak 		seg_distr[4] = 4;
357b6295960SVitaly Prosyak 		seg_distr[5] = 4;
358b6295960SVitaly Prosyak 		seg_distr[6] = 4;
359b6295960SVitaly Prosyak 		seg_distr[7] = 4;
3608f8372c7SKrunoslav Kovac 		seg_distr[8] = 4;
3618f8372c7SKrunoslav Kovac 		seg_distr[9] = 4;
3621cbcfc97SAnthony Koo 		seg_distr[10] = 1;
363b6295960SVitaly Prosyak 
3648f8372c7SKrunoslav Kovac 		region_start = -10;
3651cbcfc97SAnthony Koo 		region_end = 1;
366b6295960SVitaly Prosyak 	}
367b6295960SVitaly Prosyak 
3688f8372c7SKrunoslav Kovac 	for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
369b6295960SVitaly Prosyak 		seg_distr[i] = -1;
370b6295960SVitaly Prosyak 
371b6295960SVitaly Prosyak 	for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
372b6295960SVitaly Prosyak 		if (seg_distr[k] != -1)
373b6295960SVitaly Prosyak 			hw_points += (1 << seg_distr[k]);
374b6295960SVitaly Prosyak 	}
375b6295960SVitaly Prosyak 
376b6295960SVitaly Prosyak 	j = 0;
3778f8372c7SKrunoslav Kovac 	for (k = 0; k < (region_end - region_start); k++) {
3788f8372c7SKrunoslav Kovac 		increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
3798f8372c7SKrunoslav Kovac 		start_index = (region_start + k + MAX_LOW_POINT) *
3808f8372c7SKrunoslav Kovac 				NUMBER_SW_SEGMENTS;
3818f8372c7SKrunoslav Kovac 		for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
3828f8372c7SKrunoslav Kovac 				i += increment) {
383b6295960SVitaly Prosyak 			if (j == hw_points - 1)
384b6295960SVitaly Prosyak 				break;
3854e8c8b37SSrinivasan Shanmugam 			if (i >= TRANSFER_FUNC_POINTS) {
3864e8c8b37SSrinivasan Shanmugam 				DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n",
3874e8c8b37SSrinivasan Shanmugam 					     i, TRANSFER_FUNC_POINTS);
3884e8c8b37SSrinivasan Shanmugam 				return false;
3894e8c8b37SSrinivasan Shanmugam 			}
390b6295960SVitaly Prosyak 			rgb_resulted[j].red = output_tf->tf_pts.red[i];
391b6295960SVitaly Prosyak 			rgb_resulted[j].green = output_tf->tf_pts.green[i];
392b6295960SVitaly Prosyak 			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
393b6295960SVitaly Prosyak 			j++;
394b6295960SVitaly Prosyak 		}
395b6295960SVitaly Prosyak 	}
396b6295960SVitaly Prosyak 
397b6295960SVitaly Prosyak 	/* last point */
3988f8372c7SKrunoslav Kovac 	start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
399b6295960SVitaly Prosyak 	rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
400b6295960SVitaly Prosyak 	rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
401b6295960SVitaly Prosyak 	rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
402b6295960SVitaly Prosyak 
403ceba1a01SAidan Yang 	rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
404ceba1a01SAidan Yang 	rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
405ceba1a01SAidan Yang 	rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
406ceba1a01SAidan Yang 
40709757809SKrunoslav Kovac 	// All 3 color channels have same x
40809757809SKrunoslav Kovac 	corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
409eb0e5154SDmytro Laktyushkin 					     dc_fixpt_from_int(region_start));
41009757809SKrunoslav Kovac 	corner_points[0].green.x = corner_points[0].red.x;
41109757809SKrunoslav Kovac 	corner_points[0].blue.x = corner_points[0].red.x;
41209757809SKrunoslav Kovac 
41309757809SKrunoslav Kovac 	corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
414eb0e5154SDmytro Laktyushkin 					     dc_fixpt_from_int(region_end));
41509757809SKrunoslav Kovac 	corner_points[1].green.x = corner_points[1].red.x;
41609757809SKrunoslav Kovac 	corner_points[1].blue.x = corner_points[1].red.x;
417b6295960SVitaly Prosyak 
41809757809SKrunoslav Kovac 	corner_points[0].red.y = rgb_resulted[0].red;
41909757809SKrunoslav Kovac 	corner_points[0].green.y = rgb_resulted[0].green;
42009757809SKrunoslav Kovac 	corner_points[0].blue.y = rgb_resulted[0].blue;
421b6295960SVitaly Prosyak 
42209757809SKrunoslav Kovac 	corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y,
42309757809SKrunoslav Kovac 			corner_points[0].red.x);
42409757809SKrunoslav Kovac 	corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y,
42509757809SKrunoslav Kovac 			corner_points[0].green.x);
42609757809SKrunoslav Kovac 	corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y,
42709757809SKrunoslav Kovac 			corner_points[0].blue.x);
428b6295960SVitaly Prosyak 
429b6295960SVitaly Prosyak 	/* see comment above, m_arrPoints[1].y should be the Y value for the
430b6295960SVitaly Prosyak 	 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
431b6295960SVitaly Prosyak 	 */
43209757809SKrunoslav Kovac 	corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
43309757809SKrunoslav Kovac 	corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
43409757809SKrunoslav Kovac 	corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
43509757809SKrunoslav Kovac 	corner_points[1].red.slope = dc_fixpt_zero;
43609757809SKrunoslav Kovac 	corner_points[1].green.slope = dc_fixpt_zero;
43709757809SKrunoslav Kovac 	corner_points[1].blue.slope = dc_fixpt_zero;
438b6295960SVitaly Prosyak 
439b6295960SVitaly Prosyak 	if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
440b6295960SVitaly Prosyak 		/* for PQ, we want to have a straight line from last HW X point,
441b6295960SVitaly Prosyak 		 * and the slope to be such that we hit 1.0 at 10000 nits.
442b6295960SVitaly Prosyak 		 */
443b6295960SVitaly Prosyak 		const struct fixed31_32 end_value =
444eb0e5154SDmytro Laktyushkin 				dc_fixpt_from_int(125);
445b6295960SVitaly Prosyak 
44609757809SKrunoslav Kovac 		corner_points[1].red.slope = dc_fixpt_div(
44709757809SKrunoslav Kovac 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
44809757809SKrunoslav Kovac 			dc_fixpt_sub(end_value, corner_points[1].red.x));
44909757809SKrunoslav Kovac 		corner_points[1].green.slope = dc_fixpt_div(
45009757809SKrunoslav Kovac 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
45109757809SKrunoslav Kovac 			dc_fixpt_sub(end_value, corner_points[1].green.x));
45209757809SKrunoslav Kovac 		corner_points[1].blue.slope = dc_fixpt_div(
45309757809SKrunoslav Kovac 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
45409757809SKrunoslav Kovac 			dc_fixpt_sub(end_value, corner_points[1].blue.x));
455b6295960SVitaly Prosyak 	}
456b6295960SVitaly Prosyak 
457b6295960SVitaly Prosyak 	lut_params->hw_points_num = hw_points;
458b6295960SVitaly Prosyak 
45963bd5444SHarry Wentland 	k = 0;
46063bd5444SHarry Wentland 	for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
461b6295960SVitaly Prosyak 		if (seg_distr[k] != -1) {
462b6295960SVitaly Prosyak 			lut_params->arr_curve_points[k].segments_num =
463b6295960SVitaly Prosyak 					seg_distr[k];
464b6295960SVitaly Prosyak 			lut_params->arr_curve_points[i].offset =
465b6295960SVitaly Prosyak 					lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
466b6295960SVitaly Prosyak 		}
46763bd5444SHarry Wentland 		k++;
468b6295960SVitaly Prosyak 	}
469b6295960SVitaly Prosyak 
470b6295960SVitaly Prosyak 	if (seg_distr[k] != -1)
471b6295960SVitaly Prosyak 		lut_params->arr_curve_points[k].segments_num = seg_distr[k];
472b6295960SVitaly Prosyak 
473b6295960SVitaly Prosyak 	rgb = rgb_resulted;
474b6295960SVitaly Prosyak 	rgb_plus_1 = rgb_resulted + 1;
475c11e57f0SVladimir Stempen 	rgb_minus_1 = rgb;
476b6295960SVitaly Prosyak 
477b6295960SVitaly Prosyak 	i = 1;
478b6295960SVitaly Prosyak 	while (i != hw_points + 1) {
479c11e57f0SVladimir Stempen 
480c11e57f0SVladimir Stempen 		if (i >= hw_points - 1) {
481c11e57f0SVladimir Stempen 			if (dc_fixpt_lt(rgb_plus_1->red, rgb->red))
482c11e57f0SVladimir Stempen 				rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red);
483c11e57f0SVladimir Stempen 			if (dc_fixpt_lt(rgb_plus_1->green, rgb->green))
484c11e57f0SVladimir Stempen 				rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green);
485c11e57f0SVladimir Stempen 			if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue))
486c11e57f0SVladimir Stempen 				rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue);
487c11e57f0SVladimir Stempen 		}
488c11e57f0SVladimir Stempen 
489eb0e5154SDmytro Laktyushkin 		rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
490eb0e5154SDmytro Laktyushkin 		rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
491eb0e5154SDmytro Laktyushkin 		rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
492b6295960SVitaly Prosyak 
49327fc10d1SHarry Wentland 
494b6295960SVitaly Prosyak 		if (fixpoint == true) {
49527fc10d1SHarry Wentland 			uint32_t red_clamp = dc_fixpt_clamp_u0d14(rgb->delta_red);
49627fc10d1SHarry Wentland 			uint32_t green_clamp = dc_fixpt_clamp_u0d14(rgb->delta_green);
49727fc10d1SHarry Wentland 			uint32_t blue_clamp = dc_fixpt_clamp_u0d14(rgb->delta_blue);
49827fc10d1SHarry Wentland 
49927fc10d1SHarry Wentland 			if (red_clamp >> 10 || green_clamp >> 10 || blue_clamp >> 10)
50027fc10d1SHarry Wentland 				DC_LOG_WARNING("Losing delta precision while programming shaper LUT.");
50127fc10d1SHarry Wentland 
50227fc10d1SHarry Wentland 			rgb->delta_red_reg   = red_clamp & 0x3ff;
50327fc10d1SHarry Wentland 			rgb->delta_green_reg = green_clamp & 0x3ff;
50427fc10d1SHarry Wentland 			rgb->delta_blue_reg  = blue_clamp & 0x3ff;
505eb0e5154SDmytro Laktyushkin 			rgb->red_reg         = dc_fixpt_clamp_u0d14(rgb->red);
506eb0e5154SDmytro Laktyushkin 			rgb->green_reg       = dc_fixpt_clamp_u0d14(rgb->green);
507eb0e5154SDmytro Laktyushkin 			rgb->blue_reg        = dc_fixpt_clamp_u0d14(rgb->blue);
508b6295960SVitaly Prosyak 		}
509b6295960SVitaly Prosyak 
510b6295960SVitaly Prosyak 		++rgb_plus_1;
511c11e57f0SVladimir Stempen 		rgb_minus_1 = rgb;
512b6295960SVitaly Prosyak 		++rgb;
513b6295960SVitaly Prosyak 		++i;
514b6295960SVitaly Prosyak 	}
515b6295960SVitaly Prosyak 	cm_helper_convert_to_custom_float(rgb_resulted,
51609757809SKrunoslav Kovac 						lut_params->corner_points,
517b6295960SVitaly Prosyak 						hw_points, fixpoint);
518b6295960SVitaly Prosyak 
519b6295960SVitaly Prosyak 	return true;
520b6295960SVitaly Prosyak }
52144c6f2e5SVitaly Prosyak 
52244c6f2e5SVitaly Prosyak #define NUM_DEGAMMA_REGIONS    12
52344c6f2e5SVitaly Prosyak 
52444c6f2e5SVitaly Prosyak 
cm_helper_translate_curve_to_degamma_hw_format(const struct dc_transfer_func * output_tf,struct pwl_params * lut_params)52544c6f2e5SVitaly Prosyak bool cm_helper_translate_curve_to_degamma_hw_format(
52644c6f2e5SVitaly Prosyak 				const struct dc_transfer_func *output_tf,
52744c6f2e5SVitaly Prosyak 				struct pwl_params *lut_params)
52844c6f2e5SVitaly Prosyak {
52909757809SKrunoslav Kovac 	struct curve_points3 *corner_points;
53044c6f2e5SVitaly Prosyak 	struct pwl_result_data *rgb_resulted;
53144c6f2e5SVitaly Prosyak 	struct pwl_result_data *rgb;
53244c6f2e5SVitaly Prosyak 	struct pwl_result_data *rgb_plus_1;
53344c6f2e5SVitaly Prosyak 
53444c6f2e5SVitaly Prosyak 	int32_t region_start, region_end;
53544c6f2e5SVitaly Prosyak 	int32_t i;
53644c6f2e5SVitaly Prosyak 	uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
53744c6f2e5SVitaly Prosyak 
53844c6f2e5SVitaly Prosyak 	if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
53944c6f2e5SVitaly Prosyak 		return false;
54044c6f2e5SVitaly Prosyak 
54109757809SKrunoslav Kovac 	corner_points = lut_params->corner_points;
54244c6f2e5SVitaly Prosyak 	rgb_resulted = lut_params->rgb_resulted;
54344c6f2e5SVitaly Prosyak 	hw_points = 0;
54444c6f2e5SVitaly Prosyak 
54544c6f2e5SVitaly Prosyak 	memset(lut_params, 0, sizeof(struct pwl_params));
54644c6f2e5SVitaly Prosyak 	memset(seg_distr, 0, sizeof(seg_distr));
54744c6f2e5SVitaly Prosyak 
54844c6f2e5SVitaly Prosyak 	region_start = -NUM_DEGAMMA_REGIONS;
54944c6f2e5SVitaly Prosyak 	region_end   = 0;
55044c6f2e5SVitaly Prosyak 
55144c6f2e5SVitaly Prosyak 
55244c6f2e5SVitaly Prosyak 	for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
55344c6f2e5SVitaly Prosyak 		seg_distr[i] = -1;
55444c6f2e5SVitaly Prosyak 	/* 12 segments
55544c6f2e5SVitaly Prosyak 	 * segments are from 2^-12 to 0
55644c6f2e5SVitaly Prosyak 	 */
55744c6f2e5SVitaly Prosyak 	for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
55844c6f2e5SVitaly Prosyak 		seg_distr[i] = 4;
55944c6f2e5SVitaly Prosyak 
56044c6f2e5SVitaly Prosyak 	for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
56144c6f2e5SVitaly Prosyak 		if (seg_distr[k] != -1)
56244c6f2e5SVitaly Prosyak 			hw_points += (1 << seg_distr[k]);
56344c6f2e5SVitaly Prosyak 	}
56444c6f2e5SVitaly Prosyak 
56544c6f2e5SVitaly Prosyak 	j = 0;
56644c6f2e5SVitaly Prosyak 	for (k = 0; k < (region_end - region_start); k++) {
56744c6f2e5SVitaly Prosyak 		increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
56844c6f2e5SVitaly Prosyak 		start_index = (region_start + k + MAX_LOW_POINT) *
56944c6f2e5SVitaly Prosyak 				NUMBER_SW_SEGMENTS;
57044c6f2e5SVitaly Prosyak 		for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
57144c6f2e5SVitaly Prosyak 				i += increment) {
57244c6f2e5SVitaly Prosyak 			if (j == hw_points - 1)
57344c6f2e5SVitaly Prosyak 				break;
57444c6f2e5SVitaly Prosyak 			rgb_resulted[j].red = output_tf->tf_pts.red[i];
57544c6f2e5SVitaly Prosyak 			rgb_resulted[j].green = output_tf->tf_pts.green[i];
57644c6f2e5SVitaly Prosyak 			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
57744c6f2e5SVitaly Prosyak 			j++;
57844c6f2e5SVitaly Prosyak 		}
57944c6f2e5SVitaly Prosyak 	}
58044c6f2e5SVitaly Prosyak 
58144c6f2e5SVitaly Prosyak 	/* last point */
58244c6f2e5SVitaly Prosyak 	start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
58344c6f2e5SVitaly Prosyak 	rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
58444c6f2e5SVitaly Prosyak 	rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
58544c6f2e5SVitaly Prosyak 	rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
58644c6f2e5SVitaly Prosyak 
587ceba1a01SAidan Yang 	rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
588ceba1a01SAidan Yang 	rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
589ceba1a01SAidan Yang 	rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
590ceba1a01SAidan Yang 
59109757809SKrunoslav Kovac 	corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
592eb0e5154SDmytro Laktyushkin 					     dc_fixpt_from_int(region_start));
59309757809SKrunoslav Kovac 	corner_points[0].green.x = corner_points[0].red.x;
59409757809SKrunoslav Kovac 	corner_points[0].blue.x = corner_points[0].red.x;
59509757809SKrunoslav Kovac 	corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
596eb0e5154SDmytro Laktyushkin 					     dc_fixpt_from_int(region_end));
59709757809SKrunoslav Kovac 	corner_points[1].green.x = corner_points[1].red.x;
59809757809SKrunoslav Kovac 	corner_points[1].blue.x = corner_points[1].red.x;
59944c6f2e5SVitaly Prosyak 
60009757809SKrunoslav Kovac 	corner_points[0].red.y = rgb_resulted[0].red;
60109757809SKrunoslav Kovac 	corner_points[0].green.y = rgb_resulted[0].green;
60209757809SKrunoslav Kovac 	corner_points[0].blue.y = rgb_resulted[0].blue;
60344c6f2e5SVitaly Prosyak 
60444c6f2e5SVitaly Prosyak 	/* see comment above, m_arrPoints[1].y should be the Y value for the
60544c6f2e5SVitaly Prosyak 	 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
60644c6f2e5SVitaly Prosyak 	 */
60709757809SKrunoslav Kovac 	corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
60809757809SKrunoslav Kovac 	corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
60909757809SKrunoslav Kovac 	corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
61009757809SKrunoslav Kovac 	corner_points[1].red.slope = dc_fixpt_zero;
61109757809SKrunoslav Kovac 	corner_points[1].green.slope = dc_fixpt_zero;
61209757809SKrunoslav Kovac 	corner_points[1].blue.slope = dc_fixpt_zero;
61344c6f2e5SVitaly Prosyak 
61444c6f2e5SVitaly Prosyak 	if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
61544c6f2e5SVitaly Prosyak 		/* for PQ, we want to have a straight line from last HW X point,
61644c6f2e5SVitaly Prosyak 		 * and the slope to be such that we hit 1.0 at 10000 nits.
61744c6f2e5SVitaly Prosyak 		 */
61844c6f2e5SVitaly Prosyak 		const struct fixed31_32 end_value =
619eb0e5154SDmytro Laktyushkin 				dc_fixpt_from_int(125);
62044c6f2e5SVitaly Prosyak 
62109757809SKrunoslav Kovac 		corner_points[1].red.slope = dc_fixpt_div(
62209757809SKrunoslav Kovac 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
62309757809SKrunoslav Kovac 			dc_fixpt_sub(end_value, corner_points[1].red.x));
62409757809SKrunoslav Kovac 		corner_points[1].green.slope = dc_fixpt_div(
62509757809SKrunoslav Kovac 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
62609757809SKrunoslav Kovac 			dc_fixpt_sub(end_value, corner_points[1].green.x));
62709757809SKrunoslav Kovac 		corner_points[1].blue.slope = dc_fixpt_div(
62809757809SKrunoslav Kovac 			dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
62909757809SKrunoslav Kovac 			dc_fixpt_sub(end_value, corner_points[1].blue.x));
63044c6f2e5SVitaly Prosyak 	}
63144c6f2e5SVitaly Prosyak 
63244c6f2e5SVitaly Prosyak 	lut_params->hw_points_num = hw_points;
63344c6f2e5SVitaly Prosyak 
63463bd5444SHarry Wentland 	k = 0;
63563bd5444SHarry Wentland 	for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
63644c6f2e5SVitaly Prosyak 		if (seg_distr[k] != -1) {
63744c6f2e5SVitaly Prosyak 			lut_params->arr_curve_points[k].segments_num =
63844c6f2e5SVitaly Prosyak 					seg_distr[k];
63944c6f2e5SVitaly Prosyak 			lut_params->arr_curve_points[i].offset =
64044c6f2e5SVitaly Prosyak 					lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
64144c6f2e5SVitaly Prosyak 		}
64263bd5444SHarry Wentland 		k++;
64344c6f2e5SVitaly Prosyak 	}
64444c6f2e5SVitaly Prosyak 
64544c6f2e5SVitaly Prosyak 	if (seg_distr[k] != -1)
64644c6f2e5SVitaly Prosyak 		lut_params->arr_curve_points[k].segments_num = seg_distr[k];
64744c6f2e5SVitaly Prosyak 
64844c6f2e5SVitaly Prosyak 	rgb = rgb_resulted;
64944c6f2e5SVitaly Prosyak 	rgb_plus_1 = rgb_resulted + 1;
65044c6f2e5SVitaly Prosyak 
65144c6f2e5SVitaly Prosyak 	i = 1;
65244c6f2e5SVitaly Prosyak 	while (i != hw_points + 1) {
653eb0e5154SDmytro Laktyushkin 		rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
654eb0e5154SDmytro Laktyushkin 		rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
655eb0e5154SDmytro Laktyushkin 		rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
65644c6f2e5SVitaly Prosyak 
65744c6f2e5SVitaly Prosyak 		++rgb_plus_1;
65844c6f2e5SVitaly Prosyak 		++rgb;
65944c6f2e5SVitaly Prosyak 		++i;
66044c6f2e5SVitaly Prosyak 	}
66144c6f2e5SVitaly Prosyak 	cm_helper_convert_to_custom_float(rgb_resulted,
66209757809SKrunoslav Kovac 						lut_params->corner_points,
66344c6f2e5SVitaly Prosyak 						hw_points, false);
66444c6f2e5SVitaly Prosyak 
66544c6f2e5SVitaly Prosyak 	return true;
66644c6f2e5SVitaly Prosyak }
667