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 43 void 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 108 bool 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 299 bool 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 445 bool 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 621 bool 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