r128_driver.c revision 19019ffe
1c582b7e3Smrg/*
2c582b7e3Smrg * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
3c582b7e3Smrg *                      Precision Insight, Inc., Cedar Park, Texas, and
4c582b7e3Smrg *                      VA Linux Systems Inc., Fremont, California.
5c582b7e3Smrg *
6c582b7e3Smrg * All Rights Reserved.
7c582b7e3Smrg *
8c582b7e3Smrg * Permission is hereby granted, free of charge, to any person obtaining
9c582b7e3Smrg * a copy of this software and associated documentation files (the
10c582b7e3Smrg * "Software"), to deal in the Software without restriction, including
11c582b7e3Smrg * without limitation on the rights to use, copy, modify, merge,
12c582b7e3Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
13c582b7e3Smrg * and to permit persons to whom the Software is furnished to do so,
14c582b7e3Smrg * subject to the following conditions:
15c582b7e3Smrg *
16c582b7e3Smrg * The above copyright notice and this permission notice (including the
17c582b7e3Smrg * next paragraph) shall be included in all copies or substantial
18c582b7e3Smrg * portions of the Software.
19c582b7e3Smrg *
20c582b7e3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21c582b7e3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22c582b7e3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23c582b7e3Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
24c582b7e3Smrg * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25c582b7e3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26c582b7e3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27c582b7e3Smrg * OTHER DEALINGS IN THE SOFTWARE.
28c582b7e3Smrg */
29c582b7e3Smrg
30c582b7e3Smrg#ifdef HAVE_CONFIG_H
31c582b7e3Smrg#include "config.h"
32c582b7e3Smrg#endif
33c582b7e3Smrg
34c582b7e3Smrg/*
35c582b7e3Smrg * Authors:
36c582b7e3Smrg *   Rickard E. Faith <faith@valinux.com>
37c582b7e3Smrg *   Kevin E. Martin <martin@valinux.com>
38c582b7e3Smrg *   Gareth Hughes <gareth@valinux.com>
39c582b7e3Smrg *
40c582b7e3Smrg * Credits:
41c582b7e3Smrg *
42c582b7e3Smrg *   Thanks to Alan Hourihane <alanh@fairlite.demon..co.uk> and SuSE for
43c582b7e3Smrg *   providing source code to their 3.3.x Rage 128 driver.  Portions of
44c582b7e3Smrg *   this file are based on the initialization code for that driver.
45c582b7e3Smrg *
46c582b7e3Smrg * References:
47c582b7e3Smrg *
48c582b7e3Smrg *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
49c582b7e3Smrg *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
50c582b7e3Smrg *   1999.
51c582b7e3Smrg *
52c582b7e3Smrg *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
53c582b7e3Smrg *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
54c582b7e3Smrg *
55c582b7e3Smrg * This server does not yet support these XFree86 4.0 features:
56c582b7e3Smrg *   DDC1 & DDC2
57c582b7e3Smrg *   shadowfb
58c582b7e3Smrg *   overlay planes
59c582b7e3Smrg *
60c582b7e3Smrg * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge.
61c582b7e3Smrg *
62c582b7e3Smrg * Dualhead support - Alex Deucher <agd5f@yahoo.com>
63c582b7e3Smrg */
64c582b7e3Smrg
65c582b7e3Smrg#include <string.h>
66c582b7e3Smrg#include <stdio.h>
67c582b7e3Smrg
68c582b7e3Smrg				/* Driver data structures */
69c582b7e3Smrg#include "r128.h"
70c582b7e3Smrg#include "r128_probe.h"
71c582b7e3Smrg#include "r128_reg.h"
72c582b7e3Smrg#include "r128_version.h"
73c582b7e3Smrg
74c582b7e3Smrg#ifdef XF86DRI
75c582b7e3Smrg#define _XF86DRI_SERVER_
76c582b7e3Smrg#include "r128_dri.h"
77c582b7e3Smrg#include "r128_common.h"
78c582b7e3Smrg#include "r128_sarea.h"
79c582b7e3Smrg#endif
80c582b7e3Smrg
81c582b7e3Smrg#include "fb.h"
82c582b7e3Smrg
83c582b7e3Smrg				/* colormap initialization */
84c582b7e3Smrg#include "micmap.h"
85c582b7e3Smrg
86c582b7e3Smrg				/* X and server generic header files */
87c582b7e3Smrg#include "xf86.h"
88c582b7e3Smrg#include "xf86_OSproc.h"
89c582b7e3Smrg#include "xf86PciInfo.h"
9019019ffeSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
91c582b7e3Smrg#include "xf86RAC.h"
92c582b7e3Smrg#include "xf86Resources.h"
9319019ffeSmrg#endif
94c582b7e3Smrg#include "xf86cmap.h"
95c582b7e3Smrg#include "xf86xv.h"
96c582b7e3Smrg#include "vbe.h"
97c582b7e3Smrg
98c582b7e3Smrg				/* fbdevhw & vgahw */
99c582b7e3Smrg#ifdef WITH_VGAHW
100c582b7e3Smrg#include "vgaHW.h"
101c582b7e3Smrg#endif
102c582b7e3Smrg#include "fbdevhw.h"
103c582b7e3Smrg#include "dixstruct.h"
104c582b7e3Smrg
105c582b7e3Smrg				/* DPMS support. */
10619019ffeSmrg#ifdef HAVE_XEXTPROTO_71
10719019ffeSmrg#include <X11/extensions/dpmsconst.h>
10819019ffeSmrg#else
109c582b7e3Smrg#define DPMS_SERVER
110c582b7e3Smrg#include <X11/extensions/dpms.h>
11119019ffeSmrg#endif
11219019ffeSmrg
113c582b7e3Smrg
114c582b7e3Smrg#ifndef MAX
115c582b7e3Smrg#define MAX(a,b) ((a)>(b)?(a):(b))
116c582b7e3Smrg#endif
117c582b7e3Smrg
118c582b7e3Smrg#define USE_CRT_ONLY	0
119c582b7e3Smrg
120c582b7e3Smrg				/* Forward definitions for driver functions */
121c582b7e3Smrgstatic Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen);
122c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode);
123c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn);
124c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn);
125c582b7e3Smrgstatic Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
126c582b7e3Smrgstatic void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn,
127c582b7e3Smrg					  int PowerManagementMode, int flags);
128c582b7e3Smrgstatic void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn,
129c582b7e3Smrg					  int PowerManagementMode, int flags);
130c582b7e3Smrg
131c582b7e3Smrgtypedef enum {
132c582b7e3Smrg  OPTION_NOACCEL,
133c582b7e3Smrg  OPTION_SW_CURSOR,
134c582b7e3Smrg  OPTION_DAC_6BIT,
135c582b7e3Smrg  OPTION_DAC_8BIT,
136c582b7e3Smrg#ifdef XF86DRI
137c582b7e3Smrg  OPTION_XV_DMA,
138c582b7e3Smrg  OPTION_IS_PCI,
139c582b7e3Smrg  OPTION_CCE_PIO,
140c582b7e3Smrg  OPTION_NO_SECURITY,
141c582b7e3Smrg  OPTION_USEC_TIMEOUT,
142c582b7e3Smrg  OPTION_AGP_MODE,
143c582b7e3Smrg  OPTION_AGP_SIZE,
144c582b7e3Smrg  OPTION_RING_SIZE,
145c582b7e3Smrg  OPTION_BUFFER_SIZE,
146c582b7e3Smrg  OPTION_PAGE_FLIP,
147c582b7e3Smrg#endif
148c582b7e3Smrg#if USE_CRT_ONLY
149c582b7e3Smrg  /* FIXME: Disable CRTOnly until it is tested */
150c582b7e3Smrg  OPTION_CRT,
151c582b7e3Smrg#endif
152c582b7e3Smrg  OPTION_DISPLAY,
153c582b7e3Smrg  OPTION_PANEL_WIDTH,
154c582b7e3Smrg  OPTION_PANEL_HEIGHT,
155c582b7e3Smrg  OPTION_PROG_FP_REGS,
156c582b7e3Smrg  OPTION_FBDEV,
157c582b7e3Smrg  OPTION_VIDEO_KEY,
158c582b7e3Smrg  OPTION_SHOW_CACHE,
159c582b7e3Smrg  OPTION_VGA_ACCESS
160c582b7e3Smrg} R128Opts;
161c582b7e3Smrg
162c582b7e3Smrgstatic const OptionInfoRec R128Options[] = {
163c582b7e3Smrg  { OPTION_NOACCEL,      "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
164c582b7e3Smrg  { OPTION_SW_CURSOR,    "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
165c582b7e3Smrg  { OPTION_DAC_6BIT,     "Dac6Bit",          OPTV_BOOLEAN, {0}, FALSE },
166c582b7e3Smrg  { OPTION_DAC_8BIT,     "Dac8Bit",          OPTV_BOOLEAN, {0}, TRUE  },
167c582b7e3Smrg#ifdef XF86DRI
168c582b7e3Smrg  { OPTION_XV_DMA,       "DMAForXv",         OPTV_BOOLEAN, {0}, FALSE },
169c582b7e3Smrg  { OPTION_IS_PCI,       "ForcePCIMode",     OPTV_BOOLEAN, {0}, FALSE },
170c582b7e3Smrg  { OPTION_CCE_PIO,      "CCEPIOMode",       OPTV_BOOLEAN, {0}, FALSE },
171c582b7e3Smrg  { OPTION_NO_SECURITY,  "CCENoSecurity",    OPTV_BOOLEAN, {0}, FALSE },
172c582b7e3Smrg  { OPTION_USEC_TIMEOUT, "CCEusecTimeout",   OPTV_INTEGER, {0}, FALSE },
173c582b7e3Smrg  { OPTION_AGP_MODE,     "AGPMode",          OPTV_INTEGER, {0}, FALSE },
174c582b7e3Smrg  { OPTION_AGP_SIZE,     "AGPSize",          OPTV_INTEGER, {0}, FALSE },
175c582b7e3Smrg  { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
176c582b7e3Smrg  { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
177c582b7e3Smrg  { OPTION_PAGE_FLIP,    "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
178c582b7e3Smrg#endif
179c582b7e3Smrg  { OPTION_DISPLAY,      "Display",          OPTV_STRING,  {0}, FALSE },
180c582b7e3Smrg  { OPTION_PANEL_WIDTH,  "PanelWidth",       OPTV_INTEGER, {0}, FALSE },
181c582b7e3Smrg  { OPTION_PANEL_HEIGHT, "PanelHeight",      OPTV_INTEGER, {0}, FALSE },
182c582b7e3Smrg  { OPTION_PROG_FP_REGS, "ProgramFPRegs",    OPTV_BOOLEAN, {0}, FALSE },
183c582b7e3Smrg  { OPTION_FBDEV,        "UseFBDev",         OPTV_BOOLEAN, {0}, FALSE },
184c582b7e3Smrg  { OPTION_VIDEO_KEY,    "VideoKey",         OPTV_INTEGER, {0}, FALSE },
185c582b7e3Smrg  { OPTION_SHOW_CACHE,   "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
186c582b7e3Smrg  { OPTION_VGA_ACCESS,   "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
187c582b7e3Smrg  { -1,                  NULL,               OPTV_NONE,    {0}, FALSE }
188c582b7e3Smrg};
189c582b7e3Smrg
190c582b7e3Smrgconst OptionInfoRec *R128OptionsWeak(void) { return R128Options; }
191c582b7e3Smrg
192c582b7e3SmrgR128RAMRec R128RAM[] = {        /* Memory Specifications
193c582b7e3Smrg				   From RAGE 128 Software Development
194c582b7e3Smrg				   Manual (Technical Reference Manual P/N
195c582b7e3Smrg				   SDK-G04000 Rev 0.01), page 3-21.  */
196c582b7e3Smrg    { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
197c582b7e3Smrg    { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
198c582b7e3Smrg    { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
199c582b7e3Smrg    { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
200c582b7e3Smrg};
201c582b7e3Smrg
202c582b7e3Smrgextern _X_EXPORT int gR128EntityIndex;
203c582b7e3Smrg
204c582b7e3Smrgint getR128EntityIndex(void)
205c582b7e3Smrg{
206c582b7e3Smrg    return gR128EntityIndex;
207c582b7e3Smrg}
208c582b7e3Smrg
209c582b7e3SmrgR128EntPtr R128EntPriv(ScrnInfoPtr pScrn)
210c582b7e3Smrg{
211c582b7e3Smrg    DevUnion     *pPriv;
212c582b7e3Smrg    R128InfoPtr  info   = R128PTR(pScrn);
213c582b7e3Smrg    pPriv = xf86GetEntityPrivate(info->pEnt->index,
214c582b7e3Smrg                                 getR128EntityIndex());
215c582b7e3Smrg    return pPriv->ptr;
216c582b7e3Smrg}
217c582b7e3Smrg
218c582b7e3Smrg/* Allocate our private R128InfoRec. */
219c582b7e3Smrgstatic Bool R128GetRec(ScrnInfoPtr pScrn)
220c582b7e3Smrg{
221c582b7e3Smrg    if (pScrn->driverPrivate) return TRUE;
222c582b7e3Smrg
223c582b7e3Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1);
224c582b7e3Smrg    return TRUE;
225c582b7e3Smrg}
226c582b7e3Smrg
227c582b7e3Smrg/* Free our private R128InfoRec. */
228c582b7e3Smrgstatic void R128FreeRec(ScrnInfoPtr pScrn)
229c582b7e3Smrg{
230c582b7e3Smrg    if (!pScrn || !pScrn->driverPrivate) return;
231c582b7e3Smrg    xfree(pScrn->driverPrivate);
232c582b7e3Smrg    pScrn->driverPrivate = NULL;
233c582b7e3Smrg}
234c582b7e3Smrg
235c582b7e3Smrg/* Memory map the MMIO region.  Used during pre-init and by R128MapMem,
236c582b7e3Smrg   below. */
237c582b7e3Smrgstatic Bool R128MapMMIO(ScrnInfoPtr pScrn)
238c582b7e3Smrg{
239c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
240c582b7e3Smrg
241c582b7e3Smrg    if (info->FBDev) {
242c582b7e3Smrg	info->MMIO = fbdevHWMapMMIO(pScrn);
243c582b7e3Smrg    } else {
24419019ffeSmrg        /* If the primary screen has already mapped the MMIO region,
24519019ffeSmrg           use its pointer instead of mapping it a second time. */
24619019ffeSmrg        if (info->IsSecondary) {
24719019ffeSmrg            DevUnion* pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
24819019ffeSmrg                                                   getR128EntityIndex());
24919019ffeSmrg            R128EntPtr pR128Ent = pPriv->ptr;
25019019ffeSmrg            R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn);
25119019ffeSmrg            info->MMIO=info0->MMIO;
25219019ffeSmrg            if (info->MMIO) return TRUE;
25319019ffeSmrg        }
254c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
255c582b7e3Smrg	info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
256c582b7e3Smrg				   VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
257c582b7e3Smrg				   info->PciTag,
258c582b7e3Smrg				   info->MMIOAddr,
259c582b7e3Smrg				   R128_MMIOSIZE);
260c582b7e3Smrg#else
261c582b7e3Smrg	int err = pci_device_map_range(info->PciInfo,
262c582b7e3Smrg				       info->MMIOAddr,
263c582b7e3Smrg				       R128_MMIOSIZE,
264c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE,
265c582b7e3Smrg				       &info->MMIO);
266c582b7e3Smrg
267c582b7e3Smrg	if (err) {
268c582b7e3Smrg	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
269c582b7e3Smrg                        "Unable to map MMIO aperture. %s (%d)\n",
270c582b7e3Smrg                        strerror (err), err);
271c582b7e3Smrg	    return FALSE;
272c582b7e3Smrg	}
273c582b7e3Smrg#endif
274c582b7e3Smrg    }
275c582b7e3Smrg
276c582b7e3Smrg    if (!info->MMIO) return FALSE;
277c582b7e3Smrg    return TRUE;
278c582b7e3Smrg}
279c582b7e3Smrg
280c582b7e3Smrg/* Unmap the MMIO region.  Used during pre-init and by R128UnmapMem,
281c582b7e3Smrg   below. */
282c582b7e3Smrgstatic Bool R128UnmapMMIO(ScrnInfoPtr pScrn)
283c582b7e3Smrg{
284c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
285c582b7e3Smrg
286c582b7e3Smrg    if (info->FBDev)
287c582b7e3Smrg	fbdevHWUnmapMMIO(pScrn);
288c582b7e3Smrg    else {
289c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
290c582b7e3Smrg	xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE);
291c582b7e3Smrg#else
292c582b7e3Smrg	pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE);
293c582b7e3Smrg#endif
294c582b7e3Smrg    }
295c582b7e3Smrg    info->MMIO = NULL;
296c582b7e3Smrg    return TRUE;
297c582b7e3Smrg}
298c582b7e3Smrg
299c582b7e3Smrg/* Memory map the frame buffer.  Used by R128MapMem, below. */
300c582b7e3Smrgstatic Bool R128MapFB(ScrnInfoPtr pScrn)
301c582b7e3Smrg{
302c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
303c582b7e3Smrg
304c582b7e3Smrg    if (info->FBDev) {
305c582b7e3Smrg	info->FB = fbdevHWMapVidmem(pScrn);
306c582b7e3Smrg    } else {
307c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
308c582b7e3Smrg	info->FB = xf86MapPciMem(pScrn->scrnIndex,
309c582b7e3Smrg				 VIDMEM_FRAMEBUFFER,
310c582b7e3Smrg				 info->PciTag,
311c582b7e3Smrg				 info->LinearAddr,
312c582b7e3Smrg				 info->FbMapSize);
313c582b7e3Smrg#else
314c582b7e3Smrg	int err = pci_device_map_range(info->PciInfo,
315c582b7e3Smrg				       info->LinearAddr,
316c582b7e3Smrg				       info->FbMapSize,
317c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE |
318c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
319c582b7e3Smrg				       &info->FB);
320c582b7e3Smrg
321c582b7e3Smrg	if (err) {
322c582b7e3Smrg	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
323c582b7e3Smrg                        "Unable to map FB aperture. %s (%d)\n",
324c582b7e3Smrg                        strerror (err), err);
325c582b7e3Smrg	    return FALSE;
326c582b7e3Smrg	}
327c582b7e3Smrg#endif
328c582b7e3Smrg    }
329c582b7e3Smrg
330c582b7e3Smrg    if (!info->FB) return FALSE;
331c582b7e3Smrg    return TRUE;
332c582b7e3Smrg}
333c582b7e3Smrg
334c582b7e3Smrg/* Unmap the frame buffer.  Used by R128UnmapMem, below. */
335c582b7e3Smrgstatic Bool R128UnmapFB(ScrnInfoPtr pScrn)
336c582b7e3Smrg{
337c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
338c582b7e3Smrg
339c582b7e3Smrg    if (info->FBDev)
340c582b7e3Smrg	fbdevHWUnmapVidmem(pScrn);
341c582b7e3Smrg    else
342c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
343c582b7e3Smrg	xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
344c582b7e3Smrg#else
345c582b7e3Smrg	pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize);
346c582b7e3Smrg#endif
347c582b7e3Smrg    info->FB = NULL;
348c582b7e3Smrg    return TRUE;
349c582b7e3Smrg}
350c582b7e3Smrg
351c582b7e3Smrg/* Memory map the MMIO region and the frame buffer. */
352c582b7e3Smrgstatic Bool R128MapMem(ScrnInfoPtr pScrn)
353c582b7e3Smrg{
354c582b7e3Smrg    if (!R128MapMMIO(pScrn)) return FALSE;
355c582b7e3Smrg    if (!R128MapFB(pScrn)) {
356c582b7e3Smrg	R128UnmapMMIO(pScrn);
357c582b7e3Smrg	return FALSE;
358c582b7e3Smrg    }
359c582b7e3Smrg    return TRUE;
360c582b7e3Smrg}
361c582b7e3Smrg
362c582b7e3Smrg/* Unmap the MMIO region and the frame buffer. */
363c582b7e3Smrgstatic Bool R128UnmapMem(ScrnInfoPtr pScrn)
364c582b7e3Smrg{
365c582b7e3Smrg    if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE;
366c582b7e3Smrg    return TRUE;
367c582b7e3Smrg}
368c582b7e3Smrg
369c582b7e3Smrg/* Read PLL information */
370c582b7e3Smrgunsigned R128INPLL(ScrnInfoPtr pScrn, int addr)
371c582b7e3Smrg{
372c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
373c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
374c582b7e3Smrg
375c582b7e3Smrg    OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f);
376c582b7e3Smrg    return INREG(R128_CLOCK_CNTL_DATA);
377c582b7e3Smrg}
378c582b7e3Smrg
379c582b7e3Smrg#if 0
380c582b7e3Smrg/* Read PAL information (only used for debugging). */
381c582b7e3Smrgstatic int R128INPAL(int idx)
382c582b7e3Smrg{
383c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
384c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
385c582b7e3Smrg
386c582b7e3Smrg    OUTREG(R128_PALETTE_INDEX, idx << 16);
387c582b7e3Smrg    return INREG(R128_PALETTE_DATA);
388c582b7e3Smrg}
389c582b7e3Smrg#endif
390c582b7e3Smrg
391c582b7e3Smrg/* Wait for vertical sync. */
392c582b7e3Smrgvoid R128WaitForVerticalSync(ScrnInfoPtr pScrn)
393c582b7e3Smrg{
394c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
395c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
396c582b7e3Smrg    int           i;
397c582b7e3Smrg
398c582b7e3Smrg    OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK);
399c582b7e3Smrg    for (i = 0; i < R128_TIMEOUT; i++) {
400c582b7e3Smrg	if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break;
401c582b7e3Smrg    }
402c582b7e3Smrg}
403c582b7e3Smrg
404c582b7e3Smrg/* Blank screen. */
405c582b7e3Smrgstatic void R128Blank(ScrnInfoPtr pScrn)
406c582b7e3Smrg{
407c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
408c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
409c582b7e3Smrg
410c582b7e3Smrg    if(!info->IsSecondary)
411c582b7e3Smrg    {
412c582b7e3Smrg        switch(info->DisplayType)
413c582b7e3Smrg        {
414c582b7e3Smrg        case MT_LCD:
415c582b7e3Smrg            OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_DISPLAY_DIS,
416c582b7e3Smrg                 ~R128_LVDS_DISPLAY_DIS);
417c582b7e3Smrg	    break;
418c582b7e3Smrg        case MT_CRT:
419c582b7e3Smrg            OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS);
420c582b7e3Smrg	    break;
421c582b7e3Smrg        case MT_DFP:
422c582b7e3Smrg            OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS);
423c582b7e3Smrg	    break;
424c582b7e3Smrg        case MT_NONE:
425c582b7e3Smrg        default:
426c582b7e3Smrg           break;
427c582b7e3Smrg        }
428c582b7e3Smrg    }
429c582b7e3Smrg    else
430c582b7e3Smrg    {
431c582b7e3Smrg        OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~R128_CRTC2_DISP_DIS);
432c582b7e3Smrg    }
433c582b7e3Smrg}
434c582b7e3Smrg
435c582b7e3Smrg/* Unblank screen. */
436c582b7e3Smrgstatic void R128Unblank(ScrnInfoPtr pScrn)
437c582b7e3Smrg{
438c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
439c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
440c582b7e3Smrg
441c582b7e3Smrg    if(!info->IsSecondary)
442c582b7e3Smrg    {
443c582b7e3Smrg        switch(info->DisplayType)
444c582b7e3Smrg        {
445c582b7e3Smrg        case MT_LCD:
446c582b7e3Smrg            OUTREGP(R128_LVDS_GEN_CNTL, 0,
447c582b7e3Smrg                 ~R128_LVDS_DISPLAY_DIS);
448c582b7e3Smrg	    break;
449c582b7e3Smrg        case MT_CRT:
450c582b7e3Smrg            OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS);
451c582b7e3Smrg	    break;
452c582b7e3Smrg        case MT_DFP:
453c582b7e3Smrg            OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS);
454c582b7e3Smrg	    break;
455c582b7e3Smrg        case MT_NONE:
456c582b7e3Smrg        default:
457c582b7e3Smrg            break;
458c582b7e3Smrg        }
459c582b7e3Smrg    }
460c582b7e3Smrg    else
461c582b7e3Smrg    {
462c582b7e3Smrg        switch(info->DisplayType)
463c582b7e3Smrg        {
464c582b7e3Smrg        case MT_LCD:
465c582b7e3Smrg        case MT_DFP:
466c582b7e3Smrg        case MT_CRT:
467c582b7e3Smrg            OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_DISP_DIS);
468c582b7e3Smrg            break;
469c582b7e3Smrg        case MT_NONE:
470c582b7e3Smrg        default:
471c582b7e3Smrg            break;
472c582b7e3Smrg        }
473c582b7e3Smrg    }
474c582b7e3Smrg}
475c582b7e3Smrg
476c582b7e3Smrg/* Compute log base 2 of val. */
477c582b7e3Smrgint R128MinBits(int val)
478c582b7e3Smrg{
479c582b7e3Smrg    int bits;
480c582b7e3Smrg
481c582b7e3Smrg    if (!val) return 1;
482c582b7e3Smrg    for (bits = 0; val; val >>= 1, ++bits);
483c582b7e3Smrg    return bits;
484c582b7e3Smrg}
485c582b7e3Smrg
486c582b7e3Smrg/* Compute n/d with rounding. */
487c582b7e3Smrgstatic int R128Div(int n, int d)
488c582b7e3Smrg{
489c582b7e3Smrg    return (n + (d / 2)) / d;
490c582b7e3Smrg}
491c582b7e3Smrg
492c582b7e3Smrg/* Read the Video BIOS block and the FP registers (if applicable). */
493c582b7e3Smrgstatic Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
494c582b7e3Smrg{
495c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
496c582b7e3Smrg    int         i;
497c582b7e3Smrg    int         FPHeader = 0;
498c582b7e3Smrg
499c582b7e3Smrg#define R128_BIOS8(v)  (info->VBIOS[v])
500c582b7e3Smrg#define R128_BIOS16(v) (info->VBIOS[v] | \
501c582b7e3Smrg			(info->VBIOS[(v) + 1] << 8))
502c582b7e3Smrg#define R128_BIOS32(v) (info->VBIOS[v] | \
503c582b7e3Smrg			(info->VBIOS[(v) + 1] << 8) | \
504c582b7e3Smrg			(info->VBIOS[(v) + 2] << 16) | \
505c582b7e3Smrg			(info->VBIOS[(v) + 3] << 24))
506c582b7e3Smrg
507c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS
508c582b7e3Smrg    int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE;
509c582b7e3Smrg    info->VBIOS = xalloc(size);
510c582b7e3Smrg#else
511c582b7e3Smrg    info->VBIOS = xalloc(R128_VBIOS_SIZE);
512c582b7e3Smrg#endif
513c582b7e3Smrg
514c582b7e3Smrg    if (!info->VBIOS) {
515c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
516c582b7e3Smrg		   "Cannot allocate space for hold Video BIOS!\n");
517c582b7e3Smrg	return FALSE;
518c582b7e3Smrg    }
519c582b7e3Smrg
520c582b7e3Smrg    if (pInt10) {
521c582b7e3Smrg	info->BIOSAddr = pInt10->BIOSseg << 4;
522c582b7e3Smrg	(void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
523c582b7e3Smrg		     R128_VBIOS_SIZE);
524c582b7e3Smrg    } else {
525c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS
526c582b7e3Smrg	if (pci_device_read_rom(info->PciInfo, info->VBIOS)) {
527c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
528c582b7e3Smrg		       "Failed to read PCI ROM!\n");
529c582b7e3Smrg	}
530c582b7e3Smrg#else
531c582b7e3Smrg	xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE);
532c582b7e3Smrg	if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
533c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
534c582b7e3Smrg		       "Video BIOS not detected in PCI space!\n");
535c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
536c582b7e3Smrg		       "Attempting to read Video BIOS from legacy ISA space!\n");
537c582b7e3Smrg	    info->BIOSAddr = 0x000c0000;
538c582b7e3Smrg	    xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS);
539c582b7e3Smrg	}
540c582b7e3Smrg#endif
541c582b7e3Smrg    }
542c582b7e3Smrg    if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
543c582b7e3Smrg	info->BIOSAddr = 0x00000000;
544c582b7e3Smrg	xfree(info->VBIOS);
545c582b7e3Smrg	info->VBIOS = NULL;
546c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
547c582b7e3Smrg		   "Video BIOS not found!\n");
548c582b7e3Smrg    }
549c582b7e3Smrg
550c582b7e3Smrg        if(info->HasCRTC2)
551c582b7e3Smrg        {
552c582b7e3Smrg             if(info->IsSecondary)
553c582b7e3Smrg             {
554c582b7e3Smrg		/* there may be a way to detect this, for now, just assume
555c582b7e3Smrg		   second head is CRT */
556c582b7e3Smrg                 info->DisplayType = MT_CRT;
557c582b7e3Smrg
558c582b7e3Smrg                 if(info->DisplayType > MT_NONE)
559c582b7e3Smrg                 {
560c582b7e3Smrg                     DevUnion* pPriv;
561c582b7e3Smrg                     R128EntPtr pR128Ent;
562c582b7e3Smrg                     pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
563c582b7e3Smrg                         getR128EntityIndex());
564c582b7e3Smrg                     pR128Ent = pPriv->ptr;
565c582b7e3Smrg                     pR128Ent->HasSecondary = TRUE;
566c582b7e3Smrg
567c582b7e3Smrg                 }
568c582b7e3Smrg                 else return FALSE;
569c582b7e3Smrg
570c582b7e3Smrg             }
571c582b7e3Smrg             else
572c582b7e3Smrg             {
573c582b7e3Smrg                 /* really need some sort of detection here */
574c582b7e3Smrg		 if (info->HasPanelRegs) {
575c582b7e3Smrg		 	info->DisplayType = MT_LCD;
576c582b7e3Smrg		 } else if (info->isDFP) {
577c582b7e3Smrg			info->DisplayType = MT_DFP;
578c582b7e3Smrg                 } else
579c582b7e3Smrg                 {
580c582b7e3Smrg                     /*DVI port has no monitor connected, try CRT port.
581c582b7e3Smrg                     If something on CRT port, treat it as primary*/
582c582b7e3Smrg                     if(xf86IsEntityShared(pScrn->entityList[0]))
583c582b7e3Smrg                     {
584c582b7e3Smrg                         DevUnion* pPriv;
585c582b7e3Smrg                         R128EntPtr pR128Ent;
586c582b7e3Smrg                         pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
587c582b7e3Smrg                             getR128EntityIndex());
588c582b7e3Smrg                         pR128Ent = pPriv->ptr;
589c582b7e3Smrg                         pR128Ent->BypassSecondary = TRUE;
590c582b7e3Smrg                     }
591c582b7e3Smrg
592c582b7e3Smrg                     info->DisplayType = MT_CRT;
593c582b7e3Smrg#if 0
594c582b7e3Smrg                     {
595c582b7e3Smrg                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
596c582b7e3Smrg                             "No monitor detected!!!\n");
597c582b7e3Smrg                         return FALSE;
598c582b7e3Smrg                     }
599c582b7e3Smrg#endif
600c582b7e3Smrg                 }
601c582b7e3Smrg             }
602c582b7e3Smrg         }
603c582b7e3Smrg         else
604c582b7e3Smrg         {
605c582b7e3Smrg             /*Regular Radeon ASIC, only one CRTC, but it could be
606c582b7e3Smrg               used for DFP with a DVI output, like AIW board*/
607c582b7e3Smrg             if(info->isDFP) info->DisplayType = MT_DFP;
608c582b7e3Smrg             else info->DisplayType = MT_CRT;
609c582b7e3Smrg         }
610c582b7e3Smrg
611c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n",
612c582b7e3Smrg              (info->IsSecondary ? "Secondary" : "Primary"),
613c582b7e3Smrg               info->DisplayType);
614c582b7e3Smrg
615c582b7e3Smrg
616c582b7e3Smrg    if (info->VBIOS && info->DisplayType == MT_LCD) {
617c582b7e3Smrg	info->FPBIOSstart = 0;
618c582b7e3Smrg
619c582b7e3Smrg	/* FIXME: There should be direct access to the start of the FP info
620c582b7e3Smrg	   tables, but until we find out where that offset is stored, we
621c582b7e3Smrg	   must search for the ATI signature string: "M3      ". */
622c582b7e3Smrg	for (i = 4; i < R128_VBIOS_SIZE-8; i++) {
623c582b7e3Smrg	    if (R128_BIOS8(i)   == 'M' &&
624c582b7e3Smrg		R128_BIOS8(i+1) == '3' &&
625c582b7e3Smrg		R128_BIOS8(i+2) == ' ' &&
626c582b7e3Smrg		R128_BIOS8(i+3) == ' ' &&
627c582b7e3Smrg		R128_BIOS8(i+4) == ' ' &&
628c582b7e3Smrg		R128_BIOS8(i+5) == ' ' &&
629c582b7e3Smrg		R128_BIOS8(i+6) == ' ' &&
630c582b7e3Smrg		R128_BIOS8(i+7) == ' ') {
631c582b7e3Smrg		FPHeader = i-2;
632c582b7e3Smrg		break;
633c582b7e3Smrg	    }
634c582b7e3Smrg	}
635c582b7e3Smrg
636c582b7e3Smrg	if (!FPHeader) return TRUE;
637c582b7e3Smrg
638c582b7e3Smrg	/* Assume that only one panel is attached and supported */
639c582b7e3Smrg	for (i = FPHeader+20; i < FPHeader+84; i += 2) {
640c582b7e3Smrg	    if (R128_BIOS16(i) != 0) {
641c582b7e3Smrg		info->FPBIOSstart = R128_BIOS16(i);
642c582b7e3Smrg		break;
643c582b7e3Smrg	    }
644c582b7e3Smrg	}
645c582b7e3Smrg	if (!info->FPBIOSstart) return TRUE;
646c582b7e3Smrg
647c582b7e3Smrg	if (!info->PanelXRes)
648c582b7e3Smrg	    info->PanelXRes = R128_BIOS16(info->FPBIOSstart+25);
649c582b7e3Smrg	if (!info->PanelYRes)
650c582b7e3Smrg	    info->PanelYRes = R128_BIOS16(info->FPBIOSstart+27);
651c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n",
652c582b7e3Smrg		   info->PanelXRes, info->PanelYRes);
653c582b7e3Smrg
654c582b7e3Smrg	info->PanelPwrDly = R128_BIOS8(info->FPBIOSstart+56);
655c582b7e3Smrg
656c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: ");
657c582b7e3Smrg	for (i = 1; i <= 24; i++)
658c582b7e3Smrg	    ErrorF("%c", R128_BIOS8(info->FPBIOSstart+i));
659c582b7e3Smrg	ErrorF("\n");
660c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: ");
661c582b7e3Smrg	i = R128_BIOS16(info->FPBIOSstart+29);
662c582b7e3Smrg	if (i & 1) ErrorF("Color, ");
663c582b7e3Smrg	else       ErrorF("Monochrome, ");
664c582b7e3Smrg	if (i & 2) ErrorF("Dual(split), ");
665c582b7e3Smrg	else       ErrorF("Single, ");
666c582b7e3Smrg	switch ((i >> 2) & 0x3f) {
667c582b7e3Smrg	case 0:  ErrorF("STN");        break;
668c582b7e3Smrg	case 1:  ErrorF("TFT");        break;
669c582b7e3Smrg	case 2:  ErrorF("Active STN"); break;
670c582b7e3Smrg	case 3:  ErrorF("EL");         break;
671c582b7e3Smrg	case 4:  ErrorF("Plasma");     break;
672c582b7e3Smrg	default: ErrorF("UNKNOWN");    break;
673c582b7e3Smrg	}
674c582b7e3Smrg	ErrorF("\n");
675c582b7e3Smrg	if (R128_BIOS8(info->FPBIOSstart+61) & 1) {
676c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n");
677c582b7e3Smrg	} else {
678c582b7e3Smrg	    /* FIXME: Add Non-LVDS flat pael support */
679c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
680c582b7e3Smrg		       "Non-LVDS panel interface detected!  "
681c582b7e3Smrg		       "This support is untested and may not "
682c582b7e3Smrg		       "function properly\n");
683c582b7e3Smrg	}
684c582b7e3Smrg    }
685c582b7e3Smrg
686c582b7e3Smrg    if (!info->PanelXRes || !info->PanelYRes) {
687c582b7e3Smrg        info->HasPanelRegs = FALSE;
688c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
689c582b7e3Smrg		   "Can't determine panel dimensions, and none specified.\n"
690c582b7e3Smrg		   "\tDisabling programming of FP registers.\n");
691c582b7e3Smrg    }
692c582b7e3Smrg
693c582b7e3Smrg    return TRUE;
694c582b7e3Smrg}
695c582b7e3Smrg
696c582b7e3Smrg/* Read PLL parameters from BIOS block.  Default to typical values if there
697c582b7e3Smrg   is no BIOS. */
698c582b7e3Smrgstatic Bool R128GetPLLParameters(ScrnInfoPtr pScrn)
699c582b7e3Smrg{
700c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
701c582b7e3Smrg    R128PLLPtr    pll  = &info->pll;
702c582b7e3Smrg
703c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__)
704c582b7e3Smrg    /* there is no bios under Linux PowerPC but Open Firmware
705c582b7e3Smrg       does set up the PLL registers properly and we can use
706c582b7e3Smrg       those to calculate xclk and find the reference divider */
707c582b7e3Smrg
708c582b7e3Smrg    unsigned x_mpll_ref_fb_div;
709c582b7e3Smrg    unsigned xclk_cntl;
710c582b7e3Smrg    unsigned Nx, M;
711c582b7e3Smrg    unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12};
712c582b7e3Smrg
713c582b7e3Smrg    /* Assume REF clock is 2950 (in units of 10khz) */
714c582b7e3Smrg    /* and that all pllclk must be between 125 Mhz and 250Mhz */
715c582b7e3Smrg    pll->reference_freq = 2950;
716c582b7e3Smrg    pll->min_pll_freq   = 12500;
717c582b7e3Smrg    pll->max_pll_freq   = 25000;
718c582b7e3Smrg
719c582b7e3Smrg    /* need to memory map the io to use INPLL since it
720c582b7e3Smrg       has not been done yet at this point in the startup */
721c582b7e3Smrg    R128MapMMIO(pScrn);
722c582b7e3Smrg    x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV);
723c582b7e3Smrg    xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7;
724c582b7e3Smrg    pll->reference_div =
725c582b7e3Smrg	INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK;
726c582b7e3Smrg    /* unmap it again */
727c582b7e3Smrg    R128UnmapMMIO(pScrn);
728c582b7e3Smrg
729c582b7e3Smrg    Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8;
730c582b7e3Smrg    M =  (x_mpll_ref_fb_div & 0x0000FF);
731c582b7e3Smrg
732c582b7e3Smrg    pll->xclk =  R128Div((2 * Nx * pll->reference_freq),
733c582b7e3Smrg			 (M * PostDivSet[xclk_cntl]));
734c582b7e3Smrg
735c582b7e3Smrg#else /* !defined(__powerpc__) */
736c582b7e3Smrg
737c582b7e3Smrg    if (!info->VBIOS) {
738c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
739c582b7e3Smrg		   "Video BIOS not detected, using default PLL parameters!\n");
740c582b7e3Smrg				/* These probably aren't going to work for
741c582b7e3Smrg				   the card you are using.  Specifically,
742c582b7e3Smrg				   reference freq can be 29.50MHz,
743c582b7e3Smrg				   28.63MHz, or 14.32MHz.  YMMV. */
744c582b7e3Smrg	pll->reference_freq = 2950;
745c582b7e3Smrg	pll->reference_div  = 65;
746c582b7e3Smrg	pll->min_pll_freq   = 12500;
747c582b7e3Smrg	pll->max_pll_freq   = 25000;
748c582b7e3Smrg	pll->xclk           = 10300;
749c582b7e3Smrg    } else {
750c582b7e3Smrg	CARD16 bios_header    = R128_BIOS16(0x48);
751c582b7e3Smrg	CARD16 pll_info_block = R128_BIOS16(bios_header + 0x30);
752c582b7e3Smrg	R128TRACE(("Header at 0x%04x; PLL Information at 0x%04x\n",
753c582b7e3Smrg		   bios_header, pll_info_block));
754c582b7e3Smrg
755c582b7e3Smrg	pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e);
756c582b7e3Smrg	pll->reference_div  = R128_BIOS16(pll_info_block + 0x10);
757c582b7e3Smrg	pll->min_pll_freq   = R128_BIOS32(pll_info_block + 0x12);
758c582b7e3Smrg	pll->max_pll_freq   = R128_BIOS32(pll_info_block + 0x16);
759c582b7e3Smrg	pll->xclk           = R128_BIOS16(pll_info_block + 0x08);
760c582b7e3Smrg    }
761c582b7e3Smrg#endif /* __powerpc__ */
762c582b7e3Smrg
763c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
764c582b7e3Smrg	       "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
765c582b7e3Smrg	       pll->reference_freq,
766c582b7e3Smrg	       pll->reference_div,
767c582b7e3Smrg	       pll->min_pll_freq,
768c582b7e3Smrg	       pll->max_pll_freq,
769c582b7e3Smrg	       pll->xclk);
770c582b7e3Smrg
771c582b7e3Smrg    return TRUE;
772c582b7e3Smrg}
773c582b7e3Smrg
774c582b7e3Smrg/* This is called by R128PreInit to set up the default visual. */
775c582b7e3Smrgstatic Bool R128PreInitVisual(ScrnInfoPtr pScrn)
776c582b7e3Smrg{
777c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
778c582b7e3Smrg
779c582b7e3Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb
780c582b7e3Smrg					  | Support32bppFb
781c582b7e3Smrg					  | SupportConvert32to24
782c582b7e3Smrg					  )))
783c582b7e3Smrg	return FALSE;
784c582b7e3Smrg
785c582b7e3Smrg    switch (pScrn->depth) {
786c582b7e3Smrg    case 8:
787c582b7e3Smrg    case 15:
788c582b7e3Smrg    case 16:
789c582b7e3Smrg    case 24:
790c582b7e3Smrg	break;
791c582b7e3Smrg    default:
792c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
793c582b7e3Smrg		   "Given depth (%d) is not supported by %s driver\n",
794c582b7e3Smrg		   pScrn->depth, R128_DRIVER_NAME);
795c582b7e3Smrg	return FALSE;
796c582b7e3Smrg    }
797c582b7e3Smrg
798c582b7e3Smrg    xf86PrintDepthBpp(pScrn);
799c582b7e3Smrg
800c582b7e3Smrg    info->fifo_slots  = 0;
801c582b7e3Smrg    info->pix24bpp    = xf86GetBppFromDepth(pScrn, pScrn->depth);
802c582b7e3Smrg    info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
803c582b7e3Smrg    info->CurrentLayout.depth        = pScrn->depth;
804c582b7e3Smrg    info->CurrentLayout.pixel_bytes  = pScrn->bitsPerPixel / 8;
805c582b7e3Smrg    info->CurrentLayout.pixel_code   = (pScrn->bitsPerPixel != 16
806c582b7e3Smrg				       ? pScrn->bitsPerPixel
807c582b7e3Smrg				       : pScrn->depth);
808c582b7e3Smrg
809c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
810c582b7e3Smrg	       "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
811c582b7e3Smrg	       pScrn->depth,
812c582b7e3Smrg	       info->CurrentLayout.pixel_bytes,
813c582b7e3Smrg	       info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
814c582b7e3Smrg	       info->pix24bpp);
815c582b7e3Smrg
816c582b7e3Smrg
817c582b7e3Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
818c582b7e3Smrg
819c582b7e3Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
820c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
821c582b7e3Smrg		   "Default visual (%s) is not supported at depth %d\n",
822c582b7e3Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
823c582b7e3Smrg	return FALSE;
824c582b7e3Smrg    }
825c582b7e3Smrg    return TRUE;
826c582b7e3Smrg
827c582b7e3Smrg}
828c582b7e3Smrg
829c582b7e3Smrg/* This is called by R128PreInit to handle all color weight issues. */
830c582b7e3Smrgstatic Bool R128PreInitWeight(ScrnInfoPtr pScrn)
831c582b7e3Smrg{
832c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
833c582b7e3Smrg
834c582b7e3Smrg				/* Save flag for 6 bit DAC to use for
835c582b7e3Smrg				   setting CRTC registers.  Otherwise use
836c582b7e3Smrg				   an 8 bit DAC, even if xf86SetWeight sets
837c582b7e3Smrg				   pScrn->rgbBits to some value other than
838c582b7e3Smrg				   8. */
839c582b7e3Smrg    info->dac6bits = FALSE;
840c582b7e3Smrg    if (pScrn->depth > 8) {
841c582b7e3Smrg	rgb defaultWeight = { 0, 0, 0 };
842c582b7e3Smrg	if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
843c582b7e3Smrg    } else {
844c582b7e3Smrg	pScrn->rgbBits = 8;
845c582b7e3Smrg	if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) {
846c582b7e3Smrg	    pScrn->rgbBits = 6;
847c582b7e3Smrg	    info->dac6bits = TRUE;
848c582b7e3Smrg	}
849c582b7e3Smrg    }
850c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
851c582b7e3Smrg	       "Using %d bits per RGB (%d bit DAC)\n",
852c582b7e3Smrg	       pScrn->rgbBits, info->dac6bits ? 6 : 8);
853c582b7e3Smrg
854c582b7e3Smrg    return TRUE;
855c582b7e3Smrg
856c582b7e3Smrg}
857c582b7e3Smrg
858c582b7e3Smrg/* This is called by R128PreInit to handle config file overrides for things
859c582b7e3Smrg   like chipset and memory regions.  Also determine memory size and type.
860c582b7e3Smrg   If memory type ever needs an override, put it in this routine. */
861c582b7e3Smrgstatic Bool R128PreInitConfig(ScrnInfoPtr pScrn)
862c582b7e3Smrg{
863c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
864c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
865c582b7e3Smrg    EntityInfoPtr pEnt      = info->pEnt;
866c582b7e3Smrg    GDevPtr       dev       = pEnt->device;
867c582b7e3Smrg    int           offset    = 0;        /* RAM Type */
868c582b7e3Smrg    MessageType   from;
869c582b7e3Smrg
870c582b7e3Smrg				/* Chipset */
871c582b7e3Smrg    from = X_PROBED;
872c582b7e3Smrg    if (dev->chipset && *dev->chipset) {
873c582b7e3Smrg	info->Chipset  = xf86StringToToken(R128Chipsets, dev->chipset);
874c582b7e3Smrg	from           = X_CONFIG;
875c582b7e3Smrg    } else if (dev->chipID >= 0) {
876c582b7e3Smrg	info->Chipset  = dev->chipID;
877c582b7e3Smrg	from           = X_CONFIG;
878c582b7e3Smrg    } else {
879c582b7e3Smrg	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
880c582b7e3Smrg    }
881c582b7e3Smrg    pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset);
882c582b7e3Smrg
883c582b7e3Smrg    if (!pScrn->chipset) {
884c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
885c582b7e3Smrg		   "ChipID 0x%04x is not recognized\n", info->Chipset);
886c582b7e3Smrg	return FALSE;
887c582b7e3Smrg    }
888c582b7e3Smrg
889c582b7e3Smrg    if (info->Chipset < 0) {
890c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
891c582b7e3Smrg		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
892c582b7e3Smrg	return FALSE;
893c582b7e3Smrg    }
894c582b7e3Smrg
895c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
896c582b7e3Smrg	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
897c582b7e3Smrg	       pScrn->chipset,
898c582b7e3Smrg	       info->Chipset);
899c582b7e3Smrg
900c582b7e3Smrg				/* Framebuffer */
901c582b7e3Smrg
902c582b7e3Smrg    from             = X_PROBED;
903c582b7e3Smrg    info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000;
904c582b7e3Smrg    pScrn->memPhysBase = info->LinearAddr;
905c582b7e3Smrg    if (dev->MemBase) {
906c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
907c582b7e3Smrg		   "Linear address override, using 0x%08lx instead of 0x%08lx\n",
908c582b7e3Smrg		   dev->MemBase,
909c582b7e3Smrg		   info->LinearAddr);
910c582b7e3Smrg	info->LinearAddr = dev->MemBase;
911c582b7e3Smrg	from             = X_CONFIG;
912c582b7e3Smrg    } else if (!info->LinearAddr) {
913c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
914c582b7e3Smrg		   "No valid linear framebuffer address\n");
915c582b7e3Smrg	return FALSE;
916c582b7e3Smrg    }
917c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
918c582b7e3Smrg	       "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
919c582b7e3Smrg
920c582b7e3Smrg				/* MMIO registers */
921c582b7e3Smrg    from             = X_PROBED;
922c582b7e3Smrg    info->MMIOAddr   = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00;
923c582b7e3Smrg    if (dev->IOBase) {
924c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
925c582b7e3Smrg		   "MMIO address override, using 0x%08lx instead of 0x%08lx\n",
926c582b7e3Smrg		   dev->IOBase,
927c582b7e3Smrg		   info->MMIOAddr);
928c582b7e3Smrg	info->MMIOAddr = dev->IOBase;
929c582b7e3Smrg	from           = X_CONFIG;
930c582b7e3Smrg    } else if (!info->MMIOAddr) {
931c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
932c582b7e3Smrg	return FALSE;
933c582b7e3Smrg    }
934c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
935c582b7e3Smrg	       "MMIO registers at 0x%08lx\n", info->MMIOAddr);
936c582b7e3Smrg
937c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
938c582b7e3Smrg				/* BIOS */
939c582b7e3Smrg    from              = X_PROBED;
940c582b7e3Smrg    info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
941c582b7e3Smrg    if (dev->BiosBase) {
942c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
943c582b7e3Smrg		   "BIOS address override, using 0x%08lx instead of 0x%08lx\n",
944c582b7e3Smrg		   dev->BiosBase,
945c582b7e3Smrg		   info->BIOSAddr);
946c582b7e3Smrg	info->BIOSAddr = dev->BiosBase;
947c582b7e3Smrg	from           = X_CONFIG;
948c582b7e3Smrg    }
949c582b7e3Smrg    if (info->BIOSAddr) {
950c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, from,
951c582b7e3Smrg		   "BIOS at 0x%08lx\n", info->BIOSAddr);
952c582b7e3Smrg    }
953c582b7e3Smrg#endif
954c582b7e3Smrg
955c582b7e3Smrg				/* Flat panel (part 1) */
956c582b7e3Smrg    if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS,
957c582b7e3Smrg			  &info->HasPanelRegs)) {
958c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
959c582b7e3Smrg		   "Turned flat panel register programming %s\n",
960c582b7e3Smrg		   info->HasPanelRegs ? "on" : "off");
961c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
962c582b7e3Smrg		   "\n\nWARNING: Forcing the driver to use/not use the flat panel registers\nmight damage your flat panel.  Use at your *OWN* *RISK*.\n\n");
963c582b7e3Smrg    } else {
964c582b7e3Smrg        info->isDFP = FALSE;
965c582b7e3Smrg        info->isPro2 = FALSE;
966c582b7e3Smrg        info->HasCRTC2 = FALSE;
967c582b7e3Smrg	switch (info->Chipset) {
968c582b7e3Smrg	/* R128 Pro and Pro2 can have DFP, we will deal with it.
969c582b7e3Smrg	   No support for dual-head/xinerama yet.
970c582b7e3Smrg           M3 can also have DFP, no support for now */
971c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
972c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
973c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
974c582b7e3Smrg	/* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came
975c582b7e3Smrg	 *        out at the same time, so are of the same family likely.
976c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
977c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
978c582b7e3Smrg	 */
979c582b7e3Smrg	case PCI_CHIP_RAGE128TS:
980c582b7e3Smrg	case PCI_CHIP_RAGE128TT:
981c582b7e3Smrg	case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE;
982c582b7e3Smrg	/* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP
983c582b7e3Smrg	 *        capability, as the comment at the top suggests.
984c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
985c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
986c582b7e3Smrg	 */
987c582b7e3Smrg	case PCI_CHIP_RAGE128PA:
988c582b7e3Smrg	case PCI_CHIP_RAGE128PB:
989c582b7e3Smrg	case PCI_CHIP_RAGE128PC:
990c582b7e3Smrg	case PCI_CHIP_RAGE128PE:
991c582b7e3Smrg	case PCI_CHIP_RAGE128PG:
992c582b7e3Smrg	case PCI_CHIP_RAGE128PH:
993c582b7e3Smrg	case PCI_CHIP_RAGE128PI:
994c582b7e3Smrg	case PCI_CHIP_RAGE128PJ:
995c582b7e3Smrg	case PCI_CHIP_RAGE128PK:
996c582b7e3Smrg	case PCI_CHIP_RAGE128PL:
997c582b7e3Smrg	case PCI_CHIP_RAGE128PM:
998c582b7e3Smrg	case PCI_CHIP_RAGE128PN:
999c582b7e3Smrg	case PCI_CHIP_RAGE128PO:
1000c582b7e3Smrg	case PCI_CHIP_RAGE128PQ:
1001c582b7e3Smrg	case PCI_CHIP_RAGE128PS:
1002c582b7e3Smrg	case PCI_CHIP_RAGE128PT:
1003c582b7e3Smrg	case PCI_CHIP_RAGE128PU:
1004c582b7e3Smrg	case PCI_CHIP_RAGE128PV:
1005c582b7e3Smrg	case PCI_CHIP_RAGE128PW:
1006c582b7e3Smrg	case PCI_CHIP_RAGE128PX:
1007c582b7e3Smrg
1008c582b7e3Smrg	case PCI_CHIP_RAGE128PD:
1009c582b7e3Smrg	case PCI_CHIP_RAGE128PF:
1010c582b7e3Smrg	case PCI_CHIP_RAGE128PP:
1011c582b7e3Smrg	case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break;
1012c582b7e3Smrg
1013c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
1014c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
1015c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
1016c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
1017c582b7e3Smrg			info->HasPanelRegs = TRUE;
1018c582b7e3Smrg			/* which chips support dualhead? */
1019c582b7e3Smrg			info->HasCRTC2 = TRUE;
1020c582b7e3Smrg			break;
1021c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
1022c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
1023c582b7e3Smrg	case PCI_CHIP_RAGE128RG:
1024c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
1025c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
1026c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
1027c582b7e3Smrg	/* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as
1028c582b7e3Smrg	 *        all of them are listed as "Rage 128 4x" in ATI docs.
1029c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
1030c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
1031c582b7e3Smrg	 */
1032c582b7e3Smrg	case PCI_CHIP_RAGE128SE:
1033c582b7e3Smrg	case PCI_CHIP_RAGE128SF:
1034c582b7e3Smrg	case PCI_CHIP_RAGE128SG:
1035c582b7e3Smrg	case PCI_CHIP_RAGE128SH:
1036c582b7e3Smrg	case PCI_CHIP_RAGE128SK:
1037c582b7e3Smrg	case PCI_CHIP_RAGE128SL:
1038c582b7e3Smrg	case PCI_CHIP_RAGE128SN:
1039c582b7e3Smrg	default:                 info->HasPanelRegs = FALSE; break;
1040c582b7e3Smrg	}
1041c582b7e3Smrg    }
1042c582b7e3Smrg
1043c582b7e3Smrg				/* Read registers used to determine options */
1044c582b7e3Smrg    from                      = X_PROBED;
1045c582b7e3Smrg    R128MapMMIO(pScrn);
1046c582b7e3Smrg    R128MMIO                  = info->MMIO;
1047c582b7e3Smrg
1048c582b7e3Smrg    if (info->FBDev)
1049c582b7e3Smrg	pScrn->videoRam       = fbdevHWGetVidmem(pScrn) / 1024;
1050c582b7e3Smrg    else
1051c582b7e3Smrg	pScrn->videoRam       = INREG(R128_CONFIG_MEMSIZE) / 1024;
1052c582b7e3Smrg
1053c582b7e3Smrg    info->MemCntl             = INREG(R128_MEM_CNTL);
1054c582b7e3Smrg    info->BusCntl             = INREG(R128_BUS_CNTL);
1055c582b7e3Smrg
1056c582b7e3Smrg    /* On non-flat panel systems, the default is to display to the CRT,
1057c582b7e3Smrg       and on flat panel systems, the default is to display to the flat
1058c582b7e3Smrg       panel unless the user explicity chooses otherwise using the "Display"
1059c582b7e3Smrg       config file setting.  BIOS_5_SCRATCH holds the display device on flat
1060c582b7e3Smrg       panel systems only. */
1061c582b7e3Smrg    if (info->HasPanelRegs) {
1062c582b7e3Smrg        char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY);
1063c582b7e3Smrg
1064c582b7e3Smrg	if (info->FBDev)
1065c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1066c582b7e3Smrg		     "Option \"Display\" ignored "
1067c582b7e3Smrg		     "(framebuffer device determines display type)\n");
1068c582b7e3Smrg	else if (info->IsPrimary || info->IsSecondary)
1069c582b7e3Smrg	    info->BIOSDisplay = R128_DUALHEAD;
1070c582b7e3Smrg	else if (!Display || !xf86NameCmp(Display, "FP"))
1071c582b7e3Smrg	    info->BIOSDisplay = R128_BIOS_DISPLAY_FP;
1072c582b7e3Smrg	else if (!xf86NameCmp(Display, "BIOS"))
1073c582b7e3Smrg	    info->BIOSDisplay = INREG8(R128_BIOS_5_SCRATCH);
1074c582b7e3Smrg	else if (!xf86NameCmp(Display, "Mirror"))
1075c582b7e3Smrg	    info->BIOSDisplay = R128_BIOS_DISPLAY_FP_CRT;
1076c582b7e3Smrg	else if (!xf86NameCmp(Display, "CRT"))
1077c582b7e3Smrg	    info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
1078c582b7e3Smrg	else {
1079c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1080c582b7e3Smrg		"Unsupported type \"%s\" specified for Option \"Display\".\n"
1081c582b7e3Smrg		"\tSupported types are: "
1082c582b7e3Smrg		"\"BIOS\", \"Mirror\", \"CRT\" and \"FP\"\n", Display);
1083c582b7e3Smrg	    return FALSE;
1084c582b7e3Smrg	}
1085c582b7e3Smrg    } else {
1086c582b7e3Smrg	info->BIOSDisplay     = R128_BIOS_DISPLAY_CRT;
1087c582b7e3Smrg    }
1088c582b7e3Smrg
1089c582b7e3Smrg    R128MMIO                  = NULL;
1090c582b7e3Smrg    R128UnmapMMIO(pScrn);
1091c582b7e3Smrg
1092c582b7e3Smrg				/* RAM */
1093c582b7e3Smrg    switch (info->MemCntl & 0x3) {
1094c582b7e3Smrg    case 0:                     /* SDR SGRAM 1:1 */
1095c582b7e3Smrg	switch (info->Chipset) {
1096c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
1097c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
1098c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
1099c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
1100c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
1101c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
1102c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
1103c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
1104c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
1105c582b7e3Smrg	case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
1106c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
1107c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
1108c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
1109c582b7e3Smrg	default:                 offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
1110c582b7e3Smrg	}
1111c582b7e3Smrg	break;
1112c582b7e3Smrg    case 1:                      offset = 2; break; /*  64-bit SDR SGRAM 2:1 */
1113c582b7e3Smrg    case 2:                      offset = 3; break; /*  64-bit DDR SGRAM     */
1114c582b7e3Smrg    default:                     offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
1115c582b7e3Smrg    }
1116c582b7e3Smrg    info->ram = &R128RAM[offset];
1117c582b7e3Smrg
1118c582b7e3Smrg    if (dev->videoRam) {
1119c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1120c582b7e3Smrg		   "Video RAM override, using %d kB instead of %d kB\n",
1121c582b7e3Smrg		   dev->videoRam,
1122c582b7e3Smrg		   pScrn->videoRam);
1123c582b7e3Smrg	from             = X_CONFIG;
1124c582b7e3Smrg	pScrn->videoRam  = dev->videoRam;
1125c582b7e3Smrg    }
1126c582b7e3Smrg
1127c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
1128c582b7e3Smrg	       "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
1129c582b7e3Smrg
1130c582b7e3Smrg    if (info->IsPrimary) {
1131c582b7e3Smrg        pScrn->videoRam /= 2;
1132c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1133c582b7e3Smrg		"Using %dk of videoram for primary head\n",
1134c582b7e3Smrg		pScrn->videoRam);
1135c582b7e3Smrg    }
1136c582b7e3Smrg
1137c582b7e3Smrg    if (info->IsSecondary) {
1138c582b7e3Smrg        pScrn->videoRam /= 2;
1139c582b7e3Smrg        info->LinearAddr += pScrn->videoRam * 1024;
1140c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1141c582b7e3Smrg		"Using %dk of videoram for secondary head\n",
1142c582b7e3Smrg		pScrn->videoRam);
1143c582b7e3Smrg    }
1144c582b7e3Smrg
1145c582b7e3Smrg    pScrn->videoRam  &= ~1023;
1146c582b7e3Smrg    info->FbMapSize  = pScrn->videoRam * 1024;
1147c582b7e3Smrg
1148c582b7e3Smrg
1149c582b7e3Smrg				/* Flat panel (part 2) */
1150c582b7e3Smrg	switch (info->BIOSDisplay) {
1151c582b7e3Smrg	case R128_DUALHEAD:
1152c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1153c582b7e3Smrg		       "Dual display\n");
1154c582b7e3Smrg	    break;
1155c582b7e3Smrg	case R128_BIOS_DISPLAY_FP:
1156c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1157c582b7e3Smrg		       "Using flat panel for display\n");
1158c582b7e3Smrg	    break;
1159c582b7e3Smrg	case R128_BIOS_DISPLAY_CRT:
1160c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1161c582b7e3Smrg		       "Using external CRT for display\n");
1162c582b7e3Smrg	    break;
1163c582b7e3Smrg	case R128_BIOS_DISPLAY_FP_CRT:
1164c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1165c582b7e3Smrg		       "Using both flat panel and external CRT "
1166c582b7e3Smrg		       "for display\n");
1167c582b7e3Smrg	    break;
1168c582b7e3Smrg	}
1169c582b7e3Smrg
1170c582b7e3Smrg    if (info->HasPanelRegs) {
1171c582b7e3Smrg				/* Panel width/height overrides */
1172c582b7e3Smrg	info->PanelXRes = 0;
1173c582b7e3Smrg	info->PanelYRes = 0;
1174c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1175c582b7e3Smrg				 OPTION_PANEL_WIDTH, &(info->PanelXRes))) {
1176c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1177c582b7e3Smrg		       "Flat panel width: %d\n", info->PanelXRes);
1178c582b7e3Smrg	}
1179c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1180c582b7e3Smrg				 OPTION_PANEL_HEIGHT, &(info->PanelYRes))) {
1181c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1182c582b7e3Smrg		       "Flat panel height: %d\n", info->PanelYRes);
1183c582b7e3Smrg	}
1184c582b7e3Smrg    }
1185c582b7e3Smrg
1186c582b7e3Smrg#ifdef XF86DRI
1187c582b7e3Smrg				/* DMA for Xv */
1188c582b7e3Smrg    info->DMAForXv = xf86ReturnOptValBool(info->Options, OPTION_XV_DMA, FALSE);
1189c582b7e3Smrg    if (info->DMAForXv) {
1190c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1191c582b7e3Smrg		   "Will try to use DMA for Xv image transfers\n");
1192c582b7e3Smrg    }
1193c582b7e3Smrg
1194c582b7e3Smrg				/* AGP/PCI */
1195c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) {
1196c582b7e3Smrg	info->IsPCI = TRUE;
1197c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n");
1198c582b7e3Smrg    } else {
1199c582b7e3Smrg	switch (info->Chipset) {
1200c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
1201c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
1202c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
1203c582b7e3Smrg	case PCI_CHIP_RAGE128PD:
1204c582b7e3Smrg	case PCI_CHIP_RAGE128PR:
1205c582b7e3Smrg	case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE;  break;
1206c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
1207c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
1208c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
1209c582b7e3Smrg	case PCI_CHIP_RAGE128PF:
1210c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
1211c582b7e3Smrg	case PCI_CHIP_RAGE128RG:
1212c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
1213c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
1214c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
1215c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
1216c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
1217c582b7e3Smrg	/* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are
1218c582b7e3Smrg	 * believed to be AGP, but need confirmation. <mharris@redhat.com>
1219c582b7e3Smrg	 */
1220c582b7e3Smrg	case PCI_CHIP_RAGE128PA:
1221c582b7e3Smrg	case PCI_CHIP_RAGE128PB:
1222c582b7e3Smrg	case PCI_CHIP_RAGE128PC:
1223c582b7e3Smrg	case PCI_CHIP_RAGE128PE:
1224c582b7e3Smrg	case PCI_CHIP_RAGE128PG:
1225c582b7e3Smrg	case PCI_CHIP_RAGE128PH:
1226c582b7e3Smrg	case PCI_CHIP_RAGE128PI:
1227c582b7e3Smrg	case PCI_CHIP_RAGE128PJ:
1228c582b7e3Smrg	case PCI_CHIP_RAGE128PK:
1229c582b7e3Smrg	case PCI_CHIP_RAGE128PL:
1230c582b7e3Smrg	case PCI_CHIP_RAGE128PM:
1231c582b7e3Smrg	case PCI_CHIP_RAGE128PN:
1232c582b7e3Smrg	case PCI_CHIP_RAGE128PO:
1233c582b7e3Smrg	case PCI_CHIP_RAGE128PQ:
1234c582b7e3Smrg	case PCI_CHIP_RAGE128PS:
1235c582b7e3Smrg	case PCI_CHIP_RAGE128PT:
1236c582b7e3Smrg	case PCI_CHIP_RAGE128PU:
1237c582b7e3Smrg	case PCI_CHIP_RAGE128PV:
1238c582b7e3Smrg	case PCI_CHIP_RAGE128PW:
1239c582b7e3Smrg	case PCI_CHIP_RAGE128PX:
1240c582b7e3Smrg	case PCI_CHIP_RAGE128TS:
1241c582b7e3Smrg	case PCI_CHIP_RAGE128TT:
1242c582b7e3Smrg	case PCI_CHIP_RAGE128TU:
1243c582b7e3Smrg	case PCI_CHIP_RAGE128SE:
1244c582b7e3Smrg	case PCI_CHIP_RAGE128SF:
1245c582b7e3Smrg	case PCI_CHIP_RAGE128SG:
1246c582b7e3Smrg	case PCI_CHIP_RAGE128SH:
1247c582b7e3Smrg	case PCI_CHIP_RAGE128SK:
1248c582b7e3Smrg	case PCI_CHIP_RAGE128SL:
1249c582b7e3Smrg	case PCI_CHIP_RAGE128SN:
1250c582b7e3Smrg	default:                 info->IsPCI = FALSE; break;
1251c582b7e3Smrg	}
1252c582b7e3Smrg    }
1253c582b7e3Smrg#endif
1254c582b7e3Smrg
1255c582b7e3Smrg    return TRUE;
1256c582b7e3Smrg}
1257c582b7e3Smrg
1258c582b7e3Smrgstatic Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1259c582b7e3Smrg{
1260c582b7e3Smrg#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__)
1261c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1262c582b7e3Smrg    vbeInfoPtr pVbe;
1263c582b7e3Smrg#endif
1264c582b7e3Smrg
1265c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE;
1266c582b7e3Smrg
1267c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__)
1268c582b7e3Smrg    /* Int10 is broken on PPC and some Alphas */
1269c582b7e3Smrg    return TRUE;
1270c582b7e3Smrg#else
1271c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1272c582b7e3Smrg	pVbe = VBEInit(pInt10,info->pEnt->index);
1273c582b7e3Smrg	if (!pVbe) return FALSE;
1274c582b7e3Smrg        xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
1275c582b7e3Smrg	vbeFree(pVbe);
1276c582b7e3Smrg	return TRUE;
1277c582b7e3Smrg    } else
1278c582b7e3Smrg	return FALSE;
1279c582b7e3Smrg#endif
1280c582b7e3Smrg}
1281c582b7e3Smrg
1282c582b7e3Smrg/* This is called by R128PreInit to initialize gamma correction. */
1283c582b7e3Smrgstatic Bool R128PreInitGamma(ScrnInfoPtr pScrn)
1284c582b7e3Smrg{
1285c582b7e3Smrg    Gamma zeros = { 0.0, 0.0, 0.0 };
1286c582b7e3Smrg
1287c582b7e3Smrg    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
1288c582b7e3Smrg    return TRUE;
1289c582b7e3Smrg}
1290c582b7e3Smrg
1291c582b7e3Smrgstatic void
1292c582b7e3SmrgR128I2CGetBits(I2CBusPtr b, int *Clock, int *data)
1293c582b7e3Smrg{
1294c582b7e3Smrg    ScrnInfoPtr   pScrn       = xf86Screens[b->scrnIndex];
1295c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
1296c582b7e3Smrg    unsigned long val;
1297c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
1298c582b7e3Smrg
1299c582b7e3Smrg    /* Get the result. */
1300c582b7e3Smrg    val = INREG(info->DDCReg);
1301c582b7e3Smrg    *Clock = (val & R128_GPIO_MONID_Y_3) != 0;
1302c582b7e3Smrg    *data  = (val & R128_GPIO_MONID_Y_0) != 0;
1303c582b7e3Smrg
1304c582b7e3Smrg}
1305c582b7e3Smrg
1306c582b7e3Smrgstatic void
1307c582b7e3SmrgR128I2CPutBits(I2CBusPtr b, int Clock, int data)
1308c582b7e3Smrg{
1309c582b7e3Smrg    ScrnInfoPtr   pScrn       = xf86Screens[b->scrnIndex];
1310c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
1311c582b7e3Smrg    unsigned long val;
1312c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
1313c582b7e3Smrg
1314c582b7e3Smrg    val = INREG(info->DDCReg)
1315c582b7e3Smrg              & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3);
1316c582b7e3Smrg    val |= (Clock ? 0:R128_GPIO_MONID_EN_3);
1317c582b7e3Smrg    val |= (data ? 0:R128_GPIO_MONID_EN_0);
1318c582b7e3Smrg    OUTREG(info->DDCReg, val);
1319c582b7e3Smrg}
1320c582b7e3Smrg
1321c582b7e3Smrg
1322c582b7e3Smrgstatic Bool
1323c582b7e3SmrgR128I2cInit(ScrnInfoPtr pScrn)
1324c582b7e3Smrg{
1325c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
1326c582b7e3Smrg    if ( !xf86LoadSubModule(pScrn, "i2c") ) {
1327c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1328c582b7e3Smrg            "Failed to load i2c module\n");
1329c582b7e3Smrg		return FALSE;
1330c582b7e3Smrg    }
1331c582b7e3Smrg
1332c582b7e3Smrg    info->pI2CBus = xf86CreateI2CBusRec();
1333c582b7e3Smrg    if(!info->pI2CBus) return FALSE;
1334c582b7e3Smrg
1335c582b7e3Smrg    info->pI2CBus->BusName    = "DDC";
1336c582b7e3Smrg    info->pI2CBus->scrnIndex  = pScrn->scrnIndex;
1337c582b7e3Smrg    info->DDCReg = R128_GPIO_MONID;
1338c582b7e3Smrg    info->pI2CBus->I2CPutBits = R128I2CPutBits;
1339c582b7e3Smrg    info->pI2CBus->I2CGetBits = R128I2CGetBits;
1340c582b7e3Smrg    info->pI2CBus->AcknTimeout = 5;
1341c582b7e3Smrg
1342c582b7e3Smrg    if (!xf86I2CBusInit(info->pI2CBus)) {
1343c582b7e3Smrg        return FALSE;
1344c582b7e3Smrg    }
1345c582b7e3Smrg    return TRUE;
1346c582b7e3Smrg}
1347c582b7e3Smrg
1348c582b7e3Smrg/* return TRUE is a DFP is indeed connected to a DVI port */
1349c582b7e3Smrgstatic Bool R128GetDFPInfo(ScrnInfoPtr pScrn)
1350c582b7e3Smrg{
1351c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
1352c582b7e3Smrg    int i;
1353c582b7e3Smrg    xf86MonPtr MonInfo = NULL;
1354c582b7e3Smrg    xf86MonPtr ddc;
1355c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
1356c582b7e3Smrg
1357c582b7e3Smrg    if(!R128I2cInit(pScrn)){
1358c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1359c582b7e3Smrg                  "I2C initialization failed!\n");
1360c582b7e3Smrg    }
1361c582b7e3Smrg
1362c582b7e3Smrg    OUTREG(info->DDCReg, (INREG(info->DDCReg)
1363c582b7e3Smrg           | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3));
1364c582b7e3Smrg
1365c582b7e3Smrg    OUTREG(info->DDCReg, INREG(info->DDCReg)
1366c582b7e3Smrg           & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3));
1367c582b7e3Smrg
1368c582b7e3Smrg    MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus);
1369c582b7e3Smrg    if(!MonInfo) {
1370c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1371c582b7e3Smrg                   "No DFP detected\n");
1372c582b7e3Smrg        return FALSE;
1373c582b7e3Smrg    }
1374c582b7e3Smrg    xf86SetDDCproperties(pScrn, MonInfo);
1375c582b7e3Smrg    ddc = pScrn->monitor->DDC;
1376c582b7e3Smrg
1377c582b7e3Smrg    for(i=0; i<4; i++)
1378c582b7e3Smrg    {
1379c582b7e3Smrg        if((ddc->det_mon[i].type == 0) &&
1380c582b7e3Smrg	  (ddc->det_mon[i].section.d_timings.h_active > 0) &&
1381c582b7e3Smrg	  (ddc->det_mon[i].section.d_timings.v_active > 0))
1382c582b7e3Smrg        {
1383c582b7e3Smrg            info->PanelXRes =
1384c582b7e3Smrg                ddc->det_mon[i].section.d_timings.h_active;
1385c582b7e3Smrg            info->PanelYRes =
1386c582b7e3Smrg                ddc->det_mon[i].section.d_timings.v_active;
1387c582b7e3Smrg
1388c582b7e3Smrg            info->HOverPlus =
1389c582b7e3Smrg                ddc->det_mon[i].section.d_timings.h_sync_off;
1390c582b7e3Smrg            info->HSyncWidth =
1391c582b7e3Smrg                ddc->det_mon[i].section.d_timings.h_sync_width;
1392c582b7e3Smrg            info->HBlank =
1393c582b7e3Smrg                ddc->det_mon[i].section.d_timings.h_blanking;
1394c582b7e3Smrg            info->VOverPlus =
1395c582b7e3Smrg                ddc->det_mon[i].section.d_timings.v_sync_off;
1396c582b7e3Smrg            info->VSyncWidth =
1397c582b7e3Smrg                ddc->det_mon[i].section.d_timings.v_sync_width;
1398c582b7e3Smrg            info->VBlank =
1399c582b7e3Smrg                ddc->det_mon[i].section.d_timings.v_blanking;
1400c582b7e3Smrg        }
1401c582b7e3Smrg    }
1402c582b7e3Smrg    return TRUE;
1403c582b7e3Smrg}
1404c582b7e3Smrg
1405c582b7e3Smrg
1406c582b7e3Smrgstatic void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
1407c582b7e3Smrg{
1408c582b7e3Smrg    int i;
1409c582b7e3Smrg    xf86MonPtr ddc = pScrn->monitor->DDC;
1410c582b7e3Smrg    if(flag)  /*HSync*/
1411c582b7e3Smrg    {
1412c582b7e3Smrg        for(i=0; i<4; i++)
1413c582b7e3Smrg        {
1414c582b7e3Smrg            if(ddc->det_mon[i].type == DS_RANGES)
1415c582b7e3Smrg            {
1416c582b7e3Smrg                pScrn->monitor->nHsync = 1;
1417c582b7e3Smrg                pScrn->monitor->hsync[0].lo =
1418c582b7e3Smrg                    ddc->det_mon[i].section.ranges.min_h;
1419c582b7e3Smrg                pScrn->monitor->hsync[0].hi =
1420c582b7e3Smrg                    ddc->det_mon[i].section.ranges.max_h;
1421c582b7e3Smrg                return;
1422c582b7e3Smrg            }
1423c582b7e3Smrg        }
1424c582b7e3Smrg        /*if no sync ranges detected in detailed timing table,
1425c582b7e3Smrg          let's try to derive them from supported VESA modes
1426c582b7e3Smrg          Are we doing too much here!!!?
1427c582b7e3Smrg        **/
1428c582b7e3Smrg        i = 0;
1429c582b7e3Smrg        if(ddc->timings1.t1 & 0x02) /*800x600@56*/
1430c582b7e3Smrg        {
1431c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1432c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 35.2;
1433c582b7e3Smrg            i++;
1434c582b7e3Smrg        }
1435c582b7e3Smrg        if(ddc->timings1.t1 & 0x04) /*640x480@75*/
1436c582b7e3Smrg        {
1437c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1438c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 37.5;
1439c582b7e3Smrg            i++;
1440c582b7e3Smrg        }
1441c582b7e3Smrg        if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01))
1442c582b7e3Smrg        {
1443c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1444c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 37.9;
1445c582b7e3Smrg            i++;
1446c582b7e3Smrg        }
1447c582b7e3Smrg        if(ddc->timings1.t2 & 0x40)
1448c582b7e3Smrg        {
1449c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1450c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 46.9;
1451c582b7e3Smrg            i++;
1452c582b7e3Smrg        }
1453c582b7e3Smrg        if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08))
1454c582b7e3Smrg        {
1455c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1456c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 48.1;
1457c582b7e3Smrg            i++;
1458c582b7e3Smrg        }
1459c582b7e3Smrg        if(ddc->timings1.t2 & 0x04)
1460c582b7e3Smrg        {
1461c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1462c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 56.5;
1463c582b7e3Smrg            i++;
1464c582b7e3Smrg        }
1465c582b7e3Smrg        if(ddc->timings1.t2 & 0x02)
1466c582b7e3Smrg        {
1467c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1468c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 60.0;
1469c582b7e3Smrg            i++;
1470c582b7e3Smrg        }
1471c582b7e3Smrg        if(ddc->timings1.t2 & 0x01)
1472c582b7e3Smrg        {
1473c582b7e3Smrg            pScrn->monitor->hsync[i].lo =
1474c582b7e3Smrg                pScrn->monitor->hsync[i].hi = 64.0;
1475c582b7e3Smrg            i++;
1476c582b7e3Smrg        }
1477c582b7e3Smrg        pScrn->monitor->nHsync = i;
1478c582b7e3Smrg    }
1479c582b7e3Smrg    else      /*Vrefresh*/
1480c582b7e3Smrg    {
1481c582b7e3Smrg        for(i=0; i<4; i++)
1482c582b7e3Smrg        {
1483c582b7e3Smrg            if(ddc->det_mon[i].type == DS_RANGES)
1484c582b7e3Smrg            {
1485c582b7e3Smrg                pScrn->monitor->nVrefresh = 1;
1486c582b7e3Smrg                pScrn->monitor->vrefresh[0].lo =
1487c582b7e3Smrg                    ddc->det_mon[i].section.ranges.min_v;
1488c582b7e3Smrg                pScrn->monitor->vrefresh[0].hi =
1489c582b7e3Smrg                    ddc->det_mon[i].section.ranges.max_v;
1490c582b7e3Smrg                return;
1491c582b7e3Smrg            }
1492c582b7e3Smrg        }
1493c582b7e3Smrg        i = 0;
1494c582b7e3Smrg        if(ddc->timings1.t1 & 0x02) /*800x600@56*/
1495c582b7e3Smrg        {
1496c582b7e3Smrg            pScrn->monitor->vrefresh[i].lo =
1497c582b7e3Smrg                pScrn->monitor->vrefresh[i].hi = 56;
1498c582b7e3Smrg            i++;
1499c582b7e3Smrg        }
1500c582b7e3Smrg        if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08))
1501c582b7e3Smrg        {
1502c582b7e3Smrg            pScrn->monitor->vrefresh[i].lo =
1503c582b7e3Smrg                pScrn->monitor->vrefresh[i].hi = 60;
1504c582b7e3Smrg            i++;
1505c582b7e3Smrg        }
1506c582b7e3Smrg        if(ddc->timings1.t2 & 0x04)
1507c582b7e3Smrg        {
1508c582b7e3Smrg            pScrn->monitor->vrefresh[i].lo =
1509c582b7e3Smrg                pScrn->monitor->vrefresh[i].hi = 70;
1510c582b7e3Smrg            i++;
1511c582b7e3Smrg        }
1512c582b7e3Smrg        if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80))
1513c582b7e3Smrg        {
1514c582b7e3Smrg            pScrn->monitor->vrefresh[i].lo =
1515c582b7e3Smrg                pScrn->monitor->vrefresh[i].hi = 72;
1516c582b7e3Smrg            i++;
1517c582b7e3Smrg        }
1518c582b7e3Smrg        if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40)
1519c582b7e3Smrg           || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01))
1520c582b7e3Smrg        {
1521c582b7e3Smrg            pScrn->monitor->vrefresh[i].lo =
1522c582b7e3Smrg                pScrn->monitor->vrefresh[i].hi = 75;
1523c582b7e3Smrg            i++;
1524c582b7e3Smrg        }
1525c582b7e3Smrg        pScrn->monitor->nVrefresh = i;
1526c582b7e3Smrg    }
1527c582b7e3Smrg}
1528c582b7e3Smrg
1529c582b7e3Smrg/***********
1530c582b7e3Smrg   xfree's xf86ValidateModes routine deosn't work well with DFPs
1531c582b7e3Smrg   here is our own validation routine. All modes between
1532c582b7e3Smrg   640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted.
1533c582b7e3Smrg   NOTE: RageProII doesn't support rmx, can only work with the
1534c582b7e3Smrg         standard modes the monitor can support (scale).
1535c582b7e3Smrg************/
1536c582b7e3Smrg
1537c582b7e3Smrgstatic int R128ValidateFPModes(ScrnInfoPtr pScrn)
1538c582b7e3Smrg{
1539c582b7e3Smrg    int i, j, count=0, width, height;
1540c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
1541c582b7e3Smrg    DisplayModePtr last = NULL, new = NULL, first = NULL;
1542c582b7e3Smrg    xf86MonPtr ddc;
1543c582b7e3Smrg
1544c582b7e3Smrg    /* Free any allocated modes during configuration. We don't need them*/
1545c582b7e3Smrg    while (pScrn->modes)
1546c582b7e3Smrg    {
1547c582b7e3Smrg	    xf86DeleteMode(&pScrn->modes, pScrn->modes);
1548c582b7e3Smrg    }
1549c582b7e3Smrg    while (pScrn->modePool)
1550c582b7e3Smrg    {
1551c582b7e3Smrg	    xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
1552c582b7e3Smrg    }
1553c582b7e3Smrg
1554c582b7e3Smrg    pScrn->virtualX = pScrn->display->virtualX;
1555c582b7e3Smrg    pScrn->virtualY = pScrn->display->virtualY;
1556c582b7e3Smrg
1557c582b7e3Smrg    /* If no mode specified in config, we use native resolution*/
1558c582b7e3Smrg    if(!pScrn->display->modes[0])
1559c582b7e3Smrg    {
1560c582b7e3Smrg        pScrn->display->modes[0] = xnfalloc(16);
1561c582b7e3Smrg        sprintf(pScrn->display->modes[0], "%dx%d",
1562c582b7e3Smrg               info->PanelXRes, info->PanelYRes);
1563c582b7e3Smrg    }
1564c582b7e3Smrg
1565c582b7e3Smrg    for(i=0; pScrn->display->modes[i] != NULL; i++)
1566c582b7e3Smrg    {
1567c582b7e3Smrg        if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2)
1568c582b7e3Smrg        {
1569c582b7e3Smrg
1570c582b7e3Smrg            if(width < 640 || width > info->PanelXRes ||
1571c582b7e3Smrg               height < 480 || height > info->PanelYRes)
1572c582b7e3Smrg            {
1573c582b7e3Smrg                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1574c582b7e3Smrg                    "Mode %s is out of range.\n"
1575c582b7e3Smrg                    "Valid mode should be between 640x480-%dx%d\n",
1576c582b7e3Smrg                    pScrn->display->modes[i], info->PanelXRes, info->PanelYRes);
1577c582b7e3Smrg                continue;
1578c582b7e3Smrg            }
1579c582b7e3Smrg
1580c582b7e3Smrg            new = xnfcalloc(1, sizeof(DisplayModeRec));
1581c582b7e3Smrg            new->prev = last;
1582c582b7e3Smrg            new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1);
1583c582b7e3Smrg            strcpy(new->name, pScrn->display->modes[i]);
1584c582b7e3Smrg            new->HDisplay = new->CrtcHDisplay = width;
1585c582b7e3Smrg            new->VDisplay = new->CrtcVDisplay = height;
1586c582b7e3Smrg
1587c582b7e3Smrg            ddc = pScrn->monitor->DDC;
1588c582b7e3Smrg            for(j=0; j<DET_TIMINGS; j++)
1589c582b7e3Smrg            {
1590c582b7e3Smrg                /*We use native mode clock only*/
1591c582b7e3Smrg                if(ddc->det_mon[j].type == 0){
1592c582b7e3Smrg                    new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000;
1593c582b7e3Smrg                    break;
1594c582b7e3Smrg                }
1595c582b7e3Smrg            }
1596c582b7e3Smrg
1597c582b7e3Smrg            if(new->prev) new->prev->next = new;
1598c582b7e3Smrg            last = new;
1599c582b7e3Smrg            if(!first) first = new;
1600c582b7e3Smrg            pScrn->display->virtualX =
1601c582b7e3Smrg            pScrn->virtualX = MAX(pScrn->virtualX, width);
1602c582b7e3Smrg            pScrn->display->virtualY =
1603c582b7e3Smrg            pScrn->virtualY = MAX(pScrn->virtualY, height);
1604c582b7e3Smrg            count++;
1605c582b7e3Smrg        }
1606c582b7e3Smrg        else
1607c582b7e3Smrg        {
1608c582b7e3Smrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1609c582b7e3Smrg                "Mode name %s is invalid\n", pScrn->display->modes[i]);
1610c582b7e3Smrg            continue;
1611c582b7e3Smrg        }
1612c582b7e3Smrg   }
1613c582b7e3Smrg
1614c582b7e3Smrg   if(last)
1615c582b7e3Smrg   {
1616c582b7e3Smrg       last->next = first;
1617c582b7e3Smrg       first->prev = last;
1618c582b7e3Smrg       pScrn->modes = first;
1619c582b7e3Smrg
1620c582b7e3Smrg       /*FIXME: May need to validate line pitch here*/
1621c582b7e3Smrg       {
1622c582b7e3Smrg           int dummy = 0;
1623c582b7e3Smrg           switch(pScrn->depth / 8)
1624c582b7e3Smrg           {
1625c582b7e3Smrg              case 1:
1626c582b7e3Smrg                  dummy = 128 - pScrn->virtualX % 128;
1627c582b7e3Smrg                  break;
1628c582b7e3Smrg              case 2:
1629c582b7e3Smrg                  dummy = 32 - pScrn->virtualX % 32;
1630c582b7e3Smrg                  break;
1631c582b7e3Smrg              case 3:
1632c582b7e3Smrg              case 4:
1633c582b7e3Smrg                  dummy = 16 - pScrn->virtualX % 16;
1634c582b7e3Smrg           }
1635c582b7e3Smrg           pScrn->displayWidth = pScrn->virtualX + dummy;
1636c582b7e3Smrg       }
1637c582b7e3Smrg
1638c582b7e3Smrg   }
1639c582b7e3Smrg
1640c582b7e3Smrg   return count;
1641c582b7e3Smrg}
1642c582b7e3Smrg
1643c582b7e3Smrg
1644c582b7e3Smrg/* This is called by R128PreInit to validate modes and compute parameters
1645c582b7e3Smrg   for all of the valid modes. */
1646c582b7e3Smrgstatic Bool R128PreInitModes(ScrnInfoPtr pScrn)
1647c582b7e3Smrg{
1648c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1649c582b7e3Smrg    ClockRangePtr clockRanges;
1650c582b7e3Smrg    int           modesFound;
1651c582b7e3Smrg
1652c582b7e3Smrg    if(info->isDFP) {
1653c582b7e3Smrg        R128MapMem(pScrn);
1654c582b7e3Smrg        info->BIOSDisplay = R128_BIOS_DISPLAY_FP;
1655c582b7e3Smrg        /* validate if DFP really connected. */
1656c582b7e3Smrg        if(!R128GetDFPInfo(pScrn)) {
1657c582b7e3Smrg            info->isDFP = FALSE;
1658c582b7e3Smrg            info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
1659c582b7e3Smrg        } else if(!info->isPro2) {
1660c582b7e3Smrg            /* RageProII doesn't support rmx, we can't use native-mode
1661c582b7e3Smrg               stretching for other non-native modes. It will rely on
1662c582b7e3Smrg               whatever VESA modes monitor can support. */
1663c582b7e3Smrg            modesFound = R128ValidateFPModes(pScrn);
1664c582b7e3Smrg            if(modesFound < 1) {
1665c582b7e3Smrg                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1666c582b7e3Smrg                     "No valid mode found for this DFP/LCD\n");
1667c582b7e3Smrg                 R128UnmapMem(pScrn);
1668c582b7e3Smrg                 return FALSE;
1669c582b7e3Smrg
1670c582b7e3Smrg            }
1671c582b7e3Smrg        }
1672c582b7e3Smrg        R128UnmapMem(pScrn);
1673c582b7e3Smrg    }
1674c582b7e3Smrg
1675c582b7e3Smrg    if(!info->isDFP || info->isPro2) {
1676c582b7e3Smrg				/* Get mode information */
1677c582b7e3Smrg        pScrn->progClock                   = TRUE;
1678c582b7e3Smrg        clockRanges                        = xnfcalloc(sizeof(*clockRanges), 1);
1679c582b7e3Smrg        clockRanges->next                  = NULL;
1680c582b7e3Smrg        clockRanges->minClock              = info->pll.min_pll_freq;
1681c582b7e3Smrg        clockRanges->maxClock              = info->pll.max_pll_freq * 10;
1682c582b7e3Smrg        clockRanges->clockIndex            = -1;
1683c582b7e3Smrg        if (info->HasPanelRegs || info->isDFP) {
1684c582b7e3Smrg            clockRanges->interlaceAllowed  = FALSE;
1685c582b7e3Smrg            clockRanges->doubleScanAllowed = FALSE;
1686c582b7e3Smrg        } else {
1687c582b7e3Smrg            clockRanges->interlaceAllowed  = TRUE;
1688c582b7e3Smrg            clockRanges->doubleScanAllowed = TRUE;
1689c582b7e3Smrg        }
1690c582b7e3Smrg
1691c582b7e3Smrg        if(pScrn->monitor->DDC) {
1692c582b7e3Smrg        /*if we still don't know sync range yet, let's try EDID.
1693c582b7e3Smrg          Note that, since we can have dual heads, the Xconfigurator
1694c582b7e3Smrg          may not be able to probe both monitors correctly through
1695c582b7e3Smrg          vbe probe function (R128ProbeDDC). Here we provide an
1696c582b7e3Smrg          additional way to auto-detect sync ranges if they haven't
1697c582b7e3Smrg          been added to XF86Config manually.
1698c582b7e3Smrg        **/
1699c582b7e3Smrg            if(pScrn->monitor->nHsync <= 0)
1700c582b7e3Smrg                R128SetSyncRangeFromEdid(pScrn, 1);
1701c582b7e3Smrg            if(pScrn->monitor->nVrefresh <= 0)
1702c582b7e3Smrg                R128SetSyncRangeFromEdid(pScrn, 0);
1703c582b7e3Smrg        }
1704c582b7e3Smrg
1705c582b7e3Smrg        modesFound = xf86ValidateModes(pScrn,
1706c582b7e3Smrg				   pScrn->monitor->Modes,
1707c582b7e3Smrg				   pScrn->display->modes,
1708c582b7e3Smrg				   clockRanges,
1709c582b7e3Smrg				   NULL,        /* linePitches */
1710c582b7e3Smrg				   8 * 64,      /* minPitch */
1711c582b7e3Smrg				   8 * 1024,    /* maxPitch */
1712c582b7e3Smrg/*
1713c582b7e3Smrg * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of
1714c582b7e3Smrg * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks
1715c582b7e3Smrg */
1716c582b7e3Smrg				   8 * 32,      /* pitchInc */
1717c582b7e3Smrg				   128,         /* minHeight */
1718c582b7e3Smrg				   2048,        /* maxHeight */
1719c582b7e3Smrg				   pScrn->display->virtualX,
1720c582b7e3Smrg				   pScrn->display->virtualY,
1721c582b7e3Smrg				   info->FbMapSize,
1722c582b7e3Smrg				   LOOKUP_BEST_REFRESH);
1723c582b7e3Smrg
1724c582b7e3Smrg        if (modesFound < 1 && info->FBDev) {
1725c582b7e3Smrg		fbdevHWUseBuildinMode(pScrn);
1726c582b7e3Smrg		pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8);
1727c582b7e3Smrg		modesFound = 1;
1728c582b7e3Smrg        }
1729c582b7e3Smrg
1730c582b7e3Smrg        if (modesFound == -1) return FALSE;
1731c582b7e3Smrg        xf86PruneDriverModes(pScrn);
1732c582b7e3Smrg        if (!modesFound || !pScrn->modes) {
1733c582b7e3Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
1734c582b7e3Smrg            return FALSE;
1735c582b7e3Smrg        }
1736c582b7e3Smrg        xf86SetCrtcForModes(pScrn, 0);
1737c582b7e3Smrg    }
1738c582b7e3Smrg				/* Set DPI */
1739c582b7e3Smrg    pScrn->currentMode = pScrn->modes;
1740c582b7e3Smrg    xf86PrintModes(pScrn);
1741c582b7e3Smrg
1742c582b7e3Smrg    xf86SetDpi(pScrn, 0, 0);
1743c582b7e3Smrg
1744c582b7e3Smrg				/* Get ScreenInit function */
1745c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
1746c582b7e3Smrg
1747c582b7e3Smrg    info->CurrentLayout.displayWidth = pScrn->displayWidth;
1748c582b7e3Smrg    info->CurrentLayout.mode = pScrn->currentMode;
1749c582b7e3Smrg
1750c582b7e3Smrg    return TRUE;
1751c582b7e3Smrg}
1752c582b7e3Smrg
1753c582b7e3Smrg/* This is called by R128PreInit to initialize the hardware cursor. */
1754c582b7e3Smrgstatic Bool R128PreInitCursor(ScrnInfoPtr pScrn)
1755c582b7e3Smrg{
1756c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1757c582b7e3Smrg
1758c582b7e3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1759c582b7e3Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
1760c582b7e3Smrg    }
1761c582b7e3Smrg    return TRUE;
1762c582b7e3Smrg}
1763c582b7e3Smrg
1764c582b7e3Smrg/* This is called by R128PreInit to initialize hardware acceleration. */
1765c582b7e3Smrgstatic Bool R128PreInitAccel(ScrnInfoPtr pScrn)
1766c582b7e3Smrg{
1767c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1768c582b7e3Smrg
1769c582b7e3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
1770c582b7e3Smrg	if (!xf86LoadSubModule(pScrn, "xaa")) return FALSE;
1771c582b7e3Smrg    }
1772c582b7e3Smrg    return TRUE;
1773c582b7e3Smrg}
1774c582b7e3Smrg
1775c582b7e3Smrgstatic Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
1776c582b7e3Smrg{
1777c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1778c582b7e3Smrg#if 1 && !defined(__alpha__)
1779c582b7e3Smrg    /* int10 is broken on some Alphas */
1780c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "int10")) {
1781c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
1782c582b7e3Smrg	*ppInt10 = xf86InitInt10(info->pEnt->index);
1783c582b7e3Smrg    }
1784c582b7e3Smrg#endif
1785c582b7e3Smrg    return TRUE;
1786c582b7e3Smrg}
1787c582b7e3Smrg
1788c582b7e3Smrg#ifdef XF86DRI
1789c582b7e3Smrgstatic Bool R128PreInitDRI(ScrnInfoPtr pScrn)
1790c582b7e3Smrg{
1791c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1792c582b7e3Smrg
1793c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) {
1794c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CCE into PIO mode\n");
1795c582b7e3Smrg	info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
1796c582b7e3Smrg    } else {
1797c582b7e3Smrg	info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
1798c582b7e3Smrg    }
1799c582b7e3Smrg
1800c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
1801c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1802c582b7e3Smrg		   "WARNING!!!  CCE Security checks disabled!!! **********\n");
1803c582b7e3Smrg	info->CCESecure = FALSE;
1804c582b7e3Smrg    } else {
1805c582b7e3Smrg	info->CCESecure = TRUE;
1806c582b7e3Smrg    }
1807c582b7e3Smrg
1808c582b7e3Smrg    info->agpMode        = R128_DEFAULT_AGP_MODE;
1809c582b7e3Smrg    info->agpSize        = R128_DEFAULT_AGP_SIZE;
1810c582b7e3Smrg    info->ringSize       = R128_DEFAULT_RING_SIZE;
1811c582b7e3Smrg    info->bufSize        = R128_DEFAULT_BUFFER_SIZE;
1812c582b7e3Smrg    info->agpTexSize     = R128_DEFAULT_AGP_TEX_SIZE;
1813c582b7e3Smrg
1814c582b7e3Smrg    info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
1815c582b7e3Smrg
1816c582b7e3Smrg    if (!info->IsPCI) {
1817c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1818c582b7e3Smrg				 OPTION_AGP_MODE, &(info->agpMode))) {
1819c582b7e3Smrg	    if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
1820c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1821c582b7e3Smrg			   "Illegal AGP Mode: %d\n", info->agpMode);
1822c582b7e3Smrg		return FALSE;
1823c582b7e3Smrg	    }
1824c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1825c582b7e3Smrg		       "Using AGP %dx mode\n", info->agpMode);
1826c582b7e3Smrg	}
1827c582b7e3Smrg
1828c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1829c582b7e3Smrg				 OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
1830c582b7e3Smrg	    switch (info->agpSize) {
1831c582b7e3Smrg	    case 4:
1832c582b7e3Smrg	    case 8:
1833c582b7e3Smrg	    case 16:
1834c582b7e3Smrg	    case 32:
1835c582b7e3Smrg	    case 64:
1836c582b7e3Smrg	    case 128:
1837c582b7e3Smrg	    case 256:
1838c582b7e3Smrg		break;
1839c582b7e3Smrg	    default:
1840c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1841c582b7e3Smrg			   "Illegal AGP size: %d MB\n", info->agpSize);
1842c582b7e3Smrg		return FALSE;
1843c582b7e3Smrg	    }
1844c582b7e3Smrg	}
1845c582b7e3Smrg
1846c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1847c582b7e3Smrg				 OPTION_RING_SIZE, &(info->ringSize))) {
1848c582b7e3Smrg	    if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
1849c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1850c582b7e3Smrg			   "Illegal ring buffer size: %d MB\n",
1851c582b7e3Smrg			   info->ringSize);
1852c582b7e3Smrg		return FALSE;
1853c582b7e3Smrg	    }
1854c582b7e3Smrg	}
1855c582b7e3Smrg
1856c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1857c582b7e3Smrg				 OPTION_BUFFER_SIZE, &(info->bufSize))) {
1858c582b7e3Smrg	    if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
1859c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1860c582b7e3Smrg			   "Illegal vertex/indirect buffers size: %d MB\n",
1861c582b7e3Smrg			   info->bufSize);
1862c582b7e3Smrg		return FALSE;
1863c582b7e3Smrg	    }
1864c582b7e3Smrg	    if (info->bufSize > 2) {
1865c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1866c582b7e3Smrg			   "Illegal vertex/indirect buffers size: %d MB\n",
1867c582b7e3Smrg			   info->bufSize);
1868c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1869c582b7e3Smrg			   "Clamping vertex/indirect buffers size to 2 MB\n");
1870c582b7e3Smrg		info->bufSize = 2;
1871c582b7e3Smrg	    }
1872c582b7e3Smrg	}
1873c582b7e3Smrg
1874c582b7e3Smrg	if (info->ringSize + info->bufSize + info->agpTexSize >
1875c582b7e3Smrg	    (int)info->agpSize) {
1876c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1877c582b7e3Smrg		       "Buffers are too big for requested AGP space\n");
1878c582b7e3Smrg	    return FALSE;
1879c582b7e3Smrg	}
1880c582b7e3Smrg
1881c582b7e3Smrg	info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
1882c582b7e3Smrg    }
1883c582b7e3Smrg
1884c582b7e3Smrg    if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
1885c582b7e3Smrg			     &(info->CCEusecTimeout))) {
1886c582b7e3Smrg	/* This option checked by the R128 DRM kernel module */
1887c582b7e3Smrg    }
1888c582b7e3Smrg
1889c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1890c582b7e3Smrg	info->allowPageFlip = 0;
1891c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1892c582b7e3Smrg		   "Couldn't load shadowfb module:\n");
1893c582b7e3Smrg    } else {
1894c582b7e3Smrg	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1895c582b7e3Smrg						   OPTION_PAGE_FLIP,
1896c582b7e3Smrg						   FALSE);
1897c582b7e3Smrg    }
1898c582b7e3Smrg
1899c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n",
1900c582b7e3Smrg	       info->allowPageFlip ? "en" : "dis");
1901c582b7e3Smrg
1902c582b7e3Smrg    return TRUE;
1903c582b7e3Smrg}
1904c582b7e3Smrg#endif
1905c582b7e3Smrg
1906c582b7e3Smrgstatic void
1907c582b7e3SmrgR128ProbeDDC(ScrnInfoPtr pScrn, int indx)
1908c582b7e3Smrg{
1909c582b7e3Smrg    vbeInfoPtr pVbe;
1910c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1911c582b7e3Smrg	pVbe = VBEInit(NULL,indx);
1912c582b7e3Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1913c582b7e3Smrg	vbeFree(pVbe);
1914c582b7e3Smrg    }
1915c582b7e3Smrg}
1916c582b7e3Smrg
1917c582b7e3Smrg/* R128PreInit is called once at server startup. */
1918c582b7e3SmrgBool R128PreInit(ScrnInfoPtr pScrn, int flags)
1919c582b7e3Smrg{
1920c582b7e3Smrg    R128InfoPtr      info;
1921c582b7e3Smrg    xf86Int10InfoPtr pInt10 = NULL;
1922c582b7e3Smrg
1923c582b7e3Smrg    R128TRACE(("R128PreInit\n"));
1924c582b7e3Smrg
1925c582b7e3Smrg    if (pScrn->numEntities != 1) return FALSE;
1926c582b7e3Smrg
1927c582b7e3Smrg    if (!R128GetRec(pScrn)) return FALSE;
1928c582b7e3Smrg
1929c582b7e3Smrg    info               = R128PTR(pScrn);
1930c582b7e3Smrg
1931c582b7e3Smrg    info->IsSecondary  = FALSE;
1932c582b7e3Smrg    info->IsPrimary = FALSE;
1933c582b7e3Smrg    info->SwitchingMode = FALSE;
1934c582b7e3Smrg
1935c582b7e3Smrg    info->pEnt         = xf86GetEntityInfo(pScrn->entityList[0]);
1936c582b7e3Smrg    if (info->pEnt->location.type != BUS_PCI) goto fail;
1937c582b7e3Smrg
1938c582b7e3Smrg    if(xf86IsEntityShared(pScrn->entityList[0]))
1939c582b7e3Smrg    {
1940c582b7e3Smrg        if(xf86IsPrimInitDone(pScrn->entityList[0]))
1941c582b7e3Smrg        {
1942c582b7e3Smrg            DevUnion* pPriv;
1943c582b7e3Smrg            R128EntPtr pR128Ent;
1944c582b7e3Smrg            info->IsSecondary = TRUE;
1945c582b7e3Smrg            pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
1946c582b7e3Smrg                    getR128EntityIndex());
1947c582b7e3Smrg            pR128Ent = pPriv->ptr;
1948c582b7e3Smrg            if(pR128Ent->BypassSecondary) return FALSE;
1949c582b7e3Smrg            pR128Ent->pSecondaryScrn = pScrn;
1950c582b7e3Smrg        }
1951c582b7e3Smrg        else
1952c582b7e3Smrg        {
1953c582b7e3Smrg            DevUnion* pPriv;
1954c582b7e3Smrg            R128EntPtr pR128Ent;
1955c582b7e3Smrg	    info->IsPrimary = TRUE;
1956c582b7e3Smrg            xf86SetPrimInitDone(pScrn->entityList[0]);
1957c582b7e3Smrg            pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
1958c582b7e3Smrg                    getR128EntityIndex());
1959c582b7e3Smrg            pR128Ent = pPriv->ptr;
1960c582b7e3Smrg            pR128Ent->pPrimaryScrn = pScrn;
1961c582b7e3Smrg            pR128Ent->IsDRIEnabled = FALSE;
1962c582b7e3Smrg            pR128Ent->BypassSecondary = FALSE;
1963c582b7e3Smrg            pR128Ent->HasSecondary = FALSE;
1964c582b7e3Smrg            pR128Ent->RestorePrimary = FALSE;
1965c582b7e3Smrg            pR128Ent->IsSecondaryRestored = FALSE;
1966c582b7e3Smrg        }
1967c582b7e3Smrg    }
1968c582b7e3Smrg
1969c582b7e3Smrg    if (flags & PROBE_DETECT) {
1970c582b7e3Smrg	R128ProbeDDC(pScrn, info->pEnt->index);
1971c582b7e3Smrg	return TRUE;
1972c582b7e3Smrg    }
1973c582b7e3Smrg
1974c582b7e3Smrg    info->PciInfo      = xf86GetPciInfoForEntity(info->pEnt->index);
1975c582b7e3Smrg    info->PciTag       = pciTag(PCI_DEV_BUS(info->PciInfo),
1976c582b7e3Smrg				PCI_DEV_DEV(info->PciInfo),
1977c582b7e3Smrg				PCI_DEV_FUNC(info->PciInfo));
1978c582b7e3Smrg
1979c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1980c582b7e3Smrg	       "PCI bus %d card %d func %d\n",
1981c582b7e3Smrg	       PCI_DEV_BUS(info->PciInfo),
1982c582b7e3Smrg	       PCI_DEV_DEV(info->PciInfo),
1983c582b7e3Smrg	       PCI_DEV_FUNC(info->PciInfo));
1984c582b7e3Smrg
198519019ffeSmrg#ifndef XSERVER_LIBPCIACCESS
1986c582b7e3Smrg    if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail;
1987c582b7e3Smrg    if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail;
1988c582b7e3Smrg
1989c582b7e3Smrg    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
199019019ffeSmrg#endif
1991c582b7e3Smrg    pScrn->monitor     = pScrn->confScreen->monitor;
1992c582b7e3Smrg
1993c582b7e3Smrg    if (!R128PreInitVisual(pScrn))    goto fail;
1994c582b7e3Smrg
1995c582b7e3Smrg				/* We can't do this until we have a
1996c582b7e3Smrg				   pScrn->display. */
1997c582b7e3Smrg    xf86CollectOptions(pScrn, NULL);
1998c582b7e3Smrg    if (!(info->Options = xalloc(sizeof(R128Options))))    goto fail;
1999c582b7e3Smrg    memcpy(info->Options, R128Options, sizeof(R128Options));
2000c582b7e3Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
2001c582b7e3Smrg
2002c582b7e3Smrg    /* By default, don't do VGA IOs on ppc */
2003c582b7e3Smrg#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW)
2004c582b7e3Smrg    info->VGAAccess = FALSE;
2005c582b7e3Smrg#else
2006c582b7e3Smrg    info->VGAAccess = TRUE;
2007c582b7e3Smrg#endif
2008c582b7e3Smrg
2009c582b7e3Smrg#ifdef WITH_VGAHW
2010c582b7e3Smrg    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess);
2011c582b7e3Smrg    if (info->VGAAccess) {
2012c582b7e3Smrg       if (!xf86LoadSubModule(pScrn, "vgahw"))
2013c582b7e3Smrg           info->VGAAccess = FALSE;
2014c582b7e3Smrg        else {
2015c582b7e3Smrg            if (!vgaHWGetHWRec(pScrn))
2016c582b7e3Smrg               info->VGAAccess = FALSE;
2017c582b7e3Smrg       }
2018c582b7e3Smrg       if (!info->VGAAccess)
2019c582b7e3Smrg           xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed,"
2020c582b7e3Smrg                      " trying to run without it\n");
2021c582b7e3Smrg    } else
2022c582b7e3Smrg           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE,"
2023c582b7e3Smrg                      " VGA module load skipped\n");
2024c582b7e3Smrg    if (info->VGAAccess)
2025c582b7e3Smrg        vgaHWGetIOBase(VGAHWPTR(pScrn));
2026c582b7e3Smrg#else
2027c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAHW support not compiled, VGA "
2028c582b7e3Smrg               "module load skipped\n");
2029c582b7e3Smrg#endif
2030c582b7e3Smrg
2031c582b7e3Smrg
2032c582b7e3Smrg
2033c582b7e3Smrg    if (!R128PreInitWeight(pScrn))    goto fail;
2034c582b7e3Smrg
2035c582b7e3Smrg    if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) {
2036c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
2037c582b7e3Smrg                                info->videoKey);
2038c582b7e3Smrg    } else {
2039c582b7e3Smrg        info->videoKey = 0x1E;
2040c582b7e3Smrg    }
2041c582b7e3Smrg
2042c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) {
2043c582b7e3Smrg        info->showCache = TRUE;
2044c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
2045c582b7e3Smrg    }
2046c582b7e3Smrg
2047c582b7e3Smrg#ifdef __powerpc__
2048c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE))
2049c582b7e3Smrg#else
2050c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE))
2051c582b7e3Smrg#endif
2052c582b7e3Smrg    {
2053c582b7e3Smrg	info->FBDev = TRUE;
2054c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2055c582b7e3Smrg		   "Using framebuffer device\n");
2056c582b7e3Smrg    }
2057c582b7e3Smrg
2058c582b7e3Smrg    if (info->FBDev) {
2059c582b7e3Smrg	/* check for linux framebuffer device */
2060c582b7e3Smrg	if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE;
2061c582b7e3Smrg	if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE;
2062c582b7e3Smrg	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
2063c582b7e3Smrg	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
2064c582b7e3Smrg	pScrn->ValidMode     = fbdevHWValidModeWeak();
2065c582b7e3Smrg    }
2066c582b7e3Smrg
2067c582b7e3Smrg    if (!info->FBDev)
2068c582b7e3Smrg	if (!R128PreInitInt10(pScrn, &pInt10)) goto fail;
2069c582b7e3Smrg
2070c582b7e3Smrg    if (!R128PreInitConfig(pScrn))             goto fail;
2071c582b7e3Smrg
2072c582b7e3Smrg    if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail;
2073c582b7e3Smrg
2074c582b7e3Smrg    if (!R128GetPLLParameters(pScrn))          goto fail;
2075c582b7e3Smrg
2076c582b7e3Smrg    /* Don't fail on this one */
2077c582b7e3Smrg    R128PreInitDDC(pScrn, pInt10);
2078c582b7e3Smrg
2079c582b7e3Smrg    if (!R128PreInitGamma(pScrn))              goto fail;
2080c582b7e3Smrg
2081c582b7e3Smrg    if (!R128PreInitModes(pScrn))              goto fail;
2082c582b7e3Smrg
2083c582b7e3Smrg    if (!R128PreInitCursor(pScrn))             goto fail;
2084c582b7e3Smrg
2085c582b7e3Smrg    if (!R128PreInitAccel(pScrn))              goto fail;
2086c582b7e3Smrg
2087c582b7e3Smrg#ifdef XF86DRI
2088c582b7e3Smrg    if (!R128PreInitDRI(pScrn))                goto fail;
2089c582b7e3Smrg#endif
2090c582b7e3Smrg
2091c582b7e3Smrg				/* Free the video bios (if applicable) */
2092c582b7e3Smrg    if (info->VBIOS) {
2093c582b7e3Smrg	xfree(info->VBIOS);
2094c582b7e3Smrg	info->VBIOS = NULL;
2095c582b7e3Smrg    }
2096c582b7e3Smrg
2097c582b7e3Smrg				/* Free int10 info */
2098c582b7e3Smrg    if (pInt10)
2099c582b7e3Smrg	xf86FreeInt10(pInt10);
2100c582b7e3Smrg
2101c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
2102c582b7e3Smrg	"For information on using the multimedia capabilities\n\tof this"
2103c582b7e3Smrg	" adapter, please see http://gatos.sf.net.\n");
2104c582b7e3Smrg
2105c582b7e3Smrg    return TRUE;
2106c582b7e3Smrg
2107c582b7e3Smrg  fail:
2108c582b7e3Smrg				/* Pre-init failed. */
2109c582b7e3Smrg
2110c582b7e3Smrg				/* Free the video bios (if applicable) */
2111c582b7e3Smrg    if (info->VBIOS) {
2112c582b7e3Smrg	xfree(info->VBIOS);
2113c582b7e3Smrg	info->VBIOS = NULL;
2114c582b7e3Smrg    }
2115c582b7e3Smrg
2116c582b7e3Smrg				/* Free int10 info */
2117c582b7e3Smrg    if (pInt10)
2118c582b7e3Smrg	xf86FreeInt10(pInt10);
2119c582b7e3Smrg
2120c582b7e3Smrg#ifdef WITH_VGAHW
2121c582b7e3Smrg    if (info->VGAAccess)
2122c582b7e3Smrg           vgaHWFreeHWRec(pScrn);
2123c582b7e3Smrg#endif
2124c582b7e3Smrg    R128FreeRec(pScrn);
2125c582b7e3Smrg    return FALSE;
2126c582b7e3Smrg}
2127c582b7e3Smrg
2128c582b7e3Smrg/* Load a palette. */
2129c582b7e3Smrgstatic void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
2130c582b7e3Smrg			    int *indices, LOCO *colors, VisualPtr pVisual)
2131c582b7e3Smrg{
2132c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2133c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2134c582b7e3Smrg    int           i, j;
2135c582b7e3Smrg    int           idx;
2136c582b7e3Smrg    unsigned char r, g, b;
2137c582b7e3Smrg
2138c582b7e3Smrg    /* If the second monitor is connected, we also
2139c582b7e3Smrg       need to deal with the secondary palette*/
2140c582b7e3Smrg    if (info->IsSecondary) j = 1;
2141c582b7e3Smrg    else j = 0;
2142c582b7e3Smrg
2143c582b7e3Smrg    PAL_SELECT(j);
2144c582b7e3Smrg
2145c582b7e3Smrg
2146c582b7e3Smrg    /* Select palette 0 (main CRTC) if using FP-enabled chip */
2147c582b7e3Smrg    /*if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);*/
2148c582b7e3Smrg
2149c582b7e3Smrg    if (info->CurrentLayout.depth == 15) {
2150c582b7e3Smrg	/* 15bpp mode.  This sends 32 values. */
2151c582b7e3Smrg	for (i = 0; i < numColors; i++) {
2152c582b7e3Smrg	    idx = indices[i];
2153c582b7e3Smrg	    r   = colors[idx].red;
2154c582b7e3Smrg	    g   = colors[idx].green;
2155c582b7e3Smrg	    b   = colors[idx].blue;
2156c582b7e3Smrg	    OUTPAL(idx * 8, r, g, b);
2157c582b7e3Smrg	}
2158c582b7e3Smrg    }
2159c582b7e3Smrg    else if (info->CurrentLayout.depth == 16) {
2160c582b7e3Smrg	/* 16bpp mode.  This sends 64 values. */
2161c582b7e3Smrg				/* There are twice as many green values as
2162c582b7e3Smrg				   there are values for red and blue.  So,
2163c582b7e3Smrg				   we take each red and blue pair, and
2164c582b7e3Smrg				   combine it with each of the two green
2165c582b7e3Smrg				   values. */
2166c582b7e3Smrg	for (i = 0; i < numColors; i++) {
2167c582b7e3Smrg	    idx = indices[i];
2168c582b7e3Smrg	    r   = colors[idx / 2].red;
2169c582b7e3Smrg	    g   = colors[idx].green;
2170c582b7e3Smrg	    b   = colors[idx / 2].blue;
2171c582b7e3Smrg	    OUTPAL(idx * 4, r, g, b);
2172c582b7e3Smrg	}
2173c582b7e3Smrg    }
2174c582b7e3Smrg    else {
2175c582b7e3Smrg	/* 8bpp mode.  This sends 256 values. */
2176c582b7e3Smrg	for (i = 0; i < numColors; i++) {
2177c582b7e3Smrg	    idx = indices[i];
2178c582b7e3Smrg	    r   = colors[idx].red;
2179c582b7e3Smrg	    b   = colors[idx].blue;
2180c582b7e3Smrg	    g   = colors[idx].green;
2181c582b7e3Smrg	    OUTPAL(idx, r, g, b);
2182c582b7e3Smrg	}
2183c582b7e3Smrg    }
2184c582b7e3Smrg}
2185c582b7e3Smrg
2186c582b7e3Smrgstatic void
2187c582b7e3SmrgR128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
2188c582b7e3Smrg{
2189c582b7e3Smrg    ScreenPtr   pScreen = screenInfo.screens[i];
2190c582b7e3Smrg    ScrnInfoPtr pScrn   = xf86Screens[i];
2191c582b7e3Smrg    R128InfoPtr info    = R128PTR(pScrn);
2192c582b7e3Smrg
2193c582b7e3Smrg#ifdef XF86DRI
2194c582b7e3Smrg    if (info->directRenderingEnabled)
2195c582b7e3Smrg        FLUSH_RING();
2196c582b7e3Smrg#endif
2197c582b7e3Smrg
2198c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
2199c582b7e3Smrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
2200c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
2201c582b7e3Smrg
2202c582b7e3Smrg    if(info->VideoTimerCallback) {
2203c582b7e3Smrg        (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
2204c582b7e3Smrg    }
2205c582b7e3Smrg}
2206c582b7e3Smrg
2207c582b7e3Smrg/* Called at the start of each server generation. */
2208c582b7e3SmrgBool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
2209c582b7e3Smrg                              int argc, char **argv)
2210c582b7e3Smrg{
2211c582b7e3Smrg    ScrnInfoPtr pScrn  = xf86Screens[pScreen->myNum];
2212c582b7e3Smrg    R128InfoPtr info   = R128PTR(pScrn);
2213c582b7e3Smrg    BoxRec      MemBox;
2214c582b7e3Smrg    int		y2;
2215c582b7e3Smrg
2216c582b7e3Smrg    R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset));
2217c582b7e3Smrg
2218c582b7e3Smrg#ifdef XF86DRI
2219c582b7e3Smrg				/* Turn off the CCE for now. */
2220c582b7e3Smrg    info->CCEInUse     = FALSE;
2221c582b7e3Smrg    info->indirectBuffer = NULL;
2222c582b7e3Smrg#endif
2223c582b7e3Smrg
2224c582b7e3Smrg    if (!R128MapMem(pScrn)) return FALSE;
2225c582b7e3Smrg    pScrn->fbOffset    = 0;
2226c582b7e3Smrg    if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
2227c582b7e3Smrg#ifdef XF86DRI
2228c582b7e3Smrg    info->fbX          = 0;
2229c582b7e3Smrg    info->fbY          = 0;
2230c582b7e3Smrg    info->frontOffset  = 0;
2231c582b7e3Smrg    info->frontPitch   = pScrn->displayWidth;
2232c582b7e3Smrg#endif
2233c582b7e3Smrg
2234c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
2235c582b7e3Smrg
2236c582b7e3Smrg    R128Save(pScrn);
2237c582b7e3Smrg    if (info->FBDev) {
2238c582b7e3Smrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
2239c582b7e3Smrg    } else {
2240c582b7e3Smrg	if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
2241c582b7e3Smrg    }
2242c582b7e3Smrg
2243c582b7e3Smrg    R128SaveScreen(pScreen, SCREEN_SAVER_ON);
2244c582b7e3Smrg    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
2245c582b7e3Smrg
2246c582b7e3Smrg				/* Visual setup */
2247c582b7e3Smrg    miClearVisualTypes();
2248c582b7e3Smrg    if (!miSetVisualTypes(pScrn->depth,
2249c582b7e3Smrg			  miGetDefaultVisualMask(pScrn->depth),
2250c582b7e3Smrg			  pScrn->rgbBits,
2251c582b7e3Smrg			  pScrn->defaultVisual)) return FALSE;
2252c582b7e3Smrg    miSetPixmapDepths ();
2253c582b7e3Smrg
2254c582b7e3Smrg#ifdef XF86DRI
2255c582b7e3Smrg				/* Setup DRI after visuals have been
2256c582b7e3Smrg				   established, but before fbScreenInit is
2257c582b7e3Smrg				   called.  fbScreenInit will eventually
2258c582b7e3Smrg				   call the driver's InitGLXVisuals call
2259c582b7e3Smrg				   back. */
2260c582b7e3Smrg    {
2261c582b7e3Smrg	/* FIXME: When we move to dynamic allocation of back and depth
2262c582b7e3Smrg	   buffers, we will want to revisit the following check for 3
2263c582b7e3Smrg	   times the virtual size of the screen below. */
2264c582b7e3Smrg	int width_bytes = (pScrn->displayWidth *
2265c582b7e3Smrg			   info->CurrentLayout.pixel_bytes);
2266c582b7e3Smrg	int maxy        = info->FbMapSize / width_bytes;
2267c582b7e3Smrg
2268c582b7e3Smrg	if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
2269c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_WARNING,
2270c582b7e3Smrg		       "Acceleration disabled, not initializing the DRI\n");
2271c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
2272c582b7e3Smrg	} else if (maxy <= pScrn->virtualY * 3) {
2273c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_WARNING,
2274c582b7e3Smrg		       "Static buffer allocation failed -- "
2275c582b7e3Smrg		       "need at least %d kB video memory\n",
2276c582b7e3Smrg		       (pScrn->displayWidth * pScrn->virtualY *
2277c582b7e3Smrg			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
2278c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
2279c582b7e3Smrg	} else {
2280c582b7e3Smrg            if(info->IsSecondary)
2281c582b7e3Smrg                info->directRenderingEnabled = FALSE;
2282c582b7e3Smrg            else
2283c582b7e3Smrg            {
2284c582b7e3Smrg                /* Xinerama has sync problem with DRI, disable it for now */
2285c582b7e3Smrg                if(xf86IsEntityShared(pScrn->entityList[0]))
2286c582b7e3Smrg                {
2287c582b7e3Smrg                    info->directRenderingEnabled = FALSE;
2288c582b7e3Smrg 	            xf86DrvMsg(scrnIndex, X_WARNING,
2289c582b7e3Smrg                        "Direct Rendering Disabled -- "
2290c582b7e3Smrg                        "Dual-head configuration is not working with DRI "
2291c582b7e3Smrg                        "at present.\nPlease use only one Device/Screen "
2292c582b7e3Smrg                        "section in your XFConfig file.\n");
2293c582b7e3Smrg                }
2294c582b7e3Smrg                else
2295c582b7e3Smrg                info->directRenderingEnabled =
2296c582b7e3Smrg                    R128DRIScreenInit(pScreen);
2297c582b7e3Smrg                if(xf86IsEntityShared(pScrn->entityList[0]))
2298c582b7e3Smrg                {
2299c582b7e3Smrg                    DevUnion* pPriv;
2300c582b7e3Smrg                    R128EntPtr pR128Ent;
2301c582b7e3Smrg                    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
2302c582b7e3Smrg                        getR128EntityIndex());
2303c582b7e3Smrg                    pR128Ent = pPriv->ptr;
2304c582b7e3Smrg                    pR128Ent->IsDRIEnabled = info->directRenderingEnabled;
2305c582b7e3Smrg                }
2306c582b7e3Smrg            }
2307c582b7e3Smrg	}
2308c582b7e3Smrg    }
2309c582b7e3Smrg#endif
2310c582b7e3Smrg
2311c582b7e3Smrg    if (!fbScreenInit (pScreen, info->FB,
2312c582b7e3Smrg		       pScrn->virtualX, pScrn->virtualY,
2313c582b7e3Smrg		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2314c582b7e3Smrg		       pScrn->bitsPerPixel))
2315c582b7e3Smrg	return FALSE;
2316c582b7e3Smrg
2317c582b7e3Smrg    xf86SetBlackWhitePixels(pScreen);
2318c582b7e3Smrg
2319c582b7e3Smrg    if (pScrn->bitsPerPixel > 8) {
2320c582b7e3Smrg	VisualPtr visual;
2321c582b7e3Smrg
2322c582b7e3Smrg	visual = pScreen->visuals + pScreen->numVisuals;
2323c582b7e3Smrg	while (--visual >= pScreen->visuals) {
2324c582b7e3Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
2325c582b7e3Smrg		visual->offsetRed   = pScrn->offset.red;
2326c582b7e3Smrg		visual->offsetGreen = pScrn->offset.green;
2327c582b7e3Smrg		visual->offsetBlue  = pScrn->offset.blue;
2328c582b7e3Smrg		visual->redMask     = pScrn->mask.red;
2329c582b7e3Smrg		visual->greenMask   = pScrn->mask.green;
2330c582b7e3Smrg		visual->blueMask    = pScrn->mask.blue;
2331c582b7e3Smrg	    }
2332c582b7e3Smrg	}
2333c582b7e3Smrg    }
2334c582b7e3Smrg
2335c582b7e3Smrg    /* must be after RGB order fixed */
2336c582b7e3Smrg    fbPictureInit (pScreen, 0, 0);
2337c582b7e3Smrg
2338c582b7e3Smrg				/* Memory manager setup */
2339c582b7e3Smrg#ifdef XF86DRI
2340c582b7e3Smrg    if (info->directRenderingEnabled) {
2341c582b7e3Smrg	FBAreaPtr fbarea;
2342c582b7e3Smrg	int width_bytes = (pScrn->displayWidth *
2343c582b7e3Smrg			   info->CurrentLayout.pixel_bytes);
2344c582b7e3Smrg	int cpp = info->CurrentLayout.pixel_bytes;
2345c582b7e3Smrg	int bufferSize = pScrn->virtualY * width_bytes;
2346c582b7e3Smrg	int l, total;
2347c582b7e3Smrg	int scanlines;
2348c582b7e3Smrg
2349c582b7e3Smrg	switch (info->CCEMode) {
2350c582b7e3Smrg	case R128_DEFAULT_CCE_PIO_MODE:
2351c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
2352c582b7e3Smrg	    break;
2353c582b7e3Smrg	case R128_DEFAULT_CCE_BM_MODE:
2354c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
2355c582b7e3Smrg	    break;
2356c582b7e3Smrg	default:
2357c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
2358c582b7e3Smrg	    break;
2359c582b7e3Smrg	}
2360c582b7e3Smrg
2361c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2362c582b7e3Smrg		   "Using %d MB AGP aperture\n", info->agpSize);
2363c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2364c582b7e3Smrg		   "Using %d MB for the ring buffer\n", info->ringSize);
2365c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2366c582b7e3Smrg		   "Using %d MB for vertex/indirect buffers\n", info->bufSize);
2367c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2368c582b7e3Smrg		   "Using %d MB for AGP textures\n", info->agpTexSize);
2369c582b7e3Smrg
2370c582b7e3Smrg	/* Try for front, back, depth, and two framebuffers worth of
2371c582b7e3Smrg	 * pixmap cache.  Should be enough for a fullscreen background
2372c582b7e3Smrg	 * image plus some leftovers.
2373c582b7e3Smrg	 */
2374c582b7e3Smrg	info->textureSize = info->FbMapSize - 5 * bufferSize;
2375c582b7e3Smrg
2376c582b7e3Smrg	/* If that gives us less than half the available memory, let's
2377c582b7e3Smrg	 * be greedy and grab some more.  Sorry, I care more about 3D
2378c582b7e3Smrg	 * performance than playing nicely, and you'll get around a full
2379c582b7e3Smrg	 * framebuffer's worth of pixmap cache anyway.
2380c582b7e3Smrg	 */
2381c582b7e3Smrg	if (info->textureSize < (int)info->FbMapSize / 2) {
2382c582b7e3Smrg	    info->textureSize = info->FbMapSize - 4 * bufferSize;
2383c582b7e3Smrg	}
2384c582b7e3Smrg
2385c582b7e3Smrg	if (info->textureSize > 0) {
2386c582b7e3Smrg	    l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
2387c582b7e3Smrg	    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
2388c582b7e3Smrg
2389c582b7e3Smrg	    /* Round the texture size up to the nearest whole number of
2390c582b7e3Smrg	     * texture regions.  Again, be greedy about this, don't
2391c582b7e3Smrg	     * round down.
2392c582b7e3Smrg	     */
2393c582b7e3Smrg	    info->log2TexGran = l;
2394c582b7e3Smrg	    info->textureSize = (info->textureSize >> l) << l;
2395c582b7e3Smrg	} else {
2396c582b7e3Smrg	    info->textureSize = 0;
2397c582b7e3Smrg	}
2398c582b7e3Smrg
2399c582b7e3Smrg	/* Set a minimum usable local texture heap size.  This will fit
2400c582b7e3Smrg	 * two 256x256x32bpp textures.
2401c582b7e3Smrg	 */
2402c582b7e3Smrg	if (info->textureSize < 512 * 1024) {
2403c582b7e3Smrg	    info->textureOffset = 0;
2404c582b7e3Smrg	    info->textureSize = 0;
2405c582b7e3Smrg	}
2406c582b7e3Smrg
2407c582b7e3Smrg	total = info->FbMapSize - info->textureSize;
2408c582b7e3Smrg	scanlines = total / width_bytes;
2409c582b7e3Smrg	if (scanlines > 8191) scanlines = 8191;
2410c582b7e3Smrg
2411c582b7e3Smrg	/* Recalculate the texture offset and size to accomodate any
2412c582b7e3Smrg	 * rounding to a whole number of scanlines.
2413c582b7e3Smrg	 */
2414c582b7e3Smrg	info->textureOffset = scanlines * width_bytes;
2415c582b7e3Smrg
2416c582b7e3Smrg	MemBox.x1 = 0;
2417c582b7e3Smrg	MemBox.y1 = 0;
2418c582b7e3Smrg	MemBox.x2 = pScrn->displayWidth;
2419c582b7e3Smrg	MemBox.y2 = scanlines;
2420c582b7e3Smrg
2421c582b7e3Smrg	if (!xf86InitFBManager(pScreen, &MemBox)) {
2422c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
2423c582b7e3Smrg		       "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
2424c582b7e3Smrg		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2425c582b7e3Smrg	    return FALSE;
2426c582b7e3Smrg	} else {
2427c582b7e3Smrg	    int width, height;
2428c582b7e3Smrg
2429c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO,
2430c582b7e3Smrg		       "Memory manager initialized to (%d,%d) (%d,%d)\n",
2431c582b7e3Smrg		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2432c582b7e3Smrg	    if ((fbarea = xf86AllocateOffscreenArea(pScreen,
2433c582b7e3Smrg						    pScrn->displayWidth,
2434c582b7e3Smrg						    2, 0, NULL, NULL, NULL))) {
2435c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_INFO,
2436c582b7e3Smrg			   "Reserved area from (%d,%d) to (%d,%d)\n",
2437c582b7e3Smrg			   fbarea->box.x1, fbarea->box.y1,
2438c582b7e3Smrg			   fbarea->box.x2, fbarea->box.y2);
2439c582b7e3Smrg	    } else {
2440c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
2441c582b7e3Smrg	    }
2442c582b7e3Smrg	    if (xf86QueryLargestOffscreenArea(pScreen, &width,
2443c582b7e3Smrg					      &height, 0, 0, 0)) {
2444c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_INFO,
2445c582b7e3Smrg			   "Largest offscreen area available: %d x %d\n",
2446c582b7e3Smrg			   width, height);
2447c582b7e3Smrg	    }
2448c582b7e3Smrg	}
2449c582b7e3Smrg
2450c582b7e3Smrg				/* Allocate the shared back buffer */
2451c582b7e3Smrg	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
2452c582b7e3Smrg						pScrn->virtualX,
2453c582b7e3Smrg						pScrn->virtualY,
2454c582b7e3Smrg						32, NULL, NULL, NULL))) {
2455c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO,
2456c582b7e3Smrg		       "Reserved back buffer from (%d,%d) to (%d,%d)\n",
2457c582b7e3Smrg		       fbarea->box.x1, fbarea->box.y1,
2458c582b7e3Smrg		       fbarea->box.x2, fbarea->box.y2);
2459c582b7e3Smrg
2460c582b7e3Smrg	    info->backX = fbarea->box.x1;
2461c582b7e3Smrg	    info->backY = fbarea->box.y1;
2462c582b7e3Smrg	    info->backOffset = (fbarea->box.y1 * width_bytes +
2463c582b7e3Smrg				fbarea->box.x1 * cpp);
2464c582b7e3Smrg	    info->backPitch = pScrn->displayWidth;
2465c582b7e3Smrg	} else {
2466c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
2467c582b7e3Smrg	    info->backX = -1;
2468c582b7e3Smrg	    info->backY = -1;
2469c582b7e3Smrg	    info->backOffset = -1;
2470c582b7e3Smrg	    info->backPitch = -1;
2471c582b7e3Smrg	}
2472c582b7e3Smrg
2473c582b7e3Smrg				/* Allocate the shared depth buffer */
2474c582b7e3Smrg	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
2475c582b7e3Smrg						pScrn->virtualX,
2476c582b7e3Smrg						pScrn->virtualY + 1,
2477c582b7e3Smrg						32, NULL, NULL, NULL))) {
2478c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO,
2479c582b7e3Smrg		       "Reserved depth buffer from (%d,%d) to (%d,%d)\n",
2480c582b7e3Smrg		       fbarea->box.x1, fbarea->box.y1,
2481c582b7e3Smrg		       fbarea->box.x2, fbarea->box.y2);
2482c582b7e3Smrg
2483c582b7e3Smrg	    info->depthX = fbarea->box.x1;
2484c582b7e3Smrg	    info->depthY = fbarea->box.y1;
2485c582b7e3Smrg	    info->depthOffset = (fbarea->box.y1 * width_bytes +
2486c582b7e3Smrg				 fbarea->box.x1 * cpp);
2487c582b7e3Smrg	    info->depthPitch = pScrn->displayWidth;
2488c582b7e3Smrg	    info->spanOffset = ((fbarea->box.y2 - 1) * width_bytes +
2489c582b7e3Smrg				fbarea->box.x1 * cpp);
2490c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO,
2491c582b7e3Smrg		       "Reserved depth span from (%d,%d) offset 0x%x\n",
2492c582b7e3Smrg		       fbarea->box.x1, fbarea->box.y2 - 1, info->spanOffset);
2493c582b7e3Smrg	} else {
2494c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
2495c582b7e3Smrg	    info->depthX = -1;
2496c582b7e3Smrg	    info->depthY = -1;
2497c582b7e3Smrg	    info->depthOffset = -1;
2498c582b7e3Smrg	    info->depthPitch = -1;
2499c582b7e3Smrg	    info->spanOffset = -1;
2500c582b7e3Smrg	}
2501c582b7e3Smrg
2502c582b7e3Smrg	xf86DrvMsg(scrnIndex, X_INFO,
2503c582b7e3Smrg		   "Reserved %d kb for textures at offset 0x%x\n",
2504c582b7e3Smrg		   info->textureSize/1024, info->textureOffset);
2505c582b7e3Smrg    }
2506c582b7e3Smrg    else
2507c582b7e3Smrg#endif
2508c582b7e3Smrg    {
2509c582b7e3Smrg	MemBox.x1 = 0;
2510c582b7e3Smrg	MemBox.y1 = 0;
2511c582b7e3Smrg	MemBox.x2 = pScrn->displayWidth;
2512c582b7e3Smrg	y2        = (info->FbMapSize
2513c582b7e3Smrg		     / (pScrn->displayWidth *
2514c582b7e3Smrg			info->CurrentLayout.pixel_bytes));
2515c582b7e3Smrg				/* The acceleration engine uses 14 bit
2516c582b7e3Smrg				   signed coordinates, so we can't have any
2517c582b7e3Smrg				   drawable caches beyond this region. */
2518c582b7e3Smrg	if (y2 > 8191) y2 = 8191;
2519c582b7e3Smrg	MemBox.y2 = y2;
2520c582b7e3Smrg
2521c582b7e3Smrg	if (!xf86InitFBManager(pScreen, &MemBox)) {
2522c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
2523c582b7e3Smrg		       "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
2524c582b7e3Smrg		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2525c582b7e3Smrg	    return FALSE;
2526c582b7e3Smrg	} else {
2527c582b7e3Smrg	    int       width, height;
2528c582b7e3Smrg	    FBAreaPtr fbarea;
2529c582b7e3Smrg
2530c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO,
2531c582b7e3Smrg		       "Memory manager initialized to (%d,%d) (%d,%d)\n",
2532c582b7e3Smrg		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2533c582b7e3Smrg	    if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
2534c582b7e3Smrg						    2, 0, NULL, NULL, NULL))) {
2535c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_INFO,
2536c582b7e3Smrg			   "Reserved area from (%d,%d) to (%d,%d)\n",
2537c582b7e3Smrg			   fbarea->box.x1, fbarea->box.y1,
2538c582b7e3Smrg			   fbarea->box.x2, fbarea->box.y2);
2539c582b7e3Smrg	    } else {
2540c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
2541c582b7e3Smrg	    }
2542c582b7e3Smrg	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2543c582b7e3Smrg					      0, 0, 0)) {
2544c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_INFO,
2545c582b7e3Smrg			   "Largest offscreen area available: %d x %d\n",
2546c582b7e3Smrg			   width, height);
2547c582b7e3Smrg	    }
2548c582b7e3Smrg	}
2549c582b7e3Smrg    }
2550c582b7e3Smrg
2551c582b7e3Smrg				/* Acceleration setup */
2552c582b7e3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
2553c582b7e3Smrg	if (R128AccelInit(pScreen)) {
2554c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
2555c582b7e3Smrg	    info->accelOn = TRUE;
2556c582b7e3Smrg	} else {
2557c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
2558c582b7e3Smrg		       "Acceleration initialization failed\n");
2559c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
2560c582b7e3Smrg	    info->accelOn = FALSE;
2561c582b7e3Smrg	}
2562c582b7e3Smrg    } else {
2563c582b7e3Smrg	xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
2564c582b7e3Smrg	info->accelOn = FALSE;
2565c582b7e3Smrg    }
2566c582b7e3Smrg
2567c582b7e3Smrg				/* DGA setup */
2568c582b7e3Smrg    R128DGAInit(pScreen);
2569c582b7e3Smrg
2570c582b7e3Smrg				/* Backing store setup */
2571c582b7e3Smrg    miInitializeBackingStore(pScreen);
2572c582b7e3Smrg    xf86SetBackingStore(pScreen);
2573c582b7e3Smrg
2574c582b7e3Smrg				/* Set Silken Mouse */
2575c582b7e3Smrg    xf86SetSilkenMouse(pScreen);
2576c582b7e3Smrg
2577c582b7e3Smrg				/* Cursor setup */
2578c582b7e3Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2579c582b7e3Smrg
2580c582b7e3Smrg				/* Hardware cursor setup */
2581c582b7e3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
2582c582b7e3Smrg	if (R128CursorInit(pScreen)) {
2583c582b7e3Smrg	    int width, height;
2584c582b7e3Smrg
2585c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2586c582b7e3Smrg		       "Using hardware cursor (scanline %ld)\n",
2587c582b7e3Smrg		       info->cursor_start / pScrn->displayWidth);
2588c582b7e3Smrg	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2589c582b7e3Smrg					      0, 0, 0)) {
2590c582b7e3Smrg		xf86DrvMsg(scrnIndex, X_INFO,
2591c582b7e3Smrg			   "Largest offscreen area available: %d x %d\n",
2592c582b7e3Smrg			   width, height);
2593c582b7e3Smrg	    }
2594c582b7e3Smrg	} else {
2595c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_ERROR,
2596c582b7e3Smrg		       "Hardware cursor initialization failed\n");
2597c582b7e3Smrg	    xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
2598c582b7e3Smrg	}
2599c582b7e3Smrg    } else {
2600c582b7e3Smrg	info->cursor_start = 0;
2601c582b7e3Smrg	xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
2602c582b7e3Smrg    }
2603c582b7e3Smrg
2604c582b7e3Smrg				/* Colormap setup */
2605c582b7e3Smrg    if (!miCreateDefColormap(pScreen)) return FALSE;
2606c582b7e3Smrg    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
2607c582b7e3Smrg			     (info->FBDev ? fbdevHWLoadPaletteWeak() :
2608c582b7e3Smrg			     R128LoadPalette), NULL,
2609c582b7e3Smrg			     CMAP_PALETTED_TRUECOLOR
2610c582b7e3Smrg			     | CMAP_RELOAD_ON_MODE_SWITCH
2611c582b7e3Smrg#if 0 /* This option messes up text mode! (eich@suse.de) */
2612c582b7e3Smrg			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
2613c582b7e3Smrg#endif
2614c582b7e3Smrg			     )) return FALSE;
2615c582b7e3Smrg
2616c582b7e3Smrg    /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
2617c582b7e3Smrg    if (info->FBDev)
2618c582b7e3Smrg	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
2619c582b7e3Smrg
2620c582b7e3Smrg    else {
2621c582b7e3Smrg	if (info->DisplayType == MT_LCD)
2622c582b7e3Smrg	    xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0);
2623c582b7e3Smrg	else
2624c582b7e3Smrg	    xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0);
2625c582b7e3Smrg    }
2626c582b7e3Smrg
2627c582b7e3Smrg    if (!info->IsSecondary)
2628c582b7e3Smrg	R128InitVideo(pScreen);
2629c582b7e3Smrg
2630c582b7e3Smrg				/* Provide SaveScreen */
2631c582b7e3Smrg    pScreen->SaveScreen  = R128SaveScreen;
2632c582b7e3Smrg
2633c582b7e3Smrg				/* Wrap CloseScreen */
2634c582b7e3Smrg    info->CloseScreen    = pScreen->CloseScreen;
2635c582b7e3Smrg    pScreen->CloseScreen = R128CloseScreen;
2636c582b7e3Smrg
2637c582b7e3Smrg				/* Note unused options */
2638c582b7e3Smrg    if (serverGeneration == 1)
2639c582b7e3Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2640c582b7e3Smrg
2641c582b7e3Smrg#ifdef XF86DRI
2642c582b7e3Smrg				/* DRI finalization */
2643c582b7e3Smrg    if (info->directRenderingEnabled) {
2644c582b7e3Smrg				/* Now that mi, fb, drm and others have
2645c582b7e3Smrg				   done their thing, complete the DRI
2646c582b7e3Smrg				   setup. */
2647c582b7e3Smrg	info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
2648c582b7e3Smrg    }
2649c582b7e3Smrg    if (info->directRenderingEnabled) {
2650c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2651c582b7e3Smrg    } else {
2652c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2653c582b7e3Smrg		   "Direct rendering disabled\n");
2654c582b7e3Smrg    }
2655c582b7e3Smrg#endif
2656c582b7e3Smrg
2657c582b7e3Smrg    info->BlockHandler = pScreen->BlockHandler;
2658c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
2659c582b7e3Smrg
2660c582b7e3Smrg    return TRUE;
2661c582b7e3Smrg}
2662c582b7e3Smrg
2663c582b7e3Smrg/* Write common registers (initialized to 0). */
2664c582b7e3Smrgstatic void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2665c582b7e3Smrg{
2666c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2667c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2668c582b7e3Smrg
2669c582b7e3Smrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
2670c582b7e3Smrg
2671c582b7e3Smrg    OUTREG(R128_OVR_CLR,              restore->ovr_clr);
2672c582b7e3Smrg    OUTREG(R128_OVR_WID_LEFT_RIGHT,   restore->ovr_wid_left_right);
2673c582b7e3Smrg    OUTREG(R128_OVR_WID_TOP_BOTTOM,   restore->ovr_wid_top_bottom);
2674c582b7e3Smrg    OUTREG(R128_OV0_SCALE_CNTL,       restore->ov0_scale_cntl);
2675c582b7e3Smrg    OUTREG(R128_MPP_TB_CONFIG,        restore->mpp_tb_config );
2676c582b7e3Smrg    OUTREG(R128_MPP_GP_CONFIG,        restore->mpp_gp_config );
2677c582b7e3Smrg    OUTREG(R128_SUBPIC_CNTL,          restore->subpic_cntl);
2678c582b7e3Smrg    OUTREG(R128_VIPH_CONTROL,         restore->viph_control);
2679c582b7e3Smrg    OUTREG(R128_I2C_CNTL_1,           restore->i2c_cntl_1);
2680c582b7e3Smrg    OUTREG(R128_GEN_INT_CNTL,         restore->gen_int_cntl);
2681c582b7e3Smrg    OUTREG(R128_CAP0_TRIG_CNTL,       restore->cap0_trig_cntl);
2682c582b7e3Smrg    OUTREG(R128_CAP1_TRIG_CNTL,       restore->cap1_trig_cntl);
2683c582b7e3Smrg    OUTREG(R128_BUS_CNTL,             restore->bus_cntl);
2684c582b7e3Smrg    OUTREG(R128_CONFIG_CNTL,          restore->config_cntl);
2685c582b7e3Smrg}
2686c582b7e3Smrg
2687c582b7e3Smrg/* Write CRTC registers. */
2688c582b7e3Smrgstatic void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2689c582b7e3Smrg{
2690c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2691c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2692c582b7e3Smrg
2693c582b7e3Smrg    OUTREG(R128_CRTC_GEN_CNTL,        restore->crtc_gen_cntl);
2694c582b7e3Smrg
2695c582b7e3Smrg    OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl,
2696c582b7e3Smrg	    R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS);
2697c582b7e3Smrg
2698c582b7e3Smrg    OUTREGP(R128_DAC_CNTL, restore->dac_cntl,
2699c582b7e3Smrg	    R128_DAC_RANGE_CNTL | R128_DAC_BLANKING);
2700c582b7e3Smrg
2701c582b7e3Smrg    OUTREG(R128_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
2702c582b7e3Smrg    OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
2703c582b7e3Smrg    OUTREG(R128_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
2704c582b7e3Smrg    OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
2705c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET,          restore->crtc_offset);
2706c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
2707c582b7e3Smrg    OUTREG(R128_CRTC_PITCH,           restore->crtc_pitch);
2708c582b7e3Smrg}
2709c582b7e3Smrg
2710c582b7e3Smrg/* Write CRTC2 registers. */
2711c582b7e3Smrgstatic void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn,
2712c582b7e3Smrg				       R128SavePtr restore)
2713c582b7e3Smrg{
2714c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2715c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2716c582b7e3Smrg
2717c582b7e3Smrg    OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl,
2718c582b7e3Smrg	    R128_CRTC2_DISP_DIS);
2719c582b7e3Smrg
2720c582b7e3Smrg    OUTREG(R128_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
2721c582b7e3Smrg    OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
2722c582b7e3Smrg    OUTREG(R128_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
2723c582b7e3Smrg    OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
2724c582b7e3Smrg    OUTREG(R128_CRTC2_OFFSET,          restore->crtc2_offset);
2725c582b7e3Smrg    OUTREG(R128_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
2726c582b7e3Smrg    OUTREG(R128_CRTC2_PITCH,           restore->crtc2_pitch);
2727c582b7e3Smrg}
2728c582b7e3Smrg
2729c582b7e3Smrg/* Write flat panel registers */
2730c582b7e3Smrgstatic void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2731c582b7e3Smrg{
2732c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2733c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2734c582b7e3Smrg    CARD32        tmp;
2735c582b7e3Smrg
2736c582b7e3Smrg    if (info->BIOSDisplay != R128_DUALHEAD)
2737c582b7e3Smrg        OUTREG(R128_CRTC2_GEN_CNTL,       restore->crtc2_gen_cntl);
2738c582b7e3Smrg    OUTREG(R128_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
2739c582b7e3Smrg    OUTREG(R128_FP_VERT_STRETCH,      restore->fp_vert_stretch);
2740c582b7e3Smrg    OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
2741c582b7e3Smrg    OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
2742c582b7e3Smrg    OUTREG(R128_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
2743c582b7e3Smrg    OUTREG(R128_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
2744c582b7e3Smrg    OUTREG(R128_TMDS_CRC,             restore->tmds_crc);
2745c582b7e3Smrg    OUTREG(R128_FP_PANEL_CNTL,        restore->fp_panel_cntl);
2746c582b7e3Smrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(CARD32)R128_FP_BLANK_DIS);
2747c582b7e3Smrg
2748c582b7e3Smrg    if(info->isDFP) return;
2749c582b7e3Smrg
2750c582b7e3Smrg    tmp = INREG(R128_LVDS_GEN_CNTL);
2751c582b7e3Smrg    if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
2752c582b7e3Smrg	(restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
2753c582b7e3Smrg	OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2754c582b7e3Smrg    } else {
2755c582b7e3Smrg	if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
2756c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL,
2757c582b7e3Smrg		   restore->lvds_gen_cntl & (CARD32)~R128_LVDS_BLON);
2758c582b7e3Smrg	    usleep(R128PTR(pScrn)->PanelPwrDly * 1000);
2759c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2760c582b7e3Smrg	} else {
2761c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
2762c582b7e3Smrg	    usleep(R128PTR(pScrn)->PanelPwrDly * 1000);
2763c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2764c582b7e3Smrg	}
2765c582b7e3Smrg    }
2766c582b7e3Smrg}
2767c582b7e3Smrg
2768c582b7e3Smrgstatic void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2769c582b7e3Smrg{
2770c582b7e3Smrg    while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
2771c582b7e3Smrg}
2772c582b7e3Smrg
2773c582b7e3Smrgstatic void R128PLLWriteUpdate(ScrnInfoPtr pScrn)
2774c582b7e3Smrg{
2775c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2776c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2777c582b7e3Smrg
2778c582b7e3Smrg    while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
2779c582b7e3Smrg
2780c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W,
2781c582b7e3Smrg	    ~R128_PPLL_ATOMIC_UPDATE_W);
2782c582b7e3Smrg
2783c582b7e3Smrg}
2784c582b7e3Smrg
2785c582b7e3Smrgstatic void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2786c582b7e3Smrg{
2787c582b7e3Smrg    while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
2788c582b7e3Smrg}
2789c582b7e3Smrg
2790c582b7e3Smrgstatic void R128PLL2WriteUpdate(ScrnInfoPtr pScrn)
2791c582b7e3Smrg{
2792c582b7e3Smrg    R128InfoPtr  info       = R128PTR(pScrn);
2793c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2794c582b7e3Smrg
2795c582b7e3Smrg    while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
2796c582b7e3Smrg
2797c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_REF_DIV,
2798c582b7e3Smrg	    R128_P2PLL_ATOMIC_UPDATE_W,
2799c582b7e3Smrg	    ~(R128_P2PLL_ATOMIC_UPDATE_W));
2800c582b7e3Smrg}
2801c582b7e3Smrg
2802c582b7e3Smrg/* Write PLL registers. */
2803c582b7e3Smrgstatic void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2804c582b7e3Smrg{
2805c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2806c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2807c582b7e3Smrg
2808c582b7e3Smrg
2809c582b7e3Smrg    OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
2810c582b7e3Smrg	    R128_VCLK_SRC_SEL_CPUCLK,
2811c582b7e3Smrg	    ~(R128_VCLK_SRC_SEL_MASK));
2812c582b7e3Smrg
2813c582b7e3Smrg    OUTPLLP(pScrn,
2814c582b7e3Smrg	    R128_PPLL_CNTL,
2815c582b7e3Smrg	    R128_PPLL_RESET
2816c582b7e3Smrg	    | R128_PPLL_ATOMIC_UPDATE_EN
2817c582b7e3Smrg	    | R128_PPLL_VGA_ATOMIC_UPDATE_EN,
2818c582b7e3Smrg	    ~(R128_PPLL_RESET
2819c582b7e3Smrg	      | R128_PPLL_ATOMIC_UPDATE_EN
2820c582b7e3Smrg	      | R128_PPLL_VGA_ATOMIC_UPDATE_EN));
2821c582b7e3Smrg
2822c582b7e3Smrg    OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL));
2823c582b7e3Smrg
2824c582b7e3Smrg/*        R128PLLWaitForReadUpdateComplete(pScrn);*/
2825c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_REF_DIV,
2826c582b7e3Smrg	    restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK);
2827c582b7e3Smrg/*        R128PLLWriteUpdate(pScrn);
2828c582b7e3Smrg
2829c582b7e3Smrg        R128PLLWaitForReadUpdateComplete(pScrn);*/
2830c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_DIV_3,
2831c582b7e3Smrg	    restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK);
2832c582b7e3Smrg/*    R128PLLWriteUpdate(pScrn);*/
2833c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_DIV_3,
2834c582b7e3Smrg	    restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK);
2835c582b7e3Smrg
2836c582b7e3Smrg    R128PLLWriteUpdate(pScrn);
2837c582b7e3Smrg    R128PLLWaitForReadUpdateComplete(pScrn);
2838c582b7e3Smrg
2839c582b7e3Smrg    OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl);
2840c582b7e3Smrg/*    R128PLLWriteUpdate(pScrn);*/
2841c582b7e3Smrg
2842c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET
2843c582b7e3Smrg					| R128_PPLL_SLEEP
2844c582b7e3Smrg					| R128_PPLL_ATOMIC_UPDATE_EN
2845c582b7e3Smrg					| R128_PPLL_VGA_ATOMIC_UPDATE_EN));
2846c582b7e3Smrg
2847c582b7e3Smrg    R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
2848c582b7e3Smrg	       restore->ppll_ref_div,
2849c582b7e3Smrg	       restore->ppll_div_3,
2850c582b7e3Smrg	       restore->htotal_cntl,
2851c582b7e3Smrg	       INPLL(pScrn, R128_PPLL_CNTL)));
2852c582b7e3Smrg    R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
2853c582b7e3Smrg	       restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
2854c582b7e3Smrg	       restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
2855c582b7e3Smrg	       (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
2856c582b7e3Smrg
2857c582b7e3Smrg    usleep(5000); /* let the clock lock */
2858c582b7e3Smrg
2859c582b7e3Smrg    OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
2860c582b7e3Smrg	    R128_VCLK_SRC_SEL_PPLLCLK,
2861c582b7e3Smrg	    ~(R128_VCLK_SRC_SEL_MASK));
2862c582b7e3Smrg
2863c582b7e3Smrg}
2864c582b7e3Smrg
2865c582b7e3Smrg/* Write PLL2 registers. */
2866c582b7e3Smrgstatic void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2867c582b7e3Smrg{
2868c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2869c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2870c582b7e3Smrg
2871c582b7e3Smrg    OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
2872c582b7e3Smrg	    R128_V2CLK_SRC_SEL_CPUCLK,
2873c582b7e3Smrg	    ~R128_V2CLK_SRC_SEL_MASK);
2874c582b7e3Smrg
2875c582b7e3Smrg    OUTPLLP(pScrn,
2876c582b7e3Smrg	    R128_P2PLL_CNTL,
2877c582b7e3Smrg	    R128_P2PLL_RESET
2878c582b7e3Smrg	    | R128_P2PLL_ATOMIC_UPDATE_EN
2879c582b7e3Smrg	    | R128_P2PLL_VGA_ATOMIC_UPDATE_EN,
2880c582b7e3Smrg	    ~(R128_P2PLL_RESET
2881c582b7e3Smrg	      | R128_P2PLL_ATOMIC_UPDATE_EN
2882c582b7e3Smrg	      | R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
2883c582b7e3Smrg
2884c582b7e3Smrg#if 1
2885c582b7e3Smrg    OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK);
2886c582b7e3Smrg#endif
2887c582b7e3Smrg
2888c582b7e3Smrg        /*R128PLL2WaitForReadUpdateComplete(pScrn);*/
2889c582b7e3Smrg
2890c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK);
2891c582b7e3Smrg
2892c582b7e3Smrg/*        R128PLL2WriteUpdate(pScrn);
2893c582b7e3Smrg    R128PLL2WaitForReadUpdateComplete(pScrn);*/
2894c582b7e3Smrg
2895c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_DIV_0,
2896c582b7e3Smrg			restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK);
2897c582b7e3Smrg
2898c582b7e3Smrg/*    R128PLL2WriteUpdate(pScrn);
2899c582b7e3Smrg    R128PLL2WaitForReadUpdateComplete(pScrn);*/
2900c582b7e3Smrg
2901c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_DIV_0,
2902c582b7e3Smrg			restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK);
2903c582b7e3Smrg
2904c582b7e3Smrg    R128PLL2WriteUpdate(pScrn);
2905c582b7e3Smrg    R128PLL2WaitForReadUpdateComplete(pScrn);
2906c582b7e3Smrg
2907c582b7e3Smrg    OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2);
2908c582b7e3Smrg
2909c582b7e3Smrg/*        R128PLL2WriteUpdate(pScrn);*/
2910c582b7e3Smrg
2911c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET
2912c582b7e3Smrg					| R128_P2PLL_SLEEP
2913c582b7e3Smrg					| R128_P2PLL_ATOMIC_UPDATE_EN
2914c582b7e3Smrg					| R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
2915c582b7e3Smrg
2916c582b7e3Smrg    R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
2917c582b7e3Smrg	       restore->p2pll_ref_div,
2918c582b7e3Smrg	       restore->p2pll_div_0,
2919c582b7e3Smrg	       restore->htotal_cntl2,
2920c582b7e3Smrg	       INPLL(pScrn, RADEON_P2PLL_CNTL)));
2921c582b7e3Smrg    R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
2922c582b7e3Smrg	       restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK,
2923c582b7e3Smrg	       restore->p2pll_div_0 & RADEON_P2PLL_FB3_DIV_MASK,
2924c582b7e3Smrg	       (restore->p2pll_div_0 & RADEON_P2PLL_POST3_DIV_MASK) >>16));
2925c582b7e3Smrg
2926c582b7e3Smrg    usleep(5000); /* Let the clock to lock */
2927c582b7e3Smrg
2928c582b7e3Smrg    OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
2929c582b7e3Smrg	    R128_V2CLK_SRC_SEL_P2PLLCLK,
2930c582b7e3Smrg	    ~R128_V2CLK_SRC_SEL_MASK);
2931c582b7e3Smrg
2932c582b7e3Smrg}
2933c582b7e3Smrg
2934c582b7e3Smrg/* Write DDA registers. */
2935c582b7e3Smrgstatic void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2936c582b7e3Smrg{
2937c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2938c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2939c582b7e3Smrg
2940c582b7e3Smrg    OUTREG(R128_DDA_CONFIG, restore->dda_config);
2941c582b7e3Smrg    OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
2942c582b7e3Smrg}
2943c582b7e3Smrg
2944c582b7e3Smrg/* Write DDA registers. */
2945c582b7e3Smrgstatic void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2946c582b7e3Smrg{
2947c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2948c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2949c582b7e3Smrg
2950c582b7e3Smrg    OUTREG(R128_DDA2_CONFIG, restore->dda2_config);
2951c582b7e3Smrg    OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off);
2952c582b7e3Smrg}
2953c582b7e3Smrg
2954c582b7e3Smrg/* Write palette data. */
2955c582b7e3Smrgstatic void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore)
2956c582b7e3Smrg{
2957c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2958c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2959c582b7e3Smrg    int           i;
2960c582b7e3Smrg
2961c582b7e3Smrg    if (!restore->palette_valid) return;
2962c582b7e3Smrg
2963c582b7e3Smrg    PAL_SELECT(1);
2964c582b7e3Smrg    OUTPAL_START(0);
2965c582b7e3Smrg    for (i = 0; i < 256; i++) {
2966c582b7e3Smrg	R128WaitForFifo(pScrn, 32); /* delay */
2967c582b7e3Smrg	OUTPAL_NEXT_CARD32(restore->palette2[i]);
2968c582b7e3Smrg    }
2969c582b7e3Smrg
2970c582b7e3Smrg    PAL_SELECT(0);
2971c582b7e3Smrg    OUTPAL_START(0);
2972c582b7e3Smrg    for (i = 0; i < 256; i++) {
2973c582b7e3Smrg	R128WaitForFifo(pScrn, 32); /* delay */
2974c582b7e3Smrg	OUTPAL_NEXT_CARD32(restore->palette[i]);
2975c582b7e3Smrg    }
2976c582b7e3Smrg
2977c582b7e3Smrg}
2978c582b7e3Smrg
2979c582b7e3Smrg/* Write out state to define a new video mode.  */
2980c582b7e3Smrgstatic void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore)
2981c582b7e3Smrg{
2982c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
2983c582b7e3Smrg    DevUnion* pPriv;
2984c582b7e3Smrg    R128EntPtr pR128Ent;
2985c582b7e3Smrg    static R128SaveRec restore0;
2986c582b7e3Smrg
2987c582b7e3Smrg    R128TRACE(("R128RestoreMode(%p)\n", restore));
2988c582b7e3Smrg    if(!info->HasCRTC2)
2989c582b7e3Smrg    {
2990c582b7e3Smrg    	R128RestoreCommonRegisters(pScrn, restore);
2991c582b7e3Smrg        R128RestoreDDARegisters(pScrn, restore);
2992c582b7e3Smrg    	R128RestoreCrtcRegisters(pScrn, restore);
2993c582b7e3Smrg        if((info->DisplayType == MT_DFP) ||
2994c582b7e3Smrg           (info->DisplayType == MT_LCD))
2995c582b7e3Smrg        {
2996c582b7e3Smrg	    R128RestoreFPRegisters(pScrn, restore);
2997c582b7e3Smrg        }
2998c582b7e3Smrg        R128RestorePLLRegisters(pScrn, restore);
2999c582b7e3Smrg        return;
3000c582b7e3Smrg    }
3001c582b7e3Smrg
3002c582b7e3Smrg    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
3003c582b7e3Smrg                   getR128EntityIndex());
3004c582b7e3Smrg    pR128Ent = pPriv->ptr;
3005c582b7e3Smrg
3006c582b7e3Smrg
3007c582b7e3Smrg    /*****
3008c582b7e3Smrg      When changing mode with Dual-head card (VE/M6), care must
3009c582b7e3Smrg      be taken for the special order in setting registers. CRTC2 has
3010c582b7e3Smrg      to be set before changing CRTC_EXT register.
3011c582b7e3Smrg      In the dual-head setup, X server calls this routine twice with
3012c582b7e3Smrg      primary and secondary pScrn pointers respectively. The calls
3013c582b7e3Smrg      can come with different order. Regardless the order of X server issuing
3014c582b7e3Smrg      the calls, we have to ensure we set registers in the right order!!!
3015c582b7e3Smrg      Otherwise we may get a blank screen.
3016c582b7e3Smrg    *****/
3017c582b7e3Smrg
3018c582b7e3Smrg    if(info->IsSecondary)
3019c582b7e3Smrg    {
3020c582b7e3Smrg	if (!pR128Ent->RestorePrimary  && !info->SwitchingMode)
3021c582b7e3Smrg	    R128RestoreCommonRegisters(pScrn, restore);
3022c582b7e3Smrg        R128RestoreDDA2Registers(pScrn, restore);
3023c582b7e3Smrg        R128RestoreCrtc2Registers(pScrn, restore);
3024c582b7e3Smrg        R128RestorePLL2Registers(pScrn, restore);
3025c582b7e3Smrg
3026c582b7e3Smrg	if(info->SwitchingMode) return;
3027c582b7e3Smrg
3028c582b7e3Smrg        pR128Ent->IsSecondaryRestored = TRUE;
3029c582b7e3Smrg
3030c582b7e3Smrg        if(pR128Ent->RestorePrimary)
3031c582b7e3Smrg        {
3032c582b7e3Smrg            R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn);
3033c582b7e3Smrg            pR128Ent->RestorePrimary = FALSE;
3034c582b7e3Smrg
3035c582b7e3Smrg            R128RestoreCrtcRegisters(pScrn, &restore0);
3036c582b7e3Smrg            if((info0->DisplayType == MT_DFP) ||
3037c582b7e3Smrg               (info0->DisplayType == MT_LCD))
3038c582b7e3Smrg            {
3039c582b7e3Smrg                R128RestoreFPRegisters(pScrn, &restore0);
3040c582b7e3Smrg            }
3041c582b7e3Smrg
3042c582b7e3Smrg            R128RestorePLLRegisters(pScrn, &restore0);
3043c582b7e3Smrg            pR128Ent->IsSecondaryRestored = FALSE;
3044c582b7e3Smrg
3045c582b7e3Smrg        }
3046c582b7e3Smrg    }
3047c582b7e3Smrg    else
3048c582b7e3Smrg    {
3049c582b7e3Smrg	if (!pR128Ent->IsSecondaryRestored)
3050c582b7e3Smrg            R128RestoreCommonRegisters(pScrn, restore);
3051c582b7e3Smrg        R128RestoreDDARegisters(pScrn, restore);
3052c582b7e3Smrg        if(!pR128Ent->HasSecondary || pR128Ent->IsSecondaryRestored
3053c582b7e3Smrg            || info->SwitchingMode)
3054c582b7e3Smrg        {
3055c582b7e3Smrg	    pR128Ent->IsSecondaryRestored = FALSE;
3056c582b7e3Smrg            R128RestoreCrtcRegisters(pScrn, restore);
3057c582b7e3Smrg            if((info->DisplayType == MT_DFP) ||
3058c582b7e3Smrg               (info->DisplayType == MT_LCD))
3059c582b7e3Smrg            {
3060c582b7e3Smrg               R128RestoreFPRegisters(pScrn, restore);
3061c582b7e3Smrg            }
3062c582b7e3Smrg            R128RestorePLLRegisters(pScrn, restore);
3063c582b7e3Smrg        }
3064c582b7e3Smrg        else
3065c582b7e3Smrg        {
3066c582b7e3Smrg            memcpy(&restore0, restore, sizeof(restore0));
3067c582b7e3Smrg            pR128Ent->RestorePrimary = TRUE;
3068c582b7e3Smrg        }
3069c582b7e3Smrg    }
3070c582b7e3Smrg
3071c582b7e3Smrg    R128RestorePalette(pScrn, restore);
3072c582b7e3Smrg}
3073c582b7e3Smrg
3074c582b7e3Smrg/* Read common registers. */
3075c582b7e3Smrgstatic void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3076c582b7e3Smrg{
3077c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3078c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3079c582b7e3Smrg
3080c582b7e3Smrg    save->ovr_clr            = INREG(R128_OVR_CLR);
3081c582b7e3Smrg    save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
3082c582b7e3Smrg    save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
3083c582b7e3Smrg    save->ov0_scale_cntl     = INREG(R128_OV0_SCALE_CNTL);
3084c582b7e3Smrg    save->mpp_tb_config      = INREG(R128_MPP_TB_CONFIG);
3085c582b7e3Smrg    save->mpp_gp_config      = INREG(R128_MPP_GP_CONFIG);
3086c582b7e3Smrg    save->subpic_cntl        = INREG(R128_SUBPIC_CNTL);
3087c582b7e3Smrg    save->viph_control       = INREG(R128_VIPH_CONTROL);
3088c582b7e3Smrg    save->i2c_cntl_1         = INREG(R128_I2C_CNTL_1);
3089c582b7e3Smrg    save->gen_int_cntl       = INREG(R128_GEN_INT_CNTL);
3090c582b7e3Smrg    save->cap0_trig_cntl     = INREG(R128_CAP0_TRIG_CNTL);
3091c582b7e3Smrg    save->cap1_trig_cntl     = INREG(R128_CAP1_TRIG_CNTL);
3092c582b7e3Smrg    save->bus_cntl           = INREG(R128_BUS_CNTL);
3093c582b7e3Smrg    save->config_cntl        = INREG(R128_CONFIG_CNTL);
3094c582b7e3Smrg}
3095c582b7e3Smrg
3096c582b7e3Smrg/* Read CRTC registers. */
3097c582b7e3Smrgstatic void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3098c582b7e3Smrg{
3099c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3100c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3101c582b7e3Smrg
3102c582b7e3Smrg    save->crtc_gen_cntl        = INREG(R128_CRTC_GEN_CNTL);
3103c582b7e3Smrg    save->crtc_ext_cntl        = INREG(R128_CRTC_EXT_CNTL);
3104c582b7e3Smrg    save->dac_cntl             = INREG(R128_DAC_CNTL);
3105c582b7e3Smrg    save->crtc_h_total_disp    = INREG(R128_CRTC_H_TOTAL_DISP);
3106c582b7e3Smrg    save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
3107c582b7e3Smrg    save->crtc_v_total_disp    = INREG(R128_CRTC_V_TOTAL_DISP);
3108c582b7e3Smrg    save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
3109c582b7e3Smrg    save->crtc_offset          = INREG(R128_CRTC_OFFSET);
3110c582b7e3Smrg    save->crtc_offset_cntl     = INREG(R128_CRTC_OFFSET_CNTL);
3111c582b7e3Smrg    save->crtc_pitch           = INREG(R128_CRTC_PITCH);
3112c582b7e3Smrg}
3113c582b7e3Smrg
3114c582b7e3Smrg/* Read flat panel registers */
3115c582b7e3Smrgstatic void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3116c582b7e3Smrg{
3117c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3118c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3119c582b7e3Smrg
3120c582b7e3Smrg    if (info->BIOSDisplay != R128_DUALHEAD)
3121c582b7e3Smrg        save->crtc2_gen_cntl       = INREG(R128_CRTC2_GEN_CNTL);
3122c582b7e3Smrg    save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
3123c582b7e3Smrg    save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
3124c582b7e3Smrg    save->fp_gen_cntl          = INREG(R128_FP_GEN_CNTL);
3125c582b7e3Smrg    save->fp_h_sync_strt_wid   = INREG(R128_FP_H_SYNC_STRT_WID);
3126c582b7e3Smrg    save->fp_horz_stretch      = INREG(R128_FP_HORZ_STRETCH);
3127c582b7e3Smrg    save->fp_panel_cntl        = INREG(R128_FP_PANEL_CNTL);
3128c582b7e3Smrg    save->fp_v_sync_strt_wid   = INREG(R128_FP_V_SYNC_STRT_WID);
3129c582b7e3Smrg    save->fp_vert_stretch      = INREG(R128_FP_VERT_STRETCH);
3130c582b7e3Smrg    save->lvds_gen_cntl        = INREG(R128_LVDS_GEN_CNTL);
3131c582b7e3Smrg    save->tmds_crc             = INREG(R128_TMDS_CRC);
3132c582b7e3Smrg    save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
3133c582b7e3Smrg}
3134c582b7e3Smrg
3135c582b7e3Smrg/* Read CRTC2 registers. */
3136c582b7e3Smrgstatic void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
3137c582b7e3Smrg{
3138c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
3139c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3140c582b7e3Smrg
3141c582b7e3Smrg    save->crtc2_gen_cntl        = INREG(R128_CRTC2_GEN_CNTL);
3142c582b7e3Smrg    save->crtc2_h_total_disp    = INREG(R128_CRTC2_H_TOTAL_DISP);
3143c582b7e3Smrg    save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID);
3144c582b7e3Smrg    save->crtc2_v_total_disp    = INREG(R128_CRTC2_V_TOTAL_DISP);
3145c582b7e3Smrg    save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID);
3146c582b7e3Smrg    save->crtc2_offset          = INREG(R128_CRTC2_OFFSET);
3147c582b7e3Smrg    save->crtc2_offset_cntl     = INREG(R128_CRTC2_OFFSET_CNTL);
3148c582b7e3Smrg    save->crtc2_pitch           = INREG(R128_CRTC2_PITCH);
3149c582b7e3Smrg}
3150c582b7e3Smrg
3151c582b7e3Smrg/* Read PLL registers. */
3152c582b7e3Smrgstatic void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3153c582b7e3Smrg{
3154c582b7e3Smrg    save->ppll_ref_div         = INPLL(pScrn, R128_PPLL_REF_DIV);
3155c582b7e3Smrg    save->ppll_div_3           = INPLL(pScrn, R128_PPLL_DIV_3);
3156c582b7e3Smrg    save->htotal_cntl          = INPLL(pScrn, R128_HTOTAL_CNTL);
3157c582b7e3Smrg
3158c582b7e3Smrg    R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
3159c582b7e3Smrg	       save->ppll_ref_div,
3160c582b7e3Smrg	       save->ppll_div_3,
3161c582b7e3Smrg	       save->htotal_cntl));
3162c582b7e3Smrg    R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
3163c582b7e3Smrg	       save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
3164c582b7e3Smrg	       save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
3165c582b7e3Smrg	       (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
3166c582b7e3Smrg}
3167c582b7e3Smrg
3168c582b7e3Smrg/* Read PLL2 registers. */
3169c582b7e3Smrgstatic void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
3170c582b7e3Smrg{
3171c582b7e3Smrg    save->p2pll_ref_div        = INPLL(pScrn, R128_P2PLL_REF_DIV);
3172c582b7e3Smrg    save->p2pll_div_0          = INPLL(pScrn, R128_P2PLL_DIV_0);
3173c582b7e3Smrg    save->htotal_cntl2         = INPLL(pScrn, R128_HTOTAL2_CNTL);
3174c582b7e3Smrg
3175c582b7e3Smrg    R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
3176c582b7e3Smrg	       save->p2pll_ref_div,
3177c582b7e3Smrg	       save->p2pll_div_0,
3178c582b7e3Smrg	       save->htotal_cntl2));
3179c582b7e3Smrg    R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
3180c582b7e3Smrg	       save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
3181c582b7e3Smrg	       save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
3182c582b7e3Smrg	       (save->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >> 16));
3183c582b7e3Smrg}
3184c582b7e3Smrg
3185c582b7e3Smrg/* Read DDA registers. */
3186c582b7e3Smrgstatic void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3187c582b7e3Smrg{
3188c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3189c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3190c582b7e3Smrg
3191c582b7e3Smrg    save->dda_config           = INREG(R128_DDA_CONFIG);
3192c582b7e3Smrg    save->dda_on_off           = INREG(R128_DDA_ON_OFF);
3193c582b7e3Smrg}
3194c582b7e3Smrg
3195c582b7e3Smrg/* Read DDA2 registers. */
3196c582b7e3Smrgstatic void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
3197c582b7e3Smrg{
3198c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3199c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3200c582b7e3Smrg
3201c582b7e3Smrg    save->dda2_config           = INREG(R128_DDA2_CONFIG);
3202c582b7e3Smrg    save->dda2_on_off           = INREG(R128_DDA2_ON_OFF);
3203c582b7e3Smrg}
3204c582b7e3Smrg
3205c582b7e3Smrg/* Read palette data. */
3206c582b7e3Smrgstatic void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
3207c582b7e3Smrg{
3208c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3209c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3210c582b7e3Smrg    int           i;
3211c582b7e3Smrg
3212c582b7e3Smrg    PAL_SELECT(1);
3213c582b7e3Smrg    INPAL_START(0);
3214c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
3215c582b7e3Smrg    PAL_SELECT(0);
3216c582b7e3Smrg    INPAL_START(0);
3217c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
3218c582b7e3Smrg    save->palette_valid = TRUE;
3219c582b7e3Smrg}
3220c582b7e3Smrg
3221c582b7e3Smrg/* Save state that defines current video mode. */
3222c582b7e3Smrgstatic void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
3223c582b7e3Smrg{
3224c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3225c582b7e3Smrg
3226c582b7e3Smrg    R128TRACE(("R128SaveMode(%p)\n", save));
3227c582b7e3Smrg
3228c582b7e3Smrg    if(info->IsSecondary)
3229c582b7e3Smrg    {
3230c582b7e3Smrg        R128SaveCrtc2Registers(pScrn, save);
3231c582b7e3Smrg        R128SavePLL2Registers(pScrn, save);
3232c582b7e3Smrg        R128SaveDDA2Registers(pScrn, save);
3233c582b7e3Smrg    }
3234c582b7e3Smrg    else
3235c582b7e3Smrg    {
3236c582b7e3Smrg        R128SaveCommonRegisters(pScrn, save);
3237c582b7e3Smrg        R128SaveCrtcRegisters(pScrn, save);
3238c582b7e3Smrg        if((info->DisplayType == MT_DFP) ||
3239c582b7e3Smrg           (info->DisplayType == MT_LCD))
3240c582b7e3Smrg        {
3241c582b7e3Smrg 	    R128SaveFPRegisters(pScrn, save);
3242c582b7e3Smrg        }
3243c582b7e3Smrg        R128SavePLLRegisters(pScrn, save);
3244c582b7e3Smrg        R128SaveDDARegisters(pScrn, save);
3245c582b7e3Smrg        R128SavePalette(pScrn, save);
3246c582b7e3Smrg    }
3247c582b7e3Smrg
3248c582b7e3Smrg    R128TRACE(("R128SaveMode returns %p\n", save));
3249c582b7e3Smrg}
3250c582b7e3Smrg
3251c582b7e3Smrg/* Save everything needed to restore the original VC state. */
3252c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn)
3253c582b7e3Smrg{
3254c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3255c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3256c582b7e3Smrg    R128SavePtr   save      = &info->SavedReg;
3257c582b7e3Smrg
3258c582b7e3Smrg    R128TRACE(("R128Save\n"));
3259c582b7e3Smrg    if (info->FBDev) {
3260c582b7e3Smrg	fbdevHWSave(pScrn);
3261c582b7e3Smrg	return;
3262c582b7e3Smrg    }
3263c582b7e3Smrg
3264c582b7e3Smrg    if (!info->IsSecondary) {
3265c582b7e3Smrg#ifdef WITH_VGAHW
3266c582b7e3Smrg        if (info->VGAAccess) {
3267c582b7e3Smrg            vgaHWPtr hwp = VGAHWPTR(pScrn);
3268c582b7e3Smrg
3269c582b7e3Smrg            vgaHWUnlock(hwp);
3270c582b7e3Smrg# if defined(__powerpc__)
3271c582b7e3Smrg            /* temporary hack to prevent crashing on PowerMacs when trying to
3272c582b7e3Smrg             * read VGA fonts and colormap, will find a better solution
3273c582b7e3Smrg             * in the future. TODO: Check if there's actually some VGA stuff
3274c582b7e3Smrg             * setup in the card at all !!
3275c582b7e3Smrg             */
3276c582b7e3Smrg            vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
3277c582b7e3Smrg# else
3278c582b7e3Smrg            /* Save mode * & fonts & cmap */
3279c582b7e3Smrg            vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
3280c582b7e3Smrg# endif
3281c582b7e3Smrg            vgaHWLock(hwp);
3282c582b7e3Smrg        }
3283c582b7e3Smrg#endif
3284c582b7e3Smrg
3285c582b7e3Smrg        save->dp_datatype      = INREG(R128_DP_DATATYPE);
3286c582b7e3Smrg        save->gen_reset_cntl   = INREG(R128_GEN_RESET_CNTL);
3287c582b7e3Smrg        save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
3288c582b7e3Smrg        save->amcgpio_en_reg   = INREG(R128_AMCGPIO_EN_REG);
3289c582b7e3Smrg        save->amcgpio_mask     = INREG(R128_AMCGPIO_MASK);
3290c582b7e3Smrg    }
3291c582b7e3Smrg
3292c582b7e3Smrg    R128SaveMode(pScrn, save);
3293c582b7e3Smrg
3294c582b7e3Smrg}
3295c582b7e3Smrg
3296c582b7e3Smrg/* Restore the original (text) mode. */
3297c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn)
3298c582b7e3Smrg{
3299c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3300c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3301c582b7e3Smrg    R128SavePtr   restore   = &info->SavedReg;
3302c582b7e3Smrg
3303c582b7e3Smrg    R128TRACE(("R128Restore\n"));
3304c582b7e3Smrg    if (info->FBDev) {
3305c582b7e3Smrg	fbdevHWRestore(pScrn);
3306c582b7e3Smrg	return;
3307c582b7e3Smrg    }
3308c582b7e3Smrg
3309c582b7e3Smrg    R128Blank(pScrn);
3310c582b7e3Smrg
3311c582b7e3Smrg    if (!info->IsSecondary) {
3312c582b7e3Smrg        OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
3313c582b7e3Smrg        OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
3314c582b7e3Smrg        OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
3315c582b7e3Smrg        OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
3316c582b7e3Smrg        OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
3317c582b7e3Smrg    }
3318c582b7e3Smrg
3319c582b7e3Smrg    R128RestoreMode(pScrn, restore);
3320c582b7e3Smrg#ifdef WITH_VGAHW
3321c582b7e3Smrg    if (info->VGAAccess) {
3322c582b7e3Smrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
3323c582b7e3Smrg        if (!info->IsSecondary) {
3324c582b7e3Smrg            vgaHWUnlock(hwp);
3325c582b7e3Smrg# if defined(__powerpc__)
3326c582b7e3Smrg            /* Temporary hack to prevent crashing on PowerMacs when trying to
3327c582b7e3Smrg             * write VGA fonts, will find a better solution in the future
3328c582b7e3Smrg             */
3329c582b7e3Smrg            vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
3330c582b7e3Smrg# else
3331c582b7e3Smrg            vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
3332c582b7e3Smrg# endif
3333c582b7e3Smrg            vgaHWLock(hwp);
3334c582b7e3Smrg        } else {
3335c582b7e3Smrg            R128EntPtr  pR128Ent = R128EntPriv(pScrn);
3336c582b7e3Smrg            ScrnInfoPtr   pScrn0 = pR128Ent->pPrimaryScrn;
3337c582b7e3Smrg            R128InfoPtr info0 = R128PTR(pScrn0);
3338c582b7e3Smrg            vgaHWPtr      hwp0;
3339c582b7e3Smrg
3340c582b7e3Smrg            if (info0->VGAAccess) {
3341c582b7e3Smrg                hwp0 = VGAHWPTR(pScrn0);
3342c582b7e3Smrg                vgaHWUnlock(hwp0);
3343c582b7e3Smrg#if defined(__powerpc__)
3344c582b7e3Smrg                vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE);
3345c582b7e3Smrg#else
3346c582b7e3Smrg                vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
3347c582b7e3Smrg#endif
3348c582b7e3Smrg                vgaHWLock(hwp0);
3349c582b7e3Smrg            }
3350c582b7e3Smrg        }
3351c582b7e3Smrg    }
3352c582b7e3Smrg#endif
3353c582b7e3Smrg
3354c582b7e3Smrg    R128WaitForVerticalSync(pScrn);
3355c582b7e3Smrg    R128Unblank(pScrn);
3356c582b7e3Smrg}
3357c582b7e3Smrg
3358c582b7e3Smrg/* Define common registers for requested video mode. */
3359c582b7e3Smrgstatic void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
3360c582b7e3Smrg{
3361c582b7e3Smrg    save->ovr_clr            = 0;
3362c582b7e3Smrg    save->ovr_wid_left_right = 0;
3363c582b7e3Smrg    save->ovr_wid_top_bottom = 0;
3364c582b7e3Smrg    save->ov0_scale_cntl     = 0;
3365c582b7e3Smrg    save->mpp_tb_config      = 0;
3366c582b7e3Smrg    save->mpp_gp_config      = 0;
3367c582b7e3Smrg    save->subpic_cntl        = 0;
3368c582b7e3Smrg    save->viph_control       = 0;
3369c582b7e3Smrg    save->i2c_cntl_1         = 0;
3370c582b7e3Smrg#ifdef XF86DRI
3371c582b7e3Smrg    save->gen_int_cntl       = info->gen_int_cntl;
3372c582b7e3Smrg#else
3373c582b7e3Smrg    save->gen_int_cntl       = 0;
3374c582b7e3Smrg#endif
3375c582b7e3Smrg    save->cap0_trig_cntl     = 0;
3376c582b7e3Smrg    save->cap1_trig_cntl     = 0;
3377c582b7e3Smrg    save->bus_cntl           = info->BusCntl;
3378c582b7e3Smrg    /*
3379c582b7e3Smrg     * If bursts are enabled, turn on discards and aborts
3380c582b7e3Smrg     */
3381c582b7e3Smrg    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
3382c582b7e3Smrg	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
3383c582b7e3Smrg}
3384c582b7e3Smrg
3385c582b7e3Smrg/* Define CRTC registers for requested video mode. */
3386c582b7e3Smrgstatic Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
3387c582b7e3Smrg				  DisplayModePtr mode, R128InfoPtr info)
3388c582b7e3Smrg{
3389c582b7e3Smrg    int    format;
3390c582b7e3Smrg    int    hsync_start;
3391c582b7e3Smrg    int    hsync_wid;
3392c582b7e3Smrg    int    hsync_fudge;
3393c582b7e3Smrg    int    vsync_wid;
3394c582b7e3Smrg    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
3395c582b7e3Smrg    int    hsync_fudge_fp[]      = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
3396c582b7e3Smrg//   int    hsync_fudge_fp_crt[]  = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
3397c582b7e3Smrg
3398c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3399c582b7e3Smrg    case 4:  format = 1; break;
3400c582b7e3Smrg    case 8:  format = 2; break;
3401c582b7e3Smrg    case 15: format = 3; break;      /*  555 */
3402c582b7e3Smrg    case 16: format = 4; break;      /*  565 */
3403c582b7e3Smrg    case 24: format = 5; break;      /*  RGB */
3404c582b7e3Smrg    case 32: format = 6; break;      /* xRGB */
3405c582b7e3Smrg    default:
3406c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3407c582b7e3Smrg		   "Unsupported pixel depth (%d)\n",
3408c582b7e3Smrg		   info->CurrentLayout.bitsPerPixel);
3409c582b7e3Smrg	return FALSE;
3410c582b7e3Smrg    }
3411c582b7e3Smrg
3412c582b7e3Smrg    if ((info->DisplayType == MT_DFP) ||
3413c582b7e3Smrg        (info->DisplayType == MT_LCD))
3414c582b7e3Smrg	hsync_fudge = hsync_fudge_fp[format-1];
3415c582b7e3Smrg    else
3416c582b7e3Smrg        hsync_fudge = hsync_fudge_default[format-1];
3417c582b7e3Smrg
3418c582b7e3Smrg    save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN
3419c582b7e3Smrg			  | R128_CRTC_EN
3420c582b7e3Smrg			  | (format << 8)
3421c582b7e3Smrg			  | ((mode->Flags & V_DBLSCAN)
3422c582b7e3Smrg			     ? R128_CRTC_DBL_SCAN_EN
3423c582b7e3Smrg			     : 0)
3424c582b7e3Smrg			  | ((mode->Flags & V_INTERLACE)
3425c582b7e3Smrg			     ? R128_CRTC_INTERLACE_EN
3426c582b7e3Smrg			     : 0)
3427c582b7e3Smrg			  | ((mode->Flags & V_CSYNC)
3428c582b7e3Smrg			     ? R128_CRTC_CSYNC_EN
3429c582b7e3Smrg			     : 0));
3430c582b7e3Smrg
3431c582b7e3Smrg    if((info->DisplayType == MT_DFP) ||
3432c582b7e3Smrg       (info->DisplayType == MT_LCD))
3433c582b7e3Smrg    {
3434c582b7e3Smrg        save->crtc_ext_cntl = R128_VGA_ATI_LINEAR |
3435c582b7e3Smrg        			  R128_XCRT_CNT_EN;
3436c582b7e3Smrg        save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN |
3437c582b7e3Smrg                                  R128_CRTC_INTERLACE_EN);
3438c582b7e3Smrg    }
3439c582b7e3Smrg    else
3440c582b7e3Smrg        save->crtc_ext_cntl = R128_VGA_ATI_LINEAR |
3441c582b7e3Smrg			      R128_XCRT_CNT_EN |
3442c582b7e3Smrg			      R128_CRTC_CRT_ON;
3443c582b7e3Smrg
3444c582b7e3Smrg    save->dac_cntl      = (R128_DAC_MASK_ALL
3445c582b7e3Smrg			   | R128_DAC_VGA_ADR_EN
3446c582b7e3Smrg			   | (info->dac6bits ? 0 : R128_DAC_8BIT_EN));
3447c582b7e3Smrg
3448c582b7e3Smrg
3449c582b7e3Smrg    if(info->isDFP && !info->isPro2)
3450c582b7e3Smrg    {
3451c582b7e3Smrg        if(info->PanelXRes < mode->CrtcHDisplay)
3452c582b7e3Smrg            mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes;
3453c582b7e3Smrg        if(info->PanelYRes < mode->CrtcVDisplay)
3454c582b7e3Smrg            mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes;
3455c582b7e3Smrg        mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank;
3456c582b7e3Smrg        mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus;
3457c582b7e3Smrg        mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth;
3458c582b7e3Smrg        mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank;
3459c582b7e3Smrg        mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus;
3460c582b7e3Smrg        mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth;
3461c582b7e3Smrg    }
3462c582b7e3Smrg
3463c582b7e3Smrg    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
3464c582b7e3Smrg			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
3465c582b7e3Smrg
3466c582b7e3Smrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
3467c582b7e3Smrg    if (!hsync_wid)       hsync_wid = 1;
3468c582b7e3Smrg    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
3469c582b7e3Smrg
3470c582b7e3Smrg    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
3471c582b7e3Smrg
3472c582b7e3Smrg    save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff)
3473c582b7e3Smrg				 | (hsync_wid << 16)
3474c582b7e3Smrg				 | ((mode->Flags & V_NHSYNC)
3475c582b7e3Smrg				    ? R128_CRTC_H_SYNC_POL
3476c582b7e3Smrg				    : 0));
3477c582b7e3Smrg
3478c582b7e3Smrg#if 1
3479c582b7e3Smrg				/* This works for double scan mode. */
3480c582b7e3Smrg    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3481c582b7e3Smrg			      | ((mode->CrtcVDisplay - 1) << 16));
3482c582b7e3Smrg#else
3483c582b7e3Smrg				/* This is what cce/nbmode.c example code
3484c582b7e3Smrg				   does -- is this correct? */
3485c582b7e3Smrg    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3486c582b7e3Smrg			      | ((mode->CrtcVDisplay
3487c582b7e3Smrg				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
3488c582b7e3Smrg				 << 16));
3489c582b7e3Smrg#endif
3490c582b7e3Smrg
3491c582b7e3Smrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
3492c582b7e3Smrg    if (!vsync_wid)       vsync_wid = 1;
3493c582b7e3Smrg    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
3494c582b7e3Smrg
3495c582b7e3Smrg    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3496c582b7e3Smrg				 | (vsync_wid << 16)
3497c582b7e3Smrg				 | ((mode->Flags & V_NVSYNC)
3498c582b7e3Smrg				    ? R128_CRTC_V_SYNC_POL
3499c582b7e3Smrg				    : 0));
3500c582b7e3Smrg    save->crtc_offset      = 0;
3501c582b7e3Smrg    save->crtc_offset_cntl = 0;
3502c582b7e3Smrg    save->crtc_pitch       = info->CurrentLayout.displayWidth / 8;
3503c582b7e3Smrg
3504c582b7e3Smrg    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3505c582b7e3Smrg	       save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth));
3506c582b7e3Smrg
3507c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
3508c582b7e3Smrg    /* Change the endianness of the aperture */
3509c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3510c582b7e3Smrg    case 15:
3511c582b7e3Smrg    case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break;
3512c582b7e3Smrg    case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break;
3513c582b7e3Smrg    default: break;
3514c582b7e3Smrg    }
3515c582b7e3Smrg#endif
3516c582b7e3Smrg
3517c582b7e3Smrg    return TRUE;
3518c582b7e3Smrg}
3519c582b7e3Smrg
3520c582b7e3Smrg/* Define CRTC2 registers for requested video mode. */
3521c582b7e3Smrgstatic Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save,
3522c582b7e3Smrg				  DisplayModePtr mode, R128InfoPtr info)
3523c582b7e3Smrg{
3524c582b7e3Smrg    int    format;
3525c582b7e3Smrg    int    hsync_start;
3526c582b7e3Smrg    int    hsync_wid;
3527c582b7e3Smrg    int    hsync_fudge;
3528c582b7e3Smrg    int    vsync_wid;
3529c582b7e3Smrg    int    bytpp;
3530c582b7e3Smrg    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
3531c582b7e3Smrg
3532c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3533c582b7e3Smrg    case 4:  format = 1; bytpp = 0; break;
3534c582b7e3Smrg    case 8:  format = 2; bytpp = 1; break;
3535c582b7e3Smrg    case 15: format = 3; bytpp = 2; break;      /*  555 */
3536c582b7e3Smrg    case 16: format = 4; bytpp = 2; break;      /*  565 */
3537c582b7e3Smrg    case 24: format = 5; bytpp = 3; break;      /*  RGB */
3538c582b7e3Smrg    case 32: format = 6; bytpp = 4; break;      /* xRGB */
3539c582b7e3Smrg    default:
3540c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3541c582b7e3Smrg		   "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel);
3542c582b7e3Smrg	return FALSE;
3543c582b7e3Smrg    }
3544c582b7e3Smrg    R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp));
3545c582b7e3Smrg
3546c582b7e3Smrg    hsync_fudge = hsync_fudge_default[format-1];
3547c582b7e3Smrg
3548c582b7e3Smrg    save->crtc2_gen_cntl = (R128_CRTC2_EN
3549c582b7e3Smrg			  | (format << 8)
3550c582b7e3Smrg			  | ((mode->Flags & V_DBLSCAN)
3551c582b7e3Smrg			     ? R128_CRTC2_DBL_SCAN_EN
3552c582b7e3Smrg			     : 0));
3553c582b7e3Smrg/*
3554c582b7e3Smrg    save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN;
3555c582b7e3Smrg    save->crtc2_gen_cntl |= (1 << 21);
3556c582b7e3Smrg*/
3557c582b7e3Smrg    save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
3558c582b7e3Smrg			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
3559c582b7e3Smrg
3560c582b7e3Smrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
3561c582b7e3Smrg    if (!hsync_wid)       hsync_wid = 1;
3562c582b7e3Smrg    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
3563c582b7e3Smrg
3564c582b7e3Smrg    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
3565c582b7e3Smrg
3566c582b7e3Smrg    save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff)
3567c582b7e3Smrg				 | (hsync_wid << 16)
3568c582b7e3Smrg				 | ((mode->Flags & V_NHSYNC)
3569c582b7e3Smrg				    ? R128_CRTC2_H_SYNC_POL
3570c582b7e3Smrg				    : 0));
3571c582b7e3Smrg
3572c582b7e3Smrg#if 1
3573c582b7e3Smrg				/* This works for double scan mode. */
3574c582b7e3Smrg    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3575c582b7e3Smrg			      | ((mode->CrtcVDisplay - 1) << 16));
3576c582b7e3Smrg#else
3577c582b7e3Smrg				/* This is what cce/nbmode.c example code
3578c582b7e3Smrg				   does -- is this correct? */
3579c582b7e3Smrg    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3580c582b7e3Smrg			      | ((mode->CrtcVDisplay
3581c582b7e3Smrg				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
3582c582b7e3Smrg				 << 16));
3583c582b7e3Smrg#endif
3584c582b7e3Smrg
3585c582b7e3Smrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
3586c582b7e3Smrg    if (!vsync_wid)       vsync_wid = 1;
3587c582b7e3Smrg    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
3588c582b7e3Smrg
3589c582b7e3Smrg    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3590c582b7e3Smrg				 | (vsync_wid << 16)
3591c582b7e3Smrg				 | ((mode->Flags & V_NVSYNC)
3592c582b7e3Smrg				    ? R128_CRTC2_V_SYNC_POL
3593c582b7e3Smrg				    : 0));
3594c582b7e3Smrg
3595c582b7e3Smrg    save->crtc2_offset      = 0;
3596c582b7e3Smrg    save->crtc2_offset_cntl = 0;
3597c582b7e3Smrg
3598c582b7e3Smrg    save->crtc2_pitch       = info->CurrentLayout.displayWidth / 8;
3599c582b7e3Smrg
3600c582b7e3Smrg    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3601c582b7e3Smrg		 save->crtc2_pitch, pScrn->virtualX,
3602c582b7e3Smrg		 info->CurrentLayout.displayWidth));
3603c582b7e3Smrg    return TRUE;
3604c582b7e3Smrg}
3605c582b7e3Smrg
3606c582b7e3Smrg/* Define CRTC registers for requested video mode. */
3607c582b7e3Smrgstatic void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save,
3608c582b7e3Smrg				DisplayModePtr mode, R128InfoPtr info)
3609c582b7e3Smrg{
3610c582b7e3Smrg    int   xres = mode->CrtcHDisplay;
3611c582b7e3Smrg    int   yres = mode->CrtcVDisplay;
3612c582b7e3Smrg    float Hratio, Vratio;
3613c582b7e3Smrg
3614c582b7e3Smrg    if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) {
3615c582b7e3Smrg        save->crtc_ext_cntl  |= R128_CRTC_CRT_ON;
3616c582b7e3Smrg        save->crtc2_gen_cntl  = 0;
3617c582b7e3Smrg        save->fp_gen_cntl     = orig->fp_gen_cntl;
3618c582b7e3Smrg        save->fp_gen_cntl    &= ~(R128_FP_FPON |
3619c582b7e3Smrg            R128_FP_CRTC_USE_SHADOW_VEND |
3620c582b7e3Smrg            R128_FP_CRTC_HORZ_DIV2_EN |
3621c582b7e3Smrg            R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3622c582b7e3Smrg            R128_FP_USE_SHADOW_EN);
3623c582b7e3Smrg        save->fp_gen_cntl    |= (R128_FP_SEL_CRTC2 |
3624c582b7e3Smrg                                 R128_FP_CRTC_DONT_SHADOW_VPAR);
3625c582b7e3Smrg        save->fp_panel_cntl   = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON;
3626c582b7e3Smrg        save->lvds_gen_cntl   = orig->lvds_gen_cntl &
3627c582b7e3Smrg				    (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON);
3628c582b7e3Smrg        return;
3629c582b7e3Smrg    }
3630c582b7e3Smrg
3631c582b7e3Smrg    if (xres > info->PanelXRes) xres = info->PanelXRes;
3632c582b7e3Smrg    if (yres > info->PanelYRes) yres = info->PanelYRes;
3633c582b7e3Smrg
3634c582b7e3Smrg    Hratio = (float)xres/(float)info->PanelXRes;
3635c582b7e3Smrg    Vratio = (float)yres/(float)info->PanelYRes;
3636c582b7e3Smrg
3637c582b7e3Smrg    save->fp_horz_stretch =
3638c582b7e3Smrg	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
3639c582b7e3Smrg	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
3640c582b7e3Smrg       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
3641c582b7e3Smrg                                 R128_HORZ_FP_LOOP_STRETCH |
3642c582b7e3Smrg                                 R128_HORZ_STRETCH_RESERVED)));
3643c582b7e3Smrg    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
3644c582b7e3Smrg    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
3645c582b7e3Smrg    if (xres == info->PanelXRes)
3646c582b7e3Smrg         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3647c582b7e3Smrg    else
3648c582b7e3Smrg         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3649c582b7e3Smrg
3650c582b7e3Smrg    save->fp_vert_stretch =
3651c582b7e3Smrg	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
3652c582b7e3Smrg	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
3653c582b7e3Smrg	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
3654c582b7e3Smrg				   R128_VERT_STRETCH_RESERVED)));
3655c582b7e3Smrg    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
3656c582b7e3Smrg    if (yres == info->PanelYRes)
3657c582b7e3Smrg        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3658c582b7e3Smrg    else
3659c582b7e3Smrg        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3660c582b7e3Smrg
3661c582b7e3Smrg    save->fp_gen_cntl = (orig->fp_gen_cntl &
3662c582b7e3Smrg			 (CARD32)~(R128_FP_SEL_CRTC2 |
3663c582b7e3Smrg				   R128_FP_CRTC_USE_SHADOW_VEND |
3664c582b7e3Smrg				   R128_FP_CRTC_HORZ_DIV2_EN |
3665c582b7e3Smrg				   R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3666c582b7e3Smrg				   R128_FP_USE_SHADOW_EN));
3667c582b7e3Smrg
3668c582b7e3Smrg    save->fp_panel_cntl        = orig->fp_panel_cntl;
3669c582b7e3Smrg    save->lvds_gen_cntl        = orig->lvds_gen_cntl;
3670c582b7e3Smrg    save->tmds_crc             = orig->tmds_crc;
3671c582b7e3Smrg
3672c582b7e3Smrg    /* Disable CRT output by disabling CRT output and setting the CRT
3673c582b7e3Smrg       DAC to use CRTC2, which we set to 0's.  In the future, we will
3674c582b7e3Smrg       want to use the dual CRTC capabilities of the R128 to allow both
3675c582b7e3Smrg       the flat panel and external CRT to either simultaneously display
3676c582b7e3Smrg       the same image or display two different images. */
3677c582b7e3Smrg
3678c582b7e3Smrg
3679c582b7e3Smrg    if(!info->isDFP){
3680c582b7e3Smrg        if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) {
3681c582b7e3Smrg		save->crtc_ext_cntl  |= R128_CRTC_CRT_ON;
3682c582b7e3Smrg	} else if (info->BIOSDisplay == R128_DUALHEAD) {
3683c582b7e3Smrg		save->crtc_ext_cntl  |= R128_CRTC_CRT_ON;
3684c582b7e3Smrg		save->dac_cntl       |= R128_DAC_CRT_SEL_CRTC2;
3685c582b7e3Smrg		save->dac_cntl       |= R128_DAC_PALETTE2_SNOOP_EN;
3686c582b7e3Smrg        } else {
3687c582b7e3Smrg		save->crtc_ext_cntl  &= ~R128_CRTC_CRT_ON;
3688c582b7e3Smrg		save->dac_cntl       |= R128_DAC_CRT_SEL_CRTC2;
3689c582b7e3Smrg		save->crtc2_gen_cntl  = 0;
3690c582b7e3Smrg        }
3691c582b7e3Smrg    }
3692c582b7e3Smrg
3693c582b7e3Smrg    /* WARNING: Be careful about turning on the flat panel */
3694c582b7e3Smrg    if(info->isDFP){
3695c582b7e3Smrg        save->fp_gen_cntl = orig->fp_gen_cntl;
3696c582b7e3Smrg
3697c582b7e3Smrg        save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
3698c582b7e3Smrg                               R128_FP_CRTC_USE_SHADOW_ROWCUR |
3699c582b7e3Smrg                               R128_FP_CRTC_HORZ_DIV2_EN |
3700c582b7e3Smrg                               R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3701c582b7e3Smrg                               R128_FP_CRT_SYNC_SEL |
3702c582b7e3Smrg                               R128_FP_USE_SHADOW_EN);
3703c582b7e3Smrg
3704c582b7e3Smrg        save->fp_panel_cntl  |= (R128_FP_DIGON | R128_FP_BLON);
3705c582b7e3Smrg        save->fp_gen_cntl    |= (R128_FP_FPON | R128_FP_TDMS_EN |
3706c582b7e3Smrg             R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND);
3707c582b7e3Smrg        save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl
3708c582b7e3Smrg            & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN;
3709c582b7e3Smrg    }
3710c582b7e3Smrg    else
3711c582b7e3Smrg        save->lvds_gen_cntl  |= (R128_LVDS_ON | R128_LVDS_BLON);
3712c582b7e3Smrg
3713c582b7e3Smrg    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
3714c582b7e3Smrg    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
3715c582b7e3Smrg    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
3716c582b7e3Smrg    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
3717c582b7e3Smrg}
3718c582b7e3Smrg
3719c582b7e3Smrg/* Define PLL registers for requested video mode. */
3720c582b7e3Smrgstatic void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
3721c582b7e3Smrg				R128PLLPtr pll, double dot_clock)
3722c582b7e3Smrg{
3723c582b7e3Smrg    unsigned long freq = dot_clock * 100;
3724c582b7e3Smrg    struct {
3725c582b7e3Smrg	int divider;
3726c582b7e3Smrg	int bitvalue;
3727c582b7e3Smrg    } *post_div,
3728c582b7e3Smrg      post_divs[]   = {
3729c582b7e3Smrg				/* From RAGE 128 VR/RAGE 128 GL Register
3730c582b7e3Smrg				   Reference Manual (Technical Reference
3731c582b7e3Smrg				   Manual P/N RRG-G04100-C Rev. 0.04), page
3732c582b7e3Smrg				   3-17 (PLL_DIV_[3:0]).  */
3733c582b7e3Smrg	{  1, 0 },              /* VCLK_SRC                 */
3734c582b7e3Smrg	{  2, 1 },              /* VCLK_SRC/2               */
3735c582b7e3Smrg	{  4, 2 },              /* VCLK_SRC/4               */
3736c582b7e3Smrg	{  8, 3 },              /* VCLK_SRC/8               */
3737c582b7e3Smrg
3738c582b7e3Smrg	{  3, 4 },              /* VCLK_SRC/3               */
3739c582b7e3Smrg				/* bitvalue = 5 is reserved */
3740c582b7e3Smrg	{  6, 6 },              /* VCLK_SRC/6               */
3741c582b7e3Smrg	{ 12, 7 },              /* VCLK_SRC/12              */
3742c582b7e3Smrg	{  0, 0 }
3743c582b7e3Smrg    };
3744c582b7e3Smrg
3745c582b7e3Smrg    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3746c582b7e3Smrg    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3747c582b7e3Smrg
3748c582b7e3Smrg    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3749c582b7e3Smrg	save->pll_output_freq = post_div->divider * freq;
3750c582b7e3Smrg	if (save->pll_output_freq >= pll->min_pll_freq
3751c582b7e3Smrg	    && save->pll_output_freq <= pll->max_pll_freq) break;
3752c582b7e3Smrg    }
3753c582b7e3Smrg
3754c582b7e3Smrg    save->dot_clock_freq = freq;
3755c582b7e3Smrg    save->feedback_div   = R128Div(pll->reference_div * save->pll_output_freq,
3756c582b7e3Smrg				   pll->reference_freq);
3757c582b7e3Smrg    save->post_div       = post_div->divider;
3758c582b7e3Smrg
3759c582b7e3Smrg    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3760c582b7e3Smrg	       save->dot_clock_freq,
3761c582b7e3Smrg	       save->pll_output_freq,
3762c582b7e3Smrg	       save->feedback_div,
3763c582b7e3Smrg	       save->post_div));
3764c582b7e3Smrg
3765c582b7e3Smrg    save->ppll_ref_div   = pll->reference_div;
3766c582b7e3Smrg    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
3767c582b7e3Smrg    save->htotal_cntl    = 0;
3768c582b7e3Smrg
3769c582b7e3Smrg}
3770c582b7e3Smrg
3771c582b7e3Smrg/* Define PLL2 registers for requested video mode. */
3772c582b7e3Smrgstatic void R128InitPLL2Registers(R128SavePtr save, R128PLLPtr pll,
3773c582b7e3Smrg				   double dot_clock)
3774c582b7e3Smrg{
3775c582b7e3Smrg    unsigned long freq = dot_clock * 100;
3776c582b7e3Smrg    struct {
3777c582b7e3Smrg	int divider;
3778c582b7e3Smrg	int bitvalue;
3779c582b7e3Smrg    } *post_div,
3780c582b7e3Smrg      post_divs[]   = {
3781c582b7e3Smrg				/* From RAGE 128 VR/RAGE 128 GL Register
3782c582b7e3Smrg				   Reference Manual (Technical Reference
3783c582b7e3Smrg				   Manual P/N RRG-G04100-C Rev. 0.04), page
3784c582b7e3Smrg				   3-17 (PLL_DIV_[3:0]).  */
3785c582b7e3Smrg	{  1, 0 },              /* VCLK_SRC                 */
3786c582b7e3Smrg	{  2, 1 },              /* VCLK_SRC/2               */
3787c582b7e3Smrg	{  4, 2 },              /* VCLK_SRC/4               */
3788c582b7e3Smrg	{  8, 3 },              /* VCLK_SRC/8               */
3789c582b7e3Smrg
3790c582b7e3Smrg	{  3, 4 },              /* VCLK_SRC/3               */
3791c582b7e3Smrg				/* bitvalue = 5 is reserved */
3792c582b7e3Smrg	{  6, 6 },              /* VCLK_SRC/6               */
3793c582b7e3Smrg	{ 12, 7 },              /* VCLK_SRC/12              */
3794c582b7e3Smrg	{  0, 0 }
3795c582b7e3Smrg    };
3796c582b7e3Smrg
3797c582b7e3Smrg    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3798c582b7e3Smrg    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3799c582b7e3Smrg
3800c582b7e3Smrg    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3801c582b7e3Smrg	save->pll_output_freq_2 = post_div->divider * freq;
3802c582b7e3Smrg	if (save->pll_output_freq_2 >= pll->min_pll_freq
3803c582b7e3Smrg	    && save->pll_output_freq_2 <= pll->max_pll_freq) break;
3804c582b7e3Smrg    }
3805c582b7e3Smrg
3806c582b7e3Smrg    save->dot_clock_freq_2 = freq;
3807c582b7e3Smrg    save->feedback_div_2   = R128Div(pll->reference_div
3808c582b7e3Smrg				     * save->pll_output_freq_2,
3809c582b7e3Smrg				     pll->reference_freq);
3810c582b7e3Smrg    save->post_div_2       = post_div->divider;
3811c582b7e3Smrg
3812c582b7e3Smrg    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3813c582b7e3Smrg	       save->dot_clock_freq_2,
3814c582b7e3Smrg	       save->pll_output_freq_2,
3815c582b7e3Smrg	       save->feedback_div_2,
3816c582b7e3Smrg	       save->post_div_2));
3817c582b7e3Smrg
3818c582b7e3Smrg    save->p2pll_ref_div   = pll->reference_div;
3819c582b7e3Smrg    save->p2pll_div_0    = (save->feedback_div_2 | (post_div->bitvalue<<16));
3820c582b7e3Smrg    save->htotal_cntl2    = 0;
3821c582b7e3Smrg}
3822c582b7e3Smrg
3823c582b7e3Smrg/* Define DDA registers for requested video mode. */
3824c582b7e3Smrgstatic Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save,
3825c582b7e3Smrg				 R128PLLPtr pll, R128InfoPtr info,
3826c582b7e3Smrg                                 DisplayModePtr mode)
3827c582b7e3Smrg{
3828c582b7e3Smrg    int         DisplayFifoWidth = 128;
3829c582b7e3Smrg    int         DisplayFifoDepth = 32;
3830c582b7e3Smrg    int         XclkFreq;
3831c582b7e3Smrg    int         VclkFreq;
3832c582b7e3Smrg    int         XclksPerTransfer;
3833c582b7e3Smrg    int         XclksPerTransferPrecise;
3834c582b7e3Smrg    int         UseablePrecision;
3835c582b7e3Smrg    int         Roff;
3836c582b7e3Smrg    int         Ron;
3837c582b7e3Smrg
3838c582b7e3Smrg    XclkFreq = pll->xclk;
3839c582b7e3Smrg
3840c582b7e3Smrg    VclkFreq = R128Div(pll->reference_freq * save->feedback_div,
3841c582b7e3Smrg		       pll->reference_div * save->post_div);
3842c582b7e3Smrg
3843c582b7e3Smrg    if(info->isDFP && !info->isPro2){
3844c582b7e3Smrg        if(info->PanelXRes != mode->CrtcHDisplay)
3845c582b7e3Smrg            VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes;
3846c582b7e3Smrg	}
3847c582b7e3Smrg
3848c582b7e3Smrg    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3849c582b7e3Smrg			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3850c582b7e3Smrg
3851c582b7e3Smrg    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3852c582b7e3Smrg
3853c582b7e3Smrg    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3854c582b7e3Smrg				      << (11 - UseablePrecision),
3855c582b7e3Smrg				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3856c582b7e3Smrg
3857c582b7e3Smrg    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3858c582b7e3Smrg
3859c582b7e3Smrg    Ron   = (4 * info->ram->MB
3860c582b7e3Smrg	     + 3 * MAX(info->ram->Trcd - 2, 0)
3861c582b7e3Smrg	     + 2 * info->ram->Trp
3862c582b7e3Smrg	     + info->ram->Twr
3863c582b7e3Smrg	     + info->ram->CL
3864c582b7e3Smrg	     + info->ram->Tr2w
3865c582b7e3Smrg	     + XclksPerTransfer) << (11 - UseablePrecision);
3866c582b7e3Smrg
3867c582b7e3Smrg    if (Ron + info->ram->Rloop >= Roff) {
3868c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3869c582b7e3Smrg		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3870c582b7e3Smrg		   Ron, info->ram->Rloop, Roff);
3871c582b7e3Smrg	return FALSE;
3872c582b7e3Smrg    }
3873c582b7e3Smrg
3874c582b7e3Smrg    save->dda_config = (XclksPerTransferPrecise
3875c582b7e3Smrg			| (UseablePrecision << 16)
3876c582b7e3Smrg			| (info->ram->Rloop << 20));
3877c582b7e3Smrg
3878c582b7e3Smrg    save->dda_on_off = (Ron << 16) | Roff;
3879c582b7e3Smrg
3880c582b7e3Smrg    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3881c582b7e3Smrg	       XclkFreq,
3882c582b7e3Smrg	       VclkFreq,
3883c582b7e3Smrg	       XclksPerTransfer,
3884c582b7e3Smrg	       XclksPerTransferPrecise,
3885c582b7e3Smrg	       UseablePrecision));
3886c582b7e3Smrg    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3887c582b7e3Smrg	       Roff, Ron, info->ram->Rloop));
3888c582b7e3Smrg
3889c582b7e3Smrg    return TRUE;
3890c582b7e3Smrg}
3891c582b7e3Smrg
3892c582b7e3Smrg/* Define DDA2 registers for requested video mode. */
3893c582b7e3Smrgstatic Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save,
3894c582b7e3Smrg				 R128PLLPtr pll, R128InfoPtr info,
3895c582b7e3Smrg                                 DisplayModePtr mode)
3896c582b7e3Smrg{
3897c582b7e3Smrg    int         DisplayFifoWidth = 128;
3898c582b7e3Smrg    int         DisplayFifoDepth = 32;
3899c582b7e3Smrg    int         XclkFreq;
3900c582b7e3Smrg    int         VclkFreq;
3901c582b7e3Smrg    int         XclksPerTransfer;
3902c582b7e3Smrg    int         XclksPerTransferPrecise;
3903c582b7e3Smrg    int         UseablePrecision;
3904c582b7e3Smrg    int         Roff;
3905c582b7e3Smrg    int         Ron;
3906c582b7e3Smrg
3907c582b7e3Smrg    XclkFreq = pll->xclk;
3908c582b7e3Smrg
3909c582b7e3Smrg    VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2,
3910c582b7e3Smrg		       pll->reference_div * save->post_div_2);
3911c582b7e3Smrg
3912c582b7e3Smrg    if(info->isDFP && !info->isPro2){
3913c582b7e3Smrg        if(info->PanelXRes != mode->CrtcHDisplay)
3914c582b7e3Smrg            VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes;
3915c582b7e3Smrg	}
3916c582b7e3Smrg
3917c582b7e3Smrg    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3918c582b7e3Smrg			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3919c582b7e3Smrg
3920c582b7e3Smrg    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3921c582b7e3Smrg
3922c582b7e3Smrg    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3923c582b7e3Smrg				      << (11 - UseablePrecision),
3924c582b7e3Smrg				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3925c582b7e3Smrg
3926c582b7e3Smrg    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3927c582b7e3Smrg
3928c582b7e3Smrg    Ron   = (4 * info->ram->MB
3929c582b7e3Smrg	     + 3 * MAX(info->ram->Trcd - 2, 0)
3930c582b7e3Smrg	     + 2 * info->ram->Trp
3931c582b7e3Smrg	     + info->ram->Twr
3932c582b7e3Smrg	     + info->ram->CL
3933c582b7e3Smrg	     + info->ram->Tr2w
3934c582b7e3Smrg	     + XclksPerTransfer) << (11 - UseablePrecision);
3935c582b7e3Smrg
3936c582b7e3Smrg
3937c582b7e3Smrg    if (Ron + info->ram->Rloop >= Roff) {
3938c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3939c582b7e3Smrg		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3940c582b7e3Smrg		   Ron, info->ram->Rloop, Roff);
3941c582b7e3Smrg	return FALSE;
3942c582b7e3Smrg    }
3943c582b7e3Smrg
3944c582b7e3Smrg    save->dda2_config = (XclksPerTransferPrecise
3945c582b7e3Smrg			| (UseablePrecision << 16)
3946c582b7e3Smrg			| (info->ram->Rloop << 20));
3947c582b7e3Smrg
3948c582b7e3Smrg    /*save->dda2_on_off = (Ron << 16) | Roff;*/
3949c582b7e3Smrg    /* shift most be 18 otherwise there's corruption on crtc2 */
3950c582b7e3Smrg    save->dda2_on_off = (Ron << 18) | Roff;
3951c582b7e3Smrg
3952c582b7e3Smrg    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3953c582b7e3Smrg	       XclkFreq,
3954c582b7e3Smrg	       VclkFreq,
3955c582b7e3Smrg	       XclksPerTransfer,
3956c582b7e3Smrg	       XclksPerTransferPrecise,
3957c582b7e3Smrg	       UseablePrecision));
3958c582b7e3Smrg    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3959c582b7e3Smrg	       Roff, Ron, info->ram->Rloop));
3960c582b7e3Smrg
3961c582b7e3Smrg    return TRUE;
3962c582b7e3Smrg}
3963c582b7e3Smrg
3964c582b7e3Smrg#if 0
3965c582b7e3Smrg/* Define initial palette for requested video mode.  This doesn't do
3966c582b7e3Smrg   anything for XFree86 4.0. */
3967c582b7e3Smrgstatic void R128InitPalette(R128SavePtr save)
3968c582b7e3Smrg{
3969c582b7e3Smrg    save->palette_valid = FALSE;
3970c582b7e3Smrg}
3971c582b7e3Smrg#endif
3972c582b7e3Smrg
3973c582b7e3Smrg/* Define registers for a requested video mode. */
3974c582b7e3Smrgstatic Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save)
3975c582b7e3Smrg{
3976c582b7e3Smrg    R128InfoPtr info      = R128PTR(pScrn);
3977c582b7e3Smrg    double      dot_clock = mode->Clock/1000.0;
3978c582b7e3Smrg
3979c582b7e3Smrg#if R128_DEBUG
3980c582b7e3Smrg    ErrorF("%-12.12s %7.2f  %4d %4d %4d %4d  %4d %4d %4d %4d (%d,%d)",
3981c582b7e3Smrg	   mode->name,
3982c582b7e3Smrg	   dot_clock,
3983c582b7e3Smrg
3984c582b7e3Smrg	   mode->HDisplay,
3985c582b7e3Smrg	   mode->HSyncStart,
3986c582b7e3Smrg	   mode->HSyncEnd,
3987c582b7e3Smrg	   mode->HTotal,
3988c582b7e3Smrg
3989c582b7e3Smrg	   mode->VDisplay,
3990c582b7e3Smrg	   mode->VSyncStart,
3991c582b7e3Smrg	   mode->VSyncEnd,
3992c582b7e3Smrg	   mode->VTotal,
3993c582b7e3Smrg	   pScrn->depth,
3994c582b7e3Smrg	   pScrn->bitsPerPixel);
3995c582b7e3Smrg    if (mode->Flags & V_DBLSCAN)   ErrorF(" D");
3996c582b7e3Smrg    if (mode->Flags & V_CSYNC)     ErrorF(" C");
3997c582b7e3Smrg    if (mode->Flags & V_INTERLACE) ErrorF(" I");
3998c582b7e3Smrg    if (mode->Flags & V_PHSYNC)    ErrorF(" +H");
3999c582b7e3Smrg    if (mode->Flags & V_NHSYNC)    ErrorF(" -H");
4000c582b7e3Smrg    if (mode->Flags & V_PVSYNC)    ErrorF(" +V");
4001c582b7e3Smrg    if (mode->Flags & V_NVSYNC)    ErrorF(" -V");
4002c582b7e3Smrg    ErrorF("\n");
4003c582b7e3Smrg    ErrorF("%-12.12s %7.2f  %4d %4d %4d %4d  %4d %4d %4d %4d (%d,%d)",
4004c582b7e3Smrg	   mode->name,
4005c582b7e3Smrg	   dot_clock,
4006c582b7e3Smrg
4007c582b7e3Smrg	   mode->CrtcHDisplay,
4008c582b7e3Smrg	   mode->CrtcHSyncStart,
4009c582b7e3Smrg	   mode->CrtcHSyncEnd,
4010c582b7e3Smrg	   mode->CrtcHTotal,
4011c582b7e3Smrg
4012c582b7e3Smrg	   mode->CrtcVDisplay,
4013c582b7e3Smrg	   mode->CrtcVSyncStart,
4014c582b7e3Smrg	   mode->CrtcVSyncEnd,
4015c582b7e3Smrg	   mode->CrtcVTotal,
4016c582b7e3Smrg	   pScrn->depth,
4017c582b7e3Smrg	   pScrn->bitsPerPixel);
4018c582b7e3Smrg    if (mode->Flags & V_DBLSCAN)   ErrorF(" D");
4019c582b7e3Smrg    if (mode->Flags & V_CSYNC)     ErrorF(" C");
4020c582b7e3Smrg    if (mode->Flags & V_INTERLACE) ErrorF(" I");
4021c582b7e3Smrg    if (mode->Flags & V_PHSYNC)    ErrorF(" +H");
4022c582b7e3Smrg    if (mode->Flags & V_NHSYNC)    ErrorF(" -H");
4023c582b7e3Smrg    if (mode->Flags & V_PVSYNC)    ErrorF(" +V");
4024c582b7e3Smrg    if (mode->Flags & V_NVSYNC)    ErrorF(" -V");
4025c582b7e3Smrg    ErrorF("\n");
4026c582b7e3Smrg#endif
4027c582b7e3Smrg
4028c582b7e3Smrg    info->Flags = mode->Flags;
4029c582b7e3Smrg
4030c582b7e3Smrg    if(info->IsSecondary)
4031c582b7e3Smrg    {
4032c582b7e3Smrg        if (!R128InitCrtc2Registers(pScrn, save,
4033c582b7e3Smrg             pScrn->currentMode,info))
4034c582b7e3Smrg            return FALSE;
4035c582b7e3Smrg        R128InitPLL2Registers(save, &info->pll, dot_clock);
4036c582b7e3Smrg        if (!R128InitDDA2Registers(pScrn, save, &info->pll, info, mode))
4037c582b7e3Smrg	    return FALSE;
4038c582b7e3Smrg    }
4039c582b7e3Smrg    else
4040c582b7e3Smrg    {
4041c582b7e3Smrg        R128InitCommonRegisters(save, info);
4042c582b7e3Smrg        if(!R128InitCrtcRegisters(pScrn, save, mode, info))
4043c582b7e3Smrg            return FALSE;
4044c582b7e3Smrg        if(dot_clock)
4045c582b7e3Smrg        {
4046c582b7e3Smrg            R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock);
4047c582b7e3Smrg            if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode))
4048c582b7e3Smrg	        return FALSE;
4049c582b7e3Smrg        }
4050c582b7e3Smrg        else
4051c582b7e3Smrg        {
4052c582b7e3Smrg            save->ppll_ref_div         = info->SavedReg.ppll_ref_div;
4053c582b7e3Smrg            save->ppll_div_3           = info->SavedReg.ppll_div_3;
4054c582b7e3Smrg            save->htotal_cntl          = info->SavedReg.htotal_cntl;
4055c582b7e3Smrg            save->dda_config           = info->SavedReg.dda_config;
4056c582b7e3Smrg            save->dda_on_off           = info->SavedReg.dda_on_off;
4057c582b7e3Smrg        }
4058c582b7e3Smrg        /* not used for now */
4059c582b7e3Smrg        /*if (!info->PaletteSavedOnVT) RADEONInitPalette(save);*/
4060c582b7e3Smrg    }
4061c582b7e3Smrg
4062c582b7e3Smrg    if (((info->DisplayType == MT_DFP) ||
4063c582b7e3Smrg        (info->DisplayType == MT_LCD)))
4064c582b7e3Smrg    {
4065c582b7e3Smrg        R128InitFPRegisters(&info->SavedReg, save, mode, info);
4066c582b7e3Smrg    }
4067c582b7e3Smrg
4068c582b7e3Smrg    R128TRACE(("R128Init returns %p\n", save));
4069c582b7e3Smrg    return TRUE;
4070c582b7e3Smrg}
4071c582b7e3Smrg
4072c582b7e3Smrg/* Initialize a new mode. */
4073c582b7e3Smrgstatic Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
4074c582b7e3Smrg{
4075c582b7e3Smrg    R128InfoPtr info      = R128PTR(pScrn);
4076c582b7e3Smrg
4077c582b7e3Smrg    if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE;
4078c582b7e3Smrg				/* FIXME?  DRILock/DRIUnlock here? */
4079c582b7e3Smrg    pScrn->vtSema = TRUE;
4080c582b7e3Smrg    R128Blank(pScrn);
4081c582b7e3Smrg    R128RestoreMode(pScrn, &info->ModeReg);
4082c582b7e3Smrg    R128Unblank(pScrn);
4083c582b7e3Smrg
4084c582b7e3Smrg    info->CurrentLayout.mode = mode;
4085c582b7e3Smrg
4086c582b7e3Smrg    return TRUE;
4087c582b7e3Smrg}
4088c582b7e3Smrg
4089c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode)
4090c582b7e3Smrg{
4091c582b7e3Smrg    ScrnInfoPtr   pScrn = xf86Screens[pScreen->myNum];
4092c582b7e3Smrg    Bool unblank;
4093c582b7e3Smrg
4094c582b7e3Smrg    unblank = xf86IsUnblank(mode);
4095c582b7e3Smrg    if (unblank)
4096c582b7e3Smrg	SetTimeSinceLastInputEvent();
4097c582b7e3Smrg
4098c582b7e3Smrg    if ((pScrn != NULL) && pScrn->vtSema) {
4099c582b7e3Smrg	if (unblank)
4100c582b7e3Smrg		R128Unblank(pScrn);
4101c582b7e3Smrg	else
4102c582b7e3Smrg		R128Blank(pScrn);
4103c582b7e3Smrg    }
4104c582b7e3Smrg    return TRUE;
4105c582b7e3Smrg}
4106c582b7e3Smrg
4107c582b7e3Smrg/*
4108c582b7e3Smrg * SwitchMode() doesn't work right on crtc2 on some laptops.
4109c582b7e3Smrg * The workaround is to switch the mode, then switch to another VT, then
4110c582b7e3Smrg * switch back. --AGD
4111c582b7e3Smrg */
4112c582b7e3SmrgBool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
4113c582b7e3Smrg{
4114c582b7e3Smrg    ScrnInfoPtr   pScrn       = xf86Screens[scrnIndex];
4115c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
4116c582b7e3Smrg    Bool ret;
4117c582b7e3Smrg
4118c582b7e3Smrg    info->SwitchingMode = TRUE;
4119c582b7e3Smrg    ret = R128ModeInit(xf86Screens[scrnIndex], mode);
4120c582b7e3Smrg    info->SwitchingMode = FALSE;
4121c582b7e3Smrg    return ret;
4122c582b7e3Smrg}
4123c582b7e3Smrg
4124c582b7e3Smrg/* Used to disallow modes that are not supported by the hardware. */
4125c582b7e3SmrgModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode,
4126c582b7e3Smrg                                   Bool verbose, int flags)
4127c582b7e3Smrg{
4128c582b7e3Smrg    ScrnInfoPtr   pScrn = xf86Screens[scrnIndex];
4129c582b7e3Smrg    R128InfoPtr   info  = R128PTR(pScrn);
4130c582b7e3Smrg
4131c582b7e3Smrg    if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT)
4132c582b7e3Smrg	return MODE_OK;
4133c582b7e3Smrg
4134c582b7e3Smrg    if(info->isDFP) {
4135c582b7e3Smrg        if(info->PanelXRes < mode->CrtcHDisplay ||
4136c582b7e3Smrg           info->PanelYRes < mode->CrtcVDisplay)
4137c582b7e3Smrg            return MODE_NOMODE;
4138c582b7e3Smrg        else
4139c582b7e3Smrg            return MODE_OK;
4140c582b7e3Smrg    }
4141c582b7e3Smrg
4142c582b7e3Smrg    if (info->DisplayType == MT_LCD) {
4143c582b7e3Smrg	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
4144c582b7e3Smrg	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
4145c582b7e3Smrg    }
4146c582b7e3Smrg
4147c582b7e3Smrg    if (info->DisplayType == MT_LCD &&
4148c582b7e3Smrg	info->VBIOS) {
4149c582b7e3Smrg	int i;
4150c582b7e3Smrg	for (i = info->FPBIOSstart+64; R128_BIOS16(i) != 0; i += 2) {
4151c582b7e3Smrg	    int j = R128_BIOS16(i);
4152c582b7e3Smrg
4153c582b7e3Smrg	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
4154c582b7e3Smrg		mode->CrtcVDisplay == R128_BIOS16(j+2)) {
4155c582b7e3Smrg		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
4156c582b7e3Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4157c582b7e3Smrg			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
4158c582b7e3Smrg			       mode->CrtcHDisplay,mode->CrtcVDisplay,
4159c582b7e3Smrg			       (float)mode->Clock/1000);
4160c582b7e3Smrg
4161c582b7e3Smrg		    /* Assume we are using expanded mode */
4162c582b7e3Smrg		    if (R128_BIOS16(j+5)) j  = R128_BIOS16(j+5);
4163c582b7e3Smrg		    else                  j += 9;
4164c582b7e3Smrg
4165c582b7e3Smrg		    mode->Clock = (CARD32)R128_BIOS16(j) * 10;
4166c582b7e3Smrg
4167c582b7e3Smrg		    mode->HDisplay   = mode->CrtcHDisplay   =
4168c582b7e3Smrg			((R128_BIOS16(j+10) & 0x01ff)+1)*8;
4169c582b7e3Smrg		    mode->HSyncStart = mode->CrtcHSyncStart =
4170c582b7e3Smrg			((R128_BIOS16(j+12) & 0x01ff)+1)*8;
4171c582b7e3Smrg		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
4172c582b7e3Smrg			mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f);
4173c582b7e3Smrg		    mode->HTotal     = mode->CrtcHTotal     =
4174c582b7e3Smrg			((R128_BIOS16(j+8)  & 0x01ff)+1)*8;
4175c582b7e3Smrg
4176c582b7e3Smrg		    mode->VDisplay   = mode->CrtcVDisplay   =
4177c582b7e3Smrg			(R128_BIOS16(j+17) & 0x07ff)+1;
4178c582b7e3Smrg		    mode->VSyncStart = mode->CrtcVSyncStart =
4179c582b7e3Smrg			(R128_BIOS16(j+19) & 0x07ff)+1;
4180c582b7e3Smrg		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
4181c582b7e3Smrg			mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f);
4182c582b7e3Smrg		    mode->VTotal     = mode->CrtcVTotal     =
4183c582b7e3Smrg			(R128_BIOS16(j+15) & 0x07ff)+1;
4184c582b7e3Smrg		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
4185c582b7e3Smrg			       mode->CrtcHDisplay,mode->CrtcVDisplay,
4186c582b7e3Smrg			       (float)mode->Clock/1000);
4187c582b7e3Smrg		}
4188c582b7e3Smrg		return MODE_OK;
4189c582b7e3Smrg	    }
4190c582b7e3Smrg	}
4191c582b7e3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
4192c582b7e3Smrg		       "Mode rejected for FP %ix%i [pclk: %.1f] "
4193c582b7e3Smrg		       "(not listed in VBIOS)\n",
4194c582b7e3Smrg		       mode->CrtcHDisplay, mode->CrtcVDisplay,
4195c582b7e3Smrg		       (float)mode->Clock / 1000);
4196c582b7e3Smrg	return MODE_NOMODE;
4197c582b7e3Smrg    }
4198c582b7e3Smrg
4199c582b7e3Smrg    return MODE_OK;
4200c582b7e3Smrg}
4201c582b7e3Smrg
4202c582b7e3Smrg/* Adjust viewport into virtual desktop such that (0,0) in viewport space
4203c582b7e3Smrg   is (x,y) in virtual space. */
4204c582b7e3Smrgvoid R128AdjustFrame(int scrnIndex, int x, int y, int flags)
4205c582b7e3Smrg{
4206c582b7e3Smrg    ScrnInfoPtr   pScrn     = xf86Screens[scrnIndex];
4207c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
4208c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
4209c582b7e3Smrg    int           Base;
4210c582b7e3Smrg
4211c582b7e3Smrg    if(info->showCache && y && pScrn->vtSema)
4212c582b7e3Smrg        y += pScrn->virtualY - 1;
4213c582b7e3Smrg
4214c582b7e3Smrg    Base = y * info->CurrentLayout.displayWidth + x;
4215c582b7e3Smrg
4216c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
4217c582b7e3Smrg    case 15:
4218c582b7e3Smrg    case 16: Base *= 2; break;
4219c582b7e3Smrg    case 24: Base *= 3; break;
4220c582b7e3Smrg    case 32: Base *= 4; break;
4221c582b7e3Smrg    }
4222c582b7e3Smrg
4223c582b7e3Smrg    Base &= ~7;                 /* 3 lower bits are always 0 */
4224c582b7e3Smrg
4225c582b7e3Smrg    if (info->CurrentLayout.pixel_code == 24)
4226c582b7e3Smrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
4227c582b7e3Smrg
4228c582b7e3Smrg    if(info->IsSecondary)
4229c582b7e3Smrg    {
4230c582b7e3Smrg        Base += pScrn->fbOffset;
4231c582b7e3Smrg        OUTREG(R128_CRTC2_OFFSET, Base);
4232c582b7e3Smrg    }
4233c582b7e3Smrg    else
4234c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET, Base);
4235c582b7e3Smrg
4236c582b7e3Smrg}
4237c582b7e3Smrg
4238c582b7e3Smrg/* Called when VT switching back to the X server.  Reinitialize the video
4239c582b7e3Smrg   mode. */
4240c582b7e3SmrgBool R128EnterVT(int scrnIndex, int flags)
4241c582b7e3Smrg{
4242c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4243c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
4244c582b7e3Smrg
4245c582b7e3Smrg    R128TRACE(("R128EnterVT\n"));
4246c582b7e3Smrg    if (info->FBDev) {
4247c582b7e3Smrg        if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE;
4248c582b7e3Smrg    } else
4249c582b7e3Smrg        if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
4250c582b7e3Smrg    if (info->accelOn)
4251c582b7e3Smrg	R128EngineInit(pScrn);
4252c582b7e3Smrg
4253c582b7e3Smrg#ifdef XF86DRI
4254c582b7e3Smrg    if (info->directRenderingEnabled) {
4255c582b7e3Smrg	if (info->irq) {
4256c582b7e3Smrg	    /* Need to make sure interrupts are enabled */
4257c582b7e3Smrg	    unsigned char *R128MMIO = info->MMIO;
4258c582b7e3Smrg	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
4259c582b7e3Smrg	}
4260c582b7e3Smrg	R128CCE_START(pScrn, info);
4261c582b7e3Smrg	DRIUnlock(pScrn->pScreen);
4262c582b7e3Smrg    }
4263c582b7e3Smrg#endif
4264c582b7e3Smrg
4265c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
4266c582b7e3Smrg    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
4267c582b7e3Smrg
4268c582b7e3Smrg    return TRUE;
4269c582b7e3Smrg}
4270c582b7e3Smrg
4271c582b7e3Smrg/* Called when VT switching away from the X server.  Restore the original
4272c582b7e3Smrg   text mode. */
4273c582b7e3Smrgvoid R128LeaveVT(int scrnIndex, int flags)
4274c582b7e3Smrg{
4275c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4276c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
4277c582b7e3Smrg    R128SavePtr save  = &info->ModeReg;
4278c582b7e3Smrg
4279c582b7e3Smrg    R128TRACE(("R128LeaveVT\n"));
4280c582b7e3Smrg#ifdef XF86DRI
4281c582b7e3Smrg    if (info->directRenderingEnabled) {
4282c582b7e3Smrg	DRILock(pScrn->pScreen, 0);
4283c582b7e3Smrg	R128CCE_STOP(pScrn, info);
4284c582b7e3Smrg    }
4285c582b7e3Smrg#endif
4286c582b7e3Smrg    R128SavePalette(pScrn, save);
4287c582b7e3Smrg    info->PaletteSavedOnVT = TRUE;
4288c582b7e3Smrg    if (info->FBDev)
4289c582b7e3Smrg        fbdevHWLeaveVT(scrnIndex,flags);
4290c582b7e3Smrg    else
4291c582b7e3Smrg        R128Restore(pScrn);
4292c582b7e3Smrg}
4293c582b7e3Smrg
4294c582b7e3Smrg
4295c582b7e3Smrg/* Called at the end of each server generation.  Restore the original text
4296c582b7e3Smrg   mode, unmap video memory, and unwrap and call the saved CloseScreen
4297c582b7e3Smrg   function.  */
4298c582b7e3Smrgstatic Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen)
4299c582b7e3Smrg{
4300c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4301c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
4302c582b7e3Smrg
4303c582b7e3Smrg    R128TRACE(("R128CloseScreen\n"));
4304c582b7e3Smrg
4305c582b7e3Smrg#ifdef XF86DRI
4306c582b7e3Smrg				/* Disable direct rendering */
4307c582b7e3Smrg    if (info->directRenderingEnabled) {
4308c582b7e3Smrg	R128DRICloseScreen(pScreen);
4309c582b7e3Smrg	info->directRenderingEnabled = FALSE;
4310c582b7e3Smrg    }
4311c582b7e3Smrg#endif
4312c582b7e3Smrg
4313c582b7e3Smrg    if (pScrn->vtSema) {
4314c582b7e3Smrg	R128Restore(pScrn);
4315c582b7e3Smrg	R128UnmapMem(pScrn);
4316c582b7e3Smrg    }
4317c582b7e3Smrg
4318c582b7e3Smrg    if (info->accel)             XAADestroyInfoRec(info->accel);
4319c582b7e3Smrg    info->accel                  = NULL;
4320c582b7e3Smrg
4321c582b7e3Smrg    if (info->scratch_save)      xfree(info->scratch_save);
4322c582b7e3Smrg    info->scratch_save           = NULL;
4323c582b7e3Smrg
4324c582b7e3Smrg    if (info->cursor)            xf86DestroyCursorInfoRec(info->cursor);
4325c582b7e3Smrg    info->cursor                 = NULL;
4326c582b7e3Smrg
4327c582b7e3Smrg    if (info->DGAModes)          xfree(info->DGAModes);
4328c582b7e3Smrg    info->DGAModes               = NULL;
4329c582b7e3Smrg
4330c582b7e3Smrg    if (info->adaptor) {
4331c582b7e3Smrg        xfree(info->adaptor->pPortPrivates[0].ptr);
4332c582b7e3Smrg	xf86XVFreeVideoAdaptorRec(info->adaptor);
4333c582b7e3Smrg	info->adaptor = NULL;
4334c582b7e3Smrg    }
4335c582b7e3Smrg
4336c582b7e3Smrg    pScrn->vtSema = FALSE;
4337c582b7e3Smrg
4338c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
4339c582b7e3Smrg    pScreen->CloseScreen = info->CloseScreen;
4340c582b7e3Smrg    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
4341c582b7e3Smrg}
4342c582b7e3Smrg
4343c582b7e3Smrgvoid R128FreeScreen(int scrnIndex, int flags)
4344c582b7e3Smrg{
4345c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4346c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
4347c582b7e3Smrg
4348c582b7e3Smrg    R128TRACE(("R128FreeScreen\n"));
434919019ffeSmrg    if (info == NULL)
435019019ffeSmrg	return;
4351c582b7e3Smrg#ifdef WITH_VGAHW
4352c582b7e3Smrg    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
4353c582b7e3Smrg	vgaHWFreeHWRec(pScrn);
4354c582b7e3Smrg#endif
4355c582b7e3Smrg    R128FreeRec(pScrn);
4356c582b7e3Smrg}
4357c582b7e3Smrg
4358c582b7e3Smrg/* Sets VESA Display Power Management Signaling (DPMS) Mode.  */
4359c582b7e3Smrgstatic void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn,
4360c582b7e3Smrg					  int PowerManagementMode, int flags)
4361c582b7e3Smrg{
4362c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
4363c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
4364c582b7e3Smrg    int           mask      = (R128_CRTC_DISPLAY_DIS
4365c582b7e3Smrg			       | R128_CRTC_HSYNC_DIS
4366c582b7e3Smrg			       | R128_CRTC_VSYNC_DIS);
4367c582b7e3Smrg    int             mask2     = R128_CRTC2_DISP_DIS;
4368c582b7e3Smrg
4369c582b7e3Smrg    switch (PowerManagementMode) {
4370c582b7e3Smrg    case DPMSModeOn:
4371c582b7e3Smrg	/* Screen: On; HSync: On, VSync: On */
4372c582b7e3Smrg	if (info->IsSecondary)
4373c582b7e3Smrg		OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask2);
4374c582b7e3Smrg	else
4375c582b7e3Smrg		OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask);
4376c582b7e3Smrg	break;
4377c582b7e3Smrg    case DPMSModeStandby:
4378c582b7e3Smrg	/* Screen: Off; HSync: Off, VSync: On */
4379c582b7e3Smrg	if (info->IsSecondary)
4380c582b7e3Smrg		OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2);
4381c582b7e3Smrg	    else
4382c582b7e3Smrg		OUTREGP(R128_CRTC_EXT_CNTL,
4383c582b7e3Smrg			R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask);
4384c582b7e3Smrg	break;
4385c582b7e3Smrg    case DPMSModeSuspend:
4386c582b7e3Smrg	/* Screen: Off; HSync: On, VSync: Off */
4387c582b7e3Smrg	if (info->IsSecondary)
4388c582b7e3Smrg		OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2);
4389c582b7e3Smrg	else
4390c582b7e3Smrg		OUTREGP(R128_CRTC_EXT_CNTL,
4391c582b7e3Smrg			R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask);
4392c582b7e3Smrg	break;
4393c582b7e3Smrg    case DPMSModeOff:
4394c582b7e3Smrg	/* Screen: Off; HSync: Off, VSync: Off */
4395c582b7e3Smrg	if (info->IsSecondary)
4396c582b7e3Smrg		OUTREGP(R128_CRTC2_GEN_CNTL, mask2, ~mask2);
4397c582b7e3Smrg	else
4398c582b7e3Smrg		OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask);
4399c582b7e3Smrg	break;
4400c582b7e3Smrg    }
4401c582b7e3Smrg    if(info->isDFP) {
4402c582b7e3Smrg	switch (PowerManagementMode) {
4403c582b7e3Smrg	case DPMSModeOn:
4404c582b7e3Smrg	    OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) | (R128_FP_FPON | R128_FP_TDMS_EN));
4405c582b7e3Smrg	    break;
4406c582b7e3Smrg	case DPMSModeStandby:
4407c582b7e3Smrg	case DPMSModeSuspend:
4408c582b7e3Smrg	case DPMSModeOff:
4409c582b7e3Smrg	    OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) & ~(R128_FP_FPON | R128_FP_TDMS_EN));
4410c582b7e3Smrg	    break;
4411c582b7e3Smrg	}
4412c582b7e3Smrg    }
4413c582b7e3Smrg}
4414c582b7e3Smrg
4415c582b7e3Smrgstatic int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on);
4416c582b7e3Smrg
4417c582b7e3Smrgstatic void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn,
4418c582b7e3Smrg					  int PowerManagementMode, int flags)
4419c582b7e3Smrg{
4420c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
4421c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
4422c582b7e3Smrg    int           mask      = R128_LVDS_DISPLAY_DIS;
4423c582b7e3Smrg
4424c582b7e3Smrg    switch (PowerManagementMode) {
4425c582b7e3Smrg    case DPMSModeOn:
4426c582b7e3Smrg	/* Screen: On; HSync: On, VSync: On */
4427c582b7e3Smrg	OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask);
4428c582b7e3Smrg        r128_set_backlight_enable(pScrn, 1);
4429c582b7e3Smrg	break;
4430c582b7e3Smrg    case DPMSModeStandby:
4431c582b7e3Smrg	/* Fall through */
4432c582b7e3Smrg    case DPMSModeSuspend:
4433c582b7e3Smrg	/* Fall through */
4434c582b7e3Smrg	break;
4435c582b7e3Smrg    case DPMSModeOff:
4436c582b7e3Smrg	/* Screen: Off; HSync: Off, VSync: Off */
4437c582b7e3Smrg	OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask);
4438c582b7e3Smrg        r128_set_backlight_enable(pScrn, 0);
4439c582b7e3Smrg	break;
4440c582b7e3Smrg    }
4441c582b7e3Smrg}
4442c582b7e3Smrg
4443c582b7e3Smrgstatic int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on)
4444c582b7e3Smrg{
4445c582b7e3Smrg        R128InfoPtr info        = R128PTR(pScrn);
4446c582b7e3Smrg        unsigned char *R128MMIO = info->MMIO;
4447c582b7e3Smrg	unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL);
4448c582b7e3Smrg
4449c582b7e3Smrg	lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON);
4450c582b7e3Smrg	if (on) {
4451c582b7e3Smrg		lvds_gen_cntl |= R128_LVDS_DIGON;
4452c582b7e3Smrg		if (!(lvds_gen_cntl & R128_LVDS_ON)) {
4453c582b7e3Smrg			lvds_gen_cntl &= ~R128_LVDS_BLON;
4454c582b7e3Smrg			OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4455c582b7e3Smrg			(void)INREG(R128_LVDS_GEN_CNTL);
4456c582b7e3Smrg			usleep(10000);
4457c582b7e3Smrg			lvds_gen_cntl |= R128_LVDS_BLON;
4458c582b7e3Smrg			OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4459c582b7e3Smrg		}
4460c582b7e3Smrg#if 0
4461c582b7e3Smrg		lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK;
4462c582b7e3Smrg		lvds_gen_cntl |= (0xFF /* backlight_conv[level] */ <<
4463c582b7e3Smrg				  R128_LVDS_BL_MOD_LEVEL_SHIFT);
4464c582b7e3Smrg#endif
4465c582b7e3Smrg		lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_EN);
4466c582b7e3Smrg		lvds_gen_cntl &= ~R128_LVDS_DISPLAY_DIS;
4467c582b7e3Smrg	} else {
4468c582b7e3Smrg#if 0
4469c582b7e3Smrg		lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK;
4470c582b7e3Smrg		lvds_gen_cntl |= (0xFF /* backlight_conv[0] */ <<
4471c582b7e3Smrg				  R128_LVDS_BL_MOD_LEVEL_SHIFT);
4472c582b7e3Smrg#endif
4473c582b7e3Smrg		lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS;
4474c582b7e3Smrg		OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4475c582b7e3Smrg		usleep(10);
4476c582b7e3Smrg		lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON
4477c582b7e3Smrg				   | R128_LVDS_DIGON);
4478c582b7e3Smrg	}
4479c582b7e3Smrg
4480c582b7e3Smrg	OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4481c582b7e3Smrg
4482c582b7e3Smrg	return 0;
4483c582b7e3Smrg}
4484