环境:
a)硬件:官方ZCU106开发板 , tb-fmch-vfmc-dp子卡。
b)软件:vivado2021.1,vitis2021.1,裸机程序。
1、官方例程:
2、DP RX IP :
3、DP RX寄存器:
4、时钟:
5、像素:
Stream模式:
native模式:
6、timming:注意de非连续,每帧hsync个数和h_active一致。
7、vitis代码分析:
a)、iic使用ps测,和官方例程不一样,所以在MCDP6000这个文件夹定义iic:
PS侧iic初始化代码:iIc速率:100K
void ps_iic_init()
{
int Status;
XIicPs_Config *Config;
/* * Initialize the IIC driver so that it's ready to use
* Look up the configuration in the config table,
* then initialize it. */
Config = XIicPs_LookupConfig(XPAR_XIICPS_1_DEVICE_ID);
if (NULL == Config) {
printf("XIicPs_LookupConfig Failed\r\n");
return XST_FAILURE;
}
Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
printf("XIicPs_CfgInitialize Failed\r\n");
return XST_FAILURE;
}
/* * Perform a self-test to ensure that the hardware was built correctly. */
Status = XIicPs_SelfTest(&Iic);
if (Status != XST_SUCCESS) {
printf("XIicPs_SelfTest Failed\r\n");
return XST_FAILURE;
}
/* * Set the IIC serial clock rate. */
XIicPs_SetSClk(&Iic, 100000);
}
DP RX的初始化:
u32 Dprx_init(void)
{
u32 Status;
XDpRxSs_Config *ConfigPtr_rx;
xil_printf("config dp rx \n\r");
ConfigPtr_rx = XDpRxSs_LookupConfig(XDPRXSS_DEVICE_ID);
if (!ConfigPtr_rx) {
xil_printf("DPRXSS Lookup Config failed.\n\r");
return XST_FAILURE;
}
Status = XDpRxSs_CfgInitialize(&DpRxSsInst, ConfigPtr_rx,ConfigPtr_rx->BaseAddress);
if (Status != XST_SUCCESS) {
xil_printf("DPRXSS config initialization failed.\n\r");
return XST_FAILURE;
}
/* Check for SST/MST support */
if (DpRxSsInst.UsrOpt.MstSupport) {
xil_printf("INFO:DPRXSS is MST enabled. DPRXSS can be " "switched to SST/MST\n\r");
} else {
xil_printf("INFO:DPRXSS is SST enabled. DPRXSS works " "only in SST mode.\n\r");
}
xil_printf("Dprx_init end .\n\r");
return XST_SUCCESS;
}
中断初始化:这里RX,TX都有包含
u32 DpSs_SetupIntrSystem(void)
{
u32 Status;
XINTC *IntcInstPtr = &IntcInst;
// Tx side
DpTxSs_SetupIntrSystem();
// Rx side
#ifdef DP_RX_EN
DpRxSs_SetupIntrSystem();
#endif
/* The configuration parameters of the interrupt controller */
XScuGic_Config *IntcConfig;
/* Initialize the interrupt controller
* driver so that it is ready to use. */
IntcConfig = XScuGic_LookupConfig(XINTC_DEVICE_ID);
if (NULL == IntcConfig) {
xil_printf("XINTC_DEVICE_ID XScuGic_LookupConfig failed!\n\r");
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstPtr, IntcConfig, IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
xil_printf("XINTC_DEVICE_ID XScuGic_CfgInitialize failed!\n\r");
return XST_FAILURE;
}
/* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined
* above performs the specific interrupt processing for the device.
* */
#ifdef DP_RX_EN
Status = XScuGic_Connect(IntcInstPtr, XINTC_DPRXSS_DP_INTERRUPT_ID, (Xil_InterruptHandler)XDpRxSs_DpIntrHandler,&DpRxSsInst);
if (Status != XST_SUCCESS) {
xil_printf("ERR: DP RX SS DP interrupt connect failed!\n\r");
return XST_FAILURE;
}
/* Enable the interrupt for the DP device */
XScuGic_Enable(IntcInstPtr, XINTC_DPRXSS_DP_INTERRUPT_ID);
#endif
/* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device
*/
Status = XScuGic_Connect(IntcInstPtr, XINTC_DPTXSS_DP_INTERRUPT_ID, (Xil_InterruptHandler)XDpTxSs_DpIntrHandler,&DpTxSsInst);
if (Status != XST_SUCCESS) {
xil_printf("ERR: DP TX SS DP interrupt connect failed!\r\n");
return XST_FAILURE;
}
/* Enable the interrupt */
XScuGic_Enable(IntcInstPtr, XINTC_DPTXSS_DP_INTERRUPT_ID);
/* Initialize the exception table. */
Xil_ExceptionInit();
/* Register the interrupt controller handler with the exception
* table.*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XINTC_HANDLER,IntcInstPtr);
/* Enable exceptions. */
Xil_ExceptionEnable();
return (XST_SUCCESS);
}
DP RX的中断申请:
u32 DpRxSs_SetupIntrSystem(void)
{
// u32 Status;
// XINTC *IntcInstPtr = &IntcInst;
/* Set callbacks for all the interrupts */
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_PWR_CHG_EVENT, &DpRxSs_PowerChangeHandler, &DpRxSsInst);//2
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_NO_VID_EVENT, &DpRxSs_NoVideoHandler, &DpRxSsInst); //3
// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_VM_CHG_EVENT, &DpRxSs_VmChangeHandler, &DpRxSsInst);
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_VBLANK_EVENT, &DpRxSs_VerticalBlankHandler, &DpRxSsInst);//4
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_TLOST_EVENT, &DpRxSs_TrainingLostHandler, &DpRxSsInst);//5
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_VID_EVENT, &DpRxSs_VideoHandler, &DpRxSsInst); //6
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_TDONE_EVENT, &DpRxSs_TrainingDoneHandler, &DpRxSsInst);//9
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_UNPLUG_EVENT, &DpRxSs_UnplugHandler, &DpRxSsInst); //17
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_LINKBW_EVENT, &DpRxSs_LinkBandwidthHandler, &DpRxSsInst);//18
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_PLL_RESET_EVENT, &DpRxSs_PllResetHandler, &DpRxSsInst); //19
XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_BW_CHG_EVENT, &DpRxSs_BWChangeHandler, &DpRxSsInst); //10
// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_ACCESS_LINK_QUAL_EVENT, &DpRxSs_AccessLinkQualHandler, &DpRxSsInst);
// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_ACCESS_ERROR_COUNTER_EVENT,&DpRxSs_AccessErrorCounterHandler, &DpRxSsInst);
// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_CRC_TEST_EVENT, &DpRxSs_CRCTestEventHandler, &DpRxSsInst);
// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_INFO_PKT_EVENT, &DpRxSs_InfoPacketHandler, &DpRxSsInst);
// XDpRxSs_SetCallBack(&DpRxSsInst, XDPRXSS_HANDLER_DP_EXT_PKT_EVENT, &DpRxSs_ExtPacketHandler, &DpRxSsInst);
/* Set custom timer wait */
XDpRxSs_SetUserTimerHandler(&DpRxSsInst, &CustomWaitUs, &TmrCtr);
return (XST_SUCCESS);
}
PHY的初始化:
u32 DpSs_PhyInit(u16 DeviceId)
{
XVphy_Config *ConfigPtr;
u32 Status;
/* Obtain the device configuration for the DisplayPort RX Subsystem */
ConfigPtr = XVphy_LookupConfig(DeviceId);
if (!ConfigPtr) {
return XST_FAILURE;
}
XVphy_DpInitialize(&VPhyInst, ConfigPtr, 0,
ONBOARD_REF_CLK,
ONBOARD_REF_CLK,
XVPHY_PLL_TYPE_QPLL1,
XVPHY_PLL_TYPE_CPLL,
DP_LINK_RATE);
//set the default vswing and pe for v0po
PLLRefClkSel (&VPhyInst, DP_LINK_RATE);
#if 1
//setting vswing
XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH1, XVPHY_GTHE4_DIFF_SWING_DP_V0P0);
XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH2, XVPHY_GTHE4_DIFF_SWING_DP_V0P0);
XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH3, XVPHY_GTHE4_DIFF_SWING_DP_V0P0);
XVphy_SetTxVoltageSwing(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH4, XVPHY_GTHE4_DIFF_SWING_DP_V0P0);
//setting postcursor
XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH1, XVPHY_GTHE4_PREEMP_DP_L0);
XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH2, XVPHY_GTHE4_PREEMP_DP_L0);
XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH3, XVPHY_GTHE4_PREEMP_DP_L0);
XVphy_SetTxPostCursor(&VPhyInst, 0, XVPHY_CHANNEL_ID_CH4, XVPHY_GTHE4_PREEMP_DP_L0);
#endif
PHY_Two_byte_set (&VPhyInst, SET_RX_TO_2BYTE, SET_TX_TO_2BYTE);//SET_TX_TO_2BYTE
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX,(TRUE));
XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_TX,(TRUE));
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX,(FALSE));
XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_TX,(FALSE));
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX,(TRUE));
XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(TRUE));
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX,(FALSE));
XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(FALSE));
xil_printf("DpSs_PhyInit end .\n\r");
Status = XVphy_ReadReg(XVPHY_BASEADDR, XVPHY_RX_INIT_STATUS_REG);
xil_printf("\n DpSs_PhyInit rx initialization Status 0x28 data = %x \n\r",Status);
Status = XVphy_ReadReg(XVPHY_BASEADDR, XVPHY_PLL_LOCK_STATUS_REG);
xil_printf("\n DpSs_PhyInit rx initialization Status 0x18 data = %x \n\r",Status);
return XST_SUCCESS;
}
PHY的速率设置:
u32 config_phy(int LineRate_init_tx){
u32 Status=0;
// u8 linerate;
// u32 dptx_sts = 0;
switch(LineRate_init_tx){
case XDP_LINK_BW_SET_162GBPS:
Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 0 : 3]);
break;
case XDP_LINK_BW_SET_270GBPS:
Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 1 : 4]);
break;
case XDP_LINK_BW_SET_540GBPS:
Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 2 : 5]);
break;
case XDP_LINK_BW_SET_810GBPS:
Status = PHY_Configuration(&VPhyInst,PHY_User_Config_Table[(is_TX_CPLL) ? 9 : 10]);
break;
}
xil_printf ("config_phy LineRate_init_tx = %x \r\n",LineRate_init_tx);
if (Status != XST_SUCCESS) {
xil_printf ("++++++++++ TX GT configuration encountered a failure +++++++\r\n");
}
return Status;
}
u32 PHY_Configuration(XVphy *InstancePtr,XVphy_User_Config PHY_User_Config_Table)
{
XVphy_PllRefClkSelType QpllRefClkSel;
XVphy_PllRefClkSelType CpllRefClkSel;
XVphy_PllType TxPllSelect;
XVphy_PllType RxPllSelect;
XVphy_ChannelId TxChId;
XVphy_ChannelId RxChId;
u8 QuadId = 0;
u32 Status = XST_FAILURE;
u32 retries = 0;
QpllRefClkSel = PHY_User_Config_Table.QPLLRefClkSrc;
CpllRefClkSel = PHY_User_Config_Table.CPLLRefClkSrc;
TxPllSelect = PHY_User_Config_Table.TxPLL;
RxPllSelect = PHY_User_Config_Table.RxPLL;
TxChId = PHY_User_Config_Table.TxChId;
RxChId = PHY_User_Config_Table.RxChId;
//Set the Ref Clock Frequency
XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, QpllRefClkSel, PHY_User_Config_Table.QPLLRefClkFreqHz);
XVphy_CfgQuadRefClkFreq(InstancePtr, QuadId, CpllRefClkSel, PHY_User_Config_Table.CPLLRefClkFreqHz);
XVphy_CfgLineRate(InstancePtr, QuadId, TxChId, PHY_User_Config_Table.LineRateHz);
// XVphy_CfgLineRate(InstancePtr, QuadId, RxChId, PHY_User_Config_Table.LineRateHz);
// Initialize GT with ref clock and PLL selects
XVphy_PllInitialize(InstancePtr, QuadId, TxChId,QpllRefClkSel, CpllRefClkSel,TxPllSelect, RxPllSelect);
while (Status != XST_SUCCESS) {
Status = XVphy_ClkInitialize(InstancePtr, QuadId, TxChId, XVPHY_DIR_TX);
if (retries > 100) {
retries = 0;
xil_printf ("exhausted\r\n");
break;
}
retries++;
}
// Initialize GT with ref clock and PLL selects
Status = XVphy_ClkInitialize(InstancePtr, QuadId, RxChId, XVPHY_DIR_RX);
XVphy_WriteReg(InstancePtr->Config.BaseAddr,XVPHY_PLL_RESET_REG,(XVPHY_PLL_RESET_CPLL_MASK | XVPHY_PLL_RESET_QPLL1_MASK)); // 0x06
XVphy_WriteReg(InstancePtr->Config.BaseAddr,XVPHY_PLL_RESET_REG, 0x0);
// XVphy_ResetGtPll(InstancePtr, QuadId, RxChId, XVPHY_DIR_RX,(TRUE));
// XVphy_ResetGtPll(InstancePtr, QuadId, RxChId, XVPHY_DIR_RX,(FALSE));
XVphy_ResetGtPll(InstancePtr, QuadId,XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX,(FALSE));
// Status = XVphy_WaitForResetDone(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);
// xil_printf("\n step_phy XVphy_WaitForResetDone Status = %x \n\r",Status);
// Status = XVphy_WaitForPllLock(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA);
// xil_printf("\n step_phy XVphy_WaitForPllLock Status = %x \n\r",Status);
Status = XVphy_WaitForPmaResetDone(InstancePtr, QuadId, TxChId, XVPHY_DIR_TX);
Status += XVphy_WaitForPllLock(InstancePtr, QuadId, TxChId);
Status += XVphy_WaitForResetDone(InstancePtr, QuadId,TxChId, XVPHY_DIR_TX);
if (Status != XST_SUCCESS) {
xil_printf ("++++TX GT config encountered error++++\r\n");
}
return Status;
}
DP RX速率,lane的数目设置:
u32 DPRx_step(void)
{
u32 Status;
u32 tmp_rd;
/* Set Link rate and lane count to maximum */
XDpRxSs_SetLinkRate(&DpRxSsInst, DP_LINK_RATE);
XDpRxSs_SetLaneCount(&DpRxSsInst, DP_LANE_COUNT);
/* Start DPRX Subsystem set */
Status = XDpRxSs_Start(&DpRxSsInst);
if (Status != XST_SUCCESS) {
xil_printf("ERR:DPRX SS start failed\n\r");
return XST_FAILURE;
}
xil_printf("\r\n DPRx_step done.\n\r");
tmp_rd = XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x4);
tmp_rd |= tmp_rd | 0x06000000;
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x4, tmp_rd);
return (XST_SUCCESS);
}
DP RX 的开始training函数:
u32 DpRxSs_Setup(void)
{
u32 ReadVal;
u32 Status;
/*Disable Rx*/
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0);//hpd 拉低
/*Setting BS Idle timeout value to long value*/
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_BS_IDLE_TIME, 0x047868C0);//这个参数,在某些应用上要适当的更改。
/* Load Custom EDID */
LoadEDID();
// XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_INTERRUPT_MASK, 0xFFF87FFD);
/*Disable All Interrupts*/
// XDp_RxInterruptDisable(DpRxSsInst.DpPtr, 0xFFFFFFFF);
xil_printf("RX Link & Lane Capability is set to %x, %x\r\n",
(XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr ,XDP_RX_DPCD_LINK_BW_SET)),
(XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_DPCD_LANE_COUNT_SET)));
/*Enable Training related interrupts*/
XDp_RxInterruptEnable(DpRxSsInst.DpPtr,
XDP_RX_INTERRUPT_MASK_TP1_MASK|XDP_RX_INTERRUPT_MASK_TP2_MASK|
XDP_RX_INTERRUPT_MASK_TP3_MASK|
XDP_RX_INTERRUPT_MASK_POWER_STATE_MASK|
XDP_RX_INTERRUPT_MASK_BW_CHANGE_MASK);
/* Setting AUX Defer Count of Link Status Reads to 8 during Link Training
* 8 Defer counts is chosen to handle worst case time interrupt service
* load (PL system working at 100 MHz) when working with R5
* */
ReadVal = XDp_ReadReg(DpRxSsInst.DpPtr->Config.BaseAddr,XDP_RX_AUX_CLK_DIVIDER);
ReadVal |= ReadVal | (AUX_DEFER_COUNT<<24);
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_AUX_CLK_DIVIDER, ReadVal);
//-------------------------------------------------------------------------------------------------------------------
Status = XVphy_WaitForResetDone(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);
Status = XVphy_WaitForPllLock(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA);
xil_printf("\n step_dp_rx XVphy_WaitForPllLock Status = %x \n\r",Status);
xil_printf("\r\n addr =%x XDP_RX_PHY_STATUS = %x \r\n",XDP_RX_PHY_STATUS,XDp_ReadReg(XDPRXSS_BASEADDR, XDP_RX_PHY_STATUS));
XScuGic_Enable(&IntcInst, XINTC_DPRXSS_DP_INTERRUPT_ID);
//resetting AUX logic. Needed for some Type C based connectors
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x1C, 0x80);
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, 0x1C, 0x0);
//********************************************
if(LINK_TRAINING_DEBUG)
{
/*Updating Vswing Iteration Count*/
RxTrainConfig.ChEqOption = 1;
RxTrainConfig.ClockRecoveryOption = 2;
RxTrainConfig.Itr1Premp = 0;
RxTrainConfig.Itr2Premp = 0;
RxTrainConfig.Itr3Premp = 0;
RxTrainConfig.Itr4Premp = 0;
RxTrainConfig.Itr5Premp = 0;
RxTrainConfig.MinVoltageSwing = 1;
RxTrainConfig.SetPreemp = 1;
RxTrainConfig.SetVswing = 0;
RxTrainConfig.VswingLoopCount = 3;
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_MIN_VOLTAGE_SWING,
RxTrainConfig.MinVoltageSwing |
(RxTrainConfig.ClockRecoveryOption << 2) |
(RxTrainConfig.VswingLoopCount << 4) |
(RxTrainConfig.SetVswing << 8) |
(RxTrainConfig.ChEqOption << 10) |
(RxTrainConfig.SetPreemp << 12) |
(RxTrainConfig.Itr1Premp << 14) |
(RxTrainConfig.Itr2Premp << 16) |
(RxTrainConfig.Itr3Premp << 18) |
(RxTrainConfig.Itr4Premp << 20) |
(RxTrainConfig.Itr5Premp << 22)
);
}
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x1);//此时HPD会拉高,开始training
xil_printf("\r\n DpRxSs_Setup done.\n\r");
return XST_SUCCESS;
}
DP RX中断说明:
void DpRxSs_VerticalBlankHandler(void *InstancePtr) //检测到v_blank,当检测到200个就表示接收到视频
{
// xil_printf("\r\n 4 \r\n");
DpRxSsInst.VBlankCount++;
dp_rx_ok =0;
video_cnt =0;
if(DpRxSsInst.VBlankCount==200){
XDp_RxInterruptDisable(DpRxSsInst.DpPtr, XDP_RX_INTERRUPT_MASK_VBLANK_MASK);
DpRxSsInst.VBlankCount=0;
XDp_RxDtgDis(DpRxSsInst.DpPtr);
XDp_RxDtgEn(DpRxSsInst.DpPtr);
XDp_RxSetLineReset(DpRxSsInst.DpPtr,1);
XDp_RxSetUserPixelWidth(DpRxSsInst.DpPtr,0x04);
xil_printf("\r\n 4 VBlankCount=200 \r\n");
video_flag = 1;
}
else if(DpRxSsInst.VBlankCount==80)
{
video_flag =0;
xil_printf("\r\n 4 :VBlankCount= 80 \r\n");
}
else if(DpRxSsInst.VBlankCount==20)
{
video_flag =0;
xil_printf("\r\n 4 :VBlankCount= 20 \r\n");
XDp_RxInterruptEnable(DpRxSsInst.DpPtr,0x80000000);
}
}
void DpRxSs_TrainingLostHandler(void *InstancePtr)
{
xil_printf("\r\n 5 \r\n");
XDp_RxGenerateHpdInterrupt(DpRxSsInst.DpPtr, 750);
XDpRxSs_AudioDisable(&DpRxSsInst);
sink_power_down(); // close dp tx
vdma_stop(); // close vdma write
video_flag =0;
dp_rx_ok=0;
dp_rx_lost=1;
}
void DpRxSs_VideoHandler(void *InstancePtr) //此中断,在检测到不同的msa会进入此中断,如果一直在进入此中断,表示training ok,但是msa的数据异常,且在变化
{
xil_printf("\r\n 6 \r\n");
video_cnt++;
if((video_cnt==1)|(video_cnt==2))
dp_rx_ok = 1;
else
dp_rx_ok =0;
if(video_cnt==8)
{
// XDp_RxGenerateHpdInterrupt(DpRxSsInst.DpPtr, 750);
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0);
usleep(250000);
XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x1);
}
if(0)//video_flag
{
xil_printf("\r\n 6 \r\n");
dp_rx_ok =1;
}
}
void DpRxSs_UnplugHandler(void *InstancePtr)
{
xil_printf("\r\n 17 \r\n");
video_flag =0;
/*Enable Training related interrupts*/
XDp_RxInterruptDisable(DpRxSsInst.DpPtr, XDP_RX_INTERRUPT_MASK_ALL_MASK);
// XDp_WriteReg(DpRxSsInst.DpPtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0);
XDp_RxInterruptEnable(DpRxSsInst.DpPtr,
XDP_RX_INTERRUPT_MASK_TP1_MASK |
XDP_RX_INTERRUPT_MASK_TP2_MASK |
XDP_RX_INTERRUPT_MASK_TP3_MASK|
XDP_RX_INTERRUPT_MASK_POWER_STATE_MASK|
XDP_RX_INTERRUPT_MASK_CRC_TEST_MASK|
XDP_RX_INTERRUPT_MASK_BW_CHANGE_MASK);
XDp_RxGenerateHpdInterrupt(DpRxSsInst.DpPtr, 5000);
}
void DpRxSs_LinkBandwidthHandler(void *InstancePtr) // 根据 tx发送的 速率,进行更改phy的速率
{
u32 Status;
// xil_printf("\r\n 18 \r\n");
/*Program Video PHY to requested line rate*/
PLLRefClkSel (&VPhyInst, DpRxSsInst.UsrOpt.LinkRate);
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA,XVPHY_DIR_RX,(TRUE));
XVphy_PllInitialize(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, ONBOARD_REF_CLK, ONBOARD_REF_CLK,XVPHY_PLL_TYPE_QPLL1, XVPHY_PLL_TYPE_CPLL);
Status = XVphy_ClkInitialize(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);
if(Status != XST_SUCCESS)
xil_printf("XVphy_ClkInitialize failed\r\n");
}
void DpRxSs_PllResetHandler(void *InstancePtr) //在phy的速率更改后,重新复位。
{
// xil_printf("\r\n 19 \r\n");
// u32 ReadVal;
/* Issue resets to Video PHY - This API
* called after line rate is programmed */
XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(TRUE));
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX,(TRUE));
XVphy_ResetGtPll(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, (FALSE));
XVphy_BufgGtReset(&VPhyInst, XVPHY_DIR_RX,(FALSE));
XVphy_WaitForResetDone(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX);
XVphy_WaitForPllLock(&VPhyInst, 0, XVPHY_CHANNEL_ID_CHA);
/*Enable all interrupts */
XDp_RxInterruptEnable(DpRxSsInst.DpPtr, XDP_RX_INTERRUPT_MASK_ALL_MASK);
}