Skip to content

Commit

Permalink
radeon_hd: Move to a unified dp aux transaction function.
Browse files Browse the repository at this point in the history
* Leverage a single common dp aux message struct.
* Likely lots of obvious bugs that need fixed still.
* Untested.
  • Loading branch information
kallisti5 committed Jul 14, 2015
1 parent 6031dea commit 9816a89
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 66 deletions.
152 changes: 90 additions & 62 deletions src/add-ons/accelerants/radeon_hd/displayport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,72 +133,71 @@ dp_aux_speak(uint32 connectorIndex, uint8* send, int sendBytes,


status_t
dp_aux_write(uint32 connectorIndex, uint16 address,
uint8* send, uint8 sendBytes, uint8 delay)
dp_aux_transaction(uint32 connectorIndex, dp_aux_msg* message)
{
uint8 auxMessage[20];
int auxMessageBytes = sendBytes + 4;

if (sendBytes > 16) {
ERROR("%s: Too many bytes! (%" B_PRIu8 ")\n", __func__, sendBytes);
return -1;
uint8 delay = 0;
if (message == NULL) {
ERROR("%s: DP message is invalid!\n", __func__);
return B_ERROR;
}

auxMessage[0] = address;
auxMessage[1] = address >> 8;
auxMessage[2] = AUX_NATIVE_WRITE << 4;
auxMessage[3] = (auxMessageBytes << 4) | (sendBytes - 1);
memcpy(&auxMessage[4], send, sendBytes);

uint8 retry;
for (retry = 0; retry < 7; retry++) {
uint8 ack;
status_t result = dp_aux_speak(connectorIndex, auxMessage,
auxMessageBytes, NULL, 0, delay, &ack);
if (message->buffer == NULL) {
ERROR("%s: DP message uninitalized buffer!\n", __func__);
return B_ERROR;
}

if (result == B_BUSY)
continue;
else if (result != B_OK)
return result;
uint8 transactionSize = 4;

ack >>= 4;
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
return B_OK;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
snooze(400);
else
return B_IO_ERROR;
switch(message->request) {
case AUX_NATIVE_WRITE:
case AUX_I2C_WRITE:
transactionSize += message->size;
break;
}

ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry);
return B_IO_ERROR;
}

if (transactionSize > 20) {
ERROR("%s: Too many bytes! (%" B_PRIu8 ")\n", __func__,
transactionSize);
return B_ERROR;
}

status_t
dp_aux_read(uint32 connectorIndex, uint16 address,
uint8* recv, int recvBytes, uint8 delay)
{
uint8 auxMessage[4];
int auxMessageBytes = 4;
uint8 auxMessage[20];
auxMessage[0] = message->address & 0xff;
auxMessage[1] = message->address >> 8;
auxMessage[2] = message->request << 4;
auxMessage[3] = message->size ? (message->size - 1) : 0;

auxMessage[0] = address;
auxMessage[1] = address >> 8;
auxMessage[2] = AUX_NATIVE_READ << 4;
auxMessage[3] = (auxMessageBytes << 4) | (recvBytes - 1);
if (message->size == 0)
auxMessage[3] |= 3 << 4;
else
auxMessage[3] |= transactionSize << 4;

uint8 retry;
for (retry = 0; retry < 7; retry++) {
uint8 ack;
status_t result = dp_aux_speak(connectorIndex, auxMessage,
auxMessageBytes, recv, recvBytes, delay, &ack);
status_t result = B_ERROR;
switch(message->request) {
case AUX_NATIVE_WRITE:
case AUX_I2C_WRITE:
memcpy(&auxMessage[4], message->buffer, message->size);
result = dp_aux_speak(connectorIndex, auxMessage,
transactionSize, NULL, 0, delay, &ack);
break;
case AUX_NATIVE_READ:
case AUX_I2C_READ:
result = dp_aux_speak(connectorIndex, auxMessage,
transactionSize, (uint8*)message->buffer, message->size,
delay, &ack);
break;
}

if (result == B_BUSY)
continue;
else if (result != B_OK)
return result;

ack >>= 4;
message->reply = ack;
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
return B_OK;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
Expand All @@ -215,7 +214,13 @@ dp_aux_read(uint32 connectorIndex, uint16 address,
void
dpcd_reg_write(uint32 connectorIndex, uint16 address, uint8 value)
{
status_t result = dp_aux_write(connectorIndex, address, &value, 1, 0);
dp_aux_msg message;
message.address = address;
message.buffer = &value;
message.request = AUX_NATIVE_WRITE;
message.size = 1;

status_t result = dp_aux_transaction(connectorIndex, &message);
if (result != B_OK) {
ERROR("%s: error on DisplayPort aux write (0x%" B_PRIx32 ")\n",
__func__, result);
Expand All @@ -226,21 +231,29 @@ dpcd_reg_write(uint32 connectorIndex, uint16 address, uint8 value)
uint8
dpcd_reg_read(uint32 connectorIndex, uint16 address)
{
uint8 value = 0;
status_t result = dp_aux_read(connectorIndex, address, &value, 1, 0);
// TODO: Review dpcd response size response[3]?
uint8 response;

dp_aux_msg message;
message.address = address;
message.request = AUX_NATIVE_READ;
message.buffer = &response;

status_t result = dp_aux_transaction(connectorIndex, &message);
if (result != B_OK) {
ERROR("%s: error on DisplayPort aux read (0x%" B_PRIx32 ")\n",
__func__, result);
}

return value;
return response;
}


status_t
dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data,
bool start, bool stop)
{
// TODO: Leverage dp_aux_transaction
uint8 auxMessage[5];
int auxMessageBytes = 4; // 4 for read

Expand Down Expand Up @@ -319,6 +332,7 @@ status_t
dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data,
bool start, bool stop)
{
// TODO: Leverage dp_aux_transaction
uint8 auxMessage[5];
int auxMessageBytes = 5; // 5 for write

Expand Down Expand Up @@ -495,25 +509,30 @@ dp_setup_connectors()
uint32 auxPin = gGPIOInfo[i2cPinIndex]->hwPin;
dpInfo->auxPin = auxPin;

uint8 auxMessage[DP_DPCD_SIZE];
dp_aux_msg message;
message.address = DP_DPCD_REV;
message.request = AUX_NATIVE_READ;
// TODO: validate
message.size = DP_DPCD_SIZE;
message.buffer = dpInfo->config;

status_t result = dp_aux_read(index, DP_DPCD_REV, auxMessage,
DP_DPCD_SIZE, 0);
status_t result = dp_aux_transaction(index, &message);

if (result == B_OK) {
dpInfo->valid = true;
memcpy(dpInfo->config, auxMessage, DP_DPCD_SIZE);
TRACE("%s: connector(%" B_PRIu32 "): successful read of DPCD\n",
__func__, index);
} else {
TRACE("%s: connector(%" B_PRIu32 "): failed read of DPCD\n",
__func__, index);
}
/*
TRACE("%s: DPCD is ", __func__);
uint32 position;
for (position = 0; position < DP_DPCD_SIZE; position++)
_sPrintf("%02x ", auxMessage[position]);
uint32 position;
for (position = 0; position < message.size; position++)
_sPrintf("%02x ", message.buffer + position);
_sPrintf("\n");
*/
}
}

Expand All @@ -522,8 +541,13 @@ bool
dp_get_link_status(uint32 connectorIndex)
{
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_aux_msg message;
message.address = DP_LANE_STATUS_0_1;
message.size = DP_LINK_STATUS_SIZE;
message.buffer = dp->linkStatus;

// TODO: Delay 100? Newer AMD code doesn't care about link status
status_t result = dp_aux_transaction(connectorIndex, &message);

if (result != B_OK) {
ERROR("%s: DisplayPort link status failed\n", __func__);
Expand Down Expand Up @@ -589,9 +613,13 @@ dp_update_vs_emph(uint32 connectorIndex)
transmitter_dig_setup(connectorIndex, dp->linkRate, 0,
dp->trainingSet[0], ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH);

// Set vs and emph on the sink
dp_aux_write(connectorIndex, DP_TRAIN_LANE0,
dp->trainingSet, dp->laneCount, 0);
dp_aux_msg message;
message.request = AUX_NATIVE_WRITE;
message.address = DP_TRAIN_LANE0;
message.buffer = dp->trainingSet;
message.size = dp->laneCount;
// TODO: Review laneCount as it sounds strange.
dp_aux_transaction(connectorIndex, &message);
}


Expand Down
5 changes: 1 addition & 4 deletions src/add-ons/accelerants/radeon_hd/displayport.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ uint8 dpcd_reg_read(uint32 connectorIndex, uint16 address);
void dpcd_reg_write(uint32 connectorIndex, uint16 address, uint8 value);

// Communication over DisplayPort AUX channel
status_t dp_aux_write(uint32 connectorIndex, uint16 address, uint8* send,
uint8 sendBytes, uint8 delay);
status_t dp_aux_read(uint32 connectorIndex, uint16 address, uint8* recv,
int recvBytes, uint8 delay);
status_t dp_aux_transaction(uint32 connectorIndex, dp_aux_msg* message);

status_t dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address,
uint8* data, bool start, bool stop);
Expand Down
10 changes: 10 additions & 0 deletions src/add-ons/accelerants/radeon_hd/pll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,11 @@ pll_setup_flags(pll_info* pll, uint8 crtcID)
}


/**
* pll_adjust - Ask AtomBIOS if it wants to make adjustments to our pll
*
* Returns B_OK on successful execution.
*/
status_t
pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
{
Expand Down Expand Up @@ -732,6 +737,11 @@ pll_adjust(pll_info* pll, display_mode* mode, uint8 crtcID)
}


/*
* pll_set - Calculate and set a pll on the crtc provided based on the mode.
*
* Returns B_OK on successful execution
*/
status_t
pll_set(display_mode* mode, uint8 crtcID)
{
Expand Down

0 comments on commit 9816a89

Please sign in to comment.