embeddedsw/XilinxProcessorIPLib/drivers/dprxss/src/xdprxss.c
Shadul Shaikh b505655fe0 dprxss: Instruct RX to generate HPD interrupt
This patch generates a Hot-Plug Detect (HPD) interrupt whenever RX cable
disconnect/unplug interrupt detected.

Signed-off-by: Shadul Shaikh <shaduls@xilinx.com>
Acked-by: Andrei-Liviu Simion <andreis@xilinx.com>
2015-10-17 00:24:28 +05:30

1311 lines
39 KiB
C

/******************************************************************************
*
* Copyright (C) 2015 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
* XILINX 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 xdprxss.c
* @addtogroup dprxss_v2_0
* @{
*
* This is the main file for Xilinx DisplayPort Receiver Subsystem driver.
* This file contains a minimal set of functions for the XDpRxSs driver that
* allow access to all of the DisplayPort Receiver Subsystem core's
* functionality. Please see xdprxss.h for more details of the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ---- --- -------- ----------------------------------------------------------
* 1.00 sha 05/18/15 Initial release.
* 2.00 sha 10/05/15 Added HDCP and Timer Counter support.
* Protected HDCP under macro number of instances.
* 2.00 sha 10/15/15 Generate a HPD interrupt whenever RX cable
* disconnect/unplug interrupt is detected.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xdprxss.h"
#include "xvidc_dp159.h"
#include "string.h"
#include "xdebug.h"
/************************** Constant Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
/**************************** Type Definitions *******************************/
/* Subsystem sub-core's structure includes instances of each sub-core */
typedef struct {
XDp DpInst;
XIic IicInst;
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
XHdcp1x Hdcp1xInst;
XTmrCtr TmrCtrInst;
#endif
} XDpRxSs_SubCores;
/************************** Function Prototypes ******************************/
static void DpRxSs_GetIncludedSubCores(XDpRxSs *InstancePtr);
static void DpRxSs_PopulateDpRxPorts(XDpRxSs *InstancePtr);
static void StubTp1Callback(void *InstancePtr);
static void StubTp2Callback(void *InstancePtr);
static void StubUnplugCallback(void *InstancePtr);
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
static void DpRxSs_TimeOutCallback(void *InstancePtr, u8 TmrCtrNumber);
#endif
/************************** Variable Definitions *****************************/
/* A generic EDID structure. */
u8 GenEdid[128] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x61, 0x2c, 0x01, 0x00, 0x78, 0x56, 0x34, 0x12,
0x01, 0x18, 0x01, 0x04, 0xa0, 0x2f, 0x1e, 0x78,
0x00, 0xee, 0x95, 0xa3, 0x54, 0x4c, 0x99, 0x26,
0x0f, 0x50, 0x54, 0x21, 0x08, 0x00, 0x71, 0x4f,
0x81, 0x80, 0xb3, 0x00, 0xd1, 0xc0, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a,
0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1e,
0x00, 0x00, 0x00, 0xff, 0x00, 0x58, 0x49, 0x4c,
0x44, 0x50, 0x53, 0x49, 0x4e, 0x4b, 0x0a, 0x20,
0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x58,
0x49, 0x4c, 0x20, 0x44, 0x50, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd,
0x00, 0x38, 0x3c, 0x1e, 0x53, 0x10, 0x00, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x39
};
/* A generic DPCD structure. */
u8 GenDpcd[] = {
0x12, 0x0a, 0x84, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02
};
/* DisplayPort RX subcores instance */
XDpRxSs_SubCores DpRxSsSubCores;
/************************** Function Definitions *****************************/
/*****************************************************************************/
/**
*
* This function initializes the DisplayPort Receiver Subsystem core. This
* function must be called prior to using the core. Initialization of the core
* includes setting up the instance data and ensuring the hardware is in a
* quiescent state.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param CfgPtr points to the configuration structure associated with
* the DisplayPort RX Subsystem core.
* @param EffectiveAddr is the base address of the device. If address
* translation is being used, then this parameter must reflect the
* virtual base address. Otherwise, the physical address should be
* used.
*
* @return
* - XST_DEVICE_NOT_FOUND if sub-core not found.
* - XST_FAILURE if sub-core initialization failed.
* - XST_SUCCESS if XDpRxSs_CfgInitialize successful.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_CfgInitialize(XDpRxSs *InstancePtr, XDpRxSs_Config *CfgPtr,
u32 EffectiveAddr)
{
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
XHdcp1x_Config Hdcp1xConfig;
#endif
XIic_Config IicConfig;
XDp_Config DpConfig;
u32 Status;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(CfgPtr != NULL);
Xil_AssertNonvoid(EffectiveAddr != (u32)0x0);
/* Setup the instance */
(void)memset((void *)InstancePtr, 0, sizeof(XDpRxSs));
(void)memcpy((void *)&(InstancePtr->Config), (const void *)CfgPtr,
sizeof(XDpRxSs_Config));
InstancePtr->Config.BaseAddress = EffectiveAddr;
/* Get included sub-cores in the DisplayPort RX Subsystem */
DpRxSs_GetIncludedSubCores(InstancePtr);
/* Check for IIC availability */
if (InstancePtr->IicPtr) {
xdbg_printf((XDBG_DEBUG_GENERAL),"SS INFO: Initializing "
"IIC IP\n\r");
/* Calculate absolute base address of IIC sub-core */
InstancePtr->Config.IicSubCore.IicConfig.BaseAddress +=
InstancePtr->Config.BaseAddress;
/* Copy IIC config into local IIC config */
(void)memcpy((void *)&(IicConfig),
(const void *)&CfgPtr->IicSubCore.IicConfig,
sizeof(IicConfig));
/* IIC config initialize */
IicConfig.BaseAddress += InstancePtr->Config.BaseAddress;
Status = XIic_CfgInitialize(InstancePtr->IicPtr, &IicConfig,
IicConfig.BaseAddress);
if ((Status != XST_SUCCESS) && (Status !=
XST_DEVICE_IS_STARTED)) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:: IIC "
"initialization failed!\n\r");
return XST_FAILURE;
}
/* Reset DP159 */
XVidC_Dp159Reset(InstancePtr->IicPtr, TRUE);
/* IIC initialization for dynamic functionality */
Status = XIic_DynamicInitialize(InstancePtr->IicPtr);
if (Status != XST_SUCCESS) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:: IIC "
"dynamic initialization failed!\n\r");
return XST_FAILURE;
}
}
/* Check for DisplayPort availability */
if (InstancePtr->DpPtr) {
xdbg_printf((XDBG_DEBUG_GENERAL),"SS INFO: Initializing "
"DisplayPort Receiver IP\n\r");
/* Assign number of streams to one when MST is not enabled */
if (InstancePtr->Config.MstSupport) {
InstancePtr->UsrOpt.NumOfStreams =
InstancePtr->Config.NumMstStreams;
}
else {
InstancePtr->Config.DpSubCore.DpConfig.NumMstStreams =
1;
InstancePtr->UsrOpt.NumOfStreams = 1;
InstancePtr->Config.NumMstStreams = 1;
}
/* Calculate absolute base address of DP sub-core */
InstancePtr->Config.DpSubCore.DpConfig.BaseAddr +=
InstancePtr->Config.BaseAddress;
/* Copy DP config into local DP config */
(void)memcpy((void *)&(DpConfig),
(const void *)&CfgPtr->DpSubCore.DpConfig,
sizeof(XDp_Config));
/* DisplayPort config initialize */
DpConfig.BaseAddr += InstancePtr->Config.BaseAddress;
XDp_CfgInitialize(InstancePtr->DpPtr, &DpConfig,
DpConfig.BaseAddr);
/* Set maximum link rate for the first time */
XDp_RxSetLinkRate(InstancePtr->DpPtr,
InstancePtr->DpPtr->Config.MaxLinkRate);
/* Set maximum lane count for the first time */
XDp_RxSetLaneCount(InstancePtr->DpPtr,
InstancePtr->Config.MaxLaneCount);
/* Bring DP159 out of reset */
XVidC_Dp159Reset(InstancePtr->IicPtr, FALSE);
/* Wait for us */
XDp_WaitUs(InstancePtr->DpPtr, 1000);
/* Initialize DP159 */
XVidC_Dp159Initialize(InstancePtr->IicPtr);
/* Wait for us */
XDp_WaitUs(InstancePtr->DpPtr, 1000);
/* Initialize default training pattern callbacks in DP RX
* Subsystem
*/
XDp_RxSetIntrTp1Handler(InstancePtr->DpPtr, StubTp1Callback,
(void *)InstancePtr);
XDp_RxSetIntrTp2Handler(InstancePtr->DpPtr, StubTp2Callback,
(void *)InstancePtr);
XDp_RxSetIntrTp3Handler(InstancePtr->DpPtr, StubTp2Callback,
(void *)InstancePtr);
XDp_RxSetIntrUnplugHandler(InstancePtr->DpPtr,
StubUnplugCallback, (void *)InstancePtr);
/* Initialize configurable parameters */
InstancePtr->UsrOpt.Bpc = InstancePtr->Config.MaxBpc;
InstancePtr->UsrOpt.LaneCount =
InstancePtr->Config.MaxLaneCount;
InstancePtr->UsrOpt.LinkRate =
InstancePtr->DpPtr->Config.MaxLinkRate;
InstancePtr->UsrOpt.MstSupport =
InstancePtr->Config.MstSupport;
/* Populate the RX core's ports with default values */
DpRxSs_PopulateDpRxPorts(InstancePtr);
}
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
/* Check for Timer Counter availability */
if (InstancePtr->TmrCtrPtr != NULL) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: Initializing Timer "
"Counter IP \n\r");
/* Calculate absolute base address of Timer Counter sub-core */
InstancePtr->Config.TmrCtrSubCore.TmrCtrConfig.BaseAddress +=
InstancePtr->Config.BaseAddress;
/* Timer Counter config initialize */
Status = XTmrCtr_Initialize(InstancePtr->TmrCtrPtr,
InstancePtr->Config.TmrCtrSubCore.TmrCtrConfig.DeviceId);
if (Status != XST_SUCCESS) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:: Timer "
"Counter initialization failed\n\r");
return XST_FAILURE;
}
/* Calculate absolute base address of Timer Counter sub-core */
InstancePtr->TmrCtrPtr->Config.BaseAddress +=
InstancePtr->Config.BaseAddress;
InstancePtr->TmrCtrPtr->BaseAddress +=
InstancePtr->Config.BaseAddress;
/* Configure the callback */
XTmrCtr_SetHandler(InstancePtr->TmrCtrPtr,
(XTmrCtr_Handler)DpRxSs_TimeOutCallback,
InstancePtr);
/* Enable the specified options for Timer Counter zero */
XTmrCtr_SetOptions (InstancePtr->TmrCtrPtr, 0,
XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION);
/* Set the reset value to Timer Counter zero */
XTmrCtr_SetResetValue (InstancePtr->TmrCtrPtr, 0,
XDPRXSS_TMRCTR_RST_VAL);
}
/* Check for HDCP availability */
if ((InstancePtr->Hdcp1xPtr != NULL) &&
(InstancePtr->Config.HdcpEnable)) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: Initializing HDCP IP "
"\n\r");
/* Calculate absolute base address of HDCP sub-core */
InstancePtr->Config.Hdcp1xSubCore.Hdcp1xConfig.BaseAddress +=
InstancePtr->Config.BaseAddress;
(void)memcpy((void *)&(Hdcp1xConfig),
(const void *)&CfgPtr->Hdcp1xSubCore.Hdcp1xConfig,
sizeof(XHdcp1x_Config));
/* HDCP config initialize */
Hdcp1xConfig.BaseAddress += InstancePtr->Config.BaseAddress;
Status = XHdcp1x_CfgInitialize(InstancePtr->Hdcp1xPtr,
&Hdcp1xConfig, (void *)InstancePtr->DpPtr,
Hdcp1xConfig.BaseAddress);
if (Status != XST_SUCCESS) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:: HDCP "
"initialization failed\n\r");
return XST_FAILURE;
}
/* Set key selection value for RX */
XHdcp1x_SetKeySelect(InstancePtr->Hdcp1xPtr, 0x1);
}
#endif
/* Set the flag to indicate the subsystem is ready */
InstancePtr->IsReady = (u32)(XIL_COMPONENT_IS_READY);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function resets the DisplayPort Receiver Subsystem including all
* sub-cores.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note IIC needs to be reinitialized after reset.
*
******************************************************************************/
void XDpRxSs_Reset(XDpRxSs *InstancePtr)
{
/* Verify argument. */
Xil_AssertVoid(InstancePtr != NULL);
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
/* Reset HDCP interface */
if ((InstancePtr->Hdcp1xPtr) && (InstancePtr->Config.HdcpEnable)) {
XHdcp1x_Reset(InstancePtr->Hdcp1xPtr);
}
/* Reset Timer Counter zero */
if (InstancePtr->TmrCtrPtr) {
XTmrCtr_Reset(InstancePtr->TmrCtrPtr, 0);
}
#endif
/* Reset the video and AUX logic from DP RX */
XDpRxSs_WriteReg(InstancePtr->DpPtr->Config.BaseAddr,
XDP_RX_SOFT_RESET, XDP_RX_SOFT_RESET_VIDEO_MASK |
XDP_RX_SOFT_RESET_AUX_MASK);
/* Reset the IIC core */
XIic_Reset(InstancePtr->IicPtr);
}
/*****************************************************************************/
/**
*
* This function starts the DisplayPort Receiver Subsystem including all
* sub-cores.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS, if DP RX Subsystem and its included sub-cores
* configured successfully.
* - XST_FAILURE, otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_Start(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid((InstancePtr->UsrOpt.MstSupport == 0) ||
(InstancePtr->UsrOpt.MstSupport == 1));
/* Reinitialize DP */
Status = XDp_Initialize(InstancePtr->DpPtr);
if (Status != (XST_SUCCESS)) {
xdbg_printf((XDBG_DEBUG_GENERAL),"SS ERR::DP RX "
"start failed!\n\r");
Status = XST_FAILURE;
}
return Status;
}
/*****************************************************************************/
/**
*
* This function sets the data rate to be used by the DisplayPort RX Subsystem
* core.
*
* @param InstancePtr is a pointer to the XDpRxSs instance.
* @param LinkRate is the rate at which link needs to be driven.
* - XDPRXSS_LINK_BW_SET_162GBPS = 0x06(for a 1.62 Gbps data rate)
* - XDPRXSS_LINK_BW_SET_270GBPS = 0x0A(for a 2.70 Gbps data rate)
* - XDPRXSS_LINK_BW_SET_540GBPS = 0x14(for a 5.40 Gbps data rate)
*
* @return
* - XST_SUCCESS if setting the new lane rate was successful.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_SetLinkRate(XDpRxSs *InstancePtr, u8 LinkRate)
{
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid((LinkRate == (XDPRXSS_LINK_BW_SET_162GBPS)) ||
(LinkRate == (XDPRXSS_LINK_BW_SET_270GBPS)) ||
(LinkRate == (XDPRXSS_LINK_BW_SET_540GBPS)));
/* Check for maximum supported link rate */
if (LinkRate > InstancePtr->DpPtr->Config.MaxLinkRate) {
xdbg_printf((XDBG_DEBUG_GENERAL),"SS info: This link rate is "
"not supported by Source/Sink.\n\rMax Supported link "
"rate is 0x%x.\n\rSetting maximum supported link "
"rate.\n\r", InstancePtr->DpPtr->Config.MaxLinkRate);
LinkRate = InstancePtr->DpPtr->Config.MaxLinkRate;
}
/* Set link rate */
XDp_RxSetLinkRate(InstancePtr->DpPtr, LinkRate);
InstancePtr->UsrOpt.LinkRate = LinkRate;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function sets the number of lanes to be used by DisplayPort RX Subsystem
* core.
*
* @param InstancePtr is a pointer to the XDpRxSs instance.
* @param LaneCount is the number of lanes to be used.
* - 1 = XDPRXSS_LANE_COUNT_SET_1
* - 2 = XDPRXSS_LANE_COUNT_SET_2
* - 4 = XDPRXSS_LANE_COUNT_SET_4
* @return
* - XST_SUCCESS if setting the new lane count was successful.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_SetLaneCount(XDpRxSs *InstancePtr, u8 LaneCount)
{
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid((LaneCount == (XDPRXSS_LANE_COUNT_SET_1)) ||
(LaneCount == (XDPRXSS_LANE_COUNT_SET_2)) ||
(LaneCount == (XDPRXSS_LANE_COUNT_SET_4)));
/* Check for maximum supported lane count */
if (LaneCount > InstancePtr->DpPtr->Config.MaxLaneCount) {
xdbg_printf((XDBG_DEBUG_GENERAL),"SS info: This lane count is "
"not supported by Source/Sink.\n\rMax Supported lane "
"count is 0x%x.\n\rSetting maximum supported lane "
"count.\n\r", InstancePtr->DpPtr->Config.MaxLaneCount);
LaneCount = InstancePtr->DpPtr->Config.MaxLaneCount;
}
/* Set lane count */
XDp_RxSetLaneCount(InstancePtr->DpPtr, LaneCount);
InstancePtr->UsrOpt.LaneCount = LaneCount;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function allows the user to select number of ports to be exposed when
* replying to a LINK_ADDRESS sideband message and hides rest of the ports.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param Port specifies the number of ports to be exposed within the
* range 1 to 4.
*
* @return
* - XST_SUCCESS, if ports exposed successfully.
* - XST_FAILURE, if exposing ports which are already exposed or
* ports are exceeding total number of stream supported by the
* system.
*
* @note Number of ports are equal to number of streams.
*
******************************************************************************/
u32 XDpRxSs_ExposePort(XDpRxSs *InstancePtr, u8 Port)
{
u32 Status;
u8 PortIndex;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Port > 0x0);
if (Port == InstancePtr->UsrOpt.NumOfStreams) {
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Subsystem is "
"already in %s mode with port[s] %d.\n\r",
InstancePtr->UsrOpt.MstSupport? "MST": "SST",
Port);
Status = XST_FAILURE;
}
/* Check for stream[s] less than supported stream[s] */
else if (Port < InstancePtr->Config.NumMstStreams) {
/* Expose each port */
for (PortIndex = 0; PortIndex < Port; PortIndex++) {
/* Expose the ports configured above. Used when
* replying to a LINK_ADDRESS request. Make sure that
* the number of downstream ports matches the number
* exposed, otherwise the LINK_ADDRESS reply will be
* incorrect
*/
XDp_RxMstExposePort(InstancePtr->DpPtr,
PortIndex + 1, 1);
}
/* Set number of ports/stream[s] are exposed */
InstancePtr->UsrOpt.NumOfStreams = Port;
/* Hide remaining ports */
for (PortIndex = Port;
PortIndex <= InstancePtr->Config.NumMstStreams;
PortIndex++) {
XDp_RxMstExposePort(InstancePtr->DpPtr,
PortIndex + 1, 0);
}
Status = XST_SUCCESS;
}
/* Everything else */
else {
xdbg_printf((XDBG_DEBUG_GENERAL),"SS ERR::Subsystem does not "
"support %s mode with stream[s] %d\n\r",
InstancePtr->UsrOpt.MstSupport? "MST": "SST",
Port);
Status = XST_FAILURE;
}
return Status;
}
/*****************************************************************************/
/**
*
* This function checks if the receiver's DisplayPort Configuration Data (DPCD)
* indicates that the receiver has achieved clock recovery, channel
* equalization, symbol lock, and interlane alignment for all lanes currently
* in use.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS if the RX device has achieved clock recovery,
* channel equalization, symbol lock, and interlane alignment.
* - XST_DEVICE_NOT_FOUND if no RX device is connected.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_CheckLinkStatus(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify argument.*/
Xil_AssertNonvoid(InstancePtr != NULL);
/* Check link status */
Status = XDp_RxCheckLinkStatus(InstancePtr->DpPtr);
return Status;
}
/*****************************************************************************/
/**
*
* This function configures the number of pixels output through the user data
* interface.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param UserPixelWidth is the user pixel width to be configured.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XDpRxSs_SetUserPixelWidth(XDpRxSs *InstancePtr, u8 UserPixelWidth)
{
/* Verify arguments.*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid((UserPixelWidth == 1) || (UserPixelWidth == 2) ||
(UserPixelWidth == 4));
/* Set user pixel width */
XDp_RxSetUserPixelWidth(InstancePtr->DpPtr, UserPixelWidth);
}
/*****************************************************************************/
/**
*
* This function handles incoming sideband messages. It will
* 1) Read the contents of the down request registers,
* 2) Delegate control depending on the request type, and
* 3) Send a down reply.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS if the entire message was sent successfully.
* - XST_DEVICE_NOT_FOUND if no device is connected.
* - XST_ERROR_COUNT_MAX if sending one of the message fragments
* timed out.
* - XST_FAILURE otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_HandleDownReq(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify argument.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Status = XDp_RxHandleDownReq(InstancePtr->DpPtr);
return Status;
}
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
/*****************************************************************************/
/**
*
* This function enables High-Bandwidth Content Protection (HDCP) interface.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS, if HDCP i/f enabled successfully.
* - XST_FAILURE, otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_HdcpEnable(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Enable HDCP interface */
Status = XHdcp1x_Enable(InstancePtr->Hdcp1xPtr);
return Status;
}
/*****************************************************************************/
/**
*
* This function disables High-Bandwidth Content Protection (HDCP) interface.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS, if HDCP i/f disabled successfully.
* - XST_FAILURE, otherwise.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_HdcpDisable(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Enable HDCP interface */
Status = XHdcp1x_Disable(InstancePtr->Hdcp1xPtr);
return Status;
}
/*****************************************************************************/
/**
*
* This function polls the HDCP interface, process events and sets receive
* state machine accordingly.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS, if polling the HDCP interface was successful.
* - XST_FAILURE, if polling the HDCP interface failed.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_Poll(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Poll the HDCP interface */
Status = XHdcp1x_Poll(InstancePtr->Hdcp1xPtr);
return Status;
}
/*****************************************************************************/
/**
*
* This function enables/disables the underlying physical interface.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param PhyState indicates TRUE/FALSE value to enable/disable the
* underlying physical interface.
*
* @return
* - XST_SUCCESS, if the underlying physical interface enabled
* successfully.
* - XST_FAILURE, if the underlying physical interface failed to
* enable.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_SetPhysicalState(XDpRxSs *InstancePtr, u32 PhyState)
{
u32 Status;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid((PhyState == TRUE) || (PhyState == FALSE));
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Enable underlying physical interface */
Status = XHdcp1x_SetPhysicalState(InstancePtr->Hdcp1xPtr, PhyState);
return Status;
}
/*****************************************************************************/
/**
*
* This function sets lane(s) of the HDCP interface.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param Lane is the number of lanes to be used.
* - 1 = XDPRXSS_LANE_COUNT_SET_1
* - 2 = XDPRXSS_LANE_COUNT_SET_2
* - 4 = XDPRXSS_LANE_COUNT_SET_4
*
* @return
* - XST_SUCCESS, if lane(s) into the HDCP i/f set successfully.
* - XST_FAILURE, if failed to set lane(s) into the HDCP i/f.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_SetLane(XDpRxSs *InstancePtr, u32 Lane)
{
u32 Status;
/* Verify arguments. */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
Xil_AssertNonvoid((Lane == XDPRXSS_LANE_COUNT_SET_1) ||
(Lane == XDPRXSS_LANE_COUNT_SET_2) ||
(Lane == XDPRXSS_LANE_COUNT_SET_4));
/* Set lanes into the HDCP interface */
Status = XHdcp1x_SetLaneCount(InstancePtr->Hdcp1xPtr, Lane);
return Status;
}
/*****************************************************************************/
/**
*
* This function initiates authentication process.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - XST_SUCCESS, if authentication initiated successfully.
* - XST_FAILURE, if authentication initiated failed.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_Authenticate(XDpRxSs *InstancePtr)
{
u32 Status;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Initiate authentication process */
Status = XHdcp1x_Authenticate(InstancePtr->Hdcp1xPtr);
return Status;
}
/*****************************************************************************/
/**
*
* This function checks whether the HDCP Receiver authenticated or not.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - TRUE, if HDCP Receiver is authenticated.
* - FALSE, if the HDCP Receiver not authenticated.
*
* @note None.
*
******************************************************************************/
u32 XDpRxSs_IsAuthenticated(XDpRxSs *InstancePtr)
{
u32 Authenticate;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Check authentication has completed successfully */
Authenticate = XHdcp1x_IsAuthenticated(InstancePtr->Hdcp1xPtr);
return Authenticate;
}
/*****************************************************************************/
/**
*
* This function retrieves the current encryption map.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return
* - The current encryption map.
* - Otherwise zero.
*
* @note None.
*
******************************************************************************/
u64 XDpRxSs_GetEncryption(XDpRxSs *InstancePtr)
{
u64 StreamMap;
/* Verify arguments.*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Get stream map of the stream(s) */
StreamMap = XHdcp1x_GetEncryption(InstancePtr->Hdcp1xPtr);
return StreamMap;
}
/*****************************************************************************/
/**
*
* This function sets the debug printf function.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param PrintfFunc is the printf function.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XDpRxSs_SetDebugPrintf(XDpRxSs *InstancePtr, XDpRxSs_Printf PrintfFunc)
{
/* Verify arguments.*/
Xil_AssertVoid(InstancePtr->Config.HdcpEnable == 0x1);
Xil_AssertVoid(PrintfFunc != NULL);
/* Set debug printf function */
XHdcp1x_SetDebugPrintf(PrintfFunc);
}
/*****************************************************************************/
/**
*
* This function sets the debug log message function.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param LogFunc is the debug logging function.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XDpRxSs_SetDebugLogMsg(XDpRxSs *InstancePtr, XDpRxSs_LogMsg LogFunc)
{
/* Verify arguments.*/
Xil_AssertVoid(InstancePtr->Config.HdcpEnable == 0x1);
Xil_AssertVoid(LogFunc != NULL);
/* Set debug log message function */
XHdcp1x_SetDebugLogMsg(LogFunc);
}
/*****************************************************************************/
/**
*
* This function starts the Timer Counter in count down, interrupt mode.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XDpRxSs_StartTimer(XDpRxSs *InstancePtr)
{
/* Verify arguments.*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Enable the specified options for Timer Counter zero */
XTmrCtr_SetOptions (InstancePtr->TmrCtrPtr, 0,
XTC_DOWN_COUNT_OPTION | XTC_INT_MODE_OPTION);
/* Set the reset value to Timer Counter zero */
XTmrCtr_SetResetValue (InstancePtr->TmrCtrPtr, 0,
XDPRXSS_TMRCTR_RST_VAL);
/* Start Timer Counter 0 in count down mode */
XTmrCtr_Start(InstancePtr->TmrCtrPtr, 0);
}
/*****************************************************************************/
/**
*
* This function stops the Timer Counter.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XDpRxSs_StopTimer(XDpRxSs *InstancePtr)
{
/* Verify arguments.*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->Config.HdcpEnable == 0x1);
/* Stop Timer Counter 0 in count down mode */
XTmrCtr_Stop(InstancePtr->TmrCtrPtr, 0);
/* Reset Timer Counter reset done */
InstancePtr->TmrCtrResetDone = 0;
}
/*****************************************************************************/
/**
*
* This function is the callback called when the Timer Counter reset done with
* specified reset value, assigned during initialization.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
* @param TmrCtrNumber is the number of the timer/counter within the
* Timer Counter core.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void DpRxSs_TimeOutCallback(void *InstancePtr, u8 TmrCtrNumber)
{
XDpRxSs *XDpRxSsPtr = (XDpRxSs *)InstancePtr;
/* Verify arguments.*/
Xil_AssertVoid(XDpRxSsPtr != NULL);
Xil_AssertVoid(TmrCtrNumber < XTC_DEVICE_TIMER_COUNT);
/* Set Timer Counter reset done */
XDpRxSsPtr->TmrCtrResetDone = 1;
}
#endif
/*****************************************************************************/
/**
*
* This function reports list of cores included in DisplayPort RX Subsystem.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void DpRxSs_GetIncludedSubCores(XDpRxSs *InstancePtr)
{
/* Assign instance of DisplayPort core */
InstancePtr->DpPtr = ((InstancePtr->Config.DpSubCore.IsPresent)?
(&DpRxSsSubCores.DpInst): NULL);
/* Assign instance of IIC core */
InstancePtr->IicPtr = ((InstancePtr->Config.DpSubCore.IsPresent)?
(&DpRxSsSubCores.IicInst): NULL);
#if (XPAR_XHDCP_NUM_INSTANCES > 0)
/* Assign instance of HDCP core */
InstancePtr->Hdcp1xPtr =
((InstancePtr->Config.Hdcp1xSubCore.IsPresent)?
(&DpRxSsSubCores.Hdcp1xInst): NULL);
/* Assign instance of Timer Counter core */
InstancePtr->TmrCtrPtr =
((InstancePtr->Config.TmrCtrSubCore.IsPresent)?
(&DpRxSsSubCores.TmrCtrInst): NULL);
#endif
}
/*****************************************************************************/
/**
*
* This function sets up the downstream topology that will be used by the
* DisplayPort RX to respond to down requests coming from the TX.
* - Sinks equal to number of streams (each with its own global unique
* identifier) are exposed to LINK_ADDRESS sideband messages.
* - The extended display identification data (EDID) will be set to a generic
* EDID (GenEdid) for each of the sinks. REMOTE_I2C_READ sideband messages
* on address 0x50 will be replied to with the contents set by
* XDp_RxSetIicMapEntry for 0x50.
* - REMOTE_DPCD_READ sideband messages will be responded to with the contents
* set for the sink using XDp_RxSetDpcdMap. All sinks are given the a generic
* DPCD (GenDpcd).
* - ENUM_PATH_RESOURCES sideband messages will be responded to with the value
* set by XDp_RxMstSetPbn (or 0 if the sink already has a stream allocated to
* it).
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void DpRxSs_PopulateDpRxPorts(XDpRxSs *InstancePtr)
{
XDp_SbMsgLinkAddressReplyPortDetail Port;
u8 PortIndex;
u8 GuidIndex;
u8 StreamIndex;
/* Check for MST */
if (InstancePtr->Config.MstSupport) {
/* Ensure that all ports are not exposed in the link address */
for (PortIndex = 0; PortIndex < XDP_MAX_NPORTS; PortIndex++) {
XDp_RxMstExposePort(InstancePtr->DpPtr, PortIndex, 0);
}
/* Configure the commonality between the downstream sink
* devices
*/
Port.InputPort = 0;
Port.PeerDeviceType = 0x3;
Port.MsgCapStatus = 0;
Port.DpDevPlugStatus = 1;
Port.LegacyDevPlugStatus = 0;
Port.DpcdRev = 0x11;
Port.NumSdpStreams = InstancePtr->Config.MaxNumAudioCh;
Port.NumSdpStreamSinks = InstancePtr->Config.MaxNumAudioCh;
/* Configure the unique port number and GUID for all possible
* downstream sinks
*/
for (PortIndex = 1; PortIndex < XDPRXSS_MAX_NPORTS;
PortIndex++) {
/* Set the GUID to a repeating pattern of the port
* number
*/
for (GuidIndex = 0; GuidIndex < XDPRXSS_GUID_NBYTES;
GuidIndex++) {
Port.Guid[GuidIndex] = PortIndex;
}
/* Port.PortNum is set to the index. */
XDp_RxMstSetPort(InstancePtr->DpPtr, PortIndex, &Port);
}
/* Configure each port with I2C, DPCD and PBN values */
for (StreamIndex = 0;
StreamIndex < InstancePtr->Config.NumMstStreams;
StreamIndex++) {
/* Set I2C maps. */
XDp_RxSetIicMapEntry(InstancePtr->DpPtr,
StreamIndex + 1, 0x50, 128, GenEdid);
/* Set DPCD maps. */
XDp_RxSetDpcdMap(InstancePtr->DpPtr, StreamIndex + 1,
0, sizeof(GenDpcd), GenDpcd);
/* Set available PBN. */
XDp_RxMstSetPbn(InstancePtr->DpPtr, StreamIndex + 1,
2560);
/* Expose the ports configured above. Used when
* replying to a LINK_ADDRESS request. Make sure that
* the number of downstream ports matches the number
* exposed, otherwise the LINK_ADDRESS reply will be
* incorrect
*/
XDp_RxMstExposePort(InstancePtr->DpPtr,
StreamIndex + 1, 1);
}
/* Set up the input port and expose it */
XDp_RxMstSetInputPort(InstancePtr->DpPtr, 0, NULL);
}
}
/*****************************************************************************/
/**
*
* This routine is a stub for the asynchronous training pattern 1 interrupt
* callback. On initialization, training pattern 1 interrupt handler is set to
* this callback. It is considered as an training pattern 1 for this handler
* to be invoked.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void StubTp1Callback(void *InstancePtr)
{
XDpRxSs *DpRxSsPtr = (XDpRxSs *)InstancePtr;
/* Verify argument.*/
Xil_AssertVoid(DpRxSsPtr != NULL);
/* Read link rate */
DpRxSsPtr->UsrOpt.LinkRate =
XDpRxSs_ReadReg(DpRxSsPtr->DpPtr->Config.BaseAddr,
XDPRXSS_DPCD_LINK_BW_SET);
/* Read lane count */
DpRxSsPtr->UsrOpt.LaneCount =
XDpRxSs_ReadReg(DpRxSsPtr->DpPtr->Config.BaseAddr,
XDPRXSS_DPCD_LANE_COUNT_SET);
/* Link bandwidth callback */
if (DpRxSsPtr->LinkBwCallback) {
DpRxSsPtr->LinkBwCallback(DpRxSsPtr->LinkBwRef);
}
/* DP159 config for TP1 */
XVidC_Dp159Config(DpRxSsPtr->IicPtr, XVIDC_DP159_CT_TP1,
DpRxSsPtr->UsrOpt.LinkRate,
DpRxSsPtr->UsrOpt.LaneCount);
XDpRxSs_WriteReg(DpRxSsPtr->DpPtr->Config.BaseAddr,
XDPRXSS_RX_PHY_CONFIG, 0x3800000);
/* PLL reset callback */
if (DpRxSsPtr->PllResetCallback) {
DpRxSsPtr->PllResetCallback(DpRxSsPtr->PllResetRef);
}
/* Set vertical blank */
DpRxSsPtr->VBlankEnable = 1;
/* Enable vertical blank interrupt */
XDp_RxInterruptEnable(DpRxSsPtr->DpPtr, XDPRXSS_INTR_VBLANK_MASK);
/* Set vertical blank count */
DpRxSsPtr->VBlankCount = 0;
}
/*****************************************************************************/
/**
*
* This routine is a stub for the asynchronous training pattern 2 interrupt
* callback. On initialization, training pattern 2 interrupt handler is set to
* this callback. It is considered as an training pattern 2 for this handler
* to be invoked.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void StubTp2Callback(void *InstancePtr)
{
XDpRxSs *DpRxSsPtr = (XDpRxSs *)InstancePtr;
/* Verify argument.*/
Xil_AssertVoid(DpRxSsPtr != NULL);
/* DP159 config for TP2 */
XVidC_Dp159Config(DpRxSsPtr->IicPtr, XVIDC_DP159_CT_TP2,
DpRxSsPtr->UsrOpt.LinkRate,
DpRxSsPtr->UsrOpt.LaneCount);
}
/*****************************************************************************/
/**
*
* This routine is a stub for the asynchronous unplug interrupt callback.
* On initialization, unplug interrupt handler is set to this callback. It is
* considered as an unplug for this handler to be invoked.
*
* @param InstancePtr is a pointer to the XDpRxSs core instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void StubUnplugCallback(void *InstancePtr)
{
XDpRxSs *DpRxSsPtr = (XDpRxSs *)InstancePtr;
/* Verify argument.*/
Xil_AssertVoid(DpRxSsPtr != NULL);
/* DP159 config for TP2 */
XVidC_Dp159Config(DpRxSsPtr->IicPtr, XVIDC_DP159_CT_UNPLUG,
DpRxSsPtr->UsrOpt.LinkRate, DpRxSsPtr->UsrOpt.LaneCount);
/* Disable unplug interrupt so that no unplug event when RX is
* disconnected
*/
XDp_RxInterruptDisable(DpRxSsPtr->DpPtr,
XDP_RX_INTERRUPT_MASK_UNPLUG_MASK);
/* Generate a HPD interrupt. Bring down HPD signal for 750us */
XDp_RxGenerateHpdInterrupt(DpRxSsPtr->DpPtr, 750);
/* Unplug event callback */
if (DpRxSsPtr->UnplugCallback) {
DpRxSsPtr->UnplugCallback(DpRxSsPtr->UnplugRef);
}
}
/** @} */