abort on Init table command not found when parsing bios
[nouveau] / src / nv_driver.c
1 /* $XdotOrg: driver/xf86-video-nv/src/nv_driver.c,v 1.21 2006/01/24 16:45:29 aplattner Exp $ */
2 /* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
3 /*
4  * Copyright 1996-1997  David J. McKay
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 /* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
26    <jpaana@s2.org> */
27
28 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_driver.c,v 1.144 2006/06/16 00:19:32 mvojkovi Exp $ */
29
30 #include <stdio.h>
31
32 #include "nv_include.h"
33
34 #include "xf86int10.h"
35
36 #include "xf86drm.h"
37
38 extern DisplayModePtr xf86ModesAdd(DisplayModePtr Modes, DisplayModePtr Additions);
39
40 /*
41  * Forward definitions for the functions that make up the driver.
42  */
43 /* Mandatory functions */
44 static const OptionInfoRec * NVAvailableOptions(int chipid, int busid);
45 static void    NVIdentify(int flags);
46 #ifndef XSERVER_LIBPCIACCESS
47 static Bool    NVProbe(DriverPtr drv, int flags);
48 #endif /* XSERVER_LIBPCIACCESS */
49 static Bool    NVPreInit(ScrnInfoPtr pScrn, int flags);
50 static Bool    NVScreenInit(int Index, ScreenPtr pScreen, int argc,
51                             char **argv);
52 static Bool    NVEnterVT(int scrnIndex, int flags);
53 static void    NVLeaveVT(int scrnIndex, int flags);
54 static Bool    NVCloseScreen(int scrnIndex, ScreenPtr pScreen);
55 static Bool    NVSaveScreen(ScreenPtr pScreen, int mode);
56
57 /* Optional functions */
58 static void    NVFreeScreen(int scrnIndex, int flags);
59 static ModeStatus NVValidMode(int scrnIndex, DisplayModePtr mode,
60                               Bool verbose, int flags);
61 #ifdef RANDR
62 static Bool    NVDriverFunc(ScrnInfoPtr pScrnInfo, xorgDriverFuncOp op,
63                               pointer data);
64 #endif
65
66 /* Internally used functions */
67
68 static Bool     NVMapMem(ScrnInfoPtr pScrn);
69 static Bool     NVUnmapMem(ScrnInfoPtr pScrn);
70 static void     NVSave(ScrnInfoPtr pScrn);
71 static void     NVRestore(ScrnInfoPtr pScrn);
72 static Bool     NVModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
73
74 #ifdef XSERVER_LIBPCIACCESS
75
76 #define NOUVEAU_PCI_DEVICE(_vendor_id, _device_id) \
77         { (_vendor_id), (_device_id), PCI_MATCH_ANY, PCI_MATCH_ANY, 0x00030000, 0x00ffffff, 0 }
78
79 static const struct pci_id_match nouveau_device_match[] = {
80         NOUVEAU_PCI_DEVICE(PCI_VENDOR_NVIDIA, PCI_MATCH_ANY),
81         NOUVEAU_PCI_DEVICE(PCI_VENDOR_NVIDIA_SGS, PCI_MATCH_ANY),
82         { 0, 0, 0 },
83 };
84
85 static Bool NVPciProbe (        DriverPtr               drv,
86                                 int                     entity_num,
87                                 struct pci_device       *dev,
88                                 intptr_t                match_data      );
89
90 #endif /* XSERVER_LIBPCIACCESS */
91
92 /*
93  * This contains the functions needed by the server after loading the
94  * driver module.  It must be supplied, and gets added the driver list by
95  * the Module Setup funtion in the dynamic case.  In the static case a
96  * reference to this is compiled in, and this requires that the name of
97  * this DriverRec be an upper-case version of the driver name.
98  */
99
100 _X_EXPORT DriverRec NV = {
101         NV_VERSION,
102         NV_DRIVER_NAME,
103         NVIdentify,
104 #ifdef XSERVER_LIBPCIACCESS
105         NULL,
106 #else
107         NVProbe,
108 #endif /* XSERVER_LIBPCIACCESS */
109         NVAvailableOptions,
110         NULL,
111         0,
112         NULL,
113 #ifdef XSERVER_LIBPCIACCESS
114         nouveau_device_match,
115         NVPciProbe
116 #endif /* XSERVER_LIBPCIACCESS */
117 };
118
119 struct NvFamily
120 {
121   char *name;
122   char *chipset;
123 };
124
125 static struct NvFamily NVKnownFamilies[] =
126 {
127   { "RIVA TNT",    "NV04" },
128   { "RIVA TNT2",   "NV05" },
129   { "GeForce 256", "NV10" },
130   { "GeForce 2",   "NV11, NV15" },
131   { "GeForce 4MX", "NV17, NV18" },
132   { "GeForce 3",   "NV20" },
133   { "GeForce 4Ti", "NV25, NV28" },
134   { "GeForce FX",  "NV3x" },
135   { "GeForce 6",   "NV4x" },
136   { "GeForce 7",   "G7x" },
137   { "GeForce 8",   "G8x" },
138   { NULL, NULL}
139 };
140
141 /*
142  * List of symbols from other modules that this module references.  This
143  * list is used to tell the loader that it is OK for symbols here to be
144  * unresolved providing that it hasn't been told that they haven't been
145  * told that they are essential via a call to xf86LoaderReqSymbols() or
146  * xf86LoaderReqSymLists().  The purpose is this is to avoid warnings about
147  * unresolved symbols that are not required.
148  */
149
150 static const char *vgahwSymbols[] = {
151     "vgaHWUnmapMem",
152     "vgaHWDPMSSet",
153     "vgaHWFreeHWRec",
154     "vgaHWGetHWRec",
155     "vgaHWGetIndex",
156     "vgaHWInit",
157     "vgaHWMapMem",
158     "vgaHWProtect",
159     "vgaHWRestore",
160     "vgaHWSave",
161     "vgaHWSaveScreen",
162     NULL
163 };
164
165 static const char *fbSymbols[] = {
166     "fbPictureInit",
167     "fbScreenInit",
168     NULL
169 };
170
171 static const char *exaSymbols[] = {
172     "exaDriverInit",
173     "exaOffscreenInit",
174     NULL
175 };
176
177 static const char *ramdacSymbols[] = {
178     "xf86CreateCursorInfoRec",
179     "xf86DestroyCursorInfoRec",
180     "xf86InitCursor",
181     NULL
182 };
183
184 static const char *ddcSymbols[] = {
185     "xf86PrintEDID",
186     "xf86DoEDID_DDC2",
187     "xf86SetDDCproperties",
188     NULL
189 };
190
191 static const char *vbeSymbols[] = {
192     "VBEInit",
193     "vbeFree",
194     "vbeDoEDID",
195     NULL
196 };
197
198 static const char *i2cSymbols[] = {
199     "xf86CreateI2CBusRec",
200     "xf86I2CBusInit",
201     NULL
202 };
203
204 static const char *shadowSymbols[] = {
205     "ShadowFBInit",
206     NULL
207 };
208
209 static const char *int10Symbols[] = {
210     "xf86FreeInt10",
211     "xf86InitInt10",
212     NULL
213 };
214
215 const char *drmSymbols[] = {
216     "drmOpen", 
217     "drmAddBufs",
218     "drmAddMap",
219     "drmAgpAcquire",
220     "drmAgpVersionMajor",
221     "drmAgpVersionMinor",
222     "drmAgpAlloc",
223     "drmAgpBind",
224     "drmAgpEnable",
225     "drmAgpFree",
226     "drmAgpRelease",
227     "drmAgpUnbind",
228     "drmAuthMagic",
229     "drmCommandNone",
230     "drmCommandWrite",
231     "drmCommandWriteRead",
232     "drmCreateContext",
233     "drmCtlInstHandler",
234     "drmCtlUninstHandler",
235     "drmDestroyContext",
236     "drmFreeVersion",
237     "drmGetInterruptFromBusID",
238     "drmGetLibVersion",
239     "drmGetVersion",
240     NULL
241 };
242
243 const char *driSymbols[] = {
244     "DRICloseScreen",
245     "DRICreateInfoRec",
246     "DRIDestroyInfoRec",
247     "DRIFinishScreenInit",
248     "DRIGetSAREAPrivate",
249     "DRILock",
250     "DRIQueryVersion",
251     "DRIScreenInit",
252     "DRIUnlock",
253     "GlxSetVisualConfigs",
254     "DRICreatePCIBusID",
255     NULL
256 };
257
258
259 static MODULESETUPPROTO(nouveauSetup);
260
261 static XF86ModuleVersionInfo nouveauVersRec =
262 {
263     "nouveau",
264     MODULEVENDORSTRING,
265     MODINFOSTRING1,
266     MODINFOSTRING2,
267     XORG_VERSION_CURRENT,
268     NV_MAJOR_VERSION, NV_MINOR_VERSION, NV_PATCHLEVEL,
269     ABI_CLASS_VIDEODRV,                     /* This is a video driver */
270     ABI_VIDEODRV_VERSION,
271     MOD_CLASS_VIDEODRV,
272     {0,0,0,0}
273 };
274
275 _X_EXPORT XF86ModuleData nouveauModuleData = { &nouveauVersRec, nouveauSetup, NULL };
276
277
278 /*
279  * This is intentionally screen-independent.  It indicates the binding
280  * choice made in the first PreInit.
281  */
282 static int pix24bpp = 0;
283
284 static Bool
285 NVGetRec(ScrnInfoPtr pScrn)
286 {
287     /*
288      * Allocate an NVRec, and hook it into pScrn->driverPrivate.
289      * pScrn->driverPrivate is initialised to NULL, so we can check if
290      * the allocation has already been done.
291      */
292     if (pScrn->driverPrivate != NULL)
293         return TRUE;
294
295     pScrn->driverPrivate = xnfcalloc(sizeof(NVRec), 1);
296     /* Initialise it */
297
298     return TRUE;
299 }
300
301 static void
302 NVFreeRec(ScrnInfoPtr pScrn)
303 {
304     if (pScrn->driverPrivate == NULL)
305         return;
306     xfree(pScrn->driverPrivate);
307     pScrn->driverPrivate = NULL;
308 }
309
310
311 static pointer
312 nouveauSetup(pointer module, pointer opts, int *errmaj, int *errmin)
313 {
314         static Bool setupDone = FALSE;
315
316         /* This module should be loaded only once, but check to be sure. */
317
318         if (!setupDone) {
319                 setupDone = TRUE;
320                 /* The 1 here is needed to turn off a backwards compatibility mode */
321                 /* Otherwise NVPciProbe() is not called */
322                 xf86AddDriver(&NV, module, 1);
323
324                 /*
325                  * Modules that this driver always requires may be loaded here
326                  * by calling LoadSubModule().
327                  */
328                 /*
329                  * Tell the loader about symbols from other modules that this module
330                  * might refer to.
331                  */
332                 LoaderRefSymLists(vgahwSymbols, exaSymbols, fbSymbols,
333 #ifdef XF86DRI
334                                 drmSymbols, 
335 #endif
336                                 ramdacSymbols, shadowSymbols,
337                                 i2cSymbols, ddcSymbols, vbeSymbols,
338                                 int10Symbols, NULL);
339
340                 /*
341                  * The return value must be non-NULL on success even though there
342                  * is no TearDownProc.
343                  */
344                 return (pointer)1;
345         } else {
346                 if (errmaj) *errmaj = LDR_ONCEONLY;
347                 return NULL;
348         }
349 }
350
351 static const OptionInfoRec *
352 NVAvailableOptions(int chipid, int busid)
353 {
354     return NVOptions;
355 }
356
357 /* Mandatory */
358 static void
359 NVIdentify(int flags)
360 {
361     struct NvFamily *family;
362     size_t maxLen=0;
363
364     xf86DrvMsg(0, X_INFO, NV_NAME " driver " NV_DRIVER_DATE "\n");
365     xf86DrvMsg(0, X_INFO, NV_NAME " driver for NVIDIA chipset families :\n");
366
367     /* maximum length for alignment */
368     family = NVKnownFamilies;
369     while(family->name && family->chipset)
370     {
371         maxLen = max(maxLen, strlen(family->name));
372         family++;
373     }
374
375     /* display */
376     family = NVKnownFamilies;
377     while(family->name && family->chipset)
378     {
379         size_t len = strlen(family->name);
380         xf86ErrorF("\t%s", family->name);
381         while(len<maxLen+1)
382         {
383             xf86ErrorF(" ");
384             len++;
385         }
386         xf86ErrorF("(%s)\n", family->chipset);
387         family++;
388     }
389 }
390
391
392 static Bool
393 NVGetScrnInfoRec(PciChipsets *chips, int chip)
394 {
395     ScrnInfoPtr pScrn;
396
397     pScrn = xf86ConfigPciEntity(NULL, 0, chip,
398                                 chips, NULL, NULL, NULL,
399                                 NULL, NULL);
400
401     if(!pScrn) return FALSE;
402
403     pScrn->driverVersion    = NV_VERSION;
404     pScrn->driverName       = NV_DRIVER_NAME;
405     pScrn->name             = NV_NAME;
406
407 #ifndef XSERVER_LIBPCIACCESS
408         pScrn->Probe = NVProbe;
409 #else
410         pScrn->Probe = NULL;
411 #endif
412     pScrn->PreInit          = NVPreInit;
413     pScrn->ScreenInit       = NVScreenInit;
414     pScrn->SwitchMode       = NVSwitchMode;
415     pScrn->AdjustFrame      = NVAdjustFrame;
416     pScrn->EnterVT          = NVEnterVT;
417     pScrn->LeaveVT          = NVLeaveVT;
418     pScrn->FreeScreen       = NVFreeScreen;
419     pScrn->ValidMode        = NVValidMode;
420
421     return TRUE;
422 }
423
424 /* This returns architecture in hexdecimal, so NV40 is 0x40 */
425 static int NVGetArchitecture (volatile CARD32 *regs)
426 {
427         int architecture = 0;
428
429         /* We're dealing with >=NV10 */
430         if ((regs[0] & 0x0f000000) > 0 ) {
431                 /* Bit 27-20 contain the architecture in hex */
432                 architecture = (regs[0] & 0xff00000) >> 20;
433         /* NV04 or NV05 */
434         } else if ((regs[0] & 0xff00fff0) == 0x20004000) {
435                 architecture = 0x04;
436         }
437
438         return architecture;
439 }
440
441 /* Reading the pci_id from the card registers is the most reliable way */
442 static CARD32 NVGetPCIID (volatile CARD32 *regs)
443 {
444         CARD32 pci_id;
445
446         int architecture = NVGetArchitecture(regs);
447
448         /* Dealing with an unknown or unsupported card */
449         if (architecture == 0) {
450                 return 0;
451         }
452
453         if (architecture >= 0x40)
454                 pci_id = regs[0x88000/4];
455         else
456                 pci_id = regs[0x1800/4];
457
458         /* A pci-id can be inverted, we must correct this */
459         if ((pci_id & 0xffff) == PCI_VENDOR_NVIDIA) {
460                 pci_id = (PCI_VENDOR_NVIDIA << 16) | (pci_id >> 16);
461         } else if ((pci_id & 0xffff) == PCI_VENDOR_NVIDIA_SGS) {
462                 pci_id = (PCI_VENDOR_NVIDIA_SGS << 16) | (pci_id >> 16);
463         /* Checking endian issues */
464         } else {
465                 /* PCI_VENDOR_NVIDIA = 0x10DE */
466                 if ((pci_id & (0xffff << 16)) == (0xDE10 << 16)) { /* wrong endian */
467                         pci_id = (PCI_VENDOR_NVIDIA << 16) | ((pci_id << 8) & 0x0000ff00) |
468                                 ((pci_id >> 8) & 0x000000ff);
469                 /* PCI_VENDOR_NVIDIA_SGS = 0x12D2 */
470                 } else if ((pci_id & (0xffff << 16)) == (0xD212 << 16)) { /* wrong endian */
471                         pci_id = (PCI_VENDOR_NVIDIA_SGS << 16) | ((pci_id << 8) & 0x0000ff00) |
472                                 ((pci_id >> 8) & 0x000000ff);
473                 }
474         }
475
476         return pci_id;
477 }
478
479 #ifdef XSERVER_LIBPCIACCESS
480
481 static Bool NVPciProbe (        DriverPtr               drv,
482                                 int                     entity_num,
483                                 struct pci_device       *dev,
484                                 intptr_t                match_data      )
485 {
486         ScrnInfoPtr pScrn = NULL;
487
488         volatile CARD32 *regs = NULL;
489
490         /* Temporary mapping to discover the architecture */
491         pci_device_map_range(dev, PCI_DEV_MEM_BASE(dev, 0), 0x90000, 0, &regs);
492
493         char architecture = NVGetArchitecture(regs);
494
495         CARD32 pci_id = NVGetPCIID(regs);
496
497         pci_device_unmap_range(dev, regs, 0x90000);
498
499         /* Currently NV04 up to NV83 is supported */
500         /* For safety the fictional NV8F is used */
501         if (architecture >= 0x04 && architecture <= 0x8F) {
502
503                 /* At this stage the pci_id should be ok, so we generate this to avoid list duplication */
504                 /* AGP bridge chips need their bridge chip id to be detected */
505                 const PciChipsets NVChipsets[] = {
506                         { pci_id, PCI_DEV_PCI_ID(dev), RES_SHARED_VGA },
507                         { -1, -1, RES_UNDEFINED }
508                 };
509
510                 pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NVChipsets, 
511                                                 NULL, NULL, NULL, NULL, NULL);
512
513                 if (pScrn != NULL) {
514                         pScrn->driverVersion    = NV_VERSION;
515                         pScrn->driverName       = NV_DRIVER_NAME;
516                         pScrn->name             = NV_NAME;
517
518                         pScrn->Probe            = NULL;
519                         pScrn->PreInit          = NVPreInit;
520                         pScrn->ScreenInit       = NVScreenInit;
521                         pScrn->SwitchMode       = NVSwitchMode;
522                         pScrn->AdjustFrame      = NVAdjustFrame;
523                         pScrn->EnterVT          = NVEnterVT;
524                         pScrn->LeaveVT          = NVLeaveVT;
525                         pScrn->FreeScreen       = NVFreeScreen;
526                         pScrn->ValidMode        = NVValidMode;
527
528                         return TRUE;
529                 }
530         }
531
532         return FALSE;
533 }
534
535 #endif /* XSERVER_LIBPCIACCESS */
536
537 #define MAX_CHIPS MAXSCREENS
538
539 #ifndef XSERVER_LIBPCIACCESS
540 /* Mandatory */
541 static Bool
542 NVProbe(DriverPtr drv, int flags)
543 {
544         int i;
545         GDevPtr *devSections;
546         int *usedChips;
547         SymTabRec NVChipsets[MAX_CHIPS + 1];
548         PciChipsets NVPciChipsets[MAX_CHIPS + 1];
549         pciVideoPtr *ppPci;
550         int numDevSections;
551         int numUsed;
552         Bool foundScreen = FALSE;
553
554         if ((numDevSections = xf86MatchDevice(NV_DRIVER_NAME, &devSections)) <= 0) 
555                 return FALSE;  /* no matching device section */
556
557         if (!(ppPci = xf86GetPciVideoInfo())) 
558                 return FALSE;  /* no PCI cards found */
559
560         numUsed = 0;
561
562         /* Create the NVChipsets and NVPciChipsets from found devices */
563         while (*ppPci && (numUsed < MAX_CHIPS)) {
564                 if (((*ppPci)->vendor == PCI_VENDOR_NVIDIA_SGS) || 
565                         ((*ppPci)->vendor == PCI_VENDOR_NVIDIA)) 
566                 {
567                         volatile CARD32 *regs;
568                         CARD32 pcicmd;
569
570                         PCI_DEV_READ_LONG(*ppPci, PCI_CMD_STAT_REG, &pcicmd);
571                         /* Enable reading memory? */
572                         PCI_DEV_WRITE_LONG(*ppPci, PCI_CMD_STAT_REG, pcicmd | PCI_CMD_MEM_ENABLE);
573
574                         regs = xf86MapPciMem(-1, VIDMEM_MMIO, PCI_DEV_TAG(*ppPci), PCI_DEV_MEM_BASE(*ppPci, 0), 0x90000);
575                         int pciid = NVGetPCIID(regs);
576
577                         int architecture = NVGetArchitecture(regs);
578                         char name[25];
579                         sprintf(name, "NVIDIA NV%02X", architecture);
580                         /* NV04 upto NV83 is supported, NV8F is fictive limit */
581                         if (architecture >= 0x04 && architecture <= 0x8F) {
582                                 NVChipsets[numUsed].token = pciid;
583                                 NVChipsets[numUsed].name = name;
584                                 NVPciChipsets[numUsed].numChipset = pciid;
585                                 /* AGP bridge chips need their bridge chip id to be detected */
586                                 NVPciChipsets[numUsed].PCIid = PCI_DEV_PCI_ID(*ppPci);
587                                 NVPciChipsets[numUsed].resList = RES_SHARED_VGA;
588                                 numUsed++;
589                         }
590                         xf86UnMapVidMem(-1, (pointer)regs, 0x90000);
591
592                         /* Reset previous state */
593                         PCI_DEV_WRITE_LONG(*ppPci, PCI_CMD_STAT_REG, pcicmd);
594                 }
595                 ppPci++;
596         }
597
598         /* terminate the list */
599         NVChipsets[numUsed].token = -1;
600         NVChipsets[numUsed].name = NULL; 
601         NVPciChipsets[numUsed].numChipset = -1;
602         NVPciChipsets[numUsed].PCIid = -1;
603         NVPciChipsets[numUsed].resList = RES_UNDEFINED;
604
605         numUsed = xf86MatchPciInstances(NV_NAME, 0, NVChipsets, NVPciChipsets,
606                                         devSections, numDevSections, drv,
607                                         &usedChips);
608
609         if (numUsed <= 0) {
610                 return FALSE;
611         }
612
613         if (flags & PROBE_DETECT) {
614                 foundScreen = TRUE;
615         } else {
616                 for (i = 0; i < numUsed; i++) {
617                         pciVideoPtr pPci;
618
619                         pPci = xf86GetPciInfoForEntity(usedChips[i]);
620                         if (NVGetScrnInfoRec(NVPciChipsets, usedChips[i])) {
621                                 foundScreen = TRUE;
622                         }
623                 }
624         }
625
626         xfree(devSections);
627         xfree(usedChips);
628
629         return foundScreen;
630 }
631 #endif /* XSERVER_LIBPCIACCESS */
632
633 /*
634  * This function is needed by the XF86VideMode extension which is used by
635  * the current pre-randr clients. The API covers only one screen, but
636  * implementing the latest modesetting framework like done in the Intel
637  * driver is more than a few lines of patch, the randr-1.2 branch in its
638  * current form cannot the mode switching in a perfect way right now.
639  *
640  * As there are effors to bring modesetting into the kernel, controlled
641  * thru the drm module, of which nouveu currently requires its own version,
642  * one could even try to go one step further and try to bring the nouveau
643  * modesetting into the nouveau kernel module.c (as a first step which does
644  * not require a kernel patch), which would increase the chances that the
645  * text console is properly restored after X dies as the kernel can simply
646  * restore the text console when the process which has changed modes thru
647  * /dev/drm has been disconnected from the device.
648  *
649  * The current implementation simply tries to set each crtc to the mode
650  * for which the application asks for, hoping that one of them gives a
651  * usable monitor display (no error handling implemented), and sets
652  * the viewport of each crtc to (0,0), which means essentially clone
653  * mode with all monitors which managed to switch to the mode showing
654  * top left area of the framebuffer memory if the application's window
655  * is there. This is essentially what the Intel driver did in earlyer
656  * versions. To restore a LeftOf/RightOf layout, you two randr calls
657  * seem to be neccessary, one which sets the reversed layout, followed
658  * by one which sets the desired layout:
659  *
660  * xrandr --output Digital-1 --left-of Digital-0
661  * xrandr --output Digital-0 --left-of Digital-1
662  *
663  * FIXME: This could be fixed by getting the current viewports for the
664  * CRTCs and use these during mode settings, or (preferably) by getting
665  * the current screen layout and adapting the new viewports so that
666  * a new, continuos screen layout with the same monitor arrangement,
667  * but in the new mode is set up.
668  */
669 Bool
670 NVSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
671 {
672     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
673     NVPtr pNv = NVPTR(pScrn);
674     Bool ret = TRUE;
675
676 #ifdef ENABLE_RANDR12
677     if (pNv->randr12_enable) {
678         NVFBLayout *pLayout = &pNv->CurrentLayout;
679
680         if (pLayout->mode != mode) {
681                 /* This needs to be fixed with error handling */
682                 NVSetMode(pScrn, mode);
683                 pLayout->mode = mode;
684         }
685
686         pLayout->mode = mode;
687         return ret;
688     }
689 #endif
690
691         return NVModeInit(xf86Screens[scrnIndex], mode);
692 }
693
694 /*
695  * This function is used to initialize the Start Address - the first
696  * displayed location in the video memory.
697  */
698 /* Usually mandatory */
699 void 
700 NVAdjustFrame(int scrnIndex, int x, int y, int flags)
701 {
702     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
703     int startAddr;
704     NVPtr pNv = NVPTR(pScrn);
705     NVFBLayout *pLayout = &pNv->CurrentLayout;
706
707 #ifdef ENABLE_RANDR12
708     if (pNv->randr12_enable) {
709         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
710         int startAddr;
711         xf86CrtcPtr crtc = config->output[config->compat_output]->crtc;
712         
713         if (crtc && crtc->enabled) {
714             NVCrtcSetBase(crtc, x, y);
715         }
716     } else
717 #endif
718     {
719         startAddr = (((y*pLayout->displayWidth)+x)*(pLayout->bitsPerPixel/8));
720         startAddr += pNv->FB->offset;
721         NVSetStartAddress(pNv, startAddr);
722     }
723 }
724
725 #ifdef ENABLE_RANDR12
726 void
727 NVResetCrtcConfig(ScrnInfoPtr pScrn, int set)
728 {
729         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
730         NVPtr pNv = NVPTR(pScrn);
731         int i;
732         CARD32 val = 0;
733
734         for (i = 0; i < config->num_crtc; i++) {
735                 xf86CrtcPtr crtc = config->crtc[i];
736                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
737
738                 if (set) {
739                         NVCrtcRegPtr regp;
740
741                         regp = &pNv->ModeReg.crtc_reg[nv_crtc->head];
742                         val = regp->head;
743                 }
744
745                 nvWriteCRTC(pNv, nv_crtc->head, NV_CRTC_FSEL, val);
746         }
747 }
748 #endif
749
750 static Bool
751 NV50AcquireDisplay(ScrnInfoPtr pScrn)
752 {
753 #ifdef ENABLE_RANDR12
754         if (!NV50DispInit(pScrn))
755                 return FALSE;
756         if (!NV50CursorAcquire(pScrn))
757                 return FALSE;
758         xf86SetDesiredModes(pScrn);
759
760         return TRUE;
761 #else
762         return FALSE;
763 #endif
764 }
765
766 static Bool
767 NV50ReleaseDisplay(ScrnInfoPtr pScrn)
768 {
769 #ifdef ENABLE_RANDR12
770         NV50CursorRelease(pScrn);
771         NV50DispShutdown(pScrn);
772 #endif
773         return TRUE;
774 }
775
776 /*
777  * This is called when VT switching back to the X server.  Its job is
778  * to reinitialise the video mode.
779  *
780  * We may wish to unmap video/MMIO memory too.
781  */
782
783 /* Mandatory */
784 static Bool
785 NVEnterVT(int scrnIndex, int flags)
786 {
787     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
788     NVPtr pNv = NVPTR(pScrn);
789     
790 #ifdef ENABLE_RANDR12
791     if (pNv->randr12_enable) { 
792         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
793         int i;
794         pScrn->vtSema = TRUE;
795
796         if (pNv->Architecture == NV_ARCH_50) {
797                 if (!NV50AcquireDisplay(pScrn))
798                         return FALSE;
799                 return TRUE;
800         }
801
802         /* Save the current state */
803         if (pNv->SaveGeneration != serverGeneration) {
804                 pNv->SaveGeneration = serverGeneration;
805                 NVSave(pScrn);
806         }
807
808         for (i = 0; i < xf86_config->num_crtc; i++) {
809                 NVCrtcLockUnlock(xf86_config->crtc[i], 0);
810         }
811
812         NVResetCrtcConfig(pScrn, 0);
813         if (!xf86SetDesiredModes(pScrn))
814                 return FALSE;
815         NVResetCrtcConfig(pScrn, 1);
816
817     } else
818 #endif
819     {
820         if (!NVModeInit(pScrn, pScrn->currentMode))
821             return FALSE;
822
823     }
824     NVAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
825     if(pNv->overlayAdaptor)
826         NVResetVideo(pScrn);
827     return TRUE;
828     
829 }
830
831 /*
832  * This is called when VT switching away from the X server.  Its job is
833  * to restore the previous (text) mode.
834  *
835  * We may wish to remap video/MMIO memory too.
836  */
837
838 /* Mandatory */
839 static void
840 NVLeaveVT(int scrnIndex, int flags)
841 {
842     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
843     NVPtr pNv = NVPTR(pScrn);
844
845     if (pNv->Architecture == NV_ARCH_50) {
846         NV50ReleaseDisplay(pScrn);
847         return;
848     }
849     NVSync(pScrn);
850     NVRestore(pScrn);
851     if (!pNv->randr12_enable)
852         NVLockUnlock(pNv, 1);
853 }
854
855
856
857 static void 
858 NVBlockHandler (
859     int i, 
860     pointer blockData, 
861     pointer pTimeout,
862     pointer pReadmask
863 )
864 {
865     ScreenPtr     pScreen = screenInfo.screens[i];
866     ScrnInfoPtr   pScrnInfo = xf86Screens[i];
867     NVPtr         pNv = NVPTR(pScrnInfo);
868
869     if (pNv->DMAKickoffCallback)
870         (*pNv->DMAKickoffCallback)(pNv);
871     
872     pScreen->BlockHandler = pNv->BlockHandler;
873     (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
874     pScreen->BlockHandler = NVBlockHandler;
875
876     if (pNv->VideoTimerCallback) 
877         (*pNv->VideoTimerCallback)(pScrnInfo, currentTime.milliseconds);
878
879 }
880
881
882 /*
883  * This is called at the end of each server generation.  It restores the
884  * original (text) mode.  It should also unmap the video memory, and free
885  * any per-generation data allocated by the driver.  It should finish
886  * by unwrapping and calling the saved CloseScreen function.
887  */
888
889 /* Mandatory */
890 static Bool
891 NVCloseScreen(int scrnIndex, ScreenPtr pScreen)
892 {
893     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
894     NVPtr pNv = NVPTR(pScrn);
895
896     if (pScrn->vtSema) {
897         pScrn->vtSema = FALSE;
898         if (pNv->Architecture == NV_ARCH_50) {
899             NV50ReleaseDisplay(pScrn);
900         } else {
901             NVSync(pScrn);
902             NVRestore(pScrn);
903             if (!pNv->randr12_enable)
904                 NVLockUnlock(pNv, 1);
905         }
906     }
907
908     NVUnmapMem(pScrn);
909     vgaHWUnmapMem(pScrn);
910     if (pNv->CursorInfoRec)
911         xf86DestroyCursorInfoRec(pNv->CursorInfoRec);
912     if (pNv->ShadowPtr)
913         xfree(pNv->ShadowPtr);
914     if (pNv->overlayAdaptor)
915         xfree(pNv->overlayAdaptor);
916     if (pNv->blitAdaptor)
917         xfree(pNv->blitAdaptor);
918
919     pScrn->vtSema = FALSE;
920     pScreen->CloseScreen = pNv->CloseScreen;
921     pScreen->BlockHandler = pNv->BlockHandler;
922     return (*pScreen->CloseScreen)(scrnIndex, pScreen);
923 }
924
925 /* Free up any persistent data structures */
926
927 /* Optional */
928 static void
929 NVFreeScreen(int scrnIndex, int flags)
930 {
931     /*
932      * This only gets called when a screen is being deleted.  It does not
933      * get called routinely at the end of a server generation.
934      */
935     if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
936         vgaHWFreeHWRec(xf86Screens[scrnIndex]);
937     NVFreeRec(xf86Screens[scrnIndex]);
938 }
939
940
941 /* Checks if a mode is suitable for the selected chipset. */
942
943 /* Optional */
944 static ModeStatus
945 NVValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
946 {
947     NVPtr pNv = NVPTR(xf86Screens[scrnIndex]);
948
949     if(pNv->fpWidth && pNv->fpHeight)
950       if((pNv->fpWidth < mode->HDisplay) || (pNv->fpHeight < mode->VDisplay))
951         return (MODE_PANEL);
952
953     return (MODE_OK);
954 }
955
956 static void
957 nvProbeDDC(ScrnInfoPtr pScrn, int index)
958 {
959     vbeInfoPtr pVbe;
960
961     if (xf86LoadSubModule(pScrn, "vbe")) {
962         pVbe = VBEInit(NULL,index);
963         ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
964         vbeFree(pVbe);
965     }
966 }
967
968
969 Bool NVI2CInit(ScrnInfoPtr pScrn)
970 {
971         NVPtr pNv = NVPTR(pScrn);
972         char *mod = "i2c";
973
974         if (xf86LoadSubModule(pScrn, mod)) {
975                 xf86LoaderReqSymLists(i2cSymbols,NULL);
976
977                 mod = "ddc";
978                 if(xf86LoadSubModule(pScrn, mod)) {
979                         xf86LoaderReqSymLists(ddcSymbols, NULL);
980                         /* randr-1.2 clients have their DDC's initialized elsewhere */
981                         if (pNv->randr12_enable) {
982                                 return TRUE;
983                         } else {
984                                 return NVDACi2cInit(pScrn);
985                         }
986                 } 
987         }
988
989         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
990                 "Couldn't load %s module.  DDC probing can't be done\n", mod);
991
992         return FALSE;
993 }
994
995 static Bool NVPreInitDRI(ScrnInfoPtr pScrn)
996 {
997         NVPtr pNv = NVPTR(pScrn);
998
999         if (!NVDRIGetVersion(pScrn))
1000                 return FALSE;
1001
1002         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1003                 "[dri] Found DRI library version %d.%d.%d and kernel"
1004                 " module version %d.%d.%d\n",
1005                 pNv->pLibDRMVersion->version_major,
1006                 pNv->pLibDRMVersion->version_minor,
1007                 pNv->pLibDRMVersion->version_patchlevel,
1008                 pNv->pKernelDRMVersion->version_major,
1009                 pNv->pKernelDRMVersion->version_minor,
1010                 pNv->pKernelDRMVersion->version_patchlevel);
1011
1012         return TRUE;
1013 }
1014
1015 #ifdef ENABLE_RANDR12
1016 static Bool
1017 nv_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
1018 {
1019         scrn->virtualX = width;
1020         scrn->virtualY = height;
1021         return TRUE;
1022 }
1023
1024 static const xf86CrtcConfigFuncsRec nv_xf86crtc_config_funcs = {
1025         nv_xf86crtc_resize
1026 };
1027 #endif
1028
1029 #define NVPreInitFail(fmt, args...) do {                                    \
1030         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%d: "fmt, __LINE__, ##args); \
1031         if (pNv->pInt10)                                                    \
1032                 xf86FreeInt10(pNv->pInt10);                                 \
1033         NVFreeRec(pScrn);                                                   \
1034         return FALSE;                                                       \
1035 } while(0)
1036
1037 /* Mandatory */
1038 Bool
1039 NVPreInit(ScrnInfoPtr pScrn, int flags)
1040 {
1041 #ifdef ENABLE_RANDR12
1042     xf86CrtcConfigPtr xf86_config;
1043 #endif
1044     NVPtr pNv;
1045     MessageType from;
1046     int i, max_width, max_height;
1047     ClockRangePtr clockRanges;
1048     const char *s;
1049     int config_mon_rates = FALSE;
1050     int num_crtc;
1051
1052     if (flags & PROBE_DETECT) {
1053         EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1054
1055         if (!pEnt)
1056             return FALSE;
1057
1058         i = pEnt->index;
1059         xfree(pEnt);
1060
1061         nvProbeDDC(pScrn, i);
1062         return TRUE;
1063     }
1064
1065     /*
1066      * Note: This function is only called once at server startup, and
1067      * not at the start of each server generation.  This means that
1068      * only things that are persistent across server generations can
1069      * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
1070      * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()  
1071      * are too, and should be used for data that must persist across
1072      * server generations.
1073      *
1074      * Per-generation data should be allocated with
1075      * AllocateScreenPrivateIndex() from the ScreenInit() function.
1076      */
1077
1078     /* Check the number of entities, and fail if it isn't one. */
1079     if (pScrn->numEntities != 1)
1080         return FALSE;
1081
1082     /* Allocate the NVRec driverPrivate */
1083     if (!NVGetRec(pScrn)) {
1084         return FALSE;
1085     }
1086     pNv = NVPTR(pScrn);
1087
1088     /* Get the entity, and make sure it is PCI. */
1089     pNv->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1090     if (pNv->pEnt->location.type != BUS_PCI)
1091         return FALSE;
1092  
1093     /* Find the PCI info for this screen */
1094     pNv->PciInfo = xf86GetPciInfoForEntity(pNv->pEnt->index);
1095 #ifndef XSERVER_LIBPCIACCESS
1096     pNv->PciTag = pciTag(pNv->PciInfo->bus, pNv->PciInfo->device,
1097                           pNv->PciInfo->func);
1098 #endif /* XSERVER_LIBPCIACCESS */
1099
1100     pNv->Primary = xf86IsPrimaryPci(pNv->PciInfo);
1101
1102     /* Initialize the card through int10 interface if needed */
1103     if (xf86LoadSubModule(pScrn, "int10")) {
1104         xf86LoaderReqSymLists(int10Symbols, NULL);
1105 #if !defined(__alpha__) && !defined(__powerpc__)
1106         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
1107         pNv->pInt10 = xf86InitInt10(pNv->pEnt->index);
1108 #endif
1109     }
1110    
1111     xf86SetOperatingState(resVgaIo, pNv->pEnt->index, ResUnusedOpr);
1112     xf86SetOperatingState(resVgaMem, pNv->pEnt->index, ResDisableOpr);
1113
1114     /* Set pScrn->monitor */
1115     pScrn->monitor = pScrn->confScreen->monitor;
1116
1117         volatile CARD32 *regs = NULL;
1118 #ifdef XSERVER_LIBPCIACCESS
1119         pci_device_map_range(pNv->PciInfo, PCI_DEV_MEM_BASE(pNv->PciInfo, 0), 0x90000, 0, &regs);
1120         pNv->Chipset = NVGetPCIID(regs) & 0xffff;
1121         pNv->NVArch = NVGetArchitecture(regs);
1122         pci_device_unmap_range(pNv->PciInfo, regs, 0x90000);
1123 #else
1124         CARD32 pcicmd;
1125         PCI_DEV_READ_LONG(pNv->PciInfo, PCI_CMD_STAT_REG, &pcicmd);
1126         /* Enable reading memory? */
1127         PCI_DEV_WRITE_LONG(pNv->PciInfo, PCI_CMD_STAT_REG, pcicmd | PCI_CMD_MEM_ENABLE);
1128         regs = xf86MapPciMem(-1, VIDMEM_MMIO, pNv->PciTag, PCI_DEV_MEM_BASE(pNv->PciInfo, 0), 0x90000);
1129         pNv->Chipset = NVGetPCIID(regs) & 0xffff;
1130         pNv->NVArch = NVGetArchitecture(regs);
1131         xf86UnMapVidMem(-1, (pointer)regs, 0x90000);
1132         /* Reset previous state */
1133         PCI_DEV_WRITE_LONG(pNv->PciInfo, PCI_CMD_STAT_REG, pcicmd);
1134 #endif /* XSERVER_LIBPCIACCESS */
1135
1136         pScrn->chipset = malloc(sizeof(char) * 25);
1137         sprintf(pScrn->chipset, "NVIDIA NV%02X", pNv->NVArch);
1138
1139         if(!pScrn->chipset) {
1140                 pScrn->chipset = "Unknown NVIDIA";
1141         }
1142
1143         /*
1144         * This shouldn't happen because such problems should be caught in
1145         * NVProbe(), but check it just in case.
1146         */
1147         if (pScrn->chipset == NULL)
1148                 NVPreInitFail("ChipID 0x%04X is not recognised\n", pNv->Chipset);
1149
1150         if (pNv->NVArch < 0x04)
1151                 NVPreInitFail("Chipset \"%s\" is not recognised\n", pScrn->chipset);
1152
1153         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chipset: \"%s\"\n", pScrn->chipset);
1154
1155         /* The highest architecture currently supported is NV5x */
1156         if (pNv->NVArch >= 0x50) {
1157                 pNv->Architecture =  NV_ARCH_50;
1158         } else if (pNv->NVArch >= 0x40) {
1159                 pNv->Architecture =  NV_ARCH_40;
1160         } else if (pNv->NVArch >= 0x30) {
1161                 pNv->Architecture = NV_ARCH_30;
1162         } else if (pNv->NVArch >= 0x20) {
1163                 pNv->Architecture = NV_ARCH_20;
1164         } else if (pNv->NVArch >= 0x10) {
1165                 pNv->Architecture = NV_ARCH_10;
1166         } else if (pNv->NVArch >= 0x04) {
1167                 pNv->Architecture = NV_ARCH_04;
1168         /*  The lowest architecture currently supported is NV04 */
1169         } else {
1170                 return FALSE;
1171         }
1172
1173     /*
1174      * The first thing we should figure out is the depth, bpp, etc.
1175      */
1176
1177     if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
1178         NVPreInitFail("\n");
1179     } else {
1180         /* Check that the returned depth is one we support */
1181         switch (pScrn->depth) {
1182             case 8:
1183             case 15:
1184             case 16:
1185             case 24:
1186                 /* OK */
1187                 break;
1188             default:
1189                 NVPreInitFail("Given depth (%d) is not supported by this driver\n",
1190                               pScrn->depth);
1191         }
1192     }
1193     xf86PrintDepthBpp(pScrn);
1194
1195     /* Get the depth24 pixmap format */
1196     if (pScrn->depth == 24 && pix24bpp == 0)
1197         pix24bpp = xf86GetBppFromDepth(pScrn, 24);
1198
1199     /*
1200      * This must happen after pScrn->display has been set because
1201      * xf86SetWeight references it.
1202      */
1203     if (pScrn->depth > 8) {
1204         /* The defaults are OK for us */
1205         rgb zeros = {0, 0, 0};
1206
1207         if (!xf86SetWeight(pScrn, zeros, zeros)) {
1208             NVPreInitFail("\n");
1209         }
1210     }
1211
1212     if (!xf86SetDefaultVisual(pScrn, -1)) {
1213         NVPreInitFail("\n");
1214     } else {
1215         /* We don't currently support DirectColor at > 8bpp */
1216         if (pScrn->depth > 8 && (pScrn->defaultVisual != TrueColor)) {
1217             NVPreInitFail("Given default visual"
1218                        " (%s) is not supported at depth %d\n",
1219                        xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
1220             
1221         }
1222     }
1223
1224     /* The vgahw module should be loaded here when needed */
1225     if (!xf86LoadSubModule(pScrn, "vgahw")) {
1226         NVPreInitFail("\n");
1227     }
1228     
1229     xf86LoaderReqSymLists(vgahwSymbols, NULL);
1230
1231     /*
1232      * Allocate a vgaHWRec
1233      */
1234     if (!vgaHWGetHWRec(pScrn)) {
1235         NVPreInitFail("\n");
1236     }
1237     
1238     /* We use a programmable clock */
1239     pScrn->progClock = TRUE;
1240
1241     /* Collect all of the relevant option flags (fill in pScrn->options) */
1242     xf86CollectOptions(pScrn, NULL);
1243
1244     /* Process the options */
1245     if (!(pNv->Options = xalloc(sizeof(NVOptions))))
1246         return FALSE;
1247     memcpy(pNv->Options, NVOptions, sizeof(NVOptions));
1248     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options);
1249
1250     /* Set the bits per RGB for 8bpp mode */
1251     if (pScrn->depth == 8)
1252         pScrn->rgbBits = 8;
1253
1254     from = X_DEFAULT;
1255
1256     if (pNv->Architecture == NV_ARCH_50) {
1257             pNv->randr12_enable = TRUE;
1258     } else {
1259         pNv->randr12_enable = FALSE;
1260         if (xf86ReturnOptValBool(pNv->Options, OPTION_RANDR12, FALSE)) {
1261             pNv->randr12_enable = TRUE;
1262         }
1263     }
1264     xf86DrvMsg(pScrn->scrnIndex, from, "Randr1.2 support %sabled\n", pNv->randr12_enable ? "en" : "dis");
1265
1266     pNv->HWCursor = TRUE;
1267     /*
1268      * The preferred method is to use the "hw cursor" option as a tri-state
1269      * option, with the default set above.
1270      */
1271     if (xf86GetOptValBool(pNv->Options, OPTION_HW_CURSOR, &pNv->HWCursor)) {
1272         from = X_CONFIG;
1273     }
1274     /* For compatibility, accept this too (as an override) */
1275     if (xf86ReturnOptValBool(pNv->Options, OPTION_SW_CURSOR, FALSE)) {
1276         from = X_CONFIG;
1277         pNv->HWCursor = FALSE;
1278     }
1279     xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
1280                 pNv->HWCursor ? "HW" : "SW");
1281
1282     pNv->FpScale = TRUE;
1283     if (xf86GetOptValBool(pNv->Options, OPTION_FP_SCALE, &pNv->FpScale)) {
1284         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Flat panel scaling %s\n",
1285                    pNv->FpScale ? "on" : "off");
1286     }
1287     if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) {
1288         pNv->NoAccel = TRUE;
1289         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
1290     }
1291     if (xf86ReturnOptValBool(pNv->Options, OPTION_SHADOW_FB, FALSE)) {
1292         pNv->ShadowFB = TRUE;
1293         pNv->NoAccel = TRUE;
1294         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 
1295                 "Using \"Shadow Framebuffer\" - acceleration disabled\n");
1296     }
1297     
1298     pNv->Rotate = 0;
1299     pNv->RandRRotation = FALSE;
1300     if ((s = xf86GetOptValString(pNv->Options, OPTION_ROTATE))) {
1301       if(!xf86NameCmp(s, "CW")) {
1302         pNv->ShadowFB = TRUE;
1303         pNv->NoAccel = TRUE;
1304         pNv->HWCursor = FALSE;
1305         pNv->Rotate = 1;
1306         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 
1307                 "Rotating screen clockwise - acceleration disabled\n");
1308       } else
1309       if(!xf86NameCmp(s, "CCW")) {
1310         pNv->ShadowFB = TRUE;
1311         pNv->NoAccel = TRUE;
1312         pNv->HWCursor = FALSE;
1313         pNv->Rotate = -1;
1314         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 
1315                 "Rotating screen counter clockwise - acceleration disabled\n");
1316       } else
1317       if(!xf86NameCmp(s, "RandR")) {
1318 #ifdef RANDR
1319         pNv->ShadowFB = TRUE;
1320         pNv->NoAccel = TRUE;
1321         pNv->HWCursor = FALSE;
1322         pNv->RandRRotation = TRUE;
1323         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1324                 "Using RandR rotation - acceleration disabled\n");
1325 #else
1326         xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1327                 "This driver was not compiled with support for the Resize and "
1328                 "Rotate extension.  Cannot honor 'Option \"Rotate\" "
1329                 "\"RandR\"'.\n");
1330 #endif
1331       } else {
1332         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 
1333                 "\"%s\" is not a valid value for Option \"Rotate\"\n", s);
1334         xf86DrvMsg(pScrn->scrnIndex, X_INFO, 
1335                 "Valid options are \"CW\", \"CCW\", and \"RandR\"\n");
1336       }
1337     }
1338
1339     if(xf86GetOptValInteger(pNv->Options, OPTION_VIDEO_KEY, &(pNv->videoKey))) {
1340         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1341                                 pNv->videoKey);
1342     } else {
1343         pNv->videoKey =  (1 << pScrn->offset.red) | 
1344                           (1 << pScrn->offset.green) |
1345         (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 
1346     }
1347
1348     if (xf86GetOptValBool(pNv->Options, OPTION_FLAT_PANEL, &(pNv->FlatPanel))) {
1349         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "forcing %s usage\n",
1350                    pNv->FlatPanel ? "DFP" : "CRTC");
1351     } else {
1352         pNv->FlatPanel = -1;   /* autodetect later */
1353     }
1354
1355     pNv->FPDither = FALSE;
1356     if (xf86GetOptValBool(pNv->Options, OPTION_FP_DITHER, &(pNv->FPDither))) 
1357         xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "enabling flat panel dither\n");
1358
1359     //if (xf86GetOptValInteger(pNv->Options, OPTION_CRTC_NUMBER,
1360    //                          &pNv->CRTCnumber)) 
1361     //{
1362         //pNv->crtc_active[0] = FALSE;
1363         //pNv->crtc_active[1] = FALSE;
1364     //}
1365
1366
1367     if (xf86GetOptValInteger(pNv->Options, OPTION_FP_TWEAK, 
1368                              &pNv->PanelTweak))
1369     {
1370         pNv->usePanelTweak = TRUE;
1371     } else {
1372         pNv->usePanelTweak = FALSE;
1373     }
1374     
1375     if (pNv->pEnt->device->MemBase != 0) {
1376         /* Require that the config file value matches one of the PCI values. */
1377         if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->MemBase)) {
1378             NVPreInitFail(
1379                 "MemBase 0x%08lX doesn't match any PCI base register.\n",
1380                 pNv->pEnt->device->MemBase);
1381         }
1382         pNv->VRAMPhysical = pNv->pEnt->device->MemBase;
1383         from = X_CONFIG;
1384     } else {
1385         if (PCI_DEV_MEM_BASE(pNv->PciInfo, 1) != 0) {
1386             pNv->VRAMPhysical = PCI_DEV_MEM_BASE(pNv->PciInfo, 1) & 0xff800000;
1387             from = X_PROBED;
1388         } else {
1389             NVPreInitFail("No valid FB address in PCI config space\n");
1390             return FALSE;
1391         }
1392     }
1393     xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
1394                (unsigned long)pNv->VRAMPhysical);
1395
1396     if (pNv->pEnt->device->IOBase != 0) {
1397         /* Require that the config file value matches one of the PCI values. */
1398         if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->IOBase)) {
1399             NVPreInitFail("IOBase 0x%08lX doesn't match any PCI base register.\n",
1400                           pNv->pEnt->device->IOBase);
1401         }
1402         pNv->IOAddress = pNv->pEnt->device->IOBase;
1403         from = X_CONFIG;
1404     } else {
1405         if (PCI_DEV_MEM_BASE(pNv->PciInfo, 0) != 0) {
1406             pNv->IOAddress = PCI_DEV_MEM_BASE(pNv->PciInfo, 0) & 0xffffc000;
1407             from = X_PROBED;
1408         } else {
1409             NVPreInitFail("No valid MMIO address in PCI config space\n");
1410         }
1411     }
1412     xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
1413                (unsigned long)pNv->IOAddress);
1414      
1415         if (xf86RegisterResources(pNv->pEnt->index, NULL, ResExclusive)) {
1416                 NVPreInitFail("xf86RegisterResources() found resource conflicts\n");
1417     }
1418
1419         pNv->alphaCursor = (pNv->NVArch >= 0x11);
1420
1421         //pNv->alphaCursor = FALSE;
1422
1423 #ifdef ENABLE_RANDR12
1424     if (pNv->randr12_enable) {
1425         /* Allocate an xf86CrtcConfig */
1426         xf86CrtcConfigInit(pScrn, &nv_xf86crtc_config_funcs);
1427         xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1428         
1429         max_width = 16384;
1430         xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, 2048);
1431     }
1432 #endif
1433
1434     if (NVPreInitDRI(pScrn) == FALSE) {
1435         NVPreInitFail("\n");
1436     }
1437
1438     if (!pNv->randr12_enable) {
1439         if ((pScrn->monitor->nHsync == 0) && 
1440             (pScrn->monitor->nVrefresh == 0))
1441             config_mon_rates = FALSE;
1442         else
1443             config_mon_rates = TRUE;
1444     }
1445
1446     NVCommonSetup(pScrn);
1447
1448 #ifdef ENABLE_RANDR12
1449     if (pNv->randr12_enable) {
1450         if (pNv->Architecture < NV_ARCH_50) {
1451             NVI2CInit(pScrn);
1452             
1453             num_crtc = pNv->twoHeads ? 2 : 1;
1454             for (i = 0; i < num_crtc; i++) {
1455                 nv_crtc_init(pScrn, i);
1456             }
1457             
1458             NvSetupOutputs(pScrn);
1459         } else {
1460             if (!NV50DispPreInit(pScrn))
1461                 NVPreInitFail("\n");
1462             if (!NV50CreateOutputs(pScrn))
1463                 NVPreInitFail("\n");
1464             NV50DispCreateCrtcs(pScrn);
1465         }
1466
1467         if (!xf86InitialConfiguration(pScrn, FALSE))
1468             NVPreInitFail("No valid modes.\n");
1469     }
1470 #endif
1471
1472     pScrn->videoRam = pNv->RamAmountKBytes;
1473     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kBytes\n",
1474                pScrn->videoRam);
1475         
1476     pNv->VRAMPhysicalSize = pScrn->videoRam * 1024;
1477
1478     /*
1479      * If the driver can do gamma correction, it should call xf86SetGamma()
1480      * here.
1481      */
1482
1483     {
1484         Gamma zeros = {0.0, 0.0, 0.0};
1485
1486         if (!xf86SetGamma(pScrn, zeros)) {
1487             NVPreInitFail("\n");
1488         }
1489     }
1490
1491     /*
1492      * Setup the ClockRanges, which describe what clock ranges are available,
1493      * and what sort of modes they can be used for.
1494      */
1495
1496     clockRanges = xnfcalloc(sizeof(ClockRange), 1);
1497     clockRanges->next = NULL;
1498     clockRanges->minClock = pNv->MinVClockFreqKHz;
1499     clockRanges->maxClock = pNv->MaxVClockFreqKHz;
1500     clockRanges->clockIndex = -1;               /* programmable */
1501     clockRanges->doubleScanAllowed = TRUE;
1502     if((pNv->Architecture == NV_ARCH_20) ||
1503          ((pNv->Architecture == NV_ARCH_10) && 
1504            ((pNv->Chipset & 0x0ff0) != CHIPSET_NV10) &&
1505            ((pNv->Chipset & 0x0ff0) != CHIPSET_NV15)))
1506     {
1507        /* HW is broken */
1508        clockRanges->interlaceAllowed = FALSE;
1509     } else {
1510        clockRanges->interlaceAllowed = TRUE;
1511     }
1512
1513     if(pNv->FlatPanel == 1) {
1514        clockRanges->interlaceAllowed = FALSE;
1515        clockRanges->doubleScanAllowed = FALSE;
1516     }
1517
1518     if(pNv->Architecture < NV_ARCH_10) {
1519        max_width = (pScrn->bitsPerPixel > 16) ? 2032 : 2048;
1520        max_height = 2048;
1521     } else {
1522        max_width = (pScrn->bitsPerPixel > 16) ? 4080 : 4096;
1523        max_height = 4096;
1524     }
1525
1526 #ifdef M_T_DRIVER
1527     /* If DFP, add a modeline corresponding to its panel size */
1528     if (pNv->FlatPanel && !pNv->Television && pNv->fpWidth && pNv->fpHeight) {
1529         DisplayModePtr Mode;
1530
1531         Mode = xnfcalloc(1, sizeof(DisplayModeRec));
1532         Mode = xf86CVTMode(pNv->fpWidth, pNv->fpHeight, 60.00, TRUE, FALSE);
1533         Mode->type = M_T_DRIVER;
1534         pScrn->monitor->Modes = xf86ModesAdd(pScrn->monitor->Modes, Mode);
1535
1536         if (!config_mon_rates) {
1537             if (!Mode->HSync)
1538                 Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
1539             if (!Mode->VRefresh)
1540                 Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
1541                     ((float) (Mode->HTotal * Mode->VTotal));
1542
1543             if (Mode->HSync < pScrn->monitor->hsync[0].lo)
1544                 pScrn->monitor->hsync[0].lo = Mode->HSync;
1545             if (Mode->HSync > pScrn->monitor->hsync[0].hi)
1546                 pScrn->monitor->hsync[0].hi = Mode->HSync;
1547             if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo)
1548                 pScrn->monitor->vrefresh[0].lo = Mode->VRefresh;
1549             if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi)
1550                 pScrn->monitor->vrefresh[0].hi = Mode->VRefresh;
1551
1552             pScrn->monitor->nHsync = 1;
1553             pScrn->monitor->nVrefresh = 1;
1554         }
1555     }
1556 #endif
1557
1558     if (pNv->randr12_enable) {
1559             pScrn->displayWidth = (pScrn->virtualX + 255) & ~255;
1560     } else { 
1561             /*
1562              * xf86ValidateModes will check that the mode HTotal and VTotal values
1563              * don't exceed the chipset's limit if pScrn->maxHValue and
1564              * pScrn->maxVValue are set.  Since our NVValidMode() already takes
1565              * care of this, we don't worry about setting them here.
1566              */
1567             i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
1568                                   pScrn->display->modes, clockRanges,
1569                                   NULL, 256, max_width,
1570                                   512, 128, max_height,
1571                                   pScrn->display->virtualX,
1572                                   pScrn->display->virtualY,
1573                                   pNv->VRAMPhysicalSize / 2,
1574                                   LOOKUP_BEST_REFRESH);
1575         
1576             if (i == -1) {
1577                 NVPreInitFail("\n");
1578             }
1579         
1580             /* Prune the modes marked as invalid */
1581             xf86PruneDriverModes(pScrn);
1582
1583             /*
1584              * Set the CRTC parameters for all of the modes based on the type
1585              * of mode, and the chipset's interlace requirements.
1586              *
1587              * Calling this is required if the mode->Crtc* values are used by the
1588              * driver and if the driver doesn't provide code to set them.  They
1589              * are not pre-initialised at all.
1590              */
1591             xf86SetCrtcForModes(pScrn, 0);
1592     }
1593
1594     if (pScrn->modes == NULL) {
1595         NVPreInitFail("No valid modes found\n");
1596     }
1597
1598     /* Set the current mode to the first in the list */
1599     pScrn->currentMode = pScrn->modes;
1600
1601     /* Print the list of modes being used */
1602     xf86PrintModes(pScrn);
1603
1604     /* Set display resolution */
1605     xf86SetDpi(pScrn, 0, 0);
1606
1607
1608     /*
1609      * XXX This should be taken into account in some way in the mode valdation
1610      * section.
1611      */
1612
1613     if (xf86LoadSubModule(pScrn, "fb") == NULL) {
1614         NVPreInitFail("\n");
1615     }
1616
1617     xf86LoaderReqSymLists(fbSymbols, NULL);
1618     
1619     /* Load EXA if needed */
1620     if (!pNv->NoAccel) {
1621         if (!xf86LoadSubModule(pScrn, "exa")) {
1622             NVPreInitFail("\n");
1623         }
1624         xf86LoaderReqSymLists(exaSymbols, NULL);
1625     }
1626
1627     /* Load ramdac if needed */
1628     if (pNv->HWCursor) {
1629         if (!xf86LoadSubModule(pScrn, "ramdac")) {
1630             NVPreInitFail("\n");
1631         }
1632         xf86LoaderReqSymLists(ramdacSymbols, NULL);
1633     }
1634
1635     /* Load shadowfb if needed */
1636     if (pNv->ShadowFB) {
1637         if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1638             NVPreInitFail("\n");
1639         }
1640         xf86LoaderReqSymLists(shadowSymbols, NULL);
1641     }
1642
1643     pNv->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
1644     pNv->CurrentLayout.depth = pScrn->depth;
1645     pNv->CurrentLayout.displayWidth = pScrn->displayWidth;
1646     pNv->CurrentLayout.weight.red = pScrn->weight.red;
1647     pNv->CurrentLayout.weight.green = pScrn->weight.green;
1648     pNv->CurrentLayout.weight.blue = pScrn->weight.blue;
1649     pNv->CurrentLayout.mode = pScrn->currentMode;
1650
1651     xf86FreeInt10(pNv->pInt10);
1652
1653     pNv->pInt10 = NULL;
1654     return TRUE;
1655 }
1656
1657
1658 /*
1659  * Map the framebuffer and MMIO memory.
1660  */
1661
1662 static Bool
1663 NVMapMem(ScrnInfoPtr pScrn)
1664 {
1665         NVPtr pNv = NVPTR(pScrn);
1666
1667         pNv->FB = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, pNv->VRAMPhysicalSize/2);
1668         if (!pNv->FB) {
1669                 ErrorF("Failed to allocate memory for framebuffer!\n");
1670                 return FALSE;
1671         }
1672         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1673                    "Allocated %dMiB VRAM for framebuffer + offscreen pixmaps\n",
1674                    (unsigned int)(pNv->FB->size >> 20));
1675
1676         /*XXX: have to get these after we've allocated something, otherwise
1677          *     they're uninitialised in the DRM!
1678          */
1679         pNv->VRAMSize     = NVDRMGetParam(pNv, NOUVEAU_GETPARAM_FB_SIZE);
1680         pNv->VRAMPhysical = NVDRMGetParam(pNv, NOUVEAU_GETPARAM_FB_PHYSICAL);
1681         pNv->AGPSize      = NVDRMGetParam(pNv, NOUVEAU_GETPARAM_AGP_SIZE);
1682         pNv->AGPPhysical  = NVDRMGetParam(pNv, NOUVEAU_GETPARAM_AGP_PHYSICAL);
1683         if ( ! pNv->AGPSize ) /*if no AGP*/
1684                 /*use PCI*/
1685                 pNv->SGPhysical  = NVDRMGetParam(pNv, NOUVEAU_GETPARAM_PCI_PHYSICAL);
1686
1687         int gart_scratch_size;
1688
1689         if (pNv->AGPSize) {
1690                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1691                            "AGPGART: %dMiB available\n",
1692                            (unsigned int)(pNv->AGPSize >> 20));
1693
1694                 if (pNv->AGPSize > (16*1024*1024))
1695                         gart_scratch_size = 16*1024*1024;
1696                 else
1697                         gart_scratch_size = pNv->AGPSize;
1698
1699                 }
1700         else {
1701
1702                 gart_scratch_size = (4 << 20) - (1 << 18) ;
1703                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1704                            "GART: PCI DMA - using %dKiB\n", gart_scratch_size >> 10);
1705                 
1706         }
1707
1708         /*The DRM allocates AGP memory, PCI as a fallback */
1709         pNv->GARTScratch = NVAllocateMemory(pNv, NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI_ACCEPTABLE,
1710                                                         gart_scratch_size);
1711         if (!pNv->GARTScratch) {
1712                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1713                            "Unable to allocate GART memory\n");
1714         } else {
1715                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1716                            "GART: mapped %dMiB at %p, offset is %d\n",
1717                            (unsigned int)(pNv->GARTScratch->size >> 20),
1718                            pNv->GARTScratch->map, pNv->GARTScratch->offset);
1719         }
1720
1721
1722         pNv->Cursor = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 64*1024);
1723         if (!pNv->Cursor) {
1724                 ErrorF("Failed to allocate memory for hardware cursor\n");
1725                 return FALSE;
1726         }
1727
1728         pNv->ScratchBuffer = NVAllocateMemory(pNv, NOUVEAU_MEM_FB,
1729                         pNv->Architecture <NV_ARCH_10 ? 8192 : 16384);
1730         if (!pNv->ScratchBuffer) {
1731                 ErrorF("Failed to allocate memory for scratch buffer\n");
1732                 return FALSE;
1733         }
1734
1735         if (pNv->Architecture >= NV_ARCH_50) {
1736                 pNv->CLUT = NVAllocateMemory(pNv, NOUVEAU_MEM_FB, 0x1000);
1737                 if (!pNv->CLUT) {
1738                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1739                                    "Failed to allocate memory for CLUT\n");
1740                         return FALSE;
1741                 }
1742         }
1743
1744         return TRUE;
1745 }
1746
1747 /*
1748  * Unmap the framebuffer and MMIO memory.
1749  */
1750
1751 static Bool
1752 NVUnmapMem(ScrnInfoPtr pScrn)
1753 {
1754         NVPtr pNv = NVPTR(pScrn);
1755
1756         NVFreeMemory(pNv, pNv->FB);
1757         NVFreeMemory(pNv, pNv->ScratchBuffer);
1758         NVFreeMemory(pNv, pNv->Cursor);
1759
1760     return TRUE;
1761 }
1762
1763
1764 /*
1765  * Initialise a new mode. 
1766  */
1767
1768 static Bool
1769 NVModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1770 {
1771     vgaHWPtr hwp = VGAHWPTR(pScrn);
1772     vgaRegPtr vgaReg;
1773     NVPtr pNv = NVPTR(pScrn);
1774     NVRegPtr nvReg;
1775
1776     /* Initialise the ModeReg values */
1777     if (!vgaHWInit(pScrn, mode))
1778         return FALSE;
1779     pScrn->vtSema = TRUE;
1780
1781     vgaReg = &hwp->ModeReg;
1782     nvReg = &pNv->ModeReg;
1783
1784     if(!NVDACInit(pScrn, mode))
1785         return FALSE;
1786
1787     NVLockUnlock(pNv, 0);
1788     if(pNv->twoHeads) {
1789         nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, nvReg->crtcOwner);
1790         NVLockUnlock(pNv, 0);
1791     }
1792
1793     /* Program the registers */
1794     vgaHWProtect(pScrn, TRUE);
1795
1796     NVDACRestore(pScrn, vgaReg, nvReg, FALSE);
1797
1798 #if X_BYTE_ORDER == X_BIG_ENDIAN
1799     /* turn on LFB swapping */
1800     {
1801         unsigned char tmp;
1802
1803         tmp = nvReadVGA(pNv, NV_VGA_CRTCX_SWAPPING);
1804         tmp |= (1 << 7);
1805         nvWriteVGA(pNv, NV_VGA_CRTCX_SWAPPING, tmp);
1806     }
1807 #endif
1808
1809     if (!pNv->NoAccel)
1810             NVResetGraphics(pScrn);
1811
1812     vgaHWProtect(pScrn, FALSE);
1813
1814     pNv->CurrentLayout.mode = mode;
1815
1816     return TRUE;
1817 }
1818
1819 /*
1820  * Restore the initial (text) mode.
1821  */
1822 static void 
1823 NVRestore(ScrnInfoPtr pScrn)
1824 {
1825         vgaHWPtr hwp = VGAHWPTR(pScrn);
1826         vgaRegPtr vgaReg = &hwp->SavedReg;
1827         NVPtr pNv = NVPTR(pScrn);
1828         NVRegPtr nvReg = &pNv->SavedReg;
1829
1830 #ifdef ENABLE_RANDR12
1831         if (pNv->randr12_enable) {
1832                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1833                 int i;
1834                 int vgaflags = VGA_SR_CMAP | VGA_SR_MODE;
1835
1836                 for (i = 0; i < xf86_config->num_crtc; i++) {
1837                         NVCrtcLockUnlock(xf86_config->crtc[i], 0);
1838                 }
1839
1840                 for (i = 0; i < xf86_config->num_crtc; i++) {
1841                         xf86_config->crtc[i]->funcs->restore(xf86_config->crtc[i]);
1842                 }
1843
1844                 for (i = 0; i < xf86_config->num_output; i++) {
1845                         xf86_config->output[i]->funcs->restore(xf86_config->
1846                                                                output[i]);
1847                 }
1848
1849 #ifndef __powerpc__
1850                 vgaflags |= VGA_SR_FONTS;
1851 #endif
1852                 vgaHWRestore(pScrn, vgaReg, vgaflags);
1853                 vgaHWLock(hwp);
1854
1855                 for (i = 0; i < xf86_config->num_crtc; i++) {
1856                         NVCrtcLockUnlock(xf86_config->crtc[i], 1);
1857                 }
1858         } else
1859 #endif
1860         {
1861                 NVLockUnlock(pNv, 0);
1862
1863                 if(pNv->twoHeads) {
1864                         nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, pNv->crtc_active[1] * 0x3);
1865                         NVLockUnlock(pNv, 0);
1866                 }
1867
1868                 /* Only restore text mode fonts/text for the primary card */
1869                 vgaHWProtect(pScrn, TRUE);
1870                 NVDACRestore(pScrn, vgaReg, nvReg, pNv->Primary);
1871                 if(pNv->twoHeads) {
1872                         nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, pNv->vtOWNER);
1873                 }
1874                 vgaHWProtect(pScrn, FALSE);
1875         }
1876 }
1877
1878
1879 #define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
1880 #define MAKE_INDEX(in, w) (DEPTH_SHIFT(in, w) * 3)
1881
1882 static void
1883 NVLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1884               LOCO * colors, VisualPtr pVisual)
1885 {
1886 #ifdef ENABLE_RANDR12
1887         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1888         int c;
1889         NVPtr pNv = NVPTR(pScrn);
1890         int i, index;
1891
1892         for (c = 0; c < xf86_config->num_crtc; c++) {
1893                 xf86CrtcPtr crtc = xf86_config->crtc[c];
1894                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1895                 NVCrtcRegPtr regp;
1896
1897                 regp = &pNv->ModeReg.crtc_reg[nv_crtc->head];
1898
1899                 if (crtc->enabled == 0)
1900                         continue;
1901
1902                 switch (pNv->CurrentLayout.depth) {
1903                 case 15:
1904                         for (i = 0; i < numColors; i++) {
1905                                 index = indices[i];
1906                                 regp->DAC[MAKE_INDEX(index, 5) + 0] =
1907                                     colors[index].red;
1908                                 regp->DAC[MAKE_INDEX(index, 5) + 1] =
1909                                     colors[index].green;
1910                                 regp->DAC[MAKE_INDEX(index, 5) + 2] =
1911                                     colors[index].blue;
1912                         }
1913                         break;
1914                 case 16:
1915                         for (i = 0; i < numColors; i++) {
1916                                 index = indices[i];
1917                                 regp->DAC[MAKE_INDEX(index, 6) + 1] =
1918                                     colors[index].green;
1919                                 if (index < 32) {
1920                                         regp->DAC[MAKE_INDEX(index, 5) +
1921                                                   0] = colors[index].red;
1922                                         regp->DAC[MAKE_INDEX(index, 5) +
1923                                                   2] = colors[index].blue;
1924                                 }
1925                         }
1926                         break;
1927                 default:
1928                         for (i = 0; i < numColors; i++) {
1929                                 index = indices[i];
1930                                 regp->DAC[index * 3] = colors[index].red;
1931                                 regp->DAC[(index * 3) + 1] =
1932                                     colors[index].green;
1933                                 regp->DAC[(index * 3) + 2] =
1934                                     colors[index].blue;
1935                         }
1936                         break;
1937                 }
1938
1939                 NVCrtcLoadPalette(crtc);
1940         }
1941 #endif
1942 }
1943
1944 //#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
1945 #define COLOR(c) (unsigned int)(0x3fff * ((c)/255.0))
1946 static void
1947 NV50LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1948                 LOCO * colors, VisualPtr pVisual)
1949 {
1950         NVPtr pNv = NVPTR(pScrn);
1951         int i, index;
1952         volatile struct {
1953                 unsigned short red, green, blue, unused;
1954         } *lut = (void *) pNv->CLUT->map;
1955
1956         switch (pScrn->depth) {
1957         case 15:
1958                 for (i = 0; i < numColors; i++) {
1959                         index = indices[i];
1960                         lut[DEPTH_SHIFT(index, 5)].red =
1961                             COLOR(colors[index].red);
1962                         lut[DEPTH_SHIFT(index, 5)].green =
1963                             COLOR(colors[index].green);
1964                         lut[DEPTH_SHIFT(index, 5)].blue =
1965                             COLOR(colors[index].blue);
1966                 }
1967                 break;
1968         case 16:
1969                 for (i = 0; i < numColors; i++) {
1970                         index = indices[i];
1971                         lut[DEPTH_SHIFT(index, 6)].green =
1972                             COLOR(colors[index].green);
1973                         if (index < 32) {
1974                                 lut[DEPTH_SHIFT(index, 5)].red =
1975                                     COLOR(colors[index].red);
1976                                 lut[DEPTH_SHIFT(index, 5)].blue =
1977                                     COLOR(colors[index].blue);
1978                         }
1979                 }
1980                 break;
1981         default:
1982                 for (i = 0; i < numColors; i++) {
1983                         index = indices[i];
1984                         lut[index].red = COLOR(colors[index].red);
1985                         lut[index].green = COLOR(colors[index].green);
1986                         lut[index].blue = COLOR(colors[index].blue);
1987                 }
1988                 break;
1989         }
1990 }
1991
1992
1993 static void NVBacklightEnable(NVPtr pNv,  Bool on)
1994 {
1995     /* This is done differently on each laptop.  Here we
1996        define the ones we know for sure. */
1997
1998 #if defined(__powerpc__)
1999     if((pNv->Chipset == 0x10DE0179) || 
2000        (pNv->Chipset == 0x10DE0189) || 
2001        (pNv->Chipset == 0x10DE0329))
2002     {
2003        /* NV17,18,34 Apple iMac, iBook, PowerBook */
2004       CARD32 tmp_pmc, tmp_pcrt;
2005       tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
2006       tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
2007       if(on) {
2008           tmp_pmc |= (1 << 31);
2009           tmp_pcrt |= 0x1;
2010       }
2011       nvWriteMC(pNv, 0x10F0, tmp_pmc);
2012       nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
2013     }
2014 #endif
2015     
2016     if(pNv->LVDS) {
2017        if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11)) {
2018            nvWriteMC(pNv, 0x130C, on ? 3 : 7);
2019        }
2020     } else {
2021        CARD32 fpcontrol;
2022
2023        fpcontrol = nvReadCurRAMDAC(pNv, 0x848) & 0xCfffffCC;
2024
2025        /* cut the TMDS output */
2026        if(on) fpcontrol |= pNv->fpSyncs;
2027        else fpcontrol |= 0x20000022;
2028
2029        nvWriteCurRAMDAC(pNv, 0x0848, fpcontrol);
2030     }
2031 }
2032
2033 static void
2034 NVDPMSSetLCD(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
2035 {
2036   NVPtr pNv = NVPTR(pScrn);
2037
2038   if (!pScrn->vtSema) return;
2039
2040   vgaHWDPMSSet(pScrn, PowerManagementMode, flags);
2041
2042   switch (PowerManagementMode) {
2043   case DPMSModeStandby:  /* HSync: Off, VSync: On */
2044   case DPMSModeSuspend:  /* HSync: On, VSync: Off */
2045   case DPMSModeOff:      /* HSync: Off, VSync: Off */
2046     NVBacklightEnable(pNv, 0);
2047     break;
2048   case DPMSModeOn:       /* HSync: On, VSync: On */
2049     NVBacklightEnable(pNv, 1);
2050   default:
2051     break;
2052   }
2053 }
2054
2055
2056 static void
2057 NVDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
2058 {
2059   unsigned char crtc1A;
2060   vgaHWPtr hwp = VGAHWPTR(pScrn);
2061
2062   if (!pScrn->vtSema) return;
2063
2064   crtc1A = hwp->readCrtc(hwp, 0x1A) & ~0xC0;
2065
2066   switch (PowerManagementMode) {
2067   case DPMSModeStandby:  /* HSync: Off, VSync: On */
2068     crtc1A |= 0x80;
2069     break;
2070   case DPMSModeSuspend:  /* HSync: On, VSync: Off */
2071     crtc1A |= 0x40;
2072     break;
2073   case DPMSModeOff:      /* HSync: Off, VSync: Off */
2074     crtc1A |= 0xC0;
2075     break;
2076   case DPMSModeOn:       /* HSync: On, VSync: On */
2077   default:
2078     break;
2079   }
2080
2081   /* vgaHWDPMSSet will merely cut the dac output */
2082   vgaHWDPMSSet(pScrn, PowerManagementMode, flags);
2083
2084   hwp->writeCrtc(hwp, 0x1A, crtc1A);
2085 }
2086
2087
2088 /* Mandatory */
2089
2090 /* This gets called at the start of each server generation */
2091
2092 static Bool
2093 NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
2094 {
2095     ScrnInfoPtr pScrn;
2096     vgaHWPtr hwp;
2097     NVPtr pNv;
2098     int ret;
2099     VisualPtr visual;
2100     unsigned char *FBStart;
2101     int width, height, displayWidth, shadowHeight;
2102
2103     /* 
2104      * First get the ScrnInfoRec
2105      */
2106     pScrn = xf86Screens[pScreen->myNum];
2107
2108     hwp = VGAHWPTR(pScrn);
2109     pNv = NVPTR(pScrn);
2110
2111     /* Map the VGA memory when the primary video */
2112     if (pNv->Primary) {
2113         hwp->MapSize = 0x10000;
2114         if (!vgaHWMapMem(pScrn))
2115             return FALSE;
2116     }
2117     
2118     /* First init DRI/DRM */
2119     if (!NVDRIScreenInit(pScrn))
2120         return FALSE;
2121     
2122     ret = drmCommandNone(pNv->drm_fd, DRM_NOUVEAU_CARD_INIT);
2123     if (ret) {
2124         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2125                    "Error initialising the nouveau kernel module: %d\n",
2126                    ret);
2127         return FALSE;
2128     }
2129     
2130     /* Allocate and map memory areas we need */
2131     if (!NVMapMem(pScrn))
2132         return FALSE;
2133     
2134     if (!pNv->NoAccel) {
2135         /* Init DRM - Alloc FIFO */
2136         if (!NVInitDma(pScrn))
2137             return FALSE;
2138         
2139         /* setup graphics objects */
2140         if (!NVAccelCommonInit(pScrn))
2141             return FALSE;
2142     }
2143     
2144     if (!pNv->randr12_enable) {
2145         /* Save the current state */
2146         NVSave(pScrn);
2147         /* Initialise the first mode */
2148         if (!NVModeInit(pScrn, pScrn->currentMode))
2149             return FALSE;
2150
2151         /* Darken the screen for aesthetic reasons and set the viewport */
2152         
2153         NVSaveScreen(pScreen, SCREEN_SAVER_ON);
2154         pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
2155         
2156     } else {
2157         pScrn->memPhysBase = pNv->VRAMPhysical;
2158         pScrn->fbOffset = 0;
2159         
2160         if (!NVEnterVT(scrnIndex, 0))
2161             return FALSE;
2162     }
2163
2164
2165     /*
2166      * The next step is to setup the screen's visuals, and initialise the
2167      * framebuffer code.  In cases where the framebuffer's default
2168      * choices for things like visual layouts and bits per RGB are OK,
2169      * this may be as simple as calling the framebuffer's ScreenInit()
2170      * function.  If not, the visuals will need to be setup before calling
2171      * a fb ScreenInit() function and fixed up after.
2172      *
2173      * For most PC hardware at depths >= 8, the defaults that fb uses
2174      * are not appropriate.  In this driver, we fixup the visuals after.
2175      */
2176
2177     /*
2178      * Reset the visual list.
2179      */
2180     miClearVisualTypes();
2181
2182     /* Setup the visuals we support. */
2183
2184     if (!miSetVisualTypes(pScrn->depth, 
2185                           miGetDefaultVisualMask(pScrn->depth), 8,
2186                           pScrn->defaultVisual))
2187           return FALSE;
2188     if (!miSetPixmapDepths ()) return FALSE;
2189
2190     /*
2191      * Call the framebuffer layer's ScreenInit function, and fill in other
2192      * pScreen fields.
2193      */
2194
2195     width = pScrn->virtualX;
2196     height = pScrn->virtualY;
2197     displayWidth = pScrn->displayWidth;
2198
2199
2200     if(pNv->Rotate) {
2201         height = pScrn->virtualX;
2202         width = pScrn->virtualY;
2203     }
2204
2205     /* If RandR rotation is enabled, leave enough space in the
2206      * framebuffer for us to rotate the screen dimensions without
2207      * changing the pitch.
2208      */
2209     if(pNv->RandRRotation)
2210         shadowHeight = max(width, height);
2211     else
2212         shadowHeight = height;
2213
2214     if(pNv->ShadowFB) {
2215         pNv->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
2216         pNv->ShadowPtr = xalloc(pNv->ShadowPitch * shadowHeight);
2217         displayWidth = pNv->ShadowPitch / (pScrn->bitsPerPixel >> 3);
2218         FBStart = pNv->ShadowPtr;
2219     } else {
2220         pNv->ShadowPtr = NULL;
2221         FBStart = pNv->FB->map;
2222     }
2223
2224     switch (pScrn->bitsPerPixel) {
2225         case 8:
2226         case 16:
2227         case 32:
2228             ret = fbScreenInit(pScreen, FBStart, width, height,
2229                                pScrn->xDpi, pScrn->yDpi,
2230                                displayWidth, pScrn->bitsPerPixel);
2231             break;
2232         default:
2233             xf86DrvMsg(scrnIndex, X_ERROR,
2234                        "Internal error: invalid bpp (%d) in NVScreenInit\n",
2235                        pScrn->bitsPerPixel);
2236             ret = FALSE;
2237             break;
2238     }
2239     if (!ret)
2240         return FALSE;
2241
2242     if (pScrn->bitsPerPixel > 8) {
2243         /* Fixup RGB ordering */
2244         visual = pScreen->visuals + pScreen->numVisuals;
2245         while (--visual >= pScreen->visuals) {
2246             if ((visual->class | DynamicClass) == DirectColor) {
2247                 visual->offsetRed = pScrn->offset.red;
2248                 visual->offsetGreen = pScrn->offset.green;
2249                 visual->offsetBlue = pScrn->offset.blue;
2250                 visual->redMask = pScrn->mask.red;
2251                 visual->greenMask = pScrn->mask.green;
2252                 visual->blueMask = pScrn->mask.blue;
2253             }
2254         }
2255     }
2256
2257     fbPictureInit (pScreen, 0, 0);
2258     
2259     xf86SetBlackWhitePixels(pScreen);
2260
2261     if (!pNv->NoAccel) {
2262             NVExaInit(pScreen);
2263             NVResetGraphics(pScrn);
2264     }
2265     
2266     miInitializeBackingStore(pScreen);
2267     xf86SetBackingStore(pScreen);
2268     xf86SetSilkenMouse(pScreen);
2269
2270     /* Finish DRI init */
2271     NVDRIFinishScreenInit(pScrn);
2272
2273     /* Initialize software cursor.  
2274         Must precede creation of the default colormap */
2275     miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2276
2277     /* Initialize HW cursor layer. 
2278         Must follow software cursor initialization*/
2279     if (pNv->HWCursor) { 
2280         if (pNv->Architecture < NV_ARCH_50 && !pNv->randr12_enable)
2281                 ret = NVCursorInit(pScreen);
2282 #ifdef ENABLE_RANDR12
2283         else if (pNv->Architecture < NV_ARCH_50 && pNv->randr12_enable)
2284                 ret = NVCursorInitRandr12(pScreen);
2285         else
2286                 ret = NV50CursorInit(pScreen);
2287 #endif
2288
2289         if (ret != TRUE) {
2290             xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
2291                 "Hardware cursor initialization failed\n");
2292             pNv->HWCursor = FALSE;
2293         }
2294     }
2295
2296     /* Initialise default colourmap */
2297     if (!miCreateDefColormap(pScreen))
2298         return FALSE;
2299
2300     /* Initialize colormap layer.  
2301        Must follow initialization of the default colormap */
2302     if (!pNv->randr12_enable) {
2303         if(!xf86HandleColormaps(pScreen, 256, 8, NVDACLoadPalette,
2304                                 NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
2305             return FALSE;
2306     } else {
2307         if (pNv->Architecture < NV_ARCH_50) {
2308             if (!xf86HandleColormaps(pScreen, 256, 8, NVLoadPalette,
2309                                      NULL,
2310                                      CMAP_RELOAD_ON_MODE_SWITCH |
2311                                      CMAP_PALETTED_TRUECOLOR))
2312                 return FALSE;
2313         } else {
2314             if (!xf86HandleColormaps(pScreen, 256, 8, NV50LoadPalette,
2315                                      NULL, CMAP_PALETTED_TRUECOLOR))
2316                 return FALSE;
2317         }
2318     }
2319
2320 #ifdef ENABLE_RANDR12
2321     if (pNv->randr12_enable) {
2322         xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2323         
2324         if (!xf86CrtcScreenInit(pScreen))
2325             return FALSE;
2326
2327         pNv->PointerMoved = pScrn->PointerMoved;
2328         pScrn->PointerMoved = NVPointerMoved;
2329     }
2330 #endif
2331
2332     if(pNv->ShadowFB) {
2333         RefreshAreaFuncPtr refreshArea = NVRefreshArea;
2334
2335         if(pNv->Rotate || pNv->RandRRotation) {
2336            pNv->PointerMoved = pScrn->PointerMoved;
2337            if(pNv->Rotate)
2338                pScrn->PointerMoved = NVPointerMoved;
2339
2340            switch(pScrn->bitsPerPixel) {
2341                case 8:  refreshArea = NVRefreshArea8;   break;
2342                case 16: refreshArea = NVRefreshArea16;  break;
2343                case 32: refreshArea = NVRefreshArea32;  break;
2344            }
2345            if(!pNv->RandRRotation) {
2346                xf86DisableRandR();
2347                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2348                           "Driver rotation enabled, RandR disabled\n");
2349            }
2350         }
2351
2352         ShadowFBInit(pScreen, refreshArea);
2353     }
2354
2355     if (!pNv->randr12_enable) {
2356         if(pNv->FlatPanel)
2357             xf86DPMSInit(pScreen, NVDPMSSetLCD, 0);
2358         else
2359             xf86DPMSInit(pScreen, NVDPMSSet, 0);
2360     }
2361
2362     pScrn->memPhysBase = pNv->VRAMPhysical;
2363     pScrn->fbOffset = 0;
2364
2365     if(pNv->Rotate == 0 && !pNv->RandRRotation)
2366        NVInitVideo(pScreen);
2367
2368     pScreen->SaveScreen = NVSaveScreen;
2369
2370     /* Wrap the current CloseScreen function */
2371     pNv->CloseScreen = pScreen->CloseScreen;
2372     pScreen->CloseScreen = NVCloseScreen;
2373
2374     pNv->BlockHandler = pScreen->BlockHandler;
2375     pScreen->BlockHandler = NVBlockHandler;
2376
2377 #ifdef RANDR
2378     /* Install our DriverFunc.  We have to do it this way instead of using the
2379      * HaveDriverFuncs argument to xf86AddDriver, because InitOutput clobbers
2380      * pScrn->DriverFunc */
2381     if (!pNv->randr12_enable)
2382         pScrn->DriverFunc = NVDriverFunc;
2383 #endif
2384
2385     /* Report any unused options (only for the first generation) */
2386     if (serverGeneration == 1) {
2387         xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2388     }
2389     return TRUE;
2390 }
2391
2392 static Bool
2393 NVSaveScreen(ScreenPtr pScreen, int mode)
2394 {
2395 #ifdef ENABLE_RANDR12
2396     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
2397     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2398     NVPtr pNv = NVPTR(pScrn);
2399     int i;
2400     Bool on = xf86IsUnblank(mode);
2401     
2402     if (pNv->randr12_enable) {
2403         if (pScrn->vtSema) {
2404             for (i = 0; i < xf86_config->num_crtc; i++) {
2405                 
2406                 if (xf86_config->crtc[i]->enabled) {
2407                     NVCrtcBlankScreen(xf86_config->crtc[i],
2408                                       on);
2409                 }
2410             }
2411             
2412         }
2413         return TRUE;
2414     } else
2415 #endif
2416         return vgaHWSaveScreen(pScreen, mode);
2417 }
2418
2419 static void
2420 NVSave(ScrnInfoPtr pScrn)
2421 {
2422     NVPtr pNv = NVPTR(pScrn);
2423     NVRegPtr nvReg = &pNv->SavedReg;
2424     vgaHWPtr pVga = VGAHWPTR(pScrn);
2425     vgaRegPtr vgaReg = &pVga->SavedReg;
2426  
2427 #ifdef ENABLE_RANDR12
2428     if (pNv->randr12_enable) {
2429         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2430         int vgaflags = VGA_SR_CMAP | VGA_SR_MODE;
2431         int i;
2432
2433         for (i = 0; i < xf86_config->num_crtc; i++) {
2434                 xf86_config->crtc[i]->funcs->save(xf86_config->crtc[i]);
2435         }
2436
2437         for (i = 0; i < xf86_config->num_output; i++) {
2438                 xf86_config->output[i]->funcs->save(xf86_config->
2439                                                     output[i]);
2440         }
2441
2442         vgaHWUnlock(pVga);
2443 #ifndef __powerpc__
2444         vgaflags |= VGA_SR_FONTS;
2445 #endif
2446         vgaHWSave(pScrn, vgaReg, vgaflags);
2447     } else
2448 #endif
2449     {
2450         NVLockUnlock(pNv, 0);
2451         if(pNv->twoHeads) {
2452             nvWriteVGA(pNv, NV_VGA_CRTCX_OWNER, pNv->crtc_active[1] * 0x3);
2453             NVLockUnlock(pNv, 0);
2454         }
2455
2456         NVDACSave(pScrn, vgaReg, nvReg, pNv->Primary);
2457     }
2458 }
2459
2460 #ifdef RANDR
2461 static Bool
2462 NVRandRGetInfo(ScrnInfoPtr pScrn, Rotation *rotations)
2463 {
2464     NVPtr pNv = NVPTR(pScrn);
2465
2466     if(pNv->RandRRotation)
2467        *rotations = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_270;
2468     else
2469        *rotations = RR_Rotate_0;
2470
2471     return TRUE;
2472 }
2473
2474 static Bool
2475 NVRandRSetConfig(ScrnInfoPtr pScrn, xorgRRConfig *config)
2476 {
2477     NVPtr pNv = NVPTR(pScrn);
2478
2479     switch(config->rotation) {
2480         case RR_Rotate_0:
2481             pNv->Rotate = 0;
2482             pScrn->PointerMoved = pNv->PointerMoved;
2483             break;
2484
2485         case RR_Rotate_90:
2486             pNv->Rotate = -1;
2487             pScrn->PointerMoved = NVPointerMoved;
2488             break;
2489
2490         case RR_Rotate_270:
2491             pNv->Rotate = 1;
2492             pScrn->PointerMoved = NVPointerMoved;
2493             break;
2494
2495         default:
2496             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2497                     "Unexpected rotation in NVRandRSetConfig!\n");
2498             pNv->Rotate = 0;
2499             pScrn->PointerMoved = pNv->PointerMoved;
2500             return FALSE;
2501     }
2502
2503     return TRUE;
2504 }
2505
2506 static Bool
2507 NVDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer data)
2508 {
2509     switch(op) {
2510        case RR_GET_INFO:
2511           return NVRandRGetInfo(pScrn, (Rotation*)data);
2512        case RR_SET_CONFIG:
2513           return NVRandRSetConfig(pScrn, (xorgRRConfig*)data);
2514        default:
2515           return FALSE;
2516     }
2517
2518     return FALSE;
2519 }
2520 #endif