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