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