/** * * This function is the interrupt handler for the HDMI RX AUX peripheral. * * @param InstancePtr is a pointer to the XV_HdmiRx core instance. * * @return None. * * @note None. * ******************************************************************************/ static void HdmiRx_AuxIntrHandler(XV_HdmiRx *InstancePtr) { u32 Status; u8 Index; /* Read Status register */ Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUX_STA_OFFSET)); /* Check for new packet */ if ((Status) & (XV_HDMIRX_AUX_STA_NEW_MASK)) { // Clear event flag XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUX_STA_OFFSET), (XV_HDMIRX_AUX_STA_NEW_MASK)); /* Set HDMI flag */ InstancePtr->Stream.IsHdmi = (TRUE); /* Read header word and update AUX header field */ InstancePtr->Aux.Header.Data = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUX_DAT_OFFSET)); for (Index = 0x0; Index < 8; Index++) { /* Read data word and update AUX data field */ InstancePtr->Aux.Data.Data[Index] = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUX_DAT_OFFSET)); } /* Callback */ if (InstancePtr->IsAuxCallbackSet) { InstancePtr->AuxCallback(InstancePtr->AuxRef); } } }
/** * * This function is the interrupt handler for the HDMI RX DDC peripheral. * * @param InstancePtr is a pointer to the XV_HdmiRx core instance. * * @return None. * * @note None. * ******************************************************************************/ static void HdmiRx_DdcIntrHandler(XV_HdmiRx *InstancePtr) { u32 Status; /* Read Status register */ Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_DDC_STA_OFFSET)); /* Check for HDCP write event */ if ((Status) & (XV_HDMIRX_DDC_STA_HDCP_WR_EVT_MASK)) { // Clear event flag XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_DDC_STA_OFFSET), (XV_HDMIRX_DDC_STA_HDCP_WR_EVT_MASK)); /* Callback */ if (InstancePtr->IsHdcpCallbackSet) { InstancePtr->HdcpCallback(InstancePtr->HdcpRef); } } /* Check for HDCP read event */ if ((Status) & (XV_HDMIRX_DDC_STA_HDCP_RD_EVT_MASK)) { // Clear event flag XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_DDC_STA_OFFSET), (XV_HDMIRX_DDC_STA_HDCP_RD_EVT_MASK)); /* Callback */ if (InstancePtr->IsHdcpCallbackSet) { InstancePtr->HdcpCallback(InstancePtr->HdcpRef); } } }
/** * * This function is the interrupt handler for the HDMI RX AUD peripheral. * * @param InstancePtr is a pointer to the XV_HdmiRx core instance. * * @return None. * * @note None. * ******************************************************************************/ static void HdmiRx_AudIntrHandler(XV_HdmiRx *InstancePtr) { u32 Status; // Read Status register Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUD_STA_OFFSET)); // Check for active stream event if ((Status) & (XV_HDMIRX_AUD_STA_ACT_EVT_MASK)) { // Clear event flag XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUD_STA_OFFSET), (XV_HDMIRX_AUD_STA_ACT_EVT_MASK)); InstancePtr->Stream.Audio.Active = (TRUE); } // Check for audio channel event if ((Status) & (XV_HDMIRX_AUD_STA_CH_EVT_MASK)) { // Clear event flag XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUD_STA_OFFSET), (XV_HDMIRX_AUD_STA_CH_EVT_MASK)); // Active channels switch ((Status >> XV_HDMIRX_AUD_STA_AUD_CH_SHIFT) & XV_HDMIRX_AUD_STA_AUD_CH_MASK) { // 8 channels case 3 : InstancePtr->Stream.Audio.Channels = 8; break; // 6 channels case 2 : InstancePtr->Stream.Audio.Channels = 6; break; // 4 channels case 1 : InstancePtr->Stream.Audio.Channels = 4; break; // 2 channels default : InstancePtr->Stream.Audio.Channels = 2; break; } /* Callback */ if (InstancePtr->IsAudCallbackSet) { InstancePtr->AudCallback(InstancePtr->AudRef); } }
/** * * This function is the interrupt handler for the HDMI RX Timing Detector * (TIMDET) peripheral. * * @param InstancePtr is a pointer to the XV_HdmiRx core instance. * * @return None. * * @note None. * ******************************************************************************/ static void HdmiRx_VtdIntrHandler(XV_HdmiRx *InstancePtr) { u32 Data; u32 Status; /* Read Video timing detector Status register */ Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)); /* Check for timing parameters ready event */ if ((Status) & (XV_HDMIRX_VTD_STA_TPR_EVT_MASK)) { // Clear event flag XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET), (XV_HDMIRX_VTD_STA_TPR_EVT_MASK)); // Check if we are in lock state if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_LOCK) { // Read video timing Status = XV_HdmiRx_GetVideoTiming(InstancePtr); if (Status == XST_SUCCESS) { // Enable AXI Stream output XV_HdmiRx_AxisEnable(InstancePtr, (TRUE)); // Set stream status to up InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_UP; // The stream is up // Call stream up callback if (InstancePtr->IsStreamUpCallbackSet) { InstancePtr->StreamUpCallback(InstancePtr->StreamUpRef); } } } // Check if we are in stream up state else if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_UP) { // Read video timing Status = XV_HdmiRx_GetVideoTiming(InstancePtr); if (Status != XST_SUCCESS) { // Set stream status to up InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_LOCK; } } } }
/** * * This function is the interrupt handler for the HDMI RX TMR peripheral. * * @param InstancePtr is a pointer to the XV_HdmiRx core instance. * * @return None. * * @note None. * ******************************************************************************/ static void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr) { u32 Status; /* Read Status register */ Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_TMR_STA_OFFSET)); /* Check for counter event */ if ((Status) & (XV_HDMIRX_TMR_STA_CNT_EVT_MASK)) { // Clear counter event XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_TMR_STA_OFFSET), (XV_HDMIRX_TMR_STA_CNT_EVT_MASK)); // Idle state if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_IDLE) { // The link is stable now // Then the aux and audio peripherals can be enabled XV_HdmiRx_AuxEnable(InstancePtr); XV_HdmiRx_AudioEnable(InstancePtr); // Release HDMI RX reset XV_HdmiRx_Reset(InstancePtr, FALSE); // Enable link XV_HdmiRx_LinkEnable(InstancePtr, (TRUE)); // Set stream status to init InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_INIT; // The stream init // Load timer XV_HdmiRx_TmrStart(InstancePtr, 20000000); // 200 ms @ 100 MHz (one UHD frame is 40 ms, 5 frames) } // Init state else if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_INIT) { // Read video properties XV_HdmiRx_GetVideoProperties(InstancePtr); // Call stream init callback if (InstancePtr->IsStreamInitCallbackSet) { InstancePtr->StreamInitCallback(InstancePtr->StreamInitRef); } } // Armed state else if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_ARM) { // Set VTD threshold XV_HdmiRx_VtdSetThreshold(InstancePtr, 8); // 8 frames /* Enable VTD */ XV_HdmiRx_VtdEnable(InstancePtr); /* Enable interrupt */ XV_HdmiRx_VtdIntrEnable(InstancePtr); // Set stream status to lock InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_LOCK; } } }
/** * * This function is the interrupt handler for the HDMI RX PIO peripheral. * * @param InstancePtr is a pointer to the XV_HdmiRx core instance. * * @return None. * * @note None. * ******************************************************************************/ static void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) { u32 Event; u32 Data; /* Read PIO IN Event register.*/ Event = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_PIO_IN_EVT_OFFSET)); /* Clear event flags */ XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_PIO_IN_EVT_OFFSET), (Event)); /* Read data */ Data = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_PIO_IN_OFFSET)); // Cable detect event has occurred if ((Event) & (XV_HDMIRX_PIO_IN_DET_MASK)) { // Cable is connected if ((Data) & (XV_HDMIRX_PIO_IN_DET_MASK)) { // Set connected flag InstancePtr->Stream.IsConnected = (TRUE); } // Cable is disconnected else { // Clear connected flag InstancePtr->Stream.IsConnected = (FALSE); // Clear SCDC variables XV_HdmiRx_DdcScdcClear(InstancePtr); } // Check if user callback has been registered if (InstancePtr->IsConnectCallbackSet) { InstancePtr->ConnectCallback(InstancePtr->ConnectRef); } } // Link ready event has occurred if ((Event) & (XV_HDMIRX_PIO_IN_LNK_RDY_MASK)) { // Set stream status to idle InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_IDLE; // The stream idle // Load timer XV_HdmiRx_TmrStart(InstancePtr, 1000000); // 10 ms @ 100 MHz } // Video ready event has occurred if ((Event) & (XV_HDMIRX_PIO_IN_VID_RDY_MASK)) { // Ready if ((Data) & (XV_HDMIRX_PIO_IN_VID_RDY_MASK)) { // Check the previous state // The link can only change to up when the previous state was init // Else there was a glitch on the video ready input if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_INIT) { // Enable video XV_HdmiRx_VideoEnable(InstancePtr, (TRUE)); // Set stream status to arm InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_ARM; // The stream is armed // Load timer XV_HdmiRx_TmrStart(InstancePtr, 20000000); // 200 ms @ 100 MHz (one UHD frame is 40 ms, 5 frames) } } // Stream down else { /* Assert reset */ XV_HdmiRx_Reset(InstancePtr, (TRUE)); /* Clear variables */ XV_HdmiRx_Clear(InstancePtr); // Disable aux and audio peripheral // At this state the link clock is not stable. // Therefore these two peripheral are disabled to prevent any glitches. XV_HdmiRx_AuxDisable(InstancePtr); XV_HdmiRx_AudioDisable(InstancePtr); /* Disable VTD */ XV_HdmiRx_VtdDisable(InstancePtr); // Disable link XV_HdmiRx_LinkEnable(InstancePtr, (FALSE)); // Disable video XV_HdmiRx_VideoEnable(InstancePtr, (FALSE)); // Set stream status to down InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_DOWN; // The stream is down // Call stream down callback if (InstancePtr->IsStreamDownCallbackSet) { InstancePtr->StreamDownCallback(InstancePtr->StreamDownRef); } } } // SCDC Scrambler Enable if ((Event) & (XV_HDMIRX_PIO_IN_SCDC_SCRAMBLER_ENABLE_MASK)) { // Enable scrambler if ((Data) & (XV_HDMIRX_PIO_IN_SCDC_SCRAMBLER_ENABLE_MASK)) { XV_HdmiRx_SetScrambler(InstancePtr, (TRUE)); } // Disable scrambler else { XV_HdmiRx_SetScrambler(InstancePtr, (FALSE)); } } }
/** * * This function is the interrupt handler for the HDMI RX driver. * * This handler reads the pending interrupt from PIO, DDC, TIMDET, AUX, AUD * and LNKSTA peripherals, determines the source of the interrupts, clears the * interrupts and calls callbacks accordingly. * * The application is responsible for connecting this function to the interrupt * system. Application beyond this driver is also responsible for providing * callbacks to handle interrupts and installing the callbacks using * XV_HdmiRx_SetCallback() during initialization phase. An example delivered * with this driver demonstrates how this could be done. * * @param InstancePtr is a pointer to the XV_HdmiRx instance that just * interrupted. * * @return None. * * @note None. * ******************************************************************************/ void XV_HdmiRx_IntrHandler(void *InstancePtr) { u32 Data; XV_HdmiRx *HdmiRxPtr = (XV_HdmiRx *)InstancePtr; /* Verify arguments */ Xil_AssertVoid(HdmiRxPtr != NULL); Xil_AssertVoid(HdmiRxPtr->IsReady == XIL_COMPONENT_IS_READY); /* PIO */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_PIO_STA_OFFSET)) & (XV_HDMIRX_PIO_STA_IRQ_MASK); /* Check for IRQ flag set */ if (Data) { /* Jump to PIO handler */ HdmiRx_PioIntrHandler(HdmiRxPtr); } /* Timer */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_TMR_STA_OFFSET)) & (XV_HDMIRX_TMR_STA_IRQ_MASK); /* Check for IRQ flag set */ if (Data) { /* Jump to PIO handler */ HdmiRx_TmrIntrHandler(HdmiRxPtr); } /* Video Timing detector */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)) & (XV_HDMIRX_VTD_STA_IRQ_MASK); /* Check for IRQ flag set */ if (Data) { /* Jump to video timing detector handler */ HdmiRx_VtdIntrHandler(HdmiRxPtr); } /* DDC */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_DDC_STA_OFFSET)) & (XV_HDMIRX_DDC_STA_IRQ_MASK); /* Is the IRQ flag set */ if (Data) { /* Jump to DDC handler */ HdmiRx_DdcIntrHandler(HdmiRxPtr); } /* AUX */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_AUX_STA_OFFSET)) & (XV_HDMIRX_AUX_STA_IRQ_MASK); /* Check for IRQ flag set */ if (Data) { /* Jump to AUX handler */ HdmiRx_AuxIntrHandler(HdmiRxPtr); } /* Audio */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_AUD_STA_OFFSET)) & (XV_HDMIRX_AUD_STA_IRQ_MASK); /* Check for IRQ flag set */ if (Data) { /* Jump to Audio handler */ HdmiRx_AudIntrHandler(HdmiRxPtr); } /* Link status */ Data = XV_HdmiRx_ReadReg(HdmiRxPtr->Config.BaseAddress, (XV_HDMIRX_LNKSTA_STA_OFFSET)) & (XV_HDMIRX_LNKSTA_STA_IRQ_MASK); /* Check for IRQ flag set */ if (Data) { /* Jump to Link Status handler */ HdmiRx_LinkStatusIntrHandler(HdmiRxPtr); } }