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