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