1 /* 2 * Copyright 2006-2011, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, kallisti5@unixzen.com 7 */ 8 9 10 #include "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 "bios.h" 20 #include "connector.h" 21 #include "display.h" 22 #include "displayport.h" 23 #include "utility.h" 24 25 26 #define TRACE_ENCODER 27 #ifdef TRACE_ENCODER 28 extern "C" void _sPrintf(const char* format, ...); 29 # define TRACE(x...) _sPrintf("radeon_hd: " x) 30 #else 31 # define TRACE(x...) ; 32 #endif 33 34 #define ERROR(x...) _sPrintf("radeon_hd: " x) 35 36 37 void 38 encoder_assign_crtc(uint8 crtcID) 39 { 40 TRACE("%s\n", __func__); 41 42 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 43 44 // Table version 45 uint8 tableMajor; 46 uint8 tableMinor; 47 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 48 != B_OK) 49 return; 50 51 uint16 connectorIndex = gDisplay[crtcID]->connectorIndex; 52 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 53 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 54 55 // Prepare AtomBIOS command arguments 56 union crtcSourceParam { 57 SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 58 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 59 }; 60 union crtcSourceParam args; 61 memset(&args, 0, sizeof(args)); 62 63 switch (tableMajor) { 64 case 1: 65 switch (tableMinor) { 66 case 1: 67 default: 68 args.v1.ucCRTC = crtcID; 69 switch (encoderID) { 70 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 71 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 72 args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 73 break; 74 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 75 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 76 if ((gConnector[connectorIndex]->flags 77 & ATOM_DEVICE_LCD1_SUPPORT) != 0) 78 args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 79 else 80 args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 81 break; 82 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 83 case ENCODER_OBJECT_ID_INTERNAL_DDI: 84 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 85 args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 86 break; 87 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 88 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 89 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 90 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 91 } else if ((encoderFlags 92 & ATOM_DEVICE_CV_SUPPORT) != 0) { 93 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 94 } else 95 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 96 break; 97 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 98 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 99 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 100 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 101 } else if ((encoderFlags 102 & ATOM_DEVICE_CV_SUPPORT) != 0) { 103 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 104 } else 105 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 106 break; 107 } 108 break; 109 case 2: 110 args.v2.ucCRTC = crtcID; 111 args.v2.ucEncodeMode 112 = display_get_encoder_mode(connectorIndex); 113 switch (encoderID) { 114 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 115 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 116 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 117 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 118 switch (encoder_pick_dig(connectorIndex)) { 119 case 0: 120 args.v2.ucEncoderID 121 = ASIC_INT_DIG1_ENCODER_ID; 122 break; 123 case 1: 124 args.v2.ucEncoderID 125 = ASIC_INT_DIG2_ENCODER_ID; 126 break; 127 case 2: 128 args.v2.ucEncoderID 129 = ASIC_INT_DIG3_ENCODER_ID; 130 break; 131 case 3: 132 args.v2.ucEncoderID 133 = ASIC_INT_DIG4_ENCODER_ID; 134 break; 135 case 4: 136 args.v2.ucEncoderID 137 = ASIC_INT_DIG5_ENCODER_ID; 138 break; 139 case 5: 140 args.v2.ucEncoderID 141 = ASIC_INT_DIG6_ENCODER_ID; 142 break; 143 } 144 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 145 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 146 break; 147 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 148 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 149 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 150 } else if ((encoderFlags 151 & ATOM_DEVICE_CV_SUPPORT) != 0) { 152 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 153 } else 154 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 155 break; 156 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 157 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 158 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 159 } else if ((encoderFlags 160 & ATOM_DEVICE_CV_SUPPORT) != 0) { 161 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 162 } else 163 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 164 break; 165 } 166 break; 167 } 168 break; 169 default: 170 ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 171 __func__, tableMajor, tableMinor); 172 return; 173 } 174 175 atom_execute_table(gAtomContext, index, (uint32*)&args); 176 177 // update crtc encoder scratch register @ scratch 3 178 encoder_crtc_scratch(crtcID); 179 } 180 181 182 uint32 183 encoder_pick_dig(uint32 connectorIndex) 184 { 185 TRACE("%s\n", __func__); 186 radeon_shared_info &info = *gInfo->shared_info; 187 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 188 189 // obtain assigned CRT 190 uint32 crtcID; 191 for (crtcID = 0; crtcID < MAX_DISPLAY; crtcID++) { 192 if (gDisplay[crtcID]->active != true) 193 continue; 194 if (gDisplay[crtcID]->connectorIndex == connectorIndex) 195 break; 196 } 197 198 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration 199 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 200 201 if (info.dceMajor >= 4) { 202 switch (info.chipsetID) { 203 case RADEON_PALM: 204 return linkB ? 1 : 0; 205 case RADEON_SUMO: 206 case RADEON_SUMO2: 207 // llano follows dce 3.2 208 return crtcID; 209 } 210 211 switch (encoderID) { 212 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 213 return linkB ? 1 : 0; 214 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 215 return linkB ? 3 : 2; 216 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 217 return linkB ? 5 : 4; 218 } 219 ERROR("%s: picking DIG encoder on non-DIG dce 4+ encoder!\n", __func__); 220 } else if ((info.dceMajor >= 3) && (info.dceMinor >= 2)) { 221 // DCE 3.2 can drive any DIG encoder 222 return crtcID; 223 } 224 225 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA) { 226 // LVTMA can only be driven by DIG encoder 2 227 return 1; 228 } 229 return 0; 230 } 231 232 233 void 234 encoder_apply_quirks(uint8 crtcID) 235 { 236 TRACE("%s\n", __func__); 237 radeon_shared_info &info = *gInfo->shared_info; 238 register_info* regs = gDisplay[crtcID]->regs; 239 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 240 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 241 242 // Setting the scaler clears this on some chips... 243 if (info.dceMajor >= 3 244 && (encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0) { 245 // TODO: assume non interleave mode for now 246 // en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN 247 Write32(OUT, regs->modeDataFormat, 0); 248 } 249 } 250 251 252 void 253 encoder_mode_set(uint8 id, uint32 pixelClock) 254 { 255 TRACE("%s\n", __func__); 256 radeon_shared_info &info = *gInfo->shared_info; 257 uint32 connectorIndex = gDisplay[id]->connectorIndex; 258 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 259 260 switch (gConnector[connectorIndex]->encoder.objectID) { 261 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 262 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 263 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 264 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 265 encoder_analog_setup(connectorIndex, pixelClock, ATOM_ENABLE); 266 if ((encoderFlags 267 & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) != 0) { 268 encoder_tv_setup(connectorIndex, pixelClock, ATOM_ENABLE); 269 } else { 270 encoder_tv_setup(connectorIndex, pixelClock, ATOM_DISABLE); 271 } 272 break; 273 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 274 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 275 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 276 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 277 encoder_digital_setup(connectorIndex, pixelClock, 278 PANEL_ENCODER_ACTION_ENABLE); 279 break; 280 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 281 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 282 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 283 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 284 if (info.dceMajor >= 4) { 285 // Disable DIG transmitter 286 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 287 ATOM_TRANSMITTER_ACTION_DISABLE); 288 // Setup DIG encoder 289 encoder_dig_setup(connectorIndex, pixelClock, 290 ATOM_ENCODER_CMD_SETUP); 291 // Enable DIG transmitter 292 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 293 ATOM_TRANSMITTER_ACTION_ENABLE); 294 } else { 295 // Disable DIG transmitter 296 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 297 ATOM_TRANSMITTER_ACTION_DISABLE); 298 // Disable DIG encoder 299 encoder_dig_setup(connectorIndex, pixelClock, ATOM_DISABLE); 300 // Enable the DIG encoder 301 encoder_dig_setup(connectorIndex, pixelClock, ATOM_ENABLE); 302 303 // Setup and enable DIG transmitter 304 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 305 ATOM_TRANSMITTER_ACTION_SETUP); 306 transmitter_dig_setup(connectorIndex, pixelClock, 0, 0, 307 ATOM_TRANSMITTER_ACTION_ENABLE); 308 } 309 break; 310 case ENCODER_OBJECT_ID_INTERNAL_DDI: 311 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 312 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 313 TRACE("%s: TODO for DVO encoder setup\n", __func__); 314 break; 315 } 316 317 if (gConnector[connectorIndex]->encoder.isExternal == true) { 318 if (info.dceMajor >= 4 && info.dceMinor >= 1) { 319 encoder_external_setup(connectorIndex, pixelClock, 320 EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); 321 } else { 322 encoder_external_setup(connectorIndex, pixelClock, 323 ATOM_ENABLE); 324 } 325 } 326 327 encoder_apply_quirks(id); 328 } 329 330 331 status_t 332 encoder_tv_setup(uint32 connectorIndex, uint32 pixelClock, int command) 333 { 334 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 335 336 TV_ENCODER_CONTROL_PS_ALLOCATION args; 337 memset(&args, 0, sizeof(args)); 338 339 int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 340 341 args.sTVEncoder.ucAction = command; 342 343 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 344 args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 345 else { 346 // TODO: we assume NTSC for now 347 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 348 } 349 350 args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 351 352 return atom_execute_table(gAtomContext, index, (uint32*)&args); 353 } 354 355 356 status_t 357 encoder_digital_setup(uint32 connectorIndex, uint32 pixelClock, int command) 358 { 359 TRACE("%s\n", __func__); 360 361 int index = 0; 362 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 363 364 switch (gConnector[connectorIndex]->encoder.objectID) { 365 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 366 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 367 break; 368 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 369 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 370 index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 371 break; 372 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 373 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 374 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 375 else 376 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 377 break; 378 } 379 380 // Table verson 381 uint8 tableMajor; 382 uint8 tableMinor; 383 384 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 385 != B_OK) { 386 ERROR("%s: cannot parse command table\n", __func__); 387 return B_ERROR; 388 } 389 390 // Prepare AtomBIOS command arguments 391 union lvdsEncoderControl { 392 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 393 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 394 }; 395 union lvdsEncoderControl args; 396 memset(&args, 0, sizeof(args)); 397 398 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 399 tableMajor, tableMinor); 400 401 switch (tableMajor) { 402 case 1: 403 case 2: 404 switch (tableMinor) { 405 case 1: 406 args.v1.ucMisc = 0; 407 args.v1.ucAction = command; 408 if (0) // TODO: HDMI? 409 args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 410 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 411 412 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 413 // TODO: laptop display support 414 //if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 415 // args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 416 //if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 417 // args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 418 } else { 419 //if (dig->linkb) 420 // args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 421 if (pixelClock > 165000) 422 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 423 /*if (pScrn->rgbBits == 8) */ 424 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 425 } 426 break; 427 case 2: 428 case 3: 429 args.v2.ucMisc = 0; 430 args.v2.ucAction = command; 431 if (tableMinor == 3) { 432 //if (dig->coherent_mode) 433 // args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 434 } 435 if (0) // TODO: HDMI? 436 args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 437 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 438 args.v2.ucTruncate = 0; 439 args.v2.ucSpatial = 0; 440 args.v2.ucTemporal = 0; 441 args.v2.ucFRC = 0; 442 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 443 // TODO: laptop display support 444 //if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 445 // args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 446 //if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { 447 args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 448 //if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 449 // args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 450 //} 451 //if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { 452 // args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 453 // if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) { 454 // args.v2.ucTemporal 455 // |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 456 // } 457 // if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) 458 // & 0x3) == 2) { 459 // args.v2.ucTemporal 460 // |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 461 // } 462 //} 463 } else { 464 //if (dig->linkb) 465 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 466 if (pixelClock > 165000) 467 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 468 } 469 break; 470 default: 471 ERROR("%s: Unknown minor table version: %" 472 B_PRIu8 ".%" B_PRIu8 "\n", __func__, 473 tableMajor, tableMinor); 474 return B_ERROR; 475 } 476 break; 477 default: 478 ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 479 __func__, tableMajor, tableMinor); 480 return B_ERROR; 481 } 482 return atom_execute_table(gAtomContext, index, (uint32*)&args); 483 } 484 485 486 status_t 487 encoder_dig_setup(uint32 connectorIndex, uint32 pixelClock, int command) 488 { 489 radeon_shared_info &info = *gInfo->shared_info; 490 491 int index = 0; 492 if (info.dceMajor >= 4) 493 index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 494 else { 495 if (encoder_pick_dig(connectorIndex)) 496 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 497 else 498 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 499 } 500 501 // Table verson 502 uint8 tableMajor; 503 uint8 tableMinor; 504 505 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 506 != B_OK) { 507 ERROR("%s: cannot parse command table\n", __func__); 508 return B_ERROR; 509 } 510 511 // Prepare AtomBIOS command arguments 512 union digEncoderControl { 513 DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 514 DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 515 DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 516 DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 517 }; 518 union digEncoderControl args; 519 memset(&args, 0, sizeof(args)); 520 521 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 522 bool isDPBridge = gConnector[connectorIndex]->encoder.isDPBridge; 523 524 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration 525 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 526 527 // determine DP panel mode 528 uint32 panelMode; 529 if (info.dceMajor >= 4 && isDPBridge) { 530 if (encoderID == ENCODER_OBJECT_ID_NUTMEG) 531 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 532 else { 533 // aka ENCODER_OBJECT_ID_TRAVIS or VIDEO_CONNECTOR_EDP 534 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 535 } 536 } else 537 panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 538 539 #if 0 540 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 541 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) { 542 uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP); 543 if ((temp & 1) != 0) 544 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 545 } 546 #endif 547 548 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 549 tableMajor, tableMinor); 550 551 uint32 dpClock = dp_get_link_clock(connectorIndex); 552 switch (tableMinor) { 553 case 1: 554 args.v1.ucAction = command; 555 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 556 557 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 558 args.v3.ucPanelMode = panelMode; 559 else { 560 args.v1.ucEncoderMode 561 = display_get_encoder_mode(connectorIndex); 562 } 563 564 if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 565 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) 566 && dpClock == 270000) { 567 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 568 } 569 570 switch (encoderID) { 571 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 572 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 573 break; 574 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 575 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 576 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 577 break; 578 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 579 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 580 break; 581 } 582 583 if (linkB) 584 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 585 else 586 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 587 break; 588 case 2: 589 case 3: 590 args.v1.ucAction = command; 591 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 592 593 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 594 args.v3.ucPanelMode = panelMode; 595 else { 596 args.v3.ucEncoderMode 597 = display_get_encoder_mode(connectorIndex); 598 } 599 600 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 601 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 602 args.v1.ucLaneNum = gDPInfo[connectorIndex]->laneCount; 603 } else if (pixelClock > 165000) 604 args.v1.ucLaneNum = 8; 605 else 606 args.v1.ucLaneNum = 4; 607 608 if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 609 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) 610 && dpClock == 270000) { 611 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 612 } 613 614 args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex); 615 616 // TODO: get BPC 617 switch (8) { 618 case 0: 619 args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; 620 break; 621 case 6: 622 args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; 623 break; 624 case 8: 625 default: 626 args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; 627 break; 628 case 10: 629 args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; 630 break; 631 case 12: 632 args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; 633 break; 634 case 16: 635 args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; 636 break; 637 } 638 break; 639 case 4: 640 args.v4.ucHPD_ID = 0; 641 ERROR("%s: tableMinor 4 TODO!\n", __func__); 642 break; 643 default: 644 ERROR("%s: unknown tableMinor!\n", __func__); 645 } 646 647 status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args); 648 649 #if 0 650 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP 651 && panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) { 652 dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1); 653 } 654 #endif 655 656 return result; 657 } 658 659 660 status_t 661 encoder_external_setup(uint32 connectorIndex, uint32 pixelClock, int command) 662 { 663 TRACE("%s\n", __func__); 664 665 uint8 tableMajor; 666 uint8 tableMinor; 667 668 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 669 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 670 != B_OK) { 671 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__); 672 return B_ERROR; 673 } 674 675 // Prepare AtomBIOS command arguments 676 union externalEncoderControl { 677 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 678 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 679 }; 680 union externalEncoderControl args; 681 memset(&args, 0, sizeof(args)); 682 683 int connectorObjectID 684 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 685 >> OBJECT_ID_SHIFT; 686 687 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 688 tableMajor, tableMinor); 689 switch (tableMajor) { 690 case 1: 691 // no options needed on table 1.x 692 break; 693 case 2: 694 switch (tableMinor) { 695 case 1: 696 case 2: 697 args.v1.sDigEncoder.ucAction = command; 698 args.v1.sDigEncoder.usPixelClock 699 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 700 args.v1.sDigEncoder.ucEncoderMode 701 = display_get_encoder_mode(connectorIndex); 702 703 if (connector_is_dp(connectorIndex)) { 704 if (gDPInfo[connectorIndex]->clock == 270000) { 705 args.v1.sDigEncoder.ucConfig 706 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 707 } 708 args.v1.sDigEncoder.ucLaneNum 709 = gDPInfo[connectorIndex]->laneCount; 710 } else if (pixelClock > 165000) { 711 args.v1.sDigEncoder.ucLaneNum = 8; 712 } else { 713 args.v1.sDigEncoder.ucLaneNum = 4; 714 } 715 break; 716 case 3: 717 { 718 args.v3.sExtEncoder.ucAction = command; 719 if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) { 720 args.v3.sExtEncoder.usConnectorId 721 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 722 } else { 723 args.v3.sExtEncoder.usPixelClock 724 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 725 } 726 727 args.v3.sExtEncoder.ucEncoderMode 728 = display_get_encoder_mode(connectorIndex); 729 730 if (connector_is_dp(connectorIndex)) { 731 if (gDPInfo[connectorIndex]->clock == 270000) { 732 args.v3.sExtEncoder.ucConfig 733 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 734 } else if (gDPInfo[connectorIndex]->clock == 540000) { 735 args.v3.sExtEncoder.ucConfig 736 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 737 } 738 args.v1.sDigEncoder.ucLaneNum 739 = gDPInfo[connectorIndex]->laneCount; 740 } else if (pixelClock > 165000) { 741 args.v3.sExtEncoder.ucLaneNum = 8; 742 } else { 743 args.v3.sExtEncoder.ucLaneNum = 4; 744 } 745 746 uint16 encoderFlags 747 = gConnector[connectorIndex]->encoder.flags; 748 switch ((encoderFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) { 749 case GRAPH_OBJECT_ENUM_ID1: 750 TRACE("%s: external encoder 1\n", __func__); 751 args.v3.sExtEncoder.ucConfig 752 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 753 break; 754 case GRAPH_OBJECT_ENUM_ID2: 755 TRACE("%s: external encoder 2\n", __func__); 756 args.v3.sExtEncoder.ucConfig 757 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 758 break; 759 case GRAPH_OBJECT_ENUM_ID3: 760 TRACE("%s: external encoder 3\n", __func__); 761 args.v3.sExtEncoder.ucConfig 762 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 763 break; 764 } 765 766 // TODO: don't set statically 767 uint32 bitsPerColor = 8; 768 switch (bitsPerColor) { 769 case 0: 770 args.v3.sExtEncoder.ucBitPerColor 771 = PANEL_BPC_UNDEFINE; 772 break; 773 case 6: 774 args.v3.sExtEncoder.ucBitPerColor 775 = PANEL_6BIT_PER_COLOR; 776 break; 777 case 8: 778 default: 779 args.v3.sExtEncoder.ucBitPerColor 780 = PANEL_8BIT_PER_COLOR; 781 break; 782 case 10: 783 args.v3.sExtEncoder.ucBitPerColor 784 = PANEL_10BIT_PER_COLOR; 785 break; 786 case 12: 787 args.v3.sExtEncoder.ucBitPerColor 788 = PANEL_12BIT_PER_COLOR; 789 break; 790 case 16: 791 args.v3.sExtEncoder.ucBitPerColor 792 = PANEL_16BIT_PER_COLOR; 793 break; 794 } 795 break; 796 } 797 default: 798 ERROR("%s: Unknown table minor version: " 799 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 800 tableMajor, tableMinor); 801 return B_ERROR; 802 } 803 break; 804 default: 805 ERROR("%s: Unknown table major version: " 806 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 807 tableMajor, tableMinor); 808 return B_ERROR; 809 } 810 811 return atom_execute_table(gAtomContext, index, (uint32*)&args); 812 } 813 814 815 status_t 816 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command) 817 { 818 TRACE("%s\n", __func__); 819 820 int index = 0; 821 DAC_ENCODER_CONTROL_PS_ALLOCATION args; 822 memset(&args, 0, sizeof(args)); 823 824 switch (gConnector[connectorIndex]->encoder.objectID) { 825 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 826 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 827 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 828 break; 829 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 830 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 831 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 832 break; 833 } 834 835 args.ucAction = command; 836 args.ucDacStandard = ATOM_DAC1_PS2; 837 // TODO: or ATOM_DAC1_CV if ATOM_DEVICE_CV_SUPPORT 838 // TODO: or ATOM_DAC1_PAL or ATOM_DAC1_NTSC if else 839 840 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 841 842 return atom_execute_table(gAtomContext, index, (uint32*)&args); 843 } 844 845 846 bool 847 encoder_analog_load_detect(uint32 connectorIndex) 848 { 849 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 850 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 851 852 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0 853 && (encoderFlags & ATOM_DEVICE_CV_SUPPORT) == 0 854 && (encoderFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) { 855 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n", 856 __func__, connectorIndex); 857 return false; 858 } 859 860 // *** tell the card we want to do a DAC detection 861 862 DAC_LOAD_DETECTION_PS_ALLOCATION args; 863 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 864 uint8 tableMajor; 865 uint8 tableMinor; 866 867 memset(&args, 0, sizeof(args)); 868 869 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 870 != B_OK) { 871 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n", 872 __func__); 873 return false; 874 } 875 876 args.sDacload.ucMisc = 0; 877 878 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1 879 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) { 880 args.sDacload.ucDacType = ATOM_DAC_A; 881 } else { 882 args.sDacload.ucDacType = ATOM_DAC_B; 883 } 884 885 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 886 args.sDacload.usDeviceID 887 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT); 888 atom_execute_table(gAtomContext, index, (uint32*)&args); 889 890 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 891 892 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 893 return true; 894 895 } else if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 896 args.sDacload.usDeviceID 897 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT); 898 atom_execute_table(gAtomContext, index, (uint32*)&args); 899 900 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 901 902 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 903 return true; 904 905 } else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 906 args.sDacload.usDeviceID 907 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT); 908 if (tableMinor >= 3) 909 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 910 atom_execute_table(gAtomContext, index, (uint32*)&args); 911 912 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 913 914 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 915 return true; 916 917 } else if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 918 args.sDacload.usDeviceID 919 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT); 920 if (tableMinor >= 3) 921 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 922 atom_execute_table(gAtomContext, index, (uint32*)&args); 923 924 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 925 926 if ((biosScratch0 927 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) { 928 return true; /* Composite connected */ 929 } else if ((biosScratch0 930 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) { 931 return true; /* S-Video connected */ 932 } 933 934 } 935 return false; 936 } 937 938 939 status_t 940 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock, 941 uint8 laneNumber, uint8 laneSet, int command) 942 { 943 944 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 945 int index; 946 switch (encoderID) { 947 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 948 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 949 break; 950 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 951 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 952 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 953 index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 954 break; 955 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 956 index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); 957 break; 958 default: 959 ERROR("%s: called on non-dig encoder!\n", __func__); 960 return B_ERROR; 961 } 962 963 uint8 tableMajor; 964 uint8 tableMinor; 965 966 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 967 != B_OK) 968 return B_ERROR; 969 970 // Prepare AtomBIOS arguments 971 union digTransmitterControl { 972 DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 973 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 974 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 975 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; 976 }; 977 union digTransmitterControl args; 978 memset(&args, 0, sizeof(args)); 979 980 int connectorObjectID 981 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 982 >> OBJECT_ID_SHIFT; 983 uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID; 984 uint32 digEncoderID = encoder_pick_dig(connectorIndex); 985 986 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 987 988 bool isDP = connector_is_dp(connectorIndex); 989 bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration 990 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 991 992 uint8 dpClock = 0; 993 int dpLaneCount = 0; 994 if (gDPInfo[connectorIndex]->valid == true) { 995 dpClock = gDPInfo[connectorIndex]->clock; 996 dpLaneCount = gDPInfo[connectorIndex]->laneCount; 997 } 998 999 switch (tableMajor) { 1000 case 1: 1001 switch (tableMinor) { 1002 case 1: 1003 args.v1.ucAction = command; 1004 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1005 args.v1.usInitInfo 1006 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1007 } else if (command 1008 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1009 args.v1.asMode.ucLaneSel = laneNumber; 1010 args.v1.asMode.ucLaneSet = laneSet; 1011 } else { 1012 if (isDP) { 1013 args.v1.usPixelClock 1014 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1015 } else if (pixelClock > 165000) { 1016 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1017 (pixelClock / 2) / 10); 1018 } else { 1019 args.v1.usPixelClock 1020 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1021 } 1022 } 1023 1024 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 1025 1026 if (digEncoderID > 0) { 1027 args.v1.ucConfig 1028 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 1029 } else { 1030 args.v1.ucConfig 1031 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 1032 } 1033 1034 // TODO: IGP DIG Transmitter setup 1035 #if 0 1036 if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID 1037 == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 1038 if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { 1039 if (igp_lane_info & 0x1) 1040 args.v1.ucConfig 1041 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 1042 else if (igp_lane_info & 0x2) 1043 args.v1.ucConfig 1044 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 1045 else if (igp_lane_info & 0x4) 1046 args.v1.ucConfig 1047 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 1048 else if (igp_lane_info & 0x8) 1049 args.v1.ucConfig 1050 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 1051 } else { 1052 if (igp_lane_info & 0x3) 1053 args.v1.ucConfig 1054 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 1055 else if (igp_lane_info & 0xc) 1056 args.v1.ucConfig 1057 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 1058 } 1059 } 1060 #endif 1061 1062 if (linkB == true) 1063 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 1064 else 1065 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 1066 1067 if (isDP) 1068 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1069 else if ((gConnector[connectorIndex]->encoder.flags 1070 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1071 if (1) { 1072 // if coherentMode, i've only ever seen it true 1073 args.v1.ucConfig 1074 |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1075 } 1076 if (pixelClock > 165000) { 1077 args.v1.ucConfig 1078 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 1079 } 1080 } 1081 break; 1082 case 2: 1083 args.v2.ucAction = command; 1084 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1085 args.v2.usInitInfo 1086 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1087 } else if (command 1088 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1089 args.v2.asMode.ucLaneSel = laneNumber; 1090 args.v2.asMode.ucLaneSet = laneSet; 1091 } else { 1092 if (isDP) { 1093 args.v2.usPixelClock 1094 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1095 } else if (pixelClock > 165000) { 1096 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1097 (pixelClock / 2) / 10); 1098 } else { 1099 args.v2.usPixelClock 1100 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1101 } 1102 } 1103 args.v2.acConfig.ucEncoderSel = digEncoderID; 1104 if (linkB) 1105 args.v2.acConfig.ucLinkSel = 1; 1106 1107 switch (encoderObjectID) { 1108 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1109 args.v2.acConfig.ucTransmitterSel = 0; 1110 break; 1111 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1112 args.v2.acConfig.ucTransmitterSel = 1; 1113 break; 1114 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1115 args.v2.acConfig.ucTransmitterSel = 2; 1116 break; 1117 } 1118 1119 if (isDP) { 1120 args.v2.acConfig.fCoherentMode = 1; 1121 args.v2.acConfig.fDPConnector = 1; 1122 } else if ((gConnector[connectorIndex]->encoder.flags 1123 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1124 if (1) { 1125 // if coherentMode, i've only ever seen it true 1126 args.v2.acConfig.fCoherentMode = 1; 1127 } 1128 1129 if (pixelClock > 165000) 1130 args.v2.acConfig.fDualLinkConnector = 1; 1131 } 1132 break; 1133 case 3: 1134 args.v3.ucAction = command; 1135 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1136 args.v3.usInitInfo 1137 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1138 } else if (command 1139 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1140 args.v3.asMode.ucLaneSel = laneNumber; 1141 args.v3.asMode.ucLaneSet = laneSet; 1142 } else { 1143 if (isDP) { 1144 args.v3.usPixelClock 1145 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1146 } else if (pixelClock > 165000) { 1147 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1148 (pixelClock / 2) / 10); 1149 } else { 1150 args.v3.usPixelClock 1151 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1152 } 1153 } 1154 1155 if (isDP) 1156 args.v3.ucLaneNum = dpLaneCount; 1157 else if (pixelClock > 165000) 1158 args.v3.ucLaneNum = 8; 1159 else 1160 args.v3.ucLaneNum = 4; 1161 1162 if (linkB == true) 1163 args.v3.acConfig.ucLinkSel = 1; 1164 if (digEncoderID & 1) 1165 args.v3.acConfig.ucEncoderSel = 1; 1166 1167 // Select the PLL for the PHY 1168 // DP PHY to be clocked from external src if possible 1169 if (isDP && pll->dpExternalClock) { 1170 // use external clock source 1171 args.v3.acConfig.ucRefClkSource = 2; 1172 } else 1173 args.v3.acConfig.ucRefClkSource = pll->id; 1174 1175 switch (encoderObjectID) { 1176 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1177 args.v3.acConfig.ucTransmitterSel = 0; 1178 break; 1179 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1180 args.v3.acConfig.ucTransmitterSel = 1; 1181 break; 1182 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1183 args.v3.acConfig.ucTransmitterSel = 2; 1184 break; 1185 } 1186 1187 if (isDP) 1188 args.v3.acConfig.fCoherentMode = 1; 1189 else if ((gConnector[connectorIndex]->encoder.flags 1190 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1191 if (1) { 1192 // if coherentMode, i've only ever seen it true 1193 args.v3.acConfig.fCoherentMode = 1; 1194 } 1195 if (pixelClock > 165000) 1196 args.v3.acConfig.fDualLinkConnector = 1; 1197 } 1198 break; 1199 case 4: 1200 args.v4.ucAction = command; 1201 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1202 args.v4.usInitInfo 1203 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1204 } else if (command 1205 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1206 args.v4.asMode.ucLaneSel = laneNumber; 1207 args.v4.asMode.ucLaneSet = laneSet; 1208 } else { 1209 if (isDP) { 1210 args.v4.usPixelClock 1211 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1212 } else if (pixelClock > 165000) { 1213 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1214 (pixelClock / 2) / 10); 1215 } else { 1216 args.v4.usPixelClock 1217 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1218 } 1219 } 1220 1221 if (isDP) 1222 args.v4.ucLaneNum = dpLaneCount; 1223 else if (pixelClock > 165000) 1224 args.v4.ucLaneNum = 8; 1225 else 1226 args.v4.ucLaneNum = 4; 1227 1228 if (linkB == true) 1229 args.v4.acConfig.ucLinkSel = 1; 1230 if (digEncoderID & 1) 1231 args.v4.acConfig.ucEncoderSel = 1; 1232 1233 // Select the PLL for the PHY 1234 // DP PHY to be clocked from external src if possible 1235 if (isDP) { 1236 if (pll->dpExternalClock > 0) { 1237 args.v4.acConfig.ucRefClkSource 1238 = ENCODER_REFCLK_SRC_EXTCLK; 1239 } else { 1240 args.v4.acConfig.ucRefClkSource 1241 = ENCODER_REFCLK_SRC_DCPLL; 1242 } 1243 } else 1244 args.v4.acConfig.ucRefClkSource = pll->id; 1245 1246 switch (encoderObjectID) { 1247 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1248 args.v4.acConfig.ucTransmitterSel = 0; 1249 break; 1250 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1251 args.v4.acConfig.ucTransmitterSel = 1; 1252 break; 1253 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1254 args.v4.acConfig.ucTransmitterSel = 2; 1255 break; 1256 } 1257 1258 if (isDP) 1259 args.v4.acConfig.fCoherentMode = 1; 1260 else if ((gConnector[connectorIndex]->encoder.flags 1261 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1262 if (1) { 1263 // if coherentMode, i've only ever seen it true 1264 args.v4.acConfig.fCoherentMode = 1; 1265 } 1266 if (pixelClock > 165000) 1267 args.v4.acConfig.fDualLinkConnector = 1; 1268 } 1269 break; 1270 default: 1271 ERROR("%s: unknown table version\n", __func__); 1272 } 1273 break; 1274 default: 1275 ERROR("%s: unknown table version\n", __func__); 1276 } 1277 1278 return atom_execute_table(gAtomContext, index, (uint32*)&args); 1279 } 1280 1281 1282 void 1283 encoder_crtc_scratch(uint8 crtcID) 1284 { 1285 TRACE("%s\n", __func__); 1286 1287 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1288 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1289 1290 // TODO: r500 1291 uint32 biosScratch3 = Read32(OUT, R600_BIOS_3_SCRATCH); 1292 1293 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1294 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE; 1295 biosScratch3 |= (crtcID << 18); 1296 } 1297 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1298 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE; 1299 biosScratch3 |= (crtcID << 24); 1300 } 1301 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1302 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 1303 biosScratch3 |= (crtcID << 16); 1304 } 1305 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1306 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 1307 biosScratch3 |= (crtcID << 20); 1308 } 1309 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1310 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 1311 biosScratch3 |= (crtcID << 17); 1312 } 1313 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1314 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 1315 biosScratch3 |= (crtcID << 19); 1316 } 1317 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1318 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 1319 biosScratch3 |= (crtcID << 23); 1320 } 1321 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1322 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 1323 biosScratch3 |= (crtcID << 25); 1324 } 1325 1326 // TODO: r500 1327 Write32(OUT, R600_BIOS_3_SCRATCH, biosScratch3); 1328 } 1329 1330 1331 void 1332 encoder_dpms_scratch(uint8 crtcID, bool power) 1333 { 1334 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1335 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1336 1337 // TODO: r500 1338 uint32 biosScratch2 = Read32(OUT, R600_BIOS_2_SCRATCH); 1339 1340 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1341 if (power == true) 1342 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE; 1343 else 1344 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE; 1345 } 1346 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1347 if (power == true) 1348 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE; 1349 else 1350 biosScratch2 |= ATOM_S2_CV_DPMS_STATE; 1351 } 1352 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1353 if (power == true) 1354 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE; 1355 else 1356 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE; 1357 } 1358 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1359 if (power == true) 1360 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE; 1361 else 1362 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE; 1363 } 1364 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1365 if (power == true) 1366 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE; 1367 else 1368 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE; 1369 } 1370 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1371 if (power == true) 1372 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE; 1373 else 1374 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE; 1375 } 1376 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1377 if (power == true) 1378 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE; 1379 else 1380 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE; 1381 } 1382 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1383 if (power == true) 1384 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE; 1385 else 1386 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE; 1387 } 1388 if ((encoderFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) { 1389 if (power == true) 1390 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE; 1391 else 1392 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE; 1393 } 1394 if ((encoderFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) { 1395 if (power == true) 1396 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE; 1397 else 1398 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE; 1399 } 1400 Write32(OUT, R600_BIOS_2_SCRATCH, biosScratch2); 1401 } 1402 1403 1404 void 1405 encoder_dpms_set(uint8 crtcID, int mode) 1406 { 1407 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1408 1409 int index = -1; 1410 radeon_shared_info &info = *gInfo->shared_info; 1411 1412 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1413 memset(&args, 0, sizeof(args)); 1414 1415 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1416 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1417 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1418 1419 switch (encoderID) { 1420 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1421 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1422 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1423 break; 1424 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1425 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1426 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1427 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1428 encoder_dpms_set_dig(crtcID, mode); 1429 // We don't call OutputControl on DIG 1430 return; 1431 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1432 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1433 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1434 break; 1435 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1436 // TODO: encoder dpms set newer cards 1437 // If DCE5, dvo true 1438 // If DCE3, dig true 1439 // else... 1440 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1441 break; 1442 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1443 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1444 break; 1445 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1446 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1447 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1448 else 1449 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1450 break; 1451 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1452 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1453 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1454 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1455 else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1456 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1457 else 1458 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1459 break; 1460 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1461 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1462 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1463 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1464 else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1465 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1466 else 1467 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1468 break; 1469 } 1470 1471 switch (mode) { 1472 case B_DPMS_ON: 1473 args.ucAction = ATOM_ENABLE; 1474 break; 1475 case B_DPMS_STAND_BY: 1476 case B_DPMS_SUSPEND: 1477 case B_DPMS_OFF: 1478 args.ucAction = ATOM_DISABLE; 1479 break; 1480 } 1481 1482 if (index >= 0) { 1483 atom_execute_table(gAtomContext, index, (uint32*)&args); 1484 if (info.dceMajor < 5) { 1485 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1486 args.ucAction = args.ucAction == ATOM_DISABLE 1487 ? ATOM_LCD_BLOFF : ATOM_LCD_BLON; 1488 atom_execute_table(gAtomContext, index, (uint32*)&args); 1489 } 1490 encoder_dpms_scratch(crtcID, true); 1491 } 1492 } 1493 1494 /* TODO: I feel as though what is below may be incorrect... 1495 * AMD: the ext encoder will only show up in conjunction with an internal 1496 * encoder, the pipeline generally looks like crtc -> dvo -> ext encoder 1497 * or crtc -> uniphy -> ext encoder 1498 */ 1499 1500 if (encoder_is_external(encoderID)) 1501 encoder_dpms_set_external(crtcID, mode); 1502 } 1503 1504 1505 void 1506 encoder_dpms_set_dig(uint8 crtcID, int mode) 1507 { 1508 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1509 1510 radeon_shared_info &info = *gInfo->shared_info; 1511 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1512 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1513 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 1514 1515 switch (mode) { 1516 case B_DPMS_ON: 1517 if (info.chipsetID == RADEON_RV710 1518 || info.chipsetID == RADEON_RV730) { 1519 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1520 ATOM_TRANSMITTER_ACTION_ENABLE); 1521 } else { 1522 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1523 ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT); 1524 } 1525 if (connector_is_dp(connectorIndex)) { 1526 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) { 1527 ERROR("%s: TODO, edp_panel_power for this card!\n", 1528 __func__); 1529 // atombios_set_edp_panel_power(connector, 1530 // ATOM_TRANSMITTER_ACTION_POWER_ON); 1531 } 1532 if (info.dceMajor >= 4) { 1533 encoder_dig_setup(connectorIndex, pll->pixelClock, 1534 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1535 } 1536 // TODO: dp link train here 1537 //radeon_dp_link_train(encoder, connector); 1538 if (info.dceMajor >= 4) { 1539 encoder_dig_setup(connectorIndex, pll->pixelClock, 1540 ATOM_ENCODER_CMD_DP_VIDEO_ON); 1541 } 1542 } 1543 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1544 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1545 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON); 1546 } 1547 break; 1548 case B_DPMS_STAND_BY: 1549 case B_DPMS_SUSPEND: 1550 case B_DPMS_OFF: 1551 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1552 ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT); 1553 if (connector_is_dp(connectorIndex)) { 1554 if (info.dceMajor >= 4) { 1555 encoder_dig_setup(connectorIndex, pll->pixelClock, 1556 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1557 #if 0 1558 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 1559 atombios_set_edp_panel_power(connector, 1560 ATOM_TRANSMITTER_ACTION_POWER_OFF); 1561 radeon_dig_connector->edp_on = false; 1562 #endif 1563 } 1564 } 1565 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1566 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1567 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF); 1568 } 1569 break; 1570 } 1571 } 1572 1573 1574 void 1575 encoder_dpms_set_external(uint8 crtcID, int mode) 1576 { 1577 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1578 1579 radeon_shared_info &info = *gInfo->shared_info; 1580 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1581 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 1582 1583 switch (mode) { 1584 case B_DPMS_ON: 1585 if ((info.chipsetFlags & CHIP_APU) != 0) { 1586 encoder_external_setup(connectorIndex, pll->pixelClock, 1587 EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); 1588 encoder_external_setup(connectorIndex, pll->pixelClock, 1589 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); 1590 } else { 1591 encoder_external_setup(connectorIndex, pll->pixelClock, 1592 ATOM_ENABLE); 1593 } 1594 break; 1595 case B_DPMS_STAND_BY: 1596 case B_DPMS_SUSPEND: 1597 case B_DPMS_OFF: 1598 if ((info.chipsetFlags & CHIP_APU) != 0) { 1599 encoder_external_setup(connectorIndex, pll->pixelClock, 1600 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); 1601 encoder_external_setup(connectorIndex, pll->pixelClock, 1602 EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); 1603 } else { 1604 encoder_external_setup(connectorIndex, pll->pixelClock, 1605 ATOM_DISABLE); 1606 } 1607 break; 1608 } 1609 } 1610 1611 1612 void 1613 encoder_output_lock(bool lock) 1614 { 1615 TRACE("%s: %s\n", __func__, lock ? "true" : "false"); 1616 uint32 biosScratch6 = Read32(OUT, R600_BIOS_6_SCRATCH); 1617 1618 if (lock) { 1619 biosScratch6 |= ATOM_S6_CRITICAL_STATE; 1620 biosScratch6 &= ~ATOM_S6_ACC_MODE; 1621 } else { 1622 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE; 1623 biosScratch6 |= ATOM_S6_ACC_MODE; 1624 } 1625 1626 Write32(OUT, R600_BIOS_6_SCRATCH, biosScratch6); 1627 } 1628 1629 1630 static const char* encoder_name_matrix[36] = { 1631 "NONE", 1632 "Internal Radeon LVDS", 1633 "Internal Radeon TMDS1", 1634 "Internal Radeon TMDS2", 1635 "Internal Radeon DAC1", 1636 "Internal Radeon DAC2 (TV)", 1637 "Internal Radeon SDVOA", 1638 "Internal Radeon SDVOB", 1639 "External 3rd party SI170B", 1640 "External 3rd party CH7303", 1641 "External 3rd party CH7301", 1642 "Internal Radeon DVO1", 1643 "External 3rd party SDVOA", 1644 "External 3rd party SDVOB", 1645 "External 3rd party TITFP513", 1646 "Internal LVTM1", 1647 "External 3rd party VT1623", 1648 "External HDMI SI1930", 1649 "Internal HDMI", 1650 "Internal Kaleidoscope TMDS1", 1651 "Internal Kaleidoscope DVO1", 1652 "Internal Kaleidoscope DAC1", 1653 "Internal Kaleidoscope DAC2", 1654 "External Kaleidoscope SI178", 1655 "MVPU FPGA", 1656 "Internal Kaleidoscope DDI", 1657 "External Kaleidoscope VT1625", 1658 "External Kaleidoscope HDMI SI1932", 1659 "External Kaleidoscope DP AN9801", 1660 "External Kaleidoscope DP DP501", 1661 "Internal Kaleidoscope UNIPHY", 1662 "Internal Kaleidoscope LVTMA", 1663 "Internal Kaleidoscope UNIPHY1", 1664 "Internal Kaleidoscope UNIPHY2", 1665 "External Travis Bridge", 1666 "External Nutmeg Bridge" 1667 }; 1668 1669 1670 const char* 1671 encoder_name_lookup(uint32 encoderID) { 1672 if (encoderID <= sizeof(encoder_name_matrix)) 1673 return encoder_name_matrix[encoderID]; 1674 else 1675 return "Unknown"; 1676 } 1677 1678 1679 uint32 1680 encoder_object_lookup(uint32 encoderFlags, uint8 dacID) 1681 { 1682 // used on older cards to take a guess at the encoder 1683 // object 1684 1685 radeon_shared_info &info = *gInfo->shared_info; 1686 1687 uint32 ret = 0; 1688 1689 switch (encoderFlags) { 1690 case ATOM_DEVICE_CRT1_SUPPORT: 1691 case ATOM_DEVICE_TV1_SUPPORT: 1692 case ATOM_DEVICE_TV2_SUPPORT: 1693 case ATOM_DEVICE_CRT2_SUPPORT: 1694 case ATOM_DEVICE_CV_SUPPORT: 1695 switch (dacID) { 1696 case 1: 1697 if ((info.chipsetID == RADEON_RS400) 1698 || (info.chipsetID == RADEON_RS480)) 1699 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 1700 else if (info.chipsetID >= RADEON_RS600) 1701 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 1702 else 1703 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 1704 break; 1705 case 2: 1706 if (info.chipsetID >= RADEON_RS600) 1707 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 1708 else { 1709 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 1710 } 1711 break; 1712 case 3: // external dac 1713 if (info.chipsetID >= RADEON_RS600) 1714 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 1715 else 1716 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1717 break; 1718 } 1719 break; 1720 case ATOM_DEVICE_LCD1_SUPPORT: 1721 if (info.chipsetID >= RADEON_RS600) 1722 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 1723 else 1724 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 1725 break; 1726 case ATOM_DEVICE_DFP1_SUPPORT: 1727 if ((info.chipsetID == RADEON_RS400) 1728 || (info.chipsetID == RADEON_RS480)) 1729 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1730 else if (info.chipsetID >= RADEON_RS600) 1731 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 1732 else 1733 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 1734 break; 1735 case ATOM_DEVICE_LCD2_SUPPORT: 1736 case ATOM_DEVICE_DFP2_SUPPORT: 1737 if ((info.chipsetID == RADEON_RS600) 1738 || (info.chipsetID == RADEON_RS690) 1739 || (info.chipsetID == RADEON_RS740)) 1740 ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 1741 else if (info.chipsetID >= RADEON_RS600) 1742 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 1743 else 1744 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1745 break; 1746 case ATOM_DEVICE_DFP3_SUPPORT: 1747 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 1748 break; 1749 } 1750 1751 return ret; 1752 } 1753 1754 1755 uint32 1756 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags) 1757 { 1758 switch (encoderID) { 1759 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1760 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1761 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1762 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1763 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1764 return VIDEO_ENCODER_LVDS; 1765 else 1766 return VIDEO_ENCODER_TMDS; 1767 break; 1768 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1769 return VIDEO_ENCODER_DAC; 1770 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1771 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1772 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1773 return VIDEO_ENCODER_TVDAC; 1774 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1775 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1776 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1777 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1778 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1779 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1780 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1781 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1782 return VIDEO_ENCODER_LVDS; 1783 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1784 return VIDEO_ENCODER_DAC; 1785 else 1786 return VIDEO_ENCODER_TMDS; 1787 break; 1788 case ENCODER_OBJECT_ID_SI170B: 1789 case ENCODER_OBJECT_ID_CH7303: 1790 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 1791 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 1792 case ENCODER_OBJECT_ID_TITFP513: 1793 case ENCODER_OBJECT_ID_VT1623: 1794 case ENCODER_OBJECT_ID_HDMI_SI1930: 1795 case ENCODER_OBJECT_ID_TRAVIS: 1796 case ENCODER_OBJECT_ID_NUTMEG: 1797 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1798 return VIDEO_ENCODER_LVDS; 1799 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1800 return VIDEO_ENCODER_DAC; 1801 else 1802 return VIDEO_ENCODER_TMDS; 1803 break; 1804 } 1805 1806 return VIDEO_ENCODER_NONE; 1807 } 1808 1809 1810 bool 1811 encoder_is_external(uint32 encoderID) 1812 { 1813 switch (encoderID) { 1814 case ENCODER_OBJECT_ID_SI170B: 1815 case ENCODER_OBJECT_ID_CH7303: 1816 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 1817 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 1818 case ENCODER_OBJECT_ID_TITFP513: 1819 case ENCODER_OBJECT_ID_VT1623: 1820 case ENCODER_OBJECT_ID_HDMI_SI1930: 1821 case ENCODER_OBJECT_ID_TRAVIS: 1822 case ENCODER_OBJECT_ID_NUTMEG: 1823 return true; 1824 } 1825 1826 return false; 1827 } 1828 1829 1830 bool 1831 encoder_is_dp_bridge(uint32 encoderID) 1832 { 1833 switch (encoderID) { 1834 case ENCODER_OBJECT_ID_TRAVIS: 1835 case ENCODER_OBJECT_ID_NUTMEG: 1836 return true; 1837 } 1838 return false; 1839 } 1840