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: msg04617/pgp00000.pgp
Description: PGP signature

Reply via email to