1 /* 2 * Copyright 2006-2012, 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 "encoder.h" 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <math.h> 16 17 #include "accelerant.h" 18 #include "accelerant_protos.h" 19 #include "atombios-obsolete.h" 20 #include "bios.h" 21 #include "connector.h" 22 #include "display.h" 23 #include "displayport.h" 24 #include "utility.h" 25 26 27 #define TRACE_ENCODER 28 #ifdef TRACE_ENCODER 29 extern "C" void _sPrintf(const char* format, ...); 30 # define TRACE(x...) _sPrintf("radeon_hd: " x) 31 #else 32 # define TRACE(x...) ; 33 #endif 34 35 #define ERROR(x...) _sPrintf("radeon_hd: " x) 36 37 38 void 39 encoder_init() 40 { 41 TRACE("%s: called\n", __func__); 42 radeon_shared_info &info = *gInfo->shared_info; 43 44 for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) { 45 if (gConnector[id]->valid == false) 46 continue; 47 48 switch (gConnector[id]->encoder.objectID) { 49 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 50 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 51 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 52 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 53 transmitter_dig_setup(id, 0, 0, 0, 54 ATOM_TRANSMITTER_ACTION_INIT); 55 break; 56 default: 57 break; 58 } 59 60 if ((info.chipsetFlags & CHIP_APU) != 0) { 61 if (gConnector[id]->encoderExternal.valid == true) { 62 encoder_external_setup(id, 63 EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); 64 } 65 } 66 } 67 } 68 69 70 void 71 encoder_assign_crtc(uint8 crtcID) 72 { 73 TRACE("%s\n", __func__); 74 75 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 76 77 // Table version 78 uint8 tableMajor; 79 uint8 tableMinor; 80 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 81 != B_OK) 82 return; 83 84 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 85 tableMajor, tableMinor); 86 87 uint16 connectorIndex = gDisplay[crtcID]->connectorIndex; 88 uint16 connectorFlags = gConnector[connectorIndex]->flags; 89 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 90 91 // Prepare AtomBIOS command arguments 92 union crtcSourceParam { 93 SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 94 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 95 }; 96 union crtcSourceParam args; 97 memset(&args, 0, sizeof(args)); 98 99 switch (tableMajor) { 100 case 1: 101 switch (tableMinor) { 102 case 1: 103 default: 104 args.v1.ucCRTC = crtcID; 105 switch (encoderID) { 106 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 107 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 108 args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 109 break; 110 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 111 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 112 if ((gConnector[connectorIndex]->flags 113 & ATOM_DEVICE_LCD1_SUPPORT) != 0) 114 args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 115 else 116 args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 117 break; 118 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 119 case ENCODER_OBJECT_ID_INTERNAL_DDI: 120 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 121 args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 122 break; 123 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 124 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 125 if ((connectorFlags 126 & ATOM_DEVICE_TV_SUPPORT) != 0) { 127 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 128 } else if ((connectorFlags 129 & ATOM_DEVICE_CV_SUPPORT) != 0) { 130 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 131 } else 132 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 133 break; 134 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 135 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 136 if ((connectorFlags 137 & ATOM_DEVICE_TV_SUPPORT) != 0) { 138 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 139 } else if ((connectorFlags 140 & ATOM_DEVICE_CV_SUPPORT) != 0) { 141 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 142 } else 143 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 144 break; 145 } 146 break; 147 case 2: 148 args.v2.ucCRTC = crtcID; 149 args.v2.ucEncodeMode 150 = display_get_encoder_mode(connectorIndex); 151 switch (encoderID) { 152 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 153 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 154 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 155 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 156 switch (encoder_pick_dig(connectorIndex)) { 157 case 0: 158 args.v2.ucEncoderID 159 = ASIC_INT_DIG1_ENCODER_ID; 160 break; 161 case 1: 162 args.v2.ucEncoderID 163 = ASIC_INT_DIG2_ENCODER_ID; 164 break; 165 case 2: 166 args.v2.ucEncoderID 167 = ASIC_INT_DIG3_ENCODER_ID; 168 break; 169 case 3: 170 args.v2.ucEncoderID 171 = ASIC_INT_DIG4_ENCODER_ID; 172 break; 173 case 4: 174 args.v2.ucEncoderID 175 = ASIC_INT_DIG5_ENCODER_ID; 176 break; 177 case 5: 178 args.v2.ucEncoderID 179 = ASIC_INT_DIG6_ENCODER_ID; 180 break; 181 } 182 break; 183 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 184 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 185 break; 186 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 187 if ((connectorFlags 188 & ATOM_DEVICE_TV_SUPPORT) != 0) { 189 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 190 } else if ((connectorFlags 191 & ATOM_DEVICE_CV_SUPPORT) != 0) { 192 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 193 } else 194 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 195 break; 196 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 197 if ((connectorFlags 198 & ATOM_DEVICE_TV_SUPPORT) != 0) { 199 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 200 } else if ((connectorFlags 201 & ATOM_DEVICE_CV_SUPPORT) != 0) { 202 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 203 } else 204 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 205 break; 206 } 207 break; 208 } 209 break; 210 default: 211 ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 212 __func__, tableMajor, tableMinor); 213 return; 214 } 215 216 atom_execute_table(gAtomContext, index, (uint32*)&args); 217 218 // update crtc encoder scratch register @ scratch 3 219 encoder_crtc_scratch(crtcID); 220 } 221 222 223 uint32 224 encoder_pick_dig(uint32 connectorIndex) 225 { 226 TRACE("%s\n", __func__); 227 radeon_shared_info &info = *gInfo->shared_info; 228 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 229 230 // obtain assigned CRT 231 uint32 crtcID; 232 for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) { 233 if (gDisplay[crtcID]->attached != true) 234 continue; 235 if (gDisplay[crtcID]->connectorIndex == connectorIndex) 236 break; 237 } 238 239 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration 240 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 241 242 uint32 dceVersion = (info.dceMajor * 100) + info.dceMinor; 243 244 if (dceVersion >= 400) { 245 // APU 246 switch (info.chipsetID) { 247 case RADEON_PALM: 248 return linkB ? 1 : 0; 249 case RADEON_SUMO: 250 case RADEON_SUMO2: 251 return crtcID; 252 } 253 254 switch (encoderID) { 255 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 256 return linkB ? 1 : 0; 257 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 258 return linkB ? 3 : 2; 259 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 260 return linkB ? 5 : 4; 261 } 262 } 263 264 if (dceVersion >= 302) 265 return crtcID; 266 267 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) 268 return 1; 269 270 return 0; 271 } 272 273 274 void 275 encoder_apply_quirks(uint8 crtcID) 276 { 277 TRACE("%s\n", __func__); 278 radeon_shared_info &info = *gInfo->shared_info; 279 register_info* regs = gDisplay[crtcID]->regs; 280 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 281 uint16 connectorFlags = gConnector[connectorIndex]->flags; 282 283 // Setting the scaler clears this on some chips... 284 if (info.dceMajor >= 3 285 && (connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0) { 286 // TODO: assume non interleave mode for now 287 // en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN 288 Write32(OUT, regs->modeDataFormat, 0); 289 } 290 } 291 292 293 void 294 encoder_mode_set(uint8 crtcID) 295 { 296 TRACE("%s\n", __func__); 297 radeon_shared_info &info = *gInfo->shared_info; 298 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 299 uint16 connectorFlags = gConnector[connectorIndex]->flags; 300 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 301 302 // TODO: Should this be the adjusted pll or the original? 303 uint32 pixelClock = pll->pixelClock; 304 305 switch (gConnector[connectorIndex]->encoder.objectID) { 306 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 307 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 308 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 309 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 310 encoder_analog_setup(connectorIndex, pixelClock, ATOM_ENABLE); 311 if (info.dceMajor < 5) { 312 // TV encoder was dropped in DCE 5 313 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0 314 || (connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 315 encoder_tv_setup(connectorIndex, pixelClock, ATOM_ENABLE); 316 } else { 317 encoder_tv_setup(connectorIndex, pixelClock, ATOM_DISABLE); 318 } 319 } 320 break; 321 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 322 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 323 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 324 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 325 encoder_digital_setup(connectorIndex, pixelClock, 326 PANEL_ENCODER_ACTION_ENABLE); 327 break; 328 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 329 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 330 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 331 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 332 if ((info.chipsetFlags & CHIP_APU) != 0 333 || info.dceMajor >= 5) { 334 // Setup DIG encoder 335 encoder_dig_setup(connectorIndex, pixelClock, 336 ATOM_ENCODER_CMD_SETUP); 337 encoder_dig_setup(connectorIndex, pixelClock, 338 ATOM_ENCODER_CMD_SETUP_PANEL_MODE); 339 } else if (info.dceMajor >= 4) { 340 // Disable DIG transmitter 341 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 342 ATOM_TRANSMITTER_ACTION_DISABLE); 343 // Setup DIG encoder 344 encoder_dig_setup(connectorIndex, pixelClock, 345 ATOM_ENCODER_CMD_SETUP); 346 // Enable DIG transmitter 347 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 348 ATOM_TRANSMITTER_ACTION_ENABLE); 349 } else { 350 // Disable DIG transmitter 351 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 352 ATOM_TRANSMITTER_ACTION_DISABLE); 353 // Disable DIG encoder 354 encoder_dig_setup(connectorIndex, pixelClock, ATOM_DISABLE); 355 // Enable the DIG encoder 356 encoder_dig_setup(connectorIndex, pixelClock, ATOM_ENABLE); 357 358 // Setup and enable DIG transmitter 359 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 360 ATOM_TRANSMITTER_ACTION_SETUP); 361 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 362 ATOM_TRANSMITTER_ACTION_ENABLE); 363 } 364 break; 365 case ENCODER_OBJECT_ID_INTERNAL_DDI: 366 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 367 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 368 TRACE("%s: TODO for DVO encoder setup\n", __func__); 369 break; 370 } 371 372 if (gConnector[connectorIndex]->encoderExternal.valid == true) { 373 if ((info.chipsetFlags & CHIP_APU) != 0) { 374 // aka DCE 4.1 375 encoder_external_setup(connectorIndex, 376 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 377 } else 378 encoder_external_setup(connectorIndex, ATOM_ENABLE); 379 380 } 381 382 encoder_apply_quirks(crtcID); 383 } 384 385 386 status_t 387 encoder_tv_setup(uint32 connectorIndex, uint32 pixelClock, int command) 388 { 389 uint16 connectorFlags = gConnector[connectorIndex]->flags; 390 391 TV_ENCODER_CONTROL_PS_ALLOCATION args; 392 memset(&args, 0, sizeof(args)); 393 394 int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 395 396 args.sTVEncoder.ucAction = command; 397 398 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 399 args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 400 else { 401 // TODO: we assume NTSC for now 402 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 403 } 404 405 args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 406 407 return atom_execute_table(gAtomContext, index, (uint32*)&args); 408 } 409 410 411 status_t 412 encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command) 413 { 414 TRACE("%s\n", __func__); 415 416 int index = 0; 417 uint16 connectorFlags = gConnector[connectorIndex]->flags; 418 419 switch (gConnector[connectorIndex]->encoder.objectID) { 420 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 421 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 422 break; 423 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 424 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 425 index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 426 break; 427 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 428 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 429 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 430 else 431 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 432 break; 433 } 434 435 // Table verson 436 uint8 tableMajor; 437 uint8 tableMinor; 438 439 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 440 != B_OK) { 441 ERROR("%s: cannot parse command table\n", __func__); 442 return B_ERROR; 443 } 444 445 uint32 lvdsFlags = gConnector[connectorIndex]->lvdsFlags; 446 447 bool isHdmi = false; 448 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIA 449 || gConnector[connectorIndex]->type == VIDEO_CONNECTOR_HDMIB) { 450 isHdmi = true; 451 } 452 453 // Prepare AtomBIOS command arguments 454 union lvdsEncoderControl { 455 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 456 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 457 }; 458 union lvdsEncoderControl args; 459 memset(&args, 0, sizeof(args)); 460 461 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 462 tableMajor, tableMinor); 463 464 switch (tableMajor) { 465 case 1: 466 case 2: 467 switch (tableMinor) { 468 case 1: 469 args.v1.ucMisc = 0; 470 args.v1.ucAction = command; 471 if (isHdmi) 472 args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 473 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 474 475 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 476 if ((lvdsFlags & ATOM_PANEL_MISC_DUAL) != 0) 477 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 478 if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) 479 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 480 } else { 481 //if (dig->linkb) 482 // args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 483 if (pixelClock > 165000) 484 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 485 /*if (pScrn->rgbBits == 8) */ 486 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 487 } 488 break; 489 case 2: 490 case 3: 491 args.v2.ucMisc = 0; 492 args.v2.ucAction = command; 493 if (tableMinor == 3) { 494 //if (dig->coherent_mode) 495 // args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 496 } 497 if (isHdmi) 498 args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 499 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 500 args.v2.ucTruncate = 0; 501 args.v2.ucSpatial = 0; 502 args.v2.ucTemporal = 0; 503 args.v2.ucFRC = 0; 504 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 505 if ((lvdsFlags & ATOM_PANEL_MISC_DUAL) != 0) 506 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 507 if ((lvdsFlags & ATOM_PANEL_MISC_SPATIAL) != 0) { 508 args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 509 if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) { 510 args.v2.ucSpatial 511 |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 512 } 513 } 514 515 if ((lvdsFlags & ATOM_PANEL_MISC_TEMPORAL) != 0) { 516 args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 517 if ((lvdsFlags & ATOM_PANEL_MISC_888RGB) != 0) { 518 args.v2.ucTemporal 519 |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 520 } 521 if (((lvdsFlags >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) 522 & 0x3) == 2) { 523 args.v2.ucTemporal 524 |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 525 } 526 } 527 } else { 528 //if (dig->linkb) 529 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 530 if (pixelClock > 165000) 531 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 532 } 533 break; 534 default: 535 ERROR("%s: Unknown minor table version: %" 536 B_PRIu8 ".%" B_PRIu8 "\n", __func__, 537 tableMajor, tableMinor); 538 return B_ERROR; 539 } 540 break; 541 default: 542 ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 543 __func__, tableMajor, tableMinor); 544 return B_ERROR; 545 } 546 return atom_execute_table(gAtomContext, index, (uint32*)&args); 547 } 548 549 550 static uint32 551 encoder_get_bpc() 552 { 553 /* 554 switch (8) { 555 case 0: 556 return PANEL_BPC_UNDEFINE; 557 case 6: 558 return PANEL_6BIT_PER_COLOR; 559 case 8: 560 return PANEL_8BIT_PER_COLOR; 561 case 10: 562 return PANEL_10BIT_PER_COLOR; 563 case 12: 564 return PANEL_12BIT_PER_COLOR; 565 case 16: 566 return PANEL_16BIT_PER_COLOR; 567 } 568 */ 569 return PANEL_8BIT_PER_COLOR; 570 } 571 572 573 status_t 574 encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command) 575 { 576 radeon_shared_info &info = *gInfo->shared_info; 577 connector_info* connector = gConnector[connectorIndex]; 578 579 int index = 0; 580 if (info.dceMajor >= 4) 581 index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 582 else { 583 if (encoder_pick_dig(connectorIndex)) 584 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 585 else 586 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 587 } 588 589 // Table verson 590 uint8 tableMajor; 591 uint8 tableMinor; 592 593 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 594 != B_OK) { 595 ERROR("%s: cannot parse command table\n", __func__); 596 return B_ERROR; 597 } 598 599 // Prepare AtomBIOS command arguments 600 union digEncoderControl { 601 DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 602 DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 603 DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 604 DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 605 DIG_ENCODER_CONTROL_PARAMETERS_V5 v5; 606 }; 607 union digEncoderControl args; 608 memset(&args, 0, sizeof(args)); 609 610 bool isDPBridge = connector->encoderExternal.isDPBridge; 611 bool linkB = connector->encoder.linkEnumeration 612 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 613 uint32 digEncoderID = encoder_pick_dig(connectorIndex); 614 615 uint32 panelMode = 0; 616 // determine DP panel mode if doing panel mode setup 617 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) { 618 if (info.dceMajor >= 4 && isDPBridge) { 619 if (connector->encoderExternal.objectID == ENCODER_OBJECT_ID_NUTMEG) 620 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 621 else if (connector->encoderExternal.objectID 622 == ENCODER_OBJECT_ID_TRAVIS) { 623 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 624 uint8 id[6]; 625 int bit; 626 for (bit = 0; bit < 6; bit++) 627 id[bit] = dpcd_reg_read(dp->auxPin, 0x503 + bit); 628 if (id[0] == 0x73 && id[1] == 0x69 && id[2] == 0x76 629 && id[3] == 0x61 && id[4] == 0x72 && id[5] == 0x54) { 630 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 631 } else { 632 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 633 } 634 } else { 635 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 636 } 637 } else 638 panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 639 } 640 641 #if 0 642 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 643 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) { 644 uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP); 645 if ((temp & 1) != 0) 646 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 647 } 648 #endif 649 650 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 651 tableMajor, tableMinor); 652 653 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 654 uint32 dpClock = 0; 655 if (dpInfo->valid == true) 656 dpClock = dpInfo->linkRate; 657 658 bool dualLink = false; 659 if (connector->type == VIDEO_CONNECTOR_DVID 660 && pixelClock > 165000) { 661 // TODO: Expand on this duallink code 662 dualLink = true; 663 } 664 665 uint32 encoderMode = display_get_encoder_mode(connectorIndex); 666 667 // Careful! The mapping of ucHPD_ID differs between atombios calls 668 uint16 hpdID = connector_pick_atom_hpdid(connectorIndex); 669 670 if (tableMajor != 1) { 671 ERROR("%s: Unknown table major!\n", __func__); 672 } 673 674 switch (tableMinor) { 675 case 1: 676 args.v1.ucAction = command; 677 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 678 679 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 680 args.v3.ucPanelMode = panelMode; 681 else { 682 args.v1.ucEncoderMode = encoderMode; 683 } 684 685 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 686 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 687 args.v1.ucLaneNum = dpInfo->laneCount; 688 } else if (dualLink) 689 args.v1.ucLaneNum = 8; 690 else 691 args.v1.ucLaneNum = 4; 692 693 if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 694 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) 695 && dpClock == 270000) { 696 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 697 } 698 699 switch (connector->encoder.objectID) { 700 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 701 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 702 break; 703 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 704 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 705 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 706 break; 707 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 708 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 709 break; 710 } 711 712 if (linkB) 713 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 714 else 715 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 716 break; 717 case 2: 718 case 3: 719 args.v3.ucAction = command; 720 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 721 722 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 723 args.v3.ucPanelMode = panelMode; 724 else 725 args.v3.ucEncoderMode = encoderMode; 726 727 if (args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP 728 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 729 args.v3.ucLaneNum = dpInfo->laneCount; 730 } else if (dualLink) 731 args.v3.ucLaneNum = 8; 732 else 733 args.v3.ucLaneNum = 4; 734 735 if ((args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP 736 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) 737 && dpClock == 270000) { 738 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 739 } 740 741 args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex); 742 args.v3.ucBitPerColor = encoder_get_bpc(); 743 break; 744 case 4: 745 args.v4.ucAction = command; 746 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 747 748 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 749 args.v4.ucPanelMode = panelMode; 750 else 751 args.v4.ucEncoderMode = encoderMode; 752 753 if (args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP 754 || args.v4.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 755 // Is DP? 756 args.v4.ucLaneNum = dpInfo->laneCount; 757 if (dpClock == 270000) { 758 args.v4.ucConfig 759 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; 760 } else if (dpClock == 540000) { 761 args.v4.ucConfig 762 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; 763 } 764 } else if (dualLink) { 765 // DualLink, double the lane numbers 766 args.v4.ucLaneNum = 8; 767 } else { 768 args.v4.ucLaneNum = 4; 769 } 770 args.v4.acConfig.ucDigSel = digEncoderID; 771 args.v4.ucBitPerColor = encoder_get_bpc(); 772 773 if (hpdID == 0xff) 774 args.v4.ucHPD_ID = 0; 775 else 776 args.v4.ucHPD_ID = hpdID + 1; 777 break; 778 case 5: 779 switch(command) { 780 case ATOM_ENCODER_CMD_SETUP_PANEL_MODE: 781 args.v5.asDPPanelModeParam.ucAction = command; 782 args.v5.asDPPanelModeParam.ucPanelMode = panelMode; 783 args.v5.asDPPanelModeParam.ucDigId = digEncoderID; 784 break; 785 case ATOM_ENCODER_CMD_STREAM_SETUP: 786 args.v5.asStreamParam.ucAction = command; 787 args.v5.asStreamParam.ucDigId = digEncoderID; 788 args.v5.asStreamParam.ucDigMode = encoderMode; 789 if (encoderMode == ATOM_ENCODER_MODE_DP 790 || encoderMode == ATOM_ENCODER_MODE_DP_MST) { 791 args.v5.asStreamParam.ucLaneNum = dpInfo->laneCount; 792 } else if (dualLink) 793 args.v5.asStreamParam.ucLaneNum = 8; 794 else 795 args.v5.asStreamParam.ucLaneNum = 4; 796 args.v5.asStreamParam.ulPixelClock 797 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 798 args.v5.asStreamParam.ucBitPerColor = encoder_get_bpc(); 799 args.v5.asStreamParam.ucLinkRateIn270Mhz = dpClock / 27000; 800 break; 801 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_START: 802 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1: 803 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2: 804 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3: 805 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN4: 806 case ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE: 807 case ATOM_ENCODER_CMD_DP_VIDEO_OFF: 808 case ATOM_ENCODER_CMD_DP_VIDEO_ON: 809 args.v5.asCmdParam.ucAction = command; 810 args.v5.asCmdParam.ucDigId = digEncoderID; 811 break; 812 default: 813 ERROR("%s: Unknown command: 0x%X\n", __func__, command); 814 } 815 break; 816 default: 817 ERROR("%s: unknown tableMinor!\n", __func__); 818 return B_ERROR; 819 } 820 821 status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args); 822 823 #if 0 824 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP 825 && panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) { 826 dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1); 827 } 828 #endif 829 830 return result; 831 } 832 833 834 status_t 835 encoder_external_setup(uint32 connectorIndex, int command) 836 { 837 TRACE("%s\n", __func__); 838 839 encoder_info* encoder 840 = &gConnector[connectorIndex]->encoder; 841 encoder_info* extEncoder 842 = &gConnector[connectorIndex]->encoderExternal; 843 uint32 connectorFlags = gConnector[connectorIndex]->flags; 844 845 dp_info* dpInfo 846 = &gConnector[connectorIndex]->dpInfo; 847 848 if (extEncoder->valid != true) { 849 ERROR("%s: connector %" B_PRIu32 " doesn't have a valid " 850 "external encoder!", __func__, connectorIndex); 851 return B_ERROR; 852 } 853 854 uint8 tableMajor; 855 uint8 tableMinor; 856 857 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 858 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 859 != B_OK) { 860 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__); 861 return B_ERROR; 862 } 863 864 // Prepare AtomBIOS command arguments 865 union externalEncoderControl { 866 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 867 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 868 }; 869 union externalEncoderControl args; 870 memset(&args, 0, sizeof(args)); 871 872 int connectorObjectID 873 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 874 >> OBJECT_ID_SHIFT; 875 876 uint32 pixelClock = encoder->pll.pixelClock; 877 878 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 879 tableMajor, tableMinor); 880 switch (tableMajor) { 881 case 1: 882 // no options needed on table 1.x 883 break; 884 case 2: 885 switch (tableMinor) { 886 case 1: 887 case 2: 888 args.v1.sDigEncoder.ucAction = command; 889 args.v1.sDigEncoder.usPixelClock 890 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 891 args.v1.sDigEncoder.ucEncoderMode 892 = display_get_encoder_mode(connectorIndex); 893 894 if (connector_is_dp(connectorIndex)) { 895 if (dpInfo->linkRate == 270000) { 896 args.v1.sDigEncoder.ucConfig 897 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 898 } 899 args.v1.sDigEncoder.ucLaneNum 900 = dpInfo->laneCount; 901 } else if (pixelClock > 165000) { 902 args.v1.sDigEncoder.ucLaneNum = 8; 903 } else { 904 args.v1.sDigEncoder.ucLaneNum = 4; 905 } 906 break; 907 case 3: 908 { 909 args.v3.sExtEncoder.ucAction = command; 910 if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) { 911 args.v3.sExtEncoder.usConnectorId 912 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 913 } else { 914 args.v3.sExtEncoder.usPixelClock 915 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 916 } 917 918 args.v3.sExtEncoder.ucEncoderMode 919 = display_get_encoder_mode(connectorIndex); 920 921 if (connector_is_dp(connectorIndex)) { 922 if (dpInfo->linkRate == 270000) { 923 args.v3.sExtEncoder.ucConfig 924 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 925 } else if (dpInfo->linkRate == 540000) { 926 args.v3.sExtEncoder.ucConfig 927 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 928 } 929 args.v1.sDigEncoder.ucLaneNum 930 = dpInfo->laneCount; 931 } else if (pixelClock > 165000) { 932 args.v3.sExtEncoder.ucLaneNum = 8; 933 } else { 934 args.v3.sExtEncoder.ucLaneNum = 4; 935 } 936 937 switch ((connectorFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) { 938 case GRAPH_OBJECT_ENUM_ID1: 939 TRACE("%s: external encoder 1\n", __func__); 940 args.v3.sExtEncoder.ucConfig 941 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 942 break; 943 case GRAPH_OBJECT_ENUM_ID2: 944 TRACE("%s: external encoder 2\n", __func__); 945 args.v3.sExtEncoder.ucConfig 946 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 947 break; 948 case GRAPH_OBJECT_ENUM_ID3: 949 TRACE("%s: external encoder 3\n", __func__); 950 args.v3.sExtEncoder.ucConfig 951 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 952 break; 953 } 954 955 // TODO: don't set statically 956 uint32 bitsPerColor = 8; 957 switch (bitsPerColor) { 958 case 0: 959 args.v3.sExtEncoder.ucBitPerColor 960 = PANEL_BPC_UNDEFINE; 961 break; 962 case 6: 963 args.v3.sExtEncoder.ucBitPerColor 964 = PANEL_6BIT_PER_COLOR; 965 break; 966 case 8: 967 default: 968 args.v3.sExtEncoder.ucBitPerColor 969 = PANEL_8BIT_PER_COLOR; 970 break; 971 case 10: 972 args.v3.sExtEncoder.ucBitPerColor 973 = PANEL_10BIT_PER_COLOR; 974 break; 975 case 12: 976 args.v3.sExtEncoder.ucBitPerColor 977 = PANEL_12BIT_PER_COLOR; 978 break; 979 case 16: 980 args.v3.sExtEncoder.ucBitPerColor 981 = PANEL_16BIT_PER_COLOR; 982 break; 983 } 984 break; 985 } 986 default: 987 ERROR("%s: Unknown table minor version: " 988 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 989 tableMajor, tableMinor); 990 return B_ERROR; 991 } 992 break; 993 default: 994 ERROR("%s: Unknown table major version: " 995 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 996 tableMajor, tableMinor); 997 return B_ERROR; 998 } 999 1000 return atom_execute_table(gAtomContext, index, (uint32*)&args); 1001 } 1002 1003 1004 status_t 1005 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command) 1006 { 1007 TRACE("%s\n", __func__); 1008 1009 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1010 1011 int index = 0; 1012 DAC_ENCODER_CONTROL_PS_ALLOCATION args; 1013 memset(&args, 0, sizeof(args)); 1014 1015 switch (gConnector[connectorIndex]->encoder.objectID) { 1016 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1017 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1018 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 1019 break; 1020 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1021 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1022 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 1023 break; 1024 } 1025 1026 args.ucAction = command; 1027 1028 if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1029 args.ucDacStandard = ATOM_DAC1_PS2; 1030 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1031 args.ucDacStandard = ATOM_DAC1_CV; 1032 else { 1033 TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__); 1034 if (1) { 1035 // NTSC, NTSC_J, PAL 60 1036 args.ucDacStandard = ATOM_DAC1_NTSC; 1037 } else { 1038 // PAL, SCART. SECAM, PAL_CN 1039 args.ucDacStandard = ATOM_DAC1_PAL; 1040 } 1041 } 1042 1043 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1044 1045 return atom_execute_table(gAtomContext, index, (uint32*)&args); 1046 } 1047 1048 1049 bool 1050 encoder_analog_load_detect(uint32 connectorIndex) 1051 { 1052 TRACE("%s\n", __func__); 1053 1054 if (gConnector[connectorIndex]->encoderExternal.valid == true) 1055 return encoder_dig_load_detect(connectorIndex); 1056 1057 return encoder_dac_load_detect(connectorIndex); 1058 } 1059 1060 1061 bool 1062 encoder_dac_load_detect(uint32 connectorIndex) 1063 { 1064 TRACE("%s\n", __func__); 1065 1066 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1067 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 1068 1069 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) == 0 1070 && (connectorFlags & ATOM_DEVICE_CV_SUPPORT) == 0 1071 && (connectorFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) { 1072 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n", 1073 __func__, connectorIndex); 1074 return false; 1075 } 1076 1077 // *** tell the card we want to do a DAC detection 1078 1079 DAC_LOAD_DETECTION_PS_ALLOCATION args; 1080 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 1081 uint8 tableMajor; 1082 uint8 tableMinor; 1083 1084 memset(&args, 0, sizeof(args)); 1085 1086 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 1087 != B_OK) { 1088 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n", 1089 __func__); 1090 return false; 1091 } 1092 1093 args.sDacload.ucMisc = 0; 1094 1095 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1 1096 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) { 1097 args.sDacload.ucDacType = ATOM_DAC_A; 1098 } else { 1099 args.sDacload.ucDacType = ATOM_DAC_B; 1100 } 1101 1102 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1103 args.sDacload.usDeviceID 1104 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT); 1105 atom_execute_table(gAtomContext, index, (uint32*)&args); 1106 1107 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1108 1109 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 1110 return true; 1111 1112 } else if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1113 args.sDacload.usDeviceID 1114 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT); 1115 atom_execute_table(gAtomContext, index, (uint32*)&args); 1116 1117 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1118 1119 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 1120 return true; 1121 1122 } else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1123 args.sDacload.usDeviceID 1124 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT); 1125 if (tableMinor >= 3) 1126 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1127 atom_execute_table(gAtomContext, index, (uint32*)&args); 1128 1129 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1130 1131 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 1132 return true; 1133 1134 } else if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1135 args.sDacload.usDeviceID 1136 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT); 1137 if (tableMinor >= 3) 1138 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1139 atom_execute_table(gAtomContext, index, (uint32*)&args); 1140 1141 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1142 1143 if ((biosScratch0 1144 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) { 1145 return true; /* Composite connected */ 1146 } else if ((biosScratch0 1147 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) { 1148 return true; /* S-Video connected */ 1149 } 1150 1151 } 1152 return false; 1153 } 1154 1155 1156 bool 1157 encoder_dig_load_detect(uint32 connectorIndex) 1158 { 1159 TRACE("%s\n", __func__); 1160 radeon_shared_info &info = *gInfo->shared_info; 1161 1162 if (info.dceMajor < 4) { 1163 ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__); 1164 return false; 1165 } 1166 1167 encoder_external_setup(connectorIndex, 1168 EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); 1169 1170 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1171 1172 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1173 1174 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) 1175 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 1176 return true; 1177 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) 1178 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 1179 return true; 1180 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1181 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 1182 return true; 1183 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1184 if ((biosScratch0 1185 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) 1186 return true; /* Composite connected */ 1187 else if ((biosScratch0 1188 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) 1189 return true; /* S-Video connected */ 1190 } 1191 1192 return false; 1193 } 1194 1195 1196 status_t 1197 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock, 1198 uint8 laneNumber, uint8 laneSet, int command) 1199 { 1200 TRACE("%s\n", __func__); 1201 1202 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1203 int index; 1204 switch (encoderID) { 1205 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1206 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1207 break; 1208 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1209 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1210 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1211 index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 1212 break; 1213 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1214 index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); 1215 break; 1216 default: 1217 ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__); 1218 return B_ERROR; 1219 } 1220 1221 if (index < 0) { 1222 ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__); 1223 return B_ERROR; 1224 } 1225 1226 uint8 tableMajor; 1227 uint8 tableMinor; 1228 1229 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 1230 != B_OK) 1231 return B_ERROR; 1232 1233 // Prepare AtomBIOS arguments 1234 union digTransmitterControl { 1235 DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 1236 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 1237 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 1238 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; 1239 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5; 1240 DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 v6; 1241 }; 1242 union digTransmitterControl args; 1243 memset(&args, 0, sizeof(args)); 1244 1245 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 1246 tableMajor, tableMinor); 1247 1248 int connectorObjectID 1249 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 1250 >> OBJECT_ID_SHIFT; 1251 uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID; 1252 uint32 digEncoderID = encoder_pick_dig(connectorIndex); 1253 1254 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 1255 1256 bool isDP = connector_is_dp(connectorIndex); 1257 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration 1258 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 1259 1260 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 1261 1262 uint32 dpClock = 0; 1263 int dpLaneCount = 0; 1264 if (dpInfo->valid == true) { 1265 dpClock = dpInfo->linkRate; 1266 dpLaneCount = dpInfo->laneCount; 1267 } 1268 1269 switch (tableMajor) { 1270 case 1: 1271 switch (tableMinor) { 1272 case 1: 1273 args.v1.ucAction = command; 1274 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1275 args.v1.usInitInfo 1276 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1277 } else if (command 1278 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1279 args.v1.asMode.ucLaneSel = laneNumber; 1280 args.v1.asMode.ucLaneSet = laneSet; 1281 } else { 1282 if (isDP) { 1283 args.v1.usPixelClock 1284 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1285 } else if (pixelClock > 165000) { 1286 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1287 (pixelClock / 2) / 10); 1288 } else { 1289 args.v1.usPixelClock 1290 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1291 } 1292 } 1293 1294 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 1295 1296 if (digEncoderID > 0) { 1297 args.v1.ucConfig 1298 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 1299 } else { 1300 args.v1.ucConfig 1301 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 1302 } 1303 1304 // TODO: IGP DIG Transmitter setup 1305 #if 0 1306 if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID 1307 == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 1308 if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { 1309 if (igp_lane_info & 0x1) 1310 args.v1.ucConfig 1311 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 1312 else if (igp_lane_info & 0x2) 1313 args.v1.ucConfig 1314 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 1315 else if (igp_lane_info & 0x4) 1316 args.v1.ucConfig 1317 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 1318 else if (igp_lane_info & 0x8) 1319 args.v1.ucConfig 1320 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 1321 } else { 1322 if (igp_lane_info & 0x3) 1323 args.v1.ucConfig 1324 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 1325 else if (igp_lane_info & 0xc) 1326 args.v1.ucConfig 1327 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 1328 } 1329 } 1330 #endif 1331 1332 if (linkB == true) 1333 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 1334 else 1335 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 1336 1337 if (isDP) 1338 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1339 else if ((gConnector[connectorIndex]->flags 1340 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1341 if (1) { 1342 // if coherentMode, i've only ever seen it true 1343 args.v1.ucConfig 1344 |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1345 } 1346 if (pixelClock > 165000) { 1347 args.v1.ucConfig 1348 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 1349 } 1350 } 1351 break; 1352 case 2: 1353 args.v2.ucAction = command; 1354 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1355 args.v2.usInitInfo 1356 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1357 } else if (command 1358 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1359 args.v2.asMode.ucLaneSel = laneNumber; 1360 args.v2.asMode.ucLaneSet = laneSet; 1361 } else { 1362 if (isDP) { 1363 args.v2.usPixelClock 1364 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1365 } else if (pixelClock > 165000) { 1366 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1367 (pixelClock / 2) / 10); 1368 } else { 1369 args.v2.usPixelClock 1370 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1371 } 1372 } 1373 args.v2.acConfig.ucEncoderSel = digEncoderID; 1374 if (linkB) 1375 args.v2.acConfig.ucLinkSel = 1; 1376 1377 switch (encoderObjectID) { 1378 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1379 args.v2.acConfig.ucTransmitterSel = 0; 1380 break; 1381 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1382 args.v2.acConfig.ucTransmitterSel = 1; 1383 break; 1384 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1385 args.v2.acConfig.ucTransmitterSel = 2; 1386 break; 1387 } 1388 1389 if (isDP) { 1390 args.v2.acConfig.fCoherentMode = 1; 1391 args.v2.acConfig.fDPConnector = 1; 1392 } else if ((gConnector[connectorIndex]->flags 1393 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1394 if (1) { 1395 // if coherentMode, i've only ever seen it true 1396 args.v2.acConfig.fCoherentMode = 1; 1397 } 1398 1399 if (pixelClock > 165000) 1400 args.v2.acConfig.fDualLinkConnector = 1; 1401 } 1402 break; 1403 case 3: 1404 args.v3.ucAction = command; 1405 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1406 args.v3.usInitInfo 1407 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1408 } else if (command 1409 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1410 args.v3.asMode.ucLaneSel = laneNumber; 1411 args.v3.asMode.ucLaneSet = laneSet; 1412 } else { 1413 if (isDP) { 1414 args.v3.usPixelClock 1415 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1416 } else if (pixelClock > 165000) { 1417 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1418 (pixelClock / 2) / 10); 1419 } else { 1420 args.v3.usPixelClock 1421 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1422 } 1423 } 1424 1425 if (isDP) 1426 args.v3.ucLaneNum = dpLaneCount; 1427 else if (pixelClock > 165000) 1428 args.v3.ucLaneNum = 8; 1429 else 1430 args.v3.ucLaneNum = 4; 1431 1432 if (linkB == true) 1433 args.v3.acConfig.ucLinkSel = 1; 1434 if (digEncoderID & 1) 1435 args.v3.acConfig.ucEncoderSel = 1; 1436 1437 // Select the PLL for the PHY 1438 // DP PHY to be clocked from external src if possible 1439 1440 // DCE4 has external DCPLL clock for DP 1441 if (isDP && gInfo->dpExternalClock) { 1442 // use external clock source (id'ed to 2 on DCE4) 1443 args.v3.acConfig.ucRefClkSource = 2; // EXT clock 1444 } else 1445 args.v3.acConfig.ucRefClkSource = pll->id; 1446 1447 switch (encoderObjectID) { 1448 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1449 args.v3.acConfig.ucTransmitterSel = 0; 1450 break; 1451 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1452 args.v3.acConfig.ucTransmitterSel = 1; 1453 break; 1454 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1455 args.v3.acConfig.ucTransmitterSel = 2; 1456 break; 1457 } 1458 1459 if (isDP) 1460 args.v3.acConfig.fCoherentMode = 1; 1461 else if ((gConnector[connectorIndex]->flags 1462 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1463 if (1) { 1464 // if coherentMode, i've only ever seen it true 1465 args.v3.acConfig.fCoherentMode = 1; 1466 } 1467 if (pixelClock > 165000) 1468 args.v3.acConfig.fDualLinkConnector = 1; 1469 } 1470 break; 1471 case 4: 1472 args.v4.ucAction = command; 1473 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1474 args.v4.usInitInfo 1475 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1476 } else if (command 1477 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1478 args.v4.asMode.ucLaneSel = laneNumber; 1479 args.v4.asMode.ucLaneSet = laneSet; 1480 } else { 1481 if (isDP) { 1482 args.v4.usPixelClock 1483 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1484 } else if (pixelClock > 165000) { 1485 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1486 (pixelClock / 2) / 10); 1487 } else { 1488 args.v4.usPixelClock 1489 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1490 } 1491 } 1492 1493 if (isDP) 1494 args.v4.ucLaneNum = dpLaneCount; 1495 else if (pixelClock > 165000) 1496 args.v4.ucLaneNum = 8; 1497 else 1498 args.v4.ucLaneNum = 4; 1499 1500 if (linkB == true) 1501 args.v4.acConfig.ucLinkSel = 1; 1502 if (digEncoderID & 1) 1503 args.v4.acConfig.ucEncoderSel = 1; 1504 1505 // Select the PLL for the PHY 1506 // DP PHY to be clocked from external src if possible 1507 // DCE5, DCPLL usually generates the DP ref clock 1508 if (isDP) { 1509 if (gInfo->dpExternalClock > 0) { 1510 args.v4.acConfig.ucRefClkSource 1511 = ENCODER_REFCLK_SRC_EXTCLK; 1512 } else { 1513 args.v4.acConfig.ucRefClkSource 1514 = ENCODER_REFCLK_SRC_DCPLL; 1515 } 1516 } else 1517 args.v4.acConfig.ucRefClkSource = pll->id; 1518 1519 switch (encoderObjectID) { 1520 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1521 args.v4.acConfig.ucTransmitterSel = 0; 1522 break; 1523 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1524 args.v4.acConfig.ucTransmitterSel = 1; 1525 break; 1526 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1527 args.v4.acConfig.ucTransmitterSel = 2; 1528 break; 1529 } 1530 1531 if (isDP) 1532 args.v4.acConfig.fCoherentMode = 1; 1533 else if ((gConnector[connectorIndex]->flags 1534 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1535 if (1) { 1536 // if coherentMode, i've only ever seen it true 1537 args.v4.acConfig.fCoherentMode = 1; 1538 } 1539 if (pixelClock > 165000) 1540 args.v4.acConfig.fDualLinkConnector = 1; 1541 } 1542 break; 1543 case 5: 1544 args.v5.ucAction = command; 1545 1546 if (isDP) { 1547 args.v5.usSymClock 1548 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1549 } else { 1550 args.v5.usSymClock 1551 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1552 } 1553 switch (encoderObjectID) { 1554 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1555 if (linkB) 1556 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB; 1557 else 1558 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA; 1559 break; 1560 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1561 if (linkB) 1562 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD; 1563 else 1564 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC; 1565 break; 1566 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1567 if (linkB) 1568 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF; 1569 else 1570 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE; 1571 break; 1572 } 1573 if (isDP) { 1574 args.v5.ucLaneNum = dpLaneCount; 1575 } else if (pixelClock >= 165000) { 1576 args.v5.ucLaneNum = 8; 1577 } else { 1578 args.v5.ucLaneNum = 4; 1579 } 1580 1581 args.v5.ucConnObjId = connectorObjectID; 1582 args.v5.ucDigMode 1583 = display_get_encoder_mode(connectorIndex); 1584 1585 if (isDP && gInfo->dpExternalClock) { 1586 args.v5.asConfig.ucPhyClkSrcId 1587 = ENCODER_REFCLK_SRC_EXTCLK; 1588 } else { 1589 args.v5.asConfig.ucPhyClkSrcId = pll->id; 1590 } 1591 1592 if (isDP) { 1593 args.v5.asConfig.ucCoherentMode = 1; 1594 // DP always coherent 1595 } else if ((gConnector[connectorIndex]->flags 1596 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1597 // TODO: dig coherent mode? VVV 1598 args.v5.asConfig.ucCoherentMode = 1; 1599 } 1600 1601 // TODO: hpd_id, for now RADEON_HPD_NONE. 1602 args.v5.asConfig.ucHPDSel = 0; 1603 1604 args.v5.ucDigEncoderSel = 1 << digEncoderID; 1605 args.v5.ucDPLaneSet = laneSet; 1606 break; 1607 case 6: 1608 args.v6.ucAction = command; 1609 if (isDP) { 1610 args.v6.ulSymClock 1611 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1612 } else { 1613 args.v6.ulSymClock 1614 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1615 } 1616 switch (encoderObjectID) { 1617 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1618 if (linkB) 1619 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYB; 1620 else 1621 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYA; 1622 break; 1623 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1624 if (linkB) 1625 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYD; 1626 else 1627 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYC; 1628 break; 1629 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1630 if (linkB) 1631 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYF; 1632 else 1633 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYE; 1634 break; 1635 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 1636 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYG; 1637 break; 1638 } 1639 if (isDP) 1640 args.v6.ucLaneNum = dpLaneCount; 1641 else if (pixelClock > 165000) 1642 args.v6.ucLaneNum = 8; 1643 else 1644 args.v6.ucLaneNum = 4; 1645 1646 args.v6.ucConnObjId = connectorObjectID; 1647 1648 if (command == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) 1649 args.v6.ucDPLaneSet = laneSet; 1650 else { 1651 args.v6.ucDigMode 1652 = display_get_encoder_mode(connectorIndex); 1653 } 1654 // TODO: hpd_id, for now RADEON_HPD_NONE. 1655 args.v6.ucHPDSel = 0; 1656 1657 args.v6.ucDigEncoderSel = 1 << digEncoderID; 1658 break; 1659 default: 1660 ERROR("%s: unknown table version\n", __func__); 1661 } 1662 break; 1663 default: 1664 ERROR("%s: unknown table version\n", __func__); 1665 } 1666 1667 return atom_execute_table(gAtomContext, index, (uint32*)&args); 1668 } 1669 1670 1671 void 1672 encoder_crtc_scratch(uint8 crtcID) 1673 { 1674 TRACE("%s\n", __func__); 1675 1676 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1677 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1678 1679 // TODO: r500 1680 uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3); 1681 1682 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1683 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE; 1684 biosScratch3 |= (crtcID << 18); 1685 } 1686 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1687 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE; 1688 biosScratch3 |= (crtcID << 24); 1689 } 1690 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1691 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 1692 biosScratch3 |= (crtcID << 16); 1693 } 1694 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1695 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 1696 biosScratch3 |= (crtcID << 20); 1697 } 1698 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1699 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 1700 biosScratch3 |= (crtcID << 17); 1701 } 1702 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1703 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 1704 biosScratch3 |= (crtcID << 19); 1705 } 1706 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1707 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 1708 biosScratch3 |= (crtcID << 23); 1709 } 1710 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1711 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 1712 biosScratch3 |= (crtcID << 25); 1713 } 1714 1715 // TODO: r500 1716 Write32(OUT, R600_SCRATCH_REG3, biosScratch3); 1717 } 1718 1719 1720 void 1721 encoder_dpms_scratch(uint8 crtcID, bool power) 1722 { 1723 TRACE("%s\n", __func__); 1724 1725 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1726 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1727 1728 // TODO: r500 1729 uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2); 1730 1731 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1732 if (power == true) 1733 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE; 1734 else 1735 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE; 1736 } 1737 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1738 if (power == true) 1739 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE; 1740 else 1741 biosScratch2 |= ATOM_S2_CV_DPMS_STATE; 1742 } 1743 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1744 if (power == true) 1745 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE; 1746 else 1747 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE; 1748 } 1749 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1750 if (power == true) 1751 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE; 1752 else 1753 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE; 1754 } 1755 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1756 if (power == true) 1757 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE; 1758 else 1759 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE; 1760 } 1761 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1762 if (power == true) 1763 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE; 1764 else 1765 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE; 1766 } 1767 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1768 if (power == true) 1769 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE; 1770 else 1771 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE; 1772 } 1773 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1774 if (power == true) 1775 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE; 1776 else 1777 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE; 1778 } 1779 if ((connectorFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) { 1780 if (power == true) 1781 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE; 1782 else 1783 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE; 1784 } 1785 if ((connectorFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) { 1786 if (power == true) 1787 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE; 1788 else 1789 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE; 1790 } 1791 Write32(OUT, R600_SCRATCH_REG2, biosScratch2); 1792 } 1793 1794 1795 void 1796 encoder_dpms_set(uint8 crtcID, int mode) 1797 { 1798 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1799 1800 int index = -1; 1801 radeon_shared_info &info = *gInfo->shared_info; 1802 1803 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1804 memset(&args, 0, sizeof(args)); 1805 1806 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1807 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1808 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1809 1810 switch (encoderID) { 1811 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1812 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1813 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1814 break; 1815 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1816 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1817 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1818 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1819 encoder_dpms_set_dig(crtcID, mode); 1820 break; 1821 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1822 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1823 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1824 break; 1825 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1826 if (info.dceMajor >= 5) 1827 encoder_dpms_set_dvo(crtcID, mode); 1828 else if (info.dceMajor >= 3) 1829 encoder_dpms_set_dig(crtcID, mode); 1830 else 1831 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1832 break; 1833 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1834 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1835 break; 1836 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1837 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1838 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1839 else 1840 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1841 break; 1842 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1843 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1844 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1845 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1846 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1847 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1848 else 1849 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1850 break; 1851 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1852 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1853 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1854 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1855 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1856 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1857 else 1858 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1859 break; 1860 // default, none on purpose 1861 } 1862 1863 // If we have an index, we need to execute a table. 1864 if (index >= 0) { 1865 switch (mode) { 1866 case B_DPMS_ON: 1867 args.ucAction = ATOM_ENABLE; 1868 break; 1869 case B_DPMS_STAND_BY: 1870 case B_DPMS_SUSPEND: 1871 case B_DPMS_OFF: 1872 args.ucAction = ATOM_DISABLE; 1873 break; 1874 } 1875 1876 atom_execute_table(gAtomContext, index, (uint32*)&args); 1877 if (info.dceMajor < 5) { 1878 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1879 args.ucAction = args.ucAction == ATOM_DISABLE 1880 ? ATOM_LCD_BLOFF : ATOM_LCD_BLON; 1881 atom_execute_table(gAtomContext, index, (uint32*)&args); 1882 } 1883 } 1884 if (info.dceMajor < 4) 1885 encoder_dpms_scratch(crtcID, true); 1886 } 1887 } 1888 1889 1890 void 1891 encoder_dpms_set_dig(uint8 crtcID, int mode) 1892 { 1893 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1894 1895 radeon_shared_info &info = *gInfo->shared_info; 1896 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1897 connector_info* connector = gConnector[connectorIndex]; 1898 uint32 connectorFlags = connector->flags; 1899 pll_info* pll = &connector->encoder.pll; 1900 bool hasExternal = connector->encoderExternal.valid; 1901 bool travisQuirk = info.dceMajor < 5 1902 && (connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0 1903 && connector->encoderExternal.objectID == ENCODER_OBJECT_ID_TRAVIS; 1904 1905 switch (mode) { 1906 case B_DPMS_ON: 1907 if ((info.dceMajor == 4 && info.dceMinor == 1) 1908 || info.dceMajor >= 5) { 1909 // Setup encoder 1910 encoder_dig_setup(connectorIndex, pll->pixelClock, 1911 ATOM_ENCODER_CMD_SETUP); 1912 encoder_dig_setup(connectorIndex, pll->pixelClock, 1913 ATOM_ENCODER_CMD_SETUP_PANEL_MODE); 1914 } else if (info.dceMajor >= 4) { 1915 // Setup encoder 1916 encoder_dig_setup(connectorIndex, pll->pixelClock, 1917 ATOM_ENCODER_CMD_SETUP); 1918 } else { 1919 // Setup encoder and transmitter 1920 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE); 1921 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1922 ATOM_TRANSMITTER_ACTION_SETUP); 1923 } 1924 1925 if (connector->type == VIDEO_CONNECTOR_EDP) { 1926 // TODO: If VIDEO_CONNECTOR_EDP, ATOM_TRANSMITTER_ACTION_POWER_ON 1927 ERROR("%s: TODO, edp_panel_power!\n", 1928 __func__); 1929 } 1930 1931 // Enable transmitter 1932 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1933 ATOM_TRANSMITTER_ACTION_ENABLE); 1934 1935 if (connector_is_dp(connectorIndex)) { 1936 if (info.dceMajor >= 4) { 1937 encoder_dig_setup(connectorIndex, pll->pixelClock, 1938 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1939 } 1940 // dp link train 1941 dp_link_train(crtcID); 1942 if (info.dceMajor >= 4) { 1943 encoder_dig_setup(connectorIndex, pll->pixelClock, 1944 ATOM_ENCODER_CMD_DP_VIDEO_ON); 1945 } 1946 // not sure what AtomBIOS table/command sets this 1947 // register, but it's required to get the video output 1948 Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201); 1949 } 1950 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1951 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1952 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON); 1953 } 1954 if (hasExternal) 1955 encoder_external_setup(connectorIndex, ATOM_ENABLE); 1956 break; 1957 case B_DPMS_STAND_BY: 1958 case B_DPMS_SUSPEND: 1959 case B_DPMS_OFF: 1960 if (connector_is_dp(connectorIndex)) { 1961 if (info.dceMajor >= 4) { 1962 encoder_dig_setup(connectorIndex, pll->pixelClock, 1963 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1964 } 1965 } 1966 if (hasExternal) 1967 encoder_external_setup(connectorIndex, ATOM_DISABLE); 1968 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1969 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1970 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF); 1971 } 1972 if (connector_is_dp(connectorIndex) && !travisQuirk) { 1973 // If not TRAVIS on < DCE 5, set_rx_power_state D3 1974 ERROR("%s: TODO: dpms off set_rx_power_state D3\n", __func__); 1975 } 1976 if (info.dceMajor >= 4) { 1977 // Disable transmitter 1978 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1979 ATOM_TRANSMITTER_ACTION_DISABLE); 1980 } else { 1981 // Disable transmitter and encoder 1982 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1983 ATOM_TRANSMITTER_ACTION_DISABLE); 1984 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE); 1985 } 1986 1987 if (connector_is_dp(connectorIndex)) { 1988 if (travisQuirk) { 1989 ERROR("%s: TODO: dpms off set_rx_power_state D3\n", 1990 __func__); 1991 } 1992 if (connector->type == VIDEO_CONNECTOR_EDP) { 1993 // TODO: ATOM_TRANSMITTER_ACTION_POWER_OFF 1994 ERROR("%s: TODO, edp_panel_power!\n", __func__); 1995 } 1996 } 1997 break; 1998 } 1999 } 2000 2001 2002 void 2003 encoder_dpms_set_dvo(uint8 crtcID, int mode) 2004 { 2005 ERROR("%s: TODO, dvo encoder dpms stub\n", __func__); 2006 } 2007 2008 2009 void 2010 encoder_output_lock(bool lock) 2011 { 2012 TRACE("%s: %s\n", __func__, lock ? "true" : "false"); 2013 uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6); 2014 2015 if (lock) { 2016 biosScratch6 |= ATOM_S6_CRITICAL_STATE; 2017 biosScratch6 &= ~ATOM_S6_ACC_MODE; 2018 } else { 2019 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE; 2020 biosScratch6 |= ATOM_S6_ACC_MODE; 2021 } 2022 2023 Write32(OUT, R600_SCRATCH_REG6, biosScratch6); 2024 } 2025 2026 static const char* encoder_name_matrix[] = { 2027 "NONE", 2028 "Internal Radeon LVDS", 2029 "Internal Radeon TMDS1", 2030 "Internal Radeon TMDS2", 2031 "Internal Radeon DAC1", 2032 "Internal Radeon DAC2 (TV)", 2033 "Internal Radeon SDVOA", 2034 "Internal Radeon SDVOB", 2035 "External 3rd party SI170B", 2036 "External 3rd party CH7303", 2037 "External 3rd party CH7301", 2038 "Internal Radeon DVO1", 2039 "External 3rd party SDVOA", 2040 "External 3rd party SDVOB", 2041 "External 3rd party TITFP513", 2042 "Internal LVTM1", 2043 "External 3rd party VT1623", 2044 "External HDMI SI1930", 2045 "Internal HDMI", 2046 "Internal Kaleidoscope TMDS1", 2047 "Internal Kaleidoscope DVO1", 2048 "Internal Kaleidoscope DAC1", 2049 "Internal Kaleidoscope DAC2", 2050 "External Kaleidoscope SI178", 2051 "MVPU FPGA", 2052 "Internal Kaleidoscope DDI", 2053 "External Kaleidoscope VT1625", 2054 "External Kaleidoscope HDMI SI1932", 2055 "External Kaleidoscope DP AN9801", 2056 "External Kaleidoscope DP DP501", 2057 "Internal Kaleidoscope UNIPHY", 2058 "Internal Kaleidoscope LVTMA", 2059 "Internal Kaleidoscope UNIPHY1", 2060 "Internal Kaleidoscope UNIPHY2", 2061 "External Nutmeg Bridge", 2062 "External Travis Bridge", 2063 "Internal Kaleidoscope VCE" 2064 }; 2065 2066 2067 const char* 2068 encoder_name_lookup(uint32 encoderID) { 2069 if (encoderID < B_COUNT_OF(encoder_name_matrix)) 2070 return encoder_name_matrix[encoderID]; 2071 else 2072 return "Unknown"; 2073 } 2074 2075 2076 uint32 2077 encoder_object_lookup(uint32 connectorFlags, uint8 dacID) 2078 { 2079 // used on older cards to take a guess at the encoder 2080 // object 2081 2082 radeon_shared_info &info = *gInfo->shared_info; 2083 2084 uint32 ret = 0; 2085 2086 switch (connectorFlags) { 2087 case ATOM_DEVICE_CRT1_SUPPORT: 2088 case ATOM_DEVICE_TV1_SUPPORT: 2089 case ATOM_DEVICE_TV2_SUPPORT: 2090 case ATOM_DEVICE_CRT2_SUPPORT: 2091 case ATOM_DEVICE_CV_SUPPORT: 2092 switch (dacID) { 2093 case 1: 2094 if ((info.chipsetID == RADEON_RS400) 2095 || (info.chipsetID == RADEON_RS480)) 2096 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 2097 else if (info.chipsetID >= RADEON_RS600) 2098 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 2099 else 2100 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 2101 break; 2102 case 2: 2103 if (info.chipsetID >= RADEON_RS600) 2104 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 2105 else { 2106 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 2107 } 2108 break; 2109 case 3: // external dac 2110 if (info.chipsetID >= RADEON_RS600) 2111 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 2112 else 2113 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 2114 break; 2115 } 2116 break; 2117 case ATOM_DEVICE_LCD1_SUPPORT: 2118 if (info.chipsetID >= RADEON_RS600) 2119 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 2120 else 2121 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 2122 break; 2123 case ATOM_DEVICE_DFP1_SUPPORT: 2124 if ((info.chipsetID == RADEON_RS400) 2125 || (info.chipsetID == RADEON_RS480)) 2126 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 2127 else if (info.chipsetID >= RADEON_RS600) 2128 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 2129 else 2130 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 2131 break; 2132 case ATOM_DEVICE_LCD2_SUPPORT: 2133 case ATOM_DEVICE_DFP2_SUPPORT: 2134 if ((info.chipsetID == RADEON_RS600) 2135 || (info.chipsetID == RADEON_RS690) 2136 || (info.chipsetID == RADEON_RS740)) 2137 ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 2138 else if (info.chipsetID >= RADEON_RS600) 2139 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 2140 else 2141 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 2142 break; 2143 case ATOM_DEVICE_DFP3_SUPPORT: 2144 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 2145 break; 2146 } 2147 2148 return ret; 2149 } 2150 2151 2152 uint32 2153 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags) 2154 { 2155 switch (encoderID) { 2156 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2157 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2158 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2159 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2160 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 2161 return VIDEO_ENCODER_LVDS; 2162 else 2163 return VIDEO_ENCODER_TMDS; 2164 break; 2165 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2166 return VIDEO_ENCODER_DAC; 2167 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2168 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2169 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2170 return VIDEO_ENCODER_TVDAC; 2171 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2172 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 2173 case ENCODER_OBJECT_ID_INTERNAL_DDI: 2174 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2175 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2176 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2177 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2178 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 2179 return VIDEO_ENCODER_LVDS; 2180 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 2181 return VIDEO_ENCODER_DAC; 2182 else 2183 return VIDEO_ENCODER_TMDS; 2184 break; 2185 case ENCODER_OBJECT_ID_SI170B: 2186 case ENCODER_OBJECT_ID_CH7303: 2187 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 2188 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 2189 case ENCODER_OBJECT_ID_TITFP513: 2190 case ENCODER_OBJECT_ID_VT1623: 2191 case ENCODER_OBJECT_ID_HDMI_SI1930: 2192 case ENCODER_OBJECT_ID_TRAVIS: 2193 case ENCODER_OBJECT_ID_NUTMEG: 2194 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 2195 return VIDEO_ENCODER_LVDS; 2196 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 2197 return VIDEO_ENCODER_DAC; 2198 else 2199 return VIDEO_ENCODER_TMDS; 2200 break; 2201 } 2202 2203 return VIDEO_ENCODER_NONE; 2204 } 2205 2206 2207 bool 2208 encoder_is_external(uint32 encoderID) 2209 { 2210 switch (encoderID) { 2211 case ENCODER_OBJECT_ID_SI170B: 2212 case ENCODER_OBJECT_ID_CH7303: 2213 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 2214 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 2215 case ENCODER_OBJECT_ID_TITFP513: 2216 case ENCODER_OBJECT_ID_VT1623: 2217 case ENCODER_OBJECT_ID_HDMI_SI1930: 2218 case ENCODER_OBJECT_ID_TRAVIS: 2219 case ENCODER_OBJECT_ID_NUTMEG: 2220 return true; 2221 } 2222 2223 return false; 2224 } 2225 2226 2227 bool 2228 encoder_is_dp_bridge(uint32 encoderID) 2229 { 2230 switch (encoderID) { 2231 case ENCODER_OBJECT_ID_TRAVIS: 2232 case ENCODER_OBJECT_ID_NUTMEG: 2233 return true; 2234 } 2235 return false; 2236 } 2237