i740_driver.c revision ef6fb4a5
1301ea0f4Smrg 2301ea0f4Smrg/************************************************************************** 3301ea0f4Smrg 4301ea0f4SmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5301ea0f4SmrgAll Rights Reserved. 6301ea0f4Smrg 7301ea0f4SmrgPermission is hereby granted, free of charge, to any person obtaining a 8301ea0f4Smrgcopy of this software and associated documentation files (the 9301ea0f4Smrg"Software"), to deal in the Software without restriction, including 10301ea0f4Smrgwithout limitation the rights to use, copy, modify, merge, publish, 11301ea0f4Smrgdistribute, sub license, and/or sell copies of the Software, and to 12301ea0f4Smrgpermit persons to whom the Software is furnished to do so, subject to 13301ea0f4Smrgthe following conditions: 14301ea0f4Smrg 15301ea0f4SmrgThe above copyright notice and this permission notice (including the 16301ea0f4Smrgnext paragraph) shall be included in all copies or substantial portions 17301ea0f4Smrgof the Software. 18301ea0f4Smrg 19301ea0f4SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20301ea0f4SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21301ea0f4SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22301ea0f4SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23301ea0f4SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24301ea0f4SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25301ea0f4SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26301ea0f4Smrg 27301ea0f4Smrg**************************************************************************/ 28301ea0f4Smrg 29301ea0f4Smrg/* 30301ea0f4Smrg * Authors: 31301ea0f4Smrg * Daryll Strauss <daryll@precisioninsight.com> 32301ea0f4Smrg * 33301ea0f4Smrg */ 34301ea0f4Smrg 35301ea0f4Smrg#ifdef HAVE_CONFIG_H 36301ea0f4Smrg#include "config.h" 37301ea0f4Smrg#endif 38301ea0f4Smrg 39301ea0f4Smrg#include <string.h> 40301ea0f4Smrg#include <math.h> 41301ea0f4Smrg 42301ea0f4Smrg/* 43301ea0f4Smrg * This server does not support these XFree86 4.0 features yet 44301ea0f4Smrg * DDC1 & DDC2 (requires I2C) 45301ea0f4Smrg * shadowFb (if requested or acceleration is off) 46301ea0f4Smrg * Overlay planes 47301ea0f4Smrg * DGA 48301ea0f4Smrg */ 49301ea0f4Smrg 50301ea0f4Smrg/* 51301ea0f4Smrg * These are X and server generic header files. 52301ea0f4Smrg */ 53301ea0f4Smrg#include "xf86.h" 54301ea0f4Smrg#include "xf86_OSproc.h" 55ef6fb4a5Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 56301ea0f4Smrg#include "xf86Resources.h" 57301ea0f4Smrg#include "xf86RAC.h" 58ef6fb4a5Smrg#endif 59301ea0f4Smrg#include "xf86cmap.h" 60301ea0f4Smrg 61301ea0f4Smrg/* If the driver uses port I/O directly, it needs: */ 62301ea0f4Smrg 63301ea0f4Smrg#include "compiler.h" 64301ea0f4Smrg 65301ea0f4Smrg/* Drivers using the mi implementation of backing store need: */ 66301ea0f4Smrg 67301ea0f4Smrg#include "mibstore.h" 68301ea0f4Smrg 69301ea0f4Smrg/* All drivers using the vgahw module need this */ 70301ea0f4Smrg/* This driver needs to be modified to not use vgaHW for multihead operation */ 71301ea0f4Smrg#include "vgaHW.h" 72301ea0f4Smrg 73301ea0f4Smrg/* Drivers using the mi SW cursor need: */ 74301ea0f4Smrg 75301ea0f4Smrg#include "mipointer.h" 76301ea0f4Smrg 77301ea0f4Smrg/* Drivers using the mi colourmap code need: */ 78301ea0f4Smrg 79301ea0f4Smrg#include "micmap.h" 80301ea0f4Smrg 81301ea0f4Smrg#include "fb.h" 82301ea0f4Smrg 83301ea0f4Smrg/* The driver's own header file: */ 84301ea0f4Smrg 85301ea0f4Smrg 86301ea0f4Smrg#include "regionstr.h" 87301ea0f4Smrg 88301ea0f4Smrg#include "xf86xv.h" 89301ea0f4Smrg#include <X11/extensions/Xv.h> 90301ea0f4Smrg 91301ea0f4Smrg#include "vbe.h" 92301ea0f4Smrg#include "i740_dga.h" 93301ea0f4Smrg#include "i740.h" 94301ea0f4Smrg 95301ea0f4Smrg 96301ea0f4Smrg/* Required Functions: */ 97301ea0f4Smrgstatic const OptionInfoRec * I740AvailableOptions(int chipid, int busid); 98301ea0f4Smrg 99301ea0f4Smrg/* Print a driver identifying message. */ 100301ea0f4Smrgstatic void I740Identify(int flags); 101301ea0f4Smrg 102301ea0f4Smrg/* Identify if there is any hardware present that I know how to drive. */ 103301ea0f4Smrgstatic Bool I740Probe(DriverPtr drv, int flags); 104301ea0f4Smrg 105301ea0f4Smrg/* Process the config file and see if we have a valid configuration */ 106301ea0f4Smrgstatic Bool I740PreInit(ScrnInfoPtr pScrn, int flags); 107301ea0f4Smrg 108301ea0f4Smrg/* Initialize a screen */ 109301ea0f4Smrgstatic Bool I740ScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); 110301ea0f4Smrg 111301ea0f4Smrg/* Enter from a virtual terminal */ 112301ea0f4Smrgstatic Bool I740EnterVT(int scrnIndex, int flags); 113301ea0f4Smrg 114301ea0f4Smrg/* Leave to a virtual terminal */ 115301ea0f4Smrgstatic void I740LeaveVT(int scrnIndex, int flags); 116301ea0f4Smrg 117301ea0f4Smrg/* Close down each screen we initialized */ 118301ea0f4Smrgstatic Bool I740CloseScreen(int scrnIndex, ScreenPtr pScreen); 119301ea0f4Smrg 120301ea0f4Smrg/* Change screensaver state */ 121301ea0f4Smrgstatic Bool I740SaveScreen(ScreenPtr pScreen, int mode); 122301ea0f4Smrg 123301ea0f4Smrg/* Cleanup server private data */ 124301ea0f4Smrgstatic void I740FreeScreen(int scrnIndex, int flags); 125301ea0f4Smrg 126301ea0f4Smrg/* Check if a mode is valid on the hardware */ 127301ea0f4Smrgstatic ModeStatus I740ValidMode(int scrnIndex, DisplayModePtr mode, 128301ea0f4Smrg Bool verbose, int flags); 129301ea0f4Smrg 130301ea0f4Smrg/* Switch to various Display Power Management System levels */ 131301ea0f4Smrgstatic void I740DisplayPowerManagementSet(ScrnInfoPtr pScrn, 132301ea0f4Smrg int PowerManagermentMode, int flags); 133301ea0f4Smrg 134301ea0f4Smrgstatic void I740ProbeDDC(ScrnInfoPtr pScrn, int index); 135301ea0f4Smrg 136301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn); 137301ea0f4Smrgstatic Bool I740UnmapMem(ScrnInfoPtr pScrn); 138301ea0f4Smrg 139301ea0f4Smrg#define I740_VERSION 4000 140301ea0f4Smrg#define I740_NAME "I740" 141301ea0f4Smrg#define I740_DRIVER_NAME "i740" 1420cc67336Smrg#define I740_MAJOR_VERSION PACKAGE_VERSION_MAJOR 1430cc67336Smrg#define I740_MINOR_VERSION PACKAGE_VERSION_MINOR 1440cc67336Smrg#define I740_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 145301ea0f4Smrg 146301ea0f4Smrg_X_EXPORT DriverRec I740 = { 147301ea0f4Smrg I740_VERSION, 148301ea0f4Smrg I740_DRIVER_NAME, 149301ea0f4Smrg I740Identify, 150301ea0f4Smrg I740Probe, 151301ea0f4Smrg I740AvailableOptions, 152301ea0f4Smrg NULL, 153301ea0f4Smrg 0 154301ea0f4Smrg}; 155301ea0f4Smrg 156301ea0f4Smrg/* Chipsets */ 157301ea0f4Smrgstatic SymTabRec I740Chipsets[] = { 158301ea0f4Smrg { PCI_CHIP_I740_AGP, "i740 (agp)"}, 159301ea0f4Smrg { PCI_CHIP_I740_PCI, "i740 (pci)"}, 160301ea0f4Smrg { -1, NULL } 161301ea0f4Smrg}; 162301ea0f4Smrg 163301ea0f4Smrgstatic PciChipsets I740PciChipsets[] = { 164301ea0f4Smrg { PCI_CHIP_I740_AGP, PCI_CHIP_I740_AGP, RES_SHARED_VGA }, 165301ea0f4Smrg { PCI_CHIP_I740_PCI, PCI_CHIP_I740_PCI, RES_SHARED_VGA }, 166301ea0f4Smrg { -1, -1, RES_UNDEFINED } 167301ea0f4Smrg}; 168301ea0f4Smrg 169301ea0f4Smrgtypedef enum { 170301ea0f4Smrg OPTION_NOACCEL, 171301ea0f4Smrg OPTION_SW_CURSOR, 172301ea0f4Smrg OPTION_SDRAM, 173301ea0f4Smrg OPTION_SGRAM, 174301ea0f4Smrg OPTION_SLOW_RAM, 175301ea0f4Smrg OPTION_DAC_6BIT, 176301ea0f4Smrg OPTION_USE_PIO, 177301ea0f4Smrg OPTION_VGACOMPAT 178301ea0f4Smrg} I740Opts; 179301ea0f4Smrg 180301ea0f4Smrgstatic const OptionInfoRec I740Options[] = { 181301ea0f4Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 182301ea0f4Smrg { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 183301ea0f4Smrg { OPTION_SDRAM, "SDRAM", OPTV_BOOLEAN, {0}, FALSE}, 184301ea0f4Smrg { OPTION_SGRAM, "SGRAM", OPTV_BOOLEAN, {0}, FALSE}, 185301ea0f4Smrg { OPTION_SLOW_RAM, "SlowRam", OPTV_BOOLEAN, {0}, FALSE}, 186301ea0f4Smrg { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, 187301ea0f4Smrg { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE}, 188301ea0f4Smrg { OPTION_VGACOMPAT, "VGACompat", OPTV_BOOLEAN, {0}, FALSE}, 189301ea0f4Smrg { -1, NULL, OPTV_NONE, {0}, FALSE} 190301ea0f4Smrg}; 191301ea0f4Smrg 192301ea0f4Smrg#ifdef XFree86LOADER 193301ea0f4Smrg 194301ea0f4Smrgstatic MODULESETUPPROTO(i740Setup); 195301ea0f4Smrg 196301ea0f4Smrgstatic XF86ModuleVersionInfo i740VersRec = 197301ea0f4Smrg{ 198301ea0f4Smrg "i740", 199301ea0f4Smrg MODULEVENDORSTRING, 200301ea0f4Smrg MODINFOSTRING1, 201301ea0f4Smrg MODINFOSTRING2, 202301ea0f4Smrg XORG_VERSION_CURRENT, 203301ea0f4Smrg I740_MAJOR_VERSION, I740_MINOR_VERSION, I740_PATCHLEVEL, 204301ea0f4Smrg ABI_CLASS_VIDEODRV, 205301ea0f4Smrg ABI_VIDEODRV_VERSION, 206301ea0f4Smrg MOD_CLASS_VIDEODRV, 207301ea0f4Smrg {0,0,0,0} 208301ea0f4Smrg}; 209301ea0f4Smrg 210301ea0f4Smrg_X_EXPORT XF86ModuleData i740ModuleData = {&i740VersRec, i740Setup, 0}; 211301ea0f4Smrg 212301ea0f4Smrgstatic pointer 213301ea0f4Smrgi740Setup(pointer module, pointer opts, int *errmaj, int *errmin) 214301ea0f4Smrg{ 215301ea0f4Smrg static Bool setupDone = FALSE; 216301ea0f4Smrg 217301ea0f4Smrg /* This module should be loaded only once, but check to be sure. */ 218301ea0f4Smrg 219301ea0f4Smrg if (!setupDone) { 220301ea0f4Smrg setupDone = TRUE; 221301ea0f4Smrg xf86AddDriver(&I740, module, 0); 222301ea0f4Smrg 223301ea0f4Smrg /* 224301ea0f4Smrg * Modules that this driver always requires may be loaded here 225301ea0f4Smrg * by calling LoadSubModule(). 226301ea0f4Smrg */ 227301ea0f4Smrg 228301ea0f4Smrg /* 229301ea0f4Smrg * The return value must be non-NULL on success even though there 230301ea0f4Smrg * is no TearDownProc. 231301ea0f4Smrg */ 232301ea0f4Smrg return (pointer)1; 233301ea0f4Smrg } else { 234301ea0f4Smrg if (errmaj) *errmaj = LDR_ONCEONLY; 235301ea0f4Smrg return NULL; 236301ea0f4Smrg } 237301ea0f4Smrg} 238301ea0f4Smrg 239301ea0f4Smrg#endif 240301ea0f4Smrg 241301ea0f4Smrg/* 242301ea0f4Smrg * I740GetRec and I740FreeRec -- 243301ea0f4Smrg * 244301ea0f4Smrg * Private data for the driver is stored in the screen structure. 245301ea0f4Smrg * These two functions create and destroy that private data. 246301ea0f4Smrg * 247301ea0f4Smrg */ 248301ea0f4Smrgstatic Bool 249301ea0f4SmrgI740GetRec(ScrnInfoPtr pScrn) { 250301ea0f4Smrg if (pScrn->driverPrivate) return TRUE; 251301ea0f4Smrg 252301ea0f4Smrg pScrn->driverPrivate = xnfcalloc(sizeof(I740Rec), 1); 253301ea0f4Smrg return TRUE; 254301ea0f4Smrg} 255301ea0f4Smrg 256301ea0f4Smrgstatic void 257301ea0f4SmrgI740FreeRec(ScrnInfoPtr pScrn) { 258301ea0f4Smrg if (!pScrn) return; 259301ea0f4Smrg if (!pScrn->driverPrivate) return; 260301ea0f4Smrg xfree(pScrn->driverPrivate); 261301ea0f4Smrg pScrn->driverPrivate=0; 262301ea0f4Smrg} 263301ea0f4Smrg 264301ea0f4Smrgstatic const OptionInfoRec * 265301ea0f4SmrgI740AvailableOptions(int chipid, int busid) 266301ea0f4Smrg{ 267301ea0f4Smrg return I740Options; 268301ea0f4Smrg} 269301ea0f4Smrg 270301ea0f4Smrg/* 271301ea0f4Smrg * I740Identify -- 272301ea0f4Smrg * 273301ea0f4Smrg * Returns the string name for the driver based on the chipset. In this 274301ea0f4Smrg * case it will always be an I740, so we can return a static string. 275301ea0f4Smrg * 276301ea0f4Smrg */ 277301ea0f4Smrgstatic void 278301ea0f4SmrgI740Identify(int flags) { 279301ea0f4Smrg xf86PrintChipsets(I740_NAME, "Driver for Intel i740 chipset", I740Chipsets); 280301ea0f4Smrg} 281301ea0f4Smrg 282301ea0f4Smrg/* 283301ea0f4Smrg * I740Probe -- 284301ea0f4Smrg * 285301ea0f4Smrg * Look through the PCI bus to find cards that are I740 boards. 286301ea0f4Smrg * Setup the dispatch table for the rest of the driver functions. 287301ea0f4Smrg * 288301ea0f4Smrg */ 289301ea0f4Smrgstatic Bool 290301ea0f4SmrgI740Probe(DriverPtr drv, int flags) { 291301ea0f4Smrg int i, numUsed, numDevSections, *usedChips; 292301ea0f4Smrg GDevPtr *devSections; 293301ea0f4Smrg Bool foundScreen = FALSE; 294301ea0f4Smrg 295301ea0f4Smrg /* 296301ea0f4Smrg Find the config file Device sections that match this 297301ea0f4Smrg driver, and return if there are none. 298301ea0f4Smrg */ 299301ea0f4Smrg if ((numDevSections = xf86MatchDevice(I740_DRIVER_NAME, &devSections))<=0) { 300301ea0f4Smrg return FALSE; 301301ea0f4Smrg } 302301ea0f4Smrg 3030cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 304301ea0f4Smrg /* 305301ea0f4Smrg Since these Probing is just checking the PCI data the server already 306301ea0f4Smrg collected. 307301ea0f4Smrg */ 308301ea0f4Smrg if (!xf86GetPciVideoInfo()) return FALSE; 3090cc67336Smrg#endif 310301ea0f4Smrg 311301ea0f4Smrg /* Look for Intel based chips */ 312301ea0f4Smrg numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_INTEL, 313301ea0f4Smrg I740Chipsets, I740PciChipsets, 314301ea0f4Smrg devSections, numDevSections, 315301ea0f4Smrg drv, &usedChips); 316301ea0f4Smrg 317301ea0f4Smrg if (numUsed > 0) { 318301ea0f4Smrg if (flags & PROBE_DETECT) 319301ea0f4Smrg foundScreen = TRUE; 320301ea0f4Smrg else for (i=0; i<numUsed; i++) { 321301ea0f4Smrg ScrnInfoPtr pScrn = NULL; 322301ea0f4Smrg /* Allocate new ScrnInfoRec and claim the slot */ 323301ea0f4Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 324301ea0f4Smrg I740PciChipsets, 0, 0, 0, 0, 0))) { 325301ea0f4Smrg pScrn->driverVersion = I740_VERSION; 326301ea0f4Smrg pScrn->driverName = I740_DRIVER_NAME; 327301ea0f4Smrg pScrn->name = I740_NAME; 328301ea0f4Smrg pScrn->Probe = I740Probe; 329301ea0f4Smrg pScrn->PreInit = I740PreInit; 330301ea0f4Smrg pScrn->ScreenInit = I740ScreenInit; 331301ea0f4Smrg pScrn->SwitchMode = I740SwitchMode; 332301ea0f4Smrg pScrn->AdjustFrame = I740AdjustFrame; 333301ea0f4Smrg pScrn->EnterVT = I740EnterVT; 334301ea0f4Smrg pScrn->LeaveVT = I740LeaveVT; 335301ea0f4Smrg pScrn->FreeScreen = I740FreeScreen; 336301ea0f4Smrg pScrn->ValidMode = I740ValidMode; 337301ea0f4Smrg foundScreen = TRUE; 338301ea0f4Smrg 339301ea0f4Smrg } 340301ea0f4Smrg } 341301ea0f4Smrg } 342301ea0f4Smrg 343301ea0f4Smrg 344301ea0f4Smrg /* Look for Real3D based chips */ 345301ea0f4Smrg numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_REAL3D, 346301ea0f4Smrg I740Chipsets, I740PciChipsets, 347301ea0f4Smrg devSections, numDevSections, 348301ea0f4Smrg drv, &usedChips); 349301ea0f4Smrg 350301ea0f4Smrg if (numUsed > 0) { 351301ea0f4Smrg if (flags & PROBE_DETECT) 352301ea0f4Smrg foundScreen = TRUE; 353301ea0f4Smrg else for (i=0; i<numUsed; i++) { 354301ea0f4Smrg ScrnInfoPtr pScrn = NULL; 355301ea0f4Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 356301ea0f4Smrg I740PciChipsets, 0, 0, 0, 0, 0))) { 357301ea0f4Smrg pScrn->driverVersion = I740_VERSION; 358301ea0f4Smrg pScrn->driverName = I740_DRIVER_NAME; 359301ea0f4Smrg pScrn->name = I740_NAME; 360301ea0f4Smrg pScrn->Probe = I740Probe; 361301ea0f4Smrg pScrn->PreInit = I740PreInit; 362301ea0f4Smrg pScrn->ScreenInit = I740ScreenInit; 363301ea0f4Smrg pScrn->SwitchMode = I740SwitchMode; 364301ea0f4Smrg pScrn->AdjustFrame = I740AdjustFrame; 365301ea0f4Smrg pScrn->EnterVT = I740EnterVT; 366301ea0f4Smrg pScrn->LeaveVT = I740LeaveVT; 367301ea0f4Smrg pScrn->FreeScreen = I740FreeScreen; 368301ea0f4Smrg pScrn->ValidMode = I740ValidMode; 369301ea0f4Smrg foundScreen = TRUE; 370301ea0f4Smrg } 371301ea0f4Smrg } 372301ea0f4Smrg } 373301ea0f4Smrg 374301ea0f4Smrg xfree(devSections); 375301ea0f4Smrg xfree(usedChips); 376301ea0f4Smrg 377301ea0f4Smrg return foundScreen; 378301ea0f4Smrg} 379301ea0f4Smrg 3800cc67336Smrg/* Ugh. Can we not do this? */ 381301ea0f4Smrgstatic void 382301ea0f4SmrgI740ProbeDDC(ScrnInfoPtr pScrn, int index) 383301ea0f4Smrg{ 384301ea0f4Smrg vbeInfoPtr pVbe; 385301ea0f4Smrg if (xf86LoadSubModule(pScrn, "vbe")) { 386301ea0f4Smrg pVbe = VBEInit(NULL,index); 387301ea0f4Smrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 388301ea0f4Smrg vbeFree(pVbe); 389301ea0f4Smrg } 390301ea0f4Smrg} 391301ea0f4Smrg 392301ea0f4Smrg/* 393301ea0f4Smrg * I740PreInit -- 394301ea0f4Smrg * 395301ea0f4Smrg * Do initial setup of the board before we know what resolution we will 396301ea0f4Smrg * be running at. 397301ea0f4Smrg * 398301ea0f4Smrg */ 399301ea0f4Smrgstatic Bool 400301ea0f4SmrgI740PreInit(ScrnInfoPtr pScrn, int flags) { 401301ea0f4Smrg I740Ptr pI740; 402301ea0f4Smrg ClockRangePtr clockRanges; 403301ea0f4Smrg int i; 404301ea0f4Smrg MessageType from; 405301ea0f4Smrg int temp; 406301ea0f4Smrg int flags24; 407301ea0f4Smrg rgb defaultWeight = {0, 0, 0}; 408301ea0f4Smrg 409301ea0f4Smrg if (pScrn->numEntities != 1) return FALSE; 410301ea0f4Smrg 411301ea0f4Smrg /* Allocate driverPrivate */ 412301ea0f4Smrg if (!I740GetRec(pScrn)) { 413301ea0f4Smrg return FALSE; 414301ea0f4Smrg } 415301ea0f4Smrg 416301ea0f4Smrg pI740 = I740PTR(pScrn); 417301ea0f4Smrg 418301ea0f4Smrg pI740->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 419301ea0f4Smrg if (pI740->pEnt->location.type != BUS_PCI) return FALSE; 420301ea0f4Smrg 421301ea0f4Smrg /*I740ProbeDDC(pScrn, pI740->pEnt->index);*/ 422301ea0f4Smrg if (flags & PROBE_DETECT) { 423301ea0f4Smrg I740ProbeDDC(pScrn, pI740->pEnt->index); 424301ea0f4Smrg return TRUE; 425301ea0f4Smrg } 426301ea0f4Smrg 427301ea0f4Smrg /* The vgahw module should be loaded here when needed */ 428301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE; 429301ea0f4Smrg 430301ea0f4Smrg /* Allocate a vgaHWRec */ 431301ea0f4Smrg if (!vgaHWGetHWRec(pScrn)) return FALSE; 432301ea0f4Smrg 433301ea0f4Smrg pI740->PciInfo = xf86GetPciInfoForEntity(pI740->pEnt->index); 4340cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 435301ea0f4Smrg pI740->PciTag = pciTag(pI740->PciInfo->bus, pI740->PciInfo->device, 436301ea0f4Smrg pI740->PciInfo->func); 437301ea0f4Smrg 438301ea0f4Smrg if (xf86RegisterResources(pI740->pEnt->index, 0, ResNone)) 439301ea0f4Smrg return FALSE; 440301ea0f4Smrg if (pI740->usePIO) 441301ea0f4Smrg pScrn->racIoFlags = RAC_FB | RAC_COLORMAP; 442301ea0f4Smrg else 443301ea0f4Smrg pScrn->racMemFlags = RAC_FB | RAC_COLORMAP; 444ef6fb4a5Smrg#endif 445301ea0f4Smrg /* Set pScrn->monitor */ 446301ea0f4Smrg pScrn->monitor = pScrn->confScreen->monitor; 447301ea0f4Smrg 448301ea0f4Smrg 449301ea0f4Smrg flags24=Support24bppFb | Support32bppFb | SupportConvert32to24; 450301ea0f4Smrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) { 451301ea0f4Smrg return FALSE; 452301ea0f4Smrg } else { 453301ea0f4Smrg switch (pScrn->depth) { 454301ea0f4Smrg case 8: 455301ea0f4Smrg case 15: 456301ea0f4Smrg case 16: 457301ea0f4Smrg case 24: 458301ea0f4Smrg break; 459301ea0f4Smrg default: 460301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 461301ea0f4Smrg "Given depth (%d) is not supported by i740 driver\n", 462301ea0f4Smrg pScrn->depth); 463301ea0f4Smrg return FALSE; 464301ea0f4Smrg } 465301ea0f4Smrg } 466301ea0f4Smrg /*xf86PrintDepthBpp(pScrn);*/ 467301ea0f4Smrg 468301ea0f4Smrg if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 469301ea0f4Smrg return FALSE; 470301ea0f4Smrg 471301ea0f4Smrg if (!xf86SetDefaultVisual(pScrn, -1)) { 472301ea0f4Smrg return FALSE; 473301ea0f4Smrg } else { 474301ea0f4Smrg /* We don't currently support DirectColor at > 8bpp */ 475301ea0f4Smrg if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 476301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 477301ea0f4Smrg " (%s) is not supported at depth %d\n", 478301ea0f4Smrg xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 479301ea0f4Smrg return FALSE; 480301ea0f4Smrg } 481301ea0f4Smrg } 482301ea0f4Smrg 483301ea0f4Smrg /* We use a programamble clock */ 484301ea0f4Smrg pScrn->progClock = TRUE; 485301ea0f4Smrg 486301ea0f4Smrg pI740->cpp = pScrn->bitsPerPixel/8; 487301ea0f4Smrg 488301ea0f4Smrg /* Process the options */ 489301ea0f4Smrg xf86CollectOptions(pScrn, NULL); 490301ea0f4Smrg if (!(pI740->Options = xalloc(sizeof(I740Options)))) 491301ea0f4Smrg return FALSE; 492301ea0f4Smrg memcpy(pI740->Options, I740Options, sizeof(I740Options)); 493301ea0f4Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI740->Options); 494301ea0f4Smrg 495301ea0f4Smrg /* 6-BIT dac isn't reasonable for modes with > 8bpp */ 496301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE) && 497301ea0f4Smrg pScrn->bitsPerPixel>8) { 498301ea0f4Smrg OptionInfoPtr ptr; 499301ea0f4Smrg ptr=xf86TokenToOptinfo(pI740->Options, OPTION_DAC_6BIT); 500301ea0f4Smrg ptr->found=FALSE; 501301ea0f4Smrg } 502301ea0f4Smrg 503301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE)) 504301ea0f4Smrg pScrn->rgbBits=8; 505301ea0f4Smrg else 506301ea0f4Smrg pScrn->rgbBits=6; 507301ea0f4Smrg 508301ea0f4Smrg /* We have to use PIO to probe, because we haven't mappend yet */ 509301ea0f4Smrg I740SetPIOAccess(pI740); 510301ea0f4Smrg 511301ea0f4Smrg /* 512301ea0f4Smrg * Set the Chipset and ChipRev, allowing config file entries to 513301ea0f4Smrg * override. 514301ea0f4Smrg */ 515301ea0f4Smrg if (pI740->pEnt->device->chipset && *pI740->pEnt->device->chipset) { 516301ea0f4Smrg pScrn->chipset = pI740->pEnt->device->chipset; 517301ea0f4Smrg from = X_CONFIG; 518301ea0f4Smrg } else if (pI740->pEnt->device->chipID >= 0) { 519301ea0f4Smrg pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->pEnt->device->chipID); 520301ea0f4Smrg from = X_CONFIG; 521301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 522301ea0f4Smrg pI740->pEnt->device->chipID); 523301ea0f4Smrg } else { 524301ea0f4Smrg from = X_PROBED; 5250cc67336Smrg pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, PCI_DEV_DEVICE_ID(pI740->PciInfo)); 526301ea0f4Smrg } 527301ea0f4Smrg if (pI740->pEnt->device->chipRev >= 0) { 528301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 529301ea0f4Smrg pI740->pEnt->device->chipRev); 530301ea0f4Smrg } 531301ea0f4Smrg 532301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset!=NULL)?pScrn->chipset:"Unknown i740"); 533301ea0f4Smrg 534301ea0f4Smrg if (pI740->pEnt->device->MemBase != 0) { 535301ea0f4Smrg pI740->LinearAddr = pI740->pEnt->device->MemBase; 536301ea0f4Smrg from = X_CONFIG; 537301ea0f4Smrg } else { 5380cc67336Smrg if (PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM) != 0) { 5390cc67336Smrg pI740->LinearAddr = PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM)&0xFF000000; 540301ea0f4Smrg from = X_PROBED; 541301ea0f4Smrg } else { 542301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 543301ea0f4Smrg "No valid FB address in PCI config space\n"); 544301ea0f4Smrg I740FreeRec(pScrn); 545301ea0f4Smrg return FALSE; 546301ea0f4Smrg } 547301ea0f4Smrg } 548301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 549301ea0f4Smrg pI740->LinearAddr); 550301ea0f4Smrg 551301ea0f4Smrg if (pI740->pEnt->device->IOBase != 0) { 552301ea0f4Smrg pI740->MMIOAddr = pI740->pEnt->device->IOBase; 553301ea0f4Smrg from = X_CONFIG; 554301ea0f4Smrg } else { 5550cc67336Smrg if (PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)) { 5560cc67336Smrg pI740->MMIOAddr = PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)&0xFFF80000; 557301ea0f4Smrg from = X_PROBED; 558301ea0f4Smrg } else { 559301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 560301ea0f4Smrg "No valid MMIO address in PCI config space\n"); 561301ea0f4Smrg I740FreeRec(pScrn); 562301ea0f4Smrg return FALSE; 563301ea0f4Smrg } 564301ea0f4Smrg } 565301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", 566301ea0f4Smrg pI740->MMIOAddr); 567301ea0f4Smrg 568301ea0f4Smrg /* Calculate memory */ 569301ea0f4Smrg if (pI740->pEnt->device->videoRam) { 570301ea0f4Smrg pScrn->videoRam = pI740->pEnt->device->videoRam; 571301ea0f4Smrg from = X_CONFIG; 572301ea0f4Smrg } else { 573301ea0f4Smrg if ((pI740->readControl(pI740, XRX, DRAM_ROW_TYPE)&DRAM_ROW_1)==DRAM_ROW_1_SDRAM) 574301ea0f4Smrg pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_1); 575301ea0f4Smrg else 576301ea0f4Smrg pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_0); 577301ea0f4Smrg pScrn->videoRam = (pScrn->videoRam&0x0F)*1024; 578301ea0f4Smrg from = X_PROBED; 579301ea0f4Smrg } 580301ea0f4Smrg 581301ea0f4Smrg temp=pI740->readControl(pI740, XRX, DRAM_ROW_CNTL_LO); 582301ea0f4Smrg pI740->HasSGRAM = !((temp&DRAM_RAS_TIMING)||(temp&DRAM_RAS_PRECHARGE)); 583301ea0f4Smrg if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) { 584301ea0f4Smrg if (xf86IsOptionSet(pI740->Options, OPTION_SGRAM)) { 585301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 586301ea0f4Smrg "It is nonsensical to set both SDRAM and SGRAM options\n"); 587301ea0f4Smrg return FALSE; 588301ea0f4Smrg } 589301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_SDRAM, FALSE)) { 590301ea0f4Smrg pI740->HasSGRAM = FALSE; 591301ea0f4Smrg } else { 592301ea0f4Smrg pI740->HasSGRAM = TRUE; 593301ea0f4Smrg } 594301ea0f4Smrg } else { 595301ea0f4Smrg if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) { 596301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 597301ea0f4Smrg "It is nonsensical to set both SDRAM and SGRAM options\n"); 598301ea0f4Smrg return FALSE; 599301ea0f4Smrg } 600301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_SGRAM, FALSE)) { 601301ea0f4Smrg pI740->HasSGRAM = TRUE; 602301ea0f4Smrg } else { 603301ea0f4Smrg pI740->HasSGRAM = FALSE; 604301ea0f4Smrg } 605301ea0f4Smrg } 606301ea0f4Smrg 607301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Steve was here! VideoRAM: %d kByte %s\n", 608301ea0f4Smrg pScrn->videoRam, (pI740->HasSGRAM)?"SGRAM":"SDRAM"); 609301ea0f4Smrg pI740->FbMapSize = pScrn->videoRam*1024; 610301ea0f4Smrg 611301ea0f4Smrg /* 612301ea0f4Smrg * If the driver can do gamma correction, it should call xf86SetGamma() 613301ea0f4Smrg * here. 614301ea0f4Smrg */ 615301ea0f4Smrg 616301ea0f4Smrg { 617301ea0f4Smrg Gamma zeros = {0.0, 0.0, 0.0}; 618301ea0f4Smrg 619301ea0f4Smrg if (!xf86SetGamma(pScrn, zeros)) { 620301ea0f4Smrg return FALSE; 621301ea0f4Smrg } 622301ea0f4Smrg } 623301ea0f4Smrg 624301ea0f4Smrg pI740->MaxClock = 0; 625301ea0f4Smrg if (pI740->pEnt->device->dacSpeeds[0]) { 626301ea0f4Smrg switch (pScrn->bitsPerPixel) { 627301ea0f4Smrg case 8: 628301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP8]; 629301ea0f4Smrg break; 630301ea0f4Smrg case 16: 631301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP16]; 632301ea0f4Smrg break; 633301ea0f4Smrg case 24: 634301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP24]; 635301ea0f4Smrg break; 636301ea0f4Smrg case 32: 637301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP32]; 638301ea0f4Smrg break; 639301ea0f4Smrg } 640301ea0f4Smrg if (!pI740->MaxClock) 641301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[0]; 642301ea0f4Smrg from = X_CONFIG; 643301ea0f4Smrg } else { 644301ea0f4Smrg switch (pScrn->bitsPerPixel) { 645301ea0f4Smrg case 8: 646301ea0f4Smrg pI740->MaxClock = 203000; 647301ea0f4Smrg break; 648301ea0f4Smrg case 16: 649301ea0f4Smrg pI740->MaxClock = 163000; 650301ea0f4Smrg break; 651301ea0f4Smrg case 24: 652301ea0f4Smrg if (pI740->HasSGRAM) 653301ea0f4Smrg pI740->MaxClock = 136000; 654301ea0f4Smrg else 655301ea0f4Smrg pI740->MaxClock = 128000; 656301ea0f4Smrg break; 657301ea0f4Smrg case 32: 658301ea0f4Smrg pI740->MaxClock = 86000; 659301ea0f4Smrg } 660301ea0f4Smrg } 661301ea0f4Smrg clockRanges = xnfcalloc(sizeof(ClockRange), 1); 662301ea0f4Smrg clockRanges->next=NULL; 663301ea0f4Smrg clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */ 664301ea0f4Smrg clockRanges->maxClock=pI740->MaxClock; 665301ea0f4Smrg clockRanges->clockIndex = -1; 666301ea0f4Smrg clockRanges->interlaceAllowed = FALSE; /*PL*/ 667301ea0f4Smrg clockRanges->doubleScanAllowed = TRUE; /*PL*/ 668301ea0f4Smrg 6690cc67336Smrg { /*PL*/ 6700cc67336Smrg 6710cc67336Smrg if (xf86LoadSubModule(pScrn, "ddc")) { 6720cc67336Smrg if (xf86LoadSubModule(pScrn, "i2c") ) { 6730cc67336Smrg if (I740MapMem(pScrn)) { 6740cc67336Smrg if (I740_I2CInit(pScrn)) 6750cc67336Smrg { 6760cc67336Smrg xf86MonPtr MonInfo; 6770cc67336Smrg if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pI740->rc_i2c))) { 6780cc67336Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", 6790cc67336Smrg MonInfo); 6800cc67336Smrg xf86PrintEDID( MonInfo ); 6810cc67336Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor " 6820cc67336Smrg "info\n\n"); 6830cc67336Smrg xf86SetDDCproperties(pScrn,MonInfo); 6840cc67336Smrg } 6850cc67336Smrg } 6860cc67336Smrg else 6870cc67336Smrg xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n"); 6880cc67336Smrg 6890cc67336Smrg I740UnmapMem(pScrn); 6900cc67336Smrg } 6910cc67336Smrg } 6920cc67336Smrg } 6930cc67336Smrg } 6940cc67336Smrg 695301ea0f4Smrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 696301ea0f4Smrg pScrn->display->modes, clockRanges, 697301ea0f4Smrg 0, 320, 1600, 698301ea0f4Smrg 8, 200, 1200, 699301ea0f4Smrg pScrn->display->virtualX, pScrn->display->virtualY, 700301ea0f4Smrg pI740->FbMapSize, LOOKUP_BEST_REFRESH); 701301ea0f4Smrg 702301ea0f4Smrg if (i==-1) { 703301ea0f4Smrg I740FreeRec(pScrn); 704301ea0f4Smrg return FALSE; 705301ea0f4Smrg } 706301ea0f4Smrg 707301ea0f4Smrg xf86PruneDriverModes(pScrn); 708301ea0f4Smrg 709301ea0f4Smrg if (!i || !pScrn->modes) { 710301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 711301ea0f4Smrg I740FreeRec(pScrn); 712301ea0f4Smrg return FALSE; 713301ea0f4Smrg } 714301ea0f4Smrg 715301ea0f4Smrg xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 716301ea0f4Smrg 717301ea0f4Smrg pScrn->currentMode = pScrn->modes; 718301ea0f4Smrg 719301ea0f4Smrg xf86PrintModes(pScrn); 720301ea0f4Smrg 721301ea0f4Smrg xf86SetDpi(pScrn, 0, 0); 722301ea0f4Smrg 723301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "fb")) { 724301ea0f4Smrg I740FreeRec(pScrn); 725301ea0f4Smrg return FALSE; 726301ea0f4Smrg } 727301ea0f4Smrg 728301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE)) { 729301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "xaa")) { 730301ea0f4Smrg I740FreeRec(pScrn); 731301ea0f4Smrg return FALSE; 732301ea0f4Smrg } 733301ea0f4Smrg } 734301ea0f4Smrg 735301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) { 736301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "ramdac")) { 737301ea0f4Smrg I740FreeRec(pScrn); 738301ea0f4Smrg return FALSE; 739301ea0f4Smrg } 740301ea0f4Smrg } 741301ea0f4Smrg 742301ea0f4Smrg /* We wont be using the VGA access after the probe */ 743301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_USE_PIO, FALSE)) { 744ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS 745301ea0f4Smrg resRange vgaio[] = { {ResShrIoBlock,0x3B0,0x3BB}, 746301ea0f4Smrg {ResShrIoBlock,0x3C0,0x3DF}, 747301ea0f4Smrg _END }; 748301ea0f4Smrg resRange vgamem[] = {{ResShrMemBlock,0xA0000,0xAFFFF}, 749301ea0f4Smrg {ResShrMemBlock,0xB8000,0xBFFFF}, 750301ea0f4Smrg {ResShrMemBlock,0xB0000,0xB7FFF}, 751301ea0f4Smrg _END }; 752ef6fb4a5Smrg#endif 753301ea0f4Smrg pI740->usePIO=FALSE; 754301ea0f4Smrg I740SetMMIOAccess(pI740); 755ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS 756301ea0f4Smrg xf86SetOperatingState(vgaio, pI740->pEnt->index, ResUnusedOpr); 757301ea0f4Smrg xf86SetOperatingState(vgamem, pI740->pEnt->index, ResDisableOpr); 758ef6fb4a5Smrg#endif 759301ea0f4Smrg } else { 760301ea0f4Smrg pI740->usePIO=TRUE; 761301ea0f4Smrg } 762301ea0f4Smrg 763301ea0f4Smrg if(xf86IsOptionSet(pI740->Options, OPTION_VGACOMPAT)) 764301ea0f4Smrg pI740->usevgacompat=TRUE; 765301ea0f4Smrg else 766301ea0f4Smrg pI740->usevgacompat=FALSE; 767301ea0f4Smrg 768301ea0f4Smrg 769301ea0f4Smrg 770301ea0f4Smrg { /* Overlay */ 771301ea0f4Smrg pI740->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | 772301ea0f4Smrg (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 773301ea0f4Smrg 774301ea0f4Smrg pI740->colorKey &= ((1 << pScrn->depth) - 1); 775301ea0f4Smrg 776301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video overlay key set to 0x%x\n", pI740->colorKey); 777301ea0f4Smrg } 778301ea0f4Smrg 779301ea0f4Smrg 780301ea0f4Smrg return TRUE; 781301ea0f4Smrg} 782301ea0f4Smrg 783301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn) 784301ea0f4Smrg{ 785301ea0f4Smrg int mmioFlags; 786301ea0f4Smrg I740Ptr pI740; 787301ea0f4Smrg 788301ea0f4Smrg pI740 = I740PTR(pScrn); 789301ea0f4Smrg 7900cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 791301ea0f4Smrg mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; 792301ea0f4Smrg 793301ea0f4Smrg pI740->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 794301ea0f4Smrg pI740->PciTag, 795301ea0f4Smrg pI740->MMIOAddr, 796301ea0f4Smrg 0x80000); 7970cc67336Smrg#else 7980cc67336Smrg { 7990cc67336Smrg void** result = (void**)&pI740->MMIOBase; 8000cc67336Smrg int err = pci_device_map_range(pI740->PciInfo, 8010cc67336Smrg pI740->MMIOAddr, 8020cc67336Smrg 0x80000, 8030cc67336Smrg PCI_DEV_MAP_FLAG_WRITABLE, 8040cc67336Smrg result); 8050cc67336Smrg 8060cc67336Smrg if (err) 8070cc67336Smrg return FALSE; 8080cc67336Smrg } 8090cc67336Smrg 8100cc67336Smrg#endif 811301ea0f4Smrg if (!pI740->MMIOBase) return FALSE; 812301ea0f4Smrg 8130cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 814301ea0f4Smrg pI740->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 815301ea0f4Smrg pI740->PciTag, 816301ea0f4Smrg pI740->LinearAddr, 817301ea0f4Smrg pI740->FbMapSize); 8180cc67336Smrg#else 8190cc67336Smrg { 8200cc67336Smrg void** result = (void**)&pI740->FbBase; 8210cc67336Smrg int err = pci_device_map_range(pI740->PciInfo, 8220cc67336Smrg pI740->LinearAddr, 8230cc67336Smrg pI740->FbMapSize, 8240cc67336Smrg PCI_DEV_MAP_FLAG_WRITABLE | 8250cc67336Smrg PCI_DEV_MAP_FLAG_WRITE_COMBINE, 8260cc67336Smrg result); 8270cc67336Smrg 8280cc67336Smrg if (err) 8290cc67336Smrg return FALSE; 8300cc67336Smrg } 8310cc67336Smrg#endif 832301ea0f4Smrg if (!pI740->FbBase) return FALSE; 833301ea0f4Smrg 834301ea0f4Smrg return TRUE; 835301ea0f4Smrg} 836301ea0f4Smrg 837301ea0f4Smrgstatic Bool I740UnmapMem(ScrnInfoPtr pScrn) 838301ea0f4Smrg{ 839301ea0f4Smrg I740Ptr pI740; 840301ea0f4Smrg 841301ea0f4Smrg pI740 = I740PTR(pScrn); 842301ea0f4Smrg 8430cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 844301ea0f4Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->MMIOBase, 0x80000); 8450cc67336Smrg#else 8460cc67336Smrg pci_device_unmap_range(pI740->PciInfo, pI740->MMIOBase, 0x80000); 8470cc67336Smrg#endif 848301ea0f4Smrg pI740->MMIOBase=0; 849301ea0f4Smrg 8500cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 851301ea0f4Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->FbBase, pI740->FbMapSize); 8520cc67336Smrg#else 8530cc67336Smrg pci_device_unmap_range(pI740->PciInfo, pI740->FbBase, pI740->FbMapSize); 8540cc67336Smrg#endif 855301ea0f4Smrg pI740->FbBase = 0; 856301ea0f4Smrg return TRUE; 857301ea0f4Smrg} 858301ea0f4Smrg 859301ea0f4Smrg/* 860301ea0f4Smrg * I740Save -- 861301ea0f4Smrg * 862301ea0f4Smrg * This function saves the video state. It reads all of the SVGA registers 863301ea0f4Smrg * into the vgaI740Rec data structure. There is in general no need to 864301ea0f4Smrg * mask out bits here - just read the registers. 865301ea0f4Smrg */ 866301ea0f4Smrgstatic void 867301ea0f4SmrgDoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg, Bool saveFonts) 868301ea0f4Smrg{ 869301ea0f4Smrg I740Ptr pI740; 870301ea0f4Smrg vgaHWPtr hwp; 871301ea0f4Smrg 872301ea0f4Smrg pI740 = I740PTR(pScrn); 873301ea0f4Smrg hwp = VGAHWPTR(pScrn); 874301ea0f4Smrg 875301ea0f4Smrg /* 876301ea0f4Smrg * This function will handle creating the data structure and filling 877301ea0f4Smrg * in the generic VGA portion. 878301ea0f4Smrg */ 879301ea0f4Smrg if (saveFonts) 880301ea0f4Smrg vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS); 881301ea0f4Smrg else 882301ea0f4Smrg vgaHWSave(pScrn, vgaReg, VGA_SR_MODE); 883301ea0f4Smrg 884301ea0f4Smrg /* 885301ea0f4Smrg * The port I/O code necessary to read in the extended registers 886301ea0f4Smrg * into the fields of the vgaI740Rec structure goes here. 887301ea0f4Smrg */ 888301ea0f4Smrg 889301ea0f4Smrg i740Reg->IOControl = pI740->readControl(pI740, XRX, IO_CTNL); 890301ea0f4Smrg i740Reg->AddressMapping = pI740->readControl(pI740, XRX, ADDRESS_MAPPING); 891301ea0f4Smrg i740Reg->BitBLTControl = pI740->readControl(pI740, XRX, BITBLT_CNTL); 892301ea0f4Smrg i740Reg->VideoClk2_M = pI740->readControl(pI740, XRX, VCLK2_VCO_M); 893301ea0f4Smrg i740Reg->VideoClk2_N = pI740->readControl(pI740, XRX, VCLK2_VCO_N); 894301ea0f4Smrg i740Reg->VideoClk2_MN_MSBs = pI740->readControl(pI740, XRX, VCLK2_VCO_MN_MSBS); 895301ea0f4Smrg i740Reg->VideoClk2_DivisorSel = pI740->readControl(pI740, XRX, VCLK2_VCO_DIV_SEL); 896301ea0f4Smrg i740Reg->PLLControl = pI740->readControl(pI740, XRX, PLL_CNTL); 897301ea0f4Smrg 898301ea0f4Smrg i740Reg->ExtVertTotal=hwp->readCrtc(hwp, EXT_VERT_TOTAL); 899301ea0f4Smrg i740Reg->ExtVertDispEnd=hwp->readCrtc(hwp, EXT_VERT_DISPLAY); 900301ea0f4Smrg i740Reg->ExtVertSyncStart=hwp->readCrtc(hwp, EXT_VERT_SYNC_START); 901301ea0f4Smrg i740Reg->ExtVertBlankStart=hwp->readCrtc(hwp, EXT_VERT_BLANK_START); 902301ea0f4Smrg i740Reg->ExtHorizTotal=hwp->readCrtc(hwp, EXT_HORIZ_TOTAL); 903301ea0f4Smrg i740Reg->ExtHorizBlank=hwp->readCrtc(hwp, EXT_HORIZ_BLANK); 904301ea0f4Smrg i740Reg->ExtOffset=hwp->readCrtc(hwp, EXT_OFFSET); 905301ea0f4Smrg i740Reg->InterlaceControl=hwp->readCrtc(hwp, INTERLACE_CNTL); 906301ea0f4Smrg 907301ea0f4Smrg i740Reg->PixelPipeCfg0 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0); 908301ea0f4Smrg i740Reg->PixelPipeCfg1 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1); 909301ea0f4Smrg i740Reg->PixelPipeCfg2 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2); 910301ea0f4Smrg i740Reg->DisplayControl = pI740->readControl(pI740, XRX, DISPLAY_CNTL); 911301ea0f4Smrg 912301ea0f4Smrg i740Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC); 913301ea0f4Smrg} 914301ea0f4Smrg 915301ea0f4Smrgstatic void 916301ea0f4SmrgI740Save(ScrnInfoPtr pScrn) 917301ea0f4Smrg{ 918301ea0f4Smrg vgaHWPtr hwp; 919301ea0f4Smrg I740Ptr pI740; 920301ea0f4Smrg 921301ea0f4Smrg hwp = VGAHWPTR(pScrn); 922301ea0f4Smrg pI740 = I740PTR(pScrn); 923301ea0f4Smrg DoSave(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE); 924301ea0f4Smrg} 925301ea0f4Smrg 926301ea0f4Smrgstatic void 927301ea0f4SmrgDoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg, 928301ea0f4Smrg Bool restoreFonts) { 929301ea0f4Smrg I740Ptr pI740; 930301ea0f4Smrg vgaHWPtr hwp; 931301ea0f4Smrg unsigned char temp; 932301ea0f4Smrg unsigned int itemp; 933301ea0f4Smrg 934301ea0f4Smrg pI740 = I740PTR(pScrn); 935301ea0f4Smrg hwp = VGAHWPTR(pScrn); 936301ea0f4Smrg 937301ea0f4Smrg vgaHWProtect(pScrn, TRUE); 938301ea0f4Smrg#if 0 939301ea0f4Smrg temp=hwp->readCrtc(hwp, VERT_SYNC_END); 940301ea0f4Smrg hwp->writeCrtc(hwp, VERT_SYNC_END, temp&0x7F); 941301ea0f4Smrg#endif 942301ea0f4Smrg 943301ea0f4Smrg temp = pI740->readControl(pI740, MRX, ACQ_CNTL_2); 944301ea0f4Smrg if ((temp & FRAME_CAP_MODE) == SINGLE_CAP_MODE) { 945301ea0f4Smrg temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1); 946301ea0f4Smrg temp |= BLANK_DISP_OVERLAY; /* Disable the overlay */ 947301ea0f4Smrg pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp); 948301ea0f4Smrg } else { 949301ea0f4Smrg temp &= ~FRAME_CAP_MODE; 950301ea0f4Smrg pI740->writeControl(pI740, MRX, ACQ_CNTL_2, temp); 951301ea0f4Smrg } 952301ea0f4Smrg usleep(50000); 953301ea0f4Smrg 954301ea0f4Smrg /* Turn off DRAM Refresh */ 955301ea0f4Smrg pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE); 956301ea0f4Smrg 957301ea0f4Smrg usleep(1000); /* Wait 1 ms */ 958301ea0f4Smrg 959301ea0f4Smrg /* Write the M, N and P values */ 960301ea0f4Smrg pI740->writeControl(pI740, XRX, VCLK2_VCO_M, i740Reg->VideoClk2_M); 961301ea0f4Smrg pI740->writeControl(pI740, XRX, VCLK2_VCO_N, i740Reg->VideoClk2_N); 962301ea0f4Smrg pI740->writeControl(pI740, XRX, VCLK2_VCO_MN_MSBS, i740Reg->VideoClk2_MN_MSBs); 963301ea0f4Smrg pI740->writeControl(pI740, XRX, VCLK2_VCO_DIV_SEL, i740Reg->VideoClk2_DivisorSel); 964301ea0f4Smrg 965301ea0f4Smrg /* 966301ea0f4Smrg * Turn on 8 bit dac mode, if requested. This is needed to make 967301ea0f4Smrg * sure that vgaHWRestore writes the values into the DAC properly. 968301ea0f4Smrg * The problem occurs if 8 bit dac mode is requested and the HW is 969301ea0f4Smrg * in 6 bit dac mode. If this happens, all the values are 970301ea0f4Smrg * automatically shifted left twice by the HW and incorrect colors 971301ea0f4Smrg * will be displayed on the screen. The only time this can happen 972301ea0f4Smrg * is at server startup time and when switching back from a VT. 973301ea0f4Smrg */ 974301ea0f4Smrg temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0); 975301ea0f4Smrg temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ 976301ea0f4Smrg temp |= (i740Reg->PixelPipeCfg0 & DAC_8_BIT); 977301ea0f4Smrg pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp); 978301ea0f4Smrg 979301ea0f4Smrg /* 980301ea0f4Smrg * Code to restore any SVGA registers that have been saved/modified 981301ea0f4Smrg * goes here. Note that it is allowable, and often correct, to 982301ea0f4Smrg * only modify certain bits in a register by a read/modify/write cycle. 983301ea0f4Smrg * 984301ea0f4Smrg * A special case - when using an external clock-setting program, 985301ea0f4Smrg * this function must not change bits associated with the clock 986301ea0f4Smrg * selection. This condition can be checked by the condition: 987301ea0f4Smrg * 988301ea0f4Smrg * if (restore->std.NoClock >= 0) 989301ea0f4Smrg * restore clock-select bits. 990301ea0f4Smrg */ 991301ea0f4Smrg if (restoreFonts) 992301ea0f4Smrg vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE); 993301ea0f4Smrg else 994301ea0f4Smrg vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); 995301ea0f4Smrg 996301ea0f4Smrg hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i740Reg->ExtVertTotal); 997301ea0f4Smrg hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i740Reg->ExtVertDispEnd); 998301ea0f4Smrg hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i740Reg->ExtVertSyncStart); 999301ea0f4Smrg hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i740Reg->ExtVertBlankStart); 1000301ea0f4Smrg hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i740Reg->ExtHorizTotal); 1001301ea0f4Smrg hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i740Reg->ExtHorizBlank); 1002301ea0f4Smrg hwp->writeCrtc(hwp, EXT_OFFSET, i740Reg->ExtOffset); 1003301ea0f4Smrg 1004301ea0f4Smrg temp=hwp->readCrtc(hwp, INTERLACE_CNTL); 1005301ea0f4Smrg temp &= ~INTERLACE_ENABLE; 1006301ea0f4Smrg temp |= i740Reg->InterlaceControl; 1007301ea0f4Smrg hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); 1008301ea0f4Smrg 1009301ea0f4Smrg temp=pI740->readControl(pI740, XRX, ADDRESS_MAPPING); 1010301ea0f4Smrg temp &= 0xE0; /* Save reserved bits 7:5 */ 1011301ea0f4Smrg temp |= i740Reg->AddressMapping; 1012301ea0f4Smrg pI740->writeControl(pI740, XRX, ADDRESS_MAPPING, temp); 1013301ea0f4Smrg 1014301ea0f4Smrg temp=pI740->readControl(pI740, XRX, BITBLT_CNTL); 1015301ea0f4Smrg temp &= ~COLEXP_MODE; 1016301ea0f4Smrg temp |= i740Reg->BitBLTControl; 1017301ea0f4Smrg pI740->writeControl(pI740, XRX, BITBLT_CNTL, temp); 1018301ea0f4Smrg 1019301ea0f4Smrg temp=pI740->readControl(pI740, XRX, DISPLAY_CNTL); 1020301ea0f4Smrg temp &= ~(VGA_WRAP_MODE | GUI_MODE); 1021301ea0f4Smrg temp |= i740Reg->DisplayControl; 1022301ea0f4Smrg pI740->writeControl(pI740, XRX, DISPLAY_CNTL, temp); 1023301ea0f4Smrg 1024301ea0f4Smrg temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0); 1025301ea0f4Smrg temp &= 0x64; /* Save reserved bits 6:5,2 */ 1026301ea0f4Smrg temp |= i740Reg->PixelPipeCfg0; 1027301ea0f4Smrg pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp); 1028301ea0f4Smrg 1029301ea0f4Smrg temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2); 1030301ea0f4Smrg temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ 1031301ea0f4Smrg temp |= i740Reg->PixelPipeCfg2; 1032301ea0f4Smrg pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_2, temp); 1033301ea0f4Smrg 1034301ea0f4Smrg temp=pI740->readControl(pI740, XRX, PLL_CNTL); 1035301ea0f4Smrg temp = i740Reg->PLLControl; /* To fix the 2.3X BIOS problem */ 1036301ea0f4Smrg pI740->writeControl(pI740, XRX, PLL_CNTL, temp); 1037301ea0f4Smrg 1038301ea0f4Smrg temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1); 1039301ea0f4Smrg temp &= ~DISPLAY_COLOR_MODE; 1040301ea0f4Smrg temp |= i740Reg->PixelPipeCfg1; 1041301ea0f4Smrg pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_1, temp); 1042301ea0f4Smrg 1043301ea0f4Smrg itemp = INREG(FWATER_BLC); 1044301ea0f4Smrg itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK); 1045301ea0f4Smrg itemp |= i740Reg->LMI_FIFO_Watermark; 1046301ea0f4Smrg OUTREG(FWATER_BLC, itemp); 1047301ea0f4Smrg 1048301ea0f4Smrg /* Turn on DRAM Refresh */ 1049301ea0f4Smrg pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ); 1050301ea0f4Smrg 1051301ea0f4Smrg temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1); 1052301ea0f4Smrg temp &= ~BLANK_DISP_OVERLAY; /* Re-enable the overlay */ 1053301ea0f4Smrg pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp); 1054301ea0f4Smrg 1055301ea0f4Smrg if (!(vgaReg->Attribute[0x10] & 0x1)) { 1056301ea0f4Smrg usleep(50000); 1057301ea0f4Smrg if (restoreFonts) 1058301ea0f4Smrg vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE); 1059301ea0f4Smrg else 1060301ea0f4Smrg vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); 1061301ea0f4Smrg } 1062301ea0f4Smrg 1063301ea0f4Smrg vgaHWProtect(pScrn, FALSE); 1064301ea0f4Smrg temp=pI740->readControl(pI740, XRX, IO_CTNL); 1065301ea0f4Smrg temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL); 1066301ea0f4Smrg temp |= i740Reg->IOControl; 1067301ea0f4Smrg pI740->writeControl(pI740, XRX, IO_CTNL, temp); 1068301ea0f4Smrg#if 0 1069301ea0f4Smrg temp=hwp->readCrtc(hwp, VERT_SYNC_END); 1070301ea0f4Smrg hwp->writeCrtc(hwp, VERT_SYNC_END, temp|0x80); 1071301ea0f4Smrg#endif 1072301ea0f4Smrg} 1073301ea0f4Smrg 1074301ea0f4Smrgstatic void 1075301ea0f4SmrgI740Restore(ScrnInfoPtr pScrn) { 1076301ea0f4Smrg vgaHWPtr hwp; 1077301ea0f4Smrg I740Ptr pI740; 1078301ea0f4Smrg 1079301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1080301ea0f4Smrg pI740 = I740PTR(pScrn); 1081301ea0f4Smrg 1082301ea0f4Smrg DoRestore(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE); 1083301ea0f4Smrg} 1084301ea0f4Smrg 1085301ea0f4Smrg/* 1086301ea0f4Smrg * I740CalcFIFO -- 1087301ea0f4Smrg * 1088301ea0f4Smrg * Calculate burst length and FIFO watermark. 1089301ea0f4Smrg */ 1090301ea0f4Smrg 1091301ea0f4Smrgstatic unsigned int 1092301ea0f4SmrgI740CalcFIFO(ScrnInfoPtr pScrn, double freq) 1093301ea0f4Smrg{ 1094301ea0f4Smrg unsigned int wm = 0x18120000; 1095301ea0f4Smrg I740Ptr pI740; 1096301ea0f4Smrg 1097301ea0f4Smrg pI740 = I740PTR(pScrn); 1098301ea0f4Smrg 1099301ea0f4Smrg /* 1100301ea0f4Smrg * Would like to calculate these values automatically, but a generic 1101301ea0f4Smrg * algorithm does not seem possible. Note: These FIFO water mark 1102301ea0f4Smrg * values were tested on several cards and seem to eliminate the 1103301ea0f4Smrg * all of the snow and vertical banding, but fine adjustments will 1104301ea0f4Smrg * probably be required for other cards. 1105301ea0f4Smrg */ 1106301ea0f4Smrg 1107301ea0f4Smrg switch (pScrn->bitsPerPixel) { 1108301ea0f4Smrg case 8: 1109301ea0f4Smrg if (pI740->HasSGRAM) { 1110301ea0f4Smrg if (freq > 200) wm = 0x18120000; 1111301ea0f4Smrg else if (freq > 175) wm = 0x16110000; 1112301ea0f4Smrg else if (freq > 135) wm = 0x120E0000; 1113301ea0f4Smrg else wm = 0x100D0000; 1114301ea0f4Smrg } else { 1115301ea0f4Smrg if (freq > 200) wm = 0x18120000; 1116301ea0f4Smrg else if (freq > 175) wm = 0x16110000; 1117301ea0f4Smrg else if (freq > 135) wm = 0x120E0000; 1118301ea0f4Smrg else wm = 0x100D0000; 1119301ea0f4Smrg } 1120301ea0f4Smrg break; 1121301ea0f4Smrg case 16: 1122301ea0f4Smrg if (pI740->HasSGRAM) { 1123301ea0f4Smrg if (freq > 140) wm = 0x2C1D0000; 1124301ea0f4Smrg else if (freq > 120) wm = 0x2C180000; 1125301ea0f4Smrg else if (freq > 100) wm = 0x24160000; 1126301ea0f4Smrg else if (freq > 90) wm = 0x18120000; 1127301ea0f4Smrg else if (freq > 50) wm = 0x16110000; 1128301ea0f4Smrg else if (freq > 32) wm = 0x13100000; 1129301ea0f4Smrg else wm = 0x120E0000; 1130301ea0f4Smrg } else { 1131301ea0f4Smrg if (freq > 160) wm = 0x28200000; 1132301ea0f4Smrg else if (freq > 140) wm = 0x2A1E0000; 1133301ea0f4Smrg else if (freq > 130) wm = 0x2B1A0000; 1134301ea0f4Smrg else if (freq > 120) wm = 0x2C180000; 1135301ea0f4Smrg else if (freq > 100) wm = 0x24180000; 1136301ea0f4Smrg else if (freq > 90) wm = 0x18120000; 1137301ea0f4Smrg else if (freq > 50) wm = 0x16110000; 1138301ea0f4Smrg else if (freq > 32) wm = 0x13100000; 1139301ea0f4Smrg else wm = 0x120E0000; 1140301ea0f4Smrg } 1141301ea0f4Smrg break; 1142301ea0f4Smrg case 24: 1143301ea0f4Smrg if (pI740->HasSGRAM) { 1144301ea0f4Smrg if (freq > 130) wm = 0x31200000; 1145301ea0f4Smrg else if (freq > 120) wm = 0x2E200000; 1146301ea0f4Smrg else if (freq > 100) wm = 0x2C1D0000; 1147301ea0f4Smrg else if (freq > 80) wm = 0x25180000; 1148301ea0f4Smrg else if (freq > 64) wm = 0x24160000; 1149301ea0f4Smrg else if (freq > 49) wm = 0x18120000; 1150301ea0f4Smrg else if (freq > 32) wm = 0x16110000; 1151301ea0f4Smrg else wm = 0x13100000; 1152301ea0f4Smrg } else { 1153301ea0f4Smrg if (freq > 120) wm = 0x311F0000; 1154301ea0f4Smrg else if (freq > 100) wm = 0x2C1D0000; 1155301ea0f4Smrg else if (freq > 80) wm = 0x25180000; 1156301ea0f4Smrg else if (freq > 64) wm = 0x24160000; 1157301ea0f4Smrg else if (freq > 49) wm = 0x18120000; 1158301ea0f4Smrg else if (freq > 32) wm = 0x16110000; 1159301ea0f4Smrg else wm = 0x13100000; 1160301ea0f4Smrg } 1161301ea0f4Smrg break; 1162301ea0f4Smrg case 32: 1163301ea0f4Smrg if (pI740->HasSGRAM) { 1164301ea0f4Smrg if (freq > 80) wm = 0x2A200000; 1165301ea0f4Smrg else if (freq > 60) wm = 0x281A0000; 1166301ea0f4Smrg else if (freq > 49) wm = 0x25180000; 1167301ea0f4Smrg else if (freq > 32) wm = 0x18120000; 1168301ea0f4Smrg else wm = 0x16110000; 1169301ea0f4Smrg } else { 1170301ea0f4Smrg if (freq > 80) wm = 0x29200000; 1171301ea0f4Smrg else if (freq > 60) wm = 0x281A0000; 1172301ea0f4Smrg else if (freq > 49) wm = 0x25180000; 1173301ea0f4Smrg else if (freq > 32) wm = 0x18120000; 1174301ea0f4Smrg else wm = 0x16110000; 1175301ea0f4Smrg } 1176301ea0f4Smrg break; 1177301ea0f4Smrg } 1178301ea0f4Smrg 1179301ea0f4Smrg return wm; 1180301ea0f4Smrg} 1181301ea0f4Smrg 1182301ea0f4Smrg/* 1183301ea0f4Smrg * I740CalcVCLK -- 1184301ea0f4Smrg * 1185301ea0f4Smrg * Determine the closest clock frequency to the one requested. 1186301ea0f4Smrg */ 1187301ea0f4Smrg 1188301ea0f4Smrg#define MAX_VCO_FREQ 450.0 1189301ea0f4Smrg#define TARGET_MAX_N 30 1190301ea0f4Smrg#define REF_FREQ 66.66666666667 1191301ea0f4Smrg 1192301ea0f4Smrg#define CALC_VCLK(m,n,p,d) \ 1193301ea0f4Smrg (double)m / ((double)n * (1 << p)) * (4 << (d << 1)) * REF_FREQ 1194301ea0f4Smrg 1195301ea0f4Smrgstatic void 1196301ea0f4SmrgI740CalcVCLK(ScrnInfoPtr pScrn, double freq) 1197301ea0f4Smrg{ 1198301ea0f4Smrg I740Ptr pI740; 1199301ea0f4Smrg I740RegPtr i740Reg; 1200301ea0f4Smrg int m, n, p, d; 1201301ea0f4Smrg double f_out; 1202301ea0f4Smrg double f_err; 1203301ea0f4Smrg double f_vco; 1204301ea0f4Smrg int m_best = 0, n_best = 0, p_best = 0, d_best = 0; 1205301ea0f4Smrg double f_target = freq; 1206301ea0f4Smrg double err_max = 0.005; 1207301ea0f4Smrg double err_target = 0.001; 1208301ea0f4Smrg double err_best = 999999.0; 1209301ea0f4Smrg 1210301ea0f4Smrg pI740 = I740PTR(pScrn); 1211301ea0f4Smrg i740Reg = &pI740->ModeReg; 1212301ea0f4Smrg 1213301ea0f4Smrg p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2); 1214301ea0f4Smrg d_best = d = 0; 1215301ea0f4Smrg 1216301ea0f4Smrg f_vco = f_target * (1 << p); 1217301ea0f4Smrg 1218301ea0f4Smrg n = 2; 1219301ea0f4Smrg do { 1220301ea0f4Smrg n++; 1221301ea0f4Smrg m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; 1222301ea0f4Smrg if (m < 3) m = 3; 1223301ea0f4Smrg f_out = CALC_VCLK(m,n,p,d); 1224301ea0f4Smrg f_err = 1.0 - (f_target/f_out); 1225301ea0f4Smrg if (fabs(f_err) < err_max) { 1226301ea0f4Smrg m_best = m; 1227301ea0f4Smrg n_best = n; 1228301ea0f4Smrg err_best = f_err; 1229301ea0f4Smrg } 1230301ea0f4Smrg } while ((fabs(f_err) >= err_target) && 1231301ea0f4Smrg ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); 1232301ea0f4Smrg 1233301ea0f4Smrg if (fabs(f_err) < err_target) { 1234301ea0f4Smrg m_best = m; 1235301ea0f4Smrg n_best = n; 1236301ea0f4Smrg } 1237301ea0f4Smrg 1238301ea0f4Smrg i740Reg->VideoClk2_M = (m_best-2) & 0xFF; 1239301ea0f4Smrg i740Reg->VideoClk2_N = (n_best-2) & 0xFF; 1240301ea0f4Smrg i740Reg->VideoClk2_MN_MSBs = ((((n_best-2) >> 4) & VCO_N_MSBS) | 1241301ea0f4Smrg (((m_best-2) >> 8) & VCO_M_MSBS)); 1242301ea0f4Smrg i740Reg->VideoClk2_DivisorSel = ((p_best << 4) | 1243301ea0f4Smrg (d_best ? 4 : 0) | 1244301ea0f4Smrg REF_DIV_1); 1245301ea0f4Smrg} 1246301ea0f4Smrg 1247301ea0f4Smrgstatic Bool 1248301ea0f4SmrgI740SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) { 1249301ea0f4Smrg I740Ptr pI740; 1250301ea0f4Smrg I740RegPtr i740Reg; 1251301ea0f4Smrg vgaRegPtr pVga; 1252301ea0f4Smrg double dclk = mode->Clock/1000.0; 1253301ea0f4Smrg 1254301ea0f4Smrg pI740 = I740PTR(pScrn); 1255301ea0f4Smrg i740Reg = &pI740->ModeReg; 1256301ea0f4Smrg pVga = &VGAHWPTR(pScrn)->ModeReg; 1257301ea0f4Smrg 1258301ea0f4Smrg switch (pScrn->bitsPerPixel) { 1259301ea0f4Smrg case 8: 1260301ea0f4Smrg pVga->CRTC[0x13] = pScrn->displayWidth >> 3; 1261301ea0f4Smrg i740Reg->ExtOffset = pScrn->displayWidth >> 11; 1262301ea0f4Smrg i740Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE; 1263301ea0f4Smrg i740Reg->BitBLTControl = COLEXP_8BPP; 1264301ea0f4Smrg break; 1265301ea0f4Smrg case 16: 1266301ea0f4Smrg if (pScrn->weight.green == 5) { 1267301ea0f4Smrg i740Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE; 1268301ea0f4Smrg } else { 1269301ea0f4Smrg i740Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE; 1270301ea0f4Smrg } 1271301ea0f4Smrg pVga->CRTC[0x13] = pScrn->displayWidth >> 2; 1272301ea0f4Smrg i740Reg->ExtOffset = pScrn->displayWidth >> 10; 1273301ea0f4Smrg i740Reg->BitBLTControl = COLEXP_16BPP; 1274301ea0f4Smrg break; 1275301ea0f4Smrg case 24: 1276301ea0f4Smrg pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3; 1277301ea0f4Smrg i740Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11; 1278301ea0f4Smrg i740Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE; 1279301ea0f4Smrg i740Reg->BitBLTControl = COLEXP_24BPP; 1280301ea0f4Smrg break; 1281301ea0f4Smrg case 32: 1282301ea0f4Smrg pVga->CRTC[0x13] = pScrn->displayWidth >> 1; 1283301ea0f4Smrg i740Reg->ExtOffset = pScrn->displayWidth >> 9; 1284301ea0f4Smrg i740Reg->PixelPipeCfg1 = DISPLAY_32BPP_MODE; 1285301ea0f4Smrg i740Reg->BitBLTControl = COLEXP_RESERVED; /* Not implemented on i740 */ 1286301ea0f4Smrg break; 1287301ea0f4Smrg default: 1288301ea0f4Smrg break; 1289301ea0f4Smrg } 1290301ea0f4Smrg 1291301ea0f4Smrg /* Turn on 8 bit dac if requested */ 1292301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE)) 1293301ea0f4Smrg i740Reg->PixelPipeCfg0 = DAC_6_BIT; 1294301ea0f4Smrg else 1295301ea0f4Smrg i740Reg->PixelPipeCfg0 = DAC_8_BIT; 1296301ea0f4Smrg 1297301ea0f4Smrg i740Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE /*| OVERLAY_GAMMA_ENABLE*/; 1298301ea0f4Smrg 1299301ea0f4Smrg /* Turn on Extended VGA Interpretation */ 1300301ea0f4Smrg i740Reg->IOControl = EXTENDED_CRTC_CNTL; 1301301ea0f4Smrg 1302301ea0f4Smrg /* Turn on linear and page mapping */ 1303301ea0f4Smrg i740Reg->AddressMapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE; 1304301ea0f4Smrg 1305301ea0f4Smrg /* Turn on GUI mode */ 1306301ea0f4Smrg i740Reg->DisplayControl = HIRES_MODE; 1307301ea0f4Smrg 1308301ea0f4Smrg /* Set the MCLK freq */ 1309301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_SLOW_RAM, FALSE)) 1310301ea0f4Smrg i740Reg->PLLControl = PLL_MEMCLK__66667KHZ; /* 66 MHz */ 1311301ea0f4Smrg else 1312301ea0f4Smrg i740Reg->PLLControl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */ 1313301ea0f4Smrg 1314301ea0f4Smrg /* Calculate the extended CRTC regs */ 1315301ea0f4Smrg i740Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8; 1316301ea0f4Smrg i740Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8; 1317301ea0f4Smrg i740Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8; 1318301ea0f4Smrg i740Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8; 1319301ea0f4Smrg i740Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8; 1320301ea0f4Smrg /* 1321301ea0f4Smrg * the KGA fix in vgaHW.c results in the first 1322301ea0f4Smrg * scanline and the first character clock (8 pixels) 1323301ea0f4Smrg * of each scanline thereafter on display with an i740 1324301ea0f4Smrg * to be blank. Restoring CRTC 3, 5, & 22 to their 1325301ea0f4Smrg * "theoretical" values corrects the problem. KAO. 1326301ea0f4Smrg */ 1327301ea0f4Smrg i740Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0) << 6; 1328301ea0f4Smrg vgaHWVBlankKGA(mode, pVga, 8, 0); 1329301ea0f4Smrg 1330301ea0f4Smrg /* Turn on interlaced mode if necessary */ 1331301ea0f4Smrg if (mode->Flags & V_INTERLACE) 1332301ea0f4Smrg i740Reg->InterlaceControl = INTERLACE_ENABLE; 1333301ea0f4Smrg else 1334301ea0f4Smrg i740Reg->InterlaceControl = INTERLACE_DISABLE; 1335301ea0f4Smrg 1336301ea0f4Smrg /* 1337301ea0f4Smrg * Set the overscan color to 0. 1338301ea0f4Smrg * NOTE: This only affects >8bpp mode. 1339301ea0f4Smrg */ 1340301ea0f4Smrg pVga->Attribute[0x11] = 0; 1341301ea0f4Smrg 1342301ea0f4Smrg /* 1343301ea0f4Smrg * Calculate the VCLK that most closely matches the requested dot 1344301ea0f4Smrg * clock. 1345301ea0f4Smrg */ 1346301ea0f4Smrg I740CalcVCLK(pScrn, dclk); 1347301ea0f4Smrg 1348301ea0f4Smrg /* Since we program the clocks ourselves, always use VCLK2. */ 1349301ea0f4Smrg pVga->MiscOutReg |= 0x0C; 1350301ea0f4Smrg 1351301ea0f4Smrg /* Calculate the FIFO Watermark and Burst Length. */ 1352301ea0f4Smrg i740Reg->LMI_FIFO_Watermark = I740CalcFIFO(pScrn, dclk); 1353301ea0f4Smrg 1354301ea0f4Smrg /*-Overlay-*/ 1355301ea0f4Smrg pI740->ov_offset_x=((mode->CrtcHTotal-mode->CrtcHDisplay) & ~7)-9; 1356301ea0f4Smrg pI740->ov_offset_y=mode->CrtcVTotal-mode->CrtcVSyncEnd-2; 1357301ea0f4Smrg /*-*/ 1358301ea0f4Smrg 1359301ea0f4Smrg return TRUE; 1360301ea0f4Smrg} 1361301ea0f4Smrg 1362301ea0f4Smrgstatic Bool 1363301ea0f4SmrgI740ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode_src) 1364301ea0f4Smrg{ 1365301ea0f4Smrg vgaHWPtr hwp; 1366301ea0f4Smrg I740Ptr pI740; 1367301ea0f4Smrg struct _DisplayModeRec mode_dst; 1368301ea0f4Smrg DisplayModePtr mode=&mode_dst; 1369301ea0f4Smrg 1370301ea0f4Smrg *mode=*mode_src; 1371301ea0f4Smrg 1372301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1373301ea0f4Smrg pI740 = I740PTR(pScrn); 1374301ea0f4Smrg 1375301ea0f4Smrg vgaHWUnlock(hwp); 1376301ea0f4Smrg 1377301ea0f4Smrg 1378301ea0f4Smrg if(pI740->usevgacompat) 1379301ea0f4Smrg { /* Try to get the same visual aspect as a S3 board */ 1380301ea0f4Smrg mode->CrtcHSyncStart+=16; 1381301ea0f4Smrg mode->CrtcHSyncEnd +=16; 1382301ea0f4Smrg } 1383301ea0f4Smrg 1384301ea0f4Smrg if (!vgaHWInit(pScrn, mode)) return FALSE; 1385301ea0f4Smrg 1386301ea0f4Smrg pScrn->vtSema = TRUE; 1387301ea0f4Smrg 1388301ea0f4Smrg if (!I740SetMode(pScrn, mode)) return FALSE; 1389301ea0f4Smrg 1390301ea0f4Smrg DoRestore(pScrn, &hwp->ModeReg, &pI740->ModeReg, FALSE); 1391301ea0f4Smrg 1392301ea0f4Smrg return TRUE; 1393301ea0f4Smrg} 1394301ea0f4Smrg 1395301ea0f4Smrgstatic void I740LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) 1396301ea0f4Smrg{ 1397301ea0f4Smrg vgaHWPtr hwp; 1398301ea0f4Smrg int i, index; 1399301ea0f4Smrg unsigned char r, g, b; 1400301ea0f4Smrg 1401301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1402301ea0f4Smrg 1403301ea0f4Smrg for (i=0; i<numColors; i++) 1404301ea0f4Smrg { 1405301ea0f4Smrg index=indices[i/2]; 1406301ea0f4Smrg r=colors[index].red; 1407301ea0f4Smrg b=colors[index].blue; 1408301ea0f4Smrg g=colors[index].green; 1409301ea0f4Smrg 1410301ea0f4Smrg hwp->writeDacWriteAddr(hwp, index<<2); 1411301ea0f4Smrg hwp->writeDacData(hwp, r); 1412301ea0f4Smrg hwp->writeDacData(hwp, g); 1413301ea0f4Smrg hwp->writeDacData(hwp, b); 1414301ea0f4Smrg 1415301ea0f4Smrg i++; 1416301ea0f4Smrg hwp->writeDacWriteAddr(hwp, index<<2); 1417301ea0f4Smrg hwp->writeDacData(hwp, r); 1418301ea0f4Smrg hwp->writeDacData(hwp, g); 1419301ea0f4Smrg hwp->writeDacData(hwp, b); 1420301ea0f4Smrg } 1421301ea0f4Smrg} 1422301ea0f4Smrg 1423301ea0f4Smrgstatic void I740LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) 1424301ea0f4Smrg{ 1425301ea0f4Smrg vgaHWPtr hwp; 1426301ea0f4Smrg int i, index; 1427301ea0f4Smrg unsigned char r, g, b; 1428301ea0f4Smrg 1429301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1430301ea0f4Smrg for (i=0; i<numColors; i++) { 1431301ea0f4Smrg index=indices[i/2]; 1432301ea0f4Smrg r=colors[index].red; 1433301ea0f4Smrg b=colors[index].blue; 1434301ea0f4Smrg index=indices[i]; 1435301ea0f4Smrg g=colors[index].green; 1436301ea0f4Smrg hwp->writeDacWriteAddr(hwp, index<<2); 1437301ea0f4Smrg hwp->writeDacData(hwp, r); 1438301ea0f4Smrg hwp->writeDacData(hwp, g); 1439301ea0f4Smrg hwp->writeDacData(hwp, b); 1440301ea0f4Smrg i++; 1441301ea0f4Smrg index=indices[i]; 1442301ea0f4Smrg g=colors[index].green; 1443301ea0f4Smrg hwp->writeDacWriteAddr(hwp, index<<2); 1444301ea0f4Smrg hwp->writeDacData(hwp, r); 1445301ea0f4Smrg hwp->writeDacData(hwp, g); 1446301ea0f4Smrg hwp->writeDacData(hwp, b); 1447301ea0f4Smrg } 1448301ea0f4Smrg} 1449301ea0f4Smrg 1450301ea0f4Smrgstatic void 1451301ea0f4SmrgI740LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 1452301ea0f4Smrg VisualPtr pVisual) { 1453301ea0f4Smrg vgaHWPtr hwp; 1454301ea0f4Smrg int i, index; 1455301ea0f4Smrg unsigned char r, g, b; 1456301ea0f4Smrg 1457301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1458301ea0f4Smrg for (i=0; i<numColors; i++) { 1459301ea0f4Smrg index=indices[i]; 1460301ea0f4Smrg r=colors[index].red; 1461301ea0f4Smrg b=colors[index].blue; 1462301ea0f4Smrg index=indices[i]; 1463301ea0f4Smrg g=colors[index].green; 1464301ea0f4Smrg hwp->writeDacWriteAddr(hwp, index); 1465301ea0f4Smrg hwp->writeDacData(hwp, r); 1466301ea0f4Smrg hwp->writeDacData(hwp, g); 1467301ea0f4Smrg hwp->writeDacData(hwp, b); 1468301ea0f4Smrg } 1469301ea0f4Smrg} 1470301ea0f4Smrg 1471301ea0f4Smrgstatic Bool 1472301ea0f4SmrgI740ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { 1473301ea0f4Smrg ScrnInfoPtr pScrn; 1474301ea0f4Smrg vgaHWPtr hwp; 1475301ea0f4Smrg I740Ptr pI740; 1476301ea0f4Smrg VisualPtr visual; 1477301ea0f4Smrg 1478301ea0f4Smrg pScrn = xf86Screens[pScreen->myNum]; 1479301ea0f4Smrg pI740 = I740PTR(pScrn); 1480301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1481301ea0f4Smrg 1482301ea0f4Smrg if (!I740MapMem(pScrn)) return FALSE; 1483301ea0f4Smrg pScrn->memPhysBase = pI740->LinearAddr; 1484301ea0f4Smrg pScrn->fbOffset = 0; 1485301ea0f4Smrg 1486301ea0f4Smrg if (!pI740->usePIO) 1487301ea0f4Smrg vgaHWSetMmioFuncs(hwp, pI740->MMIOBase, 0); 1488301ea0f4Smrg vgaHWGetIOBase(hwp); 1489301ea0f4Smrg if (!vgaHWMapMem(pScrn)) return FALSE; 1490301ea0f4Smrg 1491301ea0f4Smrg I740Save(pScrn); 1492301ea0f4Smrg if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE; 1493301ea0f4Smrg 1494301ea0f4Smrg I740SaveScreen(pScreen, SCREEN_SAVER_ON); 1495301ea0f4Smrg I740AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1496301ea0f4Smrg 1497301ea0f4Smrg miClearVisualTypes(); 1498301ea0f4Smrg 1499301ea0f4Smrg if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 1500301ea0f4Smrg pScrn->rgbBits, pScrn->defaultVisual)) 1501301ea0f4Smrg return FALSE; 1502301ea0f4Smrg if (!miSetPixmapDepths ()) return FALSE; 1503301ea0f4Smrg 1504301ea0f4Smrg switch (pScrn->bitsPerPixel) { 1505301ea0f4Smrg case 8: 1506301ea0f4Smrg case 16: 1507301ea0f4Smrg case 24: 1508301ea0f4Smrg case 32: 1509301ea0f4Smrg if (!fbScreenInit(pScreen, pI740->FbBase, 1510301ea0f4Smrg pScrn->virtualX, pScrn->virtualY, 1511301ea0f4Smrg pScrn->xDpi, pScrn->yDpi, 1512301ea0f4Smrg pScrn->displayWidth,pScrn->bitsPerPixel)) 1513301ea0f4Smrg return FALSE; 1514301ea0f4Smrg break; 1515301ea0f4Smrg default: 1516301ea0f4Smrg xf86DrvMsg(scrnIndex, X_ERROR, 1517301ea0f4Smrg "Internal error: invalid bpp (%d) in I740ScrnInit\n", 1518301ea0f4Smrg pScrn->bitsPerPixel); 1519301ea0f4Smrg return FALSE; 1520301ea0f4Smrg } 1521301ea0f4Smrg fbPictureInit(pScreen,0,0); 1522301ea0f4Smrg 1523301ea0f4Smrg xf86SetBlackWhitePixels(pScreen); 1524301ea0f4Smrg 1525301ea0f4Smrg memset(&(pI740->FbMemBox), 0, sizeof(BoxRec)); 1526301ea0f4Smrg pI740->FbMemBox.x1=0; 1527301ea0f4Smrg pI740->FbMemBox.x2=pScrn->displayWidth; 1528301ea0f4Smrg pI740->FbMemBox.y1=0; 1529301ea0f4Smrg pI740->FbMemBox.y2=pI740->FbMapSize/(pScrn->displayWidth*pI740->cpp); 1530301ea0f4Smrg 1531301ea0f4Smrg I740DGAInit(pScreen); 1532301ea0f4Smrg 1533301ea0f4Smrg if (!xf86InitFBManager(pScreen, &pI740->FbMemBox)) { 1534301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); 1535301ea0f4Smrg return FALSE; 1536301ea0f4Smrg } 1537301ea0f4Smrg 1538301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE)) { 1539301ea0f4Smrg if (!I740AccelInit(pScreen)) { 1540301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1541301ea0f4Smrg "Hardware acceleration initialization failed\n"); 1542301ea0f4Smrg } 1543301ea0f4Smrg } 1544301ea0f4Smrg 1545301ea0f4Smrg if (pScrn->bitsPerPixel>8) { 1546301ea0f4Smrg visual = pScreen->visuals + pScreen->numVisuals; 1547301ea0f4Smrg while (--visual >= pScreen->visuals) { 1548301ea0f4Smrg if ((visual->class | DynamicClass) == DirectColor) { 1549301ea0f4Smrg visual->offsetRed = pScrn->offset.red; 1550301ea0f4Smrg visual->offsetGreen = pScrn->offset.green; 1551301ea0f4Smrg visual->offsetBlue = pScrn->offset.blue; 1552301ea0f4Smrg visual->redMask = pScrn->mask.red; 1553301ea0f4Smrg visual->greenMask = pScrn->mask.green; 1554301ea0f4Smrg visual->blueMask = pScrn->mask.blue; 1555301ea0f4Smrg } 1556301ea0f4Smrg } 1557301ea0f4Smrg } 1558301ea0f4Smrg 1559301ea0f4Smrg miInitializeBackingStore(pScreen); 1560301ea0f4Smrg xf86SetBackingStore(pScreen); 1561301ea0f4Smrg xf86SetSilkenMouse(pScreen); 1562301ea0f4Smrg 1563301ea0f4Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1564301ea0f4Smrg 1565301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) { 1566301ea0f4Smrg if (!I740CursorInit(pScreen)) { 1567301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1568301ea0f4Smrg "Hardware cursor initialization failed\n"); 1569301ea0f4Smrg } 1570301ea0f4Smrg } 1571301ea0f4Smrg 1572301ea0f4Smrg if (!miCreateDefColormap(pScreen)) return FALSE; 1573301ea0f4Smrg 1574301ea0f4Smrg if (pScrn->bitsPerPixel==16) 1575301ea0f4Smrg { 1576301ea0f4Smrg if (pScrn->weight.green == 5) 1577301ea0f4Smrg { 1578301ea0f4Smrg if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette15, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1579301ea0f4Smrg return FALSE; 1580301ea0f4Smrg } 1581301ea0f4Smrg else 1582301ea0f4Smrg { 1583301ea0f4Smrg if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette16, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1584301ea0f4Smrg return FALSE; 1585301ea0f4Smrg } 1586301ea0f4Smrg } 1587301ea0f4Smrg else 1588301ea0f4Smrg { 1589301ea0f4Smrg if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette24, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1590301ea0f4Smrg return FALSE; 1591301ea0f4Smrg } 1592301ea0f4Smrg 1593301ea0f4Smrg xf86DPMSInit(pScreen, I740DisplayPowerManagementSet, 0); 1594301ea0f4Smrg 1595301ea0f4Smrg pScreen->SaveScreen = I740SaveScreen; 1596301ea0f4Smrg pI740->CloseScreen = pScreen->CloseScreen; 1597301ea0f4Smrg pScreen->CloseScreen = I740CloseScreen; 1598301ea0f4Smrg 1599301ea0f4Smrg if (serverGeneration == 1) 1600301ea0f4Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1601301ea0f4Smrg 1602301ea0f4Smrg /* Overlay */ 1603301ea0f4Smrg I740InitVideo(pScreen); pI740->OverlayStart = pI740->CursorStart + 1024; 1604301ea0f4Smrg 1605301ea0f4Smrg return TRUE; 1606301ea0f4Smrg} 1607301ea0f4Smrg 1608301ea0f4SmrgBool 1609301ea0f4SmrgI740SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { 1610301ea0f4Smrg ScrnInfoPtr pScrn; 1611301ea0f4Smrg 1612301ea0f4Smrg pScrn=xf86Screens[scrnIndex]; 1613301ea0f4Smrg return I740ModeInit(pScrn, mode); 1614301ea0f4Smrg} 1615301ea0f4Smrg 1616301ea0f4Smrgvoid 1617301ea0f4SmrgI740AdjustFrame(int scrnIndex, int x, int y, int flags) { 1618301ea0f4Smrg ScrnInfoPtr pScrn; 1619301ea0f4Smrg int Base; 1620301ea0f4Smrg vgaHWPtr hwp; 1621301ea0f4Smrg 1622301ea0f4Smrg pScrn = xf86Screens[scrnIndex]; 1623301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1624301ea0f4Smrg 1625301ea0f4Smrg Base = (y * pScrn->displayWidth + x) >> 2; 1626301ea0f4Smrg switch (pScrn->bitsPerPixel) { 1627301ea0f4Smrg case 8: 1628301ea0f4Smrg break; 1629301ea0f4Smrg case 16: 1630301ea0f4Smrg Base *= 2; 1631301ea0f4Smrg break; 1632301ea0f4Smrg case 24: 1633301ea0f4Smrg /* 1634301ea0f4Smrg * The last bit does not seem to have any effect on the start 1635301ea0f4Smrg * address register in 24bpp mode, so... 1636301ea0f4Smrg */ 1637301ea0f4Smrg Base &= 0xFFFFFFFE; /* ...ignore the last bit. */ 1638301ea0f4Smrg Base *= 3; 1639301ea0f4Smrg break; 1640301ea0f4Smrg case 32: 1641301ea0f4Smrg Base *= 4; 1642301ea0f4Smrg break; 1643301ea0f4Smrg } 1644301ea0f4Smrg 1645301ea0f4Smrg hwp->writeCrtc(hwp, START_ADDR_LO, Base&0xFF); 1646301ea0f4Smrg hwp->writeCrtc(hwp, START_ADDR_HI, (Base&0xFF00)>>8); 1647301ea0f4Smrg hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base&0x3FC00000)>>22); 1648301ea0f4Smrg hwp->writeCrtc(hwp, EXT_START_ADDR, 1649301ea0f4Smrg ((Base&0x00eF0000)>>16|EXT_START_ADDR_ENABLE)); 1650301ea0f4Smrg} 1651301ea0f4Smrg 1652301ea0f4Smrgstatic Bool 1653301ea0f4SmrgI740EnterVT(int scrnIndex, int flags) { 1654301ea0f4Smrg ScrnInfoPtr pScrn; 1655301ea0f4Smrg 1656301ea0f4Smrg pScrn = xf86Screens[scrnIndex]; 1657301ea0f4Smrg if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE; 1658301ea0f4Smrg I740AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1659301ea0f4Smrg return TRUE; 1660301ea0f4Smrg} 1661301ea0f4Smrg 1662301ea0f4Smrgstatic void 1663301ea0f4SmrgI740LeaveVT(int scrnIndex, int flags) { 1664301ea0f4Smrg ScrnInfoPtr pScrn; 1665301ea0f4Smrg vgaHWPtr hwp; 1666301ea0f4Smrg 1667301ea0f4Smrg pScrn = xf86Screens[scrnIndex]; 1668301ea0f4Smrg hwp=VGAHWPTR(pScrn); 1669301ea0f4Smrg I740Restore(pScrn); 1670301ea0f4Smrg vgaHWLock(hwp); 1671301ea0f4Smrg} 1672301ea0f4Smrg 1673301ea0f4Smrgstatic Bool 1674301ea0f4SmrgI740CloseScreen(int scrnIndex, ScreenPtr pScreen) 1675301ea0f4Smrg{ 1676301ea0f4Smrg ScrnInfoPtr pScrn; 1677301ea0f4Smrg vgaHWPtr hwp; 1678301ea0f4Smrg I740Ptr pI740; 1679301ea0f4Smrg 1680301ea0f4Smrg pScrn = xf86Screens[scrnIndex]; 1681301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1682301ea0f4Smrg pI740 = I740PTR(pScrn); 1683301ea0f4Smrg 1684301ea0f4Smrg if (pScrn->vtSema) { 1685301ea0f4Smrg I740Restore(pScrn); 1686301ea0f4Smrg vgaHWLock(hwp); 1687301ea0f4Smrg } 1688301ea0f4Smrg 1689301ea0f4Smrg I740UnmapMem(pScrn); 1690301ea0f4Smrg vgaHWUnmapMem(pScrn); 1691301ea0f4Smrg if (pI740->AccelInfoRec) 1692301ea0f4Smrg XAADestroyInfoRec(pI740->AccelInfoRec); 1693301ea0f4Smrg pI740->AccelInfoRec=0; 1694301ea0f4Smrg if (pI740->CursorInfoRec) 1695301ea0f4Smrg xf86DestroyCursorInfoRec(pI740->CursorInfoRec); 1696301ea0f4Smrg pI740->CursorInfoRec=0; 1697301ea0f4Smrg pScrn->vtSema=FALSE; 1698301ea0f4Smrg 1699301ea0f4Smrg pScreen->CloseScreen = pI740->CloseScreen; 1700301ea0f4Smrg return (*pScreen->CloseScreen)(scrnIndex, pScreen); 1701301ea0f4Smrg} 1702301ea0f4Smrg 1703301ea0f4Smrgstatic void 1704301ea0f4SmrgI740FreeScreen(int scrnIndex, int flags) { 1705301ea0f4Smrg I740FreeRec(xf86Screens[scrnIndex]); 1706301ea0f4Smrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1707301ea0f4Smrg vgaHWFreeHWRec(xf86Screens[scrnIndex]); 1708301ea0f4Smrg} 1709301ea0f4Smrg 1710301ea0f4Smrgstatic ModeStatus 1711301ea0f4SmrgI740ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { 1712301ea0f4Smrg if (mode->Flags & V_INTERLACE) { 1713301ea0f4Smrg if (verbose) { 1714301ea0f4Smrg xf86DrvMsg(scrnIndex, X_PROBED, 1715301ea0f4Smrg "Removing interlaced mode \"%s\"\n", 1716301ea0f4Smrg mode->name); 1717301ea0f4Smrg } 1718301ea0f4Smrg return MODE_BAD; 1719301ea0f4Smrg } 1720301ea0f4Smrg return MODE_OK; 1721301ea0f4Smrg} 1722301ea0f4Smrg 1723301ea0f4Smrgstatic Bool 1724301ea0f4SmrgI740SaveScreen(ScreenPtr pScreen, int mode) 1725301ea0f4Smrg{ 1726301ea0f4Smrg#if 0 1727301ea0f4Smrg Bool unblack = xf86IsUnblank(mode); 1728301ea0f4Smrg if (unblack) outw(SRX, 0x0300); 1729301ea0f4Smrg else outw(SRX, 0x0100); 1730301ea0f4Smrg#endif 1731301ea0f4Smrg return vgaHWSaveScreen(pScreen, mode); 1732301ea0f4Smrg} 1733301ea0f4Smrg 1734301ea0f4Smrgstatic void 1735301ea0f4SmrgI740DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 1736301ea0f4Smrg int flags) { 1737301ea0f4Smrg I740Ptr pI740; 1738301ea0f4Smrg unsigned char SEQ01=0; 1739301ea0f4Smrg int DPMSSyncSelect=0; 1740301ea0f4Smrg 1741301ea0f4Smrg pI740 = I740PTR(pScrn); 1742301ea0f4Smrg switch (PowerManagementMode) { 1743301ea0f4Smrg case DPMSModeOn: 1744301ea0f4Smrg /* Screen: On; HSync: On, VSync: On */ 1745301ea0f4Smrg SEQ01 = 0x00; 1746301ea0f4Smrg DPMSSyncSelect = HSYNC_ON | VSYNC_ON; 1747301ea0f4Smrg break; 1748301ea0f4Smrg case DPMSModeStandby: 1749301ea0f4Smrg /* Screen: Off; HSync: Off, VSync: On */ 1750301ea0f4Smrg SEQ01 = 0x20; 1751301ea0f4Smrg DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; 1752301ea0f4Smrg break; 1753301ea0f4Smrg case DPMSModeSuspend: 1754301ea0f4Smrg /* Screen: Off; HSync: On, VSync: Off */ 1755301ea0f4Smrg SEQ01 = 0x20; 1756301ea0f4Smrg DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; 1757301ea0f4Smrg break; 1758301ea0f4Smrg case DPMSModeOff: 1759301ea0f4Smrg /* Screen: Off; HSync: Off, VSync: Off */ 1760301ea0f4Smrg SEQ01 = 0x20; 1761301ea0f4Smrg DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; 1762301ea0f4Smrg break; 1763301ea0f4Smrg } 1764301ea0f4Smrg 1765301ea0f4Smrg /* Turn the screen on/off */ 1766301ea0f4Smrg SEQ01 |= pI740->readControl(pI740, SRX, 0x01) & ~0x20; 1767301ea0f4Smrg pI740->writeControl(pI740, SRX, 0x01, SEQ01); 1768301ea0f4Smrg 1769301ea0f4Smrg /* Set the DPMS mode */ 1770301ea0f4Smrg pI740->writeControl(pI740, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect); 1771301ea0f4Smrg} 1772