From b015782fbc931b1721edffd1028fa69a41ee9ead Mon Sep 17 00:00:00 2001 From: Rohit Consul Date: Fri, 31 Jul 2015 13:47:45 -0700 Subject: [PATCH] vprocss: Added subcores support for mutiple pixel/clk - Code cleanup to remove interrupt handler registration. Subsystem does not have interrupts - Updated sub-core init routines to load default filter coefficients for scaler and chroma resamplers - Added layer 2 registers for chroma resamplers - Updated VDMA Read/Write interface to work with color depth instead of Bytes/Pixel Signed-off-by: Rohit Consul Reviewed-by: Andrei Simion --- .../drivers/vprocss/data/vprocss.mdd | 2 +- .../drivers/vprocss/src/vdma/xvprocss_vdma.c | 195 +++++++++--------- .../drivers/vprocss/src/vdma/xvprocss_vdma.h | 6 +- .../drivers/vprocss/src/xvprocss.c | 94 +++++---- .../drivers/vprocss/src/xvprocss.h | 39 ++-- .../drivers/vprocss/src/xvprocss_coreinit.c | 18 +- .../drivers/vprocss/src/xvprocss_router.c | 121 ++++++----- 7 files changed, 260 insertions(+), 215 deletions(-) diff --git a/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd b/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd index 5d95d73b..392971e8 100755 --- a/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd +++ b/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd @@ -37,7 +37,7 @@ BEGIN driver vprocss OPTION driver_state = ACTIVE; OPTION copyfiles = all; OPTION VERSION = 1.0; - OPTION DEPENDS = (video_common v_csc v_deinterlacer v_hcresampler v_vcresampler v_hscaler v_vscaler v_letterbox axivdma gpio axis_switch); + OPTION DEPENDS = (video_common_v1_1 v_csc_v1_0 v_deinterlacer_v5_0 v_hcresampler_v1_0 v_vcresampler_v1_0 v_hscaler_v1_0 v_vscaler_v1_0 v_letterbox_v1_0 axivdma_v5_1 gpio_v4_0 axis_switch_v1_0); OPTION NAME = vprocss; END driver diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.c b/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.c index 5b06591b..978ba656 100644 --- a/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.c +++ b/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.c @@ -55,9 +55,11 @@ /***************************** Include Files *********************************/ #include "xvidc.h" #include "xvprocss_vdma.h" -#include "microblaze_sleep.h" #define XVDMA_RESET_TIMEOUT (1000000) //10ms at 10ns time period (100MHz clock)) + +/************************** Function Prototypes ******************************/ + /*****************************************************************************/ /** * This function starts Read and Write channels @@ -154,9 +156,9 @@ int XVprocss_VdmaWriteSetup(XAxiVdma *pVdma, XVidC_VideoWindow *window, u32 FrameWidth, u32 FrameHeight, - u32 Bpp) + u32 PixelWidthInBits) { - XAxiVdma_DmaSetup WriteCfg; + XAxiVdma_DmaSetup WriteCfg = {0}; int Index; u32 Addr; int Status; @@ -164,24 +166,24 @@ int XVprocss_VdmaWriteSetup(XAxiVdma *pVdma, u32 StrideInBytes;; u32 BlockOffset; u32 alignBytes = 0; - int MAX_WR_FRAMES; if(pVdma) { - MAX_WR_FRAMES = pVdma->MaxNumFrames; - HSizeInBytes = window->Width*Bpp; - StrideInBytes = FrameWidth*Bpp; + HSizeInBytes = (window->Width*PixelWidthInBits)/8; + StrideInBytes = (FrameWidth*PixelWidthInBits)/8; /* Compute start location for sub-frame */ - BlockOffset = (window->StartY * StrideInBytes) + window->StartX*Bpp; + BlockOffset = (window->StartY * StrideInBytes) + (window->StartX*PixelWidthInBits)/8; /* If DMA engine does not support unaligned transfers then align block - * offset to next data width boundary (DMA WR Data-width = 128) + * offset, hsize and stride to next data width boundary */ if(!pVdma->WriteChannel.HasDRE) { alignBytes = pVdma->WriteChannel.WordLength-1; - BlockOffset = (BlockOffset+alignBytes) & ~(alignBytes); + BlockOffset = (BlockOffset + alignBytes) & ~(alignBytes); + HSizeInBytes = (HSizeInBytes + alignBytes) & ~(alignBytes); + StrideInBytes = (StrideInBytes + alignBytes) & ~(alignBytes); } WriteCfg.VertSizeInput = window->Height; @@ -211,7 +213,7 @@ int XVprocss_VdmaWriteSetup(XAxiVdma *pVdma, * Use physical addresses */ Addr = WrBaseAddress + BlockOffset; - for(Index = 0; Index < MAX_WR_FRAMES; Index++) + for(Index = 0; Index < pVdma->MaxNumFrames; Index++) { WriteCfg.FrameStoreStartAddr[Index] = Addr; Addr += StrideInBytes * FrameHeight; @@ -251,7 +253,7 @@ int XVprocss_VdmaReadSetup(XAxiVdma *pVdma, XVidC_VideoWindow *window, u32 FrameWidth, u32 FrameHeight, - u32 Bpp) + u32 PixelWidthInBits) { XAxiVdma_DmaSetup ReadCfg; int Index; @@ -261,24 +263,24 @@ int XVprocss_VdmaReadSetup(XAxiVdma *pVdma, u32 StrideInBytes; u32 BlockOffset; u32 alignBytes = 0; - int MAX_RD_FRAMES = pVdma->MaxNumFrames; if(pVdma) { - MAX_RD_FRAMES = pVdma->MaxNumFrames; - HSizeInBytes = window->Width*Bpp; - StrideInBytes = FrameWidth*Bpp; + HSizeInBytes = (window->Width*PixelWidthInBits)/8; + StrideInBytes = (FrameWidth*PixelWidthInBits)/8; //Compute start location for sub-frame - BlockOffset = (window->StartY * StrideInBytes) + window->StartX*Bpp; + BlockOffset = (window->StartY * StrideInBytes) + (window->StartX*PixelWidthInBits)/8; /* If DMA engine does not support unaligned transfers then align block - * offset to next data width boundary (DMA WR Data-width = 128) + * offset, hsize and stride to next data width boundary */ if(!pVdma->ReadChannel.HasDRE) { alignBytes = pVdma->ReadChannel.WordLength-1; - BlockOffset = (BlockOffset+alignBytes) & ~(alignBytes); + BlockOffset = (BlockOffset + alignBytes) & ~(alignBytes); + HSizeInBytes = (HSizeInBytes + alignBytes) & ~(alignBytes); + StrideInBytes = (StrideInBytes + alignBytes) & ~(alignBytes); } ReadCfg.VertSizeInput = window->Height; @@ -307,7 +309,7 @@ int XVprocss_VdmaReadSetup(XAxiVdma *pVdma, * These addresses are physical addresses */ Addr = RdBaseAddress + BlockOffset; - for(Index = 0; Index < MAX_RD_FRAMES; Index++) + for(Index = 0; Index < pVdma->MaxNumFrames; Index++) { ReadCfg.FrameStoreStartAddr[Index] = Addr; Addr += StrideInBytes * FrameHeight; @@ -363,63 +365,6 @@ int XVprocss_VdmaStartTransfer(XAxiVdma *pVdma) return XST_SUCCESS; } -/*****************************************************************************/ -/** -* -* This function prints VDMA status on the console -* -* @param pVdma is the instance pointer to the DMA engine. -* @param Bpp is Bytes per pixel to be used for data transfer -* -* @return None -* -******************************************************************************/ -void XVprocss_VdmaDbgReportStatus(XAxiVdma *pVdma, u32 Bpp) -{ - u32 height,width,stride; - u32 regOffset; - - if(pVdma) - { - xil_printf("\r\n\r\n----->VDMA IP STATUS<----\r\n"); - xil_printf("INFO: VDMA Rd/Wr Client Width/Stride defined in Bytes Per Pixel\r\n"); - xil_printf("Bytes Per Pixel = %d\r\n\r\n", Bpp); - xil_printf("Read Channel Setting \r\n" ); - //clear status register before reading - XAxiVdma_ClearDmaChannelErrors(pVdma, XAXIVDMA_READ, 0xFFFFFFFF); - MB_Sleep(100); - - //Read Registers - XAxiVdma_DmaRegisterDump(pVdma, XAXIVDMA_READ); - regOffset = XAXIVDMA_MM2S_ADDR_OFFSET; - height = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+0); - width = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+4); - stride = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+8); - stride &= XAXIVDMA_STRIDE_MASK; - - xil_printf("Height: %d \r\n", height); - xil_printf("Width : %d (%d)\r\n", width, (width/Bpp)); - xil_printf("Stride: %d (%d)\r\n", stride, (stride/Bpp)); - - xil_printf("\r\nWrite Channel Setting \r\n" ); - //clear status register before reading - XAxiVdma_ClearDmaChannelErrors(pVdma, XAXIVDMA_WRITE, 0xFFFFFFFF); - MB_Sleep(100); - - //Read Registers - XAxiVdma_DmaRegisterDump(pVdma, XAXIVDMA_WRITE); - regOffset = XAXIVDMA_S2MM_ADDR_OFFSET; - height = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+0); - width = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+4); - stride = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+8); - stride &= XAXIVDMA_STRIDE_MASK; - - xil_printf("Height: %d \r\n", height); - xil_printf("Width : %d (%d)\r\n", width, (width/Bpp)); - xil_printf("Stride: %d (%d)\r\n", stride, (stride/Bpp)); - } -} - /*****************************************************************************/ /** * This function configures the VDMA RD/WR channel for down scale mode @@ -465,11 +410,11 @@ void XVprocss_VdmaSetWinToDnScaleMode(XVprocss *pVprocss, u32 updateCh) /* write PIP window stream to DDR */ status = XVprocss_VdmaWriteSetup(pVprocss->vdma, - pVprocss->FrameBufBaseaddr, - &wrWin, - OutputWidth, - OutputHeight, - pVprocss->idata.vdmaBytesPerPixel); + pVprocss->FrameBufBaseaddr, + &wrWin, + OutputWidth, + OutputHeight, + pVprocss->idata.PixelWidthInBits); if(status != XST_SUCCESS) { xil_printf("VPROCSS ERR:: Unable to configure VDMA Write Channel \r\n"); @@ -487,11 +432,11 @@ void XVprocss_VdmaSetWinToDnScaleMode(XVprocss *pVprocss, u32 updateCh) rdWin.Height = OutputHeight; status = XVprocss_VdmaReadSetup(pVprocss->vdma, - pVprocss->FrameBufBaseaddr, - &rdWin, - OutputWidth, - OutputHeight, - pVprocss->idata.vdmaBytesPerPixel); + pVprocss->FrameBufBaseaddr, + &rdWin, + OutputWidth, + OutputHeight, + pVprocss->idata.PixelWidthInBits); if(status != XST_SUCCESS) { xil_printf("VPROCSS ERR:: Unable to configure VDMA Read Channel \r\n"); @@ -534,11 +479,11 @@ void XVprocss_VdmaSetWinToUpScaleMode(XVprocss *pVprocss, u32 updateCh) /* write input stream to DDR */ status = XVprocss_VdmaWriteSetup(pVprocss->vdma, - pVprocss->FrameBufBaseaddr, - &wrWin, - InputWidth, - InputHeight, - pVprocss->idata.vdmaBytesPerPixel); + pVprocss->FrameBufBaseaddr, + &wrWin, + InputWidth, + InputHeight, + pVprocss->idata.PixelWidthInBits); if(status != XST_SUCCESS) { xil_printf("ERR:: Unable to configure VDMA Write Channel \r\n"); @@ -564,15 +509,71 @@ void XVprocss_VdmaSetWinToUpScaleMode(XVprocss *pVprocss, u32 updateCh) } status = XVprocss_VdmaReadSetup(pVprocss->vdma, - pVprocss->FrameBufBaseaddr, - &rdWin, - InputWidth, - InputHeight, - pVprocss->idata.vdmaBytesPerPixel); + pVprocss->FrameBufBaseaddr, + &rdWin, + InputWidth, + InputHeight, + pVprocss->idata.PixelWidthInBits); if(status != XST_SUCCESS) { xil_printf("ERR:: Unable to configure VDMA Read Channel \r\n"); } } } + +/*****************************************************************************/ +/** +* +* This function prints VDMA status on the console +* +* @param pVdma is the instance pointer to the DMA engine. +* @param Bpp is Bytes per pixel to be used for data transfer +* +* @return None +* +******************************************************************************/ +void XVprocss_VdmaDbgReportStatus(XAxiVdma *pVdma, u32 PixelWidthInBits) +{ + u32 height,width,stride; + u32 regOffset; + + if(pVdma) + { + xil_printf("\r\n\r\n----->VDMA IP STATUS<----\r\n"); + xil_printf("INFO: VDMA Rd/Wr Client Width/Stride defined in Bytes Per Pixel\r\n"); + xil_printf("Bytes Per Pixel = %d\r\n\r\n", PixelWidthInBits/8); + xil_printf("Read Channel Setting \r\n" ); + //clear status register before reading + XAxiVdma_ClearDmaChannelErrors(pVdma, XAXIVDMA_READ, 0xFFFFFFFF); + + //Read Registers + XAxiVdma_DmaRegisterDump(pVdma, XAXIVDMA_READ); + regOffset = XAXIVDMA_MM2S_ADDR_OFFSET; + height = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+0); + width = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+4); + stride = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+8); + stride &= XAXIVDMA_STRIDE_MASK; + + xil_printf("Height: %d \r\n", height); + xil_printf("Width : %d (%d)\r\n", width, (width*8/PixelWidthInBits)); + xil_printf("Stride: %d (%d)\r\n", stride, (stride*8/PixelWidthInBits)); + + xil_printf("\r\nWrite Channel Setting \r\n" ); + //clear status register before reading + XAxiVdma_ClearDmaChannelErrors(pVdma, XAXIVDMA_WRITE, 0xFFFFFFFF); + + //Read Registers + XAxiVdma_DmaRegisterDump(pVdma, XAXIVDMA_WRITE); + regOffset = XAXIVDMA_S2MM_ADDR_OFFSET; + height = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+0); + width = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+4); + stride = XAxiVdma_ReadReg(pVdma->BaseAddr, regOffset+8); + stride &= XAXIVDMA_STRIDE_MASK; + + xil_printf("Height: %d \r\n", height); + xil_printf("Width : %d (%d)\r\n", width, (width*8/PixelWidthInBits)); + xil_printf("Stride: %d (%d)\r\n", stride, (stride*8/PixelWidthInBits)); + } +} + /** @} */ diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.h b/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.h index 37ba1b21..35150831 100644 --- a/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.h +++ b/XilinxProcessorIPLib/drivers/vprocss/src/vdma/xvprocss_vdma.h @@ -106,15 +106,15 @@ int XVprocss_VdmaWriteSetup(XAxiVdma *pVdma, XVidC_VideoWindow *window, u32 FrameWidth, u32 FrameHeight, - u32 Bpp); + u32 PixelWidthInBits); int XVprocss_VdmaReadSetup(XAxiVdma *pVdma, u32 RdBaseAddress, XVidC_VideoWindow *window, u32 FrameWidth, u32 FrameHeight, - u32 Bpp); + u32 PixelWidthInBits); int XVprocss_VdmaStartTransfer(XAxiVdma *pVdma); -void XVprocss_VdmaDbgReportStatus(XAxiVdma *pVdma, u32 Bpp); +void XVprocss_VdmaDbgReportStatus(XAxiVdma *pVdma, u32 PixelWidthInBits); void XVprocss_VdmaSetWinToUpScaleMode(XVprocss *pVprocss, u32 updateCh); void XVprocss_VdmaSetWinToDnScaleMode(XVprocss *pVprocss, u32 updateCh); diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c index 6aa0303f..9cc9787f 100644 --- a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c @@ -49,21 +49,23 @@ ******************************************************************************/ /***************************** Include Files *********************************/ -#include "microblaze_sleep.h" #include "xvprocss.h" #include "xenv.h" #include "xvprocss_vdma.h" #include "xvprocss_router.h" #include "xvprocss_coreinit.h" +#if defined(__arm__) +#include "sleep.h" +#elif defined(__MICROBLAZE__) +#include "microblaze_sleep.h" +#endif + /************************** Constant Definitions *****************************/ /* HW Reset Network GPIO Channel */ #define GPIO_CH_RESET_SEL (1u) -/* VDMA transaction size in Bytes/Pixel */ -#define XVPROC_VDMA_TRANS_SIZE_BYTES (4) - /** @name Reset Network * * @{ @@ -182,7 +184,7 @@ static __inline void XVprocss_ResetBlock(XGpio *pReset, u32 channel, u32 ipBlock /*****************************************************************************/ /** -* This function diverts the delay routine used in the subsystem. Preference is +* This function routes the delay routine used in the subsystem. Preference is * given to the user registered timer based routine. If no delay handler is * registered then it uses the platform specific delay handler * @@ -192,16 +194,30 @@ static __inline void XVprocss_ResetBlock(XGpio *pReset, u32 channel, u32 ipBlock * @return None * ******************************************************************************/ -static __inline void Waitms(XVprocss *pVprocss, u32 msec) +static __inline void WaitUs(XVprocss *pVprocss, u32 MicroSeconds) { - if(pVprocss->UsrDelaymsec) + if(MicroSeconds == 0) + return; + +#if defined(__arm__) + /* Wait the requested amount of time. */ + usleep(MicroSeconds); +#elif defined(__MICROBLAZE__) + if(pVprocss->UsrDelayUs) { - pVprocss->UsrDelaymsec(pVprocss->pUsrTmr, msec); + /* Use the time handler specified by the user for + * better accuracy + */ + pVprocss->UsrDelayUs(pVprocss->pUsrTmr, MicroSeconds); } else { - MB_Sleep(msec); + /* MicroBlaze sleep only has millisecond accuracy. Round up. */ + u32 MilliSeconds = (MicroSeconds + 999) / 1000; + + MB_Sleep(MilliSeconds); } +#endif } /************************** Function Definition ******************************/ @@ -289,40 +305,25 @@ void XVprocss_ReportCoreInfo(XVprocss *InstancePtr) * This function registers the user defined delay/sleep function with subsystem * * @param InstancePtr is a pointer to the Subsystem instance -* @param waitmsec is the function pointer to the user defined delay function -* @param pTimer is the pointer to timer instance used by the delay function +* @param CallbackFunc is the function pointer to the user defined delay +* function +* @param CallbackRef is the pointer to timer instance used by the delay +* function * * @return None * ******************************************************************************/ void XVprocss_RegisterDelayHandler(XVprocss *InstancePtr, - XVidC_DelayHandler waitmsec, - void *pTimer) + XVidC_DelayHandler CallbackFunc, + void *CallbackRef) { + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); - InstancePtr->UsrDelaymsec = waitmsec; - InstancePtr->pUsrTmr = pTimer; -} - -/*****************************************************************************/ -/** -* This function registers the System Interrupt controller with subsystem -* -* @param InstancePtr is a pointer to the Subsystem instance -* @param sysIntc is a pointer to the interrupt controller instance -* -* @return None -* -* @note Currently the subsystem and any of its sub-cores do not generate any -* interrupts. Use of interrupt controller is reserved for future version -******************************************************************************/ -void XVprocss_RegisterSysIntc(XVprocss *InstancePtr, XIntc *sysIntc) -{ - Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(sysIntc != NULL); - - InstancePtr->pXintc = sysIntc; + InstancePtr->UsrDelayUs = CallbackFunc; + InstancePtr->pUsrTmr = CallbackRef; } /*****************************************************************************/ @@ -416,7 +417,6 @@ int XVprocss_CfgInitialize(XVprocss *InstancePtr, XVprocss_Config *CfgPtr, Xil_AssertNonvoid(pVprocss != NULL); Xil_AssertNonvoid(CfgPtr != NULL); Xil_AssertNonvoid(EffectiveAddr != (u32)NULL); - Xil_AssertNonvoid(pVprocss->pXintc != NULL); /* Setup the instance */ memcpy((void *)&(pVprocss->Config), (const void *)CfgPtr, sizeof(XVprocss_Config)); @@ -692,8 +692,6 @@ static void SetPODConfiguration(XVprocss *pVprocss) &win); } - pVprocss->idata.vdmaBytesPerPixel = XVPROC_VDMA_TRANS_SIZE_BYTES; - /* Release reset before programming any IP Block */ XVprocss_EnableBlock(pVprocss->rstAxis, GPIO_CH_RESET_SEL, RESET_MASK_ALL_BLOCKS); @@ -731,6 +729,7 @@ void XVprocss_Start(XVprocss *InstancePtr) { u8 *pStartCore; + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); pStartCore = &InstancePtr->idata.startCore[0]; @@ -779,6 +778,7 @@ void XVprocss_Start(XVprocss *InstancePtr) ******************************************************************************/ void XVprocss_Stop(XVprocss *InstancePtr) { + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL," ->Stop Video Processing Subsystem.... \r\n"); @@ -825,6 +825,7 @@ void XVprocss_Stop(XVprocss *InstancePtr) ******************************************************************************/ void XVprocss_Reset(XVprocss *InstancePtr) { + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); xdbg_printf(XDBG_DEBUG_GENERAL," ->Reset Video Processing Subsystem.... \r\n"); @@ -842,7 +843,7 @@ void XVprocss_Reset(XVprocss *InstancePtr) XV_DeintStop(InstancePtr->deint); } - Waitms(InstancePtr, 10); /* hold reset line for 10ms */ + WaitUs(InstancePtr, 100); /* hold reset line for 100us */ /* * Make sure the video IP's are out of reset - IP's cannot be programmed when held * in reset. Will cause Axi-Lite bus to lock. @@ -851,7 +852,7 @@ void XVprocss_Reset(XVprocss *InstancePtr) // XVprocss_EnableBlock(InstancePtr->rstAximm, GPIO_CH_RESET_SEL, RESET_MASK_IP_AXIMM); // Waitms(InstancePtr, 10); /* wait for AXI-MM IP's to stabilize */ XVprocss_EnableBlock(InstancePtr->rstAxis, GPIO_CH_RESET_SEL, RESET_MASK_IP_AXIS); - Waitms(InstancePtr, 10); /* wait for AXIS to stabilize */ + WaitUs(InstancePtr, 1000); /* wait 1ms for AXIS to stabilize */ /* Reset start core flags */ memset(InstancePtr->idata.startCore, 0, sizeof(InstancePtr->idata.startCore)); @@ -872,6 +873,7 @@ int XVprocss_SetVidStreamIn(XVprocss *InstancePtr, { int status; + /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(StrmIn != NULL); @@ -904,6 +906,7 @@ int XVprocss_SetVidStreamOut(XVprocss *InstancePtr, { int status; + /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(StrmOut != NULL); @@ -937,6 +940,7 @@ int XVprocss_SetStreamResolution(XVidC_VideoStream *StreamPtr, { int status; + /* Verify arguments */ Xil_AssertNonvoid(StreamPtr != NULL); if(VmId < XVIDC_VM_NUM_SUPPORTED) @@ -972,6 +976,7 @@ int XVprocss_SetStreamResolution(XVidC_VideoStream *StreamPtr, ******************************************************************************/ void XVprocss_UpdateZoomPipWindow(XVprocss *InstancePtr) { + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); if(XVprocss_IsConfigModeMax(InstancePtr)) @@ -1028,6 +1033,7 @@ void XVprocss_SetZoomPipWindow(XVprocss *InstancePtr, { u16 wordlen; + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(win != NULL); @@ -1090,6 +1096,7 @@ void XVprocss_GetZoomPipWindow(XVprocss *InstancePtr, XVprocss_Win mode, XVidC_VideoWindow *win) { + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(win != NULL); @@ -1140,6 +1147,7 @@ void XVprocss_SetZoomMode(XVprocss *InstancePtr, u8 OnOff) { char *status[] = {"OFF","ON"}; + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); if(XVprocss_IsConfigModeMax(InstancePtr)) @@ -1179,6 +1187,7 @@ void XVprocss_SetPipMode(XVprocss *InstancePtr, u8 OnOff) { char *status[] = {"OFF","ON"}; + /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); if(XVprocss_IsConfigModeMax(InstancePtr)) @@ -1369,6 +1378,7 @@ int XVprocss_ConfigureSubsystem(XVprocss *InstancePtr) { int status = XST_SUCCESS; + /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); /* Video Processing Subsystem overrides In/Out Pixel Precision & Pixel/Clk */ @@ -1377,6 +1387,10 @@ int XVprocss_ConfigureSubsystem(XVprocss *InstancePtr) InstancePtr->VidIn.PixPerClk = (XVidC_PixelsPerClock)InstancePtr->Config.PixPerClock; + /* compute data width of input stream */ + InstancePtr->idata.PixelWidthInBits = InstancePtr->Config.NumVidComponents * + InstancePtr->VidIn.ColorDepth; + xil_printf("\r\n****** VPROC SUBSYSTEM INPUT/OUTPUT CONFIG ******\r\n"); xil_printf("->INPUT\r\n"); XVidC_ReportStreamInfo(&InstancePtr->VidIn); diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h index a9d72abf..a45d514c 100644 --- a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h @@ -105,11 +105,12 @@ * * Pre-Requisite's * -* Subsystem driver requires 2 support peripherals, Timer and an Interrupt -* Controller, to be present in the design and the application must register a -* handle to these with the subsystem using the provided API's. -* Also for memory based design application must program the base address of the -* video buffers in memory. Refer Memory Requirement section below +* - For memory based design (Full Fledged Topology) application must program +* the base address of the video buffers in memory. Refer Memory Requirement +* section below. +* - For microblaze based designs it is recommended to include a timer +* peripheral in the design and application should register a delay handling +* routine with the subsystem using the provided API. * * Subsystem Driver Usage * @@ -125,13 +126,15 @@ * Memory Requirement * * For full configuration mode DDR memory is used to store video frame buffers -* Subsystem uses 4 frame buffers for Progressive input and 3 field buffers for -* interlaced input (if supported). Amount of memory required by the subsystem -* can be calculated +* Subsystem uses 5 frame buffers for Progressive input and 3 field buffers for +* interlaced input. Amount of memory required by the subsystem can be +* calculated by below equation * -* - NUM_BUFFERS * MAX_WIDTH * MAX_HEIGHT * NUM_VIDEO_COMPONENTS * ByesPerPixel +* - 5 * MAX_WIDTHp * MAX_HEIGHTp * NUM_VIDEO_COMPONENTS * BytesPerComp +* + +* 3 * MAX_WIDTHi * MAX_HEIGHTi * NUM_VIDEO_COMPONENTS * BytesPerComp * -* BytesPerPixel +* BytesPerComp * - 1 Byte for 8 bit data pipe * - 2 Byte for 10/12/16 bit data pipe * @@ -187,7 +190,6 @@ extern "C" { /***************************** Include Files *********************************/ #include "xstatus.h" -#include "xintc.h" #include "xgpio.h" #include "xaxis_switch.h" #include "xvidc.h" @@ -265,8 +267,8 @@ typedef struct XVidC_VideoWindow rdWindow; /**< window for Zoom/Pip feature support */ XVidC_VideoWindow wrWindow; /**< window for Zoom/Pip feature support */ - u32 deintBufAddr; /**< Deinterlacer field buffer Addr. in DDR */ - u8 vdmaBytesPerPixel; /**< Number of bytes required to store 1 pixel */ + u32 deintBufAddr; /**< Deinterlacer field buffer Addr. in DDR */ + u8 PixelWidthInBits; /**< Number of bits required to store 1 pixel */ u8 RtngTable[XVPROCSS_RTR_MAX]; /**< Storage for computed routing map */ u8 startCore[XVPROCSS_RTR_MAX]; /**< Enable flag to start sub-core */ @@ -358,6 +360,9 @@ typedef struct XV_csc_L2Reg cscL2Reg; /**< Layer 2 register bank for csc sub-core */ XV_vscaler_l2 vscL2Reg; /**< Layer 2 register bank for vsc sub-core */ XV_hscaler_l2 hscL2Reg; /**< Layer 2 register bank for hsc sub-core */ + XV_hcresampler_l2 hcrL2Reg; /**< Layer 2 register bank for hcr sub-core */ + XV_vcresampler_l2 vcrInL2Reg; /**< Layer 2 register bank for hcr sub-core */ + XV_vcresampler_l2 vcrOutL2Reg; /**< Layer 2 register bank for hcr sub-core */ //I/O Streams XVidC_VideoStream VidIn; /**< Input AXIS configuration */ @@ -367,8 +372,7 @@ typedef struct instance */ u32 FrameBufBaseaddr; /**< Base address for frame buffer storage */ - XIntc *pXintc; /**< handle to system interrupt controller */ - XVidC_DelayHandler UsrDelaymsec; /**< custom user function for delay/sleep */ + XVidC_DelayHandler UsrDelayUs; /**< custom user function for delay/sleep */ void *pUsrTmr; /**< handle to timer instance used by user delay function */ } XVprocss; @@ -508,10 +512,9 @@ void XVprocss_GetZoomPipWindow(XVprocss *InstancePtr, void XVprocss_UpdateZoomPipWindow(XVprocss *InstancePtr); -void XVprocss_RegisterSysIntc(XVprocss *InstancePtr, XIntc *sysIntc); void XVprocss_RegisterDelayHandler(XVprocss *InstancePtr, - XVidC_DelayHandler waitmsec, - void *pTimer); + XVidC_DelayHandler CallbackFunc, + void *CallbackRef); #ifdef __cplusplus diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_coreinit.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_coreinit.c index 5ed63b87..b62fe7f2 100644 --- a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_coreinit.c +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_coreinit.c @@ -370,6 +370,9 @@ int XVprocss_SubcoreInitHScaler(XVprocss *pVprocss) xil_printf("VPROCSS ERR:: Horiz. Scaler Initialization failed\r\n"); return(XST_FAILURE); } + + /* Load Default filter coefficients */ + XV_HScalerLoadDefaultCoeff(pVprocss->hscaler, &pVprocss->hscL2Reg); } return(XST_SUCCESS); } @@ -423,6 +426,10 @@ int XVprocss_SubcoreInitVScaler(XVprocss *pVprocss) xil_printf("VPROCSS ERR:: Vert. Scaler Initialization failed\r\n"); return(XST_FAILURE); } + + /* Load Default filter coefficients */ + XV_VScalerLoadDefaultCoeff(pVprocss->vscaler, &pVprocss->vscL2Reg); + } return(XST_SUCCESS); } @@ -476,6 +483,9 @@ int XVprocss_SubcoreInitHCrsmplr(XVprocss *pVprocss) xil_printf("VPROCSS ERR:: H Chroma Resampler Initialization failed\r\n"); return(XST_FAILURE); } + + /* Load default filter coefficients */ + XV_HCrsmplLoadDefaultCoeff(pVprocss->hcrsmplr, &pVprocss->hcrL2Reg); } return(XST_SUCCESS); } @@ -529,6 +539,9 @@ int XVprocss_SubcoreInitVCrsmpleIn(XVprocss *pVprocss) xil_printf("VPROCSS ERR:: Input V Chroma Resampler Initialization failed\r\n"); return(XST_FAILURE); } + + /* Load default filter coefficients */ + XV_VCrsmplLoadDefaultCoeff(pVprocss->vcrsmplrIn, &pVprocss->vcrInL2Reg); } return(XST_SUCCESS); } @@ -582,6 +595,9 @@ int XVprocss_SubcoreInitVCrsmpleOut(XVprocss *pVprocss) xil_printf("VPROCSS ERR:: Output V Chroma Resampler Initialization failed\r\n"); return(XST_FAILURE); } + + /* Load default filter coefficients */ + XV_VCrsmplLoadDefaultCoeff(pVprocss->vcrsmplrOut, &pVprocss->vcrOutL2Reg); } return(XST_SUCCESS); } @@ -744,4 +760,4 @@ int XVprocss_SubcoreInitDeinterlacer(XVprocss *pVprocss) } return(XST_SUCCESS); } -/** @} */ \ No newline at end of file +/** @} */ diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c index 21b37aba..adf1bc5d 100644 --- a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c @@ -243,16 +243,16 @@ int XVprocss_BuildRoutingTable(XVprocss *pVprocss) pCfg->strmCformat = pStrIn->ColorFormatId; /* Determine Scaling Mode */ - pVprocss->idata.memEn = FALSE; - pVprocss->idata.ScaleMode = GetScalingMode(pVprocss); - if(pVprocss->idata.ScaleMode == XVPROCSS_SCALE_NOT_SUPPORTED) + pCfg->memEn = FALSE; + pCfg->ScaleMode = GetScalingMode(pVprocss); + if(pCfg->ScaleMode == XVPROCSS_SCALE_NOT_SUPPORTED) { xil_printf("VPROCSS ERR:: Scaling Mode not supported\r\n"); return(XST_FAILURE); } /* Reset Routing Table */ - memset(pTable, 0, sizeof(pVprocss->idata.RtngTable)); + memset(pTable, 0, sizeof(pCfg->RtngTable)); /* Check if input is I/P */ if(pStrIn->IsInterlaced) @@ -297,25 +297,25 @@ int XVprocss_BuildRoutingTable(XVprocss *pVprocss) } } - switch(pVprocss->idata.ScaleMode) + switch(pCfg->ScaleMode) { case XVPROCSS_SCALE_1_1: pTable[index++] = XVPROCSS_RTR_VDMA; - pVprocss->idata.memEn = TRUE; + pCfg->memEn = TRUE; break; case XVPROCSS_SCALE_UP: pTable[index++] = XVPROCSS_RTR_VDMA; /* VDMA is before Scaler */ pTable[index++] = XVPROCSS_RTR_SCALER_V; pTable[index++] = XVPROCSS_RTR_SCALER_H; - pVprocss->idata.memEn = TRUE; + pCfg->memEn = TRUE; break; case XVPROCSS_SCALE_DN: pTable[index++] = XVPROCSS_RTR_SCALER_H; pTable[index++] = XVPROCSS_RTR_SCALER_V; pTable[index++] = XVPROCSS_RTR_VDMA; /* VDMA is after Scaler */ - pVprocss->idata.memEn = TRUE; + pCfg->memEn = TRUE; break; default: @@ -467,7 +467,7 @@ int XVprocss_BuildRoutingTable(XVprocss *pVprocss) pTable[index++] = XVPROCSS_RTR_VIDOUT; /* save number of cores in processing path */ - pVprocss->idata.RtrNumCores = index; + pCfg->RtrNumCores = index; #ifdef DEBUG if(status == XST_SUCCESS) @@ -556,13 +556,13 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) * with progressive frame. Adjust active height to reflect the * progressive frame to downstream cores */ - pVprocss->idata.vidInHeight *= 2; + pCfg->vidInHeight *= 2; } /* If Vdma is enabled, RD/WR Client needs to be programmed before Scaler */ - if((pVprocss->vdma) && (pVprocss->idata.memEn)) + if((pVprocss->vdma) && (pCfg->memEn)) { - switch(pVprocss->idata.ScaleMode) + switch(pCfg->ScaleMode) { case XVPROCSS_SCALE_1_1: case XVPROCSS_SCALE_UP: @@ -570,7 +570,7 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) break; case XVPROCSS_SCALE_DN: - XVprocss_VdmaSetWinToDnScaleMode(pVprocss, XVPROCSS_VDMA_UPDATE_ALL_CH); + XVprocss_VdmaSetWinToDnScaleMode(pVprocss, XVPROCSS_VDMA_UPDATE_ALL_CH); break; default: @@ -579,28 +579,28 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) pStartCore[XVPROCSS_RTR_VDMA] = TRUE; } - for(count=0; countidata.RtrNumCores; ++count) + for(count=0; countRtrNumCores; ++count) { switch(pTable[count]) { case XVPROCSS_RTR_SCALER_V: if(pVprocss->vscaler) { - if(pVprocss->idata.ScaleMode == XVPROCSS_SCALE_DN) + if(pCfg->ScaleMode == XVPROCSS_SCALE_DN) { /* Downscale mode H Scaler is before V Scaler */ vsc_WidthIn = hsc_WidthOut; vsc_HeightIn = hsc_HeightIn; - vsc_HeightOut = ((XVprocss_IsPipModeOn(pVprocss)) ? pVprocss->idata.wrWindow.Height + vsc_HeightOut = ((XVprocss_IsPipModeOn(pVprocss)) ? pCfg->wrWindow.Height : pVprocss->VidOut.Timing.VActive); } else { /* UpScale mode V Scaler is before H Scaler */ - vsc_WidthIn = ((XVprocss_IsZoomModeOn(pVprocss)) ? pVprocss->idata.rdWindow.Width - : pVprocss->idata.vidInWidth); - vsc_HeightIn = ((XVprocss_IsZoomModeOn(pVprocss)) ? pVprocss->idata.rdWindow.Height - : pVprocss->idata.vidInHeight); + vsc_WidthIn = ((XVprocss_IsZoomModeOn(pVprocss)) ? pCfg->rdWindow.Width + : pCfg->vidInWidth); + vsc_HeightIn = ((XVprocss_IsZoomModeOn(pVprocss)) ? pCfg->rdWindow.Height + : pCfg->vidInHeight); vsc_HeightOut = pVprocss->VidOut.Timing.VActive; } @@ -608,7 +608,7 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) (int)vsc_WidthIn, (int)vsc_HeightIn, (int)vsc_WidthIn, (int)vsc_HeightOut); XV_VScalerSetup(pVprocss->vscaler, - &pVprocss->vscL2Reg, + &pVprocss->vscL2Reg, vsc_WidthIn, vsc_HeightIn, vsc_HeightOut); @@ -619,12 +619,12 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) case XVPROCSS_RTR_SCALER_H: if(pVprocss->hscaler) { - if(pVprocss->idata.ScaleMode == XVPROCSS_SCALE_DN) + if(pCfg->ScaleMode == XVPROCSS_SCALE_DN) { /* Downscale mode H Scaler is before V Scaler */ - hsc_WidthIn = pVprocss->idata.vidInWidth; - hsc_HeightIn = pVprocss->idata.vidInHeight; - hsc_WidthOut = ((XVprocss_IsPipModeOn(pVprocss)) ? pVprocss->idata.wrWindow.Width + hsc_WidthIn = pCfg->vidInWidth; + hsc_HeightIn = pCfg->vidInHeight; + hsc_WidthOut = ((XVprocss_IsPipModeOn(pVprocss)) ? pCfg->wrWindow.Width : pVprocss->VidOut.Timing.HActive); } else @@ -639,7 +639,7 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) (int)hsc_WidthIn, (int)hsc_HeightIn, (int)hsc_WidthOut, (int)hsc_HeightIn); XV_HScalerSetup(pVprocss->hscaler, - &pVprocss->hscL2Reg, + &pVprocss->hscL2Reg, hsc_HeightIn, hsc_WidthIn, hsc_WidthOut, @@ -658,7 +658,7 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) if(XVprocss_IsPipModeOn(pVprocss)) { /* get the active window for lbox */ - lboxWin = pVprocss->idata.wrWindow; + lboxWin = pCfg->wrWindow; } else //Downscale - Read full image from VDMA { @@ -669,9 +669,9 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) lboxWin.Height = pVprocss->VidOut.Timing.VActive; } XV_LBoxSetActiveWin(pVprocss->lbox, - &lboxWin, - pVprocss->VidOut.Timing.HActive, - pVprocss->VidOut.Timing.VActive); + &lboxWin, + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); pStartCore[XVPROCSS_RTR_LBOX] = TRUE; } break; @@ -680,12 +680,13 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) if(pVprocss->hcrsmplr) { XV_HCrsmplSetActiveSize(pVprocss->hcrsmplr, - pVprocss->VidOut.Timing.HActive, - pVprocss->VidOut.Timing.VActive); + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); XV_HCrsmplSetFormat(pVprocss->hcrsmplr, - pCfg->hcrIn, - pCfg->hcrOut); + &pVprocss->hcrL2Reg, + pCfg->hcrIn, + pCfg->hcrOut); pStartCore[XVPROCSS_RTR_CR_H] = TRUE; } break; @@ -694,12 +695,13 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) if(pVprocss->vcrsmplrIn) { XV_VCrsmplSetActiveSize(pVprocss->vcrsmplrIn, - pVprocss->idata.vidInWidth, - pVprocss->idata.vidInHeight); + pCfg->vidInWidth, + pCfg->vidInHeight); XV_VCrsmplSetFormat(pVprocss->vcrsmplrIn, - XVIDC_CSF_YCRCB_420, - XVIDC_CSF_YCRCB_422); + &pVprocss->vcrInL2Reg, + XVIDC_CSF_YCRCB_420, + XVIDC_CSF_YCRCB_422); pStartCore[XVPROCSS_RTR_CR_V_IN] = TRUE; } break; @@ -708,12 +710,13 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) if(pVprocss->vcrsmplrOut) { XV_VCrsmplSetActiveSize(pVprocss->vcrsmplrOut, - pVprocss->VidOut.Timing.HActive, - pVprocss->VidOut.Timing.VActive); + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); XV_VCrsmplSetFormat(pVprocss->vcrsmplrOut, - XVIDC_CSF_YCRCB_422, - XVIDC_CSF_YCRCB_420); + &pVprocss->vcrOutL2Reg, + XVIDC_CSF_YCRCB_422, + XVIDC_CSF_YCRCB_420); pStartCore[XVPROCSS_RTR_CR_V_OUT] = TRUE; } break; @@ -722,16 +725,16 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) if(pVprocss->csc) { XV_CscSetColorspace(pVprocss->csc, - &pVprocss->cscL2Reg, - pVprocss->idata.cscIn, - pVprocss->idata.cscOut, - pVprocss->cscL2Reg.StandardIn, - pVprocss->cscL2Reg.StandardOut, - pVprocss->cscL2Reg.OutputRange); + &pVprocss->cscL2Reg, + pCfg->cscIn, + pCfg->cscOut, + pVprocss->cscL2Reg.StandardIn, + pVprocss->cscL2Reg.StandardOut, + pVprocss->cscL2Reg.OutputRange); XV_CscSetActiveSize(pVprocss->csc, - pVprocss->VidOut.Timing.HActive, - pVprocss->VidOut.Timing.VActive); + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); pStartCore[XVPROCSS_RTR_CSC] = TRUE; } @@ -740,15 +743,23 @@ void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) case XVPROCSS_RTR_DEINT: if(pVprocss->deint) { - xdbg_printf(XDBG_DEBUG_GENERAL," -> Configure Deinterlacer for %dx%d to %dx%d\r\n", \ + xdbg_printf(XDBG_DEBUG_GENERAL," -> Configure Deinterlacer for %dx%d to %dx%d\r\n", \ (int)pVprocss->VidIn.Timing.HActive, (int)pVprocss->VidIn.Timing.VActive, - (int)pVprocss->idata.vidInWidth, - (int)pVprocss->idata.vidInHeight); + (int)pCfg->vidInWidth, + (int)pCfg->vidInHeight); XV_DeintSetFieldBuffers(pVprocss->deint, - pVprocss->idata.deintBufAddr, - pVprocss->VidIn.ColorFormatId); + pCfg->deintBufAddr, + pVprocss->VidIn.ColorFormatId); + + XV_deinterlacer_Set_width(pVprocss->deint, + pCfg->vidInWidth); + + XV_deinterlacer_Set_height(pVprocss->deint, + pVprocss->VidIn.Timing.VActive); //field height + + XV_deinterlacer_Set_invert_field_id(pVprocss->deint, 0); //TBD pStartCore[XVPROCSS_RTR_DEINT] = TRUE; } break;