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