From 06de4b6538bd8767a6d63b9c38e8e7aeb422c7e3 Mon Sep 17 00:00:00 2001 From: Rohit Consul Date: Wed, 27 May 2015 08:11:33 +0800 Subject: [PATCH] vprocss: Added video processing subsystem driver Video processing subsystem driver is added to the repo. This driver currently is associated with a non-HIP version of the IP. No makefile available. Hard-coded g.c file used, but not included. Signed-off-by: Rohit Consul --- .../drivers/vprocss/data/vprocss.mdd | 42 + .../drivers/vprocss/src/xvprocss.c | 1534 +++++++++++++++++ .../drivers/vprocss/src/xvprocss.h | 491 ++++++ .../drivers/vprocss/src/xvprocss_dma.c | 574 ++++++ .../drivers/vprocss/src/xvprocss_dma.h | 123 ++ .../drivers/vprocss/src/xvprocss_router.c | 757 ++++++++ .../drivers/vprocss/src/xvprocss_router.h | 70 + .../drivers/vprocss/src/xvprocss_sinit.c | 97 ++ 8 files changed, 3688 insertions(+) create mode 100644 XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.c create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.h create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.h create mode 100644 XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_sinit.c diff --git a/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd b/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd new file mode 100644 index 00000000..b6c5da2a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/data/vprocss.mdd @@ -0,0 +1,42 @@ +##****************************************************************************** +## +## Copyright (C) 2014 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 +## XILINX 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. +## +##*****************************************************************************/ + +OPTION psf_version = 2.1; + +BEGIN driver vprocss + OPTION supported_peripherals = (vprocss); + OPTION driver_state = ACTIVE; + OPTION depends = (video_common_v1_0); + OPTION copyfiles = all; + OPTION VERSION = 1.0; + OPTION NAME = vprocss; +END driver diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c new file mode 100644 index 00000000..2365f7f5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.c @@ -0,0 +1,1534 @@ +/****************************************************************************** + * + * 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 +* +* This is main code of Xilinx Video Processing Subsystem device driver. +* Please see xvprocss.h for more details of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/01/15   Initial Release
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "microblaze_sleep.h" +#include "xvprocss.h" +#include "xenv.h" +#include "xvprocss_dma.h" +#include "xvprocss_router.h" + +/************************** 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 + * + * @{ + * 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 */ + +/* Scaler Coefficients for H & V Scaler */ +const short fixed_filtercoeff[64][6] = + { + { -132, 236, 3824, 236, -132, 64, }, + { -116, 184, 3816, 292, -144, 64, }, + { -100, 132, 3812, 348, -160, 64, }, + { -88, 84, 3808, 404, -176, 64, }, + { -72, 36, 3796, 464, -192, 64, }, + { -60, -8, 3780, 524, -208, 68, }, + { -48, -52, 3768, 588, -228, 68, }, + { -32, -96, 3748, 652, -244, 68, }, + { -20, -136, 3724, 716, -260, 72, }, + { -8, -172, 3696, 784, -276, 72, }, + { 0, -208, 3676, 848, -292, 72, }, + { 12, -244, 3640, 920, -308, 76, }, + { 20, -276, 3612, 988, -324, 76, }, + { 32, -304, 3568, 1060, -340, 80, }, + { 40, -332, 3532, 1132, -356, 80, }, + { 48, -360, 3492, 1204, -372, 84, }, + { 56, -384, 3448, 1276, -388, 88, }, + { 64, -408, 3404, 1352, -404, 88, }, + { 72, -428, 3348, 1428, -416, 92, }, + { 76, -448, 3308, 1500, -432, 92, }, + { 84, -464, 3248, 1576, -444, 96, }, + { 88, -480, 3200, 1652, -460, 96, }, + { 92, -492, 3140, 1728, -472, 100, }, + { 96, -504, 3080, 1804, -484, 104, }, + { 100, -516, 3020, 1880, -492, 104, }, + { 104, -524, 2956, 1960, -504, 104, }, + { 104, -532, 2892, 2036, -512, 108, }, + { 108, -540, 2832, 2108, -520, 108, }, + { 108, -544, 2764, 2184, -528, 112, }, + { 112, -544, 2688, 2260, -532, 112, }, + { 112, -548, 2624, 2336, -540, 112, }, + { 112, -548, 2556, 2408, -544, 112, }, + { 112, -544, 2480, 2480, -544, 112, }, + { 112, -544, 2408, 2556, -548, 112, }, + { 112, -540, 2336, 2624, -548, 112, }, + { 112, -532, 2260, 2688, -544, 112, }, + { 112, -528, 2184, 2764, -544, 108, }, + { 108, -520, 2108, 2832, -540, 108, }, + { 108, -512, 2036, 2892, -532, 104, }, + { 104, -504, 1960, 2956, -524, 104, }, + { 104, -492, 1880, 3020, -516, 100, }, + { 104, -484, 1804, 3080, -504, 96, }, + { 100, -472, 1728, 3140, -492, 92, }, + { 96, -460, 1652, 3200, -480, 88, }, + { 96, -444, 1576, 3248, -464, 84, }, + { 92, -432, 1500, 3308, -448, 76, }, + { 92, -416, 1428, 3348, -428, 72, }, + { 88, -404, 1352, 3404, -408, 64, }, + { 88, -388, 1276, 3448, -384, 56, }, + { 84, -372, 1204, 3492, -360, 48, }, + { 80, -356, 1132, 3532, -332, 40, }, + { 80, -340, 1060, 3568, -304, 32, }, + { 76, -324, 988, 3612, -276, 20, }, + { 76, -308, 920, 3640, -244, 12, }, + { 72, -292, 848, 3676, -208, 0, }, + { 72, -276, 784, 3696, -172, -8, }, + { 72, -260, 716, 3724, -136, -20, }, + { 68, -244, 652, 3748, -96, -32, }, + { 68, -228, 588, 3768, -52, -48, }, + { 68, -208, 524, 3780, -8, -60, }, + { 64, -192, 464, 3796, 36, -72, }, + { 64, -176, 404, 3808, 84, -88, }, + { 64, -160, 348, 3812, 132, -100, }, + { 64, -144, 292, 3816, 184, -116, } + }; + +/************************** Function Prototypes ******************************/ +static void SetPODConfiguration(XVprocss *pVprocss); +static void GetIncludedSubcores(XVprocss *pVprocss); +static int validateVidStreamConfig(XVidC_VideoStream *pStrmIn, + XVidC_VideoStream *pStrmOut); +static int SetupStreamMode(XVprocss *pVprocss); +static int SetupMaxMode(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 diverts 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 Waitms(XVprocss *pVprocss, u32 msec) +{ + if(pVprocss->UsrDelaymsec) + { + pVprocss->UsrDelaymsec(pVprocss->pUsrTmr, msec); + } + else + { + MB_Sleep(msec); + } +} + +/************************** 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 waitmsec is the function pointer to the user defined delay function +* @param pTimer is the pointer to timer instance used by the delay function +* +* @return None +* +******************************************************************************/ +void XVprocss_RegisterDelayHandler(XVprocss *InstancePtr, + XVidC_DelayHandler waitmsec, + void *pTimer) +{ + Xil_AssertVoid(InstancePtr != 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; +} + +/*****************************************************************************/ +/** +* 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 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; + XAxis_Switch_Config *RouterCfgPtr; + int status; + + /* Verify arguments */ + 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)); + pVprocss->Config.BaseAddress = EffectiveAddr; + + /* Print the configuration selected */ + switch(pVprocss->Config.Mode) + { + case XVPROCSS_MODE_MAX: + xil_printf(" [Subsystem Configuration Mode - Full]\r\n\r\n"); + break; + + case XVPROCSS_MODE_STREAM: + xil_printf(" [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->router) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing AXIS Switch core.... \r\n"); + RouterCfgPtr = XAxisScr_LookupConfig(pVprocss->Config.Router.DeviceId); + if(RouterCfgPtr == NULL) + { + xil_printf("VPROCSS ERR:: AXIS Switch device not found\r\n"); + return(XST_DEVICE_NOT_FOUND); + } + status = XAxisScr_CfgInitialize(pVprocss->router, + RouterCfgPtr, + RouterCfgPtr->BaseAddress); + + if(status != XST_SUCCESS) + { + xil_printf("VPROCSS ERR:: AXIS Switch Initialization failed %d\r\n", status); + return(XST_FAILURE); + } + } + + if(pVprocss->rstAxis) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing AXIS Reset core.... \r\n"); + status = XGpio_Initialize(pVprocss->rstAxis, pVprocss->Config.RstAxis.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: AXIS Clk Reset device not found\r\n"); + return(status); + } + } + + if(pVprocss->rstAximm) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing AXI-MM Reset core.... \r\n"); + status = XGpio_Initialize(pVprocss->rstAximm, pVprocss->Config.RstAximm.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: AXIS Div2 Clk Reset device not found\r\n"); + return(status); + } + /* + * 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->hcrsmplr) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing H Chroma Resampler core.... \r\n"); + status = XV_hcresampler_Initialize(pVprocss->hcrsmplr, pVprocss->Config.HCrsmplr.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: H Chroma Resampler device not found\r\n"); + return(status); + } + } + + if(pVprocss->vcrsmplrIn) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing Input V Chroma Resampler core.... \r\n"); + status = XV_vcresampler_Initialize(pVprocss->vcrsmplrIn, pVprocss->Config.VCrsmplrIn.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: Input V Chroma Resampler device not found\r\n"); + return(status); + } + } + + if(pVprocss->vcrsmplrOut) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing Output V Chroma Resampler core.... \r\n"); + status = XV_vcresampler_Initialize(pVprocss->vcrsmplrOut, pVprocss->Config.VCrsmplrOut.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: Output V Chroma Resampler device not found\r\n"); + return(status); + } + } + + if(pVprocss->vscaler) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing V Scaler core.... \r\n"); + status = XV_vscaler_Initialize(pVprocss->vscaler, pVprocss->Config.Vscale.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: V Scaler device not found\r\n"); + return(status); + } + } + + if(pVprocss->hscaler) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing H Scaler core.... \r\n"); + status = XV_hscaler_Initialize(pVprocss->hscaler, pVprocss->Config.Hscale.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: H Scaler device not found\r\n"); + return(status); + } + } + + if(pVprocss->vdma) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing VDMA core.... \r\n"); + VdmaCfgPtr = XAxiVdma_LookupConfig(pVprocss->Config.Vdma.DeviceId); + if(VdmaCfgPtr == NULL) + { + xil_printf("VPROCSS ERR:: VDMA device not found\r\n"); + return(XST_DEVICE_NOT_FOUND); + } + status = XAxiVdma_CfgInitialize(pVprocss->vdma, + VdmaCfgPtr, + VdmaCfgPtr->BaseAddress); + + if(status != XST_SUCCESS) + { + xil_printf("VPROCSS ERR:: VDMA Configuration Initialization failed %d\r\n", status); + return(XST_FAILURE); + } + } + + if(pVprocss->lbox) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing Letterbox core.... \r\n"); + status = XV_letterbox_Initialize(pVprocss->lbox, pVprocss->Config.Lbox.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: LetterBox device not found\r\n"); + return(status); + } + } + + if(pVprocss->csc) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing CSC core.... \r\n"); + status = XV_csc_Initialize(pVprocss->csc, pVprocss->Config.Csc.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: CSC device not found\r\n"); + return(status); + } + } + + if(pVprocss->deint) + { + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing Deinterlacer core.... \r\n"); + status = XV_deinterlacer_Initialize(pVprocss->deint, pVprocss->Config.Deint.DeviceId); + if(status == XST_DEVICE_NOT_FOUND) + { + xil_printf("VPROCSS ERR:: Deinterlacer device not found\r\n"); + return(status); + } + } + + /* Validate DDR Frame Buffer Allocation */ + if(pVprocss->vdma) + { + u32 vdmaBufReq, deintBufReq, padBuf; + u32 totBufReq; + u32 inRange, numVdmaBuf; + + /* Validate External Memory Range available */ + numVdmaBuf = pVprocss->vdma->MaxNumFrames; + + //4 4K2K (YUV444 16-bit) buffers (~190MB) needed for frame buffers + vdmaBufReq = numVdmaBuf * (u32)3840 * 2160 * 3 * 2; + + //3 1080i (YUV444 16-bit) field buffers (~18MB) needed for de-interlacer + deintBufReq = 3*(u32)1920*540*3*2; + + //1 4K2K buffer (~48MB) reserved as pad between vdma and deint + padBuf = (u32)3840*2160*3*2; + + totBufReq = vdmaBufReq + deintBufReq + padBuf; //~256MB (0x1000 0000) + inRange = (totBufReq < pVprocss->Config.UsrExtMemAddr_Range); + if(!inRange) + { + xil_printf("VPROCSS ERR:: EXT Memory Region Allocated is small."); + xil_printf("Try increasing memory range\r\n"); + return(XST_FAILURE); + } + + /* + * DDR @0x8000 0000 + * - 512MB space reserved for elf file + * VDMA Buffer offset = 0x8000 0000 + 0x2000 0000 + * = 0xA000 0000 + * vdmaBufReq = 0x0BDD 80000 + * padBuf = 0x02F7 6000 + * ------------- + * DeInt Offst= 0x0ED4 E000 --->0xAED4 E0000 + * ------------- + */ + /* Set Deint Buffer Address Offset */ + if(pVprocss->deint) + { + pVprocss->idata.deintBufAddr = pVprocss->Config.UsrExtMemBaseAddr + vdmaBufReq + padBuf; + } + } + 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; + + /* 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 = XVIDC_BPC_10; + 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 = XVIDC_BPC_10; + vidStrmIn.PixPerClk = pVprocss->Config.PixPerClock; + + /* Setup Video Processing subsystem input/output configuration */ + XVprocss_SetVidStreamIn(pVprocss, &vidStrmIn); + XVprocss_SetVidStreamOut(pVprocss, &vidStrmOut); + + 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); + } + + 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); + + /* 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); + } + + /* Setup H Scaler */ + if(pVprocss->hscaler) + { + pVprocss->hscL2Reg.EffectiveTaps = 6; + pVprocss->hscL2Reg.UseExtCoeff = TRUE; + pVprocss->hscL2Reg.FilterSel = XV_HFILT_LANCZOS; + pVprocss->hscL2Reg.ScalerType = XV_HSCALER_POLYPHASE; + pVprocss->hscL2Reg.Gain = 1; + XV_HscalerLoadUsrCoeffients(pVprocss->hscaler, + &pVprocss->hscL2Reg, + fixed_filtercoeff); + } + + /* Setup V Scaler */ + if(pVprocss->vscaler) + { + pVprocss->vscL2Reg.EffectiveTaps = 6; + pVprocss->vscL2Reg.UseExtCoeff = TRUE; + pVprocss->vscL2Reg.FilterSel = XV_VFILT_LANCZOS; + pVprocss->vscL2Reg.ScalerType = XV_VSCALER_POLYPHASE; + pVprocss->vscL2Reg.Gain = 1; + XV_VscalerLoadUsrCoeffients(pVprocss->vscaler, + &pVprocss->vscL2Reg, + fixed_filtercoeff); + } + +} + +/****************************************************************************/ +/** +* 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; + + 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) +{ + 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) +{ + 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); + } + + Waitms(InstancePtr, 10); /* hold reset line for 10ms */ + /* + * 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); + Waitms(InstancePtr, 10); /* wait 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; + + 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; + + 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; + + 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) +{ + Xil_AssertVoid(InstancePtr != NULL); + + if(XVprocss_IsConfigModeMax(InstancePtr)) + { + /* send vdma update window to IP */ + if(XVprocss_IsPipModeOn(InstancePtr)) + { + XVprocss_SetVdmaWinToDnScaleMode(InstancePtr, XVPROCSS_VDMA_UPDATE_WR_CH); + } + else + { + XVprocss_SetVdmaWinToUpScaleMode(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 + { + xil_printf("\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; + + 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->vdma->ReadChannel.WordLength-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->vdma->WriteChannel.WordLength-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 + { + xil_printf("\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) +{ + 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 + { + xil_printf("\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"}; + + Xil_AssertVoid(InstancePtr != NULL); + + if(XVprocss_IsConfigModeMax(InstancePtr)) + { + InstancePtr->idata.ZoomEn = OnOff; + InstancePtr->idata.PipEn = FALSE; + + xil_printf("\r\n :ZOOM Mode %s \r\n", status[InstancePtr->idata.ZoomEn]); + } + else //Scaler Only Config + { + xil_printf("\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"}; + + Xil_AssertVoid(InstancePtr != NULL); + + if(XVprocss_IsConfigModeMax(InstancePtr)) + { + InstancePtr->idata.PipEn = OnOff; + InstancePtr->idata.ZoomEn = FALSE; + + xil_printf("\r\n :PIP Mode %s \r\n", status[InstancePtr->idata.PipEn]); + } + else //Scaler Only Config + { + xil_printf("\r\nVPROCSS ERR:: Feature not supported in Streaming Mode\r\n"); + } +} + +/*****************************************************************************/ +/** +* This function validates the input and output stream 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 possible +******************************************************************************/ +static int validateVidStreamConfig(XVidC_VideoStream *pStrmIn, + XVidC_VideoStream *pStrmOut) +{ + if(pStrmIn->IsInterlaced) + { + xil_printf("VPROCSS ERR: Interlaced Input not supported\r\n"); + return(XST_FAILURE); + } + + if(pStrmIn->ColorFormatId == XVIDC_CSF_YCRCB_420) + { + xil_printf("VPROCSS ERR: YUV420 Input not supported\r\n"); + return(XST_FAILURE); + } + + if(pStrmIn->ColorFormatId != pStrmOut->ColorFormatId) + { + xil_printf("VPROCSS ERR: Input & Output Stream Color Format different\r\n"); + return(XST_FAILURE); + } + + if(pStrmIn->ColorDepth != pStrmOut->ColorDepth) + { + xil_printf("VPROCSS ERR: Input & Output Color Depth different\r\n"); + return(XST_FAILURE); + } + + return(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function configures the video subsystem pipeline for Stream Mode +* configuration 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 SetupStreamMode(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)) + { + xil_printf("VPROCSS ERR:: Scaler IP not found\r\n"); + return(XST_FAILURE); + } + + /* check if input/output stream configuration is supported */ + status = validateVidStreamConfig(&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->Config.PixPerClock, + 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 + { + xil_printf("\r\n-->Command Ignored<--\r\n"); + } + return(status); +} + +/*****************************************************************************/ +/** +* This function configures the video subsystem pipeline for Maximum (Full) +* mode configuration +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* +* @return XST_SUCCESS if successful else XST_FAILURE +* +******************************************************************************/ +static int SetupMaxMode(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 + { + xil_printf("VPROCSS ERR: Subsystem Routing Table Invalid"); + xil_printf("- Ignoring Configuration Request\r\n"); + } + return(status); +} + +/*****************************************************************************/ +/** +* 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_ConfigureSubsystem(XVprocss *InstancePtr) +{ + int status = XST_SUCCESS; + + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Video Processing Subsystem overrides In/Out Pixel Precision & Pixel/Clk */ + InstancePtr->VidIn.ColorDepth = (XVidC_ColorDepth)InstancePtr->Config.PixPrecision; + InstancePtr->VidOut.ColorDepth = (XVidC_ColorDepth)InstancePtr->Config.PixPrecision; + + InstancePtr->VidIn.PixPerClk = (XVidC_PixelsPerClock)InstancePtr->Config.PixPerClock; + + 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"); + + switch(InstancePtr->Config.Mode) + { + case XVPROCSS_MODE_MAX: + status = SetupMaxMode(InstancePtr); + break; + + case XVPROCSS_MODE_STREAM: + //Only configuration supported is V->H + status = SetupStreamMode(InstancePtr); + break; + + default: + xil_printf("VPROCSS ERR: Subsystem Configuration Mode Not Supported. \r\n"); + status = XST_FAILURE; + break; + } + return(status); +} diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h new file mode 100644 index 00000000..448ff1f3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss.h @@ -0,0 +1,491 @@ +/****************************************************************************** + * + * 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.h +* +* This is main header file of the Xilinx Video Processing Subsystem driver +* +* Video Processing Subsystem Overview +* +* Video Subsystem is a collection of IP cores bounded together by software +* to provide an abstract view of the processing pipe. It hides all the +* complexities of programming the underlying cores from end user. +* +* Subsystem Driver Features +* +* Video Subsystem supports following features +* - AXI Stream Input/Output interface +* - 2 or 4 pixel-wide video interface +* - up to 16 bits per component +* - RGB & YCbCb color space +* - Memory based/streaming mode scaling in either direction (Up/Down) +* - Up to 4k2k 60Hz resolution at both Input and Output interface +* - Interlaced input support +* - Frame rate conversion +* - Drop frames if input rate > output rate +* - Repeat frames if input rate < output rate +* - Auto configuration of processing pipe based on detected use case +* - Scale Up/Down +* - Zoom mode wherein a window in input is scaled to panel resolution +* - Picture-In-Picture mode wherein the input stream is scaled down to +* a defined window size and background is painted to user define color +* - Color Space and color format Conversion +* - Interlaced to Progressive conversion +* +* Subsystem Configurations +* +* Two types of configurations are supported via GUI in IPI +* - Full Configuration: provides all the features mentioned above +* - Streaming Mode Configuration (aka Scaler-Only) with limited functionality +* +* Number of processing cores that get included in the design will depend upon +* the configuration selected. Static configuration parameters are stored in +* vprocss_g.c file that gets generated when compiling the board support package +* (BSP). A table is defined where each entry contains configuration information +* for the instances of the subsystem in the design. This information includes +* the elected configuration, sub-cores used and their device ID, base addresses +* of memory mapped devices, user specified DDR address for buffer management +* and address range available for subsystem frame/field buffers. +* +* Full configuration mode includes following sub-cores in HW +* - Scalers (horizontal/vertical) +* - Chroma Resampler (horizontal/vertical) +* - Color Space Converter +* - VDMA for buffer management +* - De-Interlacer +* - Letter Box +* - AXIS Switch +* +* Stream mode configuration mode includes following sub-cores in HW +* - Scalers (horizontal/vertical) +* +* The subsystem driver itself always includes the full software stack +* irrespective of the configuration selected. Generic API's are provided to +* interact with the subsystem and/or with the included sub-cores. +* At run-time the subsystem will query the static configuration and configures +* itself for supported use cases +* +* Subsystem Driver Description +* +* Subsystem driver is built upon layer 1&2 device drivers of included sub-cores +* Layer 1 provides API's to peek/poke registers at HW level. +* Layer 2 provides API's that abstract sub-core functionality, providing an easy to +* use feature interface +* +* 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. +* +* Subsystem Driver Usage +* +* The subsystem driver in itself is a dormant driver that needs application SW to +* make use of provided API's to configure it at boot-up. Thereafter application +* SW is responsible to monitor the system for external impetus and call the +* subsystem API's to communicate the change and trigger the reconfiguration of +* internal data processing pipe (refer API XVprocss_ConfigureSubsystem()) +* AXI Stream configuration for input/output interface is derived from the +* Xilinx video common driver and only the resolutions listed therein are +* supported at this time +* +* Interrupt Service +* +* Currently no interrupts are available from the subsystem. User application is +* responsible for triggering processing pipe update when any change in subsystem +* configuration is performed at application level +* +* Virtual Memory +* +* This driver supports Virtual Memory. The RTOS is responsible for calculating +* the correct device base address in Virtual Memory space. +* +* Threads +* +* This driver is not thread safe. Any needs for threads or thread mutual +* exclusion must be satisfied by the layer above this driver. +* + +* Asserts +* +* Asserts are used within all Xilinx drivers to enforce constraints on argument +* values. Asserts can be turned off on a system-wide basis by defining, at +* compile time, the NDEBUG identifier. By default, asserts are turned on and +* it is recommended that application developers leave asserts on during +* development. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/01/15   Initial Release
+
+* 
+* +******************************************************************************/ + +#ifndef XVPROCSS_H /**< prevent circular inclusions by using protection macros*/ +#define XVPROCSS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xstatus.h" +#include "xintc.h" +#include "xgpio.h" +#include "xaxis_switch.h" +#include "xvidc.h" +/** + * Sub-core Layer 2 driver includes + * Layer 2 includes Layer-1 + */ +#include "xaxivdma.h" +#include "xv_csc_l2.h" +#include "xv_deinterlacer_l2.h" +#include "xv_hcresampler_l2.h" +#include "xv_vcresampler_l2.h" +#include "xv_hscaler_l2.h" +#include "xv_vscaler_l2.h" +#include "xv_letterbox_l2.h" + +/****************************** Type Definitions ******************************/ +/** + * AXIS Switch Port enumeration for Sub-Core connection + */ +typedef enum +{ + XVPROCSS_RTR_VIDOUT = 0, //M0 + XVPROCSS_RTR_SCALER_V, //M1 + XVPROCSS_RTR_SCALER_H, //M2 + XVPROCSS_RTR_VDMA, //M3 + XVPROCSS_RTR_LBOX, //M4 + XVPROCSS_RTR_CR_H, //M5 + XVPROCSS_RTR_CR_V_IN, //M6 + XVPROCSS_RTR_CR_V_OUT, //M7 + XVPROCSS_RTR_CSC, //M8 + XVPROCSS_RTR_DEINT, //M9 + XVPROCSS_RTR_MAX +}XVPROCSS_RTR_MIx_ID; + +/** + * Subsystem Configuration Mode Select + */ +typedef enum +{ + XVPROCSS_MODE_MAX = 0, + XVPROCSS_MODE_STREAM +}XVPROCSS_CONFIG_MODE; + +/** + * Types of Windows (Sub-frames) available in the Subsystem + */ +typedef enum +{ + XVPROCSS_ZOOM_WIN = 0, + XVPROCSS_PIP_WIN, + XVPROCSS_PIXEL_WIN +}XVprocss_Win; + +/** + * Scaling Modes supported + */ +typedef enum +{ + XVPROCSS_SCALE_1_1 = 0, + XVPROCSS_SCALE_UP, + XVPROCSS_SCALE_DN, + XVPROCSS_SCALE_NOT_SUPPORTED +}XVprocss_ScaleMode; + +/** + * Video Processing Subsystem internal scratch pad memory. + * This contains internal flags, state variables, routing table + * and other meta-data required by the subsystem. Each instance + * of the subsystem will have its own scratch pad memory + */ +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 */ + + u8 RtngTable[XVPROCSS_RTR_MAX]; /**< Storage for computed routing map */ + u8 startCore[XVPROCSS_RTR_MAX]; /**< Enable flag to start sub-core */ + u8 RtrNumCores; /**< Number of sub-cores in routing map */ + u8 ScaleMode; /**< Stored computed scaling mode - UP/DN/1:1 */ + u8 memEn; /**< Flag to indicate if stream routes through memory */ + u8 ZoomEn; /**< Flag to store Zoom feature state */ + u8 PipEn; /**< Flag to store PIP feature state */ + u16 vidInWidth; /**< Input H Active */ + u16 vidInHeight; /**< Input V Active */ + XVidC_ColorFormat strmCformat; /**< processing pipe color format */ + XVidC_ColorFormat cscIn; /**< CSC core input color format */ + XVidC_ColorFormat cscOut; /**< CSC core output color format */ + XVidC_ColorFormat hcrIn; /**< horiz. cresmplr core input color format */ + XVidC_ColorFormat hcrOut; /**< horiz. cresmplr core output color format */ +}XVprocss_IData; + +/** + * Sub-Core Configuration Table + */ +typedef struct +{ + u16 isPresent; /**< Flag to indicate if sub-core is present in the design*/ + u16 DeviceId; /**< Device ID of the sub-core */ +}XSubCore; + +/** + * Video Processing Subsystem configuration structure. + * Each subsystem device should have a configuration structure associated + * that defines the MAX supported sub-cores within subsystem + */ + +typedef struct +{ + u16 DeviceId; /**< DeviceId is the unique ID of the device */ + u32 BaseAddress; /**< BaseAddress is the physical base address of + the device's registers */ + u8 Mode; /**< Subsystem configuration mode */ + u8 PixPerClock; /**< Number of Pixels Per Clock processed by Subsystem */ + u16 PixPrecision; /**< Processing precision of the data pipe */ + XSubCore HCrsmplr; /**< Sub-core instance configuration */ + XSubCore VCrsmplrIn; /**< Sub-core instance configuration */ + XSubCore VCrsmplrOut; /**< Sub-core instance configuration */ + XSubCore Vscale; /**< Sub-core instance configuration */ + XSubCore Hscale; /**< Sub-core instance configuration */ + XSubCore Vdma; /**< Sub-core instance configuration */ + XSubCore Lbox; /**< Sub-core instance configuration */ + XSubCore Csc; /**< Sub-core instance configuration */ + XSubCore Deint; /**< Sub-core instance configuration */ + XSubCore Router; /**< Sub-core instance configuration */ + XSubCore RstAxis; /**< Axi stream reset network instance configuration */ + XSubCore RstAximm; /**< Axi MM reset network instance configuration */ + u32 UsrExtMemBaseAddr; /**< DDR base address for buffer management */ + u32 UsrExtMemAddr_Range; /**< Range of addresses available for buffers */ +} XVprocss_Config; + +/** + * The XVprocss driver instance data. The user is required to allocate a variable + * of this type for every XVprocss device in the system. A pointer to a variable + * of this type is then passed to the driver API functions. + */ +typedef struct +{ + XVprocss_Config Config; /**< Hardware configuration */ + u32 IsReady; /**< Device and the driver instance are initialized */ + + XAxis_Switch *router; /**< handle to sub-core driver instance */ + XGpio *rstAxis; /**< handle to sub-core driver instance */ + XGpio *rstAximm; /**< handle to sub-core driver instance */ + /**< handle to sub-core driver instance */ + XV_hcresampler *hcrsmplr; /**< handle to sub-core driver instance */ + XV_vcresampler *vcrsmplrIn; /**< handle to sub-core driver instance */ + XV_vcresampler *vcrsmplrOut; /**< handle to sub-core driver instance */ + XV_vscaler *vscaler; /**< handle to sub-core driver instance */ + XV_hscaler *hscaler; /**< handle to sub-core driver instance */ + XAxiVdma *vdma; /**< handle to sub-core driver instance */ + XV_letterbox *lbox; /**< handle to sub-core driver instance */ + XV_csc *csc; /**< handle to sub-core driver instance */ + XV_deinterlacer *deint; /**< handle to sub-core driver instance */ + + /** + * Layer2 SW Register (Every Subsystem instance will have it's own copy + of Layer 2 register bank for applicable sub-cores) + */ + 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 */ + + //I/O Streams + XVidC_VideoStream VidIn; /**< Input AXIS configuration */ + XVidC_VideoStream VidOut; /**< Output AXIS configuration */ + + XVprocss_IData idata; /**< Internal Scratch pad memory for subsystem instance */ + + XIntc *pXintc; /**< handle to system interrupt controller */ + XVidC_DelayHandler UsrDelaymsec; /**< custom user function for delay/sleep */ + void *pUsrTmr; /**< handle to timer instance used by user delay function */ +} XVprocss; + +/************************** Macros Definitions *******************************/ +/*****************************************************************************/ +/** + * This macro checks if subsystem is in Maximum configuration mode + * + * @param pVprocss is a pointer to the Video Processing subsystem instance + * @return Return 1 if condition is TRUE or 0 if FALSE + * + *****************************************************************************/ +#define XVprocss_IsConfigModeMax(pVprocss) \ + ((pVprocss)->Config.Mode == XVPROCSS_MODE_MAX) + +/*****************************************************************************/ +/** + * This macro checks if subsystem configuration is in Stream Mode (Scaler Only) + * + * @param pVprocss is pointer to the Video Processing subsystem instance + * + * @return Returns 1 if condition is TRUE or 0 if FALSE + * + *****************************************************************************/ +#define XVprocss_IsConfigModeStream(pVprocss) \ + ((pVprocss)->Config.Mode == XVPROCSS_MODE_STREAM) + + +/*****************************************************************************/ +/** + * This macro returns the current state of PIP Mode stored in subsystem internal + * scratch pad memory + * + * @param pVprocss is a pointer to the Video Processing subsystem instance + * + * @return Returns 1 if PIP mode is ON or 0 if OFF + * + *****************************************************************************/ +#define XVprocss_IsPipModeOn(pVprocss) ((pVprocss)->idata.PipEn) + +/*****************************************************************************/ +/** + * This macro returns the current state of Zoom Mode stored in subsystem internal + * scratch pad memory + * + * @param pVprocss is a pointer to the Video Processing subsystem instance + * + * @return Returns 1 if ZOOM mode is ON or 0 if OFF + * + *****************************************************************************/ +#define XVprocss_IsZoomModeOn(pVprocss) ((pVprocss)->idata.ZoomEn) + +/*****************************************************************************/ +/** + * This macro clears the PIP mode flag stored in subsystem internal scratch + * pad memory. This call has no side-effect + * + * @param pVprocss is a pointer to the Video Processing subsystem instance + * + * @return None + * + *****************************************************************************/ +#define XVprocss_ResetPipModeFlag(pVprocss) ((pVprocss)->idata.PipEn = FALSE) + +/*****************************************************************************/ +/** + * This macro clears the ZOOM mode flag stored in subsystem internal scratch + * pad memory. This call has no side-effect + * + * @param pVprocss is pointer to the Video Processing subsystem instance + * + * @return None + * + *****************************************************************************/ +#define XVprocss_ResetZoomModeFlag(pVprocss) ((pVprocss)->idata.ZoomEn = FALSE) + +/*****************************************************************************/ +/** + * This macro sets the specified stream's color format. It can be used to + * update input or output stream. This call has no side-effect in isolation. + * For change to take effect user must trigger processing path reconfiguration + * by calling XVprocss_ConfigureSubsystem() + * + * @param Stream is a pointer to the Subsystem Input or Output Stream + * @param ColorFormat is the requested color format + * + * @return None + * + *****************************************************************************/ +#define XVprocss_SetStreamColorFormat(Stream, ColorFormat) \ + ((Stream)->ColorFormatId = ColorFormat) + +/*****************************************************************************/ +/** + * This macro sets the specified stream's color depth. It can be used to update + * input or output stream. This call has no side-effect in isolation + * For change to take effect user must trigger processing path reconfiguration + * by calling XVprocss_ConfigureSubsystem() + * + * @param Stream is a pointer to the Subsystem Input or Output Stream + * @param ColorDepth is the requested color depth + * + * @return None + * + *****************************************************************************/ +#define XVprocss_SetStreamColorDepth(Stream, ColorDepth) \ + ((Stream)->ColorDepth = ColorDepth) + +/************************** Function Prototypes ******************************/ +XVprocss_Config* XVprocss_LookupConfig(u32 DeviceId); +int XVprocss_CfgInitialize(XVprocss *InstancePtr, + XVprocss_Config *CfgPtr, + u32 EffectiveAddr); +int XVprocss_PowerOnInit(XVprocss *InstancePtr, u32 DeviceId); +void XVprocss_Start(XVprocss *InstancePtr); +void XVprocss_Stop(XVprocss *InstancePtr); +void XVprocss_Reset(XVprocss *InstancePtr); +int XVprocss_SetVidStreamIn(XVprocss *InstancePtr, + const XVidC_VideoStream *StrmIn); +int XVprocss_SetVidStreamOut(XVprocss *InstancePtr, + const XVidC_VideoStream *StrmOut); +int XVprocss_SetStreamResolution(XVidC_VideoStream *StreamPtr, + const XVidC_VideoMode VmId); +void XVprocss_ReportCoreInfo(XVprocss *InstancePtr); +int XVprocss_ConfigureSubsystem(XVprocss *InstancePtr); +void XVprocss_SetZoomMode(XVprocss *InstancePtr, u8 OnOff); +void XVprocss_SetPipMode(XVprocss *InstancePtr, u8 OnOff); + +void XVprocss_SetZoomPipWindow(XVprocss *InstancePtr, + XVprocss_Win mode, + XVidC_VideoWindow *win); +void XVprocss_GetZoomPipWindow(XVprocss *InstancePtr, + XVprocss_Win mode, + XVidC_VideoWindow *win); + +void XVprocss_UpdateZoomPipWindow(XVprocss *InstancePtr); + +void XVprocss_RegisterSysIntc(XVprocss *InstancePtr, XIntc *sysIntc); +void XVprocss_RegisterDelayHandler(XVprocss *InstancePtr, + XVidC_DelayHandler waitmsec, + void *pTimer); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.c new file mode 100644 index 00000000..b819125c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.c @@ -0,0 +1,574 @@ +/****************************************************************************** + * + * 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_dma.c + +* Video buffer management routine. +* The functions in this file provides an abstraction from the register peek/poke +* methodology by implementing most common use-case provided by the VDMA sub-core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/18/15   Initial Release
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xvidc.h" +#include "xvprocss_dma.h" +#include "microblaze_sleep.h" + +#define XVDMA_RESET_TIMEOUT (1000000) //10ms at 10ns time period (100MHz clock)) +/*****************************************************************************/ +/** +* This function starts Read and Write channels +* +* @param pVdma is the pointer to core instance to be worked on +* +* @return None +* +*******************************************************************************/ +void XVprocss_VdmaStart(XAxiVdma *pVdma) +{ + if(pVdma) + { + XAxiVdma_DmaStart(pVdma, XAXIVDMA_WRITE); + XAxiVdma_DmaStart(pVdma, XAXIVDMA_READ); + } +} + +/*****************************************************************************/ +/** +* This function stops Read and Write channels +* +* @param pVdma is the pointer to core instance to be worked on +* +* @return None +* +*******************************************************************************/ +void XVprocss_VdmaStop(XAxiVdma *pVdma) +{ + if(pVdma) + { + XAxiVdma_DmaStop(pVdma, XAXIVDMA_WRITE); + XAxiVdma_DmaStop(pVdma, XAXIVDMA_READ); + } +} + +/*****************************************************************************/ +/** +* This function resets Read and Write channels. +* +* @param pVdma is the pointer to core instance to be worked on +* +* @return None +* +*******************************************************************************/ +void XVprocss_VdmaReset(XAxiVdma *pVdma) +{ + u32 timeout; + + if(pVdma) + { + XAxiVdma_Reset(pVdma, XAXIVDMA_WRITE); + timeout = XVDMA_RESET_TIMEOUT; + while(timeout && XAxiVdma_ResetNotDone(pVdma, XAXIVDMA_WRITE)) + { + timeout -= 1; + } + if(!timeout) + { + xil_printf("\r\n****CRITICAL HW ERR:: VDMA WR CH RESET STUCK HIGH****\r\n"); + } + + timeout = XVDMA_RESET_TIMEOUT; + XAxiVdma_Reset(pVdma, XAXIVDMA_READ); + while(timeout && XAxiVdma_ResetNotDone(pVdma, XAXIVDMA_READ)) + { + timeout -= 1; + } + if(!timeout) + { + xil_printf("\r\n****CRITICAL HW ERR:: VDMA RD CH RESET STUCK HIGH****\r\n"); + } + } +} + + +/*****************************************************************************/ +/** +* +* This function sets up the write channel +* +* @param pVdma is the instance pointer to the DMA engine. +* @param WrBaseAddress is the address in DDR where frame buffers are located +* @param window is pointer to sub-frame window +* @param FrameWidth is the active width of the stream to be written +* @param FrameHeight is the active height of the stream to be written +* @param Bpp is Bytes Per Pixel required for the stream to be written +* +* @return XST_SUCCESS if the setup is successful, XST_FAILURE otherwise. +* +******************************************************************************/ +int XVprocss_VdmaWriteSetup(XAxiVdma *pVdma, + u32 WrBaseAddress, + XVidC_VideoWindow *window, + u32 FrameWidth, + u32 FrameHeight, + u32 Bpp) +{ + XAxiVdma_DmaSetup WriteCfg; + int Index; + u32 Addr; + int Status; + u32 HSizeInBytes; + 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; + + /* Compute start location for sub-frame */ + BlockOffset = (window->StartY * StrideInBytes) + window->StartX*Bpp; + + /* If DMA engine does not support unaligned transfers then align block + * offset to next data width boundary (DMA WR Data-width = 128) + */ + if(!pVdma->WriteChannel.HasDRE) + { + alignBytes = pVdma->WriteChannel.WordLength-1; + BlockOffset = (BlockOffset+alignBytes) & ~(alignBytes); + } + + WriteCfg.VertSizeInput = window->Height; + WriteCfg.HoriSizeInput = HSizeInBytes; + + WriteCfg.Stride = StrideInBytes; + WriteCfg.FrameDelay = 0; /* This example does not test frame delay */ + + WriteCfg.EnableCircularBuf = 1; + WriteCfg.EnableSync = 0; /* No Gen-Lock */ + + WriteCfg.PointNum = 0; /* Master we synchronize with -> vdma instance being worked with */ + WriteCfg.EnableFrameCounter = 0; /* Endless transfers */ + + WriteCfg.FixedFrameStoreAddr = 0; /* We are not doing parking */ + + WriteCfg.GenLockRepeat = 1; /* Repeat previous frame on frame errors */ + Status = XAxiVdma_DmaConfig(pVdma, XAXIVDMA_WRITE, &WriteCfg); + if (Status != XST_SUCCESS) + { + xil_printf("Write channel config failed %d\r\n", Status); + return XST_FAILURE; + } + + /* Initialize buffer addresses + * + * Use physical addresses + */ + Addr = WrBaseAddress + BlockOffset; + for(Index = 0; Index < MAX_WR_FRAMES; Index++) + { + WriteCfg.FrameStoreStartAddr[Index] = Addr; + Addr += StrideInBytes * FrameHeight; + } + + /* Set the buffer addresses for transfer in the DMA engine */ + Status = XAxiVdma_DmaSetBufferAddr(pVdma, XAXIVDMA_WRITE, + WriteCfg.FrameStoreStartAddr); + if (Status != XST_SUCCESS) + { + xil_printf("Write channel set buffer address failed %d\r\n", Status); + return XST_FAILURE; + } + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function sets up the read channel +* +* @param pVdma is the instance pointer to the DMA engine. +* @param RdBaseAddress is the address in DDR where frame buffers are located +* @param window is pointer to sub-frame window +* @param FrameWidth is the active width of the stream to be read +* @param FrameHeight is the active height of the stream to be read +* @param Bpp is Bytes Per Pixel required for the stream to be read +* +* @return XST_SUCCESS if the setup is successful, XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +int XVprocss_VdmaReadSetup(XAxiVdma *pVdma, + u32 RdBaseAddress, + XVidC_VideoWindow *window, + u32 FrameWidth, + u32 FrameHeight, + u32 Bpp) +{ + XAxiVdma_DmaSetup ReadCfg; + int Index; + u32 Addr; + int Status; + u32 HSizeInBytes; + 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; + + //Compute start location for sub-frame + BlockOffset = (window->StartY * StrideInBytes) + window->StartX*Bpp; + + /* If DMA engine does not support unaligned transfers then align block + * offset to next data width boundary (DMA WR Data-width = 128) + */ + if(!pVdma->ReadChannel.HasDRE) + { + alignBytes = pVdma->ReadChannel.WordLength-1; + BlockOffset = (BlockOffset+alignBytes) & ~(alignBytes); + } + + ReadCfg.VertSizeInput = window->Height; + ReadCfg.HoriSizeInput = HSizeInBytes; + + ReadCfg.Stride = StrideInBytes; + ReadCfg.FrameDelay = 1; /* Read is 1 Frame behind write */ + + ReadCfg.EnableCircularBuf = 1; + ReadCfg.EnableSync = 1; /* Gen-Lock Slave*/ + + ReadCfg.PointNum = 0; /* Master to synchronize with -> vdma instance being worked with */ + ReadCfg.EnableFrameCounter = 0; /* Endless transfers */ + + ReadCfg.FixedFrameStoreAddr = 0; /* We are not doing parking */ + + Status = XAxiVdma_DmaConfig(pVdma, XAXIVDMA_READ, &ReadCfg); + if (Status != XST_SUCCESS) + { + xil_printf("Read channel config failed %d\r\n", Status); + return XST_FAILURE; + } + + /* Initialize buffer addresses + * + * These addresses are physical addresses + */ + Addr = RdBaseAddress + BlockOffset; + for(Index = 0; Index < MAX_RD_FRAMES; Index++) + { + ReadCfg.FrameStoreStartAddr[Index] = Addr; + Addr += StrideInBytes * FrameHeight; + } + + /* Set the buffer addresses for transfer in the DMA engine + * The buffer addresses are physical addresses + */ + Status = XAxiVdma_DmaSetBufferAddr(pVdma, XAXIVDMA_READ, + ReadCfg.FrameStoreStartAddr); + if (Status != XST_SUCCESS) + { + xil_printf("Read channel set buffer address failed %d\r\n", Status); + return XST_FAILURE; + } + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function starts the transfer on Read/Write channels. Both channels must +* have been configured before this call is made +* +* @param pVdma is the instance pointer to the DMA engine. +* +* @return XST_SUCCESS if the setup is successful, XST_FAILURE otherwise. +* +* @note Currently the return value is ignored at subsystem level. +* +******************************************************************************/ +int XVprocss_VdmaStartTransfer(XAxiVdma *pVdma) +{ + int Status; + + if(pVdma) + { + Status = XAxiVdma_DmaStart(pVdma, XAXIVDMA_WRITE); + if (Status != XST_SUCCESS) + { + xil_printf("VDMA ERR:: Start Write transfer failed %d\r\n", Status); + return XST_FAILURE; + } + + Status = XAxiVdma_DmaStart(pVdma, XAXIVDMA_READ); + if (Status != XST_SUCCESS) + { + xil_printf("VDMA ERR:: Start read transfer failed %d\r\n", Status); + return XST_FAILURE; + } + } + 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 +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* @param updateCh defines VDMA channel (RD/WR or RD+WR) to update +* +* @return None +* +******************************************************************************/ +void XVprocss_SetVdmaWinToDnScaleMode(XVprocss *pVprocss, u32 updateCh) +{ + XVidC_VideoWindow wrWin, rdWin; + u32 OutputWidth, OutputHeight; + int status; + + OutputWidth = pVprocss->VidOut.Timing.HActive; + OutputHeight = pVprocss->VidOut.Timing.VActive; + + /*VDMA is After Scaler + WR client will receive PIP (or down scaled) stream from Scaler + RD client will read at Output resolution + */ + + if((updateCh == XVPROCSS_VDMA_UPDATE_WR_CH) || + (updateCh == XVPROCSS_VDMA_UPDATE_ALL_CH) + ) + { + /* Setup WR CLIENT window size */ + if(XVprocss_IsPipModeOn(pVprocss)) + { + /* Read PIP window setting - set elsewhere */ + XVprocss_GetZoomPipWindow(pVprocss, XVPROCSS_PIP_WIN, &wrWin); + } + else //Normal Downscale mode + { + /* set WR client window to output resolution */ + wrWin.StartX = 0; + wrWin.StartY = 0; + wrWin.Width = OutputWidth; + wrWin.Height = OutputHeight; + } + + /* write PIP window stream to DDR */ + status = XVprocss_VdmaWriteSetup(pVprocss->vdma, + pVprocss->Config.UsrExtMemBaseAddr, + &wrWin, + OutputWidth, + OutputHeight, + pVprocss->idata.vdmaBytesPerPixel); + if(status != XST_SUCCESS) + { + xil_printf("VPROCSS ERR:: Unable to configure VDMA Write Channel \r\n"); + } + } + + if((updateCh == XVPROCSS_VDMA_UPDATE_RD_CH) || + (updateCh == XVPROCSS_VDMA_UPDATE_ALL_CH) + ) + { + /* Setup RD CLIENT window size to output resolution */ + rdWin.StartX = 0; + rdWin.StartY = 0; + rdWin.Width = OutputWidth; + rdWin.Height = OutputHeight; + + status = XVprocss_VdmaReadSetup(pVprocss->vdma, + pVprocss->Config.UsrExtMemBaseAddr, + &rdWin, + OutputWidth, + OutputHeight, + pVprocss->idata.vdmaBytesPerPixel); + if(status != XST_SUCCESS) + { + xil_printf("VPROCSS ERR:: Unable to configure VDMA Read Channel \r\n"); + } + } +} + + +/*****************************************************************************/ +/** +* This function configures the VDMA RD/WR channel for UP scale (or 1:1) mode +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* @param updateCh defines VDMA channel (RD/WR or RD+WR) to update +* +* @return None +* +******************************************************************************/ +void XVprocss_SetVdmaWinToUpScaleMode(XVprocss *pVprocss, u32 updateCh) +{ + XVidC_VideoWindow wrWin, rdWin; + u32 InputWidth, InputHeight; + int status; + + InputWidth = pVprocss->idata.vidInWidth; + InputHeight = pVprocss->idata.vidInHeight; + + /*VDMA is before Scaler + WR client will receive streaming input + RD client will read Window from specified coordinates + */ + if((updateCh == XVPROCSS_VDMA_UPDATE_WR_CH) || + (updateCh == XVPROCSS_VDMA_UPDATE_ALL_CH)) + { + /* Setup WR Client window size to Input Resolution */ + wrWin.StartX = 0; + wrWin.StartY = 0; + wrWin.Width = InputWidth; + wrWin.Height = InputHeight; + + /* write input stream to DDR */ + status = XVprocss_VdmaWriteSetup(pVprocss->vdma, + pVprocss->Config.UsrExtMemBaseAddr, + &wrWin, + InputWidth, + InputHeight, + pVprocss->idata.vdmaBytesPerPixel); + if(status != XST_SUCCESS) + { + xil_printf("ERR:: Unable to configure VDMA Write Channel \r\n"); + } + } + + if((updateCh == XVPROCSS_VDMA_UPDATE_RD_CH) || + (updateCh == XVPROCSS_VDMA_UPDATE_ALL_CH) + ) + { + /* Setup RD CLIENT window size to either crop window or input resolution */ + if(XVprocss_IsZoomModeOn(pVprocss)) + { + /* Read user defined ZOOM window */ + XVprocss_GetZoomPipWindow(pVprocss, XVPROCSS_ZOOM_WIN, &rdWin); + } + else //set RD window to input resolution + { + rdWin.StartX = 0; + rdWin.StartY = 0; + rdWin.Width = InputWidth; + rdWin.Height = InputHeight; + } + + status = XVprocss_VdmaReadSetup(pVprocss->vdma, + pVprocss->Config.UsrExtMemBaseAddr, + &rdWin, + InputWidth, + InputHeight, + pVprocss->idata.vdmaBytesPerPixel); + if(status != XST_SUCCESS) + { + xil_printf("ERR:: Unable to configure VDMA Read Channel \r\n"); + } + } +} diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.h b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.h new file mode 100644 index 00000000..d136bb39 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_dma.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * + * 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_dma.h +* +* This header file contains the video processing engine DMA buffer management +* routines and helper functions. AXI-VDMA core is used to provide DMA +* functionality and the function contained herein provides a high level +* implementation of features provided by the IP, abstracting away the low +* level core configuration details from the user +* +* DMA Features +* +* The DMA supports following features +* - Abstract AXI-VDMA API to setup/program RD/WR channel +* - Start/Stop transfer on all channels with single call +* +* Initialization & Configuration +* +* The device driver enables higher layer software to communicate with the +* vdma core. +* +* Before using these API's subsystem must initialize the core by calling +* Layer-1 API's XAxiVdma_LookupConfig(). This function will look for a +* configuration structure for the device and XAxiVdma_CfgInitialize() will +* initialize it to defined HW settings. After initialization included API's +* can be used to configure the core. +* +* Interrupts +* +* Currently VDMA core does not generate any interrupts +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/18/15   Initial Release
+
+* 
+* +******************************************************************************/ +#ifndef XVPROCSS_DMA_H_ /* prevent circular inclusions */ +#define XVPROCSS_DMA_H_ /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +//#include "xaxivdma.h" +#include "xvprocss.h" +/************************** Constant Definitions *****************************/ + +/****************************** Type Definitions ******************************/ +/** + * This typedef enumerates the VDMA channel that needs update + */ +typedef enum +{ + XVPROCSS_VDMA_UPDATE_RD_CH = 0, + XVPROCSS_VDMA_UPDATE_WR_CH, + XVPROCSS_VDMA_UPDATE_ALL_CH +}XVPROCSS_VDMA_CH_UPDATE; + + +/************************** Function Prototypes ******************************/ +void XVprocss_VdmaStart(XAxiVdma *pVdma); +void XVprocss_VdmaStop(XAxiVdma *pVdma); +void XVprocss_VdmaReset(XAxiVdma *pVdma); +int XVprocss_VdmaWriteSetup(XAxiVdma *pVdma, + u32 WrBaseAddress, + XVidC_VideoWindow *window, + u32 FrameWidth, + u32 FrameHeight, + u32 Bpp); +int XVprocss_VdmaReadSetup(XAxiVdma *pVdma, + u32 RdBaseAddress, + XVidC_VideoWindow *window, + u32 FrameWidth, + u32 FrameHeight, + u32 Bpp); +int XVprocss_VdmaStartTransfer(XAxiVdma *pVdma); +void XVprocss_VdmaDbgReportStatus(XAxiVdma *pVdma, u32 Bpp); +void XVprocss_SetVdmaWinToUpScaleMode(XVprocss *pVprocss, u32 updateCh); +void XVprocss_SetVdmaWinToDnScaleMode(XVprocss *pVprocss, u32 updateCh); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c new file mode 100644 index 00000000..d5e81caf --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.c @@ -0,0 +1,757 @@ +/****************************************************************************** + * + * 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_router.c + +* Video buffer management routine. +* The functions in this file provides an abstraction from the register peek/poke +* methodology by implementing most common use-case provided by the VDMA sub-core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/18/15   Initial Release
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xvidc.h" +#include "xvprocss_router.h" +#include "xvprocss_dma.h" +/************************** Constant Definitions *****************************/ +/* AXIS Switch Port# connected to input stream */ +#define AXIS_SWITCH_VIDIN_S0 (0) + +/************************** Function Prototypes ******************************/ +static int validateWindowSize(const XVidC_VideoWindow *win, + const u32 HActive, + const u32 VActive); + +static XVprocss_ScaleMode GetScalingMode(XVprocss *pVprocss); + + +/*****************************************************************************/ +/** +* This function checks to make sure sub-frame is inside full frame +* +* @param win is a pointer to the sub-frame window +* @param Resolution is a pointer to the current output resolution +* +* @return XST_SUCCESS if window is valid else XST_FAILURE +* +******************************************************************************/ +static int validateWindowSize(const XVidC_VideoWindow *win, + const u32 HActive, + const u32 VActive) +{ + Xil_AssertNonvoid(win != NULL); + + //Check if window is valid + if((win->Width == 0) || (win->Height == 0)) + { + return(XST_FAILURE); + } + + //Check if window is within the Resolution being programmed + if(((win->StartX > HActive)) || + ((win->StartY > VActive)) || + ((win->StartX + win->Width) > HActive) || + ((win->StartY + win->Height) > VActive)) + { + return(XST_FAILURE); + } + else + { + return(XST_SUCCESS); + } +} + +/*****************************************************************************/ +/** +* This function computes the scaling mode based on input/output stream +* resolution. It also accounts for Zoom or PIP mode, if enabled +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* +* @return Scaling mode Up/Dpwn or 1:1 +* +******************************************************************************/ +static XVprocss_ScaleMode GetScalingMode(XVprocss *pVprocss) +{ + int status; + XVprocss_ScaleMode mode; + XVidC_VideoWindow win; + XVidC_VideoStream *pStrIn = &pVprocss->VidIn; + XVidC_VideoStream *pStrOut = &pVprocss->VidOut; + + if(XVprocss_IsPipModeOn(pVprocss)) + { + /* Read PIP window setting - set elsewhere */ + XVprocss_GetZoomPipWindow(pVprocss, XVPROCSS_PIP_WIN, &win); + /* validate window */ + status = validateWindowSize(&win, + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); + if(status != XST_SUCCESS) + { + xil_printf("VPROCSS ERR:: VDMA Write Channel Window Invalid \r\n"); + 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); + return(XVPROCSS_SCALE_NOT_SUPPORTED); + } + else + { + xil_printf("\r\n PIP Mode ON: Scale %dx%d -> %dx%d window in output stream\r\n", + pStrIn->Timing.HActive, + pStrIn->Timing.VActive, + pVprocss->idata.wrWindow.Width, + pVprocss->idata.wrWindow.Height); + + return(XVPROCSS_SCALE_DN); + } + } + + if(XVprocss_IsZoomModeOn(pVprocss)) + { + /* Read PIP window setting - set elsewhere */ + XVprocss_GetZoomPipWindow(pVprocss, XVPROCSS_ZOOM_WIN, &win); + /* validate window */ + status = validateWindowSize(&win, + pStrIn->Timing.HActive, + pStrIn->Timing.VActive); + if(status != XST_SUCCESS) + { + xil_printf("ERR:: VDMA Read Channel Window Invalid \r\n"); + 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); + return(XVPROCSS_SCALE_NOT_SUPPORTED); + } + else + { + xil_printf("\r\n Zoom Mode ON: Scale %dx%d window from Input Stream -> %dx%d\r\n", + pVprocss->idata.rdWindow.Width, + pVprocss->idata.rdWindow.Height, + pStrOut->Timing.HActive, + pStrOut->Timing.VActive); + + return (XVPROCSS_SCALE_UP); + } + } + + /* Pip & Zoom mode are off. Check input/output resolution */ + if((pStrIn->Timing.HActive > pStrOut->Timing.HActive) || + (pStrIn->Timing.VActive > pStrOut->Timing.VActive)) + { + mode = XVPROCSS_SCALE_DN; + } + else if((pStrIn->Timing.HActive < pStrOut->Timing.HActive) || + (pStrIn->Timing.VActive < pStrOut->Timing.VActive)) + { + mode = XVPROCSS_SCALE_UP; + } + else + { + mode = XVPROCSS_SCALE_1_1; + } + return(mode); +} + +/*****************************************************************************/ +/** +* This function examines the subsystem Input/Output Stream configuration and +* builds a routing table for the supported use-case. The computed routing +* table is stored in the scratch pad memory +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* +* @return XST_SUCCESS if routing table can be created else XST_FAILURE +* +******************************************************************************/ +int XVprocss_BuildRoutingTable(XVprocss *pVprocss) +{ +#ifdef DEBUG + const char *ipStr[XVPROCSS_RTR_MAX] = + { + "VID_OUT", + "SCALER-V", + "SCALER-H", + "VDMA", + "LBOX", + "CR-H", + "CR-VIn", + "CR-VOut", + "CSC", + "DEINT", + }; +#endif + + u32 index = 0; + XVidC_VideoStream *pStrIn = &pVprocss->VidIn; + XVidC_VideoStream *pStrOut = &pVprocss->VidOut; + XVprocss_IData *pCfg = &pVprocss->idata; + u8 *pTable = &pVprocss->idata.RtngTable[0]; + int status = XST_SUCCESS; + + xdbg_printf(XDBG_DEBUG_GENERAL," ->Build AXIS Routing Map for Subsystem Use-Case.... \r\n"); + + /* Save input resolution */ + pCfg->vidInWidth = pStrIn->Timing.HActive; + pCfg->vidInHeight = pStrIn->Timing.VActive; + pCfg->strmCformat = pStrIn->ColorFormatId; + + /* Determine Scaling Mode */ + pVprocss->idata.memEn = FALSE; + pVprocss->idata.ScaleMode = GetScalingMode(pVprocss); + if(pVprocss->idata.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)); + + /* Check if input is I/P */ + if(pStrIn->IsInterlaced) + { + if(pStrIn->ColorFormatId != XVIDC_CSF_YCRCB_420) + { + if(pVprocss->deint) + { + if((pVprocss->VidIn.VmId != XVIDC_VM_1080_60_I) && + (pVprocss->VidIn.VmId != XVIDC_VM_1080_50_I)) + { + xil_printf("VPROCSS ERR:: De-Interlacer supports only 1080i Input\r\n"); + return(XST_FAILURE); + } + pTable[index++] = XVPROCSS_RTR_DEINT; + } + else + { + xil_printf("VPROCSS ERR:: De-Interlacer IP not found - Interlaced Input not supported\r\n"); + return(XST_FAILURE); + } + } + else //YUV_420 + { + xil_printf("VPROCSS ERR:: Interlaced 420 input not supported\r\n"); + return(XST_FAILURE); + } + } + + /* Check if input is 420 */ + if(pStrIn->ColorFormatId == XVIDC_CSF_YCRCB_420) + { + if(pVprocss->vcrsmplrIn) //up-sample vertically to 422 as none of the IP supports 420 + { + pTable[index++] = XVPROCSS_RTR_CR_V_IN; + pCfg->strmCformat = XVIDC_CSF_YCRCB_422; + } + else //V Chroma Resampler IP not included in design + { + xil_printf("VPROCSS ERR:: Vertical Chroma Resampler IP not found. YUV420 Input not supported\r\n"); + return(XST_FAILURE); + } + } + + switch(pVprocss->idata.ScaleMode) + { + case XVPROCSS_SCALE_1_1: + pTable[index++] = XVPROCSS_RTR_VDMA; + pVprocss->idata.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; + 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; + break; + + default: + xil_printf("VPROCSS ERR:: Scaling Mode cannot be determined.\r\n"); + return(XST_FAILURE); + break; + } + + /* Send stream to LBox to add H/V bars, if needed */ + pTable[index++] = XVPROCSS_RTR_LBOX; + + /* Check for input and output color format to derive required conversions */ + switch(pStrOut->ColorFormatId) + { + case XVIDC_CSF_YCRCB_420: + switch(pStrIn->ColorFormatId) + { + case XVIDC_CSF_RGB: + pTable[index++] = XVPROCSS_RTR_CSC; //convert RGB->444 + pTable[index++] = XVPROCSS_RTR_CR_H; //convert 444->422 + pTable[index++] = XVPROCSS_RTR_CR_V_OUT; //convert 422->420 + pCfg->cscIn = XVIDC_CSF_RGB; + pCfg->cscOut = XVIDC_CSF_YCRCB_444; + pCfg->hcrIn = XVIDC_CSF_YCRCB_444; + pCfg->hcrOut = XVIDC_CSF_YCRCB_422; + break; + + case XVIDC_CSF_YCRCB_444: + pTable[index++] = XVPROCSS_RTR_CSC; //picture control in 444 + pTable[index++] = XVPROCSS_RTR_CR_H; //convert 444->422 + pTable[index++] = XVPROCSS_RTR_CR_V_OUT; //convert 422->420 + pCfg->cscIn = XVIDC_CSF_YCRCB_444; + pCfg->cscOut = XVIDC_CSF_YCRCB_444; + pCfg->hcrIn = XVIDC_CSF_YCRCB_444; + pCfg->hcrOut = XVIDC_CSF_YCRCB_422; + break; + + case XVIDC_CSF_YCRCB_422: + case XVIDC_CSF_YCRCB_420: //Input was up converted to 422 + pTable[index++] = XVPROCSS_RTR_CSC; //picture control in 422 + pTable[index++] = XVPROCSS_RTR_CR_V_OUT; //convert 422->420 + pCfg->cscIn = XVIDC_CSF_YCRCB_422; + pCfg->cscOut = XVIDC_CSF_YCRCB_422; + break; + + default: //Unsupported color format + xil_printf("VPROCSS ERR:: Input Color Format Not Supported \r\n"); + status = XST_FAILURE; + break; + } + break; + + case XVIDC_CSF_RGB: + switch(pStrIn->ColorFormatId) + { + case XVIDC_CSF_RGB: + case XVIDC_CSF_YCRCB_444: //convert 444->RGB + pTable[index++] = XVPROCSS_RTR_CSC; + pCfg->cscIn = pStrIn->ColorFormatId; + pCfg->cscOut = XVIDC_CSF_RGB; + break; + + case XVIDC_CSF_YCRCB_422: + case XVIDC_CSF_YCRCB_420: //Input was up converted to 422 + pTable[index++] = XVPROCSS_RTR_CR_H; //convert 422->444 + pTable[index++] = XVPROCSS_RTR_CSC; //convert 444->RGB + pCfg->hcrIn = XVIDC_CSF_YCRCB_422; + pCfg->hcrOut = XVIDC_CSF_YCRCB_444; + pCfg->cscIn = XVIDC_CSF_YCRCB_444; + pCfg->cscOut = XVIDC_CSF_RGB; + break; + + default: //Unsupported color format + xil_printf("VPROCSS ERR:: Input Color Format Not Supported \r\n"); + status = XST_FAILURE; + break; + } + break; + + case XVIDC_CSF_YCRCB_422: + switch(pStrIn->ColorFormatId) + { + case XVIDC_CSF_RGB: + pTable[index++] = XVPROCSS_RTR_CSC; //convert RGB->444 + pTable[index++] = XVPROCSS_RTR_CR_H; //convert 444->422 + pCfg->cscIn = XVIDC_CSF_RGB; + pCfg->cscOut = XVIDC_CSF_YCRCB_444; + pCfg->hcrIn = XVIDC_CSF_YCRCB_444; + pCfg->hcrOut = XVIDC_CSF_YCRCB_422; + break; + + case XVIDC_CSF_YCRCB_444: + pTable[index++] = XVPROCSS_RTR_CSC; //picture control in 444 + pTable[index++] = XVPROCSS_RTR_CR_H; //convert 444->422 + pCfg->cscIn = XVIDC_CSF_YCRCB_444; + pCfg->cscOut = XVIDC_CSF_YCRCB_444; + pCfg->hcrIn = XVIDC_CSF_YCRCB_444; + pCfg->hcrOut = XVIDC_CSF_YCRCB_422; + break; + + case XVIDC_CSF_YCRCB_422: + case XVIDC_CSF_YCRCB_420: //Input was up converted to 422 + pTable[index++] = XVPROCSS_RTR_CSC; //picture control in 422 + pCfg->cscIn = XVIDC_CSF_YCRCB_422; + pCfg->cscOut = XVIDC_CSF_YCRCB_422; + break; + + default: //Unsupported color format + xil_printf("VPROCSS ERR:: Input Color Format Not Supported \r\n"); + status = XST_FAILURE; + break; + } + break; + + case XVIDC_CSF_YCRCB_444: + switch(pStrIn->ColorFormatId) + { + case XVIDC_CSF_RGB: //convert 444->RGB + case XVIDC_CSF_YCRCB_444: + pTable[index++] = XVPROCSS_RTR_CSC; + pCfg->cscIn = pStrIn->ColorFormatId; + pCfg->cscOut = XVIDC_CSF_YCRCB_444; + break; + + case XVIDC_CSF_YCRCB_422: + case XVIDC_CSF_YCRCB_420: //Input was up converted to 422 + pTable[index++] = XVPROCSS_RTR_CR_H; //convert 422->444 + pTable[index++] = XVPROCSS_RTR_CSC; //picture control + pCfg->hcrIn = XVIDC_CSF_YCRCB_422; + pCfg->hcrOut = XVIDC_CSF_YCRCB_444; + pCfg->cscIn = XVIDC_CSF_YCRCB_444; + pCfg->cscOut = XVIDC_CSF_YCRCB_444; + break; + + default: //Unsupported color format + xil_printf("VPROCSS ERR:: Input Color Format Not Supported \r\n"); + status = XST_FAILURE; + break; + } + break; + + default: + xil_printf("VPROCSS ERR:: Output Color Format Not Supported \r\n"); + status = XST_FAILURE; + break; + } + + /* Connect Last IP in chain to switch output */ + pTable[index++] = XVPROCSS_RTR_VIDOUT; + + /* save number of cores in processing path */ + pVprocss->idata.RtrNumCores = index; + +#ifdef DEBUG + if(status == XST_SUCCESS) + { + u32 count = 0; + + //print IP Data Flow Map + xil_printf("\r\nGenerated Map: VidIn"); + while(count %s",ipStr[pTable[count++]]); + } + xil_printf("\r\n\r\n"); + } +#endif + + return(status); +} + +/*****************************************************************************/ +/** +* This function traverses the computed routing table and sets up the AXIS +* switch registers, to route the stream through processing cores, in the order +* defined in the routing map +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XVprocss_ProgRouterMux(XVprocss *pVprocss) +{ + u32 count, nextMi, prevSi; + u8 *pTable = &pVprocss->idata.RtngTable[0]; + u32 numProcElem = pVprocss->idata.RtrNumCores; + + XAxisScr_RegUpdateDisable(pVprocss->router); + + /* Disable all ports */ + XAxisScr_MiPortDisableAll(pVprocss->router); + + /* Connect Input Stream to the 1st core in path */ + nextMi = prevSi = pTable[0]; + XAxisScr_MiPortEnable(pVprocss->router, nextMi, AXIS_SWITCH_VIDIN_S0); + + /* Traverse routing map and connect cores in the chain */ + for(count=1; countrouter, nextMi, prevSi); + prevSi = nextMi; + } + + //Enable Router register update + XAxisScr_RegUpdateEnable(pVprocss->router); +} + +/*****************************************************************************/ +/** +* This function traverses the routing map built earlier and configures each +* sub-core in the processing path per its location in the chain. +* Each core in the processing path is marked and only marked cores are started +* All remaining cores stay disabled +* +* @param pVprocss is a pointer to the Subsystem instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss) +{ + XVidC_VideoWindow lboxWin; + u32 vsc_WidthIn, vsc_HeightIn, vsc_HeightOut; + u32 hsc_HeightIn, hsc_WidthIn, hsc_WidthOut; + u32 count; + XVprocss_IData *pCfg = &pVprocss->idata; + u8 *pTable = &pVprocss->idata.RtngTable[0]; + u8 *pStartCore = &pVprocss->idata.startCore[0]; + vsc_WidthIn = vsc_HeightIn = vsc_HeightOut = 0; + hsc_HeightIn = hsc_WidthIn = hsc_WidthOut = 0; + + /* Program Video Pipe Sub-Cores */ + if(pVprocss->VidIn.IsInterlaced) + { + /* Input will de-interlaced first. All downstream IP's work + * with progressive frame. Adjust active height to reflect the + * progressive frame to downstream cores + */ + pVprocss->idata.vidInHeight *= 2; + } + + /* If Vdma is enabled, RD/WR Client needs to be programmed before Scaler */ + if((pVprocss->vdma) && (pVprocss->idata.memEn)) + { + switch(pVprocss->idata.ScaleMode) + { + case XVPROCSS_SCALE_1_1: + case XVPROCSS_SCALE_UP: + XVprocss_SetVdmaWinToUpScaleMode(pVprocss, XVPROCSS_VDMA_UPDATE_ALL_CH); + break; + + case XVPROCSS_SCALE_DN: + XVprocss_SetVdmaWinToDnScaleMode(pVprocss, XVPROCSS_VDMA_UPDATE_ALL_CH); + break; + + default: + break; + } + pStartCore[XVPROCSS_RTR_VDMA] = TRUE; + } + + for(count=0; countidata.RtrNumCores; ++count) + { + switch(pTable[count]) + { + case XVPROCSS_RTR_SCALER_V: + if(pVprocss->vscaler) + { + if(pVprocss->idata.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 + : 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_HeightOut = pVprocss->VidOut.Timing.VActive; + } + + 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); + pStartCore[XVPROCSS_RTR_SCALER_V] = TRUE; + } + break; + + case XVPROCSS_RTR_SCALER_H: + if(pVprocss->hscaler) + { + if(pVprocss->idata.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 + : pVprocss->VidOut.Timing.HActive); + } + else + { + /* Upscale mode V Scaler is before H Scaler */ + hsc_WidthIn = vsc_WidthIn; + hsc_HeightIn = vsc_HeightOut; + hsc_WidthOut = pVprocss->VidOut.Timing.HActive; + } + + 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->Config.PixPerClock, + pVprocss->idata.strmCformat); + pStartCore[XVPROCSS_RTR_SCALER_H] = TRUE; + } + break; + + case XVPROCSS_RTR_VDMA: + /* NOP - Programmed before the switch statement */ + break; + + case XVPROCSS_RTR_LBOX: + if(pVprocss->lbox) + { + if(XVprocss_IsPipModeOn(pVprocss)) + { + /* get the active window for lbox */ + lboxWin = pVprocss->idata.wrWindow; + } + else //Downscale - Read full image from VDMA + { + /* window is same as output resolution */ + lboxWin.StartX = 0; + lboxWin.StartY = 0; + lboxWin.Width = pVprocss->VidOut.Timing.HActive; + lboxWin.Height = pVprocss->VidOut.Timing.VActive; + } + XV_LBoxSetActiveWin(pVprocss->lbox, + &lboxWin, + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); + pStartCore[XVPROCSS_RTR_LBOX] = TRUE; + } + break; + + case XVPROCSS_RTR_CR_H: + if(pVprocss->hcrsmplr) + { + XV_HCrsmplSetActiveSize(pVprocss->hcrsmplr, + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); + + XV_HCrsmplSetFormat(pVprocss->hcrsmplr, + pCfg->hcrIn, + pCfg->hcrOut); + pStartCore[XVPROCSS_RTR_CR_H] = TRUE; + } + break; + + case XVPROCSS_RTR_CR_V_IN: + if(pVprocss->vcrsmplrIn) + { + XV_VCrsmplSetActiveSize(pVprocss->vcrsmplrIn, + pVprocss->idata.vidInWidth, + pVprocss->idata.vidInHeight); + + XV_VCrsmplSetFormat(pVprocss->vcrsmplrIn, + XVIDC_CSF_YCRCB_420, + XVIDC_CSF_YCRCB_422); + pStartCore[XVPROCSS_RTR_CR_V_IN] = TRUE; + } + break; + + case XVPROCSS_RTR_CR_V_OUT: + if(pVprocss->vcrsmplrOut) + { + XV_VCrsmplSetActiveSize(pVprocss->vcrsmplrOut, + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); + + XV_VCrsmplSetFormat(pVprocss->vcrsmplrOut, + XVIDC_CSF_YCRCB_422, + XVIDC_CSF_YCRCB_420); + pStartCore[XVPROCSS_RTR_CR_V_OUT] = TRUE; + } + break; + + case XVPROCSS_RTR_CSC: + if(pVprocss->csc) + { + XV_CscSetColorspace(pVprocss->csc, + &pVprocss->cscL2Reg, + pVprocss->idata.cscIn, + pVprocss->idata.cscOut, + pVprocss->cscL2Reg.StandardIn, + pVprocss->cscL2Reg.StandardOut, + pVprocss->cscL2Reg.OutputRange); + + XV_CscSetActiveSize(pVprocss->csc, + pVprocss->VidOut.Timing.HActive, + pVprocss->VidOut.Timing.VActive); + + pStartCore[XVPROCSS_RTR_CSC] = TRUE; + } + break; + + case XVPROCSS_RTR_DEINT: + if(pVprocss->deint) + { + 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); + + XV_DeintSetFieldBuffers(pVprocss->deint, + pVprocss->idata.deintBufAddr, + pVprocss->VidIn.ColorFormatId); + pStartCore[XVPROCSS_RTR_DEINT] = TRUE; + } + break; + } + } + + /* Start all IP Blocks in the processing chain */ + XVprocss_Start(pVprocss); +} diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.h b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.h new file mode 100644 index 00000000..0418a40c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_router.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * 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_router.h +* +* This header file contains the video processing engine data flow setup +* routines and helper functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/18/15   Initial Release
+
+* 
+* +******************************************************************************/ +#ifndef XVPROCSS_ROUTER_H__ /* prevent circular inclusions */ +#define XVPROCSS_ROUTER_H__ /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +//#include "xaxivdma.h" +#include "xvprocss.h" +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +int XVprocss_BuildRoutingTable(XVprocss *pVprocss); +void XVprocss_ProgRouterMux(XVprocss *pVprocss); +void XVprocss_SetupRouterDataFlow(XVprocss *pVprocss); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_sinit.c b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_sinit.c new file mode 100644 index 00000000..ed586228 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/vprocss/src/xvprocss_sinit.c @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * 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_sinit.c +* +* This file contains the implementation of the Video Processing Subsystem +* driver's static initialization functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00  rc   05/01/15   Initial Release
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" +#include "xvprocss.h" + +/************************** Constant Definitions *****************************/ +//ToDo: This will be exported to xparameters.h +#define XPAR_XDSPSS_NUM_INSTANCES (1) + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XVprocss_Config XVprocss_ConfigTable[XPAR_XDSPSS_NUM_INSTANCES]; + +/*****************************************************************************/ +/** +* This function looks for the device configuration based on the unique device +* ID. The table XVprocss_ConfigTable[] contains the configuration information +* for each instance of the device in the system. +* +* @param DeviceId is the unique device ID of the device being looked up +* +* @return A pointer to the configuration table entry corresponding to the +* given device ID, or NULL if no match is found +* +*******************************************************************************/ +XVprocss_Config* XVprocss_LookupConfig(u32 DeviceId) +{ + XVprocss_Config *CfgPtr = NULL; + u32 index; + + for (index = 0U; index < (u32)XPAR_XDSPSS_NUM_INSTANCES; index++) + { + if (XVprocss_ConfigTable[index].DeviceId == DeviceId) + { + CfgPtr = &XVprocss_ConfigTable[index]; + break; + } + } + return (CfgPtr); +}