r128_driver.c revision e86a9069
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 XF86DRI
75#define _XF86DRI_SERVER_
76#include "r128_dri.h"
77#include "r128_common.h"
78#include "r128_sarea.h"
79#endif
80
81#include "fb.h"
82
83				/* colormap initialization */
84#include "micmap.h"
85
86				/* X and server generic header files */
87#include "xf86.h"
88#include "xf86_OSproc.h"
89#include "xf86PciInfo.h"
90#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
91#include "xf86RAC.h"
92#include "xf86Resources.h"
93#endif
94#include "xf86_OSlib.h"
95#include "xf86cmap.h"
96#include "xf86xv.h"
97#include "vbe.h"
98#include "xf86Priv.h"
99
100				/* fbdevhw & vgahw */
101#ifdef WITH_VGAHW
102#include "vgaHW.h"
103#endif
104
105#ifndef AVOID_FBDEV
106#include "fbdevhw.h"
107#endif
108
109#include "dixstruct.h"
110
111				/* DPMS support. */
112#ifdef HAVE_XEXTPROTO_71
113#include <X11/extensions/dpmsconst.h>
114#else
115#define DPMS_SERVER
116#include <X11/extensions/dpms.h>
117#endif
118
119#ifdef __NetBSD__
120#include <sys/time.h>
121#include <dev/wscons/wsconsio.h>
122#endif
123
124#ifndef MAX
125#define MAX(a,b) ((a)>(b)?(a):(b))
126#endif
127
128#define USE_CRT_ONLY	0
129
130				/* Forward definitions for driver functions */
131static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen);
132static Bool R128SaveScreen(ScreenPtr pScreen, int mode);
133static void R128Save(ScrnInfoPtr pScrn);
134static void R128Restore(ScrnInfoPtr pScrn);
135static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
136static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn,
137					  int PowerManagementMode, int flags);
138static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn,
139					  int PowerManagementMode, int flags);
140
141typedef enum {
142  OPTION_NOACCEL,
143  OPTION_SW_CURSOR,
144  OPTION_DAC_6BIT,
145  OPTION_DAC_8BIT,
146#ifdef XF86DRI
147  OPTION_XV_DMA,
148  OPTION_IS_PCI,
149  OPTION_CCE_PIO,
150  OPTION_NO_SECURITY,
151  OPTION_USEC_TIMEOUT,
152  OPTION_AGP_MODE,
153  OPTION_AGP_SIZE,
154  OPTION_RING_SIZE,
155  OPTION_BUFFER_SIZE,
156  OPTION_PAGE_FLIP,
157#endif
158#if USE_CRT_ONLY
159  /* FIXME: Disable CRTOnly until it is tested */
160  OPTION_CRT,
161#endif
162  OPTION_DISPLAY,
163  OPTION_PANEL_WIDTH,
164  OPTION_PANEL_HEIGHT,
165  OPTION_PROG_FP_REGS,
166#ifndef AVOID_FBDEV
167  OPTION_FBDEV,
168#endif
169  OPTION_VIDEO_KEY,
170  OPTION_SHOW_CACHE,
171  OPTION_VGA_ACCESS
172} R128Opts;
173
174static const OptionInfoRec R128Options[] = {
175  { OPTION_NOACCEL,      "NoAccel",          OPTV_BOOLEAN, {0}, FALSE },
176  { OPTION_SW_CURSOR,    "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
177  { OPTION_DAC_6BIT,     "Dac6Bit",          OPTV_BOOLEAN, {0}, FALSE },
178  { OPTION_DAC_8BIT,     "Dac8Bit",          OPTV_BOOLEAN, {0}, TRUE  },
179#ifdef XF86DRI
180  { OPTION_XV_DMA,       "DMAForXv",         OPTV_BOOLEAN, {0}, FALSE },
181  { OPTION_IS_PCI,       "ForcePCIMode",     OPTV_BOOLEAN, {0}, FALSE },
182  { OPTION_CCE_PIO,      "CCEPIOMode",       OPTV_BOOLEAN, {0}, FALSE },
183  { OPTION_NO_SECURITY,  "CCENoSecurity",    OPTV_BOOLEAN, {0}, FALSE },
184  { OPTION_USEC_TIMEOUT, "CCEusecTimeout",   OPTV_INTEGER, {0}, FALSE },
185  { OPTION_AGP_MODE,     "AGPMode",          OPTV_INTEGER, {0}, FALSE },
186  { OPTION_AGP_SIZE,     "AGPSize",          OPTV_INTEGER, {0}, FALSE },
187  { OPTION_RING_SIZE,    "RingSize",         OPTV_INTEGER, {0}, FALSE },
188  { OPTION_BUFFER_SIZE,  "BufferSize",       OPTV_INTEGER, {0}, FALSE },
189  { OPTION_PAGE_FLIP,    "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
190#endif
191  { OPTION_DISPLAY,      "Display",          OPTV_STRING,  {0}, FALSE },
192  { OPTION_PANEL_WIDTH,  "PanelWidth",       OPTV_INTEGER, {0}, FALSE },
193  { OPTION_PANEL_HEIGHT, "PanelHeight",      OPTV_INTEGER, {0}, FALSE },
194  { OPTION_PROG_FP_REGS, "ProgramFPRegs",    OPTV_BOOLEAN, {0}, FALSE },
195#ifndef AVOID_FBDEV
196  { OPTION_FBDEV,        "UseFBDev",         OPTV_BOOLEAN, {0}, FALSE },
197#endif
198  { OPTION_VIDEO_KEY,    "VideoKey",         OPTV_INTEGER, {0}, FALSE },
199  { OPTION_SHOW_CACHE,   "ShowCache",        OPTV_BOOLEAN, {0}, FALSE },
200  { OPTION_VGA_ACCESS,   "VGAAccess",        OPTV_BOOLEAN, {0}, TRUE  },
201  { -1,                  NULL,               OPTV_NONE,    {0}, FALSE }
202};
203
204const OptionInfoRec *R128OptionsWeak(void) { return R128Options; }
205
206R128RAMRec R128RAM[] = {        /* Memory Specifications
207				   From RAGE 128 Software Development
208				   Manual (Technical Reference Manual P/N
209				   SDK-G04000 Rev 0.01), page 3-21.  */
210    { 4, 4, 3, 3, 1, 3, 1, 16, 12, "128-bit SDR SGRAM 1:1" },
211    { 4, 8, 3, 3, 1, 3, 1, 17, 13, "64-bit SDR SGRAM 1:1" },
212    { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SGRAM 2:1" },
213    { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SGRAM" },
214};
215
216extern _X_EXPORT int gR128EntityIndex;
217
218int getR128EntityIndex(void)
219{
220    return gR128EntityIndex;
221}
222
223R128EntPtr R128EntPriv(ScrnInfoPtr pScrn)
224{
225    DevUnion     *pPriv;
226    R128InfoPtr  info   = R128PTR(pScrn);
227    pPriv = xf86GetEntityPrivate(info->pEnt->index,
228                                 getR128EntityIndex());
229    return pPriv->ptr;
230}
231
232/* Allocate our private R128InfoRec. */
233static Bool R128GetRec(ScrnInfoPtr pScrn)
234{
235    if (pScrn->driverPrivate) return TRUE;
236
237    pScrn->driverPrivate = xnfcalloc(sizeof(R128InfoRec), 1);
238    return TRUE;
239}
240
241/* Free our private R128InfoRec. */
242static void R128FreeRec(ScrnInfoPtr pScrn)
243{
244    if (!pScrn || !pScrn->driverPrivate) return;
245    xfree(pScrn->driverPrivate);
246    pScrn->driverPrivate = NULL;
247}
248
249/* Memory map the MMIO region.  Used during pre-init and by R128MapMem,
250   below. */
251static Bool R128MapMMIO(ScrnInfoPtr pScrn)
252{
253    R128InfoPtr info          = R128PTR(pScrn);
254
255#ifndef AVOID_FBDEV
256    if (info->FBDev) {
257	info->MMIO = fbdevHWMapMMIO(pScrn);
258    } else
259#endif
260    {
261        /* If the primary screen has already mapped the MMIO region,
262           use its pointer instead of mapping it a second time. */
263        if (info->IsSecondary) {
264            DevUnion* pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
265                                                   getR128EntityIndex());
266            R128EntPtr pR128Ent = pPriv->ptr;
267            R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn);
268            info->MMIO=info0->MMIO;
269            if (info->MMIO) return TRUE;
270        }
271#ifndef XSERVER_LIBPCIACCESS
272	info->MMIO = xf86MapPciMem(pScrn->scrnIndex,
273				   VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
274				   info->PciTag,
275				   info->MMIOAddr,
276				   R128_MMIOSIZE);
277#else
278	int err = pci_device_map_range(info->PciInfo,
279				       info->MMIOAddr,
280				       R128_MMIOSIZE,
281				       PCI_DEV_MAP_FLAG_WRITABLE,
282				       &info->MMIO);
283
284	if (err) {
285	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
286                        "Unable to map MMIO aperture. %s (%d)\n",
287                        strerror (err), err);
288	    return FALSE;
289	}
290#endif
291    }
292
293    if (!info->MMIO) return FALSE;
294    return TRUE;
295}
296
297/* Unmap the MMIO region.  Used during pre-init and by R128UnmapMem,
298   below. */
299static Bool R128UnmapMMIO(ScrnInfoPtr pScrn)
300{
301    R128InfoPtr info          = R128PTR(pScrn);
302
303#ifndef AVOID_FBDEV
304    if (info->FBDev)
305	fbdevHWUnmapMMIO(pScrn);
306    else
307#endif
308    {
309#ifndef XSERVER_LIBPCIACCESS
310	xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, R128_MMIOSIZE);
311#else
312	pci_device_unmap_range(info->PciInfo, info->MMIO, R128_MMIOSIZE);
313#endif
314    }
315    info->MMIO = NULL;
316    return TRUE;
317}
318
319/* Memory map the frame buffer.  Used by R128MapMem, below. */
320static Bool R128MapFB(ScrnInfoPtr pScrn)
321{
322    R128InfoPtr info          = R128PTR(pScrn);
323
324#ifndef AVOID_FBDEV
325    if (info->FBDev) {
326	info->FB = fbdevHWMapVidmem(pScrn);
327    } else
328#endif
329    {
330#ifndef XSERVER_LIBPCIACCESS
331	info->FB = xf86MapPciMem(pScrn->scrnIndex,
332				 VIDMEM_FRAMEBUFFER,
333				 info->PciTag,
334				 info->LinearAddr,
335				 info->FbMapSize);
336#else
337	int err = pci_device_map_range(info->PciInfo,
338				       info->LinearAddr,
339				       info->FbMapSize,
340				       PCI_DEV_MAP_FLAG_WRITABLE |
341				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
342				       &info->FB);
343
344	if (err) {
345	    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
346                        "Unable to map FB aperture. %s (%d)\n",
347                        strerror (err), err);
348	    return FALSE;
349	}
350#endif
351    }
352
353    if (!info->FB) return FALSE;
354    return TRUE;
355}
356
357/* Unmap the frame buffer.  Used by R128UnmapMem, below. */
358static Bool R128UnmapFB(ScrnInfoPtr pScrn)
359{
360    R128InfoPtr info          = R128PTR(pScrn);
361
362#ifndef AVOID_FBDEV
363    if (info->FBDev)
364	fbdevHWUnmapVidmem(pScrn);
365    else
366#endif
367#ifndef XSERVER_LIBPCIACCESS
368	xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize);
369#else
370	pci_device_unmap_range(info->PciInfo, info->FB, info->FbMapSize);
371#endif
372    info->FB = NULL;
373    return TRUE;
374}
375
376/* Memory map the MMIO region and the frame buffer. */
377static Bool R128MapMem(ScrnInfoPtr pScrn)
378{
379    if (!R128MapMMIO(pScrn)) return FALSE;
380    if (!R128MapFB(pScrn)) {
381	R128UnmapMMIO(pScrn);
382	return FALSE;
383    }
384    return TRUE;
385}
386
387/* Unmap the MMIO region and the frame buffer. */
388static Bool R128UnmapMem(ScrnInfoPtr pScrn)
389{
390    if (!R128UnmapMMIO(pScrn) || !R128UnmapFB(pScrn)) return FALSE;
391    return TRUE;
392}
393
394/* Read PLL information */
395unsigned R128INPLL(ScrnInfoPtr pScrn, int addr)
396{
397    R128InfoPtr   info      = R128PTR(pScrn);
398    unsigned char *R128MMIO = info->MMIO;
399
400    OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f);
401    return INREG(R128_CLOCK_CNTL_DATA);
402}
403
404#if 0
405/* Read PAL information (only used for debugging). */
406static int R128INPAL(int idx)
407{
408    R128InfoPtr   info      = R128PTR(pScrn);
409    unsigned char *R128MMIO = info->MMIO;
410
411    OUTREG(R128_PALETTE_INDEX, idx << 16);
412    return INREG(R128_PALETTE_DATA);
413}
414#endif
415
416/* Wait for vertical sync. */
417void R128WaitForVerticalSync(ScrnInfoPtr pScrn)
418{
419    R128InfoPtr   info      = R128PTR(pScrn);
420    unsigned char *R128MMIO = info->MMIO;
421    int           i;
422
423    OUTREG(R128_GEN_INT_STATUS, R128_VSYNC_INT_AK);
424    for (i = 0; i < R128_TIMEOUT; i++) {
425	if (INREG(R128_GEN_INT_STATUS) & R128_VSYNC_INT) break;
426    }
427}
428
429/* Blank screen. */
430static void R128Blank(ScrnInfoPtr pScrn)
431{
432    R128InfoPtr   info      = R128PTR(pScrn);
433    unsigned char *R128MMIO = info->MMIO;
434
435    if(!info->IsSecondary)
436    {
437        switch(info->DisplayType)
438        {
439        case MT_LCD:
440            OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_DISPLAY_DIS,
441                 ~R128_LVDS_DISPLAY_DIS);
442	    break;
443        case MT_CRT:
444            OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS);
445	    break;
446        case MT_DFP:
447            OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS);
448	    break;
449        case MT_NONE:
450        default:
451           break;
452        }
453    }
454    else
455    {
456        OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~R128_CRTC2_DISP_DIS);
457    }
458}
459
460/* Unblank screen. */
461static void R128Unblank(ScrnInfoPtr pScrn)
462{
463    R128InfoPtr   info      = R128PTR(pScrn);
464    unsigned char *R128MMIO = info->MMIO;
465
466    if(!info->IsSecondary)
467    {
468        switch(info->DisplayType)
469        {
470        case MT_LCD:
471            OUTREGP(R128_LVDS_GEN_CNTL, 0,
472                 ~R128_LVDS_DISPLAY_DIS);
473	    break;
474        case MT_CRT:
475            OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS);
476	    break;
477        case MT_DFP:
478            OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS);
479	    break;
480        case MT_NONE:
481        default:
482            break;
483        }
484    }
485    else
486    {
487        switch(info->DisplayType)
488        {
489        case MT_LCD:
490        case MT_DFP:
491        case MT_CRT:
492            OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_DISP_DIS);
493            break;
494        case MT_NONE:
495        default:
496            break;
497        }
498    }
499}
500
501/* Compute log base 2 of val. */
502int R128MinBits(int val)
503{
504    int bits;
505
506    if (!val) return 1;
507    for (bits = 0; val; val >>= 1, ++bits);
508    return bits;
509}
510
511/* Compute n/d with rounding. */
512static int R128Div(int n, int d)
513{
514    return (n + (d / 2)) / d;
515}
516
517/* Read the Video BIOS block and the FP registers (if applicable). */
518static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
519{
520    R128InfoPtr info = R128PTR(pScrn);
521    int         i;
522    int         FPHeader = 0;
523
524#define R128_BIOS8(v)  (info->VBIOS[v])
525#define R128_BIOS16(v) (info->VBIOS[v] | \
526			(info->VBIOS[(v) + 1] << 8))
527#define R128_BIOS32(v) (info->VBIOS[v] | \
528			(info->VBIOS[(v) + 1] << 8) | \
529			(info->VBIOS[(v) + 2] << 16) | \
530			(info->VBIOS[(v) + 3] << 24))
531
532#ifdef XSERVER_LIBPCIACCESS
533    int size = info->PciInfo->rom_size > R128_VBIOS_SIZE ? info->PciInfo->rom_size : R128_VBIOS_SIZE;
534    info->VBIOS = xalloc(size);
535#else
536    info->VBIOS = xalloc(R128_VBIOS_SIZE);
537#endif
538
539    if (!info->VBIOS) {
540	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
541		   "Cannot allocate space for hold Video BIOS!\n");
542	return FALSE;
543    }
544
545    if (pInt10) {
546	info->BIOSAddr = pInt10->BIOSseg << 4;
547	(void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
548		     R128_VBIOS_SIZE);
549    } else {
550#ifdef XSERVER_LIBPCIACCESS
551	if (pci_device_read_rom(info->PciInfo, info->VBIOS)) {
552	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
553		       "Failed to read PCI ROM!\n");
554	}
555#else
556	xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE);
557	if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
558	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
559		       "Video BIOS not detected in PCI space!\n");
560	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
561		       "Attempting to read Video BIOS from legacy ISA space!\n");
562	    info->BIOSAddr = 0x000c0000;
563	    xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS);
564	}
565#endif
566    }
567    if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
568	info->BIOSAddr = 0x00000000;
569	xfree(info->VBIOS);
570	info->VBIOS = NULL;
571	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
572		   "Video BIOS not found!\n");
573    }
574
575        if(info->HasCRTC2)
576        {
577             if(info->IsSecondary)
578             {
579		/* there may be a way to detect this, for now, just assume
580		   second head is CRT */
581                 info->DisplayType = MT_CRT;
582
583                 if(info->DisplayType > MT_NONE)
584                 {
585                     DevUnion* pPriv;
586                     R128EntPtr pR128Ent;
587                     pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
588                         getR128EntityIndex());
589                     pR128Ent = pPriv->ptr;
590                     pR128Ent->HasSecondary = TRUE;
591
592                 }
593                 else return FALSE;
594
595             }
596             else
597             {
598                 /* really need some sort of detection here */
599		 if (info->HasPanelRegs) {
600		 	info->DisplayType = MT_LCD;
601		 } else if (info->isDFP) {
602			info->DisplayType = MT_DFP;
603                 } else
604                 {
605                     /*DVI port has no monitor connected, try CRT port.
606                     If something on CRT port, treat it as primary*/
607                     if(xf86IsEntityShared(pScrn->entityList[0]))
608                     {
609                         DevUnion* pPriv;
610                         R128EntPtr pR128Ent;
611                         pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
612                             getR128EntityIndex());
613                         pR128Ent = pPriv->ptr;
614                         pR128Ent->BypassSecondary = TRUE;
615                     }
616
617                     info->DisplayType = MT_CRT;
618#if 0
619                     {
620                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
621                             "No monitor detected!!!\n");
622                         return FALSE;
623                     }
624#endif
625                 }
626             }
627         }
628         else
629         {
630             /*Regular Radeon ASIC, only one CRTC, but it could be
631               used for DFP with a DVI output, like AIW board*/
632             if(info->isDFP) info->DisplayType = MT_DFP;
633             else info->DisplayType = MT_CRT;
634         }
635
636    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n",
637              (info->IsSecondary ? "Secondary" : "Primary"),
638               info->DisplayType);
639
640
641    if (info->VBIOS && info->DisplayType == MT_LCD) {
642	info->FPBIOSstart = 0;
643
644	/* FIXME: There should be direct access to the start of the FP info
645	   tables, but until we find out where that offset is stored, we
646	   must search for the ATI signature string: "M3      ". */
647	for (i = 4; i < R128_VBIOS_SIZE-8; i++) {
648	    if (R128_BIOS8(i)   == 'M' &&
649		R128_BIOS8(i+1) == '3' &&
650		R128_BIOS8(i+2) == ' ' &&
651		R128_BIOS8(i+3) == ' ' &&
652		R128_BIOS8(i+4) == ' ' &&
653		R128_BIOS8(i+5) == ' ' &&
654		R128_BIOS8(i+6) == ' ' &&
655		R128_BIOS8(i+7) == ' ') {
656		FPHeader = i-2;
657		break;
658	    }
659	}
660
661	if (!FPHeader) return TRUE;
662
663	/* Assume that only one panel is attached and supported */
664	for (i = FPHeader+20; i < FPHeader+84; i += 2) {
665	    if (R128_BIOS16(i) != 0) {
666		info->FPBIOSstart = R128_BIOS16(i);
667		break;
668	    }
669	}
670	if (!info->FPBIOSstart) return TRUE;
671
672	if (!info->PanelXRes)
673	    info->PanelXRes = R128_BIOS16(info->FPBIOSstart+25);
674	if (!info->PanelYRes)
675	    info->PanelYRes = R128_BIOS16(info->FPBIOSstart+27);
676
677	info->PanelPwrDly = R128_BIOS8(info->FPBIOSstart+56);
678
679	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID: ");
680	for (i = 1; i <= 24; i++)
681	    ErrorF("%c", R128_BIOS8(info->FPBIOSstart+i));
682	ErrorF("\n");
683	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Type: ");
684	i = R128_BIOS16(info->FPBIOSstart+29);
685	if (i & 1) ErrorF("Color, ");
686	else       ErrorF("Monochrome, ");
687	if (i & 2) ErrorF("Dual(split), ");
688	else       ErrorF("Single, ");
689	switch ((i >> 2) & 0x3f) {
690	case 0:  ErrorF("STN");        break;
691	case 1:  ErrorF("TFT");        break;
692	case 2:  ErrorF("Active STN"); break;
693	case 3:  ErrorF("EL");         break;
694	case 4:  ErrorF("Plasma");     break;
695	default: ErrorF("UNKNOWN");    break;
696	}
697	ErrorF("\n");
698	if (R128_BIOS8(info->FPBIOSstart+61) & 1) {
699	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Interface: LVDS\n");
700	} else {
701	    /* FIXME: Add Non-LVDS flat pael support */
702	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
703		       "Non-LVDS panel interface detected!  "
704		       "This support is untested and may not "
705		       "function properly\n");
706	}
707    }
708
709#ifdef __NetBSD__
710    if (!info->PanelXRes || !info->PanelYRes) {
711	/*
712	 * we may not be on x86 so check wsdisplay for panel dimensions
713	 * XXX this assumes that the r128 is the console, although that should
714	 * be the case in the vast majority of cases where an LCD is hooked up
715	 * directly
716	 * We should probably just check the relevant registers but I'm not
717	 * sure they're available at this point.
718	 */
719	struct wsdisplay_fbinfo fbinfo;
720
721	if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GINFO, &fbinfo) == 0) {
722	    info->PanelXRes = fbinfo.width;
723	    info->PanelYRes = fbinfo.height;
724	}
725    }
726#endif
727
728    if (!info->PanelXRes || !info->PanelYRes) {
729        info->HasPanelRegs = FALSE;
730        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
731		   "Can't determine panel dimensions, and none specified.\n"
732		   "\tDisabling programming of FP registers.\n");
733    } else {
734	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel size: %dx%d\n",
735		   info->PanelXRes, info->PanelYRes);
736    }
737
738    return TRUE;
739}
740
741/* Read PLL parameters from BIOS block.  Default to typical values if there
742   is no BIOS. */
743static Bool R128GetPLLParameters(ScrnInfoPtr pScrn)
744{
745    R128InfoPtr   info = R128PTR(pScrn);
746    R128PLLPtr    pll  = &info->pll;
747
748#if defined(__powerpc__) || defined(__alpha__)
749    /* there is no bios under Linux PowerPC but Open Firmware
750       does set up the PLL registers properly and we can use
751       those to calculate xclk and find the reference divider */
752
753    unsigned x_mpll_ref_fb_div;
754    unsigned xclk_cntl;
755    unsigned Nx, M;
756    unsigned PostDivSet[] = {0, 1, 2, 4, 8, 3, 6, 12};
757
758    /* Assume REF clock is 2950 (in units of 10khz) */
759    /* and that all pllclk must be between 125 Mhz and 250Mhz */
760    pll->reference_freq = 2950;
761    pll->min_pll_freq   = 12500;
762    pll->max_pll_freq   = 25000;
763
764    /* need to memory map the io to use INPLL since it
765       has not been done yet at this point in the startup */
766    R128MapMMIO(pScrn);
767    x_mpll_ref_fb_div = INPLL(pScrn, R128_X_MPLL_REF_FB_DIV);
768    xclk_cntl = INPLL(pScrn, R128_XCLK_CNTL) & 0x7;
769    pll->reference_div =
770	INPLL(pScrn,R128_PPLL_REF_DIV) & R128_PPLL_REF_DIV_MASK;
771    /* unmap it again */
772    R128UnmapMMIO(pScrn);
773
774    Nx = (x_mpll_ref_fb_div & 0x00FF00) >> 8;
775    M =  (x_mpll_ref_fb_div & 0x0000FF);
776
777    pll->xclk =  R128Div((2 * Nx * pll->reference_freq),
778			 (M * PostDivSet[xclk_cntl]));
779
780#else /* !defined(__powerpc__) */
781
782    if (!info->VBIOS) {
783	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
784		   "Video BIOS not detected, using default PLL parameters!\n");
785				/* These probably aren't going to work for
786				   the card you are using.  Specifically,
787				   reference freq can be 29.50MHz,
788				   28.63MHz, or 14.32MHz.  YMMV. */
789	pll->reference_freq = 2950;
790	pll->reference_div  = 65;
791	pll->min_pll_freq   = 12500;
792	pll->max_pll_freq   = 25000;
793	pll->xclk           = 10300;
794    } else {
795	CARD16 bios_header    = R128_BIOS16(0x48);
796	CARD16 pll_info_block = R128_BIOS16(bios_header + 0x30);
797	R128TRACE(("Header at 0x%04x; PLL Information at 0x%04x\n",
798		   bios_header, pll_info_block));
799
800	pll->reference_freq = R128_BIOS16(pll_info_block + 0x0e);
801	pll->reference_div  = R128_BIOS16(pll_info_block + 0x10);
802	pll->min_pll_freq   = R128_BIOS32(pll_info_block + 0x12);
803	pll->max_pll_freq   = R128_BIOS32(pll_info_block + 0x16);
804	pll->xclk           = R128_BIOS16(pll_info_block + 0x08);
805    }
806#endif /* __powerpc__ */
807
808    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
809	       "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n",
810	       pll->reference_freq,
811	       pll->reference_div,
812	       pll->min_pll_freq,
813	       pll->max_pll_freq,
814	       pll->xclk);
815
816    return TRUE;
817}
818
819/* This is called by R128PreInit to set up the default visual. */
820static Bool R128PreInitVisual(ScrnInfoPtr pScrn)
821{
822    R128InfoPtr info          = R128PTR(pScrn);
823
824    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, (Support24bppFb
825					  | Support32bppFb
826					  | SupportConvert32to24
827					  )))
828	return FALSE;
829
830    switch (pScrn->depth) {
831    case 8:
832    case 15:
833    case 16:
834    case 24:
835	break;
836    default:
837	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
838		   "Given depth (%d) is not supported by %s driver\n",
839		   pScrn->depth, R128_DRIVER_NAME);
840	return FALSE;
841    }
842
843    xf86PrintDepthBpp(pScrn);
844
845    info->fifo_slots  = 0;
846    info->pix24bpp    = xf86GetBppFromDepth(pScrn, pScrn->depth);
847    info->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
848    info->CurrentLayout.depth        = pScrn->depth;
849    info->CurrentLayout.pixel_bytes  = pScrn->bitsPerPixel / 8;
850    info->CurrentLayout.pixel_code   = (pScrn->bitsPerPixel != 16
851				       ? pScrn->bitsPerPixel
852				       : pScrn->depth);
853
854    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
855	       "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
856	       pScrn->depth,
857	       info->CurrentLayout.pixel_bytes,
858	       info->CurrentLayout.pixel_bytes > 1 ? "s" : "",
859	       info->pix24bpp);
860
861
862    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
863
864    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
865	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
866		   "Default visual (%s) is not supported at depth %d\n",
867		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
868	return FALSE;
869    }
870    return TRUE;
871
872}
873
874/* This is called by R128PreInit to handle all color weight issues. */
875static Bool R128PreInitWeight(ScrnInfoPtr pScrn)
876{
877    R128InfoPtr info          = R128PTR(pScrn);
878
879				/* Save flag for 6 bit DAC to use for
880				   setting CRTC registers.  Otherwise use
881				   an 8 bit DAC, even if xf86SetWeight sets
882				   pScrn->rgbBits to some value other than
883				   8. */
884    info->dac6bits = FALSE;
885    if (pScrn->depth > 8) {
886	rgb defaultWeight = { 0, 0, 0 };
887	if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
888    } else {
889	pScrn->rgbBits = 8;
890	if (xf86ReturnOptValBool(info->Options, OPTION_DAC_6BIT, FALSE)) {
891	    pScrn->rgbBits = 6;
892	    info->dac6bits = TRUE;
893	}
894    }
895    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
896	       "Using %d bits per RGB (%d bit DAC)\n",
897	       pScrn->rgbBits, info->dac6bits ? 6 : 8);
898
899    return TRUE;
900
901}
902
903/* This is called by R128PreInit to handle config file overrides for things
904   like chipset and memory regions.  Also determine memory size and type.
905   If memory type ever needs an override, put it in this routine. */
906static Bool R128PreInitConfig(ScrnInfoPtr pScrn)
907{
908    R128InfoPtr   info      = R128PTR(pScrn);
909    unsigned char *R128MMIO = info->MMIO;
910    EntityInfoPtr pEnt      = info->pEnt;
911    GDevPtr       dev       = pEnt->device;
912    int           offset    = 0;        /* RAM Type */
913    MessageType   from;
914
915				/* Chipset */
916    from = X_PROBED;
917    if (dev->chipset && *dev->chipset) {
918	info->Chipset  = xf86StringToToken(R128Chipsets, dev->chipset);
919	from           = X_CONFIG;
920    } else if (dev->chipID >= 0) {
921	info->Chipset  = dev->chipID;
922	from           = X_CONFIG;
923    } else {
924	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
925    }
926    pScrn->chipset = (char *)xf86TokenToString(R128Chipsets, info->Chipset);
927
928    if (!pScrn->chipset) {
929	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
930		   "ChipID 0x%04x is not recognized\n", info->Chipset);
931	return FALSE;
932    }
933
934    if (info->Chipset < 0) {
935	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
936		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
937	return FALSE;
938    }
939
940    xf86DrvMsg(pScrn->scrnIndex, from,
941	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
942	       pScrn->chipset,
943	       info->Chipset);
944
945				/* Framebuffer */
946
947    from             = X_PROBED;
948    info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & 0xfc000000;
949    pScrn->memPhysBase = info->LinearAddr;
950    if (dev->MemBase) {
951	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
952		   "Linear address override, using 0x%08lx instead of 0x%08lx\n",
953		   dev->MemBase,
954		   info->LinearAddr);
955	info->LinearAddr = dev->MemBase;
956	from             = X_CONFIG;
957    } else if (!info->LinearAddr) {
958	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
959		   "No valid linear framebuffer address\n");
960	return FALSE;
961    }
962    xf86DrvMsg(pScrn->scrnIndex, from,
963	       "Linear framebuffer at 0x%08lx\n", info->LinearAddr);
964
965				/* MMIO registers */
966    from             = X_PROBED;
967    info->MMIOAddr   = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & 0xffffff00;
968    if (dev->IOBase) {
969	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
970		   "MMIO address override, using 0x%08lx instead of 0x%08lx\n",
971		   dev->IOBase,
972		   info->MMIOAddr);
973	info->MMIOAddr = dev->IOBase;
974	from           = X_CONFIG;
975    } else if (!info->MMIOAddr) {
976	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n");
977	return FALSE;
978    }
979    xf86DrvMsg(pScrn->scrnIndex, from,
980	       "MMIO registers at 0x%08lx\n", info->MMIOAddr);
981
982#ifndef XSERVER_LIBPCIACCESS
983				/* BIOS */
984    from              = X_PROBED;
985    info->BIOSAddr    = info->PciInfo->biosBase & 0xfffe0000;
986    if (dev->BiosBase) {
987	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
988		   "BIOS address override, using 0x%08lx instead of 0x%08lx\n",
989		   dev->BiosBase,
990		   info->BIOSAddr);
991	info->BIOSAddr = dev->BiosBase;
992	from           = X_CONFIG;
993    }
994    if (info->BIOSAddr) {
995	xf86DrvMsg(pScrn->scrnIndex, from,
996		   "BIOS at 0x%08lx\n", info->BIOSAddr);
997    }
998#endif
999
1000				/* Flat panel (part 1) */
1001    if (xf86GetOptValBool(info->Options, OPTION_PROG_FP_REGS,
1002			  &info->HasPanelRegs)) {
1003	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1004		   "Turned flat panel register programming %s\n",
1005		   info->HasPanelRegs ? "on" : "off");
1006	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1007		   "\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");
1008    } else {
1009        info->isDFP = FALSE;
1010        info->isPro2 = FALSE;
1011        info->HasCRTC2 = FALSE;
1012	switch (info->Chipset) {
1013	/* R128 Pro and Pro2 can have DFP, we will deal with it.
1014	   No support for dual-head/xinerama yet.
1015           M3 can also have DFP, no support for now */
1016	case PCI_CHIP_RAGE128TF:
1017	case PCI_CHIP_RAGE128TL:
1018	case PCI_CHIP_RAGE128TR:
1019	/* FIXME: RAGE128 TS/TT/TU are assumed to be PRO2 as all 6 chips came
1020	 *        out at the same time, so are of the same family likely.
1021	 *        This requires confirmation however to be fully correct.
1022	 *        Mike A. Harris <mharris@redhat.com>
1023	 */
1024	case PCI_CHIP_RAGE128TS:
1025	case PCI_CHIP_RAGE128TT:
1026	case PCI_CHIP_RAGE128TU: info->isPro2 = TRUE;
1027	/* FIXME: RAGE128 P[ABCEGHIJKLMNOQSTUVWX] are assumed to have DFP
1028	 *        capability, as the comment at the top suggests.
1029	 *        This requires confirmation however to be fully correct.
1030	 *        Mike A. Harris <mharris@redhat.com>
1031	 */
1032	case PCI_CHIP_RAGE128PA:
1033	case PCI_CHIP_RAGE128PB:
1034	case PCI_CHIP_RAGE128PC:
1035	case PCI_CHIP_RAGE128PE:
1036	case PCI_CHIP_RAGE128PG:
1037	case PCI_CHIP_RAGE128PH:
1038	case PCI_CHIP_RAGE128PI:
1039	case PCI_CHIP_RAGE128PJ:
1040	case PCI_CHIP_RAGE128PK:
1041	case PCI_CHIP_RAGE128PL:
1042	case PCI_CHIP_RAGE128PM:
1043	case PCI_CHIP_RAGE128PN:
1044	case PCI_CHIP_RAGE128PO:
1045	case PCI_CHIP_RAGE128PQ:
1046	case PCI_CHIP_RAGE128PS:
1047	case PCI_CHIP_RAGE128PT:
1048	case PCI_CHIP_RAGE128PU:
1049	case PCI_CHIP_RAGE128PV:
1050	case PCI_CHIP_RAGE128PW:
1051	case PCI_CHIP_RAGE128PX:
1052
1053	case PCI_CHIP_RAGE128PD:
1054	case PCI_CHIP_RAGE128PF:
1055	case PCI_CHIP_RAGE128PP:
1056	case PCI_CHIP_RAGE128PR: info->isDFP = TRUE; break;
1057
1058	case PCI_CHIP_RAGE128LE:
1059	case PCI_CHIP_RAGE128LF:
1060	case PCI_CHIP_RAGE128MF:
1061	case PCI_CHIP_RAGE128ML:
1062			info->HasPanelRegs = TRUE;
1063			/* which chips support dualhead? */
1064			info->HasCRTC2 = TRUE;
1065			break;
1066	case PCI_CHIP_RAGE128RE:
1067	case PCI_CHIP_RAGE128RF:
1068	case PCI_CHIP_RAGE128RG:
1069	case PCI_CHIP_RAGE128RK:
1070	case PCI_CHIP_RAGE128RL:
1071	case PCI_CHIP_RAGE128SM:
1072	/* FIXME: RAGE128 S[EFGHKLN] are assumed to be like the SM above as
1073	 *        all of them are listed as "Rage 128 4x" in ATI docs.
1074	 *        This requires confirmation however to be fully correct.
1075	 *        Mike A. Harris <mharris@redhat.com>
1076	 */
1077	case PCI_CHIP_RAGE128SE:
1078	case PCI_CHIP_RAGE128SF:
1079	case PCI_CHIP_RAGE128SG:
1080	case PCI_CHIP_RAGE128SH:
1081	case PCI_CHIP_RAGE128SK:
1082	case PCI_CHIP_RAGE128SL:
1083	case PCI_CHIP_RAGE128SN:
1084	default:                 info->HasPanelRegs = FALSE; break;
1085	}
1086    }
1087
1088				/* Read registers used to determine options */
1089    from                      = X_PROBED;
1090    R128MapMMIO(pScrn);
1091    R128MMIO                  = info->MMIO;
1092
1093#ifndef AVOID_FBDEV
1094    if (info->FBDev)
1095	pScrn->videoRam       = fbdevHWGetVidmem(pScrn) / 1024;
1096    else
1097#endif
1098	pScrn->videoRam       = INREG(R128_CONFIG_MEMSIZE) / 1024;
1099
1100    info->MemCntl             = INREG(R128_MEM_CNTL);
1101    info->BusCntl             = INREG(R128_BUS_CNTL);
1102
1103    /* On non-flat panel systems, the default is to display to the CRT,
1104       and on flat panel systems, the default is to display to the flat
1105       panel unless the user explicity chooses otherwise using the "Display"
1106       config file setting.  BIOS_5_SCRATCH holds the display device on flat
1107       panel systems only. */
1108    if (info->HasPanelRegs) {
1109        char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY);
1110
1111#ifndef AVOID_FBDEV
1112	if (info->FBDev)
1113	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1114		     "Option \"Display\" ignored "
1115		     "(framebuffer device determines display type)\n");
1116	else
1117#endif
1118	 if (info->IsPrimary || info->IsSecondary)
1119	    info->BIOSDisplay = R128_DUALHEAD;
1120	else if (!Display || !xf86NameCmp(Display, "FP"))
1121	    info->BIOSDisplay = R128_BIOS_DISPLAY_FP;
1122	else if (!xf86NameCmp(Display, "BIOS"))
1123	    info->BIOSDisplay = INREG8(R128_BIOS_5_SCRATCH);
1124	else if (!xf86NameCmp(Display, "Mirror"))
1125	    info->BIOSDisplay = R128_BIOS_DISPLAY_FP_CRT;
1126	else if (!xf86NameCmp(Display, "CRT"))
1127	    info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
1128	else {
1129	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1130		"Unsupported type \"%s\" specified for Option \"Display\".\n"
1131		"\tSupported types are: "
1132		"\"BIOS\", \"Mirror\", \"CRT\" and \"FP\"\n", Display);
1133	    return FALSE;
1134	}
1135    } else {
1136	info->BIOSDisplay     = R128_BIOS_DISPLAY_CRT;
1137    }
1138
1139    R128MMIO                  = NULL;
1140    R128UnmapMMIO(pScrn);
1141
1142				/* RAM */
1143    switch (info->MemCntl & 0x3) {
1144    case 0:                     /* SDR SGRAM 1:1 */
1145	switch (info->Chipset) {
1146	case PCI_CHIP_RAGE128TF:
1147	case PCI_CHIP_RAGE128TL:
1148	case PCI_CHIP_RAGE128TR:
1149	case PCI_CHIP_RAGE128LE:
1150	case PCI_CHIP_RAGE128LF:
1151	case PCI_CHIP_RAGE128MF:
1152	case PCI_CHIP_RAGE128ML:
1153	case PCI_CHIP_RAGE128RE:
1154	case PCI_CHIP_RAGE128RF:
1155	case PCI_CHIP_RAGE128RG: offset = 0; break; /* 128-bit SDR SGRAM 1:1 */
1156	case PCI_CHIP_RAGE128RK:
1157	case PCI_CHIP_RAGE128RL:
1158	case PCI_CHIP_RAGE128SM:
1159	default:                 offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
1160	}
1161	break;
1162    case 1:                      offset = 2; break; /*  64-bit SDR SGRAM 2:1 */
1163    case 2:                      offset = 3; break; /*  64-bit DDR SGRAM     */
1164    default:                     offset = 1; break; /*  64-bit SDR SGRAM 1:1 */
1165    }
1166    info->ram = &R128RAM[offset];
1167
1168    if (dev->videoRam) {
1169	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1170		   "Video RAM override, using %d kB instead of %d kB\n",
1171		   dev->videoRam,
1172		   pScrn->videoRam);
1173	from             = X_CONFIG;
1174	pScrn->videoRam  = dev->videoRam;
1175    }
1176
1177    xf86DrvMsg(pScrn->scrnIndex, from,
1178	       "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name);
1179
1180    if (info->IsPrimary) {
1181        pScrn->videoRam /= 2;
1182	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1183		"Using %dk of videoram for primary head\n",
1184		pScrn->videoRam);
1185    }
1186
1187    if (info->IsSecondary) {
1188        pScrn->videoRam /= 2;
1189        info->LinearAddr += pScrn->videoRam * 1024;
1190	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1191		"Using %dk of videoram for secondary head\n",
1192		pScrn->videoRam);
1193    }
1194
1195    pScrn->videoRam  &= ~1023;
1196    info->FbMapSize  = pScrn->videoRam * 1024;
1197
1198
1199				/* Flat panel (part 2) */
1200	switch (info->BIOSDisplay) {
1201	case R128_DUALHEAD:
1202	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1203		       "Dual display\n");
1204	    break;
1205	case R128_BIOS_DISPLAY_FP:
1206	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1207		       "Using flat panel for display\n");
1208	    break;
1209	case R128_BIOS_DISPLAY_CRT:
1210	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1211		       "Using external CRT for display\n");
1212	    break;
1213	case R128_BIOS_DISPLAY_FP_CRT:
1214	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1215		       "Using both flat panel and external CRT "
1216		       "for display\n");
1217	    break;
1218	}
1219
1220    if (info->HasPanelRegs) {
1221				/* Panel width/height overrides */
1222	info->PanelXRes = 0;
1223	info->PanelYRes = 0;
1224	if (xf86GetOptValInteger(info->Options,
1225				 OPTION_PANEL_WIDTH, &(info->PanelXRes))) {
1226	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1227		       "Flat panel width: %d\n", info->PanelXRes);
1228	}
1229	if (xf86GetOptValInteger(info->Options,
1230				 OPTION_PANEL_HEIGHT, &(info->PanelYRes))) {
1231	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1232		       "Flat panel height: %d\n", info->PanelYRes);
1233	}
1234    }
1235
1236#ifdef XF86DRI
1237				/* DMA for Xv */
1238    info->DMAForXv = xf86ReturnOptValBool(info->Options, OPTION_XV_DMA, FALSE);
1239    if (info->DMAForXv) {
1240	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1241		   "Will try to use DMA for Xv image transfers\n");
1242    }
1243
1244				/* AGP/PCI */
1245    if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) {
1246	info->IsPCI = TRUE;
1247	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n");
1248    } else {
1249	switch (info->Chipset) {
1250	case PCI_CHIP_RAGE128LE:
1251	case PCI_CHIP_RAGE128RE:
1252	case PCI_CHIP_RAGE128RK:
1253	case PCI_CHIP_RAGE128PD:
1254	case PCI_CHIP_RAGE128PR:
1255	case PCI_CHIP_RAGE128PP: info->IsPCI = TRUE;  break;
1256	case PCI_CHIP_RAGE128LF:
1257	case PCI_CHIP_RAGE128MF:
1258	case PCI_CHIP_RAGE128ML:
1259	case PCI_CHIP_RAGE128PF:
1260	case PCI_CHIP_RAGE128RF:
1261	case PCI_CHIP_RAGE128RG:
1262	case PCI_CHIP_RAGE128RL:
1263	case PCI_CHIP_RAGE128SM:
1264	case PCI_CHIP_RAGE128TF:
1265	case PCI_CHIP_RAGE128TL:
1266	case PCI_CHIP_RAGE128TR:
1267	/* FIXME: Rage 128 S[EFGHKLN], T[STU], P[ABCEGHIJKLMNOQSTUVWX] are
1268	 * believed to be AGP, but need confirmation. <mharris@redhat.com>
1269	 */
1270	case PCI_CHIP_RAGE128PA:
1271	case PCI_CHIP_RAGE128PB:
1272	case PCI_CHIP_RAGE128PC:
1273	case PCI_CHIP_RAGE128PE:
1274	case PCI_CHIP_RAGE128PG:
1275	case PCI_CHIP_RAGE128PH:
1276	case PCI_CHIP_RAGE128PI:
1277	case PCI_CHIP_RAGE128PJ:
1278	case PCI_CHIP_RAGE128PK:
1279	case PCI_CHIP_RAGE128PL:
1280	case PCI_CHIP_RAGE128PM:
1281	case PCI_CHIP_RAGE128PN:
1282	case PCI_CHIP_RAGE128PO:
1283	case PCI_CHIP_RAGE128PQ:
1284	case PCI_CHIP_RAGE128PS:
1285	case PCI_CHIP_RAGE128PT:
1286	case PCI_CHIP_RAGE128PU:
1287	case PCI_CHIP_RAGE128PV:
1288	case PCI_CHIP_RAGE128PW:
1289	case PCI_CHIP_RAGE128PX:
1290	case PCI_CHIP_RAGE128TS:
1291	case PCI_CHIP_RAGE128TT:
1292	case PCI_CHIP_RAGE128TU:
1293	case PCI_CHIP_RAGE128SE:
1294	case PCI_CHIP_RAGE128SF:
1295	case PCI_CHIP_RAGE128SG:
1296	case PCI_CHIP_RAGE128SH:
1297	case PCI_CHIP_RAGE128SK:
1298	case PCI_CHIP_RAGE128SL:
1299	case PCI_CHIP_RAGE128SN:
1300	default:                 info->IsPCI = FALSE; break;
1301	}
1302    }
1303#endif
1304
1305    return TRUE;
1306}
1307
1308static Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
1309{
1310#if !defined(__powerpc__) && !defined(__alpha__) && !defined(__sparc__)
1311    R128InfoPtr   info = R128PTR(pScrn);
1312    vbeInfoPtr pVbe;
1313#endif
1314
1315    if (!xf86LoadSubModule(pScrn, "ddc")) return FALSE;
1316
1317#if defined(__powerpc__) || defined(__alpha__) || defined(__sparc__)
1318    /* Int10 is broken on PPC and some Alphas */
1319    return TRUE;
1320#else
1321    if (xf86LoadSubModule(pScrn, "vbe")) {
1322	pVbe = VBEInit(pInt10,info->pEnt->index);
1323	if (!pVbe) return FALSE;
1324        xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL)));
1325	vbeFree(pVbe);
1326	return TRUE;
1327    } else
1328	return FALSE;
1329#endif
1330}
1331
1332/* This is called by R128PreInit to initialize gamma correction. */
1333static Bool R128PreInitGamma(ScrnInfoPtr pScrn)
1334{
1335    Gamma zeros = { 0.0, 0.0, 0.0 };
1336
1337    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
1338    return TRUE;
1339}
1340
1341static void
1342R128I2CGetBits(I2CBusPtr b, int *Clock, int *data)
1343{
1344    ScrnInfoPtr   pScrn       = xf86Screens[b->scrnIndex];
1345    R128InfoPtr info = R128PTR(pScrn);
1346    unsigned long val;
1347    unsigned char *R128MMIO = info->MMIO;
1348
1349    /* Get the result. */
1350    val = INREG(info->DDCReg);
1351    *Clock = (val & R128_GPIO_MONID_Y_3) != 0;
1352    *data  = (val & R128_GPIO_MONID_Y_0) != 0;
1353
1354}
1355
1356static void
1357R128I2CPutBits(I2CBusPtr b, int Clock, int data)
1358{
1359    ScrnInfoPtr   pScrn       = xf86Screens[b->scrnIndex];
1360    R128InfoPtr info = R128PTR(pScrn);
1361    unsigned long val;
1362    unsigned char *R128MMIO = info->MMIO;
1363
1364    val = INREG(info->DDCReg)
1365              & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3);
1366    val |= (Clock ? 0:R128_GPIO_MONID_EN_3);
1367    val |= (data ? 0:R128_GPIO_MONID_EN_0);
1368    OUTREG(info->DDCReg, val);
1369}
1370
1371
1372static Bool
1373R128I2cInit(ScrnInfoPtr pScrn)
1374{
1375    R128InfoPtr info = R128PTR(pScrn);
1376    if ( !xf86LoadSubModule(pScrn, "i2c") ) {
1377        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1378            "Failed to load i2c module\n");
1379		return FALSE;
1380    }
1381
1382    info->pI2CBus = xf86CreateI2CBusRec();
1383    if(!info->pI2CBus) return FALSE;
1384
1385    info->pI2CBus->BusName    = "DDC";
1386    info->pI2CBus->scrnIndex  = pScrn->scrnIndex;
1387    info->DDCReg = R128_GPIO_MONID;
1388    info->pI2CBus->I2CPutBits = R128I2CPutBits;
1389    info->pI2CBus->I2CGetBits = R128I2CGetBits;
1390    info->pI2CBus->AcknTimeout = 5;
1391
1392    if (!xf86I2CBusInit(info->pI2CBus)) {
1393        return FALSE;
1394    }
1395    return TRUE;
1396}
1397
1398/* XXX
1399 * the following comment is bogus - the code scans the main monitor port,
1400 * not R128_GPIO_MONIDB
1401 */
1402/* return TRUE is a DFP is indeed connected to a DVI port */
1403static Bool R128GetDFPInfo(ScrnInfoPtr pScrn)
1404{
1405    R128InfoPtr info  = R128PTR(pScrn);
1406    int i;
1407    xf86MonPtr MonInfo = NULL;
1408    xf86MonPtr ddc;
1409    unsigned char *R128MMIO = info->MMIO;
1410
1411    if(!R128I2cInit(pScrn)){
1412        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1413                  "I2C initialization failed!\n");
1414    }
1415
1416    OUTREG(info->DDCReg, (INREG(info->DDCReg)
1417           | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3));
1418
1419    OUTREG(info->DDCReg, INREG(info->DDCReg)
1420           & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3));
1421
1422    MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus);
1423#ifdef __NetBSD__
1424    {
1425    	struct wsdisplayio_edid_info ei;
1426    	char buffer[1024];
1427    	int i, j;
1428
1429	ei.edid_data = buffer;
1430	ei.buffer_size = 1024;
1431	if (ioctl(xf86Info.screenFd, WSDISPLAYIO_GET_EDID, &ei) != -1) {
1432	    xf86Msg(X_INFO, "got %d bytes worth of EDID from wsdisplay\n", ei.data_size);
1433	    MonInfo = xf86InterpretEDID(pScrn->scrnIndex, buffer);
1434	} else
1435	    xf86Msg(X_INFO, "ioctl failed %d\n", errno);
1436    }
1437#endif
1438
1439    if(!MonInfo) {
1440        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1441                   "No DFP detected\n");
1442        return FALSE;
1443    }
1444    xf86SetDDCproperties(pScrn, MonInfo);
1445    ddc = pScrn->monitor->DDC;
1446
1447    for(i=0; i<4; i++)
1448    {
1449        if((ddc->det_mon[i].type == 0) &&
1450	  (ddc->det_mon[i].section.d_timings.h_active > 0) &&
1451	  (ddc->det_mon[i].section.d_timings.v_active > 0))
1452        {
1453            info->PanelXRes =
1454                ddc->det_mon[i].section.d_timings.h_active;
1455            info->PanelYRes =
1456                ddc->det_mon[i].section.d_timings.v_active;
1457
1458            info->HOverPlus =
1459                ddc->det_mon[i].section.d_timings.h_sync_off;
1460            info->HSyncWidth =
1461                ddc->det_mon[i].section.d_timings.h_sync_width;
1462            info->HBlank =
1463                ddc->det_mon[i].section.d_timings.h_blanking;
1464            info->VOverPlus =
1465                ddc->det_mon[i].section.d_timings.v_sync_off;
1466            info->VSyncWidth =
1467                ddc->det_mon[i].section.d_timings.v_sync_width;
1468            info->VBlank =
1469                ddc->det_mon[i].section.d_timings.v_blanking;
1470        }
1471    }
1472    return TRUE;
1473}
1474
1475
1476static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
1477{
1478    int i;
1479    xf86MonPtr ddc = pScrn->monitor->DDC;
1480    if(flag)  /*HSync*/
1481    {
1482        for(i=0; i<4; i++)
1483        {
1484            if(ddc->det_mon[i].type == DS_RANGES)
1485            {
1486                pScrn->monitor->nHsync = 1;
1487                pScrn->monitor->hsync[0].lo =
1488                    ddc->det_mon[i].section.ranges.min_h;
1489                pScrn->monitor->hsync[0].hi =
1490                    ddc->det_mon[i].section.ranges.max_h;
1491                return;
1492            }
1493        }
1494        /*if no sync ranges detected in detailed timing table,
1495          let's try to derive them from supported VESA modes
1496          Are we doing too much here!!!?
1497        **/
1498        i = 0;
1499        if(ddc->timings1.t1 & 0x02) /*800x600@56*/
1500        {
1501            pScrn->monitor->hsync[i].lo =
1502                pScrn->monitor->hsync[i].hi = 35.2;
1503            i++;
1504        }
1505        if(ddc->timings1.t1 & 0x04) /*640x480@75*/
1506        {
1507            pScrn->monitor->hsync[i].lo =
1508                pScrn->monitor->hsync[i].hi = 37.5;
1509            i++;
1510        }
1511        if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01))
1512        {
1513            pScrn->monitor->hsync[i].lo =
1514                pScrn->monitor->hsync[i].hi = 37.9;
1515            i++;
1516        }
1517        if(ddc->timings1.t2 & 0x40)
1518        {
1519            pScrn->monitor->hsync[i].lo =
1520                pScrn->monitor->hsync[i].hi = 46.9;
1521            i++;
1522        }
1523        if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08))
1524        {
1525            pScrn->monitor->hsync[i].lo =
1526                pScrn->monitor->hsync[i].hi = 48.1;
1527            i++;
1528        }
1529        if(ddc->timings1.t2 & 0x04)
1530        {
1531            pScrn->monitor->hsync[i].lo =
1532                pScrn->monitor->hsync[i].hi = 56.5;
1533            i++;
1534        }
1535        if(ddc->timings1.t2 & 0x02)
1536        {
1537            pScrn->monitor->hsync[i].lo =
1538                pScrn->monitor->hsync[i].hi = 60.0;
1539            i++;
1540        }
1541        if(ddc->timings1.t2 & 0x01)
1542        {
1543            pScrn->monitor->hsync[i].lo =
1544                pScrn->monitor->hsync[i].hi = 64.0;
1545            i++;
1546        }
1547        pScrn->monitor->nHsync = i;
1548    }
1549    else      /*Vrefresh*/
1550    {
1551        for(i=0; i<4; i++)
1552        {
1553            if(ddc->det_mon[i].type == DS_RANGES)
1554            {
1555                pScrn->monitor->nVrefresh = 1;
1556                pScrn->monitor->vrefresh[0].lo =
1557                    ddc->det_mon[i].section.ranges.min_v;
1558                pScrn->monitor->vrefresh[0].hi =
1559                    ddc->det_mon[i].section.ranges.max_v;
1560                return;
1561            }
1562        }
1563        i = 0;
1564        if(ddc->timings1.t1 & 0x02) /*800x600@56*/
1565        {
1566            pScrn->monitor->vrefresh[i].lo =
1567                pScrn->monitor->vrefresh[i].hi = 56;
1568            i++;
1569        }
1570        if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08))
1571        {
1572            pScrn->monitor->vrefresh[i].lo =
1573                pScrn->monitor->vrefresh[i].hi = 60;
1574            i++;
1575        }
1576        if(ddc->timings1.t2 & 0x04)
1577        {
1578            pScrn->monitor->vrefresh[i].lo =
1579                pScrn->monitor->vrefresh[i].hi = 70;
1580            i++;
1581        }
1582        if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80))
1583        {
1584            pScrn->monitor->vrefresh[i].lo =
1585                pScrn->monitor->vrefresh[i].hi = 72;
1586            i++;
1587        }
1588        if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40)
1589           || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01))
1590        {
1591            pScrn->monitor->vrefresh[i].lo =
1592                pScrn->monitor->vrefresh[i].hi = 75;
1593            i++;
1594        }
1595        pScrn->monitor->nVrefresh = i;
1596    }
1597}
1598
1599/***********
1600   xfree's xf86ValidateModes routine deosn't work well with DFPs
1601   here is our own validation routine. All modes between
1602   640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted.
1603   NOTE: RageProII doesn't support rmx, can only work with the
1604         standard modes the monitor can support (scale).
1605************/
1606
1607static int R128ValidateFPModes(ScrnInfoPtr pScrn)
1608{
1609    int i, j, count=0, width, height;
1610    R128InfoPtr info = R128PTR(pScrn);
1611    DisplayModePtr last = NULL, new = NULL, first = NULL;
1612    xf86MonPtr ddc;
1613
1614    /* Free any allocated modes during configuration. We don't need them*/
1615    while (pScrn->modes)
1616    {
1617	    xf86DeleteMode(&pScrn->modes, pScrn->modes);
1618    }
1619    while (pScrn->modePool)
1620    {
1621	    xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
1622    }
1623
1624    pScrn->virtualX = pScrn->display->virtualX;
1625    pScrn->virtualY = pScrn->display->virtualY;
1626
1627    /* If no mode specified in config, we use native resolution*/
1628    if(!pScrn->display->modes[0])
1629    {
1630        pScrn->display->modes[0] = xnfalloc(16);
1631        sprintf(pScrn->display->modes[0], "%dx%d",
1632               info->PanelXRes, info->PanelYRes);
1633    }
1634
1635    for(i=0; pScrn->display->modes[i] != NULL; i++)
1636    {
1637        if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2)
1638        {
1639
1640            if(width < 640 || width > info->PanelXRes ||
1641               height < 480 || height > info->PanelYRes)
1642            {
1643                xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1644                    "Mode %s is out of range.\n"
1645                    "Valid mode should be between 640x480-%dx%d\n",
1646                    pScrn->display->modes[i], info->PanelXRes, info->PanelYRes);
1647                continue;
1648            }
1649
1650            new = xnfcalloc(1, sizeof(DisplayModeRec));
1651            new->prev = last;
1652            new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1);
1653            strcpy(new->name, pScrn->display->modes[i]);
1654            new->HDisplay = new->CrtcHDisplay = width;
1655            new->VDisplay = new->CrtcVDisplay = height;
1656
1657            ddc = pScrn->monitor->DDC;
1658            for(j=0; j<DET_TIMINGS; j++)
1659            {
1660                /*We use native mode clock only*/
1661                if(ddc->det_mon[j].type == 0){
1662                    new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000;
1663                    break;
1664                }
1665            }
1666
1667            if(new->prev) new->prev->next = new;
1668            last = new;
1669            if(!first) first = new;
1670            pScrn->display->virtualX =
1671            pScrn->virtualX = MAX(pScrn->virtualX, width);
1672            pScrn->display->virtualY =
1673            pScrn->virtualY = MAX(pScrn->virtualY, height);
1674            count++;
1675        }
1676        else
1677        {
1678            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1679                "Mode name %s is invalid\n", pScrn->display->modes[i]);
1680            continue;
1681        }
1682   }
1683
1684   if(last)
1685   {
1686       last->next = first;
1687       first->prev = last;
1688       pScrn->modes = first;
1689
1690       /*FIXME: May need to validate line pitch here*/
1691       {
1692           int dummy = 0;
1693           switch(pScrn->depth / 8)
1694           {
1695              case 1:
1696                  dummy = 128 - pScrn->virtualX % 128;
1697                  break;
1698              case 2:
1699                  dummy = 32 - pScrn->virtualX % 32;
1700                  break;
1701              case 3:
1702              case 4:
1703                  dummy = 16 - pScrn->virtualX % 16;
1704           }
1705           pScrn->displayWidth = pScrn->virtualX + dummy;
1706       }
1707
1708   }
1709
1710   return count;
1711}
1712
1713
1714/* This is called by R128PreInit to validate modes and compute parameters
1715   for all of the valid modes. */
1716static Bool R128PreInitModes(ScrnInfoPtr pScrn)
1717{
1718    R128InfoPtr   info = R128PTR(pScrn);
1719    ClockRangePtr clockRanges;
1720    int           modesFound;
1721
1722    if(info->isDFP) {
1723        R128MapMem(pScrn);
1724        info->BIOSDisplay = R128_BIOS_DISPLAY_FP;
1725        /* validate if DFP really connected. */
1726        if(!R128GetDFPInfo(pScrn)) {
1727            info->isDFP = FALSE;
1728            info->BIOSDisplay = R128_BIOS_DISPLAY_CRT;
1729        } else if(!info->isPro2) {
1730            /* RageProII doesn't support rmx, we can't use native-mode
1731               stretching for other non-native modes. It will rely on
1732               whatever VESA modes monitor can support. */
1733            modesFound = R128ValidateFPModes(pScrn);
1734            if(modesFound < 1) {
1735                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1736                     "No valid mode found for this DFP/LCD\n");
1737                 R128UnmapMem(pScrn);
1738                 return FALSE;
1739
1740            }
1741        }
1742        R128UnmapMem(pScrn);
1743    }
1744
1745    if(!info->isDFP || info->isPro2) {
1746				/* Get mode information */
1747        pScrn->progClock                   = TRUE;
1748        clockRanges                        = xnfcalloc(sizeof(*clockRanges), 1);
1749        clockRanges->next                  = NULL;
1750        clockRanges->minClock              = info->pll.min_pll_freq;
1751        clockRanges->maxClock              = info->pll.max_pll_freq * 10;
1752        clockRanges->clockIndex            = -1;
1753        if (info->HasPanelRegs || info->isDFP) {
1754            clockRanges->interlaceAllowed  = FALSE;
1755            clockRanges->doubleScanAllowed = FALSE;
1756        } else {
1757            clockRanges->interlaceAllowed  = TRUE;
1758            clockRanges->doubleScanAllowed = TRUE;
1759        }
1760
1761        if(pScrn->monitor->DDC) {
1762        /*if we still don't know sync range yet, let's try EDID.
1763          Note that, since we can have dual heads, the Xconfigurator
1764          may not be able to probe both monitors correctly through
1765          vbe probe function (R128ProbeDDC). Here we provide an
1766          additional way to auto-detect sync ranges if they haven't
1767          been added to XF86Config manually.
1768        **/
1769            if(pScrn->monitor->nHsync <= 0)
1770                R128SetSyncRangeFromEdid(pScrn, 1);
1771            if(pScrn->monitor->nVrefresh <= 0)
1772                R128SetSyncRangeFromEdid(pScrn, 0);
1773        }
1774
1775        modesFound = xf86ValidateModes(pScrn,
1776				   pScrn->monitor->Modes,
1777				   pScrn->display->modes,
1778				   clockRanges,
1779				   NULL,        /* linePitches */
1780				   8 * 64,      /* minPitch */
1781				   8 * 1024,    /* maxPitch */
1782/*
1783 * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of
1784 * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks
1785 */
1786				   8 * 32,      /* pitchInc */
1787				   128,         /* minHeight */
1788				   2048,        /* maxHeight */
1789				   pScrn->display->virtualX,
1790				   pScrn->display->virtualY,
1791				   info->FbMapSize,
1792				   LOOKUP_BEST_REFRESH);
1793#ifndef AVOID_FBDEV
1794        if (modesFound < 1 && info->FBDev) {
1795		fbdevHWUseBuildinMode(pScrn);
1796		pScrn->displayWidth = fbdevHWGetLineLength(pScrn) /
1797		    (pScrn->bitsPerPixel / 8);
1798		modesFound = 1;
1799        }
1800#endif
1801
1802        if (modesFound == -1) return FALSE;
1803        xf86PruneDriverModes(pScrn);
1804        if (!modesFound || !pScrn->modes) {
1805            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
1806            return FALSE;
1807        }
1808        xf86SetCrtcForModes(pScrn, 0);
1809    }
1810				/* Set DPI */
1811    pScrn->currentMode = pScrn->modes;
1812    xf86PrintModes(pScrn);
1813
1814    xf86SetDpi(pScrn, 0, 0);
1815
1816				/* Get ScreenInit function */
1817    if (!xf86LoadSubModule(pScrn, "fb")) return FALSE;
1818
1819    info->CurrentLayout.displayWidth = pScrn->displayWidth;
1820    info->CurrentLayout.mode = pScrn->currentMode;
1821
1822    return TRUE;
1823}
1824
1825/* This is called by R128PreInit to initialize the hardware cursor. */
1826static Bool R128PreInitCursor(ScrnInfoPtr pScrn)
1827{
1828    R128InfoPtr   info = R128PTR(pScrn);
1829
1830    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1831	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
1832    }
1833    return TRUE;
1834}
1835
1836/* This is called by R128PreInit to initialize hardware acceleration. */
1837static Bool R128PreInitAccel(ScrnInfoPtr pScrn)
1838{
1839    R128InfoPtr   info = R128PTR(pScrn);
1840
1841    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
1842	if (!xf86LoadSubModule(pScrn, "xaa")) return FALSE;
1843    }
1844    return TRUE;
1845}
1846
1847static Bool R128PreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10)
1848{
1849    R128InfoPtr   info = R128PTR(pScrn);
1850#if 1 && !defined(__alpha__)
1851    /* int10 is broken on some Alphas */
1852    if (xf86LoadSubModule(pScrn, "int10")) {
1853	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
1854	*ppInt10 = xf86InitInt10(info->pEnt->index);
1855    }
1856#endif
1857    return TRUE;
1858}
1859
1860#ifdef XF86DRI
1861static Bool R128PreInitDRI(ScrnInfoPtr pScrn)
1862{
1863    R128InfoPtr   info = R128PTR(pScrn);
1864
1865    if (xf86ReturnOptValBool(info->Options, OPTION_CCE_PIO, FALSE)) {
1866	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CCE into PIO mode\n");
1867	info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;
1868    } else {
1869	info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
1870    }
1871
1872    if (xf86ReturnOptValBool(info->Options, OPTION_NO_SECURITY, FALSE)) {
1873	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1874		   "WARNING!!!  CCE Security checks disabled!!! **********\n");
1875	info->CCESecure = FALSE;
1876    } else {
1877	info->CCESecure = TRUE;
1878    }
1879
1880    info->agpMode        = R128_DEFAULT_AGP_MODE;
1881    info->agpSize        = R128_DEFAULT_AGP_SIZE;
1882    info->ringSize       = R128_DEFAULT_RING_SIZE;
1883    info->bufSize        = R128_DEFAULT_BUFFER_SIZE;
1884    info->agpTexSize     = R128_DEFAULT_AGP_TEX_SIZE;
1885
1886    info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
1887
1888    if (!info->IsPCI) {
1889	if (xf86GetOptValInteger(info->Options,
1890				 OPTION_AGP_MODE, &(info->agpMode))) {
1891	    if (info->agpMode < 1 || info->agpMode > R128_AGP_MAX_MODE) {
1892		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1893			   "Illegal AGP Mode: %d\n", info->agpMode);
1894		return FALSE;
1895	    }
1896	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1897		       "Using AGP %dx mode\n", info->agpMode);
1898	}
1899
1900	if (xf86GetOptValInteger(info->Options,
1901				 OPTION_AGP_SIZE, (int *)&(info->agpSize))) {
1902	    switch (info->agpSize) {
1903	    case 4:
1904	    case 8:
1905	    case 16:
1906	    case 32:
1907	    case 64:
1908	    case 128:
1909	    case 256:
1910		break;
1911	    default:
1912		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1913			   "Illegal AGP size: %d MB\n", info->agpSize);
1914		return FALSE;
1915	    }
1916	}
1917
1918	if (xf86GetOptValInteger(info->Options,
1919				 OPTION_RING_SIZE, &(info->ringSize))) {
1920	    if (info->ringSize < 1 || info->ringSize >= (int)info->agpSize) {
1921		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1922			   "Illegal ring buffer size: %d MB\n",
1923			   info->ringSize);
1924		return FALSE;
1925	    }
1926	}
1927
1928	if (xf86GetOptValInteger(info->Options,
1929				 OPTION_BUFFER_SIZE, &(info->bufSize))) {
1930	    if (info->bufSize < 1 || info->bufSize >= (int)info->agpSize) {
1931		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1932			   "Illegal vertex/indirect buffers size: %d MB\n",
1933			   info->bufSize);
1934		return FALSE;
1935	    }
1936	    if (info->bufSize > 2) {
1937		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1938			   "Illegal vertex/indirect buffers size: %d MB\n",
1939			   info->bufSize);
1940		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1941			   "Clamping vertex/indirect buffers size to 2 MB\n");
1942		info->bufSize = 2;
1943	    }
1944	}
1945
1946	if (info->ringSize + info->bufSize + info->agpTexSize >
1947	    (int)info->agpSize) {
1948	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1949		       "Buffers are too big for requested AGP space\n");
1950	    return FALSE;
1951	}
1952
1953	info->agpTexSize = info->agpSize - (info->ringSize + info->bufSize);
1954    }
1955
1956    if (xf86GetOptValInteger(info->Options, OPTION_USEC_TIMEOUT,
1957			     &(info->CCEusecTimeout))) {
1958	/* This option checked by the R128 DRM kernel module */
1959    }
1960
1961    if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1962	info->allowPageFlip = 0;
1963	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1964		   "Couldn't load shadowfb module:\n");
1965    } else {
1966	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1967						   OPTION_PAGE_FLIP,
1968						   FALSE);
1969    }
1970
1971    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page flipping %sabled\n",
1972	       info->allowPageFlip ? "en" : "dis");
1973
1974    return TRUE;
1975}
1976#endif
1977
1978static void
1979R128ProbeDDC(ScrnInfoPtr pScrn, int indx)
1980{
1981    vbeInfoPtr pVbe;
1982    if (xf86LoadSubModule(pScrn, "vbe")) {
1983	pVbe = VBEInit(NULL,indx);
1984	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1985	vbeFree(pVbe);
1986    }
1987}
1988
1989/* R128PreInit is called once at server startup. */
1990Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
1991{
1992    R128InfoPtr      info;
1993    xf86Int10InfoPtr pInt10 = NULL;
1994
1995    R128TRACE(("R128PreInit\n"));
1996
1997    if (pScrn->numEntities != 1) return FALSE;
1998
1999    if (!R128GetRec(pScrn)) return FALSE;
2000
2001    info               = R128PTR(pScrn);
2002
2003    info->IsSecondary  = FALSE;
2004    info->IsPrimary = FALSE;
2005    info->SwitchingMode = FALSE;
2006
2007    info->pEnt         = xf86GetEntityInfo(pScrn->entityList[0]);
2008    if (info->pEnt->location.type != BUS_PCI) goto fail;
2009
2010    if(xf86IsEntityShared(pScrn->entityList[0]))
2011    {
2012        if(xf86IsPrimInitDone(pScrn->entityList[0]))
2013        {
2014            DevUnion* pPriv;
2015            R128EntPtr pR128Ent;
2016            info->IsSecondary = TRUE;
2017            pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
2018                    getR128EntityIndex());
2019            pR128Ent = pPriv->ptr;
2020            if(pR128Ent->BypassSecondary) return FALSE;
2021            pR128Ent->pSecondaryScrn = pScrn;
2022        }
2023        else
2024        {
2025            DevUnion* pPriv;
2026            R128EntPtr pR128Ent;
2027	    info->IsPrimary = TRUE;
2028            xf86SetPrimInitDone(pScrn->entityList[0]);
2029            pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
2030                    getR128EntityIndex());
2031            pR128Ent = pPriv->ptr;
2032            pR128Ent->pPrimaryScrn = pScrn;
2033            pR128Ent->IsDRIEnabled = FALSE;
2034            pR128Ent->BypassSecondary = FALSE;
2035            pR128Ent->HasSecondary = FALSE;
2036            pR128Ent->RestorePrimary = FALSE;
2037            pR128Ent->IsSecondaryRestored = FALSE;
2038        }
2039    }
2040
2041    if (flags & PROBE_DETECT) {
2042	R128ProbeDDC(pScrn, info->pEnt->index);
2043	return TRUE;
2044    }
2045
2046    info->PciInfo      = xf86GetPciInfoForEntity(info->pEnt->index);
2047    info->PciTag       = pciTag(PCI_DEV_BUS(info->PciInfo),
2048				PCI_DEV_DEV(info->PciInfo),
2049				PCI_DEV_FUNC(info->PciInfo));
2050
2051    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2052	       "PCI bus %d card %d func %d\n",
2053	       PCI_DEV_BUS(info->PciInfo),
2054	       PCI_DEV_DEV(info->PciInfo),
2055	       PCI_DEV_FUNC(info->PciInfo));
2056
2057#ifndef XSERVER_LIBPCIACCESS
2058    if (xf86RegisterResources(info->pEnt->index, 0, ResNone)) goto fail;
2059    if (xf86SetOperatingState(resVga, info->pEnt->index, ResUnusedOpr)) goto fail;
2060
2061    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
2062#endif
2063    pScrn->monitor     = pScrn->confScreen->monitor;
2064
2065    if (!R128PreInitVisual(pScrn))    goto fail;
2066
2067				/* We can't do this until we have a
2068				   pScrn->display. */
2069    xf86CollectOptions(pScrn, NULL);
2070    if (!(info->Options = xalloc(sizeof(R128Options))))    goto fail;
2071    memcpy(info->Options, R128Options, sizeof(R128Options));
2072    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
2073
2074    /* By default, don't do VGA IOs on ppc */
2075#if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW)
2076    info->VGAAccess = FALSE;
2077#else
2078    info->VGAAccess = TRUE;
2079#endif
2080
2081#ifdef WITH_VGAHW
2082    xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess);
2083    if (info->VGAAccess) {
2084       if (!xf86LoadSubModule(pScrn, "vgahw"))
2085           info->VGAAccess = FALSE;
2086        else {
2087            if (!vgaHWGetHWRec(pScrn))
2088               info->VGAAccess = FALSE;
2089       }
2090       if (!info->VGAAccess)
2091           xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed,"
2092                      " trying to run without it\n");
2093    } else
2094           xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE,"
2095                      " VGA module load skipped\n");
2096    if (info->VGAAccess)
2097        vgaHWGetIOBase(VGAHWPTR(pScrn));
2098#else
2099    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAHW support not compiled, VGA "
2100               "module load skipped\n");
2101#endif
2102
2103
2104
2105    if (!R128PreInitWeight(pScrn))    goto fail;
2106
2107    if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) {
2108        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
2109                                info->videoKey);
2110    } else {
2111        info->videoKey = 0x1E;
2112    }
2113
2114    if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) {
2115        info->showCache = TRUE;
2116        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
2117    }
2118
2119#ifndef AVOID_FBDEV
2120#ifdef __powerpc__
2121    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, TRUE))
2122#else
2123    if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE))
2124#endif
2125    {
2126	info->FBDev = TRUE;
2127	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2128		   "Using framebuffer device\n");
2129    }
2130
2131    if (info->FBDev) {
2132	/* check for linux framebuffer device */
2133	if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE;
2134	if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE;
2135	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
2136	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
2137	pScrn->ValidMode     = fbdevHWValidModeWeak();
2138    }
2139
2140    if (!info->FBDev)
2141#endif /* !AVOID_FBDEV */
2142	if (!R128PreInitInt10(pScrn, &pInt10)) goto fail;
2143
2144    if (!R128PreInitConfig(pScrn))             goto fail;
2145
2146    if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail;
2147
2148    if (!R128GetPLLParameters(pScrn))          goto fail;
2149
2150    /* Don't fail on this one */
2151    R128PreInitDDC(pScrn, pInt10);
2152
2153    if (!R128PreInitGamma(pScrn))              goto fail;
2154
2155    if (!R128PreInitModes(pScrn))              goto fail;
2156
2157    if (!R128PreInitCursor(pScrn))             goto fail;
2158
2159    if (!R128PreInitAccel(pScrn))              goto fail;
2160
2161#ifdef XF86DRI
2162    if (!R128PreInitDRI(pScrn))                goto fail;
2163#endif
2164
2165				/* Free the video bios (if applicable) */
2166    if (info->VBIOS) {
2167	xfree(info->VBIOS);
2168	info->VBIOS = NULL;
2169    }
2170
2171				/* Free int10 info */
2172    if (pInt10)
2173	xf86FreeInt10(pInt10);
2174
2175    xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
2176	"For information on using the multimedia capabilities\n\tof this"
2177	" adapter, please see http://gatos.sf.net.\n");
2178
2179    return TRUE;
2180
2181  fail:
2182				/* Pre-init failed. */
2183
2184				/* Free the video bios (if applicable) */
2185    if (info->VBIOS) {
2186	xfree(info->VBIOS);
2187	info->VBIOS = NULL;
2188    }
2189
2190				/* Free int10 info */
2191    if (pInt10)
2192	xf86FreeInt10(pInt10);
2193
2194#ifdef WITH_VGAHW
2195    if (info->VGAAccess)
2196           vgaHWFreeHWRec(pScrn);
2197#endif
2198    R128FreeRec(pScrn);
2199    return FALSE;
2200}
2201
2202/* Load a palette. */
2203static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors,
2204			    int *indices, LOCO *colors, VisualPtr pVisual)
2205{
2206    R128InfoPtr   info      = R128PTR(pScrn);
2207    unsigned char *R128MMIO = info->MMIO;
2208    int           i, j;
2209    int           idx;
2210    unsigned char r, g, b;
2211
2212    /* If the second monitor is connected, we also
2213       need to deal with the secondary palette*/
2214    if (info->IsSecondary) j = 1;
2215    else j = 0;
2216
2217    PAL_SELECT(j);
2218
2219
2220    /* Select palette 0 (main CRTC) if using FP-enabled chip */
2221    /*if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);*/
2222
2223    if (info->CurrentLayout.depth == 15) {
2224	/* 15bpp mode.  This sends 32 values. */
2225	for (i = 0; i < numColors; i++) {
2226	    idx = indices[i];
2227	    r   = colors[idx].red;
2228	    g   = colors[idx].green;
2229	    b   = colors[idx].blue;
2230	    OUTPAL(idx * 8, r, g, b);
2231	}
2232    }
2233    else if (info->CurrentLayout.depth == 16) {
2234	/* 16bpp mode.  This sends 64 values. */
2235				/* There are twice as many green values as
2236				   there are values for red and blue.  So,
2237				   we take each red and blue pair, and
2238				   combine it with each of the two green
2239				   values. */
2240	for (i = 0; i < numColors; i++) {
2241	    idx = indices[i];
2242	    r   = colors[idx / 2].red;
2243	    g   = colors[idx].green;
2244	    b   = colors[idx / 2].blue;
2245	    OUTPAL(idx * 4, r, g, b);
2246	}
2247    }
2248    else {
2249	/* 8bpp mode.  This sends 256 values. */
2250	for (i = 0; i < numColors; i++) {
2251	    idx = indices[i];
2252	    r   = colors[idx].red;
2253	    b   = colors[idx].blue;
2254	    g   = colors[idx].green;
2255	    OUTPAL(idx, r, g, b);
2256	}
2257    }
2258}
2259
2260static void
2261R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
2262{
2263    ScreenPtr   pScreen = screenInfo.screens[i];
2264    ScrnInfoPtr pScrn   = xf86Screens[i];
2265    R128InfoPtr info    = R128PTR(pScrn);
2266
2267#ifdef XF86DRI
2268    if (info->directRenderingEnabled)
2269        FLUSH_RING();
2270#endif
2271
2272    pScreen->BlockHandler = info->BlockHandler;
2273    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
2274    pScreen->BlockHandler = R128BlockHandler;
2275
2276    if(info->VideoTimerCallback) {
2277        (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
2278    }
2279}
2280
2281/* Called at the start of each server generation. */
2282Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen,
2283                              int argc, char **argv)
2284{
2285    ScrnInfoPtr pScrn  = xf86Screens[pScreen->myNum];
2286    R128InfoPtr info   = R128PTR(pScrn);
2287    BoxRec      MemBox;
2288    int		y2;
2289
2290    R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset));
2291
2292#ifdef XF86DRI
2293				/* Turn off the CCE for now. */
2294    info->CCEInUse     = FALSE;
2295    info->indirectBuffer = NULL;
2296#endif
2297
2298    if (!R128MapMem(pScrn)) return FALSE;
2299    pScrn->fbOffset    = 0;
2300    if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024;
2301#ifdef XF86DRI
2302    info->fbX          = 0;
2303    info->fbY          = 0;
2304    info->frontOffset  = 0;
2305    info->frontPitch   = pScrn->displayWidth;
2306#endif
2307
2308    info->PaletteSavedOnVT = FALSE;
2309
2310    R128Save(pScrn);
2311#ifndef AVOID_FBDEV
2312    if (info->FBDev) {
2313	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
2314    } else
2315#endif
2316	if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
2317
2318    R128SaveScreen(pScreen, SCREEN_SAVER_ON);
2319    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
2320
2321				/* Visual setup */
2322    miClearVisualTypes();
2323    if (!miSetVisualTypes(pScrn->depth,
2324			  miGetDefaultVisualMask(pScrn->depth),
2325			  pScrn->rgbBits,
2326			  pScrn->defaultVisual)) return FALSE;
2327    miSetPixmapDepths ();
2328
2329#ifdef XF86DRI
2330				/* Setup DRI after visuals have been
2331				   established, but before fbScreenInit is
2332				   called.  fbScreenInit will eventually
2333				   call the driver's InitGLXVisuals call
2334				   back. */
2335    {
2336	/* FIXME: When we move to dynamic allocation of back and depth
2337	   buffers, we will want to revisit the following check for 3
2338	   times the virtual size of the screen below. */
2339	int width_bytes = (pScrn->displayWidth *
2340			   info->CurrentLayout.pixel_bytes);
2341	int maxy        = info->FbMapSize / width_bytes;
2342
2343	if (xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
2344	    xf86DrvMsg(scrnIndex, X_WARNING,
2345		       "Acceleration disabled, not initializing the DRI\n");
2346	    info->directRenderingEnabled = FALSE;
2347	} else if (maxy <= pScrn->virtualY * 3) {
2348	    xf86DrvMsg(scrnIndex, X_WARNING,
2349		       "Static buffer allocation failed -- "
2350		       "need at least %d kB video memory\n",
2351		       (pScrn->displayWidth * pScrn->virtualY *
2352			info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024);
2353	    info->directRenderingEnabled = FALSE;
2354	} else {
2355            if(info->IsSecondary)
2356                info->directRenderingEnabled = FALSE;
2357            else
2358            {
2359                /* Xinerama has sync problem with DRI, disable it for now */
2360                if(xf86IsEntityShared(pScrn->entityList[0]))
2361                {
2362                    info->directRenderingEnabled = FALSE;
2363 	            xf86DrvMsg(scrnIndex, X_WARNING,
2364                        "Direct Rendering Disabled -- "
2365                        "Dual-head configuration is not working with DRI "
2366                        "at present.\nPlease use only one Device/Screen "
2367                        "section in your XFConfig file.\n");
2368                }
2369                else
2370                info->directRenderingEnabled =
2371                    R128DRIScreenInit(pScreen);
2372                if(xf86IsEntityShared(pScrn->entityList[0]))
2373                {
2374                    DevUnion* pPriv;
2375                    R128EntPtr pR128Ent;
2376                    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
2377                        getR128EntityIndex());
2378                    pR128Ent = pPriv->ptr;
2379                    pR128Ent->IsDRIEnabled = info->directRenderingEnabled;
2380                }
2381            }
2382	}
2383    }
2384#endif
2385
2386    if (!fbScreenInit (pScreen, info->FB,
2387		       pScrn->virtualX, pScrn->virtualY,
2388		       pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2389		       pScrn->bitsPerPixel))
2390	return FALSE;
2391
2392    xf86SetBlackWhitePixels(pScreen);
2393
2394    if (pScrn->bitsPerPixel > 8) {
2395	VisualPtr visual;
2396
2397	visual = pScreen->visuals + pScreen->numVisuals;
2398	while (--visual >= pScreen->visuals) {
2399	    if ((visual->class | DynamicClass) == DirectColor) {
2400		visual->offsetRed   = pScrn->offset.red;
2401		visual->offsetGreen = pScrn->offset.green;
2402		visual->offsetBlue  = pScrn->offset.blue;
2403		visual->redMask     = pScrn->mask.red;
2404		visual->greenMask   = pScrn->mask.green;
2405		visual->blueMask    = pScrn->mask.blue;
2406	    }
2407	}
2408    }
2409
2410    /* must be after RGB order fixed */
2411    fbPictureInit (pScreen, 0, 0);
2412
2413				/* Memory manager setup */
2414#ifdef XF86DRI
2415    if (info->directRenderingEnabled) {
2416	FBAreaPtr fbarea;
2417	int width_bytes = (pScrn->displayWidth *
2418			   info->CurrentLayout.pixel_bytes);
2419	int cpp = info->CurrentLayout.pixel_bytes;
2420	int bufferSize = pScrn->virtualY * width_bytes;
2421	int l, total;
2422	int scanlines;
2423
2424	switch (info->CCEMode) {
2425	case R128_DEFAULT_CCE_PIO_MODE:
2426	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in PIO mode\n");
2427	    break;
2428	case R128_DEFAULT_CCE_BM_MODE:
2429	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in BM mode\n");
2430	    break;
2431	default:
2432	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CCE in UNKNOWN mode\n");
2433	    break;
2434	}
2435
2436	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2437		   "Using %d MB AGP aperture\n", info->agpSize);
2438	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2439		   "Using %d MB for the ring buffer\n", info->ringSize);
2440	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2441		   "Using %d MB for vertex/indirect buffers\n", info->bufSize);
2442	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2443		   "Using %d MB for AGP textures\n", info->agpTexSize);
2444
2445	/* Try for front, back, depth, and two framebuffers worth of
2446	 * pixmap cache.  Should be enough for a fullscreen background
2447	 * image plus some leftovers.
2448	 */
2449	info->textureSize = info->FbMapSize - 5 * bufferSize;
2450
2451	/* If that gives us less than half the available memory, let's
2452	 * be greedy and grab some more.  Sorry, I care more about 3D
2453	 * performance than playing nicely, and you'll get around a full
2454	 * framebuffer's worth of pixmap cache anyway.
2455	 */
2456	if (info->textureSize < (int)info->FbMapSize / 2) {
2457	    info->textureSize = info->FbMapSize - 4 * bufferSize;
2458	}
2459
2460	if (info->textureSize > 0) {
2461	    l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
2462	    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
2463
2464	    /* Round the texture size up to the nearest whole number of
2465	     * texture regions.  Again, be greedy about this, don't
2466	     * round down.
2467	     */
2468	    info->log2TexGran = l;
2469	    info->textureSize = (info->textureSize >> l) << l;
2470	} else {
2471	    info->textureSize = 0;
2472	}
2473
2474	/* Set a minimum usable local texture heap size.  This will fit
2475	 * two 256x256x32bpp textures.
2476	 */
2477	if (info->textureSize < 512 * 1024) {
2478	    info->textureOffset = 0;
2479	    info->textureSize = 0;
2480	}
2481
2482	total = info->FbMapSize - info->textureSize;
2483	scanlines = total / width_bytes;
2484	if (scanlines > 8191) scanlines = 8191;
2485
2486	/* Recalculate the texture offset and size to accomodate any
2487	 * rounding to a whole number of scanlines.
2488	 */
2489	info->textureOffset = scanlines * width_bytes;
2490
2491	MemBox.x1 = 0;
2492	MemBox.y1 = 0;
2493	MemBox.x2 = pScrn->displayWidth;
2494	MemBox.y2 = scanlines;
2495
2496	if (!xf86InitFBManager(pScreen, &MemBox)) {
2497	    xf86DrvMsg(scrnIndex, X_ERROR,
2498		       "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
2499		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2500	    return FALSE;
2501	} else {
2502	    int width, height;
2503
2504	    xf86DrvMsg(scrnIndex, X_INFO,
2505		       "Memory manager initialized to (%d,%d) (%d,%d)\n",
2506		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2507	    if ((fbarea = xf86AllocateOffscreenArea(pScreen,
2508						    pScrn->displayWidth,
2509						    2, 0, NULL, NULL, NULL))) {
2510		xf86DrvMsg(scrnIndex, X_INFO,
2511			   "Reserved area from (%d,%d) to (%d,%d)\n",
2512			   fbarea->box.x1, fbarea->box.y1,
2513			   fbarea->box.x2, fbarea->box.y2);
2514	    } else {
2515		xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
2516	    }
2517	    if (xf86QueryLargestOffscreenArea(pScreen, &width,
2518					      &height, 0, 0, 0)) {
2519		xf86DrvMsg(scrnIndex, X_INFO,
2520			   "Largest offscreen area available: %d x %d\n",
2521			   width, height);
2522	    }
2523	}
2524
2525				/* Allocate the shared back buffer */
2526	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
2527						pScrn->virtualX,
2528						pScrn->virtualY,
2529						32, NULL, NULL, NULL))) {
2530	    xf86DrvMsg(scrnIndex, X_INFO,
2531		       "Reserved back buffer from (%d,%d) to (%d,%d)\n",
2532		       fbarea->box.x1, fbarea->box.y1,
2533		       fbarea->box.x2, fbarea->box.y2);
2534
2535	    info->backX = fbarea->box.x1;
2536	    info->backY = fbarea->box.y1;
2537	    info->backOffset = (fbarea->box.y1 * width_bytes +
2538				fbarea->box.x1 * cpp);
2539	    info->backPitch = pScrn->displayWidth;
2540	} else {
2541	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve back buffer\n");
2542	    info->backX = -1;
2543	    info->backY = -1;
2544	    info->backOffset = -1;
2545	    info->backPitch = -1;
2546	}
2547
2548				/* Allocate the shared depth buffer */
2549	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
2550						pScrn->virtualX,
2551						pScrn->virtualY + 1,
2552						32, NULL, NULL, NULL))) {
2553	    xf86DrvMsg(scrnIndex, X_INFO,
2554		       "Reserved depth buffer from (%d,%d) to (%d,%d)\n",
2555		       fbarea->box.x1, fbarea->box.y1,
2556		       fbarea->box.x2, fbarea->box.y2);
2557
2558	    info->depthX = fbarea->box.x1;
2559	    info->depthY = fbarea->box.y1;
2560	    info->depthOffset = (fbarea->box.y1 * width_bytes +
2561				 fbarea->box.x1 * cpp);
2562	    info->depthPitch = pScrn->displayWidth;
2563	    info->spanOffset = ((fbarea->box.y2 - 1) * width_bytes +
2564				fbarea->box.x1 * cpp);
2565	    xf86DrvMsg(scrnIndex, X_INFO,
2566		       "Reserved depth span from (%d,%d) offset 0x%x\n",
2567		       fbarea->box.x1, fbarea->box.y2 - 1, info->spanOffset);
2568	} else {
2569	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve depth buffer\n");
2570	    info->depthX = -1;
2571	    info->depthY = -1;
2572	    info->depthOffset = -1;
2573	    info->depthPitch = -1;
2574	    info->spanOffset = -1;
2575	}
2576
2577	xf86DrvMsg(scrnIndex, X_INFO,
2578		   "Reserved %d kb for textures at offset 0x%x\n",
2579		   info->textureSize/1024, info->textureOffset);
2580    }
2581    else
2582#endif
2583    {
2584	MemBox.x1 = 0;
2585	MemBox.y1 = 0;
2586	MemBox.x2 = pScrn->displayWidth;
2587	y2        = (info->FbMapSize
2588		     / (pScrn->displayWidth *
2589			info->CurrentLayout.pixel_bytes));
2590				/* The acceleration engine uses 14 bit
2591				   signed coordinates, so we can't have any
2592				   drawable caches beyond this region. */
2593	if (y2 > 8191) y2 = 8191;
2594	MemBox.y2 = y2;
2595
2596	if (!xf86InitFBManager(pScreen, &MemBox)) {
2597	    xf86DrvMsg(scrnIndex, X_ERROR,
2598		       "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
2599		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2600	    return FALSE;
2601	} else {
2602	    int       width, height;
2603	    FBAreaPtr fbarea;
2604
2605	    xf86DrvMsg(scrnIndex, X_INFO,
2606		       "Memory manager initialized to (%d,%d) (%d,%d)\n",
2607		       MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
2608	    if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->displayWidth,
2609						    2, 0, NULL, NULL, NULL))) {
2610		xf86DrvMsg(scrnIndex, X_INFO,
2611			   "Reserved area from (%d,%d) to (%d,%d)\n",
2612			   fbarea->box.x1, fbarea->box.y1,
2613			   fbarea->box.x2, fbarea->box.y2);
2614	    } else {
2615		xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
2616	    }
2617	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2618					      0, 0, 0)) {
2619		xf86DrvMsg(scrnIndex, X_INFO,
2620			   "Largest offscreen area available: %d x %d\n",
2621			   width, height);
2622	    }
2623	}
2624    }
2625
2626				/* Acceleration setup */
2627    if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) {
2628	if (R128AccelInit(pScreen)) {
2629	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
2630	    info->accelOn = TRUE;
2631	} else {
2632	    xf86DrvMsg(scrnIndex, X_ERROR,
2633		       "Acceleration initialization failed\n");
2634	    xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
2635	    info->accelOn = FALSE;
2636	}
2637    } else {
2638	xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
2639	info->accelOn = FALSE;
2640    }
2641
2642				/* DGA setup */
2643    R128DGAInit(pScreen);
2644
2645				/* Backing store setup */
2646    miInitializeBackingStore(pScreen);
2647    xf86SetBackingStore(pScreen);
2648
2649				/* Set Silken Mouse */
2650    xf86SetSilkenMouse(pScreen);
2651
2652				/* Cursor setup */
2653    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2654
2655				/* Hardware cursor setup */
2656    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
2657	if (R128CursorInit(pScreen)) {
2658	    int width, height;
2659
2660	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2661		       "Using hardware cursor (scanline %ld)\n",
2662		       info->cursor_start / pScrn->displayWidth);
2663	    if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
2664					      0, 0, 0)) {
2665		xf86DrvMsg(scrnIndex, X_INFO,
2666			   "Largest offscreen area available: %d x %d\n",
2667			   width, height);
2668	    }
2669	} else {
2670	    xf86DrvMsg(scrnIndex, X_ERROR,
2671		       "Hardware cursor initialization failed\n");
2672	    xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
2673	}
2674    } else {
2675	info->cursor_start = 0;
2676	xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n");
2677    }
2678
2679				/* Colormap setup */
2680    if (!miCreateDefColormap(pScreen)) return FALSE;
2681    if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
2682			     (
2683#ifndef AVOID_FBDEV
2684			     info->FBDev ? fbdevHWLoadPaletteWeak() :
2685#endif
2686			     R128LoadPalette), NULL,
2687			     CMAP_PALETTED_TRUECOLOR
2688			     | CMAP_RELOAD_ON_MODE_SWITCH
2689#if 0 /* This option messes up text mode! (eich@suse.de) */
2690			     | CMAP_LOAD_EVEN_IF_OFFSCREEN
2691#endif
2692			     )) return FALSE;
2693
2694    /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
2695#ifndef AVOID_FBDEV
2696    if (info->FBDev)
2697	xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
2698
2699    else
2700#endif
2701    {
2702	if (info->DisplayType == MT_LCD)
2703	    xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0);
2704	else
2705	    xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0);
2706    }
2707
2708    if (!info->IsSecondary)
2709	R128InitVideo(pScreen);
2710
2711				/* Provide SaveScreen */
2712    pScreen->SaveScreen  = R128SaveScreen;
2713
2714				/* Wrap CloseScreen */
2715    info->CloseScreen    = pScreen->CloseScreen;
2716    pScreen->CloseScreen = R128CloseScreen;
2717
2718				/* Note unused options */
2719    if (serverGeneration == 1)
2720	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2721
2722#ifdef XF86DRI
2723				/* DRI finalization */
2724    if (info->directRenderingEnabled) {
2725				/* Now that mi, fb, drm and others have
2726				   done their thing, complete the DRI
2727				   setup. */
2728	info->directRenderingEnabled = R128DRIFinishScreenInit(pScreen);
2729    }
2730    if (info->directRenderingEnabled) {
2731	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2732    } else {
2733	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2734		   "Direct rendering disabled\n");
2735    }
2736#endif
2737
2738    info->BlockHandler = pScreen->BlockHandler;
2739    pScreen->BlockHandler = R128BlockHandler;
2740
2741    return TRUE;
2742}
2743
2744/* Write common registers (initialized to 0). */
2745static void R128RestoreCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2746{
2747    R128InfoPtr   info      = R128PTR(pScrn);
2748    unsigned char *R128MMIO = info->MMIO;
2749
2750    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl | R128_FP_BLANK_DIS);
2751
2752    OUTREG(R128_OVR_CLR,              restore->ovr_clr);
2753    OUTREG(R128_OVR_WID_LEFT_RIGHT,   restore->ovr_wid_left_right);
2754    OUTREG(R128_OVR_WID_TOP_BOTTOM,   restore->ovr_wid_top_bottom);
2755    OUTREG(R128_OV0_SCALE_CNTL,       restore->ov0_scale_cntl);
2756    OUTREG(R128_MPP_TB_CONFIG,        restore->mpp_tb_config );
2757    OUTREG(R128_MPP_GP_CONFIG,        restore->mpp_gp_config );
2758    OUTREG(R128_SUBPIC_CNTL,          restore->subpic_cntl);
2759    OUTREG(R128_VIPH_CONTROL,         restore->viph_control);
2760    OUTREG(R128_I2C_CNTL_1,           restore->i2c_cntl_1);
2761    OUTREG(R128_GEN_INT_CNTL,         restore->gen_int_cntl);
2762    OUTREG(R128_CAP0_TRIG_CNTL,       restore->cap0_trig_cntl);
2763    OUTREG(R128_CAP1_TRIG_CNTL,       restore->cap1_trig_cntl);
2764    OUTREG(R128_BUS_CNTL,             restore->bus_cntl);
2765    OUTREG(R128_CONFIG_CNTL,          restore->config_cntl);
2766}
2767
2768/* Write CRTC registers. */
2769static void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2770{
2771    R128InfoPtr   info      = R128PTR(pScrn);
2772    unsigned char *R128MMIO = info->MMIO;
2773
2774    OUTREG(R128_CRTC_GEN_CNTL,        restore->crtc_gen_cntl);
2775
2776    OUTREGP(R128_CRTC_EXT_CNTL, restore->crtc_ext_cntl,
2777	    R128_CRTC_VSYNC_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_DISPLAY_DIS);
2778
2779    OUTREGP(R128_DAC_CNTL, restore->dac_cntl,
2780	    R128_DAC_RANGE_CNTL | R128_DAC_BLANKING);
2781
2782    OUTREG(R128_CRTC_H_TOTAL_DISP,    restore->crtc_h_total_disp);
2783    OUTREG(R128_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid);
2784    OUTREG(R128_CRTC_V_TOTAL_DISP,    restore->crtc_v_total_disp);
2785    OUTREG(R128_CRTC_V_SYNC_STRT_WID, restore->crtc_v_sync_strt_wid);
2786    OUTREG(R128_CRTC_OFFSET,          restore->crtc_offset);
2787    OUTREG(R128_CRTC_OFFSET_CNTL,     restore->crtc_offset_cntl);
2788    OUTREG(R128_CRTC_PITCH,           restore->crtc_pitch);
2789}
2790
2791/* Write CRTC2 registers. */
2792static void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn,
2793				       R128SavePtr restore)
2794{
2795    R128InfoPtr info        = R128PTR(pScrn);
2796    unsigned char *R128MMIO = info->MMIO;
2797
2798    OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl,
2799	    R128_CRTC2_DISP_DIS);
2800
2801    OUTREG(R128_CRTC2_H_TOTAL_DISP,    restore->crtc2_h_total_disp);
2802    OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid);
2803    OUTREG(R128_CRTC2_V_TOTAL_DISP,    restore->crtc2_v_total_disp);
2804    OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid);
2805    OUTREG(R128_CRTC2_OFFSET,          restore->crtc2_offset);
2806    OUTREG(R128_CRTC2_OFFSET_CNTL,     restore->crtc2_offset_cntl);
2807    OUTREG(R128_CRTC2_PITCH,           restore->crtc2_pitch);
2808}
2809
2810/* Write flat panel registers */
2811static void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2812{
2813    R128InfoPtr   info      = R128PTR(pScrn);
2814    unsigned char *R128MMIO = info->MMIO;
2815    CARD32        tmp;
2816
2817    if (info->BIOSDisplay != R128_DUALHEAD)
2818        OUTREG(R128_CRTC2_GEN_CNTL,       restore->crtc2_gen_cntl);
2819    OUTREG(R128_FP_HORZ_STRETCH,      restore->fp_horz_stretch);
2820    OUTREG(R128_FP_VERT_STRETCH,      restore->fp_vert_stretch);
2821    OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp);
2822    OUTREG(R128_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp);
2823    OUTREG(R128_FP_H_SYNC_STRT_WID,   restore->fp_h_sync_strt_wid);
2824    OUTREG(R128_FP_V_SYNC_STRT_WID,   restore->fp_v_sync_strt_wid);
2825    OUTREG(R128_TMDS_CRC,             restore->tmds_crc);
2826    OUTREG(R128_FP_PANEL_CNTL,        restore->fp_panel_cntl);
2827    OUTREG(R128_FP_GEN_CNTL, restore->fp_gen_cntl & ~(CARD32)R128_FP_BLANK_DIS);
2828
2829    if(info->isDFP) return;
2830
2831    tmp = INREG(R128_LVDS_GEN_CNTL);
2832    if ((tmp & (R128_LVDS_ON | R128_LVDS_BLON)) ==
2833	(restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON))) {
2834	OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2835    } else {
2836	if (restore->lvds_gen_cntl & (R128_LVDS_ON | R128_LVDS_BLON)) {
2837	    OUTREG(R128_LVDS_GEN_CNTL,
2838		   restore->lvds_gen_cntl & (CARD32)~R128_LVDS_BLON);
2839	    usleep(R128PTR(pScrn)->PanelPwrDly * 1000);
2840	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2841	} else {
2842	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl | R128_LVDS_BLON);
2843	    usleep(R128PTR(pScrn)->PanelPwrDly * 1000);
2844	    OUTREG(R128_LVDS_GEN_CNTL, restore->lvds_gen_cntl);
2845	}
2846    }
2847}
2848
2849static void R128PLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2850{
2851    while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
2852}
2853
2854static void R128PLLWriteUpdate(ScrnInfoPtr pScrn)
2855{
2856    R128InfoPtr   info      = R128PTR(pScrn);
2857    unsigned char *R128MMIO = info->MMIO;
2858
2859    while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R);
2860
2861    OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W,
2862	    ~R128_PPLL_ATOMIC_UPDATE_W);
2863
2864}
2865
2866static void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn)
2867{
2868    while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
2869}
2870
2871static void R128PLL2WriteUpdate(ScrnInfoPtr pScrn)
2872{
2873    R128InfoPtr  info       = R128PTR(pScrn);
2874    unsigned char *R128MMIO = info->MMIO;
2875
2876    while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R);
2877
2878    OUTPLLP(pScrn, R128_P2PLL_REF_DIV,
2879	    R128_P2PLL_ATOMIC_UPDATE_W,
2880	    ~(R128_P2PLL_ATOMIC_UPDATE_W));
2881}
2882
2883/* Write PLL registers. */
2884static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
2885{
2886    R128InfoPtr   info      = R128PTR(pScrn);
2887    unsigned char *R128MMIO = info->MMIO;
2888
2889
2890    OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
2891	    R128_VCLK_SRC_SEL_CPUCLK,
2892	    ~(R128_VCLK_SRC_SEL_MASK));
2893
2894    OUTPLLP(pScrn,
2895	    R128_PPLL_CNTL,
2896	    R128_PPLL_RESET
2897	    | R128_PPLL_ATOMIC_UPDATE_EN
2898	    | R128_PPLL_VGA_ATOMIC_UPDATE_EN,
2899	    ~(R128_PPLL_RESET
2900	      | R128_PPLL_ATOMIC_UPDATE_EN
2901	      | R128_PPLL_VGA_ATOMIC_UPDATE_EN));
2902
2903    OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL));
2904
2905/*        R128PLLWaitForReadUpdateComplete(pScrn);*/
2906    OUTPLLP(pScrn, R128_PPLL_REF_DIV,
2907	    restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK);
2908/*        R128PLLWriteUpdate(pScrn);
2909
2910        R128PLLWaitForReadUpdateComplete(pScrn);*/
2911    OUTPLLP(pScrn, R128_PPLL_DIV_3,
2912	    restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK);
2913/*    R128PLLWriteUpdate(pScrn);*/
2914    OUTPLLP(pScrn, R128_PPLL_DIV_3,
2915	    restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK);
2916
2917    R128PLLWriteUpdate(pScrn);
2918    R128PLLWaitForReadUpdateComplete(pScrn);
2919
2920    OUTPLLP(pScrn, R128_PPLL_DIV_0,
2921	    restore->ppll_div_0, ~R128_PPLL_FB0_DIV_MASK);
2922/*    R128PLLWriteUpdate(pScrn);*/
2923    OUTPLLP(pScrn, R128_PPLL_DIV_0,
2924	    restore->ppll_div_0, ~R128_PPLL_POST0_DIV_MASK);
2925
2926    R128PLLWriteUpdate(pScrn);
2927    R128PLLWaitForReadUpdateComplete(pScrn);
2928
2929    OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl);
2930/*    R128PLLWriteUpdate(pScrn);*/
2931
2932    OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET
2933					| R128_PPLL_SLEEP
2934					| R128_PPLL_ATOMIC_UPDATE_EN
2935					| R128_PPLL_VGA_ATOMIC_UPDATE_EN));
2936
2937    R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
2938	       restore->ppll_ref_div,
2939	       restore->ppll_div_3,
2940	       restore->htotal_cntl,
2941	       INPLL(pScrn, R128_PPLL_CNTL)));
2942    R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n",
2943	       restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
2944	       restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
2945	       (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
2946
2947    usleep(5000); /* let the clock lock */
2948
2949    OUTPLLP(pScrn, R128_VCLK_ECP_CNTL,
2950	    R128_VCLK_SRC_SEL_PPLLCLK,
2951	    ~(R128_VCLK_SRC_SEL_MASK));
2952
2953}
2954
2955/* Write PLL2 registers. */
2956static void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
2957{
2958    R128InfoPtr info        = R128PTR(pScrn);
2959    unsigned char *R128MMIO = info->MMIO;
2960
2961    OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
2962	    R128_V2CLK_SRC_SEL_CPUCLK,
2963	    ~R128_V2CLK_SRC_SEL_MASK);
2964
2965    OUTPLLP(pScrn,
2966	    R128_P2PLL_CNTL,
2967	    R128_P2PLL_RESET
2968	    | R128_P2PLL_ATOMIC_UPDATE_EN
2969	    | R128_P2PLL_VGA_ATOMIC_UPDATE_EN,
2970	    ~(R128_P2PLL_RESET
2971	      | R128_P2PLL_ATOMIC_UPDATE_EN
2972	      | R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
2973
2974#if 1
2975    OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK);
2976#endif
2977
2978        /*R128PLL2WaitForReadUpdateComplete(pScrn);*/
2979
2980    OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK);
2981
2982/*        R128PLL2WriteUpdate(pScrn);
2983    R128PLL2WaitForReadUpdateComplete(pScrn);*/
2984
2985    OUTPLLP(pScrn, R128_P2PLL_DIV_0,
2986			restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK);
2987
2988/*    R128PLL2WriteUpdate(pScrn);
2989    R128PLL2WaitForReadUpdateComplete(pScrn);*/
2990
2991    OUTPLLP(pScrn, R128_P2PLL_DIV_0,
2992			restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK);
2993
2994    R128PLL2WriteUpdate(pScrn);
2995    R128PLL2WaitForReadUpdateComplete(pScrn);
2996
2997    OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2);
2998
2999/*        R128PLL2WriteUpdate(pScrn);*/
3000
3001    OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET
3002					| R128_P2PLL_SLEEP
3003					| R128_P2PLL_ATOMIC_UPDATE_EN
3004					| R128_P2PLL_VGA_ATOMIC_UPDATE_EN));
3005
3006    R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
3007	       restore->p2pll_ref_div,
3008	       restore->p2pll_div_0,
3009	       restore->htotal_cntl2,
3010	       INPLL(pScrn, R128_P2PLL_CNTL)));
3011
3012    usleep(5000); /* Let the clock to lock */
3013
3014    OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL,
3015	    R128_V2CLK_SRC_SEL_P2PLLCLK,
3016	    ~R128_V2CLK_SRC_SEL_MASK);
3017
3018}
3019
3020/* Write DDA registers. */
3021static void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore)
3022{
3023    R128InfoPtr   info      = R128PTR(pScrn);
3024    unsigned char *R128MMIO = info->MMIO;
3025
3026    OUTREG(R128_DDA_CONFIG, restore->dda_config);
3027    OUTREG(R128_DDA_ON_OFF, restore->dda_on_off);
3028}
3029
3030/* Write DDA registers. */
3031static void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore)
3032{
3033    R128InfoPtr   info      = R128PTR(pScrn);
3034    unsigned char *R128MMIO = info->MMIO;
3035
3036    OUTREG(R128_DDA2_CONFIG, restore->dda2_config);
3037    OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off);
3038}
3039
3040/* Write palette data. */
3041static void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore)
3042{
3043    R128InfoPtr   info      = R128PTR(pScrn);
3044    unsigned char *R128MMIO = info->MMIO;
3045    int           i;
3046
3047    if (!restore->palette_valid) return;
3048
3049    PAL_SELECT(1);
3050    OUTPAL_START(0);
3051    for (i = 0; i < 256; i++) {
3052	R128WaitForFifo(pScrn, 32); /* delay */
3053	OUTPAL_NEXT_CARD32(restore->palette2[i]);
3054    }
3055
3056    PAL_SELECT(0);
3057    OUTPAL_START(0);
3058    for (i = 0; i < 256; i++) {
3059	R128WaitForFifo(pScrn, 32); /* delay */
3060	OUTPAL_NEXT_CARD32(restore->palette[i]);
3061    }
3062
3063}
3064
3065/* Write out state to define a new video mode.  */
3066static void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore)
3067{
3068    R128InfoPtr info = R128PTR(pScrn);
3069    DevUnion* pPriv;
3070    R128EntPtr pR128Ent;
3071    static R128SaveRec restore0;
3072
3073    R128TRACE(("R128RestoreMode(%p)\n", restore));
3074    if(!info->HasCRTC2)
3075    {
3076    	R128RestoreCommonRegisters(pScrn, restore);
3077        R128RestoreDDARegisters(pScrn, restore);
3078    	R128RestoreCrtcRegisters(pScrn, restore);
3079        if((info->DisplayType == MT_DFP) ||
3080           (info->DisplayType == MT_LCD))
3081        {
3082	    R128RestoreFPRegisters(pScrn, restore);
3083        }
3084        R128RestorePLLRegisters(pScrn, restore);
3085        return;
3086    }
3087
3088    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
3089                   getR128EntityIndex());
3090    pR128Ent = pPriv->ptr;
3091
3092
3093    /*****
3094      When changing mode with Dual-head card (VE/M6), care must
3095      be taken for the special order in setting registers. CRTC2 has
3096      to be set before changing CRTC_EXT register.
3097      In the dual-head setup, X server calls this routine twice with
3098      primary and secondary pScrn pointers respectively. The calls
3099      can come with different order. Regardless the order of X server issuing
3100      the calls, we have to ensure we set registers in the right order!!!
3101      Otherwise we may get a blank screen.
3102    *****/
3103
3104    if(info->IsSecondary)
3105    {
3106	if (!pR128Ent->RestorePrimary  && !info->SwitchingMode)
3107	    R128RestoreCommonRegisters(pScrn, restore);
3108        R128RestoreDDA2Registers(pScrn, restore);
3109        R128RestoreCrtc2Registers(pScrn, restore);
3110        R128RestorePLL2Registers(pScrn, restore);
3111
3112	if(info->SwitchingMode) return;
3113
3114        pR128Ent->IsSecondaryRestored = TRUE;
3115
3116        if(pR128Ent->RestorePrimary)
3117        {
3118            R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn);
3119            pR128Ent->RestorePrimary = FALSE;
3120
3121            R128RestoreCrtcRegisters(pScrn, &restore0);
3122            if((info0->DisplayType == MT_DFP) ||
3123               (info0->DisplayType == MT_LCD))
3124            {
3125                R128RestoreFPRegisters(pScrn, &restore0);
3126            }
3127
3128            R128RestorePLLRegisters(pScrn, &restore0);
3129            pR128Ent->IsSecondaryRestored = FALSE;
3130
3131        }
3132    }
3133    else
3134    {
3135	if (!pR128Ent->IsSecondaryRestored)
3136            R128RestoreCommonRegisters(pScrn, restore);
3137        R128RestoreDDARegisters(pScrn, restore);
3138        if(!pR128Ent->HasSecondary || pR128Ent->IsSecondaryRestored
3139            || info->SwitchingMode)
3140        {
3141	    pR128Ent->IsSecondaryRestored = FALSE;
3142            R128RestoreCrtcRegisters(pScrn, restore);
3143            if((info->DisplayType == MT_DFP) ||
3144               (info->DisplayType == MT_LCD))
3145            {
3146               R128RestoreFPRegisters(pScrn, restore);
3147            }
3148            R128RestorePLLRegisters(pScrn, restore);
3149        }
3150        else
3151        {
3152            memcpy(&restore0, restore, sizeof(restore0));
3153            pR128Ent->RestorePrimary = TRUE;
3154        }
3155    }
3156
3157    R128RestorePalette(pScrn, restore);
3158}
3159
3160/* Read common registers. */
3161static void R128SaveCommonRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3162{
3163    R128InfoPtr   info      = R128PTR(pScrn);
3164    unsigned char *R128MMIO = info->MMIO;
3165
3166    save->ovr_clr            = INREG(R128_OVR_CLR);
3167    save->ovr_wid_left_right = INREG(R128_OVR_WID_LEFT_RIGHT);
3168    save->ovr_wid_top_bottom = INREG(R128_OVR_WID_TOP_BOTTOM);
3169    save->ov0_scale_cntl     = INREG(R128_OV0_SCALE_CNTL);
3170    save->mpp_tb_config      = INREG(R128_MPP_TB_CONFIG);
3171    save->mpp_gp_config      = INREG(R128_MPP_GP_CONFIG);
3172    save->subpic_cntl        = INREG(R128_SUBPIC_CNTL);
3173    save->viph_control       = INREG(R128_VIPH_CONTROL);
3174    save->i2c_cntl_1         = INREG(R128_I2C_CNTL_1);
3175    save->gen_int_cntl       = INREG(R128_GEN_INT_CNTL);
3176    save->cap0_trig_cntl     = INREG(R128_CAP0_TRIG_CNTL);
3177    save->cap1_trig_cntl     = INREG(R128_CAP1_TRIG_CNTL);
3178    save->bus_cntl           = INREG(R128_BUS_CNTL);
3179    save->config_cntl        = INREG(R128_CONFIG_CNTL);
3180}
3181
3182/* Read CRTC registers. */
3183static void R128SaveCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3184{
3185    R128InfoPtr   info      = R128PTR(pScrn);
3186    unsigned char *R128MMIO = info->MMIO;
3187
3188    save->crtc_gen_cntl        = INREG(R128_CRTC_GEN_CNTL);
3189    save->crtc_ext_cntl        = INREG(R128_CRTC_EXT_CNTL);
3190    save->dac_cntl             = INREG(R128_DAC_CNTL);
3191    save->crtc_h_total_disp    = INREG(R128_CRTC_H_TOTAL_DISP);
3192    save->crtc_h_sync_strt_wid = INREG(R128_CRTC_H_SYNC_STRT_WID);
3193    save->crtc_v_total_disp    = INREG(R128_CRTC_V_TOTAL_DISP);
3194    save->crtc_v_sync_strt_wid = INREG(R128_CRTC_V_SYNC_STRT_WID);
3195    save->crtc_offset          = INREG(R128_CRTC_OFFSET);
3196    save->crtc_offset_cntl     = INREG(R128_CRTC_OFFSET_CNTL);
3197    save->crtc_pitch           = INREG(R128_CRTC_PITCH);
3198}
3199
3200/* Read flat panel registers */
3201static void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3202{
3203    R128InfoPtr   info      = R128PTR(pScrn);
3204    unsigned char *R128MMIO = info->MMIO;
3205
3206    if (info->BIOSDisplay != R128_DUALHEAD)
3207        save->crtc2_gen_cntl       = INREG(R128_CRTC2_GEN_CNTL);
3208    save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP);
3209    save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP);
3210    save->fp_gen_cntl          = INREG(R128_FP_GEN_CNTL);
3211    save->fp_h_sync_strt_wid   = INREG(R128_FP_H_SYNC_STRT_WID);
3212    save->fp_horz_stretch      = INREG(R128_FP_HORZ_STRETCH);
3213    save->fp_panel_cntl        = INREG(R128_FP_PANEL_CNTL);
3214    save->fp_v_sync_strt_wid   = INREG(R128_FP_V_SYNC_STRT_WID);
3215    save->fp_vert_stretch      = INREG(R128_FP_VERT_STRETCH);
3216    save->lvds_gen_cntl        = INREG(R128_LVDS_GEN_CNTL);
3217    save->tmds_crc             = INREG(R128_TMDS_CRC);
3218    save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL);
3219}
3220
3221/* Read CRTC2 registers. */
3222static void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
3223{
3224    R128InfoPtr info        = R128PTR(pScrn);
3225    unsigned char *R128MMIO = info->MMIO;
3226
3227    save->crtc2_gen_cntl        = INREG(R128_CRTC2_GEN_CNTL);
3228    save->crtc2_h_total_disp    = INREG(R128_CRTC2_H_TOTAL_DISP);
3229    save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID);
3230    save->crtc2_v_total_disp    = INREG(R128_CRTC2_V_TOTAL_DISP);
3231    save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID);
3232    save->crtc2_offset          = INREG(R128_CRTC2_OFFSET);
3233    save->crtc2_offset_cntl     = INREG(R128_CRTC2_OFFSET_CNTL);
3234    save->crtc2_pitch           = INREG(R128_CRTC2_PITCH);
3235}
3236
3237/* Read PLL registers. */
3238static void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3239{
3240    save->ppll_ref_div         = INPLL(pScrn, R128_PPLL_REF_DIV);
3241    save->ppll_div_3           = INPLL(pScrn, R128_PPLL_DIV_3);
3242    save->ppll_div_0           = INPLL(pScrn, R128_PPLL_DIV_0);
3243    save->htotal_cntl          = INPLL(pScrn, R128_HTOTAL_CNTL);
3244
3245    R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
3246	       save->ppll_ref_div,
3247	       save->ppll_div_3,
3248	       save->htotal_cntl));
3249    R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
3250	       save->ppll_ref_div & R128_PPLL_REF_DIV_MASK,
3251	       save->ppll_div_3 & R128_PPLL_FB3_DIV_MASK,
3252	       (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16));
3253}
3254
3255/* Read PLL2 registers. */
3256static void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
3257{
3258    save->p2pll_ref_div        = INPLL(pScrn, R128_P2PLL_REF_DIV);
3259    save->p2pll_div_0          = INPLL(pScrn, R128_P2PLL_DIV_0);
3260    save->htotal_cntl2         = INPLL(pScrn, R128_HTOTAL2_CNTL);
3261
3262    R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n",
3263	       save->p2pll_ref_div,
3264	       save->p2pll_div_0,
3265	       save->htotal_cntl2));
3266    R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n",
3267	       save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK,
3268	       save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK,
3269	       (save->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >> 16));
3270}
3271
3272/* Read DDA registers. */
3273static void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save)
3274{
3275    R128InfoPtr   info      = R128PTR(pScrn);
3276    unsigned char *R128MMIO = info->MMIO;
3277
3278    save->dda_config           = INREG(R128_DDA_CONFIG);
3279    save->dda_on_off           = INREG(R128_DDA_ON_OFF);
3280}
3281
3282/* Read DDA2 registers. */
3283static void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save)
3284{
3285    R128InfoPtr   info      = R128PTR(pScrn);
3286    unsigned char *R128MMIO = info->MMIO;
3287
3288    save->dda2_config           = INREG(R128_DDA2_CONFIG);
3289    save->dda2_on_off           = INREG(R128_DDA2_ON_OFF);
3290}
3291
3292/* Read palette data. */
3293static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save)
3294{
3295    R128InfoPtr   info      = R128PTR(pScrn);
3296    unsigned char *R128MMIO = info->MMIO;
3297    int           i;
3298
3299    PAL_SELECT(1);
3300    INPAL_START(0);
3301    for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT();
3302    PAL_SELECT(0);
3303    INPAL_START(0);
3304    for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT();
3305    save->palette_valid = TRUE;
3306}
3307
3308/* Save state that defines current video mode. */
3309static void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save)
3310{
3311    R128InfoPtr   info      = R128PTR(pScrn);
3312
3313    R128TRACE(("R128SaveMode(%p)\n", save));
3314
3315    if(info->IsSecondary)
3316    {
3317        R128SaveCrtc2Registers(pScrn, save);
3318        R128SavePLL2Registers(pScrn, save);
3319        R128SaveDDA2Registers(pScrn, save);
3320    }
3321    else
3322    {
3323        R128SaveCommonRegisters(pScrn, save);
3324        R128SaveCrtcRegisters(pScrn, save);
3325        if((info->DisplayType == MT_DFP) ||
3326           (info->DisplayType == MT_LCD))
3327        {
3328 	    R128SaveFPRegisters(pScrn, save);
3329        }
3330        R128SavePLLRegisters(pScrn, save);
3331        R128SaveDDARegisters(pScrn, save);
3332        R128SavePalette(pScrn, save);
3333    }
3334
3335    R128TRACE(("R128SaveMode returns %p\n", save));
3336}
3337
3338/* Save everything needed to restore the original VC state. */
3339static void R128Save(ScrnInfoPtr pScrn)
3340{
3341    R128InfoPtr   info      = R128PTR(pScrn);
3342    unsigned char *R128MMIO = info->MMIO;
3343    R128SavePtr   save      = &info->SavedReg;
3344
3345    R128TRACE(("R128Save\n"));
3346#ifndef AVOID_FBDEV
3347    if (info->FBDev) {
3348	fbdevHWSave(pScrn);
3349	return;
3350    }
3351#endif
3352
3353    if (!info->IsSecondary) {
3354#ifdef WITH_VGAHW
3355        if (info->VGAAccess) {
3356            vgaHWPtr hwp = VGAHWPTR(pScrn);
3357
3358            vgaHWUnlock(hwp);
3359# if defined(__powerpc__)
3360            /* temporary hack to prevent crashing on PowerMacs when trying to
3361             * read VGA fonts and colormap, will find a better solution
3362             * in the future. TODO: Check if there's actually some VGA stuff
3363             * setup in the card at all !!
3364             */
3365            vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */
3366# else
3367            /* Save mode * & fonts & cmap */
3368            vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
3369# endif
3370            vgaHWLock(hwp);
3371        }
3372#endif
3373        save->dp_datatype      = INREG(R128_DP_DATATYPE);
3374        save->gen_reset_cntl   = INREG(R128_GEN_RESET_CNTL);
3375        save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX);
3376        save->amcgpio_en_reg   = INREG(R128_AMCGPIO_EN_REG);
3377        save->amcgpio_mask     = INREG(R128_AMCGPIO_MASK);
3378    }
3379
3380    R128SaveMode(pScrn, save);
3381
3382}
3383
3384/* Restore the original (text) mode. */
3385static void R128Restore(ScrnInfoPtr pScrn)
3386{
3387    R128InfoPtr   info      = R128PTR(pScrn);
3388    unsigned char *R128MMIO = info->MMIO;
3389    R128SavePtr   restore   = &info->SavedReg;
3390
3391    R128TRACE(("R128Restore\n"));
3392#ifndef AVOID_FBDEV
3393    if (info->FBDev) {
3394	fbdevHWRestore(pScrn);
3395	return;
3396    }
3397#endif
3398    R128Blank(pScrn);
3399
3400    if (!info->IsSecondary) {
3401        OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
3402        OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
3403        OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
3404        OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
3405        OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
3406    }
3407
3408    R128RestoreMode(pScrn, restore);
3409
3410    if (!info->IsSecondary) {
3411        OUTREG(R128_AMCGPIO_MASK,     restore->amcgpio_mask);
3412        OUTREG(R128_AMCGPIO_EN_REG,   restore->amcgpio_en_reg);
3413        OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
3414        OUTREG(R128_GEN_RESET_CNTL,   restore->gen_reset_cntl);
3415        OUTREG(R128_DP_DATATYPE,      restore->dp_datatype);
3416    }
3417
3418#ifdef WITH_VGAHW
3419    if (info->VGAAccess) {
3420        vgaHWPtr hwp = VGAHWPTR(pScrn);
3421        if (!info->IsSecondary) {
3422            vgaHWUnlock(hwp);
3423# if defined(__powerpc__)
3424            /* Temporary hack to prevent crashing on PowerMacs when trying to
3425             * write VGA fonts, will find a better solution in the future
3426             */
3427            vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE );
3428# else
3429            vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
3430# endif
3431            vgaHWLock(hwp);
3432        } else {
3433            R128EntPtr  pR128Ent = R128EntPriv(pScrn);
3434            ScrnInfoPtr   pScrn0 = pR128Ent->pPrimaryScrn;
3435            R128InfoPtr info0 = R128PTR(pScrn0);
3436            vgaHWPtr      hwp0;
3437
3438            if (info0->VGAAccess) {
3439                hwp0 = VGAHWPTR(pScrn0);
3440                vgaHWUnlock(hwp0);
3441#if defined(__powerpc__)
3442                vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE);
3443#else
3444                vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS );
3445#endif
3446                vgaHWLock(hwp0);
3447            }
3448        }
3449    }
3450#endif
3451
3452    R128WaitForVerticalSync(pScrn);
3453    R128Unblank(pScrn);
3454}
3455
3456/* Define common registers for requested video mode. */
3457static void R128InitCommonRegisters(R128SavePtr save, R128InfoPtr info)
3458{
3459    save->ovr_clr            = 0;
3460    save->ovr_wid_left_right = 0;
3461    save->ovr_wid_top_bottom = 0;
3462    save->ov0_scale_cntl     = 0;
3463    save->mpp_tb_config      = 0;
3464    save->mpp_gp_config      = 0;
3465    save->subpic_cntl        = 0;
3466    save->viph_control       = 0;
3467    save->i2c_cntl_1         = 0;
3468#ifdef XF86DRI
3469    save->gen_int_cntl       = info->gen_int_cntl;
3470#else
3471    save->gen_int_cntl       = 0;
3472#endif
3473    save->cap0_trig_cntl     = 0;
3474    save->cap1_trig_cntl     = 0;
3475    save->bus_cntl           = info->BusCntl;
3476    /*
3477     * If bursts are enabled, turn on discards and aborts
3478     */
3479    if (save->bus_cntl & (R128_BUS_WRT_BURST|R128_BUS_READ_BURST))
3480	save->bus_cntl |= R128_BUS_RD_DISCARD_EN | R128_BUS_RD_ABORT_EN;
3481}
3482
3483/* Define CRTC registers for requested video mode. */
3484static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
3485				  DisplayModePtr mode, R128InfoPtr info)
3486{
3487    int    format;
3488    int    hsync_start;
3489    int    hsync_wid;
3490    int    hsync_fudge;
3491    int    vsync_wid;
3492    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
3493    int    hsync_fudge_fp[]      = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 };
3494//   int    hsync_fudge_fp_crt[]  = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 };
3495
3496    switch (info->CurrentLayout.pixel_code) {
3497    case 4:  format = 1; break;
3498    case 8:  format = 2; break;
3499    case 15: format = 3; break;      /*  555 */
3500    case 16: format = 4; break;      /*  565 */
3501    case 24: format = 5; break;      /*  RGB */
3502    case 32: format = 6; break;      /* xRGB */
3503    default:
3504	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3505		   "Unsupported pixel depth (%d)\n",
3506		   info->CurrentLayout.bitsPerPixel);
3507	return FALSE;
3508    }
3509
3510    if ((info->DisplayType == MT_DFP) ||
3511        (info->DisplayType == MT_LCD))
3512	hsync_fudge = hsync_fudge_fp[format-1];
3513    else
3514        hsync_fudge = hsync_fudge_default[format-1];
3515
3516    save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN
3517			  | R128_CRTC_EN
3518			  | (format << 8)
3519			  | ((mode->Flags & V_DBLSCAN)
3520			     ? R128_CRTC_DBL_SCAN_EN
3521			     : 0)
3522			  | ((mode->Flags & V_INTERLACE)
3523			     ? R128_CRTC_INTERLACE_EN
3524			     : 0)
3525			  | ((mode->Flags & V_CSYNC)
3526			     ? R128_CRTC_CSYNC_EN
3527			     : 0));
3528
3529    if((info->DisplayType == MT_DFP) ||
3530       (info->DisplayType == MT_LCD))
3531    {
3532        save->crtc_ext_cntl = R128_VGA_ATI_LINEAR |
3533        			  R128_XCRT_CNT_EN;
3534        save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN |
3535                                  R128_CRTC_INTERLACE_EN);
3536    }
3537    else
3538        save->crtc_ext_cntl = R128_VGA_ATI_LINEAR |
3539			      R128_XCRT_CNT_EN |
3540			      R128_CRTC_CRT_ON;
3541
3542    save->dac_cntl      = (R128_DAC_MASK_ALL
3543			   | R128_DAC_VGA_ADR_EN
3544			   | (info->dac6bits ? 0 : R128_DAC_8BIT_EN));
3545
3546
3547    if(info->isDFP && !info->isPro2)
3548    {
3549        if(info->PanelXRes < mode->CrtcHDisplay)
3550            mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes;
3551        if(info->PanelYRes < mode->CrtcVDisplay)
3552            mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes;
3553        mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank;
3554        mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus;
3555        mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth;
3556        mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank;
3557        mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus;
3558        mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth;
3559    }
3560
3561    save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
3562			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
3563
3564    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
3565    if (!hsync_wid)       hsync_wid = 1;
3566    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
3567
3568    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
3569
3570    save->crtc_h_sync_strt_wid = ((hsync_start & 0xfff)
3571				 | (hsync_wid << 16)
3572				 | ((mode->Flags & V_NHSYNC)
3573				    ? R128_CRTC_H_SYNC_POL
3574				    : 0));
3575
3576#if 1
3577				/* This works for double scan mode. */
3578    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3579			      | ((mode->CrtcVDisplay - 1) << 16));
3580#else
3581				/* This is what cce/nbmode.c example code
3582				   does -- is this correct? */
3583    save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3584			      | ((mode->CrtcVDisplay
3585				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
3586				 << 16));
3587#endif
3588
3589    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
3590    if (!vsync_wid)       vsync_wid = 1;
3591    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
3592
3593    save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3594				 | (vsync_wid << 16)
3595				 | ((mode->Flags & V_NVSYNC)
3596				    ? R128_CRTC_V_SYNC_POL
3597				    : 0));
3598    save->crtc_offset      = 0;
3599    save->crtc_offset_cntl = 0;
3600    save->crtc_pitch       = info->CurrentLayout.displayWidth / 8;
3601
3602    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3603	       save->crtc_pitch, pScrn->virtualX, info->CurrentLayout.displayWidth));
3604
3605#if X_BYTE_ORDER == X_BIG_ENDIAN
3606    /* Change the endianness of the aperture */
3607    switch (info->CurrentLayout.pixel_code) {
3608    case 15:
3609    case 16: save->config_cntl |= APER_0_BIG_ENDIAN_16BPP_SWAP; break;
3610    case 32: save->config_cntl |= APER_0_BIG_ENDIAN_32BPP_SWAP; break;
3611    default: break;
3612    }
3613#endif
3614
3615    return TRUE;
3616}
3617
3618/* Define CRTC2 registers for requested video mode. */
3619static Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save,
3620				  DisplayModePtr mode, R128InfoPtr info)
3621{
3622    int    format;
3623    int    hsync_start;
3624    int    hsync_wid;
3625    int    hsync_fudge;
3626    int    vsync_wid;
3627    int    bytpp;
3628    int    hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
3629
3630    switch (info->CurrentLayout.pixel_code) {
3631    case 4:  format = 1; bytpp = 0; break;
3632    case 8:  format = 2; bytpp = 1; break;
3633    case 15: format = 3; bytpp = 2; break;      /*  555 */
3634    case 16: format = 4; bytpp = 2; break;      /*  565 */
3635    case 24: format = 5; bytpp = 3; break;      /*  RGB */
3636    case 32: format = 6; bytpp = 4; break;      /* xRGB */
3637    default:
3638	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3639		   "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel);
3640	return FALSE;
3641    }
3642    R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp));
3643
3644    hsync_fudge = hsync_fudge_default[format-1];
3645
3646    save->crtc2_gen_cntl = (R128_CRTC2_EN
3647			  | (format << 8)
3648			  | ((mode->Flags & V_DBLSCAN)
3649			     ? R128_CRTC2_DBL_SCAN_EN
3650			     : 0));
3651/*
3652    save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN;
3653    save->crtc2_gen_cntl |= (1 << 21);
3654*/
3655    save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff)
3656			      | (((mode->CrtcHDisplay / 8) - 1) << 16));
3657
3658    hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
3659    if (!hsync_wid)       hsync_wid = 1;
3660    if (hsync_wid > 0x3f) hsync_wid = 0x3f;
3661
3662    hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
3663
3664    save->crtc2_h_sync_strt_wid = ((hsync_start & 0xfff)
3665				 | (hsync_wid << 16)
3666				 | ((mode->Flags & V_NHSYNC)
3667				    ? R128_CRTC2_H_SYNC_POL
3668				    : 0));
3669
3670#if 1
3671				/* This works for double scan mode. */
3672    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3673			      | ((mode->CrtcVDisplay - 1) << 16));
3674#else
3675				/* This is what cce/nbmode.c example code
3676				   does -- is this correct? */
3677    save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff)
3678			      | ((mode->CrtcVDisplay
3679				  * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1)
3680				 << 16));
3681#endif
3682
3683    vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
3684    if (!vsync_wid)       vsync_wid = 1;
3685    if (vsync_wid > 0x1f) vsync_wid = 0x1f;
3686
3687    save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff)
3688				 | (vsync_wid << 16)
3689				 | ((mode->Flags & V_NVSYNC)
3690				    ? R128_CRTC2_V_SYNC_POL
3691				    : 0));
3692
3693    save->crtc2_offset      = 0;
3694    save->crtc2_offset_cntl = 0;
3695
3696    save->crtc2_pitch       = info->CurrentLayout.displayWidth / 8;
3697
3698    R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
3699		 save->crtc2_pitch, pScrn->virtualX,
3700		 info->CurrentLayout.displayWidth));
3701    return TRUE;
3702}
3703
3704/* Define CRTC registers for requested video mode. */
3705static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save,
3706				DisplayModePtr mode, R128InfoPtr info)
3707{
3708    int   xres = mode->CrtcHDisplay;
3709    int   yres = mode->CrtcVDisplay;
3710    float Hratio, Vratio;
3711
3712    if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) {
3713        save->crtc_ext_cntl  |= R128_CRTC_CRT_ON;
3714        save->crtc2_gen_cntl  = 0;
3715        save->fp_gen_cntl     = orig->fp_gen_cntl;
3716        save->fp_gen_cntl    &= ~(R128_FP_FPON |
3717            R128_FP_CRTC_USE_SHADOW_VEND |
3718            R128_FP_CRTC_HORZ_DIV2_EN |
3719            R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3720            R128_FP_USE_SHADOW_EN);
3721        save->fp_gen_cntl    |= (R128_FP_SEL_CRTC2 |
3722                                 R128_FP_CRTC_DONT_SHADOW_VPAR);
3723        save->fp_panel_cntl   = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON;
3724        save->lvds_gen_cntl   = orig->lvds_gen_cntl &
3725				    (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON);
3726        return;
3727    }
3728
3729    if (xres > info->PanelXRes) xres = info->PanelXRes;
3730    if (yres > info->PanelYRes) yres = info->PanelYRes;
3731
3732    Hratio = (float)xres/(float)info->PanelXRes;
3733    Vratio = (float)yres/(float)info->PanelYRes;
3734
3735    save->fp_horz_stretch =
3736	(((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5))
3737	   & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) |
3738       (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE |
3739                                 R128_HORZ_FP_LOOP_STRETCH |
3740                                 R128_HORZ_STRETCH_RESERVED)));
3741    save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN;
3742    save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO;
3743    if (xres == info->PanelXRes)
3744         save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3745    else
3746         save->fp_horz_stretch |=  (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE);
3747
3748    save->fp_vert_stretch =
3749	(((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5))
3750	   & R128_VERT_STRETCH_RATIO_MASK) << R128_VERT_STRETCH_RATIO_SHIFT) |
3751	 (orig->fp_vert_stretch & (R128_VERT_PANEL_SIZE |
3752				   R128_VERT_STRETCH_RESERVED)));
3753    save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN;
3754    if (yres == info->PanelYRes)
3755        save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3756    else
3757        save->fp_vert_stretch |=  (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND);
3758
3759    save->fp_gen_cntl = (orig->fp_gen_cntl &
3760			 (CARD32)~(R128_FP_SEL_CRTC2 |
3761				   R128_FP_CRTC_USE_SHADOW_VEND |
3762				   R128_FP_CRTC_HORZ_DIV2_EN |
3763				   R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3764				   R128_FP_USE_SHADOW_EN));
3765
3766    save->fp_panel_cntl        = orig->fp_panel_cntl;
3767    save->lvds_gen_cntl        = orig->lvds_gen_cntl;
3768    save->tmds_crc             = orig->tmds_crc;
3769
3770    /* Disable CRT output by disabling CRT output and setting the CRT
3771       DAC to use CRTC2, which we set to 0's.  In the future, we will
3772       want to use the dual CRTC capabilities of the R128 to allow both
3773       the flat panel and external CRT to either simultaneously display
3774       the same image or display two different images. */
3775
3776
3777    if(!info->isDFP){
3778        if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) {
3779		save->crtc_ext_cntl  |= R128_CRTC_CRT_ON;
3780	} else if (info->BIOSDisplay == R128_DUALHEAD) {
3781		save->crtc_ext_cntl  |= R128_CRTC_CRT_ON;
3782		save->dac_cntl       |= R128_DAC_CRT_SEL_CRTC2;
3783		save->dac_cntl       |= R128_DAC_PALETTE2_SNOOP_EN;
3784        } else {
3785		save->crtc_ext_cntl  &= ~R128_CRTC_CRT_ON;
3786		save->dac_cntl       |= R128_DAC_CRT_SEL_CRTC2;
3787		save->crtc2_gen_cntl  = 0;
3788        }
3789    }
3790
3791    /* WARNING: Be careful about turning on the flat panel */
3792    if(info->isDFP){
3793        save->fp_gen_cntl = orig->fp_gen_cntl;
3794
3795        save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND |
3796                               R128_FP_CRTC_USE_SHADOW_ROWCUR |
3797                               R128_FP_CRTC_HORZ_DIV2_EN |
3798                               R128_FP_CRTC_HOR_CRT_DIV2_DIS |
3799                               R128_FP_CRT_SYNC_SEL |
3800                               R128_FP_USE_SHADOW_EN);
3801
3802        save->fp_panel_cntl  |= (R128_FP_DIGON | R128_FP_BLON);
3803        save->fp_gen_cntl    |= (R128_FP_FPON | R128_FP_TDMS_EN |
3804             R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND);
3805        save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl
3806            & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN;
3807    }
3808    else
3809        save->lvds_gen_cntl  |= (R128_LVDS_ON | R128_LVDS_BLON);
3810
3811    save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
3812    save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
3813    save->fp_h_sync_strt_wid   = save->crtc_h_sync_strt_wid;
3814    save->fp_v_sync_strt_wid   = save->crtc_v_sync_strt_wid;
3815}
3816
3817/* Define PLL registers for requested video mode. */
3818static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save,
3819				R128PLLPtr pll, double dot_clock)
3820{
3821    unsigned long freq = dot_clock * 100;
3822    struct {
3823	int divider;
3824	int bitvalue;
3825    } *post_div,
3826      post_divs[]   = {
3827				/* From RAGE 128 VR/RAGE 128 GL Register
3828				   Reference Manual (Technical Reference
3829				   Manual P/N RRG-G04100-C Rev. 0.04), page
3830				   3-17 (PLL_DIV_[3:0]).  */
3831	{  1, 0 },              /* VCLK_SRC                 */
3832	{  2, 1 },              /* VCLK_SRC/2               */
3833	{  4, 2 },              /* VCLK_SRC/4               */
3834	{  8, 3 },              /* VCLK_SRC/8               */
3835
3836	{  3, 4 },              /* VCLK_SRC/3               */
3837				/* bitvalue = 5 is reserved */
3838	{  6, 6 },              /* VCLK_SRC/6               */
3839	{ 12, 7 },              /* VCLK_SRC/12              */
3840	{  0, 0 }
3841    };
3842
3843    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3844    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3845
3846    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3847	save->pll_output_freq = post_div->divider * freq;
3848	if (save->pll_output_freq >= pll->min_pll_freq
3849	    && save->pll_output_freq <= pll->max_pll_freq) break;
3850    }
3851
3852    save->dot_clock_freq = freq;
3853    save->feedback_div   = R128Div(pll->reference_div * save->pll_output_freq,
3854				   pll->reference_freq);
3855    save->post_div       = post_div->divider;
3856
3857    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3858	       save->dot_clock_freq,
3859	       save->pll_output_freq,
3860	       save->feedback_div,
3861	       save->post_div));
3862
3863    save->ppll_ref_div   = pll->reference_div;
3864    save->ppll_div_3     = (save->feedback_div | (post_div->bitvalue << 16));
3865    save->htotal_cntl    = 0;
3866
3867}
3868
3869/* Define PLL2 registers for requested video mode. */
3870static void R128InitPLL2Registers(R128SavePtr save, R128PLLPtr pll,
3871				   double dot_clock)
3872{
3873    unsigned long freq = dot_clock * 100;
3874    struct {
3875	int divider;
3876	int bitvalue;
3877    } *post_div,
3878      post_divs[]   = {
3879				/* From RAGE 128 VR/RAGE 128 GL Register
3880				   Reference Manual (Technical Reference
3881				   Manual P/N RRG-G04100-C Rev. 0.04), page
3882				   3-17 (PLL_DIV_[3:0]).  */
3883	{  1, 0 },              /* VCLK_SRC                 */
3884	{  2, 1 },              /* VCLK_SRC/2               */
3885	{  4, 2 },              /* VCLK_SRC/4               */
3886	{  8, 3 },              /* VCLK_SRC/8               */
3887
3888	{  3, 4 },              /* VCLK_SRC/3               */
3889				/* bitvalue = 5 is reserved */
3890	{  6, 6 },              /* VCLK_SRC/6               */
3891	{ 12, 7 },              /* VCLK_SRC/12              */
3892	{  0, 0 }
3893    };
3894
3895    if (freq > pll->max_pll_freq)      freq = pll->max_pll_freq;
3896    if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12;
3897
3898    for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
3899	save->pll_output_freq_2 = post_div->divider * freq;
3900	if (save->pll_output_freq_2 >= pll->min_pll_freq
3901	    && save->pll_output_freq_2 <= pll->max_pll_freq) break;
3902    }
3903
3904    save->dot_clock_freq_2 = freq;
3905    save->feedback_div_2   = R128Div(pll->reference_div
3906				     * save->pll_output_freq_2,
3907				     pll->reference_freq);
3908    save->post_div_2       = post_div->divider;
3909
3910    R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n",
3911	       save->dot_clock_freq_2,
3912	       save->pll_output_freq_2,
3913	       save->feedback_div_2,
3914	       save->post_div_2));
3915
3916    save->p2pll_ref_div   = pll->reference_div;
3917    save->p2pll_div_0    = (save->feedback_div_2 | (post_div->bitvalue<<16));
3918    save->htotal_cntl2    = 0;
3919}
3920
3921/* Define DDA registers for requested video mode. */
3922static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save,
3923				 R128PLLPtr pll, R128InfoPtr info,
3924                                 DisplayModePtr mode)
3925{
3926    int         DisplayFifoWidth = 128;
3927    int         DisplayFifoDepth = 32;
3928    int         XclkFreq;
3929    int         VclkFreq;
3930    int         XclksPerTransfer;
3931    int         XclksPerTransferPrecise;
3932    int         UseablePrecision;
3933    int         Roff;
3934    int         Ron;
3935
3936    XclkFreq = pll->xclk;
3937
3938    VclkFreq = R128Div(pll->reference_freq * save->feedback_div,
3939		       pll->reference_div * save->post_div);
3940
3941    if(info->isDFP && !info->isPro2){
3942        if(info->PanelXRes != mode->CrtcHDisplay)
3943            VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes;
3944	}
3945
3946    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
3947			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3948
3949    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
3950
3951    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
3952				      << (11 - UseablePrecision),
3953				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
3954
3955    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
3956
3957    Ron   = (4 * info->ram->MB
3958	     + 3 * MAX(info->ram->Trcd - 2, 0)
3959	     + 2 * info->ram->Trp
3960	     + info->ram->Twr
3961	     + info->ram->CL
3962	     + info->ram->Tr2w
3963	     + XclksPerTransfer) << (11 - UseablePrecision);
3964
3965    if (Ron + info->ram->Rloop >= Roff) {
3966	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3967		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
3968		   Ron, info->ram->Rloop, Roff);
3969	return FALSE;
3970    }
3971
3972    save->dda_config = (XclksPerTransferPrecise
3973			| (UseablePrecision << 16)
3974			| (info->ram->Rloop << 20));
3975
3976    save->dda_on_off = (Ron << 16) | Roff;
3977
3978    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
3979	       XclkFreq,
3980	       VclkFreq,
3981	       XclksPerTransfer,
3982	       XclksPerTransferPrecise,
3983	       UseablePrecision));
3984    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
3985	       Roff, Ron, info->ram->Rloop));
3986
3987    return TRUE;
3988}
3989
3990/* Define DDA2 registers for requested video mode. */
3991static Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save,
3992				 R128PLLPtr pll, R128InfoPtr info,
3993                                 DisplayModePtr mode)
3994{
3995    int         DisplayFifoWidth = 128;
3996    int         DisplayFifoDepth = 32;
3997    int         XclkFreq;
3998    int         VclkFreq;
3999    int         XclksPerTransfer;
4000    int         XclksPerTransferPrecise;
4001    int         UseablePrecision;
4002    int         Roff;
4003    int         Ron;
4004
4005    XclkFreq = pll->xclk;
4006
4007    VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2,
4008		       pll->reference_div * save->post_div_2);
4009
4010    if(info->isDFP && !info->isPro2){
4011        if(info->PanelXRes != mode->CrtcHDisplay)
4012            VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes;
4013	}
4014
4015    XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth,
4016			       VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
4017
4018    UseablePrecision = R128MinBits(XclksPerTransfer) + 1;
4019
4020    XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth)
4021				      << (11 - UseablePrecision),
4022				      VclkFreq * (info->CurrentLayout.pixel_bytes * 8));
4023
4024    Roff  = XclksPerTransferPrecise * (DisplayFifoDepth - 4);
4025
4026    Ron   = (4 * info->ram->MB
4027	     + 3 * MAX(info->ram->Trcd - 2, 0)
4028	     + 2 * info->ram->Trp
4029	     + info->ram->Twr
4030	     + info->ram->CL
4031	     + info->ram->Tr2w
4032	     + XclksPerTransfer) << (11 - UseablePrecision);
4033
4034
4035    if (Ron + info->ram->Rloop >= Roff) {
4036	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4037		   "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n",
4038		   Ron, info->ram->Rloop, Roff);
4039	return FALSE;
4040    }
4041
4042    save->dda2_config = (XclksPerTransferPrecise
4043			| (UseablePrecision << 16)
4044			| (info->ram->Rloop << 20));
4045
4046    /*save->dda2_on_off = (Ron << 16) | Roff;*/
4047    /* shift most be 18 otherwise there's corruption on crtc2 */
4048    save->dda2_on_off = (Ron << 18) | Roff;
4049
4050    R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n",
4051	       XclkFreq,
4052	       VclkFreq,
4053	       XclksPerTransfer,
4054	       XclksPerTransferPrecise,
4055	       UseablePrecision));
4056    R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n",
4057	       Roff, Ron, info->ram->Rloop));
4058
4059    return TRUE;
4060}
4061
4062#if 0
4063/* Define initial palette for requested video mode.  This doesn't do
4064   anything for XFree86 4.0. */
4065static void R128InitPalette(R128SavePtr save)
4066{
4067    save->palette_valid = FALSE;
4068}
4069#endif
4070
4071/* Define registers for a requested video mode. */
4072static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save)
4073{
4074    R128InfoPtr info      = R128PTR(pScrn);
4075    double      dot_clock = mode->Clock/1000.0;
4076
4077#if R128_DEBUG
4078    ErrorF("%-12.12s %7.2f  %4d %4d %4d %4d  %4d %4d %4d %4d (%d,%d)",
4079	   mode->name,
4080	   dot_clock,
4081
4082	   mode->HDisplay,
4083	   mode->HSyncStart,
4084	   mode->HSyncEnd,
4085	   mode->HTotal,
4086
4087	   mode->VDisplay,
4088	   mode->VSyncStart,
4089	   mode->VSyncEnd,
4090	   mode->VTotal,
4091	   pScrn->depth,
4092	   pScrn->bitsPerPixel);
4093    if (mode->Flags & V_DBLSCAN)   ErrorF(" D");
4094    if (mode->Flags & V_CSYNC)     ErrorF(" C");
4095    if (mode->Flags & V_INTERLACE) ErrorF(" I");
4096    if (mode->Flags & V_PHSYNC)    ErrorF(" +H");
4097    if (mode->Flags & V_NHSYNC)    ErrorF(" -H");
4098    if (mode->Flags & V_PVSYNC)    ErrorF(" +V");
4099    if (mode->Flags & V_NVSYNC)    ErrorF(" -V");
4100    ErrorF("\n");
4101    ErrorF("%-12.12s %7.2f  %4d %4d %4d %4d  %4d %4d %4d %4d (%d,%d)",
4102	   mode->name,
4103	   dot_clock,
4104
4105	   mode->CrtcHDisplay,
4106	   mode->CrtcHSyncStart,
4107	   mode->CrtcHSyncEnd,
4108	   mode->CrtcHTotal,
4109
4110	   mode->CrtcVDisplay,
4111	   mode->CrtcVSyncStart,
4112	   mode->CrtcVSyncEnd,
4113	   mode->CrtcVTotal,
4114	   pScrn->depth,
4115	   pScrn->bitsPerPixel);
4116    if (mode->Flags & V_DBLSCAN)   ErrorF(" D");
4117    if (mode->Flags & V_CSYNC)     ErrorF(" C");
4118    if (mode->Flags & V_INTERLACE) ErrorF(" I");
4119    if (mode->Flags & V_PHSYNC)    ErrorF(" +H");
4120    if (mode->Flags & V_NHSYNC)    ErrorF(" -H");
4121    if (mode->Flags & V_PVSYNC)    ErrorF(" +V");
4122    if (mode->Flags & V_NVSYNC)    ErrorF(" -V");
4123    ErrorF("\n");
4124#endif
4125
4126    info->Flags = mode->Flags;
4127
4128    if(info->IsSecondary)
4129    {
4130        if (!R128InitCrtc2Registers(pScrn, save,
4131             pScrn->currentMode,info))
4132            return FALSE;
4133        R128InitPLL2Registers(save, &info->pll, dot_clock);
4134        if (!R128InitDDA2Registers(pScrn, save, &info->pll, info, mode))
4135	    return FALSE;
4136    }
4137    else
4138    {
4139        R128InitCommonRegisters(save, info);
4140        if(!R128InitCrtcRegisters(pScrn, save, mode, info))
4141            return FALSE;
4142        if(dot_clock)
4143        {
4144            R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock);
4145            if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode))
4146	        return FALSE;
4147        }
4148        else
4149        {
4150            save->ppll_ref_div         = info->SavedReg.ppll_ref_div;
4151            save->ppll_div_3           = info->SavedReg.ppll_div_3;
4152            save->htotal_cntl          = info->SavedReg.htotal_cntl;
4153            save->dda_config           = info->SavedReg.dda_config;
4154            save->dda_on_off           = info->SavedReg.dda_on_off;
4155        }
4156        /* not used for now */
4157        /*if (!info->PaletteSavedOnVT) RADEONInitPalette(save);*/
4158    }
4159
4160    if (((info->DisplayType == MT_DFP) ||
4161        (info->DisplayType == MT_LCD)))
4162    {
4163        R128InitFPRegisters(&info->SavedReg, save, mode, info);
4164    }
4165
4166    R128TRACE(("R128Init returns %p\n", save));
4167    return TRUE;
4168}
4169
4170/* Initialize a new mode. */
4171static Bool R128ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
4172{
4173    R128InfoPtr info      = R128PTR(pScrn);
4174
4175    if (!R128Init(pScrn, mode, &info->ModeReg)) return FALSE;
4176				/* FIXME?  DRILock/DRIUnlock here? */
4177    pScrn->vtSema = TRUE;
4178    R128Blank(pScrn);
4179    R128RestoreMode(pScrn, &info->ModeReg);
4180    R128Unblank(pScrn);
4181
4182    info->CurrentLayout.mode = mode;
4183
4184    return TRUE;
4185}
4186
4187static Bool R128SaveScreen(ScreenPtr pScreen, int mode)
4188{
4189    ScrnInfoPtr   pScrn = xf86Screens[pScreen->myNum];
4190    Bool unblank;
4191
4192    unblank = xf86IsUnblank(mode);
4193    if (unblank)
4194	SetTimeSinceLastInputEvent();
4195
4196    if ((pScrn != NULL) && pScrn->vtSema) {
4197	if (unblank)
4198		R128Unblank(pScrn);
4199	else
4200		R128Blank(pScrn);
4201    }
4202    return TRUE;
4203}
4204
4205/*
4206 * SwitchMode() doesn't work right on crtc2 on some laptops.
4207 * The workaround is to switch the mode, then switch to another VT, then
4208 * switch back. --AGD
4209 */
4210Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
4211{
4212    ScrnInfoPtr   pScrn       = xf86Screens[scrnIndex];
4213    R128InfoPtr info        = R128PTR(pScrn);
4214    Bool ret;
4215
4216    info->SwitchingMode = TRUE;
4217    ret = R128ModeInit(xf86Screens[scrnIndex], mode);
4218    info->SwitchingMode = FALSE;
4219    return ret;
4220}
4221
4222/* Used to disallow modes that are not supported by the hardware. */
4223ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode,
4224                                   Bool verbose, int flags)
4225{
4226    ScrnInfoPtr   pScrn = xf86Screens[scrnIndex];
4227    R128InfoPtr   info  = R128PTR(pScrn);
4228
4229    if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT)
4230	return MODE_OK;
4231
4232    if(info->isDFP) {
4233        if(info->PanelXRes < mode->CrtcHDisplay ||
4234           info->PanelYRes < mode->CrtcVDisplay)
4235            return MODE_NOMODE;
4236        else
4237            return MODE_OK;
4238    }
4239
4240    if (info->DisplayType == MT_LCD) {
4241	if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE;
4242	if (mode->Flags & V_DBLSCAN)   return MODE_NO_DBLESCAN;
4243    }
4244
4245    if (info->DisplayType == MT_LCD &&
4246	info->VBIOS) {
4247	int i;
4248	for (i = info->FPBIOSstart+64; R128_BIOS16(i) != 0; i += 2) {
4249	    int j = R128_BIOS16(i);
4250
4251	    if (mode->CrtcHDisplay == R128_BIOS16(j) &&
4252		mode->CrtcVDisplay == R128_BIOS16(j+2)) {
4253		if ((flags & MODECHECK_FINAL) == MODECHECK_FINAL) {
4254		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4255			       "Modifying mode according to VBIOS: %ix%i [pclk %.1f MHz] for FP to: ",
4256			       mode->CrtcHDisplay,mode->CrtcVDisplay,
4257			       (float)mode->Clock/1000);
4258
4259		    /* Assume we are using expanded mode */
4260		    if (R128_BIOS16(j+5)) j  = R128_BIOS16(j+5);
4261		    else                  j += 9;
4262
4263		    mode->Clock = (CARD32)R128_BIOS16(j) * 10;
4264
4265		    mode->HDisplay   = mode->CrtcHDisplay   =
4266			((R128_BIOS16(j+10) & 0x01ff)+1)*8;
4267		    mode->HSyncStart = mode->CrtcHSyncStart =
4268			((R128_BIOS16(j+12) & 0x01ff)+1)*8;
4269		    mode->HSyncEnd   = mode->CrtcHSyncEnd   =
4270			mode->CrtcHSyncStart + (R128_BIOS8(j+14) & 0x1f);
4271		    mode->HTotal     = mode->CrtcHTotal     =
4272			((R128_BIOS16(j+8)  & 0x01ff)+1)*8;
4273
4274		    mode->VDisplay   = mode->CrtcVDisplay   =
4275			(R128_BIOS16(j+17) & 0x07ff)+1;
4276		    mode->VSyncStart = mode->CrtcVSyncStart =
4277			(R128_BIOS16(j+19) & 0x07ff)+1;
4278		    mode->VSyncEnd   = mode->CrtcVSyncEnd   =
4279			mode->CrtcVSyncStart + ((R128_BIOS16(j+19) >> 11) & 0x1f);
4280		    mode->VTotal     = mode->CrtcVTotal     =
4281			(R128_BIOS16(j+15) & 0x07ff)+1;
4282		    xf86ErrorF("%ix%i [pclk %.1f MHz]\n",
4283			       mode->CrtcHDisplay,mode->CrtcVDisplay,
4284			       (float)mode->Clock/1000);
4285		}
4286		return MODE_OK;
4287	    }
4288	}
4289	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 5,
4290		       "Mode rejected for FP %ix%i [pclk: %.1f] "
4291		       "(not listed in VBIOS)\n",
4292		       mode->CrtcHDisplay, mode->CrtcVDisplay,
4293		       (float)mode->Clock / 1000);
4294	return MODE_NOMODE;
4295    }
4296
4297    return MODE_OK;
4298}
4299
4300/* Adjust viewport into virtual desktop such that (0,0) in viewport space
4301   is (x,y) in virtual space. */
4302void R128AdjustFrame(int scrnIndex, int x, int y, int flags)
4303{
4304    ScrnInfoPtr   pScrn     = xf86Screens[scrnIndex];
4305    R128InfoPtr   info      = R128PTR(pScrn);
4306    unsigned char *R128MMIO = info->MMIO;
4307    int           Base;
4308
4309    if(info->showCache && y && pScrn->vtSema)
4310        y += pScrn->virtualY - 1;
4311
4312    Base = y * info->CurrentLayout.displayWidth + x;
4313
4314    switch (info->CurrentLayout.pixel_code) {
4315    case 15:
4316    case 16: Base *= 2; break;
4317    case 24: Base *= 3; break;
4318    case 32: Base *= 4; break;
4319    }
4320
4321    Base &= ~7;                 /* 3 lower bits are always 0 */
4322
4323    if (info->CurrentLayout.pixel_code == 24)
4324	Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */
4325
4326    if(info->IsSecondary)
4327    {
4328        Base += pScrn->fbOffset;
4329        OUTREG(R128_CRTC2_OFFSET, Base);
4330    }
4331    else
4332    OUTREG(R128_CRTC_OFFSET, Base);
4333
4334}
4335
4336/* Called when VT switching back to the X server.  Reinitialize the video
4337   mode. */
4338Bool R128EnterVT(int scrnIndex, int flags)
4339{
4340    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4341    R128InfoPtr info  = R128PTR(pScrn);
4342
4343    R128TRACE(("R128EnterVT\n"));
4344#ifndef AVOID_FBDEV
4345    if (info->FBDev) {
4346        if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE;
4347    } else
4348#endif
4349        if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE;
4350    if (info->accelOn)
4351	R128EngineInit(pScrn);
4352
4353#ifdef XF86DRI
4354    if (info->directRenderingEnabled) {
4355	if (info->irq) {
4356	    /* Need to make sure interrupts are enabled */
4357	    unsigned char *R128MMIO = info->MMIO;
4358	    OUTREG(R128_GEN_INT_CNTL, info->gen_int_cntl);
4359	}
4360	R128CCE_START(pScrn, info);
4361	DRIUnlock(pScrn->pScreen);
4362    }
4363#endif
4364
4365    info->PaletteSavedOnVT = FALSE;
4366    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
4367
4368    return TRUE;
4369}
4370
4371/* Called when VT switching away from the X server.  Restore the original
4372   text mode. */
4373void R128LeaveVT(int scrnIndex, int flags)
4374{
4375    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4376    R128InfoPtr info  = R128PTR(pScrn);
4377    R128SavePtr save  = &info->ModeReg;
4378
4379    R128TRACE(("R128LeaveVT\n"));
4380#ifdef XF86DRI
4381    if (info->directRenderingEnabled) {
4382	DRILock(pScrn->pScreen, 0);
4383	R128CCE_STOP(pScrn, info);
4384    }
4385#endif
4386    R128SavePalette(pScrn, save);
4387    info->PaletteSavedOnVT = TRUE;
4388#ifndef AVOID_FBDEV
4389    if (info->FBDev)
4390        fbdevHWLeaveVT(scrnIndex,flags);
4391    else
4392#endif
4393        R128Restore(pScrn);
4394}
4395
4396
4397/* Called at the end of each server generation.  Restore the original text
4398   mode, unmap video memory, and unwrap and call the saved CloseScreen
4399   function.  */
4400static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen)
4401{
4402    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4403    R128InfoPtr info  = R128PTR(pScrn);
4404
4405    R128TRACE(("R128CloseScreen\n"));
4406
4407#ifdef XF86DRI
4408				/* Disable direct rendering */
4409    if (info->directRenderingEnabled) {
4410	R128DRICloseScreen(pScreen);
4411	info->directRenderingEnabled = FALSE;
4412    }
4413#endif
4414
4415    if (pScrn->vtSema) {
4416	R128Restore(pScrn);
4417	R128UnmapMem(pScrn);
4418    }
4419
4420    if (info->accel)             XAADestroyInfoRec(info->accel);
4421    info->accel                  = NULL;
4422
4423    if (info->scratch_save)      xfree(info->scratch_save);
4424    info->scratch_save           = NULL;
4425
4426    if (info->cursor)            xf86DestroyCursorInfoRec(info->cursor);
4427    info->cursor                 = NULL;
4428
4429    if (info->DGAModes)          xfree(info->DGAModes);
4430    info->DGAModes               = NULL;
4431
4432    if (info->adaptor) {
4433        xfree(info->adaptor->pPortPrivates[0].ptr);
4434	xf86XVFreeVideoAdaptorRec(info->adaptor);
4435	info->adaptor = NULL;
4436    }
4437
4438    pScrn->vtSema = FALSE;
4439
4440    pScreen->BlockHandler = info->BlockHandler;
4441    pScreen->CloseScreen = info->CloseScreen;
4442    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
4443}
4444
4445void R128FreeScreen(int scrnIndex, int flags)
4446{
4447    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4448    R128InfoPtr   info      = R128PTR(pScrn);
4449
4450    R128TRACE(("R128FreeScreen\n"));
4451    if (info == NULL)
4452	return;
4453#ifdef WITH_VGAHW
4454    if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
4455	vgaHWFreeHWRec(pScrn);
4456#endif
4457    R128FreeRec(pScrn);
4458}
4459
4460/* Sets VESA Display Power Management Signaling (DPMS) Mode.  */
4461static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn,
4462					  int PowerManagementMode, int flags)
4463{
4464    R128InfoPtr   info      = R128PTR(pScrn);
4465    unsigned char *R128MMIO = info->MMIO;
4466    int           mask      = (R128_CRTC_DISPLAY_DIS
4467			       | R128_CRTC_HSYNC_DIS
4468			       | R128_CRTC_VSYNC_DIS);
4469    int             mask2     = R128_CRTC2_DISP_DIS;
4470
4471    switch (PowerManagementMode) {
4472    case DPMSModeOn:
4473	/* Screen: On; HSync: On, VSync: On */
4474	if (info->IsSecondary)
4475		OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask2);
4476	else
4477		OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask);
4478	break;
4479    case DPMSModeStandby:
4480	/* Screen: Off; HSync: Off, VSync: On */
4481	if (info->IsSecondary)
4482		OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2);
4483	    else
4484		OUTREGP(R128_CRTC_EXT_CNTL,
4485			R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask);
4486	break;
4487    case DPMSModeSuspend:
4488	/* Screen: Off; HSync: On, VSync: Off */
4489	if (info->IsSecondary)
4490		OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_DISP_DIS, ~mask2);
4491	else
4492		OUTREGP(R128_CRTC_EXT_CNTL,
4493			R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask);
4494	break;
4495    case DPMSModeOff:
4496	/* Screen: Off; HSync: Off, VSync: Off */
4497	if (info->IsSecondary)
4498		OUTREGP(R128_CRTC2_GEN_CNTL, mask2, ~mask2);
4499	else
4500		OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask);
4501	break;
4502    }
4503    if(info->isDFP) {
4504	switch (PowerManagementMode) {
4505	case DPMSModeOn:
4506	    OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) | (R128_FP_FPON | R128_FP_TDMS_EN));
4507	    break;
4508	case DPMSModeStandby:
4509	case DPMSModeSuspend:
4510	case DPMSModeOff:
4511	    OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) & ~(R128_FP_FPON | R128_FP_TDMS_EN));
4512	    break;
4513	}
4514    }
4515}
4516
4517static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on);
4518
4519static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn,
4520					  int PowerManagementMode, int flags)
4521{
4522    R128InfoPtr   info      = R128PTR(pScrn);
4523    unsigned char *R128MMIO = info->MMIO;
4524    int           mask      = R128_LVDS_DISPLAY_DIS;
4525
4526    switch (PowerManagementMode) {
4527    case DPMSModeOn:
4528	/* Screen: On; HSync: On, VSync: On */
4529	OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask);
4530        r128_set_backlight_enable(pScrn, 1);
4531	break;
4532    case DPMSModeStandby:
4533	/* Fall through */
4534    case DPMSModeSuspend:
4535	/* Fall through */
4536    case DPMSModeOff:
4537	/* Screen: Off; HSync: Off, VSync: Off */
4538	OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask);
4539        r128_set_backlight_enable(pScrn, 0);
4540	break;
4541    }
4542}
4543
4544static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on)
4545{
4546        R128InfoPtr info        = R128PTR(pScrn);
4547        unsigned char *R128MMIO = info->MMIO;
4548	unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL);
4549
4550	lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON);
4551	if (on) {
4552		lvds_gen_cntl |= R128_LVDS_DIGON;
4553		if (!(lvds_gen_cntl & R128_LVDS_ON)) {
4554			lvds_gen_cntl &= ~R128_LVDS_BLON;
4555			OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4556			(void)INREG(R128_LVDS_GEN_CNTL);
4557			usleep(10000);
4558			lvds_gen_cntl |= R128_LVDS_BLON;
4559			OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4560		}
4561#if 0
4562		lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK;
4563		lvds_gen_cntl |= (0xFF /* backlight_conv[level] */ <<
4564				  R128_LVDS_BL_MOD_LEVEL_SHIFT);
4565#endif
4566		lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_EN);
4567		lvds_gen_cntl &= ~R128_LVDS_DISPLAY_DIS;
4568	} else {
4569#if 0
4570		lvds_gen_cntl &= ~R128_LVDS_BL_MOD_LEVEL_MASK;
4571		lvds_gen_cntl |= (0xFF /* backlight_conv[0] */ <<
4572				  R128_LVDS_BL_MOD_LEVEL_SHIFT);
4573#endif
4574		lvds_gen_cntl |= R128_LVDS_DISPLAY_DIS;
4575		OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4576		usleep(10);
4577		lvds_gen_cntl &= ~(R128_LVDS_ON | R128_LVDS_EN | R128_LVDS_BLON
4578				   | R128_LVDS_DIGON);
4579	}
4580
4581	OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
4582
4583	return 0;
4584}
4585