/******************************************************************************* * * Copyright (C) 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * *******************************************************************************/ /******************************************************************************/ /** * * @file xdptx_edid.c * * This file contains functions related to accessing the Extended Display * Identification Data (EDID) of a specified sink using the XDptx driver. * * @note None. * *
* MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- * 3.0 als 11/04/14 Initial release. ** *******************************************************************************/ /******************************* Include Files ********************************/ #include "xdptx.h" #include "xstatus.h" /**************************** Function Definitions ****************************/ /******************************************************************************/ /** * This function retrieves an immediately connected RX device's Extended Display * Identification Data (EDID) structure. * * @param InstancePtr is a pointer to the XDptx instance. * @param Edid is a pointer to the Edid buffer to save to. * * @return * - XST_SUCCESS if the I2C transactions to read the EDID were * successful. * - XST_ERROR_COUNT_MAX if the EDID read request timed out. * - XST_DEVICE_NOT_FOUND if no RX device is connected. * - XST_FAILURE otherwise. * * @note None. * *******************************************************************************/ u32 XDptx_GetEdid(XDptx *InstancePtr, u8 *Edid) { u32 Status; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(Edid != NULL); /* Retrieve the base EDID block = EDID block #0. */ Status = XDptx_GetEdidBlock(InstancePtr, Edid, 0); return Status; } /******************************************************************************/ /** * This function retrieves a remote RX device's Extended Display Identification * Data (EDID) structure. * * @param InstancePtr is a pointer to the XDptx instance. * @param LinkCountTotal is the number of DisplayPort links from the * DisplayPort source to the target DisplayPort device. * @param RelativeAddress is the relative address from the DisplayPort * source to the target DisplayPort device. * @param Edid is a pointer to the Edid buffer to save to. * * @return * - XST_SUCCESS if the I2C transactions to read the EDID were * successful. * - XST_ERROR_COUNT_MAX if the EDID read request timed out. * - XST_DEVICE_NOT_FOUND if no RX device is connected. * - XST_FAILURE otherwise. * * @note None. * *******************************************************************************/ u32 XDptx_GetRemoteEdid(XDptx *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, u8 *Edid) { u32 Status; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(LinkCountTotal > 0); Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); Xil_AssertNonvoid(Edid != NULL); /* Retrieve the base EDID block = EDID block #0. */ Status = XDptx_GetRemoteEdidBlock(InstancePtr, Edid, 0, LinkCountTotal, RelativeAddress); return Status; } /******************************************************************************/ /** * Retrieve an immediately connected RX device's Extended Display Identification * Data (EDID) block given the block number. A block number of 0 represents the * base EDID and subsequent block numbers represent EDID extension blocks. * * @param InstancePtr is a pointer to the XDptx instance. * @param Data is a pointer to the data buffer to save the block data to. * @param BlockNum is the EDID block number to retrieve. * * @return * - XST_SUCCESS if the block read has successfully completed with * no errors. * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to * read the requested block. * - XST_DEVICE_NOT_FOUND if no RX device is connected. * - XST_FAILURE otherwise. * * @note None. * *******************************************************************************/ u32 XDptx_GetEdidBlock(XDptx *InstancePtr, u8 *Data, u8 BlockNum) { u32 Status; u16 Offset; /* Calculate the I2C offset for the specified EDID block. */ Offset = BlockNum * XDPTX_EDID_BLOCK_SIZE; /* Issue the I2C read for the specified EDID block. */ Status = XDptx_IicRead(InstancePtr, XDPTX_EDID_ADDR, Offset, XDPTX_EDID_BLOCK_SIZE, Data); return Status; } /******************************************************************************/ /** * Retrieve a downstream DisplayPort device's Extended Display Identification * Data (EDID) block given the block number. A block number of 0 represents the * base EDID and subsequent block numbers represent EDID extension blocks. * * @param InstancePtr is a pointer to the XDptx instance. * @param Data is a pointer to the data buffer to save the block data to. * @param BlockNum is the EDID block number to retrieve. * @param LinkCountTotal is the total DisplayPort links connecting the * DisplayPort TX to the targeted downstream device. * @param RelativeAddress is the relative address from the DisplayPort * source to the targeted DisplayPort device. * * @return * - XST_SUCCESS if the block read has successfully completed with * no errors. * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to * read the requested block. * - XST_DEVICE_NOT_FOUND if no RX device is connected. * - XST_FAILURE otherwise. * * @note None. * *******************************************************************************/ u32 XDptx_GetRemoteEdidBlock(XDptx *InstancePtr, u8 *Data, u8 BlockNum, u8 LinkCountTotal, u8 *RelativeAddress) { u32 Status; u16 Offset; /* Calculate the I2C offset for the specified EDID block. */ Offset = BlockNum * XDPTX_EDID_BLOCK_SIZE; /* Issue the I2C read for the specified EDID block. */ Status = XDptx_RemoteIicRead(InstancePtr, LinkCountTotal, RelativeAddress, XDPTX_EDID_ADDR, Offset, XDPTX_EDID_BLOCK_SIZE, Data); return Status; } /******************************************************************************/ /** * Search for and retrieve a downstream DisplayPort device's Extended Display * Identification Data (EDID) extension block of type DisplayID. * * @param InstancePtr is a pointer to the XDptx instance. * @param Data is a pointer to the data buffer to save the DisplayID to. * @param LinkCountTotal is the total DisplayPort links connecting the * DisplayPort TX to the targeted downstream device. * @param RelativeAddress is the relative address from the DisplayPort * source to the targeted DisplayPort device. * * @return * - XST_SUCCESS a DisplayID extension block was found. * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to * read an extension block. * - XST_DEVICE_NOT_FOUND if no RX device is connected. * - XST_FAILURE if no DisplayID extension block was found or some * error occurred in the search. * * @note None. * *******************************************************************************/ u32 XDptx_GetRemoteEdidDispIdExt(XDptx *InstancePtr, u8 *Data, u8 LinkCountTotal, u8 *RelativeAddress) { u32 Status; u8 NumExt; u8 ExtIndex; /* Get the base EDID block. */ Status = XDptx_GetRemoteEdid(InstancePtr, LinkCountTotal, RelativeAddress, Data); if (Status != XST_SUCCESS) { return Status; } NumExt = Data[XDPTX_EDID_EXT_BLOCK_COUNT]; for (ExtIndex = 0; ExtIndex < NumExt; ExtIndex++) { /* Get an EDID extension block. */ Status = XDptx_GetRemoteEdidBlock(InstancePtr, Data, ExtIndex + 1, LinkCountTotal, RelativeAddress); if (Status != XST_SUCCESS) { return Status; } if (XDptx_IsEdidExtBlockDispId(Data)) { /* The current extension block is of type DisplayID. */ return XST_SUCCESS; } } /* All extension blocks have been searched; no DisplayID extension block * exists in sink's EDID structure. */ return XST_FAILURE; } /******************************************************************************/ /** * Given a section tag, search for and retrieve the appropriate section data * block that is part of the specified DisplayID structure. * * @param DisplayIdRaw is a pointer to the DisplayID data. * @param SectionTag is the tag to search for that represents the desired * section data block. * @param DataBlockPtr will be set by this function to point to the * appropriate section data block that is part of the DisplayIdRaw. * * @return * - XST_SUCCESS if the section data block with the specified tag * was found. * - XST_FAILURE otherwise. * * @note The DataBlockPtr argument is modified to point to the entry * in DisplayIdRaw that represents the beginning of the desired * section data block. * *******************************************************************************/ u32 XDptx_GetDispIdDataBlock(u8 *DisplayIdRaw, u8 SectionTag, u8 **DataBlockPtr) { u8 Index; u8 DispIdSize = DisplayIdRaw[XDPTX_DISPID_SIZE]; u8 *DataBlock; /* Search for a section data block matching the specified tag. */ for (Index = XDPTX_DISPID_PAYLOAD_START; Index < DispIdSize; Index++) { DataBlock = &DisplayIdRaw[Index]; /* Check if the tag mataches the current section data block. */ if (DataBlock[XDPTX_DISPID_DB_SEC_TAG] == SectionTag) { *DataBlockPtr = DataBlock; return XST_SUCCESS; } if (DataBlock[XDPTX_DISPID_DB_SEC_SIZE] == 0) { /* End of valid section data blocks. */ break; } else { /* Increment the search index to skip the remaining * bytes of the current section data block. */ Index += (XDPTX_DISPID_DB_SEC_SIZE + DataBlock[XDPTX_DISPID_DB_SEC_SIZE]); } } /* The entire DisplayID was searched or the search ended due to data * no longer containing a valid section data block. No section data * block with the specified tag was found. */ return XST_FAILURE; } /******************************************************************************/ /** * Search for and retrieve a downstream DisplayPort device's Tiled Display * Topology (TDT) section data block that is part of the downstream device's * DisplayID structure. The DisplayID structure is part of the Extended Display * Identification Data (EDID) in the form of an extension block. * * @param InstancePtr is a pointer to the XDptx instance. * @param EdidExt is a pointer to the data area that will be filled by the * retrieved DisplayID extension block. * @param LinkCountTotal is the total DisplayPort links connecting the * DisplayPort TX to the targeted downstream device. * @param RelativeAddress is the relative address from the DisplayPort * source to the targeted DisplayPort device. * @param DataBlockPtr will be set by this function to point to the TDT * data block that is part of the EdidExt extension block. * * @return * - XST_SUCCESS a DisplayID extension block was found. * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to * read an extension block. * - XST_DEVICE_NOT_FOUND if no RX device is connected. * - XST_FAILURE if no DisplayID extension block was found or some * error occurred in the search. * * @note The EdidExt will be filled with the DisplayID EDID extension * block and the DataBlockPtr argument is modified to point to the * EdidExt entry representing the TDT section data block. * *******************************************************************************/ u32 XDptx_GetRemoteTiledDisplayDb(XDptx *InstancePtr, u8 *EdidExt, u8 LinkCountTotal, u8 *RelativeAddress, u8 **DataBlockPtr) { u32 Status; u8 *EdidExtDispId; /* Obtain a DisplayID EDID extension block. */ Status = XDptx_GetRemoteEdidDispIdExt(InstancePtr, EdidExt, LinkCountTotal, RelativeAddress); if (Status != XST_SUCCESS) { /* The sink does not have a DisplayID EDID extension block. */ return Status; } /* The first byte of the extension block is the tag. */ EdidExtDispId = &EdidExt[0x01]; /* Obtain the tiled display topology block data from the DisplayId EDID * extension block. */ Status = XDptx_GetDispIdDataBlock(EdidExtDispId, XDPTX_DISPID_TDT_TAG, DataBlockPtr); if (Status != XST_SUCCESS) { /* The sink does not possess a DisplayID EDID data block with * the specified tag. */ return Status; } return XST_SUCCESS; }