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