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