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