i740_driver.c revision ef6fb4a5
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>
41301ea0f4Smrg
42301ea0f4Smrg/*
43301ea0f4Smrg * This server does not support these XFree86 4.0 features yet
44301ea0f4Smrg * DDC1 & DDC2 (requires I2C)
45301ea0f4Smrg * shadowFb (if requested or acceleration is off)
46301ea0f4Smrg * Overlay planes
47301ea0f4Smrg * DGA
48301ea0f4Smrg */
49301ea0f4Smrg
50301ea0f4Smrg/*
51301ea0f4Smrg * These are X and server generic header files.
52301ea0f4Smrg */
53301ea0f4Smrg#include "xf86.h"
54301ea0f4Smrg#include "xf86_OSproc.h"
55ef6fb4a5Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
56301ea0f4Smrg#include "xf86Resources.h"
57301ea0f4Smrg#include "xf86RAC.h"
58ef6fb4a5Smrg#endif
59301ea0f4Smrg#include "xf86cmap.h"
60301ea0f4Smrg
61301ea0f4Smrg/* If the driver uses port I/O directly, it needs: */
62301ea0f4Smrg
63301ea0f4Smrg#include "compiler.h"
64301ea0f4Smrg
65301ea0f4Smrg/* Drivers using the mi implementation of backing store need: */
66301ea0f4Smrg
67301ea0f4Smrg#include "mibstore.h"
68301ea0f4Smrg
69301ea0f4Smrg/* All drivers using the vgahw module need this */
70301ea0f4Smrg/* This driver needs to be modified to not use vgaHW for multihead operation */
71301ea0f4Smrg#include "vgaHW.h"
72301ea0f4Smrg
73301ea0f4Smrg/* Drivers using the mi SW cursor need: */
74301ea0f4Smrg
75301ea0f4Smrg#include "mipointer.h"
76301ea0f4Smrg
77301ea0f4Smrg/* Drivers using the mi colourmap code need: */
78301ea0f4Smrg
79301ea0f4Smrg#include "micmap.h"
80301ea0f4Smrg
81301ea0f4Smrg#include "fb.h"
82301ea0f4Smrg
83301ea0f4Smrg/* The driver's own header file: */
84301ea0f4Smrg
85301ea0f4Smrg
86301ea0f4Smrg#include "regionstr.h"
87301ea0f4Smrg
88301ea0f4Smrg#include "xf86xv.h"
89301ea0f4Smrg#include <X11/extensions/Xv.h>
90301ea0f4Smrg
91301ea0f4Smrg#include "vbe.h"
92301ea0f4Smrg#include "i740_dga.h"
93301ea0f4Smrg#include "i740.h"
94301ea0f4Smrg
95301ea0f4Smrg
96301ea0f4Smrg/* Required Functions: */
97301ea0f4Smrgstatic const OptionInfoRec * I740AvailableOptions(int chipid, int busid);
98301ea0f4Smrg
99301ea0f4Smrg/* Print a driver identifying message. */
100301ea0f4Smrgstatic void I740Identify(int flags);
101301ea0f4Smrg
102301ea0f4Smrg/* Identify if there is any hardware present that I know how to drive. */
103301ea0f4Smrgstatic Bool I740Probe(DriverPtr drv, int flags);
104301ea0f4Smrg
105301ea0f4Smrg/* Process the config file and see if we have a valid configuration */
106301ea0f4Smrgstatic Bool I740PreInit(ScrnInfoPtr pScrn, int flags);
107301ea0f4Smrg
108301ea0f4Smrg/* Initialize a screen */
109301ea0f4Smrgstatic Bool I740ScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
110301ea0f4Smrg
111301ea0f4Smrg/* Enter from a virtual terminal */
112301ea0f4Smrgstatic Bool I740EnterVT(int scrnIndex, int flags);
113301ea0f4Smrg
114301ea0f4Smrg/* Leave to a virtual terminal */
115301ea0f4Smrgstatic void I740LeaveVT(int scrnIndex, int flags);
116301ea0f4Smrg
117301ea0f4Smrg/* Close down each screen we initialized */
118301ea0f4Smrgstatic Bool I740CloseScreen(int scrnIndex, ScreenPtr pScreen);
119301ea0f4Smrg
120301ea0f4Smrg/* Change screensaver state */
121301ea0f4Smrgstatic Bool I740SaveScreen(ScreenPtr pScreen, int mode);
122301ea0f4Smrg
123301ea0f4Smrg/* Cleanup server private data */
124301ea0f4Smrgstatic void I740FreeScreen(int scrnIndex, int flags);
125301ea0f4Smrg
126301ea0f4Smrg/* Check if a mode is valid on the hardware */
127301ea0f4Smrgstatic ModeStatus I740ValidMode(int scrnIndex, DisplayModePtr mode,
128301ea0f4Smrg				Bool verbose, int flags);
129301ea0f4Smrg
130301ea0f4Smrg/* Switch to various Display Power Management System levels */
131301ea0f4Smrgstatic void I740DisplayPowerManagementSet(ScrnInfoPtr pScrn,
132301ea0f4Smrg					int PowerManagermentMode, int flags);
133301ea0f4Smrg
134301ea0f4Smrgstatic void I740ProbeDDC(ScrnInfoPtr pScrn, int index);
135301ea0f4Smrg
136301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn);
137301ea0f4Smrgstatic Bool I740UnmapMem(ScrnInfoPtr pScrn);
138301ea0f4Smrg
139301ea0f4Smrg#define I740_VERSION 4000
140301ea0f4Smrg#define I740_NAME "I740"
141301ea0f4Smrg#define I740_DRIVER_NAME "i740"
1420cc67336Smrg#define I740_MAJOR_VERSION PACKAGE_VERSION_MAJOR
1430cc67336Smrg#define I740_MINOR_VERSION PACKAGE_VERSION_MINOR
1440cc67336Smrg#define I740_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
145301ea0f4Smrg
146301ea0f4Smrg_X_EXPORT DriverRec I740 = {
147301ea0f4Smrg  I740_VERSION,
148301ea0f4Smrg  I740_DRIVER_NAME,
149301ea0f4Smrg  I740Identify,
150301ea0f4Smrg  I740Probe,
151301ea0f4Smrg  I740AvailableOptions,
152301ea0f4Smrg  NULL,
153301ea0f4Smrg  0
154301ea0f4Smrg};
155301ea0f4Smrg
156301ea0f4Smrg/* Chipsets */
157301ea0f4Smrgstatic SymTabRec I740Chipsets[] = {
158301ea0f4Smrg  { PCI_CHIP_I740_AGP, "i740 (agp)"},
159301ea0f4Smrg  { PCI_CHIP_I740_PCI, "i740 (pci)"},
160301ea0f4Smrg  { -1, NULL }
161301ea0f4Smrg};
162301ea0f4Smrg
163301ea0f4Smrgstatic PciChipsets I740PciChipsets[] = {
164301ea0f4Smrg  { PCI_CHIP_I740_AGP, PCI_CHIP_I740_AGP, RES_SHARED_VGA },
165301ea0f4Smrg  { PCI_CHIP_I740_PCI, PCI_CHIP_I740_PCI, RES_SHARED_VGA },
166301ea0f4Smrg  { -1, -1, RES_UNDEFINED }
167301ea0f4Smrg};
168301ea0f4Smrg
169301ea0f4Smrgtypedef enum {
170301ea0f4Smrg  OPTION_NOACCEL,
171301ea0f4Smrg  OPTION_SW_CURSOR,
172301ea0f4Smrg  OPTION_SDRAM,
173301ea0f4Smrg  OPTION_SGRAM,
174301ea0f4Smrg  OPTION_SLOW_RAM,
175301ea0f4Smrg  OPTION_DAC_6BIT,
176301ea0f4Smrg  OPTION_USE_PIO,
177301ea0f4Smrg  OPTION_VGACOMPAT
178301ea0f4Smrg} I740Opts;
179301ea0f4Smrg
180301ea0f4Smrgstatic const OptionInfoRec I740Options[] = {
181301ea0f4Smrg  { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
182301ea0f4Smrg  { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
183301ea0f4Smrg  { OPTION_SDRAM, "SDRAM", OPTV_BOOLEAN, {0}, FALSE},
184301ea0f4Smrg  { OPTION_SGRAM, "SGRAM", OPTV_BOOLEAN, {0}, FALSE},
185301ea0f4Smrg  { OPTION_SLOW_RAM, "SlowRam", OPTV_BOOLEAN, {0}, FALSE},
186301ea0f4Smrg  { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE},
187301ea0f4Smrg  { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE},
188301ea0f4Smrg  { OPTION_VGACOMPAT, "VGACompat", OPTV_BOOLEAN, {0}, FALSE},
189301ea0f4Smrg  { -1, NULL, OPTV_NONE, {0}, FALSE}
190301ea0f4Smrg};
191301ea0f4Smrg
192301ea0f4Smrg#ifdef XFree86LOADER
193301ea0f4Smrg
194301ea0f4Smrgstatic MODULESETUPPROTO(i740Setup);
195301ea0f4Smrg
196301ea0f4Smrgstatic XF86ModuleVersionInfo i740VersRec =
197301ea0f4Smrg{
198301ea0f4Smrg  "i740",
199301ea0f4Smrg  MODULEVENDORSTRING,
200301ea0f4Smrg  MODINFOSTRING1,
201301ea0f4Smrg  MODINFOSTRING2,
202301ea0f4Smrg  XORG_VERSION_CURRENT,
203301ea0f4Smrg  I740_MAJOR_VERSION, I740_MINOR_VERSION, I740_PATCHLEVEL,
204301ea0f4Smrg  ABI_CLASS_VIDEODRV,
205301ea0f4Smrg  ABI_VIDEODRV_VERSION,
206301ea0f4Smrg  MOD_CLASS_VIDEODRV,
207301ea0f4Smrg  {0,0,0,0}
208301ea0f4Smrg};
209301ea0f4Smrg
210301ea0f4Smrg_X_EXPORT XF86ModuleData i740ModuleData = {&i740VersRec, i740Setup, 0};
211301ea0f4Smrg
212301ea0f4Smrgstatic pointer
213301ea0f4Smrgi740Setup(pointer module, pointer opts, int *errmaj, int *errmin)
214301ea0f4Smrg{
215301ea0f4Smrg    static Bool setupDone = FALSE;
216301ea0f4Smrg
217301ea0f4Smrg    /* This module should be loaded only once, but check to be sure. */
218301ea0f4Smrg
219301ea0f4Smrg    if (!setupDone) {
220301ea0f4Smrg	setupDone = TRUE;
221301ea0f4Smrg	xf86AddDriver(&I740, module, 0);
222301ea0f4Smrg
223301ea0f4Smrg	/*
224301ea0f4Smrg	 * Modules that this driver always requires may be loaded here
225301ea0f4Smrg	 * by calling LoadSubModule().
226301ea0f4Smrg	 */
227301ea0f4Smrg
228301ea0f4Smrg	/*
229301ea0f4Smrg	 * The return value must be non-NULL on success even though there
230301ea0f4Smrg	 * is no TearDownProc.
231301ea0f4Smrg	 */
232301ea0f4Smrg	return (pointer)1;
233301ea0f4Smrg    } else {
234301ea0f4Smrg	if (errmaj) *errmaj = LDR_ONCEONLY;
235301ea0f4Smrg	return NULL;
236301ea0f4Smrg    }
237301ea0f4Smrg}
238301ea0f4Smrg
239301ea0f4Smrg#endif
240301ea0f4Smrg
241301ea0f4Smrg/*
242301ea0f4Smrg * I740GetRec and I740FreeRec --
243301ea0f4Smrg *
244301ea0f4Smrg * Private data for the driver is stored in the screen structure.
245301ea0f4Smrg * These two functions create and destroy that private data.
246301ea0f4Smrg *
247301ea0f4Smrg */
248301ea0f4Smrgstatic Bool
249301ea0f4SmrgI740GetRec(ScrnInfoPtr pScrn) {
250301ea0f4Smrg  if (pScrn->driverPrivate) return TRUE;
251301ea0f4Smrg
252301ea0f4Smrg  pScrn->driverPrivate = xnfcalloc(sizeof(I740Rec), 1);
253301ea0f4Smrg  return TRUE;
254301ea0f4Smrg}
255301ea0f4Smrg
256301ea0f4Smrgstatic void
257301ea0f4SmrgI740FreeRec(ScrnInfoPtr pScrn) {
258301ea0f4Smrg  if (!pScrn) return;
259301ea0f4Smrg  if (!pScrn->driverPrivate) return;
260301ea0f4Smrg  xfree(pScrn->driverPrivate);
261301ea0f4Smrg  pScrn->driverPrivate=0;
262301ea0f4Smrg}
263301ea0f4Smrg
264301ea0f4Smrgstatic const OptionInfoRec *
265301ea0f4SmrgI740AvailableOptions(int chipid, int busid)
266301ea0f4Smrg{
267301ea0f4Smrg    return I740Options;
268301ea0f4Smrg}
269301ea0f4Smrg
270301ea0f4Smrg/*
271301ea0f4Smrg * I740Identify --
272301ea0f4Smrg *
273301ea0f4Smrg * Returns the string name for the driver based on the chipset. In this
274301ea0f4Smrg * case it will always be an I740, so we can return a static string.
275301ea0f4Smrg *
276301ea0f4Smrg */
277301ea0f4Smrgstatic void
278301ea0f4SmrgI740Identify(int flags) {
279301ea0f4Smrg  xf86PrintChipsets(I740_NAME, "Driver for Intel i740 chipset", I740Chipsets);
280301ea0f4Smrg}
281301ea0f4Smrg
282301ea0f4Smrg/*
283301ea0f4Smrg * I740Probe --
284301ea0f4Smrg *
285301ea0f4Smrg * Look through the PCI bus to find cards that are I740 boards.
286301ea0f4Smrg * Setup the dispatch table for the rest of the driver functions.
287301ea0f4Smrg *
288301ea0f4Smrg */
289301ea0f4Smrgstatic Bool
290301ea0f4SmrgI740Probe(DriverPtr drv, int flags) {
291301ea0f4Smrg  int i, numUsed, numDevSections, *usedChips;
292301ea0f4Smrg  GDevPtr *devSections;
293301ea0f4Smrg  Bool foundScreen = FALSE;
294301ea0f4Smrg
295301ea0f4Smrg  /*
296301ea0f4Smrg   Find the config file Device sections that match this
297301ea0f4Smrg   driver, and return if there are none.
298301ea0f4Smrg   */
299301ea0f4Smrg  if ((numDevSections = xf86MatchDevice(I740_DRIVER_NAME, &devSections))<=0) {
300301ea0f4Smrg    return FALSE;
301301ea0f4Smrg  }
302301ea0f4Smrg
3030cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
304301ea0f4Smrg  /*
305301ea0f4Smrg     Since these Probing is just checking the PCI data the server already
306301ea0f4Smrg     collected.
307301ea0f4Smrg  */
308301ea0f4Smrg  if (!xf86GetPciVideoInfo()) return FALSE;
3090cc67336Smrg#endif
310301ea0f4Smrg
311301ea0f4Smrg  /* Look for Intel based chips */
312301ea0f4Smrg  numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_INTEL,
313301ea0f4Smrg				  I740Chipsets, I740PciChipsets,
314301ea0f4Smrg				  devSections, numDevSections,
315301ea0f4Smrg				  drv, &usedChips);
316301ea0f4Smrg
317301ea0f4Smrg  if (numUsed > 0) {
318301ea0f4Smrg      if (flags & PROBE_DETECT)
319301ea0f4Smrg	  foundScreen = TRUE;
320301ea0f4Smrg      else for (i=0; i<numUsed; i++) {
321301ea0f4Smrg	  ScrnInfoPtr pScrn = NULL;
322301ea0f4Smrg	  /* Allocate new ScrnInfoRec and claim the slot */
323301ea0f4Smrg	  if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
324301ea0f4Smrg						 I740PciChipsets, 0, 0, 0, 0, 0))) {
325301ea0f4Smrg	      pScrn->driverVersion = I740_VERSION;
326301ea0f4Smrg	      pScrn->driverName = I740_DRIVER_NAME;
327301ea0f4Smrg	      pScrn->name = I740_NAME;
328301ea0f4Smrg	      pScrn->Probe = I740Probe;
329301ea0f4Smrg	      pScrn->PreInit = I740PreInit;
330301ea0f4Smrg	      pScrn->ScreenInit = I740ScreenInit;
331301ea0f4Smrg	      pScrn->SwitchMode = I740SwitchMode;
332301ea0f4Smrg	      pScrn->AdjustFrame = I740AdjustFrame;
333301ea0f4Smrg	      pScrn->EnterVT = I740EnterVT;
334301ea0f4Smrg	      pScrn->LeaveVT = I740LeaveVT;
335301ea0f4Smrg	      pScrn->FreeScreen = I740FreeScreen;
336301ea0f4Smrg	      pScrn->ValidMode = I740ValidMode;
337301ea0f4Smrg	      foundScreen = TRUE;
338301ea0f4Smrg
339301ea0f4Smrg	  }
340301ea0f4Smrg      }
341301ea0f4Smrg  }
342301ea0f4Smrg
343301ea0f4Smrg
344301ea0f4Smrg  /* Look for Real3D based chips */
345301ea0f4Smrg  numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_REAL3D,
346301ea0f4Smrg				  I740Chipsets, I740PciChipsets,
347301ea0f4Smrg				  devSections, numDevSections,
348301ea0f4Smrg				  drv, &usedChips);
349301ea0f4Smrg
350301ea0f4Smrg  if (numUsed > 0) {
351301ea0f4Smrg      if (flags & PROBE_DETECT)
352301ea0f4Smrg	  foundScreen = TRUE;
353301ea0f4Smrg      else for (i=0; i<numUsed; i++) {
354301ea0f4Smrg	  ScrnInfoPtr pScrn = NULL;
355301ea0f4Smrg	  if ((pScrn  = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
356301ea0f4Smrg						  I740PciChipsets, 0, 0, 0, 0, 0))) {
357301ea0f4Smrg	      pScrn->driverVersion = I740_VERSION;
358301ea0f4Smrg	      pScrn->driverName = I740_DRIVER_NAME;
359301ea0f4Smrg	      pScrn->name = I740_NAME;
360301ea0f4Smrg	      pScrn->Probe = I740Probe;
361301ea0f4Smrg	      pScrn->PreInit = I740PreInit;
362301ea0f4Smrg	      pScrn->ScreenInit = I740ScreenInit;
363301ea0f4Smrg	      pScrn->SwitchMode = I740SwitchMode;
364301ea0f4Smrg	      pScrn->AdjustFrame = I740AdjustFrame;
365301ea0f4Smrg	      pScrn->EnterVT = I740EnterVT;
366301ea0f4Smrg	      pScrn->LeaveVT = I740LeaveVT;
367301ea0f4Smrg	      pScrn->FreeScreen = I740FreeScreen;
368301ea0f4Smrg	      pScrn->ValidMode = I740ValidMode;
369301ea0f4Smrg	      foundScreen = TRUE;
370301ea0f4Smrg	  }
371301ea0f4Smrg      }
372301ea0f4Smrg  }
373301ea0f4Smrg
374301ea0f4Smrg  xfree(devSections);
375301ea0f4Smrg  xfree(usedChips);
376301ea0f4Smrg
377301ea0f4Smrg  return foundScreen;
378301ea0f4Smrg}
379301ea0f4Smrg
3800cc67336Smrg/* Ugh.  Can we not do this? */
381301ea0f4Smrgstatic void
382301ea0f4SmrgI740ProbeDDC(ScrnInfoPtr pScrn, int index)
383301ea0f4Smrg{
384301ea0f4Smrg    vbeInfoPtr pVbe;
385301ea0f4Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
386301ea0f4Smrg	pVbe = VBEInit(NULL,index);
387301ea0f4Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
388301ea0f4Smrg	vbeFree(pVbe);
389301ea0f4Smrg    }
390301ea0f4Smrg}
391301ea0f4Smrg
392301ea0f4Smrg/*
393301ea0f4Smrg * I740PreInit --
394301ea0f4Smrg *
395301ea0f4Smrg * Do initial setup of the board before we know what resolution we will
396301ea0f4Smrg * be running at.
397301ea0f4Smrg *
398301ea0f4Smrg */
399301ea0f4Smrgstatic Bool
400301ea0f4SmrgI740PreInit(ScrnInfoPtr pScrn, int flags) {
401301ea0f4Smrg  I740Ptr pI740;
402301ea0f4Smrg  ClockRangePtr clockRanges;
403301ea0f4Smrg  int i;
404301ea0f4Smrg  MessageType from;
405301ea0f4Smrg  int temp;
406301ea0f4Smrg  int flags24;
407301ea0f4Smrg  rgb defaultWeight = {0, 0, 0};
408301ea0f4Smrg
409301ea0f4Smrg  if (pScrn->numEntities != 1) return FALSE;
410301ea0f4Smrg
411301ea0f4Smrg  /* Allocate driverPrivate */
412301ea0f4Smrg  if (!I740GetRec(pScrn)) {
413301ea0f4Smrg    return FALSE;
414301ea0f4Smrg  }
415301ea0f4Smrg
416301ea0f4Smrg  pI740 = I740PTR(pScrn);
417301ea0f4Smrg
418301ea0f4Smrg  pI740->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
419301ea0f4Smrg  if (pI740->pEnt->location.type != BUS_PCI) return FALSE;
420301ea0f4Smrg
421301ea0f4Smrg  /*I740ProbeDDC(pScrn, pI740->pEnt->index);*/
422301ea0f4Smrg  if (flags & PROBE_DETECT) {
423301ea0f4Smrg	I740ProbeDDC(pScrn, pI740->pEnt->index);
424301ea0f4Smrg	return TRUE;
425301ea0f4Smrg  }
426301ea0f4Smrg
427301ea0f4Smrg  /* The vgahw module should be loaded here when needed */
428301ea0f4Smrg  if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE;
429301ea0f4Smrg
430301ea0f4Smrg  /* Allocate a vgaHWRec */
431301ea0f4Smrg  if (!vgaHWGetHWRec(pScrn)) return FALSE;
432301ea0f4Smrg
433301ea0f4Smrg  pI740->PciInfo = xf86GetPciInfoForEntity(pI740->pEnt->index);
4340cc67336Smrg#ifndef XSERVER_LIBPCIACCESS
435301ea0f4Smrg  pI740->PciTag = pciTag(pI740->PciInfo->bus, pI740->PciInfo->device,
436301ea0f4Smrg			 pI740->PciInfo->func);
437301ea0f4Smrg
438301ea0f4Smrg  if (xf86RegisterResources(pI740->pEnt->index, 0, ResNone))
439301ea0f4Smrg      return FALSE;
440301ea0f4Smrg  if (pI740->usePIO)
441301ea0f4Smrg    pScrn->racIoFlags = RAC_FB | RAC_COLORMAP;
442301ea0f4Smrg  else
443301ea0f4Smrg    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP;
444ef6fb4a5Smrg#endif
445301ea0f4Smrg  /* Set pScrn->monitor */
446301ea0f4Smrg  pScrn->monitor = pScrn->confScreen->monitor;
447301ea0f4Smrg
448301ea0f4Smrg
449301ea0f4Smrg  flags24=Support24bppFb | Support32bppFb | SupportConvert32to24;
450301ea0f4Smrg  if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
451301ea0f4Smrg    return FALSE;
452301ea0f4Smrg  } else {
453301ea0f4Smrg    switch (pScrn->depth) {
454301ea0f4Smrg    case 8:
455301ea0f4Smrg    case 15:
456301ea0f4Smrg    case 16:
457301ea0f4Smrg    case 24:
458301ea0f4Smrg      break;
459301ea0f4Smrg    default:
460301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
461301ea0f4Smrg		 "Given depth (%d) is not supported by i740 driver\n",
462301ea0f4Smrg		 pScrn->depth);
463301ea0f4Smrg      return FALSE;
464301ea0f4Smrg    }
465301ea0f4Smrg  }
466301ea0f4Smrg  /*xf86PrintDepthBpp(pScrn);*/
467301ea0f4Smrg
468301ea0f4Smrg  if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
469301ea0f4Smrg    return FALSE;
470301ea0f4Smrg
471301ea0f4Smrg  if (!xf86SetDefaultVisual(pScrn, -1)) {
472301ea0f4Smrg    return FALSE;
473301ea0f4Smrg  } else {
474301ea0f4Smrg    /* We don't currently support DirectColor at > 8bpp */
475301ea0f4Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
476301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
477301ea0f4Smrg		 " (%s) is not supported at depth %d\n",
478301ea0f4Smrg		 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
479301ea0f4Smrg      return FALSE;
480301ea0f4Smrg    }
481301ea0f4Smrg  }
482301ea0f4Smrg
483301ea0f4Smrg  /* We use a programamble clock */
484301ea0f4Smrg  pScrn->progClock = TRUE;
485301ea0f4Smrg
486301ea0f4Smrg  pI740->cpp = pScrn->bitsPerPixel/8;
487301ea0f4Smrg
488301ea0f4Smrg  /* Process the options */
489301ea0f4Smrg  xf86CollectOptions(pScrn, NULL);
490301ea0f4Smrg  if (!(pI740->Options = xalloc(sizeof(I740Options))))
491301ea0f4Smrg    return FALSE;
492301ea0f4Smrg  memcpy(pI740->Options, I740Options, sizeof(I740Options));
493301ea0f4Smrg  xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI740->Options);
494301ea0f4Smrg
495301ea0f4Smrg  /* 6-BIT dac isn't reasonable for modes with > 8bpp */
496301ea0f4Smrg  if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE) &&
497301ea0f4Smrg      pScrn->bitsPerPixel>8) {
498301ea0f4Smrg    OptionInfoPtr ptr;
499301ea0f4Smrg    ptr=xf86TokenToOptinfo(pI740->Options, OPTION_DAC_6BIT);
500301ea0f4Smrg    ptr->found=FALSE;
501301ea0f4Smrg  }
502301ea0f4Smrg
503301ea0f4Smrg  if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE))
504301ea0f4Smrg    pScrn->rgbBits=8;
505301ea0f4Smrg  else
506301ea0f4Smrg    pScrn->rgbBits=6;
507301ea0f4Smrg
508301ea0f4Smrg  /* We have to use PIO to probe, because we haven't mappend yet */
509301ea0f4Smrg  I740SetPIOAccess(pI740);
510301ea0f4Smrg
511301ea0f4Smrg  /*
512301ea0f4Smrg   * Set the Chipset and ChipRev, allowing config file entries to
513301ea0f4Smrg   * override.
514301ea0f4Smrg   */
515301ea0f4Smrg  if (pI740->pEnt->device->chipset && *pI740->pEnt->device->chipset) {
516301ea0f4Smrg    pScrn->chipset = pI740->pEnt->device->chipset;
517301ea0f4Smrg    from = X_CONFIG;
518301ea0f4Smrg  } else if (pI740->pEnt->device->chipID >= 0) {
519301ea0f4Smrg    pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->pEnt->device->chipID);
520301ea0f4Smrg    from = X_CONFIG;
521301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
522301ea0f4Smrg	       pI740->pEnt->device->chipID);
523301ea0f4Smrg  } else {
524301ea0f4Smrg    from = X_PROBED;
5250cc67336Smrg    pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, PCI_DEV_DEVICE_ID(pI740->PciInfo));
526301ea0f4Smrg  }
527301ea0f4Smrg  if (pI740->pEnt->device->chipRev >= 0) {
528301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
529301ea0f4Smrg	       pI740->pEnt->device->chipRev);
530301ea0f4Smrg  }
531301ea0f4Smrg
532301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset!=NULL)?pScrn->chipset:"Unknown i740");
533301ea0f4Smrg
534301ea0f4Smrg  if (pI740->pEnt->device->MemBase != 0) {
535301ea0f4Smrg    pI740->LinearAddr = pI740->pEnt->device->MemBase;
536301ea0f4Smrg    from = X_CONFIG;
537301ea0f4Smrg  } else {
5380cc67336Smrg    if (PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM) != 0) {
5390cc67336Smrg      pI740->LinearAddr = PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM)&0xFF000000;
540301ea0f4Smrg      from = X_PROBED;
541301ea0f4Smrg    } else {
542301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
543301ea0f4Smrg		 "No valid FB address in PCI config space\n");
544301ea0f4Smrg      I740FreeRec(pScrn);
545301ea0f4Smrg      return FALSE;
546301ea0f4Smrg    }
547301ea0f4Smrg  }
548301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
549301ea0f4Smrg	     pI740->LinearAddr);
550301ea0f4Smrg
551301ea0f4Smrg  if (pI740->pEnt->device->IOBase != 0) {
552301ea0f4Smrg    pI740->MMIOAddr = pI740->pEnt->device->IOBase;
553301ea0f4Smrg    from = X_CONFIG;
554301ea0f4Smrg  } else {
5550cc67336Smrg    if (PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)) {
5560cc67336Smrg      pI740->MMIOAddr = PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)&0xFFF80000;
557301ea0f4Smrg      from = X_PROBED;
558301ea0f4Smrg    } else {
559301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
560301ea0f4Smrg		 "No valid MMIO address in PCI config space\n");
561301ea0f4Smrg      I740FreeRec(pScrn);
562301ea0f4Smrg      return FALSE;
563301ea0f4Smrg    }
564301ea0f4Smrg  }
565301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
566301ea0f4Smrg	     pI740->MMIOAddr);
567301ea0f4Smrg
568301ea0f4Smrg  /* Calculate memory */
569301ea0f4Smrg  if (pI740->pEnt->device->videoRam) {
570301ea0f4Smrg    pScrn->videoRam = pI740->pEnt->device->videoRam;
571301ea0f4Smrg    from = X_CONFIG;
572301ea0f4Smrg  } else {
573301ea0f4Smrg    if ((pI740->readControl(pI740, XRX, DRAM_ROW_TYPE)&DRAM_ROW_1)==DRAM_ROW_1_SDRAM)
574301ea0f4Smrg      pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_1);
575301ea0f4Smrg    else
576301ea0f4Smrg      pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_0);
577301ea0f4Smrg    pScrn->videoRam = (pScrn->videoRam&0x0F)*1024;
578301ea0f4Smrg    from = X_PROBED;
579301ea0f4Smrg  }
580301ea0f4Smrg
581301ea0f4Smrg  temp=pI740->readControl(pI740, XRX, DRAM_ROW_CNTL_LO);
582301ea0f4Smrg  pI740->HasSGRAM = !((temp&DRAM_RAS_TIMING)||(temp&DRAM_RAS_PRECHARGE));
583301ea0f4Smrg  if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) {
584301ea0f4Smrg    if (xf86IsOptionSet(pI740->Options, OPTION_SGRAM)) {
585301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
586301ea0f4Smrg		 "It is nonsensical to set both SDRAM and SGRAM options\n");
587301ea0f4Smrg      return FALSE;
588301ea0f4Smrg    }
589301ea0f4Smrg    if (xf86ReturnOptValBool(pI740->Options, OPTION_SDRAM, FALSE)) {
590301ea0f4Smrg      pI740->HasSGRAM = FALSE;
591301ea0f4Smrg    } else {
592301ea0f4Smrg      pI740->HasSGRAM = TRUE;
593301ea0f4Smrg    }
594301ea0f4Smrg  } else {
595301ea0f4Smrg    if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) {
596301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
597301ea0f4Smrg		 "It is nonsensical to set both SDRAM and SGRAM options\n");
598301ea0f4Smrg      return FALSE;
599301ea0f4Smrg    }
600301ea0f4Smrg    if (xf86ReturnOptValBool(pI740->Options, OPTION_SGRAM, FALSE)) {
601301ea0f4Smrg      pI740->HasSGRAM = TRUE;
602301ea0f4Smrg    } else {
603301ea0f4Smrg      pI740->HasSGRAM = FALSE;
604301ea0f4Smrg    }
605301ea0f4Smrg  }
606301ea0f4Smrg
607301ea0f4Smrg  xf86DrvMsg(pScrn->scrnIndex, from, "Steve was here! VideoRAM: %d kByte %s\n",
608301ea0f4Smrg	     pScrn->videoRam, (pI740->HasSGRAM)?"SGRAM":"SDRAM");
609301ea0f4Smrg  pI740->FbMapSize = pScrn->videoRam*1024;
610301ea0f4Smrg
611301ea0f4Smrg  /*
612301ea0f4Smrg   * If the driver can do gamma correction, it should call xf86SetGamma()
613301ea0f4Smrg   * here.
614301ea0f4Smrg   */
615301ea0f4Smrg
616301ea0f4Smrg  {
617301ea0f4Smrg    Gamma zeros = {0.0, 0.0, 0.0};
618301ea0f4Smrg
619301ea0f4Smrg    if (!xf86SetGamma(pScrn, zeros)) {
620301ea0f4Smrg      return FALSE;
621301ea0f4Smrg    }
622301ea0f4Smrg  }
623301ea0f4Smrg
624301ea0f4Smrg  pI740->MaxClock = 0;
625301ea0f4Smrg  if (pI740->pEnt->device->dacSpeeds[0]) {
626301ea0f4Smrg    switch (pScrn->bitsPerPixel) {
627301ea0f4Smrg    case 8:
628301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP8];
629301ea0f4Smrg      break;
630301ea0f4Smrg    case 16:
631301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP16];
632301ea0f4Smrg      break;
633301ea0f4Smrg    case 24:
634301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP24];
635301ea0f4Smrg      break;
636301ea0f4Smrg    case 32:
637301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP32];
638301ea0f4Smrg      break;
639301ea0f4Smrg    }
640301ea0f4Smrg    if (!pI740->MaxClock)
641301ea0f4Smrg      pI740->MaxClock = pI740->pEnt->device->dacSpeeds[0];
642301ea0f4Smrg    from = X_CONFIG;
643301ea0f4Smrg  } else {
644301ea0f4Smrg    switch (pScrn->bitsPerPixel) {
645301ea0f4Smrg    case 8:
646301ea0f4Smrg      pI740->MaxClock = 203000;
647301ea0f4Smrg      break;
648301ea0f4Smrg    case 16:
649301ea0f4Smrg      pI740->MaxClock = 163000;
650301ea0f4Smrg      break;
651301ea0f4Smrg    case 24:
652301ea0f4Smrg      if (pI740->HasSGRAM)
653301ea0f4Smrg	pI740->MaxClock = 136000;
654301ea0f4Smrg      else
655301ea0f4Smrg	pI740->MaxClock = 128000;
656301ea0f4Smrg      break;
657301ea0f4Smrg    case 32:
658301ea0f4Smrg      pI740->MaxClock = 86000;
659301ea0f4Smrg    }
660301ea0f4Smrg  }
661301ea0f4Smrg  clockRanges = xnfcalloc(sizeof(ClockRange), 1);
662301ea0f4Smrg  clockRanges->next=NULL;
663301ea0f4Smrg  clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */
664301ea0f4Smrg  clockRanges->maxClock=pI740->MaxClock;
665301ea0f4Smrg  clockRanges->clockIndex = -1;
666301ea0f4Smrg  clockRanges->interlaceAllowed = FALSE; /*PL*/
667301ea0f4Smrg  clockRanges->doubleScanAllowed = TRUE; /*PL*/
668301ea0f4Smrg
6690cc67336Smrg  { /*PL*/
6700cc67336Smrg
6710cc67336Smrg   if (xf86LoadSubModule(pScrn, "ddc")) {
6720cc67336Smrg     if (xf86LoadSubModule(pScrn, "i2c") ) {
6730cc67336Smrg       if (I740MapMem(pScrn)) {
6740cc67336Smrg	   if (I740_I2CInit(pScrn))
6750cc67336Smrg	     {
6760cc67336Smrg	       xf86MonPtr MonInfo;
6770cc67336Smrg	       if ((MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex,pI740->rc_i2c))) {
6780cc67336Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n",
6790cc67336Smrg			    MonInfo);
6800cc67336Smrg		 xf86PrintEDID( MonInfo );
6810cc67336Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor "
6820cc67336Smrg			    "info\n\n");
6830cc67336Smrg		 xf86SetDDCproperties(pScrn,MonInfo);
6840cc67336Smrg	       }
6850cc67336Smrg	     }
6860cc67336Smrg	   else
6870cc67336Smrg	     xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n");
6880cc67336Smrg
6890cc67336Smrg	   I740UnmapMem(pScrn);
6900cc67336Smrg	 }
6910cc67336Smrg     }
6920cc67336Smrg   }
6930cc67336Smrg  }
6940cc67336Smrg
695301ea0f4Smrg  i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
696301ea0f4Smrg			pScrn->display->modes, clockRanges,
697301ea0f4Smrg			0, 320, 1600,
698301ea0f4Smrg			8, 200, 1200,
699301ea0f4Smrg			pScrn->display->virtualX, pScrn->display->virtualY,
700301ea0f4Smrg			pI740->FbMapSize, LOOKUP_BEST_REFRESH);
701301ea0f4Smrg
702301ea0f4Smrg  if (i==-1) {
703301ea0f4Smrg    I740FreeRec(pScrn);
704301ea0f4Smrg    return FALSE;
705301ea0f4Smrg  }
706301ea0f4Smrg
707301ea0f4Smrg  xf86PruneDriverModes(pScrn);
708301ea0f4Smrg
709301ea0f4Smrg  if (!i || !pScrn->modes) {
710301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
711301ea0f4Smrg    I740FreeRec(pScrn);
712301ea0f4Smrg    return FALSE;
713301ea0f4Smrg  }
714301ea0f4Smrg
715301ea0f4Smrg  xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
716301ea0f4Smrg
717301ea0f4Smrg  pScrn->currentMode = pScrn->modes;
718301ea0f4Smrg
719301ea0f4Smrg  xf86PrintModes(pScrn);
720301ea0f4Smrg
721301ea0f4Smrg  xf86SetDpi(pScrn, 0, 0);
722301ea0f4Smrg
723301ea0f4Smrg  if (!xf86LoadSubModule(pScrn, "fb")) {
724301ea0f4Smrg    I740FreeRec(pScrn);
725301ea0f4Smrg    return FALSE;
726301ea0f4Smrg  }
727301ea0f4Smrg
728301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE)) {
729301ea0f4Smrg    if (!xf86LoadSubModule(pScrn, "xaa")) {
730301ea0f4Smrg      I740FreeRec(pScrn);
731301ea0f4Smrg      return FALSE;
732301ea0f4Smrg    }
733301ea0f4Smrg  }
734301ea0f4Smrg
735301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) {
736301ea0f4Smrg    if (!xf86LoadSubModule(pScrn, "ramdac")) {
737301ea0f4Smrg      I740FreeRec(pScrn);
738301ea0f4Smrg      return FALSE;
739301ea0f4Smrg    }
740301ea0f4Smrg  }
741301ea0f4Smrg
742301ea0f4Smrg  /*  We wont be using the VGA access after the probe */
743301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_USE_PIO, FALSE)) {
744ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS
745301ea0f4Smrg    resRange vgaio[] = { {ResShrIoBlock,0x3B0,0x3BB},
746301ea0f4Smrg			 {ResShrIoBlock,0x3C0,0x3DF},
747301ea0f4Smrg			 _END };
748301ea0f4Smrg    resRange vgamem[] = {{ResShrMemBlock,0xA0000,0xAFFFF},
749301ea0f4Smrg			 {ResShrMemBlock,0xB8000,0xBFFFF},
750301ea0f4Smrg			 {ResShrMemBlock,0xB0000,0xB7FFF},
751301ea0f4Smrg			 _END };
752ef6fb4a5Smrg#endif
753301ea0f4Smrg    pI740->usePIO=FALSE;
754301ea0f4Smrg    I740SetMMIOAccess(pI740);
755ef6fb4a5Smrg#ifndef XSERVER_LIBPCIACCESS
756301ea0f4Smrg    xf86SetOperatingState(vgaio, pI740->pEnt->index, ResUnusedOpr);
757301ea0f4Smrg    xf86SetOperatingState(vgamem, pI740->pEnt->index, ResDisableOpr);
758ef6fb4a5Smrg#endif
759301ea0f4Smrg  } else {
760301ea0f4Smrg    pI740->usePIO=TRUE;
761301ea0f4Smrg  }
762301ea0f4Smrg
763301ea0f4Smrg  if(xf86IsOptionSet(pI740->Options, OPTION_VGACOMPAT))
764301ea0f4Smrg    pI740->usevgacompat=TRUE;
765301ea0f4Smrg  else
766301ea0f4Smrg    pI740->usevgacompat=FALSE;
767301ea0f4Smrg
768301ea0f4Smrg
769301ea0f4Smrg
770301ea0f4Smrg  { /* Overlay */
771301ea0f4Smrg    pI740->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) |
772301ea0f4Smrg      (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
773301ea0f4Smrg
774301ea0f4Smrg    pI740->colorKey &= ((1 << pScrn->depth) - 1);
775301ea0f4Smrg
776301ea0f4Smrg    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video overlay key set to 0x%x\n", pI740->colorKey);
777301ea0f4Smrg  }
778301ea0f4Smrg
779301ea0f4Smrg
780301ea0f4Smrg  return TRUE;
781301ea0f4Smrg}
782301ea0f4Smrg
783301ea0f4Smrgstatic Bool I740MapMem(ScrnInfoPtr pScrn)
784301ea0f4Smrg{
785301ea0f4Smrg  int mmioFlags;
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
1472301ea0f4SmrgI740ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) {
1473301ea0f4Smrg  ScrnInfoPtr pScrn;
1474301ea0f4Smrg  vgaHWPtr hwp;
1475301ea0f4Smrg  I740Ptr pI740;
1476301ea0f4Smrg  VisualPtr visual;
1477301ea0f4Smrg
1478301ea0f4Smrg  pScrn = xf86Screens[pScreen->myNum];
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);
1495301ea0f4Smrg  I740AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
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:
1516301ea0f4Smrg    xf86DrvMsg(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
1538301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE)) {
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  miInitializeBackingStore(pScreen);
1560301ea0f4Smrg  xf86SetBackingStore(pScreen);
1561301ea0f4Smrg  xf86SetSilkenMouse(pScreen);
1562301ea0f4Smrg
1563301ea0f4Smrg  miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1564301ea0f4Smrg
1565301ea0f4Smrg  if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) {
1566301ea0f4Smrg    if (!I740CursorInit(pScreen)) {
1567301ea0f4Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1568301ea0f4Smrg		 "Hardware cursor initialization failed\n");
1569301ea0f4Smrg    }
1570301ea0f4Smrg  }
1571301ea0f4Smrg
1572301ea0f4Smrg  if (!miCreateDefColormap(pScreen)) return FALSE;
1573301ea0f4Smrg
1574301ea0f4Smrg  if (pScrn->bitsPerPixel==16)
1575301ea0f4Smrg    {
1576301ea0f4Smrg      if (pScrn->weight.green == 5)
1577301ea0f4Smrg	{
1578301ea0f4Smrg	  if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette15, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
1579301ea0f4Smrg	    return FALSE;
1580301ea0f4Smrg	}
1581301ea0f4Smrg      else
1582301ea0f4Smrg	{
1583301ea0f4Smrg	  if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette16, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
1584301ea0f4Smrg	    return FALSE;
1585301ea0f4Smrg	}
1586301ea0f4Smrg    }
1587301ea0f4Smrg  else
1588301ea0f4Smrg    {
1589301ea0f4Smrg      if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette24, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH))
1590301ea0f4Smrg	return FALSE;
1591301ea0f4Smrg    }
1592301ea0f4Smrg
1593301ea0f4Smrg  xf86DPMSInit(pScreen, I740DisplayPowerManagementSet, 0);
1594301ea0f4Smrg
1595301ea0f4Smrg  pScreen->SaveScreen = I740SaveScreen;
1596301ea0f4Smrg  pI740->CloseScreen = pScreen->CloseScreen;
1597301ea0f4Smrg  pScreen->CloseScreen = I740CloseScreen;
1598301ea0f4Smrg
1599301ea0f4Smrg  if (serverGeneration == 1)
1600301ea0f4Smrg    xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1601301ea0f4Smrg
1602301ea0f4Smrg  /* Overlay */
1603301ea0f4Smrg  I740InitVideo(pScreen); pI740->OverlayStart = pI740->CursorStart + 1024;
1604301ea0f4Smrg
1605301ea0f4Smrg  return TRUE;
1606301ea0f4Smrg}
1607301ea0f4Smrg
1608301ea0f4SmrgBool
1609301ea0f4SmrgI740SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) {
1610301ea0f4Smrg  ScrnInfoPtr pScrn;
1611301ea0f4Smrg
1612301ea0f4Smrg  pScrn=xf86Screens[scrnIndex];
1613301ea0f4Smrg  return I740ModeInit(pScrn, mode);
1614301ea0f4Smrg}
1615301ea0f4Smrg
1616301ea0f4Smrgvoid
1617301ea0f4SmrgI740AdjustFrame(int scrnIndex, int x, int y, int flags) {
1618301ea0f4Smrg  ScrnInfoPtr pScrn;
1619301ea0f4Smrg  int Base;
1620301ea0f4Smrg  vgaHWPtr hwp;
1621301ea0f4Smrg
1622301ea0f4Smrg  pScrn = xf86Screens[scrnIndex];
1623301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1624301ea0f4Smrg
1625301ea0f4Smrg  Base = (y * pScrn->displayWidth + x) >> 2;
1626301ea0f4Smrg  switch (pScrn->bitsPerPixel) {
1627301ea0f4Smrg  case  8:
1628301ea0f4Smrg    break;
1629301ea0f4Smrg  case 16:
1630301ea0f4Smrg    Base *= 2;
1631301ea0f4Smrg    break;
1632301ea0f4Smrg  case 24:
1633301ea0f4Smrg    /*
1634301ea0f4Smrg     * The last bit does not seem to have any effect on the start
1635301ea0f4Smrg     * address register in 24bpp mode, so...
1636301ea0f4Smrg     */
1637301ea0f4Smrg    Base &= 0xFFFFFFFE; /* ...ignore the last bit. */
1638301ea0f4Smrg    Base *= 3;
1639301ea0f4Smrg    break;
1640301ea0f4Smrg  case 32:
1641301ea0f4Smrg    Base *= 4;
1642301ea0f4Smrg    break;
1643301ea0f4Smrg  }
1644301ea0f4Smrg
1645301ea0f4Smrg  hwp->writeCrtc(hwp, START_ADDR_LO, Base&0xFF);
1646301ea0f4Smrg  hwp->writeCrtc(hwp, START_ADDR_HI, (Base&0xFF00)>>8);
1647301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base&0x3FC00000)>>22);
1648301ea0f4Smrg  hwp->writeCrtc(hwp, EXT_START_ADDR,
1649301ea0f4Smrg		 ((Base&0x00eF0000)>>16|EXT_START_ADDR_ENABLE));
1650301ea0f4Smrg}
1651301ea0f4Smrg
1652301ea0f4Smrgstatic Bool
1653301ea0f4SmrgI740EnterVT(int scrnIndex, int flags) {
1654301ea0f4Smrg  ScrnInfoPtr pScrn;
1655301ea0f4Smrg
1656301ea0f4Smrg  pScrn = xf86Screens[scrnIndex];
1657301ea0f4Smrg  if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE;
1658301ea0f4Smrg  I740AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1659301ea0f4Smrg  return TRUE;
1660301ea0f4Smrg}
1661301ea0f4Smrg
1662301ea0f4Smrgstatic void
1663301ea0f4SmrgI740LeaveVT(int scrnIndex, int flags) {
1664301ea0f4Smrg  ScrnInfoPtr pScrn;
1665301ea0f4Smrg  vgaHWPtr hwp;
1666301ea0f4Smrg
1667301ea0f4Smrg  pScrn = xf86Screens[scrnIndex];
1668301ea0f4Smrg  hwp=VGAHWPTR(pScrn);
1669301ea0f4Smrg  I740Restore(pScrn);
1670301ea0f4Smrg  vgaHWLock(hwp);
1671301ea0f4Smrg}
1672301ea0f4Smrg
1673301ea0f4Smrgstatic Bool
1674301ea0f4SmrgI740CloseScreen(int scrnIndex, ScreenPtr pScreen)
1675301ea0f4Smrg{
1676301ea0f4Smrg  ScrnInfoPtr pScrn;
1677301ea0f4Smrg  vgaHWPtr hwp;
1678301ea0f4Smrg  I740Ptr pI740;
1679301ea0f4Smrg
1680301ea0f4Smrg  pScrn = xf86Screens[scrnIndex];
1681301ea0f4Smrg  hwp = VGAHWPTR(pScrn);
1682301ea0f4Smrg  pI740 = I740PTR(pScrn);
1683301ea0f4Smrg
1684301ea0f4Smrg  if (pScrn->vtSema) {
1685301ea0f4Smrg      I740Restore(pScrn);
1686301ea0f4Smrg      vgaHWLock(hwp);
1687301ea0f4Smrg  }
1688301ea0f4Smrg
1689301ea0f4Smrg  I740UnmapMem(pScrn);
1690301ea0f4Smrg  vgaHWUnmapMem(pScrn);
1691301ea0f4Smrg  if (pI740->AccelInfoRec)
1692301ea0f4Smrg    XAADestroyInfoRec(pI740->AccelInfoRec);
1693301ea0f4Smrg  pI740->AccelInfoRec=0;
1694301ea0f4Smrg  if (pI740->CursorInfoRec)
1695301ea0f4Smrg    xf86DestroyCursorInfoRec(pI740->CursorInfoRec);
1696301ea0f4Smrg  pI740->CursorInfoRec=0;
1697301ea0f4Smrg  pScrn->vtSema=FALSE;
1698301ea0f4Smrg
1699301ea0f4Smrg  pScreen->CloseScreen = pI740->CloseScreen;
1700301ea0f4Smrg  return (*pScreen->CloseScreen)(scrnIndex, pScreen);
1701301ea0f4Smrg}
1702301ea0f4Smrg
1703301ea0f4Smrgstatic void
1704301ea0f4SmrgI740FreeScreen(int scrnIndex, int flags) {
1705301ea0f4Smrg  I740FreeRec(xf86Screens[scrnIndex]);
1706301ea0f4Smrg  if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
1707301ea0f4Smrg    vgaHWFreeHWRec(xf86Screens[scrnIndex]);
1708301ea0f4Smrg}
1709301ea0f4Smrg
1710301ea0f4Smrgstatic ModeStatus
1711301ea0f4SmrgI740ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) {
1712301ea0f4Smrg  if (mode->Flags & V_INTERLACE) {
1713301ea0f4Smrg    if (verbose) {
1714301ea0f4Smrg      xf86DrvMsg(scrnIndex, X_PROBED,
1715301ea0f4Smrg		 "Removing interlaced mode \"%s\"\n",
1716301ea0f4Smrg		 mode->name);
1717301ea0f4Smrg    }
1718301ea0f4Smrg    return MODE_BAD;
1719301ea0f4Smrg  }
1720301ea0f4Smrg  return MODE_OK;
1721301ea0f4Smrg}
1722301ea0f4Smrg
1723301ea0f4Smrgstatic Bool
1724301ea0f4SmrgI740SaveScreen(ScreenPtr pScreen, int mode)
1725301ea0f4Smrg{
1726301ea0f4Smrg#if 0
1727301ea0f4Smrg  Bool unblack = xf86IsUnblank(mode);
1728301ea0f4Smrg  if (unblack) outw(SRX, 0x0300);
1729301ea0f4Smrg  else outw(SRX, 0x0100);
1730301ea0f4Smrg#endif
1731301ea0f4Smrg  return vgaHWSaveScreen(pScreen, mode);
1732301ea0f4Smrg}
1733301ea0f4Smrg
1734301ea0f4Smrgstatic void
1735301ea0f4SmrgI740DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
1736301ea0f4Smrg			      int flags) {
1737301ea0f4Smrg  I740Ptr pI740;
1738301ea0f4Smrg  unsigned char SEQ01=0;
1739301ea0f4Smrg  int DPMSSyncSelect=0;
1740301ea0f4Smrg
1741301ea0f4Smrg  pI740 = I740PTR(pScrn);
1742301ea0f4Smrg  switch (PowerManagementMode) {
1743301ea0f4Smrg  case DPMSModeOn:
1744301ea0f4Smrg    /* Screen: On; HSync: On, VSync: On */
1745301ea0f4Smrg    SEQ01 = 0x00;
1746301ea0f4Smrg    DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
1747301ea0f4Smrg    break;
1748301ea0f4Smrg  case DPMSModeStandby:
1749301ea0f4Smrg    /* Screen: Off; HSync: Off, VSync: On */
1750301ea0f4Smrg    SEQ01 = 0x20;
1751301ea0f4Smrg    DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
1752301ea0f4Smrg    break;
1753301ea0f4Smrg  case DPMSModeSuspend:
1754301ea0f4Smrg    /* Screen: Off; HSync: On, VSync: Off */
1755301ea0f4Smrg    SEQ01 = 0x20;
1756301ea0f4Smrg    DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
1757301ea0f4Smrg    break;
1758301ea0f4Smrg  case DPMSModeOff:
1759301ea0f4Smrg    /* Screen: Off; HSync: Off, VSync: Off */
1760301ea0f4Smrg    SEQ01 = 0x20;
1761301ea0f4Smrg    DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
1762301ea0f4Smrg    break;
1763301ea0f4Smrg  }
1764301ea0f4Smrg
1765301ea0f4Smrg  /* Turn the screen on/off */
1766301ea0f4Smrg  SEQ01 |= pI740->readControl(pI740, SRX, 0x01) & ~0x20;
1767301ea0f4Smrg  pI740->writeControl(pI740, SRX, 0x01, SEQ01);
1768301ea0f4Smrg
1769301ea0f4Smrg  /* Set the DPMS mode */
1770301ea0f4Smrg  pI740->writeControl(pI740, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
1771301ea0f4Smrg}
1772