1 /*
2  * Copyright 2004-2005 The Unichrome Project  [unichrome.sf.net]
3  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
4  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sub license,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include "xf86.h"
31 #include "xf86_OSproc.h"
32 
33 #ifdef HAVE_DRI
34 #include "xf86drm.h"
35 #include "via_drmclient.h"
36 #include "via_drm.h"
37 #endif
38 #include "via_driver.h"
39 
40 #include <math.h>
41 #include <unistd.h>
42 
43 /*
44  * Warning: this file contains revision checks which are CLE266-specific.
45  * There seems to be no checking present for KM400 or more recent devices.
46  *
47  * TODO:
48  *   - pVia->Chipset checking, of course
49  *   - move content of pVia->HWDiff into pVia->swov
50  *   - merge with CLEXF40040
51  */
52 
53 /*
54  * Old via_regrec code.
55  */
56 #define VIDREG_BUFFER_SIZE  100  /* Number of entries in the VidRegBuffer. */
57 #define IN_VIDEO_DISPLAY (*((unsigned long volatile *)(pVia->MapBase + V_FLAGS)) & VBI_STATUS)
58 #define VIA_FIRETIMEOUT 40000
59 
60 enum HQV_CME_Regs {
61         HQV_SDO_CTRL1,
62         HQV_SDO_CTRL2,
63         HQV_SDO_CTRL3,
64         HQV_SDO_CTRL4
65 };
66 
67 /* register offsets for VT3553/VX800 */
68 static const unsigned hqv_cme_regs[] = {
69     [HQV_SDO_CTRL1]  = HQV_SRC_DATA_OFFSET_CONTROL1,
70     [HQV_SDO_CTRL2]  = HQV_SRC_DATA_OFFSET_CONTROL2,
71     [HQV_SDO_CTRL3]  = HQV_SRC_DATA_OFFSET_CONTROL3,
72     [HQV_SDO_CTRL4]  = HQV_SRC_DATA_OFFSET_CONTROL4
73 };
74 
75 /* register hqv offsets for new VT3409/VX855 */
76 static const unsigned hqv_cme_regs_409[] = {
77     [HQV_SDO_CTRL1]  = HQV_SRC_DATA_OFFSET_CTRL1_409,
78     [HQV_SDO_CTRL2]  = HQV_SRC_DATA_OFFSET_CTRL2_409,
79     [HQV_SDO_CTRL3]  = HQV_SRC_DATA_OFFSET_CTRL3_409,
80     [HQV_SDO_CTRL4]  = HQV_SRC_DATA_OFFSET_CTRL4_409
81 };
82 
83 #define HQV_CME_REG(HWDiff, name) (HWDiff)->HQVCmeRegs[name]
84 
85 static void
viaWaitVideoCommandFire(VIAPtr pVia)86 viaWaitVideoCommandFire(VIAPtr pVia)
87 {
88 /*
89  * Uncached PCI reading throughput is about 9 MB/s; so 8 bytes/loop means about
90  * 1M loops/second.  We want to time out after 50 ms, which means 50000 loops.
91  */
92     unsigned count = 50000;
93     CARD32 volatile *pdwState =
94             (CARD32 volatile *)(pVia->MapBase + V_COMPOSE_MODE);
95 
96     while (--count && ((*pdwState & V1_COMMAND_FIRE)
97                        || (*pdwState & V3_COMMAND_FIRE))) ;
98     if (!count) {
99         ErrorF("viaWaitVideoCommandFire: Timeout.\n");
100     }
101 }
102 
103 static void
viaWaitHQVFlip(VIAPtr pVia)104 viaWaitHQVFlip(VIAPtr pVia)
105 {
106     unsigned long proReg = 0;
107     CARD32 volatile *pdwState;
108     unsigned count = 50000;
109 
110     if (pVia->ChipId == PCI_CHIP_VT3259
111         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
112         proReg = PRO_HQV1_OFFSET;
113 
114     pdwState = (CARD32 volatile *)(pVia->MapBase + (HQV_CONTROL + proReg));
115 
116     if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
117 		while (--count && (*pdwState & HQV_SUBPIC_FLIP));
118     } else {
119         while (--count && !(*pdwState & HQV_FLIP_STATUS)) ;
120     }
121 }
122 
123 static void
viaWaitHQVFlipClear(VIAPtr pVia,unsigned long dwData)124 viaWaitHQVFlipClear(VIAPtr pVia, unsigned long dwData)
125 {
126     CARD32 volatile *pdwState =
127             (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL);
128     *pdwState = dwData;
129     unsigned count = 50000;
130 
131     while (--count && (*pdwState & HQV_FLIP_STATUS)) {
132         VIASETREG(HQV_CONTROL, *pdwState | HQV_FLIP_STATUS);
133     }
134 }
135 
136 static void
viaWaitVBI(VIAPtr pVia)137 viaWaitVBI(VIAPtr pVia)
138 {
139     while (IN_VIDEO_DISPLAY) ;
140 }
141 
142 static void
viaWaitHQVDone(VIAPtr pVia)143 viaWaitHQVDone(VIAPtr pVia)
144 {
145     CARD32 volatile *pdwState;
146     unsigned long proReg = 0;
147     unsigned count = 50000;
148 
149     if (pVia->ChipId == PCI_CHIP_VT3259
150         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
151         proReg = PRO_HQV1_OFFSET;
152 
153     pdwState = (CARD32 volatile *)(pVia->MapBase + (HQV_CONTROL + proReg));
154     if (pVia->swov.MPEG_ON) {
155         while (--count && (*pdwState & HQV_SW_FLIP)) ;
156     }
157 }
158 
159 /*
160  * Send all data in VidRegBuffer to the hardware.
161  */
162 static void
FlushVidRegBuffer(VIAPtr pVia)163 FlushVidRegBuffer(VIAPtr pVia)
164 {
165     unsigned int i;
166 
167     viaWaitVideoCommandFire(pVia);
168 
169     for (i = 0; i < pVia->VidRegCursor; i += 2) {
170         VIASETREG(pVia->VidRegBuffer[i], pVia->VidRegBuffer[i + 1]);
171         DBG_DD(ErrorF("FlushVideoRegs: [%i] %08lx %08lx\n",
172                       i >> 1, pVia->VidRegBuffer[i] + 0x200,
173                       pVia->VidRegBuffer[i + 1]));
174     }
175 
176     /* BUG: (?) VIA never resets the cursor.
177      * My fix is commented out for now, in case they had a reason for that. /A
178      */
179     /* pVia->VidRegCursor = 0; */
180 }
181 
182 /*
183  * Initialize and clear VidRegBuffer.
184  */
185 static void
ResetVidRegBuffer(VIAPtr pVia)186 ResetVidRegBuffer(VIAPtr pVia)
187 {
188     /* BUG: (Memory leak) This allocation may need have a corresponding free somewhere... /A */
189     if (!pVia->VidRegBuffer)
190         pVia->VidRegBuffer =
191                 xnfcalloc(VIDREG_BUFFER_SIZE, sizeof(CARD32) * 2);
192     pVia->VidRegCursor = 0;
193 }
194 
195 /*
196  * Save a video register and data in VidRegBuffer.
197  */
198 static void
SaveVideoRegister(VIAPtr pVia,CARD32 index,CARD32 data)199 SaveVideoRegister(VIAPtr pVia, CARD32 index, CARD32 data)
200 {
201     if (pVia->VidRegCursor >= VIDREG_BUFFER_SIZE) {
202         DBG_DD(ErrorF("SaveVideoRegister: Out of video register space flushing"));
203         FlushVidRegBuffer(pVia);
204         ResetVidRegBuffer(pVia);
205     }
206 
207     pVia->VidRegBuffer[pVia->VidRegCursor++] = index;
208     pVia->VidRegBuffer[pVia->VidRegCursor++] = data;
209 }
210 
211 /*
212  * HW Difference Flag (moved here from via_hwdiff.c)
213  *
214  * These are the entries of HWDiff used in our code (currently):
215  *                     CLE266Ax   CLE266Cx   KM400     K8M800    PM800
216  * ThreeHQVBuffer      FALSE      TRUE       TRUE      TRUE      TRUE
217  * HQVFetchByteUnit    FALSE      TRUE       TRUE      TRUE      TRUE
218  * SupportTwoColorKey  FALSE      TRUE       FALSE     FALSE     TRUE
219  * HQVInitPatch        TRUE       FALSE      FALSE     FALSE     FALSE
220  * HQVDisablePatch     FALSE      TRUE       TRUE      TRUE      FALSE
221  *
222  * This is now up to date with CLEXF40040. All unused entries were removed.
223  * The functions depending on this struct are untouched.
224  */
225 void
VIAVidHWDiffInit(ScrnInfoPtr pScrn)226 VIAVidHWDiffInit(ScrnInfoPtr pScrn)
227 {
228     VIAPtr pVia = VIAPTR(pScrn);
229     VIAHWDiff *HWDiff = &pVia->HWDiff;
230 
231     switch (pVia->Chipset) {
232         case VIA_CLE266:
233             if (CLE266_REV_IS_AX(pVia->ChipRev)) {
234                 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_FALSE;
235                 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_FALSE;
236                 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
237                 HWDiff->dwHQVInitPatch = VID_HWDIFF_TRUE;
238                 HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
239                 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
240             } else {
241                 HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
242                 HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
243                 HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
244                 HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
245                 HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
246                 HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
247             }
248             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
249             break;
250         case VIA_KM400:
251             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
252             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
253             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
254             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
255             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
256             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
257             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
258             break;
259         case VIA_K8M800:
260             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
261             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
262             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
263             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
264             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
265             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
266             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
267             break;
268         case VIA_PM800:
269             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
270             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
271             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
272             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
273             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
274             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
275             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
276             HWDiff->HQVCmeRegs = hqv_cme_regs;
277             break;
278         case VIA_P4M800PRO:
279         case VIA_P4M900:
280             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
281             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
282             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
283             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
284             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
285             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
286             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
287             HWDiff->HQVCmeRegs = hqv_cme_regs;
288             break;
289         case VIA_K8M890:
290             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
291             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
292             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
293             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
294             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
295             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_TRUE;
296             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
297             HWDiff->HQVCmeRegs = hqv_cme_regs;
298             break;
299         case VIA_P4M890:
300             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
301             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
302             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_FALSE;
303             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
304             HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
305             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
306             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
307             HWDiff->HQVCmeRegs = hqv_cme_regs;
308             break;
309         case VIA_CX700:
310             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
311             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
312             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
313             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
314             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
315             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
316             HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
317             HWDiff->HQVCmeRegs = hqv_cme_regs;
318             break;
319         case VIA_VX800:
320             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
321             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
322             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
323             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
324             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
325             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
326             HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
327             HWDiff->HQVCmeRegs = hqv_cme_regs;
328             break;
329         case VIA_VX855:
330         case VIA_VX900:
331             HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
332             HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
333             HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
334             HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
335             HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
336             HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
337             HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
338             HWDiff->HQVCmeRegs = hqv_cme_regs_409;
339             break;
340         default:
341             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
342                        "VIAVidHWDiffInit: Unhandled ChipSet.\n");
343     }
344 }
345 
346 /*
347  * Old via_overlay code.
348  */
349 typedef struct _YCBCRREC
350 {
351     CARD32 dwY;
352     CARD32 dwCB;
353     CARD32 dwCR;
354 } YCBCRREC;
355 
356 /*
357  * Verify that using V1 bit definitions on V3
358  * is not broken in OverlayGetV1V3Format().
359  */
360 
361 #if V1_COLORSPACE_SIGN != V3_COLORSPACE_SIGN
362 #error "V1_COLORSPACE_SIGN != V3_COLORSPACE_SIGN"
363 #endif
364 #if V1_YUV422 != V3_YUV422
365 #error "V1_YUV422 != V3_YUV422"
366 #endif
367 #if V1_SWAP_HW_HQV != V3_SWAP_HW_HQV
368 #error "V1_SWAP_HW_HQV != V3_SWAP_HW_HQV"
369 #endif
370 #if V1_RGB15 != V3_RGB15
371 #error "V1_RGB15 != V3_RGB15"
372 #endif
373 #if V1_RGB16 != V3_RGB16
374 #error "V1_RGB16 != V3_RGB16"
375 #endif
376 #if V1_RGB32 != V3_RGB32
377 #error "V1_RGB32 != V3_RGB32"
378 #endif
379 
380 static BOOL
viaOverlayGetV1V3Format(VIAPtr pVia,int vport,unsigned long videoFlag,unsigned long * pVidCtl,unsigned long * pHQVCtl)381 viaOverlayGetV1V3Format(VIAPtr pVia, int vport, /* 1 or 3, as in V1 or V3 */
382                         unsigned long videoFlag, unsigned long *pVidCtl,
383                         unsigned long *pHQVCtl)
384 {
385     if (videoFlag & VIDEO_HQV_INUSE) {
386         switch (pVia->swov.SrcFourCC) {
387             case FOURCC_YV12:
388             case FOURCC_I420:
389             case FOURCC_XVMC:
390                 *pHQVCtl |= HQV_YUV420;
391                 break;
392             case FOURCC_YUY2:
393                 *pHQVCtl |= HQV_YUV422;
394                 break;
395             case FOURCC_RV32:
396                 *pVidCtl |= V1_RGB32;
397                 *pHQVCtl |= HQV_RGB32;
398                 break;
399             case FOURCC_RV15:
400                 *pVidCtl |= V1_RGB15;
401                 *pHQVCtl |= HQV_RGB15;
402                 break;
403             case FOURCC_RV16:
404                 *pVidCtl |= V1_RGB16;
405                 *pHQVCtl |= HQV_RGB16;
406                 break;
407             default:
408                 DBG_DD(ErrorF("viaOverlayGetV1V3Format: "
409                               "Invalid FOURCC format (0x%lx).\n",
410                               pVia->swov.SrcFourCC));
411                 return FALSE;
412         }
413         *pVidCtl |= V1_SWAP_HW_HQV;
414         *pHQVCtl |= HQV_SRC_SW | HQV_ENABLE | HQV_SW_FLIP;
415     } else {
416         switch (pVia->swov.SrcFourCC) {
417             case FOURCC_YV12:
418             case FOURCC_I420:
419             case FOURCC_XVMC:
420                 if (vport == 1) {
421                     *pVidCtl |= V1_YCbCr420;
422                 } else {
423                     DBG_DD(ErrorF("viaOverlayGetV1V3Format: "
424                                   "V3 does not support planar YUV.\n"));
425                     return FALSE;
426                 }
427                 break;
428             case FOURCC_YUY2:
429                 *pVidCtl |= V1_YUV422;
430                 break;
431             case FOURCC_RV32:
432             case FOURCC_RV15:
433             case FOURCC_RV16:
434                 ErrorF("viaOverlayGetV1V3Format: "
435                        "Can't display RGB video in this configuration.\n");
436                 return FALSE;
437             default:
438                 DBG_DD(ErrorF("viaOverlayGetV1V3Format: "
439                               "Invalid FOURCC format (0x%lx).\n",
440                               pVia->swov.SrcFourCC));
441                 return FALSE;
442         }
443     }
444     *pVidCtl |= V1_COLORSPACE_SIGN;
445     return TRUE;
446 }
447 
448 static unsigned long
viaOverlayGetSrcStartAddress(VIAPtr pVia,unsigned long videoFlag,LPDDUPDATEOVERLAY pUpdate,unsigned long srcPitch,unsigned long * pHQVoffset)449 viaOverlayGetSrcStartAddress(VIAPtr pVia,
450                              unsigned long videoFlag,
451                              LPDDUPDATEOVERLAY pUpdate,
452                              unsigned long srcPitch,
453                              unsigned long *pHQVoffset)
454 {
455     unsigned long srcWidth =
456             (unsigned long)(pUpdate->SrcRight - pUpdate->SrcLeft);
457     unsigned long dstWidth =
458             (unsigned long)(pUpdate->DstRight - pUpdate->DstLeft);
459     unsigned long srcHeight =
460             (unsigned long)(pUpdate->SrcBottom - pUpdate->SrcTop);
461     unsigned long dstHeight =
462             (unsigned long)(pUpdate->DstBottom - pUpdate->DstTop);
463 
464     unsigned long offset = 0;
465     unsigned long srcTopOffset = 0;
466     unsigned long srcLeftOffset = 0;
467 
468     int n = 1;
469 
470     if ((pUpdate->SrcLeft != 0) || (pUpdate->SrcTop != 0)) {
471         switch (pVia->swov.SrcFourCC) {
472             case FOURCC_RV32:
473                 n = 2;
474             case FOURCC_YUY2:
475             case FOURCC_UYVY:
476             case FOURCC_RV15:
477             case FOURCC_RV16:
478 
479                 if (videoFlag & VIDEO_HQV_INUSE) {
480                     offset = (((pUpdate->SrcTop & ~3) * srcPitch)
481                               + ((pUpdate->SrcLeft << n) & ~31));
482 
483                     if (srcHeight > dstHeight)
484                         srcTopOffset = ((pUpdate->SrcTop & ~3)
485                                         * dstHeight / srcHeight) * srcPitch;
486                     else
487                         srcTopOffset = (pUpdate->SrcTop & ~3) * srcPitch;
488 
489                     if (srcWidth > dstWidth)
490                         srcLeftOffset = (((pUpdate->SrcLeft << n) & ~31)
491                                          * dstWidth / srcWidth);
492                     else
493                         srcLeftOffset = (pUpdate->SrcLeft << n) & ~31;
494                     *pHQVoffset = srcTopOffset + srcLeftOffset;
495                 } else
496                     offset = ((pUpdate->SrcTop * srcPitch)
497                               + ((pUpdate->SrcLeft << n) & ~15));
498                 break;
499 
500             case FOURCC_YV12:
501             case FOURCC_I420:
502             case FOURCC_XVMC:
503 
504                 if (videoFlag & VIDEO_HQV_INUSE)
505                     offset = (((pUpdate->SrcTop & ~3) * (srcPitch << 1))
506                               + ((pUpdate->SrcLeft << 1) & ~31));
507                 else {
508                     offset = ((((pUpdate->SrcTop & ~3) * srcPitch)
509                                + pUpdate->SrcLeft) & ~31);
510                     if (pUpdate->SrcTop > 0)
511                         pVia->swov.overlayRecordV1.dwUVoffset
512                                 = (((((pUpdate->SrcTop & ~3) >> 1) * srcPitch)
513                                     + pUpdate->SrcLeft) & ~31) >> 1;
514                     else
515                         pVia->swov.overlayRecordV1.dwUVoffset = offset >> 1;
516                 }
517                 break;
518 
519             default:
520                 DBG_DD(ErrorF("viaGetSrcStartAddress: "
521                               "Invalid FOURCC format (0x%lx).\n",
522                               pVia->swov.SrcFourCC));
523                 break;
524         }
525     } else {
526         pVia->swov.overlayRecordV1.dwUVoffset = offset = 0;
527     }
528 
529     return offset;
530 }
531 
532 static YCBCRREC
viaOverlayGetYCbCrStartAddress(unsigned long videoFlag,unsigned long startAddr,unsigned long offset,unsigned long UVoffset,unsigned long srcPitch,unsigned long srcHeight)533 viaOverlayGetYCbCrStartAddress(unsigned long videoFlag,
534                                unsigned long startAddr, unsigned long offset,
535                                unsigned long UVoffset, unsigned long srcPitch,
536                                unsigned long srcHeight)
537 {
538     YCBCRREC YCbCr;
539 
540     if (videoFlag & VIDEO_HQV_INUSE) {
541         YCbCr.dwY = startAddr;
542         YCbCr.dwCB = startAddr + srcPitch * srcHeight;
543         YCbCr.dwCR = (startAddr + srcPitch * srcHeight
544                       + srcPitch * (srcHeight >> 2));
545     } else {
546         YCbCr.dwY = startAddr + offset;
547         YCbCr.dwCB = startAddr + srcPitch * srcHeight + UVoffset;
548         YCbCr.dwCR = (startAddr + srcPitch * srcHeight + UVoffset
549                       + srcPitch * (srcHeight >> 2));
550     }
551     return YCbCr;
552 }
553 
554 static unsigned long
viaOverlayHQVCalcZoomWidth(VIAPtr pVia,unsigned long videoFlag,unsigned long srcWidth,unsigned long dstWidth,unsigned long * pZoomCtl,unsigned long * pMiniCtl,unsigned long * pHQVfilterCtl,unsigned long * pHQVminiCtl,unsigned long * pHQVscaleCtlH,unsigned long * pHQVzoomflag)555 viaOverlayHQVCalcZoomWidth(VIAPtr pVia,
556                            unsigned long videoFlag, unsigned long srcWidth,
557                            unsigned long dstWidth, unsigned long *pZoomCtl,
558                            unsigned long *pMiniCtl,
559                            unsigned long *pHQVfilterCtl,
560                            unsigned long *pHQVminiCtl,
561                            unsigned long *pHQVscaleCtlH,
562                            unsigned long *pHQVzoomflag)
563 {
564     unsigned long tmp, sw1, d, falign, mdiv;
565     Bool zoom_ok = TRUE;
566     VIAHWDiff *hwDiff = &pVia->HWDiff;
567 
568     CARD32 HQVfilter[5] = { HQV_H_FILTER_DEFAULT, HQV_H_TAP4_121,
569         HQV_H_TAP4_121, HQV_H_TAP8_12221, HQV_H_TAP8_12221
570     };
571     /* CARD HQVmini[5] = { 0, 0xc00, 0xa00, 0x900, 0x8800 }; */
572 
573     falign = 0;
574     mdiv = 1;
575 
576     if (srcWidth == dstWidth) { /* No zoom */
577         *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
578     } else if (srcWidth < dstWidth) { /* Zoom in */
579 			*pZoomCtl &= 0x0000FFFF;
580 	        tmp = srcWidth * 0x800 / dstWidth;
581 	        *pZoomCtl |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
582 	        *pMiniCtl |= V1_X_INTERPOLY;
583 	        zoom_ok = !(tmp > 0x7ff);
584 
585 	        *pHQVzoomflag = 1;
586 	        *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
587     } else { /* srcWidth > dstWidth - Zoom out */
588 		if (hwDiff->dwNewScaleCtl) {
589             if (srcWidth > (dstWidth << 3)) {
590                 /*<1/8*/
591                 /*FIXME!*/
592                 if (dstWidth <= 32) {
593                     dstWidth = 33;
594                 }
595                 if (srcWidth > (dstWidth << 5)) {
596                     tmp = 1 * 0x1000 / 31;
597                 } else {
598                     tmp = (dstWidth * 0x1000) / srcWidth;
599                 }
600 
601                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
602             } else if (srcWidth == (dstWidth << 3)) {
603                 /*1/8*/
604                 tmp = ((dstWidth - 1) * 0x1000) / srcWidth;
605                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
606             } else if (srcWidth > (dstWidth << 2)) {
607                 /*1/4 -1/8 zoom-out*/
608                 tmp = (srcWidth * 0x1000) / dstWidth;
609                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH;
610             } else {
611                 /*1-1/4 zoom-out*/
612                 /*setting :src/(destination+0.5)*/
613                 tmp = (srcWidth * 0x2000) / ((dstWidth << 1) + 1);
614                 *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_1;
615             }
616 
617             /*rounding to nearest interger*/
618             tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
619             *pHQVscaleCtlH |= (tmp & 0x7fff) | HQV_H_SCALE_ENABLE;
620 		} else {
621 	        /* HQV rounding patch, instead of:
622 	         * //tmp = dstWidth*0x0800 / srcWidth; */
623 	        tmp = dstWidth * 0x800 * 0x400 / srcWidth;
624 	        tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
625 
626 	        *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN;
627 
628 	        *pHQVminiCtl |= HQV_HDEBLOCK_FILTER;
629 		}
630         /* Scale down the picture by a factor mdiv = (1 << d) = {2, 4, 8 or 16} */
631 
632         sw1 = srcWidth;
633         for (d = 1; d < 5; d++) {
634             sw1 >>= 1;
635             if (sw1 <= dstWidth)
636                 break;
637         }
638         if (d == 5) { /* Too small. */
639             d = 4;
640             zoom_ok = FALSE;
641         }
642         mdiv = 1 << d; /* <= {2,4,8,16} */
643         falign = ((mdiv << 1) - 1) & 0xf; /* <= {3,7,15,15} */
644         *pMiniCtl |= V1_X_INTERPOLY;
645         *pMiniCtl |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */
646 
647         *pHQVfilterCtl |= HQVfilter[d];
648 
649 	/* Scale to arbitrary size, on top of previous scaling by (1 << d). */
650 
651 	if (sw1 < dstWidth) {
652 		/* CLE bug
653 		*pZoomCtl = sw1 * 0x0800 / dstWidth;*/
654 		*pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth;
655 		*pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
656 	}
657 
658 	if (videoFlag & VIDEO_1_INUSE) {
659 		pVia->swov.overlayRecordV1.dwFetchAlignment = falign;
660 		pVia->swov.overlayRecordV1.dwminifyH = mdiv;
661 	} else {
662 		pVia->swov.overlayRecordV3.dwFetchAlignment = falign;
663 		pVia->swov.overlayRecordV3.dwminifyH = mdiv;
664 	}
665     }
666     return zoom_ok;
667 }
668 
669 static unsigned long
viaOverlayHQVCalcZoomHeight(VIAPtr pVia,unsigned long srcHeight,unsigned long dstHeight,unsigned long * pZoomCtl,unsigned long * pMiniCtl,unsigned long * pHQVfilterCtl,unsigned long * pHQVminiCtl,unsigned long * pHQVscaleCtlV,unsigned long * pHQVzoomflag)670 viaOverlayHQVCalcZoomHeight(VIAPtr pVia,
671                             unsigned long srcHeight, unsigned long dstHeight,
672                             unsigned long *pZoomCtl, unsigned long *pMiniCtl,
673                             unsigned long *pHQVfilterCtl,
674                             unsigned long *pHQVminiCtl,
675                             unsigned long *pHQVscaleCtlV,
676                             unsigned long *pHQVzoomflag)
677 {
678     unsigned long tmp, sh1, d;
679     Bool zoom_ok = TRUE;
680     VIAHWDiff *hwDiff = &pVia->HWDiff;
681 
682     CARD32 HQVfilter[5] = { HQV_V_TAP4_121, HQV_V_TAP4_121, HQV_V_TAP4_121,
683                             HQV_V_TAP8_12221, HQV_V_TAP8_12221 };
684     /* CARD32 HQVmini[5] = { 0, 0x0c000000, 0x0a000000, 0x09000000, 0x08800000 }; */
685 
686     /*if (pVia->pBIOSInfo->scaleY)
687      * {
688      * dstHeight = dstHeight + 1;
689      * } */
690 
691     if (srcHeight == dstHeight) { /* No zoom */
692         *pHQVfilterCtl |= HQV_V_TAP4_121;
693     } else if (srcHeight < dstHeight) { /* Zoom in */
694 		*pZoomCtl &= 0xFFFF0000;
695 	    tmp = srcHeight * 0x400 / dstHeight - 1;
696 	    *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
697 	    *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY);
698 
699 	    *pHQVzoomflag = 1;
700 	    *pHQVfilterCtl |= HQV_V_TAP4_121;
701     } else { /* srcHeight > dstHeight - Zoom out */
702 	if (hwDiff->dwNewScaleCtl) {
703             /*setting :src/(destination+0.5)*/
704             tmp = srcHeight * 0x2000 / ((dstHeight << 1) + 1);
705             tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
706             if ((tmp & 0x1ffff) == 0) {
707                 tmp = 0x1ffff;
708             }
709 
710             *pHQVscaleCtlV = (tmp & 0x1ffff) | HQV_V_SCALE_ENABLE| HQV_V_SCALE_DOWN;
711 	} else {
712 	        /* HQV rounding patch, instead of:
713 	         * //tmp = dstHeight*0x0800 / srcHeight; */
714 	        tmp = dstHeight * 0x0800 * 0x400 / srcHeight;
715 	        tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
716 	        *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE
717 	                         | HQV_V_MINIFY_DOWN);
718 
719 	        /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */
720 	        sh1 = srcHeight;
721 	        for (d = 1; d < 5; d++) {
722 	            sh1 >>= 1;
723 	            if (sh1 <= dstHeight)
724 	                break;
725 	        }
726 	        if (d == 5) { /* Too small. */
727 	            d = 4;
728 	            zoom_ok = FALSE;
729 	        }
730 
731 	        *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
732 
733 	        *pHQVfilterCtl |= HQVfilter[d];
734 	        /* *pHQVminiCtl |= HQVmini[d]; */
735 	        *pHQVminiCtl |= HQV_VDEBLOCK_FILTER;
736 
737 	        /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
738 
739 	        if (sh1 < dstHeight) {
740 	            tmp = sh1 * 0x0400 / dstHeight;
741 	            *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
742 	            *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
743 	        }
744 	}
745     }
746     return zoom_ok;
747 }
748 
749 static unsigned long
viaOverlayGetFetch(VIAPtr pVia,unsigned long videoFlag,unsigned long srcWidth,unsigned long dstWidth,unsigned long oriSrcWidth,unsigned long * pHQVsrcFetch)750 viaOverlayGetFetch(VIAPtr pVia, unsigned long videoFlag,
751                    unsigned long srcWidth, unsigned long dstWidth,
752                    unsigned long oriSrcWidth, unsigned long *pHQVsrcFetch)
753 {
754     unsigned long fetch = 0;
755     int n = 2; /* 2^n bytes per pixel. */
756 
757     switch (pVia->swov.SrcFourCC) {
758         case FOURCC_YV12:
759         case FOURCC_I420:
760         case FOURCC_XVMC:
761             n = 0; /* 2^n = 1 byte per pixel (Y channel in planar YUV) */
762             break;
763         case FOURCC_UYVY:
764         case FOURCC_YUY2:
765         case FOURCC_RV15:
766         case FOURCC_RV16:
767             n = 1; /* 2^n = 2 bytes per pixel (packed YUV) */
768             break;
769         case FOURCC_RV32:
770             n = 2;
771             break;
772         default:
773             DBG_DD(ErrorF("viaOverlayGetFetch: "
774                           "Invalid FOURCC format (0x%lx).\n",
775                           pVia->swov.SrcFourCC));
776             break;
777     }
778 
779     if (videoFlag & VIDEO_HQV_INUSE) {
780         *pHQVsrcFetch = oriSrcWidth << n;
781         if (n == 0) {
782             /* Assume n == 0 <=> Planar YUV.
783              * The V1/V3 pixelformat is always packed YUV when we use HQV,
784              * so we switch from 8-bit to 16-bit pixels here.
785              */
786             n = 1;
787         }
788         if (dstWidth >= srcWidth)
789             fetch = (ALIGN_TO(srcWidth << n, 16) >> 4) + 1;
790         else
791             fetch = (ALIGN_TO(dstWidth << n, 16) >> 4) + 1;
792     } else {
793         if (n == 0)
794             fetch = (ALIGN_TO(srcWidth, 32) >> 4);
795         else
796             fetch = (ALIGN_TO(srcWidth << n, 16) >> 4) + 1;
797     }
798 
799     /* Fix planar mode problem. */
800     if (fetch < 4)
801         fetch = 4;
802 
803     return fetch;
804 }
805 
806 /*
807  * This function uses quadratic mapping to adjust the midpoint of the scaling.
808  */
809 static float
rangeEqualize(float inLow,float inHigh,float outLow,float outHigh,float outMid,float inValue)810 rangeEqualize(float inLow, float inHigh, float outLow, float outHigh,
811               float outMid, float inValue)
812 {
813     float inRange = inHigh - inLow,
814           outRange = outHigh - outLow,
815           normIn = ((inValue - inLow) / inRange) * 2. - 1.,
816           delta = outMid - outRange * 0.5 - outLow;
817     return ((inValue - inLow) * outRange / inRange + outLow
818             + (1. - normIn * normIn) * delta);
819 }
820 
821 static unsigned
vPackFloat(float val,float hiLimit,float loLimit,float mult,int shift,Bool doSign)822 vPackFloat(float val, float hiLimit, float loLimit, float mult, int shift,
823            Bool doSign)
824 {
825     unsigned packed, mask, sign;
826 
827     val = (val > hiLimit) ? hiLimit : val;
828     val = (val < loLimit) ? loLimit : val;
829     sign = (val < 0) ? 1 : 0;
830     val = (sign) ? -val : val;
831     packed = ((unsigned)(val * mult + 1.)) >> 1;
832     mask = (1 << shift) - 1;
833     return (((packed >= mask) ? mask : packed)
834             | ((doSign) ? (sign << shift) : 0));
835 
836 }
837 
838 typedef float colorCoeff[5];
839 static colorCoeff colorCTable[] = {
840     {1.1875, 1.625, 0.875, 0.375, 2.0},
841     {1.164, 1.596, 0.54, 0.45, 2.2}
842 };
843 
844 /*
845  * This function is a partial rewrite of the overlay.c file of the original VIA
846  * drivers, which was extremely nasty and difficult to follow. Coefficients for
847  * new chipset models should be added in the table above and, if needed,
848  * implemented in the model switch below.
849  */
850 static void
viaCalculateVideoColor(VIAPtr pVia,int hue,int saturation,int brightness,int contrast,Bool reset,CARD32 * col1,CARD32 * col2)851 viaCalculateVideoColor(VIAPtr pVia, int hue, int saturation,
852                        int brightness, int contrast, Bool reset,
853                        CARD32 * col1, CARD32 * col2)
854 {
855     float fA, fB1, fC1, fD, fB2, fC2, fB3, fC3;
856     float fPI, fContrast, fSaturation, fHue, fBrightness;
857     const float *mCoeff;
858     unsigned long dwA, dwB1, dwC1, dwD, dwB2, dwC2, dwB3, dwC3, dwS;
859     unsigned long dwD_Int, dwD_Dec;
860     int intD;
861     int model;
862 
863     fPI = (float)(M_PI / 180.);
864 
865     if (reset) {
866         saturation = 10000;
867         brightness = 5000;
868         contrast = 10000;
869     }
870 
871     switch (pVia->ChipId) {
872         case PCI_CHIP_VT3205:
873         case PCI_CHIP_VT3204:
874         case PCI_CHIP_VT3259:
875         case PCI_CHIP_VT3314:
876         case PCI_CHIP_VT3336:
877         case PCI_CHIP_VT3364:
878         case PCI_CHIP_VT3324:
879         case PCI_CHIP_VT3327:
880         case PCI_CHIP_VT3353:
881         case PCI_CHIP_VT3409:
882         case PCI_CHIP_VT3410:
883             model = 0;
884             break;
885         case PCI_CHIP_CLE3122:
886             model = (CLE266_REV_IS_CX(pVia->ChipRev) ? 0 : 1);
887             break;
888         default:
889             ErrorF("Unknown Chip ID\n");
890             model = 0;
891     }
892 
893     switch (model) {
894         case 0:
895             fBrightness = rangeEqualize(0., 10000., -128., 128., -16.,
896                                         (float)brightness);
897             fContrast = rangeEqualize(0., 20000., 0., 1.6645, 1.0,
898                                       (float)contrast);
899             fSaturation = rangeEqualize(0., 20000, 0., 2., 1.,
900                                         (float)saturation);
901             break;
902         default:
903             fBrightness = rangeEqualize(0., 10000., -128., 128., -12.,
904                                         (float)brightness);
905             fContrast = rangeEqualize(0., 20000., 0., 1.6645, 1.1,
906                                       (float)contrast);
907             fSaturation = rangeEqualize(0., 20000, 0., 2., 1.15,
908                                         (float)saturation);
909             break;
910     }
911     fHue = (float)hue;
912 
913     mCoeff = colorCTable[model];
914 
915     fA = (float)(mCoeff[0] * fContrast);
916     fB1 = (float)(-mCoeff[1] * fContrast * fSaturation * sin(fHue * fPI));
917     fC1 = (float)(mCoeff[1] * fContrast * fSaturation * cos(fHue * fPI));
918     fD = (float)(mCoeff[0] * (fBrightness));
919     fB2 = (float)((mCoeff[2] * sin(fHue * fPI) - mCoeff[3] * cos(fHue * fPI))
920                   * fContrast * fSaturation);
921     fC2 = (float)(-(mCoeff[2] * cos(fHue * fPI) + mCoeff[3] * sin(fHue * fPI))
922                   * fContrast * fSaturation);
923     fB3 = (float)(mCoeff[4] * fContrast * fSaturation * cos(fHue * fPI));
924     fC3 = (float)(mCoeff[4] * fContrast * fSaturation * sin(fHue * fPI));
925 
926     switch (model) {
927         case 0:
928             dwA = vPackFloat(fA, 1.9375, 0., 32., 5, 0);
929             dwB1 = vPackFloat(fB1, 2.125, -2.125, 16., 5, 1);
930             dwC1 = vPackFloat(fC1, 2.125, -2.125, 16., 5, 1);
931 
932             if (fD >= 0) {
933                 intD = (int)fD;
934                 if (intD > 127)
935                     intD = 127;
936                 dwD_Int = ((unsigned long)intD) & 0xff;
937                 dwD = ((unsigned long)(fD * 16 + 1)) >> 1;
938                 dwD_Dec = dwD & 0x7;
939             } else {
940                 intD = (int)fD;
941                 if (intD < -128)
942                     intD = -128;
943                 intD = intD + 256;
944                 dwD_Int = ((unsigned long)intD) & 0xff;
945                 fD = -fD;
946                 dwD = ((unsigned long)(fD * 16 + 1)) >> 1;
947                 dwD_Dec = dwD & 0x7;
948             }
949 
950             dwB2 = vPackFloat(fB2, 1.875, -1.875, 16, 4, 1);
951             dwC2 = vPackFloat(fC2, 1.875, -1.875, 16, 4, 1);
952             dwB3 = vPackFloat(fB3, 3.875, -3.875, 16, 5, 1);
953             dwC3 = vPackFloat(fC3, 3.875, -3.875, 16, 5, 1);
954             *col1 = (dwA << 24) | (dwB1 << 16) | (dwC1 << 8) | dwD_Int;
955             *col2 = (dwD_Dec << 29 | dwB2 << 24) | (dwC2 << 16) | (dwB3 << 8)
956                     | (dwC3);
957             break;
958 
959         default:
960             dwA = vPackFloat(fA, 1.9375, -0., 32, 5, 0);
961             dwB1 = vPackFloat(fB1, 0.75, -0.75, 8., 2, 1);
962             dwC1 = vPackFloat(fC1, 2.875, 1., 16., 5, 0);
963 
964             if (fD >= 127)
965                 fD = 127;
966 
967             if (fD <= -128)
968                 fD = -128;
969 
970             if (fD >= 0) {
971                 dwS = 0;
972             } else {
973                 dwS = 1;
974                 fD = fD + 128;
975             }
976 
977             dwD = ((unsigned long)(fD * 2 + 1)) >> 1;
978             if (dwD >= 0x7f) {
979                 dwD = 0x7f | (dwS << 7);
980             } else {
981                 dwD = (dwD & 0x7f) | (dwS << 7);
982             }
983 
984             dwB2 = vPackFloat(fB2, 0., -0.875, 16., 3, 0);
985             dwC2 = vPackFloat(fC2, 0., -1.875, 16., 4, 0);
986             dwB3 = vPackFloat(fB3, 3.75, 0., 8., 4, 0);
987             dwC3 = vPackFloat(fC3, 1.25, -1.25, 8., 3, 1);
988             *col1 = (dwA << 24) | (dwB1 << 18) | (dwC1 << 9) | dwD;
989             *col2 = (dwB2 << 25) | (dwC2 << 17) | (dwB3 << 10) | (dwC3 << 2);
990             break;
991     }
992 }
993 
994 /*
995  *
996  *
997  */
998 void
viaSetColorSpace(VIAPtr pVia,int hue,int saturation,int brightness,int contrast,Bool reset)999 viaSetColorSpace(VIAPtr pVia, int hue, int saturation, int brightness,
1000                  int contrast, Bool reset)
1001 {
1002     CARD32 col1, col2;
1003 
1004     viaCalculateVideoColor(pVia, hue, saturation, brightness, contrast, reset,
1005                            &col1, &col2);
1006     switch (pVia->ChipId) {
1007         case PCI_CHIP_VT3205:
1008         case PCI_CHIP_VT3204:
1009         case PCI_CHIP_VT3314:
1010             VIASETREG(V3_ColorSpaceReg_1, col1);
1011             VIASETREG(V3_ColorSpaceReg_2, col2);
1012             DBG_DD(ErrorF("000002C4 %08lx\n", col1));
1013             DBG_DD(ErrorF("000002C8 %08lx\n", col2));
1014         case PCI_CHIP_VT3259:
1015         case PCI_CHIP_VT3327:
1016         case PCI_CHIP_VT3336:
1017         case PCI_CHIP_VT3324:
1018         case PCI_CHIP_VT3364:
1019         case PCI_CHIP_VT3353:
1020         case PCI_CHIP_VT3409:
1021         case PCI_CHIP_VT3410:
1022         case PCI_CHIP_CLE3122:
1023             VIASETREG(V1_ColorSpaceReg_1, col1);
1024             VIASETREG(V1_ColorSpaceReg_2, col2);
1025             DBG_DD(ErrorF("00000288 %08lx\n", col2));
1026             DBG_DD(ErrorF("00000284 %08lx\n", col1));
1027             break;
1028         default:
1029             DBG_DD(ErrorF("Unknown DeviceID\n"));
1030             break;
1031     }
1032 }
1033 
1034 static unsigned long
ViaInitVideoStatusFlag(VIAPtr pVia)1035 ViaInitVideoStatusFlag(VIAPtr pVia)
1036 {
1037     switch (pVia->ChipId) {
1038         case PCI_CHIP_VT3205:
1039         case PCI_CHIP_VT3204:
1040         case PCI_CHIP_VT3314:
1041             return VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_3_INUSE;
1042         case PCI_CHIP_VT3259:
1043         case PCI_CHIP_VT3327:
1044         case PCI_CHIP_VT3336:
1045         case PCI_CHIP_VT3324:
1046         case PCI_CHIP_VT3364:
1047         case PCI_CHIP_VT3353:
1048         case PCI_CHIP_VT3409:
1049         case PCI_CHIP_VT3410:
1050             return (VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_1_INUSE
1051                     | VIDEO_ACTIVE | VIDEO_SHOW);
1052         case PCI_CHIP_CLE3122:
1053             return VIDEO_HQV_INUSE | SW_USE_HQV | VIDEO_1_INUSE;
1054         default:
1055             DBG_DD(ErrorF("Unknown DeviceID\n"));
1056             break;
1057     }
1058     return 0;
1059 }
1060 
1061 static unsigned long
ViaSetVidCtl(VIAPtr pVia,unsigned int videoFlag)1062 ViaSetVidCtl(VIAPtr pVia, unsigned int videoFlag)
1063 {
1064     if (videoFlag & VIDEO_1_INUSE) {
1065         /*=* Modify for C1 FIFO *=*/
1066         /* WARNING: not checking Chipset! */
1067         if (CLE266_REV_IS_CX(pVia->ChipRev))
1068             return V1_ENABLE | V1_EXPIRE_NUM_F;
1069         else {
1070             /* Overlay source format for V1 */
1071             if (pVia->swov.gdwUseExtendedFIFO)
1072                 return V1_ENABLE | V1_EXPIRE_NUM_A | V1_FIFO_EXTENDED;
1073             else
1074                 return V1_ENABLE | V1_EXPIRE_NUM;
1075         }
1076     } else {
1077         switch (pVia->ChipId) {
1078             case PCI_CHIP_VT3205:
1079             case PCI_CHIP_VT3204:
1080             case PCI_CHIP_VT3259:
1081             case PCI_CHIP_VT3314:
1082                 return V3_ENABLE | V3_EXPIRE_NUM_3205;
1083             case PCI_CHIP_VT3327:
1084             case PCI_CHIP_VT3336:
1085             case PCI_CHIP_VT3324:
1086             case PCI_CHIP_VT3364:
1087             case PCI_CHIP_VT3353:
1088                 return V3_ENABLE | VIDEO_EXPIRE_NUM_VT3336;
1089             case PCI_CHIP_VT3409:
1090             case PCI_CHIP_VT3410:
1091                 return V3_ENABLE | VIDEO_EXPIRE_NUM_VT3409;
1092             case PCI_CHIP_CLE3122:
1093                 if (CLE266_REV_IS_CX(pVia->ChipRev))
1094                     return V3_ENABLE | V3_EXPIRE_NUM_F;
1095                 else
1096                     return V3_ENABLE | V3_EXPIRE_NUM;
1097             default:
1098                 DBG_DD(ErrorF("Unknown DeviceID\n"));
1099                 break;
1100         }
1101     }
1102     return 0;
1103 }
1104 
1105 /*
1106  * Fill the buffer with 0x8000 (YUV2 black).
1107  */
1108 static void
ViaYUVFillBlack(VIAPtr pVia,void * buf,int num)1109 ViaYUVFillBlack(VIAPtr pVia, void *buf, int num)
1110 {
1111     CARD16 *ptr = (CARD16 *) buf;
1112 
1113     while (num-- > 0)
1114 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
1115         *ptr++ = 0x0080;
1116 #else
1117         *ptr++ = 0x8000;
1118 #endif
1119 }
1120 
1121 /*
1122  * Add an HQV surface to an existing FOURCC surface.
1123  * numbuf: number of buffers, 1, 2 or 3
1124  * fourcc: FOURCC code of the current (already existing) surface
1125  */
1126 static long
AddHQVSurface(ScrnInfoPtr pScrn,unsigned int numbuf,CARD32 fourcc)1127 AddHQVSurface(ScrnInfoPtr pScrn, unsigned int numbuf, CARD32 fourcc)
1128 {
1129     unsigned int i, width, height, pitch, fbsize, addr;
1130     BOOL isplanar;
1131     void *buf;
1132 
1133     VIAPtr pVia = VIAPTR(pScrn);
1134     CARD32 AddrReg[3] = { HQV_DST_STARTADDR0, HQV_DST_STARTADDR1,
1135             HQV_DST_STARTADDR2 };
1136     unsigned long proReg = 0;
1137 
1138     if (pVia->ChipId == PCI_CHIP_VT3259 &&
1139         !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
1140         proReg = PRO_HQV1_OFFSET;
1141 
1142     isplanar = ((fourcc == FOURCC_YV12) || (fourcc == FOURCC_I420) ||
1143                 (fourcc == FOURCC_XVMC));
1144 
1145     width = pVia->swov.SWDevice.gdwSWSrcWidth;
1146     height = pVia->swov.SWDevice.gdwSWSrcHeight;
1147     pitch = pVia->swov.SWDevice.dwPitch;
1148     fbsize = pitch * height * (isplanar ? 2 : 1);
1149 
1150     pVia->swov.HQVMem = drm_bo_alloc(pScrn, fbsize * numbuf, 1, TTM_PL_FLAG_VRAM);
1151     if (!pVia->swov.HQVMem)
1152         return BadAlloc;
1153     addr = pVia->swov.HQVMem->offset;
1154     buf = drm_bo_map(pScrn, pVia->swov.HQVMem);
1155 
1156     ViaYUVFillBlack(pVia, buf, fbsize);
1157 
1158     for (i = 0; i < numbuf; i++) {
1159         pVia->swov.overlayRecordV1.dwHQVAddr[i] = addr;
1160         VIASETREG(AddrReg[i] + proReg, addr);
1161         addr += fbsize;
1162     }
1163     drm_bo_unmap(pScrn, pVia->swov.HQVMem);
1164     return Success;
1165 }
1166 
1167 /*
1168  * Create a FOURCC surface.
1169  * doalloc: set true to actually allocate memory for the framebuffers
1170  */
1171 static long
CreateSurface(ScrnInfoPtr pScrn,CARD32 FourCC,CARD16 Width,CARD16 Height,BOOL doalloc)1172 CreateSurface(ScrnInfoPtr pScrn, CARD32 FourCC, CARD16 Width,
1173               CARD16 Height, BOOL doalloc)
1174 {
1175     VIAPtr pVia = VIAPTR(pScrn);
1176     unsigned long pitch, fbsize, addr;
1177     BOOL isplanar;
1178     void *buf;
1179 
1180     pVia->swov.SrcFourCC = FourCC;
1181     pVia->swov.gdwVideoFlagSW = ViaInitVideoStatusFlag(pVia);
1182 
1183     isplanar = FALSE;
1184     switch (FourCC) {
1185         case FOURCC_YV12:
1186         case FOURCC_I420:
1187         case FOURCC_XVMC:
1188             isplanar = TRUE;
1189             pitch = ALIGN_TO(Width, 32);
1190             fbsize = pitch * Height * 1.5;
1191             break;
1192         case FOURCC_RV32:
1193             pitch = ALIGN_TO(Width << 2, 32);
1194             fbsize = pitch * Height;
1195             break;
1196         default:
1197             pitch = ALIGN_TO(Width << 1, 32);
1198             fbsize = pitch * Height;
1199             break;
1200     }
1201 
1202     if (doalloc) {
1203         pVia->swov.SWfbMem = drm_bo_alloc(pScrn, fbsize * 2, 1, TTM_PL_FLAG_VRAM);
1204         if (!pVia->swov.SWfbMem)
1205             return BadAlloc;
1206         addr = pVia->swov.SWfbMem->offset;
1207         buf = drm_bo_map(pScrn, pVia->swov.SWfbMem);
1208 
1209         ViaYUVFillBlack(pVia, buf, fbsize);
1210 
1211         pVia->swov.SWDevice.dwSWPhysicalAddr[0] = addr;
1212         pVia->swov.SWDevice.dwSWPhysicalAddr[1] = addr + fbsize;
1213         pVia->swov.SWDevice.lpSWOverlaySurface[0] = buf;
1214         pVia->swov.SWDevice.lpSWOverlaySurface[1] = buf + fbsize;
1215 
1216         if (isplanar) {
1217             pVia->swov.SWDevice.dwSWCrPhysicalAddr[0] =
1218                     pVia->swov.SWDevice.dwSWPhysicalAddr[0] +
1219                     (pitch * Height);
1220             pVia->swov.SWDevice.dwSWCrPhysicalAddr[1] =
1221                     pVia->swov.SWDevice.dwSWPhysicalAddr[1] +
1222                     (pitch * Height);
1223             pVia->swov.SWDevice.dwSWCbPhysicalAddr[0] =
1224                     pVia->swov.SWDevice.dwSWCrPhysicalAddr[0] +
1225                     ((pitch >> 1) * (Height >> 1));
1226             pVia->swov.SWDevice.dwSWCbPhysicalAddr[1] =
1227                     pVia->swov.SWDevice.dwSWCrPhysicalAddr[1] +
1228                     ((pitch >> 1) * (Height >> 1));
1229         }
1230     }
1231 
1232     pVia->swov.SWDevice.gdwSWSrcWidth = Width;
1233     pVia->swov.SWDevice.gdwSWSrcHeight = Height;
1234     pVia->swov.SWDevice.dwPitch = pitch;
1235 
1236     pVia->swov.overlayRecordV1.dwV1OriWidth = Width;
1237     pVia->swov.overlayRecordV1.dwV1OriHeight = Height;
1238     pVia->swov.overlayRecordV1.dwV1OriPitch = pitch;
1239 
1240     return Success;
1241 }
1242 
1243 /*
1244  *
1245  */
1246 int
ViaSwovSurfaceCreate(ScrnInfoPtr pScrn,viaPortPrivPtr pPriv,CARD32 FourCC,CARD16 Width,CARD16 Height)1247 ViaSwovSurfaceCreate(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv,
1248                      CARD32 FourCC, CARD16 Width, CARD16 Height)
1249 {
1250     VIAPtr pVia = VIAPTR(pScrn);
1251     unsigned long retCode = Success;
1252     int numbuf = pVia->HWDiff.dwThreeHQVBuffer ? 3 : 2;
1253 
1254     DBG_DD(ErrorF("ViaSwovSurfaceCreate: FourCC =0x%08lx\n", FourCC));
1255 
1256     if ((pVia->VideoStatus & VIDEO_SWOV_SURFACE_CREATED)
1257         && (FourCC == pPriv->FourCC))
1258         return Success;
1259 
1260     pPriv->FourCC = FourCC;
1261     switch (FourCC) {
1262         case FOURCC_YUY2:
1263         case FOURCC_RV15:
1264         case FOURCC_RV16:
1265         case FOURCC_RV32:
1266             retCode = CreateSurface(pScrn, FourCC, Width, Height, TRUE);
1267             if (retCode != Success)
1268                 break;
1269             if ((pVia->swov.gdwVideoFlagSW & SW_USE_HQV))
1270                 retCode = AddHQVSurface(pScrn, numbuf, FourCC);
1271             break;
1272 
1273         case FOURCC_HQVSW:
1274             retCode = AddHQVSurface(pScrn, numbuf, FOURCC_YUY2);
1275             break;
1276 
1277         case FOURCC_YV12:
1278         case FOURCC_I420:
1279             retCode = CreateSurface(pScrn, FourCC, Width, Height, TRUE);
1280             if (retCode == Success)
1281                 retCode = AddHQVSurface(pScrn, numbuf, FourCC);
1282             break;
1283 
1284         case FOURCC_XVMC:
1285             retCode = CreateSurface(pScrn, FourCC, Width, Height, FALSE);
1286             if (retCode == Success)
1287                 retCode = AddHQVSurface(pScrn, numbuf, FOURCC_XVMC);
1288             break;
1289 
1290         default:
1291             break;
1292     }
1293 
1294     if (retCode == Success) {
1295         DBG_DD(ErrorF(" lpSWOverlaySurface[0]: %p\n",
1296                       pVia->swov.SWDevice.lpSWOverlaySurface[0]));
1297         DBG_DD(ErrorF(" lpSWOverlaySurface[1]: %p\n",
1298                       pVia->swov.SWDevice.lpSWOverlaySurface[1]));
1299 
1300         pVia->VideoStatus |= VIDEO_SWOV_SURFACE_CREATED | VIDEO_SWOV_ON;
1301     }
1302     return retCode;
1303 }
1304 
1305 /*
1306  *  Destroy Surface
1307  */
1308 void
ViaSwovSurfaceDestroy(ScrnInfoPtr pScrn,viaPortPrivPtr pPriv)1309 ViaSwovSurfaceDestroy(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv)
1310 {
1311     VIAPtr pVia = VIAPTR(pScrn);
1312 
1313     DBG_DD(ErrorF("ViaSwovSurfaceDestroy: FourCC =0x%08lx\n", pPriv->FourCC));
1314 
1315     if (pVia->VideoStatus & VIDEO_SWOV_SURFACE_CREATED) {
1316         DBG_DD(ErrorF("ViaSwovSurfaceDestroy: VideoStatus =0x%08lx\n",
1317                       pVia->VideoStatus));
1318 
1319         switch (pPriv->FourCC) {
1320             case FOURCC_YUY2:
1321             case FOURCC_RV16:
1322             case FOURCC_RV32:
1323             case FOURCC_RV15:
1324                 pVia->swov.SrcFourCC = 0;
1325 
1326                 drm_bo_unmap(pScrn, pVia->swov.SWfbMem);
1327                 drm_bo_free(pScrn, pVia->swov.SWfbMem);
1328                 if ((pVia->swov.gdwVideoFlagSW & SW_USE_HQV)) {
1329                     drm_bo_unmap(pScrn, pVia->swov.HQVMem);
1330                     drm_bo_free(pScrn, pVia->swov.HQVMem);
1331                 }
1332                 pVia->swov.gdwVideoFlagSW = 0;
1333                 break;
1334 
1335             case FOURCC_HQVSW:
1336                 drm_bo_free(pScrn, pVia->swov.HQVMem);
1337                 pVia->swov.gdwVideoFlagSW = 0;
1338                 break;
1339 
1340             case FOURCC_YV12:
1341             case FOURCC_I420:
1342                 drm_bo_unmap(pScrn, pVia->swov.SWfbMem);
1343                 drm_bo_free(pScrn, pVia->swov.SWfbMem);
1344             case FOURCC_XVMC:
1345                 pVia->swov.SrcFourCC = 0;
1346 
1347                 drm_bo_free(pScrn, pVia->swov.HQVMem);
1348                 pVia->swov.gdwVideoFlagSW = 0;
1349                 break;
1350         }
1351 
1352         pPriv->FourCC = 0;
1353         pVia->VideoStatus &= ~VIDEO_SWOV_SURFACE_CREATED;
1354 
1355     } else
1356         DBG_DD(ErrorF("ViaSwovSurfaceDestroy: No SW Surface Destroyed, "
1357                       "VideoStatus =0x%08lx\n", pVia->VideoStatus));
1358 }
1359 
1360 static void
SetFIFO_V1(VIAPtr pVia,CARD8 depth,CARD8 prethreshold,CARD8 threshold)1361 SetFIFO_V1(VIAPtr pVia, CARD8 depth, CARD8 prethreshold, CARD8 threshold)
1362 {
1363     SaveVideoRegister(pVia, V_FIFO_CONTROL,
1364                       ((depth - 1) & 0x7f) |
1365                       ((prethreshold & 0x7f) << 24) |
1366                       ((threshold & 0x7f) << 8));
1367 }
1368 
1369 static void
SetFIFO_V3(VIAPtr pVia,CARD8 depth,CARD8 prethreshold,CARD8 threshold)1370 SetFIFO_V3(VIAPtr pVia, CARD8 depth, CARD8 prethreshold, CARD8 threshold)
1371 {
1372     switch (pVia->ChipId) {
1373         case PCI_CHIP_VT3314:
1374         case PCI_CHIP_VT3324:
1375         case PCI_CHIP_VT3327:
1376         case PCI_CHIP_VT3353:
1377         case PCI_CHIP_VT3409:
1378         case PCI_CHIP_VT3410:
1379             SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
1380                               (VIAGETREG(ALPHA_V3_FIFO_CONTROL) & ALPHA_FIFO_MASK)
1381                                | ((depth - 1) & 0xff) | ((threshold & 0xff) << 8));
1382             SaveVideoRegister(pVia, ALPHA_V3_PREFIFO_CONTROL,
1383                               (VIAGETREG(ALPHA_V3_PREFIFO_CONTROL)
1384                               & ~V3_FIFO_MASK_3314) | (prethreshold & 0xff));
1385             break;
1386         default :
1387             SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
1388                               (VIAGETREG(ALPHA_V3_FIFO_CONTROL) & ALPHA_FIFO_MASK)
1389                               | ((depth - 1) & 0xff) | ((threshold & 0xff) << 8));
1390             SaveVideoRegister(pVia, ALPHA_V3_PREFIFO_CONTROL,
1391                               (VIAGETREG(ALPHA_V3_PREFIFO_CONTROL) & ~V3_FIFO_MASK)
1392                               | (prethreshold & 0x7f));
1393             break;
1394     }
1395 }
1396 
1397 static void
SetFIFO_64or32(VIAPtr pVia)1398 SetFIFO_64or32(VIAPtr pVia)
1399 {
1400     /*=* Modify for C1 FIFO *=*/
1401     /* WARNING: not checking Chipset! */
1402     if (CLE266_REV_IS_CX(pVia->ChipRev))
1403         SetFIFO_V1(pVia, 64, 56, 56);
1404     else
1405         SetFIFO_V1(pVia, 32, 29, 16);
1406 }
1407 
1408 static void
SetFIFO_64or16(VIAPtr pVia)1409 SetFIFO_64or16(VIAPtr pVia)
1410 {
1411     /*=* Modify for C1 FIFO *=*/
1412     /* WARNING: not checking Chipset! */
1413     if (CLE266_REV_IS_CX(pVia->ChipRev))
1414         SetFIFO_V1(pVia, 64, 56, 56);
1415     else
1416         SetFIFO_V1(pVia, 16, 12, 8);
1417 }
1418 
1419 static void
SetFIFO_64or48or32(VIAPtr pVia)1420 SetFIFO_64or48or32(VIAPtr pVia)
1421 {
1422     /*=* Modify for C1 FIFO *=*/
1423     /* WARNING: not checking Chipset! */
1424     if (CLE266_REV_IS_CX(pVia->ChipRev))
1425         SetFIFO_V1(pVia, 64, 56, 56);
1426     else {
1427         if (pVia->swov.gdwUseExtendedFIFO)
1428             SetFIFO_V1(pVia, 48, 40, 40);
1429         else
1430             SetFIFO_V1(pVia, 32, 29, 16);
1431     }
1432 }
1433 
1434 static void
SetFIFO_V3_64or32or32(VIAPtr pVia)1435 SetFIFO_V3_64or32or32(VIAPtr pVia)
1436 {
1437     switch (pVia->ChipId) {
1438         case PCI_CHIP_VT3327:
1439         case PCI_CHIP_VT3336:
1440         case PCI_CHIP_VT3324:
1441         case PCI_CHIP_VT3364:
1442         case PCI_CHIP_VT3353:
1443         case PCI_CHIP_VT3409:
1444         case PCI_CHIP_VT3410:
1445             SetFIFO_V3(pVia, 225, 200, 250);
1446             break;
1447         case PCI_CHIP_VT3204:
1448             SetFIFO_V3(pVia, 100, 89, 89);
1449             break;
1450         case PCI_CHIP_VT3314:
1451             SetFIFO_V3(pVia, 64, 61, 61);
1452             break;
1453         case PCI_CHIP_VT3205:
1454         case PCI_CHIP_VT3259:
1455             SetFIFO_V3(pVia, 32, 29, 29);
1456             break;
1457         case PCI_CHIP_CLE3122:
1458             if (CLE266_REV_IS_CX(pVia->ChipRev))
1459                 SetFIFO_V3(pVia, 64, 56, 56);
1460             else
1461                 SetFIFO_V3(pVia, 32, 16, 16);
1462             break;
1463         default:
1464             break;
1465     }
1466 }
1467 
1468 static void
SetFIFO_V3_64or32or16(VIAPtr pVia)1469 SetFIFO_V3_64or32or16(VIAPtr pVia)
1470 {
1471     switch (pVia->ChipId) {
1472         case PCI_CHIP_VT3327:
1473         case PCI_CHIP_VT3336:
1474         case PCI_CHIP_VT3324:
1475         case PCI_CHIP_VT3364:
1476         case PCI_CHIP_VT3353:
1477         case PCI_CHIP_VT3409:
1478         case PCI_CHIP_VT3410:
1479             SetFIFO_V3(pVia, 225, 200, 250);
1480             break;
1481         case PCI_CHIP_VT3204:
1482             SetFIFO_V3(pVia, 100, 89, 89);
1483             break;
1484         case PCI_CHIP_VT3314:
1485             SetFIFO_V3(pVia, 64, 61, 61);
1486             break;
1487         case PCI_CHIP_VT3205:
1488         case PCI_CHIP_VT3259:
1489             SetFIFO_V3(pVia, 32, 29, 29);
1490             break;
1491 
1492         case PCI_CHIP_CLE3122:
1493             if (CLE266_REV_IS_CX(pVia->ChipRev))
1494                 SetFIFO_V3(pVia, 64, 56, 56);
1495             else
1496                 SetFIFO_V3(pVia, 16, 16, 8);
1497             break;
1498 
1499         default:
1500             break;
1501     }
1502 }
1503 
1504 static void
SetupFIFOs(VIAPtr pVia,unsigned long videoFlag,unsigned long miniCtl,unsigned long srcWidth)1505 SetupFIFOs(VIAPtr pVia, unsigned long videoFlag,
1506            unsigned long miniCtl, unsigned long srcWidth)
1507 {
1508     if (miniCtl & V1_Y_INTERPOLY) {
1509         if (pVia->swov.SrcFourCC == FOURCC_YV12
1510             || pVia->swov.SrcFourCC == FOURCC_I420
1511             || pVia->swov.SrcFourCC == FOURCC_XVMC) {
1512             if (videoFlag & VIDEO_HQV_INUSE) {
1513                 if (videoFlag & VIDEO_1_INUSE)
1514                     SetFIFO_64or32(pVia);
1515                 else
1516                     SetFIFO_V3_64or32or16(pVia);
1517             } else {
1518                 /* Minified video will be skewed without this workaround. */
1519                 if (srcWidth <= 80) { /* Fetch count <= 5 */
1520                     if (videoFlag & VIDEO_1_INUSE)
1521                         SetFIFO_V1(pVia, 16, 0, 0);
1522                     else
1523                         SetFIFO_V3(pVia, 16, 16, 0);
1524                 } else {
1525                     if (videoFlag & VIDEO_1_INUSE)
1526                         SetFIFO_64or16(pVia);
1527                     else
1528                         SetFIFO_V3_64or32or16(pVia);
1529                 }
1530             }
1531         } else {
1532             if (videoFlag & VIDEO_1_INUSE)
1533                 SetFIFO_64or48or32(pVia);
1534             else {
1535                 /* Fix V3 bug. */
1536                 if (srcWidth <= 8)
1537                     SetFIFO_V3(pVia, 1, 0, 0);
1538                 else
1539                     SetFIFO_V3_64or32or32(pVia);
1540             }
1541         }
1542     } else {
1543         if (pVia->swov.SrcFourCC == FOURCC_YV12
1544             || pVia->swov.SrcFourCC == FOURCC_I420
1545             || pVia->swov.SrcFourCC == FOURCC_XVMC) {
1546             if (videoFlag & VIDEO_HQV_INUSE) {
1547                 if (videoFlag & VIDEO_1_INUSE)
1548                     SetFIFO_64or32(pVia);
1549                 else
1550                     SetFIFO_V3_64or32or16(pVia);
1551             } else {
1552                 /* Minified video will be skewed without this workaround. */
1553                 if (srcWidth <= 80) { /* Fetch count <= 5 */
1554                     if (videoFlag & VIDEO_1_INUSE)
1555                         SetFIFO_V1(pVia, 16, 0, 0);
1556                     else
1557                         SetFIFO_V3(pVia, 16, 16, 0);
1558                 } else {
1559                     if (videoFlag & VIDEO_1_INUSE)
1560                         SetFIFO_64or16(pVia);
1561                     else
1562                         SetFIFO_V3_64or32or16(pVia);
1563                 }
1564             }
1565         } else {
1566             if (videoFlag & VIDEO_1_INUSE)
1567                 SetFIFO_64or48or32(pVia);
1568             else {
1569                 /* Fix V3 bug. */
1570                 if (srcWidth <= 8)
1571                     SetFIFO_V3(pVia, 1, 0, 0);
1572                 else
1573                     SetFIFO_V3_64or32or32(pVia);
1574             }
1575         }
1576     }
1577 }
1578 
1579 static CARD32
SetColorKey(VIAPtr pVia,unsigned long videoFlag,CARD32 keyLow,CARD32 keyHigh,CARD32 compose)1580 SetColorKey(VIAPtr pVia, unsigned long videoFlag,
1581             CARD32 keyLow, CARD32 keyHigh, CARD32 compose)
1582 {
1583     keyLow &= 0x00FFFFFF;
1584     if (pVia->VideoEngine == VIDEO_ENGINE_CME)
1585         keyLow |= 0x40000000;
1586 
1587     if (videoFlag & VIDEO_1_INUSE) {
1588         SaveVideoRegister(pVia, V_COLOR_KEY, keyLow);
1589         SaveVideoRegister(pVia, SND_COLOR_KEY, keyLow);
1590     } else {
1591         if (pVia->HWDiff.dwSupportTwoColorKey)    /*CLE_C0 */
1592             SaveVideoRegister(pVia, V3_COLOR_KEY, keyLow);
1593     }
1594 
1595     /*CLE_C0 */
1596     compose = ((compose & ~0x0f) | SELECT_VIDEO_IF_COLOR_KEY |
1597                SELECT_VIDEO3_IF_COLOR_KEY);
1598 
1599     return compose;
1600 }
1601 
1602 static CARD32
SetChromaKey(VIAPtr pVia,unsigned long videoFlag,CARD32 chromaLow,CARD32 chromaHigh,CARD32 miniCtl,CARD32 compose)1603 SetChromaKey(VIAPtr pVia, unsigned long videoFlag,
1604              CARD32 chromaLow, CARD32 chromaHigh,
1605              CARD32 miniCtl, CARD32 compose)
1606 {
1607     chromaLow &= CHROMA_KEY_LOW;
1608     chromaHigh &= CHROMA_KEY_HIGH;
1609 
1610     chromaLow |= (VIAGETREG(V_CHROMAKEY_LOW) & ~CHROMA_KEY_LOW);
1611     chromaHigh |= (VIAGETREG(V_CHROMAKEY_HIGH) & ~CHROMA_KEY_HIGH);
1612 
1613     if (pVia->VideoEngine == VIDEO_ENGINE_CME)
1614         chromaLow |= 0x40000000;
1615 
1616     SaveVideoRegister(pVia, V_CHROMAKEY_HIGH, chromaHigh);
1617     if (videoFlag & VIDEO_1_INUSE) {
1618         SaveVideoRegister(pVia, V_CHROMAKEY_LOW, chromaLow & ~V_CHROMAKEY_V3);
1619         /* Temporarily solve the HW interpolation error when using Chroma key */
1620         SaveVideoRegister(pVia, V1_MINI_CONTROL, miniCtl & 0xFFFFFFF8);
1621     } else {
1622         SaveVideoRegister(pVia, V_CHROMAKEY_LOW, chromaLow | V_CHROMAKEY_V3);
1623         SaveVideoRegister(pVia, V3_MINI_CONTROL, miniCtl & 0xFFFFFFF8);
1624     }
1625 
1626     /* Modified by Scottie[2001.12.5] for select video if (Color key & Chroma key) */
1627     if (compose == SELECT_VIDEO_IF_COLOR_KEY)
1628         compose = SELECT_VIDEO_IF_COLOR_KEY | SELECT_VIDEO_IF_CHROMA_KEY;
1629     else
1630         compose = (compose & ~0x0f) | SELECT_VIDEO_IF_CHROMA_KEY;
1631 
1632     return compose;
1633 }
1634 
1635 static void
SetVideoStart(VIAPtr pVia,unsigned long videoFlag,unsigned int numbufs,CARD32 a1,CARD32 a2,CARD32 a3)1636 SetVideoStart(VIAPtr pVia, unsigned long videoFlag,
1637               unsigned int numbufs, CARD32 a1, CARD32 a2, CARD32 a3)
1638 {
1639     CARD32 V1Addr[3] = { V1_STARTADDR_0, V1_STARTADDR_1, V1_STARTADDR_2 };
1640     CARD32 V3Addr[3] = { V3_STARTADDR_0, V3_STARTADDR_1, V3_STARTADDR_2 };
1641     CARD32 *VideoAddr = (videoFlag & VIDEO_1_INUSE) ? V1Addr : V3Addr;
1642 
1643     SaveVideoRegister(pVia, VideoAddr[0], a1);
1644     if (numbufs > 1)
1645         SaveVideoRegister(pVia, VideoAddr[1], a2);
1646     if (numbufs > 2)
1647         SaveVideoRegister(pVia, VideoAddr[2], a3);
1648 }
1649 
1650 static void
SetHQVFetch(VIAPtr pVia,CARD32 srcFetch,unsigned long srcHeight)1651 SetHQVFetch(VIAPtr pVia, CARD32 srcFetch, unsigned long srcHeight)
1652 {
1653     unsigned long proReg = 0;
1654 
1655     if (pVia->ChipId == PCI_CHIP_VT3259
1656         && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
1657         proReg = PRO_HQV1_OFFSET;
1658 
1659     if (!pVia->HWDiff.dwHQVFetchByteUnit) {    /* CLE_C0 */
1660         srcFetch >>= 3;  /* fetch unit is 8 bytes */
1661     }
1662 
1663     if ((pVia->ChipId != PCI_CHIP_VT3409) && (pVia->ChipId != PCI_CHIP_VT3410))
1664         SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg,
1665                           ((srcFetch - 1) << 16) | (srcHeight - 1));
1666 }
1667 
1668 static void
SetFetch(VIAPtr pVia,unsigned long videoFlag,CARD32 fetch)1669 SetFetch(VIAPtr pVia, unsigned long videoFlag, CARD32 fetch)
1670 {
1671     fetch <<= 20;
1672     if (videoFlag & VIDEO_1_INUSE) {
1673         SaveVideoRegister(pVia, V12_QWORD_PER_LINE, fetch);
1674     } else {
1675         fetch |= VIAGETREG(V3_ALPHA_QWORD_PER_LINE) & ~V3_FETCH_COUNT;
1676         SaveVideoRegister(pVia, V3_ALPHA_QWORD_PER_LINE, fetch);
1677     }
1678 }
1679 
1680 static void
SetDisplayCount(VIAPtr pVia,unsigned long videoFlag,unsigned long srcWidth,unsigned long srcHeight)1681 SetDisplayCount(VIAPtr pVia, unsigned long videoFlag,
1682                 unsigned long srcWidth, unsigned long srcHeight)
1683 {
1684     unsigned long DisplayCount;
1685 
1686     /* Removed VIA's large pixelformat switch/case.
1687      * All formats (YV12, UYVY, YUY2, VIA, RGB16 and RGB32)
1688      * seem to use the same count. /A
1689      */
1690 
1691     if (videoFlag & VIDEO_HQV_INUSE)
1692         DisplayCount = srcWidth - 1;
1693     else
1694         DisplayCount = srcWidth - pVia->swov.overlayRecordV1.dwminifyH;
1695 
1696     if (videoFlag & VIDEO_1_INUSE)
1697         SaveVideoRegister(pVia, V1_SOURCE_HEIGHT,
1698                           (srcHeight << 16) | DisplayCount);
1699     else
1700         SaveVideoRegister(pVia, V3_SOURCE_WIDTH, DisplayCount);
1701 }
1702 
1703 static void
SetMiniAndZoom(VIAPtr pVia,unsigned long videoFlag,CARD32 miniCtl,CARD32 zoomCtl)1704 SetMiniAndZoom(VIAPtr pVia, unsigned long videoFlag,
1705                CARD32 miniCtl, CARD32 zoomCtl)
1706 {
1707     if (videoFlag & VIDEO_1_INUSE) {
1708         SaveVideoRegister(pVia, V1_MINI_CONTROL, miniCtl);
1709         SaveVideoRegister(pVia, V1_ZOOM_CONTROL, zoomCtl);
1710     } else {
1711         SaveVideoRegister(pVia, V3_MINI_CONTROL, miniCtl);
1712         SaveVideoRegister(pVia, V3_ZOOM_CONTROL, zoomCtl);
1713     }
1714 }
1715 
1716 static void
SetVideoControl(VIAPtr pVia,unsigned long videoFlag,CARD32 vidCtl)1717 SetVideoControl(VIAPtr pVia, unsigned long videoFlag, CARD32 vidCtl)
1718 {
1719     if (videoFlag & VIDEO_1_INUSE)
1720         SaveVideoRegister(pVia, V1_CONTROL, vidCtl);
1721     else
1722         SaveVideoRegister(pVia, V3_CONTROL, vidCtl);
1723 }
1724 
1725 static void
FireVideoCommand(VIAPtr pVia,unsigned long videoFlag,CARD32 compose)1726 FireVideoCommand(VIAPtr pVia, unsigned long videoFlag, CARD32 compose)
1727 {
1728     if (videoFlag & VIDEO_1_INUSE)
1729         SaveVideoRegister(pVia, V_COMPOSE_MODE, compose | V1_COMMAND_FIRE);
1730     else
1731         SaveVideoRegister(pVia, V_COMPOSE_MODE, compose | V3_COMMAND_FIRE);
1732 }
1733 
1734 static void
SetVideoWindow(ScrnInfoPtr pScrn,unsigned long videoFlag,LPDDUPDATEOVERLAY pUpdate)1735 SetVideoWindow(ScrnInfoPtr pScrn, unsigned long videoFlag,
1736                LPDDUPDATEOVERLAY pUpdate)
1737 {
1738     VIAPtr pVia = VIAPTR(pScrn);
1739     CARD32 left = pUpdate->DstLeft;
1740     CARD32 top = pUpdate->DstTop;
1741     CARD32 right = pUpdate->DstRight - 1;
1742     CARD32 bottom = pUpdate->DstBottom - 1;
1743 
1744     DBG_DD(ErrorF("SetVideoWindow: X (%ld,%ld) Y (%ld,%ld)\n",
1745                   left, right, top, bottom));
1746 
1747     /* Modify for HW DVI limitation.
1748      * When we enable both the CRT and DVI, then change resolution.
1749      * If the resolution is smaller than the panel's physical size,
1750      * the video display in Y direction will be cut.
1751      * So, we need to adjust the Y top and bottom position.
1752      *
1753     if (videoFlag & VIDEO_1_INUSE) {
1754         if (pBIOSInfo->SetDVI && pBIOSInfo->scaleY) {
1755             top = (pUpdate->DstTop * pBIOSInfo->Panel->NativeMode->Height
1756                    / pScrn->currentMode->VDisplay);
1757             bottom = (pUpdate->DstBottom * pBIOSInfo->Panel->NativeMode->Height
1758                       / pScrn->currentMode->VDisplay);
1759         }
1760     }*/
1761 
1762     if (top > 2047)
1763         top = 2047;
1764 
1765     if (bottom > 2047)
1766         bottom = 2047;
1767 
1768     if (left > 2047)
1769         left = 2047;
1770 
1771     if (right > 2047)
1772         right = 2047;
1773 
1774     if (videoFlag & VIDEO_1_INUSE) {
1775         SaveVideoRegister(pVia, V1_WIN_END_Y, (right << 16) | bottom);
1776         SaveVideoRegister(pVia, V1_WIN_START_Y, (left << 16) | top);
1777     } else {
1778         SaveVideoRegister(pVia, V3_WIN_END_Y, (right << 16) | bottom);
1779         SaveVideoRegister(pVia, V3_WIN_START_Y, (left << 16) | top);
1780     }
1781 }
1782 
1783 /*
1784  * Upd_Video()
1785  */
1786 static Bool
Upd_Video(xf86CrtcPtr crtc,unsigned long videoFlag,unsigned long startAddr,LPDDUPDATEOVERLAY pUpdate,unsigned long srcPitch,unsigned long oriSrcWidth,unsigned long oriSrcHeight,unsigned long deinterlaceMode,unsigned long haveColorKey,unsigned long haveChromaKey,unsigned long colorKeyLow,unsigned long colorKeyHigh,unsigned long chromaKeyLow,unsigned long chromaKeyHigh)1787 Upd_Video(xf86CrtcPtr crtc, unsigned long videoFlag,
1788           unsigned long startAddr, LPDDUPDATEOVERLAY pUpdate,
1789           unsigned long srcPitch,
1790           unsigned long oriSrcWidth, unsigned long oriSrcHeight,
1791           unsigned long deinterlaceMode,
1792           unsigned long haveColorKey, unsigned long haveChromaKey,
1793           unsigned long colorKeyLow, unsigned long colorKeyHigh,
1794           unsigned long chromaKeyLow, unsigned long chromaKeyHigh)
1795 {
1796     drmmode_crtc_private_ptr iga = crtc->driver_private;
1797     ScrnInfoPtr pScrn = crtc->scrn;
1798     VIAPtr pVia = VIAPTR(pScrn);
1799     vgaHWPtr hwp = VGAHWPTR(pScrn);
1800     VIAHWDiff *hwDiff = &pVia->HWDiff;
1801     unsigned long vidCtl = 0, compose;
1802     unsigned long srcWidth, srcHeight, dstWidth, dstHeight;
1803     unsigned long zoomCtl = 0, miniCtl = 0;
1804     unsigned long hqvCtl = 0;
1805     unsigned long hqvFilterCtl = 0, hqvMiniCtl = 0;
1806     unsigned long hqvScaleCtlH = 0, hqvScaleCtlV = 0;
1807     unsigned long haveHQVzoomH = 0, haveHQVzoomV = 0;
1808     unsigned long hqvSrcWidth = 0, hqvDstWidth = 0;
1809     unsigned long hqvSrcFetch = 0, hqvOffset = 0;
1810     unsigned long dwOffset = 0, fetch = 0, tmp = 0;
1811     unsigned long proReg = 0;
1812     int i;
1813 
1814     DBG_DD(ErrorF("videoflag=%ld\n", videoFlag));
1815 
1816     if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
1817         proReg = PRO_HQV1_OFFSET;
1818 
1819     compose = ((VIAGETREG(V_COMPOSE_MODE)
1820                 & ~(SELECT_VIDEO_IF_COLOR_KEY
1821                     | V1_COMMAND_FIRE | V3_COMMAND_FIRE))
1822                | V_COMMAND_LOAD_VBI);
1823 
1824     DBG_DD(ErrorF("// Upd_Video:\n"));
1825     DBG_DD(ErrorF("Modified rSrc  X (%ld,%ld) Y (%ld,%ld)\n",
1826                   pUpdate->SrcLeft, pUpdate->SrcRight,
1827                   pUpdate->SrcTop, pUpdate->SrcBottom));
1828     DBG_DD(ErrorF("Modified rDest  X (%ld,%ld) Y (%ld,%ld)\n",
1829                   pUpdate->DstLeft, pUpdate->DstRight,
1830                   pUpdate->DstTop, pUpdate->DstBottom));
1831 
1832     dstWidth = pUpdate->DstRight - pUpdate->DstLeft;
1833 	/*if (pBIOSInfo->lvds && pBIOSInfo->lvds->status == XF86OutputStatusConnected &&
1834 		pBIOSInfo->Panel->Scale) {
1835         * FIXME: We need to determine if the panel is using V1 or V3 *
1836         float hfactor = (float)pBIOSInfo->Panel->NativeMode->Width
1837                         / pScrn->currentMode->HDisplay;
1838         dstWidth *= hfactor;
1839     }*/
1840 
1841     pVia->swov.overlayRecordV1.dwWidth = dstWidth;
1842     pVia->swov.overlayRecordV1.dwHeight = dstHeight =
1843             pUpdate->DstBottom - pUpdate->DstTop;
1844     srcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft;
1845     srcHeight = (unsigned long)pUpdate->SrcBottom - pUpdate->SrcTop;
1846     DBG_DD(ErrorF("===srcWidth= %ld \n", srcWidth));
1847     DBG_DD(ErrorF("===srcHeight= %ld \n", srcHeight));
1848 
1849     vidCtl = ViaSetVidCtl(pVia, videoFlag);
1850 
1851     if (hwDiff->dwNeedV1Prefetch) {
1852         DBG_DD(ErrorF("NEEDV1PREFETCH\n"));
1853         vidCtl |= V1_PREFETCH_ON_3336;
1854     }
1855 
1856     /*
1857      * Enable video on secondary
1858      */
1859     if ((pVia->VideoEngine == VIDEO_ENGINE_CME ||
1860          pVia->Chipset == VIA_P4M800PRO) && iga->index) {
1861         /* V1_ON_SND_DISPLAY */
1862         vidCtl |= V1_ON_SND_DISPLAY;
1863         /* SECOND_DISPLAY_COLOR_KEY_ENABLE */
1864         compose |= SECOND_DISPLAY_COLOR_KEY_ENABLE | 0x1;
1865     }
1866 
1867     viaOverlayGetV1V3Format(pVia, (videoFlag & VIDEO_1_INUSE) ? 1 : 3,
1868                             videoFlag, &vidCtl, &hqvCtl);
1869 
1870     if (hwDiff->dwThreeHQVBuffer) {    /* CLE_C0: HQV supports triple-buffering */
1871         hqvCtl &= ~HQV_SW_FLIP;
1872         hqvCtl |= HQV_TRIPLE_BUFF | HQV_FLIP_STATUS;
1873     }
1874 
1875     /* Starting address of source and Source offset */
1876     dwOffset = viaOverlayGetSrcStartAddress(pVia, videoFlag, pUpdate,
1877                                             srcPitch, &hqvOffset);
1878     DBG_DD(ErrorF("===dwOffset= 0x%lx \n", dwOffset));
1879 
1880     pVia->swov.overlayRecordV1.dwOffset = dwOffset;
1881 
1882     if (pVia->swov.SrcFourCC == FOURCC_YV12
1883         || pVia->swov.SrcFourCC == FOURCC_I420
1884         || pVia->swov.SrcFourCC == FOURCC_XVMC) {
1885 
1886         YCBCRREC YCbCr;
1887 
1888         if (videoFlag & VIDEO_HQV_INUSE) {
1889             SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2,
1890                           pVia->swov.overlayRecordV1.dwHQVAddr[0] + dwOffset,
1891                           pVia->swov.overlayRecordV1.dwHQVAddr[1] + dwOffset,
1892                           pVia->swov.overlayRecordV1.dwHQVAddr[2] + dwOffset);
1893 
1894             if (pVia->swov.SrcFourCC != FOURCC_XVMC) {
1895                 YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr,
1896                                 pVia->swov.overlayRecordV1.dwOffset,
1897                                 pVia->swov.overlayRecordV1.dwUVoffset,
1898                                 srcPitch, oriSrcHeight);
1899                 if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
1900                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg,
1901                                       YCbCr.dwY);
1902                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U + proReg,
1903                                       YCbCr.dwCB);
1904                 } else {
1905                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y, YCbCr.dwY);
1906                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U, YCbCr.dwCR);
1907                     SaveVideoRegister(pVia, HQV_SRC_STARTADDR_V, YCbCr.dwCB);
1908                 }
1909             }
1910         } else {
1911             YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr,
1912                             pVia->swov.overlayRecordV1.dwOffset,
1913                             pVia->swov.overlayRecordV1.dwUVoffset,
1914                             srcPitch, oriSrcHeight);
1915 
1916             if (videoFlag & VIDEO_1_INUSE) {
1917                 SaveVideoRegister(pVia, V1_STARTADDR_0, YCbCr.dwY);
1918                 SaveVideoRegister(pVia, V1_STARTADDR_CB0, YCbCr.dwCR);
1919                 SaveVideoRegister(pVia, V1_STARTADDR_CR0, YCbCr.dwCB);
1920             } else
1921                 DBG_DD(ErrorF("Upd_Video(): "
1922                               "We do not support YV12 with V3!\n"));
1923         }
1924     } else {
1925         if (videoFlag & VIDEO_HQV_INUSE) {
1926             hqvSrcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft;
1927             hqvDstWidth = (unsigned long)pUpdate->DstRight - pUpdate->DstLeft;
1928 
1929             if (hqvSrcWidth > hqvDstWidth)
1930                 dwOffset = dwOffset * hqvDstWidth / hqvSrcWidth;
1931 
1932             SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2,
1933                           pVia->swov.overlayRecordV1.dwHQVAddr[0] + hqvOffset,
1934                           pVia->swov.overlayRecordV1.dwHQVAddr[1] + hqvOffset,
1935                           pVia->swov.overlayRecordV1.dwHQVAddr[2] + hqvOffset);
1936 
1937             if (pVia->VideoEngine == VIDEO_ENGINE_CME)
1938                 SaveVideoRegister(pVia, 0x1cc + proReg, dwOffset);
1939 
1940             SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg, startAddr);
1941         } else {
1942             startAddr += dwOffset;
1943             SetVideoStart(pVia, videoFlag, 1, startAddr, 0, 0);
1944         }
1945     }
1946 
1947     fetch = viaOverlayGetFetch(pVia, videoFlag,
1948                                srcWidth, dstWidth, oriSrcWidth, &hqvSrcFetch);
1949     DBG_DD(ErrorF("===fetch= 0x%lx\n", fetch));
1950 
1951 #if 0
1952     /* For DCT450 test-BOB INTERLEAVE */
1953     if ((deinterlaceMode & DDOVER_INTERLEAVED)
1954         && (deinterlaceMode & DDOVER_BOB)) {
1955         if (videoFlag & VIDEO_HQV_INUSE)
1956             hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE;
1957         else
1958             vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE;
1959     } else if (deinterlaceMode & DDOVER_BOB) {
1960         if (videoFlag & VIDEO_HQV_INUSE)
1961             /* The HQV source data line count should be two times of the original line count */
1962             hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE;
1963         else
1964             vidCtl |= V1_BOB_ENABLE;
1965     }
1966 #endif
1967 
1968     if (videoFlag & VIDEO_HQV_INUSE) {
1969         if (!(deinterlaceMode & DDOVER_INTERLEAVED)
1970             && (deinterlaceMode & DDOVER_BOB))
1971             SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight << 1);
1972         else
1973             SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight);
1974 
1975         if (pVia->swov.SrcFourCC == FOURCC_YV12
1976             || pVia->swov.SrcFourCC == FOURCC_I420
1977             || pVia->swov.SrcFourCC == FOURCC_XVMC) {
1978             if (videoFlag & VIDEO_1_INUSE)
1979                 SaveVideoRegister(pVia, V1_STRIDE, srcPitch << 1);
1980             else
1981                 SaveVideoRegister(pVia, V3_STRIDE, srcPitch << 1);
1982 
1983             if (pVia->HWDiff.dwHQVFetchByteUnit)
1984                 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg,
1985                                   ((srcPitch >> 1) << 16) | srcPitch |
1986                                   HQV_FIFO_DEPTH_1);
1987             else
1988                 SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg,
1989                                   ((srcPitch >> 1) << 16) | srcPitch);
1990 
1991             SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, (srcPitch << 1));
1992         } else {
1993             if (videoFlag & VIDEO_1_INUSE)
1994                 SaveVideoRegister(pVia, V1_STRIDE, srcPitch);
1995             else
1996                 SaveVideoRegister(pVia, V3_STRIDE, srcPitch);
1997 
1998             SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg, srcPitch);
1999             SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, srcPitch);
2000         }
2001 
2002     } else {
2003         if (videoFlag & VIDEO_1_INUSE)
2004             SaveVideoRegister(pVia, V1_STRIDE, srcPitch | (srcPitch << 15));
2005         else
2006             SaveVideoRegister(pVia, V3_STRIDE, srcPitch | (srcPitch << 15));
2007     }
2008 
2009     /* Set destination window */
2010     SetVideoWindow(pScrn, videoFlag, pUpdate);
2011 
2012     compose |= ALWAYS_SELECT_VIDEO;
2013 
2014     /* Set up X zoom factor */
2015 
2016     pVia->swov.overlayRecordV1.dwFetchAlignment = 0;
2017 
2018     if (!viaOverlayHQVCalcZoomWidth(pVia, videoFlag, srcWidth, dstWidth,
2019                                     &zoomCtl, &miniCtl, &hqvFilterCtl,
2020                                     &hqvMiniCtl, &hqvScaleCtlH, &haveHQVzoomH)) {
2021         /* Need to scale (minify) too much - can't handle it. */
2022         SetFetch(pVia, videoFlag, fetch);
2023         FireVideoCommand(pVia, videoFlag, compose);
2024         FlushVidRegBuffer(pVia);
2025         return FALSE;
2026     }
2027 
2028     SetFetch(pVia, videoFlag, fetch);
2029 
2030     /* Set up Y zoom factor */
2031 
2032     /* For DCT450 test-BOB INTERLEAVE */
2033     if ((deinterlaceMode & DDOVER_INTERLEAVED)
2034         && (deinterlaceMode & DDOVER_BOB)) {
2035         if (!(videoFlag & VIDEO_HQV_INUSE)) {
2036             srcHeight /= 2;
2037             if (videoFlag & VIDEO_1_INUSE)
2038                 vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE;
2039             else
2040                 vidCtl |= V3_BOB_ENABLE | V3_FRAME_BASE;
2041         } else
2042             hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE;
2043     } else if (deinterlaceMode & DDOVER_BOB) {
2044         if (videoFlag & VIDEO_HQV_INUSE) {
2045             srcHeight <<= 1;
2046             hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE;
2047         } else {
2048             if (videoFlag & VIDEO_1_INUSE)
2049                 vidCtl |= V1_BOB_ENABLE;
2050             else
2051                 vidCtl |= V3_BOB_ENABLE;
2052         }
2053     }
2054 
2055     SetDisplayCount(pVia, videoFlag, srcWidth, srcHeight);
2056 
2057     if (!viaOverlayHQVCalcZoomHeight(pVia, srcHeight, dstHeight, &zoomCtl,
2058                                      &miniCtl, &hqvFilterCtl, &hqvMiniCtl,
2059                                      &hqvScaleCtlV, &haveHQVzoomV)) {
2060         /* Need to scale (minify) too much - can't handle it. */
2061         FireVideoCommand(pVia, videoFlag, compose);
2062         FlushVidRegBuffer(pVia);
2063         return FALSE;
2064     }
2065 
2066     SetupFIFOs(pVia, videoFlag, miniCtl, srcWidth);
2067 
2068     if (videoFlag & VIDEO_HQV_INUSE) {
2069         miniCtl = 0;
2070 
2071         if (haveHQVzoomH || haveHQVzoomV) {
2072             tmp = 0;
2073 
2074             if (haveHQVzoomH) {
2075                 miniCtl = V1_X_INTERPOLY;
2076                 /* Disable X interpolation if the height exceeds
2077                  * the maximum supported by the hardware */
2078                 if (srcHeight >= pVia->swov.maxHInterp)
2079                     miniCtl &= ~V1_X_INTERPOLY;
2080                 tmp = zoomCtl & 0xffff0000;
2081             }
2082 
2083             if (haveHQVzoomV) {
2084                 miniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
2085                 /* Disable Y interpolation if the width exceeds
2086                  * the maximum supported by the hardware */
2087                 if (srcWidth >= pVia->swov.maxWInterp)
2088                     miniCtl &= ~V1_Y_INTERPOLY;
2089                 tmp |= zoomCtl & 0x0000ffff;
2090                 hqvFilterCtl &= 0xfffdffff;
2091             }
2092 
2093             /* Temporary fix for 2D bandwidth problem. 2002/08/01 */
2094             if (pVia->swov.gdwUseExtendedFIFO)
2095                 miniCtl &= ~V1_Y_INTERPOLY;
2096 
2097             SetMiniAndZoom(pVia, videoFlag, miniCtl, tmp);
2098         } else {
2099             if (srcHeight == dstHeight)
2100                 hqvFilterCtl &= 0xfffdffff;
2101             SetMiniAndZoom(pVia, videoFlag, 0, 0);
2102         }
2103 	if (hwDiff->dwNewScaleCtl) {
2104 		SaveVideoRegister(pVia, HQV_H_SCALE_CONTROL + proReg, hqvScaleCtlH);
2105 		SaveVideoRegister(pVia, HQV_V_SCALE_CONTROL + proReg, hqvScaleCtlV);
2106 	} else {
2107 		SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
2108 	}
2109 	SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
2110     } else
2111         SetMiniAndZoom(pVia, videoFlag, miniCtl, zoomCtl);
2112 
2113     if (haveColorKey)
2114         compose = SetColorKey(pVia, videoFlag, colorKeyLow, colorKeyHigh,
2115                               compose);
2116 
2117     if (haveChromaKey)
2118         compose = SetChromaKey(pVia, videoFlag, chromaKeyLow, chromaKeyHigh,
2119                                miniCtl, compose);
2120 
2121     if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
2122         SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL1),0);
2123         SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL3),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
2124         if ((pVia->Chipset == VIA_VX800) ||
2125             (pVia->Chipset == VIA_VX855) ||
2126             (pVia->Chipset == VIA_VX900)) {
2127             SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL2),0);
2128             SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL4),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
2129             if ((pVia->Chipset == VIA_VX855) ||
2130                 (pVia->Chipset == VIA_VX900)) {
2131                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL1,0);
2132                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
2133                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL2,0);
2134                 SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
2135                 SaveVideoRegister(pVia, HQV_BACKGROUND_DATA_OFFSET,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
2136                 SaveVideoRegister(pVia, HQV_EXTENDED_CONTROL,0);
2137                 /*0x3e0*/
2138                 SaveVideoRegister(pVia, HQV_SUBP_HSCALE_CTRL,0);
2139                 /*0x3e8*/
2140                 SaveVideoRegister(pVia, HQV_SUBP_VSCALE_CTRL,0);
2141             }
2142 
2143             if (pVia->Chipset == VIA_VX900) {
2144 
2145                 SaveVideoRegister(pVia, HQV_SHARPNESS_DECODER_HANDSHAKE_CTRL_410, 0);
2146             }
2147 
2148             // TODO Need to be tested on VX800
2149             /* 0x3B8 */
2150             SaveVideoRegister(pVia, HQV_DEFAULT_VIDEO_COLOR, HQV_FIX_COLOR);
2151 
2152         }
2153     }
2154 
2155     /* Set up video control */
2156     if (videoFlag & VIDEO_HQV_INUSE) {
2157 
2158         if (!pVia->swov.SWVideo_ON) {
2159             DBG_DD(ErrorF("    First HQV\n"));
2160 
2161             FlushVidRegBuffer(pVia);
2162 
2163             DBG_DD(ErrorF(" Wait flips"));
2164 
2165             if (hwDiff->dwHQVInitPatch) {
2166                 DBG_DD(ErrorF(" Initializing HQV twice ..."));
2167                 for (i = 0; i < 2; i++) {
2168                     viaWaitHQVFlipClear(pVia,
2169                                         ((hqvCtl & ~HQV_SW_FLIP) |
2170                                          HQV_FLIP_STATUS) & ~HQV_ENABLE);
2171                     VIASETREG(HQV_CONTROL + proReg, hqvCtl);
2172                     viaWaitHQVFlip(pVia);
2173                 }
2174                 DBG_DD(ErrorF(" done.\n"));
2175             } else {               /* CLE_C0 */
2176                 CARD32 volatile *HQVCtrl =
2177                         (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL +
2178                                             proReg);
2179 
2180                 /* Check that HQV is idle */
2181                 DBG_DD(ErrorF("HQV control wf - %08lx\n", *HQVCtrl));
2182                 while (!(*HQVCtrl & HQV_IDLE)) {
2183                     DBG_DD(ErrorF("HQV control busy - %08lx\n", *HQVCtrl));
2184                     usleep(1);
2185                 }
2186 
2187                 VIASETREG(HQV_CONTROL + proReg, hqvCtl & ~HQV_SW_FLIP);
2188                 VIASETREG(HQV_CONTROL + proReg, hqvCtl | HQV_SW_FLIP);
2189 
2190                 DBG_DD(ErrorF("HQV control wf5 - %08lx\n", *HQVCtrl));
2191                 DBG_DD(ErrorF(" Wait flips5"));
2192 
2193                 if (pVia->VideoEngine != VIDEO_ENGINE_CME) {
2194                     for (i = 0; (i < 50) && !(*HQVCtrl & HQV_FLIP_STATUS);
2195                          i++) {
2196                         DBG_DD(ErrorF(" HQV wait %d %08lx\n", i, *HQVCtrl));
2197                         *HQVCtrl |= HQV_SW_FLIP | HQV_FLIP_STATUS;
2198                         usleep(1);
2199                     }
2200                 } else {
2201                     viaWaitHQVFlip(pVia);
2202                 }
2203 
2204                 DBG_DD(ErrorF(" Wait flips6"));
2205             }
2206 
2207             if (videoFlag & VIDEO_1_INUSE) {
2208                 VIASETREG(V1_CONTROL, vidCtl);
2209                 VIASETREG(V_COMPOSE_MODE, compose | V1_COMMAND_FIRE);
2210                 if (pVia->swov.gdwUseExtendedFIFO) {
2211                     /* Set Display FIFO */
2212                     DBG_DD(ErrorF(" Wait flips7"));
2213                     viaWaitVBI(pVia);
2214                     DBG_DD(ErrorF(" Wait flips 8"));
2215                     hwp->writeSeq(hwp, 0x17, 0x2F);
2216                     ViaSeqMask(hwp, 0x16, 0x14, 0x1F);
2217                     hwp->writeSeq(hwp, 0x18, 0x56);
2218                     DBG_DD(ErrorF(" Wait flips 9"));
2219                 }
2220             } else {
2221                 DBG_DD(ErrorF(" Wait flips 10"));
2222                 VIASETREG(V3_CONTROL, vidCtl);
2223                 VIASETREG(V_COMPOSE_MODE, compose | V3_COMMAND_FIRE);
2224             }
2225             DBG_DD(ErrorF(" Done flips"));
2226         } else {
2227             DBG_DD(ErrorF("    Normal called\n"));
2228             SaveVideoRegister(pVia, HQV_CONTROL + proReg,
2229                               hqvCtl | HQV_FLIP_STATUS);
2230             SetVideoControl(pVia, videoFlag, vidCtl);
2231             FireVideoCommand(pVia, videoFlag, compose);
2232             viaWaitHQVDone(pVia);
2233             FlushVidRegBuffer(pVia);
2234         }
2235     } else {
2236         SetVideoControl(pVia, videoFlag, vidCtl);
2237         FireVideoCommand(pVia, videoFlag, compose);
2238         viaWaitHQVDone(pVia);
2239         FlushVidRegBuffer(pVia);
2240     }
2241     pVia->swov.SWVideo_ON = TRUE;
2242 
2243     DBG_DD(ErrorF(" Done Upd_Video"));
2244 
2245     return TRUE;
2246 
2247 }  /* Upd_Video */
2248 
2249 /*
2250  *  VIAVidUpdateOverlay()
2251  *  Parameters:   src rectangle, dst rectangle, colorkey...
2252  *  Return value: unsigned long of state
2253  *  Note: updates the overlay image parameter.
2254  */
2255 Bool
VIAVidUpdateOverlay(xf86CrtcPtr crtc,LPDDUPDATEOVERLAY pUpdate)2256 VIAVidUpdateOverlay(xf86CrtcPtr crtc, LPDDUPDATEOVERLAY pUpdate)
2257 {
2258     ScrnInfoPtr pScrn = crtc->scrn;
2259     VIAPtr pVia = VIAPTR(pScrn);
2260     OVERLAYRECORD *ovlV1 = &pVia->swov.overlayRecordV1;
2261 
2262     unsigned long flags = pUpdate->dwFlags;
2263     unsigned long videoFlag = 0;
2264     unsigned long startAddr = 0;
2265     unsigned long deinterlaceMode = 0;
2266 
2267     unsigned long haveColorKey = 0, haveChromaKey = 0;
2268     unsigned long colorKeyLow = 0, colorKeyHigh = 0;
2269     unsigned long chromaKeyLow = 0, chromaKeyHigh = 0;
2270 
2271     unsigned long scrnWidth, scrnHeight;
2272     int dstTop, dstBottom, dstLeft, dstRight;
2273     int panDX, panDY;               /* Panning delta */
2274 
2275     unsigned long proReg = 0;
2276 
2277     panDX = pVia->swov.panning_x;
2278     panDY = pVia->swov.panning_y;
2279     pVia->swov.oldPanningX = pVia->swov.panning_x;
2280     pVia->swov.oldPanningY = pVia->swov.panning_y;
2281 
2282     pUpdate->DstLeft -= panDX;
2283     pUpdate->DstTop -= panDY;
2284     pUpdate->DstRight -= panDX;
2285     pUpdate->DstBottom -= panDY;
2286 
2287     DBG_DD(ErrorF("Raw rSrc  X (%ld,%ld) Y (%ld,%ld)\n",
2288                   pUpdate->SrcLeft, pUpdate->SrcRight,
2289                   pUpdate->SrcTop, pUpdate->SrcBottom));
2290     DBG_DD(ErrorF("Raw rDest  X (%ld,%ld) Y (%ld,%ld)\n",
2291                   pUpdate->DstLeft, pUpdate->DstRight,
2292                   pUpdate->DstTop, pUpdate->DstBottom));
2293 
2294     if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
2295         (pVia->swov.SrcFourCC == FOURCC_RV15) ||
2296         (pVia->swov.SrcFourCC == FOURCC_RV16) ||
2297         (pVia->swov.SrcFourCC == FOURCC_RV32) ||
2298         (pVia->swov.SrcFourCC == FOURCC_YV12) ||
2299         (pVia->swov.SrcFourCC == FOURCC_I420) ||
2300         (pVia->swov.SrcFourCC == FOURCC_XVMC)) {
2301         videoFlag = pVia->swov.gdwVideoFlagSW;
2302     }
2303 
2304     if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
2305         proReg = PRO_HQV1_OFFSET;
2306 
2307     flags |= DDOVER_INTERLEAVED;
2308 
2309     /* Disable destination color keying if the alpha window is in use. */
2310     if (pVia->swov.gdwAlphaEnabled)
2311         flags &= ~DDOVER_KEYDEST;
2312 
2313     ResetVidRegBuffer(pVia);
2314 
2315     /* For SW decode HW overlay use */
2316     startAddr = VIAGETREG(HQV_SRC_STARTADDR_Y + proReg);
2317 
2318     if (flags & DDOVER_KEYDEST) {
2319         haveColorKey = 1;
2320         colorKeyLow = pUpdate->dwColorSpaceLowValue;
2321     }
2322 
2323     if (flags & DDOVER_INTERLEAVED)
2324         deinterlaceMode |= DDOVER_INTERLEAVED;
2325 
2326     if (flags & DDOVER_BOB)
2327         deinterlaceMode |= DDOVER_BOB;
2328 
2329     if ((pVia->ChipId == PCI_CHIP_CLE3122)
2330         && (pScrn->currentMode->HDisplay > 1024)) {
2331         DBG_DD(ErrorF("UseExtendedFIFO\n"));
2332         pVia->swov.gdwUseExtendedFIFO = 1;
2333     } else
2334         pVia->swov.gdwUseExtendedFIFO = 0;
2335 
2336     /* Figure out actual rSrc rectangle */
2337 
2338     dstLeft = pUpdate->DstLeft;
2339     dstTop = pUpdate->DstTop;
2340     dstRight = pUpdate->DstRight;
2341     dstBottom = pUpdate->DstBottom;
2342 
2343     scrnWidth = pScrn->currentMode->HDisplay;
2344     scrnHeight = pScrn->currentMode->VDisplay;
2345 
2346     if (dstLeft < 0) {
2347         pUpdate->SrcLeft = ((((-dstLeft) * ovlV1->dwV1OriWidth) +
2348                              ((dstRight - dstLeft) >> 1))
2349                             / (dstRight - dstLeft));
2350     }
2351     if (dstRight > scrnWidth) {
2352         pUpdate->SrcRight = ((((scrnWidth - dstLeft) * ovlV1->dwV1OriWidth) +
2353                               ((dstRight - dstLeft) >> 1))
2354                              / (dstRight - dstLeft));
2355     }
2356     if (dstTop < 0) {
2357         pUpdate->SrcTop = ((((-dstTop) * ovlV1->dwV1OriHeight) +
2358                             ((dstBottom - dstTop) >> 1))
2359                            / (dstBottom - dstTop));
2360     }
2361     if (dstBottom > scrnHeight) {
2362         pUpdate->SrcBottom = ((((scrnHeight - dstTop) * ovlV1->dwV1OriHeight) +
2363                                ((dstBottom - dstTop) >> 1))
2364                               / (dstBottom - dstTop));
2365     }
2366 
2367     /* Save modified src & original dest rectangle parameters */
2368 
2369     if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
2370         (pVia->swov.SrcFourCC == FOURCC_RV15) ||
2371         (pVia->swov.SrcFourCC == FOURCC_RV16) ||
2372         (pVia->swov.SrcFourCC == FOURCC_RV32) ||
2373         (pVia->swov.SrcFourCC == FOURCC_YV12) ||
2374         (pVia->swov.SrcFourCC == FOURCC_I420) ||
2375         (pVia->swov.SrcFourCC == FOURCC_XVMC)) {
2376         pVia->swov.SWDevice.gdwSWDstLeft = pUpdate->DstLeft + panDX;
2377         pVia->swov.SWDevice.gdwSWDstTop = pUpdate->DstTop + panDY;
2378         pVia->swov.SWDevice.gdwSWDstWidth =
2379                 pUpdate->DstRight - pUpdate->DstLeft;
2380         pVia->swov.SWDevice.gdwSWDstHeight =
2381                 pUpdate->DstBottom - pUpdate->DstTop;
2382 
2383         pVia->swov.SWDevice.gdwSWSrcWidth = ovlV1->dwV1SrcWidth =
2384                 pUpdate->SrcRight - pUpdate->SrcLeft;
2385         pVia->swov.SWDevice.gdwSWSrcHeight = ovlV1->dwV1SrcHeight =
2386                 pUpdate->SrcBottom - pUpdate->SrcTop;
2387     }
2388 
2389     ovlV1->dwV1SrcLeft = pUpdate->SrcLeft;
2390     ovlV1->dwV1SrcRight = pUpdate->SrcRight;
2391     ovlV1->dwV1SrcTop = pUpdate->SrcTop;
2392     ovlV1->dwV1SrcBot = pUpdate->SrcBottom;
2393 
2394     /* Figure out actual rDest rectangle */
2395 
2396     pUpdate->DstLeft = (dstLeft < 0) ? 0 : dstLeft;
2397     pUpdate->DstTop = (dstTop < 0) ? 0 : dstTop;
2398     if (pUpdate->DstTop >= scrnHeight)
2399         pUpdate->DstTop = scrnHeight - 1;
2400     pUpdate->DstRight = (dstRight > scrnWidth) ? scrnWidth : dstRight;
2401     pUpdate->DstBottom = (dstBottom > scrnHeight) ? scrnHeight : dstBottom;
2402 
2403     /* Update the overlay */
2404 
2405     if (!Upd_Video(crtc, videoFlag, startAddr, pUpdate,
2406                    pVia->swov.SWDevice.dwPitch, ovlV1->dwV1OriWidth,
2407                    ovlV1->dwV1OriHeight, deinterlaceMode, haveColorKey,
2408                    haveChromaKey, colorKeyLow, colorKeyHigh, chromaKeyLow,
2409                    chromaKeyHigh))
2410         return FALSE;
2411 
2412     pVia->swov.SWVideo_ON = FALSE;
2413 
2414     return TRUE;
2415 
2416 }  /* VIAVidUpdateOverlay */
2417 
2418 /*
2419  *
2420  */
2421 void
ViaOverlayHide(ScrnInfoPtr pScrn)2422 ViaOverlayHide(ScrnInfoPtr pScrn)
2423 {
2424     VIAPtr pVia = VIAPTR(pScrn);
2425     vgaHWPtr hwp = VGAHWPTR(pScrn);
2426     CARD32 videoFlag = 0;
2427     unsigned long proReg = 0;
2428 
2429     if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
2430         (pVia->swov.SrcFourCC == FOURCC_RV15) ||
2431         (pVia->swov.SrcFourCC == FOURCC_RV16) ||
2432         (pVia->swov.SrcFourCC == FOURCC_RV32) ||
2433         (pVia->swov.SrcFourCC == FOURCC_YV12) ||
2434         (pVia->swov.SrcFourCC == FOURCC_I420) ||
2435         (pVia->swov.SrcFourCC == FOURCC_XVMC))
2436         videoFlag = pVia->swov.gdwVideoFlagSW;
2437 
2438     if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
2439         proReg = PRO_HQV1_OFFSET;
2440 
2441     ResetVidRegBuffer(pVia);
2442 
2443     if (pVia->HWDiff.dwHQVDisablePatch)
2444         ViaSeqMask(hwp, 0x2E, 0x00, 0x10);
2445 
2446     SaveVideoRegister(pVia, V_FIFO_CONTROL, V1_FIFO_PRETHRESHOLD12 |
2447                       V1_FIFO_THRESHOLD8 | V1_FIFO_DEPTH16);
2448     SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
2449                       ALPHA_FIFO_THRESHOLD4 | ALPHA_FIFO_DEPTH8 |
2450                       V3_FIFO_THRESHOLD24 | V3_FIFO_DEPTH32);
2451 
2452     if (videoFlag & VIDEO_HQV_INUSE)
2453         SaveVideoRegister(pVia, HQV_CONTROL + proReg,
2454                           VIAGETREG(HQV_CONTROL + proReg) & ~HQV_ENABLE);
2455 
2456     if (videoFlag & VIDEO_1_INUSE)
2457         SaveVideoRegister(pVia, V1_CONTROL, VIAGETREG(V1_CONTROL) & ~V1_ENABLE);
2458     else
2459         SaveVideoRegister(pVia, V3_CONTROL, VIAGETREG(V3_CONTROL) & ~V3_ENABLE);
2460 
2461     FireVideoCommand(pVia, videoFlag, VIAGETREG(V_COMPOSE_MODE));
2462     FlushVidRegBuffer(pVia);
2463 
2464     if (pVia->HWDiff.dwHQVDisablePatch)
2465         ViaSeqMask(hwp, 0x2E, 0x10, 0x10);
2466 
2467     pVia->swov.SWVideo_ON = FALSE;
2468     pVia->VideoStatus &= ~VIDEO_SWOV_ON;
2469 }
2470