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