^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) }