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