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