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