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 <rohit.consul@xilinx.com>
Reviewed-by: Andrei Simion <andreis@xilinx.com>
This commit is contained in:
Rohit Consul 2015-07-31 13:47:45 -07:00 committed by Nava kishore Manne
parent f4901fa438
commit b015782fbc
7 changed files with 260 additions and 215 deletions

View file

@ -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

View file

@ -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));
}
}
/** @} */

View file

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

View file

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

View file

@ -105,11 +105,12 @@
*
* <b>Pre-Requisite's</b>
*
* 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.
*
* <b>Subsystem Driver Usage</b>
*
@ -125,13 +126,15 @@
* <b>Memory Requirement</b>
*
* 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

View file

@ -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);
}
/** @} */
/** @} */

View file

@ -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; count<pVprocss->idata.RtrNumCores; ++count)
for(count=0; count<pCfg->RtrNumCores; ++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;