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