diff --git a/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.c b/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.c index d23a99bc..d1a2224d 100644 --- a/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.c +++ b/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.c @@ -72,8 +72,13 @@ const short XV_vscaler_fixedcoeff_taps10[XV_VSCALER_MAX_V_PHASES][XV_VSCALER_TAP const short XV_vscaler_fixedcoeff_taps12[XV_VSCALER_MAX_V_PHASES][XV_VSCALER_TAPS_12]; /************************** Function Prototypes ******************************/ +static void XV_VScalerSelectCoeff(XV_vscaler *InstancePtr, + XV_vscaler_l2 *VscL2DataPtr, + u32 HeightIn, + u32 HeightOut); + static void XV_VScalerSetCoeff(XV_vscaler *pVsc, - XV_vscaler_l2 *pVscL2Data); + XV_vscaler_l2 *VscL2DataPtr); /*****************************************************************************/ /** @@ -114,54 +119,119 @@ void XV_VScalerStop(XV_vscaler *InstancePtr) * storage based on the selected TAP configuration * * @param InstancePtr is a pointer to the core instance to be worked on. -* @param pVscL2Data is a pointer to the core instance layer 2 data. -* +* @param VscL2DataPtr is a pointer to the core instance layer 2 data. +* @param WidthIn is the input stream height +* @param Widthout is the output stream height + * @return None * ******************************************************************************/ -void XV_VScalerLoadDefaultCoeff(XV_vscaler *InstancePtr, - XV_vscaler_l2 *pVscL2Data) +static void XV_VScalerSelectCoeff(XV_vscaler *InstancePtr, + XV_vscaler_l2 *VscL2DataPtr, + u32 HeightIn, + u32 HeightOut) { const short *coeff; u16 numTaps, numPhases; + u16 ScalingRatio; + u16 IsScaleDown; /* * validates input arguments */ Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(pVscL2Data != NULL); + Xil_AssertVoid(VscL2DataPtr != NULL); - numTaps = InstancePtr->Config.NumTaps; numPhases = (1<Config.PhaseShift); - switch(numTaps) + IsScaleDown = (HeightOut < HeightIn); + /* Scale Down Mode will use dynamic filter selection logic + * Scale Up Mode (including 1:1) will always use 6 tap filter + */ + if(IsScaleDown) { - case XV_VSCALER_TAPS_6: - coeff = &XV_vscaler_fixedcoeff_taps6[0][0]; - break; + ScalingRatio = ((HeightIn * 10)/HeightOut); - case XV_VSCALER_TAPS_8: - coeff = &XV_vscaler_fixedcoeff_taps8[0][0]; - break; + switch(InstancePtr->Config.NumTaps) + { + case XV_VSCALER_TAPS_6: + coeff = &XV_vscaler_fixedcoeff_taps6[0][0]; + numTaps = XV_VSCALER_TAPS_6; + break; - case XV_VSCALER_TAPS_10: - coeff = &XV_vscaler_fixedcoeff_taps10[0][0]; - break; + case XV_VSCALER_TAPS_8: + if(ScalingRatio > 15) + { + coeff = &XV_vscaler_fixedcoeff_taps8[0][0]; + numTaps = XV_VSCALER_TAPS_8; + } + else // <= 1.5 + { + coeff = &XV_vscaler_fixedcoeff_taps6[0][0]; + numTaps = XV_VSCALER_TAPS_6; + } + break; + + case XV_VSCALER_TAPS_10: + if(ScalingRatio > 25) // >2.5 + { + coeff = &XV_vscaler_fixedcoeff_taps10[0][0]; + numTaps = XV_VSCALER_TAPS_10; + } + else if(ScalingRatio > 15) // 1.6 < ratio <= 2.5 + { + coeff = &XV_vscaler_fixedcoeff_taps8[0][0]; + numTaps = XV_VSCALER_TAPS_8; + } + else // <= 1.5 + { + coeff = &XV_vscaler_fixedcoeff_taps6[0][0]; + numTaps = XV_VSCALER_TAPS_6; + } + break; case XV_VSCALER_TAPS_12: - coeff = &XV_vscaler_fixedcoeff_taps12[0][0]; - break; + if(ScalingRatio > 35) // > 3.5 + { + coeff = &XV_vscaler_fixedcoeff_taps12[0][0]; + numTaps = XV_VSCALER_TAPS_12; + } + else if(ScalingRatio > 25) //2.6 < Ratio <= 3.5 + { + coeff = &XV_vscaler_fixedcoeff_taps10[0][0]; + numTaps = XV_VSCALER_TAPS_10; + } + else if(ScalingRatio > 15) //1.6 < Ratio <= 2.5 + { + coeff = &XV_vscaler_fixedcoeff_taps8[0][0]; + numTaps = XV_VSCALER_TAPS_8; + } + else // <= 1.5 + { + coeff = &XV_vscaler_fixedcoeff_taps6[0][0]; + numTaps = XV_VSCALER_TAPS_6; + } + break; default: - xil_printf("ERR: V-Scaler %d Taps Not Supported",numTaps); + xil_printf("ERR: H-Scaler %d Taps Not Supported",numTaps); return; } + } + else //Scale Up + { + coeff = &XV_vscaler_fixedcoeff_taps6[0][0]; + numTaps = XV_VSCALER_TAPS_6; + } - XV_VScalerLoadUsrCoeff(InstancePtr, - pVscL2Data, - numPhases, - numTaps, - coeff); + XV_VScalerLoadExtCoeff(InstancePtr, + VscL2DataPtr, + numPhases, + numTaps, + coeff); + + /* Disable use of external coefficients */ + VscL2DataPtr->UseExtCoeff = FALSE; } /*****************************************************************************/ @@ -170,7 +240,7 @@ void XV_VScalerLoadDefaultCoeff(XV_vscaler *InstancePtr, * storage * * @param InstancePtr is a pointer to the core instance to be worked on. -* @param pVscL2Data is a pointer to the core instance layer 2 data. +* @param VscL2DataPtr is a pointer to the core instance layer 2 data. * @param num_phases is the number of phases in coefficient table * @param num_taps is the number of taps in coefficient table * @param Coeff is a pointer to user defined filter coefficients table @@ -178,8 +248,8 @@ void XV_VScalerLoadDefaultCoeff(XV_vscaler *InstancePtr, * @return None * ******************************************************************************/ -void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, - XV_vscaler_l2 *pVscL2Data, +void XV_VScalerLoadExtCoeff(XV_vscaler *InstancePtr, + XV_vscaler_l2 *VscL2DataPtr, u16 num_phases, u16 num_taps, const short *Coeff) @@ -190,7 +260,7 @@ void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, * validate input arguments */ Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(pVscL2Data != NULL); + Xil_AssertVoid(VscL2DataPtr != NULL); Xil_AssertVoid(num_taps <= InstancePtr->Config.NumTaps); Xil_AssertVoid(num_phases == (1<Config.PhaseShift)); Xil_AssertVoid(Coeff != NULL); @@ -209,7 +279,7 @@ void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, } //determine if coefficient needs padding (effective vs. max taps) - pad = XV_VSCALER_MAX_V_TAPS - InstancePtr->Config.NumTaps; + pad = XV_VSCALER_MAX_V_TAPS - num_taps; offset = ((pad) ? (pad>>1) : 0); //Load User defined coefficients into scaler coefficient table @@ -217,7 +287,7 @@ void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, { for (j=0; jcoeff[i][j+offset] = Coeff[i*num_taps+j]; + VscL2DataPtr->coeff[i][j+offset] = Coeff[i*num_taps+j]; } } @@ -228,18 +298,18 @@ void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, //pad left for (j = 0; j < offset; j++) { - pVscL2Data->coeff[i][j] = 0; + VscL2DataPtr->coeff[i][j] = 0; } //pad right for (j = (num_taps+offset); j < XV_VSCALER_MAX_V_TAPS; j++) { - pVscL2Data->coeff[i][j] = 0; + VscL2DataPtr->coeff[i][j] = 0; } } } /* Enable use of external coefficients */ - pVscL2Data->UseExtCoeff = TRUE; + VscL2DataPtr->UseExtCoeff = TRUE; } /*****************************************************************************/ @@ -260,7 +330,7 @@ void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, * computed coefficients ******************************************************************************/ static void XV_VScalerSetCoeff(XV_vscaler *pVsc, - XV_vscaler_l2 *pVscL2Data) + XV_vscaler_l2 *VscL2DataPtr) { int num_phases = 1<Config.PhaseShift; int num_taps = pVsc->Config.NumTaps/2; @@ -274,7 +344,7 @@ static void XV_VScalerSetCoeff(XV_vscaler *pVsc, for(j=0; j < num_taps; j++) { rdIndx = j*2+offset; - val = (pVscL2Data->coeff[i][rdIndx+1] << 16) | (pVscL2Data->coeff[i][rdIndx] & XVSC_MASK_LOW_16BITS); + val = (VscL2DataPtr->coeff[i][rdIndx+1] << 16) | (VscL2DataPtr->coeff[i][rdIndx] & XVSC_MASK_LOW_16BITS); Xil_Out32(baseAddr+((i*num_taps+j)*4), val); } } @@ -294,7 +364,7 @@ static void XV_VScalerSetCoeff(XV_vscaler *pVsc, * ******************************************************************************/ void XV_VScalerSetup(XV_vscaler *InstancePtr, - XV_vscaler_l2 *pVscL2Data, + XV_vscaler_l2 *VscL2DataPtr, u32 WidthIn, u32 HeightIn, u32 HeightOut) @@ -305,7 +375,7 @@ void XV_VScalerSetup(XV_vscaler *InstancePtr, * Assert validates the input arguments */ Xil_AssertVoid(InstancePtr != NULL); - Xil_AssertVoid(pVscL2Data != NULL); + Xil_AssertVoid(VscL2DataPtr != NULL); Xil_AssertVoid((WidthIn>0) && (WidthIn<=InstancePtr->Config.MaxWidth)); Xil_AssertVoid((HeightIn>0) && (HeightIn<=InstancePtr->Config.MaxHeight)); Xil_AssertVoid((HeightOut>0) && (HeightOut<=InstancePtr->Config.MaxHeight)); @@ -314,14 +384,17 @@ void XV_VScalerSetup(XV_vscaler *InstancePtr, if(InstancePtr->Config.ScalerType == XV_VSCALER_POLYPHASE) { - if(!pVscL2Data->UseExtCoeff) //No predefined coefficients + if(!VscL2DataPtr->UseExtCoeff) //No user defined coefficients { - xil_printf("\r\nERR: V Scaler coefficients not programmed\r\n"); - return; + /* Determine coefficient table to use */ + XV_VScalerSelectCoeff(InstancePtr, + VscL2DataPtr, + HeightIn, + HeightOut); } /* Program coefficients into the IP register bank */ - XV_VScalerSetCoeff(InstancePtr, pVscL2Data); + XV_VScalerSetCoeff(InstancePtr, VscL2DataPtr); } LineRate = (HeightIn * STEP_PRECISION)/HeightOut; diff --git a/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.h b/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.h index 0fded803..de8d7b68 100644 --- a/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.h +++ b/XilinxProcessorIPLib/drivers/v_vscaler/src/xv_vscaler_l2.h @@ -160,15 +160,13 @@ typedef struct /************************** Function Prototypes ******************************/ void XV_VScalerStart(XV_vscaler *InstancePtr); void XV_VScalerStop(XV_vscaler *InstancePtr); -void XV_VScalerLoadDefaultCoeff(XV_vscaler *InstancePtr, - XV_vscaler_l2 *pVscL2Data); -void XV_VScalerLoadUsrCoeff(XV_vscaler *InstancePtr, - XV_vscaler_l2 *pVscL2Data, +void XV_VScalerLoadExtCoeff(XV_vscaler *InstancePtr, + XV_vscaler_l2 *VscL2DataPtr, u16 num_phases, u16 num_taps, const short *Coeff); void XV_VScalerSetup(XV_vscaler *InstancePtr, - XV_vscaler_l2 *pVscL2Data, + XV_vscaler_l2 *VscL2DataPtr, u32 WidthIn, u32 HeightIn, u32 HeightOut);