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