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