[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#167910: [savage] patch to upgrade driver to version 25t



Package: xserver-xfree86
Version: 4.2.1-3cjh1
Severity: normal
Tags: patch

Hi, here's the patch I promised on IRC to upgrade the Savage driver to the
latest drop from http://www.probo.com/timr/savage40.html.  I made this and
tested for about 2 weeks on 4.2.1-2 and have run -3 over the last 2 days
without problems.  Suggested changelog entry:

 * patch #079: updated savage driver to Tim Roberts's 1.1.25t of 2002-09-11
   - Fix xscreensaver blaster, critical hack hangs (Closes: #112703, #140451)
   - Fix hang at beginning of xine
   - Support xgamma extension
   - Fixes for hardware cursor and tiled patterns

There are two other reports which are possibly related, but I don't know if
it will fix them: #110974 and #115223

The patchfile replaces the previous 079 in the package.

Chris
This patch generated from http://www.probo.com/timr/savage40.html, version 1.1.25t (2002-09-11)

diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_accel.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_accel.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_accel.c	2001-12-13 19:01:50.000000000 +0100
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_accel.c	2002-09-11 23:22:22.000000000 +0200
@@ -399,9 +399,11 @@
     xaaptr->SetClippingRectangle = SavageSetClippingRectangle;
     xaaptr->DisableClipping = SavageDisableClipping;
     xaaptr->ClippingFlags = 0
+#if 0
 	| HARDWARE_CLIP_SOLID_FILL 
 	| HARDWARE_CLIP_SOLID_LINE
 	| HARDWARE_CLIP_DASHED_LINE
+#endif
 	| HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY
 	| HARDWARE_CLIP_MONO_8x8_FILL
 	| HARDWARE_CLIP_COLOR_8x8_FILL
@@ -444,16 +446,31 @@
 
     /* Color 8x8 pattern fills */
 
+    /*
+     * With the exception of the Savage3D and Savage4, all of the Savage
+     * chips require that bitmap descriptors have a stride that is a
+     * multiple of 16 pixels.  This includes any descriptor used for
+     * color pattern fills, which COMPLETELY screws the XAA 8x8 color 
+     * pattern support.
+     *
+     * We could double the width ourselves into a reserved frame buffer
+     * section, but since I went 18 months with only ONE report of this
+     * error, it seems hardly worth the trouble.
+     */
+
 #if 1
-    xaaptr->SetupForColor8x8PatternFill =
-            SavageSetupForColor8x8PatternFill;
-    xaaptr->SubsequentColor8x8PatternFillRect =
-            SavageSubsequentColor8x8PatternFillRect;
-    xaaptr->Color8x8PatternFillFlags = 0
-	| NO_TRANSPARENCY
-    	| HARDWARE_PATTERN_PROGRAMMED_BITS
-	| HARDWARE_PATTERN_PROGRAMMED_ORIGIN
-	;
+    if( (psav->Chipset == S3_SAVAGE3D) || (psav->Chipset == S3_SAVAGE4) )
+    {
+	xaaptr->SetupForColor8x8PatternFill =
+		SavageSetupForColor8x8PatternFill;
+	xaaptr->SubsequentColor8x8PatternFillRect =
+		SavageSubsequentColor8x8PatternFillRect;
+	xaaptr->Color8x8PatternFillFlags = 0
+	    | NO_TRANSPARENCY
+	    | HARDWARE_PATTERN_PROGRAMMED_BITS
+	    | HARDWARE_PATTERN_PROGRAMMED_ORIGIN
+	    ;
+    }
 #endif
 
     /* Solid lines */
@@ -467,7 +484,7 @@
     xaaptr->SubsequentSolidFillTrap = SavageSubsequentSolidFillTrap; 
 #endif
 
-    xaaptr->SolidBresenhamLineErrorTermBits = 16;
+    xaaptr->SolidBresenhamLineErrorTermBits = 14;
 #endif
 
     /* ImageWrite */
@@ -988,9 +1005,9 @@
     pat_offset = (int) (patternx * psav->Bpp + patterny * psav->Bpl);
 
     cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
-        | BCI_CMD_DEST_GBD | BCI_CMD_PAT_SBD_COLOR_NEW;
+        | BCI_CMD_DEST_GBD | BCI_CMD_PAT_PBD_COLOR_NEW;
         
-    mix = SavageHelpSolidROP( pScrn, &trans_col, planemask, &rop );
+    mix = XAAHelpSolidROP( pScrn, &trans_col, planemask, &rop );
 
     BCI_CMD_SET_ROP(cmd, rop);
     bd = BCI_BD_BW_DISABLE;
@@ -1020,10 +1037,11 @@
     if( !w || !h )
 	return;
 
-    psav->WaitQueue(psav,5);
+    psav->WaitQueue(psav,6);
     BCI_SEND(psav->SavedBciCmd);
     BCI_SEND(psav->SavedSbdOffset);
     BCI_SEND(psav->SavedSbd);
+    BCI_SEND(BCI_X_Y(patternx,patterny));
     BCI_SEND(BCI_X_Y(x, y));
     BCI_SEND(BCI_W_H(w, h));
 }
@@ -1048,8 +1066,8 @@
     cmd |= BCI_CMD_LINE_LAST_PIXEL;
 
 #ifdef DEBUG_EXTRA
-    ErrorF("BresenhamLine, (%4d,%4d), len %4d, oct %d, err %4d,%4d, clr %08x\n",
-        x1, y1, length, octant, e2, e1, psav->SavedFgColor );
+    ErrorF("BresenhamLine, (%4d,%4d), len %4d, oct %d, err %4d,%4d,%4d clr %08x\n",
+        x1, y1, length, octant, e1, e2, err, psav->SavedFgColor );
 #endif
 
     psav->WaitQueue(psav, 5 );
@@ -1059,7 +1077,7 @@
     BCI_SEND(BCI_LINE_X_Y(x1, y1));
     BCI_SEND(BCI_LINE_STEPS(e2-e1, e2));
     BCI_SEND(BCI_LINE_MISC(length, 
-    			   !!(octant & YMAJOR),
+    			   (octant & YMAJOR),
 			   !(octant & XDECREASING),
 			   !(octant & YDECREASING),
 			   e2+err));
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_bci.h xc/programs/Xserver/hw/xfree86/drivers/savage/savage_bci.h
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_bci.h	2001-10-01 15:44:09.000000000 +0200
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_bci.h	2002-09-11 01:49:20.000000000 +0200
@@ -87,9 +87,11 @@
 #define BCI_LINE_X_Y(x, y)           (((y) << 16) | ((x) & 0xFFFF))
 #define BCI_LINE_STEPS(diag, axi)    (((axi) << 16) | ((diag) & 0xFFFF))
 #define BCI_LINE_MISC(maj, ym, xp, yp, err) \
-(((maj) & 0xFFF) | (((ym) & 1) << 13) | \
-(((xp) & 1) << 14) | (((yp) & 1) << 15) | \
-((err) << 16))
+	(((maj) & 0x1FFF) | \
+	((ym) ? 1<<13 : 0) | \
+	((xp) ? 1<<14 : 0) | \
+	((yp) ? 1<<15 : 0) | \
+	((err) << 16))
 
 
 #endif /* _S3BCI_H_ */
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_cursor.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_cursor.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_cursor.c	2001-11-02 17:24:51.000000000 +0100
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_cursor.c	2002-09-11 19:55:12.000000000 +0200
@@ -22,6 +22,8 @@
 
 #define inCRReg(reg) (VGAHWPTR(pScrn))->readCrtc( VGAHWPTR(pScrn), reg )
 #define outCRReg(reg, val) (VGAHWPTR(pScrn))->writeCrtc( VGAHWPTR(pScrn), reg, val )
+#define inSRReg(reg) (VGAHWPTR(pScrn))->readSeq( VGAHWPTR(pScrn), reg )
+#define outSRReg(reg, val) (VGAHWPTR(pScrn))->writeSeq( VGAHWPTR(pScrn), reg, val )
 #define inStatus1() (VGAHWPTR(pScrn))->readST01( VGAHWPTR(pScrn) )
 
 /* 
@@ -67,7 +69,7 @@
 
     if(
         ((psav->Chipset != S3_SAVAGE4) 
-       && (inCRReg(0x18) & 0x80) && (inCRReg(0x15) & 0x50) )
+       && (inSRReg(0x18) & 0x80) && (inSRReg(0x15) & 0x50) )
 	||
 	S3_SAVAGE_MOBILE_SERIES(psav->Chipset)
       )
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_dga.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_dga.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_dga.c	2001-05-19 01:35:32.000000000 +0200
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_dga.c	2002-03-08 19:23:04.000000000 +0100
@@ -155,7 +155,8 @@
 	);
 
 	if(oneMore) { /* first one is narrow width */
-	    mode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L;
+	    /* Force stride to multiple of 16 pixels. */
+	    mode->bytesPerScanline = ((pMode->HDisplay + 15) & ~15) * Bpp;
 	    mode->imageWidth = pMode->HDisplay;
 	    mode->imageHeight =  pMode->VDisplay;
 	    mode->pixmapWidth = mode->imageWidth;
@@ -172,7 +173,7 @@
  
 	    goto SECOND_PASS;
 	} else {
-	    mode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
+	    mode->bytesPerScanline = ((pScrn->displayWidth + 15) & ~15) * Bpp;
 	    mode->imageWidth = pScrn->displayWidth;
 	    mode->imageHeight = psav->videoRambytes / mode->bytesPerScanline;
 	    mode->pixmapWidth = mode->imageWidth;
@@ -260,6 +261,7 @@
     static int OldDisplayWidth[MAXSCREENS];
     static int OldBitsPerPixel[MAXSCREENS];
     static int OldDepth[MAXSCREENS];
+    static DisplayModePtr OldMode[MAXSCREENS];
     int index = pScrn->pScreen->myNum;
     SavagePtr psav = SAVPTR(pScrn);
 
@@ -269,6 +271,7 @@
 	pScrn->displayWidth = OldDisplayWidth[index];
 	pScrn->bitsPerPixel = OldBitsPerPixel[index];
 	pScrn->depth = OldDepth[index];
+	pScrn->currentMode = OldMode[index];
 
 	SavageSwitchMode(index, pScrn->currentMode, 0);
 	if( psav->hwcursor )
@@ -293,6 +296,7 @@
 	    OldDisplayWidth[index] = pScrn->displayWidth;
 	    OldBitsPerPixel[index] = pScrn->bitsPerPixel;
 	    OldDepth[index] = pScrn->depth;
+	    OldMode[index] = pScrn->currentMode;
 
 	    psav->DGAactive = TRUE;
 	}
@@ -302,7 +306,7 @@
 	pScrn->displayWidth = pMode->bytesPerScanline / 
 	    (pMode->bitsPerPixel >> 3);
 
-	psav->UseBIOS = FALSE;
+/*	psav->UseBIOS = FALSE; */
 	SavageSwitchMode(index, pMode->mode, 0);
 	psav->UseBIOS = holdBIOS;
     }
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_driver.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_driver.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_driver.c	2001-11-02 17:24:51.000000000 +0100
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_driver.c	2002-09-11 23:59:57.000000000 +0200
@@ -74,16 +74,18 @@
 static Bool SavageDDC1(int scrnIndex);
 static unsigned int SavageDDC1Read(ScrnInfoPtr pScrn);
 static void SavageProbeDDC(ScrnInfoPtr pScrn, int index);
+static void SavageGetTvMaxSize(SavagePtr psav);
+static Bool SavagePanningCheck(ScrnInfoPtr pScrn);
 
 extern ScrnInfoPtr gpScrn;
 
 #define iabs(a)	((int)(a)>0?(a):(-(a)))
 
 #define DRIVER_NAME	"savage"
-#define DRIVER_VERSION	"1.1.20"
+#define DRIVER_VERSION	"1.1.25t"
 #define VERSION_MAJOR	1
 #define VERSION_MINOR	1
-#define PATCHLEVEL	20
+#define PATCHLEVEL	25
 #define SAVAGE_VERSION	((VERSION_MAJOR << 24) | \
 			 (VERSION_MINOR << 16) | \
 			 PATCHLEVEL)
@@ -132,6 +134,8 @@
     { PCI_CHIP_SUPSAV_IX64DDR,	"SuperSavage/IX 64" },
     { PCI_CHIP_SUPSAV_IXCSDR,	"SuperSavage/IXC 64" },
     { PCI_CHIP_SUPSAV_IXCDDR,	"SuperSavage/IXC 64" },
+    { PCI_CHIP_PROSAVAGE_DDR,	"ProSavage DDR" },
+    { PCI_CHIP_PROSAVAGE_DDRK,	"ProSavage DDR-K" },
     { -1,			NULL }
 };
 
@@ -160,6 +164,8 @@
     { S3_PROSAVAGE,	PCI_CHIP_PROSAVAGE_KM,	RES_SHARED_VGA },
     { S3_PROSAVAGE,	PCI_CHIP_S3TWISTER_P,	RES_SHARED_VGA },
     { S3_PROSAVAGE,	PCI_CHIP_S3TWISTER_K,	RES_SHARED_VGA },
+    { S3_PROSAVAGE,	PCI_CHIP_PROSAVAGE_DDR,	RES_SHARED_VGA },
+    { S3_PROSAVAGE,	PCI_CHIP_PROSAVAGE_DDRK,	RES_SHARED_VGA },
     { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_MX128,	RES_SHARED_VGA },
     { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_MX64,	RES_SHARED_VGA },
     { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_MX64C,	RES_SHARED_VGA },
@@ -187,7 +193,10 @@
     OPTION_ROTATE,
     OPTION_USEBIOS,
     OPTION_SHADOW_STATUS,
-    OPTION_VIDEORAM
+    OPTION_VIDEORAM,
+    OPTION_CRT_ONLY,
+    OPTION_TV_ON,
+    OPTION_TV_PAL
 } SavageOpts;
 
 
@@ -202,6 +211,9 @@
     { OPTION_LCDCLOCK,	"LCDClock",	OPTV_FREQ,    {0}, FALSE },
     { OPTION_SHADOW_STATUS, "ShadowStatus", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_VIDEORAM,  "VideoRAM",     OPTV_INTEGER, {0}, FALSE },
+    { OPTION_CRT_ONLY,  "CrtOnly",      OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_TV_ON,     "TvOn",         OPTV_BOOLEAN, {0}, FALSE },
+    { OPTION_TV_PAL,    "PAL",          OPTV_BOOLEAN, {0}, FALSE },
     { -1,		NULL,		OPTV_NONE,    {0}, FALSE }
 };
 
@@ -719,6 +731,7 @@
 	return FALSE;
     else {
         int requiredBpp;
+	int altBpp = 0;
 
 	switch (pScrn->depth) {
 	case 8:
@@ -730,6 +743,7 @@
 	    break;
 	case 24:
 	    requiredBpp = 32;
+	    altBpp = 24;
 	    break;
 
 	default:
@@ -739,7 +753,10 @@
 	    return FALSE;
 	}
 
-	if( pScrn->bitsPerPixel != requiredBpp ) {
+	if( 
+	    (pScrn->bitsPerPixel != requiredBpp) &&
+	    (pScrn->bitsPerPixel != altBpp) 
+	) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		       "Depth %d must specify %d bpp; %d was given\n",
 		       pScrn->depth, requiredBpp, pScrn->bitsPerPixel );
@@ -839,6 +856,13 @@
 	psav->NoAccel = TRUE;
     }
 
+    if (pScrn->bitsPerPixel == 24 && !psav->NoAccel) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "HW acceleration not possible with depth 32 and bpp 24.\n");
+	psav->NoAccel = TRUE;
+    }
+
+
     /*
      * The SWCursor setting takes priority over HWCursor.  The default
      * if neither is specified is HW, unless ShadowFB is specified,
@@ -880,6 +904,25 @@
 		    "Option: ShadowStatus enabled\n" );
 
 
+    if( xf86GetOptValBool( psav->Options, OPTION_CRT_ONLY, &psav->CrtOnly))
+	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
+		    "Option: CrtOnly enabled\n" );
+
+    if( xf86GetOptValBool( psav->Options, OPTION_TV_ON, &psav->TvOn)) {
+        psav->PAL = FALSE;
+        SavageGetTvMaxSize(psav);
+    }
+
+    if( xf86GetOptValBool( psav->Options, OPTION_TV_PAL, &psav->PAL)) {
+        SavageGetTvMaxSize(psav);
+	psav->TvOn = TRUE;
+    }
+
+    if( psav->TvOn )
+	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
+		    "TV enabled in %s format\n",
+		    psav->PAL ? "PAL" : "NTSC" );
+
     /* Add more options here. */
 
     if (pScrn->numEntities > 1) {
@@ -1004,7 +1047,7 @@
 
     psav->MemOffScreen = 0;
 
-    if( psav->pVbe )
+    if( !pScrn->videoRam && psav->pVbe )
     {
         /* If VBE is available, it is the best judge of onboard memory. */
 
@@ -1108,10 +1151,15 @@
     }
     else
     {
-        /* We use 128kB for the COB on all chips. */
+	/* We use 128kB for the COB on all chips. */
 
-	psav->cobIndex = 7;
-	psav->cobSize = 0x400 << psav->cobIndex;
+	psav->cobSize = 1 << 17;
+	if (psav->Chipset == S3_SUPERSAVAGE) {
+	    psav->cobIndex = 2;
+	}
+	else {
+	    psav->cobIndex = 7;
+	}
 	psav->cobOffset = psav->videoRambytes - psav->cobSize;
     }
 
@@ -1182,11 +1230,13 @@
 		if ( xf86LoadSubModule(pScrn, "i2c") ) {
 		    xf86LoaderReqSymLists(i2cSymbols,NULL);
 		    if (SavageI2CInit(pScrn)) {
-			CARD32 temp = (INREG(DDC_REG));
-			OUTREG(DDC_REG,(temp | 0x13));
+			unsigned char tmp;
+
+			InI2CREG(tmp);
+			OutI2CREG(tmp | 0x13);
 			xf86SetDDCproperties(pScrn,xf86PrintEDID(
 			    xf86DoEDID_DDC2(pScrn->scrnIndex,psav->I2C)));
-			OUTREG(DDC_REG,temp);
+			OutI2CREG(tmp);
 		    }
 		}
 	    }
@@ -1240,7 +1290,7 @@
 
     /* Check LCD panel information */
 
-    if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
+    if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && !psav->CrtOnly )
     {
 	unsigned char cr6b = hwp->readCrtc( hwp, 0x6b );
 
@@ -1422,7 +1472,7 @@
 	xf86LoaderReqSymLists(shadowSymbols, NULL);
     }
     vbeFree(psav->pVbe);
-	  
+
     return TRUE;
 }
 
@@ -1589,6 +1639,8 @@
     save->SR30 = VGAIN8(0x3c5);
     VGAOUT8(0x3c4, 0x18);
     save->SR18 = VGAIN8(0x3c5);
+    VGAOUT8(0x3c4, 0x1b);
+    save->SR1B = VGAIN8(0x3c5);
 
     /* Save flat panel expansion regsters. */
 
@@ -1650,7 +1702,7 @@
     
     TRACE(("SavageWriteMode(%x)\n", restore->mode));
 
-    if( Entering )
+    if( Entering && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
 	SavageInitialize2DEngine(pScrn);
 
     /*
@@ -1697,6 +1749,14 @@
 	VGAOUT8(vgaCRIndex, 0x67);
 	VGAOUT8(vgaCRReg, restore->CR67);
 
+	/* Enable gamma correction. */
+
+	VGAOUT8(0x3c4, 0x1b);
+	if( pScrn->bitsPerPixel == 32 )
+		VGAOUT8(0x3c5, VGAIN8(0x3c5) | 0x28 );
+	else
+		VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x28 );
+
 	/* We may need TV/panel fixups here.  See s3bios.c line 2904. */
 
 	/* Set FIFO fetch delay. */
@@ -1968,6 +2028,8 @@
 
     VGAOUT8(0x3c4, 0x18);
     VGAOUT8(0x3c5, restore->SR18);
+    VGAOUT8(0x3c4, 0x1b);
+    VGAOUT8(0x3c5, restore->SR1B);
 
     /* load new m, n pll values for dclk & mclk */
     VGAOUT8(0x3c4, 0x15);
@@ -2203,7 +2265,7 @@
 
     miClearVisualTypes();
 
-    if (pScrn->bitsPerPixel > 8) {
+    if (pScrn->bitsPerPixel == 16) {
 	if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
 			      pScrn->rgbBits, pScrn->defaultVisual))
 	    return FALSE;
@@ -2284,11 +2346,16 @@
 
     if (psav->Chipset == S3_SAVAGE4) {
         if (!xf86HandleColormaps(pScreen, 256, 6, SavageLoadPaletteSavage4,
-				 NULL, CMAP_RELOAD_ON_MODE_SWITCH))
+				 NULL, 
+				 CMAP_RELOAD_ON_MODE_SWITCH
+				 | CMAP_PALETTED_TRUECOLOR
+				 ))
 	    return FALSE;
     } else {
         if (!xf86HandleColormaps(pScreen, 256, 6, SavageLoadPalette, NULL,
-				 CMAP_RELOAD_ON_MODE_SWITCH))
+				 CMAP_RELOAD_ON_MODE_SWITCH
+				 | CMAP_PALETTED_TRUECOLOR
+				 ))
 	    return FALSE;
     }
 
@@ -2302,7 +2369,7 @@
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed\n");
 
 #ifdef XvExtension
-    if( !psav->NoAccel )
+    if( !psav->NoAccel && !SavagePanningCheck(pScrn) )
 	SavageInitVideo( pScreen );
 #endif
 
@@ -2366,8 +2433,18 @@
     /* We prohibit modes bigger than the LCD panel. */
     /* TODO We should do this only if the panel is active. */
 
+    if( psav->TvOn )
+    {
+	if( pMode->HDisplay > psav->TVSizeX )
+	    return MODE_VIRTUAL_X;
+
+	if( pMode->VDisplay > psav->TVSizeY )
+	    return MODE_VIRTUAL_Y;
+
+    }
     if( 
-	(psav->PanelX) &&
+	!psav->CrtOnly &&
+	psav->PanelX &&
 	( 
 	    (pMode->HDisplay > psav->PanelX) ||
 	    (pMode->VDisplay > psav->PanelY)
@@ -2470,7 +2547,10 @@
 	    new->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
 	break;
     case 24:
-	new->CR67 = 0xd0;
+	if (pScrn->bitsPerPixel == 24 )
+	    new->CR67 = 0x70;
+	else
+	    new->CR67 = 0xd0;
 	break;
     }
 
@@ -2565,6 +2645,12 @@
 
 	new->SR15 = 0x03 | 0x80;
 	new->SR18 = 0x00;
+
+	VGAOUT8(0x3c4, 0x1b);
+	new->SR1B = VGAIN8(0x3c5);
+	if( pScrn->depth == 24 )
+		new->SR1B |= 0x28;
+
 	new->CR43 = new->CR45 = new->CR65 = 0x00;
 
 	VGAOUT8(vgaCRIndex, 0x40);
@@ -3116,13 +3202,21 @@
 SavageDDC1Read(ScrnInfoPtr pScrn)
 {
     register vgaHWPtr hwp = VGAHWPTR(pScrn);
-    register CARD32 tmp;
+    register unsigned char tmp;
     SavagePtr psav = SAVPTR(pScrn);
+    int vgaCRIndex, vgaCRReg, vgaIOBase;
+
+    vgaHWGetIOBase(hwp);
+    vgaIOBase = hwp->IOBase;
+    vgaCRIndex = vgaIOBase + 4;
+    vgaCRReg = vgaIOBase + 5;
+
+    VerticalRetraceWait();
 
+    InI2CREG(tmp);
     while (hwp->readST01(hwp)&0x8) {};
     while (!(hwp->readST01(hwp)&0x8)) {};
 
-    tmp = (INREG(DDC_REG));
     return ((unsigned int) (tmp & 0x08));
 }
 
@@ -3130,14 +3224,18 @@
 SavageDDC1(int scrnIndex)
 {
     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+    vgaHWPtr hwp = VGAHWPTR(pScrn);
     SavagePtr psav = SAVPTR(pScrn);
-    CARD32 tmp;
+    unsigned char tmp;
     Bool success = FALSE;
     xf86MonPtr pMon;
+    int vgaIOBase;
     
     /* initialize chipset */
-    tmp = INREG(DDC_REG);
-    OUTREG(DDC_REG,(tmp | 0x12));
+    vgaHWGetIOBase(hwp);
+    vgaIOBase = hwp->IOBase;
+    InI2CREG(tmp);
+    OutI2CREG(tmp | 0x12);
     
     if ((pMon = xf86PrintEDID(
 	xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeed,SavageDDC1Read))) != NULL)
@@ -3145,7 +3243,7 @@
     xf86SetDDCproperties(pScrn,pMon);
 
     /* undo initialization */
-    OUTREG(DDC_REG,(tmp));
+    OutI2CREG(tmp);
     return success;
 }
 
@@ -3161,3 +3259,34 @@
     }
 }
 
+
+static void
+SavageGetTvMaxSize(SavagePtr psav)
+{
+    if( psav->PAL ) {
+	psav->TVSizeX = 800;
+	psav->TVSizeY = 600;
+    }
+    else {
+	psav->TVSizeX = 640;
+	psav->TVSizeY = 480;
+    }
+}
+
+
+static Bool
+SavagePanningCheck(ScrnInfoPtr pScrn)
+{
+    SavagePtr psav = SAVPTR(pScrn);
+    DisplayModePtr pMode;
+
+    pMode = pScrn->currentMode;
+    psav->iResX = pMode->CrtcHDisplay;
+    psav->iResY = pMode->CrtcVDisplay;
+    if( psav->iResX < pScrn->virtualX || psav->iResY < pScrn->virtualY )
+	return TRUE;
+    else
+	return FALSE;
+}
+
+
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_driver.h xc/programs/Xserver/hw/xfree86/drivers/savage/savage_driver.h
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_driver.h	2001-08-09 21:14:13.000000000 +0200
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_driver.h	2002-09-11 20:24:58.000000000 +0200
@@ -35,6 +35,9 @@
 #define INREG16(addr) MMIO_IN16(psav->MapBase, addr)
 #define OUTREG16(addr,val) MMIO_OUT16(psav->MapBase, addr, val)
 
+#define SAVAGE_CRT_ON	1
+#define SAVAGE_LCD_ON	2
+#define SAVAGE_TV_ON	4
 
 typedef struct _S3VMODEENTRY {
    unsigned short Width;
@@ -54,7 +57,7 @@
 typedef struct {
     unsigned int mode, refresh;
     unsigned char SR08, SR0E, SR0F;
-    unsigned char SR10, SR11, SR12, SR13, SR15, SR18, SR29, SR30;
+    unsigned char SR10, SR11, SR12, SR13, SR15, SR18, SR1B, SR29, SR30;
     unsigned char SR54[8];
     unsigned char Clock;
     unsigned char CR31, CR32, CR33, CR34, CR36, CR3A, CR3B, CR3C;
@@ -121,8 +124,29 @@
     int			rotate;
     double		LCDClock;
     Bool		ShadowStatus;
-    int			PanelX;
-    int			PanelY;
+    Bool		CrtOnly;
+    Bool		TvOn;
+    Bool		PAL;
+    int			iDevInfo;
+    int			iDevInfoPrim;
+
+    int			PanelX;		/* panel width */
+    int			PanelY;		/* panel height */
+    int			iResX;		/* crtc X display */
+    int			iResY;		/* crtc Y display */
+    int			XFactor;	/* overlay X factor */
+    int			YFactor;	/* overlay Y factor */
+    int			displayXoffset;	/* overlay X offset */
+    int			displayYoffset;	/* overlay Y offset */
+    int			XExpansion;	/* expansion factor in x */
+    int			XExp1;
+    int			XExp2;
+    int			YExpansion;	/* expansion factor in x */
+    int			YExp1;
+    int			YExp2;
+    int			cxScreen;
+    int			TVSizeX;
+    int			TVSizeY;
 
     CloseScreenProcPtr	CloseScreen;
     pciVideoPtr		PciInfo;
@@ -176,6 +200,7 @@
     XF86VideoAdaptorPtr	adaptor;
     int			VideoZoomMax;
     int			dwBCIWait2DIdle;
+    XF86OffscreenImagePtr offscreenImages;
 
 } SavageRec, *SavagePtr;
 
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_i2c.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_i2c.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_i2c.c	2001-02-13 22:15:19.000000000 +0100
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_i2c.c	2001-12-05 01:43:48.000000000 +0100
@@ -41,23 +41,37 @@
 static void
 SavageI2CPutBits(I2CBusPtr b, int clock,  int data)
 {
-    SavagePtr psav = SAVPTR(xf86Screens[b->scrnIndex]);
-    unsigned int reg = 0x10;
+    ScrnInfoPtr pScrn = (ScrnInfoPtr)(xf86Screens[b->scrnIndex]);
+    SavagePtr psav = SAVPTR(pScrn);
+    vgaHWPtr hwp;
+    int vgaIOBase;
+    unsigned char reg = 0x10;
+
+    hwp = VGAHWPTR(pScrn);
+    vgaHWGetIOBase(hwp);
+    vgaIOBase = hwp->IOBase;
 
     if(clock) reg |= 0x1;
     if(data)  reg |= 0x2;
 
-    OUTREG(DDC_REG,reg);
+    OutI2CREG(reg);
     /*ErrorF("SavageI2CPutBits: %d %d\n", clock, data); */
 }
 
 static void
 SavageI2CGetBits(I2CBusPtr b, int *clock, int *data)
 {
-    SavagePtr psav = SAVPTR(xf86Screens[b->scrnIndex]);
-    unsigned int reg;
+    ScrnInfoPtr pScrn = (ScrnInfoPtr)(xf86Screens[b->scrnIndex]);
+    SavagePtr psav = SAVPTR(pScrn);
+    vgaHWPtr hwp;
+    int vgaIOBase;
+    unsigned char reg = 0x10;
 
-    reg = (INREG(DDC_REG));
+    hwp = VGAHWPTR(pScrn);
+    vgaHWGetIOBase(hwp);
+    vgaIOBase = hwp->IOBase;
+
+    InI2CREG(reg);
 
     *clock = reg & 0x4;
     *data = reg & 0x8;
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_regs.h xc/programs/Xserver/hw/xfree86/drivers/savage/savage_regs.h
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_regs.h	2001-11-04 23:17:48.000000000 +0100
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_regs.h	2002-03-08 19:01:06.000000000 +0100
@@ -22,6 +22,10 @@
 #define PCI_CHIP_SUPSAV_IXCSDR		0x8c2e
 #define PCI_CHIP_SUPSAV_IXCDDR		0x8c2f
 #endif
+#ifndef PCI_CHIP_PROSAVAGE_DDR
+#define PCI_CHIP_PROSAVAGE_DDR	0x8d03
+#define PCI_CHIP_PROSAVAGE_DDRK	0x8d04
+#endif
 
 #define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
 
@@ -164,9 +168,6 @@
 #define MONO_PAT_0			0xa4e8
 #define MONO_PAT_1			0xa4ec
 
-#define DDC_REG				0xff20
-
-
 /* Constants for CR69. */
 
 #define CRT_ACTIVE	0x01
@@ -202,4 +203,20 @@
 	} \
 }
 
+#define	I2C_REG		0xa0
+#define InI2CREG(a)	\
+{ \
+    VGAOUT8(vgaIOBase + 4, I2C_REG);	\
+    a = VGAIN8(vgaIOBase + 5);		\
+}
+
+#define OutI2CREG(a)	\
+{ \
+    VGAOUT8(vgaIOBase + 4, I2C_REG);	\
+    VGAOUT8(vgaIOBase + 5, a);		\
+}
+ 
+#define HZEXP_FACTOR_IGA1	0x59
+#define VTEXP_FACTOR_IGA1	0x5b
+
 #endif /* _SAVAGE_REGS_H */
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_vbe.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_vbe.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_vbe.c	2001-05-19 04:05:55.000000000 +0200
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_vbe.c	2001-12-06 00:02:32.000000000 +0100
@@ -14,6 +14,8 @@
 #define L_ADD(x)  (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00)
 
 Bool vbeModeInit( vbeInfoPtr, int );
+static int SavageGetDevice( SavagePtr psav );
+/*static int SavageGetTVType( SavagePtr psav );*/
 
 static void
 SavageClearVM86Regs( xf86Int10InfoPtr pInt )
@@ -31,6 +33,15 @@
 void
 SavageSetTextMode( SavagePtr psav )
 {
+    /* Restore display device if changed. */
+    if( psav->iDevInfo != psav->iDevInfoPrim ) {
+	SavageClearVM86Regs( psav->pInt10 );
+	psav->pInt10->ax = 0x4f14;
+	psav->pInt10->bx = 0x0003;
+	psav->pInt10->cx = psav->iDevInfoPrim;
+	xf86ExecX86int10( psav->pInt10 );
+    }
+
     SavageClearVM86Regs( psav->pInt10 );
 
     psav->pInt10->ax = 0x83;
@@ -42,16 +53,55 @@
 void
 SavageSetVESAMode( SavagePtr psav, int n, int Refresh )
 {
-    /* First, establish the refresh rate for this mode. */
+    int iDevInfo;
+    static int iCount = 0;
+
+    /* Get current display device status. */
+
+    iDevInfo = SavageGetDevice(psav);
+    psav->iDevInfo = iDevInfo;
+    if( !iCount++ )
+	psav->iDevInfoPrim = psav->iDevInfo;
+    if( psav->CrtOnly )
+	psav->iDevInfo = CRT_ACTIVE;
+    if( psav->TvOn )
+	psav->iDevInfo = TV_ACTIVE;
+
+    /* Establish the refresh rate for this mode. */
 
     SavageClearVM86Regs( psav->pInt10 );
     psav->pInt10->ax = 0x4f14;	/* S3 extensions */
     psav->pInt10->bx = 0x0001;	/* Set default refresh rate */
     psav->pInt10->cx = n;
-    psav->pInt10->di = Refresh;
+    psav->pInt10->di = Refresh & 0xffff;
 
     xf86ExecX86int10( psav->pInt10 );
 
+    /* Set TV type if TV is on. */
+    if( psav->TvOn ) {
+	SavageClearVM86Regs( psav->pInt10 );
+	psav->pInt10->ax = 0x4f14;	/* S3 extensions */
+	psav->pInt10->bx = 0x0007;	/* TV extensions */
+	psav->pInt10->cx = psav->PAL ? 0x08 : 0x04;
+	psav->pInt10->dx = 0x0c;
+	xf86ExecX86int10( psav->pInt10 );
+    }
+
+    /* Manipulate output device set. */
+    if( psav->iDevInfo != iDevInfo ) {
+	SavageClearVM86Regs( psav->pInt10 );
+	psav->pInt10->ax = 0x4f14;	/* S3 extensions */
+	psav->pInt10->bx = 0x0003;	/* set active devices */
+	psav->pInt10->cx = psav->PAL ? 0x08 : 0x04;
+	xf86ExecX86int10( psav->pInt10 );
+
+	/* Re-fetch actual device set. */
+	psav->iDevInfo = SavageGetDevice( psav );
+	iDevInfo = psav->iDevInfo;
+	psav->CrtOnly = (iDevInfo == 1);
+	psav->TvOn = !!(iDevInfo & 4);
+    }
+
     /* Now, make this mode current. */
 
     if( xf86LoaderCheckSymbol( "VBESetVBEMode" ) )
@@ -73,6 +123,20 @@
 }
 
 
+/* Function to get supported device list. */
+
+static int SavageGetDevice( SavagePtr psav )
+{
+    SavageClearVM86Regs( psav->pInt10 );
+    psav->pInt10->ax = 0x4f14;	/* S3 extensions */
+    psav->pInt10->bx = 0x0103;	/* get active devices */
+
+    xf86ExecX86int10( psav->pInt10 );
+
+    return ((psav->pInt10->cx) & 0xf);
+}
+
+
 void
 SavageFreeBIOSModeTable( SavagePtr psav, SavageModeTablePtr* ppTable )
 {
@@ -128,6 +192,11 @@
 
     vbe = (vbeControllerInfoPtr) psav->pVbe->memory;
     vbeLinear = xf86Int10AllocPages( psav->pInt10, 1, &vbeReal );
+    if( !vbeLinear )
+    {
+	ErrorF( "Cannot allocate scratch page in real mode memory." );
+	return 0;
+    }
     vmib = (struct vbe_mode_info_block *) vbeLinear;
     
     for (
diff -Nurd xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_video.c xc/programs/Xserver/hw/xfree86/drivers/savage/savage_video.c
--- xc/programs/Xserver/hw/xfree86/drivers/savage~/savage_video.c	2001-11-21 23:43:01.000000000 +0100
+++ xc/programs/Xserver/hw/xfree86/drivers/savage/savage_video.c	2002-09-11 20:26:03.000000000 +0200
@@ -78,6 +78,9 @@
     short drw_w, short drw_h
 ) = NULL;
 
+static void OverlayParamInit(ScrnInfoPtr pScrn);
+static void InitStreamsForExpansion(SavagePtr psav);
+
 /*static void SavageBlockHandler(int, pointer, pointer, pointer);*/
 
 #define XVTRACE	4
@@ -226,6 +229,13 @@
 /* CR67[3] = 1 : Mem-mapped regs */
 #define USE_MM_FOR_PRI_STREAM       0x08
 
+#define HDM_SHIFT	16
+#define HDSCALE_4	(2 << HDM_SHIFT)
+#define HDSCALE_8	(3 << HDM_SHIFT)
+#define HDSCALE_16	(4 << HDM_SHIFT)
+#define HDSCALE_32	(5 << HDM_SHIFT)
+#define HDSCALE_64	(6 << HDM_SHIFT)
+
 /* Old Streams */
 
 #define ENABLE_STREAMS_OLD	    0x0c
@@ -264,6 +274,7 @@
 #define PSTREAM_WINDOW_SIZE_REG		0x81F4
 #define SSTREAM_WINDOW_START_REG	0x81F8
 #define SSTREAM_WINDOW_SIZE_REG		0x81FC
+#define FIFO_CONTROL			0x8200
 #define PSTREAM_FBSIZE_REG		0x8300
 #define SSTREAM_FBSIZE_REG		0x8304
 #define SSTREAM_FBADDR2_REG		0x8308
@@ -363,6 +374,14 @@
 
     xf86ErrorFVerb(XVTRACE, "SavageInitStreams\n" );
 
+    if( 
+	S3_SAVAGE_MOBILE_SERIES(psav->Chipset) && 
+	!psav->CrtOnly && 
+	!psav->TvOn 
+    ) {
+	OverlayParamInit( pScrn );
+    }
+
     /* Primary stream reflects the frame buffer. */
 
     jDelta = pScrn->displayWidth * pScrn->bitsPerPixel / 8;
@@ -419,7 +438,7 @@
 
     VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 );
 
-    if( (psav->Chipset == S3_SAVAGE_MX)  ||
+    if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
         (psav->Chipset == S3_SUPERSAVAGE) ||
         (psav->Chipset == S3_SAVAGE2000) )
     {
@@ -495,7 +514,7 @@
     VGAOUT16(0x3c4, 0x0608);
 
     VGAOUT8( vgaCRIndex, EXT_MISC_CTRL2 );
-    if( (psav->Chipset == S3_SAVAGE_MX)  ||
+    if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset)  ||
         (psav->Chipset == S3_SUPERSAVAGE) ||
         (psav->Chipset == S3_SAVAGE2000) )
 	jStreamsControl = VGAIN8( vgaCRReg ) & NO_STREAMS;
@@ -528,8 +547,8 @@
 
     xf86ErrorFVerb(XVTRACE,"SavageInitVideo\n");
     if(
-	(psav->Chipset == S3_SAVAGE_MX) ||
-	(psav->Chipset == S3_SUPERSAVAGE) ||
+	S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
+        (psav->Chipset == S3_SUPERSAVAGE) ||
 	(psav->Chipset == S3_SAVAGE2000)
     )
     {
@@ -846,6 +865,15 @@
     pPriv->brightness = 0;
     pPriv->contrast = 128;
     pPriv->saturation = 128;
+#if 0
+    /* 
+     * The S3 driver has these values for some of the chips.  I have yet
+     * to find any Savage where these make sense.
+     */
+    pPriv->brightness = 64;
+    pPriv->contrast = 16;
+    pPriv->saturation = 128;
+#endif
     pPriv->hue = 0;
     pPriv->lastKnownPitch = 0;
 
@@ -1002,36 +1030,41 @@
     pointer data
 ){
     SavagePortPrivPtr pPriv = (SavagePortPrivPtr)data;
-    /*SavagePtr psav = SAVPTR(pScrn);*/
+    SavagePtr psav = SAVPTR(pScrn);
 
     if(attribute == xvColorKey) {
 	pPriv->colorKey = value;
-	SavageSetColorKey( pScrn );
+	if( psav->videoFlags & VF_STREAMS_ON)
+	    SavageSetColorKey( pScrn );
 	REGION_EMPTY(pScrn->pScreen, &pPriv->clip);   
     } 
     else if( attribute == xvBrightness) {
 	if((value < -128) || (value > 127))
 	    return BadValue;
 	pPriv->brightness = value;
-	SavageSetColor( pScrn );
+	if( psav->videoFlags & VF_STREAMS_ON)
+	    SavageSetColor( pScrn );
     }
     else if( attribute == xvContrast) {
 	if((value < 0) || (value > 255))
 	    return BadValue;
 	pPriv->contrast = value;
-	SavageSetColor( pScrn );
+	if( psav->videoFlags & VF_STREAMS_ON)
+	    SavageSetColor( pScrn );
     }
     else if( attribute == xvSaturation) {
 	if((value < 0) || (value > 255))
 	    return BadValue;
 	pPriv->saturation = value;
-	SavageSetColor( pScrn );
+	if( psav->videoFlags & VF_STREAMS_ON)
+	    SavageSetColor( pScrn );
     }
     else if( attribute == xvHue) {
 	if((value < -180) || (value > 180))
 	    return BadValue;
 	pPriv->hue = value;
-	SavageSetColor( pScrn );
+	if( psav->videoFlags & VF_STREAMS_ON)
+	    SavageSetColor( pScrn );
     }
     else
 	return BadMatch;
@@ -1163,6 +1196,7 @@
 
     pScreen = screenInfo.screens[pScrn->scrnIndex];
 
+    xf86PurgeUnlockedOffscreenAreas(pScreen);
     new_area = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 
 				numlines, 0, NULL, NULL, NULL);
 
@@ -1200,6 +1234,7 @@
     SavagePortPrivPtr pPriv = psav->adaptor->pPortPrivates[0].ptr;
     /*DisplayModePtr mode = pScrn->currentMode;*/
     int vgaCRIndex, vgaCRReg, vgaIOBase;
+    unsigned int ssControl;
 
 
     vgaIOBase = hwp->IOBase;
@@ -1222,22 +1257,45 @@
 
     /* Calculate horizontal scale factor. */
 
-    OUTREG(SSTREAM_STRETCH_REG, 32768 * src_w / drw_w );
+    OUTREG(SSTREAM_STRETCH_REG, (src_w << 15) / drw_w );
 
     /* Calculate vertical scale factor. */
 
     OUTREG(SSTREAM_LINES_REG, src_h );
     OUTREG(SSTREAM_VINITIAL_REG, 0 );
-    OUTREG(SSTREAM_VSCALE_REG, 32768 * src_h / drw_h );
+    OUTREG(SSTREAM_VSCALE_REG, (src_h << 15) / drw_h );
 
     /* Set surface location and stride. */
 
     OUTREG(SSTREAM_FBADDR0_REG, (offset + (x1>>15)) & 0x3ffff0 );
+    OUTREG(SSTREAM_FBADDR1_REG, 0 );
+    
     OUTREG(SSTREAM_STRIDE_REG, pitch & 0xfff );
 
     OUTREG(SSTREAM_WINDOW_START_REG, OS_XY(dstBox->x1, dstBox->y1) );
     OUTREG(SSTREAM_WINDOW_SIZE_REG, OS_WH(drw_w, drw_h) );
 
+    ssControl = 0;
+
+    if( src_w > (drw_w << 1) )
+    {
+	/* BUGBUG shouldn't this be >=?  */
+	if( src_w <= (drw_w << 2) )
+	    ssControl |= HDSCALE_4;
+	else if( src_w > (drw_w << 3) )
+	    ssControl |= HDSCALE_8;
+	else if( src_w > (drw_w << 4) )
+	    ssControl |= HDSCALE_16;
+	else if( src_w > (drw_w << 5) )
+	    ssControl |= HDSCALE_32;
+	else if( src_w > (drw_w << 6) )
+	    ssControl |= HDSCALE_64;
+    }
+
+    ssControl |= src_w;
+    ssControl |= (1 << 24);
+    OUTREG(SSTREAM_CONTROL_REG, ssControl);
+
     /* Set color key on primary. */
 
     SavageSetColorKey( pScrn );
@@ -1308,6 +1366,19 @@
     }
     else
     {
+	if( 
+	    S3_SAVAGE_MOBILE_SERIES(psav->Chipset) &&
+	    !psav->CrtOnly &&
+	    !psav->TvOn
+	) {
+	    drw_w = (float)(drw_w * psav->XExp1)/(float)psav->XExp2 + 1;
+	    drw_h = (float)(drw_h * psav->YExp1)/(float)psav->YExp2 + 1;
+	    dstBox->x1 = (float)(dstBox->x1 * psav->XExp1)/(float)psav->XExp2;
+	    dstBox->y1 = (float)(dstBox->y1 * psav->YExp1)/(float)psav->YExp2;
+	    dstBox->x1 += psav->displayXoffset;
+	    dstBox->y1 += psav->displayYoffset;
+	}
+
 	OUTREG(SEC_STREAM_HSCALING, 
 	    ((src_w&0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF ));
 	/* BUGBUG need to add 00040000 if src stride > 2048 */
@@ -1383,6 +1454,11 @@
     SavageClipVideo(&dstBox, &x1, &x2, &y1, &y2, 
 		REGION_EXTENTS(pScreen, clipBoxes), width, height);
 
+    drw_w = dstBox.x2 - dstBox.x1;
+    drw_h = dstBox.y2 - dstBox.y1;
+    src_w = ( x2 - x1 ) >> 16;
+    src_h = ( y2 - y1 ) >> 16;
+
     if((x1 >= x2) || (y1 >= y2))
 	return Success;
 
@@ -1740,10 +1816,16 @@
 SavageInitOffscreenImages(ScreenPtr pScreen)
 {
     XF86OffscreenImagePtr offscreenImages;
+    SavagePtr psav = SAVPTR(xf86Screens[pScreen->myNum]);
 
     /* need to free this someplace */
-    if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
-	return;
+    if (!psav->offscreenImages) {
+	if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec))))
+	    return;
+	psav->offscreenImages = offscreenImages;
+    } else {
+	offscreenImages = psav->offscreenImages;
+    }
 
     offscreenImages[0].image = &Images[0];
     offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 
@@ -1762,4 +1844,152 @@
     xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);
 }
 
-#endif  /* !XvExtension */
+/* Function to get lcd factor, display offset for overlay use
+ * Input: pScrn; Output: x,yfactor, displayoffset in pScrn
+ */
+static void OverlayParamInit(ScrnInfoPtr pScrn)
+{
+    SavagePtr psav = SAVPTR(pScrn);
+
+    psav = SAVPTR(pScrn);
+    psav->cxScreen = psav->iResX;
+    InitStreamsForExpansion(psav);
+}
+
+/* Function to calculate lcd expansion x,yfactor and offset for overlay
+ */
+static void InitStreamsForExpansion(SavagePtr psav)
+{
+    int		PanelSizeX,PanelSizeY;
+    int		ViewPortWidth,ViewPortHeight;
+    int		XFactor, YFactor;
+
+    PanelSizeX = psav->PanelX;
+    PanelSizeY = psav->PanelY;
+    ViewPortWidth = psav->iResX;
+    ViewPortHeight = psav->iResY;
+    if( PanelSizeX == 1408 )
+	PanelSizeX = 1400;
+    psav->XExpansion = 0x00010001;
+    psav->YExpansion = 0x00010001;
+    psav->displayXoffset = 0;
+    psav->displayYoffset = 0;
+
+    VGAOUT8(0x3C4, HZEXP_FACTOR_IGA1);
+    XFactor = VGAIN8(0x3C5) >> 4;
+    VGAOUT8(0x3C4, VTEXP_FACTOR_IGA1);
+    YFactor = VGAIN8(0x3C5) >> 4;
+
+    switch( XFactor )
+    {
+	case 1:
+	    psav->XExpansion = 0x00010001;
+	    psav->displayXoffset = 
+		(((PanelSizeX - ViewPortWidth) / 2) + 0x7) & 0xFFF8;
+	    break;
+
+	case 3:
+	    psav->XExpansion = 0x00090008;
+	    psav->displayXoffset = 
+		(((PanelSizeX - ((9 * ViewPortWidth)/8)) / 2) + 0x7) & 0xFFF8;
+	    break;
+
+	case 4:
+	    psav->XExpansion = 0x00050004;
+
+	    if ((psav->cxScreen == 800) && (PanelSizeX !=1400))
+	    {
+		psav->displayXoffset = 
+		    (((PanelSizeX - ((5 * ViewPortWidth)/4)) / 2) ) & 0xFFF8; 
+	    }
+	    else
+	    {
+		psav->displayXoffset = 
+		    (((PanelSizeX - ((5 * ViewPortWidth)/4)) / 2) +0x7) & 0xFFF8;
+	    }
+	    break;
+
+	case 6:
+	    psav->XExpansion = 0x00030002;
+	    psav->displayXoffset = 
+		(((PanelSizeX - ((3 * ViewPortWidth)/2)) / 2) + 0x7) & 0xFFF8;
+	    break;
+
+	case 7:
+	    psav->XExpansion = 0x00020001;
+	    psav->displayXoffset = 
+		(((PanelSizeX - (2 * ViewPortWidth)) / 2) + 0x7) & 0xFFF8;
+	    break;
+    }
+	
+    switch( YFactor )
+    {
+	case 0:
+	    psav->YExpansion = 0x00010001;
+	    psav->displayYoffset = (PanelSizeY - ViewPortHeight) / 2;
+	    break;
+	case 1:
+	    psav->YExpansion = 0x00010001;
+	    psav->displayYoffset = (PanelSizeY - ViewPortHeight) / 2;
+	    break;
+	case 2:
+	    psav->YExpansion = 0x00040003;
+	    psav->displayYoffset = (PanelSizeY - ((4 * ViewPortHeight)/3)) / 2;
+	    break;
+	case 4:
+	    psav->YExpansion = 0x00050004;
+	    psav->displayYoffset = (PanelSizeY - ((5 * ViewPortHeight)/4)) / 2;
+	    break;
+	case 5:
+	    psav->YExpansion = 0x00040003;
+
+	    if((psav->cxScreen == 1024)&&(PanelSizeX ==1400))
+	    {
+		psav->displayYoffset = 
+		    ((PanelSizeY - ((4 * ViewPortHeight)/3)) / 2) - 0x1 ;
+	    }
+	    else
+	    {
+		psav->displayYoffset = (PanelSizeY - ((4 * ViewPortHeight)/3)) / 2;
+	    }
+	    break;
+	case 6:
+	    psav->YExpansion = 0x00050004;
+	    psav->displayYoffset = (PanelSizeY - ((5 * ViewPortHeight)/4)) / 2;
+	    break;
+	case 7:
+	    psav->YExpansion = 0x00030002;
+	    psav->displayYoffset = (PanelSizeY - ((3 * ViewPortHeight)/2)) / 2;
+	    break;
+	case 8:
+	    psav->YExpansion = 0x00020001;
+	    psav->displayYoffset = (PanelSizeY - (2 * ViewPortHeight)) /2;
+	    break;
+	case 9:
+	    psav->YExpansion = 0x00090004;
+	    psav->displayYoffset = (PanelSizeY - ((9 * ViewPortHeight)/4)) /2;
+	    break;
+	case 11:
+	    psav->YExpansion = 0x00110005;
+	    psav->displayYoffset = (PanelSizeY - ((11 * ViewPortHeight)/5)) /2;
+	    break;
+	case 12:
+	    psav->YExpansion = 0x00070003;
+	    psav->displayYoffset = (PanelSizeY - ((7 * ViewPortHeight)/3)) /2;
+	    break;
+	case 14:
+	    psav->YExpansion = 0x00050002;
+	    psav->displayYoffset = (PanelSizeY - ((5 * ViewPortHeight)/2)) /2;
+	    break;
+	case 15:
+	    psav->YExpansion = 0x00040001;
+	    psav->displayYoffset = (PanelSizeY - (4 * ViewPortHeight)) /2;
+	    break;
+    }
+    psav->XExp1 = psav->XExpansion >> 16;
+    psav->XExp2 = psav->XExpansion & 0xFFFF;
+    psav->YExp1 = psav->YExpansion >> 16;
+    psav->YExp2 = psav->YExpansion & 0xFFFF;
+}  /* InitStreamsForExpansionPM */
+
+#endif /* XvExtension */

Attachment: pgpeJLIj7aNzT.pgp
Description: PGP signature


Reply to: