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