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 #include "basics/conversion.h" 28 29 #include "dce_opp.h" 30 31 #include "reg_helper.h" 32 33 #define REG(reg)\ 34 (opp110->regs->reg) 35 36 #undef FN 37 #define FN(reg_name, field_name) \ 38 opp110->opp_shift->field_name, opp110->opp_mask->field_name 39 40 #define CTX \ 41 opp110->base.ctx 42 43 enum { 44 MAX_PWL_ENTRY = 128, 45 MAX_REGIONS_NUMBER = 16 46 }; 47 48 enum { 49 MAX_LUT_ENTRY = 256, 50 MAX_NUMBER_OF_ENTRIES = 256 51 }; 52 53 54 enum { 55 OUTPUT_CSC_MATRIX_SIZE = 12 56 }; 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 /* 80 ***************************************************************************** 81 * Function: regamma_config_regions_and_segments 82 * 83 * build regamma curve by using predefined hw points 84 * uses interface parameters ,like EDID coeff. 85 * 86 * @param : parameters interface parameters 87 * @return void 88 * 89 * @note 90 * 91 * @see 92 * 93 ***************************************************************************** 94 */ 95 96 97 98 /** 99 * set_truncation 100 * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp 101 * 2) enable truncation 102 * 3) HW remove 12bit FMT support for DCE11 power saving reason. 103 */ 104 static void set_truncation( 105 struct dce110_opp *opp110, 106 const struct bit_depth_reduction_params *params) 107 { 108 /*Disable truncation*/ 109 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 110 FMT_TRUNCATE_EN, 0, 111 FMT_TRUNCATE_DEPTH, 0, 112 FMT_TRUNCATE_MODE, 0); 113 114 115 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 116 /* 8bpc trunc on YCbCr422*/ 117 if (params->flags.TRUNCATE_DEPTH == 1) 118 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 119 FMT_TRUNCATE_EN, 1, 120 FMT_TRUNCATE_DEPTH, 1, 121 FMT_TRUNCATE_MODE, 0); 122 else if (params->flags.TRUNCATE_DEPTH == 2) 123 /* 10bpc trunc on YCbCr422*/ 124 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 125 FMT_TRUNCATE_EN, 1, 126 FMT_TRUNCATE_DEPTH, 2, 127 FMT_TRUNCATE_MODE, 0); 128 return; 129 } 130 /* on other format-to do */ 131 if (params->flags.TRUNCATE_ENABLED == 0 || 132 params->flags.TRUNCATE_DEPTH == 2) 133 return; 134 /*Set truncation depth and Enable truncation*/ 135 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 136 FMT_TRUNCATE_EN, 1, 137 FMT_TRUNCATE_DEPTH, 138 params->flags.TRUNCATE_MODE, 139 FMT_TRUNCATE_MODE, 140 params->flags.TRUNCATE_DEPTH); 141 } 142 143 144 /** 145 * set_spatial_dither 146 * 1) set spatial dithering mode: pattern of seed 147 * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp 148 * 3) set random seed 149 * 4) set random mode 150 * lfsr is reset every frame or not reset 151 * RGB dithering method 152 * 0: RGB data are all dithered with x^28+x^3+1 153 * 1: R data is dithered with x^28+x^3+1 154 * G data is dithered with x^28+X^9+1 155 * B data is dithered with x^28+x^13+1 156 * enable high pass filter or not 157 * 5) enable spatical dithering 158 */ 159 static void set_spatial_dither( 160 struct dce110_opp *opp110, 161 const struct bit_depth_reduction_params *params) 162 { 163 /*Disable spatial (random) dithering*/ 164 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 165 FMT_SPATIAL_DITHER_EN, 0, 166 FMT_SPATIAL_DITHER_DEPTH, 0, 167 FMT_SPATIAL_DITHER_MODE, 0); 168 169 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 170 FMT_HIGHPASS_RANDOM_ENABLE, 0, 171 FMT_FRAME_RANDOM_ENABLE, 0, 172 FMT_RGB_RANDOM_ENABLE, 0); 173 174 REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 175 FMT_TEMPORAL_DITHER_EN, 0); 176 177 /* no 10bpc on DCE11*/ 178 if (params->flags.SPATIAL_DITHER_ENABLED == 0 || 179 params->flags.SPATIAL_DITHER_DEPTH == 2) 180 return; 181 182 /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ 183 184 if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX && 185 opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) { 186 if (params->flags.FRAME_RANDOM == 1) { 187 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || 188 params->flags.SPATIAL_DITHER_DEPTH == 1) { 189 REG_UPDATE_2(FMT_CONTROL, 190 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, 191 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); 192 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { 193 REG_UPDATE_2(FMT_CONTROL, 194 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, 195 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); 196 } else 197 return; 198 } else { 199 REG_UPDATE_2(FMT_CONTROL, 200 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, 201 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); 202 } 203 } 204 /* Set seed for random values for 205 * spatial dithering for R,G,B channels 206 */ 207 REG_UPDATE(FMT_DITHER_RAND_R_SEED, 208 FMT_RAND_R_SEED, params->r_seed_value); 209 210 REG_UPDATE(FMT_DITHER_RAND_G_SEED, 211 FMT_RAND_G_SEED, params->g_seed_value); 212 213 REG_UPDATE(FMT_DITHER_RAND_B_SEED, 214 FMT_RAND_B_SEED, params->b_seed_value); 215 216 /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero 217 * offset for the R/Cr channel, lower 4LSB 218 * is forced to zeros. Typically set to 0 219 * RGB and 0x80000 YCbCr. 220 */ 221 /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero 222 * offset for the G/Y channel, lower 4LSB is 223 * forced to zeros. Typically set to 0 RGB 224 * and 0x80000 YCbCr. 225 */ 226 /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero 227 * offset for the B/Cb channel, lower 4LSB is 228 * forced to zeros. Typically set to 0 RGB and 229 * 0x80000 YCbCr. 230 */ 231 232 /* Disable High pass filter 233 * Reset only at startup 234 * Set RGB data dithered with x^28+x^3+1 235 */ 236 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 237 FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, 238 FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, 239 FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); 240 241 /* Set spatial dithering bit depth 242 * Set spatial dithering mode 243 * (default is Seed patterrn AAAA...) 244 * Enable spatial dithering 245 */ 246 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 247 FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, 248 FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, 249 FMT_SPATIAL_DITHER_EN, 1); 250 } 251 252 /** 253 * SetTemporalDither (Frame Modulation) 254 * 1) set temporal dither depth 255 * 2) select pattern: from hard-coded pattern or programmable pattern 256 * 3) select optimized strips for BGR or RGB LCD sub-pixel 257 * 4) set s matrix 258 * 5) set t matrix 259 * 6) set grey level for 0.25, 0.5, 0.75 260 * 7) enable temporal dithering 261 */ 262 263 static void set_temporal_dither( 264 struct dce110_opp *opp110, 265 const struct bit_depth_reduction_params *params) 266 { 267 /*Disable temporal (frame modulation) dithering first*/ 268 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 269 FMT_TEMPORAL_DITHER_EN, 0, 270 FMT_TEMPORAL_DITHER_RESET, 0, 271 FMT_TEMPORAL_DITHER_OFFSET, 0); 272 273 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 274 FMT_TEMPORAL_DITHER_DEPTH, 0, 275 FMT_TEMPORAL_LEVEL, 0); 276 277 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 278 FMT_25FRC_SEL, 0, 279 FMT_50FRC_SEL, 0, 280 FMT_75FRC_SEL, 0); 281 282 /* no 10bpc dither on DCE11*/ 283 if (params->flags.FRAME_MODULATION_ENABLED == 0 || 284 params->flags.FRAME_MODULATION_DEPTH == 2) 285 return; 286 287 /* Set temporal dithering depth*/ 288 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 289 FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH, 290 FMT_TEMPORAL_DITHER_RESET, 0, 291 FMT_TEMPORAL_DITHER_OFFSET, 0); 292 293 /*Select legacy pattern based on FRC and Temporal level*/ 294 if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) { 295 REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0); 296 /*Set s matrix*/ 297 REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0); 298 /*Set t matrix*/ 299 REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0); 300 } 301 302 /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ 303 REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 304 FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL); 305 306 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 307 FMT_25FRC_SEL, params->flags.FRC25, 308 FMT_50FRC_SEL, params->flags.FRC50, 309 FMT_75FRC_SEL, params->flags.FRC75); 310 311 /*Enable bit reduction by temporal (frame modulation) dithering*/ 312 REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 313 FMT_TEMPORAL_DITHER_EN, 1); 314 } 315 316 /** 317 * Set Clamping 318 * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) 319 * 1 for 8 bpc 320 * 2 for 10 bpc 321 * 3 for 12 bpc 322 * 7 for programable 323 * 2) Enable clamp if Limited range requested 324 */ 325 void dce110_opp_set_clamping( 326 struct dce110_opp *opp110, 327 const struct clamping_and_pixel_encoding_params *params) 328 { 329 REG_SET_2(FMT_CLAMP_CNTL, 0, 330 FMT_CLAMP_DATA_EN, 0, 331 FMT_CLAMP_COLOR_FORMAT, 0); 332 333 switch (params->clamping_level) { 334 case CLAMPING_FULL_RANGE: 335 break; 336 case CLAMPING_LIMITED_RANGE_8BPC: 337 REG_SET_2(FMT_CLAMP_CNTL, 0, 338 FMT_CLAMP_DATA_EN, 1, 339 FMT_CLAMP_COLOR_FORMAT, 1); 340 break; 341 case CLAMPING_LIMITED_RANGE_10BPC: 342 REG_SET_2(FMT_CLAMP_CNTL, 0, 343 FMT_CLAMP_DATA_EN, 1, 344 FMT_CLAMP_COLOR_FORMAT, 2); 345 break; 346 case CLAMPING_LIMITED_RANGE_12BPC: 347 REG_SET_2(FMT_CLAMP_CNTL, 0, 348 FMT_CLAMP_DATA_EN, 1, 349 FMT_CLAMP_COLOR_FORMAT, 3); 350 break; 351 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: 352 /*Set clamp control*/ 353 REG_SET_2(FMT_CLAMP_CNTL, 0, 354 FMT_CLAMP_DATA_EN, 1, 355 FMT_CLAMP_COLOR_FORMAT, 7); 356 357 /*set the defaults*/ 358 REG_SET_2(FMT_CLAMP_COMPONENT_R, 0, 359 FMT_CLAMP_LOWER_R, 0x10, 360 FMT_CLAMP_UPPER_R, 0xFEF); 361 362 REG_SET_2(FMT_CLAMP_COMPONENT_G, 0, 363 FMT_CLAMP_LOWER_G, 0x10, 364 FMT_CLAMP_UPPER_G, 0xFEF); 365 366 REG_SET_2(FMT_CLAMP_COMPONENT_B, 0, 367 FMT_CLAMP_LOWER_B, 0x10, 368 FMT_CLAMP_UPPER_B, 0xFEF); 369 break; 370 default: 371 break; 372 } 373 } 374 375 /** 376 * set_pixel_encoding 377 * 378 * Set Pixel Encoding 379 * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly 380 * 1: YCbCr 4:2:2 381 */ 382 static void set_pixel_encoding( 383 struct dce110_opp *opp110, 384 const struct clamping_and_pixel_encoding_params *params) 385 { 386 if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) 387 REG_UPDATE_3(FMT_CONTROL, 388 FMT_PIXEL_ENCODING, 0, 389 FMT_SUBSAMPLING_MODE, 0, 390 FMT_CBCR_BIT_REDUCTION_BYPASS, 0); 391 else 392 REG_UPDATE_2(FMT_CONTROL, 393 FMT_PIXEL_ENCODING, 0, 394 FMT_SUBSAMPLING_MODE, 0); 395 396 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 397 REG_UPDATE_2(FMT_CONTROL, 398 FMT_PIXEL_ENCODING, 1, 399 FMT_SUBSAMPLING_ORDER, 0); 400 } 401 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { 402 REG_UPDATE_3(FMT_CONTROL, 403 FMT_PIXEL_ENCODING, 2, 404 FMT_SUBSAMPLING_MODE, 2, 405 FMT_CBCR_BIT_REDUCTION_BYPASS, 1); 406 } 407 408 } 409 410 void dce110_opp_program_bit_depth_reduction( 411 struct output_pixel_processor *opp, 412 const struct bit_depth_reduction_params *params) 413 { 414 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 415 416 set_truncation(opp110, params); 417 set_spatial_dither(opp110, params); 418 set_temporal_dither(opp110, params); 419 } 420 421 void dce110_opp_program_clamping_and_pixel_encoding( 422 struct output_pixel_processor *opp, 423 const struct clamping_and_pixel_encoding_params *params) 424 { 425 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 426 427 dce110_opp_set_clamping(opp110, params); 428 set_pixel_encoding(opp110, params); 429 } 430 431 static void program_formatter_420_memory(struct output_pixel_processor *opp) 432 { 433 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 434 uint32_t fmt_mem_cntl_value; 435 436 /* Program source select*/ 437 /* Use HW default source select for FMT_MEMORYx_CONTROL */ 438 /* Use that value for FMT_SRC_SELECT as well*/ 439 REG_GET(CONTROL, 440 FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value); 441 442 REG_UPDATE(FMT_CONTROL, 443 FMT_SRC_SELECT, fmt_mem_cntl_value); 444 445 /* Turn on the memory */ 446 REG_UPDATE(CONTROL, 447 FMT420_MEM0_PWR_FORCE, 0); 448 } 449 450 void dce110_opp_set_dyn_expansion( 451 struct output_pixel_processor *opp, 452 enum dc_color_space color_sp, 453 enum dc_color_depth color_dpth, 454 enum signal_type signal) 455 { 456 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 457 458 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 459 FMT_DYNAMIC_EXP_EN, 0, 460 FMT_DYNAMIC_EXP_MODE, 0); 461 462 /*00 - 10-bit -> 12-bit dynamic expansion*/ 463 /*01 - 8-bit -> 12-bit dynamic expansion*/ 464 if (signal == SIGNAL_TYPE_HDMI_TYPE_A || 465 signal == SIGNAL_TYPE_DISPLAY_PORT || 466 signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 467 switch (color_dpth) { 468 case COLOR_DEPTH_888: 469 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 470 FMT_DYNAMIC_EXP_EN, 1, 471 FMT_DYNAMIC_EXP_MODE, 1); 472 break; 473 case COLOR_DEPTH_101010: 474 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 475 FMT_DYNAMIC_EXP_EN, 1, 476 FMT_DYNAMIC_EXP_MODE, 0); 477 break; 478 case COLOR_DEPTH_121212: 479 REG_UPDATE_2( 480 FMT_DYNAMIC_EXP_CNTL, 481 FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ 482 FMT_DYNAMIC_EXP_MODE, 0); 483 break; 484 default: 485 break; 486 } 487 } 488 } 489 490 static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) 491 { 492 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 493 494 /* clear previous phase lock status*/ 495 REG_UPDATE(FMT_CONTROL, 496 FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1); 497 498 /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ 499 REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10); 500 501 } 502 503 void dce110_opp_program_fmt( 504 struct output_pixel_processor *opp, 505 struct bit_depth_reduction_params *fmt_bit_depth, 506 struct clamping_and_pixel_encoding_params *clamping) 507 { 508 /* dithering is affected by <CrtcSourceSelect>, hence should be 509 * programmed afterwards */ 510 511 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 512 program_formatter_420_memory(opp); 513 514 dce110_opp_program_bit_depth_reduction( 515 opp, 516 fmt_bit_depth); 517 518 dce110_opp_program_clamping_and_pixel_encoding( 519 opp, 520 clamping); 521 522 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 523 program_formatter_reset_dig_resync_fifo(opp); 524 525 return; 526 } 527 528 529 530 531 532 /*****************************************/ 533 /* Constructor, Destructor */ 534 /*****************************************/ 535 536 static const struct opp_funcs funcs = { 537 .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, 538 .opp_destroy = dce110_opp_destroy, 539 .opp_program_fmt = dce110_opp_program_fmt, 540 .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction 541 }; 542 543 void dce110_opp_construct(struct dce110_opp *opp110, 544 struct dc_context *ctx, 545 uint32_t inst, 546 const struct dce_opp_registers *regs, 547 const struct dce_opp_shift *opp_shift, 548 const struct dce_opp_mask *opp_mask) 549 { 550 opp110->base.funcs = &funcs; 551 552 opp110->base.ctx = ctx; 553 554 opp110->base.inst = inst; 555 556 opp110->regs = regs; 557 opp110->opp_shift = opp_shift; 558 opp110->opp_mask = opp_mask; 559 } 560 561 void dce110_opp_destroy(struct output_pixel_processor **opp) 562 { 563 if (*opp) 564 kfree(FROM_DCE11_OPP(*opp)); 565 *opp = NULL; 566 } 567 568