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