1 /* 2 * Copyright 2006-2011, 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 "accelerant_protos.h" 11 #include "accelerant.h" 12 #include "bios.h" 13 #include "display.h" 14 #include "utility.h" 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <math.h> 20 21 22 #define TRACE_ENCODER 23 #ifdef TRACE_ENCODER 24 extern "C" void _sPrintf(const char *format, ...); 25 # define TRACE(x...) _sPrintf("radeon_hd: " x) 26 #else 27 # define TRACE(x...) ; 28 #endif 29 30 #define ERROR(x...) _sPrintf("radeon_hd: " x) 31 32 33 union crtc_source_param { 34 SELECT_CRTC_SOURCE_PS_ALLOCATION v1; 35 SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; 36 }; 37 38 39 void 40 encoder_assign_crtc(uint8 crtcID) 41 { 42 int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); 43 union crtc_source_param args; 44 45 // Table version 46 uint8 tableMajor; 47 uint8 tableMinor; 48 49 memset(&args, 0, sizeof(args)); 50 51 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 52 != B_OK) 53 return; 54 55 uint16 connectorIndex = gDisplay[crtcID]->connectorIndex; 56 uint16 encoderID = gConnector[connectorIndex]->encoder.objectID; 57 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 58 59 switch (tableMajor) { 60 case 1: 61 switch (tableMinor) { 62 case 1: 63 default: 64 args.v1.ucCRTC = crtcID; 65 switch (encoderID) { 66 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 67 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 68 args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; 69 break; 70 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 71 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 72 if ((gConnector[connectorIndex]->flags 73 & ATOM_DEVICE_LCD1_SUPPORT) != 0) 74 args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; 75 else 76 args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; 77 break; 78 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 79 case ENCODER_OBJECT_ID_INTERNAL_DDI: 80 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 81 args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; 82 break; 83 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 84 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 85 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 86 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 87 } else if ((encoderFlags 88 & ATOM_DEVICE_CV_SUPPORT) != 0) { 89 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 90 } else 91 args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; 92 break; 93 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 94 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 95 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 96 args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; 97 } else if ((encoderFlags 98 & ATOM_DEVICE_CV_SUPPORT) != 0) { 99 args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; 100 } else 101 args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; 102 break; 103 } 104 break; 105 case 2: 106 args.v2.ucCRTC = crtcID; 107 args.v2.ucEncodeMode 108 = display_get_encoder_mode(connectorIndex); 109 switch (encoderID) { 110 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 111 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 112 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 113 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 114 ERROR("%s: DIG encoder not yet supported!\n", 115 __func__); 116 //dig = radeon_encoder->enc_priv; 117 //switch (dig->dig_encoder) { 118 // case 0: 119 // args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; 120 // break; 121 // case 1: 122 // args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; 123 // break; 124 // case 2: 125 // args.v2.ucEncoderID = ASIC_INT_DIG3_ENCODER_ID; 126 // break; 127 // case 3: 128 // args.v2.ucEncoderID = ASIC_INT_DIG4_ENCODER_ID; 129 // break; 130 // case 4: 131 // args.v2.ucEncoderID = ASIC_INT_DIG5_ENCODER_ID; 132 // break; 133 // case 5: 134 // args.v2.ucEncoderID = ASIC_INT_DIG6_ENCODER_ID; 135 // break; 136 //} 137 break; 138 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 139 args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; 140 break; 141 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 142 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 143 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 144 } else if ((encoderFlags 145 & ATOM_DEVICE_CV_SUPPORT) != 0) { 146 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 147 } else 148 args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; 149 break; 150 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 151 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) != 0) { 152 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 153 } else if ((encoderFlags 154 & ATOM_DEVICE_CV_SUPPORT) != 0) { 155 args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; 156 } else 157 args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; 158 break; 159 } 160 break; 161 } 162 break; 163 default: 164 ERROR("%s: Unknown table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 165 __func__, tableMajor, tableMinor); 166 return; 167 } 168 169 atom_execute_table(gAtomContext, index, (uint32*)&args); 170 171 // update crtc encoder scratch register @ scratch 3 172 encoder_crtc_scratch(crtcID); 173 } 174 175 176 void 177 encoder_apply_quirks(uint8 crtcID) 178 { 179 radeon_shared_info &info = *gInfo->shared_info; 180 register_info* regs = gDisplay[crtcID]->regs; 181 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 182 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 183 184 // Setting the scaler clears this on some chips... 185 if (info.dceMajor >= 3 186 && (encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0) { 187 // TODO: assume non interleave mode for now 188 // en: EVERGREEN_INTERLEAVE_EN : AVIVO_D1MODE_INTERLEAVE_EN 189 Write32(OUT, regs->modeDataFormat, 0); 190 } 191 } 192 193 194 void 195 encoder_mode_set(uint8 id, uint32 pixelClock) 196 { 197 radeon_shared_info &info = *gInfo->shared_info; 198 uint32 connectorIndex = gDisplay[id]->connectorIndex; 199 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 200 201 switch (gConnector[connectorIndex]->encoder.objectID) { 202 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 203 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 204 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 205 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 206 encoder_analog_setup(id, pixelClock, ATOM_ENABLE); 207 if ((encoderFlags 208 & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) != 0) { 209 encoder_tv_setup(id, pixelClock, ATOM_ENABLE); 210 } else { 211 encoder_tv_setup(id, pixelClock, ATOM_DISABLE); 212 } 213 break; 214 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 215 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 216 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 217 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 218 encoder_digital_setup(id, pixelClock, PANEL_ENCODER_ACTION_ENABLE); 219 break; 220 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 221 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 222 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 223 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 224 if (info.dceMajor >= 4) { 225 //atombios_dig_transmitter_setup(encoder, 226 // ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 227 // TODO: Disable the dig transmitter 228 encoder_dig_setup(id, pixelClock, ATOM_ENCODER_CMD_SETUP); 229 // Setup and enable the dig encoder 230 231 //atombios_dig_transmitter_setup(encoder, 232 // ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 233 // TODO: Enable the dig transmitter 234 } else { 235 //atombios_dig_transmitter_setup(encoder, 236 // ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); 237 // Disable the dig transmitter 238 encoder_dig_setup(id, pixelClock, ATOM_DISABLE); 239 // Disable the dig encoder 240 241 /* setup and enable the encoder and transmitter */ 242 encoder_dig_setup(id, pixelClock, ATOM_ENABLE); 243 // Setup and enable the dig encoder 244 245 //atombios_dig_transmitter_setup(encoder, 246 // ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); 247 //atombios_dig_transmitter_setup(encoder, 248 // ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); 249 // TODO: Setup and Enable the dig transmitter 250 } 251 252 TRACE("%s: TODO for DIG encoder setup\n", __func__); 253 break; 254 case ENCODER_OBJECT_ID_INTERNAL_DDI: 255 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 256 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 257 TRACE("%s: TODO for DVO encoder setup\n", __func__); 258 break; 259 default: 260 TRACE("%s: TODO for unknown encoder setup!\n", __func__); 261 } 262 263 encoder_apply_quirks(id); 264 } 265 266 267 status_t 268 encoder_tv_setup(uint8 id, uint32 pixelClock, int command) 269 { 270 uint32 connectorIndex = gDisplay[id]->connectorIndex; 271 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 272 273 TV_ENCODER_CONTROL_PS_ALLOCATION args; 274 memset(&args, 0, sizeof(args)); 275 276 int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); 277 278 args.sTVEncoder.ucAction = command; 279 280 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) 281 args.sTVEncoder.ucTvStandard = ATOM_TV_CV; 282 else { 283 // TODO: we assume NTSC for now 284 args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; 285 } 286 287 args.sTVEncoder.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 288 289 return atom_execute_table(gAtomContext, index, (uint32*)&args); 290 } 291 292 293 union lvds_encoder_control { 294 LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; 295 LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; 296 }; 297 298 299 status_t 300 encoder_digital_setup(uint8 id, uint32 pixelClock, int command) 301 { 302 TRACE("%s\n", __func__); 303 304 uint32 connectorIndex = gDisplay[id]->connectorIndex; 305 306 union lvds_encoder_control args; 307 memset(&args, 0, sizeof(args)); 308 309 int index = 0; 310 uint16 encoderFlags = gConnector[connectorIndex]->encoder.flags; 311 312 switch (gConnector[connectorIndex]->encoder.objectID) { 313 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 314 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 315 break; 316 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 317 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 318 index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); 319 break; 320 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 321 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 322 index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); 323 else 324 index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); 325 break; 326 } 327 328 // Table verson 329 uint8 tableMajor; 330 uint8 tableMinor; 331 332 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 333 != B_OK) 334 return B_ERROR; 335 336 switch (tableMajor) { 337 case 1: 338 case 2: 339 switch (tableMinor) { 340 case 1: 341 args.v1.ucMisc = 0; 342 args.v1.ucAction = command; 343 if (0) // TODO: HDMI? 344 args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 345 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 346 347 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 348 // TODO: laptop display support 349 //if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 350 // args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 351 //if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 352 // args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 353 } else { 354 //if (dig->linkb) 355 // args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 356 if (pixelClock > 165000) 357 args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; 358 /*if (pScrn->rgbBits == 8) */ 359 args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB; 360 } 361 break; 362 case 2: 363 case 3: 364 args.v2.ucMisc = 0; 365 args.v2.ucAction = command; 366 if (tableMinor == 3) { 367 //if (dig->coherent_mode) 368 // args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; 369 } 370 if (0) // TODO: HDMI? 371 args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; 372 args.v2.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 373 args.v2.ucTruncate = 0; 374 args.v2.ucSpatial = 0; 375 args.v2.ucTemporal = 0; 376 args.v2.ucFRC = 0; 377 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 378 // TODO: laptop display support 379 //if (dig->lcd_misc & ATOM_PANEL_MISC_DUAL) 380 // args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 381 //if (dig->lcd_misc & ATOM_PANEL_MISC_SPATIAL) { 382 args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; 383 //if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) 384 // args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; 385 //} 386 //if (dig->lcd_misc & ATOM_PANEL_MISC_TEMPORAL) { 387 // args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; 388 // if (dig->lcd_misc & ATOM_PANEL_MISC_888RGB) { 389 // args.v2.ucTemporal 390 // |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; 391 // } 392 // if (((dig->lcd_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) 393 // & 0x3) == 2) { 394 // args.v2.ucTemporal 395 // |= PANEL_ENCODER_TEMPORAL_LEVEL_4; 396 // } 397 //} 398 } else { 399 //if (dig->linkb) 400 // args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; 401 if (pixelClock > 165000) 402 args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; 403 } 404 break; 405 default: 406 ERROR("%s: Unknown minor table version: %" 407 B_PRIu8 ".%" B_PRIu8 "\n", __func__, 408 tableMajor, tableMinor); 409 return B_ERROR; 410 } 411 break; 412 default: 413 ERROR("%s: Unknown major table version: %" B_PRIu8 ".%" B_PRIu8 "\n", 414 __func__, tableMajor, tableMinor); 415 return B_ERROR; 416 } 417 return atom_execute_table(gAtomContext, index, (uint32*)&args); 418 } 419 420 421 union dig_encoder_control { 422 DIG_ENCODER_CONTROL_PS_ALLOCATION v1; 423 DIG_ENCODER_CONTROL_PARAMETERS_V2 v2; 424 DIG_ENCODER_CONTROL_PARAMETERS_V3 v3; 425 DIG_ENCODER_CONTROL_PARAMETERS_V4 v4; 426 }; 427 428 429 status_t 430 encoder_dig_setup(uint8 id, uint32 pixelClock, int command) 431 { 432 radeon_shared_info &info = *gInfo->shared_info; 433 434 uint32 connectorIndex = gDisplay[id]->connectorIndex; 435 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 436 437 union dig_encoder_control args; 438 int index = 0; 439 440 uint8 tableMajor; 441 uint8 tableMinor; 442 443 memset(&args, 0, sizeof(args)); 444 445 if (info.dceMajor > 4) 446 index = GetIndexIntoMasterTable(COMMAND, DIGxEncoderControl); 447 else { 448 if (1) // TODO: pick dig encoder 449 index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); 450 else 451 index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); 452 } 453 454 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 455 != B_OK) { 456 ERROR("%s: cannot parse command table\n", __func__); 457 return B_ERROR; 458 } 459 460 args.v1.ucAction = command; 461 args.v1.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 462 463 #if 0 464 if (command == ATOM_ENCODER_CMD_SETUP_PANEL_MODE) { 465 if (info.dceMajor >= 4 && 0) // TODO: 0 == if DP bridge 466 args.v3.ucPanelMode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 467 else 468 args.v3.ucPanelMode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 469 } else { 470 args.v1.ucEncoderMode = display_get_encoder_mode(connectorIndex); 471 472 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 473 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 474 args.v1.ucLaneNum = dp_lane_count; 475 } else if (pixelClock > 165000) 476 args.v1.ucLaneNum = 8; 477 else 478 args.v1.ucLaneNum = 4; 479 480 if (info.dceMajor >= 5) { 481 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 482 || args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP_MST) { 483 if (dpClock == 270000) { 484 args.v1.ucConfig 485 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ; 486 } else if (dpClock == 540000) { 487 args.v1.ucConfig 488 |= ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ; 489 } 490 } 491 args.v4.acConfig.ucDigSel = dig->dig_encoder; 492 switch (bpc) { 493 case 0: 494 args.v4.ucBitPerColor = PANEL_BPC_UNDEFINE; 495 break; 496 case 6: 497 args.v4.ucBitPerColor = PANEL_6BIT_PER_COLOR; 498 break; 499 case 8: 500 default: 501 args.v4.ucBitPerColor = PANEL_8BIT_PER_COLOR; 502 break; 503 case 10: 504 args.v4.ucBitPerColor = PANEL_10BIT_PER_COLOR; 505 break; 506 case 12: 507 args.v4.ucBitPerColor = PANEL_12BIT_PER_COLOR; 508 break; 509 case 16: 510 args.v4.ucBitPerColor = PANEL_16BIT_PER_COLOR; 511 break; 512 } 513 514 //if (hpdID == RADEON_HPD_NONE) 515 if (1) 516 args.v4.ucHPD_ID = 0; 517 else 518 args.v4.ucHPD_ID = hpd_id + 1; 519 520 } else if (info.dceMajor >= 4) { 521 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 522 && dp_clock == 270000) { 523 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; 524 } 525 526 args.v3.acConfig.ucDigSel = dig->dig_encoder; 527 switch (bpc) { 528 case 0: 529 args.v3.ucBitPerColor = PANEL_BPC_UNDEFINE; 530 break; 531 case 6: 532 args.v3.ucBitPerColor = PANEL_6BIT_PER_COLOR; 533 break; 534 case 8: 535 default: 536 args.v3.ucBitPerColor = PANEL_8BIT_PER_COLOR; 537 break; 538 case 10: 539 args.v3.ucBitPerColor = PANEL_10BIT_PER_COLOR; 540 break; 541 case 12: 542 args.v3.ucBitPerColor = PANEL_12BIT_PER_COLOR; 543 break; 544 case 16: 545 args.v3.ucBitPerColor = PANEL_16BIT_PER_COLOR; 546 break; 547 } 548 549 } else { 550 if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP 551 && dp_clock == 270000) { 552 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; 553 } 554 #endif 555 switch (encoderID) { 556 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 557 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; 558 break; 559 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 560 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 561 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; 562 break; 563 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 564 args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; 565 break; 566 } 567 #if 0 568 if (dig->linkb) 569 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; 570 else 571 args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 572 } 573 #endif 574 575 return atom_execute_table(gAtomContext, index, (uint32*)&args); 576 } 577 578 579 status_t 580 encoder_analog_setup(uint8 id, uint32 pixelClock, int command) 581 { 582 TRACE("%s\n", __func__); 583 584 uint32 connectorIndex = gDisplay[id]->connectorIndex; 585 586 int index = 0; 587 DAC_ENCODER_CONTROL_PS_ALLOCATION args; 588 memset(&args, 0, sizeof(args)); 589 590 switch (gConnector[connectorIndex]->encoder.objectID) { 591 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 592 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 593 index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); 594 break; 595 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 596 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 597 index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); 598 break; 599 } 600 601 args.ucAction = command; 602 args.ucDacStandard = ATOM_DAC1_PS2; 603 // TODO: or ATOM_DAC1_CV if ATOM_DEVICE_CV_SUPPORT 604 // TODO: or ATOM_DAC1_PAL or ATOM_DAC1_NTSC if else 605 606 args.usPixelClock = B_HOST_TO_LENDIAN_INT16(pixelClock / 10); 607 608 return atom_execute_table(gAtomContext, index, (uint32*)&args); 609 } 610 611 612 bool 613 encoder_analog_load_detect(uint8 connectorIndex) 614 { 615 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 616 uint32 encoderID = gConnector[connectorIndex]->encoder.objectID; 617 618 if ((encoderFlags & ATOM_DEVICE_TV_SUPPORT) == 0 619 && (encoderFlags & ATOM_DEVICE_CV_SUPPORT) == 0 620 && (encoderFlags & ATOM_DEVICE_CRT_SUPPORT) == 0) { 621 ERROR("%s: executed on non-dac device connector #%" B_PRIu8 "\n", 622 __func__, connectorIndex); 623 return false; 624 } 625 626 // *** tell the card we want to do a DAC detection 627 628 DAC_LOAD_DETECTION_PS_ALLOCATION args; 629 int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); 630 uint8 tableMajor; 631 uint8 tableMinor; 632 633 memset(&args, 0, sizeof(args)); 634 635 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 636 != B_OK) { 637 ERROR("%s: failed getting AtomBIOS header for DAC_LoadDetection\n", 638 __func__); 639 return false; 640 } 641 642 args.sDacload.ucMisc = 0; 643 644 if (encoderID == ENCODER_OBJECT_ID_INTERNAL_DAC1 645 || encoderID == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) { 646 args.sDacload.ucDacType = ATOM_DAC_A; 647 } else { 648 args.sDacload.ucDacType = ATOM_DAC_B; 649 } 650 651 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 652 args.sDacload.usDeviceID 653 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT1_SUPPORT); 654 atom_execute_table(gAtomContext, index, (uint32*)&args); 655 656 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 657 658 if ((biosScratch0 & ATOM_S0_CRT1_MASK) != 0) 659 return true; 660 661 } else if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 662 args.sDacload.usDeviceID 663 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CRT2_SUPPORT); 664 atom_execute_table(gAtomContext, index, (uint32*)&args); 665 666 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 667 668 if ((biosScratch0 & ATOM_S0_CRT2_MASK) != 0) 669 return true; 670 671 } else if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 672 args.sDacload.usDeviceID 673 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_CV_SUPPORT); 674 if (tableMinor >= 3) 675 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 676 atom_execute_table(gAtomContext, index, (uint32*)&args); 677 678 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 679 680 if ((biosScratch0 & (ATOM_S0_CV_MASK | ATOM_S0_CV_MASK_A)) != 0) 681 return true; 682 683 } else if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 684 args.sDacload.usDeviceID 685 = B_HOST_TO_LENDIAN_INT16(ATOM_DEVICE_TV1_SUPPORT); 686 if (tableMinor >= 3) 687 args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; 688 atom_execute_table(gAtomContext, index, (uint32*)&args); 689 690 uint32 biosScratch0 = Read32(OUT, R600_BIOS_0_SCRATCH); 691 692 if ((biosScratch0 693 & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) != 0) { 694 return true; /* Composite connected */ 695 } else if ((biosScratch0 696 & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) != 0) { 697 return true; /* S-Video connected */ 698 } 699 700 } 701 return false; 702 } 703 704 705 void 706 encoder_crtc_scratch(uint8 crtcID) 707 { 708 TRACE("%s\n", __func__); 709 710 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 711 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 712 713 // TODO: r500 714 uint32 biosScratch3 = Read32(OUT, R600_BIOS_3_SCRATCH); 715 716 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 717 biosScratch3 &= ~ATOM_S3_TV1_CRTC_ACTIVE; 718 biosScratch3 |= (crtcID << 18); 719 } 720 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 721 biosScratch3 &= ~ATOM_S3_CV_CRTC_ACTIVE; 722 biosScratch3 |= (crtcID << 24); 723 } 724 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 725 biosScratch3 &= ~ATOM_S3_CRT1_CRTC_ACTIVE; 726 biosScratch3 |= (crtcID << 16); 727 } 728 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 729 biosScratch3 &= ~ATOM_S3_CRT2_CRTC_ACTIVE; 730 biosScratch3 |= (crtcID << 20); 731 } 732 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 733 biosScratch3 &= ~ATOM_S3_LCD1_CRTC_ACTIVE; 734 biosScratch3 |= (crtcID << 17); 735 } 736 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 737 biosScratch3 &= ~ATOM_S3_DFP1_CRTC_ACTIVE; 738 biosScratch3 |= (crtcID << 19); 739 } 740 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 741 biosScratch3 &= ~ATOM_S3_DFP2_CRTC_ACTIVE; 742 biosScratch3 |= (crtcID << 23); 743 } 744 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 745 biosScratch3 &= ~ATOM_S3_DFP3_CRTC_ACTIVE; 746 biosScratch3 |= (crtcID << 25); 747 } 748 749 // TODO: r500 750 Write32(OUT, R600_BIOS_3_SCRATCH, biosScratch3); 751 } 752 753 754 void 755 encoder_dpms_scratch(uint8 crtcID, bool power) 756 { 757 TRACE("%s: power: %s\n", __func__, power ? "true" : "false"); 758 759 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 760 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 761 762 // TODO: r500 763 uint32 biosScratch2 = Read32(OUT, R600_BIOS_2_SCRATCH); 764 765 if ((encoderFlags & ATOM_DEVICE_TV1_SUPPORT) != 0) { 766 if (power == true) 767 biosScratch2 &= ~ATOM_S2_TV1_DPMS_STATE; 768 else 769 biosScratch2 |= ATOM_S2_TV1_DPMS_STATE; 770 } 771 if ((encoderFlags & ATOM_DEVICE_CV_SUPPORT) != 0) { 772 if (power == true) 773 biosScratch2 &= ~ATOM_S2_CV_DPMS_STATE; 774 else 775 biosScratch2 |= ATOM_S2_CV_DPMS_STATE; 776 } 777 if ((encoderFlags & ATOM_DEVICE_CRT1_SUPPORT) != 0) { 778 if (power == true) 779 biosScratch2 &= ~ATOM_S2_CRT1_DPMS_STATE; 780 else 781 biosScratch2 |= ATOM_S2_CRT1_DPMS_STATE; 782 } 783 if ((encoderFlags & ATOM_DEVICE_CRT2_SUPPORT) != 0) { 784 if (power == true) 785 biosScratch2 &= ~ATOM_S2_CRT2_DPMS_STATE; 786 else 787 biosScratch2 |= ATOM_S2_CRT2_DPMS_STATE; 788 } 789 if ((encoderFlags & ATOM_DEVICE_LCD1_SUPPORT) != 0) { 790 if (power == true) 791 biosScratch2 &= ~ATOM_S2_LCD1_DPMS_STATE; 792 else 793 biosScratch2 |= ATOM_S2_LCD1_DPMS_STATE; 794 } 795 if ((encoderFlags & ATOM_DEVICE_DFP1_SUPPORT) != 0) { 796 if (power == true) 797 biosScratch2 &= ~ATOM_S2_DFP1_DPMS_STATE; 798 else 799 biosScratch2 |= ATOM_S2_DFP1_DPMS_STATE; 800 } 801 if ((encoderFlags & ATOM_DEVICE_DFP2_SUPPORT) != 0) { 802 if (power == true) 803 biosScratch2 &= ~ATOM_S2_DFP2_DPMS_STATE; 804 else 805 biosScratch2 |= ATOM_S2_DFP2_DPMS_STATE; 806 } 807 if ((encoderFlags & ATOM_DEVICE_DFP3_SUPPORT) != 0) { 808 if (power == true) 809 biosScratch2 &= ~ATOM_S2_DFP3_DPMS_STATE; 810 else 811 biosScratch2 |= ATOM_S2_DFP3_DPMS_STATE; 812 } 813 if ((encoderFlags & ATOM_DEVICE_DFP4_SUPPORT) != 0) { 814 if (power == true) 815 biosScratch2 &= ~ATOM_S2_DFP4_DPMS_STATE; 816 else 817 biosScratch2 |= ATOM_S2_DFP4_DPMS_STATE; 818 } 819 if ((encoderFlags & ATOM_DEVICE_DFP5_SUPPORT) != 0) { 820 if (power == true) 821 biosScratch2 &= ~ATOM_S2_DFP5_DPMS_STATE; 822 else 823 biosScratch2 |= ATOM_S2_DFP5_DPMS_STATE; 824 } 825 Write32(OUT, R600_BIOS_2_SCRATCH, biosScratch2); 826 } 827 828 829 void 830 encoder_dpms_set(uint8 crtcID, uint8 encoderID, int mode) 831 { 832 int index = 0; 833 DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; 834 835 memset(&args, 0, sizeof(args)); 836 837 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 838 uint32 encoderFlags = gConnector[connectorIndex]->encoder.flags; 839 840 switch (encoderID) { 841 case ENCODER_OBJECT_ID_INTERNAL_TMDS1: 842 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 843 index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); 844 break; 845 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: 846 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: 847 case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: 848 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: 849 ERROR("%s: TODO DIG DPMS set\n", __func__); 850 return; 851 case ENCODER_OBJECT_ID_INTERNAL_DVO1: 852 case ENCODER_OBJECT_ID_INTERNAL_DDI: 853 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 854 break; 855 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 856 // TODO: encoder dpms set newer cards 857 // If DCE5, dvo true 858 // If DCE3, dig true 859 // else... 860 index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); 861 break; 862 case ENCODER_OBJECT_ID_INTERNAL_LVDS: 863 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 864 break; 865 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 866 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) 867 index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); 868 else 869 index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); 870 break; 871 case ENCODER_OBJECT_ID_INTERNAL_DAC1: 872 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: 873 // TODO: encoder dpms dce5 dac 874 // else... 875 /* 876 if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) 877 index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); 878 else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) 879 index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); 880 else 881 */ 882 index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); 883 break; 884 case ENCODER_OBJECT_ID_INTERNAL_DAC2: 885 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: 886 // TODO: tv or CV encoder on DAC2 887 index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); 888 break; 889 } 890 891 switch (mode) { 892 case B_DPMS_ON: 893 args.ucAction = ATOM_ENABLE; 894 atom_execute_table(gAtomContext, index, (uint32*)&args); 895 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 896 args.ucAction = ATOM_LCD_BLON; 897 atom_execute_table(gAtomContext, index, (uint32*)&args); 898 } 899 encoder_dpms_scratch(crtcID, true); 900 break; 901 case B_DPMS_STAND_BY: 902 case B_DPMS_SUSPEND: 903 case B_DPMS_OFF: 904 args.ucAction = ATOM_DISABLE; 905 atom_execute_table(gAtomContext, index, (uint32*)&args); 906 if ((encoderFlags & ATOM_DEVICE_LCD_SUPPORT) != 0) { 907 args.ucAction = ATOM_LCD_BLOFF; 908 atom_execute_table(gAtomContext, index, (uint32*)&args); 909 } 910 encoder_dpms_scratch(crtcID, false); 911 break; 912 } 913 } 914 915 916 void 917 encoder_output_lock(bool lock) 918 { 919 TRACE("%s: %s\n", __func__, lock ? "true" : "false"); 920 uint32 biosScratch6 = Read32(OUT, R600_BIOS_6_SCRATCH); 921 922 if (lock) { 923 biosScratch6 |= ATOM_S6_CRITICAL_STATE; 924 biosScratch6 &= ~ATOM_S6_ACC_MODE; 925 } else { 926 biosScratch6 &= ~ATOM_S6_CRITICAL_STATE; 927 biosScratch6 |= ATOM_S6_ACC_MODE; 928 } 929 930 Write32(OUT, R600_BIOS_6_SCRATCH, biosScratch6); 931 } 932