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