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