via_xv.c revision 90b17f1b
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25/*
26 * I N C L U D E S
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "xf86.h"
34#include "xf86_OSproc.h"
35
36#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
37#include "xf86Resources.h"
38#endif
39
40#include "compiler.h"
41#include "xf86Pci.h"
42#include "regionstr.h"
43#include "via_driver.h"
44
45#include "xf86xv.h"
46#include <X11/extensions/Xv.h>
47#include "dixstruct.h"
48#include "via_xvpriv.h"
49#include "fourcc.h"
50
51/*
52 * D E F I N E
53 */
54#define OFF_DELAY       200           /* milliseconds */
55#define FREE_DELAY      60000
56#define PARAMSIZE       1024
57#define SLICESIZE       65536
58#define OFF_TIMER       0x01
59#define FREE_TIMER      0x02
60#define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
61#define VIA_MAX_XVIMAGE_X 1920
62#define VIA_MAX_XVIMAGE_Y 1200
63
64#define LOW_BAND 0x0CB0
65#define MID_BAND 0x1f10
66
67#define  XV_IMAGE          0
68#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
69#ifndef XvExtension
70void
71viaInitVideo(ScreenPtr pScreen)
72{
73}
74
75void
76viaExitVideo(ScrnInfoPtr pScrn)
77{
78}
79void
80viaSaveVideo(ScrnInfoPtr pScrn)
81{
82}
83void
84viaRestoreVideo(ScrnInfoPtr pScrn)
85{
86}
87void
88VIAVidAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
89{
90}
91#else
92
93static vidCopyFunc viaFastVidCpy = NULL;
94
95/*
96 *  F U N C T I O N   D E C L A R A T I O N
97 */
98static unsigned viaSetupAdaptors(ScreenPtr pScreen,
99    XF86VideoAdaptorPtr ** adaptors);
100static void viaStopVideo(ScrnInfoPtr, pointer, Bool);
101static void viaQueryBestSize(ScrnInfoPtr, Bool,
102    short, short, short, short, unsigned int *, unsigned int *, pointer);
103static int viaQueryImageAttributes(ScrnInfoPtr,
104    int, unsigned short *, unsigned short *, int *, int *);
105static int viaGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
106static int viaSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
107static int viaPutImage(ScrnInfoPtr, short, short, short, short, short, short,
108    short, short, int, unsigned char *, short, short, Bool,
109    RegionPtr, pointer, DrawablePtr);
110static void UVBlit(unsigned char *dest,
111    const unsigned char *uBuffer,
112    const unsigned char *vBuffer,
113    unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines);
114static void nv12Blit(unsigned char *nv12Chroma,
115    const unsigned char *uBuffer,
116    const unsigned char *vBuffer,
117    unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines);
118
119static Atom xvBrightness, xvContrast, xvColorKey, xvHue, xvSaturation,
120    xvAutoPaint;
121
122/*
123 *  S T R U C T S
124 */
125/* client libraries expect an encoding */
126static XF86VideoEncodingRec DummyEncoding[1] = {
127    {XV_IMAGE, "XV_IMAGE", VIA_MAX_XVIMAGE_X, VIA_MAX_XVIMAGE_Y, {1, 1}},
128};
129
130#define NUM_FORMATS_G 9
131
132static XF86VideoFormatRec FormatsG[NUM_FORMATS_G] = {
133    {8, TrueColor},               /* Dithered */
134    {8, PseudoColor},               /* Using .. */
135    {8, StaticColor},
136    {8, GrayScale},
137    {8, StaticGray},               /* .. TexelLUT */
138    {16, TrueColor},
139    {24, TrueColor},
140    {16, DirectColor},
141    {24, DirectColor}
142};
143
144#define NUM_ATTRIBUTES_G 6
145
146static XF86AttributeRec AttributesG[NUM_ATTRIBUTES_G] = {
147    {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
148    {XvSettable | XvGettable, 0, 10000, "XV_BRIGHTNESS"},
149    {XvSettable | XvGettable, 0, 20000, "XV_CONTRAST"},
150    {XvSettable | XvGettable, 0, 20000, "XV_SATURATION"},
151    {XvSettable | XvGettable, -180, 180, "XV_HUE"},
152    {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"}
153};
154
155#define NUM_IMAGES_G 7
156
157static XF86ImageRec ImagesG[NUM_IMAGES_G] = {
158    XVIMAGE_YUY2,
159    XVIMAGE_YV12,
160    XVIMAGE_I420,
161    {
162        /*
163         * Below, a dummy picture type that is used in XvPutImage only to do
164         * an overlay update. Introduced for the XvMC client lib.
165         * Defined to have a zero data size.
166         */
167
168        FOURCC_XVMC,
169        XvYUV,
170        LSBFirst,
171        {   'V', 'I', 'A', 0x00,
172            0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0xAA, 0x00,
173            0x38, 0x9B, 0x71},
174        12,
175        XvPlanar,
176        1,
177        0, 0, 0, 0,
178        8, 8, 8,
179        1, 2, 2,
180        1, 2, 2,
181        {   'Y', 'V', 'U',
182            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
183            0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
184        XvTopToBottom},
185    { /* RGB 555 */
186        FOURCC_RV15,
187        XvRGB,
188        LSBFirst,
189        {   'R', 'V', '1', '5',
190            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191            0x00, 0x00, 0x00},
192        16,
193        XvPacked,
194        1,
195        15, 0x7C00, 0x03E0, 0x001F,
196        0, 0, 0,
197        0, 0, 0,
198        0, 0, 0,
199        {   'R', 'V', 'B', 0,
200            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201            0, 0, 0, 0, 0, 0, 0, 0, 0},
202        XvTopToBottom},
203    { /* RGB 565 */
204        FOURCC_RV16,
205        XvRGB,
206        LSBFirst,
207        {   'R', 'V', '1', '6',
208            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209            0x00, 0x00, 0x00},
210        16,
211        XvPacked,
212        1,
213        16, 0xF800, 0x07E0, 0x001F,
214        0, 0, 0,
215        0, 0, 0,
216        0, 0, 0,
217        {   'R', 'V', 'B', 0,
218            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219            0, 0, 0, 0, 0, 0, 0, 0, 0},
220        XvTopToBottom},
221    { /* RGB 888 */
222        FOURCC_RV32,
223        XvRGB,
224        LSBFirst,
225        {   'R', 'V', '3', '2',
226            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227            0x00, 0x00, 0x00},
228        32,
229        XvPacked,
230        1,
231        24, 0xff0000, 0x00ff00, 0x0000ff,
232        0, 0, 0,
233        0, 0, 0,
234        0, 0, 0,
235        {   'R', 'V', 'B', 0,
236            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
237            0, 0, 0, 0, 0, 0, 0, 0, 0},
238        XvTopToBottom}
239
240};
241
242static char *XvAdaptorName[XV_ADAPT_NUM] = {
243    "XV_SWOV"
244};
245
246static XF86VideoAdaptorPtr viaAdaptPtr[XV_ADAPT_NUM];
247static XF86VideoAdaptorPtr *allAdaptors;
248static unsigned numAdaptPort[XV_ADAPT_NUM] = { 1 };
249
250/*
251 *  F U N C T I O N
252 */
253
254/*
255 *   Decide if the mode support video overlay. This depends on the bandwidth
256 *   of the mode and the type of RAM available.
257 */
258
259static Bool
260DecideOverlaySupport(xf86CrtcPtr crtc)
261{
262    DisplayModePtr mode = &crtc->desiredMode;
263    ScrnInfoPtr pScrn = crtc->scrn;
264    VIAPtr pVia = VIAPTR(pScrn);
265
266#ifdef HAVE_DEBUG
267    if (pVia->disableXvBWCheck)
268        return TRUE;
269#endif
270
271    /* Small trick here. We keep the height in 16's of lines and width in 32's
272     * to avoid numeric overflow */
273
274    if (pVia->ChipId != PCI_CHIP_VT3205 &&
275        pVia->ChipId != PCI_CHIP_VT3204 &&
276        pVia->ChipId != PCI_CHIP_VT3259 &&
277        pVia->ChipId != PCI_CHIP_VT3314 &&
278        pVia->ChipId != PCI_CHIP_VT3327 &&
279        pVia->ChipId != PCI_CHIP_VT3336 &&
280        pVia->ChipId != PCI_CHIP_VT3409 &&
281        pVia->ChipId != PCI_CHIP_VT3410 &&
282        pVia->ChipId != PCI_CHIP_VT3364 &&
283        pVia->ChipId != PCI_CHIP_VT3324 &&
284        pVia->ChipId != PCI_CHIP_VT3353) {
285        CARD32 bandwidth = (mode->HDisplay >> 4) * (mode->VDisplay >> 5) *
286                            pScrn->bitsPerPixel * mode->VRefresh;
287
288        switch (pVia->MemClk) {
289        case VIA_MEM_SDR100:           /* No overlay without DDR */
290        case VIA_MEM_SDR133:
291            return FALSE;
292        case VIA_MEM_DDR200:
293            /* Basic limit for DDR200 is about this */
294            if (bandwidth > 1800000)
295                return FALSE;
296            /* But we have constraints at higher than 800x600 */
297            if (mode->HDisplay > 800) {
298                if (pScrn->bitsPerPixel != 8)
299                    return FALSE;
300                if (mode->VDisplay > 768)
301                    return FALSE;
302                if (mode->VRefresh > 60)
303                    return FALSE;
304            }
305            return TRUE;
306        case 0:               /*      FIXME: Why does my CLE266 report 0? */
307        case VIA_MEM_DDR266:
308            if (bandwidth > 7901250)
309                return FALSE;
310            return TRUE;
311        }
312        return FALSE;
313
314    } else {
315        unsigned width, height, refresh, dClock;
316        float mClock, memEfficiency, needBandWidth, totalBandWidth;
317
318        switch (pVia->MemClk) {
319            case VIA_MEM_SDR100:
320                mClock = 50;           /*HW base on 128 bit */
321                memEfficiency = (float)SINGLE_3205_100;
322                break;
323            case VIA_MEM_SDR133:
324                mClock = 66.5;
325                memEfficiency = (float)SINGLE_3205_100;
326                break;
327            case VIA_MEM_DDR200:
328                mClock = 100;
329                memEfficiency = (float)SINGLE_3205_100;
330                break;
331            case VIA_MEM_DDR266:
332                mClock = 133;
333                memEfficiency = (float)SINGLE_3205_133;
334                break;
335            case VIA_MEM_DDR333:
336                mClock = 166;
337                memEfficiency = (float)SINGLE_3205_133;
338                break;
339            case VIA_MEM_DDR400:
340                mClock = 200;
341                memEfficiency = (float)SINGLE_3205_133;
342                break;
343            case VIA_MEM_DDR533:
344                mClock = 266;
345                memEfficiency = (float)SINGLE_3205_133;
346                break;
347            case VIA_MEM_DDR667:
348                mClock = 333;
349                memEfficiency = (float)SINGLE_3205_133;
350                break;
351            case VIA_MEM_DDR800:
352                mClock = 400;
353                memEfficiency = (float)SINGLE_3205_133;
354                break;
355            case VIA_MEM_DDR1066:
356                mClock = 533;
357                memEfficiency = (float)SINGLE_3205_133;
358                break;
359            default:
360                ErrorF("Unknow DRAM Type!\n");
361                mClock = 166;
362                memEfficiency = (float)SINGLE_3205_133;
363                break;
364        }
365
366        width = mode->HDisplay;
367        height = mode->VDisplay;
368        refresh = mode->VRefresh;
369
370        if (refresh==0) {
371            refresh=60;
372            ErrorF("Unable to fetch vertical refresh value, needed for bandwidth calculation.\n");
373        }
374
375        /*
376         * Approximative, VERY conservative formula in some cases.
377         * This formula and the one below are derived analyzing the
378         * tables present in VIA's own drivers. They may reject the over-
379         * lay in some cases where VIA's driver don't.
380         */
381        dClock = (width * height * refresh) / 680000;
382        if (dClock) {
383            needBandWidth =
384                (float)(((pScrn->bitsPerPixel >> 3) + VIDEO_BPP) * dClock);
385            totalBandWidth = (float)(mClock * 16. * memEfficiency);
386
387            DBG_DD(ErrorF(" via_xv.c : cBitsPerPel= %d : \n",
388                pScrn->bitsPerPixel));
389            DBG_DD(ErrorF(" via_xv.c : Video_Bpp= %d : \n", VIDEO_BPP));
390            DBG_DD(ErrorF(" via_xv.c : refresh = %d : \n", refresh));
391            DBG_DD(ErrorF(" via_xv.c : dClock= %d : \n", dClock));
392            DBG_DD(ErrorF(" via_xv.c : mClk= %f : \n", mClock));
393            DBG_DD(ErrorF(" via_xv.c : memEfficiency= %f : \n",
394                memEfficiency));
395            ErrorF(" via_xv.c : needBandwidth= %f : \n",
396                needBandWidth);
397            ErrorF(" via_xv.c : totalBandwidth= %f : \n",
398                totalBandWidth);
399            if (needBandWidth < totalBandWidth)
400                return TRUE;
401        }
402        return FALSE;
403    }
404    return FALSE;
405}
406
407static const char *viaXvErrMsg[xve_numerr] = { "No Error.",
408    "Bandwidth is insufficient. Check bios memory settings.",
409    "PCI DMA blit failed. You probably encountered a bug.",
410    "Not enough resources to complete the request. Probably out of memory.",
411    "General Error. I wish I could be more specific.",
412    "Wrong adaptor used. Try another port number."
413};
414
415static void
416viaXvError(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, XvError error)
417{
418    if (error == xve_none) {
419        pPriv->xvErr = xve_none;
420        return;
421    }
422    if (error == pPriv->xvErr) {
423        return;
424    }
425    pPriv->xvErr = error;
426    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[Xv] Port %d: %s\n",
427            pPriv->xv_portnum, viaXvErrMsg[error]);
428}
429
430static void
431viaResetVideo(ScrnInfoPtr pScrn)
432{
433    VIAPtr pVia = VIAPTR(pScrn);
434    vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
435
436    DBG_DD(ErrorF(" via_xv.c : viaResetVideo: \n"));
437
438    viaVidEng->video1_ctl = 0;
439    viaVidEng->video3_ctl = 0;
440    viaVidEng->compose = V1_COMMAND_FIRE;
441    viaVidEng->compose = V3_COMMAND_FIRE;
442    viaVidEng->color_key = 0x821;
443    viaVidEng->snd_color_key = 0x821;
444}
445
446void
447viaSaveVideo(ScrnInfoPtr pScrn)
448{
449    VIAPtr pVia = VIAPTR(pScrn);
450    vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
451
452    DBG_DD(ErrorF(" via_xv.c : viaSaveVideo : \n"));
453    /* Save video registers */
454    memcpy(pVia->VideoRegs, (void*)viaVidEng, sizeof(video_via_regs));
455
456    pVia->dwV1 = ((vmmtr) viaVidEng)->video1_ctl;
457    pVia->dwV3 = ((vmmtr) viaVidEng)->video3_ctl;
458    viaVidEng->video1_ctl = 0;
459    viaVidEng->video3_ctl = 0;
460    viaVidEng->compose = V1_COMMAND_FIRE;
461    viaVidEng->compose = V3_COMMAND_FIRE;
462}
463
464void
465viaRestoreVideo(ScrnInfoPtr pScrn)
466{
467    VIAPtr pVia = VIAPTR(pScrn);
468    vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
469    video_via_regs  *localVidEng = pVia->VideoRegs;
470
471    DBG_DD(ErrorF(" via_xv.c : viaRestoreVideo : \n"));
472
473    /* Restore video registers */
474    /* flush restored video engines' setting to MapBase */
475    viaVidEng->alphawin_hvstart = localVidEng->alphawin_hvstart;
476    viaVidEng->alphawin_size   = localVidEng->alphawin_size;
477    viaVidEng->alphawin_ctl    = localVidEng->alphawin_ctl;
478    viaVidEng->alphafb_stride  = localVidEng->alphafb_stride;
479    viaVidEng->color_key       = localVidEng->color_key;
480    viaVidEng->alphafb_addr    = localVidEng->alphafb_addr;
481    viaVidEng->chroma_low      = localVidEng->chroma_low;
482    viaVidEng->chroma_up       = localVidEng->chroma_up;
483    viaVidEng->interruptflag   = localVidEng->interruptflag;
484
485    if (pVia->ChipId != PCI_CHIP_VT3314)
486    {
487        /*VT3314 only has V3*/
488        viaVidEng->video1_ctl      = localVidEng->video1_ctl;
489        viaVidEng->video1_fetch    = localVidEng->video1_fetch;
490        viaVidEng->video1y_addr1   = localVidEng->video1y_addr1;
491        viaVidEng->video1_stride   = localVidEng->video1_stride;
492        viaVidEng->video1_hvstart  = localVidEng->video1_hvstart;
493        viaVidEng->video1_size     = localVidEng->video1_size;
494        viaVidEng->video1y_addr2   = localVidEng->video1y_addr2;
495        viaVidEng->video1_zoom     = localVidEng->video1_zoom;
496        viaVidEng->video1_mictl    = localVidEng->video1_mictl;
497        viaVidEng->video1y_addr0   = localVidEng->video1y_addr0;
498        viaVidEng->video1_fifo     = localVidEng->video1_fifo;
499        viaVidEng->video1y_addr3   = localVidEng->video1y_addr3;
500        viaVidEng->v1_source_w_h   = localVidEng->v1_source_w_h;
501        viaVidEng->video1_CSC1     = localVidEng->video1_CSC1;
502        viaVidEng->video1_CSC2     = localVidEng->video1_CSC2;
503
504        /* Fix cursor garbage after suspend for VX855 and VX900 (#405) */
505        /* 0x2E4 T Signature Data Result 1 */
506        viaVidEng->video1u_addr1         = localVidEng->video1u_addr1;
507        /* 0x2E8 HI for Primary Display FIFO Control Signal */
508        viaVidEng->video1u_addr2         = localVidEng->video1u_addr2;
509        /* 0x2EC HI for Primary Display FIFO Transparent color */
510        viaVidEng->video1u_addr3         = localVidEng->video1u_addr3;
511        /* 0x2F0 HI for Primary Display Control Signal */
512        viaVidEng->video1v_addr0         = localVidEng->video1v_addr0;
513        /* 0x2F4 HI for Primary Display Frame Buffer Starting Address */
514        viaVidEng->video1v_addr1         = localVidEng->video1v_addr1;
515        /* 0x2F8 HI for Primary Display Horizontal and Vertical Start */
516        viaVidEng->video1v_addr2         = localVidEng->video1v_addr2;
517        /* 0x2FC HI for Primary Display Center Offset */
518        viaVidEng->video1v_addr3         = localVidEng->video1v_addr3;
519    }
520    viaVidEng->snd_color_key   = localVidEng->snd_color_key;
521    viaVidEng->v3alpha_prefifo = localVidEng->v3alpha_prefifo;
522    viaVidEng->v3alpha_fifo    = localVidEng->v3alpha_fifo;
523    viaVidEng->video3_CSC2     = localVidEng->video3_CSC2;
524    viaVidEng->video3_CSC2     = localVidEng->video3_CSC2;
525    viaVidEng->v3_source_width = localVidEng->v3_source_width;
526    viaVidEng->video3_ctl      = localVidEng->video3_ctl;
527    viaVidEng->video3_addr0    = localVidEng->video3_addr0;
528    viaVidEng->video3_addr1    = localVidEng->video3_addr1;
529    viaVidEng->video3_stride   = localVidEng->video3_stride;
530    viaVidEng->video3_hvstart  = localVidEng->video3_hvstart;
531    viaVidEng->video3_size     = localVidEng->video3_size;
532    viaVidEng->v3alpha_fetch   = localVidEng->v3alpha_fetch;
533    viaVidEng->video3_zoom     = localVidEng->video3_zoom;
534    viaVidEng->video3_mictl    = localVidEng->video3_mictl;
535    viaVidEng->video3_CSC1     = localVidEng->video3_CSC1;
536    viaVidEng->video3_CSC2     = localVidEng->video3_CSC2;
537    viaVidEng->compose         = localVidEng->compose;
538    viaVidEng->video3_ctl      = pVia->dwV3;
539
540    if (pVia->ChipId != PCI_CHIP_VT3314) {
541        viaVidEng->video1_ctl = pVia->dwV1;
542        viaVidEng->compose = V1_COMMAND_FIRE;
543    }
544    viaVidEng->compose = V3_COMMAND_FIRE;
545}
546
547void
548viaExitVideo(ScrnInfoPtr pScrn)
549{
550    VIAPtr pVia = VIAPTR(pScrn);
551    vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
552    XF86VideoAdaptorPtr curAdapt;
553    int i, j, numPorts;
554
555    DBG_DD(ErrorF(" via_xv.c : viaExitVideo : \n"));
556
557#ifdef HAVE_DRI
558    ViaCleanupXVMC(pScrn, viaAdaptPtr, XV_ADAPT_NUM);
559#endif
560
561    viaVidEng->video1_ctl = 0;
562    viaVidEng->video3_ctl = 0;
563    viaVidEng->compose = V1_COMMAND_FIRE;
564    viaVidEng->compose = V3_COMMAND_FIRE;
565
566    /*
567     * Free all adaptor info allocated in viaInitVideo.
568     */
569
570    for (i = 0; i < XV_ADAPT_NUM; ++i) {
571        curAdapt = viaAdaptPtr[i];
572        if (curAdapt) {
573            if (curAdapt->pPortPrivates) {
574                if (curAdapt->pPortPrivates->ptr) {
575                    numPorts = numAdaptPort[i];
576                    for (j = 0; j < numPorts; ++j) {
577                        viaStopVideo(pScrn,
578                            (viaPortPrivPtr) curAdapt->pPortPrivates->ptr + j,
579                            TRUE);
580                    }
581                    free(curAdapt->pPortPrivates->ptr);
582                }
583                free(curAdapt->pPortPrivates);
584            }
585            free(curAdapt);
586        }
587    }
588    if (allAdaptors)
589        free(allAdaptors);
590}
591
592void
593viaInitVideo(ScreenPtr pScreen)
594{
595    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
596    XF86VideoAdaptorPtr *adaptors, *newAdaptors;
597    VIAPtr pVia = VIAPTR(pScrn);
598    int num_adaptors, num_new;
599
600    DBG_DD(ErrorF(" via_xv.c : viaInitVideo, Screen[%d]\n", pScrn->scrnIndex));
601
602    allAdaptors = NULL;
603    newAdaptors = NULL;
604    num_new = 0;
605
606    pVia->useDmaBlit = FALSE;
607#ifdef HAVE_DRI
608    pVia->useDmaBlit = (pVia->directRenderingType == DRI_1) &&
609    ((pVia->Chipset == VIA_CLE266) ||
610        (pVia->Chipset == VIA_KM400) ||
611        (pVia->Chipset == VIA_K8M800) ||
612        (pVia->Chipset == VIA_PM800) ||
613        (pVia->Chipset == VIA_VM800) ||
614        (pVia->Chipset == VIA_K8M890) ||
615        (pVia->Chipset == VIA_P4M900) ||
616        (pVia->Chipset == VIA_CX700) ||
617        (pVia->Chipset == VIA_VX800) ||
618        (pVia->Chipset == VIA_VX855) ||
619        (pVia->Chipset == VIA_VX900) ||
620        (pVia->Chipset == VIA_P4M890));
621    if ((pVia->drmVerMajor < 2) ||
622        ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor < 9)))
623        pVia->useDmaBlit = FALSE;
624#endif
625    pVia->useDmaBlit = pVia->useDmaBlit && pVia->dmaXV;
626
627    if (pVia->useDmaBlit)
628        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
629            "[Xv] Using PCI DMA for Xv image transfer.\n");
630
631    if (!viaFastVidCpy)
632        viaFastVidCpy = viaVidCopyInit("video", pScreen);
633
634    if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400) ||
635        (pVia->Chipset == VIA_K8M800) || (pVia->Chipset == VIA_PM800) ||
636        (pVia->Chipset == VIA_VM800) || (pVia->Chipset == VIA_K8M890) ||
637        (pVia->Chipset == VIA_P4M900) || (pVia->Chipset == VIA_CX700) ||
638        (pVia->Chipset == VIA_P4M890) || (pVia->Chipset == VIA_VX800) ||
639        (pVia->Chipset == VIA_VX855 || (pVia->Chipset == VIA_VX900))) {
640        num_new = viaSetupAdaptors(pScreen, &newAdaptors);
641        num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
642    } else {
643        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
644                "[Xv] Unsupported Chipset. X video functionality disabled.\n");
645        num_adaptors = 0;
646        memset(viaAdaptPtr, 0, sizeof(viaAdaptPtr));
647    }
648
649    DBG_DD(ErrorF(" via_xv.c : num_adaptors : %d\n", num_adaptors));
650    if (newAdaptors) {
651        allAdaptors = malloc((num_adaptors + num_new) *
652                sizeof(XF86VideoAdaptorPtr *));
653        if (allAdaptors) {
654            if (num_adaptors)
655                memcpy(allAdaptors, adaptors,
656                    num_adaptors * sizeof(XF86VideoAdaptorPtr));
657            memcpy(allAdaptors + num_adaptors, newAdaptors,
658                    num_new * sizeof(XF86VideoAdaptorPtr));
659            num_adaptors += num_new;
660        }
661    }
662
663    if (num_adaptors) {
664        xf86XVScreenInit(pScreen, allAdaptors, num_adaptors);
665#ifdef HAVE_DRI
666        ViaInitXVMC(pScreen);
667#endif
668        viaSetColorSpace(pVia, 0, 0, 0, 0, TRUE);
669        pVia->swov.panning_x = 0;
670        pVia->swov.panning_y = 0;
671        pVia->swov.oldPanningX = 0;
672        pVia->swov.oldPanningY = 0;
673    }
674}
675
676static unsigned
677viaSetupAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr ** adaptors)
678{
679    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
680    int i, j, usedPorts, numPorts;
681    viaPortPrivRec *viaPortPriv;
682    DevUnion *pdevUnion;
683
684    DBG_DD(ErrorF(" via_xv.c : viaSetupAdaptors (viaSetupImageVideo): \n"));
685
686    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
687    xvContrast = MAKE_ATOM("XV_CONTRAST");
688    xvColorKey = MAKE_ATOM("XV_COLORKEY");
689    xvHue = MAKE_ATOM("XV_HUE");
690    xvSaturation = MAKE_ATOM("XV_SATURATION");
691    xvAutoPaint = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
692
693    *adaptors = NULL;
694    usedPorts = 0;
695
696    for (i = 0; i < XV_ADAPT_NUM; i++) {
697        if (!(viaAdaptPtr[i] = xf86XVAllocateVideoAdaptorRec(pScrn)))
698            return 0;
699        numPorts = numAdaptPort[i];
700
701        viaPortPriv =
702            (viaPortPrivPtr) xnfcalloc(numPorts, sizeof(viaPortPrivRec));
703        pdevUnion = (DevUnion *) xnfcalloc(numPorts, sizeof(DevUnion));
704
705        if (i == XV_ADAPT_SWOV) { /* Overlay engine */
706            viaAdaptPtr[i]->type = XvInputMask | XvWindowMask | XvImageMask |
707            XvVideoMask | XvStillMask;
708            viaAdaptPtr[i]->flags =
709            VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
710        } else {
711            viaAdaptPtr[i]->type = XvInputMask | XvWindowMask | XvVideoMask;
712            viaAdaptPtr[i]->flags =
713            VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
714        }
715        viaAdaptPtr[i]->name = XvAdaptorName[i];
716        viaAdaptPtr[i]->nEncodings = 1;
717        viaAdaptPtr[i]->pEncodings = DummyEncoding;
718        viaAdaptPtr[i]->nFormats = sizeof(FormatsG) / sizeof(FormatsG[0]);
719        viaAdaptPtr[i]->pFormats = FormatsG;
720
721        /* The adapter can handle 1 port simultaneously */
722        viaAdaptPtr[i]->nPorts = numPorts;
723        viaAdaptPtr[i]->pPortPrivates = pdevUnion;
724        viaAdaptPtr[i]->pPortPrivates->ptr = (pointer) viaPortPriv;
725        viaAdaptPtr[i]->nAttributes = NUM_ATTRIBUTES_G;
726        viaAdaptPtr[i]->pAttributes = AttributesG;
727
728        viaAdaptPtr[i]->nImages = NUM_IMAGES_G;
729        viaAdaptPtr[i]->pImages = ImagesG;
730        viaAdaptPtr[i]->PutVideo = NULL;
731        viaAdaptPtr[i]->StopVideo = viaStopVideo;
732        viaAdaptPtr[i]->QueryBestSize = viaQueryBestSize;
733        viaAdaptPtr[i]->GetPortAttribute = viaGetPortAttribute;
734        viaAdaptPtr[i]->SetPortAttribute = viaSetPortAttribute;
735        viaAdaptPtr[i]->PutImage = viaPutImage;
736        viaAdaptPtr[i]->ReputImage = NULL;
737        viaAdaptPtr[i]->QueryImageAttributes = viaQueryImageAttributes;
738        for (j = 0; j < numPorts; ++j) {
739            viaPortPriv[j].dmaBounceBuffer = NULL;
740            viaPortPriv[j].dmaBounceStride = 0;
741            viaPortPriv[j].dmaBounceLines = 0;
742            viaPortPriv[j].colorKey = 0x0821;
743            viaPortPriv[j].autoPaint = TRUE;
744            viaPortPriv[j].brightness = 5000.;
745            viaPortPriv[j].saturation = 10000;
746            viaPortPriv[j].contrast = 10000;
747            viaPortPriv[j].hue = 0;
748            viaPortPriv[j].FourCC = 0;
749            viaPortPriv[j].xv_portnum = j + usedPorts;
750            viaPortPriv[j].xvErr = xve_none;
751
752#ifdef X_USE_REGION_NULL
753            REGION_NULL(pScreen, &viaPortPriv[j].clip);
754#else
755            REGION_INIT(pScreen, &viaPortPriv[j].clip, NullBox, 1);
756#endif
757        }
758        usedPorts += j;
759
760#ifdef HAVE_DRI
761        viaXvMCInitXv(pScrn, viaAdaptPtr[i]);
762#endif
763
764    } /* End of for */
765    viaResetVideo(pScrn);
766    *adaptors = viaAdaptPtr;
767    return XV_ADAPT_NUM;
768}
769
770static void
771viaStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
772{
773    VIAPtr pVia = VIAPTR(pScrn);
774    viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
775
776    DBG_DD(ErrorF(" via_xv.c : viaStopVideo: exit=%d\n", exit));
777
778    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
779    ViaOverlayHide(pScrn);
780    if (exit) {
781        ViaSwovSurfaceDestroy(pScrn, pPriv);
782        if (pPriv->dmaBounceBuffer)
783            free(pPriv->dmaBounceBuffer);
784        pPriv->dmaBounceBuffer = 0;
785        pPriv->dmaBounceStride = 0;
786        pPriv->dmaBounceLines = 0;
787        pVia->dwFrameNum = 0;
788        pPriv->old_drw_x = 0;
789        pPriv->old_drw_y = 0;
790        pPriv->old_drw_w = 0;
791        pPriv->old_drw_h = 0;
792    }
793}
794
795static int
796viaSetPortAttribute(ScrnInfoPtr pScrn,
797        Atom attribute, INT32 value, pointer data)
798{
799    VIAPtr pVia = VIAPTR(pScrn);
800    vmmtr viaVidEng = (vmmtr) (pVia->MapBase + 0x200);
801    viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
802    int attr, avalue;
803
804    DBG_DD(ErrorF(" via_xv.c : viaSetPortAttribute : \n"));
805
806    /* Color Key */
807    if (attribute == xvColorKey) {
808        DBG_DD(ErrorF("  V4L Disable  xvColorKey = %08lx\n", value));
809
810        pPriv->colorKey = value;
811        /* All assume color depth is 16 */
812        value &= 0x00FFFFFF;
813        viaVidEng->color_key = value;
814        viaVidEng->snd_color_key = value;
815        REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
816        DBG_DD(ErrorF("  V4L Disable done  xvColorKey = %08lx\n", value));
817
818    } else if (attribute == xvAutoPaint) {
819        pPriv->autoPaint = value;
820        DBG_DD(ErrorF("       xvAutoPaint = %08lx\n", value));
821        /* Color Control */
822    } else if (attribute == xvBrightness ||
823            attribute == xvContrast ||
824            attribute == xvSaturation || attribute == xvHue) {
825        if (attribute == xvBrightness) {
826            DBG_DD(ErrorF("     xvBrightness = %08ld\n", value));
827            pPriv->brightness = value;
828        }
829        if (attribute == xvContrast) {
830            DBG_DD(ErrorF("     xvContrast = %08ld\n", value));
831            pPriv->contrast = value;
832        }
833        if (attribute == xvSaturation) {
834            DBG_DD(ErrorF("     xvSaturation = %08ld\n", value));
835            pPriv->saturation = value;
836        }
837        if (attribute == xvHue) {
838            DBG_DD(ErrorF("     xvHue = %08ld\n", value));
839            pPriv->hue = value;
840        }
841        viaSetColorSpace(pVia, pPriv->hue, pPriv->saturation,
842                pPriv->brightness, pPriv->contrast, FALSE);
843    } else {
844        DBG_DD(ErrorF
845                (" via_xv.c : viaSetPortAttribute : is not supported the attribute"));
846        return BadMatch;
847    }
848
849    /* attr,avalue hardware processing goes here */
850    (void)attr;
851    (void)avalue;
852
853    return Success;
854}
855
856static int
857viaGetPortAttribute(ScrnInfoPtr pScrn,
858        Atom attribute, INT32 * value, pointer data)
859{
860    viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
861
862    DBG_DD(ErrorF(" via_xv.c : viaGetPortAttribute : port %d %ld\n",
863                    pPriv->xv_portnum, attribute));
864
865    *value = 0;
866    if (attribute == xvColorKey) {
867        *value = (INT32) pPriv->colorKey;
868        DBG_DD(ErrorF(" via_xv.c :    ColorKey 0x%lx\n", pPriv->colorKey));
869    } else if (attribute == xvAutoPaint) {
870        *value = (INT32) pPriv->autoPaint;
871        DBG_DD(ErrorF("    AutoPaint = %08ld\n", *value));
872        /* Color Control */
873    } else if (attribute == xvBrightness ||
874            attribute == xvContrast ||
875            attribute == xvSaturation || attribute == xvHue) {
876        if (attribute == xvBrightness) {
877            *value = pPriv->brightness;
878            DBG_DD(ErrorF("    xvBrightness = %08ld\n", *value));
879        }
880        if (attribute == xvContrast) {
881            *value = pPriv->contrast;
882            DBG_DD(ErrorF("    xvContrast = %08ld\n", *value));
883        }
884        if (attribute == xvSaturation) {
885            *value = pPriv->saturation;
886            DBG_DD(ErrorF("    xvSaturation = %08ld\n", *value));
887        }
888        if (attribute == xvHue) {
889            *value = pPriv->hue;
890            DBG_DD(ErrorF("    xvHue = %08ld\n", *value));
891        }
892
893    } else {
894        DBG_DD(ErrorF(" via_xv.c : viaGetPortAttribute : is not supported the attribute\n"));
895        /*return BadMatch */;
896    }
897    return Success;
898}
899
900static void
901viaQueryBestSize(ScrnInfoPtr pScrn,
902    Bool motion,
903    short vid_w, short vid_h,
904    short drw_w, short drw_h,
905    unsigned int *p_w, unsigned int *p_h, pointer data)
906{
907    DBG_DD(ErrorF(" via_xv.c : viaQueryBestSize :\n"));
908    *p_w = drw_w;
909    *p_h = drw_h;
910
911    if (*p_w > 2048)
912        *p_w = 2048;
913}
914
915/*
916 *  To do SW Flip
917 */
918static void
919Flip(VIAPtr pVia, viaPortPrivPtr pPriv, int fourcc,
920        unsigned long DisplayBufferIndex)
921{
922    unsigned long proReg = 0;
923    unsigned count = 50000;
924
925    if (pVia->ChipId == PCI_CHIP_VT3259
926        && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
927        proReg = PRO_HQV1_OFFSET;
928
929    switch (fourcc) {
930        case FOURCC_UYVY:
931        case FOURCC_YUY2:
932        case FOURCC_RV15:
933        case FOURCC_RV16:
934        case FOURCC_RV32:
935            while ((VIAGETREG(HQV_CONTROL + proReg) & HQV_SW_FLIP)
936                    && --count);
937            VIASETREG(HQV_SRC_STARTADDR_Y + proReg,
938                pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
939            VIASETREG(HQV_CONTROL + proReg, (VIAGETREG(HQV_CONTROL + proReg) & ~HQV_FLIP_ODD) | HQV_SW_FLIP | HQV_FLIP_STATUS);
940            break;
941        case FOURCC_YV12:
942        case FOURCC_I420:
943        default:
944            while ((VIAGETREG(HQV_CONTROL + proReg) & HQV_SW_FLIP)
945                    && --count);
946            VIASETREG(HQV_SRC_STARTADDR_Y + proReg,
947                pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
948            if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
949                VIASETREG(HQV_SRC_STARTADDR_U + proReg,
950                pVia->swov.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]);
951            } else {
952                VIASETREG(HQV_SRC_STARTADDR_U,
953                    pVia->swov.SWDevice.dwSWCbPhysicalAddr[DisplayBufferIndex]);
954                VIASETREG(HQV_SRC_STARTADDR_V,
955                    pVia->swov.SWDevice.dwSWCrPhysicalAddr[DisplayBufferIndex]);
956            }
957            VIASETREG(HQV_CONTROL + proReg, (VIAGETREG(HQV_CONTROL + proReg) & ~HQV_FLIP_ODD) | HQV_SW_FLIP | HQV_FLIP_STATUS);
958	    break;
959    }
960}
961
962static void
963planar420cp(unsigned char *dst, const unsigned char *src, int dstPitch,
964            int w, int h, int i420)
965{
966    unsigned long srcUOffset, srcVOffset;
967
968    /*
969     * Blit luma component as a fake YUY2 assembler blit.
970     */
971    if (i420) {
972        srcVOffset  = w * h + (w >> 1) * (h >> 1);
973        srcUOffset = w * h;
974    } else {
975        srcUOffset  = w * h + (w >> 1) * (h >> 1);
976        srcVOffset = w * h;
977    }
978
979    (*viaFastVidCpy) (dst, src, dstPitch, w >> 1, h, 1);
980    UVBlit(dst + dstPitch * h, src + srcUOffset,
981            src + srcVOffset, w >> 1, w >> 1, dstPitch, h >> 1);
982}
983
984/*
985 * Slow and dirty. NV12 blit.
986 */
987static void
988nv12cp(unsigned char *dst, const unsigned char *src, int dstPitch,
989        int w, int h, int i420)
990{
991    unsigned long srcUOffset, srcVOffset;
992
993    /*
994     * Blit luma component as a fake YUY2 assembler blit.
995     */
996    if (i420) {
997        srcVOffset  = w * h + (w >> 1) * (h >> 1);
998        srcUOffset = w * h;
999    } else {
1000        srcUOffset  = w * h + (w >> 1) * (h >> 1);
1001        srcVOffset = w * h;
1002    }
1003
1004    (*viaFastVidCpy) (dst, src, dstPitch, w >> 1, h, TRUE);
1005    nv12Blit(dst + dstPitch * h, src + srcUOffset,
1006            src + srcVOffset, w >> 1, w >>1, dstPitch, h >> 1);
1007}
1008
1009#ifdef HAVE_DRI
1010
1011static int
1012viaDmaBlitImage(VIAPtr pVia,
1013    viaPortPrivPtr pPort,
1014    unsigned char *src,
1015    CARD32 dst, unsigned width, unsigned height, unsigned lumaStride, int id)
1016{
1017    Bool bounceBuffer;
1018    drm_via_dmablit_t blit;
1019    drm_via_blitsync_t *chromaSync = &blit.sync;
1020    drm_via_blitsync_t lumaSync;
1021    unsigned char *base;
1022    unsigned char *bounceBase;
1023    unsigned bounceStride;
1024    unsigned bounceLines;
1025    unsigned size;
1026    int err = 0;
1027    Bool nv12Conversion;
1028
1029    bounceBuffer = ((unsigned long)src & 15);
1030    nv12Conversion = (pVia->VideoEngine == VIDEO_ENGINE_CME &&
1031                     (id == FOURCC_YV12 || id == FOURCC_I420));
1032
1033    switch (id) {
1034        case FOURCC_YUY2:
1035        case FOURCC_RV15:
1036        case FOURCC_RV16:
1037            bounceStride = ALIGN_TO(2 * width, 16);
1038            bounceLines = height;
1039            break;
1040        case FOURCC_RV32:
1041            bounceStride = ALIGN_TO(4 * width, 16);
1042            bounceLines = height;
1043            break;
1044
1045        case FOURCC_YV12:
1046        case FOURCC_I420:
1047        default:
1048            bounceStride = ALIGN_TO(width, 16);
1049            bounceLines = height;
1050            break;
1051    }
1052
1053    if (bounceBuffer || nv12Conversion) {
1054        if (!pPort->dmaBounceBuffer ||
1055            pPort->dmaBounceStride != bounceStride ||
1056            pPort->dmaBounceLines != bounceLines) {
1057            if (pPort->dmaBounceBuffer) {
1058                free(pPort->dmaBounceBuffer);
1059                pPort->dmaBounceBuffer = 0;
1060            }
1061            size = bounceStride * bounceLines + 16;
1062            if (id == FOURCC_YV12 || id == FOURCC_I420)
1063                size += ALIGN_TO(bounceStride >> 1, 16) * bounceLines;
1064            pPort->dmaBounceBuffer = (unsigned char *)malloc(size);
1065            pPort->dmaBounceLines = bounceLines;
1066            pPort->dmaBounceStride = bounceStride;
1067        }
1068    }
1069
1070    bounceBase =
1071    (unsigned char *)ALIGN_TO((unsigned long)(pPort->dmaBounceBuffer),
1072        16);
1073    base = (bounceBuffer) ? bounceBase : src;
1074
1075    if (bounceBuffer) {
1076        (*viaFastVidCpy) (base, src, bounceStride, bounceStride >> 1, height,
1077        1);
1078    }
1079
1080    blit.num_lines = height;
1081    blit.line_length = bounceStride;
1082    blit.fb_addr = dst;
1083    blit.fb_stride = lumaStride;
1084    blit.mem_addr = base;
1085    blit.mem_stride = bounceStride;
1086    blit.to_fb = 1;
1087#ifdef XV_DEBUG
1088    ErrorF
1089    ("Addr: 0x%lx, Offset 0x%lx\n Fb_stride: %u, Mem_stride: %u\n width: %u num_lines: %u\n",
1090    (unsigned long)blit.mem_addr, (unsigned long)blit.fb_addr,
1091    (unsigned)blit.fb_stride, (unsigned)blit.mem_stride,
1092    (unsigned)blit.line_length, (unsigned)blit.num_lines);
1093#endif
1094    while (-EAGAIN == (err =
1095        drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, &blit,
1096        sizeof(blit)))) ;
1097    if (err < 0)
1098        return -1;
1099
1100    lumaSync = blit.sync;
1101
1102    if (id == FOURCC_YV12 || id == FOURCC_I420) {
1103        unsigned tmp = ALIGN_TO(width >> 1, 16);
1104
1105        if (nv12Conversion) {
1106            nv12Blit(bounceBase + bounceStride * height,
1107                src + bounceStride * height + tmp * (height >> 1),
1108                src + bounceStride * height, width >> 1, tmp,
1109                bounceStride, height >> 1);
1110        } else if (bounceBuffer) {
1111            (*viaFastVidCpy) (base + bounceStride * height,
1112                    src + bounceStride * height, tmp, tmp >> 1, height, 1);
1113        }
1114
1115        if (nv12Conversion) {
1116            blit.num_lines = height >> 1;
1117            blit.line_length = bounceStride;
1118            blit.mem_addr = bounceBase + bounceStride * height;
1119            blit.fb_stride = lumaStride;
1120            blit.mem_stride = bounceStride;
1121        } else {
1122            blit.num_lines = height;
1123            blit.line_length = tmp;
1124            blit.mem_addr = base + bounceStride * height;
1125            blit.fb_stride = lumaStride >> 1;
1126            blit.mem_stride = tmp;
1127        }
1128
1129        blit.fb_addr = dst + lumaStride * height;
1130        blit.to_fb = 1;
1131
1132        while (-EAGAIN == (err =
1133            drmCommandWriteRead(pVia->drmmode.fd, DRM_VIA_DMA_BLIT, &blit,
1134                sizeof(blit))));
1135        if (err < 0)
1136            return -1;
1137    }
1138
1139    while (-EAGAIN == (err = drmCommandWrite(pVia->drmmode.fd, DRM_VIA_BLIT_SYNC,
1140        chromaSync, sizeof(*chromaSync)))) ;
1141    if (err < 0)
1142        return -1;
1143
1144    return Success;
1145}
1146
1147#endif
1148
1149
1150/*
1151 * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h).
1152 * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h).
1153 * id is a fourcc code for the format of the video.
1154 * buf is the pointer to the source data in system memory.
1155 * width and height are the w/h of the source data.
1156 * If "sync" is TRUE, then we must be finished with *buf at the point of return
1157 * (which we always are).
1158 * clipBoxes is the clipping region in screen space.
1159 * data is a pointer to our port private.
1160 * pDraw is a Drawable, which might not be the screen in the case of
1161 * compositing.  It's a new argument to the function in the 1.1 server.
1162 */
1163
1164static int
1165viaPutImage(ScrnInfoPtr pScrn,
1166        short src_x, short src_y,
1167        short drw_x, short drw_y,
1168        short src_w, short src_h,
1169        short drw_w, short drw_h,
1170        int id, unsigned char *buf,
1171        short width, short height, Bool sync, RegionPtr clipBoxes,
1172        pointer data, DrawablePtr pDraw)
1173{
1174    VIAPtr pVia = VIAPTR(pScrn);
1175    viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
1176    xf86CrtcPtr crtc = NULL;
1177    unsigned long retCode;
1178
1179# ifdef XV_DEBUG
1180    ErrorF(" via_xv.c : viaPutImage : called,  Screen[%d]\n", pScrn->scrnIndex);
1181    ErrorF(" via_xv.c : FourCC=0x%x width=%d height=%d sync=%d\n", id,
1182            width, height, sync);
1183    ErrorF
1184    (" via_xv.c : src_x=%d src_y=%d src_w=%d src_h=%d colorkey=0x%lx\n",
1185            src_x, src_y, src_w, src_h, pPriv->colorKey);
1186    ErrorF(" via_xv.c : drw_x=%d drw_y=%d drw_w=%d drw_h=%d\n", drw_x,
1187            drw_y, drw_w, drw_h);
1188# endif
1189
1190    /* Find out which CRTC the surface will belong to */
1191    crtc = window_belongs_to_crtc(pScrn, drw_x, drw_y, drw_w, drw_h);
1192    if (!crtc) {
1193        DBG_DD(ErrorF(" via_xv.c : No usable CRTC\n"));
1194        viaXvError(pScrn, pPriv, xve_adaptor);
1195        return BadAlloc;
1196    }
1197
1198    switch (pPriv->xv_adaptor) {
1199        case XV_ADAPT_SWOV:
1200        {
1201            DDUPDATEOVERLAY UpdateOverlay_Video;
1202            LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video;
1203
1204            int dstPitch;
1205            unsigned long dwUseExtendedFIFO = 0;
1206
1207            DBG_DD(ErrorF(" via_xv.c :              : S/W Overlay! \n"));
1208            /*  Allocate video memory(CreateSurface),
1209             *  add codes to judge if need to re-create surface
1210             */
1211            if ((pPriv->old_src_w != src_w) || (pPriv->old_src_h != src_h)) {
1212                ViaSwovSurfaceDestroy(pScrn, pPriv);
1213            }
1214
1215            if (Success != (retCode =
1216                ViaSwovSurfaceCreate(pScrn, pPriv, id, width, height))) {
1217                DBG_DD(ErrorF
1218                        ("             : Fail to Create SW Video Surface\n"));
1219                viaXvError(pScrn, pPriv, xve_mem);
1220                return retCode;
1221            }
1222
1223            /*  Copy image data from system memory to video memory
1224             *  TODO: use DRM's DMA feature to accelerate data copy
1225             */
1226            if (id != FOURCC_XVMC) {
1227                dstPitch = pVia->swov.SWDevice.dwPitch;
1228
1229                if (pVia->useDmaBlit) {
1230#ifdef HAVE_DRI
1231                    if (viaDmaBlitImage(pVia, pPriv, buf,
1232                        (CARD32) pVia->swov.SWDevice.dwSWPhysicalAddr[pVia->dwFrameNum & 1],
1233                        width, height, dstPitch, id)) {
1234                            viaXvError(pScrn, pPriv, xve_dmablit);
1235                        return BadAccess;
1236                    }
1237#endif
1238                } else {
1239                    switch (id) {
1240                        case FOURCC_I420:
1241                            if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
1242                                nv12cp(pVia->swov.SWDevice.
1243                                    lpSWOverlaySurface[pVia->dwFrameNum & 1],
1244                                    buf, dstPitch, width, height, 1);
1245                            } else {
1246                                (*viaFastVidCpy)(pVia->swov.SWDevice.
1247                                    lpSWOverlaySurface[pVia->dwFrameNum & 1],
1248                                    buf, dstPitch, width, height, 0);
1249                            }
1250                            break;
1251                        case FOURCC_YV12:
1252                            if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
1253                                nv12cp(pVia->swov.SWDevice.
1254                                    lpSWOverlaySurface[pVia->dwFrameNum & 1],
1255                                    buf, dstPitch, width, height, 0);
1256                            } else {
1257                                (*viaFastVidCpy)(pVia->swov.SWDevice.
1258                                    lpSWOverlaySurface[pVia->dwFrameNum & 1],
1259                                    buf, dstPitch, width, height, 0);
1260                            }
1261                            break;
1262                        case FOURCC_RV32:
1263                            (*viaFastVidCpy) (pVia->swov.SWDevice.
1264                                lpSWOverlaySurface[pVia->dwFrameNum & 1],
1265                                buf, dstPitch, width << 1, height, 1);
1266                            break;
1267                        case FOURCC_UYVY:
1268                        case FOURCC_YUY2:
1269                        case FOURCC_RV15:
1270                        case FOURCC_RV16:
1271                        default:
1272                            (*viaFastVidCpy) (pVia->swov.SWDevice.
1273                                lpSWOverlaySurface[pVia->dwFrameNum & 1],
1274                                buf, dstPitch, width, height, 1);
1275                            break;
1276                    }
1277                }
1278            }
1279
1280            /* If there is bandwidth issue, block the H/W overlay */
1281            if (!(DecideOverlaySupport(crtc))) {
1282                DBG_DD(ErrorF
1283                        (" via_xv.c : Xv Overlay rejected due to insufficient "
1284                                "memory bandwidth.\n"));
1285                viaXvError(pScrn, pPriv, xve_bandwidth);
1286                return BadAlloc;
1287            }
1288
1289            /*
1290             *  fill video overlay parameter
1291             */
1292            lpUpdateOverlay->SrcLeft = src_x;
1293            lpUpdateOverlay->SrcTop = src_y;
1294            lpUpdateOverlay->SrcRight = src_x + src_w;
1295            lpUpdateOverlay->SrcBottom = src_y + src_h;
1296
1297            lpUpdateOverlay->DstLeft = drw_x;
1298            lpUpdateOverlay->DstTop = drw_y;
1299            lpUpdateOverlay->DstRight = drw_x + drw_w;
1300            lpUpdateOverlay->DstBottom = drw_y + drw_h;
1301
1302            lpUpdateOverlay->dwFlags = DDOVER_KEYDEST;
1303
1304            if (pScrn->bitsPerPixel == 8) {
1305                lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
1306            } else {
1307                lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
1308            }
1309            /* If use extend FIFO mode */
1310            if (pScrn->currentMode->HDisplay > 1024) {
1311                dwUseExtendedFIFO = 1;
1312            }
1313
1314            if (FOURCC_XVMC != id) {
1315
1316                /*
1317                 * XvMC flipping is done in the client lib.
1318                 */
1319
1320                DBG_DD(ErrorF("             : Flip\n"));
1321                Flip(pVia, pPriv, id, pVia->dwFrameNum & 1);
1322            }
1323
1324            pVia->dwFrameNum++;
1325
1326            /* If the dest rec. & extendFIFO doesn't change, don't do UpdateOverlay
1327             * unless the surface clipping has changed */
1328            if ((pPriv->old_drw_x == drw_x) && (pPriv->old_drw_y == drw_y)
1329                    && (pPriv->old_drw_w == drw_w) && (pPriv->old_drw_h == drw_h)
1330                    && (pPriv->old_src_x == src_x) && (pPriv->old_src_y == src_y)
1331                    && (pPriv->old_src_w == src_w) && (pPriv->old_src_h == src_h)
1332                    && (pVia->old_dwUseExtendedFIFO == dwUseExtendedFIFO)
1333                    && (pVia->VideoStatus & VIDEO_SWOV_ON) &&
1334                    REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
1335                DBG_DD(ErrorF(" via_xv.c : don't do UpdateOverlay! \n"));
1336                viaXvError(pScrn, pPriv, xve_none);
1337                return Success;
1338            }
1339
1340            pPriv->old_src_x = src_x;
1341            pPriv->old_src_y = src_y;
1342            pPriv->old_src_w = src_w;
1343            pPriv->old_src_h = src_h;
1344
1345            pPriv->old_drw_x = drw_x;
1346            pPriv->old_drw_y = drw_y;
1347            pPriv->old_drw_w = drw_w;
1348            pPriv->old_drw_h = drw_h;
1349            pVia->old_dwUseExtendedFIFO = dwUseExtendedFIFO;
1350            pVia->VideoStatus |= VIDEO_SWOV_ON;
1351
1352            /*  BitBlt: Draw the colorkey rectangle */
1353            if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
1354                REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
1355                if (pPriv->autoPaint) {
1356                    if (pDraw->type == DRAWABLE_WINDOW) {
1357                        xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes);
1358                        DamageDamageRegion(pDraw, clipBoxes);
1359                    } else {
1360                        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
1361                    }
1362                }
1363            } else {
1364                DBG_DD(ErrorF(" via_xv.c : // No need to draw Colorkey!! \n"));
1365            }
1366            /*
1367             *  Update video overlay
1368             */
1369            if (!VIAVidUpdateOverlay(crtc, lpUpdateOverlay)) {
1370                DBG_DD(ErrorF
1371                        (" via_xv.c : call v4l updateoverlay fail. \n"));
1372            } else {
1373                DBG_DD(ErrorF(" via_xv.c : PutImage done OK\n"));
1374                viaXvError(pScrn, pPriv, xve_none);
1375                return Success;
1376            }
1377            break;
1378        }
1379        default:
1380            DBG_DD(ErrorF(" via_xv.c : XVPort not supported\n"));
1381            viaXvError(pScrn, pPriv, xve_adaptor);
1382            break;
1383    }
1384    DBG_DD(ErrorF(" via_xv.c : PutImage done OK\n"));
1385    viaXvError(pScrn, pPriv, xve_none);
1386    return Success;
1387}
1388
1389static int
1390viaQueryImageAttributes(ScrnInfoPtr pScrn,
1391        int id, unsigned short *w, unsigned short *h, int *pitches,
1392        int *offsets)
1393{
1394    int size, tmp;
1395    VIAPtr pVia = VIAPTR(pScrn);
1396
1397    DBG_DD(ErrorF(" via_xv.c : viaQueryImageAttributes : FourCC=0x%x, ",
1398            id));
1399    DBG_DD(ErrorF(" via_xv.c : Screen[%d],  w=%d, h=%d\n", pScrn->scrnIndex, *w, *h));
1400
1401    if ((!w) || (!h))
1402        return 0;
1403
1404    if (*w > VIA_MAX_XVIMAGE_X)
1405        *w = VIA_MAX_XVIMAGE_X;
1406    if (*h > VIA_MAX_XVIMAGE_Y)
1407        *h = VIA_MAX_XVIMAGE_Y;
1408
1409    *w = (*w + 1) & ~1;
1410    if (offsets)
1411        offsets[0] = 0;
1412
1413    switch (id) {
1414        case FOURCC_I420:
1415        case FOURCC_YV12: /*Planar format : YV12 -4:2:0 */
1416            *h = (*h + 1) & ~1;
1417            size = *w;
1418            if (pVia->useDmaBlit)
1419                size = (size + 15) & ~15;
1420            if (pitches)
1421                pitches[0] = size;
1422            size *= *h;
1423            if (offsets)
1424                offsets[1] = size;
1425            tmp = (*w >> 1);
1426            if (pVia->useDmaBlit)
1427                tmp = (tmp + 15) & ~15;
1428            if (pitches)
1429                pitches[1] = pitches[2] = tmp;
1430            tmp *= (*h >> 1);
1431            size += tmp;
1432            if (offsets)
1433                offsets[2] = size;
1434            size += tmp;
1435            break;
1436        case FOURCC_XVMC:
1437            *h = (*h + 1) & ~1;
1438#ifdef HAVE_DRI
1439            size = viaXvMCPutImageSize(pScrn);
1440#else
1441            size = 0;
1442#endif
1443            if (pitches)
1444                pitches[0] = size;
1445            break;
1446        case FOURCC_AI44:
1447        case FOURCC_IA44:
1448            size = *w * *h;
1449            if (pitches)
1450                pitches[0] = *w;
1451            if (offsets)
1452                offsets[0] = 0;
1453            break;
1454        case FOURCC_RV32:
1455            size = *w << 2;
1456            if (pVia->useDmaBlit)
1457                size = (size + 15) & ~15;
1458            if (pitches)
1459                pitches[0] = size;
1460            size *= *h;
1461            break;
1462        case FOURCC_UYVY: /*Packed format : UYVY -4:2:2 */
1463        case FOURCC_YUY2: /*Packed format : YUY2 -4:2:2 */
1464        case FOURCC_RV15:
1465        case FOURCC_RV16:
1466        default:
1467            size = *w << 1;
1468            if (pVia->useDmaBlit)
1469                size = (size + 15) & ~15;
1470            if (pitches)
1471                pitches[0] = size;
1472            size *= *h;
1473        break;
1474    }
1475
1476    if (pitches)
1477        DBG_DD(ErrorF(" pitches[0]=%d, pitches[1]=%d, pitches[2]=%d, ",
1478                    pitches[0], pitches[1], pitches[2]));
1479    if (offsets)
1480        DBG_DD(ErrorF(" offsets[0]=%d, offsets[1]=%d, offsets[2]=%d, ",
1481                    offsets[0], offsets[1], offsets[2]));
1482
1483    DBG_DD(ErrorF(" width=%d, height=%d \n", *w, *h));
1484    return size;
1485}
1486
1487/*
1488 *
1489 */
1490void
1491VIAVidAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
1492{
1493    VIAPtr pVia = VIAPTR(pScrn);
1494
1495    pVia->swov.panning_x = x;
1496    pVia->swov.panning_y = y;
1497}
1498
1499/*
1500 * Blit the U and V Fields. Used to Flip the U V for I420.
1501 */
1502
1503static void
1504UVBlit(unsigned char *dst,
1505        const unsigned char *uBuffer,
1506        const unsigned char *vBuffer,
1507        unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines)
1508{
1509    int i, j;
1510
1511    dstPitch >>= 1;
1512
1513    for(j = 0; j < lines; j++)
1514    {
1515        for(i = 0; i < width; i++)
1516        {
1517            dst[i] = (uBuffer[i] << 8) | (vBuffer[i] << 16);
1518        }
1519
1520        dst += dstPitch;
1521        uBuffer += srcPitch;
1522        vBuffer += srcPitch;
1523    }
1524
1525}
1526
1527
1528/*
1529 * Blit the chroma field from one buffer to another while at the same time converting from
1530 * YV12 to NV12.
1531 */
1532
1533static void
1534nv12Blit(unsigned char *nv12Chroma,
1535        const unsigned char *uBuffer,
1536        const unsigned char *vBuffer,
1537        unsigned width, unsigned srcPitch, unsigned dstPitch, unsigned lines)
1538{
1539    int x;
1540    int dstAdd;
1541    int srcAdd;
1542
1543    dstAdd = dstPitch - (width << 1);
1544    srcAdd = srcPitch - width;
1545
1546    while (lines--) {
1547        x = width;
1548        while (x > 3) {
1549            register CARD32
1550            dst32,
1551            src32 = *((CARD32 *) vBuffer),
1552            src32_2 = *((CARD32 *) uBuffer);
1553            dst32 =
1554                (src32_2 & 0xff) | ((src32 & 0xff) << 8) |
1555                ((src32_2 & 0x0000ff00) << 8) | ((src32 & 0x0000ff00) << 16);
1556            *((CARD32 *) nv12Chroma) = dst32;
1557            nv12Chroma += 4;
1558            dst32 =
1559                ((src32_2 & 0x00ff0000) >> 16) | ((src32 & 0x00ff0000) >> 8) |
1560                ((src32_2 & 0xff000000) >> 8) | (src32 & 0xff000000);
1561            *((CARD32 *) nv12Chroma) = dst32;
1562            nv12Chroma += 4;
1563            x -= 4;
1564            vBuffer += 4;
1565            uBuffer += 4;
1566        }
1567        while (x--) {
1568            *nv12Chroma++ = *uBuffer++;
1569            *nv12Chroma++ = *vBuffer++;
1570        }
1571        nv12Chroma += dstAdd;
1572        vBuffer += srcAdd;
1573        uBuffer += srcAdd;
1574    }
1575}
1576
1577#endif /* !XvExtension */
1578