1
2
3
4
5
6
7
8
9
10
11
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/types.h>
15
16#include "STG4000Reg.h"
17#include "STG4000Interface.h"
18
19
20
21#define STG4000_NO_SCALING 0x800
22#define STG4000_NO_DECIMATION 0xFFFFFFFF
23
24
25#define STG4000_PRIM_NUM_PIX 5
26#define STG4000_PRIM_ALIGN 4
27#define STG4000_PRIM_ADDR_BITS 20
28
29#define STG4000_PRIM_MIN_WIDTH 640
30#define STG4000_PRIM_MAX_WIDTH 1600
31#define STG4000_PRIM_MIN_HEIGHT 480
32#define STG4000_PRIM_MAX_HEIGHT 1200
33
34
35#define STG4000_OVRL_NUM_PIX 4
36#define STG4000_OVRL_ALIGN 2
37#define STG4000_OVRL_ADDR_BITS 20
38#define STG4000_OVRL_NUM_MODES 5
39
40#define STG4000_OVRL_MIN_WIDTH 0
41#define STG4000_OVRL_MAX_WIDTH 720
42#define STG4000_OVRL_MIN_HEIGHT 0
43#define STG4000_OVRL_MAX_HEIGHT 576
44
45
46static u32 adwDecim8[33] = {
47 0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
48 0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7,
49 0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab,
50 0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525,
51 0xa4924925, 0x92491249, 0x91224489, 0x91111111, 0x90884211,
52 0x88410821, 0x88102041, 0x81010101, 0x80800801, 0x80010001,
53 0x80000001, 0x00000001, 0x00000000
54};
55
56typedef struct _OVRL_SRC_DEST {
57
58 u32 ulDstX1;
59 u32 ulDstY1;
60 u32 ulDstX2;
61 u32 ulDstY2;
62
63
64 u32 ulSrcX1;
65 u32 ulSrcY1;
66 u32 ulSrcX2;
67 u32 ulSrcY2;
68
69
70 s32 lDstX1;
71 s32 lDstY1;
72 s32 lDstX2;
73 s32 lDstY2;
74} OVRL_SRC_DEST;
75
76static u32 ovlWidth, ovlHeight, ovlStride;
77static int ovlLinear;
78
79void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg)
80{
81 u32 tmp;
82
83
84 tmp = STG_READ_REG(DACOverlayAddr);
85 CLEAR_BITS_FRM_TO(0, 20);
86 CLEAR_BIT(31);
87 STG_WRITE_REG(DACOverlayAddr, tmp);
88
89
90 tmp = STG_READ_REG(DACOverlayUAddr);
91 CLEAR_BITS_FRM_TO(0, 20);
92 STG_WRITE_REG(DACOverlayUAddr, tmp);
93
94
95 tmp = STG_READ_REG(DACOverlayVAddr);
96 CLEAR_BITS_FRM_TO(0, 20);
97 STG_WRITE_REG(DACOverlayVAddr, tmp);
98
99
100 tmp = STG_READ_REG(DACOverlaySize);
101 CLEAR_BITS_FRM_TO(0, 10);
102 CLEAR_BITS_FRM_TO(12, 31);
103 STG_WRITE_REG(DACOverlaySize, tmp);
104
105
106 tmp = STG4000_NO_DECIMATION;
107 STG_WRITE_REG(DACOverlayVtDec, tmp);
108
109
110 tmp = STG_READ_REG(DACPixelFormat);
111 CLEAR_BITS_FRM_TO(4, 7);
112 CLEAR_BITS_FRM_TO(16, 22);
113 STG_WRITE_REG(DACPixelFormat, tmp);
114
115
116 tmp = STG_READ_REG(DACVerticalScal);
117 CLEAR_BITS_FRM_TO(0, 11);
118 CLEAR_BITS_FRM_TO(16, 22);
119 tmp |= STG4000_NO_SCALING;
120 STG_WRITE_REG(DACVerticalScal, tmp);
121
122
123 tmp = STG_READ_REG(DACHorizontalScal);
124 CLEAR_BITS_FRM_TO(0, 11);
125 CLEAR_BITS_FRM_TO(16, 17);
126 tmp |= STG4000_NO_SCALING;
127 STG_WRITE_REG(DACHorizontalScal, tmp);
128
129
130
131
132
133 tmp = STG_READ_REG(DACBlendCtrl);
134 CLEAR_BITS_FRM_TO(0, 30);
135 tmp = (GRAPHICS_MODE << 28);
136 STG_WRITE_REG(DACBlendCtrl, tmp);
137
138}
139
140int CreateOverlaySurface(volatile STG4000REG __iomem *pSTGReg,
141 u32 inWidth,
142 u32 inHeight,
143 int bLinear,
144 u32 ulOverlayOffset,
145 u32 * retStride, u32 * retUVStride)
146{
147 u32 tmp;
148 u32 ulStride;
149
150 if (inWidth > STG4000_OVRL_MAX_WIDTH ||
151 inHeight > STG4000_OVRL_MAX_HEIGHT) {
152 return -EINVAL;
153 }
154
155
156 if (bLinear) {
157
158 if ((inWidth & 0x7) == 0) {
159 ulStride = (inWidth / 8);
160 } else {
161
162 ulStride = ((inWidth + 8) / 8);
163 }
164 } else {
165
166 if ((inWidth & 0xf) == 0) {
167 ulStride = (inWidth / 16);
168 } else {
169
170 ulStride = ((inWidth + 16) / 16);
171 }
172 }
173
174
175
176 tmp = STG_READ_REG(DACOverlayAddr);
177 CLEAR_BITS_FRM_TO(0, 20);
178 if (bLinear) {
179 CLEAR_BIT(31);
180 } else {
181 tmp |= SET_BIT(31);
182 }
183
184
185 tmp |= (ulOverlayOffset >> 4);
186 STG_WRITE_REG(DACOverlayAddr, tmp);
187
188 if (!bLinear) {
189 u32 uvSize =
190 (inWidth & 0x1) ? (inWidth + 1 / 2) : (inWidth / 2);
191 u32 uvStride;
192 u32 ulOffset;
193
194 if ((uvSize & 0xf) == 0) {
195 uvStride = (uvSize / 16);
196 } else {
197
198 uvStride = ((uvSize + 16) / 16);
199 }
200
201 ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16));
202
203 if ((ulOffset & 0x1f) != 0)
204 ulOffset = (ulOffset + 32L) & 0xffffffE0L;
205
206 tmp = STG_READ_REG(DACOverlayUAddr);
207 CLEAR_BITS_FRM_TO(0, 20);
208 tmp |= (ulOffset >> 4);
209 STG_WRITE_REG(DACOverlayUAddr, tmp);
210
211 ulOffset += (inHeight / 2) * (uvStride * 16);
212
213 if ((ulOffset & 0x1f) != 0)
214 ulOffset = (ulOffset + 32L) & 0xffffffE0L;
215
216 tmp = STG_READ_REG(DACOverlayVAddr);
217 CLEAR_BITS_FRM_TO(0, 20);
218 tmp |= (ulOffset >> 4);
219 STG_WRITE_REG(DACOverlayVAddr, tmp);
220
221 *retUVStride = uvStride * 16;
222 }
223
224
225
226
227
228 tmp = STG_READ_REG(DACPixelFormat);
229
230 CLEAR_BITS_FRM_TO(4, 9);
231 STG_WRITE_REG(DACPixelFormat, tmp);
232
233 ovlWidth = inWidth;
234 ovlHeight = inHeight;
235 ovlStride = ulStride;
236 ovlLinear = bLinear;
237 *retStride = ulStride << 4;
238
239 return 0;
240}
241
242int SetOverlayBlendMode(volatile STG4000REG __iomem *pSTGReg,
243 OVRL_BLEND_MODE mode,
244 u32 ulAlpha, u32 ulColorKey)
245{
246 u32 tmp;
247
248 tmp = STG_READ_REG(DACBlendCtrl);
249 CLEAR_BITS_FRM_TO(28, 30);
250 tmp |= (mode << 28);
251
252 switch (mode) {
253 case COLOR_KEY:
254 CLEAR_BITS_FRM_TO(0, 23);
255 tmp |= (ulColorKey & 0x00FFFFFF);
256 break;
257
258 case GLOBAL_ALPHA:
259 CLEAR_BITS_FRM_TO(24, 27);
260 tmp |= ((ulAlpha & 0xF) << 24);
261 break;
262
263 case CK_PIXEL_ALPHA:
264 CLEAR_BITS_FRM_TO(0, 23);
265 tmp |= (ulColorKey & 0x00FFFFFF);
266 break;
267
268 case CK_GLOBAL_ALPHA:
269 CLEAR_BITS_FRM_TO(0, 23);
270 tmp |= (ulColorKey & 0x00FFFFFF);
271 CLEAR_BITS_FRM_TO(24, 27);
272 tmp |= ((ulAlpha & 0xF) << 24);
273 break;
274
275 case GRAPHICS_MODE:
276 case PER_PIXEL_ALPHA:
277 break;
278
279 default:
280 return -EINVAL;
281 }
282
283 STG_WRITE_REG(DACBlendCtrl, tmp);
284
285 return 0;
286}
287
288void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg)
289{
290 u32 tmp;
291
292 tmp = STG_READ_REG(DACPixelFormat);
293 tmp |= SET_BIT(7);
294 STG_WRITE_REG(DACPixelFormat, tmp);
295
296
297 tmp = STG_READ_REG(DACStreamCtrl);
298 tmp |= SET_BIT(1);
299 STG_WRITE_REG(DACStreamCtrl, tmp);
300}
301
302static u32 Overlap(u32 ulBits, u32 ulPattern)
303{
304 u32 ulCount = 0;
305
306 while (ulBits) {
307 if (!(ulPattern & 1))
308 ulCount++;
309 ulBits--;
310 ulPattern = ulPattern >> 1;
311 }
312
313 return ulCount;
314
315}
316
317int SetOverlayViewPort(volatile STG4000REG __iomem *pSTGReg,
318 u32 left, u32 top,
319 u32 right, u32 bottom)
320{
321 OVRL_SRC_DEST srcDest;
322
323 u32 ulSrcTop, ulSrcBottom;
324 u32 ulSrc, ulDest;
325 u32 ulFxScale, ulFxOffset;
326 u32 ulHeight, ulWidth;
327 u32 ulPattern;
328 u32 ulDecimate, ulDecimated;
329 u32 ulApplied;
330 u32 ulDacXScale, ulDacYScale;
331 u32 ulScale;
332 u32 ulLeft, ulRight;
333 u32 ulSrcLeft, ulSrcRight;
334 u32 ulScaleLeft;
335 u32 ulhDecim;
336 u32 ulsVal;
337 u32 ulVertDecFactor;
338 int bResult;
339 u32 ulClipOff = 0;
340 u32 ulBits = 0;
341 u32 ulsAdd = 0;
342 u32 tmp, ulStride;
343 u32 ulExcessPixels, ulClip, ulExtraLines;
344
345
346 srcDest.ulSrcX1 = 0;
347 srcDest.ulSrcY1 = 0;
348 srcDest.ulSrcX2 = ovlWidth - 1;
349 srcDest.ulSrcY2 = ovlHeight - 1;
350
351 srcDest.ulDstX1 = left;
352 srcDest.ulDstY1 = top;
353 srcDest.ulDstX2 = right;
354 srcDest.ulDstY2 = bottom;
355
356 srcDest.lDstX1 = srcDest.ulDstX1;
357 srcDest.lDstY1 = srcDest.ulDstY1;
358 srcDest.lDstX2 = srcDest.ulDstX2;
359 srcDest.lDstY2 = srcDest.ulDstY2;
360
361
362
363
364 ulSrcTop = srcDest.ulSrcY1;
365 ulSrcBottom = srcDest.ulSrcY2;
366
367 ulSrc = ulSrcBottom - ulSrcTop;
368 ulDest = srcDest.lDstY2 - srcDest.lDstY1;
369
370 if (ulSrc <= 1)
371 return -EINVAL;
372
373
374
375
376 ulFxScale = (ulDest << 11) / ulSrc;
377 ulFxOffset = (srcDest.lDstY2 - srcDest.ulDstY2) << 11;
378
379 ulSrcBottom = ulSrcBottom - (ulFxOffset / ulFxScale);
380 ulSrc = ulSrcBottom - ulSrcTop;
381 ulHeight = ulSrc;
382
383 ulDest = srcDest.ulDstY2 - (srcDest.ulDstY1 - 1);
384 ulPattern = adwDecim8[ulBits];
385
386
387 if (ulSrc > ulDest) {
388 ulDecimate = ulSrc - ulDest;
389 ulBits = 0;
390 ulApplied = ulSrc / 32;
391
392 while (((ulBits * ulApplied) +
393 Overlap((ulSrc % 32),
394 adwDecim8[ulBits])) < ulDecimate)
395 ulBits++;
396
397 ulPattern = adwDecim8[ulBits];
398 ulDecimated =
399 (ulBits * ulApplied) + Overlap((ulSrc % 32),
400 ulPattern);
401 ulSrc = ulSrc - ulDecimated;
402 }
403
404 if (ulBits && (ulBits != 32)) {
405 ulVertDecFactor = (63 - ulBits) / (32 - ulBits);
406 } else {
407 ulVertDecFactor = 1;
408 }
409
410 ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1);
411
412 tmp = STG_READ_REG(DACOverlayVtDec);
413 CLEAR_BITS_FRM_TO(0, 31);
414 tmp = ulPattern;
415 STG_WRITE_REG(DACOverlayVtDec, tmp);
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431 ulSrc = srcDest.ulSrcX2 - srcDest.ulSrcX1;
432 ulDest = srcDest.lDstX2 - srcDest.lDstX1;
433#ifdef _OLDCODE
434 ulLeft = srcDest.ulDstX1;
435 ulRight = srcDest.ulDstX2;
436#else
437 if (srcDest.ulDstX1 > 2) {
438 ulLeft = srcDest.ulDstX1 + 2;
439 ulRight = srcDest.ulDstX2 + 1;
440 } else {
441 ulLeft = srcDest.ulDstX1;
442 ulRight = srcDest.ulDstX2 + 1;
443 }
444#endif
445
446 bResult = 1;
447
448 do {
449 if (ulDest == 0)
450 return -EINVAL;
451
452
453 ulFxScale = ((ulSrc - 1) << 11) / (ulDest);
454
455
456 ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff);
457 ulFxOffset >>= 11;
458
459
460 ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset;
461
462
463 ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2);
464 ulFxOffset >>= 11;
465
466 ulSrcRight = srcDest.ulSrcX2 - ulFxOffset;
467
468
469
470
471
472 ulScaleLeft = ulSrcLeft;
473
474
475 ulhDecim = 0;
476 ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
477
478 while (ulScale > 0x800) {
479 ulhDecim++;
480 ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
481 }
482
483
484
485
486
487
488
489
490 if (!ovlLinear) {
491 ulSrcLeft &= ~0x1f;
492
493
494
495
496
497
498 ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
499 } else {
500 ulSrcLeft &= ~0x7;
501
502
503
504
505
506 ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
507 }
508
509
510 ulWidth = ulSrcRight - ulSrcLeft;
511
512
513
514
515
516
517 ulsVal = ((ulWidth / 8) >> ulhDecim);
518
519 if ((ulWidth != (ulsVal << ulhDecim) * 8))
520 ulsAdd = 1;
521
522
523 ulSrc = ulWidth >> ulhDecim;
524
525 if (ulSrc <= 2)
526 return -EINVAL;
527
528 ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale);
529
530 ulClip = (ulSrc << 11) / ulScale;
531 ulClip -= (ulRight - ulLeft);
532 ulClip += ulExcessPixels;
533
534 if (ulClip)
535 ulClip--;
536
537
538 } while (!bResult);
539
540 ulExtraLines = (1 << ulhDecim) * ulVertDecFactor;
541 ulExtraLines += 64;
542 ulHeight += ulExtraLines;
543
544 ulDacXScale = ulScale;
545
546
547 tmp = STG_READ_REG(DACVerticalScal);
548 CLEAR_BITS_FRM_TO(0, 11);
549 CLEAR_BITS_FRM_TO(16, 22);
550
551
552
553
554
555 ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
556 tmp |= ((ulStride << 16) | (ulDacYScale));
557 STG_WRITE_REG(DACVerticalScal, tmp);
558
559
560
561
562 tmp = STG_READ_REG(DACOverlaySize);
563 CLEAR_BITS_FRM_TO(0, 10);
564 CLEAR_BITS_FRM_TO(12, 31);
565
566 if (ovlLinear) {
567 tmp |=
568 (ovlStride | ((ulHeight + 1) << 12) |
569 (((ulWidth / 8) - 1) << 23));
570 } else {
571 tmp |=
572 (ovlStride | ((ulHeight + 1) << 12) |
573 (((ulWidth / 32) - 1) << 23));
574 }
575
576 STG_WRITE_REG(DACOverlaySize, tmp);
577
578
579 tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
580 STG_WRITE_REG(DACVidWinStart, tmp);
581
582
583 tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
584 STG_WRITE_REG(DACVidWinEnd, tmp);
585
586
587
588
589 tmp = STG_READ_REG(DACPixelFormat);
590 tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff;
591 STG_WRITE_REG(DACPixelFormat, tmp);
592
593 tmp = STG_READ_REG(DACHorizontalScal);
594 CLEAR_BITS_FRM_TO(0, 11);
595 CLEAR_BITS_FRM_TO(16, 17);
596 tmp |= ((ulhDecim << 16) | (ulDacXScale));
597 STG_WRITE_REG(DACHorizontalScal, tmp);
598
599 return 0;
600}
601