i740_driver.c revision 8280d184
1301ea0f4Smrg
2301ea0f4Smrg/**************************************************************************
3301ea0f4Smrg
4301ea0f4SmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5301ea0f4SmrgAll Rights Reserved.
6301ea0f4Smrg
7301ea0f4SmrgPermission is hereby granted, free of charge, to any person obtaining a
8301ea0f4Smrgcopy of this software and associated documentation files (the
9301ea0f4Smrg"Software"), to deal in the Software without restriction, including
10301ea0f4Smrgwithout limitation the rights to use, copy, modify, merge, publish,
11301ea0f4Smrgdistribute, sub license, and/or sell copies of the Software, and to
12301ea0f4Smrgpermit persons to whom the Software is furnished to do so, subject to
13301ea0f4Smrgthe following conditions:
14301ea0f4Smrg
15301ea0f4SmrgThe above copyright notice and this permission notice (including the
16301ea0f4Smrgnext paragraph) shall be included in all copies or substantial portions
17301ea0f4Smrgof the Software.
18301ea0f4Smrg
19301ea0f4SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20301ea0f4SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21301ea0f4SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22301ea0f4SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23301ea0f4SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24301ea0f4SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25301ea0f4SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26301ea0f4Smrg
27301ea0f4Smrg**************************************************************************/
28301ea0f4Smrg
29301ea0f4Smrg/*
30301ea0f4Smrg * Authors:
31301ea0f4Smrg *   Daryll Strauss <daryll@precisioninsight.com>
32301ea0f4Smrg *
33301ea0f4Smrg */
34301ea0f4Smrg
35301ea0f4Smrg#ifdef HAVE_CONFIG_H
36301ea0f4Smrg#include "config.h"
37301ea0f4Smrg#endif
38301ea0f4Smrg
39301ea0f4Smrg#include <string.h>
40301ea0f4Smrg#include <math.h>
415c69f917Smrg#include <unistd.h>
42301ea0f4Smrg
43301ea0f4Smrg/*
44301ea0f4Smrg * This server does not support these XFree86 4.0 features yet
45301ea0f4Smrg * DDC1 & DDC2 (requires I2C)
46301ea0f4Smrg * shadowFb (if requested or acceleration is off)
47301ea0f4Smrg * Overlay planes
48301ea0f4Smrg * DGA
49301ea0f4Smrg */
50301ea0f4Smrg
51301ea0f4Smrg/*
52301ea0f4Smrg * These are X and server generic header files.
53301ea0f4Smrg */
54301ea0f4Smrg#include "xf86.h"
55301ea0f4Smrg#include "xf86_OSproc.h"
56ef6fb4a5Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
57301ea0f4Smrg#include "xf86Resources.h"
58301ea0f4Smrg#include "xf86RAC.h"
59ef6fb4a5Smrg#endif
60301ea0f4Smrg#include "xf86cmap.h"
61301ea0f4Smrg
62301ea0f4Smrg/* If the driver uses port I/O directly, it needs: */
63301ea0f4Smrg
64301ea0f4Smrg#include "compiler.h"
65301ea0f4Smrg
66301ea0f4Smrg/* All drivers using the vgahw module need this */
67301ea0f4Smrg/* This driver needs to be modified to not use vgaHW for multihead operation */
68301ea0f4Smrg#include "vgaHW.h"
69301ea0f4Smrg
70301ea0f4Smrg/* Drivers using the mi SW cursor need: */
71301ea0f4Smrg
72301ea0f4Smrg#include "mipointer.h"
73301ea0f4Smrg
74301ea0f4Smrg/* Drivers using the mi colourmap code need: */
75301ea0f4Smrg
76301ea0f4Smrg#include "micmap.h"
77301ea0f4Smrg
78301ea0f4Smrg#include "fb.h"
79301ea0f4Smrg
80301ea0f4Smrg/* The driver's own header file: */
81301ea0f4Smrg
82301ea0f4Smrg
83301ea0f4Smrg#include "regionstr.h"
84301ea0f4Smrg
85301ea0f4Smrg#include "xf86xv.h"
86301ea0f4Smrg#include <X11/extensions/Xv.h>
87301ea0f4Smrg
88301ea0f4Smrg#include "vbe.h"
89301ea0f4Smrg#include "i740_dga.h"
90301ea0f4Smrg#include "i740.h"
91301ea0f4Smrg
92301ea0f4Smrg
93301ea0f4Smrg/* Required Functions: */
94301ea0f4Smrgstatic const OptionInfoRec * I740AvailableOptions(int chipid, int busid);
95301ea0f4Smrg
96301ea0f4Smrg/* Print a driver identifying message. */
97301ea0f4Smrgstatic void I740Identify(int flags);
98301ea0f4Smrg
99301ea0f4Smrg/* Identify if there is any hardware present that I know how to drive. */
100301ea0f4Smrgstatic Bool I740Probe(DriverPtr drv, int flags);
101301ea0f4Smrg
102301ea0f4Smrg/* Process the config file and see if we have a valid configuration */
103301ea0f4Smrgstatic Bool I740PreInit(ScrnInfoPtr pScrn, int flags);
104301ea0f4Smrg
105301ea0f4Smrg/* Initialize a screen */
1065c69f917Smrgstatic Bool I740ScreenInit(SCREEN_INIT_ARGS_DECL);
107301ea0f4Smrg
108301ea0f4Smrg/* Enter from a virtual terminal */
1095c69f917Smrgstatic Bool I740EnterVT(VT_FUNC_ARGS_DECL);
110301ea0f4Smrg
111301ea0f4Smrg/* Leave to a virtual terminal */
1125c69f917Smrgstatic void I740LeaveVT(VT_FUNC_ARGS_DECL);
113301ea0f4Smrg
114301ea0f4Smrg/* Close down each screen we initialized */
1155c69f917Smrgstatic Bool I740CloseScreen(CLOSE_SCREEN_ARGS_DECL);
116301ea0f4Smrg
117301ea0f4Smrg/* Change screensaver state */
118301ea0f4Smrgstatic Bool I740SaveScreen(ScreenPtr pScreen, int mode);
119301ea0f4Smrg
120301ea0f4Smrg/* Cleanup server private data */
1215c69f917Smrgstatic void I740FreeScreen(FREE_SCREEN_ARGS_DECL);
122301ea0f4Smrg
123301ea0f4Smrg/* Check if a mode is valid on the hardware */
1245c69f917Smrgstatic ModeStatus I740ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
125301ea0f4Smrg				Bool verbose, int flags);
126301ea0f4Smrg
127301ea0f4Smrg/* Switch to various Display Power Management System levels */
128301ea0f4Smrgstatic void I740DisplayPowerManagementSet(ScrnInfoPtr pScrn,
129301ea0f4Smrg					int PowerManagermentMode, int flags);
130301ea0f4Smrg
131301ea0f4Smrgstatic void I740ProbeDDC(ScrnInfoPtr pScrn, int index);
132301ea0f4Smrg
133301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn);
134301ea0f4Smrgstatic Bool I740UnmapMem(ScrnInfoPtr pScrn);
135301ea0f4Smrg
136301ea0f4Smrg#define I740_VERSION 4000
137301ea0f4Smrg#define I740_NAME "I740"
138301ea0f4Smrg#define I740_DRIVER_NAME "i740"
1390cc67336Smrg#define I740_MAJOR_VERSION PACKAGE_VERSION_MAJOR
1400cc67336Smrg#define I740_MINOR_VERSION PACKAGE_VERSION_MINOR
1410cc67336Smrg#define I740_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
142301ea0f4Smrg
143301ea0f4Smrg_X_EXPORT DriverRec I740 = {
144301ea0f4Smrg  I740_VERSION,
145301ea0f4Smrg  I740_DRIVER_NAME,
146301ea0f4Smrg  I740Identify,
147301ea0f4Smrg  I740Probe,
148301ea0f4Smrg  I740AvailableOptions,
149301ea0f4Smrg  NULL,
150301ea0f4Smrg  0
151301ea0f4Smrg};
152301ea0f4Smrg
153301ea0f4Smrg/* Chipsets */
154301ea0f4Smrgstatic SymTabRec I740Chipsets[] = {
155301ea0f4Smrg  { PCI_CHIP_I740_AGP, "i740 (agp)"},
156301ea0f4Smrg  { PCI_CHIP_I740_PCI, "i740 (pci)"},
157301ea0f4Smrg  { -1, NULL }
158301ea0f4Smrg};
159301ea0f4Smrg
160301ea0f4Smrgstatic PciChipsets I740PciChipsets[] = {
161301ea0f4Smrg  { PCI_CHIP_I740_AGP, PCI_CHIP_I740_AGP, RES_SHARED_VGA },
162301ea0f4Smrg  { PCI_CHIP_I740_PCI, PCI_CHIP_I740_PCI, RES_SHARED_VGA },
163301ea0f4Smrg  { -1, -1, RES_UNDEFINED }
164301ea0f4Smrg};
165301ea0f4Smrg
166301ea0f4Smrgtypedef enum {
167301ea0f4Smrg  OPTION_NOACCEL,
168301ea0f4Smrg  OPTION_SW_CURSOR,
169301ea0f4Smrg  OPTION_SDRAM,
170301ea0f4Smrg  OPTION_SGRAM,
171301ea0f4Smrg  OPTION_SLOW_RAM,
172301ea0f4Smrg  OPTION_DAC_6BIT,
173301ea0f4Smrg  OPTION_USE_PIO,
174301ea0f4Smrg  OPTION_VGACOMPAT
175301ea0f4Smrg} I740Opts;
176301ea0f4Smrg
177301ea0f4Smrgstatic const OptionInfoRec I740Options[] = {
178301ea0f4Smrg  { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
179301ea0f4Smrg  { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
180301ea0f4Smrg  { OPTION_SDRAM, "SDRAM", OPTV_BOOLEAN, {0}, FALSE},
181301ea0f4Smrg  { OPTION_SGRAM, "SGRAM", OPTV_BOOLEAN, {0}, FALSE},
182301ea0f4Smrg  { OPTION_SLOW_RAM, "SlowRam", OPTV_BOOLEAN, {0}, FALSE},
183301ea0f4Smrg  { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
184301ea0f4Smrg  { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE},
185301ea0f4Smrg  { OPTION_VGACOMPAT, "VGACompat", OPTV_BOOLEAN, {0}, FALSE},
186301ea0f4Smrg  { -1, NULL, OPTV_NONE, {0}, FALSE}
187301ea0f4Smrg};
188301ea0f4Smrg
189301ea0f4Smrg#ifdef XFree86LOADER
190301ea0f4Smrg
191301ea0f4Smrgstatic MODULESETUPPROTO(i740Setup);
192301ea0f4Smrg
193301ea0f4Smrgstatic XF86ModuleVersionInfo i740VersRec =
194301ea0f4Smrg{
195301ea0f4Smrg  "i740",
196301ea0f4Smrg  MODULEVENDORSTRING,
197301ea0f4Smrg  MODINFOSTRING1,
198301ea0f4Smrg  MODINFOSTRING2,
199301ea0f4Smrg  XORG_VERSION_CURRENT,
200301ea0f4Smrg  I740_MAJOR_VERSION, I740_MINOR_VERSION, I740_PATCHLEVEL,
201301ea0f4Smrg  ABI_CLASS_VIDEODRV,
202301ea0f4Smrg  ABI_VIDEODRV_VERSION,
203301ea0f4Smrg  MOD_CLASS_VIDEODRV,
204301ea0f4Smrg  {0,0,0,0}
205301ea0f4Smrg};
206301ea0f4Smrg
207301ea0f4Smrg_X_EXPORT XF86ModuleData i740ModuleData = {&i740VersRec, i740Setup, 0};
208301ea0f4Smrg
209301ea0f4Smrgstatic pointer
210301ea0f4Smrgi740Setup(pointer module, pointer opts, int *errmaj, int *errmin)
211301ea0f4Smrg{
212301ea0f4Smrg    static Bool setupDone = FALSE;
213301ea0f4Smrg
214301ea0f4Smrg    /* This module should be loaded only once, but check to be sure. */
215301ea0f4Smrg
216301ea0f4Smrg    if (!setupDone) {
217301ea0f4Smrg	setupDone = TRUE;
218301ea0f4Smrg	xf86AddDriver(&I740, module, 0);
219301ea0f4Smrg
220301ea0f4Smrg	/*
221301ea0f4Smrg	 * Modules that this driver always requires may be loaded here
222301ea0f4Smrg	 * by calling LoadSubModule().
223301ea0f4Smrg	 */
224301ea0f4Smrg
225301ea0f4Smrg	/*
226301ea0f4Smrg	 * The return value must be non-NULL on success even though there
227301ea0f4Smrg	 * is no TearDownProc.
228301ea0f4Smrg	 */
229301ea0f4Smrg	return (pointer)1;
230301ea0f4Smrg    } else {
231301ea0f4Smrg	if (errmaj) *errmaj = LDR_ONCEONLY;
232301ea0f4Smrg	return NULL;
233301ea0f4Smrg    }
234301ea0f4Smrg}
235301ea0f4Smrg
236301ea0f4Smrg#endif
237301ea0f4Smrg
238301ea0f4Smrg/*
239301ea0f4Smrg * I740GetRec and I740FreeRec --
240301ea0f4Smrg *
241301ea0f4Smrg * Private data for the driver is stored in the screen structure.
242301ea0f4Smrg * These two functions create and destroy that private data.
243301ea0f4Smrg *
244301ea0f4Smrg */
245301ea0f4Smrgstatic Bool
246301ea0f4SmrgI740GetRec(ScrnInfoPtr pScrn) {
247301ea0f4Smrg  if (pScrn->driverPrivate) return TRUE;
248301ea0f4Smrg
249301ea0f4Smrg  pScrn->driverPrivate = xnfcalloc(sizeof(I740Rec), 1);
250301ea0f4Smrg  return TRUE;
251301ea0f4Smrg}
252301ea0f4Smrg
253301ea0f4Smrgstatic void
254301ea0f4SmrgI740FreeRec(ScrnInfoPtr pScrn) {
255301ea0f4Smrg  if (!pScrn) return;
2565c69f917Smrg  free(pScrn->driverPrivate);
257301ea0f4Smrg  pScrn->driverPrivate=0;
258301ea0f4Smrg}
259301ea0f4Smrg
260301ea0f4Smrgstatic const OptionInfoRec *
261301ea0f4SmrgI740AvailableOptions(int chipid, int busid)
262301ea0f4Smrg{
263301ea0f4Smrg    return I740Options;
264301ea0f4Smrg}
265301ea0f4Smrg
266301ea0f4Smrg/*
267301ea0f4Smrg * I740Identify --
268301ea0f4Smrg *
269301ea0f4Smrg * Returns the string name for the driver based on the chipset. In this
270301ea0f4Smrg * case it will always be an I740, so we can return a static string.
271301ea0f4Smrg *
272301ea0f4Smrg */
273301ea0f4Smrgstatic void
274301ea0f4SmrgI740Identify(int flags) {
275301ea0f4Smrg  xf86PrintChipsets(I740_NAME, "Driver for Intel i740 chipset", I740Chipsets);
276301ea0f4Smrg}
277301ea0f4Smrg
278301ea0f4Smrg/*
279301ea0f4Smrg * I740Probe --
280301ea0f4Smrg *
281301ea0f4Smrg * Look through the PCI bus to find cards that are I740 boards.
282301ea0f4Smrg * Setup the dispatch table for the rest of the driver functions.
283301ea0f4Smrg *
284301ea0f4Smrg */
285301ea0f4Smrgstatic Bool
286301ea0f4SmrgI740Probe(DriverPtr drv, int flags) {
287301ea0f4Smrg  int i, numUsed, numDevSections, *usedChips;
288301ea0f4Smrg  GDevPtr *devSections;
289301ea0f4Smrg  Bool foundScreen = FALSE;
290301ea0f4Smrg
291301ea0f4Smrg  /*
292301ea0f4Smrg   Find the config file Device sections that match this
293301ea0f4Smrg   driver, and return if there are none.
294301ea0f4Smrg   */
295301ea0f4Smrg  if ((numDevSections = xf86MatchDevice(I740_DRIVER_NAME, &devSections))<=0) {
296301ea0f4Smrg    return FALSE;
297301ea0f4Smrg  }
298301ea0f4Smrg
2990cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
300301ea0f4Smrg  /*
301301ea0f4Smrg     Since these Probing is just checking the PCI data the server already
302301ea0f4Smrg     collected.
303301ea0f4Smrg  */
304301ea0f4Smrg  if (!xf86GetPciVideoInfo()) return FALSE;
3050cc67336Smrg#endif
306301ea0f4Smrg
307301ea0f4Smrg  /* Look for Intel based chips */
308301ea0f4Smrg  numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_INTEL,
309301ea0f4Smrg				  I740Chipsets, I740PciChipsets,
310301ea0f4Smrg				  devSections, numDevSections,
311301ea0f4Smrg				  drv, &usedChips);
312301ea0f4Smrg
313301ea0f4Smrg  if (numUsed > 0) {
314301ea0f4Smrg      if (flags & PROBE_DETECT)
315301ea0f4Smrg	  foundScreen = TRUE;
316301ea0f4Smrg      else for (i=0; i<numUsed; i++) {
317301ea0f4Smrg	  ScrnInfoPtr pScrn = NULL;
318301ea0f4Smrg	  /* Allocate new ScrnInfoRec and claim the slot */
319301ea0f4Smrg	  if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
320301ea0f4Smrg						 I740PciChipsets, 0, 0, 0, 0, 0))) {
321301ea0f4Smrg	      pScrn->driverVersion = I740_VERSION;
322301ea0f4Smrg	      pScrn->driverName = I740_DRIVER_NAME;
323301ea0f4Smrg	      pScrn->name = I740_NAME;
324301ea0f4Smrg	      pScrn->Probe = I740Probe;
325301ea0f4Smrg	      pScrn->PreInit = I740PreInit;
326301ea0f4Smrg	      pScrn->ScreenInit = I740ScreenInit;
327301ea0f4Smrg	      pScrn->SwitchMode = I740SwitchMode;
328301ea0f4Smrg	      pScrn->AdjustFrame = I740AdjustFrame;
329301ea0f4Smrg	      pScrn->EnterVT = I740EnterVT;
330301ea0f4Smrg	      pScrn->LeaveVT = I740LeaveVT;
331301ea0f4Smrg	      pScrn->FreeScreen = I740FreeScreen;
332301ea0f4Smrg	      pScrn->ValidMode = I740ValidMode;
333301ea0f4Smrg	      foundScreen = TRUE;
334301ea0f4Smrg
335301ea0f4Smrg	  }
336301ea0f4Smrg      }
337301ea0f4Smrg  }
338301ea0f4Smrg
339301ea0f4Smrg
340301ea0f4Smrg  /* Look for Real3D based chips */
341301ea0f4Smrg  numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_REAL3D,
342301ea0f4Smrg				  I740Chipsets, I740PciChipsets,
343301ea0f4Smrg				  devSections, numDevSections,
344301ea0f4Smrg				  drv, &usedChips);
345301ea0f4Smrg
346301ea0f4Smrg  if (numUsed > 0) {
347301ea0f4Smrg      if (flags & PROBE_DETECT)
348301ea0f4Smrg	  foundScreen = TRUE;
349301ea0f4Smrg      else for (i=0; i<numUsed; i++) {
350301ea0f4Smrg	  ScrnInfoPtr pScrn = NULL;
351301ea0f4Smrg	  if ((pScrn  = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
352301ea0f4Smrg						  I740PciChipsets, 0, 0, 0, 0, 0))) {
353301ea0f4Smrg	      pScrn->driverVersion = I740_VERSION;
354301ea0f4Smrg	      pScrn->driverName = I740_DRIVER_NAME;
355301ea0f4Smrg	      pScrn->name = I740_NAME;
356301ea0f4Smrg	      pScrn->Probe = I740Probe;
357301ea0f4Smrg	      pScrn->PreInit = I740PreInit;
358301ea0f4Smrg	      pScrn->ScreenInit = I740ScreenInit;
359301ea0f4Smrg	      pScrn->SwitchMode = I740SwitchMode;
360301ea0f4Smrg	      pScrn->AdjustFrame = I740AdjustFrame;
361301ea0f4Smrg	      pScrn->EnterVT = I740EnterVT;
362301ea0f4Smrg	      pScrn->LeaveVT = I740LeaveVT;
363301ea0f4Smrg	      pScrn->FreeScreen = I740FreeScreen;
364301ea0f4Smrg	      pScrn->ValidMode = I740ValidMode;
365301ea0f4Smrg	      foundScreen = TRUE;
366301ea0f4Smrg	  }
367301ea0f4Smrg      }
368301ea0f4Smrg  }
369301ea0f4Smrg
3705c69f917Smrg  free(devSections);
3715c69f917Smrg  free(usedChips);
372301ea0f4Smrg
373301ea0f4Smrg  return foundScreen;
374301ea0f4Smrg}
375301ea0f4Smrg
3760cc67336Smrg/* Ugh.  Can we not do this? */
377301ea0f4Smrgstatic void
378301ea0f4SmrgI740ProbeDDC(ScrnInfoPtr pScrn, int index)
379301ea0f4Smrg{
380301ea0f4Smrg    vbeInfoPtr pVbe;
381301ea0f4Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
382301ea0f4Smrg	pVbe = VBEInit(NULL,index);
383301ea0f4Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
384301ea0f4Smrg	vbeFree(pVbe);
385301ea0f4Smrg    }
386301ea0f4Smrg}
387301ea0f4Smrg
388301ea0f4Smrg/*
389301ea0f4Smrg * I740PreInit --
390301ea0f4Smrg *
391301ea0f4Smrg * Do initial setup of the board before we know what resolution we will
392301ea0f4Smrg * be running at.
393301ea0f4Smrg *
394301ea0f4Smrg */
395301ea0f4Smrgstatic Bool
396301ea0f4SmrgI740PreInit(ScrnInfoPtr pScrn, int flags) {
397301ea0f4Smrg  I740Ptr pI740;
398301ea0f4Smrg  ClockRangePtr clockRanges;
399301ea0f4Smrg  int i;
400301ea0f4Smrg  MessageType from;
401301ea0f4Smrg  int temp;
402301ea0f4Smrg  int flags24;
403301ea0f4Smrg  rgb defaultWeight = {0, 0, 0};
404301ea0f4Smrg
405301ea0f4Smrg  if (pScrn->numEntities != 1) return FALSE;
406301ea0f4Smrg
407301ea0f4Smrg  /* Allocate driverPrivate */
408301ea0f4Smrg  if (!I740GetRec(pScrn)) {
409301ea0f4Smrg    return FALSE;
410301ea0f4Smrg  }
411301ea0f4Smrg
412301ea0f4Smrg  pI740 = I740PTR(pScrn);
413301ea0f4Smrg
414301ea0f4Smrg  pI740->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
415301ea0f4Smrg  if (pI740->pEnt->location.type != BUS_PCI) return FALSE;
416301ea0f4Smrg
417301ea0f4Smrg  /*I740ProbeDDC(pScrn, pI740->pEnt->index);*/
418301ea0f4Smrg  if (flags & PROBE_DETECT) {
419301ea0f4Smrg	I740ProbeDDC(pScrn, pI740->pEnt->index);
420301ea0f4Smrg	return TRUE;
421301ea0f4Smrg  }
422301ea0f4Smrg
423301ea0f4Smrg  /* The vgahw module should be loaded here when needed */
424301ea0f4Smrg  if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
425301ea0f4Smrg
426301ea0f4Smrg  /* Allocate a vgaHWRec */
427301ea0f4Smrg  if (!vgaHWGetHWRec(pScrn)) return FALSE;
4285c69f917Smrg  vgaHWSetStdFuncs(VGAHWPTR(pScrn));
429301ea0f4Smrg
430301ea0f4Smrg  pI740->PciInfo = xf86GetPciInfoForEntity(pI740->pEnt->index);
4310cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
432301ea0f4Smrg  pI740->PciTag = pciTag(pI740->PciInfo->bus, pI740->PciInfo->device,
433301ea0f4Smrg			 pI740->PciInfo->func);
434301ea0f4Smrg
435301ea0f4Smrg  if (xf86RegisterResources(pI740->pEnt->index, 0, ResNone))
436301ea0f4Smrg      return FALSE;
437301ea0f4Smrg  if (pI740->usePIO)
438301ea0f4Smrg    pScrn->racIoFlags = RAC_FB | RAC_COLORMAP;
439301ea0f4Smrg  else
440301ea0f4Smrg    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
441ef6fb4a5Smrg#endif
442301ea0f4Smrg  /* Set pScrn->monitor */
443301ea0f4Smrg  pScrn->monitor = pScrn->confScreen->monitor;
444301ea0f4Smrg
445301ea0f4Smrg
446301ea0f4Smrg  flags24=Support24bppFb | Support32bppFb | SupportConvert32to24;
447301ea0f4Smrg  if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
448301ea0f4Smrg    return FALSE;
449301ea0f4Smrg  } else {
450301ea0f4Smrg    switch (pScrn->depth) {
451301ea0f4Smrg    case 8:
452301ea0f4Smrg    case 15:
453301ea0f4Smrg    case 16:
454301ea0f4Smrg    case 24:
455301ea0f4Smrg      break;
456301ea0f4Smrg    default:
457301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
458301ea0f4Smrg		 "Given depth (%d) is not supported by i740 driver\n",
459301ea0f4Smrg		 pScrn->depth);
460301ea0f4Smrg      return FALSE;
461301ea0f4Smrg    }
462301ea0f4Smrg  }
463301ea0f4Smrg  /*xf86PrintDepthBpp(pScrn);*/
464301ea0f4Smrg
465301ea0f4Smrg  if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
466301ea0f4Smrg    return FALSE;
467301ea0f4Smrg
468301ea0f4Smrg  if (!xf86SetDefaultVisual(pScrn, -1)) {
469301ea0f4Smrg    return FALSE;
470301ea0f4Smrg  } else {
471301ea0f4Smrg    /* We don't currently support DirectColor at > 8bpp */
472301ea0f4Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
473301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
474301ea0f4Smrg		 " (%s) is not supported at depth %d\n",
475301ea0f4Smrg		 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
476301ea0f4Smrg      return FALSE;
477301ea0f4Smrg    }
478301ea0f4Smrg  }
479301ea0f4Smrg
480301ea0f4Smrg  /* We use a programamble clock */
481301ea0f4Smrg  pScrn->progClock = TRUE;
482301ea0f4Smrg
483301ea0f4Smrg  pI740->cpp = pScrn->bitsPerPixel/8;
484301ea0f4Smrg
485301ea0f4Smrg  /* Process the options */
486301ea0f4Smrg  xf86CollectOptions(pScrn, NULL);
4875c69f917Smrg  if (!(pI740->Options = malloc(sizeof(I740Options))))
488301ea0f4Smrg    return FALSE;
489301ea0f4Smrg  memcpy(pI740->Options, I740Options, sizeof(I740Options));
490301ea0f4Smrg  xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI740->Options);
491301ea0f4Smrg
492301ea0f4Smrg  /* 6-BIT dac isn't reasonable for modes with > 8bpp */
493301ea0f4Smrg  if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE) &&
494301ea0f4Smrg      pScrn->bitsPerPixel>8) {
495301ea0f4Smrg    OptionInfoPtr ptr;
496301ea0f4Smrg    ptr=xf86TokenToOptinfo(pI740->Options, OPTION_DAC_6BIT);
497301ea0f4Smrg    ptr->found=FALSE;
498301ea0f4Smrg  }
499301ea0f4Smrg
500301ea0f4Smrg  if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE))
501301ea0f4Smrg    pScrn->rgbBits=8;
502301ea0f4Smrg  else
503301ea0f4Smrg    pScrn->rgbBits=6;
504301ea0f4Smrg
505301ea0f4Smrg  /* We have to use PIO to probe, because we haven't mappend yet */
506301ea0f4Smrg  I740SetPIOAccess(pI740);
507301ea0f4Smrg
508301ea0f4Smrg  /*
509301ea0f4Smrg   * Set the Chipset and ChipRev, allowing config file entries to
510301ea0f4Smrg   * override.
511301ea0f4Smrg   */
512301ea0f4Smrg  if (pI740->pEnt->device->chipset && *pI740->pEnt->device->chipset) {
513301ea0f4Smrg    pScrn->chipset = pI740->pEnt->device->chipset;
514301ea0f4Smrg    from = X_CONFIG;
515301ea0f4Smrg  } else if (pI740->pEnt->device->chipID >= 0) {
516301ea0f4Smrg    pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->pEnt->device->chipID);
517301ea0f4Smrg    from = X_CONFIG;
518301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
519301ea0f4Smrg	       pI740->pEnt->device->chipID);
520301ea0f4Smrg  } else {
521301ea0f4Smrg    from = X_PROBED;
5220cc67336Smrg    pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, PCI_DEV_DEVICE_ID(pI740->PciInfo));
523301ea0f4Smrg  }
524301ea0f4Smrg  if (pI740->pEnt->device->chipRev >= 0) {
525301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
526301ea0f4Smrg	       pI740->pEnt->device->chipRev);
527301ea0f4Smrg  }
528301ea0f4Smrg
529301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset!=NULL)?pScrn->chipset:"Unknown i740");
530301ea0f4Smrg
531301ea0f4Smrg  if (pI740->pEnt->device->MemBase != 0) {
532301ea0f4Smrg    pI740->LinearAddr = pI740->pEnt->device->MemBase;
533301ea0f4Smrg    from = X_CONFIG;
534301ea0f4Smrg  } else {
5350cc67336Smrg    if (PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM) != 0) {
5360cc67336Smrg      pI740->LinearAddr = PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM)&0xFF000000;
537301ea0f4Smrg      from = X_PROBED;
538301ea0f4Smrg    } else {
539301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
540301ea0f4Smrg		 "No valid FB address in PCI config space\n");
541301ea0f4Smrg      I740FreeRec(pScrn);
542301ea0f4Smrg      return FALSE;
543301ea0f4Smrg    }
544301ea0f4Smrg  }
545301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
546301ea0f4Smrg	     pI740->LinearAddr);
547301ea0f4Smrg
548301ea0f4Smrg  if (pI740->pEnt->device->IOBase != 0) {
549301ea0f4Smrg    pI740->MMIOAddr = pI740->pEnt->device->IOBase;
550301ea0f4Smrg    from = X_CONFIG;
551301ea0f4Smrg  } else {
5520cc67336Smrg    if (PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)) {
5530cc67336Smrg      pI740->MMIOAddr = PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)&0xFFF80000;
554301ea0f4Smrg      from = X_PROBED;
555301ea0f4Smrg    } else {
556301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
557301ea0f4Smrg		 "No valid MMIO address in PCI config space\n");
558301ea0f4Smrg      I740FreeRec(pScrn);
559301ea0f4Smrg      return FALSE;
560301ea0f4Smrg    }
561301ea0f4Smrg  }
562301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
563301ea0f4Smrg	     pI740->MMIOAddr);
564301ea0f4Smrg
565301ea0f4Smrg  /* Calculate memory */
566301ea0f4Smrg  if (pI740->pEnt->device->videoRam) {
567301ea0f4Smrg    pScrn->videoRam = pI740->pEnt->device->videoRam;
568301ea0f4Smrg    from = X_CONFIG;
569301ea0f4Smrg  } else {
570301ea0f4Smrg    if ((pI740->readControl(pI740, XRX, DRAM_ROW_TYPE)&DRAM_ROW_1)==DRAM_ROW_1_SDRAM)
571301ea0f4Smrg      pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_1);
572301ea0f4Smrg    else
573301ea0f4Smrg      pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_0);
574301ea0f4Smrg    pScrn->videoRam = (pScrn->videoRam&0x0F)*1024;
575301ea0f4Smrg    from = X_PROBED;
576301ea0f4Smrg  }
577301ea0f4Smrg
578301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, DRAM_ROW_CNTL_LO);
579301ea0f4Smrg  pI740->HasSGRAM = !((temp&DRAM_RAS_TIMING)||(temp&DRAM_RAS_PRECHARGE));
580301ea0f4Smrg  if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) {
581301ea0f4Smrg    if (xf86IsOptionSet(pI740->Options, OPTION_SGRAM)) {
582301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
583301ea0f4Smrg		 "It is nonsensical to set both SDRAM and SGRAM options\n");
584301ea0f4Smrg      return FALSE;
585301ea0f4Smrg    }
586301ea0f4Smrg    if (xf86ReturnOptValBool(pI740->Options, OPTION_SDRAM, FALSE)) {
587301ea0f4Smrg      pI740->HasSGRAM = FALSE;
588301ea0f4Smrg    } else {
589301ea0f4Smrg      pI740->HasSGRAM = TRUE;
590301ea0f4Smrg    }
591301ea0f4Smrg  } else {
592301ea0f4Smrg    if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) {
593301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
594301ea0f4Smrg		 "It is nonsensical to set both SDRAM and SGRAM options\n");
595301ea0f4Smrg      return FALSE;
596301ea0f4Smrg    }
597301ea0f4Smrg    if (xf86ReturnOptValBool(pI740->Options, OPTION_SGRAM, FALSE)) {
598301ea0f4Smrg      pI740->HasSGRAM = TRUE;
599301ea0f4Smrg    } else {
600301ea0f4Smrg      pI740->HasSGRAM = FALSE;
601301ea0f4Smrg    }
602301ea0f4Smrg  }
603301ea0f4Smrg
604301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "Steve was here! VideoRAM: %d kByte %s\n",
605301ea0f4Smrg	     pScrn->videoRam, (pI740->HasSGRAM)?"SGRAM":"SDRAM");
606301ea0f4Smrg  pI740->FbMapSize = pScrn->videoRam*1024;
607301ea0f4Smrg
608301ea0f4Smrg  /*
609301ea0f4Smrg   * If the driver can do gamma correction, it should call xf86SetGamma()
610301ea0f4Smrg   * here.
611301ea0f4Smrg   */
612301ea0f4Smrg
613301ea0f4Smrg  {
614301ea0f4Smrg    Gamma zeros = {0.0, 0.0, 0.0};
615301ea0f4Smrg
616301ea0f4Smrg    if (!xf86SetGamma(pScrn, zeros)) {
617301ea0f4Smrg      return FALSE;
618301ea0f4Smrg    }
619301ea0f4Smrg  }
620301ea0f4Smrg
621301ea0f4Smrg  pI740->MaxClock = 0;
622301ea0f4Smrg  if (pI740->pEnt->device->dacSpeeds[0]) {
623301ea0f4Smrg    switch (pScrn->bitsPerPixel) {
624301ea0f4Smrg    case 8:
625301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP8];
626301ea0f4Smrg      break;
627301ea0f4Smrg    case 16:
628301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP16];
629301ea0f4Smrg      break;
630301ea0f4Smrg    case 24:
631301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP24];
632301ea0f4Smrg      break;
633301ea0f4Smrg    case 32:
634301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP32];
635301ea0f4Smrg      break;
636301ea0f4Smrg    }
637301ea0f4Smrg    if (!pI740->MaxClock)
638301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[0];
639301ea0f4Smrg    from = X_CONFIG;
640301ea0f4Smrg  } else {
641301ea0f4Smrg    switch (pScrn->bitsPerPixel) {
642301ea0f4Smrg    case 8:
643301ea0f4Smrg      pI740->MaxClock = 203000;
644301ea0f4Smrg      break;
645301ea0f4Smrg    case 16:
646301ea0f4Smrg      pI740->MaxClock = 163000;
647301ea0f4Smrg      break;
648301ea0f4Smrg    case 24:
649301ea0f4Smrg      if (pI740->HasSGRAM)
650301ea0f4Smrg	pI740->MaxClock = 136000;
651301ea0f4Smrg      else
652301ea0f4Smrg	pI740->MaxClock = 128000;
653301ea0f4Smrg      break;
654301ea0f4Smrg    case 32:
655301ea0f4Smrg      pI740->MaxClock = 86000;
656301ea0f4Smrg    }
657301ea0f4Smrg  }
658301ea0f4Smrg  clockRanges = xnfcalloc(sizeof(ClockRange), 1);
659301ea0f4Smrg  clockRanges->next=NULL;
660301ea0f4Smrg  clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */
661301ea0f4Smrg  clockRanges->maxClock=pI740->MaxClock;
662301ea0f4Smrg  clockRanges->clockIndex = -1;
663301ea0f4Smrg  clockRanges->interlaceAllowed = FALSE; /*PL*/
664301ea0f4Smrg  clockRanges->doubleScanAllowed = TRUE; /*PL*/
665301ea0f4Smrg
6660cc67336Smrg  { /*PL*/
6670cc67336Smrg
6680cc67336Smrg   if (xf86LoadSubModule(pScrn, "ddc")) {
6690cc67336Smrg     if (xf86LoadSubModule(pScrn, "i2c") ) {
6700cc67336Smrg       if (I740MapMem(pScrn)) {
6710cc67336Smrg	   if (I740_I2CInit(pScrn))
6720cc67336Smrg	     {
6730cc67336Smrg	       xf86MonPtr MonInfo;
6745c69f917Smrg	       if ((MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),pI740->rc_i2c))) {
6750cc67336Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n",
6760cc67336Smrg			    MonInfo);
6770cc67336Smrg		 xf86PrintEDID( MonInfo );
6780cc67336Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor "
6790cc67336Smrg			    "info\n\n");
6800cc67336Smrg		 xf86SetDDCproperties(pScrn,MonInfo);
6810cc67336Smrg	       }
6820cc67336Smrg	     }
6830cc67336Smrg	   else
6840cc67336Smrg	     xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n");
6850cc67336Smrg
6860cc67336Smrg	   I740UnmapMem(pScrn);
6870cc67336Smrg	 }
6880cc67336Smrg     }
6890cc67336Smrg   }
6900cc67336Smrg  }
6910cc67336Smrg
692301ea0f4Smrg  i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
693301ea0f4Smrg			pScrn->display->modes, clockRanges,
694301ea0f4Smrg			0, 320, 1600,
695301ea0f4Smrg			8, 200, 1200,
696301ea0f4Smrg			pScrn->display->virtualX, pScrn->display->virtualY,
697301ea0f4Smrg			pI740->FbMapSize, LOOKUP_BEST_REFRESH);
698301ea0f4Smrg
699301ea0f4Smrg  if (i==-1) {
700301ea0f4Smrg    I740FreeRec(pScrn);
701301ea0f4Smrg    return FALSE;
702301ea0f4Smrg  }
703301ea0f4Smrg
704301ea0f4Smrg  xf86PruneDriverModes(pScrn);
705301ea0f4Smrg
706301ea0f4Smrg  if (!i || !pScrn->modes) {
707301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
708301ea0f4Smrg    I740FreeRec(pScrn);
709301ea0f4Smrg    return FALSE;
710301ea0f4Smrg  }
711301ea0f4Smrg
712301ea0f4Smrg  xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
713301ea0f4Smrg
714301ea0f4Smrg  pScrn->currentMode = pScrn->modes;
715301ea0f4Smrg
716301ea0f4Smrg  xf86PrintModes(pScrn);
717301ea0f4Smrg
718301ea0f4Smrg  xf86SetDpi(pScrn, 0, 0);
719301ea0f4Smrg
720301ea0f4Smrg  if (!xf86LoadSubModule(pScrn, "fb")) {
721301ea0f4Smrg    I740FreeRec(pScrn);
722301ea0f4Smrg    return FALSE;
723301ea0f4Smrg  }
724301ea0f4Smrg
7255c69f917Smrg  pI740->NoAccel = xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE);
7265c69f917Smrg  if (!pI740->NoAccel) {
727301ea0f4Smrg    if (!xf86LoadSubModule(pScrn, "xaa")) {
7285c69f917Smrg      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration available\n");
7295c69f917Smrg      pI740->NoAccel = 1;
730301ea0f4Smrg    }
731301ea0f4Smrg  }
732301ea0f4Smrg
733301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) {
734301ea0f4Smrg    if (!xf86LoadSubModule(pScrn, "ramdac")) {
735301ea0f4Smrg      I740FreeRec(pScrn);
736301ea0f4Smrg      return FALSE;
737301ea0f4Smrg    }
738301ea0f4Smrg  }
739301ea0f4Smrg
740301ea0f4Smrg  /*  We wont be using the VGA access after the probe */
741301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_USE_PIO, FALSE)) {
742ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS
743301ea0f4Smrg    resRange vgaio[] = { {ResShrIoBlock,0x3B0,0x3BB},
744301ea0f4Smrg			 {ResShrIoBlock,0x3C0,0x3DF},
745301ea0f4Smrg			 _END };
746301ea0f4Smrg    resRange vgamem[] = {{ResShrMemBlock,0xA0000,0xAFFFF},
747301ea0f4Smrg			 {ResShrMemBlock,0xB8000,0xBFFFF},
748301ea0f4Smrg			 {ResShrMemBlock,0xB0000,0xB7FFF},
749301ea0f4Smrg			 _END };
750ef6fb4a5Smrg#endif
751301ea0f4Smrg    pI740->usePIO=FALSE;
752301ea0f4Smrg    I740SetMMIOAccess(pI740);
753ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS
754301ea0f4Smrg    xf86SetOperatingState(vgaio, pI740->pEnt->index, ResUnusedOpr);
755301ea0f4Smrg    xf86SetOperatingState(vgamem, pI740->pEnt->index, ResDisableOpr);
756ef6fb4a5Smrg#endif
757301ea0f4Smrg  } else {
758301ea0f4Smrg    pI740->usePIO=TRUE;
759301ea0f4Smrg  }
760301ea0f4Smrg
761301ea0f4Smrg  if(xf86IsOptionSet(pI740->Options, OPTION_VGACOMPAT))
762301ea0f4Smrg    pI740->usevgacompat=TRUE;
763301ea0f4Smrg  else
764301ea0f4Smrg    pI740->usevgacompat=FALSE;
765301ea0f4Smrg
766301ea0f4Smrg
767301ea0f4Smrg
768301ea0f4Smrg  { /* Overlay */
769301ea0f4Smrg    pI740->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) |
770301ea0f4Smrg      (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
771301ea0f4Smrg
772301ea0f4Smrg    pI740->colorKey &= ((1 << pScrn->depth) - 1);
773301ea0f4Smrg
774301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video overlay key set to 0x%x\n", pI740->colorKey);
775301ea0f4Smrg  }
776301ea0f4Smrg
777301ea0f4Smrg
778301ea0f4Smrg  return TRUE;
779301ea0f4Smrg}
780301ea0f4Smrg
781301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn)
782301ea0f4Smrg{
7838280d184Smrg#ifndef XSERVER_LIBPCIACCESS
784301ea0f4Smrg  int mmioFlags;
7858280d184Smrg#endif
786301ea0f4Smrg  I740Ptr pI740;
787301ea0f4Smrg
788301ea0f4Smrg  pI740 = I740PTR(pScrn);
789301ea0f4Smrg
7900cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
791301ea0f4Smrg  mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
792301ea0f4Smrg
793301ea0f4Smrg  pI740->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags,
794301ea0f4Smrg				      pI740->PciTag,
795301ea0f4Smrg				      pI740->MMIOAddr,
796301ea0f4Smrg				      0x80000);
7970cc67336Smrg#else
7980cc67336Smrg  {
7990cc67336Smrg    void** result = (void**)&pI740->MMIOBase;
8000cc67336Smrg    int err = pci_device_map_range(pI740->PciInfo,
8010cc67336Smrg				   pI740->MMIOAddr,
8020cc67336Smrg				   0x80000,
8030cc67336Smrg				   PCI_DEV_MAP_FLAG_WRITABLE,
8040cc67336Smrg				   result);
8050cc67336Smrg
8060cc67336Smrg    if (err)
8070cc67336Smrg      return FALSE;
8080cc67336Smrg  }
8090cc67336Smrg
8100cc67336Smrg#endif
811301ea0f4Smrg  if (!pI740->MMIOBase) return FALSE;
812301ea0f4Smrg
8130cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
814301ea0f4Smrg  pI740->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
815301ea0f4Smrg				pI740->PciTag,
816301ea0f4Smrg				pI740->LinearAddr,
817301ea0f4Smrg				pI740->FbMapSize);
8180cc67336Smrg#else
8190cc67336Smrg  {
8200cc67336Smrg    void** result = (void**)&pI740->FbBase;
8210cc67336Smrg    int err = pci_device_map_range(pI740->PciInfo,
8220cc67336Smrg				   pI740->LinearAddr,
8230cc67336Smrg				   pI740->FbMapSize,
8240cc67336Smrg				   PCI_DEV_MAP_FLAG_WRITABLE |
8250cc67336Smrg				   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
8260cc67336Smrg				   result);
8270cc67336Smrg
8280cc67336Smrg    if (err)
8290cc67336Smrg      return FALSE;
8300cc67336Smrg  }
8310cc67336Smrg#endif
832301ea0f4Smrg  if (!pI740->FbBase) return FALSE;
833301ea0f4Smrg
834301ea0f4Smrg  return TRUE;
835301ea0f4Smrg}
836301ea0f4Smrg
837301ea0f4Smrgstatic Bool I740UnmapMem(ScrnInfoPtr pScrn)
838301ea0f4Smrg{
839301ea0f4Smrg  I740Ptr pI740;
840301ea0f4Smrg
841301ea0f4Smrg  pI740 = I740PTR(pScrn);
842301ea0f4Smrg
8430cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
844301ea0f4Smrg  xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->MMIOBase, 0x80000);
8450cc67336Smrg#else
8460cc67336Smrg  pci_device_unmap_range(pI740->PciInfo, pI740->MMIOBase, 0x80000);
8470cc67336Smrg#endif
848301ea0f4Smrg  pI740->MMIOBase=0;
849301ea0f4Smrg
8500cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
851301ea0f4Smrg  xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->FbBase, pI740->FbMapSize);
8520cc67336Smrg#else
8530cc67336Smrg  pci_device_unmap_range(pI740->PciInfo, pI740->FbBase, pI740->FbMapSize);
8540cc67336Smrg#endif
855301ea0f4Smrg  pI740->FbBase = 0;
856301ea0f4Smrg  return TRUE;
857301ea0f4Smrg}
858301ea0f4Smrg
859301ea0f4Smrg/*
860301ea0f4Smrg * I740Save --
861301ea0f4Smrg *
862301ea0f4Smrg * This function saves the video state.  It reads all of the SVGA registers
863301ea0f4Smrg * into the vgaI740Rec data structure.  There is in general no need to
864301ea0f4Smrg * mask out bits here - just read the registers.
865301ea0f4Smrg */
866301ea0f4Smrgstatic void
867301ea0f4SmrgDoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg, Bool saveFonts)
868301ea0f4Smrg{
869301ea0f4Smrg  I740Ptr pI740;
870301ea0f4Smrg  vgaHWPtr hwp;
871301ea0f4Smrg
872301ea0f4Smrg  pI740 = I740PTR(pScrn);
873301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
874301ea0f4Smrg
875301ea0f4Smrg  /*
876301ea0f4Smrg   * This function will handle creating the data structure and filling
877301ea0f4Smrg   * in the generic VGA portion.
878301ea0f4Smrg   */
879301ea0f4Smrg  if (saveFonts)
880301ea0f4Smrg    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS);
881301ea0f4Smrg  else
882301ea0f4Smrg    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE);
883301ea0f4Smrg
884301ea0f4Smrg  /*
885301ea0f4Smrg   * The port I/O code necessary to read in the extended registers
886301ea0f4Smrg   * into the fields of the vgaI740Rec structure goes here.
887301ea0f4Smrg   */
888301ea0f4Smrg
889301ea0f4Smrg  i740Reg->IOControl = pI740->readControl(pI740, XRX, IO_CTNL);
890301ea0f4Smrg  i740Reg->AddressMapping = pI740->readControl(pI740, XRX, ADDRESS_MAPPING);
891301ea0f4Smrg  i740Reg->BitBLTControl = pI740->readControl(pI740, XRX, BITBLT_CNTL);
892301ea0f4Smrg  i740Reg->VideoClk2_M = pI740->readControl(pI740, XRX, VCLK2_VCO_M);
893301ea0f4Smrg  i740Reg->VideoClk2_N = pI740->readControl(pI740, XRX, VCLK2_VCO_N);
894301ea0f4Smrg  i740Reg->VideoClk2_MN_MSBs = pI740->readControl(pI740, XRX, VCLK2_VCO_MN_MSBS);
895301ea0f4Smrg  i740Reg->VideoClk2_DivisorSel = pI740->readControl(pI740, XRX, VCLK2_VCO_DIV_SEL);
896301ea0f4Smrg  i740Reg->PLLControl = pI740->readControl(pI740, XRX, PLL_CNTL);
897301ea0f4Smrg
898301ea0f4Smrg  i740Reg->ExtVertTotal=hwp->readCrtc(hwp, EXT_VERT_TOTAL);
899301ea0f4Smrg  i740Reg->ExtVertDispEnd=hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
900301ea0f4Smrg  i740Reg->ExtVertSyncStart=hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
901301ea0f4Smrg  i740Reg->ExtVertBlankStart=hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
902301ea0f4Smrg  i740Reg->ExtHorizTotal=hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
903301ea0f4Smrg  i740Reg->ExtHorizBlank=hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
904301ea0f4Smrg  i740Reg->ExtOffset=hwp->readCrtc(hwp, EXT_OFFSET);
905301ea0f4Smrg  i740Reg->InterlaceControl=hwp->readCrtc(hwp, INTERLACE_CNTL);
906301ea0f4Smrg
907301ea0f4Smrg  i740Reg->PixelPipeCfg0 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
908301ea0f4Smrg  i740Reg->PixelPipeCfg1 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1);
909301ea0f4Smrg  i740Reg->PixelPipeCfg2 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2);
910301ea0f4Smrg  i740Reg->DisplayControl = pI740->readControl(pI740, XRX, DISPLAY_CNTL);
911301ea0f4Smrg
912301ea0f4Smrg  i740Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
913301ea0f4Smrg}
914301ea0f4Smrg
915301ea0f4Smrgstatic void
916301ea0f4SmrgI740Save(ScrnInfoPtr pScrn)
917301ea0f4Smrg{
918301ea0f4Smrg  vgaHWPtr hwp;
919301ea0f4Smrg  I740Ptr pI740;
920301ea0f4Smrg
921301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
922301ea0f4Smrg  pI740 = I740PTR(pScrn);
923301ea0f4Smrg  DoSave(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE);
924301ea0f4Smrg}
925301ea0f4Smrg
926301ea0f4Smrgstatic void
927301ea0f4SmrgDoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg,
928301ea0f4Smrg	  Bool restoreFonts) {
929301ea0f4Smrg  I740Ptr pI740;
930301ea0f4Smrg  vgaHWPtr hwp;
931301ea0f4Smrg  unsigned char temp;
932301ea0f4Smrg  unsigned int  itemp;
933301ea0f4Smrg
934301ea0f4Smrg  pI740 = I740PTR(pScrn);
935301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
936301ea0f4Smrg
937301ea0f4Smrg  vgaHWProtect(pScrn, TRUE);
938301ea0f4Smrg#if 0
939301ea0f4Smrg  temp=hwp->readCrtc(hwp, VERT_SYNC_END);
940301ea0f4Smrg  hwp->writeCrtc(hwp, VERT_SYNC_END, temp&0x7F);
941301ea0f4Smrg#endif
942301ea0f4Smrg
943301ea0f4Smrg  temp = pI740->readControl(pI740, MRX, ACQ_CNTL_2);
944301ea0f4Smrg  if ((temp & FRAME_CAP_MODE) == SINGLE_CAP_MODE) {
945301ea0f4Smrg    temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1);
946301ea0f4Smrg    temp |= BLANK_DISP_OVERLAY; /* Disable the overlay */
947301ea0f4Smrg    pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp);
948301ea0f4Smrg  } else {
949301ea0f4Smrg    temp &= ~FRAME_CAP_MODE;
950301ea0f4Smrg    pI740->writeControl(pI740, MRX, ACQ_CNTL_2, temp);
951301ea0f4Smrg  }
952301ea0f4Smrg  usleep(50000);
953301ea0f4Smrg
954301ea0f4Smrg  /* Turn off DRAM Refresh */
955301ea0f4Smrg  pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
956301ea0f4Smrg
957301ea0f4Smrg  usleep(1000); /* Wait 1 ms */
958301ea0f4Smrg
959301ea0f4Smrg  /* Write the M, N and P values */
960301ea0f4Smrg  pI740->writeControl(pI740, XRX, VCLK2_VCO_M, i740Reg->VideoClk2_M);
961301ea0f4Smrg  pI740->writeControl(pI740, XRX, VCLK2_VCO_N, i740Reg->VideoClk2_N);
962301ea0f4Smrg  pI740->writeControl(pI740, XRX, VCLK2_VCO_MN_MSBS, i740Reg->VideoClk2_MN_MSBs);
963301ea0f4Smrg  pI740->writeControl(pI740, XRX, VCLK2_VCO_DIV_SEL, i740Reg->VideoClk2_DivisorSel);
964301ea0f4Smrg
965301ea0f4Smrg  /*
966301ea0f4Smrg   * Turn on 8 bit dac mode, if requested.  This is needed to make
967301ea0f4Smrg   * sure that vgaHWRestore writes the values into the DAC properly.
968301ea0f4Smrg   * The problem occurs if 8 bit dac mode is requested and the HW is
969301ea0f4Smrg   * in 6 bit dac mode.  If this happens, all the values are
970301ea0f4Smrg   * automatically shifted left twice by the HW and incorrect colors
971301ea0f4Smrg   * will be displayed on the screen.  The only time this can happen
972301ea0f4Smrg   * is at server startup time and when switching back from a VT.
973301ea0f4Smrg   */
974301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
975301ea0f4Smrg  temp &= 0x7F; /* Save all but the 8 bit dac mode bit */
976301ea0f4Smrg  temp |= (i740Reg->PixelPipeCfg0 & DAC_8_BIT);
977301ea0f4Smrg  pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp);
978301ea0f4Smrg
979301ea0f4Smrg  /*
980301ea0f4Smrg   * Code to restore any SVGA registers that have been saved/modified
981301ea0f4Smrg   * goes here.  Note that it is allowable, and often correct, to
982301ea0f4Smrg   * only modify certain bits in a register by a read/modify/write cycle.
983301ea0f4Smrg   *
984301ea0f4Smrg   * A special case - when using an external clock-setting program,
985301ea0f4Smrg   * this function must not change bits associated with the clock
986301ea0f4Smrg   * selection.  This condition can be checked by the condition:
987301ea0f4Smrg   *
988301ea0f4Smrg   *	if (restore->std.NoClock >= 0)
989301ea0f4Smrg   *		restore clock-select bits.
990301ea0f4Smrg   */
991301ea0f4Smrg  if (restoreFonts)
992301ea0f4Smrg    vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
993301ea0f4Smrg  else
994301ea0f4Smrg    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
995301ea0f4Smrg
996301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i740Reg->ExtVertTotal);
997301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i740Reg->ExtVertDispEnd);
998301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i740Reg->ExtVertSyncStart);
999301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i740Reg->ExtVertBlankStart);
1000301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i740Reg->ExtHorizTotal);
1001301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i740Reg->ExtHorizBlank);
1002301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_OFFSET, i740Reg->ExtOffset);
1003301ea0f4Smrg
1004301ea0f4Smrg  temp=hwp->readCrtc(hwp, INTERLACE_CNTL);
1005301ea0f4Smrg  temp &= ~INTERLACE_ENABLE;
1006301ea0f4Smrg  temp |= i740Reg->InterlaceControl;
1007301ea0f4Smrg  hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
1008301ea0f4Smrg
1009301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, ADDRESS_MAPPING);
1010301ea0f4Smrg  temp &= 0xE0; /* Save reserved bits 7:5 */
1011301ea0f4Smrg  temp |= i740Reg->AddressMapping;
1012301ea0f4Smrg  pI740->writeControl(pI740, XRX, ADDRESS_MAPPING, temp);
1013301ea0f4Smrg
1014301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, BITBLT_CNTL);
1015301ea0f4Smrg  temp &= ~COLEXP_MODE;
1016301ea0f4Smrg  temp |= i740Reg->BitBLTControl;
1017301ea0f4Smrg  pI740->writeControl(pI740, XRX, BITBLT_CNTL, temp);
1018301ea0f4Smrg
1019301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, DISPLAY_CNTL);
1020301ea0f4Smrg  temp &= ~(VGA_WRAP_MODE | GUI_MODE);
1021301ea0f4Smrg  temp |= i740Reg->DisplayControl;
1022301ea0f4Smrg  pI740->writeControl(pI740, XRX, DISPLAY_CNTL, temp);
1023301ea0f4Smrg
1024301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0);
1025301ea0f4Smrg  temp &= 0x64; /* Save reserved bits 6:5,2 */
1026301ea0f4Smrg  temp |= i740Reg->PixelPipeCfg0;
1027301ea0f4Smrg  pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp);
1028301ea0f4Smrg
1029301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2);
1030301ea0f4Smrg  temp &= 0xF3; /* Save reserved bits 7:4,1:0 */
1031301ea0f4Smrg  temp |= i740Reg->PixelPipeCfg2;
1032301ea0f4Smrg  pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_2, temp);
1033301ea0f4Smrg
1034301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, PLL_CNTL);
1035301ea0f4Smrg  temp = i740Reg->PLLControl; /* To fix the 2.3X BIOS problem */
1036301ea0f4Smrg  pI740->writeControl(pI740, XRX, PLL_CNTL, temp);
1037301ea0f4Smrg
1038301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1);
1039301ea0f4Smrg  temp &= ~DISPLAY_COLOR_MODE;
1040301ea0f4Smrg  temp |= i740Reg->PixelPipeCfg1;
1041301ea0f4Smrg  pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_1, temp);
1042301ea0f4Smrg
1043301ea0f4Smrg  itemp = INREG(FWATER_BLC);
1044301ea0f4Smrg  itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
1045301ea0f4Smrg  itemp |= i740Reg->LMI_FIFO_Watermark;
1046301ea0f4Smrg  OUTREG(FWATER_BLC, itemp);
1047301ea0f4Smrg
1048301ea0f4Smrg  /* Turn on DRAM Refresh */
1049301ea0f4Smrg  pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
1050301ea0f4Smrg
1051301ea0f4Smrg  temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1);
1052301ea0f4Smrg  temp &= ~BLANK_DISP_OVERLAY; /* Re-enable the overlay */
1053301ea0f4Smrg  pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp);
1054301ea0f4Smrg
1055301ea0f4Smrg  if (!(vgaReg->Attribute[0x10] & 0x1)) {
1056301ea0f4Smrg    usleep(50000);
1057301ea0f4Smrg    if (restoreFonts)
1058301ea0f4Smrg      vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE);
1059301ea0f4Smrg    else
1060301ea0f4Smrg      vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
1061301ea0f4Smrg  }
1062301ea0f4Smrg
1063301ea0f4Smrg  vgaHWProtect(pScrn, FALSE);
1064301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, IO_CTNL);
1065301ea0f4Smrg  temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
1066301ea0f4Smrg  temp |= i740Reg->IOControl;
1067301ea0f4Smrg  pI740->writeControl(pI740, XRX, IO_CTNL, temp);
1068301ea0f4Smrg#if 0
1069301ea0f4Smrg  temp=hwp->readCrtc(hwp, VERT_SYNC_END);
1070301ea0f4Smrg  hwp->writeCrtc(hwp, VERT_SYNC_END, temp|0x80);
1071301ea0f4Smrg#endif
1072301ea0f4Smrg}
1073301ea0f4Smrg
1074301ea0f4Smrgstatic void
1075301ea0f4SmrgI740Restore(ScrnInfoPtr pScrn) {
1076301ea0f4Smrg  vgaHWPtr hwp;
1077301ea0f4Smrg  I740Ptr pI740;
1078301ea0f4Smrg
1079301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1080301ea0f4Smrg  pI740 = I740PTR(pScrn);
1081301ea0f4Smrg
1082301ea0f4Smrg  DoRestore(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE);
1083301ea0f4Smrg}
1084301ea0f4Smrg
1085301ea0f4Smrg/*
1086301ea0f4Smrg * I740CalcFIFO --
1087301ea0f4Smrg *
1088301ea0f4Smrg * Calculate burst length and FIFO watermark.
1089301ea0f4Smrg */
1090301ea0f4Smrg
1091301ea0f4Smrgstatic unsigned int
1092301ea0f4SmrgI740CalcFIFO(ScrnInfoPtr pScrn, double freq)
1093301ea0f4Smrg{
1094301ea0f4Smrg  unsigned int wm = 0x18120000;
1095301ea0f4Smrg  I740Ptr pI740;
1096301ea0f4Smrg
1097301ea0f4Smrg  pI740 = I740PTR(pScrn);
1098301ea0f4Smrg
1099301ea0f4Smrg  /*
1100301ea0f4Smrg   * Would like to calculate these values automatically, but a generic
1101301ea0f4Smrg   * algorithm does not seem possible.  Note: These FIFO water mark
1102301ea0f4Smrg   * values were tested on several cards and seem to eliminate the
1103301ea0f4Smrg   * all of the snow and vertical banding, but fine adjustments will
1104301ea0f4Smrg   * probably be required for other cards.
1105301ea0f4Smrg   */
1106301ea0f4Smrg
1107301ea0f4Smrg  switch (pScrn->bitsPerPixel) {
1108301ea0f4Smrg  case 8:
1109301ea0f4Smrg    if (pI740->HasSGRAM) {
1110301ea0f4Smrg      if      (freq > 200) wm = 0x18120000;
1111301ea0f4Smrg      else if (freq > 175) wm = 0x16110000;
1112301ea0f4Smrg      else if (freq > 135) wm = 0x120E0000;
1113301ea0f4Smrg      else                 wm = 0x100D0000;
1114301ea0f4Smrg    } else {
1115301ea0f4Smrg      if      (freq > 200) wm = 0x18120000;
1116301ea0f4Smrg      else if (freq > 175) wm = 0x16110000;
1117301ea0f4Smrg      else if (freq > 135) wm = 0x120E0000;
1118301ea0f4Smrg      else                 wm = 0x100D0000;
1119301ea0f4Smrg    }
1120301ea0f4Smrg    break;
1121301ea0f4Smrg  case 16:
1122301ea0f4Smrg    if (pI740->HasSGRAM) {
1123301ea0f4Smrg      if      (freq > 140) wm = 0x2C1D0000;
1124301ea0f4Smrg      else if (freq > 120) wm = 0x2C180000;
1125301ea0f4Smrg      else if (freq > 100) wm = 0x24160000;
1126301ea0f4Smrg      else if (freq >  90) wm = 0x18120000;
1127301ea0f4Smrg      else if (freq >  50) wm = 0x16110000;
1128301ea0f4Smrg      else if (freq >  32) wm = 0x13100000;
1129301ea0f4Smrg      else                 wm = 0x120E0000;
1130301ea0f4Smrg    } else {
1131301ea0f4Smrg      if      (freq > 160) wm = 0x28200000;
1132301ea0f4Smrg      else if (freq > 140) wm = 0x2A1E0000;
1133301ea0f4Smrg      else if (freq > 130) wm = 0x2B1A0000;
1134301ea0f4Smrg      else if (freq > 120) wm = 0x2C180000;
1135301ea0f4Smrg      else if (freq > 100) wm = 0x24180000;
1136301ea0f4Smrg      else if (freq >  90) wm = 0x18120000;
1137301ea0f4Smrg      else if (freq >  50) wm = 0x16110000;
1138301ea0f4Smrg      else if (freq >  32) wm = 0x13100000;
1139301ea0f4Smrg      else                 wm = 0x120E0000;
1140301ea0f4Smrg    }
1141301ea0f4Smrg    break;
1142301ea0f4Smrg  case 24:
1143301ea0f4Smrg    if (pI740->HasSGRAM) {
1144301ea0f4Smrg      if      (freq > 130) wm = 0x31200000;
1145301ea0f4Smrg      else if (freq > 120) wm = 0x2E200000;
1146301ea0f4Smrg      else if (freq > 100) wm = 0x2C1D0000;
1147301ea0f4Smrg      else if (freq >  80) wm = 0x25180000;
1148301ea0f4Smrg      else if (freq >  64) wm = 0x24160000;
1149301ea0f4Smrg      else if (freq >  49) wm = 0x18120000;
1150301ea0f4Smrg      else if (freq >  32) wm = 0x16110000;
1151301ea0f4Smrg      else                 wm = 0x13100000;
1152301ea0f4Smrg    } else {
1153301ea0f4Smrg      if      (freq > 120) wm = 0x311F0000;
1154301ea0f4Smrg      else if (freq > 100) wm = 0x2C1D0000;
1155301ea0f4Smrg      else if (freq >  80) wm = 0x25180000;
1156301ea0f4Smrg      else if (freq >  64) wm = 0x24160000;
1157301ea0f4Smrg      else if (freq >  49) wm = 0x18120000;
1158301ea0f4Smrg      else if (freq >  32) wm = 0x16110000;
1159301ea0f4Smrg      else                 wm = 0x13100000;
1160301ea0f4Smrg    }
1161301ea0f4Smrg    break;
1162301ea0f4Smrg  case 32:
1163301ea0f4Smrg    if (pI740->HasSGRAM) {
1164301ea0f4Smrg      if      (freq >  80) wm = 0x2A200000;
1165301ea0f4Smrg      else if (freq >  60) wm = 0x281A0000;
1166301ea0f4Smrg      else if (freq >  49) wm = 0x25180000;
1167301ea0f4Smrg      else if (freq >  32) wm = 0x18120000;
1168301ea0f4Smrg      else                 wm = 0x16110000;
1169301ea0f4Smrg    } else {
1170301ea0f4Smrg      if      (freq >  80) wm = 0x29200000;
1171301ea0f4Smrg      else if (freq >  60) wm = 0x281A0000;
1172301ea0f4Smrg      else if (freq >  49) wm = 0x25180000;
1173301ea0f4Smrg      else if (freq >  32) wm = 0x18120000;
1174301ea0f4Smrg      else                 wm = 0x16110000;
1175301ea0f4Smrg    }
1176301ea0f4Smrg    break;
1177301ea0f4Smrg  }
1178301ea0f4Smrg
1179301ea0f4Smrg  return wm;
1180301ea0f4Smrg}
1181301ea0f4Smrg
1182301ea0f4Smrg/*
1183301ea0f4Smrg * I740CalcVCLK --
1184301ea0f4Smrg *
1185301ea0f4Smrg * Determine the closest clock frequency to the one requested.
1186301ea0f4Smrg */
1187301ea0f4Smrg
1188301ea0f4Smrg#define MAX_VCO_FREQ 450.0
1189301ea0f4Smrg#define TARGET_MAX_N 30
1190301ea0f4Smrg#define REF_FREQ 66.66666666667
1191301ea0f4Smrg
1192301ea0f4Smrg#define CALC_VCLK(m,n,p,d) \
1193301ea0f4Smrg    (double)m / ((double)n * (1 << p)) * (4 << (d << 1)) * REF_FREQ
1194301ea0f4Smrg
1195301ea0f4Smrgstatic void
1196301ea0f4SmrgI740CalcVCLK(ScrnInfoPtr pScrn, double freq)
1197301ea0f4Smrg{
1198301ea0f4Smrg  I740Ptr pI740;
1199301ea0f4Smrg  I740RegPtr i740Reg;
1200301ea0f4Smrg  int m, n, p, d;
1201301ea0f4Smrg  double f_out;
1202301ea0f4Smrg  double f_err;
1203301ea0f4Smrg  double f_vco;
1204301ea0f4Smrg  int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
1205301ea0f4Smrg  double f_target = freq;
1206301ea0f4Smrg  double err_max = 0.005;
1207301ea0f4Smrg  double err_target = 0.001;
1208301ea0f4Smrg  double err_best = 999999.0;
1209301ea0f4Smrg
1210301ea0f4Smrg  pI740 = I740PTR(pScrn);
1211301ea0f4Smrg  i740Reg = &pI740->ModeReg;
1212301ea0f4Smrg
1213301ea0f4Smrg  p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2);
1214301ea0f4Smrg  d_best = d = 0;
1215301ea0f4Smrg
1216301ea0f4Smrg  f_vco = f_target * (1 << p);
1217301ea0f4Smrg
1218301ea0f4Smrg  n = 2;
1219301ea0f4Smrg  do {
1220301ea0f4Smrg    n++;
1221301ea0f4Smrg    m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
1222301ea0f4Smrg    if (m < 3) m = 3;
1223301ea0f4Smrg    f_out = CALC_VCLK(m,n,p,d);
1224301ea0f4Smrg    f_err = 1.0 - (f_target/f_out);
1225301ea0f4Smrg    if (fabs(f_err) < err_max) {
1226301ea0f4Smrg      m_best = m;
1227301ea0f4Smrg      n_best = n;
1228301ea0f4Smrg      err_best = f_err;
1229301ea0f4Smrg    }
1230301ea0f4Smrg  } while ((fabs(f_err) >= err_target) &&
1231301ea0f4Smrg	   ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
1232301ea0f4Smrg
1233301ea0f4Smrg  if (fabs(f_err) < err_target) {
1234301ea0f4Smrg    m_best = m;
1235301ea0f4Smrg    n_best = n;
1236301ea0f4Smrg  }
1237301ea0f4Smrg
1238301ea0f4Smrg  i740Reg->VideoClk2_M          = (m_best-2) & 0xFF;
1239301ea0f4Smrg  i740Reg->VideoClk2_N          = (n_best-2) & 0xFF;
1240301ea0f4Smrg  i740Reg->VideoClk2_MN_MSBs    = ((((n_best-2) >> 4) & VCO_N_MSBS) |
1241301ea0f4Smrg				   (((m_best-2) >> 8) & VCO_M_MSBS));
1242301ea0f4Smrg  i740Reg->VideoClk2_DivisorSel = ((p_best << 4) |
1243301ea0f4Smrg				   (d_best ? 4 : 0) |
1244301ea0f4Smrg				   REF_DIV_1);
1245301ea0f4Smrg}
1246301ea0f4Smrg
1247301ea0f4Smrgstatic Bool
1248301ea0f4SmrgI740SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) {
1249301ea0f4Smrg  I740Ptr pI740;
1250301ea0f4Smrg  I740RegPtr i740Reg;
1251301ea0f4Smrg  vgaRegPtr pVga;
1252301ea0f4Smrg  double dclk = mode->Clock/1000.0;
1253301ea0f4Smrg
1254301ea0f4Smrg  pI740 = I740PTR(pScrn);
1255301ea0f4Smrg  i740Reg = &pI740->ModeReg;
1256301ea0f4Smrg  pVga = &VGAHWPTR(pScrn)->ModeReg;
1257301ea0f4Smrg
1258301ea0f4Smrg  switch (pScrn->bitsPerPixel) {
1259301ea0f4Smrg  case 8:
1260301ea0f4Smrg    pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
1261301ea0f4Smrg    i740Reg->ExtOffset      = pScrn->displayWidth >> 11;
1262301ea0f4Smrg    i740Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
1263301ea0f4Smrg    i740Reg->BitBLTControl = COLEXP_8BPP;
1264301ea0f4Smrg    break;
1265301ea0f4Smrg  case 16:
1266301ea0f4Smrg    if (pScrn->weight.green == 5) {
1267301ea0f4Smrg      i740Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
1268301ea0f4Smrg    } else {
1269301ea0f4Smrg      i740Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
1270301ea0f4Smrg    }
1271301ea0f4Smrg    pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
1272301ea0f4Smrg    i740Reg->ExtOffset      = pScrn->displayWidth >> 10;
1273301ea0f4Smrg    i740Reg->BitBLTControl = COLEXP_16BPP;
1274301ea0f4Smrg    break;
1275301ea0f4Smrg  case 24:
1276301ea0f4Smrg    pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
1277301ea0f4Smrg    i740Reg->ExtOffset      = (pScrn->displayWidth * 3) >> 11;
1278301ea0f4Smrg    i740Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
1279301ea0f4Smrg    i740Reg->BitBLTControl = COLEXP_24BPP;
1280301ea0f4Smrg    break;
1281301ea0f4Smrg  case 32:
1282301ea0f4Smrg    pVga->CRTC[0x13] = pScrn->displayWidth >> 1;
1283301ea0f4Smrg    i740Reg->ExtOffset      = pScrn->displayWidth >> 9;
1284301ea0f4Smrg    i740Reg->PixelPipeCfg1 = DISPLAY_32BPP_MODE;
1285301ea0f4Smrg    i740Reg->BitBLTControl = COLEXP_RESERVED; /* Not implemented on i740 */
1286301ea0f4Smrg    break;
1287301ea0f4Smrg  default:
1288301ea0f4Smrg    break;
1289301ea0f4Smrg  }
1290301ea0f4Smrg
1291301ea0f4Smrg  /* Turn on 8 bit dac if requested */
1292301ea0f4Smrg  if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE))
1293301ea0f4Smrg    i740Reg->PixelPipeCfg0 = DAC_6_BIT;
1294301ea0f4Smrg  else
1295301ea0f4Smrg    i740Reg->PixelPipeCfg0 = DAC_8_BIT;
1296301ea0f4Smrg
1297301ea0f4Smrg  i740Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE /*| OVERLAY_GAMMA_ENABLE*/;
1298301ea0f4Smrg
1299301ea0f4Smrg  /* Turn on Extended VGA Interpretation */
1300301ea0f4Smrg  i740Reg->IOControl = EXTENDED_CRTC_CNTL;
1301301ea0f4Smrg
1302301ea0f4Smrg  /* Turn on linear and page mapping */
1303301ea0f4Smrg  i740Reg->AddressMapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
1304301ea0f4Smrg
1305301ea0f4Smrg  /* Turn on GUI mode */
1306301ea0f4Smrg  i740Reg->DisplayControl = HIRES_MODE;
1307301ea0f4Smrg
1308301ea0f4Smrg  /* Set the MCLK freq */
1309301ea0f4Smrg  if (xf86ReturnOptValBool(pI740->Options, OPTION_SLOW_RAM, FALSE))
1310301ea0f4Smrg    i740Reg->PLLControl = PLL_MEMCLK__66667KHZ; /*  66 MHz */
1311301ea0f4Smrg  else
1312301ea0f4Smrg    i740Reg->PLLControl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
1313301ea0f4Smrg
1314301ea0f4Smrg  /* Calculate the extended CRTC regs */
1315301ea0f4Smrg  i740Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
1316301ea0f4Smrg  i740Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
1317301ea0f4Smrg  i740Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
1318301ea0f4Smrg  i740Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
1319301ea0f4Smrg  i740Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
1320301ea0f4Smrg  /*
1321301ea0f4Smrg   * the KGA fix in vgaHW.c results in the first
1322301ea0f4Smrg   * scanline and the first character clock (8 pixels)
1323301ea0f4Smrg   * of each scanline thereafter on display with an i740
1324301ea0f4Smrg   * to be blank. Restoring CRTC 3, 5, & 22 to their
1325301ea0f4Smrg   * "theoretical" values corrects the problem. KAO.
1326301ea0f4Smrg   */
1327301ea0f4Smrg  i740Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0) << 6;
1328301ea0f4Smrg  vgaHWVBlankKGA(mode, pVga, 8, 0);
1329301ea0f4Smrg
1330301ea0f4Smrg  /* Turn on interlaced mode if necessary */
1331301ea0f4Smrg  if (mode->Flags & V_INTERLACE)
1332301ea0f4Smrg    i740Reg->InterlaceControl = INTERLACE_ENABLE;
1333301ea0f4Smrg  else
1334301ea0f4Smrg    i740Reg->InterlaceControl = INTERLACE_DISABLE;
1335301ea0f4Smrg
1336301ea0f4Smrg  /*
1337301ea0f4Smrg   * Set the overscan color to 0.
1338301ea0f4Smrg   * NOTE: This only affects >8bpp mode.
1339301ea0f4Smrg   */
1340301ea0f4Smrg  pVga->Attribute[0x11] = 0;
1341301ea0f4Smrg
1342301ea0f4Smrg  /*
1343301ea0f4Smrg   * Calculate the VCLK that most closely matches the requested dot
1344301ea0f4Smrg   * clock.
1345301ea0f4Smrg   */
1346301ea0f4Smrg  I740CalcVCLK(pScrn, dclk);
1347301ea0f4Smrg
1348301ea0f4Smrg  /* Since we program the clocks ourselves, always use VCLK2. */
1349301ea0f4Smrg  pVga->MiscOutReg |= 0x0C;
1350301ea0f4Smrg
1351301ea0f4Smrg  /* Calculate the FIFO Watermark and Burst Length. */
1352301ea0f4Smrg  i740Reg->LMI_FIFO_Watermark = I740CalcFIFO(pScrn, dclk);
1353301ea0f4Smrg
1354301ea0f4Smrg  /*-Overlay-*/
1355301ea0f4Smrg  pI740->ov_offset_x=((mode->CrtcHTotal-mode->CrtcHDisplay) & ~7)-9;
1356301ea0f4Smrg  pI740->ov_offset_y=mode->CrtcVTotal-mode->CrtcVSyncEnd-2;
1357301ea0f4Smrg  /*-*/
1358301ea0f4Smrg
1359301ea0f4Smrg  return TRUE;
1360301ea0f4Smrg}
1361301ea0f4Smrg
1362301ea0f4Smrgstatic Bool
1363301ea0f4SmrgI740ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode_src)
1364301ea0f4Smrg{
1365301ea0f4Smrg  vgaHWPtr hwp;
1366301ea0f4Smrg  I740Ptr pI740;
1367301ea0f4Smrg  struct _DisplayModeRec mode_dst;
1368301ea0f4Smrg  DisplayModePtr mode=&mode_dst;
1369301ea0f4Smrg
1370301ea0f4Smrg  *mode=*mode_src;
1371301ea0f4Smrg
1372301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1373301ea0f4Smrg  pI740 = I740PTR(pScrn);
1374301ea0f4Smrg
1375301ea0f4Smrg  vgaHWUnlock(hwp);
1376301ea0f4Smrg
1377301ea0f4Smrg
1378301ea0f4Smrg  if(pI740->usevgacompat)
1379301ea0f4Smrg    { /* Try to get the same visual aspect as a S3 board */
1380301ea0f4Smrg      mode->CrtcHSyncStart+=16;
1381301ea0f4Smrg      mode->CrtcHSyncEnd  +=16;
1382301ea0f4Smrg    }
1383301ea0f4Smrg
1384301ea0f4Smrg  if (!vgaHWInit(pScrn, mode)) return FALSE;
1385301ea0f4Smrg
1386301ea0f4Smrg  pScrn->vtSema = TRUE;
1387301ea0f4Smrg
1388301ea0f4Smrg  if (!I740SetMode(pScrn, mode)) return FALSE;
1389301ea0f4Smrg
1390301ea0f4Smrg  DoRestore(pScrn, &hwp->ModeReg, &pI740->ModeReg, FALSE);
1391301ea0f4Smrg
1392301ea0f4Smrg  return TRUE;
1393301ea0f4Smrg}
1394301ea0f4Smrg
1395301ea0f4Smrgstatic void I740LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual)
1396301ea0f4Smrg{
1397301ea0f4Smrg  vgaHWPtr hwp;
1398301ea0f4Smrg  int i, index;
1399301ea0f4Smrg  unsigned char r, g, b;
1400301ea0f4Smrg
1401301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1402301ea0f4Smrg
1403301ea0f4Smrg  for (i=0; i<numColors; i++)
1404301ea0f4Smrg    {
1405301ea0f4Smrg      index=indices[i/2];
1406301ea0f4Smrg      r=colors[index].red;
1407301ea0f4Smrg      b=colors[index].blue;
1408301ea0f4Smrg      g=colors[index].green;
1409301ea0f4Smrg
1410301ea0f4Smrg      hwp->writeDacWriteAddr(hwp, index<<2);
1411301ea0f4Smrg      hwp->writeDacData(hwp, r);
1412301ea0f4Smrg      hwp->writeDacData(hwp, g);
1413301ea0f4Smrg      hwp->writeDacData(hwp, b);
1414301ea0f4Smrg
1415301ea0f4Smrg      i++;
1416301ea0f4Smrg      hwp->writeDacWriteAddr(hwp, index<<2);
1417301ea0f4Smrg      hwp->writeDacData(hwp, r);
1418301ea0f4Smrg      hwp->writeDacData(hwp, g);
1419301ea0f4Smrg      hwp->writeDacData(hwp, b);
1420301ea0f4Smrg    }
1421301ea0f4Smrg}
1422301ea0f4Smrg
1423301ea0f4Smrgstatic void I740LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual)
1424301ea0f4Smrg{
1425301ea0f4Smrg  vgaHWPtr hwp;
1426301ea0f4Smrg  int i, index;
1427301ea0f4Smrg  unsigned char r, g, b;
1428301ea0f4Smrg
1429301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1430301ea0f4Smrg  for (i=0; i<numColors; i++) {
1431301ea0f4Smrg    index=indices[i/2];
1432301ea0f4Smrg    r=colors[index].red;
1433301ea0f4Smrg    b=colors[index].blue;
1434301ea0f4Smrg    index=indices[i];
1435301ea0f4Smrg    g=colors[index].green;
1436301ea0f4Smrg    hwp->writeDacWriteAddr(hwp, index<<2);
1437301ea0f4Smrg    hwp->writeDacData(hwp, r);
1438301ea0f4Smrg    hwp->writeDacData(hwp, g);
1439301ea0f4Smrg    hwp->writeDacData(hwp, b);
1440301ea0f4Smrg    i++;
1441301ea0f4Smrg    index=indices[i];
1442301ea0f4Smrg    g=colors[index].green;
1443301ea0f4Smrg    hwp->writeDacWriteAddr(hwp, index<<2);
1444301ea0f4Smrg    hwp->writeDacData(hwp, r);
1445301ea0f4Smrg    hwp->writeDacData(hwp, g);
1446301ea0f4Smrg    hwp->writeDacData(hwp, b);
1447301ea0f4Smrg  }
1448301ea0f4Smrg}
1449301ea0f4Smrg
1450301ea0f4Smrgstatic void
1451301ea0f4SmrgI740LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1452301ea0f4Smrg		  VisualPtr pVisual) {
1453301ea0f4Smrg  vgaHWPtr hwp;
1454301ea0f4Smrg  int i, index;
1455301ea0f4Smrg  unsigned char r, g, b;
1456301ea0f4Smrg
1457301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1458301ea0f4Smrg  for (i=0; i<numColors; i++) {
1459301ea0f4Smrg    index=indices[i];
1460301ea0f4Smrg    r=colors[index].red;
1461301ea0f4Smrg    b=colors[index].blue;
1462301ea0f4Smrg    index=indices[i];
1463301ea0f4Smrg    g=colors[index].green;
1464301ea0f4Smrg    hwp->writeDacWriteAddr(hwp, index);
1465301ea0f4Smrg    hwp->writeDacData(hwp, r);
1466301ea0f4Smrg    hwp->writeDacData(hwp, g);
1467301ea0f4Smrg    hwp->writeDacData(hwp, b);
1468301ea0f4Smrg  }
1469301ea0f4Smrg}
1470301ea0f4Smrg
1471301ea0f4Smrgstatic Bool
14725c69f917SmrgI740ScreenInit(SCREEN_INIT_ARGS_DECL) {
1473301ea0f4Smrg  ScrnInfoPtr pScrn;
1474301ea0f4Smrg  vgaHWPtr hwp;
1475301ea0f4Smrg  I740Ptr pI740;
1476301ea0f4Smrg  VisualPtr visual;
1477301ea0f4Smrg
14785c69f917Smrg  pScrn = xf86ScreenToScrn(pScreen);
1479301ea0f4Smrg  pI740 = I740PTR(pScrn);
1480301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1481301ea0f4Smrg
1482301ea0f4Smrg  if (!I740MapMem(pScrn)) return FALSE;
1483301ea0f4Smrg  pScrn->memPhysBase = pI740->LinearAddr;
1484301ea0f4Smrg  pScrn->fbOffset = 0;
1485301ea0f4Smrg
1486301ea0f4Smrg  if (!pI740->usePIO)
1487301ea0f4Smrg    vgaHWSetMmioFuncs(hwp, pI740->MMIOBase, 0);
1488301ea0f4Smrg  vgaHWGetIOBase(hwp);
1489301ea0f4Smrg  if (!vgaHWMapMem(pScrn)) return FALSE;
1490301ea0f4Smrg
1491301ea0f4Smrg  I740Save(pScrn);
1492301ea0f4Smrg  if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE;
1493301ea0f4Smrg
1494301ea0f4Smrg  I740SaveScreen(pScreen, SCREEN_SAVER_ON);
14955c69f917Smrg  I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1496301ea0f4Smrg
1497301ea0f4Smrg  miClearVisualTypes();
1498301ea0f4Smrg
1499301ea0f4Smrg  if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
1500301ea0f4Smrg			pScrn->rgbBits, pScrn->defaultVisual))
1501301ea0f4Smrg    return FALSE;
1502301ea0f4Smrg	if (!miSetPixmapDepths ()) return FALSE;
1503301ea0f4Smrg
1504301ea0f4Smrg  switch (pScrn->bitsPerPixel) {
1505301ea0f4Smrg  case 8:
1506301ea0f4Smrg  case 16:
1507301ea0f4Smrg  case 24:
1508301ea0f4Smrg  case 32:
1509301ea0f4Smrg    if (!fbScreenInit(pScreen, pI740->FbBase,
1510301ea0f4Smrg		       pScrn->virtualX, pScrn->virtualY,
1511301ea0f4Smrg		       pScrn->xDpi, pScrn->yDpi,
1512301ea0f4Smrg		       pScrn->displayWidth,pScrn->bitsPerPixel))
1513301ea0f4Smrg      return FALSE;
1514301ea0f4Smrg    break;
1515301ea0f4Smrg  default:
15165c69f917Smrg    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1517301ea0f4Smrg	       "Internal error: invalid bpp (%d) in I740ScrnInit\n",
1518301ea0f4Smrg	       pScrn->bitsPerPixel);
1519301ea0f4Smrg    return FALSE;
1520301ea0f4Smrg  }
1521301ea0f4Smrg  fbPictureInit(pScreen,0,0);
1522301ea0f4Smrg
1523301ea0f4Smrg  xf86SetBlackWhitePixels(pScreen);
1524301ea0f4Smrg
1525301ea0f4Smrg  memset(&(pI740->FbMemBox), 0, sizeof(BoxRec));
1526301ea0f4Smrg  pI740->FbMemBox.x1=0;
1527301ea0f4Smrg  pI740->FbMemBox.x2=pScrn->displayWidth;
1528301ea0f4Smrg  pI740->FbMemBox.y1=0;
1529301ea0f4Smrg  pI740->FbMemBox.y2=pI740->FbMapSize/(pScrn->displayWidth*pI740->cpp);
1530301ea0f4Smrg
1531301ea0f4Smrg  I740DGAInit(pScreen);
1532301ea0f4Smrg
1533301ea0f4Smrg  if (!xf86InitFBManager(pScreen, &pI740->FbMemBox)) {
1534301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n");
1535301ea0f4Smrg    return FALSE;
1536301ea0f4Smrg  }
1537301ea0f4Smrg
15385c69f917Smrg  if (!pI740->NoAccel) {
1539301ea0f4Smrg    if (!I740AccelInit(pScreen)) {
1540301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1541301ea0f4Smrg		 "Hardware acceleration initialization failed\n");
1542301ea0f4Smrg    }
1543301ea0f4Smrg  }
1544301ea0f4Smrg
1545301ea0f4Smrg  if (pScrn->bitsPerPixel>8) {
1546301ea0f4Smrg    visual = pScreen->visuals + pScreen->numVisuals;
1547301ea0f4Smrg    while (--visual >= pScreen->visuals) {
1548301ea0f4Smrg      if ((visual->class | DynamicClass) == DirectColor) {
1549301ea0f4Smrg	visual->offsetRed = pScrn->offset.red;
1550301ea0f4Smrg	visual->offsetGreen = pScrn->offset.green;
1551301ea0f4Smrg	visual->offsetBlue = pScrn->offset.blue;
1552301ea0f4Smrg	visual->redMask = pScrn->mask.red;
1553301ea0f4Smrg	visual->greenMask = pScrn->mask.green;
1554301ea0f4Smrg	visual->blueMask = pScrn->mask.blue;
1555301ea0f4Smrg      }
1556301ea0f4Smrg    }
1557301ea0f4Smrg  }
1558301ea0f4Smrg
1559301ea0f4Smrg  xf86SetBackingStore(pScreen);
1560301ea0f4Smrg  xf86SetSilkenMouse(pScreen);
1561301ea0f4Smrg
1562301ea0f4Smrg  miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1563301ea0f4Smrg
1564301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) {
1565301ea0f4Smrg    if (!I740CursorInit(pScreen)) {
1566301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1567301ea0f4Smrg		 "Hardware cursor initialization failed\n");
1568301ea0f4Smrg    }
1569301ea0f4Smrg  }
1570301ea0f4Smrg
1571301ea0f4Smrg  if (!miCreateDefColormap(pScreen)) return FALSE;
1572301ea0f4Smrg
1573301ea0f4Smrg  if (pScrn->bitsPerPixel==16)
1574301ea0f4Smrg    {
1575301ea0f4Smrg      if (pScrn->weight.green == 5)
1576301ea0f4Smrg	{
1577301ea0f4Smrg	  if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette15, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
1578301ea0f4Smrg	    return FALSE;
1579301ea0f4Smrg	}
1580301ea0f4Smrg      else
1581301ea0f4Smrg	{
1582301ea0f4Smrg	  if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette16, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
1583301ea0f4Smrg	    return FALSE;
1584301ea0f4Smrg	}
1585301ea0f4Smrg    }
1586301ea0f4Smrg  else
1587301ea0f4Smrg    {
1588301ea0f4Smrg      if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette24, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
1589301ea0f4Smrg	return FALSE;
1590301ea0f4Smrg    }
1591301ea0f4Smrg
1592301ea0f4Smrg  xf86DPMSInit(pScreen, I740DisplayPowerManagementSet, 0);
1593301ea0f4Smrg
1594301ea0f4Smrg  pScreen->SaveScreen = I740SaveScreen;
1595301ea0f4Smrg  pI740->CloseScreen = pScreen->CloseScreen;
1596301ea0f4Smrg  pScreen->CloseScreen = I740CloseScreen;
1597301ea0f4Smrg
1598301ea0f4Smrg  if (serverGeneration == 1)
1599301ea0f4Smrg    xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1600301ea0f4Smrg
1601301ea0f4Smrg  /* Overlay */
1602301ea0f4Smrg  I740InitVideo(pScreen); pI740->OverlayStart = pI740->CursorStart + 1024;
1603301ea0f4Smrg
1604301ea0f4Smrg  return TRUE;
1605301ea0f4Smrg}
1606301ea0f4Smrg
1607301ea0f4SmrgBool
16085c69f917SmrgI740SwitchMode(SWITCH_MODE_ARGS_DECL) {
16095c69f917Smrg  SCRN_INFO_PTR(arg);
1610301ea0f4Smrg  return I740ModeInit(pScrn, mode);
1611301ea0f4Smrg}
1612301ea0f4Smrg
1613301ea0f4Smrgvoid
16145c69f917SmrgI740AdjustFrame(ADJUST_FRAME_ARGS_DECL) {
16155c69f917Smrg  SCRN_INFO_PTR(arg);
1616301ea0f4Smrg  int Base;
1617301ea0f4Smrg  vgaHWPtr hwp;
1618301ea0f4Smrg
1619301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1620301ea0f4Smrg
1621301ea0f4Smrg  Base = (y * pScrn->displayWidth + x) >> 2;
1622301ea0f4Smrg  switch (pScrn->bitsPerPixel) {
1623301ea0f4Smrg  case  8:
1624301ea0f4Smrg    break;
1625301ea0f4Smrg  case 16:
1626301ea0f4Smrg    Base *= 2;
1627301ea0f4Smrg    break;
1628301ea0f4Smrg  case 24:
1629301ea0f4Smrg    /*
1630301ea0f4Smrg     * The last bit does not seem to have any effect on the start
1631301ea0f4Smrg     * address register in 24bpp mode, so...
1632301ea0f4Smrg     */
1633301ea0f4Smrg    Base &= 0xFFFFFFFE; /* ...ignore the last bit. */
1634301ea0f4Smrg    Base *= 3;
1635301ea0f4Smrg    break;
1636301ea0f4Smrg  case 32:
1637301ea0f4Smrg    Base *= 4;
1638301ea0f4Smrg    break;
1639301ea0f4Smrg  }
1640301ea0f4Smrg
1641301ea0f4Smrg  hwp->writeCrtc(hwp, START_ADDR_LO, Base&0xFF);
1642301ea0f4Smrg  hwp->writeCrtc(hwp, START_ADDR_HI, (Base&0xFF00)>>8);
1643301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base&0x3FC00000)>>22);
1644301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_START_ADDR,
1645301ea0f4Smrg		 ((Base&0x00eF0000)>>16|EXT_START_ADDR_ENABLE));
1646301ea0f4Smrg}
1647301ea0f4Smrg
1648301ea0f4Smrgstatic Bool
16495c69f917SmrgI740EnterVT(VT_FUNC_ARGS_DECL) {
16505c69f917Smrg  SCRN_INFO_PTR(arg);
1651301ea0f4Smrg
1652301ea0f4Smrg  if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE;
16535c69f917Smrg  I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1654301ea0f4Smrg  return TRUE;
1655301ea0f4Smrg}
1656301ea0f4Smrg
1657301ea0f4Smrgstatic void
16585c69f917SmrgI740LeaveVT(VT_FUNC_ARGS_DECL) {
16595c69f917Smrg  SCRN_INFO_PTR(arg);
1660301ea0f4Smrg  vgaHWPtr hwp;
1661301ea0f4Smrg
1662301ea0f4Smrg  hwp=VGAHWPTR(pScrn);
1663301ea0f4Smrg  I740Restore(pScrn);
1664301ea0f4Smrg  vgaHWLock(hwp);
1665301ea0f4Smrg}
1666301ea0f4Smrg
1667301ea0f4Smrgstatic Bool
16685c69f917SmrgI740CloseScreen(CLOSE_SCREEN_ARGS_DECL)
1669301ea0f4Smrg{
1670301ea0f4Smrg  ScrnInfoPtr pScrn;
1671301ea0f4Smrg  vgaHWPtr hwp;
1672301ea0f4Smrg  I740Ptr pI740;
1673301ea0f4Smrg
16745c69f917Smrg  pScrn = xf86ScreenToScrn(pScreen);
1675301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1676301ea0f4Smrg  pI740 = I740PTR(pScrn);
1677301ea0f4Smrg
1678301ea0f4Smrg  if (pScrn->vtSema) {
1679301ea0f4Smrg      I740Restore(pScrn);
1680301ea0f4Smrg      vgaHWLock(hwp);
1681301ea0f4Smrg  }
1682301ea0f4Smrg
1683301ea0f4Smrg  I740UnmapMem(pScrn);
1684301ea0f4Smrg  vgaHWUnmapMem(pScrn);
16855c69f917Smrg#ifdef HAVE_XAA_H
1686301ea0f4Smrg  if (pI740->AccelInfoRec)
1687301ea0f4Smrg    XAADestroyInfoRec(pI740->AccelInfoRec);
1688301ea0f4Smrg  pI740->AccelInfoRec=0;
16895c69f917Smrg#endif
1690301ea0f4Smrg  if (pI740->CursorInfoRec)
1691301ea0f4Smrg    xf86DestroyCursorInfoRec(pI740->CursorInfoRec);
1692301ea0f4Smrg  pI740->CursorInfoRec=0;
1693301ea0f4Smrg  pScrn->vtSema=FALSE;
1694301ea0f4Smrg
1695301ea0f4Smrg  pScreen->CloseScreen = pI740->CloseScreen;
16965c69f917Smrg  return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
1697301ea0f4Smrg}
1698301ea0f4Smrg
1699301ea0f4Smrgstatic void
17005c69f917SmrgI740FreeScreen(FREE_SCREEN_ARGS_DECL) {
17015c69f917Smrg  SCRN_INFO_PTR(arg);
17025c69f917Smrg  I740FreeRec(pScrn);
1703301ea0f4Smrg  if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
17045c69f917Smrg    vgaHWFreeHWRec(pScrn);
1705301ea0f4Smrg}
1706301ea0f4Smrg
1707301ea0f4Smrgstatic ModeStatus
17085c69f917SmrgI740ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) {
17095c69f917Smrg  SCRN_INFO_PTR(arg);
1710301ea0f4Smrg  if (mode->Flags & V_INTERLACE) {
1711301ea0f4Smrg    if (verbose) {
17125c69f917Smrg      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1713301ea0f4Smrg		 "Removing interlaced mode \"%s\"\n",
1714301ea0f4Smrg		 mode->name);
1715301ea0f4Smrg    }
1716301ea0f4Smrg    return MODE_BAD;
1717301ea0f4Smrg  }
1718301ea0f4Smrg  return MODE_OK;
1719301ea0f4Smrg}
1720301ea0f4Smrg
1721301ea0f4Smrgstatic Bool
1722301ea0f4SmrgI740SaveScreen(ScreenPtr pScreen, int mode)
1723301ea0f4Smrg{
1724301ea0f4Smrg#if 0
1725301ea0f4Smrg  Bool unblack = xf86IsUnblank(mode);
1726301ea0f4Smrg  if (unblack) outw(SRX, 0x0300);
1727301ea0f4Smrg  else outw(SRX, 0x0100);
1728301ea0f4Smrg#endif
1729301ea0f4Smrg  return vgaHWSaveScreen(pScreen, mode);
1730301ea0f4Smrg}
1731301ea0f4Smrg
1732301ea0f4Smrgstatic void
1733301ea0f4SmrgI740DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
1734301ea0f4Smrg			      int flags) {
1735301ea0f4Smrg  I740Ptr pI740;
1736301ea0f4Smrg  unsigned char SEQ01=0;
1737301ea0f4Smrg  int DPMSSyncSelect=0;
1738301ea0f4Smrg
1739301ea0f4Smrg  pI740 = I740PTR(pScrn);
1740301ea0f4Smrg  switch (PowerManagementMode) {
1741301ea0f4Smrg  case DPMSModeOn:
1742301ea0f4Smrg    /* Screen: On; HSync: On, VSync: On */
1743301ea0f4Smrg    SEQ01 = 0x00;
1744301ea0f4Smrg    DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
1745301ea0f4Smrg    break;
1746301ea0f4Smrg  case DPMSModeStandby:
1747301ea0f4Smrg    /* Screen: Off; HSync: Off, VSync: On */
1748301ea0f4Smrg    SEQ01 = 0x20;
1749301ea0f4Smrg    DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
1750301ea0f4Smrg    break;
1751301ea0f4Smrg  case DPMSModeSuspend:
1752301ea0f4Smrg    /* Screen: Off; HSync: On, VSync: Off */
1753301ea0f4Smrg    SEQ01 = 0x20;
1754301ea0f4Smrg    DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
1755301ea0f4Smrg    break;
1756301ea0f4Smrg  case DPMSModeOff:
1757301ea0f4Smrg    /* Screen: Off; HSync: Off, VSync: Off */
1758301ea0f4Smrg    SEQ01 = 0x20;
1759301ea0f4Smrg    DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
1760301ea0f4Smrg    break;
1761301ea0f4Smrg  }
1762301ea0f4Smrg
1763301ea0f4Smrg  /* Turn the screen on/off */
1764301ea0f4Smrg  SEQ01 |= pI740->readControl(pI740, SRX, 0x01) & ~0x20;
1765301ea0f4Smrg  pI740->writeControl(pI740, SRX, 0x01, SEQ01);
1766301ea0f4Smrg
1767301ea0f4Smrg  /* Set the DPMS mode */
1768301ea0f4Smrg  pI740->writeControl(pI740, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
1769301ea0f4Smrg}
1770