r128_driver.c revision 5ef9b84e
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
28005ef9b84eSmacallan    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
28015ef9b84eSmacallan    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
28025ef9b84eSmacallan    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
28035ef9b84eSmacallan    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
28045ef9b84eSmacallan    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
28059e881af1Smacallan
2806c582b7e3Smrg#ifdef WITH_VGAHW
2807c582b7e3Smrg    if (info->VGAAccess) {
2808c582b7e3Smrg        vgaHWPtr hwp = VGAHWPTR(pScrn);
2809b3ff493bSmrg        vgaHWUnlock(hwp);
2810c582b7e3Smrg# if defined(__powerpc__)
2811b3ff493bSmrg        /* Temporary hack to prevent crashing on PowerMacs when trying to
2812b3ff493bSmrg         * write VGA fonts, will find a better solution in the future
2813b3ff493bSmrg         */
2814b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
2815c582b7e3Smrg# else
2816b3ff493bSmrg        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
2817c582b7e3Smrg# endif
2818b3ff493bSmrg        vgaHWLock(hwp);
2819c582b7e3Smrg    }
2820c582b7e3Smrg#endif
2821c582b7e3Smrg
2822c582b7e3Smrg    R128WaitForVerticalSync(pScrn);
2823c582b7e3Smrg    R128Unblank(pScrn);
2824c582b7e3Smrg}
2825c582b7e3Smrg
2826c582b7e3Smrg/* Define common registers for requested video mode. */
2827b3ff493bSmrgvoid R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
2828c582b7e3Smrg{
2829c582b7e3Smrg    save->ovr_clr            = 0;
2830c582b7e3Smrg    save->ovr_wid_left_right = 0;
2831c582b7e3Smrg    save->ovr_wid_top_bottom = 0;
2832c582b7e3Smrg    save->ov0_scale_cntl     = 0;
2833c582b7e3Smrg    save->mpp_tb_config      = 0;
2834c582b7e3Smrg    save->mpp_gp_config      = 0;
2835c582b7e3Smrg    save->subpic_cntl        = 0;
2836c582b7e3Smrg    save->viph_control       = 0;
2837c582b7e3Smrg    save->i2c_cntl_1         = 0;
283884354367Smrg#ifdef R128DRI
2839c582b7e3Smrg    save->gen_int_cntl       = info->gen_int_cntl;
2840c582b7e3Smrg#else
2841c582b7e3Smrg    save->gen_int_cntl       = 0;
2842c582b7e3Smrg#endif
2843c582b7e3Smrg    save->cap0_trig_cntl     = 0;
2844c582b7e3Smrg    save->cap1_trig_cntl     = 0;
2845c582b7e3Smrg    save->bus_cntl           = info->BusCntl;
2846c582b7e3Smrg    /*
2847c582b7e3Smrg     * If bursts are enabled, turn on discards and aborts
2848c582b7e3Smrg     */
2849c582b7e3Smrg    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
2850c582b7e3Smrg	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
2851c582b7e3Smrg}
2852c582b7e3Smrg
2853b3ff493bSmrgBool R128InitCrtcBase(xf86CrtcPtr crtc, R128SavePtr save, int x, int y)
2854b3ff493bSmrg{
2855b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
2856b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2857b3ff493bSmrg    int offset = y * info->CurrentLayout.displayWidth + x;
2858b3ff493bSmrg    int Base = pScrn->fbOffset;
2859b3ff493bSmrg
2860b3ff493bSmrg    switch (info->CurrentLayout.pixel_code) {
2861b3ff493bSmrg    case 15:
2862b3ff493bSmrg    case 16: offset *= 2; break;
2863b3ff493bSmrg    case 24: offset *= 3; break;
2864b3ff493bSmrg    case 32: offset *= 4; break;
2865b3ff493bSmrg    }
2866b3ff493bSmrg    Base += offset;
2867b3ff493bSmrg
2868b3ff493bSmrg    if (crtc->rotatedData != NULL)
2869b3ff493bSmrg        Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
2870b3ff493bSmrg
2871b3ff493bSmrg    Base &= ~7;                 /* 3 lower bits are always 0 */
2872b3ff493bSmrg    if (info->CurrentLayout.pixel_code == 24)
2873b3ff493bSmrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2874b3ff493bSmrg
2875b3ff493bSmrg    save->crtc_offset = Base;
2876b3ff493bSmrg    save->crtc_offset_cntl = 0;
2877b3ff493bSmrg
2878b3ff493bSmrg    return TRUE;
2879b3ff493bSmrg}
2880b3ff493bSmrg
2881b3ff493bSmrgBool R128InitCrtc2Base(xf86CrtcPtr crtc, R128SavePtr save, int x, int y)
2882b3ff493bSmrg{
2883b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
2884b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2885b3ff493bSmrg    int offset = y * info->CurrentLayout.displayWidth + x;
2886b3ff493bSmrg    int Base = pScrn->fbOffset;
2887b3ff493bSmrg
2888b3ff493bSmrg    switch (info->CurrentLayout.pixel_code) {
2889b3ff493bSmrg    case 15:
2890b3ff493bSmrg    case 16: offset *= 2; break;
2891b3ff493bSmrg    case 24: offset *= 3; break;
2892b3ff493bSmrg    case 32: offset *= 4; break;
2893b3ff493bSmrg    }
2894b3ff493bSmrg    Base += offset;
2895b3ff493bSmrg
2896b3ff493bSmrg    if (crtc->rotatedData != NULL)
2897b3ff493bSmrg        Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB;
2898b3ff493bSmrg
2899b3ff493bSmrg    Base &= ~7;                 /* 3 lower bits are always 0 */
2900b3ff493bSmrg    if (info->CurrentLayout.pixel_code == 24)
2901b3ff493bSmrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2902b3ff493bSmrg
2903b3ff493bSmrg    save->crtc2_offset = Base;
2904b3ff493bSmrg    save->crtc2_offset_cntl = 0;
2905b3ff493bSmrg
2906b3ff493bSmrg    return TRUE;
2907b3ff493bSmrg}
2908b3ff493bSmrg
2909c582b7e3Smrg/* Define CRTC registers for requested video mode. */
2910b3ff493bSmrgBool R128InitCrtcRegisters(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode)
2911c582b7e3Smrg{
2912b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
2913b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
2914b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(crtc);
2915b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
2916b3ff493bSmrg
2917c582b7e3Smrg    int    format;
2918c582b7e3Smrg    int    hsync_start;
2919c582b7e3Smrg    int    hsync_wid;
2920c582b7e3Smrg    int    hsync_fudge;
2921c582b7e3Smrg    int    vsync_wid;
2922c582b7e3Smrg    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
2923c582b7e3Smrg    int    hsync_fudge_fp[]      = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
2924c582b7e3Smrg//   int    hsync_fudge_fp_crt[]  = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
2925c582b7e3Smrg
2926c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
2927c582b7e3Smrg    case 4:  format = 1; break;
2928c582b7e3Smrg    case 8:  format = 2; break;
2929c582b7e3Smrg    case 15: format = 3; break;      /*  555 */
2930c582b7e3Smrg    case 16: format = 4; break;      /*  565 */
2931c582b7e3Smrg    case 24: format = 5; break;      /*  RGB */
2932c582b7e3Smrg    case 32: format = 6; break;      /* xRGB */
2933c582b7e3Smrg    default:
2934c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2935c582b7e3Smrg		   "Unsupported pixel depth (%d)\n",
2936c582b7e3Smrg		   info->CurrentLayout.bitsPerPixel);
2937c582b7e3Smrg	return FALSE;
2938c582b7e3Smrg    }
2939c582b7e3Smrg
2940b3ff493bSmrg    if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP)
2941c582b7e3Smrg	hsync_fudge = hsync_fudge_fp[format-1];
2942c582b7e3Smrg    else
2943c582b7e3Smrg        hsync_fudge = hsync_fudge_default[format-1];
2944c582b7e3Smrg
2945c582b7e3Smrg    save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN
2946c582b7e3Smrg			  | R128_CRTC_EN
2947c582b7e3Smrg			  | (format << 8)
2948c582b7e3Smrg			  | ((mode->Flags & V_DBLSCAN)
2949c582b7e3Smrg			     ? R128_CRTC_DBL_SCAN_EN
2950c582b7e3Smrg			     : 0)
2951c582b7e3Smrg			  | ((mode->Flags & V_INTERLACE)
2952c582b7e3Smrg			     ? R128_CRTC_INTERLACE_EN
2953c582b7e3Smrg			     : 0)
2954c582b7e3Smrg			  | ((mode->Flags & V_CSYNC)
2955c582b7e3Smrg			     ? R128_CRTC_CSYNC_EN
2956c582b7e3Smrg			     : 0));
2957c582b7e3Smrg
2958b3ff493bSmrg    if (r128_output->MonType == MT_LCD || r128_output->MonType == MT_DFP)
2959b3ff493bSmrg        save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | R128_CRTC_INTERLACE_EN);
2960c582b7e3Smrg
2961b3ff493bSmrg    save->crtc_ext_cntl |= R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN;
2962c582b7e3Smrg
2963c582b7e3Smrg    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
2964c582b7e3Smrg			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
2965c582b7e3Smrg
2966c582b7e3Smrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
2967c582b7e3Smrg    if (!hsync_wid)       hsync_wid = 1;
2968c582b7e3Smrg    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
2969c582b7e3Smrg
2970c582b7e3Smrg    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
2971c582b7e3Smrg
2972c582b7e3Smrg    save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff)
2973c582b7e3Smrg				 | (hsync_wid << 16)
2974c582b7e3Smrg				 | ((mode->Flags & V_NHSYNC)
2975c582b7e3Smrg				    ? R128_CRTC_H_SYNC_POL
2976c582b7e3Smrg				    : 0));
2977c582b7e3Smrg
2978c582b7e3Smrg#if 1
2979c582b7e3Smrg				/* This works for double scan mode. */
2980c582b7e3Smrg    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
2981c582b7e3Smrg			      | ((mode->CrtcVDisplay - 1) << 16));
2982c582b7e3Smrg#else
2983c582b7e3Smrg				/* This is what cce/nbmode.c example code
2984c582b7e3Smrg				   does -- is this correct? */
2985c582b7e3Smrg    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
2986c582b7e3Smrg			      | ((mode->CrtcVDisplay
2987c582b7e3Smrg				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
2988c582b7e3Smrg				 << 16));
2989c582b7e3Smrg#endif
2990c582b7e3Smrg
2991c582b7e3Smrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
2992c582b7e3Smrg    if (!vsync_wid)       vsync_wid = 1;
2993c582b7e3Smrg    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
2994c582b7e3Smrg
2995c582b7e3Smrg    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
2996c582b7e3Smrg				 | (vsync_wid << 16)
2997c582b7e3Smrg				 | ((mode->Flags & V_NVSYNC)
2998c582b7e3Smrg				    ? R128_CRTC_V_SYNC_POL
2999c582b7e3Smrg				    : 0));
3000c582b7e3Smrg    save->crtc_pitch       = info->CurrentLayout.displayWidth / 8;
3001c582b7e3Smrg
3002c582b7e3Smrg    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3003c582b7e3Smrg	       save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth));
3004c582b7e3Smrg
3005c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
3006c582b7e3Smrg    /* Change the endianness of the aperture */
3007c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3008c582b7e3Smrg    case 15:
3009c582b7e3Smrg    case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break;
3010c582b7e3Smrg    case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break;
3011c582b7e3Smrg    default: break;
3012c582b7e3Smrg    }
3013c582b7e3Smrg#endif
3014c582b7e3Smrg
3015c582b7e3Smrg    return TRUE;
3016c582b7e3Smrg}
3017c582b7e3Smrg
3018c582b7e3Smrg/* Define CRTC2 registers for requested video mode. */
3019b3ff493bSmrgBool R128InitCrtc2Registers(xf86CrtcPtr crtc, R128SavePtr save, DisplayModePtr mode)
3020c582b7e3Smrg{
3021b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
3022b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3023b3ff493bSmrg
3024c582b7e3Smrg    int    format;
3025c582b7e3Smrg    int    hsync_start;
3026c582b7e3Smrg    int    hsync_wid;
3027c582b7e3Smrg    int    hsync_fudge;
3028c582b7e3Smrg    int    vsync_wid;
3029c582b7e3Smrg    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
3030c582b7e3Smrg
3031c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3032b3ff493bSmrg    case 4:  format = 1; break;
3033b3ff493bSmrg    case 8:  format = 2; break;
3034b3ff493bSmrg    case 15: format = 3; break;      /*  555 */
3035b3ff493bSmrg    case 16: format = 4; break;      /*  565 */
3036b3ff493bSmrg    case 24: format = 5; break;      /*  RGB */
3037b3ff493bSmrg    case 32: format = 6; break;      /* xRGB */
3038c582b7e3Smrg    default:
3039c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3040c582b7e3Smrg		   "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel);
3041c582b7e3Smrg	return FALSE;
3042c582b7e3Smrg    }
3043c582b7e3Smrg
3044c582b7e3Smrg    hsync_fudge = hsync_fudge_default[format-1];
3045c582b7e3Smrg
3046c582b7e3Smrg    save->crtc2_gen_cntl = (R128_CRTC2_EN
3047c582b7e3Smrg			  | (format << 8)
3048c582b7e3Smrg			  | ((mode->Flags & V_DBLSCAN)
3049c582b7e3Smrg			     ? R128_CRTC2_DBL_SCAN_EN
3050c582b7e3Smrg			     : 0));
3051c582b7e3Smrg/*
3052c582b7e3Smrg    save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN;
3053c582b7e3Smrg    save->crtc2_gen_cntl |= (1 << 21);
3054c582b7e3Smrg*/
3055c582b7e3Smrg    save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
3056c582b7e3Smrg			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
3057c582b7e3Smrg
3058c582b7e3Smrg    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
3059c582b7e3Smrg    if (!hsync_wid)       hsync_wid = 1;
3060c582b7e3Smrg    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
3061c582b7e3Smrg
3062c582b7e3Smrg    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
3063c582b7e3Smrg
3064c582b7e3Smrg    save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff)
3065c582b7e3Smrg				 | (hsync_wid << 16)
3066c582b7e3Smrg				 | ((mode->Flags & V_NHSYNC)
3067c582b7e3Smrg				    ? R128_CRTC2_H_SYNC_POL
3068c582b7e3Smrg				    : 0));
3069c582b7e3Smrg
3070c582b7e3Smrg#if 1
3071c582b7e3Smrg				/* This works for double scan mode. */
3072c582b7e3Smrg    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3073c582b7e3Smrg			      | ((mode->CrtcVDisplay - 1) << 16));
3074c582b7e3Smrg#else
3075c582b7e3Smrg				/* This is what cce/nbmode.c example code
3076c582b7e3Smrg				   does -- is this correct? */
3077c582b7e3Smrg    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3078c582b7e3Smrg			      | ((mode->CrtcVDisplay
3079c582b7e3Smrg				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
3080c582b7e3Smrg				 << 16));
3081c582b7e3Smrg#endif
3082c582b7e3Smrg
3083c582b7e3Smrg    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
3084c582b7e3Smrg    if (!vsync_wid)       vsync_wid = 1;
3085c582b7e3Smrg    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
3086c582b7e3Smrg
3087c582b7e3Smrg    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3088c582b7e3Smrg				 | (vsync_wid << 16)
3089c582b7e3Smrg				 | ((mode->Flags & V_NVSYNC)
3090c582b7e3Smrg				    ? R128_CRTC2_V_SYNC_POL
3091c582b7e3Smrg				    : 0));
3092c582b7e3Smrg    save->crtc2_pitch       = info->CurrentLayout.displayWidth / 8;
3093c582b7e3Smrg
3094c582b7e3Smrg    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3095c582b7e3Smrg		 save->crtc2_pitch, pScrn->virtualX,
3096c582b7e3Smrg		 info->CurrentLayout.displayWidth));
3097c582b7e3Smrg    return TRUE;
3098c582b7e3Smrg}
3099c582b7e3Smrg
3100b3ff493bSmrg/* Define DAC registers for the requested video mode. */
3101b3ff493bSmrgvoid R128InitDACRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
3102b3ff493bSmrg{
3103b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
3104b3ff493bSmrg    R128InfoPtr info = R128PTR(pScrn);
3105b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
3106b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
3107b3ff493bSmrg
3108b3ff493bSmrg    save->dac_cntl = (R128_DAC_MASK_ALL | R128_DAC_VGA_ADR_EN |
3109b3ff493bSmrg                      (!r128_crtc->crtc_id ? 0 : R128_DAC_CRT_SEL_CRTC2) |
3110b3ff493bSmrg                      (info->dac6bits      ? 0 : R128_DAC_8BIT_EN));
3111b3ff493bSmrg}
3112b3ff493bSmrg
3113b3ff493bSmrg/* Define RMX registers for the requested video mode. */
3114b3ff493bSmrgvoid R128InitRMXRegisters(R128SavePtr orig, R128SavePtr save,
3115b3ff493bSmrg                          xf86OutputPtr output, DisplayModePtr mode)
3116c582b7e3Smrg{
3117b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3118b3ff493bSmrg
3119c582b7e3Smrg    int   xres = mode->CrtcHDisplay;
3120c582b7e3Smrg    int   yres = mode->CrtcVDisplay;
3121c582b7e3Smrg    float Hratio, Vratio;
3122c582b7e3Smrg
3123b3ff493bSmrg    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
3124b3ff493bSmrg    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
3125b3ff493bSmrg    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
3126b3ff493bSmrg    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
3127b3ff493bSmrg
3128b3ff493bSmrg    if (r128_output->MonType != MT_DFP && r128_output->MonType != MT_LCD)
3129c582b7e3Smrg        return;
3130c582b7e3Smrg
3131b3ff493bSmrg    if (r128_output->PanelXRes == 0 || r128_output->PanelYRes == 0) {
3132b3ff493bSmrg        xres = r128_output->PanelXRes;
3133b3ff493bSmrg        yres = r128_output->PanelYRes;
3134b3ff493bSmrg
3135b3ff493bSmrg        Hratio = 1.0;
3136b3ff493bSmrg        Vratio = 1.0;
3137b3ff493bSmrg    } else {
3138b3ff493bSmrg        if (xres > r128_output->PanelXRes) xres = r128_output->PanelXRes;
3139b3ff493bSmrg        if (yres > r128_output->PanelYRes) yres = r128_output->PanelYRes;
3140c582b7e3Smrg
3141b3ff493bSmrg        Hratio = (float)xres/(float)r128_output->PanelXRes;
3142b3ff493bSmrg        Vratio = (float)yres/(float)r128_output->PanelYRes;
3143b3ff493bSmrg    }
3144c582b7e3Smrg
3145c582b7e3Smrg    save->fp_horz_stretch =
3146c582b7e3Smrg	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
3147c582b7e3Smrg	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
3148c582b7e3Smrg       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
3149c582b7e3Smrg                                 R128_HORZ_FP_LOOP_STRETCH |
3150c582b7e3Smrg                                 R128_HORZ_STRETCH_RESERVED)));
3151c582b7e3Smrg    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
3152c582b7e3Smrg    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
3153b3ff493bSmrg    if (xres == r128_output->PanelXRes)
3154c582b7e3Smrg         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3155c582b7e3Smrg    else
3156c582b7e3Smrg         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3157c582b7e3Smrg
3158c582b7e3Smrg    save->fp_vert_stretch =
3159c582b7e3Smrg	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
3160c582b7e3Smrg	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
3161c582b7e3Smrg	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
3162c582b7e3Smrg				   R128_VERT_STRETCH_RESERVED)));
3163c582b7e3Smrg    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
3164b3ff493bSmrg    if (yres == r128_output->PanelYRes)
3165c582b7e3Smrg        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3166c582b7e3Smrg    else
3167c582b7e3Smrg        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3168b3ff493bSmrg}
3169c582b7e3Smrg
3170b3ff493bSmrg/* Define flat panel registers for the requested video mode. */
3171b3ff493bSmrgvoid R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
3172b3ff493bSmrg{
3173b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
3174b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
3175c582b7e3Smrg
3176c582b7e3Smrg    /* WARNING: Be careful about turning on the flat panel */
3177b3ff493bSmrg    save->fp_gen_cntl            = orig->fp_gen_cntl;
3178b3ff493bSmrg    save->fp_panel_cntl          = orig->fp_panel_cntl;
3179b3ff493bSmrg    save->tmds_transmitter_cntl  = orig->tmds_transmitter_cntl;
3180b3ff493bSmrg    save->tmds_crc               = orig->tmds_crc;
3181b3ff493bSmrg
3182b3ff493bSmrg    if (r128_crtc->crtc_id)
3183b3ff493bSmrg        save->fp_gen_cntl       |=   R128_FP_SEL_CRTC2;
3184c582b7e3Smrg    else
3185b3ff493bSmrg        save->fp_gen_cntl       &=  ~R128_FP_SEL_CRTC2;
3186c582b7e3Smrg
3187b3ff493bSmrg    save->fp_gen_cntl           &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
3188b3ff493bSmrg                                     R128_FP_CRTC_USE_SHADOW_ROWCUR |
3189b3ff493bSmrg                                     R128_FP_CRTC_HORZ_DIV2_EN |
3190b3ff493bSmrg                                     R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3191b3ff493bSmrg                                     R128_FP_CRT_SYNC_SEL |
3192b3ff493bSmrg                                     R128_FP_USE_SHADOW_EN);
3193b3ff493bSmrg
3194b3ff493bSmrg    save->fp_gen_cntl           |=  (R128_FP_CRTC_DONT_SHADOW_VPAR |
3195b3ff493bSmrg                                     R128_FP_CRTC_DONT_SHADOW_HEND);
3196b3ff493bSmrg
3197b3ff493bSmrg    save->fp_panel_cntl         |=  (R128_FP_DIGON | R128_FP_BLON);
3198b3ff493bSmrg    save->tmds_transmitter_cntl &=  ~R128_TMDS_PLLRST;
3199b3ff493bSmrg    save->tmds_transmitter_cntl |=   R128_TMDS_PLLEN;
3200b3ff493bSmrg}
3201b3ff493bSmrg
3202b3ff493bSmrg/* Define LVDS registers for the requested video mode. */
3203b3ff493bSmrgvoid R128InitLVDSRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
3204b3ff493bSmrg{
3205b3ff493bSmrg    xf86CrtcPtr crtc = output->crtc;
3206b3ff493bSmrg    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
3207b3ff493bSmrg
3208b3ff493bSmrg    save->lvds_gen_cntl      =  orig->lvds_gen_cntl;
3209b3ff493bSmrg
3210b3ff493bSmrg    if (r128_crtc->crtc_id)
3211b3ff493bSmrg        save->lvds_gen_cntl |=  R128_LVDS_SEL_CRTC2;
3212b3ff493bSmrg    else
3213b3ff493bSmrg        save->lvds_gen_cntl &= ~R128_LVDS_SEL_CRTC2;
3214c582b7e3Smrg}
3215c582b7e3Smrg
3216c582b7e3Smrg/* Define PLL registers for requested video mode. */
3217b3ff493bSmrgvoid R128InitPLLRegisters(xf86CrtcPtr crtc, R128SavePtr save,
3218c582b7e3Smrg				R128PLLPtr pll, double dot_clock)
3219c582b7e3Smrg{
3220b3ff493bSmrg#if R128_DEBUG
3221b3ff493bSmrg    ScrnInfoPtr pScrn  = crtc->scrn;
3222b3ff493bSmrg#endif
3223c582b7e3Smrg    unsigned long freq = dot_clock * 100;
3224c582b7e3Smrg    struct {
3225c582b7e3Smrg	int divider;
3226c582b7e3Smrg	int bitvalue;
3227c582b7e3Smrg    } *post_div,
3228c582b7e3Smrg      post_divs[]   = {
3229c582b7e3Smrg				/* From RAGE 128 VR/RAGE 128 GL Register
3230c582b7e3Smrg				   Reference Manual (Technical Reference
3231c582b7e3Smrg				   Manual P/N RRG-G04100-C Rev. 0.04), page
3232c582b7e3Smrg				   3-17 (PLL_DIV_[3:0]).  */
3233c582b7e3Smrg	{  1, 0 },              /* VCLK_SRC                 */
3234c582b7e3Smrg	{  2, 1 },              /* VCLK_SRC/2               */
3235c582b7e3Smrg	{  4, 2 },              /* VCLK_SRC/4               */
3236c582b7e3Smrg	{  8, 3 },              /* VCLK_SRC/8               */
3237c582b7e3Smrg
3238c582b7e3Smrg	{  3, 4 },              /* VCLK_SRC/3               */
3239c582b7e3Smrg				/* bitvalue = 5 is reserved */
3240c582b7e3Smrg	{  6, 6 },              /* VCLK_SRC/6               */
3241c582b7e3Smrg	{ 12, 7 },              /* VCLK_SRC/12              */
3242c582b7e3Smrg	{  0, 0 }
3243c582b7e3Smrg    };
3244c582b7e3Smrg
3245c582b7e3Smrg    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3246c582b7e3Smrg    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3247c582b7e3Smrg
3248c582b7e3Smrg    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3249c582b7e3Smrg	save->pll_output_freq = post_div->divider * freq;
3250c582b7e3Smrg	if (save->pll_output_freq >= pll->min_pll_freq
3251c582b7e3Smrg	    && save->pll_output_freq <= pll->max_pll_freq) break;
3252c582b7e3Smrg    }
3253c582b7e3Smrg
3254c582b7e3Smrg    save->dot_clock_freq = freq;
3255c582b7e3Smrg    save->feedback_div   = R128Div(pll->reference_div * save->pll_output_freq,
3256c582b7e3Smrg				   pll->reference_freq);
3257c582b7e3Smrg    save->post_div       = post_div->divider;
3258c582b7e3Smrg
3259c582b7e3Smrg    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3260c582b7e3Smrg	       save->dot_clock_freq,
3261c582b7e3Smrg	       save->pll_output_freq,
3262c582b7e3Smrg	       save->feedback_div,
3263c582b7e3Smrg	       save->post_div));
3264c582b7e3Smrg
3265c582b7e3Smrg    save->ppll_ref_div   = pll->reference_div;
3266c582b7e3Smrg    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
3267c582b7e3Smrg    save->htotal_cntl    = 0;
3268c582b7e3Smrg
3269c582b7e3Smrg}
3270c582b7e3Smrg
3271c582b7e3Smrg/* Define PLL2 registers for requested video mode. */
3272b3ff493bSmrgvoid R128InitPLL2Registers(xf86CrtcPtr crtc, R128SavePtr save,
327384354367Smrg				   R128PLLPtr pll, double dot_clock)
3274c582b7e3Smrg{
3275b3ff493bSmrg#if R128_DEBUG
3276b3ff493bSmrg    ScrnInfoPtr pScrn  = crtc->scrn;
3277b3ff493bSmrg#endif
3278c582b7e3Smrg    unsigned long freq = dot_clock * 100;
3279c582b7e3Smrg    struct {
3280c582b7e3Smrg	int divider;
3281c582b7e3Smrg	int bitvalue;
3282c582b7e3Smrg    } *post_div,
3283c582b7e3Smrg      post_divs[]   = {
3284c582b7e3Smrg				/* From RAGE 128 VR/RAGE 128 GL Register
3285c582b7e3Smrg				   Reference Manual (Technical Reference
3286c582b7e3Smrg				   Manual P/N RRG-G04100-C Rev. 0.04), page
3287c582b7e3Smrg				   3-17 (PLL_DIV_[3:0]).  */
3288c582b7e3Smrg	{  1, 0 },              /* VCLK_SRC                 */
3289c582b7e3Smrg	{  2, 1 },              /* VCLK_SRC/2               */
3290c582b7e3Smrg	{  4, 2 },              /* VCLK_SRC/4               */
3291c582b7e3Smrg	{  8, 3 },              /* VCLK_SRC/8               */
3292c582b7e3Smrg
3293c582b7e3Smrg	{  3, 4 },              /* VCLK_SRC/3               */
3294c582b7e3Smrg				/* bitvalue = 5 is reserved */
3295c582b7e3Smrg	{  6, 6 },              /* VCLK_SRC/6               */
3296c582b7e3Smrg	{ 12, 7 },              /* VCLK_SRC/12              */
3297c582b7e3Smrg	{  0, 0 }
3298c582b7e3Smrg    };
3299c582b7e3Smrg
3300c582b7e3Smrg    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3301c582b7e3Smrg    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3302c582b7e3Smrg
3303c582b7e3Smrg    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3304c582b7e3Smrg	save->pll_output_freq_2 = post_div->divider * freq;
3305c582b7e3Smrg	if (save->pll_output_freq_2 >= pll->min_pll_freq
3306c582b7e3Smrg	    && save->pll_output_freq_2 <= pll->max_pll_freq) break;
3307c582b7e3Smrg    }
3308c582b7e3Smrg
3309c582b7e3Smrg    save->dot_clock_freq_2 = freq;
3310c582b7e3Smrg    save->feedback_div_2   = R128Div(pll->reference_div
3311c582b7e3Smrg				     * save->pll_output_freq_2,
3312c582b7e3Smrg				     pll->reference_freq);
3313c582b7e3Smrg    save->post_div_2       = post_div->divider;
3314c582b7e3Smrg
3315c582b7e3Smrg    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3316c582b7e3Smrg	       save->dot_clock_freq_2,
3317c582b7e3Smrg	       save->pll_output_freq_2,
3318c582b7e3Smrg	       save->feedback_div_2,
3319c582b7e3Smrg	       save->post_div_2));
3320c582b7e3Smrg
3321c582b7e3Smrg    save->p2pll_ref_div   = pll->reference_div;
3322c582b7e3Smrg    save->p2pll_div_0    = (save->feedback_div_2 | (post_div->bitvalue<<16));
3323c582b7e3Smrg    save->htotal_cntl2    = 0;
3324c582b7e3Smrg}
3325c582b7e3Smrg
3326c582b7e3Smrg/* Define DDA registers for requested video mode. */
3327b3ff493bSmrgBool R128InitDDARegisters(xf86CrtcPtr crtc, R128SavePtr save,
3328b3ff493bSmrg				 R128PLLPtr pll, DisplayModePtr mode)
3329c582b7e3Smrg{
3330b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
3331b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3332b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(crtc);
3333b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3334b3ff493bSmrg
3335c582b7e3Smrg    int         DisplayFifoWidth = 128;
3336c582b7e3Smrg    int         DisplayFifoDepth = 32;
3337c582b7e3Smrg    int         XclkFreq;
3338c582b7e3Smrg    int         VclkFreq;
3339c582b7e3Smrg    int         XclksPerTransfer;
3340c582b7e3Smrg    int         XclksPerTransferPrecise;
3341c582b7e3Smrg    int         UseablePrecision;
3342c582b7e3Smrg    int         Roff;
3343c582b7e3Smrg    int         Ron;
3344c582b7e3Smrg
3345c582b7e3Smrg    XclkFreq = pll->xclk;
3346c582b7e3Smrg
3347c582b7e3Smrg    VclkFreq = R128Div(pll->reference_freq * save->feedback_div,
3348c582b7e3Smrg		       pll->reference_div * save->post_div);
3349c582b7e3Smrg
3350b3ff493bSmrg    if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) {
3351b3ff493bSmrg        if (r128_output->PanelXRes != mode->CrtcHDisplay)
3352b3ff493bSmrg            VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes;
3353b3ff493bSmrg    }
3354c582b7e3Smrg
3355c582b7e3Smrg    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3356c582b7e3Smrg			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3357c582b7e3Smrg
3358c582b7e3Smrg    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3359c582b7e3Smrg
3360c582b7e3Smrg    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3361c582b7e3Smrg				      << (11 - UseablePrecision),
3362c582b7e3Smrg				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3363c582b7e3Smrg
3364c582b7e3Smrg    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3365c582b7e3Smrg
3366c582b7e3Smrg    Ron   = (4 * info->ram->MB
3367c582b7e3Smrg	     + 3 * MAX(info->ram->Trcd - 2, 0)
3368c582b7e3Smrg	     + 2 * info->ram->Trp
3369c582b7e3Smrg	     + info->ram->Twr
3370c582b7e3Smrg	     + info->ram->CL
3371c582b7e3Smrg	     + info->ram->Tr2w
3372c582b7e3Smrg	     + XclksPerTransfer) << (11 - UseablePrecision);
3373c582b7e3Smrg
3374c582b7e3Smrg    if (Ron + info->ram->Rloop >= Roff) {
3375c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3376c582b7e3Smrg		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3377c582b7e3Smrg		   Ron, info->ram->Rloop, Roff);
3378c582b7e3Smrg	return FALSE;
3379c582b7e3Smrg    }
3380c582b7e3Smrg
3381c582b7e3Smrg    save->dda_config = (XclksPerTransferPrecise
3382c582b7e3Smrg			| (UseablePrecision << 16)
3383c582b7e3Smrg			| (info->ram->Rloop << 20));
3384c582b7e3Smrg
3385c582b7e3Smrg    save->dda_on_off = (Ron << 16) | Roff;
3386c582b7e3Smrg
3387c582b7e3Smrg    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3388c582b7e3Smrg	       XclkFreq,
3389c582b7e3Smrg	       VclkFreq,
3390c582b7e3Smrg	       XclksPerTransfer,
3391c582b7e3Smrg	       XclksPerTransferPrecise,
3392c582b7e3Smrg	       UseablePrecision));
3393c582b7e3Smrg    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3394c582b7e3Smrg	       Roff, Ron, info->ram->Rloop));
3395c582b7e3Smrg
3396c582b7e3Smrg    return TRUE;
3397c582b7e3Smrg}
3398c582b7e3Smrg
3399c582b7e3Smrg/* Define DDA2 registers for requested video mode. */
3400b3ff493bSmrgBool R128InitDDA2Registers(xf86CrtcPtr crtc, R128SavePtr save,
3401b3ff493bSmrg				 R128PLLPtr pll, DisplayModePtr mode)
3402c582b7e3Smrg{
3403b3ff493bSmrg    ScrnInfoPtr pScrn = crtc->scrn;
3404b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3405b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(crtc);
3406b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3407b3ff493bSmrg
3408c582b7e3Smrg    int         DisplayFifoWidth = 128;
3409c582b7e3Smrg    int         DisplayFifoDepth = 32;
3410c582b7e3Smrg    int         XclkFreq;
3411c582b7e3Smrg    int         VclkFreq;
3412c582b7e3Smrg    int         XclksPerTransfer;
3413c582b7e3Smrg    int         XclksPerTransferPrecise;
3414c582b7e3Smrg    int         UseablePrecision;
3415c582b7e3Smrg    int         Roff;
3416c582b7e3Smrg    int         Ron;
3417c582b7e3Smrg
3418c582b7e3Smrg    XclkFreq = pll->xclk;
3419c582b7e3Smrg
3420c582b7e3Smrg    VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2,
3421c582b7e3Smrg		       pll->reference_div * save->post_div_2);
3422c582b7e3Smrg
3423b3ff493bSmrg    if (info->isDFP && !info->isPro2 && r128_output->PanelXRes > 0) {
3424b3ff493bSmrg        if (r128_output->PanelXRes != mode->CrtcHDisplay)
3425b3ff493bSmrg            VclkFreq = (VclkFreq * mode->CrtcHDisplay) / r128_output->PanelXRes;
3426b3ff493bSmrg    }
3427c582b7e3Smrg
3428c582b7e3Smrg    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3429c582b7e3Smrg			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3430c582b7e3Smrg
3431c582b7e3Smrg    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3432c582b7e3Smrg
3433c582b7e3Smrg    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3434c582b7e3Smrg				      << (11 - UseablePrecision),
3435c582b7e3Smrg				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3436c582b7e3Smrg
3437c582b7e3Smrg    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3438c582b7e3Smrg
3439c582b7e3Smrg    Ron   = (4 * info->ram->MB
3440c582b7e3Smrg	     + 3 * MAX(info->ram->Trcd - 2, 0)
3441c582b7e3Smrg	     + 2 * info->ram->Trp
3442c582b7e3Smrg	     + info->ram->Twr
3443c582b7e3Smrg	     + info->ram->CL
3444c582b7e3Smrg	     + info->ram->Tr2w
3445c582b7e3Smrg	     + XclksPerTransfer) << (11 - UseablePrecision);
3446c582b7e3Smrg
3447c582b7e3Smrg
3448c582b7e3Smrg    if (Ron + info->ram->Rloop >= Roff) {
3449c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3450c582b7e3Smrg		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3451c582b7e3Smrg		   Ron, info->ram->Rloop, Roff);
3452c582b7e3Smrg	return FALSE;
3453c582b7e3Smrg    }
3454c582b7e3Smrg
3455c582b7e3Smrg    save->dda2_config = (XclksPerTransferPrecise
3456c582b7e3Smrg			| (UseablePrecision << 16)
3457c582b7e3Smrg			| (info->ram->Rloop << 20));
3458c582b7e3Smrg
3459c582b7e3Smrg    /*save->dda2_on_off = (Ron << 16) | Roff;*/
3460c582b7e3Smrg    /* shift most be 18 otherwise there's corruption on crtc2 */
3461c582b7e3Smrg    save->dda2_on_off = (Ron << 18) | Roff;
3462c582b7e3Smrg
3463c582b7e3Smrg    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3464c582b7e3Smrg	       XclkFreq,
3465c582b7e3Smrg	       VclkFreq,
3466c582b7e3Smrg	       XclksPerTransfer,
3467c582b7e3Smrg	       XclksPerTransferPrecise,
3468c582b7e3Smrg	       UseablePrecision));
3469c582b7e3Smrg    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3470c582b7e3Smrg	       Roff, Ron, info->ram->Rloop));
3471c582b7e3Smrg
3472c582b7e3Smrg    return TRUE;
3473c582b7e3Smrg}
3474c582b7e3Smrg
3475c582b7e3Smrg#if 0
3476c582b7e3Smrg/* Define initial palette for requested video mode.  This doesn't do
3477c582b7e3Smrg   anything for XFree86 4.0. */
3478c582b7e3Smrgstatic void R128InitPalette(R128SavePtr save)
3479c582b7e3Smrg{
3480c582b7e3Smrg    save->palette_valid = FALSE;
3481c582b7e3Smrg}
3482c582b7e3Smrg#endif
3483c582b7e3Smrg
3484c582b7e3Smrgstatic Bool R128SaveScreen(ScreenPtr pScreen, int mode)
3485c582b7e3Smrg{
348684354367Smrg    ScrnInfoPtr   pScrn = xf86ScreenToScrn(pScreen);
3487c582b7e3Smrg    Bool unblank;
3488c582b7e3Smrg
3489c582b7e3Smrg    unblank = xf86IsUnblank(mode);
3490c582b7e3Smrg    if (unblank)
3491c582b7e3Smrg	SetTimeSinceLastInputEvent();
3492c582b7e3Smrg
3493c582b7e3Smrg    if ((pScrn != NULL) && pScrn->vtSema) {
3494c582b7e3Smrg	if (unblank)
3495c582b7e3Smrg		R128Unblank(pScrn);
3496c582b7e3Smrg	else
3497c582b7e3Smrg		R128Blank(pScrn);
3498c582b7e3Smrg    }
3499c582b7e3Smrg    return TRUE;
3500c582b7e3Smrg}
3501c582b7e3Smrg
3502c582b7e3Smrg/*
3503c582b7e3Smrg * SwitchMode() doesn't work right on crtc2 on some laptops.
3504c582b7e3Smrg * The workaround is to switch the mode, then switch to another VT, then
3505c582b7e3Smrg * switch back. --AGD
3506c582b7e3Smrg */
350784354367SmrgBool R128SwitchMode(SWITCH_MODE_ARGS_DECL)
3508c582b7e3Smrg{
350984354367Smrg    SCRN_INFO_PTR(arg);
3510c582b7e3Smrg    R128InfoPtr info        = R128PTR(pScrn);
3511c582b7e3Smrg    Bool ret;
3512c582b7e3Smrg
3513c582b7e3Smrg    info->SwitchingMode = TRUE;
3514b3ff493bSmrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
3515c582b7e3Smrg    info->SwitchingMode = FALSE;
3516c582b7e3Smrg    return ret;
3517c582b7e3Smrg}
3518c582b7e3Smrg
3519b3ff493bSmrgModeStatus R128DoValidMode(xf86OutputPtr output, DisplayModePtr mode, int flags)
3520c582b7e3Smrg{
3521b3ff493bSmrg    ScrnInfoPtr pScrn = output->scrn;
3522b3ff493bSmrg    R128InfoPtr info  = R128PTR(pScrn);
3523b3ff493bSmrg    R128OutputPrivatePtr r128_output = output->driver_private;
3524b3ff493bSmrg    int i, j;
3525c582b7e3Smrg
3526b3ff493bSmrg    if (r128_output->MonType == MT_CRT)
3527b3ff493bSmrg        return MODE_OK;
3528c582b7e3Smrg
3529b3ff493bSmrg    if (r128_output->MonType == MT_DFP || r128_output->MonType == MT_LCD) {
3530c582b7e3Smrg	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
3531c582b7e3Smrg	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
3532c582b7e3Smrg    }
3533c582b7e3Smrg
3534b3ff493bSmrg    if (r128_output->MonType == MT_LCD && info->VBIOS) {
3535b3ff493bSmrg	for (i = info->FPBIOSstart + 64; R128_BIOS16(i) != 0; i += 2) {
3536b3ff493bSmrg	    j = R128_BIOS16(i);
3537c582b7e3Smrg
3538c582b7e3Smrg	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
3539b3ff493bSmrg		mode->CrtcVDisplay == R128_BIOS16(j + 2)) {
3540c582b7e3Smrg		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
3541c582b7e3Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3542c582b7e3Smrg			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
3543b3ff493bSmrg			       mode->CrtcHDisplay, mode->CrtcVDisplay,
3544b3ff493bSmrg			       (float)mode->Clock / 1000);
3545c582b7e3Smrg
3546c582b7e3Smrg		    /* Assume we are using expanded mode */
3547b3ff493bSmrg		    if (R128_BIOS16(j + 5)) j  = R128_BIOS16(j + 5);
3548b3ff493bSmrg		    else                    j += 9;
3549c582b7e3Smrg
3550b3ff493bSmrg		    mode->Clock = (uint32_t)R128_BIOS16(j) * 10;
3551c582b7e3Smrg
3552c582b7e3Smrg		    mode->HDisplay   = mode->CrtcHDisplay   =
3553b3ff493bSmrg			((R128_BIOS16(j + 10) & 0x01ff) + 1) * 8;
3554c582b7e3Smrg		    mode->HSyncStart = mode->CrtcHSyncStart =
3555b3ff493bSmrg			((R128_BIOS16(j + 12) & 0x01ff) + 1) * 8;
3556c582b7e3Smrg		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
3557b3ff493bSmrg			mode->CrtcHSyncStart + (R128_BIOS8(j + 14) & 0x1f);
3558c582b7e3Smrg		    mode->HTotal     = mode->CrtcHTotal     =
3559b3ff493bSmrg			((R128_BIOS16(j + 8)  & 0x01ff) + 1) * 8;
3560c582b7e3Smrg
3561c582b7e3Smrg		    mode->VDisplay   = mode->CrtcVDisplay   =
3562b3ff493bSmrg			(R128_BIOS16(j + 17) & 0x07ff) + 1;
3563c582b7e3Smrg		    mode->VSyncStart = mode->CrtcVSyncStart =
3564b3ff493bSmrg			(R128_BIOS16(j + 19) & 0x07ff) + 1;
3565c582b7e3Smrg		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
3566b3ff493bSmrg			mode->CrtcVSyncStart + ((R128_BIOS16(j + 19) >> 11) & 0x1f);
3567c582b7e3Smrg		    mode->VTotal     = mode->CrtcVTotal     =
3568b3ff493bSmrg			(R128_BIOS16(j + 15) & 0x07ff) + 1;
3569c582b7e3Smrg		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
3570c582b7e3Smrg			       mode->CrtcHDisplay,mode->CrtcVDisplay,
3571b3ff493bSmrg			       (float)mode->Clock/ 1000);
3572c582b7e3Smrg		}
3573c582b7e3Smrg		return MODE_OK;
3574c582b7e3Smrg	    }
3575c582b7e3Smrg	}
3576c582b7e3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
3577c582b7e3Smrg		       "Mode rejected for FP %ix%i [pclk: %.1f] "
3578c582b7e3Smrg		       "(not listed in VBIOS)\n",
3579c582b7e3Smrg		       mode->CrtcHDisplay, mode->CrtcVDisplay,
3580c582b7e3Smrg		       (float)mode->Clock / 1000);
3581c582b7e3Smrg	return MODE_NOMODE;
3582c582b7e3Smrg    }
3583c582b7e3Smrg
3584c582b7e3Smrg    return MODE_OK;
3585c582b7e3Smrg}
3586c582b7e3Smrg
3587b3ff493bSmrg/* Used to disallow modes that are not supported by the hardware. */
3588b3ff493bSmrgModeStatus R128ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
3589b3ff493bSmrg                                   Bool verbose, int flags)
3590b3ff493bSmrg{
3591b3ff493bSmrg    SCRN_INFO_PTR(arg);
3592b3ff493bSmrg    R128EntPtr  pR128Ent = R128EntPriv(pScrn);
3593b3ff493bSmrg    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
3594b3ff493bSmrg
3595b3ff493bSmrg    return R128DoValidMode(output, mode, flags);
3596b3ff493bSmrg}
3597b3ff493bSmrg
3598c582b7e3Smrg/* Adjust viewport into virtual desktop such that (0,0) in viewport space
3599c582b7e3Smrg   is (x,y) in virtual space. */
360084354367Smrgvoid R128AdjustFrame(ADJUST_FRAME_ARGS_DECL)
3601c582b7e3Smrg{
360284354367Smrg    SCRN_INFO_PTR(arg);
3603c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3604c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
3605c582b7e3Smrg    int           Base;
3606c582b7e3Smrg
3607c582b7e3Smrg    if(info->showCache && y && pScrn->vtSema)
3608c582b7e3Smrg        y += pScrn->virtualY - 1;
3609c582b7e3Smrg
3610c582b7e3Smrg    Base = y * info->CurrentLayout.displayWidth + x;
3611c582b7e3Smrg
3612c582b7e3Smrg    switch (info->CurrentLayout.pixel_code) {
3613c582b7e3Smrg    case 15:
3614c582b7e3Smrg    case 16: Base *= 2; break;
3615c582b7e3Smrg    case 24: Base *= 3; break;
3616c582b7e3Smrg    case 32: Base *= 4; break;
3617c582b7e3Smrg    }
3618c582b7e3Smrg
3619c582b7e3Smrg    Base &= ~7;                 /* 3 lower bits are always 0 */
3620c582b7e3Smrg
3621c582b7e3Smrg    if (info->CurrentLayout.pixel_code == 24)
3622c582b7e3Smrg	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
3623c582b7e3Smrg
3624c582b7e3Smrg    OUTREG(R128_CRTC_OFFSET, Base);
3625c582b7e3Smrg}
3626c582b7e3Smrg
3627c582b7e3Smrg/* Called when VT switching back to the X server.  Reinitialize the video
3628c582b7e3Smrg   mode. */
362984354367SmrgBool R128EnterVT(VT_FUNC_ARGS_DECL)
3630c582b7e3Smrg{
363184354367Smrg    SCRN_INFO_PTR(arg);
3632c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
3633c582b7e3Smrg
3634c582b7e3Smrg    R128TRACE(("R128EnterVT\n"));
3635b3ff493bSmrg
3636b3ff493bSmrg    pScrn->vtSema = TRUE;
363779e5230eSmacallan#ifndef AVOID_FBDEV
3638c582b7e3Smrg    if (info->FBDev) {
363984354367Smrg        if (!fbdevHWEnterVT(VT_FUNC_ARGS)) return FALSE;
36403c921f55Smrg    } else {
364179e5230eSmacallan#endif
36423c921f55Smrg	if (!xf86SetDesiredModes(pScrn)) return FALSE;
36433c921f55Smrg#ifndef AVOID_FBDEV
3644b3ff493bSmrg    }
36453c921f55Smrg#endif
3646b3ff493bSmrg
3647c582b7e3Smrg    if (info->accelOn)
3648c582b7e3Smrg	R128EngineInit(pScrn);
3649c582b7e3Smrg
365084354367Smrg#ifdef R128DRI
3651c582b7e3Smrg    if (info->directRenderingEnabled) {
3652c582b7e3Smrg	if (info->irq) {
3653c582b7e3Smrg	    /* Need to make sure interrupts are enabled */
3654c582b7e3Smrg	    unsigned char *R128MMIO = info->MMIO;
3655c582b7e3Smrg	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
3656c582b7e3Smrg	}
3657c582b7e3Smrg	R128CCE_START(pScrn, info);
3658c582b7e3Smrg	DRIUnlock(pScrn->pScreen);
3659c582b7e3Smrg    }
3660c582b7e3Smrg#endif
3661c582b7e3Smrg
3662c582b7e3Smrg    info->PaletteSavedOnVT = FALSE;
3663b3ff493bSmrg    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3664c582b7e3Smrg
3665c582b7e3Smrg    return TRUE;
3666c582b7e3Smrg}
3667c582b7e3Smrg
3668c582b7e3Smrg/* Called when VT switching away from the X server.  Restore the original
3669c582b7e3Smrg   text mode. */
367084354367Smrgvoid R128LeaveVT(VT_FUNC_ARGS_DECL)
3671c582b7e3Smrg{
367284354367Smrg    SCRN_INFO_PTR(arg);
3673c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
3674c582b7e3Smrg    R128SavePtr save  = &info->ModeReg;
3675c582b7e3Smrg
3676c582b7e3Smrg    R128TRACE(("R128LeaveVT\n"));
367784354367Smrg#ifdef R128DRI
3678c582b7e3Smrg    if (info->directRenderingEnabled) {
3679c582b7e3Smrg	DRILock(pScrn->pScreen, 0);
3680c582b7e3Smrg	R128CCE_STOP(pScrn, info);
3681c582b7e3Smrg    }
368284354367Smrg#ifdef USE_EXA
368384354367Smrg    if (info->useEXA)
368484354367Smrg        info->state_2d.composite_setup = FALSE;
368584354367Smrg#endif
3686c582b7e3Smrg#endif
3687c582b7e3Smrg    R128SavePalette(pScrn, save);
3688c582b7e3Smrg    info->PaletteSavedOnVT = TRUE;
368979e5230eSmacallan#ifndef AVOID_FBDEV
3690c582b7e3Smrg    if (info->FBDev)
369184354367Smrg        fbdevHWLeaveVT(VT_FUNC_ARGS);
3692c582b7e3Smrg    else
369379e5230eSmacallan#endif
3694c582b7e3Smrg        R128Restore(pScrn);
3695c582b7e3Smrg}
3696c582b7e3Smrg
3697c582b7e3Smrg
3698c582b7e3Smrg/* Called at the end of each server generation.  Restore the original text
3699c582b7e3Smrg   mode, unmap video memory, and unwrap and call the saved CloseScreen
3700c582b7e3Smrg   function.  */
370184354367Smrgstatic Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL)
3702c582b7e3Smrg{
370384354367Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3704c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
3705c582b7e3Smrg
3706c582b7e3Smrg    R128TRACE(("R128CloseScreen\n"));
3707c582b7e3Smrg
370884354367Smrg#ifdef R128DRI
3709c582b7e3Smrg				/* Disable direct rendering */
3710c582b7e3Smrg    if (info->directRenderingEnabled) {
3711c582b7e3Smrg	R128DRICloseScreen(pScreen);
3712c582b7e3Smrg	info->directRenderingEnabled = FALSE;
3713c582b7e3Smrg    }
3714c582b7e3Smrg#endif
3715c582b7e3Smrg
3716c582b7e3Smrg    if (pScrn->vtSema) {
3717c582b7e3Smrg	R128Restore(pScrn);
3718c582b7e3Smrg	R128UnmapMem(pScrn);
3719c582b7e3Smrg    }
3720c582b7e3Smrg
372184354367Smrg#ifdef USE_EXA
372284354367Smrg        if (info->useEXA) {
372384354367Smrg	    exaDriverFini(pScreen);
372484354367Smrg	    free(info->ExaDriver);
372584354367Smrg	} else
372684354367Smrg#endif
372784354367Smrg#ifdef HAVE_XAA_H
372884354367Smrg	{
372984354367Smrg            if (info->accel)             XAADestroyInfoRec(info->accel);
373084354367Smrg	    info->accel                  = NULL;
373184354367Smrg        }
373284354367Smrg#endif
3733c582b7e3Smrg
373484354367Smrg    if (info->scratch_save)      free(info->scratch_save);
3735c582b7e3Smrg    info->scratch_save           = NULL;
3736c582b7e3Smrg
3737c582b7e3Smrg    if (info->adaptor) {
373884354367Smrg        free(info->adaptor->pPortPrivates[0].ptr);
3739c582b7e3Smrg	xf86XVFreeVideoAdaptorRec(info->adaptor);
3740c582b7e3Smrg	info->adaptor = NULL;
3741c582b7e3Smrg    }
3742c582b7e3Smrg
3743c582b7e3Smrg    pScrn->vtSema = FALSE;
3744c582b7e3Smrg
3745c582b7e3Smrg    pScreen->BlockHandler = info->BlockHandler;
3746c582b7e3Smrg    pScreen->CloseScreen = info->CloseScreen;
374784354367Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3748c582b7e3Smrg}
3749c582b7e3Smrg
375084354367Smrgvoid R128FreeScreen(FREE_SCREEN_ARGS_DECL)
3751c582b7e3Smrg{
375284354367Smrg    SCRN_INFO_PTR(arg);
3753c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
3754c582b7e3Smrg
3755c582b7e3Smrg    R128TRACE(("R128FreeScreen\n"));
375619019ffeSmrg    if (info == NULL)
375719019ffeSmrg	return;
3758c582b7e3Smrg#ifdef WITH_VGAHW
3759c582b7e3Smrg    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
3760c582b7e3Smrg	vgaHWFreeHWRec(pScrn);
3761c582b7e3Smrg#endif
3762c582b7e3Smrg    R128FreeRec(pScrn);
3763c582b7e3Smrg}
3764