radeon_hd: Rework dp aux functions to take connector index
* This is less pretty, but we need access to the connector to find the HPD gpio pin mask on the card. * dp_aux communications seem to work again. * If you have a DisplayPort item attached to your card you may want to just unplug it at this point. We attempt DP link training and it fails. This failure will also cause other monitors to not function as app_server still isn't multi-head aware (#10486)
This commit is contained in:
@@ -258,4 +258,4 @@
|
|||||||
#define EVERGREEN_DC_GPIO_HPD_Y 0x64bc
|
#define EVERGREEN_DC_GPIO_HPD_Y 0x64bc
|
||||||
|
|
||||||
|
|
||||||
#endif /* __EVERGREEN_REG_H__ */
|
#endif /* __EVERGREEN_REG_H__ */
|
||||||
|
|||||||
@@ -304,6 +304,7 @@
|
|||||||
#define SI_LB_D6_VBLANK_INTERRUPT (1 << 3)
|
#define SI_LB_D6_VBLANK_INTERRUPT (1 << 3)
|
||||||
#define SI_DC_HPD6_INTERRUPT (1 << 17)
|
#define SI_DC_HPD6_INTERRUPT (1 << 17)
|
||||||
#define SI_DC_HPD6_RX_INTERRUPT (1 << 18)
|
#define SI_DC_HPD6_RX_INTERRUPT (1 << 18)
|
||||||
|
#define SI_DC_GPIO_HPD_A 0x65b4
|
||||||
|
|
||||||
/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */
|
/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */
|
||||||
#define SI_GRPH_INT_STATUS 0x6858
|
#define SI_GRPH_INT_STATUS 0x6858
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ typedef struct {
|
|||||||
uint16 hpdPinIndex; // id of gpio pin for hotplug detection
|
uint16 hpdPinIndex; // id of gpio pin for hotplug detection
|
||||||
struct encoder_info encoder;
|
struct encoder_info encoder;
|
||||||
struct encoder_info encoderExternal;
|
struct encoder_info encoderExternal;
|
||||||
// TODO struct radeon_hpd hpd;
|
|
||||||
dp_info dpInfo;
|
dp_info dpInfo;
|
||||||
} connector_info;
|
} connector_info;
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,13 @@
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
dp_aux_speak(uint32 hwPin, uint8* send, int sendBytes,
|
dp_aux_speak(uint32 connectorIndex, uint8* send, int sendBytes,
|
||||||
uint8* recv, int recvBytes, uint8 delay, uint8* ack)
|
uint8* recv, int recvBytes, uint8 delay, uint8* ack)
|
||||||
{
|
{
|
||||||
if (hwPin == 0) {
|
radeon_shared_info &info = *gInfo->shared_info;
|
||||||
|
|
||||||
|
dp_info* dpInfo = &gConnector[connectorIndex]->dpInfo;
|
||||||
|
if (dpInfo->auxPin == 0) {
|
||||||
ERROR("%s: cannot speak on invalid GPIO pin!\n", __func__);
|
ERROR("%s: cannot speak on invalid GPIO pin!\n", __func__);
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
@@ -52,11 +55,46 @@ dp_aux_speak(uint32 hwPin, uint8* send, int sendBytes,
|
|||||||
args.v1.lpAuxRequest = B_HOST_TO_LENDIAN_INT16(0 + 4);
|
args.v1.lpAuxRequest = B_HOST_TO_LENDIAN_INT16(0 + 4);
|
||||||
args.v1.lpDataOut = B_HOST_TO_LENDIAN_INT16(16 + 4);
|
args.v1.lpDataOut = B_HOST_TO_LENDIAN_INT16(16 + 4);
|
||||||
args.v1.ucDataOutLen = 0;
|
args.v1.ucDataOutLen = 0;
|
||||||
args.v1.ucChannelID = hwPin;
|
args.v1.ucChannelID = dpInfo->auxPin;
|
||||||
args.v1.ucDelay = delay / 10;
|
args.v1.ucDelay = delay / 10;
|
||||||
|
|
||||||
//if (ASIC_IS_DCE4(rdev))
|
uint16 hpdPinIndex = gConnector[connectorIndex]->hpdPinIndex;
|
||||||
// args.v2.ucHPD_ID = chan->rec.hpd;
|
if (info.dceMajor >= 4
|
||||||
|
&& gGPIOInfo[hpdPinIndex]->valid) {
|
||||||
|
|
||||||
|
uint32 targetReg = EVERGREEN_DC_GPIO_HPD_A;
|
||||||
|
if (info.dceMajor >= 6)
|
||||||
|
targetReg = SI_DC_GPIO_HPD_A;
|
||||||
|
|
||||||
|
// You're drunk AMD, go home. (this makes no sense)
|
||||||
|
if (gGPIOInfo[hpdPinIndex]->hwReg == targetReg) {
|
||||||
|
switch(gGPIOInfo[hpdPinIndex]->hwMask) {
|
||||||
|
case (1 << 0):
|
||||||
|
args.v2.ucHPD_ID = 0;
|
||||||
|
break;
|
||||||
|
case (1 << 8):
|
||||||
|
args.v2.ucHPD_ID = 1;
|
||||||
|
break;
|
||||||
|
case (1 << 16):
|
||||||
|
args.v2.ucHPD_ID = 2;
|
||||||
|
break;
|
||||||
|
case (1 << 24):
|
||||||
|
args.v2.ucHPD_ID = 3;
|
||||||
|
break;
|
||||||
|
case (1 << 26):
|
||||||
|
args.v2.ucHPD_ID = 4;
|
||||||
|
break;
|
||||||
|
case (1 << 28):
|
||||||
|
args.v2.ucHPD_ID = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
args.v2.ucHPD_ID = 0xff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args.v2.ucHPD_ID = 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* base = (unsigned char*)(gAtomContext->scratch + 1);
|
unsigned char* base = (unsigned char*)(gAtomContext->scratch + 1);
|
||||||
|
|
||||||
@@ -94,7 +132,7 @@ dp_aux_speak(uint32 hwPin, uint8* send, int sendBytes,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
dp_aux_write(uint32 hwPin, uint16 address,
|
dp_aux_write(uint32 connectorIndex, uint16 address,
|
||||||
uint8* send, uint8 sendBytes, uint8 delay)
|
uint8* send, uint8 sendBytes, uint8 delay)
|
||||||
{
|
{
|
||||||
uint8 auxMessage[20];
|
uint8 auxMessage[20];
|
||||||
@@ -114,8 +152,8 @@ dp_aux_write(uint32 hwPin, uint16 address,
|
|||||||
uint8 retry;
|
uint8 retry;
|
||||||
for (retry = 0; retry < 7; retry++) {
|
for (retry = 0; retry < 7; retry++) {
|
||||||
uint8 ack;
|
uint8 ack;
|
||||||
status_t result = dp_aux_speak(hwPin, auxMessage, auxMessageBytes,
|
status_t result = dp_aux_speak(connectorIndex, auxMessage,
|
||||||
NULL, 0, delay, &ack);
|
auxMessageBytes, NULL, 0, delay, &ack);
|
||||||
|
|
||||||
if (result == B_BUSY)
|
if (result == B_BUSY)
|
||||||
continue;
|
continue;
|
||||||
@@ -137,7 +175,7 @@ dp_aux_write(uint32 hwPin, uint16 address,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
dp_aux_read(uint32 hwPin, uint16 address,
|
dp_aux_read(uint32 connectorIndex, uint16 address,
|
||||||
uint8* recv, int recvBytes, uint8 delay)
|
uint8* recv, int recvBytes, uint8 delay)
|
||||||
{
|
{
|
||||||
uint8 auxMessage[4];
|
uint8 auxMessage[4];
|
||||||
@@ -151,8 +189,8 @@ dp_aux_read(uint32 hwPin, uint16 address,
|
|||||||
uint8 retry;
|
uint8 retry;
|
||||||
for (retry = 0; retry < 7; retry++) {
|
for (retry = 0; retry < 7; retry++) {
|
||||||
uint8 ack;
|
uint8 ack;
|
||||||
status_t result = dp_aux_speak(hwPin, auxMessage, auxMessageBytes,
|
status_t result = dp_aux_speak(connectorIndex, auxMessage,
|
||||||
recv, recvBytes, delay, &ack);
|
auxMessageBytes, recv, recvBytes, delay, &ack);
|
||||||
|
|
||||||
if (result == B_BUSY)
|
if (result == B_BUSY)
|
||||||
continue;
|
continue;
|
||||||
@@ -174,19 +212,19 @@ dp_aux_read(uint32 hwPin, uint16 address,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dpcd_reg_write(uint32 hwPin, uint16 address, uint8 value)
|
dpcd_reg_write(uint32 connectorIndex, uint16 address, uint8 value)
|
||||||
{
|
{
|
||||||
status_t result = dp_aux_write(hwPin, address, &value, 1, 0);
|
status_t result = dp_aux_write(connectorIndex, address, &value, 1, 0);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
ERROR("%s: error on DisplayPort aux write (0x%lX)\n", __func__, result);
|
ERROR("%s: error on DisplayPort aux write (0x%lX)\n", __func__, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8
|
uint8
|
||||||
dpcd_reg_read(uint32 hwPin, uint16 address)
|
dpcd_reg_read(uint32 connectorIndex, uint16 address)
|
||||||
{
|
{
|
||||||
uint8 value = 0;
|
uint8 value = 0;
|
||||||
status_t result = dp_aux_read(hwPin, address, &value, 1, 0);
|
status_t result = dp_aux_read(connectorIndex, address, &value, 1, 0);
|
||||||
if (result != B_OK)
|
if (result != B_OK)
|
||||||
ERROR("%s: error on DisplayPort aux read (0x%lX)\n", __func__, result);
|
ERROR("%s: error on DisplayPort aux read (0x%lX)\n", __func__, result);
|
||||||
|
|
||||||
@@ -195,7 +233,7 @@ dpcd_reg_read(uint32 hwPin, uint16 address)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* data,
|
dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data,
|
||||||
bool start, bool stop)
|
bool start, bool stop)
|
||||||
{
|
{
|
||||||
uint8 auxMessage[5];
|
uint8 auxMessage[5];
|
||||||
@@ -217,15 +255,14 @@ dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* data,
|
|||||||
auxMessageBytes = 4;
|
auxMessageBytes = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int retry;
|
int retry;
|
||||||
for (retry = 0; retry < 4; retry++) {
|
for (retry = 0; retry < 4; retry++) {
|
||||||
uint8 ack;
|
uint8 ack;
|
||||||
uint8 reply[2];
|
uint8 reply[2];
|
||||||
int replyBytes = 1;
|
int replyBytes = 1;
|
||||||
|
|
||||||
status_t result = dp_aux_speak(hwPin, auxMessage, auxMessageBytes,
|
status_t result = dp_aux_speak(connectorIndex, auxMessage,
|
||||||
reply, replyBytes, 0, &ack);
|
auxMessageBytes, reply, replyBytes, 0, &ack);
|
||||||
if (result == B_BUSY)
|
if (result == B_BUSY)
|
||||||
continue;
|
continue;
|
||||||
else if (result != B_OK) {
|
else if (result != B_OK) {
|
||||||
@@ -274,7 +311,7 @@ dp_aux_get_i2c_byte(uint32 hwPin, uint16 address, uint8* data,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* data,
|
dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data,
|
||||||
bool start, bool stop)
|
bool start, bool stop)
|
||||||
{
|
{
|
||||||
uint8 auxMessage[5];
|
uint8 auxMessage[5];
|
||||||
@@ -303,8 +340,8 @@ dp_aux_set_i2c_byte(uint32 hwPin, uint16 address, uint8* data,
|
|||||||
uint8 reply[2];
|
uint8 reply[2];
|
||||||
int replyBytes = 1;
|
int replyBytes = 1;
|
||||||
|
|
||||||
status_t result = dp_aux_speak(hwPin, auxMessage, auxMessageBytes,
|
status_t result = dp_aux_speak(connectorIndex, auxMessage,
|
||||||
reply, replyBytes, 0, &ack);
|
auxMessageBytes, reply, replyBytes, 0, &ack);
|
||||||
if (result == B_BUSY)
|
if (result == B_BUSY)
|
||||||
continue;
|
continue;
|
||||||
else if (result != B_OK) {
|
else if (result != B_OK) {
|
||||||
@@ -455,7 +492,7 @@ dp_setup_connectors()
|
|||||||
|
|
||||||
uint8 auxMessage[DP_DPCD_SIZE];
|
uint8 auxMessage[DP_DPCD_SIZE];
|
||||||
|
|
||||||
status_t result = dp_aux_read(auxPin, DP_DPCD_REV, auxMessage,
|
status_t result = dp_aux_read(index, DP_DPCD_REV, auxMessage,
|
||||||
DP_DPCD_SIZE, 0);
|
DP_DPCD_SIZE, 0);
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
@@ -476,10 +513,11 @@ dp_setup_connectors()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
dp_get_link_status(dp_info* dp)
|
dp_get_link_status(uint32 connectorIndex)
|
||||||
{
|
{
|
||||||
status_t result = dp_aux_read(dp->auxPin, DP_LANE_STATUS_0_1,
|
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
|
||||||
|
status_t result = dp_aux_read(connectorIndex, DP_LANE_STATUS_0_1,
|
||||||
dp->linkStatus, DP_LINK_STATUS_SIZE, 100);
|
dp->linkStatus, DP_LINK_STATUS_SIZE, 100);
|
||||||
|
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
@@ -547,7 +585,7 @@ dp_update_vs_emph(uint32 connectorIndex)
|
|||||||
dp->trainingSet[0], ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH);
|
dp->trainingSet[0], ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH);
|
||||||
|
|
||||||
// Set vs and emph on the sink
|
// Set vs and emph on the sink
|
||||||
dp_aux_write(dp->auxPin, DP_TRAIN_LANE0,
|
dp_aux_write(connectorIndex, DP_TRAIN_LANE0,
|
||||||
dp->trainingSet, dp->laneCount, 0);
|
dp->trainingSet, dp->laneCount, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,7 +702,7 @@ dp_set_tp(uint32 connectorIndex, int trainingPattern)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enable training pattern on the sink
|
// Enable training pattern on the sink
|
||||||
dpcd_reg_write(dp->auxPin, DP_TRAIN, trainingPattern);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -692,7 +730,7 @@ dp_link_train_cr(uint32 connectorIndex)
|
|||||||
else
|
else
|
||||||
snooze(1000 * 4 * dp->trainingReadInterval);
|
snooze(1000 * 4 * dp->trainingReadInterval);
|
||||||
|
|
||||||
if (!dp_get_link_status(dp))
|
if (!dp_get_link_status(connectorIndex))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (dp_clock_recovery_ok(dp)) {
|
if (dp_clock_recovery_ok(dp)) {
|
||||||
@@ -759,7 +797,7 @@ dp_link_train_ce(uint32 connectorIndex)
|
|||||||
else
|
else
|
||||||
snooze(1000 * 4 * dp->trainingReadInterval);
|
snooze(1000 * 4 * dp->trainingReadInterval);
|
||||||
|
|
||||||
if (!dp_get_link_status(dp))
|
if (!dp_get_link_status(connectorIndex))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (dp_clock_equalization_ok(dp)) {
|
if (dp_clock_equalization_ok(dp)) {
|
||||||
@@ -824,8 +862,6 @@ dp_link_train(uint8 crtcID)
|
|||||||
|
|
||||||
uint32 linkEnumeration
|
uint32 linkEnumeration
|
||||||
= gConnector[connectorIndex]->encoder.linkEnumeration;
|
= gConnector[connectorIndex]->encoder.linkEnumeration;
|
||||||
uint32 i2cPinIndex = gConnector[connectorIndex]->i2cPinIndex;
|
|
||||||
uint32 hwPin = gGPIOInfo[i2cPinIndex]->hwPin;
|
|
||||||
|
|
||||||
uint32 dpEncoderID = 0;
|
uint32 dpEncoderID = 0;
|
||||||
if (encoder_pick_dig(connectorIndex) > 0)
|
if (encoder_pick_dig(connectorIndex) > 0)
|
||||||
@@ -838,9 +874,9 @@ dp_link_train(uint8 crtcID)
|
|||||||
dpEncoderID |= ATOM_DP_CONFIG_LINK_A;
|
dpEncoderID |= ATOM_DP_CONFIG_LINK_A;
|
||||||
|
|
||||||
dp->trainingReadInterval
|
dp->trainingReadInterval
|
||||||
= dpcd_reg_read(hwPin, DP_TRAINING_AUX_RD_INTERVAL);
|
= dpcd_reg_read(connectorIndex, DP_TRAINING_AUX_RD_INTERVAL);
|
||||||
|
|
||||||
uint8 sandbox = dpcd_reg_read(hwPin, DP_MAX_LANE_COUNT);
|
uint8 sandbox = dpcd_reg_read(connectorIndex, DP_MAX_LANE_COUNT);
|
||||||
|
|
||||||
radeon_shared_info &info = *gInfo->shared_info;
|
radeon_shared_info &info = *gInfo->shared_info;
|
||||||
//bool dpTPS3Supported = false;
|
//bool dpTPS3Supported = false;
|
||||||
@@ -851,13 +887,14 @@ dp_link_train(uint8 crtcID)
|
|||||||
|
|
||||||
// Power up the DP sink
|
// Power up the DP sink
|
||||||
if (dp->config[0] >= DP_DPCD_REV_11)
|
if (dp->config[0] >= DP_DPCD_REV_11)
|
||||||
dpcd_reg_write(hwPin, DP_SET_POWER, DP_SET_POWER_D0);
|
dpcd_reg_write(connectorIndex, DP_SET_POWER, DP_SET_POWER_D0);
|
||||||
|
|
||||||
// Possibly enable downspread on the sink
|
// Possibly enable downspread on the sink
|
||||||
if ((dp->config[3] & 0x1) != 0)
|
if ((dp->config[3] & 0x1) != 0) {
|
||||||
dpcd_reg_write(hwPin, DP_DOWNSPREAD_CTRL, DP_DOWNSPREAD_CTRL_AMP_EN);
|
dpcd_reg_write(connectorIndex, DP_DOWNSPREAD_CTRL,
|
||||||
else
|
DP_DOWNSPREAD_CTRL_AMP_EN);
|
||||||
dpcd_reg_write(hwPin, DP_DOWNSPREAD_CTRL, 0);
|
} else
|
||||||
|
dpcd_reg_write(connectorIndex, DP_DOWNSPREAD_CTRL, 0);
|
||||||
|
|
||||||
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
||||||
ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
|
ATOM_ENCODER_CMD_SETUP_PANEL_MODE);
|
||||||
@@ -867,11 +904,11 @@ dp_link_train(uint8 crtcID)
|
|||||||
if ((dp->config[0] >= DP_DPCD_REV_11)
|
if ((dp->config[0] >= DP_DPCD_REV_11)
|
||||||
&& (dp->config[2] & DP_ENHANCED_FRAME_CAP_EN))
|
&& (dp->config[2] & DP_ENHANCED_FRAME_CAP_EN))
|
||||||
sandbox |= DP_ENHANCED_FRAME_EN;
|
sandbox |= DP_ENHANCED_FRAME_EN;
|
||||||
dpcd_reg_write(hwPin, DP_LANE_COUNT, sandbox);
|
dpcd_reg_write(connectorIndex, DP_LANE_COUNT, sandbox);
|
||||||
|
|
||||||
// Set the link rate on the DP sink
|
// Set the link rate on the DP sink
|
||||||
sandbox = dp_encode_link_rate(dp->linkRate);
|
sandbox = dp_encode_link_rate(dp->linkRate);
|
||||||
dpcd_reg_write(hwPin, DP_LINK_RATE, sandbox);
|
dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
|
||||||
|
|
||||||
// Start link training on source
|
// Start link training on source
|
||||||
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
||||||
@@ -883,7 +920,7 @@ dp_link_train(uint8 crtcID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Disable the training pattern on the sink
|
// Disable the training pattern on the sink
|
||||||
dpcd_reg_write(hwPin, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
||||||
|
|
||||||
dp_link_train_cr(connectorIndex);
|
dp_link_train_cr(connectorIndex);
|
||||||
dp_link_train_ce(connectorIndex);
|
dp_link_train_ce(connectorIndex);
|
||||||
@@ -892,7 +929,7 @@ dp_link_train(uint8 crtcID)
|
|||||||
snooze(400);
|
snooze(400);
|
||||||
|
|
||||||
// Disable the training pattern on the sink
|
// Disable the training pattern on the sink
|
||||||
dpcd_reg_write(hwPin, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
||||||
|
|
||||||
// Disable the training pattern on the source
|
// Disable the training pattern on the source
|
||||||
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
if (info.dceMajor >= 4 || !dp->trainingUseEncoder) {
|
||||||
@@ -928,29 +965,29 @@ ddc2_dp_read_edid1(uint32 connectorIndex, edid1_info* edid)
|
|||||||
// radeon code; not sure if the initial writes to address 0 are
|
// radeon code; not sure if the initial writes to address 0 are
|
||||||
// requried.
|
// requried.
|
||||||
// TODO: This surely cane be cleaned up
|
// TODO: This surely cane be cleaned up
|
||||||
dp_aux_set_i2c_byte(dpInfo->auxPin, 0x00, &sdata, true, false);
|
dp_aux_set_i2c_byte(connectorIndex, 0x00, &sdata, true, false);
|
||||||
dp_aux_set_i2c_byte(dpInfo->auxPin, 0x00, &sdata, false, true);
|
dp_aux_set_i2c_byte(connectorIndex, 0x00, &sdata, false, true);
|
||||||
|
|
||||||
dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, true, false);
|
dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, true, false);
|
||||||
dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, false);
|
dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, false, false);
|
||||||
dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, true, false);
|
dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, true, false);
|
||||||
dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, false, false);
|
dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, false, false);
|
||||||
dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, false, true);
|
dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, false, true);
|
||||||
dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, true, false);
|
dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, true, false);
|
||||||
dp_aux_set_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, false);
|
dp_aux_set_i2c_byte(connectorIndex, 0x50, &sdata, false, false);
|
||||||
dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, rdata, true, false);
|
dp_aux_get_i2c_byte(connectorIndex, 0x50, rdata, true, false);
|
||||||
|
|
||||||
for (uint32 i = 0; i < sizeof(raw); i++) {
|
for (uint32 i = 0; i < sizeof(raw); i++) {
|
||||||
status_t result = dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50,
|
status_t result = dp_aux_get_i2c_byte(connectorIndex, 0x50,
|
||||||
rdata++, false, false);
|
rdata++, false, false);
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE("%s: error reading EDID data at index %" B_PRIu32 ", "
|
TRACE("%s: error reading EDID data at index %" B_PRIu32 ", "
|
||||||
"result = 0x%lX\n", __func__, i, result);
|
"result = 0x%lX\n", __func__, i, result);
|
||||||
dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, true);
|
dp_aux_get_i2c_byte(connectorIndex, 0x50, &sdata, false, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dp_aux_get_i2c_byte(dpInfo->auxPin, 0x50, &sdata, false, true);
|
dp_aux_get_i2c_byte(connectorIndex, 0x50, &sdata, false, true);
|
||||||
|
|
||||||
if (raw.version.version != 1 || raw.version.revision > 4) {
|
if (raw.version.version != 1 || raw.version.revision > 4) {
|
||||||
ERROR("%s: EDID version or revision out of range\n", __func__);
|
ERROR("%s: EDID version or revision out of range\n", __func__);
|
||||||
|
|||||||
@@ -23,18 +23,18 @@
|
|||||||
#define DP_TPS3_SUPPORTED (1 << 6) // Stored within MAX_LANE_COUNT
|
#define DP_TPS3_SUPPORTED (1 << 6) // Stored within MAX_LANE_COUNT
|
||||||
|
|
||||||
|
|
||||||
uint8 dpcd_reg_read(uint32 hwPin, uint16 address);
|
uint8 dpcd_reg_read(uint32 connectorIndex, uint16 address);
|
||||||
void dpcd_reg_write(uint32 hwPin, uint16 address, uint8 value);
|
void dpcd_reg_write(uint32 connectorIndex, uint16 address, uint8 value);
|
||||||
|
|
||||||
// Communication over DisplayPort AUX channel
|
// Communication over DisplayPort AUX channel
|
||||||
status_t dp_aux_write(uint32 hwPin, uint16 address, uint8* send,
|
status_t dp_aux_write(uint32 connectorIndex, uint16 address, uint8* send,
|
||||||
uint8 sendBytes, uint8 delay);
|
uint8 sendBytes, uint8 delay);
|
||||||
status_t dp_aux_read(uint32 hwPin, uint16 address, uint8* recv,
|
status_t dp_aux_read(uint32 connectorIndex, uint16 address, uint8* recv,
|
||||||
int recvBytes, uint8 delay);
|
int recvBytes, uint8 delay);
|
||||||
|
|
||||||
status_t dp_aux_set_i2c_byte(uint32 hwPin, uint16 address,
|
status_t dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address,
|
||||||
uint8* data, bool start, bool stop);
|
uint8* data, bool start, bool stop);
|
||||||
status_t dp_aux_get_i2c_byte(uint32 hwPin, uint16 address,
|
status_t dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address,
|
||||||
uint8* data, bool start, bool stop);
|
uint8* data, bool start, bool stop);
|
||||||
|
|
||||||
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
|
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ radeon_get_preferred_mode(display_mode* preferredMode)
|
|||||||
status_t
|
status_t
|
||||||
radeon_get_edid_info(void* info, size_t size, uint32* edid_version)
|
radeon_get_edid_info(void* info, size_t size, uint32* edid_version)
|
||||||
{
|
{
|
||||||
// TODO: multi-monitor? for now we use VESA edid
|
// TODO: multi-monitor? for now we use display 0
|
||||||
uint8 crtcID = 0;
|
uint8 crtcID = 0;
|
||||||
|
|
||||||
TRACE("%s\n", __func__);
|
TRACE("%s\n", __func__);
|
||||||
@@ -164,14 +164,12 @@ radeon_dpms_set(uint8 id, int mode)
|
|||||||
void
|
void
|
||||||
radeon_dpms_set_hook(int mode)
|
radeon_dpms_set_hook(int mode)
|
||||||
{
|
{
|
||||||
// TODO: multi-monitor? for now we use VESA edid
|
// TODO: multi-monitor?
|
||||||
|
|
||||||
// As the accelerant hook doesn't pass crtc id
|
uint8 crtcID = 0;
|
||||||
for (uint8 id = 0; id < MAX_DISPLAY; id++) {
|
|
||||||
if (gDisplay[id]->attached == false)
|
if (gDisplay[crtcID]->attached)
|
||||||
continue;
|
radeon_dpms_set(crtcID, mode);
|
||||||
radeon_dpms_set(id, mode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -179,57 +177,55 @@ status_t
|
|||||||
radeon_set_display_mode(display_mode* mode)
|
radeon_set_display_mode(display_mode* mode)
|
||||||
{
|
{
|
||||||
// TODO: multi-monitor? For now we set the mode on
|
// TODO: multi-monitor? For now we set the mode on
|
||||||
// all displays (this is very incorrect). This also
|
// the first display found.
|
||||||
// causes a lot of problems on DisplayPort devices
|
|
||||||
|
|
||||||
// Set mode on each display
|
uint8 crtcID = 0;
|
||||||
for (uint8 id = 0; id < MAX_DISPLAY; id++) {
|
|
||||||
if (gDisplay[id]->attached == false)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Copy this display mode into the "current mode" for the display
|
if (gDisplay[crtcID]->attached == false)
|
||||||
memcpy(&gDisplay[id]->currentMode, mode, sizeof(display_mode));
|
return B_ERROR;
|
||||||
|
|
||||||
uint32 connectorIndex = gDisplay[id]->connectorIndex;
|
// Copy this display mode into the "current mode" for the display
|
||||||
|
memcpy(&gDisplay[crtcID]->currentMode, mode, sizeof(display_mode));
|
||||||
|
|
||||||
// Determine DP lanes if DP
|
uint32 connectorIndex = gDisplay[crtcID]->connectorIndex;
|
||||||
if (connector_is_dp(connectorIndex)) {
|
|
||||||
dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo;
|
|
||||||
dpInfo->laneCount = dp_get_lane_count(connectorIndex, mode);
|
|
||||||
dpInfo->linkRate = dp_get_link_rate(connectorIndex, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** crtc and encoder prep
|
// Determine DP lanes if DP
|
||||||
encoder_output_lock(true);
|
if (connector_is_dp(connectorIndex)) {
|
||||||
display_crtc_lock(id, ATOM_ENABLE);
|
dp_info *dpInfo = &gConnector[connectorIndex]->dpInfo;
|
||||||
radeon_dpms_set(id, B_DPMS_OFF);
|
dpInfo->laneCount = dp_get_lane_count(connectorIndex, mode);
|
||||||
|
dpInfo->linkRate = dp_get_link_rate(connectorIndex, mode);
|
||||||
// *** Set up encoder -> crtc routing
|
|
||||||
encoder_assign_crtc(id);
|
|
||||||
|
|
||||||
// *** CRT controler mode set
|
|
||||||
// Set up PLL for connector
|
|
||||||
pll_pick(connectorIndex);
|
|
||||||
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
|
||||||
TRACE("%s: pll %d selected for connector %" B_PRIu32 "\n", __func__,
|
|
||||||
pll->id, connectorIndex);
|
|
||||||
pll_set(mode, id);
|
|
||||||
|
|
||||||
display_crtc_set_dtd(id, mode);
|
|
||||||
|
|
||||||
display_crtc_fb_set(id, mode);
|
|
||||||
// atombios_overscan_setup
|
|
||||||
display_crtc_scale(id, mode);
|
|
||||||
|
|
||||||
// *** encoder mode set
|
|
||||||
encoder_mode_set(id);
|
|
||||||
|
|
||||||
// *** encoder and CRT controller commit
|
|
||||||
radeon_dpms_set(id, B_DPMS_ON);
|
|
||||||
display_crtc_lock(id, ATOM_DISABLE);
|
|
||||||
encoder_output_lock(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *** crtc and encoder prep
|
||||||
|
encoder_output_lock(true);
|
||||||
|
display_crtc_lock(crtcID, ATOM_ENABLE);
|
||||||
|
radeon_dpms_set(crtcID, B_DPMS_OFF);
|
||||||
|
|
||||||
|
// *** Set up encoder -> crtc routing
|
||||||
|
encoder_assign_crtc(crtcID);
|
||||||
|
|
||||||
|
// *** CRT controler mode set
|
||||||
|
// Set up PLL for connector
|
||||||
|
pll_pick(connectorIndex);
|
||||||
|
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
||||||
|
TRACE("%s: pll %d selected for connector %" B_PRIu32 "\n", __func__,
|
||||||
|
pll->id, connectorIndex);
|
||||||
|
pll_set(mode, crtcID);
|
||||||
|
|
||||||
|
display_crtc_set_dtd(crtcID, mode);
|
||||||
|
|
||||||
|
display_crtc_fb_set(crtcID, mode);
|
||||||
|
// atombios_overscan_setup
|
||||||
|
display_crtc_scale(crtcID, mode);
|
||||||
|
|
||||||
|
// *** encoder mode set
|
||||||
|
encoder_mode_set(crtcID);
|
||||||
|
|
||||||
|
// *** encoder and CRT controller commit
|
||||||
|
radeon_dpms_set(crtcID, B_DPMS_ON);
|
||||||
|
display_crtc_lock(crtcID, ATOM_DISABLE);
|
||||||
|
encoder_output_lock(false);
|
||||||
|
|
||||||
#ifdef TRACE_MODE
|
#ifdef TRACE_MODE
|
||||||
// for debugging
|
// for debugging
|
||||||
debug_dp_info();
|
debug_dp_info();
|
||||||
|
|||||||
Reference in New Issue
Block a user