162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/drivers/video/kyro/STG4000OverlayDevice.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2000 Imagination Technologies Ltd 562306a36Sopenharmony_ci * Copyright (C) 2002 STMicroelectronics 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 862306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 962306a36Sopenharmony_ci * for more details. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/errno.h> 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "STG4000Reg.h" 1762306a36Sopenharmony_ci#include "STG4000Interface.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* HW Defines */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define STG4000_NO_SCALING 0x800 2262306a36Sopenharmony_ci#define STG4000_NO_DECIMATION 0xFFFFFFFF 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Primary surface */ 2562306a36Sopenharmony_ci#define STG4000_PRIM_NUM_PIX 5 2662306a36Sopenharmony_ci#define STG4000_PRIM_ALIGN 4 2762306a36Sopenharmony_ci#define STG4000_PRIM_ADDR_BITS 20 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define STG4000_PRIM_MIN_WIDTH 640 3062306a36Sopenharmony_ci#define STG4000_PRIM_MAX_WIDTH 1600 3162306a36Sopenharmony_ci#define STG4000_PRIM_MIN_HEIGHT 480 3262306a36Sopenharmony_ci#define STG4000_PRIM_MAX_HEIGHT 1200 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Overlay surface */ 3562306a36Sopenharmony_ci#define STG4000_OVRL_NUM_PIX 4 3662306a36Sopenharmony_ci#define STG4000_OVRL_ALIGN 2 3762306a36Sopenharmony_ci#define STG4000_OVRL_ADDR_BITS 20 3862306a36Sopenharmony_ci#define STG4000_OVRL_NUM_MODES 5 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define STG4000_OVRL_MIN_WIDTH 0 4162306a36Sopenharmony_ci#define STG4000_OVRL_MAX_WIDTH 720 4262306a36Sopenharmony_ci#define STG4000_OVRL_MIN_HEIGHT 0 4362306a36Sopenharmony_ci#define STG4000_OVRL_MAX_HEIGHT 576 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* Decimation and Scaling */ 4662306a36Sopenharmony_cistatic u32 adwDecim8[33] = { 4762306a36Sopenharmony_ci 0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf, 4862306a36Sopenharmony_ci 0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7, 4962306a36Sopenharmony_ci 0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab, 5062306a36Sopenharmony_ci 0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525, 5162306a36Sopenharmony_ci 0xa4924925, 0x92491249, 0x91224489, 0x91111111, 0x90884211, 5262306a36Sopenharmony_ci 0x88410821, 0x88102041, 0x81010101, 0x80800801, 0x80010001, 5362306a36Sopenharmony_ci 0x80000001, 0x00000001, 0x00000000 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_citypedef struct _OVRL_SRC_DEST { 5762306a36Sopenharmony_ci /*clipped on-screen pixel position of overlay */ 5862306a36Sopenharmony_ci u32 ulDstX1; 5962306a36Sopenharmony_ci u32 ulDstY1; 6062306a36Sopenharmony_ci u32 ulDstX2; 6162306a36Sopenharmony_ci u32 ulDstY2; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /*clipped pixel pos of source data within buffer thses need to be 128 bit word aligned */ 6462306a36Sopenharmony_ci u32 ulSrcX1; 6562306a36Sopenharmony_ci u32 ulSrcY1; 6662306a36Sopenharmony_ci u32 ulSrcX2; 6762306a36Sopenharmony_ci u32 ulSrcY2; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* on-screen pixel position of overlay */ 7062306a36Sopenharmony_ci s32 lDstX1; 7162306a36Sopenharmony_ci s32 lDstY1; 7262306a36Sopenharmony_ci s32 lDstX2; 7362306a36Sopenharmony_ci s32 lDstY2; 7462306a36Sopenharmony_ci} OVRL_SRC_DEST; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic u32 ovlWidth, ovlHeight, ovlStride; 7762306a36Sopenharmony_cistatic int ovlLinear; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_civoid ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci u32 tmp; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Set Overlay address to default */ 8462306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayAddr); 8562306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 20); 8662306a36Sopenharmony_ci CLEAR_BIT(31); 8762306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayAddr, tmp); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* Set Overlay U address */ 9062306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayUAddr); 9162306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 20); 9262306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayUAddr, tmp); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* Set Overlay V address */ 9562306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayVAddr); 9662306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 20); 9762306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayVAddr, tmp); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Set Overlay Size */ 10062306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlaySize); 10162306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 10); 10262306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(12, 31); 10362306a36Sopenharmony_ci STG_WRITE_REG(DACOverlaySize, tmp); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Set Overlay Vt Decimation */ 10662306a36Sopenharmony_ci tmp = STG4000_NO_DECIMATION; 10762306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayVtDec, tmp); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* Set Overlay format to default value */ 11062306a36Sopenharmony_ci tmp = STG_READ_REG(DACPixelFormat); 11162306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(4, 7); 11262306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(16, 22); 11362306a36Sopenharmony_ci STG_WRITE_REG(DACPixelFormat, tmp); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* Set Vertical scaling to default */ 11662306a36Sopenharmony_ci tmp = STG_READ_REG(DACVerticalScal); 11762306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 11); 11862306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(16, 22); 11962306a36Sopenharmony_ci tmp |= STG4000_NO_SCALING; /* Set to no scaling */ 12062306a36Sopenharmony_ci STG_WRITE_REG(DACVerticalScal, tmp); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* Set Horizontal Scaling to default */ 12362306a36Sopenharmony_ci tmp = STG_READ_REG(DACHorizontalScal); 12462306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 11); 12562306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(16, 17); 12662306a36Sopenharmony_ci tmp |= STG4000_NO_SCALING; /* Set to no scaling */ 12762306a36Sopenharmony_ci STG_WRITE_REG(DACHorizontalScal, tmp); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* Set Blend mode to Alpha Blend */ 13062306a36Sopenharmony_ci /* ????? SG 08/11/2001 Surely this isn't the alpha blend mode, 13162306a36Sopenharmony_ci hopefully its overwrite 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_ci tmp = STG_READ_REG(DACBlendCtrl); 13462306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 30); 13562306a36Sopenharmony_ci tmp = (GRAPHICS_MODE << 28); 13662306a36Sopenharmony_ci STG_WRITE_REG(DACBlendCtrl, tmp); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciint CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg, 14162306a36Sopenharmony_ci u32 inWidth, 14262306a36Sopenharmony_ci u32 inHeight, 14362306a36Sopenharmony_ci int bLinear, 14462306a36Sopenharmony_ci u32 ulOverlayOffset, 14562306a36Sopenharmony_ci u32 * retStride, u32 * retUVStride) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci u32 tmp; 14862306a36Sopenharmony_ci u32 ulStride; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (inWidth > STG4000_OVRL_MAX_WIDTH || 15162306a36Sopenharmony_ci inHeight > STG4000_OVRL_MAX_HEIGHT) { 15262306a36Sopenharmony_ci return -EINVAL; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* Stride in 16 byte words - 16Bpp */ 15662306a36Sopenharmony_ci if (bLinear) { 15762306a36Sopenharmony_ci /* Format is 16bits so num 16 byte words is width/8 */ 15862306a36Sopenharmony_ci if ((inWidth & 0x7) == 0) { /* inWidth % 8 */ 15962306a36Sopenharmony_ci ulStride = (inWidth / 8); 16062306a36Sopenharmony_ci } else { 16162306a36Sopenharmony_ci /* Round up to next 16byte boundary */ 16262306a36Sopenharmony_ci ulStride = ((inWidth + 8) / 8); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci } else { 16562306a36Sopenharmony_ci /* Y component is 8bits so num 16 byte words is width/16 */ 16662306a36Sopenharmony_ci if ((inWidth & 0xf) == 0) { /* inWidth % 16 */ 16762306a36Sopenharmony_ci ulStride = (inWidth / 16); 16862306a36Sopenharmony_ci } else { 16962306a36Sopenharmony_ci /* Round up to next 16byte boundary */ 17062306a36Sopenharmony_ci ulStride = ((inWidth + 16) / 16); 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Set Overlay address and Format mode */ 17662306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayAddr); 17762306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 20); 17862306a36Sopenharmony_ci if (bLinear) { 17962306a36Sopenharmony_ci CLEAR_BIT(31); /* Overlay format to Linear */ 18062306a36Sopenharmony_ci } else { 18162306a36Sopenharmony_ci tmp |= SET_BIT(31); /* Overlay format to Planer */ 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* Only bits 24:4 of the Overlay address */ 18562306a36Sopenharmony_ci tmp |= (ulOverlayOffset >> 4); 18662306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayAddr, tmp); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (!bLinear) { 18962306a36Sopenharmony_ci u32 uvSize = 19062306a36Sopenharmony_ci (inWidth & 0x1) ? (inWidth + 1 / 2) : (inWidth / 2); 19162306a36Sopenharmony_ci u32 uvStride; 19262306a36Sopenharmony_ci u32 ulOffset; 19362306a36Sopenharmony_ci /* Y component is 8bits so num 32 byte words is width/32 */ 19462306a36Sopenharmony_ci if ((uvSize & 0xf) == 0) { /* inWidth % 16 */ 19562306a36Sopenharmony_ci uvStride = (uvSize / 16); 19662306a36Sopenharmony_ci } else { 19762306a36Sopenharmony_ci /* Round up to next 32byte boundary */ 19862306a36Sopenharmony_ci uvStride = ((uvSize + 16) / 16); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16)); 20262306a36Sopenharmony_ci /* Align U,V data to 32byte boundary */ 20362306a36Sopenharmony_ci if ((ulOffset & 0x1f) != 0) 20462306a36Sopenharmony_ci ulOffset = (ulOffset + 32L) & 0xffffffE0L; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayUAddr); 20762306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 20); 20862306a36Sopenharmony_ci tmp |= (ulOffset >> 4); 20962306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayUAddr, tmp); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci ulOffset += (inHeight / 2) * (uvStride * 16); 21262306a36Sopenharmony_ci /* Align U,V data to 32byte boundary */ 21362306a36Sopenharmony_ci if ((ulOffset & 0x1f) != 0) 21462306a36Sopenharmony_ci ulOffset = (ulOffset + 32L) & 0xffffffE0L; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayVAddr); 21762306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 20); 21862306a36Sopenharmony_ci tmp |= (ulOffset >> 4); 21962306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayVAddr, tmp); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci *retUVStride = uvStride * 16; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* Set Overlay YUV pixel format 22662306a36Sopenharmony_ci * Make sure that LUT not used - ?????? 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci tmp = STG_READ_REG(DACPixelFormat); 22962306a36Sopenharmony_ci /* Only support Planer or UYVY linear formats */ 23062306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(4, 9); 23162306a36Sopenharmony_ci STG_WRITE_REG(DACPixelFormat, tmp); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci ovlWidth = inWidth; 23462306a36Sopenharmony_ci ovlHeight = inHeight; 23562306a36Sopenharmony_ci ovlStride = ulStride; 23662306a36Sopenharmony_ci ovlLinear = bLinear; 23762306a36Sopenharmony_ci *retStride = ulStride << 4; /* In bytes */ 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci return 0; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciint SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg, 24362306a36Sopenharmony_ci OVRL_BLEND_MODE mode, 24462306a36Sopenharmony_ci u32 ulAlpha, u32 ulColorKey) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci u32 tmp; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci tmp = STG_READ_REG(DACBlendCtrl); 24962306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(28, 30); 25062306a36Sopenharmony_ci tmp |= (mode << 28); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci switch (mode) { 25362306a36Sopenharmony_ci case COLOR_KEY: 25462306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 23); 25562306a36Sopenharmony_ci tmp |= (ulColorKey & 0x00FFFFFF); 25662306a36Sopenharmony_ci break; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci case GLOBAL_ALPHA: 25962306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(24, 27); 26062306a36Sopenharmony_ci tmp |= ((ulAlpha & 0xF) << 24); 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci case CK_PIXEL_ALPHA: 26462306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 23); 26562306a36Sopenharmony_ci tmp |= (ulColorKey & 0x00FFFFFF); 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci case CK_GLOBAL_ALPHA: 26962306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 23); 27062306a36Sopenharmony_ci tmp |= (ulColorKey & 0x00FFFFFF); 27162306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(24, 27); 27262306a36Sopenharmony_ci tmp |= ((ulAlpha & 0xF) << 24); 27362306a36Sopenharmony_ci break; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci case GRAPHICS_MODE: 27662306a36Sopenharmony_ci case PER_PIXEL_ALPHA: 27762306a36Sopenharmony_ci break; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci default: 28062306a36Sopenharmony_ci return -EINVAL; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci STG_WRITE_REG(DACBlendCtrl, tmp); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_civoid EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci u32 tmp; 29162306a36Sopenharmony_ci /* Enable Overlay */ 29262306a36Sopenharmony_ci tmp = STG_READ_REG(DACPixelFormat); 29362306a36Sopenharmony_ci tmp |= SET_BIT(7); 29462306a36Sopenharmony_ci STG_WRITE_REG(DACPixelFormat, tmp); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* Set video stream control */ 29762306a36Sopenharmony_ci tmp = STG_READ_REG(DACStreamCtrl); 29862306a36Sopenharmony_ci tmp |= SET_BIT(1); /* video stream */ 29962306a36Sopenharmony_ci STG_WRITE_REG(DACStreamCtrl, tmp); 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic u32 Overlap(u32 ulBits, u32 ulPattern) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci u32 ulCount = 0; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci while (ulBits) { 30762306a36Sopenharmony_ci if (!(ulPattern & 1)) 30862306a36Sopenharmony_ci ulCount++; 30962306a36Sopenharmony_ci ulBits--; 31062306a36Sopenharmony_ci ulPattern = ulPattern >> 1; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci return ulCount; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ciint SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg, 31862306a36Sopenharmony_ci u32 left, u32 top, 31962306a36Sopenharmony_ci u32 right, u32 bottom) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci OVRL_SRC_DEST srcDest; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci u32 ulSrcTop, ulSrcBottom; 32462306a36Sopenharmony_ci u32 ulSrc, ulDest; 32562306a36Sopenharmony_ci u32 ulFxScale, ulFxOffset; 32662306a36Sopenharmony_ci u32 ulHeight, ulWidth; 32762306a36Sopenharmony_ci u32 ulPattern; 32862306a36Sopenharmony_ci u32 ulDecimate, ulDecimated; 32962306a36Sopenharmony_ci u32 ulApplied; 33062306a36Sopenharmony_ci u32 ulDacXScale, ulDacYScale; 33162306a36Sopenharmony_ci u32 ulScale; 33262306a36Sopenharmony_ci u32 ulLeft, ulRight; 33362306a36Sopenharmony_ci u32 ulSrcLeft, ulSrcRight; 33462306a36Sopenharmony_ci u32 ulScaleLeft; 33562306a36Sopenharmony_ci u32 ulhDecim; 33662306a36Sopenharmony_ci u32 ulsVal; 33762306a36Sopenharmony_ci u32 ulVertDecFactor; 33862306a36Sopenharmony_ci int bResult; 33962306a36Sopenharmony_ci u32 ulClipOff = 0; 34062306a36Sopenharmony_ci u32 ulBits = 0; 34162306a36Sopenharmony_ci u32 ulsAdd = 0; 34262306a36Sopenharmony_ci u32 tmp, ulStride; 34362306a36Sopenharmony_ci u32 ulExcessPixels, ulClip, ulExtraLines; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci srcDest.ulSrcX1 = 0; 34762306a36Sopenharmony_ci srcDest.ulSrcY1 = 0; 34862306a36Sopenharmony_ci srcDest.ulSrcX2 = ovlWidth - 1; 34962306a36Sopenharmony_ci srcDest.ulSrcY2 = ovlHeight - 1; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci srcDest.ulDstX1 = left; 35262306a36Sopenharmony_ci srcDest.ulDstY1 = top; 35362306a36Sopenharmony_ci srcDest.ulDstX2 = right; 35462306a36Sopenharmony_ci srcDest.ulDstY2 = bottom; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci srcDest.lDstX1 = srcDest.ulDstX1; 35762306a36Sopenharmony_ci srcDest.lDstY1 = srcDest.ulDstY1; 35862306a36Sopenharmony_ci srcDest.lDstX2 = srcDest.ulDstX2; 35962306a36Sopenharmony_ci srcDest.lDstY2 = srcDest.ulDstY2; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /************* Vertical decimation/scaling ******************/ 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* Get Src Top and Bottom */ 36462306a36Sopenharmony_ci ulSrcTop = srcDest.ulSrcY1; 36562306a36Sopenharmony_ci ulSrcBottom = srcDest.ulSrcY2; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ulSrc = ulSrcBottom - ulSrcTop; 36862306a36Sopenharmony_ci ulDest = srcDest.lDstY2 - srcDest.lDstY1; /* on-screen overlay */ 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (ulSrc <= 1) 37162306a36Sopenharmony_ci return -EINVAL; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* First work out the position we are to display as offset from the 37462306a36Sopenharmony_ci * source of the buffer 37562306a36Sopenharmony_ci */ 37662306a36Sopenharmony_ci ulFxScale = (ulDest << 11) / ulSrc; /* fixed point scale factor */ 37762306a36Sopenharmony_ci ulFxOffset = (srcDest.lDstY2 - srcDest.ulDstY2) << 11; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci ulSrcBottom = ulSrcBottom - (ulFxOffset / ulFxScale); 38062306a36Sopenharmony_ci ulSrc = ulSrcBottom - ulSrcTop; 38162306a36Sopenharmony_ci ulHeight = ulSrc; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci ulDest = srcDest.ulDstY2 - (srcDest.ulDstY1 - 1); 38462306a36Sopenharmony_ci ulPattern = adwDecim8[ulBits]; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* At this point ulSrc represents the input decimator */ 38762306a36Sopenharmony_ci if (ulSrc > ulDest) { 38862306a36Sopenharmony_ci ulDecimate = ulSrc - ulDest; 38962306a36Sopenharmony_ci ulBits = 0; 39062306a36Sopenharmony_ci ulApplied = ulSrc / 32; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci while (((ulBits * ulApplied) + 39362306a36Sopenharmony_ci Overlap((ulSrc % 32), 39462306a36Sopenharmony_ci adwDecim8[ulBits])) < ulDecimate) 39562306a36Sopenharmony_ci ulBits++; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci ulPattern = adwDecim8[ulBits]; 39862306a36Sopenharmony_ci ulDecimated = 39962306a36Sopenharmony_ci (ulBits * ulApplied) + Overlap((ulSrc % 32), 40062306a36Sopenharmony_ci ulPattern); 40162306a36Sopenharmony_ci ulSrc = ulSrc - ulDecimated; /* the number number of lines that will go into the scaler */ 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (ulBits && (ulBits != 32)) { 40562306a36Sopenharmony_ci ulVertDecFactor = (63 - ulBits) / (32 - ulBits); /* vertical decimation factor scaled up to nearest integer */ 40662306a36Sopenharmony_ci } else { 40762306a36Sopenharmony_ci ulVertDecFactor = 1; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlayVtDec); /* Decimation */ 41362306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 31); 41462306a36Sopenharmony_ci tmp = ulPattern; 41562306a36Sopenharmony_ci STG_WRITE_REG(DACOverlayVtDec, tmp); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /***************** Horizontal decimation/scaling ***************************/ 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* 42062306a36Sopenharmony_ci * Now we handle the horizontal case, this is a simplified version of 42162306a36Sopenharmony_ci * the vertical case in that we decimate by factors of 2. as we are 42262306a36Sopenharmony_ci * working in words we should always be able to decimate by these 42362306a36Sopenharmony_ci * factors. as we always have to have a buffer which is aligned to a 42462306a36Sopenharmony_ci * whole number of 128 bit words, we must align the left side to the 42562306a36Sopenharmony_ci * lowest to the next lowest 128 bit boundary, and the right hand edge 42662306a36Sopenharmony_ci * to the next largets boundary, (in a similar way to how we didi it in 42762306a36Sopenharmony_ci * PMX1) as the left and right hand edges are aligned to these 42862306a36Sopenharmony_ci * boundaries normally this only becomes an issue when we are chopping 42962306a36Sopenharmony_ci * of one of the sides We shall work out vertical stuff first 43062306a36Sopenharmony_ci */ 43162306a36Sopenharmony_ci ulSrc = srcDest.ulSrcX2 - srcDest.ulSrcX1; 43262306a36Sopenharmony_ci ulDest = srcDest.lDstX2 - srcDest.lDstX1; 43362306a36Sopenharmony_ci#ifdef _OLDCODE 43462306a36Sopenharmony_ci ulLeft = srcDest.ulDstX1; 43562306a36Sopenharmony_ci ulRight = srcDest.ulDstX2; 43662306a36Sopenharmony_ci#else 43762306a36Sopenharmony_ci if (srcDest.ulDstX1 > 2) { 43862306a36Sopenharmony_ci ulLeft = srcDest.ulDstX1 + 2; 43962306a36Sopenharmony_ci ulRight = srcDest.ulDstX2 + 1; 44062306a36Sopenharmony_ci } else { 44162306a36Sopenharmony_ci ulLeft = srcDest.ulDstX1; 44262306a36Sopenharmony_ci ulRight = srcDest.ulDstX2 + 1; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci#endif 44562306a36Sopenharmony_ci /* first work out the position we are to display as offset from the source of the buffer */ 44662306a36Sopenharmony_ci bResult = 1; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci do { 44962306a36Sopenharmony_ci if (ulDest == 0) 45062306a36Sopenharmony_ci return -EINVAL; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* source pixels per dest pixel <<11 */ 45362306a36Sopenharmony_ci ulFxScale = ((ulSrc - 1) << 11) / (ulDest); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* then number of destination pixels out we are */ 45662306a36Sopenharmony_ci ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff); 45762306a36Sopenharmony_ci ulFxOffset >>= 11; 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* this replaces the code which was making a decision as to use either ulFxOffset or ulSrcX1 */ 46062306a36Sopenharmony_ci ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* then number of destination pixels out we are */ 46362306a36Sopenharmony_ci ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2); 46462306a36Sopenharmony_ci ulFxOffset >>= 11; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci ulSrcRight = srcDest.ulSrcX2 - ulFxOffset; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci /* 46962306a36Sopenharmony_ci * we must align these to our 128 bit boundaries. we shall 47062306a36Sopenharmony_ci * round down the pixel pos to the nearest 8 pixels. 47162306a36Sopenharmony_ci */ 47262306a36Sopenharmony_ci ulScaleLeft = ulSrcLeft; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* shift fxscale until it is in the range of the scaler */ 47562306a36Sopenharmony_ci ulhDecim = 0; 47662306a36Sopenharmony_ci ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci while (ulScale > 0x800) { 47962306a36Sopenharmony_ci ulhDecim++; 48062306a36Sopenharmony_ci ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2); 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* 48462306a36Sopenharmony_ci * to try and get the best values We first try and use 48562306a36Sopenharmony_ci * src/dwdest for the scale factor, then we move onto src-1 48662306a36Sopenharmony_ci * 48762306a36Sopenharmony_ci * we want to check to see if we will need to clip data, if so 48862306a36Sopenharmony_ci * then we should clip our source so that we don't need to 48962306a36Sopenharmony_ci */ 49062306a36Sopenharmony_ci if (!ovlLinear) { 49162306a36Sopenharmony_ci ulSrcLeft &= ~0x1f; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci /* 49462306a36Sopenharmony_ci * we must align the right hand edge to the next 32 49562306a36Sopenharmony_ci * pixel` boundary, must be on a 256 boundary so u, and 49662306a36Sopenharmony_ci * v are 128 bit aligned 49762306a36Sopenharmony_ci */ 49862306a36Sopenharmony_ci ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f; 49962306a36Sopenharmony_ci } else { 50062306a36Sopenharmony_ci ulSrcLeft &= ~0x7; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* 50362306a36Sopenharmony_ci * we must align the right hand edge to the next 50462306a36Sopenharmony_ci * 8pixel` boundary 50562306a36Sopenharmony_ci */ 50662306a36Sopenharmony_ci ulSrcRight = (ulSrcRight + 0x7) & ~0x7; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci /* this is the input size line store needs to cope with */ 51062306a36Sopenharmony_ci ulWidth = ulSrcRight - ulSrcLeft; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci /* 51362306a36Sopenharmony_ci * use unclipped value to work out scale factror this is the 51462306a36Sopenharmony_ci * scale factor we want we shall now work out the horizonal 51562306a36Sopenharmony_ci * decimation and scaling 51662306a36Sopenharmony_ci */ 51762306a36Sopenharmony_ci ulsVal = ((ulWidth / 8) >> ulhDecim); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci if ((ulWidth != (ulsVal << ulhDecim) * 8)) 52062306a36Sopenharmony_ci ulsAdd = 1; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* input pixels to scaler; */ 52362306a36Sopenharmony_ci ulSrc = ulWidth >> ulhDecim; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (ulSrc <= 2) 52662306a36Sopenharmony_ci return -EINVAL; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci ulClip = (ulSrc << 11) / ulScale; 53162306a36Sopenharmony_ci ulClip -= (ulRight - ulLeft); 53262306a36Sopenharmony_ci ulClip += ulExcessPixels; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (ulClip) 53562306a36Sopenharmony_ci ulClip--; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* We may need to do more here if we really have a HW rev < 5 */ 53862306a36Sopenharmony_ci } while (!bResult); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci ulExtraLines = (1 << ulhDecim) * ulVertDecFactor; 54162306a36Sopenharmony_ci ulExtraLines += 64; 54262306a36Sopenharmony_ci ulHeight += ulExtraLines; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci ulDacXScale = ulScale; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci tmp = STG_READ_REG(DACVerticalScal); 54862306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 11); 54962306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(16, 22); /* Vertical Scaling */ 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci /* Calculate new output line stride, this is always the number of 422 55262306a36Sopenharmony_ci words in the line buffer, so it doesn't matter if the 55362306a36Sopenharmony_ci mode is 420. Then set the vertical scale register. 55462306a36Sopenharmony_ci */ 55562306a36Sopenharmony_ci ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd; 55662306a36Sopenharmony_ci tmp |= ((ulStride << 16) | (ulDacYScale)); /* DAC_LS_CTRL = stride */ 55762306a36Sopenharmony_ci STG_WRITE_REG(DACVerticalScal, tmp); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci /* Now set up the overlay size using the modified width and height 56062306a36Sopenharmony_ci from decimate and scaling calculations 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_ci tmp = STG_READ_REG(DACOverlaySize); 56362306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 10); 56462306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(12, 31); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (ovlLinear) { 56762306a36Sopenharmony_ci tmp |= 56862306a36Sopenharmony_ci (ovlStride | ((ulHeight + 1) << 12) | 56962306a36Sopenharmony_ci (((ulWidth / 8) - 1) << 23)); 57062306a36Sopenharmony_ci } else { 57162306a36Sopenharmony_ci tmp |= 57262306a36Sopenharmony_ci (ovlStride | ((ulHeight + 1) << 12) | 57362306a36Sopenharmony_ci (((ulWidth / 32) - 1) << 23)); 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci STG_WRITE_REG(DACOverlaySize, tmp); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* Set Video Window Start */ 57962306a36Sopenharmony_ci tmp = ((ulLeft << 16)) | (srcDest.ulDstY1); 58062306a36Sopenharmony_ci STG_WRITE_REG(DACVidWinStart, tmp); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* Set Video Window End */ 58362306a36Sopenharmony_ci tmp = ((ulRight) << 16) | (srcDest.ulDstY2); 58462306a36Sopenharmony_ci STG_WRITE_REG(DACVidWinEnd, tmp); 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci /* Finally set up the rest of the overlay regs in the order 58762306a36Sopenharmony_ci done in the IMG driver 58862306a36Sopenharmony_ci */ 58962306a36Sopenharmony_ci tmp = STG_READ_REG(DACPixelFormat); 59062306a36Sopenharmony_ci tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff; 59162306a36Sopenharmony_ci STG_WRITE_REG(DACPixelFormat, tmp); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci tmp = STG_READ_REG(DACHorizontalScal); 59462306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(0, 11); 59562306a36Sopenharmony_ci CLEAR_BITS_FRM_TO(16, 17); 59662306a36Sopenharmony_ci tmp |= ((ulhDecim << 16) | (ulDacXScale)); 59762306a36Sopenharmony_ci STG_WRITE_REG(DACHorizontalScal, tmp); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci return 0; 60062306a36Sopenharmony_ci} 601