intel_extreme: reuse DpAux code for DisplayPort
the code is moved in the Port class. Change-Id: I3beb337e29b26ee4732224723c5b76b5f415a248 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5291 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
@@ -468,6 +468,388 @@ Port::_IsInternalPanelPort()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Port::_SetupDpAuxI2c(i2c_bus *bus)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
ddc2_init_timing(bus);
|
||||||
|
bus->cookie = this;
|
||||||
|
bus->send_receive = &_DpAuxSendReceiveHook;
|
||||||
|
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 11) {
|
||||||
|
uint32 value = read32(ICL_PWR_WELL_CTL_AUX2);
|
||||||
|
if ((value & HSW_PWR_WELL_CTL_STATE(0)) != 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
write32(ICL_PWR_WELL_CTL_AUX2, value | HSW_PWR_WELL_CTL_REQ(0));
|
||||||
|
if (!wait_for_set(ICL_PWR_WELL_CTL_AUX2, HSW_PWR_WELL_CTL_STATE(0), 1000))
|
||||||
|
ERROR("%s: %s AUX didn't power on within 1000us!\n", __func__, PortName());
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Port::_DpAuxSendReceive(uint32 slaveAddress,
|
||||||
|
const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
|
||||||
|
{
|
||||||
|
size_t transferLength = 16;
|
||||||
|
|
||||||
|
dp_aux_msg message;
|
||||||
|
memset(&message, 0, sizeof(message));
|
||||||
|
|
||||||
|
if (writeBuffer != NULL) {
|
||||||
|
message.address = slaveAddress;
|
||||||
|
message.buffer = NULL;
|
||||||
|
message.request = DP_AUX_I2C_WRITE;
|
||||||
|
message.size = 0;
|
||||||
|
ssize_t result = _DpAuxTransfer(&message);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < writeLength;) {
|
||||||
|
message.buffer = (void*)(writeBuffer + i);
|
||||||
|
message.size = min_c(transferLength, writeLength - i);
|
||||||
|
// Middle-Of-Transmission on final transaction
|
||||||
|
if (writeLength - i > transferLength)
|
||||||
|
message.request |= DP_AUX_I2C_MOT;
|
||||||
|
else
|
||||||
|
message.request &= ~DP_AUX_I2C_MOT;
|
||||||
|
|
||||||
|
for (int attempt = 0; attempt < 7; attempt++) {
|
||||||
|
ssize_t result = _DpAuxTransfer(&message);
|
||||||
|
if (result < 0) {
|
||||||
|
ERROR("%s: aux_ch transaction failed!\n", __func__);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
|
||||||
|
case DP_AUX_I2C_REPLY_ACK:
|
||||||
|
goto nextWrite;
|
||||||
|
case DP_AUX_I2C_REPLY_NACK:
|
||||||
|
TRACE("%s: aux i2c nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
case DP_AUX_I2C_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux i2c defer\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux invalid I2C reply: 0x%02x\n",
|
||||||
|
__func__, message.reply);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextWrite:
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
i += message.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (readBuffer != NULL) {
|
||||||
|
message.address = slaveAddress;
|
||||||
|
message.buffer = NULL;
|
||||||
|
message.request = DP_AUX_I2C_READ;
|
||||||
|
message.size = 0;
|
||||||
|
ssize_t result = _DpAuxTransfer(&message);
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < readLength;) {
|
||||||
|
message.buffer = readBuffer + i;
|
||||||
|
message.size = min_c(transferLength, readLength - i);
|
||||||
|
// Middle-Of-Transmission on final transaction
|
||||||
|
if (readLength - i > transferLength)
|
||||||
|
message.request |= DP_AUX_I2C_MOT;
|
||||||
|
else
|
||||||
|
message.request &= ~DP_AUX_I2C_MOT;
|
||||||
|
|
||||||
|
for (int attempt = 0; attempt < 7; attempt++) {
|
||||||
|
result = _DpAuxTransfer(&message);
|
||||||
|
if (result < 0) {
|
||||||
|
ERROR("%s: aux_ch transaction failed!\n", __func__);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
|
||||||
|
case DP_AUX_I2C_REPLY_ACK:
|
||||||
|
goto nextRead;
|
||||||
|
case DP_AUX_I2C_REPLY_NACK:
|
||||||
|
TRACE("%s: aux i2c nack\n", __func__);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
case DP_AUX_I2C_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux i2c defer\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux invalid I2C reply: 0x%02x\n",
|
||||||
|
__func__, message.reply);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextRead:
|
||||||
|
if (result < 0)
|
||||||
|
return result;
|
||||||
|
if (result == 0)
|
||||||
|
i += message.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Port::_DpAuxSendReceiveHook(const struct i2c_bus *bus, uint32 slaveAddress,
|
||||||
|
const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
DigitalDisplayInterface* port = (DigitalDisplayInterface*)bus->cookie;
|
||||||
|
return port->_DpAuxSendReceive(slaveAddress, writeBuffer, writeLength, readBuffer, readLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
Port::_DpAuxTransfer(dp_aux_msg* message)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
if (message == NULL) {
|
||||||
|
ERROR("%s: DP message is invalid!\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message->size > 16) {
|
||||||
|
ERROR("%s: Too many bytes! (%" B_PRIuSIZE ")\n", __func__,
|
||||||
|
message->size);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 transmitSize = message->size > 0 ? 4 : 3;
|
||||||
|
uint8 receiveSize;
|
||||||
|
|
||||||
|
switch(message->request & ~DP_AUX_I2C_MOT) {
|
||||||
|
case DP_AUX_NATIVE_WRITE:
|
||||||
|
case DP_AUX_I2C_WRITE:
|
||||||
|
case DP_AUX_I2C_WRITE_STATUS_UPDATE:
|
||||||
|
transmitSize += message->size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not bare address, check for buffer
|
||||||
|
if (message->size > 0 && message->buffer == NULL) {
|
||||||
|
ERROR("%s: DP message uninitalized buffer!\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 receiveBuffer[20];
|
||||||
|
uint8 transmitBuffer[20];
|
||||||
|
transmitBuffer[0] = (message->request << 4) | ((message->address >> 16) & 0xf);
|
||||||
|
transmitBuffer[1] = (message->address >> 8) & 0xff;
|
||||||
|
transmitBuffer[2] = message->address & 0xff;
|
||||||
|
transmitBuffer[3] = message->size != 0 ? (message->size - 1) : 0;
|
||||||
|
|
||||||
|
uint8 retry;
|
||||||
|
for (retry = 0; retry < 7; retry++) {
|
||||||
|
ssize_t result = B_ERROR;
|
||||||
|
switch(message->request & ~DP_AUX_I2C_MOT) {
|
||||||
|
case DP_AUX_NATIVE_WRITE:
|
||||||
|
case DP_AUX_I2C_WRITE:
|
||||||
|
case DP_AUX_I2C_WRITE_STATUS_UPDATE:
|
||||||
|
receiveSize = 2;
|
||||||
|
if (message->buffer != NULL)
|
||||||
|
memcpy(transmitBuffer + 4, message->buffer, message->size);
|
||||||
|
result = _DpAuxTransfer(transmitBuffer,
|
||||||
|
transmitSize, receiveBuffer, receiveSize);
|
||||||
|
if (result > 0) {
|
||||||
|
message->reply = receiveBuffer[0] >> 4;
|
||||||
|
if (result > 1)
|
||||||
|
result = min_c(receiveBuffer[1], message->size);
|
||||||
|
else
|
||||||
|
result = message->size;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DP_AUX_NATIVE_READ:
|
||||||
|
case DP_AUX_I2C_READ:
|
||||||
|
receiveSize = message->size + 1;
|
||||||
|
result = _DpAuxTransfer(transmitBuffer,
|
||||||
|
transmitSize, receiveBuffer, receiveSize);
|
||||||
|
if (result > 0) {
|
||||||
|
message->reply = receiveBuffer[0] >> 4;
|
||||||
|
result--;
|
||||||
|
if (message->buffer != NULL)
|
||||||
|
memcpy(message->buffer, receiveBuffer + 1, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ERROR("%s: Unknown dp_aux_msg request!\n", __func__);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == B_BUSY)
|
||||||
|
continue;
|
||||||
|
else if (result < B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
switch(message->reply & DP_AUX_NATIVE_REPLY_MASK) {
|
||||||
|
case DP_AUX_NATIVE_REPLY_ACK:
|
||||||
|
return B_OK;
|
||||||
|
case DP_AUX_NATIVE_REPLY_DEFER:
|
||||||
|
TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
|
||||||
|
snooze(400);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("%s: aux invalid native reply: 0x%02x\n", __func__,
|
||||||
|
message->reply);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry);
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
Port::_DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSize,
|
||||||
|
uint8* receiveBuffer, uint8 receiveSize)
|
||||||
|
{
|
||||||
|
addr_t channelControl;
|
||||||
|
addr_t channelData[5];
|
||||||
|
aux_channel channel = _DpAuxChannel();
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 9
|
||||||
|
|| (gInfo->shared_info->pch_info != INTEL_PCH_NONE && channel == AUX_CH_A)) {
|
||||||
|
channelControl = DP_AUX_CH_CTL(channel);
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
channelData[i] = DP_AUX_CH_DATA(channel, i);
|
||||||
|
} else if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
|
||||||
|
channelControl = PCH_DP_AUX_CH_CTL(channel);
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
channelData[i] = PCH_DP_AUX_CH_DATA(channel, i);
|
||||||
|
} else {
|
||||||
|
ERROR("DigitalDisplayInterface::_DpAuxTransfer() unknown register config\n");
|
||||||
|
return B_BUSY;
|
||||||
|
}
|
||||||
|
if (transmitSize > 20 || receiveSize > 20)
|
||||||
|
return E2BIG;
|
||||||
|
|
||||||
|
int tries = 0;
|
||||||
|
while ((read32(channelControl) & INTEL_DP_AUX_CTL_BUSY) != 0) {
|
||||||
|
if (tries++ == 3) {
|
||||||
|
ERROR("%s: %s AUX channel is busy!\n", __func__, PortName());
|
||||||
|
return B_BUSY;
|
||||||
|
}
|
||||||
|
snooze(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 sendControl = 0;
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 9) {
|
||||||
|
sendControl = INTEL_DP_AUX_CTL_BUSY | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_INTERRUPT
|
||||||
|
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | INTEL_DP_AUX_CTL_TIMEOUT_1600us | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
||||||
|
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | INTEL_DP_AUX_CTL_FW_SYNC_PULSE_SKL(32)
|
||||||
|
| INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(32);
|
||||||
|
} else {
|
||||||
|
uint32 aux_clock_divider = 0xe1; // TODO: value for 450Mhz
|
||||||
|
uint32 timeout = INTEL_DP_AUX_CTL_TIMEOUT_400us;
|
||||||
|
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BDW))
|
||||||
|
timeout = INTEL_DP_AUX_CTL_TIMEOUT_600us;
|
||||||
|
sendControl = INTEL_DP_AUX_CTL_BUSY | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_INTERRUPT
|
||||||
|
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | timeout | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
||||||
|
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | (3 << INTEL_DP_AUX_CTL_PRECHARGE_2US_SHIFT)
|
||||||
|
| (aux_clock_divider << INTEL_DP_AUX_CTL_BIT_CLOCK_2X_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 retry;
|
||||||
|
uint32 status = 0;
|
||||||
|
for (retry = 0; retry < 5; retry++) {
|
||||||
|
for (uint8 i = 0; i < transmitSize;) {
|
||||||
|
uint8 index = i / 4;
|
||||||
|
uint32 data = ((uint32)transmitBuffer[i++]) << 24;
|
||||||
|
if (i < transmitSize)
|
||||||
|
data |= ((uint32)transmitBuffer[i++]) << 16;
|
||||||
|
if (i < transmitSize)
|
||||||
|
data |= ((uint32)transmitBuffer[i++]) << 8;
|
||||||
|
if (i < transmitSize)
|
||||||
|
data |= transmitBuffer[i++];
|
||||||
|
write32(channelData[index], data);
|
||||||
|
}
|
||||||
|
write32(channelControl, sendControl);
|
||||||
|
|
||||||
|
// wait 10 ms reading channelControl until INTEL_DP_AUX_CTL_BUSY
|
||||||
|
status = wait_for_clear_status(channelControl, INTEL_DP_AUX_CTL_BUSY, 10000);
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_BUSY) != 0) {
|
||||||
|
ERROR("%s: %s AUX channel stayed busy for 10000us!\n", __func__, PortName());
|
||||||
|
}
|
||||||
|
|
||||||
|
write32(channelControl, status | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_TIMEOUT_ERROR
|
||||||
|
| INTEL_DP_AUX_CTL_RECEIVE_ERROR);
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_TIMEOUT_ERROR) != 0)
|
||||||
|
continue;
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_RECEIVE_ERROR) != 0) {
|
||||||
|
snooze(400);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_DONE) != 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_DONE) == 0) {
|
||||||
|
ERROR("%s: Busy Error. %" B_PRIu8 " attempts\n", __func__, retry);
|
||||||
|
return B_BUSY;
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_RECEIVE_ERROR) != 0)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
if ((status & INTEL_DP_AUX_CTL_TIMEOUT_ERROR) != 0)
|
||||||
|
return B_TIMEOUT;
|
||||||
|
|
||||||
|
uint8 bytes = (status & INTEL_DP_AUX_CTL_MSG_SIZE_MASK) >> INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT;
|
||||||
|
if (bytes == 0 || bytes > 20) {
|
||||||
|
ERROR("%s: Status byte count incorrect %u\n", __func__, bytes);
|
||||||
|
return B_BUSY;
|
||||||
|
}
|
||||||
|
if (bytes > receiveSize)
|
||||||
|
bytes = receiveSize;
|
||||||
|
for (uint8 i = 0; i < bytes;) {
|
||||||
|
uint32 data = read32(channelData[i / 4]);
|
||||||
|
receiveBuffer[i++] = data >> 24;
|
||||||
|
if (i < bytes)
|
||||||
|
receiveBuffer[i++] = data >> 16;
|
||||||
|
if (i < bytes)
|
||||||
|
receiveBuffer[i++] = data >> 8;
|
||||||
|
if (i < bytes)
|
||||||
|
receiveBuffer[i++] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
aux_channel
|
||||||
|
Port::_DpAuxChannel()
|
||||||
|
{
|
||||||
|
uint32 foundIndex = 0;
|
||||||
|
if (!_IsPortInVBT(&foundIndex))
|
||||||
|
return AUX_CH_A;
|
||||||
|
child_device_config& config = gInfo->shared_info->device_configs[foundIndex];
|
||||||
|
switch (config.aux_channel) {
|
||||||
|
case DP_AUX_B:
|
||||||
|
return AUX_CH_B;
|
||||||
|
case DP_AUX_C:
|
||||||
|
return AUX_CH_C;
|
||||||
|
case DP_AUX_D:
|
||||||
|
return AUX_CH_D;
|
||||||
|
case DP_AUX_E:
|
||||||
|
return AUX_CH_E;
|
||||||
|
case DP_AUX_F:
|
||||||
|
return AUX_CH_F;
|
||||||
|
default:
|
||||||
|
return AUX_CH_A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Analog Port
|
// #pragma mark - Analog Port
|
||||||
|
|
||||||
|
|
||||||
@@ -1195,6 +1577,21 @@ DisplayPort::SetPipe(Pipe* pipe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DisplayPort::SetupI2c(i2c_bus *bus)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 6 && deviceConfigCount > 0) {
|
||||||
|
if (!_IsDisplayPortInVBT())
|
||||||
|
return Port::SetupI2c(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _SetupDpAuxI2c(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DisplayPort::IsConnected()
|
DisplayPort::IsConnected()
|
||||||
{
|
{
|
||||||
@@ -1233,10 +1630,11 @@ DisplayPort::IsConnected()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE("%s: %s link detected\n", __func__, PortName());
|
TRACE("%s: %s link detected\n", __func__, PortName());
|
||||||
|
bool edidDetected = HasEDID();
|
||||||
|
|
||||||
// On laptops we always have an internal panel.. (this is on the eDP port)
|
// On laptops we always have an internal panel.. (this is on the eDP port)
|
||||||
if ((gInfo->shared_info->device_type.IsMobile() || _IsInternalPanelPort())
|
if ((gInfo->shared_info->device_type.IsMobile() || _IsInternalPanelPort())
|
||||||
&& (PortIndex() == INTEL_PORT_A)) {
|
&& (PortIndex() == INTEL_PORT_A) && !edidDetected) {
|
||||||
if (gInfo->shared_info->has_vesa_edid_info) {
|
if (gInfo->shared_info->has_vesa_edid_info) {
|
||||||
TRACE("%s: Laptop. Using VESA edid info\n", __func__);
|
TRACE("%s: Laptop. Using VESA edid info\n", __func__);
|
||||||
memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
|
memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info,
|
||||||
@@ -1266,395 +1664,6 @@ DisplayPort::_DDCRegister()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
DigitalDisplayInterface::SetupI2c(i2c_bus *bus)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 6 && deviceConfigCount > 0) {
|
|
||||||
if (!_IsDisplayPortInVBT())
|
|
||||||
return Port::SetupI2c(bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
ddc2_init_timing(bus);
|
|
||||||
bus->cookie = this;
|
|
||||||
bus->send_receive = &_DpAuxSendReceiveHook;
|
|
||||||
|
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 11) {
|
|
||||||
uint32 value = read32(ICL_PWR_WELL_CTL_AUX2);
|
|
||||||
if ((value & HSW_PWR_WELL_CTL_STATE(0)) != 0)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
write32(ICL_PWR_WELL_CTL_AUX2, value | HSW_PWR_WELL_CTL_REQ(0));
|
|
||||||
if (!wait_for_set(ICL_PWR_WELL_CTL_AUX2, HSW_PWR_WELL_CTL_STATE(0), 1000))
|
|
||||||
ERROR("%s: %s AUX didn't power on within 1000us!\n", __func__, PortName());
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
DigitalDisplayInterface::_DpAuxSendReceive(uint32 slaveAddress,
|
|
||||||
const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
|
|
||||||
{
|
|
||||||
size_t transferLength = 16;
|
|
||||||
|
|
||||||
dp_aux_msg message;
|
|
||||||
memset(&message, 0, sizeof(message));
|
|
||||||
|
|
||||||
if (writeBuffer != NULL) {
|
|
||||||
message.address = slaveAddress;
|
|
||||||
message.buffer = NULL;
|
|
||||||
message.request = DP_AUX_I2C_WRITE;
|
|
||||||
message.size = 0;
|
|
||||||
ssize_t result = _DpAuxTransfer(&message);
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < writeLength;) {
|
|
||||||
message.buffer = (void*)(writeBuffer + i);
|
|
||||||
message.size = min_c(transferLength, writeLength - i);
|
|
||||||
// Middle-Of-Transmission on final transaction
|
|
||||||
if (writeLength - i > transferLength)
|
|
||||||
message.request |= DP_AUX_I2C_MOT;
|
|
||||||
else
|
|
||||||
message.request &= ~DP_AUX_I2C_MOT;
|
|
||||||
|
|
||||||
for (int attempt = 0; attempt < 7; attempt++) {
|
|
||||||
ssize_t result = _DpAuxTransfer(&message);
|
|
||||||
if (result < 0) {
|
|
||||||
ERROR("%s: aux_ch transaction failed!\n", __func__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
|
|
||||||
case DP_AUX_I2C_REPLY_ACK:
|
|
||||||
goto nextWrite;
|
|
||||||
case DP_AUX_I2C_REPLY_NACK:
|
|
||||||
TRACE("%s: aux i2c nack\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
case DP_AUX_I2C_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux i2c defer\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux invalid I2C reply: 0x%02x\n",
|
|
||||||
__func__, message.reply);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextWrite:
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
i += message.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (readBuffer != NULL) {
|
|
||||||
message.address = slaveAddress;
|
|
||||||
message.buffer = NULL;
|
|
||||||
message.request = DP_AUX_I2C_READ;
|
|
||||||
message.size = 0;
|
|
||||||
ssize_t result = _DpAuxTransfer(&message);
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < readLength;) {
|
|
||||||
message.buffer = readBuffer + i;
|
|
||||||
message.size = min_c(transferLength, readLength - i);
|
|
||||||
// Middle-Of-Transmission on final transaction
|
|
||||||
if (readLength - i > transferLength)
|
|
||||||
message.request |= DP_AUX_I2C_MOT;
|
|
||||||
else
|
|
||||||
message.request &= ~DP_AUX_I2C_MOT;
|
|
||||||
|
|
||||||
for (int attempt = 0; attempt < 7; attempt++) {
|
|
||||||
result = _DpAuxTransfer(&message);
|
|
||||||
if (result < 0) {
|
|
||||||
ERROR("%s: aux_ch transaction failed!\n", __func__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (message.reply & DP_AUX_I2C_REPLY_MASK) {
|
|
||||||
case DP_AUX_I2C_REPLY_ACK:
|
|
||||||
goto nextRead;
|
|
||||||
case DP_AUX_I2C_REPLY_NACK:
|
|
||||||
TRACE("%s: aux i2c nack\n", __func__);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
case DP_AUX_I2C_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux i2c defer\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux invalid I2C reply: 0x%02x\n",
|
|
||||||
__func__, message.reply);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextRead:
|
|
||||||
if (result < 0)
|
|
||||||
return result;
|
|
||||||
if (result == 0)
|
|
||||||
i += message.size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
DigitalDisplayInterface::_DpAuxSendReceiveHook(const struct i2c_bus *bus, uint32 slaveAddress,
|
|
||||||
const uint8 *writeBuffer, size_t writeLength, uint8 *readBuffer, size_t readLength)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
DigitalDisplayInterface* port = (DigitalDisplayInterface*)bus->cookie;
|
|
||||||
return port->_DpAuxSendReceive(slaveAddress, writeBuffer, writeLength, readBuffer, readLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
DigitalDisplayInterface::_DpAuxTransfer(dp_aux_msg* message)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
if (message == NULL) {
|
|
||||||
ERROR("%s: DP message is invalid!\n", __func__);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message->size > 16) {
|
|
||||||
ERROR("%s: Too many bytes! (%" B_PRIuSIZE ")\n", __func__,
|
|
||||||
message->size);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 transmitSize = message->size > 0 ? 4 : 3;
|
|
||||||
uint8 receiveSize;
|
|
||||||
|
|
||||||
switch(message->request & ~DP_AUX_I2C_MOT) {
|
|
||||||
case DP_AUX_NATIVE_WRITE:
|
|
||||||
case DP_AUX_I2C_WRITE:
|
|
||||||
case DP_AUX_I2C_WRITE_STATUS_UPDATE:
|
|
||||||
transmitSize += message->size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not bare address, check for buffer
|
|
||||||
if (message->size > 0 && message->buffer == NULL) {
|
|
||||||
ERROR("%s: DP message uninitalized buffer!\n", __func__);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 receiveBuffer[20];
|
|
||||||
uint8 transmitBuffer[20];
|
|
||||||
transmitBuffer[0] = (message->request << 4) | ((message->address >> 16) & 0xf);
|
|
||||||
transmitBuffer[1] = (message->address >> 8) & 0xff;
|
|
||||||
transmitBuffer[2] = message->address & 0xff;
|
|
||||||
transmitBuffer[3] = message->size != 0 ? (message->size - 1) : 0;
|
|
||||||
|
|
||||||
uint8 retry;
|
|
||||||
for (retry = 0; retry < 7; retry++) {
|
|
||||||
ssize_t result = B_ERROR;
|
|
||||||
switch(message->request & ~DP_AUX_I2C_MOT) {
|
|
||||||
case DP_AUX_NATIVE_WRITE:
|
|
||||||
case DP_AUX_I2C_WRITE:
|
|
||||||
case DP_AUX_I2C_WRITE_STATUS_UPDATE:
|
|
||||||
receiveSize = 2;
|
|
||||||
if (message->buffer != NULL)
|
|
||||||
memcpy(transmitBuffer + 4, message->buffer, message->size);
|
|
||||||
result = _DpAuxTransfer(transmitBuffer,
|
|
||||||
transmitSize, receiveBuffer, receiveSize);
|
|
||||||
if (result > 0) {
|
|
||||||
message->reply = receiveBuffer[0] >> 4;
|
|
||||||
if (result > 1)
|
|
||||||
result = min_c(receiveBuffer[1], message->size);
|
|
||||||
else
|
|
||||||
result = message->size;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DP_AUX_NATIVE_READ:
|
|
||||||
case DP_AUX_I2C_READ:
|
|
||||||
receiveSize = message->size + 1;
|
|
||||||
result = _DpAuxTransfer(transmitBuffer,
|
|
||||||
transmitSize, receiveBuffer, receiveSize);
|
|
||||||
if (result > 0) {
|
|
||||||
message->reply = receiveBuffer[0] >> 4;
|
|
||||||
result--;
|
|
||||||
if (message->buffer != NULL)
|
|
||||||
memcpy(message->buffer, receiveBuffer + 1, result);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ERROR("%s: Unknown dp_aux_msg request!\n", __func__);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == B_BUSY)
|
|
||||||
continue;
|
|
||||||
else if (result < B_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
switch(message->reply & DP_AUX_NATIVE_REPLY_MASK) {
|
|
||||||
case DP_AUX_NATIVE_REPLY_ACK:
|
|
||||||
return B_OK;
|
|
||||||
case DP_AUX_NATIVE_REPLY_DEFER:
|
|
||||||
TRACE("%s: aux reply defer received. Snoozing.\n", __func__);
|
|
||||||
snooze(400);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TRACE("%s: aux invalid native reply: 0x%02x\n", __func__,
|
|
||||||
message->reply);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERROR("%s: IO Error. %" B_PRIu8 " attempts\n", __func__, retry);
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
DigitalDisplayInterface::_DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSize,
|
|
||||||
uint8* receiveBuffer, uint8 receiveSize)
|
|
||||||
{
|
|
||||||
addr_t channelControl;
|
|
||||||
addr_t channelData[5];
|
|
||||||
aux_channel channel = _DpAuxChannel();
|
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 9
|
|
||||||
|| (gInfo->shared_info->pch_info != INTEL_PCH_NONE && channel == AUX_CH_A)) {
|
|
||||||
channelControl = DP_AUX_CH_CTL(channel);
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
channelData[i] = DP_AUX_CH_DATA(channel, i);
|
|
||||||
} else if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
|
|
||||||
channelControl = PCH_DP_AUX_CH_CTL(channel);
|
|
||||||
for (int i = 0; i < 5; i++)
|
|
||||||
channelData[i] = PCH_DP_AUX_CH_DATA(channel, i);
|
|
||||||
} else {
|
|
||||||
ERROR("DigitalDisplayInterface::_DpAuxTransfer() unknown register config\n");
|
|
||||||
return B_BUSY;
|
|
||||||
}
|
|
||||||
if (transmitSize > 20 || receiveSize > 20)
|
|
||||||
return E2BIG;
|
|
||||||
|
|
||||||
int tries = 0;
|
|
||||||
while ((read32(channelControl) & INTEL_DP_AUX_CTL_BUSY) != 0) {
|
|
||||||
if (tries++ == 3) {
|
|
||||||
ERROR("%s: %s AUX channel is busy!\n", __func__, PortName());
|
|
||||||
return B_BUSY;
|
|
||||||
}
|
|
||||||
snooze(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 sendControl = 0;
|
|
||||||
if (gInfo->shared_info->device_type.Generation() >= 9) {
|
|
||||||
sendControl = INTEL_DP_AUX_CTL_BUSY | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_INTERRUPT
|
|
||||||
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | INTEL_DP_AUX_CTL_TIMEOUT_1600us | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
|
||||||
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | INTEL_DP_AUX_CTL_FW_SYNC_PULSE_SKL(32)
|
|
||||||
| INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(32);
|
|
||||||
} else {
|
|
||||||
uint32 aux_clock_divider = 0xe1; // TODO: value for 450Mhz
|
|
||||||
uint32 timeout = INTEL_DP_AUX_CTL_TIMEOUT_400us;
|
|
||||||
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BDW))
|
|
||||||
timeout = INTEL_DP_AUX_CTL_TIMEOUT_600us;
|
|
||||||
sendControl = INTEL_DP_AUX_CTL_BUSY | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_INTERRUPT
|
|
||||||
| INTEL_DP_AUX_CTL_TIMEOUT_ERROR | timeout | INTEL_DP_AUX_CTL_RECEIVE_ERROR
|
|
||||||
| (transmitSize << INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT) | (3 << INTEL_DP_AUX_CTL_PRECHARGE_2US_SHIFT)
|
|
||||||
| (aux_clock_divider << INTEL_DP_AUX_CTL_BIT_CLOCK_2X_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 retry;
|
|
||||||
uint32 status = 0;
|
|
||||||
for (retry = 0; retry < 5; retry++) {
|
|
||||||
for (uint8 i = 0; i < transmitSize;) {
|
|
||||||
uint8 index = i / 4;
|
|
||||||
uint32 data = ((uint32)transmitBuffer[i++]) << 24;
|
|
||||||
if (i < transmitSize)
|
|
||||||
data |= ((uint32)transmitBuffer[i++]) << 16;
|
|
||||||
if (i < transmitSize)
|
|
||||||
data |= ((uint32)transmitBuffer[i++]) << 8;
|
|
||||||
if (i < transmitSize)
|
|
||||||
data |= transmitBuffer[i++];
|
|
||||||
write32(channelData[index], data);
|
|
||||||
}
|
|
||||||
write32(channelControl, sendControl);
|
|
||||||
|
|
||||||
// wait 10 ms reading channelControl until INTEL_DP_AUX_CTL_BUSY
|
|
||||||
status = wait_for_clear_status(channelControl, INTEL_DP_AUX_CTL_BUSY, 10000);
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_BUSY) != 0) {
|
|
||||||
ERROR("%s: %s AUX channel stayed busy for 10000us!\n", __func__, PortName());
|
|
||||||
}
|
|
||||||
|
|
||||||
write32(channelControl, status | INTEL_DP_AUX_CTL_DONE | INTEL_DP_AUX_CTL_TIMEOUT_ERROR
|
|
||||||
| INTEL_DP_AUX_CTL_RECEIVE_ERROR);
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_TIMEOUT_ERROR) != 0)
|
|
||||||
continue;
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_RECEIVE_ERROR) != 0) {
|
|
||||||
snooze(400);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_DONE) != 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_DONE) == 0) {
|
|
||||||
ERROR("%s: Busy Error. %" B_PRIu8 " attempts\n", __func__, retry);
|
|
||||||
return B_BUSY;
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_RECEIVE_ERROR) != 0)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
if ((status & INTEL_DP_AUX_CTL_TIMEOUT_ERROR) != 0)
|
|
||||||
return B_TIMEOUT;
|
|
||||||
|
|
||||||
uint8 bytes = (status & INTEL_DP_AUX_CTL_MSG_SIZE_MASK) >> INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT;
|
|
||||||
if (bytes == 0 || bytes > 20) {
|
|
||||||
ERROR("%s: Status byte count incorrect %u\n", __func__, bytes);
|
|
||||||
return B_BUSY;
|
|
||||||
}
|
|
||||||
if (bytes > receiveSize)
|
|
||||||
bytes = receiveSize;
|
|
||||||
for (uint8 i = 0; i < bytes;) {
|
|
||||||
uint32 data = read32(channelData[i / 4]);
|
|
||||||
receiveBuffer[i++] = data >> 24;
|
|
||||||
if (i < bytes)
|
|
||||||
receiveBuffer[i++] = data >> 16;
|
|
||||||
if (i < bytes)
|
|
||||||
receiveBuffer[i++] = data >> 8;
|
|
||||||
if (i < bytes)
|
|
||||||
receiveBuffer[i++] = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
aux_channel
|
|
||||||
DigitalDisplayInterface::_DpAuxChannel()
|
|
||||||
{
|
|
||||||
uint32 foundIndex = 0;
|
|
||||||
if (!_IsPortInVBT(&foundIndex))
|
|
||||||
return AUX_CH_A;
|
|
||||||
child_device_config& config = gInfo->shared_info->device_configs[foundIndex];
|
|
||||||
switch (config.aux_channel) {
|
|
||||||
case DP_AUX_B:
|
|
||||||
return AUX_CH_B;
|
|
||||||
case DP_AUX_C:
|
|
||||||
return AUX_CH_C;
|
|
||||||
case DP_AUX_D:
|
|
||||||
return AUX_CH_D;
|
|
||||||
case DP_AUX_E:
|
|
||||||
return AUX_CH_E;
|
|
||||||
case DP_AUX_F:
|
|
||||||
return AUX_CH_F;
|
|
||||||
default:
|
|
||||||
return AUX_CH_A;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
addr_t
|
addr_t
|
||||||
DisplayPort::_PortRegister()
|
DisplayPort::_PortRegister()
|
||||||
{
|
{
|
||||||
@@ -2155,6 +2164,21 @@ DigitalDisplayInterface::SetPipe(Pipe* pipe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DigitalDisplayInterface::SetupI2c(i2c_bus *bus)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
const uint32 deviceConfigCount = gInfo->shared_info->device_config_count;
|
||||||
|
if (gInfo->shared_info->device_type.Generation() >= 6 && deviceConfigCount > 0) {
|
||||||
|
if (!_IsDisplayPortInVBT())
|
||||||
|
return Port::SetupI2c(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _SetupDpAuxI2c(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DigitalDisplayInterface::IsConnected()
|
DigitalDisplayInterface::IsConnected()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,6 +78,19 @@ static status_t _SetI2CSignals(void* cookie, int clock,
|
|||||||
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
bool _IsPortInVBT(uint32* foundIndex = NULL);
|
||||||
bool _IsDisplayPortInVBT();
|
bool _IsDisplayPortInVBT();
|
||||||
bool _IsInternalPanelPort();
|
bool _IsInternalPanelPort();
|
||||||
|
status_t _SetupDpAuxI2c(struct i2c_bus *bus);
|
||||||
|
|
||||||
|
ssize_t _DpAuxTransfer(dp_aux_msg* message);
|
||||||
|
ssize_t _DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSize,
|
||||||
|
uint8* receiveBuffer, uint8 receiveSize);
|
||||||
|
status_t _DpAuxSendReceive(uint32 slave_address,
|
||||||
|
const uint8 *writeBuffer, size_t writeLength,
|
||||||
|
uint8 *readBuffer, size_t readLength);
|
||||||
|
static status_t _DpAuxSendReceiveHook(const struct i2c_bus *bus,
|
||||||
|
uint32 slave_address, const uint8 *writeBuffer,
|
||||||
|
size_t writeLength, uint8 *readBuffer,
|
||||||
|
size_t readLength);
|
||||||
|
aux_channel _DpAuxChannel();
|
||||||
|
|
||||||
display_mode fCurrentMode;
|
display_mode fCurrentMode;
|
||||||
Pipe* fPipe;
|
Pipe* fPipe;
|
||||||
@@ -175,6 +188,7 @@ virtual uint32 Type() const
|
|||||||
{ return INTEL_PORT_TYPE_DP; }
|
{ return INTEL_PORT_TYPE_DP; }
|
||||||
|
|
||||||
virtual status_t SetPipe(Pipe* pipe);
|
virtual status_t SetPipe(Pipe* pipe);
|
||||||
|
virtual status_t SetupI2c(i2c_bus *bus);
|
||||||
|
|
||||||
virtual bool IsConnected();
|
virtual bool IsConnected();
|
||||||
|
|
||||||
@@ -231,18 +245,6 @@ private:
|
|||||||
|
|
||||||
status_t _SetPortLinkGen8(const display_timing& timing,
|
status_t _SetPortLinkGen8(const display_timing& timing,
|
||||||
uint32 pllSel);
|
uint32 pllSel);
|
||||||
|
|
||||||
ssize_t _DpAuxTransfer(dp_aux_msg* message);
|
|
||||||
ssize_t _DpAuxTransfer(uint8* transmitBuffer, uint8 transmitSize,
|
|
||||||
uint8* receiveBuffer, uint8 receiveSize);
|
|
||||||
status_t _DpAuxSendReceive(uint32 slave_address,
|
|
||||||
const uint8 *writeBuffer, size_t writeLength,
|
|
||||||
uint8 *readBuffer, size_t readLength);
|
|
||||||
static status_t _DpAuxSendReceiveHook(const struct i2c_bus *bus,
|
|
||||||
uint32 slave_address, const uint8 *writeBuffer,
|
|
||||||
size_t writeLength, uint8 *readBuffer,
|
|
||||||
size_t readLength);
|
|
||||||
aux_channel _DpAuxChannel();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user