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