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 return; 133 /*Set truncation depth and Enable truncation*/ 134 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 135 FMT_TRUNCATE_EN, 1, 136 FMT_TRUNCATE_DEPTH, 137 params->flags.TRUNCATE_DEPTH, 138 FMT_TRUNCATE_MODE, 139 params->flags.TRUNCATE_MODE); 140 } 141 142 #if defined(CONFIG_DRM_AMD_DC_SI) 143 /* 144 * dce60_set_truncation 145 * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp 146 * 2) enable truncation 147 * 3) HW remove 12bit FMT support for DCE11 power saving reason. 148 */ 149 static void dce60_set_truncation( 150 struct dce110_opp *opp110, 151 const struct bit_depth_reduction_params *params) 152 { 153 /* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */ 154 155 /*Disable truncation*/ 156 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 157 FMT_TRUNCATE_EN, 0, 158 FMT_TRUNCATE_DEPTH, 0); 159 160 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 161 /* 8bpc trunc on YCbCr422*/ 162 if (params->flags.TRUNCATE_DEPTH == 1) 163 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 164 FMT_TRUNCATE_EN, 1, 165 FMT_TRUNCATE_DEPTH, 1); 166 else if (params->flags.TRUNCATE_DEPTH == 2) 167 /* 10bpc trunc on YCbCr422*/ 168 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 169 FMT_TRUNCATE_EN, 1, 170 FMT_TRUNCATE_DEPTH, 2); 171 return; 172 } 173 /* on other format-to do */ 174 if (params->flags.TRUNCATE_ENABLED == 0) 175 return; 176 /*Set truncation depth and Enable truncation*/ 177 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 178 FMT_TRUNCATE_EN, 1, 179 FMT_TRUNCATE_DEPTH, 180 params->flags.TRUNCATE_DEPTH); 181 } 182 #endif 183 184 /* 185 * set_spatial_dither 186 * 1) set spatial dithering mode: pattern of seed 187 * 2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp 188 * 3) set random seed 189 * 4) set random mode 190 * lfsr is reset every frame or not reset 191 * RGB dithering method 192 * 0: RGB data are all dithered with x^28+x^3+1 193 * 1: R data is dithered with x^28+x^3+1 194 * G data is dithered with x^28+X^9+1 195 * B data is dithered with x^28+x^13+1 196 * enable high pass filter or not 197 * 5) enable spatical dithering 198 */ 199 static void set_spatial_dither( 200 struct dce110_opp *opp110, 201 const struct bit_depth_reduction_params *params) 202 { 203 /*Disable spatial (random) dithering*/ 204 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 205 FMT_SPATIAL_DITHER_EN, 0, 206 FMT_SPATIAL_DITHER_DEPTH, 0, 207 FMT_SPATIAL_DITHER_MODE, 0); 208 209 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 210 FMT_HIGHPASS_RANDOM_ENABLE, 0, 211 FMT_FRAME_RANDOM_ENABLE, 0, 212 FMT_RGB_RANDOM_ENABLE, 0); 213 214 REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 215 FMT_TEMPORAL_DITHER_EN, 0); 216 217 if (params->flags.SPATIAL_DITHER_ENABLED == 0) 218 return; 219 220 /* only use FRAME_COUNTER_MAX if frameRandom == 1*/ 221 222 if (opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX && 223 opp110->opp_mask->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP) { 224 if (params->flags.FRAME_RANDOM == 1) { 225 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || 226 params->flags.SPATIAL_DITHER_DEPTH == 1) { 227 REG_UPDATE_2(FMT_CONTROL, 228 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15, 229 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2); 230 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) { 231 REG_UPDATE_2(FMT_CONTROL, 232 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3, 233 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1); 234 } else 235 return; 236 } else { 237 REG_UPDATE_2(FMT_CONTROL, 238 FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0, 239 FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0); 240 } 241 } 242 /* Set seed for random values for 243 * spatial dithering for R,G,B channels 244 */ 245 REG_UPDATE(FMT_DITHER_RAND_R_SEED, 246 FMT_RAND_R_SEED, params->r_seed_value); 247 248 REG_UPDATE(FMT_DITHER_RAND_G_SEED, 249 FMT_RAND_G_SEED, params->g_seed_value); 250 251 REG_UPDATE(FMT_DITHER_RAND_B_SEED, 252 FMT_RAND_B_SEED, params->b_seed_value); 253 254 /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero 255 * offset for the R/Cr channel, lower 4LSB 256 * is forced to zeros. Typically set to 0 257 * RGB and 0x80000 YCbCr. 258 */ 259 /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero 260 * offset for the G/Y channel, lower 4LSB is 261 * forced to zeros. Typically set to 0 RGB 262 * and 0x80000 YCbCr. 263 */ 264 /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero 265 * offset for the B/Cb channel, lower 4LSB is 266 * forced to zeros. Typically set to 0 RGB and 267 * 0x80000 YCbCr. 268 */ 269 270 /* Disable High pass filter 271 * Reset only at startup 272 * Set RGB data dithered with x^28+x^3+1 273 */ 274 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 275 FMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM, 276 FMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM, 277 FMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM); 278 279 /* Set spatial dithering bit depth 280 * Set spatial dithering mode 281 * (default is Seed patterrn AAAA...) 282 * Enable spatial dithering 283 */ 284 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 285 FMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH, 286 FMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE, 287 FMT_SPATIAL_DITHER_EN, 1); 288 } 289 290 /* 291 * SetTemporalDither (Frame Modulation) 292 * 1) set temporal dither depth 293 * 2) select pattern: from hard-coded pattern or programmable pattern 294 * 3) select optimized strips for BGR or RGB LCD sub-pixel 295 * 4) set s matrix 296 * 5) set t matrix 297 * 6) set grey level for 0.25, 0.5, 0.75 298 * 7) enable temporal dithering 299 */ 300 301 static void set_temporal_dither( 302 struct dce110_opp *opp110, 303 const struct bit_depth_reduction_params *params) 304 { 305 /*Disable temporal (frame modulation) dithering first*/ 306 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 307 FMT_TEMPORAL_DITHER_EN, 0, 308 FMT_TEMPORAL_DITHER_RESET, 0, 309 FMT_TEMPORAL_DITHER_OFFSET, 0); 310 311 REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, 312 FMT_TEMPORAL_DITHER_DEPTH, 0, 313 FMT_TEMPORAL_LEVEL, 0); 314 315 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 316 FMT_25FRC_SEL, 0, 317 FMT_50FRC_SEL, 0, 318 FMT_75FRC_SEL, 0); 319 320 /* no 10bpc dither on DCE11*/ 321 if (params->flags.FRAME_MODULATION_ENABLED == 0 || 322 params->flags.FRAME_MODULATION_DEPTH == 2) 323 return; 324 325 /* Set temporal dithering depth*/ 326 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 327 FMT_TEMPORAL_DITHER_DEPTH, params->flags.FRAME_MODULATION_DEPTH, 328 FMT_TEMPORAL_DITHER_RESET, 0, 329 FMT_TEMPORAL_DITHER_OFFSET, 0); 330 331 /*Select legacy pattern based on FRC and Temporal level*/ 332 if (REG(FMT_TEMPORAL_DITHER_PATTERN_CONTROL)) { 333 REG_WRITE(FMT_TEMPORAL_DITHER_PATTERN_CONTROL, 0); 334 /*Set s matrix*/ 335 REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX, 0); 336 /*Set t matrix*/ 337 REG_WRITE(FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX, 0); 338 } 339 340 /*Select patterns for 0.25, 0.5 and 0.75 grey level*/ 341 REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 342 FMT_TEMPORAL_LEVEL, params->flags.TEMPORAL_LEVEL); 343 344 REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, 345 FMT_25FRC_SEL, params->flags.FRC25, 346 FMT_50FRC_SEL, params->flags.FRC50, 347 FMT_75FRC_SEL, params->flags.FRC75); 348 349 /*Enable bit reduction by temporal (frame modulation) dithering*/ 350 REG_UPDATE(FMT_BIT_DEPTH_CONTROL, 351 FMT_TEMPORAL_DITHER_EN, 1); 352 } 353 354 /* 355 * Set Clamping 356 * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) 357 * 1 for 8 bpc 358 * 2 for 10 bpc 359 * 3 for 12 bpc 360 * 7 for programable 361 * 2) Enable clamp if Limited range requested 362 */ 363 void dce110_opp_set_clamping( 364 struct dce110_opp *opp110, 365 const struct clamping_and_pixel_encoding_params *params) 366 { 367 REG_SET_2(FMT_CLAMP_CNTL, 0, 368 FMT_CLAMP_DATA_EN, 0, 369 FMT_CLAMP_COLOR_FORMAT, 0); 370 371 switch (params->clamping_level) { 372 case CLAMPING_FULL_RANGE: 373 break; 374 case CLAMPING_LIMITED_RANGE_8BPC: 375 REG_SET_2(FMT_CLAMP_CNTL, 0, 376 FMT_CLAMP_DATA_EN, 1, 377 FMT_CLAMP_COLOR_FORMAT, 1); 378 break; 379 case CLAMPING_LIMITED_RANGE_10BPC: 380 REG_SET_2(FMT_CLAMP_CNTL, 0, 381 FMT_CLAMP_DATA_EN, 1, 382 FMT_CLAMP_COLOR_FORMAT, 2); 383 break; 384 case CLAMPING_LIMITED_RANGE_12BPC: 385 REG_SET_2(FMT_CLAMP_CNTL, 0, 386 FMT_CLAMP_DATA_EN, 1, 387 FMT_CLAMP_COLOR_FORMAT, 3); 388 break; 389 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: 390 /*Set clamp control*/ 391 REG_SET_2(FMT_CLAMP_CNTL, 0, 392 FMT_CLAMP_DATA_EN, 1, 393 FMT_CLAMP_COLOR_FORMAT, 7); 394 395 /*set the defaults*/ 396 REG_SET_2(FMT_CLAMP_COMPONENT_R, 0, 397 FMT_CLAMP_LOWER_R, 0x10, 398 FMT_CLAMP_UPPER_R, 0xFEF); 399 400 REG_SET_2(FMT_CLAMP_COMPONENT_G, 0, 401 FMT_CLAMP_LOWER_G, 0x10, 402 FMT_CLAMP_UPPER_G, 0xFEF); 403 404 REG_SET_2(FMT_CLAMP_COMPONENT_B, 0, 405 FMT_CLAMP_LOWER_B, 0x10, 406 FMT_CLAMP_UPPER_B, 0xFEF); 407 break; 408 default: 409 break; 410 } 411 } 412 413 #if defined(CONFIG_DRM_AMD_DC_SI) 414 /* 415 * Set Clamping for DCE6 parts 416 * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) 417 * 1 for 8 bpc 418 * 2 for 10 bpc 419 * 3 for 12 bpc 420 * 7 for programable 421 * 2) Enable clamp if Limited range requested 422 */ 423 static void dce60_opp_set_clamping( 424 struct dce110_opp *opp110, 425 const struct clamping_and_pixel_encoding_params *params) 426 { 427 REG_SET_2(FMT_CLAMP_CNTL, 0, 428 FMT_CLAMP_DATA_EN, 0, 429 FMT_CLAMP_COLOR_FORMAT, 0); 430 431 switch (params->clamping_level) { 432 case CLAMPING_FULL_RANGE: 433 break; 434 case CLAMPING_LIMITED_RANGE_8BPC: 435 REG_SET_2(FMT_CLAMP_CNTL, 0, 436 FMT_CLAMP_DATA_EN, 1, 437 FMT_CLAMP_COLOR_FORMAT, 1); 438 break; 439 case CLAMPING_LIMITED_RANGE_10BPC: 440 REG_SET_2(FMT_CLAMP_CNTL, 0, 441 FMT_CLAMP_DATA_EN, 1, 442 FMT_CLAMP_COLOR_FORMAT, 2); 443 break; 444 case CLAMPING_LIMITED_RANGE_12BPC: 445 REG_SET_2(FMT_CLAMP_CNTL, 0, 446 FMT_CLAMP_DATA_EN, 1, 447 FMT_CLAMP_COLOR_FORMAT, 3); 448 break; 449 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: 450 /*Set clamp control*/ 451 REG_SET_2(FMT_CLAMP_CNTL, 0, 452 FMT_CLAMP_DATA_EN, 1, 453 FMT_CLAMP_COLOR_FORMAT, 7); 454 455 /* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */ 456 457 break; 458 default: 459 break; 460 } 461 } 462 #endif 463 464 /* 465 * set_pixel_encoding 466 * 467 * Set Pixel Encoding 468 * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly 469 * 1: YCbCr 4:2:2 470 */ 471 static void set_pixel_encoding( 472 struct dce110_opp *opp110, 473 const struct clamping_and_pixel_encoding_params *params) 474 { 475 if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) 476 REG_UPDATE_3(FMT_CONTROL, 477 FMT_PIXEL_ENCODING, 0, 478 FMT_SUBSAMPLING_MODE, 0, 479 FMT_CBCR_BIT_REDUCTION_BYPASS, 0); 480 else 481 REG_UPDATE_2(FMT_CONTROL, 482 FMT_PIXEL_ENCODING, 0, 483 FMT_SUBSAMPLING_MODE, 0); 484 485 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 486 REG_UPDATE_2(FMT_CONTROL, 487 FMT_PIXEL_ENCODING, 1, 488 FMT_SUBSAMPLING_ORDER, 0); 489 } 490 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { 491 REG_UPDATE_3(FMT_CONTROL, 492 FMT_PIXEL_ENCODING, 2, 493 FMT_SUBSAMPLING_MODE, 2, 494 FMT_CBCR_BIT_REDUCTION_BYPASS, 1); 495 } 496 497 } 498 499 #if defined(CONFIG_DRM_AMD_DC_SI) 500 /* 501 * dce60_set_pixel_encoding 502 * DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg 503 * Set Pixel Encoding 504 * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly 505 * 1: YCbCr 4:2:2 506 */ 507 static void dce60_set_pixel_encoding( 508 struct dce110_opp *opp110, 509 const struct clamping_and_pixel_encoding_params *params) 510 { 511 if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) 512 REG_UPDATE_2(FMT_CONTROL, 513 FMT_PIXEL_ENCODING, 0, 514 FMT_CBCR_BIT_REDUCTION_BYPASS, 0); 515 else 516 REG_UPDATE(FMT_CONTROL, 517 FMT_PIXEL_ENCODING, 0); 518 519 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 520 REG_UPDATE(FMT_CONTROL, 521 FMT_PIXEL_ENCODING, 1); 522 } 523 if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { 524 REG_UPDATE_2(FMT_CONTROL, 525 FMT_PIXEL_ENCODING, 2, 526 FMT_CBCR_BIT_REDUCTION_BYPASS, 1); 527 } 528 529 } 530 #endif 531 532 void dce110_opp_program_bit_depth_reduction( 533 struct output_pixel_processor *opp, 534 const struct bit_depth_reduction_params *params) 535 { 536 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 537 538 set_truncation(opp110, params); 539 set_spatial_dither(opp110, params); 540 set_temporal_dither(opp110, params); 541 } 542 543 #if defined(CONFIG_DRM_AMD_DC_SI) 544 static void dce60_opp_program_bit_depth_reduction( 545 struct output_pixel_processor *opp, 546 const struct bit_depth_reduction_params *params) 547 { 548 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 549 550 dce60_set_truncation(opp110, params); 551 set_spatial_dither(opp110, params); 552 set_temporal_dither(opp110, params); 553 } 554 #endif 555 556 void dce110_opp_program_clamping_and_pixel_encoding( 557 struct output_pixel_processor *opp, 558 const struct clamping_and_pixel_encoding_params *params) 559 { 560 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 561 562 dce110_opp_set_clamping(opp110, params); 563 set_pixel_encoding(opp110, params); 564 } 565 566 #if defined(CONFIG_DRM_AMD_DC_SI) 567 static void dce60_opp_program_clamping_and_pixel_encoding( 568 struct output_pixel_processor *opp, 569 const struct clamping_and_pixel_encoding_params *params) 570 { 571 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 572 573 dce60_opp_set_clamping(opp110, params); 574 dce60_set_pixel_encoding(opp110, params); 575 } 576 #endif 577 578 579 static void program_formatter_420_memory(struct output_pixel_processor *opp) 580 { 581 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 582 uint32_t fmt_mem_cntl_value; 583 584 /* Program source select*/ 585 /* Use HW default source select for FMT_MEMORYx_CONTROL */ 586 /* Use that value for FMT_SRC_SELECT as well*/ 587 REG_GET(CONTROL, 588 FMT420_MEM0_SOURCE_SEL, &fmt_mem_cntl_value); 589 590 REG_UPDATE(FMT_CONTROL, 591 FMT_SRC_SELECT, fmt_mem_cntl_value); 592 593 /* Turn on the memory */ 594 REG_UPDATE(CONTROL, 595 FMT420_MEM0_PWR_FORCE, 0); 596 } 597 598 void dce110_opp_set_dyn_expansion( 599 struct output_pixel_processor *opp, 600 enum dc_color_space color_sp, 601 enum dc_color_depth color_dpth, 602 enum signal_type signal) 603 { 604 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 605 606 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 607 FMT_DYNAMIC_EXP_EN, 0, 608 FMT_DYNAMIC_EXP_MODE, 0); 609 610 /*00 - 10-bit -> 12-bit dynamic expansion*/ 611 /*01 - 8-bit -> 12-bit dynamic expansion*/ 612 if (signal == SIGNAL_TYPE_HDMI_TYPE_A || 613 signal == SIGNAL_TYPE_DISPLAY_PORT || 614 signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 615 switch (color_dpth) { 616 case COLOR_DEPTH_888: 617 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 618 FMT_DYNAMIC_EXP_EN, 1, 619 FMT_DYNAMIC_EXP_MODE, 1); 620 break; 621 case COLOR_DEPTH_101010: 622 REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL, 623 FMT_DYNAMIC_EXP_EN, 1, 624 FMT_DYNAMIC_EXP_MODE, 0); 625 break; 626 case COLOR_DEPTH_121212: 627 REG_UPDATE_2( 628 FMT_DYNAMIC_EXP_CNTL, 629 FMT_DYNAMIC_EXP_EN, 1,/*otherwise last two bits are zero*/ 630 FMT_DYNAMIC_EXP_MODE, 0); 631 break; 632 default: 633 break; 634 } 635 } 636 } 637 638 static void program_formatter_reset_dig_resync_fifo(struct output_pixel_processor *opp) 639 { 640 struct dce110_opp *opp110 = TO_DCE110_OPP(opp); 641 642 /* clear previous phase lock status*/ 643 REG_UPDATE(FMT_CONTROL, 644 FMT_420_PIXEL_PHASE_LOCKED_CLEAR, 1); 645 646 /* poll until FMT_420_PIXEL_PHASE_LOCKED become 1*/ 647 REG_WAIT(FMT_CONTROL, FMT_420_PIXEL_PHASE_LOCKED, 1, 10, 10); 648 649 } 650 651 void dce110_opp_program_fmt( 652 struct output_pixel_processor *opp, 653 struct bit_depth_reduction_params *fmt_bit_depth, 654 struct clamping_and_pixel_encoding_params *clamping) 655 { 656 /* dithering is affected by <CrtcSourceSelect>, hence should be 657 * programmed afterwards */ 658 659 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 660 program_formatter_420_memory(opp); 661 662 dce110_opp_program_bit_depth_reduction( 663 opp, 664 fmt_bit_depth); 665 666 dce110_opp_program_clamping_and_pixel_encoding( 667 opp, 668 clamping); 669 670 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 671 program_formatter_reset_dig_resync_fifo(opp); 672 673 return; 674 } 675 676 #if defined(CONFIG_DRM_AMD_DC_SI) 677 static void dce60_opp_program_fmt( 678 struct output_pixel_processor *opp, 679 struct bit_depth_reduction_params *fmt_bit_depth, 680 struct clamping_and_pixel_encoding_params *clamping) 681 { 682 /* dithering is affected by <CrtcSourceSelect>, hence should be 683 * programmed afterwards */ 684 685 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 686 program_formatter_420_memory(opp); 687 688 dce60_opp_program_bit_depth_reduction( 689 opp, 690 fmt_bit_depth); 691 692 dce60_opp_program_clamping_and_pixel_encoding( 693 opp, 694 clamping); 695 696 if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) 697 program_formatter_reset_dig_resync_fifo(opp); 698 699 return; 700 } 701 #endif 702 703 704 705 /*****************************************/ 706 /* Constructor, Destructor */ 707 /*****************************************/ 708 709 static const struct opp_funcs funcs = { 710 .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, 711 .opp_destroy = dce110_opp_destroy, 712 .opp_program_fmt = dce110_opp_program_fmt, 713 .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction 714 }; 715 716 #if defined(CONFIG_DRM_AMD_DC_SI) 717 static const struct opp_funcs dce60_opp_funcs = { 718 .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, 719 .opp_destroy = dce110_opp_destroy, 720 .opp_program_fmt = dce60_opp_program_fmt, 721 .opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction 722 }; 723 #endif 724 725 void dce110_opp_construct(struct dce110_opp *opp110, 726 struct dc_context *ctx, 727 uint32_t inst, 728 const struct dce_opp_registers *regs, 729 const struct dce_opp_shift *opp_shift, 730 const struct dce_opp_mask *opp_mask) 731 { 732 opp110->base.funcs = &funcs; 733 734 opp110->base.ctx = ctx; 735 736 opp110->base.inst = inst; 737 738 opp110->regs = regs; 739 opp110->opp_shift = opp_shift; 740 opp110->opp_mask = opp_mask; 741 } 742 743 #if defined(CONFIG_DRM_AMD_DC_SI) 744 void dce60_opp_construct(struct dce110_opp *opp110, 745 struct dc_context *ctx, 746 uint32_t inst, 747 const struct dce_opp_registers *regs, 748 const struct dce_opp_shift *opp_shift, 749 const struct dce_opp_mask *opp_mask) 750 { 751 opp110->base.funcs = &dce60_opp_funcs; 752 753 opp110->base.ctx = ctx; 754 755 opp110->base.inst = inst; 756 757 opp110->regs = regs; 758 opp110->opp_shift = opp_shift; 759 opp110->opp_mask = opp_mask; 760 } 761 #endif 762 763 void dce110_opp_destroy(struct output_pixel_processor **opp) 764 { 765 if (*opp) 766 kfree(FROM_DCE11_OPP(*opp)); 767 *opp = NULL; 768 } 769 770