From fe2c47e815054f4902e5d55ff64fb71ea0ebd16b Mon Sep 17 00:00:00 2001 From: Andrei-Liviu Simion Date: Thu, 6 Nov 2014 20:17:27 -0800 Subject: [PATCH] dptx: Added functions that reorder the sink numbering of the topology. Added functionality that reorders the sink list such that topologies containing tiled display(s) will have the contained sinks reordered in a consistent manner. The need for such functionality exists because not all tiled displays will have the same internal topologies. It was observed that two 4k2k MST based monitors (tiled display, 2 sinks) from different manufacturers would have the left and right images swapped using identical stream-to-sink mappings. Thus, the need to obtain the tiled display topology information of all sinks and their relative tile location is required to send the correct stream to the desired sink. Signed-off-by: Andrei-Liviu Simion --- XilinxProcessorIPLib/drivers/dptx/src/xdptx.h | 4 +- .../drivers/dptx/src/xdptx_mst.c | 114 ++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h b/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h index eb795460..863d0c39 100644 --- a/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h @@ -827,10 +827,12 @@ void XDptx_SetStreamSinkRad(XDptx *InstancePtr, u8 Stream, u8 LinkCountTotal, u8 *RelativeAddress); /* xdptx_mst.c: Multi-stream transport (MST) functions related to MST topology - * discovery. */ + * discovery and management. */ u32 XDptx_DiscoverTopology(XDptx *InstancePtr); u32 XDptx_FindAccessibleDpDevices(XDptx *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress); +void XDptx_TopologySwapSinks(XDptx *InstancePtr, u8 Index0, u8 Index1); +u32 XDptx_TopologySortSinksByTiling(XDptx *InstancePtr); /* xdptx_mst.c: Multi-stream transport (MST) functions for communicating * with downstream DisplayPort devices. */ diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c index 9486195a..dad8504d 100644 --- a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c @@ -162,6 +162,7 @@ static u32 XDptx_Transaction2MsgFormat(u8 *Transaction, XDptx_SidebandMsg *Msg); static u8 XDptx_Crc4CalculateHeader(XDptx_SidebandMsgHeader *Header); static u8 XDptx_Crc8CalculateBody(XDptx_SidebandMsgBody *Body); static u8 XDptx_CrcCalculate(const u8 *Data, u32 NumberOfBits, u8 Polynomial); +static u32 XDptx_IsSameTileDisplay(u8 *DispIdSecTile0, u8 *DispIdSecTile1); /**************************** Variable Definitions ****************************/ @@ -706,6 +707,93 @@ u32 XDptx_FindAccessibleDpDevices(XDptx *InstancePtr, u8 LinkCountTotal, return XST_SUCCESS; } +void XDptx_TopologySwapSinks(XDptx *InstancePtr, u8 Index0, u8 Index1) +{ + XDptx_TopologyNode *TmpSink = InstancePtr->Topology.SinkList[Index0]; + + InstancePtr->Topology.SinkList[Index0] = + InstancePtr->Topology.SinkList[Index1]; + + InstancePtr->Topology.SinkList[Index1] = TmpSink; +} + +u32 XDptx_TopologySortSinksByTiling(XDptx *InstancePtr) +{ + u32 Status; + XDptx_TopologyNode *CurrSink, *CmpSink; + u8 CurrIndex, CmpIndex, NewIndex; + u8 CurrEdidExt[128], CmpEdidExt[128]; + u8 *CurrTdt, *CmpTdt; + u8 CurrTileOrder, CmpTileOrder; + u8 SameTileDispCount, SameTileDispNum; + + for (CurrIndex = 0; CurrIndex < + (InstancePtr->Topology.SinkTotal - 1); CurrIndex++) { + CurrSink = InstancePtr->Topology.SinkList[CurrIndex]; + + Status = XDptx_GetRemoteTiledDisplayDb(InstancePtr, CurrEdidExt, + CurrSink->LinkCountTotal, + CurrSink->RelativeAddress, &CurrTdt); + if (Status != XST_SUCCESS) { + /* No tiled display topology data block exists. */ + return XST_FAILURE; + } + + /* Start by using the tiling parameters of the current sink + * index. */ + CurrTileOrder = XDptx_GetDispIdTdtTileOrder(CurrTdt); + NewIndex = CurrIndex; + SameTileDispCount = 1; + SameTileDispNum = XDptx_GetDispIdTdtNumTiles(CurrTdt); + + /* Try to find a sink that is part of the same tiled display, + * but has a smaller tile location - the sink with a smaller + * tile location should be ordered first in the topology's sink + * list. */ + for (CmpIndex = (CurrIndex + 1); + (CmpIndex < InstancePtr->Topology.SinkTotal) + && (SameTileDispCount < SameTileDispNum); + CmpIndex++) { + CmpSink = InstancePtr->Topology.SinkList[CmpIndex]; + + Status = XDptx_GetRemoteTiledDisplayDb( + InstancePtr, CmpEdidExt, + CmpSink->LinkCountTotal, + CmpSink->RelativeAddress, &CmpTdt); + if (Status != XST_SUCCESS) { + /* No tiled display topology data block. */ + return XST_FAILURE; + } + + if (!XDptx_IsSameTileDisplay(CurrTdt, CmpTdt)) { + /* The sink under comparison does not belong to + * the same tiled display. */ + continue; + } + + /* Keep track of the sink with a tile location that + * should be ordered first out of the remaining sinks + * that are part of the same tiled display. */ + CmpTileOrder = XDptx_GetDispIdTdtTileOrder(CmpTdt); + if (CurrTileOrder > CmpTileOrder) { + CurrTileOrder = CmpTileOrder; + NewIndex = CmpIndex; + SameTileDispCount++; + } + } + + /* If required, swap the current sink with the sink that is a + * part of the same tiled display, but has a smaller tile + * location. */ + if (CurrIndex != NewIndex) { + XDptx_TopologySwapSinks(InstancePtr, CurrIndex, + NewIndex); + } + } + + return XST_SUCCESS; +} + /******************************************************************************/ /** * This function performs a remote DisplayPort Configuration Data (DPCD) read @@ -2801,3 +2889,29 @@ static u8 XDptx_CrcCalculate(const u8 *Data, u32 NumberOfBits, u8 Polynomial) return Remainder & 0xFF; } + +static u32 XDptx_IsSameTileDisplay(u8 *TileDisp0, u8 *TileDisp1) +{ + if ((TileDisp0[XDPTX_DISPID_TDT_VENID0] != + TileDisp1[XDPTX_DISPID_TDT_VENID0]) || + (TileDisp0[XDPTX_DISPID_TDT_VENID1] != + TileDisp1[XDPTX_DISPID_TDT_VENID1]) || + (TileDisp0[XDPTX_DISPID_TDT_VENID2] != + TileDisp1[XDPTX_DISPID_TDT_VENID2]) || + (TileDisp0[XDPTX_DISPID_TDT_PCODE0] != + TileDisp1[XDPTX_DISPID_TDT_PCODE0]) || + (TileDisp0[XDPTX_DISPID_TDT_PCODE1] != + TileDisp1[XDPTX_DISPID_TDT_PCODE1]) || + (TileDisp0[XDPTX_DISPID_TDT_SN0] != + TileDisp1[XDPTX_DISPID_TDT_SN0]) || + (TileDisp0[XDPTX_DISPID_TDT_SN1] != + TileDisp1[XDPTX_DISPID_TDT_SN1]) || + (TileDisp0[XDPTX_DISPID_TDT_SN2] != + TileDisp1[XDPTX_DISPID_TDT_SN2]) || + (TileDisp0[XDPTX_DISPID_TDT_SN3] != + TileDisp1[XDPTX_DISPID_TDT_SN3]) ) { + return 0; + } + + return 1; +}