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