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