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