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;
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 
474 		/* shift fxscale until it is in the range of the scaler */
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 		 * to try and get the best values We first try and use
485 		 * src/dwdest for the scale factor, then we move onto src-1
486 		 *
487 		 * we want to check to see if we will need to clip data, if so
488 		 * then we should clip our source so that we don't need to
489 		 */
490 		if (!ovlLinear) {
491 			ulSrcLeft &= ~0x1f;
492 
493 			/*
494 			 * we must align the right hand edge to the next 32
495 			 * pixel` boundary, must be on a 256 boundary so u, and
496 			 * v are 128 bit aligned
497 			 */
498 			ulSrcRight = (ulSrcRight + 0x1f) & ~0x1f;
499 		} else {
500 			ulSrcLeft &= ~0x7;
501 
502 			/*
503 			 * we must align the right hand edge to the next
504 			 * 8pixel` boundary
505 			 */
506 			ulSrcRight = (ulSrcRight + 0x7) & ~0x7;
507 		}
508 
509 		/* this is the input size line store needs to cope with */
510 		ulWidth = ulSrcRight - ulSrcLeft;
511 
512 		/*
513 		 * use unclipped value to work out scale factror this is the
514 		 * scale factor we want we shall now work out the horizonal
515 		 * decimation and scaling
516 		 */
517 		ulsVal = ((ulWidth / 8) >> ulhDecim);
518 
519 		if ((ulWidth != (ulsVal << ulhDecim) * 8))
520 			ulsAdd = 1;
521 
522 		/* input pixels to scaler; */
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 		/* We may need to do more here if we really have a HW rev < 5 */
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);	/* Vertical Scaling */
550 
551 	/* Calculate new output line stride, this is always the number of 422
552 	   words in the line buffer, so it doesn't matter if the
553 	   mode is 420. Then set the vertical scale register.
554 	 */
555 	ulStride = (ulWidth >> (ulhDecim + 3)) + ulsAdd;
556 	tmp |= ((ulStride << 16) | (ulDacYScale));	/* DAC_LS_CTRL = stride */
557 	STG_WRITE_REG(DACVerticalScal, tmp);
558 
559 	/* Now set up the overlay size using the modified width and height
560 	   from decimate and scaling calculations
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 	/* Set Video Window Start */
579 	tmp = ((ulLeft << 16)) | (srcDest.ulDstY1);
580 	STG_WRITE_REG(DACVidWinStart, tmp);
581 
582 	/* Set Video Window End */
583 	tmp = ((ulRight) << 16) | (srcDest.ulDstY2);
584 	STG_WRITE_REG(DACVidWinEnd, tmp);
585 
586 	/* Finally set up the rest of the overlay regs in the order
587 	   done in the IMG driver
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