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 pwl_result_data *rgb_minus_1; 117 struct fixed31_32 end_value; 118 119 int32_t region_start, region_end; 120 int32_t i; 121 uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; 122 123 if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) 124 return false; 125 126 corner_points = lut_params->corner_points; 127 rgb_resulted = lut_params->rgb_resulted; 128 hw_points = 0; 129 130 memset(lut_params, 0, sizeof(struct pwl_params)); 131 memset(seg_distr, 0, sizeof(seg_distr)); 132 133 if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22 || 134 output_tf->tf == TRANSFER_FUNCTION_HLG) { 135 /* 32 segments 136 * segments are from 2^-25 to 2^7 137 */ 138 for (i = 0; i < NUMBER_REGIONS ; i++) 139 seg_distr[i] = 3; 140 141 region_start = -MAX_LOW_POINT; 142 region_end = NUMBER_REGIONS - MAX_LOW_POINT; 143 } else { 144 /* 11 segments 145 * segment is from 2^-10 to 2^0 146 * There are less than 256 points, for optimization 147 */ 148 seg_distr[0] = 3; 149 seg_distr[1] = 4; 150 seg_distr[2] = 4; 151 seg_distr[3] = 4; 152 seg_distr[4] = 4; 153 seg_distr[5] = 4; 154 seg_distr[6] = 4; 155 seg_distr[7] = 4; 156 seg_distr[8] = 4; 157 seg_distr[9] = 4; 158 seg_distr[10] = 1; 159 160 region_start = -10; 161 region_end = 1; 162 } 163 164 for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) 165 seg_distr[i] = -1; 166 167 for (k = 0; k < MAX_REGIONS_NUMBER; k++) { 168 if (seg_distr[k] != -1) 169 hw_points += (1 << seg_distr[k]); 170 } 171 172 j = 0; 173 for (k = 0; k < (region_end - region_start); k++) { 174 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); 175 start_index = (region_start + k + MAX_LOW_POINT) * 176 NUMBER_SW_SEGMENTS; 177 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; 178 i += increment) { 179 if (j == hw_points - 1) 180 break; 181 if (i >= TRANSFER_FUNC_POINTS) 182 return false; 183 rgb_resulted[j].red = output_tf->tf_pts.red[i]; 184 rgb_resulted[j].green = output_tf->tf_pts.green[i]; 185 rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 186 j++; 187 } 188 } 189 190 /* last point */ 191 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; 192 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; 193 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; 194 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; 195 196 rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red; 197 rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green; 198 rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue; 199 200 // All 3 color channels have same x 201 corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), 202 dc_fixpt_from_int(region_start)); 203 corner_points[0].green.x = corner_points[0].red.x; 204 corner_points[0].blue.x = corner_points[0].red.x; 205 206 corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), 207 dc_fixpt_from_int(region_end)); 208 corner_points[1].green.x = corner_points[1].red.x; 209 corner_points[1].blue.x = corner_points[1].red.x; 210 211 corner_points[0].red.y = rgb_resulted[0].red; 212 corner_points[0].green.y = rgb_resulted[0].green; 213 corner_points[0].blue.y = rgb_resulted[0].blue; 214 215 corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y, 216 corner_points[0].red.x); 217 corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y, 218 corner_points[0].green.x); 219 corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y, 220 corner_points[0].blue.x); 221 222 /* see comment above, m_arrPoints[1].y should be the Y value for the 223 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 224 */ 225 corner_points[1].red.y = rgb_resulted[hw_points - 1].red; 226 corner_points[1].green.y = rgb_resulted[hw_points - 1].green; 227 corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue; 228 corner_points[1].red.slope = dc_fixpt_zero; 229 corner_points[1].green.slope = dc_fixpt_zero; 230 corner_points[1].blue.slope = dc_fixpt_zero; 231 232 if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_HLG) { 233 /* for PQ/HLG, we want to have a straight line from last HW X point, 234 * and the slope to be such that we hit 1.0 at 10000/1000 nits. 235 */ 236 237 if (output_tf->tf == TRANSFER_FUNCTION_PQ) 238 end_value = dc_fixpt_from_int(125); 239 else 240 end_value = dc_fixpt_from_fraction(125, 10); 241 242 corner_points[1].red.slope = dc_fixpt_div( 243 dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y), 244 dc_fixpt_sub(end_value, corner_points[1].red.x)); 245 corner_points[1].green.slope = dc_fixpt_div( 246 dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y), 247 dc_fixpt_sub(end_value, corner_points[1].green.x)); 248 corner_points[1].blue.slope = dc_fixpt_div( 249 dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y), 250 dc_fixpt_sub(end_value, corner_points[1].blue.x)); 251 } 252 lut_params->hw_points_num = hw_points; 253 254 k = 0; 255 for (i = 1; i < MAX_REGIONS_NUMBER; i++) { 256 if (seg_distr[k] != -1) { 257 lut_params->arr_curve_points[k].segments_num = 258 seg_distr[k]; 259 lut_params->arr_curve_points[i].offset = 260 lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); 261 } 262 k++; 263 } 264 265 if (seg_distr[k] != -1) 266 lut_params->arr_curve_points[k].segments_num = seg_distr[k]; 267 268 rgb = rgb_resulted; 269 rgb_plus_1 = rgb_resulted + 1; 270 rgb_minus_1 = rgb; 271 272 i = 1; 273 while (i != hw_points + 1) { 274 if (i >= hw_points - 1) { 275 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 276 rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red); 277 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 278 rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green); 279 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 280 rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue); 281 } 282 283 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 284 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); 285 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); 286 287 if (fixpoint == true) { 288 rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red); 289 rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green); 290 rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue); 291 rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red); 292 rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green); 293 rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue); 294 } 295 296 ++rgb_plus_1; 297 rgb_minus_1 = rgb; 298 ++rgb; 299 ++i; 300 } 301 cm3_helper_convert_to_custom_float(rgb_resulted, 302 lut_params->corner_points, 303 hw_points, fixpoint); 304 305 return true; 306 } 307 308 #define NUM_DEGAMMA_REGIONS 12 309 310 311 bool cm3_helper_translate_curve_to_degamma_hw_format( 312 const struct dc_transfer_func *output_tf, 313 struct pwl_params *lut_params) 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 corner_points = lut_params->corner_points; 328 rgb_resulted = lut_params->rgb_resulted; 329 hw_points = 0; 330 331 memset(lut_params, 0, sizeof(struct pwl_params)); 332 memset(seg_distr, 0, sizeof(seg_distr)); 333 334 region_start = -NUM_DEGAMMA_REGIONS; 335 region_end = 0; 336 337 338 for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) 339 seg_distr[i] = -1; 340 /* 12 segments 341 * segments are from 2^-12 to 0 342 */ 343 for (i = 0; i < NUM_DEGAMMA_REGIONS ; i++) 344 seg_distr[i] = 4; 345 346 for (k = 0; k < MAX_REGIONS_NUMBER; k++) { 347 if (seg_distr[k] != -1) 348 hw_points += (1 << seg_distr[k]); 349 } 350 351 j = 0; 352 for (k = 0; k < (region_end - region_start); k++) { 353 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); 354 start_index = (region_start + k + MAX_LOW_POINT) * 355 NUMBER_SW_SEGMENTS; 356 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; 357 i += increment) { 358 if (j == hw_points - 1) 359 break; 360 if (i >= TRANSFER_FUNC_POINTS) 361 return false; 362 rgb_resulted[j].red = output_tf->tf_pts.red[i]; 363 rgb_resulted[j].green = output_tf->tf_pts.green[i]; 364 rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 365 j++; 366 } 367 } 368 369 /* last point */ 370 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; 371 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; 372 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; 373 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; 374 375 corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), 376 dc_fixpt_from_int(region_start)); 377 corner_points[0].green.x = corner_points[0].red.x; 378 corner_points[0].blue.x = corner_points[0].red.x; 379 corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), 380 dc_fixpt_from_int(region_end)); 381 corner_points[1].green.x = corner_points[1].red.x; 382 corner_points[1].blue.x = corner_points[1].red.x; 383 384 corner_points[0].red.y = rgb_resulted[0].red; 385 corner_points[0].green.y = rgb_resulted[0].green; 386 corner_points[0].blue.y = rgb_resulted[0].blue; 387 388 /* see comment above, m_arrPoints[1].y should be the Y value for the 389 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 390 */ 391 corner_points[1].red.y = rgb_resulted[hw_points - 1].red; 392 corner_points[1].green.y = rgb_resulted[hw_points - 1].green; 393 corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue; 394 corner_points[1].red.slope = dc_fixpt_zero; 395 corner_points[1].green.slope = dc_fixpt_zero; 396 corner_points[1].blue.slope = dc_fixpt_zero; 397 398 if (output_tf->tf == TRANSFER_FUNCTION_PQ) { 399 /* for PQ, we want to have a straight line from last HW X point, 400 * and the slope to be such that we hit 1.0 at 10000 nits. 401 */ 402 const struct fixed31_32 end_value = 403 dc_fixpt_from_int(125); 404 405 corner_points[1].red.slope = dc_fixpt_div( 406 dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y), 407 dc_fixpt_sub(end_value, corner_points[1].red.x)); 408 corner_points[1].green.slope = dc_fixpt_div( 409 dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y), 410 dc_fixpt_sub(end_value, corner_points[1].green.x)); 411 corner_points[1].blue.slope = dc_fixpt_div( 412 dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y), 413 dc_fixpt_sub(end_value, corner_points[1].blue.x)); 414 } 415 416 lut_params->hw_points_num = hw_points; 417 418 k = 0; 419 for (i = 1; i < MAX_REGIONS_NUMBER; i++) { 420 if (seg_distr[k] != -1) { 421 lut_params->arr_curve_points[k].segments_num = 422 seg_distr[k]; 423 lut_params->arr_curve_points[i].offset = 424 lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); 425 } 426 k++; 427 } 428 429 if (seg_distr[k] != -1) 430 lut_params->arr_curve_points[k].segments_num = seg_distr[k]; 431 432 rgb = rgb_resulted; 433 rgb_plus_1 = rgb_resulted + 1; 434 435 i = 1; 436 while (i != hw_points + 1) { 437 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 438 rgb_plus_1->red = rgb->red; 439 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 440 rgb_plus_1->green = rgb->green; 441 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 442 rgb_plus_1->blue = rgb->blue; 443 444 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 445 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); 446 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); 447 448 ++rgb_plus_1; 449 ++rgb; 450 ++i; 451 } 452 cm3_helper_convert_to_custom_float(rgb_resulted, 453 lut_params->corner_points, 454 hw_points, false); 455 456 return true; 457 } 458 459 bool cm3_helper_convert_to_custom_float( 460 struct pwl_result_data *rgb_resulted, 461 struct curve_points3 *corner_points, 462 uint32_t hw_points_num, 463 bool fixpoint) 464 { 465 struct custom_float_format fmt; 466 467 struct pwl_result_data *rgb = rgb_resulted; 468 469 uint32_t i = 0; 470 471 fmt.exponenta_bits = 6; 472 fmt.mantissa_bits = 12; 473 fmt.sign = false; 474 475 /* corner_points[0] - beginning base, slope offset for R,G,B 476 * corner_points[1] - end base, slope offset for R,G,B 477 */ 478 if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt, 479 &corner_points[0].red.custom_float_x)) { 480 BREAK_TO_DEBUGGER(); 481 return false; 482 } 483 if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt, 484 &corner_points[0].green.custom_float_x)) { 485 BREAK_TO_DEBUGGER(); 486 return false; 487 } 488 if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt, 489 &corner_points[0].blue.custom_float_x)) { 490 BREAK_TO_DEBUGGER(); 491 return false; 492 } 493 494 if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt, 495 &corner_points[0].red.custom_float_offset)) { 496 BREAK_TO_DEBUGGER(); 497 return false; 498 } 499 if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt, 500 &corner_points[0].green.custom_float_offset)) { 501 BREAK_TO_DEBUGGER(); 502 return false; 503 } 504 if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt, 505 &corner_points[0].blue.custom_float_offset)) { 506 BREAK_TO_DEBUGGER(); 507 return false; 508 } 509 510 if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt, 511 &corner_points[0].red.custom_float_slope)) { 512 BREAK_TO_DEBUGGER(); 513 return false; 514 } 515 if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt, 516 &corner_points[0].green.custom_float_slope)) { 517 BREAK_TO_DEBUGGER(); 518 return false; 519 } 520 if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt, 521 &corner_points[0].blue.custom_float_slope)) { 522 BREAK_TO_DEBUGGER(); 523 return false; 524 } 525 526 if (fixpoint == true) { 527 corner_points[1].red.custom_float_y = 528 dc_fixpt_clamp_u0d14(corner_points[1].red.y); 529 corner_points[1].green.custom_float_y = 530 dc_fixpt_clamp_u0d14(corner_points[1].green.y); 531 corner_points[1].blue.custom_float_y = 532 dc_fixpt_clamp_u0d14(corner_points[1].blue.y); 533 } else { 534 if (!convert_to_custom_float_format(corner_points[1].red.y, 535 &fmt, &corner_points[1].red.custom_float_y)) { 536 BREAK_TO_DEBUGGER(); 537 return false; 538 } 539 if (!convert_to_custom_float_format(corner_points[1].green.y, 540 &fmt, &corner_points[1].green.custom_float_y)) { 541 BREAK_TO_DEBUGGER(); 542 return false; 543 } 544 if (!convert_to_custom_float_format(corner_points[1].blue.y, 545 &fmt, &corner_points[1].blue.custom_float_y)) { 546 BREAK_TO_DEBUGGER(); 547 return false; 548 } 549 } 550 551 fmt.mantissa_bits = 10; 552 fmt.sign = false; 553 554 if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt, 555 &corner_points[1].red.custom_float_x)) { 556 BREAK_TO_DEBUGGER(); 557 return false; 558 } 559 if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt, 560 &corner_points[1].green.custom_float_x)) { 561 BREAK_TO_DEBUGGER(); 562 return false; 563 } 564 if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt, 565 &corner_points[1].blue.custom_float_x)) { 566 BREAK_TO_DEBUGGER(); 567 return false; 568 } 569 570 if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt, 571 &corner_points[1].red.custom_float_slope)) { 572 BREAK_TO_DEBUGGER(); 573 return false; 574 } 575 if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt, 576 &corner_points[1].green.custom_float_slope)) { 577 BREAK_TO_DEBUGGER(); 578 return false; 579 } 580 if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt, 581 &corner_points[1].blue.custom_float_slope)) { 582 BREAK_TO_DEBUGGER(); 583 return false; 584 } 585 586 if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true) 587 return true; 588 589 fmt.mantissa_bits = 12; 590 591 while (i != hw_points_num) { 592 if (!convert_to_custom_float_format(rgb->red, &fmt, 593 &rgb->red_reg)) { 594 BREAK_TO_DEBUGGER(); 595 return false; 596 } 597 598 if (!convert_to_custom_float_format(rgb->green, &fmt, 599 &rgb->green_reg)) { 600 BREAK_TO_DEBUGGER(); 601 return false; 602 } 603 604 if (!convert_to_custom_float_format(rgb->blue, &fmt, 605 &rgb->blue_reg)) { 606 BREAK_TO_DEBUGGER(); 607 return false; 608 } 609 610 if (!convert_to_custom_float_format(rgb->delta_red, &fmt, 611 &rgb->delta_red_reg)) { 612 BREAK_TO_DEBUGGER(); 613 return false; 614 } 615 616 if (!convert_to_custom_float_format(rgb->delta_green, &fmt, 617 &rgb->delta_green_reg)) { 618 BREAK_TO_DEBUGGER(); 619 return false; 620 } 621 622 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, 623 &rgb->delta_blue_reg)) { 624 BREAK_TO_DEBUGGER(); 625 return false; 626 } 627 628 ++rgb; 629 ++i; 630 } 631 632 return true; 633 } 634 635 bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num) 636 { 637 uint32_t i; 638 bool ret = true; 639 640 for (i = 0 ; i < num; i++) { 641 if (rgb[i].red_reg != rgb[i].green_reg || 642 rgb[i].blue_reg != rgb[i].red_reg || 643 rgb[i].blue_reg != rgb[i].green_reg) { 644 ret = false; 645 break; 646 } 647 } 648 return ret; 649 } 650 651