/** * * This function checks if there is a connected RX device to DisplayPort TX * Subsystem. * * @param InstancePtr is a pointer to the XDpTxSs core instance. * * @return * - TRUE if there is a connection. * - FALSE if there is no connection. * * @note None. * ******************************************************************************/ u32 XDpTxSs_IsConnected(XDpTxSs *InstancePtr) { u32 Status; /* Verify argument.*/ Xil_AssertNonvoid(InstancePtr != NULL); /* Check for TX connected */ Status = XDp_TxIsConnected(InstancePtr->DpPtr); return Status; }
/** * This function is the interrupt handler for the XDp driver operating in TX * mode. * * When an interrupt happens, it first detects what kind of interrupt happened, * then decides which callback function to invoke. * * @param InstancePtr is a pointer to the XDp instance. * * @return None. * * @note None. * *******************************************************************************/ static void XDp_TxInterruptHandler(XDp *InstancePtr) { u32 IntrStatus; u8 HpdEventDetected; u8 HpdPulseDetected; u32 HpdDuration; u32 IntrMask; /* Determine what kind of interrupt occurred. * Note: XDP_TX_INTERRUPT_STATUS is an RC (read-clear) register. */ IntrStatus = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_STATUS); IntrStatus &= ~XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK); IntrMask = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK); HpdEventDetected = IntrStatus & XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK; HpdPulseDetected = IntrStatus & XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK; if (HpdEventDetected) { /* Mask interrupts while event handling is taking place. API * will error out in case of a disconnection event anyway. */ XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK, IntrMask | XDP_TX_INTERRUPT_MASK_HPD_EVENT_MASK); InstancePtr->TxInstance.HpdEventHandler( InstancePtr->TxInstance.HpdEventCallbackRef); } else if (HpdPulseDetected && XDp_TxIsConnected(InstancePtr)) { /* Mask interrupts while event handling is taking place. */ XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK, IntrMask | XDP_TX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK); /* The source device must debounce the incoming HPD signal by * sampling the value at an interval greater than 0.500 ms. An * HPD pulse should be of width 0.5 ms - 1.0 ms. */ HpdDuration = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_HPD_DURATION); if (HpdDuration >= 500) { InstancePtr->TxInstance.HpdPulseHandler( InstancePtr->TxInstance.HpdPulseCallbackRef); } } /* Unmask previously masked interrupts once handling is done. */ XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK, IntrMask); }
/** * This function is called when a Hot-Plug-Detect (HPD) event is received by the * DisplayPort TX core. The XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK bit of the * core's XDP_TX_INTERRUPT_STATUS register indicates that an HPD event has * occurred. * * @param InstancePtr is a pointer to the XDp instance. * * @return None. * * @note Use the XDp_TxSetHpdEventHandler driver function to set this * function as the handler for HPD pulses. * *******************************************************************************/ static void Dptx_HpdEventHandler(void *InstancePtr) { XDp *XDp_InstancePtr = (XDp *)InstancePtr; if (XDp_TxIsConnected(XDp_InstancePtr)) { xil_printf("+===> HPD connection event detected.\n"); Dptx_Run(XDp_InstancePtr); } else { xil_printf("+===> HPD disconnection event detected.\n\n"); } }
/** * * This function starts the DisplayPort Transmitter Subsystem including all * sub-cores. * * @param InstancePtr is a pointer to the XDpTxSs core instance. * * @return * - XST_SUCCESS, if DP TX Subsystem and its included sub-cores * configured successfully. * - XST_FAILURE, otherwise. * * @note None. * ******************************************************************************/ u32 XDpTxSs_Start(XDpTxSs *InstancePtr) { u32 Status; u32 Index; u8 SinkTotal; #if (XPAR_XDUALSPLITTER_NUM_INSTANCES > 0) u8 VertSplit; #endif /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((InstancePtr->UsrOpt.MstSupport == 0) || (InstancePtr->UsrOpt.MstSupport == 1)); /* Check for downstream device connected */ if (!XDp_TxIsConnected(InstancePtr->DpPtr)) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: RX device " "is not connected!\n\r"); return XST_FAILURE; } /* Check RX device is MST capable */ Status = XDp_TxMstCapable(InstancePtr->DpPtr); if ((Status == XST_SUCCESS) && (InstancePtr->Config.MstSupport)) { if (InstancePtr->UsrOpt.MstSupport < InstancePtr->Config.MstSupport) { /* Enable SST mode when RX is MST */ InstancePtr->UsrOpt.MstSupport = 0; /* set maximum number of streams to one */ InstancePtr->UsrOpt.NumOfStreams = 1; xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: Setting " "to SST even though RX device is with MST " "capable!\n\r"); } else { /* Enable MST mode */ InstancePtr->UsrOpt.MstSupport = InstancePtr->Config.MstSupport; /* Restore maximum number of supported streams */ InstancePtr->UsrOpt.NumOfStreams = InstancePtr->Config.NumMstStreams; xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: RX device " "is with MST capable!\n\r"); } } else { /* Enable SST mode */ InstancePtr->UsrOpt.MstSupport = 0; /* set maximum number of streams to one */ InstancePtr->UsrOpt.NumOfStreams = 1; xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: RX device " "is with SST capable. OR Design supports only SST " "mode.\n\r"); } /* Start DisplayPort sub-core configuration */ Status = XDpTxSs_DpTxStart(InstancePtr->DpPtr, InstancePtr->UsrOpt.MstSupport, InstancePtr->UsrOpt.Bpc, InstancePtr->UsrOpt.VmId); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: DP Start failed " "in %s!\n\r", InstancePtr->UsrOpt.MstSupport?"MST":"SST"); return Status; } /* Align video mode being set in DisplayPort */ InstancePtr->UsrOpt.VmId = InstancePtr->DpPtr->TxInstance.MsaConfig[0].Vtm.VmId; /* Set number of stream to number of sinks found. Make sure that sink * total does not exceed total number supported streams in by Subsystem * configuration. */ if (InstancePtr->UsrOpt.MstSupport) { SinkTotal = InstancePtr->DpPtr->TxInstance.Topology.SinkTotal; InstancePtr->UsrOpt.NumOfStreams = (SinkTotal > InstancePtr->UsrOpt.NumOfStreams)? InstancePtr->UsrOpt.NumOfStreams:SinkTotal; } #if (XPAR_XDUALSPLITTER_NUM_INSTANCES > 0) if (InstancePtr->DsPtr) { /* Check video mode and MST support */ if ((InstancePtr->UsrOpt.VmId == XVIDC_VM_UHD2_60_P) && (InstancePtr->UsrOpt.MstSupport)) { /* Vertical split mode */ VertSplit = (TRUE); } else { /* Bypass mode */ VertSplit = (FALSE); } /* Setup Dual Splitter in either bypass/vertical split mode */ Status = XDpTxSs_DsSetup(InstancePtr->DsPtr, VertSplit, &InstancePtr->DpPtr->TxInstance.MsaConfig[0]); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: DS start " "failed!\n\r"); return Status; } } #endif /* Setup VTC */ for (Index = 0; Index < InstancePtr->UsrOpt.NumOfStreams; Index++) { if (InstancePtr->VtcPtr[Index]) { Status = XDpTxSs_VtcSetup(InstancePtr->VtcPtr[Index], &InstancePtr->DpPtr->TxInstance.MsaConfig[Index]); if (Status != XST_SUCCESS) { xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: " "VTC%d setup failed!\n\r", Index); return Status; } } } return XST_SUCCESS; }