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#include "xf86Privstr.h"
98
99				/* fbdevhw & vgahw */
100#ifdef WITH_VGAHW
101#include "vgaHW.h"
102#endif
103
104#ifndef AVOID_FBDEV
105#include "fbdevhw.h"
106#endif
107
108#include "dixstruct.h"
109
110				/* DPMS support. */
111#ifdef HAVE_XEXTPROTO_71
112#include <X11/extensions/dpmsconst.h>
113#else
114#define DPMS_SERVER
115#include <X11/extensions/dpms.h>
116#endif
117
118#ifdef __NetBSD__
119#include <sys/time.h>
120#include <dev/wscons/wsconsio.h>
121#endif
122
123static Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL);
124static Bool R128SaveScreen(ScreenPtr pScreen, int mode);
125static void R128Save(ScrnInfoPtr pScrn);
126static void R128Restore(ScrnInfoPtr pScrn);
127
128typedef enum {
129  OPTION_NOACCEL,
130#ifndef AVOID_FBDEV
131  OPTION_FBDEV,
132#endif
133  OPTION_DAC_6BIT,
134  OPTION_VGA_ACCESS,
135  OPTION_SHOW_CACHE,
136  OPTION_SW_CURSOR,
137  OPTION_VIDEO_KEY,
138  OPTION_PANEL_WIDTH,
139  OPTION_PANEL_HEIGHT,
140  OPTION_PROG_FP_REGS,
141#ifdef R128DRI
142  OPTION_XV_DMA,
143  OPTION_IS_PCI,
144  OPTION_CCE_PIO,
145  OPTION_NO_SECURITY,
146  OPTION_USEC_TIMEOUT,
147  OPTION_AGP_MODE,
148  OPTION_AGP_SIZE,
149  OPTION_RING_SIZE,
150  OPTION_BUFFER_SIZE,
151  OPTION_PAGE_FLIP,
152#endif
153  OPTION_ACCELMETHOD,
154  OPTION_RENDERACCEL
155} R128Opts;
156
157static const OptionInfoRec R128Options[] = {
158{ OPTION_NOACCEL,      "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
159#ifndef AVOID_FBDEV
160{ OPTION_FBDEV,        "UseFBDev",         OPTV_BOOLEAN, {0}, FALSE },
161#endif
162{ OPTION_DAC_6BIT,     "Dac6Bit",          OPTV_BOOLEAN, {0}, FALSE },
163{ OPTION_VGA_ACCESS,   "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
164{ OPTION_SHOW_CACHE,   "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
165{ OPTION_SW_CURSOR,    "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
166{ OPTION_VIDEO_KEY,    "VideoKey",         OPTV_INTEGER, {0}, FALSE },
167{ OPTION_PANEL_WIDTH,  "PanelWidth",       OPTV_INTEGER, {0}, FALSE },
168{ OPTION_PANEL_HEIGHT, "PanelHeight",      OPTV_INTEGER, {0}, FALSE },
169{ OPTION_PROG_FP_REGS, "ProgramFPRegs",    OPTV_BOOLEAN, {0}, FALSE },
170#ifdef R128DRI
171  { OPTION_XV_DMA,       "DMAForXv",         OPTV_BOOLEAN, {0}, FALSE },
172  { OPTION_IS_PCI,       "ForcePCIMode",     OPTV_BOOLEAN, {0}, FALSE },
173  { OPTION_CCE_PIO,      "CCEPIOMode",       OPTV_BOOLEAN, {0}, FALSE },
174  { OPTION_NO_SECURITY,  "CCENoSecurity",    OPTV_BOOLEAN, {0}, FALSE },
175  { OPTION_USEC_TIMEOUT, "CCEusecTimeout",   OPTV_INTEGER, {0}, FALSE },
176  { OPTION_AGP_MODE,     "AGPMode",          OPTV_INTEGER, {0}, FALSE },
177  { OPTION_AGP_SIZE,     "AGPSize",          OPTV_INTEGER, {0}, FALSE },
178  { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
179  { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
180  { OPTION_PAGE_FLIP,    "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
181#endif
182  { OPTION_ACCELMETHOD,  "AccelMethod",      OPTV_STRING,  {0}, FALSE },
183  { OPTION_RENDERACCEL,  "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
184  { -1,                  NULL,               OPTV_NONE,    {0}, FALSE }
185};
186
187const OptionInfoRec *R128OptionsWeak(void) { return R128Options; }
188
189R128RAMRec R128RAM[] = {        /* Memory Specifications
190				   From RAGE 128 Software Development
191				   Manual (Technical Reference Manual P/N
192				   SDK-G04000 Rev 0.01), page 3-21.  */
193    { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
194    { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
195    { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
196    { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
197};
198
199extern _X_EXPORT int gR128EntityIndex;
200
201int getR128EntityIndex(void)
202{
203    return gR128EntityIndex;
204}
205
206R128EntPtr R128EntPriv(ScrnInfoPtr pScrn)
207{
208    DevUnion     *pPriv;
209    R128InfoPtr  info   = R128PTR(pScrn);
210    pPriv = xf86GetEntityPrivate(info->pEnt->index,
211                                 getR128EntityIndex());
212    return pPriv->ptr;
213}
214
215/* Allocate our private R128InfoRec. */
216static Bool R128GetRec(ScrnInfoPtr pScrn)
217{
218    if (pScrn->driverPrivate) return TRUE;
219
220    pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1);
221    return TRUE;
222}
223
224/* Free our private R128InfoRec. */
225static void R128FreeRec(ScrnInfoPtr pScrn)
226{
227    if (!pScrn || !pScrn->driverPrivate) return;
228    free(pScrn->driverPrivate);
229    pScrn->driverPrivate = NULL;
230}
231
232/* Memory map the MMIO region.  Used during pre-init and by R128MapMem,
233   below. */
234static Bool R128MapMMIO(ScrnInfoPtr pScrn)
235{
236    R128InfoPtr info          = R128PTR(pScrn);
237
238#ifndef AVOID_FBDEV
239    if (info->FBDev) {
240	info->MMIO = fbdevHWMapMMIO(pScrn);
241    } else
242#endif
243    {
244#ifndef XSERVER_LIBPCIACCESS
245	info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
246				   VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
247				   info->PciTag,
248				   info->MMIOAddr,
249				   R128_MMIOSIZE);
250        if (!info->MMIO) return FALSE;
251#else
252	int err = pci_device_map_range(info->PciInfo,
253				       info->MMIOAddr,
254				       R128_MMIOSIZE,
255				       PCI_DEV_MAP_FLAG_WRITABLE,
256				       &info->MMIO);
257
258	if (err) {
259	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
260                        "Unable to map MMIO aperture. %s (%d)\n",
261                        strerror (err), err);
262	    return FALSE;
263	}
264#endif
265    }
266
267    return TRUE;
268}
269
270/* Unmap the MMIO region.  Used during pre-init and by R128UnmapMem,
271   below. */
272static Bool R128UnmapMMIO(ScrnInfoPtr pScrn)
273{
274    R128InfoPtr info          = R128PTR(pScrn);
275
276#ifndef AVOID_FBDEV
277    if (info->FBDev)
278	fbdevHWUnmapMMIO(pScrn);
279    else
280#endif
281    {
282#ifndef XSERVER_LIBPCIACCESS
283	xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE);
284#else
285	pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE);
286#endif
287    }
288    info->MMIO = NULL;
289    return TRUE;
290}
291
292/* Memory map the frame buffer.  Used by R128MapMem, below. */
293static Bool R128MapFB(ScrnInfoPtr pScrn)
294{
295    R128InfoPtr info          = R128PTR(pScrn);
296
297#ifndef AVOID_FBDEV
298    if (info->FBDev) {
299	info->FB = fbdevHWMapVidmem(pScrn);
300    } else
301#endif
302    {
303#ifndef XSERVER_LIBPCIACCESS
304	info->FB = xf86MapPciMem(pScrn->scrnIndex,
305				 VIDMEM_FRAMEBUFFER,
306				 info->PciTag,
307				 info->LinearAddr,
308				 info->FbMapSize);
309#else
310	int err = pci_device_map_range(info->PciInfo,
311				       info->LinearAddr,
312				       info->FbMapSize,
313				       PCI_DEV_MAP_FLAG_WRITABLE |
314				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
315				       &info->FB);
316
317	if (err) {
318	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
319                        "Unable to map FB aperture. %s (%d)\n",
320                        strerror (err), err);
321	    return FALSE;
322	}
323#endif
324    }
325
326    if (!info->FB) return FALSE;
327    return TRUE;
328}
329
330/* Unmap the frame buffer.  Used by R128UnmapMem, below. */
331static Bool R128UnmapFB(ScrnInfoPtr pScrn)
332{
333    R128InfoPtr info          = R128PTR(pScrn);
334
335#ifndef AVOID_FBDEV
336    if (info->FBDev)
337	fbdevHWUnmapVidmem(pScrn);
338    else
339#endif
340#ifndef XSERVER_LIBPCIACCESS
341	xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
342#else
343	pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize);
344#endif
345    info->FB = NULL;
346    return TRUE;
347}
348
349/* Memory map the MMIO region and the frame buffer. */
350static Bool R128MapMem(ScrnInfoPtr pScrn)
351{
352    if (!R128MapMMIO(pScrn)) return FALSE;
353    if (!R128MapFB(pScrn)) {
354	R128UnmapMMIO(pScrn);
355	return FALSE;
356    }
357    return TRUE;
358}
359
360/* Unmap the MMIO region and the frame buffer. */
361static Bool R128UnmapMem(ScrnInfoPtr pScrn)
362{
363    if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE;
364    return TRUE;
365}
366
367/* Read PLL information */
368unsigned R128INPLL(ScrnInfoPtr pScrn, int addr)
369{
370    R128InfoPtr   info      = R128PTR(pScrn);
371    unsigned char *R128MMIO = info->MMIO;
372
373    OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f);
374    return INREG(R128_CLOCK_CNTL_DATA);
375}
376
377#if 0
378/* Read PAL information (only used for debugging). */
379static int R128INPAL(int idx)
380{
381    R128InfoPtr   info      = R128PTR(pScrn);
382    unsigned char *R128MMIO = info->MMIO;
383
384    OUTREG(R128_PALETTE_INDEX, idx << 16);
385    return INREG(R128_PALETTE_DATA);
386}
387#endif
388
389/* Wait for vertical sync. */
390void R128WaitForVerticalSync(ScrnInfoPtr pScrn)
391{
392    R128InfoPtr   info      = R128PTR(pScrn);
393    unsigned char *R128MMIO = info->MMIO;
394    int           i;
395
396    OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK);
397    for (i = 0; i < R128_TIMEOUT; i++) {
398	if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break;
399    }
400}
401
402/* Compute log base 2 of val. */
403int R128MinBits(int val)
404{
405    int bits;
406
407    if (!val) return 1;
408    for (bits = 0; val; val >>= 1, ++bits);
409    return bits;
410}
411
412/* Finds the first output using a given crtc. */
413xf86OutputPtr R128FirstOutput(xf86CrtcPtr crtc)
414{
415    ScrnInfoPtr pScrn = crtc->scrn;
416    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
417    xf86OutputPtr output = xf86_config->output[0];
418    int o;
419
420    for (o = 0; o < xf86_config->num_output; o++) {
421        output = xf86_config->output[o];
422        if (output->crtc == crtc) break;
423    }
424
425    return output;
426}
427
428/* Read the Video BIOS block. */
429static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
430{
431    R128InfoPtr info = R128PTR(pScrn);
432
433#ifdef XSERVER_LIBPCIACCESS
434    int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE;
435    info->VBIOS = malloc(size);
436#else
437    info->VBIOS = malloc(R128_VBIOS_SIZE);
438#endif
439
440    if (!info->VBIOS) {
441	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
442		   "Cannot allocate space for hold Video BIOS!\n");
443	return FALSE;
444    }
445
446    if (pInt10) {
447	info->BIOSAddr = pInt10->BIOSseg << 4;
448	(void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
449		     R128_VBIOS_SIZE);
450    } else {
451#ifdef XSERVER_LIBPCIACCESS
452	if (pci_device_read_rom(info->PciInfo, info->VBIOS)) {
453	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
454		       "Failed to read PCI ROM!\n");
455	}
456#else
457	xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE);
458	if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
459	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
460		       "Video BIOS not detected in PCI space!\n");
461	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
462		       "Attempting to read Video BIOS from legacy ISA space!\n");
463	    info->BIOSAddr = 0x000c0000;
464	    xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS);
465	}
466#endif
467    }
468    if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
469	info->BIOSAddr = 0x00000000;
470	free(info->VBIOS);
471	info->VBIOS = NULL;
472	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
473		   "Video BIOS not found!\n");
474    }
475
476    return TRUE;
477}
478
479/* Read the FP parameters if an LVDS panel is expected. */
480void R128GetPanelInfoFromBIOS(xf86OutputPtr output)
481{
482    ScrnInfoPtr pScrn = output->scrn;
483    R128InfoPtr info  = R128PTR(pScrn);
484    R128OutputPrivatePtr r128_output = output->driver_private;
485    int FPHeader = 0;
486    int i;
487
488    r128_output->PanelPwrDly = 200;
489    xf86GetOptValInteger(info->Options, OPTION_PANEL_WIDTH,  &(r128_output->PanelXRes));
490    xf86GetOptValInteger(info->Options, OPTION_PANEL_HEIGHT, &(r128_output->PanelYRes));
491
492    if (!info->VBIOS) goto fallback;
493    info->FPBIOSstart = 0;
494
495    /* FIXME: There should be direct access to the start of the FP info
496     * tables, but until we find out where that offset is stored, we
497     * must search for the ATI signature string: "M3      ".
498     */
499    for (i = 4; i < R128_VBIOS_SIZE - 8; i++) {
500        if (R128_BIOS8(i)     == 'M' &&
501            R128_BIOS8(i + 1) == '3' &&
502            R128_BIOS8(i + 2) == ' ' &&
503            R128_BIOS8(i + 3) == ' ' &&
504            R128_BIOS8(i + 4) == ' ' &&
505            R128_BIOS8(i + 5) == ' ' &&
506            R128_BIOS8(i + 6) == ' ' &&
507            R128_BIOS8(i + 7) == ' ') {
508            FPHeader = i - 2;
509            break;
510        }
511    }
512
513    if (!FPHeader) goto fallback;
514
515
516    /* Assume that only one panel is attached and supported */
517    for (i = FPHeader + 20; i < FPHeader + 84; i += 2) {
518        if (R128_BIOS16(i) != 0) {
519            info->FPBIOSstart = R128_BIOS16(i);
520            break;
521        }
522    }
523
524#ifndef AVOID_FBDEV
525    if (!info->FPBIOSstart) return;
526#endif
527
528    if (!r128_output->PanelXRes)
529        r128_output->PanelXRes = R128_BIOS16(info->FPBIOSstart + 25);
530    if (!r128_output->PanelYRes)
531        r128_output->PanelYRes = R128_BIOS16(info->FPBIOSstart + 27);
532    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n",
533               r128_output->PanelXRes, r128_output->PanelYRes);
534
535    r128_output->PanelPwrDly = R128_BIOS8(info->FPBIOSstart + 56);
536
537    if (!r128_output->PanelXRes || !r128_output->PanelYRes) {
538        info->HasPanelRegs = FALSE;
539        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
540		   "Can't determine panel dimensions, and none specified.\n"
541		   "\tDisabling programming of FP registers.\n");
542    }
543
544    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: ");
545    for (i = 1; i <= 24; i++)
546        ErrorF("%c", R128_BIOS8(info->FPBIOSstart + i));
547
548    ErrorF("\n");
549
550    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: ");
551    i = R128_BIOS16(info->FPBIOSstart + 29);
552    if (i & 1) ErrorF("Color, ");
553    else       ErrorF("Monochrome, ");
554    if (i & 2) ErrorF("Dual(split), ");
555    else       ErrorF("Single, ");
556
557    switch ((i >> 2) & 0x3f) {
558    case 0:  ErrorF("STN");        break;
559    case 1:  ErrorF("TFT");        break;
560    case 2:  ErrorF("Active STN"); break;
561    case 3:  ErrorF("EL");         break;
562    case 4:  ErrorF("Plasma");     break;
563    default: ErrorF("UNKNOWN");    break;
564    }
565
566    ErrorF("\n");
567
568    if (R128_BIOS8(info->FPBIOSstart + 61) & 1) {
569        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n");
570    } else {
571        /* FIXME: Add Non-LVDS flat pael support */
572        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
573                   "Non-LVDS panel interface detected!  "
574                   "This support is untested and may not "
575                   "function properly\n");
576    }
577    return;
578fallback:
579#ifdef __NetBSD__
580    if ((!r128_output->PanelXRes || !r128_output->PanelYRes)  &&
581        (info->HaveWSDisplay)) {
582	/*
583	 * we may not be on x86 so check wsdisplay for panel dimensions
584	 * XXX this assumes that the r128 is the console, although that should
585	 * be the case in the vast majority of cases where an LCD is hooked up
586	 * directly
587	 * We should probably just check the relevant registers but I'm not
588	 * sure they're available at this point.
589	 */
590	struct wsdisplay_fbinfo fbinfo;
591
592	if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GINFO, &fbinfo) == 0) {
593	    r128_output->PanelXRes = fbinfo.width;
594	    r128_output->PanelYRes = fbinfo.height;
595	}
596    }
597#endif
598}
599
600/* Read PLL parameters from BIOS block.  Default to typical values if there
601   is no BIOS. */
602static Bool R128GetPLLParameters(ScrnInfoPtr pScrn)
603{
604    R128InfoPtr   info = R128PTR(pScrn);
605    R128PLLPtr    pll  = &info->pll;
606
607#if defined(__powerpc__) || defined(__alpha__)
608    /* there is no bios under Linux PowerPC but Open Firmware
609       does set up the PLL registers properly and we can use
610       those to calculate xclk and find the reference divider */
611
612    unsigned x_mpll_ref_fb_div;
613    unsigned xclk_cntl;
614    unsigned Nx, M;
615    unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12};
616
617    /* Assume REF clock is 2950 (in units of 10khz) */
618    /* and that all pllclk must be between 125 Mhz and 250Mhz */
619    pll->reference_freq = 2950;
620    pll->min_pll_freq   = 12500;
621    pll->max_pll_freq   = 25000;
622
623    x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV);
624    xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7;
625    pll->reference_div =
626	INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK;
627
628    Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8;
629    M =  (x_mpll_ref_fb_div & 0x0000FF);
630
631    pll->xclk =  R128Div((2 * Nx * pll->reference_freq),
632			 (M * PostDivSet[xclk_cntl]));
633
634#else /* !defined(__powerpc__) */
635
636    if (!info->VBIOS) {
637	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
638		   "Video BIOS not detected, using default PLL parameters!\n");
639				/* These probably aren't going to work for
640				   the card you are using.  Specifically,
641				   reference freq can be 29.50MHz,
642				   28.63MHz, or 14.32MHz.  YMMV. */
643	pll->reference_freq = 2950;
644	pll->reference_div  = 65;
645	pll->min_pll_freq   = 12500;
646	pll->max_pll_freq   = 25000;
647	pll->xclk           = 10300;
648    } else {
649	uint16_t bios_header    = R128_BIOS16(0x48);
650	uint16_t pll_info_block = R128_BIOS16(bios_header + 0x30);
651    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
652                        "Header at 0x%04x; PLL Information at 0x%04x\n",
653                        bios_header, pll_info_block));
654
655	pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e);
656	pll->reference_div  = R128_BIOS16(pll_info_block + 0x10);
657	pll->min_pll_freq   = R128_BIOS32(pll_info_block + 0x12);
658	pll->max_pll_freq   = R128_BIOS32(pll_info_block + 0x16);
659	pll->xclk           = R128_BIOS16(pll_info_block + 0x08);
660    }
661#endif /* __powerpc__ */
662
663    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
664	       "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
665	       pll->reference_freq,
666	       pll->reference_div,
667	       pll->min_pll_freq,
668	       pll->max_pll_freq,
669	       pll->xclk);
670
671    return TRUE;
672}
673
674/* This is called by R128PreInit to set up the default visual. */
675static Bool R128PreInitVisual(ScrnInfoPtr pScrn)
676{
677    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb
678					  | Support32bppFb
679					  | SupportConvert32to24
680					  )))
681	return FALSE;
682
683    switch (pScrn->depth) {
684    case 8:
685    case 15:
686    case 16:
687    case 24:
688	break;
689    default:
690	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
691		   "Given depth (%d) is not supported by %s driver\n",
692		   pScrn->depth, R128_DRIVER_NAME);
693	return FALSE;
694    }
695
696    xf86PrintDepthBpp(pScrn);
697
698    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
699
700    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
701	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
702		   "Default visual (%s) is not supported at depth %d\n",
703		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
704	return FALSE;
705    }
706    return TRUE;
707
708}
709
710/* This is called by R128PreInit to handle all color weight issues. */
711static Bool R128PreInitWeight(ScrnInfoPtr pScrn)
712{
713    R128InfoPtr info          = R128PTR(pScrn);
714    rgb defaultWeight = { 0, 0, 0 };
715
716    /*
717     * Save flag for 6 bit DAC to use for setting CRTC registers.
718     * Otherwise use an 8 bit DAC, even if xf86SetWeight sets
719     * pScrn->rgbBits to some value other than 8.
720     */
721    if (pScrn->depth <= 8) {
722        if (info->dac6bits) {
723            pScrn->rgbBits = 6;
724        } else {
725            pScrn->rgbBits = 8;
726        }
727    } else {
728        info->dac6bits = FALSE;
729        pScrn->rgbBits = 8;
730    }
731
732    if (pScrn->depth > 8) {
733        if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
734    }
735
736    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
737               "Using %d bits per RGB (%d bit DAC)\n",
738               pScrn->rgbBits, info->dac6bits ? 6 : 8);
739
740    return TRUE;
741}
742
743/* This is called by R128PreInit to handle config file overrides for things
744   like chipset and memory regions.  Also determine memory size and type.
745   If memory type ever needs an override, put it in this routine. */
746static Bool R128PreInitConfig(ScrnInfoPtr pScrn)
747{
748    R128InfoPtr   info      = R128PTR(pScrn);
749    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
750    unsigned char *R128MMIO = info->MMIO;
751    EntityInfoPtr pEnt      = info->pEnt;
752    GDevPtr       dev       = pEnt->device;
753    int           offset    = 0;        /* RAM Type */
754    MessageType   from;
755
756				/* Chipset */
757    from = X_PROBED;
758    if (dev->chipset && *dev->chipset) {
759	info->Chipset  = xf86StringToToken(R128Chipsets, dev->chipset);
760	from           = X_CONFIG;
761    } else if (dev->chipID >= 0) {
762	info->Chipset  = dev->chipID;
763	from           = X_CONFIG;
764    } else {
765	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
766    }
767    pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset);
768
769    if (!pScrn->chipset) {
770	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
771		   "ChipID 0x%04x is not recognized\n", info->Chipset);
772	return FALSE;
773    }
774
775    if (info->Chipset < 0) {
776	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
777		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
778	return FALSE;
779    }
780
781    xf86DrvMsg(pScrn->scrnIndex, from,
782	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
783	       pScrn->chipset,
784	       info->Chipset);
785
786				/* Framebuffer */
787
788    from             = X_PROBED;
789    info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000;
790    pScrn->memPhysBase = info->LinearAddr;
791    if (dev->MemBase) {
792	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
793		   "Linear address override, using 0x%08lx instead of 0x%08lx\n",
794		   dev->MemBase,
795		   info->LinearAddr);
796	info->LinearAddr = dev->MemBase;
797	from             = X_CONFIG;
798    } else if (!info->LinearAddr) {
799	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
800		   "No valid linear framebuffer address\n");
801	return FALSE;
802    }
803    xf86DrvMsg(pScrn->scrnIndex, from,
804	       "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
805
806				/* MMIO registers */
807    from             = X_PROBED;
808    info->MMIOAddr   = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00;
809    if (dev->IOBase) {
810	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
811		   "MMIO address override, using 0x%08lx instead of 0x%08lx\n",
812		   dev->IOBase,
813		   info->MMIOAddr);
814	info->MMIOAddr = dev->IOBase;
815	from           = X_CONFIG;
816    } else if (!info->MMIOAddr) {
817	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
818	return FALSE;
819    }
820    xf86DrvMsg(pScrn->scrnIndex, from,
821	       "MMIO registers at 0x%08lx\n", info->MMIOAddr);
822
823#ifndef XSERVER_LIBPCIACCESS
824				/* BIOS */
825    from              = X_PROBED;
826    info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
827    if (info->BIOSAddr) {
828	xf86DrvMsg(pScrn->scrnIndex, from,
829		   "BIOS at 0x%08lx\n", info->BIOSAddr);
830    }
831#endif
832
833				/* Flat panel (part 1) */
834    if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS,
835			  &info->HasPanelRegs)) {
836	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
837		   "Turned flat panel register programming %s\n",
838		   info->HasPanelRegs ? "on" : "off");
839	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
840		   "\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");
841    } else {
842        info->isDFP = FALSE;
843        info->isPro2 = FALSE;
844        pR128Ent->HasCRTC2 = FALSE;
845	switch (info->Chipset) {
846	/* R128 Pro and Pro2 can have DFP, we will deal with it.
847	   No support for dual-head/xinerama yet.
848           M3 can also have DFP, no support for now */
849	case PCI_CHIP_RAGE128TF:
850	case PCI_CHIP_RAGE128TL:
851	case PCI_CHIP_RAGE128TR:
852	/* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came
853	 *        out at the same time, so are of the same family likely.
854	 *        This requires confirmation however to be fully correct.
855	 *        Mike A. Harris <mharris@redhat.com>
856	 */
857	case PCI_CHIP_RAGE128TS:
858	case PCI_CHIP_RAGE128TT:
859	case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE;
860	/* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP
861	 *        capability, as the comment at the top suggests.
862	 *        This requires confirmation however to be fully correct.
863	 *        Mike A. Harris <mharris@redhat.com>
864	 */
865	case PCI_CHIP_RAGE128PA:
866	case PCI_CHIP_RAGE128PB:
867	case PCI_CHIP_RAGE128PC:
868	case PCI_CHIP_RAGE128PE:
869	case PCI_CHIP_RAGE128PG:
870	case PCI_CHIP_RAGE128PH:
871	case PCI_CHIP_RAGE128PI:
872	case PCI_CHIP_RAGE128PJ:
873	case PCI_CHIP_RAGE128PK:
874	case PCI_CHIP_RAGE128PL:
875	case PCI_CHIP_RAGE128PM:
876	case PCI_CHIP_RAGE128PN:
877	case PCI_CHIP_RAGE128PO:
878	case PCI_CHIP_RAGE128PQ:
879	case PCI_CHIP_RAGE128PS:
880	case PCI_CHIP_RAGE128PT:
881	case PCI_CHIP_RAGE128PU:
882	case PCI_CHIP_RAGE128PV:
883	case PCI_CHIP_RAGE128PW:
884	case PCI_CHIP_RAGE128PX:
885
886	case PCI_CHIP_RAGE128PD:
887	case PCI_CHIP_RAGE128PF:
888	case PCI_CHIP_RAGE128PP:
889	case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break;
890
891	case PCI_CHIP_RAGE128LE:
892	case PCI_CHIP_RAGE128LF:
893	case PCI_CHIP_RAGE128MF:
894	case PCI_CHIP_RAGE128ML:
895			info->HasPanelRegs = TRUE;
896			info->isDFP = TRUE;
897			/* which chips support dualhead? */
898			pR128Ent->HasCRTC2 = TRUE;
899			break;
900	case PCI_CHIP_RAGE128RE:
901	case PCI_CHIP_RAGE128RF:
902	case PCI_CHIP_RAGE128RG:
903	case PCI_CHIP_RAGE128RK:
904	case PCI_CHIP_RAGE128RL:
905	case PCI_CHIP_RAGE128SM:
906	/* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as
907	 *        all of them are listed as "Rage 128 4x" in ATI docs.
908	 *        This requires confirmation however to be fully correct.
909	 *        Mike A. Harris <mharris@redhat.com>
910	 */
911	case PCI_CHIP_RAGE128SE:
912	case PCI_CHIP_RAGE128SF:
913	case PCI_CHIP_RAGE128SG:
914	case PCI_CHIP_RAGE128SH:
915	case PCI_CHIP_RAGE128SK:
916	case PCI_CHIP_RAGE128SL:
917	case PCI_CHIP_RAGE128SN:
918	default:                 info->HasPanelRegs = FALSE; break;
919	}
920    }
921
922				/* Read registers used to determine options */
923    from                      = X_PROBED;
924    if (!R128MapMMIO(pScrn)) return FALSE;
925    R128MMIO                  = info->MMIO;
926
927#ifndef AVOID_FBDEV
928    if (info->FBDev)
929	pScrn->videoRam       = fbdevHWGetVidmem(pScrn) / 1024;
930    else
931#endif
932	pScrn->videoRam       = INREG(R128_CONFIG_MEMSIZE) / 1024;
933
934    info->MemCntl             = INREG(R128_MEM_CNTL);
935    info->BusCntl             = INREG(R128_BUS_CNTL);
936
937				/* RAM */
938    switch (info->MemCntl & 0x3) {
939    case 0:                     /* SDR SGRAM 1:1 */
940	switch (info->Chipset) {
941	case PCI_CHIP_RAGE128TF:
942	case PCI_CHIP_RAGE128TL:
943	case PCI_CHIP_RAGE128TR:
944	case PCI_CHIP_RAGE128LE:
945	case PCI_CHIP_RAGE128LF:
946	case PCI_CHIP_RAGE128MF:
947	case PCI_CHIP_RAGE128ML:
948	case PCI_CHIP_RAGE128RE:
949	case PCI_CHIP_RAGE128RF:
950	case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
951	case PCI_CHIP_RAGE128RK:
952	case PCI_CHIP_RAGE128RL:
953	case PCI_CHIP_RAGE128SM:
954	default:                 offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
955	}
956	break;
957    case 1:                      offset = 2; break; /*  64-bit SDR SGRAM 2:1 */
958    case 2:                      offset = 3; break; /*  64-bit DDR SGRAM     */
959    default:                     offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
960    }
961    info->ram = &R128RAM[offset];
962
963    if (dev->videoRam) {
964	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
965		   "Video RAM override, using %d kB instead of %d kB\n",
966		   dev->videoRam,
967		   pScrn->videoRam);
968	from             = X_CONFIG;
969	pScrn->videoRam  = dev->videoRam;
970    }
971
972    xf86DrvMsg(pScrn->scrnIndex, from,
973	       "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
974
975    pScrn->videoRam  &= ~1023;
976    info->FbMapSize  = pScrn->videoRam * 1024;
977
978#ifdef R128DRI
979    /* AGP/PCI */
980    if (!info->IsPCI) {
981	switch (info->Chipset) {
982	case PCI_CHIP_RAGE128LE:
983	case PCI_CHIP_RAGE128RE:
984	case PCI_CHIP_RAGE128RK:
985	case PCI_CHIP_RAGE128PD:
986	case PCI_CHIP_RAGE128PR:
987	case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE;  break;
988	case PCI_CHIP_RAGE128LF:
989	case PCI_CHIP_RAGE128MF:
990	case PCI_CHIP_RAGE128ML:
991	case PCI_CHIP_RAGE128PF:
992	case PCI_CHIP_RAGE128RF:
993	case PCI_CHIP_RAGE128RG:
994	case PCI_CHIP_RAGE128RL:
995	case PCI_CHIP_RAGE128SM:
996	case PCI_CHIP_RAGE128TF:
997	case PCI_CHIP_RAGE128TL:
998	case PCI_CHIP_RAGE128TR:
999	/* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are
1000	 * believed to be AGP, but need confirmation. <mharris@redhat.com>
1001	 */
1002	case PCI_CHIP_RAGE128PA:
1003	case PCI_CHIP_RAGE128PB:
1004	case PCI_CHIP_RAGE128PC:
1005	case PCI_CHIP_RAGE128PE:
1006	case PCI_CHIP_RAGE128PG:
1007	case PCI_CHIP_RAGE128PH:
1008	case PCI_CHIP_RAGE128PI:
1009	case PCI_CHIP_RAGE128PJ:
1010	case PCI_CHIP_RAGE128PK:
1011	case PCI_CHIP_RAGE128PL:
1012	case PCI_CHIP_RAGE128PM:
1013	case PCI_CHIP_RAGE128PN:
1014	case PCI_CHIP_RAGE128PO:
1015	case PCI_CHIP_RAGE128PQ:
1016	case PCI_CHIP_RAGE128PS:
1017	case PCI_CHIP_RAGE128PT:
1018	case PCI_CHIP_RAGE128PU:
1019	case PCI_CHIP_RAGE128PV:
1020	case PCI_CHIP_RAGE128PW:
1021	case PCI_CHIP_RAGE128PX:
1022	case PCI_CHIP_RAGE128TS:
1023	case PCI_CHIP_RAGE128TT:
1024	case PCI_CHIP_RAGE128TU:
1025	case PCI_CHIP_RAGE128SE:
1026	case PCI_CHIP_RAGE128SF:
1027	case PCI_CHIP_RAGE128SG:
1028	case PCI_CHIP_RAGE128SH:
1029	case PCI_CHIP_RAGE128SK:
1030	case PCI_CHIP_RAGE128SL:
1031	case PCI_CHIP_RAGE128SN:
1032	default:                 info->IsPCI = FALSE; break;
1033	}
1034    }
1035#endif
1036
1037    return TRUE;
1038}
1039
1040static Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1041{
1042#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__)
1043    R128InfoPtr   info = R128PTR(pScrn);
1044    vbeInfoPtr pVbe;
1045#endif
1046
1047    if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE;
1048    if (!xf86LoadSubModule(pScrn, "i2c")) return FALSE;
1049
1050#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__)
1051    /* Int10 is broken on PPC and some Alphas */
1052    return TRUE;
1053#else
1054    if (xf86LoadSubModule(pScrn, "vbe")) {
1055	pVbe = VBEInit(pInt10,info->pEnt->index);
1056	if (!pVbe) return FALSE;
1057        xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
1058	vbeFree(pVbe);
1059	return TRUE;
1060    } else
1061	return FALSE;
1062#endif
1063}
1064
1065/* This is called by R128PreInit to initialize gamma correction. */
1066static Bool R128PreInitGamma(ScrnInfoPtr pScrn)
1067{
1068    Gamma zeros = { 0.0, 0.0, 0.0 };
1069
1070    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
1071    return TRUE;
1072}
1073
1074/* This is called by R128PreInit to initialize the hardware cursor. */
1075static Bool R128PreInitCursor(ScrnInfoPtr pScrn)
1076{
1077    R128InfoPtr   info = R128PTR(pScrn);
1078
1079    if (!info->swCursor) {
1080	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
1081    }
1082    return TRUE;
1083}
1084
1085static Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
1086{
1087    R128InfoPtr   info = R128PTR(pScrn);
1088#if !defined(__powerpc__) && !defined(__alpha__)
1089    /* int10 is broken on some Alphas and powerpc */
1090    if (xf86LoadSubModule(pScrn, "int10")) {
1091	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
1092	*ppInt10 = xf86InitInt10(info->pEnt->index);
1093    }
1094#endif
1095    return TRUE;
1096}
1097
1098#ifdef R128DRI
1099static Bool R128PreInitDRI(ScrnInfoPtr pScrn)
1100{
1101    R128InfoPtr   info = R128PTR(pScrn);
1102
1103    info->agpMode        = R128_DEFAULT_AGP_MODE;
1104    info->agpSize        = R128_DEFAULT_AGP_SIZE;
1105    info->ringSize       = R128_DEFAULT_RING_SIZE;
1106    info->bufSize        = R128_DEFAULT_BUFFER_SIZE;
1107    info->agpTexSize     = R128_DEFAULT_AGP_TEX_SIZE;
1108
1109    info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
1110
1111    if (!info->IsPCI) {
1112	if (xf86GetOptValInteger(info->Options,
1113				 OPTION_AGP_MODE, &(info->agpMode))) {
1114	    if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
1115		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1116			   "Illegal AGP Mode: %d\n", info->agpMode);
1117		return FALSE;
1118	    }
1119	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1120		       "Using AGP %dx mode\n", info->agpMode);
1121	}
1122
1123	if (xf86GetOptValInteger(info->Options,
1124				 OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
1125	    switch (info->agpSize) {
1126	    case 4:
1127	    case 8:
1128	    case 16:
1129	    case 32:
1130	    case 64:
1131	    case 128:
1132	    case 256:
1133		break;
1134	    default:
1135		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1136			   "Illegal AGP size: %d MB\n", info->agpSize);
1137		return FALSE;
1138	    }
1139	}
1140
1141	if (xf86GetOptValInteger(info->Options,
1142				 OPTION_RING_SIZE, &(info->ringSize))) {
1143	    if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
1144		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1145			   "Illegal ring buffer size: %d MB\n",
1146			   info->ringSize);
1147		return FALSE;
1148	    }
1149	}
1150
1151	if (xf86GetOptValInteger(info->Options,
1152				 OPTION_BUFFER_SIZE, &(info->bufSize))) {
1153	    if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
1154		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1155			   "Illegal vertex/indirect buffers size: %d MB\n",
1156			   info->bufSize);
1157		return FALSE;
1158	    }
1159	    if (info->bufSize > 2) {
1160		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1161			   "Illegal vertex/indirect buffers size: %d MB\n",
1162			   info->bufSize);
1163		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1164			   "Clamping vertex/indirect buffers size to 2 MB\n");
1165		info->bufSize = 2;
1166	    }
1167	}
1168
1169	if (info->ringSize + info->bufSize + info->agpTexSize >
1170	    (int)info->agpSize) {
1171	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1172		       "Buffers are too big for requested AGP space\n");
1173	    return FALSE;
1174	}
1175
1176	info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
1177    }
1178
1179    if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
1180			     &(info->CCEusecTimeout))) {
1181	/* This option checked by the R128 DRM kernel module */
1182    }
1183
1184    if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1185	info->allowPageFlip = 0;
1186	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1187		   "Couldn't load shadowfb module:\n");
1188    } else {
1189	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1190						   OPTION_PAGE_FLIP,
1191						   FALSE);
1192    }
1193
1194    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n",
1195	       info->allowPageFlip ? "en" : "dis");
1196
1197    return TRUE;
1198}
1199#endif
1200
1201static Bool R128PreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1202{
1203    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1204    int found = 0;
1205    int i;
1206
1207    if (!R128GetBIOSParameters(pScrn, pInt10))
1208        return FALSE;
1209
1210    if (!R128GetPLLParameters(pScrn))
1211        return FALSE;
1212
1213    if (!R128AllocateControllers(pScrn))
1214        return FALSE;
1215
1216    if (!R128SetupConnectors(pScrn))
1217        return FALSE;
1218
1219    for (i = 0; i < config->num_output; i++) {
1220        xf86OutputPtr output = config->output[i];
1221
1222        output->status = (*output->funcs->detect) (output);
1223        if (output->status == XF86OutputStatusConnected)
1224            found++;
1225    }
1226    return !!found;
1227}
1228
1229static void
1230r128UMSOption(ScrnInfoPtr pScrn)
1231{
1232    R128InfoPtr      info = R128PTR(pScrn);
1233
1234    info->dac6bits = xf86ReturnOptValBool(info->Options,
1235                                            OPTION_DAC_6BIT, FALSE);
1236
1237#ifndef AVOID_FBDEV
1238#ifdef __powerpc__
1239    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE))
1240#else
1241    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE))
1242#endif
1243    {
1244        info->FBDev = TRUE;
1245        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1246                    "Using framebuffer device.\n");
1247    }
1248#endif
1249
1250    /* By default, don't access VGA IOs on PowerPC or SPARC. */
1251#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW)
1252    info->VGAAccess = FALSE;
1253#else
1254    info->VGAAccess = TRUE;
1255#endif
1256
1257#ifdef WITH_VGAHW
1258    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS,
1259                        &info->VGAAccess);
1260    if (info->VGAAccess) {
1261       if (!xf86LoadSubModule(pScrn, "vgahw"))
1262           info->VGAAccess = FALSE;
1263        else {
1264            if (!vgaHWGetHWRec(pScrn))
1265               info->VGAAccess = FALSE;
1266       }
1267
1268       if (!info->VGAAccess) {
1269           xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1270                       "Loading VGA module failed, trying to "
1271                       "run without it.\n");
1272       }
1273    } else
1274           xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1275                       "VGAAccess option set to FALSE, VGA "
1276                       "module load skipped.\n");
1277    if (info->VGAAccess) {
1278        vgaHWSetStdFuncs(VGAHWPTR(pScrn));
1279        vgaHWGetIOBase(VGAHWPTR(pScrn));
1280    }
1281#else
1282    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1283                "VGAHW support not compiled, VGA "
1284                "module load skipped.\n");
1285#endif
1286
1287    if (xf86ReturnOptValBool(info->Options,
1288                                OPTION_SHOW_CACHE, FALSE)) {
1289        info->showCache = TRUE;
1290        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1291                    "ShowCache enabled.\n");
1292    }
1293
1294    if (xf86ReturnOptValBool(info->Options,
1295                                OPTION_SW_CURSOR, FALSE)) {
1296        info->swCursor = TRUE;
1297        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1298                    "Software cursor requested.\n");
1299    }
1300
1301    if(xf86GetOptValInteger(info->Options,
1302                            OPTION_VIDEO_KEY, &info->videoKey)) {
1303        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1304                    "Video key set to 0x%x.\n", info->videoKey);
1305    } else {
1306        info->videoKey = 0x1E;
1307    }
1308
1309#ifdef R128DRI
1310    /* DMA for Xv */
1311    info->DMAForXv = xf86ReturnOptValBool(info->Options,
1312                                            OPTION_XV_DMA, FALSE);
1313    if (info->DMAForXv) {
1314        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1315                   "Will try to use DMA for Xv image transfers.\n");
1316    }
1317
1318    /* Force PCI Mode */
1319    info->IsPCI = xf86ReturnOptValBool(info->Options,
1320                                        OPTION_IS_PCI, FALSE);
1321    if (info->IsPCI) {
1322        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1323                    "Forced into PCI only mode.\n");
1324    }
1325
1326    if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) {
1327        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1328                    "Forcing CCE into PIO mode.\n");
1329        info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
1330    } else {
1331        info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
1332    }
1333
1334    if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
1335        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1336                    "WARNING!!! CCE Security checks disabled!!!\n");
1337        info->CCESecure = FALSE;
1338    } else {
1339        info->CCESecure = TRUE;
1340    }
1341
1342
1343#endif
1344}
1345
1346static void
1347r128AcquireOption(ScrnInfoPtr pScrn)
1348{
1349    R128InfoPtr      info = R128PTR(pScrn);
1350#ifdef USE_EXA
1351    char *optstr;
1352#endif
1353
1354    if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
1355        info->noAccel = TRUE;
1356    }
1357
1358#ifdef USE_EXA
1359    if (!info->noAccel) {
1360        optstr = (char *) xf86GetOptValString(info->Options,
1361                                                OPTION_ACCELMETHOD);
1362        if (optstr) {
1363            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1364                        "AccelMethod option found.\n");
1365            if (xf86NameCmp(optstr, "EXA") == 0) {
1366                info->useEXA = TRUE;
1367                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1368                            "AccelMethod is set to EXA, turning "
1369                            "EXA on.\n");
1370            }
1371        }
1372
1373#ifdef RENDER
1374        info->RenderAccel = xf86ReturnOptValBool(info->Options,
1375                                                    OPTION_RENDERACCEL,
1376                                                    TRUE);
1377        if (info->RenderAccel)
1378            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1379                        "Acceleration of RENDER operations will be "
1380                        "enabled upon successful loading of DRI and "
1381                        "EXA.\n");
1382#endif
1383    }
1384#endif
1385
1386    r128UMSOption(pScrn);
1387}
1388
1389static Bool R128CRTCResize(ScrnInfoPtr pScrn, int width, int height)
1390{
1391    pScrn->virtualX = width;
1392    pScrn->virtualY = height;
1393    return TRUE;
1394}
1395
1396static const xf86CrtcConfigFuncsRec R128CRTCResizeFuncs = {
1397    R128CRTCResize
1398};
1399
1400static Bool R128LegacyMS(ScrnInfoPtr pScrn)
1401{
1402    R128InfoPtr      info = R128PTR(pScrn);
1403    xf86Int10InfoPtr pInt10 = NULL;
1404    Bool ret = FALSE;
1405
1406#ifndef AVOID_FBDEV
1407    if (info->FBDev) {
1408        /* check for linux framebuffer device */
1409        if (!xf86LoadSubModule(pScrn, "fbdevhw")) goto exit;
1410        if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) goto exit;
1411        pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
1412        pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
1413        pScrn->ValidMode     = fbdevHWValidModeWeak();
1414    } else {
1415#endif /* !AVOID_FBDEV */
1416        if (!R128PreInitInt10(pScrn, &pInt10)) goto exit;
1417#ifndef AVOID_FBDEV
1418    }
1419#endif /* !AVOID_FBDEV */
1420
1421    if (!R128PreInitConfig(pScrn)) goto freeInt10;
1422
1423    xf86CrtcSetSizeRange(pScrn, 320, 200, 4096, 4096);
1424
1425    if (!R128PreInitCursor(pScrn)) goto freeInt10;
1426
1427    /* Don't fail on this one */
1428    info->DDC = R128PreInitDDC(pScrn, pInt10);
1429
1430    if (!R128PreInitControllers(pScrn, pInt10)) goto freeInt10;
1431
1432#ifdef R128DRI
1433    if (!R128PreInitDRI(pScrn)) goto freeInt10;
1434#endif
1435
1436    ret = TRUE;
1437freeInt10:
1438    /* Free int10 info */
1439    if (pInt10) {
1440        xf86FreeInt10(pInt10);
1441    }
1442
1443exit:
1444    return ret;
1445}
1446
1447static void
1448R128PreInitAccel(ScrnInfoPtr pScrn)
1449{
1450    R128InfoPtr      info = R128PTR(pScrn);
1451#ifdef USE_EXA
1452    int errmaj, errmin;
1453#endif
1454
1455    if (!info->noAccel) {
1456        if (info->useEXA) {
1457#ifdef USE_EXA
1458            info->exaReq.majorversion = EXA_VERSION_MAJOR;
1459            info->exaReq.minorversion = EXA_VERSION_MINOR;
1460
1461            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1462                        "Loading EXA module...\n");
1463            if (LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
1464                                &info->exaReq, &errmaj, &errmin)) {
1465                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1466                            "Loading EXA module.\n");
1467            } else {
1468                LoaderErrorMsg(NULL, "exa", errmaj, errmin);
1469            }
1470#endif
1471        }
1472
1473        if ((!info->useEXA) ||
1474            ((info->useEXA) && (!info->accelOn))) {
1475#ifdef HAVE_XAA_H
1476            if (xf86LoadSubModule(pScrn, "xaa")) {
1477                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1478                            "Loading XAA module.\n");
1479            }
1480#endif
1481        }
1482    }
1483}
1484
1485/* R128PreInit is called once at server startup. */
1486Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
1487{
1488    R128InfoPtr      info;
1489#ifdef __NetBSD__
1490    struct wsdisplayio_bus_id bid;
1491#endif
1492
1493    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1494                        "%s\n", __func__));
1495
1496    if (flags & PROBE_DETECT) {
1497        return TRUE;
1498    }
1499
1500    pScrn->monitor = pScrn->confScreen->monitor;
1501
1502    if (!R128PreInitVisual(pScrn)) {
1503        return FALSE;
1504    }
1505
1506    if (!R128PreInitGamma(pScrn)) {
1507        return FALSE;
1508    }
1509
1510    if (pScrn->numEntities != 1) return FALSE;
1511
1512    if (!R128GetRec(pScrn)) return FALSE;
1513
1514    info                = R128PTR(pScrn);
1515    info->SwitchingMode = FALSE;
1516    info->MMIO          = NULL;
1517
1518    info->pEnt          = xf86GetEntityInfo(pScrn->entityList[0]);
1519    if (info->pEnt->location.type != BUS_PCI) goto fail;
1520
1521    info->PciInfo       = xf86GetPciInfoForEntity(info->pEnt->index);
1522
1523    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1524	       "PCI bus %d card %d func %d\n",
1525	       PCI_DEV_BUS(info->PciInfo),
1526	       PCI_DEV_DEV(info->PciInfo),
1527	       PCI_DEV_FUNC(info->PciInfo));
1528
1529#ifdef __NetBSD__
1530    /* now check if this is the console */
1531    info->HaveWSDisplay = FALSE;
1532    info->HaveBacklightControl = FALSE;
1533    if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GET_BUSID, &bid) != -1) {
1534    	if ((bid.bus_type == WSDISPLAYIO_BUS_PCI) &&
1535    	    (bid.ubus.pci.bus == PCI_DEV_BUS(info->PciInfo)) &&
1536    	    (bid.ubus.pci.device == PCI_DEV_DEV(info->PciInfo)) &&
1537    	    (bid.ubus.pci.function == PCI_DEV_FUNC(info->PciInfo))) {
1538    	    	struct wsdisplay_param p;
1539    	    	xf86Msg(X_INFO, "Alright, this is the console\n");
1540    	    	info->HaveWSDisplay = TRUE;
1541
1542    	    	/* now see if we have hacklight control */
1543    	    	p.param = WSDISPLAYIO_PARAM_BACKLIGHT;
1544		if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GETPARAM, &p) != -1) {
1545		    xf86Msg(X_INFO, "... and we have backlight control\n");
1546		    info->HaveBacklightControl = TRUE;
1547		}
1548    	}
1549    }
1550#endif
1551
1552#ifndef XSERVER_LIBPCIACCESS
1553    info->PciTag        = pciTag(PCI_DEV_BUS(info->PciInfo),
1554				PCI_DEV_DEV(info->PciInfo),
1555				PCI_DEV_FUNC(info->PciInfo));
1556
1557    if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail;
1558    if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail;
1559
1560    pScrn->racMemFlags  = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
1561#endif
1562
1563    info->fifo_slots  = 0;
1564    info->pix24bpp    = xf86GetBppFromDepth(pScrn, pScrn->depth);
1565    info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
1566    info->CurrentLayout.depth        = pScrn->depth;
1567    info->CurrentLayout.pixel_bytes  = pScrn->bitsPerPixel / 8;
1568    info->CurrentLayout.pixel_code   = (pScrn->bitsPerPixel != 16
1569                                       ? pScrn->bitsPerPixel
1570                                       : pScrn->depth);
1571
1572    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1573           "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
1574           pScrn->depth,
1575           info->CurrentLayout.pixel_bytes,
1576           info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
1577           info->pix24bpp);
1578
1579				/* We can't do this until we have a
1580				   pScrn->display. */
1581    xf86CollectOptions(pScrn, NULL);
1582    if (!(info->Options = malloc(sizeof(R128Options))))    goto fail;
1583    memcpy(info->Options, R128Options, sizeof(R128Options));
1584    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1585
1586    info->noAccel = FALSE;
1587    info->accelOn = FALSE;
1588
1589    info->useEXA = FALSE;
1590#ifdef USE_EXA
1591    info->useEXA = TRUE;
1592#endif
1593
1594    info->swCursor = FALSE;
1595
1596    r128AcquireOption(pScrn);
1597
1598    if (!R128PreInitWeight(pScrn))    goto fail;
1599
1600    /* Allocate an xf86CrtcConfig */
1601    xf86CrtcConfigInit(pScrn, &R128CRTCResizeFuncs);
1602
1603    R128LegacyMS(pScrn);
1604
1605    if (!xf86InitialConfiguration(pScrn, TRUE)) {
1606        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
1607        goto fail;
1608    }
1609    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
1610
1611    /* Set display resolution */
1612    xf86SetDpi(pScrn, 0, 0);
1613
1614    /* Get ScreenInit function */
1615    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
1616
1617    R128PreInitAccel(pScrn);
1618
1619    info->CurrentLayout.displayWidth = pScrn->displayWidth;
1620
1621    if (!xf86RandR12PreInit(pScrn)) {
1622        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
1623        goto fail;
1624    }
1625
1626    if (pScrn->modes == NULL) {
1627        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1628        goto fail;
1629    }
1630
1631				/* Free the video bios (if applicable) */
1632    if (info->VBIOS) {
1633	free(info->VBIOS);
1634	info->VBIOS = NULL;
1635    }
1636
1637    if (info->MMIO) R128UnmapMMIO(pScrn);
1638    info->MMIO = NULL;
1639
1640    return TRUE;
1641
1642  fail:
1643				/* Pre-init failed. */
1644
1645				/* Free the video bios (if applicable) */
1646    if (info->VBIOS) {
1647	free(info->VBIOS);
1648	info->VBIOS = NULL;
1649    }
1650
1651#ifdef WITH_VGAHW
1652    if (info->VGAAccess)
1653           vgaHWFreeHWRec(pScrn);
1654#endif
1655
1656    if (info->MMIO) R128UnmapMMIO(pScrn);
1657    info->MMIO = NULL;
1658
1659    R128FreeRec(pScrn);
1660    return FALSE;
1661}
1662
1663/* Load a palette. */
1664static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
1665			    int *indices, LOCO *colors, VisualPtr pVisual)
1666{
1667    R128InfoPtr   info      = R128PTR(pScrn);
1668    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1669    int i, j;
1670    int c, index;
1671    uint16_t lut_r[256], lut_g[256], lut_b[256];
1672
1673    for (c = 0; c < xf86_config->num_crtc; c++) {
1674        xf86CrtcPtr crtc = xf86_config->crtc[c];
1675        R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
1676
1677        for (i = 0 ; i < 256; i++) {
1678            lut_r[i] = r128_crtc->lut_r[i] << 8;
1679            lut_g[i] = r128_crtc->lut_g[i] << 8;
1680            lut_b[i] = r128_crtc->lut_b[i] << 8;
1681        }
1682
1683        switch (info->CurrentLayout.depth) {
1684        case 15:
1685            for (i = 0; i < numColors; i++) {
1686                index = indices[i];
1687                for (j = 0; j < 8; j++) {
1688                    lut_r[index * 8 + j] = colors[index].red << 8;
1689                    lut_g[index * 8 + j] = colors[index].green << 8;
1690                    lut_b[index * 8 + j] = colors[index].blue << 8;
1691                }
1692            }
1693        case 16:
1694            for (i = 0; i < numColors; i++) {
1695                index = indices[i];
1696
1697                /* XXX: The old version of R128LoadPalette did not do this and
1698                 * the old version of RADEONLoadPalette has a comment asking why.
1699                 */
1700                if (i <= 31) {
1701                    for (j = 0; j < 8; j++) {
1702                        lut_r[index * 8 + j] = colors[index].red << 8;
1703                        lut_b[index * 8 + j] = colors[index].blue << 8;
1704                    }
1705                }
1706
1707                for (j = 0; j < 4; j++) {
1708                    lut_g[index * 4 + j] = colors[index].green << 8;
1709                }
1710            }
1711        default:
1712            for (i = 0; i < numColors; i++) {
1713                index = indices[i];
1714                lut_r[index] = colors[index].red << 8;
1715                lut_g[index] = colors[index].green << 8;
1716                lut_b[index] = colors[index].blue << 8;
1717            }
1718            break;
1719        }
1720
1721        /* Make the change through RandR */
1722#ifdef RANDR_12_INTERFACE
1723        if (crtc->randr_crtc)
1724            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1725        else
1726#endif
1727        crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1728    }
1729}
1730
1731static void
1732R128BlockHandler(BLOCKHANDLER_ARGS_DECL)
1733{
1734    SCREEN_PTR(arg);
1735    ScrnInfoPtr pScrn   = xf86ScreenToScrn(pScreen);
1736    R128InfoPtr info    = R128PTR(pScrn);
1737
1738#ifdef R128DRI
1739    if (info->directRenderingEnabled)
1740        FLUSH_RING();
1741#endif
1742
1743    pScreen->BlockHandler = info->BlockHandler;
1744    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1745    pScreen->BlockHandler = R128BlockHandler;
1746
1747    if(info->VideoTimerCallback) {
1748        (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
1749    }
1750}
1751
1752/* Called at the start of each server generation. */
1753Bool R128ScreenInit(SCREEN_INIT_ARGS_DECL)
1754{
1755    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1756    R128InfoPtr info   = R128PTR(pScrn);
1757    BoxRec      MemBox;
1758    int width_bytes = (pScrn->displayWidth *
1759                        info->CurrentLayout.pixel_bytes);
1760    int scanlines;
1761    int total = info->FbMapSize;
1762    FBAreaPtr fbarea = NULL;
1763#ifdef R128DRI
1764    int cpp = info->CurrentLayout.pixel_bytes;
1765    int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
1766#ifdef USE_EXA
1767    ExaOffscreenArea*     osArea = NULL;
1768#endif /* USE_EXA */
1769#endif /* R128DRI */
1770
1771    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1772                        "%s %lx %lx\n",
1773                        __func__,
1774                        pScrn->memPhysBase, pScrn->fbOffset));
1775
1776#ifdef R128DRI
1777				/* Turn off the CCE for now. */
1778    info->CCEInUse     = FALSE;
1779    info->indirectBuffer = NULL;
1780#endif
1781
1782    if (!R128MapMem(pScrn)) return FALSE;
1783    pScrn->fbOffset    = 0;
1784    //if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
1785#ifdef R128DRI
1786    info->fbX          = 0;
1787    info->fbY          = 0;
1788    info->frontOffset  = 0;
1789    info->frontPitch   = pScrn->displayWidth;
1790#endif
1791
1792    info->PaletteSavedOnVT = FALSE;
1793
1794    R128Save(pScrn);
1795
1796				/* Visual setup */
1797    miClearVisualTypes();
1798    if (!miSetVisualTypes(pScrn->depth,
1799			  miGetDefaultVisualMask(pScrn->depth),
1800			  pScrn->rgbBits,
1801			  pScrn->defaultVisual)) return FALSE;
1802    miSetPixmapDepths ();
1803
1804#ifdef R128DRI
1805				/* Setup DRI after visuals have been
1806				   established, but before fbScreenInit is
1807				   called. */
1808    {
1809	/* FIXME: When we move to dynamic allocation of back and depth
1810	   buffers, we will want to revisit the following check for 3
1811	   times the virtual size of the screen below. */
1812	int maxy        = info->FbMapSize / width_bytes;
1813
1814        if (info->noAccel) {
1815	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1816		       "Acceleration disabled, not initializing the DRI\n");
1817	    info->directRenderingEnabled = FALSE;
1818	} else if (maxy <= pScrn->virtualY * 3) {
1819	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1820		       "Static buffer allocation failed -- "
1821		       "need at least %d kB video memory\n",
1822		       (pScrn->displayWidth * pScrn->virtualY *
1823			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
1824	    info->directRenderingEnabled = FALSE;
1825	} else {
1826            info->directRenderingEnabled = R128DRIScreenInit(pScreen);
1827	}
1828    }
1829#endif
1830
1831    if (!fbScreenInit (pScreen, info->FB,
1832		       pScrn->virtualX, pScrn->virtualY,
1833		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1834		       pScrn->bitsPerPixel))
1835	return FALSE;
1836
1837    xf86SetBlackWhitePixels(pScreen);
1838
1839    if (pScrn->bitsPerPixel > 8) {
1840	VisualPtr visual;
1841
1842	visual = pScreen->visuals + pScreen->numVisuals;
1843	while (--visual >= pScreen->visuals) {
1844	    if ((visual->class | DynamicClass) == DirectColor) {
1845		visual->offsetRed   = pScrn->offset.red;
1846		visual->offsetGreen = pScrn->offset.green;
1847		visual->offsetBlue  = pScrn->offset.blue;
1848		visual->redMask     = pScrn->mask.red;
1849		visual->greenMask   = pScrn->mask.green;
1850		visual->blueMask    = pScrn->mask.blue;
1851	    }
1852	}
1853    }
1854
1855    /* must be after RGB order fixed */
1856    fbPictureInit (pScreen, 0, 0);
1857
1858				/* Memory manager setup */
1859#ifdef R128DRI
1860    if (info->directRenderingEnabled) {
1861	int bufferSize = pScrn->virtualY * width_bytes;
1862	int l;
1863
1864	switch (info->CCEMode) {
1865	case R128_DEFAULT_CCE_PIO_MODE:
1866	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
1867	    break;
1868	case R128_DEFAULT_CCE_BM_MODE:
1869	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
1870	    break;
1871	default:
1872	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
1873	    break;
1874	}
1875
1876	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1877		   "Using %d MB AGP aperture\n", info->agpSize);
1878	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1879		   "Using %d MB for the ring buffer\n", info->ringSize);
1880	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1881		   "Using %d MB for vertex/indirect buffers\n", info->bufSize);
1882	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1883		   "Using %d MB for AGP textures\n", info->agpTexSize);
1884
1885	/* Try for front, back, depth, and two framebuffers worth of
1886	 * pixmap cache.  Should be enough for a fullscreen background
1887	 * image plus some leftovers.
1888	 */
1889	info->textureSize = info->FbMapSize - 5 * bufferSize;
1890
1891	/* If that gives us less than half the available memory, let's
1892	 * be greedy and grab some more.  Sorry, I care more about 3D
1893	 * performance than playing nicely, and you'll get around a full
1894	 * framebuffer's worth of pixmap cache anyway.
1895	 */
1896	if (info->textureSize < (int)info->FbMapSize / 2) {
1897	    info->textureSize = info->FbMapSize - 4 * bufferSize;
1898	}
1899
1900	if (info->textureSize > 0) {
1901	    l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
1902	    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
1903
1904	    /* Round the texture size up to the nearest whole number of
1905	     * texture regions.  Again, be greedy about this, don't
1906	     * round down.
1907	     */
1908	    info->log2TexGran = l;
1909	    info->textureSize = (info->textureSize >> l) << l;
1910	} else {
1911	    info->textureSize = 0;
1912	}
1913
1914	/* Set a minimum usable local texture heap size.  This will fit
1915	 * two 256x256x32bpp textures.
1916	 */
1917	if (info->textureSize < 512 * 1024) {
1918	    info->textureOffset = 0;
1919	    info->textureSize = 0;
1920	}
1921
1922        total = info->FbMapSize - info->textureSize;
1923    }
1924#endif /* R128DRI */
1925
1926    scanlines = total / width_bytes;
1927    if (scanlines > 8191) scanlines = 8191;
1928
1929#ifdef R128DRI
1930    if (info->directRenderingEnabled)
1931        /*
1932         * Recalculate the texture offset and size to accommodate any
1933         * rounding to a whole number of scanlines.
1934         */
1935        info->textureOffset = scanlines * width_bytes;
1936#endif /* R128DRI */
1937
1938    MemBox.x1 = 0;
1939    MemBox.y1 = 0;
1940    MemBox.x2 = pScrn->displayWidth;
1941    MemBox.y2 = scanlines;
1942
1943	if (!info->useEXA) {
1944	    if (!xf86InitFBManager(pScreen, &MemBox)) {
1945	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1946		           "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
1947		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
1948	        return FALSE;
1949	    } else {
1950	        int width, height;
1951
1952	        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1953		           "Memory manager initialized to (%d,%d) (%d,%d)\n",
1954		           MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
1955	        if ((fbarea = xf86AllocateOffscreenArea(pScreen,
1956						        pScrn->displayWidth,
1957						        2, 0, NULL, NULL, NULL))) {
1958		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1959			       "Reserved area from (%d,%d) to (%d,%d)\n",
1960			       fbarea->box.x1, fbarea->box.y1,
1961			       fbarea->box.x2, fbarea->box.y2);
1962	        } else {
1963		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve area\n");
1964	        }
1965	        if (xf86QueryLargestOffscreenArea(pScreen, &width,
1966						  &height, 0, 0, 0)) {
1967		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1968			       "Largest offscreen area available: %d x %d\n",
1969				width, height);
1970	        }
1971
1972            if (!info->noAccel) {
1973                if (R128XAAAccelInit(pScreen)) {
1974                    info->accelOn = TRUE;
1975                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1976                                "XAA acceleration enabled.\n");
1977                } else {
1978                    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1979                                "Acceleration disabled.\n");
1980                }
1981            }
1982        }
1983    }
1984#ifdef USE_EXA
1985    else {
1986        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1987                    "Filling in EXA memory info\n");
1988
1989
1990        /*
1991         * Don't give EXA the true full memory size, because
1992         * the textureSize sized chunk on the end is handled
1993         * by DRI.
1994         */
1995        if (R128EXAInit(pScreen, total)) {
1996            info->accelOn = TRUE;
1997            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1998                        "EXA Acceleration enabled.\n");
1999        } else {
2000            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2001                        "EXA Acceleration initialization "
2002                        "failed.\n");
2003            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2004                        "Acceleration disabled.\n");
2005        }
2006    }
2007#endif
2008
2009#ifdef R128DRI
2010    if (info->directRenderingEnabled) {
2011				/* Allocate the shared back buffer */
2012	if(!info->useEXA) {
2013	    fbarea = xf86AllocateOffscreenArea(pScreen,
2014					       pScrn->virtualX,
2015					       pScrn->virtualY,
2016					       32, NULL, NULL, NULL);
2017
2018	    if (fbarea) {
2019		x1 = fbarea->box.x1;
2020		x2 = fbarea->box.x2;
2021		y1 = fbarea->box.y1;
2022		y2 = fbarea->box.y2;
2023	    }
2024	}
2025#ifdef USE_EXA
2026	else {
2027	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2028		       "Actually trying an EXA allocation...\n");
2029	    osArea = exaOffscreenAlloc(pScreen,
2030				       pScrn->virtualY * width_bytes,
2031				       32, TRUE, NULL, NULL);
2032
2033	    if (osArea) {
2034		x1 = osArea->offset % width_bytes;
2035		x2 = (osArea->offset + osArea->size) % width_bytes;
2036		y1 = osArea->offset / width_bytes;
2037		y2 = (osArea->offset + osArea->size) / width_bytes;
2038
2039		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Went swimmingly...\n");
2040	    }
2041	}
2042#endif
2043
2044	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
2045	    /* info->backOffset = y1 * width_bytes + x1 * cpp; */
2046	    info->backOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
2047	    info->backX = info->backOffset % width_bytes;
2048	    info->backY = info->backOffset / width_bytes;
2049	    info->backPitch = pScrn->displayWidth;
2050
2051	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2052		       "Reserved back buffer from (%d,%d) to (%d,%d) offset: %x\n",
2053		       x1, y1,
2054		       x2, y2, info->backOffset);
2055	} else {
2056	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
2057	    info->backX = -1;
2058	    info->backY = -1;
2059	    info->backOffset = -1;
2060	    info->backPitch = -1;
2061	}
2062
2063				/* Allocate the shared depth buffer */
2064	if(!info->useEXA) {
2065	    fbarea = xf86AllocateOffscreenArea(pScreen,
2066					       pScrn->virtualX,
2067					       pScrn->virtualY + 1,
2068					       32, NULL, NULL, NULL);
2069	    if (fbarea) {
2070		x1 = fbarea->box.x1;
2071		x2 = fbarea->box.x2;
2072		y1 = fbarea->box.y1;
2073		y2 = fbarea->box.y2;
2074	    }
2075	}
2076#ifdef USE_EXA
2077	else {
2078	    osArea = exaOffscreenAlloc(pScreen,
2079				       (pScrn->virtualY + 1) * width_bytes,
2080				       32, TRUE, NULL, NULL);
2081
2082	    if (osArea) {
2083		x1 = osArea->offset % width_bytes;
2084		x2 = (osArea->offset + osArea->size) % width_bytes;
2085		y1 = osArea->offset / width_bytes;
2086		y2 = (osArea->offset + osArea->size) / width_bytes;
2087	    }
2088	}
2089#endif
2090
2091	if ((!info->useEXA && fbarea) || (info->useEXA && osArea)) {
2092	    /* info->depthOffset = y1 * width_bytes + x1 * cpp; */
2093	    info->depthOffset = R128_ALIGN(y1 * width_bytes + x1 * cpp, 16);
2094	    info->depthX = info->depthOffset % width_bytes;
2095	    info->depthY = info->depthOffset / width_bytes;
2096	    info->depthPitch = pScrn->displayWidth;
2097	    info->spanOffset = (y2 - 1) * width_bytes + x1 * cpp;
2098
2099	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2100		       "Reserved depth buffer from (%d,%d) to (%d,%d) offset: %x\n",
2101		       x1, y1,
2102		       x2, y2, info->depthOffset);
2103
2104	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2105		       "Reserved depth span from (%d,%d) offset 0x%x\n",
2106		       x1, y2 - 1, info->spanOffset);
2107	} else {
2108	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
2109	    info->depthX = -1;
2110	    info->depthY = -1;
2111	    info->depthOffset = -1;
2112	    info->depthPitch = -1;
2113	    info->spanOffset = -1;
2114	}
2115
2116	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2117		   "Reserved %d kb for textures at offset 0x%x\n",
2118		   info->textureSize/1024, info->textureOffset);
2119    }
2120#endif /* R128DRI */
2121
2122    pScrn->vtSema = TRUE;
2123    /* xf86CrtcRotate accesses pScrn->pScreen */
2124    pScrn->pScreen = pScreen;
2125
2126#ifndef AVOID_FBDEV
2127    if (info->FBDev) {
2128	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
2129    } else {
2130#endif
2131	if (!xf86SetDesiredModes(pScrn)) return FALSE;
2132#ifndef AVOID_FBDEV
2133    }
2134#endif
2135
2136    R128SaveScreen(pScreen, SCREEN_SAVER_ON);
2137    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2138
2139				/* DGA setup */
2140#ifdef XFreeXDGA
2141    xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset);
2142#endif
2143
2144				/* Backing store setup */
2145    xf86SetBackingStore(pScreen);
2146
2147				/* Set Silken Mouse */
2148    xf86SetSilkenMouse(pScreen);
2149
2150				/* Cursor setup */
2151    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2152
2153				/* Hardware cursor setup */
2154    if (!info->swCursor) {
2155	if (R128CursorInit(pScreen)) {
2156	    int width, height;
2157
2158	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2159					      0, 0, 0)) {
2160		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2161			   "Largest offscreen area available: %d x %d\n",
2162			   width, height);
2163	    }
2164	} else {
2165	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2166		       "Hardware cursor initialization failed\n");
2167	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2168	}
2169    } else {
2170	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using software cursor\n");
2171    }
2172
2173    /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
2174#ifndef AVOID_FBDEV
2175    if (info->FBDev)
2176	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
2177    else
2178#endif
2179        xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2180
2181    R128InitVideo(pScreen);
2182
2183				/* Provide SaveScreen */
2184    pScreen->SaveScreen  = R128SaveScreen;
2185
2186				/* Wrap CloseScreen */
2187    info->CloseScreen    = pScreen->CloseScreen;
2188    pScreen->CloseScreen = R128CloseScreen;
2189
2190				/* Note unused options */
2191    if (serverGeneration == 1)
2192	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2193
2194#ifdef R128DRI
2195				/* DRI finalization */
2196    if (info->directRenderingEnabled) {
2197				/* Now that mi, fb, drm and others have
2198				   done their thing, complete the DRI
2199				   setup. */
2200	info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
2201    }
2202    if (info->directRenderingEnabled) {
2203	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2204    } else {
2205	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2206		   "Direct rendering disabled\n");
2207    }
2208#endif
2209
2210    info->BlockHandler = pScreen->BlockHandler;
2211    pScreen->BlockHandler = R128BlockHandler;
2212
2213    if (!xf86CrtcScreenInit(pScreen)) return FALSE;
2214
2215				/* Colormap setup */
2216    if (!miCreateDefColormap(pScreen)) return FALSE;
2217    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
2218			     (
2219#ifndef AVOID_FBDEV
2220			     info->FBDev ? fbdevHWLoadPaletteWeak() :
2221#endif
2222			     R128LoadPalette), NULL,
2223			     CMAP_PALETTED_TRUECOLOR
2224			     | CMAP_RELOAD_ON_MODE_SWITCH
2225#if 0 /* This option messes up text mode! (eich@suse.de) */
2226			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
2227#endif
2228			     )) return FALSE;
2229
2230    return TRUE;
2231}
2232
2233/* Write common registers (initialized to 0). */
2234void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2235{
2236    R128InfoPtr   info      = R128PTR(pScrn);
2237    unsigned char *R128MMIO = info->MMIO;
2238
2239    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
2240
2241    OUTREG(R128_OVR_CLR,              restore->ovr_clr);
2242    OUTREG(R128_OVR_WID_LEFT_RIGHT,   restore->ovr_wid_left_right);
2243    OUTREG(R128_OVR_WID_TOP_BOTTOM,   restore->ovr_wid_top_bottom);
2244    OUTREG(R128_OV0_SCALE_CNTL,       restore->ov0_scale_cntl);
2245    OUTREG(R128_MPP_TB_CONFIG,        restore->mpp_tb_config );
2246    OUTREG(R128_MPP_GP_CONFIG,        restore->mpp_gp_config );
2247    OUTREG(R128_SUBPIC_CNTL,          restore->subpic_cntl);
2248    OUTREG(R128_VIPH_CONTROL,         restore->viph_control);
2249    OUTREG(R128_I2C_CNTL_1,           restore->i2c_cntl_1);
2250    OUTREG(R128_GEN_INT_CNTL,         restore->gen_int_cntl);
2251    OUTREG(R128_CAP0_TRIG_CNTL,       restore->cap0_trig_cntl);
2252    OUTREG(R128_CAP1_TRIG_CNTL,       restore->cap1_trig_cntl);
2253    OUTREG(R128_BUS_CNTL,             restore->bus_cntl);
2254    OUTREG(R128_CONFIG_CNTL,          restore->config_cntl);
2255}
2256
2257/* Write RMX registers */
2258void R128RestoreRMXRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2259{
2260    R128InfoPtr   info      = R128PTR(pScrn);
2261    unsigned char *R128MMIO = info->MMIO;
2262
2263    OUTREG(R128_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
2264    OUTREG(R128_FP_VERT_STRETCH,      restore->fp_vert_stretch);
2265    OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
2266    OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
2267    OUTREG(R128_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
2268    OUTREG(R128_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
2269}
2270
2271/* Write flat panel registers */
2272void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2273{
2274    R128InfoPtr   info      = R128PTR(pScrn);
2275    unsigned char *R128MMIO = info->MMIO;
2276
2277    OUTREG(R128_TMDS_CRC,              restore->tmds_crc);
2278    OUTREG(R128_TMDS_TRANSMITTER_CNTL, restore->tmds_transmitter_cntl);
2279    OUTREG(R128_FP_PANEL_CNTL,         restore->fp_panel_cntl);
2280    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(uint32_t)R128_FP_BLANK_DIS);
2281}
2282
2283/* Write LVDS registers */
2284void R128RestoreLVDSRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2285{
2286    R128InfoPtr   info      = R128PTR(pScrn);
2287    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2288    unsigned char *R128MMIO = info->MMIO;
2289    uint32_t      tmp;
2290
2291    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2292    R128OutputPrivatePtr r128_output = output->driver_private;
2293
2294    tmp = INREG(R128_LVDS_GEN_CNTL);
2295    if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
2296	(restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
2297	OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2298    } else {
2299	if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
2300	    OUTREG(R128_LVDS_GEN_CNTL,
2301		   restore->lvds_gen_cntl & (uint32_t)~R128_LVDS_BLON);
2302	    usleep(r128_output->PanelPwrDly * 1000);
2303	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2304	} else {
2305	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
2306	    usleep(r128_output->PanelPwrDly * 1000);
2307	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2308	}
2309    }
2310}
2311
2312/* Write DDA registers. */
2313void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2314{
2315    R128InfoPtr   info      = R128PTR(pScrn);
2316    unsigned char *R128MMIO = info->MMIO;
2317
2318    OUTREG(R128_DDA_CONFIG, restore->dda_config);
2319    OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
2320}
2321
2322/* Write DDA registers. */
2323void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2324{
2325    R128InfoPtr   info      = R128PTR(pScrn);
2326    unsigned char *R128MMIO = info->MMIO;
2327
2328    OUTREG(R128_DDA2_CONFIG, restore->dda2_config);
2329    OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off);
2330}
2331
2332/* Read common registers. */
2333static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2334{
2335    R128InfoPtr   info      = R128PTR(pScrn);
2336    unsigned char *R128MMIO = info->MMIO;
2337
2338    save->ovr_clr            = INREG(R128_OVR_CLR);
2339    save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
2340    save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
2341    save->ov0_scale_cntl     = INREG(R128_OV0_SCALE_CNTL);
2342    save->mpp_tb_config      = INREG(R128_MPP_TB_CONFIG);
2343    save->mpp_gp_config      = INREG(R128_MPP_GP_CONFIG);
2344    save->subpic_cntl        = INREG(R128_SUBPIC_CNTL);
2345    save->viph_control       = INREG(R128_VIPH_CONTROL);
2346    save->i2c_cntl_1         = INREG(R128_I2C_CNTL_1);
2347    save->gen_int_cntl       = INREG(R128_GEN_INT_CNTL);
2348    save->cap0_trig_cntl     = INREG(R128_CAP0_TRIG_CNTL);
2349    save->cap1_trig_cntl     = INREG(R128_CAP1_TRIG_CNTL);
2350    save->bus_cntl           = INREG(R128_BUS_CNTL);
2351    save->config_cntl        = INREG(R128_CONFIG_CNTL);
2352}
2353
2354/* Read CRTC registers. */
2355static void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2356{
2357    R128InfoPtr   info      = R128PTR(pScrn);
2358    unsigned char *R128MMIO = info->MMIO;
2359
2360    save->crtc_gen_cntl        = INREG(R128_CRTC_GEN_CNTL);
2361    save->crtc_ext_cntl        = INREG(R128_CRTC_EXT_CNTL);
2362    save->dac_cntl             = INREG(R128_DAC_CNTL);
2363    save->crtc_h_total_disp    = INREG(R128_CRTC_H_TOTAL_DISP);
2364    save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
2365    save->crtc_v_total_disp    = INREG(R128_CRTC_V_TOTAL_DISP);
2366    save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
2367    save->crtc_offset          = INREG(R128_CRTC_OFFSET);
2368    save->crtc_offset_cntl     = INREG(R128_CRTC_OFFSET_CNTL);
2369    save->crtc_pitch           = INREG(R128_CRTC_PITCH);
2370}
2371
2372/* Read flat panel registers */
2373static void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2374{
2375    R128InfoPtr   info      = R128PTR(pScrn);
2376    unsigned char *R128MMIO = info->MMIO;
2377
2378    save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
2379    save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
2380    save->fp_gen_cntl          = INREG(R128_FP_GEN_CNTL);
2381    save->fp_h_sync_strt_wid   = INREG(R128_FP_H_SYNC_STRT_WID);
2382    save->fp_horz_stretch      = INREG(R128_FP_HORZ_STRETCH);
2383    save->fp_panel_cntl        = INREG(R128_FP_PANEL_CNTL);
2384    save->fp_v_sync_strt_wid   = INREG(R128_FP_V_SYNC_STRT_WID);
2385    save->fp_vert_stretch      = INREG(R128_FP_VERT_STRETCH);
2386    save->lvds_gen_cntl        = INREG(R128_LVDS_GEN_CNTL);
2387    save->tmds_crc             = INREG(R128_TMDS_CRC);
2388    save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
2389}
2390
2391/* Read CRTC2 registers. */
2392static void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2393{
2394    R128InfoPtr info        = R128PTR(pScrn);
2395    unsigned char *R128MMIO = info->MMIO;
2396
2397    save->crtc2_gen_cntl        = INREG(R128_CRTC2_GEN_CNTL);
2398    save->crtc2_h_total_disp    = INREG(R128_CRTC2_H_TOTAL_DISP);
2399    save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID);
2400    save->crtc2_v_total_disp    = INREG(R128_CRTC2_V_TOTAL_DISP);
2401    save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID);
2402    save->crtc2_offset          = INREG(R128_CRTC2_OFFSET);
2403    save->crtc2_offset_cntl     = INREG(R128_CRTC2_OFFSET_CNTL);
2404    save->crtc2_pitch           = INREG(R128_CRTC2_PITCH);
2405}
2406
2407/* Read PLL registers. */
2408static void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2409{
2410    save->ppll_ref_div         = INPLL(pScrn, R128_PPLL_REF_DIV);
2411    save->ppll_div_3           = INPLL(pScrn, R128_PPLL_DIV_3);
2412    save->ppll_div_0           = INPLL(pScrn, R128_PPLL_DIV_0);
2413    save->htotal_cntl          = INPLL(pScrn, R128_HTOTAL_CNTL);
2414
2415    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2416                        "Read: 0x%08x 0x%08x 0x%08x\n",
2417                        save->ppll_ref_div,
2418                        save->ppll_div_3,
2419                        save->htotal_cntl));
2420    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2421                        "Read: rd=%d, fd=%d, pd=%d\n",
2422                        save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
2423                        save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
2424                        (save->ppll_div_3 &
2425                                R128_PPLL_POST3_DIV_MASK) >> 16));
2426}
2427
2428/* Read PLL2 registers. */
2429static void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2430{
2431    save->p2pll_ref_div        = INPLL(pScrn, R128_P2PLL_REF_DIV);
2432    save->p2pll_div_0          = INPLL(pScrn, R128_P2PLL_DIV_0);
2433    save->htotal_cntl2         = INPLL(pScrn, R128_HTOTAL2_CNTL);
2434
2435    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2436                        "Read: 0x%08x 0x%08x 0x%08x\n",
2437                        save->p2pll_ref_div,
2438                        save->p2pll_div_0,
2439                        save->htotal_cntl2));
2440    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2441                        "Read: rd=%d, fd=%d, pd=%d\n",
2442                        save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
2443                        save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
2444                        (save->p2pll_div_0 &
2445                                R128_P2PLL_POST0_DIV_MASK) >> 16));
2446}
2447
2448/* Read DDA registers. */
2449static void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
2450{
2451    R128InfoPtr   info      = R128PTR(pScrn);
2452    unsigned char *R128MMIO = info->MMIO;
2453
2454    save->dda_config           = INREG(R128_DDA_CONFIG);
2455    save->dda_on_off           = INREG(R128_DDA_ON_OFF);
2456}
2457
2458/* Read DDA2 registers. */
2459static void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
2460{
2461    R128InfoPtr   info      = R128PTR(pScrn);
2462    unsigned char *R128MMIO = info->MMIO;
2463
2464    save->dda2_config           = INREG(R128_DDA2_CONFIG);
2465    save->dda2_on_off           = INREG(R128_DDA2_ON_OFF);
2466}
2467
2468/* Read palette data. */
2469static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
2470{
2471    R128InfoPtr   info      = R128PTR(pScrn);
2472    unsigned char *R128MMIO = info->MMIO;
2473    int           i;
2474
2475    PAL_SELECT(1);
2476    INPAL_START(0);
2477    for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
2478    PAL_SELECT(0);
2479    INPAL_START(0);
2480    for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
2481    save->palette_valid = TRUE;
2482}
2483
2484/* Save state that defines current video mode. */
2485static void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
2486{
2487    R128InfoPtr   info      = R128PTR(pScrn);
2488    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2489
2490    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2491                        "%s(%p)\n", __func__, save));
2492
2493    R128SaveCommonRegisters(pScrn, save);
2494    R128SaveCrtcRegisters(pScrn, save);
2495    R128SavePLLRegisters(pScrn, save);
2496    R128SaveDDARegisters(pScrn, save);
2497    if (pR128Ent->HasCRTC2) {
2498        R128SaveCrtc2Registers(pScrn, save);
2499        R128SavePLL2Registers(pScrn, save);
2500        R128SaveDDA2Registers(pScrn, save);
2501    }
2502    if (info->HasPanelRegs) {
2503        R128SaveFPRegisters(pScrn, save);
2504    }
2505    R128SavePalette(pScrn, save);
2506
2507    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2508                        "%s returns %p\n", __func__, save));
2509}
2510
2511/* Save everything needed to restore the original VC state. */
2512static void R128Save(ScrnInfoPtr pScrn)
2513{
2514    R128InfoPtr   info      = R128PTR(pScrn);
2515    unsigned char *R128MMIO = info->MMIO;
2516    R128SavePtr   save      = &info->SavedReg;
2517
2518#ifndef AVOID_FBDEV
2519    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2520                        "%s\n", __func__));
2521    if (info->FBDev) {
2522	fbdevHWSave(pScrn);
2523	return;
2524    }
2525#endif
2526
2527#ifdef WITH_VGAHW
2528    if (info->VGAAccess) {
2529        vgaHWPtr hwp = VGAHWPTR(pScrn);
2530
2531        vgaHWUnlock(hwp);
2532# if defined(__powerpc__)
2533        /* temporary hack to prevent crashing on PowerMacs when trying to
2534         * read VGA fonts and colormap, will find a better solution
2535         * in the future. TODO: Check if there's actually some VGA stuff
2536         * setup in the card at all !!
2537         */
2538        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
2539# else
2540        /* Save mode * & fonts & cmap */
2541        vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
2542# endif
2543        vgaHWLock(hwp);
2544    }
2545#endif
2546
2547    save->dp_datatype      = INREG(R128_DP_DATATYPE);
2548    save->gen_reset_cntl   = INREG(R128_GEN_RESET_CNTL);
2549    save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
2550    save->amcgpio_en_reg   = INREG(R128_AMCGPIO_EN_REG);
2551    save->amcgpio_mask     = INREG(R128_AMCGPIO_MASK);
2552
2553    R128SaveMode(pScrn, save);
2554}
2555
2556/* Restore the original (text) mode. */
2557static void R128Restore(ScrnInfoPtr pScrn)
2558{
2559    R128InfoPtr   info      = R128PTR(pScrn);
2560    R128EntPtr    pR128Ent  = R128EntPriv(pScrn);
2561    unsigned char *R128MMIO = info->MMIO;
2562    R128SavePtr   restore   = &info->SavedReg;
2563
2564#ifndef AVOID_FBDEV
2565    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2566                        "%s\n", __func__));
2567    if (info->FBDev) {
2568	fbdevHWRestore(pScrn);
2569	return;
2570    }
2571#endif
2572    R128Blank(pScrn);
2573
2574    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
2575    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
2576    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
2577    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
2578    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
2579
2580    R128RestoreCommonRegisters(pScrn, restore);
2581    if (pR128Ent->HasCRTC2) {
2582        R128RestoreDDA2Registers(pScrn, restore);
2583        R128RestoreCrtc2Registers(pScrn, restore);
2584        R128RestorePLL2Registers(pScrn, restore);
2585    }
2586    R128RestoreDDARegisters(pScrn, restore);
2587    R128RestoreCrtcRegisters(pScrn, restore);
2588    R128RestorePLLRegisters(pScrn, restore);
2589    R128RestoreDACRegisters(pScrn, restore);
2590    R128RestoreRMXRegisters(pScrn, restore);
2591    R128RestoreFPRegisters(pScrn, restore);
2592    R128RestoreLVDSRegisters(pScrn, restore);
2593
2594    OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
2595    OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
2596    OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
2597    OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
2598    OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
2599
2600#ifdef WITH_VGAHW
2601    if (info->VGAAccess) {
2602        vgaHWPtr hwp = VGAHWPTR(pScrn);
2603        vgaHWUnlock(hwp);
2604# if defined(__powerpc__)
2605        /* Temporary hack to prevent crashing on PowerMacs when trying to
2606         * write VGA fonts, will find a better solution in the future
2607         */
2608        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
2609# else
2610        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
2611# endif
2612        vgaHWLock(hwp);
2613    }
2614#endif
2615
2616    R128WaitForVerticalSync(pScrn);
2617    R128Unblank(pScrn);
2618}
2619
2620/* Define common registers for requested video mode. */
2621void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
2622{
2623    save->ovr_clr            = 0;
2624    save->ovr_wid_left_right = 0;
2625    save->ovr_wid_top_bottom = 0;
2626    save->ov0_scale_cntl     = 0;
2627    save->mpp_tb_config      = 0;
2628    save->mpp_gp_config      = 0;
2629    save->subpic_cntl        = 0;
2630    save->viph_control       = 0;
2631    save->i2c_cntl_1         = 0;
2632#ifdef R128DRI
2633    save->gen_int_cntl       = info->gen_int_cntl;
2634#else
2635    save->gen_int_cntl       = 0;
2636#endif
2637    save->cap0_trig_cntl     = 0;
2638    save->cap1_trig_cntl     = 0;
2639    save->bus_cntl           = info->BusCntl;
2640    /*
2641     * If bursts are enabled, turn on discards and aborts
2642     */
2643    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
2644	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
2645}
2646
2647/* Define RMX registers for the requested video mode. */
2648void R128InitRMXRegisters(R128SavePtr orig, R128SavePtr save,
2649                          xf86OutputPtr output, DisplayModePtr mode)
2650{
2651    R128OutputPrivatePtr r128_output = output->driver_private;
2652
2653    int   xres = mode->CrtcHDisplay;
2654    int   yres = mode->CrtcVDisplay;
2655    float Hratio, Vratio;
2656
2657    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
2658    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
2659    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
2660    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
2661
2662    if (r128_output->MonType != MT_DFP && r128_output->MonType != MT_LCD)
2663        return;
2664
2665    if (r128_output->PanelXRes == 0 || r128_output->PanelYRes == 0) {
2666        xres = r128_output->PanelXRes;
2667        yres = r128_output->PanelYRes;
2668
2669        Hratio = 1.0;
2670        Vratio = 1.0;
2671    } else {
2672        if (xres > r128_output->PanelXRes) xres = r128_output->PanelXRes;
2673        if (yres > r128_output->PanelYRes) yres = r128_output->PanelYRes;
2674
2675        Hratio = (float)xres/(float)r128_output->PanelXRes;
2676        Vratio = (float)yres/(float)r128_output->PanelYRes;
2677    }
2678
2679    save->fp_horz_stretch =
2680	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
2681	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
2682       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
2683                                 R128_HORZ_FP_LOOP_STRETCH |
2684                                 R128_HORZ_STRETCH_RESERVED)));
2685    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
2686    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
2687    if (xres == r128_output->PanelXRes)
2688         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
2689    else
2690         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
2691
2692    save->fp_vert_stretch =
2693	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
2694	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
2695	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
2696				   R128_VERT_STRETCH_RESERVED)));
2697    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
2698    if (yres == r128_output->PanelYRes)
2699        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
2700    else
2701        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
2702}
2703
2704/* Define flat panel registers for the requested video mode. */
2705void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
2706{
2707    xf86CrtcPtr crtc = output->crtc;
2708    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
2709
2710    /* WARNING: Be careful about turning on the flat panel */
2711    save->fp_gen_cntl            = orig->fp_gen_cntl;
2712    save->fp_panel_cntl          = orig->fp_panel_cntl;
2713    save->tmds_transmitter_cntl  = orig->tmds_transmitter_cntl;
2714    save->tmds_crc               = orig->tmds_crc;
2715
2716    if (r128_crtc->crtc_id)
2717        save->fp_gen_cntl       |=   R128_FP_SEL_CRTC2;
2718    else
2719        save->fp_gen_cntl       &=  ~R128_FP_SEL_CRTC2;
2720
2721    save->fp_gen_cntl           &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
2722                                     R128_FP_CRTC_USE_SHADOW_ROWCUR |
2723                                     R128_FP_CRTC_HORZ_DIV2_EN |
2724                                     R128_FP_CRTC_HOR_CRT_DIV2_DIS |
2725                                     R128_FP_CRT_SYNC_SEL |
2726                                     R128_FP_USE_SHADOW_EN);
2727
2728    save->fp_gen_cntl           |=  (R128_FP_CRTC_DONT_SHADOW_VPAR |
2729                                     R128_FP_CRTC_DONT_SHADOW_HEND);
2730
2731    save->fp_panel_cntl         |=  (R128_FP_DIGON | R128_FP_BLON);
2732    save->tmds_transmitter_cntl &=  ~R128_TMDS_PLLRST;
2733    save->tmds_transmitter_cntl |=   R128_TMDS_PLLEN;
2734}
2735
2736/* Define LVDS registers for the requested video mode. */
2737void R128InitLVDSRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output)
2738{
2739    xf86CrtcPtr crtc = output->crtc;
2740    R128CrtcPrivatePtr r128_crtc = crtc->driver_private;
2741
2742    save->lvds_gen_cntl      =  orig->lvds_gen_cntl;
2743
2744    if (r128_crtc->crtc_id)
2745        save->lvds_gen_cntl |=  R128_LVDS_SEL_CRTC2;
2746    else
2747        save->lvds_gen_cntl &= ~R128_LVDS_SEL_CRTC2;
2748}
2749
2750#if 0
2751/* Define initial palette for requested video mode.  This doesn't do
2752   anything for XFree86 4.0. */
2753static void R128InitPalette(R128SavePtr save)
2754{
2755    save->palette_valid = FALSE;
2756}
2757#endif
2758
2759static Bool R128SaveScreen(ScreenPtr pScreen, int mode)
2760{
2761    ScrnInfoPtr   pScrn = xf86ScreenToScrn(pScreen);
2762    Bool unblank;
2763
2764    unblank = xf86IsUnblank(mode);
2765    if (unblank)
2766	SetTimeSinceLastInputEvent();
2767
2768    if ((pScrn != NULL) && pScrn->vtSema) {
2769	if (unblank)
2770		R128Unblank(pScrn);
2771	else
2772		R128Blank(pScrn);
2773    }
2774    return TRUE;
2775}
2776
2777/*
2778 * SwitchMode() doesn't work right on crtc2 on some laptops.
2779 * The workaround is to switch the mode, then switch to another VT, then
2780 * switch back. --AGD
2781 */
2782Bool R128SwitchMode(SWITCH_MODE_ARGS_DECL)
2783{
2784    SCRN_INFO_PTR(arg);
2785    R128InfoPtr info        = R128PTR(pScrn);
2786    Bool ret;
2787
2788    info->SwitchingMode = TRUE;
2789    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
2790    info->SwitchingMode = FALSE;
2791    return ret;
2792}
2793
2794ModeStatus R128DoValidMode(xf86OutputPtr output, DisplayModePtr mode, int flags)
2795{
2796    ScrnInfoPtr pScrn = output->scrn;
2797    R128InfoPtr info  = R128PTR(pScrn);
2798    R128OutputPrivatePtr r128_output = output->driver_private;
2799    int i, j;
2800
2801    if (r128_output->MonType == MT_CRT)
2802        return MODE_OK;
2803
2804    if (r128_output->MonType == MT_DFP || r128_output->MonType == MT_LCD) {
2805	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
2806	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
2807    }
2808
2809    if (r128_output->MonType == MT_LCD && info->VBIOS) {
2810	for (i = info->FPBIOSstart + 64; R128_BIOS16(i) != 0; i += 2) {
2811	    j = R128_BIOS16(i);
2812
2813	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
2814		mode->CrtcVDisplay == R128_BIOS16(j + 2)) {
2815		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
2816		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2817			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
2818			       mode->CrtcHDisplay, mode->CrtcVDisplay,
2819			       (float)mode->Clock / 1000);
2820
2821		    /* Assume we are using expanded mode */
2822		    if (R128_BIOS16(j + 5)) j  = R128_BIOS16(j + 5);
2823		    else                    j += 9;
2824
2825		    mode->Clock = (uint32_t)R128_BIOS16(j) * 10;
2826
2827		    mode->HDisplay   = mode->CrtcHDisplay   =
2828			((R128_BIOS16(j + 10) & 0x01ff) + 1) * 8;
2829		    mode->HSyncStart = mode->CrtcHSyncStart =
2830			((R128_BIOS16(j + 12) & 0x01ff) + 1) * 8;
2831		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
2832			mode->CrtcHSyncStart + (R128_BIOS8(j + 14) & 0x1f);
2833		    mode->HTotal     = mode->CrtcHTotal     =
2834			((R128_BIOS16(j + 8)  & 0x01ff) + 1) * 8;
2835
2836		    mode->VDisplay   = mode->CrtcVDisplay   =
2837			(R128_BIOS16(j + 17) & 0x07ff) + 1;
2838		    mode->VSyncStart = mode->CrtcVSyncStart =
2839			(R128_BIOS16(j + 19) & 0x07ff) + 1;
2840		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
2841			mode->CrtcVSyncStart + ((R128_BIOS16(j + 19) >> 11) & 0x1f);
2842		    mode->VTotal     = mode->CrtcVTotal     =
2843			(R128_BIOS16(j + 15) & 0x07ff) + 1;
2844		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
2845			       mode->CrtcHDisplay,mode->CrtcVDisplay,
2846			       (float)mode->Clock/ 1000);
2847		}
2848		return MODE_OK;
2849	    }
2850	}
2851	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
2852		       "Mode rejected for FP %ix%i [pclk: %.1f] "
2853		       "(not listed in VBIOS)\n",
2854		       mode->CrtcHDisplay, mode->CrtcVDisplay,
2855		       (float)mode->Clock / 1000);
2856	return MODE_NOMODE;
2857    }
2858
2859    return MODE_OK;
2860}
2861
2862/* Used to disallow modes that are not supported by the hardware. */
2863ModeStatus R128ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
2864                                   Bool verbose, int flags)
2865{
2866    SCRN_INFO_PTR(arg);
2867    R128EntPtr  pR128Ent = R128EntPriv(pScrn);
2868    xf86OutputPtr output = R128FirstOutput(pR128Ent->pCrtc[0]);
2869
2870    return R128DoValidMode(output, mode, flags);
2871}
2872
2873/* Adjust viewport into virtual desktop such that (0,0) in viewport space
2874   is (x,y) in virtual space. */
2875void R128AdjustFrame(ADJUST_FRAME_ARGS_DECL)
2876{
2877    SCRN_INFO_PTR(arg);
2878    R128InfoPtr   info      = R128PTR(pScrn);
2879    unsigned char *R128MMIO = info->MMIO;
2880    int           Base;
2881
2882    if(info->showCache && y && pScrn->vtSema)
2883        y += pScrn->virtualY - 1;
2884
2885    Base = y * info->CurrentLayout.displayWidth + x;
2886
2887    switch (info->CurrentLayout.pixel_code) {
2888    case 15:
2889    case 16: Base *= 2; break;
2890    case 24: Base *= 3; break;
2891    case 32: Base *= 4; break;
2892    }
2893
2894    Base &= ~7;                 /* 3 lower bits are always 0 */
2895
2896    if (info->CurrentLayout.pixel_code == 24)
2897	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
2898
2899    OUTREG(R128_CRTC_OFFSET, Base);
2900}
2901
2902/* Called when VT switching back to the X server.  Reinitialize the video
2903   mode. */
2904Bool R128EnterVT(VT_FUNC_ARGS_DECL)
2905{
2906    SCRN_INFO_PTR(arg);
2907    R128InfoPtr info  = R128PTR(pScrn);
2908
2909    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2910                        "%s\n", __func__));
2911
2912    pScrn->vtSema = TRUE;
2913#ifndef AVOID_FBDEV
2914    if (info->FBDev) {
2915        if (!fbdevHWEnterVT(VT_FUNC_ARGS)) return FALSE;
2916    } else {
2917#endif
2918	if (!xf86SetDesiredModes(pScrn)) return FALSE;
2919#ifndef AVOID_FBDEV
2920    }
2921#endif
2922
2923    if (info->accelOn)
2924	R128EngineInit(pScrn);
2925
2926#ifdef R128DRI
2927    if (info->directRenderingEnabled) {
2928	if (info->irq) {
2929	    /* Need to make sure interrupts are enabled */
2930	    unsigned char *R128MMIO = info->MMIO;
2931	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
2932	}
2933	R128CCE_START(pScrn, info);
2934	DRIUnlock(pScrn->pScreen);
2935    }
2936#endif
2937
2938    info->PaletteSavedOnVT = FALSE;
2939    //pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
2940
2941    return TRUE;
2942}
2943
2944/* Called when VT switching away from the X server.  Restore the original
2945   text mode. */
2946void R128LeaveVT(VT_FUNC_ARGS_DECL)
2947{
2948    SCRN_INFO_PTR(arg);
2949    R128InfoPtr info  = R128PTR(pScrn);
2950    R128SavePtr save  = &info->ModeReg;
2951
2952    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2953                        "%s\n", __func__));
2954#ifdef R128DRI
2955    if (info->directRenderingEnabled) {
2956	DRILock(pScrn->pScreen, 0);
2957	R128CCE_STOP(pScrn, info);
2958    }
2959#ifdef USE_EXA
2960    if (info->useEXA)
2961        info->state_2d.composite_setup = FALSE;
2962#endif
2963#endif
2964    R128SavePalette(pScrn, save);
2965    info->PaletteSavedOnVT = TRUE;
2966#ifndef AVOID_FBDEV
2967    if (info->FBDev)
2968        fbdevHWLeaveVT(VT_FUNC_ARGS);
2969    else
2970#endif
2971        R128Restore(pScrn);
2972}
2973
2974
2975/* Called at the end of each server generation.  Restore the original text
2976   mode, unmap video memory, and unwrap and call the saved CloseScreen
2977   function.  */
2978static Bool R128CloseScreen(CLOSE_SCREEN_ARGS_DECL)
2979{
2980    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2981    R128InfoPtr info  = R128PTR(pScrn);
2982
2983    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2984                        "%s\n", __func__));
2985
2986#ifdef R128DRI
2987				/* Disable direct rendering */
2988    if (info->directRenderingEnabled) {
2989	R128DRICloseScreen(pScreen);
2990	info->directRenderingEnabled = FALSE;
2991    }
2992#endif
2993
2994    if (pScrn->vtSema) {
2995	R128Restore(pScrn);
2996	R128UnmapMem(pScrn);
2997    }
2998
2999#ifdef USE_EXA
3000        if (info->useEXA) {
3001	    exaDriverFini(pScreen);
3002	    free(info->ExaDriver);
3003	} else
3004#endif
3005#ifdef HAVE_XAA_H
3006	{
3007            if (info->accel)             XAADestroyInfoRec(info->accel);
3008	    info->accel                  = NULL;
3009        }
3010#endif
3011
3012    if (info->scratch_save)      free(info->scratch_save);
3013    info->scratch_save           = NULL;
3014
3015    if (info->adaptor) {
3016        free(info->adaptor->pPortPrivates[0].ptr);
3017	xf86XVFreeVideoAdaptorRec(info->adaptor);
3018	info->adaptor = NULL;
3019    }
3020
3021    pScrn->vtSema = FALSE;
3022
3023    pScreen->BlockHandler = info->BlockHandler;
3024    pScreen->CloseScreen = info->CloseScreen;
3025    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3026}
3027
3028void R128FreeScreen(FREE_SCREEN_ARGS_DECL)
3029{
3030    SCRN_INFO_PTR(arg);
3031    R128InfoPtr   info      = R128PTR(pScrn);
3032
3033    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3034                        "%s\n", __func__));
3035    if (info == NULL)
3036	return;
3037#ifdef WITH_VGAHW
3038    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
3039	vgaHWFreeHWRec(pScrn);
3040#endif
3041    R128FreeRec(pScrn);
3042}
3043