root/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cm_helper_program_color_matrices
  2. cm_helper_program_xfer_func
  3. cm_helper_convert_to_custom_float
  4. cm_helper_translate_curve_to_hw_format
  5. cm_helper_translate_curve_to_degamma_hw_format

   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 
  41 void 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 
  65 void 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 
 128 bool 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 
 311 bool 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 
 320         int32_t region_start, region_end;
 321         int32_t i;
 322         uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
 323 
 324         if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
 325                 return false;
 326 
 327         PERF_TRACE_CTX(output_tf->ctx);
 328 
 329         corner_points = lut_params->corner_points;
 330         rgb_resulted = lut_params->rgb_resulted;
 331         hw_points = 0;
 332 
 333         memset(lut_params, 0, sizeof(struct pwl_params));
 334         memset(seg_distr, 0, sizeof(seg_distr));
 335 
 336         if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22) {
 337                 /* 32 segments
 338                  * segments are from 2^-25 to 2^7
 339                  */
 340                 for (i = 0; i < NUMBER_REGIONS ; i++)
 341                         seg_distr[i] = 3;
 342 
 343                 region_start = -MAX_LOW_POINT;
 344                 region_end   = NUMBER_REGIONS - MAX_LOW_POINT;
 345         } else {
 346                 /* 11 segments
 347                  * segment is from 2^-10 to 2^1
 348                  * There are less than 256 points, for optimization
 349                  */
 350                 seg_distr[0] = 3;
 351                 seg_distr[1] = 4;
 352                 seg_distr[2] = 4;
 353                 seg_distr[3] = 4;
 354                 seg_distr[4] = 4;
 355                 seg_distr[5] = 4;
 356                 seg_distr[6] = 4;
 357                 seg_distr[7] = 4;
 358                 seg_distr[8] = 4;
 359                 seg_distr[9] = 4;
 360                 seg_distr[10] = 1;
 361 
 362                 region_start = -10;
 363                 region_end = 1;
 364         }
 365 
 366         for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
 367                 seg_distr[i] = -1;
 368 
 369         for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
 370                 if (seg_distr[k] != -1)
 371                         hw_points += (1 << seg_distr[k]);
 372         }
 373 
 374         j = 0;
 375         for (k = 0; k < (region_end - region_start); k++) {
 376                 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
 377                 start_index = (region_start + k + MAX_LOW_POINT) *
 378                                 NUMBER_SW_SEGMENTS;
 379                 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
 380                                 i += increment) {
 381                         if (j == hw_points - 1)
 382                                 break;
 383                         rgb_resulted[j].red = output_tf->tf_pts.red[i];
 384                         rgb_resulted[j].green = output_tf->tf_pts.green[i];
 385                         rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
 386                         j++;
 387                 }
 388         }
 389 
 390         /* last point */
 391         start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
 392         rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
 393         rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
 394         rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
 395 
 396         rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
 397         rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
 398         rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
 399 
 400         // All 3 color channels have same x
 401         corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
 402                                              dc_fixpt_from_int(region_start));
 403         corner_points[0].green.x = corner_points[0].red.x;
 404         corner_points[0].blue.x = corner_points[0].red.x;
 405 
 406         corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
 407                                              dc_fixpt_from_int(region_end));
 408         corner_points[1].green.x = corner_points[1].red.x;
 409         corner_points[1].blue.x = corner_points[1].red.x;
 410 
 411         corner_points[0].red.y = rgb_resulted[0].red;
 412         corner_points[0].green.y = rgb_resulted[0].green;
 413         corner_points[0].blue.y = rgb_resulted[0].blue;
 414 
 415         corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y,
 416                         corner_points[0].red.x);
 417         corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y,
 418                         corner_points[0].green.x);
 419         corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y,
 420                         corner_points[0].blue.x);
 421 
 422         /* see comment above, m_arrPoints[1].y should be the Y value for the
 423          * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
 424          */
 425         corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
 426         corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
 427         corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
 428         corner_points[1].red.slope = dc_fixpt_zero;
 429         corner_points[1].green.slope = dc_fixpt_zero;
 430         corner_points[1].blue.slope = dc_fixpt_zero;
 431 
 432         if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
 433                 /* for PQ, we want to have a straight line from last HW X point,
 434                  * and the slope to be such that we hit 1.0 at 10000 nits.
 435                  */
 436                 const struct fixed31_32 end_value =
 437                                 dc_fixpt_from_int(125);
 438 
 439                 corner_points[1].red.slope = dc_fixpt_div(
 440                         dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
 441                         dc_fixpt_sub(end_value, corner_points[1].red.x));
 442                 corner_points[1].green.slope = dc_fixpt_div(
 443                         dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
 444                         dc_fixpt_sub(end_value, corner_points[1].green.x));
 445                 corner_points[1].blue.slope = dc_fixpt_div(
 446                         dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
 447                         dc_fixpt_sub(end_value, corner_points[1].blue.x));
 448         }
 449 
 450         lut_params->hw_points_num = hw_points;
 451 
 452         k = 0;
 453         for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
 454                 if (seg_distr[k] != -1) {
 455                         lut_params->arr_curve_points[k].segments_num =
 456                                         seg_distr[k];
 457                         lut_params->arr_curve_points[i].offset =
 458                                         lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
 459                 }
 460                 k++;
 461         }
 462 
 463         if (seg_distr[k] != -1)
 464                 lut_params->arr_curve_points[k].segments_num = seg_distr[k];
 465 
 466         rgb = rgb_resulted;
 467         rgb_plus_1 = rgb_resulted + 1;
 468 
 469         i = 1;
 470         while (i != hw_points + 1) {
 471                 rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
 472                 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
 473                 rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
 474 
 475                 if (fixpoint == true) {
 476                         rgb->delta_red_reg   = dc_fixpt_clamp_u0d10(rgb->delta_red);
 477                         rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green);
 478                         rgb->delta_blue_reg  = dc_fixpt_clamp_u0d10(rgb->delta_blue);
 479                         rgb->red_reg         = dc_fixpt_clamp_u0d14(rgb->red);
 480                         rgb->green_reg       = dc_fixpt_clamp_u0d14(rgb->green);
 481                         rgb->blue_reg        = dc_fixpt_clamp_u0d14(rgb->blue);
 482                 }
 483 
 484                 ++rgb_plus_1;
 485                 ++rgb;
 486                 ++i;
 487         }
 488         cm_helper_convert_to_custom_float(rgb_resulted,
 489                                                 lut_params->corner_points,
 490                                                 hw_points, fixpoint);
 491 
 492         return true;
 493 }
 494 
 495 #define NUM_DEGAMMA_REGIONS    12
 496 
 497 
 498 bool cm_helper_translate_curve_to_degamma_hw_format(
 499                                 const struct dc_transfer_func *output_tf,
 500                                 struct pwl_params *lut_params)
 501 {
 502         struct curve_points3 *corner_points;
 503         struct pwl_result_data *rgb_resulted;
 504         struct pwl_result_data *rgb;
 505         struct pwl_result_data *rgb_plus_1;
 506 
 507         int32_t region_start, region_end;
 508         int32_t i;
 509         uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
 510 
 511         if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS)
 512                 return false;
 513 
 514         PERF_TRACE_CTX(output_tf->ctx);
 515 
 516         corner_points = lut_params->corner_points;
 517         rgb_resulted = lut_params->rgb_resulted;
 518         hw_points = 0;
 519 
 520         memset(lut_params, 0, sizeof(struct pwl_params));
 521         memset(seg_distr, 0, sizeof(seg_distr));
 522 
 523         region_start = -NUM_DEGAMMA_REGIONS;
 524         region_end   = 0;
 525 
 526 
 527         for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
 528                 seg_distr[i] = -1;
 529         /* 12 segments
 530          * segments are from 2^-12 to 0
 531          */
 532         for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++)
 533                 seg_distr[i] = 4;
 534 
 535         for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
 536                 if (seg_distr[k] != -1)
 537                         hw_points += (1 << seg_distr[k]);
 538         }
 539 
 540         j = 0;
 541         for (k = 0; k < (region_end - region_start); k++) {
 542                 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
 543                 start_index = (region_start + k + MAX_LOW_POINT) *
 544                                 NUMBER_SW_SEGMENTS;
 545                 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
 546                                 i += increment) {
 547                         if (j == hw_points - 1)
 548                                 break;
 549                         rgb_resulted[j].red = output_tf->tf_pts.red[i];
 550                         rgb_resulted[j].green = output_tf->tf_pts.green[i];
 551                         rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
 552                         j++;
 553                 }
 554         }
 555 
 556         /* last point */
 557         start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
 558         rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
 559         rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
 560         rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
 561 
 562         rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red;
 563         rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green;
 564         rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue;
 565 
 566         corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
 567                                              dc_fixpt_from_int(region_start));
 568         corner_points[0].green.x = corner_points[0].red.x;
 569         corner_points[0].blue.x = corner_points[0].red.x;
 570         corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2),
 571                                              dc_fixpt_from_int(region_end));
 572         corner_points[1].green.x = corner_points[1].red.x;
 573         corner_points[1].blue.x = corner_points[1].red.x;
 574 
 575         corner_points[0].red.y = rgb_resulted[0].red;
 576         corner_points[0].green.y = rgb_resulted[0].green;
 577         corner_points[0].blue.y = rgb_resulted[0].blue;
 578 
 579         /* see comment above, m_arrPoints[1].y should be the Y value for the
 580          * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
 581          */
 582         corner_points[1].red.y = rgb_resulted[hw_points - 1].red;
 583         corner_points[1].green.y = rgb_resulted[hw_points - 1].green;
 584         corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue;
 585         corner_points[1].red.slope = dc_fixpt_zero;
 586         corner_points[1].green.slope = dc_fixpt_zero;
 587         corner_points[1].blue.slope = dc_fixpt_zero;
 588 
 589         if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
 590                 /* for PQ, we want to have a straight line from last HW X point,
 591                  * and the slope to be such that we hit 1.0 at 10000 nits.
 592                  */
 593                 const struct fixed31_32 end_value =
 594                                 dc_fixpt_from_int(125);
 595 
 596                 corner_points[1].red.slope = dc_fixpt_div(
 597                         dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y),
 598                         dc_fixpt_sub(end_value, corner_points[1].red.x));
 599                 corner_points[1].green.slope = dc_fixpt_div(
 600                         dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y),
 601                         dc_fixpt_sub(end_value, corner_points[1].green.x));
 602                 corner_points[1].blue.slope = dc_fixpt_div(
 603                         dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y),
 604                         dc_fixpt_sub(end_value, corner_points[1].blue.x));
 605         }
 606 
 607         lut_params->hw_points_num = hw_points;
 608 
 609         k = 0;
 610         for (i = 1; i < MAX_REGIONS_NUMBER; i++) {
 611                 if (seg_distr[k] != -1) {
 612                         lut_params->arr_curve_points[k].segments_num =
 613                                         seg_distr[k];
 614                         lut_params->arr_curve_points[i].offset =
 615                                         lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
 616                 }
 617                 k++;
 618         }
 619 
 620         if (seg_distr[k] != -1)
 621                 lut_params->arr_curve_points[k].segments_num = seg_distr[k];
 622 
 623         rgb = rgb_resulted;
 624         rgb_plus_1 = rgb_resulted + 1;
 625 
 626         i = 1;
 627         while (i != hw_points + 1) {
 628                 rgb->delta_red   = dc_fixpt_sub(rgb_plus_1->red,   rgb->red);
 629                 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green);
 630                 rgb->delta_blue  = dc_fixpt_sub(rgb_plus_1->blue,  rgb->blue);
 631 
 632                 ++rgb_plus_1;
 633                 ++rgb;
 634                 ++i;
 635         }
 636         cm_helper_convert_to_custom_float(rgb_resulted,
 637                                                 lut_params->corner_points,
 638                                                 hw_points, false);
 639 
 640         return true;
 641 }

/* [<][>][^][v][top][bottom][index][help] */