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