0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/errno.h>
0014 #include <linux/types.h>
0015
0016 #include "STG4000Reg.h"
0017 #include "STG4000Interface.h"
0018
0019
0020
0021 #define STG4000_NO_SCALING 0x800
0022 #define STG4000_NO_DECIMATION 0xFFFFFFFF
0023
0024
0025 #define STG4000_PRIM_NUM_PIX 5
0026 #define STG4000_PRIM_ALIGN 4
0027 #define STG4000_PRIM_ADDR_BITS 20
0028
0029 #define STG4000_PRIM_MIN_WIDTH 640
0030 #define STG4000_PRIM_MAX_WIDTH 1600
0031 #define STG4000_PRIM_MIN_HEIGHT 480
0032 #define STG4000_PRIM_MAX_HEIGHT 1200
0033
0034
0035 #define STG4000_OVRL_NUM_PIX 4
0036 #define STG4000_OVRL_ALIGN 2
0037 #define STG4000_OVRL_ADDR_BITS 20
0038 #define STG4000_OVRL_NUM_MODES 5
0039
0040 #define STG4000_OVRL_MIN_WIDTH 0
0041 #define STG4000_OVRL_MAX_WIDTH 720
0042 #define STG4000_OVRL_MIN_HEIGHT 0
0043 #define STG4000_OVRL_MAX_HEIGHT 576
0044
0045
0046 static u32 adwDecim8[33] = {
0047 0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
0048 0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7,
0049 0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab,
0050 0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525,
0051 0xa4924925, 0x92491249, 0x91224489, 0x91111111, 0x90884211,
0052 0x88410821, 0x88102041, 0x81010101, 0x80800801, 0x80010001,
0053 0x80000001, 0x00000001, 0x00000000
0054 };
0055
0056 typedef struct _OVRL_SRC_DEST {
0057
0058 u32 ulDstX1;
0059 u32 ulDstY1;
0060 u32 ulDstX2;
0061 u32 ulDstY2;
0062
0063
0064 u32 ulSrcX1;
0065 u32 ulSrcY1;
0066 u32 ulSrcX2;
0067 u32 ulSrcY2;
0068
0069
0070 s32 lDstX1;
0071 s32 lDstY1;
0072 s32 lDstX2;
0073 s32 lDstY2;
0074 } OVRL_SRC_DEST;
0075
0076 static u32 ovlWidth, ovlHeight, ovlStride;
0077 static int ovlLinear;
0078
0079 void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg)
0080 {
0081 u32 tmp;
0082
0083
0084 tmp = STG_READ_REG(DACOverlayAddr);
0085 CLEAR_BITS_FRM_TO(0, 20);
0086 CLEAR_BIT(31);
0087 STG_WRITE_REG(DACOverlayAddr, tmp);
0088
0089
0090 tmp = STG_READ_REG(DACOverlayUAddr);
0091 CLEAR_BITS_FRM_TO(0, 20);
0092 STG_WRITE_REG(DACOverlayUAddr, tmp);
0093
0094
0095 tmp = STG_READ_REG(DACOverlayVAddr);
0096 CLEAR_BITS_FRM_TO(0, 20);
0097 STG_WRITE_REG(DACOverlayVAddr, tmp);
0098
0099
0100 tmp = STG_READ_REG(DACOverlaySize);
0101 CLEAR_BITS_FRM_TO(0, 10);
0102 CLEAR_BITS_FRM_TO(12, 31);
0103 STG_WRITE_REG(DACOverlaySize, tmp);
0104
0105
0106 tmp = STG4000_NO_DECIMATION;
0107 STG_WRITE_REG(DACOverlayVtDec, tmp);
0108
0109
0110 tmp = STG_READ_REG(DACPixelFormat);
0111 CLEAR_BITS_FRM_TO(4, 7);
0112 CLEAR_BITS_FRM_TO(16, 22);
0113 STG_WRITE_REG(DACPixelFormat, tmp);
0114
0115
0116 tmp = STG_READ_REG(DACVerticalScal);
0117 CLEAR_BITS_FRM_TO(0, 11);
0118 CLEAR_BITS_FRM_TO(16, 22);
0119 tmp |= STG4000_NO_SCALING;
0120 STG_WRITE_REG(DACVerticalScal, tmp);
0121
0122
0123 tmp = STG_READ_REG(DACHorizontalScal);
0124 CLEAR_BITS_FRM_TO(0, 11);
0125 CLEAR_BITS_FRM_TO(16, 17);
0126 tmp |= STG4000_NO_SCALING;
0127 STG_WRITE_REG(DACHorizontalScal, tmp);
0128
0129
0130
0131
0132
0133 tmp = STG_READ_REG(DACBlendCtrl);
0134 CLEAR_BITS_FRM_TO(0, 30);
0135 tmp = (GRAPHICS_MODE << 28);
0136 STG_WRITE_REG(DACBlendCtrl, tmp);
0137
0138 }
0139
0140 int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
0141 u32 inWidth,
0142 u32 inHeight,
0143 int bLinear,
0144 u32 ulOverlayOffset,
0145 u32 * retStride, u32 * retUVStride)
0146 {
0147 u32 tmp;
0148 u32 ulStride;
0149
0150 if (inWidth > STG4000_OVRL_MAX_WIDTH ||
0151 inHeight > STG4000_OVRL_MAX_HEIGHT) {
0152 return -EINVAL;
0153 }
0154
0155
0156 if (bLinear) {
0157
0158 if ((inWidth & 0x7) == 0) {
0159 ulStride = (inWidth / 8);
0160 } else {
0161
0162 ulStride = ((inWidth + 8) / 8);
0163 }
0164 } else {
0165
0166 if ((inWidth & 0xf) == 0) {
0167 ulStride = (inWidth / 16);
0168 } else {
0169
0170 ulStride = ((inWidth + 16) / 16);
0171 }
0172 }
0173
0174
0175
0176 tmp = STG_READ_REG(DACOverlayAddr);
0177 CLEAR_BITS_FRM_TO(0, 20);
0178 if (bLinear) {
0179 CLEAR_BIT(31);
0180 } else {
0181 tmp |= SET_BIT(31);
0182 }
0183
0184
0185 tmp |= (ulOverlayOffset >> 4);
0186 STG_WRITE_REG(DACOverlayAddr, tmp);
0187
0188 if (!bLinear) {
0189 u32 uvSize =
0190 (inWidth & 0x1) ? (inWidth + 1 / 2) : (inWidth / 2);
0191 u32 uvStride;
0192 u32 ulOffset;
0193
0194 if ((uvSize & 0xf) == 0) {
0195 uvStride = (uvSize / 16);
0196 } else {
0197
0198 uvStride = ((uvSize + 16) / 16);
0199 }
0200
0201 ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16));
0202
0203 if ((ulOffset & 0x1f) != 0)
0204 ulOffset = (ulOffset + 32L) & 0xffffffE0L;
0205
0206 tmp = STG_READ_REG(DACOverlayUAddr);
0207 CLEAR_BITS_FRM_TO(0, 20);
0208 tmp |= (ulOffset >> 4);
0209 STG_WRITE_REG(DACOverlayUAddr, tmp);
0210
0211 ulOffset += (inHeight / 2) * (uvStride * 16);
0212
0213 if ((ulOffset & 0x1f) != 0)
0214 ulOffset = (ulOffset + 32L) & 0xffffffE0L;
0215
0216 tmp = STG_READ_REG(DACOverlayVAddr);
0217 CLEAR_BITS_FRM_TO(0, 20);
0218 tmp |= (ulOffset >> 4);
0219 STG_WRITE_REG(DACOverlayVAddr, tmp);
0220
0221 *retUVStride = uvStride * 16;
0222 }
0223
0224
0225
0226
0227
0228 tmp = STG_READ_REG(DACPixelFormat);
0229
0230 CLEAR_BITS_FRM_TO(4, 9);
0231 STG_WRITE_REG(DACPixelFormat, tmp);
0232
0233 ovlWidth = inWidth;
0234 ovlHeight = inHeight;
0235 ovlStride = ulStride;
0236 ovlLinear = bLinear;
0237 *retStride = ulStride << 4;
0238
0239 return 0;
0240 }
0241
0242 int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
0243 OVRL_BLEND_MODE mode,
0244 u32 ulAlpha, u32 ulColorKey)
0245 {
0246 u32 tmp;
0247
0248 tmp = STG_READ_REG(DACBlendCtrl);
0249 CLEAR_BITS_FRM_TO(28, 30);
0250 tmp |= (mode << 28);
0251
0252 switch (mode) {
0253 case COLOR_KEY:
0254 CLEAR_BITS_FRM_TO(0, 23);
0255 tmp |= (ulColorKey & 0x00FFFFFF);
0256 break;
0257
0258 case GLOBAL_ALPHA:
0259 CLEAR_BITS_FRM_TO(24, 27);
0260 tmp |= ((ulAlpha & 0xF) << 24);
0261 break;
0262
0263 case CK_PIXEL_ALPHA:
0264 CLEAR_BITS_FRM_TO(0, 23);
0265 tmp |= (ulColorKey & 0x00FFFFFF);
0266 break;
0267
0268 case CK_GLOBAL_ALPHA:
0269 CLEAR_BITS_FRM_TO(0, 23);
0270 tmp |= (ulColorKey & 0x00FFFFFF);
0271 CLEAR_BITS_FRM_TO(24, 27);
0272 tmp |= ((ulAlpha & 0xF) << 24);
0273 break;
0274
0275 case GRAPHICS_MODE:
0276 case PER_PIXEL_ALPHA:
0277 break;
0278
0279 default:
0280 return -EINVAL;
0281 }
0282
0283 STG_WRITE_REG(DACBlendCtrl, tmp);
0284
0285 return 0;
0286 }
0287
0288 void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg)
0289 {
0290 u32 tmp;
0291
0292 tmp = STG_READ_REG(DACPixelFormat);
0293 tmp |= SET_BIT(7);
0294 STG_WRITE_REG(DACPixelFormat, tmp);
0295
0296
0297 tmp = STG_READ_REG(DACStreamCtrl);
0298 tmp |= SET_BIT(1);
0299 STG_WRITE_REG(DACStreamCtrl, tmp);
0300 }
0301
0302 static u32 Overlap(u32 ulBits, u32 ulPattern)
0303 {
0304 u32 ulCount = 0;
0305
0306 while (ulBits) {
0307 if (!(ulPattern & 1))
0308 ulCount++;
0309 ulBits--;
0310 ulPattern = ulPattern >> 1;
0311 }
0312
0313 return ulCount;
0314
0315 }
0316
0317 int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
0318 u32 left, u32 top,
0319 u32 right, u32 bottom)
0320 {
0321 OVRL_SRC_DEST srcDest;
0322
0323 u32 ulSrcTop, ulSrcBottom;
0324 u32 ulSrc, ulDest;
0325 u32 ulFxScale, ulFxOffset;
0326 u32 ulHeight, ulWidth;
0327 u32 ulPattern;
0328 u32 ulDecimate, ulDecimated;
0329 u32 ulApplied;
0330 u32 ulDacXScale, ulDacYScale;
0331 u32 ulScale;
0332 u32 ulLeft, ulRight;
0333 u32 ulSrcLeft, ulSrcRight;
0334 u32 ulScaleLeft;
0335 u32 ulhDecim;
0336 u32 ulsVal;
0337 u32 ulVertDecFactor;
0338 int bResult;
0339 u32 ulClipOff = 0;
0340 u32 ulBits = 0;
0341 u32 ulsAdd = 0;
0342 u32 tmp, ulStride;
0343 u32 ulExcessPixels, ulClip, ulExtraLines;
0344
0345
0346 srcDest.ulSrcX1 = 0;
0347 srcDest.ulSrcY1 = 0;
0348 srcDest.ulSrcX2 = ovlWidth - 1;
0349 srcDest.ulSrcY2 = ovlHeight - 1;
0350
0351 srcDest.ulDstX1 = left;
0352 srcDest.ulDstY1 = top;
0353 srcDest.ulDstX2 = right;
0354 srcDest.ulDstY2 = bottom;
0355
0356 srcDest.lDstX1 = srcDest.ulDstX1;
0357 srcDest.lDstY1 = srcDest.ulDstY1;
0358 srcDest.lDstX2 = srcDest.ulDstX2;
0359 srcDest.lDstY2 = srcDest.ulDstY2;
0360
0361
0362
0363
0364 ulSrcTop = srcDest.ulSrcY1;
0365 ulSrcBottom = srcDest.ulSrcY2;
0366
0367 ulSrc = ulSrcBottom - ulSrcTop;
0368 ulDest = srcDest.lDstY2 - srcDest.lDstY1;
0369
0370 if (ulSrc <= 1)
0371 return -EINVAL;
0372
0373
0374
0375
0376 ulFxScale = (ulDest << 11) / ulSrc;
0377 ulFxOffset = (srcDest.lDstY2 - srcDest.ulDstY2) << 11;
0378
0379 ulSrcBottom = ulSrcBottom - (ulFxOffset / ulFxScale);
0380 ulSrc = ulSrcBottom - ulSrcTop;
0381 ulHeight = ulSrc;
0382
0383 ulDest = srcDest.ulDstY2 - (srcDest.ulDstY1 - 1);
0384 ulPattern = adwDecim8[ulBits];
0385
0386
0387 if (ulSrc > ulDest) {
0388 ulDecimate = ulSrc - ulDest;
0389 ulBits = 0;
0390 ulApplied = ulSrc / 32;
0391
0392 while (((ulBits * ulApplied) +
0393 Overlap((ulSrc % 32),
0394 adwDecim8[ulBits])) < ulDecimate)
0395 ulBits++;
0396
0397 ulPattern = adwDecim8[ulBits];
0398 ulDecimated =
0399 (ulBits * ulApplied) + Overlap((ulSrc % 32),
0400 ulPattern);
0401 ulSrc = ulSrc - ulDecimated;
0402 }
0403
0404 if (ulBits && (ulBits != 32)) {
0405 ulVertDecFactor = (63 - ulBits) / (32 - ulBits);
0406 } else {
0407 ulVertDecFactor = 1;
0408 }
0409
0410 ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1);
0411
0412 tmp = STG_READ_REG(DACOverlayVtDec);
0413 CLEAR_BITS_FRM_TO(0, 31);
0414 tmp = ulPattern;
0415 STG_WRITE_REG(DACOverlayVtDec, tmp);
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431 ulSrc = srcDest.ulSrcX2 - srcDest.ulSrcX1;
0432 ulDest = srcDest.lDstX2 - srcDest.lDstX1;
0433 #ifdef _OLDCODE
0434 ulLeft = srcDest.ulDstX1;
0435 ulRight = srcDest.ulDstX2;
0436 #else
0437 if (srcDest.ulDstX1 > 2) {
0438 ulLeft = srcDest.ulDstX1 + 2;
0439 ulRight = srcDest.ulDstX2 + 1;
0440 } else {
0441 ulLeft = srcDest.ulDstX1;
0442 ulRight = srcDest.ulDstX2 + 1;
0443 }
0444 #endif
0445
0446 bResult = 1;
0447
0448 do {
0449 if (ulDest == 0)
0450 return -EINVAL;
0451
0452
0453 ulFxScale = ((ulSrc - 1) << 11) / (ulDest);
0454
0455
0456 ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff);
0457 ulFxOffset >>= 11;
0458
0459
0460 ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset;
0461
0462
0463 ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2);
0464 ulFxOffset >>= 11;
0465
0466 ulSrcRight = srcDest.ulSrcX2 - ulFxOffset;
0467
0468
0469
0470
0471
0472 ulScaleLeft = ulSrcLeft;
0473
0474
0475 ulhDecim = 0;
0476 ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
0477
0478 while (ulScale > 0x800) {
0479 ulhDecim++;
0480 ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
0481 }
0482
0483
0484
0485
0486
0487
0488
0489
0490 if (!ovlLinear) {
0491 ulSrcLeft &= ~0x1f;
0492
0493
0494
0495
0496
0497
0498 ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
0499 } else {
0500 ulSrcLeft &= ~0x7;
0501
0502
0503
0504
0505
0506 ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
0507 }
0508
0509
0510 ulWidth = ulSrcRight - ulSrcLeft;
0511
0512
0513
0514
0515
0516
0517 ulsVal = ((ulWidth / 8) >> ulhDecim);
0518
0519 if ((ulWidth != (ulsVal << ulhDecim) * 8))
0520 ulsAdd = 1;
0521
0522
0523 ulSrc = ulWidth >> ulhDecim;
0524
0525 if (ulSrc <= 2)
0526 return -EINVAL;
0527
0528 ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale);
0529
0530 ulClip = (ulSrc << 11) / ulScale;
0531 ulClip -= (ulRight - ulLeft);
0532 ulClip += ulExcessPixels;
0533
0534 if (ulClip)
0535 ulClip--;
0536
0537
0538 } while (!bResult);
0539
0540 ulExtraLines = (1 << ulhDecim) * ulVertDecFactor;
0541 ulExtraLines += 64;
0542 ulHeight += ulExtraLines;
0543
0544 ulDacXScale = ulScale;
0545
0546
0547 tmp = STG_READ_REG(DACVerticalScal);
0548 CLEAR_BITS_FRM_TO(0, 11);
0549 CLEAR_BITS_FRM_TO(16, 22);
0550
0551
0552
0553
0554
0555 ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
0556 tmp |= ((ulStride << 16) | (ulDacYScale));
0557 STG_WRITE_REG(DACVerticalScal, tmp);
0558
0559
0560
0561
0562 tmp = STG_READ_REG(DACOverlaySize);
0563 CLEAR_BITS_FRM_TO(0, 10);
0564 CLEAR_BITS_FRM_TO(12, 31);
0565
0566 if (ovlLinear) {
0567 tmp |=
0568 (ovlStride | ((ulHeight + 1) << 12) |
0569 (((ulWidth / 8) - 1) << 23));
0570 } else {
0571 tmp |=
0572 (ovlStride | ((ulHeight + 1) << 12) |
0573 (((ulWidth / 32) - 1) << 23));
0574 }
0575
0576 STG_WRITE_REG(DACOverlaySize, tmp);
0577
0578
0579 tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
0580 STG_WRITE_REG(DACVidWinStart, tmp);
0581
0582
0583 tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
0584 STG_WRITE_REG(DACVidWinEnd, tmp);
0585
0586
0587
0588
0589 tmp = STG_READ_REG(DACPixelFormat);
0590 tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff;
0591 STG_WRITE_REG(DACPixelFormat, tmp);
0592
0593 tmp = STG_READ_REG(DACHorizontalScal);
0594 CLEAR_BITS_FRM_TO(0, 11);
0595 CLEAR_BITS_FRM_TO(16, 17);
0596 tmp |= ((ulhDecim << 16) | (ulDacXScale));
0597 STG_WRITE_REG(DACHorizontalScal, tmp);
0598
0599 return 0;
0600 }