1428d7b3dSmrg 2428d7b3dSmrg/************************************************************************** 3428d7b3dSmrg 4428d7b3dSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5428d7b3dSmrgAll Rights Reserved. 6428d7b3dSmrg 7428d7b3dSmrgPermission is hereby granted, free of charge, to any person obtaining a 8428d7b3dSmrgcopy of this software and associated documentation files (the 9428d7b3dSmrg"Software"), to deal in the Software without restriction, including 10428d7b3dSmrgwithout limitation the rights to use, copy, modify, merge, publish, 11428d7b3dSmrgdistribute, sub license, and/or sell copies of the Software, and to 12428d7b3dSmrgpermit persons to whom the Software is furnished to do so, subject to 13428d7b3dSmrgthe following conditions: 14428d7b3dSmrg 15428d7b3dSmrgThe above copyright notice and this permission notice (including the 16428d7b3dSmrgnext paragraph) shall be included in all copies or substantial portions 17428d7b3dSmrgof the Software. 18428d7b3dSmrg 19428d7b3dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20428d7b3dSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21428d7b3dSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22428d7b3dSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23428d7b3dSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24428d7b3dSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25428d7b3dSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26428d7b3dSmrg 27428d7b3dSmrg**************************************************************************/ 28428d7b3dSmrg 29428d7b3dSmrg#ifdef HAVE_CONFIG_H 30428d7b3dSmrg#include "config.h" 31428d7b3dSmrg#endif 32428d7b3dSmrg 33428d7b3dSmrg/* 34428d7b3dSmrg * Authors: 35428d7b3dSmrg * Keith Whitwell <keith@tungstengraphics.com> 36428d7b3dSmrg * 37428d7b3dSmrg * Add ARGB HW cursor support: 38428d7b3dSmrg * Alan Hourihane <alanh@tungstengraphics.com> 39428d7b3dSmrg * 40428d7b3dSmrg */ 41428d7b3dSmrg 42428d7b3dSmrg/* 43428d7b3dSmrg * This server does not support these XFree86 4.0 features yet 44428d7b3dSmrg * shadowFb (if requested or acceleration is off) 45428d7b3dSmrg * Overlay planes 46428d7b3dSmrg * DGA 47428d7b3dSmrg */ 48428d7b3dSmrg 49428d7b3dSmrg#include <math.h> 50428d7b3dSmrg#include <string.h> 51428d7b3dSmrg#include <unistd.h> 52428d7b3dSmrg 53428d7b3dSmrg/* 54428d7b3dSmrg * These are X and server generic header files. 55428d7b3dSmrg */ 56428d7b3dSmrg#include "xorg-server.h" 57428d7b3dSmrg#include "xf86.h" 58428d7b3dSmrg#include "xf86_OSproc.h" 59428d7b3dSmrg#include "xf86cmap.h" 60428d7b3dSmrg 61428d7b3dSmrg#include "compiler.h" 62428d7b3dSmrg#include "vgaHW.h" 63428d7b3dSmrg#include "mipointer.h" 64428d7b3dSmrg#include "micmap.h" 65428d7b3dSmrg 66428d7b3dSmrg#include "fb.h" 67428d7b3dSmrg#include "miscstruct.h" 68428d7b3dSmrg#include "xf86xv.h" 69428d7b3dSmrg#include <X11/extensions/Xv.h> 70428d7b3dSmrg#include "vbe.h" 71428d7b3dSmrg#include "xf86fbman.h" 72428d7b3dSmrg 73428d7b3dSmrg#include "i810.h" 74428d7b3dSmrg 75428d7b3dSmrg#ifdef HAVE_DRI1 76428d7b3dSmrg#include "dri.h" 77428d7b3dSmrg#endif 78428d7b3dSmrg 79428d7b3dSmrg#include "../legacy.h" 80428d7b3dSmrg 81428d7b3dSmrgstatic Bool I810PreInit(ScrnInfoPtr pScrn, int flags); 82428d7b3dSmrgstatic Bool I810ScreenInit(SCREEN_INIT_ARGS_DECL); 83428d7b3dSmrgstatic Bool I810EnterVT(VT_FUNC_ARGS_DECL); 84428d7b3dSmrgstatic void I810LeaveVT(VT_FUNC_ARGS_DECL); 85428d7b3dSmrgstatic Bool I810CloseScreen(CLOSE_SCREEN_ARGS_DECL); 86428d7b3dSmrgstatic Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank); 87428d7b3dSmrgstatic void I810FreeScreen(FREE_SCREEN_ARGS_DECL); 88428d7b3dSmrgstatic void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, 89428d7b3dSmrg int PowerManagermentMode, 90428d7b3dSmrg int flags); 91428d7b3dSmrgstatic ModeStatus I810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 92428d7b3dSmrg Bool verbose, int flags); 93428d7b3dSmrg 94428d7b3dSmrgtypedef enum { 95428d7b3dSmrg OPTION_NOACCEL, 96428d7b3dSmrg OPTION_SW_CURSOR, 97428d7b3dSmrg OPTION_COLOR_KEY, 98428d7b3dSmrg OPTION_CACHE_LINES, 99428d7b3dSmrg OPTION_DAC_6BIT, 100428d7b3dSmrg OPTION_DRI, 101428d7b3dSmrg OPTION_NO_DDC, 102428d7b3dSmrg OPTION_SHOW_CACHE, 103428d7b3dSmrg OPTION_XVMC_SURFACES, 104428d7b3dSmrg OPTION_PAGEFLIP 105428d7b3dSmrg} I810Opts; 106428d7b3dSmrg 107428d7b3dSmrgstatic const OptionInfoRec I810Options[] = { 108428d7b3dSmrg {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, 109428d7b3dSmrg {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 110428d7b3dSmrg {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, 111428d7b3dSmrg {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, 112428d7b3dSmrg {OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, 113428d7b3dSmrg {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, 114428d7b3dSmrg {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, 115428d7b3dSmrg {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, 116428d7b3dSmrg {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, 117428d7b3dSmrg {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, 118428d7b3dSmrg {-1, NULL, OPTV_NONE, {0}, FALSE} 119428d7b3dSmrg}; 120428d7b3dSmrg/* *INDENT-ON* */ 121428d7b3dSmrg 122428d7b3dSmrg#ifndef I810_DEBUG 123428d7b3dSmrgint I810_DEBUG = (0 124428d7b3dSmrg/* | DEBUG_ALWAYS_SYNC */ 125428d7b3dSmrg/* | DEBUG_VERBOSE_ACCEL */ 126428d7b3dSmrg/* | DEBUG_VERBOSE_SYNC */ 127428d7b3dSmrg/* | DEBUG_VERBOSE_VGA */ 128428d7b3dSmrg/* | DEBUG_VERBOSE_RING */ 129428d7b3dSmrg/* | DEBUG_VERBOSE_OUTREG */ 130428d7b3dSmrg/* | DEBUG_VERBOSE_MEMORY */ 131428d7b3dSmrg/* | DEBUG_VERBOSE_CURSOR */ 132428d7b3dSmrg ); 133428d7b3dSmrg#endif 134428d7b3dSmrg 135428d7b3dSmrg#ifdef HAVE_DRI1 136428d7b3dSmrgstatic int i810_pitches[] = { 137428d7b3dSmrg 512, 138428d7b3dSmrg 1024, 139428d7b3dSmrg 2048, 140428d7b3dSmrg 4096, 141428d7b3dSmrg 0 142428d7b3dSmrg}; 143428d7b3dSmrg#endif 144428d7b3dSmrg 145428d7b3dSmrg/* 146428d7b3dSmrg * I810GetRec and I810FreeRec -- 147428d7b3dSmrg * 148428d7b3dSmrg * Private data for the driver is stored in the screen structure. 149428d7b3dSmrg * These two functions create and destroy that private data. 150428d7b3dSmrg * 151428d7b3dSmrg */ 152428d7b3dSmrgstatic Bool 153428d7b3dSmrgI810GetRec(ScrnInfoPtr scrn) 154428d7b3dSmrg{ 155428d7b3dSmrg if (((uintptr_t)scrn->driverPrivate & 3) == 0) 156428d7b3dSmrg return TRUE; 157428d7b3dSmrg 158428d7b3dSmrg scrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1); 159428d7b3dSmrg return TRUE; 160428d7b3dSmrg} 161428d7b3dSmrg 162428d7b3dSmrgstatic void 163428d7b3dSmrgI810FreeRec(ScrnInfoPtr scrn) 164428d7b3dSmrg{ 165428d7b3dSmrg if (!scrn) 166428d7b3dSmrg return; 167428d7b3dSmrg if (!scrn->driverPrivate) 168428d7b3dSmrg return; 169428d7b3dSmrg free(scrn->driverPrivate); 170428d7b3dSmrg scrn->driverPrivate = NULL; 171428d7b3dSmrg} 172428d7b3dSmrg 173428d7b3dSmrgstruct pci_device * 174428d7b3dSmrgintel_host_bridge (void) 175428d7b3dSmrg{ 176428d7b3dSmrg static const struct pci_slot_match bridge_match = { 177428d7b3dSmrg 0, 0, 0, PCI_MATCH_ANY, 0 178428d7b3dSmrg }; 179428d7b3dSmrg struct pci_device_iterator *slot_iterator; 180428d7b3dSmrg struct pci_device *bridge; 181428d7b3dSmrg 182428d7b3dSmrg slot_iterator = pci_slot_match_iterator_create (&bridge_match); 183428d7b3dSmrg bridge = pci_device_next (slot_iterator); 184428d7b3dSmrg pci_iterator_destroy (slot_iterator); 185428d7b3dSmrg return bridge; 186428d7b3dSmrg} 187428d7b3dSmrg 188428d7b3dSmrgstatic void 189428d7b3dSmrgI810ProbeDDC(ScrnInfoPtr scrn, int index) 190428d7b3dSmrg{ 191428d7b3dSmrg vbeInfoPtr pVbe; 192428d7b3dSmrg 193428d7b3dSmrg if (xf86LoadSubModule(scrn, "vbe")) { 194428d7b3dSmrg pVbe = VBEInit(NULL, index); 195428d7b3dSmrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 196428d7b3dSmrg vbeFree(pVbe); 197428d7b3dSmrg } 198428d7b3dSmrg} 199428d7b3dSmrg 200428d7b3dSmrgstatic xf86MonPtr 201428d7b3dSmrgI810DoDDC(ScrnInfoPtr scrn, int index) 202428d7b3dSmrg{ 203428d7b3dSmrg vbeInfoPtr pVbe; 204428d7b3dSmrg xf86MonPtr MonInfo = NULL; 205428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 206428d7b3dSmrg 207428d7b3dSmrg /* Honour Option "noDDC" */ 208428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) { 209428d7b3dSmrg return MonInfo; 210428d7b3dSmrg } 211428d7b3dSmrg 212428d7b3dSmrg if (xf86LoadSubModule(scrn, "vbe") && (pVbe = VBEInit(NULL, index))) { 213428d7b3dSmrg MonInfo = vbeDoEDID(pVbe, NULL); 214428d7b3dSmrg xf86PrintEDID(MonInfo); 215428d7b3dSmrg xf86SetDDCproperties(scrn, MonInfo); 216428d7b3dSmrg vbeFree(pVbe); 217428d7b3dSmrg } else { 218428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 219428d7b3dSmrg "this driver cannot do DDC without VBE\n"); 220428d7b3dSmrg } 221428d7b3dSmrg 222428d7b3dSmrg return MonInfo; 223428d7b3dSmrg} 224428d7b3dSmrg 225428d7b3dSmrg/* 226428d7b3dSmrg * I810PreInit -- 227428d7b3dSmrg * 228428d7b3dSmrg * Do initial setup of the board before we know what resolution we will 229428d7b3dSmrg * be running at. 230428d7b3dSmrg * 231428d7b3dSmrg */ 232428d7b3dSmrgstatic Bool 233428d7b3dSmrgI810PreInit(ScrnInfoPtr scrn, int flags) 234428d7b3dSmrg{ 235428d7b3dSmrg I810Ptr pI810; 236428d7b3dSmrg ClockRangePtr clockRanges; 237428d7b3dSmrg int i; 238428d7b3dSmrg MessageType from; 239428d7b3dSmrg int flags24; 240428d7b3dSmrg rgb defaultWeight = { 0, 0, 0 }; 241428d7b3dSmrg int mem; 242428d7b3dSmrg Bool enable; 243428d7b3dSmrg 244428d7b3dSmrg if (scrn->numEntities != 1) 245428d7b3dSmrg return FALSE; 246428d7b3dSmrg 247428d7b3dSmrg /* Allocate driverPrivate */ 248428d7b3dSmrg if (!I810GetRec(scrn)) 249428d7b3dSmrg return FALSE; 250428d7b3dSmrg 251428d7b3dSmrg pI810 = I810PTR(scrn); 252428d7b3dSmrg 253428d7b3dSmrg pI810->pEnt = xf86GetEntityInfo(scrn->entityList[0]); 254428d7b3dSmrg if (pI810->pEnt == NULL || pI810->pEnt->location.type != BUS_PCI) 255428d7b3dSmrg return FALSE; 256428d7b3dSmrg 257428d7b3dSmrg if (flags & PROBE_DETECT) { 258428d7b3dSmrg I810ProbeDDC(scrn, pI810->pEnt->index); 259428d7b3dSmrg return TRUE; 260428d7b3dSmrg } 261428d7b3dSmrg 262428d7b3dSmrg /* The vgahw module should be loaded here when needed */ 263428d7b3dSmrg if (!xf86LoadSubModule(scrn, "vgahw")) 264428d7b3dSmrg return FALSE; 265428d7b3dSmrg 266428d7b3dSmrg /* Allocate a vgaHWRec */ 267428d7b3dSmrg if (!vgaHWGetHWRec(scrn)) 268428d7b3dSmrg return FALSE; 269428d7b3dSmrg 270428d7b3dSmrg pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index); 271428d7b3dSmrg 272428d7b3dSmrg /* Set scrn->monitor */ 273428d7b3dSmrg scrn->monitor = scrn->confScreen->monitor; 274428d7b3dSmrg 275428d7b3dSmrg flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24; 276428d7b3dSmrg if (!xf86SetDepthBpp(scrn, 16, 0, 16, flags24)) { 277428d7b3dSmrg return FALSE; 278428d7b3dSmrg } else { 279428d7b3dSmrg switch (scrn->depth) { 280428d7b3dSmrg case 8: 281428d7b3dSmrg case 15: 282428d7b3dSmrg case 16: 283428d7b3dSmrg case 24: 284428d7b3dSmrg break; 285428d7b3dSmrg default: 286428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 287428d7b3dSmrg "Given depth (%d) is not supported by i810 driver\n", 288428d7b3dSmrg scrn->depth); 289428d7b3dSmrg return FALSE; 290428d7b3dSmrg } 291428d7b3dSmrg } 292428d7b3dSmrg xf86PrintDepthBpp(scrn); 293428d7b3dSmrg 294428d7b3dSmrg switch (scrn->bitsPerPixel) { 295428d7b3dSmrg case 8: 296428d7b3dSmrg case 16: 297428d7b3dSmrg case 24: 298428d7b3dSmrg break; 299428d7b3dSmrg default: 300428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 301428d7b3dSmrg "Given bpp (%d) is not supported by i810 driver\n", 302428d7b3dSmrg scrn->bitsPerPixel); 303428d7b3dSmrg return FALSE; 304428d7b3dSmrg } 305428d7b3dSmrg 306428d7b3dSmrg if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 307428d7b3dSmrg return FALSE; 308428d7b3dSmrg 309428d7b3dSmrg if (!xf86SetDefaultVisual(scrn, -1)) 310428d7b3dSmrg return FALSE; 311428d7b3dSmrg 312428d7b3dSmrg /* We use a programmable clock */ 313428d7b3dSmrg scrn->progClock = TRUE; 314428d7b3dSmrg 315428d7b3dSmrg pI810->cpp = scrn->bitsPerPixel / 8; 316428d7b3dSmrg 317428d7b3dSmrg /* Process the options */ 318428d7b3dSmrg xf86CollectOptions(scrn, NULL); 319428d7b3dSmrg if (!(pI810->Options = malloc(sizeof(I810Options)))) 320428d7b3dSmrg return FALSE; 321428d7b3dSmrg memcpy(pI810->Options, I810Options, sizeof(I810Options)); 322428d7b3dSmrg xf86ProcessOptions(scrn->scrnIndex, scrn->options, pI810->Options); 323428d7b3dSmrg 324428d7b3dSmrg scrn->rgbBits = 8; 325428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) 326428d7b3dSmrg scrn->rgbBits = 6; 327428d7b3dSmrg 328428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE)) 329428d7b3dSmrg pI810->showCache = TRUE; 330428d7b3dSmrg else 331428d7b3dSmrg pI810->showCache = FALSE; 332428d7b3dSmrg 333428d7b3dSmrg /* 6-BIT dac isn't reasonable for modes with > 8bpp */ 334428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) && 335428d7b3dSmrg scrn->bitsPerPixel > 8) { 336428d7b3dSmrg OptionInfoPtr ptr; 337428d7b3dSmrg 338428d7b3dSmrg ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT); 339428d7b3dSmrg ptr->found = FALSE; 340428d7b3dSmrg } 341428d7b3dSmrg 342428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) 343428d7b3dSmrg pI810->noAccel = TRUE; 344428d7b3dSmrg 345428d7b3dSmrg if (!pI810->noAccel && !xf86LoadSubModule(scrn, "xaa")) 346428d7b3dSmrg pI810->noAccel = TRUE; 347428d7b3dSmrg 348428d7b3dSmrg#ifdef HAVE_DRI1 349428d7b3dSmrg pI810->directRenderingDisabled = 350428d7b3dSmrg !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE); 351428d7b3dSmrg 352428d7b3dSmrg if (!pI810->directRenderingDisabled) { 353428d7b3dSmrg if (scrn->depth!=16) { 354428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "DRI is disabled because it " 355428d7b3dSmrg "runs only at 16-bit depth.\n"); 356428d7b3dSmrg pI810->directRenderingDisabled=TRUE; 357428d7b3dSmrg } 358428d7b3dSmrg } 359428d7b3dSmrg#endif 360428d7b3dSmrg 361428d7b3dSmrg /* Get DDC info from monitor */ 362428d7b3dSmrg /* after xf86ProcessOptions, 363428d7b3dSmrg * because it is controlled by options [no]vbe and [no]ddc 364428d7b3dSmrg */ 365428d7b3dSmrg I810DoDDC(scrn, pI810->pEnt->index); 366428d7b3dSmrg 367428d7b3dSmrg intel_detect_chipset(scrn, NULL); 368428d7b3dSmrg 369428d7b3dSmrg pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr; 370428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n", 371428d7b3dSmrg (unsigned long)pI810->LinearAddr); 372428d7b3dSmrg 373428d7b3dSmrg pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr; 374428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, "IO registers at addr 0x%lX\n", 375428d7b3dSmrg (unsigned long)pI810->MMIOAddr); 376428d7b3dSmrg 377428d7b3dSmrg /* AGP GART support is required. Don't proceed any further if it isn't 378428d7b3dSmrg * present. 379428d7b3dSmrg */ 380428d7b3dSmrg if (!xf86AgpGARTSupported()) { 381428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 382428d7b3dSmrg "AGP GART support is not available. Make sure your kernel has\n" 383428d7b3dSmrg "\tagpgart support or that the agpgart kernel module is loaded.\n"); 384428d7b3dSmrg return FALSE; 385428d7b3dSmrg } 386428d7b3dSmrg 387428d7b3dSmrg /* Find out memory bus frequency. 388428d7b3dSmrg */ 389428d7b3dSmrg { 390428d7b3dSmrg uint32_t whtcfg_pamr_drp; 391428d7b3dSmrg 392428d7b3dSmrg pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP); 393428d7b3dSmrg 394428d7b3dSmrg /* Need this for choosing watermarks. 395428d7b3dSmrg */ 396428d7b3dSmrg if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133) 397428d7b3dSmrg pI810->LmFreqSel = 133; 398428d7b3dSmrg else 399428d7b3dSmrg pI810->LmFreqSel = 100; 400428d7b3dSmrg } 401428d7b3dSmrg 402428d7b3dSmrg /* Default to 4MB framebuffer, which is sufficient for all 403428d7b3dSmrg * supported 2d resolutions. If the user has specified a different 404428d7b3dSmrg * size in the XF86Config, use that amount instead. 405428d7b3dSmrg * 406428d7b3dSmrg * Changed to 8 Meg so we can have acceleration by default (Mark). 407428d7b3dSmrg */ 408428d7b3dSmrg mem = I810CheckAvailableMemory(scrn); 409428d7b3dSmrg if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */ 410428d7b3dSmrg scrn->videoRam = 8192; 411428d7b3dSmrg else if (mem < 196608) 412428d7b3dSmrg scrn->videoRam = 16384; /* < 192 MB */ 413428d7b3dSmrg else 414428d7b3dSmrg scrn->videoRam = 24576; 415428d7b3dSmrg 416428d7b3dSmrg from = X_DEFAULT; 417428d7b3dSmrg 418428d7b3dSmrg if (pI810->pEnt->device->videoRam) { 419428d7b3dSmrg scrn->videoRam = pI810->pEnt->device->videoRam; 420428d7b3dSmrg from = X_CONFIG; 421428d7b3dSmrg } 422428d7b3dSmrg 423428d7b3dSmrg if (mem > 0 && mem < scrn->videoRam) { 424428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%dk of memory was requested," 425428d7b3dSmrg " but the\n\t maximum AGP memory available is %dk.\n", 426428d7b3dSmrg scrn->videoRam, mem); 427428d7b3dSmrg from = X_PROBED; 428428d7b3dSmrg if (mem > (6 * 1024)) { 429428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 430428d7b3dSmrg "Reducing video memory to 4MB\n"); 431428d7b3dSmrg scrn->videoRam = 4096; 432428d7b3dSmrg } else { 433428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory" 434428d7b3dSmrg " is available. Cannot proceed.\n"); 435428d7b3dSmrg I810FreeRec(scrn); 436428d7b3dSmrg return FALSE; 437428d7b3dSmrg } 438428d7b3dSmrg } 439428d7b3dSmrg 440428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, from, 441428d7b3dSmrg "Will alloc AGP framebuffer: %d kByte\n", scrn->videoRam); 442428d7b3dSmrg 443428d7b3dSmrg /* Calculate Fixed Offsets depending on graphics aperture size */ 444428d7b3dSmrg { 445428d7b3dSmrg struct pci_device *bridge = intel_host_bridge (); 446428d7b3dSmrg uint32_t smram_miscc; 447428d7b3dSmrg 448428d7b3dSmrg pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC); 449428d7b3dSmrg 450428d7b3dSmrg if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) { 451428d7b3dSmrg pI810->FbMapSize = 0x1000000; 452428d7b3dSmrg pI810->DepthOffset = 0x1000000; 453428d7b3dSmrg pI810->BackOffset = 0x1800000; 454428d7b3dSmrg } else { 455428d7b3dSmrg pI810->FbMapSize = 0x3000000; 456428d7b3dSmrg pI810->DepthOffset = 0x3000000; 457428d7b3dSmrg pI810->BackOffset = 0x3800000; 458428d7b3dSmrg } 459428d7b3dSmrg } 460428d7b3dSmrg 461428d7b3dSmrg /* 462428d7b3dSmrg * If the driver can do gamma correction, it should call xf86SetGamma() 463428d7b3dSmrg * here. 464428d7b3dSmrg */ 465428d7b3dSmrg { 466428d7b3dSmrg Gamma zeros = { 0.0, 0.0, 0.0 }; 467428d7b3dSmrg 468428d7b3dSmrg if (!xf86SetGamma(scrn, zeros)) { 469428d7b3dSmrg return FALSE; 470428d7b3dSmrg } 471428d7b3dSmrg } 472428d7b3dSmrg 473428d7b3dSmrg pI810->MaxClock = 0; 474428d7b3dSmrg if (pI810->pEnt->device->dacSpeeds[0]) { 475428d7b3dSmrg switch (scrn->bitsPerPixel) { 476428d7b3dSmrg case 8: 477428d7b3dSmrg pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8]; 478428d7b3dSmrg break; 479428d7b3dSmrg case 16: 480428d7b3dSmrg pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16]; 481428d7b3dSmrg break; 482428d7b3dSmrg case 24: 483428d7b3dSmrg pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24]; 484428d7b3dSmrg break; 485428d7b3dSmrg case 32: /* not supported */ 486428d7b3dSmrg pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32]; 487428d7b3dSmrg break; 488428d7b3dSmrg } 489428d7b3dSmrg if (!pI810->MaxClock) 490428d7b3dSmrg pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0]; 491428d7b3dSmrg } else { 492428d7b3dSmrg switch (scrn->bitsPerPixel) { 493428d7b3dSmrg case 8: 494428d7b3dSmrg pI810->MaxClock = 203000; 495428d7b3dSmrg break; 496428d7b3dSmrg case 16: 497428d7b3dSmrg pI810->MaxClock = 163000; 498428d7b3dSmrg break; 499428d7b3dSmrg case 24: 500428d7b3dSmrg pI810->MaxClock = 136000; 501428d7b3dSmrg break; 502428d7b3dSmrg case 32: /* not supported */ 503428d7b3dSmrg pI810->MaxClock = 86000; 504428d7b3dSmrg } 505428d7b3dSmrg } 506428d7b3dSmrg clockRanges = xnfcalloc(sizeof(ClockRange), 1); 507428d7b3dSmrg clockRanges->next = NULL; 508428d7b3dSmrg /* 9.4MHz appears to be the smallest that works. */ 509428d7b3dSmrg clockRanges->minClock = 9500; 510428d7b3dSmrg clockRanges->maxClock = pI810->MaxClock; 511428d7b3dSmrg clockRanges->clockIndex = -1; 512428d7b3dSmrg clockRanges->interlaceAllowed = TRUE; 513428d7b3dSmrg clockRanges->doubleScanAllowed = FALSE; 514428d7b3dSmrg 515428d7b3dSmrg i = xf86ValidateModes(scrn, scrn->monitor->Modes, 516428d7b3dSmrg scrn->display->modes, clockRanges, 517428d7b3dSmrg#ifndef HAVE_DRI1 518428d7b3dSmrg 0, 320, 1600, 64 * scrn->bitsPerPixel, 519428d7b3dSmrg#else 520428d7b3dSmrg i810_pitches, 0, 0, 64 * scrn->bitsPerPixel, 521428d7b3dSmrg#endif 522428d7b3dSmrg 200, 1200, 523428d7b3dSmrg scrn->display->virtualX, scrn->display->virtualY, 524428d7b3dSmrg scrn->videoRam * 1024, LOOKUP_BEST_REFRESH); 525428d7b3dSmrg 526428d7b3dSmrg if (i == -1) { 527428d7b3dSmrg I810FreeRec(scrn); 528428d7b3dSmrg return FALSE; 529428d7b3dSmrg } 530428d7b3dSmrg 531428d7b3dSmrg xf86PruneDriverModes(scrn); 532428d7b3dSmrg 533428d7b3dSmrg if (!i || !scrn->modes) { 534428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No valid modes found\n"); 535428d7b3dSmrg I810FreeRec(scrn); 536428d7b3dSmrg return FALSE; 537428d7b3dSmrg } 538428d7b3dSmrg 539428d7b3dSmrg xf86SetCrtcForModes(scrn, INTERLACE_HALVE_V); 540428d7b3dSmrg 541428d7b3dSmrg scrn->currentMode = scrn->modes; 542428d7b3dSmrg 543428d7b3dSmrg xf86PrintModes(scrn); 544428d7b3dSmrg 545428d7b3dSmrg xf86SetDpi(scrn, 0, 0); 546428d7b3dSmrg 547428d7b3dSmrg if (!xf86LoadSubModule(scrn, "fb")) { 548428d7b3dSmrg I810FreeRec(scrn); 549428d7b3dSmrg return FALSE; 550428d7b3dSmrg } 551428d7b3dSmrg 552428d7b3dSmrg if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { 553428d7b3dSmrg if (!xf86LoadSubModule(scrn, "ramdac")) { 554428d7b3dSmrg I810FreeRec(scrn); 555428d7b3dSmrg return FALSE; 556428d7b3dSmrg } 557428d7b3dSmrg } 558428d7b3dSmrg 559428d7b3dSmrg if (xf86GetOptValInteger 560428d7b3dSmrg (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) { 561428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 562428d7b3dSmrg "video overlay key set to 0x%x\n", pI810->colorKey); 563428d7b3dSmrg } else { 564428d7b3dSmrg pI810->colorKey = (1 << scrn->offset.red) | 565428d7b3dSmrg (1 << scrn->offset.green) | 566428d7b3dSmrg (((scrn->mask.blue >> scrn->offset.blue) - 567428d7b3dSmrg 1) << scrn->offset.blue); 568428d7b3dSmrg } 569428d7b3dSmrg 570428d7b3dSmrg pI810->allowPageFlip=FALSE; 571428d7b3dSmrg enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE); 572428d7b3dSmrg 573428d7b3dSmrg#ifdef HAVE_DRI1 574428d7b3dSmrg if (!pI810->directRenderingDisabled) { 575428d7b3dSmrg pI810->allowPageFlip = enable; 576428d7b3dSmrg if (pI810->allowPageFlip == TRUE) 577428d7b3dSmrg { 578428d7b3dSmrg if (!xf86LoadSubModule(scrn, "shadowfb")) { 579428d7b3dSmrg pI810->allowPageFlip = 0; 580428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 581428d7b3dSmrg "Couldn't load shadowfb module:\n"); 582428d7b3dSmrg } 583428d7b3dSmrg } 584428d7b3dSmrg 585428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "page flipping %s\n", 586428d7b3dSmrg enable ? "enabled" : "disabled"); 587428d7b3dSmrg 588428d7b3dSmrg } 589428d7b3dSmrg#endif 590428d7b3dSmrg 591428d7b3dSmrg if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES, 592428d7b3dSmrg &(pI810->numSurfaces))) { 593428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n", 594428d7b3dSmrg pI810->numSurfaces); 595428d7b3dSmrg if (pI810->numSurfaces > 7) { 596428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, 597428d7b3dSmrg "Using 7 XvMC Surfaces (Maximum Allowed).\n"); 598428d7b3dSmrg pI810->numSurfaces = 7; 599428d7b3dSmrg } 600428d7b3dSmrg if (pI810->numSurfaces < 6) { 601428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, 602428d7b3dSmrg "Using 6 XvMC Surfaces (Minimum Allowed).\n"); 603428d7b3dSmrg pI810->numSurfaces = 6; 604428d7b3dSmrg } 605428d7b3dSmrg } else { 606428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 607428d7b3dSmrg "XvMC is Disabled: use XvMCSurfaces config option to enable.\n"); 608428d7b3dSmrg pI810->numSurfaces = 0; 609428d7b3dSmrg } 610428d7b3dSmrg 611428d7b3dSmrg#ifdef HAVE_DRI1 612428d7b3dSmrg /* Load the dri module if requested. */ 613428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) { 614428d7b3dSmrg xf86LoadSubModule(scrn, "dri"); 615428d7b3dSmrg } 616428d7b3dSmrg#endif 617428d7b3dSmrg 618428d7b3dSmrg return TRUE; 619428d7b3dSmrg} 620428d7b3dSmrg 621428d7b3dSmrgstatic Bool 622428d7b3dSmrgI810MapMMIO(ScrnInfoPtr scrn) 623428d7b3dSmrg{ 624428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 625428d7b3dSmrg struct pci_device *const device = pI810->PciInfo; 626428d7b3dSmrg int err; 627428d7b3dSmrg 628428d7b3dSmrg err = pci_device_map_range (device, 629428d7b3dSmrg pI810->MMIOAddr, 630428d7b3dSmrg I810_REG_SIZE, 631428d7b3dSmrg PCI_DEV_MAP_FLAG_WRITABLE, 632428d7b3dSmrg (void **) &pI810->MMIOBase); 633428d7b3dSmrg if (err) 634428d7b3dSmrg { 635428d7b3dSmrg xf86DrvMsg (scrn->scrnIndex, X_ERROR, 636428d7b3dSmrg "Unable to map mmio BAR. %s (%d)\n", 637428d7b3dSmrg strerror (err), err); 638428d7b3dSmrg return FALSE; 639428d7b3dSmrg } 640428d7b3dSmrg return TRUE; 641428d7b3dSmrg} 642428d7b3dSmrg 643428d7b3dSmrgstatic Bool 644428d7b3dSmrgI810MapMem(ScrnInfoPtr scrn) 645428d7b3dSmrg{ 646428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 647428d7b3dSmrg struct pci_device *const device = pI810->PciInfo; 648428d7b3dSmrg int err; 649428d7b3dSmrg 650428d7b3dSmrg if (!I810MapMMIO(scrn)) 651428d7b3dSmrg return FALSE; 652428d7b3dSmrg 653428d7b3dSmrg err = pci_device_map_range (device, 654428d7b3dSmrg pI810->LinearAddr, 655428d7b3dSmrg pI810->FbMapSize, 656428d7b3dSmrg PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, 657428d7b3dSmrg (void **) &pI810->FbBase); 658428d7b3dSmrg if (err) 659428d7b3dSmrg { 660428d7b3dSmrg xf86DrvMsg (scrn->scrnIndex, X_ERROR, 661428d7b3dSmrg "Unable to map frame buffer BAR. %s (%d)\n", 662428d7b3dSmrg strerror (err), err); 663428d7b3dSmrg return FALSE; 664428d7b3dSmrg } 665428d7b3dSmrg 666428d7b3dSmrg pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; 667428d7b3dSmrg 668428d7b3dSmrg return TRUE; 669428d7b3dSmrg} 670428d7b3dSmrg 671428d7b3dSmrgstatic void 672428d7b3dSmrgI810UnmapMMIO(ScrnInfoPtr scrn) 673428d7b3dSmrg{ 674428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 675428d7b3dSmrg 676428d7b3dSmrg pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE); 677428d7b3dSmrg pI810->MMIOBase = NULL; 678428d7b3dSmrg} 679428d7b3dSmrg 680428d7b3dSmrgstatic Bool 681428d7b3dSmrgI810UnmapMem(ScrnInfoPtr scrn) 682428d7b3dSmrg{ 683428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 684428d7b3dSmrg 685428d7b3dSmrg pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize); 686428d7b3dSmrg pI810->FbBase = NULL; 687428d7b3dSmrg I810UnmapMMIO(scrn); 688428d7b3dSmrg return TRUE; 689428d7b3dSmrg} 690428d7b3dSmrg 691428d7b3dSmrg/* Famous last words 692428d7b3dSmrg */ 693428d7b3dSmrgvoid 694428d7b3dSmrgI810PrintErrorState(ScrnInfoPtr scrn) 695428d7b3dSmrg{ 696428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 697428d7b3dSmrg 698428d7b3dSmrg ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", 699428d7b3dSmrg (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR)); 700428d7b3dSmrg 701428d7b3dSmrg ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR), 702428d7b3dSmrg (unsigned long) INREG(IPEHR)); 703428d7b3dSmrg 704428d7b3dSmrg ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", 705428d7b3dSmrg (unsigned long) INREG(LP_RING + RING_TAIL), 706428d7b3dSmrg (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR, 707428d7b3dSmrg (unsigned long) INREG(LP_RING + RING_LEN), 708428d7b3dSmrg (unsigned long) INREG(LP_RING + RING_START)); 709428d7b3dSmrg 710428d7b3dSmrg ErrorF("eir: %x esr: %x emr: %x\n", 711428d7b3dSmrg INREG16(EIR), INREG16(ESR), INREG16(EMR)); 712428d7b3dSmrg 713428d7b3dSmrg ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); 714428d7b3dSmrg 715428d7b3dSmrg ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE), 716428d7b3dSmrg (unsigned long) INREG(INST_PS)); 717428d7b3dSmrg 718428d7b3dSmrg ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", 719428d7b3dSmrg INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); 720428d7b3dSmrg} 721428d7b3dSmrg 722428d7b3dSmrg/* 723428d7b3dSmrg * I810Save -- 724428d7b3dSmrg * 725428d7b3dSmrg * This function saves the video state. It reads all of the SVGA registers 726428d7b3dSmrg * into the vgaI810Rec data structure. There is in general no need to 727428d7b3dSmrg * mask out bits here - just read the registers. 728428d7b3dSmrg */ 729428d7b3dSmrgstatic void 730428d7b3dSmrgDoSave(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, 731428d7b3dSmrg Bool saveFonts) 732428d7b3dSmrg{ 733428d7b3dSmrg I810Ptr pI810; 734428d7b3dSmrg vgaHWPtr hwp; 735428d7b3dSmrg int i; 736428d7b3dSmrg 737428d7b3dSmrg pI810 = I810PTR(scrn); 738428d7b3dSmrg hwp = VGAHWPTR(scrn); 739428d7b3dSmrg 740428d7b3dSmrg /* 741428d7b3dSmrg * This function will handle creating the data structure and filling 742428d7b3dSmrg * in the generic VGA portion. 743428d7b3dSmrg */ 744428d7b3dSmrg if (saveFonts) 745428d7b3dSmrg vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP); 746428d7b3dSmrg else 747428d7b3dSmrg vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 748428d7b3dSmrg 749428d7b3dSmrg /* 750428d7b3dSmrg * The port I/O code necessary to read in the extended registers 751428d7b3dSmrg * into the fields of the vgaI810Rec structure goes here. 752428d7b3dSmrg */ 753428d7b3dSmrg i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL); 754428d7b3dSmrg i810Reg->AddressMapping = hwp->readGr(hwp, ADDRESS_MAPPING); 755428d7b3dSmrg i810Reg->BitBLTControl = INREG8(BITBLT_CNTL); 756428d7b3dSmrg i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M); 757428d7b3dSmrg i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N); 758428d7b3dSmrg i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL); 759428d7b3dSmrg 760428d7b3dSmrg i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL); 761428d7b3dSmrg i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY); 762428d7b3dSmrg i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START); 763428d7b3dSmrg i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START); 764428d7b3dSmrg i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL); 765428d7b3dSmrg i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK); 766428d7b3dSmrg i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET); 767428d7b3dSmrg i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL); 768428d7b3dSmrg 769428d7b3dSmrg i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0); 770428d7b3dSmrg i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1); 771428d7b3dSmrg i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2); 772428d7b3dSmrg i810Reg->DisplayControl = INREG8(DISPLAY_CNTL); 773428d7b3dSmrg i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC); 774428d7b3dSmrg 775428d7b3dSmrg for (i = 0; i < 8; i++) 776428d7b3dSmrg i810Reg->Fence[i] = INREG(FENCE + i * 4); 777428d7b3dSmrg 778428d7b3dSmrg i810Reg->LprbTail = INREG(LP_RING + RING_TAIL); 779428d7b3dSmrg i810Reg->LprbHead = INREG(LP_RING + RING_HEAD); 780428d7b3dSmrg i810Reg->LprbStart = INREG(LP_RING + RING_START); 781428d7b3dSmrg i810Reg->LprbLen = INREG(LP_RING + RING_LEN); 782428d7b3dSmrg 783428d7b3dSmrg if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) && 784428d7b3dSmrg i810Reg->LprbLen & RING_VALID) { 785428d7b3dSmrg I810PrintErrorState(scrn); 786428d7b3dSmrg FatalError("Active ring not flushed\n"); 787428d7b3dSmrg } 788428d7b3dSmrg} 789428d7b3dSmrg 790428d7b3dSmrgstatic void 791428d7b3dSmrgI810Save(ScrnInfoPtr scrn) 792428d7b3dSmrg{ 793428d7b3dSmrg vgaHWPtr hwp; 794428d7b3dSmrg I810Ptr pI810; 795428d7b3dSmrg uint32_t temp; 796428d7b3dSmrg 797428d7b3dSmrg hwp = VGAHWPTR(scrn); 798428d7b3dSmrg pI810 = I810PTR(scrn); 799428d7b3dSmrg DoSave(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); 800428d7b3dSmrg 801428d7b3dSmrg temp = INREG(MEMMODE); 802428d7b3dSmrg temp |= 4; 803428d7b3dSmrg OUTREG(MEMMODE, temp); 804428d7b3dSmrg} 805428d7b3dSmrg 806428d7b3dSmrgstatic void 807428d7b3dSmrgi810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode) 808428d7b3dSmrg{ 809428d7b3dSmrg int i; 810428d7b3dSmrg 811428d7b3dSmrg ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg); 812428d7b3dSmrg 813428d7b3dSmrg ErrorF("SEQ: "); 814428d7b3dSmrg for (i = 0; i < vgaReg->numSequencer; i++) { 815428d7b3dSmrg if ((i & 7) == 0) 816428d7b3dSmrg ErrorF("\n"); 817428d7b3dSmrg ErrorF(" %d: %x", i, vgaReg->Sequencer[i]); 818428d7b3dSmrg } 819428d7b3dSmrg ErrorF("\n"); 820428d7b3dSmrg 821428d7b3dSmrg ErrorF("CRTC: "); 822428d7b3dSmrg for (i = 0; i < vgaReg->numCRTC; i++) { 823428d7b3dSmrg if ((i & 3) == 0) 824428d7b3dSmrg ErrorF("\n"); 825428d7b3dSmrg ErrorF(" %d: %x", i, vgaReg->CRTC[i]); 826428d7b3dSmrg } 827428d7b3dSmrg ErrorF("\n"); 828428d7b3dSmrg 829428d7b3dSmrg ErrorF("GFX: "); 830428d7b3dSmrg for (i = 0; i < vgaReg->numGraphics; i++) { 831428d7b3dSmrg if ((i & 7) == 0) 832428d7b3dSmrg ErrorF("\n"); 833428d7b3dSmrg ErrorF(" %d: %x", i, vgaReg->Graphics[i]); 834428d7b3dSmrg } 835428d7b3dSmrg ErrorF("\n"); 836428d7b3dSmrg 837428d7b3dSmrg ErrorF("ATTR: "); 838428d7b3dSmrg for (i = 0; i < vgaReg->numAttribute; i++) { 839428d7b3dSmrg if ((i & 7) == 0) 840428d7b3dSmrg ErrorF("\n"); 841428d7b3dSmrg ErrorF(" %d: %x", i, vgaReg->Attribute[i]); 842428d7b3dSmrg } 843428d7b3dSmrg ErrorF("\n"); 844428d7b3dSmrg 845428d7b3dSmrg ErrorF(" DisplayControl: %x\n", mode->DisplayControl); 846428d7b3dSmrg ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0); 847428d7b3dSmrg ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1); 848428d7b3dSmrg ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2); 849428d7b3dSmrg ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M); 850428d7b3dSmrg ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N); 851428d7b3dSmrg ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel); 852428d7b3dSmrg ErrorF(" AddressMapping: %x\n", mode->AddressMapping); 853428d7b3dSmrg ErrorF(" IOControl: %x\n", mode->IOControl); 854428d7b3dSmrg ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl); 855428d7b3dSmrg ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal); 856428d7b3dSmrg ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd); 857428d7b3dSmrg ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart); 858428d7b3dSmrg ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart); 859428d7b3dSmrg ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal); 860428d7b3dSmrg ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank); 861428d7b3dSmrg ErrorF(" ExtOffset: %x\n", mode->ExtOffset); 862428d7b3dSmrg ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl); 863428d7b3dSmrg ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark); 864428d7b3dSmrg ErrorF(" LprbTail: %x\n", mode->LprbTail); 865428d7b3dSmrg ErrorF(" LprbHead: %x\n", mode->LprbHead); 866428d7b3dSmrg ErrorF(" LprbStart: %x\n", mode->LprbStart); 867428d7b3dSmrg ErrorF(" LprbLen: %x\n", mode->LprbLen); 868428d7b3dSmrg} 869428d7b3dSmrg 870428d7b3dSmrgstatic void 871428d7b3dSmrgDoRestore(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, 872428d7b3dSmrg Bool restoreFonts) 873428d7b3dSmrg{ 874428d7b3dSmrg I810Ptr pI810; 875428d7b3dSmrg vgaHWPtr hwp; 876428d7b3dSmrg unsigned char temp; 877428d7b3dSmrg unsigned int itemp; 878428d7b3dSmrg int i; 879428d7b3dSmrg 880428d7b3dSmrg pI810 = I810PTR(scrn); 881428d7b3dSmrg hwp = VGAHWPTR(scrn); 882428d7b3dSmrg 883428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_VGA) { 884428d7b3dSmrg ErrorF("Setting mode in I810Restore:\n"); 885428d7b3dSmrg i810PrintMode(vgaReg, i810Reg); 886428d7b3dSmrg } 887428d7b3dSmrg 888428d7b3dSmrg vgaHWProtect(scrn, TRUE); 889428d7b3dSmrg 890428d7b3dSmrg usleep(50000); 891428d7b3dSmrg 892428d7b3dSmrg /* Turn off DRAM Refresh */ 893428d7b3dSmrg temp = INREG8(DRAM_ROW_CNTL_HI); 894428d7b3dSmrg temp &= ~DRAM_REFRESH_RATE; 895428d7b3dSmrg temp |= DRAM_REFRESH_DISABLE; 896428d7b3dSmrg OUTREG8(DRAM_ROW_CNTL_HI, temp); 897428d7b3dSmrg 898428d7b3dSmrg usleep(1000); /* Wait 1 ms */ 899428d7b3dSmrg 900428d7b3dSmrg /* Write the M, N and P values */ 901428d7b3dSmrg OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M); 902428d7b3dSmrg OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N); 903428d7b3dSmrg OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel); 904428d7b3dSmrg 905428d7b3dSmrg /* 906428d7b3dSmrg * Turn on 8 bit dac mode, if requested. This is needed to make 907428d7b3dSmrg * sure that vgaHWRestore writes the values into the DAC properly. 908428d7b3dSmrg * The problem occurs if 8 bit dac mode is requested and the HW is 909428d7b3dSmrg * in 6 bit dac mode. If this happens, all the values are 910428d7b3dSmrg * automatically shifted left twice by the HW and incorrect colors 911428d7b3dSmrg * will be displayed on the screen. The only time this can happen 912428d7b3dSmrg * is at server startup time and when switching back from a VT. 913428d7b3dSmrg */ 914428d7b3dSmrg temp = INREG8(PIXPIPE_CONFIG_0); 915428d7b3dSmrg temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ 916428d7b3dSmrg temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT); 917428d7b3dSmrg OUTREG8(PIXPIPE_CONFIG_0, temp); 918428d7b3dSmrg 919428d7b3dSmrg /* 920428d7b3dSmrg * Code to restore any SVGA registers that have been saved/modified 921428d7b3dSmrg * goes here. Note that it is allowable, and often correct, to 922428d7b3dSmrg * only modify certain bits in a register by a read/modify/write cycle. 923428d7b3dSmrg * 924428d7b3dSmrg * A special case - when using an external clock-setting program, 925428d7b3dSmrg * this function must not change bits associated with the clock 926428d7b3dSmrg * selection. This condition can be checked by the condition: 927428d7b3dSmrg * 928428d7b3dSmrg * if (i810Reg->std.NoClock >= 0) 929428d7b3dSmrg * restore clock-select bits. 930428d7b3dSmrg */ 931428d7b3dSmrg if (restoreFonts) 932428d7b3dSmrg vgaHWRestore(scrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); 933428d7b3dSmrg else 934428d7b3dSmrg vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 935428d7b3dSmrg 936428d7b3dSmrg hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal); 937428d7b3dSmrg hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd); 938428d7b3dSmrg hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart); 939428d7b3dSmrg hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart); 940428d7b3dSmrg hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal); 941428d7b3dSmrg hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank); 942428d7b3dSmrg hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset); 943428d7b3dSmrg 944428d7b3dSmrg temp = hwp->readCrtc(hwp, INTERLACE_CNTL); 945428d7b3dSmrg temp &= ~INTERLACE_ENABLE; 946428d7b3dSmrg temp |= i810Reg->InterlaceControl; 947428d7b3dSmrg hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); 948428d7b3dSmrg 949428d7b3dSmrg temp = hwp->readGr(hwp, ADDRESS_MAPPING); 950428d7b3dSmrg temp &= 0xE0; /* Save reserved bits 7:5 */ 951428d7b3dSmrg temp |= i810Reg->AddressMapping; 952428d7b3dSmrg hwp->writeGr(hwp, ADDRESS_MAPPING, temp); 953428d7b3dSmrg 954428d7b3dSmrg /* Setting the OVRACT Register for video overlay */ 955428d7b3dSmrg { 956428d7b3dSmrg uint32_t LCD_TV_Control = INREG(LCD_TV_C); 957428d7b3dSmrg uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL); 958428d7b3dSmrg uint32_t ActiveStart, ActiveEnd; 959428d7b3dSmrg 960428d7b3dSmrg if((LCD_TV_Control & LCD_TV_ENABLE) 961428d7b3dSmrg && !(LCD_TV_Control & LCD_TV_VGAMOD) 962428d7b3dSmrg && TV_HTotal) { 963428d7b3dSmrg ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31; 964428d7b3dSmrg ActiveEnd = (TV_HTotal & 0x3ff) - 31; 965428d7b3dSmrg } else { 966428d7b3dSmrg ActiveStart = i810Reg->OverlayActiveStart; 967428d7b3dSmrg ActiveEnd = i810Reg->OverlayActiveEnd; 968428d7b3dSmrg } 969428d7b3dSmrg OUTREG(LCD_TV_OVRACT, 970428d7b3dSmrg (ActiveEnd << 16) | ActiveStart); 971428d7b3dSmrg } 972428d7b3dSmrg 973428d7b3dSmrg /* Turn on DRAM Refresh */ 974428d7b3dSmrg temp = INREG8(DRAM_ROW_CNTL_HI); 975428d7b3dSmrg temp &= ~DRAM_REFRESH_RATE; 976428d7b3dSmrg temp |= DRAM_REFRESH_60HZ; 977428d7b3dSmrg OUTREG8(DRAM_ROW_CNTL_HI, temp); 978428d7b3dSmrg 979428d7b3dSmrg temp = INREG8(BITBLT_CNTL); 980428d7b3dSmrg temp &= ~COLEXP_MODE; 981428d7b3dSmrg temp |= i810Reg->BitBLTControl; 982428d7b3dSmrg OUTREG8(BITBLT_CNTL, temp); 983428d7b3dSmrg 984428d7b3dSmrg temp = INREG8(DISPLAY_CNTL); 985428d7b3dSmrg temp &= ~(VGA_WRAP_MODE | GUI_MODE); 986428d7b3dSmrg temp |= i810Reg->DisplayControl; 987428d7b3dSmrg OUTREG8(DISPLAY_CNTL, temp); 988428d7b3dSmrg 989428d7b3dSmrg temp = INREG8(PIXPIPE_CONFIG_0); 990428d7b3dSmrg temp &= 0x64; /* Save reserved bits 6:5,2 */ 991428d7b3dSmrg temp |= i810Reg->PixelPipeCfg0; 992428d7b3dSmrg OUTREG8(PIXPIPE_CONFIG_0, temp); 993428d7b3dSmrg 994428d7b3dSmrg temp = INREG8(PIXPIPE_CONFIG_2); 995428d7b3dSmrg temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ 996428d7b3dSmrg temp |= i810Reg->PixelPipeCfg2; 997428d7b3dSmrg OUTREG8(PIXPIPE_CONFIG_2, temp); 998428d7b3dSmrg 999428d7b3dSmrg temp = INREG8(PIXPIPE_CONFIG_1); 1000428d7b3dSmrg temp &= ~DISPLAY_COLOR_MODE; 1001428d7b3dSmrg temp &= 0xEF; /* Restore the CRT control bit */ 1002428d7b3dSmrg temp |= i810Reg->PixelPipeCfg1; 1003428d7b3dSmrg OUTREG8(PIXPIPE_CONFIG_1, temp); 1004428d7b3dSmrg 1005428d7b3dSmrg OUTREG16(EIR, 0); 1006428d7b3dSmrg 1007428d7b3dSmrg itemp = INREG(FWATER_BLC); 1008428d7b3dSmrg itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK | 1009428d7b3dSmrg MM_BURST_LENGTH | MM_FIFO_WATERMARK); 1010428d7b3dSmrg itemp |= i810Reg->LMI_FIFO_Watermark; 1011428d7b3dSmrg OUTREG(FWATER_BLC, itemp); 1012428d7b3dSmrg 1013428d7b3dSmrg for (i = 0; i < 8; i++) { 1014428d7b3dSmrg OUTREG(FENCE + i * 4, i810Reg->Fence[i]); 1015428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_VGA) 1016428d7b3dSmrg ErrorF("Fence Register : %x\n", i810Reg->Fence[i]); 1017428d7b3dSmrg } 1018428d7b3dSmrg 1019428d7b3dSmrg /* First disable the ring buffer (Need to wait for empty first?, if so 1020428d7b3dSmrg * should probably do it before entering this section) 1021428d7b3dSmrg */ 1022428d7b3dSmrg itemp = INREG(LP_RING + RING_LEN); 1023428d7b3dSmrg itemp &= ~RING_VALID_MASK; 1024428d7b3dSmrg OUTREG(LP_RING + RING_LEN, itemp); 1025428d7b3dSmrg 1026428d7b3dSmrg /* Set up the low priority ring buffer. 1027428d7b3dSmrg */ 1028428d7b3dSmrg OUTREG(LP_RING + RING_TAIL, 0); 1029428d7b3dSmrg OUTREG(LP_RING + RING_HEAD, 0); 1030428d7b3dSmrg 1031428d7b3dSmrg pI810->LpRing->head = 0; 1032428d7b3dSmrg pI810->LpRing->tail = 0; 1033428d7b3dSmrg 1034428d7b3dSmrg itemp = INREG(LP_RING + RING_START); 1035428d7b3dSmrg itemp &= ~(START_ADDR); 1036428d7b3dSmrg itemp |= i810Reg->LprbStart; 1037428d7b3dSmrg OUTREG(LP_RING + RING_START, itemp); 1038428d7b3dSmrg 1039428d7b3dSmrg itemp = INREG(LP_RING + RING_LEN); 1040428d7b3dSmrg itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); 1041428d7b3dSmrg itemp |= i810Reg->LprbLen; 1042428d7b3dSmrg OUTREG(LP_RING + RING_LEN, itemp); 1043428d7b3dSmrg 1044428d7b3dSmrg if (!(vgaReg->Attribute[0x10] & 0x1)) { 1045428d7b3dSmrg usleep(50000); 1046428d7b3dSmrg if (restoreFonts) 1047428d7b3dSmrg vgaHWRestore(scrn, vgaReg, 1048428d7b3dSmrg VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); 1049428d7b3dSmrg else 1050428d7b3dSmrg vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 1051428d7b3dSmrg } 1052428d7b3dSmrg 1053428d7b3dSmrg vgaHWProtect(scrn, FALSE); 1054428d7b3dSmrg 1055428d7b3dSmrg temp = hwp->readCrtc(hwp, IO_CTNL); 1056428d7b3dSmrg temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL); 1057428d7b3dSmrg temp |= i810Reg->IOControl; 1058428d7b3dSmrg hwp->writeCrtc(hwp, IO_CTNL, temp); 1059428d7b3dSmrg} 1060428d7b3dSmrg 1061428d7b3dSmrgstatic void 1062428d7b3dSmrgI810SetRingRegs(ScrnInfoPtr scrn) 1063428d7b3dSmrg{ 1064428d7b3dSmrg unsigned int itemp; 1065428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1066428d7b3dSmrg 1067428d7b3dSmrg OUTREG(LP_RING + RING_TAIL, 0); 1068428d7b3dSmrg OUTREG(LP_RING + RING_HEAD, 0); 1069428d7b3dSmrg 1070428d7b3dSmrg itemp = INREG(LP_RING + RING_START); 1071428d7b3dSmrg itemp &= ~(START_ADDR); 1072428d7b3dSmrg itemp |= pI810->LpRing->mem.Start; 1073428d7b3dSmrg OUTREG(LP_RING + RING_START, itemp); 1074428d7b3dSmrg 1075428d7b3dSmrg itemp = INREG(LP_RING + RING_LEN); 1076428d7b3dSmrg itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); 1077428d7b3dSmrg itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID); 1078428d7b3dSmrg OUTREG(LP_RING + RING_LEN, itemp); 1079428d7b3dSmrg} 1080428d7b3dSmrg 1081428d7b3dSmrgstatic void 1082428d7b3dSmrgI810Restore(ScrnInfoPtr scrn) 1083428d7b3dSmrg{ 1084428d7b3dSmrg vgaHWPtr hwp; 1085428d7b3dSmrg I810Ptr pI810; 1086428d7b3dSmrg 1087428d7b3dSmrg hwp = VGAHWPTR(scrn); 1088428d7b3dSmrg pI810 = I810PTR(scrn); 1089428d7b3dSmrg 1090428d7b3dSmrg DoRestore(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); 1091428d7b3dSmrg} 1092428d7b3dSmrg 1093428d7b3dSmrg/* 1094428d7b3dSmrg * I810CalcVCLK -- 1095428d7b3dSmrg * 1096428d7b3dSmrg * Determine the closest clock frequency to the one requested. 1097428d7b3dSmrg */ 1098428d7b3dSmrg 1099428d7b3dSmrg#define MAX_VCO_FREQ 600.0 1100428d7b3dSmrg#define TARGET_MAX_N 30 1101428d7b3dSmrg#define REF_FREQ 24.0 1102428d7b3dSmrg 1103428d7b3dSmrg#define CALC_VCLK(m,n,p) \ 1104428d7b3dSmrg (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ 1105428d7b3dSmrg 1106428d7b3dSmrgstatic void 1107428d7b3dSmrgI810CalcVCLK(ScrnInfoPtr scrn, double freq) 1108428d7b3dSmrg{ 1109428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1110428d7b3dSmrg I810RegPtr i810Reg = &pI810->ModeReg; 1111428d7b3dSmrg int m, n, p; 1112428d7b3dSmrg double f_out; 1113428d7b3dSmrg double f_err; 1114428d7b3dSmrg double f_vco; 1115428d7b3dSmrg int m_best = 0, n_best = 0, p_best = 0; 1116428d7b3dSmrg double f_target = freq; 1117428d7b3dSmrg double err_max = 0.005; 1118428d7b3dSmrg double err_target = 0.001; 1119428d7b3dSmrg double err_best = 999999.0; 1120428d7b3dSmrg 1121428d7b3dSmrg p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2); 1122428d7b3dSmrg /* Make sure p is within range. */ 1123428d7b3dSmrg if (p_best > 5) { 1124428d7b3dSmrg p_best = p = 5; 1125428d7b3dSmrg } 1126428d7b3dSmrg 1127428d7b3dSmrg f_vco = f_target * (1 << p); 1128428d7b3dSmrg 1129428d7b3dSmrg n = 2; 1130428d7b3dSmrg do { 1131428d7b3dSmrg n++; 1132428d7b3dSmrg m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; 1133428d7b3dSmrg if (m < 3) 1134428d7b3dSmrg m = 3; 1135428d7b3dSmrg f_out = CALC_VCLK(m, n, p); 1136428d7b3dSmrg f_err = 1.0 - (f_target / f_out); 1137428d7b3dSmrg if (fabs(f_err) < err_max) { 1138428d7b3dSmrg m_best = m; 1139428d7b3dSmrg n_best = n; 1140428d7b3dSmrg err_best = f_err; 1141428d7b3dSmrg } 1142428d7b3dSmrg } while ((fabs(f_err) >= err_target) && 1143428d7b3dSmrg ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); 1144428d7b3dSmrg 1145428d7b3dSmrg if (fabs(f_err) < err_target) { 1146428d7b3dSmrg m_best = m; 1147428d7b3dSmrg n_best = n; 1148428d7b3dSmrg } 1149428d7b3dSmrg 1150428d7b3dSmrg i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF; 1151428d7b3dSmrg i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF; 1152428d7b3dSmrg i810Reg->VideoClk2_DivisorSel = (p_best << 4); 1153428d7b3dSmrg 1154428d7b3dSmrg xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, 3, 1155428d7b3dSmrg "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] " 1156428d7b3dSmrg "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best), 1157428d7b3dSmrg i810Reg->VideoClk2_M, i810Reg->VideoClk2_N, 1158428d7b3dSmrg i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best); 1159428d7b3dSmrg} 1160428d7b3dSmrg 1161428d7b3dSmrgstatic Bool 1162428d7b3dSmrgI810SetMode(ScrnInfoPtr scrn, DisplayModePtr mode) 1163428d7b3dSmrg{ 1164428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1165428d7b3dSmrg I810RegPtr i810Reg = &pI810->ModeReg; 1166428d7b3dSmrg vgaRegPtr pVga = &VGAHWPTR(scrn)->ModeReg; 1167428d7b3dSmrg double dclk = mode->Clock / 1000.0; 1168428d7b3dSmrg 1169428d7b3dSmrg switch (scrn->bitsPerPixel) { 1170428d7b3dSmrg case 8: 1171428d7b3dSmrg pVga->CRTC[0x13] = scrn->displayWidth >> 3; 1172428d7b3dSmrg i810Reg->ExtOffset = scrn->displayWidth >> 11; 1173428d7b3dSmrg i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE; 1174428d7b3dSmrg i810Reg->BitBLTControl = COLEXP_8BPP; 1175428d7b3dSmrg break; 1176428d7b3dSmrg case 16: 1177428d7b3dSmrg if (scrn->weight.green == 5) { 1178428d7b3dSmrg i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE; 1179428d7b3dSmrg } else { 1180428d7b3dSmrg i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE; 1181428d7b3dSmrg } 1182428d7b3dSmrg pVga->CRTC[0x13] = scrn->displayWidth >> 2; 1183428d7b3dSmrg i810Reg->ExtOffset = scrn->displayWidth >> 10; 1184428d7b3dSmrg i810Reg->BitBLTControl = COLEXP_16BPP; 1185428d7b3dSmrg 1186428d7b3dSmrg /* Enable Palette Programming for Direct Color visuals. -jens */ 1187428d7b3dSmrg i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; 1188428d7b3dSmrg break; 1189428d7b3dSmrg case 24: 1190428d7b3dSmrg pVga->CRTC[0x13] = (scrn->displayWidth * 3) >> 3; 1191428d7b3dSmrg i810Reg->ExtOffset = (scrn->displayWidth * 3) >> 11; 1192428d7b3dSmrg 1193428d7b3dSmrg i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE; 1194428d7b3dSmrg i810Reg->BitBLTControl = COLEXP_24BPP; 1195428d7b3dSmrg 1196428d7b3dSmrg /* Enable Palette Programming for Direct Color visuals. -jens */ 1197428d7b3dSmrg i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; 1198428d7b3dSmrg break; 1199428d7b3dSmrg default: 1200428d7b3dSmrg break; 1201428d7b3dSmrg } 1202428d7b3dSmrg 1203428d7b3dSmrg /* Turn on 8 bit dac if requested */ 1204428d7b3dSmrg if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) 1205428d7b3dSmrg i810Reg->PixelPipeCfg0 = DAC_6_BIT; 1206428d7b3dSmrg else 1207428d7b3dSmrg i810Reg->PixelPipeCfg0 = DAC_8_BIT; 1208428d7b3dSmrg 1209428d7b3dSmrg /* Do not delay CRT Blank: needed for video overlay */ 1210428d7b3dSmrg i810Reg->PixelPipeCfg1 |= 0x10; 1211428d7b3dSmrg 1212428d7b3dSmrg /* Turn on Extended VGA Interpretation */ 1213428d7b3dSmrg i810Reg->IOControl = EXTENDED_CRTC_CNTL; 1214428d7b3dSmrg 1215428d7b3dSmrg /* Turn on linear and page mapping */ 1216428d7b3dSmrg i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE); 1217428d7b3dSmrg 1218428d7b3dSmrg /* Turn on GUI mode */ 1219428d7b3dSmrg i810Reg->DisplayControl = HIRES_MODE; 1220428d7b3dSmrg 1221428d7b3dSmrg /* Calculate the extended CRTC regs */ 1222428d7b3dSmrg i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8; 1223428d7b3dSmrg i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8; 1224428d7b3dSmrg i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8; 1225428d7b3dSmrg i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8; 1226428d7b3dSmrg i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8; 1227428d7b3dSmrg i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6; 1228428d7b3dSmrg 1229428d7b3dSmrg /* 1230428d7b3dSmrg * the KGA fix in vgaHW.c results in the first 1231428d7b3dSmrg * scanline and the first character clock (8 pixels) 1232428d7b3dSmrg * of each scanline thereafter on display with an i810 1233428d7b3dSmrg * to be blank. Restoring CRTC 3, 5, & 22 to their 1234428d7b3dSmrg * "theoretical" values corrects the problem. KAO. 1235428d7b3dSmrg */ 1236428d7b3dSmrg pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; 1237428d7b3dSmrg pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) 1238428d7b3dSmrg | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); 1239428d7b3dSmrg pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1240428d7b3dSmrg 1241428d7b3dSmrg i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0); 1242428d7b3dSmrg vgaHWVBlankKGA(mode, pVga, 8, 0); 1243428d7b3dSmrg 1244428d7b3dSmrg /* 1245428d7b3dSmrg * The following workarounds are needed to get video overlay working 1246428d7b3dSmrg * at 1024x768 and 1280x1024 display resolutions. 1247428d7b3dSmrg */ 1248428d7b3dSmrg if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) { 1249428d7b3dSmrg i810Reg->ExtVertBlankStart = 2; 1250428d7b3dSmrg } 1251428d7b3dSmrg if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) { 1252428d7b3dSmrg i810Reg->ExtVertBlankStart = 3; 1253428d7b3dSmrg } 1254428d7b3dSmrg 1255428d7b3dSmrg /* OVRACT Register */ 1256428d7b3dSmrg i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32; 1257428d7b3dSmrg i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32; 1258428d7b3dSmrg 1259428d7b3dSmrg /* Turn on interlaced mode if necessary */ 1260428d7b3dSmrg if (mode->Flags & V_INTERLACE) { 1261428d7b3dSmrg i810Reg->InterlaceControl = INTERLACE_ENABLE; 1262428d7b3dSmrg i810Reg->ExtVertDispEnd *= 2; 1263428d7b3dSmrg } else 1264428d7b3dSmrg i810Reg->InterlaceControl = INTERLACE_DISABLE; 1265428d7b3dSmrg 1266428d7b3dSmrg /* 1267428d7b3dSmrg * Set the overscan color to 0. 1268428d7b3dSmrg * NOTE: This only affects >8bpp mode. 1269428d7b3dSmrg */ 1270428d7b3dSmrg pVga->Attribute[0x11] = 0; 1271428d7b3dSmrg 1272428d7b3dSmrg /* 1273428d7b3dSmrg * Calculate the VCLK that most closely matches the requested dot 1274428d7b3dSmrg * clock. 1275428d7b3dSmrg */ 1276428d7b3dSmrg I810CalcVCLK(scrn, dclk); 1277428d7b3dSmrg 1278428d7b3dSmrg /* Since we program the clocks ourselves, always use VCLK2. */ 1279428d7b3dSmrg pVga->MiscOutReg |= 0x0C; 1280428d7b3dSmrg 1281428d7b3dSmrg /* Calculate the FIFO Watermark and Burst Length. */ 1282428d7b3dSmrg i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(scrn, dclk, FALSE); 1283428d7b3dSmrg 1284428d7b3dSmrg /* Setup the ring buffer */ 1285428d7b3dSmrg i810Reg->LprbTail = 0; 1286428d7b3dSmrg i810Reg->LprbHead = 0; 1287428d7b3dSmrg i810Reg->LprbStart = pI810->LpRing->mem.Start; 1288428d7b3dSmrg 1289428d7b3dSmrg if (i810Reg->LprbStart) 1290428d7b3dSmrg i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) | 1291428d7b3dSmrg RING_NO_REPORT | RING_VALID); 1292428d7b3dSmrg else 1293428d7b3dSmrg i810Reg->LprbLen = RING_INVALID; 1294428d7b3dSmrg 1295428d7b3dSmrg return TRUE; 1296428d7b3dSmrg} 1297428d7b3dSmrg 1298428d7b3dSmrgstatic Bool 1299428d7b3dSmrgI810ModeInit(ScrnInfoPtr scrn, DisplayModePtr mode) 1300428d7b3dSmrg{ 1301428d7b3dSmrg vgaHWPtr hwp; 1302428d7b3dSmrg I810Ptr pI810; 1303428d7b3dSmrg 1304428d7b3dSmrg hwp = VGAHWPTR(scrn); 1305428d7b3dSmrg pI810 = I810PTR(scrn); 1306428d7b3dSmrg 1307428d7b3dSmrg vgaHWUnlock(hwp); 1308428d7b3dSmrg 1309428d7b3dSmrg if (!vgaHWInit(scrn, mode)) 1310428d7b3dSmrg return FALSE; 1311428d7b3dSmrg 1312428d7b3dSmrg scrn->vtSema = TRUE; 1313428d7b3dSmrg 1314428d7b3dSmrg if (!I810SetMode(scrn, mode)) 1315428d7b3dSmrg return FALSE; 1316428d7b3dSmrg 1317428d7b3dSmrg#ifdef HAVE_DRI1 1318428d7b3dSmrg if (pI810->directRenderingEnabled) { 1319428d7b3dSmrg DRILock(xf86ScrnToScreen(scrn), 0); 1320428d7b3dSmrg pI810->LockHeld = 1; 1321428d7b3dSmrg } 1322428d7b3dSmrg#endif 1323428d7b3dSmrg 1324428d7b3dSmrg DoRestore(scrn, &hwp->ModeReg, &pI810->ModeReg, FALSE); 1325428d7b3dSmrg 1326428d7b3dSmrg#ifdef HAVE_DRI1 1327428d7b3dSmrg if (pI810->directRenderingEnabled) { 1328428d7b3dSmrg DRIUnlock(xf86ScrnToScreen(scrn)); 1329428d7b3dSmrg pI810->LockHeld = 0; 1330428d7b3dSmrg } 1331428d7b3dSmrg#endif 1332428d7b3dSmrg 1333428d7b3dSmrg return TRUE; 1334428d7b3dSmrg} 1335428d7b3dSmrg 1336428d7b3dSmrgstatic void 1337428d7b3dSmrgI810LoadPalette15(ScrnInfoPtr scrn, int numColors, int *indices, 1338428d7b3dSmrg LOCO * colors, VisualPtr pVisual) 1339428d7b3dSmrg{ 1340428d7b3dSmrg vgaHWPtr hwp; 1341428d7b3dSmrg int i, j, index; 1342428d7b3dSmrg unsigned char r, g, b; 1343428d7b3dSmrg 1344428d7b3dSmrg hwp = VGAHWPTR(scrn); 1345428d7b3dSmrg 1346428d7b3dSmrg for (i = 0; i < numColors; i++) { 1347428d7b3dSmrg index = indices[i]; 1348428d7b3dSmrg r = colors[index].red; 1349428d7b3dSmrg g = colors[index].green; 1350428d7b3dSmrg b = colors[index].blue; 1351428d7b3dSmrg for (j = 0; j < 8; j++) { 1352428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 3) + j); 1353428d7b3dSmrg hwp->writeDacData(hwp, r); 1354428d7b3dSmrg hwp->writeDacData(hwp, g); 1355428d7b3dSmrg hwp->writeDacData(hwp, b); 1356428d7b3dSmrg } 1357428d7b3dSmrg } 1358428d7b3dSmrg} 1359428d7b3dSmrg 1360428d7b3dSmrgstatic void 1361428d7b3dSmrgI810LoadPalette16(ScrnInfoPtr scrn, int numColors, int *indices, 1362428d7b3dSmrg LOCO * colors, VisualPtr pVisual) 1363428d7b3dSmrg{ 1364428d7b3dSmrg vgaHWPtr hwp; 1365428d7b3dSmrg int i, index; 1366428d7b3dSmrg unsigned char r, g, b; 1367428d7b3dSmrg 1368428d7b3dSmrg hwp = VGAHWPTR(scrn); 1369428d7b3dSmrg 1370428d7b3dSmrg /* Load all four entries in each of the 64 color ranges. -jens */ 1371428d7b3dSmrg for (i = 0; i < numColors; i++) { 1372428d7b3dSmrg index = indices[i / 2]; 1373428d7b3dSmrg r = colors[index].red; 1374428d7b3dSmrg b = colors[index].blue; 1375428d7b3dSmrg index = indices[i]; 1376428d7b3dSmrg g = colors[index].green; 1377428d7b3dSmrg 1378428d7b3dSmrg hwp->writeDacWriteAddr(hwp, index << 2); 1379428d7b3dSmrg hwp->writeDacData(hwp, r); 1380428d7b3dSmrg hwp->writeDacData(hwp, g); 1381428d7b3dSmrg hwp->writeDacData(hwp, b); 1382428d7b3dSmrg 1383428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 2) + 1); 1384428d7b3dSmrg hwp->writeDacData(hwp, r); 1385428d7b3dSmrg hwp->writeDacData(hwp, g); 1386428d7b3dSmrg hwp->writeDacData(hwp, b); 1387428d7b3dSmrg 1388428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 2) + 2); 1389428d7b3dSmrg hwp->writeDacData(hwp, r); 1390428d7b3dSmrg hwp->writeDacData(hwp, g); 1391428d7b3dSmrg hwp->writeDacData(hwp, b); 1392428d7b3dSmrg 1393428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 2) + 3); 1394428d7b3dSmrg hwp->writeDacData(hwp, r); 1395428d7b3dSmrg hwp->writeDacData(hwp, g); 1396428d7b3dSmrg hwp->writeDacData(hwp, b); 1397428d7b3dSmrg 1398428d7b3dSmrg i++; 1399428d7b3dSmrg index = indices[i]; 1400428d7b3dSmrg g = colors[index].green; 1401428d7b3dSmrg 1402428d7b3dSmrg hwp->writeDacWriteAddr(hwp, index << 2); 1403428d7b3dSmrg hwp->writeDacData(hwp, r); 1404428d7b3dSmrg hwp->writeDacData(hwp, g); 1405428d7b3dSmrg hwp->writeDacData(hwp, b); 1406428d7b3dSmrg 1407428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 2) + 1); 1408428d7b3dSmrg hwp->writeDacData(hwp, r); 1409428d7b3dSmrg hwp->writeDacData(hwp, g); 1410428d7b3dSmrg hwp->writeDacData(hwp, b); 1411428d7b3dSmrg 1412428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 2) + 2); 1413428d7b3dSmrg hwp->writeDacData(hwp, r); 1414428d7b3dSmrg hwp->writeDacData(hwp, g); 1415428d7b3dSmrg hwp->writeDacData(hwp, b); 1416428d7b3dSmrg 1417428d7b3dSmrg hwp->writeDacWriteAddr(hwp, (index << 2) + 3); 1418428d7b3dSmrg hwp->writeDacData(hwp, r); 1419428d7b3dSmrg hwp->writeDacData(hwp, g); 1420428d7b3dSmrg hwp->writeDacData(hwp, b); 1421428d7b3dSmrg } 1422428d7b3dSmrg} 1423428d7b3dSmrg 1424428d7b3dSmrgstatic void 1425428d7b3dSmrgI810LoadPalette24(ScrnInfoPtr scrn, int numColors, int *indices, 1426428d7b3dSmrg LOCO * colors, VisualPtr pVisual) 1427428d7b3dSmrg{ 1428428d7b3dSmrg vgaHWPtr hwp; 1429428d7b3dSmrg int i, index; 1430428d7b3dSmrg unsigned char r, g, b; 1431428d7b3dSmrg 1432428d7b3dSmrg hwp = VGAHWPTR(scrn); 1433428d7b3dSmrg 1434428d7b3dSmrg for (i = 0; i < numColors; i++) { 1435428d7b3dSmrg index = indices[i]; 1436428d7b3dSmrg r = colors[index].red; 1437428d7b3dSmrg g = colors[index].green; 1438428d7b3dSmrg b = colors[index].blue; 1439428d7b3dSmrg hwp->writeDacWriteAddr(hwp, index); 1440428d7b3dSmrg hwp->writeDacData(hwp, r); 1441428d7b3dSmrg hwp->writeDacData(hwp, g); 1442428d7b3dSmrg hwp->writeDacData(hwp, b); 1443428d7b3dSmrg } 1444428d7b3dSmrg} 1445428d7b3dSmrg 1446428d7b3dSmrgBool 1447428d7b3dSmrgI810AllocateFront(ScrnInfoPtr scrn) 1448428d7b3dSmrg{ 1449428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1450428d7b3dSmrg int cache_lines = -1; 1451428d7b3dSmrg 1452428d7b3dSmrg if (pI810->DoneFrontAlloc) 1453428d7b3dSmrg return TRUE; 1454428d7b3dSmrg 1455428d7b3dSmrg memset(&(pI810->FbMemBox), 0, sizeof(BoxRec)); 1456428d7b3dSmrg /* Alloc FrontBuffer/Ring/Accel memory */ 1457428d7b3dSmrg pI810->FbMemBox.x1 = 0; 1458428d7b3dSmrg pI810->FbMemBox.x2 = scrn->displayWidth; 1459428d7b3dSmrg pI810->FbMemBox.y1 = 0; 1460428d7b3dSmrg pI810->FbMemBox.y2 = scrn->virtualY; 1461428d7b3dSmrg 1462428d7b3dSmrg xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines); 1463428d7b3dSmrg 1464428d7b3dSmrg if (cache_lines < 0) { 1465428d7b3dSmrg /* make sure there is enough for two DVD sized YUV buffers */ 1466428d7b3dSmrg cache_lines = (scrn->depth == 24) ? 256 : 384; 1467428d7b3dSmrg if (scrn->displayWidth <= 1024) 1468428d7b3dSmrg cache_lines *= 2; 1469428d7b3dSmrg } 1470428d7b3dSmrg /* Make sure there's enough space for cache_lines. 1471428d7b3dSmrg * 1472428d7b3dSmrg * Had a bug here where maxCacheLines was computed to be less than 0. 1473428d7b3dSmrg * Not sure why 256 was initially subtracted from videoRam in the 1474428d7b3dSmrg * maxCacheLines calculation, but that was causing a problem 1475428d7b3dSmrg * for configurations that have exactly enough Ram for the framebuffer. 1476428d7b3dSmrg * Common code should catch the case where there isn't enough space for 1477428d7b3dSmrg * framebuffer, we'll just check for no space for cache_lines. -jens 1478428d7b3dSmrg * 1479428d7b3dSmrg */ 1480428d7b3dSmrg { 1481428d7b3dSmrg int maxCacheLines; 1482428d7b3dSmrg 1483428d7b3dSmrg maxCacheLines = (scrn->videoRam * 1024 / 1484428d7b3dSmrg (scrn->bitsPerPixel / 8) / 1485428d7b3dSmrg scrn->displayWidth) - scrn->virtualY; 1486428d7b3dSmrg if (maxCacheLines < 0) 1487428d7b3dSmrg maxCacheLines = 0; 1488428d7b3dSmrg if (cache_lines > maxCacheLines) 1489428d7b3dSmrg cache_lines = maxCacheLines; 1490428d7b3dSmrg } 1491428d7b3dSmrg pI810->FbMemBox.y2 += cache_lines; 1492428d7b3dSmrg 1493428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, 1494428d7b3dSmrg "Adding %i scanlines for pixmap caching\n", cache_lines); 1495428d7b3dSmrg 1496428d7b3dSmrg /* Reserve room for the framebuffer and pixcache. Put at the top 1497428d7b3dSmrg * of memory so we can have nice alignment for the tiled regions at 1498428d7b3dSmrg * the start of memory. 1499428d7b3dSmrg */ 1500428d7b3dSmrg 1501428d7b3dSmrg if (!I810AllocLow(&(pI810->FrontBuffer), 1502428d7b3dSmrg &(pI810->SysMem), 1503428d7b3dSmrg ALIGN((pI810->FbMemBox.x2 * pI810->FbMemBox.y2 * pI810->cpp), 4096))) { 1504428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, 1505428d7b3dSmrg X_WARNING, "Framebuffer allocation failed\n"); 1506428d7b3dSmrg return FALSE; 1507428d7b3dSmrg } 1508428d7b3dSmrg 1509428d7b3dSmrg memset(pI810->LpRing, 0, sizeof(I810RingBuffer)); 1510428d7b3dSmrg if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) { 1511428d7b3dSmrg pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1; 1512428d7b3dSmrg pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; 1513428d7b3dSmrg pI810->LpRing->head = 0; 1514428d7b3dSmrg pI810->LpRing->tail = 0; 1515428d7b3dSmrg pI810->LpRing->space = 0; 1516428d7b3dSmrg } else { 1517428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1518428d7b3dSmrg "Ring buffer allocation failed\n"); 1519428d7b3dSmrg return (FALSE); 1520428d7b3dSmrg } 1521428d7b3dSmrg 1522428d7b3dSmrg if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) || 1523428d7b3dSmrg I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) { 1524428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n"); 1525428d7b3dSmrg } else { 1526428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1527428d7b3dSmrg "Scratch memory allocation failed\n"); 1528428d7b3dSmrg return (FALSE); 1529428d7b3dSmrg } 1530428d7b3dSmrg 1531428d7b3dSmrg pI810->DoneFrontAlloc = TRUE; 1532428d7b3dSmrg return TRUE; 1533428d7b3dSmrg} 1534428d7b3dSmrg 1535428d7b3dSmrgstatic Bool 1536428d7b3dSmrgI810ScreenInit(SCREEN_INIT_ARGS_DECL) 1537428d7b3dSmrg{ 1538428d7b3dSmrg ScrnInfoPtr scrn; 1539428d7b3dSmrg vgaHWPtr hwp; 1540428d7b3dSmrg I810Ptr pI810; 1541428d7b3dSmrg VisualPtr visual; 1542428d7b3dSmrg 1543428d7b3dSmrg scrn = xf86ScreenToScrn(screen); 1544428d7b3dSmrg pI810 = I810PTR(scrn); 1545428d7b3dSmrg hwp = VGAHWPTR(scrn); 1546428d7b3dSmrg 1547428d7b3dSmrg pI810->LpRing = calloc(sizeof(I810RingBuffer),1); 1548428d7b3dSmrg if (!pI810->LpRing) { 1549428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1550428d7b3dSmrg "Could not allocate lpring data structure.\n"); 1551428d7b3dSmrg return FALSE; 1552428d7b3dSmrg } 1553428d7b3dSmrg 1554428d7b3dSmrg miClearVisualTypes(); 1555428d7b3dSmrg 1556428d7b3dSmrg /* Re-implemented Direct Color support, -jens */ 1557428d7b3dSmrg if (!miSetVisualTypes(scrn->depth, miGetDefaultVisualMask(scrn->depth), 1558428d7b3dSmrg scrn->rgbBits, scrn->defaultVisual)) 1559428d7b3dSmrg return FALSE; 1560428d7b3dSmrg 1561428d7b3dSmrg if (!miSetPixmapDepths()) 1562428d7b3dSmrg return FALSE; 1563428d7b3dSmrg 1564428d7b3dSmrg { 1565428d7b3dSmrg I810RegPtr i810Reg = &pI810->ModeReg; 1566428d7b3dSmrg int i; 1567428d7b3dSmrg 1568428d7b3dSmrg for (i = 0; i < 8; i++) 1569428d7b3dSmrg i810Reg->Fence[i] = 0; 1570428d7b3dSmrg } 1571428d7b3dSmrg 1572428d7b3dSmrg /* Have to init the DRM earlier than in other drivers to get agp 1573428d7b3dSmrg * memory. Wonder if this is going to be a problem... 1574428d7b3dSmrg */ 1575428d7b3dSmrg 1576428d7b3dSmrg#ifdef HAVE_DRI1 1577428d7b3dSmrg /* 1578428d7b3dSmrg * Setup DRI after visuals have been established, but before fbScreenInit 1579428d7b3dSmrg * is called. fbScreenInit will eventually call into the drivers 1580428d7b3dSmrg * InitGLXVisuals call back. 1581428d7b3dSmrg */ 1582428d7b3dSmrg /* 1583428d7b3dSmrg * pI810->directRenderingDisabled is set once in PreInit. Reinitialise 1584428d7b3dSmrg * pI810->directRenderingEnabled based on it each generation. 1585428d7b3dSmrg */ 1586428d7b3dSmrg pI810->directRenderingEnabled = !pI810->directRenderingDisabled; 1587428d7b3dSmrg 1588428d7b3dSmrg if (pI810->directRenderingEnabled==TRUE) 1589428d7b3dSmrg pI810->directRenderingEnabled = I810DRIScreenInit(screen); 1590428d7b3dSmrg 1591428d7b3dSmrg#else 1592428d7b3dSmrg pI810->directRenderingEnabled = FALSE; 1593428d7b3dSmrg if (!I810AllocateGARTMemory(scrn)) 1594428d7b3dSmrg return FALSE; 1595428d7b3dSmrg if (!I810AllocateFront(scrn)) 1596428d7b3dSmrg return FALSE; 1597428d7b3dSmrg#endif 1598428d7b3dSmrg 1599428d7b3dSmrg if (!I810MapMem(scrn)) 1600428d7b3dSmrg return FALSE; 1601428d7b3dSmrg 1602428d7b3dSmrg scrn->memPhysBase = (unsigned long)pI810->LinearAddr; 1603428d7b3dSmrg scrn->fbOffset = 0; 1604428d7b3dSmrg 1605428d7b3dSmrg vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0); 1606428d7b3dSmrg vgaHWGetIOBase(hwp); 1607428d7b3dSmrg if (!vgaHWMapMem(scrn)) 1608428d7b3dSmrg return FALSE; 1609428d7b3dSmrg 1610428d7b3dSmrg I810Save(scrn); 1611428d7b3dSmrg if (!I810ModeInit(scrn, scrn->currentMode)) 1612428d7b3dSmrg return FALSE; 1613428d7b3dSmrg 1614428d7b3dSmrg I810SaveScreen(screen, FALSE); 1615428d7b3dSmrg I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0)); 1616428d7b3dSmrg 1617428d7b3dSmrg if (!fbScreenInit(screen, pI810->FbBase + scrn->fbOffset, 1618428d7b3dSmrg scrn->virtualX, scrn->virtualY, 1619428d7b3dSmrg scrn->xDpi, scrn->yDpi, 1620428d7b3dSmrg scrn->displayWidth, scrn->bitsPerPixel)) 1621428d7b3dSmrg return FALSE; 1622428d7b3dSmrg 1623428d7b3dSmrg if (scrn->bitsPerPixel > 8) { 1624428d7b3dSmrg /* Fixup RGB ordering */ 1625428d7b3dSmrg visual = screen->visuals + screen->numVisuals; 1626428d7b3dSmrg while (--visual >= screen->visuals) { 1627428d7b3dSmrg if ((visual->class | DynamicClass) == DirectColor) { 1628428d7b3dSmrg visual->offsetRed = scrn->offset.red; 1629428d7b3dSmrg visual->offsetGreen = scrn->offset.green; 1630428d7b3dSmrg visual->offsetBlue = scrn->offset.blue; 1631428d7b3dSmrg visual->redMask = scrn->mask.red; 1632428d7b3dSmrg visual->greenMask = scrn->mask.green; 1633428d7b3dSmrg visual->blueMask = scrn->mask.blue; 1634428d7b3dSmrg } 1635428d7b3dSmrg } 1636428d7b3dSmrg } 1637428d7b3dSmrg 1638428d7b3dSmrg fbPictureInit(screen, NULL, 0); 1639428d7b3dSmrg 1640428d7b3dSmrg xf86SetBlackWhitePixels(screen); 1641428d7b3dSmrg 1642428d7b3dSmrg#ifdef HAVE_DRI1 1643428d7b3dSmrg if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) { 1644428d7b3dSmrg pI810->directRenderingEnabled = FALSE; 1645428d7b3dSmrg I810DRICloseScreen(screen); 1646428d7b3dSmrg } 1647428d7b3dSmrg 1648428d7b3dSmrg if (!pI810->directRenderingEnabled) { 1649428d7b3dSmrg pI810->DoneFrontAlloc = FALSE; 1650428d7b3dSmrg if (!I810AllocateGARTMemory(scrn)) 1651428d7b3dSmrg return FALSE; 1652428d7b3dSmrg if (!I810AllocateFront(scrn)) 1653428d7b3dSmrg return FALSE; 1654428d7b3dSmrg } 1655428d7b3dSmrg#endif 1656428d7b3dSmrg 1657428d7b3dSmrg#ifdef HAVE_DGAPROC_H 1658428d7b3dSmrg I810DGAInit(screen); 1659428d7b3dSmrg#endif 1660428d7b3dSmrg 1661428d7b3dSmrg if (!xf86InitFBManager(screen, &(pI810->FbMemBox))) { 1662428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1663428d7b3dSmrg "Failed to init memory manager\n"); 1664428d7b3dSmrg return FALSE; 1665428d7b3dSmrg } 1666428d7b3dSmrg 1667428d7b3dSmrg if (pI810->LpRing->mem.Size != 0) { 1668428d7b3dSmrg I810SetRingRegs(scrn); 1669428d7b3dSmrg 1670428d7b3dSmrg if (!pI810->noAccel && !I810AccelInit(screen)) { 1671428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1672428d7b3dSmrg "Hardware acceleration initialization failed\n"); 1673428d7b3dSmrg } 1674428d7b3dSmrg 1675428d7b3dSmrg I810EmitFlush(scrn); 1676428d7b3dSmrg } 1677428d7b3dSmrg 1678428d7b3dSmrg xf86SetBackingStore(screen); 1679428d7b3dSmrg xf86SetSilkenMouse(screen); 1680428d7b3dSmrg 1681428d7b3dSmrg miDCInitialize(screen, xf86GetPointerScreenFuncs()); 1682428d7b3dSmrg 1683428d7b3dSmrg if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { 1684428d7b3dSmrg if (!I810CursorInit(screen)) { 1685428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_ERROR, 1686428d7b3dSmrg "Hardware cursor initialization failed\n"); 1687428d7b3dSmrg } 1688428d7b3dSmrg } 1689428d7b3dSmrg 1690428d7b3dSmrg if (!miCreateDefColormap(screen)) 1691428d7b3dSmrg return FALSE; 1692428d7b3dSmrg 1693428d7b3dSmrg /* Use driver specific palette load routines for Direct Color support. -jens */ 1694428d7b3dSmrg if (scrn->bitsPerPixel == 16) { 1695428d7b3dSmrg if (scrn->depth == 15) { 1696428d7b3dSmrg if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette15, NULL, 1697428d7b3dSmrg CMAP_PALETTED_TRUECOLOR | 1698428d7b3dSmrg CMAP_RELOAD_ON_MODE_SWITCH)) 1699428d7b3dSmrg return FALSE; 1700428d7b3dSmrg } else { 1701428d7b3dSmrg if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette16, NULL, 1702428d7b3dSmrg CMAP_PALETTED_TRUECOLOR | 1703428d7b3dSmrg CMAP_RELOAD_ON_MODE_SWITCH)) 1704428d7b3dSmrg return FALSE; 1705428d7b3dSmrg } 1706428d7b3dSmrg } else { 1707428d7b3dSmrg if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette24, NULL, 1708428d7b3dSmrg CMAP_PALETTED_TRUECOLOR | 1709428d7b3dSmrg CMAP_RELOAD_ON_MODE_SWITCH)) 1710428d7b3dSmrg return FALSE; 1711428d7b3dSmrg } 1712428d7b3dSmrg 1713428d7b3dSmrg xf86DPMSInit(screen, I810DisplayPowerManagementSet, 0); 1714428d7b3dSmrg 1715428d7b3dSmrg I810InitVideo(screen); 1716428d7b3dSmrg 1717428d7b3dSmrg#ifdef HAVE_DRI1 1718428d7b3dSmrg if (pI810->directRenderingEnabled) { 1719428d7b3dSmrg /* Now that mi, fb, drm and others have done their thing, 1720428d7b3dSmrg * complete the DRI setup. 1721428d7b3dSmrg */ 1722428d7b3dSmrg pI810->directRenderingEnabled = I810DRIFinishScreenInit(screen); 1723428d7b3dSmrg } 1724428d7b3dSmrg#ifdef XvMCExtension 1725428d7b3dSmrg if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) { 1726428d7b3dSmrg /* Initialize the hardware motion compensation code */ 1727428d7b3dSmrg I810InitMC(screen); 1728428d7b3dSmrg } 1729428d7b3dSmrg#endif 1730428d7b3dSmrg#endif 1731428d7b3dSmrg 1732428d7b3dSmrg if (pI810->directRenderingEnabled) { 1733428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 1734428d7b3dSmrg } else { 1735428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); 1736428d7b3dSmrg } 1737428d7b3dSmrg 1738428d7b3dSmrg screen->SaveScreen = I810SaveScreen; 1739428d7b3dSmrg pI810->CloseScreen = screen->CloseScreen; 1740428d7b3dSmrg screen->CloseScreen = I810CloseScreen; 1741428d7b3dSmrg 1742428d7b3dSmrg if (serverGeneration == 1) 1743428d7b3dSmrg xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 1744428d7b3dSmrg 1745428d7b3dSmrg return TRUE; 1746428d7b3dSmrg} 1747428d7b3dSmrg 1748428d7b3dSmrgBool 1749428d7b3dSmrgI810SwitchMode(SWITCH_MODE_ARGS_DECL) 1750428d7b3dSmrg{ 1751428d7b3dSmrg SCRN_INFO_PTR(arg); 1752428d7b3dSmrg#if 0 1753428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1754428d7b3dSmrg#endif 1755428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) 1756428d7b3dSmrg ErrorF("I810SwitchMode %p\n", (void *)mode); 1757428d7b3dSmrg 1758428d7b3dSmrg#if 0 1759428d7b3dSmrg/* 1760428d7b3dSmrg * This has been added to prevent lockups on mode switch by modeling 1761428d7b3dSmrg * it after I810Leave()/I810Enter() but the call to I810DRILeave() 1762428d7b3dSmrg * was missing so it caused the opposite. 1763428d7b3dSmrg * The version below works but it is doubtful it does any good. 1764428d7b3dSmrg * If lockups on mode switch are still seen revisit this code. (EE) 1765428d7b3dSmrg */ 1766428d7b3dSmrg 1767428d7b3dSmrg# ifdef HAVE_DRI1 1768428d7b3dSmrg if (pI810->directRenderingEnabled) { 1769428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1770428d7b3dSmrg ErrorF("calling dri lock\n"); 1771428d7b3dSmrg DRILock(screenInfo.screens[scrnIndex], 0); 1772428d7b3dSmrg pI810->LockHeld = 1; 1773428d7b3dSmrg } 1774428d7b3dSmrg# endif 1775428d7b3dSmrg if (pI810->AccelInfoRec != NULL) { 1776428d7b3dSmrg I810RefreshRing(scrn); 1777428d7b3dSmrg I810Sync(scrn); 1778428d7b3dSmrg pI810->AccelInfoRec->NeedToSync = FALSE; 1779428d7b3dSmrg } 1780428d7b3dSmrg I810Restore(scrn); 1781428d7b3dSmrg 1782428d7b3dSmrg# ifdef HAVE_DRI1 1783428d7b3dSmrg if (pI810->directRenderingEnabled) { 1784428d7b3dSmrg if (!I810DRILeave(scrn)) 1785428d7b3dSmrg return FALSE; 1786428d7b3dSmrg if (!I810DRIEnter(scrn)) 1787428d7b3dSmrg return FALSE; 1788428d7b3dSmrg 1789428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1790428d7b3dSmrg ErrorF("calling dri unlock\n"); 1791428d7b3dSmrg DRIUnlock(screenInfo.screens[scrnIndex]); 1792428d7b3dSmrg pI810->LockHeld = 0; 1793428d7b3dSmrg } 1794428d7b3dSmrg# endif 1795428d7b3dSmrg#endif 1796428d7b3dSmrg return I810ModeInit(scrn, mode); 1797428d7b3dSmrg} 1798428d7b3dSmrg 1799428d7b3dSmrgvoid 1800428d7b3dSmrgI810AdjustFrame(ADJUST_FRAME_ARGS_DECL) 1801428d7b3dSmrg{ 1802428d7b3dSmrg SCRN_INFO_PTR(arg); 1803428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1804428d7b3dSmrg vgaHWPtr hwp = VGAHWPTR(scrn); 1805428d7b3dSmrg int Base; 1806428d7b3dSmrg 1807428d7b3dSmrg#if 1 1808428d7b3dSmrg if (pI810->showCache) { 1809428d7b3dSmrg int lastline = pI810->FbMapSize / 1810428d7b3dSmrg ((scrn->displayWidth * scrn->bitsPerPixel) / 8); 1811428d7b3dSmrg lastline -= scrn->currentMode->VDisplay; 1812428d7b3dSmrg if (y > 0) 1813428d7b3dSmrg y += scrn->currentMode->VDisplay; 1814428d7b3dSmrg if (y > lastline) y = lastline; 1815428d7b3dSmrg } 1816428d7b3dSmrg#endif 1817428d7b3dSmrg Base = (y * scrn->displayWidth + x) >> 2; 1818428d7b3dSmrg 1819428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) 1820428d7b3dSmrg ErrorF("I810AdjustFrame %d,%d\n", x, y); 1821428d7b3dSmrg 1822428d7b3dSmrg switch (scrn->bitsPerPixel) { 1823428d7b3dSmrg case 8: 1824428d7b3dSmrg break; 1825428d7b3dSmrg case 16: 1826428d7b3dSmrg Base *= 2; 1827428d7b3dSmrg break; 1828428d7b3dSmrg case 24: 1829428d7b3dSmrg /* KW: Need to do 16-pixel alignment for i810, otherwise you 1830428d7b3dSmrg * get bad watermark problems. Need to fixup the mouse 1831428d7b3dSmrg * pointer positioning to take this into account. 1832428d7b3dSmrg */ 1833428d7b3dSmrg pI810->CursorOffset = (Base & 0x3) * 4; 1834428d7b3dSmrg Base &= ~0x3; 1835428d7b3dSmrg Base *= 3; 1836428d7b3dSmrg break; 1837428d7b3dSmrg case 32: 1838428d7b3dSmrg Base *= 4; 1839428d7b3dSmrg break; 1840428d7b3dSmrg } 1841428d7b3dSmrg 1842428d7b3dSmrg hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF); 1843428d7b3dSmrg hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8); 1844428d7b3dSmrg hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22); 1845428d7b3dSmrg hwp->writeCrtc(hwp, EXT_START_ADDR, 1846428d7b3dSmrg ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE)); 1847428d7b3dSmrg} 1848428d7b3dSmrg 1849428d7b3dSmrg/* These functions are usually called with the lock **not held**. 1850428d7b3dSmrg */ 1851428d7b3dSmrgstatic Bool 1852428d7b3dSmrgI810EnterVT(VT_FUNC_ARGS_DECL) 1853428d7b3dSmrg{ 1854428d7b3dSmrg SCRN_INFO_PTR(arg); 1855428d7b3dSmrg 1856428d7b3dSmrg#ifdef HAVE_DRI1 1857428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1858428d7b3dSmrg#endif 1859428d7b3dSmrg 1860428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1861428d7b3dSmrg ErrorF("\n\nENTER VT\n"); 1862428d7b3dSmrg 1863428d7b3dSmrg if (!I810BindGARTMemory(scrn)) { 1864428d7b3dSmrg return FALSE; 1865428d7b3dSmrg } 1866428d7b3dSmrg#ifdef HAVE_DRI1 1867428d7b3dSmrg if (!I810DRIEnter(scrn)) { 1868428d7b3dSmrg return FALSE; 1869428d7b3dSmrg } 1870428d7b3dSmrg if (pI810->directRenderingEnabled) { 1871428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1872428d7b3dSmrg ErrorF("calling dri unlock\n"); 1873428d7b3dSmrg DRIUnlock(xf86ScrnToScreen(scrn)); 1874428d7b3dSmrg pI810->LockHeld = 0; 1875428d7b3dSmrg } 1876428d7b3dSmrg#endif 1877428d7b3dSmrg 1878428d7b3dSmrg if (!I810ModeInit(scrn, scrn->currentMode)) 1879428d7b3dSmrg return FALSE; 1880428d7b3dSmrg I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0)); 1881428d7b3dSmrg return TRUE; 1882428d7b3dSmrg} 1883428d7b3dSmrg 1884428d7b3dSmrgstatic void 1885428d7b3dSmrgI810LeaveVT(VT_FUNC_ARGS_DECL) 1886428d7b3dSmrg{ 1887428d7b3dSmrg SCRN_INFO_PTR(arg); 1888428d7b3dSmrg vgaHWPtr hwp = VGAHWPTR(scrn); 1889428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1890428d7b3dSmrg 1891428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1892428d7b3dSmrg ErrorF("\n\n\nLeave VT\n"); 1893428d7b3dSmrg 1894428d7b3dSmrg#ifdef HAVE_DRI1 1895428d7b3dSmrg if (pI810->directRenderingEnabled) { 1896428d7b3dSmrg if (I810_DEBUG & DEBUG_VERBOSE_DRI) 1897428d7b3dSmrg ErrorF("calling dri lock\n"); 1898428d7b3dSmrg DRILock(xf86ScrnToScreen(scrn), 0); 1899428d7b3dSmrg pI810->LockHeld = 1; 1900428d7b3dSmrg } 1901428d7b3dSmrg#endif 1902428d7b3dSmrg 1903428d7b3dSmrg#ifdef HAVE_XAA_H 1904428d7b3dSmrg if (pI810->AccelInfoRec != NULL) { 1905428d7b3dSmrg I810RefreshRing(scrn); 1906428d7b3dSmrg I810Sync(scrn); 1907428d7b3dSmrg pI810->AccelInfoRec->NeedToSync = FALSE; 1908428d7b3dSmrg } 1909428d7b3dSmrg#endif 1910428d7b3dSmrg I810Restore(scrn); 1911428d7b3dSmrg 1912428d7b3dSmrg if (!I810UnbindGARTMemory(scrn)) 1913428d7b3dSmrg return; 1914428d7b3dSmrg#ifdef HAVE_DRI1 1915428d7b3dSmrg if (!I810DRILeave(scrn)) 1916428d7b3dSmrg return; 1917428d7b3dSmrg#endif 1918428d7b3dSmrg 1919428d7b3dSmrg vgaHWLock(hwp); 1920428d7b3dSmrg} 1921428d7b3dSmrg 1922428d7b3dSmrgstatic Bool 1923428d7b3dSmrgI810CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1924428d7b3dSmrg{ 1925428d7b3dSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 1926428d7b3dSmrg vgaHWPtr hwp = VGAHWPTR(scrn); 1927428d7b3dSmrg I810Ptr pI810 = I810PTR(scrn); 1928428d7b3dSmrg#ifdef HAVE_XAA_H 1929428d7b3dSmrg XAAInfoRecPtr infoPtr = pI810->AccelInfoRec; 1930428d7b3dSmrg#endif 1931428d7b3dSmrg 1932428d7b3dSmrg if (scrn->vtSema == TRUE) { 1933428d7b3dSmrg#ifdef HAVE_XAA_H 1934428d7b3dSmrg if (pI810->AccelInfoRec != NULL) { 1935428d7b3dSmrg I810RefreshRing(scrn); 1936428d7b3dSmrg I810Sync(scrn); 1937428d7b3dSmrg pI810->AccelInfoRec->NeedToSync = FALSE; 1938428d7b3dSmrg } 1939428d7b3dSmrg#endif 1940428d7b3dSmrg I810Restore(scrn); 1941428d7b3dSmrg vgaHWLock(hwp); 1942428d7b3dSmrg } 1943428d7b3dSmrg#ifdef HAVE_DRI1 1944428d7b3dSmrg if (pI810->directRenderingEnabled) { 1945428d7b3dSmrg I810DRICloseScreen(screen); 1946428d7b3dSmrg pI810->directRenderingEnabled = FALSE; 1947428d7b3dSmrg } 1948428d7b3dSmrg#endif 1949428d7b3dSmrg 1950428d7b3dSmrg if (scrn->vtSema == TRUE) { 1951428d7b3dSmrg I810UnbindGARTMemory(scrn); 1952428d7b3dSmrg I810Restore(scrn); 1953428d7b3dSmrg vgaHWLock(hwp); 1954428d7b3dSmrg } 1955428d7b3dSmrg 1956428d7b3dSmrg I810UnmapMem(scrn); 1957428d7b3dSmrg vgaHWUnmapMem(scrn); 1958428d7b3dSmrg 1959428d7b3dSmrg if (pI810->ScanlineColorExpandBuffers) { 1960428d7b3dSmrg free(pI810->ScanlineColorExpandBuffers); 1961428d7b3dSmrg pI810->ScanlineColorExpandBuffers = NULL; 1962428d7b3dSmrg } 1963428d7b3dSmrg 1964428d7b3dSmrg#ifdef HAVE_XAA_H 1965428d7b3dSmrg if (infoPtr) { 1966428d7b3dSmrg if (infoPtr->ScanlineColorExpandBuffers) 1967428d7b3dSmrg free(infoPtr->ScanlineColorExpandBuffers); 1968428d7b3dSmrg XAADestroyInfoRec(infoPtr); 1969428d7b3dSmrg pI810->AccelInfoRec = NULL; 1970428d7b3dSmrg } 1971428d7b3dSmrg#endif 1972428d7b3dSmrg 1973428d7b3dSmrg if (pI810->CursorInfoRec) { 1974428d7b3dSmrg xf86DestroyCursorInfoRec(pI810->CursorInfoRec); 1975428d7b3dSmrg pI810->CursorInfoRec = NULL; 1976428d7b3dSmrg } 1977428d7b3dSmrg 1978428d7b3dSmrg /* Free all allocated video ram. 1979428d7b3dSmrg */ 1980428d7b3dSmrg pI810->SysMem = pI810->SavedSysMem; 1981428d7b3dSmrg pI810->DcacheMem = pI810->SavedDcacheMem; 1982428d7b3dSmrg pI810->DoneFrontAlloc = FALSE; 1983428d7b3dSmrg 1984428d7b3dSmrg /* Need to actually close the gart fd, or the unbound memory will just sit 1985428d7b3dSmrg * around. Will prevent the Xserver from recycling. 1986428d7b3dSmrg */ 1987428d7b3dSmrg xf86GARTCloseScreen(scrn->scrnIndex); 1988428d7b3dSmrg 1989428d7b3dSmrg free(pI810->LpRing); 1990428d7b3dSmrg pI810->LpRing = NULL; 1991428d7b3dSmrg 1992428d7b3dSmrg scrn->vtSema = FALSE; 1993428d7b3dSmrg screen->CloseScreen = pI810->CloseScreen; 1994428d7b3dSmrg return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS); 1995428d7b3dSmrg} 1996428d7b3dSmrg 1997428d7b3dSmrgstatic void 1998428d7b3dSmrgI810FreeScreen(FREE_SCREEN_ARGS_DECL) 1999428d7b3dSmrg{ 2000428d7b3dSmrg SCRN_INFO_PTR(arg); 2001428d7b3dSmrg I810FreeRec(scrn); 2002428d7b3dSmrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 2003428d7b3dSmrg vgaHWFreeHWRec(scrn); 2004428d7b3dSmrg} 2005428d7b3dSmrg 2006428d7b3dSmrgstatic ModeStatus 2007428d7b3dSmrgI810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 2008428d7b3dSmrg{ 2009428d7b3dSmrg SCRN_INFO_PTR(arg); 2010428d7b3dSmrg if (mode->Flags & V_INTERLACE) { 2011428d7b3dSmrg if (verbose) { 2012428d7b3dSmrg xf86DrvMsg(scrn->scrnIndex, X_PROBED, 2013428d7b3dSmrg "Removing interlaced mode \"%s\"\n", mode->name); 2014428d7b3dSmrg } 2015428d7b3dSmrg return MODE_BAD; 2016428d7b3dSmrg } 2017428d7b3dSmrg return MODE_OK; 2018428d7b3dSmrg} 2019428d7b3dSmrg 2020428d7b3dSmrgstatic Bool 2021428d7b3dSmrgI810SaveScreen(ScreenPtr screen, Bool unblack) 2022428d7b3dSmrg{ 2023428d7b3dSmrg return vgaHWSaveScreen(screen, unblack); 2024428d7b3dSmrg} 2025428d7b3dSmrg 2026428d7b3dSmrgstatic void 2027428d7b3dSmrgI810DisplayPowerManagementSet(ScrnInfoPtr scrn, int PowerManagementMode, 2028428d7b3dSmrg int flags) 2029428d7b3dSmrg{ 2030428d7b3dSmrg I810Ptr pI810; 2031428d7b3dSmrg unsigned char SEQ01 = 0; 2032428d7b3dSmrg int DPMSSyncSelect = 0; 2033428d7b3dSmrg vgaHWPtr hwp; 2034428d7b3dSmrg 2035428d7b3dSmrg pI810 = I810PTR(scrn); 2036428d7b3dSmrg switch (PowerManagementMode) { 2037428d7b3dSmrg case DPMSModeOn: 2038428d7b3dSmrg /* Screen: On; HSync: On, VSync: On */ 2039428d7b3dSmrg SEQ01 = 0x00; 2040428d7b3dSmrg DPMSSyncSelect = HSYNC_ON | VSYNC_ON; 2041428d7b3dSmrg break; 2042428d7b3dSmrg case DPMSModeStandby: 2043428d7b3dSmrg /* Screen: Off; HSync: Off, VSync: On */ 2044428d7b3dSmrg SEQ01 = 0x20; 2045428d7b3dSmrg DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; 2046428d7b3dSmrg break; 2047428d7b3dSmrg case DPMSModeSuspend: 2048428d7b3dSmrg /* Screen: Off; HSync: On, VSync: Off */ 2049428d7b3dSmrg SEQ01 = 0x20; 2050428d7b3dSmrg DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; 2051428d7b3dSmrg break; 2052428d7b3dSmrg case DPMSModeOff: 2053428d7b3dSmrg /* Screen: Off; HSync: Off, VSync: Off */ 2054428d7b3dSmrg SEQ01 = 0x20; 2055428d7b3dSmrg DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; 2056428d7b3dSmrg break; 2057428d7b3dSmrg } 2058428d7b3dSmrg 2059428d7b3dSmrg hwp = VGAHWPTR(scrn); 2060428d7b3dSmrg 2061428d7b3dSmrg /* Turn the screen on/off */ 2062428d7b3dSmrg SEQ01 |= hwp->readSeq(hwp, 0x01) & ~0x20; 2063428d7b3dSmrg hwp->writeSeq(hwp, 0x01, SEQ01); 2064428d7b3dSmrg 2065428d7b3dSmrg /* Set the DPMS mode */ 2066428d7b3dSmrg OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect); 2067428d7b3dSmrg} 2068428d7b3dSmrg 2069428d7b3dSmrgconst OptionInfoRec * 2070428d7b3dSmrglg_i810_available_options(int chipid, int busid) 2071428d7b3dSmrg{ 2072428d7b3dSmrg return I810Options; 2073428d7b3dSmrg} 2074428d7b3dSmrg 2075428d7b3dSmrg 2076428d7b3dSmrgBool lg_i810_init(ScrnInfoPtr scrn) 2077428d7b3dSmrg{ 2078428d7b3dSmrg scrn->PreInit = I810PreInit; 2079428d7b3dSmrg scrn->ScreenInit = I810ScreenInit; 2080428d7b3dSmrg scrn->SwitchMode = I810SwitchMode; 2081428d7b3dSmrg scrn->AdjustFrame = I810AdjustFrame; 2082428d7b3dSmrg scrn->EnterVT = I810EnterVT; 2083428d7b3dSmrg scrn->LeaveVT = I810LeaveVT; 2084428d7b3dSmrg scrn->FreeScreen = I810FreeScreen; 2085428d7b3dSmrg scrn->ValidMode = I810ValidMode; 2086428d7b3dSmrg return TRUE; 2087428d7b3dSmrg} 2088