ct_driver.c revision 4cac844d
1/*
2 * Copyright 1993 by Jon Block <block@frc.com>
3 * Modified by Mike Hollick <hollick@graphics.cis.upenn.edu>
4 * Modified 1994 by Régis Cridlig <cridlig@dmi.ens.fr>
5 *
6 * Major Contributors to XFree86 3.2
7 *   Modified 1995/6 by Nozomi Ytow
8 *   Modified 1996 by Egbert Eich <eich@xfree86.org>
9 *   Modified 1996 by David Bateman <dbateman@club-internet.fr>
10 *   Modified 1996 by Xavier Ducoin <xavier@rd.lectra.fr>
11 *
12 * Contributors to XFree86 3.2
13 *   Modified 1995/6 by Ken Raeburn <raeburn@raeburn.org>
14 *   Modified 1996 by Shigehiro Nomura <nomura@sm.sony.co.jp>
15 *   Modified 1996 by Marc de Courville <marc@courville.org>
16 *   Modified 1996 by Adam Sulmicki <adam@cfar.umd.edu>
17 *   Modified 1996 by Jens Maurer <jmaurer@cck.uni-kl.de>
18 *
19 * Large parts rewritten for XFree86 4.0
20 *   Modified 1998 by David Bateman <dbateman@club-internet.fr>
21 *   Modified 1998 by Egbert Eich <eich@xfree86.org>
22 *   Modified 1998 by Nozomi Ytow
23 *
24 * Permission to use, copy, modify, distribute, and sell this software and its
25 * documentation for any purpose is hereby granted without fee, provided that
26 * the above copyright notice appear in all copies and that both that
27 * copyright notice and this permission notice appear in supporting
28 * documentation, and that the name of the authors not be used in
29 * advertising or publicity pertaining to distribution of the software without
30 * specific, written prior permission.  The authors makes no representations
31 * about the suitability of this software for any purpose.  It is provided
32 * "as is" without express or implied warranty.
33 *
34 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
35 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
36 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
37 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
38 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
39 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
40 * PERFORMANCE OF THIS SOFTWARE.
41 */
42/*
43 * Copyright 1997
44 * Digital Equipment Corporation. All rights reserved.
45 * This software is furnished under license and may be used and copied only in
46 * accordance with the following terms and conditions.  Subject to these
47 * conditions, you may download, copy, install, use, modify and distribute
48 * this software in source and/or binary form. No title or ownership is
49 * transferred hereby.
50 * 1) Any source code used, modified or distributed must reproduce and retain
51 *    this copyright notice and list of conditions as they appear in the
52 *    source file.
53 *
54 * 2) No right is granted to use any trade name, trademark, or logo of Digital
55 *    Equipment Corporation. Neither the "Digital Equipment Corporation" name
56 *    nor any trademark or logo of Digital Equipment Corporation may be used
57 *    to endorse or promote products derived from this software without the
58 *    prior written permission of Digital Equipment Corporation.
59 *
60 * 3) This software is provided "AS-IS" and any express or implied warranties,
61 *    including but not limited to, any implied warranties of merchantability,
62 *    fitness for a particular purpose, or non-infringement are disclaimed. In
63 *    no event shall DIGITAL be liable for any damages whatsoever, and in
64 *    particular, DIGITAL shall not be liable for special, indirect,
65 *    consequential, or incidental damages or damages for lost profits, loss
66 *    of revenue or loss of use, whether such damages arise in contract,
67 *    negligence, tort, under statute, in equity, at law or otherwise, even if
68 *    advised of the possibility of such damage.
69 */
70
71#ifdef HAVE_CONFIG_H
72#include "config.h"
73#endif
74
75/* All drivers should typically include these */
76#include "xf86.h"
77#include "xf86_OSproc.h"
78
79/* Everything using inb/outb, etc needs "compiler.h" */
80#include "compiler.h"
81
82/* Drivers for PCI hardware need this */
83#include "xf86PciInfo.h"
84
85/* Drivers that need to access the PCI config space directly need this */
86#include "xf86Pci.h"
87
88#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
89/* Standard resources are defined here */
90#include "xf86Resources.h"
91
92/* Needed by Resources Access Control (RAC) */
93#include "xf86RAC.h"
94#endif
95
96/* All drivers using the vgahw module need this */
97#include "vgaHW.h"
98
99/* All drivers initialising the SW cursor need this */
100#include "mipointer.h"
101
102/* All drivers implementing backing store need this */
103#include "mibstore.h"
104
105/* All drivers using the mi banking wrapper need this */
106#include "mibank.h"
107
108/* All drivers using the mi colormap manipulation need this */
109#include "micmap.h"
110
111#include "fb.h"
112#include "xf86Priv.h"
113
114/* Needed for the 1 and 4 bpp framebuffers */
115#ifdef HAVE_XF1BPP
116#include "xf1bpp.h"
117#endif
118#ifdef HAVE_XF4BPP
119#include "xf4bpp.h"
120#endif
121
122/* int10 */
123#include "xf86int10.h"
124#include "vbe.h"
125
126/* Needed by the Shadow Framebuffer */
127#include "shadowfb.h"
128
129/* Needed for replacement LoadPalette function for Gamma Correction */
130#include "xf86cmap.h"
131
132#include "dixstruct.h"
133
134/* Driver specific headers */
135#include "ct_driver.h"
136
137/* Mandatory functions */
138static const OptionInfoRec *	CHIPSAvailableOptions(int chipid, int busid);
139static void     CHIPSIdentify(int flags);
140static Bool     CHIPSPciProbe(DriverPtr drv, int entity_num,
141			      struct pci_device *dev, intptr_t match_data);
142#ifdef HAVE_ISA
143static Bool     CHIPSProbe(DriverPtr drv, int flags);
144#endif
145static Bool     CHIPSPreInit(ScrnInfoPtr pScrn, int flags);
146static Bool     CHIPSScreenInit(int Index, ScreenPtr pScreen, int argc,
147                                  char **argv);
148static Bool     CHIPSEnterVT(int scrnIndex, int flags);
149static void     CHIPSLeaveVT(int scrnIndex, int flags);
150static Bool     CHIPSCloseScreen(int scrnIndex, ScreenPtr pScreen);
151static void     CHIPSFreeScreen(int scrnIndex, int flags);
152static ModeStatus CHIPSValidMode(int scrnIndex, DisplayModePtr mode,
153                                 Bool verbose, int flags);
154static Bool	CHIPSSaveScreen(ScreenPtr pScreen, int mode);
155
156/* Internally used functions */
157static int      chipsFindIsaDevice(GDevPtr dev);
158static Bool     chipsClockSelect(ScrnInfoPtr pScrn, int no);
159Bool     chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
160static void     chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave,
161			  CHIPSRegPtr ChipsSave);
162static void     chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg,
163				 CHIPSRegPtr ChipsReg, Bool restoreFonts);
164static void     chipsLock(ScrnInfoPtr pScrn);
165static void     chipsUnlock(ScrnInfoPtr pScrn);
166static void     chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock);
167static void     chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock);
168static Bool     chipsClockFind(ScrnInfoPtr pScrn, DisplayModePtr mode,
169			       int no, CHIPSClockPtr Clock);
170static void     chipsCalcClock(ScrnInfoPtr pScrn, int Clock,
171				 unsigned char *vclk);
172static int      chipsGetHWClock(ScrnInfoPtr pScrn);
173static Bool     chipsPreInit655xx(ScrnInfoPtr pScrn, int flags);
174static Bool     chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags);
175static Bool     chipsPreInitWingine(ScrnInfoPtr pScrn, int flags);
176static int      chipsSetMonitor(ScrnInfoPtr pScrn);
177static Bool	chipsMapMem(ScrnInfoPtr pScrn);
178static Bool	chipsUnmapMem(ScrnInfoPtr pScrn);
179static void     chipsProtect(ScrnInfoPtr pScrn, Bool on);
180static void	chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank);
181static void     chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs);
182static void     chipsRestoreStretching(ScrnInfoPtr pScrn,
183				unsigned char ctHorizontalStretch,
184				unsigned char ctVerticalStretch);
185static Bool     chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode);
186static Bool     chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode);
187static Bool     chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode);
188static int      chipsVideoMode(int vgaBitsPerPixel,int displayHSize,
189			       int displayVSize);
190static void     chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn,
191				int PowerManagementMode, int flags);
192static void     chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn);
193static void     chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn);
194static void     chipsFixResume(ScrnInfoPtr pScrn);
195static void     chipsLoadPalette(ScrnInfoPtr pScrn, int numColors,
196				int *indices, LOCO *colors, VisualPtr pVisual);
197static void     chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors,
198				int *indices, LOCO *colors, VisualPtr pVisual);
199static void chipsSetPanelType(CHIPSPtr cPtr);
200static void chipsBlockHandler(int, pointer, pointer, pointer);
201
202/*
203 * This is intentionally screen-independent.  It indicates the binding
204 * choice made in the first PreInit.
205 */
206static int pix24bpp = 0;
207
208/*
209 * Index of Entity
210 */
211static int CHIPSEntityIndex = -1;
212
213
214/* Set the non-documented SAR04 register for overlay/video */
215#define SAR04
216
217/*
218 * Initialise some arrays that are used in multiple instances of the
219 * acceleration code. Set them up here as its a convenient place to do it.
220 */
221/* alu to C&T conversion for use with source data */
222int ChipsAluConv[] =
223{
224    0x00,			/* dest =  0; GXclear, 0 */
225    0x88,			/* dest &= src; GXand, 0x1 */
226    0x44,			/* dest =  src & ~dest; GXandReverse, 0x2 */
227    0xCC,			/* dest =  src; GXcopy, 0x3 */
228    0x22,			/* dest &= ~src; GXandInverted, 0x4 */
229    0xAA,			/* dest =  dest; GXnoop, 0x5 */
230    0x66,			/* dest =  ^src; GXxor, 0x6 */
231    0xEE,			/* dest |= src; GXor, 0x7 */
232    0x11,			/* dest =  ~src & ~dest;GXnor, 0x8 */
233    0x99,			/* dest ^= ~src ;GXequiv, 0x9 */
234    0x55,			/* dest =  ~dest; GXInvert, 0xA */
235    0xDD,			/* dest =  src|~dest ;GXorReverse, 0xB */
236    0x33,			/* dest =  ~src; GXcopyInverted, 0xC */
237    0xBB,			/* dest |= ~src; GXorInverted, 0xD */
238    0x77,			/* dest =  ~src|~dest ;GXnand, 0xE */
239    0xFF,			/* dest =  0xFF; GXset, 0xF */
240};
241
242/* alu to C&T conversion for use with pattern data */
243int ChipsAluConv2[] =
244{
245    0x00,			/* dest =  0; GXclear, 0 */
246    0xA0,			/* dest &= src; GXand, 0x1 */
247    0x50,			/* dest =  src & ~dest; GXandReverse, 0x2 */
248    0xF0,			/* dest =  src; GXcopy, 0x3 */
249    0x0A,			/* dest &= ~src; GXandInverted, 0x4 */
250    0xAA,			/* dest =  dest; GXnoop, 0x5 */
251    0x5A,			/* dest =  ^src; GXxor, 0x6 */
252    0xFA,			/* dest |= src; GXor, 0x7 */
253    0x05,			/* dest =  ~src & ~dest;GXnor, 0x8 */
254    0xA5,			/* dest ^= ~src ;GXequiv, 0x9 */
255    0x55,			/* dest =  ~dest; GXInvert, 0xA */
256    0xF5,			/* dest =  src|~dest ;GXorReverse, 0xB */
257    0x0F,			/* dest =  ~src; GXcopyInverted, 0xC */
258    0xAF,			/* dest |= ~src; GXorInverted, 0xD */
259    0x5F,			/* dest =  ~src|~dest ;GXnand, 0xE */
260    0xFF,			/* dest =  0xFF; GXset, 0xF */
261};
262
263/* alu to C&T conversion for use with pattern data as a planemask */
264int ChipsAluConv3[] =
265{
266    0x0A,			/* dest =  0; GXclear, 0 */
267    0x8A,			/* dest &= src; GXand, 0x1 */
268    0x4A,			/* dest =  src & ~dest; GXandReverse, 0x2 */
269    0xCA,			/* dest =  src; GXcopy, 0x3 */
270    0x2A,			/* dest &= ~src; GXandInverted, 0x4 */
271    0xAA,			/* dest =  dest; GXnoop, 0x5 */
272    0x6A,			/* dest =  ^src; GXxor, 0x6 */
273    0xEA,			/* dest |= src; GXor, 0x7 */
274    0x1A,			/* dest =  ~src & ~dest;GXnor, 0x8 */
275    0x9A,			/* dest ^= ~src ;GXequiv, 0x9 */
276    0x5A,			/* dest =  ~dest; GXInvert, 0xA */
277    0xDA,			/* dest =  src|~dest ;GXorReverse, 0xB */
278    0x3A,			/* dest =  ~src; GXcopyInverted, 0xC */
279    0xBA,			/* dest |= ~src; GXorInverted, 0xD */
280    0x7A,			/* dest =  ~src|~dest ;GXnand, 0xE */
281    0xFA,			/* dest =  0xFF; GXset, 0xF */
282};
283
284/* The addresses of the acceleration registers */
285unsigned int ChipsReg32HiQV[] =
286{
287    0x00,		/* BR00 Source and Destination offset register */
288    0x04,		/* BR01 Color expansion background color       */
289    0x08,		/* BR02 Color expansion foreground color       */
290    0x0C,		/* BR03 Monochrome source control register     */
291    0x10,		/* BR04 BitBLT control register                */
292    0x14,		/* BR05 Pattern address register               */
293    0x18,		/* BR06 Source address register                */
294    0x1C,		/* BR07 Destination  address register          */
295    0x20		/* BR08 Destination width and height register  */
296};
297
298unsigned int ChipsReg32[] =
299{
300  /*BitBLT */
301    0x83D0,			       /*DR0 src/dest offset                 */
302    0x87D0,			       /*DR1 BitBlt. address of freeVram?    */
303    0x8BD0,			       /*DR2 BitBlt. paintBrush, or tile pat.*/
304    0x8FD0,                            /*DR3                                 */
305    0x93D0,			       /*DR4 BitBlt.                         */
306    0x97D0,			       /*DR5 BitBlt. srcAddr, or 0 in VRAM   */
307    0x9BD0,			       /*DR6 BitBlt. dest?                   */
308    0x9FD0,			       /*DR7 BitBlt. width << 16 | height    */
309  /*H/W cursor */
310    0xA3D0,			       /*DR8 write/erase cursor              */
311		                       /*bit 0-1 if 0  cursor is not shown
312		                        * if 1  32x32 cursor
313					* if 2  64x64 cursor
314					* if 3  128x128 cursor
315					*/
316                                        /* bit 7 if 1  cursor is not shown   */
317		                        /* bit 9 cursor expansion in X       */
318		                        /* bit 10 cursor expansion in Y      */
319    0xA7D0,			        /* DR9 foreGroundCursorColor         */
320    0xABD0,			        /* DR0xA backGroundCursorColor       */
321    0xAFD0,			        /* DR0xB cursorPosition              */
322		                        /* bit 0-7       x coordinate        */
323		                        /* bit 8-14      0                   */
324		                        /* bit 15        x signum            */
325		                        /* bit 16-23     y coordinate        */
326		                        /* bit 24-30     0                   */
327		                        /* bit 31        y signum            */
328    0xB3D0,			        /* DR0xC address of cursor pattern   */
329};
330
331#if defined(__arm__) && defined(__NetBSD__)
332/*
333 * Built in TV output modes: These modes have been tested on NetBSD with
334 * CT65550 and StrongARM. They give what seems to be the best output for
335 * a roughly 640x480 display. To enable one of the built in modes, add
336 * the identifier "NTSC" or "PAL" to the list of modes in the appropriate
337 * "Display" subsection of the "Screen" section in the XF86Config file.
338 * Note that the call to xf86SetTVOut(), which tells the kernel to enable
339 * TV output results in hardware specific actions. There must be code to
340 * support this in the kernel or TV output won't work.
341 */
342static DisplayModeRec ChipsPALMode = {
343	NULL, NULL,     /* prev, next */
344	"PAL",          /* identifier of this mode */
345	MODE_OK,        /* mode status */
346	M_T_BUILTIN,    /* mode type */
347	15000,		/* Clock frequency */
348	776,		/* HDisplay */
349	800,		/* HSyncStart */
350	872,		/* HSyncEnd */
351	960,		/* HTotal */
352	0,		/* HSkew */
353	585,		/* VDisplay */
354	590,		/* VSyncStart */
355	595,		/* VSyncEnd */
356	625,		/* VTotal */
357	0,		/* VScan */
358	V_INTERLACE,	/* Flags */
359	-1,		/* ClockIndex */
360	15000,		/* SynthClock */
361	776,		/* CRTC HDisplay */
362	800,            /* CRTC HBlankStart */
363	800,            /* CRTC HSyncStart */
364	872,            /* CRTC HSyncEnd */
365	872,            /* CRTC HBlankEnd */
366	960,            /* CRTC HTotal */
367	0,              /* CRTC HSkew */
368	585,		/* CRTC VDisplay */
369	590,		/* CRTC VBlankStart */
370	590,		/* CRTC VSyncStart */
371	595,		/* CRTC VSyncEnd */
372	595,		/* CRTC VBlankEnd */
373	625,		/* CRTC VTotal */
374	FALSE,		/* CrtcHAdjusted */
375	FALSE,		/* CrtcVAdjusted */
376	0,		/* PrivSize */
377	NULL,		/* Private */
378	0.0,		/* HSync */
379	0.0		/* VRefresh */
380};
381
382/*
383** So far, it looks like SECAM uses the same values as PAL
384*/
385static DisplayModeRec ChipsSECAMMode = {
386	NULL,           /* prev */
387	&ChipsPALMode,  /* next */
388	"SECAM",        /* identifier of this mode */
389	MODE_OK,        /* mode status */
390	M_T_BUILTIN,    /* mode type */
391	15000,		/* Clock frequency */
392	776,		/* HDisplay */
393	800,		/* HSyncStart */
394	872,		/* HSyncEnd */
395	960,		/* HTotal */
396	0,		/* HSkew */
397	585,		/* VDisplay */
398	590,		/* VSyncStart */
399	595,		/* VSyncEnd */
400	625,		/* VTotal */
401	0,		/* VScan */
402	V_INTERLACE,	/* Flags */
403	-1,		/* ClockIndex */
404	15000,		/* SynthClock */
405	776,		/* CRTC HDisplay */
406	800,            /* CRTC HBlankStart */
407	800,            /* CRTC HSyncStart */
408	872,            /* CRTC HSyncEnd */
409	872,            /* CRTC HBlankEnd */
410	960,            /* CRTC HTotal */
411	0,              /* CRTC HSkew */
412	585,		/* CRTC VDisplay */
413	590,		/* CRTC VBlankStart */
414	590,		/* CRTC VSyncStart */
415	595,		/* CRTC VSyncEnd */
416	595,		/* CRTC VBlankEnd */
417	625,		/* CRTC VTotal */
418	FALSE,		/* CrtcHAdjusted */
419	FALSE,		/* CrtcVAdjusted */
420	0,		/* PrivSize */
421	NULL,		/* Private */
422	0.0,		/* HSync */
423	0.0		/* VRefresh */
424};
425
426
427static DisplayModeRec ChipsNTSCMode = {
428	NULL,           /* prev */
429	&ChipsSECAMMode,/* next */
430	"NTSC",         /* identifier of this mode */
431	MODE_OK,        /* mode status */
432	M_T_BUILTIN,    /* mode type */
433	11970,		/* Clock frequency */
434	584,		/* HDisplay */
435	640,		/* HSyncStart */
436	696,		/* HSyncEnd */
437	760,		/* HTotal */
438	0,		/* HSkew */
439	450,		/* VDisplay */
440	479,		/* VSyncStart */
441	485,		/* VSyncEnd */
442	525,		/* VTotal */
443	0,		/* VScan */
444	V_INTERLACE | V_NVSYNC | V_NHSYNC ,	/* Flags */
445	-1,		/* ClockIndex */
446	11970,		/* SynthClock */
447	584,		/* CRTC HDisplay */
448	640,            /* CRTC HBlankStart */
449	640,            /* CRTC HSyncStart */
450	696,            /* CRTC HSyncEnd */
451	696,            /* CRTC HBlankEnd */
452	760,            /* CRTC HTotal */
453	0,              /* CRTC HSkew */
454	450,		/* CRTC VDisplay */
455	479,		/* CRTC VBlankStart */
456	479,		/* CRTC VSyncStart */
457	485,		/* CRTC VSyncEnd */
458	485,		/* CRTC VBlankEnd */
459	525,		/* CRTC VTotal */
460	FALSE,		/* CrtcHAdjusted */
461	FALSE,		/* CrtcVAdjusted */
462	0,		/* PrivSize */
463	NULL,		/* Private */
464	0.0,		/* HSync */
465	0.0		/* VRefresh */
466};
467#endif
468
469#define CHIPS_VERSION 4000
470#define CHIPS_NAME "CHIPS"
471#define CHIPS_DRIVER_NAME "chips"
472#define CHIPS_MAJOR_VERSION PACKAGE_VERSION_MAJOR
473#define CHIPS_MINOR_VERSION PACKAGE_VERSION_MINOR
474#define CHIPS_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
475
476
477#ifdef XSERVER_LIBPCIACCESS
478
479#define CHIPS_DEVICE_MATCH(d, i) \
480  { PCI_VENDOR_CHIPSTECH, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
481
482static const struct pci_id_match chips_device_match[] = {
483  CHIPS_DEVICE_MATCH(PCI_CHIP_65545, CHIPS_CT65545),
484  CHIPS_DEVICE_MATCH(PCI_CHIP_65548, CHIPS_CT65548),
485  CHIPS_DEVICE_MATCH(PCI_CHIP_65550, CHIPS_CT65550),
486  CHIPS_DEVICE_MATCH(PCI_CHIP_65554, CHIPS_CT65554),
487  CHIPS_DEVICE_MATCH(PCI_CHIP_65555, CHIPS_CT65555),
488  CHIPS_DEVICE_MATCH(PCI_CHIP_68554, CHIPS_CT68554),
489  CHIPS_DEVICE_MATCH(PCI_CHIP_69000, CHIPS_CT69000),
490  CHIPS_DEVICE_MATCH(PCI_CHIP_69030, CHIPS_CT69030),
491  { 0, 0, 0 },
492};
493#endif
494
495/*
496 * This contains the functions needed by the server after loading the driver
497 * module.  It must be supplied, and gets passed back by the SetupProc
498 * function in the dynamic case.  In the static case, a reference to this
499 * is compiled in, and this requires that the name of this DriverRec be
500 * an upper-case version of the driver name.
501 */
502
503_X_EXPORT DriverRec CHIPS = {
504	CHIPS_VERSION,
505	CHIPS_DRIVER_NAME,
506	CHIPSIdentify,
507#ifdef HAVE_ISA
508	CHIPSProbe,
509#else
510	NULL,
511#endif
512	CHIPSAvailableOptions,
513	NULL,
514	0,
515	NULL,
516
517#ifdef XSERVER_LIBPCIACCESS
518	chips_device_match,
519	CHIPSPciProbe,
520#endif
521};
522
523static SymTabRec CHIPSChipsets[] = {
524    { CHIPS_CT65520,		"ct65520" },
525    { CHIPS_CT65525,		"ct65525" },
526    { CHIPS_CT65530,		"ct65530" },
527    { CHIPS_CT65535,		"ct65535" },
528    { CHIPS_CT65540,		"ct65540" },
529    { CHIPS_CT65545,		"ct65545" },
530    { CHIPS_CT65546,		"ct65546" },
531    { CHIPS_CT65548,		"ct65548" },
532    { CHIPS_CT65550,		"ct65550" },
533    { CHIPS_CT65554,		"ct65554" },
534    { CHIPS_CT65555,		"ct65555" },
535    { CHIPS_CT68554,		"ct68554" },
536    { CHIPS_CT69000,		"ct69000" },
537    { CHIPS_CT69030,		"ct69030" },
538    { CHIPS_CT64200,		"ct64200" },
539    { CHIPS_CT64300,		"ct64300" },
540    { -1,			NULL }
541};
542
543
544/* Conversion PCI ID to chipset name */
545static PciChipsets CHIPSPCIchipsets[] = {
546    { CHIPS_CT65545, PCI_CHIP_65545, RES_SHARED_VGA },
547    { CHIPS_CT65548, PCI_CHIP_65548, RES_SHARED_VGA },
548    { CHIPS_CT65550, PCI_CHIP_65550, RES_SHARED_VGA },
549    { CHIPS_CT65554, PCI_CHIP_65554, RES_SHARED_VGA },
550    { CHIPS_CT65555, PCI_CHIP_65555, RES_SHARED_VGA },
551    { CHIPS_CT68554, PCI_CHIP_68554, RES_SHARED_VGA },
552    { CHIPS_CT69000, PCI_CHIP_69000, RES_SHARED_VGA },
553    { CHIPS_CT69030, PCI_CHIP_69030, RES_SHARED_VGA },
554    { -1,	     -1,	     RES_UNDEFINED}
555};
556
557/* The options supported by the Chips and Technologies Driver */
558typedef enum {
559    OPTION_LINEAR,
560    OPTION_NOACCEL,
561    OPTION_HW_CLKS,
562    OPTION_SW_CURSOR,
563    OPTION_HW_CURSOR,
564    OPTION_STN,
565    OPTION_USE_MODELINE,
566    OPTION_LCD_STRETCH,
567    OPTION_LCD_CENTER,
568    OPTION_MMIO,
569    OPTION_FULL_MMIO,
570    OPTION_SUSPEND_HACK,
571    OPTION_RGB_BITS,
572    OPTION_SYNC_ON_GREEN,
573    OPTION_PANEL_SIZE,
574    OPTION_18_BIT_BUS,
575    OPTION_SHOWCACHE,
576    OPTION_SHADOW_FB,
577    OPTION_OVERLAY,
578    OPTION_COLOR_KEY,
579    OPTION_VIDEO_KEY,
580    OPTION_FP_CLOCK_8,
581    OPTION_FP_CLOCK_16,
582    OPTION_FP_CLOCK_24,
583    OPTION_FP_CLOCK_32,
584    OPTION_SET_MCLK,
585    OPTION_ROTATE,
586    OPTION_NO_TMED,
587    OPTION_CRT2_MEM,
588    OPTION_DUAL_REFRESH,
589    OPTION_CRT_CLK_INDX,
590    OPTION_FP_CLK_INDX,
591    OPTION_FP_MODE
592} CHIPSOpts;
593
594static const OptionInfoRec Chips655xxOptions[] = {
595    { OPTION_LINEAR,		"Linear",	OPTV_BOOLEAN,	{0}, FALSE },
596    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
597    { OPTION_HW_CLKS,		"HWclocks",	OPTV_BOOLEAN,	{0}, FALSE },
598    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
599    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
600    { OPTION_STN,		"STN",		OPTV_BOOLEAN,	{0}, FALSE },
601    { OPTION_USE_MODELINE,	"UseModeline",	OPTV_BOOLEAN,	{0}, FALSE },
602    { OPTION_LCD_STRETCH,	"Stretch",	OPTV_BOOLEAN,	{0}, FALSE },
603    { OPTION_LCD_CENTER,	"LcdCenter",	OPTV_BOOLEAN,	{0}, FALSE },
604    { OPTION_MMIO,		"MMIO",		OPTV_BOOLEAN,	{0}, FALSE },
605    { OPTION_SUSPEND_HACK,	"SuspendHack",	OPTV_BOOLEAN,	{0}, FALSE },
606    { OPTION_PANEL_SIZE,	"FixPanelSize",	OPTV_BOOLEAN,	{0}, FALSE },
607#if 0
608    { OPTION_RGB_BITS,		"RGBbits",	OPTV_INTEGER,	{0}, FALSE },
609#endif
610    { OPTION_18_BIT_BUS,	"18BitBus",	OPTV_BOOLEAN,	{0}, FALSE },
611    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
612    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
613    { OPTION_ROTATE, 	        "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
614    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,      {0}, FALSE },
615    { OPTION_FP_CLOCK_8,        "FPClock8",	OPTV_FREQ,      {0}, FALSE },
616    { OPTION_FP_CLOCK_16,	"FPClock16",	OPTV_FREQ,      {0}, FALSE },
617    { OPTION_FP_CLOCK_24,	"FPClock24",	OPTV_FREQ,      {0}, FALSE },
618    { OPTION_FP_MODE,		"FPMode",	OPTV_BOOLEAN,   {0}, FALSE },
619    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
620};
621
622static const OptionInfoRec ChipsWingineOptions[] = {
623    { OPTION_LINEAR,		"Linear",	OPTV_BOOLEAN,	{0}, FALSE },
624    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
625    { OPTION_HW_CLKS,		"HWclocks",	OPTV_BOOLEAN,	{0}, FALSE },
626    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
627    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
628#if 0
629    { OPTION_RGB_BITS,		"RGBbits",	OPTV_INTEGER,	{0}, FALSE },
630#endif
631    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
632    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
633    { OPTION_ROTATE,  	        "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
634    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
635};
636
637static const OptionInfoRec ChipsHiQVOptions[] = {
638    { OPTION_LINEAR,		"Linear",	OPTV_BOOLEAN,	{0}, FALSE },
639    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
640    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
641    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
642    { OPTION_STN,		"STN",		OPTV_BOOLEAN,	{0}, FALSE },
643    { OPTION_USE_MODELINE,	"UseModeline",	OPTV_BOOLEAN,	{0}, FALSE },
644    { OPTION_LCD_STRETCH,	"Stretch",	OPTV_BOOLEAN,	{0}, FALSE },
645    { OPTION_LCD_CENTER,	"LcdCenter",	OPTV_BOOLEAN,	{0}, FALSE },
646    { OPTION_MMIO,		"MMIO",		OPTV_BOOLEAN,	{0}, FALSE },
647    { OPTION_FULL_MMIO,		"FullMMIO",	OPTV_BOOLEAN,	{0}, FALSE },
648    { OPTION_SUSPEND_HACK,	"SuspendHack",	OPTV_BOOLEAN,	{0}, FALSE },
649    { OPTION_PANEL_SIZE,	"FixPanelSize",	OPTV_BOOLEAN,	{0}, FALSE },
650    { OPTION_RGB_BITS,		"RGBbits",	OPTV_INTEGER,	{0}, FALSE },
651    { OPTION_SYNC_ON_GREEN,	"SyncOnGreen",	OPTV_BOOLEAN,	{0}, FALSE },
652    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
653    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
654    { OPTION_ROTATE, 	        "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
655    { OPTION_OVERLAY,		"Overlay",	OPTV_ANYSTR,	{0}, FALSE },
656    { OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE },
657    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
658    { OPTION_FP_CLOCK_8,	"FPClock8",	OPTV_FREQ,      {0}, FALSE },
659    { OPTION_FP_CLOCK_16,	"FPClock16",	OPTV_FREQ,      {0}, FALSE },
660    { OPTION_FP_CLOCK_24,	"FPClock24",	OPTV_FREQ,      {0}, FALSE },
661    { OPTION_FP_CLOCK_32,	"FPClock32",	OPTV_FREQ,      {0}, FALSE },
662    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,      {0}, FALSE },
663    { OPTION_NO_TMED,		"NoTMED",	OPTV_BOOLEAN,	{0}, FALSE },
664    { OPTION_CRT2_MEM,		"Crt2Memory",	OPTV_INTEGER,	{0}, FALSE },
665    { OPTION_DUAL_REFRESH,	"DualRefresh",	OPTV_BOOLEAN,	{0}, FALSE },
666    { OPTION_CRT_CLK_INDX,	"CrtClkIndx",	OPTV_INTEGER,	{0}, FALSE },
667    { OPTION_FP_CLK_INDX,	"FPClkIndx",	OPTV_INTEGER,	{0}, FALSE },
668    { OPTION_FP_MODE,		"FPMode",	OPTV_BOOLEAN,   {0}, FALSE },
669    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
670};
671
672#ifdef XFree86LOADER
673
674static MODULESETUPPROTO(chipsSetup);
675
676static XF86ModuleVersionInfo chipsVersRec =
677{
678	"chips",
679	MODULEVENDORSTRING,
680	MODINFOSTRING1,
681	MODINFOSTRING2,
682	XORG_VERSION_CURRENT,
683	CHIPS_MAJOR_VERSION, CHIPS_MINOR_VERSION, CHIPS_PATCHLEVEL,
684	ABI_CLASS_VIDEODRV,
685	ABI_VIDEODRV_VERSION,
686	MOD_CLASS_VIDEODRV,
687	{0,0,0,0}
688};
689
690/*
691 * This is the module init data.
692 * Its name has to be the driver name followed by ModuleData
693 */
694_X_EXPORT XF86ModuleData chipsModuleData = { &chipsVersRec, chipsSetup, NULL };
695
696static pointer
697chipsSetup(pointer module, pointer opts, int *errmaj, int *errmin)
698{
699    static Bool setupDone = FALSE;
700
701    if (!setupDone) {
702	setupDone = TRUE;
703        xf86AddDriver(&CHIPS, module, HaveDriverFuncs);
704
705	/*
706	 * Modules that this driver always requires can be loaded here
707	 * by calling LoadSubModule().
708	 */
709
710	/*
711	 * The return value must be non-NULL on success even though there
712	 * is no TearDownProc.
713	 */
714	return (pointer)1;
715    } else {
716	if (errmaj) *errmaj = LDR_ONCEONLY;
717	return NULL;
718    }
719}
720
721#endif /* XFree86LOADER */
722
723static Bool
724CHIPSGetRec(ScrnInfoPtr pScrn)
725{
726    /*
727     * Allocate a CHIPSRec, and hook it into pScrn->driverPrivate.
728     * pScrn->driverPrivate is initialised to NULL, so we can check if
729     * the allocation has already been done.
730     */
731    if (pScrn->driverPrivate != NULL)
732	return TRUE;
733
734    pScrn->driverPrivate = xnfcalloc(sizeof(CHIPSRec), 1);
735
736    if (pScrn->driverPrivate == NULL)
737	return FALSE;
738
739    return TRUE;
740}
741
742static void
743CHIPSFreeRec(ScrnInfoPtr pScrn)
744{
745    if (pScrn->driverPrivate == NULL)
746	return;
747    xfree(pScrn->driverPrivate);
748    pScrn->driverPrivate = NULL;
749}
750
751/* Mandatory */
752static void
753CHIPSIdentify(int flags)
754{
755    xf86PrintChipsets(CHIPS_NAME, "Driver for Chips and Technologies chipsets",
756			CHIPSChipsets);
757}
758
759static const OptionInfoRec *
760CHIPSAvailableOptions(int chipid, int busid)
761{
762    int chip = chipid & 0x0000ffff;
763
764    if (busid == BUS_ISA) {
765    	if ((chip == CHIPS_CT64200) || (chip == CHIPS_CT64300))
766	    return ChipsWingineOptions;
767    }
768    if (busid == BUS_PCI) {
769    	if ((chip >= CHIPS_CT65550) && (chip <= CHIPS_CT69030))
770	    return ChipsHiQVOptions;
771    }
772    return Chips655xxOptions;
773}
774
775/* Mandatory */
776Bool
777CHIPSPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev,
778	    intptr_t match_data)
779{
780    ScrnInfoPtr pScrn = NULL;
781    CHIPSPtr cPtr;
782
783    /* Allocate a ScrnInfoRec and claim the slot */
784    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, CHIPSPCIchipsets, NULL,
785				NULL, NULL, NULL, NULL);
786    if (pScrn != NULL) {
787	/* Fill in what we can of the ScrnInfoRec */
788	pScrn->driverVersion	= CHIPS_VERSION;
789	pScrn->driverName	= CHIPS_DRIVER_NAME;
790	pScrn->name		= CHIPS_NAME;
791	pScrn->Probe		= NULL;
792	pScrn->PreInit		= CHIPSPreInit;
793	pScrn->ScreenInit	= CHIPSScreenInit;
794	pScrn->SwitchMode	= CHIPSSwitchMode;
795	pScrn->AdjustFrame	= CHIPSAdjustFrame;
796	pScrn->EnterVT		= CHIPSEnterVT;
797	pScrn->LeaveVT		= CHIPSLeaveVT;
798	pScrn->FreeScreen	= CHIPSFreeScreen;
799	pScrn->ValidMode	= CHIPSValidMode;
800
801	if (!CHIPSGetRec(pScrn)) {
802		return;
803	}
804	cPtr = CHIPSPTR(pScrn);
805	cPtr->Chipset = match_data;
806	/*
807	 * For cards that can do dual head per entity, mark the entity
808	 * as sharable.
809	 */
810	if (match_data == CHIPS_CT69030) {
811	    CHIPSEntPtr cPtrEnt = NULL;
812	    DevUnion *pPriv;
813
814	    xf86SetEntitySharable(entity_num);
815	    /* Allocate an entity private if necessary */
816	    if (CHIPSEntityIndex < 0)
817	      CHIPSEntityIndex = xf86AllocateEntityPrivateIndex();
818	    pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex);
819	    if (!pPriv->ptr) {
820		pPriv->ptr = xnfcalloc(sizeof(CHIPSEntRec), 1);
821		cPtrEnt = pPriv->ptr;
822		cPtrEnt->lastInstance = -1;
823	    } else {
824		cPtrEnt = pPriv->ptr;
825	    }
826	    /*
827	     * Set the entity instance for this instance of the driver.  For
828	     * dual head per card, instance 0 is the "master" instance, driving
829	     * the primary head, and instance 1 is the "slave".
830	     */
831	    cPtrEnt->lastInstance++;
832	    xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
833					   cPtrEnt->lastInstance);
834	}
835    }
836
837    return (pScrn != NULL);
838}
839
840#ifdef HAVE_ISA
841static Bool
842CHIPSProbe(DriverPtr drv, int flags)
843{
844    ScrnInfoPtr pScrn = NULL;
845    CHIPSPtr cPtr;
846    Bool foundScreen = FALSE;
847    int numDevSections, numUsed;
848    GDevPtr *devSections;
849    int *usedChips;
850    int i, chipset, entity;
851
852    /*
853     * Find the config file Device sections that match this
854     * driver, and return if there are none.
855     */
856    if ((numDevSections = xf86MatchDevice(CHIPS_DRIVER_NAME,
857					  &devSections)) <= 0) {
858	return FALSE;
859    }
860
861    /* Isa Bus */
862    if ((numDevSections =
863      xf86MatchDevice(CHIPS_DRIVER_NAME, &devSections)) > 0) {
864	for (i = 0; i < numDevSections; i++) {
865	    if ((chipset = chipsFindIsaDevice(devSections[i])) > -1) {
866		if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
867		    xf86AddBusDeviceToConfigure(CHIPS_DRIVER_NAME, BUS_ISA,
868			  NULL, chipset);
869		}
870		if (flags & PROBE_DETECT) {
871		    return TRUE;
872		}
873		if (!xf86CheckStrOption(devSections[i]->options, "BusID",
874		  "ISA")) {
875		    continue;
876		}
877
878		pScrn = NULL;
879		entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE);
880	    	pScrn = xf86ConfigFbEntity(NULL, 0, entity, NULL, NULL,
881		  NULL, NULL);
882		pScrn->driverVersion = CHIPS_VERSION;
883		pScrn->driverName    = CHIPS_DRIVER_NAME;
884		pScrn->name          = CHIPS_NAME;
885		pScrn->Probe         = CHIPSProbe;
886		pScrn->PreInit       = CHIPSPreInit;
887		pScrn->ScreenInit    = CHIPSScreenInit;
888		pScrn->SwitchMode    = CHIPSSwitchMode;
889		pScrn->AdjustFrame   = CHIPSAdjustFrame;
890		pScrn->EnterVT       = CHIPSEnterVT;
891		pScrn->LeaveVT       = CHIPSLeaveVT;
892		pScrn->FreeScreen    = CHIPSFreeScreen;
893		pScrn->ValidMode     = CHIPSValidMode;
894		if (!CHIPSGetRec(pScrn)) {
895		    return;
896		}
897		cPtr = CHIPSPTR(pScrn);
898		cPtr->Chipset = chipset;
899	    }
900	}
901    }
902
903    xfree(devSections);
904    return foundScreen;
905}
906
907static int
908chipsFindIsaDevice(GDevPtr dev)
909{
910    int found = -1;
911    unsigned char tmp;
912
913    /*
914     * This function has the only direct register access in the C&T driver.
915     * All other register access through functions to allow for full MMIO.
916     */
917    outb(0x3D6, 0x00);
918    tmp = inb(0x3D7);
919
920    switch (tmp & 0xF0) {
921    case 0x70: 		/* CT65520 */
922	found = CHIPS_CT65520; break;
923    case 0x80:		/* CT65525 or CT65530 */
924	found = CHIPS_CT65530; break;
925    case 0xA0:		/* CT64200 */
926	found = CHIPS_CT64200; break;
927    case 0xB0:		/* CT64300 */
928	found = CHIPS_CT64300; break;
929    case 0xC0:		/* CT65535 */
930	found = CHIPS_CT65535; break;
931    default:
932	switch (tmp & 0xF8) {
933	    case 0xD0:		/* CT65540 */
934		found = CHIPS_CT65540; break;
935	    case 0xD8:		/* CT65545 or CT65546 or CT65548 */
936		switch (tmp & 7) {
937		case 3:
938		    found = CHIPS_CT65546; break;
939		case 4:
940		    found = CHIPS_CT65548; break;
941		default:
942		    found = CHIPS_CT65545; break;
943
944		}
945		break;
946	    default:
947		if (tmp == 0x2C) {
948		    outb(0x3D6, 0x01);
949		    tmp = inb(0x3D7);
950		    if (tmp != 0x10) break;
951		    outb(0x3D6, 0x02);
952		    tmp = inb(0x3D7);
953		    switch (tmp) {
954		    case 0xE0:		/* CT65550 */
955			found = CHIPS_CT65550; break;
956		    case 0xE4:		/* CT65554 */
957			found = CHIPS_CT65554; break;
958		    case 0xE5:		/* CT65555 */
959			found = CHIPS_CT65555; break;
960		    case 0xF4:		/* CT68554 */
961			found = CHIPS_CT68554; break;
962		    case 0xC0:		/* CT69000 */
963			found = CHIPS_CT69000; break;
964		    case 0x30:		/* CT69030 */
965			outb(0x3D6, 0x03);
966			tmp = inb(0x3D7);
967			if (tmp == 0xC)
968			    found = CHIPS_CT69030;
969			break;
970		    default:
971			break;
972		    }
973		}
974		break;
975	}
976	break;
977    }
978    /* We only want ISA/VL Bus - so check for PCI Bus */
979    if(found > CHIPS_CT65548) {
980	outb(0x3D6, 0x08);
981	tmp = inb(0x3D7);
982	if(tmp & 0x01) found = -1;
983    } else if(found > CHIPS_CT65535) {
984	outb(0x3D6, 0x01);
985	tmp = inb(0x3D7);
986	if ((tmp & 0x07) == 0x06) found = -1;
987    }
988    return found;
989}
990#endif
991
992/* Mandatory */
993Bool
994CHIPSPreInit(ScrnInfoPtr pScrn, int flags)
995{
996    pciVideoPtr pciPtr;
997    ClockRangePtr clockRanges;
998    int i;
999    CHIPSPtr cPtr;
1000    Bool res = FALSE;
1001    CHIPSEntPtr cPtrEnt = NULL;
1002
1003    if (flags & PROBE_DETECT) return FALSE;
1004
1005    /* The vgahw module should be loaded here when needed */
1006    if (!xf86LoadSubModule(pScrn, "vgahw"))
1007	return FALSE;
1008
1009    /* Allocate the ChipsRec driverPrivate */
1010    if (!CHIPSGetRec(pScrn)) {
1011	return FALSE;
1012    }
1013    cPtr = CHIPSPTR(pScrn);
1014
1015    /* XXX Check the number of entities, and fail if it isn't one. */
1016    if (pScrn->numEntities != 1)
1017	return FALSE;
1018
1019    /* Since the capabilities are determined by the chipset the very
1020     * first thing to do is, figure out the chipset and its capabilities
1021     */
1022
1023    /* This is the general case */
1024    for (i = 0; i<pScrn->numEntities; i++) {
1025	cPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
1026#ifndef XSERVER_LIBPCIACCESS
1027	if (cPtr->pEnt->resources) return FALSE;
1028#endif
1029	/* If we are using libpciaccess this is already set in CHIPSPciProbe.
1030	 * If we are using something else we need to set it here.
1031	 */
1032	if (!cPtr->Chipset)
1033		cPtr->Chipset = cPtr->pEnt->chipset;
1034	pScrn->chipset = (char *)xf86TokenToString(CHIPSChipsets,
1035						   cPtr->pEnt->chipset);
1036	if ((cPtr->Chipset == CHIPS_CT64200) ||
1037	    (cPtr->Chipset == CHIPS_CT64300)) cPtr->Flags |= ChipsWingine;
1038	if ((cPtr->Chipset >= CHIPS_CT65550) &&
1039	    (cPtr->Chipset <= CHIPS_CT69030)) cPtr->Flags |= ChipsHiQV;
1040
1041	/* This driver can handle ISA and PCI buses */
1042	if (cPtr->pEnt->location.type == BUS_PCI) {
1043	    pciPtr = xf86GetPciInfoForEntity(cPtr->pEnt->index);
1044	    cPtr->PciInfo = pciPtr;
1045#ifndef XSERVER_LIBPCIACCESS
1046	    cPtr->PciTag = pciTag(cPtr->PciInfo->bus,
1047				  cPtr->PciInfo->device,
1048				  cPtr->PciInfo->func);
1049#endif
1050	}
1051    }
1052    /* INT10 */
1053#if 0
1054    if (xf86LoadSubModule(pScrn, "int10")) {
1055 	xf86Int10InfoPtr pInt;
1056#if 1
1057	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
1058	pInt = xf86InitInt10(cPtr->pEnt->index);
1059	xf86FreeInt10(pInt);
1060#endif
1061    }
1062#endif
1063
1064    if (xf86LoadSubModule(pScrn, "vbe")) {
1065	cPtr->pVbe =  VBEInit(NULL,cPtr->pEnt->index);
1066    }
1067
1068    /* Now that we've identified the chipset, setup the capabilities flags */
1069    switch (cPtr->Chipset) {
1070    case CHIPS_CT69030:
1071	cPtr->Flags |= ChipsDualChannelSupport;
1072    case CHIPS_CT69000:
1073	cPtr->Flags |= ChipsFullMMIOSupport;
1074	/* Fall through */
1075    case CHIPS_CT65555:
1076	cPtr->Flags |= ChipsImageReadSupport; /* Does the 69000 support it? */
1077	/* Fall through */
1078    case CHIPS_CT68554:
1079	cPtr->Flags |= ChipsTMEDSupport;
1080	/* Fall through */
1081    case CHIPS_CT65554:
1082    case CHIPS_CT65550:
1083	cPtr->Flags |= ChipsGammaSupport;
1084	cPtr->Flags |= ChipsVideoSupport;
1085	/* Fall through */
1086    case CHIPS_CT65548:
1087    case CHIPS_CT65546:
1088    case CHIPS_CT65545:
1089	cPtr->Flags |= ChipsMMIOSupport;
1090	/* Fall through */
1091    case CHIPS_CT64300:
1092	cPtr->Flags |= ChipsAccelSupport;
1093	/* Fall through */
1094    case CHIPS_CT65540:
1095	cPtr->Flags |= ChipsHDepthSupport;
1096	cPtr->Flags |= ChipsDPMSSupport;
1097	/* Fall through */
1098    case CHIPS_CT65535:
1099    case CHIPS_CT65530:
1100    case CHIPS_CT65525:
1101	cPtr->Flags |= ChipsLinearSupport;
1102	/* Fall through */
1103    case CHIPS_CT64200:
1104    case CHIPS_CT65520:
1105	break;
1106    }
1107
1108    /* Check for shared entities */
1109    if (xf86IsEntityShared(pScrn->entityList[0])) {
1110        if (!(cPtr->Flags & ChipsDualChannelSupport))
1111	    return FALSE;
1112
1113	/* Make sure entity is PCI for now, though this might not be needed. */
1114	if (cPtr->pEnt->location.type != BUS_PCI)
1115	    return FALSE;
1116
1117	/* Allocate an entity private if necessary */
1118	if (xf86IsEntityShared(pScrn->entityList[0])) {
1119	    cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1120					CHIPSEntityIndex)->ptr;
1121	    cPtr->entityPrivate = cPtrEnt;
1122	}
1123#if 0
1124	/* Set cPtr->device to the relevant Device section */
1125	cPtr->device = xf86GetDevFromEntity(pScrn->entityList[0],
1126					    pScrn->entityInstanceList[0]);
1127#endif
1128    }
1129
1130    /* Set the driver to use the PIO register functions by default */
1131    CHIPSSetStdExtFuncs(cPtr);
1132
1133    /* Call the device specific PreInit */
1134    if (IS_HiQV(cPtr))
1135	res = chipsPreInitHiQV(pScrn, flags);
1136    else if (IS_Wingine(cPtr))
1137	res = chipsPreInitWingine(pScrn, flags);
1138    else
1139	res = chipsPreInit655xx(pScrn, flags);
1140
1141    if (cPtr->UseFullMMIO)
1142	chipsUnmapMem(pScrn);
1143
1144    if (!res) {
1145	vbeFree(cPtr->pVbe);
1146	cPtr->pVbe = NULL;
1147	return FALSE;
1148    }
1149
1150/*********/
1151    /*
1152     * Setup the ClockRanges, which describe what clock ranges are available,
1153     * and what sort of modes they can be used for.
1154     */
1155    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
1156    clockRanges->next = NULL;
1157    clockRanges->ClockMulFactor = cPtr->ClockMulFactor;
1158    clockRanges->minClock = cPtr->MinClock;
1159    clockRanges->maxClock = cPtr->MaxClock;
1160    clockRanges->clockIndex = -1;		/* programmable */
1161    if (cPtr->PanelType & ChipsLCD) {
1162	clockRanges->interlaceAllowed = FALSE;
1163	clockRanges->doubleScanAllowed = FALSE;
1164    } else {
1165	clockRanges->interlaceAllowed = TRUE;
1166        clockRanges->doubleScanAllowed = TRUE;
1167    }
1168    /*
1169     * Reduce the amount of video ram for the modes, so that they
1170     * don't overlap with the DSTN framebuffer
1171     */
1172    pScrn->videoRam -= (cPtr->FrameBufferSize + 1023) / 1024;
1173
1174    cPtr->Rounding = 8 * (pScrn->bitsPerPixel <= 8 ? 8
1175			  : pScrn->bitsPerPixel);
1176
1177    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
1178			  pScrn->display->modes, clockRanges,
1179			  NULL, 256, 2048, cPtr->Rounding,
1180			  128, 2048, pScrn->display->virtualX,
1181			  pScrn->display->virtualY, cPtr->FbMapSize,
1182			  LOOKUP_BEST_REFRESH);
1183
1184    if (i == -1) {
1185	vbeFree(cPtr->pVbe);
1186	cPtr->pVbe = NULL;
1187	CHIPSFreeRec(pScrn);
1188	return FALSE;
1189    }
1190
1191    /*
1192     * Put the DSTN framebuffer back into the video ram
1193     */
1194    pScrn->videoRam += (cPtr->FrameBufferSize + 1023) / 1024;
1195
1196    /* Prune the modes marked as invalid */
1197    xf86PruneDriverModes(pScrn);
1198
1199    if (i == 0 || pScrn->modes == NULL) {
1200	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
1201	vbeFree(cPtr->pVbe);
1202	cPtr->pVbe = NULL;
1203	CHIPSFreeRec(pScrn);
1204	return FALSE;
1205    }
1206
1207    /*
1208     * Set the CRTC parameters for all of the modes based on the type
1209     * of mode, and the chipset's interlace requirements.
1210     *
1211     * Calling this is required if the mode->Crtc* values are used by the
1212     * driver and if the driver doesn't provide code to set them.  They
1213     * are not pre-initialised at all.
1214     */
1215    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
1216
1217    /* Set the current mode to the first in the list */
1218    pScrn->currentMode = pScrn->modes;
1219
1220    /* Print the list of modes being used */
1221    xf86PrintModes(pScrn);
1222
1223    /* If monitor resolution is set on the command line, use it */
1224    xf86SetDpi(pScrn, 0, 0);
1225
1226    /* Load bpp-specific modules */
1227    switch (pScrn->bitsPerPixel) {
1228#ifdef HAVE_XF1BPP
1229    case 1:
1230	if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) {
1231	    vbeFree(cPtr->pVbe);
1232	    cPtr->pVbe = NULL;
1233	    CHIPSFreeRec(pScrn);
1234	    return FALSE;
1235	}
1236	break;
1237#endif
1238#ifdef HAVE_XF4BPP
1239    case 4:
1240	if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) {
1241	    vbeFree(cPtr->pVbe);
1242	    cPtr->pVbe = NULL;
1243	    CHIPSFreeRec(pScrn);
1244	    return FALSE;
1245	}
1246	break;
1247#endif
1248    case 16:
1249	if (cPtr->Flags & ChipsOverlay8plus16) {
1250	    if (xf86LoadSubModule(pScrn, "xf8_16bpp") == NULL) {
1251		vbeFree(cPtr->pVbe);
1252		cPtr->pVbe = NULL;
1253	        CHIPSFreeRec(pScrn);
1254		return FALSE;
1255	    }
1256	    break;
1257	}
1258    default:
1259	if (xf86LoadSubModule(pScrn, "fb") == NULL) {
1260	    vbeFree(cPtr->pVbe);
1261	    cPtr->pVbe = NULL;
1262	    CHIPSFreeRec(pScrn);
1263	    return FALSE;
1264	}
1265	break;
1266    }
1267
1268    if (cPtr->Flags & ChipsAccelSupport) {
1269	if (!xf86LoadSubModule(pScrn, "xaa")) {
1270	    vbeFree(cPtr->pVbe);
1271	    cPtr->pVbe = NULL;
1272	    CHIPSFreeRec(pScrn);
1273	    return FALSE;
1274	}
1275    }
1276
1277    if (cPtr->Flags & ChipsShadowFB) {
1278	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1279	    vbeFree(cPtr->pVbe);
1280	    cPtr->pVbe = NULL;
1281	    CHIPSFreeRec(pScrn);
1282	    return FALSE;
1283	}
1284    }
1285
1286    if (cPtr->Accel.UseHWCursor) {
1287	if (!xf86LoadSubModule(pScrn, "ramdac")) {
1288	    vbeFree(cPtr->pVbe);
1289	    cPtr->pVbe = NULL;
1290	    CHIPSFreeRec(pScrn);
1291	    return FALSE;
1292	}
1293    }
1294
1295#ifndef XSERVER_LIBPCIACCESS
1296    if (cPtr->Flags & ChipsLinearSupport)
1297 	xf86SetOperatingState(resVgaMem, cPtr->pEnt->index, ResDisableOpr);
1298
1299    if (cPtr->MMIOBaseVGA)
1300 	xf86SetOperatingState(resVgaIo, cPtr->pEnt->index, ResDisableOpr);
1301#endif
1302
1303    vbeFree(cPtr->pVbe);
1304    cPtr->pVbe = NULL;
1305    return TRUE;
1306}
1307
1308static Bool
1309chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags)
1310{
1311    int bytesPerPixel;
1312    unsigned char tmp;
1313    MessageType from;
1314    int i;
1315    unsigned int Probed[3], FPclkI, CRTclkI;
1316    double real;
1317    int val, indx;
1318    const char *s;
1319    pointer pVbeModule = NULL;
1320
1321    vgaHWPtr hwp;
1322    CHIPSPtr cPtr = CHIPSPTR(pScrn);
1323    CHIPSEntPtr cPtrEnt = NULL;
1324    CHIPSPanelSizePtr Size = &cPtr->PanelSize;
1325    CHIPSMemClockPtr MemClk = &cPtr->MemClock;
1326    CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock);
1327#ifndef XSERVER_LIBPCIACCESS
1328    resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END };
1329#endif
1330
1331    /* Set pScrn->monitor */
1332    pScrn->monitor = pScrn->confScreen->monitor;
1333
1334    /* All HiQV chips support 16/24/32 bpp */
1335    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb |
1336				SupportConvert32to24 | PreferConvert32to24))
1337	return FALSE;
1338    else {
1339	/* Check that the returned depth is one we support */
1340	switch (pScrn->depth) {
1341	case 1:
1342	case 4:
1343	case 8:
1344	case 15:
1345	case 16:
1346	case 24:
1347	case 32:
1348	    /* OK */
1349	    break;
1350	default:
1351	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1352		       "Given depth (%d) is not supported by this driver\n",
1353		       pScrn->depth);
1354	    return FALSE;
1355	}
1356    }
1357    xf86PrintDepthBpp(pScrn);
1358
1359    /* Get the depth24 pixmap format */
1360    if (pScrn->depth == 24 && pix24bpp == 0)
1361	pix24bpp = xf86GetBppFromDepth(pScrn, 24);
1362
1363    /*
1364     * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp
1365     */
1366    if (!vgaHWGetHWRec(pScrn))
1367        return FALSE;
1368
1369    hwp = VGAHWPTR(pScrn);
1370    vgaHWGetIOBase(hwp);
1371    cPtr->PIOBase = hwp->PIOOffset;
1372    /*
1373     * Must allow ensure that storage for the 2nd set of vga registers is
1374     * allocated for dual channel cards
1375     */
1376    if ((cPtr->Flags & ChipsDualChannelSupport) &&
1377		(! xf86IsEntityShared(pScrn->entityList[0])))
1378	vgaHWAllocDefaultRegs(&(cPtr->VgaSavedReg2));
1379
1380    /*
1381     * This must happen after pScrn->display has been set because
1382     * xf86SetWeight references it.
1383     */
1384    if (pScrn->depth > 8) {
1385	/* The defaults are OK for us */
1386	rgb zeros = {0, 0, 0};
1387
1388	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1389	    return FALSE;
1390	} else {
1391	    /* XXX check that weight returned is supported */
1392            ;
1393        }
1394    }
1395
1396    if (!xf86SetDefaultVisual(pScrn, -1))
1397	return FALSE;
1398
1399    /* The gamma fields must be initialised when using the new cmap code */
1400    if (pScrn->depth > 1) {
1401	Gamma zeros = {0.0, 0.0, 0.0};
1402
1403	if (!xf86SetGamma(pScrn, zeros))
1404	    return FALSE;
1405    }
1406
1407    bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3);
1408
1409    /* Collect all of the relevant option flags (fill in pScrn->options) */
1410    xf86CollectOptions(pScrn, NULL);
1411    /* Process the options */
1412    if (!(cPtr->Options = xalloc(sizeof(ChipsHiQVOptions))))
1413	return FALSE;
1414    memcpy(cPtr->Options, ChipsHiQVOptions, sizeof(ChipsHiQVOptions));
1415    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options);
1416
1417    /* Set the bits per RGB */
1418    if (pScrn->depth > 1) {
1419	/* Default to 6, is this right for HiQV?? */
1420	pScrn->rgbBits = 8;
1421	if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, &val)) {
1422	    if (val == 6 || val == 8) {
1423		pScrn->rgbBits = val;
1424		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to "
1425			   "%d\n", pScrn->rgbBits);
1426	    } else
1427		xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid number of "
1428			   "rgb bits %d\n", val);
1429	}
1430    }
1431    if ((cPtr->Flags & ChipsAccelSupport) &&
1432	(xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) {
1433	cPtr->Flags &= ~ChipsAccelSupport;
1434	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
1435    }
1436
1437    from = X_DEFAULT;
1438    if (pScrn->bitsPerPixel < 8) {
1439	/* Default to SW cursor for 1/4 bpp */
1440	cPtr->Accel.UseHWCursor = FALSE;
1441    } else {
1442	cPtr->Accel.UseHWCursor = TRUE;
1443    }
1444    if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR,
1445			  &cPtr->Accel.UseHWCursor))
1446	from = X_CONFIG;
1447    if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR,
1448			  &cPtr->Accel.UseHWCursor)) {
1449	from = X_CONFIG;
1450	cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor;
1451    }
1452    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
1453	       (cPtr->Accel.UseHWCursor) ? "HW" : "SW");
1454
1455    /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */
1456    if (pScrn->bitsPerPixel < 8) {
1457	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) {
1458	cPtr->Flags &= ~ChipsLinearSupport;
1459	from = X_CONFIG;
1460	}
1461    } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) {
1462	cPtr->Flags &= ~ChipsLinearSupport;
1463	from = X_CONFIG;
1464    }
1465
1466    /* linear base */
1467    if (cPtr->Flags & ChipsLinearSupport) {
1468	if (cPtr->pEnt->location.type == BUS_PCI) {
1469	    /* Tack on 0x800000 to access the big-endian aperture? */
1470#if X_BYTE_ORDER == X_BIG_ENDIAN
1471	    if (BE_SWAP_APRETURE(pScrn,cPtr))
1472	        cPtr->FbAddress =  (PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000) + 0x800000L;
1473	    else
1474#endif
1475	        cPtr->FbAddress =  PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000;
1476
1477	    from = X_PROBED;
1478#ifndef XSERVER_LIBPCIACCESS
1479	    if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone))
1480		cPtr->Flags &= ~ChipsLinearSupport;
1481#endif
1482	} else 	{
1483	    if (cPtr->pEnt->device->MemBase) {
1484		cPtr->FbAddress = cPtr->pEnt->device->MemBase;
1485		from = X_CONFIG;
1486	    } else {
1487		cPtr->FbAddress = ((unsigned int)
1488				   (cPtr->readXR(cPtr, 0x06))) << 24;
1489		cPtr->FbAddress |= ((unsigned int)
1490				    (0x80 & (cPtr->readXR(cPtr, 0x05)))) << 16;
1491		from = X_PROBED;
1492	    }
1493#ifndef XSERVER_LIBPCIACCESS
1494	    linearRes[0].rBegin = cPtr->FbAddress;
1495	    linearRes[0].rEnd = cPtr->FbAddress + 0x800000;
1496	    if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) {
1497		cPtr->Flags &= ~ChipsLinearSupport;
1498		from = X_PROBED;
1499	    }
1500#endif
1501	}
1502    }
1503    if (cPtr->Flags & ChipsLinearSupport) {
1504	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1505		   "Enabling linear addressing\n");
1506	xf86DrvMsg(pScrn->scrnIndex, from,
1507		   "base address is set at 0x%lX.\n", cPtr->FbAddress);
1508#if X_BYTE_ORDER == X_BIG_ENDIAN
1509	if (BE_SWAP_APRETURE(pScrn,cPtr))
1510	    cPtr->IOAddress = cPtr->FbAddress - 0x400000L;
1511	else
1512#endif
1513	    cPtr->IOAddress = cPtr->FbAddress + 0x400000L;
1514 	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
1515 		   "IOAddress is set at 0x%lX.\n",cPtr->IOAddress);
1516
1517    } else
1518	xf86DrvMsg(pScrn->scrnIndex, from,
1519		   "Disabling linear addressing\n");
1520
1521    if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE))
1522	|| xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) {
1523	if (!(cPtr->Flags & ChipsLinearSupport)) {
1524	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1525		    "Option \"ShadowFB\" ignored. Not supported without linear addressing\n");
1526	} else if (pScrn->depth < 8) {
1527	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1528		    "Option \"ShadowFB\" ignored. Not supported at this depth.\n");
1529	} else {
1530	    cPtr->Rotate = 0;
1531	    if (s) {
1532		if(!xf86NameCmp(s, "CW")) {
1533		    /* accel is disabled below for shadowFB */
1534		    cPtr->Flags |= ChipsShadowFB;
1535		    cPtr->Rotate = 1;
1536		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1537			       "Rotating screen clockwise\n");
1538		} else if(!xf86NameCmp(s, "CCW")) {
1539		    cPtr->Flags |= ChipsShadowFB;
1540		    cPtr->Rotate = -1;
1541		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
1542			       "counter clockwise\n");
1543		} else {
1544		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
1545			       "value for Option \"Rotate\"\n", s);
1546		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1547			       "Valid options are \"CW\" or \"CCW\"\n");
1548		}
1549	    } else {
1550		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1551			   "Using \"Shadow Framebuffer\"\n");
1552		cPtr->Flags |= ChipsShadowFB;
1553	    }
1554	}
1555    }
1556
1557    if ((s = xf86GetOptValString(cPtr->Options, OPTION_OVERLAY))) {
1558	if (!*s || !xf86NameCmp(s, "8,16") || !xf86NameCmp(s, "16,8")) {
1559	  if (pScrn->bitsPerPixel == 16) {
1560	    if (cPtr->Flags & ChipsLinearSupport) {
1561		cPtr->Flags |= ChipsOverlay8plus16;
1562		if(!xf86GetOptValInteger(
1563			cPtr->Options, OPTION_COLOR_KEY, &(pScrn->colorKey)))
1564		    pScrn->colorKey = TRANSPARENCY_KEY;
1565		pScrn->overlayFlags = OVERLAY_8_16_DUALFB;
1566		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1567			   "PseudoColor overlay enabled.\n");
1568		if (!xf86IsOptionSet(cPtr->Options, OPTION_LCD_STRETCH))
1569		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1570			   "                             - Forcing option \"Stretch\" \"ON\".\n");
1571		if (!xf86IsOptionSet(cPtr->Options, OPTION_LCD_CENTER))
1572		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1573			   "                             - Forcing option \"LcdCenter\" \"OFF\".\n");
1574		if (cPtr->Flags & ChipsShadowFB) {
1575		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1576		           "                             - Disabling \"Shadow Framebuffer\".\n");
1577		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1578			   "                               Not support with option \"8Plus16\".\n");
1579		    cPtr->Flags &= ~ChipsShadowFB;
1580		    cPtr->Rotate = 0;
1581		}
1582	    } else {
1583		xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"Overlay\" ignored. Not supported without linear addressing\n");
1584	    }
1585	  } else {
1586	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1587		"Option \"Overlay\" is not supported in this configuration\n");
1588	  }
1589	} else {
1590	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1591		"\"%s\" is not a valid value for Option \"Overlay\"\n", s);
1592	}
1593    }
1594
1595    if (!(cPtr->Flags & ChipsOverlay8plus16)) {
1596	if(xf86GetOptValInteger(cPtr->Options, OPTION_VIDEO_KEY,
1597		&(cPtr->videoKey))) {
1598	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1599		cPtr->videoKey);
1600	} else {
1601	    cPtr->videoKey =  (1 << pScrn->offset.red) |
1602			(1 << pScrn->offset.green) |
1603			(((pScrn->mask.blue >> pScrn->offset.blue) - 1)
1604			<< pScrn->offset.blue);
1605	}
1606    }
1607
1608    if (cPtr->Flags & ChipsShadowFB) {
1609	if (cPtr->Flags & ChipsAccelSupport) {
1610	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1611		"HW acceleration is not supported with shadow fb\n");
1612	    cPtr->Flags &= ~ChipsAccelSupport;
1613	}
1614	if (cPtr->Rotate && cPtr->Accel.UseHWCursor) {
1615	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1616		"HW cursor is not supported with rotate\n");
1617	    cPtr->Accel.UseHWCursor = FALSE;
1618	}
1619    }
1620
1621    if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, TRUE)) {
1622        cPtr->UseMMIO = TRUE;
1623	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1624		   "Using MMIO\n");
1625
1626	/* Are we using MMIO mapping of VGA registers */
1627	if (xf86ReturnOptValBool(cPtr->Options, OPTION_FULL_MMIO, FALSE)) {
1628	    if ((cPtr->Flags & ChipsLinearSupport)
1629		&& (cPtr->Flags & ChipsFullMMIOSupport)
1630		&& (cPtr->pEnt->location.type == BUS_PCI)) {
1631
1632		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1633			   "Enabling Full MMIO\n");
1634		cPtr->UseFullMMIO = TRUE;
1635		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1636			   "Using Full MMIO\n");
1637
1638		/*
1639		 * We need to map the framebuffer to read/write regs.
1640		 * but can't do that without the FbMapSize. So need to
1641		 * fake value for PreInit. This isn't a problem as
1642		 * framebuffer isn't actually used in PreInit
1643		 */
1644		cPtr->FbMapSize = 1024 * 1024;
1645
1646		/* Map the linear framebuffer */
1647		if (!chipsMapMem(pScrn))
1648		  return FALSE;
1649
1650		/* Setup the MMIO register functions */
1651		if (cPtr->MMIOBaseVGA) {
1652		  CHIPSSetMmioExtFuncs(cPtr);
1653		  CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0);
1654		}
1655	    } else {
1656		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1657			   "FULL_MMIO option ignored\n");
1658	    }
1659	}
1660    } else {
1661	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"Disabling MMIO: "
1662		   "no acceleration, no hw_cursor\n");
1663	cPtr->UseMMIO = FALSE;
1664	cPtr->Accel.UseHWCursor = FALSE;
1665	cPtr->Flags &= ~ChipsAccelSupport;
1666    }
1667
1668
1669    if (cPtr->Flags & ChipsDualChannelSupport) {
1670
1671	if (xf86IsEntityShared(pScrn->entityList[0])) {
1672	    cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1673					CHIPSEntityIndex)->ptr;
1674#if 1
1675	    /*
1676	     * XXX This assumes that the lower number screen is always the
1677	     * "master" head, and that the "master" is the first CRTC.  This
1678	     * can result in unexpected behaviour when the config file marks
1679	     * the primary CRTC as the second screen.
1680	     */
1681	    if (xf86IsPrimInitDone(pScrn->entityList[0]))
1682#else
1683	    /*
1684	     * This is an alternative version that determines which is the
1685	     * secondary CRTC from the screen field in cPtr->pEnt->device.
1686	     * It doesn't currently work because there are things that assume
1687	     * the primary CRTC is initialised first.
1688	     */
1689	    if (cPtr->pEnt->device->screen == 1)
1690
1691#endif
1692	    {
1693		/* This is the second crtc */
1694		cPtr->SecondCrtc = TRUE;
1695		cPtr->UseDualChannel = TRUE;
1696	    } else
1697		cPtr->SecondCrtc = FALSE;
1698
1699	} else {
1700	    if (xf86ReturnOptValBool(cPtr->Options,
1701				   OPTION_DUAL_REFRESH, FALSE)) {
1702		cPtr->Flags |= ChipsDualRefresh;
1703		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1704			   "Dual Refresh mode enabled\n");
1705		cPtr->UseDualChannel = TRUE;
1706	    }
1707	}
1708
1709	/* Store IOSS/MSS so that we can restore them */
1710	cPtr->storeIOSS = cPtr->readIOSS(cPtr);
1711	cPtr->storeMSS = cPtr->readMSS(cPtr);
1712        DUALOPEN;
1713    }
1714
1715	    /* memory size */
1716    if (cPtr->pEnt->device->videoRam != 0) {
1717	pScrn->videoRam = cPtr->pEnt->device->videoRam;
1718	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n",
1719		   pScrn->videoRam);
1720    } else {
1721        /* not given, probe it    */
1722	switch (cPtr->Chipset) {
1723	case CHIPS_CT69030:
1724	    /* The ct69030 has 4Mb of SGRAM integrated */
1725	    pScrn->videoRam = 4096;
1726	    cPtr->Flags |= Chips64BitMemory;
1727	    break;
1728	case CHIPS_CT69000:
1729	    /* The ct69000 has 2Mb of SGRAM integrated */
1730	    pScrn->videoRam = 2048;
1731	    cPtr->Flags |= Chips64BitMemory;
1732	    break;
1733	case CHIPS_CT65550:
1734	    /* XR43: DRAM interface   */
1735	    /* bit 2-1: memory size   */
1736	    /*          0: 1024 kB    */
1737	    /*          1: 2048 kB    */
1738	    /*          2:  reserved  */
1739	    /*          3: reserved   */
1740	    switch (((cPtr->readXR(cPtr, 0x43)) & 0x06) >> 1) {
1741	    case 0:
1742		pScrn->videoRam = 1024;
1743		break;
1744	    case 1:
1745	    case 2:
1746	    case 3:
1747		pScrn->videoRam = 2048;
1748		break;
1749	    }
1750	    break;
1751	default:
1752	    /* XRE0: Software reg     */
1753	    /* bit 3-0: memory size   */
1754	    /*          0: 512k       */
1755	    /*          1: 1024k      */
1756	    /*          2: 1536k(1.5M)*/
1757	    /*          3: 2048k      */
1758	    /*          7: 4096k      */
1759	    tmp = (cPtr->readXR(cPtr, 0xE0)) & 0xF;
1760	    switch (tmp) {
1761	    case 0:
1762		pScrn->videoRam = 512;
1763		break;
1764	    case 1:
1765		pScrn->videoRam = 1024;
1766		break;
1767	    case 2:
1768		pScrn->videoRam = 1536;
1769		break;
1770	    case 3:
1771		pScrn->videoRam = 2048;
1772		break;
1773	    case 7:
1774		pScrn->videoRam = 4096;
1775		break;
1776	    default:
1777		pScrn->videoRam = 1024;
1778		break;
1779	    }
1780	    /* XR43: DRAM interface        */
1781	    /* bit 4-5 mem interface width */
1782	    /* 00: 32Bit		   */
1783	    /* 01: 64Bit		   */
1784	    tmp = cPtr->readXR(cPtr, 0x43);
1785	    if ((tmp & 0x10) == 0x10)
1786		cPtr->Flags |= Chips64BitMemory;
1787	    break;
1788	}
1789    }
1790
1791#if X_BYTE_ORDER == X_BIG_ENDIAN
1792    if (cPtr->pEnt->chipset == CHIPS_CT69030 && ((cPtr->readXR(cPtr, 0x71) & 0x2)) == 0) /* CFG9: Pipeline variable ByteSwap mapping */
1793	cPtr->dualEndianAp = TRUE;
1794    else  /* CFG9: Pipeline A/B mapping */
1795	cPtr->dualEndianAp = FALSE;
1796#endif
1797
1798    if ((cPtr->Flags & ChipsDualChannelSupport) &&
1799		(xf86IsEntityShared(pScrn->entityList[0]))) {
1800       /*
1801	* This takes gives either half or the amount of memory specified
1802        * with the Crt2Memory option
1803        */
1804	pScrn->memPhysBase = cPtr->FbAddress;
1805
1806        if(cPtr->SecondCrtc == FALSE) {
1807	    int crt2mem = -1, adjust;
1808
1809	    xf86GetOptValInteger(cPtr->Options, OPTION_CRT2_MEM, &crt2mem);
1810	    if (crt2mem > 0) {
1811		adjust = crt2mem;
1812		from = X_CONFIG;
1813	    } else {
1814		adjust = pScrn->videoRam / 2;
1815		from = X_DEFAULT;
1816	    }
1817	    xf86DrvMsg(pScrn->scrnIndex, from,
1818			   "CRT2 will use %dK of VideoRam\n",
1819			   adjust);
1820
1821	    cPtrEnt->mastervideoRam = pScrn->videoRam - adjust;
1822	    pScrn->videoRam = cPtrEnt->mastervideoRam;
1823	    cPtrEnt->slavevideoRam = adjust;
1824	    cPtrEnt->masterFbAddress = cPtr->FbAddress;
1825	    cPtr->FbMapSize =
1826	       cPtrEnt->masterFbMapSize = pScrn->videoRam * 1024;
1827	    cPtrEnt->slaveFbMapSize = cPtrEnt->slavevideoRam * 1024;
1828	    pScrn->fbOffset = 0;
1829	} else {
1830	    cPtrEnt->slaveFbAddress = cPtr->FbAddress +
1831				cPtrEnt->masterFbMapSize;
1832	    cPtr->FbMapSize = cPtrEnt->slaveFbMapSize;
1833	    pScrn->videoRam = cPtrEnt->slavevideoRam;
1834	    pScrn->fbOffset = cPtrEnt->masterFbMapSize;
1835	}
1836
1837        cPtrEnt->refCount++;
1838    } else {
1839        /* Normal Handling of video ram etc */
1840        cPtr->FbMapSize = pScrn->videoRam * 1024;
1841    }
1842
1843    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n",
1844		   pScrn->videoRam);
1845
1846    /* Store register values that might be messed up by a suspend resume */
1847    /* Do this early as some of the other code in PreInit relies on it   */
1848    cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01);
1849    cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ?
1850				  0x3D0 : 0x3B0);
1851
1852    /*
1853     * Do DDC here: if VESA BIOS detects an external monitor it
1854     * might switch. SetPanelType() will detect this.
1855     */
1856    if ((pVbeModule = xf86LoadSubModule(pScrn, "ddc"))) {
1857	Bool ddc_done = FALSE;
1858	xf86MonPtr pMon;
1859
1860	if (cPtr->pVbe) {
1861	    if ((pMon
1862		 = xf86PrintEDID(vbeDoEDID(cPtr->pVbe, pVbeModule))) != NULL) {
1863		ddc_done = TRUE;
1864		xf86SetDDCproperties(pScrn,pMon);
1865	    }
1866	}
1867
1868	if (!ddc_done)
1869	    if (xf86LoadSubModule(pScrn, "i2c")) {
1870		if (chips_i2cInit(pScrn)) {
1871		    if ((pMon = xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,
1872						      cPtr->I2C))) != NULL)
1873		       ddc_done = TRUE;
1874		       xf86SetDDCproperties(pScrn,pMon);
1875		}
1876	    }
1877	if (!ddc_done)
1878	    chips_ddc1(pScrn);
1879    }
1880
1881    /*test STN / TFT */
1882    tmp = cPtr->readFR(cPtr, 0x10);
1883
1884    /* XR51 or FR10: DISPLAY TYPE REGISTER                      */
1885    /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType,          */
1886    /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */
1887    switch (tmp & 0x3) {
1888    case 0:
1889	if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) {
1890	    cPtr->PanelType |= ChipsSS;
1891	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n");
1892	} else {
1893	    cPtr->PanelType |= ChipsTFT;
1894	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n");
1895	}
1896	break;
1897    case 2:
1898	cPtr->PanelType |= ChipsDS;
1899	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n");
1900    case 3:
1901	cPtr->PanelType |= ChipsDD;
1902	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n");
1903	break;
1904    default:
1905	break;
1906    }
1907
1908    chipsSetPanelType(cPtr);
1909    from = X_PROBED;
1910    {
1911      Bool fp_mode;
1912      if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) {
1913	if (fp_mode) {
1914	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n");
1915	  cPtr->PanelType |= ChipsLCD;
1916	} else {
1917	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n");
1918	  cPtr->PanelType = ~ChipsLCD;
1919	}
1920	from = X_CONFIG;
1921      }
1922    }
1923    if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT))
1924	xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n");
1925    else if (cPtr->PanelType & ChipsLCD)
1926        xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n");
1927    else if (cPtr->PanelType & ChipsCRT) {
1928        xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n");
1929	/* monitor info */
1930#if 1
1931	cPtr->Monitor = chipsSetMonitor(pScrn);
1932#endif
1933    }
1934    /* screen size */
1935    /*
1936     * In LCD mode / dual mode we want to derive the timing values from
1937     * the ones preset by bios
1938     */
1939    if (cPtr->PanelType & ChipsLCD) {
1940
1941	/* for 65550 we only need H/VDisplay values for screen size */
1942	unsigned char fr25, tmp1;
1943#ifdef DEBUG
1944	unsigned char fr26;
1945	char tmp2;
1946#endif
1947 	fr25 = cPtr->readFR(cPtr, 0x25);
1948 	tmp = cPtr->readFR(cPtr, 0x20);
1949	Size->HDisplay = ((tmp + ((fr25 & 0x0F) << 8)) + 1) << 3;
1950 	tmp = cPtr->readFR(cPtr, 0x30);
1951 	tmp1 = cPtr->readFR(cPtr, 0x35);
1952	Size->VDisplay = ((tmp1 & 0x0F) << 8) + tmp + 1;
1953#ifdef DEBUG
1954 	tmp = cPtr->readFR(cPtr, 0x21);
1955	Size->HRetraceStart = ((tmp + ((fr25 & 0xF0) << 4)) + 1) << 3;
1956 	tmp1 = cPtr->readFR(cPtr, 0x22);
1957	tmp2 = (tmp1 & 0x1F) - (tmp & 0x3F);
1958	Size->HRetraceEnd = ((((tmp2 < 0) ? (tmp2 + 0x40) : tmp2) << 3)
1959			     + Size->HRetraceStart);
1960 	tmp = cPtr->readFR(cPtr, 0x23);
1961 	fr26 = cPtr->readFR(cPtr, 0x26);
1962	Size->HTotal = ((tmp + ((fr26 & 0x0F) << 8)) + 5) << 3;
1963	xf86ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n",
1964	       Size->HDisplay, Size->VDisplay,
1965	       Size->HRetraceStart,Size->HRetraceEnd,
1966	       Size->HTotal);
1967#endif
1968	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n",
1969		   Size->HDisplay, Size->VDisplay);
1970	/* Warn the user if the panel size has been overridden by
1971	 * the modeline values
1972	 */
1973	if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) {
1974	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1975		       "Display size overridden by modelines.\n");
1976	}
1977    }
1978
1979    /* Frame Buffer */                 /* for LCDs          */
1980    if (IS_STN(cPtr->PanelType)) {
1981	tmp = cPtr->readFR(cPtr, 0x1A); /*Frame Buffer Ctrl. */
1982	if (tmp & 1) {
1983	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n");
1984	    if (!(tmp & 0x80)) {
1985		/* Formula for calculating the size of the framebuffer. 3
1986		 * bits per pixel 10 pixels per 32 bit dword. If frame
1987		 * acceleration is enabled the size can be halved.
1988		 */
1989		cPtr->FrameBufferSize = ( Size->HDisplay *
1990				  Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2);
1991		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1992			   "Using embedded Frame Buffer, size %d bytes\n",
1993			   cPtr->FrameBufferSize);
1994	    } else
1995		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1996			   "Using external Frame Buffer used\n");
1997	}
1998	if (tmp & 2)
1999	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2000		       "Frame accelerator enabled\n");
2001    }
2002
2003    /* bus type */
2004    tmp = (cPtr->readXR(cPtr, 0x08)) & 1;
2005    if (tmp == 1) {	       /*PCI */
2006	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n");
2007	cPtr->Bus = ChipsPCI;
2008    } else {   /* XR08: Linear addressing base, not for PCI */
2009	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n");
2010	cPtr->Bus = ChipsVLB;
2011    }
2012
2013    /* disable acceleration for 1 and 4 bpp */
2014    if (pScrn->bitsPerPixel < 8) {
2015	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2016		   "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel);
2017	cPtr->Flags &= ~ChipsAccelSupport;
2018    }
2019
2020    /* Set the flags for Colour transparency. This is dependent
2021     * on the revision on the chip. Until exactly which chips
2022     * have this bug are found, only allow 8bpp Colour transparency */
2023    if ((pScrn->bitsPerPixel == 8) || ((cPtr->Chipset >= CHIPS_CT65555) &&
2024	    (pScrn->bitsPerPixel >= 8) && (pScrn->bitsPerPixel <= 24)))
2025        cPtr->Flags |= ChipsColorTransparency;
2026    else
2027        cPtr->Flags &= ~ChipsColorTransparency;
2028
2029    /* DAC info */
2030    if (!((cPtr->readXR(cPtr, 0xD0)) & 0x01))
2031	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n");
2032
2033    /* MMIO address offset */
2034    cPtr->Regs32 = ChipsReg32HiQV;
2035
2036    /* sync reset ignored on this chipset */
2037    cPtr->SyncResetIgn = TRUE;   /* !! */
2038
2039    /* We use a programmable clock */
2040    pScrn->numClocks = 26;		/* Some number */
2041    pScrn->progClock = TRUE;
2042    cPtr->ClockType = HiQV_STYLE | TYPE_PROGRAMMABLE;
2043
2044    if (cPtr->pEnt->device->textClockFreq > 0) {
2045	SaveClk->Clock = cPtr->pEnt->device->textClockFreq;
2046	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2047		   "Using textclock freq: %7.3f.\n",
2048		   SaveClk->Clock/1000.0);
2049    } else
2050	SaveClk->Clock = 0;
2051
2052    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n");
2053
2054    /* Set the maximum memory clock. */
2055    switch (cPtr->Chipset) {
2056    case CHIPS_CT65550:
2057	if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6)
2058	    MemClk->Max = 38000; /* Revision A chips */
2059	else
2060	    MemClk->Max = 50000; /* Revision B chips */
2061	break;
2062    case CHIPS_CT65554:
2063    case CHIPS_CT65555:
2064    case CHIPS_CT68554:
2065	MemClk->Max = 55000;
2066	break;
2067    case CHIPS_CT69000:
2068	MemClk->Max = 83000;
2069	break;
2070    case CHIPS_CT69030:
2071	MemClk->Max = 100000;
2072	break;
2073    }
2074
2075    /* Probe the dot clocks */
2076    for (i = 0; i < 3; i++) {
2077      unsigned int N,M,PSN,P,VCO_D;
2078      int offset = i * 4;
2079
2080      tmp = cPtr->readXR(cPtr,0xC2 + offset);
2081      M = (cPtr->readXR(cPtr, 0xC0 + offset)
2082	   | (tmp & 0x03)) + 2;
2083      N = (cPtr->readXR(cPtr, 0xC1 + offset)
2084	| (( tmp >> 4) & 0x03)) + 2;
2085      tmp = cPtr->readXR(cPtr, 0xC3 + offset);
2086      PSN = (cPtr->Chipset == CHIPS_CT69000 || cPtr->Chipset == CHIPS_CT69030)
2087		? 1 : (((tmp & 0x1) ? 1 : 4) * ((tmp & 0x02) ? 5 : 1));
2088      VCO_D = ((tmp & 0x04) ? ((cPtr->Chipset == CHIPS_CT69000 ||
2089				cPtr->Chipset == CHIPS_CT69030) ? 1 : 16) : 4);
2090      P = ((tmp & 0x70) >> 4);
2091      Probed[i] = VCO_D * Fref / N;
2092      Probed[i] = Probed[i] * M / (PSN * (1 << P));
2093      Probed[i] = Probed[i] / 1000;
2094    }
2095    CRTclkI = (hwp->readMiscOut(hwp) >> 2) & 0x03;
2096    if (CRTclkI == 3) CRTclkI = 2;
2097    if (cPtr->Chipset == CHIPS_CT69030)
2098	FPclkI = (cPtr->readFR(cPtr, 0x01) >> 2) & 0x3;
2099    else
2100	FPclkI = (cPtr->readFR(cPtr, 0x03) >> 2) & 0x3;
2101    if (FPclkI == 3) FPclkI = 2;
2102    for (i = 0; i < 3; i++) {
2103      xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2104		 "Dot clock %i: %7.3f MHz",i,
2105		 (float)(Probed[i])/1000.);
2106      if (FPclkI == i) xf86ErrorF(" FPclk");
2107      if (CRTclkI == i) xf86ErrorF(" CRTclk");
2108      xf86ErrorF("\n");
2109    }
2110    cPtr->FPclock = Probed[FPclkI];
2111    cPtr->FPclkInx = FPclkI;
2112    if (CRTclkI == FPclkI) {
2113      if (FPclkI == 2)
2114	CRTclkI = 1;
2115      else
2116	CRTclkI = 2;
2117    }
2118    cPtr->CRTclkInx = CRTclkI;
2119
2120
2121    /*
2122     * Some chips seem to dislike some clocks in one of the PLL's. Give
2123     * the user the oppurtunity to change it
2124     */
2125    if (xf86GetOptValInteger(cPtr->Options, OPTION_CRT_CLK_INDX, &indx)) {
2126	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Force CRT Clock index to %d\n",
2127		 indx);
2128	cPtr->CRTclkInx = indx;
2129
2130	if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, &indx)) {
2131	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2132		       "Force FP Clock index to %d\n", indx);
2133	    cPtr->FPclkInx = indx;
2134	} else {
2135	    if (indx == cPtr->FPclkInx) {
2136		if (indx == 2)
2137		    cPtr->FPclkInx = 1;
2138		else
2139		    cPtr->FPclkInx = indx + 1;
2140		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2141			   "FP Clock index forced to %d\n", cPtr->FPclkInx);
2142	    }
2143	}
2144    } else if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX,
2145				    &indx)) {
2146	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2147		   "Force FP Clock index to %d\n", indx);
2148	cPtr->FPclkInx = indx;
2149	if (indx == cPtr->CRTclkInx) {
2150	    if (indx == 2)
2151		cPtr->CRTclkInx = 1;
2152	    else
2153		cPtr->CRTclkInx = indx + 1;
2154	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2155		       "CRT Clock index forced to %d\n", cPtr->CRTclkInx);
2156	}
2157    }
2158
2159
2160    /* Probe the memory clock currently in use */
2161    MemClk->xrCC = cPtr->readXR(cPtr, 0xCC);
2162    MemClk->M = (MemClk->xrCC  & 0x7F) + 2;
2163    MemClk->xrCD = cPtr->readXR(cPtr, 0xCD);
2164    MemClk->N = (MemClk->xrCD & 0x7F) + 2;
2165    MemClk->xrCE = cPtr->readXR(cPtr, 0xCE);
2166    MemClk->PSN = (MemClk->xrCE & 0x1) ? 1 : 4;
2167    MemClk->P = ((MemClk->xrCE & 0x70) >> 4);
2168    /* Be careful with the calculation of ProbeClk as it can overflow */
2169    MemClk->ProbedClk = 4 * Fref / MemClk->N;
2170    MemClk->ProbedClk = MemClk->ProbedClk * MemClk->M / (MemClk->PSN *
2171							 (1 << MemClk->P));
2172    MemClk->ProbedClk = MemClk->ProbedClk / 1000;
2173    MemClk->Clk = MemClk->ProbedClk;
2174
2175    if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
2176	int mclk = (int)(real * 1000.0);
2177	if (mclk <= MemClk->Max) {
2178	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2179		       "Using memory clock of %7.3f MHz\n",
2180		       (float)(mclk/1000.));
2181
2182	    /* Only alter the memory clock if the desired memory clock differs
2183	     * by 50kHz from the one currently being used.
2184	     */
2185	    if (abs(mclk - MemClk->ProbedClk) > 50) {
2186		unsigned char vclk[3];
2187
2188		MemClk->Clk = mclk;
2189		chipsCalcClock(pScrn, MemClk->Clk, vclk);
2190		MemClk->M = vclk[1] + 2;
2191		MemClk->N = vclk[2] + 2;
2192		MemClk->P = (vclk[0] & 0x70) >> 4;
2193		MemClk->PSN = (vclk[0] & 0x1) ? 1 : 4;
2194		MemClk->xrCC = vclk[1];
2195		MemClk->xrCD = vclk[2];
2196		MemClk->xrCE = 0x80 || vclk[0];
2197	    }
2198	} else
2199	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2200		       "Memory clock of %7.3f MHz exceeds limit of %7.3f MHz\n",
2201		       (float)(mclk/1000.),
2202		       (float)(MemClk->Max/1000.));
2203    } else
2204        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2205		   "Probed memory clock of %7.3f MHz\n",
2206		   (float)(MemClk->ProbedClk/1000.));
2207
2208    cPtr->ClockMulFactor = 1;
2209
2210    /* Set the min/max pixel clock */
2211    switch (cPtr->Chipset) {
2212    case CHIPS_CT69030:
2213	cPtr->MinClock = 3000;
2214	cPtr->MaxClock = 170000;
2215	break;
2216    case CHIPS_CT69000:
2217	cPtr->MinClock = 3000;
2218	cPtr->MaxClock = 135000;
2219	break;
2220    case CHIPS_CT68554:
2221    case CHIPS_CT65555:
2222	cPtr->MinClock = 1000;
2223	cPtr->MaxClock = 110000;
2224	break;
2225    case CHIPS_CT65554:
2226	cPtr->MinClock = 1000;
2227	cPtr->MaxClock = 95000;
2228	break;
2229    case CHIPS_CT65550:
2230	cPtr->MinClock = 1000;
2231	if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) {
2232   if ((cPtr->readFR(cPtr, 0x0A)) & 2) {
2233		/*5V Vcc */
2234		cPtr->MaxClock = 100000;
2235	    } else {
2236		/*3.3V Vcc */
2237		cPtr->MaxClock = 80000;
2238	    }
2239	} else
2240	    cPtr->MaxClock = 95000; /* Revision B */
2241	break;
2242    }
2243    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n",
2244	       (float)(cPtr->MinClock / 1000.));
2245
2246    /* Check if maxClock is limited by the MemClk. Only 70% to allow for */
2247    /* RAS/CAS. Extra byte per memory clock needed if framebuffer used   */
2248    /* Extra byte if the overlay plane is activated                      */
2249    /* If flag Chips64BitMemory is set assume a 64bitmemory interface,   */
2250    /* and 32bits on the others. Thus multiply by a suitable factor      */
2251    if (cPtr->Flags & Chips64BitMemory) {
2252	if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD))
2253	    if (cPtr->Flags & ChipsOverlay8plus16 )
2254		cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / 4);
2255	    else
2256		cPtr->MaxClock = min(cPtr->MaxClock,
2257			     MemClk->Clk * 8 * 0.7 / (bytesPerPixel + 1));
2258	else
2259	    if (cPtr->Flags & ChipsOverlay8plus16)
2260		cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / 3);
2261	    else
2262		cPtr->MaxClock = min(cPtr->MaxClock,
2263			     MemClk->Clk * 8 * 0.7 / bytesPerPixel);
2264    } else {
2265	if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD))
2266	    if (cPtr->Flags & ChipsOverlay8plus16 )
2267		cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / 4);
2268	    else
2269		cPtr->MaxClock = min(cPtr->MaxClock,
2270			     MemClk->Clk * 4 * 0.7 / (bytesPerPixel + 1));
2271	else
2272	    if (cPtr->Flags & ChipsOverlay8plus16)
2273		cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / 3);
2274	    else
2275		cPtr->MaxClock = min(cPtr->MaxClock,
2276			     MemClk->Clk * 4 * 0.7 / bytesPerPixel);
2277    }
2278
2279
2280
2281    if (cPtr->pEnt->device->dacSpeeds[0]) {
2282	int speed = 0;
2283	switch (pScrn->bitsPerPixel) {
2284	case 1:
2285	case 4:
2286	case 8:
2287	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8];
2288	    break;
2289	case 16:
2290	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16];
2291	    break;
2292	case 24:
2293	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24];
2294	    break;
2295	case 32:
2296	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP32];
2297	    break;
2298	}
2299
2300	if (speed == 0)
2301	    speed = cPtr->pEnt->device->dacSpeeds[0];
2302	from = X_CONFIG;
2303	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2304		   "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n",
2305		   (float)(speed / 1000.), (float)(cPtr->MaxClock / 1000.));
2306	cPtr->MaxClock = speed;
2307    } else {
2308	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2309		   "Max pixel clock is %7.3f MHz\n",
2310		   (float)(cPtr->MaxClock / 1000.));
2311    }
2312    /*
2313     * Prepare the FPclock:
2314     *    if FPclock <= MaxClock : don't modify the FP clock.
2315     *    else set FPclock to 90% of MaxClock.
2316     */
2317    real = 0.;
2318    switch(bytesPerPixel) {
2319    case 1:
2320        if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, OPTUNITS_MHZ, &real))
2321	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2322		       "FP clock %7.3f MHz requested\n",real);
2323	break;
2324    case 2:
2325        if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, OPTUNITS_MHZ, &real))
2326	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2327		       "FP clock %7.3f MHz requested\n",real);
2328	break;
2329    case 3:
2330        if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, OPTUNITS_MHZ, &real))
2331	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2332		       "FP clock %7.3f MHz requested\n",real);
2333	break;
2334    case 4:
2335        if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_32, OPTUNITS_MHZ, &real))
2336	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2337		       "FP clock %7.3f MHz requested\n",real);
2338	break;
2339    }
2340    val = (int) (real * 1000.);
2341    if (val && val >= cPtr->MinClock && val <= cPtr->MaxClock)
2342      cPtr->FPclock = val;
2343    else if (cPtr->FPclock > cPtr->MaxClock)
2344        cPtr->FPclock = (int)((float)cPtr->MaxClock * 0.9);
2345    else
2346        cPtr->FPclock = 0; /* special value */
2347    cPtr->FPClkModified = FALSE;
2348    if (cPtr->FPclock)
2349        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2350		   "FP clock set to %7.3f MHz\n",
2351		   (float)(cPtr->FPclock / 1000.));
2352
2353#if defined(__arm__) && defined(__NetBSD__)
2354    ChipsPALMode.next = pScrn->monitor->Modes;
2355    pScrn->monitor->Modes = &ChipsNTSCMode;
2356#endif
2357
2358
2359    if (cPtr->Flags & ChipsDualChannelSupport) {
2360	if (xf86IsEntityShared(pScrn->entityList[0])) {
2361	    if (cPtr->SecondCrtc == TRUE) {
2362		cPtrEnt->slaveActive = FALSE;
2363	    } else {
2364		cPtrEnt->masterActive = FALSE;
2365	    }
2366	}
2367	/* Put IOSS/MSS back to normal */
2368	cPtr->writeIOSS(cPtr, cPtr->storeIOSS);
2369	cPtr->writeMSS(cPtr, hwp, cPtr->storeMSS);
2370
2371	xf86SetPrimInitDone(pScrn->entityList[0]);
2372    }
2373
2374    return TRUE;
2375}
2376
2377static Bool
2378chipsPreInitWingine(ScrnInfoPtr pScrn, int flags)
2379{
2380    int i, bytesPerPixel, NoClocks = 0;
2381    unsigned char tmp;
2382    MessageType from;
2383    vgaHWPtr hwp;
2384    CHIPSPtr cPtr = CHIPSPTR(pScrn);
2385    CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock);
2386    Bool useLinear = FALSE;
2387    char *s;
2388#ifndef XSERVER_LIBPCIACCESS
2389    resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END };
2390#endif
2391
2392    /* Set pScrn->monitor */
2393    pScrn->monitor = pScrn->confScreen->monitor;
2394
2395    if (cPtr->Flags & ChipsHDepthSupport)
2396	i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb |
2397				SupportConvert32to24 | PreferConvert32to24);
2398    else
2399	i = xf86SetDepthBpp(pScrn, 8, 0, 0, NoDepth24Support);
2400
2401    if (!i)
2402	return FALSE;
2403    else {
2404	/* Check that the returned depth is one we support */
2405	switch (pScrn->depth) {
2406	case 1:
2407	case 4:
2408	case 8:
2409	    /* OK */
2410	    break;
2411	case 15:
2412	case 16:
2413	case 24:
2414	    if (cPtr->Flags & ChipsHDepthSupport)
2415		break; /* OK */
2416	    /* fall through */
2417	default:
2418	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2419		       "Given depth (%d) is not supported by this driver\n",
2420		       pScrn->depth);
2421	    return FALSE;
2422	}
2423    }
2424
2425    xf86PrintDepthBpp(pScrn);
2426
2427    /* Get the depth24 pixmap format */
2428    if (pScrn->depth == 24 && pix24bpp == 0)
2429	pix24bpp = xf86GetBppFromDepth(pScrn, 24);
2430
2431    /*
2432     * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp
2433     */
2434    if (!vgaHWGetHWRec(pScrn))
2435        return FALSE;
2436
2437    hwp = VGAHWPTR(pScrn);
2438    vgaHWGetIOBase(hwp);
2439
2440    /*
2441     * This must happen after pScrn->display has been set because
2442     * xf86SetWeight references it.
2443     */
2444    if (pScrn->depth > 8) {
2445	/* The defaults are OK for us */
2446	rgb zeros = {0, 0, 0};
2447
2448	if (!xf86SetWeight(pScrn, zeros, zeros)) {
2449	    return FALSE;
2450	} else {
2451	    /* XXX check that weight returned is supported */
2452            ;
2453        }
2454    }
2455
2456    if (!xf86SetDefaultVisual(pScrn, -1))
2457	return FALSE;
2458
2459    /* The gamma fields must be initialised when using the new cmap code */
2460    if (pScrn->depth > 1) {
2461	Gamma zeros = {0.0, 0.0, 0.0};
2462
2463	if (!xf86SetGamma(pScrn, zeros))
2464	    return FALSE;
2465    }
2466
2467    /* Store register values that might be messed up by a suspend resume */
2468    /* Do this early as some of the other code in PreInit relies on it   */
2469    cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18;
2470    cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A;
2471    cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20;
2472    cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15);
2473
2474    cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01);
2475    cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ?
2476				  0x3D0 : 0x3B0);
2477
2478    bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3);
2479
2480    /* Collect all of the relevant option flags (fill in pScrn->options) */
2481    xf86CollectOptions(pScrn, NULL);
2482
2483    /* Process the options */
2484    if (!(cPtr->Options = xalloc(sizeof(ChipsWingineOptions))))
2485	return FALSE;
2486    memcpy(cPtr->Options, ChipsWingineOptions, sizeof(ChipsWingineOptions));
2487    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options);
2488
2489    /* Set the bits per RGB */
2490    if (pScrn->depth > 1) {
2491	/* Default to 6, is this right?? */
2492	pScrn->rgbBits = 6;
2493#if 0
2494	if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS,
2495				 &pScrn->rgbBits)) {
2496	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n",
2497		       pScrn->rgbBits);
2498	}
2499#endif
2500    }
2501    if ((cPtr->Flags & ChipsAccelSupport) &&
2502	    (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) {
2503	cPtr->Flags &= ~ChipsAccelSupport;
2504	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
2505    }
2506
2507    from = X_DEFAULT;
2508    if (pScrn->bitsPerPixel < 8) {
2509	/* Default to SW cursor for 1/4 bpp */
2510	cPtr->Accel.UseHWCursor = FALSE;
2511    } else {
2512	cPtr->Accel.UseHWCursor = TRUE;
2513    }
2514    if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR,
2515			  &cPtr->Accel.UseHWCursor))
2516	from = X_CONFIG;
2517    if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR,
2518			  &cPtr->Accel.UseHWCursor)) {
2519	from = X_CONFIG;
2520	cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor;
2521    }
2522    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
2523	       (cPtr->Accel.UseHWCursor) ? "HW" : "SW");
2524
2525    /* memory size */
2526    if (cPtr->pEnt->device->videoRam != 0) {
2527	pScrn->videoRam = cPtr->pEnt->device->videoRam;
2528	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n",
2529               pScrn->videoRam);
2530    } else {
2531	/* not given, probe it    */
2532	/* XR0F: Software flags 0 */
2533	/* bit 1-0: memory size   */
2534	/*          0: 256 kB     */
2535	/*          1: 512 kB     */
2536	/*          2: 1024 kB    */
2537	/*          3: 1024 kB    */
2538
2539	switch ((cPtr->readXR(cPtr, 0x0F)) & 3) {
2540	case 0:
2541	    pScrn->videoRam = 256;
2542	    break;
2543	case 1:
2544	    pScrn->videoRam = 512;
2545	    break;
2546	case 2:
2547	    pScrn->videoRam = 1024;
2548	    break;
2549	case 3:
2550	    pScrn->videoRam = 2048;
2551	    break;
2552	}
2553	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n",
2554               pScrn->videoRam);
2555    }
2556    cPtr->FbMapSize = pScrn->videoRam * 1024;
2557
2558    /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */
2559    if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE;
2560    if (pScrn->bitsPerPixel < 8) {
2561	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) {
2562	    useLinear = FALSE;
2563	    from = X_CONFIG;
2564	}
2565    } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) {
2566	useLinear = FALSE;
2567	from = X_CONFIG;
2568    }
2569
2570    /* linear base */
2571    if (useLinear) {
2572	unsigned char mask = 0xF8;
2573	if (pScrn->videoRam == 1024)
2574	    mask = 0xF0;
2575	else if (pScrn->videoRam == 2048)
2576	    mask = 0xE0;
2577	if (cPtr->pEnt->device->MemBase) {
2578	    cPtr->FbAddress = cPtr->pEnt->device->MemBase
2579		& ((0xFF << 24) | (mask << 16));
2580	    from = X_CONFIG;
2581	} else {
2582	    cPtr->FbAddress = ((0xFF & (cPtr->readXR(cPtr, 0x09))) << 24);
2583	    cPtr->FbAddress |= ((mask  & (cPtr->readXR(cPtr, 0x08))) << 16);
2584	    from = X_PROBED;
2585	}
2586#ifndef XSERVER_LIBPCIACCESS
2587	linearRes[0].rBegin = cPtr->FbAddress;
2588	linearRes[0].rEnd = cPtr->FbAddress + 0x800000;
2589	if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) {
2590	    useLinear = FALSE;
2591	    from = X_PROBED;
2592	}
2593#endif
2594    }
2595
2596    if (useLinear) {
2597	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2598		   "Enabling linear addressing\n");
2599	xf86DrvMsg(pScrn->scrnIndex, from,
2600		   "base address is set at 0x%lX.\n", cPtr->FbAddress);
2601	if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) &&
2602	    (cPtr->Flags & ChipsMMIOSupport)) {
2603	    cPtr->UseMMIO = TRUE;
2604	    cPtr->IOAddress = cPtr->FbAddress + 0x200000L;
2605	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n");
2606	}
2607    } else {
2608	if (cPtr->Flags & ChipsLinearSupport)
2609	    xf86DrvMsg(pScrn->scrnIndex, from,
2610		       "Disabling linear addressing\n");
2611	cPtr->Flags &= ~ChipsLinearSupport;
2612    }
2613
2614    if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE))
2615	|| xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) {
2616	if (!(cPtr->Flags & ChipsLinearSupport)) {
2617	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2618		    "Option \"ShadowFB\" ignored. Not supported without linear addressing\n");
2619	} else if (pScrn->depth < 8) {
2620	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2621		    "Option \"ShadowFB\" ignored. Not supported at this depth.\n");
2622	} else {
2623	    cPtr->Rotate = 0;
2624	    if (s) {
2625		if(!xf86NameCmp(s, "CW")) {
2626		    /* accel is disabled below for shadowFB */
2627		    cPtr->Flags |= ChipsShadowFB;
2628		    cPtr->Rotate = 1;
2629		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2630			       "Rotating screen clockwise\n");
2631		} else if(!xf86NameCmp(s, "CCW")) {
2632		    cPtr->Flags |= ChipsShadowFB;
2633		    cPtr->Rotate = -1;
2634		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
2635			       "counter clockwise\n");
2636		} else {
2637		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
2638			       "value for Option \"Rotate\"\n", s);
2639		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2640			       "Valid options are \"CW\" or \"CCW\"\n");
2641		}
2642	    } else {
2643		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2644			   "Using \"Shadow Framebuffer\"\n");
2645		cPtr->Flags |= ChipsShadowFB;
2646	    }
2647	}
2648    }
2649    if (cPtr->Flags & ChipsShadowFB) {
2650	if (cPtr->Flags & ChipsAccelSupport) {
2651	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2652		"HW acceleration is not supported with shadow fb\n");
2653	    cPtr->Flags &= ~ChipsAccelSupport;
2654	}
2655	if (cPtr->Rotate && cPtr->Accel.UseHWCursor) {
2656	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2657		"HW cursor is not supported with rotate\n");
2658	    cPtr->Accel.UseHWCursor = FALSE;
2659	}
2660    }
2661
2662    cPtr->PanelType |= ChipsCRT;
2663    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT\n");
2664
2665    /* monitor info */
2666    cPtr->Monitor = chipsSetMonitor(pScrn);
2667
2668    /* bus type */
2669    tmp = cPtr->readXR(cPtr, 0x01) & 3;
2670    switch (tmp) {
2671    case 0:
2672	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n");
2673	cPtr->Bus = ChipsISA;
2674	break;
2675    case 3:
2676	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n");
2677	cPtr->Bus = ChipsVLB;
2678	break;
2679    default:
2680	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n");
2681	cPtr->Bus = ChipsUnknown;
2682	break;
2683    }
2684
2685    /* disable acceleration for 1 and 4 bpp */
2686    if (pScrn->bitsPerPixel < 8) {
2687	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2688		 "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel);
2689	cPtr->Flags &= ~ChipsAccelSupport;
2690    }
2691
2692    /* 32bit register address offsets */
2693    if ((cPtr->Flags & ChipsAccelSupport) ||
2694	    (cPtr->Accel.UseHWCursor)) {
2695	cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32));
2696	tmp = cPtr->readXR(cPtr, 0x07);
2697	for( i = 0; i < (sizeof(ChipsReg32) / sizeof(ChipsReg32[0])); i++) {
2698	    cPtr->Regs32[i] =  ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80)
2699		<< 8)| ((tmp & 0x7F) << 2);
2700#ifdef DEBUG
2701	    ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]);
2702#endif
2703	}
2704#ifndef XSERVER_LIBPCIACCESS
2705	linearRes[0].type = ResExcIoSparse | ResBios | ResBus;
2706	linearRes[0].rBase = cPtr->Regs32[0];
2707	linearRes[0].rMask = 0x83FC;
2708	if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) {
2709	    if (cPtr->Flags & ChipsAccelSupport) {
2710		cPtr->Flags &= ~ChipsAccelSupport;
2711		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2712			   "Cannot allocate IO registers: "
2713			   "Disabling acceleration\n");
2714	    }
2715	    if (cPtr->Accel.UseHWCursor) {
2716		cPtr->Accel.UseHWCursor = FALSE;
2717		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2718			   "Cannot allocate IO registers: "
2719			   "Disabling HWCursor\n");
2720	    }
2721	}
2722#endif
2723    }
2724
2725    cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1);
2726    if (cPtr->ClockMulFactor != 1)
2727	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2728	       "Clocks scaled by %d\n", cPtr->ClockMulFactor);
2729
2730    /* Clock type */
2731    switch (cPtr->Chipset) {
2732    case CHIPS_CT64200:
2733	NoClocks = 4;
2734	cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW;
2735	break;
2736    default:
2737	if (!((cPtr->readXR(cPtr, 0x01)) & 0x10)) {
2738	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2739		       "Using external clock generator\n");
2740	    NoClocks = 4;
2741	    cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW;
2742	} else {
2743	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2744		       "Using internal clock generator\n");
2745	    if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) {
2746		NoClocks = 3;
2747		cPtr->ClockType = WINGINE_2_STYLE | TYPE_HW;
2748	    } else {
2749		NoClocks = 26; /* some number */
2750		cPtr->ClockType = WINGINE_2_STYLE | TYPE_PROGRAMMABLE;
2751		pScrn->progClock = TRUE;
2752	    }
2753	}
2754    }
2755
2756    if (cPtr->ClockType & TYPE_PROGRAMMABLE) {
2757	pScrn->numClocks = NoClocks;
2758	if(cPtr->pEnt->device->textClockFreq > 0) {
2759	    SaveClk->Clock = cPtr->pEnt->device->textClockFreq;
2760	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2761		       "Using textclock freq: %7.3f.\n",
2762		       SaveClk->Clock/1000.0);
2763	} else
2764	   SaveClk->Clock = CRT_TEXT_CLK_FREQ;
2765	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n");
2766    } else {  /* TYPE_PROGRAMMABLE */
2767	SaveClk->Clock = chipsGetHWClock(pScrn);
2768	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n",
2769	       SaveClk->Clock);
2770	if (!cPtr->pEnt->device->numclocks) {
2771	    pScrn->numClocks = NoClocks;
2772	    xf86GetClocks(pScrn, NoClocks, chipsClockSelect,
2773			  chipsProtect, chipsBlankScreen,
2774			  cPtr->IOBase + 0x0A, 0x08, 1, 28322);
2775	    from = X_PROBED;
2776	} else {
2777	    pScrn->numClocks = cPtr->pEnt->device->numclocks;
2778	    if (pScrn->numClocks > NoClocks) {
2779		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2780			   "Too many Clocks specified in configuration file.\n");
2781		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2782			   "\t\tAt most %d clocks may be specified\n", NoClocks);
2783		pScrn->numClocks= NoClocks;
2784	    }
2785	    for (i = 0; i < pScrn->numClocks; i++)
2786		pScrn->clock[i] = cPtr->pEnt->device->clock[i];
2787	    from = X_CONFIG;
2788	}
2789	xf86ShowClocks(pScrn, from);
2790    }
2791
2792    /* Set the min pixel clock */
2793    /* XXX Guess, need to check this */
2794    cPtr->MinClock = 11000 / cPtr->ClockMulFactor;
2795    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n",
2796	       (float)(cPtr->MinClock / 1000.));
2797    /* maximal clock */
2798    switch (cPtr->Chipset) {
2799    case CHIPS_CT64200:
2800	cPtr->MaxClock = 80000 / cPtr->ClockMulFactor;
2801	break;
2802    case CHIPS_CT64300:
2803	cPtr->MaxClock = 85000 / cPtr->ClockMulFactor;
2804	break;
2805    }
2806
2807    if (cPtr->pEnt->device->dacSpeeds[0]) {
2808	int speed = 0;
2809	switch (pScrn->bitsPerPixel) {
2810	case 1:
2811	case 4:
2812	case 8:
2813	   speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8];
2814	   break;
2815	case 16:
2816	   speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16];
2817	   break;
2818	case 24:
2819	   speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24];
2820	   break;
2821	}
2822	if (speed == 0)
2823	    cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0];
2824	from = X_CONFIG;
2825	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2826	    "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n",
2827	    (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.));
2828	cPtr->MaxClock = speed;
2829    } else {
2830	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2831		"Max pixel clock is %7.3f MHz\n",
2832		(float)(cPtr->MaxClock / 1000.));
2833    }
2834
2835    if (xf86LoadSubModule(pScrn, "ddc")) {
2836	if (cPtr->pVbe)
2837	    xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL)));
2838    }
2839    return TRUE;
2840}
2841
2842static Bool
2843chipsPreInit655xx(ScrnInfoPtr pScrn, int flags)
2844{
2845    int i, bytesPerPixel, NoClocks = 0;
2846    unsigned char tmp;
2847    MessageType from;
2848    vgaHWPtr hwp;
2849    CHIPSPtr cPtr = CHIPSPTR(pScrn);
2850    CHIPSPanelSizePtr Size = &cPtr->PanelSize;
2851    CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock);
2852    Bool useLinear = FALSE;
2853    char *s;
2854#ifndef XSERVER_LIBPCIACCESS
2855    resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END };
2856#endif
2857
2858    /* Set pScrn->monitor */
2859    pScrn->monitor = pScrn->confScreen->monitor;
2860
2861    if (cPtr->Flags & ChipsHDepthSupport)
2862	i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb |
2863				SupportConvert32to24 | PreferConvert32to24);
2864    else
2865	i = xf86SetDepthBpp(pScrn, 8, 0, 0, NoDepth24Support);
2866
2867    if (!i)
2868	return FALSE;
2869    else {
2870	/* Check that the returned depth is one we support */
2871	switch (pScrn->depth) {
2872	case 1:
2873	case 4:
2874	case 8:
2875	    /* OK */
2876	    break;
2877	case 15:
2878	case 16:
2879	case 24:
2880	    if (cPtr->Flags & ChipsHDepthSupport)
2881		break; /* OK */
2882	    /* fall through */
2883	default:
2884	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2885		       "Given depth (%d) is not supported by this driver\n",
2886		       pScrn->depth);
2887	    return FALSE;
2888	}
2889    }
2890    xf86PrintDepthBpp(pScrn);
2891
2892    /* Get the depth24 pixmap format */
2893    if (pScrn->depth == 24 && pix24bpp == 0)
2894	pix24bpp = xf86GetBppFromDepth(pScrn, 24);
2895
2896    /*
2897     * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp
2898     */
2899    if (!vgaHWGetHWRec(pScrn))
2900        return FALSE;
2901
2902    hwp = VGAHWPTR(pScrn);
2903    vgaHWGetIOBase(hwp);
2904
2905    /*
2906     * This must happen after pScrn->display has been set because
2907     * xf86SetWeight references it.
2908     */
2909    if (pScrn->depth > 8) {
2910	/* The defaults are OK for us */
2911	rgb zeros = {0, 0, 0};
2912
2913	if (!xf86SetWeight(pScrn, zeros, zeros)) {
2914	    return FALSE;
2915	} else {
2916	    /* XXX check that weight returned is supported */
2917            ;
2918        }
2919    }
2920
2921    if (!xf86SetDefaultVisual(pScrn, -1))
2922	return FALSE;
2923
2924    /* The gamma fields must be initialised when using the new cmap code */
2925    if (pScrn->depth > 1) {
2926	Gamma zeros = {0.0, 0.0, 0.0};
2927
2928	if (!xf86SetGamma(pScrn, zeros))
2929	    return FALSE;
2930    }
2931
2932    /* Store register values that might be messed up by a suspend resume */
2933    /* Do this early as some of the other code in PreInit relies on it   */
2934    cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18;
2935    cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A;
2936    cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20;
2937    cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15);
2938
2939    cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01);
2940    cPtr->IOBase = cPtr->SuspendHack.vgaIOBaseFlag ? 0x3D0 : 0x3B0;
2941
2942    bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3);
2943
2944    /* Collect all of the relevant option flags (fill in pScrn->options) */
2945    xf86CollectOptions(pScrn, NULL);
2946
2947    /* Process the options */
2948    if (!(cPtr->Options = xalloc(sizeof(Chips655xxOptions))))
2949	return FALSE;
2950    memcpy(cPtr->Options, Chips655xxOptions, sizeof(Chips655xxOptions));
2951    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options);
2952
2953    /* Set the bits per RGB */
2954    if (pScrn->depth > 1) {
2955	/* Default to 6, is this right */
2956	pScrn->rgbBits = 6;
2957#if 0
2958	if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS,
2959				 &pScrn->rgbBits)) {
2960	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n",
2961		       pScrn->rgbBits);
2962	}
2963#endif
2964    }
2965    if ((cPtr->Flags & ChipsAccelSupport) &&
2966	    (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) {
2967	cPtr->Flags &= ~ChipsAccelSupport;
2968	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
2969    }
2970
2971    from = X_DEFAULT;
2972    if (pScrn->bitsPerPixel < 8) {
2973	/* Default to SW cursor for 1/4 bpp */
2974	cPtr->Accel.UseHWCursor = FALSE;
2975    } else {
2976	cPtr->Accel.UseHWCursor = TRUE;
2977    }
2978    if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR,
2979			  &cPtr->Accel.UseHWCursor))
2980	from = X_CONFIG;
2981    if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR,
2982			  &cPtr->Accel.UseHWCursor)) {
2983	from = X_CONFIG;
2984	cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor;
2985    }
2986    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
2987	       (cPtr->Accel.UseHWCursor) ? "HW" : "SW");
2988
2989    /* memory size */
2990    if (cPtr->pEnt->device->videoRam != 0) {
2991	pScrn->videoRam = cPtr->pEnt->device->videoRam;
2992	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n",
2993               pScrn->videoRam);
2994    } else {
2995        /* not given, probe it    */
2996	/* XR0F: Software flags 0 */
2997	/* bit 1-0: memory size   */
2998	/*          0: 256 kB     */
2999	/*          1: 512 kB     */
3000	/*          2: 1024 kB    */
3001	/*          3: 1024 kB    */
3002
3003	switch ((cPtr->readXR(cPtr, 0x0F)) & 3) {
3004	case 0:
3005	    pScrn->videoRam = 256;
3006	    break;
3007	case 1:
3008	    pScrn->videoRam = 512;
3009	    break;
3010	case 2:
3011	case 3:
3012	    pScrn->videoRam = 1024;
3013	    break;
3014	}
3015
3016	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n",
3017               pScrn->videoRam);
3018    }
3019    cPtr->FbMapSize = pScrn->videoRam * 1024;
3020
3021    /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */
3022    if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE;
3023    if (pScrn->bitsPerPixel < 8) {
3024	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) {
3025	    useLinear = FALSE;
3026	    from = X_CONFIG;
3027	}
3028    } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) {
3029	useLinear = FALSE;
3030	from = X_CONFIG;
3031    }
3032
3033    /* linear base */
3034    if (useLinear) {
3035	unsigned char mask;
3036	if (cPtr->Chipset == CHIPS_CT65535) {
3037	    mask = (pScrn->videoRam > 512) ? 0xF8 :0xFC;
3038	    if (cPtr->Bus == ChipsISA)
3039	    mask &= 0x7F;
3040	} else if (cPtr->Bus == ChipsISA) {
3041	    mask = 0x0F;
3042	} else {
3043	    mask = 0xFF;
3044	    tmp = cPtr->readXR(cPtr, 0x01);
3045	    if(tmp & 0x40)
3046		mask &= 0x3F;
3047	    if(!(tmp & 0x80))
3048		mask &= 0xCF;
3049	}
3050	if (cPtr->pEnt->location.type == BUS_PCI) {
3051	    cPtr->FbAddress =  PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000;
3052#ifndef XSERVER_LIBPCIACCESS
3053	    if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) {
3054	        useLinear = FALSE;
3055		from = X_PROBED;
3056	    }
3057#endif
3058	} else {
3059	    if (cPtr->pEnt->device->MemBase) {
3060		cPtr->FbAddress = cPtr->pEnt->device->MemBase;
3061		if (cPtr->Chipset == CHIPS_CT65535)
3062		    cPtr->FbAddress &= (mask << 17);
3063		else if (cPtr->Chipset > CHIPS_CT65535)
3064		    cPtr->FbAddress &= (mask << 20);
3065		from = X_CONFIG;
3066	    } else {
3067		if (cPtr->Chipset <= CHIPS_CT65530) {
3068		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3069			       "base address assumed at  0xC00000!\n");
3070		    cPtr->FbAddress = 0xC00000;
3071		    from = X_CONFIG;
3072		} else if (cPtr->Chipset == CHIPS_CT65535) {
3073		    cPtr->FbAddress =
3074			((mask & (cPtr->readXR(cPtr, 0x08))) << 17);
3075		} else {
3076		    cPtr->FbAddress =
3077			((mask & (cPtr->readXR(cPtr, 0x08))) << 20);
3078		}
3079		from = X_PROBED;
3080	    }
3081#ifndef XSERVER_LIBPCIACCESS
3082	    linearRes[0].rBegin = cPtr->FbAddress;
3083	    linearRes[0].rEnd = cPtr->FbAddress + 0x800000;
3084	    if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) {
3085		useLinear = FALSE;
3086		from = X_PROBED;
3087	    }
3088#endif
3089	}
3090    }
3091
3092    if (useLinear) {
3093	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3094		   "Enabling linear addressing\n");
3095	xf86DrvMsg(pScrn->scrnIndex, from,
3096		   "base address is set at 0x%lX.\n", cPtr->FbAddress);
3097	if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) &&
3098	    (cPtr->Flags & ChipsMMIOSupport)) {
3099	    cPtr->UseMMIO = TRUE;
3100	    cPtr->IOAddress = cPtr->FbAddress + 0x200000L;
3101	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n");
3102	}
3103    } else {
3104	if (cPtr->Flags & ChipsLinearSupport)
3105	    xf86DrvMsg(pScrn->scrnIndex, from,
3106		       "Disabling linear addressing\n");
3107	cPtr->Flags &= ~ChipsLinearSupport;
3108    }
3109
3110    if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE))
3111	|| xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) {
3112	if (!(cPtr->Flags & ChipsLinearSupport)) {
3113	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3114		    "Option \"ShadowFB\" ignored. Not supported without linear addressing\n");
3115	} else if (pScrn->depth < 8) {
3116	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3117		    "Option \"ShadowFB\" ignored. Not supported at this depth.\n");
3118	} else {
3119	    cPtr->Rotate = 0;
3120	    if (s) {
3121		if(!xf86NameCmp(s, "CW")) {
3122		    /* accel is disabled below for shadowFB */
3123		    cPtr->Flags |= ChipsShadowFB;
3124		    cPtr->Rotate = 1;
3125		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3126			       "Rotating screen clockwise\n");
3127		} else if(!xf86NameCmp(s, "CCW")) {
3128		    cPtr->Flags |= ChipsShadowFB;
3129		    cPtr->Rotate = -1;
3130		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
3131			       "counter clockwise\n");
3132		} else {
3133		    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
3134			       "value for Option \"Rotate\"\n", s);
3135		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3136			       "Valid options are \"CW\" or \"CCW\"\n");
3137		}
3138	    } else {
3139		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3140			   "Using \"Shadow Framebuffer\"\n");
3141		cPtr->Flags |= ChipsShadowFB;
3142	    }
3143	}
3144    }
3145    if (cPtr->Flags & ChipsShadowFB) {
3146	if (cPtr->Flags & ChipsAccelSupport) {
3147	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3148		"HW acceleration is not supported with shadow fb\n");
3149	    cPtr->Flags &= ~ChipsAccelSupport;
3150	}
3151	if (cPtr->Rotate && cPtr->Accel.UseHWCursor) {
3152	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3153		"HW cursor is not supported with rotate\n");
3154	    cPtr->Accel.UseHWCursor = FALSE;
3155	}
3156    }
3157
3158    /*test STN / TFT */
3159    tmp = cPtr->readXR(cPtr, 0x51);
3160
3161    /* XR51 or FR10: DISPLAY TYPE REGISTER                      */
3162    /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType,          */
3163    /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */
3164    switch (tmp & 0x3) {
3165    case 0:
3166	if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) {
3167	    cPtr->PanelType |= ChipsSS;
3168	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n");
3169	} else {
3170	    cPtr->PanelType |= ChipsTFT;
3171	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n");
3172	}
3173	break;
3174    case 2:
3175	cPtr->PanelType |= ChipsDS;
3176	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n");
3177    case 3:
3178	cPtr->PanelType |= ChipsDD;
3179	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n");
3180	break;
3181    default:
3182	break;
3183    }
3184
3185    chipsSetPanelType(cPtr);
3186    from = X_PROBED;
3187    {
3188        Bool fp_mode;
3189	if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) {
3190	    if (fp_mode) {
3191	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n");
3192		cPtr->PanelType |= ChipsLCD;
3193	    } else {
3194	       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n");
3195	       cPtr->PanelType = ~ChipsLCD;
3196	    }
3197	    from = X_CONFIG;
3198	}
3199    }
3200    if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT))
3201	xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n");
3202    else if (cPtr->PanelType & ChipsLCD)
3203        xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n");
3204    else if (cPtr->PanelType & ChipsCRT) {
3205        xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n");
3206	/* monitor info */
3207	cPtr->Monitor = chipsSetMonitor(pScrn);
3208    }
3209
3210    /* screen size */
3211    /*
3212     * In LCD mode / dual mode we want to derive the timing values from
3213     * the ones preset by bios
3214     */
3215    if (cPtr->PanelType & ChipsLCD) {
3216	unsigned char xr17, tmp1;
3217	char tmp2;
3218
3219	xr17 = cPtr->readXR(cPtr, 0x17);
3220	tmp = cPtr->readXR(cPtr, 0x1B);
3221	Size->HTotal =((tmp + ((xr17 & 0x01) << 8)) + 5) << 3;
3222	tmp = cPtr->readXR(cPtr, 0x1C);
3223	Size->HDisplay = ((tmp + ((xr17 & 0x02) << 7)) + 1) << 3;
3224	tmp = cPtr->readXR(cPtr, 0x19);
3225	Size->HRetraceStart = ((tmp + ((xr17 & 0x04) << 9)) + 1) << 3;
3226	tmp1 = cPtr->readXR(cPtr, 0x1A);
3227	tmp2 = (tmp1 & 0x1F) + ((xr17 & 0x08) << 2) - (tmp & 0x3F);
3228	Size->HRetraceEnd = ((((tmp2 & 0x080u) ? (tmp2 + 0x40) : tmp2) << 3)
3229		+ Size->HRetraceStart);
3230	tmp1 = cPtr->readXR(cPtr, 0x65);
3231	tmp = cPtr->readXR(cPtr, 0x68);
3232	Size->VDisplay = ((tmp1 & 0x02) << 7)
3233	      + ((tmp1 & 0x40) << 3) + tmp + 1;
3234	tmp = cPtr->readXR(cPtr, 0x66);
3235	Size->VRetraceStart = ((tmp1 & 0x04) << 6)
3236	      + ((tmp1 & 0x80) << 2) + tmp + 1;
3237	tmp = cPtr->readXR(cPtr, 0x64);
3238	Size->VTotal = ((tmp1 & 0x01) << 8)
3239	      + ((tmp1 & 0x20) << 4) + tmp + 2;
3240#ifdef DEBUG
3241	ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n",
3242	       Size->HDisplay, Size->VDisplay,
3243	       Size->HRetraceStart, Size->HRetraceEnd,
3244	       Size->HTotal);
3245#endif
3246	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n",
3247		Size->HDisplay, Size->VDisplay);
3248	/* Warn the user if the panel size has been overridden by
3249	 * the modeline values
3250	 */
3251	if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) {
3252	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3253		       "Display size overridden by modelines.\n");
3254	}
3255    }
3256
3257    /* Frame Buffer */                 /* for LCDs          */
3258    if (IS_STN(cPtr->PanelType)) {
3259	tmp = cPtr->readXR(cPtr, 0x6F); /*Frame Buffer Ctrl. */
3260	if (tmp & 1) {
3261	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n");
3262	    if ((cPtr->Chipset > CHIPS_CT65530) && !(tmp & 0x80)) {
3263		/* Formula for calculating the size of the framebuffer. 3
3264		 * bits per pixel 10 pixels per 32 bit dword. If frame
3265		 * acceleration is enabled the size can be halved.
3266		 */
3267		cPtr->FrameBufferSize = ( Size->HDisplay *
3268			Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2);
3269		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3270			   "Using embedded Frame Buffer, size %d bytes\n",
3271			   cPtr->FrameBufferSize);
3272	    } else
3273		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3274			   "Using external Frame Buffer used\n");
3275	}
3276	if (tmp & 2)
3277	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3278		       "Frame accelerator enabled\n");
3279    }
3280
3281    /* bus type */
3282    if (cPtr->Chipset > CHIPS_CT65535) {
3283	tmp = (cPtr->readXR(cPtr, 0x01)) & 7;
3284	if (tmp == 6) {	       /*PCI */
3285	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n");
3286	    cPtr->Bus = ChipsPCI;
3287	    if ((cPtr->Chipset == CHIPS_CT65545) ||
3288		    (cPtr->Chipset == CHIPS_CT65546)) {
3289		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3290			   "32Bit IO not supported on 65545 PCI\n");
3291		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "\tenabling MMIO\n");
3292		cPtr->UseMMIO = TRUE;
3293		cPtr->IOAddress = cPtr->FbAddress + 0x200000L;
3294	    }
3295
3296	} else {   /* XR08: Linear addressing base, not for PCI */
3297	    switch (tmp) {
3298	    case 3:
3299		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CPU Direct\n");
3300		cPtr->Bus = ChipsCPUDirect;
3301		break;
3302	    case 5:
3303		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n");
3304		cPtr->Bus = ChipsISA;
3305		break;
3306	    case 7:
3307		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n");
3308		cPtr->Bus = ChipsVLB;
3309		break;
3310	    default:
3311		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n");
3312	    }
3313	}
3314    } else {
3315	tmp = (cPtr->readXR(cPtr, 0x01)) & 3;
3316	switch (tmp) {
3317	case 0:
3318	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PI Bus\n");
3319	    cPtr->Bus = ChipsPIB;
3320	    break;
3321	case 1:
3322	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MC Bus\n");
3323	    cPtr->Bus = ChipsMCB;
3324	    break;
3325	case 2:
3326	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n");
3327	    cPtr->Bus = ChipsVLB;
3328	    break;
3329	case 3:
3330	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n");
3331	    cPtr->Bus = ChipsISA;
3332	    break;
3333	}
3334    }
3335
3336    if (!(cPtr->Bus == ChipsPCI) && (cPtr->UseMMIO)) {
3337	cPtr->UseMMIO = FALSE;
3338	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3339		   "MMIO only supported on PCI Bus. Disabling MMIO\n");
3340    }
3341
3342    /* disable acceleration for 1 and 4 bpp */
3343    if (pScrn->bitsPerPixel < 8) {
3344	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3345		 "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel);
3346	cPtr->Flags &= ~ChipsAccelSupport;
3347    }
3348
3349    if ((cPtr->Chipset == CHIPS_CT65530) &&
3350	    (cPtr->Flags & ChipsLinearSupport)) {
3351	/* linear mode is no longer default on ct65530 since it */
3352	/* requires additional hardware which some manufacturers*/
3353	/* might not provide.                                   */
3354	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE))
3355	    cPtr->Flags &= ~ChipsLinearSupport;
3356
3357	/* Test wether linear addressing is possible on 65530 */
3358	/* on the 65530 only the A19 select scheme can be used*/
3359	/* for linear addressing since MEMW is used on ISA bus*/
3360	/* systems.                                           */
3361	/* A19 however is used if video memory is > 512 Mb    */
3362	if ((cPtr->Bus == ChipsISA) && (pScrn->videoRam > 512)) {
3363	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3364		       "User selected linear fb not supported by HW!\n");
3365	    cPtr->Flags &= ~ChipsLinearSupport;
3366	}
3367    }
3368
3369    /* DAC info */
3370    if ((cPtr->readXR(cPtr, 0x06)) & 0x02)
3371	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n");
3372
3373    /* MMIO address offset */
3374    if (cPtr->UseMMIO)
3375	cPtr->Regs32 = ChipsReg32;
3376    else if ((cPtr->Flags & ChipsAccelSupport) ||
3377	     (cPtr->Accel.UseHWCursor)) {
3378	cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32));
3379	tmp =  cPtr->readXR(cPtr, 0x07);
3380	for (i = 0; i < (sizeof(ChipsReg32)/sizeof(ChipsReg32[0])); i++) {
3381	    cPtr->Regs32[i] =
3382		((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80)<< 8)
3383		| ((tmp & 0x7F) << 2);
3384#ifdef DEBUG
3385	    ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]);
3386#endif
3387	}
3388#ifndef XSERVER_LIBPCIACCESS
3389	linearRes[0].type = ResExcIoSparse | ResBios | ResBus;
3390	linearRes[0].rBase = cPtr->Regs32[0];
3391	linearRes[0].rMask = 0x83FC;
3392	if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) {
3393	    if (cPtr->Flags & ChipsAccelSupport) {
3394		cPtr->Flags &= ~ChipsAccelSupport;
3395		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3396			   "Cannot allocate IO registers: "
3397			   "Disabling acceleration\n");
3398	    }
3399	    if (cPtr->Accel.UseHWCursor) {
3400		cPtr->Accel.UseHWCursor = FALSE;
3401		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3402			   "Cannot allocate IO registers: "
3403			   "Disabling HWCursor\n");
3404	    }
3405	}
3406#endif
3407    }
3408
3409    /* sync reset ignored on this chipset */
3410    if (cPtr->Chipset > CHIPS_CT65530) {
3411	tmp = cPtr->readXR(cPtr, 0x0E);
3412	if (tmp & 0x80)
3413	    cPtr->SyncResetIgn = TRUE;
3414	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3415		   "Synchronous reset %signored.\n",
3416		   (cPtr->SyncResetIgn ? "" : "not "));
3417    }
3418
3419    cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1);
3420    if (cPtr->ClockMulFactor != 1)
3421	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3422	       "Clocks scaled by %d\n", cPtr->ClockMulFactor);
3423    /* We use a programmable clock */
3424    switch (cPtr->Chipset) {
3425    case CHIPS_CT65520:
3426    case CHIPS_CT65525:
3427    case CHIPS_CT65530:
3428	NoClocks = 4;		/* Some number */
3429	cPtr->ClockType = OLD_STYLE | TYPE_HW;
3430	break;
3431    default:
3432	if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) {
3433	    NoClocks = 5;		/* Some number */
3434	    cPtr->ClockType = NEW_STYLE | TYPE_HW;
3435	} else {
3436	    NoClocks = 26;		/* Some number */
3437	    cPtr->ClockType = NEW_STYLE | TYPE_PROGRAMMABLE;
3438	    pScrn->progClock = TRUE;
3439	}
3440    }
3441
3442    if (cPtr->ClockType & TYPE_PROGRAMMABLE) {
3443	pScrn->numClocks = NoClocks;
3444	if (cPtr->pEnt->device->textClockFreq > 0) {
3445	    SaveClk->Clock = cPtr->pEnt->device->textClockFreq;
3446	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3447		       "Using textclock freq: %7.3f.\n",
3448		       SaveClk->Clock/1000.0);
3449	} else
3450	   SaveClk->Clock = ((cPtr->PanelType & ChipsLCDProbed) ?
3451				 LCD_TEXT_CLK_FREQ : CRT_TEXT_CLK_FREQ);
3452	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n");
3453    } else {  /* TYPE_PROGRAMMABLE */
3454	SaveClk->Clock = chipsGetHWClock(pScrn);
3455	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n",
3456	       SaveClk->Clock);
3457	if (!cPtr->pEnt->device->numclocks) {
3458	    pScrn->numClocks = NoClocks;
3459	    xf86GetClocks(pScrn, NoClocks, chipsClockSelect,
3460			  chipsProtect, chipsBlankScreen,
3461			  cPtr->IOBase + 0x0A, 0x08, 1, 28322);
3462	    from = X_PROBED;
3463	} else {
3464	    pScrn->numClocks = cPtr->pEnt->device->numclocks;
3465	    if (pScrn->numClocks > NoClocks) {
3466		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3467			   "Too many Clocks specified in configuration file.\n");
3468		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3469			   "\t\tAt most %d clocks may be specified\n", NoClocks);
3470		pScrn->numClocks = NoClocks;
3471	    }
3472	    for (i = 0; i < pScrn->numClocks; i++)
3473		pScrn->clock[i] = cPtr->pEnt->device->clock[i];
3474	    from = X_CONFIG;
3475	}
3476	xf86ShowClocks(pScrn, from);
3477    }
3478    /* Set the min pixel clock */
3479    /* XXX Guess, need to check this */
3480    cPtr->MinClock = 11000 / cPtr->ClockMulFactor;
3481    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n",
3482	       (float)(cPtr->MinClock / 1000.));
3483    /* Set the max pixel clock */
3484    switch (cPtr->Chipset) {
3485    case CHIPS_CT65546:
3486    case CHIPS_CT65548:
3487	/* max VCLK is 80 MHz, max MCLK is 75 MHz for CT65548 */
3488	/* It is not sure for CT65546, but it works with 60 nsec EDODRAM */
3489	cPtr->MaxClock = 80000 / cPtr->ClockMulFactor;
3490	break;
3491    default:
3492	if ((cPtr->readXR(cPtr, 0x6C)) & 2) {
3493	    /*5V Vcc */
3494	    cPtr->MaxClock = 68000 / cPtr->ClockMulFactor;
3495	} else {
3496	    /*3.3V Vcc */
3497	    cPtr->MaxClock = 56000 / cPtr->ClockMulFactor;
3498	}
3499    }
3500
3501    if (cPtr->pEnt->device->dacSpeeds[0]) {
3502	int speed = 0;
3503	switch (pScrn->bitsPerPixel) {
3504	case 1:
3505	case 4:
3506	case 8:
3507	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8];
3508	    break;
3509	case 16:
3510	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16];
3511	    break;
3512	case 24:
3513	    speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24];
3514	    break;
3515	}
3516	if (speed == 0)
3517	    cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0];
3518	from = X_CONFIG;
3519	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3520	    "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n",
3521	    (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.));
3522	cPtr->MaxClock = speed;
3523    } else {
3524	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3525		   "Max pixel clock is %7.3f MHz\n",
3526		   (float)(cPtr->MaxClock / 1000.));
3527    }
3528
3529    /* FP clock */
3530    if (cPtr->ClockType & TYPE_PROGRAMMABLE) {
3531	double real = 0;
3532
3533	switch(bytesPerPixel) {
3534	case 1:
3535	    xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8,
3536			      OPTUNITS_MHZ, &real);
3537	    break;
3538	case 2:
3539	    xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16,
3540			      OPTUNITS_MHZ, &real);
3541	    break;
3542	case 3:
3543	    xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24,
3544			      OPTUNITS_MHZ, &real);
3545	    break;
3546	}
3547
3548	if (real > 0) {
3549	    int val;
3550	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3551		       "FP clock %7.3f MHz requested\n",real);
3552	    val = (int) (real * 1000.);
3553	    if (val && (val >= cPtr->MinClock)
3554		&& (val <= cPtr->MaxClock))
3555		cPtr->FPclock = val * cPtr->ClockMulFactor;
3556	    else if (val > cPtr->MaxClock)
3557		cPtr->FPclock = (int)((float)cPtr->MaxClock
3558				      * cPtr->ClockMulFactor * 0.9);
3559	    else
3560		cPtr->FPclock = 0; /* special value */
3561	}  else
3562	    cPtr->FPclock = 0; /* special value */
3563
3564	if (cPtr->FPclock)
3565	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3566		       "FP clock set to %7.3f MHz\n",
3567		       (float)(cPtr->FPclock / 1000.));
3568    } else {
3569	if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK))
3570	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3571		       "FP clock option not supported for this chipset\n");
3572    }
3573
3574    /* Memory Clock */
3575    if (cPtr->ClockType & TYPE_PROGRAMMABLE) {
3576	double real;
3577
3578	switch (cPtr->Chipset) {
3579	case CHIPS_CT65546:
3580	case CHIPS_CT65548:
3581	    /* max MCLK is 75 MHz for CT65548 */
3582	    cPtr->MemClock.Max = 75000;
3583	    break;
3584	default:
3585	    if ((cPtr->readXR(cPtr, 0x6C)) & 2) {
3586		/*5V Vcc */
3587		cPtr->MemClock.Max = 68000;
3588	    } else {
3589		/*3.3V Vcc */
3590		cPtr->MemClock.Max = 56000;
3591	    }
3592	}
3593
3594	if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK,
3595			      OPTUNITS_MHZ, &real)) {
3596	    int mclk = (int)(real * 1000.0);
3597	    if (mclk <= cPtr->MemClock.Max) {
3598		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3599			   "Using memory clock of %7.3f MHz\n",
3600			   (float)(mclk/1000.));
3601		cPtr->MemClock.Clk = mclk;
3602	    } else {
3603		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3604			   "Memory clock of %7.3f MHz exceeds limit of "
3605			   "%7.3f MHz\n",(float)(mclk/1000.),
3606			   (float)(cPtr->MemClock.Max/1000.));
3607		cPtr->MemClock.Clk = cPtr->MemClock.Max * 0.9;
3608	    }
3609	} else
3610	    cPtr->MemClock.Clk = 0;
3611    } else
3612	if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK))
3613	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3614		       "Memory clock option not supported for this chipset\n");
3615
3616    if (xf86LoadSubModule(pScrn, "ddc")) {
3617	if (cPtr->pVbe)
3618	    xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL)));
3619    }
3620    return TRUE;
3621}
3622
3623
3624/* Mandatory */
3625static Bool
3626CHIPSEnterVT(int scrnIndex, int flags)
3627{
3628    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3629    CHIPSPtr cPtr = CHIPSPTR(pScrn);
3630    CHIPSEntPtr cPtrEnt;
3631
3632    if (cPtr->Flags & ChipsDualChannelSupport) {
3633        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
3634					       CHIPSEntityIndex)->ptr;
3635	DUALOPEN;
3636    }
3637    /* Should we re-save the text mode on each VT enter? */
3638    if(!chipsModeInit(pScrn, pScrn->currentMode))
3639      return FALSE;
3640    if ((!(cPtr->Flags & ChipsOverlay8plus16))
3641	&& (cPtr->Flags & ChipsVideoSupport)
3642	&& (cPtr->Flags & ChipsLinearSupport))
3643        CHIPSResetVideo(pScrn);
3644
3645    /*xf86UDelay(50000);*/
3646    chipsHWCursorOn(cPtr, pScrn);
3647    /* cursor settle delay */
3648    xf86UDelay(50000);
3649    CHIPSAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
3650    xf86UDelay(50000);
3651    return TRUE;
3652}
3653
3654/* Mandatory */
3655static void
3656CHIPSLeaveVT(int scrnIndex, int flags)
3657{
3658    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3659    CHIPSPtr cPtr = CHIPSPTR(pScrn);
3660    CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn);
3661    CHIPSEntPtr cPtrEnt;
3662
3663    /* Invalidate the cached acceleration registers */
3664    cAcl->planemask = -1;
3665    cAcl->fgColor = -1;
3666    cAcl->bgColor = -1;
3667
3668    if (cPtr->Flags & ChipsDualChannelSupport) {
3669        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
3670				       CHIPSEntityIndex)->ptr;
3671	if (cPtr->UseDualChannel)
3672	    DUALREOPEN;
3673       	DUALCLOSE;
3674    } else {
3675	chipsHWCursorOff(cPtr, pScrn);
3676	chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg,
3677					TRUE);
3678	chipsLock(pScrn);
3679    }
3680}
3681
3682
3683static void
3684chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
3685		 VisualPtr pVisual)
3686{
3687    vgaHWPtr hwp = VGAHWPTR(pScrn);
3688    CHIPSPtr cPtr = CHIPSPTR(pScrn);
3689    int i, index, shift ;
3690    CHIPSEntPtr cPtrEnt;
3691
3692    shift = ((pScrn->depth == 15) &&
3693	     (!(cPtr->Flags & ChipsOverlay8plus16))) ? 3 : 0;
3694
3695    if (cPtr->UseDualChannel) {
3696        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
3697					       CHIPSEntityIndex)->ptr;
3698	DUALREOPEN;
3699    }
3700
3701    for (i = 0; i < numColors; i++) {
3702	index = indices[i];
3703	hwp->writeDacWriteAddr(hwp,index << shift);
3704	DACDelay(hwp);
3705	hwp->writeDacData(hwp, colors[index].red);
3706	DACDelay(hwp);
3707	hwp->writeDacData(hwp, colors[index].green);
3708	DACDelay(hwp);
3709	hwp->writeDacData(hwp, colors[index].blue);
3710	DACDelay(hwp);
3711    }
3712
3713    if (cPtr->UseDualChannel &&
3714		(! xf86IsEntityShared(pScrn->entityList[0]))) {
3715	unsigned int IOSS, MSS;
3716	IOSS = cPtr->readIOSS(cPtr);
3717	MSS = cPtr->readMSS(cPtr);
3718	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
3719			       IOSS_PIPE_B));
3720	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B));
3721
3722	for (i = 0; i < numColors; i++) {
3723	    index = indices[i];
3724	    hwp->writeDacWriteAddr(hwp,index << shift);
3725	    DACDelay(hwp);
3726	    hwp->writeDacData(hwp, colors[index].red);
3727	    DACDelay(hwp);
3728	    hwp->writeDacData(hwp, colors[index].green);
3729	    DACDelay(hwp);
3730	    hwp->writeDacData(hwp, colors[index].blue);
3731	    DACDelay(hwp);
3732	}
3733	cPtr->writeIOSS(cPtr, IOSS);
3734	cPtr->writeMSS(cPtr, hwp, MSS);
3735    }
3736
3737    /* This shouldn't be necessary, but we'll play safe. */
3738    hwp->disablePalette(hwp);
3739}
3740
3741static void
3742chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices,
3743		 LOCO *colors, VisualPtr pVisual)
3744{
3745    vgaHWPtr hwp = VGAHWPTR(pScrn);
3746    CHIPSPtr cPtr = CHIPSPTR(pScrn);
3747    CHIPSEntPtr cPtrEnt;
3748
3749    int i, index;
3750
3751    if (cPtr->UseDualChannel) {
3752        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
3753					       CHIPSEntityIndex)->ptr;
3754	DUALREOPEN;
3755    }
3756
3757    for (i = 0; i < numColors; i++) {
3758	index = indices[i];
3759	hwp->writeDacWriteAddr(hwp, index << 2);
3760	DACDelay(hwp);
3761	hwp->writeDacData(hwp, colors[index >> 1].red);
3762	DACDelay(hwp);
3763	hwp->writeDacData(hwp, colors[index].green);
3764	DACDelay(hwp);
3765	hwp->writeDacData(hwp, colors[index >> 1].blue);
3766	DACDelay(hwp);
3767    }
3768
3769
3770    if (cPtr->UseDualChannel &&
3771		(! xf86IsEntityShared(pScrn->entityList[0]))) {
3772	unsigned int IOSS, MSS;
3773	IOSS = cPtr->readIOSS(cPtr);
3774	MSS = cPtr->readMSS(cPtr);
3775	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
3776			       IOSS_PIPE_B));
3777	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B));
3778
3779	for (i = 0; i < numColors; i++) {
3780	    index = indices[i];
3781	    hwp->writeDacWriteAddr(hwp, index << 2);
3782	    DACDelay(hwp);
3783	    hwp->writeDacData(hwp, colors[index >> 1].red);
3784	    DACDelay(hwp);
3785	    hwp->writeDacData(hwp, colors[index].green);
3786	    DACDelay(hwp);
3787	    hwp->writeDacData(hwp, colors[index >> 1].blue);
3788	    DACDelay(hwp);
3789	}
3790
3791	cPtr->writeIOSS(cPtr, IOSS);
3792	cPtr->writeMSS(cPtr, hwp, MSS);
3793    }
3794
3795    /* This shouldn't be necessary, but we'll play safe. */
3796    hwp->disablePalette(hwp);
3797}
3798
3799/* Mandatory */
3800static Bool
3801CHIPSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
3802{
3803    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
3804    vgaHWPtr hwp;
3805    CHIPSPtr cPtr;
3806    CHIPSACLPtr cAcl;
3807    int ret;
3808    int init_picture = 0;
3809    VisualPtr visual;
3810    int allocatebase, freespace, currentaddr;
3811    unsigned int racflag = 0;
3812    unsigned char *FBStart;
3813    int height, width, displayWidth;
3814    CHIPSEntPtr cPtrEnt = NULL;
3815#ifdef DEBUG
3816    ErrorF("CHIPSScreenInit\n");
3817#endif
3818
3819    /*
3820     * we need to get the ScrnInfoRec for this screen, so let's allocate
3821     * one first thing
3822     */
3823    cPtr = CHIPSPTR(pScrn);
3824    cAcl = CHIPSACLPTR(pScrn);
3825
3826    hwp = VGAHWPTR(pScrn);
3827    hwp->MapSize = 0x10000;		/* Standard 64k VGA window */
3828
3829    /* Map the VGA memory */
3830    if (!vgaHWMapMem(pScrn))
3831	return FALSE;
3832
3833    /* Map the Chips memory and possible MMIO areas */
3834    if (!chipsMapMem(pScrn))
3835	return FALSE;
3836
3837    /* Setup a pointer to the overlay if needed */
3838    if (cPtr->Flags & ChipsOverlay8plus16) {
3839	cPtr->FbOffset16 = pScrn->displayWidth * pScrn->virtualY;
3840	cPtr->FbSize16 =  (pScrn->displayWidth << 1) * pScrn->virtualY;
3841	if (cPtr->FbSize16 > (cPtr->FbMapSize - cPtr->FrameBufferSize)) {
3842	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3843		   "Too little memory for overlay. Disabling.\n");
3844	    cPtr->Flags &= ~ChipsOverlay8plus16;
3845	}
3846	if ((pScrn->displayWidth > 1024) || (pScrn->virtualY > 1024)) {
3847	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3848		   "Max overlay Width/Height 1024 pixels. Disabling.\n");
3849	    cPtr->Flags &= ~ChipsOverlay8plus16;
3850	}
3851    }
3852
3853    /* Setup the MMIO register access functions if need */
3854    if (cPtr->UseFullMMIO && cPtr->MMIOBaseVGA) {
3855	CHIPSSetMmioExtFuncs(cPtr);
3856	CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0);
3857    }
3858
3859    if (cPtr->Flags & ChipsDualChannelSupport) {
3860        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
3861					       CHIPSEntityIndex)->ptr;
3862	DUALOPEN;
3863    }
3864
3865#if defined(__arm__) && defined(___NetBSD__)
3866    if (strcmp(pScrn->currentMode->name,"PAL") == 0) {
3867	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using built-in PAL TV mode\n");
3868	cPtr->TVMode = XMODE_PAL;
3869    } else if (strcmp(pScrn->currentMode->name,"SECAM") == 0){
3870	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3871		   "Using built-in SECAM TV mode\n");
3872	cPtr->TVMode = XMODE_SECAM;
3873    } else if (strcmp(pScrn->currentMode->name,"NTSC") == 0) {
3874	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
3875		   "Using built-in NTSC TV mode\n");
3876	cPtr->TVMode = XMODE_NTSC;
3877    } else
3878	cPtr->TVMode = XMODE_RGB;
3879#endif
3880
3881    /*
3882     * next we save the current state and setup the first mode
3883     */
3884    if ((cPtr->Flags & ChipsDualChannelSupport) &&
3885		(! xf86IsEntityShared(pScrn->entityList[0]))) {
3886	unsigned int IOSS, MSS;
3887	IOSS = cPtr->readIOSS(cPtr);
3888	MSS = cPtr->readMSS(cPtr);
3889	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
3890					IOSS_PIPE_A));
3891	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_A));
3892	chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg);
3893	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
3894			       IOSS_PIPE_B));
3895	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B));
3896	chipsSave(pScrn, &cPtr->VgaSavedReg2, &cPtr->SavedReg2);
3897	cPtr->writeIOSS(cPtr, IOSS);
3898	cPtr->writeMSS(cPtr, hwp, MSS);
3899    } else
3900	chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg);
3901
3902    if (!chipsModeInit(pScrn,pScrn->currentMode))
3903	return FALSE;
3904    CHIPSSaveScreen(pScreen,SCREEN_SAVER_ON);
3905    CHIPSAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
3906
3907    /*
3908     * The next step is to setup the screen's visuals, and initialise the
3909     * framebuffer code.  In cases where the framebuffer's default
3910     * choices for things like visual layouts and bits per RGB are OK,
3911     * this may be as simple as calling the framebuffer's ScreenInit()
3912     * function.  If not, the visuals will need to be setup before calling
3913     * a fb ScreenInit() function and fixed up after.
3914     *
3915     * For most PC hardware at depths >= 8, the defaults that cfb uses
3916     * are not appropriate.  In this driver, we fixup the visuals after.
3917     */
3918
3919    /*
3920     * Reset visual list.
3921     */
3922    miClearVisualTypes();
3923
3924    /* Setup the visuals we support. */
3925    if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)){
3926	if (!miSetVisualTypes(8, PseudoColorMask | GrayScaleMask,
3927			      pScrn->rgbBits, PseudoColor))
3928		return FALSE;
3929	if (!miSetVisualTypes(16, TrueColorMask, pScrn->rgbBits, TrueColor))
3930		return FALSE;
3931    } else {
3932      if (!miSetVisualTypes(pScrn->depth,
3933			    miGetDefaultVisualMask(pScrn->depth),
3934			    pScrn->rgbBits, pScrn->defaultVisual))
3935	return FALSE;
3936    }
3937    miSetPixmapDepths ();
3938
3939    /*
3940     * Call the framebuffer layer's ScreenInit function, and fill in other
3941     * pScreen fields.
3942     */
3943    if ((cPtr->Flags & ChipsShadowFB) && cPtr->Rotate) {
3944	height = pScrn->virtualX;
3945	width = pScrn->virtualY;
3946    } else {
3947	width = pScrn->virtualX;
3948	height = pScrn->virtualY;
3949    }
3950
3951    if(cPtr->Flags & ChipsShadowFB) {
3952	cPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
3953	cPtr->ShadowPtr = xalloc(cPtr->ShadowPitch * height);
3954	displayWidth = cPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3);
3955	FBStart = cPtr->ShadowPtr;
3956    } else {
3957	cPtr->ShadowPtr = NULL;
3958	displayWidth = pScrn->displayWidth;
3959	FBStart = cPtr->FbBase;
3960    }
3961
3962    switch (pScrn->bitsPerPixel) {
3963#ifdef HAVE_XF1BPP
3964    case 1:
3965	ret = xf1bppScreenInit(pScreen, FBStart,
3966 		        width,height,
3967			pScrn->xDpi, pScrn->yDpi,
3968			displayWidth);
3969	break;
3970#endif
3971#ifdef HAVE_XF4BPP
3972    case 4:
3973	ret = xf4bppScreenInit(pScreen, FBStart,
3974 		        width,height,
3975			pScrn->xDpi, pScrn->yDpi,
3976			displayWidth);
3977	break;
3978#endif
3979    case 16:
3980      if (cPtr->Flags & ChipsOverlay8plus16) {
3981	  ret = cfb8_16ScreenInit(pScreen, (unsigned char *)FBStart +
3982				  cPtr->FbOffset16, FBStart, width,
3983				  height, pScrn->xDpi, pScrn->yDpi,
3984				  displayWidth, displayWidth);
3985	  break;
3986      }
3987    default:
3988	ret = fbScreenInit(pScreen, FBStart,
3989 		        width,height,
3990			pScrn->xDpi, pScrn->yDpi,
3991			displayWidth,pScrn->bitsPerPixel);
3992	init_picture = 1;
3993	break;
3994    }
3995
3996    if (!ret)
3997	return FALSE;
3998
3999#if X_BYTE_ORDER == X_BIG_ENDIAN
4000 	/* TODO : find a better way to do this */
4001 	if (pScrn->depth == 24) {
4002 		int dummy ;
4003 		  /* Fixup RGB ordering in 24 BPP */
4004 			dummy = pScrn->offset.red ;
4005 			pScrn->offset.red = pScrn->offset.blue;
4006 			pScrn->offset.blue = dummy ;
4007
4008 			dummy = pScrn->mask.red ;
4009 			pScrn->mask.red = pScrn->mask.blue;
4010 			pScrn->mask.blue = dummy ;
4011 	}
4012#endif
4013
4014    if (pScrn->depth > 8) {
4015        /* Fixup RGB ordering */
4016        visual = pScreen->visuals + pScreen->numVisuals;
4017        while (--visual >= pScreen->visuals) {
4018	    if ((visual->class | DynamicClass) == DirectColor) {
4019		visual->offsetRed = pScrn->offset.red;
4020		visual->offsetGreen = pScrn->offset.green;
4021		visual->offsetBlue = pScrn->offset.blue;
4022		visual->redMask = pScrn->mask.red;
4023		visual->greenMask = pScrn->mask.green;
4024		visual->blueMask = pScrn->mask.blue;
4025	    }
4026	}
4027    }
4028
4029    /* must be after RGB ordering fixed */
4030    if (init_picture)
4031	fbPictureInit (pScreen, 0, 0);
4032
4033    xf86SetBlackWhitePixels(pScreen);
4034
4035    cPtr->BlockHandler = pScreen->BlockHandler;
4036    pScreen->BlockHandler = chipsBlockHandler;
4037
4038    if ( (pScrn->depth >= 8))
4039	CHIPSDGAInit(pScreen);
4040
4041    cPtr->HWCursorShown = FALSE;
4042
4043    if (!(cPtr->Flags & ChipsLinearSupport)) {
4044	miBankInfoPtr pBankInfo;
4045
4046	/* Setup the vga banking variables */
4047	pBankInfo = (miBankInfoPtr)xnfcalloc(sizeof(miBankInfoRec),1);
4048	if (pBankInfo == NULL)
4049	    return FALSE;
4050
4051#if defined(__arm__)
4052	cPtr->Bank = -1;
4053#endif
4054	pBankInfo->pBankA = hwp->Base;
4055	pBankInfo->pBankB = (unsigned char *)hwp->Base + 0x08000;
4056	pBankInfo->BankSize = 0x08000;
4057	pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth;
4058
4059	if (IS_HiQV(cPtr)) {
4060	    pBankInfo->pBankB = hwp->Base;
4061	    pBankInfo->BankSize = 0x10000;
4062	    if (pScrn->bitsPerPixel < 8) {
4063		pBankInfo->SetSourceBank =
4064			(miBankProcPtr)CHIPSHiQVSetReadWritePlanar;
4065		pBankInfo->SetDestinationBank =
4066			(miBankProcPtr)CHIPSHiQVSetReadWritePlanar;
4067		pBankInfo->SetSourceAndDestinationBanks =
4068			(miBankProcPtr)CHIPSHiQVSetReadWritePlanar;
4069	    } else {
4070		pBankInfo->SetSourceBank =
4071			(miBankProcPtr)CHIPSHiQVSetReadWrite;
4072		pBankInfo->SetDestinationBank =
4073			(miBankProcPtr)CHIPSHiQVSetReadWrite;
4074		pBankInfo->SetSourceAndDestinationBanks =
4075			(miBankProcPtr)CHIPSHiQVSetReadWrite;
4076	    }
4077	} else {
4078	    if (IS_Wingine(cPtr)) {
4079		if (pScrn->bitsPerPixel < 8) {
4080		    pBankInfo->SetSourceBank =
4081			    (miBankProcPtr)CHIPSWINSetReadPlanar;
4082		    pBankInfo->SetDestinationBank =
4083			    (miBankProcPtr)CHIPSWINSetWritePlanar;
4084		    pBankInfo->SetSourceAndDestinationBanks =
4085			    (miBankProcPtr)CHIPSWINSetReadWritePlanar;
4086		} else {
4087		    pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSWINSetRead;
4088		    pBankInfo->SetDestinationBank =
4089			    (miBankProcPtr)CHIPSWINSetWrite;
4090		    pBankInfo->SetSourceAndDestinationBanks =
4091			    (miBankProcPtr)CHIPSWINSetReadWrite;
4092		}
4093	    } else {
4094		if (pScrn->bitsPerPixel < 8) {
4095		    pBankInfo->SetSourceBank =
4096			    (miBankProcPtr)CHIPSSetReadPlanar;
4097		    pBankInfo->SetDestinationBank =
4098			    (miBankProcPtr)CHIPSSetWritePlanar;
4099		    pBankInfo->SetSourceAndDestinationBanks =
4100			    (miBankProcPtr)CHIPSSetReadWritePlanar;
4101		} else {
4102		    pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSSetRead;
4103		    pBankInfo->SetDestinationBank =
4104			    (miBankProcPtr)CHIPSSetWrite;
4105		    pBankInfo->SetSourceAndDestinationBanks =
4106			    (miBankProcPtr)CHIPSSetReadWrite;
4107		}
4108	    }
4109	}
4110	if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY,
4111				 pScrn->displayWidth, pBankInfo)) {
4112	    xfree(pBankInfo);
4113	    pBankInfo = NULL;
4114	    return FALSE;
4115	}
4116	miInitializeBackingStore(pScreen);
4117	xf86SetBackingStore(pScreen);
4118
4119	/* Initialise cursor functions */
4120	miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
4121
4122    } else {
4123    /* !!! Only support linear addressing for now. This might change */
4124	/* Setup pointers to free space in video ram */
4125#define CHIPSALIGN(size, align) (currentaddr - ((currentaddr - size) & ~align))
4126	allocatebase = (pScrn->videoRam<<10) - cPtr->FrameBufferSize;
4127
4128	if (pScrn->bitsPerPixel < 8)
4129	    freespace = allocatebase - pScrn->displayWidth *
4130		    pScrn->virtualY / 2;
4131	else if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16))
4132	    freespace = allocatebase - pScrn->displayWidth *
4133		    pScrn->virtualY - cPtr->FbSize16;
4134	else
4135	    freespace = allocatebase - pScrn->displayWidth *
4136		    pScrn->virtualY * (pScrn->bitsPerPixel >> 3);
4137
4138	if ((cPtr->Flags & ChipsDualChannelSupport) &&
4139	    (cPtr->SecondCrtc == TRUE)) {
4140	    currentaddr = allocatebase + cPtrEnt->masterFbMapSize;
4141	} else
4142	    currentaddr = allocatebase;
4143	if (serverGeneration == 1)
4144	    xf86DrvMsg(scrnIndex, X_PROBED,
4145		   "%d bytes off-screen memory available\n", freespace);
4146
4147	/*
4148	 * Allocate video memory to store the hardware cursor. Allocate 1kB
4149	 * vram to the cursor, with 1kB alignment for 6554x's and 4kb alignment
4150	 * for 65550's. Wingine cursor is stored in registers and so no memory
4151	 * is needed.
4152	 */
4153	if (cAcl->UseHWCursor) {
4154	    cAcl->CursorAddress = -1;
4155	    if (IS_HiQV(cPtr)) {
4156		if (CHIPSALIGN(1024, 0xFFF) <= freespace) {
4157		    currentaddr -= CHIPSALIGN(1024, 0xFFF);
4158		    freespace -= CHIPSALIGN(1024, 0xFFF);
4159		    cAcl->CursorAddress = currentaddr;
4160		}
4161	    } else if (IS_Wingine(cPtr)) {
4162		cAcl->CursorAddress = 0;
4163	    } else if (CHIPSALIGN(1024, 0x3FF) <= freespace) {
4164		currentaddr -= CHIPSALIGN(1024, 0x3FF);
4165		freespace -= CHIPSALIGN(1024, 0x3FF);
4166		cAcl->CursorAddress = currentaddr;
4167	    }
4168	    if (cAcl->CursorAddress == -1)
4169		xf86DrvMsg(scrnIndex, X_ERROR,
4170		       "Too little space for H/W cursor.\n");
4171	}
4172
4173	cAcl->CacheEnd = currentaddr;
4174
4175	/* Setup the acceleration primitives */
4176	/* Calculate space needed of offscreen pixmaps etc. */
4177	if (cPtr->Flags & ChipsAccelSupport) {
4178	    /*
4179	     * A scratch area is now allocated in the video ram. This is used
4180	     * at 8 and 16 bpp to simulate a planemask with a complex ROP, and
4181	     * at 24 and 32 bpp to aid in accelerating solid fills
4182	     */
4183	    cAcl->ScratchAddress = -1;
4184	    switch  (pScrn->bitsPerPixel) {
4185	    case 8:
4186		if (CHIPSALIGN(64, 0x3F) <= freespace) {
4187		    currentaddr -= CHIPSALIGN(64, 0x3F);
4188		    freespace -= CHIPSALIGN(64, 0x3F);
4189		    cAcl->ScratchAddress = currentaddr;
4190		}
4191		break;
4192	    case 16:
4193		if (CHIPSALIGN(128, 0x7F) <= freespace) {
4194		    currentaddr -= CHIPSALIGN(128, 0x7F);
4195		    freespace -= CHIPSALIGN(128, 0x7F);
4196		    cAcl->ScratchAddress = currentaddr;
4197		}
4198		break;
4199	    case 24:
4200		/* One scanline of data used for solid fill */
4201		if (!IS_HiQV(cPtr)) {
4202		    if (CHIPSALIGN(3 * (pScrn->displayWidth + 4), 0x3)
4203			<= freespace) {
4204			currentaddr -= CHIPSALIGN(3 * (pScrn->displayWidth
4205					       + 4), 0x3);
4206			freespace -= CHIPSALIGN(3 * (pScrn->displayWidth + 4),
4207						0x3);
4208			cAcl->ScratchAddress = currentaddr;
4209		    }
4210		}
4211		break;
4212	    case 32:
4213		/* 16bpp 8x8 mono pattern fill for solid fill. QWORD aligned */
4214		if (IS_HiQV(cPtr)) {
4215		    if (CHIPSALIGN(8, 0x7) <= freespace) {
4216			currentaddr -= CHIPSALIGN(8, 0x7);
4217			freespace -= CHIPSALIGN(8, 0x7);
4218			cAcl->ScratchAddress = currentaddr;
4219		    }
4220		}
4221		break;
4222	    }
4223
4224	    /* Setup the boundaries of the pixmap cache */
4225	    cAcl->CacheStart = currentaddr - freespace;
4226	    cAcl->CacheEnd = currentaddr;
4227
4228	    if (cAcl->CacheStart >= cAcl->CacheEnd) {
4229		xf86DrvMsg(scrnIndex, X_ERROR,
4230		       "Too little space for pixmap cache.\n");
4231		cAcl->CacheStart = 0;
4232		cAcl->CacheEnd = 0;
4233	    }
4234
4235	    if (IS_HiQV(cPtr))
4236		cAcl->BltDataWindow = (unsigned char *)cPtr->MMIOBase
4237		    + 0x10000L;
4238	    else
4239		cAcl->BltDataWindow = cPtr->FbBase;
4240
4241	}
4242	/*
4243	 * Initialize FBManager:
4244	 * we do even with no acceleration enabled
4245	 * so that video support can allocate space.
4246	 */
4247
4248	{
4249	    BoxRec AvailFBArea;
4250	    AvailFBArea.x1 = 0;
4251	    AvailFBArea.y1 = 0;
4252	    AvailFBArea.x2 = pScrn->displayWidth;
4253	    AvailFBArea.y2 = cAcl->CacheEnd /
4254		(pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
4255
4256	    if (!(cPtr->Flags & ChipsOverlay8plus16)) {
4257		xf86InitFBManager(pScreen, &AvailFBArea);
4258	    }
4259	}
4260	if (cPtr->Flags & ChipsAccelSupport) {
4261	    if (IS_HiQV(cPtr)) {
4262		CHIPSHiQVAccelInit(pScreen);
4263	    } else if (cPtr->UseMMIO) {
4264		CHIPSMMIOAccelInit(pScreen);
4265	    } else {
4266		CHIPSAccelInit(pScreen);
4267	    }
4268	}
4269
4270	miInitializeBackingStore(pScreen);
4271	xf86SetBackingStore(pScreen);
4272#ifdef ENABLE_SILKEN_MOUSE
4273	xf86SetSilkenMouse(pScreen);
4274#endif
4275
4276	/* Initialise cursor functions */
4277	miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
4278
4279	if ((cAcl->UseHWCursor) && (cAcl->CursorAddress != -1)) {
4280	    /* HW cursor functions */
4281	    if (!CHIPSCursorInit(pScreen)) {
4282		xf86DrvMsg(scrnIndex, X_ERROR,
4283		       "Hardware cursor initialization failed\n");
4284		return FALSE;
4285	    }
4286	}
4287    }
4288
4289    if (cPtr->Flags & ChipsShadowFB) {
4290	RefreshAreaFuncPtr refreshArea = chipsRefreshArea;
4291
4292	if(cPtr->Rotate) {
4293	    if (!cPtr->PointerMoved) {
4294		cPtr->PointerMoved = pScrn->PointerMoved;
4295		pScrn->PointerMoved = chipsPointerMoved;
4296	    }
4297
4298	   switch(pScrn->bitsPerPixel) {
4299	   case 8:	refreshArea = chipsRefreshArea8;	break;
4300	   case 16:	refreshArea = chipsRefreshArea16;	break;
4301	   case 24:	refreshArea = chipsRefreshArea24;	break;
4302	   case 32:	refreshArea = chipsRefreshArea32;	break;
4303	   }
4304	}
4305	ShadowFBInit(pScreen, refreshArea);
4306    }
4307
4308    /* Initialise default colourmap */
4309    if (!miCreateDefColormap(pScreen))
4310	return FALSE;
4311
4312    if ((cPtr->Flags & ChipsOverlay8plus16) && (pScrn->bitsPerPixel == 16)) {
4313	if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, chipsLoadPalette,
4314		NULL, CMAP_RELOAD_ON_MODE_SWITCH))
4315	    return FALSE;
4316    } else {
4317	if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,
4318		(pScrn->depth == 16 ? chipsLoadPalette16 : chipsLoadPalette),
4319		NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
4320	    return FALSE;
4321    }
4322
4323#ifndef XSERVER_LIBPCIACCESS
4324    racflag = RAC_COLORMAP;
4325    if (cAcl->UseHWCursor)
4326        racflag |= RAC_CURSOR;
4327    racflag |= (RAC_FB | RAC_VIEWPORT);
4328    /* XXX Check if I/O and Mem flags need to be the same. */
4329    pScrn->racIoFlags = pScrn->racMemFlags = racflag;
4330#endif
4331#ifdef ENABLE_SILKEN_MOUSE
4332	xf86SetSilkenMouse(pScreen);
4333#endif
4334
4335	if ((!(cPtr->Flags & ChipsOverlay8plus16))
4336	    && (cPtr->Flags & ChipsVideoSupport)
4337	    && (cPtr->Flags & ChipsLinearSupport)) {
4338	    CHIPSInitVideo(pScreen);
4339    }
4340
4341    pScreen->SaveScreen = CHIPSSaveScreen;
4342
4343    /* Setup DPMS mode */
4344    if (cPtr->Flags & ChipsDPMSSupport)
4345	xf86DPMSInit(pScreen, (DPMSSetProcPtr)chipsDisplayPowerManagementSet,
4346		     0);
4347
4348    /* Wrap the current CloseScreen function */
4349    cPtr->CloseScreen = pScreen->CloseScreen;
4350    pScreen->CloseScreen = CHIPSCloseScreen;
4351
4352    /* Report any unused options (only for the first generation) */
4353    if (serverGeneration == 1) {
4354	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
4355    }
4356
4357    return TRUE;
4358}
4359
4360/* Mandatory */
4361Bool
4362CHIPSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
4363{
4364    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4365    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4366    CHIPSEntPtr cPtrEnt;
4367
4368#ifdef DEBUG
4369    ErrorF("CHIPSSwitchMode\n");
4370#endif
4371    if (cPtr->UseDualChannel) {
4372        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
4373					       CHIPSEntityIndex)->ptr;
4374	DUALREOPEN;
4375    }
4376
4377    return chipsModeInit(xf86Screens[scrnIndex], mode);
4378}
4379
4380/* Mandatory */
4381void
4382CHIPSAdjustFrame(int scrnIndex, int x, int y, int flags)
4383{
4384    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4385    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4386    CHIPSEntPtr cPtrEnt;
4387
4388    int Base;
4389    vgaHWPtr hwp = VGAHWPTR(pScrn);
4390    unsigned char tmp;
4391
4392    if (xf86ReturnOptValBool(cPtr->Options, OPTION_SHOWCACHE, FALSE) && y) {
4393	int lastline = cPtr->FbMapSize /
4394		((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
4395	lastline -= pScrn->currentMode->VDisplay;
4396	y += pScrn->virtualY - 1;
4397        if (y > lastline) y = lastline;
4398    }
4399
4400    Base = y * pScrn->displayWidth + x;
4401
4402    /* calculate base bpp dep. */
4403    switch (pScrn->bitsPerPixel) {
4404    case 1:
4405    case 4:
4406	Base >>= 3;
4407	break;
4408    case 16:
4409	if (!(cPtr->Flags & ChipsOverlay8plus16))
4410	   Base >>= 1;
4411	else
4412	   Base >>= 2;
4413	break;
4414    case 24:
4415	if (!IS_HiQV(cPtr))
4416	    Base = (Base >> 2) * 3;
4417	else
4418	    Base = (Base >> 3) * 6;  /* 65550 seems to need 64bit alignment */
4419	break;
4420    case 32:
4421	break;
4422    default:			     /* 8bpp */
4423	Base >>= 2;
4424	break;
4425    }
4426
4427    if (cPtr->UseDualChannel) {
4428        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
4429					       CHIPSEntityIndex)->ptr;
4430	DUALREOPEN;
4431    }
4432
4433    /* write base to chip */
4434    /*
4435     * These are the generic starting address registers.
4436     */
4437    chipsFixResume(pScrn);
4438    hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8);
4439    hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
4440    if (IS_HiQV(cPtr)) {
4441	if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1)
4442	    hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80);
4443    } else {
4444	tmp = cPtr->readXR(cPtr, 0x0C);
4445	cPtr->writeXR(cPtr, 0x0C, ((Base & (IS_Wingine(cPtr) ? 0x0F0000 :
4446	     0x030000)) >> 16) | (tmp & 0xF8));
4447    }
4448
4449    if (cPtr->UseDualChannel &&
4450		(! xf86IsEntityShared(pScrn->entityList[0]))) {
4451	unsigned int IOSS, MSS;
4452	IOSS = cPtr->readIOSS(cPtr);
4453	MSS = cPtr->readMSS(cPtr);
4454	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
4455			       IOSS_PIPE_B));
4456	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B));
4457
4458	chipsFixResume(pScrn);
4459	hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8);
4460	hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
4461	if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1)
4462	    hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80);
4463
4464	cPtr->writeIOSS(cPtr, IOSS);
4465	cPtr->writeMSS(cPtr, hwp, MSS);
4466    }
4467
4468    if (cPtr->Flags & ChipsOverlay8plus16) {
4469	Base = (Base << 3) & ~(unsigned long)0xF;
4470
4471	cPtr->writeMR(cPtr, 0x22, (cPtr->FbOffset16 + Base) & 0xF8);
4472	cPtr->writeMR(cPtr, 0x23, ((cPtr->FbOffset16 + Base) >> 8) & 0xFF);
4473	cPtr->writeMR(cPtr, 0x24, ((cPtr->FbOffset16 + Base) >> 16) & 0xFF);
4474    }
4475
4476}
4477
4478/* Mandatory */
4479static Bool
4480CHIPSCloseScreen(int scrnIndex, ScreenPtr pScreen)
4481{
4482    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4483    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4484    CHIPSEntPtr cPtrEnt;
4485
4486    if(pScrn->vtSema){   /*§§§*/
4487	if (cPtr->Flags & ChipsDualChannelSupport) {
4488  	    cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
4489					   CHIPSEntityIndex)->ptr;
4490	    if (cPtr->UseDualChannel)
4491		DUALREOPEN;
4492	    DUALCLOSE;
4493	} else {
4494	    chipsHWCursorOff(cPtr, pScrn);
4495	    chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg,
4496					TRUE);
4497	    chipsLock(pScrn);
4498	}
4499	chipsUnmapMem(pScrn);
4500    }
4501
4502    if (xf86IsEntityShared(pScrn->entityList[0])) {
4503	DevUnion *pPriv;
4504	pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex);
4505	cPtrEnt = pPriv->ptr;
4506	cPtrEnt->refCount--;
4507    }
4508    if (cPtr->AccelInfoRec)
4509	XAADestroyInfoRec(cPtr->AccelInfoRec);
4510    if (cPtr->CursorInfoRec)
4511	xf86DestroyCursorInfoRec(cPtr->CursorInfoRec);
4512    if (cPtr->ShadowPtr)
4513	xfree(cPtr->ShadowPtr);
4514    if (cPtr->DGAModes)
4515	xfree(cPtr->DGAModes);
4516    pScrn->vtSema = FALSE;
4517    if(cPtr->BlockHandler)
4518	pScreen->BlockHandler = cPtr->BlockHandler;
4519
4520    pScreen->CloseScreen = cPtr->CloseScreen; /*§§§*/
4521    xf86ClearPrimInitDone(pScrn->entityList[0]);
4522    return (*pScreen->CloseScreen)(scrnIndex, pScreen);/*§§§*/
4523}
4524
4525/* Optional */
4526static void
4527CHIPSFreeScreen(int scrnIndex, int flags)
4528{
4529    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
4530	vgaHWFreeHWRec(xf86Screens[scrnIndex]);
4531    CHIPSFreeRec(xf86Screens[scrnIndex]);
4532}
4533
4534/* Optional */
4535static ModeStatus
4536CHIPSValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
4537{
4538    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4539    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4540
4541    if (flags & MODECHECK_FINAL) {
4542    /* Don't subtract FrambufferSize here as it should be subtracted already */
4543    if ((cPtr->Flags & ChipsOverlay8plus16)
4544      && ((pScrn->videoRam<<10) - pScrn->displayWidth * 3 * pScrn->virtualY
4545	  < 0))
4546	return MODE_MEM;
4547    }
4548    /* The tests here need to be expanded */
4549    if ((mode->Flags & V_INTERLACE) && (cPtr->PanelType & ChipsLCD))
4550	return MODE_NO_INTERLACE;
4551    if ((cPtr->PanelType & ChipsLCD)
4552	&& !xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)
4553	&& ((cPtr->PanelSize.HDisplay < mode->HDisplay)
4554	    || (cPtr->PanelSize.VDisplay < mode->VDisplay)))
4555      return MODE_PANEL;
4556
4557    return MODE_OK;
4558}
4559
4560/*
4561 * DPMS Control registers
4562 *
4563 * XR73 6554x and 64300 (what about 65535?)
4564 * XR61 6555x
4565 *    0   HSync Powerdown data
4566 *    1   HSync Select 1=Powerdown
4567 *    2   VSync Powerdown data
4568 *    3   VSync Select 1=Powerdown
4569 */
4570
4571static void
4572chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
4573			       int flags)
4574{
4575    vgaHWPtr hwp = VGAHWPTR(pScrn);
4576    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4577    CHIPSEntPtr cPtrEnt;
4578
4579    unsigned char dpmsreg, seqreg, lcdoff, tmp;
4580
4581    if (!pScrn->vtSema)
4582	return;
4583
4584    xf86EnableAccess(pScrn);
4585    switch (PowerManagementMode) {
4586    case DPMSModeOn:
4587	/* Screen: On; HSync: On, VSync: On */
4588	dpmsreg = 0x00;
4589	seqreg = 0x00;
4590	lcdoff = 0x0;
4591	break;
4592    case DPMSModeStandby:
4593	/* Screen: Off; HSync: Off, VSync: On */
4594	dpmsreg = 0x02;
4595	seqreg = 0x20;
4596	lcdoff = 0x0;
4597	break;
4598    case DPMSModeSuspend:
4599	/* Screen: Off; HSync: On, VSync: Off */
4600	dpmsreg = 0x08;
4601	seqreg = 0x20;
4602	lcdoff = 0x1;
4603	break;
4604    case DPMSModeOff:
4605	/* Screen: Off; HSync: Off, VSync: Off */
4606	dpmsreg = 0x0A;
4607	seqreg = 0x20;
4608	lcdoff = 0x1;
4609	break;
4610    default:
4611	return;
4612    }
4613
4614    if (cPtr->UseDualChannel) {
4615        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
4616					       CHIPSEntityIndex)->ptr;
4617	DUALREOPEN;
4618    }
4619
4620    seqreg |= hwp->readSeq(hwp, 0x01) & ~0x20;
4621    hwp->writeSeq(hwp, 0x01, seqreg);
4622    if (IS_HiQV(cPtr)) {
4623	tmp = cPtr->readXR(cPtr, 0x61);
4624	cPtr->writeXR(cPtr, 0x61, (tmp & 0xF0) | dpmsreg);
4625    } else {
4626	tmp = cPtr->readXR(cPtr, 0x73);
4627	cPtr->writeXR(cPtr, 0x73, (tmp & 0xF0) | dpmsreg);
4628    }
4629
4630    /* Turn off the flat panel */
4631    if (cPtr->PanelType & ChipsLCDProbed) {
4632	if (IS_HiQV(cPtr)) {
4633	    if (cPtr->Chipset == CHIPS_CT69030) {
4634#if 0
4635	        /* Where is this for the 69030?? */
4636		tmp = cPtr->readFR(cPtr, 0x05);
4637		if (lcdoff)
4638		    cPtr->writeFR(cPtr, 0x05, tmp | 0x08);
4639		else
4640		    cPtr->writeFR(cPtr, 0x05, tmp & 0xF7);
4641#endif
4642	    } else {
4643		tmp = cPtr->readFR(cPtr, 0x05);
4644		if (lcdoff)
4645		    cPtr->writeFR(cPtr, 0x05, tmp | 0x08);
4646		else
4647		    cPtr->writeFR(cPtr, 0x05, tmp & 0xF7);
4648	    }
4649	} else {
4650	    tmp = cPtr->readXR(cPtr, 0x52);
4651	    if (lcdoff)
4652		cPtr->writeXR(cPtr, 0x52, tmp | 0x08);
4653	    else
4654		cPtr->writeXR(cPtr, 0x52, tmp & 0xF7);
4655	}
4656    }
4657}
4658
4659static Bool
4660CHIPSSaveScreen(ScreenPtr pScreen, int mode)
4661{
4662    ScrnInfoPtr pScrn = NULL;            /* §§§ */
4663    Bool unblank;
4664
4665    unblank = xf86IsUnblank(mode);
4666
4667    if (pScreen != NULL)
4668	pScrn = xf86Screens[pScreen->myNum];
4669
4670    if (unblank)
4671	SetTimeSinceLastInputEvent();
4672
4673    if ((pScrn != NULL) && pScrn->vtSema) { /* §§§ */
4674	chipsBlankScreen(pScrn, unblank);
4675    }
4676    return (TRUE);
4677}
4678
4679static Bool
4680chipsClockSelect(ScrnInfoPtr pScrn, int no)
4681{
4682    CHIPSClockReg TmpClock;
4683    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4684
4685    switch (no) {
4686    case CLK_REG_SAVE:
4687	chipsClockSave(pScrn, &cPtr->SaveClock);
4688	break;
4689
4690    case CLK_REG_RESTORE:
4691	chipsClockLoad(pScrn, &cPtr->SaveClock);
4692	break;
4693
4694    default:
4695	if (!chipsClockFind(pScrn, NULL, no, &TmpClock))
4696	    return (FALSE);
4697	chipsClockLoad(pScrn, &TmpClock);
4698    }
4699    return (TRUE);
4700}
4701
4702/*
4703 *
4704 * Fout = (Fref * 4 * M) / (PSN * N * (1 << P) )
4705 * Fvco = (Fref * 4 * M) / (PSN * N)
4706 * where
4707 * M = XR31+2
4708 * N = XR32+2
4709 * P = XR30[3:1]
4710 * PSN = XR30[0]? 1:4
4711 *
4712 * constraints:
4713 * 4 MHz <= Fref <= 20 MHz (typ. 14.31818 MHz)
4714 * 150 kHz <= Fref/(PSN * N) <= 2 MHz
4715 * 48 MHz <= Fvco <= 220 MHz
4716 * 2 < M < 128
4717 * 2 < N < 128
4718 */
4719
4720static void
4721chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock)
4722{
4723    unsigned char tmp;
4724    vgaHWPtr hwp = VGAHWPTR(pScrn);
4725    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4726    unsigned char Type = cPtr->ClockType;
4727    CHIPSEntPtr cPtrEnt;
4728
4729    Clock->msr = hwp->readMiscOut(hwp)&0xFE; /* save standard VGA clock reg */
4730    switch (Type & GET_STYLE) {
4731    case HiQV_STYLE:
4732	/* save alternate clock select reg.*/
4733	/* The 69030 FP clock select is at FR01 instead */
4734      if (cPtr->UseDualChannel) {
4735        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
4736					       CHIPSEntityIndex)->ptr;
4737	DUALREOPEN;
4738      }
4739
4740	if (cPtr->Flags & ChipsDualChannelSupport)
4741	    Clock->fr03 = cPtr->readFR(cPtr, 0x01);
4742	else
4743	    Clock->fr03 = cPtr->readFR(cPtr, 0x03);
4744	if (!Clock->Clock) {   /* save HiQV console clock           */
4745	    tmp = cPtr->CRTclkInx << 2;
4746	    cPtr->CRTClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp);
4747	    cPtr->CRTClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp);
4748	    cPtr->CRTClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp);
4749	    cPtr->CRTClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp);
4750	    tmp = cPtr->FPclkInx << 2;
4751	    cPtr->FPClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp);
4752	    cPtr->FPClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp);
4753	    cPtr->FPClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp);
4754	    cPtr->FPClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp);
4755	}
4756	break;
4757    case OLD_STYLE:
4758	Clock->fcr = hwp->readFCR(hwp);
4759	Clock->xr02 = cPtr->readXR(cPtr, 0x02);
4760	Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/
4761	break;
4762    case WINGINE_1_STYLE:
4763    case WINGINE_2_STYLE:
4764	break;
4765    case NEW_STYLE:
4766	Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/
4767	Clock->xr33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK sel reg.*/
4768	break;
4769    }
4770#ifdef DEBUG
4771    ErrorF("saved \n");
4772#endif
4773}
4774
4775static Bool
4776chipsClockFind(ScrnInfoPtr pScrn, DisplayModePtr mode,
4777	       int no, CHIPSClockPtr Clock )
4778{
4779    vgaHWPtr hwp = VGAHWPTR(pScrn);
4780    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4781    unsigned char Type = cPtr->ClockType;
4782    CHIPSEntPtr cPtrEnt;
4783
4784    if (no > (pScrn->numClocks - 1))
4785	return (FALSE);
4786
4787    if (cPtr->UseDualChannel) {
4788        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
4789					       CHIPSEntityIndex)->ptr;
4790	DUALREOPEN;
4791    }
4792
4793    switch (Type & GET_STYLE) {
4794    case HiQV_STYLE:
4795	Clock->msr = cPtr->CRTclkInx << 2;
4796	Clock->fr03 = cPtr->FPclkInx << 2;
4797	Clock->Clock = mode ? mode->Clock : 0;
4798	if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) {
4799	    Clock->FPClock = mode ? mode->Clock : 0;
4800	} else
4801	    Clock->FPClock = cPtr->FPclock;
4802	break;
4803    case NEW_STYLE:
4804	if (Type & TYPE_HW) {
4805	    Clock->msr = (no == 4 ? 3 << 2: (no & 0x01) << 2);
4806	    Clock->xr54 = Clock->msr;
4807	    Clock->xr33 = no > 1 ? 0x80 : 0;
4808	} else {
4809	    Clock->msr = 3 << 2;
4810	    Clock->xr33 = 0;
4811	    Clock->xr54 = Clock->msr;
4812	    /* update panel type in case somebody switched.
4813	     * This should be handled more generally:
4814	     * On mode switch DDC should be reread, all
4815	     * display dependent data should be reevaluated.
4816	     * This will be built in when we start Display
4817	     * HotPlug support.
4818	     * Until then we have to do it here as somebody
4819	     * might have switched displays on us and we only
4820	     * have one programmable clock which needs to
4821	     * be shared for CRT and LCD.
4822	     */
4823	    chipsSetPanelType(cPtr);
4824	    {
4825	      Bool fp_m;
4826	      if (cPtr->Options
4827		  && xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_m)) {
4828		   if (fp_m)
4829		       cPtr->PanelType |= ChipsLCD;
4830		   else
4831		       cPtr->PanelType = ~ChipsLCD;
4832	      }
4833	    }
4834
4835	    if ((cPtr->PanelType & ChipsLCD) && cPtr->FPclock)
4836		Clock->Clock = cPtr->FPclock;
4837	    else
4838		Clock->Clock = mode ? mode->SynthClock : 0;
4839	}
4840	break;
4841    case OLD_STYLE:
4842	if (no > 3) {
4843	    Clock->msr = 3 << 2;
4844	    Clock->fcr = no & 0x03;
4845	    Clock->xr02 = 0;
4846	    Clock->xr54 = Clock->msr & (Clock->fcr << 4);
4847	} else {
4848	    Clock->msr = (no << 2) & 0x4;
4849	    Clock->fcr = 0;
4850	    Clock->xr02 = no & 0x02;
4851	    Clock->xr54 = Clock->msr;
4852	}
4853	break;
4854    case WINGINE_1_STYLE:
4855	Clock->msr = no << 2;
4856    case WINGINE_2_STYLE:
4857	if (Type & TYPE_HW) {
4858	    Clock->msr = (no == 2 ? 3 << 2: (no & 0x01) << 2);
4859	    Clock->xr33 = 0;
4860	} else {
4861	    Clock->msr = 3 << 2;
4862	    Clock->xr33 = 0;
4863	    Clock->Clock = mode ? mode->SynthClock : 0;
4864	}
4865	break;
4866    }
4867    Clock->msr |= (hwp->readMiscOut(hwp) & 0xF2);
4868
4869#ifdef DEBUG
4870    ErrorF("found\n");
4871#endif
4872    return (TRUE);
4873}
4874
4875
4876static int
4877chipsGetHWClock(ScrnInfoPtr pScrn)
4878{
4879    vgaHWPtr hwp = VGAHWPTR(pScrn);
4880    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4881    unsigned char Type = cPtr->ClockType;
4882    unsigned char tmp, tmp1;
4883
4884    if (!(Type & TYPE_HW))
4885        return 0;		/* shouldn't happen                   */
4886
4887    switch (Type & GET_STYLE) {
4888    case WINGINE_1_STYLE:
4889	return ((hwp->readMiscOut(hwp) & 0x0C) >> 2);
4890    case WINGINE_2_STYLE:
4891	tmp = ((hwp->readMiscOut(hwp) & 0x04) >> 2);
4892	return (tmp > 2) ? 2 : tmp;
4893    case OLD_STYLE:
4894	if (!(cPtr->PanelType & ChipsLCDProbed))
4895	    tmp = hwp->readMiscOut(hwp);
4896	else
4897	    tmp = cPtr->readXR(cPtr, 0x54);
4898	if (tmp & 0x08) {
4899	    if (!(cPtr->PanelType & ChipsLCDProbed))
4900		tmp = hwp->readFCR(hwp) & 0x03;
4901	    else
4902		tmp = (tmp >> 4) & 0x03;
4903	    return (tmp + 4);
4904	} else {
4905	    tmp = (tmp >> 2) & 0x01;
4906	    tmp1 = cPtr->readXR(cPtr, 0x02);
4907	    return (tmp + (tmp1 & 0x02));
4908	}
4909    case NEW_STYLE:
4910	if (cPtr->PanelType & ChipsLCDProbed) {
4911	    tmp = cPtr->readXR(cPtr, 0x54);
4912	} else
4913	    tmp = hwp->readMiscOut(hwp);
4914	tmp = (tmp & 0x0C) >> 2;
4915	if (tmp > 1) return 4;
4916	tmp1 = cPtr->readXR(cPtr, 0x33);
4917	tmp1 = (tmp1 & 0x80) >> 6; /* iso mode 25.175/28.322 or 32/36 MHz  */
4918	return (tmp + tmp1);       /*            ^=0    ^=1     ^=4 ^=5    */
4919    default:		       /* we should never get here              */
4920	return (0);
4921    }
4922}
4923
4924static void
4925chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock)
4926{
4927    vgaHWPtr hwp = VGAHWPTR(pScrn);
4928    CHIPSPtr cPtr = CHIPSPTR(pScrn);
4929    unsigned char Type = cPtr->ClockType;
4930    volatile unsigned char tmp, tmpmsr, tmpfcr, tmp02;
4931    volatile unsigned char tmp33, tmp54, tmpf03;
4932    unsigned char vclk[3];
4933
4934    tmpmsr = hwp->readMiscOut(hwp);  /* read msr, needed for all styles */
4935
4936    switch (Type & GET_STYLE) {
4937    case HiQV_STYLE:
4938	/* save alternate clock select reg.  */
4939	/* The 69030 FP clock select is at FR01 instead */
4940	if (cPtr->Flags & ChipsDualChannelSupport) {
4941	    tmpf03 = cPtr->readFR(cPtr, 0x01);
4942	} else
4943	    tmpf03 = cPtr->readFR(cPtr, 0x03);
4944	/* select fixed clock 0  before tampering with VCLK select */
4945	hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) |
4946			   cPtr->SuspendHack.vgaIOBaseFlag);
4947	/* The 69030 FP clock select is at FR01 instead */
4948	if (cPtr->Flags & ChipsDualChannelSupport) {
4949	    cPtr->writeFR(cPtr, 0x01, (tmpf03 & ~0x0C) | 0x04);
4950	} else
4951	    cPtr->writeFR(cPtr, 0x03, (tmpf03 & ~0x0C) | 0x04);
4952	if (!Clock->Clock) {      /* Hack to load saved console clock  */
4953	    tmp = cPtr->CRTclkInx << 2;
4954	    cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->CRTClk[0] & 0xFF));
4955	    cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->CRTClk[1] & 0xFF));
4956	    cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->CRTClk[2] & 0xFF));
4957	    cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->CRTClk[3] & 0xFF));
4958
4959	    if (cPtr->FPClkModified) {
4960	        usleep(10000); /* let VCO stabilize */
4961	        tmp = cPtr->FPclkInx << 2;
4962		cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->FPClk[0] & 0xFF));
4963		cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->FPClk[1] & 0xFF));
4964		cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->FPClk[2] & 0xFF));
4965		cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->FPClk[3] & 0xFF));
4966	    }
4967	} else {
4968	    /*
4969	     * Don't use the extra 2 bits in the M, N registers available
4970	     * on the HiQV, so write zero to 0xCA
4971	     */
4972	    chipsCalcClock(pScrn, Clock->Clock, vclk);
4973	    tmp = cPtr->CRTclkInx << 2;
4974	    cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF));
4975	    cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF));
4976	    cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0);
4977	    cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF));
4978	    if (Clock->FPClock) {
4979	        usleep(10000); /* let VCO stabilize */
4980    	        chipsCalcClock(pScrn, Clock->FPClock, vclk);
4981	        tmp = cPtr->FPclkInx << 2;
4982		cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF));
4983		cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF));
4984		cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0);
4985		cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF));
4986		cPtr->FPClkModified = TRUE;
4987	    }
4988	}
4989	usleep(10000);		         /* Let VCO stabilise    */
4990	/* The 69030 FP clock select is at FR01 instead */
4991	if (cPtr->Flags & ChipsDualChannelSupport) {
4992	    cPtr->writeFR(cPtr, 0x01, ((tmpf03 & ~0x0C) |
4993			(Clock->fr03 & 0x0C)));
4994	} else
4995	    cPtr->writeFR(cPtr, 0x03, ((tmpf03 & ~0x0C) |
4996			(Clock->fr03 & 0x0C)));
4997	break;
4998    case WINGINE_1_STYLE:
4999	break;
5000    case WINGINE_2_STYLE:
5001	/* Only write to soft clock registers if we really need to */
5002	if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) {
5003	    /* select fixed clock 0  before tampering with VCLK select */
5004	    hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) |
5005			       cPtr->SuspendHack.vgaIOBaseFlag);
5006	    chipsCalcClock(pScrn, Clock->Clock, vclk);
5007	    tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */
5008	    cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);
5009	    cPtr->writeXR(cPtr, 0x30, vclk[0]);
5010	    cPtr->writeXR(cPtr, 0x31, vclk[1]);     /* restore VCLK regs.   */
5011	    cPtr->writeXR(cPtr, 0x32, vclk[2]);
5012	    /*  cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/
5013	    usleep(10000);		     /* Let VCO stabilise    */
5014	}
5015	break;
5016    case OLD_STYLE:
5017	tmp02 = cPtr->readXR(cPtr, 0x02);
5018	tmp54 = cPtr->readXR(cPtr, 0x54);
5019	tmpfcr = hwp->readFCR(hwp);
5020	cPtr->writeXR(cPtr, 0x02, ((tmp02 & ~0x02) | (Clock->xr02 & 0x02)));
5021	cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF0) | (Clock->xr54 & ~0xF0)));
5022	hwp->writeFCR(hwp, (tmpfcr & ~0x03) & Clock->fcr);
5023	break;
5024    case NEW_STYLE:
5025	tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */
5026	tmp54 = cPtr->readXR(cPtr, 0x54);
5027	/* Only write to soft clock registers if we really need to */
5028	if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) {
5029	    /* select fixed clock 0  before tampering with VCLK select */
5030	    hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) |
5031			   cPtr->SuspendHack.vgaIOBaseFlag);
5032	    cPtr->writeXR(cPtr, 0x54, (tmp54 & 0xF3));
5033	    /* if user wants to set the memory clock, do it first */
5034	    if (cPtr->MemClock.Clk) {
5035		chipsCalcClock(pScrn, cPtr->MemClock.Clk, vclk);
5036		/* close eyes, hold breath ....*/
5037		cPtr->writeXR(cPtr, 0x33, tmp33 | 0x20);
5038		cPtr->writeXR(cPtr, 0x30, vclk[0]);
5039		cPtr->writeXR(cPtr, 0x31, vclk[1]);
5040		cPtr->writeXR(cPtr, 0x32, vclk[2]);
5041		usleep(10000);
5042	    }
5043	    chipsCalcClock(pScrn, Clock->Clock, vclk);
5044	    cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);
5045	    cPtr->writeXR(cPtr, 0x30, vclk[0]);
5046	    cPtr->writeXR(cPtr, 0x31, vclk[1]);     /* restore VCLK regs.   */
5047	    cPtr->writeXR(cPtr, 0x32, vclk[2]);
5048	    /*  cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/
5049	    usleep(10000);		         /* Let VCO stabilise    */
5050	}
5051	cPtr->writeXR(cPtr, 0x33, ((tmp33 & ~0x80) | (Clock->xr33 & 0x80)));
5052	cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF3) | (Clock->xr54 & ~0xF3)));
5053	break;
5054    }
5055    hwp->writeMiscOut(hwp, (Clock->msr & 0xFE) |
5056			   cPtr->SuspendHack.vgaIOBaseFlag);
5057#ifdef DEBUG
5058    ErrorF("restored\n");
5059#endif
5060}
5061
5062/*
5063 * This is Ken Raeburn's <raeburn@raeburn.org> clock
5064 * calculation code just modified a little bit to fit in here.
5065 */
5066
5067static void
5068chipsCalcClock(ScrnInfoPtr pScrn, int Clock, unsigned char *vclk)
5069{
5070    CHIPSPtr cPtr = CHIPSPTR(pScrn);
5071    int M, N, P = 0, PSN = 0, PSNx = 0;
5072
5073    int bestM = 0, bestN = 0, bestP = 0, bestPSN = 0;
5074    double abest = 42;
5075#ifdef DEBUG
5076    double bestFout = 0;
5077#endif
5078    double target;
5079
5080    double Fvco, Fout;
5081    double error, aerror;
5082
5083    int M_min = 3;
5084
5085    /* Hack to deal with problem of Toshiba 720CDT clock */
5086    int M_max = (IS_HiQV(cPtr) && cPtr->Chipset != CHIPS_CT69000 &&
5087				   cPtr->Chipset != CHIPS_CT69030) ? 63 : 127;
5088
5089    /* @@@ < CHIPS_CT690x0 ?? */
5090
5091    /* Other parameters available on the 65548 but not the 65545, and
5092     * not documented in the Clock Synthesizer doc in rev 1.0 of the
5093     * 65548 datasheet:
5094     *
5095     * + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545)
5096     * 1, VCO divider loop uses divide by 16
5097     *
5098     * + XR30[5] = 1, reference clock is divided by 5
5099     *
5100     * Other parameters available on the 65550 and not on the 65545
5101     *
5102     * + XRCB[2] = 0, VCO divider loop uses divide by 4 (same as 65545)
5103     * 1, VCO divider loop uses divide by 16
5104     *
5105     * + XRCB[1] = 1, reference clock is divided by 5
5106     *
5107     * + XRCB[7] = Vclk = Mclk
5108     *
5109     * + XRCA[0:1] = 2 MSB of a 10 bit M-Divisor
5110     *
5111     * + XRCA[4:5] = 2 MSB of a 10 bit N-Divisor
5112     *
5113     * I haven't put in any support for those here.  For simplicity,
5114     * they should be set to 0 on the 65548, and left untouched on
5115     * earlier chips.
5116     *
5117     * Other parameters available on the 690x0
5118     *
5119     * + The 690x0 has no reference clock divider, so PSN must
5120     *   always be 1.
5121     *   XRCB[0:1] are reserved according to the data book
5122     */
5123
5124
5125    target = Clock * 1000;
5126
5127    /* @@@ >= CHIPS_CT690x0 ?? */
5128    for (PSNx = ((cPtr->Chipset == CHIPS_CT69000) ||
5129		 (cPtr->Chipset == CHIPS_CT69030)) ? 1 : 0; PSNx <= 1; PSNx++) {
5130	int low_N, high_N;
5131	double Fref4PSN;
5132
5133	PSN = PSNx ? 1 : 4;
5134
5135	low_N = 3;
5136	high_N = 127;
5137
5138	while (Fref / (PSN * low_N) > (((cPtr->Chipset == CHIPS_CT69000) ||
5139					(cPtr->Chipset == CHIPS_CT69030)) ? 5.0e6 : 2.0e6))
5140	    low_N++;
5141	while (Fref / (PSN * high_N) < 150.0e3)
5142	    high_N--;
5143
5144	Fref4PSN = Fref * 4 / PSN;
5145	for (N = low_N; N <= high_N; N++) {
5146	    double tmp = Fref4PSN / N;
5147
5148	    /* @@@ < CHIPS_CT690x0 ?? */
5149	    for (P = (IS_HiQV(cPtr) && (cPtr->Chipset != CHIPS_CT69000) &&
5150				(cPtr->Chipset != CHIPS_CT69030)) ? 1 : 0;
5151		 P <= 5; P++) {
5152	        /* to force post divisor on Toshiba 720CDT */
5153		double Fvco_desired = target * (1 << P);
5154		double M_desired = Fvco_desired / tmp;
5155
5156		/* Which way will M_desired be rounded?  Do all three just to
5157		 * be safe.  */
5158		int M_low = M_desired - 1;
5159		int M_hi = M_desired + 1;
5160
5161		if (M_hi < M_min || M_low > M_max)
5162		    continue;
5163
5164		if (M_low < M_min)
5165		    M_low = M_min;
5166		if (M_hi > M_max)
5167		    M_hi = M_max;
5168
5169		for (M = M_low; M <= M_hi; M++) {
5170		    Fvco = tmp * M;
5171		    /* @@@ >= CHIPS_CT690x0 ?? */
5172		    if (Fvco <= ((cPtr->Chipset == CHIPS_CT69000 ||
5173			cPtr->Chipset == CHIPS_CT69030) ? 100.0e6 : 48.0e6))
5174			continue;
5175		    if (Fvco > 220.0e6)
5176			break;
5177
5178		    Fout = Fvco / (1 << P);
5179
5180		    error = (target - Fout) / target;
5181
5182		    aerror = (error < 0) ? -error : error;
5183		    if (aerror < abest) {
5184			abest = aerror;
5185			bestM = M;
5186			bestN = N;
5187			bestP = P;
5188			bestPSN = PSN;
5189#ifdef DEBUG
5190			bestFout = Fout;
5191#endif
5192		    }
5193		}
5194	    }
5195	}
5196    }
5197    /* @@@ >= CHIPS_CT690x0 ?? */
5198    vclk[0] = (bestP << (IS_HiQV(cPtr) ? 4 : 1)) +
5199	(((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030))
5200	? 0 : (bestPSN == 1));
5201    vclk[1] = bestM - 2;
5202    vclk[2] = bestN - 2;
5203#ifdef DEBUG
5204    ErrorF("Freq. selected: %.2f MHz, vclk[0]=%X, vclk[1]=%X, vclk[2]=%X\n",
5205	(float)(Clock / 1000.), vclk[0], vclk[1], vclk[2]);
5206    ErrorF("Freq. set: %.2f MHz\n", bestFout / 1.0e6);
5207#endif
5208}
5209
5210static void
5211chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, CHIPSRegPtr ChipsSave)
5212{
5213    vgaHWPtr hwp = VGAHWPTR(pScrn);
5214    CHIPSPtr cPtr = CHIPSPTR(pScrn);
5215    int i;
5216    unsigned char tmp;
5217#ifdef DEBUG
5218    ErrorF("chipsSave\n");
5219#endif
5220
5221    /* set registers that we can program the controller */
5222    /* bank 0 */
5223    if (IS_HiQV(cPtr)) {
5224	cPtr->writeXR(cPtr, 0x0E, 0x00);
5225    } else {
5226	cPtr->writeXR(cPtr, 0x10, 0x00);
5227	cPtr->writeXR(cPtr, 0x11, 0x00);
5228	tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */
5229	cPtr->writeXR(cPtr, 0x0C, tmp);
5230    }
5231    chipsFixResume(pScrn);
5232    tmp = cPtr->readXR(cPtr, 0x02);
5233    cPtr->writeXR(cPtr, 0x02, tmp & ~0x18);
5234    /* get generic registers */
5235    vgaHWSave(pScrn, VgaSave, VGA_SR_ALL);
5236
5237    /* save clock */
5238    chipsClockSave(pScrn, &ChipsSave->Clock);
5239
5240    /* save extended registers */
5241    if (IS_HiQV(cPtr)) {
5242	for (i = 0; i < 0xFF; i++) {
5243#ifdef SAR04
5244	    /* Save SAR04 multimedia register correctly */
5245	    if (i == 0x4F)
5246	        cPtr->writeXR(cPtr, 0x4E, 0x04);
5247#endif
5248	    ChipsSave->XR[i] = cPtr->readXR(cPtr,i);
5249#ifdef DEBUG
5250	    ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]);
5251#endif
5252	}
5253	for (i = 0; i < 0x80; i++) {
5254	    ChipsSave->FR[i] = cPtr->readFR(cPtr, i);
5255#ifdef DEBUG
5256	    ErrorF("FS%X - %X\n", i, ChipsSave->FR[i]);
5257#endif
5258	}
5259	for (i = 0; i < 0x80; i++) {
5260		ChipsSave->MR[i] = cPtr->readMR(cPtr, i);
5261#ifdef DEBUG
5262	    ErrorF("MS%X - %X\n", i, ChipsSave->FR[i]);
5263#endif
5264	}
5265	/* Save CR0-CR40 even though we don't use them, so they can be
5266	 *  printed */
5267	for (i = 0x0; i < 0x80; i++) {
5268	    ChipsSave->CR[i] = hwp->readCrtc(hwp, i);
5269#ifdef DEBUG
5270	    ErrorF("CS%X - %X\n", i, ChipsSave->CR[i]);
5271#endif
5272	}
5273    } else {
5274	for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */
5275	    ChipsSave->XR[i] = cPtr->readXR(cPtr, i);
5276#ifdef DEBUG
5277	    ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]);
5278#endif
5279	}
5280    }
5281}
5282
5283Bool
5284chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
5285{
5286    CHIPSPtr cPtr = CHIPSPTR(pScrn);
5287#ifdef DEBUG
5288    ErrorF("chipsModeInit\n");
5289#endif
5290#if 0
5291    *(int*)0xFFFFFF0 = 0;
5292    ErrorF("done\n");
5293#endif
5294
5295    chipsUnlock(pScrn);
5296    chipsFixResume(pScrn);
5297
5298    if (cPtr->Accel.UseHWCursor)
5299	cPtr->Flags |= ChipsHWCursor;
5300    else
5301	cPtr->Flags &= ~ChipsHWCursor;
5302    /*
5303     * We need to delay cursor loading after resetting the video mode
5304     * to give the engine a chance to recover.
5305     */
5306    cPtr->cursorDelay = TRUE;
5307
5308    if (IS_HiQV(cPtr))
5309	return chipsModeInitHiQV(pScrn, mode);
5310    else if (IS_Wingine(cPtr))
5311        return chipsModeInitWingine(pScrn, mode);
5312    else
5313      return chipsModeInit655xx(pScrn, mode);
5314}
5315
5316/*
5317 * The timing register of the C&T FP chipsets are organized
5318 * as follows:
5319 * The chipsets have two sets of timing registers:
5320 * the standard horizontal and vertical timing registers for
5321 * display size, blank start, sync start, sync end, blank end
5322 * and total size at their default VGA locations and extensions
5323 * and the alternate horizontal and vertical timing registers for
5324 * display size, sync start, sync end and total size.
5325 * In LCD and mixed (LCD+CRT) mode the alternate timing registers
5326 * control the timing. The alternate horizontal and vertical display
5327 * size registers are set to the physical pixel size of the display.
5328 * Normally the alternalte registers are set by the BIOS to optimized
5329 * values.
5330 * While the horizontal an vertical refresh rates are fixed independent
5331 * of the visible display size to ensure optimal performace of both
5332 * displays they can be adapted to the screen resolution and CRT
5333 * requirements in CRT mode by programming the standard timing registers
5334 * in the VGA fashion.
5335 * In LCD and mixed mode the _standard_ horizontal and vertical display
5336 * size registers control the size of the _visible_ part of the display
5337 * in contast to the _physical_ size of the display which is specified
5338 * by the _alternate_ horizontal and vertical display size registers.
5339 * The size of the visible should always be equal or less than the
5340 * physical size.
5341 * For the 69030 chipsets, the CRT and LCD display channels are seperate
5342 * and so can be driven independently.
5343 */
5344static Bool
5345chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode)
5346{
5347    int i;
5348    int lcdHTotal, lcdHDisplay;
5349    int lcdVTotal, lcdVDisplay;
5350    int lcdHRetraceStart, lcdHRetraceEnd;
5351    int lcdVRetraceStart, lcdVRetraceEnd;
5352    int lcdHSyncStart;
5353    vgaHWPtr hwp = VGAHWPTR(pScrn);
5354    CHIPSPtr cPtr = CHIPSPTR(pScrn);
5355    CHIPSRegPtr ChipsNew;
5356    vgaRegPtr ChipsStd;
5357    unsigned int tmp;
5358
5359    ChipsNew = &cPtr->ModeReg;
5360    ChipsStd = &hwp->ModeReg;
5361
5362
5363    /*
5364     * Possibly fix up the panel size, if the manufacture is stupid
5365     * enough to set it incorrectly in text modes
5366     */
5367    if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) {
5368	cPtr->PanelSize.HDisplay = mode->CrtcHDisplay;
5369	cPtr->PanelSize.VDisplay = mode->CrtcVDisplay;
5370    }
5371
5372    /* generic init */
5373    if (!vgaHWInit(pScrn, mode)) {
5374	ErrorF("bomb 1\n");
5375	return (FALSE);
5376    }
5377    pScrn->vtSema = TRUE;
5378
5379    /* init clock */
5380    if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) {
5381	ErrorF("bomb 2\n");
5382	return (FALSE);
5383    }
5384
5385    /* Give Warning if the dual display mode will cause problems */
5386    /* Note 64bit wide memory bus assumed (as in 69000 and 69030 */
5387    if (cPtr->UseDualChannel && ((cPtr->SecondCrtc == TRUE) ||
5388				 (cPtr->Flags & ChipsDualRefresh))) {
5389	if (((ChipsNew->Clock.FPClock + ChipsNew->Clock.Clock) *
5390		(max(1, pScrn->bitsPerPixel >> 3) +
5391		((cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) ?
5392		1 : 0)) / (8 * 0.7)) > cPtr->MemClock.Max) {
5393	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5394		"Memory bandwidth requirements exceeded by dual-channel\n");
5395	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5396		       "   mode. Display might be corrupted!!!\n");
5397	}
5398    }
5399
5400    /* get C&T Specific Registers */
5401    for (i = 0; i < 0xFF; i++) {
5402#ifdef SAR04
5403	/* Save SAR04 multimedia register correctly */
5404	if (i == 0x4F)
5405	    cPtr->writeXR(cPtr, 0x4E, 0x04);
5406#endif
5407	ChipsNew->XR[i] = cPtr->readXR(cPtr, i);
5408    }
5409    for (i = 0; i < 0x80; i++) {
5410	ChipsNew->FR[i] = cPtr->readFR(cPtr, i);
5411    }
5412    for (i = 0; i < 0x80; i++) {
5413	ChipsNew->MR[i] = cPtr->readMR(cPtr, i);
5414    }
5415    for (i = 0x30; i < 0x80; i++) {    /* These are the CT extended CRT regs */
5416	ChipsNew->CR[i] = hwp->readCrtc(hwp, i);
5417    }
5418
5419    /*
5420     * Here all of the other fields of 'ChipsNew' get filled in, to
5421     * handle the SVGA extended registers.  It is also allowable
5422     * to override generic registers whenever necessary.
5423     */
5424
5425    /* some generic settings */
5426    if (pScrn->depth == 1) {
5427	ChipsStd->Attribute[0x10] = 0x03;   /* mode */
5428    } else {
5429	ChipsStd->Attribute[0x10] = 0x01;   /* mode */
5430    }
5431    if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)) {
5432	/* Make sure that the overlay isn't visible in the overscan region */
5433	if (ChipsStd->Attribute[0x11] == pScrn->colorKey)
5434	    ChipsStd->Attribute[0x11] = pScrn->colorKey - 1;
5435    } else
5436	ChipsStd->Attribute[0x11] = 0x00;   /* overscan (border) color */
5437    ChipsStd->Attribute[0x12] = 0x0F;   /* enable all color planes */
5438    ChipsStd->Attribute[0x13] = 0x00;   /* horiz pixel panning 0 */
5439
5440    ChipsStd->Graphics[0x05] = 0x00;    /* normal read/write mode */
5441
5442    /* set virtual screen width */
5443    tmp = pScrn->displayWidth >> 3;
5444    if (pScrn->bitsPerPixel == 16) {
5445	if (!(cPtr->Flags & ChipsOverlay8plus16))
5446	    tmp <<= 1;		       /* double the width of the buffer */
5447    } else if (pScrn->bitsPerPixel == 24) {
5448	tmp += tmp << 1;
5449    } else if (pScrn->bitsPerPixel == 32) {
5450	tmp <<= 2;
5451    } else if (pScrn->bitsPerPixel < 8) {
5452	tmp >>= 1;
5453    }
5454    ChipsStd->CRTC[0x13] = tmp & 0xFF;
5455    ChipsNew->CR[0x41] = (tmp >> 8) & 0x0F;
5456
5457    /* Set paging mode on the HiQV32 architecture, if required */
5458    if (!(cPtr->Flags & ChipsLinearSupport) || (pScrn->bitsPerPixel < 8))
5459	ChipsNew->XR[0x0A] |= 0x1;
5460
5461#if X_BYTE_ORDER == X_BIG_ENDIAN
5462    ChipsNew->XR[0x0A] &= 0xCF;
5463    if (pScrn->bitsPerPixel == 16) {
5464	if  (!cPtr->dualEndianAp)
5465	    ChipsNew->XR[0x0A] |= 0x10;
5466    }
5467#endif
5468    ChipsNew->XR[0x09] |= 0x1;	       /* Enable extended CRT registers */
5469    ChipsNew->XR[0x0E] = 0;           /* Single map */
5470    ChipsNew->XR[0x40] |= 0x2;	       /* Don't wrap at 256kb */
5471    ChipsNew->XR[0x81] &= 0xF8;
5472    if (pScrn->bitsPerPixel >= 8) {
5473        ChipsNew->XR[0x40] |= 0x1;    /* High Resolution. XR40[1] reserved? */
5474	ChipsNew->XR[0x81] |= 0x2;    /* 256 Color Video */
5475    }
5476    ChipsNew->XR[0x80] |= 0x10;       /* Enable cursor output on P0 and P1 */
5477    if (pScrn->depth > 1) {
5478	if (pScrn->rgbBits == 8)
5479	    ChipsNew->XR[0x80] |= 0x80;
5480	else
5481	    ChipsNew->XR[0x80] &= ~0x80;
5482    }
5483
5484    if (abs(cPtr->MemClock.Clk - cPtr->MemClock.ProbedClk) > 50) {
5485	/* set mem clk */
5486	ChipsNew->XR[0xCC] = cPtr->MemClock.xrCC;
5487	ChipsNew->XR[0xCD] = cPtr->MemClock.xrCD;
5488	ChipsNew->XR[0xCE] = cPtr->MemClock.xrCE;
5489    }
5490
5491    /* Set the 69030 dual channel settings */
5492    if (cPtr->Flags & ChipsDualChannelSupport) {
5493	ChipsNew->FR[0x01] &= 0xFC;
5494        if ((cPtr->SecondCrtc == FALSE) && (cPtr->PanelType & ChipsLCD))
5495	    ChipsNew->FR[0x01] |= 0x02;
5496	else
5497	    ChipsNew->FR[0x01] |= 0x01;
5498	ChipsNew->FR[0x02] &= 0xCC;
5499	if ((cPtr->SecondCrtc == TRUE) || (cPtr->Flags & ChipsDualRefresh))
5500	    ChipsNew->FR[0x02] |= 0x01;	/* Set DAC to pipe B */
5501	else
5502	    ChipsNew->FR[0x02] &= 0xFE;	/* Set DAC to pipe A */
5503
5504        if (cPtr->PanelType & ChipsLCD)
5505	    ChipsNew->FR[0x02] |= 0x20;	/* Enable the LCD output */
5506        if (cPtr->PanelType & ChipsCRT)
5507	    ChipsNew->FR[0x02] |= 0x10;	/* Enable the CRT output */
5508    }
5509
5510    /* linear specific */
5511    if (cPtr->Flags & ChipsLinearSupport) {
5512	ChipsNew->XR[0x0A] |= 0x02;   /* Linear Addressing Mode */
5513	ChipsNew->XR[0x20] = 0x0;     /*BitBLT Draw Mode for 8 */
5514	ChipsNew->XR[0x05] =
5515	    (unsigned char)((cPtr->FbAddress >> 16) & 0xFF);
5516	ChipsNew->XR[0x06] =
5517	    (unsigned char)((cPtr->FbAddress >> 24) & 0xFF);
5518    }
5519
5520    /* panel timing */
5521    /* By default don't set panel timings, but allow it as an option */
5522    if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) {
5523	lcdHTotal = (mode->CrtcHTotal >> 3) - 5;
5524	lcdHDisplay = (cPtr->PanelSize.HDisplay >> 3) - 1;
5525	lcdHRetraceStart = (mode->CrtcHSyncStart >> 3);
5526	lcdHRetraceEnd = (mode->CrtcHSyncEnd >> 3);
5527	lcdHSyncStart = lcdHRetraceStart - 2;
5528
5529	lcdVTotal = mode->CrtcVTotal - 2;
5530	lcdVDisplay = cPtr->PanelSize.VDisplay - 1;
5531	lcdVRetraceStart = mode->CrtcVSyncStart;
5532	lcdVRetraceEnd = mode->CrtcVSyncEnd;
5533
5534	ChipsNew->FR[0x20] = lcdHDisplay & 0xFF;
5535	ChipsNew->FR[0x21] = lcdHRetraceStart & 0xFF;
5536	ChipsNew->FR[0x25] = ((lcdHRetraceStart & 0xF00) >> 4) |
5537	    ((lcdHDisplay & 0xF00) >> 8);
5538	ChipsNew->FR[0x22] = lcdHRetraceEnd & 0x1F;
5539	ChipsNew->FR[0x23] = lcdHTotal & 0xFF;
5540	ChipsNew->FR[0x24] = (lcdHSyncStart >> 3) & 0xFF;
5541	ChipsNew->FR[0x26] = (ChipsNew->FR[0x26] & ~0x1F)
5542	    | ((lcdHTotal & 0xF00) >> 8)
5543	    | (((lcdHSyncStart >> 3) & 0x100) >> 4);
5544	ChipsNew->FR[0x27] &= 0x7F;
5545
5546	ChipsNew->FR[0x30] = lcdVDisplay & 0xFF;
5547	ChipsNew->FR[0x31] = lcdVRetraceStart & 0xFF;
5548	ChipsNew->FR[0x35] = ((lcdVRetraceStart & 0xF00) >> 4)
5549	    | ((lcdVDisplay & 0xF00) >> 8);
5550	ChipsNew->FR[0x32] = lcdVRetraceEnd & 0x0F;
5551	ChipsNew->FR[0x33] = lcdVTotal & 0xFF;
5552	ChipsNew->FR[0x34] = (lcdVTotal - lcdVRetraceStart) & 0xFF;
5553	ChipsNew->FR[0x36] = ((lcdVTotal & 0xF00) >> 8) |
5554	    (((lcdVTotal - lcdVRetraceStart) & 0x700) >> 4);
5555	ChipsNew->FR[0x37] |= 0x80;
5556    }
5557
5558    /* Set up the extended CRT registers of the HiQV32 chips */
5559    ChipsNew->CR[0x30] = ((mode->CrtcVTotal - 2) & 0xF00) >> 8;
5560    ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8;
5561    ChipsNew->CR[0x32] = (mode->CrtcVSyncStart & 0xF00) >> 8;
5562    ChipsNew->CR[0x33] = (mode->CrtcVBlankStart & 0xF00) >> 8;
5563    if ((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) {
5564	/* The 690xx has overflow bits for the horizontal values as well */
5565	ChipsNew->CR[0x38] = (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8;
5566	ChipsNew->CR[0x3C] = vgaHWHBlankKGA(mode, ChipsStd, 8, 0) << 6;
5567    } else
5568      vgaHWHBlankKGA(mode, ChipsStd, 6, 0);
5569    vgaHWVBlankKGA(mode, ChipsStd, 8, 0);
5570
5571    ChipsNew->CR[0x40] |= 0x80;
5572
5573    /* centering/stretching */
5574    if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) {
5575	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE) ||
5576	(cPtr->Flags & ChipsOverlay8plus16)) {
5577	    ChipsNew->FR[0x40] &= 0xDF;    /* Disable Horizontal stretching */
5578	    ChipsNew->FR[0x48] &= 0xFB;    /* Disable vertical stretching */
5579	    ChipsNew->XR[0xA0] = 0x10;     /* Disable cursor stretching */
5580	} else {
5581	    ChipsNew->FR[0x40] |= 0x21;    /* Enable Horizontal stretching */
5582	    ChipsNew->FR[0x48] |= 0x05;    /* Enable vertical stretching */
5583	    ChipsNew->XR[0xA0] = 0x70;     /* Enable cursor stretching */
5584	    if (cPtr->Accel.UseHWCursor
5585		&& cPtr->PanelSize.HDisplay && cPtr->PanelSize.VDisplay
5586		&& (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay)
5587		&& (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) {
5588		if(cPtr->Accel.UseHWCursor)
5589		    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5590			       "Disabling HW Cursor on stretched LCD\n");
5591		cPtr->Flags &= ~ChipsHWCursor;
5592	    }
5593	}
5594    }
5595
5596    if ((xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE))
5597		|| (cPtr->Flags & ChipsOverlay8plus16)) {
5598	ChipsNew->FR[0x40] |= 0x3;    /* Enable Horizontal centering */
5599	ChipsNew->FR[0x48] |= 0x3;    /* Enable Vertical centering */
5600    } else {
5601	ChipsNew->FR[0x40] &= 0xFD;    /* Disable Horizontal centering */
5602	ChipsNew->FR[0x48] &= 0xFD;    /* Disable Vertical centering */
5603    }
5604
5605    /* sync on green */
5606    if (xf86ReturnOptValBool(cPtr->Options, OPTION_SYNC_ON_GREEN, FALSE))
5607	ChipsNew->XR[0x82] |=0x02;
5608
5609    /* software mode flag */
5610    ChipsNew->XR[0xE2] = chipsVideoMode(((cPtr->Flags & ChipsOverlay8plus16) ?
5611	8 : pScrn->depth), (cPtr->PanelType & ChipsLCD) ?
5612	min(mode->CrtcHDisplay, cPtr->PanelSize.HDisplay) :
5613	mode->CrtcHDisplay, mode->CrtcVDisplay);
5614#ifdef DEBUG
5615    ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0xE2]);
5616#endif
5617
5618    /* sync. polarities */
5619    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
5620	&& (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
5621	if (mode->Flags & (V_PHSYNC | V_NHSYNC)) {
5622	    if (mode->Flags & V_PHSYNC)
5623		ChipsNew->FR[0x08] &= 0xBF;	/* Alt. CRT Hsync positive */
5624	    else
5625		ChipsNew->FR[0x08] |= 0x40;	/* Alt. CRT Hsync negative */
5626	}
5627	if (mode->Flags & (V_PVSYNC | V_NVSYNC)) {
5628	    if (mode->Flags & V_PVSYNC)
5629		ChipsNew->FR[0x08] &= 0x7F;	/* Alt. CRT Vsync positive */
5630	    else
5631		ChipsNew->FR[0x08] |= 0x80;	/* Alt. CRT Vsync negative */
5632	}
5633    }
5634    if (mode->Flags & (V_PCSYNC | V_NCSYNC)) {
5635	ChipsNew->FR[0x0B] |= 0x20;
5636	if (mode->Flags & V_PCSYNC) {
5637	    ChipsNew->FR[0x08] &= 0x7F;	/* Alt. CRT Vsync positive */
5638	    ChipsNew->FR[0x08] &= 0xBF;	/* Alt. CRT Hsync positive */
5639	    ChipsStd->MiscOutReg &= 0x7F;
5640	    ChipsStd->MiscOutReg &= 0xBF;
5641	} else {
5642	    ChipsNew->FR[0x08] |= 0x80;	/* Alt. CRT Vsync negative */
5643	    ChipsNew->FR[0x08] |= 0x40;	/* Alt. CRT Hsync negative */
5644	    ChipsStd->MiscOutReg |= 0x40;
5645	    ChipsStd->MiscOutReg |= 0x80;
5646    	}
5647    }
5648    /* bpp depend */
5649    if ((pScrn->bitsPerPixel == 16) && (!(cPtr->Flags & ChipsOverlay8plus16))) {
5650	ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x4;
5651	if (cPtr->Flags & ChipsGammaSupport)
5652	    ChipsNew->XR[0x82] |= 0x0C;
5653	/* 16bpp = 5-5-5             */
5654	ChipsNew->FR[0x10] |= 0x0C;   /*Colour Panel               */
5655	ChipsNew->XR[0x20] = 0x10;    /*BitBLT Draw Mode for 16 bpp */
5656	if (pScrn->weight.green != 5)
5657	    ChipsNew->XR[0x81] |= 0x01;	/*16bpp */
5658    } else if (pScrn->bitsPerPixel == 24) {
5659	ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x6;
5660	if (cPtr->Flags & ChipsGammaSupport)
5661	    ChipsNew->XR[0x82] |= 0x0C;
5662	/* 24bpp colour              */
5663	ChipsNew->XR[0x20] = 0x20;    /*BitBLT Draw Mode for 24 bpp */
5664    } else if (pScrn->bitsPerPixel == 32) {
5665	ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x7;
5666	if (cPtr->Flags & ChipsGammaSupport)
5667	    ChipsNew->XR[0x82] |= 0x0C;
5668	/* 32bpp colour              */
5669	ChipsNew->XR[0x20] = 0x10;    /*BitBLT Mode for 16bpp used at 32bpp */
5670    }
5671
5672    /*CRT only */
5673    if (!(cPtr->PanelType & ChipsLCD)) {
5674	if (mode->Flags & V_INTERLACE) {
5675	    ChipsNew->CR[0x70] = 0x80          /*   set interlace */
5676	      | (((((mode->CrtcHDisplay >> 3) - 1) >> 1) - 6) & 0x7F);
5677	    /*
5678	     ** Double VDisplay to get back the full screen value, otherwise
5679	     ** you only see half the picture.
5680	     */
5681	    mode->CrtcVDisplay = mode->VDisplay;
5682	    tmp = ChipsStd->CRTC[7] & ~0x42;
5683	    ChipsStd->CRTC[7] = (tmp |
5684				((((mode->CrtcVDisplay -1) & 0x100) >> 7 ) |
5685				 (((mode->CrtcVDisplay -1) & 0x200) >> 3 )));
5686	    ChipsStd->CRTC[0x12] = (mode->CrtcVDisplay -1) & 0xFF;
5687	    ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8;
5688	} else {
5689	    ChipsNew->CR[0x70] &= ~0x80;	/* unset interlace */
5690	}
5691    }
5692
5693#if defined(__arm__) && defined(___NetBSD__)
5694    if (cPtr->TVMode != XMODE_RGB) {
5695	/*
5696	 * Put the console into TV Out mode.
5697	 */
5698	xf86SetTVOut(cPtr->TVMode);
5699
5700	ChipsNew->CR[0x72] = (mode->CrtcHTotal >> 1) >> 3;/* First horizontal
5701							   * serration pulse */
5702	ChipsNew->CR[0x73] = mode->CrtcHTotal >> 3; /* Second pulse */
5703	ChipsNew->CR[0x74] = (((mode->HSyncEnd - mode->HSyncStart) >> 3) - 1)
5704					& 0x1F; /* equalization pulse */
5705
5706	if (cPtr->TVMode == XMODE_PAL || cPtr->TVMode == XMODE_SECAM) {
5707	    ChipsNew->CR[0x71] = 0xA0; /* PAL support with blanking delay */
5708	} else {
5709	    ChipsNew->CR[0x71] = 0x20; /* NTSC support with blanking delay */
5710	}
5711    } else {	/* XMODE_RGB */
5712	/*
5713	 * Put the console into RGB Out mode.
5714	 */
5715	xf86SetRGBOut();
5716    }
5717#endif
5718
5719    /* STN specific */
5720    if (IS_STN(cPtr->PanelType)) {
5721	ChipsNew->FR[0x11] &= ~0x03;	/* FRC clear                    */
5722	ChipsNew->FR[0x11] &= ~0x8C;	/* Dither clear                 */
5723	ChipsNew->FR[0x11] |= 0x01;	/* 16 frame FRC                 */
5724	ChipsNew->FR[0x11] |= 0x84;	/* Dither                       */
5725	if ((cPtr->Flags & ChipsTMEDSupport) &&
5726		!xf86ReturnOptValBool(cPtr->Options, OPTION_NO_TMED, FALSE)) {
5727	    ChipsNew->FR[0x73] &= 0x4F; /* Clear TMED                   */
5728	    ChipsNew->FR[0x73] |= 0x80; /* Enable TMED                  */
5729	    ChipsNew->FR[0x73] |= 0x30; /* TMED 256 Shades of RGB       */
5730	}
5731	if (cPtr->PanelType & ChipsDD)	/* Shift Clock Mask. Use to get */
5732	    ChipsNew->FR[0x12] |= 0x4;	/* rid of line in DSTN screens  */
5733    }
5734
5735    /*
5736     * The zero position of the overlay does not align with the zero
5737     * position of the display. The skew is dependent on the depth,
5738     * display type and refresh rate. Calculate the skew before setting
5739     * the X and Y dimensions of the overlay. These values are needed
5740     * both by the overlay and XvImages. So calculate and store them
5741     */
5742    if (cPtr->PanelType & ChipsLCD) {
5743	cPtr->OverlaySkewX = (((ChipsNew->FR[0x23] & 0xFF)
5744			    - (ChipsNew->FR[0x20] & 0xFF) + 3) << 3)
5745	    - 1;
5746	cPtr->OverlaySkewY = (ChipsNew->FR[0x33]
5747			    + ((ChipsNew->FR[0x36] & 0xF) << 8)
5748			    - (ChipsNew->FR[0x31] & 0xF0)
5749			    - (ChipsNew->FR[0x32] & 0x0F)
5750			    - ((ChipsNew->FR[0x35] & 0xF0) << 4));
5751	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE)
5752	      && xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE))
5753	{
5754	    if (cPtr->PanelSize.HDisplay > mode->CrtcHDisplay)
5755		cPtr->OverlaySkewX += (cPtr->PanelSize.HDisplay -
5756				       mode->CrtcHDisplay) / 2;
5757	    if (cPtr->PanelSize.VDisplay > mode->CrtcVDisplay)
5758		cPtr->OverlaySkewY += (cPtr->PanelSize.VDisplay -
5759				       mode->CrtcVDisplay) / 2;
5760	}
5761    } else {
5762	cPtr->OverlaySkewX = mode->CrtcHTotal - mode->CrtcHBlankStart - 9;
5763	cPtr->OverlaySkewY = mode->CrtcVTotal - mode->CrtcVSyncEnd - 1;
5764
5765	if (mode->Flags & V_INTERLACE) {
5766	    /*
5767	     * This handles 1024 and 1280 interlaced modes only. Its
5768	     * pretty arbitrary, but its what C&T recommends
5769	     */
5770#if 0
5771	    if (mode->CrtcHDisplay == 1024)
5772		cPtr->OverlaySkewY += 5;
5773	    else  if (mode->CrtcHDisplay == 1280)
5774#endif
5775		cPtr->OverlaySkewY *= 2;
5776
5777	}
5778    }
5779
5780    /* mask for viewport granularity */
5781
5782    switch (pScrn->bitsPerPixel) {
5783    case 8:
5784	cPtr->viewportMask = ~7U;
5785	break;
5786    case 16:
5787	cPtr->viewportMask = ~3U;
5788	break;
5789    case 24:
5790	cPtr->viewportMask = ~7U;
5791	break;
5792    case 32:
5793	cPtr->viewportMask = ~0U;
5794	break;
5795    default:
5796	cPtr->viewportMask = ~7U;
5797    }
5798
5799    /* Turn off multimedia by default as it degrades performance */
5800    ChipsNew->XR[0xD0] &= 0x0f;
5801
5802    /* Setup the video/overlay */
5803    if (cPtr->Flags & ChipsOverlay8plus16) {
5804	ChipsNew->XR[0xD0] |= 0x10;	/* Force the Multimedia engine on */
5805#ifdef SAR04
5806	ChipsNew->XR[0x4F] = 0x2A;	/* SAR04 >352 pixel overlay width */
5807#endif
5808	ChipsNew->MR[0x1E] &= 0xE0;	/* Set Zoom and Direction */
5809	if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE))
5810	    ChipsNew->MR[0x1E] |= 0x10;	/* Interlace */
5811	ChipsNew->MR[0x1F] &= 0x14;	/* Mask reserved bits */
5812	ChipsNew->MR[0x1F] |= 0x08;	/* RGB 16bpp */
5813	if (pScrn->weight.green == 5)
5814	    ChipsNew->MR[0x1F] |= 0x01;	/* RGB 15bpp */
5815
5816	ChipsNew->MR[0x20] &= 0x03;	/* Mask reserved bits */
5817	ChipsNew->MR[0x20] |= 0x80;	/* Auto Centre, Use mem ptr1 */
5818	ChipsNew->MR[0x22] = cPtr->FbOffset16 & 0xF8;	/* Setup Pointer 1 */
5819	ChipsNew->MR[0x23] = (cPtr->FbOffset16 >> 8) & 0xFF;
5820	ChipsNew->MR[0x24] = (cPtr->FbOffset16 >> 16) & 0xFF;
5821	ChipsNew->MR[0x25] = cPtr->FbOffset16 & 0xF8;	/* Setup Pointer 2 */
5822	ChipsNew->MR[0x26] = (cPtr->FbOffset16 >> 8) & 0xFF;
5823	ChipsNew->MR[0x27] = (cPtr->FbOffset16 >> 16) & 0xFF;
5824	ChipsNew->MR[0x28] = (pScrn->displayWidth >> 2) - 1; /* Width */
5825	ChipsNew->MR[0x34] = (pScrn->displayWidth >> 2) - 1;
5826
5827	/* Left Edge of Overlay */
5828	ChipsNew->MR[0x2A] = cPtr->OverlaySkewX;
5829	ChipsNew->MR[0x2B] &= 0xF8;	/* Mask reserved bits */
5830	ChipsNew->MR[0x2B] |= ((cPtr->OverlaySkewX >> 8) & 0x7);
5831	/* Right Edge of Overlay */
5832	ChipsNew->MR[0x2C] = (cPtr->OverlaySkewX + pScrn->displayWidth -
5833							1) & 0xFF;
5834	ChipsNew->MR[0x2D] &= 0xF8;	/* Mask reserved bits */
5835	ChipsNew->MR[0x2D] |= ((cPtr->OverlaySkewX + pScrn->displayWidth -
5836							1) >> 8) & 0x07;
5837	/* Top Edge of Overlay */
5838	ChipsNew->MR[0x2E] = cPtr->OverlaySkewY;
5839	ChipsNew->MR[0x2F] &= 0xF8;
5840	ChipsNew->MR[0x2F] |= ((cPtr->OverlaySkewY >> 8) & 0x7);
5841	/* Bottom Edge of Overlay*/
5842	ChipsNew->MR[0x30] = (cPtr->OverlaySkewY + pScrn->virtualY - 1 )& 0xFF;
5843	ChipsNew->MR[0x31] &= 0xF8;	/* Mask reserved bits */
5844	ChipsNew->MR[0x31] |= ((cPtr->OverlaySkewY + pScrn->virtualY -
5845							1 ) >> 8) & 0x07;
5846
5847	ChipsNew->MR[0x3C] &= 0x18;	/* Mask reserved bits */
5848	ChipsNew->MR[0x3C] |= 0x07;	/* Enable keyed overlay window */
5849	ChipsNew->MR[0x3D] = 0x00;
5850	ChipsNew->MR[0x3E] = 0x00;
5851	ChipsNew->MR[0x3F] = pScrn->colorKey; /* 8bpp transparency key */
5852	ChipsNew->MR[0x40] = 0xFF;
5853	ChipsNew->MR[0x41] = 0xFF;
5854	ChipsNew->MR[0x42] = 0x00;
5855    } else if (cPtr->Flags & ChipsVideoSupport) {
5856#if 0   /* if we do this even though video isn't playing we kill performance */
5857	ChipsNew->XR[0xD0] |= 0x10;	/* Force the Multimedia engine on */
5858#endif
5859#ifdef SAR04
5860	ChipsNew->XR[0x4F] = 0x2A;	/* SAR04 >352 pixel overlay width */
5861#endif
5862	ChipsNew->MR[0x3C] &= 0x18;	/* Ensure that the overlay is off */
5863	cPtr->VideoZoomMax = 0x100;
5864
5865	if (cPtr->Chipset == CHIPS_CT65550) {
5866	    tmp = cPtr->readXR(cPtr, 0x04);
5867	    if (tmp < 0x02)				/* 65550 ES0 has */
5868		cPtr->VideoZoomMax = 0x40;		/* 0x40 max zoom */
5869	}
5870    }
5871
5872    /* Program the registers */
5873    /*vgaHWProtect(pScrn, TRUE);*/
5874
5875    if (cPtr->Chipset <= CHIPS_CT69000) {
5876        ChipsNew->FR[0x01] &= ~0x03;
5877	if (cPtr->PanelType & ChipsLCD)
5878	    ChipsNew->FR[0x01] |= 0x02;
5879	else
5880	    ChipsNew->FR[0x01] |= 0x01;
5881    }
5882    if ((cPtr->Flags & ChipsDualChannelSupport) &&
5883	(!xf86IsEntityShared(pScrn->entityList[0]))) {
5884	unsigned char IOSS, MSS, tmpfr01;
5885
5886
5887	IOSS = cPtr->readIOSS(cPtr);
5888	MSS = cPtr->readMSS(cPtr);
5889	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
5890			       IOSS_PIPE_A));
5891	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) |
5892			      MSS_PIPE_A));
5893	chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE);
5894	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
5895			       IOSS_PIPE_B));
5896	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) |
5897			      MSS_PIPE_B));
5898	/*
5899	 * Hack:: Force Pipe-B on for dual refresh, and off elsewise
5900	 */
5901	tmpfr01 = ChipsNew->FR[0x01];
5902	ChipsNew->FR[0x01] &= 0xFC;
5903	if (cPtr->UseDualChannel)
5904	    ChipsNew->FR[0x01] |= 0x01;
5905	chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE);
5906	ChipsNew->FR[0x01] = tmpfr01;
5907	cPtr->writeIOSS(cPtr, IOSS);
5908	cPtr->writeMSS(cPtr, hwp, MSS);
5909    } else {
5910	chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE);
5911    }
5912
5913    /*vgaHWProtect(pScrn, FALSE);*/
5914    usleep(100000);  /* prevents cursor corruption seen on a TECRA 510 */
5915
5916    return(TRUE);
5917}
5918
5919static Bool
5920chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode)
5921{
5922    int i, bytesPerPixel;
5923    vgaHWPtr hwp = VGAHWPTR(pScrn);
5924    CHIPSPtr cPtr = CHIPSPTR(pScrn);
5925    CHIPSRegPtr ChipsNew;
5926    vgaRegPtr ChipsStd;
5927    unsigned int tmp;
5928
5929    ChipsNew = &cPtr->ModeReg;
5930    ChipsStd = &hwp->ModeReg;
5931
5932    bytesPerPixel = pScrn->bitsPerPixel >> 3;
5933
5934    /*
5935     * This chipset seems to have problems if
5936     * HBlankEnd is choosen equals HTotal
5937     */
5938    if (!mode->CrtcHAdjusted)
5939      mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2);
5940
5941    /* correct the timings for 16/24 bpp */
5942    if (pScrn->bitsPerPixel == 16) {
5943	if (!mode->CrtcHAdjusted) {
5944	    mode->CrtcHDisplay++;
5945	    mode->CrtcHDisplay <<= 1;
5946	    mode->CrtcHDisplay--;
5947	    mode->CrtcHSyncStart <<= 1;
5948	    mode->CrtcHSyncEnd <<= 1;
5949	    mode->CrtcHBlankStart <<= 1;
5950	    mode->CrtcHBlankEnd <<= 1;
5951	    mode->CrtcHTotal <<= 1;
5952	    mode->CrtcHAdjusted = TRUE;
5953	}
5954    } else if (pScrn->bitsPerPixel == 24) {
5955	if (!mode->CrtcHAdjusted) {
5956	    mode->CrtcHDisplay++;
5957	    mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1);
5958	    mode->CrtcHDisplay--;
5959	    mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1);
5960	    mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1);
5961	    mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1);
5962	    mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1);
5963	    mode->CrtcHTotal += ((mode->CrtcHTotal) << 1);
5964	    mode->CrtcHAdjusted = TRUE;
5965	}
5966    }
5967
5968    /* generic init */
5969    if (!vgaHWInit(pScrn, mode)) {
5970	ErrorF("bomb 3\n");
5971	return (FALSE);
5972    }
5973    pScrn->vtSema = TRUE;
5974
5975    /* init clock */
5976    if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) {
5977	ErrorF("bomb 4\n");
5978	return (FALSE);
5979    }
5980
5981    /* get  C&T Specific Registers */
5982    for (i = 0; i < 0x7D; i++) {   /* don't touch XR7D and XR7F on WINGINE */
5983	ChipsNew->XR[i] = cPtr->readXR(cPtr, i);
5984    }
5985
5986    /* some generic settings */
5987    if (pScrn->bitsPerPixel == 1) {
5988	ChipsStd->Attribute[0x10] = 0x03;   /* mode */
5989    } else {
5990	ChipsStd->Attribute[0x10] = 0x01;   /* mode */
5991    }
5992    ChipsStd->Attribute[0x11] = 0x00;   /* overscan (border) color */
5993    ChipsStd->Attribute[0x12] = 0x0F;   /* enable all color planes */
5994    ChipsStd->Attribute[0x13] = 0x00;   /* horiz pixel panning 0 */
5995
5996    ChipsStd->Graphics[0x05] = 0x00;    /* normal read/write mode */
5997
5998
5999    /* set virtual screen width */
6000    if (pScrn->bitsPerPixel >= 8)
6001	ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3;
6002    else
6003	ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4;
6004
6005
6006    /* set C&T Specific Registers */
6007    /* set virtual screen width */
6008    if (pScrn->bitsPerPixel >= 8)
6009	tmp = (pScrn->displayWidth >> 4) * bytesPerPixel;
6010    else
6011	tmp = (pScrn->displayWidth >> 5);
6012    ChipsNew->XR[0x0D] = (tmp & 0x80) >> 5;
6013
6014    ChipsNew->XR[0x04] |= 4;	       /* enable addr counter bits 16-17 */
6015    /* XR04: Memory control 1 */
6016    /* bit 2: Memory Wraparound */
6017    /*        Enable CRTC addr counter bits 16-17 if set */
6018
6019    ChipsNew->XR[0x0B] |= 0x07;       /* extended mode, dual pages enabled */
6020    ChipsNew->XR[0x0B] &= ~0x10;      /* linear mode off */
6021    /* XR0B: CPU paging */
6022    /* bit 0: Memory mapping mode */
6023    /*        VGA compatible if 0 (default) */
6024    /*        Extended mode (mapping for > 256 kB mem) if 1 */
6025    /* bit 1: CPU single/dual mapping */
6026    /*        0, CPU uses only a single map to access (default) */
6027    /*        1, CPU uses two maps to access */
6028    /* bit 2: CPU address divide by 4 */
6029
6030    ChipsNew->XR[0x10] = 0;	       /* XR10: Single/low map */
6031    ChipsNew->XR[0x11] = 0;	       /* XR11: High map      */
6032    ChipsNew->XR[0x0C] &= ~0x50;       /* MSB for XR10 & XR11  */
6033    if (pScrn->bitsPerPixel >= 8) {
6034	ChipsNew->XR[0x28] |= 0x10;       /* 256-color video     */
6035    } else {
6036	ChipsNew->XR[0x28] &= 0xEF;       /* 16-color video      */
6037    }
6038    /* set up extended display timings */
6039    /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */
6040    ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8)
6041	| ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7)
6042	| ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6)
6043	| ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2)
6044	| ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4)
6045	| ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1);
6046
6047
6048    ChipsNew->XR[0x16]  = (((mode->CrtcVTotal -2) & 0x400) >> 10 )
6049	| (((mode->CrtcVDisplay -1) & 0x400) >> 9 )
6050	| ((mode->CrtcVSyncStart & 0x400) >> 8 )
6051	| (((mode->CrtcVBlankStart) & 0x400) >> 6 );
6052
6053    /* set video mode */
6054    ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, mode->CrtcHDisplay, mode->CrtcVDisplay);
6055#ifdef DEBUG
6056    ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]);
6057#endif
6058
6059    /* set some linear specific registers */
6060    if (cPtr->Flags & ChipsLinearSupport) {
6061	/* enable linear addressing  */
6062	ChipsNew->XR[0x0B] &= 0xFD;   /* dual page clear                */
6063	ChipsNew->XR[0x0B] |= 0x10;   /* linear mode on                 */
6064
6065	ChipsNew->XR[0x08] =
6066	  (unsigned char)((cPtr->FbAddress >> 16) & 0xFF);
6067	ChipsNew->XR[0x09] =
6068	  (unsigned char)((cPtr->FbAddress >> 24) & 0xFF);
6069
6070	/* general setup */
6071	ChipsNew->XR[0x40] = 0x01;    /*BitBLT Draw Mode for 8 and 24 bpp */
6072    }
6073
6074    /* common general setup */
6075    ChipsNew->XR[0x52] |= 0x01;       /* Refresh count                   */
6076    ChipsNew->XR[0x0F] &= 0xEF;       /* not Hi-/True-Colour             */
6077    ChipsNew->XR[0x02] &= 0xE7;       /* Attr. Cont. default access      */
6078                                       /* use ext. regs. for hor. in dual */
6079    ChipsNew->XR[0x06] &= 0xF3;       /* bpp clear                       */
6080
6081    /* bpp depend */
6082    /*XR06: Palette control */
6083    /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def)  */
6084    /* bit 1: Internal DAC disable                                   */
6085    /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */
6086    /*          2 for 24 bpp, 3 for 16(5-6-5)bpp                     */
6087    /* bit 4:   Enable PC Video Overlay on colour key                */
6088    /* bit 5:   Bypass Internal VGA palette                          */
6089    /* bit 7-6: Colour reduction select, 0 for NTSC (default),       */
6090    /*          1 for Equivalent weighting, 2 for green only,        */
6091    /*          3 for Colour w/o reduction                           */
6092    /* XR50 Panel Format Register 1                                  */
6093    /* bit 1-0: Frame Rate Control; 00, No FRC;                      */
6094    /*          01, 16-frame FRC for colour STN and monochrome       */
6095    /*          10, 2-frame FRC for colour TFT or monochrome;        */
6096    /*          11, reserved                                         */
6097    /* bit 3-2: Dither Enable                                        */
6098    /*          00, disable dithering; 01, enable dithering          */
6099    /*          for 256 mode                                         */
6100    /*          10, enable dithering for all modes; 11, reserved     */
6101    /* bit6-4: Clock Divide (CD)                                     */
6102    /*          000, Shift Clock Freq = Dot Clock Freq;              */
6103    /*          001, SClk = DClk/2; 010 SClk = DClk/4;               */
6104    /*          011, SClk = DClk/8; 100 SClk = DClk/16;              */
6105    /* bit 7: TFT data width                                         */
6106    /*          0, 16 bit(565RGB); 1, 24bit (888RGB)                 */
6107    if (pScrn->bitsPerPixel == 16) {
6108	ChipsNew->XR[0x06] |= 0xC4;   /*15 or 16 bpp colour         */
6109	ChipsNew->XR[0x0F] |= 0x10;   /*Hi-/True-Colour             */
6110	ChipsNew->XR[0x40] = 0x02;    /*BitBLT Draw Mode for 16 bpp */
6111	if (pScrn->weight.green != 5)
6112	    ChipsNew->XR[0x06] |= 0x08;	/*16bpp              */
6113    } else if (pScrn->bitsPerPixel == 24) {
6114	ChipsNew->XR[0x06] |= 0xC8;   /*24 bpp colour               */
6115	ChipsNew->XR[0x0F] |= 0x10;   /*Hi-/True-Colour             */
6116    }
6117
6118    /*CRT only: interlaced mode */
6119    if (mode->Flags & V_INTERLACE) {
6120	ChipsNew->XR[0x28] |= 0x20;    /* set interlace         */
6121	/* empirical value       */
6122	tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1)
6123	       - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 ));
6124	ChipsNew->XR[0x19] = tmp & 0xFF;
6125	ChipsNew->XR[0x17] |= ((tmp & 0x100) >> 1); /* overflow */
6126	ChipsNew->XR[0x0F] &= ~0x40;   /* set SW-Flag           */
6127    } else {
6128	ChipsNew->XR[0x28] &= ~0x20;   /* unset interlace       */
6129	ChipsNew->XR[0x0F] |=  0x40;   /* set SW-Flag           */
6130    }
6131
6132    /* Program the registers */
6133    /*vgaHWProtect(pScrn, TRUE);*/
6134    chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE);
6135    /*vgaHWProtect(pScrn, FALSE);*/
6136
6137    return (TRUE);
6138}
6139
6140static Bool
6141chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode)
6142{
6143    int i, bytesPerPixel;
6144    int lcdHTotal, lcdHDisplay;
6145    int lcdVTotal, lcdVDisplay;
6146    int lcdHRetraceStart, lcdHRetraceEnd;
6147    int lcdVRetraceStart, lcdVRetraceEnd;
6148    int HSyncStart, HDisplay;
6149    int CrtcHDisplay;
6150    vgaHWPtr hwp = VGAHWPTR(pScrn);
6151    CHIPSPtr cPtr = CHIPSPTR(pScrn);
6152    CHIPSRegPtr ChipsNew;
6153    vgaRegPtr ChipsStd;
6154    unsigned int tmp;
6155
6156    ChipsNew = &cPtr->ModeReg;
6157    ChipsStd = &hwp->ModeReg;
6158
6159    bytesPerPixel = pScrn->bitsPerPixel >> 3;
6160
6161    /*
6162     * Possibly fix up the panel size, if the manufacture is stupid
6163     * enough to set it incorrectly in text modes
6164     */
6165    if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) {
6166	cPtr->PanelSize.HDisplay = mode->CrtcHDisplay;
6167	cPtr->PanelSize.VDisplay = mode->CrtcVDisplay;
6168    }
6169
6170    /*
6171     * This chipset seems to have problems if
6172     * HBlankEnd is choosen equals HTotal
6173     */
6174    if (!mode->CrtcHAdjusted)
6175      mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2);
6176
6177    /* correct the timings for 16/24 bpp */
6178    if (pScrn->bitsPerPixel == 16) {
6179	if (!mode->CrtcHAdjusted) {
6180	    mode->CrtcHDisplay++;
6181	    mode->CrtcHDisplay <<= 1;
6182	    mode->CrtcHDisplay--;
6183	    mode->CrtcHSyncStart <<= 1;
6184	    mode->CrtcHSyncEnd <<= 1;
6185	    mode->CrtcHBlankStart <<= 1;
6186	    mode->CrtcHBlankEnd <<= 1;
6187	    mode->CrtcHTotal <<= 1;
6188	    mode->CrtcHAdjusted = TRUE;
6189	}
6190    } else if (pScrn->bitsPerPixel == 24) {
6191	if (!mode->CrtcHAdjusted) {
6192	    mode->CrtcHDisplay++;
6193	    mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1);
6194	    mode->CrtcHDisplay--;
6195	    mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1);
6196	    mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1);
6197	    mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1);
6198	    mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1);
6199	    mode->CrtcHTotal += ((mode->CrtcHTotal) << 1);
6200	    mode->CrtcHAdjusted = TRUE;
6201	}
6202    }
6203
6204    /* store orig. HSyncStart needed for flat panel mode */
6205    HSyncStart = mode->CrtcHSyncStart / (pScrn->bitsPerPixel >= 8 ?
6206					 bytesPerPixel : 1 ) - 16;
6207    HDisplay = (mode->CrtcHDisplay + 1) /  (pScrn->bitsPerPixel >= 8 ?
6208					 bytesPerPixel : 1 );
6209
6210    /* generic init */
6211    if (!vgaHWInit(pScrn, mode)) {
6212	ErrorF("bomb 5\n");
6213	return (FALSE);
6214    }
6215    pScrn->vtSema = TRUE;
6216
6217    /* init clock */
6218    if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) {
6219	ErrorF("bomb 6\n");
6220	return (FALSE);
6221    }
6222
6223    /* get  C&T Specific Registers */
6224    for (i = 0; i < 0x80; i++) {
6225	ChipsNew->XR[i] = cPtr->readXR(cPtr, i);
6226    }
6227
6228    /* some generic settings */
6229    if (pScrn->bitsPerPixel == 1) {
6230	ChipsStd->Attribute[0x10] = 0x03;   /* mode */
6231    } else {
6232	ChipsStd->Attribute[0x10] = 0x01;   /* mode */
6233    }
6234    ChipsStd->Attribute[0x11] = 0x00;   /* overscan (border) color */
6235    ChipsStd->Attribute[0x12] = 0x0F;   /* enable all color planes */
6236    ChipsStd->Attribute[0x13] = 0x00;   /* horiz pixel panning 0 */
6237
6238    ChipsStd->Graphics[0x05] = 0x00;    /* normal read/write mode */
6239
6240    /* set virtual screen width */
6241    if (pScrn->bitsPerPixel >= 8)
6242	ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3;
6243    else
6244	ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4;
6245
6246
6247    /* set C&T Specific Registers */
6248    /* set virtual screen width */
6249    ChipsNew->XR[0x1E] = ChipsStd->CRTC[0x13];	/* alternate offset */
6250    /*databook is not clear about 0x1E might be needed for 65520/30 */
6251    if (pScrn->bitsPerPixel >= 8)
6252	tmp = (pScrn->displayWidth * bytesPerPixel) >> 2;
6253    else
6254	tmp = pScrn->displayWidth >> 3;
6255    ChipsNew->XR[0x0D] = (tmp & 0x01) | ((tmp << 1) & 0x02)  ;
6256
6257    ChipsNew->XR[0x04] |= 4;	       /* enable addr counter bits 16-17 */
6258    /* XR04: Memory control 1 */
6259    /* bit 2: Memory Wraparound */
6260    /*        Enable CRTC addr counter bits 16-17 if set */
6261
6262    ChipsNew->XR[0x0B] |= 0x07;       /* extended mode, dual pages enabled */
6263    ChipsNew->XR[0x0B] &= ~0x10;      /* linear mode off */
6264    /* XR0B: CPU paging */
6265    /* bit 0: Memory mapping mode */
6266    /*        VGA compatible if 0 (default) */
6267    /*        Extended mode (mapping for > 256 kB mem) if 1 */
6268    /* bit 1: CPU single/dual mapping */
6269    /*        0, CPU uses only a single map to access (default) */
6270    /*        1, CPU uses two maps to access */
6271    /* bit 2: CPU address divide by 4 */
6272
6273    ChipsNew->XR[0x10] = 0;	       /* XR10: Single/low map */
6274    ChipsNew->XR[0x11] = 0;	       /* XR11: High map      */
6275    if (pScrn->bitsPerPixel >= 8) {
6276	ChipsNew->XR[0x28] |= 0x10;       /* 256-color video     */
6277    } else {
6278	ChipsNew->XR[0x28] &= 0xEF;       /* 16-color video      */
6279    }
6280    /* set up extended display timings */
6281    if (!(cPtr->PanelType & ChipsLCD)) {
6282	/* in CRTonly mode this is simple: only set overflow for CR00-CR06 */
6283	ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8)
6284	    | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7)
6285	    | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6)
6286	    | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2)
6287	    | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4)
6288	    | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1);
6289
6290	ChipsNew->XR[0x16]  = (((mode->CrtcVTotal -2) & 0x400) >> 10 )
6291	    | (((mode->CrtcVDisplay -1) & 0x400) >> 9 )
6292	    | ((mode->CrtcVSyncStart & 0x400) >> 8 )
6293	    | (((mode->CrtcVBlankStart) & 0x400) >> 6 );
6294    } else {
6295	/* horizontal timing registers */
6296	/* in LCD/dual mode use saved bios values to derive timing values if
6297	 * not told otherwise */
6298	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) {
6299	    lcdHTotal = cPtr->PanelSize.HTotal;
6300	    lcdHRetraceStart = cPtr->PanelSize.HRetraceStart;
6301	    lcdHRetraceEnd = cPtr->PanelSize.HRetraceEnd;
6302	    if (pScrn->bitsPerPixel == 16) {
6303		lcdHRetraceStart <<= 1;
6304		lcdHRetraceEnd <<= 1;
6305		lcdHTotal <<= 1;
6306	    } else if (pScrn->bitsPerPixel == 24) {
6307		lcdHRetraceStart += (lcdHRetraceStart << 1);
6308		lcdHRetraceEnd += (lcdHRetraceEnd << 1);
6309		lcdHTotal += (lcdHTotal << 1);
6310	    }
6311 	    lcdHRetraceStart -=8;       /* HBlank =  HRetrace - 1: for */
6312 	    lcdHRetraceEnd   -=8;       /* compatibility with vgaHW.c  */
6313	} else {
6314	    /* use modeline values if bios values don't work */
6315	    lcdHTotal = mode->CrtcHTotal;
6316	    lcdHRetraceStart = mode->CrtcHSyncStart;
6317	    lcdHRetraceEnd = mode->CrtcHSyncEnd;
6318	}
6319	/* The chip takes the size of the visible display area from the
6320	 * CRTC values. We use bios screensize for LCD in LCD/dual mode
6321	 * wether or not we use modeline for LCD. This way we can specify
6322	 * always specify a smaller than default display size on LCD
6323	 * by writing it to the CRTC registers. */
6324	lcdHDisplay = cPtr->PanelSize.HDisplay;
6325	if (pScrn->bitsPerPixel == 16) {
6326	    lcdHDisplay++;
6327	    lcdHDisplay <<= 1;
6328	    lcdHDisplay--;
6329	} else if (pScrn->bitsPerPixel == 24) {
6330	    lcdHDisplay++;
6331	    lcdHDisplay += (lcdHDisplay << 1);
6332	    lcdHDisplay--;
6333	}
6334	lcdHTotal = (lcdHTotal >> 3) - 5;
6335	lcdHDisplay = (lcdHDisplay >> 3) - 1;
6336	lcdHRetraceStart = (lcdHRetraceStart >> 3);
6337	lcdHRetraceEnd = (lcdHRetraceEnd >> 3);
6338	/* This ugly hack is needed because CR01 and XR1C share the 8th bit!*/
6339	CrtcHDisplay = ((mode->CrtcHDisplay >> 3) - 1);
6340	if ((lcdHDisplay & 0x100) != (CrtcHDisplay & 0x100)) {
6341	    xf86ErrorF("This display configuration might cause problems !\n");
6342	    lcdHDisplay = 255;
6343	}
6344
6345	/* now init register values */
6346	ChipsNew->XR[0x17] = (((lcdHTotal) & 0x100) >> 8)
6347	    | ((lcdHDisplay & 0x100) >> 7)
6348	    | ((lcdHRetraceStart & 0x100) >> 6)
6349	    | (((lcdHRetraceEnd) & 0x20) >> 2);
6350
6351	ChipsNew->XR[0x19] = lcdHRetraceStart & 0xFF;
6352	ChipsNew->XR[0x1A] = lcdHRetraceEnd & 0x1F;
6353
6354	/* XR1B: Alternate horizontal total */
6355	/* used in all flat panel mode with horiz. compression disabled, */
6356	/* CRT CGA text and graphic modes and Hercules graphics mode */
6357	/* similar to CR00, actual value - 5 */
6358	ChipsNew->XR[0x1B] = lcdHTotal & 0xFF;
6359
6360	/*XR1C: Alternate horizontal blank start (CRT mode) */
6361	/*      /horizontal panel size (FP mode) */
6362	/* FP horizontal panel size (FP mode), */
6363	/* actual value - 1 (in characters unit) */
6364	/* CRT horizontal blank start (CRT mode) */
6365	/* similar to CR02, actual value - 1 */
6366	ChipsNew->XR[0x1C] = lcdHDisplay & 0xFF;
6367
6368	if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) {
6369	    /* for ext. packed pixel mode on 64520/64530 */
6370	    /* no need to rescale: used only in 65530    */
6371	    ChipsNew->XR[0x21] = lcdHRetraceStart & 0xFF;
6372	    ChipsNew->XR[0x22] = lcdHRetraceEnd & 0x1F;
6373	    ChipsNew->XR[0x23] = lcdHTotal & 0xFF;
6374
6375	    /* vertical timing registers */
6376	    lcdVTotal = mode->CrtcVTotal - 2;
6377	    lcdVDisplay = cPtr->PanelSize.VDisplay - 1;
6378	    lcdVRetraceStart = mode->CrtcVSyncStart;
6379	    lcdVRetraceEnd = mode->CrtcVSyncEnd;
6380
6381	    ChipsNew->XR[0x64] = lcdVTotal & 0xFF;
6382	    ChipsNew->XR[0x66] = lcdVRetraceStart & 0xFF;
6383	    ChipsNew->XR[0x67] = lcdVRetraceEnd & 0x0F;
6384	    ChipsNew->XR[0x68] = lcdVDisplay & 0xFF;
6385	    ChipsNew->XR[0x65] = ((lcdVTotal & 0x100) >> 8)
6386		| ((lcdVDisplay & 0x100) >> 7)
6387		| ((lcdVRetraceStart & 0x100) >> 6)
6388		| ((lcdVRetraceStart & 0x400) >> 7)
6389		| ((lcdVTotal & 0x400) >> 6)
6390		| ((lcdVTotal & 0x200) >> 4)
6391		| ((lcdVDisplay & 0x200) >> 3)
6392		| ((lcdVRetraceStart & 0x200) >> 2);
6393
6394	    /*
6395	     * These are important: 0x2C specifies the numbers of lines
6396	     * (hsync pulses) between vertical blank start and vertical
6397	     * line total, 0x2D specifies the number of clock ticks? to
6398	     * horiz. blank start ( caution ! 16bpp/24bpp modes: that's
6399	     * why we need HSyncStart - can't use mode->CrtcHSyncStart)
6400	     */
6401	    tmp = ((cPtr->PanelType & ChipsDD) && !(ChipsNew->XR[0x6F] & 0x02))
6402	      ? 1 : 0; /* double LP delay, FLM: 2 lines iff DD+no acc*/
6403	    /* Currently we support 2 FLM schemes: #1: FLM coincides with
6404	     * VTotal ie. the delay is programmed to the difference bet-
6405	     * ween lctVTotal and lcdVRetraceStart.    #2: FLM coincides
6406	     * lcdVRetraceStart - in this case FLM delay will be turned
6407	     * off. To decide which scheme to use we compare the value of
6408	     * XR2C set by the bios to the two schemes. The one that fits
6409	     * better will be used.
6410	     */
6411
6412	    if (ChipsNew->XR[0x2C]  < abs((cPtr->PanelSize.VTotal -
6413		    cPtr->PanelSize.VRetraceStart - tmp - 1) -
6414		    ChipsNew->XR[0x2C]))
6415	        ChipsNew->XR[0x2F] |= 0x80;   /* turn FLM delay off */
6416	    ChipsNew->XR[0x2C] = lcdVTotal - lcdVRetraceStart - tmp;
6417	    /*ChipsNew->XR[0x2D] = (HSyncStart >> (3 - tmp)) & 0xFF;*/
6418	    ChipsNew->XR[0x2D] = (HDisplay >> (3 - tmp)) & 0xFF;
6419	    ChipsNew->XR[0x2F] = (ChipsNew->XR[0x2F] & 0xDF)
6420		| (((HSyncStart >> (3 - tmp)) & 0x100) >> 3);
6421	}
6422
6423	/* set stretching/centering */
6424	if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) {
6425	    ChipsNew->XR[0x51] |= 0x40;   /* enable FP compensation          */
6426	    ChipsNew->XR[0x55] |= 0x01;   /* enable horiz. compensation      */
6427	    ChipsNew->XR[0x57] |= 0x01;   /* enable horiz. compensation      */
6428	    if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH,
6429				     FALSE)) {
6430		if (mode->CrtcHDisplay < 1489)      /* HWBug                 */
6431		    ChipsNew->XR[0x55] |= 0x02;	/* enable auto h-centering   */
6432		else {
6433		    ChipsNew->XR[0x55] &= 0xFD;	/* disable auto h-centering  */
6434		    if (pScrn->bitsPerPixel == 24) /* ? */
6435			ChipsNew->XR[0x56] = (lcdHDisplay - CrtcHDisplay) >> 1;
6436		}
6437	    } else {
6438	      ChipsNew->XR[0x55] &= 0xFD;	/* disable h-centering    */
6439	      ChipsNew->XR[0x56] = 0;
6440	    }
6441	    ChipsNew->XR[0x57] = 0x03;    /* enable v-comp disable v-stretch */
6442	    if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH,
6443				      FALSE)) {
6444		ChipsNew->XR[0x55] |= 0x20; /* enable h-comp disable h-double*/
6445		ChipsNew->XR[0x57] |= 0x60; /* Enable vertical stretching    */
6446		tmp = (mode->CrtcVDisplay / (cPtr->PanelSize.VDisplay -
6447		    mode->CrtcVDisplay + 1));
6448		if (tmp) {
6449			if (cPtr->PanelSize.HDisplay
6450			    && cPtr->PanelSize.VDisplay
6451			    && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay)
6452			 && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) {
6453			    /* Possible H/W bug? */
6454			    if(cPtr->Accel.UseHWCursor)
6455				xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
6456				    "Disabling HW Cursor on stretched LCD\n");
6457			    cPtr->Flags &= ~ChipsHWCursor;
6458			}
6459		    }
6460		if (cPtr->Flags & ChipsHWCursor)
6461		    tmp = (tmp == 0 ? 1 : tmp);  /* Bug when doubling */
6462		ChipsNew->XR[0x5A] = tmp > 0x0F ? 0 : (unsigned char)tmp;
6463	    } else {
6464		ChipsNew->XR[0x55] &= 0xDF; /* disable h-comp, h-double */
6465		ChipsNew->XR[0x57] &= 0x9F; /* disable vertical stretching  */
6466	    }
6467	}
6468    }
6469
6470    /* set video mode */
6471    ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, (cPtr->PanelType & ChipsLCD) ?
6472	min(HDisplay, cPtr->PanelSize.HDisplay) : HDisplay,cPtr->PanelSize.VDisplay);
6473#ifdef DEBUG
6474    ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]);
6475#endif
6476
6477    /* set some linear specific registers */
6478    if (cPtr->Flags & ChipsLinearSupport) {
6479	/* enable linear addressing  */
6480	ChipsNew->XR[0x0B] &= 0xFD;   /* dual page clear                */
6481	ChipsNew->XR[0x0B] |= 0x10;   /* linear mode on                 */
6482 	if (cPtr->Chipset == CHIPS_CT65535)
6483 	    ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 17);
6484 	else if (cPtr->Chipset > CHIPS_CT65535)
6485 	    ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 20);
6486	else {
6487            /* Its probably set correctly by BIOS anyway. Leave it alone    */
6488	    /* 65525 - 65530 require XR04[6] set for greater than 512k of   */
6489            /* ram. We only correct obvious bugs; VL probably uses MEMR/MEMW*/
6490	    if (cPtr->Bus == ChipsISA)
6491		ChipsNew->XR[0x04] &= ~0x40;  /* A19 sceme       */
6492	    if (pScrn->videoRam > 512)
6493		ChipsNew->XR[0x04] |= 0x40;   /* MEMR/MEMW sceme */
6494	}
6495
6496	/* general setup */
6497	ChipsNew->XR[0x03] |= 0x08;   /* High bandwidth on 65548         */
6498	ChipsNew->XR[0x40] = 0x01;    /*BitBLT Draw Mode for 8 and 24 bpp */
6499    }
6500
6501    /* common general setup */
6502    ChipsNew->XR[0x52] |= 0x01;       /* Refresh count                   */
6503    ChipsNew->XR[0x0F] &= 0xEF;       /* not Hi-/True-Colour             */
6504    ChipsNew->XR[0x02] |= 0x01;       /* 16bit CPU Memory Access         */
6505    ChipsNew->XR[0x02] &= 0xE3;       /* Attr. Cont. default access      */
6506                                      /* use ext. regs. for hor. in dual */
6507    ChipsNew->XR[0x06] &= 0xF3;       /* bpp clear                       */
6508
6509    /* PCI */
6510    if (cPtr->Bus == ChipsPCI)
6511	ChipsNew->XR[0x03] |= 0x40;   /*PCI burst */
6512
6513    /* sync. polarities */
6514    if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
6515	&& (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
6516	if (mode->Flags & (V_PHSYNC | V_NHSYNC)) {
6517	    if (mode->Flags & V_PHSYNC) {
6518		ChipsNew->XR[0x55] &= 0xBF;	/* CRT Hsync positive */
6519	    } else {
6520		ChipsNew->XR[0x55] |= 0x40;	/* CRT Hsync negative */
6521	    }
6522	}
6523	if (mode->Flags & (V_PVSYNC | V_NVSYNC)) {
6524	    if (mode->Flags & V_PVSYNC) {
6525		ChipsNew->XR[0x55] &= 0x7F;	/* CRT Vsync positive */
6526	    } else {
6527		ChipsNew->XR[0x55] |= 0x80;	/* CRT Vsync negative */
6528	    }
6529	}
6530    }
6531
6532    /* bpp depend */
6533    /*XR06: Palette control */
6534    /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def)  */
6535    /* bit 1: Internal DAC disable                                   */
6536    /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */
6537    /*          2 for 24 bpp, 3 for 16(5-6-5)bpp                     */
6538    /* bit 4:   Enable PC Video Overlay on colour key                */
6539    /* bit 5:   Bypass Internal VGA palette                          */
6540    /* bit 7-6: Colour reduction select, 0 for NTSC (default),       */
6541    /*          1 for Equivalent weighting, 2 for green only,        */
6542    /*          3 for Colour w/o reduction                           */
6543    /* XR50 Panel Format Register 1                                  */
6544    /* bit 1-0: Frame Rate Control; 00, No FRC;                      */
6545    /*          01, 16-frame FRC for colour STN and monochrome       */
6546    /*          10, 2-frame FRC for colour TFT or monochrome;        */
6547    /*          11, reserved                                         */
6548    /* bit 3-2: Dither Enable                                        */
6549    /*          00, disable dithering; 01, enable dithering          */
6550    /*          for 256 mode                                         */
6551    /*          10, enable dithering for all modes; 11, reserved     */
6552    /* bit6-4: Clock Divide (CD)                                     */
6553    /*          000, Shift Clock Freq = Dot Clock Freq;              */
6554    /*          001, SClk = DClk/2; 010 SClk = DClk/4;               */
6555    /*          011, SClk = DClk/8; 100 SClk = DClk/16;              */
6556    /* bit 7: TFT data width                                         */
6557    /*          0, 16 bit(565RGB); 1, 24bit (888RGB)                 */
6558    if (pScrn->bitsPerPixel == 16) {
6559	ChipsNew->XR[0x06] |= 0xC4;   /*15 or 16 bpp colour         */
6560	ChipsNew->XR[0x0F] |= 0x10;   /*Hi-/True-Colour             */
6561	ChipsNew->XR[0x40] = 0x02;    /*BitBLT Draw Mode for 16 bpp */
6562	if (pScrn->weight.green != 5)
6563	    ChipsNew->XR[0x06] |= 0x08;	/*16bpp              */
6564    } else if (pScrn->bitsPerPixel == 24) {
6565	ChipsNew->XR[0x06] |= 0xC8;   /*24 bpp colour               */
6566	ChipsNew->XR[0x0F] |= 0x10;   /*Hi-/True-Colour             */
6567	if (xf86ReturnOptValBool(cPtr->Options, OPTION_18_BIT_BUS, FALSE)) {
6568	    ChipsNew->XR[0x50] &= 0x7F;   /*18 bit TFT data width   */
6569	} else {
6570	    ChipsNew->XR[0x50] |= 0x80;   /*24 bit TFT data width   */
6571	}
6572    }
6573
6574    /*CRT only: interlaced mode */
6575    if (!(cPtr->PanelType & ChipsLCD)) {
6576	if (mode->Flags & V_INTERLACE){
6577	    ChipsNew->XR[0x28] |= 0x20;    /* set interlace         */
6578	    /* empirical value       */
6579	    tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1)
6580		- 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 ));
6581	    if(cPtr->Chipset < CHIPS_CT65535)
6582		ChipsNew->XR[0x19] = tmp & 0xFF;
6583	    else
6584		ChipsNew->XR[0x29] = tmp & 0xFF;
6585 	    ChipsNew->XR[0x0F] &= ~0x40;   /* set SW-Flag           */
6586	} else {
6587	    ChipsNew->XR[0x28] &= ~0x20;   /* unset interlace       */
6588 	    ChipsNew->XR[0x0F] |=  0x40;   /* set SW-Flag           */
6589	}
6590    }
6591
6592    /* STN specific */
6593    if (IS_STN(cPtr->PanelType)) {
6594	ChipsNew->XR[0x50] &= ~0x03;  /* FRC clear                  */
6595	ChipsNew->XR[0x50] |= 0x01;   /* 16 frame FRC               */
6596	ChipsNew->XR[0x50] &= ~0x0C;  /* Dither clear               */
6597	ChipsNew->XR[0x50] |= 0x08;   /* Dither all modes           */
6598 	if (cPtr->Chipset == CHIPS_CT65548) {
6599	    ChipsNew->XR[0x03] |= 0x20; /* CRT I/F priority           */
6600	    ChipsNew->XR[0x04] |= 0x10; /* RAS precharge 65548        */
6601	}
6602    }
6603
6604    /* This stuff was emprically derived several years ago. Not sure its
6605     * still needed, and I'd love to get rid of it as its ugly
6606     */
6607    switch (cPtr->Chipset) {
6608    case CHIPS_CT65545:		  /*jet mini *//*DEC HighNote Ultra DSTN */
6609	ChipsNew->XR[0x03] |= 0x10;   /* do not hold off CPU for palette acc*/
6610	break;
6611    case CHIPS_CT65546:			       /*CT 65546, only for Toshiba */
6612	ChipsNew->XR[0x05] |= 0x80;   /* EDO RAM enable */
6613	break;
6614    }
6615
6616    if (cPtr->PanelType & ChipsLCD)
6617        ChipsNew->XR[0x51] |= 0x04;
6618    else
6619        ChipsNew->XR[0x51] &= ~0x04;
6620
6621    /* Program the registers */
6622    /*vgaHWProtect(pScrn, TRUE);*/
6623    chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE);
6624    /*vgaHWProtect(pScrn, FALSE);*/
6625
6626    return (TRUE);
6627}
6628
6629static void
6630chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, CHIPSRegPtr ChipsReg,
6631	     Bool restoreFonts)
6632{
6633    vgaHWPtr hwp = VGAHWPTR(pScrn);
6634    CHIPSPtr cPtr = CHIPSPTR(pScrn);
6635    unsigned char tmp = 0;
6636
6637    /*vgaHWProtect(pScrn, TRUE);*/
6638
6639    /* set registers so that we can program the controller */
6640    if (IS_HiQV(cPtr)) {
6641	cPtr->writeXR(cPtr, 0x0E, 0x00);
6642	if (cPtr->Flags & ChipsDualChannelSupport) {
6643	    tmp = cPtr->readFR(cPtr, 0x01);		/* Disable pipeline */
6644	    cPtr->writeFR(cPtr, 0x01, (tmp & 0xFC));
6645	    cPtr->writeFR(cPtr, 0x02, 0x00);		/* CRT/FP off */
6646	}
6647    } else {
6648	cPtr->writeXR(cPtr, 0x10, 0x00);
6649	cPtr->writeXR(cPtr, 0x11, 0x00);
6650	tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */
6651	cPtr->writeXR(cPtr, 0x0C, tmp);
6652	cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect all registers */
6653	tmp = cPtr->readXR(cPtr, 0x14);
6654	cPtr->writeXR(cPtr, 0x14, tmp & ~0x20);  /* enable vsync on ST01 */
6655    }
6656
6657    chipsFixResume(pScrn);
6658
6659    /*
6660     * Wait for vsync if sequencer is running - stop sequencer.
6661     * Only do if sync reset is ignored. Dual pipeline capable
6662     * chips have pipeline forced off here, so we don't care.
6663     */
6664    if ((cPtr->SyncResetIgn)  && (!(cPtr->Flags & ChipsDualChannelSupport))) {
6665	while (((hwp->readST01(hwp)) & 0x08) == 0x08); /* VSync off */
6666	while (((hwp->readST01(hwp)) & 0x08) == 0x00); /* VSync on  */
6667	hwp->writeSeq(hwp, 0x07, 0x00); /* reset hsync - just in case...  */
6668    }
6669
6670    /* set the clock */
6671    chipsClockLoad(pScrn, &ChipsReg->Clock);
6672    /* chipsClockLoad() sets this so we don't want vgaHWRestore() change it */
6673    VgaReg->MiscOutReg = inb(cPtr->PIOBase + 0x3CC);
6674
6675    /* set extended regs */
6676    chipsRestoreExtendedRegs(pScrn, ChipsReg);
6677#if 0
6678    /* if people complain about lock ups or blank screens -- reenable */
6679    /* set CRTC registers - do it before sequencer restarts */
6680    for (i=0; i<25; i++)
6681	hwp->writeCrtc(hwp, i, VgaReg->CRTC[i]);
6682#endif
6683    /* set generic registers */
6684    /*
6685     * Enabling writing to the colourmap causes 69030's to lock.
6686     * Anyone care to explain to me why ????
6687     */
6688    if (cPtr->Flags & ChipsDualChannelSupport) {
6689        /* Enable pipeline if needed */
6690        cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]);
6691	cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]);
6692	vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE |
6693		(restoreFonts ? VGA_SR_FONTS : 0));
6694    } else {
6695	vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | VGA_SR_CMAP |
6696		     (restoreFonts ? VGA_SR_FONTS : 0));
6697    }
6698
6699    /* set stretching registers */
6700    if (IS_HiQV(cPtr)) {
6701	chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40],
6702			       (unsigned char)ChipsReg->FR[0x48]);
6703#if 0
6704	/* if people report about stretching not working -- reenable */
6705	/* why twice ? :
6706	 * sometimes the console is not well restored even if these registers
6707	 * are good, re-write the registers works around it
6708	 */
6709	chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40],
6710			       (unsigned char)ChipsReg->FR[0x48]);
6711#endif
6712    } else if (!IS_Wingine(cPtr))
6713	chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->XR[0x55],
6714			       (unsigned char)ChipsReg->XR[0x57]);
6715
6716    /* perform a synchronous reset */
6717    if (!cPtr->SyncResetIgn) {
6718	if (!IS_HiQV(cPtr)) {
6719	    /* enable syncronous reset on 655xx */
6720	    tmp = cPtr->readXR(cPtr, 0x0E);
6721	    cPtr->writeXR(cPtr, 0x0E, tmp & 0x7F);
6722	}
6723	hwp->writeSeq(hwp, 0x00, 0x01);
6724	usleep(10000);
6725	hwp->writeSeq(hwp, 0x00, 0x03);
6726	if (!IS_HiQV(cPtr))
6727	    cPtr->writeXR(cPtr, 0x0E, tmp);
6728    }
6729    /* Flag valid start address, if using CRT extensions */
6730    if (IS_HiQV(cPtr) && (ChipsReg->XR[0x09] & 0x1) == 0x1) {
6731	tmp = hwp->readCrtc(hwp, 0x40);
6732	hwp->writeCrtc(hwp, 0x40, tmp | 0x80);
6733    }
6734
6735    /* Fix resume again here, as Nozomi seems to need it          */
6736     chipsFixResume(pScrn);
6737    /*vgaHWProtect(pScrn, FALSE);*/
6738
6739#if 0
6740     /* Enable pipeline if needed */
6741     if (cPtr->Flags & ChipsDualChannelSupport) {
6742	cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]);
6743	cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]);
6744     }
6745#endif
6746}
6747
6748static void
6749chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs)
6750{
6751    vgaHWPtr hwp = VGAHWPTR(pScrn);
6752    CHIPSPtr cPtr = CHIPSPTR(pScrn);
6753    int i;
6754    unsigned char tmp;
6755
6756    if (IS_HiQV(cPtr)) {
6757	/* set extended regs */
6758	for (i = 0; i < 0x43; i++) {
6759	    if ((cPtr->readXR(cPtr, i)) != Regs->XR[i])
6760		cPtr->writeXR(cPtr, i, Regs->XR[i]);
6761	}
6762
6763	/* Set SAR04 multimedia register correctly */
6764	if ((cPtr->Flags & ChipsOverlay8plus16)
6765	    || (cPtr->Flags & ChipsVideoSupport)) {
6766#ifdef SAR04
6767	    cPtr->writeXR(cPtr, 0x4E, 0x04);
6768	    if (cPtr->readXR(cPtr, 0x4F) != Regs->XR[0x4F])
6769		cPtr->writeXR(cPtr, 0x4F, Regs->XR[0x4F]);
6770#endif
6771	}
6772
6773	/* Don't touch reserved memory control registers */
6774	for (i = 0x50; i < 0xBF; i++) {
6775	    if ((cPtr->readXR(cPtr, i)) != Regs->XR[i])
6776		cPtr->writeXR(cPtr, i, Regs->XR[i]);
6777	}
6778	/* Don't touch VCLK regs, but fix up MClk */
6779
6780	/* set mem clock */
6781	tmp = cPtr->readXR(cPtr, 0xCE); /* Select Fixed MClk before */
6782	cPtr->writeXR(cPtr, 0xCE, tmp & 0x7F);
6783	if ((cPtr->readXR(cPtr, 0xCC)) != Regs->XR[0xCC])
6784	    cPtr->writeXR(cPtr, 0xCC, Regs->XR[0xCC]);
6785	if ((cPtr->readXR(cPtr, 0xCD)) != Regs->XR[0xCD])
6786	    cPtr->writeXR(cPtr, 0xCD, Regs->XR[0xCD]);
6787	if ((cPtr->readXR(cPtr, 0xCE)) != Regs->XR[0xCE])
6788	    cPtr->writeXR(cPtr, 0xCE, Regs->XR[0xCE]);
6789
6790	/* set flat panel regs. */
6791	for (i = 0xD0; i < 0xFF; i++) {
6792	    if ((cPtr->readXR(cPtr, i)) != Regs->XR[i])
6793		cPtr->writeXR(cPtr, i, Regs->XR[i]);
6794	}
6795
6796	for (i = 0; i < 0x80; i++) {
6797	    /* Don't touch alternate clock select reg. */
6798	    if ((i == 0x01) && (cPtr->Chipset == CHIPS_CT69030)) {
6799	    	/* restore the non clock bits */
6800		tmp = cPtr->readFR(cPtr, 0x01);
6801		cPtr->writeFR(cPtr, 0x01, ((Regs->FR[0x01] & 0xF0) |
6802				(tmp & ~0xF0)));
6803		continue;
6804	    }
6805
6806	    if ((i == 0x02) && (cPtr->Chipset == CHIPS_CT69030))
6807	    	/* keep pipeline disabled till we are ready */
6808		continue;
6809
6810	    if ((i == 0x03) && (cPtr->Chipset != CHIPS_CT69030)) {
6811	    	/* restore the non clock bits */
6812		tmp = cPtr->readFR(cPtr, 0x03);
6813		cPtr->writeFR(cPtr, 0x03, ((Regs->FR[0x03] & 0xC3) |
6814				(tmp & ~0xC3)));
6815		continue;
6816	    }
6817
6818	    if ((i > 0x03) && (cPtr->Chipset != CHIPS_CT69030) &&
6819				(cPtr->SecondCrtc == TRUE))
6820		continue;
6821
6822	    if ( (i == 0x40) || (i==0x48)) {
6823	      /* !! set stretching but disable compensation   */
6824	      cPtr->writeFR(cPtr, i, Regs->FR[i] & 0xFE);
6825	      continue ;     /* some registers must be set before FR40/FR48 */
6826	    }
6827	    if ((cPtr->readFR(cPtr, i)) != Regs->FR[i]) {
6828		cPtr->writeFR(cPtr, i, Regs->FR[i]);
6829	    }
6830	}
6831
6832	/* set the multimedia regs */
6833	for (i = 0x02; i < 0x80; i++) {
6834	    if ( (i == 0x43) || (i == 0x44))
6835		continue;
6836	    if ((cPtr->readMR(cPtr, i)) != Regs->MR[i])
6837		cPtr->writeMR(cPtr, i, Regs->MR[i]);
6838	}
6839
6840	/* set extended crtc regs. */
6841	for (i = 0x30; i < 0x80; i++) {
6842	    if ((hwp->readCrtc(hwp, i)) != Regs->CR[i])
6843		hwp->writeCrtc(hwp, i, Regs->CR[i]);
6844	}
6845    } else {
6846	/* set extended regs. */
6847	for (i = 0; i < 0x30; i++) {
6848	    if ((cPtr->readXR(cPtr, i)) != Regs->XR[i])
6849		cPtr->writeXR(cPtr, i, Regs->XR[i]);
6850	}
6851	cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect just in case ... */
6852	/* Don't touch MCLK/VCLK regs. */
6853	for (i = 0x34; i < 0x54; i++) {
6854	    if ((cPtr->readXR(cPtr, i)) != Regs->XR[i])
6855		cPtr->writeXR(cPtr, i, Regs->XR[i]);
6856	}
6857	tmp = cPtr->readXR(cPtr, 0x54);	/*  restore the non clock bits     */
6858	cPtr->writeXR(cPtr, 0x54, ((Regs->XR[0x54] & 0xF3) | (tmp & ~0xF3)));
6859	cPtr->writeXR(cPtr, 0x55, Regs->XR[0x55] & 0xFE); /* h-comp off     */
6860	cPtr->writeXR(cPtr, 0x56, Regs->XR[0x56]);
6861	cPtr->writeXR(cPtr, 0x57, Regs->XR[0x57] & 0xFE); /* v-comp off     */
6862	for (i=0x58; i < 0x7D; i++) {/* don't touch XR7D and XR7F on WINGINE */
6863	    if ((cPtr->readXR(cPtr, i)) != Regs->XR[i])
6864		cPtr->writeXR(cPtr, i, Regs->XR[i]);
6865	}
6866    }
6867#ifdef DEBUG
6868    /* debug - dump out all the extended registers... */
6869    if (IS_HiQV(cPtr)) {
6870	for (i = 0; i < 0xFF; i++) {
6871	    ErrorF("XR%X - %X : %X\n", i, Regs->XR[i],
6872		   cPtr->readXR(cPtr, i));
6873	}
6874	for (i = 0; i < 0x80; i++) {
6875	    ErrorF("FR%X - %X : %X\n", i, Regs->FR[i],
6876		   cPtr->readFR(cPtr, i));
6877	}
6878    } else {
6879	for (i = 0; i < 0x80; i++) {
6880	    ErrorF("XR%X - %X : %X\n", i, Regs->XR[i],
6881		   cPtr->readXR(cPtr, i));
6882	}
6883    }
6884#endif
6885}
6886
6887static void
6888chipsRestoreStretching(ScrnInfoPtr pScrn, unsigned char ctHorizontalStretch,
6889		       unsigned char ctVerticalStretch)
6890{
6891    unsigned char tmp;
6892    CHIPSPtr cPtr = CHIPSPTR(pScrn);
6893
6894    /* write to regs. */
6895    if (IS_HiQV(cPtr)) {
6896	tmp = cPtr->readFR(cPtr, 0x48);
6897	cPtr->writeFR(cPtr, 0x48, (tmp & 0xFE) | (ctVerticalStretch & 0x01));
6898	tmp = cPtr->readFR(cPtr, 0x40);
6899	cPtr->writeFR(cPtr, 0x40, (tmp & 0xFE) | (ctHorizontalStretch & 0x01));
6900    } else {
6901	tmp = cPtr->readXR(cPtr, 0x55);
6902	cPtr->writeXR(cPtr, 0x55, (tmp & 0xFE) | (ctHorizontalStretch & 0x01));
6903	tmp = cPtr->readXR(cPtr, 0x57);
6904	cPtr->writeXR(cPtr, 0x57, (tmp & 0xFE) | (ctVerticalStretch & 0x01));
6905    }
6906
6907    usleep(20000);			/* to be active */
6908}
6909
6910static int
6911chipsVideoMode(int depth, int displayHSize,
6912	       int displayVSize)
6913{
6914    /*     4 bpp  8 bpp  16 bpp  18 bpp  24 bpp  32 bpp */
6915    /* 640  0x20   0x30    0x40    -      0x50     -    */
6916    /* 800  0x22   0x32    0x42    -      0x52     -    */
6917    /*1024  0x24   0x34    0x44    -      0x54     -    for 1024x768 */
6918    /*1024   -     0x36    0x47    -      0x56     -    for 1024x600 */
6919    /*1152  0x27   0x37    0x47    -      0x57     -    */
6920    /*1280  0x28   0x38    0x49    -        -      -    */
6921    /*1600  0x2C   0x3C    0x4C   0x5D      -      -    */
6922    /*This value is only for BIOS.... */
6923
6924    int videoMode = 0;
6925
6926    switch (depth) {
6927    case 1:
6928    case 4:
6929	videoMode = 0x20;
6930	break;
6931    case 8:
6932	videoMode = 0x30;
6933	break;
6934    case 15:
6935	videoMode = 0x40;
6936	break;
6937    case 16:
6938	videoMode = 0x41;
6939	break;
6940    default:
6941	videoMode = 0x50;
6942	break;
6943    }
6944
6945    switch (displayHSize) {
6946    case 800:
6947	videoMode |= 0x02;
6948	break;
6949    case 1024:
6950	videoMode |= 0x04;
6951	if(displayVSize < 768)
6952	    videoMode |= 0x02;
6953	break;
6954    case 1152:
6955	videoMode |= 0x07;
6956	break;
6957    case 1280:
6958	videoMode |= 0x08;
6959	break;
6960    case 1600:
6961	videoMode |= 0x0C; /*0x0A??*/
6962	break;
6963    }
6964
6965    return videoMode;
6966}
6967
6968
6969/*
6970 * Map the framebuffer and MMIO memory.
6971 */
6972
6973static Bool
6974chipsMapMem(ScrnInfoPtr pScrn)
6975{
6976    CHIPSPtr cPtr = CHIPSPTR(pScrn);
6977    vgaHWPtr hwp = VGAHWPTR(pScrn);
6978    CHIPSEntPtr cPtrEnt;
6979
6980    if (cPtr->Flags & ChipsLinearSupport) {
6981	if (cPtr->UseMMIO) {
6982	    if (IS_HiQV(cPtr)) {
6983#ifndef XSERVER_LIBPCIACCESS
6984		if (cPtr->pEnt->location.type == BUS_PCI)
6985		    cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex,
6986			   VIDMEM_MMIO_32BIT,cPtr->PciTag, cPtr->IOAddress,
6987			   0x20000L);
6988		 else
6989		    cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex,
6990			   VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x20000L);
6991#else
6992		{
6993		    if (cPtr->pEnt->location.type == BUS_PCI) {
6994		        void** result = (void**)&cPtr->MMIOBase;
6995		        int err = pci_device_map_range(cPtr->PciInfo,
6996						 cPtr->IOAddress,
6997						 0x20000L,
6998						 PCI_DEV_MAP_FLAG_WRITABLE,
6999						 result);
7000		        if (err) {
7001			    xf86Msg(X_ERROR, "PCI mmap failed\n");
7002		            return FALSE;
7003			}
7004		    } else
7005			cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex,
7006			   VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x20000L);
7007
7008		}
7009#endif
7010	    } else {
7011#ifndef XSERVER_LIBPCIACCESS
7012		if (cPtr->pEnt->location.type == BUS_PCI)
7013		    cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex,
7014			  VIDMEM_MMIO_32BIT, cPtr->PciTag, cPtr->IOAddress,
7015			  0x10000L);
7016		else
7017		    cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex,
7018			  VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x10000L);
7019#else
7020		{
7021		    if (cPtr->pEnt->location.type == BUS_PCI) {
7022			void** result = (void**)&cPtr->MMIOBase;
7023			int err = pci_device_map_range(cPtr->PciInfo,
7024						 cPtr->IOAddress,
7025						 0x10000L,
7026						 PCI_DEV_MAP_FLAG_WRITABLE,
7027						 result);
7028		        if (err) {
7029			    xf86Msg(X_ERROR, "PCI mmap failed\n");
7030		            return FALSE;
7031			}
7032		    } else
7033		        cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex,
7034			  VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x10000L);
7035		}
7036#endif
7037	    }
7038
7039	    if (cPtr->MMIOBase == NULL)
7040		return FALSE;
7041	}
7042	if (cPtr->FbMapSize) {
7043	  unsigned long Addr = (unsigned long)cPtr->FbAddress;
7044	  unsigned int Map =  cPtr->FbMapSize;
7045
7046	  if ((cPtr->Flags & ChipsDualChannelSupport) &&
7047	      (xf86IsEntityShared(pScrn->entityList[0]))) {
7048	      cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
7049					     CHIPSEntityIndex)->ptr;
7050	    if(cPtr->SecondCrtc == FALSE) {
7051	      Addr = cPtrEnt->masterFbAddress;
7052	      Map = cPtrEnt->masterFbMapSize;
7053	    } else {
7054	      Addr = cPtrEnt->slaveFbAddress;
7055	      Map = cPtrEnt->slaveFbMapSize;
7056	    }
7057	  }
7058
7059#ifndef XSERVER_LIBPCIACCESS
7060	  if (cPtr->pEnt->location.type == BUS_PCI)
7061	      cPtr->FbBase = xf86MapPciMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER,
7062 			          cPtr->PciTag, Addr, Map);
7063
7064	  else
7065	      cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER,
7066					   Addr, Map);
7067#else
7068	  if (cPtr->pEnt->location.type == BUS_PCI) {
7069	    void** result = (void**)&cPtr->FbBase;
7070	    int err = pci_device_map_range(cPtr->PciInfo,
7071					   Addr,
7072					   Map,
7073					   PCI_DEV_MAP_FLAG_WRITABLE |
7074					   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
7075					   result);
7076		        if (err) {
7077			    xf86Msg(X_ERROR, "PCI mmap fb failed\n");
7078		            return FALSE;
7079			}
7080	  } else
7081	      cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER,
7082					   Addr, Map);
7083
7084#endif
7085
7086	  if (cPtr->FbBase == NULL)
7087	      return FALSE;
7088	}
7089	if (cPtr->Flags & ChipsFullMMIOSupport) {
7090#ifndef XSERVER_LIBPCIACCESS
7091		cPtr->MMIOBaseVGA = xf86MapPciMem(pScrn->scrnIndex,
7092						  VIDMEM_MMIO,cPtr->PciTag,
7093						  cPtr->IOAddress, 0x2000L);
7094#else
7095		cPtr->MMIOBaseVGA = cPtr->MMIOBase;
7096#endif
7097	    /* 69030 MMIO Fix.
7098	     *
7099	     * The hardware lets us map the PipeB data registers
7100	     * into the MMIO address space normally occupied by PipeA,
7101	     * but it doesn't allow remapping of the index registers.
7102	     * So we're forced to map a separate MMIO space for each
7103	     * pipe and to toggle between them as necessary. -GHB
7104	     */
7105	    if (cPtr->Flags & ChipsDualChannelSupport)
7106#ifndef XSERVER_LIBPCIACCESS
7107	       	cPtr->MMIOBasePipeB = xf86MapPciMem(pScrn->scrnIndex,
7108				      VIDMEM_MMIO,cPtr->PciTag,
7109				      cPtr->IOAddress + 0x800000, 0x2000L);
7110#else
7111	    {
7112	      void** result = (void**)&cPtr->MMIOBasePipeB;
7113	      int err = pci_device_map_range(cPtr->PciInfo,
7114					     cPtr->IOAddress + 0x800000,
7115					     0x2000L,
7116					     PCI_DEV_MAP_FLAG_WRITABLE,
7117					     result);
7118	      if (err)
7119		return FALSE;
7120	    }
7121#endif
7122
7123	    cPtr->MMIOBasePipeA = cPtr->MMIOBaseVGA;
7124	}
7125    } else {
7126	/* In paged mode Base is the VGA window at 0xA0000 */
7127	cPtr->FbBase = hwp->Base;
7128    }
7129
7130    return TRUE;
7131}
7132
7133
7134/*
7135 * Unmap the framebuffer and MMIO memory.
7136 */
7137
7138static Bool
7139chipsUnmapMem(ScrnInfoPtr pScrn)
7140{
7141    CHIPSPtr cPtr = CHIPSPTR(pScrn);
7142
7143    if (cPtr->Flags & ChipsLinearSupport) {
7144	if (IS_HiQV(cPtr)) {
7145#ifndef XSERVER_LIBPCIACCESS
7146	    if (cPtr->MMIOBase)
7147		xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase,
7148				0x20000);
7149	    if (cPtr->MMIOBasePipeB)
7150		xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBasePipeB,
7151				0x20000);
7152#else
7153	    if (cPtr->MMIOBase)
7154	      pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x20000);
7155
7156	    if (cPtr->MMIOBasePipeB)
7157	      pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBasePipeB, 0x2000);
7158
7159#endif
7160	    cPtr->MMIOBasePipeB = NULL;
7161	} else {
7162#ifndef XSERVER_LIBPCIACCESS
7163	  if (cPtr->MMIOBase)
7164	      xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase,
7165			      0x10000);
7166#else
7167	    if (cPtr->MMIOBase)
7168	      pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x10000);
7169#endif
7170	}
7171	cPtr->MMIOBase = NULL;
7172#ifndef XSERVER_LIBPCIACCESS
7173	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->FbBase,
7174			cPtr->FbMapSize);
7175#else
7176	pci_device_unmap_range(cPtr->PciInfo, cPtr->FbBase, cPtr->FbMapSize);
7177#endif
7178    }
7179    cPtr->FbBase = NULL;
7180
7181    return TRUE;
7182}
7183
7184static void
7185chipsProtect(ScrnInfoPtr pScrn, Bool on)
7186{
7187    vgaHWProtect(pScrn, on);
7188}
7189
7190static void
7191chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank)
7192{
7193    CHIPSPtr cPtr = CHIPSPTR(pScrn);
7194    vgaHWPtr hwp = VGAHWPTR(pScrn);
7195    unsigned char scrn;
7196    CHIPSEntPtr cPtrEnt;
7197
7198    if (cPtr->UseDualChannel) {
7199        cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0],
7200					       CHIPSEntityIndex)->ptr;
7201	DUALREOPEN;
7202    }
7203
7204    /* fix things that could be messed up by suspend/resume */
7205    if (!IS_HiQV(cPtr))
7206	cPtr->writeXR(cPtr, 0x15, 0x00);
7207
7208    scrn = hwp->readSeq(hwp, 0x01);
7209
7210    if (unblank) {
7211	scrn &= 0xDF;                       /* enable screen */
7212    } else {
7213	scrn |= 0x20;                       /* blank screen */
7214    }
7215
7216    /* synchronous reset - stop counters */
7217    if (!cPtr->SyncResetIgn) {
7218	hwp->writeSeq(hwp, 0x00, 0x01);
7219    }
7220
7221    hwp->writeSeq(hwp, 0x01, scrn); /* change mode */
7222
7223    /* end reset - start counters */
7224    if (!cPtr->SyncResetIgn) {
7225	hwp->writeSeq(hwp, 0x00, 0x03);
7226    }
7227
7228    if ((cPtr->UseDualChannel) &&
7229		(! xf86IsEntityShared(pScrn->entityList[0]))) {
7230	unsigned int IOSS, MSS;
7231	IOSS = cPtr->readIOSS(cPtr);
7232	MSS = cPtr->readMSS(cPtr);
7233	cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
7234			       IOSS_PIPE_B));
7235	cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B));
7236
7237	/* fix things that could be messed up by suspend/resume */
7238	if (!IS_HiQV(cPtr))
7239	    cPtr->writeXR(cPtr, 0x15, 0x00);
7240
7241	scrn = hwp->readSeq(hwp, 0x01);
7242
7243	if (unblank) {
7244	    scrn &= 0xDF;                       /* enable screen */
7245	} else {
7246	    scrn |= 0x20;                       /* blank screen */
7247	}
7248
7249	/* synchronous reset - stop counters */
7250	if (!cPtr->SyncResetIgn) {
7251	    hwp->writeSeq(hwp, 0x00, 0x01);
7252	}
7253
7254	hwp->writeSeq(hwp, 0x01, scrn); /* change mode */
7255
7256	/* end reset - start counters */
7257	if (!cPtr->SyncResetIgn) {
7258	    hwp->writeSeq(hwp, 0x00, 0x03);
7259	}
7260
7261	cPtr->writeIOSS(cPtr, IOSS);
7262	cPtr->writeMSS(cPtr, hwp, MSS);
7263    }
7264
7265}
7266
7267static void
7268chipsLock(ScrnInfoPtr pScrn)
7269{
7270    vgaHWPtr hwp = VGAHWPTR(pScrn);
7271    CHIPSPtr cPtr = CHIPSPTR(pScrn);
7272    unsigned char tmp;
7273
7274    vgaHWLock(hwp);
7275
7276    if (!IS_HiQV(cPtr)) {
7277	/* group protection attribute controller access */
7278	cPtr->writeXR(cPtr, 0x15, cPtr->SuspendHack.xr15);
7279	tmp = cPtr->readXR(cPtr, 0x02);
7280	cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18) | cPtr->SuspendHack.xr02);
7281	tmp = cPtr->readXR(cPtr, 0x14);
7282	cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20) | cPtr->SuspendHack.xr14);
7283
7284	/* reset 32 bit register access */
7285	if (cPtr->Chipset > CHIPS_CT65540) {
7286	    tmp = cPtr->readXR(cPtr, 0x03);
7287	    cPtr->writeXR(cPtr, 0x03, (tmp & ~0x0A) | cPtr->SuspendHack.xr03);
7288	}
7289    }
7290}
7291
7292static void
7293chipsUnlock(ScrnInfoPtr pScrn)
7294{
7295    vgaHWPtr hwp = VGAHWPTR(pScrn);
7296    CHIPSPtr cPtr = CHIPSPTR(pScrn);
7297    unsigned char tmp;
7298
7299    if (!IS_HiQV(cPtr)) {
7300	/* group protection attribute controller access */
7301	cPtr->writeXR(cPtr, 0x15, 0x00);
7302	tmp = cPtr->readXR(cPtr, 0x02);
7303	cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18));
7304	tmp = cPtr->readXR(cPtr, 0x14);
7305	cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20));
7306	/* enable 32 bit register access */
7307	if (cPtr->Chipset > CHIPS_CT65540) {
7308	    cPtr->writeXR(cPtr, 0x03, cPtr->SuspendHack.xr03 | 0x0A);
7309	}
7310    }
7311    vgaHWUnlock(hwp);
7312}
7313
7314static void
7315chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn)
7316{
7317    /* enable HW cursor */
7318    if (cPtr->HWCursorShown) {
7319	if (IS_HiQV(cPtr)) {
7320	    cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF);
7321	    if (cPtr->UseDualChannel &&
7322		(! xf86IsEntityShared(pScrn->entityList[0]))) {
7323		unsigned int IOSS, MSS;
7324		IOSS = cPtr->readIOSS(cPtr);
7325		MSS = cPtr->readMSS(cPtr);
7326		cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) |
7327				       IOSS_PIPE_B));
7328		cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS &
7329					  MSS_MASK) | MSS_PIPE_B));
7330		cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF);
7331		cPtr->writeIOSS(cPtr, IOSS);
7332		cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS);
7333	    }
7334	} else {
7335	    HW_DEBUG(0x8);
7336	    if (cPtr->UseMMIO) {
7337		MMIOmeml(DR(0x8)) = cPtr->HWCursorContents;
7338	    } else {
7339		outl(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents);
7340	    }
7341	}
7342    }
7343}
7344
7345static void
7346chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn)
7347{
7348    /* disable HW cursor */
7349    if (cPtr->HWCursorShown) {
7350	if (IS_HiQV(cPtr)) {
7351	    cPtr->HWCursorContents = cPtr->readXR(cPtr, 0xA0);
7352	    cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xF8);
7353	} else {
7354	    HW_DEBUG(0x8);
7355	    if (cPtr->UseMMIO) {
7356		cPtr->HWCursorContents = MMIOmeml(DR(0x8));
7357		/* Below used to be MMIOmemw() change back if problem!!! */
7358		/* Also see ct_cursor.c */
7359		MMIOmeml(DR(0x8)) = cPtr->HWCursorContents & 0xFFFE;
7360	    } else {
7361		cPtr->HWCursorContents = inl(cPtr->PIOBase + DR(0x8));
7362		outw(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents & 0xFFFE);
7363	    }
7364	}
7365    }
7366}
7367
7368void
7369chipsFixResume(ScrnInfoPtr pScrn)
7370{
7371    CHIPSPtr cPtr = CHIPSPTR(pScrn);
7372    vgaHWPtr hwp = VGAHWPTR(pScrn);
7373    unsigned char tmp;
7374
7375    /* fix things that could be messed up by suspend/resume */
7376    if (!IS_HiQV(cPtr))
7377	cPtr->writeXR(cPtr, 0x15, 0x00);
7378    tmp = hwp->readMiscOut(hwp);
7379    hwp->writeMiscOut(hwp, (tmp & 0xFE) | cPtr->SuspendHack.vgaIOBaseFlag);
7380    tmp = hwp->readCrtc(hwp, 0x11);
7381    hwp->writeCrtc(hwp, 0x11, (tmp & 0x7F));
7382}
7383
7384static char
7385chipsTestDACComp(ScrnInfoPtr pScrn, unsigned char a, unsigned char b,
7386		 unsigned char c)
7387{
7388    vgaHWPtr hwp = VGAHWPTR(pScrn);
7389    unsigned char type;
7390
7391    hwp->writeDacWriteAddr(hwp, 0x00);
7392    while ((hwp->readST01(hwp)) & 0x08){};    /* wait for vsync to end */
7393    while (!(hwp->readST01(hwp)) & 0x08){};   /* wait for new vsync  */
7394    hwp->writeDacData(hwp, a);                /* set pattern */
7395    hwp->writeDacData(hwp, b);
7396    hwp->writeDacData(hwp, c);
7397    while (!(hwp->readST01(hwp)) & 0x01){};   /* wait for hsync to end  */
7398    while ((hwp->readST01(hwp)) & 0x01){};    /* wait for hsync to end  */
7399    type = hwp->readST00(hwp);                /* read comparator        */
7400    return (type & 0x10);
7401}
7402
7403static int
7404chipsProbeMonitor(ScrnInfoPtr pScrn)
7405{
7406    CHIPSPtr cPtr = CHIPSPTR(pScrn);
7407    vgaHWPtr hwp = VGAHWPTR(pScrn);
7408    unsigned char dacmask;
7409    unsigned char dacdata[3];
7410    unsigned char xr1, xr2;
7411    int type = 2;  /* no monitor */
7412    unsigned char IOSS=0, MSS=0, tmpfr02=0, tmpfr01a=0, tmpfr01b=0;
7413
7414    /* Dual channel display, enable both pipelines */
7415    if (cPtr->Flags & ChipsDualChannelSupport) {
7416	IOSS = cPtr->readIOSS(cPtr);
7417	MSS = cPtr->readMSS(cPtr);
7418	tmpfr02 = cPtr->readFR(cPtr,0x02);
7419	cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF)); /* CRT/FP off */
7420	usleep(1000);
7421	cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A));
7422	cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A));
7423	tmpfr01a = cPtr->readFR(cPtr,0x01);
7424	if ((tmpfr01a & 0x3) != 0x01)
7425	  cPtr->writeFR(cPtr, 0x01, ((tmpfr01a & 0xFC) | 0x1));
7426	cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B));
7427	cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B));
7428	tmpfr01b = cPtr->readFR(cPtr,0x01);
7429	if ((tmpfr01b & 0x3) != 0x01)
7430	  cPtr->writeFR(cPtr, 0x01, ((tmpfr01b & 0xFC) | 0x1));
7431	cPtr->writeIOSS(cPtr, IOSS);
7432	cPtr->writeMSS(cPtr, hwp, MSS);
7433	cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF) | 0x10); /* CRT on/FP off*/
7434    }
7435
7436    dacmask = hwp->readDacMask(hwp);    /* save registers */
7437    hwp->writeDacMask(hwp, 0x00);
7438    hwp->writeDacReadAddr(hwp, 0x00);
7439
7440    dacdata[0]=hwp->readDacData(hwp);
7441    dacdata[1]=hwp->readDacData(hwp);
7442    dacdata[2]=hwp->readDacData(hwp);
7443
7444    if (!IS_HiQV(cPtr)) {
7445	xr1 = cPtr->readXR(cPtr, 0x06);
7446	xr2 = cPtr->readXR(cPtr, 0x1F);
7447	cPtr->writeXR(cPtr, 0x06, xr1 & 0xF1);  /* turn on dac */
7448	cPtr->writeXR(cPtr, 0x1F, xr2 & 0x7F);  /* enable comp */
7449    } else {
7450	xr1 = cPtr->readXR(cPtr, 0x81);
7451	xr2 = cPtr->readXR(cPtr, 0xD0);
7452	cPtr->writeXR(cPtr, 0x81,(xr1 & 0xF0));
7453	cPtr->writeXR(cPtr, 0xD0,(xr2 | 0x03));
7454    }
7455    if (chipsTestDACComp(pScrn, 0x12,0x12,0x12)) {         /* test patterns */
7456	if (chipsTestDACComp(pScrn,0x14,0x14,0x14))        /* taken  from   */
7457	    if (!chipsTestDACComp(pScrn,0x2D,0x14,0x14))   /* BIOS          */
7458		if (!chipsTestDACComp(pScrn,0x14,0x2D,0x14))
7459		    if (!chipsTestDACComp(pScrn,0x14,0x14,0x2D))
7460			if (!chipsTestDACComp(pScrn,0x2D,0x2D,0x2D))
7461			    type = 0;    /* color monitor */
7462    } else {
7463	if (chipsTestDACComp(pScrn,0x04,0x12,0x04))
7464	    if (!chipsTestDACComp(pScrn,0x1E,0x12,0x04))
7465		if (!chipsTestDACComp(pScrn,0x04,0x2D,0x04))
7466		    if (!chipsTestDACComp(pScrn,0x1E,0x16,0x15))
7467			if (chipsTestDACComp(pScrn,0x00,0x00,0x00))
7468			    type = 1;    /* monochrome */
7469    }
7470
7471    hwp->writeDacWriteAddr(hwp, 0x00);         /* restore registers */
7472    hwp->writeDacData(hwp, dacdata[0]);
7473    hwp->writeDacData(hwp, dacdata[1]);
7474    hwp->writeDacData(hwp, dacdata[2]);
7475    hwp->writeDacMask(hwp, dacmask);
7476    if (!IS_HiQV(cPtr)) {
7477	cPtr->writeXR(cPtr,0x06,xr1);
7478	cPtr->writeXR(cPtr,0x1F,xr2);
7479    } else {
7480	cPtr->writeXR(cPtr,0x81,xr1);
7481	cPtr->writeXR(cPtr,0xD0,xr2);
7482    }
7483
7484    if (cPtr->Flags & ChipsDualChannelSupport) {
7485	cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A));
7486	cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A));
7487	cPtr->writeFR(cPtr, 0x01, tmpfr01a);
7488	cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B));
7489	cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B));
7490	cPtr->writeFR(cPtr, 0x01, tmpfr01b);
7491	usleep(1000);
7492	cPtr->writeIOSS(cPtr, IOSS);
7493	cPtr->writeMSS(cPtr, hwp, MSS);
7494	cPtr->writeFR(cPtr, 0x02, tmpfr02);
7495    }
7496
7497    return type;
7498}
7499
7500static int
7501chipsSetMonitor(ScrnInfoPtr pScrn)
7502{
7503    int tmp= chipsProbeMonitor(pScrn);
7504
7505    switch (tmp) {
7506    case 0:
7507	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Color monitor detected\n");
7508	break;
7509    case 1:
7510	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Monochrome monitor detected\n");
7511	break;
7512    default:
7513	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No monitor detected\n");
7514    }
7515    return (tmp);
7516}
7517
7518static void
7519chipsSetPanelType(CHIPSPtr cPtr)
7520{
7521    CARD8 tmp;
7522
7523    if (IS_HiQV(cPtr)) {
7524	if (cPtr->Chipset == CHIPS_CT69030) {
7525	    tmp = cPtr->readFR(cPtr, 0x00);
7526	    if (tmp & 0x20) {
7527		/* FR02: DISPLAY TYPE REGISTER                         */
7528		/* FR02[4] = CRT, FR02[5] = FlatPanel                  */
7529		tmp = cPtr->readFR(cPtr, 0x02);
7530		if (tmp & 0x10)
7531		    cPtr->PanelType |= ChipsCRT;
7532		if (tmp & 0x20)
7533		    cPtr->PanelType |= ChipsLCD | ChipsLCDProbed;
7534	    } else {
7535		cPtr->PanelType |= ChipsCRT;
7536	    }
7537	} else {
7538	    /* test LCD */
7539	    /* FR01: DISPLAY TYPE REGISTER                         */
7540	    /* FR01[1:0]:   Display Type, 01 = CRT, 10 = FlatPanel */
7541	    /* LCD                                                 */
7542	    tmp = cPtr->readFR(cPtr, 0x01);
7543	    if ((tmp & 0x03) == 0x02) {
7544	        cPtr->PanelType |= ChipsLCD | ChipsLCDProbed;
7545	    }
7546	    tmp = cPtr->readXR(cPtr,0xD0);
7547	    if (tmp & 0x01) {
7548	        cPtr->PanelType |= ChipsCRT;
7549	    }
7550	}
7551    } else {
7552	tmp = cPtr->readXR(cPtr, 0x51);
7553	/* test LCD */
7554	/* XR51: DISPLAY TYPE REGISTER                     */
7555	/* XR51[2]:   Display Type, 0 = CRT, 1 = FlatPanel */
7556	if (tmp & 0x04) {
7557	    cPtr->PanelType |= ChipsLCD | ChipsLCDProbed;
7558	}
7559	if ((cPtr->readXR(cPtr, 0x06)) & 0x02) {
7560	    cPtr->PanelType |= ChipsCRT;
7561	}
7562    }
7563}
7564
7565static void
7566chipsBlockHandler (
7567    int i,
7568    pointer     blockData,
7569    pointer     pTimeout,
7570    pointer     pReadmask
7571){
7572    ScreenPtr   pScreen = screenInfo.screens[i];
7573    ScrnInfoPtr pScrn = xf86Screens[i];
7574    CHIPSPtr    cPtr = CHIPSPTR(pScrn);
7575
7576    pScreen->BlockHandler = cPtr->BlockHandler;
7577    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
7578    pScreen->BlockHandler = chipsBlockHandler;
7579
7580    if(cPtr->VideoTimerCallback) {
7581	UpdateCurrentTime();
7582	(*cPtr->VideoTimerCallback)(pScrn, currentTime.milliseconds);
7583    }
7584}
7585