r128_driver.c revision 81f79626
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#ifndef HAVE_XAA_H
159281f79626Smrg    info->useEXA = TRUE;
1593c582b7e3Smrg#endif
1594c582b7e3Smrg
159581f79626Smrg    info->swCursor = FALSE;
159681f79626Smrg
159781f79626Smrg    r128AcquireOption(pScrn);
159881f79626Smrg
1599c582b7e3Smrg    if (!R128PreInitWeight(pScrn))    goto fail;
1600c582b7e3Smrg
160181f79626Smrg    /* Allocate an xf86CrtcConfig */
160281f79626Smrg    xf86CrtcConfigInit(pScrn, &R128CRTCResizeFuncs);
1603c582b7e3Smrg
160481f79626Smrg    R128LegacyMS(pScrn);
160581f79626Smrg
160681f79626Smrg    if (!xf86InitialConfiguration(pScrn, TRUE)) {
160781f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
160881f79626Smrg        goto fail;
1609c582b7e3Smrg    }
161081f79626Smrg    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
1611b3ff493bSmrg
1612b3ff493bSmrg    /* Set display resolution */
1613b3ff493bSmrg    xf86SetDpi(pScrn, 0, 0);
1614b3ff493bSmrg
1615b3ff493bSmrg    /* Get ScreenInit function */
1616b3ff493bSmrg    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
1617b3ff493bSmrg
161881f79626Smrg    R128PreInitAccel(pScrn);
1619c582b7e3Smrg
1620b3ff493bSmrg    info->CurrentLayout.displayWidth = pScrn->displayWidth;
1621b3ff493bSmrg
1622b3ff493bSmrg    if (!xf86RandR12PreInit(pScrn)) {
1623b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
1624b3ff493bSmrg        goto fail;
1625b3ff493bSmrg    }
1626b3ff493bSmrg
1627b3ff493bSmrg    if (pScrn->modes == NULL) {
1628b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1629b3ff493bSmrg        goto fail;
1630b3ff493bSmrg    }
1631b3ff493bSmrg
1632c582b7e3Smrg				/* Free the video bios (if applicable) */
1633c582b7e3Smrg    if (info->VBIOS) {
163484354367Smrg	free(info->VBIOS);
1635c582b7e3Smrg	info->VBIOS = NULL;
1636c582b7e3Smrg    }
1637c582b7e3Smrg
1638b3ff493bSmrg    if (info->MMIO) R128UnmapMMIO(pScrn);
1639b3ff493bSmrg    info->MMIO = NULL;
1640b3ff493bSmrg
1641c582b7e3Smrg    return TRUE;
1642c582b7e3Smrg
1643c582b7e3Smrg  fail:
1644c582b7e3Smrg				/* Pre-init failed. */
1645c582b7e3Smrg
1646c582b7e3Smrg				/* Free the video bios (if applicable) */
1647c582b7e3Smrg    if (info->VBIOS) {
164884354367Smrg	free(info->VBIOS);
1649c582b7e3Smrg	info->VBIOS = NULL;
1650c582b7e3Smrg    }
1651c582b7e3Smrg
1652c582b7e3Smrg#ifdef WITH_VGAHW
1653c582b7e3Smrg    if (info->VGAAccess)
1654c582b7e3Smrg           vgaHWFreeHWRec(pScrn);
1655c582b7e3Smrg#endif
1656b3ff493bSmrg
1657b3ff493bSmrg    if (info->MMIO) R128UnmapMMIO(pScrn);
1658b3ff493bSmrg    info->MMIO = NULL;
1659b3ff493bSmrg
1660c582b7e3Smrg    R128FreeRec(pScrn);
1661c582b7e3Smrg    return FALSE;
1662c582b7e3Smrg}
1663c582b7e3Smrg
1664c582b7e3Smrg/* Load a palette. */
1665c582b7e3Smrgstatic void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
1666c582b7e3Smrg			    int *indices, LOCO *colors, VisualPtr pVisual)
1667c582b7e3Smrg{
1668c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
1669b3ff493bSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1670b3ff493bSmrg    int i, j;
1671b3ff493bSmrg    int c, index;
1672b3ff493bSmrg    uint16_t lut_r[256], lut_g[256], lut_b[256];
1673b3ff493bSmrg
1674b3ff493bSmrg    for (c = 0; c < xf86_config->num_crtc; c++) {
1675b3ff493bSmrg        xf86CrtcPtr crtc = xf86_config->crtc[c];
1676b3ff493bSmrg        R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
1677b3ff493bSmrg
1678b3ff493bSmrg        for (i = 0 ; i < 256; i++) {
1679b3ff493bSmrg            lut_r[i] = r128_crtc->lut_r[i] << 8;
1680b3ff493bSmrg            lut_g[i] = r128_crtc->lut_g[i] << 8;
1681b3ff493bSmrg            lut_b[i] = r128_crtc->lut_b[i] << 8;
1682b3ff493bSmrg        }
1683c582b7e3Smrg
1684b3ff493bSmrg        switch (info->CurrentLayout.depth) {
1685b3ff493bSmrg        case 15:
1686b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1687b3ff493bSmrg                index = indices[i];
1688b3ff493bSmrg                for (j = 0; j < 8; j++) {
1689b3ff493bSmrg                    lut_r[index * 8 + j] = colors[index].red << 8;
1690b3ff493bSmrg                    lut_g[index * 8 + j] = colors[index].green << 8;
1691b3ff493bSmrg                    lut_b[index * 8 + j] = colors[index].blue << 8;
1692b3ff493bSmrg                }
1693b3ff493bSmrg            }
1694b3ff493bSmrg        case 16:
1695b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1696b3ff493bSmrg                index = indices[i];
1697b3ff493bSmrg
1698b3ff493bSmrg                /* XXX: The old version of R128LoadPalette did not do this and
1699b3ff493bSmrg                 * the old version of RADEONLoadPalette has a comment asking why.
1700b3ff493bSmrg                 */
1701b3ff493bSmrg                if (i <= 31) {
1702b3ff493bSmrg                    for (j = 0; j < 8; j++) {
1703b3ff493bSmrg                        lut_r[index * 8 + j] = colors[index].red << 8;
1704b3ff493bSmrg                        lut_b[index * 8 + j] = colors[index].blue << 8;
1705b3ff493bSmrg                    }
1706b3ff493bSmrg                }
1707c582b7e3Smrg
1708b3ff493bSmrg                for (j = 0; j < 4; j++) {
1709b3ff493bSmrg                    lut_g[index * 4 + j] = colors[index].green << 8;
1710b3ff493bSmrg                }
1711b3ff493bSmrg            }
1712b3ff493bSmrg        default:
1713b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1714b3ff493bSmrg                index = indices[i];
1715b3ff493bSmrg                lut_r[index] = colors[index].red << 8;
1716b3ff493bSmrg                lut_g[index] = colors[index].green << 8;
1717b3ff493bSmrg                lut_b[index] = colors[index].blue << 8;
1718b3ff493bSmrg            }
1719b3ff493bSmrg            break;
1720b3ff493bSmrg        }
1721c582b7e3Smrg
1722b3ff493bSmrg        /* Make the change through RandR */
1723b3ff493bSmrg#ifdef RANDR_12_INTERFACE
1724b3ff493bSmrg        if (crtc->randr_crtc)
1725b3ff493bSmrg            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1726b3ff493bSmrg        else
1727b3ff493bSmrg#endif
1728b3ff493bSmrg        crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1729c582b7e3Smrg    }
1730c582b7e3Smrg}
1731c582b7e3Smrg
1732c582b7e3Smrgstatic void
173384354367SmrgR128BlockHandler(BLOCKHANDLER_ARGS_DECL)
1734c582b7e3Smrg{
173584354367Smrg    SCREEN_PTR(arg);
173684354367Smrg    ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
1737c582b7e3Smrg    R128InfoPtr info    = R128PTR(pScrn);
1738c582b7e3Smrg
173984354367Smrg#ifdef R128DRI
1740c582b7e3Smrg    if (info->directRenderingEnabled)
1741c582b7e3Smrg        FLUSH_RING();
1742c582b7e3Smrg#endif
1743c582b7e3Smrg
1744c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
174584354367Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1746c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
1747c582b7e3Smrg
1748c582b7e3Smrg    if(info->VideoTimerCallback) {
1749c582b7e3Smrg        (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
1750c582b7e3Smrg    }
1751c582b7e3Smrg}
1752c582b7e3Smrg
1753c582b7e3Smrg/* Called at the start of each server generation. */
175484354367SmrgBool R128ScreenInit(SCREEN_INIT_ARGS_DECL)
1755c582b7e3Smrg{
175684354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1757c582b7e3Smrg    R128InfoPtr info   = R128PTR(pScrn);
1758c582b7e3Smrg    BoxRec      MemBox;
175984354367Smrg    int width_bytes = (pScrn->displayWidth *
176081f79626Smrg                        info->CurrentLayout.pixel_bytes);
176181f79626Smrg    int scanlines;
176281f79626Smrg    int total = info->FbMapSize;
176381f79626Smrg    FBAreaPtr fbarea = NULL;
176481f79626Smrg#ifdef R128DRI
176581f79626Smrg    int cpp = info->CurrentLayout.pixel_bytes;
176681f79626Smrg    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
176784354367Smrg#ifdef USE_EXA
176884354367Smrg    ExaOffscreenArea*     osArea = NULL;
176981f79626Smrg#endif /* USE_EXA */
177081f79626Smrg#endif /* R128DRI */
177184354367Smrg
177281f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
177381f79626Smrg                        "%s %lx %lx\n",
177481f79626Smrg                        __func__,
177581f79626Smrg                        pScrn->memPhysBase, pScrn->fbOffset));
1776c582b7e3Smrg
177784354367Smrg#ifdef R128DRI
1778c582b7e3Smrg				/* Turn off the CCE for now. */
1779c582b7e3Smrg    info->CCEInUse     = FALSE;
1780c582b7e3Smrg    info->indirectBuffer = NULL;
1781c582b7e3Smrg#endif
1782c582b7e3Smrg
1783c582b7e3Smrg    if (!R128MapMem(pScrn)) return FALSE;
1784c582b7e3Smrg    pScrn->fbOffset    = 0;
1785b3ff493bSmrg    //if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
178684354367Smrg#ifdef R128DRI
1787c582b7e3Smrg    info->fbX          = 0;
1788c582b7e3Smrg    info->fbY          = 0;
1789c582b7e3Smrg    info->frontOffset  = 0;
1790c582b7e3Smrg    info->frontPitch   = pScrn->displayWidth;
1791c582b7e3Smrg#endif
1792c582b7e3Smrg
1793c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
1794c582b7e3Smrg
1795c582b7e3Smrg    R128Save(pScrn);
1796c582b7e3Smrg
1797c582b7e3Smrg				/* Visual setup */
1798c582b7e3Smrg    miClearVisualTypes();
1799c582b7e3Smrg    if (!miSetVisualTypes(pScrn->depth,
1800c582b7e3Smrg			  miGetDefaultVisualMask(pScrn->depth),
1801c582b7e3Smrg			  pScrn->rgbBits,
1802c582b7e3Smrg			  pScrn->defaultVisual)) return FALSE;
1803c582b7e3Smrg    miSetPixmapDepths ();
1804c582b7e3Smrg
180584354367Smrg#ifdef R128DRI
1806c582b7e3Smrg				/* Setup DRI after visuals have been
1807c582b7e3Smrg				   established, but before fbScreenInit is
180881f79626Smrg				   called. */
1809c582b7e3Smrg    {
1810c582b7e3Smrg	/* FIXME: When we move to dynamic allocation of back and depth
1811c582b7e3Smrg	   buffers, we will want to revisit the following check for 3
1812c582b7e3Smrg	   times the virtual size of the screen below. */
1813c582b7e3Smrg	int maxy        = info->FbMapSize / width_bytes;
1814c582b7e3Smrg
181581f79626Smrg        if (info->noAccel) {
181684354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1817c582b7e3Smrg		       "Acceleration disabled, not initializing the DRI\n");
1818c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
1819c582b7e3Smrg	} else if (maxy <= pScrn->virtualY * 3) {
182084354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1821c582b7e3Smrg		       "Static buffer allocation failed -- "
1822c582b7e3Smrg		       "need at least %d kB video memory\n",
1823c582b7e3Smrg		       (pScrn->displayWidth * pScrn->virtualY *
1824c582b7e3Smrg			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
1825c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
1826c582b7e3Smrg	} else {
1827b3ff493bSmrg            info->directRenderingEnabled = R128DRIScreenInit(pScreen);
1828c582b7e3Smrg	}
1829c582b7e3Smrg    }
1830c582b7e3Smrg#endif
1831c582b7e3Smrg
1832c582b7e3Smrg    if (!fbScreenInit (pScreen, info->FB,
1833c582b7e3Smrg		       pScrn->virtualX, pScrn->virtualY,
1834c582b7e3Smrg		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1835c582b7e3Smrg		       pScrn->bitsPerPixel))
1836c582b7e3Smrg	return FALSE;
1837c582b7e3Smrg
1838c582b7e3Smrg    xf86SetBlackWhitePixels(pScreen);
1839c582b7e3Smrg
1840c582b7e3Smrg    if (pScrn->bitsPerPixel > 8) {
1841c582b7e3Smrg	VisualPtr visual;
1842c582b7e3Smrg
1843c582b7e3Smrg	visual = pScreen->visuals + pScreen->numVisuals;
1844c582b7e3Smrg	while (--visual >= pScreen->visuals) {
1845c582b7e3Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
1846c582b7e3Smrg		visual->offsetRed   = pScrn->offset.red;
1847c582b7e3Smrg		visual->offsetGreen = pScrn->offset.green;
1848c582b7e3Smrg		visual->offsetBlue  = pScrn->offset.blue;
1849c582b7e3Smrg		visual->redMask     = pScrn->mask.red;
1850c582b7e3Smrg		visual->greenMask   = pScrn->mask.green;
1851c582b7e3Smrg		visual->blueMask    = pScrn->mask.blue;
1852c582b7e3Smrg	    }
1853c582b7e3Smrg	}
1854c582b7e3Smrg    }
1855c582b7e3Smrg
1856c582b7e3Smrg    /* must be after RGB order fixed */
1857c582b7e3Smrg    fbPictureInit (pScreen, 0, 0);
1858c582b7e3Smrg
1859c582b7e3Smrg				/* Memory manager setup */
186084354367Smrg#ifdef R128DRI
1861c582b7e3Smrg    if (info->directRenderingEnabled) {
1862c582b7e3Smrg	int bufferSize = pScrn->virtualY * width_bytes;
186381f79626Smrg	int l;
1864c582b7e3Smrg
1865c582b7e3Smrg	switch (info->CCEMode) {
1866c582b7e3Smrg	case R128_DEFAULT_CCE_PIO_MODE:
1867c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
1868c582b7e3Smrg	    break;
1869c582b7e3Smrg	case R128_DEFAULT_CCE_BM_MODE:
1870c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
1871c582b7e3Smrg	    break;
1872c582b7e3Smrg	default:
1873c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
1874c582b7e3Smrg	    break;
1875c582b7e3Smrg	}
1876c582b7e3Smrg
1877c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1878c582b7e3Smrg		   "Using %d MB AGP aperture\n", info->agpSize);
1879c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1880c582b7e3Smrg		   "Using %d MB for the ring buffer\n", info->ringSize);
1881c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1882c582b7e3Smrg		   "Using %d MB for vertex/indirect buffers\n", info->bufSize);
1883c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1884c582b7e3Smrg		   "Using %d MB for AGP textures\n", info->agpTexSize);
1885c582b7e3Smrg
1886c582b7e3Smrg	/* Try for front, back, depth, and two framebuffers worth of
1887c582b7e3Smrg	 * pixmap cache.  Should be enough for a fullscreen background
1888c582b7e3Smrg	 * image plus some leftovers.
1889c582b7e3Smrg	 */
1890c582b7e3Smrg	info->textureSize = info->FbMapSize - 5 * bufferSize;
1891c582b7e3Smrg
1892c582b7e3Smrg	/* If that gives us less than half the available memory, let's
1893c582b7e3Smrg	 * be greedy and grab some more.  Sorry, I care more about 3D
1894c582b7e3Smrg	 * performance than playing nicely, and you'll get around a full
1895c582b7e3Smrg	 * framebuffer's worth of pixmap cache anyway.
1896c582b7e3Smrg	 */
1897c582b7e3Smrg	if (info->textureSize < (int)info->FbMapSize / 2) {
1898c582b7e3Smrg	    info->textureSize = info->FbMapSize - 4 * bufferSize;
1899c582b7e3Smrg	}
1900c582b7e3Smrg
1901c582b7e3Smrg	if (info->textureSize > 0) {
1902c582b7e3Smrg	    l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
1903c582b7e3Smrg	    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
1904c582b7e3Smrg
1905c582b7e3Smrg	    /* Round the texture size up to the nearest whole number of
1906c582b7e3Smrg	     * texture regions.  Again, be greedy about this, don't
1907c582b7e3Smrg	     * round down.
1908c582b7e3Smrg	     */
1909c582b7e3Smrg	    info->log2TexGran = l;
1910c582b7e3Smrg	    info->textureSize = (info->textureSize >> l) << l;
1911c582b7e3Smrg	} else {
1912c582b7e3Smrg	    info->textureSize = 0;
1913c582b7e3Smrg	}
1914c582b7e3Smrg
1915c582b7e3Smrg	/* Set a minimum usable local texture heap size.  This will fit
1916c582b7e3Smrg	 * two 256x256x32bpp textures.
1917c582b7e3Smrg	 */
1918c582b7e3Smrg	if (info->textureSize < 512 * 1024) {
1919c582b7e3Smrg	    info->textureOffset = 0;
1920c582b7e3Smrg	    info->textureSize = 0;
1921c582b7e3Smrg	}
1922c582b7e3Smrg
192381f79626Smrg        total = info->FbMapSize - info->textureSize;
192481f79626Smrg    }
192581f79626Smrg#endif /* R128DRI */
1926c582b7e3Smrg
192781f79626Smrg    scanlines = total / width_bytes;
192881f79626Smrg    if (scanlines > 8191) scanlines = 8191;
192981f79626Smrg
193081f79626Smrg#ifdef R128DRI
193181f79626Smrg    if (info->directRenderingEnabled)
193281f79626Smrg        /*
193381f79626Smrg         * Recalculate the texture offset and size to accomodate any
193481f79626Smrg         * rounding to a whole number of scanlines.
193581f79626Smrg         */
193681f79626Smrg        info->textureOffset = scanlines * width_bytes;
193781f79626Smrg#endif /* R128DRI */
1938c582b7e3Smrg
193981f79626Smrg    MemBox.x1 = 0;
194081f79626Smrg    MemBox.y1 = 0;
194181f79626Smrg    MemBox.x2 = pScrn->displayWidth;
194281f79626Smrg    MemBox.y2 = scanlines;
1943c582b7e3Smrg
194484354367Smrg	if (!info->useEXA) {
194584354367Smrg	    if (!xf86InitFBManager(pScreen, &MemBox)) {
194684354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
194784354367Smrg		           "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
194884354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
194984354367Smrg	        return FALSE;
1950c582b7e3Smrg	    } else {
195184354367Smrg	        int width, height;
195284354367Smrg
195384354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
195484354367Smrg		           "Memory manager initialized to (%d,%d) (%d,%d)\n",
195584354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
195684354367Smrg	        if ((fbarea = xf86AllocateOffscreenArea(pScreen,
195784354367Smrg						        pScrn->displayWidth,
195884354367Smrg						        2, 0, NULL, NULL, NULL))) {
195984354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
196084354367Smrg			       "Reserved area from (%d,%d) to (%d,%d)\n",
196184354367Smrg			       fbarea->box.x1, fbarea->box.y1,
196284354367Smrg			       fbarea->box.x2, fbarea->box.y2);
196384354367Smrg	        } else {
196484354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve area\n");
196584354367Smrg	        }
196684354367Smrg	        if (xf86QueryLargestOffscreenArea(pScreen, &width,
196784354367Smrg						  &height, 0, 0, 0)) {
196884354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
196984354367Smrg			       "Largest offscreen area available: %d x %d\n",
197084354367Smrg				width, height);
197184354367Smrg	        }
197284354367Smrg
197381f79626Smrg            if (!info->noAccel) {
197481f79626Smrg                if (R128XAAAccelInit(pScreen)) {
197581f79626Smrg                    info->accelOn = TRUE;
197681f79626Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
197781f79626Smrg                                "XAA acceleration enabled.\n");
197881f79626Smrg                } else {
197981f79626Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
198081f79626Smrg                                "Acceleration disabled.\n");
198181f79626Smrg                }
198281f79626Smrg            }
198381f79626Smrg        }
198481f79626Smrg    }
198584354367Smrg#ifdef USE_EXA
198681f79626Smrg    else {
198781f79626Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
198881f79626Smrg                    "Filling in EXA memory info\n");
198984354367Smrg
199084354367Smrg
199181f79626Smrg        /*
199281f79626Smrg         * Don't give EXA the true full memory size, because
199381f79626Smrg         * the textureSize sized chunk on the end is handled
199481f79626Smrg         * by DRI.
199581f79626Smrg         */
199681f79626Smrg        if (R128EXAInit(pScreen, total)) {
199781f79626Smrg            info->accelOn = TRUE;
199881f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
199981f79626Smrg                        "EXA Acceleration enabled.\n");
200081f79626Smrg        } else {
200181f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
200281f79626Smrg                        "EXA Acceleration initialization "
200381f79626Smrg                        "failed.\n");
200481f79626Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
200581f79626Smrg                        "Acceleration disabled.\n");
200681f79626Smrg        }
200781f79626Smrg    }
200884354367Smrg#endif
2009c582b7e3Smrg
201081f79626Smrg#ifdef R128DRI
201181f79626Smrg    if (info->directRenderingEnabled) {
2012c582b7e3Smrg				/* Allocate the shared back buffer */
201384354367Smrg	if(!info->useEXA) {
201484354367Smrg	    fbarea = xf86AllocateOffscreenArea(pScreen,
201584354367Smrg					       pScrn->virtualX,
201684354367Smrg					       pScrn->virtualY,
201784354367Smrg					       32, NULL, NULL, NULL);
201884354367Smrg
201984354367Smrg	    if (fbarea) {
202084354367Smrg		x1 = fbarea->box.x1;
202184354367Smrg		x2 = fbarea->box.x2;
202284354367Smrg		y1 = fbarea->box.y1;
202384354367Smrg		y2 = fbarea->box.y2;
202484354367Smrg	    }
202584354367Smrg	}
202684354367Smrg#ifdef USE_EXA
202784354367Smrg	else {
202884354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
202984354367Smrg		       "Actually trying an EXA allocation...\n");
203084354367Smrg	    osArea = exaOffscreenAlloc(pScreen,
203184354367Smrg				       pScrn->virtualY * width_bytes,
203284354367Smrg				       32, TRUE, NULL, NULL);
203384354367Smrg
203484354367Smrg	    if (osArea) {
203584354367Smrg		x1 = osArea->offset % width_bytes;
203684354367Smrg		x2 = (osArea->offset + osArea->size) % width_bytes;
203784354367Smrg		y1 = osArea->offset / width_bytes;
203884354367Smrg		y2 = (osArea->offset + osArea->size) / width_bytes;
203984354367Smrg
204084354367Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Went swimmingly...\n");
204184354367Smrg	    }
204284354367Smrg	}
204384354367Smrg#endif
204484354367Smrg
204584354367Smrg	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
204684354367Smrg	    /* info->backOffset = y1 * width_bytes + x1 * cpp; */
204784354367Smrg	    info->backOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
204884354367Smrg	    info->backX = info->backOffset % width_bytes;
204984354367Smrg	    info->backY = info->backOffset / width_bytes;
2050c582b7e3Smrg	    info->backPitch = pScrn->displayWidth;
205184354367Smrg
205284354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
205384354367Smrg		       "Reserved back buffer from (%d,%d) to (%d,%d) offset: %x\n",
205484354367Smrg		       x1, y1,
205584354367Smrg		       x2, y2, info->backOffset);
2056c582b7e3Smrg	} else {
205784354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
2058c582b7e3Smrg	    info->backX = -1;
2059c582b7e3Smrg	    info->backY = -1;
2060c582b7e3Smrg	    info->backOffset = -1;
2061c582b7e3Smrg	    info->backPitch = -1;
2062c582b7e3Smrg	}
2063c582b7e3Smrg
2064c582b7e3Smrg				/* Allocate the shared depth buffer */
206584354367Smrg	if(!info->useEXA) {
206684354367Smrg	    fbarea = xf86AllocateOffscreenArea(pScreen,
206784354367Smrg					       pScrn->virtualX,
206884354367Smrg					       pScrn->virtualY + 1,
206984354367Smrg					       32, NULL, NULL, NULL);
207084354367Smrg	    if (fbarea) {
207184354367Smrg		x1 = fbarea->box.x1;
207284354367Smrg		x2 = fbarea->box.x2;
207384354367Smrg		y1 = fbarea->box.y1;
207484354367Smrg		y2 = fbarea->box.y2;
207584354367Smrg	    }
207684354367Smrg	}
207784354367Smrg#ifdef USE_EXA
207884354367Smrg	else {
207984354367Smrg	    osArea = exaOffscreenAlloc(pScreen,
208084354367Smrg				       (pScrn->virtualY + 1) * width_bytes,
208184354367Smrg				       32, TRUE, NULL, NULL);
208284354367Smrg
208384354367Smrg	    if (osArea) {
208484354367Smrg		x1 = osArea->offset % width_bytes;
208584354367Smrg		x2 = (osArea->offset + osArea->size) % width_bytes;
208684354367Smrg		y1 = osArea->offset / width_bytes;
208784354367Smrg		y2 = (osArea->offset + osArea->size) / width_bytes;
208884354367Smrg	    }
208984354367Smrg	}
209084354367Smrg#endif
209184354367Smrg
209284354367Smrg	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
209384354367Smrg	    /* info->depthOffset = y1 * width_bytes + x1 * cpp; */
209484354367Smrg	    info->depthOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
209584354367Smrg	    info->depthX = info->depthOffset % width_bytes;
209684354367Smrg	    info->depthY = info->depthOffset / width_bytes;
2097c582b7e3Smrg	    info->depthPitch = pScrn->displayWidth;
209884354367Smrg	    info->spanOffset = (y2 - 1) * width_bytes + x1 * cpp;
209984354367Smrg
210084354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
210184354367Smrg		       "Reserved depth buffer from (%d,%d) to (%d,%d) offset: %x\n",
210284354367Smrg		       x1, y1,
210384354367Smrg		       x2, y2, info->depthOffset);
210484354367Smrg
210584354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2106c582b7e3Smrg		       "Reserved depth span from (%d,%d) offset 0x%x\n",
210784354367Smrg		       x1, y2 - 1, info->spanOffset);
2108c582b7e3Smrg	} else {
210984354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
2110c582b7e3Smrg	    info->depthX = -1;
2111c582b7e3Smrg	    info->depthY = -1;
2112c582b7e3Smrg	    info->depthOffset = -1;
2113c582b7e3Smrg	    info->depthPitch = -1;
2114c582b7e3Smrg	    info->spanOffset = -1;
2115c582b7e3Smrg	}
2116c582b7e3Smrg
211784354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2118c582b7e3Smrg		   "Reserved %d kb for textures at offset 0x%x\n",
2119c582b7e3Smrg		   info->textureSize/1024, info->textureOffset);
2120c582b7e3Smrg    }
212184354367Smrg#endif /* R128DRI */
2122c582b7e3Smrg
2123b3ff493bSmrg    pScrn->vtSema = TRUE;
2124b3ff493bSmrg    /* xf86CrtcRotate accesses pScrn->pScreen */
2125b3ff493bSmrg    pScrn->pScreen = pScreen;
2126b3ff493bSmrg
21273c921f55Smrg#ifndef AVOID_FBDEV
2128b3ff493bSmrg    if (info->FBDev) {
2129b3ff493bSmrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
2130b3ff493bSmrg    } else {
21313c921f55Smrg#endif
2132b3ff493bSmrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
21333c921f55Smrg#ifndef AVOID_FBDEV
2134b3ff493bSmrg    }
21353c921f55Smrg#endif
2136b3ff493bSmrg
2137b3ff493bSmrg    R128SaveScreen(pScreen, SCREEN_SAVER_ON);
2138b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2139b3ff493bSmrg
2140c582b7e3Smrg				/* DGA setup */
2141b3ff493bSmrg#ifdef XFreeXDGA
2142b3ff493bSmrg    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
2143b3ff493bSmrg#endif
2144c582b7e3Smrg
2145c582b7e3Smrg				/* Backing store setup */
2146c582b7e3Smrg    xf86SetBackingStore(pScreen);
2147c582b7e3Smrg
2148c582b7e3Smrg				/* Set Silken Mouse */
2149c582b7e3Smrg    xf86SetSilkenMouse(pScreen);
2150c582b7e3Smrg
2151c582b7e3Smrg				/* Cursor setup */
2152c582b7e3Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2153c582b7e3Smrg
2154c582b7e3Smrg				/* Hardware cursor setup */
215581f79626Smrg    if (!info->swCursor) {
2156c582b7e3Smrg	if (R128CursorInit(pScreen)) {
2157c582b7e3Smrg	    int width, height;
2158c582b7e3Smrg
2159c582b7e3Smrg	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2160c582b7e3Smrg					      0, 0, 0)) {
216184354367Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2162c582b7e3Smrg			   "Largest offscreen area available: %d x %d\n",
2163c582b7e3Smrg			   width, height);
2164c582b7e3Smrg	    }
2165c582b7e3Smrg	} else {
216684354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2167c582b7e3Smrg		       "Hardware cursor initialization failed\n");
216884354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2169c582b7e3Smrg	}
2170c582b7e3Smrg    } else {
217184354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2172c582b7e3Smrg    }
2173c582b7e3Smrg
2174c582b7e3Smrg    /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
217579e5230eSmacallan#ifndef AVOID_FBDEV
2176c582b7e3Smrg    if (info->FBDev)
2177c582b7e3Smrg	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
2178b3ff493bSmrg    else
217979e5230eSmacallan#endif
21803c921f55Smrg        xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2181c582b7e3Smrg
21823c921f55Smrg    R128InitVideo(pScreen);
2183c582b7e3Smrg
2184c582b7e3Smrg				/* Provide SaveScreen */
2185c582b7e3Smrg    pScreen->SaveScreen  = R128SaveScreen;
2186c582b7e3Smrg
2187c582b7e3Smrg				/* Wrap CloseScreen */
2188c582b7e3Smrg    info->CloseScreen    = pScreen->CloseScreen;
2189c582b7e3Smrg    pScreen->CloseScreen = R128CloseScreen;
2190c582b7e3Smrg
2191c582b7e3Smrg				/* Note unused options */
2192c582b7e3Smrg    if (serverGeneration == 1)
2193c582b7e3Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2194c582b7e3Smrg
219584354367Smrg#ifdef R128DRI
2196c582b7e3Smrg				/* DRI finalization */
2197c582b7e3Smrg    if (info->directRenderingEnabled) {
2198c582b7e3Smrg				/* Now that mi, fb, drm and others have
2199c582b7e3Smrg				   done their thing, complete the DRI
2200c582b7e3Smrg				   setup. */
2201c582b7e3Smrg	info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
2202c582b7e3Smrg    }
2203c582b7e3Smrg    if (info->directRenderingEnabled) {
2204c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2205c582b7e3Smrg    } else {
2206c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2207c582b7e3Smrg		   "Direct rendering disabled\n");
2208c582b7e3Smrg    }
2209c582b7e3Smrg#endif
2210c582b7e3Smrg
2211c582b7e3Smrg    info->BlockHandler = pScreen->BlockHandler;
2212c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
2213c582b7e3Smrg
2214b3ff493bSmrg    if (!xf86CrtcScreenInit(pScreen)) return FALSE;
2215b3ff493bSmrg
2216b3ff493bSmrg				/* Colormap setup */
2217b3ff493bSmrg    if (!miCreateDefColormap(pScreen)) return FALSE;
2218b3ff493bSmrg    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
2219b3ff493bSmrg			     (
2220b3ff493bSmrg#ifndef AVOID_FBDEV
2221b3ff493bSmrg			     info->FBDev ? fbdevHWLoadPaletteWeak() :
2222b3ff493bSmrg#endif
2223b3ff493bSmrg			     R128LoadPalette), NULL,
2224b3ff493bSmrg			     CMAP_PALETTED_TRUECOLOR
2225b3ff493bSmrg			     | CMAP_RELOAD_ON_MODE_SWITCH
2226b3ff493bSmrg#if 0 /* This option messes up text mode! (eich@suse.de) */
2227b3ff493bSmrg			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
2228b3ff493bSmrg#endif
2229b3ff493bSmrg			     )) return FALSE;
2230b3ff493bSmrg
2231c582b7e3Smrg    return TRUE;
2232c582b7e3Smrg}
2233c582b7e3Smrg
2234c582b7e3Smrg/* Write common registers (initialized to 0). */
2235b3ff493bSmrgvoid R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2236c582b7e3Smrg{
2237c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2238c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2239c582b7e3Smrg
2240c582b7e3Smrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
2241c582b7e3Smrg
2242c582b7e3Smrg    OUTREG(R128_OVR_CLR,              restore->ovr_clr);
2243c582b7e3Smrg    OUTREG(R128_OVR_WID_LEFT_RIGHT,   restore->ovr_wid_left_right);
2244c582b7e3Smrg    OUTREG(R128_OVR_WID_TOP_BOTTOM,   restore->ovr_wid_top_bottom);
2245c582b7e3Smrg    OUTREG(R128_OV0_SCALE_CNTL,       restore->ov0_scale_cntl);
2246c582b7e3Smrg    OUTREG(R128_MPP_TB_CONFIG,        restore->mpp_tb_config );
2247c582b7e3Smrg    OUTREG(R128_MPP_GP_CONFIG,        restore->mpp_gp_config );
2248c582b7e3Smrg    OUTREG(R128_SUBPIC_CNTL,          restore->subpic_cntl);
2249c582b7e3Smrg    OUTREG(R128_VIPH_CONTROL,         restore->viph_control);
2250c582b7e3Smrg    OUTREG(R128_I2C_CNTL_1,           restore->i2c_cntl_1);
2251c582b7e3Smrg    OUTREG(R128_GEN_INT_CNTL,         restore->gen_int_cntl);
2252c582b7e3Smrg    OUTREG(R128_CAP0_TRIG_CNTL,       restore->cap0_trig_cntl);
2253c582b7e3Smrg    OUTREG(R128_CAP1_TRIG_CNTL,       restore->cap1_trig_cntl);
2254c582b7e3Smrg    OUTREG(R128_BUS_CNTL,             restore->bus_cntl);
2255c582b7e3Smrg    OUTREG(R128_CONFIG_CNTL,          restore->config_cntl);
2256c582b7e3Smrg}
2257c582b7e3Smrg
2258b3ff493bSmrg/* Write RMX registers */
2259b3ff493bSmrgvoid R128RestoreRMXRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2260c582b7e3Smrg{
2261c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2262c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2263c582b7e3Smrg
2264c582b7e3Smrg    OUTREG(R128_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
2265c582b7e3Smrg    OUTREG(R128_FP_VERT_STRETCH,      restore->fp_vert_stretch);
2266c582b7e3Smrg    OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
2267c582b7e3Smrg    OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
2268c582b7e3Smrg    OUTREG(R128_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
2269c582b7e3Smrg    OUTREG(R128_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
2270b3ff493bSmrg}
2271b3ff493bSmrg
2272b3ff493bSmrg/* Write flat panel registers */
2273b3ff493bSmrgvoid R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2274b3ff493bSmrg{
2275b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2276b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2277b3ff493bSmrg
2278b3ff493bSmrg    OUTREG(R128_TMDS_CRC,              restore->tmds_crc);
2279b3ff493bSmrg    OUTREG(R128_TMDS_TRANSMITTER_CNTL, restore->tmds_transmitter_cntl);
2280b3ff493bSmrg    OUTREG(R128_FP_PANEL_CNTL,         restore->fp_panel_cntl);
2281b3ff493bSmrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(uint32_t)R128_FP_BLANK_DIS);
2282b3ff493bSmrg}
2283b3ff493bSmrg
2284b3ff493bSmrg/* Write LVDS registers */
2285b3ff493bSmrgvoid R128RestoreLVDSRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2286b3ff493bSmrg{
2287b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2288b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2289b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2290b3ff493bSmrg    uint32_t      tmp;
2291c582b7e3Smrg
2292b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2293b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2294c582b7e3Smrg
2295c582b7e3Smrg    tmp = INREG(R128_LVDS_GEN_CNTL);
2296c582b7e3Smrg    if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
2297c582b7e3Smrg	(restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
2298c582b7e3Smrg	OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2299c582b7e3Smrg    } else {
2300c582b7e3Smrg	if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
2301c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL,
2302b3ff493bSmrg		   restore->lvds_gen_cntl & (uint32_t)~R128_LVDS_BLON);
2303b3ff493bSmrg	    usleep(r128_output->PanelPwrDly * 1000);
2304c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2305c582b7e3Smrg	} else {
2306c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
2307b3ff493bSmrg	    usleep(r128_output->PanelPwrDly * 1000);
2308c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2309c582b7e3Smrg	}
2310c582b7e3Smrg    }
2311c582b7e3Smrg}
2312c582b7e3Smrg
2313c582b7e3Smrg/* Write DDA registers. */
2314b3ff493bSmrgvoid R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2315c582b7e3Smrg{
2316c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2317c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2318c582b7e3Smrg
2319c582b7e3Smrg    OUTREG(R128_DDA_CONFIG, restore->dda_config);
2320c582b7e3Smrg    OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
2321c582b7e3Smrg}
2322c582b7e3Smrg
2323c582b7e3Smrg/* Write DDA registers. */
2324b3ff493bSmrgvoid R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2325c582b7e3Smrg{
2326c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2327c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2328c582b7e3Smrg
2329c582b7e3Smrg    OUTREG(R128_DDA2_CONFIG, restore->dda2_config);
2330c582b7e3Smrg    OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off);
2331c582b7e3Smrg}
2332c582b7e3Smrg
2333c582b7e3Smrg/* Read common registers. */
2334c582b7e3Smrgstatic void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2335c582b7e3Smrg{
2336c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2337c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2338c582b7e3Smrg
2339c582b7e3Smrg    save->ovr_clr            = INREG(R128_OVR_CLR);
2340c582b7e3Smrg    save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
2341c582b7e3Smrg    save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
2342c582b7e3Smrg    save->ov0_scale_cntl     = INREG(R128_OV0_SCALE_CNTL);
2343c582b7e3Smrg    save->mpp_tb_config      = INREG(R128_MPP_TB_CONFIG);
2344c582b7e3Smrg    save->mpp_gp_config      = INREG(R128_MPP_GP_CONFIG);
2345c582b7e3Smrg    save->subpic_cntl        = INREG(R128_SUBPIC_CNTL);
2346c582b7e3Smrg    save->viph_control       = INREG(R128_VIPH_CONTROL);
2347c582b7e3Smrg    save->i2c_cntl_1         = INREG(R128_I2C_CNTL_1);
2348c582b7e3Smrg    save->gen_int_cntl       = INREG(R128_GEN_INT_CNTL);
2349c582b7e3Smrg    save->cap0_trig_cntl     = INREG(R128_CAP0_TRIG_CNTL);
2350c582b7e3Smrg    save->cap1_trig_cntl     = INREG(R128_CAP1_TRIG_CNTL);
2351c582b7e3Smrg    save->bus_cntl           = INREG(R128_BUS_CNTL);
2352c582b7e3Smrg    save->config_cntl        = INREG(R128_CONFIG_CNTL);
2353c582b7e3Smrg}
2354c582b7e3Smrg
2355c582b7e3Smrg/* Read CRTC registers. */
2356c582b7e3Smrgstatic void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2357c582b7e3Smrg{
2358c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2359c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2360c582b7e3Smrg
2361c582b7e3Smrg    save->crtc_gen_cntl        = INREG(R128_CRTC_GEN_CNTL);
2362c582b7e3Smrg    save->crtc_ext_cntl        = INREG(R128_CRTC_EXT_CNTL);
2363c582b7e3Smrg    save->dac_cntl             = INREG(R128_DAC_CNTL);
2364c582b7e3Smrg    save->crtc_h_total_disp    = INREG(R128_CRTC_H_TOTAL_DISP);
2365c582b7e3Smrg    save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
2366c582b7e3Smrg    save->crtc_v_total_disp    = INREG(R128_CRTC_V_TOTAL_DISP);
2367c582b7e3Smrg    save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
2368c582b7e3Smrg    save->crtc_offset          = INREG(R128_CRTC_OFFSET);
2369c582b7e3Smrg    save->crtc_offset_cntl     = INREG(R128_CRTC_OFFSET_CNTL);
2370c582b7e3Smrg    save->crtc_pitch           = INREG(R128_CRTC_PITCH);
2371c582b7e3Smrg}
2372c582b7e3Smrg
2373c582b7e3Smrg/* Read flat panel registers */
2374c582b7e3Smrgstatic void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2375c582b7e3Smrg{
2376c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2377c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2378c582b7e3Smrg
2379c582b7e3Smrg    save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
2380c582b7e3Smrg    save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
2381c582b7e3Smrg    save->fp_gen_cntl          = INREG(R128_FP_GEN_CNTL);
2382c582b7e3Smrg    save->fp_h_sync_strt_wid   = INREG(R128_FP_H_SYNC_STRT_WID);
2383c582b7e3Smrg    save->fp_horz_stretch      = INREG(R128_FP_HORZ_STRETCH);
2384c582b7e3Smrg    save->fp_panel_cntl        = INREG(R128_FP_PANEL_CNTL);
2385c582b7e3Smrg    save->fp_v_sync_strt_wid   = INREG(R128_FP_V_SYNC_STRT_WID);
2386c582b7e3Smrg    save->fp_vert_stretch      = INREG(R128_FP_VERT_STRETCH);
2387c582b7e3Smrg    save->lvds_gen_cntl        = INREG(R128_LVDS_GEN_CNTL);
2388c582b7e3Smrg    save->tmds_crc             = INREG(R128_TMDS_CRC);
2389c582b7e3Smrg    save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
2390c582b7e3Smrg}
2391c582b7e3Smrg
2392c582b7e3Smrg/* Read CRTC2 registers. */
2393c582b7e3Smrgstatic void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2394c582b7e3Smrg{
2395c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2396c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2397c582b7e3Smrg
2398c582b7e3Smrg    save->crtc2_gen_cntl        = INREG(R128_CRTC2_GEN_CNTL);
2399c582b7e3Smrg    save->crtc2_h_total_disp    = INREG(R128_CRTC2_H_TOTAL_DISP);
2400c582b7e3Smrg    save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID);
2401c582b7e3Smrg    save->crtc2_v_total_disp    = INREG(R128_CRTC2_V_TOTAL_DISP);
2402c582b7e3Smrg    save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID);
2403c582b7e3Smrg    save->crtc2_offset          = INREG(R128_CRTC2_OFFSET);
2404c582b7e3Smrg    save->crtc2_offset_cntl     = INREG(R128_CRTC2_OFFSET_CNTL);
2405c582b7e3Smrg    save->crtc2_pitch           = INREG(R128_CRTC2_PITCH);
2406c582b7e3Smrg}
2407c582b7e3Smrg
2408c582b7e3Smrg/* Read PLL registers. */
2409c582b7e3Smrgstatic void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2410c582b7e3Smrg{
2411c582b7e3Smrg    save->ppll_ref_div         = INPLL(pScrn, R128_PPLL_REF_DIV);
2412c582b7e3Smrg    save->ppll_div_3           = INPLL(pScrn, R128_PPLL_DIV_3);
24139e881af1Smacallan    save->ppll_div_0           = INPLL(pScrn, R128_PPLL_DIV_0);
2414c582b7e3Smrg    save->htotal_cntl          = INPLL(pScrn, R128_HTOTAL_CNTL);
2415c582b7e3Smrg
241681f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
241781f79626Smrg                        "Read: 0x%08x 0x%08x 0x%08x\n",
241881f79626Smrg                        save->ppll_ref_div,
241981f79626Smrg                        save->ppll_div_3,
242081f79626Smrg                        save->htotal_cntl));
242181f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
242281f79626Smrg                        "Read: rd=%d, fd=%d, pd=%d\n",
242381f79626Smrg                        save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
242481f79626Smrg                        save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
242581f79626Smrg                        (save->ppll_div_3 &
242681f79626Smrg                                R128_PPLL_POST3_DIV_MASK) >> 16));
2427c582b7e3Smrg}
2428c582b7e3Smrg
2429c582b7e3Smrg/* Read PLL2 registers. */
2430c582b7e3Smrgstatic void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2431c582b7e3Smrg{
2432c582b7e3Smrg    save->p2pll_ref_div        = INPLL(pScrn, R128_P2PLL_REF_DIV);
2433c582b7e3Smrg    save->p2pll_div_0          = INPLL(pScrn, R128_P2PLL_DIV_0);
2434c582b7e3Smrg    save->htotal_cntl2         = INPLL(pScrn, R128_HTOTAL2_CNTL);
2435c582b7e3Smrg
243681f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
243781f79626Smrg                        "Read: 0x%08x 0x%08x 0x%08x\n",
243881f79626Smrg                        save->p2pll_ref_div,
243981f79626Smrg                        save->p2pll_div_0,
244081f79626Smrg                        save->htotal_cntl2));
244181f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
244281f79626Smrg                        "Read: rd=%d, fd=%d, pd=%d\n",
244381f79626Smrg                        save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
244481f79626Smrg                        save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
244581f79626Smrg                        (save->p2pll_div_0 &
244681f79626Smrg                                R128_P2PLL_POST0_DIV_MASK) >> 16));
2447c582b7e3Smrg}
2448c582b7e3Smrg
2449c582b7e3Smrg/* Read DDA registers. */
2450c582b7e3Smrgstatic void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2451c582b7e3Smrg{
2452c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2453c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2454c582b7e3Smrg
2455c582b7e3Smrg    save->dda_config           = INREG(R128_DDA_CONFIG);
2456c582b7e3Smrg    save->dda_on_off           = INREG(R128_DDA_ON_OFF);
2457c582b7e3Smrg}
2458c582b7e3Smrg
2459c582b7e3Smrg/* Read DDA2 registers. */
2460c582b7e3Smrgstatic void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2461c582b7e3Smrg{
2462c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2463c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2464c582b7e3Smrg
2465c582b7e3Smrg    save->dda2_config           = INREG(R128_DDA2_CONFIG);
2466c582b7e3Smrg    save->dda2_on_off           = INREG(R128_DDA2_ON_OFF);
2467c582b7e3Smrg}
2468c582b7e3Smrg
2469c582b7e3Smrg/* Read palette data. */
2470c582b7e3Smrgstatic void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
2471c582b7e3Smrg{
2472c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2473c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2474c582b7e3Smrg    int           i;
2475c582b7e3Smrg
2476c582b7e3Smrg    PAL_SELECT(1);
2477c582b7e3Smrg    INPAL_START(0);
2478c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
2479c582b7e3Smrg    PAL_SELECT(0);
2480c582b7e3Smrg    INPAL_START(0);
2481c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
2482c582b7e3Smrg    save->palette_valid = TRUE;
2483c582b7e3Smrg}
2484c582b7e3Smrg
2485c582b7e3Smrg/* Save state that defines current video mode. */
2486c582b7e3Smrgstatic void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
2487c582b7e3Smrg{
2488c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2489b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2490c582b7e3Smrg
249181f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
249281f79626Smrg                        "%s(%p)\n", __func__, save));
2493c582b7e3Smrg
2494b3ff493bSmrg    R128SaveCommonRegisters(pScrn, save);
2495b3ff493bSmrg    R128SaveCrtcRegisters(pScrn, save);
2496b3ff493bSmrg    R128SavePLLRegisters(pScrn, save);
2497b3ff493bSmrg    R128SaveDDARegisters(pScrn, save);
2498b3ff493bSmrg    if (pR128Ent->HasCRTC2) {
2499c582b7e3Smrg        R128SaveCrtc2Registers(pScrn, save);
2500c582b7e3Smrg        R128SavePLL2Registers(pScrn, save);
2501c582b7e3Smrg        R128SaveDDA2Registers(pScrn, save);
2502c582b7e3Smrg    }
2503b3ff493bSmrg    if (info->HasPanelRegs) {
2504b3ff493bSmrg        R128SaveFPRegisters(pScrn, save);
2505c582b7e3Smrg    }
2506b3ff493bSmrg    R128SavePalette(pScrn, save);
2507c582b7e3Smrg
250881f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
250981f79626Smrg                        "%s returns %p\n", __func__, save));
2510c582b7e3Smrg}
2511c582b7e3Smrg
2512c582b7e3Smrg/* Save everything needed to restore the original VC state. */
2513c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn)
2514c582b7e3Smrg{
2515c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2516c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2517c582b7e3Smrg    R128SavePtr   save      = &info->SavedReg;
2518c582b7e3Smrg
251979e5230eSmacallan#ifndef AVOID_FBDEV
252081f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
252181f79626Smrg                        "%s\n", __func__));
2522c582b7e3Smrg    if (info->FBDev) {
2523c582b7e3Smrg	fbdevHWSave(pScrn);
2524c582b7e3Smrg	return;
2525c582b7e3Smrg    }
252679e5230eSmacallan#endif
2527c582b7e3Smrg
2528c582b7e3Smrg#ifdef WITH_VGAHW
2529b3ff493bSmrg    if (info->VGAAccess) {
2530b3ff493bSmrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2531c582b7e3Smrg
2532b3ff493bSmrg        vgaHWUnlock(hwp);
2533c582b7e3Smrg# if defined(__powerpc__)
2534b3ff493bSmrg        /* temporary hack to prevent crashing on PowerMacs when trying to
2535b3ff493bSmrg         * read VGA fonts and colormap, will find a better solution
2536b3ff493bSmrg         * in the future. TODO: Check if there's actually some VGA stuff
2537b3ff493bSmrg         * setup in the card at all !!
2538b3ff493bSmrg         */
2539b3ff493bSmrg        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
2540c582b7e3Smrg# else
2541b3ff493bSmrg        /* Save mode * & fonts & cmap */
2542b3ff493bSmrg        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
2543c582b7e3Smrg# endif
2544b3ff493bSmrg        vgaHWLock(hwp);
2545c582b7e3Smrg    }
2546b3ff493bSmrg#endif
2547c582b7e3Smrg
2548b3ff493bSmrg    save->dp_datatype      = INREG(R128_DP_DATATYPE);
2549b3ff493bSmrg    save->gen_reset_cntl   = INREG(R128_GEN_RESET_CNTL);
2550b3ff493bSmrg    save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
2551b3ff493bSmrg    save->amcgpio_en_reg   = INREG(R128_AMCGPIO_EN_REG);
2552b3ff493bSmrg    save->amcgpio_mask     = INREG(R128_AMCGPIO_MASK);
2553c582b7e3Smrg
2554b3ff493bSmrg    R128SaveMode(pScrn, save);
2555c582b7e3Smrg}
2556c582b7e3Smrg
2557c582b7e3Smrg/* Restore the original (text) mode. */
2558c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn)
2559c582b7e3Smrg{
2560c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2561b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2562c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2563c582b7e3Smrg    R128SavePtr   restore   = &info->SavedReg;
2564c582b7e3Smrg
256579e5230eSmacallan#ifndef AVOID_FBDEV
256681f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
256781f79626Smrg                        "%s\n", __func__));
2568c582b7e3Smrg    if (info->FBDev) {
2569c582b7e3Smrg	fbdevHWRestore(pScrn);
2570c582b7e3Smrg	return;
2571c582b7e3Smrg    }
257279e5230eSmacallan#endif
2573c582b7e3Smrg    R128Blank(pScrn);
2574c582b7e3Smrg
2575b3ff493bSmrg    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
2576b3ff493bSmrg    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
2577b3ff493bSmrg    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
2578b3ff493bSmrg    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
2579b3ff493bSmrg    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
2580c582b7e3Smrg
2581b3ff493bSmrg    R128RestoreCommonRegisters(pScrn, restore);
2582b3ff493bSmrg    if (pR128Ent->HasCRTC2) {
2583b3ff493bSmrg        R128RestoreDDA2Registers(pScrn, restore);
2584b3ff493bSmrg        R128RestoreCrtc2Registers(pScrn, restore);
2585b3ff493bSmrg        R128RestorePLL2Registers(pScrn, restore);
2586b3ff493bSmrg    }
2587b3ff493bSmrg    R128RestoreDDARegisters(pScrn, restore);
2588b3ff493bSmrg    R128RestoreCrtcRegisters(pScrn, restore);
2589b3ff493bSmrg    R128RestorePLLRegisters(pScrn, restore);
2590b3ff493bSmrg    R128RestoreDACRegisters(pScrn, restore);
2591b3ff493bSmrg    R128RestoreRMXRegisters(pScrn, restore);
2592b3ff493bSmrg    R128RestoreFPRegisters(pScrn, restore);
2593b3ff493bSmrg    R128RestoreLVDSRegisters(pScrn, restore);
25949e881af1Smacallan
25955ef9b84eSmacallan    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
25965ef9b84eSmacallan    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
25975ef9b84eSmacallan    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
25985ef9b84eSmacallan    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
25995ef9b84eSmacallan    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
26009e881af1Smacallan
2601c582b7e3Smrg#ifdef WITH_VGAHW
2602c582b7e3Smrg    if (info->VGAAccess) {
2603c582b7e3Smrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2604b3ff493bSmrg        vgaHWUnlock(hwp);
2605c582b7e3Smrg# if defined(__powerpc__)
2606b3ff493bSmrg        /* Temporary hack to prevent crashing on PowerMacs when trying to
2607b3ff493bSmrg         * write VGA fonts, will find a better solution in the future
2608b3ff493bSmrg         */
2609b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
2610c582b7e3Smrg# else
2611b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
2612c582b7e3Smrg# endif
2613b3ff493bSmrg        vgaHWLock(hwp);
2614c582b7e3Smrg    }
2615c582b7e3Smrg#endif
2616c582b7e3Smrg
2617c582b7e3Smrg    R128WaitForVerticalSync(pScrn);
2618c582b7e3Smrg    R128Unblank(pScrn);
2619c582b7e3Smrg}
2620c582b7e3Smrg
2621c582b7e3Smrg/* Define common registers for requested video mode. */
2622b3ff493bSmrgvoid R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
2623c582b7e3Smrg{
2624c582b7e3Smrg    save->ovr_clr            = 0;
2625c582b7e3Smrg    save->ovr_wid_left_right = 0;
2626c582b7e3Smrg    save->ovr_wid_top_bottom = 0;
2627c582b7e3Smrg    save->ov0_scale_cntl     = 0;
2628c582b7e3Smrg    save->mpp_tb_config      = 0;
2629c582b7e3Smrg    save->mpp_gp_config      = 0;
2630c582b7e3Smrg    save->subpic_cntl        = 0;
2631c582b7e3Smrg    save->viph_control       = 0;
2632c582b7e3Smrg    save->i2c_cntl_1         = 0;
263384354367Smrg#ifdef R128DRI
2634c582b7e3Smrg    save->gen_int_cntl       = info->gen_int_cntl;
2635c582b7e3Smrg#else
2636c582b7e3Smrg    save->gen_int_cntl       = 0;
2637c582b7e3Smrg#endif
2638c582b7e3Smrg    save->cap0_trig_cntl     = 0;
2639c582b7e3Smrg    save->cap1_trig_cntl     = 0;
2640c582b7e3Smrg    save->bus_cntl           = info->BusCntl;
2641c582b7e3Smrg    /*
2642c582b7e3Smrg     * If bursts are enabled, turn on discards and aborts
2643c582b7e3Smrg     */
2644c582b7e3Smrg    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
2645c582b7e3Smrg	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
2646c582b7e3Smrg}
2647c582b7e3Smrg
2648b3ff493bSmrg/* Define RMX registers for the requested video mode. */
2649b3ff493bSmrgvoid R128InitRMXRegisters(R128SavePtr orig, R128SavePtr save,
2650b3ff493bSmrg                          xf86OutputPtr output, DisplayModePtr mode)
2651c582b7e3Smrg{
2652b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2653b3ff493bSmrg
2654c582b7e3Smrg    int   xres = mode->CrtcHDisplay;
2655c582b7e3Smrg    int   yres = mode->CrtcVDisplay;
2656c582b7e3Smrg    float Hratio, Vratio;
2657c582b7e3Smrg
2658b3ff493bSmrg    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
2659b3ff493bSmrg    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
2660b3ff493bSmrg    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
2661b3ff493bSmrg    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
2662b3ff493bSmrg
2663b3ff493bSmrg    if (r128_output->MonType != MT_DFP && r128_output->MonType != MT_LCD)
2664c582b7e3Smrg        return;
2665c582b7e3Smrg
2666b3ff493bSmrg    if (r128_output->PanelXRes == 0 || r128_output->PanelYRes == 0) {
2667b3ff493bSmrg        xres = r128_output->PanelXRes;
2668b3ff493bSmrg        yres = r128_output->PanelYRes;
2669b3ff493bSmrg
2670b3ff493bSmrg        Hratio = 1.0;
2671b3ff493bSmrg        Vratio = 1.0;
2672b3ff493bSmrg    } else {
2673b3ff493bSmrg        if (xres > r128_output->PanelXRes) xres = r128_output->PanelXRes;
2674b3ff493bSmrg        if (yres > r128_output->PanelYRes) yres = r128_output->PanelYRes;
2675c582b7e3Smrg
2676b3ff493bSmrg        Hratio = (float)xres/(float)r128_output->PanelXRes;
2677b3ff493bSmrg        Vratio = (float)yres/(float)r128_output->PanelYRes;
2678b3ff493bSmrg    }
2679c582b7e3Smrg
2680c582b7e3Smrg    save->fp_horz_stretch =
2681c582b7e3Smrg	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
2682c582b7e3Smrg	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
2683c582b7e3Smrg       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
2684c582b7e3Smrg                                 R128_HORZ_FP_LOOP_STRETCH |
2685c582b7e3Smrg                                 R128_HORZ_STRETCH_RESERVED)));
2686c582b7e3Smrg    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
2687c582b7e3Smrg    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
2688b3ff493bSmrg    if (xres == r128_output->PanelXRes)
2689c582b7e3Smrg         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
2690c582b7e3Smrg    else
2691c582b7e3Smrg         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
2692c582b7e3Smrg
2693c582b7e3Smrg    save->fp_vert_stretch =
2694c582b7e3Smrg	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
2695c582b7e3Smrg	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
2696c582b7e3Smrg	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
2697c582b7e3Smrg				   R128_VERT_STRETCH_RESERVED)));
2698c582b7e3Smrg    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
2699b3ff493bSmrg    if (yres == r128_output->PanelYRes)
2700c582b7e3Smrg        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
2701c582b7e3Smrg    else
2702c582b7e3Smrg        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
2703b3ff493bSmrg}
2704c582b7e3Smrg
2705b3ff493bSmrg/* Define flat panel registers for the requested video mode. */
2706b3ff493bSmrgvoid R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
2707b3ff493bSmrg{
2708b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
2709b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
2710c582b7e3Smrg
2711c582b7e3Smrg    /* WARNING: Be careful about turning on the flat panel */
2712b3ff493bSmrg    save->fp_gen_cntl            = orig->fp_gen_cntl;
2713b3ff493bSmrg    save->fp_panel_cntl          = orig->fp_panel_cntl;
2714b3ff493bSmrg    save->tmds_transmitter_cntl  = orig->tmds_transmitter_cntl;
2715b3ff493bSmrg    save->tmds_crc               = orig->tmds_crc;
2716b3ff493bSmrg
2717b3ff493bSmrg    if (r128_crtc->crtc_id)
2718b3ff493bSmrg        save->fp_gen_cntl       |=   R128_FP_SEL_CRTC2;
2719c582b7e3Smrg    else
2720b3ff493bSmrg        save->fp_gen_cntl       &=  ~R128_FP_SEL_CRTC2;
2721c582b7e3Smrg
2722b3ff493bSmrg    save->fp_gen_cntl           &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
2723b3ff493bSmrg                                     R128_FP_CRTC_USE_SHADOW_ROWCUR |
2724b3ff493bSmrg                                     R128_FP_CRTC_HORZ_DIV2_EN |
2725b3ff493bSmrg                                     R128_FP_CRTC_HOR_CRT_DIV2_DIS |
2726b3ff493bSmrg                                     R128_FP_CRT_SYNC_SEL |
2727b3ff493bSmrg                                     R128_FP_USE_SHADOW_EN);
2728b3ff493bSmrg
2729b3ff493bSmrg    save->fp_gen_cntl           |=  (R128_FP_CRTC_DONT_SHADOW_VPAR |
2730b3ff493bSmrg                                     R128_FP_CRTC_DONT_SHADOW_HEND);
2731b3ff493bSmrg
2732b3ff493bSmrg    save->fp_panel_cntl         |=  (R128_FP_DIGON | R128_FP_BLON);
2733b3ff493bSmrg    save->tmds_transmitter_cntl &=  ~R128_TMDS_PLLRST;
2734b3ff493bSmrg    save->tmds_transmitter_cntl |=   R128_TMDS_PLLEN;
2735b3ff493bSmrg}
2736b3ff493bSmrg
2737b3ff493bSmrg/* Define LVDS registers for the requested video mode. */
2738b3ff493bSmrgvoid R128InitLVDSRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
2739b3ff493bSmrg{
2740b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
2741b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
2742b3ff493bSmrg
2743b3ff493bSmrg    save->lvds_gen_cntl      =  orig->lvds_gen_cntl;
2744b3ff493bSmrg
2745b3ff493bSmrg    if (r128_crtc->crtc_id)
2746b3ff493bSmrg        save->lvds_gen_cntl |=  R128_LVDS_SEL_CRTC2;
2747b3ff493bSmrg    else
2748b3ff493bSmrg        save->lvds_gen_cntl &= ~R128_LVDS_SEL_CRTC2;
2749c582b7e3Smrg}
2750c582b7e3Smrg
2751c582b7e3Smrg#if 0
2752c582b7e3Smrg/* Define initial palette for requested video mode.  This doesn't do
2753c582b7e3Smrg   anything for XFree86 4.0. */
2754c582b7e3Smrgstatic void R128InitPalette(R128SavePtr save)
2755c582b7e3Smrg{
2756c582b7e3Smrg    save->palette_valid = FALSE;
2757c582b7e3Smrg}
2758c582b7e3Smrg#endif
2759c582b7e3Smrg
2760c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode)
2761c582b7e3Smrg{
276284354367Smrg    ScrnInfoPtr   pScrn = xf86ScreenToScrn(pScreen);
2763c582b7e3Smrg    Bool unblank;
2764c582b7e3Smrg
2765c582b7e3Smrg    unblank = xf86IsUnblank(mode);
2766c582b7e3Smrg    if (unblank)
2767c582b7e3Smrg	SetTimeSinceLastInputEvent();
2768c582b7e3Smrg
2769c582b7e3Smrg    if ((pScrn != NULL) && pScrn->vtSema) {
2770c582b7e3Smrg	if (unblank)
2771c582b7e3Smrg		R128Unblank(pScrn);
2772c582b7e3Smrg	else
2773c582b7e3Smrg		R128Blank(pScrn);
2774c582b7e3Smrg    }
2775c582b7e3Smrg    return TRUE;
2776c582b7e3Smrg}
2777c582b7e3Smrg
2778c582b7e3Smrg/*
2779c582b7e3Smrg * SwitchMode() doesn't work right on crtc2 on some laptops.
2780c582b7e3Smrg * The workaround is to switch the mode, then switch to another VT, then
2781c582b7e3Smrg * switch back. --AGD
2782c582b7e3Smrg */
278384354367SmrgBool R128SwitchMode(SWITCH_MODE_ARGS_DECL)
2784c582b7e3Smrg{
278584354367Smrg    SCRN_INFO_PTR(arg);
2786c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2787c582b7e3Smrg    Bool ret;
2788c582b7e3Smrg
2789c582b7e3Smrg    info->SwitchingMode = TRUE;
2790b3ff493bSmrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
2791c582b7e3Smrg    info->SwitchingMode = FALSE;
2792c582b7e3Smrg    return ret;
2793c582b7e3Smrg}
2794c582b7e3Smrg
2795b3ff493bSmrgModeStatus R128DoValidMode(xf86OutputPtr output, DisplayModePtr mode, int flags)
2796c582b7e3Smrg{
2797b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
2798b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2799b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2800b3ff493bSmrg    int i, j;
2801c582b7e3Smrg
2802b3ff493bSmrg    if (r128_output->MonType == MT_CRT)
2803b3ff493bSmrg        return MODE_OK;
2804c582b7e3Smrg
2805b3ff493bSmrg    if (r128_output->MonType == MT_DFP || r128_output->MonType == MT_LCD) {
2806c582b7e3Smrg	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
2807c582b7e3Smrg	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
2808c582b7e3Smrg    }
2809c582b7e3Smrg
2810b3ff493bSmrg    if (r128_output->MonType == MT_LCD && info->VBIOS) {
2811b3ff493bSmrg	for (i = info->FPBIOSstart + 64; R128_BIOS16(i) != 0; i += 2) {
2812b3ff493bSmrg	    j = R128_BIOS16(i);
2813c582b7e3Smrg
2814c582b7e3Smrg	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
2815b3ff493bSmrg		mode->CrtcVDisplay == R128_BIOS16(j + 2)) {
2816c582b7e3Smrg		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
2817c582b7e3Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2818c582b7e3Smrg			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
2819b3ff493bSmrg			       mode->CrtcHDisplay, mode->CrtcVDisplay,
2820b3ff493bSmrg			       (float)mode->Clock / 1000);
2821c582b7e3Smrg
2822c582b7e3Smrg		    /* Assume we are using expanded mode */
2823b3ff493bSmrg		    if (R128_BIOS16(j + 5)) j  = R128_BIOS16(j + 5);
2824b3ff493bSmrg		    else                    j += 9;
2825c582b7e3Smrg
2826b3ff493bSmrg		    mode->Clock = (uint32_t)R128_BIOS16(j) * 10;
2827c582b7e3Smrg
2828c582b7e3Smrg		    mode->HDisplay   = mode->CrtcHDisplay   =
2829b3ff493bSmrg			((R128_BIOS16(j + 10) & 0x01ff) + 1) * 8;
2830c582b7e3Smrg		    mode->HSyncStart = mode->CrtcHSyncStart =
2831b3ff493bSmrg			((R128_BIOS16(j + 12) & 0x01ff) + 1) * 8;
2832c582b7e3Smrg		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
2833b3ff493bSmrg			mode->CrtcHSyncStart + (R128_BIOS8(j + 14) & 0x1f);
2834c582b7e3Smrg		    mode->HTotal     = mode->CrtcHTotal     =
2835b3ff493bSmrg			((R128_BIOS16(j + 8)  & 0x01ff) + 1) * 8;
2836c582b7e3Smrg
2837c582b7e3Smrg		    mode->VDisplay   = mode->CrtcVDisplay   =
2838b3ff493bSmrg			(R128_BIOS16(j + 17) & 0x07ff) + 1;
2839c582b7e3Smrg		    mode->VSyncStart = mode->CrtcVSyncStart =
2840b3ff493bSmrg			(R128_BIOS16(j + 19) & 0x07ff) + 1;
2841c582b7e3Smrg		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
2842b3ff493bSmrg			mode->CrtcVSyncStart + ((R128_BIOS16(j + 19) >> 11) & 0x1f);
2843c582b7e3Smrg		    mode->VTotal     = mode->CrtcVTotal     =
2844b3ff493bSmrg			(R128_BIOS16(j + 15) & 0x07ff) + 1;
2845c582b7e3Smrg		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
2846c582b7e3Smrg			       mode->CrtcHDisplay,mode->CrtcVDisplay,
2847b3ff493bSmrg			       (float)mode->Clock/ 1000);
2848c582b7e3Smrg		}
2849c582b7e3Smrg		return MODE_OK;
2850c582b7e3Smrg	    }
2851c582b7e3Smrg	}
2852c582b7e3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
2853c582b7e3Smrg		       "Mode rejected for FP %ix%i [pclk: %.1f] "
2854c582b7e3Smrg		       "(not listed in VBIOS)\n",
2855c582b7e3Smrg		       mode->CrtcHDisplay, mode->CrtcVDisplay,
2856c582b7e3Smrg		       (float)mode->Clock / 1000);
2857c582b7e3Smrg	return MODE_NOMODE;
2858c582b7e3Smrg    }
2859c582b7e3Smrg
2860c582b7e3Smrg    return MODE_OK;
2861c582b7e3Smrg}
2862c582b7e3Smrg
2863b3ff493bSmrg/* Used to disallow modes that are not supported by the hardware. */
2864b3ff493bSmrgModeStatus R128ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
2865b3ff493bSmrg                                   Bool verbose, int flags)
2866b3ff493bSmrg{
2867b3ff493bSmrg    SCRN_INFO_PTR(arg);
2868b3ff493bSmrg    R128EntPtr  pR128Ent = R128EntPriv(pScrn);
2869b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2870b3ff493bSmrg
2871b3ff493bSmrg    return R128DoValidMode(output, mode, flags);
2872b3ff493bSmrg}
2873b3ff493bSmrg
2874c582b7e3Smrg/* Adjust viewport into virtual desktop such that (0,0) in viewport space
2875c582b7e3Smrg   is (x,y) in virtual space. */
287684354367Smrgvoid R128AdjustFrame(ADJUST_FRAME_ARGS_DECL)
2877c582b7e3Smrg{
287884354367Smrg    SCRN_INFO_PTR(arg);
2879c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2880c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2881c582b7e3Smrg    int           Base;
2882c582b7e3Smrg
2883c582b7e3Smrg    if(info->showCache && y && pScrn->vtSema)
2884c582b7e3Smrg        y += pScrn->virtualY - 1;
2885c582b7e3Smrg
2886c582b7e3Smrg    Base = y * info->CurrentLayout.displayWidth + x;
2887c582b7e3Smrg
2888c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
2889c582b7e3Smrg    case 15:
2890c582b7e3Smrg    case 16: Base *= 2; break;
2891c582b7e3Smrg    case 24: Base *= 3; break;
2892c582b7e3Smrg    case 32: Base *= 4; break;
2893c582b7e3Smrg    }
2894c582b7e3Smrg
2895c582b7e3Smrg    Base &= ~7;                 /* 3 lower bits are always 0 */
2896c582b7e3Smrg
2897c582b7e3Smrg    if (info->CurrentLayout.pixel_code == 24)
2898c582b7e3Smrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2899c582b7e3Smrg
2900c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET, Base);
2901c582b7e3Smrg}
2902c582b7e3Smrg
2903c582b7e3Smrg/* Called when VT switching back to the X server.  Reinitialize the video
2904c582b7e3Smrg   mode. */
290584354367SmrgBool R128EnterVT(VT_FUNC_ARGS_DECL)
2906c582b7e3Smrg{
290784354367Smrg    SCRN_INFO_PTR(arg);
2908c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
2909c582b7e3Smrg
291081f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
291181f79626Smrg                        "%s\n", __func__));
2912b3ff493bSmrg
2913b3ff493bSmrg    pScrn->vtSema = TRUE;
291479e5230eSmacallan#ifndef AVOID_FBDEV
2915c582b7e3Smrg    if (info->FBDev) {
291684354367Smrg        if (!fbdevHWEnterVT(VT_FUNC_ARGS)) return FALSE;
29173c921f55Smrg    } else {
291879e5230eSmacallan#endif
29193c921f55Smrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
29203c921f55Smrg#ifndef AVOID_FBDEV
2921b3ff493bSmrg    }
29223c921f55Smrg#endif
2923b3ff493bSmrg
2924c582b7e3Smrg    if (info->accelOn)
2925c582b7e3Smrg	R128EngineInit(pScrn);
2926c582b7e3Smrg
292784354367Smrg#ifdef R128DRI
2928c582b7e3Smrg    if (info->directRenderingEnabled) {
2929c582b7e3Smrg	if (info->irq) {
2930c582b7e3Smrg	    /* Need to make sure interrupts are enabled */
2931c582b7e3Smrg	    unsigned char *R128MMIO = info->MMIO;
2932c582b7e3Smrg	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
2933c582b7e3Smrg	}
2934c582b7e3Smrg	R128CCE_START(pScrn, info);
2935c582b7e3Smrg	DRIUnlock(pScrn->pScreen);
2936c582b7e3Smrg    }
2937c582b7e3Smrg#endif
2938c582b7e3Smrg
2939c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
2940b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2941c582b7e3Smrg
2942c582b7e3Smrg    return TRUE;
2943c582b7e3Smrg}
2944c582b7e3Smrg
2945c582b7e3Smrg/* Called when VT switching away from the X server.  Restore the original
2946c582b7e3Smrg   text mode. */
294784354367Smrgvoid R128LeaveVT(VT_FUNC_ARGS_DECL)
2948c582b7e3Smrg{
294984354367Smrg    SCRN_INFO_PTR(arg);
2950c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
2951c582b7e3Smrg    R128SavePtr save  = &info->ModeReg;
2952c582b7e3Smrg
295381f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
295481f79626Smrg                        "%s\n", __func__));
295584354367Smrg#ifdef R128DRI
2956c582b7e3Smrg    if (info->directRenderingEnabled) {
2957c582b7e3Smrg	DRILock(pScrn->pScreen, 0);
2958c582b7e3Smrg	R128CCE_STOP(pScrn, info);
2959c582b7e3Smrg    }
296084354367Smrg#ifdef USE_EXA
296184354367Smrg    if (info->useEXA)
296284354367Smrg        info->state_2d.composite_setup = FALSE;
296384354367Smrg#endif
2964c582b7e3Smrg#endif
2965c582b7e3Smrg    R128SavePalette(pScrn, save);
2966c582b7e3Smrg    info->PaletteSavedOnVT = TRUE;
296779e5230eSmacallan#ifndef AVOID_FBDEV
2968c582b7e3Smrg    if (info->FBDev)
296984354367Smrg        fbdevHWLeaveVT(VT_FUNC_ARGS);
2970c582b7e3Smrg    else
297179e5230eSmacallan#endif
2972c582b7e3Smrg        R128Restore(pScrn);
2973c582b7e3Smrg}
2974c582b7e3Smrg
2975c582b7e3Smrg
2976c582b7e3Smrg/* Called at the end of each server generation.  Restore the original text
2977c582b7e3Smrg   mode, unmap video memory, and unwrap and call the saved CloseScreen
2978c582b7e3Smrg   function.  */
297984354367Smrgstatic Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL)
2980c582b7e3Smrg{
298184354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2982c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
2983c582b7e3Smrg
298481f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
298581f79626Smrg                        "%s\n", __func__));
2986c582b7e3Smrg
298784354367Smrg#ifdef R128DRI
2988c582b7e3Smrg				/* Disable direct rendering */
2989c582b7e3Smrg    if (info->directRenderingEnabled) {
2990c582b7e3Smrg	R128DRICloseScreen(pScreen);
2991c582b7e3Smrg	info->directRenderingEnabled = FALSE;
2992c582b7e3Smrg    }
2993c582b7e3Smrg#endif
2994c582b7e3Smrg
2995c582b7e3Smrg    if (pScrn->vtSema) {
2996c582b7e3Smrg	R128Restore(pScrn);
2997c582b7e3Smrg	R128UnmapMem(pScrn);
2998c582b7e3Smrg    }
2999c582b7e3Smrg
300084354367Smrg#ifdef USE_EXA
300184354367Smrg        if (info->useEXA) {
300284354367Smrg	    exaDriverFini(pScreen);
300384354367Smrg	    free(info->ExaDriver);
300484354367Smrg	} else
300584354367Smrg#endif
300684354367Smrg#ifdef HAVE_XAA_H
300784354367Smrg	{
300884354367Smrg            if (info->accel)             XAADestroyInfoRec(info->accel);
300984354367Smrg	    info->accel                  = NULL;
301084354367Smrg        }
301184354367Smrg#endif
3012c582b7e3Smrg
301384354367Smrg    if (info->scratch_save)      free(info->scratch_save);
3014c582b7e3Smrg    info->scratch_save           = NULL;
3015c582b7e3Smrg
3016c582b7e3Smrg    if (info->adaptor) {
301784354367Smrg        free(info->adaptor->pPortPrivates[0].ptr);
3018c582b7e3Smrg	xf86XVFreeVideoAdaptorRec(info->adaptor);
3019c582b7e3Smrg	info->adaptor = NULL;
3020c582b7e3Smrg    }
3021c582b7e3Smrg
3022c582b7e3Smrg    pScrn->vtSema = FALSE;
3023c582b7e3Smrg
3024c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
3025c582b7e3Smrg    pScreen->CloseScreen = info->CloseScreen;
302684354367Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3027c582b7e3Smrg}
3028c582b7e3Smrg
302984354367Smrgvoid R128FreeScreen(FREE_SCREEN_ARGS_DECL)
3030c582b7e3Smrg{
303184354367Smrg    SCRN_INFO_PTR(arg);
3032c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3033c582b7e3Smrg
303481f79626Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
303581f79626Smrg                        "%s\n", __func__));
303619019ffeSmrg    if (info == NULL)
303719019ffeSmrg	return;
3038c582b7e3Smrg#ifdef WITH_VGAHW
3039c582b7e3Smrg    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
3040c582b7e3Smrg	vgaHWFreeHWRec(pScrn);
3041c582b7e3Smrg#endif
3042c582b7e3Smrg    R128FreeRec(pScrn);
3043c582b7e3Smrg}
3044