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, ®val0,76 csc_c12, ®val1);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