xf86-video-nv: 16 commits - compat/.gitignore compat/Makefile.am compat/README configure.ac Makefile.am man/Makefile.am man/nv.man src/g80_cursor.c src/g80_cursor.h src/g80_dac.c src/g80_ddc.c src/g80_ddc.h src/g80_display.c src/g80_display.h src/g80_driver.c src/g80_output.c src/g80_output.h src/g80_sor.c src/g80_type.h src/local_xf86Rename.h src/Makefile.am src/nv_driver.c src/nv_include.h src/nv_local.h src/nv_video.c src/riva_include.h src/riva_local.h

Aaron Plattner aplattner at kemper.freedesktop.org
Wed Apr 25 02:02:51 EEST 2007


 Makefile.am            |    2 
 compat/.gitignore      |    2 
 compat/Makefile.am     |   15 +
 compat/README          |    7 
 configure.ac           |   70 +++++---
 man/Makefile.am        |    9 -
 man/nv.man             |   13 -
 src/Makefile.am        |   29 +++
 src/g80_cursor.c       |  150 ++++--------------
 src/g80_cursor.h       |    8 
 src/g80_dac.c          |  199 ++++++++++++++++++++++++
 src/g80_ddc.c          |  230 ---------------------------
 src/g80_ddc.h          |    1 
 src/g80_display.c      |  406 ++++++++++++++++++++++++-------------------------
 src/g80_display.h      |   21 +-
 src/g80_driver.c       |  162 ++++++++-----------
 src/g80_output.c       |  347 +++++++++++++++++++++++++++++++++++++++++
 src/g80_output.h       |   29 +++
 src/g80_sor.c          |  151 ++++++++++++++++++
 src/g80_type.h         |   19 --
 src/local_xf86Rename.h |   23 ++
 src/nv_driver.c        |   19 --
 src/nv_include.h       |    5 
 src/nv_local.h         |    3 
 src/nv_video.c         |   13 -
 src/riva_include.h     |    5 
 src/riva_local.h       |    3 
 27 files changed, 1186 insertions(+), 755 deletions(-)

New commits:
diff-tree c6e4105ce40ef053e026cc0ffe4925ab568ea700 (from parents)
Merge: 5d9b75b432dbc525e10c1c00436a1820456f6fb4 4ff648c85f8aa90b343b7e2df176c0511b3cdaa5
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Tue Apr 24 15:43:48 2007 -0700

    Merge branch 'randr-1.2'
    
    Conflicts:
    
    	configure.ac
    	man/Makefile.am
    	man/nv.man
    	src/g80_display.h
    	src/g80_output.c
    	src/nv_driver.c

diff --cc Makefile.am
index fd65d86,5acfc99..aa4996b
@@@ -19,9 -19,9 +19,9 @@@
  #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  AUTOMAKE_OPTIONS = foreign
- SUBDIRS = src man
+ SUBDIRS = src man compat
  
 -EXTRA_DIST = README.NV1 ChangeLog
 +EXTRA_DIST = README.NV1 README.G80 ChangeLog
  
  CLEANFILES = ChangeLog
  .PHONY: ChangeLog
diff --cc man/nv.man
index 0d8d079,c8d2fcb..6ef62c5
@@@ -58,12 -58,9 +58,9 @@@
  .TP 22
  .B GeForce 7XXX
  G70, G71, G72, G73
- .de G8
  .TP 22
  .B GeForce 8XXX
 -G80
 +G80, G84, G86
- ..
- .if __support_g80__ .G8
  
  .SH CONFIGURATION DETAILS
  Please refer to __xconfigfile__(__filemansuffix__) for general configuration
diff --cc src/g80_driver.c
index 2a3120f,9ce23ff..a4e7bad
@@@ -401,15 -395,14 +395,11 @@@
  static Bool
  AcquireDisplay(ScrnInfoPtr pScrn)
  {
-     G80Ptr pNv = G80PTR(pScrn);
- 
      if(!G80DispInit(pScrn))
          return FALSE;
-     if(!G80CursorAcquire(pNv))
+     if(!G80CursorAcquire(pScrn))
          return FALSE;
-     if(!G80DispSetMode(pScrn, pScrn->currentMode))
-         return FALSE;
-     G80DispDPMSSet(pScrn, DPMSModeOn, 0);
 -#if 0
 -    G80DispDPMSSet(pScrn, DPMSModeOn, 0);
 -#endif
+     xf86SetDesiredModes(pScrn);
  
      return TRUE;
  }
diff --cc src/g80_output.c
index 0000000,fd32f98..354d39a
mode 000000,100644..100644
@@@ -1,0 -1,347 +1,347 @@@
+ /*
+  * Copyright (c) 2007 NVIDIA, Corporation
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the
+  * "Software"), to deal in the Software without restriction, including
+  * without limitation the rights to use, copy, modify, merge, publish,
+  * distribute, sublicense, and/or sell copies of the Software, and to
+  * permit persons to whom the Software is furnished to do so, subject to
+  * the following conditions:
+  *
+  * The above copyright notice and this permission notice shall be included
+  * in all copies or substantial portions of the Software.
+  *
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+  */
+ 
+ 
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+ #endif
+ 
+ #include <strings.h>
+ #include <xf86DDC.h>
+ 
+ #include "g80_type.h"
+ #include "g80_output.h"
+ 
+ static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
+ {
+     unsigned char *table2;
+     unsigned char headerSize, entries;
+     int i;
+     CARD16 a;
+     CARD32 b;
+ 
+     /* Clear the i2c map to invalid */
+     for(i = 0; i < 4; i++)
+         pNv->i2cMap[i].dac = pNv->i2cMap[i].sor = -1;
+ 
+     if(*(CARD16*)pNv->table1 != 0xaa55) goto fail;
+ 
+     a = *(CARD16*)(pNv->table1 + 0x36);
+     table2 = (unsigned char*)pNv->table1 + a;
+ 
+     if(table2[0] != 0x40) goto fail;
+ 
+     b = *(CARD32*)(table2 + 6);
+     if(b != 0x4edcbdcb) goto fail;
+ 
+     headerSize = table2[1];
+     entries = table2[2];
+ 
+     for(i = 0; i < entries; i++) {
 -        CARD32 type, port;
++        int type, port;
+         ORNum or;
+ 
+         b = *(CARD32*)&table2[headerSize + 8*i];
+         type = b & 0xf;
+         port = (b >> 4) & 0xf;
+         or = ffs((b >> 24) & 0xf) - 1;
+ 
+         if(type < 4 && port != 0xf) {
+             switch(type) {
+                 case 0: /* CRT */
+                 case 1: /* TV */
+                     if(pNv->i2cMap[port].dac != -1) {
+                         xf86DrvMsg(scrnIndex, X_WARNING,
+                                    "DDC routing table corrupt!  DAC %i -> %i "
+                                    "for port %i\n",
+                                    or, pNv->i2cMap[port].dac, port);
+                     }
+                     pNv->i2cMap[port].dac = or;
+                     break;
+                 case 2: /* TMDS */
+                 case 3: /* LVDS */
+                     if(pNv->i2cMap[port].sor != -1)
+                         xf86DrvMsg(scrnIndex, X_WARNING,
+                                    "DDC routing table corrupt!  SOR %i -> %i "
+                                    "for port %i\n",
+                                    or, pNv->i2cMap[port].sor, port);
+                     pNv->i2cMap[port].sor = or;
+                     break;
+             }
+         }
+     }
+ 
+     xf86DrvMsg(scrnIndex, X_PROBED, "I2C map:\n");
+     for(i = 0; i < 4; i++) {
+         if(pNv->i2cMap[i].dac != -1)
+             xf86DrvMsg(scrnIndex, X_PROBED, "  Bus %i -> DAC%i\n", i, pNv->i2cMap[i].dac);
+         if(pNv->i2cMap[i].sor != -1)
+             xf86DrvMsg(scrnIndex, X_PROBED, "  Bus %i -> SOR%i\n", i, pNv->i2cMap[i].sor);
+     }
+ 
+     return TRUE;
+ 
+ fail:
+     xf86DrvMsg(scrnIndex, X_ERROR, "Couldn't find the DDC routing table.  "
+                "Mode setting will probably fail!\n");
+     return FALSE;
+ }
+ 
+ static void G80_I2CPutBits(I2CBusPtr b, int clock, int data)
+ {
+     G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
+     const int off = b->DriverPrivate.val * 0x18;
+ 
+     pNv->reg[(0x0000E138+off)/4] = 4 | clock | data << 1;
+ }
+ 
+ static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+ {
+     G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
+     const int off = b->DriverPrivate.val * 0x18;
+     unsigned char val;
+ 
+     val = pNv->reg[(0x0000E138+off)/4];
+     *clock = !!(val & 1);
+     *data = !!(val & 2);
+ }
+ 
+ static I2CBusPtr
+ G80I2CInit(ScrnInfoPtr pScrn, const char *name, const int port)
+ {
+     I2CBusPtr i2c;
+ 
+     /* Allocate the I2C bus structure */
+     i2c = xf86CreateI2CBusRec();
+     if(!i2c) return NULL;
+ 
+     i2c->BusName = strdup(name);
+     i2c->scrnIndex = pScrn->scrnIndex;
+     i2c->I2CPutBits = G80_I2CPutBits;
+     i2c->I2CGetBits = G80_I2CGetBits;
+     i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+     i2c->StartTimeout = 550;
+     i2c->BitTimeout = 40;
+     i2c->ByteTimeout = 40;
+     i2c->AcknTimeout = 40;
+     i2c->DriverPrivate.val = port;
+ 
+     if(xf86I2CBusInit(i2c)) {
+         return i2c;
+     } else {
+         xfree(i2c);
+         return NULL;
+     }
+ }
+ 
+ void
+ G80OutputSetPClk(xf86OutputPtr output, int pclk)
+ {
+     G80OutputPrivPtr pPriv = output->driver_private;
+     pPriv->set_pclk(output, pclk);
+ }
+ 
+ int
+ G80OutputModeValid(xf86OutputPtr output, DisplayModePtr mode)
+ {
+     if(mode->Clock > 400000 || mode->Clock < 25000)
+         return MODE_CLOCK_RANGE;
+ 
+     return MODE_OK;
+ }
+ 
+ Bool
+ G80OutputModeFixup(xf86OutputPtr output, DisplayModePtr mode,
+                    DisplayModePtr adjusted_mode)
+ {
+     return TRUE;
+ }
+ 
+ void
+ G80OutputPrepare(xf86OutputPtr output)
+ {
+ }
+ 
+ void
+ G80OutputCommit(xf86OutputPtr output)
+ {
+ }
+ 
+ static xf86MonPtr
+ ProbeDDC(I2CBusPtr i2c)
+ {
+     ScrnInfoPtr pScrn = xf86Screens[i2c->scrnIndex];
+     G80Ptr pNv = G80PTR(pScrn);
+     xf86MonPtr monInfo = NULL;
+     const int bus = i2c->DriverPrivate.val, off = bus * 0x18;
+ 
+     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+             "Probing for EDID on I2C bus %i...\n", bus);
+     pNv->reg[(0x0000E138+off)/4] = 7;
+     /* Should probably use xf86OutputGetEDID here */
+     monInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, i2c);
+     pNv->reg[(0x0000E138+off)/4] = 3;
+ 
+     if(monInfo) {
+         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+                 "DDC detected a %s:\n", monInfo->features.input_type ?
+                 "DFP" : "CRT");
+         xf86PrintEDID(monInfo);
+     } else {
+         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "  ... none found\n");
+     }
+ 
+     return monInfo;
+ }
+ 
+ /*
+  * Read an EDID from the i2c port.  Perform load detection on the DAC (if
+  * present) to see if the display is connected via VGA.  Sets the cached status
+  * of both outputs.  The status is marked dirty again in the BlockHandler.
+  */
+ void G80OutputPartnersDetect(xf86OutputPtr dac, xf86OutputPtr sor, I2CBusPtr i2c)
+ {
+     xf86MonPtr monInfo = ProbeDDC(i2c);
+     xf86OutputPtr connected = NULL;
+     Bool load = dac && G80DacLoadDetect(dac);
+ 
+     if(dac) {
+         G80OutputPrivPtr pPriv = dac->driver_private;
+ 
+         if(load) {
+             pPriv->cached_status = XF86OutputStatusConnected;
+             connected = dac;
+         } else {
+             pPriv->cached_status = XF86OutputStatusDisconnected;
+         }
+     }
+ 
+     if(sor) {
+         G80OutputPrivPtr pPriv = sor->driver_private;
+ 
+         if(monInfo && !load) {
+             pPriv->cached_status = XF86OutputStatusConnected;
+             connected = sor;
+         } else {
+             pPriv->cached_status = XF86OutputStatusDisconnected;
+         }
+     }
+ 
+     if(connected)
+         xf86OutputSetEDID(connected, monInfo);
+ }
+ 
+ /*
+  * Reset the cached output status for all outputs.  Called from G80BlockHandler.
+  */
+ void
+ G80OutputResetCachedStatus(ScrnInfoPtr pScrn)
+ {
+     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int i;
+ 
+     for(i = 0; i < xf86_config->num_output; i++) {
+         G80OutputPrivPtr pPriv = xf86_config->output[i]->driver_private;
+         pPriv->cached_status = XF86OutputStatusUnknown;
+     }
+ }
+ 
+ DisplayModePtr
+ G80OutputGetDDCModes(xf86OutputPtr output)
+ {
+     /* The EDID is read as part of the detect step */
+     output->funcs->detect(output);
+     return xf86OutputGetEDIDModes(output);
+ }
+ 
+ void
+ G80OutputDestroy(xf86OutputPtr output)
+ {
+     G80OutputPrivPtr pPriv = output->driver_private;
+ 
+     if(pPriv->partner)
+         ((G80OutputPrivPtr)pPriv->partner->driver_private)->partner = NULL;
+     else
+         xf86DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE);
+     pPriv->i2c = NULL;
+ }
+ 
+ Bool
+ G80CreateOutputs(ScrnInfoPtr pScrn)
+ {
+     G80Ptr pNv = G80PTR(pScrn);
+     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int i;
+ 
+     if(!G80ReadPortMapping(pScrn->scrnIndex, pNv))
+         return FALSE;
+ 
+     /* For each DDC port, create an output for the attached ORs */
+     for(i = 0; i < 4; i++) {
+         xf86OutputPtr dac = NULL, sor = NULL;
+         I2CBusPtr i2c;
+         char i2cName[16];
+ 
+         if(pNv->i2cMap[i].dac == -1 && pNv->i2cMap[i].sor == -1)
+             /* No outputs on this port */
+             continue;
+ 
+         snprintf(i2cName, sizeof(i2cName), "I2C%i", i);
+         i2c = G80I2CInit(pScrn, i2cName, i);
+         if(!i2c) {
+             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                        "Failed to initialize I2C for port %i.\n",
+                        i);
+             continue;
+         }
+ 
+         if(pNv->i2cMap[i].dac != -1)
+             dac = G80CreateDac(pScrn, pNv->i2cMap[i].dac);
+         if(pNv->i2cMap[i].sor != -1)
+             sor = G80CreateSor(pScrn, pNv->i2cMap[i].sor);
+ 
+         if(dac) {
+             G80OutputPrivPtr pPriv = dac->driver_private;
+ 
+             pPriv->partner = sor;
+             pPriv->i2c = i2c;
+         }
+         if(sor) {
+             G80OutputPrivPtr pPriv = sor->driver_private;
+ 
+             pPriv->partner = dac;
+             pPriv->i2c = i2c;
+         }
+     }
+ 
+     /* For each output, set the crtc and clone masks */
+     for(i = 0; i < xf86_config->num_output; i++) {
+         xf86OutputPtr output = xf86_config->output[i];
+ 
+         /* Any output can connect to any head */
+         output->possible_crtcs = 0x3;
+         output->possible_clones = 0;
+     }
+ 
+     return TRUE;
+ }
diff --cc src/nv_driver.c
index d90dd37,f9fdc7e..c8b98b8
@@@ -338,12 -338,6 +338,11 @@@
    { 0x10DE0193, "GeForce 8800 GTS" },
    { 0x10DE019D, "Quadro FX 5600" },
    { 0x10DE019E, "Quadro FX 4600" },
 +  { 0x10DE0400, "GeForce 8600 GTS" },
 +  { 0x10DE0402, "GeForce 8600 GT" },
 +  { 0x10DE0421, "GeForce 8500 GT" },
 +  { 0x10DE0422, "GeForce 8400 GS" },
 +  { 0x10DE0423, "GeForce 8300 GS" },
- #endif
  
    {-1, NULL}
  };
@@@ -1026,33 -1011,6 +1019,31 @@@
      return FALSE;
  }
  
 +
- #ifdef USE_CVTMODE_FUNC
 +/* Copied from ddc/Property.c */
 +static DisplayModePtr
 +NVModesAdd(DisplayModePtr Modes, DisplayModePtr Additions)
 +{
 +    if (!Modes) {
 +        if (Additions)
 +            return Additions;
 +        else
 +            return NULL;
 +    }
 +
 +    if (Additions) {
 +        DisplayModePtr Mode = Modes;
 +
 +        while (Mode->next)
 +            Mode = Mode->next;
 +        
 +        Mode->next = Additions;
 +        Additions->prev = Mode;
 +    }
 +
 +    return Modes;
 +}
- #endif
 +
  /* Mandatory */
  Bool
  NVPreInit(ScrnInfoPtr pScrn, int flags)
@@@ -1062,9 -1020,6 +1053,7 @@@
      int i, max_width, max_height;
      ClockRangePtr clockRanges;
      const char *s;
- #ifdef USE_CVTMODE_FUNC
-     int config_mon_rates;
- #endif
++    Bool config_mon_rates;
  
      if (flags & PROBE_DETECT) {
          EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
@@@ -1522,14 -1477,6 +1511,12 @@@
      pNv->alphaCursor = (pNv->Architecture >= NV_ARCH_10) &&
                         ((pNv->Chipset & 0x0ff0) != 0x0100);
  
- #ifdef USE_CVTMODE_FUNC
 +    if ((pScrn->monitor->nHsync == 0) && 
 +	(pScrn->monitor->nVrefresh == 0))
 +	config_mon_rates = FALSE;
 +    else
 +	config_mon_rates = TRUE;
- #endif
 +
      NVCommonSetup(pScrn);
  
      if (pNv->FBDev) {
@@@ -1599,37 -1546,6 +1586,35 @@@
         max_height = 4096;
      }
  
- #ifdef USE_CVTMODE_FUNC
 +    /* If DFP, add a modeline corresponding to its panel size */
 +    if (pNv->FlatPanel && !pNv->Television && pNv->fpWidth && pNv->fpHeight) {
 +	DisplayModePtr Mode;
 +
 +	Mode = xf86CVTMode(pNv->fpWidth, pNv->fpHeight, 60.00, TRUE, FALSE);
 +	Mode->type = M_T_DRIVER;
 +	pScrn->monitor->Modes = NVModesAdd(pScrn->monitor->Modes, Mode);
 +
 +	if (!config_mon_rates) {
 +	    if (!Mode->HSync)
 +            	Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
 +            if (!Mode->VRefresh)
 +            	Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
 +                    ((float) (Mode->HTotal * Mode->VTotal));
 +
 + 	    if (Mode->HSync < pScrn->monitor->hsync[0].lo)
 +            	pScrn->monitor->hsync[0].lo = Mode->HSync;
 +            if (Mode->HSync > pScrn->monitor->hsync[0].hi)
 +            	pScrn->monitor->hsync[0].hi = Mode->HSync;
 +            if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo)
 +            	pScrn->monitor->vrefresh[0].lo = Mode->VRefresh;
 +            if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi)
 +            	pScrn->monitor->vrefresh[0].hi = Mode->VRefresh;
 +
 +	    pScrn->monitor->nHsync = 1;
 +	    pScrn->monitor->nVrefresh = 1;
 +	}
 +    }
- #endif
 +
      /*
       * xf86ValidateModes will check that the mode HTotal and VTotal values
       * don't exceed the chipset's limit if pScrn->maxHValue and
diff-tree 4ff648c85f8aa90b343b7e2df176c0511b3cdaa5 (from 48f9a6f94550acea4fce81d2539a6508049c1551)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 20 16:24:15 2007 -0700

    Depend on server 1.2 or higher.
    
    Remove support for building with the libc wrapper or without the Drawable XV
    argument.

diff --git a/configure.ac b/configure.ac
index b4fd037..5370beb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -59,14 +59,8 @@ XORG_DRIVER_CHECK_EXT(RENDER, renderprot
 XORG_DRIVER_CHECK_EXT(XV, videoproto)
 XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
 
-# Determine whether XV PutImage takes a DrawablePtr and whether or not to use
-# the libcwrapper.
-PKG_CHECK_EXISTS([xorg-server >= 1.0.99.901],
-                 [AC_DEFINE(HAVE_XV_DRAWABLE,1,[XV hooks take a DrawablePtr])],
-                 [AC_DEFINE(USE_LIBC_WRAPPER,1,[Use the libc wrapper])])
-
 # Checks for pkg-config packages
-PKG_CHECK_MODULES(XORG, [xorg-server xproto fontsproto $REQUIRED_MODULES])
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.2 xproto fontsproto $REQUIRED_MODULES])
 sdkdir=$(pkg-config --variable=sdkdir xorg-server)
 
 # Checks for libraries.
diff --git a/src/nv_include.h b/src/nv_include.h
index 03f2997..648ac31 100644
--- a/src/nv_include.h
+++ b/src/nv_include.h
@@ -3,19 +3,14 @@
 #ifndef __NV_INCLUDE_H__
 #define __NV_INCLUDE_H__
 
-#if !USE_LIBC_WRAPPER
 #include <string.h>
 #include <math.h>
 #include <unistd.h>
-#endif
 
 /* All drivers should typically include these */
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
-#if USE_LIBC_WRAPPER
-#include "xf86_ansic.h"
-#endif
 #include "compiler.h"
 
 /* Drivers for PCI hardware need this */
diff --git a/src/nv_local.h b/src/nv_local.h
index 6cb0264..3d5d202 100644
--- a/src/nv_local.h
+++ b/src/nv_local.h
@@ -46,9 +46,6 @@
  * HW.  Put all affected includes, typdefs, etc. here so the riva_hw.* files
  * can stay generic in nature.
  */ 
-#if USE_LIBC_WRAPPER
-#include "xf86_ansic.h"
-#endif
 #include "compiler.h"
 #include "xf86_OSproc.h"
 
diff --git a/src/nv_video.c b/src/nv_video.c
index 1a428fb..c9ee5fe 100644
--- a/src/nv_video.c
+++ b/src/nv_video.c
@@ -7,9 +7,6 @@
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
-#if USE_LIBC_WRAPPER
-#include "xf86_ansic.h"
-#endif
 #include "compiler.h"
 #include "xf86PciInfo.h"
 #include "xf86Pci.h"
@@ -83,11 +80,7 @@ static int  NVGetBlitPortAttribute(ScrnI
 static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool);
 static void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool);
 
-#if HAVE_XV_DRAWABLE
 static int  NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
-#else
-static int  NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer);
-#endif
 
 static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
 static int  NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *,  int *, int *);
@@ -1012,10 +1005,8 @@ static int NVPutImage
     short        height, 
     Bool         Sync,
     RegionPtr    clipBoxes,
-    pointer      data
-#if HAVE_XV_DRAWABLE
-    , DrawablePtr  pDraw
-#endif
+    pointer      data,
+    DrawablePtr  pDraw
 )
 {
     NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
diff --git a/src/riva_include.h b/src/riva_include.h
index 675899b..2f269df 100644
--- a/src/riva_include.h
+++ b/src/riva_include.h
@@ -3,17 +3,12 @@
 #ifndef __RIVA_INCLUDE_H__
 #define __RIVA_INCLUDE_H__
 
-#if !USE_LIBC_WRAPPER
 #include <string.h>
-#endif
 
 /* All drivers should typically include these */
 #include "xf86.h"
 #include "xf86_OSproc.h"
 #include "xf86Resources.h"
-#if USE_LIBC_WRAPPER
-#include "xf86_ansic.h"
-#endif
 #include "compiler.h"
 
 /* Drivers for PCI hardware need this */
diff --git a/src/riva_local.h b/src/riva_local.h
index bdfe2b9..833ed04 100644
--- a/src/riva_local.h
+++ b/src/riva_local.h
@@ -46,9 +46,6 @@
  * HW.  Put all affected includes, typdefs, etc. here so the riva_hw.* files
  * can stay generic in nature.
  */ 
-#if USE_LIBC_WRAPPER
-#include "xf86_ansic.h"
-#endif
 #include "compiler.h"
 #include "xf86_OSproc.h"
 
diff-tree 48f9a6f94550acea4fce81d2539a6508049c1551 (from 7a07a765c2a3816e8cd0487e8f66bc767024142d)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 20 15:37:09 2007 -0700

    G80: Remove AdjustFrame printout.

diff --git a/src/g80_display.h b/src/g80_display.h
index 99436be..fac7877 100644
--- a/src/g80_display.h
+++ b/src/g80_display.h
@@ -11,6 +11,5 @@ void G80CrtcBlankScreen(xf86CrtcPtr, Boo
 void G80CrtcEnableCursor(xf86CrtcPtr, Bool update);
 void G80CrtcDisableCursor(xf86CrtcPtr, Bool update);
 void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y);
-void G80CrtcSetDither(xf86CrtcPtr, CARD32 mask, CARD32 val);
 
 void G80DispCreateCrtcs(ScrnInfoPtr pScrn);
diff --git a/src/g80_driver.c b/src/g80_driver.c
index b79fa9c..9ce23ff 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -842,7 +842,6 @@ G80SwitchMode(int scrnIndex, DisplayMode
 static void
 G80AdjustFrame(int scrnIndex, int x, int y, int flags)
 {
-    ErrorF("AdjustFrame unimplemented\n");
 }
 
 static Bool
diff-tree 7a07a765c2a3816e8cd0487e8f66bc767024142d (from 2971fd0a18e947c5d39d6af78b0b77d6e4fe00d8)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 20 14:30:45 2007 -0700

    Steal RandR1.2 compat code from the Intel driver.
    
    Spruce it up a bit so that --with-xserver-source works even if there's a local
    compat copy.

diff --git a/Makefile.am b/Makefile.am
index 3924813..5acfc99 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@
 #  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS = src man
+SUBDIRS = src man compat
 
 EXTRA_DIST = README.NV1 ChangeLog
 
diff --git a/compat/.gitignore b/compat/.gitignore
new file mode 100644
index 0000000..8d30df6
--- /dev/null
+++ b/compat/.gitignore
@@ -0,0 +1,2 @@
+modes
+parser
diff --git a/compat/Makefile.am b/compat/Makefile.am
new file mode 100644
index 0000000..f5f8d93
--- /dev/null
+++ b/compat/Makefile.am
@@ -0,0 +1,15 @@
+EXTRA_DIST = \
+    parser/xf86Parser.h \
+    parser/xf86Optrec.h \
+    modes/xf86Crtc.c \
+    modes/xf86Crtc.h \
+    modes/xf86Cursors.c \
+    modes/xf86cvt.c \
+    modes/xf86DiDGA.c \
+    modes/xf86EdidModes.c \
+    modes/xf86Modes.c \
+    modes/xf86Modes.h \
+    modes/xf86RandR12.c \
+    modes/xf86RandR12.h \
+    modes/xf86Rename.h \
+    modes/xf86Rotate.c
diff --git a/compat/README b/compat/README
new file mode 100644
index 0000000..3e2b089
--- /dev/null
+++ b/compat/README
@@ -0,0 +1,7 @@
+This directory contains a copy of the mode and parser code from RandR 1.2.
+
+If you are building from git and you don't have xorg-server-1.3 or higher or you
+want to be able to make dist, you should create symlinks to the modes and parser
+directories from a RandR 1.2-enabled server here:
+
+  $ ln -s /path/to/xorg/xserver/hw/xfree86/{modes,parser} .
diff --git a/configure.ac b/configure.ac
index 9bb243a..b4fd037 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,12 +41,18 @@ AC_PROG_CC
 
 AH_TOP([#include "xorg-server.h"])
 
+# Options
 AC_ARG_WITH(xorg-module-dir,
             AC_HELP_STRING([--with-xorg-module-dir=DIR],
                            [Default xorg module directory [[default=$libdir/xorg/modules]]]),
             [moduledir="$withval"],
             [moduledir="$libdir/xorg/modules"])
 
+AC_ARG_WITH(xserver-source,AC_HELP_STRING([--with-xserver-source=XSERVER_SOURCE],
+                                          [Path to X server source tree]),
+                           [ XSERVER_SOURCE="$withval" ],
+                           [ XSERVER_SOURCE="" ])
+
 # Checks for extensions
 XORG_DRIVER_CHECK_EXT(RANDR, randrproto)
 XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
@@ -68,6 +74,47 @@ sdkdir=$(pkg-config --variable=sdkdir xo
 # Checks for header files.
 AC_HEADER_STDC
 
+save_CFLAGS="$CFLAGS"
+CFLAGS="$XORG_CFLAGS"
+AC_CHECK_HEADER(xf86Modes.h,[BUILD_XMODES=no],[BUILD_XMODES=yes],[#include "xorg-server.h"])
+CFLAGS="$save_CFLAGS"
+AM_CONDITIONAL(BUILD_XMODES, test "x$BUILD_XMODES" = xyes)
+if test "x$XSERVER_SOURCE" != x; then
+    if test -d "$XSERVER_SOURCE"; then
+        XSERVER_SOURCE=`cd "$XSERVER_SOURCE" && pwd`
+        if test -f "$XSERVER_SOURCE/hw/xfree86/modes/xf86Modes.h" -a -f "$XSERVER_SOURCE/hw/xfree86/parser/xf86Parser.h"; then
+            :
+        else
+            AC_ERROR([Server source at $XSERVER_SOURCE doesn't have the new mode code])
+        fi
+    else
+        AC_ERROR([Can't find xserver-source path $XSERVER_SOURCE])
+    fi
+fi
+if test "x$BUILD_XMODES" = xno; then
+    AC_MSG_NOTICE([X server has new mode code])
+    XMODES_CFLAGS=
+    parser_dir=
+    modes_dir=
+else
+    if test "x$XSERVER_SOURCE" = x; then
+            AC_MSG_NOTICE([X server is missing new mode code and --with-xserver-source not specified, using local copy])
+            AC_MSG_NOTICE([If you're building from git, please read compat/README])
+            parser_dir='$(top_srcdir)/compat/parser'
+            modes_dir='$(top_srcdir)/compat/modes'
+    else
+            AC_MSG_NOTICE([Using mode code from $XSERVER_SOURCE])
+            parser_dir="$XSERVER_SOURCE/hw/xfree86/parser"
+            modes_dir="$XSERVER_SOURCE/hw/xfree86/modes"
+    fi
+    XMODES_CFLAGS="-DXF86_MODES_RENAME -I\"$modes_dir\" -I\"$parser_dir\""
+    AC_DEFINE(BUILD_XMODES, 1,[X server doesn't have built-in mode code, so we need to build it])
+fi
+AC_SUBST([XMODES_CFLAGS])
+AC_SUBST([parser_dir])
+AC_SUBST([modes_dir])
+
+# Substitutions
 AC_SUBST([XORG_CFLAGS])
 AC_SUBST([moduledir])
 
@@ -81,4 +128,5 @@ AC_OUTPUT([
 	Makefile
 	src/Makefile
 	man/Makefile
+	compat/Makefile
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index b31ebea..52b6b47 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,7 @@
 # -avoid-version prevents gratuitous .0.0.0 version numbers on the end
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
-AM_CFLAGS = @XORG_CFLAGS@
+AM_CFLAGS = @XMODES_CFLAGS@ @XORG_CFLAGS@
 nv_drv_la_LTLIBRARIES = nv_drv.la
 nv_drv_la_LDFLAGS = -module -avoid-version
 nv_drv_ladir = @moduledir@/drivers
@@ -81,3 +81,24 @@ g80_sources = \
          g80_type.h \
          g80_xaa.c \
          g80_xaa.h
+
+xmode_sources = \
+         @parser_dir@/xf86Parser.h \
+         @parser_dir@/xf86Optrec.h \
+         @modes_dir@/xf86Modes.h \
+         @modes_dir@/xf86Modes.c \
+         @modes_dir@/xf86cvt.c \
+         @modes_dir@/xf86Crtc.h \
+         @modes_dir@/xf86Crtc.c \
+         @modes_dir@/xf86Cursors.c \
+         @modes_dir@/xf86EdidModes.c \
+         @modes_dir@/xf86RandR12.c \
+         @modes_dir@/xf86RandR12.h \
+         @modes_dir@/xf86Rename.h \
+         @modes_dir@/xf86Rotate.c \
+         @modes_dir@/xf86DiDGA.c
+
+if BUILD_XMODES
+EXTRA_nv_drv_la_SOURCES = local_xf86Rename.h
+nodist_nv_drv_la_SOURCES = $(xmode_sources)
+endif
diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h
new file mode 100644
index 0000000..f3a07c6
--- /dev/null
+++ b/src/local_xf86Rename.h
@@ -0,0 +1,23 @@
+/*
+ *Copyright © 2006 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#define XF86NAME(x) nv_##x
diff-tree 2971fd0a18e947c5d39d6af78b0b77d6e4fe00d8 (from ae582bdd2107d7e0106d1d5a9a9d6b9e39f1c901)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 20 13:40:33 2007 -0700

    Remove unused g80_ddc.h.

diff --git a/src/g80_ddc.h b/src/g80_ddc.h
deleted file mode 100644
index d209d62..0000000
--- a/src/g80_ddc.h
+++ /dev/null
@@ -1 +0,0 @@
-Bool G80ProbeDDC(ScrnInfoPtr pScrn);
diff --git a/src/g80_driver.c b/src/g80_driver.c
index a3d86c7..b79fa9c 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -43,7 +43,6 @@
 #include "g80_type.h"
 #include "g80_cursor.h"
 #include "g80_display.h"
-#include "g80_ddc.h"
 #include "g80_dma.h"
 #include "g80_output.h"
 #include "g80_xaa.h"
diff --git a/src/g80_output.c b/src/g80_output.c
index a3b28a5..fd32f98 100644
--- a/src/g80_output.c
+++ b/src/g80_output.c
@@ -30,7 +30,6 @@
 #include <xf86DDC.h>
 
 #include "g80_type.h"
-#include "g80_ddc.h"
 #include "g80_output.h"
 
 static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
diff-tree ae582bdd2107d7e0106d1d5a9a9d6b9e39f1c901 (from f7c62016f8bf9ced7d56f74ce26e13b6df040379)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 20 00:13:31 2007 -0700

    Always support G80.

diff --git a/configure.ac b/configure.ac
index 6b1f98e..9bb243a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -63,17 +63,6 @@ PKG_CHECK_EXISTS([xorg-server >= 1.0.99.
 PKG_CHECK_MODULES(XORG, [xorg-server xproto fontsproto $REQUIRED_MODULES])
 sdkdir=$(pkg-config --variable=sdkdir xorg-server)
 
-# Check for optional compile-time support
-AC_ARG_ENABLE(g80, AC_HELP_STRING([--disable-g80],
-                                  [Disable G80 support [[default=no]]]),
-              [SUPPORT_G80="$enableval"],
-              [SUPPORT_G80=yes])
-AM_CONDITIONAL(SUPPORT_G80, test x$SUPPORT_G80 = xyes)
-if test "$SUPPORT_G80" = yes; then
-        AC_DEFINE(SUPPORT_G80,1,[Enable G80 support])
-        echo "Enabling G80 support"
-fi
-
 # Checks for libraries.
 
 # Checks for header files.
diff --git a/man/Makefile.am b/man/Makefile.am
index 036545c..bf7ec17 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -41,12 +41,6 @@ SED = sed
 XORGRELSTRING = @PACKAGE_STRING@
   XORGMANNAME = X Version 11
 
-if SUPPORT_G80
-MAN_SUPPORT_G80 := 1
-else
-MAN_SUPPORT_G80 := 0
-endif
-
 MAN_SUBSTS = \
 	-e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
 	-e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
@@ -57,8 +51,7 @@ MAN_SUBSTS = \
 	-e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
 	-e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
 	-e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \
-	-e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' \
-	-e 's|__support_g80__|$(MAN_SUPPORT_G80)|g'
+	-e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g'
 
 SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
 
diff --git a/man/nv.man b/man/nv.man
index e892ecf..c8d2fcb 100644
--- a/man/nv.man
+++ b/man/nv.man
@@ -58,12 +58,9 @@ NV40, NV41, NV43, NV44, NV45, C51
 .TP 22
 .B GeForce 7XXX
 G70, G71, G72, G73
-.de G8
 .TP 22
 .B GeForce 8XXX
 G80
-..
-.if __support_g80__ .G8
 
 .SH CONFIGURATION DETAILS
 Please refer to __xconfigfile__(__filemansuffix__) for general configuration
@@ -136,7 +133,6 @@ Default: no rotation support.
 Enable or disable use of the shadow framebuffer layer.  Default: off.
 .
 .\" ******************** begin G80 section ********************
-.de G8
 .PP
 The following driver
 .B Options
@@ -147,8 +143,6 @@ Enable or disable the hardware cursor.  
 .TP
 .BI "Option \*qNoAccel\*q \*q" boolean \*q
 Disable or enable acceleration.  Default: acceleration is enabled.
-..
-.if __support_g80__ .G8
 .\" ******************** end G80 section ********************
 .
 .SH "SEE ALSO"
diff --git a/src/Makefile.am b/src/Makefile.am
index d024283..b31ebea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,7 +66,6 @@ riva_sources = \
          riva_type.h \
          riva_xaa.c
 
-if SUPPORT_G80
 g80_sources = \
          g80_cursor.c \
          g80_cursor.h \
@@ -82,4 +81,3 @@ g80_sources = \
          g80_type.h \
          g80_xaa.c \
          g80_xaa.h
-endif
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 64d45c5..f9fdc7e 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -333,12 +333,11 @@ static SymTabRec NVKnownChipsets[] =
   { 0x10DE0244, "GeForce Go 6150" },
   { 0x10DE0247, "GeForce Go 6100" },
 
-#if SUPPORT_G80
+/*************** G8x ***************/
   { 0x10DE0191, "GeForce 8800 GTX" },
   { 0x10DE0193, "GeForce 8800 GTS" },
   { 0x10DE019D, "Quadro FX 5600" },
   { 0x10DE019E, "Quadro FX 4600" },
-#endif
 
   {-1, NULL}
 };
@@ -655,7 +654,6 @@ NVGetPCIXpressChip (pciVideoPtr pVideo)
     return pciid;
 }
 
-#if SUPPORT_G80
 static Bool
 NVIsG80(int chipType)
 {
@@ -668,7 +666,6 @@ NVIsG80(int chipType)
 
     return FALSE;
 }
-#endif
 
 /* Mandatory */
 static Bool
@@ -754,10 +751,8 @@ NVProbe(DriverPtr drv, int flags)
                default:  break;  /* we don't recognize it */
                }
 
-#if SUPPORT_G80
                if(NVIsG80((*ppPci)->chipType))
                    canHandle = TRUE;
-#endif
 
                if(canHandle) {
                    NVChipsets[numUsed].token = pciid;
@@ -795,11 +790,9 @@ NVProbe(DriverPtr drv, int flags)
         if(pPci->vendor == PCI_VENDOR_NVIDIA_SGS) {
             if(RivaGetScrnInfoRec(NVPciChipsets, usedChips[i]))
                 foundScreen = TRUE;
-#if SUPPORT_G80
         } else if (NVIsG80(pPci->chipType)) {
             if(G80GetScrnInfoRec(NVPciChipsets, usedChips[i]))
                 foundScreen = TRUE;
-#endif
         } else {
             if(NVGetScrnInfoRec(NVPciChipsets, usedChips[i])) 
 	        foundScreen = TRUE;
diff-tree f7c62016f8bf9ced7d56f74ce26e13b6df040379 (from f1cda5eaba9cbbfeb913d249d014586a6e8fd7a6)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 13 23:02:35 2007 -0700

    G80: Get rid of debug printouts.

diff --git a/src/g80_dac.c b/src/g80_dac.c
index e536ef7..7848de2 100644
--- a/src/g80_dac.c
+++ b/src/g80_dac.c
@@ -84,9 +84,6 @@ G80DacModeSet(xf86OutputPtr output, Disp
     G80OutputPrivPtr pPriv = output->driver_private;
     const int dacOff = 0x80 * pPriv->or;
 
-    if(adjusted_mode)
-        ErrorF("DAC%i mode %s -> HEAD%i\n", pPriv->or, adjusted_mode->name, G80CrtcGetHead(output->crtc));
-
     if(!adjusted_mode) {
         C(0x00000400 + dacOff, 0);
         return;
diff --git a/src/g80_display.c b/src/g80_display.c
index d7f52dd..652a5a9 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -461,17 +461,11 @@ G80CrtcPrepare(xf86CrtcPtr crtc)
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     int i;
 
-    ErrorF("Outputs:\n");
     for(i = 0; i < xf86_config->num_output; i++) {
         xf86OutputPtr output = xf86_config->output[i];
 
-        if(output->crtc) {
-            G80CrtcPrivPtr pPriv = output->crtc->driver_private;
-            ErrorF("\t%s -> HEAD%i\n", output->name, pPriv->head);
-        } else {
-            ErrorF("\t%s disconnected\n", output->name);
+        if(!output->crtc)
             output->funcs->mode_set(output, NULL, NULL);
-        }
     }
 }
 
diff --git a/src/g80_driver.c b/src/g80_driver.c
index 6ab92ee..a3d86c7 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -131,7 +131,6 @@ G80ResizeScreen(ScrnInfoPtr pScrn, int w
 
     pitch = (pitch + 255) & ~255;
 
-    ErrorF("Resizing screen to %ix%i\n", width, height);
     pScrn->virtualX = width;
     pScrn->virtualY = height;
 
@@ -481,12 +480,6 @@ G80BlockHandler(int i, pointer blockData
 static Bool
 G80SaveScreen(ScreenPtr pScreen, int mode)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-
-    if(!pScrn->vtSema) return FALSE;
-
-    ErrorF("SaveScreen unimplemented\n");
-
     return FALSE;
 }
 
diff --git a/src/g80_sor.c b/src/g80_sor.c
index 5187d1f..90119f0 100644
--- a/src/g80_sor.c
+++ b/src/g80_sor.c
@@ -71,9 +71,6 @@ G80SorModeSet(xf86OutputPtr output, Disp
     G80OutputPrivPtr pPriv = output->driver_private;
     const int sorOff = 0x40 * pPriv->or;
 
-    if(adjusted_mode)
-        ErrorF("SOR%i mode %s -> HEAD%i\n", pPriv->or, adjusted_mode->name, G80CrtcGetHead(output->crtc));
-
     if(!adjusted_mode) {
         /* Disconnect the SOR */
         C(0x00000600 + sorOff, 0);
diff-tree f1cda5eaba9cbbfeb913d249d014586a6e8fd7a6 (from 550af781bd9f7cb7256b298281c2c27febfc4722)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Apr 13 22:29:57 2007 -0700

    G80: Get DPMS working with RandR 1.2.
    
    Work around xf86DisableUnusedFunctions lameness by forcing DPMSModeOn at modeset
    time.

diff --git a/src/g80_dac.c b/src/g80_dac.c
index ac82616..e536ef7 100644
--- a/src/g80_dac.c
+++ b/src/g80_dac.c
@@ -27,6 +27,9 @@
 
 #include <unistd.h>
 
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
 #include "g80_type.h"
 #include "g80_display.h"
 #include "g80_output.h"
@@ -44,7 +47,33 @@ G80DacSetPClk(xf86OutputPtr output, int 
 static void
 G80DacDPMSSet(xf86OutputPtr output, int mode)
 {
-    ErrorF("DAC dpms unimplemented\n");
+    G80Ptr pNv = G80PTR(output->scrn);
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int off = 0x800 * pPriv->or;
+    CARD32 tmp;
+
+    /*
+     * DPMSModeOn       everything on
+     * DPMSModeStandby  hsync disabled, vsync enabled
+     * DPMSModeSuspend  hsync enabled, vsync disabled
+     * DPMSModeOff      sync disabled
+     */
+    while(pNv->reg[(0x0061A004+off)/4] & 0x80000000);
+
+    tmp = pNv->reg[(0x0061A004+off)/4];
+    tmp &= ~0x7f;
+    tmp |= 0x80000000;
+
+    if(mode == DPMSModeStandby || mode == DPMSModeOff)
+        tmp |= 1;
+    if(mode == DPMSModeSuspend || mode == DPMSModeOff)
+        tmp |= 4;
+    if(mode != DPMSModeOn)
+        tmp |= 0x10;
+    if(mode == DPMSModeOff)
+        tmp |= 0x40;
+
+    pNv->reg[(0x0061A004+off)/4] = tmp;
 }
 
 static void
@@ -63,6 +92,11 @@ G80DacModeSet(xf86OutputPtr output, Disp
         return;
     }
 
+    // This wouldn't be necessary, but the server is stupid and calls
+    // G80DacDPMSSet after the output is disconnected, even though the hardware
+    // turns it off automatically.
+    G80DacDPMSSet(output, DPMSModeOn);
+
     C(0x00000400 + dacOff,
         (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | 0x40);
     C(0x00000404 + dacOff,
@@ -94,12 +128,13 @@ G80DacLoadDetect(xf86OutputPtr output)
     G80OutputPrivPtr pPriv = output->driver_private;
     const int scrnIndex = pScrn->scrnIndex;
     const int dacOff = 2048 * pPriv->or;
-    CARD32 load, tmp;
+    CARD32 load, tmp, tmp2;
 
     xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on VGA%i ... ",
             pPriv->or);
 
     pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001;
+    tmp2 = pNv->reg[(0x0061A004+dacOff)/4];
     pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000;
     while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000);
     tmp = pNv->architecture == 0x50 ? 420 : 340;
@@ -107,7 +142,7 @@ G80DacLoadDetect(xf86OutputPtr output)
     usleep(4500);
     load = pNv->reg[(0x0061A00C+dacOff)/4];
     pNv->reg[(0x0061A00C+dacOff)/4] = 0;
-    pNv->reg[(0x0061A004+dacOff)/4] = 0x80550000;
+    pNv->reg[(0x0061A004+dacOff)/4] = 0x80000000 | tmp2;
 
     // Use this DAC if all three channels show load.
     if((load & 0x38000000) == 0x38000000) {
diff --git a/src/g80_display.c b/src/g80_display.c
index a5a1bc8..d7f52dd 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -36,9 +36,6 @@
 #include "g80_display.h"
 #include "g80_output.h"
 
-#define DPMS_SERVER
-#include <X11/extensions/dpms.h>
-
 typedef struct G80CrtcPrivRec {
     Head head;
     int pclk; /* Target pixel clock in kHz */
@@ -423,55 +420,6 @@ G80CrtcBlankScreen(xf86CrtcPtr crtc, Boo
 void
 G80CrtcDPMSSet(xf86CrtcPtr crtc, int mode)
 {
-    ErrorF("CRTC dpms unimplemented\n");
-#if 0
-    G80Ptr pNv = G80PTR(pScrn);
-    const int off = 0x800 * pNv->or;
-    CARD32 tmp;
-
-    /*
-     * DPMSModeOn       everything on
-     * DPMSModeStandby  hsync disabled, vsync enabled
-     * DPMSModeSuspend  hsync enabled, vsync disabled
-     * DPMSModeOff      sync disabled
-     */
-    switch(pNv->orType) {
-    case DAC:
-        while(pNv->reg[(0x0061A004+off)/4] & 0x80000000);
-
-        tmp = pNv->reg[(0x0061A004+off)/4];
-        tmp &= ~0x7f;
-        tmp |= 0x80000000;
-
-        if(mode == DPMSModeStandby || mode == DPMSModeOff)
-            tmp |= 1;
-        if(mode == DPMSModeSuspend || mode == DPMSModeOff)
-            tmp |= 4;
-        if(mode != DPMSModeOn)
-            tmp |= 0x10;
-        if(mode == DPMSModeOff)
-            tmp |= 0x40;
-
-        pNv->reg[(0x0061A004+off)/4] = tmp;
-
-        break;
-
-    case SOR:
-        while(pNv->reg[(0x0061C004+off)/4] & 0x80000000);
-
-        tmp = pNv->reg[(0x0061C004+off)/4];
-        tmp |= 0x80000000;
-
-        if(mode == DPMSModeOn)
-            tmp |= 1;
-        else
-            tmp &= ~1;
-
-        pNv->reg[(0x0061C004+off)/4] = tmp;
-
-        break;
-    }
-#endif
 }
 
 /******************************** Cursor stuff ********************************/
diff --git a/src/g80_sor.c b/src/g80_sor.c
index 74bccb0..5187d1f 100644
--- a/src/g80_sor.c
+++ b/src/g80_sor.c
@@ -25,6 +25,9 @@
 #include "config.h"
 #endif
 
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
 #include "g80_type.h"
 #include "g80_display.h"
 #include "g80_output.h"
@@ -42,7 +45,22 @@ G80SorSetPClk(xf86OutputPtr output, int 
 static void
 G80SorDPMSSet(xf86OutputPtr output, int mode)
 {
-    ErrorF("SOR dpms unimplemented\n");
+    G80Ptr pNv = G80PTR(output->scrn);
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int off = 0x800 * pPriv->or;
+    CARD32 tmp;
+
+    while(pNv->reg[(0x0061C004+off)/4] & 0x80000000);
+
+    tmp = pNv->reg[(0x0061C004+off)/4];
+    tmp |= 0x80000000;
+
+    if(mode == DPMSModeOn)
+        tmp |= 1;
+    else
+        tmp &= ~1;
+
+    pNv->reg[(0x0061C004+off)/4] = tmp;
 }
 
 static void
@@ -62,6 +80,11 @@ G80SorModeSet(xf86OutputPtr output, Disp
         return;
     }
 
+    // This wouldn't be necessary, but the server is stupid and calls
+    // G80SorDPMSSet after the output is disconnected, even though the hardware
+    // turns it off automatically.
+    G80SorDPMSSet(output, DPMSModeOn);
+
     C(0x00000600 + sorOff,
         (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) |
         (adjusted_mode->Clock > 165000 ? 0x500 : 0x100) |
diff-tree 550af781bd9f7cb7256b298281c2c27febfc4722 (from 5c03bd8acfcc814890fb13c891be4f135ea800d4)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Mon Apr 2 09:42:11 2007 -0700

    G80: Use the right mode struct when setting up an SOR.

diff --git a/src/g80_sor.c b/src/g80_sor.c
index fe34e7e..74bccb0 100644
--- a/src/g80_sor.c
+++ b/src/g80_sor.c
@@ -64,9 +64,9 @@ G80SorModeSet(xf86OutputPtr output, Disp
 
     C(0x00000600 + sorOff,
         (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) |
-        (mode->SynthClock > 165000 ? 0x500 : 0x100) |
-        ((mode->Flags & V_NHSYNC) ? 0x1000 : 0) |
-        ((mode->Flags & V_NVSYNC) ? 0x2000 : 0));
+        (adjusted_mode->Clock > 165000 ? 0x500 : 0x100) |
+        ((adjusted_mode->Flags & V_NHSYNC) ? 0x1000 : 0) |
+        ((adjusted_mode->Flags & V_NVSYNC) ? 0x2000 : 0));
 }
 
 static xf86OutputStatus
diff-tree 5c03bd8acfcc814890fb13c891be4f135ea800d4 (from 8f7769aadf175e8298f27387428214d6de49e6a5)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Mon Apr 2 01:37:38 2007 -0700

    G80: Get HW cursor working with RandR 1.2.

diff --git a/src/g80_cursor.c b/src/g80_cursor.c
index f416860..98a2736 100644
--- a/src/g80_cursor.c
+++ b/src/g80_cursor.c
@@ -21,8 +21,6 @@
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if 0
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -37,36 +35,10 @@
 
 #define CURSOR_PTR ((CARD32*)pNv->mem + pNv->videoRam * 256 - 0x1000)
 
-static void G80SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
-{
-    G80Ptr pNv = G80PTR(pScrn);
-    CARD32 *dst = CURSOR_PTR;
-    CARD32 *src = pNv->tmpCursor;
-    int i, j;
-
-    fg |= 0xff000000;
-    bg |= 0xff000000;
-
-    for(i = 0; i < 128; i++) {
-        CARD32 b = *src++;
-        CARD32 m = *src++;
-
-        for(j = 0; j < 32; j++) {
-            if(m & 1)
-                *dst = (b & 1) ? fg : bg;
-            else
-                *dst = 0;
-            b >>= 1;
-            m >>= 1;
-            dst++;
-        }
-    }
-}
-
-static void G80SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+void G80SetCursorPosition(xf86CrtcPtr crtc, int x, int y)
 {
-    G80Ptr pNv = G80PTR(pScrn);
-    const int headOff = 0x1000*pNv->head;
+    G80Ptr pNv = G80PTR(crtc->scrn);
+    const int headOff = 0x1000*G80CrtcGetHead(crtc);
 
     x &= 0xffff;
     y &= 0xffff;
@@ -74,115 +46,58 @@ static void G80SetCursorPosition(ScrnInf
     pNv->reg[(0x00647080 + headOff)/4] = 0;
 }
 
-static void G80LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
-{
-    G80Ptr pNv = G80PTR(pScrn);
-    memcpy(pNv->tmpCursor, bits, sizeof(pNv->tmpCursor));
-}
-
-static void G80HideCursor(ScrnInfoPtr pScrn)
+void G80LoadCursorARGB(xf86CrtcPtr crtc, CARD32 *src)
 {
-    G80Ptr pNv = G80PTR(pScrn);
+    G80Ptr pNv = G80PTR(crtc->scrn);
+    CARD32 *dst = CURSOR_PTR;
 
-    pNv->cursorVisible = FALSE;
-    G80DispHideCursor(G80PTR(pScrn), TRUE);
+    /* Assume cursor is 64x64 */
+    memcpy(dst, src, 64 * 64 * 4);
 }
 
-static void G80ShowCursor(ScrnInfoPtr pScrn)
+Bool G80CursorAcquire(ScrnInfoPtr pScrn)
 {
     G80Ptr pNv = G80PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
 
-    pNv->cursorVisible = TRUE;
-    G80DispShowCursor(G80PTR(pScrn), TRUE);
-}
-
-static Bool G80UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
-{
-    return TRUE;
-}
+    if(!pNv->HWCursor) return TRUE;
 
-#ifdef ARGB_CURSOR
-static Bool G80UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
-{
-    if((pCurs->bits->width <= 64) && (pCurs->bits->height <= 64))
-        return TRUE;
+    /* Initialize the cursor on each head */
+    for(i = 0; i < xf86_config->num_crtc; i++) {
+        const int headOff = 0x10 * G80CrtcGetHead(xf86_config->crtc[i]);
 
-    return FALSE;
-}
+        pNv->reg[(0x00610270+headOff)/4] = 0x2000;
+        while(pNv->reg[(0x00610270+headOff)/4] & 0x30000);
 
-static void G80LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
-{
-    G80Ptr pNv = G80PTR(pScrn);
-    CARD32 *dst = CURSOR_PTR, *src = pCurs->bits->argb;
-    int y;
-
-    for(y = 0; y < pCurs->bits->height; y++) {
-        memcpy(dst, src, pCurs->bits->width * 4);
-        memset(dst + pCurs->bits->width, 0, (64 - pCurs->bits->width) * 4);
-        src += pCurs->bits->width;
-        dst += 64;
+        pNv->reg[(0x00610270+headOff)/4] = 1;
+        while((pNv->reg[(0x00610270+headOff)/4] & 0x30000) != 0x10000);
     }
 
-    memset(dst, 0, (64 - y) * 64 * 4);
-}
-#endif
-
-Bool G80CursorAcquire(G80Ptr pNv)
-{
-    const int headOff = 0x10 * pNv->head;
-
-    if(!pNv->HWCursor) return TRUE;
-
-    pNv->reg[(0x00610270+headOff)/4] = 0x2000;
-    while(pNv->reg[(0x00610270+headOff)/4] & 0x30000);
-
-    pNv->reg[(0x00610270+headOff)/4] = 1;
-    while((pNv->reg[(0x00610270+headOff)/4] & 0x30000) != 0x10000);
-
     return TRUE;
 }
 
-void G80CursorRelease(G80Ptr pNv)
+void G80CursorRelease(ScrnInfoPtr pScrn)
 {
-    const int headOff = 0x10 * pNv->head;
+    G80Ptr pNv = G80PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
 
     if(!pNv->HWCursor) return;
 
-    pNv->reg[(0x00610270+headOff)/4] = 0;
-    while(pNv->reg[(0x00610270+headOff)/4] & 0x30000);
+    /* Release the cursor on each head */
+    for(i = 0; i < xf86_config->num_crtc; i++) {
+        const int headOff = 0x10 * G80CrtcGetHead(xf86_config->crtc[i]);
+
+        pNv->reg[(0x00610270+headOff)/4] = 0;
+        while(pNv->reg[(0x00610270+headOff)/4] & 0x30000);
+    }
 }
 
 Bool G80CursorInit(ScreenPtr pScreen)
 {
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    G80Ptr pNv = G80PTR(pScrn);
-    xf86CursorInfoPtr infoPtr;
-
-    if(!pNv->HWCursor)
-        return TRUE;
-
-    infoPtr = xf86CreateCursorInfoRec();
-    if(!infoPtr) return FALSE;
-
-    pNv->CursorInfo = infoPtr;
-    pNv->cursorVisible = FALSE;
-
-    infoPtr->MaxWidth = infoPtr->MaxHeight = 64;
-    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
-                     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
-    infoPtr->SetCursorColors = G80SetCursorColors;
-    infoPtr->SetCursorPosition = G80SetCursorPosition;
-    infoPtr->LoadCursorImage = G80LoadCursorImage;
-    infoPtr->HideCursor = G80HideCursor;
-    infoPtr->ShowCursor = G80ShowCursor;
-    infoPtr->UseHWCursor = G80UseHWCursor;
-
-#ifdef ARGB_CURSOR
-    infoPtr->UseHWCursorARGB = G80UseHWCursorARGB;
-    infoPtr->LoadCursorARGB = G80LoadCursorARGB;
-#endif
-
-    return xf86InitCursor(pScreen, infoPtr);
+    return xf86_cursors_init(pScreen, 64, 64,
+            HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
+            HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
+            HARDWARE_CURSOR_ARGB);
 }
-
-#endif
diff --git a/src/g80_cursor.h b/src/g80_cursor.h
index 9cd56ee..4d81d80 100644
--- a/src/g80_cursor.h
+++ b/src/g80_cursor.h
@@ -1,3 +1,7 @@
 Bool G80CursorInit(ScreenPtr);
-Bool G80CursorAcquire(G80Ptr);
-void G80CursorRelease(G80Ptr);
+Bool G80CursorAcquire(ScrnInfoPtr);
+void G80CursorRelease(ScrnInfoPtr);
+
+/* CRTC cursor functions */
+void G80SetCursorPosition(xf86CrtcPtr crtc, int x, int y);
+void G80LoadCursorARGB(xf86CrtcPtr crtc, CARD32 *src);
diff --git a/src/g80_display.c b/src/g80_display.c
index 2442e96..a5a1bc8 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -32,6 +32,7 @@
 #include <unistd.h>
 
 #include "g80_type.h"
+#include "g80_cursor.h"
 #include "g80_display.h"
 #include "g80_output.h"
 
@@ -41,8 +42,11 @@
 typedef struct G80CrtcPrivRec {
     Head head;
     int pclk; /* Target pixel clock in kHz */
+    Bool cursorVisible;
 } G80CrtcPrivRec, *G80CrtcPrivPtr;
 
+static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update);
+
 /*
  * PLL calculation.  pclk is in kHz.
  */
@@ -383,10 +387,11 @@ G80CrtcBlankScreen(xf86CrtcPtr crtc, Boo
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     G80Ptr pNv = G80PTR(pScrn);
-    const int headOff = 0x400 * G80CrtcGetHead(crtc);
+    G80CrtcPrivPtr pPriv = crtc->driver_private;
+    const int headOff = 0x400 * pPriv->head;
 
     if(blank) {
-        // G80DispHideCursor(pNv, FALSE);
+        G80CrtcShowHideCursor(crtc, FALSE, FALSE);
 
         C(0x00000840 + headOff, 0);
         C(0x00000844 + headOff, 0);
@@ -405,8 +410,8 @@ G80CrtcBlankScreen(xf86CrtcPtr crtc, Boo
         C(0x00000884 + headOff, (pNv->videoRam << 2) - 0x40);
         if(pNv->architecture != 0x50)
             C(0x0000089C + headOff, 1);
-        // if(pNv->cursorVisible)
-        //     G80DispShowCursor(pNv, FALSE);
+        if(pPriv->cursorVisible)
+            G80CrtcShowHideCursor(crtc, TRUE, FALSE);
         C(0x00000840 + headOff, pScrn->depth == 8 ? 0x80000000 : 0xc0000000);
         C(0x00000844 + headOff, (pNv->videoRam * 1024 - 0x5000) >> 8);
         if(pNv->architecture != 0x50)
@@ -470,33 +475,27 @@ G80CrtcDPMSSet(xf86CrtcPtr crtc, int mod
 }
 
 /******************************** Cursor stuff ********************************/
-void G80CrtcShowCursor(xf86CrtcPtr crtc, Bool update)
+static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
+    G80CrtcPrivPtr pPriv = crtc->driver_private;
     const int headOff = 0x400 * G80CrtcGetHead(crtc);
 
-    C(0x00000880 + headOff, 0x85000000);
-    if(update) C(0x00000080, 0);
+    C(0x00000880 + headOff, show ? 0x85000000 : 0x5000000);
+    if(update) {
+        pPriv->cursorVisible = show;
+        C(0x00000080, 0);
+    }
 }
 
-void G80CrtcHideCursor(xf86CrtcPtr crtc, Bool update)
+void G80CrtcShowCursor(xf86CrtcPtr crtc)
 {
-    ScrnInfoPtr pScrn = crtc->scrn;
-    const int headOff = 0x400 * G80CrtcGetHead(crtc);
-
-    C(0x00000880 + headOff, 0x5000000);
-    if(update) C(0x00000080, 0);
+    G80CrtcShowHideCursor(crtc, TRUE, TRUE);
 }
 
-void G80CrtcSetCursorPosition(xf86CrtcPtr crtc, int x, int y)
+void G80CrtcHideCursor(xf86CrtcPtr crtc)
 {
-    G80Ptr pNv = G80PTR(crtc->scrn);
-    const int headOff = 0x647000 + 0x1000*G80CrtcGetHead(crtc);
-
-    x &= 0xffff;
-    y &= 0xffff;
-    pNv->reg[(0x84 + headOff)/4] = y << 16 | x;
-    pNv->reg[(0x80 + headOff)/4] = 0;
+    G80CrtcShowHideCursor(crtc, FALSE, TRUE);
 }
 
 /******************************** CRTC stuff ********************************/
@@ -564,6 +563,10 @@ static const xf86CrtcFuncsRec g80_crtc_f
     .commit = G80CrtcCommit,
     .shadow_create = NULL,
     .shadow_destroy = NULL,
+    .set_cursor_position = G80SetCursorPosition,
+    .show_cursor = G80CrtcShowCursor,
+    .hide_cursor = G80CrtcHideCursor,
+    .load_cursor_argb = G80LoadCursorARGB,
     .destroy = NULL,
 };
 
diff --git a/src/g80_driver.c b/src/g80_driver.c
index 2a5fceb..6ab92ee 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -397,15 +397,11 @@ fail:
 static Bool
 AcquireDisplay(ScrnInfoPtr pScrn)
 {
-//    G80Ptr pNv = G80PTR(pScrn);
-
     if(!G80DispInit(pScrn))
         return FALSE;
-#if 0
-    if(!G80CursorAcquire(pNv))
-        return FALSE;
-    if(!G80DispSetMode(pScrn, pScrn->currentMode))
+    if(!G80CursorAcquire(pScrn))
         return FALSE;
+#if 0
     G80DispDPMSSet(pScrn, DPMSModeOn, 0);
 #endif
     xf86SetDesiredModes(pScrn);
@@ -421,9 +417,7 @@ ReleaseDisplay(ScrnInfoPtr pScrn)
 {
     G80Ptr pNv = G80PTR(pScrn);
 
-#if 0
-    G80CursorRelease(pNv);
-#endif
+    G80CursorRelease(pScrn);
     G80DispShutdown(pScrn);
 
     if(pNv->int10 && pNv->int10Mode) {
@@ -451,10 +445,7 @@ G80CloseScreen(int scrnIndex, ScreenPtr 
 
     if(pNv->xaa)
         XAADestroyInfoRec(pNv->xaa);
-#if 0
-    if(pNv->HWCursor)
-        xf86DestroyCursorInfoRec(pNv->CursorInfo);
-#endif
+    xf86_cursors_fini(pScreen);
 
     if(xf86ServerIsExiting()) {
         if(pNv->int10) xf86FreeInt10(pNv->int10);
@@ -795,13 +786,11 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
     miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
 
     /* Initialize hardware cursor.  Must follow software cursor initialization. */
-#if 0
     if(pNv->HWCursor && !G80CursorInit(pScreen)) {
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "Hardware cursor initialization failed\n");
         pNv->HWCursor = FALSE;
     }
-#endif
 
     /* Initialize default colormap */
     if(!miCreateDefColormap(pScreen))
diff --git a/src/g80_type.h b/src/g80_type.h
index a8788bc..95517e3 100644
--- a/src/g80_type.h
+++ b/src/g80_type.h
@@ -47,11 +47,6 @@ typedef struct G80Rec {
     Bool                HWCursor;
     Bool                NoAccel;
 
-    /* Cursor */
-    xf86CursorInfoPtr   CursorInfo;
-    Bool                cursorVisible;
-    CARD32              tmpCursor[256]; /* Temporary 1bpp cursor image */
-
     /* XAA */
     XAAInfoRecPtr       xaa;
     CARD32              currentRop;
diff-tree 8f7769aadf175e8298f27387428214d6de49e6a5 (from 2d8d5bd597d760968b683d41ced6a0a76518ec26)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Wed Mar 28 14:10:41 2007 -0700

    G80: Use xf86CrtcScreenInit and xf86SetDesiredModes.

diff --git a/src/g80_driver.c b/src/g80_driver.c
index 4c72bbb..2a5fceb 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -408,8 +408,7 @@ AcquireDisplay(ScrnInfoPtr pScrn)
         return FALSE;
     G80DispDPMSSet(pScrn, DPMSModeOn, 0);
 #endif
-    ErrorF("TODO: Set the current config, rather than using xf86SetSingleMode\n");
-    xf86SetSingleMode(pScrn, pScrn->currentMode, RR_Rotate_0);
+    xf86SetDesiredModes(pScrn);
 
     return TRUE;
 }
@@ -468,7 +467,6 @@ G80CloseScreen(int scrnIndex, ScreenPtr 
     pScrn->vtSema = FALSE;
     pScreen->CloseScreen = pNv->CloseScreen;
     pScreen->BlockHandler = pNv->BlockHandler;
-    pScreen->CreateScreenResources = pNv->CreateScreenResources;
     return (*pScreen->CloseScreen)(scrnIndex, pScreen);
 }
 
@@ -501,21 +499,6 @@ G80SaveScreen(ScreenPtr pScreen, int mod
     return FALSE;
 }
 
-static Bool
-G80CreateScreenResources(ScreenPtr pScreen)
-{
-    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-    G80Ptr pNv = G80PTR(pScrn);
-
-    pScreen->CreateScreenResources = pNv->CreateScreenResources;
-    if(!(*pScreen->CreateScreenResources)(pScreen))
-        return FALSE;
-
-    if(!xf86RandR12CreateScreenResources(pScreen))
-        return FALSE;
-    return TRUE;
- }
-
 static void
 G80InitHW(ScrnInfoPtr pScrn)
 {
@@ -850,19 +833,14 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
 
     pScreen->SaveScreen = G80SaveScreen;
 
-    pNv->CreateScreenResources =  pScreen->CreateScreenResources;
-    pScreen->CreateScreenResources = G80CreateScreenResources;
-
     pNv->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = G80CloseScreen;
 
     pNv->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = G80BlockHandler;
 
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR 1.2 enabled. Please ignore the following RandR disabled message.\n");
-    xf86DisableRandR();
-    xf86RandR12Init(pScreen);
-    xf86RandR12SetRotations(pScreen, RR_Rotate_0);
+    if(!xf86CrtcScreenInit(pScreen))
+        return FALSE;
 
     return TRUE;
 }
diff --git a/src/g80_type.h b/src/g80_type.h
index 6c031c4..a8788bc 100644
--- a/src/g80_type.h
+++ b/src/g80_type.h
@@ -64,7 +64,6 @@ typedef struct G80Rec {
     CARD32 *            dmaBase;
     void              (*DMAKickoffCallback)(ScrnInfoPtr);
 
-    CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr           CloseScreen;
     ScreenBlockHandlerProcPtr    BlockHandler;
 } G80Rec, *G80Ptr;
diff-tree 2d8d5bd597d760968b683d41ced6a0a76518ec26 (from 4b8ed8497a9ab6ef1316bfcce9f31d96dd4b3540)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Tue Mar 27 17:12:21 2007 -0700

    G80: Improve output detection.
    
    Detect output status for paired outputs together and cache status until the
    BlockHandler to avoid redundantly probing for EDIDs or performing load
    detection.

diff --git a/src/g80_dac.c b/src/g80_dac.c
index bb86748..ac82616 100644
--- a/src/g80_dac.c
+++ b/src/g80_dac.c
@@ -76,6 +76,19 @@ G80DacModeSet(xf86OutputPtr output, Disp
 static xf86OutputStatus
 G80DacDetect(xf86OutputPtr output)
 {
+    G80OutputPrivPtr pPriv = output->driver_private;
+
+    /* Assume physical status isn't going to change before the BlockHandler */
+    if(pPriv->cached_status != XF86OutputStatusUnknown)
+        return pPriv->cached_status;
+
+    G80OutputPartnersDetect(output, pPriv->partner, pPriv->i2c);
+    return pPriv->cached_status;
+}
+
+Bool
+G80DacLoadDetect(xf86OutputPtr output)
+{
     ScrnInfoPtr pScrn = output->scrn;
     G80Ptr pNv = G80PTR(pScrn);
     G80OutputPrivPtr pPriv = output->driver_private;
@@ -99,11 +112,11 @@ G80DacDetect(xf86OutputPtr output)
     // Use this DAC if all three channels show load.
     if((load & 0x38000000) == 0x38000000) {
         xf86ErrorF("found one!\n");
-        return XF86OutputStatusConnected;
+        return TRUE;
     }
 
     xf86ErrorF("nothing.\n");
-    return XF86OutputStatusDisconnected;
+    return FALSE;
 }
 
 static void
@@ -144,6 +157,7 @@ G80CreateDac(ScrnInfoPtr pScrn, ORNum or
 
     pPriv->type = DAC;
     pPriv->or = or;
+    pPriv->cached_status = XF86OutputStatusUnknown;
     pPriv->set_pclk = G80DacSetPClk;
     output->driver_private = pPriv;
     output->interlaceAllowed = TRUE;
diff --git a/src/g80_driver.c b/src/g80_driver.c
index 8dff209..4c72bbb 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -482,6 +482,8 @@ G80BlockHandler(int i, pointer blockData
     if(pNv->DMAKickoffCallback)
         (*pNv->DMAKickoffCallback)(pScrnInfo);
 
+    G80OutputResetCachedStatus(pScrnInfo);
+
     pScreen->BlockHandler = pNv->BlockHandler;
     (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
     pScreen->BlockHandler = G80BlockHandler;
diff --git a/src/g80_output.c b/src/g80_output.c
index d847e2e..a3b28a5 100644
--- a/src/g80_output.c
+++ b/src/g80_output.c
@@ -188,26 +188,21 @@ G80OutputCommit(xf86OutputPtr output)
 {
 }
 
-DisplayModePtr
-G80OutputGetDDCModes(xf86OutputPtr output)
+static xf86MonPtr
+ProbeDDC(I2CBusPtr i2c)
 {
-    ScrnInfoPtr pScrn = output->scrn;
+    ScrnInfoPtr pScrn = xf86Screens[i2c->scrnIndex];
     G80Ptr pNv = G80PTR(pScrn);
-    G80OutputPrivPtr pPriv = output->driver_private;
-    I2CBusPtr i2c = pPriv->i2c;
     xf86MonPtr monInfo = NULL;
-    DisplayModePtr modes;
     const int bus = i2c->DriverPrivate.val, off = bus * 0x18;
 
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
             "Probing for EDID on I2C bus %i...\n", bus);
     pNv->reg[(0x0000E138+off)/4] = 7;
-    monInfo = xf86OutputGetEDID(output, i2c);
+    /* Should probably use xf86OutputGetEDID here */
+    monInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, i2c);
     pNv->reg[(0x0000E138+off)/4] = 3;
 
-    xf86OutputSetEDID(output, monInfo);
-    modes = xf86OutputGetEDIDModes(output);
-
     if(monInfo) {
         xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
                 "DDC detected a %s:\n", monInfo->features.input_type ?
@@ -217,7 +212,67 @@ G80OutputGetDDCModes(xf86OutputPtr outpu
         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "  ... none found\n");
     }
 
-    return modes;
+    return monInfo;
+}
+
+/*
+ * Read an EDID from the i2c port.  Perform load detection on the DAC (if
+ * present) to see if the display is connected via VGA.  Sets the cached status
+ * of both outputs.  The status is marked dirty again in the BlockHandler.
+ */
+void G80OutputPartnersDetect(xf86OutputPtr dac, xf86OutputPtr sor, I2CBusPtr i2c)
+{
+    xf86MonPtr monInfo = ProbeDDC(i2c);
+    xf86OutputPtr connected = NULL;
+    Bool load = dac && G80DacLoadDetect(dac);
+
+    if(dac) {
+        G80OutputPrivPtr pPriv = dac->driver_private;
+
+        if(load) {
+            pPriv->cached_status = XF86OutputStatusConnected;
+            connected = dac;
+        } else {
+            pPriv->cached_status = XF86OutputStatusDisconnected;
+        }
+    }
+
+    if(sor) {
+        G80OutputPrivPtr pPriv = sor->driver_private;
+
+        if(monInfo && !load) {
+            pPriv->cached_status = XF86OutputStatusConnected;
+            connected = sor;
+        } else {
+            pPriv->cached_status = XF86OutputStatusDisconnected;
+        }
+    }
+
+    if(connected)
+        xf86OutputSetEDID(connected, monInfo);
+}
+
+/*
+ * Reset the cached output status for all outputs.  Called from G80BlockHandler.
+ */
+void
+G80OutputResetCachedStatus(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    for(i = 0; i < xf86_config->num_output; i++) {
+        G80OutputPrivPtr pPriv = xf86_config->output[i]->driver_private;
+        pPriv->cached_status = XF86OutputStatusUnknown;
+    }
+}
+
+DisplayModePtr
+G80OutputGetDDCModes(xf86OutputPtr output)
+{
+    /* The EDID is read as part of the detect step */
+    output->funcs->detect(output);
+    return xf86OutputGetEDIDModes(output);
 }
 
 void
diff --git a/src/g80_output.h b/src/g80_output.h
index 819df15..0b666f5 100644
--- a/src/g80_output.h
+++ b/src/g80_output.h
@@ -5,6 +5,8 @@ typedef struct G80OutputPrivRec {
     xf86OutputPtr partner;
     I2CBusPtr i2c;
 
+    xf86OutputStatus cached_status;
+
     void (*set_pclk)(xf86OutputPtr, int pclk);
 } G80OutputPrivRec, *G80OutputPrivPtr;
 
@@ -13,12 +15,15 @@ int G80OutputModeValid(xf86OutputPtr, Di
 Bool G80OutputModeFixup(xf86OutputPtr, DisplayModePtr mode, DisplayModePtr adjusted_mode);
 void G80OutputPrepare(xf86OutputPtr);
 void G80OutputCommit(xf86OutputPtr);
+void G80OutputPartnersDetect(xf86OutputPtr dac, xf86OutputPtr sor, I2CBusPtr i2c);
+void G80OutputResetCachedStatus(ScrnInfoPtr);
 DisplayModePtr G80OutputGetDDCModes(xf86OutputPtr);
 void G80OutputDestroy(xf86OutputPtr);
 Bool G80CreateOutputs(ScrnInfoPtr);
 
 /* g80_dac.c */
 xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum);
+Bool G80DacLoadDetect(xf86OutputPtr);
 
 /* g80_sor.c */
 xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum);
diff --git a/src/g80_sor.c b/src/g80_sor.c
index 55a643f..fe34e7e 100644
--- a/src/g80_sor.c
+++ b/src/g80_sor.c
@@ -25,8 +25,6 @@
 #include "config.h"
 #endif
 
-#include <X11/Xatom.h>
-
 #include "g80_type.h"
 #include "g80_display.h"
 #include "g80_output.h"
@@ -74,20 +72,15 @@ G80SorModeSet(xf86OutputPtr output, Disp
 static xf86OutputStatus
 G80SorDetect(xf86OutputPtr output)
 {
-    return XF86OutputStatusUnknown;
 
-#if 0
-    DisplayModePtr modes = output->funcs->get_modes(output);
-    xf86OutputStatus status;
-
-    if(modes)
-        status = XF86OutputStatusConnected;
-    else
-        status = XF86OutputStatusDisconnected;
-    xfree(modes);
+    G80OutputPrivPtr pPriv = output->driver_private;
+
+    /* Assume physical status isn't going to change before the BlockHandler */
+    if(pPriv->cached_status != XF86OutputStatusUnknown)
+        return pPriv->cached_status;
 
-    return status;
-#endif
+    G80OutputPartnersDetect(pPriv->partner, output, pPriv->i2c);
+    return pPriv->cached_status;
 }
 
 static void
@@ -128,6 +121,7 @@ G80CreateSor(ScrnInfoPtr pScrn, ORNum or
 
     pPriv->type = SOR;
     pPriv->or = or;
+    pPriv->cached_status = XF86OutputStatusUnknown;
     pPriv->set_pclk = G80SorSetPClk;
     output->driver_private = pPriv;
     output->interlaceAllowed = TRUE;
diff-tree 4b8ed8497a9ab6ef1316bfcce9f31d96dd4b3540 (from ad4abba20b8a6db7b52898bc7159809539cbed43)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Tue Mar 27 13:33:11 2007 -0700

    G80: Create output partners.
    
    Each pair of outputs shares an I2C rec.  This will be used in a future change
    for the detect and get_modes routines.

diff --git a/src/g80_dac.c b/src/g80_dac.c
index 991e3be..bb86748 100644
--- a/src/g80_dac.c
+++ b/src/g80_dac.c
@@ -130,7 +130,7 @@ static const xf86OutputFuncsRec G80DacOu
 };
 
 xf86OutputPtr
-G80CreateDac(ScrnInfoPtr pScrn, ORNum or, int i2cPort)
+G80CreateDac(ScrnInfoPtr pScrn, ORNum or)
 {
     G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1);
     xf86OutputPtr output;
@@ -149,8 +149,5 @@ G80CreateDac(ScrnInfoPtr pScrn, ORNum or
     output->interlaceAllowed = TRUE;
     output->doubleScanAllowed = TRUE;
 
-    /* Create an I2C object */
-    G80I2CInit(output, i2cPort);
-
     return output;
 }
diff --git a/src/g80_output.c b/src/g80_output.c
index b56bf00..d847e2e 100644
--- a/src/g80_output.c
+++ b/src/g80_output.c
@@ -127,18 +127,17 @@ static void G80_I2CGetBits(I2CBusPtr b, 
     *data = !!(val & 2);
 }
 
-Bool
-G80I2CInit(xf86OutputPtr output, const int port)
+static I2CBusPtr
+G80I2CInit(ScrnInfoPtr pScrn, const char *name, const int port)
 {
-    G80OutputPrivPtr pPriv = output->driver_private;
     I2CBusPtr i2c;
 
     /* Allocate the I2C bus structure */
     i2c = xf86CreateI2CBusRec();
-    if(!i2c) return FALSE;
+    if(!i2c) return NULL;
 
-    i2c->BusName = output->name;
-    i2c->scrnIndex = output->scrn->scrnIndex;
+    i2c->BusName = strdup(name);
+    i2c->scrnIndex = pScrn->scrnIndex;
     i2c->I2CPutBits = G80_I2CPutBits;
     i2c->I2CGetBits = G80_I2CGetBits;
     i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
@@ -149,11 +148,10 @@ G80I2CInit(xf86OutputPtr output, const i
     i2c->DriverPrivate.val = port;
 
     if(xf86I2CBusInit(i2c)) {
-        pPriv->i2c = i2c;
-        return TRUE;
+        return i2c;
     } else {
         xfree(i2c);
-        return FALSE;
+        return NULL;
     }
 }
 
@@ -227,7 +225,10 @@ G80OutputDestroy(xf86OutputPtr output)
 {
     G80OutputPrivPtr pPriv = output->driver_private;
 
-    xf86DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE);
+    if(pPriv->partner)
+        ((G80OutputPrivPtr)pPriv->partner->driver_private)->partner = NULL;
+    else
+        xf86DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE);
     pPriv->i2c = NULL;
 }
 
@@ -243,10 +244,40 @@ G80CreateOutputs(ScrnInfoPtr pScrn)
 
     /* For each DDC port, create an output for the attached ORs */
     for(i = 0; i < 4; i++) {
+        xf86OutputPtr dac = NULL, sor = NULL;
+        I2CBusPtr i2c;
+        char i2cName[16];
+
+        if(pNv->i2cMap[i].dac == -1 && pNv->i2cMap[i].sor == -1)
+            /* No outputs on this port */
+            continue;
+
+        snprintf(i2cName, sizeof(i2cName), "I2C%i", i);
+        i2c = G80I2CInit(pScrn, i2cName, i);
+        if(!i2c) {
+            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "Failed to initialize I2C for port %i.\n",
+                       i);
+            continue;
+        }
+
         if(pNv->i2cMap[i].dac != -1)
-            G80CreateDac(pScrn, pNv->i2cMap[i].dac, i);
+            dac = G80CreateDac(pScrn, pNv->i2cMap[i].dac);
         if(pNv->i2cMap[i].sor != -1)
-            G80CreateSor(pScrn, pNv->i2cMap[i].sor, i);
+            sor = G80CreateSor(pScrn, pNv->i2cMap[i].sor);
+
+        if(dac) {
+            G80OutputPrivPtr pPriv = dac->driver_private;
+
+            pPriv->partner = sor;
+            pPriv->i2c = i2c;
+        }
+        if(sor) {
+            G80OutputPrivPtr pPriv = sor->driver_private;
+
+            pPriv->partner = dac;
+            pPriv->i2c = i2c;
+        }
     }
 
     /* For each output, set the crtc and clone masks */
@@ -260,4 +291,3 @@ G80CreateOutputs(ScrnInfoPtr pScrn)
 
     return TRUE;
 }
-
diff --git a/src/g80_output.h b/src/g80_output.h
index efc9a16..819df15 100644
--- a/src/g80_output.h
+++ b/src/g80_output.h
@@ -2,12 +2,12 @@ typedef struct G80OutputPrivRec {
     ORType type;
     ORNum or;
 
+    xf86OutputPtr partner;
     I2CBusPtr i2c;
 
     void (*set_pclk)(xf86OutputPtr, int pclk);
 } G80OutputPrivRec, *G80OutputPrivPtr;
 
-Bool G80I2CInit(xf86OutputPtr, const int port);
 void G80OutputSetPClk(xf86OutputPtr, int pclk);
 int G80OutputModeValid(xf86OutputPtr, DisplayModePtr);
 Bool G80OutputModeFixup(xf86OutputPtr, DisplayModePtr mode, DisplayModePtr adjusted_mode);
@@ -18,7 +18,7 @@ void G80OutputDestroy(xf86OutputPtr);
 Bool G80CreateOutputs(ScrnInfoPtr);
 
 /* g80_dac.c */
-xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum, int i2cPort);
+xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum);
 
 /* g80_sor.c */
-xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum, int i2cPort);
+xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum);
diff --git a/src/g80_sor.c b/src/g80_sor.c
index 7d377a8..55a643f 100644
--- a/src/g80_sor.c
+++ b/src/g80_sor.c
@@ -114,7 +114,7 @@ static const xf86OutputFuncsRec G80SorOu
 };
 
 xf86OutputPtr
-G80CreateSor(ScrnInfoPtr pScrn, ORNum or, int i2cPort)
+G80CreateSor(ScrnInfoPtr pScrn, ORNum or)
 {
     G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1);
     xf86OutputPtr output;
@@ -133,8 +133,5 @@ G80CreateSor(ScrnInfoPtr pScrn, ORNum or
     output->interlaceAllowed = TRUE;
     output->doubleScanAllowed = TRUE;
 
-    /* Create an I2C object */
-    G80I2CInit(output, i2cPort);
-
     return output;
 }
diff-tree ad4abba20b8a6db7b52898bc7159809539cbed43 (from 7e0e5c1fb38922add99db33f282baf2ee1531685)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Tue Mar 27 14:49:30 2007 -0700

    Fix warnings.

diff --git a/src/g80_display.c b/src/g80_display.c
index b9882da..2442e96 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -322,7 +322,6 @@ G80CrtcModeSet(xf86CrtcPtr crtc, Display
                DisplayModePtr adjusted_mode, int x, int y)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
-    G80Ptr pNv = G80PTR(pScrn);
     G80CrtcPrivPtr pPriv = crtc->driver_private;
     const int HDisplay = mode->HDisplay, VDisplay = mode->VDisplay;
     const int headOff = 0x400 * G80CrtcGetHead(crtc);
diff --git a/src/g80_driver.c b/src/g80_driver.c
index 6d19cce..8dff209 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -30,6 +30,7 @@
 
 #include <xf86_OSproc.h>
 #include <xf86Resources.h>
+#include <xf86RandR12.h>
 #include <mipointer.h>
 #include <mibstore.h>
 #include <micmap.h>
@@ -44,6 +45,7 @@
 #include "g80_display.h"
 #include "g80_ddc.h"
 #include "g80_dma.h"
+#include "g80_output.h"
 #include "g80_xaa.h"
 
 #define G80_REG_SIZE (1024 * 1024 * 16)
@@ -119,6 +121,7 @@ G80FreeRec(ScrnInfoPtr pScrn)
     pScrn->driverPrivate = NULL;
 }
 
+static Bool
 G80ResizeScreen(ScrnInfoPtr pScrn, int width, int height)
 {
     G80Ptr pNv = G80PTR(pScrn);
@@ -161,7 +164,6 @@ G80PreInit(ScrnInfoPtr pScrn, int flags)
     PCITAG pcitag;
     MessageType from;
     Bool primary;
-    char *s;
     const rgb zeros = {0, 0, 0};
     const Gamma gzeros = {0.0, 0.0, 0.0};
     CARD32 tmp;
@@ -395,7 +397,7 @@ fail:
 static Bool
 AcquireDisplay(ScrnInfoPtr pScrn)
 {
-    G80Ptr pNv = G80PTR(pScrn);
+//    G80Ptr pNv = G80PTR(pScrn);
 
     if(!G80DispInit(pScrn))
         return FALSE;
diff --git a/src/g80_output.c b/src/g80_output.c
index 481dd85..b56bf00 100644
--- a/src/g80_output.c
+++ b/src/g80_output.c
@@ -236,7 +236,7 @@ G80CreateOutputs(ScrnInfoPtr pScrn)
 {
     G80Ptr pNv = G80PTR(pScrn);
     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i, count = 0;
+    int i;
 
     if(!G80ReadPortMapping(pScrn->scrnIndex, pNv))
         return FALSE;
@@ -252,7 +252,6 @@ G80CreateOutputs(ScrnInfoPtr pScrn)
     /* For each output, set the crtc and clone masks */
     for(i = 0; i < xf86_config->num_output; i++) {
         xf86OutputPtr output = xf86_config->output[i];
-        G80OutputPrivPtr pPriv = output->driver_private;
 
         /* Any output can connect to any head */
         output->possible_crtcs = 0x3;
diff-tree 7e0e5c1fb38922add99db33f282baf2ee1531685 (from 636adcd57f1c5b33edf2d8fbf9e7fa9aac1ccb1a)
Author: root <root at treble.(none)>
Date:   Sun Mar 11 00:38:11 2007 -0800

    Initial RandR 1.2 support for G80.
    
    Mostly just rearranging code.

diff --git a/src/Makefile.am b/src/Makefile.am
index b7c1128..d024283 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -70,13 +70,15 @@ if SUPPORT_G80
 g80_sources = \
          g80_cursor.c \
          g80_cursor.h \
-         g80_ddc.c \
-         g80_ddc.h \
+         g80_dac.c \
          g80_display.c \
          g80_display.h \
          g80_dma.c \
          g80_dma.h \
          g80_driver.c \
+         g80_output.c \
+         g80_output.h \
+         g80_sor.c \
          g80_type.h \
          g80_xaa.c \
          g80_xaa.h
diff --git a/src/g80_dac.c b/src/g80_dac.c
new file mode 100644
index 0000000..991e3be
--- /dev/null
+++ b/src/g80_dac.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2007 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include "g80_type.h"
+#include "g80_display.h"
+#include "g80_output.h"
+
+static void
+G80DacSetPClk(xf86OutputPtr output, int pclk)
+{
+    G80Ptr pNv = G80PTR(output->scrn);
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int orOff = 0x800 * pPriv->or;
+
+    pNv->reg[(0x00614280+orOff)/4] = 0;
+}
+
+static void
+G80DacDPMSSet(xf86OutputPtr output, int mode)
+{
+    ErrorF("DAC dpms unimplemented\n");
+}
+
+static void
+G80DacModeSet(xf86OutputPtr output, DisplayModePtr mode,
+              DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int dacOff = 0x80 * pPriv->or;
+
+    if(adjusted_mode)
+        ErrorF("DAC%i mode %s -> HEAD%i\n", pPriv->or, adjusted_mode->name, G80CrtcGetHead(output->crtc));
+
+    if(!adjusted_mode) {
+        C(0x00000400 + dacOff, 0);
+        return;
+    }
+
+    C(0x00000400 + dacOff,
+        (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | 0x40);
+    C(0x00000404 + dacOff,
+        (adjusted_mode->Flags & V_NHSYNC) ? 1 : 0 |
+        (adjusted_mode->Flags & V_NVSYNC) ? 2 : 0);
+}
+
+/*
+ * Perform DAC load detection to determine if there is a connected display.
+ */
+static xf86OutputStatus
+G80DacDetect(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    G80Ptr pNv = G80PTR(pScrn);
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int scrnIndex = pScrn->scrnIndex;
+    const int dacOff = 2048 * pPriv->or;
+    CARD32 load, tmp;
+
+    xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on VGA%i ... ",
+            pPriv->or);
+
+    pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001;
+    pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000;
+    while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000);
+    tmp = pNv->architecture == 0x50 ? 420 : 340;
+    pNv->reg[(0x0061A00C+dacOff)/4] = tmp | 0x100000;
+    usleep(4500);
+    load = pNv->reg[(0x0061A00C+dacOff)/4];
+    pNv->reg[(0x0061A00C+dacOff)/4] = 0;
+    pNv->reg[(0x0061A004+dacOff)/4] = 0x80550000;
+
+    // Use this DAC if all three channels show load.
+    if((load & 0x38000000) == 0x38000000) {
+        xf86ErrorF("found one!\n");
+        return XF86OutputStatusConnected;
+    }
+
+    xf86ErrorF("nothing.\n");
+    return XF86OutputStatusDisconnected;
+}
+
+static void
+G80DacDestroy(xf86OutputPtr output)
+{
+    G80OutputDestroy(output);
+
+    xfree(output->driver_private);
+    output->driver_private = NULL;
+}
+
+static const xf86OutputFuncsRec G80DacOutputFuncs = {
+    .dpms = G80DacDPMSSet,
+    .save = NULL,
+    .restore = NULL,
+    .mode_valid = G80OutputModeValid,
+    .mode_fixup = G80OutputModeFixup,
+    .prepare = G80OutputPrepare,
+    .commit = G80OutputCommit,
+    .mode_set = G80DacModeSet,
+    .detect = G80DacDetect,
+    .get_modes = G80OutputGetDDCModes,
+    .destroy = G80DacDestroy,
+};
+
+xf86OutputPtr
+G80CreateDac(ScrnInfoPtr pScrn, ORNum or, int i2cPort)
+{
+    G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1);
+    xf86OutputPtr output;
+    char orName[5];
+
+    if(!pPriv)
+        return FALSE;
+
+    snprintf(orName, 5, "VGA%i", or);
+    output = xf86OutputCreate(pScrn, &G80DacOutputFuncs, orName);
+
+    pPriv->type = DAC;
+    pPriv->or = or;
+    pPriv->set_pclk = G80DacSetPClk;
+    output->driver_private = pPriv;
+    output->interlaceAllowed = TRUE;
+    output->doubleScanAllowed = TRUE;
+
+    /* Create an I2C object */
+    G80I2CInit(output, i2cPort);
+
+    return output;
+}
diff --git a/src/g80_ddc.c b/src/g80_ddc.c
deleted file mode 100644
index bcc4bff..0000000
--- a/src/g80_ddc.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2007 NVIDIA, Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <strings.h>
-#include <xf86DDC.h>
-
-#include "g80_type.h"
-#include "g80_ddc.h"
-
-static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
-{
-    unsigned char *table2;
-    unsigned char headerSize, entries;
-    int i;
-    CARD16 a;
-    CARD32 b;
-
-    /* Clear the i2c map to invalid */
-    for(i = 0; i < 4; i++)
-        pNv->i2cMap[i].dac = pNv->i2cMap[i].sor = -1;
-
-    if(*(CARD16*)pNv->table1 != 0xaa55) goto fail;
-
-    a = *(CARD16*)(pNv->table1 + 0x36);
-    table2 = (unsigned char*)pNv->table1 + a;
-
-    if(table2[0] != 0x40) goto fail;
-
-    b = *(CARD32*)(table2 + 6);
-    if(b != 0x4edcbdcb) goto fail;
-
-    headerSize = table2[1];
-    entries = table2[2];
-
-    for(i = 0; i < entries; i++) {
-        CARD32 type, port;
-        ORNum or;
-
-        b = *(CARD32*)&table2[headerSize + 8*i];
-        type = b & 0xf;
-        port = (b >> 4) & 0xf;
-        or = ffs((b >> 24) & 0xf) - 1;
-
-        if(type < 4 && port != 0xf) {
-            switch(type) {
-                case 0: /* CRT */
-                case 1: /* TV */
-                    if(pNv->i2cMap[port].dac != -1) {
-                        xf86DrvMsg(scrnIndex, X_WARNING,
-                                   "DDC routing table corrupt!  DAC %i -> %i "
-                                   "for port %i\n",
-                                   or, pNv->i2cMap[port].dac, port);
-                    }
-                    pNv->i2cMap[port].dac = or;
-                    break;
-                case 2: /* TMDS */
-                case 3: /* LVDS */
-                    if(pNv->i2cMap[port].sor != -1)
-                        xf86DrvMsg(scrnIndex, X_WARNING,
-                                   "DDC routing table corrupt!  SOR %i -> %i "
-                                   "for port %i\n",
-                                   or, pNv->i2cMap[port].sor, port);
-                    pNv->i2cMap[port].sor = or;
-                    break;
-            }
-        }
-    }
-
-    xf86DrvMsg(scrnIndex, X_PROBED, "I2C map:\n");
-    for(i = 0; i < 4; i++) {
-        if(pNv->i2cMap[i].dac != -1)
-            xf86DrvMsg(scrnIndex, X_PROBED, "  Bus %i -> DAC%i\n", i, pNv->i2cMap[i].dac);
-        if(pNv->i2cMap[i].sor != -1)
-            xf86DrvMsg(scrnIndex, X_PROBED, "  Bus %i -> SOR%i\n", i, pNv->i2cMap[i].sor);
-    }
-
-    return TRUE;
-
-fail:
-    xf86DrvMsg(scrnIndex, X_ERROR, "Couldn't find the DDC routing table.  "
-               "Mode setting will probably fail!\n");
-    return FALSE;
-}
-
-static void G80_I2CPutBits(I2CBusPtr b, int clock, int data)
-{
-    G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
-    const int off = b->DriverPrivate.val;
-
-    pNv->reg[(0x0000E138+off)/4] = 4 | clock | data << 1;
-}
-
-static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data)
-{
-    G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
-    const int off = b->DriverPrivate.val;
-    unsigned char val;
-
-    val = pNv->reg[(0x0000E138+off)/4];
-    *clock = !!(val & 1);
-    *data = !!(val & 2);
-}
-
-static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus)
-{
-    G80Ptr pNv = G80PTR(pScrn);
-    I2CBusPtr i2c;
-    xf86MonPtr monInfo = NULL;
-    const int off = bus * 0x18;
-
-    /* Allocate the I2C bus structure */
-    i2c = xf86CreateI2CBusRec();
-    if(!i2c) return NULL;
-
-    i2c->BusName = "DDC";
-    i2c->scrnIndex = pScrn->scrnIndex;
-    i2c->I2CPutBits = G80_I2CPutBits;
-    i2c->I2CGetBits = G80_I2CGetBits;
-    i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
-    i2c->StartTimeout = 550;
-    i2c->BitTimeout = 40;
-    i2c->ByteTimeout = 40;
-    i2c->AcknTimeout = 40;
-    i2c->DriverPrivate.val = off;
-
-    if(!xf86I2CBusInit(i2c)) goto done;
-
-    pNv->reg[(0x0000E138+off)/4] = 7;
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-            "Probing for EDID on I2C bus %i...\n", bus);
-    monInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, i2c);
-
-    pNv->reg[(0x0000E138+off)/4] = 3;
-
-    if(monInfo) {
-        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-                "DDC detected a %s:\n", monInfo->features.input_type ?
-                "DFP" : "CRT");
-        xf86PrintEDID(monInfo);
-    } else {
-        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "  ... none found\n");
-    }
-
-done:
-    xf86DestroyI2CBusRec(i2c, TRUE, TRUE);
-
-    return monInfo;
-}
-
-/*
- * Try DDC on each bus until we find one that works.
- */
-Bool G80ProbeDDC(ScrnInfoPtr pScrn)
-{
-    G80Ptr pNv = G80PTR(pScrn);
-    xf86MonPtr monInfo;
-    int port;
-    Bool flatPanel;
-
-    if(!G80ReadPortMapping(pScrn->scrnIndex, pNv))
-        return FALSE;
-
-    for(port = 0; port < 4; port++) {
-        if(pNv->i2cMap[port].dac == -1 && pNv->i2cMap[port].sor == -1)
-            /* No outputs on this port.  Skip it. */
-            continue;
-
-        monInfo = G80ProbeDDCBus(pScrn, port);
-        if(!monInfo)
-            /* No EDID on this port. */
-            continue;
-
-        flatPanel = (monInfo->features.input_type == 1);
-
-        if(pNv->i2cMap[port].dac != -1 &&
-           G80DispDetectLoad(pScrn, pNv->i2cMap[port].dac)) {
-            pNv->orType = DAC;
-            pNv->or = pNv->i2cMap[port].dac;
-        } else if(pNv->i2cMap[port].sor != -1) {
-            pNv->orType = SOR;
-            pNv->or = pNv->i2cMap[port].sor;
-        } else {
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-                       "Saw an EDID on I2C port %i but no DAC load was "
-                       "detected and no SOR is connected to this port.  Using "
-                       "DAC%i.\n", port,
-                       pNv->or);
-            pNv->orType = DAC;
-            pNv->or = pNv->i2cMap[port].dac;
-        }
-
-        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-                   "Found a %s on I2C port %i, assigning %s%i\n",
-                   flatPanel ? "flat panel" : "CRT",
-                   port, pNv->orType == SOR ? "SOR" : "DAC", pNv->or);
-
-        pScrn->monitor->DDC = monInfo;
-        xf86SetDDCproperties(pScrn, monInfo);
-
-        return TRUE;
-    }
-
-    return FALSE;
-}
diff --git a/src/g80_display.c b/src/g80_display.c
index 95c3d34..b9882da 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -33,10 +33,16 @@
 
 #include "g80_type.h"
 #include "g80_display.h"
+#include "g80_output.h"
 
 #define DPMS_SERVER
 #include <X11/extensions/dpms.h>
 
+typedef struct G80CrtcPrivRec {
+    Head head;
+    int pclk; /* Target pixel clock in kHz */
+} G80CrtcPrivRec, *G80CrtcPrivPtr;
+
 /*
  * PLL calculation.  pclk is in kHz.
  */
@@ -137,8 +143,42 @@ G80CalcPLL(float pclk, int *pNA, int *pM
 }
 
 static void
-G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data)
+G80CrtcSetPClk(xf86CrtcPtr crtc)
 {
+    G80Ptr pNv = G80PTR(crtc->scrn);
+    G80CrtcPrivPtr pPriv = crtc->driver_private;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+    const int headOff = 0x800 * pPriv->head;
+    int lo_n, lo_m, hi_n, hi_m, p, i;
+    CARD32 lo = pNv->reg[(0x00614104+headOff)/4];
+    CARD32 hi = pNv->reg[(0x00614108+headOff)/4];
+
+    pNv->reg[(0x00614100+headOff)/4] = 0x10000610;
+    lo &= 0xff00ff00;
+    hi &= 0x8000ff00;
+
+    G80CalcPLL(pPriv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p);
+
+    lo |= (lo_m << 16) | lo_n;
+    hi |= (p << 28) | (hi_m << 16) | hi_n;
+    pNv->reg[(0x00614104+headOff)/4] = lo;
+    pNv->reg[(0x00614108+headOff)/4] = hi;
+    pNv->reg[(0x00614200+headOff)/4] = 0;
+
+    for(i = 0; i < xf86_config->num_output; i++) {
+        xf86OutputPtr output = xf86_config->output[i];
+
+        if(output->crtc != crtc)
+            continue;
+        G80OutputSetPClk(output, pPriv->pclk);
+    }
+}
+
+void
+G80DispCommand(ScrnInfoPtr pScrn, CARD32 addr, CARD32 data)
+{
+    G80Ptr pNv = G80PTR(pScrn);
+
     pNv->reg[0x00610304/4] = data;
     pNv->reg[0x00610300/4] = addr | 0x80010001;
 
@@ -147,35 +187,17 @@ G80DispCommand(G80Ptr pNv, CARD32 addr, 
 
         if(super) {
             if(super == 2) {
-                const int headOff = 0x800 * pNv->head;
-                const int orOff = 0x800 * pNv->or;
+                xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+                const CARD32 r = pNv->reg[0x00610030/4];
+                int i;
 
-                if(pNv->reg[0x00610030/4] & 0x600) {
-                    int lo_n, lo_m, hi_n, hi_m, p;
-                    CARD32 lo = pNv->reg[(0x00614104+headOff)/4];
-                    CARD32 hi = pNv->reg[(0x00614108+headOff)/4];
-
-                    pNv->reg[(0x00614100+headOff)/4] = 0x10000610;
-                    lo &= 0xff00ff00;
-                    hi &= 0x8000ff00;
-
-                    G80CalcPLL(pNv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p);
-
-                    lo |= (lo_m << 16) | lo_n;
-                    hi |= (p << 28) | (hi_m << 16) | hi_n;
-                    pNv->reg[(0x00614104+headOff)/4] = lo;
-                    pNv->reg[(0x00614108+headOff)/4] = hi;
-                }
+                for(i = 0; i < xf86_config->num_crtc; i++)
+                {
+                    xf86CrtcPtr crtc = xf86_config->crtc[i];
+                    G80CrtcPrivPtr pPriv = crtc->driver_private;
 
-                pNv->reg[(0x00614200+headOff)/4] = 0;
-                switch(pNv->orType) {
-                case DAC:
-                    pNv->reg[(0x00614280+orOff)/4] = 0;
-                    break;
-                case SOR:
-                    pNv->reg[(0x00614300+orOff)/4] =
-                        (pNv->pclk > 165000) ? 0x101 : 0;
-                    break;
+                    if(r & (0x200 << pPriv->head))
+                        G80CrtcSetPClk(crtc);
                 }
             }
 
@@ -184,59 +206,16 @@ G80DispCommand(G80Ptr pNv, CARD32 addr, 
         }
     }
 }
-#define C(mthd, data) G80DispCommand(pNv, (mthd), (data))
 
-/*
- * Performs load detection on a single DAC.
- */
-Bool G80DispDetectLoad(ScrnInfoPtr pScrn, ORNum or)
+Head
+G80CrtcGetHead(xf86CrtcPtr crtc)
 {
-    G80Ptr pNv = G80PTR(pScrn);
-    const int dacOff = 2048 * or;
-    CARD32 load, tmp;
-
-    pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001;
-    pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000;
-    while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000);
-    tmp = pNv->architecture == 0x50 ? 420 : 340;
-    pNv->reg[(0x0061A00C+dacOff)/4] = tmp | 0x100000;
-    usleep(4500);
-    load = pNv->reg[(0x0061A00C+dacOff)/4];
-    pNv->reg[(0x0061A00C+dacOff)/4] = 0;
-    pNv->reg[(0x0061A004+dacOff)/4] = 0x80550000;
-
-    return (load & 0x38000000) == 0x38000000;
-}
-
-/*
- * Performs load detection on the DACs.  Sets pNv->orType and pNv->or
- * accordingly.
- */
-Bool G80LoadDetect(ScrnInfoPtr pScrn)
-{
-    G80Ptr pNv = G80PTR(pScrn);
-    const int scrnIndex = pScrn->scrnIndex;
-    ORNum or;
-
-    pNv->orType = DAC;
-
-    for(or = DAC0; or <= DAC2; or++) {
-        xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on DAC%i ... ", or);
-
-        if(G80DispDetectLoad(pScrn, or)) {
-            xf86ErrorF("found one!\n");
-            pNv->or = or;
-            return TRUE;
-        }
-
-        xf86ErrorF("nothing.\n");
-    }
-
-    return FALSE;
+    G80CrtcPrivPtr pPriv = crtc->driver_private;
+    return pPriv->head;
 }
 
 Bool
-G80DispInit(ScrnInfoPtr pScrn)
+G80DispPreInit(ScrnInfoPtr pScrn)
 {
     G80Ptr pNv = G80PTR(pScrn);
 
@@ -269,6 +248,14 @@ G80DispInit(ScrnInfoPtr pScrn)
     pNv->reg[0x0061B004/4] = 0x80550000;
     pNv->reg[0x0061B010/4] = 0x00000001;
 
+    return TRUE;
+}
+
+Bool
+G80DispInit(ScrnInfoPtr pScrn)
+{
+    G80Ptr pNv = G80PTR(pScrn);
+
     if(pNv->reg[0x00610024/4] & 0x100) {
         pNv->reg[0x00610024/4] = 0x100;
         pNv->reg[0x006194E8/4] &= ~1;
@@ -295,65 +282,60 @@ void
 G80DispShutdown(ScrnInfoPtr pScrn)
 {
     G80Ptr pNv = G80PTR(pScrn);
-    CARD32 mask;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
 
-    G80DispBlankScreen(pScrn, TRUE);
+    for(i = 0; i < xf86_config->num_crtc; i++) {
+        xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+        G80CrtcBlankScreen(crtc, TRUE);
+    }
+
+    C(0x00000080, 0);
+
+    for(i = 0; i < xf86_config->num_crtc; i++) {
+        xf86CrtcPtr crtc = xf86_config->crtc[i];
+
+        if(crtc->enabled) {
+            const CARD32 mask = 4 << G80CrtcGetHead(crtc);
+
+            pNv->reg[0x00610024/4] = mask;
+            while(!(pNv->reg[0x00610024/4] & mask));
+        }
+    }
 
-    mask = 4 << pNv->head;
-    pNv->reg[0x00610024/4] = mask;
-    while(!(pNv->reg[0x00610024/4] & mask));
     pNv->reg[0x00610200/4] = 0;
     pNv->reg[0x00610300/4] = 0;
     while((pNv->reg[0x00610200/4] & 0x1e0000) != 0);
 }
 
-static void
-setupDAC(G80Ptr pNv, Head head, ORNum or, DisplayModePtr mode)
+static Bool
+G80CrtcModeFixup(xf86CrtcPtr crtc,
+                 DisplayModePtr mode, DisplayModePtr adjusted_mode)
 {
-    const int dacOff = 0x80 * pNv->or;
-
-    C(0x00000400 + dacOff, (head == HEAD0 ? 1 : 2) | 0x40);
-    C(0x00000404 + dacOff,
-        (mode->Flags & V_NHSYNC) ? 1 : 0 |
-        (mode->Flags & V_NVSYNC) ? 2 : 0);
+    // TODO: Fix up the mode here
+    return TRUE;
 }
 
 static void
-setupSOR(G80Ptr pNv, Head head, ORNum or, DisplayModePtr mode)
-{
-    const int sorOff = 0x40 * pNv->or;
-
-    C(0x00000600 + sorOff,
-        (head == HEAD0 ? 1 : 2) |
-        (mode->SynthClock > 165000 ? 0x500 : 0x100) |
-        ((mode->Flags & V_NHSYNC) ? 0x1000 : 0) |
-        ((mode->Flags & V_NVSYNC) ? 0x2000 : 0));
-}
-
-Bool
-G80DispSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode,
+               DisplayModePtr adjusted_mode, int x, int y)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     G80Ptr pNv = G80PTR(pScrn);
+    G80CrtcPrivPtr pPriv = crtc->driver_private;
     const int HDisplay = mode->HDisplay, VDisplay = mode->VDisplay;
-    const int headOff = 0x400 * pNv->head;
+    const int headOff = 0x400 * G80CrtcGetHead(crtc);
     int interlaceDiv, fudge;
 
-    pNv->pclk = mode->SynthClock;
+    // TODO: Use adjusted_mode and fix it up in G80CrtcModeFixup
+    pPriv->pclk = mode->Clock;
 
     /* Magic mode timing fudge factor */
     fudge = ((mode->Flags & V_INTERLACE) && (mode->Flags & V_DBLSCAN)) ? 2 : 1;
     interlaceDiv = (mode->Flags & V_INTERLACE) ? 2 : 1;
 
-    switch(pNv->orType) {
-    case DAC:
-        setupDAC(pNv, pNv->head, pNv->or, mode);
-        break;
-    case SOR:
-        setupSOR(pNv, pNv->head, pNv->or, mode);
-        break;
-    }
-
-    C(0x00000804 + headOff, mode->SynthClock | 0x800000);
+    C(0x00000804 + headOff, mode->Clock | 0x800000);
     C(0x00000808 + headOff, (mode->Flags & V_INTERLACE) ? 2 : 0);
     C(0x00000810 + headOff, 0);
     C(0x0000082C + headOff, 0);
@@ -388,41 +370,24 @@ G80DispSetMode(ScrnInfoPtr pScrn, Displa
         C(0x000008A4 + headOff, 0);
     }
     C(0x000008A8 + headOff, 0x40000);
-    /* Use the screen's panning, but not if it's bogus */
-    if(pScrn->frameX0 >= 0 && pScrn->frameY0 >= 0 &&
-       pScrn->frameX0 + HDisplay <= pScrn->virtualX &&
-       pScrn->frameY0 + VDisplay <= pScrn->virtualY) {
-        C(0x000008C0 + headOff, pScrn->frameY0 << 16 | pScrn->frameX0);
-    } else {
-        C(0x000008C0 + headOff, 0);
-    }
+    C(0x000008C0 + headOff, y << 16 | x);
     C(0x000008C8 + headOff, VDisplay << 16 | HDisplay);
     C(0x000008D4 + headOff, 0);
     C(0x000008D8 + headOff, mode->CrtcVDisplay << 16 | mode->CrtcHDisplay);
     C(0x000008DC + headOff, mode->CrtcVDisplay << 16 | mode->CrtcHDisplay);
 
-    G80DispBlankScreen(pScrn, FALSE);
-
-    return TRUE;
+    G80CrtcBlankScreen(crtc, FALSE);
 }
 
 void
-G80DispAdjustFrame(G80Ptr pNv, int x, int y)
-{
-    const int headOff = 0x400 * pNv->head;
-
-    C(0x000008C0 + headOff, y << 16 | x);
-    C(0x00000080, 0);
-}
-
-void
-G80DispBlankScreen(ScrnInfoPtr pScrn, Bool blank)
+G80CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
     G80Ptr pNv = G80PTR(pScrn);
-    const int headOff = 0x400 * pNv->head;
+    const int headOff = 0x400 * G80CrtcGetHead(crtc);
 
     if(blank) {
-        G80DispHideCursor(pNv, FALSE);
+        // G80DispHideCursor(pNv, FALSE);
 
         C(0x00000840 + headOff, 0);
         C(0x00000844 + headOff, 0);
@@ -441,21 +406,21 @@ G80DispBlankScreen(ScrnInfoPtr pScrn, Bo
         C(0x00000884 + headOff, (pNv->videoRam << 2) - 0x40);
         if(pNv->architecture != 0x50)
             C(0x0000089C + headOff, 1);
-        if(pNv->cursorVisible)
-            G80DispShowCursor(pNv, FALSE);
+        // if(pNv->cursorVisible)
+        //     G80DispShowCursor(pNv, FALSE);
         C(0x00000840 + headOff, pScrn->depth == 8 ? 0x80000000 : 0xc0000000);
         C(0x00000844 + headOff, (pNv->videoRam * 1024 - 0x5000) >> 8);
         if(pNv->architecture != 0x50)
             C(0x0000085C + headOff, 1);
         C(0x00000874 + headOff, 1);
     }
-
-    C(0x00000080, 0);
 }
 
 void
-G80DispDPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
+G80CrtcDPMSSet(xf86CrtcPtr crtc, int mode)
 {
+    ErrorF("CRTC dpms unimplemented\n");
+#if 0
     G80Ptr pNv = G80PTR(pScrn);
     const int off = 0x800 * pNv->or;
     CARD32 tmp;
@@ -502,21 +467,121 @@ G80DispDPMSSet(ScrnInfoPtr pScrn, int mo
 
         break;
     }
+#endif
 }
 
 /******************************** Cursor stuff ********************************/
-void G80DispShowCursor(G80Ptr pNv, Bool update)
+void G80CrtcShowCursor(xf86CrtcPtr crtc, Bool update)
 {
-    const int headOff = 0x400 * pNv->head;
+    ScrnInfoPtr pScrn = crtc->scrn;
+    const int headOff = 0x400 * G80CrtcGetHead(crtc);
 
     C(0x00000880 + headOff, 0x85000000);
     if(update) C(0x00000080, 0);
 }
 
-void G80DispHideCursor(G80Ptr pNv, Bool update)
+void G80CrtcHideCursor(xf86CrtcPtr crtc, Bool update)
 {
-    const int headOff = 0x400 * pNv->head;
+    ScrnInfoPtr pScrn = crtc->scrn;
+    const int headOff = 0x400 * G80CrtcGetHead(crtc);
 
     C(0x00000880 + headOff, 0x5000000);
     if(update) C(0x00000080, 0);
 }
+
+void G80CrtcSetCursorPosition(xf86CrtcPtr crtc, int x, int y)
+{
+    G80Ptr pNv = G80PTR(crtc->scrn);
+    const int headOff = 0x647000 + 0x1000*G80CrtcGetHead(crtc);
+
+    x &= 0xffff;
+    y &= 0xffff;
+    pNv->reg[(0x84 + headOff)/4] = y << 16 | x;
+    pNv->reg[(0x80 + headOff)/4] = 0;
+}
+
+/******************************** CRTC stuff ********************************/
+
+static Bool
+G80CrtcLock(xf86CrtcPtr crtc)
+{
+    return FALSE;
+}
+
+static void
+G80CrtcPrepare(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i;
+
+    ErrorF("Outputs:\n");
+    for(i = 0; i < xf86_config->num_output; i++) {
+        xf86OutputPtr output = xf86_config->output[i];
+
+        if(output->crtc) {
+            G80CrtcPrivPtr pPriv = output->crtc->driver_private;
+            ErrorF("\t%s -> HEAD%i\n", output->name, pPriv->head);
+        } else {
+            ErrorF("\t%s disconnected\n", output->name);
+            output->funcs->mode_set(output, NULL, NULL);
+        }
+    }
+}
+
+static void
+G80CrtcCommit(xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+    int i, crtc_mask = 0;
+
+    /* If any heads are unused, blank them */
+    for(i = 0; i < xf86_config->num_output; i++) {
+        xf86OutputPtr output = xf86_config->output[i];
+
+        if(output->crtc)
+            /* XXXagp: This assumes that xf86_config->crtc[i] is HEADi */
+            crtc_mask |= 1 << G80CrtcGetHead(output->crtc);
+    }
+
+    for(i = 0; i < xf86_config->num_crtc; i++)
+        if(!((1 << i) & crtc_mask))
+            G80CrtcBlankScreen(xf86_config->crtc[i], TRUE);
+
+    C(0x00000080, 0);
+}
+
+static const xf86CrtcFuncsRec g80_crtc_funcs = {
+    .dpms = G80CrtcDPMSSet,
+    .save = NULL,
+    .restore = NULL,
+    .lock = G80CrtcLock,
+    .unlock = NULL,
+    .mode_fixup = G80CrtcModeFixup,
+    .prepare = G80CrtcPrepare,
+    .mode_set = G80CrtcModeSet,
+    // .gamma_set = G80DispGammaSet,
+    .commit = G80CrtcCommit,
+    .shadow_create = NULL,
+    .shadow_destroy = NULL,
+    .destroy = NULL,
+};
+
+void
+G80DispCreateCrtcs(ScrnInfoPtr pScrn)
+{
+    Head head;
+    xf86CrtcPtr crtc;
+    G80CrtcPrivPtr g80_crtc;
+
+    /* Create a "crtc" object for each head */
+    for(head = HEAD0; head <= HEAD1; head++) {
+        crtc = xf86CrtcCreate(pScrn, &g80_crtc_funcs);
+        if(!crtc) return;
+
+        g80_crtc = xnfcalloc(sizeof(*g80_crtc), 1);
+        g80_crtc->head = head;
+        crtc->driver_private = g80_crtc;
+    }
+}
diff --git a/src/g80_display.h b/src/g80_display.h
index cbe312f..99436be 100644
--- a/src/g80_display.h
+++ b/src/g80_display.h
@@ -1,10 +1,16 @@
-Bool G80LoadDetect(ScrnInfoPtr);
-Bool G80DispLoadDetect(ScrnInfoPtr, ORNum or);
+Bool G80DispPreInit(ScrnInfoPtr);
 Bool G80DispInit(ScrnInfoPtr);
-Bool G80DispSetMode(ScrnInfoPtr, DisplayModePtr);
 void G80DispShutdown(ScrnInfoPtr);
-void G80DispAdjustFrame(G80Ptr pNv, int x, int y);
-void G80DispBlankScreen(ScrnInfoPtr, Bool blank);
-void G80DispDPMSSet(ScrnInfoPtr, int mode, int flags);
-void G80DispShowCursor(G80Ptr, Bool update);
-void G80DispHideCursor(G80Ptr, Bool update);
+
+void G80DispCommand(ScrnInfoPtr, CARD32 addr, CARD32 data);
+#define C(mthd, data) G80DispCommand(pScrn, (mthd), (data))
+
+Head G80CrtcGetHead(xf86CrtcPtr);
+
+void G80CrtcBlankScreen(xf86CrtcPtr, Bool blank);
+void G80CrtcEnableCursor(xf86CrtcPtr, Bool update);
+void G80CrtcDisableCursor(xf86CrtcPtr, Bool update);
+void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y);
+void G80CrtcSetDither(xf86CrtcPtr, CARD32 mask, CARD32 val);
+
+void G80DispCreateCrtcs(ScrnInfoPtr pScrn);
diff --git a/src/g80_driver.c b/src/g80_driver.c
index 4bef070..6d19cce 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -119,6 +119,39 @@ G80FreeRec(ScrnInfoPtr pScrn)
     pScrn->driverPrivate = NULL;
 }
 
+G80ResizeScreen(ScrnInfoPtr pScrn, int width, int height)
+{
+    G80Ptr pNv = G80PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int pitch = width * (pScrn->bitsPerPixel / 8);
+    int i;
+
+    pitch = (pitch + 255) & ~255;
+
+    ErrorF("Resizing screen to %ix%i\n", width, height);
+    pScrn->virtualX = width;
+    pScrn->virtualY = height;
+
+    /* Can resize if XAA is disabled */
+    if(!pNv->xaa) {
+        (*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen)->devKind = pitch;
+        pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
+
+        /* Re-set the modes so the new pitch is taken into account */
+        for(i = 0; i < xf86_config->num_crtc; i++) {
+            xf86CrtcPtr crtc = xf86_config->crtc[i];
+            if(crtc->enabled)
+                xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y);
+        }
+    }
+
+    return TRUE;
+}
+
+static const xf86CrtcConfigFuncsRec randr12_screen_funcs = {
+    .resize = G80ResizeScreen,
+};
+
 static Bool
 G80PreInit(ScrnInfoPtr pScrn, int flags)
 {
@@ -126,10 +159,8 @@ G80PreInit(ScrnInfoPtr pScrn, int flags)
     EntityInfoPtr pEnt;
     pciVideoPtr pPci;
     PCITAG pcitag;
-    ClockRangePtr clockRanges;
     MessageType from;
     Bool primary;
-    int i;
     char *s;
     const rgb zeros = {0, 0, 0};
     const Gamma gzeros = {0.0, 0.0, 0.0};
@@ -248,18 +279,6 @@ G80PreInit(ScrnInfoPtr pScrn, int flags)
 
     if(!xf86SetGamma(pScrn, gzeros)) goto fail;
 
-    /*
-     * Setup the ClockRanges, which describe what clock ranges are available,
-     * and what sort of modes they can be used for.
-     */
-    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
-    clockRanges->next = NULL;
-    clockRanges->minClock = 0;
-    clockRanges->maxClock = 400000;
-    clockRanges->clockIndex = -1;       /* programmable */
-    clockRanges->doubleScanAllowed = TRUE;
-    clockRanges->interlaceAllowed = TRUE;
-
     /* Map memory */
     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lx\n",
                pPci->memBase[0]);
@@ -308,33 +327,35 @@ G80PreInit(ScrnInfoPtr pScrn, int flags)
     else
         pNv->table1 -= 0x10000;
 
-    /* Probe DDC */
-    /* If no DDC info found, try DAC load detection */
+    xf86CrtcConfigInit(pScrn, &randr12_screen_funcs);
+    xf86CrtcSetSizeRange(pScrn, 320, 200, 8192, 8192);
+
     if(!xf86LoadSubModule(pScrn, "i2c")) goto fail;
     if(!xf86LoadSubModule(pScrn, "ddc")) goto fail;
     xf86LoaderReqSymLists(i2cSymbols, ddcSymbols, NULL);
-    if(!G80ProbeDDC(pScrn) && !G80LoadDetect(pScrn)) {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No display devices found\n");
+
+    if(!G80DispPreInit(pScrn)) goto fail;
+    /* Read the DDC routing table and create outputs */
+    if(!G80CreateOutputs(pScrn)) goto fail;
+    /* Create the crtcs */
+    G80DispCreateCrtcs(pScrn);
+
+    /* We can grow the desktop if XAA is disabled */
+    if(!xf86InitialConfiguration(pScrn, pNv->NoAccel)) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+            "No valid initial configuration found\n");
         goto fail;
     }
-    /* Hardcode HEAD0 for now.  RandR 1.2 will move this into a Crtc struct. */
-    pNv->head = 0;
+    pScrn->displayWidth = (pScrn->virtualX + 255) & ~255;
 
-    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
-                          pScrn->display->modes, clockRanges,
-                          NULL, 256, 8192,
-                          512, 128, 8192,
-                          pScrn->display->virtualX,
-                          pScrn->display->virtualY,
-                          pNv->videoRam * 1024 - G80_RESERVED_VIDMEM,
-                          LOOKUP_BEST_REFRESH);
-    if(i == -1) goto fail;
-    xf86PruneDriverModes(pScrn);
-    if(i == 0 || !pScrn->modes) {
-        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+    if(!xf86RandR12PreInit(pScrn)) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n");
+        goto fail;
+    }
+    if(!pScrn->modes) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n");
         goto fail;
     }
-    xf86SetCrtcForModes(pScrn, 0);
 
     pScrn->currentMode = pScrn->modes;
     xf86PrintModes(pScrn);
@@ -381,10 +402,12 @@ AcquireDisplay(ScrnInfoPtr pScrn)
 #if 0
     if(!G80CursorAcquire(pNv))
         return FALSE;
-#endif
     if(!G80DispSetMode(pScrn, pScrn->currentMode))
         return FALSE;
     G80DispDPMSSet(pScrn, DPMSModeOn, 0);
+#endif
+    ErrorF("TODO: Set the current config, rather than using xf86SetSingleMode\n");
+    xf86SetSingleMode(pScrn, pScrn->currentMode, RR_Rotate_0);
 
     return TRUE;
 }
@@ -443,6 +466,7 @@ G80CloseScreen(int scrnIndex, ScreenPtr 
     pScrn->vtSema = FALSE;
     pScreen->CloseScreen = pNv->CloseScreen;
     pScreen->BlockHandler = pNv->BlockHandler;
+    pScreen->CreateScreenResources = pNv->CreateScreenResources;
     return (*pScreen->CloseScreen)(scrnIndex, pScreen);
 }
 
@@ -468,11 +492,26 @@ G80SaveScreen(ScreenPtr pScreen, int mod
 
     if(!pScrn->vtSema) return FALSE;
 
-    G80DispBlankScreen(pScrn, !xf86IsUnblank(mode));
+    ErrorF("SaveScreen unimplemented\n");
 
-    return TRUE;
+    return FALSE;
 }
 
+static Bool
+G80CreateScreenResources(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    G80Ptr pNv = G80PTR(pScrn);
+
+    pScreen->CreateScreenResources = pNv->CreateScreenResources;
+    if(!(*pScreen->CreateScreenResources)(pScreen))
+        return FALSE;
+
+    if(!xf86RandR12CreateScreenResources(pScreen))
+        return FALSE;
+    return TRUE;
+ }
+
 static void
 G80InitHW(ScrnInfoPtr pScrn)
 {
@@ -710,8 +749,6 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
 
     /* pad the screen pitch to 256 bytes */
     pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
-    pitch = (pitch + 0xff) & ~0xff;
-    pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
 
     /* fb init */
     if(!fbScreenInit(pScreen, pNv->mem,
@@ -758,7 +795,7 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
         if(!G80XAAInit(pScreen)) {
             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                        "Hardware acceleration initialization failed\n");
-            pNv->NoAccel = FALSE;
+            return FALSE;
         }
     }
 
@@ -789,7 +826,7 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
                             CMAP_PALETTED_TRUECOLOR))
         return FALSE;
 
-    xf86DPMSInit(pScreen, G80DispDPMSSet, 0);
+    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
 
     /* Clear the screen */
     if(pNv->xaa) {
@@ -809,12 +846,20 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
 
     pScreen->SaveScreen = G80SaveScreen;
 
+    pNv->CreateScreenResources =  pScreen->CreateScreenResources;
+    pScreen->CreateScreenResources = G80CreateScreenResources;
+
     pNv->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = G80CloseScreen;
 
     pNv->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = G80BlockHandler;
 
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR 1.2 enabled. Please ignore the following RandR disabled message.\n");
+    xf86DisableRandR();
+    xf86RandR12Init(pScreen);
+    xf86RandR12SetRotations(pScreen, RR_Rotate_0);
+
     return TRUE;
 }
 
@@ -828,22 +873,13 @@ static Bool
 G80SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
 {
     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-
-    return G80DispSetMode(pScrn, mode);
+    return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
 }
 
 static void
 G80AdjustFrame(int scrnIndex, int x, int y, int flags)
 {
-    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-    G80Ptr pNv = G80PTR(pScrn);
-
-    if(x + pScrn->currentMode->HDisplay > pScrn->virtualX ||
-       y + pScrn->currentMode->VDisplay > pScrn->virtualY ||
-       x < 0 || y < 0)
-        /* Ignore bogus panning */
-        return;
-    G80DispAdjustFrame(pNv, x, y);
+    ErrorF("AdjustFrame unimplemented\n");
 }
 
 static Bool
diff --git a/src/g80_output.c b/src/g80_output.c
new file mode 100644
index 0000000..481dd85
--- /dev/null
+++ b/src/g80_output.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2007 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <strings.h>
+#include <xf86DDC.h>
+
+#include "g80_type.h"
+#include "g80_ddc.h"
+#include "g80_output.h"
+
+static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
+{
+    unsigned char *table2;
+    unsigned char headerSize, entries;
+    int i;
+    CARD16 a;
+    CARD32 b;
+
+    /* Clear the i2c map to invalid */
+    for(i = 0; i < 4; i++)
+        pNv->i2cMap[i].dac = pNv->i2cMap[i].sor = -1;
+
+    if(*(CARD16*)pNv->table1 != 0xaa55) goto fail;
+
+    a = *(CARD16*)(pNv->table1 + 0x36);
+    table2 = (unsigned char*)pNv->table1 + a;
+
+    if(table2[0] != 0x40) goto fail;
+
+    b = *(CARD32*)(table2 + 6);
+    if(b != 0x4edcbdcb) goto fail;
+
+    headerSize = table2[1];
+    entries = table2[2];
+
+    for(i = 0; i < entries; i++) {
+        CARD32 type, port;
+        ORNum or;
+
+        b = *(CARD32*)&table2[headerSize + 8*i];
+        type = b & 0xf;
+        port = (b >> 4) & 0xf;
+        or = ffs((b >> 24) & 0xf) - 1;
+
+        if(type < 4 && port != 0xf) {
+            switch(type) {
+                case 0: /* CRT */
+                case 1: /* TV */
+                    if(pNv->i2cMap[port].dac != -1) {
+                        xf86DrvMsg(scrnIndex, X_WARNING,
+                                   "DDC routing table corrupt!  DAC %i -> %i "
+                                   "for port %i\n",
+                                   or, pNv->i2cMap[port].dac, port);
+                    }
+                    pNv->i2cMap[port].dac = or;
+                    break;
+                case 2: /* TMDS */
+                case 3: /* LVDS */
+                    if(pNv->i2cMap[port].sor != -1)
+                        xf86DrvMsg(scrnIndex, X_WARNING,
+                                   "DDC routing table corrupt!  SOR %i -> %i "
+                                   "for port %i\n",
+                                   or, pNv->i2cMap[port].sor, port);
+                    pNv->i2cMap[port].sor = or;
+                    break;
+            }
+        }
+    }
+
+    xf86DrvMsg(scrnIndex, X_PROBED, "I2C map:\n");
+    for(i = 0; i < 4; i++) {
+        if(pNv->i2cMap[i].dac != -1)
+            xf86DrvMsg(scrnIndex, X_PROBED, "  Bus %i -> DAC%i\n", i, pNv->i2cMap[i].dac);
+        if(pNv->i2cMap[i].sor != -1)
+            xf86DrvMsg(scrnIndex, X_PROBED, "  Bus %i -> SOR%i\n", i, pNv->i2cMap[i].sor);
+    }
+
+    return TRUE;
+
+fail:
+    xf86DrvMsg(scrnIndex, X_ERROR, "Couldn't find the DDC routing table.  "
+               "Mode setting will probably fail!\n");
+    return FALSE;
+}
+
+static void G80_I2CPutBits(I2CBusPtr b, int clock, int data)
+{
+    G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
+    const int off = b->DriverPrivate.val * 0x18;
+
+    pNv->reg[(0x0000E138+off)/4] = 4 | clock | data << 1;
+}
+
+static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data)
+{
+    G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
+    const int off = b->DriverPrivate.val * 0x18;
+    unsigned char val;
+
+    val = pNv->reg[(0x0000E138+off)/4];
+    *clock = !!(val & 1);
+    *data = !!(val & 2);
+}
+
+Bool
+G80I2CInit(xf86OutputPtr output, const int port)
+{
+    G80OutputPrivPtr pPriv = output->driver_private;
+    I2CBusPtr i2c;
+
+    /* Allocate the I2C bus structure */
+    i2c = xf86CreateI2CBusRec();
+    if(!i2c) return FALSE;
+
+    i2c->BusName = output->name;
+    i2c->scrnIndex = output->scrn->scrnIndex;
+    i2c->I2CPutBits = G80_I2CPutBits;
+    i2c->I2CGetBits = G80_I2CGetBits;
+    i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+    i2c->StartTimeout = 550;
+    i2c->BitTimeout = 40;
+    i2c->ByteTimeout = 40;
+    i2c->AcknTimeout = 40;
+    i2c->DriverPrivate.val = port;
+
+    if(xf86I2CBusInit(i2c)) {
+        pPriv->i2c = i2c;
+        return TRUE;
+    } else {
+        xfree(i2c);
+        return FALSE;
+    }
+}
+
+void
+G80OutputSetPClk(xf86OutputPtr output, int pclk)
+{
+    G80OutputPrivPtr pPriv = output->driver_private;
+    pPriv->set_pclk(output, pclk);
+}
+
+int
+G80OutputModeValid(xf86OutputPtr output, DisplayModePtr mode)
+{
+    if(mode->Clock > 400000 || mode->Clock < 25000)
+        return MODE_CLOCK_RANGE;
+
+    return MODE_OK;
+}
+
+Bool
+G80OutputModeFixup(xf86OutputPtr output, DisplayModePtr mode,
+                   DisplayModePtr adjusted_mode)
+{
+    return TRUE;
+}
+
+void
+G80OutputPrepare(xf86OutputPtr output)
+{
+}
+
+void
+G80OutputCommit(xf86OutputPtr output)
+{
+}
+
+DisplayModePtr
+G80OutputGetDDCModes(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    G80Ptr pNv = G80PTR(pScrn);
+    G80OutputPrivPtr pPriv = output->driver_private;
+    I2CBusPtr i2c = pPriv->i2c;
+    xf86MonPtr monInfo = NULL;
+    DisplayModePtr modes;
+    const int bus = i2c->DriverPrivate.val, off = bus * 0x18;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+            "Probing for EDID on I2C bus %i...\n", bus);
+    pNv->reg[(0x0000E138+off)/4] = 7;
+    monInfo = xf86OutputGetEDID(output, i2c);
+    pNv->reg[(0x0000E138+off)/4] = 3;
+
+    xf86OutputSetEDID(output, monInfo);
+    modes = xf86OutputGetEDIDModes(output);
+
+    if(monInfo) {
+        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+                "DDC detected a %s:\n", monInfo->features.input_type ?
+                "DFP" : "CRT");
+        xf86PrintEDID(monInfo);
+    } else {
+        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "  ... none found\n");
+    }
+
+    return modes;
+}
+
+void
+G80OutputDestroy(xf86OutputPtr output)
+{
+    G80OutputPrivPtr pPriv = output->driver_private;
+
+    xf86DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE);
+    pPriv->i2c = NULL;
+}
+
+Bool
+G80CreateOutputs(ScrnInfoPtr pScrn)
+{
+    G80Ptr pNv = G80PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int i, count = 0;
+
+    if(!G80ReadPortMapping(pScrn->scrnIndex, pNv))
+        return FALSE;
+
+    /* For each DDC port, create an output for the attached ORs */
+    for(i = 0; i < 4; i++) {
+        if(pNv->i2cMap[i].dac != -1)
+            G80CreateDac(pScrn, pNv->i2cMap[i].dac, i);
+        if(pNv->i2cMap[i].sor != -1)
+            G80CreateSor(pScrn, pNv->i2cMap[i].sor, i);
+    }
+
+    /* For each output, set the crtc and clone masks */
+    for(i = 0; i < xf86_config->num_output; i++) {
+        xf86OutputPtr output = xf86_config->output[i];
+        G80OutputPrivPtr pPriv = output->driver_private;
+
+        /* Any output can connect to any head */
+        output->possible_crtcs = 0x3;
+        output->possible_clones = 0;
+    }
+
+    return TRUE;
+}
+
diff --git a/src/g80_output.h b/src/g80_output.h
new file mode 100644
index 0000000..efc9a16
--- /dev/null
+++ b/src/g80_output.h
@@ -0,0 +1,24 @@
+typedef struct G80OutputPrivRec {
+    ORType type;
+    ORNum or;
+
+    I2CBusPtr i2c;
+
+    void (*set_pclk)(xf86OutputPtr, int pclk);
+} G80OutputPrivRec, *G80OutputPrivPtr;
+
+Bool G80I2CInit(xf86OutputPtr, const int port);
+void G80OutputSetPClk(xf86OutputPtr, int pclk);
+int G80OutputModeValid(xf86OutputPtr, DisplayModePtr);
+Bool G80OutputModeFixup(xf86OutputPtr, DisplayModePtr mode, DisplayModePtr adjusted_mode);
+void G80OutputPrepare(xf86OutputPtr);
+void G80OutputCommit(xf86OutputPtr);
+DisplayModePtr G80OutputGetDDCModes(xf86OutputPtr);
+void G80OutputDestroy(xf86OutputPtr);
+Bool G80CreateOutputs(ScrnInfoPtr);
+
+/* g80_dac.c */
+xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum, int i2cPort);
+
+/* g80_sor.c */
+xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum, int i2cPort);
diff --git a/src/g80_sor.c b/src/g80_sor.c
new file mode 100644
index 0000000..7d377a8
--- /dev/null
+++ b/src/g80_sor.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2007 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <X11/Xatom.h>
+
+#include "g80_type.h"
+#include "g80_display.h"
+#include "g80_output.h"
+
+static void
+G80SorSetPClk(xf86OutputPtr output, int pclk)
+{
+    G80Ptr pNv = G80PTR(output->scrn);
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int orOff = 0x800 * pPriv->or;
+
+    pNv->reg[(0x00614300+orOff)/4] = (pclk > 165000) ? 0x101 : 0;
+}
+
+static void
+G80SorDPMSSet(xf86OutputPtr output, int mode)
+{
+    ErrorF("SOR dpms unimplemented\n");
+}
+
+static void
+G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode,
+              DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    G80OutputPrivPtr pPriv = output->driver_private;
+    const int sorOff = 0x40 * pPriv->or;
+
+    if(adjusted_mode)
+        ErrorF("SOR%i mode %s -> HEAD%i\n", pPriv->or, adjusted_mode->name, G80CrtcGetHead(output->crtc));
+
+    if(!adjusted_mode) {
+        /* Disconnect the SOR */
+        C(0x00000600 + sorOff, 0);
+        return;
+    }
+
+    C(0x00000600 + sorOff,
+        (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) |
+        (mode->SynthClock > 165000 ? 0x500 : 0x100) |
+        ((mode->Flags & V_NHSYNC) ? 0x1000 : 0) |
+        ((mode->Flags & V_NVSYNC) ? 0x2000 : 0));
+}
+
+static xf86OutputStatus
+G80SorDetect(xf86OutputPtr output)
+{
+    return XF86OutputStatusUnknown;
+
+#if 0
+    DisplayModePtr modes = output->funcs->get_modes(output);
+    xf86OutputStatus status;
+
+    if(modes)
+        status = XF86OutputStatusConnected;
+    else
+        status = XF86OutputStatusDisconnected;
+    xfree(modes);
+
+    return status;
+#endif
+}
+
+static void
+G80SorDestroy(xf86OutputPtr output)
+{
+    G80OutputDestroy(output);
+
+    xfree(output->driver_private);
+    output->driver_private = NULL;
+}
+
+static const xf86OutputFuncsRec G80SorOutputFuncs = {
+    .dpms = G80SorDPMSSet,
+    .save = NULL,
+    .restore = NULL,
+    .mode_valid = G80OutputModeValid,
+    .mode_fixup = G80OutputModeFixup,
+    .prepare = G80OutputPrepare,
+    .commit = G80OutputCommit,
+    .mode_set = G80SorModeSet,
+    .detect = G80SorDetect,
+    .get_modes = G80OutputGetDDCModes,
+    .destroy = G80SorDestroy,
+};
+
+xf86OutputPtr
+G80CreateSor(ScrnInfoPtr pScrn, ORNum or, int i2cPort)
+{
+    G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1);
+    xf86OutputPtr output;
+    char orName[5];
+
+    if(!pPriv)
+        return FALSE;
+
+    snprintf(orName, 5, "DVI%i", or);
+    output = xf86OutputCreate(pScrn, &G80SorOutputFuncs, orName);
+
+    pPriv->type = SOR;
+    pPriv->or = or;
+    pPriv->set_pclk = G80SorSetPClk;
+    output->driver_private = pPriv;
+    output->interlaceAllowed = TRUE;
+    output->doubleScanAllowed = TRUE;
+
+    /* Create an I2C object */
+    G80I2CInit(output, i2cPort);
+
+    return output;
+}
diff --git a/src/g80_type.h b/src/g80_type.h
index 20b5e8b..6c031c4 100644
--- a/src/g80_type.h
+++ b/src/g80_type.h
@@ -2,6 +2,9 @@
 #include <xf86.h>
 #include <xf86int10.h>
 #include <xf86Cursor.h>
+#include <xf86DDC.h>
+#include <xf86Crtc.h>
+#include <xf86int10.h>
 
 typedef enum Head {
     HEAD0 = 0,
@@ -36,12 +39,6 @@ typedef struct G80Rec {
         ORNum sor;
     } i2cMap[4];
 
-    float               pclk; /* Current mode pclk in kHz */
-
-    Head                head;
-    ORType              orType;
-    ORNum               or;
-
     xf86Int10InfoPtr    int10;
     int                 int10Mode; /* Console mode to restore */
 
@@ -67,8 +64,9 @@ typedef struct G80Rec {
     CARD32 *            dmaBase;
     void              (*DMAKickoffCallback)(ScrnInfoPtr);
 
-    CloseScreenProcPtr  CloseScreen;
-    ScreenBlockHandlerProcPtr BlockHandler;
+    CreateScreenResourcesProcPtr CreateScreenResources;
+    CloseScreenProcPtr           CloseScreen;
+    ScreenBlockHandlerProcPtr    BlockHandler;
 } G80Rec, *G80Ptr;
 
 #define G80PTR(p) ((G80Ptr)((p)->driverPrivate))
diff-tree 636adcd57f1c5b33edf2d8fbf9e7fa9aac1ccb1a (from 8b2c7bc457d34b7ed59cd08719bec8754ebf6fb8)
Author: root <root at treble.(none)>
Date:   Sat Mar 10 22:12:39 2007 -0800

    Get rid of BackendMode and disable hw cursor for now.

diff --git a/man/nv.man b/man/nv.man
index 243b406..e892ecf 100644
--- a/man/nv.man
+++ b/man/nv.man
@@ -147,13 +147,6 @@ Enable or disable the hardware cursor.  
 .TP
 .BI "Option \*qNoAccel\*q \*q" boolean \*q
 Disable or enable acceleration.  Default: acceleration is enabled.
-.TP
-.BI "Option \*qBackendMode\*q \*q" mode \*q
-Designate a mode to be used as the physical mode driving the display.
-The screen will be scaled to fit the requested mode.
-For example, if
-.B Option \*qBackendMode\*q \*q1280x1024\*q
-is specified, the monitor will always display the 1280x1024 mode and the screen will be scaled to match.
 ..
 .if __support_g80__ .G8
 .\" ******************** end G80 section ********************
diff --git a/src/g80_cursor.c b/src/g80_cursor.c
index 07422e5..f416860 100644
--- a/src/g80_cursor.c
+++ b/src/g80_cursor.c
@@ -21,6 +21,7 @@
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#if 0
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -183,3 +184,5 @@ Bool G80CursorInit(ScreenPtr pScreen)
 
     return xf86InitCursor(pScreen, infoPtr);
 }
+
+#endif
diff --git a/src/g80_display.c b/src/g80_display.c
index 068e902..95c3d34 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -338,9 +338,6 @@ G80DispSetMode(ScrnInfoPtr pScrn, Displa
     const int headOff = 0x400 * pNv->head;
     int interlaceDiv, fudge;
 
-    if(pNv->BackendMode)
-        mode = pNv->BackendMode;
-
     pNv->pclk = mode->SynthClock;
 
     /* Magic mode timing fudge factor */
diff --git a/src/g80_driver.c b/src/g80_driver.c
index 2a3120f..4bef070 100644
--- a/src/g80_driver.c
+++ b/src/g80_driver.c
@@ -95,13 +95,11 @@ static const char *int10Symbols[] = {
 typedef enum {
     OPTION_HW_CURSOR,
     OPTION_NOACCEL,
-    OPTION_BACKEND_MODE,
 } G80Opts;
 
 static const OptionInfoRec G80Options[] = {
     { OPTION_HW_CURSOR,         "HWCursor",     OPTV_BOOLEAN,   {0}, FALSE },
     { OPTION_NOACCEL,           "NoAccel",      OPTV_BOOLEAN,   {0}, FALSE },
-    { OPTION_BACKEND_MODE,      "BackendMode",  OPTV_ANYSTR,    {0}, FALSE },
     { -1,                       NULL,           OPTV_NONE,      {0}, FALSE }
 };
 
@@ -342,31 +340,6 @@ G80PreInit(ScrnInfoPtr pScrn, int flags)
     xf86PrintModes(pScrn);
     xf86SetDpi(pScrn, 0, 0);
 
-    /* Custom backend timings */
-    pNv->BackendMode = NULL;
-    if((s = xf86GetOptValString(pNv->Options, OPTION_BACKEND_MODE))) {
-        DisplayModePtr mode;
-
-        for(mode = pScrn->modes; ; mode = mode->next) {
-            if(!strcmp(mode->name, s))
-                break;
-            if(mode->next == pScrn->modes) {
-                mode = NULL;
-                break;
-            }
-        }
-
-        pNv->BackendMode = mode;
-
-        if(mode)
-            xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BackendMode: Using mode "
-                       "\"%s\" for display timings\n", mode->name);
-        else
-            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cannot honor "
-                       "\"BackendMode\" option: no mode named \"%s\" "
-                       "found.\n", s);
-    }
-
     /* Load fb */
     if(!xf86LoadSubModule(pScrn, "fb")) goto fail;
     xf86LoaderReqSymLists(fbSymbols, NULL);
@@ -405,8 +378,10 @@ AcquireDisplay(ScrnInfoPtr pScrn)
 
     if(!G80DispInit(pScrn))
         return FALSE;
+#if 0
     if(!G80CursorAcquire(pNv))
         return FALSE;
+#endif
     if(!G80DispSetMode(pScrn, pScrn->currentMode))
         return FALSE;
     G80DispDPMSSet(pScrn, DPMSModeOn, 0);
@@ -422,7 +397,9 @@ ReleaseDisplay(ScrnInfoPtr pScrn)
 {
     G80Ptr pNv = G80PTR(pScrn);
 
+#if 0
     G80CursorRelease(pNv);
+#endif
     G80DispShutdown(pScrn);
 
     if(pNv->int10 && pNv->int10Mode) {
@@ -450,8 +427,10 @@ G80CloseScreen(int scrnIndex, ScreenPtr 
 
     if(pNv->xaa)
         XAADestroyInfoRec(pNv->xaa);
+#if 0
     if(pNv->HWCursor)
         xf86DestroyCursorInfoRec(pNv->CursorInfo);
+#endif
 
     if(xf86ServerIsExiting()) {
         if(pNv->int10) xf86FreeInt10(pNv->int10);
@@ -792,11 +771,13 @@ G80ScreenInit(int scrnIndex, ScreenPtr p
     miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
 
     /* Initialize hardware cursor.  Must follow software cursor initialization. */
+#if 0
     if(pNv->HWCursor && !G80CursorInit(pScreen)) {
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "Hardware cursor initialization failed\n");
         pNv->HWCursor = FALSE;
     }
+#endif
 
     /* Initialize default colormap */
     if(!miCreateDefColormap(pScreen))
diff --git a/src/g80_type.h b/src/g80_type.h
index 39d737c..20b5e8b 100644
--- a/src/g80_type.h
+++ b/src/g80_type.h
@@ -49,7 +49,6 @@ typedef struct G80Rec {
     OptionInfoPtr       Options;
     Bool                HWCursor;
     Bool                NoAccel;
-    DisplayModePtr      BackendMode;
 
     /* Cursor */
     xf86CursorInfoPtr   CursorInfo;



More information about the xorg-commit mailing list