Hi,

I used the enclosed file to modify the 4.2.1-1 version of xfree to add the support for Xv in neomagic.

In fact the patch is essentially taken from redhat's package (in rawhide).

I am currently using it in my ThinkPad 600x since yesterday and mplayer & xine are quite happy with it.

Can you add it to a next iteration of your packages ?

Thanks,

yas
diff -x CVS -uNr xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/Imakefile 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/Imakefile
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/Imakefile      Wed Jan 
24 01:06:21 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/Imakefile   Thu Apr  4 
16:05:44 2002
@@ -4,10 +4,10 @@
 
 
 SRCS = neo_driver.c neo_bank.c neo_cursor.c neo_2097.c neo_2070.c \
-       neo_2090.c neo_2200.c neo_i2c.c neo_shadow.c neo_dga.c
+       neo_2090.c neo_2200.c neo_i2c.c neo_shadow.c neo_dga.c neo_video.c
 
 OBJS = neo_driver.o neo_bank.o neo_cursor.o neo_2097.o neo_2070.o \
-       neo_2090.o neo_2200.o neo_i2c.o neo_shadow.o neo_dga.o
+       neo_2090.o neo_2200.o neo_i2c.o neo_shadow.o neo_dga.o neo_video.o
 
 DEFINES = -DPSZ=8
 
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/NM-reg.txt 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/NM-reg.txt
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/NM-reg.txt     Thu Jan 
 1 01:00:00 1970
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/NM-reg.txt  Thu Apr  4 
16:05:44 2002
@@ -0,0 +1,69 @@
+NM2160 Register GUESS  
+   --- Overlay and ZV capture ---
+
+2002,2.3.
+
+1. Overlay
+  GRB0  bit5    Format; 0:YUY2/1:RGB
+        bit1    1
+        bit0    Enable overlay ; 1:enable/0:disable
+  GRB1  bit7:4  X2[11:8]
+        bit3:0  X1[11:8]
+  GRB2          X1[7:0]
+  GRB3          X2[7:0]
+  GRB4  bit7:4  Y2[11:8]
+        bit3:0  Y1[11:8]
+  GRB5          Y1[7:0]
+  GRB6          Y2[7:0]
+  GRB7          VRAM offset[24:17]
+  GRB8          VRAM offset[16:9]
+  GRB9          VRAM offset[8:1]
+  GRBA          Width in byte[15:8]
+  GRBB          Width in byte[7:0]
+  GRBC          0x4f
+  GRBD          -
+  GRBE          -
+  GRBF  bit2    0:normal/1:mirror
+        bit1:0  b'10'
+  GRC0          X scale[15:8] ; x1.0 == 0x1000
+  GRC1          X scale[7:0]
+  GRC2          Y scale[15:8] ; x1.0 == 0x1000
+  GRC3          Y scale[7:0]
+  GRC4          brightness   ; -128 to +127
+  GRC5          Color key(R)
+  GRC6          Color key(G) / Color key(8bpp)
+  GRC7          Color key(B)
+
+2. ZV capture
+  GR0A  bit5    Enable extended SR reg. ; 1:enable/0:disable
+        bit0    1
+
+  SR08  bit7:1  b'1010000'
+        bit0    Enable capture ; 1:enable/0:disable
+  SR09          0x11
+  SR0A          0x00
+  SR0B          -
+  SR0C          VRAM offset[8:1]
+  SR0D          VRAM offset[16:9]
+  SR0E          VRAM offset[24:17]
+  SR0F          -
+  SR10          -
+  SR11          -
+  SR12          -
+  SR13          -
+  SR14          Y1[7:0]
+  SR15          Y2[7:0]
+  SR16  bit7:4  Y2[11:4]
+        bit3:0  Y1[11:4]
+  SR17          X1[7:0]
+  SR18          X2[7:0]
+  SR19  bit7:4  X2[11:8]
+        bit3:0  X1[11:8]
+  SR1A          Width in byte[7:0]
+  SR1B          Width in byte[15:8]
+  SR1C          0xfb
+  SR1D          0x00
+  SR1E          0xe2
+  SR1F          0x02
+
[EMAIL PROTECTED]
diff -x CVS -uNr xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo.h 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo.h
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo.h  Mon Oct  1 
15:44:07 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo.h       Thu Apr  4 
16:05:44 2002
@@ -60,6 +60,11 @@
 
 #include "xf86i2c.h"
 
+#ifdef XvExtension
+# include "xf86xv.h"
+# include "Xv.h"
+#endif /* XvExtension */
+
 /*
  * Driver data structures.
  */
@@ -121,6 +126,10 @@
 /* in neo_dga.c */
 Bool NEODGAInit(ScreenPtr pScreen);
 
+/* in neo_video.c */
+extern void NEOInitVideo(ScreenPtr pScreen);
+extern void NEOResetVideo(ScrnInfoPtr pScrn);
+
 /* shadow regs */
 
 #define NEO_EXT_CR_MAX 0x85
@@ -199,6 +208,8 @@
     unsigned long NeoMMIOAddr;
     unsigned long NeoLinearAddr;
     unsigned char* NeoMMIOBase;
+    unsigned long NeoMMIOAddr2;
+    unsigned char* NeoMMIOBase2;
     unsigned char* NeoFbBase;
     long NeoFbMapSize;
     unsigned long vgaIOBase;
@@ -249,6 +260,17 @@
     RefreshAreaFuncPtr refreshArea;
     void       (*PointerMoved)(int index, int x, int y);
     int rotate;
+    Bool showcache;
+#ifdef XvExtension
+    Bool video;
+    double videoHZoom;
+    double videoVZoom;
+    XF86VideoAdaptorPtr overlayAdaptor;
+    int overlay;
+    int overlay_offset;
+    int videoKey;
+    int interlace;
+#endif /* XvExtension */
 } NEORec, *NEOPtr;
 
 typedef struct {
@@ -264,18 +286,20 @@
 #define GRAX   0x3CE
 
 /* vga IO functions */
-#define VGArCR(index) hwp->readCrtc(hwp,index)
-#define VGAwCR(index,val) hwp->writeCrtc(hwp,index,val)
-#define VGArGR(index) hwp->readGr(hwp,index)
-#define VGAwGR(index,val) hwp->writeGr(hwp,index,val)
+#define VGArCR(index)          (*hwp->readCrtc)(hwp, index)
+#define VGAwCR(index, val)     (*hwp->writeCrtc)(hwp, index, val)
+#define VGArGR(index)          (*hwp->readGr)(hwp, index)
+#define VGAwGR(index, val)     (*hwp->writeGr)(hwp, index, val)
+#define VGArSR(index)          (*hwp->readSeq)(hwp, index)
+#define VGAwSR(index, val)     (*hwp->writeSeq)(hwp, index, val)
 
 /* memory mapped register access macros */
-#define INREG8(addr) MMIO_IN8(nPtr->NeoMMIOBase, (addr))
-#define INREG16(addr) MMIO_IN16(nPtr->NeoMMIOBase, (addr))
-#define INREG(addr) MMIO_IN32(nPtr->NeoMMIOBase, (addr))
-#define OUTREG8(addr, val) MMIO_OUT8(nPtr->NeoMMIOBase, (addr), (val))
-#define OUTREG16(addr, val) MMIO_OUT16(nPtr->NeoMMIOBase, (addr), (val))
-#define OUTREG(addr, val) MMIO_OUT32(nPtr->NeoMMIOBase, (addr), (val))
+#define INREG8(addr)           MMIO_IN8(nPtr->NeoMMIOBase, addr)
+#define INREG16(addr)          MMIO_IN16(nPtr->NeoMMIOBase, addr)
+#define INREG(addr)            MMIO_IN32(nPtr->NeoMMIOBase, addr)
+#define OUTREG8(addr, val)     MMIO_OUT8(nPtr->NeoMMIOBase, addr, val)
+#define OUTREG16(addr, val)    MMIO_OUT16(nPtr->NeoMMIOBase, addr, val)
+#define OUTREG(addr, val)      MMIO_OUT32(nPtr->NeoMMIOBase, addr, val)
 
 /* This swizzle macro is to support the manipulation of cursor masks when
  * the sprite moves off the left edge of the display.  This code is
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2070.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2070.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2070.c     Tue Sep 
26 01:57:08 2000
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2070.c  Thu Apr  4 
16:05:44 2002
@@ -104,8 +104,6 @@
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     NEOPtr nPtr = NEOPTR(pScrn);
     NEOACLPtr nAcl = NEOACLPTR(pScrn);
-    BoxRec AvailFBArea;
-    int lines;
 
     nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
     if(!infoPtr) return FALSE;
@@ -158,23 +156,7 @@
     default:
        return FALSE;
     }
-
-    /* Initialize for widths */
-    nAcl->Pitch = pScrn->displayWidth * nAcl->PixelWidth;
-    lines = nAcl->cacheEnd /
-      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
-    if(lines > 1024) lines = 1024;
-
-    AvailFBArea.x1 = 0;
-    AvailFBArea.y1 = 0;
-    AvailFBArea.x2 = pScrn->displayWidth;
-    AvailFBArea.y2 = lines;
-    xf86InitFBManager(pScreen, &AvailFBArea); 
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-               "Using %i scanlines of offscreen memory for pixmap caching\n",
-                lines - pScrn->virtualY);
-
+    
     return(XAAInit(pScreen, infoPtr));
 
 }
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c     Mon Oct 
 1 15:44:07 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2090.c  Thu Apr  4 
16:05:44 2002
@@ -101,8 +101,6 @@
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     NEOPtr nPtr = NEOPTR(pScrn);
     NEOACLPtr nAcl = NEOACLPTR(pScrn);
-    BoxRec AvailFBArea;
-    int lines;
 
     nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
     if(!infoPtr) return FALSE;
@@ -197,20 +195,6 @@
 
     nAcl->BltCntlFlags |= NEO_BC3_FIFO_EN;
 
-    lines =  nAcl->cacheEnd /
-      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
-    if(lines > 1024) lines = 1024;
-
-    AvailFBArea.x1 = 0;
-    AvailFBArea.y1 = 0;
-    AvailFBArea.x2 = pScrn->displayWidth;
-    AvailFBArea.y2 = lines;
-    xf86InitFBManager(pScreen, &AvailFBArea); 
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-               "Using %i scanlines of offscreen memory for pixmap caching\n",
-                lines - pScrn->virtualY);
-
     return(XAAInit(pScreen, infoPtr));
 }
 
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2097.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2097.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2097.c     Mon Oct 
 1 15:44:07 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2097.c  Thu Apr  4 
16:05:44 2002
@@ -123,8 +123,6 @@
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     NEOPtr nPtr = NEOPTR(pScrn);
     NEOACLPtr nAcl = NEOACLPTR(pScrn);
-    int lines;
-    BoxRec AvailFBArea;
 
     nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
     if(!infoPtr) return FALSE;
@@ -245,21 +243,7 @@
     default:
        return FALSE;
     }
-
-    lines =  nAcl->cacheEnd /
-      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
-    if(lines > 1024) lines = 1024;
-
-    AvailFBArea.x1 = 0;
-    AvailFBArea.y1 = 0;
-    AvailFBArea.x2 = pScrn->displayWidth;
-    AvailFBArea.y2 = lines;
-    xf86InitFBManager(pScreen, &AvailFBArea); 
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-               "Using %i scanlines of offscreen memory for pixmap caching\n",
-               lines - pScrn->virtualY);
-
+    
     return(XAAInit(pScreen, infoPtr));
 }
 
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2200.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2200.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2200.c     Sun Oct 
28 04:33:42 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_2200.c  Thu Apr  4 
16:05:44 2002
@@ -120,8 +120,6 @@
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     NEOPtr nPtr = NEOPTR(pScrn);
     NEOACLPtr nAcl = NEOACLPTR(pScrn);
-    BoxRec AvailFBArea;
-    int lines;
 
     nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
     if(!infoPtr) return FALSE;
@@ -251,19 +249,6 @@
        return FALSE;
     }
 
-    lines =  nAcl->cacheEnd /
-      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
-    if(lines > 1024) lines = 1024;
-
-    AvailFBArea.x1 = 0;
-    AvailFBArea.y1 = 0;
-    AvailFBArea.x2 = pScrn->displayWidth;
-    AvailFBArea.y2 = lines;
-    xf86InitFBManager(pScreen, &AvailFBArea); 
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
-               "Using %i scanlines of offscreen memory for pixmap caching\n",
-                lines - pScrn->virtualY);
 
     return(XAAInit(pScreen, infoPtr));
 }
@@ -482,7 +467,7 @@
     NEOPtr nPtr = NEOPTR(pScrn);
 
     WAIT_ENGINE_IDLE();
-    OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
+    OUTREG(NEOREG_DSTSTARTOFF, (y <<16) | (x & 0xffff));
     OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
 }
 
diff -x CVS -uNr xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c      Mon Oct 
 1 15:44:07 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c   Thu Apr  4 
16:05:44 2002
@@ -43,8 +43,10 @@
 static void NEO_SetViewport(ScrnInfoPtr, int, int, int);
 static void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
 static void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
+#if 0
 static void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, 
                                        unsigned long);
+#endif
 
 static
 DGAFunctionRec NEODGAFuncs = {
@@ -76,7 +78,7 @@
    imlines =  (pScrn->videoRam * 1024) /
       (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
 
-   pixlines = (imlines > 1024 && !pNEO->noAccel)  ? 1024 : imlines;
+   pixlines =  (imlines > 1024 && !pNEO->noAccel)  ? 1024 : imlines;
 
    pMode = firstMode = pScrn->modes;
 
@@ -184,7 +186,7 @@
 ){
    NEOPtr pNEO = NEOPTR(pScrn);
    vgaHWPtr hwp = VGAHWPTR(pScrn);
-
+   
    NEOAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
    /* wait for retrace */
    while((hwp->readST01(hwp) & 0x08));
@@ -240,7 +242,7 @@
     }
 }
 
-
+#if 0
 static void 
 NEO_BlitTransRect(
    ScrnInfoPtr pScrn, 
@@ -252,7 +254,7 @@
   /* this one should be separate since the XAA function would
      prohibit usage of ~0 as the key */
 }
-
+#endif
 
 static Bool 
 NEO_OpenFramebuffer(
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c   Fri Nov 
30 13:11:57 2001
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_driver.c        Sat Apr 
 6 19:49:40 2002
@@ -299,7 +307,11 @@
     OPTION_PROG_LCD_MODE_REGS,
     OPTION_PROG_LCD_MODE_STRETCH,
     OPTION_OVERRIDE_VALIDATE_MODE,
+    OPTION_SHOWCACHE,
     OPTION_ROTATE,
+    OPTION_VIDEO_KEY,
+    OPTION_OVERLAYMEM,
+    OPTION_VIDEO_INTERLACE,
     OPTION_DISPLAY_HEIGHT_480,
     OPTION_STRANGE_LOCKUPS
 } NEOOpts;
@@ -314,6 +326,7 @@
     { OPTION_LCD_STRETCH, "NoStretch", OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_SHADOW_FB,   "ShadowFB",  OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_PCI_BURST,         "pciBurst",    OPTV_BOOLEAN,   {0}, FALSE },
+    { OPTION_SHOWCACHE,  "ShowCache",   OPTV_BOOLEAN,  {0}, FALSE },
     { OPTION_ROTATE,    "Rotate",      OPTV_ANYSTR,    {0}, FALSE },
     { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs",
       OPTV_BOOLEAN, {0}, FALSE },
@@ -321,6 +334,10 @@
       OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode",
       OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_VIDEO_KEY, "VideoKey",     OPTV_INTEGER,   {0}, FALSE },
+    { OPTION_OVERLAYMEM, "OverlayMem",  OPTV_INTEGER,   {0}, FALSE },
+    { OPTION_VIDEO_INTERLACE, "Interlace",
+      OPTV_INTEGER,   {0}, FALSE },
     { -1,                  NULL,           OPTV_NONE,  {0}, FALSE }
 };
 
@@ -335,6 +352,7 @@
     { OPTION_SHADOW_FB,  "ShadowFB",   OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_LCD_STRETCH,"NoStretch",  OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_PCI_BURST,         "pciBurst",    OPTV_BOOLEAN,   {0}, FALSE },
+    { OPTION_SHOWCACHE,  "ShowCache",   OPTV_BOOLEAN,  {0}, FALSE },
     { OPTION_ROTATE,    "Rotate",      OPTV_ANYSTR,    {0}, FALSE },
     { OPTION_STRANGE_LOCKUPS, "StrangeLockups", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_DISPLAY_HEIGHT_480, "DisplayHeight480",
@@ -345,6 +363,10 @@
       OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode",
       OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_VIDEO_KEY, "VideoKey",     OPTV_INTEGER,   {0}, FALSE },
+    { OPTION_OVERLAYMEM, "OverlayMem",  OPTV_INTEGER,   {0}, FALSE },
+    { OPTION_VIDEO_INTERLACE, "Interlace",
+      OPTV_INTEGER,   {0}, FALSE },
     { -1,                  NULL,           OPTV_NONE,  {0}, FALSE }
 };
 
@@ -979,6 +1001,7 @@
     xf86GetOptValBool(nPtr->Options, OPTION_LCD_CENTER,&nPtr->lcdCenter);
     xf86GetOptValBool(nPtr->Options, OPTION_LCD_STRETCH,&nPtr->noLcdStretch);
     xf86GetOptValBool(nPtr->Options, OPTION_SHADOW_FB,&nPtr->shadowFB);
+    xf86GetOptValBool(nPtr->Options, OPTION_SHOWCACHE,&nPtr->showcache);
     nPtr->onPciBurst = TRUE;
     xf86GetOptValBool(nPtr->Options, OPTION_PCI_BURST,&nPtr->onPciBurst);
     xf86GetOptValBool(nPtr->Options,
@@ -1014,6 +1037,39 @@
                       "Valid options are \"CW\" or \"CCW\"\n");
       }
     }
+#ifdef XvExtension
+    if(xf86GetOptValInteger(nPtr->Options,
+                           OPTION_VIDEO_KEY, &(nPtr->videoKey))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
+                  nPtr->videoKey);
+    } else {
+        nPtr->videoKey = (1 << pScrn->offset.red) | 
+           (1 << pScrn->offset.green) |
+           (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
+            << pScrn->offset.blue); 
+    }
+    if(xf86GetOptValInteger(nPtr->Options, OPTION_OVERLAYMEM,
+                           &(nPtr->overlay))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+                  "reserve %d bytes for overlay.\n", nPtr->overlay);
+    } else {
+       nPtr->overlay = 0;
+    }
+    nPtr->interlace = 0;
+    if(xf86GetOptValInteger(nPtr->Options, OPTION_VIDEO_INTERLACE,
+                           &(nPtr->interlace))) {
+       if (nPtr->interlace >= 0  &&  nPtr->interlace <= 2){
+           xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "interlace flag = %d\n",
+                      nPtr->interlace);
+       } else {
+           xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+                      "\"%s\" is not a valid value for "
+                      "Option \"Interlaced\"\n", s);
+           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are  0..2\n");
+        }
+    }
+#endif /* XvExtension */
+
 
     if (height_480 && nPtr->NeoPanelWidth == 800) {
        xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
@@ -1069,6 +1125,9 @@
     if (nPtr->strangeLockups)
        xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
                   "Option StrangeLockups set: disabling some acceleration\n");
+    if (nPtr->showcache)
+       xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,
+                  "Show chache for debugging\n");
     if (nPtr->shadowFB) {
        if (nPtr->noLinear) {
            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
@@ -1096,6 +1155,8 @@
        nPtr->NeoLinearAddr = 0;
     }
 
+    nPtr->NeoMMIOAddr2 = 0;
+    nPtr->NeoMMIOBase2 = NULL;
     if (nPtr->pEnt->device->IOBase && !nPtr->noMMIO) {
        /* XXX Check this matches a PCI base address */
        nPtr->NeoMMIOAddr = nPtr->pEnt->device->IOBase;
@@ -1113,7 +1174,7 @@
                       "FB base address is set at 0x%X.\n",
                       nPtr->NeoLinearAddr);
        }
-       if (!nPtr->NeoMMIOAddr) {
+       if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) {
            switch (nPtr->NeoChipset) {
            case NM2070 :
                nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000;
@@ -1129,11 +1190,17 @@
            case NM2360:
            case NM2380:
                nPtr->NeoMMIOAddr = nPtr->PciInfo->memBase[1];
+               nPtr->NeoMMIOAddr2 = nPtr->PciInfo->memBase[2];
                break;
            }
            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                       "MMIO base address is set at 0x%X.\n",
                       nPtr->NeoMMIOAddr);
+           if (nPtr->NeoMMIOAddr2 != 0){
+               xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+                          "MMIO base address2 is set at 0x%X.\n",
+                          nPtr->NeoMMIOAddr2);
+           }
        }
        /* XXX What about VGA resources in OPERATING mode? */
        if (xf86RegisterResources(nPtr->pEnt->index, NULL, ResExclusive))
@@ -1152,7 +1219,7 @@
                       "FB base address is set at 0x%X.\n",
                       nPtr->NeoLinearAddr);
        }
-       if (!nPtr->NeoMMIOAddr) {
+       if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) {
            nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000;
            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                       "MMIO base address is set at 0x%X.\n",
@@ -1293,6 +1360,10 @@
     /* Should we re-save the text mode on each VT enter? */
     if(!neoModeInit(pScrn, pScrn->currentMode))
       return FALSE;
+#ifdef XvExtension
+    if (nPtr->video)
+       NEOResetVideo(pScrn);
+#endif
     if (nPtr->NeoHWCursorShown) 
        NeoShowCursor(pScrn);
     NEOAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);    
@@ -1384,12 +1455,12 @@
     /* Map the Neo memory and possible MMIO areas */
     if (!neoMapMem(pScrn))
        return FALSE;
-
+    
     /*
      * next we save the current state and setup the first mode
      */
     neoSave(pScrn);
-
+    
     if (!neoModeInit(pScrn,pScrn->currentMode))
        return FALSE;
     vgaHWSaveScreen(pScreen,SCREEN_SAVER_ON);
@@ -1431,7 +1502,7 @@
        nPtr->ShadowPtr = NULL;
        FBStart = nPtr->NeoFbBase;
     }
-
+    
     ret = fbScreenInit(pScreen, FBStart,
                            width, height,
                            pScrn->xDpi, pScrn->yDpi,
@@ -1509,13 +1580,13 @@
                   nPtr->NeoLinearAddr);
        /* Setup pointers to free space in video ram */
        allocatebase = (pScrn->videoRam << 10);
-       freespace = allocatebase - pScrn->displayWidth * 
+       freespace = allocatebase - pScrn->displayWidth *
            pScrn->virtualY * (pScrn->bitsPerPixel >> 3);
        currentaddr = allocatebase;
        xf86DrvMsg(scrnIndex, X_PROBED,
                   "%d bytes off-screen memory available\n", freespace);
 
-       if (nPtr->swCursor || nPtr->noMMIO) {
+       if (nPtr->swCursor || !nPtr->NeoMMIOBase) {
            xf86DrvMsg(scrnIndex, X_CONFIG,
                       "Using Software Cursor.\n");
        } else if (nPtr->NeoCursorMem <= freespace) {
@@ -1530,19 +1601,52 @@
        } else xf86DrvMsg(scrnIndex, X_ERROR,
                          "Too little space for H/W cursor.\n");
        
-       if (!nPtr->noAccel && nPtr->noMMIO)
+       if (!nPtr->noAccel && !nPtr->NeoMMIOBase)
          xf86DrvMsg(pScrn->scrnIndex,X_INFO,
                     "Acceleration disabled when not using MMIO\n");
-
-       /* Setup the acceleration primitives */
-       if (!nPtr->noAccel && !nPtr->noMMIO) {
+       {
+#ifdef XvExtension
+           if (nPtr->overlay > 0){
+               if (nPtr->overlay > freespace){
+                   xf86DrvMsg(pScrn->scrnIndex,X_INFO,
+                              "Can not reserve %d bytes for overlay. "
+                              "Resize to %d bytes.\n",
+                              nPtr->overlay, freespace);
+                   nPtr->overlay = freespace;
+               }
+               currentaddr -= nPtr->overlay;
+               freespace -= nPtr->overlay;
+               nPtr->overlay_offset = currentaddr;
+               xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Overlay at 0x%x\n",
+                          nPtr->overlay_offset);
+           }
+#endif /* XvExtension */
            nAcl->cacheStart = currentaddr - freespace;
            nAcl->cacheEnd = currentaddr;
            freespace = 0;
+           if (nAcl->cacheStart < nAcl->cacheEnd) {
+               BoxRec AvailFBArea;
+               int lines = nAcl->cacheEnd /
+                   (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
+               if (!nPtr->noAccel && nPtr->NeoMMIOBase && lines > 1024) 
+                   lines = 1024;
+               AvailFBArea.x1 = 0;
+               AvailFBArea.y1 = 0;
+               AvailFBArea.x2 = pScrn->displayWidth;
+               AvailFBArea.y2 = lines;
+               xf86InitFBManager(pScreen, &AvailFBArea); 
+
+               xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
+                          "Using %i scanlines of offscreen memory \n"
+                          , lines - pScrn->virtualY);
+           }
+       }
+       /* Setup the acceleration primitives */
+       if (!nPtr->noAccel && nPtr->NeoMMIOBase) {
            if (nAcl->cacheStart >= nAcl->cacheEnd) {
                xf86DrvMsg(scrnIndex, X_ERROR,
                           "Too little space for pixmap cache.\n");
-           }
+           }       
            switch(nPtr->NeoChipset) {
            case NM2070 :
                Neo2070AccelInit(pScreen);
@@ -1624,6 +1728,8 @@
 
     pScrn->racIoFlags = pScrn->racMemFlags = racflag;
 
+    NEOInitVideo(pScreen);
+
     pScreen->SaveScreen = vgaHWSaveScreen;
 
     /* Setup DPMS mode */
@@ -1635,18 +1741,7 @@
         pScrn->memPhysBase = (unsigned long)nPtr->NeoFbBase;
        pScrn->fbOffset = 0;
     }
-
-#ifdef XvExtension
-    {
-        XF86VideoAdaptorPtr *ptr;
-       int n;
-       
-       n = xf86XVListGenericAdaptors(pScrn,&ptr);
-       if (n)
-           xf86XVScreenInit(pScreen, ptr, n);
-    }
-#endif
-
+    
     /* Wrap the current CloseScreen function */
     nPtr->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = NEOCloseScreen;
@@ -1677,11 +1772,21 @@
     int Base; 
 
     pScrn = xf86Screens[scrnIndex];
-    Base = (y * pScrn->displayWidth + x) >> 2;
     hwp = VGAHWPTR(pScrn);
     nPtr = NEOPTR(pScrn);
-    /* Scale Base by the number of bytes per pixel. */
 
+    if (nPtr->showcache && y) {
+       int lastline = nPtr->NeoFbMapSize / 
+           ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
+       
+       lastline -= pScrn->currentMode->VDisplay;
+       y += pScrn->virtualY - 1;
+        if (y > lastline) y = lastline;
+    }
+
+    Base = (y * pScrn->displayWidth + x) >> 2;
+
+    /* Scale Base by the number of bytes per pixel. */
     switch (pScrn->depth) {
     case  8 :
        break;
@@ -1730,6 +1835,7 @@
        if (nPtr->NeoHWCursorShown)
            NeoHideCursor(pScrn);
        neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, 
TRUE);
+
        neoLock(pScrn);
        neoUnmapMem(pScrn);
     }
@@ -1845,12 +1951,18 @@
 
     if (!nPtr->noLinear) {
        if (!nPtr->noMMIO) {
-           if (nPtr->pEnt->location.type == BUS_PCI)
+           if (nPtr->pEnt->location.type == BUS_PCI){
                nPtr->NeoMMIOBase =
                    xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
                                  nPtr->PciTag, nPtr->NeoMMIOAddr,
                                  0x200000L);
-           else
+               if (nPtr->NeoMMIOAddr2 != 0){
+                   nPtr->NeoMMIOBase2 =
+                       xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
+                                     nPtr->PciTag, nPtr->NeoMMIOAddr2,
+                                     0x100000L);
+               }
+           } else
                nPtr->NeoMMIOBase =
                    xf86MapVidMem(pScrn->scrnIndex,
                                  VIDMEM_MMIO, nPtr->NeoMMIOAddr,
@@ -1889,8 +2001,14 @@
     NEOPtr nPtr = NEOPTR(pScrn);
 
     if (!nPtr->noLinear) {
-      xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase, 0x200000L);
+      if (nPtr->NeoMMIOBase)
+         xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase,
+                         0x200000L);
       nPtr->NeoMMIOBase = NULL;
+      if (nPtr->NeoMMIOBase2)
+         xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase2,
+                         0x100000L);
+      nPtr->NeoMMIOBase2 = NULL;
       xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoFbBase,
                    nPtr->NeoFbMapSize); 
     }
@@ -2200,7 +2318,7 @@
     unsigned char temp;
     int i;
     Bool clock_hi = FALSE;
-    
+
     vgaHWProtect(pScrn,TRUE);          /* Blank the screen */
     
     VGAwGR(0x09,0x26);
@@ -2220,6 +2338,7 @@
      * any reserved bits.
      */
     temp = VGArGR(0x90);
+
     switch (nPtr->NeoChipset) {
     case NM2070 :
        temp &= 0xF0; /* Save bits 7:4 */
@@ -2238,6 +2357,7 @@
        break;
     }
     VGAwGR(0x90,temp);
+
     /*
      * In some rare cases a lockup might occur if we don't delay
      * here. (Reported by Miles Lane)
@@ -2256,7 +2376,6 @@
      * had time to take effect.
      */
     xf86UDelay(200000);
-
     /*
      * This function handles restoring the generic VGA registers.  */
     vgaHWRestore(pScrn, VgaReg,
@@ -2273,6 +2392,7 @@
     VGAwGR(0x11, restore->SysIfaceCntl2);
     VGAwGR(0x15, restore->SingleAddrPage);
     VGAwGR(0x16, restore->DualAddrPage);
+
     temp = VGArGR(0x20);
     switch (nPtr->NeoChipset) {
     case NM2070 :
@@ -2349,7 +2469,7 @@
     }
     if (restore->biosMode)
        VGAwCR(0x23,restore->biosMode);
-    
+
     if (restore->reg) {
        VGAwCR(0x23,restore->reg->CR[0x23]);
        VGAwCR(0x25,restore->reg->CR[0x25]);
@@ -2371,13 +2491,13 @@
            VGAwGR(i, restore->reg->GR[i]);
        }
     }
+
     /* Program vertical extension register */
     if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230
        || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) {
        VGAwCR(0x70, restore->VerticalExt);
     }
-
-
+    
     vgaHWProtect(pScrn, FALSE);                /* Turn on screen */
 
 }
@@ -2574,7 +2694,7 @@
     NeoNew->PanelHorizCenterReg3 = 0x00;
     NeoNew->PanelHorizCenterReg4 = 0x00;
     NeoNew->PanelHorizCenterReg5 = 0x00;
-
+    
     if (nPtr->lcdCenter &&
        (NeoNew->PanelDispCntlReg1 & 0x02)) {
        if (mode->HDisplay == nPtr->NeoPanelWidth) {
@@ -2632,6 +2752,18 @@
            }
        }
     }
+#ifdef XvExtension
+    if (!noLcdStretch)  {
+       if (mode->HDisplay != nPtr->NeoPanelWidth)
+           nPtr->videoHZoom = (double)nPtr->NeoPanelWidth/mode->HDisplay;
+       if (mode->VDisplay != nPtr->NeoPanelHeight)
+           nPtr->videoVZoom = (double)nPtr->NeoPanelHeight/mode->VDisplay;
+    } else {
+       nPtr->videoHZoom = 1.0;
+       nPtr->videoVZoom = 1.0;
+    }
+#endif
+    
     NeoNew->biosMode = neoFindMode(mode->HDisplay,mode->VDisplay,pScrn->depth);
     
     /*
@@ -2764,9 +2896,8 @@
     }
 
     /* Turn the screen on/off */
-    outb(0x3C4, 0x01);
-    SEQ01 |= inb(0x3C5) & ~0x20;
-    outb(0x3C5, SEQ01);
+    SEQ01 |= VGArSR(0x01) & ~0x20;
+    VGAwSR(0x01, SEQ01);
 
     /* Turn the LCD on/off */
     LCD_on |= VGArGR(0x20) & ~0x02;
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.c 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.c
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.c    Thu Jan 
 1 01:00:00 1970
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.c Thu Apr  4 
16:05:44 2002
@@ -0,0 +1,1232 @@
+/**********************************************************************
+Copyright 2002 by Shigehiro Nomura.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, distribute, and sell this software and
+its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Shigehiro Nomura not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  Shigehiro Nomura
+and its suppliers make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+
+SHIGEHIRO NOMURA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL SHIGEHIRO NOMURA AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+**********************************************************************/
+
+/*
+ * Copyright 2002 SuSE Linux AG, Author: Egbert Eich
+ */
+
+#include "neo.h"
+#include "neo_video.h"
+
+#define nElems(x)              (sizeof(x) / sizeof(x[0]))
+#define MAKE_ATOM(a)   MakeAtom(a, sizeof(a) - 1, TRUE)
+
+#if defined(XvExtension)
+
+#include "dixstruct.h"
+#include "xaa.h"
+#include "xaalocal.h"
+
+static XF86VideoAdaptorPtr NEOSetupVideo(ScreenPtr);
+
+static int NEOPutVideo(ScrnInfoPtr, short, short, short, short, 
+                      short, short, short, short, RegionPtr, pointer);
+
+static void NEOStopVideo(ScrnInfoPtr, pointer, Bool);
+static int NEOSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
+static int NEOGetPortAttribute(ScrnInfoPtr, Atom, INT32 *, pointer);
+static void NEOQueryBestSize(ScrnInfoPtr, Bool, short, short, short, 
+                            short, unsigned int *, unsigned int *, pointer);
+static int NEOPutImage(ScrnInfoPtr, short, short, short, short, short, short, 
+                      short, short, int, unsigned char *, short, short, Bool,
+                      RegionPtr, pointer);
+static int NEOQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, 
+                                  unsigned short *, int *, int *);
+
+static Bool RegionsEqual(RegionPtr, RegionPtr);
+static void NEODisplayVideo(ScrnInfoPtr, int, int, short, short, int, int, 
+                           int, int, int, BoxPtr, short, short, short, short);
+
+static void NEOInitOffscreenImages(ScreenPtr);
+static FBLinearPtr NEOAllocateMemory(ScrnInfoPtr, FBLinearPtr, int);
+static void NEOCopyData(unsigned char *, unsigned char *, int, int, int, int);
+static void NEOCopyYV12Data(unsigned char *, unsigned char *, unsigned char *,
+                           unsigned char *, int, int, int, int, int);
+
+static int NEOAllocSurface(ScrnInfoPtr, int, unsigned short, unsigned short, 
+                          XF86SurfacePtr);
+static int NEOFreeSurface(XF86SurfacePtr);
+static int NEODisplaySurface(XF86SurfacePtr, short, short, short, short, 
+                            short, short, short, short, RegionPtr clipBoxes);
+static int NEOStopSurface(XF86SurfacePtr);
+static int NEOGetSurfaceAttribute(ScrnInfoPtr, Atom, INT32 *);
+static int NEOSetSurfaceAttribute(ScrnInfoPtr, Atom, INT32);
+
+static Atom xvColorKey, xvBrightness, xvInterlace;
+
+void
+NEOInitVideo(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    NEOPtr nPtr = NEOPTR(pScrn);
+    XF86VideoAdaptorPtr *overlayAdaptors, *newAdaptors = NULL;
+    XF86VideoAdaptorPtr newAdaptor = NULL;
+    int numAdaptors;
+
+    numAdaptors = xf86XVListGenericAdaptors(pScrn, &overlayAdaptors);
+
+    if (nPtr->NeoChipset >= NM2160 
+       && !nPtr->noLinear 
+       && nPtr->NeoMMIOBase2 != NULL){
+       nPtr->video = TRUE;
+       newAdaptor = NEOSetupVideo(pScreen);
+       NEOInitOffscreenImages(pScreen);
+    } else
+       nPtr->video = FALSE;
+
+    if (newAdaptor){
+       if (!numAdaptors){
+           numAdaptors = 1;
+           overlayAdaptors = &newAdaptor;
+       } else {
+           newAdaptors = xalloc((numAdaptors + 1) 
+                                * sizeof(XF86VideoAdaptorPtr*));
+           if (newAdaptors){
+               memcpy(newAdaptors, overlayAdaptors, 
+                      numAdaptors * sizeof(XF86VideoAdaptorPtr));
+               newAdaptors[numAdaptors++] = newAdaptor;
+               overlayAdaptors = newAdaptors;
+           }
+       }
+    }
+
+    if (numAdaptors)
+       xf86XVScreenInit(pScreen, overlayAdaptors, numAdaptors);
+
+    if (newAdaptors)
+       xfree(newAdaptors);
+}
+
+static XF86VideoEncodingRec NEOVideoEncodings[] =
+{
+    {
+       NEO_VIDEO_VIDEO,
+       "XV_VIDEO",
+       1024, 1024,
+       {1, 1}
+    },
+    {
+       NEO_VIDEO_IMAGE,
+       "XV_IMAGE",
+       1024, 1024,
+       {1, 1}
+    }
+};
+
+static XF86VideoFormatRec NEOVideoFormats[] =
+{
+    {  8, PseudoColor },
+    { 15, TrueColor },
+    { 16, TrueColor },
+    { 24, TrueColor },
+};
+
+static XF86AttributeRec NEOVideoAttributes[] =
+{
+    {
+       XvSettable | XvGettable,
+       0x000000, 0xFFFFFF,
+       "XV_COLORKEY"
+    },
+    {
+       XvSettable | XvGettable,
+       -128, 127,
+       "XV_BRIGHTNESS"
+    },
+    {
+       XvSettable | XvGettable,
+       0,2,
+       "XV_INTERLACE"
+    },
+};
+
+static XF86ImageRec NEOVideoImages[] =
+{
+    XVIMAGE_YUY2,
+    XVIMAGE_YV12,
+    XVIMAGE_I420,
+    {
+       FOURCC_RV15,
+       XvRGB,
+       LSBFirst,
+       { 'R', 'V' ,'1', '5',
+         0x00,'5',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
+       16,
+       XvPacked,
+       1,
+       15, 0x001F, 0x03E0, 0x7C00,
+       0, 0, 0,
+       0, 0, 0,
+       0, 0, 0,
+       { 'R', 'V', 'B' },
+       XvTopToBottom
+    },
+    {
+       FOURCC_RV16,
+       XvRGB,
+       LSBFirst,
+       { 'R', 'V' ,'1', '6',
+         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+       16,
+       XvPacked,
+       1,
+       16, 0x001F, 0x07E0, 0xF800,
+       0, 0, 0,
+       0, 0, 0,
+       0, 0, 0,
+       { 'R', 'V', 'B' },
+       XvTopToBottom
+    }
+};
+
+static XF86VideoAdaptorPtr
+NEOSetupVideo(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    NEOPtr nPtr = NEOPTR(pScrn);
+    NEOPortPtr pPriv;
+    XF86VideoAdaptorPtr overlayAdaptor;
+    int i;
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetupVideo\n");
+#endif
+    if ((overlayAdaptor = xcalloc(1, sizeof(XF86VideoAdaptorRec) +
+                             sizeof(DevUnion) + 
+                             sizeof(NEOPortRec))) == NULL){
+       return (NULL);
+    }
+
+    overlayAdaptor->type = XvInputMask | XvImageMask | XvWindowMask 
+       | XvOutputMask | XvVideoMask;
+    overlayAdaptor->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+    overlayAdaptor->name = "NeoMagic Video Engine";
+    overlayAdaptor->nEncodings = nElems(NEOVideoEncodings);
+    overlayAdaptor->pEncodings = NEOVideoEncodings;
+    for (i = 0; i < nElems(NEOVideoEncodings); i++){
+       NEOVideoEncodings[i].width = 1024;
+       NEOVideoEncodings[i].height = 1024;
+    }
+    overlayAdaptor->nFormats = nElems(NEOVideoFormats);
+    overlayAdaptor->pFormats = NEOVideoFormats;
+    overlayAdaptor->nPorts = 1;
+    overlayAdaptor->pPortPrivates = (DevUnion*) &overlayAdaptor[1];
+    overlayAdaptor->pPortPrivates[0].ptr = 
+       (pointer) &overlayAdaptor->pPortPrivates[1];
+    overlayAdaptor->nAttributes = nElems(NEOVideoAttributes);
+    overlayAdaptor->pAttributes = NEOVideoAttributes;
+    overlayAdaptor->nImages = nElems(NEOVideoImages);
+    overlayAdaptor->pImages = NEOVideoImages;
+
+    overlayAdaptor->PutVideo = NEOPutVideo;
+    overlayAdaptor->PutStill = NULL;
+    overlayAdaptor->GetVideo = NULL;
+    overlayAdaptor->GetStill = NULL;
+
+    overlayAdaptor->StopVideo = NEOStopVideo;
+    overlayAdaptor->SetPortAttribute = NEOSetPortAttribute;
+    overlayAdaptor->GetPortAttribute = NEOGetPortAttribute;
+    overlayAdaptor->QueryBestSize = NEOQueryBestSize;
+    overlayAdaptor->PutImage = NEOPutImage;
+    overlayAdaptor->QueryImageAttributes = NEOQueryImageAttributes;
+
+    pPriv = (NEOPortPtr)overlayAdaptor->pPortPrivates[0].ptr;
+    pPriv->colorKey = nPtr->videoKey;
+    pPriv->interlace = nPtr->interlace;
+    pPriv->videoStatus = 0;
+    pPriv->brightness = 0;
+    REGION_INIT(pScreen, &pPriv->clip, NullBox, 0);
+    nPtr->overlayAdaptor = overlayAdaptor;
+
+    xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+    xvColorKey = MAKE_ATOM("XV_COLORKEY");
+    xvInterlace = MAKE_ATOM("XV_INTERLACE");
+    
+    NEOResetVideo(pScrn);
+
+    return (overlayAdaptor);
+}
+
+void
+NEOResetVideo(ScrnInfoPtr pScrn)
+{
+    NEOPtr nPtr = NEOPTR(pScrn);
+    NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr;
+    int r, g, b;
+    VGA_HWP(pScrn);
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOResetVideo\n");
+#endif
+    switch (pScrn->depth){
+    case 8:
+       OUTGR(0xc6, pPriv->colorKey & 0);
+       OUTGR(0xc5, pPriv->colorKey & 0xff);
+       OUTGR(0xc7, pPriv->colorKey & 0);
+       break;
+    default:
+       r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
+       g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
+       b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
+       OUTGR(0xc5, r);
+       OUTGR(0xc6, g);
+       OUTGR(0xc7, b);
+       break;
+    }
+    OUTGR(0xc4, pPriv->brightness);
+}
+
+static int
+NEOPutVideo(ScrnInfoPtr pScrn, 
+            short src_x, short src_y, short drw_x, short drw_y,
+            short src_w, short src_h, short drw_w, short drw_h,
+            RegionPtr clipBoxes, pointer data)
+{
+    NEOPortPtr pPriv = (NEOPortPtr)data;
+    NEOPtr nPtr = NEOPTR(pScrn);
+    CARD32 src_pitch, offset;
+    int xscale, yscale;
+    BoxRec dstBox;
+    INT32 x1, y1, x2, y2;
+    int size, bpp;
+    unsigned char capctrl;
+    VGA_HWP(pScrn);
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: src: %d %d %d %d\n", 
+              src_x, src_y, src_w, src_h);
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: drw: %d %d %d %d\n", 
+              drw_x, drw_y, drw_w, drw_h);
+#endif
+    if (src_w > 720)
+       src_w = 720;
+    if (src_h > 576)
+        src_h = 576;
+    if (pPriv->interlace != 2)
+       src_h /= 2;
+    x1 = src_x;
+    y1 = src_y;
+    x2 = src_x + src_w;
+    y2 = src_y + src_h;
+
+    dstBox.x1 = drw_x;
+    dstBox.y1 = drw_y;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y2 = drw_y + drw_h;
+
+    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
+                              clipBoxes, src_w, src_h)){
+       return(Success);
+    }
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: %d %d %d %d\n", 
+              x1, y1, x2, y2);
+#endif
+
+    dstBox.x1 -= pScrn->frameX0;
+    dstBox.y1 -= pScrn->frameY0;
+    dstBox.x2 -= pScrn->frameX0;
+    dstBox.y2 -= pScrn->frameY0;
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: dstBox %d %d %d %d\n", 
+              dstBox.x1, dstBox.y1, dstBox.x2, dstBox.y2);
+#endif
+
+    bpp = (pScrn->bitsPerPixel + 1) >> 3;
+    src_pitch = (src_w + 7) & ~7;
+
+    xscale = 0x1000;
+    if (src_w <= drw_w){
+       xscale = (src_w * 0x1000 / drw_w) & 0xffff;
+    }
+
+    yscale = 0x1000;
+    if (src_h <= drw_h){
+       yscale = (src_h * 0x1000 / drw_h) & 0xffff;
+    }
+
+    size = src_h * src_pitch * 2;
+
+    if (size > nPtr->overlay){
+       if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) 
+           == NULL){
+           return (BadAlloc);
+       }
+    } else {
+       pPriv->linear = NULL;
+    }
+    
+    if (pPriv->linear == NULL){
+       offset = nPtr->overlay_offset;
+    } else {
+       offset = pPriv->linear->offset * bpp;
+    }
+    
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutVideo: offset=0x%x\n", offset);
+#endif
+     WAIT_ENGINE_IDLE();
+     memset(nPtr->NeoFbBase + offset, 0, size);
+
+    if (!RegionsEqual(&pPriv->clip, clipBoxes)){
+       REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+       xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey,
+                           clipBoxes);
+    }
+
+    x1 >>= 16;
+    y1 >>= 16;
+    x2 >>= 16;
+    y2 >>= 16;
+
+    switch (nPtr->NeoChipset) {
+    default:
+    case NM2160: 
+       offset/=2;
+       OUTGR(0xbc, 0x4f);
+       break;
+    case NM2200:
+    case NM2230:
+    case NM2360:
+    case NM2380:
+       OUTGR(0xbc, 0x2e);
+       break;
+    }
+ 
+
+    OUTGR(0xb1, (((dstBox.x2-1) >> 4) & 0xf0) | ((dstBox.x1 >> 8) & 0x0f));
+    OUTGR(0xb2, dstBox.x1);
+    OUTGR(0xb3, dstBox.x2 - 1);
+    OUTGR(0xb4, (((dstBox.y2 - 1) >> 4) & 0xf0) | ((dstBox.y1 >> 8) & 0x0f));
+    OUTGR(0xb5, dstBox.y1);
+    OUTGR(0xb6, dstBox.y2 - 1);
+    OUTGR(0xb7, offset >> 16);
+    OUTGR(0xb8, offset >> 8);
+    OUTGR(0xb9, offset );
+    OUTGR(0xba, src_pitch >> 8);
+    OUTGR(0xbb, src_pitch);
+
+    OUTGR(0xc0, xscale >> 8);
+    OUTGR(0xc1, xscale);
+    OUTGR(0xc2, yscale >> 8);
+    OUTGR(0xc3, yscale);
+    OUTGR(0xbf, 0x02);
+
+    OUTGR(0x0a, 0x21);
+
+    OUTSR(0x0c, offset );
+    OUTSR(0x0d, offset >> 8);
+    OUTSR(0x0e, offset >> 16);
+    OUTSR(0x1a, src_pitch);
+    OUTSR(0x1b, src_pitch>>8);
+
+    OUTSR(0x17, 0 + x1);
+    OUTSR(0x18, 0 + x2 -1);
+    OUTSR(0x19, (((0 + x2 - 1) >> 4) & 0xf0) | (((0 + x1) >> 8) & 0x0f));
+
+    OUTSR(0x14, 14 + y1);
+    OUTSR(0x15, 14 + y2 - 2);
+    OUTSR(0x16, (((14 + y2 - 1) >> 4) & 0xf0) | (((14 + y1) >> 8) & 0x0f));
+
+    OUTSR(0x1c, 0xfb);
+    OUTSR(0x1d, 0x00);
+    OUTSR(0x1e, 0xe2);
+    OUTSR(0x1f, 0x02);
+
+    OUTSR(0x09, 0x11);
+    OUTSR(0x0a, 0x00);
+
+    capctrl = 0x21;
+    switch (pPriv->interlace){
+    case 0: /* Combine 2 fields */
+       break;
+    case 1: /* one field only */
+       capctrl |= 0x80;
+       break;
+    case 2: /* Interlaced fields */
+       capctrl |= 0x40;
+       break;
+    }
+    OUTSR(0x08, capctrl);
+
+#if 0
+    OUTGR(0x0a, 0x01);
+#endif
+    OUTGR(0xb0, 0x03);
+
+    pPriv->videoStatus = CLIENT_VIDEO_ON;
+    return (Success);
+}
+
+static void
+NEOStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit)
+{
+    NEOPortPtr pPriv = (NEOPortPtr)data;
+    NEOPtr nPtr = NEOPTR(pScrn);
+    VGA_HWP(pScrn);
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo\n");
+#endif
+    REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
+
+    if (exit){
+       if (pPriv->videoStatus & CLIENT_VIDEO_ON){
+#ifdef DEBUG
+            xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOStopVideo: stop capture\n");
+#endif
+           OUTGR(0xb0, 0x02);
+           OUTGR(0x0a, 0x21);
+           OUTSR(0x08, 0xa0);
+#if 0
+           OUTGR(0x0a, 0x01);
+#endif
+       }
+       if (pPriv->linear != NULL){
+           xf86FreeOffscreenLinear(pPriv->linear);
+           pPriv->linear = NULL;
+       }
+       pPriv->videoStatus = 0;
+    } else {
+       if (pPriv->videoStatus & CLIENT_VIDEO_ON){
+           OUTGR(0xb0, 0x02);
+           OUTGR(0x0a, 0x21);
+           OUTSR(0x08, 0xa0);
+#if 0
+           OUTGR(0x0a, 0x01);
+#endif
+           pPriv->videoStatus |= OFF_TIMER;
+           pPriv->offTime = currentTime.milliseconds + OFF_DELAY;
+       }
+    }
+}
+
+static int
+NEOSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, 
+                   pointer data)
+{
+    NEOPortPtr pPriv = (NEOPortPtr)data;
+    NEOPtr nPtr = NEOPTR(pScrn);
+    VGA_HWP(pScrn);
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetPortAttribute\n");
+#endif
+    if (attribute == xvColorKey){
+       int r, g, b;
+
+       pPriv->colorKey = value;
+       switch (pScrn->depth){
+       case 8:
+           OUTGR(0xc6, pPriv->colorKey & 0xff);
+           OUTGR(0xc5, 0x00);
+           OUTGR(0xc7, 0x00);
+           break;
+       default:
+           r = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red;
+           g = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green;
+           b = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue;
+           OUTGR(0xc5, r);
+           OUTGR(0xc6, g);
+           OUTGR(0xc7, b);
+       }
+    } else if (attribute == xvBrightness){
+       if ((value < -128) || (value > 127)){
+           return (BadValue);
+       }
+       pPriv->brightness = value;
+       OUTGR(0xc4, value);
+    } else if (attribute == xvInterlace){
+       if (value < 0  ||  value > 2){
+           return (BadValue);
+       }
+       pPriv->interlace = value;
+    } else {
+       return (BadMatch);
+    }
+    return (Success);
+}
+
+static int
+NEOGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, 
+                   pointer data)
+{
+    NEOPortPtr pPriv = (NEOPortPtr)data;
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetPortAttribute\n");
+#endif
+    if (attribute == xvColorKey){
+       *value = pPriv->colorKey;
+    } else if (attribute == xvBrightness){
+       *value = pPriv->brightness;
+    } else if (attribute == xvInterlace){
+       *value = pPriv->interlace;
+    } else {
+       return (BadMatch);
+    }
+    return (Success);
+}
+
+static void
+NEOQueryBestSize(ScrnInfoPtr pScrn, Bool motion, 
+                short vid_w, short vid_h, short drw_w, short drw_h,
+                unsigned int *p_w, unsigned int *p_h,
+                pointer data)
+{
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryBestSize\n");
+#endif
+    *p_w = min(drw_w, 1024);
+    *p_h = min(drw_h, 1024);
+}
+
+static int
+NEOPutImage(ScrnInfoPtr pScrn, 
+           short src_x, short src_y, short drw_x, short drw_y,
+           short src_w, short src_h, short drw_w, short drw_h,
+           int id, unsigned char *buf, short width, short height,
+           Bool sync, RegionPtr clipBoxes, pointer data)
+{
+    NEOPtr nPtr = NEOPTR(pScrn);
+    NEOPortPtr pPriv = (NEOPortPtr)nPtr->overlayAdaptor->pPortPrivates[0].ptr;
+    INT32 x1, y1, x2, y2;
+    int bpp;
+    int srcPitch, srcPitch2 = 0, dstPitch, size;
+    BoxRec dstBox;
+    CARD32 offset, offset2 = 0, offset3 = 0, tmp;
+    int left, top, nPixels, nLines;
+    unsigned char *dstStart;
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOPutImage\n");
+#endif
+
+    x1 = src_x;
+    y1 = src_y;
+    x2 = src_x + src_w;
+    y2 = src_y + src_h;
+    
+    dstBox.x1 = drw_x;
+    dstBox.y1 = drw_y;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y2 = drw_y + drw_h;
+
+    if (!xf86XVClipVideoHelper(&dstBox, &x1, &x2, &y1, &y2,
+                              clipBoxes, width, height)){
+       return (Success);
+    }
+
+    dstBox.x1 -= pScrn->frameX0;
+    dstBox.y1 -= pScrn->frameY0;
+    dstBox.x2 -= pScrn->frameX0;
+    dstBox.y2 -= pScrn->frameY0;    
+    
+    bpp = ((pScrn->bitsPerPixel + 1) >> 3);
+    
+    switch (id){
+    case FOURCC_YV12:
+       srcPitch  = (width + 3) & ~3;
+       offset2   = srcPitch * height;
+       srcPitch2 = ((width >> 1) + 3) & ~3;
+       offset3   = offset2 + (srcPitch2 * (height >> 1));
+       dstPitch  = ((width << 1) + 15) & ~15; 
+       break;
+    case FOURCC_I420:
+       srcPitch  = (width + 3) & ~3;
+       offset3   = srcPitch * height;
+       srcPitch2 = ((width >> 1) + 3) & ~3;
+       offset2   = offset3 + (srcPitch2 * (height >> 1));
+       dstPitch  = ((width << 1) + 15) & ~15;
+       break;
+    case FOURCC_YUY2:
+    case FOURCC_RV15:
+    case FOURCC_RV16:
+    default:
+       srcPitch = width << 1;
+       dstPitch = (srcPitch + 15) & ~15;
+       break;
+    }
+    
+    size = dstPitch * height;
+    if (size > nPtr->overlay){
+       if ((pPriv->linear = NEOAllocateMemory(pScrn, pPriv->linear, size)) 
+           == NULL){
+           return (BadAlloc);
+       }
+    } else {
+       pPriv->linear = NULL;
+    }
+
+    top = y1 >> 16;
+    left = (x1 >> 16) & ~1;
+    nPixels = ((((x2 + 0xFFFF) >> 16) + 1) & ~1) - left;
+    left <<= 1;
+
+    if (pPriv->linear == NULL){
+       offset = nPtr->overlay_offset;
+    } else {
+       offset =  pPriv->linear->offset * bpp;
+    }
+    
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"offset=%x\n", offset);
+#endif
+
+    dstStart = (unsigned char *)(nPtr->NeoFbBase + offset + left);
+    
+    switch (id){
+    case FOURCC_YV12:
+    case FOURCC_I420:
+       top &= ~1;
+       tmp = ((top >> 1) * srcPitch2) + (left >> 2);
+       offset2 += tmp;
+       offset3 += tmp;
+       nLines = ((((y2 + 0xFFFF) >> 16) + 1) & ~1) - top;
+       NEOCopyYV12Data(buf + (top * srcPitch) + (left >> 1), buf + offset2, 
+                       buf + offset3, dstStart, srcPitch, srcPitch2, 
+                       dstPitch, nLines, nPixels);
+       break;
+    default:
+       buf += (top * srcPitch) + left;
+       nLines = ((y2 + 0xFFFF) >> 16) - top;
+       NEOCopyData(buf, dstStart, srcPitch, dstPitch, nLines, nPixels << 1);
+    }
+
+    if (!RegionsEqual(&pPriv->clip, clipBoxes)){
+       REGION_COPY(pScreen, &pPriv->clip, clipBoxes);
+        xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+    }
+       NEODisplayVideo(pScrn, id, offset, width, height, dstPitch, x1, y1,
+                       x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+    
+    pPriv->videoStatus = CLIENT_VIDEO_ON;
+    return (Success);
+       
+}
+
+static int
+NEOQueryImageAttributes(ScrnInfoPtr pScrn, int id, 
+                       unsigned short *width, unsigned short *height,
+                       int *pitches, int *offsets)
+{
+    int size, tmp;
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOQueryImageAttributes\n");
+#endif
+    if (*width > 1024){
+       *width = 1024;
+    }
+    if (*height > 1024){
+       *height = 1024;
+    }
+
+    *width = (*width + 1) & ~1;
+    if (offsets != NULL){
+       offsets[0] = 0;
+    }
+
+    switch (id){
+    case FOURCC_YV12:
+    case FOURCC_I420:
+       *height = (*height + 1) & ~1;
+       size = (*width + 3) & ~3;
+       if (pitches != NULL){
+           pitches[0] = size;
+       }
+       size *= *height;
+       if (offsets != NULL){
+           offsets[1] = size;
+       }
+       tmp = ((*width >> 1) + 3) & ~3;
+       if (pitches != NULL){
+           pitches[1] = pitches[2] = tmp;
+       }
+       tmp *= (*height >> 1);
+       size += tmp;
+       if (offsets != NULL){
+           offsets[2] = size;
+       }
+       size += tmp;
+       break;
+    case FOURCC_YUY2:
+    case FOURCC_RV15:
+    case FOURCC_RV16:
+    default:
+       size = *width * 2;
+       if (pitches != NULL){
+           pitches[0] = size;
+       }
+       size *= *height;
+       break;
+    }
+    return (size);
+}
+
+static Bool
+RegionsEqual(RegionPtr A, RegionPtr B)
+{
+    int *dataA, *dataB;
+    int num;
+
+    num = REGION_NUM_RECTS(A);
+    if (num != REGION_NUM_RECTS(B)){
+       return (FALSE);
+    }
+
+    if ((A->extents.x1 != B->extents.x1)
+       || (A->extents.y1 != B->extents.y1)
+       || (A->extents.x2 != B->extents.x2)
+       || (A->extents.y2 != B->extents.y2)){
+       return (FALSE);
+    }
+
+    dataA = (int*) REGION_RECTS(A);
+    dataB = (int*) REGION_RECTS(B);
+
+    while (num--){
+       if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])){
+           return (FALSE);
+       }
+       dataA += 2;
+       dataB += 2;
+    }
+    return (TRUE);
+}
+
+static void
+NEODisplayVideo(ScrnInfoPtr pScrn, int id, int offset, 
+                short width, short height, int pitch,
+                int x1, int y1, int x2, int y2, BoxPtr dstBox,
+                short src_w, short src_h, short drw_w, short drw_h)
+{
+    NEOPtr nPtr = NEOPTR(pScrn);
+    int hstretch, vstretch, fmt;
+    VGA_HWP(pScrn);
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo\n");
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEODisplayVideo src_w=%d, src_h=%d, 
pitch=%d, drw_w=%d, drw_h=%d\n", src_w, src_h, pitch, drw_w, drw_h);
+#endif
+#define WIDTH_THRESHOLD 160
+    if (dstBox->x2 >= pScrn->virtualX) {
+       /*
+        * This is a hack to work around a problem when video is moved
+        * accross the right border.
+        */
+       int diff_s = (width - ((x2 - x1) >> 16)) & ~1;
+       int diff_d = (drw_w - dstBox->x2 + dstBox->x1) & ~1;
+
+       offset -= 2 * ((diff_s > diff_d) ? diff_d : diff_s);
+       dstBox->x1 -= diff_d;
+    } else if (dstBox->x2 - dstBox->x1 < WIDTH_THRESHOLD) {
+       /*
+        * When the video window is less than about 160 pixel wide
+        * it will be distoreted. We attempt to fix it by actually
+        * making it wider and relying on the color key to prevent
+        * it from appearanig outside of the video.
+        */
+       int pre, post;
+       int scale = 1;
+       
+       if (dstBox->x1 < WIDTH_THRESHOLD) {
+           pre = dstBox->x1;
+           post = 160 - pre;
+       } else {
+           pre = 160;
+           post = 0;
+       }
+       offset -= 2 * scale * pre;
+       dstBox->x1 -= pre;
+       dstBox->x2 += post;
+    }
+    if (nPtr->videoHZoom != 1.0) {
+       if ((dstBox->x2 += 5) > pScrn->virtualX)
+           dstBox->x2 = pScrn->virtualX;
+       if (dstBox->x1 > 0) dstBox->x1 += 2;
+    }
+    
+    fmt = 0x00;
+    switch (id){
+    case FOURCC_YV12:
+    case FOURCC_I420:
+    case FOURCC_YUY2:
+       fmt = 0x00;
+       break;
+    case FOURCC_RV15:
+    case FOURCC_RV16:
+       fmt = 0x20;
+       break;
+    }
+
+    offset += (x1 >> 15) & ~0x03;
+    
+    switch (nPtr->NeoChipset) {
+    default:
+    case NM2160: 
+        offset/=2;
+       pitch/=2;
+        OUTGR(0xbc, 0x4f);
+       break;
+    case NM2200:
+    case NM2230:
+    case NM2360:
+    case NM2380:
+        OUTGR(0xbc, 0x2e);
+       break;
+    }
+
+    /* factor 4 for granularity */
+    hstretch = (double)0x1000 * 4 / (int)(nPtr->videoHZoom * 4);
+    if (drw_w > src_w)
+       hstretch = (((int)src_w) * hstretch) / (int) drw_w;
+    
+    vstretch = (double)0x1000 / nPtr->videoVZoom;
+    if (drw_h > src_h)
+       vstretch = (((int)src_h) * vstretch )/ (int) drw_h;
+
+    OUTGR(0xb1, (((dstBox->x2 - 1) >> 4) & 0xf0) | ((dstBox->x1 >> 8) & 0x0f));
+    OUTGR(0xb2, dstBox->x1);
+    OUTGR(0xb3, dstBox->x2 - 1);
+    OUTGR(0xb4, (((dstBox->y2 - 1) >> 4) & 0xf0) | ((dstBox->y1 >> 8) & 0x0f));
+    OUTGR(0xb5, dstBox->y1);
+    OUTGR(0xb6, dstBox->y2 - 1);
+    OUTGR(0xb7, offset >> 16);
+    OUTGR(0xb8, offset >> 8);
+    OUTGR(0xb9, offset );
+    OUTGR(0xba, pitch >> 8);
+    OUTGR(0xbb, pitch);
+     
+    OUTGR(0xbd, 0x02);
+    OUTGR(0xbe, 0x00);
+    OUTGR(0xbf, 0x02);
+
+    OUTGR(0xc0, hstretch >> 8);
+    OUTGR(0xc1, hstretch);
+    OUTGR(0xc2, vstretch >> 8);
+    OUTGR(0xc3, vstretch);
+
+    OUTGR(0xb0, fmt | 0x03);
+
+    OUTGR(0x0a, 0x21);
+    OUTSR(0x08, 0xa0);
+    OUTGR(0x0a, 0x01);
+}
+
+static void
+NEOInitOffscreenImages(ScreenPtr pScreen)
+{
+    XF86OffscreenImagePtr offscreenImages;
+
+#ifdef DEBUG
+    
xf86DrvMsg(xf86Screens[pScreen->myNum]->scrnIndex,X_INFO,"NEOInitOffscreenImages\n");
+#endif
+    if ((offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))) == NULL){
+       return;
+    }
+
+    offscreenImages->image = NEOVideoImages;
+    offscreenImages->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+    offscreenImages->alloc_surface = NEOAllocSurface;
+    offscreenImages->free_surface = NEOFreeSurface;
+    offscreenImages->display = NEODisplaySurface;
+    offscreenImages->stop = NEOStopSurface;
+    offscreenImages->getAttribute = NEOGetSurfaceAttribute;
+    offscreenImages->setAttribute = NEOSetSurfaceAttribute;
+    offscreenImages->max_width = 1024;
+    offscreenImages->max_height = 1024;
+    offscreenImages->num_attributes = nElems(NEOVideoAttributes);
+    offscreenImages->attributes = NEOVideoAttributes;
+
+    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
+}
+
+static FBLinearPtr
+NEOAllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size)
+{
+    ScreenPtr pScreen;
+    FBLinearPtr new_linear;
+    int bytespp = pScrn->bitsPerPixel >> 3;
+
+    /* convert size in bytes into number of pixels */
+    size = (size + bytespp - 1) / bytespp;
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,
+              "NEOAllocateMemory: linear=%x, size=%d\n", linear, size);
+#endif
+    if (linear){
+#ifdef DEBUG
+        xf86DrvMsg(pScrn->scrnIndex,X_INFO,
+                  "NEOAllocateMemory: linear->size=%d\n", linear->size);
+#endif
+       if (linear->size >= size){
+           return (linear);
+       }
+
+       if (xf86ResizeOffscreenLinear(linear, size)){
+           return (linear);
+       }
+
+       xf86FreeOffscreenLinear(linear);
+    }
+
+
+    pScreen = screenInfo.screens[pScrn->scrnIndex];
+    if ((new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, NULL,
+                                                 NULL, NULL)) == NULL){
+       int max_size;
+
+       xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, 
+                                       PRIORITY_EXTREME);
+#ifdef DEBUG
+        xf86DrvMsg(pScrn->scrnIndex,X_INFO,
+                  "NEOAllocateMemory: max_size=%d\n", max_size);
+#endif
+       if (max_size < size){
+           return (NULL);
+       }
+
+       xf86PurgeUnlockedOffscreenAreas(pScreen);
+       new_linear = xf86AllocateOffscreenLinear(pScreen, 
+                                                size, 16, NULL, NULL, NULL);
+    }
+    
+    return (new_linear);
+}
+
+static void
+NEOCopyData(unsigned char *src, unsigned char *dst, 
+           int srcPitch, int dstPitch,
+           int height, int width)
+{
+    while (height-- > 0){
+       memcpy(dst, src, width);
+       src += srcPitch;
+       dst += dstPitch;
+    }
+}
+
+static void
+NEOCopyYV12Data(unsigned char *src1, unsigned char *src2,
+               unsigned char *src3, unsigned char *dst,
+               int srcPitch1, int srcPitch2, int dstPitch,
+               int height, int width)
+{
+    CARD32 *pDst = (CARD32 *) dst;
+    int i;
+
+    width >>= 1;
+    height >>= 1;
+    dstPitch >>= 2;
+    while (--height >= 0){
+       for (i =0; i < width; i++){
+           pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
+               (src3[i] << 8) | (src2[i] << 24);
+       }
+       pDst += dstPitch;
+       src1 += srcPitch1;
+
+       for (i =0; i < width; i++){
+           pDst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) |
+               (src3[i] << 8) | (src2[i] << 24);
+       }
+       pDst += dstPitch;
+       src1 += srcPitch1;
+           src2 += srcPitch2;
+           src3 += srcPitch2;
+    }
+}
+
+static int
+NEOAllocSurface(ScrnInfoPtr pScrn, int id, 
+               unsigned short width, unsigned short height,
+               XF86SurfacePtr surface)
+{
+    int pitch, bpp, size;
+    NEOOffscreenPtr pPriv;
+    FBLinearPtr linear;
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOAllocSurface\n");
+#endif
+    if (width > 1024  || height > 1024){
+       return (BadAlloc);
+    }
+
+    width = (width + 1) & ~1;
+    bpp = ((pScrn->bitsPerPixel + 1) >> 3);
+    pitch = ((width << 1) + 15) & ~15;
+    size = pitch * height;
+
+    if ((linear = NEOAllocateMemory(pScrn, NULL, size)) == NULL){
+       return (BadAlloc);
+    }
+
+    surface->width = width;
+    surface->height = height;
+    if ((surface->pitches = xalloc(sizeof(int))) == NULL){
+       xf86FreeOffscreenLinear(linear);
+       return (BadAlloc);
+    }
+    if ((surface->offsets = xalloc(sizeof(int))) == NULL){
+       xfree(surface->pitches);
+       xf86FreeOffscreenLinear(linear);
+       return (BadAlloc);
+    }
+
+    if ((pPriv = xalloc(sizeof(NEOOffscreenRec))) == NULL){
+       xfree(surface->pitches);
+       xfree(surface->offsets);
+       xf86FreeOffscreenLinear(linear);
+       return (BadAlloc);
+    }
+
+    pPriv->linear = linear;
+    pPriv->isOn = FALSE;
+
+    surface->pScrn = pScrn;
+    surface->id = id;
+    surface->pitches[0] = pitch;
+    surface->offsets[0] = linear->offset << 1;
+    surface->devPrivate.ptr = (pointer)pPriv;
+    return (Success);
+}
+
+static int
+NEOFreeSurface(XF86SurfacePtr surface)
+{
+    NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr;
+
+#ifdef DEBUG
+    xf86DrvMsg(0,X_INFO,"NEOFreeSurface\n");
+#endif
+    if (pPriv->isOn)
+       NEOStopSurface(surface);
+
+    xf86FreeOffscreenLinear(pPriv->linear);
+    xfree(surface->pitches);
+    xfree(surface->offsets);
+    xfree(surface->devPrivate.ptr);
+    return (Success);
+}
+
+static int
+NEODisplaySurface(XF86SurfacePtr surface,
+                 short src_x, short src_y, short drw_x, short drw_y,
+                 short src_w, short src_h, short drw_w, short drw_h,
+                 RegionPtr clipBoxes)
+{
+    NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr;
+    NEOPtr nPtr = NEOPTR(surface->pScrn);
+    NEOPortPtr portPriv = nPtr->overlayAdaptor->pPortPrivates[0].ptr;
+    INT32 x1, y1, x2, y2;
+    BoxRec dstBox;
+
+#ifdef DEBUG
+    xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEODisplaySurface\n");
+#endif
+    x1 = src_x;
+    x2 = src_x + src_w;
+    y1 = src_y;
+    y2 = src_y + src_h;
+
+    dstBox.x1 = drw_x;
+    dstBox.x2 = drw_x + drw_w;
+    dstBox.y1 = drw_y;
+    dstBox.y2 = drw_y + drw_h;
+    if (!xf86XVClipVideoHelper( &dstBox, &x1, &x2, &y1, &y2,
+                              clipBoxes, surface->width, surface->height)){
+       return (Success);
+    }
+
+    dstBox.x1 -= surface->pScrn->frameX0;
+    dstBox.y1 -= surface->pScrn->frameY0;
+    dstBox.x2 -= surface->pScrn->frameX0;
+    dstBox.y2 -= surface->pScrn->frameY0;
+
+    xf86XVFillKeyHelper(surface->pScrn->pScreen, portPriv->colorKey,
+                       clipBoxes);
+    NEOResetVideo(surface->pScrn);
+    NEODisplayVideo(surface->pScrn, surface->id, surface->offsets[0],
+                   surface->width, surface->height, surface->pitches[0], 
+                   x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+    
+    pPriv->isOn = TRUE;
+    if (portPriv->videoStatus & CLIENT_VIDEO_ON){
+       REGION_EMPTY(pScrn->pScreen, &portPriv->clip);
+       UpdateCurrentTime();
+       portPriv->videoStatus = FREE_TIMER;
+       portPriv->freeTime = currentTime.milliseconds + FREE_DELAY;
+    }
+    return (Success);
+}
+
+static int
+NEOStopSurface(XF86SurfacePtr surface)
+{
+    NEOOffscreenPtr pPriv = (NEOOffscreenPtr)surface->devPrivate.ptr;
+
+#ifdef DEBUG
+    xf86DrvMsg(surface->pScrn->scrnIndex,X_INFO,"NEOStopSurface\n");
+#endif
+    if (pPriv->isOn){
+       NEOPtr nPtr = NEOPTR(surface->pScrn);
+       VGA_HWP(surface->pScrn);
+       OUTGR(0xb0, 0x02);
+       pPriv->isOn = FALSE;
+    }
+    return (Success);
+}
+
+static int
+NEOGetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 *value)
+{
+    NEOPtr nPtr = NEOPTR(pScrn);
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOGetSurfaceAttribute\n");
+#endif
+    return (NEOGetPortAttribute(pScrn, 
+            attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr));
+}
+
+static int
+NEOSetSurfaceAttribute(ScrnInfoPtr pScrn, Atom attr, INT32 value)
+{
+    NEOPtr nPtr = NEOPTR(pScrn);
+
+#ifdef DEBUG
+    xf86DrvMsg(pScrn->scrnIndex,X_INFO,"NEOSetSurfaceAttribute\n");
+#endif
+    return (NEOSetPortAttribute(pScrn, 
+            attr, value, (pointer)nPtr->overlayAdaptor->pPortPrivates[0].ptr));
+}
+
+#else /* XvExtension */
+
+void NEOInitVideo(ScreenPtr pScreen) {}
+void NEOResetVideo(ScreenPtr pScreen) {}
+
+#endif
diff -x CVS -uNr 
xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.h 
xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.h
--- xc.orig/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.h    Thu Jan 
 1 01:00:00 1970
+++ xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_video.h Thu Apr  4 
16:05:44 2002
@@ -0,0 +1,83 @@
+/**********************************************************************
+Copyright 2002 by Shigehiro Nomura.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, distribute, and sell this software and
+its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Shigehiro Nomura not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  Shigehiro Nomura
+and its suppliers make no representations about the suitability of this
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+
+SHIGEHIRO NOMURA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL SHIGEHIRO NOMURA AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+**********************************************************************/
+
+#ifndef _NEO_VIDEO_H
+#define _NEO_VIDEO_H
+
+#define ACC_MMIO
+
+#include "vgaHW.h"
+#include "fourcc.h"
+#include "Xv.h"
+
+#define NEO_VIDEO_VIDEO                0
+#define NEO_VIDEO_IMAGE                1
+
+#define FOURCC_RV15                    0x35315652
+#define FOURCC_RV16                    0x36315652
+
+#define OFF_DELAY                      200             /* milliseconds */
+#define FREE_DELAY                     60000   /* milliseconds */
+
+#define OFF_TIMER                      0x01
+#define FREE_TIMER                     0x02
+#define CLIENT_VIDEO_ON                0x04
+#define TIMER_MASK                     (OFF_TIMER | FREE_TIMER)
+
+typedef struct
+{
+    FBLinearPtr        linear;
+    RegionRec  clip;
+    CARD32     colorKey;
+    CARD32     interlace;
+    CARD32     brightness;
+    CARD32     videoStatus;
+    Time       offTime;
+    Time       freeTime;
+} NEOPortRec, *NEOPortPtr;
+
+typedef struct
+{
+    FBLinearPtr        linear;
+    Bool       isOn;
+} NEOOffscreenRec, *NEOOffscreenPtr;
+
+/* I/O Functions */
+# define OUTGR(idx,dat) \
+   if (nPtr->NeoMMIOBase2) \
+     (*(unsigned short *)(nPtr->NeoMMIOBase2+VGA_GRAPH_INDEX)\
+                                                     =(idx)|((dat)<<8));\
+   else \
+      VGAwGR((idx),(dat));
+
+#  define OUTSR(idx,dat) \
+if (nPtr->NeoMMIOBase2) \
+   (*(unsigned short *)(nPtr->NeoMMIOBase2+VGA_SEQ_INDEX)=(idx)|((dat)<<8));\
+else \
+   VGAwSR((idx),(dat));
+
+# define VGA_HWP(x)     vgaHWPtr hwp = VGAHWPTR(x)
+
+#endif /* _NEO_VIDEO_H */

Reply via email to