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