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
7484354367Smrg#ifdef R128DRI
75c582b7e3Smrg#define _XF86DRI_SERVER_
76c582b7e3Smrg#include "r128_dri.h"
77c582b7e3Smrg#include "r128_common.h"
78c582b7e3Smrg#include "r128_sarea.h"
79c582b7e3Smrg#endif
80c582b7e3Smrg
81c582b7e3Smrg				/* colormap initialization */
82c582b7e3Smrg#include "micmap.h"
83c582b7e3Smrg
84c582b7e3Smrg				/* X and server generic header files */
85c582b7e3Smrg#include "xf86.h"
86c582b7e3Smrg#include "xf86_OSproc.h"
87b3ff493bSmrg#include "xf86RandR12.h"
8819019ffeSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
89c582b7e3Smrg#include "xf86RAC.h"
90c582b7e3Smrg#include "xf86Resources.h"
9119019ffeSmrg#endif
92a9060c92Schristos#include "xf86_OSlib.h"
93c582b7e3Smrg#include "xf86cmap.h"
94c582b7e3Smrg#include "xf86xv.h"
95c582b7e3Smrg#include "vbe.h"
9699d7194aSmacallan#include "xf86Priv.h"
97a4470643Smrg#include "xf86Privstr.h"
98c582b7e3Smrg
99c582b7e3Smrg				/* fbdevhw & vgahw */
100c582b7e3Smrg#ifdef WITH_VGAHW
101c582b7e3Smrg#include "vgaHW.h"
102c582b7e3Smrg#endif
10379e5230eSmacallan
10479e5230eSmacallan#ifndef AVOID_FBDEV
105c582b7e3Smrg#include "fbdevhw.h"
10679e5230eSmacallan#endif
10779e5230eSmacallan
108c582b7e3Smrg#include "dixstruct.h"
109c582b7e3Smrg
110c582b7e3Smrg				/* DPMS support. */
11119019ffeSmrg#ifdef HAVE_XEXTPROTO_71
11219019ffeSmrg#include <X11/extensions/dpmsconst.h>
11319019ffeSmrg#else
114c582b7e3Smrg#define DPMS_SERVER
115c582b7e3Smrg#include <X11/extensions/dpms.h>
11619019ffeSmrg#endif
11719019ffeSmrg
11899d7194aSmacallan#ifdef __NetBSD__
11999d7194aSmacallan#include <sys/time.h>
12099d7194aSmacallan#include <dev/wscons/wsconsio.h>
12199d7194aSmacallan#endif
122c582b7e3Smrg
12384354367Smrgstatic Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL);
124c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode);
125c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn);
126c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn);
127c582b7e3Smrg
128c582b7e3Smrgtypedef enum {
129c582b7e3Smrg  OPTION_NOACCEL,
13081f79626Smrg#ifndef AVOID_FBDEV
13181f79626Smrg  OPTION_FBDEV,
13281f79626Smrg#endif
133c582b7e3Smrg  OPTION_DAC_6BIT,
13481f79626Smrg  OPTION_VGA_ACCESS,
13581f79626Smrg  OPTION_SHOW_CACHE,
13681f79626Smrg  OPTION_SW_CURSOR,
13781f79626Smrg  OPTION_VIDEO_KEY,
13881f79626Smrg  OPTION_PANEL_WIDTH,
13981f79626Smrg  OPTION_PANEL_HEIGHT,
14081f79626Smrg  OPTION_PROG_FP_REGS,
14184354367Smrg#ifdef R128DRI
142c582b7e3Smrg  OPTION_XV_DMA,
143c582b7e3Smrg  OPTION_IS_PCI,
144c582b7e3Smrg  OPTION_CCE_PIO,
145c582b7e3Smrg  OPTION_NO_SECURITY,
146c582b7e3Smrg  OPTION_USEC_TIMEOUT,
147c582b7e3Smrg  OPTION_AGP_MODE,
148c582b7e3Smrg  OPTION_AGP_SIZE,
149c582b7e3Smrg  OPTION_RING_SIZE,
150c582b7e3Smrg  OPTION_BUFFER_SIZE,
151c582b7e3Smrg  OPTION_PAGE_FLIP,
152c582b7e3Smrg#endif
15384354367Smrg  OPTION_ACCELMETHOD,
15484354367Smrg  OPTION_RENDERACCEL
155c582b7e3Smrg} R128Opts;
156c582b7e3Smrg
157c582b7e3Smrgstatic const OptionInfoRec R128Options[] = {
15881f79626Smrg{ OPTION_NOACCEL,      "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
15981f79626Smrg#ifndef AVOID_FBDEV
16081f79626Smrg{ OPTION_FBDEV,        "UseFBDev",         OPTV_BOOLEAN, {0}, FALSE },
16181f79626Smrg#endif
16281f79626Smrg{ OPTION_DAC_6BIT,     "Dac6Bit",          OPTV_BOOLEAN, {0}, FALSE },
16381f79626Smrg{ OPTION_VGA_ACCESS,   "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
16481f79626Smrg{ OPTION_SHOW_CACHE,   "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
16581f79626Smrg{ OPTION_SW_CURSOR,    "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
16681f79626Smrg{ OPTION_VIDEO_KEY,    "VideoKey",         OPTV_INTEGER, {0}, FALSE },
16781f79626Smrg{ OPTION_PANEL_WIDTH,  "PanelWidth",       OPTV_INTEGER, {0}, FALSE },
16881f79626Smrg{ OPTION_PANEL_HEIGHT, "PanelHeight",      OPTV_INTEGER, {0}, FALSE },
16981f79626Smrg{ OPTION_PROG_FP_REGS, "ProgramFPRegs",    OPTV_BOOLEAN, {0}, FALSE },
17084354367Smrg#ifdef R128DRI
171c582b7e3Smrg  { OPTION_XV_DMA,       "DMAForXv",         OPTV_BOOLEAN, {0}, FALSE },
172c582b7e3Smrg  { OPTION_IS_PCI,       "ForcePCIMode",     OPTV_BOOLEAN, {0}, FALSE },
173c582b7e3Smrg  { OPTION_CCE_PIO,      "CCEPIOMode",       OPTV_BOOLEAN, {0}, FALSE },
174c582b7e3Smrg  { OPTION_NO_SECURITY,  "CCENoSecurity",    OPTV_BOOLEAN, {0}, FALSE },
175c582b7e3Smrg  { OPTION_USEC_TIMEOUT, "CCEusecTimeout",   OPTV_INTEGER, {0}, FALSE },
176c582b7e3Smrg  { OPTION_AGP_MODE,     "AGPMode",          OPTV_INTEGER, {0}, FALSE },
177c582b7e3Smrg  { OPTION_AGP_SIZE,     "AGPSize",          OPTV_INTEGER, {0}, FALSE },
178c582b7e3Smrg  { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
179c582b7e3Smrg  { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
180c582b7e3Smrg  { OPTION_PAGE_FLIP,    "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
181c582b7e3Smrg#endif
18284354367Smrg  { OPTION_ACCELMETHOD,  "AccelMethod",      OPTV_STRING,  {0}, FALSE },
18384354367Smrg  { OPTION_RENDERACCEL,  "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
184c582b7e3Smrg  { -1,                  NULL,               OPTV_NONE,    {0}, FALSE }
185c582b7e3Smrg};
186c582b7e3Smrg
187c582b7e3Smrgconst OptionInfoRec *R128OptionsWeak(void) { return R128Options; }
188c582b7e3Smrg
189c582b7e3SmrgR128RAMRec R128RAM[] = {        /* Memory Specifications
190c582b7e3Smrg				   From RAGE 128 Software Development
191c582b7e3Smrg				   Manual (Technical Reference Manual P/N
192c582b7e3Smrg				   SDK-G04000 Rev 0.01), page 3-21.  */
193c582b7e3Smrg    { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
194c582b7e3Smrg    { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
195c582b7e3Smrg    { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
196c582b7e3Smrg    { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
197c582b7e3Smrg};
198c582b7e3Smrg
199c582b7e3Smrgextern _X_EXPORT int gR128EntityIndex;
200c582b7e3Smrg
201c582b7e3Smrgint getR128EntityIndex(void)
202c582b7e3Smrg{
203c582b7e3Smrg    return gR128EntityIndex;
204c582b7e3Smrg}
205c582b7e3Smrg
206c582b7e3SmrgR128EntPtr R128EntPriv(ScrnInfoPtr pScrn)
207c582b7e3Smrg{
208c582b7e3Smrg    DevUnion     *pPriv;
209c582b7e3Smrg    R128InfoPtr  info   = R128PTR(pScrn);
210c582b7e3Smrg    pPriv = xf86GetEntityPrivate(info->pEnt->index,
211c582b7e3Smrg                                 getR128EntityIndex());
212c582b7e3Smrg    return pPriv->ptr;
213c582b7e3Smrg}
214c582b7e3Smrg
215c582b7e3Smrg/* Allocate our private R128InfoRec. */
216c582b7e3Smrgstatic Bool R128GetRec(ScrnInfoPtr pScrn)
217c582b7e3Smrg{
218c582b7e3Smrg    if (pScrn->driverPrivate) return TRUE;
219c582b7e3Smrg
220c582b7e3Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1);
221c582b7e3Smrg    return TRUE;
222c582b7e3Smrg}
223c582b7e3Smrg
224c582b7e3Smrg/* Free our private R128InfoRec. */
225c582b7e3Smrgstatic void R128FreeRec(ScrnInfoPtr pScrn)
226c582b7e3Smrg{
227c582b7e3Smrg    if (!pScrn || !pScrn->driverPrivate) return;
22884354367Smrg    free(pScrn->driverPrivate);
229c582b7e3Smrg    pScrn->driverPrivate = NULL;
230c582b7e3Smrg}
231c582b7e3Smrg
232c582b7e3Smrg/* Memory map the MMIO region.  Used during pre-init and by R128MapMem,
233c582b7e3Smrg   below. */
234c582b7e3Smrgstatic Bool R128MapMMIO(ScrnInfoPtr pScrn)
235c582b7e3Smrg{
236c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
237c582b7e3Smrg
23879e5230eSmacallan#ifndef AVOID_FBDEV
239c582b7e3Smrg    if (info->FBDev) {
240c582b7e3Smrg	info->MMIO = fbdevHWMapMMIO(pScrn);
24179e5230eSmacallan    } else
24279e5230eSmacallan#endif
24379e5230eSmacallan    {
244c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
245c582b7e3Smrg	info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
246c582b7e3Smrg				   VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
247c582b7e3Smrg				   info->PciTag,
248c582b7e3Smrg				   info->MMIOAddr,
249c582b7e3Smrg				   R128_MMIOSIZE);
250b3ff493bSmrg        if (!info->MMIO) return FALSE;
251c582b7e3Smrg#else
252c582b7e3Smrg	int err = pci_device_map_range(info->PciInfo,
253c582b7e3Smrg				       info->MMIOAddr,
254c582b7e3Smrg				       R128_MMIOSIZE,
255c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE,
256c582b7e3Smrg				       &info->MMIO);
257c582b7e3Smrg
258c582b7e3Smrg	if (err) {
259c582b7e3Smrg	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
260c582b7e3Smrg                        "Unable to map MMIO aperture. %s (%d)\n",
261c582b7e3Smrg                        strerror (err), err);
262c582b7e3Smrg	    return FALSE;
263c582b7e3Smrg	}
264c582b7e3Smrg#endif
265c582b7e3Smrg    }
266c582b7e3Smrg
267c582b7e3Smrg    return TRUE;
268c582b7e3Smrg}
269c582b7e3Smrg
270c582b7e3Smrg/* Unmap the MMIO region.  Used during pre-init and by R128UnmapMem,
271c582b7e3Smrg   below. */
272c582b7e3Smrgstatic Bool R128UnmapMMIO(ScrnInfoPtr pScrn)
273c582b7e3Smrg{
274c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
275c582b7e3Smrg
27679e5230eSmacallan#ifndef AVOID_FBDEV
277c582b7e3Smrg    if (info->FBDev)
278c582b7e3Smrg	fbdevHWUnmapMMIO(pScrn);
27979e5230eSmacallan    else
28079e5230eSmacallan#endif
28179e5230eSmacallan    {
282c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
283c582b7e3Smrg	xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE);
284c582b7e3Smrg#else
285c582b7e3Smrg	pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE);
286c582b7e3Smrg#endif
287c582b7e3Smrg    }
288c582b7e3Smrg    info->MMIO = NULL;
289c582b7e3Smrg    return TRUE;
290c582b7e3Smrg}
291c582b7e3Smrg
292c582b7e3Smrg/* Memory map the frame buffer.  Used by R128MapMem, below. */
293c582b7e3Smrgstatic Bool R128MapFB(ScrnInfoPtr pScrn)
294c582b7e3Smrg{
295c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
296c582b7e3Smrg
29779e5230eSmacallan#ifndef AVOID_FBDEV
298c582b7e3Smrg    if (info->FBDev) {
299c582b7e3Smrg	info->FB = fbdevHWMapVidmem(pScrn);
30079e5230eSmacallan    } else
30179e5230eSmacallan#endif
30279e5230eSmacallan    {
303c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
304c582b7e3Smrg	info->FB = xf86MapPciMem(pScrn->scrnIndex,
305c582b7e3Smrg				 VIDMEM_FRAMEBUFFER,
306c582b7e3Smrg				 info->PciTag,
307c582b7e3Smrg				 info->LinearAddr,
308c582b7e3Smrg				 info->FbMapSize);
309c582b7e3Smrg#else
310c582b7e3Smrg	int err = pci_device_map_range(info->PciInfo,
311c582b7e3Smrg				       info->LinearAddr,
312c582b7e3Smrg				       info->FbMapSize,
313c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE |
314c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
315c582b7e3Smrg				       &info->FB);
316c582b7e3Smrg
317c582b7e3Smrg	if (err) {
318c582b7e3Smrg	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
319c582b7e3Smrg                        "Unable to map FB aperture. %s (%d)\n",
320c582b7e3Smrg                        strerror (err), err);
321c582b7e3Smrg	    return FALSE;
322c582b7e3Smrg	}
323c582b7e3Smrg#endif
324c582b7e3Smrg    }
325c582b7e3Smrg
326c582b7e3Smrg    if (!info->FB) return FALSE;
327c582b7e3Smrg    return TRUE;
328c582b7e3Smrg}
329c582b7e3Smrg
330c582b7e3Smrg/* Unmap the frame buffer.  Used by R128UnmapMem, below. */
331c582b7e3Smrgstatic Bool R128UnmapFB(ScrnInfoPtr pScrn)
332c582b7e3Smrg{
333c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
334c582b7e3Smrg
33579e5230eSmacallan#ifndef AVOID_FBDEV
336c582b7e3Smrg    if (info->FBDev)
337c582b7e3Smrg	fbdevHWUnmapVidmem(pScrn);
338c582b7e3Smrg    else
33979e5230eSmacallan#endif
340c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
341c582b7e3Smrg	xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
342c582b7e3Smrg#else
343c582b7e3Smrg	pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize);
344c582b7e3Smrg#endif
345c582b7e3Smrg    info->FB = NULL;
346c582b7e3Smrg    return TRUE;
347c582b7e3Smrg}
348c582b7e3Smrg
349c582b7e3Smrg/* Memory map the MMIO region and the frame buffer. */
350c582b7e3Smrgstatic Bool R128MapMem(ScrnInfoPtr pScrn)
351c582b7e3Smrg{
352c582b7e3Smrg    if (!R128MapMMIO(pScrn)) return FALSE;
353c582b7e3Smrg    if (!R128MapFB(pScrn)) {
354c582b7e3Smrg	R128UnmapMMIO(pScrn);
355c582b7e3Smrg	return FALSE;
356c582b7e3Smrg    }
357c582b7e3Smrg    return TRUE;
358c582b7e3Smrg}
359c582b7e3Smrg
360c582b7e3Smrg/* Unmap the MMIO region and the frame buffer. */
361c582b7e3Smrgstatic Bool R128UnmapMem(ScrnInfoPtr pScrn)
362c582b7e3Smrg{
363c582b7e3Smrg    if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE;
364c582b7e3Smrg    return TRUE;
365c582b7e3Smrg}
366c582b7e3Smrg
367c582b7e3Smrg/* Read PLL information */
368c582b7e3Smrgunsigned R128INPLL(ScrnInfoPtr pScrn, int addr)
369c582b7e3Smrg{
370c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
371c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
372c582b7e3Smrg
373c582b7e3Smrg    OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f);
374c582b7e3Smrg    return INREG(R128_CLOCK_CNTL_DATA);
375c582b7e3Smrg}
376c582b7e3Smrg
377c582b7e3Smrg#if 0
378c582b7e3Smrg/* Read PAL information (only used for debugging). */
379c582b7e3Smrgstatic int R128INPAL(int idx)
380c582b7e3Smrg{
381c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
382c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
383c582b7e3Smrg
384c582b7e3Smrg    OUTREG(R128_PALETTE_INDEX, idx << 16);
385c582b7e3Smrg    return INREG(R128_PALETTE_DATA);
386c582b7e3Smrg}
387c582b7e3Smrg#endif
388c582b7e3Smrg
389c582b7e3Smrg/* Wait for vertical sync. */
390c582b7e3Smrgvoid R128WaitForVerticalSync(ScrnInfoPtr pScrn)
391c582b7e3Smrg{
392c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
393c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
394c582b7e3Smrg    int           i;
395c582b7e3Smrg
396c582b7e3Smrg    OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK);
397c582b7e3Smrg    for (i = 0; i < R128_TIMEOUT; i++) {
398c582b7e3Smrg	if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break;
399c582b7e3Smrg    }
400c582b7e3Smrg}
401c582b7e3Smrg
402c582b7e3Smrg/* Compute log base 2 of val. */
403c582b7e3Smrgint R128MinBits(int val)
404c582b7e3Smrg{
405c582b7e3Smrg    int bits;
406c582b7e3Smrg
407c582b7e3Smrg    if (!val) return 1;
408c582b7e3Smrg    for (bits = 0; val; val >>= 1, ++bits);
409c582b7e3Smrg    return bits;
410c582b7e3Smrg}
411c582b7e3Smrg
412b3ff493bSmrg/* Finds the first output using a given crtc. */
413b3ff493bSmrgxf86OutputPtr R128FirstOutput(xf86CrtcPtr crtc)
414b3ff493bSmrg{
415b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
416b3ff493bSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
417b3ff493bSmrg    xf86OutputPtr output = xf86_config->output[0];
418b3ff493bSmrg    int o;
419b3ff493bSmrg
420b3ff493bSmrg    for (o = 0; o < xf86_config->num_output; o++) {
421b3ff493bSmrg        output = xf86_config->output[o];
422b3ff493bSmrg        if (output->crtc == crtc) break;
423b3ff493bSmrg    }
424b3ff493bSmrg
425b3ff493bSmrg    return output;
426b3ff493bSmrg}
427b3ff493bSmrg
428b3ff493bSmrg/* Read the Video BIOS block. */
429c582b7e3Smrgstatic Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
430c582b7e3Smrg{
431c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
432c582b7e3Smrg
433c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS
434c582b7e3Smrg    int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE;
43584354367Smrg    info->VBIOS = malloc(size);
436c582b7e3Smrg#else
43784354367Smrg    info->VBIOS = malloc(R128_VBIOS_SIZE);
438c582b7e3Smrg#endif
439c582b7e3Smrg
440c582b7e3Smrg    if (!info->VBIOS) {
441c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
442c582b7e3Smrg		   "Cannot allocate space for hold Video BIOS!\n");
443c582b7e3Smrg	return FALSE;
444c582b7e3Smrg    }
445c582b7e3Smrg
446c582b7e3Smrg    if (pInt10) {
447c582b7e3Smrg	info->BIOSAddr = pInt10->BIOSseg << 4;
448c582b7e3Smrg	(void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
449c582b7e3Smrg		     R128_VBIOS_SIZE);
450c582b7e3Smrg    } else {
451c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS
452c582b7e3Smrg	if (pci_device_read_rom(info->PciInfo, info->VBIOS)) {
453c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
454c582b7e3Smrg		       "Failed to read PCI ROM!\n");
455c582b7e3Smrg	}
456c582b7e3Smrg#else
457c582b7e3Smrg	xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE);
458c582b7e3Smrg	if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
459c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
460c582b7e3Smrg		       "Video BIOS not detected in PCI space!\n");
461c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
462c582b7e3Smrg		       "Attempting to read Video BIOS from legacy ISA space!\n");
463c582b7e3Smrg	    info->BIOSAddr = 0x000c0000;
464c582b7e3Smrg	    xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS);
465c582b7e3Smrg	}
466c582b7e3Smrg#endif
467c582b7e3Smrg    }
468c582b7e3Smrg    if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
469c582b7e3Smrg	info->BIOSAddr = 0x00000000;
47084354367Smrg	free(info->VBIOS);
471c582b7e3Smrg	info->VBIOS = NULL;
472c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
473c582b7e3Smrg		   "Video BIOS not found!\n");
474c582b7e3Smrg    }
475c582b7e3Smrg
476b3ff493bSmrg    return TRUE;
477b3ff493bSmrg}
478c582b7e3Smrg
479b3ff493bSmrg/* Read the FP parameters if an LVDS panel is expected. */
480b3ff493bSmrgvoid R128GetPanelInfoFromBIOS(xf86OutputPtr output)
481b3ff493bSmrg{
482b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
483b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
484b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
485b3ff493bSmrg    int FPHeader = 0;
486b3ff493bSmrg    int i;
487c582b7e3Smrg
488b3ff493bSmrg    r128_output->PanelPwrDly = 200;
489b3ff493bSmrg    xf86GetOptValInteger(info->Options, OPTION_PANEL_WIDTH,  &(r128_output->PanelXRes));
490b3ff493bSmrg    xf86GetOptValInteger(info->Options, OPTION_PANEL_HEIGHT, &(r128_output->PanelYRes));
491b3ff493bSmrg
492449624caSmacallan    if (!info->VBIOS) goto fallback;
493b3ff493bSmrg    info->FPBIOSstart = 0;
494b3ff493bSmrg
495b3ff493bSmrg    /* FIXME: There should be direct access to the start of the FP info
496b3ff493bSmrg     * tables, but until we find out where that offset is stored, we
497b3ff493bSmrg     * must search for the ATI signature string: "M3      ".
498b3ff493bSmrg     */
499b3ff493bSmrg    for (i = 4; i < R128_VBIOS_SIZE - 8; i++) {
500b3ff493bSmrg        if (R128_BIOS8(i)     == 'M' &&
501b3ff493bSmrg            R128_BIOS8(i + 1) == '3' &&
502b3ff493bSmrg            R128_BIOS8(i + 2) == ' ' &&
503b3ff493bSmrg            R128_BIOS8(i + 3) == ' ' &&
504b3ff493bSmrg            R128_BIOS8(i + 4) == ' ' &&
505b3ff493bSmrg            R128_BIOS8(i + 5) == ' ' &&
506b3ff493bSmrg            R128_BIOS8(i + 6) == ' ' &&
507b3ff493bSmrg            R128_BIOS8(i + 7) == ' ') {
508b3ff493bSmrg            FPHeader = i - 2;
509b3ff493bSmrg            break;
510b3ff493bSmrg        }
511b3ff493bSmrg    }
512b3ff493bSmrg
513449624caSmacallan    if (!FPHeader) goto fallback;
514b3ff493bSmrg
515b3ff493bSmrg
516b3ff493bSmrg    /* Assume that only one panel is attached and supported */
517b3ff493bSmrg    for (i = FPHeader + 20; i < FPHeader + 84; i += 2) {
518b3ff493bSmrg        if (R128_BIOS16(i) != 0) {
519b3ff493bSmrg            info->FPBIOSstart = R128_BIOS16(i);
520b3ff493bSmrg            break;
521b3ff493bSmrg        }
522c582b7e3Smrg    }
523c582b7e3Smrg
524b3ff493bSmrg#ifndef AVOID_FBDEV
525b3ff493bSmrg    if (!info->FPBIOSstart) return;
526b3ff493bSmrg#endif
527b3ff493bSmrg
528b3ff493bSmrg    if (!r128_output->PanelXRes)
529b3ff493bSmrg        r128_output->PanelXRes = R128_BIOS16(info->FPBIOSstart + 25);
530b3ff493bSmrg    if (!r128_output->PanelYRes)
531b3ff493bSmrg        r128_output->PanelYRes = R128_BIOS16(info->FPBIOSstart + 27);
532b3ff493bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n",
533b3ff493bSmrg               r128_output->PanelXRes, r128_output->PanelYRes);
534b3ff493bSmrg
535b3ff493bSmrg    r128_output->PanelPwrDly = R128_BIOS8(info->FPBIOSstart + 56);
536b3ff493bSmrg
537b3ff493bSmrg    if (!r128_output->PanelXRes || !r128_output->PanelYRes) {
538c582b7e3Smrg        info->HasPanelRegs = FALSE;
539c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
540c582b7e3Smrg		   "Can't determine panel dimensions, and none specified.\n"
541c582b7e3Smrg		   "\tDisabling programming of FP registers.\n");
542c582b7e3Smrg    }
543c582b7e3Smrg
544b3ff493bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: ");
545b3ff493bSmrg    for (i = 1; i <= 24; i++)
546b3ff493bSmrg        ErrorF("%c", R128_BIOS8(info->FPBIOSstart + i));
547b3ff493bSmrg
548b3ff493bSmrg    ErrorF("\n");
549b3ff493bSmrg
550b3ff493bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: ");
551b3ff493bSmrg    i = R128_BIOS16(info->FPBIOSstart + 29);
552b3ff493bSmrg    if (i & 1) ErrorF("Color, ");
553b3ff493bSmrg    else       ErrorF("Monochrome, ");
554b3ff493bSmrg    if (i & 2) ErrorF("Dual(split), ");
555b3ff493bSmrg    else       ErrorF("Single, ");
556b3ff493bSmrg
557b3ff493bSmrg    switch ((i >> 2) & 0x3f) {
558b3ff493bSmrg    case 0:  ErrorF("STN");        break;
559b3ff493bSmrg    case 1:  ErrorF("TFT");        break;
560b3ff493bSmrg    case 2:  ErrorF("Active STN"); break;
561b3ff493bSmrg    case 3:  ErrorF("EL");         break;
562b3ff493bSmrg    case 4:  ErrorF("Plasma");     break;
563b3ff493bSmrg    default: ErrorF("UNKNOWN");    break;
564b3ff493bSmrg    }
565b3ff493bSmrg
566b3ff493bSmrg    ErrorF("\n");
567b3ff493bSmrg
568b3ff493bSmrg    if (R128_BIOS8(info->FPBIOSstart + 61) & 1) {
569b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n");
570b3ff493bSmrg    } else {
571b3ff493bSmrg        /* FIXME: Add Non-LVDS flat pael support */
572b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
573b3ff493bSmrg                   "Non-LVDS panel interface detected!  "
574b3ff493bSmrg                   "This support is untested and may not "
575b3ff493bSmrg                   "function properly\n");
576b3ff493bSmrg    }
577449624caSmacallan    return;
578449624caSmacallanfallback:
579449624caSmacallan#ifdef __NetBSD__
580e1efbb8aSmacallan    if ((!r128_output->PanelXRes || !r128_output->PanelYRes)  &&
581e1efbb8aSmacallan        (info->HaveWSDisplay)) {
582449624caSmacallan	/*
583449624caSmacallan	 * we may not be on x86 so check wsdisplay for panel dimensions
584449624caSmacallan	 * XXX this assumes that the r128 is the console, although that should
585449624caSmacallan	 * be the case in the vast majority of cases where an LCD is hooked up
586449624caSmacallan	 * directly
587449624caSmacallan	 * We should probably just check the relevant registers but I'm not
588449624caSmacallan	 * sure they're available at this point.
589449624caSmacallan	 */
590449624caSmacallan	struct wsdisplay_fbinfo fbinfo;
591449624caSmacallan
592a4470643Smrg	if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GINFO, &fbinfo) == 0) {
593449624caSmacallan	    r128_output->PanelXRes = fbinfo.width;
594449624caSmacallan	    r128_output->PanelYRes = fbinfo.height;
595449624caSmacallan	}
596449624caSmacallan    }
597449624caSmacallan#endif
598c582b7e3Smrg}
599c582b7e3Smrg
600c582b7e3Smrg/* Read PLL parameters from BIOS block.  Default to typical values if there
601c582b7e3Smrg   is no BIOS. */
602c582b7e3Smrgstatic Bool R128GetPLLParameters(ScrnInfoPtr pScrn)
603c582b7e3Smrg{
604c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
605c582b7e3Smrg    R128PLLPtr    pll  = &info->pll;
606c582b7e3Smrg
607c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__)
608c582b7e3Smrg    /* there is no bios under Linux PowerPC but Open Firmware
609c582b7e3Smrg       does set up the PLL registers properly and we can use
610c582b7e3Smrg       those to calculate xclk and find the reference divider */
611c582b7e3Smrg
612c582b7e3Smrg    unsigned x_mpll_ref_fb_div;
613c582b7e3Smrg    unsigned xclk_cntl;
614c582b7e3Smrg    unsigned Nx, M;
615c582b7e3Smrg    unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12};
616c582b7e3Smrg
617c582b7e3Smrg    /* Assume REF clock is 2950 (in units of 10khz) */
618c582b7e3Smrg    /* and that all pllclk must be between 125 Mhz and 250Mhz */
619c582b7e3Smrg    pll->reference_freq = 2950;
620c582b7e3Smrg    pll->min_pll_freq   = 12500;
621c582b7e3Smrg    pll->max_pll_freq   = 25000;
622c582b7e3Smrg
623c582b7e3Smrg    x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV);
624c582b7e3Smrg    xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7;
625c582b7e3Smrg    pll->reference_div =
626c582b7e3Smrg	INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK;
627c582b7e3Smrg
628c582b7e3Smrg    Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8;
629c582b7e3Smrg    M =  (x_mpll_ref_fb_div & 0x0000FF);
630c582b7e3Smrg
631c582b7e3Smrg    pll->xclk =  R128Div((2 * Nx * pll->reference_freq),
632c582b7e3Smrg			 (M * PostDivSet[xclk_cntl]));
633c582b7e3Smrg
634c582b7e3Smrg#else /* !defined(__powerpc__) */
635c582b7e3Smrg
636c582b7e3Smrg    if (!info->VBIOS) {
637c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
638c582b7e3Smrg		   "Video BIOS not detected, using default PLL parameters!\n");
639c582b7e3Smrg				/* These probably aren't going to work for
640c582b7e3Smrg				   the card you are using.  Specifically,
641c582b7e3Smrg				   reference freq can be 29.50MHz,
642c582b7e3Smrg				   28.63MHz, or 14.32MHz.  YMMV. */
643c582b7e3Smrg	pll->reference_freq = 2950;
644c582b7e3Smrg	pll->reference_div  = 65;
645c582b7e3Smrg	pll->min_pll_freq   = 12500;
646c582b7e3Smrg	pll->max_pll_freq   = 25000;
647c582b7e3Smrg	pll->xclk           = 10300;
648c582b7e3Smrg    } else {
649b3ff493bSmrg	uint16_t bios_header    = R128_BIOS16(0x48);
650b3ff493bSmrg	uint16_t pll_info_block = R128_BIOS16(bios_header + 0x30);
65181f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
65281f79626Smrg                        "Header at 0x%04x; PLL Information at 0x%04x\n",
65381f79626Smrg                        bios_header, pll_info_block));
654c582b7e3Smrg
655c582b7e3Smrg	pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e);
656c582b7e3Smrg	pll->reference_div  = R128_BIOS16(pll_info_block + 0x10);
657c582b7e3Smrg	pll->min_pll_freq   = R128_BIOS32(pll_info_block + 0x12);
658c582b7e3Smrg	pll->max_pll_freq   = R128_BIOS32(pll_info_block + 0x16);
659c582b7e3Smrg	pll->xclk           = R128_BIOS16(pll_info_block + 0x08);
660c582b7e3Smrg    }
661c582b7e3Smrg#endif /* __powerpc__ */
662c582b7e3Smrg
663c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
664c582b7e3Smrg	       "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
665c582b7e3Smrg	       pll->reference_freq,
666c582b7e3Smrg	       pll->reference_div,
667c582b7e3Smrg	       pll->min_pll_freq,
668c582b7e3Smrg	       pll->max_pll_freq,
669c582b7e3Smrg	       pll->xclk);
670c582b7e3Smrg
671c582b7e3Smrg    return TRUE;
672c582b7e3Smrg}
673c582b7e3Smrg
674c582b7e3Smrg/* This is called by R128PreInit to set up the default visual. */
675c582b7e3Smrgstatic Bool R128PreInitVisual(ScrnInfoPtr pScrn)
676c582b7e3Smrg{
677c582b7e3Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb
678c582b7e3Smrg					  | Support32bppFb
679c582b7e3Smrg					  | SupportConvert32to24
680c582b7e3Smrg					  )))
681c582b7e3Smrg	return FALSE;
682c582b7e3Smrg
683c582b7e3Smrg    switch (pScrn->depth) {
684c582b7e3Smrg    case 8:
685c582b7e3Smrg    case 15:
686c582b7e3Smrg    case 16:
687c582b7e3Smrg    case 24:
688c582b7e3Smrg	break;
689c582b7e3Smrg    default:
690c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
691c582b7e3Smrg		   "Given depth (%d) is not supported by %s driver\n",
692c582b7e3Smrg		   pScrn->depth, R128_DRIVER_NAME);
693c582b7e3Smrg	return FALSE;
694c582b7e3Smrg    }
695c582b7e3Smrg
696c582b7e3Smrg    xf86PrintDepthBpp(pScrn);
697c582b7e3Smrg
698c582b7e3Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
699c582b7e3Smrg
700c582b7e3Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
701c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
702c582b7e3Smrg		   "Default visual (%s) is not supported at depth %d\n",
703c582b7e3Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
704c582b7e3Smrg	return FALSE;
705c582b7e3Smrg    }
706c582b7e3Smrg    return TRUE;
707c582b7e3Smrg
708c582b7e3Smrg}
709c582b7e3Smrg
710c582b7e3Smrg/* This is called by R128PreInit to handle all color weight issues. */
711c582b7e3Smrgstatic Bool R128PreInitWeight(ScrnInfoPtr pScrn)
712c582b7e3Smrg{
713c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
71481f79626Smrg    rgb defaultWeight = { 0, 0, 0 };
715c582b7e3Smrg
71681f79626Smrg    /*
71781f79626Smrg     * Save flag for 6 bit DAC to use for setting CRTC registers.
71881f79626Smrg     * Otherwise use an 8 bit DAC, even if xf86SetWeight sets
71981f79626Smrg     * pScrn->rgbBits to some value other than 8.
72081f79626Smrg     */
72181f79626Smrg    if (pScrn->depth <= 8) {
72281f79626Smrg        if (info->dac6bits) {
72381f79626Smrg            pScrn->rgbBits = 6;
72481f79626Smrg        } else {
72581f79626Smrg            pScrn->rgbBits = 8;
72681f79626Smrg        }
727c582b7e3Smrg    } else {
72881f79626Smrg        info->dac6bits = FALSE;
72981f79626Smrg        pScrn->rgbBits = 8;
73081f79626Smrg    }
73181f79626Smrg
73281f79626Smrg    if (pScrn->depth > 8) {
73381f79626Smrg        if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
734c582b7e3Smrg    }
73581f79626Smrg
736c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
73781f79626Smrg               "Using %d bits per RGB (%d bit DAC)\n",
73881f79626Smrg               pScrn->rgbBits, info->dac6bits ? 6 : 8);
739c582b7e3Smrg
740c582b7e3Smrg    return TRUE;
741c582b7e3Smrg}
742c582b7e3Smrg
743c582b7e3Smrg/* This is called by R128PreInit to handle config file overrides for things
744c582b7e3Smrg   like chipset and memory regions.  Also determine memory size and type.
745c582b7e3Smrg   If memory type ever needs an override, put it in this routine. */
746c582b7e3Smrgstatic Bool R128PreInitConfig(ScrnInfoPtr pScrn)
747c582b7e3Smrg{
748c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
749b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
750c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
751c582b7e3Smrg    EntityInfoPtr pEnt      = info->pEnt;
752c582b7e3Smrg    GDevPtr       dev       = pEnt->device;
753c582b7e3Smrg    int           offset    = 0;        /* RAM Type */
754c582b7e3Smrg    MessageType   from;
755c582b7e3Smrg
756c582b7e3Smrg				/* Chipset */
757c582b7e3Smrg    from = X_PROBED;
758c582b7e3Smrg    if (dev->chipset && *dev->chipset) {
759c582b7e3Smrg	info->Chipset  = xf86StringToToken(R128Chipsets, dev->chipset);
760c582b7e3Smrg	from           = X_CONFIG;
761c582b7e3Smrg    } else if (dev->chipID >= 0) {
762c582b7e3Smrg	info->Chipset  = dev->chipID;
763c582b7e3Smrg	from           = X_CONFIG;
764c582b7e3Smrg    } else {
765c582b7e3Smrg	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
766c582b7e3Smrg    }
767c582b7e3Smrg    pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset);
768c582b7e3Smrg
769c582b7e3Smrg    if (!pScrn->chipset) {
770c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
771c582b7e3Smrg		   "ChipID 0x%04x is not recognized\n", info->Chipset);
772c582b7e3Smrg	return FALSE;
773c582b7e3Smrg    }
774c582b7e3Smrg
775c582b7e3Smrg    if (info->Chipset < 0) {
776c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
777c582b7e3Smrg		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
778c582b7e3Smrg	return FALSE;
779c582b7e3Smrg    }
780c582b7e3Smrg
781c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
782c582b7e3Smrg	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
783c582b7e3Smrg	       pScrn->chipset,
784c582b7e3Smrg	       info->Chipset);
785c582b7e3Smrg
786c582b7e3Smrg				/* Framebuffer */
787c582b7e3Smrg
788c582b7e3Smrg    from             = X_PROBED;
789c582b7e3Smrg    info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000;
790c582b7e3Smrg    pScrn->memPhysBase = info->LinearAddr;
791c582b7e3Smrg    if (dev->MemBase) {
792c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
793c582b7e3Smrg		   "Linear address override, using 0x%08lx instead of 0x%08lx\n",
794c582b7e3Smrg		   dev->MemBase,
795c582b7e3Smrg		   info->LinearAddr);
796c582b7e3Smrg	info->LinearAddr = dev->MemBase;
797c582b7e3Smrg	from             = X_CONFIG;
798c582b7e3Smrg    } else if (!info->LinearAddr) {
799c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
800c582b7e3Smrg		   "No valid linear framebuffer address\n");
801c582b7e3Smrg	return FALSE;
802c582b7e3Smrg    }
803c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
804c582b7e3Smrg	       "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
805c582b7e3Smrg
806c582b7e3Smrg				/* MMIO registers */
807c582b7e3Smrg    from             = X_PROBED;
808c582b7e3Smrg    info->MMIOAddr   = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00;
809c582b7e3Smrg    if (dev->IOBase) {
810c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
811c582b7e3Smrg		   "MMIO address override, using 0x%08lx instead of 0x%08lx\n",
812c582b7e3Smrg		   dev->IOBase,
813c582b7e3Smrg		   info->MMIOAddr);
814c582b7e3Smrg	info->MMIOAddr = dev->IOBase;
815c582b7e3Smrg	from           = X_CONFIG;
816c582b7e3Smrg    } else if (!info->MMIOAddr) {
817c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
818c582b7e3Smrg	return FALSE;
819c582b7e3Smrg    }
820c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
821c582b7e3Smrg	       "MMIO registers at 0x%08lx\n", info->MMIOAddr);
822c582b7e3Smrg
823c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
824c582b7e3Smrg				/* BIOS */
825c582b7e3Smrg    from              = X_PROBED;
826c582b7e3Smrg    info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
827c582b7e3Smrg    if (info->BIOSAddr) {
828c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, from,
829c582b7e3Smrg		   "BIOS at 0x%08lx\n", info->BIOSAddr);
830c582b7e3Smrg    }
831c582b7e3Smrg#endif
832c582b7e3Smrg
833c582b7e3Smrg				/* Flat panel (part 1) */
834c582b7e3Smrg    if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS,
835c582b7e3Smrg			  &info->HasPanelRegs)) {
836c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
837c582b7e3Smrg		   "Turned flat panel register programming %s\n",
838c582b7e3Smrg		   info->HasPanelRegs ? "on" : "off");
839c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
840c582b7e3Smrg		   "\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");
841c582b7e3Smrg    } else {
842c582b7e3Smrg        info->isDFP = FALSE;
843c582b7e3Smrg        info->isPro2 = FALSE;
844b3ff493bSmrg        pR128Ent->HasCRTC2 = FALSE;
845c582b7e3Smrg	switch (info->Chipset) {
846c582b7e3Smrg	/* R128 Pro and Pro2 can have DFP, we will deal with it.
847c582b7e3Smrg	   No support for dual-head/xinerama yet.
848c582b7e3Smrg           M3 can also have DFP, no support for now */
849c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
850c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
851c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
852c582b7e3Smrg	/* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came
853c582b7e3Smrg	 *        out at the same time, so are of the same family likely.
854c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
855c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
856c582b7e3Smrg	 */
857c582b7e3Smrg	case PCI_CHIP_RAGE128TS:
858c582b7e3Smrg	case PCI_CHIP_RAGE128TT:
859c582b7e3Smrg	case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE;
860c582b7e3Smrg	/* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP
861c582b7e3Smrg	 *        capability, as the comment at the top suggests.
862c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
863c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
864c582b7e3Smrg	 */
865c582b7e3Smrg	case PCI_CHIP_RAGE128PA:
866c582b7e3Smrg	case PCI_CHIP_RAGE128PB:
867c582b7e3Smrg	case PCI_CHIP_RAGE128PC:
868c582b7e3Smrg	case PCI_CHIP_RAGE128PE:
869c582b7e3Smrg	case PCI_CHIP_RAGE128PG:
870c582b7e3Smrg	case PCI_CHIP_RAGE128PH:
871c582b7e3Smrg	case PCI_CHIP_RAGE128PI:
872c582b7e3Smrg	case PCI_CHIP_RAGE128PJ:
873c582b7e3Smrg	case PCI_CHIP_RAGE128PK:
874c582b7e3Smrg	case PCI_CHIP_RAGE128PL:
875c582b7e3Smrg	case PCI_CHIP_RAGE128PM:
876c582b7e3Smrg	case PCI_CHIP_RAGE128PN:
877c582b7e3Smrg	case PCI_CHIP_RAGE128PO:
878c582b7e3Smrg	case PCI_CHIP_RAGE128PQ:
879c582b7e3Smrg	case PCI_CHIP_RAGE128PS:
880c582b7e3Smrg	case PCI_CHIP_RAGE128PT:
881c582b7e3Smrg	case PCI_CHIP_RAGE128PU:
882c582b7e3Smrg	case PCI_CHIP_RAGE128PV:
883c582b7e3Smrg	case PCI_CHIP_RAGE128PW:
884c582b7e3Smrg	case PCI_CHIP_RAGE128PX:
885c582b7e3Smrg
886c582b7e3Smrg	case PCI_CHIP_RAGE128PD:
887c582b7e3Smrg	case PCI_CHIP_RAGE128PF:
888c582b7e3Smrg	case PCI_CHIP_RAGE128PP:
889c582b7e3Smrg	case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break;
890c582b7e3Smrg
891c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
892c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
893c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
894c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
895d6cc4c59Smacallan			info->HasPanelRegs = TRUE;
896d6cc4c59Smacallan			info->isDFP = TRUE;
897c582b7e3Smrg			/* which chips support dualhead? */
898b3ff493bSmrg			pR128Ent->HasCRTC2 = TRUE;
899c582b7e3Smrg			break;
900c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
901c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
902c582b7e3Smrg	case PCI_CHIP_RAGE128RG:
903c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
904c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
905c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
906c582b7e3Smrg	/* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as
907c582b7e3Smrg	 *        all of them are listed as "Rage 128 4x" in ATI docs.
908c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
909c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
910c582b7e3Smrg	 */
911c582b7e3Smrg	case PCI_CHIP_RAGE128SE:
912c582b7e3Smrg	case PCI_CHIP_RAGE128SF:
913c582b7e3Smrg	case PCI_CHIP_RAGE128SG:
914c582b7e3Smrg	case PCI_CHIP_RAGE128SH:
915c582b7e3Smrg	case PCI_CHIP_RAGE128SK:
916c582b7e3Smrg	case PCI_CHIP_RAGE128SL:
917c582b7e3Smrg	case PCI_CHIP_RAGE128SN:
918c582b7e3Smrg	default:                 info->HasPanelRegs = FALSE; break;
919c582b7e3Smrg	}
920c582b7e3Smrg    }
921c582b7e3Smrg
922c582b7e3Smrg				/* Read registers used to determine options */
923c582b7e3Smrg    from                      = X_PROBED;
924b3ff493bSmrg    if (!R128MapMMIO(pScrn)) return FALSE;
925c582b7e3Smrg    R128MMIO                  = info->MMIO;
926c582b7e3Smrg
92779e5230eSmacallan#ifndef AVOID_FBDEV
928c582b7e3Smrg    if (info->FBDev)
929c582b7e3Smrg	pScrn->videoRam       = fbdevHWGetVidmem(pScrn) / 1024;
930c582b7e3Smrg    else
93179e5230eSmacallan#endif
932c582b7e3Smrg	pScrn->videoRam       = INREG(R128_CONFIG_MEMSIZE) / 1024;
933c582b7e3Smrg
934c582b7e3Smrg    info->MemCntl             = INREG(R128_MEM_CNTL);
935c582b7e3Smrg    info->BusCntl             = INREG(R128_BUS_CNTL);
936c582b7e3Smrg
937c582b7e3Smrg				/* RAM */
938c582b7e3Smrg    switch (info->MemCntl & 0x3) {
939c582b7e3Smrg    case 0:                     /* SDR SGRAM 1:1 */
940c582b7e3Smrg	switch (info->Chipset) {
941c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
942c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
943c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
944c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
945c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
946c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
947c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
948c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
949c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
950c582b7e3Smrg	case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
951c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
952c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
953c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
954c582b7e3Smrg	default:                 offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
955c582b7e3Smrg	}
956c582b7e3Smrg	break;
957c582b7e3Smrg    case 1:                      offset = 2; break; /*  64-bit SDR SGRAM 2:1 */
958c582b7e3Smrg    case 2:                      offset = 3; break; /*  64-bit DDR SGRAM     */
959c582b7e3Smrg    default:                     offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
960c582b7e3Smrg    }
961c582b7e3Smrg    info->ram = &R128RAM[offset];
962c582b7e3Smrg
963c582b7e3Smrg    if (dev->videoRam) {
964c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
965c582b7e3Smrg		   "Video RAM override, using %d kB instead of %d kB\n",
966c582b7e3Smrg		   dev->videoRam,
967c582b7e3Smrg		   pScrn->videoRam);
968c582b7e3Smrg	from             = X_CONFIG;
969c582b7e3Smrg	pScrn->videoRam  = dev->videoRam;
970c582b7e3Smrg    }
971c582b7e3Smrg
972c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
973c582b7e3Smrg	       "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
974c582b7e3Smrg
975c582b7e3Smrg    pScrn->videoRam  &= ~1023;
976c582b7e3Smrg    info->FbMapSize  = pScrn->videoRam * 1024;
977c582b7e3Smrg
97884354367Smrg#ifdef R128DRI
97981f79626Smrg    /* AGP/PCI */
98081f79626Smrg    if (!info->IsPCI) {
981c582b7e3Smrg	switch (info->Chipset) {
982c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
983c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
984c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
985c582b7e3Smrg	case PCI_CHIP_RAGE128PD:
986c582b7e3Smrg	case PCI_CHIP_RAGE128PR:
987c582b7e3Smrg	case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE;  break;
988c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
989c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
990c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
991c582b7e3Smrg	case PCI_CHIP_RAGE128PF:
992c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
993c582b7e3Smrg	case PCI_CHIP_RAGE128RG:
994c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
995c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
996c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
997c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
998c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
999c582b7e3Smrg	/* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are
1000c582b7e3Smrg	 * believed to be AGP, but need confirmation. <mharris@redhat.com>
1001c582b7e3Smrg	 */
1002c582b7e3Smrg	case PCI_CHIP_RAGE128PA:
1003c582b7e3Smrg	case PCI_CHIP_RAGE128PB:
1004c582b7e3Smrg	case PCI_CHIP_RAGE128PC:
1005c582b7e3Smrg	case PCI_CHIP_RAGE128PE:
1006c582b7e3Smrg	case PCI_CHIP_RAGE128PG:
1007c582b7e3Smrg	case PCI_CHIP_RAGE128PH:
1008c582b7e3Smrg	case PCI_CHIP_RAGE128PI:
1009c582b7e3Smrg	case PCI_CHIP_RAGE128PJ:
1010c582b7e3Smrg	case PCI_CHIP_RAGE128PK:
1011c582b7e3Smrg	case PCI_CHIP_RAGE128PL:
1012c582b7e3Smrg	case PCI_CHIP_RAGE128PM:
1013c582b7e3Smrg	case PCI_CHIP_RAGE128PN:
1014c582b7e3Smrg	case PCI_CHIP_RAGE128PO:
1015c582b7e3Smrg	case PCI_CHIP_RAGE128PQ:
1016c582b7e3Smrg	case PCI_CHIP_RAGE128PS:
1017c582b7e3Smrg	case PCI_CHIP_RAGE128PT:
1018c582b7e3Smrg	case PCI_CHIP_RAGE128PU:
1019c582b7e3Smrg	case PCI_CHIP_RAGE128PV:
1020c582b7e3Smrg	case PCI_CHIP_RAGE128PW:
1021c582b7e3Smrg	case PCI_CHIP_RAGE128PX:
1022c582b7e3Smrg	case PCI_CHIP_RAGE128TS:
1023c582b7e3Smrg	case PCI_CHIP_RAGE128TT:
1024c582b7e3Smrg	case PCI_CHIP_RAGE128TU:
1025c582b7e3Smrg	case PCI_CHIP_RAGE128SE:
1026c582b7e3Smrg	case PCI_CHIP_RAGE128SF:
1027c582b7e3Smrg	case PCI_CHIP_RAGE128SG:
1028c582b7e3Smrg	case PCI_CHIP_RAGE128SH:
1029c582b7e3Smrg	case PCI_CHIP_RAGE128SK:
1030c582b7e3Smrg	case PCI_CHIP_RAGE128SL:
1031c582b7e3Smrg	case PCI_CHIP_RAGE128SN:
1032c582b7e3Smrg	default:                 info->IsPCI = FALSE; break;
1033c582b7e3Smrg	}
1034c582b7e3Smrg    }
1035c582b7e3Smrg#endif
1036c582b7e3Smrg
1037c582b7e3Smrg    return TRUE;
1038c582b7e3Smrg}
1039c582b7e3Smrg
1040c582b7e3Smrgstatic Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1041c582b7e3Smrg{
1042c582b7e3Smrg#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__)
1043c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1044c582b7e3Smrg    vbeInfoPtr pVbe;
1045c582b7e3Smrg#endif
1046c582b7e3Smrg
1047c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE;
1048b3ff493bSmrg    if (!xf86LoadSubModule(pScrn, "i2c")) return FALSE;
1049c582b7e3Smrg
1050c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__)
1051c582b7e3Smrg    /* Int10 is broken on PPC and some Alphas */
1052c582b7e3Smrg    return TRUE;
1053c582b7e3Smrg#else
1054c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1055c582b7e3Smrg	pVbe = VBEInit(pInt10,info->pEnt->index);
1056c582b7e3Smrg	if (!pVbe) return FALSE;
1057c582b7e3Smrg        xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
1058c582b7e3Smrg	vbeFree(pVbe);
1059c582b7e3Smrg	return TRUE;
1060c582b7e3Smrg    } else
1061c582b7e3Smrg	return FALSE;
1062c582b7e3Smrg#endif
1063c582b7e3Smrg}
1064c582b7e3Smrg
1065c582b7e3Smrg/* This is called by R128PreInit to initialize gamma correction. */
1066c582b7e3Smrgstatic Bool R128PreInitGamma(ScrnInfoPtr pScrn)
1067c582b7e3Smrg{
1068c582b7e3Smrg    Gamma zeros = { 0.0, 0.0, 0.0 };
1069c582b7e3Smrg
1070c582b7e3Smrg    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
1071c582b7e3Smrg    return TRUE;
1072c582b7e3Smrg}
1073c582b7e3Smrg
1074c582b7e3Smrg/* This is called by R128PreInit to initialize the hardware cursor. */
1075c582b7e3Smrgstatic Bool R128PreInitCursor(ScrnInfoPtr pScrn)
1076c582b7e3Smrg{
1077c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1078c582b7e3Smrg
107981f79626Smrg    if (!info->swCursor) {
1080c582b7e3Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
1081c582b7e3Smrg    }
1082c582b7e3Smrg    return TRUE;
1083c582b7e3Smrg}
1084c582b7e3Smrg
1085c582b7e3Smrgstatic Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
1086c582b7e3Smrg{
1087c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1088b3ff493bSmrg#if !defined(__powerpc__) && !defined(__alpha__)
1089b3ff493bSmrg    /* int10 is broken on some Alphas and powerpc */
1090c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "int10")) {
1091c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
1092c582b7e3Smrg	*ppInt10 = xf86InitInt10(info->pEnt->index);
1093c582b7e3Smrg    }
1094c582b7e3Smrg#endif
1095c582b7e3Smrg    return TRUE;
1096c582b7e3Smrg}
1097c582b7e3Smrg
109884354367Smrg#ifdef R128DRI
1099c582b7e3Smrgstatic Bool R128PreInitDRI(ScrnInfoPtr pScrn)
1100c582b7e3Smrg{
1101c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1102c582b7e3Smrg
1103c582b7e3Smrg    info->agpMode        = R128_DEFAULT_AGP_MODE;
1104c582b7e3Smrg    info->agpSize        = R128_DEFAULT_AGP_SIZE;
1105c582b7e3Smrg    info->ringSize       = R128_DEFAULT_RING_SIZE;
1106c582b7e3Smrg    info->bufSize        = R128_DEFAULT_BUFFER_SIZE;
1107c582b7e3Smrg    info->agpTexSize     = R128_DEFAULT_AGP_TEX_SIZE;
1108c582b7e3Smrg
1109c582b7e3Smrg    info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
1110c582b7e3Smrg
1111c582b7e3Smrg    if (!info->IsPCI) {
1112c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1113c582b7e3Smrg				 OPTION_AGP_MODE, &(info->agpMode))) {
1114c582b7e3Smrg	    if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
1115c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1116c582b7e3Smrg			   "Illegal AGP Mode: %d\n", info->agpMode);
1117c582b7e3Smrg		return FALSE;
1118c582b7e3Smrg	    }
1119c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1120c582b7e3Smrg		       "Using AGP %dx mode\n", info->agpMode);
1121c582b7e3Smrg	}
1122c582b7e3Smrg
1123c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1124c582b7e3Smrg				 OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
1125c582b7e3Smrg	    switch (info->agpSize) {
1126c582b7e3Smrg	    case 4:
1127c582b7e3Smrg	    case 8:
1128c582b7e3Smrg	    case 16:
1129c582b7e3Smrg	    case 32:
1130c582b7e3Smrg	    case 64:
1131c582b7e3Smrg	    case 128:
1132c582b7e3Smrg	    case 256:
1133c582b7e3Smrg		break;
1134c582b7e3Smrg	    default:
1135c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1136c582b7e3Smrg			   "Illegal AGP size: %d MB\n", info->agpSize);
1137c582b7e3Smrg		return FALSE;
1138c582b7e3Smrg	    }
1139c582b7e3Smrg	}
1140c582b7e3Smrg
1141c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1142c582b7e3Smrg				 OPTION_RING_SIZE, &(info->ringSize))) {
1143c582b7e3Smrg	    if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
1144c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1145c582b7e3Smrg			   "Illegal ring buffer size: %d MB\n",
1146c582b7e3Smrg			   info->ringSize);
1147c582b7e3Smrg		return FALSE;
1148c582b7e3Smrg	    }
1149c582b7e3Smrg	}
1150c582b7e3Smrg
1151c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1152c582b7e3Smrg				 OPTION_BUFFER_SIZE, &(info->bufSize))) {
1153c582b7e3Smrg	    if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
1154c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1155c582b7e3Smrg			   "Illegal vertex/indirect buffers size: %d MB\n",
1156c582b7e3Smrg			   info->bufSize);
1157c582b7e3Smrg		return FALSE;
1158c582b7e3Smrg	    }
1159c582b7e3Smrg	    if (info->bufSize > 2) {
1160c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1161c582b7e3Smrg			   "Illegal vertex/indirect buffers size: %d MB\n",
1162c582b7e3Smrg			   info->bufSize);
1163c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1164c582b7e3Smrg			   "Clamping vertex/indirect buffers size to 2 MB\n");
1165c582b7e3Smrg		info->bufSize = 2;
1166c582b7e3Smrg	    }
1167c582b7e3Smrg	}
1168c582b7e3Smrg
1169c582b7e3Smrg	if (info->ringSize + info->bufSize + info->agpTexSize >
1170c582b7e3Smrg	    (int)info->agpSize) {
1171c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1172c582b7e3Smrg		       "Buffers are too big for requested AGP space\n");
1173c582b7e3Smrg	    return FALSE;
1174c582b7e3Smrg	}
1175c582b7e3Smrg
1176c582b7e3Smrg	info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
1177c582b7e3Smrg    }
1178c582b7e3Smrg
1179c582b7e3Smrg    if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
1180c582b7e3Smrg			     &(info->CCEusecTimeout))) {
1181c582b7e3Smrg	/* This option checked by the R128 DRM kernel module */
1182c582b7e3Smrg    }
1183c582b7e3Smrg
1184c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1185c582b7e3Smrg	info->allowPageFlip = 0;
1186c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1187c582b7e3Smrg		   "Couldn't load shadowfb module:\n");
1188c582b7e3Smrg    } else {
1189c582b7e3Smrg	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1190c582b7e3Smrg						   OPTION_PAGE_FLIP,
1191c582b7e3Smrg						   FALSE);
1192c582b7e3Smrg    }
1193c582b7e3Smrg
1194c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n",
1195c582b7e3Smrg	       info->allowPageFlip ? "en" : "dis");
1196c582b7e3Smrg
1197c582b7e3Smrg    return TRUE;
1198c582b7e3Smrg}
1199c582b7e3Smrg#endif
1200c582b7e3Smrg
1201b3ff493bSmrgstatic Bool R128PreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1202b3ff493bSmrg{
1203b3ff493bSmrg    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1204b3ff493bSmrg    int found = 0;
1205b3ff493bSmrg    int i;
1206b3ff493bSmrg
1207b3ff493bSmrg    if (!R128GetBIOSParameters(pScrn, pInt10))
1208b3ff493bSmrg        return FALSE;
1209b3ff493bSmrg
1210b3ff493bSmrg    if (!R128GetPLLParameters(pScrn))
1211b3ff493bSmrg        return FALSE;
1212b3ff493bSmrg
1213b3ff493bSmrg    if (!R128AllocateControllers(pScrn))
1214b3ff493bSmrg        return FALSE;
1215b3ff493bSmrg
1216b3ff493bSmrg    if (!R128SetupConnectors(pScrn))
1217b3ff493bSmrg        return FALSE;
1218b3ff493bSmrg
1219b3ff493bSmrg    for (i = 0; i < config->num_output; i++) {
1220b3ff493bSmrg        xf86OutputPtr output = config->output[i];
1221b3ff493bSmrg
1222b3ff493bSmrg        output->status = (*output->funcs->detect) (output);
1223b3ff493bSmrg        if (output->status == XF86OutputStatusConnected)
1224b3ff493bSmrg            found++;
1225b3ff493bSmrg    }
1226b3ff493bSmrg    return !!found;
1227b3ff493bSmrg}
1228b3ff493bSmrg
1229c582b7e3Smrgstatic void
123081f79626Smrgr128UMSOption(ScrnInfoPtr pScrn)
1231c582b7e3Smrg{
123281f79626Smrg    R128InfoPtr      info = R128PTR(pScrn);
1233b3ff493bSmrg
123481f79626Smrg    info->dac6bits = xf86ReturnOptValBool(info->Options,
123581f79626Smrg                                            OPTION_DAC_6BIT, FALSE);
123681f79626Smrg
123781f79626Smrg#ifndef AVOID_FBDEV
123881f79626Smrg#ifdef __powerpc__
123981f79626Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE))
124081f79626Smrg#else
124181f79626Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE))
124281f79626Smrg#endif
124381f79626Smrg    {
124481f79626Smrg        info->FBDev = TRUE;
124581f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
124681f79626Smrg                    "Using framebuffer device.\n");
124781f79626Smrg    }
124881f79626Smrg#endif
124981f79626Smrg
125081f79626Smrg    /* By default, don't access VGA IOs on PowerPC or SPARC. */
125181f79626Smrg#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW)
125281f79626Smrg    info->VGAAccess = FALSE;
125381f79626Smrg#else
125481f79626Smrg    info->VGAAccess = TRUE;
125581f79626Smrg#endif
125681f79626Smrg
125781f79626Smrg#ifdef WITH_VGAHW
125881f79626Smrg    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS,
125981f79626Smrg                        &info->VGAAccess);
126081f79626Smrg    if (info->VGAAccess) {
126181f79626Smrg       if (!xf86LoadSubModule(pScrn, "vgahw"))
126281f79626Smrg           info->VGAAccess = FALSE;
126381f79626Smrg        else {
126481f79626Smrg            if (!vgaHWGetHWRec(pScrn))
126581f79626Smrg               info->VGAAccess = FALSE;
126681f79626Smrg       }
126781f79626Smrg
126881f79626Smrg       if (!info->VGAAccess) {
126981f79626Smrg           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
127081f79626Smrg                       "Loading VGA module failed, trying to "
127181f79626Smrg                       "run without it.\n");
127281f79626Smrg       }
127381f79626Smrg    } else
127481f79626Smrg           xf86DrvMsg(pScrn->scrnIndex, X_INFO,
127581f79626Smrg                       "VGAAccess option set to FALSE, VGA "
127681f79626Smrg                       "module load skipped.\n");
127781f79626Smrg    if (info->VGAAccess) {
127881f79626Smrg        vgaHWSetStdFuncs(VGAHWPTR(pScrn));
127981f79626Smrg        vgaHWGetIOBase(VGAHWPTR(pScrn));
128081f79626Smrg    }
128181f79626Smrg#else
128281f79626Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
128381f79626Smrg                "VGAHW support not compiled, VGA "
128481f79626Smrg                "module load skipped.\n");
128581f79626Smrg#endif
128681f79626Smrg
128781f79626Smrg    if (xf86ReturnOptValBool(info->Options,
128881f79626Smrg                                OPTION_SHOW_CACHE, FALSE)) {
128981f79626Smrg        info->showCache = TRUE;
129081f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
129181f79626Smrg                    "ShowCache enabled.\n");
129281f79626Smrg    }
129381f79626Smrg
129481f79626Smrg    if (xf86ReturnOptValBool(info->Options,
129581f79626Smrg                                OPTION_SW_CURSOR, FALSE)) {
129681f79626Smrg        info->swCursor = TRUE;
129781f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
129881f79626Smrg                    "Software cursor requested.\n");
129981f79626Smrg    }
130081f79626Smrg
130181f79626Smrg    if(xf86GetOptValInteger(info->Options,
130281f79626Smrg                            OPTION_VIDEO_KEY, &info->videoKey)) {
130381f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
130481f79626Smrg                    "Video key set to 0x%x.\n", info->videoKey);
130581f79626Smrg    } else {
130681f79626Smrg        info->videoKey = 0x1E;
130781f79626Smrg    }
130881f79626Smrg
130981f79626Smrg#ifdef R128DRI
131081f79626Smrg    /* DMA for Xv */
131181f79626Smrg    info->DMAForXv = xf86ReturnOptValBool(info->Options,
131281f79626Smrg                                            OPTION_XV_DMA, FALSE);
131381f79626Smrg    if (info->DMAForXv) {
131481f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
131581f79626Smrg                   "Will try to use DMA for Xv image transfers.\n");
131681f79626Smrg    }
131781f79626Smrg
131881f79626Smrg    /* Force PCI Mode */
131981f79626Smrg    info->IsPCI = xf86ReturnOptValBool(info->Options,
132081f79626Smrg                                        OPTION_IS_PCI, FALSE);
132181f79626Smrg    if (info->IsPCI) {
132281f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
132381f79626Smrg                    "Forced into PCI only mode.\n");
132481f79626Smrg    }
132581f79626Smrg
132681f79626Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) {
132781f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
132881f79626Smrg                    "Forcing CCE into PIO mode.\n");
132981f79626Smrg        info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
133081f79626Smrg    } else {
133181f79626Smrg        info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
133281f79626Smrg    }
133381f79626Smrg
133481f79626Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
133581f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
133681f79626Smrg                    "WARNING!!! CCE Security checks disabled!!!\n");
133781f79626Smrg        info->CCESecure = FALSE;
133881f79626Smrg    } else {
133981f79626Smrg        info->CCESecure = TRUE;
134081f79626Smrg    }
134181f79626Smrg
134281f79626Smrg
134381f79626Smrg#endif
134481f79626Smrg}
134581f79626Smrg
134681f79626Smrgstatic void
134781f79626Smrgr128AcquireOption(ScrnInfoPtr pScrn)
134881f79626Smrg{
134981f79626Smrg    R128InfoPtr      info = R128PTR(pScrn);
135081f79626Smrg#ifdef USE_EXA
135181f79626Smrg    char *optstr;
135281f79626Smrg#endif
135381f79626Smrg
135481f79626Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
135581f79626Smrg        info->noAccel = TRUE;
135681f79626Smrg    }
135781f79626Smrg
135881f79626Smrg#ifdef USE_EXA
135981f79626Smrg    if (!info->noAccel) {
136081f79626Smrg        optstr = (char *) xf86GetOptValString(info->Options,
136181f79626Smrg                                                OPTION_ACCELMETHOD);
136281f79626Smrg        if (optstr) {
136381f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
136481f79626Smrg                        "AccelMethod option found.\n");
136581f79626Smrg            if (xf86NameCmp(optstr, "EXA") == 0) {
136681f79626Smrg                info->useEXA = TRUE;
136781f79626Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
136881f79626Smrg                            "AccelMethod is set to EXA, turning "
136981f79626Smrg                            "EXA on.\n");
137081f79626Smrg            }
137181f79626Smrg        }
137281f79626Smrg
137381f79626Smrg#ifdef RENDER
137481f79626Smrg        info->RenderAccel = xf86ReturnOptValBool(info->Options,
137581f79626Smrg                                                    OPTION_RENDERACCEL,
137681f79626Smrg                                                    TRUE);
137781f79626Smrg        if (info->RenderAccel)
137881f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
137981f79626Smrg                        "Acceleration of RENDER operations will be "
138081f79626Smrg                        "enabled upon successful loading of DRI and "
138181f79626Smrg                        "EXA.\n");
138281f79626Smrg#endif
1383c582b7e3Smrg    }
1384b3ff493bSmrg#endif
138581f79626Smrg
138681f79626Smrg    r128UMSOption(pScrn);
1387b3ff493bSmrg}
1388b3ff493bSmrg
1389b3ff493bSmrgstatic Bool R128CRTCResize(ScrnInfoPtr pScrn, int width, int height)
1390b3ff493bSmrg{
1391b3ff493bSmrg    pScrn->virtualX = width;
1392b3ff493bSmrg    pScrn->virtualY = height;
1393b3ff493bSmrg    return TRUE;
1394c582b7e3Smrg}
1395c582b7e3Smrg
1396b3ff493bSmrgstatic const xf86CrtcConfigFuncsRec R128CRTCResizeFuncs = {
1397b3ff493bSmrg    R128CRTCResize
1398b3ff493bSmrg};
1399b3ff493bSmrg
140081f79626Smrgstatic Bool R128LegacyMS(ScrnInfoPtr pScrn)
140181f79626Smrg{
140281f79626Smrg    R128InfoPtr      info = R128PTR(pScrn);
140381f79626Smrg    xf86Int10InfoPtr pInt10 = NULL;
140481f79626Smrg    Bool ret = FALSE;
140581f79626Smrg
140681f79626Smrg#ifndef AVOID_FBDEV
140781f79626Smrg    if (info->FBDev) {
140881f79626Smrg        /* check for linux framebuffer device */
140981f79626Smrg        if (!xf86LoadSubModule(pScrn, "fbdevhw")) goto exit;
141081f79626Smrg        if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) goto exit;
141181f79626Smrg        pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
141281f79626Smrg        pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
141381f79626Smrg        pScrn->ValidMode     = fbdevHWValidModeWeak();
141481f79626Smrg    } else {
141581f79626Smrg#endif /* !AVOID_FBDEV */
141681f79626Smrg        if (!R128PreInitInt10(pScrn, &pInt10)) goto exit;
141781f79626Smrg#ifndef AVOID_FBDEV
141881f79626Smrg    }
141981f79626Smrg#endif /* !AVOID_FBDEV */
142081f79626Smrg
142181f79626Smrg    if (!R128PreInitConfig(pScrn)) goto freeInt10;
142281f79626Smrg
142381f79626Smrg    xf86CrtcSetSizeRange(pScrn, 320, 200, 4096, 4096);
142481f79626Smrg
142581f79626Smrg    if (!R128PreInitCursor(pScrn)) goto freeInt10;
142681f79626Smrg
142781f79626Smrg    /* Don't fail on this one */
142881f79626Smrg    info->DDC = R128PreInitDDC(pScrn, pInt10);
142981f79626Smrg
143081f79626Smrg    if (!R128PreInitControllers(pScrn, pInt10)) goto freeInt10;
143181f79626Smrg
143281f79626Smrg#ifdef R128DRI
143381f79626Smrg    if (!R128PreInitDRI(pScrn)) goto freeInt10;
143481f79626Smrg#endif
143581f79626Smrg
143681f79626Smrg    ret = TRUE;
143781f79626SmrgfreeInt10:
143881f79626Smrg    /* Free int10 info */
143981f79626Smrg    if (pInt10) {
144081f79626Smrg        xf86FreeInt10(pInt10);
144181f79626Smrg    }
144281f79626Smrg
144381f79626Smrgexit:
144481f79626Smrg    return ret;
144581f79626Smrg}
144681f79626Smrg
144781f79626Smrgstatic void
144881f79626SmrgR128PreInitAccel(ScrnInfoPtr pScrn)
144981f79626Smrg{
145081f79626Smrg    R128InfoPtr      info = R128PTR(pScrn);
145181f79626Smrg#ifdef USE_EXA
145281f79626Smrg    int errmaj, errmin;
145381f79626Smrg#endif
145481f79626Smrg
145581f79626Smrg    if (!info->noAccel) {
145681f79626Smrg        if (info->useEXA) {
145781f79626Smrg#ifdef USE_EXA
145881f79626Smrg            info->exaReq.majorversion = EXA_VERSION_MAJOR;
145981f79626Smrg            info->exaReq.minorversion = EXA_VERSION_MINOR;
146081f79626Smrg
146181f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
146281f79626Smrg                        "Loading EXA module...\n");
146381f79626Smrg            if (LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
146481f79626Smrg                                &info->exaReq, &errmaj, &errmin)) {
146581f79626Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
146681f79626Smrg                            "Loading EXA module.\n");
146781f79626Smrg            } else {
146881f79626Smrg                LoaderErrorMsg(NULL, "exa", errmaj, errmin);
146981f79626Smrg            }
147081f79626Smrg#endif
147181f79626Smrg        }
147281f79626Smrg
147381f79626Smrg        if ((!info->useEXA) ||
147481f79626Smrg            ((info->useEXA) && (!info->accelOn))) {
147581f79626Smrg#ifdef HAVE_XAA_H
147681f79626Smrg            if (xf86LoadSubModule(pScrn, "xaa")) {
147781f79626Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
147881f79626Smrg                            "Loading XAA module.\n");
147981f79626Smrg            }
148081f79626Smrg#endif
148181f79626Smrg        }
148281f79626Smrg    }
148381f79626Smrg}
148481f79626Smrg
1485c582b7e3Smrg/* R128PreInit is called once at server startup. */
1486c582b7e3SmrgBool R128PreInit(ScrnInfoPtr pScrn, int flags)
1487c582b7e3Smrg{
1488c582b7e3Smrg    R128InfoPtr      info;
1489e1efbb8aSmacallan#ifdef __NetBSD__
1490e1efbb8aSmacallan    struct wsdisplayio_bus_id bid;
1491e1efbb8aSmacallan#endif
1492c582b7e3Smrg
149381f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
149481f79626Smrg                        "%s\n", __func__));
149581f79626Smrg
149681f79626Smrg    if (flags & PROBE_DETECT) {
149781f79626Smrg        return TRUE;
149881f79626Smrg    }
149981f79626Smrg
150081f79626Smrg    pScrn->monitor = pScrn->confScreen->monitor;
150181f79626Smrg
150281f79626Smrg    if (!R128PreInitVisual(pScrn)) {
150381f79626Smrg        return FALSE;
150481f79626Smrg    }
150581f79626Smrg
150681f79626Smrg    if (!R128PreInitGamma(pScrn)) {
150781f79626Smrg        return FALSE;
150881f79626Smrg    }
1509c582b7e3Smrg
1510c582b7e3Smrg    if (pScrn->numEntities != 1) return FALSE;
1511c582b7e3Smrg
1512c582b7e3Smrg    if (!R128GetRec(pScrn)) return FALSE;
1513c582b7e3Smrg
1514b3ff493bSmrg    info                = R128PTR(pScrn);
1515c582b7e3Smrg    info->SwitchingMode = FALSE;
1516b3ff493bSmrg    info->MMIO          = NULL;
1517c582b7e3Smrg
1518b3ff493bSmrg    info->pEnt          = xf86GetEntityInfo(pScrn->entityList[0]);
1519c582b7e3Smrg    if (info->pEnt->location.type != BUS_PCI) goto fail;
1520c582b7e3Smrg
1521b3ff493bSmrg    info->PciInfo       = xf86GetPciInfoForEntity(info->pEnt->index);
1522c582b7e3Smrg
1523c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1524c582b7e3Smrg	       "PCI bus %d card %d func %d\n",
1525c582b7e3Smrg	       PCI_DEV_BUS(info->PciInfo),
1526c582b7e3Smrg	       PCI_DEV_DEV(info->PciInfo),
1527c582b7e3Smrg	       PCI_DEV_FUNC(info->PciInfo));
1528c582b7e3Smrg
1529e1efbb8aSmacallan#ifdef __NetBSD__
1530e1efbb8aSmacallan    /* now check if this is the console */
1531e1efbb8aSmacallan    info->HaveWSDisplay = FALSE;
1532e1efbb8aSmacallan    info->HaveBacklightControl = FALSE;
1533a4470643Smrg    if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GET_BUSID, &bid) != -1) {
1534e1efbb8aSmacallan    	if ((bid.bus_type == WSDISPLAYIO_BUS_PCI) &&
1535e1efbb8aSmacallan    	    (bid.ubus.pci.bus == PCI_DEV_BUS(info->PciInfo)) &&
1536e1efbb8aSmacallan    	    (bid.ubus.pci.device == PCI_DEV_DEV(info->PciInfo)) &&
1537e1efbb8aSmacallan    	    (bid.ubus.pci.function == PCI_DEV_FUNC(info->PciInfo))) {
1538e1efbb8aSmacallan    	    	struct wsdisplay_param p;
1539e1efbb8aSmacallan    	    	xf86Msg(X_INFO, "Alright, this is the console\n");
1540e1efbb8aSmacallan    	    	info->HaveWSDisplay = TRUE;
1541e1efbb8aSmacallan
1542e1efbb8aSmacallan    	    	/* now see if we have hacklight control */
1543e1efbb8aSmacallan    	    	p.param = WSDISPLAYIO_PARAM_BACKLIGHT;
1544a4470643Smrg		if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GETPARAM, &p) != -1) {
1545e1efbb8aSmacallan		    xf86Msg(X_INFO, "... and we have backlight control\n");
1546e1efbb8aSmacallan		    info->HaveBacklightControl = TRUE;
1547e1efbb8aSmacallan		}
1548e1efbb8aSmacallan    	}
1549e1efbb8aSmacallan    }
1550e1efbb8aSmacallan#endif
1551e1efbb8aSmacallan
155219019ffeSmrg#ifndef XSERVER_LIBPCIACCESS
1553b3ff493bSmrg    info->PciTag        = pciTag(PCI_DEV_BUS(info->PciInfo),
1554b3ff493bSmrg				PCI_DEV_DEV(info->PciInfo),
1555b3ff493bSmrg				PCI_DEV_FUNC(info->PciInfo));
1556b3ff493bSmrg
1557c582b7e3Smrg    if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail;
1558c582b7e3Smrg    if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail;
1559c582b7e3Smrg
1560b3ff493bSmrg    pScrn->racMemFlags  = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
156119019ffeSmrg#endif
1562b3ff493bSmrg
156381f79626Smrg    info->fifo_slots  = 0;
156481f79626Smrg    info->pix24bpp    = xf86GetBppFromDepth(pScrn, pScrn->depth);
156581f79626Smrg    info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
156681f79626Smrg    info->CurrentLayout.depth        = pScrn->depth;
156781f79626Smrg    info->CurrentLayout.pixel_bytes  = pScrn->bitsPerPixel / 8;
156881f79626Smrg    info->CurrentLayout.pixel_code   = (pScrn->bitsPerPixel != 16
156981f79626Smrg                                       ? pScrn->bitsPerPixel
157081f79626Smrg                                       : pScrn->depth);
1571c582b7e3Smrg
157281f79626Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
157381f79626Smrg           "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
157481f79626Smrg           pScrn->depth,
157581f79626Smrg           info->CurrentLayout.pixel_bytes,
157681f79626Smrg           info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
157781f79626Smrg           info->pix24bpp);
1578c582b7e3Smrg
1579c582b7e3Smrg				/* We can't do this until we have a
1580c582b7e3Smrg				   pScrn->display. */
1581c582b7e3Smrg    xf86CollectOptions(pScrn, NULL);
158284354367Smrg    if (!(info->Options = malloc(sizeof(R128Options))))    goto fail;
1583c582b7e3Smrg    memcpy(info->Options, R128Options, sizeof(R128Options));
1584c582b7e3Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1585c582b7e3Smrg
158681f79626Smrg    info->noAccel = FALSE;
158781f79626Smrg    info->accelOn = FALSE;
1588c582b7e3Smrg
158981f79626Smrg    info->useEXA = FALSE;
159081f79626Smrg#ifdef USE_EXA
159181f79626Smrg    info->useEXA = TRUE;
1592c582b7e3Smrg#endif
1593c582b7e3Smrg
159481f79626Smrg    info->swCursor = FALSE;
159581f79626Smrg
159681f79626Smrg    r128AcquireOption(pScrn);
159781f79626Smrg
1598c582b7e3Smrg    if (!R128PreInitWeight(pScrn))    goto fail;
1599c582b7e3Smrg
160081f79626Smrg    /* Allocate an xf86CrtcConfig */
160181f79626Smrg    xf86CrtcConfigInit(pScrn, &R128CRTCResizeFuncs);
1602c582b7e3Smrg
160381f79626Smrg    R128LegacyMS(pScrn);
160481f79626Smrg
160581f79626Smrg    if (!xf86InitialConfiguration(pScrn, TRUE)) {
160681f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
160781f79626Smrg        goto fail;
1608c582b7e3Smrg    }
160981f79626Smrg    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
1610b3ff493bSmrg
1611b3ff493bSmrg    /* Set display resolution */
1612b3ff493bSmrg    xf86SetDpi(pScrn, 0, 0);
1613b3ff493bSmrg
1614b3ff493bSmrg    /* Get ScreenInit function */
1615b3ff493bSmrg    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
1616b3ff493bSmrg
161781f79626Smrg    R128PreInitAccel(pScrn);
1618c582b7e3Smrg
1619b3ff493bSmrg    info->CurrentLayout.displayWidth = pScrn->displayWidth;
1620b3ff493bSmrg
1621b3ff493bSmrg    if (!xf86RandR12PreInit(pScrn)) {
1622b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
1623b3ff493bSmrg        goto fail;
1624b3ff493bSmrg    }
1625b3ff493bSmrg
1626b3ff493bSmrg    if (pScrn->modes == NULL) {
1627b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1628b3ff493bSmrg        goto fail;
1629b3ff493bSmrg    }
1630b3ff493bSmrg
1631c582b7e3Smrg				/* Free the video bios (if applicable) */
1632c582b7e3Smrg    if (info->VBIOS) {
163384354367Smrg	free(info->VBIOS);
1634c582b7e3Smrg	info->VBIOS = NULL;
1635c582b7e3Smrg    }
1636c582b7e3Smrg
1637b3ff493bSmrg    if (info->MMIO) R128UnmapMMIO(pScrn);
1638b3ff493bSmrg    info->MMIO = NULL;
1639b3ff493bSmrg
1640c582b7e3Smrg    return TRUE;
1641c582b7e3Smrg
1642c582b7e3Smrg  fail:
1643c582b7e3Smrg				/* Pre-init failed. */
1644c582b7e3Smrg
1645c582b7e3Smrg				/* Free the video bios (if applicable) */
1646c582b7e3Smrg    if (info->VBIOS) {
164784354367Smrg	free(info->VBIOS);
1648c582b7e3Smrg	info->VBIOS = NULL;
1649c582b7e3Smrg    }
1650c582b7e3Smrg
1651c582b7e3Smrg#ifdef WITH_VGAHW
1652c582b7e3Smrg    if (info->VGAAccess)
1653c582b7e3Smrg           vgaHWFreeHWRec(pScrn);
1654c582b7e3Smrg#endif
1655b3ff493bSmrg
1656b3ff493bSmrg    if (info->MMIO) R128UnmapMMIO(pScrn);
1657b3ff493bSmrg    info->MMIO = NULL;
1658b3ff493bSmrg
1659c582b7e3Smrg    R128FreeRec(pScrn);
1660c582b7e3Smrg    return FALSE;
1661c582b7e3Smrg}
1662c582b7e3Smrg
1663c582b7e3Smrg/* Load a palette. */
1664c582b7e3Smrgstatic void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
1665c582b7e3Smrg			    int *indices, LOCO *colors, VisualPtr pVisual)
1666c582b7e3Smrg{
1667c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
1668b3ff493bSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1669b3ff493bSmrg    int i, j;
1670b3ff493bSmrg    int c, index;
1671b3ff493bSmrg    uint16_t lut_r[256], lut_g[256], lut_b[256];
1672b3ff493bSmrg
1673b3ff493bSmrg    for (c = 0; c < xf86_config->num_crtc; c++) {
1674b3ff493bSmrg        xf86CrtcPtr crtc = xf86_config->crtc[c];
1675b3ff493bSmrg        R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
1676b3ff493bSmrg
1677b3ff493bSmrg        for (i = 0 ; i < 256; i++) {
1678b3ff493bSmrg            lut_r[i] = r128_crtc->lut_r[i] << 8;
1679b3ff493bSmrg            lut_g[i] = r128_crtc->lut_g[i] << 8;
1680b3ff493bSmrg            lut_b[i] = r128_crtc->lut_b[i] << 8;
1681b3ff493bSmrg        }
1682c582b7e3Smrg
1683b3ff493bSmrg        switch (info->CurrentLayout.depth) {
1684b3ff493bSmrg        case 15:
1685b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1686b3ff493bSmrg                index = indices[i];
1687b3ff493bSmrg                for (j = 0; j < 8; j++) {
1688b3ff493bSmrg                    lut_r[index * 8 + j] = colors[index].red << 8;
1689b3ff493bSmrg                    lut_g[index * 8 + j] = colors[index].green << 8;
1690b3ff493bSmrg                    lut_b[index * 8 + j] = colors[index].blue << 8;
1691b3ff493bSmrg                }
1692b3ff493bSmrg            }
1693b3ff493bSmrg        case 16:
1694b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1695b3ff493bSmrg                index = indices[i];
1696b3ff493bSmrg
1697b3ff493bSmrg                /* XXX: The old version of R128LoadPalette did not do this and
1698b3ff493bSmrg                 * the old version of RADEONLoadPalette has a comment asking why.
1699b3ff493bSmrg                 */
1700b3ff493bSmrg                if (i <= 31) {
1701b3ff493bSmrg                    for (j = 0; j < 8; j++) {
1702b3ff493bSmrg                        lut_r[index * 8 + j] = colors[index].red << 8;
1703b3ff493bSmrg                        lut_b[index * 8 + j] = colors[index].blue << 8;
1704b3ff493bSmrg                    }
1705b3ff493bSmrg                }
1706c582b7e3Smrg
1707b3ff493bSmrg                for (j = 0; j < 4; j++) {
1708b3ff493bSmrg                    lut_g[index * 4 + j] = colors[index].green << 8;
1709b3ff493bSmrg                }
1710b3ff493bSmrg            }
1711b3ff493bSmrg        default:
1712b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1713b3ff493bSmrg                index = indices[i];
1714b3ff493bSmrg                lut_r[index] = colors[index].red << 8;
1715b3ff493bSmrg                lut_g[index] = colors[index].green << 8;
1716b3ff493bSmrg                lut_b[index] = colors[index].blue << 8;
1717b3ff493bSmrg            }
1718b3ff493bSmrg            break;
1719b3ff493bSmrg        }
1720c582b7e3Smrg
1721b3ff493bSmrg        /* Make the change through RandR */
1722b3ff493bSmrg#ifdef RANDR_12_INTERFACE
1723b3ff493bSmrg        if (crtc->randr_crtc)
1724b3ff493bSmrg            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1725b3ff493bSmrg        else
1726b3ff493bSmrg#endif
1727b3ff493bSmrg        crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1728c582b7e3Smrg    }
1729c582b7e3Smrg}
1730c582b7e3Smrg
1731c582b7e3Smrgstatic void
173284354367SmrgR128BlockHandler(BLOCKHANDLER_ARGS_DECL)
1733c582b7e3Smrg{
173484354367Smrg    SCREEN_PTR(arg);
173584354367Smrg    ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
1736c582b7e3Smrg    R128InfoPtr info    = R128PTR(pScrn);
1737c582b7e3Smrg
173884354367Smrg#ifdef R128DRI
1739c582b7e3Smrg    if (info->directRenderingEnabled)
1740c582b7e3Smrg        FLUSH_RING();
1741c582b7e3Smrg#endif
1742c582b7e3Smrg
1743c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
174484354367Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1745c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
1746c582b7e3Smrg
1747c582b7e3Smrg    if(info->VideoTimerCallback) {
1748c582b7e3Smrg        (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
1749c582b7e3Smrg    }
1750c582b7e3Smrg}
1751c582b7e3Smrg
1752c582b7e3Smrg/* Called at the start of each server generation. */
175384354367SmrgBool R128ScreenInit(SCREEN_INIT_ARGS_DECL)
1754c582b7e3Smrg{
175584354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1756c582b7e3Smrg    R128InfoPtr info   = R128PTR(pScrn);
1757c582b7e3Smrg    BoxRec      MemBox;
175884354367Smrg    int width_bytes = (pScrn->displayWidth *
175981f79626Smrg                        info->CurrentLayout.pixel_bytes);
176081f79626Smrg    int scanlines;
176181f79626Smrg    int total = info->FbMapSize;
176281f79626Smrg    FBAreaPtr fbarea = NULL;
176381f79626Smrg#ifdef R128DRI
176481f79626Smrg    int cpp = info->CurrentLayout.pixel_bytes;
176581f79626Smrg    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
176684354367Smrg#ifdef USE_EXA
176784354367Smrg    ExaOffscreenArea*     osArea = NULL;
176881f79626Smrg#endif /* USE_EXA */
176981f79626Smrg#endif /* R128DRI */
177084354367Smrg
177181f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
177281f79626Smrg                        "%s %lx %lx\n",
177381f79626Smrg                        __func__,
177481f79626Smrg                        pScrn->memPhysBase, pScrn->fbOffset));
1775c582b7e3Smrg
177684354367Smrg#ifdef R128DRI
1777c582b7e3Smrg				/* Turn off the CCE for now. */
1778c582b7e3Smrg    info->CCEInUse     = FALSE;
1779c582b7e3Smrg    info->indirectBuffer = NULL;
1780c582b7e3Smrg#endif
1781c582b7e3Smrg
1782c582b7e3Smrg    if (!R128MapMem(pScrn)) return FALSE;
1783c582b7e3Smrg    pScrn->fbOffset    = 0;
1784b3ff493bSmrg    //if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
178584354367Smrg#ifdef R128DRI
1786c582b7e3Smrg    info->fbX          = 0;
1787c582b7e3Smrg    info->fbY          = 0;
1788c582b7e3Smrg    info->frontOffset  = 0;
1789c582b7e3Smrg    info->frontPitch   = pScrn->displayWidth;
1790c582b7e3Smrg#endif
1791c582b7e3Smrg
1792c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
1793c582b7e3Smrg
1794c582b7e3Smrg    R128Save(pScrn);
1795c582b7e3Smrg
1796c582b7e3Smrg				/* Visual setup */
1797c582b7e3Smrg    miClearVisualTypes();
1798c582b7e3Smrg    if (!miSetVisualTypes(pScrn->depth,
1799c582b7e3Smrg			  miGetDefaultVisualMask(pScrn->depth),
1800c582b7e3Smrg			  pScrn->rgbBits,
1801c582b7e3Smrg			  pScrn->defaultVisual)) return FALSE;
1802c582b7e3Smrg    miSetPixmapDepths ();
1803c582b7e3Smrg
180484354367Smrg#ifdef R128DRI
1805c582b7e3Smrg				/* Setup DRI after visuals have been
1806c582b7e3Smrg				   established, but before fbScreenInit is
180781f79626Smrg				   called. */
1808c582b7e3Smrg    {
1809c582b7e3Smrg	/* FIXME: When we move to dynamic allocation of back and depth
1810c582b7e3Smrg	   buffers, we will want to revisit the following check for 3
1811c582b7e3Smrg	   times the virtual size of the screen below. */
1812c582b7e3Smrg	int maxy        = info->FbMapSize / width_bytes;
1813c582b7e3Smrg
181481f79626Smrg        if (info->noAccel) {
181584354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1816c582b7e3Smrg		       "Acceleration disabled, not initializing the DRI\n");
1817c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
1818c582b7e3Smrg	} else if (maxy <= pScrn->virtualY * 3) {
181984354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1820c582b7e3Smrg		       "Static buffer allocation failed -- "
1821c582b7e3Smrg		       "need at least %d kB video memory\n",
1822c582b7e3Smrg		       (pScrn->displayWidth * pScrn->virtualY *
1823c582b7e3Smrg			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
1824c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
1825c582b7e3Smrg	} else {
1826b3ff493bSmrg            info->directRenderingEnabled = R128DRIScreenInit(pScreen);
1827c582b7e3Smrg	}
1828c582b7e3Smrg    }
1829c582b7e3Smrg#endif
1830c582b7e3Smrg
1831c582b7e3Smrg    if (!fbScreenInit (pScreen, info->FB,
1832c582b7e3Smrg		       pScrn->virtualX, pScrn->virtualY,
1833c582b7e3Smrg		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1834c582b7e3Smrg		       pScrn->bitsPerPixel))
1835c582b7e3Smrg	return FALSE;
1836c582b7e3Smrg
1837c582b7e3Smrg    xf86SetBlackWhitePixels(pScreen);
1838c582b7e3Smrg
1839c582b7e3Smrg    if (pScrn->bitsPerPixel > 8) {
1840c582b7e3Smrg	VisualPtr visual;
1841c582b7e3Smrg
1842c582b7e3Smrg	visual = pScreen->visuals + pScreen->numVisuals;
1843c582b7e3Smrg	while (--visual >= pScreen->visuals) {
1844c582b7e3Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
1845c582b7e3Smrg		visual->offsetRed   = pScrn->offset.red;
1846c582b7e3Smrg		visual->offsetGreen = pScrn->offset.green;
1847c582b7e3Smrg		visual->offsetBlue  = pScrn->offset.blue;
1848c582b7e3Smrg		visual->redMask     = pScrn->mask.red;
1849c582b7e3Smrg		visual->greenMask   = pScrn->mask.green;
1850c582b7e3Smrg		visual->blueMask    = pScrn->mask.blue;
1851c582b7e3Smrg	    }
1852c582b7e3Smrg	}
1853c582b7e3Smrg    }
1854c582b7e3Smrg
1855c582b7e3Smrg    /* must be after RGB order fixed */
1856c582b7e3Smrg    fbPictureInit (pScreen, 0, 0);
1857c582b7e3Smrg
1858c582b7e3Smrg				/* Memory manager setup */
185984354367Smrg#ifdef R128DRI
1860c582b7e3Smrg    if (info->directRenderingEnabled) {
1861c582b7e3Smrg	int bufferSize = pScrn->virtualY * width_bytes;
186281f79626Smrg	int l;
1863c582b7e3Smrg
1864c582b7e3Smrg	switch (info->CCEMode) {
1865c582b7e3Smrg	case R128_DEFAULT_CCE_PIO_MODE:
1866c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
1867c582b7e3Smrg	    break;
1868c582b7e3Smrg	case R128_DEFAULT_CCE_BM_MODE:
1869c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
1870c582b7e3Smrg	    break;
1871c582b7e3Smrg	default:
1872c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
1873c582b7e3Smrg	    break;
1874c582b7e3Smrg	}
1875c582b7e3Smrg
1876c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1877c582b7e3Smrg		   "Using %d MB AGP aperture\n", info->agpSize);
1878c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1879c582b7e3Smrg		   "Using %d MB for the ring buffer\n", info->ringSize);
1880c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1881c582b7e3Smrg		   "Using %d MB for vertex/indirect buffers\n", info->bufSize);
1882c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1883c582b7e3Smrg		   "Using %d MB for AGP textures\n", info->agpTexSize);
1884c582b7e3Smrg
1885c582b7e3Smrg	/* Try for front, back, depth, and two framebuffers worth of
1886c582b7e3Smrg	 * pixmap cache.  Should be enough for a fullscreen background
1887c582b7e3Smrg	 * image plus some leftovers.
1888c582b7e3Smrg	 */
1889c582b7e3Smrg	info->textureSize = info->FbMapSize - 5 * bufferSize;
1890c582b7e3Smrg
1891c582b7e3Smrg	/* If that gives us less than half the available memory, let's
1892c582b7e3Smrg	 * be greedy and grab some more.  Sorry, I care more about 3D
1893c582b7e3Smrg	 * performance than playing nicely, and you'll get around a full
1894c582b7e3Smrg	 * framebuffer's worth of pixmap cache anyway.
1895c582b7e3Smrg	 */
1896c582b7e3Smrg	if (info->textureSize < (int)info->FbMapSize / 2) {
1897c582b7e3Smrg	    info->textureSize = info->FbMapSize - 4 * bufferSize;
1898c582b7e3Smrg	}
1899c582b7e3Smrg
1900c582b7e3Smrg	if (info->textureSize > 0) {
1901c582b7e3Smrg	    l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
1902c582b7e3Smrg	    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
1903c582b7e3Smrg
1904c582b7e3Smrg	    /* Round the texture size up to the nearest whole number of
1905c582b7e3Smrg	     * texture regions.  Again, be greedy about this, don't
1906c582b7e3Smrg	     * round down.
1907c582b7e3Smrg	     */
1908c582b7e3Smrg	    info->log2TexGran = l;
1909c582b7e3Smrg	    info->textureSize = (info->textureSize >> l) << l;
1910c582b7e3Smrg	} else {
1911c582b7e3Smrg	    info->textureSize = 0;
1912c582b7e3Smrg	}
1913c582b7e3Smrg
1914c582b7e3Smrg	/* Set a minimum usable local texture heap size.  This will fit
1915c582b7e3Smrg	 * two 256x256x32bpp textures.
1916c582b7e3Smrg	 */
1917c582b7e3Smrg	if (info->textureSize < 512 * 1024) {
1918c582b7e3Smrg	    info->textureOffset = 0;
1919c582b7e3Smrg	    info->textureSize = 0;
1920c582b7e3Smrg	}
1921c582b7e3Smrg
192281f79626Smrg        total = info->FbMapSize - info->textureSize;
192381f79626Smrg    }
192481f79626Smrg#endif /* R128DRI */
1925c582b7e3Smrg
192681f79626Smrg    scanlines = total / width_bytes;
192781f79626Smrg    if (scanlines > 8191) scanlines = 8191;
192881f79626Smrg
192981f79626Smrg#ifdef R128DRI
193081f79626Smrg    if (info->directRenderingEnabled)
193181f79626Smrg        /*
1932e8b4ed9fSmrg         * Recalculate the texture offset and size to accommodate any
193381f79626Smrg         * rounding to a whole number of scanlines.
193481f79626Smrg         */
193581f79626Smrg        info->textureOffset = scanlines * width_bytes;
193681f79626Smrg#endif /* R128DRI */
1937c582b7e3Smrg
193881f79626Smrg    MemBox.x1 = 0;
193981f79626Smrg    MemBox.y1 = 0;
194081f79626Smrg    MemBox.x2 = pScrn->displayWidth;
194181f79626Smrg    MemBox.y2 = scanlines;
1942c582b7e3Smrg
194384354367Smrg	if (!info->useEXA) {
194484354367Smrg	    if (!xf86InitFBManager(pScreen, &MemBox)) {
194584354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
194684354367Smrg		           "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
194784354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
194884354367Smrg	        return FALSE;
1949c582b7e3Smrg	    } else {
195084354367Smrg	        int width, height;
195184354367Smrg
195284354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
195384354367Smrg		           "Memory manager initialized to (%d,%d) (%d,%d)\n",
195484354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
195584354367Smrg	        if ((fbarea = xf86AllocateOffscreenArea(pScreen,
195684354367Smrg						        pScrn->displayWidth,
195784354367Smrg						        2, 0, NULL, NULL, NULL))) {
195884354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
195984354367Smrg			       "Reserved area from (%d,%d) to (%d,%d)\n",
196084354367Smrg			       fbarea->box.x1, fbarea->box.y1,
196184354367Smrg			       fbarea->box.x2, fbarea->box.y2);
196284354367Smrg	        } else {
196384354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve area\n");
196484354367Smrg	        }
196584354367Smrg	        if (xf86QueryLargestOffscreenArea(pScreen, &width,
196684354367Smrg						  &height, 0, 0, 0)) {
196784354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
196884354367Smrg			       "Largest offscreen area available: %d x %d\n",
196984354367Smrg				width, height);
197084354367Smrg	        }
197184354367Smrg
197281f79626Smrg            if (!info->noAccel) {
197381f79626Smrg                if (R128XAAAccelInit(pScreen)) {
197481f79626Smrg                    info->accelOn = TRUE;
197581f79626Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
197681f79626Smrg                                "XAA acceleration enabled.\n");
197781f79626Smrg                } else {
197881f79626Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
197981f79626Smrg                                "Acceleration disabled.\n");
198081f79626Smrg                }
198181f79626Smrg            }
198281f79626Smrg        }
198381f79626Smrg    }
198484354367Smrg#ifdef USE_EXA
198581f79626Smrg    else {
198681f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
198781f79626Smrg                    "Filling in EXA memory info\n");
198884354367Smrg
198984354367Smrg
199081f79626Smrg        /*
199181f79626Smrg         * Don't give EXA the true full memory size, because
199281f79626Smrg         * the textureSize sized chunk on the end is handled
199381f79626Smrg         * by DRI.
199481f79626Smrg         */
199581f79626Smrg        if (R128EXAInit(pScreen, total)) {
199681f79626Smrg            info->accelOn = TRUE;
199781f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
199881f79626Smrg                        "EXA Acceleration enabled.\n");
199981f79626Smrg        } else {
200081f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
200181f79626Smrg                        "EXA Acceleration initialization "
200281f79626Smrg                        "failed.\n");
200381f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
200481f79626Smrg                        "Acceleration disabled.\n");
200581f79626Smrg        }
200681f79626Smrg    }
200784354367Smrg#endif
2008c582b7e3Smrg
200981f79626Smrg#ifdef R128DRI
201081f79626Smrg    if (info->directRenderingEnabled) {
2011c582b7e3Smrg				/* Allocate the shared back buffer */
201284354367Smrg	if(!info->useEXA) {
201384354367Smrg	    fbarea = xf86AllocateOffscreenArea(pScreen,
201484354367Smrg					       pScrn->virtualX,
201584354367Smrg					       pScrn->virtualY,
201684354367Smrg					       32, NULL, NULL, NULL);
201784354367Smrg
201884354367Smrg	    if (fbarea) {
201984354367Smrg		x1 = fbarea->box.x1;
202084354367Smrg		x2 = fbarea->box.x2;
202184354367Smrg		y1 = fbarea->box.y1;
202284354367Smrg		y2 = fbarea->box.y2;
202384354367Smrg	    }
202484354367Smrg	}
202584354367Smrg#ifdef USE_EXA
202684354367Smrg	else {
202784354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
202884354367Smrg		       "Actually trying an EXA allocation...\n");
202984354367Smrg	    osArea = exaOffscreenAlloc(pScreen,
203084354367Smrg				       pScrn->virtualY * width_bytes,
203184354367Smrg				       32, TRUE, NULL, NULL);
203284354367Smrg
203384354367Smrg	    if (osArea) {
203484354367Smrg		x1 = osArea->offset % width_bytes;
203584354367Smrg		x2 = (osArea->offset + osArea->size) % width_bytes;
203684354367Smrg		y1 = osArea->offset / width_bytes;
203784354367Smrg		y2 = (osArea->offset + osArea->size) / width_bytes;
203884354367Smrg
203984354367Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Went swimmingly...\n");
204084354367Smrg	    }
204184354367Smrg	}
204284354367Smrg#endif
204384354367Smrg
204484354367Smrg	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
204584354367Smrg	    /* info->backOffset = y1 * width_bytes + x1 * cpp; */
204684354367Smrg	    info->backOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
204784354367Smrg	    info->backX = info->backOffset % width_bytes;
204884354367Smrg	    info->backY = info->backOffset / width_bytes;
2049c582b7e3Smrg	    info->backPitch = pScrn->displayWidth;
205084354367Smrg
205184354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
205284354367Smrg		       "Reserved back buffer from (%d,%d) to (%d,%d) offset: %x\n",
205384354367Smrg		       x1, y1,
205484354367Smrg		       x2, y2, info->backOffset);
2055c582b7e3Smrg	} else {
205684354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
2057c582b7e3Smrg	    info->backX = -1;
2058c582b7e3Smrg	    info->backY = -1;
2059c582b7e3Smrg	    info->backOffset = -1;
2060c582b7e3Smrg	    info->backPitch = -1;
2061c582b7e3Smrg	}
2062c582b7e3Smrg
2063c582b7e3Smrg				/* Allocate the shared depth buffer */
206484354367Smrg	if(!info->useEXA) {
206584354367Smrg	    fbarea = xf86AllocateOffscreenArea(pScreen,
206684354367Smrg					       pScrn->virtualX,
206784354367Smrg					       pScrn->virtualY + 1,
206884354367Smrg					       32, NULL, NULL, NULL);
206984354367Smrg	    if (fbarea) {
207084354367Smrg		x1 = fbarea->box.x1;
207184354367Smrg		x2 = fbarea->box.x2;
207284354367Smrg		y1 = fbarea->box.y1;
207384354367Smrg		y2 = fbarea->box.y2;
207484354367Smrg	    }
207584354367Smrg	}
207684354367Smrg#ifdef USE_EXA
207784354367Smrg	else {
207884354367Smrg	    osArea = exaOffscreenAlloc(pScreen,
207984354367Smrg				       (pScrn->virtualY + 1) * width_bytes,
208084354367Smrg				       32, TRUE, NULL, NULL);
208184354367Smrg
208284354367Smrg	    if (osArea) {
208384354367Smrg		x1 = osArea->offset % width_bytes;
208484354367Smrg		x2 = (osArea->offset + osArea->size) % width_bytes;
208584354367Smrg		y1 = osArea->offset / width_bytes;
208684354367Smrg		y2 = (osArea->offset + osArea->size) / width_bytes;
208784354367Smrg	    }
208884354367Smrg	}
208984354367Smrg#endif
209084354367Smrg
209184354367Smrg	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
209284354367Smrg	    /* info->depthOffset = y1 * width_bytes + x1 * cpp; */
209384354367Smrg	    info->depthOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
209484354367Smrg	    info->depthX = info->depthOffset % width_bytes;
209584354367Smrg	    info->depthY = info->depthOffset / width_bytes;
2096c582b7e3Smrg	    info->depthPitch = pScrn->displayWidth;
209784354367Smrg	    info->spanOffset = (y2 - 1) * width_bytes + x1 * cpp;
209884354367Smrg
209984354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
210084354367Smrg		       "Reserved depth buffer from (%d,%d) to (%d,%d) offset: %x\n",
210184354367Smrg		       x1, y1,
210284354367Smrg		       x2, y2, info->depthOffset);
210384354367Smrg
210484354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2105c582b7e3Smrg		       "Reserved depth span from (%d,%d) offset 0x%x\n",
210684354367Smrg		       x1, y2 - 1, info->spanOffset);
2107c582b7e3Smrg	} else {
210884354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
2109c582b7e3Smrg	    info->depthX = -1;
2110c582b7e3Smrg	    info->depthY = -1;
2111c582b7e3Smrg	    info->depthOffset = -1;
2112c582b7e3Smrg	    info->depthPitch = -1;
2113c582b7e3Smrg	    info->spanOffset = -1;
2114c582b7e3Smrg	}
2115c582b7e3Smrg
211684354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2117c582b7e3Smrg		   "Reserved %d kb for textures at offset 0x%x\n",
2118c582b7e3Smrg		   info->textureSize/1024, info->textureOffset);
2119c582b7e3Smrg    }
212084354367Smrg#endif /* R128DRI */
2121c582b7e3Smrg
2122b3ff493bSmrg    pScrn->vtSema = TRUE;
2123b3ff493bSmrg    /* xf86CrtcRotate accesses pScrn->pScreen */
2124b3ff493bSmrg    pScrn->pScreen = pScreen;
2125b3ff493bSmrg
21263c921f55Smrg#ifndef AVOID_FBDEV
2127b3ff493bSmrg    if (info->FBDev) {
2128b3ff493bSmrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
2129b3ff493bSmrg    } else {
21303c921f55Smrg#endif
2131b3ff493bSmrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
21323c921f55Smrg#ifndef AVOID_FBDEV
2133b3ff493bSmrg    }
21343c921f55Smrg#endif
2135b3ff493bSmrg
2136b3ff493bSmrg    R128SaveScreen(pScreen, SCREEN_SAVER_ON);
2137b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2138b3ff493bSmrg
2139c582b7e3Smrg				/* DGA setup */
2140b3ff493bSmrg#ifdef XFreeXDGA
2141b3ff493bSmrg    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
2142b3ff493bSmrg#endif
2143c582b7e3Smrg
2144c582b7e3Smrg				/* Backing store setup */
2145c582b7e3Smrg    xf86SetBackingStore(pScreen);
2146c582b7e3Smrg
2147c582b7e3Smrg				/* Set Silken Mouse */
2148c582b7e3Smrg    xf86SetSilkenMouse(pScreen);
2149c582b7e3Smrg
2150c582b7e3Smrg				/* Cursor setup */
2151c582b7e3Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2152c582b7e3Smrg
2153c582b7e3Smrg				/* Hardware cursor setup */
215481f79626Smrg    if (!info->swCursor) {
2155c582b7e3Smrg	if (R128CursorInit(pScreen)) {
2156c582b7e3Smrg	    int width, height;
2157c582b7e3Smrg
2158c582b7e3Smrg	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2159c582b7e3Smrg					      0, 0, 0)) {
216084354367Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2161c582b7e3Smrg			   "Largest offscreen area available: %d x %d\n",
2162c582b7e3Smrg			   width, height);
2163c582b7e3Smrg	    }
2164c582b7e3Smrg	} else {
216584354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2166c582b7e3Smrg		       "Hardware cursor initialization failed\n");
216784354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2168c582b7e3Smrg	}
2169c582b7e3Smrg    } else {
217084354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2171c582b7e3Smrg    }
2172c582b7e3Smrg
2173c582b7e3Smrg    /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
217479e5230eSmacallan#ifndef AVOID_FBDEV
2175c582b7e3Smrg    if (info->FBDev)
2176c582b7e3Smrg	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
2177b3ff493bSmrg    else
217879e5230eSmacallan#endif
21793c921f55Smrg        xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2180c582b7e3Smrg
21813c921f55Smrg    R128InitVideo(pScreen);
2182c582b7e3Smrg
2183c582b7e3Smrg				/* Provide SaveScreen */
2184c582b7e3Smrg    pScreen->SaveScreen  = R128SaveScreen;
2185c582b7e3Smrg
2186c582b7e3Smrg				/* Wrap CloseScreen */
2187c582b7e3Smrg    info->CloseScreen    = pScreen->CloseScreen;
2188c582b7e3Smrg    pScreen->CloseScreen = R128CloseScreen;
2189c582b7e3Smrg
2190c582b7e3Smrg				/* Note unused options */
2191c582b7e3Smrg    if (serverGeneration == 1)
2192c582b7e3Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2193c582b7e3Smrg
219484354367Smrg#ifdef R128DRI
2195c582b7e3Smrg				/* DRI finalization */
2196c582b7e3Smrg    if (info->directRenderingEnabled) {
2197c582b7e3Smrg				/* Now that mi, fb, drm and others have
2198c582b7e3Smrg				   done their thing, complete the DRI
2199c582b7e3Smrg				   setup. */
2200c582b7e3Smrg	info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
2201c582b7e3Smrg    }
2202c582b7e3Smrg    if (info->directRenderingEnabled) {
2203c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2204c582b7e3Smrg    } else {
2205c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2206c582b7e3Smrg		   "Direct rendering disabled\n");
2207c582b7e3Smrg    }
2208c582b7e3Smrg#endif
2209c582b7e3Smrg
2210c582b7e3Smrg    info->BlockHandler = pScreen->BlockHandler;
2211c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
2212c582b7e3Smrg
2213b3ff493bSmrg    if (!xf86CrtcScreenInit(pScreen)) return FALSE;
2214b3ff493bSmrg
2215b3ff493bSmrg				/* Colormap setup */
2216b3ff493bSmrg    if (!miCreateDefColormap(pScreen)) return FALSE;
2217b3ff493bSmrg    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
2218b3ff493bSmrg			     (
2219b3ff493bSmrg#ifndef AVOID_FBDEV
2220b3ff493bSmrg			     info->FBDev ? fbdevHWLoadPaletteWeak() :
2221b3ff493bSmrg#endif
2222b3ff493bSmrg			     R128LoadPalette), NULL,
2223b3ff493bSmrg			     CMAP_PALETTED_TRUECOLOR
2224b3ff493bSmrg			     | CMAP_RELOAD_ON_MODE_SWITCH
2225b3ff493bSmrg#if 0 /* This option messes up text mode! (eich@suse.de) */
2226b3ff493bSmrg			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
2227b3ff493bSmrg#endif
2228b3ff493bSmrg			     )) return FALSE;
2229b3ff493bSmrg
2230c582b7e3Smrg    return TRUE;
2231c582b7e3Smrg}
2232c582b7e3Smrg
2233c582b7e3Smrg/* Write common registers (initialized to 0). */
2234b3ff493bSmrgvoid R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2235c582b7e3Smrg{
2236c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2237c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2238c582b7e3Smrg
2239c582b7e3Smrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
2240c582b7e3Smrg
2241c582b7e3Smrg    OUTREG(R128_OVR_CLR,              restore->ovr_clr);
2242c582b7e3Smrg    OUTREG(R128_OVR_WID_LEFT_RIGHT,   restore->ovr_wid_left_right);
2243c582b7e3Smrg    OUTREG(R128_OVR_WID_TOP_BOTTOM,   restore->ovr_wid_top_bottom);
2244c582b7e3Smrg    OUTREG(R128_OV0_SCALE_CNTL,       restore->ov0_scale_cntl);
2245c582b7e3Smrg    OUTREG(R128_MPP_TB_CONFIG,        restore->mpp_tb_config );
2246c582b7e3Smrg    OUTREG(R128_MPP_GP_CONFIG,        restore->mpp_gp_config );
2247c582b7e3Smrg    OUTREG(R128_SUBPIC_CNTL,          restore->subpic_cntl);
2248c582b7e3Smrg    OUTREG(R128_VIPH_CONTROL,         restore->viph_control);
2249c582b7e3Smrg    OUTREG(R128_I2C_CNTL_1,           restore->i2c_cntl_1);
2250c582b7e3Smrg    OUTREG(R128_GEN_INT_CNTL,         restore->gen_int_cntl);
2251c582b7e3Smrg    OUTREG(R128_CAP0_TRIG_CNTL,       restore->cap0_trig_cntl);
2252c582b7e3Smrg    OUTREG(R128_CAP1_TRIG_CNTL,       restore->cap1_trig_cntl);
2253c582b7e3Smrg    OUTREG(R128_BUS_CNTL,             restore->bus_cntl);
2254c582b7e3Smrg    OUTREG(R128_CONFIG_CNTL,          restore->config_cntl);
2255c582b7e3Smrg}
2256c582b7e3Smrg
2257b3ff493bSmrg/* Write RMX registers */
2258b3ff493bSmrgvoid R128RestoreRMXRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2259c582b7e3Smrg{
2260c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2261c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2262c582b7e3Smrg
2263c582b7e3Smrg    OUTREG(R128_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
2264c582b7e3Smrg    OUTREG(R128_FP_VERT_STRETCH,      restore->fp_vert_stretch);
2265c582b7e3Smrg    OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
2266c582b7e3Smrg    OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
2267c582b7e3Smrg    OUTREG(R128_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
2268c582b7e3Smrg    OUTREG(R128_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
2269b3ff493bSmrg}
2270b3ff493bSmrg
2271b3ff493bSmrg/* Write flat panel registers */
2272b3ff493bSmrgvoid R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2273b3ff493bSmrg{
2274b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2275b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2276b3ff493bSmrg
2277b3ff493bSmrg    OUTREG(R128_TMDS_CRC,              restore->tmds_crc);
2278b3ff493bSmrg    OUTREG(R128_TMDS_TRANSMITTER_CNTL, restore->tmds_transmitter_cntl);
2279b3ff493bSmrg    OUTREG(R128_FP_PANEL_CNTL,         restore->fp_panel_cntl);
2280b3ff493bSmrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(uint32_t)R128_FP_BLANK_DIS);
2281b3ff493bSmrg}
2282b3ff493bSmrg
2283b3ff493bSmrg/* Write LVDS registers */
2284b3ff493bSmrgvoid R128RestoreLVDSRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2285b3ff493bSmrg{
2286b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2287b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2288b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2289b3ff493bSmrg    uint32_t      tmp;
2290c582b7e3Smrg
2291b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2292b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2293c582b7e3Smrg
2294c582b7e3Smrg    tmp = INREG(R128_LVDS_GEN_CNTL);
2295c582b7e3Smrg    if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
2296c582b7e3Smrg	(restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
2297c582b7e3Smrg	OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2298c582b7e3Smrg    } else {
2299c582b7e3Smrg	if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
2300c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL,
2301b3ff493bSmrg		   restore->lvds_gen_cntl & (uint32_t)~R128_LVDS_BLON);
2302b3ff493bSmrg	    usleep(r128_output->PanelPwrDly * 1000);
2303c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2304c582b7e3Smrg	} else {
2305c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
2306b3ff493bSmrg	    usleep(r128_output->PanelPwrDly * 1000);
2307c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2308c582b7e3Smrg	}
2309c582b7e3Smrg    }
2310c582b7e3Smrg}
2311c582b7e3Smrg
2312c582b7e3Smrg/* Write DDA registers. */
2313b3ff493bSmrgvoid R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2314c582b7e3Smrg{
2315c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2316c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2317c582b7e3Smrg
2318c582b7e3Smrg    OUTREG(R128_DDA_CONFIG, restore->dda_config);
2319c582b7e3Smrg    OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
2320c582b7e3Smrg}
2321c582b7e3Smrg
2322c582b7e3Smrg/* Write DDA registers. */
2323b3ff493bSmrgvoid R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2324c582b7e3Smrg{
2325c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2326c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2327c582b7e3Smrg
2328c582b7e3Smrg    OUTREG(R128_DDA2_CONFIG, restore->dda2_config);
2329c582b7e3Smrg    OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off);
2330c582b7e3Smrg}
2331c582b7e3Smrg
2332c582b7e3Smrg/* Read common registers. */
2333c582b7e3Smrgstatic void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2334c582b7e3Smrg{
2335c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2336c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2337c582b7e3Smrg
2338c582b7e3Smrg    save->ovr_clr            = INREG(R128_OVR_CLR);
2339c582b7e3Smrg    save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
2340c582b7e3Smrg    save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
2341c582b7e3Smrg    save->ov0_scale_cntl     = INREG(R128_OV0_SCALE_CNTL);
2342c582b7e3Smrg    save->mpp_tb_config      = INREG(R128_MPP_TB_CONFIG);
2343c582b7e3Smrg    save->mpp_gp_config      = INREG(R128_MPP_GP_CONFIG);
2344c582b7e3Smrg    save->subpic_cntl        = INREG(R128_SUBPIC_CNTL);
2345c582b7e3Smrg    save->viph_control       = INREG(R128_VIPH_CONTROL);
2346c582b7e3Smrg    save->i2c_cntl_1         = INREG(R128_I2C_CNTL_1);
2347c582b7e3Smrg    save->gen_int_cntl       = INREG(R128_GEN_INT_CNTL);
2348c582b7e3Smrg    save->cap0_trig_cntl     = INREG(R128_CAP0_TRIG_CNTL);
2349c582b7e3Smrg    save->cap1_trig_cntl     = INREG(R128_CAP1_TRIG_CNTL);
2350c582b7e3Smrg    save->bus_cntl           = INREG(R128_BUS_CNTL);
2351c582b7e3Smrg    save->config_cntl        = INREG(R128_CONFIG_CNTL);
2352c582b7e3Smrg}
2353c582b7e3Smrg
2354c582b7e3Smrg/* Read CRTC registers. */
2355c582b7e3Smrgstatic void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2356c582b7e3Smrg{
2357c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2358c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2359c582b7e3Smrg
2360c582b7e3Smrg    save->crtc_gen_cntl        = INREG(R128_CRTC_GEN_CNTL);
2361c582b7e3Smrg    save->crtc_ext_cntl        = INREG(R128_CRTC_EXT_CNTL);
2362c582b7e3Smrg    save->dac_cntl             = INREG(R128_DAC_CNTL);
2363c582b7e3Smrg    save->crtc_h_total_disp    = INREG(R128_CRTC_H_TOTAL_DISP);
2364c582b7e3Smrg    save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
2365c582b7e3Smrg    save->crtc_v_total_disp    = INREG(R128_CRTC_V_TOTAL_DISP);
2366c582b7e3Smrg    save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
2367c582b7e3Smrg    save->crtc_offset          = INREG(R128_CRTC_OFFSET);
2368c582b7e3Smrg    save->crtc_offset_cntl     = INREG(R128_CRTC_OFFSET_CNTL);
2369c582b7e3Smrg    save->crtc_pitch           = INREG(R128_CRTC_PITCH);
2370c582b7e3Smrg}
2371c582b7e3Smrg
2372c582b7e3Smrg/* Read flat panel registers */
2373c582b7e3Smrgstatic void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2374c582b7e3Smrg{
2375c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2376c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2377c582b7e3Smrg
2378c582b7e3Smrg    save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
2379c582b7e3Smrg    save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
2380c582b7e3Smrg    save->fp_gen_cntl          = INREG(R128_FP_GEN_CNTL);
2381c582b7e3Smrg    save->fp_h_sync_strt_wid   = INREG(R128_FP_H_SYNC_STRT_WID);
2382c582b7e3Smrg    save->fp_horz_stretch      = INREG(R128_FP_HORZ_STRETCH);
2383c582b7e3Smrg    save->fp_panel_cntl        = INREG(R128_FP_PANEL_CNTL);
2384c582b7e3Smrg    save->fp_v_sync_strt_wid   = INREG(R128_FP_V_SYNC_STRT_WID);
2385c582b7e3Smrg    save->fp_vert_stretch      = INREG(R128_FP_VERT_STRETCH);
2386c582b7e3Smrg    save->lvds_gen_cntl        = INREG(R128_LVDS_GEN_CNTL);
2387c582b7e3Smrg    save->tmds_crc             = INREG(R128_TMDS_CRC);
2388c582b7e3Smrg    save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
2389c582b7e3Smrg}
2390c582b7e3Smrg
2391c582b7e3Smrg/* Read CRTC2 registers. */
2392c582b7e3Smrgstatic void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2393c582b7e3Smrg{
2394c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2395c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2396c582b7e3Smrg
2397c582b7e3Smrg    save->crtc2_gen_cntl        = INREG(R128_CRTC2_GEN_CNTL);
2398c582b7e3Smrg    save->crtc2_h_total_disp    = INREG(R128_CRTC2_H_TOTAL_DISP);
2399c582b7e3Smrg    save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID);
2400c582b7e3Smrg    save->crtc2_v_total_disp    = INREG(R128_CRTC2_V_TOTAL_DISP);
2401c582b7e3Smrg    save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID);
2402c582b7e3Smrg    save->crtc2_offset          = INREG(R128_CRTC2_OFFSET);
2403c582b7e3Smrg    save->crtc2_offset_cntl     = INREG(R128_CRTC2_OFFSET_CNTL);
2404c582b7e3Smrg    save->crtc2_pitch           = INREG(R128_CRTC2_PITCH);
2405c582b7e3Smrg}
2406c582b7e3Smrg
2407c582b7e3Smrg/* Read PLL registers. */
2408c582b7e3Smrgstatic void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2409c582b7e3Smrg{
2410c582b7e3Smrg    save->ppll_ref_div         = INPLL(pScrn, R128_PPLL_REF_DIV);
2411c582b7e3Smrg    save->ppll_div_3           = INPLL(pScrn, R128_PPLL_DIV_3);
24129e881af1Smacallan    save->ppll_div_0           = INPLL(pScrn, R128_PPLL_DIV_0);
2413c582b7e3Smrg    save->htotal_cntl          = INPLL(pScrn, R128_HTOTAL_CNTL);
2414c582b7e3Smrg
241581f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
241681f79626Smrg                        "Read: 0x%08x 0x%08x 0x%08x\n",
241781f79626Smrg                        save->ppll_ref_div,
241881f79626Smrg                        save->ppll_div_3,
241981f79626Smrg                        save->htotal_cntl));
242081f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
242181f79626Smrg                        "Read: rd=%d, fd=%d, pd=%d\n",
242281f79626Smrg                        save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
242381f79626Smrg                        save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
242481f79626Smrg                        (save->ppll_div_3 &
242581f79626Smrg                                R128_PPLL_POST3_DIV_MASK) >> 16));
2426c582b7e3Smrg}
2427c582b7e3Smrg
2428c582b7e3Smrg/* Read PLL2 registers. */
2429c582b7e3Smrgstatic void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2430c582b7e3Smrg{
2431c582b7e3Smrg    save->p2pll_ref_div        = INPLL(pScrn, R128_P2PLL_REF_DIV);
2432c582b7e3Smrg    save->p2pll_div_0          = INPLL(pScrn, R128_P2PLL_DIV_0);
2433c582b7e3Smrg    save->htotal_cntl2         = INPLL(pScrn, R128_HTOTAL2_CNTL);
2434c582b7e3Smrg
243581f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
243681f79626Smrg                        "Read: 0x%08x 0x%08x 0x%08x\n",
243781f79626Smrg                        save->p2pll_ref_div,
243881f79626Smrg                        save->p2pll_div_0,
243981f79626Smrg                        save->htotal_cntl2));
244081f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
244181f79626Smrg                        "Read: rd=%d, fd=%d, pd=%d\n",
244281f79626Smrg                        save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
244381f79626Smrg                        save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
244481f79626Smrg                        (save->p2pll_div_0 &
244581f79626Smrg                                R128_P2PLL_POST0_DIV_MASK) >> 16));
2446c582b7e3Smrg}
2447c582b7e3Smrg
2448c582b7e3Smrg/* Read DDA registers. */
2449c582b7e3Smrgstatic void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2450c582b7e3Smrg{
2451c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2452c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2453c582b7e3Smrg
2454c582b7e3Smrg    save->dda_config           = INREG(R128_DDA_CONFIG);
2455c582b7e3Smrg    save->dda_on_off           = INREG(R128_DDA_ON_OFF);
2456c582b7e3Smrg}
2457c582b7e3Smrg
2458c582b7e3Smrg/* Read DDA2 registers. */
2459c582b7e3Smrgstatic void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2460c582b7e3Smrg{
2461c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2462c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2463c582b7e3Smrg
2464c582b7e3Smrg    save->dda2_config           = INREG(R128_DDA2_CONFIG);
2465c582b7e3Smrg    save->dda2_on_off           = INREG(R128_DDA2_ON_OFF);
2466c582b7e3Smrg}
2467c582b7e3Smrg
2468c582b7e3Smrg/* Read palette data. */
2469c582b7e3Smrgstatic void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
2470c582b7e3Smrg{
2471c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2472c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2473c582b7e3Smrg    int           i;
2474c582b7e3Smrg
2475c582b7e3Smrg    PAL_SELECT(1);
2476c582b7e3Smrg    INPAL_START(0);
2477c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
2478c582b7e3Smrg    PAL_SELECT(0);
2479c582b7e3Smrg    INPAL_START(0);
2480c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
2481c582b7e3Smrg    save->palette_valid = TRUE;
2482c582b7e3Smrg}
2483c582b7e3Smrg
2484c582b7e3Smrg/* Save state that defines current video mode. */
2485c582b7e3Smrgstatic void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
2486c582b7e3Smrg{
2487c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2488b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2489c582b7e3Smrg
249081f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
249181f79626Smrg                        "%s(%p)\n", __func__, save));
2492c582b7e3Smrg
2493b3ff493bSmrg    R128SaveCommonRegisters(pScrn, save);
2494b3ff493bSmrg    R128SaveCrtcRegisters(pScrn, save);
2495b3ff493bSmrg    R128SavePLLRegisters(pScrn, save);
2496b3ff493bSmrg    R128SaveDDARegisters(pScrn, save);
2497b3ff493bSmrg    if (pR128Ent->HasCRTC2) {
2498c582b7e3Smrg        R128SaveCrtc2Registers(pScrn, save);
2499c582b7e3Smrg        R128SavePLL2Registers(pScrn, save);
2500c582b7e3Smrg        R128SaveDDA2Registers(pScrn, save);
2501c582b7e3Smrg    }
2502b3ff493bSmrg    if (info->HasPanelRegs) {
2503b3ff493bSmrg        R128SaveFPRegisters(pScrn, save);
2504c582b7e3Smrg    }
2505b3ff493bSmrg    R128SavePalette(pScrn, save);
2506c582b7e3Smrg
250781f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
250881f79626Smrg                        "%s returns %p\n", __func__, save));
2509c582b7e3Smrg}
2510c582b7e3Smrg
2511c582b7e3Smrg/* Save everything needed to restore the original VC state. */
2512c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn)
2513c582b7e3Smrg{
2514c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2515c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2516c582b7e3Smrg    R128SavePtr   save      = &info->SavedReg;
2517c582b7e3Smrg
251879e5230eSmacallan#ifndef AVOID_FBDEV
251981f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
252081f79626Smrg                        "%s\n", __func__));
2521c582b7e3Smrg    if (info->FBDev) {
2522c582b7e3Smrg	fbdevHWSave(pScrn);
2523c582b7e3Smrg	return;
2524c582b7e3Smrg    }
252579e5230eSmacallan#endif
2526c582b7e3Smrg
2527c582b7e3Smrg#ifdef WITH_VGAHW
2528b3ff493bSmrg    if (info->VGAAccess) {
2529b3ff493bSmrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2530c582b7e3Smrg
2531b3ff493bSmrg        vgaHWUnlock(hwp);
2532c582b7e3Smrg# if defined(__powerpc__)
2533b3ff493bSmrg        /* temporary hack to prevent crashing on PowerMacs when trying to
2534b3ff493bSmrg         * read VGA fonts and colormap, will find a better solution
2535b3ff493bSmrg         * in the future. TODO: Check if there's actually some VGA stuff
2536b3ff493bSmrg         * setup in the card at all !!
2537b3ff493bSmrg         */
2538b3ff493bSmrg        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
2539c582b7e3Smrg# else
2540b3ff493bSmrg        /* Save mode * & fonts & cmap */
2541b3ff493bSmrg        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
2542c582b7e3Smrg# endif
2543b3ff493bSmrg        vgaHWLock(hwp);
2544c582b7e3Smrg    }
2545b3ff493bSmrg#endif
2546c582b7e3Smrg
2547b3ff493bSmrg    save->dp_datatype      = INREG(R128_DP_DATATYPE);
2548b3ff493bSmrg    save->gen_reset_cntl   = INREG(R128_GEN_RESET_CNTL);
2549b3ff493bSmrg    save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
2550b3ff493bSmrg    save->amcgpio_en_reg   = INREG(R128_AMCGPIO_EN_REG);
2551b3ff493bSmrg    save->amcgpio_mask     = INREG(R128_AMCGPIO_MASK);
2552c582b7e3Smrg
2553b3ff493bSmrg    R128SaveMode(pScrn, save);
2554c582b7e3Smrg}
2555c582b7e3Smrg
2556c582b7e3Smrg/* Restore the original (text) mode. */
2557c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn)
2558c582b7e3Smrg{
2559c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2560b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2561c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2562c582b7e3Smrg    R128SavePtr   restore   = &info->SavedReg;
2563c582b7e3Smrg
256479e5230eSmacallan#ifndef AVOID_FBDEV
256581f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
256681f79626Smrg                        "%s\n", __func__));
2567c582b7e3Smrg    if (info->FBDev) {
2568c582b7e3Smrg	fbdevHWRestore(pScrn);
2569c582b7e3Smrg	return;
2570c582b7e3Smrg    }
257179e5230eSmacallan#endif
2572c582b7e3Smrg    R128Blank(pScrn);
2573c582b7e3Smrg
2574b3ff493bSmrg    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
2575b3ff493bSmrg    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
2576b3ff493bSmrg    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
2577b3ff493bSmrg    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
2578b3ff493bSmrg    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
2579c582b7e3Smrg
2580b3ff493bSmrg    R128RestoreCommonRegisters(pScrn, restore);
2581b3ff493bSmrg    if (pR128Ent->HasCRTC2) {
2582b3ff493bSmrg        R128RestoreDDA2Registers(pScrn, restore);
2583b3ff493bSmrg        R128RestoreCrtc2Registers(pScrn, restore);
2584b3ff493bSmrg        R128RestorePLL2Registers(pScrn, restore);
2585b3ff493bSmrg    }
2586b3ff493bSmrg    R128RestoreDDARegisters(pScrn, restore);
2587b3ff493bSmrg    R128RestoreCrtcRegisters(pScrn, restore);
2588b3ff493bSmrg    R128RestorePLLRegisters(pScrn, restore);
2589b3ff493bSmrg    R128RestoreDACRegisters(pScrn, restore);
2590b3ff493bSmrg    R128RestoreRMXRegisters(pScrn, restore);
2591b3ff493bSmrg    R128RestoreFPRegisters(pScrn, restore);
2592b3ff493bSmrg    R128RestoreLVDSRegisters(pScrn, restore);
25939e881af1Smacallan
25945ef9b84eSmacallan    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
25955ef9b84eSmacallan    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
25965ef9b84eSmacallan    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
25975ef9b84eSmacallan    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
25985ef9b84eSmacallan    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
25999e881af1Smacallan
2600c582b7e3Smrg#ifdef WITH_VGAHW
2601c582b7e3Smrg    if (info->VGAAccess) {
2602c582b7e3Smrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2603b3ff493bSmrg        vgaHWUnlock(hwp);
2604c582b7e3Smrg# if defined(__powerpc__)
2605b3ff493bSmrg        /* Temporary hack to prevent crashing on PowerMacs when trying to
2606b3ff493bSmrg         * write VGA fonts, will find a better solution in the future
2607b3ff493bSmrg         */
2608b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
2609c582b7e3Smrg# else
2610b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
2611c582b7e3Smrg# endif
2612b3ff493bSmrg        vgaHWLock(hwp);
2613c582b7e3Smrg    }
2614c582b7e3Smrg#endif
2615c582b7e3Smrg
2616c582b7e3Smrg    R128WaitForVerticalSync(pScrn);
2617c582b7e3Smrg    R128Unblank(pScrn);
2618c582b7e3Smrg}
2619c582b7e3Smrg
2620c582b7e3Smrg/* Define common registers for requested video mode. */
2621b3ff493bSmrgvoid R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
2622c582b7e3Smrg{
2623c582b7e3Smrg    save->ovr_clr            = 0;
2624c582b7e3Smrg    save->ovr_wid_left_right = 0;
2625c582b7e3Smrg    save->ovr_wid_top_bottom = 0;
2626c582b7e3Smrg    save->ov0_scale_cntl     = 0;
2627c582b7e3Smrg    save->mpp_tb_config      = 0;
2628c582b7e3Smrg    save->mpp_gp_config      = 0;
2629c582b7e3Smrg    save->subpic_cntl        = 0;
2630c582b7e3Smrg    save->viph_control       = 0;
2631c582b7e3Smrg    save->i2c_cntl_1         = 0;
263284354367Smrg#ifdef R128DRI
2633c582b7e3Smrg    save->gen_int_cntl       = info->gen_int_cntl;
2634c582b7e3Smrg#else
2635c582b7e3Smrg    save->gen_int_cntl       = 0;
2636c582b7e3Smrg#endif
2637c582b7e3Smrg    save->cap0_trig_cntl     = 0;
2638c582b7e3Smrg    save->cap1_trig_cntl     = 0;
2639c582b7e3Smrg    save->bus_cntl           = info->BusCntl;
2640c582b7e3Smrg    /*
2641c582b7e3Smrg     * If bursts are enabled, turn on discards and aborts
2642c582b7e3Smrg     */
2643c582b7e3Smrg    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
2644c582b7e3Smrg	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
2645c582b7e3Smrg}
2646c582b7e3Smrg
2647b3ff493bSmrg/* Define RMX registers for the requested video mode. */
2648b3ff493bSmrgvoid R128InitRMXRegisters(R128SavePtr orig, R128SavePtr save,
2649b3ff493bSmrg                          xf86OutputPtr output, DisplayModePtr mode)
2650c582b7e3Smrg{
2651b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2652b3ff493bSmrg
2653c582b7e3Smrg    int   xres = mode->CrtcHDisplay;
2654c582b7e3Smrg    int   yres = mode->CrtcVDisplay;
2655c582b7e3Smrg    float Hratio, Vratio;
2656c582b7e3Smrg
2657b3ff493bSmrg    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
2658b3ff493bSmrg    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
2659b3ff493bSmrg    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
2660b3ff493bSmrg    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
2661b3ff493bSmrg
2662b3ff493bSmrg    if (r128_output->MonType != MT_DFP && r128_output->MonType != MT_LCD)
2663c582b7e3Smrg        return;
2664c582b7e3Smrg
2665b3ff493bSmrg    if (r128_output->PanelXRes == 0 || r128_output->PanelYRes == 0) {
2666b3ff493bSmrg        xres = r128_output->PanelXRes;
2667b3ff493bSmrg        yres = r128_output->PanelYRes;
2668b3ff493bSmrg
2669b3ff493bSmrg        Hratio = 1.0;
2670b3ff493bSmrg        Vratio = 1.0;
2671b3ff493bSmrg    } else {
2672b3ff493bSmrg        if (xres > r128_output->PanelXRes) xres = r128_output->PanelXRes;
2673b3ff493bSmrg        if (yres > r128_output->PanelYRes) yres = r128_output->PanelYRes;
2674c582b7e3Smrg
2675b3ff493bSmrg        Hratio = (float)xres/(float)r128_output->PanelXRes;
2676b3ff493bSmrg        Vratio = (float)yres/(float)r128_output->PanelYRes;
2677b3ff493bSmrg    }
2678c582b7e3Smrg
2679c582b7e3Smrg    save->fp_horz_stretch =
2680c582b7e3Smrg	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
2681c582b7e3Smrg	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
2682c582b7e3Smrg       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
2683c582b7e3Smrg                                 R128_HORZ_FP_LOOP_STRETCH |
2684c582b7e3Smrg                                 R128_HORZ_STRETCH_RESERVED)));
2685c582b7e3Smrg    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
2686c582b7e3Smrg    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
2687b3ff493bSmrg    if (xres == r128_output->PanelXRes)
2688c582b7e3Smrg         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
2689c582b7e3Smrg    else
2690c582b7e3Smrg         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
2691c582b7e3Smrg
2692c582b7e3Smrg    save->fp_vert_stretch =
2693c582b7e3Smrg	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
2694c582b7e3Smrg	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
2695c582b7e3Smrg	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
2696c582b7e3Smrg				   R128_VERT_STRETCH_RESERVED)));
2697c582b7e3Smrg    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
2698b3ff493bSmrg    if (yres == r128_output->PanelYRes)
2699c582b7e3Smrg        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
2700c582b7e3Smrg    else
2701c582b7e3Smrg        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
2702b3ff493bSmrg}
2703c582b7e3Smrg
2704b3ff493bSmrg/* Define flat panel registers for the requested video mode. */
2705b3ff493bSmrgvoid R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
2706b3ff493bSmrg{
2707b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
2708b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
2709c582b7e3Smrg
2710c582b7e3Smrg    /* WARNING: Be careful about turning on the flat panel */
2711b3ff493bSmrg    save->fp_gen_cntl            = orig->fp_gen_cntl;
2712b3ff493bSmrg    save->fp_panel_cntl          = orig->fp_panel_cntl;
2713b3ff493bSmrg    save->tmds_transmitter_cntl  = orig->tmds_transmitter_cntl;
2714b3ff493bSmrg    save->tmds_crc               = orig->tmds_crc;
2715b3ff493bSmrg
2716b3ff493bSmrg    if (r128_crtc->crtc_id)
2717b3ff493bSmrg        save->fp_gen_cntl       |=   R128_FP_SEL_CRTC2;
2718c582b7e3Smrg    else
2719b3ff493bSmrg        save->fp_gen_cntl       &=  ~R128_FP_SEL_CRTC2;
2720c582b7e3Smrg
2721b3ff493bSmrg    save->fp_gen_cntl           &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
2722b3ff493bSmrg                                     R128_FP_CRTC_USE_SHADOW_ROWCUR |
2723b3ff493bSmrg                                     R128_FP_CRTC_HORZ_DIV2_EN |
2724b3ff493bSmrg                                     R128_FP_CRTC_HOR_CRT_DIV2_DIS |
2725b3ff493bSmrg                                     R128_FP_CRT_SYNC_SEL |
2726b3ff493bSmrg                                     R128_FP_USE_SHADOW_EN);
2727b3ff493bSmrg
2728b3ff493bSmrg    save->fp_gen_cntl           |=  (R128_FP_CRTC_DONT_SHADOW_VPAR |
2729b3ff493bSmrg                                     R128_FP_CRTC_DONT_SHADOW_HEND);
2730b3ff493bSmrg
2731b3ff493bSmrg    save->fp_panel_cntl         |=  (R128_FP_DIGON | R128_FP_BLON);
2732b3ff493bSmrg    save->tmds_transmitter_cntl &=  ~R128_TMDS_PLLRST;
2733b3ff493bSmrg    save->tmds_transmitter_cntl |=   R128_TMDS_PLLEN;
2734b3ff493bSmrg}
2735b3ff493bSmrg
2736b3ff493bSmrg/* Define LVDS registers for the requested video mode. */
2737b3ff493bSmrgvoid R128InitLVDSRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
2738b3ff493bSmrg{
2739b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
2740b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
2741b3ff493bSmrg
2742b3ff493bSmrg    save->lvds_gen_cntl      =  orig->lvds_gen_cntl;
2743b3ff493bSmrg
2744b3ff493bSmrg    if (r128_crtc->crtc_id)
2745b3ff493bSmrg        save->lvds_gen_cntl |=  R128_LVDS_SEL_CRTC2;
2746b3ff493bSmrg    else
2747b3ff493bSmrg        save->lvds_gen_cntl &= ~R128_LVDS_SEL_CRTC2;
2748c582b7e3Smrg}
2749c582b7e3Smrg
2750c582b7e3Smrg#if 0
2751c582b7e3Smrg/* Define initial palette for requested video mode.  This doesn't do
2752c582b7e3Smrg   anything for XFree86 4.0. */
2753c582b7e3Smrgstatic void R128InitPalette(R128SavePtr save)
2754c582b7e3Smrg{
2755c582b7e3Smrg    save->palette_valid = FALSE;
2756c582b7e3Smrg}
2757c582b7e3Smrg#endif
2758c582b7e3Smrg
2759c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode)
2760c582b7e3Smrg{
276184354367Smrg    ScrnInfoPtr   pScrn = xf86ScreenToScrn(pScreen);
2762c582b7e3Smrg    Bool unblank;
2763c582b7e3Smrg
2764c582b7e3Smrg    unblank = xf86IsUnblank(mode);
2765c582b7e3Smrg    if (unblank)
2766c582b7e3Smrg	SetTimeSinceLastInputEvent();
2767c582b7e3Smrg
2768c582b7e3Smrg    if ((pScrn != NULL) && pScrn->vtSema) {
2769c582b7e3Smrg	if (unblank)
2770c582b7e3Smrg		R128Unblank(pScrn);
2771c582b7e3Smrg	else
2772c582b7e3Smrg		R128Blank(pScrn);
2773c582b7e3Smrg    }
2774c582b7e3Smrg    return TRUE;
2775c582b7e3Smrg}
2776c582b7e3Smrg
2777c582b7e3Smrg/*
2778c582b7e3Smrg * SwitchMode() doesn't work right on crtc2 on some laptops.
2779c582b7e3Smrg * The workaround is to switch the mode, then switch to another VT, then
2780c582b7e3Smrg * switch back. --AGD
2781c582b7e3Smrg */
278284354367SmrgBool R128SwitchMode(SWITCH_MODE_ARGS_DECL)
2783c582b7e3Smrg{
278484354367Smrg    SCRN_INFO_PTR(arg);
2785c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2786c582b7e3Smrg    Bool ret;
2787c582b7e3Smrg
2788c582b7e3Smrg    info->SwitchingMode = TRUE;
2789b3ff493bSmrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
2790c582b7e3Smrg    info->SwitchingMode = FALSE;
2791c582b7e3Smrg    return ret;
2792c582b7e3Smrg}
2793c582b7e3Smrg
2794b3ff493bSmrgModeStatus R128DoValidMode(xf86OutputPtr output, DisplayModePtr mode, int flags)
2795c582b7e3Smrg{
2796b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
2797b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2798b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2799b3ff493bSmrg    int i, j;
2800c582b7e3Smrg
2801b3ff493bSmrg    if (r128_output->MonType == MT_CRT)
2802b3ff493bSmrg        return MODE_OK;
2803c582b7e3Smrg
2804b3ff493bSmrg    if (r128_output->MonType == MT_DFP || r128_output->MonType == MT_LCD) {
2805c582b7e3Smrg	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
2806c582b7e3Smrg	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
2807c582b7e3Smrg    }
2808c582b7e3Smrg
2809b3ff493bSmrg    if (r128_output->MonType == MT_LCD && info->VBIOS) {
2810b3ff493bSmrg	for (i = info->FPBIOSstart + 64; R128_BIOS16(i) != 0; i += 2) {
2811b3ff493bSmrg	    j = R128_BIOS16(i);
2812c582b7e3Smrg
2813c582b7e3Smrg	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
2814b3ff493bSmrg		mode->CrtcVDisplay == R128_BIOS16(j + 2)) {
2815c582b7e3Smrg		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
2816c582b7e3Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2817c582b7e3Smrg			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
2818b3ff493bSmrg			       mode->CrtcHDisplay, mode->CrtcVDisplay,
2819b3ff493bSmrg			       (float)mode->Clock / 1000);
2820c582b7e3Smrg
2821c582b7e3Smrg		    /* Assume we are using expanded mode */
2822b3ff493bSmrg		    if (R128_BIOS16(j + 5)) j  = R128_BIOS16(j + 5);
2823b3ff493bSmrg		    else                    j += 9;
2824c582b7e3Smrg
2825b3ff493bSmrg		    mode->Clock = (uint32_t)R128_BIOS16(j) * 10;
2826c582b7e3Smrg
2827c582b7e3Smrg		    mode->HDisplay   = mode->CrtcHDisplay   =
2828b3ff493bSmrg			((R128_BIOS16(j + 10) & 0x01ff) + 1) * 8;
2829c582b7e3Smrg		    mode->HSyncStart = mode->CrtcHSyncStart =
2830b3ff493bSmrg			((R128_BIOS16(j + 12) & 0x01ff) + 1) * 8;
2831c582b7e3Smrg		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
2832b3ff493bSmrg			mode->CrtcHSyncStart + (R128_BIOS8(j + 14) & 0x1f);
2833c582b7e3Smrg		    mode->HTotal     = mode->CrtcHTotal     =
2834b3ff493bSmrg			((R128_BIOS16(j + 8)  & 0x01ff) + 1) * 8;
2835c582b7e3Smrg
2836c582b7e3Smrg		    mode->VDisplay   = mode->CrtcVDisplay   =
2837b3ff493bSmrg			(R128_BIOS16(j + 17) & 0x07ff) + 1;
2838c582b7e3Smrg		    mode->VSyncStart = mode->CrtcVSyncStart =
2839b3ff493bSmrg			(R128_BIOS16(j + 19) & 0x07ff) + 1;
2840c582b7e3Smrg		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
2841b3ff493bSmrg			mode->CrtcVSyncStart + ((R128_BIOS16(j + 19) >> 11) & 0x1f);
2842c582b7e3Smrg		    mode->VTotal     = mode->CrtcVTotal     =
2843b3ff493bSmrg			(R128_BIOS16(j + 15) & 0x07ff) + 1;
2844c582b7e3Smrg		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
2845c582b7e3Smrg			       mode->CrtcHDisplay,mode->CrtcVDisplay,
2846b3ff493bSmrg			       (float)mode->Clock/ 1000);
2847c582b7e3Smrg		}
2848c582b7e3Smrg		return MODE_OK;
2849c582b7e3Smrg	    }
2850c582b7e3Smrg	}
2851c582b7e3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
2852c582b7e3Smrg		       "Mode rejected for FP %ix%i [pclk: %.1f] "
2853c582b7e3Smrg		       "(not listed in VBIOS)\n",
2854c582b7e3Smrg		       mode->CrtcHDisplay, mode->CrtcVDisplay,
2855c582b7e3Smrg		       (float)mode->Clock / 1000);
2856c582b7e3Smrg	return MODE_NOMODE;
2857c582b7e3Smrg    }
2858c582b7e3Smrg
2859c582b7e3Smrg    return MODE_OK;
2860c582b7e3Smrg}
2861c582b7e3Smrg
2862b3ff493bSmrg/* Used to disallow modes that are not supported by the hardware. */
2863b3ff493bSmrgModeStatus R128ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
2864b3ff493bSmrg                                   Bool verbose, int flags)
2865b3ff493bSmrg{
2866b3ff493bSmrg    SCRN_INFO_PTR(arg);
2867b3ff493bSmrg    R128EntPtr  pR128Ent = R128EntPriv(pScrn);
2868b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2869b3ff493bSmrg
2870b3ff493bSmrg    return R128DoValidMode(output, mode, flags);
2871b3ff493bSmrg}
2872b3ff493bSmrg
2873c582b7e3Smrg/* Adjust viewport into virtual desktop such that (0,0) in viewport space
2874c582b7e3Smrg   is (x,y) in virtual space. */
287584354367Smrgvoid R128AdjustFrame(ADJUST_FRAME_ARGS_DECL)
2876c582b7e3Smrg{
287784354367Smrg    SCRN_INFO_PTR(arg);
2878c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2879c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2880c582b7e3Smrg    int           Base;
2881c582b7e3Smrg
2882c582b7e3Smrg    if(info->showCache && y && pScrn->vtSema)
2883c582b7e3Smrg        y += pScrn->virtualY - 1;
2884c582b7e3Smrg
2885c582b7e3Smrg    Base = y * info->CurrentLayout.displayWidth + x;
2886c582b7e3Smrg
2887c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
2888c582b7e3Smrg    case 15:
2889c582b7e3Smrg    case 16: Base *= 2; break;
2890c582b7e3Smrg    case 24: Base *= 3; break;
2891c582b7e3Smrg    case 32: Base *= 4; break;
2892c582b7e3Smrg    }
2893c582b7e3Smrg
2894c582b7e3Smrg    Base &= ~7;                 /* 3 lower bits are always 0 */
2895c582b7e3Smrg
2896c582b7e3Smrg    if (info->CurrentLayout.pixel_code == 24)
2897c582b7e3Smrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2898c582b7e3Smrg
2899c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET, Base);
2900c582b7e3Smrg}
2901c582b7e3Smrg
2902c582b7e3Smrg/* Called when VT switching back to the X server.  Reinitialize the video
2903c582b7e3Smrg   mode. */
290484354367SmrgBool R128EnterVT(VT_FUNC_ARGS_DECL)
2905c582b7e3Smrg{
290684354367Smrg    SCRN_INFO_PTR(arg);
2907c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
2908c582b7e3Smrg
290981f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
291081f79626Smrg                        "%s\n", __func__));
2911b3ff493bSmrg
2912b3ff493bSmrg    pScrn->vtSema = TRUE;
291379e5230eSmacallan#ifndef AVOID_FBDEV
2914c582b7e3Smrg    if (info->FBDev) {
291584354367Smrg        if (!fbdevHWEnterVT(VT_FUNC_ARGS)) return FALSE;
29163c921f55Smrg    } else {
291779e5230eSmacallan#endif
29183c921f55Smrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
29193c921f55Smrg#ifndef AVOID_FBDEV
2920b3ff493bSmrg    }
29213c921f55Smrg#endif
2922b3ff493bSmrg
2923c582b7e3Smrg    if (info->accelOn)
2924c582b7e3Smrg	R128EngineInit(pScrn);
2925c582b7e3Smrg
292684354367Smrg#ifdef R128DRI
2927c582b7e3Smrg    if (info->directRenderingEnabled) {
2928c582b7e3Smrg	if (info->irq) {
2929c582b7e3Smrg	    /* Need to make sure interrupts are enabled */
2930c582b7e3Smrg	    unsigned char *R128MMIO = info->MMIO;
2931c582b7e3Smrg	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
2932c582b7e3Smrg	}
2933c582b7e3Smrg	R128CCE_START(pScrn, info);
2934c582b7e3Smrg	DRIUnlock(pScrn->pScreen);
2935c582b7e3Smrg    }
2936c582b7e3Smrg#endif
2937c582b7e3Smrg
2938c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
2939b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2940c582b7e3Smrg
2941c582b7e3Smrg    return TRUE;
2942c582b7e3Smrg}
2943c582b7e3Smrg
2944c582b7e3Smrg/* Called when VT switching away from the X server.  Restore the original
2945c582b7e3Smrg   text mode. */
294684354367Smrgvoid R128LeaveVT(VT_FUNC_ARGS_DECL)
2947c582b7e3Smrg{
294884354367Smrg    SCRN_INFO_PTR(arg);
2949c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
2950c582b7e3Smrg    R128SavePtr save  = &info->ModeReg;
2951c582b7e3Smrg
295281f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
295381f79626Smrg                        "%s\n", __func__));
295484354367Smrg#ifdef R128DRI
2955c582b7e3Smrg    if (info->directRenderingEnabled) {
2956c582b7e3Smrg	DRILock(pScrn->pScreen, 0);
2957c582b7e3Smrg	R128CCE_STOP(pScrn, info);
2958c582b7e3Smrg    }
295984354367Smrg#ifdef USE_EXA
296084354367Smrg    if (info->useEXA)
296184354367Smrg        info->state_2d.composite_setup = FALSE;
296284354367Smrg#endif
2963c582b7e3Smrg#endif
2964c582b7e3Smrg    R128SavePalette(pScrn, save);
2965c582b7e3Smrg    info->PaletteSavedOnVT = TRUE;
296679e5230eSmacallan#ifndef AVOID_FBDEV
2967c582b7e3Smrg    if (info->FBDev)
296884354367Smrg        fbdevHWLeaveVT(VT_FUNC_ARGS);
2969c582b7e3Smrg    else
297079e5230eSmacallan#endif
2971c582b7e3Smrg        R128Restore(pScrn);
2972c582b7e3Smrg}
2973c582b7e3Smrg
2974c582b7e3Smrg
2975c582b7e3Smrg/* Called at the end of each server generation.  Restore the original text
2976c582b7e3Smrg   mode, unmap video memory, and unwrap and call the saved CloseScreen
2977c582b7e3Smrg   function.  */
297884354367Smrgstatic Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL)
2979c582b7e3Smrg{
298084354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2981c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
2982c582b7e3Smrg
298381f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
298481f79626Smrg                        "%s\n", __func__));
2985c582b7e3Smrg
298684354367Smrg#ifdef R128DRI
2987c582b7e3Smrg				/* Disable direct rendering */
2988c582b7e3Smrg    if (info->directRenderingEnabled) {
2989c582b7e3Smrg	R128DRICloseScreen(pScreen);
2990c582b7e3Smrg	info->directRenderingEnabled = FALSE;
2991c582b7e3Smrg    }
2992c582b7e3Smrg#endif
2993c582b7e3Smrg
2994c582b7e3Smrg    if (pScrn->vtSema) {
2995c582b7e3Smrg	R128Restore(pScrn);
2996c582b7e3Smrg	R128UnmapMem(pScrn);
2997c582b7e3Smrg    }
2998c582b7e3Smrg
299984354367Smrg#ifdef USE_EXA
300084354367Smrg        if (info->useEXA) {
300184354367Smrg	    exaDriverFini(pScreen);
300284354367Smrg	    free(info->ExaDriver);
300384354367Smrg	} else
300484354367Smrg#endif
300584354367Smrg#ifdef HAVE_XAA_H
300684354367Smrg	{
300784354367Smrg            if (info->accel)             XAADestroyInfoRec(info->accel);
300884354367Smrg	    info->accel                  = NULL;
300984354367Smrg        }
301084354367Smrg#endif
3011c582b7e3Smrg
301284354367Smrg    if (info->scratch_save)      free(info->scratch_save);
3013c582b7e3Smrg    info->scratch_save           = NULL;
3014c582b7e3Smrg
3015c582b7e3Smrg    if (info->adaptor) {
301684354367Smrg        free(info->adaptor->pPortPrivates[0].ptr);
3017c582b7e3Smrg	xf86XVFreeVideoAdaptorRec(info->adaptor);
3018c582b7e3Smrg	info->adaptor = NULL;
3019c582b7e3Smrg    }
3020c582b7e3Smrg
3021c582b7e3Smrg    pScrn->vtSema = FALSE;
3022c582b7e3Smrg
3023c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
3024c582b7e3Smrg    pScreen->CloseScreen = info->CloseScreen;
302584354367Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3026c582b7e3Smrg}
3027c582b7e3Smrg
302884354367Smrgvoid R128FreeScreen(FREE_SCREEN_ARGS_DECL)
3029c582b7e3Smrg{
303084354367Smrg    SCRN_INFO_PTR(arg);
3031c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3032c582b7e3Smrg
303381f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
303481f79626Smrg                        "%s\n", __func__));
303519019ffeSmrg    if (info == NULL)
303619019ffeSmrg	return;
3037c582b7e3Smrg#ifdef WITH_VGAHW
3038c582b7e3Smrg    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
3039c582b7e3Smrg	vgaHWFreeHWRec(pScrn);
3040c582b7e3Smrg#endif
3041c582b7e3Smrg    R128FreeRec(pScrn);
3042c582b7e3Smrg}
3043