File xf86-video-ati-6.7.197-r128-xvideo.patch of Package xorg-x11-driver-video

diff --git a/src/r128.h b/src/r128.h
index 1205245..6e608b9 100644
--- a/src/r128.h
+++ b/src/r128.h
@@ -430,6 +430,12 @@ typedef struct {
     XF86VideoAdaptorPtr adaptor;
     void              (*VideoTimerCallback)(ScrnInfoPtr, Time);
     int               videoKey;
+    Bool              forceXvProbing;
+    int		      RageTheatreCrystal;
+    int               RageTheatreTunerPort;
+    int               RageTheatreCompositePort;
+    int               RageTheatreSVideoPort;
+    int               tunerType;
     Bool              showCache;
     OptionInfoPtr     Options;
 
@@ -473,6 +479,11 @@ extern Bool        R128DGAInit(ScreenPtr pScreen);
 extern int         R128MinBits(int val);
 
 extern void        R128InitVideo(ScreenPtr pScreen);
+#ifdef XvExtension
+extern void	   R128ShutdownVideo(ScrnInfoPtr pScrn);
+extern void        R128LeaveVT_Video(ScrnInfoPtr pScrn);
+extern void        R128EnterVT_Video(ScrnInfoPtr pScrn);
+#endif
 
 #ifdef XF86DRI
 extern Bool        R128DRIScreenInit(ScreenPtr pScreen);
diff --git a/src/r128_accel.c b/src/r128_accel.c
index 8870682..f75b38e 100644
--- a/src/r128_accel.c
+++ b/src/r128_accel.c
@@ -242,6 +242,10 @@ void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
     R128InfoPtr info = R128PTR(pScrn);
     int         ret, i;
 
+    if(!info->CCEInUse){
+         R128WaitForIdle(pScrn);
+         return;
+         }
     FLUSH_RING();
 
     for (;;) {
@@ -260,7 +264,10 @@ void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
 		       "%s: (DEBUG) CCE idle took i = %d\n", __FUNCTION__, i);
 	}
 
-	if (ret == 0) return;
+	if (ret == 0){
+		 R128WaitForIdle(pScrn);
+		 return;
+		 }
 
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		   "Idle timed out, resetting engine...\n");
diff --git a/src/r128_driver.c b/src/r128_driver.c
index 45917cd..c5a77b6 100644
--- a/src/r128_driver.c
+++ b/src/r128_driver.c
@@ -78,7 +78,18 @@
 #include "r128_sarea.h"
 #endif
 
+#define USE_FB                  /* don't disable it: CFB code is broken */
+#ifdef USE_FB
 #include "fb.h"
+#else
+
+				/* CFB support */
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb16.h"
+#include "cfb32.h"
+#endif
 
 				/* colormap initialization */
 #include "micmap.h"
@@ -90,6 +101,7 @@
 #include "xf86Resources.h"
 #include "xf86cmap.h"
 #include "xf86xv.h"
+#include "xf86i2c.h"
 #include "vbe.h"
 
 				/* fbdevhw & vgahw */
@@ -144,6 +156,14 @@ typedef enum {
   /* FIXME: Disable CRTOnly until it is tested */
   OPTION_CRT,
 #endif
+#ifdef XvExtension
+  OPTION_FORCE_XV_PROBING,
+  OPTION_RAGE_THEATRE_CRYSTAL,
+  OPTION_RAGE_THEATRE_TUNER_PORT,
+  OPTION_RAGE_THEATRE_COMPOSITE_PORT,
+  OPTION_RAGE_THEATRE_SVIDEO_PORT,
+  OPTION_TUNER_TYPE,
+#endif
   OPTION_DISPLAY,
   OPTION_PANEL_WIDTH,
   OPTION_PANEL_HEIGHT,
@@ -179,6 +199,15 @@ static const OptionInfoRec R128Options[] = {
   { OPTION_VIDEO_KEY,    "VideoKey",         OPTV_INTEGER, {0}, FALSE },
   { OPTION_SHOW_CACHE,   "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
   { OPTION_VGA_ACCESS,   "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
+#ifdef XvExtension
+  { OPTION_VIDEO_KEY, "VideoKey",      OPTV_INTEGER, {0}, FALSE },
+  { OPTION_FORCE_XV_PROBING, "ForceXvProbing", OPTV_BOOLEAN, {0}, FALSE},
+  { OPTION_RAGE_THEATRE_CRYSTAL, "RageTheatreCrystal",      OPTV_INTEGER, {0}, FALSE },
+  { OPTION_RAGE_THEATRE_TUNER_PORT, "RageTheatreTunerPort",      OPTV_INTEGER, {0}, FALSE },
+  { OPTION_RAGE_THEATRE_COMPOSITE_PORT, "RageTheatreCompositePort",      OPTV_INTEGER, {0}, FALSE },
+  { OPTION_RAGE_THEATRE_SVIDEO_PORT, "RageTheatreSVideoPort",      OPTV_INTEGER, {0}, FALSE },
+  { OPTION_TUNER_TYPE, "TunerType",      OPTV_INTEGER, {0}, FALSE },
+#endif
   { -1,                  NULL,               OPTV_NONE,    {0}, FALSE }
 };
 
@@ -762,7 +791,7 @@ static Bool R128PreInitVisual(ScrnInfoPtr pScrn)
 {
     R128InfoPtr info          = R128PTR(pScrn);
 
-    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb
+    if (!xf86SetDepthBpp(pScrn, 8, 8, 8, (Support24bppFb
 					  | Support32bppFb
 					  | SupportConvert32to24
 					  )))
@@ -1315,7 +1344,7 @@ R128I2cInit(ScrnInfoPtr pScrn)
 		return FALSE;
     }
 
-    info->pI2CBus = xf86CreateI2CBusRec();
+    info->pI2CBus = xf86CreateI2CBusRec(); 
     if(!info->pI2CBus) return FALSE;
 
     info->pI2CBus->BusName    = "DDC";
@@ -1634,6 +1663,10 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn)
     R128InfoPtr   info = R128PTR(pScrn);
     ClockRangePtr clockRanges;
     int           modesFound;
+    char          *mod = NULL;
+#ifndef USE_FB
+    const char    *Sym = NULL;
+#endif
 
     if(info->isDFP) {
         R128MapMem(pScrn);
@@ -2016,6 +2049,76 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
 
     if (!R128PreInitWeight(pScrn))    goto fail;
 
+#ifdef XvExtension
+    if(xf86GetOptValInteger(info->Options, OPTION_RAGE_THEATRE_CRYSTAL, &(info->RageTheatreCrystal))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rage Theatre Crystal frequency was specified as %d.%d Mhz\n",
+                                info->RageTheatreCrystal/100, info->RageTheatreCrystal % 100);
+    } else {
+    	info->RageTheatreCrystal=-1;
+    }
+
+    if(xf86GetOptValInteger(info->Options, OPTION_RAGE_THEATRE_TUNER_PORT, &(info->RageTheatreTunerPort))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rage Theatre tuner port was specified as %d\n",
+                                info->RageTheatreTunerPort);
+    } else {
+    	info->RageTheatreTunerPort=-1;
+    }
+    
+    if(info->RageTheatreTunerPort>5){
+         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to assign Rage Theatre tuner port to invalid value. Disabling setting\n");
+	 info->RageTheatreTunerPort=-1;
+	 }
+
+    if(xf86GetOptValInteger(info->Options, OPTION_RAGE_THEATRE_COMPOSITE_PORT, &(info->RageTheatreCompositePort))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rage Theatre composite port was specified as %d\n",
+                                info->RageTheatreCompositePort);
+    } else {
+    	info->RageTheatreCompositePort=-1;
+    }
+
+    if(info->RageTheatreCompositePort>6){
+         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to assign Rage Theatre composite port to invalid value. Disabling setting\n");
+	 info->RageTheatreCompositePort=-1;
+	 }
+
+    if(xf86GetOptValInteger(info->Options, OPTION_RAGE_THEATRE_SVIDEO_PORT, &(info->RageTheatreSVideoPort))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rage Theatre SVideo Port was specified as %d\n",
+                                info->RageTheatreSVideoPort);
+    } else {
+    	info->RageTheatreSVideoPort=-1;
+    }
+
+    if(info->RageTheatreSVideoPort>6){
+         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to assign Rage Theatre SVideo port to invalid value. Disabling setting\n");
+	 info->RageTheatreSVideoPort=-1;
+	 }
+
+    if(xf86GetOptValInteger(info->Options, OPTION_TUNER_TYPE, &(info->tunerType))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Tuner type was specified as %d\n",
+                                info->tunerType);
+    } else {
+    	info->tunerType=-1;
+    }
+
+    if(info->tunerType>31){
+         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to set tuner type to invalid value. Disabling setting\n");
+	 info->tunerType=-1;
+	 }
+
+    if(xf86ReturnOptValBool(info->Options, OPTION_FORCE_XV_PROBING, FALSE)) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing Xv probing for multimedia harware (lockup prone)\n");
+	info->forceXvProbing=TRUE;
+    } 
+
+    if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) {
+        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
+                                info->videoKey);
+    } else {
+        /* this default is very unlikely to occur (mostly a few pixels in photos) */
+        info->videoKey = (1<<pScrn->offset.red) | (2<<pScrn->offset.green) | (3<<pScrn->offset.blue);
+    }
+#endif
+
     if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) {
         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
                                 info->videoKey);
@@ -2073,10 +2176,12 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
 #endif
 
 				/* Free the video bios (if applicable) */
+#ifndef XvExtension
     if (info->VBIOS) {
 	xfree(info->VBIOS);
 	info->VBIOS = NULL;
     }
+#endif
 
 				/* Free int10 info */
     if (pInt10)
@@ -2292,12 +2397,18 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
     }
 #endif
 
+#ifdef USE_FB
     if (!fbScreenInit (pScreen, info->FB,
 		       pScrn->virtualX, pScrn->virtualY,
 		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
 		       pScrn->bitsPerPixel))
 	return FALSE;
-
+#else
+    if (!cfbScreenInit(pScreen, info->FB,
+		       pScrn->virtualX, pScrn->virtualY,
+		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth))
+	return FALSE;
+#endif
     xf86SetBlackWhitePixels(pScreen);
 
     if (pScrn->bitsPerPixel > 8) {
@@ -2316,9 +2427,10 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
 	}
     }
 
+#ifdef USE_FB    
     /* must be after RGB order fixed */
     fbPictureInit (pScreen, 0, 0);
-
+#endif
 				/* Memory manager setup */
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
@@ -3375,6 +3487,7 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
     int    hsync_wid;
     int    hsync_fudge;
     int    vsync_wid;
+    int    bytpp;
     int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
     int    hsync_fudge_fp[]      = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
 //   int    hsync_fudge_fp_crt[]  = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
@@ -3498,6 +3611,10 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
     }
 #endif
 
+#ifdef XvExtension
+    R128EnterVT_Video(pScrn);
+#endif
+
     return TRUE;
 }
 
@@ -4261,6 +4378,10 @@ void R128LeaveVT(int scrnIndex, int flags)
     R128SavePtr save  = &info->ModeReg;
 
     R128TRACE(("R128LeaveVT\n"));
+#ifdef XvExtension
+    R128LeaveVT_Video(pScrn);
+#endif
+
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
 	DRILock(pScrn->pScreen, 0);
@@ -4311,11 +4432,15 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen)
     if (info->DGAModes)          xfree(info->DGAModes);
     info->DGAModes               = NULL;
 
+#if 0
+    /* This code causes server crash on exit freedesktop#8811#c12 */
     if (info->adaptor) {
+    	R128ShutdownVideo(pScrn);
         xfree(info->adaptor->pPortPrivates[0].ptr);
 	xf86XVFreeVideoAdaptorRec(info->adaptor);
 	info->adaptor = NULL;
     }
+#endif
 
     pScrn->vtSema = FALSE;
 
diff --git a/src/r128_reg.h b/src/r128_reg.h
index dac22e6..beed9b2 100644
--- a/src/r128_reg.h
+++ b/src/r128_reg.h
@@ -275,7 +275,11 @@
 #define R128_CACHE_CNTL                   0x1724
 #define R128_CACHE_LINE                   0x0f0c /* PCI */
 #define R128_CAP0_TRIG_CNTL               0x0950 /* ? */
-#define R128_CAP1_TRIG_CNTL               0x09c0 /* ? */
+#define R128_CAP0_TRIG_CNTL_TRIGGER_GET   0x00000003        
+#define R128_CAP0_TRIG_CNTL_TRIGGER_SET   0x00000001        
+#define R128_CAP0_TRIG_CNTL_CAPTURE_EN    0x00000010        
+#define R128_CAP0_TRIG_CNTL_VSYNC_GET     0x0000FF00        
+#define R128_CAP0_TRIG_CNTL_VSYNC_SET     0x00010000        
 #define R128_CAPABILITIES_ID              0x0f50 /* PCI */
 #define R128_CAPABILITIES_PTR             0x0f34 /* PCI */
 #define R128_CLK_PIN_CNTL                 0x0001 /* PLL */
@@ -713,6 +717,10 @@
 #define R128_HW_DEBUG2                    0x011c
 
 #define R128_I2C_CNTL_1                   0x0094 /* ? */
+#define R128_I2C_CNTL_0			  0x0090
+#define R128_I2C_CNTL_1                   0x0094 
+#define R128_I2C_DATA			  0x0098
+
 #define R128_INTERRUPT_LINE               0x0f3c /* PCI */
 #define R128_INTERRUPT_PIN                0x0f3d /* PCI */
 #define R128_IO_BASE                      0x0f14 /* PCI */
@@ -841,6 +849,16 @@
 #define R128_OV0_VID_BUF_PITCH0_VALUE     0x0460
 #define R128_OV0_VID_BUF_PITCH1_VALUE     0x0464
 #define R128_OV0_AUTO_FLIP_CNTL           0x0470
+#define  R128_OV0_AUTO_FLIP_CNTL_SOFT_BUF_NUM        0x00000007
+#define  R128_OV0_AUTO_FLIP_CNTL_SOFT_REPEAT_FIELD   0x00000008
+#define  R128_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD        0x00000010
+#define  R128_OV0_AUTO_FLIP_CNTL_IGNORE_REPEAT_FIELD 0x00000020
+#define  R128_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE     0x00000040
+#define  R128_OV0_AUTO_FLIP_CNTL_VID_PORT_SELECT     0x00000300
+#define  R128_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN  0x00010000
+#define  R128_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN     0x00040000
+#define  R128_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN      0x00080000
+#define  R128_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE    0x00800000
 #define R128_OV0_DEINTERLACE_PATTERN      0x0474
 #define R128_OV0_H_INC                    0x0480
 #define R128_OV0_STEP_BY                  0x0484
@@ -876,6 +894,92 @@
 #       define  R128_CMP_MIX_AND                 0x00000100L
 #define R128_OV0_TEST                     0x04F8
 
+/* first capture unit */
+
+#define R128_CAP0_BUF0_OFFSET	 	  0x0920
+#define R128_CAP0_BUF1_OFFSET	 	  0x0924
+#define R128_CAP0_BUF0_EVEN_OFFSET	  0x0928
+#define R128_CAP0_BUF1_EVEN_OFFSET	  0x092C
+
+#define R128_CAP0_BUF_PITCH		  0x0930
+#define R128_CAP0_V_WINDOW		  0x0934
+#define R128_CAP0_H_WINDOW		  0x0938
+#define R128_CAP0_VBI_ODD_OFFSET	  0x093C
+#define R128_CAP0_VBI_EVEN_OFFSET	  0x0940
+#define R128_CAP0_VBI_V_WINDOW		  0x0944
+#define R128_CAP0_VBI_H_WINDOW		  0x0948
+#define R128_CAP0_PORT_MODE_CNTL	  0x094C
+#define R128_CAP0_TRIG_CNTL		  0x0950
+#define R128_CAP0_DEBUG			  0x0954
+#define R128_CAP0_CONFIG		  0x0958
+#define R128_CAP0_CONFIG_CONTINUOS          0x00000001
+#define R128_CAP0_CONFIG_START_FIELD_EVEN   0x00000002
+#define R128_CAP0_CONFIG_START_BUF_GET      0x00000004
+#define R128_CAP0_CONFIG_START_BUF_SET      0x00000008
+#define R128_CAP0_CONFIG_BUF_TYPE_ALT       0x00000010
+#define R128_CAP0_CONFIG_BUF_TYPE_FRAME     0x00000020
+#define R128_CAP0_CONFIG_ONESHOT_MODE_FRAME 0x00000040
+#define R128_CAP0_CONFIG_BUF_MODE_DOUBLE    0x00000080
+#define R128_CAP0_CONFIG_BUF_MODE_TRIPLE    0x00000100
+#define R128_CAP0_CONFIG_MIRROR_EN          0x00000200
+#define R128_CAP0_CONFIG_ONESHOT_MIRROR_EN  0x00000400
+#define R128_CAP0_CONFIG_VIDEO_SIGNED_UV    0x00000800
+#define R128_CAP0_CONFIG_ANC_DECODE_EN      0x00001000
+#define R128_CAP0_CONFIG_VBI_EN             0x00002000
+#define R128_CAP0_CONFIG_SOFT_PULL_DOWN_EN  0x00004000
+#define R128_CAP0_CONFIG_VIP_EXTEND_FLAG_EN 0x00008000
+#define R128_CAP0_CONFIG_FAKE_FIELD_EN      0x00010000
+#define R128_CAP0_CONFIG_ODD_ONE_MORE_LINE  0x00020000
+#define R128_CAP0_CONFIG_EVEN_ONE_MORE_LINE 0x00040000
+#define R128_CAP0_CONFIG_HORZ_DIVIDE_2      0x00080000
+#define R128_CAP0_CONFIG_HORZ_DIVIDE_4      0x00100000
+#define R128_CAP0_CONFIG_VERT_DIVIDE_2      0x00200000
+#define R128_CAP0_CONFIG_VERT_DIVIDE_4      0x00400000
+#define R128_CAP0_CONFIG_FORMAT_BROOKTREE   0x00000000
+#define R128_CAP0_CONFIG_FORMAT_CCIR656     0x00800000
+#define R128_CAP0_CONFIG_FORMAT_ZV          0x01000000
+#define R128_CAP0_CONFIG_FORMAT_VIP         0x01800000
+#define R128_CAP0_CONFIG_FORMAT_TRANSPORT   0x02000000
+#define R128_CAP0_CONFIG_HORZ_DECIMATOR     0x04000000
+#define R128_CAP0_CONFIG_VIDEO_IN_YVYU422   0x00000000
+#define R128_CAP0_CONFIG_VIDEO_IN_VYUY422   0x20000000
+#define R128_CAP0_ANC_ODD_OFFSET	  0x095C
+#define R128_CAP0_ANC_EVEN_OFFSET	  0x0960
+#define R128_CAP0_ANC_H_WINDOW		  0x0964
+#define R128_CAP0_VIDEO_SYNC_TEST	  0x0968
+#define R128_CAP0_ONESHOT_BUF_OFFSET	  0x096C
+#define R128_CAP0_BUF_STATUS		  0x0970
+#define R128_CAP0_DWNSC_XRATIO	 	  0x0978
+#define R128_CAP0_XSHARPNESS		  0x097C
+
+/* second capture unit */
+
+#define R128_CAP1_BUF0_OFFSET	 	  0x0990
+#define R128_CAP1_BUF1_OFFSET	 	  0x0994
+#define R128_CAP1_BUF0_EVEN_OFFSET	  0x0998
+#define R128_CAP1_BUF1_EVEN_OFFSET	  0x099C
+
+#define R128_CAP1_BUF_PITCH		  0x09A0
+#define R128_CAP1_V_WINDOW		  0x09A4
+#define R128_CAP1_H_WINDOW		  0x09A8
+#define R128_CAP1_VBI_ODD_OFFSET	  0x09AC
+#define R128_CAP1_VBI_EVEN_OFFSET	  0x09B0
+#define R128_CAP1_VBI_V_WINDOW		  0x09B4
+#define R128_CAP1_VBI_H_WINDOW		  0x09B8
+#define R128_CAP1_PORT_MODE_CNTL	  0x09BC
+#define R128_CAP1_TRIG_CNTL		  0x09C0
+#define R128_CAP1_DEBUG			  0x09C4
+#define R128_CAP1_CONFIG		  0x09C8
+#define R128_CAP1_ANC_ODD_OFFSET	  0x09CC
+#define R128_CAP1_ANC_EVEN_OFFSET	  0x09D0
+#define R128_CAP1_ANC_H_WINDOW		  0x09D4
+#define R128_CAP1_VIDEO_SYNC_TEST	  0x09D8
+#define R128_CAP1_ONESHOT_BUF_OFFSET	  0x09DC
+#define R128_CAP1_BUF_STATUS		  0x09E0
+#define R128_CAP1_DWNSC_XRATIO	 	  0x09E8
+#define R128_CAP1_XSHARPNESS		  0x09EC
+
+
 
 #define R128_PALETTE_DATA                 0x00b4
 #define R128_PALETTE_INDEX                0x00b0
diff --git a/src/r128_sarea.h b/src/r128_sarea.h
index 70f9122..cad9aa8 100644
--- a/src/r128_sarea.h
+++ b/src/r128_sarea.h
@@ -157,10 +157,12 @@ typedef struct {
     unsigned int vertsize;
     unsigned int vc_format;
 
+#ifdef XF86DRI
     /* The current cliprects, or a subset thereof.
      */
     drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS];
     unsigned int nbox;
+#endif
 
     /* Counters for throttling of rendering clients.
      */
diff --git a/src/r128_video.c b/src/r128_video.c
index 8e83323..339bd66 100644
--- a/src/r128_video.c
+++ b/src/r128_video.c
@@ -15,6 +15,18 @@
 
 #include "xf86.h"
 #include "dixstruct.h"
+#include "xf86PciInfo.h"
+#include "xf86i2c.h"
+#include "fi1236.h"
+#include "msp3430.h"
+#include "bt829.h"
+#include "tda9850.h"
+#include "tda8425.h"
+#include "generic_bus.h"
+#include "theatre_reg.h"
+#include "theatre.h"
+#include "theatre_detect.h"
+#include "i2c_def.h"
 
 #include <X11/extensions/Xv.h>
 #include "fourcc.h"
@@ -28,6 +40,10 @@
 
 #define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
 
+#ifndef XvExtension
+void R128InitVideo(ScreenPtr pScreen) {}
+#else
+
 static XF86VideoAdaptorPtr R128SetupImageVideo(ScreenPtr);
 static int  R128SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
 static int  R128GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
@@ -37,6 +53,9 @@ static void R128QueryBestSize(ScrnInfoPtr, Bool, short, short, short, short,
 static int  R128PutImage(ScrnInfoPtr, short, short, short, short, short,
 			short, short, short, int, unsigned char*, short,
 			short, Bool, RegionPtr, pointer, DrawablePtr);
+static int R128PutVideo(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);
 static int  R128QueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
 			unsigned short *,  int *, int *);
 
@@ -48,12 +67,31 @@ static void R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now);
 
 #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
 
-static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
+static Atom xvBrightness, xvColorKey, xvSaturation, xvColor, xvDoubleBuffer, 
+          xvEncoding, xvVolume, xvMute, xvFrequency, xvContrast, xvHue,
+	  xv_autopaint_colorkey, xv_set_defaults, xvTunerStatus, xvSAP,
+	     xvLocationID, xvDeviceID, xvInstanceID;
+
+typedef struct
+{
+    BYTE table_revision;
+    BYTE table_size;
+    BYTE tuner_type;
+    BYTE audio_chip;
+    BYTE product_id;
+    BYTE tuner_voltage_teletext_fm;
+    BYTE i2s_config; /* configuration of the sound chip */
+    BYTE video_decoder_type;
+    BYTE video_decoder_host_config;
+    BYTE input[5];
+} _MM_TABLE;
 
 
 typedef struct {
    int           brightness;
    int           saturation;
+   int           contrast;
+   int           hue;
    Bool          doubleBuffer;
    unsigned char currentBuffer;
    FBLinearPtr   linear;
@@ -62,9 +100,55 @@ typedef struct {
    CARD32        videoStatus;
    Time          offTime;
    Time          freeTime;
+
+   I2CBusPtr	 i2c;
+   CARD32 	 r128_i2c_timing;
+   CARD32        r128_M;
+   CARD32        r128_N;
+
+   FI1236Ptr     fi1236;
+   MSP3430Ptr    msp3430;
+   BT829Ptr	 bt829;
+   TDA9850Ptr	 tda9850;
+   TDA8425Ptr    tda8425;
+
+   GENERIC_BUS_Ptr VIP;
+   TheatrePtr      theatre;
+
+   Bool          video_stream_active;
+   int           encoding;
+   CARD32        frequency;
+   int           volume;
+   Bool		 mute;
+   int		 sap_channel;
+   int           v;
    int           ecp_div;
+
+   Bool          MM_TABLE_valid;
+   _MM_TABLE     MM_TABLE;
+
+   Bool		 EEPROM_present;
+   int		 EEPROM_addr;
+
+   Bool          addon_board;
+   CARD8         board_info;
+   int           board_control;
+
+   Bool          autopaint_colorkey;
+   Atom		 device_id, location_id, instance_id;
+
 } R128PortPrivRec, *R128PortPrivPtr;
 
+static void R128MuteAudio(R128PortPrivPtr pPriv, Bool mute);
+void R128_detect_addon(R128PortPrivPtr pPriv);
+Bool R128SetupTheatre(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv, TheatrePtr t);
+void R128_RT_SetEncoding(R128PortPrivPtr pPriv);
+void R128_MSP_SetEncoding(R128PortPrivPtr pPriv);
+void R128_BT_SetEncoding(R128PortPrivPtr pPriv);
+void R128_board_setmisc(R128PortPrivPtr pPriv);
+void R128VIP_init(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv);
+void R128VIP_reset(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv);
+  
 static void R128ECP(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
 {
     R128InfoPtr     info      = R128PTR(pScrn);
@@ -81,10 +165,12 @@ static void R128ECP(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
 void R128InitVideo(ScreenPtr pScreen)
 {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    R128InfoPtr info  = R128PTR(pScrn);
     XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
     XF86VideoAdaptorPtr newAdaptor = NULL;
     int num_adaptors;
 
+    if(info->accel && info->accel->FillSolidRects)
     newAdaptor = R128SetupImageVideo(pScreen);
 
     num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
@@ -125,6 +211,29 @@ static XF86VideoEncodingRec DummyEncoding =
    {1, 1}
 };
 
+ /* the picture is interlaced - hence the half-heights */
+
+static XF86VideoEncodingRec
+InputVideoEncodings[] =
+{
+    { 0, "XV_IMAGE",			2048,2048,{1,1}},        
+    { 1, "pal-composite",		720, 288, { 1, 50 }},
+    { 2, "pal-tuner",			720, 288, { 1, 50 }},
+    { 3, "pal-svideo",			720, 288, { 1, 50 }},
+    { 4, "ntsc-composite",		640, 240, { 1001, 60000 }},
+    { 5, "ntsc-tuner",			640, 240, { 1001, 60000 }},
+    { 6, "ntsc-svideo",			640, 240, { 1001, 60000 }},
+    { 7, "secam-composite",		720, 288, { 1, 50 }},
+    { 8, "secam-tuner",			720, 288, { 1, 50 }},
+    { 9, "secam-svideo",		720, 288, { 1, 50 }},
+    { 10,"pal_60-composite",		768, 288, { 1, 50 }},
+    { 11,"pal_60-tuner",		768, 288, { 1, 50 }},
+    { 12,"pal_60-svideo",		768, 288, { 1, 50 }},
+    { 13, "pal_m-composite",           640, 240, { 1001, 60000 }},
+    { 14, "pal_m-tuner",               640, 240, { 1001, 60000 }},
+    { 15, "pal_m-svideo",              640, 240, { 1001, 60000 }}
+};
+
 #define NUM_FORMATS 12
 
 static XF86VideoFormatRec Formats[NUM_FORMATS] =
@@ -136,14 +245,29 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] =
 };
 
 
-#define NUM_ATTRIBUTES 4
+#define NUM_ATTRIBUTES 18
 
-static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
+static XF86AttributeRec Attributes[NUM_ATTRIBUTES+1] =
 {
-   {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
-   {XvSettable | XvGettable, -64, 63, "XV_BRIGHTNESS"},
-   {XvSettable | XvGettable, 0, 31, "XV_SATURATION"},
-   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"}
+   {             XvGettable, 0, ~0, "XV_DEVICE_ID"},
+   {             XvGettable, 0, ~0, "XV_LOCATION_ID"},
+   {             XvGettable, 0, ~0, "XV_INSTANCE_ID"},
+   {XvSettable             , 0, 1, "XV_SET_DEFAULTS"},
+   {XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
+   {XvSettable | XvGettable, 0, ~0, "XV_COLORKEY"},
+   {XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
+   {XvSettable | XvGettable, 0, 12, "XV_ENCODING"},
+   {XvSettable | XvGettable, 0, -1, "XV_FREQ"},
+   {XvGettable, -1000, 1000, "XV_TUNER_STATUS"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_SATURATION"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_COLOR"},
+   {XvSettable | XvGettable, -1000, 1000, "XV_HUE"},
+   {XvSettable | XvGettable, 0, 1, "XV_MUTE"},
+   {XvSettable | XvGettable, 0, 1, "XV_SAP" },
+   {XvSettable | XvGettable, -1000, 1000, "XV_VOLUME"},
+   { 0, 0, 0, NULL}  /* just a place holder so I don't have to be fancy with commas */
 };
 
 #define NUM_IMAGES 4
@@ -157,24 +281,1018 @@ static XF86ImageRec Images[NUM_IMAGES] =
 };
 
 static void
+R128MuteAudio(R128PortPrivPtr pPriv, Bool mute)
+{
+  pPriv->mute=mute;
+  if (pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume));
+  if (pPriv->tda9850 != NULL) xf86_tda9850_mute(pPriv->tda9850, mute);
+  if (pPriv->tda8425 != NULL) xf86_tda8425_mute(pPriv->tda8425, mute);
+  if ((pPriv->bt829 != NULL) && (pPriv->bt829->out_en)) {
+    if (mute) xf86_bt829_SetP_IO(pPriv->bt829, 0x02);
+    else {
+      switch (pPriv->bt829->mux) {
+        case BT829_MUX2:
+          xf86_bt829_SetP_IO(pPriv->bt829, 0x00);
+          break;
+        case BT829_MUX0:
+          xf86_bt829_SetP_IO(pPriv->bt829, 0x01);
+          break;
+        case BT829_MUX1:
+          xf86_bt829_SetP_IO(pPriv->bt829, 0x00);
+          break;
+        default: /* shouldn't get here */
+          xf86_bt829_SetP_IO(pPriv->bt829, 0x00); /* hardware default */
+          break;
+      }
+    }
+  }
+}
+
+void R128LeaveVT_Video(ScrnInfoPtr pScrn)
+{
+    R128InfoPtr   info      = R128PTR(pScrn);
+    R128PortPrivPtr pPriv;
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LeaveVT: Shutting down Xvideo subsystems\n");
+
+    if(info->adaptor==NULL)return;
+    pPriv = info->adaptor->pPortPrivates[0].ptr;
+    R128ResetVideo(pScrn);
+    if(pPriv==NULL)return;
+    if(pPriv->theatre!=NULL){
+    	xf86_ShutdownTheatre(pPriv->theatre);
+	}
+}
+
+void R128EnterVT_Video(ScrnInfoPtr pScrn)
+{
+    R128InfoPtr   info      = R128PTR(pScrn);
+    R128PortPrivPtr pPriv;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Starting up Xvideo subsystems\n");
+    if(info->adaptor==NULL)return;
+    pPriv = info->adaptor->pPortPrivates[0].ptr;
+    if(pPriv==NULL)return;
+    R128ResetVideo(pScrn);
+}
+
+void R128ShutdownVideo(ScrnInfoPtr pScrn)
+{
+    R128InfoPtr   info      = R128PTR(pScrn);
+    R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "** Shutting down Xvideo subsystems\n");
+    if(pPriv->theatre!=NULL){
+	xf86_ShutdownTheatre(pPriv->theatre);
+	}
+    if(pPriv->i2c!=NULL){
+	if(pPriv->msp3430!=NULL){
+		xfree(pPriv->msp3430);
+		pPriv->msp3430=NULL;
+		}
+	if(pPriv->fi1236!=NULL){
+		xfree(pPriv->fi1236);
+		pPriv->fi1236=NULL;
+		}
+	if(pPriv->bt829!=NULL){
+		xfree(pPriv->bt829);
+		pPriv->bt829=NULL;
+		}
+	if(pPriv->tda9850!=NULL){
+		xfree(pPriv->tda9850);
+		pPriv->tda9850=NULL;
+		}
+	if(pPriv->tda8425!=NULL){
+		xfree(pPriv->tda8425);
+		pPriv->tda8425=NULL;
+		}
+	DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE);
+	pPriv->i2c=NULL;
+	}
+    if(pPriv->VIP!=NULL){
+	xfree(pPriv->VIP);
+	pPriv->VIP=NULL;
+	}
+    if(pPriv->theatre!=NULL){
+	xfree(pPriv->theatre);
+	pPriv->theatre=NULL;
+	}
+}
+
+void
 R128ResetVideo(ScrnInfoPtr pScrn)
 {
     R128InfoPtr   info      = R128PTR(pScrn);
     unsigned char *R128MMIO = info->MMIO;
     R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
+    char tmp[200];
 
+    /* this is done here because each time the server is reset these
+       could change.. Otherwise they remain constant */
 
+    xvBrightness   = MAKE_ATOM("XV_BRIGHTNESS");
+    xvSaturation   = MAKE_ATOM("XV_SATURATION");
+    xvColor        = MAKE_ATOM("XV_COLOR");
+    xvContrast     = MAKE_ATOM("XV_CONTRAST");
+    xvColorKey     = MAKE_ATOM("XV_COLORKEY");
+    xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
+    xvEncoding     = MAKE_ATOM("XV_ENCODING");
+    xvTunerStatus  = MAKE_ATOM("XV_TUNER_STATUS");
+    xvFrequency    = MAKE_ATOM("XV_FREQ");
+    xvVolume       = MAKE_ATOM("XV_VOLUME");
+    xvMute         = MAKE_ATOM("XV_MUTE");
+    xvSAP          = MAKE_ATOM("XV_SAP");
+    xvHue          = MAKE_ATOM("XV_HUE");
+    xv_autopaint_colorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
+    xv_set_defaults = MAKE_ATOM("XV_SET_DEFAULTS");
+
+    xvInstanceID = MAKE_ATOM("XV_INSTANCE_ID");
+    xvDeviceID = MAKE_ATOM("XV_DEVICE_ID");
+    xvLocationID = MAKE_ATOM("XV_LOCATION_ID");
+    
+    sprintf(tmp, "RXXX:%d.%d.%d", info->PciInfo->vendor, info->PciInfo->chipType, info->PciInfo->chipRev);
+    pPriv->device_id = MAKE_ATOM(tmp);
+    sprintf(tmp, "PCI:%02d:%02d.%d", info->PciInfo->bus, info->PciInfo->device, info->PciInfo->func);
+    pPriv->location_id = MAKE_ATOM(tmp);
+    sprintf(tmp, "INSTANCE:%d", pScrn->scrnIndex);
+    pPriv->instance_id = MAKE_ATOM(tmp);
+
+
+    R128WaitForFifo(pScrn, 11); 
     OUTREG(R128_OV0_SCALE_CNTL, 0x80000000);
     OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0);
     OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0);   /* maybe */
     OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f);
-    OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) |
-				 (pPriv->saturation << 8) |
-				 (pPriv->saturation << 16));
+    OUTREG(R128_OV0_COLOUR_CNTL, (((pPriv->brightness*64)/1000) & 0x7f) |
+				     (((pPriv->saturation*31+31000)/2000) << 8) |
+				     (((pPriv->saturation*31+31000)/2000) << 16));
     OUTREG(R128_OV0_GRAPHICS_KEY_MSK, (1 << pScrn->depth) - 1);
     OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey);
     OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE);
     OUTREG(R128_OV0_TEST, 0);
+    OUTPLL(R128_FCP_CNTL, 0x404);
+    OUTREG(R128_CAP0_TRIG_CNTL, 0x0);
+    
+    if(pPriv->VIP!=NULL){
+    	R128VIP_init(pScrn, pPriv);
+	}
+    
+    if(pPriv->theatre != NULL){
+    	xf86_InitTheatre(pPriv->theatre);
+	}
+}
+
+
+#define I2C_DONE	(1<<0)
+#define I2C_NACK	(1<<1)
+#define I2C_HALT	(1<<2)
+#define I2C_SOFT_RST	(1<<5)
+#define I2C_DRIVE_EN	(1<<6)
+#define I2C_DRIVE_SEL	(1<<7)
+#define I2C_START	(1<<8)
+#define I2C_STOP	(1<<9)
+#define I2C_RECEIVE	(1<<10)
+#define I2C_ABORT	(1<<11)
+#define I2C_GO		(1<<12)
+#define I2C_SEL		(1<<16)
+#define I2C_EN		(1<<17)
+
+
+/****************************************************************************
+ *  I2C_WaitForAck (void)                                                   *
+ *                                                                          *
+ *  Function: polls the I2C status bits, waiting for an acknowledge or      *
+ *            an error condition.                                           *
+ *    Inputs: NONE                                                          *
+ *   Outputs: I2C_DONE - the I2C transfer was completed                     *
+ *            I2C_NACK - an NACK was received from the slave                *
+ *            I2C_HALT - a timeout condition has occured                    *
+ ****************************************************************************/
+static CARD8 R128_I2C_WaitForAck (ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
+{
+    CARD8 retval = 0;
+    R128InfoPtr info = R128PTR(pScrn);
+    unsigned char *R128MMIO = info->MMIO;
+    long counter = 0;
+
+    usleep(1000);
+    while(1)
+    {
+        retval = INREG8(R128_I2C_CNTL_0);
+        if (retval & I2C_HALT)
+        {
+            return (I2C_HALT);
+        }
+        if (retval & I2C_NACK)
+        {
+            return (I2C_NACK);
+        }
+	if (retval & I2C_DONE)
+	{
+	    return (I2C_DONE);
+	}
+	counter++;
+	if(counter>1000000)
+	{
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Timeout condition on rage128 i2c bus\n");
+		return (I2C_HALT);
+	}
+		
+    }
+}
+
+static void R128_I2C_Halt (ScrnInfoPtr pScrn)
+{
+    R128InfoPtr info = R128PTR(pScrn);
+    unsigned char *R128MMIO = info->MMIO;
+    CARD8    reg;
+    long counter = 0;
+
+    /* reset status flags */
+    reg = INREG8 (R128_I2C_CNTL_0 + 0) & 0xF8;
+    OUTREG8 (R128_I2C_CNTL_0 + 0, reg);
+
+    /* issue ABORT call */
+    reg = INREG8 (R128_I2C_CNTL_0 + 1) & 0xE7;
+    OUTREG8 (R128_I2C_CNTL_0 + 1, (reg | 0x18));
+
+    /* wait for GO bit to go low */
+    while (INREG8 (R128_I2C_CNTL_0 + 1) & (I2C_GO >> 8))
+    {
+       counter++;
+       if(counter>1000000)return;
+    }
+
+} 
+
+
+
+static Bool R128I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite,
+                            I2CByte *ReadBuffer, int nRead)
+{
+    int loop, status;
+    CARD32 i2c_cntl_0, i2c_cntl_1;
+    R128PortPrivPtr pPriv = (R128PortPrivPtr)(d->pI2CBus->DriverPrivate.ptr);
+    ScrnInfoPtr pScrn = xf86Screens[d->pI2CBus->scrnIndex];
+    R128InfoPtr info = R128PTR(pScrn);
+    unsigned char *R128MMIO = info->MMIO;
+
+    status=I2C_DONE;
+
+    if(nWrite>0){
+      R128WaitForFifo(pScrn, 4+nWrite);
+
+      /* Clear the status bits of the I2C Controller */
+      OUTREG(R128_I2C_CNTL_0, I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST);
+
+      /* Write the address into the buffer first */
+      OUTREG(R128_I2C_DATA, (CARD32) (d->SlaveAddr) & ~(1));
+
+      /* Write Value into the buffer */
+      for (loop = 0; loop < nWrite; loop++)
+      {
+        OUTREG8(R128_I2C_DATA, WriteBuffer[loop]);
+      }
+
+      i2c_cntl_1 = (pPriv->r128_i2c_timing << 24) | I2C_EN | I2C_SEL | 
+    			nWrite | 0x100;
+      OUTREG(R128_I2C_CNTL_1, i2c_cntl_1);
+    
+      i2c_cntl_0 = (pPriv->r128_N << 24) | (pPriv->r128_M << 16) | 
+    			I2C_GO | (1<<8) | (((nRead>0)?0:1) << 9) | I2C_DRIVE_EN;
+      OUTREG(R128_I2C_CNTL_0, i2c_cntl_0);
+    
+      while(INREG8(R128_I2C_CNTL_0+1) & (I2C_GO >> 8));
+
+      status=R128_I2C_WaitForAck(pScrn,pPriv);
+
+      if(status!=I2C_DONE){
+      	R128_I2C_Halt(pScrn);
+      	return FALSE;
+	}
+    }
+    
+    if(nRead > 0) {
+      R128WaitForFifo(pScrn, 4+nRead);
+    
+      OUTREG(R128_I2C_CNTL_0, 0x27);
+
+      /* Write the address into the buffer first */
+      OUTREG(R128_I2C_DATA, (CARD32) (d->SlaveAddr) | (1));
+
+      i2c_cntl_1 = (pPriv->r128_i2c_timing << 24) | I2C_EN | I2C_SEL | 
+    			nRead | 0x100;
+      OUTREG(R128_I2C_CNTL_1, i2c_cntl_1);
+    
+      i2c_cntl_0 = (pPriv->r128_N << 24) | (pPriv->r128_M << 16) | 
+    			I2C_GO | (1<<8) | ((1) << 9) | I2C_DRIVE_EN | I2C_RECEIVE;
+      OUTREG(R128_I2C_CNTL_0, i2c_cntl_0);
+    
+      while(INREG8(R128_I2C_CNTL_0+1) & (I2C_GO >> 8));
+
+      status=R128_I2C_WaitForAck(pScrn,pPriv);
+
+      /* Write Value into the buffer */
+      for (loop = 0; loop < nRead; loop++)
+      {
+        R128WaitForFifo(pScrn, 1);
+	if((status == I2C_HALT) || (status == I2C_NACK))
+	{
+	ReadBuffer[loop]=0xff;
+	} else {
+        ReadBuffer[loop]=INREG8(R128_I2C_DATA) & 0xff;
+	}
+      }
+
+    }
+    
+    if(status!=I2C_DONE){
+    	R128_I2C_Halt(pScrn);
+    	return FALSE;
+	}
+    return TRUE;
+}
+
+static Bool R128ProbeAddress(I2CBusPtr b, I2CSlaveAddr addr)
+{
+     I2CByte a;
+     I2CDevRec d;
+     
+     d.DevName = "Probing";
+     d.SlaveAddr = addr;
+     d.pI2CBus = b;
+     d.NextDev = NULL;
+     
+     return I2C_WriteRead(&d, NULL, 0, &a, 1);
+}
+
+
+#define I2C_CLOCK_FREQ     (80000.0)
+
+const struct 
+{
+   char *name; 
+   int type;
+} R128_tuners[32] =
+    {
+        /* name	,index to tuner_parms table */
+	{"NO TUNNER"		, -1},
+	{"FI1236"		, TUNER_TYPE_FI1236},
+	{"FI1236"		, TUNER_TYPE_FI1236},
+	{"FI1216"		, TUNER_TYPE_FI1216},
+	{"FI1246"		, TUNER_TYPE_FI1246},
+	{"FI1216MF"		, TUNER_TYPE_FI1216},
+	{"FI1236"		, TUNER_TYPE_FI1236},
+	{"FI1256"		, TUNER_TYPE_FI1256},
+	{"FI1236"		, TUNER_TYPE_FI1236},
+	{"FI1216"		, TUNER_TYPE_FI1216},
+	{"FI1246"		, TUNER_TYPE_FI1246},
+	{"FI1216MF"		, TUNER_TYPE_FI1216},
+	{"FI1236"		, TUNER_TYPE_FI1236},
+	{"TEMIC-FN5AL"		, TUNER_TYPE_TEMIC_FN5AL},
+	{"FQ1216ME/P"		, TUNER_TYPE_FI1216},
+	{"UNKNOWN-15"		, -1},
+	{"Alps TSBH5"		, -1},
+	{"Alps TSCxx"		, -1},
+	{"Alps TSCH5 FM"	, -1},
+	{"UNKNOWN-19"		, -1},
+	{"UNKNOWN-20"		, -1},
+	{"UNKNOWN-21"		, -1},
+	{"UNKNOWN-22"		, -1},
+	{"UNKNOWN-23"		, -1},
+        {"UNKNOWN-24"		, -1},
+	{"UNKNOWN-25"		, -1},
+	{"UNKNOWN-26"		, -1},
+	{"UNKNOWN-27"		, -1},
+	{"UNKNOWN-28"		, -1},
+	{"UNKNOWN-29"		, -1},
+        {"UNKNOWN-30"		, -1},
+	{"UNKNOWN-31"		, -1}
+    };
+
+static void R128ResetI2C(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
+{
+    R128InfoPtr info = R128PTR(pScrn);
+    unsigned char *R128MMIO = info->MMIO;
+
+    OUTREG8(R128_I2C_CNTL_1+2, ((I2C_SEL | I2C_EN)>>16));
+    OUTREG8(R128_I2C_CNTL_0+0, (I2C_DONE | I2C_NACK | I2C_HALT | I2C_SOFT_RST | I2C_DRIVE_EN | I2C_DRIVE_SEL));
+}
+
+static void R128InitI2C(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
+{
+    double nm;
+    R128InfoPtr info = R128PTR(pScrn);
+    R128PLLPtr  pll = &(info->pll);
+
+    pPriv->fi1236 = NULL;
+    pPriv->bt829 = NULL;
+    pPriv->tda9850 = NULL;
+    pPriv->msp3430 = NULL;
+    
+    if(pPriv->i2c==NULL) {
+    if(!xf86LoadSubModule(pScrn,"i2c")) {
+    	xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to initialize i2c bus\n");
+	pPriv->i2c=NULL;
+	return;
+        } 
+    xf86LoaderReqSymbols("xf86CreateI2CBusRec", 
+    			  "xf86I2CBusInit",
+			  "xf86DestroyI2CBus",
+			  "xf86CreateI2CDevRec",
+			  "xf86DestroyI2CDevRec",
+			  "xf86I2CDevInit",
+			  "xf86I2CWriteRead",
+			  NULL);
+    pPriv->i2c=CreateI2CBusRec();
+    pPriv->i2c->scrnIndex=pScrn->scrnIndex;
+    pPriv->i2c->BusName="Rage 128 multimedia bus";
+    pPriv->i2c->DriverPrivate.ptr=(pointer)pPriv;
+    pPriv->i2c->I2CWriteRead=R128I2CWriteRead;
+    if(!I2CBusInit(pPriv->i2c)){
+    	xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Failed to register i2c bus\n");
+    	}
+    }
+
+    nm=(pll->reference_freq * 10000.0)/(4.0 * I2C_CLOCK_FREQ);
+    for(pPriv->r128_N=1; pPriv->r128_N<255; pPriv->r128_N++)
+          if((pPriv->r128_N * (pPriv->r128_N-1)) > nm)break;
+    pPriv->r128_M=pPriv->r128_N-1;
+    pPriv->r128_i2c_timing=2*pPriv->r128_N;
+    
+    R128ResetI2C(pScrn, pPriv);
+
+       /* You can't attach addon card to a notebook */
+    if(!pPriv->MM_TABLE_valid && 
+                 (((info->Chipset != PCI_CHIP_RAGE128LE) &&
+		 (info->Chipset != PCI_CHIP_RAGE128LF) &&
+		 (info->Chipset != PCI_CHIP_RAGE128MF) &&
+		 (info->Chipset != PCI_CHIP_RAGE128ML)) || 
+		 info->forceXvProbing))R128_detect_addon(pPriv);
+    	  else pPriv->addon_board = FALSE;
+    
+    /* no multimedia capabilities detected */
+    /* the following code _will_ lockup with MobilityM3 and no i2c device attached 
+       at the moment no safe way is known to detect this (as BIOS has no multimedia table) */ 
+    if(!pPriv->MM_TABLE_valid && !pPriv->addon_board)
+    {
+       if(!info->forceXvProbing){
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No video input capabilities detected\n");
+       	       return;
+	       } else {
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No video input capabilities detected, but continuing anyway.\n");
+	       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Don't be surprised if the system locks up.\n");
+	       }	       
+    }
+
+    if(!xf86LoadSubModule(pScrn,"fi1236"))
+    {
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize fi1236 driver\n");
+    }
+    else
+    {
+    xf86LoaderReqSymbols(FI1236SymbolsList, NULL);
+    if(pPriv->fi1236 == NULL)
+    {
+    	pPriv->fi1236 = xf86_Detect_FI1236(pPriv->i2c, FI1236_ADDR_1);
+    }
+    if(pPriv->fi1236 == NULL)
+    {
+    	pPriv->fi1236 = xf86_Detect_FI1236(pPriv->i2c, FI1236_ADDR_2);
+    }
+    }
+    if(pPriv->fi1236 != NULL)
+    {
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected %s device at 0x%02x\n", 
+	       R128_tuners[pPriv->board_info & 0x0f].name,
+               FI1236_ADDR(pPriv->fi1236));
+               xf86_FI1236_set_tuner_type(pPriv->fi1236, R128_tuners[pPriv->board_info & 0x0f].type);
+    }
+
+    if(!xf86LoadSubModule(pScrn, "bt829"))
+    {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize bt829 driver\n");
+    } else 
+    {
+      xf86LoaderReqSymbols(BT829SymbolsList, NULL);
+      if(pPriv->bt829 == NULL)
+      {
+         pPriv->bt829 = xf86_bt829_Detect(pPriv->i2c, BT829_ATI_ADDR_1);
+      }
+      if(pPriv->bt829 == NULL)
+      {
+         pPriv->bt829 = xf86_bt829_Detect(pPriv->i2c, BT829_ATI_ADDR_2);
+      }
+      if(pPriv->bt829 != NULL)
+      {
+	 pPriv->bt829->tunertype = pPriv->board_info & 0x0f;
+         if(xf86_bt829_ATIInit(pPriv->bt829) < 0)pPriv->bt829 = NULL; /* disable it */
+         if(pPriv->MM_TABLE_valid && (pPriv->bt829!=NULL))
+         {
+           xf86_bt829_SetP_IO(pPriv->bt829, 0x02); /* mute */
+           xf86_bt829_SetOUT_EN(pPriv->bt829, 1);
+         }
+      }
+    }
+
+/* I am not sure whether this is really necessary.. but just in case - and it does
+   not hurt right now */
+
+#if 1    
+    if(!pPriv->MM_TABLE_valid)
+      {
+     	xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Skipping Rage Theatre detection because of absent or invalid MM_TABLE\n");
+	pPriv->theatre=NULL;
+      } else      
+#endif
+    if(pPriv->bt829 == NULL){ 
+    
+       R128VIP_init(pScrn,pPriv);
+
+      if(!xf86LoadSubModule(pScrn,"theatre_detect")) 
+      {
+     	xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre detect module\n");
+	pPriv->theatre=NULL;
+      } else 
+      {
+        pPriv->theatre=xf86_DetectTheatre(pPriv->VIP);
+        if((pPriv->theatre != NULL) && !R128SetupTheatre(pScrn, pPriv, pPriv->theatre))
+        {
+    	  free(pPriv->theatre);
+	  pPriv->theatre=NULL;
+	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize Rage Theatre, chip disabled\n");
+        }
+       
+        if(pPriv->theatre != NULL) {
+	  if(!xf86LoadSubModule(pScrn,"theatre")) 
+	    {
+	      xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to load Rage Theatre module\n");
+	      pPriv->theatre=NULL;
+	    } else 
+	    xf86_InitTheatre(pPriv->theatre);
+        }
+      }
+    }
+
+    if((pPriv->bt829 == NULL) && (pPriv->theatre == NULL))
+             /* No decoder found. No sense initializing audio chips */
+    {
+       return;
+    }
+
+    if(!xf86LoadSubModule(pScrn, "msp3430"))
+    {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize msp3430 driver\n");
+    } 
+    else 
+    {
+    xf86LoaderReqSymbols(MSP3430SymbolsList, NULL);
+    if(pPriv->msp3430 == NULL)
+    {
+       pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_1);
+    }
+    if(pPriv->msp3430 == NULL)
+    {
+       pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_2);
+    }
+#if 0  /* this would confuse bt829 with MSP3430 */
+    if(pPriv->msp3430 == NULL)
+    {
+       pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_3);
+    }
+#endif
+    }
+    if(pPriv->msp3430 != NULL)
+    {
+       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected MSP3430 at 0x%02x\n", 
+                 MSP3430_ADDR(pPriv->msp3430));
+    }
+
+    if(!xf86LoadSubModule(pScrn, "tda9850"))
+    {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize tda9850 driver\n");
+    } else 
+    {
+       xf86LoaderReqSymbols(TDA9850SymbolsList, NULL);
+       if(pPriv->tda9850 == NULL)
+       {
+          pPriv->tda9850 = xf86_Detect_tda9850(pPriv->i2c, TDA9850_ADDR_1);
+       }
+       if(pPriv->tda9850 != NULL)
+       {
+          if(!xf86_tda9850_init(pPriv->tda9850))pPriv->tda9850 = NULL; /* disable it */
+       }
+       if(pPriv->tda9850 != NULL)
+       {
+          xf86_tda9850_setaudio(pPriv->tda9850);
+	  xf86DrvMsg(pScrn->scrnIndex, X_INFO, "tda9850 status 0x%04x\n", xf86_tda9850_getstatus(pPriv->tda9850));
+       }  
+    }
+    if(!xf86LoadSubModule(pScrn, "tda8425"))
+    {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize tda8425 driver\n");
+    } else 
+    {
+       /* Bug bug bug. I don't know how to probe a write-only device properly with Rage 128
+          hardware assisted  i2c. Help ?! */
+       xf86LoaderReqSymbols(TDA8425SymbolsList, NULL);
+       if((pPriv->tda8425 == NULL) && !pPriv->MM_TABLE_valid)
+       {
+          pPriv->tda8425 = xf86_Detect_tda8425(pPriv->i2c, TDA8425_ADDR_1, TRUE);
+       }
+       if(pPriv->tda8425 != NULL)
+       {
+          if(!xf86_tda8425_init(pPriv->tda8425))pPriv->tda8425 = NULL; /* disable it */
+       }
+    }
+
+   if(pPriv->i2c!=NULL) R128_board_setmisc(pPriv);
+}
+
+#define VIP_NAME      "R128 VIP BUS"
+#define VIP_TYPE      "ATI VIP BUS"
+
+static Bool R128VIP_ioctl(GENERIC_BUS_Ptr b, long ioctl, long arg1, char *arg2)
+{
+    long count;
+    switch(ioctl){
+        case GB_IOCTL_GET_NAME:
+	          count=strlen(VIP_NAME)+1;
+		  if(count>arg1)return FALSE;
+		  memcpy(arg2,VIP_NAME,count);
+		  return TRUE;
+		  
+        case GB_IOCTL_GET_TYPE:
+	          count=strlen(VIP_TYPE)+1;
+		  if(count>arg1)return FALSE;
+		  memcpy(arg2,VIP_TYPE,count);
+		  return TRUE;
+		  
+        default: 
+	          return FALSE;
+    }
+}
+
+static CARD32 R128VIP_idle(GENERIC_BUS_Ptr b)
+{
+   ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+   R128InfoPtr info = R128PTR(pScrn);
+   unsigned char *R128MMIO = info->MMIO;
+
+   CARD32 timeout;
+   
+   timeout = INREG(VIPH_TIMEOUT_STAT);
+   if(timeout & VIPH_TIMEOUT_STAT__VIPH_REG_STAT) /* lockup ?? */
+   {
+      OUTREG(VIPH_TIMEOUT_STAT, (timeout & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REG_AK);
+      return (INREG(VIPH_CONTROL) & 0x2000) ? VIP_BUSY: VIP_RESET;
+   }
+   return (INREG(VIPH_CONTROL) & 0x2000) ? VIP_BUSY: VIP_IDLE; 
+}
+
+/* address format:
+     ((device & 0x3)<<14)   | (fifo << 12) | (addr)
+*/
+
+static Bool R128VIP_read(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD8 *buffer)
+{
+   ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+   R128InfoPtr info = R128PTR(pScrn);
+   unsigned char *R128MMIO = info->MMIO;
+   CARD32 status;
+
+   if((count!=1) && (count!=2) && (count!=4))
+   {
+   xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Attempt to access VIP bus with non-stadard transaction length\n");
+   return FALSE;
+   }
+   
+   OUTREG(VIPH_REG_ADDR, address | 0x2000);
+   while(VIP_BUSY == (status = R128VIP_idle(b)));
+   if(VIP_IDLE != status) return FALSE;
+   
+/*
+         disable VIPH_REGR_DIS to enable VIP cycle.
+         The LSB of VIPH_TIMEOUT_STAT are set to 0
+         because 1 would have acknowledged various VIP
+         interrupts unexpectedly 
+*/	
+   OUTREG(VIPH_TIMEOUT_STAT, INREG(VIPH_TIMEOUT_STAT) & (0xffffff00 & ~VIPH_TIMEOUT_STAT__VIPH_REGR_DIS) );
+/*
+         the value returned here is garbage.  The read merely initiates
+         a register cycle
+*/
+    INREG(VIPH_REG_DATA);
+    
+    while(VIP_BUSY == (status = R128VIP_idle(b)));
+    if(VIP_IDLE != status) return FALSE;
+/*
+        set VIPH_REGR_DIS so that the read won't take too long.
+*/
+    OUTREG(VIPH_TIMEOUT_STAT, (INREG(VIPH_TIMEOUT_STAT) & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);	      
+    switch(count){
+        case 1:
+	     *buffer=(CARD8)(INREG(VIPH_REG_DATA) & 0xff);
+	     break;
+	case 2:
+	     *(CARD16 *)buffer=(CARD16) (INREG(VIPH_REG_DATA) & 0xffff);
+	     break;
+	case 4:
+	     *(CARD32 *)buffer=(CARD32) ( INREG(VIPH_REG_DATA) & 0xffffffff);
+	     break;
+	}
+     while(VIP_BUSY == (status = R128VIP_idle(b)));
+     if(VIP_IDLE != status) return FALSE;
+ /*	
+ so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles.
+*/
+     OUTREG(VIPH_TIMEOUT_STAT, (INREG(VIPH_TIMEOUT_STAT) & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
+     return TRUE;
+}
+
+static Bool R128VIP_write(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD8 *buffer)
+{
+    ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+    R128InfoPtr info = R128PTR(pScrn);
+    unsigned char *R128MMIO = info->MMIO;
+    
+    CARD32 status;
+
+
+    if((count!=4))
+    {
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to access VIP bus with non-stadard transaction length\n");
+    return FALSE;
+    }
+    
+    OUTREG(VIPH_REG_ADDR, address & (~0x2000));
+    while(VIP_BUSY == (status = R128VIP_idle(b)));
+    
+    if(VIP_IDLE != status) return FALSE;
+    
+    switch(count){
+        case 4:
+	     OUTREG(VIPH_REG_DATA, *(CARD32 *)buffer);
+	     break;
+	}
+    while(VIP_BUSY == (status = R128VIP_idle(b)));
+    if(VIP_IDLE != status) return FALSE;
+    return TRUE;
+}
+
+static int R128_eeprom_addresses[] = { 0xA8, 0x70, 0x40, 0x78, 0x72, 0x42, 0};
+
+static void R128_read_eeprom(R128PortPrivPtr pPriv)
+{
+   I2CDevRec d;
+   unsigned char data[5];
+   int i;
+   if(pPriv->i2c == NULL) return;
+   
+   d.DevName = "temporary";
+   d.pI2CBus = pPriv->i2c;
+   d.NextDev = NULL;
+   d.StartTimeout = pPriv->i2c->StartTimeout;
+   d.BitTimeout = pPriv->i2c->BitTimeout;
+   d.AcknTimeout = pPriv->i2c->AcknTimeout;
+   d.ByteTimeout = pPriv->i2c->ByteTimeout;
+   pPriv->EEPROM_addr = 0;
+
+   for(i=0;R128_eeprom_addresses[i];i++)
+   {
+     d.SlaveAddr = R128_eeprom_addresses[i];
+     data[0]=0x00;
+     if(!I2C_WriteRead(&d, data, 1, NULL, 0))continue;
+     if(!I2C_WriteRead(&d, NULL, 0, data, 5))continue;
+     if(!memcmp(data, "ATI", 3))
+     {
+        pPriv->EEPROM_present = TRUE;
+	pPriv->EEPROM_addr = R128_eeprom_addresses[i];
+	break;
+     }
+     xf86DrvMsg(pPriv->i2c->scrnIndex, X_INFO, "Device at eeprom addr 0x%02x found, returned 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x\n",
+         d.SlaveAddr,
+     	 data[0], data[1], data[2], data[3], data[4]);
+   }
+
+
+}
+
+void R128VIP_reset(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
+{
+    R128InfoPtr info = R128PTR(pScrn);
+    unsigned char *R128MMIO = info->MMIO;
+
+    R128WaitForFifo(pScrn, 7);
+    OUTREG(VIPH_CONTROL, 0x003F0004); /* slowest, timeout in 16 phases */
+    OUTREG(VIPH_TIMEOUT_STAT, (INREG(VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
+    OUTREG(VIPH_DV_LAT, 0x444400FF); /* set timeslice */
+    OUTREG(VIPH_BM_CHUNK, 0x151);
+    OUTREG(R128_TEST_DEBUG_CNTL, INREG(R128_TEST_DEBUG_CNTL) & (~TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN));
+    OUTREG(R128_MPP_GP_CONFIG, 0);
+    OUTREG(R128_MPP_TB_CONFIG, 0);
+}
+
+void R128VIP_init(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
+{
+    pPriv->VIP=xcalloc(1,sizeof(GENERIC_BUS_Rec));
+    pPriv->VIP->scrnIndex=pScrn->scrnIndex;
+    pPriv->VIP->DriverPrivate.ptr=pPriv;
+    pPriv->VIP->ioctl=R128VIP_ioctl;
+    pPriv->VIP->read=R128VIP_read;
+    pPriv->VIP->write=R128VIP_write;
+
+    R128VIP_reset(pScrn, pPriv);
+}
+
+
+static void R128ReadMM_TABLE(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv)
+{
+     R128InfoPtr info = R128PTR(pScrn);
+     CARD16 mm_table;
+     CARD16 bios_header;
+
+     
+     if((info->VBIOS==NULL)||(info->VBIOS[0]!=0x55)||(info->VBIOS[1]!=0xaa)){
+     	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cannot access BIOS or it is not valid.\n"
+		"\t\tYou will need to specify options RageTheatreCrystal, RageTheatreTunerPort, \n"
+		"\t\tRageTheatreSVideoPort and TunerType in /etc/XF86Config.\n"
+		);
+	pPriv->MM_TABLE_valid = FALSE;
+     	} else {
+
+
+     bios_header=info->VBIOS[0x48];
+     bios_header+=(((int)info->VBIOS[0x49]+0)<<8);	     
+	
+     mm_table=info->VBIOS[bios_header+0x38];
+     if(mm_table==0)
+     {
+         xf86DrvMsg(pScrn->scrnIndex,X_INFO,"No MM_TABLE found, %x, %x\n",bios_header,mm_table);
+	 pPriv->MM_TABLE_valid = FALSE;
+	 goto forced_settings;
+     }    
+     
+     mm_table+=(((int)info->VBIOS[bios_header+0x39]+0)<<8)-2;
+
+     xf86DrvMsg(pScrn->scrnIndex,X_INFO,"VIDEO BIOS TABLE OFFSETS: bios_header=0x%04x mm_table=0x%04x\n",bios_header,mm_table);
+
+     if(mm_table>0)
+     {
+	 memcpy(&(pPriv->MM_TABLE), &(info->VBIOS[mm_table]), sizeof(_MM_TABLE));
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MM_TABLE: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
+	     pPriv->MM_TABLE.table_revision,
+    	     pPriv->MM_TABLE.table_size,
+	     pPriv->MM_TABLE.tuner_type,
+    	     pPriv->MM_TABLE.audio_chip,
+	     pPriv->MM_TABLE.product_id,
+    	     pPriv->MM_TABLE.tuner_voltage_teletext_fm,
+	     pPriv->MM_TABLE.i2s_config,
+	     pPriv->MM_TABLE.video_decoder_type,
+    	     pPriv->MM_TABLE.video_decoder_host_config,
+	     pPriv->MM_TABLE.input[0],
+    	     pPriv->MM_TABLE.input[1],
+	     pPriv->MM_TABLE.input[2],
+    	     pPriv->MM_TABLE.input[3],
+	     pPriv->MM_TABLE.input[4]);
+	 pPriv->MM_TABLE_valid = TRUE;
+	 pPriv->board_info = pPriv->MM_TABLE.tuner_type;
+     } else {
+         xf86DrvMsg(pScrn->scrnIndex,X_INFO,"No MM_TABLE found: %x, %x\n",bios_header,mm_table);
+	 pPriv->MM_TABLE_valid = FALSE;
+     } }
+     forced_settings:
+
+     if(info->tunerType>=0){
+     		pPriv->MM_TABLE.tuner_type=info->tunerType;
+		pPriv->board_info=info->tunerType;
+     		}
+     /* enough information was provided in the options */
+     
+     if(!pPriv->MM_TABLE_valid && (info->tunerType>=0) && (info->RageTheatreCrystal>=0) &&
+            (info->RageTheatreTunerPort>=0) && (info->RageTheatreCompositePort>=0) &&
+	    (info->RageTheatreSVideoPort>=0) ) {
+	    	pPriv->MM_TABLE_valid = TRUE;
+	    	}
+}
+
+static int R128_addon_addresses[] = { 0x70, 0x40, 0x78, 0x72, 0x42, 0};
+
+void R128_detect_addon(R128PortPrivPtr pPriv)
+{
+   I2CDevRec d;
+   CARD8 data[1];
+   int i;
+   if(pPriv->i2c == NULL) return;
+   
+   d.DevName = "temporary";
+   d.pI2CBus = pPriv->i2c;
+   d.NextDev = NULL;
+   d.StartTimeout = pPriv->i2c->StartTimeout;
+   d.BitTimeout = pPriv->i2c->BitTimeout;
+   d.AcknTimeout = pPriv->i2c->AcknTimeout;
+   d.ByteTimeout = pPriv->i2c->ByteTimeout;
+   pPriv->addon_board = FALSE;
+
+   for(i=0;R128_addon_addresses[i];i++)
+   {
+     d.SlaveAddr = R128_addon_addresses[i];
+     data[0]=0xFF;
+     if(!I2C_WriteRead(&d, data, 1, NULL, 0))continue;
+     if(!I2C_WriteRead(&d, NULL, 0, data, 1))continue;
+     if((data[0] == 0xFF) || (data[0] == 0x00))continue;
+     pPriv->addon_board = TRUE;
+     pPriv->board_control = R128_addon_addresses[i];
+     pPriv->board_info = data[0];
+     xf86DrvMsg(pPriv->i2c->scrnIndex, X_INFO, "Standalone board at addr 0x%02x found, returned 0x%02x\n",
+         d.SlaveAddr,
+     	 data[0]);
+     R128_board_setmisc(pPriv);
+     break;
+   }
+
+
+}
+
+Bool R128SetupTheatre(ScrnInfoPtr pScrn, R128PortPrivPtr pPriv, TheatrePtr t)
+{
+    R128InfoPtr info = R128PTR(pScrn);
+    R128PLLPtr  pll = &(info->pll);
+
+    CARD8 a;
+    CARD16 bios_header;
+    CARD16 pll_info_block;
+    int i;
+	
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%02x 0x%02x\n", info->VBIOS[0],
+               info->VBIOS[1]);	
+     bios_header=info->VBIOS[0x48];
+     bios_header+=(((int)info->VBIOS[0x49]+0)<<8);	     
+	
+     pll_info_block=info->VBIOS[bios_header+0x30];
+     pll_info_block+=(((int)info->VBIOS[bios_header+0x31]+0)<<8);
+       
+     t->video_decoder_type=info->VBIOS[pll_info_block+0x08];
+     t->video_decoder_type+=(((int)info->VBIOS[pll_info_block+0x09]+0)<<8);
+	
+     xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"video decoder type is 0x%04x versus 0x%04x\n",t->video_decoder_type,
+		pll->xclk);
+	
+     if(!pPriv->MM_TABLE_valid)
+     {
+       xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "no multimedia table present, not using Rage Theatre for input\n");
+       free(pPriv->theatre);
+       pPriv->theatre = NULL;
+       return FALSE;
+     }
+     for(i=0;i<5;i++){
+		a=pPriv->MM_TABLE.input[i];
+		
+		switch(a & 0x3){
+			case 1:
+				t->wTunerConnector=i;
+				xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"Tuner is on port %d\n",i);
+				break;
+			case 2:  if(a & 0x4){
+				   t->wComp0Connector=RT_COMP2;
+				   } else {
+				   t->wComp0Connector=RT_COMP1;
+				   }
+				xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"Composite connector is port %d\n",(int)t->wComp0Connector);
+				  break;
+			case 3:  if(a & 0x4){
+				   t->wSVideo0Connector=RT_YCR_COMP4;
+				   } else {
+				   t->wSVideo0Connector=RT_YCF_COMP4;
+				   }
+				xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"SVideo connector is port %d\n",(int)t->wSVideo0Connector);
+				   break;
+			default:
+				break;
+			}
+		}
+
+	xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"Rage Theatre: Connectors (detected): tuner=%d, composite=%d, svideo=%d\n",(int)t->wTunerConnector, (int)t->wComp0Connector, (int)t->wSVideo0Connector);
+
+	if(info->RageTheatreTunerPort>=0)t->wTunerConnector=info->RageTheatreTunerPort;
+	if(info->RageTheatreCompositePort>=0)t->wComp0Connector=info->RageTheatreCompositePort;
+	if(info->RageTheatreSVideoPort>=0)t->wSVideo0Connector=info->RageTheatreSVideoPort;
+	
+	xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"Rage Theatre: Connectors (using): tuner=%d, composite=%d, svideo=%d\n",(int)t->wTunerConnector, (int)t->wComp0Connector, (int)t->wSVideo0Connector);
+
+	switch((info->RageTheatreCrystal>=0)?info->RageTheatreCrystal:pll->reference_freq){
+		case 2700:
+			t->video_decoder_type=RT_FREF_2700;
+			break;
+		case 2950:
+			t->video_decoder_type=RT_FREF_2950;
+			break;
+		default:
+			xf86DrvMsg(t->VIP->scrnIndex,X_INFO,
+				"Unsupported reference clock frequency, Rage Theatre disabled\n");
+			t->theatre_num=-1;
+			return FALSE;
+		}
+	xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"video decoder type used: 0x%04x\n",t->video_decoder_type);
+	return TRUE;
 }
 
 
@@ -184,6 +1302,7 @@ R128AllocAdaptor(ScrnInfoPtr pScrn)
     XF86VideoAdaptorPtr adapt;
     R128InfoPtr info = R128PTR(pScrn);
     R128PortPrivPtr pPriv;
+    unsigned char *R128MMIO = info->MMIO;
 
     if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn)))
 	return NULL;
@@ -206,10 +1325,29 @@ R128AllocAdaptor(ScrnInfoPtr pScrn)
     pPriv->doubleBuffer = TRUE;
     pPriv->videoStatus = 0;
     pPriv->brightness = 0;
-    pPriv->saturation = 16;
+    pPriv->saturation = 0;
+    pPriv->contrast = 0;
+    pPriv->hue = 0;
     pPriv->currentBuffer = 0;
     R128ECP(pScrn, pPriv);
 
+    pPriv->video_stream_active = FALSE;
+    pPriv->encoding = 1;
+    pPriv->frequency = 1000;
+    pPriv->volume = -1000;
+    pPriv->mute = TRUE;
+    pPriv->v=0;
+   
+    pPriv->autopaint_colorkey = TRUE;
+    /* choose ecp_div setting */
+    if(info->ModeReg.dot_clock_freq < 12500) pPriv->ecp_div = 0;
+    	   else
+    if(info->ModeReg.dot_clock_freq < 25000) pPriv->ecp_div = 1;
+    	   else pPriv->ecp_div = 2;
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div);
+
+    OUTPLL(R128_VCLK_ECP_CNTL, (INPLL(pScrn, R128_VCLK_ECP_CNTL) & 0xfffffCff) | (pPriv->ecp_div << 8));
+
     return adapt;
 }
 
@@ -221,22 +1359,55 @@ R128SetupImageVideo(ScreenPtr pScreen)
     R128PortPrivPtr pPriv;
     XF86VideoAdaptorPtr adapt;
 
+    info->accel->Sync(pScrn);
+
+    if(info->adaptor != NULL){
+    	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reinitializing Xvideo subsystems\n");
+	R128ResetVideo(pScrn);
+	return info->adaptor;
+	}
+
     if(!(adapt = R128AllocAdaptor(pScrn)))
 	return NULL;
+    pPriv = (R128PortPrivPtr)(adapt->pPortPrivates[0].ptr);
+    
+    R128ReadMM_TABLE(pScrn, pPriv);
+
+    R128InitI2C(pScrn,pPriv);
 
     adapt->type = XvWindowMask | XvInputMask | XvImageMask;
     adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
     adapt->name = "ATI Rage128 Video Overlay";
+       if(pPriv->theatre != NULL)
+       {
+          adapt->type = XvWindowMask | XvInputMask | XvImageMask | XvVideoMask;
+          adapt->nEncodings = 13;
+          adapt->pEncodings = InputVideoEncodings;
+       } else 
+       if(pPriv->bt829 != NULL)
+       {
+          adapt->type = XvWindowMask | XvInputMask | XvImageMask | XvVideoMask;
+          adapt->nEncodings = 16;
+	  adapt->pEncodings = InputVideoEncodings;
+       } else
+       {
+          adapt->type = XvWindowMask | XvInputMask | XvImageMask;
     adapt->nEncodings = 1;
     adapt->pEncodings = &DummyEncoding;
+       }
     adapt->nFormats = NUM_FORMATS;
     adapt->pFormats = Formats;
     adapt->nPorts = 1;
+       if(pPriv->msp3430!=NULL)
     adapt->nAttributes = NUM_ATTRIBUTES;
+	       else 
+       if((pPriv->theatre!=NULL)||(pPriv->bt829!=NULL))
+	       adapt->nAttributes = NUM_ATTRIBUTES-1;
+	       else adapt->nAttributes =  NUM_ATTRIBUTES-3;
     adapt->pAttributes = Attributes;
     adapt->nImages = NUM_IMAGES;
     adapt->pImages = Images;
-    adapt->PutVideo = NULL;
+       adapt->PutVideo = R128PutVideo;
     adapt->PutStill = NULL;
     adapt->GetVideo = NULL;
     adapt->GetStill = NULL;
@@ -254,9 +1425,135 @@ R128SetupImageVideo(ScreenPtr pScreen)
 
     R128ResetVideo(pScrn);
 
+    if(info->VBIOS!=NULL){
+    	xfree(info->VBIOS);
+	info->VBIOS=NULL;
+	}
+
     return adapt;
 }
 
+/* I really should stick this in miregion */
+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.x2 != B->extents.x2) ||
+       (A->extents.y1 != B->extents.y1) ||
+       (A->extents.y2 != B->extents.y2))
+	return FALSE;
+
+    dataA = (pointer)REGION_RECTS(A);
+    dataB = (pointer)REGION_RECTS(B);
+
+    while(num--) {
+	if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+	   return FALSE;
+	dataA += 2;
+	dataB += 2;
+    }
+
+    return TRUE;
+}
+
+
+/* R128ClipVideo -
+
+   Takes the dst box in standard X BoxRec form (top and left
+   edges inclusive, bottom and right exclusive).  The new dst
+   box is returned.  The source boundaries are given (xa, ya
+   inclusive, xb, yb exclusive) and returned are the new source
+   boundaries in 16.16 fixed point.
+*/
+
+#define DummyScreen screenInfo.screens[0]
+
+static Bool
+R128ClipVideo(
+  BoxPtr dst,
+  INT32 *xa,
+  INT32 *xb,
+  INT32 *ya,
+  INT32 *yb,
+  RegionPtr reg,
+  INT32 width,
+  INT32 height
+){
+    INT32 vscale, hscale, delta;
+    BoxPtr extents = REGION_EXTENTS(DummyScreen, reg);
+    int diff;
+
+    hscale = ((*xb - *xa) << 16) / (dst->x2 - dst->x1);
+    vscale = ((*yb - *ya) << 16) / (dst->y2 - dst->y1);
+
+    *xa <<= 16; *xb <<= 16;
+    *ya <<= 16; *yb <<= 16;
+
+    diff = extents->x1 - dst->x1;
+    if(diff > 0) {
+	dst->x1 = extents->x1;
+	*xa += diff * hscale;
+    }
+    diff = dst->x2 - extents->x2;
+    if(diff > 0) {
+	dst->x2 = extents->x2;
+	*xb -= diff * hscale;
+    }
+    diff = extents->y1 - dst->y1;
+    if(diff > 0) {
+	dst->y1 = extents->y1;
+	*ya += diff * vscale;
+    }
+    diff = dst->y2 - extents->y2;
+    if(diff > 0) {
+	dst->y2 = extents->y2;
+	*yb -= diff * vscale;
+    }
+
+    if(*xa < 0) {
+	diff =  (- *xa + hscale - 1)/ hscale;
+	dst->x1 += diff;
+	*xa += diff * hscale;
+    }
+    delta = *xb - (width << 16);
+    if(delta > 0) {
+	diff = (delta + hscale - 1)/ hscale;
+	dst->x2 -= diff;
+	*xb -= diff * hscale;
+    }
+    if(*xa >= *xb) return FALSE;
+
+    if(*ya < 0) {
+	diff =  (- *ya + vscale - 1)/ vscale;
+	dst->y1 += diff;
+	*ya += diff * vscale;
+    }
+    delta = *yb - (height << 16);
+    if(delta > 0) {
+	diff = (delta + vscale - 1)/ vscale;
+	dst->y2 -= diff;
+	*yb -= diff * vscale;
+    }
+    if(*ya >= *yb) return FALSE;
+
+    if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) ||
+       (dst->y1 != extents->y1) || (dst->y2 != extents->y2))
+    {
+	RegionRec clipReg;
+	REGION_INIT(DummyScreen, &clipReg, dst, 1);
+	REGION_INTERSECT(DummyScreen, reg, reg, &clipReg);
+	REGION_UNINIT(DummyScreen, &clipReg);
+    }
+    return TRUE;
+}
+
 static void
 R128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
 {
@@ -269,6 +1566,17 @@ R128StopVideo(ScrnInfoPtr pScrn, pointer data, Bool cleanup)
   if(cleanup) {
      if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
 	OUTREG(R128_OV0_SCALE_CNTL, 0);
+	if (info->cursor_start)
+	   xf86ForceHWCursor (pScrn->pScreen, FALSE);
+     }
+    if(pPriv->video_stream_active) {
+	R128WaitForFifo(pScrn, 8); 
+        OUTPLL(R128_FCP_CNTL, 0x404);
+        OUTREG(R128_CAP0_TRIG_CNTL, 0x0);
+	R128ResetVideo(pScrn);
+	pPriv->video_stream_active = FALSE;
+        R128MuteAudio(pPriv, TRUE);
+        if(pPriv->i2c!=NULL) R128_board_setmisc(pPriv);
      }
      if(pPriv->linear) {
 	xf86FreeOffscreenLinear(pPriv->linear);
@@ -293,24 +1601,60 @@ R128SetPortAttribute(
   R128InfoPtr info = R128PTR(pScrn);
   unsigned char *R128MMIO = info->MMIO;
   R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
+  Bool save_mute;
+
+  info->accel->Sync(pScrn);
 
+  if(attribute == xv_autopaint_colorkey) {
+  	pPriv->autopaint_colorkey = value;
+  } else
+  if(attribute == xv_set_defaults) {
+        R128SetPortAttribute(pScrn, xv_autopaint_colorkey, TRUE, data);
+        R128SetPortAttribute(pScrn, xvBrightness, 0, data);
+        R128SetPortAttribute(pScrn, xvSaturation, 0, data);
+        R128SetPortAttribute(pScrn, xvContrast,   0, data);
+        R128SetPortAttribute(pScrn, xvHue,   0, data);
+        R128SetPortAttribute(pScrn, xvVolume,   0, data);
+        R128SetPortAttribute(pScrn, xvMute,   1, data);
+        R128SetPortAttribute(pScrn, xvSAP,   0, data);
+        R128SetPortAttribute(pScrn, xvDoubleBuffer,   1, data);
+  } else
   if(attribute == xvBrightness) {
-	if((value < -64) || (value > 63))
-	   return BadValue;
-	pPriv->brightness = value;
+        if(value < -1000)value = -1000;
+	if(value > 1000)value = 1000;
 
-	OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) |
-				     (pPriv->saturation << 8) |
-				     (pPriv->saturation << 16));
+	pPriv->brightness = value;
+	R128WaitForFifo(pScrn, 2);
+	OUTREG(R128_OV0_COLOUR_CNTL, (((pPriv->brightness*64)/1000) & 0x7f) |
+				     (((pPriv->saturation*31+31000)/2000) << 8) |
+				     (((pPriv->saturation*31+31000)/2000) << 16));
+	if(pPriv->theatre!=NULL) xf86_RT_SetBrightness(pPriv->theatre, pPriv->brightness);	
+	if(pPriv->bt829!=NULL) xf86_bt829_SetBrightness(pPriv->bt829, pPriv->brightness);	
   } else
-  if(attribute == xvSaturation) {
-	if((value < 0) || (value > 31))
-	   return BadValue;
+  if((attribute == xvSaturation) || (attribute == xvColor)) {
+        if(value < -1000)value = -1000;
+	if(value > 1000)value = 1000;
 	pPriv->saturation = value;
-
-	OUTREG(R128_OV0_COLOUR_CNTL, (pPriv->brightness & 0x7f) |
-				     (pPriv->saturation << 8) |
-				     (pPriv->saturation << 16));
+	R128WaitForFifo(pScrn, 2);
+	OUTREG(R128_OV0_COLOUR_CNTL, (((pPriv->brightness*64)/1000) & 0x7f) |
+				     (((pPriv->saturation*31+31000)/2000) << 8) |
+				     (((pPriv->saturation*31+31000)/2000) << 16));
+	if(pPriv->theatre != NULL)xf86_RT_SetSaturation(pPriv->theatre, value);
+	if(pPriv->bt829!=NULL) xf86_bt829_SetSaturation(pPriv->bt829, pPriv->saturation);	
+  } else
+  if(attribute == xvContrast) {
+        if(value < -1000)value = -1000;
+	if(value > 1000)value = 1000;
+	pPriv->contrast = value;
+	if(pPriv->theatre != NULL)xf86_RT_SetContrast(pPriv->theatre, value);
+	if(pPriv->bt829!=NULL) xf86_bt829_SetContrast(pPriv->bt829, pPriv->contrast);	
+  } else
+  if(attribute == xvHue) {
+        if(value < -1000)value = -1000;
+	if(value > 1000)value = 1000;
+	pPriv->hue = value;
+	if(pPriv->theatre != NULL)xf86_RT_SetTint(pPriv->theatre, value);
+	if(pPriv->bt829!=NULL) xf86_bt829_SetTint(pPriv->bt829, pPriv->hue);	
   } else
   if(attribute == xvDoubleBuffer) {
 	if((value < 0) || (value > 1))
@@ -319,10 +1663,51 @@ R128SetPortAttribute(
   } else
   if(attribute == xvColorKey) {
 	pPriv->colorKey = value;
+	R128WaitForFifo(pScrn, 2);
 	OUTREG(R128_OV0_GRAPHICS_KEY_CLR, pPriv->colorKey);
 
 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
-  } else return BadMatch;
+  } else 
+  if(attribute == xvEncoding) {
+	pPriv->encoding = value;
+	if(pPriv->video_stream_active)
+	{
+	   if(pPriv->theatre != NULL) R128_RT_SetEncoding(pPriv);
+	   if(pPriv->bt829 != NULL) R128_BT_SetEncoding(pPriv);
+	   if(pPriv->msp3430 != NULL) R128_MSP_SetEncoding(pPriv);
+           if(pPriv->i2c!=NULL) R128_board_setmisc(pPriv);
+	/* put more here to actually change it */
+	}
+  } else 
+  if(attribute == xvFrequency) {
+        pPriv->frequency = value;
+	save_mute = pPriv->mute;
+	R128MuteAudio(pPriv, TRUE);
+  	if(pPriv->fi1236 != NULL) xf86_TUNER_set_frequency(pPriv->fi1236, value);
+	if((pPriv->msp3430 != NULL) && (pPriv->msp3430->recheck))
+		xf86_InitMSP3430(pPriv->msp3430);
+	R128MuteAudio(pPriv, save_mute);
+  } else 
+  if(attribute == xvMute) {
+        pPriv->mute = value;
+        R128MuteAudio(pPriv, pPriv->mute);
+        if(pPriv->i2c!=NULL) R128_board_setmisc(pPriv);
+  } else 
+  if(attribute == xvSAP) {
+        pPriv->sap_channel = value;
+	if(pPriv->msp3430!=NULL)xf86_MSP3430SetSAP(pPriv->msp3430, pPriv->sap_channel?4:3);
+	if(pPriv->tda9850!=NULL)xf86_tda9850_sap_mute(pPriv->tda9850, pPriv->sap_channel?1:0);
+  } else 
+  if(attribute == xvVolume) {
+  	if(value<-1000) value=-1000;
+	if(value>1000) value=1000;
+        pPriv->volume = value;
+	pPriv->mute = FALSE;
+        if(pPriv->msp3430 != NULL) xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_VOLUME(value));
+        R128MuteAudio(pPriv, pPriv->mute);
+        if(pPriv->i2c!=NULL) R128_board_setmisc(pPriv);
+  } else 
+     return BadMatch;
 
   return Success;
 }
@@ -334,20 +1719,65 @@ R128GetPortAttribute(
   INT32 *value,
   pointer data
 ){
+  R128InfoPtr info = R128PTR(pScrn);
   R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
 
+  info->accel->Sync(pScrn);
+
+  if(attribute == xv_autopaint_colorkey) {
+  	*value = pPriv->autopaint_colorkey;
+  } else
   if(attribute == xvBrightness) {
 	*value = pPriv->brightness;
   } else
-  if(attribute == xvSaturation) {
+  if((attribute == xvSaturation) || (attribute == xvColor)) {
 	*value = pPriv->saturation;
   } else
+  if(attribute == xvContrast) {
+	*value = pPriv->contrast;
+  } else
+  if(attribute == xvHue) {
+	*value = pPriv->hue;
+  } else
   if(attribute == xvDoubleBuffer) {
 	*value = pPriv->doubleBuffer ? 1 : 0;
   } else
   if(attribute == xvColorKey) {
 	*value = pPriv->colorKey;
-  } else return BadMatch;
+  } else 
+  if(attribute == xvEncoding) {
+	*value = pPriv->encoding;
+  } else 
+  if(attribute == xvFrequency) {
+        *value = pPriv->frequency;
+  } else 
+  if(attribute == xvTunerStatus) {
+  	if(pPriv->fi1236==NULL){
+		*value=TUNER_OFF;
+		} else
+		{
+	        *value = xf86_TUNER_get_afc_hint(pPriv->fi1236);
+		}
+  } else 
+  if(attribute == xvMute) {
+        *value = pPriv->mute;
+  } else 
+  if(attribute == xvSAP) {
+        *value = pPriv->sap_channel;
+  } else 
+  if(attribute == xvVolume) {
+        *value = pPriv->volume;
+  } else 
+  if(attribute == xvDeviceID) {
+        *value = pPriv->device_id;
+  } else 
+  if(attribute == xvLocationID) {
+        *value = pPriv->location_id;
+  } else 
+  if(attribute == xvInstanceID) {
+        *value = pPriv->instance_id;
+  } else 
+    return BadMatch;
 
   return Success;
 }
@@ -383,6 +1813,7 @@ R128QueryBestSize(
 
 static Bool
 R128DMA(
+  ScrnInfoPtr pScrn,
   R128InfoPtr info,
   unsigned char *src,
   unsigned char *dst,
@@ -414,6 +1845,10 @@ R128DMA(
     if ((passes = (h+hpass-1)/hpass) > MAXPASSES)
         return FALSE;
 
+#if 0
+    R128CCEWaitForIdle(pScrn);
+#endif
+
     /* Request indirect buffers */
     srcpassbytes = w*hpass;
 
@@ -491,6 +1926,7 @@ R128DMA(
 
 static void
 R128CopyData422(
+  ScrnInfoPtr pScrn,
   R128InfoPtr info,
   unsigned char *src,
   unsigned char *dst,
@@ -503,7 +1939,7 @@ R128CopyData422(
 
     /* Attempt data transfer with DMA and fall back to memcpy */
 
-    if (!R128DMA(info, src, dst, srcPitch, dstPitch, h, w)) {
+    if (!R128DMA(pScrn, info, src, dst, srcPitch, dstPitch, h, w)) {
         while(h--) {
 	    memcpy(dst, src, w);
 	    src += srcPitch;
@@ -514,6 +1950,7 @@ R128CopyData422(
 
 static void
 R128CopyData420(
+   ScrnInfoPtr pScrn,
    R128InfoPtr info,
    unsigned char *src1,
    unsigned char *src2,
@@ -531,7 +1968,7 @@ R128CopyData420(
 
    /* Attempt data transfer with DMA and fall back to memcpy */
 
-   if (!R128DMA(info, src1, dst1, srcPitch, dstPitch, h, w)) {
+   if (!R128DMA(pScrn,info, src1, dst1, srcPitch, dstPitch, h, w)) {
        count = h;
        while(count--) {
 	   memcpy(dst1, src1, w);
@@ -544,7 +1981,7 @@ R128CopyData420(
    h >>= 1;
    dstPitch >>= 1;
 
-   if (!R128DMA(info, src2, dst2, srcPitch2, dstPitch, h, w)) {
+   if (!R128DMA(pScrn,info, src2, dst2, srcPitch2, dstPitch, h, w)) {
        count = h;
        while(count--) {
 	   memcpy(dst2, src2, w);
@@ -553,7 +1990,7 @@ R128CopyData420(
        }
    }
 
-   if (!R128DMA(info, src3, dst3, srcPitch2, dstPitch, h, w)) {
+   if (!R128DMA(pScrn, info, src3, dst3, srcPitch2, dstPitch, h, w)) {
        count = h;
        while(count--) {
 	   memcpy(dst3, src3, w);
@@ -609,7 +2046,7 @@ static void
 R128DisplayVideo422(
     ScrnInfoPtr pScrn,
     int id,
-    int offset,
+    int offset1, int offset2,
     short width, short height,
     int pitch,
     int left, int right, int top,
@@ -621,13 +2058,31 @@ R128DisplayVideo422(
     unsigned char *R128MMIO = info->MMIO;
     R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
     int v_inc, h_inc, step_by, tmp;
+    double v_inc_d;
     int p1_h_accum_init, p23_h_accum_init;
     int p1_v_accum_init;
+    long counter;
 
     R128ECP(pScrn, pPriv);
+    /* Choose ecp_div setting. As the user may have switched resolution
+      we better do it again. */
+    if(info->ModeReg.dot_clock_freq < 12500) pPriv->ecp_div = 0;
+    	   else
+    if(info->ModeReg.dot_clock_freq < 25000) pPriv->ecp_div = 1;
+    	   else pPriv->ecp_div = 2;
 
-    v_inc = (src_h << 20) / drw_h;
-    h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w;
+    OUTPLL(R128_VCLK_ECP_CNTL, (INPLL(pScrn, R128_VCLK_ECP_CNTL) & 0xfffffCff) | (pPriv->ecp_div << 8));
+
+    v_inc = (1 << (20
+		+ ((pScrn->currentMode->Flags & V_INTERLACE)?1:0)
+		- ((pScrn->currentMode->Flags & V_DBLSCAN)?1:0)));
+
+    v_inc_d = src_h;
+    v_inc_d = v_inc_d/drw_h;
+    v_inc = v_inc * v_inc_d;
+
+    h_inc = ((src_w << (12
+    		+ pPriv->ecp_div)) / drw_w);
     step_by = 1;
 
     while(h_inc >= (2 << 12)) {
@@ -637,7 +2092,8 @@ R128DisplayVideo422(
 
     /* keep everything in 16.16 */
 
-    offset += ((left >> 16) & ~7) << 1;
+    offset1 += ((left >> 16) & ~7) << 1;
+    offset2 += ((left >> 16) & ~7) << 1;
 
     tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
     p1_h_accum_init = ((tmp <<  4) & 0x000f8000) |
@@ -652,13 +2108,17 @@ R128DisplayVideo422(
 
     left = (left >> 16) & 7;
 
-    OUTREG(R128_OV0_REG_LOAD_CNTL, 1);
-    while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3)));
+    R128WaitForFifo(pScrn,2);
+    OUTREG(R128_OV0_REG_LOAD_CNTL, R128_REG_LD_CTL_LOCK);
+    R128WaitForIdle(pScrn);
+    counter=10000;
+    while(!(INREG(R128_OV0_REG_LOAD_CNTL) & R128_REG_LD_CTL_LOCK_READBACK) && (counter>=0))counter--;
+    if(counter<0)xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot lock overlay registers\n");
 
     OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16));
     OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8));
-    OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16));
-    OUTREG(R128_OV0_Y_X_END,   dstBox->x2 | (dstBox->y2 << 16));
+    OUTREG(R128_OV0_Y_X_START, dstBox->x1 | ((dstBox->y1*((pScrn->currentMode->Flags & V_DBLSCAN)?2:1)) << 16));
+    OUTREG(R128_OV0_Y_X_END,   dstBox->x2 | ((dstBox->y2*((pScrn->currentMode->Flags & V_DBLSCAN)?2:1)) << 16));
     OUTREG(R128_OV0_V_INC, v_inc);
     OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
     OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch);
@@ -666,17 +2126,41 @@ R128DisplayVideo422(
     left >>= 1; width >>= 1;
     OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16));
     OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16));
-    OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset & 0xfffffff0);
+    OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0);
+
+    R128WaitForFifo(pScrn, 14);
+    OUTREG(R128_OV0_VID_BUF1_BASE_ADRS, offset1 & 0xfffffff0);
+    OUTREG(R128_OV0_VID_BUF2_BASE_ADRS, offset1 & 0xfffffff0);
+
+    OUTREG(R128_OV0_VID_BUF3_BASE_ADRS, offset2 & 0xfffffff0);
+    OUTREG(R128_OV0_VID_BUF4_BASE_ADRS, offset2 & 0xfffffff0);
+    OUTREG(R128_OV0_VID_BUF5_BASE_ADRS, offset2 & 0xfffffff0);
     OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
     OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0);
     OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
     OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
-
+/*  older, original magic
     if(id == FOURCC_UYVY)
        OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8C03);
     else
        OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03);
-
+*/
+    if(id == FOURCC_UYVY)
+       OUTREG(R128_OV0_SCALE_CNTL, R128_SCALER_PIX_EXPAND \
+	       | R128_SCALER_Y2R_TEMP \
+	       | R128_SCALER_SOURCE_YVYU422 \
+	       | R128_SCALER_SMART_SWITCH \
+	       | R128_SCALER_BURST_PER_PLANE \
+	       | R128_SCALER_DOUBLE_BUFFER \
+	       | R128_SCALER_ENABLE);
+    else
+       OUTREG(R128_OV0_SCALE_CNTL, R128_SCALER_PIX_EXPAND \
+	       | R128_SCALER_Y2R_TEMP \
+	       | R128_SCALER_SOURCE_VYUY422 \
+	       | R128_SCALER_SMART_SWITCH \
+	       | R128_SCALER_BURST_PER_PLANE \
+	       | R128_SCALER_DOUBLE_BUFFER \
+	       | R128_SCALER_ENABLE);
     OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
 }
 
@@ -697,8 +2181,20 @@ R128DisplayVideo420(
     int v_inc, h_inc, step_by, tmp, leftUV;
     int p1_h_accum_init, p23_h_accum_init;
     int p1_v_accum_init, p23_v_accum_init;
+    long counter;
 
-    v_inc = (src_h << 20) / drw_h;
+    /* Choose ecp_div setting. As the user may have switched resolution
+      we better do it again. */
+    if(info->ModeReg.dot_clock_freq < 12500) pPriv->ecp_div = 0;
+    	   else
+    if(info->ModeReg.dot_clock_freq < 25000) pPriv->ecp_div = 1;
+    	   else pPriv->ecp_div = 2;
+
+    OUTPLL(R128_VCLK_ECP_CNTL, (INPLL(pScrn, R128_VCLK_ECP_CNTL) & 0xfffffCff) | (pPriv->ecp_div << 8));
+
+    v_inc = (src_h << (20
+		+ ((pScrn->currentMode->Flags & V_INTERLACE)?1:0)
+		- ((pScrn->currentMode->Flags & V_DBLSCAN)?1:0))) / drw_h;
     h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w;
     step_by = 1;
 
@@ -730,13 +2226,17 @@ R128DisplayVideo420(
     leftUV = (left >> 17) & 15;
     left = (left >> 16) & 15;
 
-    OUTREG(R128_OV0_REG_LOAD_CNTL, 1);
-    while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3)));
+    R128WaitForFifo(pScrn, 2);
+    OUTREG(R128_OV0_REG_LOAD_CNTL, R128_REG_LD_CTL_LOCK);
+    R128WaitForIdle(pScrn);
+    counter=10000;
+    while(!(INREG(R128_OV0_REG_LOAD_CNTL) & R128_REG_LD_CTL_LOCK_READBACK) && (counter>=0))counter--;
+    if(counter<0)xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot lock overlay registers\n");
 
     OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16));
     OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8));
-    OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16));
-    OUTREG(R128_OV0_Y_X_END,   dstBox->x2 | (dstBox->y2 << 16));
+    OUTREG(R128_OV0_Y_X_START, dstBox->x1 | ((dstBox->y1*((pScrn->currentMode->Flags & V_DBLSCAN)?2:1)) << 16));
+    OUTREG(R128_OV0_Y_X_END,   dstBox->x2 | ((dstBox->y2*((pScrn->currentMode->Flags & V_DBLSCAN)?2:1)) << 16));
     OUTREG(R128_OV0_V_INC, v_inc);
     OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16));
     src_h = (src_h + 1) >> 1;
@@ -745,6 +2245,7 @@ R128DisplayVideo420(
     OUTREG(R128_OV0_VID_BUF_PITCH1_VALUE, pitch >> 1);
     OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16));
     width >>= 1;
+    R128WaitForFifo(pScrn,14);
     OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (leftUV << 16));
     OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (leftUV << 16));
     OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0);
@@ -754,7 +2255,16 @@ R128DisplayVideo420(
     OUTREG(R128_OV0_P23_V_ACCUM_INIT, p23_v_accum_init);
     OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
     OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
+/*  original magic 
     OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8A03);
+*/
+    OUTREG(R128_OV0_SCALE_CNTL, R128_SCALER_PIX_EXPAND \
+	       | R128_SCALER_Y2R_TEMP \
+	       | R128_SCALER_SOURCE_YUV12 \
+	       | R128_SCALER_SMART_SWITCH \
+	       | R128_SCALER_BURST_PER_PLANE \
+	       | R128_SCALER_DOUBLE_BUFFER \
+	       | R128_SCALER_ENABLE );
 
     OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
 }
@@ -777,13 +2287,15 @@ R128PutImage(
    R128InfoPtr info = R128PTR(pScrn);
    R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
    unsigned char *fb = (CARD8*)info->FB;
+   unsigned char *R128MMIO = info->MMIO;
    INT32 xa, xb, ya, yb;
-   int new_size, offset, s1offset, s2offset, s3offset;
+   int pitch, new_size, offset, s1offset, s2offset, s3offset;
    int srcPitch, srcPitch2, dstPitch;
    int d1line, d2line, d3line, d1offset, d2offset, d3offset;
    int top, left, npixels, nlines, bpp;
    BoxRec dstBox;
    CARD32 tmp;
+   int retcode;
 #if X_BYTE_ORDER == X_BIG_ENDIAN
    unsigned char *R128MMIO = info->MMIO;
    CARD32 config_cntl = INREG(R128_CONFIG_CNTL);
@@ -793,6 +2305,18 @@ R128PutImage(
 	  ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP));
 #endif
 
+   info->accel->Sync(pScrn);
+
+   /* if capture was active shutdown it first */
+   if(pPriv->video_stream_active)
+   {
+	R128WaitForFifo(pScrn, 8); 
+        OUTPLL(R128_FCP_CNTL, 0x404);
+        OUTREG(R128_CAP0_TRIG_CNTL, 0x0);
+	pPriv->video_stream_active = FALSE;
+        R128MuteAudio(pPriv, TRUE);
+   }   
+
    /*
     * s1offset, s2offset, s3offset - byte offsets to the Y, U and V planes
     *                                of the source.
@@ -824,9 +2348,11 @@ R128PutImage(
    dstBox.y1 = drw_y;
    dstBox.y2 = drw_y + drw_h;
 
-   if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb,
-			     clipBoxes, width, height))
-	return Success;
+   if(!R128ClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height))
+   {
+	retcode = Success;
+        goto done;
+   }
 
    dstBox.x1 -= pScrn->frameX0;
    dstBox.x2 -= pScrn->frameX0;
@@ -834,6 +2360,13 @@ R128PutImage(
    dstBox.y2 -= pScrn->frameY0;
 
    bpp = pScrn->bitsPerPixel >> 3;
+   pitch = bpp * pScrn->displayWidth;
+
+   R128WaitForFifo(pScrn, 4);
+   OUTREG(R128_OV0_DEINTERLACE_PATTERN, 0xAAAAA);
+   OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0);
+   OUTREG(R128_VIDEOMUX_CNTL, (INREG(R128_VIDEOMUX_CNTL)& ~3));
+   OUTREG(R128_CAP0_CONFIG, 0);
 
    switch(id) {
    case FOURCC_YV12:
@@ -862,7 +2395,8 @@ R128PutImage(
    if(!(pPriv->linear = R128AllocateMemory(pScrn, pPriv->linear,
 		pPriv->doubleBuffer ? (new_size << 1) : new_size)))
    {
-	return BadAlloc;
+	retcode = BadAlloc;
+        goto done;
    }
 
    pPriv->currentBuffer ^= 1;
@@ -876,6 +2410,8 @@ R128PutImage(
    if(pPriv->doubleBuffer)
 	offset += pPriv->currentBuffer * new_size * bpp;
 
+   
+   info->accel->Sync(pScrn);
    switch(id) {
     case FOURCC_YV12:
     case FOURCC_I420:
@@ -900,7 +2436,7 @@ R128PutImage(
 	}
 
 	nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
-	R128CopyData420(info, buf + s1offset, buf + s2offset, buf + s3offset,
+	R128CopyData420(pScrn, info, buf + s1offset, buf + s2offset, buf + s3offset,
 			fb + d1offset, fb + d2offset, fb + d3offset,
 			srcPitch, srcPitch2, dstPitch, nlines, npixels);
 	break;
@@ -916,7 +2452,7 @@ R128PutImage(
 	d3offset = 0;
 	s1offset += (top * srcPitch) + left;
 	nlines = ((yb + 0xffff) >> 16) - top;
-	R128CopyData422(info, buf + s1offset, fb + d1offset,
+	R128CopyData422(pScrn, info, buf + s1offset, fb + d1offset,
 			srcPitch, dstPitch, nlines, npixels);
 	break;
     }
@@ -930,9 +2466,13 @@ R128PutImage(
     if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
 	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
 	/* draw these */
-	xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+	if(pPriv->autopaint_colorkey)(*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy,
+					(CARD32)~0,
+					REGION_NUM_RECTS(clipBoxes),
+					REGION_RECTS(clipBoxes));
     }
 
+    info->accel->Sync(pScrn);
 
     switch(id) {
      case FOURCC_YV12:
@@ -944,18 +2484,26 @@ R128PutImage(
      case FOURCC_UYVY:
      case FOURCC_YUY2:
      default:
-	R128DisplayVideo422(pScrn, id, offset + d1line, width, height, dstPitch,
+	R128DisplayVideo422(pScrn, id, offset + d1line, offset + d1line, width, height, dstPitch,
 		     xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
 	break;
     }
 
+    if (info->cursor_start && !(pPriv->videoStatus & CLIENT_VIDEO_ON))
+	xf86ForceHWCursor (pScrn->pScreen, TRUE);
     pPriv->videoStatus = CLIENT_VIDEO_ON;
 
     info->VideoTimerCallback = R128VideoTimerCallback;
+    retcode = Success;
 
-    return Success;
-}
+done:
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+    /* restore byte swapping */
+    OUTREG(R128_CONFIG_CNTL, config_cntl);
+#endif
 
+    return retcode;
+}
 
 static int
 R128QueryImageAttributes(
@@ -999,6 +2547,518 @@ R128QueryImageAttributes(
     return size;
 }
 
+/* this routine is here because different mach64/r128 boards use
+   different methods of muting. And because sometimes there is
+   no good way to autodetect this (besides knowing which board
+   we have) */
+
+
+
+void R128_board_setmisc(R128PortPrivPtr pPriv)
+{
+    CARD8 a;
+    I2CDevRec d;
+
+    d.DevName = "temporary";
+    d.pI2CBus = pPriv->i2c;
+    d.NextDev = NULL;
+    d.StartTimeout = pPriv->i2c->StartTimeout;
+    d.BitTimeout = pPriv->i2c->BitTimeout;
+    d.AcknTimeout = pPriv->i2c->AcknTimeout;
+    d.ByteTimeout = pPriv->i2c->ByteTimeout;
+
+    if(pPriv->addon_board)
+    {
+       a = 0x2F;
+       if(!pPriv->mute && pPriv->video_stream_active) a |= 0x50;
+       if(((pPriv->encoding-1) % 3) != 1) a |= 0x40; 
+       d.SlaveAddr = pPriv->board_control;
+       I2C_WriteRead(&d, &a, 1, NULL, 0);    
+    }
+
+    if(pPriv->tda8425 != NULL)
+    {
+       pPriv->tda8425->v_left = (pPriv->mute ? 0xc0 : 0xff);
+       pPriv->tda8425->v_right = (pPriv->mute ? 0xc0 : 0xff);
+       if(((pPriv->encoding-1) % 3) != 1) pPriv->tda8425->mux = 0;
+                         else pPriv->tda8425->mux = 1; /* this is a fancy way
+                                                    to choose all encodings
+						    except tuner ones */ 
+       xf86_tda8425_setaudio(pPriv->tda8425);
+    }
+
+    /* Adjust PAL/SECAM constants for FI1216MF tuner */
+    if((((pPriv->board_info & 0xf)==5) ||
+       ((pPriv->board_info & 0xf)==11) ||
+       ((pPriv->board_info & 0xf)==14))&& (pPriv->fi1236!=NULL))
+    {
+        if((pPriv->encoding>=1)&&(pPriv->encoding<=3)) /*PAL*/
+	{
+    	   pPriv->fi1236->parm.band_low = 0xA1;
+	   pPriv->fi1236->parm.band_mid = 0x91;
+	   pPriv->fi1236->parm.band_high = 0x31;
+	}
+        if((pPriv->encoding>=7)&&(pPriv->encoding<=9)) /*SECAM*/
+	{
+    	   pPriv->fi1236->parm.band_low = 0xA3;
+	   pPriv->fi1236->parm.band_mid = 0x93;
+	   pPriv->fi1236->parm.band_high = 0x33;
+	}
+    }
+
+    R128MuteAudio(pPriv, pPriv->mute);
+}
+
+
+void R128_RT_SetEncoding(R128PortPrivPtr pPriv)
+{
+switch(pPriv->encoding){
+	case 1:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL);
+		xf86_RT_SetConnector(pPriv->theatre,DEC_COMPOSITE, 0);
+		pPriv->v=24;
+		break;
+	case 2:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL);
+		xf86_RT_SetConnector(pPriv->theatre,DEC_TUNER,0);
+		pPriv->v=24;
+		break;
+	case 3:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL);
+		xf86_RT_SetConnector(pPriv->theatre,DEC_SVIDEO,0);
+		pPriv->v=24;
+		break;
+	case 4:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE);
+		xf86_RT_SetConnector(pPriv->theatre, DEC_COMPOSITE,0);
+		pPriv->v=23;
+		break;
+	case 5:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE);
+		xf86_RT_SetConnector(pPriv->theatre, DEC_TUNER, 0);
+		pPriv->v=23;
+		break;
+	case 6:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_NTSC | extNONE);
+		xf86_RT_SetConnector(pPriv->theatre, DEC_SVIDEO, 0);
+		pPriv->v=23;
+		break;
+	case 7:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE);
+		xf86_RT_SetConnector(pPriv->theatre, DEC_COMPOSITE, 0);
+		pPriv->v=25;
+		break;
+	case 8:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE);
+		xf86_RT_SetConnector(pPriv->theatre, DEC_TUNER, 0);
+		pPriv->v=25;
+		break;
+	case 9:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_SECAM | extNONE);
+		xf86_RT_SetConnector(pPriv->theatre, DEC_SVIDEO, 0);
+		pPriv->v=25;
+		break;
+	case 10:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60);
+		xf86_RT_SetConnector(pPriv->theatre,DEC_COMPOSITE, 0);
+		pPriv->v=24;
+		break;
+	case 11:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60);
+		xf86_RT_SetConnector(pPriv->theatre,DEC_TUNER,0);
+		pPriv->v=24;
+		break;
+	case 12:
+		xf86_RT_SetStandard(pPriv->theatre,DEC_PAL | extPAL_60);
+		xf86_RT_SetConnector(pPriv->theatre,DEC_SVIDEO,0);
+		pPriv->v=24;
+		break;
+	default:
+	        pPriv->v=0;
+		return;
+	}	
+}
+
+void R128_MSP_SetEncoding(R128PortPrivPtr pPriv)
+{
+xf86_MSP3430SetVolume(pPriv->msp3430, MSP3430_FAST_MUTE);
+switch(pPriv->encoding){
+	case 1:
+		pPriv->msp3430->standard = MSP3430_PAL;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
+		break;
+	case 2:
+		pPriv->msp3430->standard = MSP3430_PAL;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
+		break;
+	case 3:
+		pPriv->msp3430->standard = MSP3430_PAL;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
+		break;
+	case 4:
+		pPriv->msp3430->standard = MSP3430_NTSC;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
+		break;
+	case 5:
+		pPriv->msp3430->standard = MSP3430_NTSC;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
+		break;
+	case 6:
+		pPriv->msp3430->standard = MSP3430_NTSC;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
+		break;
+	case 7:
+		pPriv->msp3430->standard = MSP3430_SECAM;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
+		break;
+	case 8:
+		pPriv->msp3430->standard = MSP3430_SECAM;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
+		break;
+	case 9:
+		pPriv->msp3430->standard = MSP3430_SECAM;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
+		break;
+	case 10:
+		pPriv->msp3430->standard = MSP3430_SECAM;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_3;
+		break;
+	case 11:
+		pPriv->msp3430->standard = MSP3430_SECAM;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
+		break;
+	case 12:
+		pPriv->msp3430->standard = MSP3430_SECAM;
+		pPriv->msp3430->connector = MSP3430_CONNECTOR_2;
+		break;
+	default:
+		return;
+	}	
+xf86_InitMSP3430(pPriv->msp3430);
+xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume));
+}
+
+void R128_BT_SetEncoding(R128PortPrivPtr pPriv)
+{
+switch(pPriv->encoding){
+	case 1:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX2);
+		pPriv->v=24;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_PAL);
+		break;
+	case 2:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX0);
+		pPriv->v=24;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_PAL);
+		break;
+	case 3:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX1);
+		pPriv->v=24;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_PAL);
+		break;
+	case 4:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX2);
+		pPriv->v=23;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_NTSC);
+		break;
+	case 5:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX0);
+		pPriv->v=23;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_NTSC);
+		break;
+	case 6:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX1);
+		pPriv->v=23;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_NTSC);
+		break;
+	case 7:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX2);
+		pPriv->v=25;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_SECAM);
+		break;
+	case 8:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX0);
+		pPriv->v=25;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_SECAM);
+		break;
+	case 9:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX1);
+		pPriv->v=25;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_SECAM);
+		break;
+       case 13:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX2);
+                pPriv->v=23;
+                xf86_bt829_SetFormat(pPriv->bt829, BT829_PAL_M);
+                break;
+       case 14:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX0);
+                pPriv->v=23;
+                xf86_bt829_SetFormat(pPriv->bt829, BT829_PAL_M);
+                break;
+       case 15:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX1);
+                pPriv->v=23;
+                xf86_bt829_SetFormat(pPriv->bt829, BT829_PAL_M);
+                break;
+	default:
+                xf86_bt829_SetMux(pPriv->bt829, BT829_MUX2);
+		pPriv->v=23;
+	        xf86_bt829_SetFormat(pPriv->bt829, BT829_NTSC);
+		return;
+	}	
+if(pPriv->tda9850!=NULL){
+	pPriv->tda9850->mux = pPriv->bt829->mux;
+	xf86_tda9850_setaudio(pPriv->tda9850);
+	}
+}
+
+/* capture config constants */
+#define BUF_TYPE_FIELD		0
+#define BUF_TYPE_ALTERNATING	1
+#define BUF_TYPE_FRAME		2
+
+
+#define BUF_MODE_SINGLE		0
+#define BUF_MODE_DOUBLE		1
+#define BUF_MODE_TRIPLE		2
+/* CAP0_CONFIG values */
+
+
+/* Older, original magic.. let's leave these for reference 
+#define ENABLE_R128_CAPTURE_WEAVE (0x1C000005L \
+		| (BUF_MODE_SINGLE <<7) \
+		| (BUF_TYPE_FRAME << 4) \
+		| ( (pPriv->theatre !=NULL)?(1L<<23):0) \
+		| (1<<29)) 
+#define ENABLE_R128_CAPTURE_BOB (0x1C000005L \
+		| (BUF_MODE_SINGLE <<7) \
+		| (BUF_TYPE_ALTERNATING << 4) \
+		| ( (pPriv->theatre !=NULL)?(1L<<23):0) \
+		| (0<<15) \
+		| (1<<29)) 
+
+*/
+
+#define ENABLE_R128_CAPTURE_WEAVE (R128_CAP0_CONFIG_CONTINUOS \
+			| (BUF_MODE_SINGLE <<7) \
+			| (BUF_TYPE_FRAME << 4) \
+			| ( (pPriv->theatre !=NULL) ? \
+				(R128_CAP0_CONFIG_FORMAT_CCIR656): \
+				(R128_CAP0_CONFIG_FORMAT_BROOKTREE)) \
+			| R128_CAP0_CONFIG_HORZ_DECIMATOR \
+			| R128_CAP0_CONFIG_VIDEO_IN_VYUY422)
+
+#define ENABLE_R128_CAPTURE_BOB (R128_CAP0_CONFIG_CONTINUOS \
+			| (BUF_MODE_SINGLE <<7)  \
+			| (BUF_TYPE_ALTERNATING << 4) \
+			| ( (pPriv->theatre !=NULL) ? \
+				(R128_CAP0_CONFIG_FORMAT_CCIR656): \
+				(R128_CAP0_CONFIG_FORMAT_BROOKTREE)) \
+			| R128_CAP0_CONFIG_HORZ_DECIMATOR \
+			| R128_CAP0_CONFIG_VIDEO_IN_VYUY422)
+
+static int
+R128PutVideo(
+  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
+){
+   R128InfoPtr info = R128PTR(pScrn);
+   R128PortPrivPtr pPriv = (R128PortPrivPtr)data;
+   unsigned char *R128MMIO = info->MMIO;
+   INT32 xa, xb, ya, yb, top;
+   int pitch, new_size, offset1, offset2, s2offset, s3offset;
+   int srcPitch, srcPitch2, dstPitch;
+   int bpp;
+   BoxRec dstBox;
+   CARD32 id;
+   int width, height;
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PutVideo\n");
+   info->accel->Sync(pScrn);
+   /*
+    * s2offset, s3offset - byte offsets into U and V plane of the
+    *                      source where copying starts.  Y plane is
+    *                      done by editing "buf".
+    *
+    * offset - byte offset to the first line of the destination.
+    *
+    * dst_start - byte address to the first displayed pel.
+    *
+    */
+
+   /* make the compiler happy */
+   s2offset = s3offset = srcPitch2 = 0;
+
+   if(src_w > (drw_w << 4))
+	drw_w = src_w >> 4;
+   if(src_h > (drw_h << 4))
+	drw_h = src_h >> 4;
+
+   /* Clip */
+   xa = src_x;
+   xb = src_x + src_w;
+   ya = src_y;
+   yb = 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(pPriv->theatre != NULL)
+   {
+      width = InputVideoEncodings[pPriv->encoding].width;
+      height = InputVideoEncodings[pPriv->encoding].height; 
+   } else 
+   if(pPriv->bt829 != NULL)
+   {
+      width = InputVideoEncodings[pPriv->encoding].width;
+      height = InputVideoEncodings[pPriv->encoding].height;
+   } else 
+      return FALSE;
+        
+   if(!R128ClipVideo(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height))
+	return Success;
+
+   dstBox.x1 -= pScrn->frameX0;
+   dstBox.x2 -= pScrn->frameX0;
+   dstBox.y1 -= pScrn->frameY0;
+   dstBox.y2 -= pScrn->frameY0;
+
+   bpp = pScrn->bitsPerPixel >> 3;
+   pitch = bpp * pScrn->displayWidth;
+
+   id = FOURCC_YUY2;
+
+   top = ya>>16;
+
+   switch(id) {
+   case FOURCC_YV12:
+   case FOURCC_I420:
+   	top &= ~1;
+	dstPitch = ((width << 1) + 15) & ~15;
+	new_size = ((dstPitch * height) + bpp - 1) / bpp;
+	srcPitch = (width + 3) & ~3;
+	s2offset = srcPitch * height;
+	srcPitch2 = ((width >> 1) + 3) & ~3;
+	s3offset = (srcPitch2 * (height >> 1)) + s2offset;
+	break;
+   case FOURCC_UYVY:
+   case FOURCC_YUY2:
+   default:
+	dstPitch = ((width << 1) + 15) & ~15;
+	new_size = ((dstPitch * height) + bpp - 1) / bpp;
+	srcPitch = (width << 1);
+	break;
+   }
+
+   new_size += 0x1f;  /* for aligning */
+
+   if(!(pPriv->linear = R128AllocateMemory(pScrn, pPriv->linear, new_size*2)))
+   {
+	return BadAlloc;
+   }
+
+
+   R128WaitForFifo(pScrn, 14);
+
+   offset1 = (pPriv->linear->offset*bpp+0xf) & (~0xf);
+   offset2 = ((pPriv->linear->offset+new_size)*bpp + 0x1f) & (~0xf);
+   
+   OUTREG(R128_CAP0_BUF0_OFFSET, offset1);
+   OUTREG(R128_CAP0_BUF0_EVEN_OFFSET, offset2);
+   OUTREG(R128_CAP0_ONESHOT_BUF_OFFSET, offset1);
+   OUTREG(R128_CAP0_BUF1_OFFSET, offset1);
+   OUTREG(R128_CAP0_BUF1_EVEN_OFFSET, offset2);
+   
+   OUTREG(R128_CAP0_BUF_PITCH, width*2);
+   OUTREG(R128_CAP0_H_WINDOW, (2*width)<<16);
+   OUTREG(R128_CAP0_V_WINDOW, (((height)+pPriv->v-1)<<16)|(pPriv->v));
+   OUTREG(R128_OV0_AUTO_FLIP_CNTL, R128_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
+   OUTREG(R128_CAP0_CONFIG, ENABLE_R128_CAPTURE_BOB);
+   OUTREG(R128_CAP0_DEBUG, 0);
+   
+   OUTREG(R128_CAP0_DWNSC_XRATIO, 0x10001000);
+   OUTREG(R128_CAP0_XSHARPNESS, 0);
+   OUTREG(R128_TEST_DEBUG_CNTL, 0);
+   
+   if(! pPriv->video_stream_active){
+
+   /* activate capture unit */
+   R128WaitForFifo(pScrn, 4);
+   
+   /* undocumented magic, note: these work.. unlike the values in ATI kit,
+      ATI has been notified.. */
+   OUTREG(R128_VIDEOMUX_CNTL, (INREG(R128_VIDEOMUX_CNTL)| 2 |1));
+
+   OUTREG(R128_CAP0_PORT_MODE_CNTL, (pPriv->theatre!=NULL)? 1: 0);
+   
+   OUTPLL(R128_FCP_CNTL, 0x101);
+
+   OUTREG(R128_CAP0_TRIG_CNTL, R128_CAP0_TRIG_CNTL_TRIGGER_SET | 
+                               R128_CAP0_TRIG_CNTL_CAPTURE_EN);
+   
+   
+   if(pPriv->theatre != NULL) 
+   {
+      xf86_RT_SetInterlace(pPriv->theatre, 1);
+      R128_RT_SetEncoding(pPriv);
+      xf86_RT_SetOutputVideoSize(pPriv->theatre, width, height*2, 0, 0);   
+   }
+   
+   if(pPriv->bt829 != NULL) 
+   {
+      R128_BT_SetEncoding(pPriv);
+      xf86_bt829_SetCaptSize(pPriv->bt829, width, height*2);
+   }
+   
+   if(pPriv->i2c!=NULL) R128_board_setmisc(pPriv);
+   if(pPriv->msp3430 != NULL) R128_MSP_SetEncoding(pPriv);
+   if(pPriv->tda9850 != NULL)
+   { 
+      xf86_tda9850_mute(pPriv->tda9850, pPriv->mute);
+   }
+   }
+    /* update cliplist */
+    if(!RegionsEqual(&pPriv->clip, clipBoxes)) {
+	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+	/* draw these */
+	if(pPriv->autopaint_colorkey)(*info->accel->FillSolidRects)(pScrn, pPriv->colorKey, GXcopy, ~0,
+					REGION_NUM_RECTS(clipBoxes),
+					REGION_RECTS(clipBoxes));
+    }
+
+    pPriv->doubleBuffer = 1;
+    R128DisplayVideo422(pScrn, id, offset1 + top*srcPitch, offset2 + top*srcPitch, width, height, dstPitch,
+		     xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h);
+
+    R128WaitForIdle(pScrn);
+
+    OUTREG(R128_OV0_REG_LOAD_CNTL, R128_REG_LD_CTL_LOCK);
+    while(!(INREG(R128_OV0_REG_LOAD_CNTL) &  R128_REG_LD_CTL_LOCK_READBACK));
+
+    OUTREG(R128_OV0_AUTO_FLIP_CNTL, R128_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD|R128_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN);
+
+    OUTREG (R128_OV0_AUTO_FLIP_CNTL, (INREG (R128_OV0_AUTO_FLIP_CNTL) ^ R128_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE  ));
+    OUTREG (R128_OV0_AUTO_FLIP_CNTL, (INREG (R128_OV0_AUTO_FLIP_CNTL) ^ R128_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE  ));
+
+    OUTREG(R128_OV0_DEINTERLACE_PATTERN, 0xAAAAA);
+
+    OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
+
+    pPriv->videoStatus = CLIENT_VIDEO_ON;
+    pPriv->video_stream_active = TRUE;
+
+    info->VideoTimerCallback = R128VideoTimerCallback;
+
+    return Success;
+}
+
 static void
 R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now)
 {
@@ -1010,6 +3070,8 @@ R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now)
 	    if(pPriv->offTime < now) {
 		unsigned char *R128MMIO = info->MMIO;
 		OUTREG(R128_OV0_SCALE_CNTL, 0);
+		if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON)
+		    xf86ForceHWCursor (pScrn->pScreen, FALSE);
 		pPriv->videoStatus = FREE_TIMER;
 		pPriv->freeTime = now + FREE_DELAY;
 	    }
@@ -1019,6 +3081,8 @@ R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now)
 		   xf86FreeOffscreenLinear(pPriv->linear);
 		   pPriv->linear = NULL;
 		}
+		if (info->cursor_start && pPriv->videoStatus & CLIENT_VIDEO_ON)
+		    xf86ForceHWCursor (pScrn->pScreen, FALSE);
 		pPriv->videoStatus = 0;
 		info->VideoTimerCallback = NULL;
 	    }
@@ -1026,3 +3090,6 @@ R128VideoTimerCallback(ScrnInfoPtr pScrn, Time now)
     } else  /* shouldn't get here */
 	info->VideoTimerCallback = NULL;
 }
+
+
+#endif  /* !XvExtension */
openSUSE Build Service is sponsored by