103b705cfSriastradh 203b705cfSriastradh/************************************************************************** 303b705cfSriastradh 403b705cfSriastradhCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 503b705cfSriastradhAll Rights Reserved. 603b705cfSriastradh 703b705cfSriastradhPermission is hereby granted, free of charge, to any person obtaining a 803b705cfSriastradhcopy of this software and associated documentation files (the 903b705cfSriastradh"Software"), to deal in the Software without restriction, including 1003b705cfSriastradhwithout limitation the rights to use, copy, modify, merge, publish, 1103b705cfSriastradhdistribute, sub license, and/or sell copies of the Software, and to 1203b705cfSriastradhpermit persons to whom the Software is furnished to do so, subject to 1303b705cfSriastradhthe following conditions: 1403b705cfSriastradh 1503b705cfSriastradhThe above copyright notice and this permission notice (including the 1603b705cfSriastradhnext paragraph) shall be included in all copies or substantial portions 1703b705cfSriastradhof the Software. 1803b705cfSriastradh 1903b705cfSriastradhTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2003b705cfSriastradhOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2103b705cfSriastradhMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2203b705cfSriastradhIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 2303b705cfSriastradhANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2403b705cfSriastradhTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2503b705cfSriastradhSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2603b705cfSriastradh 2703b705cfSriastradh**************************************************************************/ 2803b705cfSriastradh 2903b705cfSriastradh#ifdef HAVE_CONFIG_H 3003b705cfSriastradh#include "config.h" 3103b705cfSriastradh#endif 3203b705cfSriastradh 3303b705cfSriastradh/* 3403b705cfSriastradh * Authors: 3503b705cfSriastradh * Keith Whitwell <keith@tungstengraphics.com> 3603b705cfSriastradh * 3703b705cfSriastradh * Add ARGB HW cursor support: 3803b705cfSriastradh * Alan Hourihane <alanh@tungstengraphics.com> 3903b705cfSriastradh * 4003b705cfSriastradh */ 4103b705cfSriastradh 4203b705cfSriastradh/* 4303b705cfSriastradh * This server does not support these XFree86 4.0 features yet 4403b705cfSriastradh * shadowFb (if requested or acceleration is off) 4503b705cfSriastradh * Overlay planes 4603b705cfSriastradh * DGA 4703b705cfSriastradh */ 4803b705cfSriastradh 4903b705cfSriastradh#include <math.h> 5003b705cfSriastradh#include <string.h> 5103b705cfSriastradh#include <unistd.h> 5203b705cfSriastradh 5303b705cfSriastradh/* 5403b705cfSriastradh * These are X and server generic header files. 5503b705cfSriastradh */ 5642542f5fSchristos#include "xorg-server.h" 5703b705cfSriastradh#include "xf86.h" 5803b705cfSriastradh#include "xf86_OSproc.h" 5903b705cfSriastradh#include "xf86cmap.h" 6003b705cfSriastradh 6103b705cfSriastradh#include "compiler.h" 6203b705cfSriastradh#include "vgaHW.h" 6303b705cfSriastradh#include "mipointer.h" 6403b705cfSriastradh#include "micmap.h" 6503b705cfSriastradh 6603b705cfSriastradh#include "fb.h" 6703b705cfSriastradh#include "miscstruct.h" 6803b705cfSriastradh#include "xf86xv.h" 6903b705cfSriastradh#include <X11/extensions/Xv.h> 7003b705cfSriastradh#include "vbe.h" 7103b705cfSriastradh#include "xf86fbman.h" 7203b705cfSriastradh 7303b705cfSriastradh#include "i810.h" 7403b705cfSriastradh 7503b705cfSriastradh#ifdef HAVE_DRI1 7603b705cfSriastradh#include "dri.h" 7703b705cfSriastradh#endif 7803b705cfSriastradh 7903b705cfSriastradh#include "../legacy.h" 8003b705cfSriastradh 8103b705cfSriastradhstatic Bool I810PreInit(ScrnInfoPtr pScrn, int flags); 8203b705cfSriastradhstatic Bool I810ScreenInit(SCREEN_INIT_ARGS_DECL); 8303b705cfSriastradhstatic Bool I810EnterVT(VT_FUNC_ARGS_DECL); 8403b705cfSriastradhstatic void I810LeaveVT(VT_FUNC_ARGS_DECL); 8503b705cfSriastradhstatic Bool I810CloseScreen(CLOSE_SCREEN_ARGS_DECL); 8603b705cfSriastradhstatic Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank); 8703b705cfSriastradhstatic void I810FreeScreen(FREE_SCREEN_ARGS_DECL); 8803b705cfSriastradhstatic void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, 8903b705cfSriastradh int PowerManagermentMode, 9003b705cfSriastradh int flags); 9103b705cfSriastradhstatic ModeStatus I810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 9203b705cfSriastradh Bool verbose, int flags); 9303b705cfSriastradh 9403b705cfSriastradhtypedef enum { 9503b705cfSriastradh OPTION_NOACCEL, 9603b705cfSriastradh OPTION_SW_CURSOR, 9703b705cfSriastradh OPTION_COLOR_KEY, 9803b705cfSriastradh OPTION_CACHE_LINES, 9903b705cfSriastradh OPTION_DAC_6BIT, 10003b705cfSriastradh OPTION_DRI, 10103b705cfSriastradh OPTION_NO_DDC, 10203b705cfSriastradh OPTION_SHOW_CACHE, 10303b705cfSriastradh OPTION_XVMC_SURFACES, 10403b705cfSriastradh OPTION_PAGEFLIP 10503b705cfSriastradh} I810Opts; 10603b705cfSriastradh 10703b705cfSriastradhstatic const OptionInfoRec I810Options[] = { 10803b705cfSriastradh {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, 10903b705cfSriastradh {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 11003b705cfSriastradh {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, 11103b705cfSriastradh {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, 11203b705cfSriastradh {OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, 11303b705cfSriastradh {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, 11403b705cfSriastradh {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, 11503b705cfSriastradh {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, 11603b705cfSriastradh {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, 11703b705cfSriastradh {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, 11803b705cfSriastradh {-1, NULL, OPTV_NONE, {0}, FALSE} 11903b705cfSriastradh}; 12003b705cfSriastradh/* *INDENT-ON* */ 12103b705cfSriastradh 12203b705cfSriastradh#ifndef I810_DEBUG 12303b705cfSriastradhint I810_DEBUG = (0 12403b705cfSriastradh/* | DEBUG_ALWAYS_SYNC */ 12503b705cfSriastradh/* | DEBUG_VERBOSE_ACCEL */ 12603b705cfSriastradh/* | DEBUG_VERBOSE_SYNC */ 12703b705cfSriastradh/* | DEBUG_VERBOSE_VGA */ 12803b705cfSriastradh/* | DEBUG_VERBOSE_RING */ 12903b705cfSriastradh/* | DEBUG_VERBOSE_OUTREG */ 13003b705cfSriastradh/* | DEBUG_VERBOSE_MEMORY */ 13103b705cfSriastradh/* | DEBUG_VERBOSE_CURSOR */ 13203b705cfSriastradh ); 13303b705cfSriastradh#endif 13403b705cfSriastradh 13503b705cfSriastradh#ifdef HAVE_DRI1 13603b705cfSriastradhstatic int i810_pitches[] = { 13703b705cfSriastradh 512, 13803b705cfSriastradh 1024, 13903b705cfSriastradh 2048, 14003b705cfSriastradh 4096, 14103b705cfSriastradh 0 14203b705cfSriastradh}; 14303b705cfSriastradh#endif 14403b705cfSriastradh 14503b705cfSriastradh/* 14603b705cfSriastradh * I810GetRec and I810FreeRec -- 14703b705cfSriastradh * 14803b705cfSriastradh * Private data for the driver is stored in the screen structure. 14903b705cfSriastradh * These two functions create and destroy that private data. 15003b705cfSriastradh * 15103b705cfSriastradh */ 15203b705cfSriastradhstatic Bool 15303b705cfSriastradhI810GetRec(ScrnInfoPtr scrn) 15403b705cfSriastradh{ 15542542f5fSchristos if (((uintptr_t)scrn->driverPrivate & 3) == 0) 15603b705cfSriastradh return TRUE; 15703b705cfSriastradh 15803b705cfSriastradh scrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1); 15903b705cfSriastradh return TRUE; 16003b705cfSriastradh} 16103b705cfSriastradh 16203b705cfSriastradhstatic void 16303b705cfSriastradhI810FreeRec(ScrnInfoPtr scrn) 16403b705cfSriastradh{ 16503b705cfSriastradh if (!scrn) 16603b705cfSriastradh return; 16703b705cfSriastradh if (!scrn->driverPrivate) 16803b705cfSriastradh return; 16903b705cfSriastradh free(scrn->driverPrivate); 17003b705cfSriastradh scrn->driverPrivate = NULL; 17103b705cfSriastradh} 17203b705cfSriastradh 17303b705cfSriastradhstruct pci_device * 17403b705cfSriastradhintel_host_bridge (void) 17503b705cfSriastradh{ 17603b705cfSriastradh static const struct pci_slot_match bridge_match = { 17703b705cfSriastradh 0, 0, 0, PCI_MATCH_ANY, 0 17803b705cfSriastradh }; 17903b705cfSriastradh struct pci_device_iterator *slot_iterator; 18003b705cfSriastradh struct pci_device *bridge; 18103b705cfSriastradh 18203b705cfSriastradh slot_iterator = pci_slot_match_iterator_create (&bridge_match); 18303b705cfSriastradh bridge = pci_device_next (slot_iterator); 18403b705cfSriastradh pci_iterator_destroy (slot_iterator); 18503b705cfSriastradh return bridge; 18603b705cfSriastradh} 18703b705cfSriastradh 18803b705cfSriastradhstatic void 18903b705cfSriastradhI810ProbeDDC(ScrnInfoPtr scrn, int index) 19003b705cfSriastradh{ 19103b705cfSriastradh vbeInfoPtr pVbe; 19203b705cfSriastradh 19303b705cfSriastradh if (xf86LoadSubModule(scrn, "vbe")) { 19403b705cfSriastradh pVbe = VBEInit(NULL, index); 19503b705cfSriastradh ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 19603b705cfSriastradh vbeFree(pVbe); 19703b705cfSriastradh } 19803b705cfSriastradh} 19903b705cfSriastradh 20003b705cfSriastradhstatic xf86MonPtr 20103b705cfSriastradhI810DoDDC(ScrnInfoPtr scrn, int index) 20203b705cfSriastradh{ 20303b705cfSriastradh vbeInfoPtr pVbe; 20403b705cfSriastradh xf86MonPtr MonInfo = NULL; 20503b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 20603b705cfSriastradh 20703b705cfSriastradh /* Honour Option "noDDC" */ 20803b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) { 20903b705cfSriastradh return MonInfo; 21003b705cfSriastradh } 21103b705cfSriastradh 21203b705cfSriastradh if (xf86LoadSubModule(scrn, "vbe") && (pVbe = VBEInit(NULL, index))) { 21303b705cfSriastradh MonInfo = vbeDoEDID(pVbe, NULL); 21403b705cfSriastradh xf86PrintEDID(MonInfo); 21503b705cfSriastradh xf86SetDDCproperties(scrn, MonInfo); 21603b705cfSriastradh vbeFree(pVbe); 21703b705cfSriastradh } else { 21803b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 21903b705cfSriastradh "this driver cannot do DDC without VBE\n"); 22003b705cfSriastradh } 22103b705cfSriastradh 22203b705cfSriastradh return MonInfo; 22303b705cfSriastradh} 22403b705cfSriastradh 22503b705cfSriastradh/* 22603b705cfSriastradh * I810PreInit -- 22703b705cfSriastradh * 22803b705cfSriastradh * Do initial setup of the board before we know what resolution we will 22903b705cfSriastradh * be running at. 23003b705cfSriastradh * 23103b705cfSriastradh */ 23203b705cfSriastradhstatic Bool 23303b705cfSriastradhI810PreInit(ScrnInfoPtr scrn, int flags) 23403b705cfSriastradh{ 23503b705cfSriastradh I810Ptr pI810; 23603b705cfSriastradh ClockRangePtr clockRanges; 23703b705cfSriastradh int i; 23803b705cfSriastradh MessageType from; 23903b705cfSriastradh int flags24; 24003b705cfSriastradh rgb defaultWeight = { 0, 0, 0 }; 24103b705cfSriastradh int mem; 24203b705cfSriastradh Bool enable; 24303b705cfSriastradh 24403b705cfSriastradh if (scrn->numEntities != 1) 24503b705cfSriastradh return FALSE; 24603b705cfSriastradh 24703b705cfSriastradh /* Allocate driverPrivate */ 24803b705cfSriastradh if (!I810GetRec(scrn)) 24903b705cfSriastradh return FALSE; 25003b705cfSriastradh 25103b705cfSriastradh pI810 = I810PTR(scrn); 25203b705cfSriastradh 25303b705cfSriastradh pI810->pEnt = xf86GetEntityInfo(scrn->entityList[0]); 25403b705cfSriastradh if (pI810->pEnt == NULL || pI810->pEnt->location.type != BUS_PCI) 25503b705cfSriastradh return FALSE; 25603b705cfSriastradh 25703b705cfSriastradh if (flags & PROBE_DETECT) { 25803b705cfSriastradh I810ProbeDDC(scrn, pI810->pEnt->index); 25903b705cfSriastradh return TRUE; 26003b705cfSriastradh } 26103b705cfSriastradh 26203b705cfSriastradh /* The vgahw module should be loaded here when needed */ 26303b705cfSriastradh if (!xf86LoadSubModule(scrn, "vgahw")) 26403b705cfSriastradh return FALSE; 26503b705cfSriastradh 26603b705cfSriastradh /* Allocate a vgaHWRec */ 26703b705cfSriastradh if (!vgaHWGetHWRec(scrn)) 26803b705cfSriastradh return FALSE; 26903b705cfSriastradh 27003b705cfSriastradh pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index); 27103b705cfSriastradh 27203b705cfSriastradh /* Set scrn->monitor */ 27303b705cfSriastradh scrn->monitor = scrn->confScreen->monitor; 27403b705cfSriastradh 27503b705cfSriastradh flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24; 27603b705cfSriastradh if (!xf86SetDepthBpp(scrn, 16, 0, 16, flags24)) { 27703b705cfSriastradh return FALSE; 27803b705cfSriastradh } else { 27903b705cfSriastradh switch (scrn->depth) { 28003b705cfSriastradh case 8: 28103b705cfSriastradh case 15: 28203b705cfSriastradh case 16: 28303b705cfSriastradh case 24: 28403b705cfSriastradh break; 28503b705cfSriastradh default: 28603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 28703b705cfSriastradh "Given depth (%d) is not supported by i810 driver\n", 28803b705cfSriastradh scrn->depth); 28903b705cfSriastradh return FALSE; 29003b705cfSriastradh } 29103b705cfSriastradh } 29203b705cfSriastradh xf86PrintDepthBpp(scrn); 29303b705cfSriastradh 29403b705cfSriastradh switch (scrn->bitsPerPixel) { 29503b705cfSriastradh case 8: 29603b705cfSriastradh case 16: 29703b705cfSriastradh case 24: 29803b705cfSriastradh break; 29903b705cfSriastradh default: 30003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 30103b705cfSriastradh "Given bpp (%d) is not supported by i810 driver\n", 30203b705cfSriastradh scrn->bitsPerPixel); 30303b705cfSriastradh return FALSE; 30403b705cfSriastradh } 30503b705cfSriastradh 30603b705cfSriastradh if (!xf86SetWeight(scrn, defaultWeight, defaultWeight)) 30703b705cfSriastradh return FALSE; 30803b705cfSriastradh 30903b705cfSriastradh if (!xf86SetDefaultVisual(scrn, -1)) 31003b705cfSriastradh return FALSE; 31103b705cfSriastradh 31203b705cfSriastradh /* We use a programmable clock */ 31303b705cfSriastradh scrn->progClock = TRUE; 31403b705cfSriastradh 31503b705cfSriastradh pI810->cpp = scrn->bitsPerPixel / 8; 31603b705cfSriastradh 31703b705cfSriastradh /* Process the options */ 31803b705cfSriastradh xf86CollectOptions(scrn, NULL); 31903b705cfSriastradh if (!(pI810->Options = malloc(sizeof(I810Options)))) 32003b705cfSriastradh return FALSE; 32103b705cfSriastradh memcpy(pI810->Options, I810Options, sizeof(I810Options)); 32203b705cfSriastradh xf86ProcessOptions(scrn->scrnIndex, scrn->options, pI810->Options); 32303b705cfSriastradh 32403b705cfSriastradh scrn->rgbBits = 8; 32503b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) 32603b705cfSriastradh scrn->rgbBits = 6; 32703b705cfSriastradh 32803b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE)) 32903b705cfSriastradh pI810->showCache = TRUE; 33003b705cfSriastradh else 33103b705cfSriastradh pI810->showCache = FALSE; 33203b705cfSriastradh 33303b705cfSriastradh /* 6-BIT dac isn't reasonable for modes with > 8bpp */ 33403b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) && 33503b705cfSriastradh scrn->bitsPerPixel > 8) { 33603b705cfSriastradh OptionInfoPtr ptr; 33703b705cfSriastradh 33803b705cfSriastradh ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT); 33903b705cfSriastradh ptr->found = FALSE; 34003b705cfSriastradh } 34103b705cfSriastradh 34203b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) 34303b705cfSriastradh pI810->noAccel = TRUE; 34403b705cfSriastradh 34503b705cfSriastradh if (!pI810->noAccel && !xf86LoadSubModule(scrn, "xaa")) 34603b705cfSriastradh pI810->noAccel = TRUE; 34703b705cfSriastradh 34803b705cfSriastradh#ifdef HAVE_DRI1 34903b705cfSriastradh pI810->directRenderingDisabled = 35003b705cfSriastradh !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE); 35103b705cfSriastradh 35203b705cfSriastradh if (!pI810->directRenderingDisabled) { 35303b705cfSriastradh if (scrn->depth!=16) { 35403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, "DRI is disabled because it " 35503b705cfSriastradh "runs only at 16-bit depth.\n"); 35603b705cfSriastradh pI810->directRenderingDisabled=TRUE; 35703b705cfSriastradh } 35803b705cfSriastradh } 35903b705cfSriastradh#endif 36003b705cfSriastradh 36103b705cfSriastradh /* Get DDC info from monitor */ 36203b705cfSriastradh /* after xf86ProcessOptions, 36303b705cfSriastradh * because it is controlled by options [no]vbe and [no]ddc 36403b705cfSriastradh */ 36503b705cfSriastradh I810DoDDC(scrn, pI810->pEnt->index); 36603b705cfSriastradh 36713496ba1Ssnj intel_detect_chipset(scrn, NULL); 36803b705cfSriastradh 36903b705cfSriastradh pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr; 37003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n", 37103b705cfSriastradh (unsigned long)pI810->LinearAddr); 37203b705cfSriastradh 37303b705cfSriastradh pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr; 37403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_PROBED, "IO registers at addr 0x%lX\n", 37503b705cfSriastradh (unsigned long)pI810->MMIOAddr); 37603b705cfSriastradh 37703b705cfSriastradh /* AGP GART support is required. Don't proceed any further if it isn't 37803b705cfSriastradh * present. 37903b705cfSriastradh */ 38003b705cfSriastradh if (!xf86AgpGARTSupported()) { 38103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 38203b705cfSriastradh "AGP GART support is not available. Make sure your kernel has\n" 38303b705cfSriastradh "\tagpgart support or that the agpgart kernel module is loaded.\n"); 38403b705cfSriastradh return FALSE; 38503b705cfSriastradh } 38603b705cfSriastradh 38703b705cfSriastradh /* Find out memory bus frequency. 38803b705cfSriastradh */ 38903b705cfSriastradh { 39003b705cfSriastradh uint32_t whtcfg_pamr_drp; 39103b705cfSriastradh 39203b705cfSriastradh pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP); 39303b705cfSriastradh 39403b705cfSriastradh /* Need this for choosing watermarks. 39503b705cfSriastradh */ 39603b705cfSriastradh if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133) 39703b705cfSriastradh pI810->LmFreqSel = 133; 39803b705cfSriastradh else 39903b705cfSriastradh pI810->LmFreqSel = 100; 40003b705cfSriastradh } 40103b705cfSriastradh 40203b705cfSriastradh /* Default to 4MB framebuffer, which is sufficient for all 40303b705cfSriastradh * supported 2d resolutions. If the user has specified a different 40403b705cfSriastradh * size in the XF86Config, use that amount instead. 40503b705cfSriastradh * 40603b705cfSriastradh * Changed to 8 Meg so we can have acceleration by default (Mark). 40703b705cfSriastradh */ 40803b705cfSriastradh mem = I810CheckAvailableMemory(scrn); 40903b705cfSriastradh if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */ 41003b705cfSriastradh scrn->videoRam = 8192; 41103b705cfSriastradh else if (mem < 196608) 41203b705cfSriastradh scrn->videoRam = 16384; /* < 192 MB */ 41303b705cfSriastradh else 41403b705cfSriastradh scrn->videoRam = 24576; 41503b705cfSriastradh 41603b705cfSriastradh from = X_DEFAULT; 41703b705cfSriastradh 41803b705cfSriastradh if (pI810->pEnt->device->videoRam) { 41903b705cfSriastradh scrn->videoRam = pI810->pEnt->device->videoRam; 42003b705cfSriastradh from = X_CONFIG; 42103b705cfSriastradh } 42203b705cfSriastradh 42303b705cfSriastradh if (mem > 0 && mem < scrn->videoRam) { 42403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%dk of memory was requested," 42503b705cfSriastradh " but the\n\t maximum AGP memory available is %dk.\n", 42603b705cfSriastradh scrn->videoRam, mem); 42703b705cfSriastradh from = X_PROBED; 42803b705cfSriastradh if (mem > (6 * 1024)) { 42903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 43003b705cfSriastradh "Reducing video memory to 4MB\n"); 43103b705cfSriastradh scrn->videoRam = 4096; 43203b705cfSriastradh } else { 43303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory" 43403b705cfSriastradh " is available. Cannot proceed.\n"); 43503b705cfSriastradh I810FreeRec(scrn); 43603b705cfSriastradh return FALSE; 43703b705cfSriastradh } 43803b705cfSriastradh } 43903b705cfSriastradh 44003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, from, 44103b705cfSriastradh "Will alloc AGP framebuffer: %d kByte\n", scrn->videoRam); 44203b705cfSriastradh 44303b705cfSriastradh /* Calculate Fixed Offsets depending on graphics aperture size */ 44403b705cfSriastradh { 44503b705cfSriastradh struct pci_device *bridge = intel_host_bridge (); 44603b705cfSriastradh uint32_t smram_miscc; 44703b705cfSriastradh 44803b705cfSriastradh pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC); 44903b705cfSriastradh 45003b705cfSriastradh if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) { 45103b705cfSriastradh pI810->FbMapSize = 0x1000000; 45203b705cfSriastradh pI810->DepthOffset = 0x1000000; 45303b705cfSriastradh pI810->BackOffset = 0x1800000; 45403b705cfSriastradh } else { 45503b705cfSriastradh pI810->FbMapSize = 0x3000000; 45603b705cfSriastradh pI810->DepthOffset = 0x3000000; 45703b705cfSriastradh pI810->BackOffset = 0x3800000; 45803b705cfSriastradh } 45903b705cfSriastradh } 46003b705cfSriastradh 46103b705cfSriastradh /* 46203b705cfSriastradh * If the driver can do gamma correction, it should call xf86SetGamma() 46303b705cfSriastradh * here. 46403b705cfSriastradh */ 46503b705cfSriastradh { 46603b705cfSriastradh Gamma zeros = { 0.0, 0.0, 0.0 }; 46703b705cfSriastradh 46803b705cfSriastradh if (!xf86SetGamma(scrn, zeros)) { 46903b705cfSriastradh return FALSE; 47003b705cfSriastradh } 47103b705cfSriastradh } 47203b705cfSriastradh 47303b705cfSriastradh pI810->MaxClock = 0; 47403b705cfSriastradh if (pI810->pEnt->device->dacSpeeds[0]) { 47503b705cfSriastradh switch (scrn->bitsPerPixel) { 47603b705cfSriastradh case 8: 47703b705cfSriastradh pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8]; 47803b705cfSriastradh break; 47903b705cfSriastradh case 16: 48003b705cfSriastradh pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16]; 48103b705cfSriastradh break; 48203b705cfSriastradh case 24: 48303b705cfSriastradh pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24]; 48403b705cfSriastradh break; 48503b705cfSriastradh case 32: /* not supported */ 48603b705cfSriastradh pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32]; 48703b705cfSriastradh break; 48803b705cfSriastradh } 48903b705cfSriastradh if (!pI810->MaxClock) 49003b705cfSriastradh pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0]; 49103b705cfSriastradh } else { 49203b705cfSriastradh switch (scrn->bitsPerPixel) { 49303b705cfSriastradh case 8: 49403b705cfSriastradh pI810->MaxClock = 203000; 49503b705cfSriastradh break; 49603b705cfSriastradh case 16: 49703b705cfSriastradh pI810->MaxClock = 163000; 49803b705cfSriastradh break; 49903b705cfSriastradh case 24: 50003b705cfSriastradh pI810->MaxClock = 136000; 50103b705cfSriastradh break; 50203b705cfSriastradh case 32: /* not supported */ 50303b705cfSriastradh pI810->MaxClock = 86000; 50403b705cfSriastradh } 50503b705cfSriastradh } 50603b705cfSriastradh clockRanges = xnfcalloc(sizeof(ClockRange), 1); 50703b705cfSriastradh clockRanges->next = NULL; 50803b705cfSriastradh /* 9.4MHz appears to be the smallest that works. */ 50903b705cfSriastradh clockRanges->minClock = 9500; 51003b705cfSriastradh clockRanges->maxClock = pI810->MaxClock; 51103b705cfSriastradh clockRanges->clockIndex = -1; 51203b705cfSriastradh clockRanges->interlaceAllowed = TRUE; 51303b705cfSriastradh clockRanges->doubleScanAllowed = FALSE; 51403b705cfSriastradh 51503b705cfSriastradh i = xf86ValidateModes(scrn, scrn->monitor->Modes, 51603b705cfSriastradh scrn->display->modes, clockRanges, 51703b705cfSriastradh#ifndef HAVE_DRI1 51803b705cfSriastradh 0, 320, 1600, 64 * scrn->bitsPerPixel, 51903b705cfSriastradh#else 52003b705cfSriastradh i810_pitches, 0, 0, 64 * scrn->bitsPerPixel, 52103b705cfSriastradh#endif 52203b705cfSriastradh 200, 1200, 52303b705cfSriastradh scrn->display->virtualX, scrn->display->virtualY, 52403b705cfSriastradh scrn->videoRam * 1024, LOOKUP_BEST_REFRESH); 52503b705cfSriastradh 52603b705cfSriastradh if (i == -1) { 52703b705cfSriastradh I810FreeRec(scrn); 52803b705cfSriastradh return FALSE; 52903b705cfSriastradh } 53003b705cfSriastradh 53103b705cfSriastradh xf86PruneDriverModes(scrn); 53203b705cfSriastradh 53303b705cfSriastradh if (!i || !scrn->modes) { 53403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, "No valid modes found\n"); 53503b705cfSriastradh I810FreeRec(scrn); 53603b705cfSriastradh return FALSE; 53703b705cfSriastradh } 53803b705cfSriastradh 53903b705cfSriastradh xf86SetCrtcForModes(scrn, INTERLACE_HALVE_V); 54003b705cfSriastradh 54103b705cfSriastradh scrn->currentMode = scrn->modes; 54203b705cfSriastradh 54303b705cfSriastradh xf86PrintModes(scrn); 54403b705cfSriastradh 54503b705cfSriastradh xf86SetDpi(scrn, 0, 0); 54603b705cfSriastradh 54703b705cfSriastradh if (!xf86LoadSubModule(scrn, "fb")) { 54803b705cfSriastradh I810FreeRec(scrn); 54903b705cfSriastradh return FALSE; 55003b705cfSriastradh } 55103b705cfSriastradh 55203b705cfSriastradh if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { 55303b705cfSriastradh if (!xf86LoadSubModule(scrn, "ramdac")) { 55403b705cfSriastradh I810FreeRec(scrn); 55503b705cfSriastradh return FALSE; 55603b705cfSriastradh } 55703b705cfSriastradh } 55803b705cfSriastradh 55903b705cfSriastradh if (xf86GetOptValInteger 56003b705cfSriastradh (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) { 56103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_CONFIG, 56203b705cfSriastradh "video overlay key set to 0x%x\n", pI810->colorKey); 56303b705cfSriastradh } else { 56403b705cfSriastradh pI810->colorKey = (1 << scrn->offset.red) | 56503b705cfSriastradh (1 << scrn->offset.green) | 56603b705cfSriastradh (((scrn->mask.blue >> scrn->offset.blue) - 56703b705cfSriastradh 1) << scrn->offset.blue); 56803b705cfSriastradh } 56903b705cfSriastradh 57003b705cfSriastradh pI810->allowPageFlip=FALSE; 57103b705cfSriastradh enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE); 57203b705cfSriastradh 57303b705cfSriastradh#ifdef HAVE_DRI1 57403b705cfSriastradh if (!pI810->directRenderingDisabled) { 57503b705cfSriastradh pI810->allowPageFlip = enable; 57603b705cfSriastradh if (pI810->allowPageFlip == TRUE) 57703b705cfSriastradh { 57803b705cfSriastradh if (!xf86LoadSubModule(scrn, "shadowfb")) { 57903b705cfSriastradh pI810->allowPageFlip = 0; 58003b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 58103b705cfSriastradh "Couldn't load shadowfb module:\n"); 58203b705cfSriastradh } 58303b705cfSriastradh } 58403b705cfSriastradh 58503b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "page flipping %s\n", 58603b705cfSriastradh enable ? "enabled" : "disabled"); 58703b705cfSriastradh 58803b705cfSriastradh } 58903b705cfSriastradh#endif 59003b705cfSriastradh 59103b705cfSriastradh if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES, 59203b705cfSriastradh &(pI810->numSurfaces))) { 59303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n", 59403b705cfSriastradh pI810->numSurfaces); 59503b705cfSriastradh if (pI810->numSurfaces > 7) { 59603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_PROBED, 59703b705cfSriastradh "Using 7 XvMC Surfaces (Maximum Allowed).\n"); 59803b705cfSriastradh pI810->numSurfaces = 7; 59903b705cfSriastradh } 60003b705cfSriastradh if (pI810->numSurfaces < 6) { 60103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_PROBED, 60203b705cfSriastradh "Using 6 XvMC Surfaces (Minimum Allowed).\n"); 60303b705cfSriastradh pI810->numSurfaces = 6; 60403b705cfSriastradh } 60503b705cfSriastradh } else { 60603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 60703b705cfSriastradh "XvMC is Disabled: use XvMCSurfaces config option to enable.\n"); 60803b705cfSriastradh pI810->numSurfaces = 0; 60903b705cfSriastradh } 61003b705cfSriastradh 61103b705cfSriastradh#ifdef HAVE_DRI1 61203b705cfSriastradh /* Load the dri module if requested. */ 61303b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) { 61403b705cfSriastradh xf86LoadSubModule(scrn, "dri"); 61503b705cfSriastradh } 61603b705cfSriastradh#endif 61703b705cfSriastradh 61803b705cfSriastradh return TRUE; 61903b705cfSriastradh} 62003b705cfSriastradh 62103b705cfSriastradhstatic Bool 62203b705cfSriastradhI810MapMMIO(ScrnInfoPtr scrn) 62303b705cfSriastradh{ 62403b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 62503b705cfSriastradh struct pci_device *const device = pI810->PciInfo; 62603b705cfSriastradh int err; 62703b705cfSriastradh 62803b705cfSriastradh err = pci_device_map_range (device, 62903b705cfSriastradh pI810->MMIOAddr, 63003b705cfSriastradh I810_REG_SIZE, 63103b705cfSriastradh PCI_DEV_MAP_FLAG_WRITABLE, 63203b705cfSriastradh (void **) &pI810->MMIOBase); 63303b705cfSriastradh if (err) 63403b705cfSriastradh { 63503b705cfSriastradh xf86DrvMsg (scrn->scrnIndex, X_ERROR, 63603b705cfSriastradh "Unable to map mmio BAR. %s (%d)\n", 63703b705cfSriastradh strerror (err), err); 63803b705cfSriastradh return FALSE; 63903b705cfSriastradh } 64003b705cfSriastradh return TRUE; 64103b705cfSriastradh} 64203b705cfSriastradh 64303b705cfSriastradhstatic Bool 64403b705cfSriastradhI810MapMem(ScrnInfoPtr scrn) 64503b705cfSriastradh{ 64603b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 64703b705cfSriastradh struct pci_device *const device = pI810->PciInfo; 64803b705cfSriastradh int err; 64903b705cfSriastradh 65003b705cfSriastradh if (!I810MapMMIO(scrn)) 65103b705cfSriastradh return FALSE; 65203b705cfSriastradh 65303b705cfSriastradh err = pci_device_map_range (device, 65403b705cfSriastradh pI810->LinearAddr, 65503b705cfSriastradh pI810->FbMapSize, 65603b705cfSriastradh PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, 65703b705cfSriastradh (void **) &pI810->FbBase); 65803b705cfSriastradh if (err) 65903b705cfSriastradh { 66003b705cfSriastradh xf86DrvMsg (scrn->scrnIndex, X_ERROR, 66103b705cfSriastradh "Unable to map frame buffer BAR. %s (%d)\n", 66203b705cfSriastradh strerror (err), err); 66303b705cfSriastradh return FALSE; 66403b705cfSriastradh } 66503b705cfSriastradh 66603b705cfSriastradh pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; 66703b705cfSriastradh 66803b705cfSriastradh return TRUE; 66903b705cfSriastradh} 67003b705cfSriastradh 67103b705cfSriastradhstatic void 67203b705cfSriastradhI810UnmapMMIO(ScrnInfoPtr scrn) 67303b705cfSriastradh{ 67403b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 67503b705cfSriastradh 67603b705cfSriastradh pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE); 67703b705cfSriastradh pI810->MMIOBase = NULL; 67803b705cfSriastradh} 67903b705cfSriastradh 68003b705cfSriastradhstatic Bool 68103b705cfSriastradhI810UnmapMem(ScrnInfoPtr scrn) 68203b705cfSriastradh{ 68303b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 68403b705cfSriastradh 68503b705cfSriastradh pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize); 68603b705cfSriastradh pI810->FbBase = NULL; 68703b705cfSriastradh I810UnmapMMIO(scrn); 68803b705cfSriastradh return TRUE; 68903b705cfSriastradh} 69003b705cfSriastradh 69103b705cfSriastradh/* Famous last words 69203b705cfSriastradh */ 69303b705cfSriastradhvoid 69403b705cfSriastradhI810PrintErrorState(ScrnInfoPtr scrn) 69503b705cfSriastradh{ 69603b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 69703b705cfSriastradh 69803b705cfSriastradh ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", 69903b705cfSriastradh (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR)); 70003b705cfSriastradh 70103b705cfSriastradh ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR), 70203b705cfSriastradh (unsigned long) INREG(IPEHR)); 70303b705cfSriastradh 70403b705cfSriastradh ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", 70503b705cfSriastradh (unsigned long) INREG(LP_RING + RING_TAIL), 70603b705cfSriastradh (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR, 70703b705cfSriastradh (unsigned long) INREG(LP_RING + RING_LEN), 70803b705cfSriastradh (unsigned long) INREG(LP_RING + RING_START)); 70903b705cfSriastradh 71003b705cfSriastradh ErrorF("eir: %x esr: %x emr: %x\n", 71103b705cfSriastradh INREG16(EIR), INREG16(ESR), INREG16(EMR)); 71203b705cfSriastradh 71303b705cfSriastradh ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); 71403b705cfSriastradh 71503b705cfSriastradh ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE), 71603b705cfSriastradh (unsigned long) INREG(INST_PS)); 71703b705cfSriastradh 71803b705cfSriastradh ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", 71903b705cfSriastradh INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); 72003b705cfSriastradh} 72103b705cfSriastradh 72203b705cfSriastradh/* 72303b705cfSriastradh * I810Save -- 72403b705cfSriastradh * 72503b705cfSriastradh * This function saves the video state. It reads all of the SVGA registers 72603b705cfSriastradh * into the vgaI810Rec data structure. There is in general no need to 72703b705cfSriastradh * mask out bits here - just read the registers. 72803b705cfSriastradh */ 72903b705cfSriastradhstatic void 73003b705cfSriastradhDoSave(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, 73103b705cfSriastradh Bool saveFonts) 73203b705cfSriastradh{ 73303b705cfSriastradh I810Ptr pI810; 73403b705cfSriastradh vgaHWPtr hwp; 73503b705cfSriastradh int i; 73603b705cfSriastradh 73703b705cfSriastradh pI810 = I810PTR(scrn); 73803b705cfSriastradh hwp = VGAHWPTR(scrn); 73903b705cfSriastradh 74003b705cfSriastradh /* 74103b705cfSriastradh * This function will handle creating the data structure and filling 74203b705cfSriastradh * in the generic VGA portion. 74303b705cfSriastradh */ 74403b705cfSriastradh if (saveFonts) 74503b705cfSriastradh vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP); 74603b705cfSriastradh else 74703b705cfSriastradh vgaHWSave(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 74803b705cfSriastradh 74903b705cfSriastradh /* 75003b705cfSriastradh * The port I/O code necessary to read in the extended registers 75103b705cfSriastradh * into the fields of the vgaI810Rec structure goes here. 75203b705cfSriastradh */ 75303b705cfSriastradh i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL); 75403b705cfSriastradh i810Reg->AddressMapping = hwp->readGr(hwp, ADDRESS_MAPPING); 75503b705cfSriastradh i810Reg->BitBLTControl = INREG8(BITBLT_CNTL); 75603b705cfSriastradh i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M); 75703b705cfSriastradh i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N); 75803b705cfSriastradh i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL); 75903b705cfSriastradh 76003b705cfSriastradh i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL); 76103b705cfSriastradh i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY); 76203b705cfSriastradh i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START); 76303b705cfSriastradh i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START); 76403b705cfSriastradh i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL); 76503b705cfSriastradh i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK); 76603b705cfSriastradh i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET); 76703b705cfSriastradh i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL); 76803b705cfSriastradh 76903b705cfSriastradh i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0); 77003b705cfSriastradh i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1); 77103b705cfSriastradh i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2); 77203b705cfSriastradh i810Reg->DisplayControl = INREG8(DISPLAY_CNTL); 77303b705cfSriastradh i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC); 77403b705cfSriastradh 77503b705cfSriastradh for (i = 0; i < 8; i++) 77603b705cfSriastradh i810Reg->Fence[i] = INREG(FENCE + i * 4); 77703b705cfSriastradh 77803b705cfSriastradh i810Reg->LprbTail = INREG(LP_RING + RING_TAIL); 77903b705cfSriastradh i810Reg->LprbHead = INREG(LP_RING + RING_HEAD); 78003b705cfSriastradh i810Reg->LprbStart = INREG(LP_RING + RING_START); 78103b705cfSriastradh i810Reg->LprbLen = INREG(LP_RING + RING_LEN); 78203b705cfSriastradh 78303b705cfSriastradh if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) && 78403b705cfSriastradh i810Reg->LprbLen & RING_VALID) { 78503b705cfSriastradh I810PrintErrorState(scrn); 78603b705cfSriastradh FatalError("Active ring not flushed\n"); 78703b705cfSriastradh } 78803b705cfSriastradh} 78903b705cfSriastradh 79003b705cfSriastradhstatic void 79103b705cfSriastradhI810Save(ScrnInfoPtr scrn) 79203b705cfSriastradh{ 79303b705cfSriastradh vgaHWPtr hwp; 79403b705cfSriastradh I810Ptr pI810; 79503b705cfSriastradh uint32_t temp; 79603b705cfSriastradh 79703b705cfSriastradh hwp = VGAHWPTR(scrn); 79803b705cfSriastradh pI810 = I810PTR(scrn); 79903b705cfSriastradh DoSave(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); 80003b705cfSriastradh 80103b705cfSriastradh temp = INREG(MEMMODE); 80203b705cfSriastradh temp |= 4; 80303b705cfSriastradh OUTREG(MEMMODE, temp); 80403b705cfSriastradh} 80503b705cfSriastradh 80603b705cfSriastradhstatic void 80703b705cfSriastradhi810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode) 80803b705cfSriastradh{ 80903b705cfSriastradh int i; 81003b705cfSriastradh 81103b705cfSriastradh ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg); 81203b705cfSriastradh 81303b705cfSriastradh ErrorF("SEQ: "); 81403b705cfSriastradh for (i = 0; i < vgaReg->numSequencer; i++) { 81503b705cfSriastradh if ((i & 7) == 0) 81603b705cfSriastradh ErrorF("\n"); 81703b705cfSriastradh ErrorF(" %d: %x", i, vgaReg->Sequencer[i]); 81803b705cfSriastradh } 81903b705cfSriastradh ErrorF("\n"); 82003b705cfSriastradh 82103b705cfSriastradh ErrorF("CRTC: "); 82203b705cfSriastradh for (i = 0; i < vgaReg->numCRTC; i++) { 82303b705cfSriastradh if ((i & 3) == 0) 82403b705cfSriastradh ErrorF("\n"); 82503b705cfSriastradh ErrorF(" %d: %x", i, vgaReg->CRTC[i]); 82603b705cfSriastradh } 82703b705cfSriastradh ErrorF("\n"); 82803b705cfSriastradh 82903b705cfSriastradh ErrorF("GFX: "); 83003b705cfSriastradh for (i = 0; i < vgaReg->numGraphics; i++) { 83103b705cfSriastradh if ((i & 7) == 0) 83203b705cfSriastradh ErrorF("\n"); 83303b705cfSriastradh ErrorF(" %d: %x", i, vgaReg->Graphics[i]); 83403b705cfSriastradh } 83503b705cfSriastradh ErrorF("\n"); 83603b705cfSriastradh 83703b705cfSriastradh ErrorF("ATTR: "); 83803b705cfSriastradh for (i = 0; i < vgaReg->numAttribute; i++) { 83903b705cfSriastradh if ((i & 7) == 0) 84003b705cfSriastradh ErrorF("\n"); 84103b705cfSriastradh ErrorF(" %d: %x", i, vgaReg->Attribute[i]); 84203b705cfSriastradh } 84303b705cfSriastradh ErrorF("\n"); 84403b705cfSriastradh 84503b705cfSriastradh ErrorF(" DisplayControl: %x\n", mode->DisplayControl); 84603b705cfSriastradh ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0); 84703b705cfSriastradh ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1); 84803b705cfSriastradh ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2); 84903b705cfSriastradh ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M); 85003b705cfSriastradh ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N); 85103b705cfSriastradh ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel); 85203b705cfSriastradh ErrorF(" AddressMapping: %x\n", mode->AddressMapping); 85303b705cfSriastradh ErrorF(" IOControl: %x\n", mode->IOControl); 85403b705cfSriastradh ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl); 85503b705cfSriastradh ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal); 85603b705cfSriastradh ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd); 85703b705cfSriastradh ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart); 85803b705cfSriastradh ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart); 85903b705cfSriastradh ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal); 86003b705cfSriastradh ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank); 86103b705cfSriastradh ErrorF(" ExtOffset: %x\n", mode->ExtOffset); 86203b705cfSriastradh ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl); 86303b705cfSriastradh ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark); 86403b705cfSriastradh ErrorF(" LprbTail: %x\n", mode->LprbTail); 86503b705cfSriastradh ErrorF(" LprbHead: %x\n", mode->LprbHead); 86603b705cfSriastradh ErrorF(" LprbStart: %x\n", mode->LprbStart); 86703b705cfSriastradh ErrorF(" LprbLen: %x\n", mode->LprbLen); 86803b705cfSriastradh} 86903b705cfSriastradh 87003b705cfSriastradhstatic void 87103b705cfSriastradhDoRestore(ScrnInfoPtr scrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, 87203b705cfSriastradh Bool restoreFonts) 87303b705cfSriastradh{ 87403b705cfSriastradh I810Ptr pI810; 87503b705cfSriastradh vgaHWPtr hwp; 87603b705cfSriastradh unsigned char temp; 87703b705cfSriastradh unsigned int itemp; 87803b705cfSriastradh int i; 87903b705cfSriastradh 88003b705cfSriastradh pI810 = I810PTR(scrn); 88103b705cfSriastradh hwp = VGAHWPTR(scrn); 88203b705cfSriastradh 88303b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_VGA) { 88403b705cfSriastradh ErrorF("Setting mode in I810Restore:\n"); 88503b705cfSriastradh i810PrintMode(vgaReg, i810Reg); 88603b705cfSriastradh } 88703b705cfSriastradh 88803b705cfSriastradh vgaHWProtect(scrn, TRUE); 88903b705cfSriastradh 89003b705cfSriastradh usleep(50000); 89103b705cfSriastradh 89203b705cfSriastradh /* Turn off DRAM Refresh */ 89303b705cfSriastradh temp = INREG8(DRAM_ROW_CNTL_HI); 89403b705cfSriastradh temp &= ~DRAM_REFRESH_RATE; 89503b705cfSriastradh temp |= DRAM_REFRESH_DISABLE; 89603b705cfSriastradh OUTREG8(DRAM_ROW_CNTL_HI, temp); 89703b705cfSriastradh 89803b705cfSriastradh usleep(1000); /* Wait 1 ms */ 89903b705cfSriastradh 90003b705cfSriastradh /* Write the M, N and P values */ 90103b705cfSriastradh OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M); 90203b705cfSriastradh OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N); 90303b705cfSriastradh OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel); 90403b705cfSriastradh 90503b705cfSriastradh /* 90603b705cfSriastradh * Turn on 8 bit dac mode, if requested. This is needed to make 90703b705cfSriastradh * sure that vgaHWRestore writes the values into the DAC properly. 90803b705cfSriastradh * The problem occurs if 8 bit dac mode is requested and the HW is 90903b705cfSriastradh * in 6 bit dac mode. If this happens, all the values are 91003b705cfSriastradh * automatically shifted left twice by the HW and incorrect colors 91103b705cfSriastradh * will be displayed on the screen. The only time this can happen 91203b705cfSriastradh * is at server startup time and when switching back from a VT. 91303b705cfSriastradh */ 91403b705cfSriastradh temp = INREG8(PIXPIPE_CONFIG_0); 91503b705cfSriastradh temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ 91603b705cfSriastradh temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT); 91703b705cfSriastradh OUTREG8(PIXPIPE_CONFIG_0, temp); 91803b705cfSriastradh 91903b705cfSriastradh /* 92003b705cfSriastradh * Code to restore any SVGA registers that have been saved/modified 92103b705cfSriastradh * goes here. Note that it is allowable, and often correct, to 92203b705cfSriastradh * only modify certain bits in a register by a read/modify/write cycle. 92303b705cfSriastradh * 92403b705cfSriastradh * A special case - when using an external clock-setting program, 92503b705cfSriastradh * this function must not change bits associated with the clock 92603b705cfSriastradh * selection. This condition can be checked by the condition: 92703b705cfSriastradh * 92803b705cfSriastradh * if (i810Reg->std.NoClock >= 0) 92903b705cfSriastradh * restore clock-select bits. 93003b705cfSriastradh */ 93103b705cfSriastradh if (restoreFonts) 93203b705cfSriastradh vgaHWRestore(scrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); 93303b705cfSriastradh else 93403b705cfSriastradh vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 93503b705cfSriastradh 93603b705cfSriastradh hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal); 93703b705cfSriastradh hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd); 93803b705cfSriastradh hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart); 93903b705cfSriastradh hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart); 94003b705cfSriastradh hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal); 94103b705cfSriastradh hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank); 94203b705cfSriastradh hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset); 94303b705cfSriastradh 94403b705cfSriastradh temp = hwp->readCrtc(hwp, INTERLACE_CNTL); 94503b705cfSriastradh temp &= ~INTERLACE_ENABLE; 94603b705cfSriastradh temp |= i810Reg->InterlaceControl; 94703b705cfSriastradh hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); 94803b705cfSriastradh 94903b705cfSriastradh temp = hwp->readGr(hwp, ADDRESS_MAPPING); 95003b705cfSriastradh temp &= 0xE0; /* Save reserved bits 7:5 */ 95103b705cfSriastradh temp |= i810Reg->AddressMapping; 95203b705cfSriastradh hwp->writeGr(hwp, ADDRESS_MAPPING, temp); 95303b705cfSriastradh 95403b705cfSriastradh /* Setting the OVRACT Register for video overlay */ 95503b705cfSriastradh { 95603b705cfSriastradh uint32_t LCD_TV_Control = INREG(LCD_TV_C); 95703b705cfSriastradh uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL); 95803b705cfSriastradh uint32_t ActiveStart, ActiveEnd; 95903b705cfSriastradh 96003b705cfSriastradh if((LCD_TV_Control & LCD_TV_ENABLE) 96103b705cfSriastradh && !(LCD_TV_Control & LCD_TV_VGAMOD) 96203b705cfSriastradh && TV_HTotal) { 96303b705cfSriastradh ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31; 96403b705cfSriastradh ActiveEnd = (TV_HTotal & 0x3ff) - 31; 96503b705cfSriastradh } else { 96603b705cfSriastradh ActiveStart = i810Reg->OverlayActiveStart; 96703b705cfSriastradh ActiveEnd = i810Reg->OverlayActiveEnd; 96803b705cfSriastradh } 96903b705cfSriastradh OUTREG(LCD_TV_OVRACT, 97003b705cfSriastradh (ActiveEnd << 16) | ActiveStart); 97103b705cfSriastradh } 97203b705cfSriastradh 97303b705cfSriastradh /* Turn on DRAM Refresh */ 97403b705cfSriastradh temp = INREG8(DRAM_ROW_CNTL_HI); 97503b705cfSriastradh temp &= ~DRAM_REFRESH_RATE; 97603b705cfSriastradh temp |= DRAM_REFRESH_60HZ; 97703b705cfSriastradh OUTREG8(DRAM_ROW_CNTL_HI, temp); 97803b705cfSriastradh 97903b705cfSriastradh temp = INREG8(BITBLT_CNTL); 98003b705cfSriastradh temp &= ~COLEXP_MODE; 98103b705cfSriastradh temp |= i810Reg->BitBLTControl; 98203b705cfSriastradh OUTREG8(BITBLT_CNTL, temp); 98303b705cfSriastradh 98403b705cfSriastradh temp = INREG8(DISPLAY_CNTL); 98503b705cfSriastradh temp &= ~(VGA_WRAP_MODE | GUI_MODE); 98603b705cfSriastradh temp |= i810Reg->DisplayControl; 98703b705cfSriastradh OUTREG8(DISPLAY_CNTL, temp); 98803b705cfSriastradh 98903b705cfSriastradh temp = INREG8(PIXPIPE_CONFIG_0); 99003b705cfSriastradh temp &= 0x64; /* Save reserved bits 6:5,2 */ 99103b705cfSriastradh temp |= i810Reg->PixelPipeCfg0; 99203b705cfSriastradh OUTREG8(PIXPIPE_CONFIG_0, temp); 99303b705cfSriastradh 99403b705cfSriastradh temp = INREG8(PIXPIPE_CONFIG_2); 99503b705cfSriastradh temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ 99603b705cfSriastradh temp |= i810Reg->PixelPipeCfg2; 99703b705cfSriastradh OUTREG8(PIXPIPE_CONFIG_2, temp); 99803b705cfSriastradh 99903b705cfSriastradh temp = INREG8(PIXPIPE_CONFIG_1); 100003b705cfSriastradh temp &= ~DISPLAY_COLOR_MODE; 100103b705cfSriastradh temp &= 0xEF; /* Restore the CRT control bit */ 100203b705cfSriastradh temp |= i810Reg->PixelPipeCfg1; 100303b705cfSriastradh OUTREG8(PIXPIPE_CONFIG_1, temp); 100403b705cfSriastradh 100503b705cfSriastradh OUTREG16(EIR, 0); 100603b705cfSriastradh 100703b705cfSriastradh itemp = INREG(FWATER_BLC); 100803b705cfSriastradh itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK | 100903b705cfSriastradh MM_BURST_LENGTH | MM_FIFO_WATERMARK); 101003b705cfSriastradh itemp |= i810Reg->LMI_FIFO_Watermark; 101103b705cfSriastradh OUTREG(FWATER_BLC, itemp); 101203b705cfSriastradh 101303b705cfSriastradh for (i = 0; i < 8; i++) { 101403b705cfSriastradh OUTREG(FENCE + i * 4, i810Reg->Fence[i]); 101503b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_VGA) 101603b705cfSriastradh ErrorF("Fence Register : %x\n", i810Reg->Fence[i]); 101703b705cfSriastradh } 101803b705cfSriastradh 101903b705cfSriastradh /* First disable the ring buffer (Need to wait for empty first?, if so 102003b705cfSriastradh * should probably do it before entering this section) 102103b705cfSriastradh */ 102203b705cfSriastradh itemp = INREG(LP_RING + RING_LEN); 102303b705cfSriastradh itemp &= ~RING_VALID_MASK; 102403b705cfSriastradh OUTREG(LP_RING + RING_LEN, itemp); 102503b705cfSriastradh 102603b705cfSriastradh /* Set up the low priority ring buffer. 102703b705cfSriastradh */ 102803b705cfSriastradh OUTREG(LP_RING + RING_TAIL, 0); 102903b705cfSriastradh OUTREG(LP_RING + RING_HEAD, 0); 103003b705cfSriastradh 103103b705cfSriastradh pI810->LpRing->head = 0; 103203b705cfSriastradh pI810->LpRing->tail = 0; 103303b705cfSriastradh 103403b705cfSriastradh itemp = INREG(LP_RING + RING_START); 103503b705cfSriastradh itemp &= ~(START_ADDR); 103603b705cfSriastradh itemp |= i810Reg->LprbStart; 103703b705cfSriastradh OUTREG(LP_RING + RING_START, itemp); 103803b705cfSriastradh 103903b705cfSriastradh itemp = INREG(LP_RING + RING_LEN); 104003b705cfSriastradh itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); 104103b705cfSriastradh itemp |= i810Reg->LprbLen; 104203b705cfSriastradh OUTREG(LP_RING + RING_LEN, itemp); 104303b705cfSriastradh 104403b705cfSriastradh if (!(vgaReg->Attribute[0x10] & 0x1)) { 104503b705cfSriastradh usleep(50000); 104603b705cfSriastradh if (restoreFonts) 104703b705cfSriastradh vgaHWRestore(scrn, vgaReg, 104803b705cfSriastradh VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); 104903b705cfSriastradh else 105003b705cfSriastradh vgaHWRestore(scrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 105103b705cfSriastradh } 105203b705cfSriastradh 105303b705cfSriastradh vgaHWProtect(scrn, FALSE); 105403b705cfSriastradh 105503b705cfSriastradh temp = hwp->readCrtc(hwp, IO_CTNL); 105603b705cfSriastradh temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL); 105703b705cfSriastradh temp |= i810Reg->IOControl; 105803b705cfSriastradh hwp->writeCrtc(hwp, IO_CTNL, temp); 105903b705cfSriastradh} 106003b705cfSriastradh 106103b705cfSriastradhstatic void 106203b705cfSriastradhI810SetRingRegs(ScrnInfoPtr scrn) 106303b705cfSriastradh{ 106403b705cfSriastradh unsigned int itemp; 106503b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 106603b705cfSriastradh 106703b705cfSriastradh OUTREG(LP_RING + RING_TAIL, 0); 106803b705cfSriastradh OUTREG(LP_RING + RING_HEAD, 0); 106903b705cfSriastradh 107003b705cfSriastradh itemp = INREG(LP_RING + RING_START); 107103b705cfSriastradh itemp &= ~(START_ADDR); 107203b705cfSriastradh itemp |= pI810->LpRing->mem.Start; 107303b705cfSriastradh OUTREG(LP_RING + RING_START, itemp); 107403b705cfSriastradh 107503b705cfSriastradh itemp = INREG(LP_RING + RING_LEN); 107603b705cfSriastradh itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); 107703b705cfSriastradh itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID); 107803b705cfSriastradh OUTREG(LP_RING + RING_LEN, itemp); 107903b705cfSriastradh} 108003b705cfSriastradh 108103b705cfSriastradhstatic void 108203b705cfSriastradhI810Restore(ScrnInfoPtr scrn) 108303b705cfSriastradh{ 108403b705cfSriastradh vgaHWPtr hwp; 108503b705cfSriastradh I810Ptr pI810; 108603b705cfSriastradh 108703b705cfSriastradh hwp = VGAHWPTR(scrn); 108803b705cfSriastradh pI810 = I810PTR(scrn); 108903b705cfSriastradh 109003b705cfSriastradh DoRestore(scrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); 109103b705cfSriastradh} 109203b705cfSriastradh 109303b705cfSriastradh/* 109403b705cfSriastradh * I810CalcVCLK -- 109503b705cfSriastradh * 109603b705cfSriastradh * Determine the closest clock frequency to the one requested. 109703b705cfSriastradh */ 109803b705cfSriastradh 109903b705cfSriastradh#define MAX_VCO_FREQ 600.0 110003b705cfSriastradh#define TARGET_MAX_N 30 110103b705cfSriastradh#define REF_FREQ 24.0 110203b705cfSriastradh 110303b705cfSriastradh#define CALC_VCLK(m,n,p) \ 110403b705cfSriastradh (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ 110503b705cfSriastradh 110603b705cfSriastradhstatic void 110703b705cfSriastradhI810CalcVCLK(ScrnInfoPtr scrn, double freq) 110803b705cfSriastradh{ 110903b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 111003b705cfSriastradh I810RegPtr i810Reg = &pI810->ModeReg; 111103b705cfSriastradh int m, n, p; 111203b705cfSriastradh double f_out; 111303b705cfSriastradh double f_err; 111403b705cfSriastradh double f_vco; 111503b705cfSriastradh int m_best = 0, n_best = 0, p_best = 0; 111603b705cfSriastradh double f_target = freq; 111703b705cfSriastradh double err_max = 0.005; 111803b705cfSriastradh double err_target = 0.001; 111903b705cfSriastradh double err_best = 999999.0; 112003b705cfSriastradh 112103b705cfSriastradh p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2); 112203b705cfSriastradh /* Make sure p is within range. */ 112303b705cfSriastradh if (p_best > 5) { 112403b705cfSriastradh p_best = p = 5; 112503b705cfSriastradh } 112603b705cfSriastradh 112703b705cfSriastradh f_vco = f_target * (1 << p); 112803b705cfSriastradh 112903b705cfSriastradh n = 2; 113003b705cfSriastradh do { 113103b705cfSriastradh n++; 113203b705cfSriastradh m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; 113303b705cfSriastradh if (m < 3) 113403b705cfSriastradh m = 3; 113503b705cfSriastradh f_out = CALC_VCLK(m, n, p); 113603b705cfSriastradh f_err = 1.0 - (f_target / f_out); 113703b705cfSriastradh if (fabs(f_err) < err_max) { 113803b705cfSriastradh m_best = m; 113903b705cfSriastradh n_best = n; 114003b705cfSriastradh err_best = f_err; 114103b705cfSriastradh } 114203b705cfSriastradh } while ((fabs(f_err) >= err_target) && 114303b705cfSriastradh ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); 114403b705cfSriastradh 114503b705cfSriastradh if (fabs(f_err) < err_target) { 114603b705cfSriastradh m_best = m; 114703b705cfSriastradh n_best = n; 114803b705cfSriastradh } 114903b705cfSriastradh 115003b705cfSriastradh i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF; 115103b705cfSriastradh i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF; 115203b705cfSriastradh i810Reg->VideoClk2_DivisorSel = (p_best << 4); 115303b705cfSriastradh 115403b705cfSriastradh xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, 3, 115503b705cfSriastradh "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] " 115603b705cfSriastradh "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best), 115703b705cfSriastradh i810Reg->VideoClk2_M, i810Reg->VideoClk2_N, 115803b705cfSriastradh i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best); 115903b705cfSriastradh} 116003b705cfSriastradh 116103b705cfSriastradhstatic Bool 116203b705cfSriastradhI810SetMode(ScrnInfoPtr scrn, DisplayModePtr mode) 116303b705cfSriastradh{ 116403b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 116503b705cfSriastradh I810RegPtr i810Reg = &pI810->ModeReg; 116603b705cfSriastradh vgaRegPtr pVga = &VGAHWPTR(scrn)->ModeReg; 116703b705cfSriastradh double dclk = mode->Clock / 1000.0; 116803b705cfSriastradh 116903b705cfSriastradh switch (scrn->bitsPerPixel) { 117003b705cfSriastradh case 8: 117103b705cfSriastradh pVga->CRTC[0x13] = scrn->displayWidth >> 3; 117203b705cfSriastradh i810Reg->ExtOffset = scrn->displayWidth >> 11; 117303b705cfSriastradh i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE; 117403b705cfSriastradh i810Reg->BitBLTControl = COLEXP_8BPP; 117503b705cfSriastradh break; 117603b705cfSriastradh case 16: 117703b705cfSriastradh if (scrn->weight.green == 5) { 117803b705cfSriastradh i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE; 117903b705cfSriastradh } else { 118003b705cfSriastradh i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE; 118103b705cfSriastradh } 118203b705cfSriastradh pVga->CRTC[0x13] = scrn->displayWidth >> 2; 118303b705cfSriastradh i810Reg->ExtOffset = scrn->displayWidth >> 10; 118403b705cfSriastradh i810Reg->BitBLTControl = COLEXP_16BPP; 118503b705cfSriastradh 118603b705cfSriastradh /* Enable Palette Programming for Direct Color visuals. -jens */ 118703b705cfSriastradh i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; 118803b705cfSriastradh break; 118903b705cfSriastradh case 24: 119003b705cfSriastradh pVga->CRTC[0x13] = (scrn->displayWidth * 3) >> 3; 119103b705cfSriastradh i810Reg->ExtOffset = (scrn->displayWidth * 3) >> 11; 119203b705cfSriastradh 119303b705cfSriastradh i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE; 119403b705cfSriastradh i810Reg->BitBLTControl = COLEXP_24BPP; 119503b705cfSriastradh 119603b705cfSriastradh /* Enable Palette Programming for Direct Color visuals. -jens */ 119703b705cfSriastradh i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; 119803b705cfSriastradh break; 119903b705cfSriastradh default: 120003b705cfSriastradh break; 120103b705cfSriastradh } 120203b705cfSriastradh 120303b705cfSriastradh /* Turn on 8 bit dac if requested */ 120403b705cfSriastradh if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) 120503b705cfSriastradh i810Reg->PixelPipeCfg0 = DAC_6_BIT; 120603b705cfSriastradh else 120703b705cfSriastradh i810Reg->PixelPipeCfg0 = DAC_8_BIT; 120803b705cfSriastradh 120903b705cfSriastradh /* Do not delay CRT Blank: needed for video overlay */ 121003b705cfSriastradh i810Reg->PixelPipeCfg1 |= 0x10; 121103b705cfSriastradh 121203b705cfSriastradh /* Turn on Extended VGA Interpretation */ 121303b705cfSriastradh i810Reg->IOControl = EXTENDED_CRTC_CNTL; 121403b705cfSriastradh 121503b705cfSriastradh /* Turn on linear and page mapping */ 121603b705cfSriastradh i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE); 121703b705cfSriastradh 121803b705cfSriastradh /* Turn on GUI mode */ 121903b705cfSriastradh i810Reg->DisplayControl = HIRES_MODE; 122003b705cfSriastradh 122103b705cfSriastradh /* Calculate the extended CRTC regs */ 122203b705cfSriastradh i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8; 122303b705cfSriastradh i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8; 122403b705cfSriastradh i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8; 122503b705cfSriastradh i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8; 122603b705cfSriastradh i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8; 122703b705cfSriastradh i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6; 122803b705cfSriastradh 122903b705cfSriastradh /* 123003b705cfSriastradh * the KGA fix in vgaHW.c results in the first 123103b705cfSriastradh * scanline and the first character clock (8 pixels) 123203b705cfSriastradh * of each scanline thereafter on display with an i810 123303b705cfSriastradh * to be blank. Restoring CRTC 3, 5, & 22 to their 123403b705cfSriastradh * "theoretical" values corrects the problem. KAO. 123503b705cfSriastradh */ 123603b705cfSriastradh pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; 123703b705cfSriastradh pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) 123803b705cfSriastradh | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); 123903b705cfSriastradh pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 124003b705cfSriastradh 124103b705cfSriastradh i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0); 124203b705cfSriastradh vgaHWVBlankKGA(mode, pVga, 8, 0); 124303b705cfSriastradh 124403b705cfSriastradh /* 124503b705cfSriastradh * The following workarounds are needed to get video overlay working 124603b705cfSriastradh * at 1024x768 and 1280x1024 display resolutions. 124703b705cfSriastradh */ 124803b705cfSriastradh if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) { 124903b705cfSriastradh i810Reg->ExtVertBlankStart = 2; 125003b705cfSriastradh } 125103b705cfSriastradh if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) { 125203b705cfSriastradh i810Reg->ExtVertBlankStart = 3; 125303b705cfSriastradh } 125403b705cfSriastradh 125503b705cfSriastradh /* OVRACT Register */ 125603b705cfSriastradh i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32; 125703b705cfSriastradh i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32; 125803b705cfSriastradh 125903b705cfSriastradh /* Turn on interlaced mode if necessary */ 126003b705cfSriastradh if (mode->Flags & V_INTERLACE) { 126103b705cfSriastradh i810Reg->InterlaceControl = INTERLACE_ENABLE; 126203b705cfSriastradh i810Reg->ExtVertDispEnd *= 2; 126303b705cfSriastradh } else 126403b705cfSriastradh i810Reg->InterlaceControl = INTERLACE_DISABLE; 126503b705cfSriastradh 126603b705cfSriastradh /* 126703b705cfSriastradh * Set the overscan color to 0. 126803b705cfSriastradh * NOTE: This only affects >8bpp mode. 126903b705cfSriastradh */ 127003b705cfSriastradh pVga->Attribute[0x11] = 0; 127103b705cfSriastradh 127203b705cfSriastradh /* 127303b705cfSriastradh * Calculate the VCLK that most closely matches the requested dot 127403b705cfSriastradh * clock. 127503b705cfSriastradh */ 127603b705cfSriastradh I810CalcVCLK(scrn, dclk); 127703b705cfSriastradh 127803b705cfSriastradh /* Since we program the clocks ourselves, always use VCLK2. */ 127903b705cfSriastradh pVga->MiscOutReg |= 0x0C; 128003b705cfSriastradh 128103b705cfSriastradh /* Calculate the FIFO Watermark and Burst Length. */ 128203b705cfSriastradh i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(scrn, dclk, FALSE); 128303b705cfSriastradh 128403b705cfSriastradh /* Setup the ring buffer */ 128503b705cfSriastradh i810Reg->LprbTail = 0; 128603b705cfSriastradh i810Reg->LprbHead = 0; 128703b705cfSriastradh i810Reg->LprbStart = pI810->LpRing->mem.Start; 128803b705cfSriastradh 128903b705cfSriastradh if (i810Reg->LprbStart) 129003b705cfSriastradh i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) | 129103b705cfSriastradh RING_NO_REPORT | RING_VALID); 129203b705cfSriastradh else 129303b705cfSriastradh i810Reg->LprbLen = RING_INVALID; 129403b705cfSriastradh 129503b705cfSriastradh return TRUE; 129603b705cfSriastradh} 129703b705cfSriastradh 129803b705cfSriastradhstatic Bool 129903b705cfSriastradhI810ModeInit(ScrnInfoPtr scrn, DisplayModePtr mode) 130003b705cfSriastradh{ 130103b705cfSriastradh vgaHWPtr hwp; 130203b705cfSriastradh I810Ptr pI810; 130303b705cfSriastradh 130403b705cfSriastradh hwp = VGAHWPTR(scrn); 130503b705cfSriastradh pI810 = I810PTR(scrn); 130603b705cfSriastradh 130703b705cfSriastradh vgaHWUnlock(hwp); 130803b705cfSriastradh 130903b705cfSriastradh if (!vgaHWInit(scrn, mode)) 131003b705cfSriastradh return FALSE; 131103b705cfSriastradh 131203b705cfSriastradh scrn->vtSema = TRUE; 131303b705cfSriastradh 131403b705cfSriastradh if (!I810SetMode(scrn, mode)) 131503b705cfSriastradh return FALSE; 131603b705cfSriastradh 131703b705cfSriastradh#ifdef HAVE_DRI1 131803b705cfSriastradh if (pI810->directRenderingEnabled) { 131903b705cfSriastradh DRILock(xf86ScrnToScreen(scrn), 0); 132003b705cfSriastradh pI810->LockHeld = 1; 132103b705cfSriastradh } 132203b705cfSriastradh#endif 132303b705cfSriastradh 132403b705cfSriastradh DoRestore(scrn, &hwp->ModeReg, &pI810->ModeReg, FALSE); 132503b705cfSriastradh 132603b705cfSriastradh#ifdef HAVE_DRI1 132703b705cfSriastradh if (pI810->directRenderingEnabled) { 132803b705cfSriastradh DRIUnlock(xf86ScrnToScreen(scrn)); 132903b705cfSriastradh pI810->LockHeld = 0; 133003b705cfSriastradh } 133103b705cfSriastradh#endif 133203b705cfSriastradh 133303b705cfSriastradh return TRUE; 133403b705cfSriastradh} 133503b705cfSriastradh 133603b705cfSriastradhstatic void 133703b705cfSriastradhI810LoadPalette15(ScrnInfoPtr scrn, int numColors, int *indices, 133803b705cfSriastradh LOCO * colors, VisualPtr pVisual) 133903b705cfSriastradh{ 134003b705cfSriastradh vgaHWPtr hwp; 134103b705cfSriastradh int i, j, index; 134203b705cfSriastradh unsigned char r, g, b; 134303b705cfSriastradh 134403b705cfSriastradh hwp = VGAHWPTR(scrn); 134503b705cfSriastradh 134603b705cfSriastradh for (i = 0; i < numColors; i++) { 134703b705cfSriastradh index = indices[i]; 134803b705cfSriastradh r = colors[index].red; 134903b705cfSriastradh g = colors[index].green; 135003b705cfSriastradh b = colors[index].blue; 135103b705cfSriastradh for (j = 0; j < 8; j++) { 135203b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 3) + j); 135303b705cfSriastradh hwp->writeDacData(hwp, r); 135403b705cfSriastradh hwp->writeDacData(hwp, g); 135503b705cfSriastradh hwp->writeDacData(hwp, b); 135603b705cfSriastradh } 135703b705cfSriastradh } 135803b705cfSriastradh} 135903b705cfSriastradh 136003b705cfSriastradhstatic void 136103b705cfSriastradhI810LoadPalette16(ScrnInfoPtr scrn, int numColors, int *indices, 136203b705cfSriastradh LOCO * colors, VisualPtr pVisual) 136303b705cfSriastradh{ 136403b705cfSriastradh vgaHWPtr hwp; 136503b705cfSriastradh int i, index; 136603b705cfSriastradh unsigned char r, g, b; 136703b705cfSriastradh 136803b705cfSriastradh hwp = VGAHWPTR(scrn); 136903b705cfSriastradh 137003b705cfSriastradh /* Load all four entries in each of the 64 color ranges. -jens */ 137103b705cfSriastradh for (i = 0; i < numColors; i++) { 137203b705cfSriastradh index = indices[i / 2]; 137303b705cfSriastradh r = colors[index].red; 137403b705cfSriastradh b = colors[index].blue; 137503b705cfSriastradh index = indices[i]; 137603b705cfSriastradh g = colors[index].green; 137703b705cfSriastradh 137803b705cfSriastradh hwp->writeDacWriteAddr(hwp, index << 2); 137903b705cfSriastradh hwp->writeDacData(hwp, r); 138003b705cfSriastradh hwp->writeDacData(hwp, g); 138103b705cfSriastradh hwp->writeDacData(hwp, b); 138203b705cfSriastradh 138303b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 2) + 1); 138403b705cfSriastradh hwp->writeDacData(hwp, r); 138503b705cfSriastradh hwp->writeDacData(hwp, g); 138603b705cfSriastradh hwp->writeDacData(hwp, b); 138703b705cfSriastradh 138803b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 2) + 2); 138903b705cfSriastradh hwp->writeDacData(hwp, r); 139003b705cfSriastradh hwp->writeDacData(hwp, g); 139103b705cfSriastradh hwp->writeDacData(hwp, b); 139203b705cfSriastradh 139303b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 2) + 3); 139403b705cfSriastradh hwp->writeDacData(hwp, r); 139503b705cfSriastradh hwp->writeDacData(hwp, g); 139603b705cfSriastradh hwp->writeDacData(hwp, b); 139703b705cfSriastradh 139803b705cfSriastradh i++; 139903b705cfSriastradh index = indices[i]; 140003b705cfSriastradh g = colors[index].green; 140103b705cfSriastradh 140203b705cfSriastradh hwp->writeDacWriteAddr(hwp, index << 2); 140303b705cfSriastradh hwp->writeDacData(hwp, r); 140403b705cfSriastradh hwp->writeDacData(hwp, g); 140503b705cfSriastradh hwp->writeDacData(hwp, b); 140603b705cfSriastradh 140703b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 2) + 1); 140803b705cfSriastradh hwp->writeDacData(hwp, r); 140903b705cfSriastradh hwp->writeDacData(hwp, g); 141003b705cfSriastradh hwp->writeDacData(hwp, b); 141103b705cfSriastradh 141203b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 2) + 2); 141303b705cfSriastradh hwp->writeDacData(hwp, r); 141403b705cfSriastradh hwp->writeDacData(hwp, g); 141503b705cfSriastradh hwp->writeDacData(hwp, b); 141603b705cfSriastradh 141703b705cfSriastradh hwp->writeDacWriteAddr(hwp, (index << 2) + 3); 141803b705cfSriastradh hwp->writeDacData(hwp, r); 141903b705cfSriastradh hwp->writeDacData(hwp, g); 142003b705cfSriastradh hwp->writeDacData(hwp, b); 142103b705cfSriastradh } 142203b705cfSriastradh} 142303b705cfSriastradh 142403b705cfSriastradhstatic void 142503b705cfSriastradhI810LoadPalette24(ScrnInfoPtr scrn, int numColors, int *indices, 142603b705cfSriastradh LOCO * colors, VisualPtr pVisual) 142703b705cfSriastradh{ 142803b705cfSriastradh vgaHWPtr hwp; 142903b705cfSriastradh int i, index; 143003b705cfSriastradh unsigned char r, g, b; 143103b705cfSriastradh 143203b705cfSriastradh hwp = VGAHWPTR(scrn); 143303b705cfSriastradh 143403b705cfSriastradh for (i = 0; i < numColors; i++) { 143503b705cfSriastradh index = indices[i]; 143603b705cfSriastradh r = colors[index].red; 143703b705cfSriastradh g = colors[index].green; 143803b705cfSriastradh b = colors[index].blue; 143903b705cfSriastradh hwp->writeDacWriteAddr(hwp, index); 144003b705cfSriastradh hwp->writeDacData(hwp, r); 144103b705cfSriastradh hwp->writeDacData(hwp, g); 144203b705cfSriastradh hwp->writeDacData(hwp, b); 144303b705cfSriastradh } 144403b705cfSriastradh} 144503b705cfSriastradh 144603b705cfSriastradhBool 144703b705cfSriastradhI810AllocateFront(ScrnInfoPtr scrn) 144803b705cfSriastradh{ 144903b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 145003b705cfSriastradh int cache_lines = -1; 145103b705cfSriastradh 145203b705cfSriastradh if (pI810->DoneFrontAlloc) 145303b705cfSriastradh return TRUE; 145403b705cfSriastradh 145503b705cfSriastradh memset(&(pI810->FbMemBox), 0, sizeof(BoxRec)); 145603b705cfSriastradh /* Alloc FrontBuffer/Ring/Accel memory */ 145703b705cfSriastradh pI810->FbMemBox.x1 = 0; 145803b705cfSriastradh pI810->FbMemBox.x2 = scrn->displayWidth; 145903b705cfSriastradh pI810->FbMemBox.y1 = 0; 146003b705cfSriastradh pI810->FbMemBox.y2 = scrn->virtualY; 146103b705cfSriastradh 146203b705cfSriastradh xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines); 146303b705cfSriastradh 146403b705cfSriastradh if (cache_lines < 0) { 146503b705cfSriastradh /* make sure there is enough for two DVD sized YUV buffers */ 146603b705cfSriastradh cache_lines = (scrn->depth == 24) ? 256 : 384; 146703b705cfSriastradh if (scrn->displayWidth <= 1024) 146803b705cfSriastradh cache_lines *= 2; 146903b705cfSriastradh } 147003b705cfSriastradh /* Make sure there's enough space for cache_lines. 147103b705cfSriastradh * 147203b705cfSriastradh * Had a bug here where maxCacheLines was computed to be less than 0. 147303b705cfSriastradh * Not sure why 256 was initially subtracted from videoRam in the 147403b705cfSriastradh * maxCacheLines calculation, but that was causing a problem 147503b705cfSriastradh * for configurations that have exactly enough Ram for the framebuffer. 147603b705cfSriastradh * Common code should catch the case where there isn't enough space for 147703b705cfSriastradh * framebuffer, we'll just check for no space for cache_lines. -jens 147803b705cfSriastradh * 147903b705cfSriastradh */ 148003b705cfSriastradh { 148103b705cfSriastradh int maxCacheLines; 148203b705cfSriastradh 148303b705cfSriastradh maxCacheLines = (scrn->videoRam * 1024 / 148403b705cfSriastradh (scrn->bitsPerPixel / 8) / 148503b705cfSriastradh scrn->displayWidth) - scrn->virtualY; 148603b705cfSriastradh if (maxCacheLines < 0) 148703b705cfSriastradh maxCacheLines = 0; 148803b705cfSriastradh if (cache_lines > maxCacheLines) 148903b705cfSriastradh cache_lines = maxCacheLines; 149003b705cfSriastradh } 149103b705cfSriastradh pI810->FbMemBox.y2 += cache_lines; 149203b705cfSriastradh 149303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, 149403b705cfSriastradh "Adding %i scanlines for pixmap caching\n", cache_lines); 149503b705cfSriastradh 149603b705cfSriastradh /* Reserve room for the framebuffer and pixcache. Put at the top 149703b705cfSriastradh * of memory so we can have nice alignment for the tiled regions at 149803b705cfSriastradh * the start of memory. 149903b705cfSriastradh */ 150003b705cfSriastradh 150103b705cfSriastradh if (!I810AllocLow(&(pI810->FrontBuffer), 150203b705cfSriastradh &(pI810->SysMem), 150303b705cfSriastradh ALIGN((pI810->FbMemBox.x2 * pI810->FbMemBox.y2 * pI810->cpp), 4096))) { 150403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, 150503b705cfSriastradh X_WARNING, "Framebuffer allocation failed\n"); 150603b705cfSriastradh return FALSE; 150703b705cfSriastradh } 150803b705cfSriastradh 150903b705cfSriastradh memset(pI810->LpRing, 0, sizeof(I810RingBuffer)); 151003b705cfSriastradh if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) { 151103b705cfSriastradh pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1; 151203b705cfSriastradh pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; 151303b705cfSriastradh pI810->LpRing->head = 0; 151403b705cfSriastradh pI810->LpRing->tail = 0; 151503b705cfSriastradh pI810->LpRing->space = 0; 151603b705cfSriastradh } else { 151703b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 151803b705cfSriastradh "Ring buffer allocation failed\n"); 151903b705cfSriastradh return (FALSE); 152003b705cfSriastradh } 152103b705cfSriastradh 152203b705cfSriastradh if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) || 152303b705cfSriastradh I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) { 152403b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n"); 152503b705cfSriastradh } else { 152603b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 152703b705cfSriastradh "Scratch memory allocation failed\n"); 152803b705cfSriastradh return (FALSE); 152903b705cfSriastradh } 153003b705cfSriastradh 153103b705cfSriastradh pI810->DoneFrontAlloc = TRUE; 153203b705cfSriastradh return TRUE; 153303b705cfSriastradh} 153403b705cfSriastradh 153503b705cfSriastradhstatic Bool 153603b705cfSriastradhI810ScreenInit(SCREEN_INIT_ARGS_DECL) 153703b705cfSriastradh{ 153803b705cfSriastradh ScrnInfoPtr scrn; 153903b705cfSriastradh vgaHWPtr hwp; 154003b705cfSriastradh I810Ptr pI810; 154103b705cfSriastradh VisualPtr visual; 154203b705cfSriastradh 154303b705cfSriastradh scrn = xf86ScreenToScrn(screen); 154403b705cfSriastradh pI810 = I810PTR(scrn); 154503b705cfSriastradh hwp = VGAHWPTR(scrn); 154603b705cfSriastradh 154703b705cfSriastradh pI810->LpRing = calloc(sizeof(I810RingBuffer),1); 154803b705cfSriastradh if (!pI810->LpRing) { 154903b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 155003b705cfSriastradh "Could not allocate lpring data structure.\n"); 155103b705cfSriastradh return FALSE; 155203b705cfSriastradh } 155303b705cfSriastradh 155403b705cfSriastradh miClearVisualTypes(); 155503b705cfSriastradh 155603b705cfSriastradh /* Re-implemented Direct Color support, -jens */ 155703b705cfSriastradh if (!miSetVisualTypes(scrn->depth, miGetDefaultVisualMask(scrn->depth), 155803b705cfSriastradh scrn->rgbBits, scrn->defaultVisual)) 155903b705cfSriastradh return FALSE; 156003b705cfSriastradh 156103b705cfSriastradh if (!miSetPixmapDepths()) 156203b705cfSriastradh return FALSE; 156303b705cfSriastradh 156403b705cfSriastradh { 156503b705cfSriastradh I810RegPtr i810Reg = &pI810->ModeReg; 156603b705cfSriastradh int i; 156703b705cfSriastradh 156803b705cfSriastradh for (i = 0; i < 8; i++) 156903b705cfSriastradh i810Reg->Fence[i] = 0; 157003b705cfSriastradh } 157103b705cfSriastradh 157203b705cfSriastradh /* Have to init the DRM earlier than in other drivers to get agp 157303b705cfSriastradh * memory. Wonder if this is going to be a problem... 157403b705cfSriastradh */ 157503b705cfSriastradh 157603b705cfSriastradh#ifdef HAVE_DRI1 157703b705cfSriastradh /* 157803b705cfSriastradh * Setup DRI after visuals have been established, but before fbScreenInit 157903b705cfSriastradh * is called. fbScreenInit will eventually call into the drivers 158003b705cfSriastradh * InitGLXVisuals call back. 158103b705cfSriastradh */ 158203b705cfSriastradh /* 158303b705cfSriastradh * pI810->directRenderingDisabled is set once in PreInit. Reinitialise 158403b705cfSriastradh * pI810->directRenderingEnabled based on it each generation. 158503b705cfSriastradh */ 158603b705cfSriastradh pI810->directRenderingEnabled = !pI810->directRenderingDisabled; 158703b705cfSriastradh 158803b705cfSriastradh if (pI810->directRenderingEnabled==TRUE) 158903b705cfSriastradh pI810->directRenderingEnabled = I810DRIScreenInit(screen); 159003b705cfSriastradh 159103b705cfSriastradh#else 159203b705cfSriastradh pI810->directRenderingEnabled = FALSE; 159303b705cfSriastradh if (!I810AllocateGARTMemory(scrn)) 159403b705cfSriastradh return FALSE; 159503b705cfSriastradh if (!I810AllocateFront(scrn)) 159603b705cfSriastradh return FALSE; 159703b705cfSriastradh#endif 159803b705cfSriastradh 159903b705cfSriastradh if (!I810MapMem(scrn)) 160003b705cfSriastradh return FALSE; 160103b705cfSriastradh 160203b705cfSriastradh scrn->memPhysBase = (unsigned long)pI810->LinearAddr; 160303b705cfSriastradh scrn->fbOffset = 0; 160403b705cfSriastradh 160503b705cfSriastradh vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0); 160603b705cfSriastradh vgaHWGetIOBase(hwp); 160703b705cfSriastradh if (!vgaHWMapMem(scrn)) 160803b705cfSriastradh return FALSE; 160903b705cfSriastradh 161003b705cfSriastradh I810Save(scrn); 161103b705cfSriastradh if (!I810ModeInit(scrn, scrn->currentMode)) 161203b705cfSriastradh return FALSE; 161303b705cfSriastradh 161403b705cfSriastradh I810SaveScreen(screen, FALSE); 161503b705cfSriastradh I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0)); 161603b705cfSriastradh 161703b705cfSriastradh if (!fbScreenInit(screen, pI810->FbBase + scrn->fbOffset, 161803b705cfSriastradh scrn->virtualX, scrn->virtualY, 161903b705cfSriastradh scrn->xDpi, scrn->yDpi, 162003b705cfSriastradh scrn->displayWidth, scrn->bitsPerPixel)) 162103b705cfSriastradh return FALSE; 162203b705cfSriastradh 162303b705cfSriastradh if (scrn->bitsPerPixel > 8) { 162403b705cfSriastradh /* Fixup RGB ordering */ 162503b705cfSriastradh visual = screen->visuals + screen->numVisuals; 162603b705cfSriastradh while (--visual >= screen->visuals) { 162703b705cfSriastradh if ((visual->class | DynamicClass) == DirectColor) { 162803b705cfSriastradh visual->offsetRed = scrn->offset.red; 162903b705cfSriastradh visual->offsetGreen = scrn->offset.green; 163003b705cfSriastradh visual->offsetBlue = scrn->offset.blue; 163103b705cfSriastradh visual->redMask = scrn->mask.red; 163203b705cfSriastradh visual->greenMask = scrn->mask.green; 163303b705cfSriastradh visual->blueMask = scrn->mask.blue; 163403b705cfSriastradh } 163503b705cfSriastradh } 163603b705cfSriastradh } 163703b705cfSriastradh 163803b705cfSriastradh fbPictureInit(screen, NULL, 0); 163903b705cfSriastradh 164003b705cfSriastradh xf86SetBlackWhitePixels(screen); 164103b705cfSriastradh 164203b705cfSriastradh#ifdef HAVE_DRI1 164303b705cfSriastradh if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) { 164403b705cfSriastradh pI810->directRenderingEnabled = FALSE; 164503b705cfSriastradh I810DRICloseScreen(screen); 164603b705cfSriastradh } 164703b705cfSriastradh 164803b705cfSriastradh if (!pI810->directRenderingEnabled) { 164903b705cfSriastradh pI810->DoneFrontAlloc = FALSE; 165003b705cfSriastradh if (!I810AllocateGARTMemory(scrn)) 165103b705cfSriastradh return FALSE; 165203b705cfSriastradh if (!I810AllocateFront(scrn)) 165303b705cfSriastradh return FALSE; 165403b705cfSriastradh } 165503b705cfSriastradh#endif 165603b705cfSriastradh 165703b705cfSriastradh#ifdef HAVE_DGAPROC_H 165803b705cfSriastradh I810DGAInit(screen); 165903b705cfSriastradh#endif 166003b705cfSriastradh 166103b705cfSriastradh if (!xf86InitFBManager(screen, &(pI810->FbMemBox))) { 166203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 166303b705cfSriastradh "Failed to init memory manager\n"); 166403b705cfSriastradh return FALSE; 166503b705cfSriastradh } 166603b705cfSriastradh 166703b705cfSriastradh if (pI810->LpRing->mem.Size != 0) { 166803b705cfSriastradh I810SetRingRegs(scrn); 166903b705cfSriastradh 167003b705cfSriastradh if (!pI810->noAccel && !I810AccelInit(screen)) { 167103b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 167203b705cfSriastradh "Hardware acceleration initialization failed\n"); 167303b705cfSriastradh } 167403b705cfSriastradh 167503b705cfSriastradh I810EmitFlush(scrn); 167603b705cfSriastradh } 167703b705cfSriastradh 167803b705cfSriastradh xf86SetBackingStore(screen); 167903b705cfSriastradh xf86SetSilkenMouse(screen); 168003b705cfSriastradh 168103b705cfSriastradh miDCInitialize(screen, xf86GetPointerScreenFuncs()); 168203b705cfSriastradh 168303b705cfSriastradh if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { 168403b705cfSriastradh if (!I810CursorInit(screen)) { 168503b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_ERROR, 168603b705cfSriastradh "Hardware cursor initialization failed\n"); 168703b705cfSriastradh } 168803b705cfSriastradh } 168903b705cfSriastradh 169003b705cfSriastradh if (!miCreateDefColormap(screen)) 169103b705cfSriastradh return FALSE; 169203b705cfSriastradh 169303b705cfSriastradh /* Use driver specific palette load routines for Direct Color support. -jens */ 169403b705cfSriastradh if (scrn->bitsPerPixel == 16) { 169503b705cfSriastradh if (scrn->depth == 15) { 169603b705cfSriastradh if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette15, NULL, 169703b705cfSriastradh CMAP_PALETTED_TRUECOLOR | 169803b705cfSriastradh CMAP_RELOAD_ON_MODE_SWITCH)) 169903b705cfSriastradh return FALSE; 170003b705cfSriastradh } else { 170103b705cfSriastradh if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette16, NULL, 170203b705cfSriastradh CMAP_PALETTED_TRUECOLOR | 170303b705cfSriastradh CMAP_RELOAD_ON_MODE_SWITCH)) 170403b705cfSriastradh return FALSE; 170503b705cfSriastradh } 170603b705cfSriastradh } else { 170703b705cfSriastradh if (!xf86HandleColormaps(screen, 256, 8, I810LoadPalette24, NULL, 170803b705cfSriastradh CMAP_PALETTED_TRUECOLOR | 170903b705cfSriastradh CMAP_RELOAD_ON_MODE_SWITCH)) 171003b705cfSriastradh return FALSE; 171103b705cfSriastradh } 171203b705cfSriastradh 171303b705cfSriastradh xf86DPMSInit(screen, I810DisplayPowerManagementSet, 0); 171403b705cfSriastradh 171503b705cfSriastradh I810InitVideo(screen); 171603b705cfSriastradh 171703b705cfSriastradh#ifdef HAVE_DRI1 171803b705cfSriastradh if (pI810->directRenderingEnabled) { 171903b705cfSriastradh /* Now that mi, fb, drm and others have done their thing, 172003b705cfSriastradh * complete the DRI setup. 172103b705cfSriastradh */ 172203b705cfSriastradh pI810->directRenderingEnabled = I810DRIFinishScreenInit(screen); 172303b705cfSriastradh } 172403b705cfSriastradh#ifdef XvMCExtension 172503b705cfSriastradh if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) { 172603b705cfSriastradh /* Initialize the hardware motion compensation code */ 172703b705cfSriastradh I810InitMC(screen); 172803b705cfSriastradh } 172903b705cfSriastradh#endif 173003b705cfSriastradh#endif 173103b705cfSriastradh 173203b705cfSriastradh if (pI810->directRenderingEnabled) { 173303b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); 173403b705cfSriastradh } else { 173503b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); 173603b705cfSriastradh } 173703b705cfSriastradh 173803b705cfSriastradh screen->SaveScreen = I810SaveScreen; 173903b705cfSriastradh pI810->CloseScreen = screen->CloseScreen; 174003b705cfSriastradh screen->CloseScreen = I810CloseScreen; 174103b705cfSriastradh 174203b705cfSriastradh if (serverGeneration == 1) 174303b705cfSriastradh xf86ShowUnusedOptions(scrn->scrnIndex, scrn->options); 174403b705cfSriastradh 174503b705cfSriastradh return TRUE; 174603b705cfSriastradh} 174703b705cfSriastradh 174803b705cfSriastradhBool 174903b705cfSriastradhI810SwitchMode(SWITCH_MODE_ARGS_DECL) 175003b705cfSriastradh{ 175103b705cfSriastradh SCRN_INFO_PTR(arg); 175203b705cfSriastradh#if 0 175303b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 175403b705cfSriastradh#endif 175503b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) 175603b705cfSriastradh ErrorF("I810SwitchMode %p\n", (void *)mode); 175703b705cfSriastradh 175803b705cfSriastradh#if 0 175903b705cfSriastradh/* 176003b705cfSriastradh * This has been added to prevent lockups on mode switch by modeling 176103b705cfSriastradh * it after I810Leave()/I810Enter() but the call to I810DRILeave() 176203b705cfSriastradh * was missing so it caused the opposite. 176303b705cfSriastradh * The version below works but it is doubtful it does any good. 176403b705cfSriastradh * If lockups on mode switch are still seen revisit this code. (EE) 176503b705cfSriastradh */ 176603b705cfSriastradh 176703b705cfSriastradh# ifdef HAVE_DRI1 176803b705cfSriastradh if (pI810->directRenderingEnabled) { 176903b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_DRI) 177003b705cfSriastradh ErrorF("calling dri lock\n"); 177103b705cfSriastradh DRILock(screenInfo.screens[scrnIndex], 0); 177203b705cfSriastradh pI810->LockHeld = 1; 177303b705cfSriastradh } 177403b705cfSriastradh# endif 177503b705cfSriastradh if (pI810->AccelInfoRec != NULL) { 177603b705cfSriastradh I810RefreshRing(scrn); 177703b705cfSriastradh I810Sync(scrn); 177803b705cfSriastradh pI810->AccelInfoRec->NeedToSync = FALSE; 177903b705cfSriastradh } 178003b705cfSriastradh I810Restore(scrn); 178103b705cfSriastradh 178203b705cfSriastradh# ifdef HAVE_DRI1 178303b705cfSriastradh if (pI810->directRenderingEnabled) { 178403b705cfSriastradh if (!I810DRILeave(scrn)) 178503b705cfSriastradh return FALSE; 178603b705cfSriastradh if (!I810DRIEnter(scrn)) 178703b705cfSriastradh return FALSE; 178803b705cfSriastradh 178903b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_DRI) 179003b705cfSriastradh ErrorF("calling dri unlock\n"); 179103b705cfSriastradh DRIUnlock(screenInfo.screens[scrnIndex]); 179203b705cfSriastradh pI810->LockHeld = 0; 179303b705cfSriastradh } 179403b705cfSriastradh# endif 179503b705cfSriastradh#endif 179603b705cfSriastradh return I810ModeInit(scrn, mode); 179703b705cfSriastradh} 179803b705cfSriastradh 179903b705cfSriastradhvoid 180003b705cfSriastradhI810AdjustFrame(ADJUST_FRAME_ARGS_DECL) 180103b705cfSriastradh{ 180203b705cfSriastradh SCRN_INFO_PTR(arg); 180303b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 180403b705cfSriastradh vgaHWPtr hwp = VGAHWPTR(scrn); 180503b705cfSriastradh int Base; 180603b705cfSriastradh 180703b705cfSriastradh#if 1 180803b705cfSriastradh if (pI810->showCache) { 180903b705cfSriastradh int lastline = pI810->FbMapSize / 181003b705cfSriastradh ((scrn->displayWidth * scrn->bitsPerPixel) / 8); 181103b705cfSriastradh lastline -= scrn->currentMode->VDisplay; 181203b705cfSriastradh if (y > 0) 181303b705cfSriastradh y += scrn->currentMode->VDisplay; 181403b705cfSriastradh if (y > lastline) y = lastline; 181503b705cfSriastradh } 181603b705cfSriastradh#endif 181703b705cfSriastradh Base = (y * scrn->displayWidth + x) >> 2; 181803b705cfSriastradh 181903b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) 182003b705cfSriastradh ErrorF("I810AdjustFrame %d,%d\n", x, y); 182103b705cfSriastradh 182203b705cfSriastradh switch (scrn->bitsPerPixel) { 182303b705cfSriastradh case 8: 182403b705cfSriastradh break; 182503b705cfSriastradh case 16: 182603b705cfSriastradh Base *= 2; 182703b705cfSriastradh break; 182803b705cfSriastradh case 24: 182903b705cfSriastradh /* KW: Need to do 16-pixel alignment for i810, otherwise you 183003b705cfSriastradh * get bad watermark problems. Need to fixup the mouse 183103b705cfSriastradh * pointer positioning to take this into account. 183203b705cfSriastradh */ 183303b705cfSriastradh pI810->CursorOffset = (Base & 0x3) * 4; 183403b705cfSriastradh Base &= ~0x3; 183503b705cfSriastradh Base *= 3; 183603b705cfSriastradh break; 183703b705cfSriastradh case 32: 183803b705cfSriastradh Base *= 4; 183903b705cfSriastradh break; 184003b705cfSriastradh } 184103b705cfSriastradh 184203b705cfSriastradh hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF); 184303b705cfSriastradh hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8); 184403b705cfSriastradh hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22); 184503b705cfSriastradh hwp->writeCrtc(hwp, EXT_START_ADDR, 184603b705cfSriastradh ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE)); 184703b705cfSriastradh} 184803b705cfSriastradh 184903b705cfSriastradh/* These functions are usually called with the lock **not held**. 185003b705cfSriastradh */ 185103b705cfSriastradhstatic Bool 185203b705cfSriastradhI810EnterVT(VT_FUNC_ARGS_DECL) 185303b705cfSriastradh{ 185403b705cfSriastradh SCRN_INFO_PTR(arg); 185503b705cfSriastradh 185603b705cfSriastradh#ifdef HAVE_DRI1 185703b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 185803b705cfSriastradh#endif 185903b705cfSriastradh 186003b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_DRI) 186103b705cfSriastradh ErrorF("\n\nENTER VT\n"); 186203b705cfSriastradh 186303b705cfSriastradh if (!I810BindGARTMemory(scrn)) { 186403b705cfSriastradh return FALSE; 186503b705cfSriastradh } 186603b705cfSriastradh#ifdef HAVE_DRI1 186703b705cfSriastradh if (!I810DRIEnter(scrn)) { 186803b705cfSriastradh return FALSE; 186903b705cfSriastradh } 187003b705cfSriastradh if (pI810->directRenderingEnabled) { 187103b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_DRI) 187203b705cfSriastradh ErrorF("calling dri unlock\n"); 187303b705cfSriastradh DRIUnlock(xf86ScrnToScreen(scrn)); 187403b705cfSriastradh pI810->LockHeld = 0; 187503b705cfSriastradh } 187603b705cfSriastradh#endif 187703b705cfSriastradh 187803b705cfSriastradh if (!I810ModeInit(scrn, scrn->currentMode)) 187903b705cfSriastradh return FALSE; 188003b705cfSriastradh I810AdjustFrame(ADJUST_FRAME_ARGS(scrn, scrn->frameX0, scrn->frameY0)); 188103b705cfSriastradh return TRUE; 188203b705cfSriastradh} 188303b705cfSriastradh 188403b705cfSriastradhstatic void 188503b705cfSriastradhI810LeaveVT(VT_FUNC_ARGS_DECL) 188603b705cfSriastradh{ 188703b705cfSriastradh SCRN_INFO_PTR(arg); 188803b705cfSriastradh vgaHWPtr hwp = VGAHWPTR(scrn); 188903b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 189003b705cfSriastradh 189103b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_DRI) 189203b705cfSriastradh ErrorF("\n\n\nLeave VT\n"); 189303b705cfSriastradh 189403b705cfSriastradh#ifdef HAVE_DRI1 189503b705cfSriastradh if (pI810->directRenderingEnabled) { 189603b705cfSriastradh if (I810_DEBUG & DEBUG_VERBOSE_DRI) 189703b705cfSriastradh ErrorF("calling dri lock\n"); 189803b705cfSriastradh DRILock(xf86ScrnToScreen(scrn), 0); 189903b705cfSriastradh pI810->LockHeld = 1; 190003b705cfSriastradh } 190103b705cfSriastradh#endif 190203b705cfSriastradh 190303b705cfSriastradh#ifdef HAVE_XAA_H 190403b705cfSriastradh if (pI810->AccelInfoRec != NULL) { 190503b705cfSriastradh I810RefreshRing(scrn); 190603b705cfSriastradh I810Sync(scrn); 190703b705cfSriastradh pI810->AccelInfoRec->NeedToSync = FALSE; 190803b705cfSriastradh } 190903b705cfSriastradh#endif 191003b705cfSriastradh I810Restore(scrn); 191103b705cfSriastradh 191203b705cfSriastradh if (!I810UnbindGARTMemory(scrn)) 191303b705cfSriastradh return; 191403b705cfSriastradh#ifdef HAVE_DRI1 191503b705cfSriastradh if (!I810DRILeave(scrn)) 191603b705cfSriastradh return; 191703b705cfSriastradh#endif 191803b705cfSriastradh 191903b705cfSriastradh vgaHWLock(hwp); 192003b705cfSriastradh} 192103b705cfSriastradh 192203b705cfSriastradhstatic Bool 192303b705cfSriastradhI810CloseScreen(CLOSE_SCREEN_ARGS_DECL) 192403b705cfSriastradh{ 192503b705cfSriastradh ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 192603b705cfSriastradh vgaHWPtr hwp = VGAHWPTR(scrn); 192703b705cfSriastradh I810Ptr pI810 = I810PTR(scrn); 192803b705cfSriastradh#ifdef HAVE_XAA_H 192903b705cfSriastradh XAAInfoRecPtr infoPtr = pI810->AccelInfoRec; 193003b705cfSriastradh#endif 193103b705cfSriastradh 193203b705cfSriastradh if (scrn->vtSema == TRUE) { 193303b705cfSriastradh#ifdef HAVE_XAA_H 193403b705cfSriastradh if (pI810->AccelInfoRec != NULL) { 193503b705cfSriastradh I810RefreshRing(scrn); 193603b705cfSriastradh I810Sync(scrn); 193703b705cfSriastradh pI810->AccelInfoRec->NeedToSync = FALSE; 193803b705cfSriastradh } 193903b705cfSriastradh#endif 194003b705cfSriastradh I810Restore(scrn); 194103b705cfSriastradh vgaHWLock(hwp); 194203b705cfSriastradh } 194303b705cfSriastradh#ifdef HAVE_DRI1 194403b705cfSriastradh if (pI810->directRenderingEnabled) { 194503b705cfSriastradh I810DRICloseScreen(screen); 194603b705cfSriastradh pI810->directRenderingEnabled = FALSE; 194703b705cfSriastradh } 194803b705cfSriastradh#endif 194903b705cfSriastradh 195003b705cfSriastradh if (scrn->vtSema == TRUE) { 195103b705cfSriastradh I810UnbindGARTMemory(scrn); 195203b705cfSriastradh I810Restore(scrn); 195303b705cfSriastradh vgaHWLock(hwp); 195403b705cfSriastradh } 195503b705cfSriastradh 195603b705cfSriastradh I810UnmapMem(scrn); 195703b705cfSriastradh vgaHWUnmapMem(scrn); 195803b705cfSriastradh 195903b705cfSriastradh if (pI810->ScanlineColorExpandBuffers) { 196003b705cfSriastradh free(pI810->ScanlineColorExpandBuffers); 196103b705cfSriastradh pI810->ScanlineColorExpandBuffers = NULL; 196203b705cfSriastradh } 196303b705cfSriastradh 196403b705cfSriastradh#ifdef HAVE_XAA_H 196503b705cfSriastradh if (infoPtr) { 196603b705cfSriastradh if (infoPtr->ScanlineColorExpandBuffers) 196703b705cfSriastradh free(infoPtr->ScanlineColorExpandBuffers); 196803b705cfSriastradh XAADestroyInfoRec(infoPtr); 196903b705cfSriastradh pI810->AccelInfoRec = NULL; 197003b705cfSriastradh } 197103b705cfSriastradh#endif 197203b705cfSriastradh 197303b705cfSriastradh if (pI810->CursorInfoRec) { 197403b705cfSriastradh xf86DestroyCursorInfoRec(pI810->CursorInfoRec); 197503b705cfSriastradh pI810->CursorInfoRec = NULL; 197603b705cfSriastradh } 197703b705cfSriastradh 197803b705cfSriastradh /* Free all allocated video ram. 197903b705cfSriastradh */ 198003b705cfSriastradh pI810->SysMem = pI810->SavedSysMem; 198103b705cfSriastradh pI810->DcacheMem = pI810->SavedDcacheMem; 198203b705cfSriastradh pI810->DoneFrontAlloc = FALSE; 198303b705cfSriastradh 198403b705cfSriastradh /* Need to actually close the gart fd, or the unbound memory will just sit 198503b705cfSriastradh * around. Will prevent the Xserver from recycling. 198603b705cfSriastradh */ 198703b705cfSriastradh xf86GARTCloseScreen(scrn->scrnIndex); 198803b705cfSriastradh 198903b705cfSriastradh free(pI810->LpRing); 199003b705cfSriastradh pI810->LpRing = NULL; 199103b705cfSriastradh 199203b705cfSriastradh scrn->vtSema = FALSE; 199303b705cfSriastradh screen->CloseScreen = pI810->CloseScreen; 199403b705cfSriastradh return (*screen->CloseScreen) (CLOSE_SCREEN_ARGS); 199503b705cfSriastradh} 199603b705cfSriastradh 199703b705cfSriastradhstatic void 199803b705cfSriastradhI810FreeScreen(FREE_SCREEN_ARGS_DECL) 199903b705cfSriastradh{ 200003b705cfSriastradh SCRN_INFO_PTR(arg); 200103b705cfSriastradh I810FreeRec(scrn); 200203b705cfSriastradh if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 200303b705cfSriastradh vgaHWFreeHWRec(scrn); 200403b705cfSriastradh} 200503b705cfSriastradh 200603b705cfSriastradhstatic ModeStatus 200703b705cfSriastradhI810ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 200803b705cfSriastradh{ 200903b705cfSriastradh SCRN_INFO_PTR(arg); 201003b705cfSriastradh if (mode->Flags & V_INTERLACE) { 201103b705cfSriastradh if (verbose) { 201203b705cfSriastradh xf86DrvMsg(scrn->scrnIndex, X_PROBED, 201303b705cfSriastradh "Removing interlaced mode \"%s\"\n", mode->name); 201403b705cfSriastradh } 201503b705cfSriastradh return MODE_BAD; 201603b705cfSriastradh } 201703b705cfSriastradh return MODE_OK; 201803b705cfSriastradh} 201903b705cfSriastradh 202003b705cfSriastradhstatic Bool 202103b705cfSriastradhI810SaveScreen(ScreenPtr screen, Bool unblack) 202203b705cfSriastradh{ 202303b705cfSriastradh return vgaHWSaveScreen(screen, unblack); 202403b705cfSriastradh} 202503b705cfSriastradh 202603b705cfSriastradhstatic void 202703b705cfSriastradhI810DisplayPowerManagementSet(ScrnInfoPtr scrn, int PowerManagementMode, 202803b705cfSriastradh int flags) 202903b705cfSriastradh{ 203003b705cfSriastradh I810Ptr pI810; 203103b705cfSriastradh unsigned char SEQ01 = 0; 203203b705cfSriastradh int DPMSSyncSelect = 0; 203303b705cfSriastradh vgaHWPtr hwp; 203403b705cfSriastradh 203503b705cfSriastradh pI810 = I810PTR(scrn); 203603b705cfSriastradh switch (PowerManagementMode) { 203703b705cfSriastradh case DPMSModeOn: 203803b705cfSriastradh /* Screen: On; HSync: On, VSync: On */ 203903b705cfSriastradh SEQ01 = 0x00; 204003b705cfSriastradh DPMSSyncSelect = HSYNC_ON | VSYNC_ON; 204103b705cfSriastradh break; 204203b705cfSriastradh case DPMSModeStandby: 204303b705cfSriastradh /* Screen: Off; HSync: Off, VSync: On */ 204403b705cfSriastradh SEQ01 = 0x20; 204503b705cfSriastradh DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; 204603b705cfSriastradh break; 204703b705cfSriastradh case DPMSModeSuspend: 204803b705cfSriastradh /* Screen: Off; HSync: On, VSync: Off */ 204903b705cfSriastradh SEQ01 = 0x20; 205003b705cfSriastradh DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; 205103b705cfSriastradh break; 205203b705cfSriastradh case DPMSModeOff: 205303b705cfSriastradh /* Screen: Off; HSync: Off, VSync: Off */ 205403b705cfSriastradh SEQ01 = 0x20; 205503b705cfSriastradh DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; 205603b705cfSriastradh break; 205703b705cfSriastradh } 205803b705cfSriastradh 205903b705cfSriastradh hwp = VGAHWPTR(scrn); 206003b705cfSriastradh 206103b705cfSriastradh /* Turn the screen on/off */ 206203b705cfSriastradh SEQ01 |= hwp->readSeq(hwp, 0x01) & ~0x20; 206303b705cfSriastradh hwp->writeSeq(hwp, 0x01, SEQ01); 206403b705cfSriastradh 206503b705cfSriastradh /* Set the DPMS mode */ 206603b705cfSriastradh OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect); 206703b705cfSriastradh} 206803b705cfSriastradh 206903b705cfSriastradhconst OptionInfoRec * 207003b705cfSriastradhlg_i810_available_options(int chipid, int busid) 207103b705cfSriastradh{ 207203b705cfSriastradh return I810Options; 207303b705cfSriastradh} 207403b705cfSriastradh 207503b705cfSriastradh 207603b705cfSriastradhBool lg_i810_init(ScrnInfoPtr scrn) 207703b705cfSriastradh{ 207803b705cfSriastradh scrn->PreInit = I810PreInit; 207903b705cfSriastradh scrn->ScreenInit = I810ScreenInit; 208003b705cfSriastradh scrn->SwitchMode = I810SwitchMode; 208103b705cfSriastradh scrn->AdjustFrame = I810AdjustFrame; 208203b705cfSriastradh scrn->EnterVT = I810EnterVT; 208303b705cfSriastradh scrn->LeaveVT = I810LeaveVT; 208403b705cfSriastradh scrn->FreeScreen = I810FreeScreen; 208503b705cfSriastradh scrn->ValidMode = I810ValidMode; 208603b705cfSriastradh return TRUE; 208703b705cfSriastradh} 2088