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