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