~ubuntu-branches/ubuntu/precise/xserver-xorg-video-openchrome-lts-trusty/precise-proposed

« back to all changes in this revision

Viewing changes to src/via_xv_overlay.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2014-05-15 12:47:33 UTC
  • Revision ID: package-import@ubuntu.com-20140515124733-qw5cb5dqlvejqsy3
Tags: upstream-0.3.3
ImportĀ upstreamĀ versionĀ 0.3.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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
 
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
 
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
 
137
viaWaitVBI(VIAPtr pVia)
 
138
{
 
139
    while (IN_VIDEO_DISPLAY) ;
 
140
}
 
141
 
 
142
static void
 
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
 
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
 
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
 
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
 
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_VM800:
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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 < 0)
 
1763
        top = 0;
 
1764
    else if (top > 2047)
 
1765
        top = 2047;
 
1766
 
 
1767
    if (bottom < 0)
 
1768
        bottom = 0;
 
1769
    else if (bottom > 2047)
 
1770
        bottom = 2047;
 
1771
 
 
1772
    if (left < 0)
 
1773
        left = 0;
 
1774
    else if (left > 2047)
 
1775
        left = 2047;
 
1776
 
 
1777
    if (right < 0)
 
1778
        right = 0;
 
1779
    else if (right > 2047)
 
1780
        right = 2047;
 
1781
 
 
1782
    if (videoFlag & VIDEO_1_INUSE) {
 
1783
        SaveVideoRegister(pVia, V1_WIN_END_Y, (right << 16) | bottom);
 
1784
        SaveVideoRegister(pVia, V1_WIN_START_Y, (left << 16) | top);
 
1785
    } else {
 
1786
        SaveVideoRegister(pVia, V3_WIN_END_Y, (right << 16) | bottom);
 
1787
        SaveVideoRegister(pVia, V3_WIN_START_Y, (left << 16) | top);
 
1788
    }
 
1789
}
 
1790
 
 
1791
/*
 
1792
 * Upd_Video()
 
1793
 */
 
1794
static Bool
 
1795
Upd_Video(xf86CrtcPtr crtc, unsigned long videoFlag,
 
1796
          unsigned long startAddr, LPDDUPDATEOVERLAY pUpdate,
 
1797
          unsigned long srcPitch,
 
1798
          unsigned long oriSrcWidth, unsigned long oriSrcHeight,
 
1799
          unsigned long deinterlaceMode,
 
1800
          unsigned long haveColorKey, unsigned long haveChromaKey,
 
1801
          unsigned long colorKeyLow, unsigned long colorKeyHigh,
 
1802
          unsigned long chromaKeyLow, unsigned long chromaKeyHigh)
 
1803
{
 
1804
    drmmode_crtc_private_ptr iga = crtc->driver_private;
 
1805
    ScrnInfoPtr pScrn = crtc->scrn;
 
1806
    VIAPtr pVia = VIAPTR(pScrn);
 
1807
    vgaHWPtr hwp = VGAHWPTR(pScrn);
 
1808
    VIAHWDiff *hwDiff = &pVia->HWDiff;
 
1809
    unsigned long vidCtl = 0, compose;
 
1810
    unsigned long srcWidth, srcHeight, dstWidth, dstHeight;
 
1811
    unsigned long zoomCtl = 0, miniCtl = 0;
 
1812
    unsigned long hqvCtl = 0;
 
1813
    unsigned long hqvFilterCtl = 0, hqvMiniCtl = 0;
 
1814
    unsigned long hqvScaleCtlH = 0, hqvScaleCtlV = 0;
 
1815
    unsigned long haveHQVzoomH = 0, haveHQVzoomV = 0;
 
1816
    unsigned long hqvSrcWidth = 0, hqvDstWidth = 0;
 
1817
    unsigned long hqvSrcFetch = 0, hqvOffset = 0;
 
1818
    unsigned long dwOffset = 0, fetch = 0, tmp = 0;
 
1819
    unsigned long proReg = 0;
 
1820
    int i;
 
1821
 
 
1822
    DBG_DD(ErrorF("videoflag=%ld\n", videoFlag));
 
1823
 
 
1824
    if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
 
1825
        proReg = PRO_HQV1_OFFSET;
 
1826
 
 
1827
    compose = ((VIAGETREG(V_COMPOSE_MODE)
 
1828
                & ~(SELECT_VIDEO_IF_COLOR_KEY
 
1829
                    | V1_COMMAND_FIRE | V3_COMMAND_FIRE))
 
1830
               | V_COMMAND_LOAD_VBI);
 
1831
 
 
1832
    DBG_DD(ErrorF("// Upd_Video:\n"));
 
1833
    DBG_DD(ErrorF("Modified rSrc  X (%ld,%ld) Y (%ld,%ld)\n",
 
1834
                  pUpdate->SrcLeft, pUpdate->SrcRight,
 
1835
                  pUpdate->SrcTop, pUpdate->SrcBottom));
 
1836
    DBG_DD(ErrorF("Modified rDest  X (%ld,%ld) Y (%ld,%ld)\n",
 
1837
                  pUpdate->DstLeft, pUpdate->DstRight,
 
1838
                  pUpdate->DstTop, pUpdate->DstBottom));
 
1839
 
 
1840
    dstWidth = pUpdate->DstRight - pUpdate->DstLeft;
 
1841
        /*if (pBIOSInfo->lvds && pBIOSInfo->lvds->status == XF86OutputStatusConnected &&
 
1842
                pBIOSInfo->Panel->Scale) {
 
1843
        * FIXME: We need to determine if the panel is using V1 or V3 *
 
1844
        float hfactor = (float)pBIOSInfo->Panel->NativeMode->Width
 
1845
                        / pScrn->currentMode->HDisplay;
 
1846
        dstWidth *= hfactor;
 
1847
    }*/
 
1848
 
 
1849
    pVia->swov.overlayRecordV1.dwWidth = dstWidth;
 
1850
    pVia->swov.overlayRecordV1.dwHeight = dstHeight =
 
1851
            pUpdate->DstBottom - pUpdate->DstTop;
 
1852
    srcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft;
 
1853
    srcHeight = (unsigned long)pUpdate->SrcBottom - pUpdate->SrcTop;
 
1854
    DBG_DD(ErrorF("===srcWidth= %ld \n", srcWidth));
 
1855
    DBG_DD(ErrorF("===srcHeight= %ld \n", srcHeight));
 
1856
 
 
1857
    vidCtl = ViaSetVidCtl(pVia, videoFlag);
 
1858
 
 
1859
    if (hwDiff->dwNeedV1Prefetch) {
 
1860
        DBG_DD(ErrorF("NEEDV1PREFETCH\n"));
 
1861
        vidCtl |= V1_PREFETCH_ON_3336;
 
1862
    }
 
1863
 
 
1864
    /*
 
1865
     * Enable video on secondary
 
1866
     */
 
1867
    if ((pVia->VideoEngine == VIDEO_ENGINE_CME ||
 
1868
         pVia->Chipset == VIA_VM800) && iga->index) {
 
1869
        /* V1_ON_SND_DISPLAY */
 
1870
        vidCtl |= V1_ON_SND_DISPLAY;
 
1871
        /* SECOND_DISPLAY_COLOR_KEY_ENABLE */
 
1872
        compose |= SECOND_DISPLAY_COLOR_KEY_ENABLE | 0x1;
 
1873
    }
 
1874
 
 
1875
    viaOverlayGetV1V3Format(pVia, (videoFlag & VIDEO_1_INUSE) ? 1 : 3,
 
1876
                            videoFlag, &vidCtl, &hqvCtl);
 
1877
 
 
1878
    if (hwDiff->dwThreeHQVBuffer) {    /* CLE_C0: HQV supports triple-buffering */
 
1879
        hqvCtl &= ~HQV_SW_FLIP;
 
1880
        hqvCtl |= HQV_TRIPLE_BUFF | HQV_FLIP_STATUS;
 
1881
    }
 
1882
 
 
1883
    /* Starting address of source and Source offset */
 
1884
    dwOffset = viaOverlayGetSrcStartAddress(pVia, videoFlag, pUpdate,
 
1885
                                            srcPitch, &hqvOffset);
 
1886
    DBG_DD(ErrorF("===dwOffset= 0x%lx \n", dwOffset));
 
1887
 
 
1888
    pVia->swov.overlayRecordV1.dwOffset = dwOffset;
 
1889
 
 
1890
    if (pVia->swov.SrcFourCC == FOURCC_YV12
 
1891
        || pVia->swov.SrcFourCC == FOURCC_I420
 
1892
        || pVia->swov.SrcFourCC == FOURCC_XVMC) {
 
1893
 
 
1894
        YCBCRREC YCbCr;
 
1895
 
 
1896
        if (videoFlag & VIDEO_HQV_INUSE) {
 
1897
            SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2,
 
1898
                          pVia->swov.overlayRecordV1.dwHQVAddr[0] + dwOffset,
 
1899
                          pVia->swov.overlayRecordV1.dwHQVAddr[1] + dwOffset,
 
1900
                          pVia->swov.overlayRecordV1.dwHQVAddr[2] + dwOffset);
 
1901
 
 
1902
            if (pVia->swov.SrcFourCC != FOURCC_XVMC) {
 
1903
                YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr,
 
1904
                                pVia->swov.overlayRecordV1.dwOffset,
 
1905
                                pVia->swov.overlayRecordV1.dwUVoffset,
 
1906
                                srcPitch, oriSrcHeight);
 
1907
                if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
 
1908
                    SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg,
 
1909
                                      YCbCr.dwY);
 
1910
                    SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U + proReg,
 
1911
                                      YCbCr.dwCB);
 
1912
                } else {
 
1913
                    SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y, YCbCr.dwY);
 
1914
                    SaveVideoRegister(pVia, HQV_SRC_STARTADDR_U, YCbCr.dwCR);
 
1915
                    SaveVideoRegister(pVia, HQV_SRC_STARTADDR_V, YCbCr.dwCB);
 
1916
                }
 
1917
            }
 
1918
        } else {
 
1919
            YCbCr = viaOverlayGetYCbCrStartAddress(videoFlag, startAddr,
 
1920
                            pVia->swov.overlayRecordV1.dwOffset,
 
1921
                            pVia->swov.overlayRecordV1.dwUVoffset,
 
1922
                            srcPitch, oriSrcHeight);
 
1923
 
 
1924
            if (videoFlag & VIDEO_1_INUSE) {
 
1925
                SaveVideoRegister(pVia, V1_STARTADDR_0, YCbCr.dwY);
 
1926
                SaveVideoRegister(pVia, V1_STARTADDR_CB0, YCbCr.dwCR);
 
1927
                SaveVideoRegister(pVia, V1_STARTADDR_CR0, YCbCr.dwCB);
 
1928
            } else
 
1929
                DBG_DD(ErrorF("Upd_Video(): "
 
1930
                              "We do not support YV12 with V3!\n"));
 
1931
        }
 
1932
    } else {
 
1933
        if (videoFlag & VIDEO_HQV_INUSE) {
 
1934
            hqvSrcWidth = (unsigned long)pUpdate->SrcRight - pUpdate->SrcLeft;
 
1935
            hqvDstWidth = (unsigned long)pUpdate->DstRight - pUpdate->DstLeft;
 
1936
 
 
1937
            if (hqvSrcWidth > hqvDstWidth)
 
1938
                dwOffset = dwOffset * hqvDstWidth / hqvSrcWidth;
 
1939
 
 
1940
            SetVideoStart(pVia, videoFlag, hwDiff->dwThreeHQVBuffer ? 3 : 2,
 
1941
                          pVia->swov.overlayRecordV1.dwHQVAddr[0] + hqvOffset,
 
1942
                          pVia->swov.overlayRecordV1.dwHQVAddr[1] + hqvOffset,
 
1943
                          pVia->swov.overlayRecordV1.dwHQVAddr[2] + hqvOffset);
 
1944
 
 
1945
            if (pVia->VideoEngine == VIDEO_ENGINE_CME)
 
1946
                SaveVideoRegister(pVia, 0x1cc + proReg, dwOffset);
 
1947
 
 
1948
            SaveVideoRegister(pVia, HQV_SRC_STARTADDR_Y + proReg, startAddr);
 
1949
        } else {
 
1950
            startAddr += dwOffset;
 
1951
            SetVideoStart(pVia, videoFlag, 1, startAddr, 0, 0);
 
1952
        }
 
1953
    }
 
1954
 
 
1955
    fetch = viaOverlayGetFetch(pVia, videoFlag,
 
1956
                               srcWidth, dstWidth, oriSrcWidth, &hqvSrcFetch);
 
1957
    DBG_DD(ErrorF("===fetch= 0x%lx\n", fetch));
 
1958
 
 
1959
#if 0
 
1960
    /* For DCT450 test-BOB INTERLEAVE */
 
1961
    if ((deinterlaceMode & DDOVER_INTERLEAVED)
 
1962
        && (deinterlaceMode & DDOVER_BOB)) {
 
1963
        if (videoFlag & VIDEO_HQV_INUSE)
 
1964
            hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE;
 
1965
        else
 
1966
            vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE;
 
1967
    } else if (deinterlaceMode & DDOVER_BOB) {
 
1968
        if (videoFlag & VIDEO_HQV_INUSE)
 
1969
            /* The HQV source data line count should be two times of the original line count */
 
1970
            hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE;
 
1971
        else
 
1972
            vidCtl |= V1_BOB_ENABLE;
 
1973
    }
 
1974
#endif
 
1975
 
 
1976
    if (videoFlag & VIDEO_HQV_INUSE) {
 
1977
        if (!(deinterlaceMode & DDOVER_INTERLEAVED)
 
1978
            && (deinterlaceMode & DDOVER_BOB))
 
1979
            SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight << 1);
 
1980
        else
 
1981
            SetHQVFetch(pVia, hqvSrcFetch, oriSrcHeight);
 
1982
 
 
1983
        if (pVia->swov.SrcFourCC == FOURCC_YV12
 
1984
            || pVia->swov.SrcFourCC == FOURCC_I420
 
1985
            || pVia->swov.SrcFourCC == FOURCC_XVMC) {
 
1986
            if (videoFlag & VIDEO_1_INUSE)
 
1987
                SaveVideoRegister(pVia, V1_STRIDE, srcPitch << 1);
 
1988
            else
 
1989
                SaveVideoRegister(pVia, V3_STRIDE, srcPitch << 1);
 
1990
 
 
1991
            if (pVia->HWDiff.dwHQVFetchByteUnit)
 
1992
                SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg,
 
1993
                                  ((srcPitch >> 1) << 16) | srcPitch |
 
1994
                                  HQV_FIFO_DEPTH_1);
 
1995
            else
 
1996
                SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg,
 
1997
                                  ((srcPitch >> 1) << 16) | srcPitch);
 
1998
 
 
1999
            SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, (srcPitch << 1));
 
2000
        } else {
 
2001
            if (videoFlag & VIDEO_1_INUSE)
 
2002
                SaveVideoRegister(pVia, V1_STRIDE, srcPitch);
 
2003
            else
 
2004
                SaveVideoRegister(pVia, V3_STRIDE, srcPitch);
 
2005
 
 
2006
            SaveVideoRegister(pVia, HQV_SRC_STRIDE + proReg, srcPitch);
 
2007
            SaveVideoRegister(pVia, HQV_DST_STRIDE + proReg, srcPitch);
 
2008
        }
 
2009
 
 
2010
    } else {
 
2011
        if (videoFlag & VIDEO_1_INUSE)
 
2012
            SaveVideoRegister(pVia, V1_STRIDE, srcPitch | (srcPitch << 15));
 
2013
        else
 
2014
            SaveVideoRegister(pVia, V3_STRIDE, srcPitch | (srcPitch << 15));
 
2015
    }
 
2016
 
 
2017
    /* Set destination window */
 
2018
    SetVideoWindow(pScrn, videoFlag, pUpdate);
 
2019
 
 
2020
    compose |= ALWAYS_SELECT_VIDEO;
 
2021
 
 
2022
    /* Set up X zoom factor */
 
2023
 
 
2024
    pVia->swov.overlayRecordV1.dwFetchAlignment = 0;
 
2025
 
 
2026
    if (!viaOverlayHQVCalcZoomWidth(pVia, videoFlag, srcWidth, dstWidth,
 
2027
                                    &zoomCtl, &miniCtl, &hqvFilterCtl,
 
2028
                                    &hqvMiniCtl, &hqvScaleCtlH, &haveHQVzoomH)) {
 
2029
        /* Need to scale (minify) too much - can't handle it. */
 
2030
        SetFetch(pVia, videoFlag, fetch);
 
2031
        FireVideoCommand(pVia, videoFlag, compose);
 
2032
        FlushVidRegBuffer(pVia);
 
2033
        return FALSE;
 
2034
    }
 
2035
 
 
2036
    SetFetch(pVia, videoFlag, fetch);
 
2037
 
 
2038
    /* Set up Y zoom factor */
 
2039
 
 
2040
    /* For DCT450 test-BOB INTERLEAVE */
 
2041
    if ((deinterlaceMode & DDOVER_INTERLEAVED)
 
2042
        && (deinterlaceMode & DDOVER_BOB)) {
 
2043
        if (!(videoFlag & VIDEO_HQV_INUSE)) {
 
2044
            srcHeight /= 2;
 
2045
            if (videoFlag & VIDEO_1_INUSE)
 
2046
                vidCtl |= V1_BOB_ENABLE | V1_FRAME_BASE;
 
2047
            else
 
2048
                vidCtl |= V3_BOB_ENABLE | V3_FRAME_BASE;
 
2049
        } else
 
2050
            hqvCtl |= HQV_FIELD_2_FRAME | HQV_FRAME_2_FIELD | HQV_DEINTERLACE;
 
2051
    } else if (deinterlaceMode & DDOVER_BOB) {
 
2052
        if (videoFlag & VIDEO_HQV_INUSE) {
 
2053
            srcHeight <<= 1;
 
2054
            hqvCtl |= HQV_FIELD_2_FRAME | HQV_DEINTERLACE;
 
2055
        } else {
 
2056
            if (videoFlag & VIDEO_1_INUSE)
 
2057
                vidCtl |= V1_BOB_ENABLE;
 
2058
            else
 
2059
                vidCtl |= V3_BOB_ENABLE;
 
2060
        }
 
2061
    }
 
2062
 
 
2063
    SetDisplayCount(pVia, videoFlag, srcWidth, srcHeight);
 
2064
 
 
2065
    if (!viaOverlayHQVCalcZoomHeight(pVia, srcHeight, dstHeight, &zoomCtl,
 
2066
                                     &miniCtl, &hqvFilterCtl, &hqvMiniCtl,
 
2067
                                     &hqvScaleCtlV, &haveHQVzoomV)) {
 
2068
        /* Need to scale (minify) too much - can't handle it. */
 
2069
        FireVideoCommand(pVia, videoFlag, compose);
 
2070
        FlushVidRegBuffer(pVia);
 
2071
        return FALSE;
 
2072
    }
 
2073
 
 
2074
    SetupFIFOs(pVia, videoFlag, miniCtl, srcWidth);
 
2075
 
 
2076
    if (videoFlag & VIDEO_HQV_INUSE) {
 
2077
        miniCtl = 0;
 
2078
 
 
2079
        if (haveHQVzoomH || haveHQVzoomV) {
 
2080
            tmp = 0;
 
2081
 
 
2082
            if (haveHQVzoomH) {
 
2083
                miniCtl = V1_X_INTERPOLY;
 
2084
                /* Disable X interpolation if the height exceeds
 
2085
                 * the maximum supported by the hardware */
 
2086
                if (srcHeight >= pVia->swov.maxHInterp)
 
2087
                    miniCtl &= ~V1_X_INTERPOLY;
 
2088
                tmp = zoomCtl & 0xffff0000;
 
2089
            }
 
2090
 
 
2091
            if (haveHQVzoomV) {
 
2092
                miniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
 
2093
                /* Disable Y interpolation if the width exceeds
 
2094
                 * the maximum supported by the hardware */
 
2095
                if (srcWidth >= pVia->swov.maxWInterp)
 
2096
                    miniCtl &= ~V1_Y_INTERPOLY;
 
2097
                tmp |= zoomCtl & 0x0000ffff;
 
2098
                hqvFilterCtl &= 0xfffdffff;
 
2099
            }
 
2100
 
 
2101
            /* Temporary fix for 2D bandwidth problem. 2002/08/01 */
 
2102
            if (pVia->swov.gdwUseExtendedFIFO)
 
2103
                miniCtl &= ~V1_Y_INTERPOLY;
 
2104
 
 
2105
            SetMiniAndZoom(pVia, videoFlag, miniCtl, tmp);
 
2106
        } else {
 
2107
            if (srcHeight == dstHeight)
 
2108
                hqvFilterCtl &= 0xfffdffff;
 
2109
            SetMiniAndZoom(pVia, videoFlag, 0, 0);
 
2110
        }
 
2111
        if (hwDiff->dwNewScaleCtl) {
 
2112
                SaveVideoRegister(pVia, HQV_H_SCALE_CONTROL + proReg, hqvScaleCtlH);
 
2113
                SaveVideoRegister(pVia, HQV_V_SCALE_CONTROL + proReg, hqvScaleCtlV);
 
2114
        } else {
 
2115
                SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
 
2116
        }
 
2117
        SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
 
2118
    } else
 
2119
        SetMiniAndZoom(pVia, videoFlag, miniCtl, zoomCtl);
 
2120
 
 
2121
    if (haveColorKey)
 
2122
        compose = SetColorKey(pVia, videoFlag, colorKeyLow, colorKeyHigh,
 
2123
                              compose);
 
2124
 
 
2125
    if (haveChromaKey)
 
2126
        compose = SetChromaKey(pVia, videoFlag, chromaKeyLow, chromaKeyHigh,
 
2127
                               miniCtl, compose);
 
2128
 
 
2129
    if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
 
2130
        SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL1),0);
 
2131
        SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL3),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
 
2132
        if ((pVia->Chipset == VIA_VX800) ||
 
2133
            (pVia->Chipset == VIA_VX855) ||
 
2134
            (pVia->Chipset == VIA_VX900)) {
 
2135
            SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL2),0);
 
2136
            SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL4),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
 
2137
            if ((pVia->Chipset == VIA_VX855) ||
 
2138
                (pVia->Chipset == VIA_VX900)) {
 
2139
                SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL1,0);
 
2140
                SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
 
2141
                SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL2,0);
 
2142
                SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
 
2143
                SaveVideoRegister(pVia, HQV_BACKGROUND_DATA_OFFSET,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
 
2144
                SaveVideoRegister(pVia, HQV_EXTENDED_CONTROL,0);
 
2145
                /*0x3e0*/
 
2146
                SaveVideoRegister(pVia, HQV_SUBP_HSCALE_CTRL,0);
 
2147
                /*0x3e8*/
 
2148
                SaveVideoRegister(pVia, HQV_SUBP_VSCALE_CTRL,0);
 
2149
            }
 
2150
 
 
2151
            if (pVia->Chipset == VIA_VX900) {
 
2152
 
 
2153
                SaveVideoRegister(pVia, HQV_SHARPNESS_DECODER_HANDSHAKE_CTRL_410, 0);        
 
2154
            }
 
2155
 
 
2156
            // TODO Need to be tested on VX800
 
2157
            /* 0x3B8 */
 
2158
            SaveVideoRegister(pVia, HQV_DEFAULT_VIDEO_COLOR, HQV_FIX_COLOR);
 
2159
    
 
2160
        }
 
2161
    }
 
2162
 
 
2163
    /* Set up video control */
 
2164
    if (videoFlag & VIDEO_HQV_INUSE) {
 
2165
 
 
2166
        if (!pVia->swov.SWVideo_ON) {
 
2167
            DBG_DD(ErrorF("    First HQV\n"));
 
2168
 
 
2169
            FlushVidRegBuffer(pVia);
 
2170
 
 
2171
            DBG_DD(ErrorF(" Wait flips"));
 
2172
 
 
2173
            if (hwDiff->dwHQVInitPatch) {
 
2174
                DBG_DD(ErrorF(" Initializing HQV twice ..."));
 
2175
                for (i = 0; i < 2; i++) {
 
2176
                    viaWaitHQVFlipClear(pVia,
 
2177
                                        ((hqvCtl & ~HQV_SW_FLIP) |
 
2178
                                         HQV_FLIP_STATUS) & ~HQV_ENABLE);
 
2179
                    VIASETREG(HQV_CONTROL + proReg, hqvCtl);
 
2180
                    viaWaitHQVFlip(pVia);
 
2181
                }
 
2182
                DBG_DD(ErrorF(" done.\n"));
 
2183
            } else {               /* CLE_C0 */
 
2184
                CARD32 volatile *HQVCtrl =
 
2185
                        (CARD32 volatile *)(pVia->MapBase + HQV_CONTROL +
 
2186
                                            proReg);
 
2187
 
 
2188
                /* Check that HQV is idle */
 
2189
                DBG_DD(ErrorF("HQV control wf - %08lx\n", *HQVCtrl));
 
2190
                while (!(*HQVCtrl & HQV_IDLE)) {
 
2191
                    DBG_DD(ErrorF("HQV control busy - %08lx\n", *HQVCtrl));
 
2192
                    usleep(1);
 
2193
                }
 
2194
 
 
2195
                VIASETREG(HQV_CONTROL + proReg, hqvCtl & ~HQV_SW_FLIP);
 
2196
                VIASETREG(HQV_CONTROL + proReg, hqvCtl | HQV_SW_FLIP);
 
2197
 
 
2198
                DBG_DD(ErrorF("HQV control wf5 - %08lx\n", *HQVCtrl));
 
2199
                DBG_DD(ErrorF(" Wait flips5"));
 
2200
 
 
2201
                if (pVia->VideoEngine != VIDEO_ENGINE_CME) {
 
2202
                    for (i = 0; (i < 50) && !(*HQVCtrl & HQV_FLIP_STATUS);
 
2203
                         i++) {
 
2204
                        DBG_DD(ErrorF(" HQV wait %d %08lx\n", i, *HQVCtrl));
 
2205
                        *HQVCtrl |= HQV_SW_FLIP | HQV_FLIP_STATUS;
 
2206
                        usleep(1);
 
2207
                    }
 
2208
                } else {
 
2209
                    viaWaitHQVFlip(pVia);
 
2210
                }
 
2211
 
 
2212
                DBG_DD(ErrorF(" Wait flips6"));
 
2213
            }
 
2214
 
 
2215
            if (videoFlag & VIDEO_1_INUSE) {
 
2216
                VIASETREG(V1_CONTROL, vidCtl);
 
2217
                VIASETREG(V_COMPOSE_MODE, compose | V1_COMMAND_FIRE);
 
2218
                if (pVia->swov.gdwUseExtendedFIFO) {
 
2219
                    /* Set Display FIFO */
 
2220
                    DBG_DD(ErrorF(" Wait flips7"));
 
2221
                    viaWaitVBI(pVia);
 
2222
                    DBG_DD(ErrorF(" Wait flips 8"));
 
2223
                    hwp->writeSeq(hwp, 0x17, 0x2F);
 
2224
                    ViaSeqMask(hwp, 0x16, 0x14, 0x1F);
 
2225
                    hwp->writeSeq(hwp, 0x18, 0x56);
 
2226
                    DBG_DD(ErrorF(" Wait flips 9"));
 
2227
                }
 
2228
            } else {
 
2229
                DBG_DD(ErrorF(" Wait flips 10"));
 
2230
                VIASETREG(V3_CONTROL, vidCtl);
 
2231
                VIASETREG(V_COMPOSE_MODE, compose | V3_COMMAND_FIRE);
 
2232
            }
 
2233
            DBG_DD(ErrorF(" Done flips"));
 
2234
        } else {
 
2235
            DBG_DD(ErrorF("    Normal called\n"));
 
2236
            SaveVideoRegister(pVia, HQV_CONTROL + proReg,
 
2237
                              hqvCtl | HQV_FLIP_STATUS);
 
2238
            SetVideoControl(pVia, videoFlag, vidCtl);
 
2239
            FireVideoCommand(pVia, videoFlag, compose);
 
2240
            viaWaitHQVDone(pVia);
 
2241
            FlushVidRegBuffer(pVia);
 
2242
        }
 
2243
    } else {
 
2244
        SetVideoControl(pVia, videoFlag, vidCtl);
 
2245
        FireVideoCommand(pVia, videoFlag, compose);
 
2246
        viaWaitHQVDone(pVia);
 
2247
        FlushVidRegBuffer(pVia);
 
2248
    }
 
2249
    pVia->swov.SWVideo_ON = TRUE;
 
2250
 
 
2251
    DBG_DD(ErrorF(" Done Upd_Video"));
 
2252
 
 
2253
    return TRUE;
 
2254
 
 
2255
}  /* Upd_Video */
 
2256
 
 
2257
/*
 
2258
 *  VIAVidUpdateOverlay()
 
2259
 *  Parameters:   src rectangle, dst rectangle, colorkey...
 
2260
 *  Return value: unsigned long of state
 
2261
 *  Note: updates the overlay image parameter.
 
2262
 */
 
2263
Bool
 
2264
VIAVidUpdateOverlay(xf86CrtcPtr crtc, LPDDUPDATEOVERLAY pUpdate)
 
2265
{
 
2266
    ScrnInfoPtr pScrn = crtc->scrn;
 
2267
    VIAPtr pVia = VIAPTR(pScrn);
 
2268
    OVERLAYRECORD *ovlV1 = &pVia->swov.overlayRecordV1;
 
2269
 
 
2270
    unsigned long flags = pUpdate->dwFlags;
 
2271
    unsigned long videoFlag = 0;
 
2272
    unsigned long startAddr = 0;
 
2273
    unsigned long deinterlaceMode = 0;
 
2274
 
 
2275
    unsigned long haveColorKey = 0, haveChromaKey = 0;
 
2276
    unsigned long colorKeyLow = 0, colorKeyHigh = 0;
 
2277
    unsigned long chromaKeyLow = 0, chromaKeyHigh = 0;
 
2278
 
 
2279
    unsigned long scrnWidth, scrnHeight;
 
2280
    int dstTop, dstBottom, dstLeft, dstRight;
 
2281
    int panDX, panDY;               /* Panning delta */
 
2282
 
 
2283
    unsigned long proReg = 0;
 
2284
 
 
2285
    panDX = pVia->swov.panning_x;
 
2286
    panDY = pVia->swov.panning_y;
 
2287
    pVia->swov.oldPanningX = pVia->swov.panning_x;
 
2288
    pVia->swov.oldPanningY = pVia->swov.panning_y;
 
2289
 
 
2290
    pUpdate->DstLeft -= panDX;
 
2291
    pUpdate->DstTop -= panDY;
 
2292
    pUpdate->DstRight -= panDX;
 
2293
    pUpdate->DstBottom -= panDY;
 
2294
 
 
2295
    DBG_DD(ErrorF("Raw rSrc  X (%ld,%ld) Y (%ld,%ld)\n",
 
2296
                  pUpdate->SrcLeft, pUpdate->SrcRight,
 
2297
                  pUpdate->SrcTop, pUpdate->SrcBottom));
 
2298
    DBG_DD(ErrorF("Raw rDest  X (%ld,%ld) Y (%ld,%ld)\n",
 
2299
                  pUpdate->DstLeft, pUpdate->DstRight,
 
2300
                  pUpdate->DstTop, pUpdate->DstBottom));
 
2301
 
 
2302
    if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
 
2303
        (pVia->swov.SrcFourCC == FOURCC_RV15) ||
 
2304
        (pVia->swov.SrcFourCC == FOURCC_RV16) ||
 
2305
        (pVia->swov.SrcFourCC == FOURCC_RV32) ||
 
2306
        (pVia->swov.SrcFourCC == FOURCC_YV12) ||
 
2307
        (pVia->swov.SrcFourCC == FOURCC_I420) ||
 
2308
        (pVia->swov.SrcFourCC == FOURCC_XVMC)) {
 
2309
        videoFlag = pVia->swov.gdwVideoFlagSW;
 
2310
    }
 
2311
 
 
2312
    if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
 
2313
        proReg = PRO_HQV1_OFFSET;
 
2314
 
 
2315
    flags |= DDOVER_INTERLEAVED;
 
2316
 
 
2317
    /* Disable destination color keying if the alpha window is in use. */
 
2318
    if (pVia->swov.gdwAlphaEnabled)
 
2319
        flags &= ~DDOVER_KEYDEST;
 
2320
 
 
2321
    ResetVidRegBuffer(pVia);
 
2322
 
 
2323
    /* For SW decode HW overlay use */
 
2324
    startAddr = VIAGETREG(HQV_SRC_STARTADDR_Y + proReg);
 
2325
 
 
2326
    if (flags & DDOVER_KEYDEST) {
 
2327
        haveColorKey = 1;
 
2328
        colorKeyLow = pUpdate->dwColorSpaceLowValue;
 
2329
    }
 
2330
 
 
2331
    if (flags & DDOVER_INTERLEAVED)
 
2332
        deinterlaceMode |= DDOVER_INTERLEAVED;
 
2333
 
 
2334
    if (flags & DDOVER_BOB)
 
2335
        deinterlaceMode |= DDOVER_BOB;
 
2336
 
 
2337
    if ((pVia->ChipId == PCI_CHIP_CLE3122)
 
2338
        && (pScrn->currentMode->HDisplay > 1024)) {
 
2339
        DBG_DD(ErrorF("UseExtendedFIFO\n"));
 
2340
        pVia->swov.gdwUseExtendedFIFO = 1;
 
2341
    } else
 
2342
        pVia->swov.gdwUseExtendedFIFO = 0;
 
2343
 
 
2344
    /* Figure out actual rSrc rectangle */
 
2345
 
 
2346
    dstLeft = pUpdate->DstLeft;
 
2347
    dstTop = pUpdate->DstTop;
 
2348
    dstRight = pUpdate->DstRight;
 
2349
    dstBottom = pUpdate->DstBottom;
 
2350
 
 
2351
    scrnWidth = pScrn->currentMode->HDisplay;
 
2352
    scrnHeight = pScrn->currentMode->VDisplay;
 
2353
 
 
2354
    if (dstLeft < 0) {
 
2355
        pUpdate->SrcLeft = ((((-dstLeft) * ovlV1->dwV1OriWidth) +
 
2356
                             ((dstRight - dstLeft) >> 1))
 
2357
                            / (dstRight - dstLeft));
 
2358
    }
 
2359
    if (dstRight > scrnWidth) {
 
2360
        pUpdate->SrcRight = ((((scrnWidth - dstLeft) * ovlV1->dwV1OriWidth) +
 
2361
                              ((dstRight - dstLeft) >> 1))
 
2362
                             / (dstRight - dstLeft));
 
2363
    }
 
2364
    if (dstTop < 0) {
 
2365
        pUpdate->SrcTop = ((((-dstTop) * ovlV1->dwV1OriHeight) +
 
2366
                            ((dstBottom - dstTop) >> 1))
 
2367
                           / (dstBottom - dstTop));
 
2368
    }
 
2369
    if (dstBottom > scrnHeight) {
 
2370
        pUpdate->SrcBottom = ((((scrnHeight - dstTop) * ovlV1->dwV1OriHeight) +
 
2371
                               ((dstBottom - dstTop) >> 1))
 
2372
                              / (dstBottom - dstTop));
 
2373
    }
 
2374
 
 
2375
    /* Save modified src & original dest rectangle parameters */
 
2376
 
 
2377
    if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
 
2378
        (pVia->swov.SrcFourCC == FOURCC_RV15) ||
 
2379
        (pVia->swov.SrcFourCC == FOURCC_RV16) ||
 
2380
        (pVia->swov.SrcFourCC == FOURCC_RV32) ||
 
2381
        (pVia->swov.SrcFourCC == FOURCC_YV12) ||
 
2382
        (pVia->swov.SrcFourCC == FOURCC_I420) ||
 
2383
        (pVia->swov.SrcFourCC == FOURCC_XVMC)) {
 
2384
        pVia->swov.SWDevice.gdwSWDstLeft = pUpdate->DstLeft + panDX;
 
2385
        pVia->swov.SWDevice.gdwSWDstTop = pUpdate->DstTop + panDY;
 
2386
        pVia->swov.SWDevice.gdwSWDstWidth =
 
2387
                pUpdate->DstRight - pUpdate->DstLeft;
 
2388
        pVia->swov.SWDevice.gdwSWDstHeight =
 
2389
                pUpdate->DstBottom - pUpdate->DstTop;
 
2390
 
 
2391
        pVia->swov.SWDevice.gdwSWSrcWidth = ovlV1->dwV1SrcWidth =
 
2392
                pUpdate->SrcRight - pUpdate->SrcLeft;
 
2393
        pVia->swov.SWDevice.gdwSWSrcHeight = ovlV1->dwV1SrcHeight =
 
2394
                pUpdate->SrcBottom - pUpdate->SrcTop;
 
2395
    }
 
2396
 
 
2397
    ovlV1->dwV1SrcLeft = pUpdate->SrcLeft;
 
2398
    ovlV1->dwV1SrcRight = pUpdate->SrcRight;
 
2399
    ovlV1->dwV1SrcTop = pUpdate->SrcTop;
 
2400
    ovlV1->dwV1SrcBot = pUpdate->SrcBottom;
 
2401
 
 
2402
    /* Figure out actual rDest rectangle */
 
2403
 
 
2404
    pUpdate->DstLeft = (dstLeft < 0) ? 0 : dstLeft;
 
2405
    pUpdate->DstTop = (dstTop < 0) ? 0 : dstTop;
 
2406
    if (pUpdate->DstTop >= scrnHeight)
 
2407
        pUpdate->DstTop = scrnHeight - 1;
 
2408
    pUpdate->DstRight = (dstRight > scrnWidth) ? scrnWidth : dstRight;
 
2409
    pUpdate->DstBottom = (dstBottom > scrnHeight) ? scrnHeight : dstBottom;
 
2410
 
 
2411
    /* Update the overlay */
 
2412
 
 
2413
    if (!Upd_Video(crtc, videoFlag, startAddr, pUpdate,
 
2414
                   pVia->swov.SWDevice.dwPitch, ovlV1->dwV1OriWidth,
 
2415
                   ovlV1->dwV1OriHeight, deinterlaceMode, haveColorKey,
 
2416
                   haveChromaKey, colorKeyLow, colorKeyHigh, chromaKeyLow,
 
2417
                   chromaKeyHigh))
 
2418
        return FALSE;
 
2419
 
 
2420
    pVia->swov.SWVideo_ON = FALSE;
 
2421
 
 
2422
    return TRUE;
 
2423
 
 
2424
}  /* VIAVidUpdateOverlay */
 
2425
 
 
2426
/*
 
2427
 *
 
2428
 */
 
2429
void
 
2430
ViaOverlayHide(ScrnInfoPtr pScrn)
 
2431
{
 
2432
    VIAPtr pVia = VIAPTR(pScrn);
 
2433
    vgaHWPtr hwp = VGAHWPTR(pScrn);
 
2434
    CARD32 videoFlag = 0;
 
2435
    unsigned long proReg = 0;
 
2436
 
 
2437
    if ((pVia->swov.SrcFourCC == FOURCC_YUY2) ||
 
2438
        (pVia->swov.SrcFourCC == FOURCC_RV15) ||
 
2439
        (pVia->swov.SrcFourCC == FOURCC_RV16) ||
 
2440
        (pVia->swov.SrcFourCC == FOURCC_RV32) ||
 
2441
        (pVia->swov.SrcFourCC == FOURCC_YV12) ||
 
2442
        (pVia->swov.SrcFourCC == FOURCC_I420) ||
 
2443
        (pVia->swov.SrcFourCC == FOURCC_XVMC))
 
2444
        videoFlag = pVia->swov.gdwVideoFlagSW;
 
2445
 
 
2446
    if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
 
2447
        proReg = PRO_HQV1_OFFSET;
 
2448
 
 
2449
    ResetVidRegBuffer(pVia);
 
2450
 
 
2451
    if (pVia->HWDiff.dwHQVDisablePatch)
 
2452
        ViaSeqMask(hwp, 0x2E, 0x00, 0x10);
 
2453
 
 
2454
    SaveVideoRegister(pVia, V_FIFO_CONTROL, V1_FIFO_PRETHRESHOLD12 |
 
2455
                      V1_FIFO_THRESHOLD8 | V1_FIFO_DEPTH16);
 
2456
    SaveVideoRegister(pVia, ALPHA_V3_FIFO_CONTROL,
 
2457
                      ALPHA_FIFO_THRESHOLD4 | ALPHA_FIFO_DEPTH8 |
 
2458
                      V3_FIFO_THRESHOLD24 | V3_FIFO_DEPTH32);
 
2459
 
 
2460
    if (videoFlag & VIDEO_HQV_INUSE)
 
2461
        SaveVideoRegister(pVia, HQV_CONTROL + proReg,
 
2462
                          VIAGETREG(HQV_CONTROL + proReg) & ~HQV_ENABLE);
 
2463
 
 
2464
    if (videoFlag & VIDEO_1_INUSE)
 
2465
        SaveVideoRegister(pVia, V1_CONTROL, VIAGETREG(V1_CONTROL) & ~V1_ENABLE);
 
2466
    else
 
2467
        SaveVideoRegister(pVia, V3_CONTROL, VIAGETREG(V3_CONTROL) & ~V3_ENABLE);
 
2468
 
 
2469
    FireVideoCommand(pVia, videoFlag, VIAGETREG(V_COMPOSE_MODE));
 
2470
    FlushVidRegBuffer(pVia);
 
2471
 
 
2472
    if (pVia->HWDiff.dwHQVDisablePatch)
 
2473
        ViaSeqMask(hwp, 0x2E, 0x10, 0x10);
 
2474
 
 
2475
    pVia->swov.SWVideo_ON = FALSE;
 
2476
    pVia->VideoStatus &= ~VIDEO_SWOV_ON;
 
2477
}