embeddedsw/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c
Nava kishore Manne 1fb0b91e37 vprocss: Added @addtogroup tag with appropriate version information
Signed-off-by: Nava kishore Manne <navam@xilinx.com>
Reviewed-by: Kedareswara rao Appana <appanad@xilinx.com>
2015-08-14 11:39:10 +05:30

1651 lines
53 KiB
C

/******************************************************************************
*
* Copyright (C) 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xvprocss.c
* @addtogroup vprocss_v1_0
* @{
*
* This is main code of Xilinx Video Processing Subsystem device driver.
* Please see xvprocss.h for more details of the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00 rco 07/21/15 Initial Release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#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)
/** @name Reset Network
*
* @{
* The following constants define various reset lines in the subsystem
*/
#define RESET_MASK_VIDEO_IN (0x01) /**< Reset line going out of subsystem */
#define RESET_MASK_IP_AXIS (0x02) /**< Reset line for all video IP blocks */
#define RESET_MASK_IP_AXIMM (0x01) /**< Reset line for AXI-MM blocks */
/*@}*/
#define RESET_MASK_ALL_BLOCKS (RESET_MASK_VIDEO_IN | \
RESET_MASK_IP_AXIS)
/**************************** Type Definitions *******************************/
/**
* This typedef declares the driver instances of all the cores in the subsystem
*/
typedef struct
{
XAxis_Switch router;
XGpio rstAxis; //Reset for IP's running at AXIS Clk
XGpio rstAximm; //Reset for IP's with AXI MM interface
XV_hcresampler hcrsmplr;
XV_vcresampler vcrsmplrIn;
XV_vcresampler vcrsmplrOut;
XV_vscaler vscaler;
XV_hscaler hscaler;
XAxiVdma vdma;
XV_letterbox lbox;
XV_csc csc;
XV_deinterlacer deint;
}XVprocss_SubCores;
/**************************** Local Global ***********************************/
XVprocss_SubCores subcoreRepo; /**< Define Driver instance of all sub-core
included in the design */
/** @name VDMA Alignment required step size
*
* @{
* The following constants define various Zoom/Pip window horizontal step sizes
* that keeps the VDMA access aligned to aximm interface width, based on
* Pixels/Clock and Color Depth of the configured subsystem. This is required
* as current version of VDMA does not support DRE if interface width is
* >64bits. Software has to align the hsize and stride for all possible
* configurations supported by the subsystem.
* Current subsystem version supports the following
* - Number of components = 3 (Fixed)
* - Pixels/Clock = 1, 2, 4
* - Color Depth = 8, 10, 12, 16 (4 variations)
*/
const u16 XVprocss_PixelHStep[XVIDC_PPC_NUM_SUPPORTED][4] =
{
{16, 4, 32, 8}, //XVIDC_PPC_1
{16, 4, 64, 16}, //XVIDC_PPC_2
{32, 128, 128, 32}, //XVIDC_PPC_4
};
/************************** Function Prototypes ******************************/
static void SetPODConfiguration(XVprocss *pVprocss);
static void GetIncludedSubcores(XVprocss *pVprocss);
static int ValidateSubsystemConfig(XVprocss *InstancePtr);
static int ValidateScalerOnlyConfig(XVidC_VideoStream *pStrmIn,
XVidC_VideoStream *pStrmOut);
static int SetupModeScalerOnly(XVprocss *pVprocss);
static int SetupModeMax(XVprocss *pVprocss);
/***************** Macros (Inline Functions) Definitions *********************/
/*****************************************************************************/
/**
* This macro reads the subsystem reset network state
*
* @param pReset is a pointer to the Reset IP Block
* @param channel is number of reset channel to work upon
*
* @return Reset state
* -1: Normal
* -0: Reset
*
******************************************************************************/
static __inline u32 XVprocss_GetResetState(XGpio *pReset, u32 channel)
{
return(XGpio_DiscreteRead(pReset, channel));
}
/*****************************************************************************/
/**
* This macro enables the IP's connected to subsystem reset network
*
* @param pReset is a pointer to the Reset IP Block
* @param channel is number of reset channel to work upon
* @param ipBlock is the reset line to be activated
*
* @return None
*
* @note If reset block is not included in the subsystem instance function does
* not do anything
******************************************************************************/
static __inline void XVprocss_EnableBlock(XGpio *pReset, u32 channel, u32 ipBlock)
{
u32 val;
if(pReset)
{
val = XVprocss_GetResetState(pReset, channel);
val |= ipBlock;
XGpio_DiscreteWrite(pReset, channel, val);
}
}
/*****************************************************************************/
/**
* This macro resets the IP connected to subsystem reset network
*
* @param pReset is a pointer to the Reset IP Block
* @param channel is number of reset channel to work upon
* @param ipBlock is the reset line to be asserted
*
* @return None
*
* @note If reset block is not included in the subsystem instance function does
* not do anything
******************************************************************************/
static __inline void XVprocss_ResetBlock(XGpio *pReset, u32 channel, u32 ipBlock)
{
u32 val;
if(pReset)
{
val = XVprocss_GetResetState(pReset, channel);
val &= ~ipBlock;
XGpio_DiscreteWrite(pReset, channel, val);
}
}
/*****************************************************************************/
/**
* 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
*
* @param pVprocss is a pointer to the subsystem instance
* @param msec is delay required
*
* @return None
*
******************************************************************************/
static __inline void WaitUs(XVprocss *pVprocss, u32 MicroSeconds)
{
if(MicroSeconds == 0)
return;
#if defined(__arm__)
/* Wait the requested amount of time. */
usleep(MicroSeconds);
#elif defined(__MICROBLAZE__)
if(pVprocss->UsrDelayUs)
{
/* Use the time handler specified by the user for
* better accuracy
*/
pVprocss->UsrDelayUs(pVprocss->pUsrTmr, MicroSeconds);
}
else
{
/* MicroBlaze sleep only has millisecond accuracy. Round up. */
u32 MilliSeconds = (MicroSeconds + 999) / 1000;
MB_Sleep(MilliSeconds);
}
#endif
}
/************************** Function Definition ******************************/
/*****************************************************************************/
/**
* This function reports list of cores included in Video Processing Subsystem
*
* @param InstancePtr is a pointer to the Subsystem instance.
*
* @return None
*
******************************************************************************/
void XVprocss_ReportCoreInfo(XVprocss *InstancePtr)
{
Xil_AssertVoid(InstancePtr != NULL);
xil_printf("\r\n ->Video Processing Subsystem Cores\r\n");
/* Report all the included cores in the subsystem instance */
if(InstancePtr->hcrsmplr)
{
xil_printf(" : Horiz. Chroma Resampler \r\n");
}
if(InstancePtr->vcrsmplrIn)
{
xil_printf(" : Vert Chroma Resampler - Input\r\n");
}
if(InstancePtr->vcrsmplrOut)
{
xil_printf(" : Vert Chroma Resampler - Output\r\n");
}
if(InstancePtr->hscaler)
{
xil_printf(" : H Scaler\r\n");
}
if(InstancePtr->vscaler)
{
xil_printf(" : V Scaler\r\n");
}
if(InstancePtr->vdma)
{
xil_printf(" : VDMA\r\n");
}
if(InstancePtr->lbox)
{
xil_printf(" : LetterBox\r\n");
}
if(InstancePtr->csc)
{
xil_printf(" : Color Space Converter\r\n");
}
if(InstancePtr->deint)
{
xil_printf(" : Deinterlacer\r\n");
}
if(InstancePtr->rstAxis)
{
xil_printf(" : Reset (AXIS)\r\n");
}
if(InstancePtr->rstAximm)
{
xil_printf(" : Reset (AXI-MM) \r\n");
}
if(InstancePtr->router)
{
xil_printf(" : AXIS Router\r\n");
}
}
/*****************************************************************************/
/**
* This function registers the user defined delay/sleep function with subsystem
*
* @param InstancePtr is a pointer to the Subsystem instance
* @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 CallbackFunc,
void *CallbackRef)
{
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(CallbackFunc != NULL);
Xil_AssertVoid(CallbackRef != NULL);
InstancePtr->UsrDelayUs = CallbackFunc;
InstancePtr->pUsrTmr = CallbackRef;
}
/*****************************************************************************/
/**
* This function queries the subsystem instance configuration to determine
* the included sub-cores. For each sub-core that is present in the design
* the sub-core driver instance is binded with the subsystem sub-core driver
* handle
*
* @param pVprocss is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
******************************************************************************/
static void GetIncludedSubcores(XVprocss *pVprocss)
{
pVprocss->hcrsmplr = ((pVprocss->Config.HCrsmplr.isPresent) \
? (&subcoreRepo.hcrsmplr) : NULL);
pVprocss->vcrsmplrIn = ((pVprocss->Config.VCrsmplrIn.isPresent) \
? (&subcoreRepo.vcrsmplrIn) : NULL);
pVprocss->vcrsmplrOut = ((pVprocss->Config.VCrsmplrOut.isPresent) \
? (&subcoreRepo.vcrsmplrOut) : NULL);
pVprocss->vscaler = ((pVprocss->Config.Vscale.isPresent) \
? (&subcoreRepo.vscaler) : NULL);
pVprocss->hscaler = ((pVprocss->Config.Hscale.isPresent) \
? (&subcoreRepo.hscaler) : NULL);
pVprocss->vdma = ((pVprocss->Config.Vdma.isPresent) \
? (&subcoreRepo.vdma) : NULL);
pVprocss->lbox = ((pVprocss->Config.Lbox.isPresent) \
? (&subcoreRepo.lbox) : NULL);
pVprocss->csc = ((pVprocss->Config.Csc.isPresent) \
? (&subcoreRepo.csc) : NULL);
pVprocss->deint = ((pVprocss->Config.Deint.isPresent) \
? (&subcoreRepo.deint) : NULL);
pVprocss->router = ((pVprocss->Config.Router.isPresent) \
? (&subcoreRepo.router) : NULL);
pVprocss->rstAxis = ((pVprocss->Config.RstAxis.isPresent) \
? (&subcoreRepo.rstAxis) : NULL);
pVprocss->rstAximm = ((pVprocss->Config.RstAximm.isPresent) \
? (&subcoreRepo.rstAximm) : NULL);
}
/*****************************************************************************/
/**
* This function sets the base address of the video frame buffers used by the
* subsystem instance
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param addr is the base address of the video frame buffers
*
* @return None
*
******************************************************************************/
void XVprocss_SetFrameBufBaseaddr(XVprocss *InstancePtr, u32 addr)
{
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(addr != 0);
InstancePtr->FrameBufBaseaddr = addr;
}
/*****************************************************************************/
/**
* This function initializes the video subsystem and included sub-cores.
* This function must be called prior to using the subsystem. Initialization
* includes setting up the instance data for top level as well as all included
* sub-core therein, and ensuring the hardware is in a known stable state.
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param CfgPtr points to the configuration structure associated with the
* subsystem instance.
* @param EffectiveAddr is the base address of the device. If address
* translation is being used, then this parameter must reflect the
* virtual base address. Otherwise, the physical address should be
* used.
*
* @return XST_SUCCESS if initialization is successful else XST_FAILURE
*
******************************************************************************/
int XVprocss_CfgInitialize(XVprocss *InstancePtr, XVprocss_Config *CfgPtr,
u32 EffectiveAddr)
{
XVprocss *pVprocss = InstancePtr;
XAxiVdma_Config *VdmaCfgPtr;
int status;
u32 AbsAddr;
/* Verify arguments */
Xil_AssertNonvoid(pVprocss != NULL);
Xil_AssertNonvoid(CfgPtr != NULL);
Xil_AssertNonvoid(EffectiveAddr != (u32)NULL);
/* Setup the instance */
memcpy((void *)&(pVprocss->Config), (const void *)CfgPtr, sizeof(XVprocss_Config));
pVprocss->Config.BaseAddress = EffectiveAddr;
switch(pVprocss->Config.Topology)
{
case XVPROCSS_TOPOLOGY_FULL_FLEDGED:
xdbg_printf(XDBG_DEBUG_GENERAL," [Subsystem Configuration Mode - Full]\r\n\r\n");
break;
case XVPROCSS_TOPOLOGY_SCALER_ONLY:
xdbg_printf(XDBG_DEBUG_GENERAL," [Subsystem Configuration Mode - Scaler-Only]\r\n\r\n");
break;
default:
xil_printf("ERROR: Subsystem Configuration Mode Not Supported. \r\n");
return(XST_FAILURE);
}
/* Determine sub-cores included in the provided instance of subsystem */
GetIncludedSubcores(pVprocss);
/* Initialize all included sub_cores */
if(pVprocss->rstAxis)
{
if(XVprocss_SubcoreInitResetAxis(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->rstAximm)
{
if(XVprocss_SubcoreInitResetAximm(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
/*
* Make sure AXI-MM interface is not in reset. If in reset it will prevent
* Deinterlacer from being initialized
*/
XVprocss_EnableBlock(InstancePtr->rstAximm, GPIO_CH_RESET_SEL, RESET_MASK_IP_AXIMM);
}
if(pVprocss->router)
{
if(XVprocss_SubcoreInitRouter(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->csc)
{
if(XVprocss_SubcoreInitCsc(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->hscaler)
{
if(XVprocss_SubcoreInitHScaler(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->vscaler)
{
if(XVprocss_SubcoreInitVScaler(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->hcrsmplr)
{
if(XVprocss_SubcoreInitHCrsmplr(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->vcrsmplrIn)
{
if(XVprocss_SubcoreInitVCrsmpleIn(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->vcrsmplrOut)
{
if(XVprocss_SubcoreInitVCrsmpleOut(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->lbox)
{
if(XVprocss_SubcoreInitLetterbox(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
}
if(pVprocss->vdma)
{
if(XVprocss_SubcoreInitVdma(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
if(pVprocss->FrameBufBaseaddr == 0)
{
xil_printf("\r\nVPROCSS ERR:: Video Frame Buffer base address not set\r\n");
xil_printf(" Use XVprocss_SetFrameBufBaseaddr() API before subsystem init\r\n\r\n");
return(XST_FAILURE);
}
}
if(pVprocss->deint)
{
if(XVprocss_SubcoreInitDeinterlacer(pVprocss) != XST_SUCCESS)
{
return(XST_FAILURE);
}
/* Set Deinterlacer buffer offset in allocated DDR Frame Buffer */
if(pVprocss->vdma) //vdma must be present for this to work
{
u32 vdmaBufReq, bufsize;
u32 Bpp; //bytes per pixel
Bpp = (pVprocss->Config.ColorDepth + 7)/8;
//compute buffer size based on subsystem configuration
//For 1 4K2K buffer (YUV444 16-bit) size is ~48MB
bufsize = pVprocss->Config.MaxWidth *
pVprocss->Config.MaxHeight *
pVprocss->Config.NumVidComponents *
Bpp;
//VDMA requires 4 buffers for total size of ~190MB
vdmaBufReq = pVprocss->vdma->MaxNumFrames * bufsize;
/*
* vdmaBufReq = 0x0BDD 80000
* padBuf = 0x02F7 6000 (1 buffer is added as pad between vdma and deint)
* -------------
* DeInt Offst= 0x0ED4 E000
* -------------
*/
/* Set Deint Buffer Address Offset */
pVprocss->idata.deintBufAddr = pVprocss->FrameBufBaseaddr + vdmaBufReq + bufsize;
}
else
{
xil_printf("\r\nVPROCSS ERR:: VDMA IP not found. Unable to assign De-interlacer buffer offsets\r\n");
return(XST_FAILURE);
}
}
return(XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function initializes the subsystem to power on default state. Subsystem
* device id is used to access the HW configuration for the instance.
* This configuration is then initialized along with any sub-cores included.
* As the last step the internal state of the subsystem is set to pre-defined
* power up default and Subsystem Ready state is set
*
* @param InstancePtr is the pointer to subsystem instance
* @param DeviceId is the unique device ID of the device for the lookup operation.
*
* @return XST_SUCCESS if successful
* XST_DEVICE_NOT_FOUND if no device match is found.
* XST_FAILURE otherwise
*
*******************************************************************************/
int XVprocss_PowerOnInit(XVprocss *InstancePtr, u32 DeviceId)
{
XVprocss_Config *ConfigPtr;
int status;
Xil_AssertNonvoid(InstancePtr != NULL);
ConfigPtr = XVprocss_LookupConfig(DeviceId);
if(ConfigPtr == NULL)
{
InstancePtr->IsReady = 0;
return (XST_DEVICE_NOT_FOUND);
}
//Initialize top level and all included sub-cores
status = XVprocss_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddress);
if(status != XST_SUCCESS)
{
xil_printf("ERR:: Video Processing Subsystem Initialization failed %d\r\n", status);
return(XST_FAILURE);
}
/* All sub-cores static configuration extracted. Next configure subsystem to
* power on default state
*/
SetPODConfiguration(InstancePtr);
/* Reset the hardware and set the flag to indicate the
subsystem is ready
*/
XVprocss_Reset(InstancePtr);
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
return(XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function configures the Video Processing subsystem internal blocks
* to power on default configuration
*
* @param pVprocss is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
******************************************************************************/
static void SetPODConfiguration(XVprocss *pVprocss)
{
XVidC_VideoStream vidStrmIn;
XVidC_VideoStream vidStrmOut;
XVidC_VideoWindow win;
u16 PixPrecisionIndex;
/* Setup Default Output Stream configuration */
vidStrmOut.VmId = XVIDC_VM_1920x1080_60_P;
vidStrmOut.ColorFormatId = XVIDC_CSF_RGB;
vidStrmOut.FrameRate = XVIDC_FR_60HZ;
vidStrmOut.IsInterlaced = FALSE;
vidStrmOut.ColorDepth = pVprocss->Config.ColorDepth;
vidStrmOut.PixPerClk = pVprocss->Config.PixPerClock;
/* Setup Default Input Stream configuration */
vidStrmIn.VmId = XVIDC_VM_1920x1080_60_P;
vidStrmIn.ColorFormatId = XVIDC_CSF_RGB;
vidStrmIn.FrameRate = XVIDC_FR_60HZ;
vidStrmIn.IsInterlaced = FALSE;
vidStrmIn.ColorDepth = pVprocss->Config.ColorDepth;
vidStrmIn.PixPerClk = pVprocss->Config.PixPerClock;
/* Setup Video Processing subsystem input/output configuration */
XVprocss_SetVidStreamIn(pVprocss, &vidStrmIn);
XVprocss_SetVidStreamOut(pVprocss, &vidStrmOut);
/* compute data width supported by vdma */
pVprocss->idata.PixelWidthInBits = pVprocss->Config.NumVidComponents *
pVprocss->VidIn.ColorDepth;
switch(pVprocss->Config.PixPerClock)
{
case XVIDC_PPC_1:
case XVIDC_PPC_2:
if(pVprocss->Config.ColorDepth == XVIDC_BPC_10)
{
/* Align the bit width to next byte boundary for this particular case
* Num_Channel Color Depth PixelWidth Align
* ----------------------------------------------------
* 2 10 20 24
* 3 10 30 32
*
* HW will do the bit padding for 20->24 and 30->32
*/
pVprocss->idata.PixelWidthInBits = ((pVprocss->idata.PixelWidthInBits + 7)/8)*8;
}
break;
default:
break;
}
/* Setup Pixel Step size for define HW configuration */
switch(pVprocss->Config.ColorDepth)
{
case XVIDC_BPC_8: PixPrecisionIndex = 0; break;
case XVIDC_BPC_10: PixPrecisionIndex = 1; break;
case XVIDC_BPC_12: PixPrecisionIndex = 2; break;
case XVIDC_BPC_16: PixPrecisionIndex = 3; break;
default: break;
}
pVprocss->idata.PixelHStepSize = XVprocss_PixelHStep[pVprocss->Config.PixPerClock>>1][PixPrecisionIndex];
if(XVprocss_IsConfigModeMax(pVprocss))
{
/* Set default Zoom Window */
win.Width = 400;
win.Height = 400;
win.StartX = win.StartY = 0;
XVprocss_SetZoomPipWindow(pVprocss,
XVPROCSS_ZOOM_WIN,
&win);
/* Set default PIP Window */
XVprocss_SetZoomPipWindow(pVprocss,
XVPROCSS_PIP_WIN,
&win);
}
/* Release reset before programming any IP Block */
XVprocss_EnableBlock(pVprocss->rstAxis, GPIO_CH_RESET_SEL, RESET_MASK_ALL_BLOCKS);
/* User parameter configuration */
/* Set default background color for Letter Box */
if(pVprocss->lbox)
{
XV_LboxSetBackgroundColor(pVprocss->lbox,
XLBOX_BKGND_BLACK,
pVprocss->VidOut.ColorFormatId,
pVprocss->VidOut.ColorDepth);
}
/* Initialize CSC sub-core layer 2 driver. This block has FW register map */
if(pVprocss->csc)
{
XV_CscInitPowerOnDefault(&pVprocss->cscL2Reg);
XV_CscSetColorDepth((&pVprocss->cscL2Reg), vidStrmIn.ColorDepth);
}
}
/****************************************************************************/
/**
* This function starts the video subsystem including all sub-cores that are
* included in the processing pipeline for a given use-case. Video pipe is
* started from back to front
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
* @note Cores are started only if the corresponding start flag in the scratch
* pad memory is set. This allows to selectively start only those cores
* included in the processing chain
******************************************************************************/
void XVprocss_Start(XVprocss *InstancePtr)
{
u8 *pStartCore;
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
pStartCore = &InstancePtr->idata.startCore[0];
xdbg_printf(XDBG_DEBUG_GENERAL," ->Start Video Processing Subsystem.... \r\n");
if(pStartCore[XVPROCSS_RTR_CR_V_OUT])
XV_VCrsmplStart(InstancePtr->vcrsmplrOut);
if(pStartCore[XVPROCSS_RTR_CR_H])
XV_HCrsmplStart(InstancePtr->hcrsmplr);
if(pStartCore[XVPROCSS_RTR_CSC])
XV_CscStart(InstancePtr->csc);
if(pStartCore[XVPROCSS_RTR_LBOX])
XV_LBoxStart(InstancePtr->lbox);
if(pStartCore[XVPROCSS_RTR_SCALER_H])
XV_HScalerStart(InstancePtr->hscaler);
if(pStartCore[XVPROCSS_RTR_SCALER_V])
XV_VScalerStart(InstancePtr->vscaler);
if(pStartCore[XVPROCSS_RTR_VDMA])
XVprocss_VdmaStartTransfer(InstancePtr->vdma);
if(pStartCore[XVPROCSS_RTR_DEINT])
XV_DeintStart(InstancePtr->deint);
if(pStartCore[XVPROCSS_RTR_CR_V_IN])
XV_VCrsmplStart(InstancePtr->vcrsmplrIn);
/* Subsystem ready to accept axis - Enable Video Input */
XVprocss_EnableBlock(InstancePtr->rstAxis, GPIO_CH_RESET_SEL, RESET_MASK_VIDEO_IN);
}
/*****************************************************************************/
/**
* This function stops the video subsystem including all sub-cores
* Stop the video pipe starting from front to back
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
******************************************************************************/
void XVprocss_Stop(XVprocss *InstancePtr)
{
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
xdbg_printf(XDBG_DEBUG_GENERAL," ->Stop Video Processing Subsystem.... \r\n");
if(InstancePtr->vcrsmplrIn)
XV_VCrsmplStop(InstancePtr->vcrsmplrIn);
if(InstancePtr->deint)
XV_DeintStop(InstancePtr->deint);
if(InstancePtr->vdma)
XVprocss_VdmaStop(InstancePtr->vdma);
if(InstancePtr->vscaler)
XV_VScalerStop(InstancePtr->vscaler);
if(InstancePtr->hscaler)
XV_HScalerStop(InstancePtr->hscaler);
if(InstancePtr->lbox)
XV_LBoxStop(InstancePtr->lbox);
if(InstancePtr->csc)
XV_CscStop(InstancePtr->csc);
if(InstancePtr->hcrsmplr)
XV_HCrsmplStop(InstancePtr->hcrsmplr);
if(InstancePtr->vcrsmplrOut)
XV_VCrsmplStop(InstancePtr->vcrsmplrOut);
}
/*****************************************************************************/
/**
* This function resets the video subsystem sub-cores. There are 2 reset
* networks within the subsystem
* - For cores that are on AXIS interface
* - For cores that are on AXI-MM interface
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
******************************************************************************/
void XVprocss_Reset(XVprocss *InstancePtr)
{
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
xdbg_printf(XDBG_DEBUG_GENERAL," ->Reset Video Processing Subsystem.... \r\n");
/* Soft Reset */
XVprocss_VdmaReset(InstancePtr->vdma);
/* Reset All IP Blocks on AXIS interface*/
XVprocss_ResetBlock(InstancePtr->rstAxis, GPIO_CH_RESET_SEL, RESET_MASK_ALL_BLOCKS);
/* Reset All IP Blocks on AXI-MM interface*/
// XVprocss_ResetBlock(InstancePtr->rstAximm, GPIO_CH_RESET_SEL, RESET_MASK_IP_AXIMM);
/* If enabled, Stop AXI-MM traffic */
if((InstancePtr->deint) && (InstancePtr->idata.startCore[XVPROCSS_RTR_DEINT]))
{
XV_DeintStop(InstancePtr->deint);
}
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.
* Release IP reset - but hold vid_in in reset
*/
// 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);
WaitUs(InstancePtr, 1000); /* wait 1ms for AXIS to stabilize */
/* Reset start core flags */
memset(InstancePtr->idata.startCore, 0, sizeof(InstancePtr->idata.startCore));
}
/*****************************************************************************/
/**
* This function configures the video subsystem input interface
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param StrmIn is the pointer to input stream configuration
*
* @return XST_SUCESS if successful else XST_FAILURE
*
******************************************************************************/
int XVprocss_SetVidStreamIn(XVprocss *InstancePtr,
const XVidC_VideoStream *StrmIn)
{
int status;
/* Verify arguments */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(StrmIn != NULL);
/* Set Timing information based on resolution ID */
status = XVprocss_SetStreamResolution(&InstancePtr->VidIn, StrmIn->VmId);
if(!status)
{
InstancePtr->VidIn.ColorFormatId = StrmIn->ColorFormatId;
InstancePtr->VidIn.ColorDepth = StrmIn->ColorDepth;
InstancePtr->VidIn.PixPerClk = StrmIn->PixPerClk;
InstancePtr->VidIn.FrameRate = StrmIn->FrameRate;
InstancePtr->VidIn.IsInterlaced = StrmIn->IsInterlaced;
}
return(status);
}
/*****************************************************************************/
/**
* This function configures the video subsystem output interface
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param StrmOut is the pointer to input stream configuration
*
* @return XST_SUCESS if successful else XST_FAILURE
*
******************************************************************************/
int XVprocss_SetVidStreamOut(XVprocss *InstancePtr,
const XVidC_VideoStream *StrmOut)
{
int status;
/* Verify arguments */
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(StrmOut != NULL);
/* Set Timing information based on resolution ID */
status = XVprocss_SetStreamResolution(&InstancePtr->VidOut, StrmOut->VmId);
if(!status)
{
InstancePtr->VidOut.ColorFormatId = StrmOut->ColorFormatId;
InstancePtr->VidOut.ColorDepth = StrmOut->ColorDepth;
InstancePtr->VidOut.PixPerClk = StrmOut->PixPerClk;
InstancePtr->VidOut.FrameRate = StrmOut->FrameRate;
InstancePtr->VidOut.IsInterlaced = StrmOut->IsInterlaced;
}
return(status);
}
/*****************************************************************************/
/**
* This function validates the video mode id against the supported resolutions
* and if successful extracts the timing information for the mode
*
* @param StreamPtr is a pointer to the video stream to be configured
* @param VmId is the Video Mode ID of the new resolution to be set
* @return XST_SUCESS if successful else XST_FAILURE
*
******************************************************************************/
int XVprocss_SetStreamResolution(XVidC_VideoStream *StreamPtr,
const XVidC_VideoMode VmId)
{
int status;
/* Verify arguments */
Xil_AssertNonvoid(StreamPtr != NULL);
if(VmId < XVIDC_VM_NUM_SUPPORTED)
{
XVidC_VideoTiming const *pResTiming = XVidC_GetTimingInfo(VmId);
StreamPtr->VmId = VmId;
memcpy(&StreamPtr->Timing, pResTiming, sizeof(XVidC_VideoTiming));
status = XST_SUCCESS;
}
else
{
xil_printf("\r\nVPROCSS ERR:: Stream Resolution Not Supported. Command Ignored\r\n");
status = XST_FAILURE;
}
return(status);
}
/*****************************************************************************/
/**
* This function updates the Pip/Zoom window currently on screen in-place.
* This implies the video is not blanked and the new coordinates will update
* instantly as the function executes
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
* @note This function must be called only after the respective mode (PIP/Zoom)
* has been enabled and user wants to move window to a new location
* This function is not applicable in Subsystem Stream Mode Configuration
*
******************************************************************************/
void XVprocss_UpdateZoomPipWindow(XVprocss *InstancePtr)
{
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
if(XVprocss_IsConfigModeMax(InstancePtr))
{
/* send vdma update window to IP */
if(XVprocss_IsPipModeOn(InstancePtr))
{
XVprocss_VdmaSetWinToDnScaleMode(InstancePtr, XVPROCSS_VDMA_UPDATE_WR_CH);
}
else
{
XVprocss_VdmaSetWinToUpScaleMode(InstancePtr, XVPROCSS_VDMA_UPDATE_RD_CH);
}
XVprocss_VdmaStartTransfer(InstancePtr->vdma);
/*
* Final output of Video Processing subsystem goes via LBox IP
* Program the output resolution window
*/
if(XVprocss_IsPipModeOn(InstancePtr))
{
XV_LBoxSetActiveWin(InstancePtr->lbox,
&InstancePtr->idata.wrWindow,
InstancePtr->VidOut.Timing.HActive,
InstancePtr->VidOut.Timing.VActive);
}
}
else //Scaler Only Config
{
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\nVPROCSS ERR:: Feature not supported in Streaming Mode\r\n");
}
}
/*****************************************************************************/
/**
* This function allows user to set the Zoom or PIP window. Scratch pad memory
* is updated with the new window information
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param mode is feature to be updated PIP or ZOOM
* @param win is structure that contains window coordinates and size
*
* @return None
*
* @note For Zoom mode RD client window is written in scratch pad memory
* For Pip mode WR client window is written in scratch pad memory
* This function is not applicable in Subsystem Stream Mode Configuration
*
******************************************************************************/
void XVprocss_SetZoomPipWindow(XVprocss *InstancePtr,
XVprocss_Win mode,
XVidC_VideoWindow *win)
{
u16 wordlen;
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(win != NULL);
if(XVprocss_IsConfigModeMax(InstancePtr))
{
if(mode == XVPROCSS_ZOOM_WIN)
{
/* check if DMA includes DRE. If not then auto-align to selected bus width */
if(!InstancePtr->vdma->ReadChannel.HasDRE)
{
wordlen = InstancePtr->idata.PixelHStepSize-1;
win->StartX = ((win->StartX + wordlen) & ~(wordlen));
win->Width = ((win->Width + wordlen) & ~(wordlen));
}
//VDMA RD Client
InstancePtr->idata.rdWindow.StartX = win->StartX;
InstancePtr->idata.rdWindow.StartY = win->StartY;
InstancePtr->idata.rdWindow.Width = win->Width;
InstancePtr->idata.rdWindow.Height = win->Height;
}
else //PIP
{
/* check if DMA does not have DRE then auto-align */
if(!InstancePtr->vdma->WriteChannel.HasDRE)
{
wordlen = InstancePtr->idata.PixelHStepSize-1;
win->StartX = ((win->StartX + wordlen) & ~(wordlen));
win->Width = ((win->Width + wordlen) & ~(wordlen));
}
//VDMA WR Client
InstancePtr->idata.wrWindow.StartX = win->StartX;
InstancePtr->idata.wrWindow.StartY = win->StartY;
InstancePtr->idata.wrWindow.Width = win->Width;
InstancePtr->idata.wrWindow.Height = win->Height;
}
}
else //Scaler Only Config
{
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\nVPROCSS ERR:: Feature not supported in Streaming Mode\r\n");
}
}
/*****************************************************************************/
/**
* This function reads the user defined Zoom/Pip window from scratch pad memory
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param mode is feature (PIP or ZOOM) whose window coordinates are to be
* retrieved
* @param win is structure that will contain read window coordinates and size
*
** @note For Zoom mode RD client window is read from scratch pad memory
* For Pip mode WR client window is read from scratch pad memory
* This function is not applicable in Subsystem Stream Mode Configuration
*
******************************************************************************/
void XVprocss_GetZoomPipWindow(XVprocss *InstancePtr,
XVprocss_Win mode,
XVidC_VideoWindow *win)
{
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(win != NULL);
if(XVprocss_IsConfigModeMax(InstancePtr))
{
if(mode == XVPROCSS_ZOOM_WIN)
{
win->StartX = InstancePtr->idata.rdWindow.StartX;
win->StartY = InstancePtr->idata.rdWindow.StartY;
win->Width = InstancePtr->idata.rdWindow.Width;
win->Height = InstancePtr->idata.rdWindow.Height;
}
else //PIP
{
win->StartX = InstancePtr->idata.wrWindow.StartX;
win->StartY = InstancePtr->idata.wrWindow.StartY;
win->Width = InstancePtr->idata.wrWindow.Width;
win->Height = InstancePtr->idata.wrWindow.Height;
}
}
else //Scaler Only Config
{
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\nVPROCSS ERR:: Feature not supported in Streaming Mode\r\n");
}
}
/*****************************************************************************/
/**
* This function configures the video subsystem to enable/disable ZOOM feature
* If ZOOM mode is set to ON but user has not set window coordinates then
* quarter of input stream resolution at coordinates 0,0 is set as the default
* zoom window
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param OnOff is the action required
*
* @return None
*
* @note User must call XVprocss_ConfigureSubsystem() for change to take effect
* This call has not been added here such that it provides an opportunity
* to make the change during vertical blanking at system level. This
* behavior will change once shadow register support is available in
* sub-core IP's
* This function is not applicable in Subsystem Stream Mode Configuration
*
******************************************************************************/
void XVprocss_SetZoomMode(XVprocss *InstancePtr, u8 OnOff)
{
char *status[] = {"OFF","ON"};
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
if(XVprocss_IsConfigModeMax(InstancePtr))
{
InstancePtr->idata.ZoomEn = OnOff;
InstancePtr->idata.PipEn = FALSE;
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\n :ZOOM Mode %s \r\n", status[InstancePtr->idata.ZoomEn]);
}
else //Scaler Only Config
{
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\nVPROCSS ERR:: Feature not supported in Streaming Mode\r\n");
}
}
/*****************************************************************************/
/**
* This function configures the video subsystem to enable/disable PIP feature
* If PIP mode is set to ON but user has not set window coordinates then
* half of input stream resolution at coordinates 0,0 is set as the default
* zoom window
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
* @param OnOff is the action required
*
* @return None
*
* @note User must call XVprocss_ConfigureSubsystem() for change to take effect
* This call has not been added here such that it provides an opportunity
* to make the change during vertical blanking at system level. This
* behavior will change once shadow register support is available in
* sub-core IP's
* This function is not applicable in Subsystem Stream Mode Configuration
*
******************************************************************************/
void XVprocss_SetPipMode(XVprocss *InstancePtr, u8 OnOff)
{
char *status[] = {"OFF","ON"};
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
if(XVprocss_IsConfigModeMax(InstancePtr))
{
InstancePtr->idata.PipEn = OnOff;
InstancePtr->idata.ZoomEn = FALSE;
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\n :PIP Mode %s \r\n", status[InstancePtr->idata.PipEn]);
}
else //Scaler Only Config
{
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\nVPROCSS ERR:: Feature not supported in Streaming Mode\r\n");
}
}
/*****************************************************************************/
/**
* This function validates the input and output stream configuration for scaler
* only configuration
*
* @param pStrmIn is a pointer to the input stream
* @param pStrmOut is a pointer to the output stream
*
* @return XST_SUCCESS if successful else XST_FAILURE
*
* @note This function is applicable only for Stream mode configuration of the
* subsystem. In this mode very limited functionality is available
******************************************************************************/
static int ValidateScalerOnlyConfig(XVidC_VideoStream *pStrmIn,
XVidC_VideoStream *pStrmOut)
{
if(pStrmIn->ColorFormatId == XVIDC_CSF_YCRCB_420)
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR: YUV420 Input not supported\r\n");
return(XST_FAILURE);
}
if(pStrmIn->ColorFormatId != pStrmOut->ColorFormatId)
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR: Input & Output Stream Color Format different\r\n");
return(XST_FAILURE);
}
if(pStrmIn->ColorDepth != pStrmOut->ColorDepth)
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR: Input & Output Color Depth different\r\n");
return(XST_FAILURE);
}
return(XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function configures the video subsystem pipeline for ScalerOnly
* topology of the subsystem
*
* @param pVprocss is a pointer to the Subsystem instance to be worked on.
*
* @return XST_SUCCESS if successful else XST_FAILURE
*
* @note If use case is possible the subsystem will configure the sub-cores
* accordingly else will ignore the request
*
******************************************************************************/
static int SetupModeScalerOnly(XVprocss *pVprocss)
{
u32 vsc_WidthIn, vsc_HeightIn, vsc_HeightOut;
u32 hsc_HeightIn, hsc_WidthIn, hsc_WidthOut;
int status = XST_SUCCESS;
vsc_WidthIn = vsc_HeightIn = vsc_HeightOut = 0;
hsc_HeightIn = hsc_WidthIn = hsc_WidthOut = 0;
if((!pVprocss->vscaler) || (!pVprocss->hscaler))
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: Scaler IP not found\r\n");
return(XST_FAILURE);
}
/* check if input/output stream configuration is supported */
status = ValidateScalerOnlyConfig(&pVprocss->VidIn,
&pVprocss->VidOut);
if(status == XST_SUCCESS)
{
/* Reset All IP Blocks */
XVprocss_Reset(pVprocss);
/* UpScale mode V Scaler is before H Scaler */
vsc_WidthIn = pVprocss->VidIn.Timing.HActive;
vsc_HeightIn = pVprocss->VidIn.Timing.VActive;
vsc_HeightOut = pVprocss->VidOut.Timing.VActive;
hsc_WidthIn = vsc_WidthIn;
hsc_HeightIn = vsc_HeightOut;
hsc_WidthOut = pVprocss->VidOut.Timing.HActive;
/* Configure scaler to scale input to output resolution */
xdbg_printf(XDBG_DEBUG_GENERAL," -> Configure VScaler for %dx%d to %dx%d\r\n", \
(int)vsc_WidthIn, (int)vsc_HeightIn, (int)vsc_WidthIn, (int)vsc_HeightOut);
XV_VScalerSetup(pVprocss->vscaler,
&pVprocss->vscL2Reg,
vsc_WidthIn,
vsc_HeightIn,
vsc_HeightOut);
xdbg_printf(XDBG_DEBUG_GENERAL," -> Configure HScaler for %dx%d to %dx%d\r\n", \
(int)hsc_WidthIn, (int)hsc_HeightIn, (int)hsc_WidthOut, (int)hsc_HeightIn);
XV_HScalerSetup(pVprocss->hscaler,
&pVprocss->hscL2Reg,
hsc_HeightIn,
hsc_WidthIn,
hsc_WidthOut,
pVprocss->VidIn.ColorFormatId);
/* Start Scaler sub-cores */
XV_HScalerStart(pVprocss->hscaler);
XV_VScalerStart(pVprocss->vscaler);
/* Subsystem Ready to accept input stream - Enable Video Input */
XVprocss_EnableBlock(pVprocss->rstAxis, GPIO_CH_RESET_SEL, RESET_MASK_VIDEO_IN);
}
else
{
xdbg_printf(XDBG_DEBUG_GENERAL,"\r\n-->Command Ignored<--\r\n");
}
return(status);
}
/*****************************************************************************/
/**
* This function configures the video subsystem pipeline for Maximum
* (Full_Fledged) topology
*
* @param pVprocss is a pointer to the Subsystem instance to be worked on.
*
* @return XST_SUCCESS if successful else XST_FAILURE
*
******************************************************************************/
static int SetupModeMax(XVprocss *pVprocss)
{
int status;
/* Build Routing table */
status = XVprocss_BuildRoutingTable(pVprocss);
if(status == XST_SUCCESS)
{
/* Reset All IP Blocks */
XVprocss_Reset(pVprocss);
/* Set AXI Switch registers */
XVprocss_ProgRouterMux(pVprocss);
/* program use case */
XVprocss_SetupRouterDataFlow(pVprocss);
}
else
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR: Subsystem Routing Table Invalid");
xdbg_printf(XDBG_DEBUG_GENERAL,"- Ignoring Configuration Request\r\n");
}
return(status);
}
/*****************************************************************************/
/**
* This function validates the input and output stream configuration against the
* Subsystem hardware capabilities
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return XST_SUCCESS if successful else XST_FAILURE
*
******************************************************************************/
static int ValidateSubsystemConfig(XVprocss *InstancePtr)
{
XVidC_VideoStream *StrmIn = &InstancePtr->VidIn;
XVidC_VideoStream *StrmOut = &InstancePtr->VidOut;
/* Runtime Color Depth conversion not supported
* Always overwrite input/output stream color depth with subsystem setting
*/
StrmIn->ColorDepth = InstancePtr->Config.ColorDepth;
StrmOut->ColorDepth = InstancePtr->Config.ColorDepth;
/* Runtime Pixel/Clock conversion not supported
* Always overwrite input/output stream pixel/clk with subsystem setting
*/
StrmIn->PixPerClk = InstancePtr->Config.PixPerClock;
StrmOut->PixPerClk = InstancePtr->Config.PixPerClock;
/* Check Stream Width is aligned at Samples/Clock boundary */
if(((StrmIn->Timing.HActive % InstancePtr->Config.PixPerClock) != 0) ||
((StrmOut->Timing.HActive % InstancePtr->Config.PixPerClock) != 0))
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: Input/Output Width not aligned with Samples/Clk\r\n");
return(XST_FAILURE);
}
/* Check if Subsystem HW Configuration can process requested resolution*/
if(((StrmIn->PixPerClk == XVIDC_PPC_1) && (StrmIn->VmId > XVIDC_VM_3840x2160_30_P))||
((StrmOut->PixPerClk == XVIDC_PPC_1) && (StrmOut->VmId > XVIDC_VM_3840x2160_30_P)))
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: 1 Sample/Clk can support Max resolution of 4K2K@30Hz \r\n");
return(XST_FAILURE);
}
/* Check for YUV422 In/Out stream width is even */
if(((StrmIn->ColorFormatId == XVIDC_CSF_YCRCB_422) && ((StrmIn->Timing.HActive % 2) != 0)) ||
((StrmOut->ColorFormatId == XVIDC_CSF_YCRCB_422) && ((StrmOut->Timing.HActive % 2) != 0)))
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: YUV422 stream width must be even\r\n");
return(XST_FAILURE);
}
/* Check for YUV420 In stream width and height is even */
if(StrmIn->ColorFormatId == XVIDC_CSF_YCRCB_420)
{
if(InstancePtr->vcrsmplrIn)
{
if(((StrmIn->Timing.HActive % 2) != 0) && ((StrmIn->Timing.VActive % 2) != 0))
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: YUV420 input stream width and height must be even\r\n");
return(XST_FAILURE);
}
}
else
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: Vertical Chroma Resampler IP not found. YUV420 Input not supported\r\n");
return(XST_FAILURE);
}
}
/* Check for YUV420 out stream width and height is even */
if(StrmOut->ColorFormatId == XVIDC_CSF_YCRCB_420)
{
if(InstancePtr->vcrsmplrOut)
{
if(((StrmOut->Timing.HActive % 2) != 0) && ((StrmOut->Timing.VActive % 2) != 0))
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: YUV420 output stream width and height must be even\r\n");
return(XST_FAILURE);
}
}
else
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: Vertical Chroma Resampler IP not found. YUV420 Output not supported\r\n");
return(XST_FAILURE);
}
}
/* Check for Interlaced input limitation */
if(StrmIn->IsInterlaced)
{
if(StrmIn->ColorFormatId == XVIDC_CSF_YCRCB_420)
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: Interlaced YUV420 stream not supported\r\n");
return(XST_FAILURE);
}
if(!InstancePtr->deint)
{
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR:: Interlaced input not supported\r\n");
return(XST_FAILURE);
}
}
return(XST_SUCCESS);
}
/*****************************************************************************/
/**
* This function is the entry point into the video processing subsystem driver
* processing path. It will examine the instantiated subsystem configuration mode
* and the input and output stream configuration. Based on the available
* information control flow is determined and requisite sub-cores are configured
* to implement the supported use case
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return XST_SUCCESS if successful else XST_FAILURE
*
******************************************************************************/
int XVprocss_SetSubsystemConfig(XVprocss *InstancePtr)
{
int status = XST_SUCCESS;
/* Verify arguments */
Xil_AssertNonvoid(InstancePtr != NULL);
#ifdef DEBUG
xil_printf("\r\n****** VPROC SUBSYSTEM INPUT/OUTPUT CONFIG ******\r\n");
xil_printf("->INPUT\r\n");
XVidC_ReportStreamInfo(&InstancePtr->VidIn);
xil_printf("\r\n->OUTPUT\r\n");
XVidC_ReportStreamInfo(&InstancePtr->VidOut);
xil_printf("**************************************************\r\n\r\n");
#endif
/* validate subsystem configuration */
if(ValidateSubsystemConfig(InstancePtr) != XST_SUCCESS)
{
return(XST_FAILURE);
}
switch(InstancePtr->Config.Topology)
{
case XVPROCSS_TOPOLOGY_FULL_FLEDGED:
status = SetupModeMax(InstancePtr);
break;
case XVPROCSS_TOPOLOGY_SCALER_ONLY:
//Only configuration supported is V->H
status = SetupModeScalerOnly(InstancePtr);
break;
default:
xdbg_printf(XDBG_DEBUG_GENERAL,"VPROCSS ERR: Subsystem Configuration Mode Not Supported. \r\n");
status = XST_FAILURE;
break;
}
return(status);
}
/*****************************************************************************/
/**
* This function reports the subsystem HW and input/output stream configuration
*
* @param InstancePtr is a pointer to the Subsystem instance to be worked on.
*
* @return None
*
******************************************************************************/
void XVprocss_ReportSubsystemConfig(XVprocss *InstancePtr)
{
char *topology[2] = {"Scaler-Only", "Full-Fledged"};
XVidC_VideoWindow win;
/* Verify arguments */
Xil_AssertVoid(InstancePtr != NULL);
xil_printf("\r\n****** Video Processing Subsystem Configuration ******\r\n");
/* Print the configuration selected */
if(InstancePtr->Config.Topology <= XVPROCSS_TOPOLOGY_FULL_FLEDGED)
{
xil_printf("\r\nTopology: %s\r\n", topology[InstancePtr->Config.Topology]);
XVprocss_ReportCoreInfo(InstancePtr);
}
else
{
xil_printf("VPROCSS ERR:: Unknown Topology\r\n");
return;
}
xil_printf("\r\nPixels/Clk = %d\r\n", InstancePtr->Config.PixPerClock);
xil_printf("Color Depth = %d\r\n", InstancePtr->Config.ColorDepth);
xil_printf("Num Video Components = %d\r\n", InstancePtr->Config.NumVidComponents);
xil_printf("Max Width Supported = %d\r\n", InstancePtr->Config.MaxWidth);
xil_printf("Max Height Supported = %d\r\n", InstancePtr->Config.MaxHeight);
xil_printf("\r\n------ SUBSYSTEM INPUT/OUTPUT CONFIG ------\r\n");
xil_printf("->INPUT\r\n");
XVidC_ReportStreamInfo(&InstancePtr->VidIn);
xil_printf("\r\n->OUTPUT\r\n");
XVidC_ReportStreamInfo(&InstancePtr->VidOut);
if(XVprocss_IsConfigModeMax(InstancePtr))
{
if(XVprocss_IsZoomModeOn(InstancePtr))
{
xil_printf("\r\nZoom Mode: ON\r\n");
XVprocss_GetZoomPipWindow(InstancePtr, XVPROCSS_ZOOM_WIN, &win);
xil_printf(" Start X = %d\r\n", win.StartX);
xil_printf(" Start Y = %d\r\n", win.StartY);
xil_printf(" Win Width = %d\r\n", win.Width);
xil_printf(" Win Height = %d\r\n", win.Height);
}
else
{
xil_printf("\r\nZoom Mode: OFF\r\n");
}
if(XVprocss_IsPipModeOn(InstancePtr))
{
xil_printf("\r\nPip Mode: ON\r\n");
XVprocss_GetZoomPipWindow(InstancePtr, XVPROCSS_PIP_WIN, &win);
xil_printf(" Start X = %d\r\n", win.StartX);
xil_printf(" Start Y = %d\r\n", win.StartY);
xil_printf(" Win Width = %d\r\n", win.Width);
xil_printf(" Win Height = %d\r\n", win.Height);
}
else
{
xil_printf("\r\nPip Mode: OFF\r\n");
}
}
xil_printf("**************************************************\r\n\r\n");
}
/** @} */