dptx: Improved remote IIC reads/writes to automatically work on 16-byte chunks.

Some monitors don't support sideband messages with IIC reads greater than 16
bytes. This improvement breaks up the higher-level read/write request into
multiple reads/writes that work with up to 16 bytes in size.

These higher-level remote IIC read/write functions also serve as a wrapper for
an IIC read/write in case that the link count total is equal to 1 (a read/write
request to the RX device directly connected to the TX (not "remote")).

Signed-off-by: Andrei-Liviu Simion <andrei.simion@xilinx.com>
This commit is contained in:
Andrei-Liviu Simion 2014-10-31 14:16:59 -07:00 committed by Suneel Garapati
parent bc8b86b940
commit ce0e1fd561
3 changed files with 124 additions and 9 deletions

View file

@ -838,7 +838,7 @@ u32 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u16 Offset,
/* Reposition based on a segment length of 256 bytes. */
SegPtr = 0;
if (Offset >= 255) {
if (Offset > 255) {
SegPtr += Offset / 256;
Offset %= 256;
}

View file

@ -839,6 +839,11 @@ u32 XDptx_RemoteDpcdRead(XDptx *InstancePtr, u8 LinkCountTotal,
u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData);
u32 XDptx_RemoteDpcdWrite(XDptx *InstancePtr, u8 LinkCountTotal,
u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData);
u32 XDptx_RemoteIicRead(XDptx *InstancePtr, u8 LinkCountTotal,
u8 *RelativeAddress, u8 IicAddress, u16 Offset, u16 BytesToRead,
u8 *ReadData);
u32 XDptx_RemoteIicWrite(XDptx *InstancePtr, u8 LinkCountTotal,
u8 *RelativeAddress, u8 IicAddress, u8 BytesToWrite, u8 *WriteData);
/* xdptx_mst.c: Multi-stream transport (MST) functions related to MST stream
* allocation. */

View file

@ -784,6 +784,122 @@ u32 XDptx_RemoteDpcdWrite(XDptx *InstancePtr, u8 LinkCountTotal,
return Status;
}
u32 XDptx_RemoteIicRead(XDptx *InstancePtr, u8 LinkCountTotal,
u8 *RelativeAddress, u8 IicAddress, u16 Offset, u16 BytesToRead,
u8 *ReadData)
{
u32 Status;
if (LinkCountTotal == 1) {
Status = XDptx_IicRead(InstancePtr, IicAddress, Offset,
BytesToRead, ReadData);
return Status;
}
u8 SegPtr;
u16 NumBytesLeftInSeg;
u16 BytesLeft = BytesToRead;
u8 CurrBytesToRead;
/* Reposition based on a segment length of 256 bytes. */
SegPtr = 0;
if (Offset > 255) {
SegPtr += Offset / 256;
Offset %= 256;
}
NumBytesLeftInSeg = 256 - Offset;
/* Set the segment pointer to 0. */
Status = XDptx_RemoteIicWrite(InstancePtr, LinkCountTotal,
RelativeAddress, 0x30, 1, &SegPtr);
if (Status != XST_SUCCESS) {
/* The I2C write to set the segment pointer failed. */
return Status;
}
/* Send I2C read message in 16 byte chunks. */
while (BytesLeft > 0) {
/* Reposition based on segment boundaries. */
if (NumBytesLeftInSeg >= 16) {
CurrBytesToRead = 16;
}
else if (NumBytesLeftInSeg >= BytesLeft) {
CurrBytesToRead = BytesLeft;
}
else {
CurrBytesToRead = NumBytesLeftInSeg;
}
/* Send remote I2C read sideband message. */
Status = XDptx_SendSbMsgRemoteIicRead(InstancePtr,
LinkCountTotal, RelativeAddress, IicAddress, Offset,
BytesLeft, ReadData);
if (Status != XST_SUCCESS) {
/* The sideband message transaction failed. */
return Status;
}
/* I2C read of 16 bytes. */
if (BytesLeft > CurrBytesToRead) {
BytesLeft -= CurrBytesToRead;
Offset += CurrBytesToRead;
ReadData += CurrBytesToRead;
NumBytesLeftInSeg -= CurrBytesToRead;
}
/* Last I2C read. */
else {
BytesLeft = 0;
}
/* Increment the segment pointer to access more I2C address
* space. */
if ((NumBytesLeftInSeg == 0) && (BytesLeft > 0)) {
SegPtr++;
Offset %= 256;
NumBytesLeftInSeg = 256;
Status = XDptx_RemoteIicWrite(InstancePtr,
LinkCountTotal, RelativeAddress, 0x30, 1,
&SegPtr);
if (Status != XST_SUCCESS) {
return Status;
}
}
}
/* Reset the segment pointer to 0. */
SegPtr = 0;
Status = XDptx_RemoteIicWrite(InstancePtr, LinkCountTotal,
RelativeAddress, 0x30, 1, &SegPtr);
return Status;
}
u32 XDptx_RemoteIicWrite(XDptx *InstancePtr, u8 LinkCountTotal,
u8 *RelativeAddress, u8 IicAddress, u8 BytesToWrite,
u8 *WriteData)
{
u32 Status;
if (LinkCountTotal == 1) {
Status = XDptx_IicWrite(InstancePtr, IicAddress, BytesToWrite,
WriteData);
}
else {
Status = XDptx_SendSbMsgRemoteIicWrite(InstancePtr,
LinkCountTotal, RelativeAddress, IicAddress,
BytesToWrite, WriteData);
if (Status != XST_SUCCESS) {
/* The AUX read transaction failed. */
return Status;
}
}
return Status;
}
/******************************************************************************/
/**
* This function will allocate bandwidth for all enabled stream.
@ -1803,14 +1919,8 @@ u32 XDptx_GetRemoteEdid(XDptx *InstancePtr, u8 LinkCountTotal,
Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1));
Xil_AssertNonvoid(Edid != NULL);
if (LinkCountTotal == 1) {
Status = XDptx_GetEdid(InstancePtr, Edid);
}
else {
Status = XDptx_SendSbMsgRemoteIicRead(InstancePtr,
LinkCountTotal, RelativeAddress,
XDPTX_EDID_ADDR, 0, XDPTX_EDID_SIZE, Edid);
}
Status = XDptx_RemoteIicRead(InstancePtr, LinkCountTotal,
RelativeAddress, XDPTX_EDID_ADDR, 0, XDPTX_EDID_SIZE, Edid);
return Status;
}