Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19 477 lines 15 kB view raw
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/dcn30_dpp.h" 30#include "basics/conversion.h" 31#include "dcn30/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 108#define DC_LOGGER \ 109 ctx->logger 110 111bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx, 112 const struct dc_transfer_func *output_tf, 113 struct pwl_params *lut_params, bool fixpoint) 114{ 115 struct curve_points3 *corner_points; 116 struct pwl_result_data *rgb_resulted; 117 struct pwl_result_data *rgb; 118 struct pwl_result_data *rgb_plus_1; 119 struct pwl_result_data *rgb_minus_1; 120 121 int32_t region_start, region_end; 122 int32_t i; 123 uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points; 124 125 if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) 126 return false; 127 128 corner_points = lut_params->corner_points; 129 rgb_resulted = lut_params->rgb_resulted; 130 hw_points = 0; 131 132 memset(lut_params, 0, sizeof(struct pwl_params)); 133 memset(seg_distr, 0, sizeof(seg_distr)); 134 135 if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_GAMMA22 || 136 output_tf->tf == TRANSFER_FUNCTION_HLG) { 137 /* 32 segments 138 * segments are from 2^-25 to 2^7 139 */ 140 for (i = 0; i < NUMBER_REGIONS ; i++) 141 seg_distr[i] = 3; 142 143 region_start = -MAX_LOW_POINT; 144 region_end = NUMBER_REGIONS - MAX_LOW_POINT; 145 } else { 146 /* 13 segments 147 * segment is from 2^-12 to 2^0 148 * There are less than 256 points, for optimization 149 */ 150 const uint8_t SEG_COUNT = 12; 151 152 for (i = 0; i < SEG_COUNT; i++) 153 seg_distr[i] = 4; 154 155 seg_distr[SEG_COUNT] = 1; 156 157 region_start = -SEG_COUNT; 158 region_end = 1; 159 } 160 161 for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++) 162 seg_distr[i] = -1; 163 164 for (k = 0; k < MAX_REGIONS_NUMBER; k++) { 165 if (seg_distr[k] != -1) 166 hw_points += (1 << seg_distr[k]); 167 } 168 169 // DCN3+ have 257 pts in lieu of no separate slope registers 170 // Prior HW had 256 base+slope pairs 171 // Shaper LUT (i.e. fixpoint == true) is still 256 bases and 256 deltas 172 hw_points = fixpoint ? (hw_points - 1) : hw_points; 173 174 j = 0; 175 for (k = 0; k < (region_end - region_start); k++) { 176 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]); 177 start_index = (region_start + k + MAX_LOW_POINT) * 178 NUMBER_SW_SEGMENTS; 179 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; 180 i += increment) { 181 if (j == hw_points) 182 break; 183 if (i >= TRANSFER_FUNC_POINTS) 184 return false; 185 rgb_resulted[j].red = output_tf->tf_pts.red[i]; 186 rgb_resulted[j].green = output_tf->tf_pts.green[i]; 187 rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; 188 j++; 189 } 190 } 191 192 /* last point */ 193 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; 194 rgb_resulted[hw_points].red = output_tf->tf_pts.red[start_index]; 195 rgb_resulted[hw_points].green = output_tf->tf_pts.green[start_index]; 196 rgb_resulted[hw_points].blue = output_tf->tf_pts.blue[start_index]; 197 198 rgb_resulted[hw_points+1].red = rgb_resulted[hw_points].red; 199 rgb_resulted[hw_points+1].green = rgb_resulted[hw_points].green; 200 rgb_resulted[hw_points+1].blue = rgb_resulted[hw_points].blue; 201 202 // All 3 color channels have same x 203 corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), 204 dc_fixpt_from_int(region_start)); 205 corner_points[0].green.x = corner_points[0].red.x; 206 corner_points[0].blue.x = corner_points[0].red.x; 207 208 corner_points[1].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), 209 dc_fixpt_from_int(region_end)); 210 corner_points[1].green.x = corner_points[1].red.x; 211 corner_points[1].blue.x = corner_points[1].red.x; 212 213 corner_points[0].red.y = rgb_resulted[0].red; 214 corner_points[0].green.y = rgb_resulted[0].green; 215 corner_points[0].blue.y = rgb_resulted[0].blue; 216 217 corner_points[0].red.slope = dc_fixpt_div(corner_points[0].red.y, 218 corner_points[0].red.x); 219 corner_points[0].green.slope = dc_fixpt_div(corner_points[0].green.y, 220 corner_points[0].green.x); 221 corner_points[0].blue.slope = dc_fixpt_div(corner_points[0].blue.y, 222 corner_points[0].blue.x); 223 224 /* see comment above, m_arrPoints[1].y should be the Y value for the 225 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) 226 */ 227 corner_points[1].red.y = rgb_resulted[hw_points].red; 228 corner_points[1].green.y = rgb_resulted[hw_points].green; 229 corner_points[1].blue.y = rgb_resulted[hw_points].blue; 230 corner_points[1].red.slope = dc_fixpt_zero; 231 corner_points[1].green.slope = dc_fixpt_zero; 232 corner_points[1].blue.slope = dc_fixpt_zero; 233 234 lut_params->hw_points_num = hw_points + 1; 235 236 k = 0; 237 for (i = 1; i < MAX_REGIONS_NUMBER; i++) { 238 if (seg_distr[k] != -1) { 239 lut_params->arr_curve_points[k].segments_num = 240 seg_distr[k]; 241 lut_params->arr_curve_points[i].offset = 242 lut_params->arr_curve_points[k].offset + (1 << seg_distr[k]); 243 } 244 k++; 245 } 246 247 if (seg_distr[k] != -1) 248 lut_params->arr_curve_points[k].segments_num = seg_distr[k]; 249 250 rgb = rgb_resulted; 251 rgb_plus_1 = rgb_resulted + 1; 252 rgb_minus_1 = rgb; 253 254 if (fixpoint == true) { 255 i = 1; 256 while (i != hw_points + 2) { 257 uint32_t red_clamp; 258 uint32_t green_clamp; 259 uint32_t blue_clamp; 260 261 if (i >= hw_points) { 262 if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) 263 rgb_plus_1->red = dc_fixpt_add(rgb->red, 264 rgb_minus_1->delta_red); 265 if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) 266 rgb_plus_1->green = dc_fixpt_add(rgb->green, 267 rgb_minus_1->delta_green); 268 if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) 269 rgb_plus_1->blue = dc_fixpt_add(rgb->blue, 270 rgb_minus_1->delta_blue); 271 } 272 273 rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); 274 rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); 275 rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); 276 277 red_clamp = dc_fixpt_clamp_u0d14(rgb->delta_red); 278 green_clamp = dc_fixpt_clamp_u0d14(rgb->delta_green); 279 blue_clamp = dc_fixpt_clamp_u0d14(rgb->delta_blue); 280 281 if (red_clamp >> 10 || green_clamp >> 10 || blue_clamp >> 10) 282 DC_LOG_ERROR("Losing delta precision while programming shaper LUT."); 283 284 rgb->delta_red_reg = red_clamp & 0x3ff; 285 rgb->delta_green_reg = green_clamp & 0x3ff; 286 rgb->delta_blue_reg = blue_clamp & 0x3ff; 287 rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red); 288 rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green); 289 rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue); 290 291 ++rgb_plus_1; 292 rgb_minus_1 = rgb; 293 ++rgb; 294 ++i; 295 } 296 } 297 cm3_helper_convert_to_custom_float(rgb_resulted, 298 lut_params->corner_points, 299 hw_points+1, fixpoint); 300 301 return true; 302} 303 304bool cm3_helper_convert_to_custom_float( 305 struct pwl_result_data *rgb_resulted, 306 struct curve_points3 *corner_points, 307 uint32_t hw_points_num, 308 bool fixpoint) 309{ 310 struct custom_float_format fmt; 311 312 struct pwl_result_data *rgb = rgb_resulted; 313 314 uint32_t i = 0; 315 316 fmt.exponenta_bits = 6; 317 fmt.mantissa_bits = 12; 318 fmt.sign = false; 319 320 /* corner_points[0] - beginning base, slope offset for R,G,B 321 * corner_points[1] - end base, slope offset for R,G,B 322 */ 323 if (!convert_to_custom_float_format(corner_points[0].red.x, &fmt, 324 &corner_points[0].red.custom_float_x)) { 325 BREAK_TO_DEBUGGER(); 326 return false; 327 } 328 if (!convert_to_custom_float_format(corner_points[0].green.x, &fmt, 329 &corner_points[0].green.custom_float_x)) { 330 BREAK_TO_DEBUGGER(); 331 return false; 332 } 333 if (!convert_to_custom_float_format(corner_points[0].blue.x, &fmt, 334 &corner_points[0].blue.custom_float_x)) { 335 BREAK_TO_DEBUGGER(); 336 return false; 337 } 338 339 if (!convert_to_custom_float_format(corner_points[0].red.offset, &fmt, 340 &corner_points[0].red.custom_float_offset)) { 341 BREAK_TO_DEBUGGER(); 342 return false; 343 } 344 if (!convert_to_custom_float_format(corner_points[0].green.offset, &fmt, 345 &corner_points[0].green.custom_float_offset)) { 346 BREAK_TO_DEBUGGER(); 347 return false; 348 } 349 if (!convert_to_custom_float_format(corner_points[0].blue.offset, &fmt, 350 &corner_points[0].blue.custom_float_offset)) { 351 BREAK_TO_DEBUGGER(); 352 return false; 353 } 354 355 if (!convert_to_custom_float_format(corner_points[0].red.slope, &fmt, 356 &corner_points[0].red.custom_float_slope)) { 357 BREAK_TO_DEBUGGER(); 358 return false; 359 } 360 if (!convert_to_custom_float_format(corner_points[0].green.slope, &fmt, 361 &corner_points[0].green.custom_float_slope)) { 362 BREAK_TO_DEBUGGER(); 363 return false; 364 } 365 if (!convert_to_custom_float_format(corner_points[0].blue.slope, &fmt, 366 &corner_points[0].blue.custom_float_slope)) { 367 BREAK_TO_DEBUGGER(); 368 return false; 369 } 370 371 if (fixpoint == true) { 372 corner_points[1].red.custom_float_y = 373 dc_fixpt_clamp_u0d14(corner_points[1].red.y); 374 corner_points[1].green.custom_float_y = 375 dc_fixpt_clamp_u0d14(corner_points[1].green.y); 376 corner_points[1].blue.custom_float_y = 377 dc_fixpt_clamp_u0d14(corner_points[1].blue.y); 378 } else { 379 if (!convert_to_custom_float_format(corner_points[1].red.y, 380 &fmt, &corner_points[1].red.custom_float_y)) { 381 BREAK_TO_DEBUGGER(); 382 return false; 383 } 384 if (!convert_to_custom_float_format(corner_points[1].green.y, 385 &fmt, &corner_points[1].green.custom_float_y)) { 386 BREAK_TO_DEBUGGER(); 387 return false; 388 } 389 if (!convert_to_custom_float_format(corner_points[1].blue.y, 390 &fmt, &corner_points[1].blue.custom_float_y)) { 391 BREAK_TO_DEBUGGER(); 392 return false; 393 } 394 } 395 396 fmt.mantissa_bits = 10; 397 fmt.sign = false; 398 399 if (!convert_to_custom_float_format(corner_points[1].red.x, &fmt, 400 &corner_points[1].red.custom_float_x)) { 401 BREAK_TO_DEBUGGER(); 402 return false; 403 } 404 if (!convert_to_custom_float_format(corner_points[1].green.x, &fmt, 405 &corner_points[1].green.custom_float_x)) { 406 BREAK_TO_DEBUGGER(); 407 return false; 408 } 409 if (!convert_to_custom_float_format(corner_points[1].blue.x, &fmt, 410 &corner_points[1].blue.custom_float_x)) { 411 BREAK_TO_DEBUGGER(); 412 return false; 413 } 414 415 if (!convert_to_custom_float_format(corner_points[1].red.slope, &fmt, 416 &corner_points[1].red.custom_float_slope)) { 417 BREAK_TO_DEBUGGER(); 418 return false; 419 } 420 if (!convert_to_custom_float_format(corner_points[1].green.slope, &fmt, 421 &corner_points[1].green.custom_float_slope)) { 422 BREAK_TO_DEBUGGER(); 423 return false; 424 } 425 if (!convert_to_custom_float_format(corner_points[1].blue.slope, &fmt, 426 &corner_points[1].blue.custom_float_slope)) { 427 BREAK_TO_DEBUGGER(); 428 return false; 429 } 430 431 if (hw_points_num == 0 || rgb_resulted == NULL || fixpoint == true) 432 return true; 433 434 fmt.mantissa_bits = 12; 435 436 while (i != hw_points_num) { 437 if (!convert_to_custom_float_format(rgb->red, &fmt, 438 &rgb->red_reg)) { 439 BREAK_TO_DEBUGGER(); 440 return false; 441 } 442 443 if (!convert_to_custom_float_format(rgb->green, &fmt, 444 &rgb->green_reg)) { 445 BREAK_TO_DEBUGGER(); 446 return false; 447 } 448 449 if (!convert_to_custom_float_format(rgb->blue, &fmt, 450 &rgb->blue_reg)) { 451 BREAK_TO_DEBUGGER(); 452 return false; 453 } 454 455 ++rgb; 456 ++i; 457 } 458 459 return true; 460} 461 462bool is_rgb_equal(const struct pwl_result_data *rgb, uint32_t num) 463{ 464 uint32_t i; 465 bool ret = true; 466 467 for (i = 0 ; i < num; i++) { 468 if (rgb[i].red_reg != rgb[i].green_reg || 469 rgb[i].blue_reg != rgb[i].red_reg || 470 rgb[i].blue_reg != rgb[i].green_reg) { 471 ret = false; 472 break; 473 } 474 } 475 return ret; 476} 477