环境:
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);
}