📄 ipu_base.cpp
字号:
{
phyAddr.QuadPart = CSP_BASE_REG_PA_IPU;
// Map peripheral physical address to virtual address
g_pIPU = (PCSP_IPU_REGS) MmMapIoSpace(phyAddr, sizeof(CSP_IPU_REGS),
FALSE);
// Check if virtual mapping failed
if (g_pIPU == NULL)
{
DEBUGMSG(ZONE_ERROR,
(_T("Init: MmMapIoSpace failed!\r\n")));
goto cleanUp;
}
}
rc = TRUE;
cleanUp:
// If initialization failed, be sure to clean up
if (!rc) IpuDealloc();
IPU_FUNCTION_EXIT();
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: PrpIpuDealloc
//
// This function deallocates the data structures required for interaction
// with the IPU hardware.
//
// Parameters:
// None.
//
// Returns:
// Returns TRUE.
//
//-----------------------------------------------------------------------------
static void IpuDealloc(void)
{
IPU_FUNCTION_ENTRY();
// Unmap peripheral registers
if (g_pIPU)
{
MmUnmapIoSpace(g_pIPU, sizeof(CSP_IPU_REGS));
g_pIPU = NULL;
}
IPU_FUNCTION_EXIT();
}
//------------------------------------------------------------------------------
//
// Function: IpuIntrInit
//
// This function initializes the g_pIntrGroupMask array with
// the appropriate interrupt group masks.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
static BOOL IpuIntrInit(void)
{
DWORD ipuIrq;
BOOL ret = FALSE;
IPU_FUNCTION_ENTRY();
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for IPU Interrupt\r\n"), __WFUNCTION__));
g_hIpuIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_hIpuIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for IPU Interrupt failed\r\n"), __WFUNCTION__));
return ret;
}
// IRQ is defined at SOC level
ipuIrq = IPUGetIRQ();
// Translate IRQ to SYSINTR
if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ipuIrq, sizeof(ipuIrq),
&g_ipuIntr, sizeof(g_ipuIntr), NULL))
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Request SYSINTR failed (IPU Interrupt)\r\n"), __WFUNCTION__));
return ret;
}
if(!InterruptInitialize(g_ipuIntr, g_hIpuIntrEvent, NULL, 0))
{
CloseHandle(g_hIpuIntrEvent);
g_hIpuIntrEvent = NULL;
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: Interrupt initialization failed! (IPU Interrupt)\r\n"), __WFUNCTION__));
return ret;
}
// Create events to facilitate communication of
// interrupt status with drivers for IPU sub-modules.
// Event names are shared between the common IPU code and
// the Prp and Pp drivers through event strings found in Ipu.h
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for Pre-processor Interrupt event\r\n"), __WFUNCTION__));
g_hPrpIntrEvent = CreateEvent(NULL, FALSE, FALSE, IPU_PRP_INTR_EVENT);
if (g_hPrpIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for Pre-processor Interrupt Event failed\r\n"), __WFUNCTION__));
return ret;
}
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for Post-processor Interrupt event\r\n"), __WFUNCTION__));
g_hPpIntrEvent = CreateEvent(NULL, FALSE, FALSE, IPU_PP_INTR_EVENT);
if (g_hPpIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for Post-processor Interrupt Event failed\r\n"), __WFUNCTION__));
return ret;
}
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for Post-filtering Interrupt event\r\n"), __WFUNCTION__));
g_hPfIntrEvent = CreateEvent(NULL, FALSE, FALSE, IPU_PF_INTR_EVENT);
if (g_hPfIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for Post-filtering Interrupt Event failed\r\n"), __WFUNCTION__));
return ret;
}
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for SDC Background plane Interrupt event\r\n"), __WFUNCTION__));
g_hSDCBGIntrEvent = CreateEvent(NULL, FALSE, FALSE, IPU_SDC_BG_INTR_EVENT);
if (g_hSDCBGIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for SDC Background plane Interrupt Event failed\r\n"), __WFUNCTION__));
return ret;
}
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for SDC Foreground plane Interrupt event\r\n"), __WFUNCTION__));
g_hSDCFGIntrEvent = CreateEvent(NULL, FALSE, FALSE, IPU_SDC_FG_INTR_EVENT);
if (g_hSDCFGIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for SDC Foreground plane Interrupt Event failed\r\n"), __WFUNCTION__));
return ret;
}
DEBUGMSG(ZONE_INIT, (TEXT("%s: CreateEvent for ADC Interrupt event\r\n"), __WFUNCTION__));
g_hADCIntrEvent = CreateEvent(NULL, FALSE, FALSE, IPU_ADC_INTR_EVENT);
if (g_hADCIntrEvent == NULL)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("%s: CreateEvent for ADC Interrupt Event failed\r\n"), __WFUNCTION__));
return ret;
}
g_phIntrHdlr[IPU_INT_DMAIC_0] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_1] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_2] = g_hPpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_3] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_4] = g_hPpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_5] = g_hPpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_6] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_7] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_8] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_9] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_10] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_11] = g_hPrpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_12] = g_hPpIntrEvent;
g_phIntrHdlr[IPU_INT_DMAIC_13] = g_hPpIntrEvent;
g_phIntrHdlr[IPU_INT_DMASDC_0] = g_hSDCBGIntrEvent;
g_phIntrHdlr[IPU_INT_DMASDC_1] = g_hSDCFGIntrEvent;
g_phIntrHdlr[IPU_INT_DMASDC_2] = 0;
g_phIntrHdlr[IPU_INT_DMASDC_3] = 0;
g_phIntrHdlr[IPU_INT_DMAADC_2] = g_hADCIntrEvent;
g_phIntrHdlr[IPU_INT_DMAADC_3] = g_hADCIntrEvent;
g_phIntrHdlr[IPU_INT_DMAADC_4] = g_hADCIntrEvent;
g_phIntrHdlr[IPU_INT_DMAADC_5] = g_hADCIntrEvent;
g_phIntrHdlr[IPU_INT_DMAADC_6] = g_hADCIntrEvent;
g_phIntrHdlr[IPU_INT_DMAADC_7] = g_hADCIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_0] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_1] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_2] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_3] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_4] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_5] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_6] = g_hPfIntrEvent;
g_phIntrHdlr[IPU_INT_DMAPF_7] = g_hPfIntrEvent;
g_pIntrGroupMask[IPU_INT_DMAIC_0] = PRP_ENC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_1] = PRP_VF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_2] = PP_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_3] = PRP_VF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_4] = PP_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_5] = PP_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_6] = 0;
g_pIntrGroupMask[IPU_INT_DMAIC_7] = 0;
g_pIntrGroupMask[IPU_INT_DMAIC_8] = PRP_ENC_ROT_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_9] = PRP_VF_ROT_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_10] = PRP_ENC_ROT_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_11] = PRP_VF_ROT_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_12] = PP_ROT_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAIC_13] = PP_ROT_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMASDC_0] = SDC_BG_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMASDC_1] = SDC_FG_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMASDC_2] = 0;
g_pIntrGroupMask[IPU_INT_DMASDC_3] = 0;
g_pIntrGroupMask[IPU_INT_DMAADC_2] = ADC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAADC_3] = ADC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAADC_4] = ADC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAADC_5] = ADC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAADC_6] = ADC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAADC_7] = ADC_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_0] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_1] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_2] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_3] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_4] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_5] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_6] = PF_DMA_CHA_MASK;
g_pIntrGroupMask[IPU_INT_DMAPF_7] = PF_DMA_CHA_MASK;
ret = TRUE;
IPU_FUNCTION_EXIT();
return ret;
}
//------------------------------------------------------------------------------
//
// Function: IpuIntrThread
//
// This function is the IPU IST thread.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
static void IpuIntrThread(LPVOID lpParameter)
{
IPU_FUNCTION_ENTRY();
IpuISRLoop(INFINITE);
IPU_FUNCTION_EXIT();
}
//-----------------------------------------------------------------------------
//
// Function: IpuISRLoop
//
// This function is the interrupt handler for the Preprocessor.
// It waits for the End-Of-Frame (EOF) interrupt, and signals
// the EOF event registered by the user of the preprocessor.
//
// Parameters:
// timeout
// [in] Timeout value while waiting for EOF interrupt.
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
static void IpuISRLoop(UINT32 timeout)
{
DWORD ctrlReg1, statReg1, statReg5, clearCtrlBits, int_src;
UINT32 oldCtrl, newCtrl;
IPU_FUNCTION_ENTRY();
// loop here
while(TRUE)
{
DEBUGMSG (ZONE_INFO, (TEXT("%s: In the loop\r\n"), __WFUNCTION__));
if (WaitForSingleObject(g_hIpuIntrEvent, timeout) == WAIT_OBJECT_0)
{
DEBUGMSG (ZONE_INFO, (TEXT("%s: Interrupt received\r\n"), __WFUNCTION__));
ctrlReg1 = INREG32(&g_pIPU->IPU_INT_CTRL_1);
statReg1 = INREG32(&g_pIPU->IPU_INT_STAT_1);
statReg5 = INREG32(&g_pIPU->IPU_INT_STAT_5);
clearCtrlBits = 0;
int_src = 31 - _CountLeadingZeros(statReg1 & ctrlReg1);
// If interrupt source is valid
if (int_src < IPU_INT_MAX_ID)
{
// Clear interrupt control bits so we do not
// continue to receive this interrupt. The signalled
// driver is responsible for re-enabling these bits.
clearCtrlBits = g_pIntrGroupMask[int_src];
// Use interlocked function to update control registers
do
{
oldCtrl = INREG32(&g_pIPU->IPU_INT_CTRL_1);
newCtrl = oldCtrl & ~clearCtrlBits;
} while (InterlockedTestExchange((LPLONG) &g_pIPU->IPU_INT_CTRL_1,
oldCtrl, newCtrl) != oldCtrl);
// If client event installed
if (g_phIntrHdlr[int_src] != NULL)
{
// Signal registered event
// Note: Rescheduling may occur and could result in more
// interrupts pending.
SetEvent(g_phIntrHdlr[int_src]);
}
else
{
DEBUGMSG(ZONE_ERROR, (_T("No IPU submodule event registered for interrupt source = %d\r\n"), int_src));
}
}
else if (_CountLeadingZeros(statReg1 & ctrlReg1) == 32)
{
DEBUGMSG(ZONE_INFO, (_T("No interrupt source?\r\n")));
}
else
{
DEBUGMSG(ZONE_ERROR, (_T("Invalid IPU interrupt source (%d)\r\n"), int_src));
}
if (statReg5 & 0xFFFF)
{
// TODO: Properly Handle Error Cases
DEBUGMSG (ZONE_INFO, (TEXT("%s: Error Interrupt received!\r\n"), __WFUNCTION__));
if (INREG32(&g_pIPU->IPU_INT_STAT_5) & 0x3800)
{
DEBUGMSG (ZONE_INFO, (TEXT("%s: Frame Lost.\r\n"), __WFUNCTION__));
// Clear frame drop interrupt registers
OUTREG32(&g_pIPU->IPU_INT_STAT_5, 0x3800);
DEBUGMSG (ZONE_INFO, (TEXT("%s: Cleared INT_STAT_5: %x\r\n"),
__WFUNCTION__, INREG32(&g_pIPU->IPU_INT_STAT_5)));
}
else
{
DEBUGMSG (ZONE_INFO, (TEXT("%s: Other error.\r\n"), __WFUNCTION__));
}
}
// Kernel call to unmask the interrupt so that it can be signalled again
InterruptDone(g_ipuIntr);
}
else
{
DEBUGMSG (ZONE_INFO, (TEXT("%s: Time out\r\n"), __WFUNCTION__));
}
}
IPU_FUNCTION_EXIT();
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -