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