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