radeon_hd: Improve tracing; implement older DCE3 DP training.

* Implement older DCE 3 DisplayPort Training Service.
This commit is contained in:
Alexander von Gluck IV 2017-09-12 10:15:59 -05:00
parent ce1ac42908
commit b82657abfb
3 changed files with 94 additions and 21 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016, Haiku, Inc. All Rights Reserved.
* Copyright 2016-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -21,4 +21,22 @@
#define ATOM_S2_DFP5_DPMS_STATE 0x08000000L
// ucAction
#define ATOM_DP_ACTION_TRAINING_START 0x02
#define ATOM_DP_ACTION_TRAINING_COMPLETE 0x03
#define ATOM_DP_ACTION_TRAINING_PATTERN_SEL 0x04
#define ATOM_DP_ACTION_SET_VSWING_PREEMP 0x05
#define ATOM_DP_ACTION_GET_VSWING_PREEMP 0x06
#define ATOM_DP_ACTION_BLANKING 0x07
// ucConfig
#define ATOM_DP_CONFIG_ENCODER_SEL_MASK 0x03
#define ATOM_DP_CONFIG_DIG1_ENCODER 0x00
#define ATOM_DP_CONFIG_DIG2_ENCODER 0x01
#define ATOM_DP_CONFIG_EXTERNAL_ENCODER 0x02
#define ATOM_DP_CONFIG_LINK_SEL_MASK 0x04
#define ATOM_DP_CONFIG_LINK_A 0x00
#define ATOM_DP_CONFIG_LINK_B 0x04
#endif /* _ATOMBIOS_OBSOLETE_H */

View File

@ -13,6 +13,7 @@
#include <Debug.h>
#include "accelerant_protos.h"
#include "atombios-obsolete.h"
#include "connector.h"
#include "mode.h"
#include "edid.h"
@ -327,6 +328,28 @@ dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data,
}
uint32
dp_get_encoder_config(uint32 connectorIndex)
{
uint32 result = 0;
uint32 digEncoderID = encoder_pick_dig(connectorIndex);
if (digEncoderID)
result |= ATOM_DP_CONFIG_DIG2_ENCODER;
else
result |= ATOM_DP_CONFIG_DIG1_ENCODER;
bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
== GRAPH_OBJECT_ENUM_ID2 ? true : false;
if (linkB)
result |= ATOM_DP_CONFIG_LINK_B;
else
result |= ATOM_DP_CONFIG_LINK_A;
return result;
}
uint32
dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
{
@ -541,17 +564,21 @@ dp_clock_equalization_ok(dp_info* dp)
uint8 laneAlignment
= dp->linkStatus[DP_LANE_ALIGN - DP_LANE_STATUS_0_1];
if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0)
if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0) {
TRACE("%s: false. Lane alignment incomplete.\n", __func__);
return false;
}
int lane;
for (lane = 0; lane < dp->laneCount; lane++) {
uint8 laneStatus = dp_get_lane_status(dp, lane);
if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A)
!= DP_LANE_STATUS_EQUALIZED_A) {
TRACE("%s: false. Lanes not yet equalized.\n", __func__);
return false;
}
}
TRACE("%s: true. Lanes equalized.\n", __func__);
return true;
}
@ -649,24 +676,39 @@ static void
dp_set_tp(uint32 connectorIndex, int trainingPattern)
{
TRACE("%s\n", __func__);
radeon_shared_info &info = *gInfo->shared_info;
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
int rawTrainingPattern = 0;
/* set training pattern on the source */
TRACE("%s: Training with encoder...\n", __func__);
switch (trainingPattern) {
case DP_TRAIN_PATTERN_1:
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
break;
case DP_TRAIN_PATTERN_2:
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
break;
case DP_TRAIN_PATTERN_3:
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
break;
if (info.dceMajor >= 4) {
TRACE("%s: Training with encoder...\n", __func__);
switch (trainingPattern) {
case DP_TRAIN_PATTERN_1:
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
break;
case DP_TRAIN_PATTERN_2:
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
break;
case DP_TRAIN_PATTERN_3:
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
break;
}
encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
} else {
switch (trainingPattern) {
case DP_TRAIN_PATTERN_1:
rawTrainingPattern = 0;
break;
case DP_TRAIN_PATTERN_2:
rawTrainingPattern = 1;
break;
}
uint32 encoderConfig = dp_get_encoder_config(connectorIndex);
dp_encoder_service(ATOM_DP_ACTION_TRAINING_PATTERN_SEL, pll->pixelClock,
rawTrainingPattern, encoderConfig);
}
encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
// Enable training pattern on the sink
dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern);
@ -676,7 +718,7 @@ dp_set_tp(uint32 connectorIndex, int trainingPattern)
status_t
dp_link_train_cr(uint32 connectorIndex)
{
TRACE("%s\n", __func__);
TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
@ -748,7 +790,7 @@ dp_link_train_cr(uint32 connectorIndex)
status_t
dp_link_train_ce(uint32 connectorIndex, bool tp3Support)
{
TRACE("%s\n", __func__);
TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
@ -853,9 +895,16 @@ dp_link_train(uint8 crtcID)
sandbox = dp_encode_link_rate(dp->linkRate);
dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
uint32 encoderConfig = dp_get_encoder_config(connectorIndex);
// Start link training on source
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
if (info.dceMajor >= 4) {
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
} else {
dp_encoder_service(ATOM_DP_ACTION_TRAINING_START,
mode->timing.pixel_clock, 0, encoderConfig);
}
// Disable the training pattern on the sink
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
@ -870,8 +919,13 @@ dp_link_train(uint8 crtcID)
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
// Disable the training pattern on the source
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
if (info.dceMajor >= 4) {
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
} else {
dp_encoder_service(ATOM_DP_ACTION_TRAINING_COMPLETE,
mode->timing.pixel_clock, 0, encoderConfig);
}
return B_OK;
}

View File

@ -36,6 +36,7 @@ status_t dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address,
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode);
uint32 dp_get_encoder_config(uint32 connectorIndex);
uint8 dp_get_sink_type(uint32 connectorIndex);
void dp_setup_connectors();