1 /* $NetBSD: amdgpu_dce110_opp_regamma_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $ */ 2 3 /* 4 * Copyright 2012-15 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: amdgpu_dce110_opp_regamma_v.c,v 1.2 2021/12/18 23:45:02 riastradh Exp $"); 30 31 #include <linux/delay.h> 32 33 #include "dm_services.h" 34 35 /* include DCE11 register header files */ 36 #include "dce/dce_11_0_d.h" 37 #include "dce/dce_11_0_sh_mask.h" 38 39 #include "dce110_transform_v.h" 40 41 static void power_on_lut(struct transform *xfm, 42 bool power_on, bool inputgamma, bool regamma) 43 { 44 uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); 45 int i; 46 47 if (power_on) { 48 if (inputgamma) 49 set_reg_field_value( 50 value, 51 1, 52 DCFEV_MEM_PWR_CTRL, 53 COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); 54 if (regamma) 55 set_reg_field_value( 56 value, 57 1, 58 DCFEV_MEM_PWR_CTRL, 59 COL_MAN_GAMMA_CORR_MEM_PWR_DIS); 60 } else { 61 if (inputgamma) 62 set_reg_field_value( 63 value, 64 0, 65 DCFEV_MEM_PWR_CTRL, 66 COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); 67 if (regamma) 68 set_reg_field_value( 69 value, 70 0, 71 DCFEV_MEM_PWR_CTRL, 72 COL_MAN_GAMMA_CORR_MEM_PWR_DIS); 73 } 74 75 dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); 76 77 for (i = 0; i < 3; i++) { 78 value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); 79 if (get_reg_field_value(value, 80 DCFEV_MEM_PWR_CTRL, 81 COL_MAN_INPUT_GAMMA_MEM_PWR_DIS) && 82 get_reg_field_value(value, 83 DCFEV_MEM_PWR_CTRL, 84 COL_MAN_GAMMA_CORR_MEM_PWR_DIS)) 85 break; 86 87 udelay(2); 88 } 89 } 90 91 static void set_bypass_input_gamma(struct dce_transform *xfm_dce) 92 { 93 uint32_t value; 94 95 value = dm_read_reg(xfm_dce->base.ctx, 96 mmCOL_MAN_INPUT_GAMMA_CONTROL1); 97 98 set_reg_field_value( 99 value, 100 0, 101 COL_MAN_INPUT_GAMMA_CONTROL1, 102 INPUT_GAMMA_MODE); 103 104 dm_write_reg(xfm_dce->base.ctx, 105 mmCOL_MAN_INPUT_GAMMA_CONTROL1, value); 106 } 107 108 static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode) 109 { 110 uint32_t value = 0; 111 112 set_reg_field_value( 113 value, 114 mode, 115 GAMMA_CORR_CONTROL, 116 GAMMA_CORR_MODE); 117 118 dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0); 119 } 120 121 /* 122 ***************************************************************************** 123 * Function: regamma_config_regions_and_segments 124 * 125 * build regamma curve by using predefined hw points 126 * uses interface parameters ,like EDID coeff. 127 * 128 * @param : parameters interface parameters 129 * @return void 130 * 131 * @note 132 * 133 * @see 134 * 135 ***************************************************************************** 136 */ 137 static void regamma_config_regions_and_segments( 138 struct dce_transform *xfm_dce, const struct pwl_params *params) 139 { 140 const struct gamma_curve *curve; 141 uint32_t value = 0; 142 143 { 144 set_reg_field_value( 145 value, 146 params->arr_points[0].custom_float_x, 147 GAMMA_CORR_CNTLA_START_CNTL, 148 GAMMA_CORR_CNTLA_EXP_REGION_START); 149 150 set_reg_field_value( 151 value, 152 0, 153 GAMMA_CORR_CNTLA_START_CNTL, 154 GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT); 155 156 dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CNTLA_START_CNTL, 157 value); 158 } 159 { 160 value = 0; 161 set_reg_field_value( 162 value, 163 params->arr_points[0].custom_float_slope, 164 GAMMA_CORR_CNTLA_SLOPE_CNTL, 165 GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE); 166 167 dm_write_reg(xfm_dce->base.ctx, 168 mmGAMMA_CORR_CNTLA_SLOPE_CNTL, value); 169 } 170 { 171 value = 0; 172 set_reg_field_value( 173 value, 174 params->arr_points[1].custom_float_x, 175 GAMMA_CORR_CNTLA_END_CNTL1, 176 GAMMA_CORR_CNTLA_EXP_REGION_END); 177 178 dm_write_reg(xfm_dce->base.ctx, 179 mmGAMMA_CORR_CNTLA_END_CNTL1, value); 180 } 181 { 182 value = 0; 183 set_reg_field_value( 184 value, 185 params->arr_points[1].custom_float_slope, 186 GAMMA_CORR_CNTLA_END_CNTL2, 187 GAMMA_CORR_CNTLA_EXP_REGION_END_BASE); 188 189 set_reg_field_value( 190 value, 191 params->arr_points[1].custom_float_y, 192 GAMMA_CORR_CNTLA_END_CNTL2, 193 GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE); 194 195 dm_write_reg(xfm_dce->base.ctx, 196 mmGAMMA_CORR_CNTLA_END_CNTL2, value); 197 } 198 199 curve = params->arr_curve_points; 200 201 { 202 value = 0; 203 set_reg_field_value( 204 value, 205 curve[0].offset, 206 GAMMA_CORR_CNTLA_REGION_0_1, 207 GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET); 208 209 set_reg_field_value( 210 value, 211 curve[0].segments_num, 212 GAMMA_CORR_CNTLA_REGION_0_1, 213 GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS); 214 215 set_reg_field_value( 216 value, 217 curve[1].offset, 218 GAMMA_CORR_CNTLA_REGION_0_1, 219 GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET); 220 221 set_reg_field_value( 222 value, 223 curve[1].segments_num, 224 GAMMA_CORR_CNTLA_REGION_0_1, 225 GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS); 226 227 dm_write_reg( 228 xfm_dce->base.ctx, 229 mmGAMMA_CORR_CNTLA_REGION_0_1, 230 value); 231 } 232 233 curve += 2; 234 { 235 value = 0; 236 set_reg_field_value( 237 value, 238 curve[0].offset, 239 GAMMA_CORR_CNTLA_REGION_2_3, 240 GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET); 241 242 set_reg_field_value( 243 value, 244 curve[0].segments_num, 245 GAMMA_CORR_CNTLA_REGION_2_3, 246 GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS); 247 248 set_reg_field_value( 249 value, 250 curve[1].offset, 251 GAMMA_CORR_CNTLA_REGION_2_3, 252 GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET); 253 254 set_reg_field_value( 255 value, 256 curve[1].segments_num, 257 GAMMA_CORR_CNTLA_REGION_2_3, 258 GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS); 259 260 dm_write_reg(xfm_dce->base.ctx, 261 mmGAMMA_CORR_CNTLA_REGION_2_3, 262 value); 263 } 264 265 curve += 2; 266 { 267 value = 0; 268 set_reg_field_value( 269 value, 270 curve[0].offset, 271 GAMMA_CORR_CNTLA_REGION_4_5, 272 GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET); 273 274 set_reg_field_value( 275 value, 276 curve[0].segments_num, 277 GAMMA_CORR_CNTLA_REGION_4_5, 278 GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS); 279 280 set_reg_field_value( 281 value, 282 curve[1].offset, 283 GAMMA_CORR_CNTLA_REGION_4_5, 284 GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET); 285 286 set_reg_field_value( 287 value, 288 curve[1].segments_num, 289 GAMMA_CORR_CNTLA_REGION_4_5, 290 GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS); 291 292 dm_write_reg(xfm_dce->base.ctx, 293 mmGAMMA_CORR_CNTLA_REGION_4_5, 294 value); 295 } 296 297 curve += 2; 298 { 299 value = 0; 300 set_reg_field_value( 301 value, 302 curve[0].offset, 303 GAMMA_CORR_CNTLA_REGION_6_7, 304 GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET); 305 306 set_reg_field_value( 307 value, 308 curve[0].segments_num, 309 GAMMA_CORR_CNTLA_REGION_6_7, 310 GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS); 311 312 set_reg_field_value( 313 value, 314 curve[1].offset, 315 GAMMA_CORR_CNTLA_REGION_6_7, 316 GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET); 317 318 set_reg_field_value( 319 value, 320 curve[1].segments_num, 321 GAMMA_CORR_CNTLA_REGION_6_7, 322 GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS); 323 324 dm_write_reg(xfm_dce->base.ctx, 325 mmGAMMA_CORR_CNTLA_REGION_6_7, 326 value); 327 } 328 329 curve += 2; 330 { 331 value = 0; 332 set_reg_field_value( 333 value, 334 curve[0].offset, 335 GAMMA_CORR_CNTLA_REGION_8_9, 336 GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET); 337 338 set_reg_field_value( 339 value, 340 curve[0].segments_num, 341 GAMMA_CORR_CNTLA_REGION_8_9, 342 GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS); 343 344 set_reg_field_value( 345 value, 346 curve[1].offset, 347 GAMMA_CORR_CNTLA_REGION_8_9, 348 GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET); 349 350 set_reg_field_value( 351 value, 352 curve[1].segments_num, 353 GAMMA_CORR_CNTLA_REGION_8_9, 354 GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS); 355 356 dm_write_reg(xfm_dce->base.ctx, 357 mmGAMMA_CORR_CNTLA_REGION_8_9, 358 value); 359 } 360 361 curve += 2; 362 { 363 value = 0; 364 set_reg_field_value( 365 value, 366 curve[0].offset, 367 GAMMA_CORR_CNTLA_REGION_10_11, 368 GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET); 369 370 set_reg_field_value( 371 value, 372 curve[0].segments_num, 373 GAMMA_CORR_CNTLA_REGION_10_11, 374 GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS); 375 376 set_reg_field_value( 377 value, 378 curve[1].offset, 379 GAMMA_CORR_CNTLA_REGION_10_11, 380 GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET); 381 382 set_reg_field_value( 383 value, 384 curve[1].segments_num, 385 GAMMA_CORR_CNTLA_REGION_10_11, 386 GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS); 387 388 dm_write_reg(xfm_dce->base.ctx, 389 mmGAMMA_CORR_CNTLA_REGION_10_11, 390 value); 391 } 392 393 curve += 2; 394 { 395 value = 0; 396 set_reg_field_value( 397 value, 398 curve[0].offset, 399 GAMMA_CORR_CNTLA_REGION_12_13, 400 GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET); 401 402 set_reg_field_value( 403 value, 404 curve[0].segments_num, 405 GAMMA_CORR_CNTLA_REGION_12_13, 406 GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS); 407 408 set_reg_field_value( 409 value, 410 curve[1].offset, 411 GAMMA_CORR_CNTLA_REGION_12_13, 412 GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET); 413 414 set_reg_field_value( 415 value, 416 curve[1].segments_num, 417 GAMMA_CORR_CNTLA_REGION_12_13, 418 GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS); 419 420 dm_write_reg(xfm_dce->base.ctx, 421 mmGAMMA_CORR_CNTLA_REGION_12_13, 422 value); 423 } 424 425 curve += 2; 426 { 427 value = 0; 428 set_reg_field_value( 429 value, 430 curve[0].offset, 431 GAMMA_CORR_CNTLA_REGION_14_15, 432 GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET); 433 434 set_reg_field_value( 435 value, 436 curve[0].segments_num, 437 GAMMA_CORR_CNTLA_REGION_14_15, 438 GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS); 439 440 set_reg_field_value( 441 value, 442 curve[1].offset, 443 GAMMA_CORR_CNTLA_REGION_14_15, 444 GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET); 445 446 set_reg_field_value( 447 value, 448 curve[1].segments_num, 449 GAMMA_CORR_CNTLA_REGION_14_15, 450 GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS); 451 452 dm_write_reg(xfm_dce->base.ctx, 453 mmGAMMA_CORR_CNTLA_REGION_14_15, 454 value); 455 } 456 } 457 458 static void program_pwl(struct dce_transform *xfm_dce, 459 const struct pwl_params *params) 460 { 461 uint32_t value = 0; 462 463 set_reg_field_value( 464 value, 465 7, 466 GAMMA_CORR_LUT_WRITE_EN_MASK, 467 GAMMA_CORR_LUT_WRITE_EN_MASK); 468 469 dm_write_reg(xfm_dce->base.ctx, 470 mmGAMMA_CORR_LUT_WRITE_EN_MASK, value); 471 472 dm_write_reg(xfm_dce->base.ctx, 473 mmGAMMA_CORR_LUT_INDEX, 0); 474 475 /* Program REGAMMA_LUT_DATA */ 476 { 477 const uint32_t addr = mmGAMMA_CORR_LUT_DATA; 478 uint32_t i = 0; 479 const struct pwl_result_data *rgb = 480 params->rgb_resulted; 481 482 while (i != params->hw_points_num) { 483 dm_write_reg(xfm_dce->base.ctx, addr, rgb->red_reg); 484 dm_write_reg(xfm_dce->base.ctx, addr, rgb->green_reg); 485 dm_write_reg(xfm_dce->base.ctx, addr, rgb->blue_reg); 486 487 dm_write_reg(xfm_dce->base.ctx, addr, 488 rgb->delta_red_reg); 489 dm_write_reg(xfm_dce->base.ctx, addr, 490 rgb->delta_green_reg); 491 dm_write_reg(xfm_dce->base.ctx, addr, 492 rgb->delta_blue_reg); 493 494 ++rgb; 495 ++i; 496 } 497 } 498 } 499 500 void dce110_opp_program_regamma_pwl_v( 501 struct transform *xfm, 502 const struct pwl_params *params) 503 { 504 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 505 506 /* Setup regions */ 507 regamma_config_regions_and_segments(xfm_dce, params); 508 509 set_bypass_input_gamma(xfm_dce); 510 511 /* Power on gamma LUT memory */ 512 power_on_lut(xfm, true, false, true); 513 514 /* Program PWL */ 515 program_pwl(xfm_dce, params); 516 517 /* program regamma config */ 518 configure_regamma_mode(xfm_dce, 1); 519 520 /* Power return to auto back */ 521 power_on_lut(xfm, false, false, true); 522 } 523 524 void dce110_opp_power_on_regamma_lut_v( 525 struct transform *xfm, 526 bool power_on) 527 { 528 uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); 529 530 set_reg_field_value( 531 value, 532 0, 533 DCFEV_MEM_PWR_CTRL, 534 COL_MAN_GAMMA_CORR_MEM_PWR_FORCE); 535 536 set_reg_field_value( 537 value, 538 power_on, 539 DCFEV_MEM_PWR_CTRL, 540 COL_MAN_GAMMA_CORR_MEM_PWR_DIS); 541 542 set_reg_field_value( 543 value, 544 0, 545 DCFEV_MEM_PWR_CTRL, 546 COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE); 547 548 set_reg_field_value( 549 value, 550 power_on, 551 DCFEV_MEM_PWR_CTRL, 552 COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); 553 554 dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); 555 } 556 557 void dce110_opp_set_regamma_mode_v( 558 struct transform *xfm, 559 enum opp_regamma mode) 560 { 561 // TODO: need to implement the function 562 } 563