1 /*
2  *  linux/drivers/video/kyro/STG4000OverlayDevice.c
3  *
4  *  Copyright (C) 2000 Imagination Technologies Ltd
5  *  Copyright (C) 2002 STMicroelectronics
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file COPYING in the main directory of this archive
9  * for more details.
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 /* HW Defines */
20 
21 #define STG4000_NO_SCALING    0x800
22 #define STG4000_NO_DECIMATION 0xFFFFFFFF
23 
24 /* Primary surface */
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 /* Overlay surface */
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 /* Decimation and Scaling */
46 static 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 
56 typedef struct _OVRL_SRC_DEST {
57 	/*clipped on-screen pixel position of overlay */
58 	u32 ulDstX1;
59 	u32 ulDstY1;
60 	u32 ulDstX2;
61 	u32 ulDstY2;
62 
63 	/*clipped pixel pos of source data within buffer thses need to be 128 bit word aligned */
64 	u32 ulSrcX1;
65 	u32 ulSrcY1;
66 	u32 ulSrcX2;
67 	u32 ulSrcY2;
68 
69 	/* on-screen pixel position of overlay */
70 	s32 lDstX1;
71 	s32 lDstY1;
72 	s32 lDstX2;
73 	s32 lDstY2;
74 } OVRL_SRC_DEST;
75 
76 static u32 ovlWidth, ovlHeight, ovlStride;
77 static int ovlLinear;
78 
79 void ResetOverlayRegisters(volatile STG4000REG __iomem *pSTGReg)
80 {
81 	u32 tmp;
82 
83 	/* Set Overlay address to default */
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 	/* Set Overlay U address */
90 	tmp = STG_READ_REG(DACOverlayUAddr);
91 	CLEAR_BITS_FRM_TO(0, 20);
92 	STG_WRITE_REG(DACOverlayUAddr, tmp);
93 
94 	/* Set Overlay V address */
95 	tmp = STG_READ_REG(DACOverlayVAddr);
96 	CLEAR_BITS_FRM_TO(0, 20);
97 	STG_WRITE_REG(DACOverlayVAddr, tmp);
98 
99 	/* Set Overlay Size */
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 	/* Set Overlay Vt Decimation */
106 	tmp = STG4000_NO_DECIMATION;
107 	STG_WRITE_REG(DACOverlayVtDec, tmp);
108 
109 	/* Set Overlay format to default value */
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 	/* Set Vertical scaling to default */
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;	/* Set to no scaling */
120 	STG_WRITE_REG(DACVerticalScal, tmp);
121 
122 	/* Set Horizontal Scaling to default */
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;	/* Set to no scaling */
127 	STG_WRITE_REG(DACHorizontalScal, tmp);
128 
129 	/* Set Blend mode to Alpha Blend */
130 	/* ????? SG 08/11/2001 Surely this isn't the alpha blend mode,
131 	   hopefully its overwrite
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 
140 int 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 	/* Stride in 16 byte words - 16Bpp */
156 	if (bLinear) {
157 		/* Format is 16bits so num 16 byte words is width/8 */
158 		if ((inWidth & 0x7) == 0) {	/* inWidth % 8 */
159 			ulStride = (inWidth / 8);
160 		} else {
161 			/* Round up to next 16byte boundary */
162 			ulStride = ((inWidth + 8) / 8);
163 		}
164 	} else {
165 		/* Y component is 8bits so num 16 byte words is width/16 */
166 		if ((inWidth & 0xf) == 0) {	/* inWidth % 16 */
167 			ulStride = (inWidth / 16);
168 		} else {
169 			/* Round up to next 16byte boundary */
170 			ulStride = ((inWidth + 16) / 16);
171 		}
172 	}
173 
174 
175 	/* Set Overlay address and Format mode */
176 	tmp = STG_READ_REG(DACOverlayAddr);
177 	CLEAR_BITS_FRM_TO(0, 20);
178 	if (bLinear) {
179 		CLEAR_BIT(31);	/* Overlay format to Linear */
180 	} else {
181 		tmp |= SET_BIT(31);	/* Overlay format to Planer */
182 	}
183 
184 	/* Only bits 24:4 of the Overlay address */
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 		/* Y component is 8bits so num 32 byte words is width/32 */
194 		if ((uvSize & 0xf) == 0) {	/* inWidth % 16 */
195 			uvStride = (uvSize / 16);
196 		} else {
197 			/* Round up to next 32byte boundary */
198 			uvStride = ((uvSize + 16) / 16);
199 		}
200 
201 		ulOffset = ulOverlayOffset + (inHeight * (ulStride * 16));
202 		/* Align U,V data to 32byte boundary */
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 		/* Align U,V data to 32byte boundary */
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 	/* Set Overlay YUV pixel format
226 	 * Make sure that LUT not used - ??????
227 	 */
228 	tmp = STG_READ_REG(DACPixelFormat);
229 	/* Only support Planer or UYVY linear formats */
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;	/* In bytes */
238 
239 	return 0;
240 }
241 
242 int 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 
288 void EnableOverlayPlane(volatile STG4000REG __iomem *pSTGReg)
289 {
290 	u32 tmp;
291 	/* Enable Overlay */
292 	tmp = STG_READ_REG(DACPixelFormat);
293 	tmp |= SET_BIT(7);
294 	STG_WRITE_REG(DACPixelFormat, tmp);
295 
296 	/* Set video stream control */
297 	tmp = STG_READ_REG(DACStreamCtrl);
298 	tmp |= SET_BIT(1);	/* video stream */
299 	STG_WRITE_REG(DACStreamCtrl, tmp);
300 }
301 
302 static 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 
317 int 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, ulScaleRight;
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     /************* Vertical decimation/scaling ******************/
362 
363 	/* Get Src Top and Bottom */
364 	ulSrcTop = srcDest.ulSrcY1;
365 	ulSrcBottom = srcDest.ulSrcY2;
366 
367 	ulSrc = ulSrcBottom - ulSrcTop;
368 	ulDest = srcDest.lDstY2 - srcDest.lDstY1;	/* on-screen overlay */
369 
370 	if (ulSrc <= 1)
371 		return -EINVAL;
372 
373 	/* First work out the position we are to display as offset from the
374 	 * source of the buffer
375 	 */
376 	ulFxScale = (ulDest << 11) / ulSrc;	/* fixed point scale factor */
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 	/* At this point ulSrc represents the input decimator */
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;	/* the number number of lines that will go into the scaler */
402 	}
403 
404 	if (ulBits && (ulBits != 32)) {
405 		ulVertDecFactor = (63 - ulBits) / (32 - ulBits);	/* vertical decimation factor scaled up to nearest integer */
406 	} else {
407 		ulVertDecFactor = 1;
408 	}
409 
410 	ulDacYScale = ((ulSrc - 1) * 2048) / (ulDest + 1);
411 
412 	tmp = STG_READ_REG(DACOverlayVtDec);	/* Decimation */
413 	CLEAR_BITS_FRM_TO(0, 31);
414 	tmp = ulPattern;
415 	STG_WRITE_REG(DACOverlayVtDec, tmp);
416 
417 	/***************** Horizontal decimation/scaling ***************************/
418 
419 	/*
420 	 * Now we handle the horizontal case, this is a simplified version of
421 	 * the vertical case in that we decimate by factors of 2.  as we are
422 	 * working in words we should always be able to decimate by these
423 	 * factors.  as we always have to have a buffer which is aligned to a
424 	 * whole number of 128 bit words, we must align the left side to the
425 	 * lowest to the next lowest 128 bit boundary, and the right hand edge
426 	 * to the next largets boundary, (in a similar way to how we didi it in
427 	 * PMX1) as the left and right hand edges are aligned to these
428 	 * boundaries normally this only becomes an issue when we are chopping
429 	 * of one of the sides We shall work out vertical stuff first
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 	/* first work out the position we are to display as offset from the source of the buffer */
446 	bResult = 1;
447 
448 	do {
449 		if (ulDest == 0)
450 			return -EINVAL;
451 
452 		/* source pixels per dest pixel <<11 */
453 		ulFxScale = ((ulSrc - 1) << 11) / (ulDest);
454 
455 		/* then number of destination pixels out we are */
456 		ulFxOffset = ulFxScale * ((srcDest.ulDstX1 - srcDest.lDstX1) + ulClipOff);
457 		ulFxOffset >>= 11;
458 
459 		/* this replaces the code which was making a decision as to use either ulFxOffset or ulSrcX1 */
460 		ulSrcLeft = srcDest.ulSrcX1 + ulFxOffset;
461 
462 		/* then number of destination pixels out we are */
463 		ulFxOffset = ulFxScale * (srcDest.lDstX2 - srcDest.ulDstX2);
464 		ulFxOffset >>= 11;
465 
466 		ulSrcRight = srcDest.ulSrcX2 - ulFxOffset;
467 
468 		/*
469 		 * we must align these to our 128 bit boundaries. we shall
470 		 * round down the pixel pos to the nearest 8 pixels.
471 		 */
472 		ulScaleLeft = ulSrcLeft;
473 		ulScaleRight = ulSrcRight;
474 
475 		/* shift fxscale until it is in the range of the scaler */
476 		ulhDecim = 0;
477 		ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
478 
479 		while (ulScale > 0x800) {
480 			ulhDecim++;
481 			ulScale = (((ulSrcRight - ulSrcLeft) - 1) << (11 - ulhDecim)) / (ulRight - ulLeft + 2);
482 		}
483 
484 		/*
485 		 * to try and get the best values We first try and use
486 		 * src/dwdest for the scale factor, then we move onto src-1
487 		 *
488 		 * we want to check to see if we will need to clip data, if so
489 		 * then we should clip our source so that we don't need to
490 		 */
491 		if (!ovlLinear) {
492 			ulSrcLeft &= ~0x1f;
493 
494 			/*
495 			 * we must align the right hand edge to the next 32
496 			 * pixel` boundary, must be on a 256 boundary so u, and
497 			 * v are 128 bit aligned
498 			 */
499 			ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
500 		} else {
501 			ulSrcLeft &= ~0x7;
502 
503 			/*
504 			 * we must align the right hand edge to the next
505 			 * 8pixel` boundary
506 			 */
507 			ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
508 		}
509 
510 		/* this is the input size line store needs to cope with */
511 		ulWidth = ulSrcRight - ulSrcLeft;
512 
513 		/*
514 		 * use unclipped value to work out scale factror this is the
515 		 * scale factor we want we shall now work out the horizonal
516 		 * decimation and scaling
517 		 */
518 		ulsVal = ((ulWidth / 8) >> ulhDecim);
519 
520 		if ((ulWidth != (ulsVal << ulhDecim) * 8))
521 			ulsAdd = 1;
522 
523 		/* input pixels to scaler; */
524 		ulSrc = ulWidth >> ulhDecim;
525 
526 		if (ulSrc <= 2)
527 			return -EINVAL;
528 
529 		ulExcessPixels = ((((ulScaleLeft - ulSrcLeft)) << (11 - ulhDecim)) / ulScale);
530 
531 		ulClip = (ulSrc << 11) / ulScale;
532 		ulClip -= (ulRight - ulLeft);
533 		ulClip += ulExcessPixels;
534 
535 		if (ulClip)
536 			ulClip--;
537 
538 		/* We may need to do more here if we really have a HW rev < 5 */
539 	} while (!bResult);
540 
541 	ulExtraLines = (1 << ulhDecim) * ulVertDecFactor;
542 	ulExtraLines += 64;
543 	ulHeight += ulExtraLines;
544 
545 	ulDacXScale = ulScale;
546 
547 
548 	tmp = STG_READ_REG(DACVerticalScal);
549 	CLEAR_BITS_FRM_TO(0, 11);
550 	CLEAR_BITS_FRM_TO(16, 22);	/* Vertical Scaling */
551 
552 	/* Calculate new output line stride, this is always the number of 422
553 	   words in the line buffer, so it doesn't matter if the
554 	   mode is 420. Then set the vertical scale register.
555 	 */
556 	ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
557 	tmp |= ((ulStride << 16) | (ulDacYScale));	/* DAC_LS_CTRL = stride */
558 	STG_WRITE_REG(DACVerticalScal, tmp);
559 
560 	/* Now set up the overlay size using the modified width and height
561 	   from decimate and scaling calculations
562 	 */
563 	tmp = STG_READ_REG(DACOverlaySize);
564 	CLEAR_BITS_FRM_TO(0, 10);
565 	CLEAR_BITS_FRM_TO(12, 31);
566 
567 	if (ovlLinear) {
568 		tmp |=
569 		    (ovlStride | ((ulHeight + 1) << 12) |
570 		     (((ulWidth / 8) - 1) << 23));
571 	} else {
572 		tmp |=
573 		    (ovlStride | ((ulHeight + 1) << 12) |
574 		     (((ulWidth / 32) - 1) << 23));
575 	}
576 
577 	STG_WRITE_REG(DACOverlaySize, tmp);
578 
579 	/* Set Video Window Start */
580 	tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
581 	STG_WRITE_REG(DACVidWinStart, tmp);
582 
583 	/* Set Video Window End */
584 	tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
585 	STG_WRITE_REG(DACVidWinEnd, tmp);
586 
587 	/* Finally set up the rest of the overlay regs in the order
588 	   done in the IMG driver
589 	 */
590 	tmp = STG_READ_REG(DACPixelFormat);
591 	tmp = ((ulExcessPixels << 16) | tmp) & 0x7fffffff;
592 	STG_WRITE_REG(DACPixelFormat, tmp);
593 
594 	tmp = STG_READ_REG(DACHorizontalScal);
595 	CLEAR_BITS_FRM_TO(0, 11);
596 	CLEAR_BITS_FRM_TO(16, 17);
597 	tmp |= ((ulhDecim << 16) | (ulDacXScale));
598 	STG_WRITE_REG(DACHorizontalScal, tmp);
599 
600 	return 0;
601 }
602