xilinx PL测 DP 点屏 /接收(二)–RX

  • Post author:
  • Post category:其他


环境:

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);


}




版权声明:本文为weixin_36590806原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。