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