1 /* 2 * Copyright 2011-2013, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck IV, kallisti5@unixzen.com 7 * Bill Randle, billr@neocat.org 8 */ 9 10 11 #include "displayport.h" 12 13 #include <Debug.h> 14 15 #include "accelerant_protos.h" 16 #include "connector.h" 17 #include "mode.h" 18 #include "edid.h" 19 20 21 #undef TRACE 22 23 #define TRACE_DP 24 #ifdef TRACE_DP 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 static status_t 34 dp_aux_speak(uint32 connectorIndex, uint8* send, int sendBytes, 35 uint8* recv, int recvBytes, uint8 delay, uint8* ack) 36 { 37 radeon_shared_info &info = *gInfo->shared_info; 38 39 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 40 if (dpInfo->auxPin == 0) { 41 ERROR("%s: cannot speak on invalid GPIO pin!\n", __func__); 42 return B_IO_ERROR; 43 } 44 45 int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); 46 47 // Build AtomBIOS Transaction 48 union auxChannelTransaction { 49 PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; 50 PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; 51 }; 52 union auxChannelTransaction args; 53 memset(&args, 0, sizeof(args)); 54 55 args.v1.lpAuxRequest = B_HOST_TO_LENDIAN_INT16(0 + 4); 56 args.v1.lpDataOut = B_HOST_TO_LENDIAN_INT16(16 + 4); 57 args.v1.ucDataOutLen = 0; 58 args.v1.ucChannelID = dpInfo->auxPin; 59 args.v1.ucDelay = delay / 10; 60 61 uint16 hpdPinIndex = gConnector[connectorIndex]->hpdPinIndex; 62 if (info.dceMajor >= 4 63 && gGPIOInfo[hpdPinIndex]->valid) { 64 65 uint32 targetReg = EVERGREEN_DC_GPIO_HPD_A; 66 if (info.dceMajor >= 6) 67 targetReg = SI_DC_GPIO_HPD_A; 68 69 // You're drunk AMD, go home. (this makes no sense) 70 if (gGPIOInfo[hpdPinIndex]->hwReg == targetReg) { 71 switch(gGPIOInfo[hpdPinIndex]->hwMask) { 72 case (1 << 0): 73 args.v2.ucHPD_ID = 0; 74 break; 75 case (1 << 8): 76 args.v2.ucHPD_ID = 1; 77 break; 78 case (1 << 16): 79 args.v2.ucHPD_ID = 2; 80 break; 81 case (1 << 24): 82 args.v2.ucHPD_ID = 3; 83 break; 84 case (1 << 26): 85 args.v2.ucHPD_ID = 4; 86 break; 87 case (1 << 28): 88 args.v2.ucHPD_ID = 5; 89 break; 90 default: 91 args.v2.ucHPD_ID = 0xff; 92 break; 93 } 94 } else { 95 args.v2.ucHPD_ID = 0xff; 96 } 97 } 98 99 unsigned char* base = (unsigned char*)(gAtomContext->scratch + 1); 100 101 // TODO: This isn't correct for big endian systems! 102 // send needs to be swapped on big endian. 103 memcpy(base, send, sendBytes); 104 105 atom_execute_table(gAtomContext, index, (uint32*)&args); 106 107 *ack = args.v1.ucReplyStatus; 108 109 switch (args.v1.ucReplyStatus) { 110 case 1: 111 ERROR("%s: dp_aux_ch timeout!\n", __func__); 112 return B_TIMED_OUT; 113 case 2: 114 ERROR("%s: dp_aux_ch flags not zero!\n", __func__); 115 return B_BUSY; 116 case 3: 117 ERROR("%s: dp_aux_ch error!\n", __func__); 118 return B_IO_ERROR; 119 } 120 121 int recvLength = args.v1.ucDataOutLen; 122 if (recvLength > recvBytes) 123 recvLength = recvBytes; 124 125 // TODO: This isn't correct for big endian systems! 126 // recv needs to be swapped on big endian. 127 if (recv && recvBytes) 128 memcpy(recv, base + 16, recvLength); 129 130 return B_OK; 131 } 132 133 134 status_t 135 dp_aux_write(uint32 connectorIndex, uint16 address, 136 uint8* send, uint8 sendBytes, uint8 delay) 137 { 138 uint8 auxMessage[20]; 139 int auxMessageBytes = sendBytes + 4; 140 141 if (sendBytes > 16) { 142 ERROR("%s: Too many bytes! (%" B_PRIu8 ")\n", __func__, sendBytes); 143 return -1; 144 } 145 146 auxMessage[0] = address; 147 auxMessage[1] = address >> 8; 148 auxMessage[2] = AUX_NATIVE_WRITE << 4; 149 auxMessage[3] = (auxMessageBytes << 4) | (sendBytes - 1); 150 memcpy(&auxMessage[4], send, sendBytes); 151 152 uint8 retry; 153 for (retry = 0; retry < 7; retry++) { 154 uint8 ack; 155 status_t result = dp_aux_speak(connectorIndex, auxMessage, 156 auxMessageBytes, NULL, 0, delay, &ack); 157 158 if (result == B_BUSY) 159 continue; 160 else if (result != B_OK) 161 return result; 162 163 ack >>= 4; 164 if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) 165 return B_OK; 166 else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) 167 snooze(400); 168 else 169 return B_IO_ERROR; 170 } 171 172 ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry); 173 return B_IO_ERROR; 174 } 175 176 177 status_t 178 dp_aux_read(uint32 connectorIndex, uint16 address, 179 uint8* recv, int recvBytes, uint8 delay) 180 { 181 uint8 auxMessage[4]; 182 int auxMessageBytes = 4; 183 184 auxMessage[0] = address; 185 auxMessage[1] = address >> 8; 186 auxMessage[2] = AUX_NATIVE_READ << 4; 187 auxMessage[3] = (auxMessageBytes << 4) | (recvBytes - 1); 188 189 uint8 retry; 190 for (retry = 0; retry < 7; retry++) { 191 uint8 ack; 192 status_t result = dp_aux_speak(connectorIndex, auxMessage, 193 auxMessageBytes, recv, recvBytes, delay, &ack); 194 195 if (result == B_BUSY) 196 continue; 197 else if (result != B_OK) 198 return result; 199 200 ack >>= 4; 201 if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) 202 return B_OK; 203 else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) 204 snooze(400); 205 else 206 return B_IO_ERROR; 207 } 208 209 ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry); 210 return B_IO_ERROR; 211 } 212 213 214 void 215 dpcd_reg_write(uint32 connectorIndex, uint16 address, uint8 value) 216 { 217 status_t result = dp_aux_write(connectorIndex, address, &value, 1, 0); 218 if (result != B_OK) 219 ERROR("%s: error on DisplayPort aux write (0x%lX)\n", __func__, result); 220 } 221 222 223 uint8 224 dpcd_reg_read(uint32 connectorIndex, uint16 address) 225 { 226 uint8 value = 0; 227 status_t result = dp_aux_read(connectorIndex, address, &value, 1, 0); 228 if (result != B_OK) 229 ERROR("%s: error on DisplayPort aux read (0x%lX)\n", __func__, result); 230 231 return value; 232 } 233 234 235 status_t 236 dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data, 237 bool start, bool stop) 238 { 239 uint8 auxMessage[5]; 240 int auxMessageBytes = 4; // 4 for read 241 242 /* Set up the command byte */ 243 auxMessage[2] = AUX_I2C_READ << 4; 244 if (stop == false) 245 auxMessage[2] |= AUX_I2C_MOT << 4; 246 247 auxMessage[0] = address; 248 auxMessage[1] = address >> 8; 249 250 auxMessage[3] = auxMessageBytes << 4; 251 252 /* special case for sending the START or STOP */ 253 if (start || stop) { 254 auxMessage[3] = 3 << 4; 255 auxMessageBytes = 4; 256 } 257 258 int retry; 259 for (retry = 0; retry < 4; retry++) { 260 uint8 ack; 261 uint8 reply[2]; 262 int replyBytes = 1; 263 264 status_t result = dp_aux_speak(connectorIndex, auxMessage, 265 auxMessageBytes, reply, replyBytes, 0, &ack); 266 if (result == B_BUSY) 267 continue; 268 else if (result != B_OK) { 269 ERROR("%s: aux_ch speak failed 0x%lX\n", __func__, result); 270 return B_ERROR; 271 } 272 273 switch (ack & AUX_NATIVE_REPLY_MASK) { 274 case AUX_NATIVE_REPLY_ACK: 275 // I2C-over-AUX Reply field is only valid for AUX_ACK 276 break; 277 case AUX_NATIVE_REPLY_NACK: 278 TRACE("%s: aux_ch native nack\n", __func__); 279 return B_IO_ERROR; 280 case AUX_NATIVE_REPLY_DEFER: 281 TRACE("%s: aux_ch native defer\n", __func__); 282 snooze(400); 283 continue; 284 default: 285 TRACE("%s: aux_ch invalid native reply: 0x%02x\n", 286 __func__, ack); 287 return B_ERROR; 288 } 289 290 switch (ack & AUX_I2C_REPLY_MASK) { 291 case AUX_I2C_REPLY_ACK: 292 *data = reply[0]; 293 return B_OK; 294 case AUX_I2C_REPLY_NACK: 295 TRACE("%s: aux_i2c nack\n", __func__); 296 return B_IO_ERROR; 297 case AUX_I2C_REPLY_DEFER: 298 TRACE("%s: aux_i2c defer\n", __func__); 299 snooze(400); 300 break; 301 default: 302 TRACE("%s: aux_i2c invalid native reply: 0x%02x\n", 303 __func__, ack); 304 return B_ERROR; 305 } 306 } 307 308 TRACE("%s: aux i2c too many retries, giving up.\n", __func__); 309 return B_ERROR; 310 } 311 312 313 status_t 314 dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data, 315 bool start, bool stop) 316 { 317 uint8 auxMessage[5]; 318 int auxMessageBytes = 5; // 5 for write 319 320 /* Set up the command byte */ 321 auxMessage[2] = AUX_I2C_WRITE << 4; 322 if (stop == false) 323 auxMessage[2] |= AUX_I2C_MOT << 4; 324 325 auxMessage[0] = address; 326 auxMessage[1] = address >> 8; 327 328 auxMessage[3] = auxMessageBytes << 4; 329 auxMessage[4] = *data; 330 331 /* special case for sending the START or STOP */ 332 if (start || stop) { 333 auxMessage[3] = 3 << 4; 334 auxMessageBytes = 4; 335 } 336 337 int retry; 338 for (retry = 0; retry < 4; retry++) { 339 uint8 ack; 340 uint8 reply[2]; 341 int replyBytes = 1; 342 343 status_t result = dp_aux_speak(connectorIndex, auxMessage, 344 auxMessageBytes, reply, replyBytes, 0, &ack); 345 if (result == B_BUSY) 346 continue; 347 else if (result != B_OK) { 348 ERROR("%s: aux_ch speak failed 0x%lX\n", __func__, result); 349 return B_ERROR; 350 } 351 352 switch (ack & AUX_NATIVE_REPLY_MASK) { 353 case AUX_NATIVE_REPLY_ACK: 354 // I2C-over-AUX Reply field is only valid for AUX_ACK 355 break; 356 case AUX_NATIVE_REPLY_NACK: 357 TRACE("%s: aux_ch native nack\n", __func__); 358 return B_IO_ERROR; 359 case AUX_NATIVE_REPLY_DEFER: 360 TRACE("%s: aux_ch native defer\n", __func__); 361 snooze(400); 362 continue; 363 default: 364 TRACE("%s: aux_ch invalid native reply: 0x%02x\n", 365 __func__, ack); 366 return B_ERROR; 367 } 368 369 switch (ack & AUX_I2C_REPLY_MASK) { 370 case AUX_I2C_REPLY_ACK: 371 // Success! 372 return B_OK; 373 case AUX_I2C_REPLY_NACK: 374 TRACE("%s: aux_i2c nack\n", __func__); 375 return B_IO_ERROR; 376 case AUX_I2C_REPLY_DEFER: 377 TRACE("%s: aux_i2c defer\n", __func__); 378 snooze(400); 379 break; 380 default: 381 TRACE("%s: aux_i2c invalid native reply: 0x%02x\n", 382 __func__, ack); 383 return B_ERROR; 384 } 385 } 386 387 TRACE("%s: aux i2c too many retries, giving up.\n", __func__); 388 return B_OK; 389 } 390 391 392 uint32 393 dp_get_lane_count(uint32 connectorIndex, display_mode* mode) 394 { 395 // Radeon specific 396 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 397 398 size_t pixelChunk; 399 size_t pixelsPerChunk; 400 status_t result = dp_get_pixel_size_for((color_space)mode->space, 401 &pixelChunk, NULL, &pixelsPerChunk); 402 403 if (result != B_OK) { 404 TRACE("%s: Invalid color space!\n", __func__); 405 return 0; 406 } 407 408 uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8; 409 410 uint32 dpMaxLinkRate = dp_get_link_rate_max(dpInfo); 411 uint32 dpMaxLaneCount = dp_get_lane_count_max(dpInfo); 412 413 uint32 lane; 414 // don't go below 2 lanes or display is jittery 415 for (lane = 2; lane < dpMaxLaneCount; lane <<= 1) { 416 uint32 maxPixelClock = dp_get_pixel_clock_max(dpMaxLinkRate, lane, 417 bitsPerPixel); 418 if (mode->timing.pixel_clock <= maxPixelClock) 419 break; 420 } 421 422 TRACE("%s: Lanes: %" B_PRIu32 "\n", __func__, lane); 423 return lane; 424 } 425 426 427 uint32 428 dp_get_link_rate(uint32 connectorIndex, display_mode* mode) 429 { 430 uint16 encoderID = gConnector[connectorIndex]->encoderExternal.objectID; 431 432 if (encoderID == ENCODER_OBJECT_ID_NUTMEG) 433 return 270000; 434 435 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 436 uint32 laneCount = dp_get_lane_count(connectorIndex, mode); 437 438 size_t pixelChunk; 439 size_t pixelsPerChunk; 440 status_t result = dp_get_pixel_size_for((color_space)mode->space, 441 &pixelChunk, NULL, &pixelsPerChunk); 442 443 if (result != B_OK) { 444 TRACE("%s: Invalid color space!\n", __func__); 445 return 0; 446 } 447 448 uint32 bitsPerPixel = (pixelChunk / pixelsPerChunk) * 8; 449 450 uint32 maxPixelClock 451 = dp_get_pixel_clock_max(162000, laneCount, bitsPerPixel); 452 if (mode->timing.pixel_clock <= maxPixelClock) 453 return 162000; 454 455 maxPixelClock = dp_get_pixel_clock_max(270000, laneCount, bitsPerPixel); 456 if (mode->timing.pixel_clock <= maxPixelClock) 457 return 270000; 458 459 // TODO: DisplayPort 1.2 460 #if 0 461 if (dp_is_dp12_capable(connectorIndex)) { 462 maxPixelClock = dp_get_pixel_clock_max(540000, laneCount, bitsPerPixel); 463 if (mode->timing.pixel_clock <= maxPixelClock) 464 return 540000; 465 } 466 #endif 467 468 return dp_get_link_rate_max(dpInfo); 469 } 470 471 472 void 473 dp_setup_connectors() 474 { 475 TRACE("%s\n", __func__); 476 477 for (uint32 index = 0; index < ATOM_MAX_SUPPORTED_DEVICE; index++) { 478 dp_info* dpInfo = &gConnector[index]->dpInfo; 479 dpInfo->valid = false; 480 if (gConnector[index]->valid == false 481 || connector_is_dp(index) == false) { 482 dpInfo->config[0] = 0; 483 continue; 484 } 485 486 TRACE("%s: found dp connector on index %" B_PRIu32 "\n", 487 __func__, index); 488 uint32 i2cPinIndex = gConnector[index]->i2cPinIndex; 489 490 uint32 auxPin = gGPIOInfo[i2cPinIndex]->hwPin; 491 dpInfo->auxPin = auxPin; 492 493 uint8 auxMessage[DP_DPCD_SIZE]; 494 495 status_t result = dp_aux_read(index, DP_DPCD_REV, auxMessage, 496 DP_DPCD_SIZE, 0); 497 498 if (result == B_OK) { 499 dpInfo->valid = true; 500 memcpy(dpInfo->config, auxMessage, DP_DPCD_SIZE); 501 TRACE("%s: connector(%" B_PRIu32 "): successful read of DPCD\n", 502 __func__, index); 503 } else { 504 TRACE("%s: connector(%" B_PRIu32 "): failed read of DPCD\n", 505 __func__, index); 506 } 507 TRACE("%s: DPCD is ", __func__); 508 uint32 position; 509 for (position = 0; position < DP_DPCD_SIZE; position++) 510 _sPrintf("%02x ", auxMessage[position]); 511 _sPrintf("\n"); 512 } 513 } 514 515 516 bool 517 dp_get_link_status(uint32 connectorIndex) 518 { 519 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 520 status_t result = dp_aux_read(connectorIndex, DP_LANE_STATUS_0_1, 521 dp->linkStatus, DP_LINK_STATUS_SIZE, 100); 522 523 if (result != B_OK) { 524 ERROR("%s: DisplayPort link status failed\n", __func__); 525 return false; 526 } 527 528 return true; 529 } 530 531 532 static uint8 533 dp_get_lane_status(dp_info* dp, int lane) 534 { 535 int i = DP_LANE_STATUS_0_1 + (lane >> 1); 536 int s = (lane & 1) * 4; 537 uint8 l = dp->linkStatus[i - DP_LANE_STATUS_0_1]; 538 return (l >> s) & 0xf; 539 } 540 541 542 static bool 543 dp_clock_recovery_ok(dp_info* dp) 544 { 545 int lane; 546 uint8 laneStatus; 547 548 for (lane = 0; lane < dp->laneCount; lane++) { 549 laneStatus = dp_get_lane_status(dp, lane); 550 if ((laneStatus & DP_LANE_STATUS_CR_DONE_A) == 0) 551 return false; 552 } 553 return true; 554 } 555 556 557 static bool 558 dp_clock_equalization_ok(dp_info* dp) 559 { 560 uint8 laneAlignment 561 = dp->linkStatus[DP_LANE_ALIGN - DP_LANE_STATUS_0_1]; 562 563 if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0) 564 return false; 565 566 int lane; 567 for (lane = 0; lane < dp->laneCount; lane++) { 568 uint8 laneStatus = dp_get_lane_status(dp, lane); 569 if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A) 570 != DP_LANE_STATUS_EQUALIZED_A) { 571 return false; 572 } 573 } 574 return true; 575 } 576 577 578 static void 579 dp_update_vs_emph(uint32 connectorIndex) 580 { 581 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 582 583 // Set initial vs and emph on source 584 transmitter_dig_setup(connectorIndex, dp->linkRate, 0, 585 dp->trainingSet[0], ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH); 586 587 // Set vs and emph on the sink 588 dp_aux_write(connectorIndex, DP_TRAIN_LANE0, 589 dp->trainingSet, dp->laneCount, 0); 590 } 591 592 593 static uint8 594 dp_get_adjust_request_voltage(dp_info* dp, int lane) 595 { 596 int i = DP_ADJ_REQUEST_0_1 + (lane >> 1); 597 int s = (((lane & 1) != 0) ? DP_ADJ_VCC_SWING_LANEB_SHIFT 598 : DP_ADJ_VCC_SWING_LANEA_SHIFT); 599 uint8 l = dp->linkStatus[i - DP_LANE_STATUS_0_1]; 600 601 return ((l >> s) & 0x3) << DP_TRAIN_VCC_SWING_SHIFT; 602 } 603 604 605 static uint8 606 dp_get_adjust_request_pre_emphasis(dp_info* dp, int lane) 607 { 608 int i = DP_ADJ_REQUEST_0_1 + (lane >> 1); 609 int s = (((lane & 1) != 0) ? DP_ADJ_PRE_EMPHASIS_LANEB_SHIFT 610 : DP_ADJ_PRE_EMPHASIS_LANEA_SHIFT); 611 uint8 l = dp->linkStatus[i - DP_LANE_STATUS_0_1]; 612 613 return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; 614 } 615 616 617 static void 618 dp_get_adjust_train(dp_info* dp) 619 { 620 TRACE("%s\n", __func__); 621 622 const char* voltageNames[] = { 623 "0.4V", "0.6V", "0.8V", "1.2V" 624 }; 625 const char* preEmphasisNames[] = { 626 "0dB", "3.5dB", "6dB", "9.5dB" 627 }; 628 629 uint8 voltage = 0; 630 uint8 preEmphasis = 0; 631 int lane; 632 633 for (lane = 0; lane < dp->laneCount; lane++) { 634 uint8 laneVoltage = dp_get_adjust_request_voltage(dp, lane); 635 uint8 lanePreEmphasis = dp_get_adjust_request_pre_emphasis(dp, lane); 636 637 TRACE("%s: Requested %s at %s for lane %d\n", __func__, 638 preEmphasisNames[lanePreEmphasis >> DP_TRAIN_PRE_EMPHASIS_SHIFT], 639 voltageNames[laneVoltage >> DP_TRAIN_VCC_SWING_SHIFT], 640 lane); 641 642 if (laneVoltage > voltage) 643 voltage = laneVoltage; 644 if (lanePreEmphasis > preEmphasis) 645 preEmphasis = lanePreEmphasis; 646 } 647 648 // Check for maximum voltage and toggle max if reached 649 if (voltage >= DP_TRAIN_VCC_SWING_1200) 650 voltage |= DP_TRAIN_MAX_SWING_EN; 651 652 // Check for maximum pre-emphasis and toggle max if reached 653 if (preEmphasis >= DP_TRAIN_PRE_EMPHASIS_9_5) 654 preEmphasis |= DP_TRAIN_MAX_EMPHASIS_EN; 655 656 for (lane = 0; lane < 4; lane++) 657 dp->trainingSet[lane] = voltage | preEmphasis; 658 } 659 660 661 static void 662 dp_set_tp(uint32 connectorIndex, int trainingPattern) 663 { 664 TRACE("%s\n", __func__); 665 666 radeon_shared_info &info = *gInfo->shared_info; 667 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 668 pll_info* pll = &gConnector[connectorIndex]->encoder.pll; 669 670 int rawTrainingPattern = 0; 671 672 /* set training pattern on the source */ 673 if (info.dceMajor >= 4 || !dp->trainingUseEncoder) { 674 switch (trainingPattern) { 675 case DP_TRAIN_PATTERN_1: 676 rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; 677 break; 678 case DP_TRAIN_PATTERN_2: 679 rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; 680 break; 681 case DP_TRAIN_PATTERN_3: 682 rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; 683 break; 684 } 685 encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern); 686 } else { 687 ERROR("%s: TODO: dp_encoder_service\n", __func__); 688 return; 689 #if 0 690 switch (trainingPattern) { 691 case DP_TRAINING_PATTERN_1: 692 rawTrainingPattern = 0; 693 break; 694 case DP_TRAINING_PATTERN_2: 695 rawTrainingPattern = 1; 696 break; 697 } 698 radeon_dp_encoder_service(dp_info->rdev, 699 ATOM_DP_ACTION_TRAINING_PATTERN_SEL, dp_info->dp_clock, 700 dp_info->enc_id, rawTrainingPattern); 701 #endif 702 } 703 704 // Enable training pattern on the sink 705 dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern); 706 } 707 708 709 status_t 710 dp_link_train_cr(uint32 connectorIndex) 711 { 712 TRACE("%s\n", __func__); 713 714 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 715 716 // Display Port Clock Recovery Training 717 718 bool clockRecovery = false; 719 uint8 voltage = 0xff; 720 int lane; 721 722 dp_set_tp(connectorIndex, DP_TRAIN_PATTERN_1); 723 memset(dp->trainingSet, 0, 4); 724 dp_update_vs_emph(connectorIndex); 725 snooze(400); 726 727 while (1) { 728 if (dp->trainingReadInterval == 0) 729 snooze(100); 730 else 731 snooze(1000 * 4 * dp->trainingReadInterval); 732 733 if (!dp_get_link_status(connectorIndex)) 734 break; 735 736 if (dp_clock_recovery_ok(dp)) { 737 clockRecovery = true; 738 break; 739 } 740 741 for (lane = 0; lane < dp->laneCount; lane++) { 742 if ((dp->trainingSet[lane] & DP_TRAIN_MAX_SWING_EN) == 0) 743 break; 744 } 745 746 if (lane == dp->laneCount) { 747 ERROR("%s: clock recovery reached max voltage\n", __func__); 748 break; 749 } 750 751 if ((dp->trainingSet[0] & DP_TRAIN_VCC_SWING_MASK) == voltage) { 752 dp->trainingAttempts++; 753 if (dp->trainingAttempts >= 5) { 754 ERROR("%s: clock recovery tried 5 times\n", __func__); 755 break; 756 } 757 } else 758 dp->trainingAttempts = 0; 759 760 voltage = dp->trainingSet[0] & DP_TRAIN_VCC_SWING_MASK; 761 762 // Compute new trainingSet as requested by sink 763 dp_get_adjust_train(dp); 764 765 dp_update_vs_emph(connectorIndex); 766 } 767 768 if (!clockRecovery) { 769 ERROR("%s: clock recovery failed\n", __func__); 770 return B_ERROR; 771 } 772 773 TRACE("%s: clock recovery at voltage %d pre-emphasis %d\n", 774 __func__, dp->trainingSet[0] & DP_TRAIN_VCC_SWING_MASK, 775 (dp->trainingSet[0] & DP_TRAIN_PRE_EMPHASIS_MASK) 776 >> DP_TRAIN_PRE_EMPHASIS_SHIFT); 777 return B_OK; 778 } 779 780 781 status_t 782 dp_link_train_ce(uint32 connectorIndex, bool tp3Support) 783 { 784 TRACE("%s\n", __func__); 785 786 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 787 788 if (tp3Support) 789 dp_set_tp(connectorIndex, DP_TRAIN_PATTERN_3); 790 else 791 dp_set_tp(connectorIndex, DP_TRAIN_PATTERN_2); 792 793 dp->trainingAttempts = 0; 794 bool channelEqual = false; 795 796 while (1) { 797 if (dp->trainingReadInterval == 0) 798 snooze(400); 799 else 800 snooze(1000 * 4 * dp->trainingReadInterval); 801 802 if (!dp_get_link_status(connectorIndex)) { 803 ERROR("%s: ERROR: Unable to get link status!\n", __func__); 804 break; 805 } 806 807 if (dp_clock_equalization_ok(dp)) { 808 channelEqual = true; 809 break; 810 } 811 812 if (dp->trainingAttempts > 5) { 813 ERROR("%s: ERROR: failed > 5 times!\n", __func__); 814 break; 815 } 816 817 dp_get_adjust_train(dp); 818 819 dp_update_vs_emph(connectorIndex); 820 dp->trainingAttempts++; 821 } 822 823 if (!channelEqual) { 824 ERROR("%s: ERROR: failed\n", __func__); 825 return B_ERROR; 826 } 827 828 TRACE("%s: channels equalized at voltage %d pre-emphasis %d\n", 829 __func__, dp->trainingSet[0] & DP_ADJ_VCC_SWING_LANEA_MASK, 830 (dp->trainingSet[0] & DP_TRAIN_PRE_EMPHASIS_MASK) 831 >> DP_TRAIN_PRE_EMPHASIS_SHIFT); 832 833 return B_OK; 834 } 835 836 837 status_t 838 dp_link_train(uint8 crtcID) 839 { 840 TRACE("%s\n", __func__); 841 842 uint32 connectorIndex = gDisplay[crtcID]->connectorIndex; 843 dp_info* dp = &gConnector[connectorIndex]->dpInfo; 844 display_mode* mode = &gDisplay[crtcID]->currentMode; 845 846 if (dp->valid != true) { 847 ERROR("%s: started on invalid DisplayPort connector #%" B_PRIu32 "\n", 848 __func__, connectorIndex); 849 return B_ERROR; 850 } 851 852 int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); 853 // Table version 854 uint8 tableMajor; 855 uint8 tableMinor; 856 857 dp->trainingUseEncoder = true; 858 if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor) 859 == B_OK) { 860 if (tableMinor > 1) { 861 // The AtomBIOS DPEncoderService greater then 1.1 can't program the 862 // training pattern properly. 863 dp->trainingUseEncoder = false; 864 } 865 } 866 867 uint32 linkEnumeration 868 = gConnector[connectorIndex]->encoder.linkEnumeration; 869 870 uint32 dpEncoderID = 0; 871 if (encoder_pick_dig(connectorIndex) > 0) 872 dpEncoderID |= ATOM_DP_CONFIG_DIG2_ENCODER; 873 else 874 dpEncoderID |= ATOM_DP_CONFIG_DIG1_ENCODER; 875 if (linkEnumeration == GRAPH_OBJECT_ENUM_ID2) 876 dpEncoderID |= ATOM_DP_CONFIG_LINK_B; 877 else 878 dpEncoderID |= ATOM_DP_CONFIG_LINK_A; 879 880 dp->trainingReadInterval 881 = dpcd_reg_read(connectorIndex, DP_TRAINING_AUX_RD_INTERVAL); 882 883 uint8 sandbox = dpcd_reg_read(connectorIndex, DP_MAX_LANE_COUNT); 884 885 radeon_shared_info &info = *gInfo->shared_info; 886 bool dpTPS3Supported = false; 887 if (info.dceMajor >= 5 && (sandbox & DP_TPS3_SUPPORTED) != 0) 888 dpTPS3Supported = true; 889 890 // *** DisplayPort link training initialization 891 892 // Power up the DP sink 893 if (dp->config[0] >= DP_DPCD_REV_11) 894 dpcd_reg_write(connectorIndex, DP_SET_POWER, DP_SET_POWER_D0); 895 896 // Possibly enable downspread on the sink 897 if ((dp->config[3] & 0x1) != 0) { 898 dpcd_reg_write(connectorIndex, DP_DOWNSPREAD_CTRL, 899 DP_DOWNSPREAD_CTRL_AMP_EN); 900 } else 901 dpcd_reg_write(connectorIndex, DP_DOWNSPREAD_CTRL, 0); 902 903 encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, 904 ATOM_ENCODER_CMD_SETUP_PANEL_MODE); 905 906 // TODO: Doesn't this overwrite important dpcd info? 907 sandbox = dp->laneCount; 908 if ((dp->config[0] >= DP_DPCD_REV_11) 909 && (dp->config[2] & DP_ENHANCED_FRAME_CAP_EN)) 910 sandbox |= DP_ENHANCED_FRAME_EN; 911 dpcd_reg_write(connectorIndex, DP_LANE_COUNT, sandbox); 912 913 // Set the link rate on the DP sink 914 sandbox = dp_encode_link_rate(dp->linkRate); 915 dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox); 916 917 // Start link training on source 918 if (info.dceMajor >= 4 || !dp->trainingUseEncoder) { 919 encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, 920 ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); 921 } else { 922 ERROR("%s: TODO: cannot use AtomBIOS DPEncoderService on card!\n", 923 __func__); 924 } 925 926 // Disable the training pattern on the sink 927 dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED); 928 929 dp_link_train_cr(connectorIndex); 930 dp_link_train_ce(connectorIndex, dpTPS3Supported); 931 932 // *** DisplayPort link training finish 933 snooze(400); 934 935 // Disable the training pattern on the sink 936 dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED); 937 938 // Disable the training pattern on the source 939 if (info.dceMajor >= 4 || !dp->trainingUseEncoder) { 940 encoder_dig_setup(connectorIndex, mode->timing.pixel_clock, 941 ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); 942 } else { 943 ERROR("%s: TODO: cannot use AtomBIOS DPEncoderService on card!\n", 944 __func__); 945 } 946 947 return B_OK; 948 } 949 950 951 bool 952 ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* edid) 953 { 954 TRACE("%s\n", __func__); 955 956 dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo; 957 958 if (!dpInfo->valid) { 959 ERROR("%s: connector(%" B_PRIu32 ") missing valid DisplayPort data!\n", 960 __func__, connectorIndex); 961 return false; 962 } 963 964 edid1_raw raw; 965 uint8* rdata = (uint8*)&raw; 966 uint8 sdata = 0; 967 968 // The following sequence is from a trace of the Linux kernel 969 // radeon code; not sure if the initial writes to address 0 are 970 // requried. 971 // TODO: This surely cane be cleaned up 972 dp_aux_set_i2c_byte(connectorIndex, 0x00, &sdata, true, false); 973 dp_aux_set_i2c_byte(connectorIndex, 0x00, &sdata, false, true); 974 975 dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, true, false); 976 dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, false, false); 977 dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, true, false); 978 dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, false, false); 979 dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, false, true); 980 dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, true, false); 981 dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, false, false); 982 dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, true, false); 983 984 for (uint32 i = 0; i < sizeof(raw); i++) { 985 status_t result = dp_aux_get_i2c_byte(connectorIndex, 0x50, 986 rdata++, false, false); 987 if (result != B_OK) { 988 TRACE("%s: error reading EDID data at index %" B_PRIu32 ", " 989 "result = 0x%lX\n", __func__, i, result); 990 dp_aux_get_i2c_byte(connectorIndex, 0x50, &sdata, false, true); 991 return false; 992 } 993 } 994 dp_aux_get_i2c_byte(connectorIndex, 0x50, &sdata, false, true); 995 996 if (raw.version.version != 1 || raw.version.revision > 4) { 997 ERROR("%s: EDID version or revision out of range\n", __func__); 998 return false; 999 } 1000 1001 edid_decode(edid, &raw); 1002 1003 return true; 1004 } 1005 1006 1007 status_t 1008 dp_get_pixel_size_for(color_space space, size_t *pixelChunk, 1009 size_t *rowAlignment, size_t *pixelsPerChunk) 1010 { 1011 status_t result = get_pixel_size_for(space, pixelChunk, NULL, 1012 pixelsPerChunk); 1013 1014 if ((space == B_RGB32) || (space == B_RGBA32) || (space == B_RGB32_BIG) 1015 || (space == B_RGBA32_BIG)) { 1016 *pixelChunk = 3; 1017 } 1018 1019 return result; 1020 } 1021 1022 1023 bool 1024 dp_is_dp12_capable(uint32 connectorIndex) 1025 { 1026 TRACE("%s\n", __func__); 1027 radeon_shared_info &info = *gInfo->shared_info; 1028 1029 uint32 capabilities = gConnector[connectorIndex]->encoder.capabilities; 1030 1031 if (info.dceMajor >= 5 1032 && gInfo->dpExternalClock >= 539000 1033 && (capabilities & ATOM_ENCODER_CAP_RECORD_HBR2) != 0) { 1034 return true; 1035 } 1036 1037 return false; 1038 } 1039 1040 1041 void 1042 debug_dp_info() 1043 { 1044 ERROR("Current DisplayPort Info =================\n"); 1045 for (uint32 id = 0; id < ATOM_MAX_SUPPORTED_DEVICE; id++) { 1046 if (gConnector[id]->valid == true) { 1047 dp_info* dp = &gConnector[id]->dpInfo; 1048 ERROR("Connector #%" B_PRIu32 ") DP: %s\n", id, 1049 dp->valid ? "true" : "false"); 1050 1051 if (!dp->valid) 1052 continue; 1053 ERROR(" + DP Config Data\n"); 1054 ERROR(" - max lane count: %d\n", 1055 dp->config[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK); 1056 ERROR(" - max link rate: %d\n", 1057 dp->config[DP_MAX_LINK_RATE]); 1058 ERROR(" - receiver port count: %d\n", 1059 dp->config[DP_NORP] & DP_NORP_MASK); 1060 ERROR(" - downstream port present: %s\n", 1061 (dp->config[DP_DOWNSTREAMPORT] & DP_DOWNSTREAMPORT_EN) 1062 ? "yes" : "no"); 1063 ERROR(" - downstream port count: %d\n", 1064 dp->config[DP_DOWNSTREAMPORT_COUNT] 1065 & DP_DOWNSTREAMPORT_COUNT_MASK); 1066 ERROR(" + Training\n"); 1067 ERROR(" - use encoder: %s\n", 1068 dp->trainingUseEncoder ? "true" : "false"); 1069 ERROR(" - attempts: %" B_PRIu8 "\n", 1070 dp->trainingAttempts); 1071 ERROR(" - delay: %d\n", 1072 dp->trainingReadInterval); 1073 ERROR(" + Data\n"); 1074 ERROR(" - auxPin: 0x%" B_PRIX32"\n", dp->auxPin); 1075 ERROR(" + Video\n"); 1076 ERROR(" - laneCount: %d\n", dp->laneCount); 1077 ERROR(" - linkRate: %" B_PRIu32 "\n", 1078 dp->linkRate); 1079 } 1080 } 1081 ERROR("==========================================\n"); 1082 } 1083