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 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 593 uint8 id[6]; 594 int bit; 595 for (bit = 0; bit < 6; bit++) 596 id[bit] = dpcd_reg_read(dp->auxPin, 0x503 + bit); 597 if (id[0] == 0x73 && id[1] == 0x69 && id[2] == 0x76 598 && id[3] == 0x61 && id[4] == 0x72 && id[5] == 0x54) { 599 panelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 600 } else { 601 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 602 } 603 } else { 604 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 605 } 606 } else 607 panelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 608 } 609 610 #if 0 611 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 612 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) { 613 uint8 temp = dpcd_read_reg(hwPin, DP_EDP_CONFIGURATION_CAP); 614 if ((temp & 1) != 0) 615 panelMode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 616 } 617 #endif 618 619 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 620 tableMajor, tableMinor); 621 622 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 623 uint8 dpClock = 0; 624 if (dpInfo->valid == true) 625 dpClock = dpInfo->linkRate; 626 627 bool dualLink = false; 628 if (connector->type == VIDEO_CONNECTOR_DVID 629 && pixelClock > 165000) { 630 // TODO: Expand on this 631 dualLink = true; 632 } 633 634 switch (tableMinor) { 635 case 1: 636 args.v1.ucAction = command; 637 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 638 639 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 640 args.v3.ucPanelMode = panelMode; 641 else { 642 args.v1.ucEncoderMode 643 = display_get_encoder_mode(connectorIndex); 644 } 645 646 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 647 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 648 args.v1.ucLaneNum = dpInfo->laneCount; 649 } else if (dualLink) 650 args.v1.ucLaneNum = 8; 651 else 652 args.v1.ucLaneNum = 4; 653 654 if ((args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 655 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) 656 && dpClock == 270000) { 657 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 658 } 659 660 switch (connector->encoder.objectID) { 661 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 662 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 663 break; 664 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 665 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 666 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 667 break; 668 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 669 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 670 break; 671 } 672 673 if (linkB) 674 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 675 else 676 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 677 break; 678 case 2: 679 case 3: 680 args.v3.ucAction = command; 681 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 682 683 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) 684 args.v3.ucPanelMode = panelMode; 685 else { 686 args.v3.ucEncoderMode 687 = display_get_encoder_mode(connectorIndex); 688 } 689 690 if (args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP 691 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 692 args.v3.ucLaneNum = dpInfo->laneCount; 693 } else if (dualLink) 694 args.v3.ucLaneNum = 8; 695 else 696 args.v3.ucLaneNum = 4; 697 698 if ((args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP 699 || args.v3.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) 700 && dpClock == 270000) { 701 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 702 } 703 704 args.v3.acConfig.ucDigSel = encoder_pick_dig(connectorIndex); 705 706 // TODO: get BPC 707 switch (8) { 708 case 0: 709 args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE; 710 break; 711 case 6: 712 args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR; 713 break; 714 case 8: 715 default: 716 args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; 717 break; 718 case 10: 719 args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR; 720 break; 721 case 12: 722 args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR; 723 break; 724 case 16: 725 args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR; 726 break; 727 } 728 break; 729 case 4: 730 args.v4.ucHPD_ID = 0; 731 ERROR("%s: tableMinor 4 TODO!\n", __func__); 732 break; 733 default: 734 ERROR("%s: unknown tableMinor!\n", __func__); 735 } 736 737 status_t result = atom_execute_table(gAtomContext, index, (uint32*)&args); 738 739 #if 0 740 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP 741 && panelMode == DP_PANEL_MODE_INTERNAL_DP2_MODE) { 742 dpcd_write_reg(hwPin, DP_EDP_CONFIGURATION_SET, 1); 743 } 744 #endif 745 746 return result; 747 } 748 749 750 status_t 751 encoder_external_setup(uint32 connectorIndex, int command) 752 { 753 TRACE("%s\n", __func__); 754 755 encoder_info* encoder 756 = &gConnector[connectorIndex]->encoder; 757 encoder_info* extEncoder 758 = &gConnector[connectorIndex]->encoderExternal; 759 760 dp_info* dpInfo 761 = &gConnector[connectorIndex]->dpInfo; 762 763 if (extEncoder->valid != true) { 764 ERROR("%s: connector %" B_PRIu32 " doesn't have a valid " 765 "external encoder!", __func__, connectorIndex); 766 return B_ERROR; 767 } 768 769 uint8 tableMajor; 770 uint8 tableMinor; 771 772 int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); 773 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 774 != B_OK) { 775 ERROR("%s: Error parsing ExternalEncoderControl table\n", __func__); 776 return B_ERROR; 777 } 778 779 // Prepare AtomBIOS command arguments 780 union externalEncoderControl { 781 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; 782 EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; 783 }; 784 union externalEncoderControl args; 785 memset(&args, 0, sizeof(args)); 786 787 int connectorObjectID 788 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 789 >> OBJECT_ID_SHIFT; 790 791 uint32 pixelClock = encoder->pll.pixelClock; 792 793 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 794 tableMajor, tableMinor); 795 switch (tableMajor) { 796 case 1: 797 // no options needed on table 1.x 798 break; 799 case 2: 800 switch (tableMinor) { 801 case 1: 802 case 2: 803 args.v1.sDigEncoder.ucAction = command; 804 args.v1.sDigEncoder.usPixelClock 805 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 806 args.v1.sDigEncoder.ucEncoderMode 807 = display_get_encoder_mode(connectorIndex); 808 809 if (connector_is_dp(connectorIndex)) { 810 if (dpInfo->linkRate == 270000) { 811 args.v1.sDigEncoder.ucConfig 812 |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 813 } 814 args.v1.sDigEncoder.ucLaneNum 815 = dpInfo->laneCount; 816 } else if (pixelClock > 165000) { 817 args.v1.sDigEncoder.ucLaneNum = 8; 818 } else { 819 args.v1.sDigEncoder.ucLaneNum = 4; 820 } 821 break; 822 case 3: 823 { 824 args.v3.sExtEncoder.ucAction = command; 825 if (command == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) { 826 args.v3.sExtEncoder.usConnectorId 827 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 828 } else { 829 args.v3.sExtEncoder.usPixelClock 830 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 831 } 832 833 args.v3.sExtEncoder.ucEncoderMode 834 = display_get_encoder_mode(connectorIndex); 835 836 if (connector_is_dp(connectorIndex)) { 837 if (dpInfo->linkRate == 270000) { 838 args.v3.sExtEncoder.ucConfig 839 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 840 } else if (dpInfo->linkRate == 540000) { 841 args.v3.sExtEncoder.ucConfig 842 |=EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; 843 } 844 args.v1.sDigEncoder.ucLaneNum 845 = dpInfo->laneCount; 846 } else if (pixelClock > 165000) { 847 args.v3.sExtEncoder.ucLaneNum = 8; 848 } else { 849 args.v3.sExtEncoder.ucLaneNum = 4; 850 } 851 852 uint16 extEncoderFlags = extEncoder->flags; 853 854 switch ((extEncoderFlags & ENUM_ID_MASK) >> ENUM_ID_SHIFT) { 855 case GRAPH_OBJECT_ENUM_ID1: 856 TRACE("%s: external encoder 1\n", __func__); 857 args.v3.sExtEncoder.ucConfig 858 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; 859 break; 860 case GRAPH_OBJECT_ENUM_ID2: 861 TRACE("%s: external encoder 2\n", __func__); 862 args.v3.sExtEncoder.ucConfig 863 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; 864 break; 865 case GRAPH_OBJECT_ENUM_ID3: 866 TRACE("%s: external encoder 3\n", __func__); 867 args.v3.sExtEncoder.ucConfig 868 |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; 869 break; 870 } 871 872 // TODO: don't set statically 873 uint32 bitsPerColor = 8; 874 switch (bitsPerColor) { 875 case 0: 876 args.v3.sExtEncoder.ucBitPerColor 877 = PANEL_BPC_UNDEFINE; 878 break; 879 case 6: 880 args.v3.sExtEncoder.ucBitPerColor 881 = PANEL_6BIT_PER_COLOR; 882 break; 883 case 8: 884 default: 885 args.v3.sExtEncoder.ucBitPerColor 886 = PANEL_8BIT_PER_COLOR; 887 break; 888 case 10: 889 args.v3.sExtEncoder.ucBitPerColor 890 = PANEL_10BIT_PER_COLOR; 891 break; 892 case 12: 893 args.v3.sExtEncoder.ucBitPerColor 894 = PANEL_12BIT_PER_COLOR; 895 break; 896 case 16: 897 args.v3.sExtEncoder.ucBitPerColor 898 = PANEL_16BIT_PER_COLOR; 899 break; 900 } 901 break; 902 } 903 default: 904 ERROR("%s: Unknown table minor version: " 905 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 906 tableMajor, tableMinor); 907 return B_ERROR; 908 } 909 break; 910 default: 911 ERROR("%s: Unknown table major version: " 912 "%" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 913 tableMajor, tableMinor); 914 return B_ERROR; 915 } 916 917 return atom_execute_table(gAtomContext, index, (uint32*)&args); 918 } 919 920 921 status_t 922 encoder_analog_setup(uint32 connectorIndex, uint32 pixelClock, int command) 923 { 924 TRACE("%s\n", __func__); 925 926 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 927 928 int index = 0; 929 DAC_ENCODER_CONTROL_PS_ALLOCATION args; 930 memset(&args, 0, sizeof(args)); 931 932 switch (gConnector[connectorIndex]->encoder.objectID) { 933 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 934 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 935 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 936 break; 937 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 938 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 939 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 940 break; 941 } 942 943 args.ucAction = command; 944 945 if ((encoderFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 946 args.ucDacStandard = ATOM_DAC1_PS2; 947 else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 948 args.ucDacStandard = ATOM_DAC1_CV; 949 else { 950 TRACE("%s: TODO, hardcoded NTSC TV support\n", __func__); 951 if (1) { 952 // NTSC, NTSC_J, PAL 60 953 args.ucDacStandard = ATOM_DAC1_NTSC; 954 } else { 955 // PAL, SCART. SECAM, PAL_CN 956 args.ucDacStandard = ATOM_DAC1_PAL; 957 } 958 } 959 960 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 961 962 return atom_execute_table(gAtomContext, index, (uint32*)&args); 963 } 964 965 966 bool 967 encoder_analog_load_detect(uint32 connectorIndex) 968 { 969 TRACE("%s\n", __func__); 970 971 if (gConnector[connectorIndex]->encoderExternal.valid == true) 972 return encoder_dig_load_detect(connectorIndex); 973 974 return encoder_dac_load_detect(connectorIndex); 975 } 976 977 978 bool 979 encoder_dac_load_detect(uint32 connectorIndex) 980 { 981 TRACE("%s\n", __func__); 982 983 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 984 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 985 986 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0 987 && (encoderFlags & ATOM_DEVICE_CV_SUPPORT) == 0 988 && (encoderFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) { 989 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n", 990 __func__, connectorIndex); 991 return false; 992 } 993 994 // *** tell the card we want to do a DAC detection 995 996 DAC_LOAD_DETECTION_PS_ALLOCATION args; 997 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 998 uint8 tableMajor; 999 uint8 tableMinor; 1000 1001 memset(&args, 0, sizeof(args)); 1002 1003 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 1004 != B_OK) { 1005 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n", 1006 __func__); 1007 return false; 1008 } 1009 1010 args.sDacload.ucMisc = 0; 1011 1012 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1 1013 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) { 1014 args.sDacload.ucDacType = ATOM_DAC_A; 1015 } else { 1016 args.sDacload.ucDacType = ATOM_DAC_B; 1017 } 1018 1019 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1020 args.sDacload.usDeviceID 1021 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT); 1022 atom_execute_table(gAtomContext, index, (uint32*)&args); 1023 1024 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1025 1026 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 1027 return true; 1028 1029 } else if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1030 args.sDacload.usDeviceID 1031 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT); 1032 atom_execute_table(gAtomContext, index, (uint32*)&args); 1033 1034 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1035 1036 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 1037 return true; 1038 1039 } else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1040 args.sDacload.usDeviceID 1041 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT); 1042 if (tableMinor >= 3) 1043 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1044 atom_execute_table(gAtomContext, index, (uint32*)&args); 1045 1046 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1047 1048 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 1049 return true; 1050 1051 } else if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1052 args.sDacload.usDeviceID 1053 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT); 1054 if (tableMinor >= 3) 1055 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 1056 atom_execute_table(gAtomContext, index, (uint32*)&args); 1057 1058 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1059 1060 if ((biosScratch0 1061 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) { 1062 return true; /* Composite connected */ 1063 } else if ((biosScratch0 1064 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) { 1065 return true; /* S-Video connected */ 1066 } 1067 1068 } 1069 return false; 1070 } 1071 1072 1073 bool 1074 encoder_dig_load_detect(uint32 connectorIndex) 1075 { 1076 TRACE("%s\n", __func__); 1077 radeon_shared_info &info = *gInfo->shared_info; 1078 1079 if (info.dceMajor < 4) { 1080 ERROR("%s: Strange: External DIG encoder on DCE < 4?\n", __func__); 1081 return false; 1082 } 1083 1084 encoder_external_setup(connectorIndex, 1085 EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); 1086 1087 uint32 biosScratch0 = Read32(OUT, R600_SCRATCH_REG0); 1088 1089 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1090 1091 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) 1092 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 1093 return true; 1094 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) 1095 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 1096 return true; 1097 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1098 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 1099 return true; 1100 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1101 if ((biosScratch0 1102 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) 1103 return true; /* Composite connected */ 1104 else if ((biosScratch0 1105 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) 1106 return true; /* S-Video connected */ 1107 } 1108 1109 return false; 1110 } 1111 1112 1113 status_t 1114 transmitter_dig_setup(uint32 connectorIndex, uint32 pixelClock, 1115 uint8 laneNumber, uint8 laneSet, int command) 1116 { 1117 TRACE("%s\n", __func__); 1118 1119 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1120 int index; 1121 switch (encoderID) { 1122 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1123 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1124 break; 1125 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1126 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1127 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1128 index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); 1129 break; 1130 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1131 index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); 1132 break; 1133 default: 1134 ERROR("%s: BUG: dig setup run on non-dig encoder!\n", __func__); 1135 return B_ERROR; 1136 } 1137 1138 if (index < 0) { 1139 ERROR("%s: GetIndexIntoMasterTable failed!\n", __func__); 1140 return B_ERROR; 1141 } 1142 1143 uint8 tableMajor; 1144 uint8 tableMinor; 1145 1146 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 1147 != B_OK) 1148 return B_ERROR; 1149 1150 // Prepare AtomBIOS arguments 1151 union digTransmitterControl { 1152 DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; 1153 DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; 1154 DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3; 1155 DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4; 1156 }; 1157 union digTransmitterControl args; 1158 memset(&args, 0, sizeof(args)); 1159 1160 TRACE("%s: table %" B_PRIu8 ".%" B_PRIu8 "\n", __func__, 1161 tableMajor, tableMinor); 1162 1163 int connectorObjectID 1164 = (gConnector[connectorIndex]->objectID & OBJECT_ID_MASK) 1165 >> OBJECT_ID_SHIFT; 1166 uint32 encoderObjectID = gConnector[connectorIndex]->encoder.objectID; 1167 uint32 digEncoderID = encoder_pick_dig(connectorIndex); 1168 1169 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 1170 1171 bool isDP = connector_is_dp(connectorIndex); 1172 bool linkB = gConnector[connectorIndex]->encoderExternal.linkEnumeration 1173 == GRAPH_OBJECT_ENUM_ID2 ? true : false; 1174 1175 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 1176 1177 uint8 dpClock = 0; 1178 int dpLaneCount = 0; 1179 if (dpInfo->valid == true) { 1180 dpClock = dpInfo->linkRate; 1181 dpLaneCount = dpInfo->laneCount; 1182 } 1183 1184 switch (tableMajor) { 1185 case 1: 1186 switch (tableMinor) { 1187 case 1: 1188 args.v1.ucAction = command; 1189 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1190 args.v1.usInitInfo 1191 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1192 } else if (command 1193 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1194 args.v1.asMode.ucLaneSel = laneNumber; 1195 args.v1.asMode.ucLaneSet = laneSet; 1196 } else { 1197 if (isDP) { 1198 args.v1.usPixelClock 1199 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1200 } else if (pixelClock > 165000) { 1201 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1202 (pixelClock / 2) / 10); 1203 } else { 1204 args.v1.usPixelClock 1205 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1206 } 1207 } 1208 1209 args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; 1210 1211 if (digEncoderID > 0) { 1212 args.v1.ucConfig 1213 |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; 1214 } else { 1215 args.v1.ucConfig 1216 |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; 1217 } 1218 1219 // TODO: IGP DIG Transmitter setup 1220 #if 0 1221 if ((rdev->flags & RADEON_IS_IGP) && (encoderObjectID 1222 == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { 1223 if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { 1224 if (igp_lane_info & 0x1) 1225 args.v1.ucConfig 1226 |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; 1227 else if (igp_lane_info & 0x2) 1228 args.v1.ucConfig 1229 |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; 1230 else if (igp_lane_info & 0x4) 1231 args.v1.ucConfig 1232 |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; 1233 else if (igp_lane_info & 0x8) 1234 args.v1.ucConfig 1235 |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; 1236 } else { 1237 if (igp_lane_info & 0x3) 1238 args.v1.ucConfig 1239 |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; 1240 else if (igp_lane_info & 0xc) 1241 args.v1.ucConfig 1242 |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; 1243 } 1244 } 1245 #endif 1246 1247 if (linkB == true) 1248 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; 1249 else 1250 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 1251 1252 if (isDP) 1253 args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1254 else if ((gConnector[connectorIndex]->encoder.flags 1255 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1256 if (1) { 1257 // if coherentMode, i've only ever seen it true 1258 args.v1.ucConfig 1259 |= ATOM_TRANSMITTER_CONFIG_COHERENT; 1260 } 1261 if (pixelClock > 165000) { 1262 args.v1.ucConfig 1263 |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; 1264 } 1265 } 1266 break; 1267 case 2: 1268 args.v2.ucAction = command; 1269 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1270 args.v2.usInitInfo 1271 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1272 } else if (command 1273 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1274 args.v2.asMode.ucLaneSel = laneNumber; 1275 args.v2.asMode.ucLaneSet = laneSet; 1276 } else { 1277 if (isDP) { 1278 args.v2.usPixelClock 1279 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1280 } else if (pixelClock > 165000) { 1281 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1282 (pixelClock / 2) / 10); 1283 } else { 1284 args.v2.usPixelClock 1285 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1286 } 1287 } 1288 args.v2.acConfig.ucEncoderSel = digEncoderID; 1289 if (linkB) 1290 args.v2.acConfig.ucLinkSel = 1; 1291 1292 switch (encoderObjectID) { 1293 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1294 args.v2.acConfig.ucTransmitterSel = 0; 1295 break; 1296 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1297 args.v2.acConfig.ucTransmitterSel = 1; 1298 break; 1299 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1300 args.v2.acConfig.ucTransmitterSel = 2; 1301 break; 1302 } 1303 1304 if (isDP) { 1305 args.v2.acConfig.fCoherentMode = 1; 1306 args.v2.acConfig.fDPConnector = 1; 1307 } else if ((gConnector[connectorIndex]->encoder.flags 1308 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1309 if (1) { 1310 // if coherentMode, i've only ever seen it true 1311 args.v2.acConfig.fCoherentMode = 1; 1312 } 1313 1314 if (pixelClock > 165000) 1315 args.v2.acConfig.fDualLinkConnector = 1; 1316 } 1317 break; 1318 case 3: 1319 args.v3.ucAction = command; 1320 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1321 args.v3.usInitInfo 1322 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1323 } else if (command 1324 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1325 args.v3.asMode.ucLaneSel = laneNumber; 1326 args.v3.asMode.ucLaneSet = laneSet; 1327 } else { 1328 if (isDP) { 1329 args.v3.usPixelClock 1330 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1331 } else if (pixelClock > 165000) { 1332 args.v3.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1333 (pixelClock / 2) / 10); 1334 } else { 1335 args.v3.usPixelClock 1336 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1337 } 1338 } 1339 1340 if (isDP) 1341 args.v3.ucLaneNum = dpLaneCount; 1342 else if (pixelClock > 165000) 1343 args.v3.ucLaneNum = 8; 1344 else 1345 args.v3.ucLaneNum = 4; 1346 1347 if (linkB == true) 1348 args.v3.acConfig.ucLinkSel = 1; 1349 if (digEncoderID & 1) 1350 args.v3.acConfig.ucEncoderSel = 1; 1351 1352 // Select the PLL for the PHY 1353 // DP PHY to be clocked from external src if possible 1354 if (isDP && gInfo->dpExternalClock) { 1355 // use external clock source 1356 args.v3.acConfig.ucRefClkSource = ATOM_DCPLL; 1357 } else 1358 args.v3.acConfig.ucRefClkSource = pll->id; 1359 1360 switch (encoderObjectID) { 1361 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1362 args.v3.acConfig.ucTransmitterSel = 0; 1363 break; 1364 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1365 args.v3.acConfig.ucTransmitterSel = 1; 1366 break; 1367 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1368 args.v3.acConfig.ucTransmitterSel = 2; 1369 break; 1370 } 1371 1372 if (isDP) 1373 args.v3.acConfig.fCoherentMode = 1; 1374 else if ((gConnector[connectorIndex]->encoder.flags 1375 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1376 if (1) { 1377 // if coherentMode, i've only ever seen it true 1378 args.v3.acConfig.fCoherentMode = 1; 1379 } 1380 if (pixelClock > 165000) 1381 args.v3.acConfig.fDualLinkConnector = 1; 1382 } 1383 break; 1384 case 4: 1385 args.v4.ucAction = command; 1386 if (command == ATOM_TRANSMITTER_ACTION_INIT) { 1387 args.v4.usInitInfo 1388 = B_HOST_TO_LENDIAN_INT16(connectorObjectID); 1389 } else if (command 1390 == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { 1391 args.v4.asMode.ucLaneSel = laneNumber; 1392 args.v4.asMode.ucLaneSet = laneSet; 1393 } else { 1394 if (isDP) { 1395 args.v4.usPixelClock 1396 = B_HOST_TO_LENDIAN_INT16(dpClock / 10); 1397 } else if (pixelClock > 165000) { 1398 args.v4.usPixelClock = B_HOST_TO_LENDIAN_INT16( 1399 (pixelClock / 2) / 10); 1400 } else { 1401 args.v4.usPixelClock 1402 = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 1403 } 1404 } 1405 1406 if (isDP) 1407 args.v4.ucLaneNum = dpLaneCount; 1408 else if (pixelClock > 165000) 1409 args.v4.ucLaneNum = 8; 1410 else 1411 args.v4.ucLaneNum = 4; 1412 1413 if (linkB == true) 1414 args.v4.acConfig.ucLinkSel = 1; 1415 if (digEncoderID & 1) 1416 args.v4.acConfig.ucEncoderSel = 1; 1417 1418 // Select the PLL for the PHY 1419 // DP PHY to be clocked from external src if possible 1420 if (isDP) { 1421 if (gInfo->dpExternalClock > 0) { 1422 args.v4.acConfig.ucRefClkSource 1423 = ENCODER_REFCLK_SRC_EXTCLK; 1424 } else { 1425 args.v4.acConfig.ucRefClkSource 1426 = ENCODER_REFCLK_SRC_DCPLL; 1427 } 1428 } else 1429 args.v4.acConfig.ucRefClkSource = pll->id; 1430 1431 switch (encoderObjectID) { 1432 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1433 args.v4.acConfig.ucTransmitterSel = 0; 1434 break; 1435 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1436 args.v4.acConfig.ucTransmitterSel = 1; 1437 break; 1438 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1439 args.v4.acConfig.ucTransmitterSel = 2; 1440 break; 1441 } 1442 1443 if (isDP) 1444 args.v4.acConfig.fCoherentMode = 1; 1445 else if ((gConnector[connectorIndex]->encoder.flags 1446 & ATOM_DEVICE_DFP_SUPPORT) != 0) { 1447 if (1) { 1448 // if coherentMode, i've only ever seen it true 1449 args.v4.acConfig.fCoherentMode = 1; 1450 } 1451 if (pixelClock > 165000) 1452 args.v4.acConfig.fDualLinkConnector = 1; 1453 } 1454 break; 1455 default: 1456 ERROR("%s: unknown table version\n", __func__); 1457 } 1458 break; 1459 default: 1460 ERROR("%s: unknown table version\n", __func__); 1461 } 1462 1463 return atom_execute_table(gAtomContext, index, (uint32*)&args); 1464 } 1465 1466 1467 void 1468 encoder_crtc_scratch(uint8 crtcID) 1469 { 1470 TRACE("%s\n", __func__); 1471 1472 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1473 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1474 1475 // TODO: r500 1476 uint32 biosScratch3 = Read32(OUT, R600_SCRATCH_REG3); 1477 1478 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1479 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE; 1480 biosScratch3 |= (crtcID << 18); 1481 } 1482 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1483 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE; 1484 biosScratch3 |= (crtcID << 24); 1485 } 1486 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1487 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 1488 biosScratch3 |= (crtcID << 16); 1489 } 1490 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1491 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 1492 biosScratch3 |= (crtcID << 20); 1493 } 1494 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1495 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 1496 biosScratch3 |= (crtcID << 17); 1497 } 1498 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1499 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 1500 biosScratch3 |= (crtcID << 19); 1501 } 1502 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1503 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 1504 biosScratch3 |= (crtcID << 23); 1505 } 1506 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1507 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 1508 biosScratch3 |= (crtcID << 25); 1509 } 1510 1511 // TODO: r500 1512 Write32(OUT, R600_SCRATCH_REG3, biosScratch3); 1513 } 1514 1515 1516 void 1517 encoder_dpms_scratch(uint8 crtcID, bool power) 1518 { 1519 TRACE("%s\n", __func__); 1520 1521 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1522 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1523 1524 // TODO: r500 1525 uint32 biosScratch2 = Read32(OUT, R600_SCRATCH_REG2); 1526 1527 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 1528 if (power == true) 1529 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE; 1530 else 1531 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE; 1532 } 1533 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 1534 if (power == true) 1535 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE; 1536 else 1537 biosScratch2 |= ATOM_S2_CV_DPMS_STATE; 1538 } 1539 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 1540 if (power == true) 1541 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE; 1542 else 1543 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE; 1544 } 1545 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 1546 if (power == true) 1547 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE; 1548 else 1549 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE; 1550 } 1551 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 1552 if (power == true) 1553 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE; 1554 else 1555 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE; 1556 } 1557 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 1558 if (power == true) 1559 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE; 1560 else 1561 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE; 1562 } 1563 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 1564 if (power == true) 1565 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE; 1566 else 1567 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE; 1568 } 1569 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 1570 if (power == true) 1571 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE; 1572 else 1573 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE; 1574 } 1575 if ((encoderFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) { 1576 if (power == true) 1577 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE; 1578 else 1579 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE; 1580 } 1581 if ((encoderFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) { 1582 if (power == true) 1583 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE; 1584 else 1585 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE; 1586 } 1587 Write32(OUT, R600_SCRATCH_REG2, biosScratch2); 1588 } 1589 1590 1591 void 1592 encoder_dpms_set(uint8 crtcID, int mode) 1593 { 1594 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1595 1596 int index = -1; 1597 radeon_shared_info &info = *gInfo->shared_info; 1598 1599 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 1600 memset(&args, 0, sizeof(args)); 1601 1602 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1603 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1604 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 1605 1606 switch (encoderID) { 1607 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1608 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1609 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 1610 break; 1611 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1612 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1613 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1614 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1615 encoder_dpms_set_dig(crtcID, mode); 1616 break; 1617 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1618 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1619 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1620 break; 1621 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1622 if (info.dceMajor >= 5) 1623 encoder_dpms_set_dvo(crtcID, mode); 1624 else if (info.dceMajor >= 3) 1625 encoder_dpms_set_dig(crtcID, mode); 1626 else 1627 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 1628 break; 1629 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1630 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1631 break; 1632 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1633 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1634 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 1635 else 1636 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 1637 break; 1638 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1639 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1640 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1641 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1642 else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1643 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1644 else 1645 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 1646 break; 1647 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1648 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1649 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) 1650 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 1651 else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 1652 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 1653 else 1654 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 1655 break; 1656 // default, none on purpose 1657 } 1658 1659 // If we have an index, we need to execute a table. 1660 if (index >= 0) { 1661 switch (mode) { 1662 case B_DPMS_ON: 1663 args.ucAction = ATOM_ENABLE; 1664 break; 1665 case B_DPMS_STAND_BY: 1666 case B_DPMS_SUSPEND: 1667 case B_DPMS_OFF: 1668 args.ucAction = ATOM_DISABLE; 1669 break; 1670 } 1671 1672 atom_execute_table(gAtomContext, index, (uint32*)&args); 1673 if (info.dceMajor < 5) { 1674 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1675 args.ucAction = args.ucAction == ATOM_DISABLE 1676 ? ATOM_LCD_BLOFF : ATOM_LCD_BLON; 1677 atom_execute_table(gAtomContext, index, (uint32*)&args); 1678 } 1679 encoder_dpms_scratch(crtcID, true); 1680 } 1681 } 1682 1683 // If an external encoder exists, we should flip it on as well 1684 if (gConnector[connectorIndex]->encoderExternal.valid == true) 1685 encoder_dpms_set_external(crtcID, mode); 1686 } 1687 1688 1689 void 1690 encoder_dpms_set_dig(uint8 crtcID, int mode) 1691 { 1692 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1693 1694 radeon_shared_info &info = *gInfo->shared_info; 1695 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1696 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 1697 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 1698 1699 switch (mode) { 1700 case B_DPMS_ON: 1701 if (info.chipsetID == RADEON_RV710 1702 || info.chipsetID == RADEON_RV730 1703 || (info.chipsetFlags & CHIP_APU) != 0 1704 || info.dceMajor >= 5) { 1705 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1706 ATOM_TRANSMITTER_ACTION_ENABLE); 1707 } else { 1708 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1709 ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT); 1710 } 1711 if (connector_is_dp(connectorIndex)) { 1712 if (gConnector[connectorIndex]->type == VIDEO_CONNECTOR_EDP) { 1713 ERROR("%s: TODO, edp_panel_power for this card!\n", 1714 __func__); 1715 // atombios_set_edp_panel_power(connector, 1716 // ATOM_TRANSMITTER_ACTION_POWER_ON); 1717 } 1718 if (info.dceMajor >= 4) { 1719 encoder_dig_setup(connectorIndex, pll->pixelClock, 1720 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1721 } 1722 // TODO: dp link train here 1723 //radeon_dp_link_train(encoder, connector); 1724 if (info.dceMajor >= 4) { 1725 encoder_dig_setup(connectorIndex, pll->pixelClock, 1726 ATOM_ENCODER_CMD_DP_VIDEO_ON); 1727 } 1728 } 1729 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1730 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1731 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLON); 1732 } 1733 break; 1734 case B_DPMS_STAND_BY: 1735 case B_DPMS_SUSPEND: 1736 case B_DPMS_OFF: 1737 if ((info.chipsetFlags & CHIP_APU) != 0 || info.dceMajor >= 5) { 1738 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1739 ATOM_TRANSMITTER_ACTION_DISABLE); 1740 } else { 1741 transmitter_dig_setup(connectorIndex, pll->pixelClock, 0, 0, 1742 ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT); 1743 } 1744 if (connector_is_dp(connectorIndex)) { 1745 if (info.dceMajor >= 4) { 1746 encoder_dig_setup(connectorIndex, pll->pixelClock, 1747 ATOM_ENCODER_CMD_DP_VIDEO_OFF); 1748 #if 0 1749 if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 1750 atombios_set_edp_panel_power(connector, 1751 ATOM_TRANSMITTER_ACTION_POWER_OFF); 1752 radeon_dig_connector->edp_on = false; 1753 #endif 1754 } 1755 } 1756 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 1757 transmitter_dig_setup(connectorIndex, pll->pixelClock, 1758 0, 0, ATOM_TRANSMITTER_ACTION_LCD_BLOFF); 1759 } 1760 break; 1761 } 1762 } 1763 1764 1765 void 1766 encoder_dpms_set_external(uint8 crtcID, int mode) 1767 { 1768 TRACE("%s: power: %s\n", __func__, mode == B_DPMS_ON ? "true" : "false"); 1769 1770 radeon_shared_info &info = *gInfo->shared_info; 1771 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 1772 1773 switch (mode) { 1774 case B_DPMS_ON: 1775 if ((info.chipsetFlags & CHIP_APU) != 0) { 1776 encoder_external_setup(connectorIndex, 1777 EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); 1778 encoder_external_setup(connectorIndex, 1779 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); 1780 } else 1781 encoder_external_setup(connectorIndex, ATOM_ENABLE); 1782 1783 break; 1784 case B_DPMS_STAND_BY: 1785 case B_DPMS_SUSPEND: 1786 case B_DPMS_OFF: 1787 if ((info.chipsetFlags & CHIP_APU) != 0) { 1788 encoder_external_setup(connectorIndex, 1789 EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); 1790 encoder_external_setup(connectorIndex, 1791 EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); 1792 } else 1793 encoder_external_setup(connectorIndex, ATOM_DISABLE); 1794 1795 break; 1796 } 1797 } 1798 1799 1800 void 1801 encoder_dpms_set_dvo(uint8 crtcID, int mode) 1802 { 1803 ERROR("%s: TODO, dvo encoder dpms stub\n", __func__); 1804 } 1805 1806 1807 void 1808 encoder_output_lock(bool lock) 1809 { 1810 TRACE("%s: %s\n", __func__, lock ? "true" : "false"); 1811 uint32 biosScratch6 = Read32(OUT, R600_SCRATCH_REG6); 1812 1813 if (lock) { 1814 biosScratch6 |= ATOM_S6_CRITICAL_STATE; 1815 biosScratch6 &= ~ATOM_S6_ACC_MODE; 1816 } else { 1817 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE; 1818 biosScratch6 |= ATOM_S6_ACC_MODE; 1819 } 1820 1821 Write32(OUT, R600_SCRATCH_REG6, biosScratch6); 1822 } 1823 1824 1825 static const char* encoder_name_matrix[37] = { 1826 "NONE", 1827 "Internal Radeon LVDS", 1828 "Internal Radeon TMDS1", 1829 "Internal Radeon TMDS2", 1830 "Internal Radeon DAC1", 1831 "Internal Radeon DAC2 (TV)", 1832 "Internal Radeon SDVOA", 1833 "Internal Radeon SDVOB", 1834 "External 3rd party SI170B", 1835 "External 3rd party CH7303", 1836 "External 3rd party CH7301", 1837 "Internal Radeon DVO1", 1838 "External 3rd party SDVOA", 1839 "External 3rd party SDVOB", 1840 "External 3rd party TITFP513", 1841 "Internal LVTM1", 1842 "External 3rd party VT1623", 1843 "External HDMI SI1930", 1844 "Internal HDMI", 1845 "Internal Kaleidoscope TMDS1", 1846 "Internal Kaleidoscope DVO1", 1847 "Internal Kaleidoscope DAC1", 1848 "Internal Kaleidoscope DAC2", 1849 "External Kaleidoscope SI178", 1850 "MVPU FPGA", 1851 "Internal Kaleidoscope DDI", 1852 "External Kaleidoscope VT1625", 1853 "External Kaleidoscope HDMI SI1932", 1854 "External Kaleidoscope DP AN9801", 1855 "External Kaleidoscope DP DP501", 1856 "Internal Kaleidoscope UNIPHY", 1857 "Internal Kaleidoscope LVTMA", 1858 "Internal Kaleidoscope UNIPHY1", 1859 "Internal Kaleidoscope UNIPHY2", 1860 "External Nutmeg Bridge", 1861 "External Travis Bridge", 1862 "Internal Kaleidoscope VCE" 1863 }; 1864 1865 1866 const char* 1867 encoder_name_lookup(uint32 encoderID) { 1868 if (encoderID <= sizeof(encoder_name_matrix)) 1869 return encoder_name_matrix[encoderID]; 1870 else 1871 return "Unknown"; 1872 } 1873 1874 1875 uint32 1876 encoder_object_lookup(uint32 encoderFlags, uint8 dacID) 1877 { 1878 // used on older cards to take a guess at the encoder 1879 // object 1880 1881 radeon_shared_info &info = *gInfo->shared_info; 1882 1883 uint32 ret = 0; 1884 1885 switch (encoderFlags) { 1886 case ATOM_DEVICE_CRT1_SUPPORT: 1887 case ATOM_DEVICE_TV1_SUPPORT: 1888 case ATOM_DEVICE_TV2_SUPPORT: 1889 case ATOM_DEVICE_CRT2_SUPPORT: 1890 case ATOM_DEVICE_CV_SUPPORT: 1891 switch (dacID) { 1892 case 1: 1893 if ((info.chipsetID == RADEON_RS400) 1894 || (info.chipsetID == RADEON_RS480)) 1895 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 1896 else if (info.chipsetID >= RADEON_RS600) 1897 ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; 1898 else 1899 ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; 1900 break; 1901 case 2: 1902 if (info.chipsetID >= RADEON_RS600) 1903 ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; 1904 else { 1905 ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; 1906 } 1907 break; 1908 case 3: // external dac 1909 if (info.chipsetID >= RADEON_RS600) 1910 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 1911 else 1912 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1913 break; 1914 } 1915 break; 1916 case ATOM_DEVICE_LCD1_SUPPORT: 1917 if (info.chipsetID >= RADEON_RS600) 1918 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 1919 else 1920 ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; 1921 break; 1922 case ATOM_DEVICE_DFP1_SUPPORT: 1923 if ((info.chipsetID == RADEON_RS400) 1924 || (info.chipsetID == RADEON_RS480)) 1925 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1926 else if (info.chipsetID >= RADEON_RS600) 1927 ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; 1928 else 1929 ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; 1930 break; 1931 case ATOM_DEVICE_LCD2_SUPPORT: 1932 case ATOM_DEVICE_DFP2_SUPPORT: 1933 if ((info.chipsetID == RADEON_RS600) 1934 || (info.chipsetID == RADEON_RS690) 1935 || (info.chipsetID == RADEON_RS740)) 1936 ret = ENCODER_INTERNAL_DDI_ENUM_ID1; 1937 else if (info.chipsetID >= RADEON_RS600) 1938 ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; 1939 else 1940 ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; 1941 break; 1942 case ATOM_DEVICE_DFP3_SUPPORT: 1943 ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; 1944 break; 1945 } 1946 1947 return ret; 1948 } 1949 1950 1951 uint32 1952 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags) 1953 { 1954 switch (encoderID) { 1955 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 1956 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 1957 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 1958 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 1959 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1960 return VIDEO_ENCODER_LVDS; 1961 else 1962 return VIDEO_ENCODER_TMDS; 1963 break; 1964 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 1965 return VIDEO_ENCODER_DAC; 1966 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 1967 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 1968 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 1969 return VIDEO_ENCODER_TVDAC; 1970 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 1971 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 1972 case ENCODER_OBJECT_ID_INTERNAL_DDI: 1973 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 1974 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 1975 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 1976 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 1977 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1978 return VIDEO_ENCODER_LVDS; 1979 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1980 return VIDEO_ENCODER_DAC; 1981 else 1982 return VIDEO_ENCODER_TMDS; 1983 break; 1984 case ENCODER_OBJECT_ID_SI170B: 1985 case ENCODER_OBJECT_ID_CH7303: 1986 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 1987 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 1988 case ENCODER_OBJECT_ID_TITFP513: 1989 case ENCODER_OBJECT_ID_VT1623: 1990 case ENCODER_OBJECT_ID_HDMI_SI1930: 1991 case ENCODER_OBJECT_ID_TRAVIS: 1992 case ENCODER_OBJECT_ID_NUTMEG: 1993 if ((connectorFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 1994 return VIDEO_ENCODER_LVDS; 1995 else if ((connectorFlags & ATOM_DEVICE_CRT_SUPPORT) != 0) 1996 return VIDEO_ENCODER_DAC; 1997 else 1998 return VIDEO_ENCODER_TMDS; 1999 break; 2000 } 2001 2002 return VIDEO_ENCODER_NONE; 2003 } 2004 2005 2006 bool 2007 encoder_is_external(uint32 encoderID) 2008 { 2009 switch (encoderID) { 2010 case ENCODER_OBJECT_ID_SI170B: 2011 case ENCODER_OBJECT_ID_CH7303: 2012 case ENCODER_OBJECT_ID_EXTERNAL_SDVOA: 2013 case ENCODER_OBJECT_ID_EXTERNAL_SDVOB: 2014 case ENCODER_OBJECT_ID_TITFP513: 2015 case ENCODER_OBJECT_ID_VT1623: 2016 case ENCODER_OBJECT_ID_HDMI_SI1930: 2017 case ENCODER_OBJECT_ID_TRAVIS: 2018 case ENCODER_OBJECT_ID_NUTMEG: 2019 return true; 2020 } 2021 2022 return false; 2023 } 2024 2025 2026 bool 2027 encoder_is_dp_bridge(uint32 encoderID) 2028 { 2029 switch (encoderID) { 2030 case ENCODER_OBJECT_ID_TRAVIS: 2031 case ENCODER_OBJECT_ID_NUTMEG: 2032 return true; 2033 } 2034 return false; 2035 } 2036