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 bool isDP = connector_is_dp(connectorIndex); 1265 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration 1266 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 1267 1268 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 1269 1270 uint32 dpClock = 0; 1271 int dpLaneCount = 0; 1272 if (dpInfo->valid == true) { 1273 dpClock = dpInfo->linkRate; 1274 dpLaneCount = dpInfo->laneCount; 1275 } 1276 1277 switch (tableMajor) { 1278 case 1: 1279 switch (tableMinor) { 1280 case 1: 1281 args.v1.ucAction = command; 1282 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1283 args.v1.usInitInfo 1284 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1285 } else if (command 1286 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1287 args.v1.asMode.ucLaneSel = laneNumber; 1288 args.v1.asMode.ucLaneSet = laneSet; 1289 } else { 1290 if (isDP) { 1291 args.v1.usPixelClock 1292 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1293 } else if (pixelClock > 165000) { 1294 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1295 (pixelClock / 2) / 10); 1296 } else { 1297 args.v1.usPixelClock 1298 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1299 } 1300 } 1301 1302 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 1303 1304 if (digEncoderID > 0) { 1305 args.v1.ucConfig 1306 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 1307 } else { 1308 args.v1.ucConfig 1309 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 1310 } 1311 1312 // TODO: IGP DIG Transmitter setup 1313 #if 0 1314 if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID 1315 == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 1316 if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { 1317 if (igp_lane_info & 0x1) 1318 args.v1.ucConfig 1319 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 1320 else if (igp_lane_info & 0x2) 1321 args.v1.ucConfig 1322 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 1323 else if (igp_lane_info & 0x4) 1324 args.v1.ucConfig 1325 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 1326 else if (igp_lane_info & 0x8) 1327 args.v1.ucConfig 1328 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 1329 } else { 1330 if (igp_lane_info & 0x3) 1331 args.v1.ucConfig 1332 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 1333 else if (igp_lane_info & 0xc) 1334 args.v1.ucConfig 1335 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 1336 } 1337 } 1338 #endif 1339 1340 if (linkB == true) 1341 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 1342 else 1343 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 1344 1345 if (isDP) 1346 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1347 else if ((gConnector[connectorIndex]->flags 1348 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1349 if (1) { 1350 // if coherentMode, i've only ever seen it true 1351 args.v1.ucConfig 1352 |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1353 } 1354 if (pixelClock > 165000) { 1355 args.v1.ucConfig 1356 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 1357 } 1358 } 1359 break; 1360 case 2: 1361 args.v2.ucAction = command; 1362 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1363 args.v2.usInitInfo 1364 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1365 } else if (command 1366 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1367 args.v2.asMode.ucLaneSel = laneNumber; 1368 args.v2.asMode.ucLaneSet = laneSet; 1369 } else { 1370 if (isDP) { 1371 args.v2.usPixelClock 1372 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1373 } else if (pixelClock > 165000) { 1374 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1375 (pixelClock / 2) / 10); 1376 } else { 1377 args.v2.usPixelClock 1378 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1379 } 1380 } 1381 args.v2.acConfig.ucEncoderSel = digEncoderID; 1382 if (linkB) 1383 args.v2.acConfig.ucLinkSel = 1; 1384 1385 switch (encoderObjectID) { 1386 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1387 args.v2.acConfig.ucTransmitterSel = 0; 1388 break; 1389 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1390 args.v2.acConfig.ucTransmitterSel = 1; 1391 break; 1392 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1393 args.v2.acConfig.ucTransmitterSel = 2; 1394 break; 1395 } 1396 1397 if (isDP) { 1398 args.v2.acConfig.fCoherentMode = 1; 1399 args.v2.acConfig.fDPConnector = 1; 1400 } else if ((gConnector[connectorIndex]->flags 1401 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1402 if (1) { 1403 // if coherentMode, i've only ever seen it true 1404 args.v2.acConfig.fCoherentMode = 1; 1405 } 1406 1407 if (pixelClock > 165000) 1408 args.v2.acConfig.fDualLinkConnector = 1; 1409 } 1410 break; 1411 case 3: 1412 args.v3.ucAction = command; 1413 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1414 args.v3.usInitInfo 1415 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1416 } else if (command 1417 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1418 args.v3.asMode.ucLaneSel = laneNumber; 1419 args.v3.asMode.ucLaneSet = laneSet; 1420 } else { 1421 if (isDP) { 1422 args.v3.usPixelClock 1423 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1424 } else if (pixelClock > 165000) { 1425 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1426 (pixelClock / 2) / 10); 1427 } else { 1428 args.v3.usPixelClock 1429 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1430 } 1431 } 1432 1433 if (isDP) 1434 args.v3.ucLaneNum = dpLaneCount; 1435 else if (pixelClock > 165000) 1436 args.v3.ucLaneNum = 8; 1437 else 1438 args.v3.ucLaneNum = 4; 1439 1440 if (linkB == true) 1441 args.v3.acConfig.ucLinkSel = 1; 1442 if (digEncoderID & 1) 1443 args.v3.acConfig.ucEncoderSel = 1; 1444 1445 // Select the PLL for the PHY 1446 // DP PHY to be clocked from external src if possible 1447 1448 // DCE4 has external DCPLL clock for DP 1449 if (isDP && gInfo->dpExternalClock) { 1450 // use external clock source (id'ed to 2 on DCE4) 1451 args.v3.acConfig.ucRefClkSource = 2; // EXT clock 1452 } else 1453 args.v3.acConfig.ucRefClkSource = pll->id; 1454 1455 switch (encoderObjectID) { 1456 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1457 args.v3.acConfig.ucTransmitterSel = 0; 1458 break; 1459 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1460 args.v3.acConfig.ucTransmitterSel = 1; 1461 break; 1462 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1463 args.v3.acConfig.ucTransmitterSel = 2; 1464 break; 1465 } 1466 1467 if (isDP) 1468 args.v3.acConfig.fCoherentMode = 1; 1469 else if ((gConnector[connectorIndex]->flags 1470 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1471 if (1) { 1472 // if coherentMode, i've only ever seen it true 1473 args.v3.acConfig.fCoherentMode = 1; 1474 } 1475 if (pixelClock > 165000) 1476 args.v3.acConfig.fDualLinkConnector = 1; 1477 } 1478 break; 1479 case 4: 1480 args.v4.ucAction = command; 1481 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1482 args.v4.usInitInfo 1483 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1484 } else if (command 1485 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1486 args.v4.asMode.ucLaneSel = laneNumber; 1487 args.v4.asMode.ucLaneSet = laneSet; 1488 } else { 1489 if (isDP) { 1490 args.v4.usPixelClock 1491 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1492 } else if (pixelClock > 165000) { 1493 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1494 (pixelClock / 2) / 10); 1495 } else { 1496 args.v4.usPixelClock 1497 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1498 } 1499 } 1500 1501 if (isDP) 1502 args.v4.ucLaneNum = dpLaneCount; 1503 else if (pixelClock > 165000) 1504 args.v4.ucLaneNum = 8; 1505 else 1506 args.v4.ucLaneNum = 4; 1507 1508 if (linkB == true) 1509 args.v4.acConfig.ucLinkSel = 1; 1510 if (digEncoderID & 1) 1511 args.v4.acConfig.ucEncoderSel = 1; 1512 1513 // Select the PLL for the PHY 1514 // DP PHY to be clocked from external src if possible 1515 // DCE5, DCPLL usually generates the DP ref clock 1516 if (isDP) { 1517 if (gInfo->dpExternalClock > 0) { 1518 args.v4.acConfig.ucRefClkSource 1519 = ENCODER_REFCLK_SRC_EXTCLK; 1520 } else { 1521 args.v4.acConfig.ucRefClkSource 1522 = ENCODER_REFCLK_SRC_DCPLL; 1523 } 1524 } else 1525 args.v4.acConfig.ucRefClkSource = pll->id; 1526 1527 switch (encoderObjectID) { 1528 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1529 args.v4.acConfig.ucTransmitterSel = 0; 1530 break; 1531 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1532 args.v4.acConfig.ucTransmitterSel = 1; 1533 break; 1534 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1535 args.v4.acConfig.ucTransmitterSel = 2; 1536 break; 1537 } 1538 1539 if (isDP) 1540 args.v4.acConfig.fCoherentMode = 1; 1541 else if ((gConnector[connectorIndex]->flags 1542 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1543 if (1) { 1544 // if coherentMode, i've only ever seen it true 1545 args.v4.acConfig.fCoherentMode = 1; 1546 } 1547 if (pixelClock > 165000) 1548 args.v4.acConfig.fDualLinkConnector = 1; 1549 } 1550 break; 1551 case 5: 1552 args.v5.ucAction = command; 1553 1554 if (isDP) { 1555 args.v5.usSymClock 1556 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1557 } else { 1558 args.v5.usSymClock 1559 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1560 } 1561 switch (encoderObjectID) { 1562 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1563 if (linkB) 1564 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYB; 1565 else 1566 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYA; 1567 break; 1568 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1569 if (linkB) 1570 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYD; 1571 else 1572 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYC; 1573 break; 1574 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1575 if (linkB) 1576 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYF; 1577 else 1578 args.v5.ucPhyId = ATOM_PHY_ID_UNIPHYE; 1579 break; 1580 } 1581 if (isDP) { 1582 args.v5.ucLaneNum = dpLaneCount; 1583 } else if (pixelClock >= 165000) { 1584 args.v5.ucLaneNum = 8; 1585 } else { 1586 args.v5.ucLaneNum = 4; 1587 } 1588 1589 args.v5.ucConnObjId = connectorObjectID; 1590 1591 if (command != ATOM_TRANSMITTER_ACTION_INIT) { 1592 // not used on INIT and display_get_encoder_mode 1593 // unavailable until displays are probed. 1594 args.v5.ucDigMode 1595 = display_get_encoder_mode(connectorIndex); 1596 } 1597 1598 if (isDP && gInfo->dpExternalClock) { 1599 args.v5.asConfig.ucPhyClkSrcId 1600 = ENCODER_REFCLK_SRC_EXTCLK; 1601 } else { 1602 args.v5.asConfig.ucPhyClkSrcId = pll->id; 1603 } 1604 1605 if (isDP) { 1606 args.v5.asConfig.ucCoherentMode = 1; 1607 // DP always coherent 1608 } else if ((gConnector[connectorIndex]->flags 1609 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1610 // TODO: dig coherent mode? VVV 1611 args.v5.asConfig.ucCoherentMode = 1; 1612 } 1613 1614 // TODO: hpd_id, for now RADEON_HPD_NONE. 1615 args.v5.asConfig.ucHPDSel = 0; 1616 1617 args.v5.ucDigEncoderSel = 1 << digEncoderID; 1618 args.v5.ucDPLaneSet = laneSet; 1619 break; 1620 case 6: 1621 args.v6.ucAction = command; 1622 if (isDP) { 1623 args.v6.ulSymClock 1624 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1625 } else { 1626 args.v6.ulSymClock 1627 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1628 } 1629 switch (encoderObjectID) { 1630 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1631 if (linkB) 1632 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYB; 1633 else 1634 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYA; 1635 break; 1636 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1637 if (linkB) 1638 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYD; 1639 else 1640 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYC; 1641 break; 1642 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1643 if (linkB) 1644 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYF; 1645 else 1646 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYE; 1647 break; 1648 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3: 1649 args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYG; 1650 break; 1651 } 1652 if (isDP) 1653 args.v6.ucLaneNum = dpLaneCount; 1654 else if (pixelClock > 165000) 1655 args.v6.ucLaneNum = 8; 1656 else 1657 args.v6.ucLaneNum = 4; 1658 1659 args.v6.ucConnObjId = connectorObjectID; 1660 1661 if (command == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) 1662 args.v6.ucDPLaneSet = laneSet; 1663 else if (command != ATOM_TRANSMITTER_ACTION_INIT) { 1664 // not used on INIT and display_get_encoder_mode 1665 // unavailable until displays are probed. 1666 args.v6.ucDigMode 1667 = display_get_encoder_mode(connectorIndex); 1668 } 1669 // TODO: hpd_id, for now RADEON_HPD_NONE. 1670 args.v6.ucHPDSel = 0; 1671 1672 args.v6.ucDigEncoderSel = 1 << digEncoderID; 1673 break; 1674 default: 1675 ERROR("%s: unknown table version\n", __func__); 1676 } 1677 break; 1678 default: 1679 ERROR("%s: unknown table version\n", __func__); 1680 } 1681 1682 return atom_execute_table(gAtomContext, index, (uint32*)&args); 1683 } 1684 1685 1686 void 1687 encoder_crtc_scratch(uint8 crtcID) 1688 { 1689 TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID); 1690 1691 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1692 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1693 1694 // TODO: r500 1695 uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3); 1696 1697 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1698 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE; 1699 biosScratch3 |= (crtcID << 18); 1700 } 1701 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1702 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE; 1703 biosScratch3 |= (crtcID << 24); 1704 } 1705 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1706 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 1707 biosScratch3 |= (crtcID << 16); 1708 } 1709 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1710 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 1711 biosScratch3 |= (crtcID << 20); 1712 } 1713 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1714 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 1715 biosScratch3 |= (crtcID << 17); 1716 } 1717 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1718 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 1719 biosScratch3 |= (crtcID << 19); 1720 } 1721 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1722 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 1723 biosScratch3 |= (crtcID << 23); 1724 } 1725 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1726 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 1727 biosScratch3 |= (crtcID << 25); 1728 } 1729 1730 // TODO: r500 1731 Write32(OUT, R600_SCRATCH_REG3, biosScratch3); 1732 } 1733 1734 1735 void 1736 encoder_dpms_scratch(uint8 crtcID, bool power) 1737 { 1738 TRACE("%s: display %" B_PRIu8 "\n", __func__, crtcID); 1739 1740 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1741 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1742 1743 // TODO: r500 1744 uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2); 1745 1746 if ((connectorFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1747 if (power == true) 1748 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE; 1749 else 1750 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE; 1751 } 1752 if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1753 if (power == true) 1754 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE; 1755 else 1756 biosScratch2 |= ATOM_S2_CV_DPMS_STATE; 1757 } 1758 if ((connectorFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1759 if (power == true) 1760 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE; 1761 else 1762 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE; 1763 } 1764 if ((connectorFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1765 if (power == true) 1766 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE; 1767 else 1768 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE; 1769 } 1770 if ((connectorFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1771 if (power == true) 1772 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE; 1773 else 1774 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE; 1775 } 1776 if ((connectorFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1777 if (power == true) 1778 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE; 1779 else 1780 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE; 1781 } 1782 if ((connectorFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1783 if (power == true) 1784 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE; 1785 else 1786 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE; 1787 } 1788 if ((connectorFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1789 if (power == true) 1790 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE; 1791 else 1792 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE; 1793 } 1794 if ((connectorFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) { 1795 if (power == true) 1796 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE; 1797 else 1798 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE; 1799 } 1800 if ((connectorFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) { 1801 if (power == true) 1802 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE; 1803 else 1804 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE; 1805 } 1806 Write32(OUT, R600_SCRATCH_REG2, biosScratch2); 1807 } 1808 1809 1810 void 1811 encoder_dpms_set(uint8 crtcID, int mode) 1812 { 1813 TRACE("%s: display %" B_PRIu8 ", power: %s\n", __func__, crtcID, 1814 mode == B_DPMS_ON ? "true" : "false"); 1815 1816 int index = -1; 1817 radeon_shared_info &info = *gInfo->shared_info; 1818 1819 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1820 memset(&args, 0, sizeof(args)); 1821 1822 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1823 uint32 connectorFlags = gConnector[connectorIndex]->flags; 1824 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1825 1826 switch (encoderID) { 1827 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1828 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1829 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1830 break; 1831 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1832 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1833 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1834 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1835 encoder_dpms_set_dig(crtcID, mode); 1836 break; 1837 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1838 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1839 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1840 break; 1841 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1842 if (info.dceMajor >= 5) 1843 encoder_dpms_set_dvo(crtcID, mode); 1844 else if (info.dceMajor >= 3) 1845 encoder_dpms_set_dig(crtcID, mode); 1846 else 1847 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1848 break; 1849 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1850 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1851 break; 1852 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1853 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1854 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1855 else 1856 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1857 break; 1858 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1859 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1860 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1861 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1862 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1863 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1864 else 1865 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1866 break; 1867 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1868 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1869 if ((connectorFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1870 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1871 else if ((connectorFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1872 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1873 else 1874 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1875 break; 1876 // default, none on purpose 1877 } 1878 1879 // If we have an index, we need to execute a table. 1880 if (index >= 0) { 1881 switch (mode) { 1882 case B_DPMS_ON: 1883 args.ucAction = ATOM_ENABLE; 1884 break; 1885 case B_DPMS_STAND_BY: 1886 case B_DPMS_SUSPEND: 1887 case B_DPMS_OFF: 1888 args.ucAction = ATOM_DISABLE; 1889 break; 1890 } 1891 1892 atom_execute_table(gAtomContext, index, (uint32*)&args); 1893 if (info.dceMajor < 5) { 1894 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1895 args.ucAction = args.ucAction == ATOM_DISABLE 1896 ? ATOM_LCD_BLOFF : ATOM_LCD_BLON; 1897 atom_execute_table(gAtomContext, index, (uint32*)&args); 1898 } 1899 } 1900 if (info.dceMajor < 4) 1901 encoder_dpms_scratch(crtcID, true); 1902 } 1903 } 1904 1905 1906 void 1907 encoder_dpms_set_dig(uint8 crtcID, int mode) 1908 { 1909 TRACE("%s: display %" B_PRIu8 ", power: %s\n", __func__, crtcID, 1910 mode == B_DPMS_ON ? "true" : "false"); 1911 1912 radeon_shared_info &info = *gInfo->shared_info; 1913 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1914 connector_info* connector = gConnector[connectorIndex]; 1915 uint32 connectorFlags = connector->flags; 1916 pll_info* pll = &connector->encoder.pll; 1917 bool hasExternal = connector->encoderExternal.valid; 1918 bool travisQuirk = info.dceMajor < 5 1919 && (connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0 1920 && connector->encoderExternal.objectID == ENCODER_OBJECT_ID_TRAVIS; 1921 1922 switch (mode) { 1923 case B_DPMS_ON: 1924 if ((info.dceMajor == 4 && info.dceMinor == 1) 1925 || info.dceMajor >= 5) { 1926 // Setup encoder 1927 encoder_dig_setup(connectorIndex, pll->pixelClock, 1928 ATOM_ENCODER_CMD_SETUP); 1929 encoder_dig_setup(connectorIndex, pll->pixelClock, 1930 ATOM_ENCODER_CMD_SETUP_PANEL_MODE); 1931 } else if (info.dceMajor >= 4) { 1932 // Setup encoder 1933 encoder_dig_setup(connectorIndex, pll->pixelClock, 1934 ATOM_ENCODER_CMD_SETUP); 1935 } else { 1936 // Setup encoder and transmitter 1937 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_ENABLE); 1938 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1939 ATOM_TRANSMITTER_ACTION_SETUP); 1940 } 1941 1942 if (connector->type == VIDEO_CONNECTOR_EDP) { 1943 // TODO: If VIDEO_CONNECTOR_EDP, ATOM_TRANSMITTER_ACTION_POWER_ON 1944 ERROR("%s: TODO, edp_panel_power!\n", 1945 __func__); 1946 } 1947 1948 // Enable transmitter 1949 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1950 ATOM_TRANSMITTER_ACTION_ENABLE); 1951 1952 if (connector_is_dp(connectorIndex)) { 1953 if (info.dceMajor >= 4) { 1954 encoder_dig_setup(connectorIndex, pll->pixelClock, 1955 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1956 } 1957 // dp link train 1958 dp_link_train(crtcID); 1959 if (info.dceMajor >= 4) { 1960 encoder_dig_setup(connectorIndex, pll->pixelClock, 1961 ATOM_ENCODER_CMD_DP_VIDEO_ON); 1962 } 1963 // not sure what AtomBIOS table/command sets this 1964 // register, but it's required to get the video output 1965 Write32(OUT, AVIVO_DP_VID_STREAM_CNTL, 0x201); 1966 } 1967 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1968 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1969 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON); 1970 } 1971 if (hasExternal) 1972 encoder_external_setup(connectorIndex, ATOM_ENABLE); 1973 break; 1974 case B_DPMS_STAND_BY: 1975 case B_DPMS_SUSPEND: 1976 case B_DPMS_OFF: 1977 if (connector_is_dp(connectorIndex)) { 1978 if (info.dceMajor >= 4) { 1979 encoder_dig_setup(connectorIndex, pll->pixelClock, 1980 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1981 } 1982 } 1983 if (hasExternal) 1984 encoder_external_setup(connectorIndex, ATOM_DISABLE); 1985 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1986 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1987 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF); 1988 } 1989 if (connector_is_dp(connectorIndex) && !travisQuirk) { 1990 // If not TRAVIS on < DCE 5, set_rx_power_state D3 1991 ERROR("%s: TODO: dpms off set_rx_power_state D3\n", __func__); 1992 } 1993 if (info.dceMajor >= 4) { 1994 // Disable transmitter 1995 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1996 ATOM_TRANSMITTER_ACTION_DISABLE); 1997 } else { 1998 // Disable transmitter and encoder 1999 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 2000 ATOM_TRANSMITTER_ACTION_DISABLE); 2001 encoder_dig_setup(connectorIndex, pll->pixelClock, ATOM_DISABLE); 2002 } 2003 2004 if (connector_is_dp(connectorIndex)) { 2005 if (travisQuirk) { 2006 ERROR("%s: TODO: dpms off set_rx_power_state D3\n", 2007 __func__); 2008 } 2009 if (connector->type == VIDEO_CONNECTOR_EDP) { 2010 // TODO: ATOM_TRANSMITTER_ACTION_POWER_OFF 2011 ERROR("%s: TODO, edp_panel_power!\n", __func__); 2012 } 2013 } 2014 break; 2015 } 2016 } 2017 2018 2019 void 2020 encoder_dpms_set_dvo(uint8 crtcID, int mode) 2021 { 2022 ERROR("%s: TODO, dvo encoder dpms stub\n", __func__); 2023 } 2024 2025 2026 void 2027 encoder_output_lock(bool lock) 2028 { 2029 TRACE("%s: %s\n", __func__, lock ? "true" : "false"); 2030 uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6); 2031 2032 if (lock) { 2033 biosScratch6 |= ATOM_S6_CRITICAL_STATE; 2034 biosScratch6 &= ~ATOM_S6_ACC_MODE; 2035 } else { 2036 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE; 2037 biosScratch6 |= ATOM_S6_ACC_MODE; 2038 } 2039 2040 Write32(OUT, R600_SCRATCH_REG6, biosScratch6); 2041 } 2042 2043 static const char* encoder_name_matrix[] = { 2044 "NONE", 2045 "Internal Radeon LVDS", 2046 "Internal Radeon TMDS1", 2047 "Internal Radeon TMDS2", 2048 "Internal Radeon DAC1", 2049 "Internal Radeon DAC2 (TV)", 2050 "Internal Radeon SDVOA", 2051 "Internal Radeon SDVOB", 2052 "External 3rd party SI170B", 2053 "External 3rd party CH7303", 2054 "External 3rd party CH7301", 2055 "Internal Radeon DVO1", 2056 "External 3rd party SDVOA", 2057 "External 3rd party SDVOB", 2058 "External 3rd party TITFP513", 2059 "Internal LVTM1", 2060 "External 3rd party VT1623", 2061 "External HDMI SI1930", 2062 "Internal HDMI", 2063 "Internal Kaleidoscope TMDS1", 2064 "Internal Kaleidoscope DVO1", 2065 "Internal Kaleidoscope DAC1", 2066 "Internal Kaleidoscope DAC2", 2067 "External Kaleidoscope SI178", 2068 "MVPU FPGA", 2069 "Internal Kaleidoscope DDI", 2070 "External Kaleidoscope VT1625", 2071 "External Kaleidoscope HDMI SI1932", 2072 "External Kaleidoscope DP AN9801", 2073 "External Kaleidoscope DP DP501", 2074 "Internal Kaleidoscope UNIPHY", 2075 "Internal Kaleidoscope LVTMA", 2076 "Internal Kaleidoscope UNIPHY1", 2077 "Internal Kaleidoscope UNIPHY2", 2078 "External Nutmeg Bridge", 2079 "External Travis Bridge", 2080 "Internal Kaleidoscope VCE" 2081 }; 2082 2083 2084 const char* 2085 encoder_name_lookup(uint32 encoderID) { 2086 if (encoderID < B_COUNT_OF(encoder_name_matrix)) 2087 return encoder_name_matrix[encoderID]; 2088 else 2089 return "Unknown"; 2090 } 2091 2092 2093 uint32 2094 encoder_object_lookup(uint32 connectorFlags, uint8 dacID) 2095 { 2096 // used on older cards to take a guess at the encoder 2097 // object 2098 2099 radeon_shared_info &info = *gInfo->shared_info; 2100 2101 uint32 ret = 0; 2102 2103 switch (connectorFlags) { 2104 case ATOM_DEVICE_CRT1_SUPPORT: 2105 case ATOM_DEVICE_TV1_SUPPORT: 2106 case ATOM_DEVICE_TV2_SUPPORT: 2107 case ATOM_DEVICE_CRT2_SUPPORT: 2108 case ATOM_DEVICE_CV_SUPPORT: 2109 switch (dacID) { 2110 case 1: 2111 if ((info.chipsetID == RADEON_RS400) 2112 || (info.chipsetID == RADEON_RS480)) 2113 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 2114 else if (info.chipsetID >= RADEON_RS600) 2115 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 2116 else 2117 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 2118 break; 2119 case 2: 2120 if (info.chipsetID >= RADEON_RS600) 2121 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 2122 else { 2123 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 2124 } 2125 break; 2126 case 3: // external dac 2127 if (info.chipsetID >= RADEON_RS600) 2128 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 2129 else 2130 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 2131 break; 2132 } 2133 break; 2134 case ATOM_DEVICE_LCD1_SUPPORT: 2135 if (info.chipsetID >= RADEON_RS600) 2136 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 2137 else 2138 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 2139 break; 2140 case ATOM_DEVICE_DFP1_SUPPORT: 2141 if ((info.chipsetID == RADEON_RS400) 2142 || (info.chipsetID == RADEON_RS480)) 2143 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 2144 else if (info.chipsetID >= RADEON_RS600) 2145 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 2146 else 2147 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 2148 break; 2149 case ATOM_DEVICE_LCD2_SUPPORT: 2150 case ATOM_DEVICE_DFP2_SUPPORT: 2151 if ((info.chipsetID == RADEON_RS600) 2152 || (info.chipsetID == RADEON_RS690) 2153 || (info.chipsetID == RADEON_RS740)) 2154 ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 2155 else if (info.chipsetID >= RADEON_RS600) 2156 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 2157 else 2158 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 2159 break; 2160 case ATOM_DEVICE_DFP3_SUPPORT: 2161 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 2162 break; 2163 } 2164 2165 return ret; 2166 } 2167 2168 2169 uint32 2170 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags) 2171 { 2172 switch (encoderID) { 2173 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 2174 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 2175 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 2176 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 2177 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 2178 return VIDEO_ENCODER_LVDS; 2179 else 2180 return VIDEO_ENCODER_TMDS; 2181 break; 2182 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 2183 return VIDEO_ENCODER_DAC; 2184 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 2185 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 2186 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 2187 return VIDEO_ENCODER_TVDAC; 2188 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 2189 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 2190 case ENCODER_OBJECT_ID_INTERNAL_DDI: 2191 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 2192 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 2193 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 2194 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 2195 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 2196 return VIDEO_ENCODER_LVDS; 2197 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 2198 return VIDEO_ENCODER_DAC; 2199 else 2200 return VIDEO_ENCODER_TMDS; 2201 break; 2202 case ENCODER_OBJECT_ID_SI170B: 2203 case ENCODER_OBJECT_ID_CH7303: 2204 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 2205 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 2206 case ENCODER_OBJECT_ID_TITFP513: 2207 case ENCODER_OBJECT_ID_VT1623: 2208 case ENCODER_OBJECT_ID_HDMI_SI1930: 2209 case ENCODER_OBJECT_ID_TRAVIS: 2210 case ENCODER_OBJECT_ID_NUTMEG: 2211 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 2212 return VIDEO_ENCODER_LVDS; 2213 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 2214 return VIDEO_ENCODER_DAC; 2215 else 2216 return VIDEO_ENCODER_TMDS; 2217 break; 2218 } 2219 2220 return VIDEO_ENCODER_NONE; 2221 } 2222 2223 2224 bool 2225 encoder_is_external(uint32 encoderID) 2226 { 2227 switch (encoderID) { 2228 case ENCODER_OBJECT_ID_SI170B: 2229 case ENCODER_OBJECT_ID_CH7303: 2230 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 2231 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 2232 case ENCODER_OBJECT_ID_TITFP513: 2233 case ENCODER_OBJECT_ID_VT1623: 2234 case ENCODER_OBJECT_ID_HDMI_SI1930: 2235 case ENCODER_OBJECT_ID_TRAVIS: 2236 case ENCODER_OBJECT_ID_NUTMEG: 2237 return true; 2238 } 2239 2240 return false; 2241 } 2242 2243 2244 bool 2245 encoder_is_dp_bridge(uint32 encoderID) 2246 { 2247 switch (encoderID) { 2248 case ENCODER_OBJECT_ID_TRAVIS: 2249 case ENCODER_OBJECT_ID_NUTMEG: 2250 return true; 2251 } 2252 return false; 2253 } 2254