savage_driver.c revision ab47cfaa
1ab47cfaaSmrg/* 2ab47cfaaSmrg * Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3ab47cfaaSmrg * Copyright (c) 2003-2006, X.Org Foundation 4ab47cfaaSmrg * 5ab47cfaaSmrg * Permission is hereby granted, free of charge, to any person obtaining a 6ab47cfaaSmrg * copy of this software and associated documentation files (the "Software"), 7ab47cfaaSmrg * to deal in the Software without restriction, including without limitation 8ab47cfaaSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9ab47cfaaSmrg * and/or sell copies of the Software, and to permit persons to whom the 10ab47cfaaSmrg * Software is furnished to do so, subject to the following conditions: 11ab47cfaaSmrg * 12ab47cfaaSmrg * The above copyright notice and this permission notice shall be included in 13ab47cfaaSmrg * all copies or substantial portions of the Software. 14ab47cfaaSmrg * 15ab47cfaaSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16ab47cfaaSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17ab47cfaaSmrg * FITESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18ab47cfaaSmrg * COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19ab47cfaaSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20ab47cfaaSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21ab47cfaaSmrg * DEALINGS IN THE SOFTWARE. 22ab47cfaaSmrg * 23ab47cfaaSmrg * Except as contained in this notice, the name of the copyright holder(s) 24ab47cfaaSmrg * and author(s) shall not be used in advertising or otherwise to promote 25ab47cfaaSmrg * the sale, use or other dealings in this Software without prior written 26ab47cfaaSmrg * authorization from the copyright holder(s) and author(s). 27ab47cfaaSmrg */ 28ab47cfaaSmrg 29ab47cfaaSmrg/** 30ab47cfaaSmrg * \file savage_driver.c 31ab47cfaaSmrg * 32ab47cfaaSmrg * \author Tim Roberts <timr@probo.com> 33ab47cfaaSmrg * \author Ani Joshi <ajoshi@unixbox.com> 34ab47cfaaSmrg * 35ab47cfaaSmrg * \todo Add credits for the 3.3.x authors. 36ab47cfaaSmrg */ 37ab47cfaaSmrg 38ab47cfaaSmrg#ifdef HAVE_CONFIG_H 39ab47cfaaSmrg#include "config.h" 40ab47cfaaSmrg#endif 41ab47cfaaSmrg 42ab47cfaaSmrg#include "xf86RAC.h" 43ab47cfaaSmrg#include "shadowfb.h" 44ab47cfaaSmrg 45ab47cfaaSmrg#include "globals.h" 46ab47cfaaSmrg#define DPMS_SERVER 47ab47cfaaSmrg#include <X11/extensions/dpms.h> 48ab47cfaaSmrg 49ab47cfaaSmrg#include "xf86xv.h" 50ab47cfaaSmrg 51ab47cfaaSmrg#include "savage_driver.h" 52ab47cfaaSmrg#include "savage_regs.h" 53ab47cfaaSmrg#include "savage_bci.h" 54ab47cfaaSmrg#include "savage_streams.h" 55ab47cfaaSmrg 56ab47cfaaSmrg#define TRANSPARENCY_KEY 0xff; 57ab47cfaaSmrg 58ab47cfaaSmrg#ifdef XF86DRI 59ab47cfaaSmrg#define _XF86DRI_SERVER_ 60ab47cfaaSmrg#include "savage_dri.h" 61ab47cfaaSmrg#include "savage_sarea.h" 62ab47cfaaSmrg#endif 63ab47cfaaSmrg 64ab47cfaaSmrg 65ab47cfaaSmrg/* 66ab47cfaaSmrg * prototypes 67ab47cfaaSmrg */ 68ab47cfaaSmrgstatic void SavageEnableMMIO(ScrnInfoPtr pScrn); 69ab47cfaaSmrgstatic void SavageDisableMMIO(ScrnInfoPtr pScrn); 70ab47cfaaSmrg 71ab47cfaaSmrgstatic const OptionInfoRec * SavageAvailableOptions(int chipid, int busid); 72ab47cfaaSmrgstatic void SavageIdentify(int flags); 73ab47cfaaSmrgstatic Bool SavageProbe(DriverPtr drv, int flags); 74ab47cfaaSmrgstatic Bool SavagePreInit(ScrnInfoPtr pScrn, int flags); 75ab47cfaaSmrg 76ab47cfaaSmrgstatic Bool SavageEnterVT(int scrnIndex, int flags); 77ab47cfaaSmrgstatic void SavageLeaveVT(int scrnIndex, int flags); 78ab47cfaaSmrgstatic void SavageSave(ScrnInfoPtr pScrn); 79ab47cfaaSmrgstatic void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr, SavageRegPtr, Bool); 80ab47cfaaSmrg 81ab47cfaaSmrgstatic void SavageInitStatus(ScrnInfoPtr pScrn); 82ab47cfaaSmrgstatic void SavageInitShadowStatus(ScrnInfoPtr pScrn); 83ab47cfaaSmrg 84ab47cfaaSmrgstatic Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, 85ab47cfaaSmrg char **argv); 86ab47cfaaSmrgstatic int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen); 87ab47cfaaSmrgstatic ModeStatus SavageValidMode(int index, DisplayModePtr mode, 88ab47cfaaSmrg Bool verbose, int flags); 89ab47cfaaSmrg 90ab47cfaaSmrgvoid SavageDGAInit(ScreenPtr); 91ab47cfaaSmrgstatic Bool SavageMapMem(ScrnInfoPtr pScrn); 92ab47cfaaSmrgstatic void SavageUnmapMem(ScrnInfoPtr pScrn, int All); 93ab47cfaaSmrgstatic Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 94ab47cfaaSmrgstatic Bool SavageCloseScreen(int scrnIndex, ScreenPtr pScreen); 95ab47cfaaSmrgstatic Bool SavageSaveScreen(ScreenPtr pScreen, int mode); 96ab47cfaaSmrgstatic void SavageLoadPalette(ScrnInfoPtr pScrn, int numColors, 97ab47cfaaSmrg int *indicies, LOCO *colors, 98ab47cfaaSmrg VisualPtr pVisual); 99ab47cfaaSmrgstatic void SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors, 100ab47cfaaSmrg int *indicies, LOCO *colors, 101ab47cfaaSmrg VisualPtr pVisual); 102ab47cfaaSmrgstatic void SavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b); 103ab47cfaaSmrgstatic void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1, 104ab47cfaaSmrg int min_n2, int max_n2, long freq_min, 105ab47cfaaSmrg long freq_max, unsigned int *mdiv, 106ab47cfaaSmrg unsigned int *ndiv, unsigned int *r); 107ab47cfaaSmrgvoid SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file); 108ab47cfaaSmrgvoid SavagePrintRegs(ScrnInfoPtr pScrn); 109ab47cfaaSmrgstatic void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags); 110ab47cfaaSmrgstatic Bool SavageDDC1(int scrnIndex); 111ab47cfaaSmrgstatic unsigned int SavageDDC1Read(ScrnInfoPtr pScrn); 112ab47cfaaSmrgstatic void SavageProbeDDC(ScrnInfoPtr pScrn, int index); 113ab47cfaaSmrgstatic void SavageGetTvMaxSize(SavagePtr psav); 114ab47cfaaSmrgstatic Bool SavagePanningCheck(ScrnInfoPtr pScrn); 115ab47cfaaSmrg#ifdef XF86DRI 116ab47cfaaSmrgstatic Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn); 117ab47cfaaSmrg#endif 118ab47cfaaSmrgstatic void SavageResetStreams(ScrnInfoPtr pScrn); 119ab47cfaaSmrg 120ab47cfaaSmrgextern ScrnInfoPtr gpScrn; 121ab47cfaaSmrg 122ab47cfaaSmrg#define iabs(a) ((int)(a)>0?(a):(-(a))) 123ab47cfaaSmrg 124ab47cfaaSmrg/*#define TRACEON*/ 125ab47cfaaSmrg#ifdef TRACEON 126ab47cfaaSmrg#define TRACE(prms) ErrorF prms 127ab47cfaaSmrg#else 128ab47cfaaSmrg#define TRACE(prms) 129ab47cfaaSmrg#endif 130ab47cfaaSmrg 131ab47cfaaSmrgint gSavageEntityIndex = -1; 132ab47cfaaSmrg 133ab47cfaaSmrg_X_EXPORT DriverRec SAVAGE = 134ab47cfaaSmrg{ 135ab47cfaaSmrg SAVAGE_VERSION, 136ab47cfaaSmrg SAVAGE_DRIVER_NAME, 137ab47cfaaSmrg SavageIdentify, 138ab47cfaaSmrg SavageProbe, 139ab47cfaaSmrg SavageAvailableOptions, 140ab47cfaaSmrg NULL, 141ab47cfaaSmrg 0, 142ab47cfaaSmrg NULL 143ab47cfaaSmrg}; 144ab47cfaaSmrg 145ab47cfaaSmrg 146ab47cfaaSmrg/* Supported chipsets */ 147ab47cfaaSmrg 148ab47cfaaSmrgstatic SymTabRec SavageChips[] = { 149ab47cfaaSmrg { PCI_CHIP_SAVAGE4, "Savage4" }, 150ab47cfaaSmrg { PCI_CHIP_SAVAGE3D, "Savage3D" }, 151ab47cfaaSmrg { PCI_CHIP_SAVAGE3D_MV, "Savage3D-MV" }, 152ab47cfaaSmrg { PCI_CHIP_SAVAGE2000, "Savage2000" }, 153ab47cfaaSmrg { PCI_CHIP_SAVAGE_MX_MV, "Savage/MX-MV" }, 154ab47cfaaSmrg { PCI_CHIP_SAVAGE_MX, "Savage/MX" }, 155ab47cfaaSmrg { PCI_CHIP_SAVAGE_IX_MV, "Savage/IX-MV" }, 156ab47cfaaSmrg { PCI_CHIP_SAVAGE_IX, "Savage/IX" }, 157ab47cfaaSmrg { PCI_CHIP_PROSAVAGE_PM, "ProSavage PM133" }, 158ab47cfaaSmrg { PCI_CHIP_PROSAVAGE_KM, "ProSavage KM133" }, 159ab47cfaaSmrg { PCI_CHIP_S3TWISTER_P, "Twister PN133" }, 160ab47cfaaSmrg { PCI_CHIP_S3TWISTER_K, "Twister KN133" }, 161ab47cfaaSmrg { PCI_CHIP_SUPSAV_MX128, "SuperSavage/MX 128" }, 162ab47cfaaSmrg { PCI_CHIP_SUPSAV_MX64, "SuperSavage/MX 64" }, 163ab47cfaaSmrg { PCI_CHIP_SUPSAV_MX64C, "SuperSavage/MX 64C" }, 164ab47cfaaSmrg { PCI_CHIP_SUPSAV_IX128SDR, "SuperSavage/IX 128" }, 165ab47cfaaSmrg { PCI_CHIP_SUPSAV_IX128DDR, "SuperSavage/IX 128" }, 166ab47cfaaSmrg { PCI_CHIP_SUPSAV_IX64SDR, "SuperSavage/IX 64" }, 167ab47cfaaSmrg { PCI_CHIP_SUPSAV_IX64DDR, "SuperSavage/IX 64" }, 168ab47cfaaSmrg { PCI_CHIP_SUPSAV_IXCSDR, "SuperSavage/IXC 64" }, 169ab47cfaaSmrg { PCI_CHIP_SUPSAV_IXCDDR, "SuperSavage/IXC 64" }, 170ab47cfaaSmrg { PCI_CHIP_PROSAVAGE_DDR, "ProSavage DDR" }, 171ab47cfaaSmrg { PCI_CHIP_PROSAVAGE_DDRK, "ProSavage DDR-K" }, 172ab47cfaaSmrg { -1, NULL } 173ab47cfaaSmrg}; 174ab47cfaaSmrg 175ab47cfaaSmrgstatic SymTabRec SavageChipsets[] = { 176ab47cfaaSmrg { S3_SAVAGE3D, "Savage3D" }, 177ab47cfaaSmrg { S3_SAVAGE4, "Savage4" }, 178ab47cfaaSmrg { S3_SAVAGE2000, "Savage2000" }, 179ab47cfaaSmrg { S3_SAVAGE_MX, "MobileSavage" }, 180ab47cfaaSmrg { S3_PROSAVAGE, "ProSavage" }, 181ab47cfaaSmrg { S3_TWISTER, "Twister"}, 182ab47cfaaSmrg { S3_PROSAVAGEDDR, "ProSavageDDR"}, 183ab47cfaaSmrg { S3_SUPERSAVAGE, "SuperSavage" }, 184ab47cfaaSmrg { -1, NULL } 185ab47cfaaSmrg}; 186ab47cfaaSmrg 187ab47cfaaSmrg/* This table maps a PCI device ID to a chipset family identifier. */ 188ab47cfaaSmrg 189ab47cfaaSmrgstatic PciChipsets SavagePciChipsets[] = { 190ab47cfaaSmrg { S3_SAVAGE3D, PCI_CHIP_SAVAGE3D, RES_SHARED_VGA }, 191ab47cfaaSmrg { S3_SAVAGE3D, PCI_CHIP_SAVAGE3D_MV, RES_SHARED_VGA }, 192ab47cfaaSmrg { S3_SAVAGE4, PCI_CHIP_SAVAGE4, RES_SHARED_VGA }, 193ab47cfaaSmrg { S3_SAVAGE2000, PCI_CHIP_SAVAGE2000, RES_SHARED_VGA }, 194ab47cfaaSmrg { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_MX_MV, RES_SHARED_VGA }, 195ab47cfaaSmrg { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_MX, RES_SHARED_VGA }, 196ab47cfaaSmrg { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_IX_MV, RES_SHARED_VGA }, 197ab47cfaaSmrg { S3_SAVAGE_MX, PCI_CHIP_SAVAGE_IX, RES_SHARED_VGA }, 198ab47cfaaSmrg { S3_PROSAVAGE, PCI_CHIP_PROSAVAGE_PM, RES_SHARED_VGA }, 199ab47cfaaSmrg { S3_PROSAVAGE, PCI_CHIP_PROSAVAGE_KM, RES_SHARED_VGA }, 200ab47cfaaSmrg { S3_TWISTER, PCI_CHIP_S3TWISTER_P, RES_SHARED_VGA }, 201ab47cfaaSmrg { S3_TWISTER, PCI_CHIP_S3TWISTER_K, RES_SHARED_VGA }, 202ab47cfaaSmrg { S3_PROSAVAGEDDR, PCI_CHIP_PROSAVAGE_DDR, RES_SHARED_VGA }, 203ab47cfaaSmrg { S3_PROSAVAGEDDR, PCI_CHIP_PROSAVAGE_DDRK, RES_SHARED_VGA }, 204ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_MX128, RES_SHARED_VGA }, 205ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_MX64, RES_SHARED_VGA }, 206ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_MX64C, RES_SHARED_VGA }, 207ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX128SDR, RES_SHARED_VGA }, 208ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX128DDR, RES_SHARED_VGA }, 209ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX64SDR, RES_SHARED_VGA }, 210ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IX64DDR, RES_SHARED_VGA }, 211ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IXCSDR, RES_SHARED_VGA }, 212ab47cfaaSmrg { S3_SUPERSAVAGE, PCI_CHIP_SUPSAV_IXCDDR, RES_SHARED_VGA }, 213ab47cfaaSmrg { -1, -1, RES_UNDEFINED } 214ab47cfaaSmrg}; 215ab47cfaaSmrg 216ab47cfaaSmrgtypedef enum { 217ab47cfaaSmrg OPTION_PCI_BURST 218ab47cfaaSmrg ,OPTION_PCI_RETRY 219ab47cfaaSmrg ,OPTION_NOACCEL 220ab47cfaaSmrg ,OPTION_ACCELMETHOD 221ab47cfaaSmrg ,OPTION_LCD_CENTER 222ab47cfaaSmrg ,OPTION_LCDCLOCK 223ab47cfaaSmrg ,OPTION_MCLK 224ab47cfaaSmrg ,OPTION_REFCLK 225ab47cfaaSmrg ,OPTION_SHOWCACHE 226ab47cfaaSmrg ,OPTION_SWCURSOR 227ab47cfaaSmrg ,OPTION_HWCURSOR 228ab47cfaaSmrg ,OPTION_SHADOW_FB 229ab47cfaaSmrg ,OPTION_ROTATE 230ab47cfaaSmrg ,OPTION_USEBIOS 231ab47cfaaSmrg ,OPTION_SHADOW_STATUS 232ab47cfaaSmrg ,OPTION_CRT_ONLY 233ab47cfaaSmrg ,OPTION_TV_ON 234ab47cfaaSmrg ,OPTION_TV_PAL 235ab47cfaaSmrg ,OPTION_FORCE_INIT 236ab47cfaaSmrg ,OPTION_OVERLAY 237ab47cfaaSmrg ,OPTION_T_KEY 238ab47cfaaSmrg ,OPTION_DISABLE_XVMC 239ab47cfaaSmrg ,OPTION_DISABLE_TILE 240ab47cfaaSmrg ,OPTION_DISABLE_COB 241ab47cfaaSmrg ,OPTION_BCI_FOR_XV 242ab47cfaaSmrg ,OPTION_DVI 243ab47cfaaSmrg ,OPTION_BUS_TYPE 244ab47cfaaSmrg ,OPTION_DMA_TYPE 245ab47cfaaSmrg ,OPTION_DMA_MODE 246ab47cfaaSmrg ,OPTION_AGP_MODE 247ab47cfaaSmrg ,OPTION_AGP_SIZE 248ab47cfaaSmrg ,OPTION_DRI 249ab47cfaaSmrg} SavageOpts; 250ab47cfaaSmrg 251ab47cfaaSmrg 252ab47cfaaSmrgstatic const OptionInfoRec SavageOptions[] = 253ab47cfaaSmrg{ 254ab47cfaaSmrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 255ab47cfaaSmrg { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, 256ab47cfaaSmrg { OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, 257ab47cfaaSmrg { OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE }, 258ab47cfaaSmrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 259ab47cfaaSmrg { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 260ab47cfaaSmrg { OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE }, 261ab47cfaaSmrg { OPTION_LCDCLOCK, "LCDClock", OPTV_FREQ, {0}, FALSE }, 262ab47cfaaSmrg { OPTION_SHADOW_STATUS, "ShadowStatus", OPTV_BOOLEAN, {0}, FALSE }, 263ab47cfaaSmrg { OPTION_CRT_ONLY, "CrtOnly", OPTV_BOOLEAN, {0}, FALSE }, 264ab47cfaaSmrg { OPTION_TV_ON, "TvOn", OPTV_BOOLEAN, {0}, FALSE }, 265ab47cfaaSmrg { OPTION_TV_PAL, "PAL", OPTV_BOOLEAN, {0}, FALSE }, 266ab47cfaaSmrg { OPTION_FORCE_INIT,"ForceInit", OPTV_BOOLEAN, {0}, FALSE }, 267ab47cfaaSmrg { OPTION_OVERLAY, "Overlay", OPTV_ANYSTR, {0}, FALSE }, 268ab47cfaaSmrg { OPTION_T_KEY, "TransparencyKey", OPTV_ANYSTR, {0}, FALSE }, 269ab47cfaaSmrg { OPTION_FORCE_INIT, "ForceInit", OPTV_BOOLEAN, {0}, FALSE }, 270ab47cfaaSmrg { OPTION_DISABLE_XVMC, "DisableXVMC", OPTV_BOOLEAN, {0}, FALSE }, 271ab47cfaaSmrg { OPTION_DISABLE_TILE, "DisableTile", OPTV_BOOLEAN, {0}, FALSE }, 272ab47cfaaSmrg { OPTION_DISABLE_COB, "DisableCOB", OPTV_BOOLEAN, {0}, FALSE }, 273ab47cfaaSmrg { OPTION_BCI_FOR_XV, "BCIforXv", OPTV_BOOLEAN, {0}, FALSE }, 274ab47cfaaSmrg { OPTION_DVI, "DVI", OPTV_BOOLEAN, {0}, FALSE }, 275ab47cfaaSmrg#ifdef XF86DRI 276ab47cfaaSmrg { OPTION_BUS_TYPE, "BusType", OPTV_ANYSTR, {0}, FALSE }, 277ab47cfaaSmrg { OPTION_DMA_TYPE, "DmaType", OPTV_ANYSTR, {0}, FALSE }, 278ab47cfaaSmrg { OPTION_DMA_MODE, "DmaMode", OPTV_ANYSTR, {0}, FALSE }, 279ab47cfaaSmrg { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, 280ab47cfaaSmrg { OPTION_AGP_SIZE, "AGPSize", OPTV_INTEGER, {0}, FALSE }, 281ab47cfaaSmrg { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, TRUE }, 282ab47cfaaSmrg#endif 283ab47cfaaSmrg { -1, NULL, OPTV_NONE, {0}, FALSE } 284ab47cfaaSmrg}; 285ab47cfaaSmrg 286ab47cfaaSmrg 287ab47cfaaSmrgstatic const char *vgaHWSymbols[] = { 288ab47cfaaSmrg "vgaHWBlankScreen", 289ab47cfaaSmrg "vgaHWCopyReg", 290ab47cfaaSmrg "vgaHWGetHWRec", 291ab47cfaaSmrg "vgaHWGetIOBase", 292ab47cfaaSmrg "vgaHWGetIndex", 293ab47cfaaSmrg "vgaHWInit", 294ab47cfaaSmrg "vgaHWLock", 295ab47cfaaSmrg "vgaHWProtect", 296ab47cfaaSmrg "vgaHWRestore", 297ab47cfaaSmrg "vgaHWSave", 298ab47cfaaSmrg "vgaHWSaveScreen", 299ab47cfaaSmrg "vgaHWSetMmioFuncs", 300ab47cfaaSmrg "vgaHWSetStdFuncs", 301ab47cfaaSmrg "vgaHWUnmapMem", 302ab47cfaaSmrg "vgaHWddc1SetSpeedWeak", 303ab47cfaaSmrg#if 0 304ab47cfaaSmrg "vgaHWFreeHWRec", 305ab47cfaaSmrg "vgaHWMapMem", 306ab47cfaaSmrg "vgaHWUnlock", 307ab47cfaaSmrg#endif 308ab47cfaaSmrg NULL 309ab47cfaaSmrg}; 310ab47cfaaSmrg 311ab47cfaaSmrg#ifdef XF86DRI 312ab47cfaaSmrgstatic const char *drmSymbols[] = { 313ab47cfaaSmrg "drmAvailable", 314ab47cfaaSmrg "drmAddBufs", 315ab47cfaaSmrg "drmAddMap", 316ab47cfaaSmrg "drmCtlInstHandler", 317ab47cfaaSmrg "drmGetInterruptFromBusID", 318ab47cfaaSmrg "drmFreeVersion", 319ab47cfaaSmrg "drmGetVersion", 320ab47cfaaSmrg "drmMap", 321ab47cfaaSmrg "drmUnmap", 322ab47cfaaSmrg "drmMapBufs", 323ab47cfaaSmrg "drmUnmapBufs", 324ab47cfaaSmrg "drmAgpAcquire", 325ab47cfaaSmrg "drmAgpRelease", 326ab47cfaaSmrg "drmAgpEnable", 327ab47cfaaSmrg "drmAgpAlloc", 328ab47cfaaSmrg "drmAgpFree", 329ab47cfaaSmrg "drmAgpBind", 330ab47cfaaSmrg "drmAgpUnbind", 331ab47cfaaSmrg "drmAgpGetMode", 332ab47cfaaSmrg "drmAgpBase", 333ab47cfaaSmrg "drmAgpSize", 334ab47cfaaSmrg "drmAgpVendorId", 335ab47cfaaSmrg "drmAgpDeviceId", 336ab47cfaaSmrg "drmMGAInitDMA", 337ab47cfaaSmrg "drmMGACleanupDMA", 338ab47cfaaSmrg "drmMGAFlushDMA", 339ab47cfaaSmrg "drmMGAEngineReset", 340ab47cfaaSmrg NULL 341ab47cfaaSmrg}; 342ab47cfaaSmrg 343ab47cfaaSmrgstatic const char *driSymbols[] = { 344ab47cfaaSmrg "DRIGetDrawableIndex", 345ab47cfaaSmrg "DRIFinishScreenInit", 346ab47cfaaSmrg "DRIDestroyInfoRec", 347ab47cfaaSmrg "DRICloseScreen", 348ab47cfaaSmrg "DRIDestroyInfoRec", 349ab47cfaaSmrg "DRIScreenInit", 350ab47cfaaSmrg "DRIDestroyInfoRec", 351ab47cfaaSmrg "DRICreateInfoRec", 352ab47cfaaSmrg "DRILock", 353ab47cfaaSmrg "DRIUnlock", 354ab47cfaaSmrg "DRIGetSAREAPrivate", 355ab47cfaaSmrg "DRIGetContext", 356ab47cfaaSmrg "DRIQueryVersion", 357ab47cfaaSmrg "DRIAdjustFrame", 358ab47cfaaSmrg "DRIOpenFullScreen", 359ab47cfaaSmrg "DRICloseFullScreen", 360ab47cfaaSmrg "GlxSetVisualConfigs", 361ab47cfaaSmrg NULL 362ab47cfaaSmrg}; 363ab47cfaaSmrg#endif 364ab47cfaaSmrg 365ab47cfaaSmrg 366ab47cfaaSmrgstatic const char *ramdacSymbols[] = { 367ab47cfaaSmrg "xf86CreateCursorInfoRec", 368ab47cfaaSmrg#if 0 369ab47cfaaSmrg "xf86DestroyCursorInfoRec", 370ab47cfaaSmrg#endif 371ab47cfaaSmrg "xf86InitCursor", 372ab47cfaaSmrg NULL 373ab47cfaaSmrg}; 374ab47cfaaSmrg 375ab47cfaaSmrgstatic const char *int10Symbols[] = { 376ab47cfaaSmrg "xf86ExecX86int10", 377ab47cfaaSmrg "xf86Int10AllocPages", 378ab47cfaaSmrg "xf86int10Addr", 379ab47cfaaSmrg "xf86Int10FreePages" 380ab47cfaaSmrg}; 381ab47cfaaSmrg 382ab47cfaaSmrgstatic const char *vbeSymbols[] = { 383ab47cfaaSmrg "VBEInit", 384ab47cfaaSmrg "vbeDoEDID", 385ab47cfaaSmrg#if 0 386ab47cfaaSmrg "vbeFree", 387ab47cfaaSmrg#endif 388ab47cfaaSmrg NULL 389ab47cfaaSmrg}; 390ab47cfaaSmrg 391ab47cfaaSmrgstatic const char *vbeOptSymbols[] = { 392ab47cfaaSmrg "vbeModeInit", 393ab47cfaaSmrg "VBESetVBEMode", 394ab47cfaaSmrg "VBEGetVBEInfo", 395ab47cfaaSmrg "VBEFreeVBEInfo", 396ab47cfaaSmrg NULL 397ab47cfaaSmrg}; 398ab47cfaaSmrg 399ab47cfaaSmrgstatic const char *ddcSymbols[] = { 400ab47cfaaSmrg "xf86DoEDID_DDC1", 401ab47cfaaSmrg "xf86DoEDID_DDC2", 402ab47cfaaSmrg "xf86PrintEDID", 403ab47cfaaSmrg "xf86SetDDCproperties", 404ab47cfaaSmrg NULL 405ab47cfaaSmrg}; 406ab47cfaaSmrg 407ab47cfaaSmrgstatic const char *i2cSymbols[] = { 408ab47cfaaSmrg "xf86CreateI2CBusRec", 409ab47cfaaSmrg "xf86I2CBusInit", 410ab47cfaaSmrg "xf86CreateI2CDevRec", 411ab47cfaaSmrg "xf86I2CDevInit", 412ab47cfaaSmrg "xf86I2CWriteByte", 413ab47cfaaSmrg "xf86I2CWriteBytes", 414ab47cfaaSmrg "xf86I2CReadByte", 415ab47cfaaSmrg "xf86I2CReadBytes", 416ab47cfaaSmrg "xf86I2CWriteRead", 417ab47cfaaSmrg "xf86DestroyI2CDevRec", 418ab47cfaaSmrg NULL 419ab47cfaaSmrg}; 420ab47cfaaSmrg 421ab47cfaaSmrgstatic const char *xaaSymbols[] = { 422ab47cfaaSmrg "XAAGetCopyROP", 423ab47cfaaSmrg "XAAGetCopyROP_PM", 424ab47cfaaSmrg "XAACreateInfoRec", 425ab47cfaaSmrg "XAADestroyInfoRec", 426ab47cfaaSmrg "XAAFillSolidRects", 427ab47cfaaSmrg "XAAHelpPatternROP", 428ab47cfaaSmrg "XAAHelpSolidROP", 429ab47cfaaSmrg "XAAInit", 430ab47cfaaSmrg "XAAScreenIndex", 431ab47cfaaSmrg NULL 432ab47cfaaSmrg}; 433ab47cfaaSmrg 434ab47cfaaSmrgstatic const char *exaSymbols[] = { 435ab47cfaaSmrg "exaDriverAlloc", 436ab47cfaaSmrg "exaDriverInit", 437ab47cfaaSmrg "exaDriverFini", 438ab47cfaaSmrg "exaOffscreenAlloc", 439ab47cfaaSmrg "exaOffscreenFree", 440ab47cfaaSmrg "exaGetPixmapOffset", 441ab47cfaaSmrg "exaGetPixmapPitch", 442ab47cfaaSmrg "exaGetPixmapSize", 443ab47cfaaSmrg NULL 444ab47cfaaSmrg}; 445ab47cfaaSmrg 446ab47cfaaSmrgstatic const char *shadowSymbols[] = { 447ab47cfaaSmrg "ShadowFBInit", 448ab47cfaaSmrg NULL 449ab47cfaaSmrg}; 450ab47cfaaSmrg 451ab47cfaaSmrgstatic const char *fbSymbols[] = { 452ab47cfaaSmrg "fbPictureInit", 453ab47cfaaSmrg "fbScreenInit", 454ab47cfaaSmrg NULL 455ab47cfaaSmrg}; 456ab47cfaaSmrg 457ab47cfaaSmrg#ifdef XFree86LOADER 458ab47cfaaSmrg 459ab47cfaaSmrgstatic MODULESETUPPROTO(SavageSetup); 460ab47cfaaSmrg 461ab47cfaaSmrgstatic XF86ModuleVersionInfo SavageVersRec = { 462ab47cfaaSmrg "savage", 463ab47cfaaSmrg MODULEVENDORSTRING, 464ab47cfaaSmrg MODINFOSTRING1, 465ab47cfaaSmrg MODINFOSTRING2, 466ab47cfaaSmrg XORG_VERSION_CURRENT, 467ab47cfaaSmrg SAVAGE_VERSION_MAJOR, SAVAGE_VERSION_MINOR, SAVAGE_PATCHLEVEL, 468ab47cfaaSmrg ABI_CLASS_VIDEODRV, 469ab47cfaaSmrg ABI_VIDEODRV_VERSION, 470ab47cfaaSmrg MOD_CLASS_VIDEODRV, 471ab47cfaaSmrg {0, 0, 0, 0} 472ab47cfaaSmrg}; 473ab47cfaaSmrg 474ab47cfaaSmrg_X_EXPORT XF86ModuleData savageModuleData = { 475ab47cfaaSmrg &SavageVersRec, 476ab47cfaaSmrg SavageSetup, 477ab47cfaaSmrg NULL 478ab47cfaaSmrg}; 479ab47cfaaSmrg 480ab47cfaaSmrgstatic pointer SavageSetup(pointer module, pointer opts, int *errmaj, 481ab47cfaaSmrg int *errmin) 482ab47cfaaSmrg{ 483ab47cfaaSmrg static Bool setupDone = FALSE; 484ab47cfaaSmrg 485ab47cfaaSmrg if (!setupDone) { 486ab47cfaaSmrg setupDone = TRUE; 487ab47cfaaSmrg xf86AddDriver(&SAVAGE, module, 1); 488ab47cfaaSmrg LoaderRefSymLists(vgaHWSymbols, fbSymbols, ramdacSymbols, 489ab47cfaaSmrg xaaSymbols, 490ab47cfaaSmrg exaSymbols, 491ab47cfaaSmrg shadowSymbols, vbeSymbols, vbeOptSymbols, 492ab47cfaaSmrg#ifdef XF86DRI 493ab47cfaaSmrg drmSymbols, driSymbols, 494ab47cfaaSmrg#endif 495ab47cfaaSmrg int10Symbols, i2cSymbols, ddcSymbols, NULL); 496ab47cfaaSmrg return (pointer) 1; 497ab47cfaaSmrg } else { 498ab47cfaaSmrg if (errmaj) 499ab47cfaaSmrg *errmaj = LDR_ONCEONLY; 500ab47cfaaSmrg return NULL; 501ab47cfaaSmrg } 502ab47cfaaSmrg} 503ab47cfaaSmrg 504ab47cfaaSmrg#endif /* XFree86LOADER */ 505ab47cfaaSmrg 506ab47cfaaSmrgstatic SavageEntPtr SavageEntPriv(ScrnInfoPtr pScrn) 507ab47cfaaSmrg{ 508ab47cfaaSmrg DevUnion *pPriv; 509ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 510ab47cfaaSmrg pPriv = xf86GetEntityPrivate(psav->pEnt->index, 511ab47cfaaSmrg gSavageEntityIndex); 512ab47cfaaSmrg return pPriv->ptr; 513ab47cfaaSmrg} 514ab47cfaaSmrg 515ab47cfaaSmrg 516ab47cfaaSmrg/* 517ab47cfaaSmrg * I'd rather have these wait macros be inline, but S3 has made it 518ab47cfaaSmrg * darned near impossible. The bit fields are in a different place in 519ab47cfaaSmrg * all three families, the status register has a different address in the 520ab47cfaaSmrg * three families, and even the idle vs busy sense flipped in the Sav2K. 521ab47cfaaSmrg */ 522ab47cfaaSmrg 523ab47cfaaSmrgstatic void 524ab47cfaaSmrgResetBCI2K( SavagePtr psav ) 525ab47cfaaSmrg{ 526ab47cfaaSmrg CARD32 cob = INREG( 0x48c18 ); 527ab47cfaaSmrg /* if BCI is enabled and BCI is busy... */ 528ab47cfaaSmrg 529ab47cfaaSmrg if( 530ab47cfaaSmrg (cob & 0x00000008) && 531ab47cfaaSmrg ! (ALT_STATUS_WORD0 & 0x00200000) 532ab47cfaaSmrg ) 533ab47cfaaSmrg { 534ab47cfaaSmrg ErrorF( "Resetting BCI, stat = %08lx...\n", 535ab47cfaaSmrg (unsigned long) ALT_STATUS_WORD0); 536ab47cfaaSmrg /* Turn off BCI */ 537ab47cfaaSmrg OUTREG( 0x48c18, cob & ~8 ); 538ab47cfaaSmrg usleep(10000); 539ab47cfaaSmrg /* Turn it back on */ 540ab47cfaaSmrg OUTREG( 0x48c18, cob ); 541ab47cfaaSmrg usleep(10000); 542ab47cfaaSmrg } 543ab47cfaaSmrg} 544ab47cfaaSmrg 545ab47cfaaSmrgstatic Bool 546ab47cfaaSmrgShadowWait( SavagePtr psav ) 547ab47cfaaSmrg{ 548ab47cfaaSmrg BCI_GET_PTR; 549ab47cfaaSmrg int loop = 0; 550ab47cfaaSmrg 551ab47cfaaSmrg if( !psav->NoPCIRetry ) 552ab47cfaaSmrg return 0; 553ab47cfaaSmrg 554ab47cfaaSmrg psav->ShadowCounter = (psav->ShadowCounter + 1) & 0xffff; 555ab47cfaaSmrg if (psav->ShadowCounter == 0) 556ab47cfaaSmrg psav->ShadowCounter++; /* 0 is reserved for the BIOS 557ab47cfaaSmrg to avoid confusion in the DRM */ 558ab47cfaaSmrg BCI_SEND( psav->dwBCIWait2DIdle ); 559ab47cfaaSmrg BCI_SEND( 0x98000000 + psav->ShadowCounter ); 560ab47cfaaSmrg 561ab47cfaaSmrg while( 562ab47cfaaSmrg (int)(psav->ShadowVirtual[psav->eventStatusReg] & 0xffff) != 563ab47cfaaSmrg psav->ShadowCounter && (loop++ < MAXLOOP) 564ab47cfaaSmrg ) 565ab47cfaaSmrg ; 566ab47cfaaSmrg 567ab47cfaaSmrg return loop >= MAXLOOP; 568ab47cfaaSmrg} 569ab47cfaaSmrg 570ab47cfaaSmrgstatic Bool 571ab47cfaaSmrgShadowWaitQueue( SavagePtr psav, int v ) 572ab47cfaaSmrg{ 573ab47cfaaSmrg int loop = 0; 574ab47cfaaSmrg CARD32 slots = MAXFIFO - v; 575ab47cfaaSmrg 576ab47cfaaSmrg if (slots >= psav->bciThresholdHi) 577ab47cfaaSmrg slots = psav->bciThresholdHi; 578ab47cfaaSmrg else 579ab47cfaaSmrg return ShadowWait( psav ); 580ab47cfaaSmrg 581ab47cfaaSmrg /* Savage 2000 reports only entries filled in the COB, not the on-chip 582ab47cfaaSmrg * queue. Also it reports in qword units instead of dwords. */ 583ab47cfaaSmrg if (psav->Chipset == S3_SAVAGE2000) 584ab47cfaaSmrg slots = (slots - 32) / 4; 585ab47cfaaSmrg 586ab47cfaaSmrg while( ((psav->ShadowVirtual[0] & psav->bciUsedMask) >= slots) && (loop++ < MAXLOOP)) 587ab47cfaaSmrg ; 588ab47cfaaSmrg 589ab47cfaaSmrg return loop >= MAXLOOP; 590ab47cfaaSmrg} 591ab47cfaaSmrg 592ab47cfaaSmrg/* Wait until "v" queue entries are free */ 593ab47cfaaSmrg 594ab47cfaaSmrgstatic int 595ab47cfaaSmrgWaitQueue3D( SavagePtr psav, int v ) 596ab47cfaaSmrg{ 597ab47cfaaSmrg int loop = 0; 598ab47cfaaSmrg CARD32 slots = MAXFIFO - v; 599ab47cfaaSmrg 600ab47cfaaSmrg mem_barrier(); 601ab47cfaaSmrg if( psav->ShadowVirtual ) 602ab47cfaaSmrg { 603ab47cfaaSmrg psav->WaitQueue = ShadowWaitQueue; 604ab47cfaaSmrg return ShadowWaitQueue(psav, v); 605ab47cfaaSmrg } 606ab47cfaaSmrg else 607ab47cfaaSmrg { 608ab47cfaaSmrg loop &= STATUS_WORD0; 609ab47cfaaSmrg while( ((STATUS_WORD0 & 0x0000ffff) > slots) && (loop++ < MAXLOOP)) 610ab47cfaaSmrg ; 611ab47cfaaSmrg } 612ab47cfaaSmrg return loop >= MAXLOOP; 613ab47cfaaSmrg} 614ab47cfaaSmrg 615ab47cfaaSmrgstatic int 616ab47cfaaSmrgWaitQueue4( SavagePtr psav, int v ) 617ab47cfaaSmrg{ 618ab47cfaaSmrg int loop = 0; 619ab47cfaaSmrg CARD32 slots = MAXFIFO - v; 620ab47cfaaSmrg 621ab47cfaaSmrg if( !psav->NoPCIRetry ) 622ab47cfaaSmrg return 0; 623ab47cfaaSmrg mem_barrier(); 624ab47cfaaSmrg if( psav->ShadowVirtual ) 625ab47cfaaSmrg { 626ab47cfaaSmrg psav->WaitQueue = ShadowWaitQueue; 627ab47cfaaSmrg return ShadowWaitQueue(psav, v); 628ab47cfaaSmrg } 629ab47cfaaSmrg else 630ab47cfaaSmrg while( ((ALT_STATUS_WORD0 & 0x001fffff) > slots) && (loop++ < MAXLOOP)); 631ab47cfaaSmrg return loop >= MAXLOOP; 632ab47cfaaSmrg} 633ab47cfaaSmrg 634ab47cfaaSmrgstatic int 635ab47cfaaSmrgWaitQueue2K( SavagePtr psav, int v ) 636ab47cfaaSmrg{ 637ab47cfaaSmrg int loop = 0; 638ab47cfaaSmrg CARD32 slots = (MAXFIFO - v) / 4; 639ab47cfaaSmrg 640ab47cfaaSmrg if( !psav->NoPCIRetry ) 641ab47cfaaSmrg return 0; 642ab47cfaaSmrg mem_barrier(); 643ab47cfaaSmrg if( psav->ShadowVirtual ) 644ab47cfaaSmrg { 645ab47cfaaSmrg psav->WaitQueue = ShadowWaitQueue; 646ab47cfaaSmrg return ShadowWaitQueue(psav, v); 647ab47cfaaSmrg } 648ab47cfaaSmrg else 649ab47cfaaSmrg while( ((ALT_STATUS_WORD0 & 0x000fffff) > slots) && (loop++ < MAXLOOP)) 650ab47cfaaSmrg ; 651ab47cfaaSmrg if( loop >= MAXLOOP ) 652ab47cfaaSmrg ResetBCI2K(psav); 653ab47cfaaSmrg return loop >= MAXLOOP; 654ab47cfaaSmrg} 655ab47cfaaSmrg 656ab47cfaaSmrg/* Wait until GP is idle and queue is empty */ 657ab47cfaaSmrg 658ab47cfaaSmrgstatic int 659ab47cfaaSmrgWaitIdleEmpty3D(SavagePtr psav) 660ab47cfaaSmrg{ 661ab47cfaaSmrg int loop = 0; 662ab47cfaaSmrg mem_barrier(); 663ab47cfaaSmrg if( psav->ShadowVirtual ) 664ab47cfaaSmrg { 665ab47cfaaSmrg psav->WaitIdleEmpty = ShadowWait; 666ab47cfaaSmrg return ShadowWait(psav); 667ab47cfaaSmrg } 668ab47cfaaSmrg loop &= STATUS_WORD0; 669ab47cfaaSmrg while( ((STATUS_WORD0 & 0x0008ffff) != 0x80000) && (loop++ < MAXLOOP) ); 670ab47cfaaSmrg return loop >= MAXLOOP; 671ab47cfaaSmrg} 672ab47cfaaSmrg 673ab47cfaaSmrgstatic int 674ab47cfaaSmrgWaitIdleEmpty4(SavagePtr psav) 675ab47cfaaSmrg{ 676ab47cfaaSmrg int loop = 0; 677ab47cfaaSmrg mem_barrier(); 678ab47cfaaSmrg if( psav->ShadowVirtual ) 679ab47cfaaSmrg { 680ab47cfaaSmrg psav->WaitIdleEmpty = ShadowWait; 681ab47cfaaSmrg return ShadowWait(psav); 682ab47cfaaSmrg } 683ab47cfaaSmrg /* which is right?*/ 684ab47cfaaSmrg /*while( ((ALT_STATUS_WORD0 & 0x00a1ffff) != 0x00a00000) && (loop++ < MAXLOOP) );*/ /* tim */ 685ab47cfaaSmrg while (((ALT_STATUS_WORD0 & 0x00e1ffff) != 0x00e00000) && (loop++ < MAXLOOP)); /* S3 */ 686ab47cfaaSmrg return loop >= MAXLOOP; 687ab47cfaaSmrg} 688ab47cfaaSmrg 689ab47cfaaSmrgstatic int 690ab47cfaaSmrgWaitIdleEmpty2K(SavagePtr psav) 691ab47cfaaSmrg{ 692ab47cfaaSmrg int loop = 0; 693ab47cfaaSmrg mem_barrier(); 694ab47cfaaSmrg if( psav->ShadowVirtual ) 695ab47cfaaSmrg { 696ab47cfaaSmrg psav->WaitIdleEmpty = ShadowWait; 697ab47cfaaSmrg return ShadowWait(psav); 698ab47cfaaSmrg } 699ab47cfaaSmrg loop &= ALT_STATUS_WORD0; 700ab47cfaaSmrg while( ((ALT_STATUS_WORD0 & 0x009fffff) != 0) && (loop++ < MAXLOOP) ); 701ab47cfaaSmrg if( loop >= MAXLOOP ) 702ab47cfaaSmrg ResetBCI2K(psav); 703ab47cfaaSmrg return loop >= MAXLOOP; 704ab47cfaaSmrg} 705ab47cfaaSmrg 706ab47cfaaSmrg/* Wait until GP is idle */ 707ab47cfaaSmrg 708ab47cfaaSmrgstatic int 709ab47cfaaSmrgWaitIdle3D(SavagePtr psav) 710ab47cfaaSmrg{ 711ab47cfaaSmrg int loop = 0; 712ab47cfaaSmrg mem_barrier(); 713ab47cfaaSmrg if( psav->ShadowVirtual ) 714ab47cfaaSmrg { 715ab47cfaaSmrg psav->WaitIdle = ShadowWait; 716ab47cfaaSmrg return ShadowWait(psav); 717ab47cfaaSmrg } 718ab47cfaaSmrg while( (!(STATUS_WORD0 & 0x00080000)) && (loop++ < MAXLOOP) ); 719ab47cfaaSmrg return loop >= MAXLOOP; 720ab47cfaaSmrg} 721ab47cfaaSmrg 722ab47cfaaSmrgstatic int 723ab47cfaaSmrgWaitIdle4(SavagePtr psav) 724ab47cfaaSmrg{ 725ab47cfaaSmrg int loop = 0; 726ab47cfaaSmrg mem_barrier(); 727ab47cfaaSmrg if( psav->ShadowVirtual ) 728ab47cfaaSmrg { 729ab47cfaaSmrg psav->WaitIdle = ShadowWait; 730ab47cfaaSmrg return ShadowWait(psav); 731ab47cfaaSmrg } 732ab47cfaaSmrg /* which is right?*/ 733ab47cfaaSmrg /*while( (!(ALT_STATUS_WORD0 & 0x00800000)) && (loop++ < MAXLOOP) );*/ /* tim */ 734ab47cfaaSmrg while (((ALT_STATUS_WORD0 & 0x00E00000)!=0x00E00000) && (loop++ < MAXLOOP)); /* S3 */ 735ab47cfaaSmrg return loop >= MAXLOOP; 736ab47cfaaSmrg} 737ab47cfaaSmrg 738ab47cfaaSmrgstatic int 739ab47cfaaSmrgWaitIdle2K(SavagePtr psav) 740ab47cfaaSmrg{ 741ab47cfaaSmrg int loop = 0; 742ab47cfaaSmrg mem_barrier(); 743ab47cfaaSmrg if( psav->ShadowVirtual ) 744ab47cfaaSmrg { 745ab47cfaaSmrg psav->WaitIdle = ShadowWait; 746ab47cfaaSmrg return ShadowWait(psav); 747ab47cfaaSmrg } 748ab47cfaaSmrg loop &= ALT_STATUS_WORD0; 749ab47cfaaSmrg while( (ALT_STATUS_WORD0 & 0x00900000) && (loop++ < MAXLOOP) ); 750ab47cfaaSmrg return loop >= MAXLOOP; 751ab47cfaaSmrg} 752ab47cfaaSmrg 753ab47cfaaSmrg 754ab47cfaaSmrgstatic Bool SavageGetRec(ScrnInfoPtr pScrn) 755ab47cfaaSmrg{ 756ab47cfaaSmrg if (pScrn->driverPrivate) 757ab47cfaaSmrg return TRUE; 758ab47cfaaSmrg 759ab47cfaaSmrg pScrn->driverPrivate = xnfcalloc(sizeof(SavageRec), 1); 760ab47cfaaSmrg return TRUE; 761ab47cfaaSmrg} 762ab47cfaaSmrg 763ab47cfaaSmrg 764ab47cfaaSmrgstatic void SavageFreeRec(ScrnInfoPtr pScrn) 765ab47cfaaSmrg{ 766ab47cfaaSmrg TRACE(( "SavageFreeRec(%x)\n", pScrn->driverPrivate )); 767ab47cfaaSmrg if (!pScrn->driverPrivate) 768ab47cfaaSmrg return; 769ab47cfaaSmrg SavageUnmapMem(pScrn, 1); 770ab47cfaaSmrg xfree(pScrn->driverPrivate); 771ab47cfaaSmrg pScrn->driverPrivate = NULL; 772ab47cfaaSmrg} 773ab47cfaaSmrg 774ab47cfaaSmrg 775ab47cfaaSmrgstatic const OptionInfoRec * SavageAvailableOptions(int chipid, int busid) 776ab47cfaaSmrg{ 777ab47cfaaSmrg return SavageOptions; 778ab47cfaaSmrg} 779ab47cfaaSmrg 780ab47cfaaSmrg 781ab47cfaaSmrgstatic void SavageIdentify(int flags) 782ab47cfaaSmrg{ 783ab47cfaaSmrg xf86PrintChipsets("SAVAGE", 784ab47cfaaSmrg "driver (version " SAVAGE_DRIVER_VERSION ") for S3 Savage chipsets", 785ab47cfaaSmrg SavageChips); 786ab47cfaaSmrg} 787ab47cfaaSmrg 788ab47cfaaSmrg 789ab47cfaaSmrgstatic Bool SavageProbe(DriverPtr drv, int flags) 790ab47cfaaSmrg{ 791ab47cfaaSmrg int i; 792ab47cfaaSmrg GDevPtr *devSections = NULL; 793ab47cfaaSmrg int *usedChips; 794ab47cfaaSmrg int numDevSections; 795ab47cfaaSmrg int numUsed; 796ab47cfaaSmrg Bool foundScreen = FALSE; 797ab47cfaaSmrg 798ab47cfaaSmrg /* sanity checks */ 799ab47cfaaSmrg if ((numDevSections = xf86MatchDevice("savage", &devSections)) <= 0) 800ab47cfaaSmrg return FALSE; 801ab47cfaaSmrg if (xf86GetPciVideoInfo() == NULL) { 802ab47cfaaSmrg if (devSections) 803ab47cfaaSmrg xfree(devSections); 804ab47cfaaSmrg return FALSE; 805ab47cfaaSmrg } 806ab47cfaaSmrg 807ab47cfaaSmrg numUsed = xf86MatchPciInstances("SAVAGE", PCI_VENDOR_S3, 808ab47cfaaSmrg SavageChipsets, SavagePciChipsets, 809ab47cfaaSmrg devSections, numDevSections, drv, 810ab47cfaaSmrg &usedChips); 811ab47cfaaSmrg if (devSections) 812ab47cfaaSmrg xfree(devSections); 813ab47cfaaSmrg devSections = NULL; 814ab47cfaaSmrg if (numUsed <= 0) 815ab47cfaaSmrg return FALSE; 816ab47cfaaSmrg 817ab47cfaaSmrg if (flags & PROBE_DETECT) 818ab47cfaaSmrg foundScreen = TRUE; 819ab47cfaaSmrg else 820ab47cfaaSmrg for (i=0; i<numUsed; i++) { 821ab47cfaaSmrg EntityInfoPtr pEnt = xf86GetEntityInfo(usedChips[i]);; 822ab47cfaaSmrg ScrnInfoPtr pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], 823ab47cfaaSmrg NULL, RES_SHARED_VGA, 824ab47cfaaSmrg NULL, NULL, NULL, NULL); 825ab47cfaaSmrg 826ab47cfaaSmrg if (pScrn != NULL) { 827ab47cfaaSmrg pScrn->driverVersion = SAVAGE_VERSION; 828ab47cfaaSmrg pScrn->driverName = SAVAGE_DRIVER_NAME; 829ab47cfaaSmrg pScrn->name = "SAVAGE"; 830ab47cfaaSmrg pScrn->Probe = SavageProbe; 831ab47cfaaSmrg pScrn->PreInit = SavagePreInit; 832ab47cfaaSmrg pScrn->ScreenInit = SavageScreenInit; 833ab47cfaaSmrg pScrn->SwitchMode = SavageSwitchMode; 834ab47cfaaSmrg pScrn->AdjustFrame = SavageAdjustFrame; 835ab47cfaaSmrg pScrn->EnterVT = SavageEnterVT; 836ab47cfaaSmrg pScrn->LeaveVT = SavageLeaveVT; 837ab47cfaaSmrg pScrn->FreeScreen = NULL; 838ab47cfaaSmrg pScrn->ValidMode = SavageValidMode; 839ab47cfaaSmrg foundScreen = TRUE; 840ab47cfaaSmrg } 841ab47cfaaSmrg 842ab47cfaaSmrg pEnt = xf86GetEntityInfo(usedChips[i]); 843ab47cfaaSmrg 844ab47cfaaSmrg /* MX, IX, SuperSavage cards support Dual-Head, mark the entity as sharable*/ 845ab47cfaaSmrg if(pEnt->chipset == S3_SAVAGE_MX || pEnt->chipset == S3_SUPERSAVAGE) 846ab47cfaaSmrg { 847ab47cfaaSmrg DevUnion *pPriv; 848ab47cfaaSmrg SavageEntPtr pSavageEnt; 849ab47cfaaSmrg 850ab47cfaaSmrg xf86SetEntitySharable(usedChips[i]); 851ab47cfaaSmrg 852ab47cfaaSmrg if (gSavageEntityIndex == -1) 853ab47cfaaSmrg gSavageEntityIndex = xf86AllocateEntityPrivateIndex(); 854ab47cfaaSmrg 855ab47cfaaSmrg pPriv = xf86GetEntityPrivate(pEnt->index, 856ab47cfaaSmrg gSavageEntityIndex); 857ab47cfaaSmrg 858ab47cfaaSmrg if (!pPriv->ptr) { 859ab47cfaaSmrg int j; 860ab47cfaaSmrg int instance = xf86GetNumEntityInstances(pEnt->index); 861ab47cfaaSmrg 862ab47cfaaSmrg for (j = 0; j < instance; j++) 863ab47cfaaSmrg xf86SetEntityInstanceForScreen(pScrn, pEnt->index, j); 864ab47cfaaSmrg 865ab47cfaaSmrg pPriv->ptr = xnfcalloc(sizeof(SavageEntRec), 1); 866ab47cfaaSmrg pSavageEnt = pPriv->ptr; 867ab47cfaaSmrg pSavageEnt->HasSecondary = FALSE; 868ab47cfaaSmrg } else { 869ab47cfaaSmrg pSavageEnt = pPriv->ptr; 870ab47cfaaSmrg pSavageEnt->HasSecondary = TRUE; 871ab47cfaaSmrg } 872ab47cfaaSmrg } 873ab47cfaaSmrg xfree(pEnt); 874ab47cfaaSmrg } 875ab47cfaaSmrg 876ab47cfaaSmrg 877ab47cfaaSmrg xfree(usedChips); 878ab47cfaaSmrg return foundScreen; 879ab47cfaaSmrg} 880ab47cfaaSmrg 881ab47cfaaSmrgstatic int LookupChipID( PciChipsets* pset, int ChipID ) 882ab47cfaaSmrg{ 883ab47cfaaSmrg /* Is there a function to do this for me? */ 884ab47cfaaSmrg while( pset->numChipset >= 0 ) 885ab47cfaaSmrg { 886ab47cfaaSmrg if( pset->PCIid == ChipID ) 887ab47cfaaSmrg return pset->numChipset; 888ab47cfaaSmrg pset++; 889ab47cfaaSmrg } 890ab47cfaaSmrg 891ab47cfaaSmrg return -1; 892ab47cfaaSmrg} 893ab47cfaaSmrg 894ab47cfaaSmrgstatic void SavageDoDDC(ScrnInfoPtr pScrn) 895ab47cfaaSmrg{ 896ab47cfaaSmrg SavagePtr psav= SAVPTR(pScrn); 897ab47cfaaSmrg pointer ddc; 898ab47cfaaSmrg 899ab47cfaaSmrg /* Do the DDC dance. */ /* S3/VIA's DDC code */ 900ab47cfaaSmrg ddc = xf86LoadSubModule(pScrn, "ddc"); 901ab47cfaaSmrg if (ddc) { 902ab47cfaaSmrg xf86LoaderReqSymLists(ddcSymbols, NULL); 903ab47cfaaSmrg switch( psav->Chipset ) { 904ab47cfaaSmrg case S3_SAVAGE3D: 905ab47cfaaSmrg case S3_SAVAGE_MX: 906ab47cfaaSmrg case S3_SUPERSAVAGE: 907ab47cfaaSmrg case S3_SAVAGE2000: 908ab47cfaaSmrg psav->DDCPort = 0xAA; 909ab47cfaaSmrg psav->I2CPort = 0xA0; 910ab47cfaaSmrg break; 911ab47cfaaSmrg 912ab47cfaaSmrg case S3_SAVAGE4: 913ab47cfaaSmrg case S3_PROSAVAGE: 914ab47cfaaSmrg case S3_TWISTER: 915ab47cfaaSmrg case S3_PROSAVAGEDDR: 916ab47cfaaSmrg psav->DDCPort = 0xB1; 917ab47cfaaSmrg psav->I2CPort = 0xA0; 918ab47cfaaSmrg break; 919ab47cfaaSmrg } 920ab47cfaaSmrg 921ab47cfaaSmrg if (!SavageDDC1(pScrn->scrnIndex)) { 922ab47cfaaSmrg /* DDC1 failed,switch to DDC2 */ 923ab47cfaaSmrg if (xf86LoadSubModule(pScrn, "i2c")) { 924ab47cfaaSmrg xf86LoaderReqSymLists(i2cSymbols,NULL); 925ab47cfaaSmrg if (SavageI2CInit(pScrn)) { 926ab47cfaaSmrg unsigned char tmp; 927ab47cfaaSmrg 928ab47cfaaSmrg InI2CREG(tmp,psav->DDCPort); 929ab47cfaaSmrg OutI2CREG(tmp | 0x13,psav->DDCPort); 930ab47cfaaSmrg xf86SetDDCproperties(pScrn,xf86PrintEDID( 931ab47cfaaSmrg xf86DoEDID_DDC2(pScrn->scrnIndex,psav->I2C))); 932ab47cfaaSmrg OutI2CREG(tmp,psav->DDCPort); 933ab47cfaaSmrg } 934ab47cfaaSmrg } 935ab47cfaaSmrg } 936ab47cfaaSmrg } 937ab47cfaaSmrg} 938ab47cfaaSmrg 939ab47cfaaSmrg/* Copied from ddc/Property.c via nv */ 940ab47cfaaSmrgstatic DisplayModePtr 941ab47cfaaSmrgSavageModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) 942ab47cfaaSmrg{ 943ab47cfaaSmrg if (!Modes) { 944ab47cfaaSmrg if (Additions) 945ab47cfaaSmrg return Additions; 946ab47cfaaSmrg else 947ab47cfaaSmrg return NULL; 948ab47cfaaSmrg } 949ab47cfaaSmrg 950ab47cfaaSmrg if (Additions) { 951ab47cfaaSmrg DisplayModePtr Mode = Modes; 952ab47cfaaSmrg 953ab47cfaaSmrg while (Mode->next) 954ab47cfaaSmrg Mode = Mode->next; 955ab47cfaaSmrg 956ab47cfaaSmrg Mode->next = Additions; 957ab47cfaaSmrg Additions->prev = Mode; 958ab47cfaaSmrg } 959ab47cfaaSmrg 960ab47cfaaSmrg return Modes; 961ab47cfaaSmrg} 962ab47cfaaSmrg 963ab47cfaaSmrg/* borrowed from nv */ 964ab47cfaaSmrgstatic void 965ab47cfaaSmrgSavageAddPanelMode(ScrnInfoPtr pScrn) 966ab47cfaaSmrg{ 967ab47cfaaSmrg SavagePtr psav= SAVPTR(pScrn); 968ab47cfaaSmrg DisplayModePtr Mode = NULL; 969ab47cfaaSmrg 970ab47cfaaSmrg Mode = xf86CVTMode(psav->PanelX, psav->PanelY, 60.00, TRUE, FALSE); 971ab47cfaaSmrg Mode->type = M_T_DRIVER | M_T_PREFERRED; 972ab47cfaaSmrg pScrn->monitor->Modes = SavageModesAdd(pScrn->monitor->Modes, Mode); 973ab47cfaaSmrg 974ab47cfaaSmrg if ((pScrn->monitor->nHsync == 0) && 975ab47cfaaSmrg (pScrn->monitor->nVrefresh == 0)) { 976ab47cfaaSmrg if (!Mode->HSync) 977ab47cfaaSmrg Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); 978ab47cfaaSmrg if (!Mode->VRefresh) 979ab47cfaaSmrg Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / 980ab47cfaaSmrg ((float) (Mode->HTotal * Mode->VTotal)); 981ab47cfaaSmrg 982ab47cfaaSmrg if (Mode->HSync < pScrn->monitor->hsync[0].lo) 983ab47cfaaSmrg pScrn->monitor->hsync[0].lo = Mode->HSync; 984ab47cfaaSmrg if (Mode->HSync > pScrn->monitor->hsync[0].hi) 985ab47cfaaSmrg pScrn->monitor->hsync[0].hi = Mode->HSync; 986ab47cfaaSmrg if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo) 987ab47cfaaSmrg pScrn->monitor->vrefresh[0].lo = Mode->VRefresh; 988ab47cfaaSmrg if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi) 989ab47cfaaSmrg pScrn->monitor->vrefresh[0].hi = Mode->VRefresh; 990ab47cfaaSmrg 991ab47cfaaSmrg pScrn->monitor->nHsync = 1; 992ab47cfaaSmrg pScrn->monitor->nVrefresh = 1; 993ab47cfaaSmrg } 994ab47cfaaSmrg} 995ab47cfaaSmrg 996ab47cfaaSmrgstatic void SavageGetPanelInfo(ScrnInfoPtr pScrn) 997ab47cfaaSmrg{ 998ab47cfaaSmrg SavagePtr psav= SAVPTR(pScrn); 999ab47cfaaSmrg vgaHWPtr hwp; 1000ab47cfaaSmrg unsigned char cr6b; 1001ab47cfaaSmrg int panelX, panelY; 1002ab47cfaaSmrg char * sTechnology = "Unknown"; 1003ab47cfaaSmrg enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */ 1004ab47cfaaSmrg ActiveCRT = 0x01, 1005ab47cfaaSmrg ActiveLCD = 0x02, 1006ab47cfaaSmrg ActiveTV = 0x04, 1007ab47cfaaSmrg ActiveCRT2 = 0x20, 1008ab47cfaaSmrg ActiveDUO = 0x80 1009ab47cfaaSmrg }; 1010ab47cfaaSmrg 1011ab47cfaaSmrg hwp = VGAHWPTR(pScrn); 1012ab47cfaaSmrg 1013ab47cfaaSmrg /* Check LCD panel information */ 1014ab47cfaaSmrg 1015ab47cfaaSmrg cr6b = hwp->readCrtc( hwp, 0x6b ); 1016ab47cfaaSmrg 1017ab47cfaaSmrg panelX = (hwp->readSeq(hwp, 0x61) + 1018ab47cfaaSmrg ((hwp->readSeq(hwp, 0x66) & 0x02) << 7) + 1) * 8; 1019ab47cfaaSmrg panelY = hwp->readSeq(hwp, 0x69) + 1020ab47cfaaSmrg ((hwp->readSeq(hwp, 0x6e) & 0x70) << 4) + 1; 1021ab47cfaaSmrg 1022ab47cfaaSmrg 1023ab47cfaaSmrg /* OK, I admit it. I don't know how to limit the max dot clock 1024ab47cfaaSmrg * for LCD panels of various sizes. I thought I copied the formula 1025ab47cfaaSmrg * from the BIOS, but many users have informed me of my folly. 1026ab47cfaaSmrg * 1027ab47cfaaSmrg * Instead, I'll abandon any attempt to automatically limit the 1028ab47cfaaSmrg * clock, and add an LCDClock option to XF86Config. Some day, 1029ab47cfaaSmrg * I should come back to this. 1030ab47cfaaSmrg */ 1031ab47cfaaSmrg 1032ab47cfaaSmrg 1033ab47cfaaSmrg if( (hwp->readSeq( hwp, 0x39 ) & 0x03) == 0 ) 1034ab47cfaaSmrg { 1035ab47cfaaSmrg sTechnology = "TFT"; 1036ab47cfaaSmrg } 1037ab47cfaaSmrg else if( (hwp->readSeq( hwp, 0x30 ) & 0x01) == 0 ) 1038ab47cfaaSmrg { 1039ab47cfaaSmrg sTechnology = "DSTN"; 1040ab47cfaaSmrg } 1041ab47cfaaSmrg else 1042ab47cfaaSmrg { 1043ab47cfaaSmrg sTechnology = "STN"; 1044ab47cfaaSmrg } 1045ab47cfaaSmrg 1046ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1047ab47cfaaSmrg "%dx%d %s LCD panel detected %s\n", 1048ab47cfaaSmrg panelX, panelY, sTechnology, 1049ab47cfaaSmrg cr6b & ActiveLCD ? "and active" : "but not active"); 1050ab47cfaaSmrg 1051ab47cfaaSmrg if( cr6b & ActiveLCD ) { 1052ab47cfaaSmrg /* If the LCD is active and panel expansion is enabled, */ 1053ab47cfaaSmrg /* we probably want to kill the HW cursor. */ 1054ab47cfaaSmrg 1055ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1056ab47cfaaSmrg "- Limiting video mode to %dx%d\n", 1057ab47cfaaSmrg panelX, panelY ); 1058ab47cfaaSmrg 1059ab47cfaaSmrg psav->PanelX = panelX; 1060ab47cfaaSmrg psav->PanelY = panelY; 1061ab47cfaaSmrg 1062ab47cfaaSmrg if( psav->LCDClock > 0.0 ) 1063ab47cfaaSmrg { 1064ab47cfaaSmrg psav->maxClock = psav->LCDClock * 1000.0; 1065ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1066ab47cfaaSmrg "- Limiting dot clock to %1.2f MHz\n", 1067ab47cfaaSmrg psav->LCDClock ); 1068ab47cfaaSmrg } 1069ab47cfaaSmrg } else { 1070ab47cfaaSmrg psav->DisplayType = MT_CRT; 1071ab47cfaaSmrg } 1072ab47cfaaSmrg} 1073ab47cfaaSmrg 1074ab47cfaaSmrg 1075ab47cfaaSmrgstatic Bool SavagePreInit(ScrnInfoPtr pScrn, int flags) 1076ab47cfaaSmrg{ 1077ab47cfaaSmrg EntityInfoPtr pEnt; 1078ab47cfaaSmrg SavagePtr psav; 1079ab47cfaaSmrg MessageType from = X_DEFAULT; 1080ab47cfaaSmrg int i; 1081ab47cfaaSmrg ClockRangePtr clockRanges; 1082ab47cfaaSmrg char *s = NULL; 1083ab47cfaaSmrg unsigned char config1, m, n, n1, n2, sr8, cr66 = 0, tmp; 1084ab47cfaaSmrg int mclk; 1085ab47cfaaSmrg vgaHWPtr hwp; 1086ab47cfaaSmrg int vgaCRIndex, vgaCRReg; 1087ab47cfaaSmrg Bool dvi; 1088ab47cfaaSmrg 1089ab47cfaaSmrg TRACE(("SavagePreInit(%d)\n", flags)); 1090ab47cfaaSmrg 1091ab47cfaaSmrg gpScrn = pScrn; 1092ab47cfaaSmrg 1093ab47cfaaSmrg if (flags & PROBE_DETECT) { 1094ab47cfaaSmrg SavageProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 1095ab47cfaaSmrg return TRUE; 1096ab47cfaaSmrg } 1097ab47cfaaSmrg 1098ab47cfaaSmrg if (!xf86LoadSubModule(pScrn, "vgahw")) 1099ab47cfaaSmrg return FALSE; 1100ab47cfaaSmrg 1101ab47cfaaSmrg xf86LoaderReqSymLists(vgaHWSymbols, NULL); 1102ab47cfaaSmrg if (!vgaHWGetHWRec(pScrn)) 1103ab47cfaaSmrg return FALSE; 1104ab47cfaaSmrg 1105ab47cfaaSmrg#if 0 1106ab47cfaaSmrg /* Here we can alter the number of registers saved and restored by the 1107ab47cfaaSmrg * standard vgaHWSave and Restore routines. 1108ab47cfaaSmrg */ 1109ab47cfaaSmrg vgaHWSetRegCounts( pScrn, VGA_NUM_CRTC, VGA_NUM_SEQ, VGA_NUM_GFX, VGA_NUM_ATTR ); 1110ab47cfaaSmrg#endif 1111ab47cfaaSmrg 1112ab47cfaaSmrg pScrn->monitor = pScrn->confScreen->monitor; 1113ab47cfaaSmrg 1114ab47cfaaSmrg /* 1115ab47cfaaSmrg * We support depths of 8, 15, 16 and 24. 1116ab47cfaaSmrg * We support bpp of 8, 16, and 32. 1117ab47cfaaSmrg */ 1118ab47cfaaSmrg 1119ab47cfaaSmrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 1120ab47cfaaSmrg return FALSE; 1121ab47cfaaSmrg else { 1122ab47cfaaSmrg int requiredBpp; 1123ab47cfaaSmrg int altBpp = 0; 1124ab47cfaaSmrg 1125ab47cfaaSmrg switch (pScrn->depth) { 1126ab47cfaaSmrg case 8: 1127ab47cfaaSmrg case 16: 1128ab47cfaaSmrg requiredBpp = pScrn->depth; 1129ab47cfaaSmrg break; 1130ab47cfaaSmrg case 15: 1131ab47cfaaSmrg requiredBpp = 16; 1132ab47cfaaSmrg break; 1133ab47cfaaSmrg case 24: 1134ab47cfaaSmrg requiredBpp = 32; 1135ab47cfaaSmrg altBpp = 24; 1136ab47cfaaSmrg break; 1137ab47cfaaSmrg 1138ab47cfaaSmrg default: 1139ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1140ab47cfaaSmrg "Given depth (%d) is not supported by this driver\n", 1141ab47cfaaSmrg pScrn->depth); 1142ab47cfaaSmrg return FALSE; 1143ab47cfaaSmrg } 1144ab47cfaaSmrg 1145ab47cfaaSmrg if( 1146ab47cfaaSmrg (pScrn->bitsPerPixel != requiredBpp) && 1147ab47cfaaSmrg (pScrn->bitsPerPixel != altBpp) 1148ab47cfaaSmrg ) { 1149ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1150ab47cfaaSmrg "Depth %d must specify %d bpp; %d was given\n", 1151ab47cfaaSmrg pScrn->depth, requiredBpp, pScrn->bitsPerPixel ); 1152ab47cfaaSmrg return FALSE; 1153ab47cfaaSmrg } 1154ab47cfaaSmrg } 1155ab47cfaaSmrg 1156ab47cfaaSmrg xf86PrintDepthBpp(pScrn); 1157ab47cfaaSmrg 1158ab47cfaaSmrg if (pScrn->depth > 8) { 1159ab47cfaaSmrg rgb zeros = {0, 0, 0}; 1160ab47cfaaSmrg 1161ab47cfaaSmrg if (!xf86SetWeight(pScrn, zeros, zeros)) 1162ab47cfaaSmrg return FALSE; 1163ab47cfaaSmrg else { 1164ab47cfaaSmrg /* TODO check weight returned is supported */ 1165ab47cfaaSmrg ; 1166ab47cfaaSmrg } 1167ab47cfaaSmrg } 1168ab47cfaaSmrg 1169ab47cfaaSmrg if (!xf86SetDefaultVisual(pScrn, -1)) { 1170ab47cfaaSmrg return FALSE; 1171ab47cfaaSmrg } else { 1172ab47cfaaSmrg /* We don't currently support DirectColor at 16bpp */ 1173ab47cfaaSmrg if (pScrn->bitsPerPixel == 16 && pScrn->defaultVisual != TrueColor) { 1174ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 1175ab47cfaaSmrg " (%s) is not supported at depth %d\n", 1176ab47cfaaSmrg xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 1177ab47cfaaSmrg return FALSE; 1178ab47cfaaSmrg } 1179ab47cfaaSmrg } 1180ab47cfaaSmrg 1181ab47cfaaSmrg pScrn->progClock = TRUE; 1182ab47cfaaSmrg 1183ab47cfaaSmrg if (!SavageGetRec(pScrn)) 1184ab47cfaaSmrg return FALSE; 1185ab47cfaaSmrg psav = SAVPTR(pScrn); 1186ab47cfaaSmrg 1187ab47cfaaSmrg hwp = VGAHWPTR(pScrn); 1188ab47cfaaSmrg vgaHWGetIOBase(hwp); 1189ab47cfaaSmrg psav->vgaIOBase = hwp->IOBase; 1190ab47cfaaSmrg 1191ab47cfaaSmrg xf86CollectOptions(pScrn, NULL); 1192ab47cfaaSmrg 1193ab47cfaaSmrg if (pScrn->depth == 8) 1194ab47cfaaSmrg pScrn->rgbBits = 8; 1195ab47cfaaSmrg 1196ab47cfaaSmrg if (!(psav->Options = xalloc(sizeof(SavageOptions)))) 1197ab47cfaaSmrg return FALSE; 1198ab47cfaaSmrg memcpy(psav->Options, SavageOptions, sizeof(SavageOptions)); 1199ab47cfaaSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, psav->Options); 1200ab47cfaaSmrg 1201ab47cfaaSmrg xf86GetOptValBool(psav->Options, OPTION_PCI_BURST, &psav->pci_burst); 1202ab47cfaaSmrg 1203ab47cfaaSmrg if (psav->pci_burst) { 1204ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1205ab47cfaaSmrg "Option: pci_burst - PCI burst read enabled\n"); 1206ab47cfaaSmrg } 1207ab47cfaaSmrg 1208ab47cfaaSmrg psav->NoPCIRetry = 1; /* default */ 1209ab47cfaaSmrg if (xf86ReturnOptValBool(psav->Options, OPTION_PCI_RETRY, FALSE)) { 1210ab47cfaaSmrg if (xf86ReturnOptValBool(psav->Options, OPTION_PCI_BURST, FALSE)) { 1211ab47cfaaSmrg psav->NoPCIRetry = 0; 1212ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n"); 1213ab47cfaaSmrg } else 1214ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires \"pci_burst\"\n"); 1215ab47cfaaSmrg } 1216ab47cfaaSmrg 1217ab47cfaaSmrg xf86GetOptValBool( psav->Options, OPTION_SHADOW_FB, &psav->shadowFB ); 1218ab47cfaaSmrg if (psav->shadowFB) { 1219ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n"); 1220ab47cfaaSmrg } 1221ab47cfaaSmrg 1222ab47cfaaSmrg psav->primStreamBpp = pScrn->bitsPerPixel; 1223ab47cfaaSmrg 1224ab47cfaaSmrg if ((s = xf86GetOptValString(psav->Options, OPTION_ROTATE))) { 1225ab47cfaaSmrg if(!xf86NameCmp(s, "CW")) { 1226ab47cfaaSmrg /* accel is disabled below for shadowFB */ 1227ab47cfaaSmrg /* RandR is disabled when the Rotate option is used (does 1228ab47cfaaSmrg * not work well together and scrambles the screen) */ 1229ab47cfaaSmrg 1230ab47cfaaSmrg psav->shadowFB = TRUE; 1231ab47cfaaSmrg psav->rotate = 1; 1232ab47cfaaSmrg xf86DisableRandR(); 1233ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1234ab47cfaaSmrg "Rotating screen clockwise" 1235ab47cfaaSmrg "- acceleration and RandR disabled\n"); 1236ab47cfaaSmrg } else if(!xf86NameCmp(s, "CCW")) { 1237ab47cfaaSmrg psav->shadowFB = TRUE; 1238ab47cfaaSmrg psav->rotate = -1; 1239ab47cfaaSmrg xf86DisableRandR(); 1240ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1241ab47cfaaSmrg "Rotating screen counter clockwise" 1242ab47cfaaSmrg " - acceleration and RandR disabled\n"); 1243ab47cfaaSmrg 1244ab47cfaaSmrg } else { 1245ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 1246ab47cfaaSmrg "value for Option \"Rotate\"\n", s); 1247ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1248ab47cfaaSmrg "Valid options are \"CW\" or \"CCW\"\n"); 1249ab47cfaaSmrg } 1250ab47cfaaSmrg } 1251ab47cfaaSmrg 1252ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_NOACCEL, &psav->NoAccel)) 1253ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1254ab47cfaaSmrg "Option: NoAccel - Acceleration Disabled\n"); 1255ab47cfaaSmrg 1256ab47cfaaSmrg if (psav->shadowFB && !psav->NoAccel) { 1257ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1258ab47cfaaSmrg "HW acceleration not supported with \"shadowFB\".\n"); 1259ab47cfaaSmrg psav->NoAccel = TRUE; 1260ab47cfaaSmrg } 1261ab47cfaaSmrg 1262ab47cfaaSmrg if(!psav->NoAccel) { 1263ab47cfaaSmrg from = X_DEFAULT; 1264ab47cfaaSmrg char *strptr; 1265ab47cfaaSmrg if((strptr = (char *)xf86GetOptValString(psav->Options, OPTION_ACCELMETHOD))) { 1266ab47cfaaSmrg if(!xf86NameCmp(strptr,"XAA")) { 1267ab47cfaaSmrg from = X_CONFIG; 1268ab47cfaaSmrg psav->useEXA = FALSE; 1269ab47cfaaSmrg } else if(!xf86NameCmp(strptr,"EXA")) { 1270ab47cfaaSmrg from = X_CONFIG; 1271ab47cfaaSmrg psav->useEXA = TRUE; 1272ab47cfaaSmrg } 1273ab47cfaaSmrg } 1274ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n", 1275ab47cfaaSmrg psav->useEXA ? "EXA" : "XAA"); 1276ab47cfaaSmrg } 1277ab47cfaaSmrg 1278ab47cfaaSmrg if ((s = xf86GetOptValString(psav->Options, OPTION_OVERLAY))) { 1279ab47cfaaSmrg 1280ab47cfaaSmrg if (psav->shadowFB) { 1281ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1282ab47cfaaSmrg "Option \"Overlay\" not supported with shadowFB\n"); 1283ab47cfaaSmrg } else { 1284ab47cfaaSmrg if (pScrn->depth == 8) { 1285ab47cfaaSmrg if (!*s || !xf86NameCmp(s, "24")) { 1286ab47cfaaSmrg psav->overlayDepth = 24; 1287ab47cfaaSmrg psav->NoAccel = TRUE; /* Preliminary */ 1288ab47cfaaSmrg pScrn->colorKey = TRANSPARENCY_KEY; 1289ab47cfaaSmrg pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1290ab47cfaaSmrg } else if (!xf86NameCmp(s, "16")) { 1291ab47cfaaSmrg psav->overlayDepth = 16; 1292ab47cfaaSmrg psav->NoAccel = TRUE; /* Preliminary */ 1293ab47cfaaSmrg pScrn->colorKey = TRANSPARENCY_KEY; 1294ab47cfaaSmrg pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1295ab47cfaaSmrg } else { 1296ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: " 1297ab47cfaaSmrg "\"%s\" Ingnoring\n",s); 1298ab47cfaaSmrg } 1299ab47cfaaSmrg } else if (pScrn->depth != 15) { 1300ab47cfaaSmrg psav->overlayDepth = 8; 1301ab47cfaaSmrg psav->NoAccel = TRUE; /* Preliminary */ 1302ab47cfaaSmrg pScrn->colorKey = TRANSPARENCY_KEY; 1303ab47cfaaSmrg pScrn->overlayFlags = OVERLAY_8_32_DUALFB; 1304ab47cfaaSmrg if (*s && (xf86NameCmp(s, "8"))) 1305ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: " 1306ab47cfaaSmrg "\"%s\" for depth %i overlay depth must be 8\n", 1307ab47cfaaSmrg s,pScrn->depth); 1308ab47cfaaSmrg } else { 1309ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Overlay not " 1310ab47cfaaSmrg "supported for depth 15\n"); 1311ab47cfaaSmrg } 1312ab47cfaaSmrg if (psav->overlayDepth) { 1313ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"%i/%i Overlay enabled\n", 1314ab47cfaaSmrg pScrn->depth,psav->overlayDepth); 1315ab47cfaaSmrg psav->primStreamBpp = 8; 1316ab47cfaaSmrg } 1317ab47cfaaSmrg } 1318ab47cfaaSmrg } 1319ab47cfaaSmrg 1320ab47cfaaSmrg if (pScrn->bitsPerPixel == 24 && !psav->NoAccel) { 1321ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1322ab47cfaaSmrg "HW acceleration not possible with depth 32 and bpp 24.\n"); 1323ab47cfaaSmrg psav->NoAccel = TRUE; 1324ab47cfaaSmrg } 1325ab47cfaaSmrg 1326ab47cfaaSmrg /* 1327ab47cfaaSmrg * The SWCursor setting takes priority over HWCursor. The default 1328ab47cfaaSmrg * if neither is specified is HW, unless ShadowFB is specified, 1329ab47cfaaSmrg * then SW. 1330ab47cfaaSmrg */ 1331ab47cfaaSmrg 1332ab47cfaaSmrg from = X_DEFAULT; 1333ab47cfaaSmrg psav->hwcursor = psav->shadowFB ? FALSE : TRUE; 1334ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_HWCURSOR, &psav->hwcursor)) 1335ab47cfaaSmrg from = X_CONFIG; 1336ab47cfaaSmrg if (xf86ReturnOptValBool(psav->Options, OPTION_SWCURSOR, FALSE)) { 1337ab47cfaaSmrg psav->hwcursor = FALSE; 1338ab47cfaaSmrg from = X_CONFIG; 1339ab47cfaaSmrg } 1340ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 1341ab47cfaaSmrg psav->hwcursor ? "HW" : "SW"); 1342ab47cfaaSmrg 1343ab47cfaaSmrg from = X_DEFAULT; 1344ab47cfaaSmrg psav->UseBIOS = TRUE; 1345ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_USEBIOS, &psav->UseBIOS) ) 1346ab47cfaaSmrg from = X_CONFIG; 1347ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, "%ssing video BIOS to set modes\n", 1348ab47cfaaSmrg psav->UseBIOS ? "U" : "Not u" ); 1349ab47cfaaSmrg 1350ab47cfaaSmrg psav->LCDClock = 0.0; 1351ab47cfaaSmrg if( xf86GetOptValFreq( psav->Options, OPTION_LCDCLOCK, OPTUNITS_MHZ, &psav->LCDClock ) ) 1352ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1353ab47cfaaSmrg "Option: LCDClock %1.2f MHz\n", psav->LCDClock ); 1354ab47cfaaSmrg 1355ab47cfaaSmrg if( xf86GetOptValBool( psav->Options, OPTION_SHADOW_STATUS, &psav->ShadowStatus)) { 1356ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1357ab47cfaaSmrg "Option: ShadowStatus %sabled\n", psav->ShadowStatus ? "en" : "dis" ); 1358ab47cfaaSmrg psav->ForceShadowStatus = TRUE; 1359ab47cfaaSmrg } else 1360ab47cfaaSmrg psav->ForceShadowStatus = FALSE; 1361ab47cfaaSmrg /* If ShadowStatus is off it will be automatically enabled for DRI. 1362ab47cfaaSmrg * If DRI initialization fails fall back to ConfigShadowStatus. */ 1363ab47cfaaSmrg psav->ConfigShadowStatus = psav->ShadowStatus; 1364ab47cfaaSmrg 1365ab47cfaaSmrg if( xf86GetOptValBool( psav->Options, OPTION_CRT_ONLY, &psav->CrtOnly)) 1366ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1367ab47cfaaSmrg "Option: CrtOnly enabled\n" ); 1368ab47cfaaSmrg 1369ab47cfaaSmrg if( xf86GetOptValBool( psav->Options, OPTION_TV_ON, &psav->TvOn)) { 1370ab47cfaaSmrg psav->PAL = FALSE; 1371ab47cfaaSmrg SavageGetTvMaxSize(psav); 1372ab47cfaaSmrg } 1373ab47cfaaSmrg 1374ab47cfaaSmrg if( xf86GetOptValBool( psav->Options, OPTION_TV_PAL, &psav->PAL)) { 1375ab47cfaaSmrg SavageGetTvMaxSize(psav); 1376ab47cfaaSmrg psav->TvOn = TRUE; 1377ab47cfaaSmrg } 1378ab47cfaaSmrg 1379ab47cfaaSmrg if( psav->TvOn ) 1380ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1381ab47cfaaSmrg "TV enabled in %s format\n", 1382ab47cfaaSmrg psav->PAL ? "PAL" : "NTSC" ); 1383ab47cfaaSmrg 1384ab47cfaaSmrg psav->ForceInit = 0; 1385ab47cfaaSmrg if( xf86GetOptValBool( psav->Options, OPTION_FORCE_INIT, &psav->ForceInit)) 1386ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_CONFIG, 1387ab47cfaaSmrg "Option: ForceInit enabled\n" ); 1388ab47cfaaSmrg 1389ab47cfaaSmrg if (pScrn->numEntities > 1) { 1390ab47cfaaSmrg SavageFreeRec(pScrn); 1391ab47cfaaSmrg return FALSE; 1392ab47cfaaSmrg } 1393ab47cfaaSmrg 1394ab47cfaaSmrg pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 1395ab47cfaaSmrg if (pEnt->resources) { 1396ab47cfaaSmrg xfree(pEnt); 1397ab47cfaaSmrg SavageFreeRec(pScrn); 1398ab47cfaaSmrg return FALSE; 1399ab47cfaaSmrg } 1400ab47cfaaSmrg psav->EntityIndex = pEnt->index; 1401ab47cfaaSmrg 1402ab47cfaaSmrg if (xf86LoadSubModule(pScrn, "vbe")) { 1403ab47cfaaSmrg xf86LoaderReqSymLists(vbeSymbols, NULL); 1404ab47cfaaSmrg psav->pVbe = VBEInit(NULL, pEnt->index); 1405ab47cfaaSmrg } 1406ab47cfaaSmrg 1407ab47cfaaSmrg psav->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 1408ab47cfaaSmrg xf86RegisterResources(pEnt->index, NULL, ResNone); 1409ab47cfaaSmrg xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); 1410ab47cfaaSmrg xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); 1411ab47cfaaSmrg 1412ab47cfaaSmrg from = X_DEFAULT; 1413ab47cfaaSmrg if (pEnt->device->chipset && *pEnt->device->chipset) { 1414ab47cfaaSmrg pScrn->chipset = pEnt->device->chipset; 1415ab47cfaaSmrg psav->ChipId = pEnt->device->chipID; 1416ab47cfaaSmrg psav->Chipset = xf86StringToToken(SavageChipsets, pScrn->chipset); 1417ab47cfaaSmrg from = X_CONFIG; 1418ab47cfaaSmrg } else if (pEnt->device->chipID >= 0) { 1419ab47cfaaSmrg psav->ChipId = pEnt->device->chipID; 1420ab47cfaaSmrg psav->Chipset = LookupChipID(SavagePciChipsets, psav->ChipId); 1421ab47cfaaSmrg pScrn->chipset = (char *)xf86TokenToString(SavageChipsets, 1422ab47cfaaSmrg psav->Chipset); 1423ab47cfaaSmrg from = X_CONFIG; 1424ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 1425ab47cfaaSmrg pEnt->device->chipID); 1426ab47cfaaSmrg } else { 1427ab47cfaaSmrg from = X_PROBED; 1428ab47cfaaSmrg psav->ChipId = psav->PciInfo->chipType; 1429ab47cfaaSmrg psav->Chipset = LookupChipID(SavagePciChipsets, psav->ChipId); 1430ab47cfaaSmrg pScrn->chipset = (char *)xf86TokenToString(SavageChipsets, 1431ab47cfaaSmrg psav->Chipset); 1432ab47cfaaSmrg } 1433ab47cfaaSmrg 1434ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chip: id %04x, \"%s\"\n", 1435ab47cfaaSmrg psav->ChipId, xf86TokenToString( SavageChips, psav->ChipId ) ); 1436ab47cfaaSmrg 1437ab47cfaaSmrg if (pEnt->device->chipRev >= 0) { 1438ab47cfaaSmrg psav->ChipRev = pEnt->device->chipRev; 1439ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 1440ab47cfaaSmrg psav->ChipRev); 1441ab47cfaaSmrg } else 1442ab47cfaaSmrg psav->ChipRev = psav->PciInfo->chipRev; 1443ab47cfaaSmrg 1444ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Engine: \"%s\"\n", pScrn->chipset); 1445ab47cfaaSmrg 1446ab47cfaaSmrg if (pEnt->device->videoRam != 0) 1447ab47cfaaSmrg pScrn->videoRam = pEnt->device->videoRam; 1448ab47cfaaSmrg 1449ab47cfaaSmrg xfree(pEnt); 1450ab47cfaaSmrg 1451ab47cfaaSmrg psav->PciTag = pciTag(psav->PciInfo->bus, psav->PciInfo->device, 1452ab47cfaaSmrg psav->PciInfo->func); 1453ab47cfaaSmrg 1454ab47cfaaSmrg 1455ab47cfaaSmrg /* Set AGP Mode from config */ 1456ab47cfaaSmrg /* We support 1X 2X and 4X */ 1457ab47cfaaSmrg#ifdef XF86DRI 1458ab47cfaaSmrg /* AGP/PCI (FK: copied from radeon_driver.c) */ 1459ab47cfaaSmrg /* Proper autodetection of an AGP capable device requires examining 1460ab47cfaaSmrg * PCI config registers to determine if the device implements extended 1461ab47cfaaSmrg * PCI capabilities, and then walking the capability list as indicated 1462ab47cfaaSmrg * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP 1463ab47cfaaSmrg * capability is present. The procedure is outlined as follows: 1464ab47cfaaSmrg * 1465ab47cfaaSmrg * 1) Test bit 4 (CAP_LIST) of the PCI status register of the device 1466ab47cfaaSmrg * to determine wether or not this device implements any extended 1467ab47cfaaSmrg * capabilities. If this bit is zero, then the device is a PCI 2.1 1468ab47cfaaSmrg * or earlier device and is not AGP capable, and we can conclude it 1469ab47cfaaSmrg * to be a PCI device. 1470ab47cfaaSmrg * 1471ab47cfaaSmrg * 2) If bit 4 of the status register is set, then the device implements 1472ab47cfaaSmrg * extended capabilities. There is an 8 bit wide capabilities pointer 1473ab47cfaaSmrg * register located at offset 0x34 in PCI config space which points to 1474ab47cfaaSmrg * the first capability in a linked list of extended capabilities that 1475ab47cfaaSmrg * this device implements. The lower two bits of this register are 1476ab47cfaaSmrg * reserved and MBZ so must be masked out. 1477ab47cfaaSmrg * 1478ab47cfaaSmrg * 3) The extended capabilities list is formed by one or more extended 1479ab47cfaaSmrg * capabilities structures which are aligned on DWORD boundaries. 1480ab47cfaaSmrg * The first byte of the structure is the capability ID (CAP_ID) 1481ab47cfaaSmrg * indicating what extended capability this structure refers to. The 1482ab47cfaaSmrg * second byte of the structure is an offset from the beginning of 1483ab47cfaaSmrg * PCI config space pointing to the next capability in the linked 1484ab47cfaaSmrg * list (NEXT_PTR) or NULL (0x00) at the end of the list. The lower 1485ab47cfaaSmrg * two bits of this pointer are reserved and MBZ. By examining the 1486ab47cfaaSmrg * CAP_ID of each capability and walking through the list, we will 1487ab47cfaaSmrg * either find the AGP_CAP_ID (0x02) indicating this device is an 1488ab47cfaaSmrg * AGP device, or we'll reach the end of the list, indicating it is 1489ab47cfaaSmrg * a PCI device. 1490ab47cfaaSmrg * 1491ab47cfaaSmrg * Mike A. Harris <mharris@redhat.com> 1492ab47cfaaSmrg * 1493ab47cfaaSmrg * References: 1494ab47cfaaSmrg * - PCI Local Bus Specification Revision 2.2, Chapter 6 1495ab47cfaaSmrg * - AGP Interface Specification Revision 2.0, Section 6.1.5 1496ab47cfaaSmrg */ 1497ab47cfaaSmrg 1498ab47cfaaSmrg psav->IsPCI = TRUE; 1499ab47cfaaSmrg 1500ab47cfaaSmrg if (pciReadLong(psav->PciTag, PCI_CMD_STAT_REG) & SAVAGE_CAP_LIST) { 1501ab47cfaaSmrg CARD32 cap_ptr, cap_id; 1502ab47cfaaSmrg 1503ab47cfaaSmrg cap_ptr = pciReadLong(psav->PciTag, 1504ab47cfaaSmrg SAVAGE_CAPABILITIES_PTR_PCI_CONFIG) 1505ab47cfaaSmrg & SAVAGE_CAP_PTR_MASK; 1506ab47cfaaSmrg 1507ab47cfaaSmrg while(cap_ptr != SAVAGE_CAP_ID_NULL) { 1508ab47cfaaSmrg cap_id = pciReadLong(psav->PciTag, cap_ptr); 1509ab47cfaaSmrg if ((cap_id & 0xff) == SAVAGE_CAP_ID_AGP) { 1510ab47cfaaSmrg psav->IsPCI = FALSE; 1511ab47cfaaSmrg break; 1512ab47cfaaSmrg } 1513ab47cfaaSmrg cap_ptr = (cap_id >> 8) & SAVAGE_CAP_PTR_MASK; 1514ab47cfaaSmrg } 1515ab47cfaaSmrg } 1516ab47cfaaSmrg 1517ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%s card detected\n", 1518ab47cfaaSmrg (psav->IsPCI) ? "PCI" : "AGP"); 1519ab47cfaaSmrg 1520ab47cfaaSmrg if ((s = xf86GetOptValString(psav->Options, OPTION_BUS_TYPE))) { 1521ab47cfaaSmrg if (strcmp(s, "AGP") == 0) { 1522ab47cfaaSmrg if (psav->IsPCI) { 1523ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1524ab47cfaaSmrg "BusType AGP not available on PCI card\n"); 1525ab47cfaaSmrg } else { 1526ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to AGP\n"); 1527ab47cfaaSmrg } 1528ab47cfaaSmrg } else if (strcmp(s, "PCI") == 0) { 1529ab47cfaaSmrg psav->IsPCI = TRUE; 1530ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to PCI\n"); 1531ab47cfaaSmrg } else { 1532ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1533ab47cfaaSmrg "Invalid BusType option, using %s DMA\n", 1534ab47cfaaSmrg psav->IsPCI ? "PCI" : "AGP"); 1535ab47cfaaSmrg } 1536ab47cfaaSmrg } 1537ab47cfaaSmrg 1538ab47cfaaSmrg psav->AgpDMA = !psav->IsPCI; 1539ab47cfaaSmrg if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_TYPE))) { 1540ab47cfaaSmrg if (strcmp(s, "AGP") == 0) { 1541ab47cfaaSmrg if (psav->IsPCI) { 1542ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1543ab47cfaaSmrg "AGP DMA not available on PCI card, using PCI DMA\n"); 1544ab47cfaaSmrg } else { 1545ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using AGP DMA\n"); 1546ab47cfaaSmrg } 1547ab47cfaaSmrg } else if (strcmp(s, "PCI") == 0) { 1548ab47cfaaSmrg psav->AgpDMA = FALSE; 1549ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using PCI DMA\n"); 1550ab47cfaaSmrg } else { 1551ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1552ab47cfaaSmrg "Invalid DmaType option, using %s DMA\n", 1553ab47cfaaSmrg psav->AgpDMA ? "AGP" : "PCI"); 1554ab47cfaaSmrg } 1555ab47cfaaSmrg } else { 1556ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 1557ab47cfaaSmrg "Using %s DMA\n", psav->AgpDMA ? "AGP" : "PCI"); 1558ab47cfaaSmrg } 1559ab47cfaaSmrg 1560ab47cfaaSmrg psav->CommandDMA = TRUE; 1561ab47cfaaSmrg psav->VertexDMA = TRUE; 1562ab47cfaaSmrg from = X_DEFAULT; 1563ab47cfaaSmrg if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_MODE))) { 1564ab47cfaaSmrg from = X_CONFIG; 1565ab47cfaaSmrg if (strcmp(s, "Command") == 0) 1566ab47cfaaSmrg psav->VertexDMA = FALSE; 1567ab47cfaaSmrg else if (strcmp(s, "Vertex") == 0) 1568ab47cfaaSmrg psav->CommandDMA = FALSE; 1569ab47cfaaSmrg else if (strcmp(s, "None") == 0) 1570ab47cfaaSmrg psav->VertexDMA = psav->CommandDMA = FALSE; 1571ab47cfaaSmrg else if (strcmp(s, "Any") != 0) { 1572ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid DmaMode option\n"); 1573ab47cfaaSmrg from = X_DEFAULT; 1574ab47cfaaSmrg } 1575ab47cfaaSmrg } 1576ab47cfaaSmrg if (psav->CommandDMA && S3_SAVAGE3D_SERIES(psav->Chipset)) { 1577ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO, 1578ab47cfaaSmrg "Savage3D/MX/IX does not support command DMA.\n"); 1579ab47cfaaSmrg psav->CommandDMA = FALSE; 1580ab47cfaaSmrg } 1581ab47cfaaSmrg if ((psav->CommandDMA || psav->VertexDMA) && 1582ab47cfaaSmrg psav->Chipset == S3_SUPERSAVAGE) { 1583ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO, 1584ab47cfaaSmrg "DMA is not supported on SuperSavages.\n"); 1585ab47cfaaSmrg psav->CommandDMA = psav->VertexDMA = FALSE; 1586ab47cfaaSmrg } 1587ab47cfaaSmrg if (psav->CommandDMA && psav->VertexDMA) 1588ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, 1589ab47cfaaSmrg "Will try command and vertex DMA mode\n"); 1590ab47cfaaSmrg else if (psav->CommandDMA && !psav->VertexDMA) 1591ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, 1592ab47cfaaSmrg "Will try only command DMA mode\n"); 1593ab47cfaaSmrg else if (!psav->CommandDMA && psav->VertexDMA) 1594ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, 1595ab47cfaaSmrg "Will try only vertex DMA mode\n"); 1596ab47cfaaSmrg else 1597ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, 1598ab47cfaaSmrg "DMA disabled\n"); 1599ab47cfaaSmrg 1600ab47cfaaSmrg if (!psav->IsPCI) { 1601ab47cfaaSmrg from = X_DEFAULT; 1602ab47cfaaSmrg psav->agpMode = SAVAGE_DEFAULT_AGP_MODE; 1603ab47cfaaSmrg /*psav->agpMode = SAVAGE_MAX_AGP_MODE;*/ 1604ab47cfaaSmrg psav->agpSize = 16; 1605ab47cfaaSmrg 1606ab47cfaaSmrg if (xf86GetOptValInteger(psav->Options, 1607ab47cfaaSmrg OPTION_AGP_MODE, &(psav->agpMode))) { 1608ab47cfaaSmrg if (psav->agpMode < 1) { 1609ab47cfaaSmrg psav->agpMode = 1; 1610ab47cfaaSmrg } 1611ab47cfaaSmrg if (psav->agpMode > SAVAGE_MAX_AGP_MODE) { 1612ab47cfaaSmrg psav->agpMode = SAVAGE_MAX_AGP_MODE; 1613ab47cfaaSmrg } 1614ab47cfaaSmrg if ((psav->agpMode > 2) && 1615ab47cfaaSmrg (psav->Chipset == S3_SAVAGE3D || 1616ab47cfaaSmrg psav->Chipset == S3_SAVAGE_MX)) 1617ab47cfaaSmrg psav->agpMode = 2; /* old savages only support 2x */ 1618ab47cfaaSmrg from = X_CONFIG; 1619ab47cfaaSmrg } 1620ab47cfaaSmrg 1621ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n", 1622ab47cfaaSmrg psav->agpMode); 1623ab47cfaaSmrg 1624ab47cfaaSmrg from = X_DEFAULT; 1625ab47cfaaSmrg if (xf86GetOptValInteger(psav->Options, 1626ab47cfaaSmrg OPTION_AGP_SIZE, (int *)&(psav->agpSize))) { 1627ab47cfaaSmrg switch (psav->agpSize) { 1628ab47cfaaSmrg case 4: 1629ab47cfaaSmrg case 8: 1630ab47cfaaSmrg case 16: 1631ab47cfaaSmrg case 32: 1632ab47cfaaSmrg case 64: 1633ab47cfaaSmrg case 128: 1634ab47cfaaSmrg case 256: 1635ab47cfaaSmrg from = X_CONFIG; 1636ab47cfaaSmrg break; 1637ab47cfaaSmrg default: 1638ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1639ab47cfaaSmrg "Illegal AGP size: %d MB, defaulting to 16 MB\n", psav->agpSize); 1640ab47cfaaSmrg psav->agpSize = 16; 1641ab47cfaaSmrg } 1642ab47cfaaSmrg } 1643ab47cfaaSmrg 1644ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, from, 1645ab47cfaaSmrg "Using %d MB AGP aperture\n", psav->agpSize); 1646ab47cfaaSmrg } else { 1647ab47cfaaSmrg psav->agpMode = 0; 1648ab47cfaaSmrg psav->agpSize = 0; 1649ab47cfaaSmrg } 1650ab47cfaaSmrg 1651ab47cfaaSmrg#endif 1652ab47cfaaSmrg 1653ab47cfaaSmrg /* we can use Option "DisableTile TRUE" to disable tile mode */ 1654ab47cfaaSmrg psav->bDisableTile = FALSE; 1655ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_TILE,&psav->bDisableTile)) { 1656ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1657ab47cfaaSmrg "Option: %s Tile Mode and Program it \n",(psav->bDisableTile?"Disable":"Enable")); 1658ab47cfaaSmrg } 1659ab47cfaaSmrg 1660ab47cfaaSmrg#ifdef XF86DRI 1661ab47cfaaSmrg /* disabled by default...doesn't seem to work */ 1662ab47cfaaSmrg psav->bDisableXvMC = TRUE; /* if you want to free up more mem for DRI,etc. */ 1663ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_XVMC, &psav->bDisableXvMC)) { 1664ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1665ab47cfaaSmrg "Option: %s Hardware XvMC support\n",(psav->bDisableXvMC?"Disable":"Enable")); 1666ab47cfaaSmrg } 1667ab47cfaaSmrg#endif 1668ab47cfaaSmrg 1669ab47cfaaSmrg psav->disableCOB = FALSE; /* if you are having problems on savage4+ */ 1670ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_COB, &psav->disableCOB)) { 1671ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1672ab47cfaaSmrg "Option: %s the COB\n",(psav->disableCOB?"Disable":"Enable")); 1673ab47cfaaSmrg } 1674ab47cfaaSmrg if (psav->Chipset == S3_PROSAVAGE || 1675ab47cfaaSmrg psav->Chipset == S3_TWISTER || 1676ab47cfaaSmrg psav->Chipset == S3_PROSAVAGEDDR) 1677ab47cfaaSmrg psav->BCIforXv = TRUE; 1678ab47cfaaSmrg else 1679ab47cfaaSmrg psav->BCIforXv = FALSE; /* use the BCI for Xv */ 1680ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_BCI_FOR_XV, &psav->BCIforXv)) { 1681ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1682ab47cfaaSmrg "Option: %s use of the BCI for Xv\n",(psav->BCIforXv?"Enable":"Disable")); 1683ab47cfaaSmrg } 1684ab47cfaaSmrg psav->dvi = FALSE; 1685ab47cfaaSmrg if (xf86GetOptValBool(psav->Options, OPTION_DVI, &psav->dvi)) { 1686ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1687ab47cfaaSmrg "%s DVI port support (Savage4 only)\n",(psav->dvi?"Force":"Disable")); 1688ab47cfaaSmrg } 1689ab47cfaaSmrg 1690ab47cfaaSmrg /* Add more options here. */ 1691ab47cfaaSmrg 1692ab47cfaaSmrg 1693ab47cfaaSmrg psav = SAVPTR(pScrn); 1694ab47cfaaSmrg psav->IsSecondary = FALSE; 1695ab47cfaaSmrg psav->IsPrimary = FALSE; 1696ab47cfaaSmrg psav->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 1697ab47cfaaSmrg 1698ab47cfaaSmrg if (xf86IsEntityShared(psav->pEnt->index)) { 1699ab47cfaaSmrg if (xf86IsPrimInitDone(psav->pEnt->index)) { 1700ab47cfaaSmrg 1701ab47cfaaSmrg SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); 1702ab47cfaaSmrg 1703ab47cfaaSmrg psav->IsSecondary = TRUE; 1704ab47cfaaSmrg pSavageEnt->pSecondaryScrn = pScrn; 1705ab47cfaaSmrg psav->TvOn = pSavageEnt->TvOn; 1706ab47cfaaSmrg } else { 1707ab47cfaaSmrg SavageEntPtr pSavageEnt = SavageEntPriv(pScrn); 1708ab47cfaaSmrg 1709ab47cfaaSmrg xf86SetPrimInitDone(psav->pEnt->index); 1710ab47cfaaSmrg 1711ab47cfaaSmrg psav->IsPrimary = TRUE; 1712ab47cfaaSmrg pSavageEnt->pPrimaryScrn = pScrn; 1713ab47cfaaSmrg pSavageEnt->TvOn = psav->TvOn; 1714ab47cfaaSmrg } 1715ab47cfaaSmrg } 1716ab47cfaaSmrg 1717ab47cfaaSmrg switch(psav->Chipset) { 1718ab47cfaaSmrg case S3_SAVAGE_MX: 1719ab47cfaaSmrg case S3_SUPERSAVAGE: 1720ab47cfaaSmrg psav->HasCRTC2 = TRUE; 1721ab47cfaaSmrg break; 1722ab47cfaaSmrg default: 1723ab47cfaaSmrg psav->HasCRTC2 = FALSE; 1724ab47cfaaSmrg } 1725ab47cfaaSmrg 1726ab47cfaaSmrg if ((psav->IsSecondary || psav->IsPrimary) && !psav->UseBIOS) { 1727ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "BIOS currently required for Dualhead mode setting.\n"); 1728ab47cfaaSmrg return FALSE; 1729ab47cfaaSmrg } 1730ab47cfaaSmrg 1731ab47cfaaSmrg if (psav->IsSecondary && 1732ab47cfaaSmrg (pScrn->bitsPerPixel > 16) && 1733ab47cfaaSmrg !psav->NoAccel && 1734ab47cfaaSmrg (psav->Chipset == S3_SAVAGE_MX)) { 1735ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No acceleration in Dualhead mode at depth 24\n"); 1736ab47cfaaSmrg return FALSE; 1737ab47cfaaSmrg } 1738ab47cfaaSmrg 1739ab47cfaaSmrg /* maybe throw in some more sanity checks here */ 1740ab47cfaaSmrg 1741ab47cfaaSmrg if (!SavageMapMem(pScrn)) { 1742ab47cfaaSmrg SavageFreeRec(pScrn); 1743ab47cfaaSmrg vbeFree(psav->pVbe); 1744ab47cfaaSmrg psav->pVbe = NULL; 1745ab47cfaaSmrg return FALSE; 1746ab47cfaaSmrg } 1747ab47cfaaSmrg 1748ab47cfaaSmrg vgaCRIndex = psav->vgaIOBase + 4; 1749ab47cfaaSmrg vgaCRReg = psav->vgaIOBase + 5; 1750ab47cfaaSmrg 1751ab47cfaaSmrg xf86EnableIO(); 1752ab47cfaaSmrg /* unprotect CRTC[0-7] */ 1753ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x11); 1754ab47cfaaSmrg tmp = VGAIN8(vgaCRReg); 1755ab47cfaaSmrg VGAOUT8(vgaCRReg, tmp & 0x7f); 1756ab47cfaaSmrg 1757ab47cfaaSmrg /* unlock extended regs */ 1758ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x4838); 1759ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0xa039); 1760ab47cfaaSmrg VGAOUT16(0x3c4, 0x0608); 1761ab47cfaaSmrg 1762ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x40); 1763ab47cfaaSmrg tmp = VGAIN8(vgaCRReg); 1764ab47cfaaSmrg VGAOUT8(vgaCRReg, tmp & ~0x01); 1765ab47cfaaSmrg 1766ab47cfaaSmrg /* unlock sys regs */ 1767ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x38); 1768ab47cfaaSmrg VGAOUT8(vgaCRReg, 0x48); 1769ab47cfaaSmrg 1770ab47cfaaSmrg { 1771ab47cfaaSmrg Gamma zeros = {0.0, 0.0, 0.0}; 1772ab47cfaaSmrg 1773ab47cfaaSmrg if (!xf86SetGamma(pScrn, zeros)) { 1774ab47cfaaSmrg vbeFree(psav->pVbe); 1775ab47cfaaSmrg psav->pVbe = NULL; 1776ab47cfaaSmrg SavageFreeRec(pScrn); 1777ab47cfaaSmrg return FALSE; 1778ab47cfaaSmrg } 1779ab47cfaaSmrg } 1780ab47cfaaSmrg 1781ab47cfaaSmrg /* Unlock system registers. */ 1782ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x4838); 1783ab47cfaaSmrg 1784ab47cfaaSmrg /* Next go on to detect amount of installed ram */ 1785ab47cfaaSmrg 1786ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x36); /* for register CR36 (CONFG_REG1), */ 1787ab47cfaaSmrg config1 = VGAIN8(vgaCRReg); /* get amount of vram installed */ 1788ab47cfaaSmrg 1789ab47cfaaSmrg /* Compute the amount of video memory and offscreen memory. */ 1790ab47cfaaSmrg 1791ab47cfaaSmrg if (!pScrn->videoRam) { 1792ab47cfaaSmrg static const unsigned char RamSavage3D[] = { 8, 4, 4, 2 }; 1793ab47cfaaSmrg static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; 1794ab47cfaaSmrg static const unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; 1795ab47cfaaSmrg static const unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 }; 1796ab47cfaaSmrg 1797ab47cfaaSmrg switch( psav->Chipset ) { 1798ab47cfaaSmrg case S3_SAVAGE3D: 1799ab47cfaaSmrg pScrn->videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024; 1800ab47cfaaSmrg break; 1801ab47cfaaSmrg 1802ab47cfaaSmrg case S3_SAVAGE4: 1803ab47cfaaSmrg /* 1804ab47cfaaSmrg * The Savage4 has one ugly special case to consider. On 1805ab47cfaaSmrg * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB 1806ab47cfaaSmrg * when it really means 8MB. Why do it the same when you 1807ab47cfaaSmrg * can do it different... 1808ab47cfaaSmrg */ 1809ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x68); /* memory control 1 */ 1810ab47cfaaSmrg if( (VGAIN8(vgaCRReg) & 0xC0) == (0x01 << 6) ) 1811ab47cfaaSmrg RamSavage4[1] = 8; 1812ab47cfaaSmrg 1813ab47cfaaSmrg /*FALLTHROUGH*/ 1814ab47cfaaSmrg 1815ab47cfaaSmrg case S3_SAVAGE2000: 1816ab47cfaaSmrg pScrn->videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024; 1817ab47cfaaSmrg break; 1818ab47cfaaSmrg 1819ab47cfaaSmrg case S3_SAVAGE_MX: 1820ab47cfaaSmrg case S3_SUPERSAVAGE: 1821ab47cfaaSmrg pScrn->videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024; 1822ab47cfaaSmrg break; 1823ab47cfaaSmrg 1824ab47cfaaSmrg case S3_PROSAVAGE: 1825ab47cfaaSmrg case S3_PROSAVAGEDDR: 1826ab47cfaaSmrg case S3_TWISTER: 1827ab47cfaaSmrg pScrn->videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024; 1828ab47cfaaSmrg break; 1829ab47cfaaSmrg 1830ab47cfaaSmrg default: 1831ab47cfaaSmrg /* How did we get here? */ 1832ab47cfaaSmrg pScrn->videoRam = 0; 1833ab47cfaaSmrg break; 1834ab47cfaaSmrg } 1835ab47cfaaSmrg 1836ab47cfaaSmrg psav->videoRambytes = pScrn->videoRam * 1024; 1837ab47cfaaSmrg 1838ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1839ab47cfaaSmrg "probed videoram: %dk\n", 1840ab47cfaaSmrg pScrn->videoRam); 1841ab47cfaaSmrg } else { 1842ab47cfaaSmrg psav->videoRambytes = pScrn->videoRam * 1024; 1843ab47cfaaSmrg 1844ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1845ab47cfaaSmrg "videoram = %dk\n", 1846ab47cfaaSmrg pScrn->videoRam); 1847ab47cfaaSmrg } 1848ab47cfaaSmrg 1849ab47cfaaSmrg /* Get video RAM */ 1850ab47cfaaSmrg if( !pScrn->videoRam && psav->pVbe ) 1851ab47cfaaSmrg { 1852ab47cfaaSmrg /* If VBE is available, ask it about onboard memory. */ 1853ab47cfaaSmrg 1854ab47cfaaSmrg VbeInfoBlock* vib; 1855ab47cfaaSmrg 1856ab47cfaaSmrg vib = VBEGetVBEInfo( psav->pVbe ); 1857ab47cfaaSmrg pScrn->videoRam = vib->TotalMemory * 64; 1858ab47cfaaSmrg VBEFreeVBEInfo( vib ); 1859ab47cfaaSmrg 1860ab47cfaaSmrg /* VBE often cuts 64k off of the RAM total. */ 1861ab47cfaaSmrg 1862ab47cfaaSmrg if( pScrn->videoRam & 64 ) 1863ab47cfaaSmrg pScrn->videoRam += 64; 1864ab47cfaaSmrg 1865ab47cfaaSmrg psav->videoRambytes = pScrn->videoRam * 1024; 1866ab47cfaaSmrg } 1867ab47cfaaSmrg 1868ab47cfaaSmrg 1869ab47cfaaSmrg /* 1870ab47cfaaSmrg * If we're running with acceleration, compute the command overflow 1871ab47cfaaSmrg * buffer location. The command overflow buffer must END at a 1872ab47cfaaSmrg * 4MB boundary; for all practical purposes, that means the very 1873ab47cfaaSmrg * end of the frame buffer. 1874ab47cfaaSmrg */ 1875ab47cfaaSmrg if (psav->NoAccel) { 1876ab47cfaaSmrg psav->cobIndex = 0; 1877ab47cfaaSmrg psav->cobSize = 0; 1878ab47cfaaSmrg } 1879ab47cfaaSmrg else if( ((S3_SAVAGE4_SERIES(psav->Chipset)) || 1880ab47cfaaSmrg (S3_SUPERSAVAGE == psav->Chipset)) && psav->disableCOB ) { 1881ab47cfaaSmrg /* 1882ab47cfaaSmrg * The Savage4 and ProSavage have COB coherency bugs which render 1883ab47cfaaSmrg * the buffer useless. 1884ab47cfaaSmrg */ 1885ab47cfaaSmrg /* 1886ab47cfaaSmrg psav->cobIndex = 2; 1887ab47cfaaSmrg psav->cobSize = 0x8000 << psav->cobIndex; 1888ab47cfaaSmrg */ 1889ab47cfaaSmrg psav->cobIndex = 0; 1890ab47cfaaSmrg psav->cobSize = 0; 1891ab47cfaaSmrg psav->bciThresholdHi = 32; 1892ab47cfaaSmrg psav->bciThresholdLo = 0; 1893ab47cfaaSmrg } else { 1894ab47cfaaSmrg /* We use 128kB for the COB on all other chips. */ 1895ab47cfaaSmrg psav->cobSize = 0x20000; 1896ab47cfaaSmrg if (S3_SAVAGE3D_SERIES(psav->Chipset) || 1897ab47cfaaSmrg psav->Chipset == S3_SAVAGE2000) { 1898ab47cfaaSmrg psav->cobIndex = 7; /* rev.A savage4 apparently also uses 7 */ 1899ab47cfaaSmrg } else { 1900ab47cfaaSmrg psav->cobIndex = 2; 1901ab47cfaaSmrg } 1902ab47cfaaSmrg /* max command size: 2560 entries */ 1903ab47cfaaSmrg psav->bciThresholdHi = psav->cobSize/4 + 32 - 2560; 1904ab47cfaaSmrg psav->bciThresholdLo = psav->bciThresholdHi - 2560; 1905ab47cfaaSmrg } 1906ab47cfaaSmrg 1907ab47cfaaSmrg /* align cob to 128k */ 1908ab47cfaaSmrg psav->cobOffset = (psav->videoRambytes - psav->cobSize) & ~0x1ffff; 1909ab47cfaaSmrg 1910ab47cfaaSmrg /* The cursor must be aligned on a 4k boundary. */ 1911ab47cfaaSmrg psav->CursorKByte = (psav->cobOffset >> 10) - 4; 1912ab47cfaaSmrg psav->endfb = (psav->CursorKByte << 10) - 1; 1913ab47cfaaSmrg 1914ab47cfaaSmrg if (psav->IsPrimary) { 1915ab47cfaaSmrg pScrn->videoRam /= 2; 1916ab47cfaaSmrg psav->videoRambytes = pScrn->videoRam * 1024; 1917ab47cfaaSmrg psav->CursorKByte = (psav->videoRambytes >> 10) - 4; 1918ab47cfaaSmrg psav->endfb = (psav->CursorKByte << 10) - 1; 1919ab47cfaaSmrg psav->videoRambytes *= 2; 1920ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1921ab47cfaaSmrg "Using %dk of videoram for primary head\n", 1922ab47cfaaSmrg pScrn->videoRam); 1923ab47cfaaSmrg } 1924ab47cfaaSmrg 1925ab47cfaaSmrg if(psav->IsSecondary) 1926ab47cfaaSmrg { 1927ab47cfaaSmrg pScrn->videoRam /= 2; 1928ab47cfaaSmrg /*psav->videoRambytes = pScrn->videoRam * 1024;*/ 1929ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1930ab47cfaaSmrg "Using %dk of videoram for secondary head\n", 1931ab47cfaaSmrg pScrn->videoRam); 1932ab47cfaaSmrg } 1933ab47cfaaSmrg 1934ab47cfaaSmrg pScrn->fbOffset = (psav->IsSecondary) 1935ab47cfaaSmrg ? pScrn->videoRam * 1024 : 0; 1936ab47cfaaSmrg 1937ab47cfaaSmrg /* reset graphics engine to avoid memory corruption */ 1938ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 1939ab47cfaaSmrg cr66 = VGAIN8(vgaCRReg); 1940ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 | 0x02); 1941ab47cfaaSmrg usleep(10000); 1942ab47cfaaSmrg 1943ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 1944ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 & ~0x02); /* clear reset flag */ 1945ab47cfaaSmrg usleep(10000); 1946ab47cfaaSmrg 1947ab47cfaaSmrg /* Set status word positions based on chip type. */ 1948ab47cfaaSmrg SavageInitStatus(pScrn); 1949ab47cfaaSmrg 1950ab47cfaaSmrg /* check for DVI/flat panel */ 1951ab47cfaaSmrg dvi = FALSE; 1952ab47cfaaSmrg if (psav->Chipset == S3_SAVAGE4) { 1953ab47cfaaSmrg unsigned char sr30 = 0x00; 1954ab47cfaaSmrg VGAOUT8(0x3c4, 0x30); 1955ab47cfaaSmrg /* clear bit 1 */ 1956ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x02); 1957ab47cfaaSmrg sr30 = VGAIN8(0x3c5); 1958ab47cfaaSmrg if (sr30 & 0x02 /*0x04 */) { 1959ab47cfaaSmrg dvi = TRUE; 1960ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Digital Flat Panel Detected\n"); 1961ab47cfaaSmrg } 1962ab47cfaaSmrg } 1963ab47cfaaSmrg 1964ab47cfaaSmrg if( (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 1965ab47cfaaSmrg S3_MOBILE_TWISTER_SERIES(psav->Chipset)) && !psav->CrtOnly ) { 1966ab47cfaaSmrg psav->DisplayType = MT_LCD; 1967ab47cfaaSmrg } else if (dvi || ((psav->Chipset == S3_SAVAGE4) && psav->dvi)) { 1968ab47cfaaSmrg psav->DisplayType = MT_DFP; 1969ab47cfaaSmrg } else { 1970ab47cfaaSmrg psav->DisplayType = MT_CRT; 1971ab47cfaaSmrg } 1972ab47cfaaSmrg 1973ab47cfaaSmrg if (psav->IsSecondary) 1974ab47cfaaSmrg psav->DisplayType = MT_CRT; 1975ab47cfaaSmrg 1976ab47cfaaSmrg /* Do the DDC dance. */ 1977ab47cfaaSmrg SavageDoDDC(pScrn); 1978ab47cfaaSmrg 1979ab47cfaaSmrg /* set up ramdac max clock - might be altered by SavageGetPanelInfo */ 1980ab47cfaaSmrg if (pScrn->bitsPerPixel >= 24) 1981ab47cfaaSmrg psav->maxClock = 220000; 1982ab47cfaaSmrg else 1983ab47cfaaSmrg psav->maxClock = 250000; 1984ab47cfaaSmrg 1985ab47cfaaSmrg /* detect current mclk */ 1986ab47cfaaSmrg VGAOUT8(0x3c4, 0x08); 1987ab47cfaaSmrg sr8 = VGAIN8(0x3c5); 1988ab47cfaaSmrg VGAOUT8(0x3c5, 0x06); 1989ab47cfaaSmrg VGAOUT8(0x3c4, 0x10); 1990ab47cfaaSmrg n = VGAIN8(0x3c5); 1991ab47cfaaSmrg VGAOUT8(0x3c4, 0x11); 1992ab47cfaaSmrg m = VGAIN8(0x3c5); 1993ab47cfaaSmrg VGAOUT8(0x3c4, 0x08); 1994ab47cfaaSmrg VGAOUT8(0x3c5, sr8); 1995ab47cfaaSmrg m &= 0x7f; 1996ab47cfaaSmrg n1 = n & 0x1f; 1997ab47cfaaSmrg n2 = (n >> 5) & 0x03; 1998ab47cfaaSmrg mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100; 1999ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n", 2000ab47cfaaSmrg mclk / 1000.0); 2001ab47cfaaSmrg 2002ab47cfaaSmrg pScrn->maxHValue = 2048 << 3; /* 11 bits of h_total 8-pixel units */ 2003ab47cfaaSmrg pScrn->maxVValue = 2048; /* 11 bits of v_total */ 2004ab47cfaaSmrg pScrn->virtualX = pScrn->display->virtualX; 2005ab47cfaaSmrg pScrn->virtualY = pScrn->display->virtualY; 2006ab47cfaaSmrg 2007ab47cfaaSmrg /* Check LCD panel information */ 2008ab47cfaaSmrg 2009ab47cfaaSmrg if(psav->DisplayType == MT_LCD) 2010ab47cfaaSmrg { 2011ab47cfaaSmrg SavageGetPanelInfo(pScrn); 2012ab47cfaaSmrg SavageAddPanelMode(pScrn); 2013ab47cfaaSmrg } 2014ab47cfaaSmrg 2015ab47cfaaSmrg#if 0 2016ab47cfaaSmrg if (psav->CrtOnly && !psav->UseBIOS) { 2017ab47cfaaSmrg VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 2018ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); /* disable FP */ 2019ab47cfaaSmrg if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) /*|| 2020ab47cfaaSmrg S3_MOBILE_TWISTER_SERIES(psav->Chipset)*/) { /* not sure this works on mobile prosavage */ 2021ab47cfaaSmrg VGAOUT8(0x3c4, 0x31); 2022ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x04); /* make sure crtc1 is crt source */ 2023ab47cfaaSmrg } 2024ab47cfaaSmrg } 2025ab47cfaaSmrg#endif 2026ab47cfaaSmrg 2027ab47cfaaSmrg if( psav->UseBIOS ) 2028ab47cfaaSmrg { 2029ab47cfaaSmrg /* Go probe the BIOS for all the modes and refreshes at this depth. */ 2030ab47cfaaSmrg 2031ab47cfaaSmrg if( psav->ModeTable ) 2032ab47cfaaSmrg { 2033ab47cfaaSmrg SavageFreeBIOSModeTable( psav, &psav->ModeTable ); 2034ab47cfaaSmrg } 2035ab47cfaaSmrg 2036ab47cfaaSmrg psav->ModeTable = SavageGetBIOSModeTable( psav, psav->primStreamBpp ); 2037ab47cfaaSmrg 2038ab47cfaaSmrg if( !psav->ModeTable || !psav->ModeTable->NumModes ) { 2039ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2040ab47cfaaSmrg "Failed to fetch any BIOS modes. Disabling BIOS.\n"); 2041ab47cfaaSmrg psav->UseBIOS = FALSE; 2042ab47cfaaSmrg } 2043ab47cfaaSmrg else 2044ab47cfaaSmrg /*if( xf86Verbose )*/ 2045ab47cfaaSmrg { 2046ab47cfaaSmrg SavageModeEntryPtr pmt; 2047ab47cfaaSmrg 2048ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2049ab47cfaaSmrg "Found %d modes at this depth:\n", 2050ab47cfaaSmrg psav->ModeTable->NumModes); 2051ab47cfaaSmrg 2052ab47cfaaSmrg for( 2053ab47cfaaSmrg i = 0, pmt = psav->ModeTable->Modes; 2054ab47cfaaSmrg i < psav->ModeTable->NumModes; 2055ab47cfaaSmrg i++, pmt++ ) 2056ab47cfaaSmrg { 2057ab47cfaaSmrg int j; 2058ab47cfaaSmrg ErrorF( " [%03x] %d x %d", 2059ab47cfaaSmrg pmt->VesaMode, pmt->Width, pmt->Height ); 2060ab47cfaaSmrg for( j = 0; j < pmt->RefreshCount; j++ ) 2061ab47cfaaSmrg { 2062ab47cfaaSmrg ErrorF( ", %dHz", pmt->RefreshRate[j] ); 2063ab47cfaaSmrg } 2064ab47cfaaSmrg ErrorF( "\n"); 2065ab47cfaaSmrg } 2066ab47cfaaSmrg } 2067ab47cfaaSmrg } 2068ab47cfaaSmrg 2069ab47cfaaSmrg clockRanges = xnfalloc(sizeof(ClockRange)); 2070ab47cfaaSmrg clockRanges->next = NULL; 2071ab47cfaaSmrg clockRanges->minClock = 10000; 2072ab47cfaaSmrg clockRanges->maxClock = psav->maxClock; 2073ab47cfaaSmrg clockRanges->clockIndex = -1; 2074ab47cfaaSmrg clockRanges->interlaceAllowed = TRUE; 2075ab47cfaaSmrg clockRanges->doubleScanAllowed = TRUE; 2076ab47cfaaSmrg clockRanges->ClockDivFactor = 1.0; 2077ab47cfaaSmrg clockRanges->ClockMulFactor = 1.0; 2078ab47cfaaSmrg 2079ab47cfaaSmrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 2080ab47cfaaSmrg pScrn->display->modes, clockRanges, NULL, 2081ab47cfaaSmrg 256, 2048, 16 * pScrn->bitsPerPixel, 2082ab47cfaaSmrg 128, 2048, 2083ab47cfaaSmrg pScrn->virtualX, pScrn->virtualY, 2084ab47cfaaSmrg psav->videoRambytes, LOOKUP_BEST_REFRESH); 2085ab47cfaaSmrg 2086ab47cfaaSmrg if (i == -1) { 2087ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n"); 2088ab47cfaaSmrg SavageFreeRec(pScrn); 2089ab47cfaaSmrg vbeFree(psav->pVbe); 2090ab47cfaaSmrg psav->pVbe = NULL; 2091ab47cfaaSmrg return FALSE; 2092ab47cfaaSmrg } 2093ab47cfaaSmrg 2094ab47cfaaSmrg xf86PruneDriverModes(pScrn); 2095ab47cfaaSmrg 2096ab47cfaaSmrg if (i == 0 || pScrn->modes == NULL) { 2097ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 2098ab47cfaaSmrg SavageFreeRec(pScrn); 2099ab47cfaaSmrg vbeFree(psav->pVbe); 2100ab47cfaaSmrg psav->pVbe = NULL; 2101ab47cfaaSmrg return FALSE; 2102ab47cfaaSmrg } 2103ab47cfaaSmrg 2104ab47cfaaSmrg xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 2105ab47cfaaSmrg pScrn->currentMode = pScrn->modes; 2106ab47cfaaSmrg xf86PrintModes(pScrn); 2107ab47cfaaSmrg xf86SetDpi(pScrn, 0, 0); 2108ab47cfaaSmrg 2109ab47cfaaSmrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 2110ab47cfaaSmrg SavageFreeRec(pScrn); 2111ab47cfaaSmrg vbeFree(psav->pVbe); 2112ab47cfaaSmrg psav->pVbe = NULL; 2113ab47cfaaSmrg return FALSE; 2114ab47cfaaSmrg } 2115ab47cfaaSmrg 2116ab47cfaaSmrg xf86LoaderReqSymLists(fbSymbols, NULL); 2117ab47cfaaSmrg 2118ab47cfaaSmrg if( !psav->NoAccel ) { 2119ab47cfaaSmrg 2120ab47cfaaSmrg char *modName = NULL; 2121ab47cfaaSmrg const char **symNames = NULL; 2122ab47cfaaSmrg 2123ab47cfaaSmrg if (psav->useEXA) { 2124ab47cfaaSmrg modName = "exa"; 2125ab47cfaaSmrg symNames = exaSymbols; 2126ab47cfaaSmrg XF86ModReqInfo req; 2127ab47cfaaSmrg int errmaj, errmin; 2128ab47cfaaSmrg memset(&req, 0, sizeof(req)); 2129ab47cfaaSmrg req.majorversion = 2; 2130ab47cfaaSmrg req.minorversion = 0; 2131ab47cfaaSmrg 2132ab47cfaaSmrg if( !LoadSubModule(pScrn->module, modName, 2133ab47cfaaSmrg NULL, NULL, NULL, &req, &errmaj, &errmin) ) { 2134ab47cfaaSmrg LoaderErrorMsg(NULL, modName, errmaj, errmin); 2135ab47cfaaSmrg SavageFreeRec(pScrn); 2136ab47cfaaSmrg vbeFree(psav->pVbe); 2137ab47cfaaSmrg psav->pVbe = NULL; 2138ab47cfaaSmrg return FALSE; 2139ab47cfaaSmrg } 2140ab47cfaaSmrg } else { 2141ab47cfaaSmrg modName = "xaa"; 2142ab47cfaaSmrg symNames = xaaSymbols; 2143ab47cfaaSmrg if( !xf86LoadSubModule(pScrn, modName) ) { 2144ab47cfaaSmrg SavageFreeRec(pScrn); 2145ab47cfaaSmrg vbeFree(psav->pVbe); 2146ab47cfaaSmrg psav->pVbe = NULL; 2147ab47cfaaSmrg return FALSE; 2148ab47cfaaSmrg } 2149ab47cfaaSmrg } 2150ab47cfaaSmrg 2151ab47cfaaSmrg xf86LoaderReqSymLists(symNames, NULL ); 2152ab47cfaaSmrg 2153ab47cfaaSmrg } 2154ab47cfaaSmrg 2155ab47cfaaSmrg if (psav->hwcursor) { 2156ab47cfaaSmrg if (!xf86LoadSubModule(pScrn, "ramdac")) { 2157ab47cfaaSmrg SavageFreeRec(pScrn); 2158ab47cfaaSmrg vbeFree(psav->pVbe); 2159ab47cfaaSmrg psav->pVbe = NULL; 2160ab47cfaaSmrg return FALSE; 2161ab47cfaaSmrg } 2162ab47cfaaSmrg xf86LoaderReqSymLists(ramdacSymbols, NULL); 2163ab47cfaaSmrg } 2164ab47cfaaSmrg 2165ab47cfaaSmrg if (psav->shadowFB) { 2166ab47cfaaSmrg if (!xf86LoadSubModule(pScrn, "shadowfb")) { 2167ab47cfaaSmrg SavageFreeRec(pScrn); 2168ab47cfaaSmrg vbeFree(psav->pVbe); 2169ab47cfaaSmrg psav->pVbe = NULL; 2170ab47cfaaSmrg return FALSE; 2171ab47cfaaSmrg } 2172ab47cfaaSmrg xf86LoaderReqSymLists(shadowSymbols, NULL); 2173ab47cfaaSmrg } 2174ab47cfaaSmrg vbeFree(psav->pVbe); 2175ab47cfaaSmrg 2176ab47cfaaSmrg psav->pVbe = NULL; 2177ab47cfaaSmrg 2178ab47cfaaSmrg return TRUE; 2179ab47cfaaSmrg} 2180ab47cfaaSmrg 2181ab47cfaaSmrg 2182ab47cfaaSmrgstatic Bool SavageEnterVT(int scrnIndex, int flags) 2183ab47cfaaSmrg{ 2184ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2185ab47cfaaSmrg#ifdef XF86DRI 2186ab47cfaaSmrg SavagePtr psav= SAVPTR(pScrn); 2187ab47cfaaSmrg ScreenPtr pScreen; 2188ab47cfaaSmrg SAVAGESAREAPrivPtr pSAREAPriv; 2189ab47cfaaSmrg#endif 2190ab47cfaaSmrg 2191ab47cfaaSmrg TRACE(("SavageEnterVT(%d)\n", flags)); 2192ab47cfaaSmrg 2193ab47cfaaSmrg gpScrn = pScrn; 2194ab47cfaaSmrg SavageEnableMMIO(pScrn); 2195ab47cfaaSmrg 2196ab47cfaaSmrg#ifdef XF86DRI 2197ab47cfaaSmrg if (psav->directRenderingEnabled) { 2198ab47cfaaSmrg pScreen = screenInfo.screens[scrnIndex]; 2199ab47cfaaSmrg pSAREAPriv = (SAVAGESAREAPrivPtr)DRIGetSAREAPrivate(pScreen); 2200ab47cfaaSmrg /* Assume that 3D state was clobbered, invalidate it by 2201ab47cfaaSmrg * changing ctxOwner in the sarea. */ 2202ab47cfaaSmrg pSAREAPriv->ctxOwner = DRIGetContext(pScreen); 2203ab47cfaaSmrg DRIUnlock(pScreen); 2204ab47cfaaSmrg psav->LockHeld = 0; 2205ab47cfaaSmrg } 2206ab47cfaaSmrg#endif 2207ab47cfaaSmrg if (!SAVPTR(pScrn)->IsSecondary) 2208ab47cfaaSmrg SavageSave(pScrn); 2209ab47cfaaSmrg if(SavageModeInit(pScrn, pScrn->currentMode)) { 2210ab47cfaaSmrg /* some BIOSes seem to enable HW cursor on PM resume */ 2211ab47cfaaSmrg if (!SAVPTR(pScrn)->hwc_on) 2212ab47cfaaSmrg SavageHideCursor( pScrn ); 2213ab47cfaaSmrg return TRUE; 2214ab47cfaaSmrg } 2215ab47cfaaSmrg 2216ab47cfaaSmrg return FALSE; 2217ab47cfaaSmrg} 2218ab47cfaaSmrg 2219ab47cfaaSmrg 2220ab47cfaaSmrgstatic void SavageLeaveVT(int scrnIndex, int flags) 2221ab47cfaaSmrg{ 2222ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 2223ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2224ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 2225ab47cfaaSmrg vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2226ab47cfaaSmrg SavageRegPtr SavageSavePtr = &psav->SavedReg; 2227ab47cfaaSmrg#ifdef XF86DRI 2228ab47cfaaSmrg ScreenPtr pScreen; 2229ab47cfaaSmrg#endif 2230ab47cfaaSmrg 2231ab47cfaaSmrg TRACE(("SavageLeaveVT(%d)\n", flags)); 2232ab47cfaaSmrg gpScrn = pScrn; 2233ab47cfaaSmrg 2234ab47cfaaSmrg#ifdef XF86DRI 2235ab47cfaaSmrg if (psav->directRenderingEnabled) { 2236ab47cfaaSmrg pScreen = screenInfo.screens[scrnIndex]; 2237ab47cfaaSmrg DRILock(pScreen, 0); 2238ab47cfaaSmrg psav->LockHeld = 1; 2239ab47cfaaSmrg } 2240ab47cfaaSmrg#endif 2241ab47cfaaSmrg if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON)) 2242ab47cfaaSmrg SavageStreamsOff(pScrn); 2243ab47cfaaSmrg SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE); 2244ab47cfaaSmrg SavageResetStreams(pScrn); 2245ab47cfaaSmrg SavageDisableMMIO(pScrn); 2246ab47cfaaSmrg 2247ab47cfaaSmrg} 2248ab47cfaaSmrg 2249ab47cfaaSmrg 2250ab47cfaaSmrgstatic void SavageSave(ScrnInfoPtr pScrn) 2251ab47cfaaSmrg{ 2252ab47cfaaSmrg unsigned char cr3a, cr53, cr66; 2253ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2254ab47cfaaSmrg vgaRegPtr vgaSavePtr = &hwp->SavedReg; 2255ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 2256ab47cfaaSmrg SavageRegPtr save = &psav->SavedReg; 2257ab47cfaaSmrg unsigned short vgaCRReg = psav->vgaIOBase + 5; 2258ab47cfaaSmrg unsigned short vgaCRIndex = psav->vgaIOBase + 4; 2259ab47cfaaSmrg 2260ab47cfaaSmrg TRACE(("SavageSave()\n")); 2261ab47cfaaSmrg 2262ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x4838); 2263ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0xa039); 2264ab47cfaaSmrg VGAOUT16(0x3c4, 0x0608); 2265ab47cfaaSmrg 2266ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2267ab47cfaaSmrg cr66 = VGAIN8(vgaCRReg); 2268ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 | 0x80); 2269ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2270ab47cfaaSmrg cr3a = VGAIN8(vgaCRReg); 2271ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a | 0x80); 2272ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x53); 2273ab47cfaaSmrg cr53 = VGAIN8(vgaCRReg); 2274ab47cfaaSmrg VGAOUT8(vgaCRReg, cr53 & 0x7f); 2275ab47cfaaSmrg 2276ab47cfaaSmrg if (xf86IsPrimaryPci(psav->PciInfo)) 2277ab47cfaaSmrg vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL); 2278ab47cfaaSmrg else 2279ab47cfaaSmrg vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE); 2280ab47cfaaSmrg 2281ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2282ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66); 2283ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2284ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a); 2285ab47cfaaSmrg 2286ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2287ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66); 2288ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2289ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a); 2290ab47cfaaSmrg 2291ab47cfaaSmrg /* unlock extended seq regs */ 2292ab47cfaaSmrg VGAOUT8(0x3c4, 0x08); 2293ab47cfaaSmrg save->SR08 = VGAIN8(0x3c5); 2294ab47cfaaSmrg VGAOUT8(0x3c5, 0x06); 2295ab47cfaaSmrg 2296ab47cfaaSmrg /* now save all the extended regs we need */ 2297ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x31); 2298ab47cfaaSmrg save->CR31 = VGAIN8(vgaCRReg); 2299ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x32); 2300ab47cfaaSmrg save->CR32 = VGAIN8(vgaCRReg); 2301ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x34); 2302ab47cfaaSmrg save->CR34 = VGAIN8(vgaCRReg); 2303ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x36); 2304ab47cfaaSmrg save->CR36 = VGAIN8(vgaCRReg); 2305ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2306ab47cfaaSmrg save->CR3A = VGAIN8(vgaCRReg); 2307ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x40); 2308ab47cfaaSmrg save->CR40 = VGAIN8(vgaCRReg); 2309ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x42); 2310ab47cfaaSmrg save->CR42 = VGAIN8(vgaCRReg); 2311ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x45); 2312ab47cfaaSmrg save->CR45 = VGAIN8(vgaCRReg); 2313ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x50); 2314ab47cfaaSmrg save->CR50 = VGAIN8(vgaCRReg); 2315ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x51); 2316ab47cfaaSmrg save->CR51 = VGAIN8(vgaCRReg); 2317ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x53); 2318ab47cfaaSmrg save->CR53 = VGAIN8(vgaCRReg); 2319ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x58); 2320ab47cfaaSmrg save->CR58 = VGAIN8(vgaCRReg); 2321ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x60); 2322ab47cfaaSmrg save->CR60 = VGAIN8(vgaCRReg); 2323ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2324ab47cfaaSmrg save->CR66 = VGAIN8(vgaCRReg); 2325ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2326ab47cfaaSmrg save->CR67 = VGAIN8(vgaCRReg); 2327ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x68); 2328ab47cfaaSmrg save->CR68 = VGAIN8(vgaCRReg); 2329ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x69); 2330ab47cfaaSmrg save->CR69 = VGAIN8(vgaCRReg); 2331ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x6f); 2332ab47cfaaSmrg save->CR6F = VGAIN8(vgaCRReg); 2333ab47cfaaSmrg 2334ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x33); 2335ab47cfaaSmrg save->CR33 = VGAIN8(vgaCRReg); 2336ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x86); 2337ab47cfaaSmrg save->CR86 = VGAIN8(vgaCRReg); 2338ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x88); 2339ab47cfaaSmrg save->CR88 = VGAIN8(vgaCRReg); 2340ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x90); 2341ab47cfaaSmrg save->CR90 = VGAIN8(vgaCRReg); 2342ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x91); 2343ab47cfaaSmrg save->CR91 = VGAIN8(vgaCRReg); 2344ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0xb0); 2345ab47cfaaSmrg save->CRB0 = VGAIN8(vgaCRReg) | 0x80; 2346ab47cfaaSmrg 2347ab47cfaaSmrg /* extended mode timing regs */ 2348ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3b); 2349ab47cfaaSmrg save->CR3B = VGAIN8(vgaCRReg); 2350ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3c); 2351ab47cfaaSmrg save->CR3C = VGAIN8(vgaCRReg); 2352ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x43); 2353ab47cfaaSmrg save->CR43 = VGAIN8(vgaCRReg); 2354ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x5d); 2355ab47cfaaSmrg save->CR5D = VGAIN8(vgaCRReg); 2356ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x5e); 2357ab47cfaaSmrg save->CR5E = VGAIN8(vgaCRReg); 2358ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x65); 2359ab47cfaaSmrg save->CR65 = VGAIN8(vgaCRReg); 2360ab47cfaaSmrg 2361ab47cfaaSmrg /* save seq extended regs for DCLK PLL programming */ 2362ab47cfaaSmrg VGAOUT8(0x3c4, 0x0e); 2363ab47cfaaSmrg save->SR0E = VGAIN8(0x3c5); 2364ab47cfaaSmrg VGAOUT8(0x3c4, 0x0f); 2365ab47cfaaSmrg save->SR0F = VGAIN8(0x3c5); 2366ab47cfaaSmrg VGAOUT8(0x3c4, 0x10); 2367ab47cfaaSmrg save->SR10 = VGAIN8(0x3c5); 2368ab47cfaaSmrg VGAOUT8(0x3c4, 0x11); 2369ab47cfaaSmrg save->SR11 = VGAIN8(0x3c5); 2370ab47cfaaSmrg VGAOUT8(0x3c4, 0x12); 2371ab47cfaaSmrg save->SR12 = VGAIN8(0x3c5); 2372ab47cfaaSmrg VGAOUT8(0x3c4, 0x13); 2373ab47cfaaSmrg save->SR13 = VGAIN8(0x3c5); 2374ab47cfaaSmrg VGAOUT8(0x3c4, 0x29); 2375ab47cfaaSmrg save->SR29 = VGAIN8(0x3c5); 2376ab47cfaaSmrg 2377ab47cfaaSmrg VGAOUT8(0x3c4, 0x15); 2378ab47cfaaSmrg save->SR15 = VGAIN8(0x3c5); 2379ab47cfaaSmrg VGAOUT8(0x3c4, 0x30); 2380ab47cfaaSmrg save->SR30 = VGAIN8(0x3c5); 2381ab47cfaaSmrg VGAOUT8(0x3c4, 0x18); 2382ab47cfaaSmrg save->SR18 = VGAIN8(0x3c5); 2383ab47cfaaSmrg VGAOUT8(0x3c4, 0x1b); 2384ab47cfaaSmrg save->SR1B = VGAIN8(0x3c5); 2385ab47cfaaSmrg 2386ab47cfaaSmrg /* Save flat panel expansion registers. */ 2387ab47cfaaSmrg 2388ab47cfaaSmrg if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 2389ab47cfaaSmrg S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { 2390ab47cfaaSmrg int i; 2391ab47cfaaSmrg for( i = 0; i < 8; i++ ) { 2392ab47cfaaSmrg VGAOUT8(0x3c4, 0x54+i); 2393ab47cfaaSmrg save->SR54[i] = VGAIN8(0x3c5); 2394ab47cfaaSmrg } 2395ab47cfaaSmrg } 2396ab47cfaaSmrg 2397ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2398ab47cfaaSmrg cr66 = VGAIN8(vgaCRReg); 2399ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 | 0x80); 2400ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2401ab47cfaaSmrg cr3a = VGAIN8(vgaCRReg); 2402ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a | 0x80); 2403ab47cfaaSmrg 2404ab47cfaaSmrg /* now save MIU regs */ 2405ab47cfaaSmrg if( ! S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 2406ab47cfaaSmrg save->MMPR0 = INREG(FIFO_CONTROL_REG); 2407ab47cfaaSmrg save->MMPR1 = INREG(MIU_CONTROL_REG); 2408ab47cfaaSmrg save->MMPR2 = INREG(STREAMS_TIMEOUT_REG); 2409ab47cfaaSmrg save->MMPR3 = INREG(MISC_TIMEOUT_REG); 2410ab47cfaaSmrg } 2411ab47cfaaSmrg 2412ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2413ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a); 2414ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2415ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66); 2416ab47cfaaSmrg 2417ab47cfaaSmrg if (!psav->ModeStructInit) { 2418ab47cfaaSmrg vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr); 2419ab47cfaaSmrg memcpy(&psav->ModeReg, save, sizeof(SavageRegRec)); 2420ab47cfaaSmrg psav->ModeStructInit = TRUE; 2421ab47cfaaSmrg } 2422ab47cfaaSmrg 2423ab47cfaaSmrg#if 0 2424ab47cfaaSmrg if (xf86GetVerbosity() > 1) 2425ab47cfaaSmrg SavagePrintRegs(pScrn); 2426ab47cfaaSmrg#endif 2427ab47cfaaSmrg 2428ab47cfaaSmrg return; 2429ab47cfaaSmrg} 2430ab47cfaaSmrg 2431ab47cfaaSmrg 2432ab47cfaaSmrgstatic void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, 2433ab47cfaaSmrg SavageRegPtr restore, Bool Entering) 2434ab47cfaaSmrg{ 2435ab47cfaaSmrg unsigned char tmp, cr3a, cr66; 2436ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2437ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 2438ab47cfaaSmrg int vgaCRIndex, vgaCRReg, vgaIOBase; 2439ab47cfaaSmrg 2440ab47cfaaSmrg 2441ab47cfaaSmrg vgaIOBase = hwp->IOBase; 2442ab47cfaaSmrg vgaCRIndex = vgaIOBase + 4; 2443ab47cfaaSmrg vgaCRReg = vgaIOBase + 5; 2444ab47cfaaSmrg 2445ab47cfaaSmrg TRACE(("SavageWriteMode(%x)\n", restore->mode)); 2446ab47cfaaSmrg 2447ab47cfaaSmrg#ifdef XF86DRI 2448ab47cfaaSmrg if (psav->directRenderingEnabled) { 2449ab47cfaaSmrg DRILock(screenInfo.screens[pScrn->scrnIndex], 0); 2450ab47cfaaSmrg psav->LockHeld = 1; 2451ab47cfaaSmrg } 2452ab47cfaaSmrg#endif 2453ab47cfaaSmrg 2454ab47cfaaSmrg if (psav->IsSecondary) { 2455ab47cfaaSmrg /* Set up the mode. Don't clear video RAM. */ 2456ab47cfaaSmrg SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); 2457ab47cfaaSmrg SavageSetGBD(pScrn); 2458ab47cfaaSmrg return; 2459ab47cfaaSmrg } 2460ab47cfaaSmrg 2461ab47cfaaSmrg if( Entering && 2462ab47cfaaSmrg (!S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || (psav->ForceInit)) 2463ab47cfaaSmrg ) 2464ab47cfaaSmrg SavageInitialize2DEngine(pScrn); 2465ab47cfaaSmrg 2466ab47cfaaSmrg /* 2467ab47cfaaSmrg * If we figured out a VESA mode number for this timing, just use 2468ab47cfaaSmrg * the S3 BIOS to do the switching, with a few additional tweaks. 2469ab47cfaaSmrg */ 2470ab47cfaaSmrg 2471ab47cfaaSmrg if( psav->UseBIOS && restore->mode > 0x13 ) 2472ab47cfaaSmrg { 2473ab47cfaaSmrg int width; 2474ab47cfaaSmrg unsigned short cr6d; 2475ab47cfaaSmrg unsigned short cr79 = 0; 2476ab47cfaaSmrg 2477ab47cfaaSmrg /* Set up the mode. Don't clear video RAM. */ 2478ab47cfaaSmrg SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh ); 2479ab47cfaaSmrg 2480ab47cfaaSmrg /* Restore the DAC. */ 2481ab47cfaaSmrg vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP); 2482ab47cfaaSmrg 2483ab47cfaaSmrg /* Unlock the extended registers. */ 2484ab47cfaaSmrg 2485ab47cfaaSmrg#if 0 2486ab47cfaaSmrg /* Which way is better? */ 2487ab47cfaaSmrg hwp->writeCrtc( hwp, 0x38, 0x48 ); 2488ab47cfaaSmrg hwp->writeCrtc( hwp, 0x39, 0xa0 ); 2489ab47cfaaSmrg hwp->writeSeq( hwp, 0x08, 0x06 ); 2490ab47cfaaSmrg#endif 2491ab47cfaaSmrg 2492ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x4838); 2493ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0xA039); 2494ab47cfaaSmrg VGAOUT16(0x3c4, 0x0608); 2495ab47cfaaSmrg 2496ab47cfaaSmrg /* Enable linear addressing. */ 2497ab47cfaaSmrg 2498ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x1358); 2499ab47cfaaSmrg 2500ab47cfaaSmrg /* Disable old MMIO. */ 2501ab47cfaaSmrg 2502ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x53); 2503ab47cfaaSmrg VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & ~0x10); 2504ab47cfaaSmrg 2505ab47cfaaSmrg /* Disable HW cursor */ 2506ab47cfaaSmrg 2507ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x0045); 2508ab47cfaaSmrg 2509ab47cfaaSmrg /* Set the color mode. */ 2510ab47cfaaSmrg 2511ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2512ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR67); 2513ab47cfaaSmrg 2514ab47cfaaSmrg /* Enable gamma correction, set CLUT to 8 bit */ 2515ab47cfaaSmrg 2516ab47cfaaSmrg VGAOUT8(0x3c4, 0x1b); 2517ab47cfaaSmrg if( (pScrn->bitsPerPixel == 32) && !psav->DGAactive 2518ab47cfaaSmrg && ! psav->FBStart2nd ) 2519ab47cfaaSmrg VGAOUT8(0x3c5, 0x18 ); 2520ab47cfaaSmrg else 2521ab47cfaaSmrg VGAOUT8(0x3c5, 0x10 ); 2522ab47cfaaSmrg 2523ab47cfaaSmrg /* We may need TV/panel fixups here. See s3bios.c line 2904. */ 2524ab47cfaaSmrg 2525ab47cfaaSmrg /* Set FIFO fetch delay. */ 2526ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x85); 2527ab47cfaaSmrg VGAOUT8(vgaCRReg, (VGAIN8(vgaCRReg) & 0xf8) | 0x03); 2528ab47cfaaSmrg 2529ab47cfaaSmrg /* Patch CR79. These values are magical. */ 2530ab47cfaaSmrg 2531ab47cfaaSmrg if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2532ab47cfaaSmrg { 2533ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x6d); 2534ab47cfaaSmrg cr6d = VGAIN8(vgaCRReg); 2535ab47cfaaSmrg 2536ab47cfaaSmrg cr79 = 0x04; 2537ab47cfaaSmrg 2538ab47cfaaSmrg if( pScrn->displayWidth >= 1024 ) 2539ab47cfaaSmrg { 2540ab47cfaaSmrg if(psav->primStreamBpp == 32 ) 2541ab47cfaaSmrg { 2542ab47cfaaSmrg if( restore->refresh >= 130 ) 2543ab47cfaaSmrg cr79 = 0x03; 2544ab47cfaaSmrg else if( pScrn->displayWidth >= 1280 ) 2545ab47cfaaSmrg cr79 = 0x02; 2546ab47cfaaSmrg else if( 2547ab47cfaaSmrg (pScrn->displayWidth == 1024) && 2548ab47cfaaSmrg (restore->refresh >= 75) 2549ab47cfaaSmrg ) 2550ab47cfaaSmrg { 2551ab47cfaaSmrg if( cr6d && LCD_ACTIVE ) 2552ab47cfaaSmrg cr79 = 0x05; 2553ab47cfaaSmrg else 2554ab47cfaaSmrg cr79 = 0x08; 2555ab47cfaaSmrg } 2556ab47cfaaSmrg } 2557ab47cfaaSmrg else if( psav->primStreamBpp == 16) 2558ab47cfaaSmrg { 2559ab47cfaaSmrg 2560ab47cfaaSmrg/* The windows driver uses 0x13 for 16-bit 130Hz, but I see terrible 2561ab47cfaaSmrg * screen artifacts with that value. Let's keep it low for now. 2562ab47cfaaSmrg * if( restore->refresh >= 130 ) 2563ab47cfaaSmrg * cr79 = 0x13; 2564ab47cfaaSmrg * else 2565ab47cfaaSmrg */ 2566ab47cfaaSmrg if( pScrn->displayWidth == 1024 ) 2567ab47cfaaSmrg { 2568ab47cfaaSmrg if( cr6d && LCD_ACTIVE ) 2569ab47cfaaSmrg cr79 = 0x08; 2570ab47cfaaSmrg else 2571ab47cfaaSmrg cr79 = 0x0e; 2572ab47cfaaSmrg } 2573ab47cfaaSmrg } 2574ab47cfaaSmrg } 2575ab47cfaaSmrg } 2576ab47cfaaSmrg 2577ab47cfaaSmrg if( (psav->Chipset != S3_SAVAGE2000) && 2578ab47cfaaSmrg !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2579ab47cfaaSmrg VGAOUT16(vgaCRIndex, (cr79 << 8) | 0x79); 2580ab47cfaaSmrg 2581ab47cfaaSmrg /* Make sure 16-bit memory access is enabled. */ 2582ab47cfaaSmrg 2583ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x0c31); 2584ab47cfaaSmrg 2585ab47cfaaSmrg /* Enable the graphics engine. */ 2586ab47cfaaSmrg 2587ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x0140); 2588ab47cfaaSmrg 2589ab47cfaaSmrg /* Handle the pitch. */ 2590ab47cfaaSmrg 2591ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x50); 2592ab47cfaaSmrg VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1); 2593ab47cfaaSmrg 2594ab47cfaaSmrg width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3; 2595ab47cfaaSmrg VGAOUT16(vgaCRIndex, ((width & 0xff) << 8) | 0x13 ); 2596ab47cfaaSmrg VGAOUT16(vgaCRIndex, ((width & 0x300) << 4) | 0x51 ); 2597ab47cfaaSmrg 2598ab47cfaaSmrg /* Some non-S3 BIOSes enable block write even on non-SGRAM devices. */ 2599ab47cfaaSmrg 2600ab47cfaaSmrg switch( psav->Chipset ) 2601ab47cfaaSmrg { 2602ab47cfaaSmrg case S3_SAVAGE2000: 2603ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x73); 2604ab47cfaaSmrg VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & 0xdf ); 2605ab47cfaaSmrg break; 2606ab47cfaaSmrg 2607ab47cfaaSmrg case S3_SAVAGE3D: 2608ab47cfaaSmrg case S3_SAVAGE4: 2609ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x68); 2610ab47cfaaSmrg if( !(VGAIN8(vgaCRReg) & 0x80) ) 2611ab47cfaaSmrg { 2612ab47cfaaSmrg /* Not SGRAM; disable block write. */ 2613ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x88); 2614ab47cfaaSmrg VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0x10); 2615ab47cfaaSmrg } 2616ab47cfaaSmrg break; 2617ab47cfaaSmrg } 2618ab47cfaaSmrg 2619ab47cfaaSmrg /* set the correct clock for some BIOSes */ 2620ab47cfaaSmrg VGAOUT8(VGA_MISC_OUT_W, 2621ab47cfaaSmrg VGAIN8(VGA_MISC_OUT_R) | 0x0C); 2622ab47cfaaSmrg /* Some BIOSes turn on clock doubling on non-doubled modes */ 2623ab47cfaaSmrg if (pScrn->bitsPerPixel < 24) { 2624ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2625ab47cfaaSmrg if (!(VGAIN8(vgaCRReg) & 0x10)) { 2626ab47cfaaSmrg VGAOUT8(0x3c4, 0x15); 2627ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3C5) & ~0x10); 2628ab47cfaaSmrg VGAOUT8(0x3c4, 0x18); 2629ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x80); 2630ab47cfaaSmrg } 2631ab47cfaaSmrg } 2632ab47cfaaSmrg 2633ab47cfaaSmrg SavageInitialize2DEngine(pScrn); 2634ab47cfaaSmrg 2635ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x0140); 2636ab47cfaaSmrg 2637ab47cfaaSmrg SavageSetGBD(pScrn); 2638ab47cfaaSmrg 2639ab47cfaaSmrg 2640ab47cfaaSmrg#ifdef XF86DRI 2641ab47cfaaSmrg if (psav->directRenderingEnabled) 2642ab47cfaaSmrg DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); 2643ab47cfaaSmrg psav->LockHeld = 0; 2644ab47cfaaSmrg#endif 2645ab47cfaaSmrg 2646ab47cfaaSmrg return; 2647ab47cfaaSmrg } 2648ab47cfaaSmrg 2649ab47cfaaSmrg VGAOUT8(0x3c2, 0x23); 2650ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x4838); 2651ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0xa039); 2652ab47cfaaSmrg VGAOUT16(0x3c4, 0x0608); 2653ab47cfaaSmrg 2654ab47cfaaSmrg vgaHWProtect(pScrn, TRUE); 2655ab47cfaaSmrg 2656ab47cfaaSmrg /* will we be reenabling STREAMS for the new mode? */ 2657ab47cfaaSmrg psav->STREAMSRunning = 0; 2658ab47cfaaSmrg 2659ab47cfaaSmrg /* reset GE to make sure nothing is going on */ 2660ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2661ab47cfaaSmrg if(VGAIN8(vgaCRReg) & 0x01) 2662ab47cfaaSmrg SavageGEReset(pScrn,0,__LINE__,__FILE__); 2663ab47cfaaSmrg 2664ab47cfaaSmrg /* 2665ab47cfaaSmrg * Some Savage/MX and /IX systems go nuts when trying to exit the 2666ab47cfaaSmrg * server after WindowMaker has displayed a gradient background. I 2667ab47cfaaSmrg * haven't been able to find what causes it, but a non-destructive 2668ab47cfaaSmrg * switch to mode 3 here seems to eliminate the issue. 2669ab47cfaaSmrg */ 2670ab47cfaaSmrg 2671ab47cfaaSmrg if( ((restore->CR31 & 0x0a) == 0) && psav->pVbe ) { 2672ab47cfaaSmrg SavageSetTextMode( psav ); 2673ab47cfaaSmrg } 2674ab47cfaaSmrg 2675ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2676ab47cfaaSmrg (void) VGAIN8(vgaCRReg); 2677ab47cfaaSmrg /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */ 2678ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no STREAMS yet old and new */ 2679ab47cfaaSmrg 2680ab47cfaaSmrg /* restore extended regs */ 2681ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2682ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR66); 2683ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2684ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR3A); 2685ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x31); 2686ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR31); 2687ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x32); 2688ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR32); 2689ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x58); 2690ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR58); 2691ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x53); 2692ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR53 & 0x7f); 2693ab47cfaaSmrg 2694ab47cfaaSmrg VGAOUT16(0x3c4, 0x0608); 2695ab47cfaaSmrg 2696ab47cfaaSmrg /* Restore DCLK registers. */ 2697ab47cfaaSmrg 2698ab47cfaaSmrg VGAOUT8(0x3c4, 0x0e); 2699ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR0E); 2700ab47cfaaSmrg VGAOUT8(0x3c4, 0x0f); 2701ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR0F); 2702ab47cfaaSmrg VGAOUT8(0x3c4, 0x29); 2703ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR29); 2704ab47cfaaSmrg VGAOUT8(0x3c4, 0x15); 2705ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR15); 2706ab47cfaaSmrg 2707ab47cfaaSmrg /* Restore flat panel expansion registers. */ 2708ab47cfaaSmrg if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 2709ab47cfaaSmrg S3_MOBILE_TWISTER_SERIES(psav->Chipset)) { 2710ab47cfaaSmrg int i; 2711ab47cfaaSmrg for( i = 0; i < 8; i++ ) { 2712ab47cfaaSmrg VGAOUT8(0x3c4, 0x54+i); 2713ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR54[i]); 2714ab47cfaaSmrg } 2715ab47cfaaSmrg } 2716ab47cfaaSmrg 2717ab47cfaaSmrg /* restore the standard vga regs */ 2718ab47cfaaSmrg if (xf86IsPrimaryPci(psav->PciInfo)) 2719ab47cfaaSmrg vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL); 2720ab47cfaaSmrg else 2721ab47cfaaSmrg vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE); 2722ab47cfaaSmrg 2723ab47cfaaSmrg /* extended mode timing registers */ 2724ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x53); 2725ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR53); 2726ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x5d); 2727ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR5D); 2728ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x5e); 2729ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR5E); 2730ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3b); 2731ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR3B); 2732ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3c); 2733ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR3C); 2734ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x43); 2735ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR43); 2736ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x65); 2737ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR65); 2738ab47cfaaSmrg 2739ab47cfaaSmrg /* restore the desired video mode with cr67 */ 2740ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2741ab47cfaaSmrg /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */ 2742ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no streams for new and old streams engines */ 2743ab47cfaaSmrg 2744ab47cfaaSmrg /* other mode timing and extended regs */ 2745ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x34); 2746ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR34); 2747ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x40); 2748ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR40); 2749ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x42); 2750ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR42); 2751ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x45); 2752ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR45); 2753ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x50); 2754ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR50); 2755ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x51); 2756ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR51); 2757ab47cfaaSmrg 2758ab47cfaaSmrg /* memory timings */ 2759ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x36); 2760ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR36); 2761ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x60); 2762ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR60); 2763ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x68); 2764ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR68); 2765ab47cfaaSmrg VerticalRetraceWait(); 2766ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x69); 2767ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR69); 2768ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x6f); 2769ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR6F); 2770ab47cfaaSmrg 2771ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x33); 2772ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR33); 2773ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x86); 2774ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR86); 2775ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x88); 2776ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR88); 2777ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x90); 2778ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR90); 2779ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x91); 2780ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR91); 2781ab47cfaaSmrg if( psav->Chipset == S3_SAVAGE4 ) 2782ab47cfaaSmrg { 2783ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0xb0); 2784ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CRB0); 2785ab47cfaaSmrg } 2786ab47cfaaSmrg 2787ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x32); 2788ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR32); 2789ab47cfaaSmrg 2790ab47cfaaSmrg /* unlock extended seq regs */ 2791ab47cfaaSmrg VGAOUT8(0x3c4, 0x08); 2792ab47cfaaSmrg VGAOUT8(0x3c5, 0x06); 2793ab47cfaaSmrg 2794ab47cfaaSmrg /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that 2795ab47cfaaSmrg * we should leave the default SR10 and SR11 values there. 2796ab47cfaaSmrg */ 2797ab47cfaaSmrg if (restore->SR10 != 255) { 2798ab47cfaaSmrg VGAOUT8(0x3c4, 0x10); 2799ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR10); 2800ab47cfaaSmrg VGAOUT8(0x3c4, 0x11); 2801ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR11); 2802ab47cfaaSmrg } 2803ab47cfaaSmrg 2804ab47cfaaSmrg /* restore extended seq regs for dclk */ 2805ab47cfaaSmrg VGAOUT8(0x3c4, 0x0e); 2806ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR0E); 2807ab47cfaaSmrg VGAOUT8(0x3c4, 0x0f); 2808ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR0F); 2809ab47cfaaSmrg VGAOUT8(0x3c4, 0x12); 2810ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR12); 2811ab47cfaaSmrg VGAOUT8(0x3c4, 0x13); 2812ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR13); 2813ab47cfaaSmrg VGAOUT8(0x3c4, 0x29); 2814ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR29); 2815ab47cfaaSmrg 2816ab47cfaaSmrg VGAOUT8(0x3c4, 0x18); 2817ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR18); 2818ab47cfaaSmrg VGAOUT8(0x3c4, 0x1b); 2819ab47cfaaSmrg if( psav->DGAactive ) 2820ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR1B & ~0x08 ); 2821ab47cfaaSmrg else 2822ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR1B); 2823ab47cfaaSmrg 2824ab47cfaaSmrg /* load new m, n pll values for dclk & mclk */ 2825ab47cfaaSmrg VGAOUT8(0x3c4, 0x15); 2826ab47cfaaSmrg tmp = VGAIN8(0x3c5) & ~0x21; 2827ab47cfaaSmrg 2828ab47cfaaSmrg VGAOUT8(0x3c5, tmp | 0x03); 2829ab47cfaaSmrg VGAOUT8(0x3c5, tmp | 0x23); 2830ab47cfaaSmrg VGAOUT8(0x3c5, tmp | 0x03); 2831ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR15); 2832ab47cfaaSmrg usleep( 100 ); 2833ab47cfaaSmrg 2834ab47cfaaSmrg VGAOUT8(0x3c4, 0x30); 2835ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR30); 2836ab47cfaaSmrg VGAOUT8(0x3c4, 0x08); 2837ab47cfaaSmrg VGAOUT8(0x3c5, restore->SR08); 2838ab47cfaaSmrg 2839ab47cfaaSmrg /* now write out cr67 in full, possibly starting STREAMS */ 2840ab47cfaaSmrg VerticalRetraceWait(); 2841ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2842ab47cfaaSmrg#if 0 2843ab47cfaaSmrg VGAOUT8(vgaCRReg, 0x50); 2844ab47cfaaSmrg usleep(10000); 2845ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x67); 2846ab47cfaaSmrg#endif 2847ab47cfaaSmrg VGAOUT8(vgaCRReg, restore->CR67); 2848ab47cfaaSmrg 2849ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2850ab47cfaaSmrg cr66 = VGAIN8(vgaCRReg); 2851ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 | 0x80); 2852ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2853ab47cfaaSmrg cr3a = VGAIN8(vgaCRReg); 2854ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a | 0x80); 2855ab47cfaaSmrg 2856ab47cfaaSmrg if (Entering) 2857ab47cfaaSmrg SavageGEReset(pScrn,0,__LINE__,__FILE__); 2858ab47cfaaSmrg 2859ab47cfaaSmrg if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 2860ab47cfaaSmrg { 2861ab47cfaaSmrg VerticalRetraceWait(); 2862ab47cfaaSmrg OUTREG(FIFO_CONTROL_REG, restore->MMPR0); 2863ab47cfaaSmrg OUTREG(MIU_CONTROL_REG, restore->MMPR1); 2864ab47cfaaSmrg OUTREG(STREAMS_TIMEOUT_REG, restore->MMPR2); 2865ab47cfaaSmrg OUTREG(MISC_TIMEOUT_REG, restore->MMPR3); 2866ab47cfaaSmrg } 2867ab47cfaaSmrg 2868ab47cfaaSmrg /* If we're going into graphics mode and acceleration was enabled, */ 2869ab47cfaaSmrg /* go set up the BCI buffer and the global bitmap descriptor. */ 2870ab47cfaaSmrg 2871ab47cfaaSmrg#if 0 2872ab47cfaaSmrg if( Entering && (!psav->NoAccel) ) 2873ab47cfaaSmrg { 2874ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x50); 2875ab47cfaaSmrg VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1); 2876ab47cfaaSmrg SavageInitialize2DEngine(pScrn); 2877ab47cfaaSmrg } 2878ab47cfaaSmrg#endif 2879ab47cfaaSmrg 2880ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 2881ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66); 2882ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 2883ab47cfaaSmrg VGAOUT8(vgaCRReg, cr3a); 2884ab47cfaaSmrg 2885ab47cfaaSmrg if( Entering ) { 2886ab47cfaaSmrg SavageInitialize2DEngine(pScrn); 2887ab47cfaaSmrg 2888ab47cfaaSmrg VGAOUT16(vgaCRIndex, 0x0140); 2889ab47cfaaSmrg 2890ab47cfaaSmrg SavageSetGBD(pScrn); 2891ab47cfaaSmrg } 2892ab47cfaaSmrg 2893ab47cfaaSmrg vgaHWProtect(pScrn, FALSE); 2894ab47cfaaSmrg 2895ab47cfaaSmrg 2896ab47cfaaSmrg#ifdef XF86DRI 2897ab47cfaaSmrg if (psav->directRenderingEnabled) 2898ab47cfaaSmrg DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); 2899ab47cfaaSmrg psav->LockHeld = 0; 2900ab47cfaaSmrg#endif 2901ab47cfaaSmrg 2902ab47cfaaSmrg return; 2903ab47cfaaSmrg} 2904ab47cfaaSmrg 2905ab47cfaaSmrg 2906ab47cfaaSmrgstatic Bool SavageMapMem(ScrnInfoPtr pScrn) 2907ab47cfaaSmrg{ 2908ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 2909ab47cfaaSmrg int mode; 2910ab47cfaaSmrg unsigned i; 2911ab47cfaaSmrg 2912ab47cfaaSmrg TRACE(("SavageMapMem()\n")); 2913ab47cfaaSmrg 2914ab47cfaaSmrg if( S3_SAVAGE3D_SERIES(psav->Chipset) ) { 2915ab47cfaaSmrg psav->MmioRegion.bar = 0; 2916ab47cfaaSmrg psav->MmioRegion.offset = SAVAGE_NEWMMIO_REGBASE_S3; 2917ab47cfaaSmrg 2918ab47cfaaSmrg psav->FbRegion.bar = 0; 2919ab47cfaaSmrg psav->FbRegion.offset = 0; 2920ab47cfaaSmrg 2921ab47cfaaSmrg psav->last_bar = 0; 2922ab47cfaaSmrg } else { 2923ab47cfaaSmrg psav->MmioRegion.bar = 0; 2924ab47cfaaSmrg psav->MmioRegion.offset = SAVAGE_NEWMMIO_REGBASE_S4; 2925ab47cfaaSmrg 2926ab47cfaaSmrg psav->FbRegion.bar = 1; 2927ab47cfaaSmrg psav->FbRegion.offset = 0; 2928ab47cfaaSmrg 2929ab47cfaaSmrg psav->last_bar = 1; 2930ab47cfaaSmrg } 2931ab47cfaaSmrg 2932ab47cfaaSmrg /* On Paramount and Savage 2000, aperture 0 is PCI base 2. On other 2933ab47cfaaSmrg * chipsets it's in the same BAR as the framebuffer. 2934ab47cfaaSmrg */ 2935ab47cfaaSmrg if ((psav->Chipset == S3_SUPERSAVAGE) 2936ab47cfaaSmrg || (psav->Chipset == S3_SAVAGE2000)) { 2937ab47cfaaSmrg psav->ApertureRegion.bar = 2; 2938ab47cfaaSmrg psav->ApertureRegion.offset = 0; 2939ab47cfaaSmrg 2940ab47cfaaSmrg psav->last_bar = 2; 2941ab47cfaaSmrg } else { 2942ab47cfaaSmrg psav->ApertureRegion.bar = psav->FbRegion.bar; 2943ab47cfaaSmrg psav->ApertureRegion.offset = 0x02000000; 2944ab47cfaaSmrg } 2945ab47cfaaSmrg 2946ab47cfaaSmrg 2947ab47cfaaSmrg psav->MmioBase = psav->PciInfo->memBase[ psav->MmioRegion.bar ] 2948ab47cfaaSmrg + psav->MmioRegion.offset; 2949ab47cfaaSmrg 2950ab47cfaaSmrg psav->FrameBufferBase = psav->PciInfo->memBase[ psav->FbRegion.bar ] 2951ab47cfaaSmrg + psav->FbRegion.offset; 2952ab47cfaaSmrg 2953ab47cfaaSmrg psav->ApertureBase = psav->PciInfo->memBase[ psav->FbRegion.bar ] 2954ab47cfaaSmrg + psav->ApertureRegion.offset; 2955ab47cfaaSmrg 2956ab47cfaaSmrg 2957ab47cfaaSmrg /* FIXME: This seems fine even on Savage3D where the same BAR contains the 2958ab47cfaaSmrg * FIXME: MMIO space and the framebuffer. Write-combining gets fixed up 2959ab47cfaaSmrg * FIXME: later. Someone should investigate this, though. And kick S3 2960ab47cfaaSmrg * FIXME: for doing something so silly. 2961ab47cfaaSmrg */ 2962ab47cfaaSmrg mode = VIDMEM_MMIO; 2963ab47cfaaSmrg for (i = 0; i <= psav->last_bar; i++) { 2964ab47cfaaSmrg psav->bar_mappings[i] = xf86MapPciMem(pScrn->scrnIndex, mode, 2965ab47cfaaSmrg psav->PciTag, 2966ab47cfaaSmrg psav->PciInfo->memBase[i], 2967ab47cfaaSmrg (1U << psav->PciInfo->size[i])); 2968ab47cfaaSmrg if (!psav->bar_mappings[i]) { 2969ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2970ab47cfaaSmrg "Internal error: cound not map PCI region %u, last BAR = %u\n", 2971ab47cfaaSmrg i, psav->last_bar); 2972ab47cfaaSmrg return FALSE; 2973ab47cfaaSmrg } 2974ab47cfaaSmrg 2975ab47cfaaSmrg mode = VIDMEM_FRAMEBUFFER; 2976ab47cfaaSmrg } 2977ab47cfaaSmrg 2978ab47cfaaSmrg psav->MapBase = psav->bar_mappings[ psav->MmioRegion.bar ] 2979ab47cfaaSmrg + psav->MmioRegion.offset; 2980ab47cfaaSmrg 2981ab47cfaaSmrg psav->BciMem = psav->MapBase + 0x10000; 2982ab47cfaaSmrg 2983ab47cfaaSmrg SavageEnableMMIO(pScrn); 2984ab47cfaaSmrg 2985ab47cfaaSmrg psav->FBBase = psav->bar_mappings[ psav->FbRegion.bar ] 2986ab47cfaaSmrg + psav->FbRegion.offset; 2987ab47cfaaSmrg 2988ab47cfaaSmrg psav->FBStart = (psav->IsSecondary) 2989ab47cfaaSmrg ? psav->FBBase + 0x1000000 : psav->FBBase; 2990ab47cfaaSmrg 2991ab47cfaaSmrg psav->ApertureMap = psav->bar_mappings[ psav->ApertureRegion.bar ] 2992ab47cfaaSmrg + psav->ApertureRegion.offset; 2993ab47cfaaSmrg 2994ab47cfaaSmrg if (psav->IsSecondary) { 2995ab47cfaaSmrg psav->ApertureMap += 0x1000000; 2996ab47cfaaSmrg } 2997ab47cfaaSmrg 2998ab47cfaaSmrg pScrn->memPhysBase = psav->PciInfo->memBase[0]; 2999ab47cfaaSmrg 3000ab47cfaaSmrg return TRUE; 3001ab47cfaaSmrg} 3002ab47cfaaSmrg 3003ab47cfaaSmrg 3004ab47cfaaSmrgstatic void SavageUnmapMem(ScrnInfoPtr pScrn, int All) 3005ab47cfaaSmrg{ 3006ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3007ab47cfaaSmrg unsigned i; 3008ab47cfaaSmrg 3009ab47cfaaSmrg TRACE(("SavageUnmapMem(%x,%x)\n", psav->MapBase, psav->FBBase)); 3010ab47cfaaSmrg 3011ab47cfaaSmrg if (psav->PrimaryVidMapped) { 3012ab47cfaaSmrg vgaHWUnmapMem(pScrn); 3013ab47cfaaSmrg psav->PrimaryVidMapped = FALSE; 3014ab47cfaaSmrg } 3015ab47cfaaSmrg 3016ab47cfaaSmrg SavageDisableMMIO(pScrn); 3017ab47cfaaSmrg 3018ab47cfaaSmrg for (i = (All) ? 0 : 1; i <= psav->last_bar; i++) { 3019ab47cfaaSmrg if (psav->bar_mappings[i]) { 3020ab47cfaaSmrg xf86UnMapVidMem(pScrn->scrnIndex, psav->bar_mappings[i], 3021ab47cfaaSmrg (1U << psav->PciInfo->size[i])); 3022ab47cfaaSmrg psav->bar_mappings[i] = NULL; 3023ab47cfaaSmrg } 3024ab47cfaaSmrg } 3025ab47cfaaSmrg 3026ab47cfaaSmrg if (All) { 3027ab47cfaaSmrg psav->MapBase = 0; 3028ab47cfaaSmrg psav->BciMem = 0; 3029ab47cfaaSmrg } 3030ab47cfaaSmrg 3031ab47cfaaSmrg psav->FBBase = 0; 3032ab47cfaaSmrg psav->FBStart = 0; 3033ab47cfaaSmrg psav->ApertureMap = 0; 3034ab47cfaaSmrg 3035ab47cfaaSmrg return; 3036ab47cfaaSmrg} 3037ab47cfaaSmrg 3038ab47cfaaSmrg#ifdef XF86DRI 3039ab47cfaaSmrgstatic Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn) 3040ab47cfaaSmrg{ 3041ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3042ab47cfaaSmrg int cpp = pScrn->bitsPerPixel / 8; 3043ab47cfaaSmrg int tiledBufferSize, RamNeededFor3D; 3044ab47cfaaSmrg 3045ab47cfaaSmrg if (cpp == 2) { 3046ab47cfaaSmrg tiledBufferSize = ((pScrn->virtualX+63)/64)*((pScrn->virtualY+15)/16) * 2048; 3047ab47cfaaSmrg } else { 3048ab47cfaaSmrg tiledBufferSize = ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16) * 2048; 3049ab47cfaaSmrg } 3050ab47cfaaSmrg 3051ab47cfaaSmrg RamNeededFor3D = 4096 + /* hw cursor*/ 3052ab47cfaaSmrg psav->cobSize + /*COB*/ 3053ab47cfaaSmrg tiledBufferSize + /* front buffer */ 3054ab47cfaaSmrg tiledBufferSize + /* back buffer */ 3055ab47cfaaSmrg tiledBufferSize; /* depth buffer */ 3056ab47cfaaSmrg 3057ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 3058ab47cfaaSmrg "%d kB of Videoram needed for 3D; %d kB of Videoram available\n", 3059ab47cfaaSmrg RamNeededFor3D/1024, psav->videoRambytes/1024); 3060ab47cfaaSmrg 3061ab47cfaaSmrg if (RamNeededFor3D <= psav->videoRambytes) { 3062ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Sufficient Videoram available for 3D\n"); 3063ab47cfaaSmrg return TRUE; 3064ab47cfaaSmrg } else { 3065ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Insufficient Videoram available for 3D -- " 3066ab47cfaaSmrg "Try a lower color depth or smaller desktop. " 3067ab47cfaaSmrg "For integrated savages try increasing the videoram in the BIOS.\n"); 3068ab47cfaaSmrg return FALSE; 3069ab47cfaaSmrg } 3070ab47cfaaSmrg} 3071ab47cfaaSmrg#endif 3072ab47cfaaSmrg 3073ab47cfaaSmrgstatic void SavageInitStatus(ScrnInfoPtr pScrn) 3074ab47cfaaSmrg{ 3075ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3076ab47cfaaSmrg 3077ab47cfaaSmrg switch( psav->Chipset ) { 3078ab47cfaaSmrg case S3_SAVAGE3D: 3079ab47cfaaSmrg case S3_SAVAGE_MX: 3080ab47cfaaSmrg psav->WaitQueue = WaitQueue3D; 3081ab47cfaaSmrg psav->WaitIdle = WaitIdle3D; 3082ab47cfaaSmrg psav->WaitIdleEmpty = WaitIdleEmpty3D; 3083ab47cfaaSmrg psav->bciUsedMask = 0x1ffff; 3084ab47cfaaSmrg psav->eventStatusReg= 1; 3085ab47cfaaSmrg break; 3086ab47cfaaSmrg 3087ab47cfaaSmrg case S3_SAVAGE4: 3088ab47cfaaSmrg case S3_PROSAVAGE: 3089ab47cfaaSmrg case S3_SUPERSAVAGE: 3090ab47cfaaSmrg case S3_PROSAVAGEDDR: 3091ab47cfaaSmrg case S3_TWISTER: 3092ab47cfaaSmrg psav->WaitQueue = WaitQueue4; 3093ab47cfaaSmrg psav->WaitIdle = WaitIdle4; 3094ab47cfaaSmrg psav->WaitIdleEmpty = WaitIdleEmpty4; 3095ab47cfaaSmrg psav->bciUsedMask = 0x1fffff; 3096ab47cfaaSmrg psav->eventStatusReg= 1; 3097ab47cfaaSmrg break; 3098ab47cfaaSmrg 3099ab47cfaaSmrg case S3_SAVAGE2000: 3100ab47cfaaSmrg psav->WaitQueue = WaitQueue2K; 3101ab47cfaaSmrg psav->WaitIdle = WaitIdle2K; 3102ab47cfaaSmrg psav->WaitIdleEmpty = WaitIdleEmpty2K; 3103ab47cfaaSmrg psav->bciUsedMask = 0xfffff; 3104ab47cfaaSmrg psav->eventStatusReg= 2; 3105ab47cfaaSmrg break; 3106ab47cfaaSmrg } 3107ab47cfaaSmrg} 3108ab47cfaaSmrg 3109ab47cfaaSmrgstatic void SavageInitShadowStatus(ScrnInfoPtr pScrn) 3110ab47cfaaSmrg{ 3111ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3112ab47cfaaSmrg 3113ab47cfaaSmrg psav->ShadowStatus = psav->ConfigShadowStatus; 3114ab47cfaaSmrg 3115ab47cfaaSmrg SavageInitStatus(pScrn); 3116ab47cfaaSmrg 3117ab47cfaaSmrg if( psav->ShadowStatus ) { 3118ab47cfaaSmrg psav->ShadowPhysical = 3119ab47cfaaSmrg psav->FrameBufferBase + psav->CursorKByte*1024 + 4096 - 32; 3120ab47cfaaSmrg 3121ab47cfaaSmrg psav->ShadowVirtual = (CARD32 *) 3122ab47cfaaSmrg (psav->FBBase + psav->CursorKByte*1024 + 4096 - 32); 3123ab47cfaaSmrg 3124ab47cfaaSmrg xf86DrvMsg( pScrn->scrnIndex, X_PROBED, 3125ab47cfaaSmrg "Shadow area physical %08lx, linear %p\n", 3126ab47cfaaSmrg psav->ShadowPhysical, (void *)psav->ShadowVirtual ); 3127ab47cfaaSmrg 3128ab47cfaaSmrg psav->WaitQueue = ShadowWaitQueue; 3129ab47cfaaSmrg psav->WaitIdle = ShadowWait; 3130ab47cfaaSmrg psav->WaitIdleEmpty = ShadowWait; 3131ab47cfaaSmrg } 3132ab47cfaaSmrg 3133ab47cfaaSmrg if( psav->Chipset == S3_SAVAGE2000 ) 3134ab47cfaaSmrg psav->dwBCIWait2DIdle = 0xc0040000; 3135ab47cfaaSmrg else 3136ab47cfaaSmrg psav->dwBCIWait2DIdle = 0xc0020000; 3137ab47cfaaSmrg} 3138ab47cfaaSmrg 3139ab47cfaaSmrgstatic Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, 3140ab47cfaaSmrg int argc, char **argv) 3141ab47cfaaSmrg{ 3142ab47cfaaSmrg ScrnInfoPtr pScrn; 3143ab47cfaaSmrg SavagePtr psav; 3144ab47cfaaSmrg EntityInfoPtr pEnt; 3145ab47cfaaSmrg int ret; 3146ab47cfaaSmrg int colormapFlags; 3147ab47cfaaSmrg 3148ab47cfaaSmrg TRACE(("SavageScreenInit()\n")); 3149ab47cfaaSmrg 3150ab47cfaaSmrg pScrn = xf86Screens[pScreen->myNum]; 3151ab47cfaaSmrg psav = SAVPTR(pScrn); 3152ab47cfaaSmrg 3153ab47cfaaSmrg pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 3154ab47cfaaSmrg if (!psav->pVbe) 3155ab47cfaaSmrg psav->pVbe = VBEInit(NULL, pEnt->index); 3156ab47cfaaSmrg 3157ab47cfaaSmrg SavageEnableMMIO(pScrn); 3158ab47cfaaSmrg 3159ab47cfaaSmrg if (!SavageMapMem(pScrn)) 3160ab47cfaaSmrg return FALSE; 3161ab47cfaaSmrg 3162ab47cfaaSmrg psav->FBStart2nd = 0; 3163ab47cfaaSmrg 3164ab47cfaaSmrg if (psav->overlayDepth) { 3165ab47cfaaSmrg if ((pScrn->virtualX * pScrn->virtualY * 3166ab47cfaaSmrg (DEPTH_BPP(DEPTH_2ND(pScrn))) >> 3) 3167ab47cfaaSmrg > (psav->CursorKByte * 1024)) 3168ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_WARNING, 3169ab47cfaaSmrg "Not enough memory for overlay mode: disabling\n"); 3170ab47cfaaSmrg else psav->FBStart2nd = psav->FBStart 3171ab47cfaaSmrg + ((pScrn->virtualX * pScrn->virtualY + 0xff) & ~0xff); 3172ab47cfaaSmrg 3173ab47cfaaSmrg } 3174ab47cfaaSmrg 3175ab47cfaaSmrg SavageInitShadowStatus(pScrn); 3176ab47cfaaSmrg psav->ShadowCounter = 0; 3177ab47cfaaSmrg 3178ab47cfaaSmrg SavageSave(pScrn); 3179ab47cfaaSmrg 3180ab47cfaaSmrg vgaHWBlankScreen(pScrn, TRUE); 3181ab47cfaaSmrg 3182ab47cfaaSmrg#ifdef XF86DRI 3183ab47cfaaSmrg if (!xf86ReturnOptValBool(psav->Options, OPTION_DRI, TRUE)) { 3184ab47cfaaSmrg psav->directRenderingEnabled = FALSE; 3185ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3186ab47cfaaSmrg "Direct rendering forced off\n"); 3187ab47cfaaSmrg } else if (psav->IsSecondary) { 3188ab47cfaaSmrg psav->directRenderingEnabled = FALSE; 3189ab47cfaaSmrg } else if (xf86IsEntityShared(psav->pEnt->index)) { 3190ab47cfaaSmrg /* Xinerama has sync problem with DRI, disable it for now */ 3191ab47cfaaSmrg psav->directRenderingEnabled = FALSE; 3192ab47cfaaSmrg xf86DrvMsg(scrnIndex, X_WARNING, 3193ab47cfaaSmrg "Direct Rendering Disabled -- " 3194ab47cfaaSmrg "Dual-head configuration is not working with " 3195ab47cfaaSmrg "DRI at present.\n"); 3196ab47cfaaSmrg } else if (/*!psav->bTiled*/psav->bDisableTile) { 3197ab47cfaaSmrg xf86DrvMsg(scrnIndex, X_WARNING, 3198ab47cfaaSmrg "Direct Rendering requires a tiled framebuffer -- " 3199ab47cfaaSmrg "Set Option \"DisableTile\" \"false\"\n"); 3200ab47cfaaSmrg } else if (psav->cobSize == 0) { 3201ab47cfaaSmrg xf86DrvMsg(scrnIndex, X_WARNING, 3202ab47cfaaSmrg "Direct Rendering requires the COB -- " 3203ab47cfaaSmrg "Set Option \"DisableCOB\" \"false\"\n"); 3204ab47cfaaSmrg } else if (((psav->Chipset == S3_TWISTER) 3205ab47cfaaSmrg || (psav->Chipset == S3_PROSAVAGE) 3206ab47cfaaSmrg || (psav->Chipset == S3_SAVAGE4) 3207ab47cfaaSmrg || (psav->Chipset == S3_SAVAGE_MX) 3208ab47cfaaSmrg || (psav->Chipset == S3_SAVAGE3D) 3209ab47cfaaSmrg || (psav->Chipset == S3_SUPERSAVAGE) 3210ab47cfaaSmrg || (psav->Chipset == S3_PROSAVAGEDDR)) 3211ab47cfaaSmrg && (!psav->NoAccel) 3212ab47cfaaSmrg && (SavageCheckAvailableRamFor3D(pScrn))) { 3213ab47cfaaSmrg /* Setup DRI after visuals have been established */ 3214ab47cfaaSmrg psav->directRenderingEnabled = SAVAGEDRIScreenInit(pScreen); 3215ab47cfaaSmrg /* If DRI init failed, reset shadow status. */ 3216ab47cfaaSmrg if (!psav->directRenderingEnabled && 3217ab47cfaaSmrg psav->ShadowStatus != psav->ConfigShadowStatus) { 3218ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n"); 3219ab47cfaaSmrg SavageInitShadowStatus(pScrn); 3220ab47cfaaSmrg } 3221ab47cfaaSmrg /* If shadow status was enabled for DRI, hook up the shadow 3222ab47cfaaSmrg * waiting functions now. */ 3223ab47cfaaSmrg else if (psav->ShadowStatus && !psav->ConfigShadowStatus) { 3224ab47cfaaSmrg psav->WaitQueue = ShadowWaitQueue; 3225ab47cfaaSmrg psav->WaitIdle = ShadowWait; 3226ab47cfaaSmrg psav->WaitIdleEmpty = ShadowWait; 3227ab47cfaaSmrg } 3228ab47cfaaSmrg } else 3229ab47cfaaSmrg psav->directRenderingEnabled = FALSE; 3230ab47cfaaSmrg 3231ab47cfaaSmrg if(psav->directRenderingEnabled) { 3232ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"DRI is enabled\n"); 3233ab47cfaaSmrg } 3234ab47cfaaSmrg else { 3235ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DRI isn't enabled\n"); 3236ab47cfaaSmrg } 3237ab47cfaaSmrg#endif 3238ab47cfaaSmrg 3239ab47cfaaSmrg if (!SavageModeInit(pScrn, pScrn->currentMode)) 3240ab47cfaaSmrg return FALSE; 3241ab47cfaaSmrg 3242ab47cfaaSmrg miClearVisualTypes(); 3243ab47cfaaSmrg 3244ab47cfaaSmrg { 3245ab47cfaaSmrg int visual; 3246ab47cfaaSmrg 3247ab47cfaaSmrg visual = ((psav->FBStart2nd && pScrn->bitsPerPixel > 8) 3248ab47cfaaSmrg || pScrn->bitsPerPixel == 16) ? TrueColorMask 3249ab47cfaaSmrg : miGetDefaultVisualMask(DEPTH_BPP(pScrn->depth)); 3250ab47cfaaSmrg if (!miSetVisualTypes(pScrn->depth, visual, 3251ab47cfaaSmrg pScrn->rgbBits, pScrn->defaultVisual)) 3252ab47cfaaSmrg return FALSE; 3253ab47cfaaSmrg 3254ab47cfaaSmrg if (psav->FBStart2nd) {/* we have overlay */ 3255ab47cfaaSmrg visual = psav->overlayDepth > 8 ? TrueColorMask : 3256ab47cfaaSmrg miGetDefaultVisualMask(DEPTH_BPP(psav->overlayDepth)); 3257ab47cfaaSmrg if (!miSetVisualTypes(psav->overlayDepth, visual, 3258ab47cfaaSmrg psav->overlayDepth > 8 ? 8 : 6, 3259ab47cfaaSmrg pScrn->defaultVisual)) 3260ab47cfaaSmrg return FALSE; 3261ab47cfaaSmrg } 3262ab47cfaaSmrg } 3263ab47cfaaSmrg if (!miSetPixmapDepths ()) 3264ab47cfaaSmrg return FALSE; 3265ab47cfaaSmrg 3266ab47cfaaSmrg ret = SavageInternalScreenInit(scrnIndex, pScreen); 3267ab47cfaaSmrg if (!ret) 3268ab47cfaaSmrg return FALSE; 3269ab47cfaaSmrg 3270ab47cfaaSmrg xf86SetBlackWhitePixels(pScreen); 3271ab47cfaaSmrg 3272ab47cfaaSmrg { 3273ab47cfaaSmrg VisualPtr visual; 3274ab47cfaaSmrg visual = pScreen->visuals + pScreen->numVisuals; 3275ab47cfaaSmrg while (--visual >= pScreen->visuals) { 3276ab47cfaaSmrg if ((visual->class | DynamicClass) == DirectColor 3277ab47cfaaSmrg && visual->nplanes > MAX_PSEUDO_DEPTH) { 3278ab47cfaaSmrg if (visual->nplanes == pScrn->depth) { 3279ab47cfaaSmrg visual->offsetRed = pScrn->offset.red; 3280ab47cfaaSmrg visual->offsetGreen = pScrn->offset.green; 3281ab47cfaaSmrg visual->offsetBlue = pScrn->offset.blue; 3282ab47cfaaSmrg visual->redMask = pScrn->mask.red; 3283ab47cfaaSmrg visual->greenMask = pScrn->mask.green; 3284ab47cfaaSmrg visual->blueMask = pScrn->mask.blue; 3285ab47cfaaSmrg } else if (visual->offsetRed > 8 3286ab47cfaaSmrg || visual->offsetGreen > 8 3287ab47cfaaSmrg || visual->offsetBlue > 8) { 3288ab47cfaaSmrg /* 3289ab47cfaaSmrg * mi has set these wrong. fix it here -- we cannot use pScrn 3290ab47cfaaSmrg * as this is set up for the default depth 8. 3291ab47cfaaSmrg */ 3292ab47cfaaSmrg int tmp; 3293ab47cfaaSmrg int c_s = 0; 3294ab47cfaaSmrg 3295ab47cfaaSmrg tmp = visual->offsetBlue; 3296ab47cfaaSmrg visual->offsetBlue = visual->offsetRed; 3297ab47cfaaSmrg visual->offsetRed = tmp; 3298ab47cfaaSmrg tmp = visual->blueMask; 3299ab47cfaaSmrg visual->blueMask = visual->redMask; 3300ab47cfaaSmrg visual->redMask = tmp; 3301ab47cfaaSmrg switch (DEPTH_2ND(pScrn)) { 3302ab47cfaaSmrg case 16: 3303ab47cfaaSmrg visual->offsetRed = 11; 3304ab47cfaaSmrg visual->offsetGreen = 5; 3305ab47cfaaSmrg visual->offsetBlue = 0; 3306ab47cfaaSmrg visual->redMask = 0xF800; 3307ab47cfaaSmrg visual->greenMask = 0x7E0; 3308ab47cfaaSmrg visual->blueMask = 0x1F; 3309ab47cfaaSmrg break; 3310ab47cfaaSmrg case 24: 3311ab47cfaaSmrg visual->offsetRed = 16; 3312ab47cfaaSmrg visual->offsetGreen = 8; 3313ab47cfaaSmrg visual->offsetBlue = 0; 3314ab47cfaaSmrg visual->redMask = 0xFF0000; 3315ab47cfaaSmrg visual->greenMask = 0xFF00; 3316ab47cfaaSmrg visual->blueMask = 0xFF; 3317ab47cfaaSmrg c_s = 2; 3318ab47cfaaSmrg break; 3319ab47cfaaSmrg } 3320ab47cfaaSmrg psav->overlay.redMask = visual->redMask; 3321ab47cfaaSmrg psav->overlay.greenMask = visual->greenMask; 3322ab47cfaaSmrg psav->overlay.blueMask = visual->blueMask; 3323ab47cfaaSmrg psav->overlay.redShift = visual->offsetRed + c_s; 3324ab47cfaaSmrg psav->overlay.greenShift = visual->offsetGreen + c_s; 3325ab47cfaaSmrg psav->overlay.blueShift = visual->offsetBlue + c_s; 3326ab47cfaaSmrg } 3327ab47cfaaSmrg } 3328ab47cfaaSmrg } 3329ab47cfaaSmrg } 3330ab47cfaaSmrg 3331ab47cfaaSmrg /* must be after RGB ordering fixed */ 3332ab47cfaaSmrg fbPictureInit (pScreen, 0, 0); 3333ab47cfaaSmrg 3334ab47cfaaSmrg if( !psav->NoAccel ) { 3335ab47cfaaSmrg SavageInitAccel(pScreen); 3336ab47cfaaSmrg } 3337ab47cfaaSmrg 3338ab47cfaaSmrg miInitializeBackingStore(pScreen); 3339ab47cfaaSmrg xf86SetBackingStore(pScreen); 3340ab47cfaaSmrg 3341ab47cfaaSmrg if( !psav->shadowFB && !psav->useEXA ) 3342ab47cfaaSmrg SavageDGAInit(pScreen); 3343ab47cfaaSmrg 3344ab47cfaaSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 3345ab47cfaaSmrg 3346ab47cfaaSmrg if (psav->hwcursor) 3347ab47cfaaSmrg if (!SavageHWCursorInit(pScreen)) 3348ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 3349ab47cfaaSmrg "Hardware cursor initialization failed\n"); 3350ab47cfaaSmrg 3351ab47cfaaSmrg if (psav->shadowFB) { 3352ab47cfaaSmrg RefreshAreaFuncPtr refreshArea = SavageRefreshArea; 3353ab47cfaaSmrg 3354ab47cfaaSmrg if(psav->rotate) { 3355ab47cfaaSmrg if (!psav->PointerMoved) { 3356ab47cfaaSmrg psav->PointerMoved = pScrn->PointerMoved; 3357ab47cfaaSmrg pScrn->PointerMoved = SavagePointerMoved; 3358ab47cfaaSmrg } 3359ab47cfaaSmrg 3360ab47cfaaSmrg switch(pScrn->bitsPerPixel) { 3361ab47cfaaSmrg case 8: refreshArea = SavageRefreshArea8; break; 3362ab47cfaaSmrg case 16: refreshArea = SavageRefreshArea16; break; 3363ab47cfaaSmrg case 24: refreshArea = SavageRefreshArea24; break; 3364ab47cfaaSmrg case 32: refreshArea = SavageRefreshArea32; break; 3365ab47cfaaSmrg } 3366ab47cfaaSmrg } 3367ab47cfaaSmrg 3368ab47cfaaSmrg ShadowFBInit(pScreen, refreshArea); 3369ab47cfaaSmrg } 3370ab47cfaaSmrg 3371ab47cfaaSmrg if (!miCreateDefColormap(pScreen)) 3372ab47cfaaSmrg return FALSE; 3373ab47cfaaSmrg 3374ab47cfaaSmrg colormapFlags = CMAP_RELOAD_ON_MODE_SWITCH 3375ab47cfaaSmrg | ((psav->FBStart2nd) ? 0 : CMAP_PALETTED_TRUECOLOR); 3376ab47cfaaSmrg 3377ab47cfaaSmrg if (psav->Chipset == S3_SAVAGE4) { 3378ab47cfaaSmrg if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPaletteSavage4, 3379ab47cfaaSmrg NULL, colormapFlags )) 3380ab47cfaaSmrg return FALSE; 3381ab47cfaaSmrg } else { 3382ab47cfaaSmrg if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPalette, NULL, 3383ab47cfaaSmrg colormapFlags )) 3384ab47cfaaSmrg return FALSE; 3385ab47cfaaSmrg } 3386ab47cfaaSmrg 3387ab47cfaaSmrg vgaHWBlankScreen(pScrn, FALSE); 3388ab47cfaaSmrg 3389ab47cfaaSmrg psav->CloseScreen = pScreen->CloseScreen; 3390ab47cfaaSmrg pScreen->SaveScreen = SavageSaveScreen; 3391ab47cfaaSmrg pScreen->CloseScreen = SavageCloseScreen; 3392ab47cfaaSmrg 3393ab47cfaaSmrg if (xf86DPMSInit(pScreen, SavageDPMS, 0) == FALSE) 3394ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed\n"); 3395ab47cfaaSmrg 3396ab47cfaaSmrg#ifdef XF86DRI 3397ab47cfaaSmrg if (psav->directRenderingEnabled) { 3398ab47cfaaSmrg /* complete the DRI setup.*/ 3399ab47cfaaSmrg psav->directRenderingEnabled = SAVAGEDRIFinishScreenInit(pScreen); 3400ab47cfaaSmrg /* If DRI initialization failed, reset shadow status and 3401ab47cfaaSmrg * reinitialize 2D engine. */ 3402ab47cfaaSmrg if (!psav->directRenderingEnabled && 3403ab47cfaaSmrg psav->ShadowStatus != psav->ConfigShadowStatus) { 3404ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n"); 3405ab47cfaaSmrg SavageInitShadowStatus(pScrn); 3406ab47cfaaSmrg SavageInitialize2DEngine(pScrn); 3407ab47cfaaSmrg } 3408ab47cfaaSmrg } 3409ab47cfaaSmrg if (psav->directRenderingEnabled) { 3410ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 3411ab47cfaaSmrg } else { 3412ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); 3413ab47cfaaSmrg } 3414ab47cfaaSmrg#endif 3415ab47cfaaSmrg 3416ab47cfaaSmrg SavagePanningCheck(pScrn); 3417ab47cfaaSmrg#ifdef XvExtension 3418ab47cfaaSmrg if( !psav->FBStart2nd && !psav->NoAccel /*&& !SavagePanningCheck(pScrn)*/ ) { 3419ab47cfaaSmrg if (psav->IsSecondary) 3420ab47cfaaSmrg /* Xv should work on crtc2, but I haven't gotten there yet. -- AGD */ 3421ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv currently disabled for crtc2.\n"); 3422ab47cfaaSmrg else 3423ab47cfaaSmrg SavageInitVideo( pScreen ); 3424ab47cfaaSmrg } 3425ab47cfaaSmrg#endif 3426ab47cfaaSmrg 3427ab47cfaaSmrg#ifdef XF86DRI 3428ab47cfaaSmrg if ((psav->directRenderingEnabled) && (!psav->bDisableXvMC)) { 3429ab47cfaaSmrg if (SAVAGEInitMC(pScreen)) 3430ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is enabled\n"); 3431ab47cfaaSmrg else 3432ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is not enabled\n"); 3433ab47cfaaSmrg } 3434ab47cfaaSmrg#endif 3435ab47cfaaSmrg 3436ab47cfaaSmrg if (serverGeneration == 1) 3437ab47cfaaSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 3438ab47cfaaSmrg 3439ab47cfaaSmrg return TRUE; 3440ab47cfaaSmrg} 3441ab47cfaaSmrg 3442ab47cfaaSmrg 3443ab47cfaaSmrgstatic int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen) 3444ab47cfaaSmrg{ 3445ab47cfaaSmrg int ret = TRUE; 3446ab47cfaaSmrg ScrnInfoPtr pScrn; 3447ab47cfaaSmrg SavagePtr psav; 3448ab47cfaaSmrg int width, height, displayWidth; 3449ab47cfaaSmrg unsigned char *FBStart; 3450ab47cfaaSmrg 3451ab47cfaaSmrg TRACE(("SavageInternalScreenInit()\n")); 3452ab47cfaaSmrg 3453ab47cfaaSmrg pScrn = xf86Screens[pScreen->myNum]; 3454ab47cfaaSmrg psav = SAVPTR(pScrn); 3455ab47cfaaSmrg 3456ab47cfaaSmrg displayWidth = pScrn->displayWidth; 3457ab47cfaaSmrg 3458ab47cfaaSmrg if (psav->rotate) { 3459ab47cfaaSmrg height = pScrn->virtualX; 3460ab47cfaaSmrg width = pScrn->virtualY; 3461ab47cfaaSmrg } else { 3462ab47cfaaSmrg width = pScrn->virtualX; 3463ab47cfaaSmrg height = pScrn->virtualY; 3464ab47cfaaSmrg } 3465ab47cfaaSmrg 3466ab47cfaaSmrg 3467ab47cfaaSmrg if(psav->shadowFB) { 3468ab47cfaaSmrg psav->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 3469ab47cfaaSmrg psav->ShadowPtr = xalloc(psav->ShadowPitch * height); 3470ab47cfaaSmrg displayWidth = psav->ShadowPitch / (pScrn->bitsPerPixel >> 3); 3471ab47cfaaSmrg FBStart = psav->ShadowPtr; 3472ab47cfaaSmrg } else { 3473ab47cfaaSmrg psav->ShadowPtr = NULL; 3474ab47cfaaSmrg FBStart = psav->FBStart; 3475ab47cfaaSmrg } 3476ab47cfaaSmrg 3477ab47cfaaSmrg if (!psav->FBStart2nd) { 3478ab47cfaaSmrg 3479ab47cfaaSmrg ret = fbScreenInit(pScreen, FBStart, width, height, 3480ab47cfaaSmrg pScrn->xDpi, pScrn->yDpi, 3481ab47cfaaSmrg psav->ulAperturePitch / (pScrn->bitsPerPixel >> 3), /*displayWidth,*/ 3482ab47cfaaSmrg pScrn->bitsPerPixel); 3483ab47cfaaSmrg 3484ab47cfaaSmrg } else { 3485ab47cfaaSmrg FbOverlayScrPrivPtr pScrPriv; 3486ab47cfaaSmrg int Depth2nd = DEPTH_2ND(pScrn); 3487ab47cfaaSmrg if (!fbSetupScreen (pScreen, FBStart, width, height, 3488ab47cfaaSmrg pScrn->xDpi, pScrn->yDpi, displayWidth, 8)) 3489ab47cfaaSmrg return FALSE; 3490ab47cfaaSmrg if (pScrn->depth == 8) { 3491ab47cfaaSmrg ret = fbOverlayFinishScreenInit (pScreen, FBStart, 3492ab47cfaaSmrg psav->FBStart2nd, width, 3493ab47cfaaSmrg height,pScrn->xDpi, pScrn->yDpi, 3494ab47cfaaSmrg displayWidth,displayWidth, 3495ab47cfaaSmrg 8, DEPTH_BPP(Depth2nd), 3496ab47cfaaSmrg 8, Depth2nd); 3497ab47cfaaSmrg pScrPriv = fbOverlayGetScrPriv(pScreen); 3498ab47cfaaSmrg pScrPriv->layer[0].key = pScrn->colorKey; 3499ab47cfaaSmrg } else { 3500ab47cfaaSmrg ret = fbOverlayFinishScreenInit (pScreen, psav->FBStart2nd, 3501ab47cfaaSmrg FBStart, 3502ab47cfaaSmrg width, height,pScrn->xDpi, 3503ab47cfaaSmrg pScrn->yDpi, 3504ab47cfaaSmrg displayWidth,displayWidth, 3505ab47cfaaSmrg DEPTH_BPP(Depth2nd), 8, 3506ab47cfaaSmrg Depth2nd, 8); 3507ab47cfaaSmrg pScrPriv = fbOverlayGetScrPriv(pScreen); 3508ab47cfaaSmrg pScrPriv->layer[1].key = pScrn->colorKey; 3509ab47cfaaSmrg } 3510ab47cfaaSmrg } 3511ab47cfaaSmrg return ret; 3512ab47cfaaSmrg} 3513ab47cfaaSmrg 3514ab47cfaaSmrg 3515ab47cfaaSmrgstatic int SavageGetRefresh(DisplayModePtr mode) 3516ab47cfaaSmrg{ 3517ab47cfaaSmrg int refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal); 3518ab47cfaaSmrg if (mode->Flags & V_INTERLACE) 3519ab47cfaaSmrg refresh *= 2.0; 3520ab47cfaaSmrg if (mode->Flags & V_DBLSCAN) 3521ab47cfaaSmrg refresh /= 2.0; 3522ab47cfaaSmrg if (mode->VScan > 1) 3523ab47cfaaSmrg refresh /= mode->VScan; 3524ab47cfaaSmrg return refresh; 3525ab47cfaaSmrg} 3526ab47cfaaSmrg 3527ab47cfaaSmrg 3528ab47cfaaSmrgstatic ModeStatus SavageValidMode(int index, DisplayModePtr pMode, 3529ab47cfaaSmrg Bool verbose, int flags) 3530ab47cfaaSmrg{ 3531ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[index]; 3532ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3533ab47cfaaSmrg int refresh; 3534ab47cfaaSmrg 3535ab47cfaaSmrg TRACE(("SavageValidMode\n")); 3536ab47cfaaSmrg 3537ab47cfaaSmrg /* We prohibit modes bigger than the LCD panel. */ 3538ab47cfaaSmrg /* TODO We should do this only if the panel is active. */ 3539ab47cfaaSmrg 3540ab47cfaaSmrg if( psav->TvOn ) 3541ab47cfaaSmrg { 3542ab47cfaaSmrg if( pMode->HDisplay > psav->TVSizeX ) 3543ab47cfaaSmrg return MODE_VIRTUAL_X; 3544ab47cfaaSmrg 3545ab47cfaaSmrg if( pMode->VDisplay > psav->TVSizeY ) 3546ab47cfaaSmrg return MODE_VIRTUAL_Y; 3547ab47cfaaSmrg 3548ab47cfaaSmrg } 3549ab47cfaaSmrg 3550ab47cfaaSmrg if((psav->DisplayType == MT_LCD) && 3551ab47cfaaSmrg ((pMode->HDisplay > psav->PanelX) || 3552ab47cfaaSmrg (pMode->VDisplay > psav->PanelY))) 3553ab47cfaaSmrg return MODE_PANEL; 3554ab47cfaaSmrg 3555ab47cfaaSmrg if (psav->UseBIOS) { 3556ab47cfaaSmrg refresh = SavageGetRefresh(pMode); 3557ab47cfaaSmrg return (SavageMatchBiosMode(pScrn,pMode->HDisplay, 3558ab47cfaaSmrg pMode->VDisplay, 3559ab47cfaaSmrg refresh,NULL,NULL)); 3560ab47cfaaSmrg } 3561ab47cfaaSmrg 3562ab47cfaaSmrg return MODE_OK; 3563ab47cfaaSmrg} 3564ab47cfaaSmrg 3565ab47cfaaSmrgstatic Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 3566ab47cfaaSmrg{ 3567ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3568ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3569ab47cfaaSmrg int width, dclk, i, j; /*, refresh; */ 3570ab47cfaaSmrg unsigned int m, n, r; 3571ab47cfaaSmrg unsigned char tmp = 0; 3572ab47cfaaSmrg SavageRegPtr new = &psav->ModeReg; 3573ab47cfaaSmrg vgaRegPtr vganew = &hwp->ModeReg; 3574ab47cfaaSmrg int vgaCRIndex, vgaCRReg, vgaIOBase; 3575ab47cfaaSmrg int refresh; 3576ab47cfaaSmrg unsigned int newmode=0, newrefresh=0; 3577ab47cfaaSmrg 3578ab47cfaaSmrg vgaIOBase = hwp->IOBase; 3579ab47cfaaSmrg vgaCRIndex = vgaIOBase + 4; 3580ab47cfaaSmrg vgaCRReg = vgaIOBase + 5; 3581ab47cfaaSmrg 3582ab47cfaaSmrg TRACE(("SavageModeInit(%dx%d, %dHz)\n", 3583ab47cfaaSmrg mode->HDisplay, mode->VDisplay, mode->Clock)); 3584ab47cfaaSmrg 3585ab47cfaaSmrg#if 0 3586ab47cfaaSmrg ErrorF("Clock = %d, HDisplay = %d, HSStart = %d\n", 3587ab47cfaaSmrg mode->Clock, mode->HDisplay, mode->HSyncStart); 3588ab47cfaaSmrg ErrorF("HSEnd = %d, HSkew = %d\n", 3589ab47cfaaSmrg mode->HSyncEnd, mode->HSkew); 3590ab47cfaaSmrg ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n", 3591ab47cfaaSmrg mode->VDisplay, mode->VSyncStart, mode->VSyncEnd); 3592ab47cfaaSmrg ErrorF("VTotal = %d\n", 3593ab47cfaaSmrg mode->VTotal); 3594ab47cfaaSmrg ErrorF("HDisplay = %d, HSStart = %d\n", 3595ab47cfaaSmrg mode->CrtcHDisplay, mode->CrtcHSyncStart); 3596ab47cfaaSmrg ErrorF("HSEnd = %d, HSkey = %d\n", 3597ab47cfaaSmrg mode->CrtcHSyncEnd, mode->CrtcHSkew); 3598ab47cfaaSmrg ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n", 3599ab47cfaaSmrg mode->CrtcVDisplay, mode->CrtcVSyncStart, mode->CrtcVSyncEnd); 3600ab47cfaaSmrg ErrorF("VTotal = %d\n", 3601ab47cfaaSmrg mode->CrtcVTotal); 3602ab47cfaaSmrg#endif 3603ab47cfaaSmrg 3604ab47cfaaSmrg if (psav->IsSecondary) { 3605ab47cfaaSmrg refresh = SavageGetRefresh(mode); 3606ab47cfaaSmrg 3607ab47cfaaSmrg SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, 3608ab47cfaaSmrg &newmode,&newrefresh); 3609ab47cfaaSmrg new->mode = newmode; 3610ab47cfaaSmrg new->refresh = newrefresh; 3611ab47cfaaSmrg 3612ab47cfaaSmrg /* do it! */ 3613ab47cfaaSmrg SavageWriteMode(pScrn, vganew, new, TRUE); 3614ab47cfaaSmrg 3615ab47cfaaSmrg if (psav->FBStart2nd) { 3616ab47cfaaSmrg SavageStreamsOn(pScrn); 3617ab47cfaaSmrg SavageInitSecondaryStream(pScrn); 3618ab47cfaaSmrg } 3619ab47cfaaSmrg 3620ab47cfaaSmrg SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3621ab47cfaaSmrg return TRUE; 3622ab47cfaaSmrg } 3623ab47cfaaSmrg 3624ab47cfaaSmrg 3625ab47cfaaSmrg if (pScrn->bitsPerPixel == 8) 3626ab47cfaaSmrg psav->HorizScaleFactor = 1; 3627ab47cfaaSmrg else if (pScrn->bitsPerPixel == 16) 3628ab47cfaaSmrg psav->HorizScaleFactor = 1; /* I don't think we ever want 2 */ 3629ab47cfaaSmrg else 3630ab47cfaaSmrg psav->HorizScaleFactor = 1; 3631ab47cfaaSmrg 3632ab47cfaaSmrg if (psav->HorizScaleFactor == 2) 3633ab47cfaaSmrg if (!mode->CrtcHAdjusted) { 3634ab47cfaaSmrg mode->CrtcHDisplay *= 2; 3635ab47cfaaSmrg mode->CrtcHSyncStart *= 2; 3636ab47cfaaSmrg mode->CrtcHSyncEnd *= 2; 3637ab47cfaaSmrg mode->CrtcHBlankStart *= 2; 3638ab47cfaaSmrg mode->CrtcHBlankEnd *= 2; 3639ab47cfaaSmrg mode->CrtcHTotal *= 2; 3640ab47cfaaSmrg mode->CrtcHSkew *= 2; 3641ab47cfaaSmrg mode->CrtcHAdjusted = TRUE; 3642ab47cfaaSmrg } 3643ab47cfaaSmrg 3644ab47cfaaSmrg if (!vgaHWInit(pScrn, mode)) 3645ab47cfaaSmrg return FALSE; 3646ab47cfaaSmrg 3647ab47cfaaSmrg new->mode = 0; 3648ab47cfaaSmrg 3649ab47cfaaSmrg /* We need to set CR67 whether or not we use the BIOS. */ 3650ab47cfaaSmrg 3651ab47cfaaSmrg dclk = mode->Clock; 3652ab47cfaaSmrg new->CR67 = 0x00; 3653ab47cfaaSmrg 3654ab47cfaaSmrg switch( pScrn->depth ) { 3655ab47cfaaSmrg case 8: 3656ab47cfaaSmrg if( (psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000) ) 3657ab47cfaaSmrg new->CR67 = 0x10; /* 8bpp, 2 pixels/clock */ 3658ab47cfaaSmrg else 3659ab47cfaaSmrg new->CR67 = 0x00; /* 8bpp, 1 pixel/clock */ 3660ab47cfaaSmrg break; 3661ab47cfaaSmrg case 15: 3662ab47cfaaSmrg if( 3663ab47cfaaSmrg S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 3664ab47cfaaSmrg ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000)) 3665ab47cfaaSmrg ) 3666ab47cfaaSmrg new->CR67 = 0x30; /* 15bpp, 2 pixel/clock */ 3667ab47cfaaSmrg else 3668ab47cfaaSmrg new->CR67 = 0x20; /* 15bpp, 1 pixels/clock */ 3669ab47cfaaSmrg break; 3670ab47cfaaSmrg case 16: 3671ab47cfaaSmrg if( 3672ab47cfaaSmrg S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || 3673ab47cfaaSmrg ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000)) 3674ab47cfaaSmrg ) 3675ab47cfaaSmrg new->CR67 = 0x50; /* 16bpp, 2 pixel/clock */ 3676ab47cfaaSmrg else 3677ab47cfaaSmrg new->CR67 = 0x40; /* 16bpp, 1 pixels/clock */ 3678ab47cfaaSmrg break; 3679ab47cfaaSmrg case 24: 3680ab47cfaaSmrg if (psav->primStreamBpp == 24 ) 3681ab47cfaaSmrg new->CR67 = 0x70; 3682ab47cfaaSmrg else 3683ab47cfaaSmrg new->CR67 = 0xd0; 3684ab47cfaaSmrg break; 3685ab47cfaaSmrg } 3686ab47cfaaSmrg 3687ab47cfaaSmrg 3688ab47cfaaSmrg if( psav->UseBIOS ) { 3689ab47cfaaSmrg int refresh; 3690ab47cfaaSmrg unsigned int newmode=0, newrefresh=0; 3691ab47cfaaSmrg 3692ab47cfaaSmrg refresh = SavageGetRefresh(mode); 3693ab47cfaaSmrg 3694ab47cfaaSmrg SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh, 3695ab47cfaaSmrg &newmode,&newrefresh); 3696ab47cfaaSmrg new->mode = newmode; 3697ab47cfaaSmrg new->refresh = newrefresh; 3698ab47cfaaSmrg } 3699ab47cfaaSmrg 3700ab47cfaaSmrg if( !new->mode ) { 3701ab47cfaaSmrg /* 3702ab47cfaaSmrg * Either BIOS use is disabled, or we failed to find a suitable 3703ab47cfaaSmrg * match. Fall back to traditional register-crunching. 3704ab47cfaaSmrg */ 3705ab47cfaaSmrg 3706ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x3a); 3707ab47cfaaSmrg tmp = VGAIN8(vgaCRReg); 3708ab47cfaaSmrg if (psav->pci_burst) 3709ab47cfaaSmrg new->CR3A = (tmp & 0x7f) | 0x15; 3710ab47cfaaSmrg else 3711ab47cfaaSmrg new->CR3A = tmp | 0x95; 3712ab47cfaaSmrg 3713ab47cfaaSmrg new->CR53 = 0x00; 3714ab47cfaaSmrg new->CR31 = 0x8c; 3715ab47cfaaSmrg new->CR66 = 0x89; 3716ab47cfaaSmrg 3717ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x58); 3718ab47cfaaSmrg new->CR58 = VGAIN8(vgaCRReg) & 0x80; 3719ab47cfaaSmrg new->CR58 |= 0x13; 3720ab47cfaaSmrg 3721ab47cfaaSmrg#if 0 3722ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x55); 3723ab47cfaaSmrg new->CR55 = VGAIN8(vgaCRReg); 3724ab47cfaaSmrg if (psav->hwcursor) 3725ab47cfaaSmrg new->CR55 |= 0x10; 3726ab47cfaaSmrg#endif 3727ab47cfaaSmrg 3728ab47cfaaSmrg new->SR15 = 0x03 | 0x80; 3729ab47cfaaSmrg new->SR18 = 0x00; 3730ab47cfaaSmrg 3731ab47cfaaSmrg 3732ab47cfaaSmrg /* enable gamma correction */ 3733ab47cfaaSmrg if( pScrn->depth == 24 ) 3734ab47cfaaSmrg new->SR1B = 0x18; 3735ab47cfaaSmrg else 3736ab47cfaaSmrg new->SR1B = 0x00; 3737ab47cfaaSmrg 3738ab47cfaaSmrg /* set 8-bit CLUT */ 3739ab47cfaaSmrg new->SR1B |= 0x10; 3740ab47cfaaSmrg 3741ab47cfaaSmrg new->CR43 = new->CR45 = new->CR65 = 0x00; 3742ab47cfaaSmrg 3743ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x40); 3744ab47cfaaSmrg new->CR40 = VGAIN8(vgaCRReg) & ~0x01; 3745ab47cfaaSmrg 3746ab47cfaaSmrg new->MMPR0 = 0x010400; 3747ab47cfaaSmrg new->MMPR1 = 0x00; 3748ab47cfaaSmrg new->MMPR2 = 0x0808; 3749ab47cfaaSmrg new->MMPR3 = 0x08080810; 3750ab47cfaaSmrg 3751ab47cfaaSmrg if (psav->fifo_aggressive || psav->fifo_moderate || 3752ab47cfaaSmrg psav->fifo_conservative) { 3753ab47cfaaSmrg new->MMPR1 = 0x0200; 3754ab47cfaaSmrg new->MMPR2 = 0x1808; 3755ab47cfaaSmrg new->MMPR3 = 0x08081810; 3756ab47cfaaSmrg } 3757ab47cfaaSmrg 3758ab47cfaaSmrg if (psav->MCLK <= 0) { 3759ab47cfaaSmrg new->SR10 = 255; 3760ab47cfaaSmrg new->SR11 = 255; 3761ab47cfaaSmrg } 3762ab47cfaaSmrg 3763ab47cfaaSmrg psav->NeedSTREAMS = FALSE; 3764ab47cfaaSmrg 3765ab47cfaaSmrg SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, 3766ab47cfaaSmrg &m, &n, &r); 3767ab47cfaaSmrg new->SR12 = (r << 6) | (n & 0x3f); 3768ab47cfaaSmrg new->SR13 = m & 0xff; 3769ab47cfaaSmrg new->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; 3770ab47cfaaSmrg 3771ab47cfaaSmrg if (psav->fifo_moderate) { 3772ab47cfaaSmrg if (psav->primStreamBpp < 24) 3773ab47cfaaSmrg new->MMPR0 -= 0x8000; 3774ab47cfaaSmrg else 3775ab47cfaaSmrg new->MMPR0 -= 0x4000; 3776ab47cfaaSmrg } else if (psav->fifo_aggressive) { 3777ab47cfaaSmrg if (psav->primStreamBpp < 24) 3778ab47cfaaSmrg new->MMPR0 -= 0xc000; 3779ab47cfaaSmrg else 3780ab47cfaaSmrg new->MMPR0 -= 0x6000; 3781ab47cfaaSmrg } 3782ab47cfaaSmrg 3783ab47cfaaSmrg if (mode->Flags & V_INTERLACE) 3784ab47cfaaSmrg new->CR42 = 0x20; 3785ab47cfaaSmrg else 3786ab47cfaaSmrg new->CR42 = 0x00; 3787ab47cfaaSmrg 3788ab47cfaaSmrg new->CR34 = 0x10; 3789ab47cfaaSmrg 3790ab47cfaaSmrg i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | 3791ab47cfaaSmrg ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | 3792ab47cfaaSmrg ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | 3793ab47cfaaSmrg ((mode->CrtcHSyncStart & 0x800) >> 7); 3794ab47cfaaSmrg 3795ab47cfaaSmrg if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64) 3796ab47cfaaSmrg i |= 0x08; 3797ab47cfaaSmrg if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32) 3798ab47cfaaSmrg i |= 0x20; 3799ab47cfaaSmrg j = (vganew->CRTC[0] + ((i & 0x01) << 8) + 3800ab47cfaaSmrg vganew->CRTC[4] + ((i & 0x10) << 4) + 1) / 2; 3801ab47cfaaSmrg if (j - (vganew->CRTC[4] + ((i & 0x10) << 4)) < 4) { 3802ab47cfaaSmrg if (vganew->CRTC[4] + ((i & 0x10) << 4) + 4 <= 3803ab47cfaaSmrg vganew->CRTC[0] + ((i & 0x01) << 8)) 3804ab47cfaaSmrg j = vganew->CRTC[4] + ((i & 0x10) << 4) + 4; 3805ab47cfaaSmrg else 3806ab47cfaaSmrg j = vganew->CRTC[0] + ((i & 0x01) << 8) + 1; 3807ab47cfaaSmrg } 3808ab47cfaaSmrg 3809ab47cfaaSmrg new->CR3B = j & 0xff; 3810ab47cfaaSmrg i |= (j & 0x100) >> 2; 3811ab47cfaaSmrg new->CR3C = (vganew->CRTC[0] + ((i & 0x01) << 8)) / 2 ; 3812ab47cfaaSmrg new->CR5D = i; 3813ab47cfaaSmrg new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) | 3814ab47cfaaSmrg (((mode->CrtcVDisplay - 1) & 0x400) >> 9) | 3815ab47cfaaSmrg (((mode->CrtcVSyncStart) & 0x400) >> 8) | 3816ab47cfaaSmrg (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40; 3817ab47cfaaSmrg width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3; 3818ab47cfaaSmrg new->CR91 = vganew->CRTC[19] = 0xff & width; 3819ab47cfaaSmrg new->CR51 = (0x300 & width) >> 4; 3820ab47cfaaSmrg new->CR90 = 0x80 | (width >> 8); 3821ab47cfaaSmrg vganew->MiscOutReg |= 0x0c; 3822ab47cfaaSmrg 3823ab47cfaaSmrg /* Set frame buffer description. */ 3824ab47cfaaSmrg 3825ab47cfaaSmrg if (psav->primStreamBpp <= 8) 3826ab47cfaaSmrg new->CR50 = 0; 3827ab47cfaaSmrg else if (psav->primStreamBpp <= 16) 3828ab47cfaaSmrg new->CR50 = 0x10; 3829ab47cfaaSmrg else 3830ab47cfaaSmrg new->CR50 = 0x30; 3831ab47cfaaSmrg 3832ab47cfaaSmrg if (pScrn->displayWidth == 640) 3833ab47cfaaSmrg new->CR50 |= 0x40; 3834ab47cfaaSmrg else if (pScrn->displayWidth == 800) 3835ab47cfaaSmrg new->CR50 |= 0x80; 3836ab47cfaaSmrg else if (pScrn->displayWidth == 1024) 3837ab47cfaaSmrg new->CR50 |= 0x00; 3838ab47cfaaSmrg else if (pScrn->displayWidth == 1152) 3839ab47cfaaSmrg new->CR50 |= 0x01; 3840ab47cfaaSmrg else if (pScrn->displayWidth == 1280) 3841ab47cfaaSmrg new->CR50 |= 0xc0; 3842ab47cfaaSmrg else if (pScrn->displayWidth == 1600) 3843ab47cfaaSmrg new->CR50 |= 0x81; 3844ab47cfaaSmrg else 3845ab47cfaaSmrg new->CR50 |= 0xc1; /* Use GBD */ 3846ab47cfaaSmrg 3847ab47cfaaSmrg if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) 3848ab47cfaaSmrg new->CR33 = 0x00; 3849ab47cfaaSmrg else 3850ab47cfaaSmrg new->CR33 = 0x08; 3851ab47cfaaSmrg 3852ab47cfaaSmrg vganew->CRTC[0x17] = 0xeb; 3853ab47cfaaSmrg 3854ab47cfaaSmrg new->CR67 |= 1; 3855ab47cfaaSmrg 3856ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x36); 3857ab47cfaaSmrg new->CR36 = VGAIN8(vgaCRReg); 3858ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x68); 3859ab47cfaaSmrg new->CR68 = VGAIN8(vgaCRReg); 3860ab47cfaaSmrg 3861ab47cfaaSmrg new->CR69 = 0; 3862ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x6f); 3863ab47cfaaSmrg new->CR6F = VGAIN8(vgaCRReg); 3864ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x86); 3865ab47cfaaSmrg new->CR86 = VGAIN8(vgaCRReg) | 0x08; 3866ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x88); 3867ab47cfaaSmrg new->CR88 = VGAIN8(vgaCRReg) | DISABLE_BLOCK_WRITE_2D; 3868ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0xb0); 3869ab47cfaaSmrg new->CRB0 = VGAIN8(vgaCRReg) | 0x80; 3870ab47cfaaSmrg } 3871ab47cfaaSmrg 3872ab47cfaaSmrg pScrn->vtSema = TRUE; 3873ab47cfaaSmrg 3874ab47cfaaSmrg /* do it! */ 3875ab47cfaaSmrg SavageWriteMode(pScrn, vganew, new, TRUE); 3876ab47cfaaSmrg 3877ab47cfaaSmrg if (psav->FBStart2nd) { 3878ab47cfaaSmrg SavageStreamsOn(pScrn); 3879ab47cfaaSmrg SavageInitSecondaryStream(pScrn); 3880ab47cfaaSmrg } 3881ab47cfaaSmrg 3882ab47cfaaSmrg SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3883ab47cfaaSmrg 3884ab47cfaaSmrg return TRUE; 3885ab47cfaaSmrg} 3886ab47cfaaSmrg 3887ab47cfaaSmrg 3888ab47cfaaSmrgstatic Bool SavageCloseScreen(int scrnIndex, ScreenPtr pScreen) 3889ab47cfaaSmrg{ 3890ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3891ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3892ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3893ab47cfaaSmrg vgaRegPtr vgaSavePtr = &hwp->SavedReg; 3894ab47cfaaSmrg SavageRegPtr SavageSavePtr = &psav->SavedReg; 3895ab47cfaaSmrg 3896ab47cfaaSmrg TRACE(("SavageCloseScreen\n")); 3897ab47cfaaSmrg 3898ab47cfaaSmrg#ifdef XF86DRI 3899ab47cfaaSmrg if (psav->directRenderingEnabled) { 3900ab47cfaaSmrg SAVAGEDRICloseScreen(pScreen); 3901ab47cfaaSmrg /* reset shadow values */ 3902ab47cfaaSmrg SavageInitShadowStatus(pScrn); 3903ab47cfaaSmrg psav->directRenderingEnabled=FALSE; 3904ab47cfaaSmrg } 3905ab47cfaaSmrg#endif 3906ab47cfaaSmrg 3907ab47cfaaSmrg if (psav->EXADriverPtr) { 3908ab47cfaaSmrg exaDriverFini(pScreen); 3909ab47cfaaSmrg psav->EXADriverPtr = NULL; 3910ab47cfaaSmrg } 3911ab47cfaaSmrg 3912ab47cfaaSmrg if( psav->AccelInfoRec ) { 3913ab47cfaaSmrg XAADestroyInfoRec( psav->AccelInfoRec ); 3914ab47cfaaSmrg psav->AccelInfoRec = NULL; 3915ab47cfaaSmrg } 3916ab47cfaaSmrg 3917ab47cfaaSmrg if( psav->DGAModes ) { 3918ab47cfaaSmrg xfree( psav->DGAModes ); 3919ab47cfaaSmrg psav->DGAModes = NULL; 3920ab47cfaaSmrg psav->numDGAModes = 0; 3921ab47cfaaSmrg } 3922ab47cfaaSmrg 3923ab47cfaaSmrg if (pScrn->vtSema) { 3924ab47cfaaSmrg if (psav->FBStart2nd) 3925ab47cfaaSmrg SavageStreamsOff(pScrn); 3926ab47cfaaSmrg SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE); 3927ab47cfaaSmrg SavageResetStreams(pScrn); 3928ab47cfaaSmrg vgaHWLock(hwp); 3929ab47cfaaSmrg SavageUnmapMem(pScrn, 0); 3930ab47cfaaSmrg } 3931ab47cfaaSmrg 3932ab47cfaaSmrg if (psav->pVbe) 3933ab47cfaaSmrg vbeFree(psav->pVbe); 3934ab47cfaaSmrg psav->pVbe = NULL; 3935ab47cfaaSmrg 3936ab47cfaaSmrg pScrn->vtSema = FALSE; 3937ab47cfaaSmrg pScreen->CloseScreen = psav->CloseScreen; 3938ab47cfaaSmrg 3939ab47cfaaSmrg return (*pScreen->CloseScreen)(scrnIndex, pScreen); 3940ab47cfaaSmrg} 3941ab47cfaaSmrg 3942ab47cfaaSmrg 3943ab47cfaaSmrgstatic Bool SavageSaveScreen(ScreenPtr pScreen, int mode) 3944ab47cfaaSmrg{ 3945ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3946ab47cfaaSmrg 3947ab47cfaaSmrg TRACE(("SavageSaveScreen(0x%x)\n", mode)); 3948ab47cfaaSmrg 3949ab47cfaaSmrg if( pScrn->vtSema && SAVPTR(pScrn)->hwcursor && SAVPTR(pScrn)->hwc_on ) 3950ab47cfaaSmrg { 3951ab47cfaaSmrg if( xf86IsUnblank(mode) ) 3952ab47cfaaSmrg SavageShowCursor( pScrn ); 3953ab47cfaaSmrg else 3954ab47cfaaSmrg SavageHideCursor( pScrn ); 3955ab47cfaaSmrg SAVPTR(pScrn)->hwc_on = TRUE; /*restore */ 3956ab47cfaaSmrg } 3957ab47cfaaSmrg 3958ab47cfaaSmrg return vgaHWSaveScreen(pScreen, mode); 3959ab47cfaaSmrg} 3960ab47cfaaSmrg 3961ab47cfaaSmrgvoid SavageAdjustFrame(int scrnIndex, int x, int y, int flags) 3962ab47cfaaSmrg{ 3963ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3964ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3965ab47cfaaSmrg 3966ab47cfaaSmrg if (psav->IsSecondary) { 3967ab47cfaaSmrg SavageDoAdjustFrame(pScrn, x, y, TRUE); 3968ab47cfaaSmrg } else { 3969ab47cfaaSmrg SavageDoAdjustFrame(pScrn, x, y, FALSE); 3970ab47cfaaSmrg } 3971ab47cfaaSmrg 3972ab47cfaaSmrg} 3973ab47cfaaSmrg 3974ab47cfaaSmrgvoid 3975ab47cfaaSmrgSavageDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int crtc2) 3976ab47cfaaSmrg{ 3977ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 3978ab47cfaaSmrg int address=0,top=0,left=0,tile_height,tile_size; 3979ab47cfaaSmrg 3980ab47cfaaSmrg TRACE(("SavageDoAdjustFrame(%d,%d,%x)\n", x, y, flags)); 3981ab47cfaaSmrg 3982ab47cfaaSmrg if (psav->Chipset == S3_SAVAGE2000) { 3983ab47cfaaSmrg tile_height = TILEHEIGHT_2000; /* 32 */ 3984ab47cfaaSmrg tile_size = TILE_SIZE_BYTE_2000; /* 4096 */ 3985ab47cfaaSmrg } else { 3986ab47cfaaSmrg tile_height = TILEHEIGHT; /* 16 */ 3987ab47cfaaSmrg tile_size = TILE_SIZE_BYTE; /* 2048 */ 3988ab47cfaaSmrg } 3989ab47cfaaSmrg 3990ab47cfaaSmrg if (!psav->bTiled) { 3991ab47cfaaSmrg left = x - x % 64; 3992ab47cfaaSmrg top = y; 3993ab47cfaaSmrg address = (top * psav->lDelta) + left * (pScrn->bitsPerPixel >> 3); 3994ab47cfaaSmrg address = (address >> 5) << 5; 3995ab47cfaaSmrg } else { 3996ab47cfaaSmrg top = y - y % tile_height; 3997ab47cfaaSmrg if (pScrn->bitsPerPixel == 16) { 3998ab47cfaaSmrg left = x - x % TILEWIDTH_16BPP; 3999ab47cfaaSmrg address = top * psav->lDelta + left * tile_size / TILEWIDTH_16BPP; 4000ab47cfaaSmrg } else if (pScrn->bitsPerPixel == 32) { 4001ab47cfaaSmrg left = x - x % TILEWIDTH_32BPP; 4002ab47cfaaSmrg address = top * psav->lDelta + left * tile_size / TILEWIDTH_32BPP; 4003ab47cfaaSmrg } 4004ab47cfaaSmrg } 4005ab47cfaaSmrg 4006ab47cfaaSmrg address += pScrn->fbOffset; 4007ab47cfaaSmrg 4008ab47cfaaSmrg if (psav->Chipset == S3_SAVAGE_MX) { 4009ab47cfaaSmrg if (!crtc2) { 4010ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC); 4011ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC);/* IGA1 */ 4012ab47cfaaSmrg } else { 4013ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR0, address & 0xFFFFFFFC);/* IGA2 */ 4014ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFFC); 4015ab47cfaaSmrg } 4016ab47cfaaSmrg } else if (psav->Chipset == S3_SUPERSAVAGE) { 4017ab47cfaaSmrg if (!crtc2) { 4018ab47cfaaSmrg /* IGA1 */ 4019ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0, 0x80000000); 4020ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8); 4021ab47cfaaSmrg } else { 4022ab47cfaaSmrg /* IGA2 */ 4023ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR0, ((address & 0xFFFFFFF8) | 0x80000000)); 4024ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFF8); 4025ab47cfaaSmrg } 4026ab47cfaaSmrg } else if (psav->Chipset == S3_SAVAGE2000) { 4027ab47cfaaSmrg /* certain Y values seems to cause havoc, not sure why */ 4028ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0, (address & 0xFFFFFFF8)); 4029ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR0, (address & 0xFFFFFFF8)); 4030ab47cfaaSmrg } else { 4031ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0,address | 0xFFFFFFFC); 4032ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR1,address | 0x80000000); 4033ab47cfaaSmrg } 4034ab47cfaaSmrg 4035ab47cfaaSmrg return; 4036ab47cfaaSmrg} 4037ab47cfaaSmrg 4038ab47cfaaSmrgBool SavageSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 4039ab47cfaaSmrg{ 4040ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4041ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4042ab47cfaaSmrg Bool success; 4043ab47cfaaSmrg 4044ab47cfaaSmrg TRACE(("SavageSwitchMode\n")); 4045ab47cfaaSmrg 4046ab47cfaaSmrg if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON)) 4047ab47cfaaSmrg SavageStreamsOff(xf86Screens[scrnIndex]); 4048ab47cfaaSmrg 4049ab47cfaaSmrg success = SavageModeInit(xf86Screens[scrnIndex], mode); 4050ab47cfaaSmrg 4051ab47cfaaSmrg /* switching mode on primary will reset secondary. it needs to be reset as well*/ 4052ab47cfaaSmrg if (psav->IsPrimary) { 4053ab47cfaaSmrg DevUnion* pPriv; 4054ab47cfaaSmrg SavageEntPtr pSavEnt; 4055ab47cfaaSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 4056ab47cfaaSmrg gSavageEntityIndex); 4057ab47cfaaSmrg pSavEnt = pPriv->ptr; 4058ab47cfaaSmrg SavageModeInit(pSavEnt->pSecondaryScrn, pSavEnt->pSecondaryScrn->currentMode); 4059ab47cfaaSmrg } 4060ab47cfaaSmrg SavagePanningCheck(pScrn); 4061ab47cfaaSmrg 4062ab47cfaaSmrg return success; 4063ab47cfaaSmrg} 4064ab47cfaaSmrg 4065ab47cfaaSmrg 4066ab47cfaaSmrgvoid SavageEnableMMIO(ScrnInfoPtr pScrn) 4067ab47cfaaSmrg{ 4068ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 4069ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4070ab47cfaaSmrg int vgaCRIndex, vgaCRReg; 4071ab47cfaaSmrg unsigned char val; 4072ab47cfaaSmrg 4073ab47cfaaSmrg TRACE(("SavageEnableMMIO\n")); 4074ab47cfaaSmrg 4075ab47cfaaSmrg vgaHWSetStdFuncs(hwp); 4076ab47cfaaSmrg vgaHWSetMmioFuncs(hwp, psav->MapBase, 0x8000); 4077ab47cfaaSmrg val = VGAIN8(0x3c3); 4078ab47cfaaSmrg VGAOUT8(0x3c3, val | 0x01); 4079ab47cfaaSmrg val = VGAIN8(VGA_MISC_OUT_R); 4080ab47cfaaSmrg VGAOUT8(VGA_MISC_OUT_W, val | 0x01); 4081ab47cfaaSmrg vgaCRIndex = psav->vgaIOBase + 4; 4082ab47cfaaSmrg vgaCRReg = psav->vgaIOBase + 5; 4083ab47cfaaSmrg 4084ab47cfaaSmrg if( psav->Chipset >= S3_SAVAGE4 ) 4085ab47cfaaSmrg { 4086ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x40); 4087ab47cfaaSmrg val = VGAIN8(vgaCRReg); 4088ab47cfaaSmrg VGAOUT8(vgaCRReg, val | 1); 4089ab47cfaaSmrg } 4090ab47cfaaSmrg 4091ab47cfaaSmrg return; 4092ab47cfaaSmrg} 4093ab47cfaaSmrg 4094ab47cfaaSmrg 4095ab47cfaaSmrgvoid SavageDisableMMIO(ScrnInfoPtr pScrn) 4096ab47cfaaSmrg{ 4097ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 4098ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4099ab47cfaaSmrg int vgaCRIndex, vgaCRReg; 4100ab47cfaaSmrg unsigned char val; 4101ab47cfaaSmrg 4102ab47cfaaSmrg TRACE(("SavageDisableMMIO\n")); 4103ab47cfaaSmrg 4104ab47cfaaSmrg vgaCRIndex = psav->vgaIOBase + 4; 4105ab47cfaaSmrg vgaCRReg = psav->vgaIOBase + 5; 4106ab47cfaaSmrg 4107ab47cfaaSmrg if( psav->Chipset >= S3_SAVAGE4 ) 4108ab47cfaaSmrg { 4109ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x40); 4110ab47cfaaSmrg val = VGAIN8(vgaCRReg); 4111ab47cfaaSmrg VGAOUT8(vgaCRReg, val | 1); 4112ab47cfaaSmrg } 4113ab47cfaaSmrg 4114ab47cfaaSmrg vgaHWSetStdFuncs(hwp); 4115ab47cfaaSmrg 4116ab47cfaaSmrg return; 4117ab47cfaaSmrg} 4118ab47cfaaSmrg 4119ab47cfaaSmrgvoid SavageLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, 4120ab47cfaaSmrg LOCO *colors, VisualPtr pVisual) 4121ab47cfaaSmrg{ 4122ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4123ab47cfaaSmrg int i, index; 4124ab47cfaaSmrg int updateKey = -1; 4125ab47cfaaSmrg unsigned char byte = 0; 4126ab47cfaaSmrg 4127ab47cfaaSmrg /* choose CLUT */ 4128ab47cfaaSmrg if (psav->IsPrimary) { 4129ab47cfaaSmrg /* enable CLUT 1 */ 4130ab47cfaaSmrg VGAOUT8(0x3c4, 0x21); 4131ab47cfaaSmrg byte = VGAIN8(0x3c5); 4132ab47cfaaSmrg VGAOUT8(0x3c5, (byte & ~0x01)); 4133ab47cfaaSmrg /* select CLUT 1 */ 4134ab47cfaaSmrg VGAOUT8(0x3c4, 0x47); 4135ab47cfaaSmrg byte = VGAIN8(0x3c5); 4136ab47cfaaSmrg VGAOUT8(0x3c5, (byte & ~0x03) | 0x01); /* CLUT 1 */ 4137ab47cfaaSmrg } else if (psav->IsSecondary) { 4138ab47cfaaSmrg /* enable CLUT 2 */ 4139ab47cfaaSmrg VGAOUT8(0x3c4, 0x21); 4140ab47cfaaSmrg byte = VGAIN8(0x3c5); 4141ab47cfaaSmrg VGAOUT8(0x3c5, (byte & ~0x10)); 4142ab47cfaaSmrg /* select CLUT 2 */ 4143ab47cfaaSmrg VGAOUT8(0x3c4, 0x47); 4144ab47cfaaSmrg byte = VGAIN8(0x3c5); 4145ab47cfaaSmrg VGAOUT8(0x3c5, (byte & ~0x03) | 0x02); /* CLUT 2 */ 4146ab47cfaaSmrg } 4147ab47cfaaSmrg 4148ab47cfaaSmrg for (i=0; i<numColors; i++) { 4149ab47cfaaSmrg index = indicies[i]; 4150ab47cfaaSmrg if (index == pScrn->colorKey) updateKey = index; 4151ab47cfaaSmrg VGAOUT8(0x3c8, index); 4152ab47cfaaSmrg VGAOUT8(0x3c9, colors[index].red); 4153ab47cfaaSmrg VGAOUT8(0x3c9, colors[index].green); 4154ab47cfaaSmrg VGAOUT8(0x3c9, colors[index].blue); 4155ab47cfaaSmrg } 4156ab47cfaaSmrg 4157ab47cfaaSmrg /* restore saved CLUT index value */ 4158ab47cfaaSmrg if (psav->IsPrimary || psav->IsSecondary) { 4159ab47cfaaSmrg VGAOUT8(0x3c4, 0x47); 4160ab47cfaaSmrg VGAOUT8(0x3c5, byte); 4161ab47cfaaSmrg } 4162ab47cfaaSmrg 4163ab47cfaaSmrg if (updateKey != -1) 4164ab47cfaaSmrg SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green, 4165ab47cfaaSmrg colors[updateKey].blue); 4166ab47cfaaSmrg} 4167ab47cfaaSmrg 4168ab47cfaaSmrg#define Shift(v,d) ((d) < 0 ? ((v) >> (-d)) : ((v) << (d))) 4169ab47cfaaSmrg 4170ab47cfaaSmrgstatic void 4171ab47cfaaSmrgSavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b) 4172ab47cfaaSmrg{ 4173ab47cfaaSmrg ScreenPtr pScreen; 4174ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4175ab47cfaaSmrg FbOverlayScrPrivPtr pScrOvlPriv; 4176ab47cfaaSmrg CARD32 key; 4177ab47cfaaSmrg int ul = 0, ol = 1; 4178ab47cfaaSmrg 4179ab47cfaaSmrg if (pScrn->depth != 8) { 4180ab47cfaaSmrg ul = 1; 4181ab47cfaaSmrg ol = 0; 4182ab47cfaaSmrg } 4183ab47cfaaSmrg if (!(pScreen = pScrn->pScreen) 4184ab47cfaaSmrg || !(pScrOvlPriv = fbOverlayGetScrPriv(pScreen))) 4185ab47cfaaSmrg return; 4186ab47cfaaSmrg key = ((Shift(r,psav->overlay.redShift) & psav->overlay.redMask) 4187ab47cfaaSmrg | (Shift(g,psav->overlay.greenShift) & psav->overlay.greenMask) 4188ab47cfaaSmrg | (Shift(b,psav->overlay.blueShift) & psav->overlay.blueMask)); 4189ab47cfaaSmrg if (pScrOvlPriv->layer[ol].key != key) { 4190ab47cfaaSmrg pScrOvlPriv->layer[ol].key = key; 4191ab47cfaaSmrg (*pScrOvlPriv->PaintKey) (&pScrOvlPriv->layer[ol].u.run.pixmap->drawable, 4192ab47cfaaSmrg &pScrOvlPriv->layer[ul].u.run.region, 4193ab47cfaaSmrg pScrOvlPriv->layer[ol].key, ol); 4194ab47cfaaSmrg } 4195ab47cfaaSmrg} 4196ab47cfaaSmrg 4197ab47cfaaSmrg#if 0 4198ab47cfaaSmrg#define inStatus1() (hwp->readST01( hwp )) 4199ab47cfaaSmrg#endif 4200ab47cfaaSmrg 4201ab47cfaaSmrgvoid SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors, int *indicies, 4202ab47cfaaSmrg LOCO *colors, VisualPtr pVisual) 4203ab47cfaaSmrg{ 4204ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4205ab47cfaaSmrg int i, index; 4206ab47cfaaSmrg int updateKey = -1; 4207ab47cfaaSmrg 4208ab47cfaaSmrg VerticalRetraceWait(); 4209ab47cfaaSmrg 4210ab47cfaaSmrg for (i=0; i<numColors; i++) { 4211ab47cfaaSmrg if (!(inStatus1()) & 0x08) 4212ab47cfaaSmrg VerticalRetraceWait(); 4213ab47cfaaSmrg index = indicies[i]; 4214ab47cfaaSmrg VGAOUT8(0x3c8, index); 4215ab47cfaaSmrg VGAOUT8(0x3c9, colors[index].red); 4216ab47cfaaSmrg VGAOUT8(0x3c9, colors[index].green); 4217ab47cfaaSmrg VGAOUT8(0x3c9, colors[index].blue); 4218ab47cfaaSmrg if (index == pScrn->colorKey) updateKey = index; 4219ab47cfaaSmrg } 4220ab47cfaaSmrg if (updateKey != -1) 4221ab47cfaaSmrg SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green, 4222ab47cfaaSmrg colors[updateKey].blue); 4223ab47cfaaSmrg} 4224ab47cfaaSmrg 4225ab47cfaaSmrgstatic void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1, 4226ab47cfaaSmrg int min_n2, int max_n2, long freq_min, 4227ab47cfaaSmrg long freq_max, unsigned int *mdiv, 4228ab47cfaaSmrg unsigned int *ndiv, unsigned int *r) 4229ab47cfaaSmrg{ 4230ab47cfaaSmrg double ffreq, ffreq_min, ffreq_max; 4231ab47cfaaSmrg double div, diff, best_diff; 4232ab47cfaaSmrg unsigned int m; 4233ab47cfaaSmrg unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2; 4234ab47cfaaSmrg 4235ab47cfaaSmrg ffreq = freq / 1000.0 / BASE_FREQ; 4236ab47cfaaSmrg ffreq_max = freq_max / 1000.0 / BASE_FREQ; 4237ab47cfaaSmrg ffreq_min = freq_min / 1000.0 / BASE_FREQ; 4238ab47cfaaSmrg 4239ab47cfaaSmrg if (ffreq < ffreq_min / (1 << max_n2)) { 4240ab47cfaaSmrg ErrorF("invalid frequency %1.3f Mhz\n", 4241ab47cfaaSmrg ffreq*BASE_FREQ); 4242ab47cfaaSmrg ffreq = ffreq_min / (1 << max_n2); 4243ab47cfaaSmrg } 4244ab47cfaaSmrg if (ffreq > ffreq_max / (1 << min_n2)) { 4245ab47cfaaSmrg ErrorF("invalid frequency %1.3f Mhz\n", 4246ab47cfaaSmrg ffreq*BASE_FREQ); 4247ab47cfaaSmrg ffreq = ffreq_max / (1 << min_n2); 4248ab47cfaaSmrg } 4249ab47cfaaSmrg 4250ab47cfaaSmrg /* work out suitable timings */ 4251ab47cfaaSmrg 4252ab47cfaaSmrg best_diff = ffreq; 4253ab47cfaaSmrg 4254ab47cfaaSmrg for (n2=min_n2; n2<=max_n2; n2++) { 4255ab47cfaaSmrg for (n1=min_n1+2; n1<=max_n1+2; n1++) { 4256ab47cfaaSmrg m = (int)(ffreq * n1 * (1 << n2) + 0.5); 4257ab47cfaaSmrg if (m < min_m+2 || m > 127+2) 4258ab47cfaaSmrg continue; 4259ab47cfaaSmrg div = (double)(m) / (double)(n1); 4260ab47cfaaSmrg if ((div >= ffreq_min) && 4261ab47cfaaSmrg (div <= ffreq_max)) { 4262ab47cfaaSmrg diff = ffreq - div / (1 << n2); 4263ab47cfaaSmrg if (diff < 0.0) 4264ab47cfaaSmrg diff = -diff; 4265ab47cfaaSmrg if (diff < best_diff) { 4266ab47cfaaSmrg best_diff = diff; 4267ab47cfaaSmrg best_m = m; 4268ab47cfaaSmrg best_n1 = n1; 4269ab47cfaaSmrg best_n2 = n2; 4270ab47cfaaSmrg } 4271ab47cfaaSmrg } 4272ab47cfaaSmrg } 4273ab47cfaaSmrg } 4274ab47cfaaSmrg 4275ab47cfaaSmrg *ndiv = best_n1 - 2; 4276ab47cfaaSmrg *r = best_n2; 4277ab47cfaaSmrg *mdiv = best_m - 2; 4278ab47cfaaSmrg} 4279ab47cfaaSmrg 4280ab47cfaaSmrg 4281ab47cfaaSmrgvoid SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file) 4282ab47cfaaSmrg{ 4283ab47cfaaSmrg unsigned char cr66; 4284ab47cfaaSmrg int r, success = 0; 4285ab47cfaaSmrg CARD32 fifo_control = 0, miu_control = 0; 4286ab47cfaaSmrg CARD32 streams_timeout = 0, misc_timeout = 0; 4287ab47cfaaSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 4288ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4289ab47cfaaSmrg int vgaCRIndex, vgaCRReg, vgaIOBase; 4290ab47cfaaSmrg 4291ab47cfaaSmrg TRACE(("SavageGEReset(%d,%s)\n", line, file)); 4292ab47cfaaSmrg 4293ab47cfaaSmrg vgaIOBase = hwp->IOBase; 4294ab47cfaaSmrg vgaCRIndex = vgaIOBase + 4; 4295ab47cfaaSmrg vgaCRReg = vgaIOBase + 5; 4296ab47cfaaSmrg 4297ab47cfaaSmrg if (from_timeout) { 4298ab47cfaaSmrg if (psav->GEResetCnt++ < 10 || xf86GetVerbosity() > 1) 4299ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4300ab47cfaaSmrg "SavageGEReset called from %s line %d\n", file, line); 4301ab47cfaaSmrg } else 4302ab47cfaaSmrg psav->WaitIdleEmpty(psav); 4303ab47cfaaSmrg 4304ab47cfaaSmrg if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 4305ab47cfaaSmrg fifo_control = INREG(FIFO_CONTROL_REG); 4306ab47cfaaSmrg miu_control = INREG(MIU_CONTROL_REG); 4307ab47cfaaSmrg streams_timeout = INREG(STREAMS_TIMEOUT_REG); 4308ab47cfaaSmrg misc_timeout = INREG(MISC_TIMEOUT_REG); 4309ab47cfaaSmrg } 4310ab47cfaaSmrg 4311ab47cfaaSmrg VGAOUT8(vgaCRIndex, 0x66); 4312ab47cfaaSmrg cr66 = VGAIN8(vgaCRReg); 4313ab47cfaaSmrg 4314ab47cfaaSmrg usleep(10000); 4315ab47cfaaSmrg for (r=1; r<10; r++) { 4316ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 | 0x02); 4317ab47cfaaSmrg usleep(10000); 4318ab47cfaaSmrg VGAOUT8(vgaCRReg, cr66 & ~0x02); 4319ab47cfaaSmrg usleep(10000); 4320ab47cfaaSmrg 4321ab47cfaaSmrg if (!from_timeout) 4322ab47cfaaSmrg psav->WaitIdleEmpty(psav); 4323ab47cfaaSmrg OUTREG(DEST_SRC_STR, psav->Bpl << 16 | psav->Bpl); 4324ab47cfaaSmrg 4325ab47cfaaSmrg usleep(10000); 4326ab47cfaaSmrg switch(psav->Chipset) { 4327ab47cfaaSmrg case S3_SAVAGE3D: 4328ab47cfaaSmrg case S3_SAVAGE_MX: 4329ab47cfaaSmrg success = (STATUS_WORD0 & 0x0008ffff) == 0x00080000; 4330ab47cfaaSmrg break; 4331ab47cfaaSmrg case S3_SAVAGE4: 4332ab47cfaaSmrg case S3_PROSAVAGE: 4333ab47cfaaSmrg case S3_PROSAVAGEDDR: 4334ab47cfaaSmrg case S3_TWISTER: 4335ab47cfaaSmrg case S3_SUPERSAVAGE: 4336ab47cfaaSmrg success = (ALT_STATUS_WORD0 & 0x0081ffff) == 0x00800000; 4337ab47cfaaSmrg break; 4338ab47cfaaSmrg case S3_SAVAGE2000: 4339ab47cfaaSmrg success = (ALT_STATUS_WORD0 & 0x008fffff) == 0; 4340ab47cfaaSmrg break; 4341ab47cfaaSmrg } 4342ab47cfaaSmrg if(!success) { 4343ab47cfaaSmrg usleep(10000); 4344ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 4345ab47cfaaSmrg "restarting S3 graphics engine reset %2d ...\n", r); 4346ab47cfaaSmrg } 4347ab47cfaaSmrg else 4348ab47cfaaSmrg break; 4349ab47cfaaSmrg } 4350ab47cfaaSmrg 4351ab47cfaaSmrg /* At this point, the FIFO is empty and the engine is idle. */ 4352ab47cfaaSmrg 4353ab47cfaaSmrg if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) { 4354ab47cfaaSmrg OUTREG(FIFO_CONTROL_REG, fifo_control); 4355ab47cfaaSmrg OUTREG(MIU_CONTROL_REG, miu_control); 4356ab47cfaaSmrg OUTREG(STREAMS_TIMEOUT_REG, streams_timeout); 4357ab47cfaaSmrg OUTREG(MISC_TIMEOUT_REG, misc_timeout); 4358ab47cfaaSmrg } 4359ab47cfaaSmrg 4360ab47cfaaSmrg OUTREG(SRC_BASE, 0); 4361ab47cfaaSmrg OUTREG(DEST_BASE, 0); 4362ab47cfaaSmrg OUTREG(CLIP_L_R, ((0) << 16) | pScrn->displayWidth); 4363ab47cfaaSmrg OUTREG(CLIP_T_B, ((0) << 16) | psav->ScissB); 4364ab47cfaaSmrg OUTREG(MONO_PAT_0, ~0); 4365ab47cfaaSmrg OUTREG(MONO_PAT_1, ~0); 4366ab47cfaaSmrg 4367ab47cfaaSmrg SavageSetGBD(pScrn); 4368ab47cfaaSmrg 4369ab47cfaaSmrg} 4370ab47cfaaSmrg 4371ab47cfaaSmrg 4372ab47cfaaSmrg 4373ab47cfaaSmrg/* This function is used to debug, it prints out the contents of s3 regs */ 4374ab47cfaaSmrg 4375ab47cfaaSmrgvoid 4376ab47cfaaSmrgSavagePrintRegs(ScrnInfoPtr pScrn) 4377ab47cfaaSmrg{ 4378ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4379ab47cfaaSmrg unsigned char i; 4380ab47cfaaSmrg int vgaCRIndex = 0x3d4; 4381ab47cfaaSmrg int vgaCRReg = 0x3d5; 4382ab47cfaaSmrg 4383ab47cfaaSmrg ErrorF( "SR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" ); 4384ab47cfaaSmrg 4385ab47cfaaSmrg for( i = 0; i < 0x70; i++ ) { 4386ab47cfaaSmrg if( !(i % 16) ) 4387ab47cfaaSmrg ErrorF( "\nSR%xx ", i >> 4 ); 4388ab47cfaaSmrg VGAOUT8( 0x3c4, i ); 4389ab47cfaaSmrg ErrorF( " %02x", VGAIN8(0x3c5) ); 4390ab47cfaaSmrg } 4391ab47cfaaSmrg 4392ab47cfaaSmrg ErrorF( "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" ); 4393ab47cfaaSmrg 4394ab47cfaaSmrg for( i = 0; i < 0xB7; i++ ) { 4395ab47cfaaSmrg if( !(i % 16) ) 4396ab47cfaaSmrg ErrorF( "\nCR%xx ", i >> 4 ); 4397ab47cfaaSmrg VGAOUT8( vgaCRIndex, i ); 4398ab47cfaaSmrg ErrorF( " %02x", VGAIN8(vgaCRReg) ); 4399ab47cfaaSmrg } 4400ab47cfaaSmrg 4401ab47cfaaSmrg ErrorF("\n\n"); 4402ab47cfaaSmrg} 4403ab47cfaaSmrg 4404ab47cfaaSmrgstatic void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags) 4405ab47cfaaSmrg{ 4406ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4407ab47cfaaSmrg unsigned char sr8 = 0x00, srd = 0x00; 4408ab47cfaaSmrg 4409ab47cfaaSmrg TRACE(("SavageDPMS(%d,%x)\n", mode, flags)); 4410ab47cfaaSmrg 4411ab47cfaaSmrg if (psav->DisplayType == MT_CRT) { 4412ab47cfaaSmrg VGAOUT8(0x3c4, 0x08); 4413ab47cfaaSmrg sr8 = VGAIN8(0x3c5); 4414ab47cfaaSmrg sr8 |= 0x06; 4415ab47cfaaSmrg VGAOUT8(0x3c5, sr8); 4416ab47cfaaSmrg 4417ab47cfaaSmrg VGAOUT8(0x3c4, 0x0d); 4418ab47cfaaSmrg srd = VGAIN8(0x3c5); 4419ab47cfaaSmrg 4420ab47cfaaSmrg srd &= 0x03; 4421ab47cfaaSmrg 4422ab47cfaaSmrg switch (mode) { 4423ab47cfaaSmrg case DPMSModeOn: 4424ab47cfaaSmrg break; 4425ab47cfaaSmrg case DPMSModeStandby: 4426ab47cfaaSmrg srd |= 0x10; 4427ab47cfaaSmrg break; 4428ab47cfaaSmrg case DPMSModeSuspend: 4429ab47cfaaSmrg srd |= 0x40; 4430ab47cfaaSmrg break; 4431ab47cfaaSmrg case DPMSModeOff: 4432ab47cfaaSmrg srd |= 0x50; 4433ab47cfaaSmrg break; 4434ab47cfaaSmrg default: 4435ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); 4436ab47cfaaSmrg break; 4437ab47cfaaSmrg } 4438ab47cfaaSmrg 4439ab47cfaaSmrg VGAOUT8(0x3c4, 0x0d); 4440ab47cfaaSmrg VGAOUT8(0x3c5, srd); 4441ab47cfaaSmrg } 4442ab47cfaaSmrg 4443ab47cfaaSmrg if (psav->DisplayType == MT_LCD || psav->DisplayType == MT_DFP) { 4444ab47cfaaSmrg if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) && psav->UseBIOS) { 4445ab47cfaaSmrg SavageSetPanelEnabled(psav, (mode == DPMSModeOn)); 4446ab47cfaaSmrg } else { 4447ab47cfaaSmrg switch (mode) { 4448ab47cfaaSmrg case DPMSModeOn: 4449ab47cfaaSmrg VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 4450ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3c5) | 0x10); 4451ab47cfaaSmrg break; 4452ab47cfaaSmrg case DPMSModeStandby: 4453ab47cfaaSmrg case DPMSModeSuspend: 4454ab47cfaaSmrg case DPMSModeOff: 4455ab47cfaaSmrg VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */ 4456ab47cfaaSmrg VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); 4457ab47cfaaSmrg break; 4458ab47cfaaSmrg default: 4459ab47cfaaSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode); 4460ab47cfaaSmrg break; 4461ab47cfaaSmrg } 4462ab47cfaaSmrg } 4463ab47cfaaSmrg } 4464ab47cfaaSmrg 4465ab47cfaaSmrg return; 4466ab47cfaaSmrg} 4467ab47cfaaSmrg 4468ab47cfaaSmrgstatic void 4469ab47cfaaSmrgSavageProbeDDC(ScrnInfoPtr pScrn, int index) 4470ab47cfaaSmrg{ 4471ab47cfaaSmrg vbeInfoPtr pVbe; 4472ab47cfaaSmrg 4473ab47cfaaSmrg if (xf86LoadSubModule(pScrn, "vbe")) { 4474ab47cfaaSmrg xf86LoaderReqSymLists(vbeSymbols, NULL); 4475ab47cfaaSmrg pVbe = VBEInit(NULL, index); 4476ab47cfaaSmrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 4477ab47cfaaSmrg vbeFree(pVbe); 4478ab47cfaaSmrg } 4479ab47cfaaSmrg} 4480ab47cfaaSmrg 4481ab47cfaaSmrgstatic unsigned int 4482ab47cfaaSmrgSavageDDC1Read(ScrnInfoPtr pScrn) 4483ab47cfaaSmrg{ 4484ab47cfaaSmrg register unsigned char tmp; 4485ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4486ab47cfaaSmrg 4487ab47cfaaSmrg UnLockExtRegs(); 4488ab47cfaaSmrg 4489ab47cfaaSmrg VerticalRetraceWait(); 4490ab47cfaaSmrg 4491ab47cfaaSmrg InI2CREG(tmp,psav->I2CPort); 4492ab47cfaaSmrg 4493ab47cfaaSmrg return ((unsigned int) (tmp & 0x08)); 4494ab47cfaaSmrg} 4495ab47cfaaSmrg 4496ab47cfaaSmrgstatic Bool 4497ab47cfaaSmrgSavageDDC1(int scrnIndex) 4498ab47cfaaSmrg{ 4499ab47cfaaSmrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4500ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4501ab47cfaaSmrg unsigned char byte; 4502ab47cfaaSmrg xf86MonPtr pMon; 4503ab47cfaaSmrg 4504ab47cfaaSmrg UnLockExtRegs(); 4505ab47cfaaSmrg 4506ab47cfaaSmrg /* initialize chipset */ 4507ab47cfaaSmrg InI2CREG(byte,psav->I2CPort); 4508ab47cfaaSmrg OutI2CREG(byte | 0x12,psav->I2CPort); 4509ab47cfaaSmrg 4510ab47cfaaSmrg pMon = xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(),SavageDDC1Read); 4511ab47cfaaSmrg if (!pMon) 4512ab47cfaaSmrg return FALSE; 4513ab47cfaaSmrg 4514ab47cfaaSmrg xf86PrintEDID(pMon); 4515ab47cfaaSmrg 4516ab47cfaaSmrg xf86SetDDCproperties(pScrn,pMon); 4517ab47cfaaSmrg 4518ab47cfaaSmrg /* undo initialization */ 4519ab47cfaaSmrg OutI2CREG(byte,psav->I2CPort); 4520ab47cfaaSmrg 4521ab47cfaaSmrg return TRUE; 4522ab47cfaaSmrg} 4523ab47cfaaSmrg 4524ab47cfaaSmrgstatic void 4525ab47cfaaSmrgSavageGetTvMaxSize(SavagePtr psav) 4526ab47cfaaSmrg{ 4527ab47cfaaSmrg if( psav->PAL ) { 4528ab47cfaaSmrg psav->TVSizeX = 800; 4529ab47cfaaSmrg psav->TVSizeY = 600; 4530ab47cfaaSmrg } 4531ab47cfaaSmrg else { 4532ab47cfaaSmrg psav->TVSizeX = 640; 4533ab47cfaaSmrg psav->TVSizeY = 480; 4534ab47cfaaSmrg } 4535ab47cfaaSmrg} 4536ab47cfaaSmrg 4537ab47cfaaSmrg 4538ab47cfaaSmrgstatic Bool 4539ab47cfaaSmrgSavagePanningCheck(ScrnInfoPtr pScrn) 4540ab47cfaaSmrg{ 4541ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4542ab47cfaaSmrg DisplayModePtr pMode; 4543ab47cfaaSmrg 4544ab47cfaaSmrg pMode = pScrn->currentMode; 4545ab47cfaaSmrg psav->iResX = pMode->CrtcHDisplay; 4546ab47cfaaSmrg psav->iResY = pMode->CrtcVDisplay; 4547ab47cfaaSmrg 4548ab47cfaaSmrg if ((psav->iResX < psav->PanelX || psav->iResY < psav->PanelY)) 4549ab47cfaaSmrg psav->FPExpansion = TRUE; 4550ab47cfaaSmrg else 4551ab47cfaaSmrg psav->FPExpansion = FALSE; 4552ab47cfaaSmrg 4553ab47cfaaSmrg if( psav->iResX < pScrn->virtualX || psav->iResY < pScrn->virtualY ) 4554ab47cfaaSmrg return TRUE; 4555ab47cfaaSmrg else 4556ab47cfaaSmrg return FALSE; 4557ab47cfaaSmrg} 4558ab47cfaaSmrg 4559ab47cfaaSmrgstatic void 4560ab47cfaaSmrgSavageResetStreams(ScrnInfoPtr pScrn) 4561ab47cfaaSmrg{ 4562ab47cfaaSmrg SavagePtr psav = SAVPTR(pScrn); 4563ab47cfaaSmrg unsigned char cr67; 4564ab47cfaaSmrg unsigned char cr69; 4565ab47cfaaSmrg 4566ab47cfaaSmrg /* disable streams */ 4567ab47cfaaSmrg switch (psav->Chipset) { 4568ab47cfaaSmrg case S3_SAVAGE_MX: 4569ab47cfaaSmrg case S3_SUPERSAVAGE: 4570ab47cfaaSmrg OUTREG32(PRI_STREAM_STRIDE,0); 4571ab47cfaaSmrg OUTREG32(PRI_STREAM2_STRIDE, 0); 4572ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); 4573ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); 4574ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x00000000); 4575ab47cfaaSmrg OUTREG32(PRI_STREAM2_FBUF_ADDR1,0x00000000); 4576ab47cfaaSmrg OUTREG8(CRT_ADDRESS_REG, 0x67); 4577ab47cfaaSmrg cr67 = INREG8(CRT_DATA_REG); 4578ab47cfaaSmrg cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */ 4579ab47cfaaSmrg cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */ 4580ab47cfaaSmrg cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */ 4581ab47cfaaSmrg OUTREG8(CRT_DATA_REG, cr67); 4582ab47cfaaSmrg break; 4583ab47cfaaSmrg case S3_SAVAGE3D: 4584ab47cfaaSmrg case S3_SAVAGE4: 4585ab47cfaaSmrg case S3_TWISTER: 4586ab47cfaaSmrg case S3_PROSAVAGE: 4587ab47cfaaSmrg case S3_PROSAVAGEDDR: 4588ab47cfaaSmrg OUTREG32(PRI_STREAM_STRIDE,0); 4589ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0,0); 4590ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR1,0); 4591ab47cfaaSmrg OUTREG8(CRT_ADDRESS_REG, 0x67); 4592ab47cfaaSmrg cr67 = INREG8(CRT_DATA_REG); 4593ab47cfaaSmrg cr67 &= ~0x0c; /* CR67[2] = 1 : enable stream 1 */ 4594ab47cfaaSmrg OUTREG8(CRT_DATA_REG, cr67); 4595ab47cfaaSmrg OUTREG8(CRT_ADDRESS_REG, 0x69); 4596ab47cfaaSmrg cr69 = INREG8(CRT_DATA_REG); 4597ab47cfaaSmrg cr69 &= ~0x80; /* CR69[0] = 1 : Mem-mapped regs */ 4598ab47cfaaSmrg OUTREG8(CRT_DATA_REG, cr69); 4599ab47cfaaSmrg break; 4600ab47cfaaSmrg case S3_SAVAGE2000: 4601ab47cfaaSmrg OUTREG32(PRI_STREAM_STRIDE,0); 4602ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000); 4603ab47cfaaSmrg OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000); 4604ab47cfaaSmrg OUTREG8(CRT_ADDRESS_REG, 0x67); 4605ab47cfaaSmrg cr67 = INREG8(CRT_DATA_REG); 4606ab47cfaaSmrg cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */ 4607ab47cfaaSmrg cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */ 4608ab47cfaaSmrg cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */ 4609ab47cfaaSmrg OUTREG8(CRT_DATA_REG, cr67); 4610ab47cfaaSmrg break; 4611ab47cfaaSmrg default: 4612ab47cfaaSmrg break; 4613ab47cfaaSmrg } 4614ab47cfaaSmrg 4615ab47cfaaSmrg} 4616