1 /* 2 * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, kallisti5@unixzen.com 7 */ 8 9 10 #include "accelerant_protos.h" 11 #include "accelerant.h" 12 #include "bios.h" 13 #include "display.h" 14 #include "utility.h" 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <math.h> 20 21 22 #define TRACE_ENCODER 23 #ifdef TRACE_ENCODER 24 extern "C" void _sPrintf(const char *format, ...); 25 # define TRACE(x...) _sPrintf("radeon_hd: " x) 26 #else 27 # define TRACE(x...) ; 28 #endif 29 30 #define ERROR(x...) _sPrintf("radeon_hd: " x) 31 32 33 union crtc_source_param { 34 SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 35 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 36 }; 37 38 39 void 40 encoder_assign_crtc(uint8 crtcID) 41 { 42 TRACE("%s\n", __func__); 43 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 44 union crtc_source_param args; 45 46 // Table version 47 uint8 tableMajor; 48 uint8 tableMinor; 49 50 memset(&args, 0, sizeof(args)); 51 52 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 53 != B_OK) 54 return; 55 56 uint16 connectorIndex = gDisplay[crtcID]->connectorIndex; 57 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 58 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 59 60 switch (tableMajor) { 61 case 1: 62 switch (tableMinor) { 63 case 1: 64 default: 65 args.v1.ucCRTC = crtcID; 66 switch (encoderID) { 67 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 68 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 69 args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 70 break; 71 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 72 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 73 if ((gConnector[connectorIndex]->flags 74 & ATOM_DEVICE_LCD1_SUPPORT) != 0) 75 args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 76 else 77 args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 78 break; 79 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 80 case ENCODER_OBJECT_ID_INTERNAL_DDI: 81 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 82 args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 83 break; 84 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 85 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 86 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 87 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 88 } else if ((encoderFlags 89 & ATOM_DEVICE_CV_SUPPORT) != 0) { 90 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 91 } else 92 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 93 break; 94 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 95 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 96 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 97 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 98 } else if ((encoderFlags 99 & ATOM_DEVICE_CV_SUPPORT) != 0) { 100 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 101 } else 102 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 103 break; 104 } 105 break; 106 case 2: 107 args.v2.ucCRTC = crtcID; 108 args.v2.ucEncodeMode 109 = display_get_encoder_mode(connectorIndex); 110 switch (encoderID) { 111 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 112 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 113 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 114 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 115 ERROR("%s: DIG encoder not yet supported!\n", 116 __func__); 117 //dig = radeon_encoder->enc_priv; 118 //switch (dig->dig_encoder) { 119 // case 0: 120 // args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 121 // break; 122 // case 1: 123 // args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 124 // break; 125 // case 2: 126 // args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 127 // break; 128 // case 3: 129 // args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 130 // break; 131 // case 4: 132 // args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 133 // break; 134 // case 5: 135 // args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 136 // break; 137 //} 138 break; 139 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 140 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 141 break; 142 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 143 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 144 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 145 } else if ((encoderFlags 146 & ATOM_DEVICE_CV_SUPPORT) != 0) { 147 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 148 } else 149 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 150 break; 151 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 152 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 153 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 154 } else if ((encoderFlags 155 & ATOM_DEVICE_CV_SUPPORT) != 0) { 156 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 157 } else 158 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 159 break; 160 } 161 break; 162 } 163 break; 164 default: 165 ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 166 __func__, tableMajor, tableMinor); 167 return; 168 } 169 170 atom_execute_table(gAtomContext, index, (uint32*)&args); 171 172 // update crtc encoder scratch register @ scratch 3 173 encoder_crtc_scratch(crtcID); 174 } 175 176 177 void 178 encoder_apply_quirks(uint8 crtcID) 179 { 180 TRACE("%s\n", __func__); 181 radeon_shared_info &info = *gInfo->shared_info; 182 register_info* regs = gDisplay[crtcID]->regs; 183 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 184 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 185 186 // Setting the scaler clears this on some chips... 187 if (info.dceMajor >= 3 188 && (encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0) { 189 // TODO: assume non interleave mode for now 190 // en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN 191 Write32(OUT, regs->modeDataFormat, 0); 192 } 193 } 194 195 196 void 197 encoder_mode_set(uint8 id, uint32 pixelClock) 198 { 199 TRACE("%s\n", __func__); 200 radeon_shared_info &info = *gInfo->shared_info; 201 uint32 connectorIndex = gDisplay[id]->connectorIndex; 202 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 203 204 switch (gConnector[connectorIndex]->encoder.objectID) { 205 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 206 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 207 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 208 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 209 encoder_analog_setup(id, pixelClock, ATOM_ENABLE); 210 if ((encoderFlags 211 & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) != 0) { 212 encoder_tv_setup(id, pixelClock, ATOM_ENABLE); 213 } else { 214 encoder_tv_setup(id, pixelClock, ATOM_DISABLE); 215 } 216 break; 217 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 218 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 219 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 220 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 221 encoder_digital_setup(id, pixelClock, PANEL_ENCODER_ACTION_ENABLE); 222 break; 223 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 224 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 225 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 226 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 227 if (info.dceMajor >= 4) { 228 //atombios_dig_transmitter_setup(encoder, 229 // ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 230 // TODO: Disable the dig transmitter 231 encoder_dig_setup(id, pixelClock, ATOM_ENCODER_CMD_SETUP); 232 // Setup and enable the dig encoder 233 234 //atombios_dig_transmitter_setup(encoder, 235 // ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 236 // TODO: Enable the dig transmitter 237 } else { 238 //atombios_dig_transmitter_setup(encoder, 239 // ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 240 // Disable the dig transmitter 241 encoder_dig_setup(id, pixelClock, ATOM_DISABLE); 242 // Disable the dig encoder 243 244 /* setup and enable the encoder and transmitter */ 245 encoder_dig_setup(id, pixelClock, ATOM_ENABLE); 246 // Setup and enable the dig encoder 247 248 //atombios_dig_transmitter_setup(encoder, 249 // ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 250 //atombios_dig_transmitter_setup(encoder, 251 // ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 252 // TODO: Setup and Enable the dig transmitter 253 } 254 255 TRACE("%s: TODO for DIG encoder setup\n", __func__); 256 break; 257 case ENCODER_OBJECT_ID_INTERNAL_DDI: 258 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 259 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 260 TRACE("%s: TODO for DVO encoder setup\n", __func__); 261 break; 262 case ENCODER_OBJECT_ID_TRAVIS: // external DP -> LVDS encoder 263 case ENCODER_OBJECT_ID_NUTMEG: // external DP -> VGA encoder 264 ERROR("%s: Oh, you have a TRAVIS or NUTMEG DP external encoder..." 265 " what a pitty.\n", __func__); 266 // * PALM can have native LVDS / VGA, or have them wired via DP 267 // This is an OEM choice on PALM chipsets 268 // * SUMO or SUMO2 *always* have LVDS or VGA connected through DP 269 // fallthrough 270 case ENCODER_OBJECT_ID_SI170B: 271 case ENCODER_OBJECT_ID_CH7303: 272 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 273 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 274 case ENCODER_OBJECT_ID_TITFP513: 275 case ENCODER_OBJECT_ID_VT1623: 276 case ENCODER_OBJECT_ID_HDMI_SI1930: 277 if (info.dceMajor >= 4 && info.dceMinor >= 1) { 278 encoder_external_setup(id, pixelClock, 279 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 280 } else { 281 encoder_external_setup(id, pixelClock, 282 ATOM_ENABLE); 283 } 284 break; 285 default: 286 TRACE("%s: TODO for unknown encoder setup!\n", __func__); 287 } 288 289 encoder_apply_quirks(id); 290 } 291 292 293 status_t 294 encoder_tv_setup(uint8 id, uint32 pixelClock, int command) 295 { 296 uint32 connectorIndex = gDisplay[id]->connectorIndex; 297 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 298 299 TV_ENCODER_CONTROL_PS_ALLOCATION args; 300 memset(&args, 0, sizeof(args)); 301 302 int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 303 304 args.sTVEncoder.ucAction = command; 305 306 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 307 args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 308 else { 309 // TODO: we assume NTSC for now 310 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 311 } 312 313 args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 314 315 return atom_execute_table(gAtomContext, index, (uint32*)&args); 316 } 317 318 319 union lvds_encoder_control { 320 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 321 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 322 }; 323 324 325 status_t 326 encoder_digital_setup(uint8 id, uint32 pixelClock, int command) 327 { 328 TRACE("%s\n", __func__); 329 330 uint32 connectorIndex = gDisplay[id]->connectorIndex; 331 332 union lvds_encoder_control args; 333 memset(&args, 0, sizeof(args)); 334 335 int index = 0; 336 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 337 338 switch (gConnector[connectorIndex]->encoder.objectID) { 339 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 340 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 341 break; 342 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 343 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 344 index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 345 break; 346 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 347 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 348 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 349 else 350 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 351 break; 352 } 353 354 // Table verson 355 uint8 tableMajor; 356 uint8 tableMinor; 357 358 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 359 != B_OK) { 360 ERROR("%s: cannot parse command table\n", __func__); 361 return B_ERROR; 362 } 363 364 switch (tableMajor) { 365 case 1: 366 case 2: 367 switch (tableMinor) { 368 case 1: 369 args.v1.ucMisc = 0; 370 args.v1.ucAction = command; 371 if (0) // TODO: HDMI? 372 args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 373 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 374 375 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 376 // TODO: laptop display support 377 //if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 378 // args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 379 //if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 380 // args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 381 } else { 382 //if (dig->linkb) 383 // args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 384 if (pixelClock > 165000) 385 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 386 /*if (pScrn->rgbBits == 8) */ 387 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 388 } 389 break; 390 case 2: 391 case 3: 392 args.v2.ucMisc = 0; 393 args.v2.ucAction = command; 394 if (tableMinor == 3) { 395 //if (dig->coherent_mode) 396 // args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 397 } 398 if (0) // TODO: HDMI? 399 args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 400 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 401 args.v2.ucTruncate = 0; 402 args.v2.ucSpatial = 0; 403 args.v2.ucTemporal = 0; 404 args.v2.ucFRC = 0; 405 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 406 // TODO: laptop display support 407 //if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 408 // args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 409 //if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { 410 args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 411 //if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 412 // args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 413 //} 414 //if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { 415 // args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 416 // if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) { 417 // args.v2.ucTemporal 418 // |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 419 // } 420 // if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) 421 // & 0x3) == 2) { 422 // args.v2.ucTemporal 423 // |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 424 // } 425 //} 426 } else { 427 //if (dig->linkb) 428 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 429 if (pixelClock > 165000) 430 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 431 } 432 break; 433 default: 434 ERROR("%s: Unknown minor table version: %" 435 B_PRIu8 ".%" B_PRIu8 "\n", __func__, 436 tableMajor, tableMinor); 437 return B_ERROR; 438 } 439 break; 440 default: 441 ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 442 __func__, tableMajor, tableMinor); 443 return B_ERROR; 444 } 445 return atom_execute_table(gAtomContext, index, (uint32*)&args); 446 } 447 448 449 union dig_encoder_control { 450 DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 451 DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 452 DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 453 DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 454 }; 455 456 457 status_t 458 encoder_dig_setup(uint8 id, uint32 pixelClock, int command) 459 { 460 radeon_shared_info &info = *gInfo->shared_info; 461 462 uint32 connectorIndex = gDisplay[id]->connectorIndex; 463 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 464 465 union dig_encoder_control args; 466 int index = 0; 467 468 // Table verson 469 uint8 tableMajor; 470 uint8 tableMinor; 471 472 memset(&args, 0, sizeof(args)); 473 474 if (info.dceMajor > 4) 475 index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 476 else { 477 if (1) // TODO: pick dig encoder 478 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 479 else 480 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 481 } 482 483 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 484 != B_OK) { 485 ERROR("%s: cannot parse command table\n", __func__); 486 return B_ERROR; 487 } 488 489 args.v1.ucAction = command; 490 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 491 492 #if 0 493 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) { 494 if (info.dceMajor >= 4 && 0) // TODO: 0 == if DP bridge 495 args.v3.ucPanelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 496 else 497 args.v3.ucPanelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 498 } else { 499 args.v1.ucEncoderMode = display_get_encoder_mode(connectorIndex); 500 501 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 502 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 503 args.v1.ucLaneNum = dp_lane_count; 504 } else if (pixelClock > 165000) 505 args.v1.ucLaneNum = 8; 506 else 507 args.v1.ucLaneNum = 4; 508 509 if (info.dceMajor >= 5) { 510 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 511 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 512 if (dpClock == 270000) { 513 args.v1.ucConfig 514 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; 515 } else if (dpClock == 540000) { 516 args.v1.ucConfig 517 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; 518 } 519 } 520 args.v4.acConfig.ucDigSel = dig->dig_encoder; 521 switch (bpc) { 522 case 0: 523 args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; 524 break; 525 case 6: 526 args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; 527 break; 528 case 8: 529 default: 530 args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; 531 break; 532 case 10: 533 args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; 534 break; 535 case 12: 536 args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; 537 break; 538 case 16: 539 args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; 540 break; 541 } 542 543 //if (hpdID == RADEON_HPD_NONE) 544 if (1) 545 args.v4.ucHPD_ID = 0; 546 else 547 args.v4.ucHPD_ID = hpd_id + 1; 548 549 } else if (info.dceMajor >= 4) { 550 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 551 && dp_clock == 270000) { 552 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 553 } 554 555 args.v3.acConfig.ucDigSel = dig->dig_encoder; 556 switch (bpc) { 557 case 0: 558 args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE; 559 break; 560 case 6: 561 args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR; 562 break; 563 case 8: 564 default: 565 args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; 566 break; 567 case 10: 568 args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR; 569 break; 570 case 12: 571 args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR; 572 break; 573 case 16: 574 args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR; 575 break; 576 } 577 578 } else { 579 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 580 && dp_clock == 270000) { 581 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 582 } 583 #endif 584 switch (encoderID) { 585 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 586 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 587 break; 588 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 589 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 590 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 591 break; 592 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 593 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 594 break; 595 } 596 #if 0 597 if (dig->linkb) 598 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 599 else 600 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 601 } 602 #endif 603 604 return atom_execute_table(gAtomContext, index, (uint32*)&args); 605 } 606 607 608 union external_encoder_control { 609 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 610 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 611 }; 612 613 614 status_t 615 encoder_external_setup(uint8 id, uint32 pixelClock, int command) 616 { 617 TRACE("%s\n", __func__); 618 619 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 620 union external_encoder_control args; 621 memset(&args, 0, sizeof(args)); 622 623 uint32 connectorIndex = gDisplay[id]->connectorIndex; 624 int connectorObjectID 625 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 626 >> OBJECT_ID_SHIFT; 627 628 uint8 tableMajor; 629 uint8 tableMinor; 630 631 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 632 != B_OK) { 633 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__); 634 return B_ERROR; 635 } 636 637 switch (tableMajor) { 638 case 1: 639 // no options needed on table 1.x 640 break; 641 case 2: 642 switch (tableMinor) { 643 case 1: 644 case 2: 645 args.v1.sDigEncoder.ucAction = command; 646 args.v1.sDigEncoder.usPixelClock 647 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 648 args.v1.sDigEncoder.ucEncoderMode 649 = display_get_encoder_mode(connectorIndex); 650 #if 0 651 if (0) { // ENCODER_MODE_IS_DP(v1.sDigEncoder.ucEncoderMode) 652 if (dp_clock == 270000) { 653 args.v1.sDigEncoder.ucConfig 654 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 655 } 656 args.v1.sDigEncoder.ucLaneNum = dp_lane_count; 657 } else if (pixelClock > 165000) { 658 #endif 659 if (pixelClock > 165000) { 660 args.v1.sDigEncoder.ucLaneNum = 8; 661 } else { 662 args.v1.sDigEncoder.ucLaneNum = 4; 663 } 664 break; 665 case 3: 666 { 667 args.v3.sExtEncoder.ucAction = command; 668 if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) { 669 args.v3.sExtEncoder.usConnectorId 670 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 671 } else { 672 args.v3.sExtEncoder.usPixelClock 673 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 674 } 675 676 args.v3.sExtEncoder.ucEncoderMode 677 = display_get_encoder_mode(connectorIndex); 678 679 #if 0 680 if (ENCODER_MODE_IS_DP(args.v3.sExtEncoder.ucEncoderMode)) { 681 if (dp_clock == 270000) { 682 args.v3.sExtEncoder.ucConfig 683 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 684 } else if (dp_clock == 540000) { 685 args.v3.sExtEncoder.ucConfig 686 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 687 } 688 args.v3.sExtEncoder.ucLaneNum = dp_lane_count; 689 } else if (pixelClock > 165000) { 690 #endif 691 if (pixelClock > 165000) { 692 args.v3.sExtEncoder.ucLaneNum = 8; 693 } else { 694 args.v3.sExtEncoder.ucLaneNum = 4; 695 } 696 697 uint16 encoderFlags 698 = gConnector[connectorIndex]->encoder.flags; 699 switch ((encoderFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) { 700 case GRAPH_OBJECT_ENUM_ID1: 701 TRACE("%s: external encoder 1\n", __func__); 702 args.v3.sExtEncoder.ucConfig 703 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 704 break; 705 case GRAPH_OBJECT_ENUM_ID2: 706 TRACE("%s: external encoder 2\n", __func__); 707 args.v3.sExtEncoder.ucConfig 708 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 709 break; 710 case GRAPH_OBJECT_ENUM_ID3: 711 TRACE("%s: external encoder 3\n", __func__); 712 args.v3.sExtEncoder.ucConfig 713 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 714 break; 715 } 716 717 // TODO: don't set statically 718 uint32 bitsPerColor = 8; 719 switch (bitsPerColor) { 720 case 0: 721 args.v3.sExtEncoder.ucBitPerColor 722 = PANEL_BPC_UNDEFINE; 723 break; 724 case 6: 725 args.v3.sExtEncoder.ucBitPerColor 726 = PANEL_6BIT_PER_COLOR; 727 break; 728 case 8: 729 default: 730 args.v3.sExtEncoder.ucBitPerColor 731 = PANEL_8BIT_PER_COLOR; 732 break; 733 case 10: 734 args.v3.sExtEncoder.ucBitPerColor 735 = PANEL_10BIT_PER_COLOR; 736 break; 737 case 12: 738 args.v3.sExtEncoder.ucBitPerColor 739 = PANEL_12BIT_PER_COLOR; 740 break; 741 case 16: 742 args.v3.sExtEncoder.ucBitPerColor 743 = PANEL_16BIT_PER_COLOR; 744 break; 745 } 746 break; 747 } 748 default: 749 ERROR("%s: Unknown table minor version: " 750 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 751 tableMajor, tableMinor); 752 return B_ERROR; 753 } 754 break; 755 default: 756 ERROR("%s: Unknown table major version: " 757 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 758 tableMajor, tableMinor); 759 return B_ERROR; 760 } 761 762 return atom_execute_table(gAtomContext, index, (uint32*)&args); 763 } 764 765 766 status_t 767 encoder_analog_setup(uint8 id, uint32 pixelClock, int command) 768 { 769 TRACE("%s\n", __func__); 770 771 uint32 connectorIndex = gDisplay[id]->connectorIndex; 772 773 int index = 0; 774 DAC_ENCODER_CONTROL_PS_ALLOCATION args; 775 memset(&args, 0, sizeof(args)); 776 777 switch (gConnector[connectorIndex]->encoder.objectID) { 778 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 779 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 780 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 781 break; 782 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 783 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 784 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 785 break; 786 } 787 788 args.ucAction = command; 789 args.ucDacStandard = ATOM_DAC1_PS2; 790 // TODO: or ATOM_DAC1_CV if ATOM_DEVICE_CV_SUPPORT 791 // TODO: or ATOM_DAC1_PAL or ATOM_DAC1_NTSC if else 792 793 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 794 795 return atom_execute_table(gAtomContext, index, (uint32*)&args); 796 } 797 798 799 bool 800 encoder_analog_load_detect(uint8 connectorIndex) 801 { 802 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 803 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 804 805 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0 806 && (encoderFlags & ATOM_DEVICE_CV_SUPPORT) == 0 807 && (encoderFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) { 808 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n", 809 __func__, connectorIndex); 810 return false; 811 } 812 813 // *** tell the card we want to do a DAC detection 814 815 DAC_LOAD_DETECTION_PS_ALLOCATION args; 816 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 817 uint8 tableMajor; 818 uint8 tableMinor; 819 820 memset(&args, 0, sizeof(args)); 821 822 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 823 != B_OK) { 824 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n", 825 __func__); 826 return false; 827 } 828 829 args.sDacload.ucMisc = 0; 830 831 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1 832 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) { 833 args.sDacload.ucDacType = ATOM_DAC_A; 834 } else { 835 args.sDacload.ucDacType = ATOM_DAC_B; 836 } 837 838 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 839 args.sDacload.usDeviceID 840 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT); 841 atom_execute_table(gAtomContext, index, (uint32*)&args); 842 843 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 844 845 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 846 return true; 847 848 } else if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 849 args.sDacload.usDeviceID 850 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT); 851 atom_execute_table(gAtomContext, index, (uint32*)&args); 852 853 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 854 855 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 856 return true; 857 858 } else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 859 args.sDacload.usDeviceID 860 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT); 861 if (tableMinor >= 3) 862 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 863 atom_execute_table(gAtomContext, index, (uint32*)&args); 864 865 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 866 867 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 868 return true; 869 870 } else if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 871 args.sDacload.usDeviceID 872 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT); 873 if (tableMinor >= 3) 874 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 875 atom_execute_table(gAtomContext, index, (uint32*)&args); 876 877 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 878 879 if ((biosScratch0 880 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) { 881 return true; /* Composite connected */ 882 } else if ((biosScratch0 883 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) { 884 return true; /* S-Video connected */ 885 } 886 887 } 888 return false; 889 } 890 891 892 void 893 encoder_crtc_scratch(uint8 crtcID) 894 { 895 TRACE("%s\n", __func__); 896 897 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 898 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 899 900 // TODO: r500 901 uint32 biosScratch3 = Read32(OUT, R600_BIOS_3_SCRATCH); 902 903 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 904 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE; 905 biosScratch3 |= (crtcID << 18); 906 } 907 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 908 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE; 909 biosScratch3 |= (crtcID << 24); 910 } 911 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 912 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 913 biosScratch3 |= (crtcID << 16); 914 } 915 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 916 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 917 biosScratch3 |= (crtcID << 20); 918 } 919 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 920 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 921 biosScratch3 |= (crtcID << 17); 922 } 923 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 924 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 925 biosScratch3 |= (crtcID << 19); 926 } 927 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 928 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 929 biosScratch3 |= (crtcID << 23); 930 } 931 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 932 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 933 biosScratch3 |= (crtcID << 25); 934 } 935 936 // TODO: r500 937 Write32(OUT, R600_BIOS_3_SCRATCH, biosScratch3); 938 } 939 940 941 void 942 encoder_dpms_scratch(uint8 crtcID, bool power) 943 { 944 TRACE("%s: power: %s\n", __func__, power ? "true" : "false"); 945 946 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 947 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 948 949 // TODO: r500 950 uint32 biosScratch2 = Read32(OUT, R600_BIOS_2_SCRATCH); 951 952 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 953 if (power == true) 954 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE; 955 else 956 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE; 957 } 958 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 959 if (power == true) 960 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE; 961 else 962 biosScratch2 |= ATOM_S2_CV_DPMS_STATE; 963 } 964 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 965 if (power == true) 966 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE; 967 else 968 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE; 969 } 970 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 971 if (power == true) 972 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE; 973 else 974 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE; 975 } 976 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 977 if (power == true) 978 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE; 979 else 980 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE; 981 } 982 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 983 if (power == true) 984 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE; 985 else 986 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE; 987 } 988 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 989 if (power == true) 990 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE; 991 else 992 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE; 993 } 994 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 995 if (power == true) 996 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE; 997 else 998 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE; 999 } 1000 if ((encoderFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) { 1001 if (power == true) 1002 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE; 1003 else 1004 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE; 1005 } 1006 if ((encoderFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) { 1007 if (power == true) 1008 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE; 1009 else 1010 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE; 1011 } 1012 Write32(OUT, R600_BIOS_2_SCRATCH, biosScratch2); 1013 } 1014 1015 1016 void 1017 encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode) 1018 { 1019 int index = 0; 1020 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1021 1022 memset(&args, 0, sizeof(args)); 1023 1024 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1025 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1026 1027 switch (encoderID) { 1028 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1029 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1030 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1031 break; 1032 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1033 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1034 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1035 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1036 ERROR("%s: TODO DIG DPMS set\n", __func__); 1037 return; 1038 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1039 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1040 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1041 break; 1042 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1043 // TODO: encoder dpms set newer cards 1044 // If DCE5, dvo true 1045 // If DCE3, dig true 1046 // else... 1047 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1048 break; 1049 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1050 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1051 break; 1052 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1053 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1054 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1055 else 1056 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1057 break; 1058 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1059 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1060 // TODO: encoder dpms dce5 dac 1061 // else... 1062 /* 1063 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 1064 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1065 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 1066 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1067 else 1068 */ 1069 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1070 break; 1071 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1072 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1073 // TODO: tv or CV encoder on DAC2 1074 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1075 break; 1076 } 1077 1078 switch (mode) { 1079 case B_DPMS_ON: 1080 args.ucAction = ATOM_ENABLE; 1081 atom_execute_table(gAtomContext, index, (uint32*)&args); 1082 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1083 args.ucAction = ATOM_LCD_BLON; 1084 atom_execute_table(gAtomContext, index, (uint32*)&args); 1085 } 1086 encoder_dpms_scratch(crtcID, true); 1087 break; 1088 case B_DPMS_STAND_BY: 1089 case B_DPMS_SUSPEND: 1090 case B_DPMS_OFF: 1091 args.ucAction = ATOM_DISABLE; 1092 atom_execute_table(gAtomContext, index, (uint32*)&args); 1093 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1094 args.ucAction = ATOM_LCD_BLOFF; 1095 atom_execute_table(gAtomContext, index, (uint32*)&args); 1096 } 1097 encoder_dpms_scratch(crtcID, false); 1098 break; 1099 } 1100 } 1101 1102 1103 void 1104 encoder_output_lock(bool lock) 1105 { 1106 TRACE("%s: %s\n", __func__, lock ? "true" : "false"); 1107 uint32 biosScratch6 = Read32(OUT, R600_BIOS_6_SCRATCH); 1108 1109 if (lock) { 1110 biosScratch6 |= ATOM_S6_CRITICAL_STATE; 1111 biosScratch6 &= ~ATOM_S6_ACC_MODE; 1112 } else { 1113 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE; 1114 biosScratch6 |= ATOM_S6_ACC_MODE; 1115 } 1116 1117 Write32(OUT, R600_BIOS_6_SCRATCH, biosScratch6); 1118 } 1119 1120 1121 static const char *encoder_name_matrix[36] = { 1122 "NONE", 1123 "Internal Radeon LVDS", 1124 "Internal Radeon TMDS1", 1125 "Internal Radeon TMDS2", 1126 "Internal Radeon DAC1", 1127 "Internal Radeon DAC2 (TV)", 1128 "Internal Radeon SDVOA", 1129 "Internal Radeon SDVOB", 1130 "External 3rd party SI170B", 1131 "External 3rd party CH7303", 1132 "External 3rd party CH7301", 1133 "Internal Radeon DVO1", 1134 "External 3rd party SDVOA", 1135 "External 3rd party SDVOB", 1136 "External 3rd party TITFP513", 1137 "Internal LVTM1", 1138 "External 3rd party VT1623", 1139 "External HDMI SI1930", 1140 "Internal HDMI", 1141 "Internal Kaleidoscope TMDS1", 1142 "Internal Kaleidoscope DVO1", 1143 "Internal Kaleidoscope DAC1", 1144 "Internal Kaleidoscope DAC2", 1145 "External Kaleidoscope SI178", 1146 "MVPU FPGA", 1147 "Internal Kaleidoscope DDI", 1148 "External Kaleidoscope VT1625", 1149 "External Kaleidoscope HDMI SI1932", 1150 "External Kaleidoscope DP AN9801", 1151 "External Kaleidoscope DP DP501", 1152 "Internal Kaleidoscope UNIPHY", 1153 "Internal Kaleidoscope LVTMA", 1154 "Internal Kaleidoscope UNIPHY1", 1155 "Internal Kaleidoscope UNIPHY2", 1156 "External Travis Bridge", 1157 "External Nutmeg Bridge" 1158 }; 1159 1160 1161 const char* 1162 encoder_name_lookup(uint32 encoderID) { 1163 if (encoderID <= sizeof(encoder_name_matrix)) 1164 return encoder_name_matrix[encoderID]; 1165 else 1166 return "Unknown"; 1167 } 1168 1169 1170 uint32 1171 encoder_object_lookup(uint32 encoderFlags, uint8 dacID) 1172 { 1173 // used on older cards to take a guess at the encoder 1174 // object 1175 1176 radeon_shared_info &info = *gInfo->shared_info; 1177 1178 uint32 ret = 0; 1179 1180 switch (encoderFlags) { 1181 case ATOM_DEVICE_CRT1_SUPPORT: 1182 case ATOM_DEVICE_TV1_SUPPORT: 1183 case ATOM_DEVICE_TV2_SUPPORT: 1184 case ATOM_DEVICE_CRT2_SUPPORT: 1185 case ATOM_DEVICE_CV_SUPPORT: 1186 switch (dacID) { 1187 case 1: 1188 if ((info.chipsetID == RADEON_RS400) 1189 || (info.chipsetID == RADEON_RS480)) 1190 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 1191 else if (info.chipsetID >= RADEON_RS600) 1192 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 1193 else 1194 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 1195 break; 1196 case 2: 1197 if (info.chipsetID >= RADEON_RS600) 1198 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 1199 else { 1200 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 1201 } 1202 break; 1203 case 3: // external dac 1204 if (info.chipsetID >= RADEON_RS600) 1205 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 1206 else 1207 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1208 break; 1209 } 1210 break; 1211 case ATOM_DEVICE_LCD1_SUPPORT: 1212 if (info.chipsetID >= RADEON_RS600) 1213 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 1214 else 1215 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 1216 break; 1217 case ATOM_DEVICE_DFP1_SUPPORT: 1218 if ((info.chipsetID == RADEON_RS400) 1219 || (info.chipsetID == RADEON_RS480)) 1220 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1221 else if (info.chipsetID >= RADEON_RS600) 1222 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 1223 else 1224 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 1225 break; 1226 case ATOM_DEVICE_LCD2_SUPPORT: 1227 case ATOM_DEVICE_DFP2_SUPPORT: 1228 if ((info.chipsetID == RADEON_RS600) 1229 || (info.chipsetID == RADEON_RS690) 1230 || (info.chipsetID == RADEON_RS740)) 1231 ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 1232 else if (info.chipsetID >= RADEON_RS600) 1233 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 1234 else 1235 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1236 break; 1237 case ATOM_DEVICE_DFP3_SUPPORT: 1238 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 1239 break; 1240 } 1241 1242 return ret; 1243 } 1244 1245 1246 uint32 1247 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags) 1248 { 1249 switch(encoderID) { 1250 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1251 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1252 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1253 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1254 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1255 return VIDEO_ENCODER_LVDS; 1256 else 1257 return VIDEO_ENCODER_TMDS; 1258 break; 1259 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1260 return VIDEO_ENCODER_DAC; 1261 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1262 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1263 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1264 return VIDEO_ENCODER_TVDAC; 1265 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1266 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1267 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1268 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1269 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1270 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1271 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1272 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1273 return VIDEO_ENCODER_LVDS; 1274 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1275 return VIDEO_ENCODER_DAC; 1276 else 1277 return VIDEO_ENCODER_TMDS; 1278 break; 1279 case ENCODER_OBJECT_ID_SI170B: 1280 case ENCODER_OBJECT_ID_CH7303: 1281 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 1282 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 1283 case ENCODER_OBJECT_ID_TITFP513: 1284 case ENCODER_OBJECT_ID_VT1623: 1285 case ENCODER_OBJECT_ID_HDMI_SI1930: 1286 case ENCODER_OBJECT_ID_TRAVIS: 1287 case ENCODER_OBJECT_ID_NUTMEG: 1288 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1289 return VIDEO_ENCODER_LVDS; 1290 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1291 return VIDEO_ENCODER_DAC; 1292 else 1293 return VIDEO_ENCODER_TMDS; 1294 break; 1295 } 1296 1297 return VIDEO_ENCODER_NONE; 1298 } 1299 1300 1301 bool 1302 encoder_is_external(uint32 encoderID) 1303 { 1304 switch (encoderID) { 1305 case ENCODER_OBJECT_ID_SI170B: 1306 case ENCODER_OBJECT_ID_CH7303: 1307 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 1308 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 1309 case ENCODER_OBJECT_ID_TITFP513: 1310 case ENCODER_OBJECT_ID_VT1623: 1311 case ENCODER_OBJECT_ID_HDMI_SI1930: 1312 case ENCODER_OBJECT_ID_TRAVIS: 1313 case ENCODER_OBJECT_ID_NUTMEG: 1314 return true; 1315 } 1316 1317 return false; 1318 } 1319 1320 1321 bool 1322 encoder_is_dp_bridge(uint32 encoderID) { 1323 switch (encoderID) { 1324 case ENCODER_OBJECT_ID_TRAVIS: 1325 case ENCODER_OBJECT_ID_NUTMEG: 1326 return true; 1327 } 1328 return false; 1329 } 1330 1331 1332 uint32 1333 encoder_get_dp_link_clock(uint32 connectorIndex) { 1334 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1335 1336 if (encoderID == ENCODER_OBJECT_ID_NUTMEG) 1337 return 270000; 1338 1339 // TODO: calculate DisplayPort max pixel clock based on bpp and DP channels 1340 return 162000; 1341 } 1342