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