Introduce new displayport source file
* Move existing displayport functions to new source file * Move was done due to large amount of DP code * Style fixes * Stub out new DP link training function
This commit is contained in:
@@ -16,6 +16,7 @@ Addon radeon_hd.accelerant :
|
|||||||
connector.cpp
|
connector.cpp
|
||||||
create_display_modes.cpp
|
create_display_modes.cpp
|
||||||
display.cpp
|
display.cpp
|
||||||
|
displayport.cpp
|
||||||
encoder.cpp
|
encoder.cpp
|
||||||
engine.cpp
|
engine.cpp
|
||||||
gpu.cpp
|
gpu.cpp
|
||||||
|
|||||||
@@ -31,281 +31,6 @@
|
|||||||
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
dp_aux_speak(uint32 hwLine, uint8* send, int sendBytes,
|
|
||||||
uint8* recv, int recvBytes, uint8 delay, uint8* ack)
|
|
||||||
{
|
|
||||||
if (hwLine == 0) {
|
|
||||||
ERROR("%s: cannot speak on invalid GPIO pin!\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
|
|
||||||
|
|
||||||
// Build AtomBIOS Transaction
|
|
||||||
union auxChannelTransaction {
|
|
||||||
PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
|
|
||||||
PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
|
|
||||||
};
|
|
||||||
union auxChannelTransaction args;
|
|
||||||
memset(&args, 0, sizeof(args));
|
|
||||||
|
|
||||||
args.v1.lpAuxRequest = 0;
|
|
||||||
args.v1.lpDataOut = 16;
|
|
||||||
args.v1.ucDataOutLen = 0;
|
|
||||||
args.v1.ucChannelID = hwLine;
|
|
||||||
args.v1.ucDelay = delay / 10;
|
|
||||||
|
|
||||||
//if (ASIC_IS_DCE4(rdev))
|
|
||||||
// args.v2.ucHPD_ID = chan->rec.hpd;
|
|
||||||
|
|
||||||
unsigned char* base = (unsigned char*)gAtomContext->scratch;
|
|
||||||
memcpy(base, send, sendBytes);
|
|
||||||
|
|
||||||
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
|
||||||
|
|
||||||
*ack = args.v1.ucReplyStatus;
|
|
||||||
|
|
||||||
switch (args.v1.ucReplyStatus) {
|
|
||||||
case 1:
|
|
||||||
ERROR("%s: dp_aux_ch timeout!\n", __func__);
|
|
||||||
return B_TIMED_OUT;
|
|
||||||
case 2:
|
|
||||||
ERROR("%s: dp_aux_ch flags not zero!\n", __func__);
|
|
||||||
return B_BUSY;
|
|
||||||
case 3:
|
|
||||||
ERROR("%s: dp_aux_ch error!\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
int recvLength = args.v1.ucDataOutLen;
|
|
||||||
if (recvLength > recvBytes)
|
|
||||||
recvLength = recvBytes;
|
|
||||||
|
|
||||||
if (recv && recvBytes)
|
|
||||||
memcpy(recv, base + 16, recvLength);
|
|
||||||
|
|
||||||
return recvLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
dp_aux_write(uint32 hwLine, uint16 address,
|
|
||||||
uint8* send, uint8 sendBytes, uint8 delay)
|
|
||||||
{
|
|
||||||
uint8 auxMessage[20];
|
|
||||||
int auxMessageBytes = sendBytes + 4;
|
|
||||||
|
|
||||||
if (sendBytes > 16)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
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 < 4; retry++) {
|
|
||||||
uint8 ack;
|
|
||||||
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
|
||||||
NULL, 0, delay, &ack);
|
|
||||||
|
|
||||||
if (result == B_BUSY)
|
|
||||||
continue;
|
|
||||||
else if (result < B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
|
|
||||||
return sendBytes;
|
|
||||||
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
|
|
||||||
snooze(400);
|
|
||||||
else
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
dp_aux_read(uint32 hwLine, uint16 address,
|
|
||||||
uint8* recv, int recvBytes, uint8 delay)
|
|
||||||
{
|
|
||||||
uint8 auxMessage[4];
|
|
||||||
int auxMessageBytes = 4;
|
|
||||||
|
|
||||||
auxMessage[0] = address;
|
|
||||||
auxMessage[1] = address >> 8;
|
|
||||||
auxMessage[2] = AUX_NATIVE_READ << 4;
|
|
||||||
auxMessage[3] = (auxMessageBytes << 4) | (recvBytes - 1);
|
|
||||||
|
|
||||||
uint8 retry;
|
|
||||||
for (retry = 0; retry < 4; retry++) {
|
|
||||||
uint8 ack;
|
|
||||||
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
|
||||||
recv, recvBytes, delay, &ack);
|
|
||||||
|
|
||||||
if (result == B_BUSY)
|
|
||||||
continue;
|
|
||||||
else if (result < B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
|
|
||||||
return result;
|
|
||||||
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
|
|
||||||
snooze(400);
|
|
||||||
else
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
dp_aux_get_i2c_byte(uint32 hwLine, uint16 address, uint8* data, bool end)
|
|
||||||
{
|
|
||||||
uint8 auxMessage[5];
|
|
||||||
int auxMessageBytes = 4; // 4 for read
|
|
||||||
|
|
||||||
/* Set up the command byte */
|
|
||||||
auxMessage[2] = AUX_I2C_READ << 4;
|
|
||||||
if (end == false)
|
|
||||||
auxMessage[2] |= AUX_I2C_MOT << 4;
|
|
||||||
|
|
||||||
auxMessage[0] = address;
|
|
||||||
auxMessage[1] = address >> 8;
|
|
||||||
|
|
||||||
auxMessage[3] = auxMessageBytes << 4;
|
|
||||||
|
|
||||||
int retry;
|
|
||||||
for (retry = 0; retry < 4; retry++) {
|
|
||||||
uint8 ack;
|
|
||||||
uint8 reply[2];
|
|
||||||
int replyBytes = 1;
|
|
||||||
|
|
||||||
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
|
||||||
reply, replyBytes, 0, &ack);
|
|
||||||
if (result == B_BUSY)
|
|
||||||
continue;
|
|
||||||
else if (result < 0) {
|
|
||||||
ERROR("%s: aux_ch failed: %d\n", __func__, result);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ack & AUX_NATIVE_REPLY_MASK) {
|
|
||||||
case AUX_NATIVE_REPLY_ACK:
|
|
||||||
// I2C-over-AUX Reply field is only valid for AUX_ACK
|
|
||||||
break;
|
|
||||||
case AUX_NATIVE_REPLY_NACK:
|
|
||||||
TRACE("%s: aux_ch native nack\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
case AUX_NATIVE_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux_ch native defer\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux_ch invalid native reply: 0x%02x\n",
|
|
||||||
__func__, ack);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ack & AUX_I2C_REPLY_MASK) {
|
|
||||||
case AUX_I2C_REPLY_ACK:
|
|
||||||
*data = reply[0];
|
|
||||||
return B_OK;
|
|
||||||
case AUX_I2C_REPLY_NACK:
|
|
||||||
TRACE("%s: aux_i2c nack\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
case AUX_I2C_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux_i2c defer\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux_i2c invalid native reply: 0x%02x\n",
|
|
||||||
__func__, ack);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("%s: aux i2c too many retries, giving up.\n", __func__);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
dp_aux_set_i2c_byte(uint32 hwLine, uint16 address, uint8* data, bool end)
|
|
||||||
{
|
|
||||||
uint8 auxMessage[5];
|
|
||||||
int auxMessageBytes = 5; // 5 for write
|
|
||||||
|
|
||||||
/* Set up the command byte */
|
|
||||||
auxMessage[2] = AUX_I2C_WRITE << 4;
|
|
||||||
if (end == false)
|
|
||||||
auxMessage[2] |= AUX_I2C_MOT << 4;
|
|
||||||
|
|
||||||
auxMessage[0] = address;
|
|
||||||
auxMessage[1] = address >> 8;
|
|
||||||
|
|
||||||
auxMessage[3] = auxMessageBytes << 4;
|
|
||||||
auxMessage[4] = *data;
|
|
||||||
|
|
||||||
int retry;
|
|
||||||
for (retry = 0; retry < 4; retry++) {
|
|
||||||
uint8 ack;
|
|
||||||
uint8 reply[2];
|
|
||||||
int replyBytes = 1;
|
|
||||||
|
|
||||||
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
|
||||||
reply, replyBytes, 0, &ack);
|
|
||||||
if (result == B_BUSY)
|
|
||||||
continue;
|
|
||||||
else if (result < 0) {
|
|
||||||
ERROR("%s: aux_ch failed: %d\n", __func__, result);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ack & AUX_NATIVE_REPLY_MASK) {
|
|
||||||
case AUX_NATIVE_REPLY_ACK:
|
|
||||||
// I2C-over-AUX Reply field is only valid for AUX_ACK
|
|
||||||
break;
|
|
||||||
case AUX_NATIVE_REPLY_NACK:
|
|
||||||
TRACE("%s: aux_ch native nack\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
case AUX_NATIVE_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux_ch native defer\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux_ch invalid native reply: 0x%02x\n",
|
|
||||||
__func__, ack);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ack & AUX_I2C_REPLY_MASK) {
|
|
||||||
case AUX_I2C_REPLY_ACK:
|
|
||||||
// Success!
|
|
||||||
return B_OK;
|
|
||||||
case AUX_I2C_REPLY_NACK:
|
|
||||||
TRACE("%s: aux_i2c nack\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
case AUX_I2C_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux_i2c defer\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux_i2c invalid native reply: 0x%02x\n",
|
|
||||||
__func__, ack);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("%s: aux i2c too many retries, giving up.\n", __func__);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gpio_lock_i2c(void* cookie, bool lock)
|
gpio_lock_i2c(void* cookie, bool lock)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,26 +14,6 @@
|
|||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
|
|
||||||
|
|
||||||
// From the VESA DisplayPort spec
|
|
||||||
// TODO: may want to move these into common code
|
|
||||||
#define AUX_NATIVE_WRITE 0x8
|
|
||||||
#define AUX_NATIVE_READ 0x9
|
|
||||||
#define AUX_I2C_WRITE 0x0
|
|
||||||
#define AUX_I2C_READ 0x1
|
|
||||||
#define AUX_I2C_STATUS 0x2
|
|
||||||
#define AUX_I2C_MOT 0x4
|
|
||||||
|
|
||||||
#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
|
|
||||||
#define AUX_NATIVE_REPLY_NACK (0x1 << 4)
|
|
||||||
#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
|
|
||||||
#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
|
|
||||||
|
|
||||||
#define AUX_I2C_REPLY_ACK (0x0 << 6)
|
|
||||||
#define AUX_I2C_REPLY_NACK (0x1 << 6)
|
|
||||||
#define AUX_I2C_REPLY_DEFER (0x2 << 6)
|
|
||||||
#define AUX_I2C_REPLY_MASK (0x3 << 6)
|
|
||||||
|
|
||||||
|
|
||||||
// convert radeon connector to common connector type
|
// convert radeon connector to common connector type
|
||||||
const int kConnectorConvertLegacy[] = {
|
const int kConnectorConvertLegacy[] = {
|
||||||
VIDEO_CONNECTOR_UNKNOWN,
|
VIDEO_CONNECTOR_UNKNOWN,
|
||||||
@@ -80,16 +60,6 @@ const int kConnectorConvert[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int dp_aux_write(uint32 hwLine, uint16 address, uint8* send,
|
|
||||||
uint8 sendBytes, uint8 delay);
|
|
||||||
int dp_aux_read(uint32 hwLine, uint16 address, uint8* recv,
|
|
||||||
int recvBytes, uint8 delay);
|
|
||||||
status_t dp_aux_set_i2c_byte(uint32 hwLine, uint16 address,
|
|
||||||
uint8* data, bool end);
|
|
||||||
status_t dp_aux_get_i2c_byte(uint32 hwLine, uint16 address,
|
|
||||||
uint8* data, bool end);
|
|
||||||
|
|
||||||
|
|
||||||
status_t gpio_probe();
|
status_t gpio_probe();
|
||||||
status_t connector_attach_gpio(uint32 id, uint8 hw_line);
|
status_t connector_attach_gpio(uint32 id, uint8 hw_line);
|
||||||
bool connector_read_edid(uint32 connector, edid1_info* edid);
|
bool connector_read_edid(uint32 connector, edid1_info* edid);
|
||||||
|
|||||||
@@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck IV, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "displayport.h"
|
||||||
|
|
||||||
|
#include <Debug.h>
|
||||||
|
|
||||||
|
#include "accelerant.h"
|
||||||
|
#include "accelerant_protos.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef TRACE
|
||||||
|
|
||||||
|
#define TRACE_DP
|
||||||
|
#ifdef TRACE_DP
|
||||||
|
# define TRACE(x...) _sPrintf("radeon_hd: " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ERROR(x...) _sPrintf("radeon_hd: " x)
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
dp_aux_speak(uint32 hwLine, uint8* send, int sendBytes,
|
||||||
|
uint8* recv, int recvBytes, uint8 delay, uint8* ack)
|
||||||
|
{
|
||||||
|
if (hwLine == 0) {
|
||||||
|
ERROR("%s: cannot speak on invalid GPIO pin!\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
|
||||||
|
|
||||||
|
// Build AtomBIOS Transaction
|
||||||
|
union auxChannelTransaction {
|
||||||
|
PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1;
|
||||||
|
PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2;
|
||||||
|
};
|
||||||
|
union auxChannelTransaction args;
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
|
||||||
|
args.v1.lpAuxRequest = 0;
|
||||||
|
args.v1.lpDataOut = 16;
|
||||||
|
args.v1.ucDataOutLen = 0;
|
||||||
|
args.v1.ucChannelID = hwLine;
|
||||||
|
args.v1.ucDelay = delay / 10;
|
||||||
|
|
||||||
|
//if (ASIC_IS_DCE4(rdev))
|
||||||
|
// args.v2.ucHPD_ID = chan->rec.hpd;
|
||||||
|
|
||||||
|
unsigned char* base = (unsigned char*)gAtomContext->scratch;
|
||||||
|
memcpy(base, send, sendBytes);
|
||||||
|
|
||||||
|
atom_execute_table(gAtomContext, index, (uint32*)&args);
|
||||||
|
|
||||||
|
*ack = args.v1.ucReplyStatus;
|
||||||
|
|
||||||
|
switch (args.v1.ucReplyStatus) {
|
||||||
|
case 1:
|
||||||
|
ERROR("%s: dp_aux_ch timeout!\n", __func__);
|
||||||
|
return B_TIMED_OUT;
|
||||||
|
case 2:
|
||||||
|
ERROR("%s: dp_aux_ch flags not zero!\n", __func__);
|
||||||
|
return B_BUSY;
|
||||||
|
case 3:
|
||||||
|
ERROR("%s: dp_aux_ch error!\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recvLength = args.v1.ucDataOutLen;
|
||||||
|
if (recvLength > recvBytes)
|
||||||
|
recvLength = recvBytes;
|
||||||
|
|
||||||
|
if (recv && recvBytes)
|
||||||
|
memcpy(recv, base + 16, recvLength);
|
||||||
|
|
||||||
|
return recvLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dp_aux_write(uint32 hwLine, uint16 address,
|
||||||
|
uint8* send, uint8 sendBytes, uint8 delay)
|
||||||
|
{
|
||||||
|
uint8 auxMessage[20];
|
||||||
|
int auxMessageBytes = sendBytes + 4;
|
||||||
|
|
||||||
|
if (sendBytes > 16)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
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 < 4; retry++) {
|
||||||
|
uint8 ack;
|
||||||
|
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
||||||
|
NULL, 0, delay, &ack);
|
||||||
|
|
||||||
|
if (result == B_BUSY)
|
||||||
|
continue;
|
||||||
|
else if (result < B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
|
||||||
|
return sendBytes;
|
||||||
|
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
|
||||||
|
snooze(400);
|
||||||
|
else
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dp_aux_read(uint32 hwLine, uint16 address,
|
||||||
|
uint8* recv, int recvBytes, uint8 delay)
|
||||||
|
{
|
||||||
|
uint8 auxMessage[4];
|
||||||
|
int auxMessageBytes = 4;
|
||||||
|
|
||||||
|
auxMessage[0] = address;
|
||||||
|
auxMessage[1] = address >> 8;
|
||||||
|
auxMessage[2] = AUX_NATIVE_READ << 4;
|
||||||
|
auxMessage[3] = (auxMessageBytes << 4) | (recvBytes - 1);
|
||||||
|
|
||||||
|
uint8 retry;
|
||||||
|
for (retry = 0; retry < 4; retry++) {
|
||||||
|
uint8 ack;
|
||||||
|
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
||||||
|
recv, recvBytes, delay, &ack);
|
||||||
|
|
||||||
|
if (result == B_BUSY)
|
||||||
|
continue;
|
||||||
|
else if (result < B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
|
||||||
|
return result;
|
||||||
|
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
|
||||||
|
snooze(400);
|
||||||
|
else
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dp_aux_get_i2c_byte(uint32 hwLine, uint16 address, uint8* data, bool end)
|
||||||
|
{
|
||||||
|
uint8 auxMessage[5];
|
||||||
|
int auxMessageBytes = 4; // 4 for read
|
||||||
|
|
||||||
|
/* Set up the command byte */
|
||||||
|
auxMessage[2] = AUX_I2C_READ << 4;
|
||||||
|
if (end == false)
|
||||||
|
auxMessage[2] |= AUX_I2C_MOT << 4;
|
||||||
|
|
||||||
|
auxMessage[0] = address;
|
||||||
|
auxMessage[1] = address >> 8;
|
||||||
|
|
||||||
|
auxMessage[3] = auxMessageBytes << 4;
|
||||||
|
|
||||||
|
int retry;
|
||||||
|
for (retry = 0; retry < 4; retry++) {
|
||||||
|
uint8 ack;
|
||||||
|
uint8 reply[2];
|
||||||
|
int replyBytes = 1;
|
||||||
|
|
||||||
|
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
||||||
|
reply, replyBytes, 0, &ack);
|
||||||
|
if (result == B_BUSY)
|
||||||
|
continue;
|
||||||
|
else if (result < 0) {
|
||||||
|
ERROR("%s: aux_ch failed: %d\n", __func__, result);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ack & AUX_NATIVE_REPLY_MASK) {
|
||||||
|
case AUX_NATIVE_REPLY_ACK:
|
||||||
|
// I2C-over-AUX Reply field is only valid for AUX_ACK
|
||||||
|
break;
|
||||||
|
case AUX_NATIVE_REPLY_NACK:
|
||||||
|
TRACE("%s: aux_ch native nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
case AUX_NATIVE_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux_ch native defer\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux_ch invalid native reply: 0x%02x\n",
|
||||||
|
__func__, ack);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ack & AUX_I2C_REPLY_MASK) {
|
||||||
|
case AUX_I2C_REPLY_ACK:
|
||||||
|
*data = reply[0];
|
||||||
|
return B_OK;
|
||||||
|
case AUX_I2C_REPLY_NACK:
|
||||||
|
TRACE("%s: aux_i2c nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
case AUX_I2C_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux_i2c defer\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux_i2c invalid native reply: 0x%02x\n",
|
||||||
|
__func__, ack);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s: aux i2c too many retries, giving up.\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dp_aux_set_i2c_byte(uint32 hwLine, uint16 address, uint8* data, bool end)
|
||||||
|
{
|
||||||
|
uint8 auxMessage[5];
|
||||||
|
int auxMessageBytes = 5; // 5 for write
|
||||||
|
|
||||||
|
/* Set up the command byte */
|
||||||
|
auxMessage[2] = AUX_I2C_WRITE << 4;
|
||||||
|
if (end == false)
|
||||||
|
auxMessage[2] |= AUX_I2C_MOT << 4;
|
||||||
|
|
||||||
|
auxMessage[0] = address;
|
||||||
|
auxMessage[1] = address >> 8;
|
||||||
|
|
||||||
|
auxMessage[3] = auxMessageBytes << 4;
|
||||||
|
auxMessage[4] = *data;
|
||||||
|
|
||||||
|
int retry;
|
||||||
|
for (retry = 0; retry < 4; retry++) {
|
||||||
|
uint8 ack;
|
||||||
|
uint8 reply[2];
|
||||||
|
int replyBytes = 1;
|
||||||
|
|
||||||
|
int result = dp_aux_speak(hwLine, auxMessage, auxMessageBytes,
|
||||||
|
reply, replyBytes, 0, &ack);
|
||||||
|
if (result == B_BUSY)
|
||||||
|
continue;
|
||||||
|
else if (result < 0) {
|
||||||
|
ERROR("%s: aux_ch failed: %d\n", __func__, result);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ack & AUX_NATIVE_REPLY_MASK) {
|
||||||
|
case AUX_NATIVE_REPLY_ACK:
|
||||||
|
// I2C-over-AUX Reply field is only valid for AUX_ACK
|
||||||
|
break;
|
||||||
|
case AUX_NATIVE_REPLY_NACK:
|
||||||
|
TRACE("%s: aux_ch native nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
case AUX_NATIVE_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux_ch native defer\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux_ch invalid native reply: 0x%02x\n",
|
||||||
|
__func__, ack);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ack & AUX_I2C_REPLY_MASK) {
|
||||||
|
case AUX_I2C_REPLY_ACK:
|
||||||
|
// Success!
|
||||||
|
return B_OK;
|
||||||
|
case AUX_I2C_REPLY_NACK:
|
||||||
|
TRACE("%s: aux_i2c nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
case AUX_I2C_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux_i2c defer\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux_i2c invalid native reply: 0x%02x\n",
|
||||||
|
__func__, ack);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%s: aux i2c too many retries, giving up.\n", __func__);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
dp_get_link_clock(uint32 connectorIndex)
|
||||||
|
{
|
||||||
|
uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
|
||||||
|
|
||||||
|
if (encoderID == ENCODER_OBJECT_ID_NUTMEG)
|
||||||
|
return 270000;
|
||||||
|
|
||||||
|
// TODO: calculate DisplayPort max pixel clock based on bpp and DP channels
|
||||||
|
return 162000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
dp_link_train(uint32 connectorIndex)
|
||||||
|
{
|
||||||
|
TRACE("%s\n", __func__);
|
||||||
|
|
||||||
|
int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService);
|
||||||
|
// Table version
|
||||||
|
uint8 tableMajor;
|
||||||
|
uint8 tableMinor;
|
||||||
|
|
||||||
|
bool useDpencoder = true; // ??
|
||||||
|
if (atom_parse_cmd_header(gAtomContext, index, &tableMajor, &tableMinor)
|
||||||
|
== B_OK) {
|
||||||
|
if (tableMinor > 1) {
|
||||||
|
useDpencoder = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: perform displayport training
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Alexander von Gluck IV, [email protected]
|
||||||
|
*/
|
||||||
|
#ifndef RADEON_HD_DISPLAYPORT_H
|
||||||
|
#define RADEON_HD_DISPLAYPORT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
// From the VESA DisplayPort spec
|
||||||
|
// TODO: may want to move these into common code
|
||||||
|
#define AUX_NATIVE_WRITE 0x8
|
||||||
|
#define AUX_NATIVE_READ 0x9
|
||||||
|
#define AUX_I2C_WRITE 0x0
|
||||||
|
#define AUX_I2C_READ 0x1
|
||||||
|
#define AUX_I2C_STATUS 0x2
|
||||||
|
#define AUX_I2C_MOT 0x4
|
||||||
|
|
||||||
|
#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
|
||||||
|
#define AUX_NATIVE_REPLY_NACK (0x1 << 4)
|
||||||
|
#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
|
||||||
|
#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
|
||||||
|
|
||||||
|
#define AUX_I2C_REPLY_ACK (0x0 << 6)
|
||||||
|
#define AUX_I2C_REPLY_NACK (0x1 << 6)
|
||||||
|
#define AUX_I2C_REPLY_DEFER (0x2 << 6)
|
||||||
|
#define AUX_I2C_REPLY_MASK (0x3 << 6)
|
||||||
|
|
||||||
|
|
||||||
|
int dp_aux_write(uint32 hwLine, uint16 address, uint8* send,
|
||||||
|
uint8 sendBytes, uint8 delay);
|
||||||
|
int dp_aux_read(uint32 hwLine, uint16 address, uint8* recv,
|
||||||
|
int recvBytes, uint8 delay);
|
||||||
|
status_t dp_aux_set_i2c_byte(uint32 hwLine, uint16 address,
|
||||||
|
uint8* data, bool end);
|
||||||
|
status_t dp_aux_get_i2c_byte(uint32 hwLine, uint16 address,
|
||||||
|
uint8* data, bool end);
|
||||||
|
|
||||||
|
uint32 dp_get_link_clock(uint32 connectorIndex);
|
||||||
|
status_t dp_link_train(uint32 connectorIndex);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* RADEON_HD_DISPLAYPORT_H */
|
||||||
@@ -1361,7 +1361,8 @@ encoder_is_external(uint32 encoderID)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
encoder_is_dp_bridge(uint32 encoderID) {
|
encoder_is_dp_bridge(uint32 encoderID)
|
||||||
|
{
|
||||||
switch (encoderID) {
|
switch (encoderID) {
|
||||||
case ENCODER_OBJECT_ID_TRAVIS:
|
case ENCODER_OBJECT_ID_TRAVIS:
|
||||||
case ENCODER_OBJECT_ID_NUTMEG:
|
case ENCODER_OBJECT_ID_NUTMEG:
|
||||||
@@ -1369,15 +1370,3 @@ encoder_is_dp_bridge(uint32 encoderID) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
|
||||||
encoder_get_dp_link_clock(uint32 connectorIndex) {
|
|
||||||
uint16 encoderID = gConnector[connectorIndex]->encoder.objectID;
|
|
||||||
|
|
||||||
if (encoderID == ENCODER_OBJECT_ID_NUTMEG)
|
|
||||||
return 270000;
|
|
||||||
|
|
||||||
// TODO: calculate DisplayPort max pixel clock based on bpp and DP channels
|
|
||||||
return 162000;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ uint32 encoder_object_lookup(uint32 encoderFlags, uint8 dacID);
|
|||||||
uint32 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags);
|
uint32 encoder_type_lookup(uint32 encoderID, uint32 connectorFlags);
|
||||||
bool encoder_is_external(uint32 encoderID);
|
bool encoder_is_external(uint32 encoderID);
|
||||||
bool encoder_is_dp_bridge(uint32 encoderID);
|
bool encoder_is_dp_bridge(uint32 encoderID);
|
||||||
uint32 encoder_get_dp_link_clock(uint32 connectorIndex);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* RADEON_HD_ENCODER_H */
|
#endif /* RADEON_HD_ENCODER_H */
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
#include "accelerant.h"
|
#include "accelerant.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "displayport.h"
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_PLL
|
#define TRACE_PLL
|
||||||
#ifdef TRACE_PLL
|
#ifdef TRACE_PLL
|
||||||
extern "C" void _sPrintf(const char* format, ...);
|
extern "C" void _sPrintf(const char* format, ...);
|
||||||
@@ -401,7 +403,7 @@ pll_adjust(pll_info* pll, uint8 crtcID)
|
|||||||
|= DISPPLL_CONFIG_COHERENT_MODE;
|
|= DISPPLL_CONFIG_COHERENT_MODE;
|
||||||
/* 16200 or 27000 */
|
/* 16200 or 27000 */
|
||||||
uint32 dpLinkSpeed
|
uint32 dpLinkSpeed
|
||||||
= encoder_get_dp_link_clock(connectorIndex);
|
= dp_get_link_clock(connectorIndex);
|
||||||
args.v3.sInput.usPixelClock
|
args.v3.sInput.usPixelClock
|
||||||
= B_LENDIAN_TO_HOST_INT16(dpLinkSpeed / 10);
|
= B_LENDIAN_TO_HOST_INT16(dpLinkSpeed / 10);
|
||||||
} else if ((encoderFlags & ATOM_DEVICE_DFP_SUPPORT)
|
} else if ((encoderFlags & ATOM_DEVICE_DFP_SUPPORT)
|
||||||
|
|||||||
Reference in New Issue
Block a user