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