r128_driver.c revision e1efbb8a
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"
97c582b7e3Smrg
98c582b7e3Smrg				/* fbdevhw & vgahw */
99c582b7e3Smrg#ifdef WITH_VGAHW
100c582b7e3Smrg#include "vgaHW.h"
101c582b7e3Smrg#endif
10279e5230eSmacallan
10379e5230eSmacallan#ifndef AVOID_FBDEV
104c582b7e3Smrg#include "fbdevhw.h"
10579e5230eSmacallan#endif
10679e5230eSmacallan
107c582b7e3Smrg#include "dixstruct.h"
108c582b7e3Smrg
109c582b7e3Smrg				/* DPMS support. */
11019019ffeSmrg#ifdef HAVE_XEXTPROTO_71
11119019ffeSmrg#include <X11/extensions/dpmsconst.h>
11219019ffeSmrg#else
113c582b7e3Smrg#define DPMS_SERVER
114c582b7e3Smrg#include <X11/extensions/dpms.h>
11519019ffeSmrg#endif
11619019ffeSmrg
11799d7194aSmacallan#ifdef __NetBSD__
11899d7194aSmacallan#include <sys/time.h>
11999d7194aSmacallan#include <dev/wscons/wsconsio.h>
12099d7194aSmacallan#endif
121c582b7e3Smrg
122c582b7e3Smrg#ifndef MAX
123c582b7e3Smrg#define MAX(a,b) ((a)>(b)?(a):(b))
124c582b7e3Smrg#endif
125c582b7e3Smrg
126c582b7e3Smrg#define USE_CRT_ONLY	0
127c582b7e3Smrg
128c582b7e3Smrg				/* Forward definitions for driver functions */
12984354367Smrgstatic Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL);
130c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode);
131c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn);
132c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn);
133c582b7e3Smrg
134c582b7e3Smrgtypedef enum {
135c582b7e3Smrg  OPTION_NOACCEL,
136c582b7e3Smrg  OPTION_SW_CURSOR,
137c582b7e3Smrg  OPTION_DAC_6BIT,
138c582b7e3Smrg  OPTION_DAC_8BIT,
13984354367Smrg#ifdef R128DRI
140c582b7e3Smrg  OPTION_XV_DMA,
141c582b7e3Smrg  OPTION_IS_PCI,
142c582b7e3Smrg  OPTION_CCE_PIO,
143c582b7e3Smrg  OPTION_NO_SECURITY,
144c582b7e3Smrg  OPTION_USEC_TIMEOUT,
145c582b7e3Smrg  OPTION_AGP_MODE,
146c582b7e3Smrg  OPTION_AGP_SIZE,
147c582b7e3Smrg  OPTION_RING_SIZE,
148c582b7e3Smrg  OPTION_BUFFER_SIZE,
149c582b7e3Smrg  OPTION_PAGE_FLIP,
150c582b7e3Smrg#endif
151c582b7e3Smrg#if USE_CRT_ONLY
152c582b7e3Smrg  /* FIXME: Disable CRTOnly until it is tested */
153c582b7e3Smrg  OPTION_CRT,
154c582b7e3Smrg#endif
155c582b7e3Smrg  OPTION_DISPLAY,
156c582b7e3Smrg  OPTION_PANEL_WIDTH,
157c582b7e3Smrg  OPTION_PANEL_HEIGHT,
158c582b7e3Smrg  OPTION_PROG_FP_REGS,
15979e5230eSmacallan#ifndef AVOID_FBDEV
160c582b7e3Smrg  OPTION_FBDEV,
16179e5230eSmacallan#endif
162c582b7e3Smrg  OPTION_VIDEO_KEY,
163c582b7e3Smrg  OPTION_SHOW_CACHE,
16484354367Smrg  OPTION_VGA_ACCESS,
16584354367Smrg  OPTION_ACCELMETHOD,
16684354367Smrg  OPTION_RENDERACCEL
167c582b7e3Smrg} R128Opts;
168c582b7e3Smrg
169c582b7e3Smrgstatic const OptionInfoRec R128Options[] = {
170c582b7e3Smrg  { OPTION_NOACCEL,      "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
171c582b7e3Smrg  { OPTION_SW_CURSOR,    "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
172c582b7e3Smrg  { OPTION_DAC_6BIT,     "Dac6Bit",          OPTV_BOOLEAN, {0}, FALSE },
173c582b7e3Smrg  { OPTION_DAC_8BIT,     "Dac8Bit",          OPTV_BOOLEAN, {0}, TRUE  },
17484354367Smrg#ifdef R128DRI
175c582b7e3Smrg  { OPTION_XV_DMA,       "DMAForXv",         OPTV_BOOLEAN, {0}, FALSE },
176c582b7e3Smrg  { OPTION_IS_PCI,       "ForcePCIMode",     OPTV_BOOLEAN, {0}, FALSE },
177c582b7e3Smrg  { OPTION_CCE_PIO,      "CCEPIOMode",       OPTV_BOOLEAN, {0}, FALSE },
178c582b7e3Smrg  { OPTION_NO_SECURITY,  "CCENoSecurity",    OPTV_BOOLEAN, {0}, FALSE },
179c582b7e3Smrg  { OPTION_USEC_TIMEOUT, "CCEusecTimeout",   OPTV_INTEGER, {0}, FALSE },
180c582b7e3Smrg  { OPTION_AGP_MODE,     "AGPMode",          OPTV_INTEGER, {0}, FALSE },
181c582b7e3Smrg  { OPTION_AGP_SIZE,     "AGPSize",          OPTV_INTEGER, {0}, FALSE },
182c582b7e3Smrg  { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
183c582b7e3Smrg  { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
184c582b7e3Smrg  { OPTION_PAGE_FLIP,    "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
185c582b7e3Smrg#endif
186c582b7e3Smrg  { OPTION_PANEL_WIDTH,  "PanelWidth",       OPTV_INTEGER, {0}, FALSE },
187c582b7e3Smrg  { OPTION_PANEL_HEIGHT, "PanelHeight",      OPTV_INTEGER, {0}, FALSE },
188c582b7e3Smrg  { OPTION_PROG_FP_REGS, "ProgramFPRegs",    OPTV_BOOLEAN, {0}, FALSE },
18979e5230eSmacallan#ifndef AVOID_FBDEV
190c582b7e3Smrg  { OPTION_FBDEV,        "UseFBDev",         OPTV_BOOLEAN, {0}, FALSE },
19179e5230eSmacallan#endif
192c582b7e3Smrg  { OPTION_VIDEO_KEY,    "VideoKey",         OPTV_INTEGER, {0}, FALSE },
193c582b7e3Smrg  { OPTION_SHOW_CACHE,   "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
194c582b7e3Smrg  { OPTION_VGA_ACCESS,   "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
19584354367Smrg  { OPTION_ACCELMETHOD,  "AccelMethod",      OPTV_STRING,  {0}, FALSE },
19684354367Smrg  { OPTION_RENDERACCEL,  "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
197c582b7e3Smrg  { -1,                  NULL,               OPTV_NONE,    {0}, FALSE }
198c582b7e3Smrg};
199c582b7e3Smrg
200c582b7e3Smrgconst OptionInfoRec *R128OptionsWeak(void) { return R128Options; }
201c582b7e3Smrg
202c582b7e3SmrgR128RAMRec R128RAM[] = {        /* Memory Specifications
203c582b7e3Smrg				   From RAGE 128 Software Development
204c582b7e3Smrg				   Manual (Technical Reference Manual P/N
205c582b7e3Smrg				   SDK-G04000 Rev 0.01), page 3-21.  */
206c582b7e3Smrg    { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
207c582b7e3Smrg    { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
208c582b7e3Smrg    { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
209c582b7e3Smrg    { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
210c582b7e3Smrg};
211c582b7e3Smrg
212c582b7e3Smrgextern _X_EXPORT int gR128EntityIndex;
213c582b7e3Smrg
214c582b7e3Smrgint getR128EntityIndex(void)
215c582b7e3Smrg{
216c582b7e3Smrg    return gR128EntityIndex;
217c582b7e3Smrg}
218c582b7e3Smrg
219c582b7e3SmrgR128EntPtr R128EntPriv(ScrnInfoPtr pScrn)
220c582b7e3Smrg{
221c582b7e3Smrg    DevUnion     *pPriv;
222c582b7e3Smrg    R128InfoPtr  info   = R128PTR(pScrn);
223c582b7e3Smrg    pPriv = xf86GetEntityPrivate(info->pEnt->index,
224c582b7e3Smrg                                 getR128EntityIndex());
225c582b7e3Smrg    return pPriv->ptr;
226c582b7e3Smrg}
227c582b7e3Smrg
228c582b7e3Smrg/* Allocate our private R128InfoRec. */
229c582b7e3Smrgstatic Bool R128GetRec(ScrnInfoPtr pScrn)
230c582b7e3Smrg{
231c582b7e3Smrg    if (pScrn->driverPrivate) return TRUE;
232c582b7e3Smrg
233c582b7e3Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1);
234c582b7e3Smrg    return TRUE;
235c582b7e3Smrg}
236c582b7e3Smrg
237c582b7e3Smrg/* Free our private R128InfoRec. */
238c582b7e3Smrgstatic void R128FreeRec(ScrnInfoPtr pScrn)
239c582b7e3Smrg{
240c582b7e3Smrg    if (!pScrn || !pScrn->driverPrivate) return;
24184354367Smrg    free(pScrn->driverPrivate);
242c582b7e3Smrg    pScrn->driverPrivate = NULL;
243c582b7e3Smrg}
244c582b7e3Smrg
245c582b7e3Smrg/* Memory map the MMIO region.  Used during pre-init and by R128MapMem,
246c582b7e3Smrg   below. */
247c582b7e3Smrgstatic Bool R128MapMMIO(ScrnInfoPtr pScrn)
248c582b7e3Smrg{
249c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
250c582b7e3Smrg
25179e5230eSmacallan#ifndef AVOID_FBDEV
252c582b7e3Smrg    if (info->FBDev) {
253c582b7e3Smrg	info->MMIO = fbdevHWMapMMIO(pScrn);
25479e5230eSmacallan    } else
25579e5230eSmacallan#endif
25679e5230eSmacallan    {
257c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
258c582b7e3Smrg	info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
259c582b7e3Smrg				   VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
260c582b7e3Smrg				   info->PciTag,
261c582b7e3Smrg				   info->MMIOAddr,
262c582b7e3Smrg				   R128_MMIOSIZE);
263b3ff493bSmrg        if (!info->MMIO) return FALSE;
264c582b7e3Smrg#else
265c582b7e3Smrg	int err = pci_device_map_range(info->PciInfo,
266c582b7e3Smrg				       info->MMIOAddr,
267c582b7e3Smrg				       R128_MMIOSIZE,
268c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE,
269c582b7e3Smrg				       &info->MMIO);
270c582b7e3Smrg
271c582b7e3Smrg	if (err) {
272c582b7e3Smrg	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
273c582b7e3Smrg                        "Unable to map MMIO aperture. %s (%d)\n",
274c582b7e3Smrg                        strerror (err), err);
275c582b7e3Smrg	    return FALSE;
276c582b7e3Smrg	}
277c582b7e3Smrg#endif
278c582b7e3Smrg    }
279c582b7e3Smrg
280c582b7e3Smrg    return TRUE;
281c582b7e3Smrg}
282c582b7e3Smrg
283c582b7e3Smrg/* Unmap the MMIO region.  Used during pre-init and by R128UnmapMem,
284c582b7e3Smrg   below. */
285c582b7e3Smrgstatic Bool R128UnmapMMIO(ScrnInfoPtr pScrn)
286c582b7e3Smrg{
287c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
288c582b7e3Smrg
28979e5230eSmacallan#ifndef AVOID_FBDEV
290c582b7e3Smrg    if (info->FBDev)
291c582b7e3Smrg	fbdevHWUnmapMMIO(pScrn);
29279e5230eSmacallan    else
29379e5230eSmacallan#endif
29479e5230eSmacallan    {
295c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
296c582b7e3Smrg	xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE);
297c582b7e3Smrg#else
298c582b7e3Smrg	pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE);
299c582b7e3Smrg#endif
300c582b7e3Smrg    }
301c582b7e3Smrg    info->MMIO = NULL;
302c582b7e3Smrg    return TRUE;
303c582b7e3Smrg}
304c582b7e3Smrg
305c582b7e3Smrg/* Memory map the frame buffer.  Used by R128MapMem, below. */
306c582b7e3Smrgstatic Bool R128MapFB(ScrnInfoPtr pScrn)
307c582b7e3Smrg{
308c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
309c582b7e3Smrg
31079e5230eSmacallan#ifndef AVOID_FBDEV
311c582b7e3Smrg    if (info->FBDev) {
312c582b7e3Smrg	info->FB = fbdevHWMapVidmem(pScrn);
31379e5230eSmacallan    } else
31479e5230eSmacallan#endif
31579e5230eSmacallan    {
316c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
317c582b7e3Smrg	info->FB = xf86MapPciMem(pScrn->scrnIndex,
318c582b7e3Smrg				 VIDMEM_FRAMEBUFFER,
319c582b7e3Smrg				 info->PciTag,
320c582b7e3Smrg				 info->LinearAddr,
321c582b7e3Smrg				 info->FbMapSize);
322c582b7e3Smrg#else
323c582b7e3Smrg	int err = pci_device_map_range(info->PciInfo,
324c582b7e3Smrg				       info->LinearAddr,
325c582b7e3Smrg				       info->FbMapSize,
326c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITABLE |
327c582b7e3Smrg				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
328c582b7e3Smrg				       &info->FB);
329c582b7e3Smrg
330c582b7e3Smrg	if (err) {
331c582b7e3Smrg	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
332c582b7e3Smrg                        "Unable to map FB aperture. %s (%d)\n",
333c582b7e3Smrg                        strerror (err), err);
334c582b7e3Smrg	    return FALSE;
335c582b7e3Smrg	}
336c582b7e3Smrg#endif
337c582b7e3Smrg    }
338c582b7e3Smrg
339c582b7e3Smrg    if (!info->FB) return FALSE;
340c582b7e3Smrg    return TRUE;
341c582b7e3Smrg}
342c582b7e3Smrg
343c582b7e3Smrg/* Unmap the frame buffer.  Used by R128UnmapMem, below. */
344c582b7e3Smrgstatic Bool R128UnmapFB(ScrnInfoPtr pScrn)
345c582b7e3Smrg{
346c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
347c582b7e3Smrg
34879e5230eSmacallan#ifndef AVOID_FBDEV
349c582b7e3Smrg    if (info->FBDev)
350c582b7e3Smrg	fbdevHWUnmapVidmem(pScrn);
351c582b7e3Smrg    else
35279e5230eSmacallan#endif
353c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
354c582b7e3Smrg	xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
355c582b7e3Smrg#else
356c582b7e3Smrg	pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize);
357c582b7e3Smrg#endif
358c582b7e3Smrg    info->FB = NULL;
359c582b7e3Smrg    return TRUE;
360c582b7e3Smrg}
361c582b7e3Smrg
362c582b7e3Smrg/* Memory map the MMIO region and the frame buffer. */
363c582b7e3Smrgstatic Bool R128MapMem(ScrnInfoPtr pScrn)
364c582b7e3Smrg{
365c582b7e3Smrg    if (!R128MapMMIO(pScrn)) return FALSE;
366c582b7e3Smrg    if (!R128MapFB(pScrn)) {
367c582b7e3Smrg	R128UnmapMMIO(pScrn);
368c582b7e3Smrg	return FALSE;
369c582b7e3Smrg    }
370c582b7e3Smrg    return TRUE;
371c582b7e3Smrg}
372c582b7e3Smrg
373c582b7e3Smrg/* Unmap the MMIO region and the frame buffer. */
374c582b7e3Smrgstatic Bool R128UnmapMem(ScrnInfoPtr pScrn)
375c582b7e3Smrg{
376c582b7e3Smrg    if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE;
377c582b7e3Smrg    return TRUE;
378c582b7e3Smrg}
379c582b7e3Smrg
380c582b7e3Smrg/* Read PLL information */
381c582b7e3Smrgunsigned R128INPLL(ScrnInfoPtr pScrn, int addr)
382c582b7e3Smrg{
383c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
384c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
385c582b7e3Smrg
386c582b7e3Smrg    OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f);
387c582b7e3Smrg    return INREG(R128_CLOCK_CNTL_DATA);
388c582b7e3Smrg}
389c582b7e3Smrg
390c582b7e3Smrg#if 0
391c582b7e3Smrg/* Read PAL information (only used for debugging). */
392c582b7e3Smrgstatic int R128INPAL(int idx)
393c582b7e3Smrg{
394c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
395c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
396c582b7e3Smrg
397c582b7e3Smrg    OUTREG(R128_PALETTE_INDEX, idx << 16);
398c582b7e3Smrg    return INREG(R128_PALETTE_DATA);
399c582b7e3Smrg}
400c582b7e3Smrg#endif
401c582b7e3Smrg
402c582b7e3Smrg/* Wait for vertical sync. */
403c582b7e3Smrgvoid R128WaitForVerticalSync(ScrnInfoPtr pScrn)
404c582b7e3Smrg{
405c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
406c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
407c582b7e3Smrg    int           i;
408c582b7e3Smrg
409c582b7e3Smrg    OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK);
410c582b7e3Smrg    for (i = 0; i < R128_TIMEOUT; i++) {
411c582b7e3Smrg	if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break;
412c582b7e3Smrg    }
413c582b7e3Smrg}
414c582b7e3Smrg
415c582b7e3Smrg/* Compute log base 2 of val. */
416c582b7e3Smrgint R128MinBits(int val)
417c582b7e3Smrg{
418c582b7e3Smrg    int bits;
419c582b7e3Smrg
420c582b7e3Smrg    if (!val) return 1;
421c582b7e3Smrg    for (bits = 0; val; val >>= 1, ++bits);
422c582b7e3Smrg    return bits;
423c582b7e3Smrg}
424c582b7e3Smrg
425c582b7e3Smrg/* Compute n/d with rounding. */
426c582b7e3Smrgstatic int R128Div(int n, int d)
427c582b7e3Smrg{
428c582b7e3Smrg    return (n + (d / 2)) / d;
429c582b7e3Smrg}
430c582b7e3Smrg
431b3ff493bSmrg/* Finds the first output using a given crtc. */
432b3ff493bSmrgxf86OutputPtr R128FirstOutput(xf86CrtcPtr crtc)
433b3ff493bSmrg{
434b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
435b3ff493bSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
436b3ff493bSmrg    xf86OutputPtr output = xf86_config->output[0];
437b3ff493bSmrg    int o;
438b3ff493bSmrg
439b3ff493bSmrg    for (o = 0; o < xf86_config->num_output; o++) {
440b3ff493bSmrg        output = xf86_config->output[o];
441b3ff493bSmrg        if (output->crtc == crtc) break;
442b3ff493bSmrg    }
443b3ff493bSmrg
444b3ff493bSmrg    return output;
445b3ff493bSmrg}
446b3ff493bSmrg
447b3ff493bSmrg/* Read the Video BIOS block. */
448c582b7e3Smrgstatic Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
449c582b7e3Smrg{
450c582b7e3Smrg    R128InfoPtr info = R128PTR(pScrn);
451c582b7e3Smrg
452c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS
453c582b7e3Smrg    int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE;
45484354367Smrg    info->VBIOS = malloc(size);
455c582b7e3Smrg#else
45684354367Smrg    info->VBIOS = malloc(R128_VBIOS_SIZE);
457c582b7e3Smrg#endif
458c582b7e3Smrg
459c582b7e3Smrg    if (!info->VBIOS) {
460c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
461c582b7e3Smrg		   "Cannot allocate space for hold Video BIOS!\n");
462c582b7e3Smrg	return FALSE;
463c582b7e3Smrg    }
464c582b7e3Smrg
465c582b7e3Smrg    if (pInt10) {
466c582b7e3Smrg	info->BIOSAddr = pInt10->BIOSseg << 4;
467c582b7e3Smrg	(void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
468c582b7e3Smrg		     R128_VBIOS_SIZE);
469c582b7e3Smrg    } else {
470c582b7e3Smrg#ifdef XSERVER_LIBPCIACCESS
471c582b7e3Smrg	if (pci_device_read_rom(info->PciInfo, info->VBIOS)) {
472c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
473c582b7e3Smrg		       "Failed to read PCI ROM!\n");
474c582b7e3Smrg	}
475c582b7e3Smrg#else
476c582b7e3Smrg	xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE);
477c582b7e3Smrg	if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
478c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
479c582b7e3Smrg		       "Video BIOS not detected in PCI space!\n");
480c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
481c582b7e3Smrg		       "Attempting to read Video BIOS from legacy ISA space!\n");
482c582b7e3Smrg	    info->BIOSAddr = 0x000c0000;
483c582b7e3Smrg	    xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS);
484c582b7e3Smrg	}
485c582b7e3Smrg#endif
486c582b7e3Smrg    }
487c582b7e3Smrg    if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
488c582b7e3Smrg	info->BIOSAddr = 0x00000000;
48984354367Smrg	free(info->VBIOS);
490c582b7e3Smrg	info->VBIOS = NULL;
491c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
492c582b7e3Smrg		   "Video BIOS not found!\n");
493c582b7e3Smrg    }
494c582b7e3Smrg
495b3ff493bSmrg    return TRUE;
496b3ff493bSmrg}
497c582b7e3Smrg
498b3ff493bSmrg/* Read the FP parameters if an LVDS panel is expected. */
499b3ff493bSmrgvoid R128GetPanelInfoFromBIOS(xf86OutputPtr output)
500b3ff493bSmrg{
501b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
502b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
503b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
504b3ff493bSmrg    int FPHeader = 0;
505b3ff493bSmrg    int i;
506c582b7e3Smrg
507b3ff493bSmrg    r128_output->PanelPwrDly = 200;
508b3ff493bSmrg    xf86GetOptValInteger(info->Options, OPTION_PANEL_WIDTH,  &(r128_output->PanelXRes));
509b3ff493bSmrg    xf86GetOptValInteger(info->Options, OPTION_PANEL_HEIGHT, &(r128_output->PanelYRes));
510b3ff493bSmrg
511449624caSmacallan    if (!info->VBIOS) goto fallback;
512b3ff493bSmrg    info->FPBIOSstart = 0;
513b3ff493bSmrg
514b3ff493bSmrg    /* FIXME: There should be direct access to the start of the FP info
515b3ff493bSmrg     * tables, but until we find out where that offset is stored, we
516b3ff493bSmrg     * must search for the ATI signature string: "M3      ".
517b3ff493bSmrg     */
518b3ff493bSmrg    for (i = 4; i < R128_VBIOS_SIZE - 8; i++) {
519b3ff493bSmrg        if (R128_BIOS8(i)     == 'M' &&
520b3ff493bSmrg            R128_BIOS8(i + 1) == '3' &&
521b3ff493bSmrg            R128_BIOS8(i + 2) == ' ' &&
522b3ff493bSmrg            R128_BIOS8(i + 3) == ' ' &&
523b3ff493bSmrg            R128_BIOS8(i + 4) == ' ' &&
524b3ff493bSmrg            R128_BIOS8(i + 5) == ' ' &&
525b3ff493bSmrg            R128_BIOS8(i + 6) == ' ' &&
526b3ff493bSmrg            R128_BIOS8(i + 7) == ' ') {
527b3ff493bSmrg            FPHeader = i - 2;
528b3ff493bSmrg            break;
529b3ff493bSmrg        }
530b3ff493bSmrg    }
531b3ff493bSmrg
532449624caSmacallan    if (!FPHeader) goto fallback;
533b3ff493bSmrg
534b3ff493bSmrg
535b3ff493bSmrg    /* Assume that only one panel is attached and supported */
536b3ff493bSmrg    for (i = FPHeader + 20; i < FPHeader + 84; i += 2) {
537b3ff493bSmrg        if (R128_BIOS16(i) != 0) {
538b3ff493bSmrg            info->FPBIOSstart = R128_BIOS16(i);
539b3ff493bSmrg            break;
540b3ff493bSmrg        }
541c582b7e3Smrg    }
542c582b7e3Smrg
543b3ff493bSmrg#ifndef AVOID_FBDEV
544b3ff493bSmrg    if (!info->FPBIOSstart) return;
545b3ff493bSmrg#endif
546b3ff493bSmrg
547b3ff493bSmrg    if (!r128_output->PanelXRes)
548b3ff493bSmrg        r128_output->PanelXRes = R128_BIOS16(info->FPBIOSstart + 25);
549b3ff493bSmrg    if (!r128_output->PanelYRes)
550b3ff493bSmrg        r128_output->PanelYRes = R128_BIOS16(info->FPBIOSstart + 27);
551b3ff493bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n",
552b3ff493bSmrg               r128_output->PanelXRes, r128_output->PanelYRes);
553b3ff493bSmrg
554b3ff493bSmrg    r128_output->PanelPwrDly = R128_BIOS8(info->FPBIOSstart + 56);
555b3ff493bSmrg
556b3ff493bSmrg    if (!r128_output->PanelXRes || !r128_output->PanelYRes) {
557c582b7e3Smrg        info->HasPanelRegs = FALSE;
558c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
559c582b7e3Smrg		   "Can't determine panel dimensions, and none specified.\n"
560c582b7e3Smrg		   "\tDisabling programming of FP registers.\n");
561c582b7e3Smrg    }
562c582b7e3Smrg
563b3ff493bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: ");
564b3ff493bSmrg    for (i = 1; i <= 24; i++)
565b3ff493bSmrg        ErrorF("%c", R128_BIOS8(info->FPBIOSstart + i));
566b3ff493bSmrg
567b3ff493bSmrg    ErrorF("\n");
568b3ff493bSmrg
569b3ff493bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: ");
570b3ff493bSmrg    i = R128_BIOS16(info->FPBIOSstart + 29);
571b3ff493bSmrg    if (i & 1) ErrorF("Color, ");
572b3ff493bSmrg    else       ErrorF("Monochrome, ");
573b3ff493bSmrg    if (i & 2) ErrorF("Dual(split), ");
574b3ff493bSmrg    else       ErrorF("Single, ");
575b3ff493bSmrg
576b3ff493bSmrg    switch ((i >> 2) & 0x3f) {
577b3ff493bSmrg    case 0:  ErrorF("STN");        break;
578b3ff493bSmrg    case 1:  ErrorF("TFT");        break;
579b3ff493bSmrg    case 2:  ErrorF("Active STN"); break;
580b3ff493bSmrg    case 3:  ErrorF("EL");         break;
581b3ff493bSmrg    case 4:  ErrorF("Plasma");     break;
582b3ff493bSmrg    default: ErrorF("UNKNOWN");    break;
583b3ff493bSmrg    }
584b3ff493bSmrg
585b3ff493bSmrg    ErrorF("\n");
586b3ff493bSmrg
587b3ff493bSmrg    if (R128_BIOS8(info->FPBIOSstart + 61) & 1) {
588b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n");
589b3ff493bSmrg    } else {
590b3ff493bSmrg        /* FIXME: Add Non-LVDS flat pael support */
591b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
592b3ff493bSmrg                   "Non-LVDS panel interface detected!  "
593b3ff493bSmrg                   "This support is untested and may not "
594b3ff493bSmrg                   "function properly\n");
595b3ff493bSmrg    }
596449624caSmacallan    return;
597449624caSmacallanfallback:
598449624caSmacallan#ifdef __NetBSD__
599e1efbb8aSmacallan    if ((!r128_output->PanelXRes || !r128_output->PanelYRes)  &&
600e1efbb8aSmacallan        (info->HaveWSDisplay)) {
601449624caSmacallan	/*
602449624caSmacallan	 * we may not be on x86 so check wsdisplay for panel dimensions
603449624caSmacallan	 * XXX this assumes that the r128 is the console, although that should
604449624caSmacallan	 * be the case in the vast majority of cases where an LCD is hooked up
605449624caSmacallan	 * directly
606449624caSmacallan	 * We should probably just check the relevant registers but I'm not
607449624caSmacallan	 * sure they're available at this point.
608449624caSmacallan	 */
609449624caSmacallan	struct wsdisplay_fbinfo fbinfo;
610449624caSmacallan
611449624caSmacallan	if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GINFO, &fbinfo) == 0) {
612449624caSmacallan	    r128_output->PanelXRes = fbinfo.width;
613449624caSmacallan	    r128_output->PanelYRes = fbinfo.height;
614449624caSmacallan	}
615449624caSmacallan    }
616449624caSmacallan#endif
617c582b7e3Smrg}
618c582b7e3Smrg
619c582b7e3Smrg/* Read PLL parameters from BIOS block.  Default to typical values if there
620c582b7e3Smrg   is no BIOS. */
621c582b7e3Smrgstatic Bool R128GetPLLParameters(ScrnInfoPtr pScrn)
622c582b7e3Smrg{
623c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
624c582b7e3Smrg    R128PLLPtr    pll  = &info->pll;
625c582b7e3Smrg
626c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__)
627c582b7e3Smrg    /* there is no bios under Linux PowerPC but Open Firmware
628c582b7e3Smrg       does set up the PLL registers properly and we can use
629c582b7e3Smrg       those to calculate xclk and find the reference divider */
630c582b7e3Smrg
631c582b7e3Smrg    unsigned x_mpll_ref_fb_div;
632c582b7e3Smrg    unsigned xclk_cntl;
633c582b7e3Smrg    unsigned Nx, M;
634c582b7e3Smrg    unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12};
635c582b7e3Smrg
636c582b7e3Smrg    /* Assume REF clock is 2950 (in units of 10khz) */
637c582b7e3Smrg    /* and that all pllclk must be between 125 Mhz and 250Mhz */
638c582b7e3Smrg    pll->reference_freq = 2950;
639c582b7e3Smrg    pll->min_pll_freq   = 12500;
640c582b7e3Smrg    pll->max_pll_freq   = 25000;
641c582b7e3Smrg
642c582b7e3Smrg    x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV);
643c582b7e3Smrg    xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7;
644c582b7e3Smrg    pll->reference_div =
645c582b7e3Smrg	INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK;
646c582b7e3Smrg
647c582b7e3Smrg    Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8;
648c582b7e3Smrg    M =  (x_mpll_ref_fb_div & 0x0000FF);
649c582b7e3Smrg
650c582b7e3Smrg    pll->xclk =  R128Div((2 * Nx * pll->reference_freq),
651c582b7e3Smrg			 (M * PostDivSet[xclk_cntl]));
652c582b7e3Smrg
653c582b7e3Smrg#else /* !defined(__powerpc__) */
654c582b7e3Smrg
655c582b7e3Smrg    if (!info->VBIOS) {
656c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
657c582b7e3Smrg		   "Video BIOS not detected, using default PLL parameters!\n");
658c582b7e3Smrg				/* These probably aren't going to work for
659c582b7e3Smrg				   the card you are using.  Specifically,
660c582b7e3Smrg				   reference freq can be 29.50MHz,
661c582b7e3Smrg				   28.63MHz, or 14.32MHz.  YMMV. */
662c582b7e3Smrg	pll->reference_freq = 2950;
663c582b7e3Smrg	pll->reference_div  = 65;
664c582b7e3Smrg	pll->min_pll_freq   = 12500;
665c582b7e3Smrg	pll->max_pll_freq   = 25000;
666c582b7e3Smrg	pll->xclk           = 10300;
667c582b7e3Smrg    } else {
668b3ff493bSmrg	uint16_t bios_header    = R128_BIOS16(0x48);
669b3ff493bSmrg	uint16_t pll_info_block = R128_BIOS16(bios_header + 0x30);
670c582b7e3Smrg	R128TRACE(("Header at 0x%04x; PLL Information at 0x%04x\n",
671c582b7e3Smrg		   bios_header, pll_info_block));
672c582b7e3Smrg
673c582b7e3Smrg	pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e);
674c582b7e3Smrg	pll->reference_div  = R128_BIOS16(pll_info_block + 0x10);
675c582b7e3Smrg	pll->min_pll_freq   = R128_BIOS32(pll_info_block + 0x12);
676c582b7e3Smrg	pll->max_pll_freq   = R128_BIOS32(pll_info_block + 0x16);
677c582b7e3Smrg	pll->xclk           = R128_BIOS16(pll_info_block + 0x08);
678c582b7e3Smrg    }
679c582b7e3Smrg#endif /* __powerpc__ */
680c582b7e3Smrg
681c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
682c582b7e3Smrg	       "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
683c582b7e3Smrg	       pll->reference_freq,
684c582b7e3Smrg	       pll->reference_div,
685c582b7e3Smrg	       pll->min_pll_freq,
686c582b7e3Smrg	       pll->max_pll_freq,
687c582b7e3Smrg	       pll->xclk);
688c582b7e3Smrg
689c582b7e3Smrg    return TRUE;
690c582b7e3Smrg}
691c582b7e3Smrg
692c582b7e3Smrg/* This is called by R128PreInit to set up the default visual. */
693c582b7e3Smrgstatic Bool R128PreInitVisual(ScrnInfoPtr pScrn)
694c582b7e3Smrg{
695c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
696c582b7e3Smrg
697c582b7e3Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb
698c582b7e3Smrg					  | Support32bppFb
699c582b7e3Smrg					  | SupportConvert32to24
700c582b7e3Smrg					  )))
701c582b7e3Smrg	return FALSE;
702c582b7e3Smrg
703c582b7e3Smrg    switch (pScrn->depth) {
704c582b7e3Smrg    case 8:
705c582b7e3Smrg    case 15:
706c582b7e3Smrg    case 16:
707c582b7e3Smrg    case 24:
708c582b7e3Smrg	break;
709c582b7e3Smrg    default:
710c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
711c582b7e3Smrg		   "Given depth (%d) is not supported by %s driver\n",
712c582b7e3Smrg		   pScrn->depth, R128_DRIVER_NAME);
713c582b7e3Smrg	return FALSE;
714c582b7e3Smrg    }
715c582b7e3Smrg
716c582b7e3Smrg    xf86PrintDepthBpp(pScrn);
717c582b7e3Smrg
718c582b7e3Smrg    info->fifo_slots  = 0;
719c582b7e3Smrg    info->pix24bpp    = xf86GetBppFromDepth(pScrn, pScrn->depth);
720c582b7e3Smrg    info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
721c582b7e3Smrg    info->CurrentLayout.depth        = pScrn->depth;
722c582b7e3Smrg    info->CurrentLayout.pixel_bytes  = pScrn->bitsPerPixel / 8;
723c582b7e3Smrg    info->CurrentLayout.pixel_code   = (pScrn->bitsPerPixel != 16
724c582b7e3Smrg				       ? pScrn->bitsPerPixel
725c582b7e3Smrg				       : pScrn->depth);
726c582b7e3Smrg
727c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
728c582b7e3Smrg	       "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
729c582b7e3Smrg	       pScrn->depth,
730c582b7e3Smrg	       info->CurrentLayout.pixel_bytes,
731c582b7e3Smrg	       info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
732c582b7e3Smrg	       info->pix24bpp);
733c582b7e3Smrg
734c582b7e3Smrg
735c582b7e3Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
736c582b7e3Smrg
737c582b7e3Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
738c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
739c582b7e3Smrg		   "Default visual (%s) is not supported at depth %d\n",
740c582b7e3Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
741c582b7e3Smrg	return FALSE;
742c582b7e3Smrg    }
743c582b7e3Smrg    return TRUE;
744c582b7e3Smrg
745c582b7e3Smrg}
746c582b7e3Smrg
747c582b7e3Smrg/* This is called by R128PreInit to handle all color weight issues. */
748c582b7e3Smrgstatic Bool R128PreInitWeight(ScrnInfoPtr pScrn)
749c582b7e3Smrg{
750c582b7e3Smrg    R128InfoPtr info          = R128PTR(pScrn);
751c582b7e3Smrg
752c582b7e3Smrg				/* Save flag for 6 bit DAC to use for
753c582b7e3Smrg				   setting CRTC registers.  Otherwise use
754c582b7e3Smrg				   an 8 bit DAC, even if xf86SetWeight sets
755c582b7e3Smrg				   pScrn->rgbBits to some value other than
756c582b7e3Smrg				   8. */
757c582b7e3Smrg    info->dac6bits = FALSE;
758c582b7e3Smrg    if (pScrn->depth > 8) {
759c582b7e3Smrg	rgb defaultWeight = { 0, 0, 0 };
760c582b7e3Smrg	if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
761c582b7e3Smrg    } else {
762c582b7e3Smrg	pScrn->rgbBits = 8;
763c582b7e3Smrg	if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) {
764c582b7e3Smrg	    pScrn->rgbBits = 6;
765c582b7e3Smrg	    info->dac6bits = TRUE;
766c582b7e3Smrg	}
767c582b7e3Smrg    }
768c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
769c582b7e3Smrg	       "Using %d bits per RGB (%d bit DAC)\n",
770c582b7e3Smrg	       pScrn->rgbBits, info->dac6bits ? 6 : 8);
771c582b7e3Smrg
772c582b7e3Smrg    return TRUE;
773c582b7e3Smrg
774c582b7e3Smrg}
775c582b7e3Smrg
776c582b7e3Smrg/* This is called by R128PreInit to handle config file overrides for things
777c582b7e3Smrg   like chipset and memory regions.  Also determine memory size and type.
778c582b7e3Smrg   If memory type ever needs an override, put it in this routine. */
779c582b7e3Smrgstatic Bool R128PreInitConfig(ScrnInfoPtr pScrn)
780c582b7e3Smrg{
781c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
782b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
783c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
784c582b7e3Smrg    EntityInfoPtr pEnt      = info->pEnt;
785c582b7e3Smrg    GDevPtr       dev       = pEnt->device;
786c582b7e3Smrg    int           offset    = 0;        /* RAM Type */
787c582b7e3Smrg    MessageType   from;
788c582b7e3Smrg
789c582b7e3Smrg				/* Chipset */
790c582b7e3Smrg    from = X_PROBED;
791c582b7e3Smrg    if (dev->chipset && *dev->chipset) {
792c582b7e3Smrg	info->Chipset  = xf86StringToToken(R128Chipsets, dev->chipset);
793c582b7e3Smrg	from           = X_CONFIG;
794c582b7e3Smrg    } else if (dev->chipID >= 0) {
795c582b7e3Smrg	info->Chipset  = dev->chipID;
796c582b7e3Smrg	from           = X_CONFIG;
797c582b7e3Smrg    } else {
798c582b7e3Smrg	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
799c582b7e3Smrg    }
800c582b7e3Smrg    pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset);
801c582b7e3Smrg
802c582b7e3Smrg    if (!pScrn->chipset) {
803c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
804c582b7e3Smrg		   "ChipID 0x%04x is not recognized\n", info->Chipset);
805c582b7e3Smrg	return FALSE;
806c582b7e3Smrg    }
807c582b7e3Smrg
808c582b7e3Smrg    if (info->Chipset < 0) {
809c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
810c582b7e3Smrg		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
811c582b7e3Smrg	return FALSE;
812c582b7e3Smrg    }
813c582b7e3Smrg
814c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
815c582b7e3Smrg	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
816c582b7e3Smrg	       pScrn->chipset,
817c582b7e3Smrg	       info->Chipset);
818c582b7e3Smrg
819c582b7e3Smrg				/* Framebuffer */
820c582b7e3Smrg
821c582b7e3Smrg    from             = X_PROBED;
822c582b7e3Smrg    info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000;
823c582b7e3Smrg    pScrn->memPhysBase = info->LinearAddr;
824c582b7e3Smrg    if (dev->MemBase) {
825c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
826c582b7e3Smrg		   "Linear address override, using 0x%08lx instead of 0x%08lx\n",
827c582b7e3Smrg		   dev->MemBase,
828c582b7e3Smrg		   info->LinearAddr);
829c582b7e3Smrg	info->LinearAddr = dev->MemBase;
830c582b7e3Smrg	from             = X_CONFIG;
831c582b7e3Smrg    } else if (!info->LinearAddr) {
832c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
833c582b7e3Smrg		   "No valid linear framebuffer address\n");
834c582b7e3Smrg	return FALSE;
835c582b7e3Smrg    }
836c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
837c582b7e3Smrg	       "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
838c582b7e3Smrg
839c582b7e3Smrg				/* MMIO registers */
840c582b7e3Smrg    from             = X_PROBED;
841c582b7e3Smrg    info->MMIOAddr   = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00;
842c582b7e3Smrg    if (dev->IOBase) {
843c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
844c582b7e3Smrg		   "MMIO address override, using 0x%08lx instead of 0x%08lx\n",
845c582b7e3Smrg		   dev->IOBase,
846c582b7e3Smrg		   info->MMIOAddr);
847c582b7e3Smrg	info->MMIOAddr = dev->IOBase;
848c582b7e3Smrg	from           = X_CONFIG;
849c582b7e3Smrg    } else if (!info->MMIOAddr) {
850c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
851c582b7e3Smrg	return FALSE;
852c582b7e3Smrg    }
853c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
854c582b7e3Smrg	       "MMIO registers at 0x%08lx\n", info->MMIOAddr);
855c582b7e3Smrg
856c582b7e3Smrg#ifndef XSERVER_LIBPCIACCESS
857c582b7e3Smrg				/* BIOS */
858c582b7e3Smrg    from              = X_PROBED;
859c582b7e3Smrg    info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
860c582b7e3Smrg    if (info->BIOSAddr) {
861c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, from,
862c582b7e3Smrg		   "BIOS at 0x%08lx\n", info->BIOSAddr);
863c582b7e3Smrg    }
864c582b7e3Smrg#endif
865c582b7e3Smrg
866c582b7e3Smrg				/* Flat panel (part 1) */
867c582b7e3Smrg    if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS,
868c582b7e3Smrg			  &info->HasPanelRegs)) {
869c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
870c582b7e3Smrg		   "Turned flat panel register programming %s\n",
871c582b7e3Smrg		   info->HasPanelRegs ? "on" : "off");
872c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
873c582b7e3Smrg		   "\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");
874c582b7e3Smrg    } else {
875c582b7e3Smrg        info->isDFP = FALSE;
876c582b7e3Smrg        info->isPro2 = FALSE;
877b3ff493bSmrg        pR128Ent->HasCRTC2 = FALSE;
878c582b7e3Smrg	switch (info->Chipset) {
879c582b7e3Smrg	/* R128 Pro and Pro2 can have DFP, we will deal with it.
880c582b7e3Smrg	   No support for dual-head/xinerama yet.
881c582b7e3Smrg           M3 can also have DFP, no support for now */
882c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
883c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
884c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
885c582b7e3Smrg	/* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came
886c582b7e3Smrg	 *        out at the same time, so are of the same family likely.
887c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
888c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
889c582b7e3Smrg	 */
890c582b7e3Smrg	case PCI_CHIP_RAGE128TS:
891c582b7e3Smrg	case PCI_CHIP_RAGE128TT:
892c582b7e3Smrg	case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE;
893c582b7e3Smrg	/* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP
894c582b7e3Smrg	 *        capability, as the comment at the top suggests.
895c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
896c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
897c582b7e3Smrg	 */
898c582b7e3Smrg	case PCI_CHIP_RAGE128PA:
899c582b7e3Smrg	case PCI_CHIP_RAGE128PB:
900c582b7e3Smrg	case PCI_CHIP_RAGE128PC:
901c582b7e3Smrg	case PCI_CHIP_RAGE128PE:
902c582b7e3Smrg	case PCI_CHIP_RAGE128PG:
903c582b7e3Smrg	case PCI_CHIP_RAGE128PH:
904c582b7e3Smrg	case PCI_CHIP_RAGE128PI:
905c582b7e3Smrg	case PCI_CHIP_RAGE128PJ:
906c582b7e3Smrg	case PCI_CHIP_RAGE128PK:
907c582b7e3Smrg	case PCI_CHIP_RAGE128PL:
908c582b7e3Smrg	case PCI_CHIP_RAGE128PM:
909c582b7e3Smrg	case PCI_CHIP_RAGE128PN:
910c582b7e3Smrg	case PCI_CHIP_RAGE128PO:
911c582b7e3Smrg	case PCI_CHIP_RAGE128PQ:
912c582b7e3Smrg	case PCI_CHIP_RAGE128PS:
913c582b7e3Smrg	case PCI_CHIP_RAGE128PT:
914c582b7e3Smrg	case PCI_CHIP_RAGE128PU:
915c582b7e3Smrg	case PCI_CHIP_RAGE128PV:
916c582b7e3Smrg	case PCI_CHIP_RAGE128PW:
917c582b7e3Smrg	case PCI_CHIP_RAGE128PX:
918c582b7e3Smrg
919c582b7e3Smrg	case PCI_CHIP_RAGE128PD:
920c582b7e3Smrg	case PCI_CHIP_RAGE128PF:
921c582b7e3Smrg	case PCI_CHIP_RAGE128PP:
922c582b7e3Smrg	case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break;
923c582b7e3Smrg
924c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
925c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
926c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
927c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
928d6cc4c59Smacallan			info->HasPanelRegs = TRUE;
929d6cc4c59Smacallan			info->isDFP = TRUE;
930c582b7e3Smrg			/* which chips support dualhead? */
931b3ff493bSmrg			pR128Ent->HasCRTC2 = TRUE;
932c582b7e3Smrg			break;
933c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
934c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
935c582b7e3Smrg	case PCI_CHIP_RAGE128RG:
936c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
937c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
938c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
939c582b7e3Smrg	/* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as
940c582b7e3Smrg	 *        all of them are listed as "Rage 128 4x" in ATI docs.
941c582b7e3Smrg	 *        This requires confirmation however to be fully correct.
942c582b7e3Smrg	 *        Mike A. Harris <mharris@redhat.com>
943c582b7e3Smrg	 */
944c582b7e3Smrg	case PCI_CHIP_RAGE128SE:
945c582b7e3Smrg	case PCI_CHIP_RAGE128SF:
946c582b7e3Smrg	case PCI_CHIP_RAGE128SG:
947c582b7e3Smrg	case PCI_CHIP_RAGE128SH:
948c582b7e3Smrg	case PCI_CHIP_RAGE128SK:
949c582b7e3Smrg	case PCI_CHIP_RAGE128SL:
950c582b7e3Smrg	case PCI_CHIP_RAGE128SN:
951c582b7e3Smrg	default:                 info->HasPanelRegs = FALSE; break;
952c582b7e3Smrg	}
953c582b7e3Smrg    }
954c582b7e3Smrg
955c582b7e3Smrg				/* Read registers used to determine options */
956c582b7e3Smrg    from                      = X_PROBED;
957b3ff493bSmrg    if (!R128MapMMIO(pScrn)) return FALSE;
958c582b7e3Smrg    R128MMIO                  = info->MMIO;
959c582b7e3Smrg
96079e5230eSmacallan#ifndef AVOID_FBDEV
961c582b7e3Smrg    if (info->FBDev)
962c582b7e3Smrg	pScrn->videoRam       = fbdevHWGetVidmem(pScrn) / 1024;
963c582b7e3Smrg    else
96479e5230eSmacallan#endif
965c582b7e3Smrg	pScrn->videoRam       = INREG(R128_CONFIG_MEMSIZE) / 1024;
966c582b7e3Smrg
967c582b7e3Smrg    info->MemCntl             = INREG(R128_MEM_CNTL);
968c582b7e3Smrg    info->BusCntl             = INREG(R128_BUS_CNTL);
969c582b7e3Smrg
970c582b7e3Smrg				/* RAM */
971c582b7e3Smrg    switch (info->MemCntl & 0x3) {
972c582b7e3Smrg    case 0:                     /* SDR SGRAM 1:1 */
973c582b7e3Smrg	switch (info->Chipset) {
974c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
975c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
976c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
977c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
978c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
979c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
980c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
981c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
982c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
983c582b7e3Smrg	case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
984c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
985c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
986c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
987c582b7e3Smrg	default:                 offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
988c582b7e3Smrg	}
989c582b7e3Smrg	break;
990c582b7e3Smrg    case 1:                      offset = 2; break; /*  64-bit SDR SGRAM 2:1 */
991c582b7e3Smrg    case 2:                      offset = 3; break; /*  64-bit DDR SGRAM     */
992c582b7e3Smrg    default:                     offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
993c582b7e3Smrg    }
994c582b7e3Smrg    info->ram = &R128RAM[offset];
995c582b7e3Smrg
996c582b7e3Smrg    if (dev->videoRam) {
997c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
998c582b7e3Smrg		   "Video RAM override, using %d kB instead of %d kB\n",
999c582b7e3Smrg		   dev->videoRam,
1000c582b7e3Smrg		   pScrn->videoRam);
1001c582b7e3Smrg	from             = X_CONFIG;
1002c582b7e3Smrg	pScrn->videoRam  = dev->videoRam;
1003c582b7e3Smrg    }
1004c582b7e3Smrg
1005c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
1006c582b7e3Smrg	       "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
1007c582b7e3Smrg
1008c582b7e3Smrg    pScrn->videoRam  &= ~1023;
1009c582b7e3Smrg    info->FbMapSize  = pScrn->videoRam * 1024;
1010c582b7e3Smrg
101184354367Smrg#ifdef R128DRI
1012c582b7e3Smrg				/* DMA for Xv */
1013c582b7e3Smrg    info->DMAForXv = xf86ReturnOptValBool(info->Options, OPTION_XV_DMA, FALSE);
1014c582b7e3Smrg    if (info->DMAForXv) {
1015c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1016c582b7e3Smrg		   "Will try to use DMA for Xv image transfers\n");
1017c582b7e3Smrg    }
1018c582b7e3Smrg
1019c582b7e3Smrg				/* AGP/PCI */
1020c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) {
1021c582b7e3Smrg	info->IsPCI = TRUE;
1022c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n");
1023c582b7e3Smrg    } else {
1024c582b7e3Smrg	switch (info->Chipset) {
1025c582b7e3Smrg	case PCI_CHIP_RAGE128LE:
1026c582b7e3Smrg	case PCI_CHIP_RAGE128RE:
1027c582b7e3Smrg	case PCI_CHIP_RAGE128RK:
1028c582b7e3Smrg	case PCI_CHIP_RAGE128PD:
1029c582b7e3Smrg	case PCI_CHIP_RAGE128PR:
1030c582b7e3Smrg	case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE;  break;
1031c582b7e3Smrg	case PCI_CHIP_RAGE128LF:
1032c582b7e3Smrg	case PCI_CHIP_RAGE128MF:
1033c582b7e3Smrg	case PCI_CHIP_RAGE128ML:
1034c582b7e3Smrg	case PCI_CHIP_RAGE128PF:
1035c582b7e3Smrg	case PCI_CHIP_RAGE128RF:
1036c582b7e3Smrg	case PCI_CHIP_RAGE128RG:
1037c582b7e3Smrg	case PCI_CHIP_RAGE128RL:
1038c582b7e3Smrg	case PCI_CHIP_RAGE128SM:
1039c582b7e3Smrg	case PCI_CHIP_RAGE128TF:
1040c582b7e3Smrg	case PCI_CHIP_RAGE128TL:
1041c582b7e3Smrg	case PCI_CHIP_RAGE128TR:
1042c582b7e3Smrg	/* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are
1043c582b7e3Smrg	 * believed to be AGP, but need confirmation. <mharris@redhat.com>
1044c582b7e3Smrg	 */
1045c582b7e3Smrg	case PCI_CHIP_RAGE128PA:
1046c582b7e3Smrg	case PCI_CHIP_RAGE128PB:
1047c582b7e3Smrg	case PCI_CHIP_RAGE128PC:
1048c582b7e3Smrg	case PCI_CHIP_RAGE128PE:
1049c582b7e3Smrg	case PCI_CHIP_RAGE128PG:
1050c582b7e3Smrg	case PCI_CHIP_RAGE128PH:
1051c582b7e3Smrg	case PCI_CHIP_RAGE128PI:
1052c582b7e3Smrg	case PCI_CHIP_RAGE128PJ:
1053c582b7e3Smrg	case PCI_CHIP_RAGE128PK:
1054c582b7e3Smrg	case PCI_CHIP_RAGE128PL:
1055c582b7e3Smrg	case PCI_CHIP_RAGE128PM:
1056c582b7e3Smrg	case PCI_CHIP_RAGE128PN:
1057c582b7e3Smrg	case PCI_CHIP_RAGE128PO:
1058c582b7e3Smrg	case PCI_CHIP_RAGE128PQ:
1059c582b7e3Smrg	case PCI_CHIP_RAGE128PS:
1060c582b7e3Smrg	case PCI_CHIP_RAGE128PT:
1061c582b7e3Smrg	case PCI_CHIP_RAGE128PU:
1062c582b7e3Smrg	case PCI_CHIP_RAGE128PV:
1063c582b7e3Smrg	case PCI_CHIP_RAGE128PW:
1064c582b7e3Smrg	case PCI_CHIP_RAGE128PX:
1065c582b7e3Smrg	case PCI_CHIP_RAGE128TS:
1066c582b7e3Smrg	case PCI_CHIP_RAGE128TT:
1067c582b7e3Smrg	case PCI_CHIP_RAGE128TU:
1068c582b7e3Smrg	case PCI_CHIP_RAGE128SE:
1069c582b7e3Smrg	case PCI_CHIP_RAGE128SF:
1070c582b7e3Smrg	case PCI_CHIP_RAGE128SG:
1071c582b7e3Smrg	case PCI_CHIP_RAGE128SH:
1072c582b7e3Smrg	case PCI_CHIP_RAGE128SK:
1073c582b7e3Smrg	case PCI_CHIP_RAGE128SL:
1074c582b7e3Smrg	case PCI_CHIP_RAGE128SN:
1075c582b7e3Smrg	default:                 info->IsPCI = FALSE; break;
1076c582b7e3Smrg	}
1077c582b7e3Smrg    }
1078c582b7e3Smrg#endif
1079c582b7e3Smrg
1080c582b7e3Smrg    return TRUE;
1081c582b7e3Smrg}
1082c582b7e3Smrg
1083c582b7e3Smrgstatic Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1084c582b7e3Smrg{
1085c582b7e3Smrg#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__)
1086c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1087c582b7e3Smrg    vbeInfoPtr pVbe;
1088c582b7e3Smrg#endif
1089c582b7e3Smrg
1090c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE;
1091b3ff493bSmrg    if (!xf86LoadSubModule(pScrn, "i2c")) return FALSE;
1092c582b7e3Smrg
1093c582b7e3Smrg#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__)
1094c582b7e3Smrg    /* Int10 is broken on PPC and some Alphas */
1095c582b7e3Smrg    return TRUE;
1096c582b7e3Smrg#else
1097c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1098c582b7e3Smrg	pVbe = VBEInit(pInt10,info->pEnt->index);
1099c582b7e3Smrg	if (!pVbe) return FALSE;
1100c582b7e3Smrg        xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
1101c582b7e3Smrg	vbeFree(pVbe);
1102c582b7e3Smrg	return TRUE;
1103c582b7e3Smrg    } else
1104c582b7e3Smrg	return FALSE;
1105c582b7e3Smrg#endif
1106c582b7e3Smrg}
1107c582b7e3Smrg
1108c582b7e3Smrg/* This is called by R128PreInit to initialize gamma correction. */
1109c582b7e3Smrgstatic Bool R128PreInitGamma(ScrnInfoPtr pScrn)
1110c582b7e3Smrg{
1111c582b7e3Smrg    Gamma zeros = { 0.0, 0.0, 0.0 };
1112c582b7e3Smrg
1113c582b7e3Smrg    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
1114c582b7e3Smrg    return TRUE;
1115c582b7e3Smrg}
1116c582b7e3Smrg
1117c582b7e3Smrg/* This is called by R128PreInit to initialize the hardware cursor. */
1118c582b7e3Smrgstatic Bool R128PreInitCursor(ScrnInfoPtr pScrn)
1119c582b7e3Smrg{
1120c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1121c582b7e3Smrg
1122c582b7e3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1123c582b7e3Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
1124c582b7e3Smrg    }
1125c582b7e3Smrg    return TRUE;
1126c582b7e3Smrg}
1127c582b7e3Smrg
1128c582b7e3Smrgstatic Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
1129c582b7e3Smrg{
1130c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1131b3ff493bSmrg#if !defined(__powerpc__) && !defined(__alpha__)
1132b3ff493bSmrg    /* int10 is broken on some Alphas and powerpc */
1133c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "int10")) {
1134c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
1135c582b7e3Smrg	*ppInt10 = xf86InitInt10(info->pEnt->index);
1136c582b7e3Smrg    }
1137c582b7e3Smrg#endif
1138c582b7e3Smrg    return TRUE;
1139c582b7e3Smrg}
1140c582b7e3Smrg
114184354367Smrg#ifdef R128DRI
1142c582b7e3Smrgstatic Bool R128PreInitDRI(ScrnInfoPtr pScrn)
1143c582b7e3Smrg{
1144c582b7e3Smrg    R128InfoPtr   info = R128PTR(pScrn);
1145c582b7e3Smrg
1146c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) {
1147c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CCE into PIO mode\n");
1148c582b7e3Smrg	info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
1149c582b7e3Smrg    } else {
1150c582b7e3Smrg	info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
1151c582b7e3Smrg    }
1152c582b7e3Smrg
1153c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
1154c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1155c582b7e3Smrg		   "WARNING!!!  CCE Security checks disabled!!! **********\n");
1156c582b7e3Smrg	info->CCESecure = FALSE;
1157c582b7e3Smrg    } else {
1158c582b7e3Smrg	info->CCESecure = TRUE;
1159c582b7e3Smrg    }
1160c582b7e3Smrg
1161c582b7e3Smrg    info->agpMode        = R128_DEFAULT_AGP_MODE;
1162c582b7e3Smrg    info->agpSize        = R128_DEFAULT_AGP_SIZE;
1163c582b7e3Smrg    info->ringSize       = R128_DEFAULT_RING_SIZE;
1164c582b7e3Smrg    info->bufSize        = R128_DEFAULT_BUFFER_SIZE;
1165c582b7e3Smrg    info->agpTexSize     = R128_DEFAULT_AGP_TEX_SIZE;
1166c582b7e3Smrg
1167c582b7e3Smrg    info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
1168c582b7e3Smrg
1169c582b7e3Smrg    if (!info->IsPCI) {
1170c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1171c582b7e3Smrg				 OPTION_AGP_MODE, &(info->agpMode))) {
1172c582b7e3Smrg	    if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
1173c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1174c582b7e3Smrg			   "Illegal AGP Mode: %d\n", info->agpMode);
1175c582b7e3Smrg		return FALSE;
1176c582b7e3Smrg	    }
1177c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1178c582b7e3Smrg		       "Using AGP %dx mode\n", info->agpMode);
1179c582b7e3Smrg	}
1180c582b7e3Smrg
1181c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1182c582b7e3Smrg				 OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
1183c582b7e3Smrg	    switch (info->agpSize) {
1184c582b7e3Smrg	    case 4:
1185c582b7e3Smrg	    case 8:
1186c582b7e3Smrg	    case 16:
1187c582b7e3Smrg	    case 32:
1188c582b7e3Smrg	    case 64:
1189c582b7e3Smrg	    case 128:
1190c582b7e3Smrg	    case 256:
1191c582b7e3Smrg		break;
1192c582b7e3Smrg	    default:
1193c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1194c582b7e3Smrg			   "Illegal AGP size: %d MB\n", info->agpSize);
1195c582b7e3Smrg		return FALSE;
1196c582b7e3Smrg	    }
1197c582b7e3Smrg	}
1198c582b7e3Smrg
1199c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1200c582b7e3Smrg				 OPTION_RING_SIZE, &(info->ringSize))) {
1201c582b7e3Smrg	    if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
1202c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1203c582b7e3Smrg			   "Illegal ring buffer size: %d MB\n",
1204c582b7e3Smrg			   info->ringSize);
1205c582b7e3Smrg		return FALSE;
1206c582b7e3Smrg	    }
1207c582b7e3Smrg	}
1208c582b7e3Smrg
1209c582b7e3Smrg	if (xf86GetOptValInteger(info->Options,
1210c582b7e3Smrg				 OPTION_BUFFER_SIZE, &(info->bufSize))) {
1211c582b7e3Smrg	    if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
1212c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1213c582b7e3Smrg			   "Illegal vertex/indirect buffers size: %d MB\n",
1214c582b7e3Smrg			   info->bufSize);
1215c582b7e3Smrg		return FALSE;
1216c582b7e3Smrg	    }
1217c582b7e3Smrg	    if (info->bufSize > 2) {
1218c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1219c582b7e3Smrg			   "Illegal vertex/indirect buffers size: %d MB\n",
1220c582b7e3Smrg			   info->bufSize);
1221c582b7e3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1222c582b7e3Smrg			   "Clamping vertex/indirect buffers size to 2 MB\n");
1223c582b7e3Smrg		info->bufSize = 2;
1224c582b7e3Smrg	    }
1225c582b7e3Smrg	}
1226c582b7e3Smrg
1227c582b7e3Smrg	if (info->ringSize + info->bufSize + info->agpTexSize >
1228c582b7e3Smrg	    (int)info->agpSize) {
1229c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1230c582b7e3Smrg		       "Buffers are too big for requested AGP space\n");
1231c582b7e3Smrg	    return FALSE;
1232c582b7e3Smrg	}
1233c582b7e3Smrg
1234c582b7e3Smrg	info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
1235c582b7e3Smrg    }
1236c582b7e3Smrg
1237c582b7e3Smrg    if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
1238c582b7e3Smrg			     &(info->CCEusecTimeout))) {
1239c582b7e3Smrg	/* This option checked by the R128 DRM kernel module */
1240c582b7e3Smrg    }
1241c582b7e3Smrg
1242c582b7e3Smrg    if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1243c582b7e3Smrg	info->allowPageFlip = 0;
1244c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1245c582b7e3Smrg		   "Couldn't load shadowfb module:\n");
1246c582b7e3Smrg    } else {
1247c582b7e3Smrg	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1248c582b7e3Smrg						   OPTION_PAGE_FLIP,
1249c582b7e3Smrg						   FALSE);
1250c582b7e3Smrg    }
1251c582b7e3Smrg
1252c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n",
1253c582b7e3Smrg	       info->allowPageFlip ? "en" : "dis");
1254c582b7e3Smrg
1255c582b7e3Smrg    return TRUE;
1256c582b7e3Smrg}
1257c582b7e3Smrg#endif
1258c582b7e3Smrg
1259b3ff493bSmrgstatic Bool R128PreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1260b3ff493bSmrg{
1261b3ff493bSmrg    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1262b3ff493bSmrg    int found = 0;
1263b3ff493bSmrg    int i;
1264b3ff493bSmrg
1265b3ff493bSmrg    if (!R128GetBIOSParameters(pScrn, pInt10))
1266b3ff493bSmrg        return FALSE;
1267b3ff493bSmrg
1268b3ff493bSmrg    if (!R128GetPLLParameters(pScrn))
1269b3ff493bSmrg        return FALSE;
1270b3ff493bSmrg
1271b3ff493bSmrg    if (!R128AllocateControllers(pScrn))
1272b3ff493bSmrg        return FALSE;
1273b3ff493bSmrg
1274b3ff493bSmrg    if (!R128SetupConnectors(pScrn))
1275b3ff493bSmrg        return FALSE;
1276b3ff493bSmrg
1277b3ff493bSmrg    for (i = 0; i < config->num_output; i++) {
1278b3ff493bSmrg        xf86OutputPtr output = config->output[i];
1279b3ff493bSmrg
1280b3ff493bSmrg        output->status = (*output->funcs->detect) (output);
1281b3ff493bSmrg        if (output->status == XF86OutputStatusConnected)
1282b3ff493bSmrg            found++;
1283b3ff493bSmrg    }
1284b3ff493bSmrg    return !!found;
1285b3ff493bSmrg}
1286b3ff493bSmrg
1287c582b7e3Smrgstatic void
1288c582b7e3SmrgR128ProbeDDC(ScrnInfoPtr pScrn, int indx)
1289c582b7e3Smrg{
1290c582b7e3Smrg    vbeInfoPtr pVbe;
1291b3ff493bSmrg
1292b3ff493bSmrg#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__)
1293c582b7e3Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1294c582b7e3Smrg	pVbe = VBEInit(NULL,indx);
1295c582b7e3Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1296c582b7e3Smrg	vbeFree(pVbe);
1297c582b7e3Smrg    }
1298b3ff493bSmrg#endif
1299b3ff493bSmrg}
1300b3ff493bSmrg
1301b3ff493bSmrgstatic Bool R128CRTCResize(ScrnInfoPtr pScrn, int width, int height)
1302b3ff493bSmrg{
1303b3ff493bSmrg    pScrn->virtualX = width;
1304b3ff493bSmrg    pScrn->virtualY = height;
1305b3ff493bSmrg    return TRUE;
1306c582b7e3Smrg}
1307c582b7e3Smrg
1308b3ff493bSmrgstatic const xf86CrtcConfigFuncsRec R128CRTCResizeFuncs = {
1309b3ff493bSmrg    R128CRTCResize
1310b3ff493bSmrg};
1311b3ff493bSmrg
1312c582b7e3Smrg/* R128PreInit is called once at server startup. */
1313c582b7e3SmrgBool R128PreInit(ScrnInfoPtr pScrn, int flags)
1314c582b7e3Smrg{
1315c582b7e3Smrg    R128InfoPtr      info;
1316c582b7e3Smrg    xf86Int10InfoPtr pInt10 = NULL;
1317e1efbb8aSmacallan#ifdef __NetBSD__
1318e1efbb8aSmacallan    struct wsdisplayio_bus_id bid;
1319e1efbb8aSmacallan#endif
1320c582b7e3Smrg
1321c582b7e3Smrg    R128TRACE(("R128PreInit\n"));
1322c582b7e3Smrg
1323c582b7e3Smrg    if (pScrn->numEntities != 1) return FALSE;
1324c582b7e3Smrg
1325c582b7e3Smrg    if (!R128GetRec(pScrn)) return FALSE;
1326c582b7e3Smrg
1327b3ff493bSmrg    info                = R128PTR(pScrn);
1328c582b7e3Smrg    info->SwitchingMode = FALSE;
1329b3ff493bSmrg    info->MMIO          = NULL;
1330c582b7e3Smrg
1331b3ff493bSmrg    info->pEnt          = xf86GetEntityInfo(pScrn->entityList[0]);
1332c582b7e3Smrg    if (info->pEnt->location.type != BUS_PCI) goto fail;
1333c582b7e3Smrg
1334c582b7e3Smrg    if (flags & PROBE_DETECT) {
1335c582b7e3Smrg	R128ProbeDDC(pScrn, info->pEnt->index);
1336c582b7e3Smrg	return TRUE;
1337c582b7e3Smrg    }
1338c582b7e3Smrg
1339b3ff493bSmrg    info->PciInfo       = xf86GetPciInfoForEntity(info->pEnt->index);
1340c582b7e3Smrg
1341c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1342c582b7e3Smrg	       "PCI bus %d card %d func %d\n",
1343c582b7e3Smrg	       PCI_DEV_BUS(info->PciInfo),
1344c582b7e3Smrg	       PCI_DEV_DEV(info->PciInfo),
1345c582b7e3Smrg	       PCI_DEV_FUNC(info->PciInfo));
1346c582b7e3Smrg
1347e1efbb8aSmacallan#ifdef __NetBSD__
1348e1efbb8aSmacallan    /* now check if this is the console */
1349e1efbb8aSmacallan    info->HaveWSDisplay = FALSE;
1350e1efbb8aSmacallan    info->HaveBacklightControl = FALSE;
1351e1efbb8aSmacallan    if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GET_BUSID, &bid) != -1) {
1352e1efbb8aSmacallan    	if ((bid.bus_type == WSDISPLAYIO_BUS_PCI) &&
1353e1efbb8aSmacallan    	    (bid.ubus.pci.bus == PCI_DEV_BUS(info->PciInfo)) &&
1354e1efbb8aSmacallan    	    (bid.ubus.pci.device == PCI_DEV_DEV(info->PciInfo)) &&
1355e1efbb8aSmacallan    	    (bid.ubus.pci.function == PCI_DEV_FUNC(info->PciInfo))) {
1356e1efbb8aSmacallan    	    	struct wsdisplay_param p;
1357e1efbb8aSmacallan    	    	xf86Msg(X_INFO, "Alright, this is the console\n");
1358e1efbb8aSmacallan    	    	info->HaveWSDisplay = TRUE;
1359e1efbb8aSmacallan
1360e1efbb8aSmacallan    	    	/* now see if we have hacklight control */
1361e1efbb8aSmacallan    	    	p.param = WSDISPLAYIO_PARAM_BACKLIGHT;
1362e1efbb8aSmacallan		if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GETPARAM, &p) != -1) {
1363e1efbb8aSmacallan		    xf86Msg(X_INFO, "... and we have backlight control\n");
1364e1efbb8aSmacallan		    info->HaveBacklightControl = TRUE;
1365e1efbb8aSmacallan		}
1366e1efbb8aSmacallan    	}
1367e1efbb8aSmacallan    }
1368e1efbb8aSmacallan#endif
1369e1efbb8aSmacallan
137019019ffeSmrg#ifndef XSERVER_LIBPCIACCESS
1371b3ff493bSmrg    info->PciTag        = pciTag(PCI_DEV_BUS(info->PciInfo),
1372b3ff493bSmrg				PCI_DEV_DEV(info->PciInfo),
1373b3ff493bSmrg				PCI_DEV_FUNC(info->PciInfo));
1374b3ff493bSmrg
1375c582b7e3Smrg    if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail;
1376c582b7e3Smrg    if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail;
1377c582b7e3Smrg
1378b3ff493bSmrg    pScrn->racMemFlags  = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
137919019ffeSmrg#endif
1380b3ff493bSmrg    pScrn->monitor      = pScrn->confScreen->monitor;
1381b3ff493bSmrg
1382b3ff493bSmrg    /* Allocate an xf86CrtcConfig */
1383b3ff493bSmrg    xf86CrtcConfigInit(pScrn, &R128CRTCResizeFuncs);
1384c582b7e3Smrg
1385c582b7e3Smrg    if (!R128PreInitVisual(pScrn))    goto fail;
1386c582b7e3Smrg
1387c582b7e3Smrg				/* We can't do this until we have a
1388c582b7e3Smrg				   pScrn->display. */
1389c582b7e3Smrg    xf86CollectOptions(pScrn, NULL);
139084354367Smrg    if (!(info->Options = malloc(sizeof(R128Options))))    goto fail;
1391c582b7e3Smrg    memcpy(info->Options, R128Options, sizeof(R128Options));
1392c582b7e3Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1393c582b7e3Smrg
1394c582b7e3Smrg    /* By default, don't do VGA IOs on ppc */
1395c582b7e3Smrg#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW)
1396c582b7e3Smrg    info->VGAAccess = FALSE;
1397c582b7e3Smrg#else
1398c582b7e3Smrg    info->VGAAccess = TRUE;
1399c582b7e3Smrg#endif
1400c582b7e3Smrg
1401c582b7e3Smrg#ifdef WITH_VGAHW
1402c582b7e3Smrg    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess);
1403c582b7e3Smrg    if (info->VGAAccess) {
1404c582b7e3Smrg       if (!xf86LoadSubModule(pScrn, "vgahw"))
1405c582b7e3Smrg           info->VGAAccess = FALSE;
1406c582b7e3Smrg        else {
1407c582b7e3Smrg            if (!vgaHWGetHWRec(pScrn))
1408c582b7e3Smrg               info->VGAAccess = FALSE;
1409c582b7e3Smrg       }
1410c582b7e3Smrg       if (!info->VGAAccess)
1411c582b7e3Smrg           xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed,"
1412c582b7e3Smrg                      " trying to run without it\n");
1413c582b7e3Smrg    } else
1414c582b7e3Smrg           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE,"
1415c582b7e3Smrg                      " VGA module load skipped\n");
141684354367Smrg    if (info->VGAAccess) {
141784354367Smrg	vgaHWSetStdFuncs(VGAHWPTR(pScrn));
1418c582b7e3Smrg        vgaHWGetIOBase(VGAHWPTR(pScrn));
141984354367Smrg    }
1420c582b7e3Smrg#else
1421c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAHW support not compiled, VGA "
1422c582b7e3Smrg               "module load skipped\n");
1423c582b7e3Smrg#endif
1424c582b7e3Smrg
1425c582b7e3Smrg    if (!R128PreInitWeight(pScrn))    goto fail;
1426c582b7e3Smrg
1427c582b7e3Smrg    if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) {
1428c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1429c582b7e3Smrg                                info->videoKey);
1430c582b7e3Smrg    } else {
1431c582b7e3Smrg        info->videoKey = 0x1E;
1432c582b7e3Smrg    }
1433c582b7e3Smrg
1434c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) {
1435c582b7e3Smrg        info->showCache = TRUE;
1436c582b7e3Smrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
1437c582b7e3Smrg    }
1438c582b7e3Smrg
143979e5230eSmacallan#ifndef AVOID_FBDEV
1440c582b7e3Smrg#ifdef __powerpc__
1441c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE))
1442c582b7e3Smrg#else
1443c582b7e3Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE))
1444c582b7e3Smrg#endif
1445c582b7e3Smrg    {
1446c582b7e3Smrg	info->FBDev = TRUE;
1447c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1448c582b7e3Smrg		   "Using framebuffer device\n");
1449c582b7e3Smrg    }
1450c582b7e3Smrg
1451c582b7e3Smrg    if (info->FBDev) {
1452c582b7e3Smrg	/* check for linux framebuffer device */
1453c582b7e3Smrg	if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE;
1454c582b7e3Smrg	if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE;
1455c582b7e3Smrg	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
1456c582b7e3Smrg	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
1457c582b7e3Smrg	pScrn->ValidMode     = fbdevHWValidModeWeak();
1458c582b7e3Smrg    }
1459c582b7e3Smrg
1460c582b7e3Smrg    if (!info->FBDev)
146179e5230eSmacallan#endif /* !AVOID_FBDEV */
1462b3ff493bSmrg	if (!R128PreInitInt10(pScrn, &pInt10))  goto fail;
1463c582b7e3Smrg
1464b3ff493bSmrg    if (!R128PreInitConfig(pScrn))              goto fail;
1465c582b7e3Smrg
1466b3ff493bSmrg    xf86CrtcSetSizeRange(pScrn, 320, 200, 4096, 4096);
1467c582b7e3Smrg
1468c582b7e3Smrg    /* Don't fail on this one */
1469b3ff493bSmrg    info->DDC = R128PreInitDDC(pScrn, pInt10);
1470c582b7e3Smrg
1471b3ff493bSmrg    if (!R128PreInitControllers(pScrn, pInt10)) goto fail;
1472c582b7e3Smrg
1473b3ff493bSmrg    if (!xf86InitialConfiguration(pScrn, TRUE)) {
1474b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
1475b3ff493bSmrg        goto fail;
1476b3ff493bSmrg    }
1477b3ff493bSmrg    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
1478b3ff493bSmrg
1479b3ff493bSmrg    /* Set display resolution */
1480b3ff493bSmrg    xf86SetDpi(pScrn, 0, 0);
1481b3ff493bSmrg
1482b3ff493bSmrg    /* Get ScreenInit function */
1483b3ff493bSmrg    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
1484b3ff493bSmrg
1485b3ff493bSmrg    if (!R128PreInitGamma(pScrn))              goto fail;
1486c582b7e3Smrg
1487c582b7e3Smrg    if (!R128PreInitCursor(pScrn))             goto fail;
1488c582b7e3Smrg
148984354367Smrg#ifdef R128DRI
1490c582b7e3Smrg    if (!R128PreInitDRI(pScrn))                goto fail;
1491c582b7e3Smrg#endif
1492c582b7e3Smrg
1493b3ff493bSmrg    info->CurrentLayout.displayWidth = pScrn->displayWidth;
1494b3ff493bSmrg
1495b3ff493bSmrg    if (!xf86RandR12PreInit(pScrn)) {
1496b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
1497b3ff493bSmrg        goto fail;
1498b3ff493bSmrg    }
1499b3ff493bSmrg
1500b3ff493bSmrg    if (pScrn->modes == NULL) {
1501b3ff493bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1502b3ff493bSmrg        goto fail;
1503b3ff493bSmrg    }
1504b3ff493bSmrg
1505c582b7e3Smrg				/* Free the video bios (if applicable) */
1506c582b7e3Smrg    if (info->VBIOS) {
150784354367Smrg	free(info->VBIOS);
1508c582b7e3Smrg	info->VBIOS = NULL;
1509c582b7e3Smrg    }
1510c582b7e3Smrg
1511c582b7e3Smrg				/* Free int10 info */
1512c582b7e3Smrg    if (pInt10)
1513c582b7e3Smrg	xf86FreeInt10(pInt10);
1514c582b7e3Smrg
1515b3ff493bSmrg    if (info->MMIO) R128UnmapMMIO(pScrn);
1516b3ff493bSmrg    info->MMIO = NULL;
1517b3ff493bSmrg
1518c582b7e3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
1519c582b7e3Smrg	"For information on using the multimedia capabilities\n\tof this"
1520c582b7e3Smrg	" adapter, please see http://gatos.sf.net.\n");
1521c582b7e3Smrg
1522c582b7e3Smrg    return TRUE;
1523c582b7e3Smrg
1524c582b7e3Smrg  fail:
1525c582b7e3Smrg				/* Pre-init failed. */
1526c582b7e3Smrg
1527c582b7e3Smrg				/* Free the video bios (if applicable) */
1528c582b7e3Smrg    if (info->VBIOS) {
152984354367Smrg	free(info->VBIOS);
1530c582b7e3Smrg	info->VBIOS = NULL;
1531c582b7e3Smrg    }
1532c582b7e3Smrg
1533c582b7e3Smrg				/* Free int10 info */
1534c582b7e3Smrg    if (pInt10)
1535c582b7e3Smrg	xf86FreeInt10(pInt10);
1536c582b7e3Smrg
1537c582b7e3Smrg#ifdef WITH_VGAHW
1538c582b7e3Smrg    if (info->VGAAccess)
1539c582b7e3Smrg           vgaHWFreeHWRec(pScrn);
1540c582b7e3Smrg#endif
1541b3ff493bSmrg
1542b3ff493bSmrg    if (info->MMIO) R128UnmapMMIO(pScrn);
1543b3ff493bSmrg    info->MMIO = NULL;
1544b3ff493bSmrg
1545c582b7e3Smrg    R128FreeRec(pScrn);
1546c582b7e3Smrg    return FALSE;
1547c582b7e3Smrg}
1548c582b7e3Smrg
1549c582b7e3Smrg/* Load a palette. */
1550c582b7e3Smrgstatic void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
1551c582b7e3Smrg			    int *indices, LOCO *colors, VisualPtr pVisual)
1552c582b7e3Smrg{
1553c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
1554b3ff493bSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1555b3ff493bSmrg    int i, j;
1556b3ff493bSmrg    int c, index;
1557b3ff493bSmrg    uint16_t lut_r[256], lut_g[256], lut_b[256];
1558b3ff493bSmrg
1559b3ff493bSmrg    for (c = 0; c < xf86_config->num_crtc; c++) {
1560b3ff493bSmrg        xf86CrtcPtr crtc = xf86_config->crtc[c];
1561b3ff493bSmrg        R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
1562b3ff493bSmrg
1563b3ff493bSmrg        for (i = 0 ; i < 256; i++) {
1564b3ff493bSmrg            lut_r[i] = r128_crtc->lut_r[i] << 8;
1565b3ff493bSmrg            lut_g[i] = r128_crtc->lut_g[i] << 8;
1566b3ff493bSmrg            lut_b[i] = r128_crtc->lut_b[i] << 8;
1567b3ff493bSmrg        }
1568c582b7e3Smrg
1569b3ff493bSmrg        switch (info->CurrentLayout.depth) {
1570b3ff493bSmrg        case 15:
1571b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1572b3ff493bSmrg                index = indices[i];
1573b3ff493bSmrg                for (j = 0; j < 8; j++) {
1574b3ff493bSmrg                    lut_r[index * 8 + j] = colors[index].red << 8;
1575b3ff493bSmrg                    lut_g[index * 8 + j] = colors[index].green << 8;
1576b3ff493bSmrg                    lut_b[index * 8 + j] = colors[index].blue << 8;
1577b3ff493bSmrg                }
1578b3ff493bSmrg            }
1579b3ff493bSmrg        case 16:
1580b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1581b3ff493bSmrg                index = indices[i];
1582b3ff493bSmrg
1583b3ff493bSmrg                /* XXX: The old version of R128LoadPalette did not do this and
1584b3ff493bSmrg                 * the old version of RADEONLoadPalette has a comment asking why.
1585b3ff493bSmrg                 */
1586b3ff493bSmrg                if (i <= 31) {
1587b3ff493bSmrg                    for (j = 0; j < 8; j++) {
1588b3ff493bSmrg                        lut_r[index * 8 + j] = colors[index].red << 8;
1589b3ff493bSmrg                        lut_b[index * 8 + j] = colors[index].blue << 8;
1590b3ff493bSmrg                    }
1591b3ff493bSmrg                }
1592c582b7e3Smrg
1593b3ff493bSmrg                for (j = 0; j < 4; j++) {
1594b3ff493bSmrg                    lut_g[index * 4 + j] = colors[index].green << 8;
1595b3ff493bSmrg                }
1596b3ff493bSmrg            }
1597b3ff493bSmrg        default:
1598b3ff493bSmrg            for (i = 0; i < numColors; i++) {
1599b3ff493bSmrg                index = indices[i];
1600b3ff493bSmrg                lut_r[index] = colors[index].red << 8;
1601b3ff493bSmrg                lut_g[index] = colors[index].green << 8;
1602b3ff493bSmrg                lut_b[index] = colors[index].blue << 8;
1603b3ff493bSmrg            }
1604b3ff493bSmrg            break;
1605b3ff493bSmrg        }
1606c582b7e3Smrg
1607b3ff493bSmrg        /* Make the change through RandR */
1608b3ff493bSmrg#ifdef RANDR_12_INTERFACE
1609b3ff493bSmrg        if (crtc->randr_crtc)
1610b3ff493bSmrg            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1611b3ff493bSmrg        else
1612b3ff493bSmrg#endif
1613b3ff493bSmrg        crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1614c582b7e3Smrg    }
1615c582b7e3Smrg}
1616c582b7e3Smrg
1617c582b7e3Smrgstatic void
161884354367SmrgR128BlockHandler(BLOCKHANDLER_ARGS_DECL)
1619c582b7e3Smrg{
162084354367Smrg    SCREEN_PTR(arg);
162184354367Smrg    ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
1622c582b7e3Smrg    R128InfoPtr info    = R128PTR(pScrn);
1623c582b7e3Smrg
162484354367Smrg#ifdef R128DRI
1625c582b7e3Smrg    if (info->directRenderingEnabled)
1626c582b7e3Smrg        FLUSH_RING();
1627c582b7e3Smrg#endif
1628c582b7e3Smrg
1629c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
163084354367Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1631c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
1632c582b7e3Smrg
1633c582b7e3Smrg    if(info->VideoTimerCallback) {
1634c582b7e3Smrg        (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
1635c582b7e3Smrg    }
1636c582b7e3Smrg}
1637c582b7e3Smrg
163884354367Smrg#ifdef USE_EXA
163984354367SmrgBool R128VerboseInitEXA(ScreenPtr pScreen)
164084354367Smrg{
164184354367Smrg    ScrnInfoPtr pScrn  = xf86ScreenToScrn(pScreen);
164284354367Smrg    R128InfoPtr info   = R128PTR(pScrn);
164384354367Smrg
164484354367Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Going to init EXA...\n");
164584354367Smrg
164684354367Smrg    if (R128EXAInit(pScreen)) {
164784354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled\n");
164884354367Smrg	info->accelOn = TRUE;
164984354367Smrg
165084354367Smrg	return TRUE;
165184354367Smrg    } else {
165284354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
165384354367Smrg		   "EXA Acceleration initialization failed\n");
165484354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration disabled\n");
165584354367Smrg	info->accelOn = FALSE;
165684354367Smrg
165784354367Smrg	return FALSE;
165884354367Smrg    }
165984354367Smrg}
166084354367Smrg#endif
166184354367Smrg
166284354367Smrgvoid R128VerboseInitAccel(Bool noAccel, ScreenPtr pScreen)
166384354367Smrg{
166484354367Smrg    ScrnInfoPtr pScrn  = xf86ScreenToScrn(pScreen);
166584354367Smrg    R128InfoPtr info   = R128PTR(pScrn);
166684354367Smrg
166784354367Smrg    if (!noAccel) {
166884354367Smrg	if (R128AccelInit(pScreen)) {
166984354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration enabled\n");
167084354367Smrg	    info->accelOn = TRUE;
167184354367Smrg	} else {
167284354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
167384354367Smrg		       "Acceleration initialization failed\n");
167484354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
167584354367Smrg	    info->accelOn = FALSE;
167684354367Smrg	}
167784354367Smrg    } else {
167884354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
167984354367Smrg	info->accelOn = FALSE;
168084354367Smrg    }
168184354367Smrg}
168284354367Smrg
1683c582b7e3Smrg/* Called at the start of each server generation. */
168484354367SmrgBool R128ScreenInit(SCREEN_INIT_ARGS_DECL)
1685c582b7e3Smrg{
168684354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1687c582b7e3Smrg    R128InfoPtr info   = R128PTR(pScrn);
1688c582b7e3Smrg    BoxRec      MemBox;
168984354367Smrg    int width_bytes = (pScrn->displayWidth *
169084354367Smrg			   info->CurrentLayout.pixel_bytes);
169184354367Smrg    int         x1 = 0, x2 = 0, y1 = 0, y2 = 0;
169284354367Smrg    Bool	noAccel;
169384354367Smrg#ifdef USE_EXA
169484354367Smrg    ExaOffscreenArea*     osArea = NULL;
169584354367Smrg#else
169684354367Smrg    void*		  osArea = NULL;
169784354367Smrg#endif
169884354367Smrg    char *optstr;
1699c582b7e3Smrg
1700c582b7e3Smrg    R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset));
170184354367Smrg    info->useEXA = FALSE;
170284354367Smrg#ifdef USE_EXA
170384354367Smrg#ifndef HAVE_XAA_H
170484354367Smrg    info->useEXA = TRUE;
170584354367Smrg#endif
170684354367Smrg#endif
170784354367Smrg
170884354367Smrg#ifdef USE_EXA
170984354367Smrg    optstr = (char *)xf86GetOptValString(info->Options, OPTION_ACCELMETHOD);
171084354367Smrg    if (optstr != NULL) {
171184354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AccelMethod option found\n");
171284354367Smrg	if (xf86NameCmp(optstr, "EXA") == 0) {
171384354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AccelMethod is set to EXA, turning EXA on\n");
171484354367Smrg	    info->useEXA = TRUE;
171584354367Smrg	}
171684354367Smrg    }
171784354367Smrg#ifdef RENDER
171884354367Smrg    info->RenderAccel = xf86ReturnOptValBool(info->Options, OPTION_RENDERACCEL, TRUE);
171984354367Smrg    if (info->RenderAccel)
1720a0e1ef58Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration of RENDER operations will be enabled "
172184354367Smrg					     "upon successful loading of DRI and EXA\n");
172284354367Smrg#endif
172384354367Smrg#endif
1724c582b7e3Smrg
172584354367Smrg#ifdef R128DRI
1726c582b7e3Smrg				/* Turn off the CCE for now. */
1727c582b7e3Smrg    info->CCEInUse     = FALSE;
1728c582b7e3Smrg    info->indirectBuffer = NULL;
1729c582b7e3Smrg#endif
1730c582b7e3Smrg
1731c582b7e3Smrg    if (!R128MapMem(pScrn)) return FALSE;
1732c582b7e3Smrg    pScrn->fbOffset    = 0;
1733b3ff493bSmrg    //if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
173484354367Smrg#ifdef R128DRI
1735c582b7e3Smrg    info->fbX          = 0;
1736c582b7e3Smrg    info->fbY          = 0;
1737c582b7e3Smrg    info->frontOffset  = 0;
1738c582b7e3Smrg    info->frontPitch   = pScrn->displayWidth;
1739c582b7e3Smrg#endif
1740c582b7e3Smrg
1741c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
1742c582b7e3Smrg
1743c582b7e3Smrg    R128Save(pScrn);
1744c582b7e3Smrg
1745c582b7e3Smrg				/* Visual setup */
1746c582b7e3Smrg    miClearVisualTypes();
1747c582b7e3Smrg    if (!miSetVisualTypes(pScrn->depth,
1748c582b7e3Smrg			  miGetDefaultVisualMask(pScrn->depth),
1749c582b7e3Smrg			  pScrn->rgbBits,
1750c582b7e3Smrg			  pScrn->defaultVisual)) return FALSE;
1751c582b7e3Smrg    miSetPixmapDepths ();
1752c582b7e3Smrg
175384354367Smrg    noAccel = xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE);
1754b3ff493bSmrg    if (noAccel) info->useEXA = FALSE;
175584354367Smrg
175684354367Smrg#ifdef R128DRI
1757c582b7e3Smrg				/* Setup DRI after visuals have been
1758c582b7e3Smrg				   established, but before fbScreenInit is
1759c582b7e3Smrg				   called.  fbScreenInit will eventually
1760c582b7e3Smrg				   call the driver's InitGLXVisuals call
1761c582b7e3Smrg				   back. */
1762c582b7e3Smrg    {
1763c582b7e3Smrg	/* FIXME: When we move to dynamic allocation of back and depth
1764c582b7e3Smrg	   buffers, we will want to revisit the following check for 3
1765c582b7e3Smrg	   times the virtual size of the screen below. */
1766c582b7e3Smrg	int maxy        = info->FbMapSize / width_bytes;
1767c582b7e3Smrg
176884354367Smrg	if (noAccel) {
176984354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1770c582b7e3Smrg		       "Acceleration disabled, not initializing the DRI\n");
1771c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
1772c582b7e3Smrg	} else if (maxy <= pScrn->virtualY * 3) {
177384354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1774c582b7e3Smrg		       "Static buffer allocation failed -- "
1775c582b7e3Smrg		       "need at least %d kB video memory\n",
1776c582b7e3Smrg		       (pScrn->displayWidth * pScrn->virtualY *
1777c582b7e3Smrg			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
1778c582b7e3Smrg	    info->directRenderingEnabled = FALSE;
1779c582b7e3Smrg	} else {
1780b3ff493bSmrg            info->directRenderingEnabled = R128DRIScreenInit(pScreen);
1781c582b7e3Smrg	}
1782c582b7e3Smrg    }
1783c582b7e3Smrg#endif
1784c582b7e3Smrg
1785c582b7e3Smrg    if (!fbScreenInit (pScreen, info->FB,
1786c582b7e3Smrg		       pScrn->virtualX, pScrn->virtualY,
1787c582b7e3Smrg		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1788c582b7e3Smrg		       pScrn->bitsPerPixel))
1789c582b7e3Smrg	return FALSE;
1790c582b7e3Smrg
1791c582b7e3Smrg    xf86SetBlackWhitePixels(pScreen);
1792c582b7e3Smrg
1793c582b7e3Smrg    if (pScrn->bitsPerPixel > 8) {
1794c582b7e3Smrg	VisualPtr visual;
1795c582b7e3Smrg
1796c582b7e3Smrg	visual = pScreen->visuals + pScreen->numVisuals;
1797c582b7e3Smrg	while (--visual >= pScreen->visuals) {
1798c582b7e3Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
1799c582b7e3Smrg		visual->offsetRed   = pScrn->offset.red;
1800c582b7e3Smrg		visual->offsetGreen = pScrn->offset.green;
1801c582b7e3Smrg		visual->offsetBlue  = pScrn->offset.blue;
1802c582b7e3Smrg		visual->redMask     = pScrn->mask.red;
1803c582b7e3Smrg		visual->greenMask   = pScrn->mask.green;
1804c582b7e3Smrg		visual->blueMask    = pScrn->mask.blue;
1805c582b7e3Smrg	    }
1806c582b7e3Smrg	}
1807c582b7e3Smrg    }
1808c582b7e3Smrg
1809c582b7e3Smrg    /* must be after RGB order fixed */
1810c582b7e3Smrg    fbPictureInit (pScreen, 0, 0);
1811c582b7e3Smrg
1812c582b7e3Smrg				/* Memory manager setup */
181384354367Smrg#ifdef R128DRI
1814c582b7e3Smrg    if (info->directRenderingEnabled) {
181584354367Smrg	FBAreaPtr fbarea = NULL;
1816c582b7e3Smrg	int cpp = info->CurrentLayout.pixel_bytes;
1817c582b7e3Smrg	int bufferSize = pScrn->virtualY * width_bytes;
1818c582b7e3Smrg	int l, total;
1819c582b7e3Smrg	int scanlines;
1820c582b7e3Smrg
1821c582b7e3Smrg	switch (info->CCEMode) {
1822c582b7e3Smrg	case R128_DEFAULT_CCE_PIO_MODE:
1823c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
1824c582b7e3Smrg	    break;
1825c582b7e3Smrg	case R128_DEFAULT_CCE_BM_MODE:
1826c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
1827c582b7e3Smrg	    break;
1828c582b7e3Smrg	default:
1829c582b7e3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
1830c582b7e3Smrg	    break;
1831c582b7e3Smrg	}
1832c582b7e3Smrg
1833c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1834c582b7e3Smrg		   "Using %d MB AGP aperture\n", info->agpSize);
1835c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1836c582b7e3Smrg		   "Using %d MB for the ring buffer\n", info->ringSize);
1837c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1838c582b7e3Smrg		   "Using %d MB for vertex/indirect buffers\n", info->bufSize);
1839c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1840c582b7e3Smrg		   "Using %d MB for AGP textures\n", info->agpTexSize);
1841c582b7e3Smrg
1842c582b7e3Smrg	/* Try for front, back, depth, and two framebuffers worth of
1843c582b7e3Smrg	 * pixmap cache.  Should be enough for a fullscreen background
1844c582b7e3Smrg	 * image plus some leftovers.
1845c582b7e3Smrg	 */
1846c582b7e3Smrg	info->textureSize = info->FbMapSize - 5 * bufferSize;
1847c582b7e3Smrg
1848c582b7e3Smrg	/* If that gives us less than half the available memory, let's
1849c582b7e3Smrg	 * be greedy and grab some more.  Sorry, I care more about 3D
1850c582b7e3Smrg	 * performance than playing nicely, and you'll get around a full
1851c582b7e3Smrg	 * framebuffer's worth of pixmap cache anyway.
1852c582b7e3Smrg	 */
1853c582b7e3Smrg	if (info->textureSize < (int)info->FbMapSize / 2) {
1854c582b7e3Smrg	    info->textureSize = info->FbMapSize - 4 * bufferSize;
1855c582b7e3Smrg	}
1856c582b7e3Smrg
1857c582b7e3Smrg	if (info->textureSize > 0) {
1858c582b7e3Smrg	    l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
1859c582b7e3Smrg	    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
1860c582b7e3Smrg
1861c582b7e3Smrg	    /* Round the texture size up to the nearest whole number of
1862c582b7e3Smrg	     * texture regions.  Again, be greedy about this, don't
1863c582b7e3Smrg	     * round down.
1864c582b7e3Smrg	     */
1865c582b7e3Smrg	    info->log2TexGran = l;
1866c582b7e3Smrg	    info->textureSize = (info->textureSize >> l) << l;
1867c582b7e3Smrg	} else {
1868c582b7e3Smrg	    info->textureSize = 0;
1869c582b7e3Smrg	}
1870c582b7e3Smrg
1871c582b7e3Smrg	/* Set a minimum usable local texture heap size.  This will fit
1872c582b7e3Smrg	 * two 256x256x32bpp textures.
1873c582b7e3Smrg	 */
1874c582b7e3Smrg	if (info->textureSize < 512 * 1024) {
1875c582b7e3Smrg	    info->textureOffset = 0;
1876c582b7e3Smrg	    info->textureSize = 0;
1877c582b7e3Smrg	}
1878c582b7e3Smrg
1879c582b7e3Smrg	total = info->FbMapSize - info->textureSize;
1880c582b7e3Smrg	scanlines = total / width_bytes;
1881c582b7e3Smrg	if (scanlines > 8191) scanlines = 8191;
1882c582b7e3Smrg
1883c582b7e3Smrg	/* Recalculate the texture offset and size to accomodate any
1884c582b7e3Smrg	 * rounding to a whole number of scanlines.
1885c582b7e3Smrg	 */
1886c582b7e3Smrg	info->textureOffset = scanlines * width_bytes;
1887c582b7e3Smrg
1888c582b7e3Smrg	MemBox.x1 = 0;
1889c582b7e3Smrg	MemBox.y1 = 0;
1890c582b7e3Smrg	MemBox.x2 = pScrn->displayWidth;
1891c582b7e3Smrg	MemBox.y2 = scanlines;
1892c582b7e3Smrg
189384354367Smrg	if (!info->useEXA) {
189484354367Smrg	    if (!xf86InitFBManager(pScreen, &MemBox)) {
189584354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
189684354367Smrg		           "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
189784354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
189884354367Smrg	        return FALSE;
1899c582b7e3Smrg	    } else {
190084354367Smrg	        int width, height;
190184354367Smrg
190284354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
190384354367Smrg		           "Memory manager initialized to (%d,%d) (%d,%d)\n",
190484354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
190584354367Smrg	        if ((fbarea = xf86AllocateOffscreenArea(pScreen,
190684354367Smrg						        pScrn->displayWidth,
190784354367Smrg						        2, 0, NULL, NULL, NULL))) {
190884354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
190984354367Smrg			       "Reserved area from (%d,%d) to (%d,%d)\n",
191084354367Smrg			       fbarea->box.x1, fbarea->box.y1,
191184354367Smrg			       fbarea->box.x2, fbarea->box.y2);
191284354367Smrg	        } else {
191384354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve area\n");
191484354367Smrg	        }
191584354367Smrg	        if (xf86QueryLargestOffscreenArea(pScreen, &width,
191684354367Smrg						  &height, 0, 0, 0)) {
191784354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
191884354367Smrg			       "Largest offscreen area available: %d x %d\n",
191984354367Smrg				width, height);
192084354367Smrg	        }
192184354367Smrg
192284354367Smrg		R128VerboseInitAccel(noAccel, pScreen);
1923c582b7e3Smrg	    }
1924c582b7e3Smrg	}
192584354367Smrg#ifdef USE_EXA
192684354367Smrg	else {
192784354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
192884354367Smrg		       "Filling in EXA memory info\n");
192984354367Smrg
193084354367Smrg	    R128VerboseInitAccel(noAccel, pScreen);
193184354367Smrg	    info->ExaDriver->offScreenBase = pScrn->virtualY * width_bytes;
193284354367Smrg
193384354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
193484354367Smrg		       "Filled in offs\n");
193584354367Smrg
193684354367Smrg	    /* Don't give EXA the true full memory size, because the
193784354367Smrg	       textureSize sized chunk on the end is handled by DRI */
193884354367Smrg	    info->ExaDriver->memorySize = total;
193984354367Smrg
194084354367Smrg	    R128VerboseInitEXA(pScreen);
194184354367Smrg	}
194284354367Smrg#endif
1943c582b7e3Smrg
1944c582b7e3Smrg				/* Allocate the shared back buffer */
194584354367Smrg	if(!info->useEXA) {
194684354367Smrg	    fbarea = xf86AllocateOffscreenArea(pScreen,
194784354367Smrg					       pScrn->virtualX,
194884354367Smrg					       pScrn->virtualY,
194984354367Smrg					       32, NULL, NULL, NULL);
195084354367Smrg
195184354367Smrg	    if (fbarea) {
195284354367Smrg		x1 = fbarea->box.x1;
195384354367Smrg		x2 = fbarea->box.x2;
195484354367Smrg		y1 = fbarea->box.y1;
195584354367Smrg		y2 = fbarea->box.y2;
195684354367Smrg	    }
195784354367Smrg	}
195884354367Smrg#ifdef USE_EXA
195984354367Smrg	else {
196084354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
196184354367Smrg		       "Actually trying an EXA allocation...\n");
196284354367Smrg	    osArea = exaOffscreenAlloc(pScreen,
196384354367Smrg				       pScrn->virtualY * width_bytes,
196484354367Smrg				       32, TRUE, NULL, NULL);
196584354367Smrg
196684354367Smrg	    if (osArea) {
196784354367Smrg		x1 = osArea->offset % width_bytes;
196884354367Smrg		x2 = (osArea->offset + osArea->size) % width_bytes;
196984354367Smrg		y1 = osArea->offset / width_bytes;
197084354367Smrg		y2 = (osArea->offset + osArea->size) / width_bytes;
197184354367Smrg
197284354367Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Went swimmingly...\n");
197384354367Smrg	    }
197484354367Smrg	}
197584354367Smrg#endif
197684354367Smrg
197784354367Smrg	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
197884354367Smrg	    /* info->backOffset = y1 * width_bytes + x1 * cpp; */
197984354367Smrg	    info->backOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
198084354367Smrg	    info->backX = info->backOffset % width_bytes;
198184354367Smrg	    info->backY = info->backOffset / width_bytes;
1982c582b7e3Smrg	    info->backPitch = pScrn->displayWidth;
198384354367Smrg
198484354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
198584354367Smrg		       "Reserved back buffer from (%d,%d) to (%d,%d) offset: %x\n",
198684354367Smrg		       x1, y1,
198784354367Smrg		       x2, y2, info->backOffset);
1988c582b7e3Smrg	} else {
198984354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
1990c582b7e3Smrg	    info->backX = -1;
1991c582b7e3Smrg	    info->backY = -1;
1992c582b7e3Smrg	    info->backOffset = -1;
1993c582b7e3Smrg	    info->backPitch = -1;
1994c582b7e3Smrg	}
1995c582b7e3Smrg
1996c582b7e3Smrg				/* Allocate the shared depth buffer */
199784354367Smrg	if(!info->useEXA) {
199884354367Smrg	    fbarea = xf86AllocateOffscreenArea(pScreen,
199984354367Smrg					       pScrn->virtualX,
200084354367Smrg					       pScrn->virtualY + 1,
200184354367Smrg					       32, NULL, NULL, NULL);
200284354367Smrg	    if (fbarea) {
200384354367Smrg		x1 = fbarea->box.x1;
200484354367Smrg		x2 = fbarea->box.x2;
200584354367Smrg		y1 = fbarea->box.y1;
200684354367Smrg		y2 = fbarea->box.y2;
200784354367Smrg	    }
200884354367Smrg	}
200984354367Smrg#ifdef USE_EXA
201084354367Smrg	else {
201184354367Smrg	    osArea = exaOffscreenAlloc(pScreen,
201284354367Smrg				       (pScrn->virtualY + 1) * width_bytes,
201384354367Smrg				       32, TRUE, NULL, NULL);
201484354367Smrg
201584354367Smrg	    if (osArea) {
201684354367Smrg		x1 = osArea->offset % width_bytes;
201784354367Smrg		x2 = (osArea->offset + osArea->size) % width_bytes;
201884354367Smrg		y1 = osArea->offset / width_bytes;
201984354367Smrg		y2 = (osArea->offset + osArea->size) / width_bytes;
202084354367Smrg	    }
202184354367Smrg	}
202284354367Smrg#endif
202384354367Smrg
202484354367Smrg	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
202584354367Smrg	    /* info->depthOffset = y1 * width_bytes + x1 * cpp; */
202684354367Smrg	    info->depthOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
202784354367Smrg	    info->depthX = info->depthOffset % width_bytes;
202884354367Smrg	    info->depthY = info->depthOffset / width_bytes;
2029c582b7e3Smrg	    info->depthPitch = pScrn->displayWidth;
203084354367Smrg	    info->spanOffset = (y2 - 1) * width_bytes + x1 * cpp;
203184354367Smrg
203284354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
203384354367Smrg		       "Reserved depth buffer from (%d,%d) to (%d,%d) offset: %x\n",
203484354367Smrg		       x1, y1,
203584354367Smrg		       x2, y2, info->depthOffset);
203684354367Smrg
203784354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2038c582b7e3Smrg		       "Reserved depth span from (%d,%d) offset 0x%x\n",
203984354367Smrg		       x1, y2 - 1, info->spanOffset);
2040c582b7e3Smrg	} else {
204184354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
2042c582b7e3Smrg	    info->depthX = -1;
2043c582b7e3Smrg	    info->depthY = -1;
2044c582b7e3Smrg	    info->depthOffset = -1;
2045c582b7e3Smrg	    info->depthPitch = -1;
2046c582b7e3Smrg	    info->spanOffset = -1;
2047c582b7e3Smrg	}
2048c582b7e3Smrg
204984354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2050c582b7e3Smrg		   "Reserved %d kb for textures at offset 0x%x\n",
2051c582b7e3Smrg		   info->textureSize/1024, info->textureOffset);
2052c582b7e3Smrg    }
2053c582b7e3Smrg    else
205484354367Smrg#endif /* R128DRI */
2055c582b7e3Smrg    {
2056c582b7e3Smrg	MemBox.x1 = 0;
2057c582b7e3Smrg	MemBox.y1 = 0;
2058c582b7e3Smrg	MemBox.x2 = pScrn->displayWidth;
2059c582b7e3Smrg	y2        = (info->FbMapSize
2060c582b7e3Smrg		     / (pScrn->displayWidth *
2061c582b7e3Smrg			info->CurrentLayout.pixel_bytes));
2062c582b7e3Smrg				/* The acceleration engine uses 14 bit
2063c582b7e3Smrg				   signed coordinates, so we can't have any
2064c582b7e3Smrg				   drawable caches beyond this region. */
2065c582b7e3Smrg	if (y2 > 8191) y2 = 8191;
2066c582b7e3Smrg	MemBox.y2 = y2;
2067c582b7e3Smrg
206884354367Smrg	if (!info->useEXA) {
206984354367Smrg	    if (!xf86InitFBManager(pScreen, &MemBox)) {
207084354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
207184354367Smrg		           "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
207284354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
207384354367Smrg	        return FALSE;
2074c582b7e3Smrg	    } else {
207584354367Smrg	        int       width, height;
207684354367Smrg	        FBAreaPtr fbarea;
207784354367Smrg
207884354367Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
207984354367Smrg		           "Memory manager initialized to (%d,%d) (%d,%d)\n",
208084354367Smrg		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
208184354367Smrg	        if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth, 2, 0, NULL, NULL, NULL))) {
208284354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
208384354367Smrg			       "Reserved area from (%d,%d) to (%d,%d)\n",
208484354367Smrg			       fbarea->box.x1, fbarea->box.y1,
208584354367Smrg			       fbarea->box.x2, fbarea->box.y2);
208684354367Smrg	        } else {
208784354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve area\n");
208884354367Smrg	        }
208984354367Smrg	        if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) {
209084354367Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
209184354367Smrg			       "Largest offscreen area available: %d x %d\n",
209284354367Smrg				width, height);
209384354367Smrg	        }
209484354367Smrg
209584354367Smrg		R128VerboseInitAccel(noAccel, pScreen);
2096c582b7e3Smrg	    }
2097c582b7e3Smrg	}
209884354367Smrg#ifdef USE_EXA
209984354367Smrg	else {
210084354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
210184354367Smrg		       "Filling in EXA memory info\n");
2102c582b7e3Smrg
210384354367Smrg	    R128VerboseInitAccel(noAccel, pScreen);
210484354367Smrg	    info->ExaDriver->offScreenBase = pScrn->virtualY * width_bytes;
210584354367Smrg
210684354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
210784354367Smrg		       "Filled in offs\n");
210884354367Smrg
210984354367Smrg	    info->ExaDriver->memorySize = info->FbMapSize;
211084354367Smrg	    R128VerboseInitEXA(pScreen);
2111c582b7e3Smrg	}
211284354367Smrg#endif
2113c582b7e3Smrg    }
2114c582b7e3Smrg
2115b3ff493bSmrg    pScrn->vtSema = TRUE;
2116b3ff493bSmrg    /* xf86CrtcRotate accesses pScrn->pScreen */
2117b3ff493bSmrg    pScrn->pScreen = pScreen;
2118b3ff493bSmrg
21193c921f55Smrg#ifndef AVOID_FBDEV
2120b3ff493bSmrg    if (info->FBDev) {
2121b3ff493bSmrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
2122b3ff493bSmrg    } else {
21233c921f55Smrg#endif
2124b3ff493bSmrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
21253c921f55Smrg#ifndef AVOID_FBDEV
2126b3ff493bSmrg    }
21273c921f55Smrg#endif
2128b3ff493bSmrg
2129b3ff493bSmrg    R128SaveScreen(pScreen, SCREEN_SAVER_ON);
2130b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2131b3ff493bSmrg
2132c582b7e3Smrg				/* DGA setup */
2133b3ff493bSmrg#ifdef XFreeXDGA
2134b3ff493bSmrg    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
2135b3ff493bSmrg#endif
2136c582b7e3Smrg
2137c582b7e3Smrg				/* Backing store setup */
2138c582b7e3Smrg    xf86SetBackingStore(pScreen);
2139c582b7e3Smrg
2140c582b7e3Smrg				/* Set Silken Mouse */
2141c582b7e3Smrg    xf86SetSilkenMouse(pScreen);
2142c582b7e3Smrg
2143c582b7e3Smrg				/* Cursor setup */
2144c582b7e3Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2145c582b7e3Smrg
2146c582b7e3Smrg				/* Hardware cursor setup */
2147c582b7e3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
2148c582b7e3Smrg	if (R128CursorInit(pScreen)) {
2149c582b7e3Smrg	    int width, height;
2150c582b7e3Smrg
2151c582b7e3Smrg	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2152c582b7e3Smrg					      0, 0, 0)) {
215384354367Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2154c582b7e3Smrg			   "Largest offscreen area available: %d x %d\n",
2155c582b7e3Smrg			   width, height);
2156c582b7e3Smrg	    }
2157c582b7e3Smrg	} else {
215884354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2159c582b7e3Smrg		       "Hardware cursor initialization failed\n");
216084354367Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2161c582b7e3Smrg	}
2162c582b7e3Smrg    } else {
216384354367Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2164c582b7e3Smrg    }
2165c582b7e3Smrg
2166c582b7e3Smrg    /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
216779e5230eSmacallan#ifndef AVOID_FBDEV
2168c582b7e3Smrg    if (info->FBDev)
2169c582b7e3Smrg	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
2170b3ff493bSmrg    else
217179e5230eSmacallan#endif
21723c921f55Smrg        xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2173c582b7e3Smrg
21743c921f55Smrg    R128InitVideo(pScreen);
2175c582b7e3Smrg
2176c582b7e3Smrg				/* Provide SaveScreen */
2177c582b7e3Smrg    pScreen->SaveScreen  = R128SaveScreen;
2178c582b7e3Smrg
2179c582b7e3Smrg				/* Wrap CloseScreen */
2180c582b7e3Smrg    info->CloseScreen    = pScreen->CloseScreen;
2181c582b7e3Smrg    pScreen->CloseScreen = R128CloseScreen;
2182c582b7e3Smrg
2183c582b7e3Smrg				/* Note unused options */
2184c582b7e3Smrg    if (serverGeneration == 1)
2185c582b7e3Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2186c582b7e3Smrg
218784354367Smrg#ifdef R128DRI
2188c582b7e3Smrg				/* DRI finalization */
2189c582b7e3Smrg    if (info->directRenderingEnabled) {
2190c582b7e3Smrg				/* Now that mi, fb, drm and others have
2191c582b7e3Smrg				   done their thing, complete the DRI
2192c582b7e3Smrg				   setup. */
2193c582b7e3Smrg	info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
2194c582b7e3Smrg    }
2195c582b7e3Smrg    if (info->directRenderingEnabled) {
2196c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2197c582b7e3Smrg    } else {
2198c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2199c582b7e3Smrg		   "Direct rendering disabled\n");
2200c582b7e3Smrg    }
2201c582b7e3Smrg#endif
2202c582b7e3Smrg
2203c582b7e3Smrg    info->BlockHandler = pScreen->BlockHandler;
2204c582b7e3Smrg    pScreen->BlockHandler = R128BlockHandler;
2205c582b7e3Smrg
2206b3ff493bSmrg    if (!xf86CrtcScreenInit(pScreen)) return FALSE;
2207b3ff493bSmrg
2208b3ff493bSmrg				/* Colormap setup */
2209b3ff493bSmrg    if (!miCreateDefColormap(pScreen)) return FALSE;
2210b3ff493bSmrg    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
2211b3ff493bSmrg			     (
2212b3ff493bSmrg#ifndef AVOID_FBDEV
2213b3ff493bSmrg			     info->FBDev ? fbdevHWLoadPaletteWeak() :
2214b3ff493bSmrg#endif
2215b3ff493bSmrg			     R128LoadPalette), NULL,
2216b3ff493bSmrg			     CMAP_PALETTED_TRUECOLOR
2217b3ff493bSmrg			     | CMAP_RELOAD_ON_MODE_SWITCH
2218b3ff493bSmrg#if 0 /* This option messes up text mode! (eich@suse.de) */
2219b3ff493bSmrg			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
2220b3ff493bSmrg#endif
2221b3ff493bSmrg			     )) return FALSE;
2222b3ff493bSmrg
2223c582b7e3Smrg    return TRUE;
2224c582b7e3Smrg}
2225c582b7e3Smrg
2226c582b7e3Smrg/* Write common registers (initialized to 0). */
2227b3ff493bSmrgvoid R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2228c582b7e3Smrg{
2229c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2230c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2231c582b7e3Smrg
2232c582b7e3Smrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
2233c582b7e3Smrg
2234c582b7e3Smrg    OUTREG(R128_OVR_CLR,              restore->ovr_clr);
2235c582b7e3Smrg    OUTREG(R128_OVR_WID_LEFT_RIGHT,   restore->ovr_wid_left_right);
2236c582b7e3Smrg    OUTREG(R128_OVR_WID_TOP_BOTTOM,   restore->ovr_wid_top_bottom);
2237c582b7e3Smrg    OUTREG(R128_OV0_SCALE_CNTL,       restore->ov0_scale_cntl);
2238c582b7e3Smrg    OUTREG(R128_MPP_TB_CONFIG,        restore->mpp_tb_config );
2239c582b7e3Smrg    OUTREG(R128_MPP_GP_CONFIG,        restore->mpp_gp_config );
2240c582b7e3Smrg    OUTREG(R128_SUBPIC_CNTL,          restore->subpic_cntl);
2241c582b7e3Smrg    OUTREG(R128_VIPH_CONTROL,         restore->viph_control);
2242c582b7e3Smrg    OUTREG(R128_I2C_CNTL_1,           restore->i2c_cntl_1);
2243c582b7e3Smrg    OUTREG(R128_GEN_INT_CNTL,         restore->gen_int_cntl);
2244c582b7e3Smrg    OUTREG(R128_CAP0_TRIG_CNTL,       restore->cap0_trig_cntl);
2245c582b7e3Smrg    OUTREG(R128_CAP1_TRIG_CNTL,       restore->cap1_trig_cntl);
2246c582b7e3Smrg    OUTREG(R128_BUS_CNTL,             restore->bus_cntl);
2247c582b7e3Smrg    OUTREG(R128_CONFIG_CNTL,          restore->config_cntl);
2248c582b7e3Smrg}
2249c582b7e3Smrg
2250c582b7e3Smrg/* Write CRTC registers. */
2251b3ff493bSmrgvoid R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2252c582b7e3Smrg{
2253c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2254c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2255c582b7e3Smrg
2256c582b7e3Smrg    OUTREG(R128_CRTC_GEN_CNTL,        restore->crtc_gen_cntl);
2257c582b7e3Smrg
2258c582b7e3Smrg    OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl,
2259c582b7e3Smrg	    R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS);
2260c582b7e3Smrg
2261c582b7e3Smrg    OUTREG(R128_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
2262c582b7e3Smrg    OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
2263c582b7e3Smrg    OUTREG(R128_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
2264c582b7e3Smrg    OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
2265c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET,          restore->crtc_offset);
2266c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
2267c582b7e3Smrg    OUTREG(R128_CRTC_PITCH,           restore->crtc_pitch);
2268c582b7e3Smrg}
2269c582b7e3Smrg
2270c582b7e3Smrg/* Write CRTC2 registers. */
2271b3ff493bSmrgvoid R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2272c582b7e3Smrg{
2273c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2274c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2275c582b7e3Smrg
2276c582b7e3Smrg    OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl,
2277c582b7e3Smrg	    R128_CRTC2_DISP_DIS);
2278c582b7e3Smrg
2279c582b7e3Smrg    OUTREG(R128_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
2280c582b7e3Smrg    OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
2281c582b7e3Smrg    OUTREG(R128_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
2282c582b7e3Smrg    OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
2283c582b7e3Smrg    OUTREG(R128_CRTC2_OFFSET,          restore->crtc2_offset);
2284c582b7e3Smrg    OUTREG(R128_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
2285c582b7e3Smrg    OUTREG(R128_CRTC2_PITCH,           restore->crtc2_pitch);
2286c582b7e3Smrg}
2287c582b7e3Smrg
2288b3ff493bSmrg/* Write DAC registers */
2289b3ff493bSmrgvoid R128RestoreDACRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2290b3ff493bSmrg{
2291b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2292b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2293b3ff493bSmrg
2294b3ff493bSmrg    OUTREGP(R128_DAC_CNTL, restore->dac_cntl,
2295b3ff493bSmrg	    R128_DAC_RANGE_CNTL | R128_DAC_BLANKING);
2296b3ff493bSmrg}
2297b3ff493bSmrg
2298b3ff493bSmrg/* Write RMX registers */
2299b3ff493bSmrgvoid R128RestoreRMXRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2300c582b7e3Smrg{
2301c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2302c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2303c582b7e3Smrg
2304c582b7e3Smrg    OUTREG(R128_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
2305c582b7e3Smrg    OUTREG(R128_FP_VERT_STRETCH,      restore->fp_vert_stretch);
2306c582b7e3Smrg    OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
2307c582b7e3Smrg    OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
2308c582b7e3Smrg    OUTREG(R128_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
2309c582b7e3Smrg    OUTREG(R128_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
2310b3ff493bSmrg}
2311b3ff493bSmrg
2312b3ff493bSmrg/* Write flat panel registers */
2313b3ff493bSmrgvoid R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2314b3ff493bSmrg{
2315b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2316b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2317b3ff493bSmrg
2318b3ff493bSmrg    OUTREG(R128_TMDS_CRC,              restore->tmds_crc);
2319b3ff493bSmrg    OUTREG(R128_TMDS_TRANSMITTER_CNTL, restore->tmds_transmitter_cntl);
2320b3ff493bSmrg    OUTREG(R128_FP_PANEL_CNTL,         restore->fp_panel_cntl);
2321b3ff493bSmrg    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(uint32_t)R128_FP_BLANK_DIS);
2322b3ff493bSmrg}
2323b3ff493bSmrg
2324b3ff493bSmrg/* Write LVDS registers */
2325b3ff493bSmrgvoid R128RestoreLVDSRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2326b3ff493bSmrg{
2327b3ff493bSmrg    R128InfoPtr   info      = R128PTR(pScrn);
2328b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2329b3ff493bSmrg    unsigned char *R128MMIO = info->MMIO;
2330b3ff493bSmrg    uint32_t      tmp;
2331c582b7e3Smrg
2332b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2333b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2334c582b7e3Smrg
2335c582b7e3Smrg    tmp = INREG(R128_LVDS_GEN_CNTL);
2336c582b7e3Smrg    if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
2337c582b7e3Smrg	(restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
2338c582b7e3Smrg	OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2339c582b7e3Smrg    } else {
2340c582b7e3Smrg	if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
2341c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL,
2342b3ff493bSmrg		   restore->lvds_gen_cntl & (uint32_t)~R128_LVDS_BLON);
2343b3ff493bSmrg	    usleep(r128_output->PanelPwrDly * 1000);
2344c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2345c582b7e3Smrg	} else {
2346c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
2347b3ff493bSmrg	    usleep(r128_output->PanelPwrDly * 1000);
2348c582b7e3Smrg	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2349c582b7e3Smrg	}
2350c582b7e3Smrg    }
2351c582b7e3Smrg}
2352c582b7e3Smrg
2353c582b7e3Smrgstatic void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2354c582b7e3Smrg{
2355c582b7e3Smrg    while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
2356c582b7e3Smrg}
2357c582b7e3Smrg
2358c582b7e3Smrgstatic void R128PLLWriteUpdate(ScrnInfoPtr pScrn)
2359c582b7e3Smrg{
2360c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2361c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2362c582b7e3Smrg
2363c582b7e3Smrg    while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
2364c582b7e3Smrg
2365c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W,
2366c582b7e3Smrg	    ~R128_PPLL_ATOMIC_UPDATE_W);
2367c582b7e3Smrg
2368c582b7e3Smrg}
2369c582b7e3Smrg
2370c582b7e3Smrgstatic void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2371c582b7e3Smrg{
2372c582b7e3Smrg    while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
2373c582b7e3Smrg}
2374c582b7e3Smrg
2375c582b7e3Smrgstatic void R128PLL2WriteUpdate(ScrnInfoPtr pScrn)
2376c582b7e3Smrg{
2377c582b7e3Smrg    R128InfoPtr  info       = R128PTR(pScrn);
2378c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2379c582b7e3Smrg
2380c582b7e3Smrg    while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
2381c582b7e3Smrg
2382c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_REF_DIV,
2383c582b7e3Smrg	    R128_P2PLL_ATOMIC_UPDATE_W,
2384c582b7e3Smrg	    ~(R128_P2PLL_ATOMIC_UPDATE_W));
2385c582b7e3Smrg}
2386c582b7e3Smrg
2387c582b7e3Smrg/* Write PLL registers. */
2388b3ff493bSmrgvoid R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2389c582b7e3Smrg{
2390c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2391c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2392c582b7e3Smrg
2393c582b7e3Smrg
2394c582b7e3Smrg    OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
2395c582b7e3Smrg	    R128_VCLK_SRC_SEL_CPUCLK,
2396c582b7e3Smrg	    ~(R128_VCLK_SRC_SEL_MASK));
2397c582b7e3Smrg
2398c582b7e3Smrg    OUTPLLP(pScrn,
2399c582b7e3Smrg	    R128_PPLL_CNTL,
2400c582b7e3Smrg	    R128_PPLL_RESET
2401c582b7e3Smrg	    | R128_PPLL_ATOMIC_UPDATE_EN
2402c582b7e3Smrg	    | R128_PPLL_VGA_ATOMIC_UPDATE_EN,
2403c582b7e3Smrg	    ~(R128_PPLL_RESET
2404c582b7e3Smrg	      | R128_PPLL_ATOMIC_UPDATE_EN
2405c582b7e3Smrg	      | R128_PPLL_VGA_ATOMIC_UPDATE_EN));
2406c582b7e3Smrg
2407c582b7e3Smrg    OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL));
2408c582b7e3Smrg
2409c582b7e3Smrg/*        R128PLLWaitForReadUpdateComplete(pScrn);*/
2410c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_REF_DIV,
2411c582b7e3Smrg	    restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK);
2412c582b7e3Smrg/*        R128PLLWriteUpdate(pScrn);
2413c582b7e3Smrg
2414c582b7e3Smrg        R128PLLWaitForReadUpdateComplete(pScrn);*/
2415c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_DIV_3,
2416c582b7e3Smrg	    restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK);
2417c582b7e3Smrg/*    R128PLLWriteUpdate(pScrn);*/
2418c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_DIV_3,
2419c582b7e3Smrg	    restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK);
2420c582b7e3Smrg
2421c582b7e3Smrg    R128PLLWriteUpdate(pScrn);
2422c582b7e3Smrg    R128PLLWaitForReadUpdateComplete(pScrn);
2423c582b7e3Smrg
24249e881af1Smacallan    OUTPLLP(pScrn, R128_PPLL_DIV_0,
24259e881af1Smacallan	    restore->ppll_div_0, ~R128_PPLL_FB0_DIV_MASK);
24269e881af1Smacallan/*    R128PLLWriteUpdate(pScrn);*/
24279e881af1Smacallan    OUTPLLP(pScrn, R128_PPLL_DIV_0,
24289e881af1Smacallan	    restore->ppll_div_0, ~R128_PPLL_POST0_DIV_MASK);
24299e881af1Smacallan
24309e881af1Smacallan    R128PLLWriteUpdate(pScrn);
24319e881af1Smacallan    R128PLLWaitForReadUpdateComplete(pScrn);
24329e881af1Smacallan
2433c582b7e3Smrg    OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl);
2434c582b7e3Smrg/*    R128PLLWriteUpdate(pScrn);*/
2435c582b7e3Smrg
2436c582b7e3Smrg    OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET
2437c582b7e3Smrg					| R128_PPLL_SLEEP
2438c582b7e3Smrg					| R128_PPLL_ATOMIC_UPDATE_EN
2439c582b7e3Smrg					| R128_PPLL_VGA_ATOMIC_UPDATE_EN));
2440c582b7e3Smrg
2441c582b7e3Smrg    R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
2442c582b7e3Smrg	       restore->ppll_ref_div,
2443c582b7e3Smrg	       restore->ppll_div_3,
2444c582b7e3Smrg	       restore->htotal_cntl,
2445c582b7e3Smrg	       INPLL(pScrn, R128_PPLL_CNTL)));
2446c582b7e3Smrg    R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
2447c582b7e3Smrg	       restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
2448c582b7e3Smrg	       restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
2449c582b7e3Smrg	       (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
2450c582b7e3Smrg
2451c582b7e3Smrg    usleep(5000); /* let the clock lock */
2452c582b7e3Smrg
2453c582b7e3Smrg    OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
2454c582b7e3Smrg	    R128_VCLK_SRC_SEL_PPLLCLK,
2455c582b7e3Smrg	    ~(R128_VCLK_SRC_SEL_MASK));
2456c582b7e3Smrg
2457c582b7e3Smrg}
2458c582b7e3Smrg
2459c582b7e3Smrg/* Write PLL2 registers. */
2460b3ff493bSmrgvoid R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2461c582b7e3Smrg{
2462c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2463c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2464c582b7e3Smrg
2465c582b7e3Smrg    OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
2466c582b7e3Smrg	    R128_V2CLK_SRC_SEL_CPUCLK,
2467c582b7e3Smrg	    ~R128_V2CLK_SRC_SEL_MASK);
2468c582b7e3Smrg
2469c582b7e3Smrg    OUTPLLP(pScrn,
2470c582b7e3Smrg	    R128_P2PLL_CNTL,
2471c582b7e3Smrg	    R128_P2PLL_RESET
2472c582b7e3Smrg	    | R128_P2PLL_ATOMIC_UPDATE_EN
2473c582b7e3Smrg	    | R128_P2PLL_VGA_ATOMIC_UPDATE_EN,
2474c582b7e3Smrg	    ~(R128_P2PLL_RESET
2475c582b7e3Smrg	      | R128_P2PLL_ATOMIC_UPDATE_EN
2476c582b7e3Smrg	      | R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
2477c582b7e3Smrg
2478c582b7e3Smrg#if 1
2479c582b7e3Smrg    OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK);
2480c582b7e3Smrg#endif
2481c582b7e3Smrg
2482c582b7e3Smrg        /*R128PLL2WaitForReadUpdateComplete(pScrn);*/
2483c582b7e3Smrg
2484c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK);
2485c582b7e3Smrg
2486c582b7e3Smrg/*        R128PLL2WriteUpdate(pScrn);
2487c582b7e3Smrg    R128PLL2WaitForReadUpdateComplete(pScrn);*/
2488c582b7e3Smrg
2489c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_DIV_0,
2490c582b7e3Smrg			restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK);
2491c582b7e3Smrg
2492c582b7e3Smrg/*    R128PLL2WriteUpdate(pScrn);
2493c582b7e3Smrg    R128PLL2WaitForReadUpdateComplete(pScrn);*/
2494c582b7e3Smrg
2495c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_DIV_0,
2496c582b7e3Smrg			restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK);
2497c582b7e3Smrg
2498c582b7e3Smrg    R128PLL2WriteUpdate(pScrn);
2499c582b7e3Smrg    R128PLL2WaitForReadUpdateComplete(pScrn);
2500c582b7e3Smrg
2501c582b7e3Smrg    OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2);
2502c582b7e3Smrg
2503c582b7e3Smrg/*        R128PLL2WriteUpdate(pScrn);*/
2504c582b7e3Smrg
2505c582b7e3Smrg    OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET
2506c582b7e3Smrg					| R128_P2PLL_SLEEP
2507c582b7e3Smrg					| R128_P2PLL_ATOMIC_UPDATE_EN
2508c582b7e3Smrg					| R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
2509c582b7e3Smrg
2510c582b7e3Smrg    R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
2511c582b7e3Smrg	       restore->p2pll_ref_div,
2512c582b7e3Smrg	       restore->p2pll_div_0,
2513c582b7e3Smrg	       restore->htotal_cntl2,
25149e881af1Smacallan	       INPLL(pScrn, R128_P2PLL_CNTL)));
251584354367Smrg    R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
251684354367Smrg	       restore->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
251784354367Smrg	       restore->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
251884354367Smrg	       (restore->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >>16));
2519c582b7e3Smrg
2520c582b7e3Smrg    usleep(5000); /* Let the clock to lock */
2521c582b7e3Smrg
2522c582b7e3Smrg    OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
2523c582b7e3Smrg	    R128_V2CLK_SRC_SEL_P2PLLCLK,
2524c582b7e3Smrg	    ~R128_V2CLK_SRC_SEL_MASK);
2525c582b7e3Smrg
2526c582b7e3Smrg}
2527c582b7e3Smrg
2528c582b7e3Smrg/* Write DDA registers. */
2529b3ff493bSmrgvoid R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2530c582b7e3Smrg{
2531c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2532c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2533c582b7e3Smrg
2534c582b7e3Smrg    OUTREG(R128_DDA_CONFIG, restore->dda_config);
2535c582b7e3Smrg    OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
2536c582b7e3Smrg}
2537c582b7e3Smrg
2538c582b7e3Smrg/* Write DDA registers. */
2539b3ff493bSmrgvoid R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2540c582b7e3Smrg{
2541c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2542c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2543c582b7e3Smrg
2544c582b7e3Smrg    OUTREG(R128_DDA2_CONFIG, restore->dda2_config);
2545c582b7e3Smrg    OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off);
2546c582b7e3Smrg}
2547c582b7e3Smrg
2548c582b7e3Smrg/* Read common registers. */
2549c582b7e3Smrgstatic void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2550c582b7e3Smrg{
2551c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2552c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2553c582b7e3Smrg
2554c582b7e3Smrg    save->ovr_clr            = INREG(R128_OVR_CLR);
2555c582b7e3Smrg    save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
2556c582b7e3Smrg    save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
2557c582b7e3Smrg    save->ov0_scale_cntl     = INREG(R128_OV0_SCALE_CNTL);
2558c582b7e3Smrg    save->mpp_tb_config      = INREG(R128_MPP_TB_CONFIG);
2559c582b7e3Smrg    save->mpp_gp_config      = INREG(R128_MPP_GP_CONFIG);
2560c582b7e3Smrg    save->subpic_cntl        = INREG(R128_SUBPIC_CNTL);
2561c582b7e3Smrg    save->viph_control       = INREG(R128_VIPH_CONTROL);
2562c582b7e3Smrg    save->i2c_cntl_1         = INREG(R128_I2C_CNTL_1);
2563c582b7e3Smrg    save->gen_int_cntl       = INREG(R128_GEN_INT_CNTL);
2564c582b7e3Smrg    save->cap0_trig_cntl     = INREG(R128_CAP0_TRIG_CNTL);
2565c582b7e3Smrg    save->cap1_trig_cntl     = INREG(R128_CAP1_TRIG_CNTL);
2566c582b7e3Smrg    save->bus_cntl           = INREG(R128_BUS_CNTL);
2567c582b7e3Smrg    save->config_cntl        = INREG(R128_CONFIG_CNTL);
2568c582b7e3Smrg}
2569c582b7e3Smrg
2570c582b7e3Smrg/* Read CRTC registers. */
2571c582b7e3Smrgstatic void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2572c582b7e3Smrg{
2573c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2574c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2575c582b7e3Smrg
2576c582b7e3Smrg    save->crtc_gen_cntl        = INREG(R128_CRTC_GEN_CNTL);
2577c582b7e3Smrg    save->crtc_ext_cntl        = INREG(R128_CRTC_EXT_CNTL);
2578c582b7e3Smrg    save->dac_cntl             = INREG(R128_DAC_CNTL);
2579c582b7e3Smrg    save->crtc_h_total_disp    = INREG(R128_CRTC_H_TOTAL_DISP);
2580c582b7e3Smrg    save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
2581c582b7e3Smrg    save->crtc_v_total_disp    = INREG(R128_CRTC_V_TOTAL_DISP);
2582c582b7e3Smrg    save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
2583c582b7e3Smrg    save->crtc_offset          = INREG(R128_CRTC_OFFSET);
2584c582b7e3Smrg    save->crtc_offset_cntl     = INREG(R128_CRTC_OFFSET_CNTL);
2585c582b7e3Smrg    save->crtc_pitch           = INREG(R128_CRTC_PITCH);
2586c582b7e3Smrg}
2587c582b7e3Smrg
2588c582b7e3Smrg/* Read flat panel registers */
2589c582b7e3Smrgstatic void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2590c582b7e3Smrg{
2591c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2592c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2593c582b7e3Smrg
2594c582b7e3Smrg    save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
2595c582b7e3Smrg    save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
2596c582b7e3Smrg    save->fp_gen_cntl          = INREG(R128_FP_GEN_CNTL);
2597c582b7e3Smrg    save->fp_h_sync_strt_wid   = INREG(R128_FP_H_SYNC_STRT_WID);
2598c582b7e3Smrg    save->fp_horz_stretch      = INREG(R128_FP_HORZ_STRETCH);
2599c582b7e3Smrg    save->fp_panel_cntl        = INREG(R128_FP_PANEL_CNTL);
2600c582b7e3Smrg    save->fp_v_sync_strt_wid   = INREG(R128_FP_V_SYNC_STRT_WID);
2601c582b7e3Smrg    save->fp_vert_stretch      = INREG(R128_FP_VERT_STRETCH);
2602c582b7e3Smrg    save->lvds_gen_cntl        = INREG(R128_LVDS_GEN_CNTL);
2603c582b7e3Smrg    save->tmds_crc             = INREG(R128_TMDS_CRC);
2604c582b7e3Smrg    save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
2605c582b7e3Smrg}
2606c582b7e3Smrg
2607c582b7e3Smrg/* Read CRTC2 registers. */
2608c582b7e3Smrgstatic void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2609c582b7e3Smrg{
2610c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
2611c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2612c582b7e3Smrg
2613c582b7e3Smrg    save->crtc2_gen_cntl        = INREG(R128_CRTC2_GEN_CNTL);
2614c582b7e3Smrg    save->crtc2_h_total_disp    = INREG(R128_CRTC2_H_TOTAL_DISP);
2615c582b7e3Smrg    save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID);
2616c582b7e3Smrg    save->crtc2_v_total_disp    = INREG(R128_CRTC2_V_TOTAL_DISP);
2617c582b7e3Smrg    save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID);
2618c582b7e3Smrg    save->crtc2_offset          = INREG(R128_CRTC2_OFFSET);
2619c582b7e3Smrg    save->crtc2_offset_cntl     = INREG(R128_CRTC2_OFFSET_CNTL);
2620c582b7e3Smrg    save->crtc2_pitch           = INREG(R128_CRTC2_PITCH);
2621c582b7e3Smrg}
2622c582b7e3Smrg
2623c582b7e3Smrg/* Read PLL registers. */
2624c582b7e3Smrgstatic void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2625c582b7e3Smrg{
2626c582b7e3Smrg    save->ppll_ref_div         = INPLL(pScrn, R128_PPLL_REF_DIV);
2627c582b7e3Smrg    save->ppll_div_3           = INPLL(pScrn, R128_PPLL_DIV_3);
26289e881af1Smacallan    save->ppll_div_0           = INPLL(pScrn, R128_PPLL_DIV_0);
2629c582b7e3Smrg    save->htotal_cntl          = INPLL(pScrn, R128_HTOTAL_CNTL);
2630c582b7e3Smrg
2631c582b7e3Smrg    R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
2632c582b7e3Smrg	       save->ppll_ref_div,
2633c582b7e3Smrg	       save->ppll_div_3,
2634c582b7e3Smrg	       save->htotal_cntl));
2635c582b7e3Smrg    R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
2636c582b7e3Smrg	       save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
2637c582b7e3Smrg	       save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
2638c582b7e3Smrg	       (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
2639c582b7e3Smrg}
2640c582b7e3Smrg
2641c582b7e3Smrg/* Read PLL2 registers. */
2642c582b7e3Smrgstatic void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2643c582b7e3Smrg{
2644c582b7e3Smrg    save->p2pll_ref_div        = INPLL(pScrn, R128_P2PLL_REF_DIV);
2645c582b7e3Smrg    save->p2pll_div_0          = INPLL(pScrn, R128_P2PLL_DIV_0);
2646c582b7e3Smrg    save->htotal_cntl2         = INPLL(pScrn, R128_HTOTAL2_CNTL);
2647c582b7e3Smrg
2648c582b7e3Smrg    R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
2649c582b7e3Smrg	       save->p2pll_ref_div,
2650c582b7e3Smrg	       save->p2pll_div_0,
2651c582b7e3Smrg	       save->htotal_cntl2));
2652c582b7e3Smrg    R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
2653c582b7e3Smrg	       save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
2654c582b7e3Smrg	       save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
2655c582b7e3Smrg	       (save->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >> 16));
2656c582b7e3Smrg}
2657c582b7e3Smrg
2658c582b7e3Smrg/* Read DDA registers. */
2659c582b7e3Smrgstatic void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2660c582b7e3Smrg{
2661c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2662c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2663c582b7e3Smrg
2664c582b7e3Smrg    save->dda_config           = INREG(R128_DDA_CONFIG);
2665c582b7e3Smrg    save->dda_on_off           = INREG(R128_DDA_ON_OFF);
2666c582b7e3Smrg}
2667c582b7e3Smrg
2668c582b7e3Smrg/* Read DDA2 registers. */
2669c582b7e3Smrgstatic void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2670c582b7e3Smrg{
2671c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2672c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2673c582b7e3Smrg
2674c582b7e3Smrg    save->dda2_config           = INREG(R128_DDA2_CONFIG);
2675c582b7e3Smrg    save->dda2_on_off           = INREG(R128_DDA2_ON_OFF);
2676c582b7e3Smrg}
2677c582b7e3Smrg
2678c582b7e3Smrg/* Read palette data. */
2679c582b7e3Smrgstatic void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
2680c582b7e3Smrg{
2681c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2682c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2683c582b7e3Smrg    int           i;
2684c582b7e3Smrg
2685c582b7e3Smrg    PAL_SELECT(1);
2686c582b7e3Smrg    INPAL_START(0);
2687c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
2688c582b7e3Smrg    PAL_SELECT(0);
2689c582b7e3Smrg    INPAL_START(0);
2690c582b7e3Smrg    for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
2691c582b7e3Smrg    save->palette_valid = TRUE;
2692c582b7e3Smrg}
2693c582b7e3Smrg
2694c582b7e3Smrg/* Save state that defines current video mode. */
2695c582b7e3Smrgstatic void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
2696c582b7e3Smrg{
2697c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2698b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2699c582b7e3Smrg
2700c582b7e3Smrg    R128TRACE(("R128SaveMode(%p)\n", save));
2701c582b7e3Smrg
2702b3ff493bSmrg    R128SaveCommonRegisters(pScrn, save);
2703b3ff493bSmrg    R128SaveCrtcRegisters(pScrn, save);
2704b3ff493bSmrg    R128SavePLLRegisters(pScrn, save);
2705b3ff493bSmrg    R128SaveDDARegisters(pScrn, save);
2706b3ff493bSmrg    if (pR128Ent->HasCRTC2) {
2707c582b7e3Smrg        R128SaveCrtc2Registers(pScrn, save);
2708c582b7e3Smrg        R128SavePLL2Registers(pScrn, save);
2709c582b7e3Smrg        R128SaveDDA2Registers(pScrn, save);
2710c582b7e3Smrg    }
2711b3ff493bSmrg    if (info->HasPanelRegs) {
2712b3ff493bSmrg        R128SaveFPRegisters(pScrn, save);
2713c582b7e3Smrg    }
2714b3ff493bSmrg    R128SavePalette(pScrn, save);
2715c582b7e3Smrg
2716c582b7e3Smrg    R128TRACE(("R128SaveMode returns %p\n", save));
2717c582b7e3Smrg}
2718c582b7e3Smrg
2719c582b7e3Smrg/* Save everything needed to restore the original VC state. */
2720c582b7e3Smrgstatic void R128Save(ScrnInfoPtr pScrn)
2721c582b7e3Smrg{
2722c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2723c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2724c582b7e3Smrg    R128SavePtr   save      = &info->SavedReg;
2725c582b7e3Smrg
2726c582b7e3Smrg    R128TRACE(("R128Save\n"));
272779e5230eSmacallan#ifndef AVOID_FBDEV
2728c582b7e3Smrg    if (info->FBDev) {
2729c582b7e3Smrg	fbdevHWSave(pScrn);
2730c582b7e3Smrg	return;
2731c582b7e3Smrg    }
273279e5230eSmacallan#endif
2733c582b7e3Smrg
2734c582b7e3Smrg#ifdef WITH_VGAHW
2735b3ff493bSmrg    if (info->VGAAccess) {
2736b3ff493bSmrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2737c582b7e3Smrg
2738b3ff493bSmrg        vgaHWUnlock(hwp);
2739c582b7e3Smrg# if defined(__powerpc__)
2740b3ff493bSmrg        /* temporary hack to prevent crashing on PowerMacs when trying to
2741b3ff493bSmrg         * read VGA fonts and colormap, will find a better solution
2742b3ff493bSmrg         * in the future. TODO: Check if there's actually some VGA stuff
2743b3ff493bSmrg         * setup in the card at all !!
2744b3ff493bSmrg         */
2745b3ff493bSmrg        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
2746c582b7e3Smrg# else
2747b3ff493bSmrg        /* Save mode * & fonts & cmap */
2748b3ff493bSmrg        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
2749c582b7e3Smrg# endif
2750b3ff493bSmrg        vgaHWLock(hwp);
2751c582b7e3Smrg    }
2752b3ff493bSmrg#endif
2753c582b7e3Smrg
2754b3ff493bSmrg    save->dp_datatype      = INREG(R128_DP_DATATYPE);
2755b3ff493bSmrg    save->gen_reset_cntl   = INREG(R128_GEN_RESET_CNTL);
2756b3ff493bSmrg    save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
2757b3ff493bSmrg    save->amcgpio_en_reg   = INREG(R128_AMCGPIO_EN_REG);
2758b3ff493bSmrg    save->amcgpio_mask     = INREG(R128_AMCGPIO_MASK);
2759c582b7e3Smrg
2760b3ff493bSmrg    R128SaveMode(pScrn, save);
2761c582b7e3Smrg}
2762c582b7e3Smrg
2763c582b7e3Smrg/* Restore the original (text) mode. */
2764c582b7e3Smrgstatic void R128Restore(ScrnInfoPtr pScrn)
2765c582b7e3Smrg{
2766c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
2767b3ff493bSmrg    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2768c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
2769c582b7e3Smrg    R128SavePtr   restore   = &info->SavedReg;
2770c582b7e3Smrg
2771c582b7e3Smrg    R128TRACE(("R128Restore\n"));
277279e5230eSmacallan#ifndef AVOID_FBDEV
2773c582b7e3Smrg    if (info->FBDev) {
2774c582b7e3Smrg	fbdevHWRestore(pScrn);
2775c582b7e3Smrg	return;
2776c582b7e3Smrg    }
277779e5230eSmacallan#endif
2778c582b7e3Smrg    R128Blank(pScrn);
2779c582b7e3Smrg
2780b3ff493bSmrg    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
2781b3ff493bSmrg    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
2782b3ff493bSmrg    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
2783b3ff493bSmrg    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
2784b3ff493bSmrg    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
2785c582b7e3Smrg
2786b3ff493bSmrg    R128RestoreCommonRegisters(pScrn, restore);
2787b3ff493bSmrg    if (pR128Ent->HasCRTC2) {
2788b3ff493bSmrg        R128RestoreDDA2Registers(pScrn, restore);
2789b3ff493bSmrg        R128RestoreCrtc2Registers(pScrn, restore);
2790b3ff493bSmrg        R128RestorePLL2Registers(pScrn, restore);
2791b3ff493bSmrg    }
2792b3ff493bSmrg    R128RestoreDDARegisters(pScrn, restore);
2793b3ff493bSmrg    R128RestoreCrtcRegisters(pScrn, restore);
2794b3ff493bSmrg    R128RestorePLLRegisters(pScrn, restore);
2795b3ff493bSmrg    R128RestoreDACRegisters(pScrn, restore);
2796b3ff493bSmrg    R128RestoreRMXRegisters(pScrn, restore);
2797b3ff493bSmrg    R128RestoreFPRegisters(pScrn, restore);
2798b3ff493bSmrg    R128RestoreLVDSRegisters(pScrn, restore);
27999e881af1Smacallan
28003c921f55Smrg#if 0
28019e881af1Smacallan    if (!info->IsSecondary) {
28029e881af1Smacallan        OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
28039e881af1Smacallan        OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
28049e881af1Smacallan        OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
28059e881af1Smacallan        OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
28069e881af1Smacallan        OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
28079e881af1Smacallan    }
28083c921f55Smrg#endif
28099e881af1Smacallan
2810c582b7e3Smrg#ifdef WITH_VGAHW
2811c582b7e3Smrg    if (info->VGAAccess) {
2812c582b7e3Smrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2813b3ff493bSmrg        vgaHWUnlock(hwp);
2814c582b7e3Smrg# if defined(__powerpc__)
2815b3ff493bSmrg        /* Temporary hack to prevent crashing on PowerMacs when trying to
2816b3ff493bSmrg         * write VGA fonts, will find a better solution in the future
2817b3ff493bSmrg         */
2818b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
2819c582b7e3Smrg# else
2820b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
2821c582b7e3Smrg# endif
2822b3ff493bSmrg        vgaHWLock(hwp);
2823c582b7e3Smrg    }
2824c582b7e3Smrg#endif
2825c582b7e3Smrg
2826c582b7e3Smrg    R128WaitForVerticalSync(pScrn);
2827c582b7e3Smrg    R128Unblank(pScrn);
2828c582b7e3Smrg}
2829c582b7e3Smrg
2830c582b7e3Smrg/* Define common registers for requested video mode. */
2831b3ff493bSmrgvoid R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
2832c582b7e3Smrg{
2833c582b7e3Smrg    save->ovr_clr            = 0;
2834c582b7e3Smrg    save->ovr_wid_left_right = 0;
2835c582b7e3Smrg    save->ovr_wid_top_bottom = 0;
2836c582b7e3Smrg    save->ov0_scale_cntl     = 0;
2837c582b7e3Smrg    save->mpp_tb_config      = 0;
2838c582b7e3Smrg    save->mpp_gp_config      = 0;
2839c582b7e3Smrg    save->subpic_cntl        = 0;
2840c582b7e3Smrg    save->viph_control       = 0;
2841c582b7e3Smrg    save->i2c_cntl_1         = 0;
284284354367Smrg#ifdef R128DRI
2843c582b7e3Smrg    save->gen_int_cntl       = info->gen_int_cntl;
2844c582b7e3Smrg#else
2845c582b7e3Smrg    save->gen_int_cntl       = 0;
2846c582b7e3Smrg#endif
2847c582b7e3Smrg    save->cap0_trig_cntl     = 0;
2848c582b7e3Smrg    save->cap1_trig_cntl     = 0;
2849c582b7e3Smrg    save->bus_cntl           = info->BusCntl;
2850c582b7e3Smrg    /*
2851c582b7e3Smrg     * If bursts are enabled, turn on discards and aborts
2852c582b7e3Smrg     */
2853c582b7e3Smrg    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
2854c582b7e3Smrg	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
2855c582b7e3Smrg}
2856c582b7e3Smrg
2857b3ff493bSmrgBool R128InitCrtcBase(xf86CrtcPtr crtc, R128SavePtr save, int x, int y)
2858b3ff493bSmrg{
2859b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
2860b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2861b3ff493bSmrg    int offset = y * info->CurrentLayout.displayWidth + x;
2862b3ff493bSmrg    int Base = pScrn->fbOffset;
2863b3ff493bSmrg
2864b3ff493bSmrg    switch (info->CurrentLayout.pixel_code) {
2865b3ff493bSmrg    case 15:
2866b3ff493bSmrg    case 16: offset *= 2; break;
2867b3ff493bSmrg    case 24: offset *= 3; break;
2868b3ff493bSmrg    case 32: offset *= 4; break;
2869b3ff493bSmrg    }
2870b3ff493bSmrg    Base += offset;
2871b3ff493bSmrg
2872b3ff493bSmrg    if (crtc->rotatedData != NULL)
2873b3ff493bSmrg        Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
2874b3ff493bSmrg
2875b3ff493bSmrg    Base &= ~7;                 /* 3 lower bits are always 0 */
2876b3ff493bSmrg    if (info->CurrentLayout.pixel_code == 24)
2877b3ff493bSmrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2878b3ff493bSmrg
2879b3ff493bSmrg    save->crtc_offset = Base;
2880b3ff493bSmrg    save->crtc_offset_cntl = 0;
2881b3ff493bSmrg
2882b3ff493bSmrg    return TRUE;
2883b3ff493bSmrg}
2884b3ff493bSmrg
2885b3ff493bSmrgBool R128InitCrtc2Base(xf86CrtcPtr crtc, R128SavePtr save, int x, int y)
2886b3ff493bSmrg{
2887b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
2888b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2889b3ff493bSmrg    int offset = y * info->CurrentLayout.displayWidth + x;
2890b3ff493bSmrg    int Base = pScrn->fbOffset;
2891b3ff493bSmrg
2892b3ff493bSmrg    switch (info->CurrentLayout.pixel_code) {
2893b3ff493bSmrg    case 15:
2894b3ff493bSmrg    case 16: offset *= 2; break;
2895b3ff493bSmrg    case 24: offset *= 3; break;
2896b3ff493bSmrg    case 32: offset *= 4; break;
2897b3ff493bSmrg    }
2898b3ff493bSmrg    Base += offset;
2899b3ff493bSmrg
2900b3ff493bSmrg    if (crtc->rotatedData != NULL)
2901b3ff493bSmrg        Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
2902b3ff493bSmrg
2903b3ff493bSmrg    Base &= ~7;                 /* 3 lower bits are always 0 */
2904b3ff493bSmrg    if (info->CurrentLayout.pixel_code == 24)
2905b3ff493bSmrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2906b3ff493bSmrg
2907b3ff493bSmrg    save->crtc2_offset = Base;
2908b3ff493bSmrg    save->crtc2_offset_cntl = 0;
2909b3ff493bSmrg
2910b3ff493bSmrg    return TRUE;
2911b3ff493bSmrg}
2912b3ff493bSmrg
2913c582b7e3Smrg/* Define CRTC registers for requested video mode. */
2914b3ff493bSmrgBool R128InitCrtcRegisters(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode)
2915c582b7e3Smrg{
2916b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
2917b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2918b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(crtc);
2919b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2920b3ff493bSmrg
2921c582b7e3Smrg    int    format;
2922c582b7e3Smrg    int    hsync_start;
2923c582b7e3Smrg    int    hsync_wid;
2924c582b7e3Smrg    int    hsync_fudge;
2925c582b7e3Smrg    int    vsync_wid;
2926c582b7e3Smrg    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
2927c582b7e3Smrg    int    hsync_fudge_fp[]      = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
2928c582b7e3Smrg//   int    hsync_fudge_fp_crt[]  = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
2929c582b7e3Smrg
2930c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
2931c582b7e3Smrg    case 4:  format = 1; break;
2932c582b7e3Smrg    case 8:  format = 2; break;
2933c582b7e3Smrg    case 15: format = 3; break;      /*  555 */
2934c582b7e3Smrg    case 16: format = 4; break;      /*  565 */
2935c582b7e3Smrg    case 24: format = 5; break;      /*  RGB */
2936c582b7e3Smrg    case 32: format = 6; break;      /* xRGB */
2937c582b7e3Smrg    default:
2938c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2939c582b7e3Smrg		   "Unsupported pixel depth (%d)\n",
2940c582b7e3Smrg		   info->CurrentLayout.bitsPerPixel);
2941c582b7e3Smrg	return FALSE;
2942c582b7e3Smrg    }
2943c582b7e3Smrg
2944b3ff493bSmrg    if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP)
2945c582b7e3Smrg	hsync_fudge = hsync_fudge_fp[format-1];
2946c582b7e3Smrg    else
2947c582b7e3Smrg        hsync_fudge = hsync_fudge_default[format-1];
2948c582b7e3Smrg
2949c582b7e3Smrg    save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN
2950c582b7e3Smrg			  | R128_CRTC_EN
2951c582b7e3Smrg			  | (format << 8)
2952c582b7e3Smrg			  | ((mode->Flags & V_DBLSCAN)
2953c582b7e3Smrg			     ? R128_CRTC_DBL_SCAN_EN
2954c582b7e3Smrg			     : 0)
2955c582b7e3Smrg			  | ((mode->Flags & V_INTERLACE)
2956c582b7e3Smrg			     ? R128_CRTC_INTERLACE_EN
2957c582b7e3Smrg			     : 0)
2958c582b7e3Smrg			  | ((mode->Flags & V_CSYNC)
2959c582b7e3Smrg			     ? R128_CRTC_CSYNC_EN
2960c582b7e3Smrg			     : 0));
2961c582b7e3Smrg
2962b3ff493bSmrg    if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP)
2963b3ff493bSmrg        save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | R128_CRTC_INTERLACE_EN);
2964c582b7e3Smrg
2965b3ff493bSmrg    save->crtc_ext_cntl |= R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN;
2966c582b7e3Smrg
2967c582b7e3Smrg    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
2968c582b7e3Smrg			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
2969c582b7e3Smrg
2970c582b7e3Smrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
2971c582b7e3Smrg    if (!hsync_wid)       hsync_wid = 1;
2972c582b7e3Smrg    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
2973c582b7e3Smrg
2974c582b7e3Smrg    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
2975c582b7e3Smrg
2976c582b7e3Smrg    save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff)
2977c582b7e3Smrg				 | (hsync_wid << 16)
2978c582b7e3Smrg				 | ((mode->Flags & V_NHSYNC)
2979c582b7e3Smrg				    ? R128_CRTC_H_SYNC_POL
2980c582b7e3Smrg				    : 0));
2981c582b7e3Smrg
2982c582b7e3Smrg#if 1
2983c582b7e3Smrg				/* This works for double scan mode. */
2984c582b7e3Smrg    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
2985c582b7e3Smrg			      | ((mode->CrtcVDisplay - 1) << 16));
2986c582b7e3Smrg#else
2987c582b7e3Smrg				/* This is what cce/nbmode.c example code
2988c582b7e3Smrg				   does -- is this correct? */
2989c582b7e3Smrg    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
2990c582b7e3Smrg			      | ((mode->CrtcVDisplay
2991c582b7e3Smrg				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
2992c582b7e3Smrg				 << 16));
2993c582b7e3Smrg#endif
2994c582b7e3Smrg
2995c582b7e3Smrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
2996c582b7e3Smrg    if (!vsync_wid)       vsync_wid = 1;
2997c582b7e3Smrg    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
2998c582b7e3Smrg
2999c582b7e3Smrg    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3000c582b7e3Smrg				 | (vsync_wid << 16)
3001c582b7e3Smrg				 | ((mode->Flags & V_NVSYNC)
3002c582b7e3Smrg				    ? R128_CRTC_V_SYNC_POL
3003c582b7e3Smrg				    : 0));
3004c582b7e3Smrg    save->crtc_pitch       = info->CurrentLayout.displayWidth / 8;
3005c582b7e3Smrg
3006c582b7e3Smrg    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3007c582b7e3Smrg	       save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth));
3008c582b7e3Smrg
3009c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
3010c582b7e3Smrg    /* Change the endianness of the aperture */
3011c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3012c582b7e3Smrg    case 15:
3013c582b7e3Smrg    case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break;
3014c582b7e3Smrg    case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break;
3015c582b7e3Smrg    default: break;
3016c582b7e3Smrg    }
3017c582b7e3Smrg#endif
3018c582b7e3Smrg
3019c582b7e3Smrg    return TRUE;
3020c582b7e3Smrg}
3021c582b7e3Smrg
3022c582b7e3Smrg/* Define CRTC2 registers for requested video mode. */
3023b3ff493bSmrgBool R128InitCrtc2Registers(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode)
3024c582b7e3Smrg{
3025b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
3026b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3027b3ff493bSmrg
3028c582b7e3Smrg    int    format;
3029c582b7e3Smrg    int    hsync_start;
3030c582b7e3Smrg    int    hsync_wid;
3031c582b7e3Smrg    int    hsync_fudge;
3032c582b7e3Smrg    int    vsync_wid;
3033c582b7e3Smrg    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
3034c582b7e3Smrg
3035c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3036b3ff493bSmrg    case 4:  format = 1; break;
3037b3ff493bSmrg    case 8:  format = 2; break;
3038b3ff493bSmrg    case 15: format = 3; break;      /*  555 */
3039b3ff493bSmrg    case 16: format = 4; break;      /*  565 */
3040b3ff493bSmrg    case 24: format = 5; break;      /*  RGB */
3041b3ff493bSmrg    case 32: format = 6; break;      /* xRGB */
3042c582b7e3Smrg    default:
3043c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3044c582b7e3Smrg		   "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel);
3045c582b7e3Smrg	return FALSE;
3046c582b7e3Smrg    }
3047c582b7e3Smrg
3048c582b7e3Smrg    hsync_fudge = hsync_fudge_default[format-1];
3049c582b7e3Smrg
3050c582b7e3Smrg    save->crtc2_gen_cntl = (R128_CRTC2_EN
3051c582b7e3Smrg			  | (format << 8)
3052c582b7e3Smrg			  | ((mode->Flags & V_DBLSCAN)
3053c582b7e3Smrg			     ? R128_CRTC2_DBL_SCAN_EN
3054c582b7e3Smrg			     : 0));
3055c582b7e3Smrg/*
3056c582b7e3Smrg    save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN;
3057c582b7e3Smrg    save->crtc2_gen_cntl |= (1 << 21);
3058c582b7e3Smrg*/
3059c582b7e3Smrg    save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
3060c582b7e3Smrg			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
3061c582b7e3Smrg
3062c582b7e3Smrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
3063c582b7e3Smrg    if (!hsync_wid)       hsync_wid = 1;
3064c582b7e3Smrg    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
3065c582b7e3Smrg
3066c582b7e3Smrg    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
3067c582b7e3Smrg
3068c582b7e3Smrg    save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff)
3069c582b7e3Smrg				 | (hsync_wid << 16)
3070c582b7e3Smrg				 | ((mode->Flags & V_NHSYNC)
3071c582b7e3Smrg				    ? R128_CRTC2_H_SYNC_POL
3072c582b7e3Smrg				    : 0));
3073c582b7e3Smrg
3074c582b7e3Smrg#if 1
3075c582b7e3Smrg				/* This works for double scan mode. */
3076c582b7e3Smrg    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3077c582b7e3Smrg			      | ((mode->CrtcVDisplay - 1) << 16));
3078c582b7e3Smrg#else
3079c582b7e3Smrg				/* This is what cce/nbmode.c example code
3080c582b7e3Smrg				   does -- is this correct? */
3081c582b7e3Smrg    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3082c582b7e3Smrg			      | ((mode->CrtcVDisplay
3083c582b7e3Smrg				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
3084c582b7e3Smrg				 << 16));
3085c582b7e3Smrg#endif
3086c582b7e3Smrg
3087c582b7e3Smrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
3088c582b7e3Smrg    if (!vsync_wid)       vsync_wid = 1;
3089c582b7e3Smrg    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
3090c582b7e3Smrg
3091c582b7e3Smrg    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3092c582b7e3Smrg				 | (vsync_wid << 16)
3093c582b7e3Smrg				 | ((mode->Flags & V_NVSYNC)
3094c582b7e3Smrg				    ? R128_CRTC2_V_SYNC_POL
3095c582b7e3Smrg				    : 0));
3096c582b7e3Smrg    save->crtc2_pitch       = info->CurrentLayout.displayWidth / 8;
3097c582b7e3Smrg
3098c582b7e3Smrg    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3099c582b7e3Smrg		 save->crtc2_pitch, pScrn->virtualX,
3100c582b7e3Smrg		 info->CurrentLayout.displayWidth));
3101c582b7e3Smrg    return TRUE;
3102c582b7e3Smrg}
3103c582b7e3Smrg
3104b3ff493bSmrg/* Define DAC registers for the requested video mode. */
3105b3ff493bSmrgvoid R128InitDACRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
3106b3ff493bSmrg{
3107b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
3108b3ff493bSmrg    R128InfoPtr info = R128PTR(pScrn);
3109b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
3110b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
3111b3ff493bSmrg
3112b3ff493bSmrg    save->dac_cntl = (R128_DAC_MASK_ALL | R128_DAC_VGA_ADR_EN |
3113b3ff493bSmrg                      (!r128_crtc->crtc_id ? 0 : R128_DAC_CRT_SEL_CRTC2) |
3114b3ff493bSmrg                      (info->dac6bits      ? 0 : R128_DAC_8BIT_EN));
3115b3ff493bSmrg}
3116b3ff493bSmrg
3117b3ff493bSmrg/* Define RMX registers for the requested video mode. */
3118b3ff493bSmrgvoid R128InitRMXRegisters(R128SavePtr orig, R128SavePtr save,
3119b3ff493bSmrg                          xf86OutputPtr output, DisplayModePtr mode)
3120c582b7e3Smrg{
3121b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3122b3ff493bSmrg
3123c582b7e3Smrg    int   xres = mode->CrtcHDisplay;
3124c582b7e3Smrg    int   yres = mode->CrtcVDisplay;
3125c582b7e3Smrg    float Hratio, Vratio;
3126c582b7e3Smrg
3127b3ff493bSmrg    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
3128b3ff493bSmrg    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
3129b3ff493bSmrg    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
3130b3ff493bSmrg    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
3131b3ff493bSmrg
3132b3ff493bSmrg    if (r128_output->MonType != MT_DFP && r128_output->MonType != MT_LCD)
3133c582b7e3Smrg        return;
3134c582b7e3Smrg
3135b3ff493bSmrg    if (r128_output->PanelXRes == 0 || r128_output->PanelYRes == 0) {
3136b3ff493bSmrg        xres = r128_output->PanelXRes;
3137b3ff493bSmrg        yres = r128_output->PanelYRes;
3138b3ff493bSmrg
3139b3ff493bSmrg        Hratio = 1.0;
3140b3ff493bSmrg        Vratio = 1.0;
3141b3ff493bSmrg    } else {
3142b3ff493bSmrg        if (xres > r128_output->PanelXRes) xres = r128_output->PanelXRes;
3143b3ff493bSmrg        if (yres > r128_output->PanelYRes) yres = r128_output->PanelYRes;
3144c582b7e3Smrg
3145b3ff493bSmrg        Hratio = (float)xres/(float)r128_output->PanelXRes;
3146b3ff493bSmrg        Vratio = (float)yres/(float)r128_output->PanelYRes;
3147b3ff493bSmrg    }
3148c582b7e3Smrg
3149c582b7e3Smrg    save->fp_horz_stretch =
3150c582b7e3Smrg	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
3151c582b7e3Smrg	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
3152c582b7e3Smrg       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
3153c582b7e3Smrg                                 R128_HORZ_FP_LOOP_STRETCH |
3154c582b7e3Smrg                                 R128_HORZ_STRETCH_RESERVED)));
3155c582b7e3Smrg    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
3156c582b7e3Smrg    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
3157b3ff493bSmrg    if (xres == r128_output->PanelXRes)
3158c582b7e3Smrg         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3159c582b7e3Smrg    else
3160c582b7e3Smrg         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3161c582b7e3Smrg
3162c582b7e3Smrg    save->fp_vert_stretch =
3163c582b7e3Smrg	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
3164c582b7e3Smrg	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
3165c582b7e3Smrg	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
3166c582b7e3Smrg				   R128_VERT_STRETCH_RESERVED)));
3167c582b7e3Smrg    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
3168b3ff493bSmrg    if (yres == r128_output->PanelYRes)
3169c582b7e3Smrg        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3170c582b7e3Smrg    else
3171c582b7e3Smrg        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3172b3ff493bSmrg}
3173c582b7e3Smrg
3174b3ff493bSmrg/* Define flat panel registers for the requested video mode. */
3175b3ff493bSmrgvoid R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
3176b3ff493bSmrg{
3177b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
3178b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
3179c582b7e3Smrg
3180c582b7e3Smrg    /* WARNING: Be careful about turning on the flat panel */
3181b3ff493bSmrg    save->fp_gen_cntl            = orig->fp_gen_cntl;
3182b3ff493bSmrg    save->fp_panel_cntl          = orig->fp_panel_cntl;
3183b3ff493bSmrg    save->tmds_transmitter_cntl  = orig->tmds_transmitter_cntl;
3184b3ff493bSmrg    save->tmds_crc               = orig->tmds_crc;
3185b3ff493bSmrg
3186b3ff493bSmrg    if (r128_crtc->crtc_id)
3187b3ff493bSmrg        save->fp_gen_cntl       |=   R128_FP_SEL_CRTC2;
3188c582b7e3Smrg    else
3189b3ff493bSmrg        save->fp_gen_cntl       &=  ~R128_FP_SEL_CRTC2;
3190c582b7e3Smrg
3191b3ff493bSmrg    save->fp_gen_cntl           &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
3192b3ff493bSmrg                                     R128_FP_CRTC_USE_SHADOW_ROWCUR |
3193b3ff493bSmrg                                     R128_FP_CRTC_HORZ_DIV2_EN |
3194b3ff493bSmrg                                     R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3195b3ff493bSmrg                                     R128_FP_CRT_SYNC_SEL |
3196b3ff493bSmrg                                     R128_FP_USE_SHADOW_EN);
3197b3ff493bSmrg
3198b3ff493bSmrg    save->fp_gen_cntl           |=  (R128_FP_CRTC_DONT_SHADOW_VPAR |
3199b3ff493bSmrg                                     R128_FP_CRTC_DONT_SHADOW_HEND);
3200b3ff493bSmrg
3201b3ff493bSmrg    save->fp_panel_cntl         |=  (R128_FP_DIGON | R128_FP_BLON);
3202b3ff493bSmrg    save->tmds_transmitter_cntl &=  ~R128_TMDS_PLLRST;
3203b3ff493bSmrg    save->tmds_transmitter_cntl |=   R128_TMDS_PLLEN;
3204b3ff493bSmrg}
3205b3ff493bSmrg
3206b3ff493bSmrg/* Define LVDS registers for the requested video mode. */
3207b3ff493bSmrgvoid R128InitLVDSRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
3208b3ff493bSmrg{
3209b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
3210b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
3211b3ff493bSmrg
3212b3ff493bSmrg    save->lvds_gen_cntl      =  orig->lvds_gen_cntl;
3213b3ff493bSmrg
3214b3ff493bSmrg    if (r128_crtc->crtc_id)
3215b3ff493bSmrg        save->lvds_gen_cntl |=  R128_LVDS_SEL_CRTC2;
3216b3ff493bSmrg    else
3217b3ff493bSmrg        save->lvds_gen_cntl &= ~R128_LVDS_SEL_CRTC2;
3218c582b7e3Smrg}
3219c582b7e3Smrg
3220c582b7e3Smrg/* Define PLL registers for requested video mode. */
3221b3ff493bSmrgvoid R128InitPLLRegisters(xf86CrtcPtr crtc, R128SavePtr save,
3222c582b7e3Smrg				R128PLLPtr pll, double dot_clock)
3223c582b7e3Smrg{
3224b3ff493bSmrg#if R128_DEBUG
3225b3ff493bSmrg    ScrnInfoPtr pScrn  = crtc->scrn;
3226b3ff493bSmrg#endif
3227c582b7e3Smrg    unsigned long freq = dot_clock * 100;
3228c582b7e3Smrg    struct {
3229c582b7e3Smrg	int divider;
3230c582b7e3Smrg	int bitvalue;
3231c582b7e3Smrg    } *post_div,
3232c582b7e3Smrg      post_divs[]   = {
3233c582b7e3Smrg				/* From RAGE 128 VR/RAGE 128 GL Register
3234c582b7e3Smrg				   Reference Manual (Technical Reference
3235c582b7e3Smrg				   Manual P/N RRG-G04100-C Rev. 0.04), page
3236c582b7e3Smrg				   3-17 (PLL_DIV_[3:0]).  */
3237c582b7e3Smrg	{  1, 0 },              /* VCLK_SRC                 */
3238c582b7e3Smrg	{  2, 1 },              /* VCLK_SRC/2               */
3239c582b7e3Smrg	{  4, 2 },              /* VCLK_SRC/4               */
3240c582b7e3Smrg	{  8, 3 },              /* VCLK_SRC/8               */
3241c582b7e3Smrg
3242c582b7e3Smrg	{  3, 4 },              /* VCLK_SRC/3               */
3243c582b7e3Smrg				/* bitvalue = 5 is reserved */
3244c582b7e3Smrg	{  6, 6 },              /* VCLK_SRC/6               */
3245c582b7e3Smrg	{ 12, 7 },              /* VCLK_SRC/12              */
3246c582b7e3Smrg	{  0, 0 }
3247c582b7e3Smrg    };
3248c582b7e3Smrg
3249c582b7e3Smrg    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3250c582b7e3Smrg    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3251c582b7e3Smrg
3252c582b7e3Smrg    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3253c582b7e3Smrg	save->pll_output_freq = post_div->divider * freq;
3254c582b7e3Smrg	if (save->pll_output_freq >= pll->min_pll_freq
3255c582b7e3Smrg	    && save->pll_output_freq <= pll->max_pll_freq) break;
3256c582b7e3Smrg    }
3257c582b7e3Smrg
3258c582b7e3Smrg    save->dot_clock_freq = freq;
3259c582b7e3Smrg    save->feedback_div   = R128Div(pll->reference_div * save->pll_output_freq,
3260c582b7e3Smrg				   pll->reference_freq);
3261c582b7e3Smrg    save->post_div       = post_div->divider;
3262c582b7e3Smrg
3263c582b7e3Smrg    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3264c582b7e3Smrg	       save->dot_clock_freq,
3265c582b7e3Smrg	       save->pll_output_freq,
3266c582b7e3Smrg	       save->feedback_div,
3267c582b7e3Smrg	       save->post_div));
3268c582b7e3Smrg
3269c582b7e3Smrg    save->ppll_ref_div   = pll->reference_div;
3270c582b7e3Smrg    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
3271c582b7e3Smrg    save->htotal_cntl    = 0;
3272c582b7e3Smrg
3273c582b7e3Smrg}
3274c582b7e3Smrg
3275c582b7e3Smrg/* Define PLL2 registers for requested video mode. */
3276b3ff493bSmrgvoid R128InitPLL2Registers(xf86CrtcPtr crtc, R128SavePtr save,
327784354367Smrg				   R128PLLPtr pll, double dot_clock)
3278c582b7e3Smrg{
3279b3ff493bSmrg#if R128_DEBUG
3280b3ff493bSmrg    ScrnInfoPtr pScrn  = crtc->scrn;
3281b3ff493bSmrg#endif
3282c582b7e3Smrg    unsigned long freq = dot_clock * 100;
3283c582b7e3Smrg    struct {
3284c582b7e3Smrg	int divider;
3285c582b7e3Smrg	int bitvalue;
3286c582b7e3Smrg    } *post_div,
3287c582b7e3Smrg      post_divs[]   = {
3288c582b7e3Smrg				/* From RAGE 128 VR/RAGE 128 GL Register
3289c582b7e3Smrg				   Reference Manual (Technical Reference
3290c582b7e3Smrg				   Manual P/N RRG-G04100-C Rev. 0.04), page
3291c582b7e3Smrg				   3-17 (PLL_DIV_[3:0]).  */
3292c582b7e3Smrg	{  1, 0 },              /* VCLK_SRC                 */
3293c582b7e3Smrg	{  2, 1 },              /* VCLK_SRC/2               */
3294c582b7e3Smrg	{  4, 2 },              /* VCLK_SRC/4               */
3295c582b7e3Smrg	{  8, 3 },              /* VCLK_SRC/8               */
3296c582b7e3Smrg
3297c582b7e3Smrg	{  3, 4 },              /* VCLK_SRC/3               */
3298c582b7e3Smrg				/* bitvalue = 5 is reserved */
3299c582b7e3Smrg	{  6, 6 },              /* VCLK_SRC/6               */
3300c582b7e3Smrg	{ 12, 7 },              /* VCLK_SRC/12              */
3301c582b7e3Smrg	{  0, 0 }
3302c582b7e3Smrg    };
3303c582b7e3Smrg
3304c582b7e3Smrg    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3305c582b7e3Smrg    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3306c582b7e3Smrg
3307c582b7e3Smrg    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3308c582b7e3Smrg	save->pll_output_freq_2 = post_div->divider * freq;
3309c582b7e3Smrg	if (save->pll_output_freq_2 >= pll->min_pll_freq
3310c582b7e3Smrg	    && save->pll_output_freq_2 <= pll->max_pll_freq) break;
3311c582b7e3Smrg    }
3312c582b7e3Smrg
3313c582b7e3Smrg    save->dot_clock_freq_2 = freq;
3314c582b7e3Smrg    save->feedback_div_2   = R128Div(pll->reference_div
3315c582b7e3Smrg				     * save->pll_output_freq_2,
3316c582b7e3Smrg				     pll->reference_freq);
3317c582b7e3Smrg    save->post_div_2       = post_div->divider;
3318c582b7e3Smrg
3319c582b7e3Smrg    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3320c582b7e3Smrg	       save->dot_clock_freq_2,
3321c582b7e3Smrg	       save->pll_output_freq_2,
3322c582b7e3Smrg	       save->feedback_div_2,
3323c582b7e3Smrg	       save->post_div_2));
3324c582b7e3Smrg
3325c582b7e3Smrg    save->p2pll_ref_div   = pll->reference_div;
3326c582b7e3Smrg    save->p2pll_div_0    = (save->feedback_div_2 | (post_div->bitvalue<<16));
3327c582b7e3Smrg    save->htotal_cntl2    = 0;
3328c582b7e3Smrg}
3329c582b7e3Smrg
3330c582b7e3Smrg/* Define DDA registers for requested video mode. */
3331b3ff493bSmrgBool R128InitDDARegisters(xf86CrtcPtr crtc, R128SavePtr save,
3332b3ff493bSmrg				 R128PLLPtr pll, DisplayModePtr mode)
3333c582b7e3Smrg{
3334b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
3335b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3336b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(crtc);
3337b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3338b3ff493bSmrg
3339c582b7e3Smrg    int         DisplayFifoWidth = 128;
3340c582b7e3Smrg    int         DisplayFifoDepth = 32;
3341c582b7e3Smrg    int         XclkFreq;
3342c582b7e3Smrg    int         VclkFreq;
3343c582b7e3Smrg    int         XclksPerTransfer;
3344c582b7e3Smrg    int         XclksPerTransferPrecise;
3345c582b7e3Smrg    int         UseablePrecision;
3346c582b7e3Smrg    int         Roff;
3347c582b7e3Smrg    int         Ron;
3348c582b7e3Smrg
3349c582b7e3Smrg    XclkFreq = pll->xclk;
3350c582b7e3Smrg
3351c582b7e3Smrg    VclkFreq = R128Div(pll->reference_freq * save->feedback_div,
3352c582b7e3Smrg		       pll->reference_div * save->post_div);
3353c582b7e3Smrg
3354b3ff493bSmrg    if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) {
3355b3ff493bSmrg        if (r128_output->PanelXRes != mode->CrtcHDisplay)
3356b3ff493bSmrg            VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes;
3357b3ff493bSmrg    }
3358c582b7e3Smrg
3359c582b7e3Smrg    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3360c582b7e3Smrg			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3361c582b7e3Smrg
3362c582b7e3Smrg    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3363c582b7e3Smrg
3364c582b7e3Smrg    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3365c582b7e3Smrg				      << (11 - UseablePrecision),
3366c582b7e3Smrg				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3367c582b7e3Smrg
3368c582b7e3Smrg    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3369c582b7e3Smrg
3370c582b7e3Smrg    Ron   = (4 * info->ram->MB
3371c582b7e3Smrg	     + 3 * MAX(info->ram->Trcd - 2, 0)
3372c582b7e3Smrg	     + 2 * info->ram->Trp
3373c582b7e3Smrg	     + info->ram->Twr
3374c582b7e3Smrg	     + info->ram->CL
3375c582b7e3Smrg	     + info->ram->Tr2w
3376c582b7e3Smrg	     + XclksPerTransfer) << (11 - UseablePrecision);
3377c582b7e3Smrg
3378c582b7e3Smrg    if (Ron + info->ram->Rloop >= Roff) {
3379c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3380c582b7e3Smrg		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3381c582b7e3Smrg		   Ron, info->ram->Rloop, Roff);
3382c582b7e3Smrg	return FALSE;
3383c582b7e3Smrg    }
3384c582b7e3Smrg
3385c582b7e3Smrg    save->dda_config = (XclksPerTransferPrecise
3386c582b7e3Smrg			| (UseablePrecision << 16)
3387c582b7e3Smrg			| (info->ram->Rloop << 20));
3388c582b7e3Smrg
3389c582b7e3Smrg    save->dda_on_off = (Ron << 16) | Roff;
3390c582b7e3Smrg
3391c582b7e3Smrg    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3392c582b7e3Smrg	       XclkFreq,
3393c582b7e3Smrg	       VclkFreq,
3394c582b7e3Smrg	       XclksPerTransfer,
3395c582b7e3Smrg	       XclksPerTransferPrecise,
3396c582b7e3Smrg	       UseablePrecision));
3397c582b7e3Smrg    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3398c582b7e3Smrg	       Roff, Ron, info->ram->Rloop));
3399c582b7e3Smrg
3400c582b7e3Smrg    return TRUE;
3401c582b7e3Smrg}
3402c582b7e3Smrg
3403c582b7e3Smrg/* Define DDA2 registers for requested video mode. */
3404b3ff493bSmrgBool R128InitDDA2Registers(xf86CrtcPtr crtc, R128SavePtr save,
3405b3ff493bSmrg				 R128PLLPtr pll, DisplayModePtr mode)
3406c582b7e3Smrg{
3407b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
3408b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3409b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(crtc);
3410b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3411b3ff493bSmrg
3412c582b7e3Smrg    int         DisplayFifoWidth = 128;
3413c582b7e3Smrg    int         DisplayFifoDepth = 32;
3414c582b7e3Smrg    int         XclkFreq;
3415c582b7e3Smrg    int         VclkFreq;
3416c582b7e3Smrg    int         XclksPerTransfer;
3417c582b7e3Smrg    int         XclksPerTransferPrecise;
3418c582b7e3Smrg    int         UseablePrecision;
3419c582b7e3Smrg    int         Roff;
3420c582b7e3Smrg    int         Ron;
3421c582b7e3Smrg
3422c582b7e3Smrg    XclkFreq = pll->xclk;
3423c582b7e3Smrg
3424c582b7e3Smrg    VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2,
3425c582b7e3Smrg		       pll->reference_div * save->post_div_2);
3426c582b7e3Smrg
3427b3ff493bSmrg    if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) {
3428b3ff493bSmrg        if (r128_output->PanelXRes != mode->CrtcHDisplay)
3429b3ff493bSmrg            VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes;
3430b3ff493bSmrg    }
3431c582b7e3Smrg
3432c582b7e3Smrg    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3433c582b7e3Smrg			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3434c582b7e3Smrg
3435c582b7e3Smrg    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3436c582b7e3Smrg
3437c582b7e3Smrg    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3438c582b7e3Smrg				      << (11 - UseablePrecision),
3439c582b7e3Smrg				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3440c582b7e3Smrg
3441c582b7e3Smrg    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3442c582b7e3Smrg
3443c582b7e3Smrg    Ron   = (4 * info->ram->MB
3444c582b7e3Smrg	     + 3 * MAX(info->ram->Trcd - 2, 0)
3445c582b7e3Smrg	     + 2 * info->ram->Trp
3446c582b7e3Smrg	     + info->ram->Twr
3447c582b7e3Smrg	     + info->ram->CL
3448c582b7e3Smrg	     + info->ram->Tr2w
3449c582b7e3Smrg	     + XclksPerTransfer) << (11 - UseablePrecision);
3450c582b7e3Smrg
3451c582b7e3Smrg
3452c582b7e3Smrg    if (Ron + info->ram->Rloop >= Roff) {
3453c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3454c582b7e3Smrg		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3455c582b7e3Smrg		   Ron, info->ram->Rloop, Roff);
3456c582b7e3Smrg	return FALSE;
3457c582b7e3Smrg    }
3458c582b7e3Smrg
3459c582b7e3Smrg    save->dda2_config = (XclksPerTransferPrecise
3460c582b7e3Smrg			| (UseablePrecision << 16)
3461c582b7e3Smrg			| (info->ram->Rloop << 20));
3462c582b7e3Smrg
3463c582b7e3Smrg    /*save->dda2_on_off = (Ron << 16) | Roff;*/
3464c582b7e3Smrg    /* shift most be 18 otherwise there's corruption on crtc2 */
3465c582b7e3Smrg    save->dda2_on_off = (Ron << 18) | Roff;
3466c582b7e3Smrg
3467c582b7e3Smrg    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3468c582b7e3Smrg	       XclkFreq,
3469c582b7e3Smrg	       VclkFreq,
3470c582b7e3Smrg	       XclksPerTransfer,
3471c582b7e3Smrg	       XclksPerTransferPrecise,
3472c582b7e3Smrg	       UseablePrecision));
3473c582b7e3Smrg    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3474c582b7e3Smrg	       Roff, Ron, info->ram->Rloop));
3475c582b7e3Smrg
3476c582b7e3Smrg    return TRUE;
3477c582b7e3Smrg}
3478c582b7e3Smrg
3479c582b7e3Smrg#if 0
3480c582b7e3Smrg/* Define initial palette for requested video mode.  This doesn't do
3481c582b7e3Smrg   anything for XFree86 4.0. */
3482c582b7e3Smrgstatic void R128InitPalette(R128SavePtr save)
3483c582b7e3Smrg{
3484c582b7e3Smrg    save->palette_valid = FALSE;
3485c582b7e3Smrg}
3486c582b7e3Smrg#endif
3487c582b7e3Smrg
3488c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode)
3489c582b7e3Smrg{
349084354367Smrg    ScrnInfoPtr   pScrn = xf86ScreenToScrn(pScreen);
3491c582b7e3Smrg    Bool unblank;
3492c582b7e3Smrg
3493c582b7e3Smrg    unblank = xf86IsUnblank(mode);
3494c582b7e3Smrg    if (unblank)
3495c582b7e3Smrg	SetTimeSinceLastInputEvent();
3496c582b7e3Smrg
3497c582b7e3Smrg    if ((pScrn != NULL) && pScrn->vtSema) {
3498c582b7e3Smrg	if (unblank)
3499c582b7e3Smrg		R128Unblank(pScrn);
3500c582b7e3Smrg	else
3501c582b7e3Smrg		R128Blank(pScrn);
3502c582b7e3Smrg    }
3503c582b7e3Smrg    return TRUE;
3504c582b7e3Smrg}
3505c582b7e3Smrg
3506c582b7e3Smrg/*
3507c582b7e3Smrg * SwitchMode() doesn't work right on crtc2 on some laptops.
3508c582b7e3Smrg * The workaround is to switch the mode, then switch to another VT, then
3509c582b7e3Smrg * switch back. --AGD
3510c582b7e3Smrg */
351184354367SmrgBool R128SwitchMode(SWITCH_MODE_ARGS_DECL)
3512c582b7e3Smrg{
351384354367Smrg    SCRN_INFO_PTR(arg);
3514c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
3515c582b7e3Smrg    Bool ret;
3516c582b7e3Smrg
3517c582b7e3Smrg    info->SwitchingMode = TRUE;
3518b3ff493bSmrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
3519c582b7e3Smrg    info->SwitchingMode = FALSE;
3520c582b7e3Smrg    return ret;
3521c582b7e3Smrg}
3522c582b7e3Smrg
3523b3ff493bSmrgModeStatus R128DoValidMode(xf86OutputPtr output, DisplayModePtr mode, int flags)
3524c582b7e3Smrg{
3525b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
3526b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3527b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3528b3ff493bSmrg    int i, j;
3529c582b7e3Smrg
3530b3ff493bSmrg    if (r128_output->MonType == MT_CRT)
3531b3ff493bSmrg        return MODE_OK;
3532c582b7e3Smrg
3533b3ff493bSmrg    if (r128_output->MonType == MT_DFP || r128_output->MonType == MT_LCD) {
3534c582b7e3Smrg	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
3535c582b7e3Smrg	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
3536c582b7e3Smrg    }
3537c582b7e3Smrg
3538b3ff493bSmrg    if (r128_output->MonType == MT_LCD && info->VBIOS) {
3539b3ff493bSmrg	for (i = info->FPBIOSstart + 64; R128_BIOS16(i) != 0; i += 2) {
3540b3ff493bSmrg	    j = R128_BIOS16(i);
3541c582b7e3Smrg
3542c582b7e3Smrg	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
3543b3ff493bSmrg		mode->CrtcVDisplay == R128_BIOS16(j + 2)) {
3544c582b7e3Smrg		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
3545c582b7e3Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3546c582b7e3Smrg			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
3547b3ff493bSmrg			       mode->CrtcHDisplay, mode->CrtcVDisplay,
3548b3ff493bSmrg			       (float)mode->Clock / 1000);
3549c582b7e3Smrg
3550c582b7e3Smrg		    /* Assume we are using expanded mode */
3551b3ff493bSmrg		    if (R128_BIOS16(j + 5)) j  = R128_BIOS16(j + 5);
3552b3ff493bSmrg		    else                    j += 9;
3553c582b7e3Smrg
3554b3ff493bSmrg		    mode->Clock = (uint32_t)R128_BIOS16(j) * 10;
3555c582b7e3Smrg
3556c582b7e3Smrg		    mode->HDisplay   = mode->CrtcHDisplay   =
3557b3ff493bSmrg			((R128_BIOS16(j + 10) & 0x01ff) + 1) * 8;
3558c582b7e3Smrg		    mode->HSyncStart = mode->CrtcHSyncStart =
3559b3ff493bSmrg			((R128_BIOS16(j + 12) & 0x01ff) + 1) * 8;
3560c582b7e3Smrg		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
3561b3ff493bSmrg			mode->CrtcHSyncStart + (R128_BIOS8(j + 14) & 0x1f);
3562c582b7e3Smrg		    mode->HTotal     = mode->CrtcHTotal     =
3563b3ff493bSmrg			((R128_BIOS16(j + 8)  & 0x01ff) + 1) * 8;
3564c582b7e3Smrg
3565c582b7e3Smrg		    mode->VDisplay   = mode->CrtcVDisplay   =
3566b3ff493bSmrg			(R128_BIOS16(j + 17) & 0x07ff) + 1;
3567c582b7e3Smrg		    mode->VSyncStart = mode->CrtcVSyncStart =
3568b3ff493bSmrg			(R128_BIOS16(j + 19) & 0x07ff) + 1;
3569c582b7e3Smrg		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
3570b3ff493bSmrg			mode->CrtcVSyncStart + ((R128_BIOS16(j + 19) >> 11) & 0x1f);
3571c582b7e3Smrg		    mode->VTotal     = mode->CrtcVTotal     =
3572b3ff493bSmrg			(R128_BIOS16(j + 15) & 0x07ff) + 1;
3573c582b7e3Smrg		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
3574c582b7e3Smrg			       mode->CrtcHDisplay,mode->CrtcVDisplay,
3575b3ff493bSmrg			       (float)mode->Clock/ 1000);
3576c582b7e3Smrg		}
3577c582b7e3Smrg		return MODE_OK;
3578c582b7e3Smrg	    }
3579c582b7e3Smrg	}
3580c582b7e3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
3581c582b7e3Smrg		       "Mode rejected for FP %ix%i [pclk: %.1f] "
3582c582b7e3Smrg		       "(not listed in VBIOS)\n",
3583c582b7e3Smrg		       mode->CrtcHDisplay, mode->CrtcVDisplay,
3584c582b7e3Smrg		       (float)mode->Clock / 1000);
3585c582b7e3Smrg	return MODE_NOMODE;
3586c582b7e3Smrg    }
3587c582b7e3Smrg
3588c582b7e3Smrg    return MODE_OK;
3589c582b7e3Smrg}
3590c582b7e3Smrg
3591b3ff493bSmrg/* Used to disallow modes that are not supported by the hardware. */
3592b3ff493bSmrgModeStatus R128ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
3593b3ff493bSmrg                                   Bool verbose, int flags)
3594b3ff493bSmrg{
3595b3ff493bSmrg    SCRN_INFO_PTR(arg);
3596b3ff493bSmrg    R128EntPtr  pR128Ent = R128EntPriv(pScrn);
3597b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
3598b3ff493bSmrg
3599b3ff493bSmrg    return R128DoValidMode(output, mode, flags);
3600b3ff493bSmrg}
3601b3ff493bSmrg
3602c582b7e3Smrg/* Adjust viewport into virtual desktop such that (0,0) in viewport space
3603c582b7e3Smrg   is (x,y) in virtual space. */
360484354367Smrgvoid R128AdjustFrame(ADJUST_FRAME_ARGS_DECL)
3605c582b7e3Smrg{
360684354367Smrg    SCRN_INFO_PTR(arg);
3607c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3608c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3609c582b7e3Smrg    int           Base;
3610c582b7e3Smrg
3611c582b7e3Smrg    if(info->showCache && y && pScrn->vtSema)
3612c582b7e3Smrg        y += pScrn->virtualY - 1;
3613c582b7e3Smrg
3614c582b7e3Smrg    Base = y * info->CurrentLayout.displayWidth + x;
3615c582b7e3Smrg
3616c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3617c582b7e3Smrg    case 15:
3618c582b7e3Smrg    case 16: Base *= 2; break;
3619c582b7e3Smrg    case 24: Base *= 3; break;
3620c582b7e3Smrg    case 32: Base *= 4; break;
3621c582b7e3Smrg    }
3622c582b7e3Smrg
3623c582b7e3Smrg    Base &= ~7;                 /* 3 lower bits are always 0 */
3624c582b7e3Smrg
3625c582b7e3Smrg    if (info->CurrentLayout.pixel_code == 24)
3626c582b7e3Smrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
3627c582b7e3Smrg
3628c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET, Base);
3629c582b7e3Smrg}
3630c582b7e3Smrg
3631c582b7e3Smrg/* Called when VT switching back to the X server.  Reinitialize the video
3632c582b7e3Smrg   mode. */
363384354367SmrgBool R128EnterVT(VT_FUNC_ARGS_DECL)
3634c582b7e3Smrg{
363584354367Smrg    SCRN_INFO_PTR(arg);
3636c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
3637c582b7e3Smrg
3638c582b7e3Smrg    R128TRACE(("R128EnterVT\n"));
3639b3ff493bSmrg
3640b3ff493bSmrg    pScrn->vtSema = TRUE;
364179e5230eSmacallan#ifndef AVOID_FBDEV
3642c582b7e3Smrg    if (info->FBDev) {
364384354367Smrg        if (!fbdevHWEnterVT(VT_FUNC_ARGS)) return FALSE;
36443c921f55Smrg    } else {
364579e5230eSmacallan#endif
36463c921f55Smrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
36473c921f55Smrg#ifndef AVOID_FBDEV
3648b3ff493bSmrg    }
36493c921f55Smrg#endif
3650b3ff493bSmrg
3651c582b7e3Smrg    if (info->accelOn)
3652c582b7e3Smrg	R128EngineInit(pScrn);
3653c582b7e3Smrg
365484354367Smrg#ifdef R128DRI
3655c582b7e3Smrg    if (info->directRenderingEnabled) {
3656c582b7e3Smrg	if (info->irq) {
3657c582b7e3Smrg	    /* Need to make sure interrupts are enabled */
3658c582b7e3Smrg	    unsigned char *R128MMIO = info->MMIO;
3659c582b7e3Smrg	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
3660c582b7e3Smrg	}
3661c582b7e3Smrg	R128CCE_START(pScrn, info);
3662c582b7e3Smrg	DRIUnlock(pScrn->pScreen);
3663c582b7e3Smrg    }
3664c582b7e3Smrg#endif
3665c582b7e3Smrg
3666c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
3667b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3668c582b7e3Smrg
3669c582b7e3Smrg    return TRUE;
3670c582b7e3Smrg}
3671c582b7e3Smrg
3672c582b7e3Smrg/* Called when VT switching away from the X server.  Restore the original
3673c582b7e3Smrg   text mode. */
367484354367Smrgvoid R128LeaveVT(VT_FUNC_ARGS_DECL)
3675c582b7e3Smrg{
367684354367Smrg    SCRN_INFO_PTR(arg);
3677c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
3678c582b7e3Smrg    R128SavePtr save  = &info->ModeReg;
3679c582b7e3Smrg
3680c582b7e3Smrg    R128TRACE(("R128LeaveVT\n"));
368184354367Smrg#ifdef R128DRI
3682c582b7e3Smrg    if (info->directRenderingEnabled) {
3683c582b7e3Smrg	DRILock(pScrn->pScreen, 0);
3684c582b7e3Smrg	R128CCE_STOP(pScrn, info);
3685c582b7e3Smrg    }
368684354367Smrg#ifdef USE_EXA
368784354367Smrg    if (info->useEXA)
368884354367Smrg        info->state_2d.composite_setup = FALSE;
368984354367Smrg#endif
3690c582b7e3Smrg#endif
3691c582b7e3Smrg    R128SavePalette(pScrn, save);
3692c582b7e3Smrg    info->PaletteSavedOnVT = TRUE;
369379e5230eSmacallan#ifndef AVOID_FBDEV
3694c582b7e3Smrg    if (info->FBDev)
369584354367Smrg        fbdevHWLeaveVT(VT_FUNC_ARGS);
3696c582b7e3Smrg    else
369779e5230eSmacallan#endif
3698c582b7e3Smrg        R128Restore(pScrn);
3699c582b7e3Smrg}
3700c582b7e3Smrg
3701c582b7e3Smrg
3702c582b7e3Smrg/* Called at the end of each server generation.  Restore the original text
3703c582b7e3Smrg   mode, unmap video memory, and unwrap and call the saved CloseScreen
3704c582b7e3Smrg   function.  */
370584354367Smrgstatic Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL)
3706c582b7e3Smrg{
370784354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3708c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
3709c582b7e3Smrg
3710c582b7e3Smrg    R128TRACE(("R128CloseScreen\n"));
3711c582b7e3Smrg
371284354367Smrg#ifdef R128DRI
3713c582b7e3Smrg				/* Disable direct rendering */
3714c582b7e3Smrg    if (info->directRenderingEnabled) {
3715c582b7e3Smrg	R128DRICloseScreen(pScreen);
3716c582b7e3Smrg	info->directRenderingEnabled = FALSE;
3717c582b7e3Smrg    }
3718c582b7e3Smrg#endif
3719c582b7e3Smrg
3720c582b7e3Smrg    if (pScrn->vtSema) {
3721c582b7e3Smrg	R128Restore(pScrn);
3722c582b7e3Smrg	R128UnmapMem(pScrn);
3723c582b7e3Smrg    }
3724c582b7e3Smrg
372584354367Smrg#ifdef USE_EXA
372684354367Smrg        if (info->useEXA) {
372784354367Smrg	    exaDriverFini(pScreen);
372884354367Smrg	    free(info->ExaDriver);
372984354367Smrg	} else
373084354367Smrg#endif
373184354367Smrg#ifdef HAVE_XAA_H
373284354367Smrg	{
373384354367Smrg            if (info->accel)             XAADestroyInfoRec(info->accel);
373484354367Smrg	    info->accel                  = NULL;
373584354367Smrg        }
373684354367Smrg#endif
3737c582b7e3Smrg
373884354367Smrg    if (info->scratch_save)      free(info->scratch_save);
3739c582b7e3Smrg    info->scratch_save           = NULL;
3740c582b7e3Smrg
3741c582b7e3Smrg    if (info->adaptor) {
374284354367Smrg        free(info->adaptor->pPortPrivates[0].ptr);
3743c582b7e3Smrg	xf86XVFreeVideoAdaptorRec(info->adaptor);
3744c582b7e3Smrg	info->adaptor = NULL;
3745c582b7e3Smrg    }
3746c582b7e3Smrg
3747c582b7e3Smrg    pScrn->vtSema = FALSE;
3748c582b7e3Smrg
3749c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
3750c582b7e3Smrg    pScreen->CloseScreen = info->CloseScreen;
375184354367Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3752c582b7e3Smrg}
3753c582b7e3Smrg
375484354367Smrgvoid R128FreeScreen(FREE_SCREEN_ARGS_DECL)
3755c582b7e3Smrg{
375684354367Smrg    SCRN_INFO_PTR(arg);
3757c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3758c582b7e3Smrg
3759c582b7e3Smrg    R128TRACE(("R128FreeScreen\n"));
376019019ffeSmrg    if (info == NULL)
376119019ffeSmrg	return;
3762c582b7e3Smrg#ifdef WITH_VGAHW
3763c582b7e3Smrg    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
3764c582b7e3Smrg	vgaHWFreeHWRec(pScrn);
3765c582b7e3Smrg#endif
3766c582b7e3Smrg    R128FreeRec(pScrn);
3767c582b7e3Smrg}
3768