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