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