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