Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *  linux/drivers/video/kyro/STG4000OverlayDevice.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Copyright (C) 2000 Imagination Technologies Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2002 STMicroelectronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * License.  See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "STG4000Reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "STG4000Interface.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /* HW Defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define STG4000_NO_SCALING    0x800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define STG4000_NO_DECIMATION 0xFFFFFFFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) /* Primary surface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define STG4000_PRIM_NUM_PIX   5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define STG4000_PRIM_ALIGN     4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define STG4000_PRIM_ADDR_BITS 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define STG4000_PRIM_MIN_WIDTH  640
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define STG4000_PRIM_MAX_WIDTH  1600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define STG4000_PRIM_MIN_HEIGHT 480
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define STG4000_PRIM_MAX_HEIGHT 1200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) /* Overlay surface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define STG4000_OVRL_NUM_PIX   4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define STG4000_OVRL_ALIGN     2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define STG4000_OVRL_ADDR_BITS 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define STG4000_OVRL_NUM_MODES 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define STG4000_OVRL_MIN_WIDTH  0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define STG4000_OVRL_MAX_WIDTH  720
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define STG4000_OVRL_MIN_HEIGHT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define STG4000_OVRL_MAX_HEIGHT 576
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) /* Decimation and Scaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static u32 adwDecim8[33] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	    0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	    0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	    0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	    0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	    0xa4924925, 0x92491249, 0x91224489, 0x91111111, 0x90884211,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	    0x88410821, 0x88102041, 0x81010101, 0x80800801, 0x80010001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	    0x80000001, 0x00000001, 0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) typedef struct _OVRL_SRC_DEST {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	/*clipped on-screen pixel position of overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	u32 ulDstX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	u32 ulDstY1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	u32 ulDstX2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	u32 ulDstY2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	/*clipped pixel pos of source data within buffer thses need to be 128 bit word aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	u32 ulSrcX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	u32 ulSrcY1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	u32 ulSrcX2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	u32 ulSrcY2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	/* on-screen pixel position of overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	s32 lDstX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	s32 lDstY1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	s32 lDstX2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	s32 lDstY2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) } OVRL_SRC_DEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static u32 ovlWidth, ovlHeight, ovlStride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static int ovlLinear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	/* Set Overlay address to default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	tmp = STG_READ_REG(DACOverlayAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	CLEAR_BITS_FRM_TO(0, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	CLEAR_BIT(31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	STG_WRITE_REG(DACOverlayAddr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	/* Set Overlay U address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	tmp = STG_READ_REG(DACOverlayUAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	CLEAR_BITS_FRM_TO(0, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	STG_WRITE_REG(DACOverlayUAddr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	/* Set Overlay V address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	tmp = STG_READ_REG(DACOverlayVAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	CLEAR_BITS_FRM_TO(0, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	STG_WRITE_REG(DACOverlayVAddr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	/* Set Overlay Size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	tmp = STG_READ_REG(DACOverlaySize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	CLEAR_BITS_FRM_TO(0, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	CLEAR_BITS_FRM_TO(12, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	STG_WRITE_REG(DACOverlaySize, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	/* Set Overlay Vt Decimation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	tmp = STG4000_NO_DECIMATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	STG_WRITE_REG(DACOverlayVtDec, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	/* Set Overlay format to default value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	tmp = STG_READ_REG(DACPixelFormat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	CLEAR_BITS_FRM_TO(4, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	CLEAR_BITS_FRM_TO(16, 22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	STG_WRITE_REG(DACPixelFormat, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	/* Set Vertical scaling to default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	tmp = STG_READ_REG(DACVerticalScal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	CLEAR_BITS_FRM_TO(0, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	CLEAR_BITS_FRM_TO(16, 22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	tmp |= STG4000_NO_SCALING;	/* Set to no scaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	STG_WRITE_REG(DACVerticalScal, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	/* Set Horizontal Scaling to default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	tmp = STG_READ_REG(DACHorizontalScal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	CLEAR_BITS_FRM_TO(0, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	CLEAR_BITS_FRM_TO(16, 17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	tmp |= STG4000_NO_SCALING;	/* Set to no scaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	STG_WRITE_REG(DACHorizontalScal, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	/* Set Blend mode to Alpha Blend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	/* ????? SG 08/11/2001 Surely this isn't the alpha blend mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	   hopefully its overwrite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	tmp = STG_READ_REG(DACBlendCtrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	CLEAR_BITS_FRM_TO(0, 30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	tmp = (GRAPHICS_MODE << 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	STG_WRITE_REG(DACBlendCtrl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			 u32 inWidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			 u32 inHeight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			 int bLinear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			 u32 ulOverlayOffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			 u32 * retStride, u32 * retUVStride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	u32 ulStride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	if (inWidth > STG4000_OVRL_MAX_WIDTH ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	    inHeight > STG4000_OVRL_MAX_HEIGHT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	/* Stride in 16 byte words - 16Bpp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (bLinear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		/* Format is 16bits so num 16 byte words is width/8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		if ((inWidth & 0x7) == 0) {	/* inWidth % 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			ulStride = (inWidth / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			/* Round up to next 16byte boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 			ulStride = ((inWidth + 8) / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		/* Y component is 8bits so num 16 byte words is width/16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		if ((inWidth & 0xf) == 0) {	/* inWidth % 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			ulStride = (inWidth / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			/* Round up to next 16byte boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			ulStride = ((inWidth + 16) / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	/* Set Overlay address and Format mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	tmp = STG_READ_REG(DACOverlayAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	CLEAR_BITS_FRM_TO(0, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (bLinear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		CLEAR_BIT(31);	/* Overlay format to Linear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		tmp |= SET_BIT(31);	/* Overlay format to Planer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	/* Only bits 24:4 of the Overlay address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	tmp |= (ulOverlayOffset >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	STG_WRITE_REG(DACOverlayAddr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (!bLinear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		u32 uvSize =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		    (inWidth & 0x1) ? (inWidth + 1 / 2) : (inWidth / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		u32 uvStride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		u32 ulOffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		/* Y component is 8bits so num 32 byte words is width/32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if ((uvSize & 0xf) == 0) {	/* inWidth % 16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			uvStride = (uvSize / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			/* Round up to next 32byte boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			uvStride = ((uvSize + 16) / 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		/* Align U,V data to 32byte boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		if ((ulOffset & 0x1f) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			ulOffset = (ulOffset + 32L) & 0xffffffE0L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		tmp = STG_READ_REG(DACOverlayUAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		CLEAR_BITS_FRM_TO(0, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		tmp |= (ulOffset >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		STG_WRITE_REG(DACOverlayUAddr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		ulOffset += (inHeight / 2) * (uvStride * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		/* Align U,V data to 32byte boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		if ((ulOffset & 0x1f) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			ulOffset = (ulOffset + 32L) & 0xffffffE0L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		tmp = STG_READ_REG(DACOverlayVAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		CLEAR_BITS_FRM_TO(0, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		tmp |= (ulOffset >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		STG_WRITE_REG(DACOverlayVAddr, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		*retUVStride = uvStride * 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	/* Set Overlay YUV pixel format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	 * Make sure that LUT not used - ??????
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	tmp = STG_READ_REG(DACPixelFormat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	/* Only support Planer or UYVY linear formats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	CLEAR_BITS_FRM_TO(4, 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	STG_WRITE_REG(DACPixelFormat, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	ovlWidth = inWidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	ovlHeight = inHeight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	ovlStride = ulStride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	ovlLinear = bLinear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	*retStride = ulStride << 4;	/* In bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			OVRL_BLEND_MODE mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			u32 ulAlpha, u32 ulColorKey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	tmp = STG_READ_REG(DACBlendCtrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	CLEAR_BITS_FRM_TO(28, 30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	tmp |= (mode << 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	case COLOR_KEY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		CLEAR_BITS_FRM_TO(0, 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		tmp |= (ulColorKey & 0x00FFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	case GLOBAL_ALPHA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		CLEAR_BITS_FRM_TO(24, 27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		tmp |= ((ulAlpha & 0xF) << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	case CK_PIXEL_ALPHA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		CLEAR_BITS_FRM_TO(0, 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		tmp |= (ulColorKey & 0x00FFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	case CK_GLOBAL_ALPHA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		CLEAR_BITS_FRM_TO(0, 23);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		tmp |= (ulColorKey & 0x00FFFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		CLEAR_BITS_FRM_TO(24, 27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		tmp |= ((ulAlpha & 0xF) << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	case GRAPHICS_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	case PER_PIXEL_ALPHA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	STG_WRITE_REG(DACBlendCtrl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	u32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	/* Enable Overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	tmp = STG_READ_REG(DACPixelFormat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	tmp |= SET_BIT(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	STG_WRITE_REG(DACPixelFormat, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	/* Set video stream control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	tmp = STG_READ_REG(DACStreamCtrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	tmp |= SET_BIT(1);	/* video stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	STG_WRITE_REG(DACStreamCtrl, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static u32 Overlap(u32 ulBits, u32 ulPattern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	u32 ulCount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	while (ulBits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		if (!(ulPattern & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 			ulCount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		ulBits--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		ulPattern = ulPattern >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	return ulCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		       u32 left, u32 top,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		       u32 right, u32 bottom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	OVRL_SRC_DEST srcDest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	u32 ulSrcTop, ulSrcBottom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	u32 ulSrc, ulDest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	u32 ulFxScale, ulFxOffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	u32 ulHeight, ulWidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	u32 ulPattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	u32 ulDecimate, ulDecimated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	u32 ulApplied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	u32 ulDacXScale, ulDacYScale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	u32 ulScale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	u32 ulLeft, ulRight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	u32 ulSrcLeft, ulSrcRight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	u32 ulScaleLeft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	u32 ulhDecim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	u32 ulsVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	u32 ulVertDecFactor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	int bResult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	u32 ulClipOff = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	u32 ulBits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	u32 ulsAdd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	u32 tmp, ulStride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	u32 ulExcessPixels, ulClip, ulExtraLines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	srcDest.ulSrcX1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	srcDest.ulSrcY1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	srcDest.ulSrcX2 = ovlWidth - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	srcDest.ulSrcY2 = ovlHeight - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	srcDest.ulDstX1 = left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	srcDest.ulDstY1 = top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	srcDest.ulDstX2 = right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	srcDest.ulDstY2 = bottom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	srcDest.lDstX1 = srcDest.ulDstX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	srcDest.lDstY1 = srcDest.ulDstY1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	srcDest.lDstX2 = srcDest.ulDstX2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	srcDest.lDstY2 = srcDest.ulDstY2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)     /************* Vertical decimation/scaling ******************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	/* Get Src Top and Bottom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	ulSrcTop = srcDest.ulSrcY1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	ulSrcBottom = srcDest.ulSrcY2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	ulSrc = ulSrcBottom - ulSrcTop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	ulDest = srcDest.lDstY2 - srcDest.lDstY1;	/* on-screen overlay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (ulSrc <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	/* First work out the position we are to display as offset from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	 * source of the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	ulFxScale = (ulDest << 11) / ulSrc;	/* fixed point scale factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	ulFxOffset = (srcDest.lDstY2 - srcDest.ulDstY2) << 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	ulSrcBottom = ulSrcBottom - (ulFxOffset / ulFxScale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	ulSrc = ulSrcBottom - ulSrcTop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	ulHeight = ulSrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	ulDest = srcDest.ulDstY2 - (srcDest.ulDstY1 - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	ulPattern = adwDecim8[ulBits];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	/* At this point ulSrc represents the input decimator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	if (ulSrc > ulDest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		ulDecimate = ulSrc - ulDest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		ulBits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		ulApplied = ulSrc / 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		while (((ulBits * ulApplied) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			Overlap((ulSrc % 32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 				adwDecim8[ulBits])) < ulDecimate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 			ulBits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		ulPattern = adwDecim8[ulBits];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		ulDecimated =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		    (ulBits * ulApplied) + Overlap((ulSrc % 32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 						   ulPattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		ulSrc = ulSrc - ulDecimated;	/* the number number of lines that will go into the scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	if (ulBits && (ulBits != 32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		ulVertDecFactor = (63 - ulBits) / (32 - ulBits);	/* vertical decimation factor scaled up to nearest integer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		ulVertDecFactor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	tmp = STG_READ_REG(DACOverlayVtDec);	/* Decimation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	CLEAR_BITS_FRM_TO(0, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	tmp = ulPattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	STG_WRITE_REG(DACOverlayVtDec, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	/***************** Horizontal decimation/scaling ***************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	 * Now we handle the horizontal case, this is a simplified version of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	 * the vertical case in that we decimate by factors of 2.  as we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	 * working in words we should always be able to decimate by these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	 * factors.  as we always have to have a buffer which is aligned to a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	 * whole number of 128 bit words, we must align the left side to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	 * lowest to the next lowest 128 bit boundary, and the right hand edge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	 * to the next largets boundary, (in a similar way to how we didi it in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	 * PMX1) as the left and right hand edges are aligned to these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	 * boundaries normally this only becomes an issue when we are chopping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	 * of one of the sides We shall work out vertical stuff first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	ulSrc = srcDest.ulSrcX2 - srcDest.ulSrcX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	ulDest = srcDest.lDstX2 - srcDest.lDstX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) #ifdef _OLDCODE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	ulLeft = srcDest.ulDstX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	ulRight = srcDest.ulDstX2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	if (srcDest.ulDstX1 > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		ulLeft = srcDest.ulDstX1 + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		ulRight = srcDest.ulDstX2 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		ulLeft = srcDest.ulDstX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		ulRight = srcDest.ulDstX2 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	/* first work out the position we are to display as offset from the source of the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	bResult = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		if (ulDest == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		/* source pixels per dest pixel <<11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		ulFxScale = ((ulSrc - 1) << 11) / (ulDest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		/* then number of destination pixels out we are */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		ulFxOffset >>= 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		/* this replaces the code which was making a decision as to use either ulFxOffset or ulSrcX1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		/* then number of destination pixels out we are */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		ulFxOffset >>= 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		ulSrcRight = srcDest.ulSrcX2 - ulFxOffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		 * we must align these to our 128 bit boundaries. we shall
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		 * round down the pixel pos to the nearest 8 pixels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		ulScaleLeft = ulSrcLeft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		/* shift fxscale until it is in the range of the scaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		ulhDecim = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		while (ulScale > 0x800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 			ulhDecim++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 			ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		 * to try and get the best values We first try and use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		 * src/dwdest for the scale factor, then we move onto src-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		 * we want to check to see if we will need to clip data, if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		 * then we should clip our source so that we don't need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		if (!ovlLinear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 			ulSrcLeft &= ~0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 			 * we must align the right hand edge to the next 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 			 * pixel` boundary, must be on a 256 boundary so u, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 			 * v are 128 bit aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 			ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 			ulSrcLeft &= ~0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 			 * we must align the right hand edge to the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 			 * 8pixel` boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		/* this is the input size line store needs to cope with */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		ulWidth = ulSrcRight - ulSrcLeft;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		 * use unclipped value to work out scale factror this is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		 * scale factor we want we shall now work out the horizonal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		 * decimation and scaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		ulsVal = ((ulWidth / 8) >> ulhDecim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		if ((ulWidth != (ulsVal << ulhDecim) * 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 			ulsAdd = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		/* input pixels to scaler; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		ulSrc = ulWidth >> ulhDecim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		if (ulSrc <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		ulClip = (ulSrc << 11) / ulScale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		ulClip -= (ulRight - ulLeft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		ulClip += ulExcessPixels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		if (ulClip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			ulClip--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		/* We may need to do more here if we really have a HW rev < 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	} while (!bResult);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	ulExtraLines = (1 << ulhDecim) * ulVertDecFactor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	ulExtraLines += 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	ulHeight += ulExtraLines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	ulDacXScale = ulScale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	tmp = STG_READ_REG(DACVerticalScal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	CLEAR_BITS_FRM_TO(0, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	CLEAR_BITS_FRM_TO(16, 22);	/* Vertical Scaling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	/* Calculate new output line stride, this is always the number of 422
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	   words in the line buffer, so it doesn't matter if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	   mode is 420. Then set the vertical scale register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	tmp |= ((ulStride << 16) | (ulDacYScale));	/* DAC_LS_CTRL = stride */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	STG_WRITE_REG(DACVerticalScal, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	/* Now set up the overlay size using the modified width and height
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	   from decimate and scaling calculations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	tmp = STG_READ_REG(DACOverlaySize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	CLEAR_BITS_FRM_TO(0, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	CLEAR_BITS_FRM_TO(12, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	if (ovlLinear) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		tmp |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		    (ovlStride | ((ulHeight + 1) << 12) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		     (((ulWidth / 8) - 1) << 23));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		tmp |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		    (ovlStride | ((ulHeight + 1) << 12) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		     (((ulWidth / 32) - 1) << 23));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	STG_WRITE_REG(DACOverlaySize, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	/* Set Video Window Start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 	STG_WRITE_REG(DACVidWinStart, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	/* Set Video Window End */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	STG_WRITE_REG(DACVidWinEnd, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	/* Finally set up the rest of the overlay regs in the order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	   done in the IMG driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	tmp = STG_READ_REG(DACPixelFormat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	STG_WRITE_REG(DACPixelFormat, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	tmp = STG_READ_REG(DACHorizontalScal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	CLEAR_BITS_FRM_TO(0, 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	CLEAR_BITS_FRM_TO(16, 17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	tmp |= ((ulhDecim << 16) | (ulDacXScale));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	STG_WRITE_REG(DACHorizontalScal, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }