i740_driver.c revision 8280d184
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> 415c69f917Smrg#include <unistd.h> 42301ea0f4Smrg 43301ea0f4Smrg/* 44301ea0f4Smrg * This server does not support these XFree86 4.0 features yet 45301ea0f4Smrg * DDC1 & DDC2 (requires I2C) 46301ea0f4Smrg * shadowFb (if requested or acceleration is off) 47301ea0f4Smrg * Overlay planes 48301ea0f4Smrg * DGA 49301ea0f4Smrg */ 50301ea0f4Smrg 51301ea0f4Smrg/* 52301ea0f4Smrg * These are X and server generic header files. 53301ea0f4Smrg */ 54301ea0f4Smrg#include "xf86.h" 55301ea0f4Smrg#include "xf86_OSproc.h" 56ef6fb4a5Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 57301ea0f4Smrg#include "xf86Resources.h" 58301ea0f4Smrg#include "xf86RAC.h" 59ef6fb4a5Smrg#endif 60301ea0f4Smrg#include "xf86cmap.h" 61301ea0f4Smrg 62301ea0f4Smrg/* If the driver uses port I/O directly, it needs: */ 63301ea0f4Smrg 64301ea0f4Smrg#include "compiler.h" 65301ea0f4Smrg 66301ea0f4Smrg/* All drivers using the vgahw module need this */ 67301ea0f4Smrg/* This driver needs to be modified to not use vgaHW for multihead operation */ 68301ea0f4Smrg#include "vgaHW.h" 69301ea0f4Smrg 70301ea0f4Smrg/* Drivers using the mi SW cursor need: */ 71301ea0f4Smrg 72301ea0f4Smrg#include "mipointer.h" 73301ea0f4Smrg 74301ea0f4Smrg/* Drivers using the mi colourmap code need: */ 75301ea0f4Smrg 76301ea0f4Smrg#include "micmap.h" 77301ea0f4Smrg 78301ea0f4Smrg#include "fb.h" 79301ea0f4Smrg 80301ea0f4Smrg/* The driver's own header file: */ 81301ea0f4Smrg 82301ea0f4Smrg 83301ea0f4Smrg#include "regionstr.h" 84301ea0f4Smrg 85301ea0f4Smrg#include "xf86xv.h" 86301ea0f4Smrg#include <X11/extensions/Xv.h> 87301ea0f4Smrg 88301ea0f4Smrg#include "vbe.h" 89301ea0f4Smrg#include "i740_dga.h" 90301ea0f4Smrg#include "i740.h" 91301ea0f4Smrg 92301ea0f4Smrg 93301ea0f4Smrg/* Required Functions: */ 94301ea0f4Smrgstatic const OptionInfoRec * I740AvailableOptions(int chipid, int busid); 95301ea0f4Smrg 96301ea0f4Smrg/* Print a driver identifying message. */ 97301ea0f4Smrgstatic void I740Identify(int flags); 98301ea0f4Smrg 99301ea0f4Smrg/* Identify if there is any hardware present that I know how to drive. */ 100301ea0f4Smrgstatic Bool I740Probe(DriverPtr drv, int flags); 101301ea0f4Smrg 102301ea0f4Smrg/* Process the config file and see if we have a valid configuration */ 103301ea0f4Smrgstatic Bool I740PreInit(ScrnInfoPtr pScrn, int flags); 104301ea0f4Smrg 105301ea0f4Smrg/* Initialize a screen */ 1065c69f917Smrgstatic Bool I740ScreenInit(SCREEN_INIT_ARGS_DECL); 107301ea0f4Smrg 108301ea0f4Smrg/* Enter from a virtual terminal */ 1095c69f917Smrgstatic Bool I740EnterVT(VT_FUNC_ARGS_DECL); 110301ea0f4Smrg 111301ea0f4Smrg/* Leave to a virtual terminal */ 1125c69f917Smrgstatic void I740LeaveVT(VT_FUNC_ARGS_DECL); 113301ea0f4Smrg 114301ea0f4Smrg/* Close down each screen we initialized */ 1155c69f917Smrgstatic Bool I740CloseScreen(CLOSE_SCREEN_ARGS_DECL); 116301ea0f4Smrg 117301ea0f4Smrg/* Change screensaver state */ 118301ea0f4Smrgstatic Bool I740SaveScreen(ScreenPtr pScreen, int mode); 119301ea0f4Smrg 120301ea0f4Smrg/* Cleanup server private data */ 1215c69f917Smrgstatic void I740FreeScreen(FREE_SCREEN_ARGS_DECL); 122301ea0f4Smrg 123301ea0f4Smrg/* Check if a mode is valid on the hardware */ 1245c69f917Smrgstatic ModeStatus I740ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 125301ea0f4Smrg Bool verbose, int flags); 126301ea0f4Smrg 127301ea0f4Smrg/* Switch to various Display Power Management System levels */ 128301ea0f4Smrgstatic void I740DisplayPowerManagementSet(ScrnInfoPtr pScrn, 129301ea0f4Smrg int PowerManagermentMode, int flags); 130301ea0f4Smrg 131301ea0f4Smrgstatic void I740ProbeDDC(ScrnInfoPtr pScrn, int index); 132301ea0f4Smrg 133301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn); 134301ea0f4Smrgstatic Bool I740UnmapMem(ScrnInfoPtr pScrn); 135301ea0f4Smrg 136301ea0f4Smrg#define I740_VERSION 4000 137301ea0f4Smrg#define I740_NAME "I740" 138301ea0f4Smrg#define I740_DRIVER_NAME "i740" 1390cc67336Smrg#define I740_MAJOR_VERSION PACKAGE_VERSION_MAJOR 1400cc67336Smrg#define I740_MINOR_VERSION PACKAGE_VERSION_MINOR 1410cc67336Smrg#define I740_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 142301ea0f4Smrg 143301ea0f4Smrg_X_EXPORT DriverRec I740 = { 144301ea0f4Smrg I740_VERSION, 145301ea0f4Smrg I740_DRIVER_NAME, 146301ea0f4Smrg I740Identify, 147301ea0f4Smrg I740Probe, 148301ea0f4Smrg I740AvailableOptions, 149301ea0f4Smrg NULL, 150301ea0f4Smrg 0 151301ea0f4Smrg}; 152301ea0f4Smrg 153301ea0f4Smrg/* Chipsets */ 154301ea0f4Smrgstatic SymTabRec I740Chipsets[] = { 155301ea0f4Smrg { PCI_CHIP_I740_AGP, "i740 (agp)"}, 156301ea0f4Smrg { PCI_CHIP_I740_PCI, "i740 (pci)"}, 157301ea0f4Smrg { -1, NULL } 158301ea0f4Smrg}; 159301ea0f4Smrg 160301ea0f4Smrgstatic PciChipsets I740PciChipsets[] = { 161301ea0f4Smrg { PCI_CHIP_I740_AGP, PCI_CHIP_I740_AGP, RES_SHARED_VGA }, 162301ea0f4Smrg { PCI_CHIP_I740_PCI, PCI_CHIP_I740_PCI, RES_SHARED_VGA }, 163301ea0f4Smrg { -1, -1, RES_UNDEFINED } 164301ea0f4Smrg}; 165301ea0f4Smrg 166301ea0f4Smrgtypedef enum { 167301ea0f4Smrg OPTION_NOACCEL, 168301ea0f4Smrg OPTION_SW_CURSOR, 169301ea0f4Smrg OPTION_SDRAM, 170301ea0f4Smrg OPTION_SGRAM, 171301ea0f4Smrg OPTION_SLOW_RAM, 172301ea0f4Smrg OPTION_DAC_6BIT, 173301ea0f4Smrg OPTION_USE_PIO, 174301ea0f4Smrg OPTION_VGACOMPAT 175301ea0f4Smrg} I740Opts; 176301ea0f4Smrg 177301ea0f4Smrgstatic const OptionInfoRec I740Options[] = { 178301ea0f4Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 179301ea0f4Smrg { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 180301ea0f4Smrg { OPTION_SDRAM, "SDRAM", OPTV_BOOLEAN, {0}, FALSE}, 181301ea0f4Smrg { OPTION_SGRAM, "SGRAM", OPTV_BOOLEAN, {0}, FALSE}, 182301ea0f4Smrg { OPTION_SLOW_RAM, "SlowRam", OPTV_BOOLEAN, {0}, FALSE}, 183301ea0f4Smrg { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, 184301ea0f4Smrg { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE}, 185301ea0f4Smrg { OPTION_VGACOMPAT, "VGACompat", OPTV_BOOLEAN, {0}, FALSE}, 186301ea0f4Smrg { -1, NULL, OPTV_NONE, {0}, FALSE} 187301ea0f4Smrg}; 188301ea0f4Smrg 189301ea0f4Smrg#ifdef XFree86LOADER 190301ea0f4Smrg 191301ea0f4Smrgstatic MODULESETUPPROTO(i740Setup); 192301ea0f4Smrg 193301ea0f4Smrgstatic XF86ModuleVersionInfo i740VersRec = 194301ea0f4Smrg{ 195301ea0f4Smrg "i740", 196301ea0f4Smrg MODULEVENDORSTRING, 197301ea0f4Smrg MODINFOSTRING1, 198301ea0f4Smrg MODINFOSTRING2, 199301ea0f4Smrg XORG_VERSION_CURRENT, 200301ea0f4Smrg I740_MAJOR_VERSION, I740_MINOR_VERSION, I740_PATCHLEVEL, 201301ea0f4Smrg ABI_CLASS_VIDEODRV, 202301ea0f4Smrg ABI_VIDEODRV_VERSION, 203301ea0f4Smrg MOD_CLASS_VIDEODRV, 204301ea0f4Smrg {0,0,0,0} 205301ea0f4Smrg}; 206301ea0f4Smrg 207301ea0f4Smrg_X_EXPORT XF86ModuleData i740ModuleData = {&i740VersRec, i740Setup, 0}; 208301ea0f4Smrg 209301ea0f4Smrgstatic pointer 210301ea0f4Smrgi740Setup(pointer module, pointer opts, int *errmaj, int *errmin) 211301ea0f4Smrg{ 212301ea0f4Smrg static Bool setupDone = FALSE; 213301ea0f4Smrg 214301ea0f4Smrg /* This module should be loaded only once, but check to be sure. */ 215301ea0f4Smrg 216301ea0f4Smrg if (!setupDone) { 217301ea0f4Smrg setupDone = TRUE; 218301ea0f4Smrg xf86AddDriver(&I740, module, 0); 219301ea0f4Smrg 220301ea0f4Smrg /* 221301ea0f4Smrg * Modules that this driver always requires may be loaded here 222301ea0f4Smrg * by calling LoadSubModule(). 223301ea0f4Smrg */ 224301ea0f4Smrg 225301ea0f4Smrg /* 226301ea0f4Smrg * The return value must be non-NULL on success even though there 227301ea0f4Smrg * is no TearDownProc. 228301ea0f4Smrg */ 229301ea0f4Smrg return (pointer)1; 230301ea0f4Smrg } else { 231301ea0f4Smrg if (errmaj) *errmaj = LDR_ONCEONLY; 232301ea0f4Smrg return NULL; 233301ea0f4Smrg } 234301ea0f4Smrg} 235301ea0f4Smrg 236301ea0f4Smrg#endif 237301ea0f4Smrg 238301ea0f4Smrg/* 239301ea0f4Smrg * I740GetRec and I740FreeRec -- 240301ea0f4Smrg * 241301ea0f4Smrg * Private data for the driver is stored in the screen structure. 242301ea0f4Smrg * These two functions create and destroy that private data. 243301ea0f4Smrg * 244301ea0f4Smrg */ 245301ea0f4Smrgstatic Bool 246301ea0f4SmrgI740GetRec(ScrnInfoPtr pScrn) { 247301ea0f4Smrg if (pScrn->driverPrivate) return TRUE; 248301ea0f4Smrg 249301ea0f4Smrg pScrn->driverPrivate = xnfcalloc(sizeof(I740Rec), 1); 250301ea0f4Smrg return TRUE; 251301ea0f4Smrg} 252301ea0f4Smrg 253301ea0f4Smrgstatic void 254301ea0f4SmrgI740FreeRec(ScrnInfoPtr pScrn) { 255301ea0f4Smrg if (!pScrn) return; 2565c69f917Smrg free(pScrn->driverPrivate); 257301ea0f4Smrg pScrn->driverPrivate=0; 258301ea0f4Smrg} 259301ea0f4Smrg 260301ea0f4Smrgstatic const OptionInfoRec * 261301ea0f4SmrgI740AvailableOptions(int chipid, int busid) 262301ea0f4Smrg{ 263301ea0f4Smrg return I740Options; 264301ea0f4Smrg} 265301ea0f4Smrg 266301ea0f4Smrg/* 267301ea0f4Smrg * I740Identify -- 268301ea0f4Smrg * 269301ea0f4Smrg * Returns the string name for the driver based on the chipset. In this 270301ea0f4Smrg * case it will always be an I740, so we can return a static string. 271301ea0f4Smrg * 272301ea0f4Smrg */ 273301ea0f4Smrgstatic void 274301ea0f4SmrgI740Identify(int flags) { 275301ea0f4Smrg xf86PrintChipsets(I740_NAME, "Driver for Intel i740 chipset", I740Chipsets); 276301ea0f4Smrg} 277301ea0f4Smrg 278301ea0f4Smrg/* 279301ea0f4Smrg * I740Probe -- 280301ea0f4Smrg * 281301ea0f4Smrg * Look through the PCI bus to find cards that are I740 boards. 282301ea0f4Smrg * Setup the dispatch table for the rest of the driver functions. 283301ea0f4Smrg * 284301ea0f4Smrg */ 285301ea0f4Smrgstatic Bool 286301ea0f4SmrgI740Probe(DriverPtr drv, int flags) { 287301ea0f4Smrg int i, numUsed, numDevSections, *usedChips; 288301ea0f4Smrg GDevPtr *devSections; 289301ea0f4Smrg Bool foundScreen = FALSE; 290301ea0f4Smrg 291301ea0f4Smrg /* 292301ea0f4Smrg Find the config file Device sections that match this 293301ea0f4Smrg driver, and return if there are none. 294301ea0f4Smrg */ 295301ea0f4Smrg if ((numDevSections = xf86MatchDevice(I740_DRIVER_NAME, &devSections))<=0) { 296301ea0f4Smrg return FALSE; 297301ea0f4Smrg } 298301ea0f4Smrg 2990cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 300301ea0f4Smrg /* 301301ea0f4Smrg Since these Probing is just checking the PCI data the server already 302301ea0f4Smrg collected. 303301ea0f4Smrg */ 304301ea0f4Smrg if (!xf86GetPciVideoInfo()) return FALSE; 3050cc67336Smrg#endif 306301ea0f4Smrg 307301ea0f4Smrg /* Look for Intel based chips */ 308301ea0f4Smrg numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_INTEL, 309301ea0f4Smrg I740Chipsets, I740PciChipsets, 310301ea0f4Smrg devSections, numDevSections, 311301ea0f4Smrg drv, &usedChips); 312301ea0f4Smrg 313301ea0f4Smrg if (numUsed > 0) { 314301ea0f4Smrg if (flags & PROBE_DETECT) 315301ea0f4Smrg foundScreen = TRUE; 316301ea0f4Smrg else for (i=0; i<numUsed; i++) { 317301ea0f4Smrg ScrnInfoPtr pScrn = NULL; 318301ea0f4Smrg /* Allocate new ScrnInfoRec and claim the slot */ 319301ea0f4Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 320301ea0f4Smrg I740PciChipsets, 0, 0, 0, 0, 0))) { 321301ea0f4Smrg pScrn->driverVersion = I740_VERSION; 322301ea0f4Smrg pScrn->driverName = I740_DRIVER_NAME; 323301ea0f4Smrg pScrn->name = I740_NAME; 324301ea0f4Smrg pScrn->Probe = I740Probe; 325301ea0f4Smrg pScrn->PreInit = I740PreInit; 326301ea0f4Smrg pScrn->ScreenInit = I740ScreenInit; 327301ea0f4Smrg pScrn->SwitchMode = I740SwitchMode; 328301ea0f4Smrg pScrn->AdjustFrame = I740AdjustFrame; 329301ea0f4Smrg pScrn->EnterVT = I740EnterVT; 330301ea0f4Smrg pScrn->LeaveVT = I740LeaveVT; 331301ea0f4Smrg pScrn->FreeScreen = I740FreeScreen; 332301ea0f4Smrg pScrn->ValidMode = I740ValidMode; 333301ea0f4Smrg foundScreen = TRUE; 334301ea0f4Smrg 335301ea0f4Smrg } 336301ea0f4Smrg } 337301ea0f4Smrg } 338301ea0f4Smrg 339301ea0f4Smrg 340301ea0f4Smrg /* Look for Real3D based chips */ 341301ea0f4Smrg numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_REAL3D, 342301ea0f4Smrg I740Chipsets, I740PciChipsets, 343301ea0f4Smrg devSections, numDevSections, 344301ea0f4Smrg drv, &usedChips); 345301ea0f4Smrg 346301ea0f4Smrg if (numUsed > 0) { 347301ea0f4Smrg if (flags & PROBE_DETECT) 348301ea0f4Smrg foundScreen = TRUE; 349301ea0f4Smrg else for (i=0; i<numUsed; i++) { 350301ea0f4Smrg ScrnInfoPtr pScrn = NULL; 351301ea0f4Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 352301ea0f4Smrg I740PciChipsets, 0, 0, 0, 0, 0))) { 353301ea0f4Smrg pScrn->driverVersion = I740_VERSION; 354301ea0f4Smrg pScrn->driverName = I740_DRIVER_NAME; 355301ea0f4Smrg pScrn->name = I740_NAME; 356301ea0f4Smrg pScrn->Probe = I740Probe; 357301ea0f4Smrg pScrn->PreInit = I740PreInit; 358301ea0f4Smrg pScrn->ScreenInit = I740ScreenInit; 359301ea0f4Smrg pScrn->SwitchMode = I740SwitchMode; 360301ea0f4Smrg pScrn->AdjustFrame = I740AdjustFrame; 361301ea0f4Smrg pScrn->EnterVT = I740EnterVT; 362301ea0f4Smrg pScrn->LeaveVT = I740LeaveVT; 363301ea0f4Smrg pScrn->FreeScreen = I740FreeScreen; 364301ea0f4Smrg pScrn->ValidMode = I740ValidMode; 365301ea0f4Smrg foundScreen = TRUE; 366301ea0f4Smrg } 367301ea0f4Smrg } 368301ea0f4Smrg } 369301ea0f4Smrg 3705c69f917Smrg free(devSections); 3715c69f917Smrg free(usedChips); 372301ea0f4Smrg 373301ea0f4Smrg return foundScreen; 374301ea0f4Smrg} 375301ea0f4Smrg 3760cc67336Smrg/* Ugh. Can we not do this? */ 377301ea0f4Smrgstatic void 378301ea0f4SmrgI740ProbeDDC(ScrnInfoPtr pScrn, int index) 379301ea0f4Smrg{ 380301ea0f4Smrg vbeInfoPtr pVbe; 381301ea0f4Smrg if (xf86LoadSubModule(pScrn, "vbe")) { 382301ea0f4Smrg pVbe = VBEInit(NULL,index); 383301ea0f4Smrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 384301ea0f4Smrg vbeFree(pVbe); 385301ea0f4Smrg } 386301ea0f4Smrg} 387301ea0f4Smrg 388301ea0f4Smrg/* 389301ea0f4Smrg * I740PreInit -- 390301ea0f4Smrg * 391301ea0f4Smrg * Do initial setup of the board before we know what resolution we will 392301ea0f4Smrg * be running at. 393301ea0f4Smrg * 394301ea0f4Smrg */ 395301ea0f4Smrgstatic Bool 396301ea0f4SmrgI740PreInit(ScrnInfoPtr pScrn, int flags) { 397301ea0f4Smrg I740Ptr pI740; 398301ea0f4Smrg ClockRangePtr clockRanges; 399301ea0f4Smrg int i; 400301ea0f4Smrg MessageType from; 401301ea0f4Smrg int temp; 402301ea0f4Smrg int flags24; 403301ea0f4Smrg rgb defaultWeight = {0, 0, 0}; 404301ea0f4Smrg 405301ea0f4Smrg if (pScrn->numEntities != 1) return FALSE; 406301ea0f4Smrg 407301ea0f4Smrg /* Allocate driverPrivate */ 408301ea0f4Smrg if (!I740GetRec(pScrn)) { 409301ea0f4Smrg return FALSE; 410301ea0f4Smrg } 411301ea0f4Smrg 412301ea0f4Smrg pI740 = I740PTR(pScrn); 413301ea0f4Smrg 414301ea0f4Smrg pI740->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 415301ea0f4Smrg if (pI740->pEnt->location.type != BUS_PCI) return FALSE; 416301ea0f4Smrg 417301ea0f4Smrg /*I740ProbeDDC(pScrn, pI740->pEnt->index);*/ 418301ea0f4Smrg if (flags & PROBE_DETECT) { 419301ea0f4Smrg I740ProbeDDC(pScrn, pI740->pEnt->index); 420301ea0f4Smrg return TRUE; 421301ea0f4Smrg } 422301ea0f4Smrg 423301ea0f4Smrg /* The vgahw module should be loaded here when needed */ 424301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE; 425301ea0f4Smrg 426301ea0f4Smrg /* Allocate a vgaHWRec */ 427301ea0f4Smrg if (!vgaHWGetHWRec(pScrn)) return FALSE; 4285c69f917Smrg vgaHWSetStdFuncs(VGAHWPTR(pScrn)); 429301ea0f4Smrg 430301ea0f4Smrg pI740->PciInfo = xf86GetPciInfoForEntity(pI740->pEnt->index); 4310cc67336Smrg#ifndef XSERVER_LIBPCIACCESS 432301ea0f4Smrg pI740->PciTag = pciTag(pI740->PciInfo->bus, pI740->PciInfo->device, 433301ea0f4Smrg pI740->PciInfo->func); 434301ea0f4Smrg 435301ea0f4Smrg if (xf86RegisterResources(pI740->pEnt->index, 0, ResNone)) 436301ea0f4Smrg return FALSE; 437301ea0f4Smrg if (pI740->usePIO) 438301ea0f4Smrg pScrn->racIoFlags = RAC_FB | RAC_COLORMAP; 439301ea0f4Smrg else 440301ea0f4Smrg pScrn->racMemFlags = RAC_FB | RAC_COLORMAP; 441ef6fb4a5Smrg#endif 442301ea0f4Smrg /* Set pScrn->monitor */ 443301ea0f4Smrg pScrn->monitor = pScrn->confScreen->monitor; 444301ea0f4Smrg 445301ea0f4Smrg 446301ea0f4Smrg flags24=Support24bppFb | Support32bppFb | SupportConvert32to24; 447301ea0f4Smrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) { 448301ea0f4Smrg return FALSE; 449301ea0f4Smrg } else { 450301ea0f4Smrg switch (pScrn->depth) { 451301ea0f4Smrg case 8: 452301ea0f4Smrg case 15: 453301ea0f4Smrg case 16: 454301ea0f4Smrg case 24: 455301ea0f4Smrg break; 456301ea0f4Smrg default: 457301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 458301ea0f4Smrg "Given depth (%d) is not supported by i740 driver\n", 459301ea0f4Smrg pScrn->depth); 460301ea0f4Smrg return FALSE; 461301ea0f4Smrg } 462301ea0f4Smrg } 463301ea0f4Smrg /*xf86PrintDepthBpp(pScrn);*/ 464301ea0f4Smrg 465301ea0f4Smrg if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 466301ea0f4Smrg return FALSE; 467301ea0f4Smrg 468301ea0f4Smrg if (!xf86SetDefaultVisual(pScrn, -1)) { 469301ea0f4Smrg return FALSE; 470301ea0f4Smrg } else { 471301ea0f4Smrg /* We don't currently support DirectColor at > 8bpp */ 472301ea0f4Smrg if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 473301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 474301ea0f4Smrg " (%s) is not supported at depth %d\n", 475301ea0f4Smrg xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 476301ea0f4Smrg return FALSE; 477301ea0f4Smrg } 478301ea0f4Smrg } 479301ea0f4Smrg 480301ea0f4Smrg /* We use a programamble clock */ 481301ea0f4Smrg pScrn->progClock = TRUE; 482301ea0f4Smrg 483301ea0f4Smrg pI740->cpp = pScrn->bitsPerPixel/8; 484301ea0f4Smrg 485301ea0f4Smrg /* Process the options */ 486301ea0f4Smrg xf86CollectOptions(pScrn, NULL); 4875c69f917Smrg if (!(pI740->Options = malloc(sizeof(I740Options)))) 488301ea0f4Smrg return FALSE; 489301ea0f4Smrg memcpy(pI740->Options, I740Options, sizeof(I740Options)); 490301ea0f4Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI740->Options); 491301ea0f4Smrg 492301ea0f4Smrg /* 6-BIT dac isn't reasonable for modes with > 8bpp */ 493301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE) && 494301ea0f4Smrg pScrn->bitsPerPixel>8) { 495301ea0f4Smrg OptionInfoPtr ptr; 496301ea0f4Smrg ptr=xf86TokenToOptinfo(pI740->Options, OPTION_DAC_6BIT); 497301ea0f4Smrg ptr->found=FALSE; 498301ea0f4Smrg } 499301ea0f4Smrg 500301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE)) 501301ea0f4Smrg pScrn->rgbBits=8; 502301ea0f4Smrg else 503301ea0f4Smrg pScrn->rgbBits=6; 504301ea0f4Smrg 505301ea0f4Smrg /* We have to use PIO to probe, because we haven't mappend yet */ 506301ea0f4Smrg I740SetPIOAccess(pI740); 507301ea0f4Smrg 508301ea0f4Smrg /* 509301ea0f4Smrg * Set the Chipset and ChipRev, allowing config file entries to 510301ea0f4Smrg * override. 511301ea0f4Smrg */ 512301ea0f4Smrg if (pI740->pEnt->device->chipset && *pI740->pEnt->device->chipset) { 513301ea0f4Smrg pScrn->chipset = pI740->pEnt->device->chipset; 514301ea0f4Smrg from = X_CONFIG; 515301ea0f4Smrg } else if (pI740->pEnt->device->chipID >= 0) { 516301ea0f4Smrg pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->pEnt->device->chipID); 517301ea0f4Smrg from = X_CONFIG; 518301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 519301ea0f4Smrg pI740->pEnt->device->chipID); 520301ea0f4Smrg } else { 521301ea0f4Smrg from = X_PROBED; 5220cc67336Smrg pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, PCI_DEV_DEVICE_ID(pI740->PciInfo)); 523301ea0f4Smrg } 524301ea0f4Smrg if (pI740->pEnt->device->chipRev >= 0) { 525301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 526301ea0f4Smrg pI740->pEnt->device->chipRev); 527301ea0f4Smrg } 528301ea0f4Smrg 529301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset!=NULL)?pScrn->chipset:"Unknown i740"); 530301ea0f4Smrg 531301ea0f4Smrg if (pI740->pEnt->device->MemBase != 0) { 532301ea0f4Smrg pI740->LinearAddr = pI740->pEnt->device->MemBase; 533301ea0f4Smrg from = X_CONFIG; 534301ea0f4Smrg } else { 5350cc67336Smrg if (PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM) != 0) { 5360cc67336Smrg pI740->LinearAddr = PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM)&0xFF000000; 537301ea0f4Smrg from = X_PROBED; 538301ea0f4Smrg } else { 539301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 540301ea0f4Smrg "No valid FB address in PCI config space\n"); 541301ea0f4Smrg I740FreeRec(pScrn); 542301ea0f4Smrg return FALSE; 543301ea0f4Smrg } 544301ea0f4Smrg } 545301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 546301ea0f4Smrg pI740->LinearAddr); 547301ea0f4Smrg 548301ea0f4Smrg if (pI740->pEnt->device->IOBase != 0) { 549301ea0f4Smrg pI740->MMIOAddr = pI740->pEnt->device->IOBase; 550301ea0f4Smrg from = X_CONFIG; 551301ea0f4Smrg } else { 5520cc67336Smrg if (PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)) { 5530cc67336Smrg pI740->MMIOAddr = PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)&0xFFF80000; 554301ea0f4Smrg from = X_PROBED; 555301ea0f4Smrg } else { 556301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 557301ea0f4Smrg "No valid MMIO address in PCI config space\n"); 558301ea0f4Smrg I740FreeRec(pScrn); 559301ea0f4Smrg return FALSE; 560301ea0f4Smrg } 561301ea0f4Smrg } 562301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", 563301ea0f4Smrg pI740->MMIOAddr); 564301ea0f4Smrg 565301ea0f4Smrg /* Calculate memory */ 566301ea0f4Smrg if (pI740->pEnt->device->videoRam) { 567301ea0f4Smrg pScrn->videoRam = pI740->pEnt->device->videoRam; 568301ea0f4Smrg from = X_CONFIG; 569301ea0f4Smrg } else { 570301ea0f4Smrg if ((pI740->readControl(pI740, XRX, DRAM_ROW_TYPE)&DRAM_ROW_1)==DRAM_ROW_1_SDRAM) 571301ea0f4Smrg pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_1); 572301ea0f4Smrg else 573301ea0f4Smrg pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_0); 574301ea0f4Smrg pScrn->videoRam = (pScrn->videoRam&0x0F)*1024; 575301ea0f4Smrg from = X_PROBED; 576301ea0f4Smrg } 577301ea0f4Smrg 578301ea0f4Smrg temp=pI740->readControl(pI740, XRX, DRAM_ROW_CNTL_LO); 579301ea0f4Smrg pI740->HasSGRAM = !((temp&DRAM_RAS_TIMING)||(temp&DRAM_RAS_PRECHARGE)); 580301ea0f4Smrg if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) { 581301ea0f4Smrg if (xf86IsOptionSet(pI740->Options, OPTION_SGRAM)) { 582301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 583301ea0f4Smrg "It is nonsensical to set both SDRAM and SGRAM options\n"); 584301ea0f4Smrg return FALSE; 585301ea0f4Smrg } 586301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_SDRAM, FALSE)) { 587301ea0f4Smrg pI740->HasSGRAM = FALSE; 588301ea0f4Smrg } else { 589301ea0f4Smrg pI740->HasSGRAM = TRUE; 590301ea0f4Smrg } 591301ea0f4Smrg } else { 592301ea0f4Smrg if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) { 593301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 594301ea0f4Smrg "It is nonsensical to set both SDRAM and SGRAM options\n"); 595301ea0f4Smrg return FALSE; 596301ea0f4Smrg } 597301ea0f4Smrg if (xf86ReturnOptValBool(pI740->Options, OPTION_SGRAM, FALSE)) { 598301ea0f4Smrg pI740->HasSGRAM = TRUE; 599301ea0f4Smrg } else { 600301ea0f4Smrg pI740->HasSGRAM = FALSE; 601301ea0f4Smrg } 602301ea0f4Smrg } 603301ea0f4Smrg 604301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, from, "Steve was here! VideoRAM: %d kByte %s\n", 605301ea0f4Smrg pScrn->videoRam, (pI740->HasSGRAM)?"SGRAM":"SDRAM"); 606301ea0f4Smrg pI740->FbMapSize = pScrn->videoRam*1024; 607301ea0f4Smrg 608301ea0f4Smrg /* 609301ea0f4Smrg * If the driver can do gamma correction, it should call xf86SetGamma() 610301ea0f4Smrg * here. 611301ea0f4Smrg */ 612301ea0f4Smrg 613301ea0f4Smrg { 614301ea0f4Smrg Gamma zeros = {0.0, 0.0, 0.0}; 615301ea0f4Smrg 616301ea0f4Smrg if (!xf86SetGamma(pScrn, zeros)) { 617301ea0f4Smrg return FALSE; 618301ea0f4Smrg } 619301ea0f4Smrg } 620301ea0f4Smrg 621301ea0f4Smrg pI740->MaxClock = 0; 622301ea0f4Smrg if (pI740->pEnt->device->dacSpeeds[0]) { 623301ea0f4Smrg switch (pScrn->bitsPerPixel) { 624301ea0f4Smrg case 8: 625301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP8]; 626301ea0f4Smrg break; 627301ea0f4Smrg case 16: 628301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP16]; 629301ea0f4Smrg break; 630301ea0f4Smrg case 24: 631301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP24]; 632301ea0f4Smrg break; 633301ea0f4Smrg case 32: 634301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP32]; 635301ea0f4Smrg break; 636301ea0f4Smrg } 637301ea0f4Smrg if (!pI740->MaxClock) 638301ea0f4Smrg pI740->MaxClock = pI740->pEnt->device->dacSpeeds[0]; 639301ea0f4Smrg from = X_CONFIG; 640301ea0f4Smrg } else { 641301ea0f4Smrg switch (pScrn->bitsPerPixel) { 642301ea0f4Smrg case 8: 643301ea0f4Smrg pI740->MaxClock = 203000; 644301ea0f4Smrg break; 645301ea0f4Smrg case 16: 646301ea0f4Smrg pI740->MaxClock = 163000; 647301ea0f4Smrg break; 648301ea0f4Smrg case 24: 649301ea0f4Smrg if (pI740->HasSGRAM) 650301ea0f4Smrg pI740->MaxClock = 136000; 651301ea0f4Smrg else 652301ea0f4Smrg pI740->MaxClock = 128000; 653301ea0f4Smrg break; 654301ea0f4Smrg case 32: 655301ea0f4Smrg pI740->MaxClock = 86000; 656301ea0f4Smrg } 657301ea0f4Smrg } 658301ea0f4Smrg clockRanges = xnfcalloc(sizeof(ClockRange), 1); 659301ea0f4Smrg clockRanges->next=NULL; 660301ea0f4Smrg clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */ 661301ea0f4Smrg clockRanges->maxClock=pI740->MaxClock; 662301ea0f4Smrg clockRanges->clockIndex = -1; 663301ea0f4Smrg clockRanges->interlaceAllowed = FALSE; /*PL*/ 664301ea0f4Smrg clockRanges->doubleScanAllowed = TRUE; /*PL*/ 665301ea0f4Smrg 6660cc67336Smrg { /*PL*/ 6670cc67336Smrg 6680cc67336Smrg if (xf86LoadSubModule(pScrn, "ddc")) { 6690cc67336Smrg if (xf86LoadSubModule(pScrn, "i2c") ) { 6700cc67336Smrg if (I740MapMem(pScrn)) { 6710cc67336Smrg if (I740_I2CInit(pScrn)) 6720cc67336Smrg { 6730cc67336Smrg xf86MonPtr MonInfo; 6745c69f917Smrg if ((MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),pI740->rc_i2c))) { 6750cc67336Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", 6760cc67336Smrg MonInfo); 6770cc67336Smrg xf86PrintEDID( MonInfo ); 6780cc67336Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor " 6790cc67336Smrg "info\n\n"); 6800cc67336Smrg xf86SetDDCproperties(pScrn,MonInfo); 6810cc67336Smrg } 6820cc67336Smrg } 6830cc67336Smrg else 6840cc67336Smrg xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n"); 6850cc67336Smrg 6860cc67336Smrg I740UnmapMem(pScrn); 6870cc67336Smrg } 6880cc67336Smrg } 6890cc67336Smrg } 6900cc67336Smrg } 6910cc67336Smrg 692301ea0f4Smrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 693301ea0f4Smrg pScrn->display->modes, clockRanges, 694301ea0f4Smrg 0, 320, 1600, 695301ea0f4Smrg 8, 200, 1200, 696301ea0f4Smrg pScrn->display->virtualX, pScrn->display->virtualY, 697301ea0f4Smrg pI740->FbMapSize, LOOKUP_BEST_REFRESH); 698301ea0f4Smrg 699301ea0f4Smrg if (i==-1) { 700301ea0f4Smrg I740FreeRec(pScrn); 701301ea0f4Smrg return FALSE; 702301ea0f4Smrg } 703301ea0f4Smrg 704301ea0f4Smrg xf86PruneDriverModes(pScrn); 705301ea0f4Smrg 706301ea0f4Smrg if (!i || !pScrn->modes) { 707301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 708301ea0f4Smrg I740FreeRec(pScrn); 709301ea0f4Smrg return FALSE; 710301ea0f4Smrg } 711301ea0f4Smrg 712301ea0f4Smrg xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 713301ea0f4Smrg 714301ea0f4Smrg pScrn->currentMode = pScrn->modes; 715301ea0f4Smrg 716301ea0f4Smrg xf86PrintModes(pScrn); 717301ea0f4Smrg 718301ea0f4Smrg xf86SetDpi(pScrn, 0, 0); 719301ea0f4Smrg 720301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "fb")) { 721301ea0f4Smrg I740FreeRec(pScrn); 722301ea0f4Smrg return FALSE; 723301ea0f4Smrg } 724301ea0f4Smrg 7255c69f917Smrg pI740->NoAccel = xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE); 7265c69f917Smrg if (!pI740->NoAccel) { 727301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "xaa")) { 7285c69f917Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration available\n"); 7295c69f917Smrg pI740->NoAccel = 1; 730301ea0f4Smrg } 731301ea0f4Smrg } 732301ea0f4Smrg 733301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) { 734301ea0f4Smrg if (!xf86LoadSubModule(pScrn, "ramdac")) { 735301ea0f4Smrg I740FreeRec(pScrn); 736301ea0f4Smrg return FALSE; 737301ea0f4Smrg } 738301ea0f4Smrg } 739301ea0f4Smrg 740301ea0f4Smrg /* We wont be using the VGA access after the probe */ 741301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_USE_PIO, FALSE)) { 742ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS 743301ea0f4Smrg resRange vgaio[] = { {ResShrIoBlock,0x3B0,0x3BB}, 744301ea0f4Smrg {ResShrIoBlock,0x3C0,0x3DF}, 745301ea0f4Smrg _END }; 746301ea0f4Smrg resRange vgamem[] = {{ResShrMemBlock,0xA0000,0xAFFFF}, 747301ea0f4Smrg {ResShrMemBlock,0xB8000,0xBFFFF}, 748301ea0f4Smrg {ResShrMemBlock,0xB0000,0xB7FFF}, 749301ea0f4Smrg _END }; 750ef6fb4a5Smrg#endif 751301ea0f4Smrg pI740->usePIO=FALSE; 752301ea0f4Smrg I740SetMMIOAccess(pI740); 753ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS 754301ea0f4Smrg xf86SetOperatingState(vgaio, pI740->pEnt->index, ResUnusedOpr); 755301ea0f4Smrg xf86SetOperatingState(vgamem, pI740->pEnt->index, ResDisableOpr); 756ef6fb4a5Smrg#endif 757301ea0f4Smrg } else { 758301ea0f4Smrg pI740->usePIO=TRUE; 759301ea0f4Smrg } 760301ea0f4Smrg 761301ea0f4Smrg if(xf86IsOptionSet(pI740->Options, OPTION_VGACOMPAT)) 762301ea0f4Smrg pI740->usevgacompat=TRUE; 763301ea0f4Smrg else 764301ea0f4Smrg pI740->usevgacompat=FALSE; 765301ea0f4Smrg 766301ea0f4Smrg 767301ea0f4Smrg 768301ea0f4Smrg { /* Overlay */ 769301ea0f4Smrg pI740->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | 770301ea0f4Smrg (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 771301ea0f4Smrg 772301ea0f4Smrg pI740->colorKey &= ((1 << pScrn->depth) - 1); 773301ea0f4Smrg 774301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video overlay key set to 0x%x\n", pI740->colorKey); 775301ea0f4Smrg } 776301ea0f4Smrg 777301ea0f4Smrg 778301ea0f4Smrg return TRUE; 779301ea0f4Smrg} 780301ea0f4Smrg 781301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn) 782301ea0f4Smrg{ 7838280d184Smrg#ifndef XSERVER_LIBPCIACCESS 784301ea0f4Smrg int mmioFlags; 7858280d184Smrg#endif 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 14725c69f917SmrgI740ScreenInit(SCREEN_INIT_ARGS_DECL) { 1473301ea0f4Smrg ScrnInfoPtr pScrn; 1474301ea0f4Smrg vgaHWPtr hwp; 1475301ea0f4Smrg I740Ptr pI740; 1476301ea0f4Smrg VisualPtr visual; 1477301ea0f4Smrg 14785c69f917Smrg pScrn = xf86ScreenToScrn(pScreen); 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); 14955c69f917Smrg I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 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: 15165c69f917Smrg xf86DrvMsg(pScrn->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 15385c69f917Smrg if (!pI740->NoAccel) { 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 xf86SetBackingStore(pScreen); 1560301ea0f4Smrg xf86SetSilkenMouse(pScreen); 1561301ea0f4Smrg 1562301ea0f4Smrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1563301ea0f4Smrg 1564301ea0f4Smrg if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) { 1565301ea0f4Smrg if (!I740CursorInit(pScreen)) { 1566301ea0f4Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1567301ea0f4Smrg "Hardware cursor initialization failed\n"); 1568301ea0f4Smrg } 1569301ea0f4Smrg } 1570301ea0f4Smrg 1571301ea0f4Smrg if (!miCreateDefColormap(pScreen)) return FALSE; 1572301ea0f4Smrg 1573301ea0f4Smrg if (pScrn->bitsPerPixel==16) 1574301ea0f4Smrg { 1575301ea0f4Smrg if (pScrn->weight.green == 5) 1576301ea0f4Smrg { 1577301ea0f4Smrg if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette15, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1578301ea0f4Smrg return FALSE; 1579301ea0f4Smrg } 1580301ea0f4Smrg else 1581301ea0f4Smrg { 1582301ea0f4Smrg if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette16, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1583301ea0f4Smrg return FALSE; 1584301ea0f4Smrg } 1585301ea0f4Smrg } 1586301ea0f4Smrg else 1587301ea0f4Smrg { 1588301ea0f4Smrg if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette24, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1589301ea0f4Smrg return FALSE; 1590301ea0f4Smrg } 1591301ea0f4Smrg 1592301ea0f4Smrg xf86DPMSInit(pScreen, I740DisplayPowerManagementSet, 0); 1593301ea0f4Smrg 1594301ea0f4Smrg pScreen->SaveScreen = I740SaveScreen; 1595301ea0f4Smrg pI740->CloseScreen = pScreen->CloseScreen; 1596301ea0f4Smrg pScreen->CloseScreen = I740CloseScreen; 1597301ea0f4Smrg 1598301ea0f4Smrg if (serverGeneration == 1) 1599301ea0f4Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1600301ea0f4Smrg 1601301ea0f4Smrg /* Overlay */ 1602301ea0f4Smrg I740InitVideo(pScreen); pI740->OverlayStart = pI740->CursorStart + 1024; 1603301ea0f4Smrg 1604301ea0f4Smrg return TRUE; 1605301ea0f4Smrg} 1606301ea0f4Smrg 1607301ea0f4SmrgBool 16085c69f917SmrgI740SwitchMode(SWITCH_MODE_ARGS_DECL) { 16095c69f917Smrg SCRN_INFO_PTR(arg); 1610301ea0f4Smrg return I740ModeInit(pScrn, mode); 1611301ea0f4Smrg} 1612301ea0f4Smrg 1613301ea0f4Smrgvoid 16145c69f917SmrgI740AdjustFrame(ADJUST_FRAME_ARGS_DECL) { 16155c69f917Smrg SCRN_INFO_PTR(arg); 1616301ea0f4Smrg int Base; 1617301ea0f4Smrg vgaHWPtr hwp; 1618301ea0f4Smrg 1619301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1620301ea0f4Smrg 1621301ea0f4Smrg Base = (y * pScrn->displayWidth + x) >> 2; 1622301ea0f4Smrg switch (pScrn->bitsPerPixel) { 1623301ea0f4Smrg case 8: 1624301ea0f4Smrg break; 1625301ea0f4Smrg case 16: 1626301ea0f4Smrg Base *= 2; 1627301ea0f4Smrg break; 1628301ea0f4Smrg case 24: 1629301ea0f4Smrg /* 1630301ea0f4Smrg * The last bit does not seem to have any effect on the start 1631301ea0f4Smrg * address register in 24bpp mode, so... 1632301ea0f4Smrg */ 1633301ea0f4Smrg Base &= 0xFFFFFFFE; /* ...ignore the last bit. */ 1634301ea0f4Smrg Base *= 3; 1635301ea0f4Smrg break; 1636301ea0f4Smrg case 32: 1637301ea0f4Smrg Base *= 4; 1638301ea0f4Smrg break; 1639301ea0f4Smrg } 1640301ea0f4Smrg 1641301ea0f4Smrg hwp->writeCrtc(hwp, START_ADDR_LO, Base&0xFF); 1642301ea0f4Smrg hwp->writeCrtc(hwp, START_ADDR_HI, (Base&0xFF00)>>8); 1643301ea0f4Smrg hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base&0x3FC00000)>>22); 1644301ea0f4Smrg hwp->writeCrtc(hwp, EXT_START_ADDR, 1645301ea0f4Smrg ((Base&0x00eF0000)>>16|EXT_START_ADDR_ENABLE)); 1646301ea0f4Smrg} 1647301ea0f4Smrg 1648301ea0f4Smrgstatic Bool 16495c69f917SmrgI740EnterVT(VT_FUNC_ARGS_DECL) { 16505c69f917Smrg SCRN_INFO_PTR(arg); 1651301ea0f4Smrg 1652301ea0f4Smrg if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE; 16535c69f917Smrg I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1654301ea0f4Smrg return TRUE; 1655301ea0f4Smrg} 1656301ea0f4Smrg 1657301ea0f4Smrgstatic void 16585c69f917SmrgI740LeaveVT(VT_FUNC_ARGS_DECL) { 16595c69f917Smrg SCRN_INFO_PTR(arg); 1660301ea0f4Smrg vgaHWPtr hwp; 1661301ea0f4Smrg 1662301ea0f4Smrg hwp=VGAHWPTR(pScrn); 1663301ea0f4Smrg I740Restore(pScrn); 1664301ea0f4Smrg vgaHWLock(hwp); 1665301ea0f4Smrg} 1666301ea0f4Smrg 1667301ea0f4Smrgstatic Bool 16685c69f917SmrgI740CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1669301ea0f4Smrg{ 1670301ea0f4Smrg ScrnInfoPtr pScrn; 1671301ea0f4Smrg vgaHWPtr hwp; 1672301ea0f4Smrg I740Ptr pI740; 1673301ea0f4Smrg 16745c69f917Smrg pScrn = xf86ScreenToScrn(pScreen); 1675301ea0f4Smrg hwp = VGAHWPTR(pScrn); 1676301ea0f4Smrg pI740 = I740PTR(pScrn); 1677301ea0f4Smrg 1678301ea0f4Smrg if (pScrn->vtSema) { 1679301ea0f4Smrg I740Restore(pScrn); 1680301ea0f4Smrg vgaHWLock(hwp); 1681301ea0f4Smrg } 1682301ea0f4Smrg 1683301ea0f4Smrg I740UnmapMem(pScrn); 1684301ea0f4Smrg vgaHWUnmapMem(pScrn); 16855c69f917Smrg#ifdef HAVE_XAA_H 1686301ea0f4Smrg if (pI740->AccelInfoRec) 1687301ea0f4Smrg XAADestroyInfoRec(pI740->AccelInfoRec); 1688301ea0f4Smrg pI740->AccelInfoRec=0; 16895c69f917Smrg#endif 1690301ea0f4Smrg if (pI740->CursorInfoRec) 1691301ea0f4Smrg xf86DestroyCursorInfoRec(pI740->CursorInfoRec); 1692301ea0f4Smrg pI740->CursorInfoRec=0; 1693301ea0f4Smrg pScrn->vtSema=FALSE; 1694301ea0f4Smrg 1695301ea0f4Smrg pScreen->CloseScreen = pI740->CloseScreen; 16965c69f917Smrg return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1697301ea0f4Smrg} 1698301ea0f4Smrg 1699301ea0f4Smrgstatic void 17005c69f917SmrgI740FreeScreen(FREE_SCREEN_ARGS_DECL) { 17015c69f917Smrg SCRN_INFO_PTR(arg); 17025c69f917Smrg I740FreeRec(pScrn); 1703301ea0f4Smrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 17045c69f917Smrg vgaHWFreeHWRec(pScrn); 1705301ea0f4Smrg} 1706301ea0f4Smrg 1707301ea0f4Smrgstatic ModeStatus 17085c69f917SmrgI740ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) { 17095c69f917Smrg SCRN_INFO_PTR(arg); 1710301ea0f4Smrg if (mode->Flags & V_INTERLACE) { 1711301ea0f4Smrg if (verbose) { 17125c69f917Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1713301ea0f4Smrg "Removing interlaced mode \"%s\"\n", 1714301ea0f4Smrg mode->name); 1715301ea0f4Smrg } 1716301ea0f4Smrg return MODE_BAD; 1717301ea0f4Smrg } 1718301ea0f4Smrg return MODE_OK; 1719301ea0f4Smrg} 1720301ea0f4Smrg 1721301ea0f4Smrgstatic Bool 1722301ea0f4SmrgI740SaveScreen(ScreenPtr pScreen, int mode) 1723301ea0f4Smrg{ 1724301ea0f4Smrg#if 0 1725301ea0f4Smrg Bool unblack = xf86IsUnblank(mode); 1726301ea0f4Smrg if (unblack) outw(SRX, 0x0300); 1727301ea0f4Smrg else outw(SRX, 0x0100); 1728301ea0f4Smrg#endif 1729301ea0f4Smrg return vgaHWSaveScreen(pScreen, mode); 1730301ea0f4Smrg} 1731301ea0f4Smrg 1732301ea0f4Smrgstatic void 1733301ea0f4SmrgI740DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 1734301ea0f4Smrg int flags) { 1735301ea0f4Smrg I740Ptr pI740; 1736301ea0f4Smrg unsigned char SEQ01=0; 1737301ea0f4Smrg int DPMSSyncSelect=0; 1738301ea0f4Smrg 1739301ea0f4Smrg pI740 = I740PTR(pScrn); 1740301ea0f4Smrg switch (PowerManagementMode) { 1741301ea0f4Smrg case DPMSModeOn: 1742301ea0f4Smrg /* Screen: On; HSync: On, VSync: On */ 1743301ea0f4Smrg SEQ01 = 0x00; 1744301ea0f4Smrg DPMSSyncSelect = HSYNC_ON | VSYNC_ON; 1745301ea0f4Smrg break; 1746301ea0f4Smrg case DPMSModeStandby: 1747301ea0f4Smrg /* Screen: Off; HSync: Off, VSync: On */ 1748301ea0f4Smrg SEQ01 = 0x20; 1749301ea0f4Smrg DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; 1750301ea0f4Smrg break; 1751301ea0f4Smrg case DPMSModeSuspend: 1752301ea0f4Smrg /* Screen: Off; HSync: On, VSync: Off */ 1753301ea0f4Smrg SEQ01 = 0x20; 1754301ea0f4Smrg DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; 1755301ea0f4Smrg break; 1756301ea0f4Smrg case DPMSModeOff: 1757301ea0f4Smrg /* Screen: Off; HSync: Off, VSync: Off */ 1758301ea0f4Smrg SEQ01 = 0x20; 1759301ea0f4Smrg DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; 1760301ea0f4Smrg break; 1761301ea0f4Smrg } 1762301ea0f4Smrg 1763301ea0f4Smrg /* Turn the screen on/off */ 1764301ea0f4Smrg SEQ01 |= pI740->readControl(pI740, SRX, 0x01) & ~0x20; 1765301ea0f4Smrg pI740->writeControl(pI740, SRX, 0x01, SEQ01); 1766301ea0f4Smrg 1767301ea0f4Smrg /* Set the DPMS mode */ 1768301ea0f4Smrg pI740->writeControl(pI740, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect); 1769301ea0f4Smrg} 1770