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