
From: "Antonino A. Daplas" <adaplas@hotpop.com>

Because nVidia keeps pumping out new graphics chipsets, it is becoming
harder to add support for these with the old rivafb code.  Currently, rivafb
can properly support NV_ARCH_20 chipsets and older.

Instead of rewriting rivafb to support the latest chipsets, I've decided to
write a new driver, called nvidiafb.  The aim is to closely follow Xorg
development.  

Currently, this driver is based on the most recent CVS Xorg nv driver. Main

  - console acceleration for all chipsets
  - uses DMA instead of PIO
  - better LCD/digital output support
  - better monitor detection
  - support for Riva128 will be dropped as it cannot do DMA, rivafb
    will remain as the driver for this chipset

It should work with Xorg/XFree86 nv driver, but as with rivafb, is not
compatible with the proprietary nvidia driver.

Once the code becomes stable, rivafb code will be trimmed to only support the
Riva128 and perhaps some of the older chipsets.  The code has been tested on
several nVidia graphics card on x86 and x86_64.  I'm still waiting for
feedback from Guido Guenther regarding ppc.

This need not go to mainline immediately, as I would prefer the code to
receive rigorous testing in the mm tree.

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/video/Kconfig           |   32 
 25-akpm/drivers/video/Makefile          |    1 
 25-akpm/drivers/video/nvidia/Makefile   |   12 
 25-akpm/drivers/video/nvidia/nv_accel.c |  367 ++++++
 25-akpm/drivers/video/nvidia/nv_dma.h   |  178 +++
 25-akpm/drivers/video/nvidia/nv_hw.c    | 1582 +++++++++++++++++++++++++++++
 25-akpm/drivers/video/nvidia/nv_i2c.c   |  209 +++
 25-akpm/drivers/video/nvidia/nv_local.h |   98 +
 25-akpm/drivers/video/nvidia/nv_of.c    |   59 +
 25-akpm/drivers/video/nvidia/nv_proto.h |   61 +
 25-akpm/drivers/video/nvidia/nv_setup.c |  622 +++++++++++
 25-akpm/drivers/video/nvidia/nv_type.h  |  174 +++
 25-akpm/drivers/video/nvidia/nvidia.c   | 1725 ++++++++++++++++++++++++++++++++
 25-akpm/include/linux/fb.h              |    5 
 25-akpm/include/linux/pci_ids.h         |   84 +
 15 files changed, 5207 insertions(+), 2 deletions(-)

diff -puN drivers/video/Kconfig~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets drivers/video/Kconfig
--- 25/drivers/video/Kconfig~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets	2005-02-24 23:15:31.000000000 -0800
+++ 25-akpm/drivers/video/Kconfig	2005-02-24 23:15:31.000000000 -0800
@@ -606,6 +606,38 @@ config FB_EPSON1355
 	  framebuffer.  Product specs at
 	  <http://www.erd.epson.com/vdc/html/products.htm>.
 
+config FB_NVIDIA
+	tristate "nVidia Framebuffer Support"
+	depends on FB && PCI
+	select I2C_ALGOBIT if FB_NVIDIA_I2C
+	select I2C if FB_NVIDIA_I2C
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+	help
+	  This driver supports graphics boards with the nVidia chips, TNT
+	  and newer. For very old chipsets, such as the RIVA128, then use
+	  the the rivafb.
+	  Say Y if you have such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called nvidiafb.
+          none yet
+
+config FB_NVIDIA_I2C
+       bool "Enable DDC Support"
+       depends on FB_NVIDIA && !PPC_OF
+       help
+	  This enables I2C support for nVidia Chipsets.  This is used
+	  only for getting EDID information from the attached display
+	  allowing for robust video mode handling and switching.
+
+	  Because fbdev-2.6 requires that drivers must be able to
+	  independently validate video mode parameters, you should say Y
+	  here.
+
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
diff -puN drivers/video/Makefile~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets drivers/video/Makefile
--- 25/drivers/video/Makefile~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets	2005-02-24 23:15:31.000000000 -0800
+++ 25-akpm/drivers/video/Makefile	2005-02-24 23:15:31.000000000 -0800
@@ -30,6 +30,7 @@ obj-$(CONFIG_FB_PM3)		  += pm3fb.o
 
 obj-$(CONFIG_FB_MATROX)		  += matrox/
 obj-$(CONFIG_FB_RIVA)		  += riva/ vgastate.o
+obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
 obj-$(CONFIG_FB_ATY)		  += aty/
 obj-$(CONFIG_FB_ATY128)		  += aty/
 obj-$(CONFIG_FB_RADEON)		  += aty/
diff -puN /dev/null drivers/video/nvidia/Makefile
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/Makefile	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,12 @@
+#
+# Makefile for the nVidia framebuffer driver
+#
+
+obj-$(CONFIG_FB_NVIDIA)          += nvidiafb.o
+
+nvidiafb-y                       := nvidia.o nv_hw.o nv_setup.o \
+			            nv_accel.o
+nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
+nvidiafb-$(CONFIG_PPC_OF)	 += nv_of.o
+
+nvidiafb-objs                    := $(nvidiafb-y)
\ No newline at end of file
diff -puN /dev/null drivers/video/nvidia/nv_accel.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_accel.c	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,367 @@
+/*
+ * linux/drivers/video/nvidia/nv_accel.c - nVidia Hardware Acceleration
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/fb.h>
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+#include "nv_local.h"
+
+/* There is a HW race condition with videoram command buffers.
+   You can't jump to the location of your put offset.  We write put
+   at the jump offset + SKIPS dwords with noop padding in between
+   to solve this problem */
+#define SKIPS  8
+
+static const int NVCopyROP[16] = {
+	0xCC,			/* copy   */
+	0x55			/* invert */
+};
+
+static const int NVCopyROP_PM[16] = {
+	0xCA,			/* copy  */
+	0x5A,			/* invert */
+};
+
+static inline void NVFlush(struct nvidia_par *par)
+{
+	int count = 1000000000;
+
+	while (--count && READ_GET(par) != par->dmaPut) ;
+
+	if (!count) {
+		printk("nvidiafb: DMA Flush lockup\n");
+		par->lockup = 1;
+	}
+}
+
+static inline void NVSync(struct nvidia_par *par)
+{
+	int count = 1000000000;
+
+	while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
+
+	if (!count) {
+		printk("nvidiafb: DMA Sync lockup\n");
+		par->lockup = 1;
+	}
+}
+
+void NVDmaKickoff(struct nvidia_par *par)
+{
+	if (par->dmaCurrent != par->dmaPut) {
+		par->dmaPut = par->dmaCurrent;
+		WRITE_PUT(par, par->dmaPut);
+	}
+}
+
+void NVDmaWait(struct nvidia_par *par, int size)
+{
+	int dmaGet;
+	int count = 1000000000, cnt;
+	size++;
+
+	while (par->dmaFree < size && --count && !par->lockup) {
+		dmaGet = READ_GET(par);
+
+		if (par->dmaPut >= dmaGet) {
+			par->dmaFree = par->dmaMax - par->dmaCurrent;
+			if (par->dmaFree < size) {
+				NVDmaNext(par, 0x20000000);
+				if (dmaGet <= SKIPS) {
+					if (par->dmaPut <= SKIPS)
+						WRITE_PUT(par, SKIPS + 1);
+					cnt = 1000000000;
+					do {
+						dmaGet = READ_GET(par);
+					} while (--cnt && dmaGet <= SKIPS);
+					if (!cnt) {
+						printk("DMA Get lockup\n");
+						par->lockup = 1;
+					}
+				}
+				WRITE_PUT(par, SKIPS);
+				par->dmaCurrent = par->dmaPut = SKIPS;
+				par->dmaFree = dmaGet - (SKIPS + 1);
+			}
+		} else
+			par->dmaFree = dmaGet - par->dmaCurrent - 1;
+	}
+
+	if (!count) {
+		printk("DMA Wait Lockup\n");
+		par->lockup = 1;
+	}
+}
+
+static void NVSetPattern(struct nvidia_par *par, u32 clr0, u32 clr1,
+			 u32 pat0, u32 pat1)
+{
+	NVDmaStart(par, PATTERN_COLOR_0, 4);
+	NVDmaNext(par, clr0);
+	NVDmaNext(par, clr1);
+	NVDmaNext(par, pat0);
+	NVDmaNext(par, pat1);
+}
+
+static void NVSetRopSolid(struct nvidia_par *par, u32 rop, u32 planemask)
+{
+	if (planemask != ~0) {
+		NVSetPattern(par, 0, planemask, ~0, ~0);
+		if (par->currentRop != (rop + 32)) {
+			NVDmaStart(par, ROP_SET, 1);
+			NVDmaNext(par, NVCopyROP_PM[rop]);
+			par->currentRop = rop + 32;
+		}
+	} else if (par->currentRop != rop) {
+		if (par->currentRop >= 16)
+			NVSetPattern(par, ~0, ~0, ~0, ~0);
+		NVDmaStart(par, ROP_SET, 1);
+		NVDmaNext(par, NVCopyROP[rop]);
+		par->currentRop = rop;
+	}
+}
+
+static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
+				   int x2, int y2)
+{
+	struct nvidia_par *par = info->par;
+	int h = y2 - y1 + 1;
+	int w = x2 - x1 + 1;
+
+	NVDmaStart(par, CLIP_POINT, 2);
+	NVDmaNext(par, (y1 << 16) | x1);
+	NVDmaNext(par, (h << 16) | w);
+}
+
+void NVResetGraphics(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 surfaceFormat, patternFormat, rectFormat, lineFormat;
+	int pitch, i;
+
+	pitch = info->fix.line_length;
+
+	par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]);
+
+	for (i = 0; i < SKIPS; i++)
+		NV_WR32(&par->dmaBase[i], 0, 0x00000000);
+
+	NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000);
+	NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010);
+	NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000);
+	NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011);
+	NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000);
+	NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012);
+	NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000);
+	NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013);
+	NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000);
+	NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014);
+	NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000);
+	NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015);
+	NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000);
+	NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016);
+	NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000);
+	NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017);
+
+	par->dmaPut = 0;
+	par->dmaCurrent = 16 + SKIPS;
+	par->dmaMax = 8191;
+	par->dmaFree = par->dmaMax - par->dmaCurrent;
+
+	switch (info->var.bits_per_pixel) {
+	case 32:
+	case 24:
+		surfaceFormat = SURFACE_FORMAT_DEPTH24;
+		patternFormat = PATTERN_FORMAT_DEPTH24;
+		rectFormat = RECT_FORMAT_DEPTH24;
+		lineFormat = LINE_FORMAT_DEPTH24;
+		break;
+	case 16:
+		surfaceFormat = SURFACE_FORMAT_DEPTH16;
+		patternFormat = PATTERN_FORMAT_DEPTH16;
+		rectFormat = RECT_FORMAT_DEPTH16;
+		lineFormat = LINE_FORMAT_DEPTH16;
+		break;
+	default:
+		surfaceFormat = SURFACE_FORMAT_DEPTH8;
+		patternFormat = PATTERN_FORMAT_DEPTH8;
+		rectFormat = RECT_FORMAT_DEPTH8;
+		lineFormat = LINE_FORMAT_DEPTH8;
+		break;
+	}
+
+	NVDmaStart(par, SURFACE_FORMAT, 4);
+	NVDmaNext(par, surfaceFormat);
+	NVDmaNext(par, pitch | (pitch << 16));
+	NVDmaNext(par, 0);
+	NVDmaNext(par, 0);
+
+	NVDmaStart(par, PATTERN_FORMAT, 1);
+	NVDmaNext(par, patternFormat);
+
+	NVDmaStart(par, RECT_FORMAT, 1);
+	NVDmaNext(par, rectFormat);
+
+	NVDmaStart(par, LINE_FORMAT, 1);
+	NVDmaNext(par, lineFormat);
+
+	par->currentRop = ~0;	/* set to something invalid */
+	NVSetRopSolid(par, ROP_COPY, ~0);
+
+	NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
+			       info->var.yres_virtual);
+
+	NVDmaKickoff(par);
+}
+
+u8 byte_rev[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+int nvidiafb_sync(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	if (!par->lockup)
+		NVFlush(par);
+
+	if (!par->lockup)
+		NVSync(par);
+
+	return 0;
+}
+
+void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct nvidia_par *par = info->par;
+
+	if (par->lockup)
+		return cfb_copyarea(info, region);
+
+	NVDmaStart(par, BLIT_POINT_SRC, 3);
+	NVDmaNext(par, (region->sy << 16) | region->sx);
+	NVDmaNext(par, (region->dy << 16) | region->dx);
+	NVDmaNext(par, (region->height << 16) | region->width);
+
+	NVDmaKickoff(par);
+}
+
+void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nvidia_par *par = info->par;
+	u32 color;
+
+	if (par->lockup)
+		return cfb_fillrect(info, rect);
+
+	if (info->var.bits_per_pixel == 8)
+		color = rect->color;
+	else
+		color = ((u32 *) info->pseudo_palette)[rect->color];
+
+	if (rect->rop != ROP_COPY)
+		NVSetRopSolid(par, rect->rop, ~0);
+
+	NVDmaStart(par, RECT_SOLID_COLOR, 1);
+	NVDmaNext(par, color);
+
+	NVDmaStart(par, RECT_SOLID_RECTS(0), 2);
+	NVDmaNext(par, (rect->dx << 16) | rect->dy);
+	NVDmaNext(par, (rect->width << 16) | rect->height);
+
+	NVDmaKickoff(par);
+
+	if (rect->rop != ROP_COPY)
+		NVSetRopSolid(par, ROP_COPY, ~0);
+}
+
+static void nvidiafb_mono_color_expand(struct fb_info *info,
+				       const struct fb_image *image)
+{
+	struct nvidia_par *par = info->par;
+	u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
+	u32 dsize, width, *data = (u32 *) image->data, tmp;
+	int i, j, k = 0;
+
+	width = (image->width + 31) & ~31;
+	dsize = width >> 5;
+
+	if (info->var.bits_per_pixel == 8) {
+		fg = image->fg_color | mask;
+		bg = image->bg_color | mask;
+	} else {
+		fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask;
+		bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
+	}
+
+	NVDmaStart(par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
+	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+	NVDmaNext(par, ((image->dy + image->height) << 16) |
+		  ((image->dx + image->width) & 0xffff));
+	NVDmaNext(par, bg);
+	NVDmaNext(par, fg);
+	NVDmaNext(par, (image->height << 16) | width);
+	NVDmaNext(par, (image->height << 16) | width);
+	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+
+	for (i = image->height; i--;) {
+		NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+		for (j = dsize; j--;) {
+			tmp = data[k++];
+			reverse_order(&tmp);
+			NVDmaNext(par, tmp);
+		}
+	}
+
+	NVDmaKickoff(par);
+}
+
+void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nvidia_par *par = info->par;
+
+	if (image->depth == 1 && !par->lockup)
+		nvidiafb_mono_color_expand(info, image);
+	else
+		cfb_imageblit(info, image);
+}
diff -puN /dev/null drivers/video/nvidia/nv_dma.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_dma.h	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,178 @@
+
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING 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 SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+#define SURFACE_FORMAT                                              0x00000300
+#define SURFACE_FORMAT_DEPTH8                                       0x00000001
+#define SURFACE_FORMAT_DEPTH15                                      0x00000002
+#define SURFACE_FORMAT_DEPTH16                                      0x00000004
+#define SURFACE_FORMAT_DEPTH24                                      0x00000006
+#define SURFACE_PITCH                                               0x00000304
+#define SURFACE_PITCH_SRC                                           15:0
+#define SURFACE_PITCH_DST                                           31:16
+#define SURFACE_OFFSET_SRC                                          0x00000308
+#define SURFACE_OFFSET_DST                                          0x0000030C
+
+#define ROP_SET                                                     0x00002300
+
+#define PATTERN_FORMAT                                              0x00004300
+#define PATTERN_FORMAT_DEPTH8                                       0x00000003
+#define PATTERN_FORMAT_DEPTH16                                      0x00000001
+#define PATTERN_FORMAT_DEPTH24                                      0x00000003
+#define PATTERN_COLOR_0                                             0x00004310
+#define PATTERN_COLOR_1                                             0x00004314
+#define PATTERN_PATTERN_0                                           0x00004318
+#define PATTERN_PATTERN_1                                           0x0000431C
+
+#define CLIP_POINT                                                  0x00006300
+#define CLIP_POINT_X                                                15:0
+#define CLIP_POINT_Y                                                31:16
+#define CLIP_SIZE                                                   0x00006304
+#define CLIP_SIZE_WIDTH                                             15:0
+#define CLIP_SIZE_HEIGHT                                            31:16
+
+#define LINE_FORMAT                                                 0x00008300
+#define LINE_FORMAT_DEPTH8                                          0x00000003
+#define LINE_FORMAT_DEPTH16                                         0x00000001
+#define LINE_FORMAT_DEPTH24                                         0x00000003
+#define LINE_COLOR                                                  0x00008304
+#define LINE_MAX_LINES                                              16
+#define LINE_LINES(i)                                               0x00008400\
+                                                                    +(i)*8
+#define LINE_LINES_POINT0_X                                         15:0
+#define LINE_LINES_POINT0_Y                                         31:16
+#define LINE_LINES_POINT1_X                                         47:32
+#define LINE_LINES_POINT1_Y                                         63:48
+
+#define BLIT_POINT_SRC                                              0x0000A300
+#define BLIT_POINT_SRC_X                                            15:0
+#define BLIT_POINT_SRC_Y                                            31:16
+#define BLIT_POINT_DST                                              0x0000A304
+#define BLIT_POINT_DST_X                                            15:0
+#define BLIT_POINT_DST_Y                                            31:16
+#define BLIT_SIZE                                                   0x0000A308
+#define BLIT_SIZE_WIDTH                                             15:0
+#define BLIT_SIZE_HEIGHT                                            31:16
+
+#define RECT_FORMAT                                                 0x0000C300
+#define RECT_FORMAT_DEPTH8                                          0x00000003
+#define RECT_FORMAT_DEPTH16                                         0x00000001
+#define RECT_FORMAT_DEPTH24                                         0x00000003
+#define RECT_SOLID_COLOR                                            0x0000C3FC
+#define RECT_SOLID_RECTS_MAX_RECTS                                  32
+#define RECT_SOLID_RECTS(i)                                         0x0000C400\
+                                                                    +(i)*8
+#define RECT_SOLID_RECTS_Y                                          15:0
+#define RECT_SOLID_RECTS_X                                          31:16
+#define RECT_SOLID_RECTS_HEIGHT                                     47:32
+#define RECT_SOLID_RECTS_WIDTH                                      63:48
+
+#define RECT_EXPAND_ONE_COLOR_CLIP                                  0x0000C7EC
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_ONE_COLOR_COLOR                                 0x0000C7F4
+#define RECT_EXPAND_ONE_COLOR_SIZE                                  0x0000C7F8
+#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH                            15:0
+#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT                           31:16
+#define RECT_EXPAND_ONE_COLOR_POINT                                 0x0000C7FC
+#define RECT_EXPAND_ONE_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_ONE_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_ONE_COLOR_DATA(i)                               0x0000C800\
+                                                                    +(i)*4
+
+#define RECT_EXPAND_TWO_COLOR_CLIP                                  0x0000CBE4
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_TWO_COLOR_COLOR_0                               0x0000CBEC
+#define RECT_EXPAND_TWO_COLOR_COLOR_1                               0x0000CBF0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN                               0x0000CBF4
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH                         15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT                        31:16
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT                              0x0000CBF8
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH                        15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT                       31:16
+#define RECT_EXPAND_TWO_COLOR_POINT                                 0x0000CBFC
+#define RECT_EXPAND_TWO_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_TWO_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_TWO_COLOR_DATA(i)                               0x0000CC00\
+                                                                    +(i)*4
+
+#define STRETCH_BLIT_FORMAT                                         0x0000E300
+#define STRETCH_BLIT_FORMAT_DEPTH8                                  0x00000004
+#define STRETCH_BLIT_FORMAT_DEPTH16                                 0x00000007
+#define STRETCH_BLIT_FORMAT_DEPTH24                                 0x00000004
+#define STRETCH_BLIT_FORMAT_X8R8G8B8                                0x00000004
+#define STRETCH_BLIT_FORMAT_YUYV                                    0x00000005
+#define STRETCH_BLIT_FORMAT_UYVY                                    0x00000006
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_POINT_X                                   15:0
+#define STRETCH_BLIT_CLIP_POINT_Y                                   31:16
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_SIZE                                      0x0000E30C
+#define STRETCH_BLIT_CLIP_SIZE_WIDTH                                15:0
+#define STRETCH_BLIT_CLIP_SIZE_HEIGHT                               31:16
+#define STRETCH_BLIT_DST_POINT                                      0x0000E310
+#define STRETCH_BLIT_DST_POINT_X                                    15:0
+#define STRETCH_BLIT_DST_POINT_Y                                    31:16
+#define STRETCH_BLIT_DST_SIZE                                       0x0000E314
+#define STRETCH_BLIT_DST_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_DST_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_DU_DX                                          0x0000E318
+#define STRETCH_BLIT_DV_DY                                          0x0000E31C
+#define STRETCH_BLIT_SRC_SIZE                                       0x0000E400
+#define STRETCH_BLIT_SRC_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_SRC_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_SRC_FORMAT                                     0x0000E404
+#define STRETCH_BLIT_SRC_FORMAT_PITCH                               15:0
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN                              23:16
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER                       0x00000001
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER                       0x00000002
+#define STRETCH_BLIT_SRC_FORMAT_FILTER                              31:24
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE                 0x00000000
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR                     0x00000001
+#define STRETCH_BLIT_SRC_OFFSET                                     0x0000E408
+#define STRETCH_BLIT_SRC_POINT                                      0x0000E40C
+#define STRETCH_BLIT_SRC_POINT_U                                    15:0
+#define STRETCH_BLIT_SRC_POINT_V                                    31:16
diff -puN /dev/null drivers/video/nvidia/nv_hw.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_hw.c	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,1582 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING 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 SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
+
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+
+void NVLockUnlock(struct nvidia_par *par, int Lock)
+{
+	u8 cr11;
+
+	VGA_WR08(par->PCIO, 0x3D4, 0x1F);
+	VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+
+	VGA_WR08(par->PCIO, 0x3D4, 0x11);
+	cr11 = VGA_RD08(par->PCIO, 0x3D5);
+	if (Lock)
+		cr11 |= 0x80;
+	else
+		cr11 &= ~0x80;
+	VGA_WR08(par->PCIO, 0x3D5, cr11);
+}
+
+int NVShowHideCursor(struct nvidia_par *par, int ShowHide)
+{
+	int cur = par->CurrentState->cursor1;
+
+	par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) |
+	    (ShowHide & 0x01);
+	VGA_WR08(par->PCIO, 0x3D4, 0x31);
+	VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1);
+
+	if (par->Architecture == NV_ARCH_40)
+		NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300));
+
+	return (cur & 0x01);
+}
+
+/****************************************************************************\
+*                                                                            *
+* The video arbitration routines calculate some "magic" numbers.  Fixes      *
+* the snow seen when accessing the framebuffer without it.                   *
+* It just works (I hope).                                                    *
+*                                                                            *
+\****************************************************************************/
+
+typedef struct {
+	int graphics_lwm;
+	int video_lwm;
+	int graphics_burst_size;
+	int video_burst_size;
+	int valid;
+} nv4_fifo_info;
+
+typedef struct {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	char mem_page_miss;
+	char mem_latency;
+	int memory_width;
+	char enable_video;
+	char gr_during_vid;
+	char pix_bpp;
+	char mem_aligned;
+	char enable_mp;
+} nv4_sim_state;
+
+typedef struct {
+	int graphics_lwm;
+	int video_lwm;
+	int graphics_burst_size;
+	int video_burst_size;
+	int valid;
+} nv10_fifo_info;
+
+typedef struct {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	char mem_page_miss;
+	char mem_latency;
+	int memory_type;
+	int memory_width;
+	char enable_video;
+	char gr_during_vid;
+	char pix_bpp;
+	char mem_aligned;
+	char enable_mp;
+} nv10_sim_state;
+
+static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
+			unsigned int *NVClk)
+{
+	unsigned int pll, N, M, MB, NB, P;
+
+	if (par->Architecture >= NV_ARCH_40) {
+		pll = NV_RD32(par->PMC, 0x4020);
+		P = (pll >> 16) & 0x03;
+		pll = NV_RD32(par->PMC, 0x4024);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		MB = (pll >> 16) & 0xFF;
+		NB = (pll >> 24) & 0xFF;
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PMC, 0x4000);
+		P = (pll >> 16) & 0x03;
+		pll = NV_RD32(par->PMC, 0x4004);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		MB = (pll >> 16) & 0xFF;
+		NB = (pll >> 24) & 0xFF;
+
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else if (par->twoStagePLL) {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		pll = NV_RD32(par->PRAMDAC0, 0x0574);
+		if (pll & 0x80000000) {
+			MB = pll & 0xFF;
+			NB = (pll >> 8) & 0xFF;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		pll = NV_RD32(par->PRAMDAC0, 0x0570);
+		if (pll & 0x80000000) {
+			MB = pll & 0xFF;
+			NB = (pll >> 8) & 0xFF;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else
+	    if (((par->Chipset & 0x0ff0) == 0x0300) ||
+		((par->Chipset & 0x0ff0) == 0x0330)) {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0x0F;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x07;
+		if (pll & 0x00000080) {
+			MB = (pll >> 4) & 0x07;
+			NB = (pll >> 19) & 0x1f;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0x0F;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x07;
+		if (pll & 0x00000080) {
+			MB = (pll >> 4) & 0x07;
+			NB = (pll >> 19) & 0x1f;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		*MClk = (N * par->CrystalFreqKHz / M) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		*NVClk = (N * par->CrystalFreqKHz / M) >> P;
+	}
+}
+
+static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb)
+{
+	int data, pagemiss, cas, width, video_enable, bpp;
+	int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+	int found, mclk_extra, mclk_loop, cbs, m1, p1;
+	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+	int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
+	int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
+
+	fifo->valid = 1;
+	pclk_freq = arb->pclk_khz;
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	cas = arb->mem_latency;
+	width = arb->memory_width >> 6;
+	video_enable = arb->enable_video;
+	bpp = arb->pix_bpp;
+	mp_enable = arb->enable_mp;
+	clwm = 0;
+	vlwm = 0;
+	cbs = 128;
+	pclks = 2;
+	nvclks = 2;
+	nvclks += 2;
+	nvclks += 1;
+	mclks = 5;
+	mclks += 3;
+	mclks += 1;
+	mclks += cas;
+	mclks += 1;
+	mclks += 1;
+	mclks += 1;
+	mclks += 1;
+	mclk_extra = 3;
+	nvclks += 2;
+	nvclks += 1;
+	nvclks += 1;
+	nvclks += 1;
+	if (mp_enable)
+		mclks += 4;
+	nvclks += 0;
+	pclks += 0;
+	found = 0;
+	vbs = 0;
+	while (found != 1) {
+		fifo->valid = 1;
+		found = 1;
+		mclk_loop = mclks + mclk_extra;
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		us_p = nvclks * 1000 * 1000 / pclk_freq;
+		if (video_enable) {
+			video_drain_rate = pclk_freq * 2;
+			crtc_drain_rate = pclk_freq * bpp / 8;
+			vpagemiss = 2;
+			vpagemiss += 1;
+			crtpagemiss = 2;
+			vpm_us =
+			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+			if (nvclk_freq * 2 > mclk_freq * width)
+				video_fill_us =
+				    cbs * 1000 * 1000 / 16 / nvclk_freq;
+			else
+				video_fill_us =
+				    cbs * 1000 * 1000 / (8 * width) /
+				    mclk_freq;
+			us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
+			vlwm = us_video * video_drain_rate / (1000 * 1000);
+			vlwm++;
+			vbs = 128;
+			if (vlwm > 128)
+				vbs = 64;
+			if (vlwm > (256 - 64))
+				vbs = 32;
+			if (nvclk_freq * 2 > mclk_freq * width)
+				video_fill_us =
+				    vbs * 1000 * 1000 / 16 / nvclk_freq;
+			else
+				video_fill_us =
+				    vbs * 1000 * 1000 / (8 * width) /
+				    mclk_freq;
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt =
+			    us_video + video_fill_us + cpm_us + us_m + us_n +
+			    us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			clwm++;
+		} else {
+			crtc_drain_rate = pclk_freq * bpp / 8;
+			crtpagemiss = 2;
+			crtpagemiss += 1;
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt = cpm_us + us_m + us_n + us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			clwm++;
+		}
+		m1 = clwm + cbs - 512;
+		p1 = m1 * pclk_freq / mclk_freq;
+		p1 = p1 * bpp / 8;
+		if ((p1 < m1) && (m1 > 0)) {
+			fifo->valid = 0;
+			found = 0;
+			if (mclk_extra == 0)
+				found = 1;
+			mclk_extra--;
+		} else if (video_enable) {
+			if ((clwm > 511) || (vlwm > 255)) {
+				fifo->valid = 0;
+				found = 0;
+				if (mclk_extra == 0)
+					found = 1;
+				mclk_extra--;
+			}
+		} else {
+			if (clwm > 519) {
+				fifo->valid = 0;
+				found = 0;
+				if (mclk_extra == 0)
+					found = 1;
+				mclk_extra--;
+			}
+		}
+		if (clwm < 384)
+			clwm = 384;
+		if (vlwm < 128)
+			vlwm = 128;
+		data = (int)(clwm);
+		fifo->graphics_lwm = data;
+		fifo->graphics_burst_size = 128;
+		data = (int)((vlwm + 15));
+		fifo->video_lwm = data;
+		fifo->video_burst_size = vbs;
+	}
+}
+
+static void nv4UpdateArbitrationSettings(unsigned VClk,
+					 unsigned pixelDepth,
+					 unsigned *burst,
+					 unsigned *lwm, struct nvidia_par *par)
+{
+	nv4_fifo_info fifo_data;
+	nv4_sim_state sim_data;
+	unsigned int MClk, NVClk, cfg1;
+
+	nvGetClocks(par, &MClk, &NVClk);
+
+	cfg1 = NV_RD32(par->PFB, 0x00000204);
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 0;
+	sim_data.enable_mp = 0;
+	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+	    128 : 64;
+	sim_data.mem_latency = (char)cfg1 & 0x0F;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss =
+	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv4CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb)
+{
+	int data, pagemiss, width, video_enable, bpp;
+	int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
+	int nvclk_fill;
+	int found, mclk_extra, mclk_loop, cbs, m1;
+	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+	int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
+	int vus_m;
+	int vpm_us, us_video, cpm_us, us_crt, clwm;
+	int clwm_rnd_down;
+	int m2us, us_pipe_min, p1clk, p2;
+	int min_mclk_extra;
+	int us_min_mclk_extra;
+
+	fifo->valid = 1;
+	pclk_freq = arb->pclk_khz;	/* freq in KHz */
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	width = arb->memory_width / 64;
+	video_enable = arb->enable_video;
+	bpp = arb->pix_bpp;
+	mp_enable = arb->enable_mp;
+	clwm = 0;
+
+	cbs = 512;
+
+	pclks = 4;	/* lwm detect. */
+
+	nvclks = 3;	/* lwm -> sync. */
+	nvclks += 2;	/* fbi bus cycles (1 req + 1 busy) */
+	/* 2 edge sync.  may be very close to edge so just put one. */
+	mclks = 1;
+	mclks += 1;	/* arb_hp_req */
+	mclks += 5;	/* ap_hp_req   tiling pipeline */
+
+	mclks += 2;	/* tc_req     latency fifo */
+	mclks += 2;	/* fb_cas_n_  memory request to fbio block */
+	mclks += 7;	/* sm_d_rdv   data returned from fbio block */
+
+	/* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
+	if (arb->memory_type == 0)
+		if (arb->memory_width == 64)	/* 64 bit bus */
+			mclks += 4;
+		else
+			mclks += 2;
+	else if (arb->memory_width == 64)	/* 64 bit bus */
+		mclks += 2;
+	else
+		mclks += 1;
+
+	if ((!video_enable) && (arb->memory_width == 128)) {
+		mclk_extra = (bpp == 32) ? 31 : 42;	/* Margin of error */
+		min_mclk_extra = 17;
+	} else {
+		mclk_extra = (bpp == 32) ? 8 : 4;	/* Margin of error */
+		/* mclk_extra = 4; *//* Margin of error */
+		min_mclk_extra = 18;
+	}
+
+	/* 2 edge sync.  may be very close to edge so just put one. */
+	nvclks += 1;
+	nvclks += 1;		/* fbi_d_rdv_n */
+	nvclks += 1;		/* Fbi_d_rdata */
+	nvclks += 1;		/* crtfifo load */
+
+	if (mp_enable)
+		mclks += 4;	/* Mp can get in with a burst of 8. */
+	/* Extra clocks determined by heuristics */
+
+	nvclks += 0;
+	pclks += 0;
+	found = 0;
+	while (found != 1) {
+		fifo->valid = 1;
+		found = 1;
+		mclk_loop = mclks + mclk_extra;
+		/* Mclk latency in us */
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		/* Minimum Mclk latency in us */
+		us_m_min = mclks * 1000 * 1000 / mclk_freq;
+		us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
+		/* nvclk latency in us */
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		/* nvclk latency in us */
+		us_p = pclks * 1000 * 1000 / pclk_freq;
+		us_pipe_min = us_m_min + us_n + us_p;
+
+		/* Mclk latency in us */
+		vus_m = mclk_loop * 1000 * 1000 / mclk_freq;
+
+		if (video_enable) {
+			crtc_drain_rate = pclk_freq * bpp / 8;	/* MB/s */
+
+			vpagemiss = 1;	/* self generating page miss */
+			vpagemiss += 1;	/* One higher priority before */
+
+			crtpagemiss = 2;	/* self generating page miss */
+			if (mp_enable)
+				crtpagemiss += 1;	/* if MA0 conflict */
+
+			vpm_us =
+			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+
+			/* Video has separate read return path */
+			us_video = vpm_us + vus_m;
+
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			/* Wait for video */
+			us_crt = us_video
+			    + cpm_us	/* CRT Page miss */
+			    + us_m + us_n + us_p	/* other latency */
+			    ;
+
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			/* fixed point <= float_point - 1.  Fixes that */
+			clwm++;
+		} else {
+		    /* bpp * pclk/8 */
+			crtc_drain_rate = pclk_freq * bpp / 8;
+
+			crtpagemiss = 1;	/* self generating page miss */
+			crtpagemiss += 1;	/* MA0 page miss */
+			if (mp_enable)
+				crtpagemiss += 1;	/* if MA0 conflict */
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt = cpm_us + us_m + us_n + us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			/* fixed point <= float_point - 1.  Fixes that */
+			clwm++;
+
+			/* Finally, a heuristic check when width == 64 bits */
+			if (width == 1) {
+				nvclk_fill = nvclk_freq * 8;
+				if (crtc_drain_rate * 100 >= nvclk_fill * 102)
+					/*Large number to fail */
+					clwm = 0xfff;
+
+				else if (crtc_drain_rate * 100 >=
+					 nvclk_fill * 98) {
+					clwm = 1024;
+					cbs = 512;
+				}
+			}
+		}
+
+		/*
+		   Overfill check:
+		 */
+
+		clwm_rnd_down = ((int)clwm / 8) * 8;
+		if (clwm_rnd_down < clwm)
+			clwm += 8;
+
+		m1 = clwm + cbs - 1024;	/* Amount of overfill */
+		m2us = us_pipe_min + us_min_mclk_extra;
+
+		/* pclk cycles to drain */
+		p1clk = m2us * pclk_freq / (1000 * 1000);
+		p2 = p1clk * bpp / 8;	/* bytes drained. */
+
+		if ((p2 < m1) && (m1 > 0)) {
+			fifo->valid = 0;
+			found = 0;
+			if (min_mclk_extra == 0) {
+				if (cbs <= 32) {
+					/* Can't adjust anymore! */
+					found = 1;
+				} else {
+					/* reduce the burst size */
+					cbs = cbs / 2;
+				}
+			} else {
+				min_mclk_extra--;
+			}
+		} else {
+			if (clwm > 1023) {	/* Have some margin */
+				fifo->valid = 0;
+				found = 0;
+				if (min_mclk_extra == 0)
+					/* Can't adjust anymore! */
+					found = 1;
+				else
+					min_mclk_extra--;
+			}
+		}
+
+		if (clwm < (1024 - cbs + 8))
+			clwm = 1024 - cbs + 8;
+		data = (int)(clwm);
+		/*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n",
+		    clwm, data ); */
+		fifo->graphics_lwm = data;
+		fifo->graphics_burst_size = cbs;
+
+		fifo->video_lwm = 1024;
+		fifo->video_burst_size = 512;
+	}
+}
+
+static void nv10UpdateArbitrationSettings(unsigned VClk,
+					  unsigned pixelDepth,
+					  unsigned *burst,
+					  unsigned *lwm,
+					  struct nvidia_par *par)
+{
+	nv10_fifo_info fifo_data;
+	nv10_sim_state sim_data;
+	unsigned int MClk, NVClk, cfg1;
+
+	nvGetClocks(par, &MClk, &NVClk);
+
+	cfg1 = NV_RD32(par->PFB, 0x0204);
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 1;
+	sim_data.enable_mp = 0;
+	sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 0;
+	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+	    128 : 64;
+	sim_data.mem_latency = (char)cfg1 & 0x0F;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss =
+	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv10CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+static void nv30UpdateArbitrationSettings (
+    struct nvidia_par *par,
+    unsigned int      *burst,
+    unsigned int      *lwm
+)
+{
+    unsigned int MClk, NVClk;
+    unsigned int fifo_size, burst_size, graphics_lwm;
+
+    fifo_size = 2048;
+    burst_size = 512;
+    graphics_lwm = fifo_size - burst_size;
+
+    nvGetClocks(par, &MClk, &NVClk);
+
+    *burst = 0;
+    burst_size >>= 5;
+    while(burst_size >>= 1) (*burst)++;
+    *lwm = graphics_lwm >> 3;
+}
+
+static void nForceUpdateArbitrationSettings(unsigned VClk,
+					    unsigned pixelDepth,
+					    unsigned *burst,
+					    unsigned *lwm,
+					    struct nvidia_par *par)
+{
+	nv10_fifo_info fifo_data;
+	nv10_sim_state sim_data;
+	unsigned int M, N, P, pll, MClk, NVClk, memctrl;
+	struct pci_dev *dev;
+
+	if ((par->Chipset & 0x0FF0) == 0x01A0) {
+		unsigned int uMClkPostDiv;
+		dev = pci_find_slot(0, 3);
+		pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+		uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
+
+		if (!uMClkPostDiv)
+			uMClkPostDiv = 4;
+		MClk = 400000 / uMClkPostDiv;
+	} else {
+		dev = pci_find_slot(0, 5);
+		pci_read_config_dword(dev, 0x4c, &MClk);
+		MClk /= 1000;
+	}
+
+	pll = NV_RD32(par->PRAMDAC0, 0x0500);
+	M = (pll >> 0) & 0xFF;
+	N = (pll >> 8) & 0xFF;
+	P = (pll >> 16) & 0x0F;
+	NVClk = (N * par->CrystalFreqKHz / M) >> P;
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 0;
+	sim_data.enable_mp = 0;
+	pci_find_slot(0, 1);
+	pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+	sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
+	sim_data.memory_width = 64;
+
+	dev = pci_find_slot(0, 3);
+	pci_read_config_dword(dev, 0, &memctrl);
+	memctrl >>= 16;
+
+	if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
+		int dimm[3];
+
+		pci_find_slot(0, 2);
+		pci_read_config_dword(dev, 0x40, &dimm[0]);
+		dimm[0] = (dimm[0] >> 8) & 0x4f;
+		pci_read_config_dword(dev, 0x44, &dimm[1]);
+		dimm[1] = (dimm[1] >> 8) & 0x4f;
+		pci_read_config_dword(dev, 0x48, &dimm[2]);
+		dimm[2] = (dimm[2] >> 8) & 0x4f;
+
+		if ((dimm[0] + dimm[1]) != dimm[2]) {
+			printk("nvidiafb: your nForce DIMMs are not arranged "
+			       "in optimal banks!\n");
+		}
+	}
+
+	sim_data.mem_latency = 3;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss = 10;
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv10CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+/****************************************************************************\
+*                                                                            *
+*                          RIVA Mode State Routines                          *
+*                                                                            *
+\****************************************************************************/
+
+/*
+ * Calculate the Video Clock parameters for the PLL.
+ */
+static void CalcVClock(int clockIn,
+		       int *clockOut, u32 * pllOut, struct nvidia_par *par)
+{
+	unsigned lowM, highM;
+	unsigned DeltaNew, DeltaOld;
+	unsigned VClk, Freq;
+	unsigned M, N, P;
+
+	DeltaOld = 0xFFFFFFFF;
+
+	VClk = (unsigned)clockIn;
+
+	if (par->CrystalFreqKHz == 13500) {
+		lowM = 7;
+		highM = 13;
+	} else {
+		lowM = 8;
+		highM = 14;
+	}
+
+	for (P = 0; P <= 4; P++) {
+		Freq = VClk << P;
+		if ((Freq >= 128000) && (Freq <= 350000)) {
+			for (M = lowM; M <= highM; M++) {
+				N = ((VClk << P) * M) / par->CrystalFreqKHz;
+				if (N <= 255) {
+					Freq =
+					    ((par->CrystalFreqKHz * N) /
+					     M) >> P;
+					if (Freq > VClk)
+						DeltaNew = Freq - VClk;
+					else
+						DeltaNew = VClk - Freq;
+					if (DeltaNew < DeltaOld) {
+						*pllOut =
+						    (P << 16) | (N << 8) | M;
+						*clockOut = Freq;
+						DeltaOld = DeltaNew;
+					}
+				}
+			}
+		}
+	}
+}
+
+static void CalcVClock2Stage(int clockIn,
+			     int *clockOut,
+			     u32 * pllOut,
+			     u32 * pllBOut, struct nvidia_par *par)
+{
+	unsigned DeltaNew, DeltaOld;
+	unsigned VClk, Freq;
+	unsigned M, N, P;
+
+	DeltaOld = 0xFFFFFFFF;
+
+	*pllBOut = 0x80000401;	/* fixed at x4 for now */
+
+	VClk = (unsigned)clockIn;
+
+	for (P = 0; P <= 6; P++) {
+		Freq = VClk << P;
+		if ((Freq >= 400000) && (Freq <= 1000000)) {
+			for (M = 1; M <= 13; M++) {
+				N = ((VClk << P) * M) /
+				    (par->CrystalFreqKHz << 2);
+				if ((N >= 5) && (N <= 255)) {
+					Freq =
+					    (((par->CrystalFreqKHz << 2) * N) /
+					     M) >> P;
+					if (Freq > VClk)
+						DeltaNew = Freq - VClk;
+					else
+						DeltaNew = VClk - Freq;
+					if (DeltaNew < DeltaOld) {
+						*pllOut =
+						    (P << 16) | (N << 8) | M;
+						*clockOut = Freq;
+						DeltaOld = DeltaNew;
+					}
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Calculate extended mode parameters (SVGA) and save in a
+ * mode state structure.
+ */
+void NVCalcStateExt(struct nvidia_par *par,
+		    RIVA_HW_STATE * state,
+		    int bpp,
+		    int width,
+		    int hDisplaySize, int height, int dotClock, int flags)
+{
+	int pixelDepth, VClk;
+	/*
+	 * Save mode parameters.
+	 */
+	state->bpp = bpp;	/* this is not bitsPerPixel, it's 8,15,16,32 */
+	state->width = width;
+	state->height = height;
+	/*
+	 * Extended RIVA registers.
+	 */
+	pixelDepth = (bpp + 1) / 8;
+	if (par->twoStagePLL)
+		CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB,
+				 par);
+	else
+		CalcVClock(dotClock, &VClk, &state->pll, par);
+
+	switch (par->Architecture) {
+	case NV_ARCH_04:
+		nv4UpdateArbitrationSettings(VClk,
+					     pixelDepth * 8,
+					     &(state->arbitration0),
+					     &(state->arbitration1), par);
+		state->cursor0 = 0x00;
+		state->cursor1 = 0xbC;
+		if (flags & FB_VMODE_DOUBLE)
+			state->cursor1 |= 2;
+		state->cursor2 = 0x00000000;
+		state->pllsel = 0x10000700;
+		state->config = 0x00001114;
+		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+		break;
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_30:
+	default:
+		if (((par->Chipset & 0xffff) == 0x01A0) ||
+		    ((par->Chipset & 0xffff) == 0x01f0)) {
+			nForceUpdateArbitrationSettings(VClk,
+							pixelDepth * 8,
+							&(state->arbitration0),
+							&(state->arbitration1),
+							par);
+		} else if (par->Architecture < NV_ARCH_30) {
+			nv10UpdateArbitrationSettings(VClk,
+						      pixelDepth * 8,
+						      &(state->arbitration0),
+						      &(state->arbitration1),
+						      par);
+		} else {
+			nv30UpdateArbitrationSettings(par,
+						      &(state->arbitration0),
+						      &(state->arbitration1));
+		}
+
+		state->cursor0 = 0x80 | (par->CursorStart >> 17);
+		state->cursor1 = (par->CursorStart >> 11) << 2;
+		state->cursor2 = par->CursorStart >> 24;
+		if (flags & FB_VMODE_DOUBLE)
+			state->cursor1 |= 2;
+		state->pllsel = 0x10000700;
+		state->config = NV_RD32(par->PFB, 0x00000200);
+		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+		break;
+	}
+
+	if (bpp != 8)		/* DirectColor */
+		state->general |= 0x00000030;
+
+	state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
+	state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
+}
+
+void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
+{
+	int i;
+
+	NV_WR32(par->PMC, 0x0140, 0x00000000);
+	NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
+	NV_WR32(par->PMC, 0x0200, 0xFFFFFFFF);
+
+	NV_WR32(par->PTIMER, 0x0200 * 4, 0x00000008);
+	NV_WR32(par->PTIMER, 0x0210 * 4, 0x00000003);
+	NV_WR32(par->PTIMER, 0x0140 * 4, 0x00000000);
+	NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
+
+	if (par->Architecture == NV_ARCH_04) {
+		NV_WR32(par->PFB, 0x0200, state->config);
+	} else if ((par->Chipset & 0xfff0) == 0x0090) {
+		for (i = 0; i < 15; i++) {
+			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1);
+		}
+	} else {
+		for (i = 0; i < 8; i++) {
+			NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+		}
+	}
+
+	if (par->Architecture >= NV_ARCH_40) {
+		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x00101202);
+		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x00101204);
+		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x00101206);
+		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x00101208);
+		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x0010120A);
+		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+		NV_WR32(par->PRAMIN, 0x000B * 4, 0x0010120C);
+		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+		NV_WR32(par->PRAMIN, 0x000D * 4, 0x0010120E);
+		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+		NV_WR32(par->PRAMIN, 0x000F * 4, 0x00101210);
+		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x02080062);
+		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x080C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x02080043);
+		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0818 * 4, 0x02080044);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x02000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x02080019);
+		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0828 * 4, 0x020A005C);
+		NV_WR32(par->PRAMIN, 0x0829 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0830 * 4, 0x0208009F);
+		NV_WR32(par->PRAMIN, 0x0831 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0832 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0833 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0834 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0835 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0838 * 4, 0x0208004A);
+		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x02000000);
+		NV_WR32(par->PRAMIN, 0x083A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0840 * 4, 0x02080077);
+		NV_WR32(par->PRAMIN, 0x0841 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0842 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0843 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0844 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0845 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x084C * 4, 0x00003002);
+		NV_WR32(par->PRAMIN, 0x084D * 4, 0x00007FFF);
+		NV_WR32(par->PRAMIN, 0x084E * 4,
+			par->FbUsableSize | 0x00000002);
+
+#ifdef __BIG_ENDIAN
+		NV_WR32(par->PRAMIN, 0x080A * 4,
+			NV_RD32(par->PRAMIN, 0x080A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4,
+			NV_RD32(par->PRAMIN, 0x0812 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4,
+			NV_RD32(par->PRAMIN, 0x081A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4,
+			NV_RD32(par->PRAMIN, 0x0822 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x082A * 4,
+			NV_RD32(par->PRAMIN, 0x082A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0832 * 4,
+			NV_RD32(par->PRAMIN, 0x0832 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x083A * 4,
+			NV_RD32(par->PRAMIN, 0x083A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0842 * 4,
+			NV_RD32(par->PRAMIN, 0x0842 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x01000000);
+#endif
+	} else {
+		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x80011201);
+		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x80011202);
+		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x80011203);
+		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x80011204);
+		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x80011205);
+		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+		NV_WR32(par->PRAMIN, 0x000B * 4, 0x80011206);
+		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+		NV_WR32(par->PRAMIN, 0x000D * 4, 0x80011207);
+		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+		NV_WR32(par->PRAMIN, 0x000F * 4, 0x80011208);
+		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0803 * 4, 0x00000002);
+		if (par->Architecture >= NV_ARCH_10)
+			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008062);
+		else
+			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008042);
+		NV_WR32(par->PRAMIN, 0x0805 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0806 * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x0807 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x01008043);
+		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080C * 4, 0x01008044);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x080E * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080F * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x01008019);
+		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x0100A05C);
+		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0816 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0817 * 4, 0x00000000);
+		if (par->WaitVSyncPossible)
+			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100809F);
+		else
+			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100805F);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081C * 4, 0x0100804A);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x081E * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081F * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x01018077);
+		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00003002);
+		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00007FFF);
+		NV_WR32(par->PRAMIN, 0x0826 * 4,
+			par->FbUsableSize | 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0827 * 4, 0x00000002);
+#ifdef __BIG_ENDIAN
+		NV_WR32(par->PRAMIN, 0x0804 * 4,
+			NV_RD32(par->PRAMIN, 0x0804 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0808 * 4,
+			NV_RD32(par->PRAMIN, 0x0808 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x080C * 4,
+			NV_RD32(par->PRAMIN, 0x080C * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4,
+			NV_RD32(par->PRAMIN, 0x0810 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4,
+			NV_RD32(par->PRAMIN, 0x0814 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0818 * 4,
+			NV_RD32(par->PRAMIN, 0x0818 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x081C * 4,
+			NV_RD32(par->PRAMIN, 0x081C * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4,
+			NV_RD32(par->PRAMIN, 0x0820 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000001);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000001);
+#endif
+	}
+	if (par->Architecture < NV_ARCH_10) {
+		if ((par->Chipset & 0x0fff) == 0x0020) {
+			NV_WR32(par->PRAMIN, 0x0824 * 4,
+				NV_RD32(par->PRAMIN, 0x0824 * 4) | 0x00020000);
+			NV_WR32(par->PRAMIN, 0x0826 * 4,
+				NV_RD32(par->PRAMIN,
+					0x0826 * 4) + par->FbAddress);
+		}
+		NV_WR32(par->PGRAPH, 0x0080, 0x000001FF);
+		NV_WR32(par->PGRAPH, 0x0080, 0x1230C000);
+		NV_WR32(par->PGRAPH, 0x0084, 0x72111101);
+		NV_WR32(par->PGRAPH, 0x0088, 0x11D5F071);
+		NV_WR32(par->PGRAPH, 0x008C, 0x0004FF31);
+		NV_WR32(par->PGRAPH, 0x008C, 0x4004FF31);
+		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0170, 0x10010100);
+		NV_WR32(par->PGRAPH, 0x0710, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+		NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+	} else {
+		NV_WR32(par->PGRAPH, 0x0080, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0080, 0x00000000);
+
+		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0144, 0x10010100);
+		NV_WR32(par->PGRAPH, 0x0714, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+		NV_WR32(par->PGRAPH, 0x0710,
+			NV_RD32(par->PGRAPH, 0x0710) & 0x0007ff00);
+		NV_WR32(par->PGRAPH, 0x0710,
+			NV_RD32(par->PGRAPH, 0x0710) | 0x00020100);
+
+		if (par->Architecture == NV_ARCH_10) {
+			NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+			NV_WR32(par->PGRAPH, 0x0088, 0x24E00810);
+			NV_WR32(par->PGRAPH, 0x008C, 0x55DE0030);
+
+			for (i = 0; i < 32; i++)
+				NV_WR32(&par->PGRAPH[(0x0B00 / 4) + i], 0,
+					NV_RD32(&par->PFB[(0x0240 / 4) + i],
+						0));
+
+			NV_WR32(par->PGRAPH, 0x640, 0);
+			NV_WR32(par->PGRAPH, 0x644, 0);
+			NV_WR32(par->PGRAPH, 0x684, par->FbMapSize - 1);
+			NV_WR32(par->PGRAPH, 0x688, par->FbMapSize - 1);
+
+			NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+		} else {
+			if (par->Architecture >= NV_ARCH_40) {
+				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
+				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+
+				if ((par->Chipset & 0xfff0) == 0x0040) {
+					NV_WR32(par->PGRAPH, 0x09b0,
+						0x83280fff);
+					NV_WR32(par->PGRAPH, 0x09b4,
+						0x000000a0);
+				} else {
+					NV_WR32(par->PGRAPH, 0x0820,
+						0x83280eff);
+					NV_WR32(par->PGRAPH, 0x0824,
+						0x000000a0);
+				}
+
+				switch (par->Chipset & 0xfff0) {
+				case 0x0040:
+				case 0x0210:
+					NV_WR32(par->PGRAPH, 0x09b8,
+						0x0078e366);
+					NV_WR32(par->PGRAPH, 0x09bc,
+						0x0000014c);
+					NV_WR32(par->PFB, 0x033C,
+						NV_RD32(par->PFB, 0x33C) &
+						0xffff7fff);
+					break;
+				case 0x00C0:
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x007596ff);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x00000108);
+					break;
+				case 0x0160:
+				case 0x01D0:
+					NV_WR32(par->PMC, 0x1700,
+						NV_RD32(par->PFB, 0x020C));
+					NV_WR32(par->PMC, 0x1704, 0);
+					NV_WR32(par->PMC, 0x1708, 0);
+					NV_WR32(par->PMC, 0x170C,
+						NV_RD32(par->PFB, 0x020C));
+					NV_WR32(par->PGRAPH, 0x0860, 0);
+					NV_WR32(par->PGRAPH, 0x0864, 0);
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC,
+							0x0608) | 0x00100000);
+					break;
+				case 0x0140:
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x0072cb77);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x00000108);
+					break;
+				case 0x0220:
+				case 0x0230:
+					NV_WR32(par->PGRAPH, 0x0860, 0);
+					NV_WR32(par->PGRAPH, 0x0864, 0);
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC, 0x0608) |
+						0x00100000);
+					break;
+				case 0x0090:
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC, 0x0608) |
+						0x00100000);
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x07830610);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x0000016A);
+					break;
+				default:
+					break;
+				};
+
+				NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800);
+				NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000);
+				NV_WR32(par->PGRAPH, 0x032C, 0x01000000);
+				NV_WR32(par->PGRAPH, 0x0220, 0x00001200);
+			} else if (par->Architecture == NV_ARCH_30) {
+				NV_WR32(par->PGRAPH, 0x0084, 0x40108700);
+				NV_WR32(par->PGRAPH, 0x0890, 0x00140000);
+				NV_WR32(par->PGRAPH, 0x008C, 0xf00e0431);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+				NV_WR32(par->PGRAPH, 0x0610, 0xf04b1f36);
+				NV_WR32(par->PGRAPH, 0x0B80, 0x1002d888);
+				NV_WR32(par->PGRAPH, 0x0B88, 0x62ff007f);
+			} else {
+				NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+				NV_WR32(par->PGRAPH, 0x008C, 0xF20E0431);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00000000);
+				NV_WR32(par->PGRAPH, 0x009C, 0x00000040);
+
+				if ((par->Chipset & 0x0ff0) >= 0x0250) {
+					NV_WR32(par->PGRAPH, 0x0890,
+						0x00080000);
+					NV_WR32(par->PGRAPH, 0x0610,
+						0x304B1FB6);
+					NV_WR32(par->PGRAPH, 0x0B80,
+						0x18B82880);
+					NV_WR32(par->PGRAPH, 0x0B84,
+						0x44000000);
+					NV_WR32(par->PGRAPH, 0x0098,
+						0x40000080);
+					NV_WR32(par->PGRAPH, 0x0B88,
+						0x000000ff);
+				} else {
+					NV_WR32(par->PGRAPH, 0x0880,
+						0x00080000);
+					NV_WR32(par->PGRAPH, 0x0094,
+						0x00000005);
+					NV_WR32(par->PGRAPH, 0x0B80,
+						0x45CAA208);
+					NV_WR32(par->PGRAPH, 0x0B84,
+						0x24000000);
+					NV_WR32(par->PGRAPH, 0x0098,
+						0x00000040);
+					NV_WR32(par->PGRAPH, 0x0750,
+						0x00E00038);
+					NV_WR32(par->PGRAPH, 0x0754,
+						0x00000030);
+					NV_WR32(par->PGRAPH, 0x0750,
+						0x00E10038);
+					NV_WR32(par->PGRAPH, 0x0754,
+						0x00000030);
+				}
+			}
+
+			if ((par->Chipset & 0xfff0) == 0x0090) {
+				for (i = 0; i < 60; i++)
+					NV_WR32(par->PGRAPH, 0x0D00 + i,
+						NV_RD32(par->PFB, 0x0600 + i));
+			} else {
+				for (i = 0; i < 32; i++)
+					NV_WR32(par->PGRAPH, 0x0900 + i,
+						NV_RD32(par->PFB, 0x0240 + i));
+			}
+
+			if (par->Architecture >= NV_ARCH_40) {
+				if ((par->Chipset & 0xfff0) == 0x0040) {
+					NV_WR32(par->PGRAPH, 0x09A4,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x09A8,
+						NV_RD32(par->PFB, 0x0204));
+					NV_WR32(par->PGRAPH, 0x69A4,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x69A8,
+						NV_RD32(par->PFB, 0x0204));
+
+					NV_WR32(par->PGRAPH, 0x0820, 0);
+					NV_WR32(par->PGRAPH, 0x0824, 0);
+					NV_WR32(par->PGRAPH, 0x0864,
+						par->FbMapSize - 1);
+					NV_WR32(par->PGRAPH, 0x0868,
+						par->FbMapSize - 1);
+				} else {
+					if((par->Chipset & 0xfff0) == 0x0090) {
+						NV_WR32(par->PGRAPH, 0x0DF0,
+							NV_RD32(par->PFB, 0x0200));
+						NV_WR32(par->PGRAPH, 0x0DF4,
+							NV_RD32(par->PFB, 0x0204));
+					} else {
+						NV_WR32(par->PGRAPH, 0x09F0,
+							NV_RD32(par->PFB, 0x0200));
+						NV_WR32(par->PGRAPH, 0x09F4,
+							NV_RD32(par->PFB, 0x0204));
+					}
+					NV_WR32(par->PGRAPH, 0x69F0,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x69F4,
+						NV_RD32(par->PFB, 0x0204));
+
+					NV_WR32(par->PGRAPH, 0x0840, 0);
+					NV_WR32(par->PGRAPH, 0x0844, 0);
+					NV_WR32(par->PGRAPH, 0x08a0,
+						par->FbMapSize - 1);
+					NV_WR32(par->PGRAPH, 0x08a4,
+						par->FbMapSize - 1);
+				}
+			} else {
+				NV_WR32(par->PGRAPH, 0x09A4,
+					NV_RD32(par->PFB, 0x0200));
+				NV_WR32(par->PGRAPH, 0x09A8,
+					NV_RD32(par->PFB, 0x0204));
+				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0000);
+				NV_WR32(par->PGRAPH, 0x0754,
+					NV_RD32(par->PFB, 0x0200));
+				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0004);
+				NV_WR32(par->PGRAPH, 0x0754,
+					NV_RD32(par->PFB, 0x0204));
+
+				NV_WR32(par->PGRAPH, 0x0820, 0);
+				NV_WR32(par->PGRAPH, 0x0824, 0);
+				NV_WR32(par->PGRAPH, 0x0864,
+					par->FbMapSize - 1);
+				NV_WR32(par->PGRAPH, 0x0868,
+					par->FbMapSize - 1);
+			}
+			NV_WR32(par->PGRAPH, 0x0B20, 0x00000000);
+			NV_WR32(par->PGRAPH, 0x0B04, 0xFFFFFFFF);
+		}
+	}
+	NV_WR32(par->PGRAPH, 0x053C, 0);
+	NV_WR32(par->PGRAPH, 0x0540, 0);
+	NV_WR32(par->PGRAPH, 0x0544, 0x00007FFF);
+	NV_WR32(par->PGRAPH, 0x0548, 0x00007FFF);
+
+	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0141 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000000);
+	if (par->Architecture >= NV_ARCH_40)
+		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00010000);
+	else
+		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00000100);
+	NV_WR32(par->PFIFO, 0x0490 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0491 * 4, 0x00000000);
+	if (par->Architecture >= NV_ARCH_40)
+		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001213);
+	else
+		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001209);
+	NV_WR32(par->PFIFO, 0x0400 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0414 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0084 * 4, 0x03000100);
+	NV_WR32(par->PFIFO, 0x0085 * 4, 0x00000110);
+	NV_WR32(par->PFIFO, 0x0086 * 4, 0x00000112);
+	NV_WR32(par->PFIFO, 0x0143 * 4, 0x0000FFFF);
+	NV_WR32(par->PFIFO, 0x0496 * 4, 0x0000FFFF);
+	NV_WR32(par->PFIFO, 0x0050 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0040 * 4, 0xFFFFFFFF);
+	NV_WR32(par->PFIFO, 0x0415 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x048C * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x04A0 * 4, 0x00000000);
+#ifdef __BIG_ENDIAN
+	NV_WR32(par->PFIFO, 0x0489 * 4, 0x800F0078);
+#else
+	NV_WR32(par->PFIFO, 0x0489 * 4, 0x000F0078);
+#endif
+	NV_WR32(par->PFIFO, 0x0488 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+	if (par->Architecture >= NV_ARCH_10) {
+		if (par->twoHeads) {
+			NV_WR32(par->PCRTC0, 0x0860, state->head);
+			NV_WR32(par->PCRTC0, 0x2860, state->head2);
+		}
+		NV_WR32(par->PRAMDAC, 0x0404, NV_RD32(par->PRAMDAC, 0x0404) |
+			(1 << 25));
+
+		NV_WR32(par->PMC, 0x8704, 1);
+		NV_WR32(par->PMC, 0x8140, 0);
+		NV_WR32(par->PMC, 0x8920, 0);
+		NV_WR32(par->PMC, 0x8924, 0);
+		NV_WR32(par->PMC, 0x8908, par->FbMapSize - 1);
+		NV_WR32(par->PMC, 0x890C, par->FbMapSize - 1);
+		NV_WR32(par->PMC, 0x1588, 0);
+
+		NV_WR32(par->PCRTC, 0x0810, state->cursorConfig);
+		NV_WR32(par->PCRTC, 0x0830, state->displayV - 3);
+		NV_WR32(par->PCRTC, 0x0834, state->displayV - 1);
+
+		if (par->FlatPanel) {
+			if ((par->Chipset & 0x0ff0) == 0x0110) {
+				NV_WR32(par->PRAMDAC, 0x0528, state->dither);
+			} else if (par->twoHeads) {
+				NV_WR32(par->PRAMDAC, 0x083C, state->dither);
+			}
+
+			VGA_WR08(par->PCIO, 0x03D4, 0x53);
+			VGA_WR08(par->PCIO, 0x03D5, state->timingH);
+			VGA_WR08(par->PCIO, 0x03D4, 0x54);
+			VGA_WR08(par->PCIO, 0x03D5, state->timingV);
+			VGA_WR08(par->PCIO, 0x03D4, 0x21);
+			VGA_WR08(par->PCIO, 0x03D5, 0xfa);
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x41);
+		VGA_WR08(par->PCIO, 0x03D5, state->extra);
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x19);
+	VGA_WR08(par->PCIO, 0x03D5, state->repaint0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+	VGA_WR08(par->PCIO, 0x03D5, state->repaint1);
+	VGA_WR08(par->PCIO, 0x03D4, 0x25);
+	VGA_WR08(par->PCIO, 0x03D5, state->screen);
+	VGA_WR08(par->PCIO, 0x03D4, 0x28);
+	VGA_WR08(par->PCIO, 0x03D5, state->pixel);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+	VGA_WR08(par->PCIO, 0x03D5, state->horiz);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	VGA_WR08(par->PCIO, 0x03D5, state->fifo);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+	VGA_WR08(par->PCIO, 0x03D5, state->arbitration0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x20);
+	VGA_WR08(par->PCIO, 0x03D5, state->arbitration1);
+
+	if(par->Architecture >= NV_ARCH_30) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x47);
+		VGA_WR08(par->PCIO, 0x03D5, state->arbitration1 >> 8);
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x30);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x31);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor1);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor2);
+	VGA_WR08(par->PCIO, 0x03D4, 0x39);
+	VGA_WR08(par->PCIO, 0x03D5, state->interlace);
+
+	if (!par->FlatPanel) {
+		NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
+		NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
+		if (par->twoHeads)
+			NV_WR32(par->PRAMDAC0, 0x0520, state->vpll2);
+		if (par->twoStagePLL) {
+			NV_WR32(par->PRAMDAC0, 0x0578, state->vpllB);
+			NV_WR32(par->PRAMDAC0, 0x057C, state->vpll2B);
+		}
+	} else {
+		NV_WR32(par->PRAMDAC, 0x0848, state->scale);
+		NV_WR32(par->PRAMDAC, 0x0828, state->crtcSync +
+			par->PanelTweak);
+	}
+
+	NV_WR32(par->PRAMDAC, 0x0600, state->general);
+
+	NV_WR32(par->PCRTC, 0x0140, 0);
+	NV_WR32(par->PCRTC, 0x0100, 1);
+
+	par->CurrentState = state;
+}
+
+void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) {
+	VGA_WR08(par->PCIO, 0x03D4, 0x19);
+	state->repaint0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+	state->repaint1 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x25);
+	state->screen = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x28);
+	state->pixel = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+	state->horiz = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	state->fifo         = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+	state->arbitration0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x20);
+	state->arbitration1 = VGA_RD08(par->PCIO, 0x03D5);
+
+	if(par->Architecture >= NV_ARCH_30) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x47);
+		state->arbitration1 |= (VGA_RD08(par->PCIO, 0x03D5) & 1) << 8;
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x30);
+	state->cursor0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x31);
+	state->cursor1 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+	state->cursor2 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x39);
+	state->interlace = VGA_RD08(par->PCIO, 0x03D5);
+	state->vpll = NV_RD32(par->PRAMDAC0, 0x0508);
+	if (par->twoHeads)
+		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+	if (par->twoStagePLL) {
+		state->vpllB = NV_RD32(par->PRAMDAC0, 0x0578);
+		state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+	}
+	state->pllsel = NV_RD32(par->PRAMDAC0, 0x050C);
+	state->general = NV_RD32(par->PRAMDAC, 0x0600);
+	state->scale = NV_RD32(par->PRAMDAC, 0x0848);
+	state->config = NV_RD32(par->PFB, 0x0200);
+
+	if (par->Architecture >= NV_ARCH_10) {
+		if (par->twoHeads) {
+			state->head = NV_RD32(par->PCRTC0, 0x0860);
+			state->head2 = NV_RD32(par->PCRTC0, 0x2860);
+			VGA_WR08(par->PCIO, 0x03D4, 0x44);
+			state->crtcOwner = VGA_RD08(par->PCIO, 0x03D5);
+		}
+		VGA_WR08(par->PCIO, 0x03D4, 0x41);
+		state->extra = VGA_RD08(par->PCIO, 0x03D5);
+		state->cursorConfig = NV_RD32(par->PCRTC, 0x0810);
+
+		if ((par->Chipset & 0x0ff0) == 0x0110) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x0528);
+		} else if (par->twoHeads) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x083C);
+		}
+
+		if (par->FlatPanel) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x53);
+			state->timingH = VGA_RD08(par->PCIO, 0x03D5);
+			VGA_WR08(par->PCIO, 0x03D4, 0x54);
+			state->timingV = VGA_RD08(par->PCIO, 0x03D5);
+		}
+	}
+}
+
+void NVSetStartAddress(struct nvidia_par *par, u32 start)
+{
+	NV_WR32(par->PCRTC, 0x800, start);
+}
diff -puN /dev/null drivers/video/nvidia/nv_i2c.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_i2c.c	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,209 @@
+/*
+ * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+#include "../edid.h"
+
+static void nvidia_gpio_setscl(void *data, int state)
+{
+	struct nvidia_i2c_chan *chan = data;
+	struct nvidia_par *par = chan->par;
+	u32 val;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x20;
+	else
+		val &= ~0x20;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+}
+
+static void nvidia_gpio_setsda(void *data, int state)
+{
+	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_par *par = chan->par;
+	u32 val;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x10;
+	else
+		val &= ~0x10;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+}
+
+static int nvidia_gpio_getscl(void *data)
+{
+	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_par *par = chan->par;
+	u32 val = 0;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->PCIO, 0x3d5) & 0x04)
+		val = 1;
+
+	val = VGA_RD08(par->PCIO, 0x3d5);
+
+	return val;
+}
+
+static int nvidia_gpio_getsda(void *data)
+{
+	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_par *par = chan->par;
+	u32 val = 0;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->PCIO, 0x3d5) & 0x08)
+		val = 1;
+
+	return val;
+}
+
+#define I2C_ALGO_NVIDIA   0x0e0000
+static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
+{
+	int rc;
+
+	strcpy(chan->adapter.name, name);
+	chan->adapter.owner = THIS_MODULE;
+	chan->adapter.id = I2C_ALGO_NVIDIA;
+	chan->adapter.algo_data = &chan->algo;
+	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
+	chan->algo.setsda = nvidia_gpio_setsda;
+	chan->algo.setscl = nvidia_gpio_setscl;
+	chan->algo.getsda = nvidia_gpio_getsda;
+	chan->algo.getscl = nvidia_gpio_getscl;
+	chan->algo.udelay = 40;
+	chan->algo.timeout = msecs_to_jiffies(2);
+	chan->algo.data = chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	nvidia_gpio_setsda(chan, 1);
+	nvidia_gpio_setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		dev_dbg(&chan->par->pci_dev->dev,
+			"I2C bus %s registered.\n", name);
+	else
+		dev_warn(&chan->par->pci_dev->dev,
+			 "Failed to register I2C bus %s.\n", name);
+	return rc;
+}
+
+void nvidia_create_i2c_busses(struct nvidia_par *par)
+{
+	par->bus = 3;
+
+	par->chan[0].par = par;
+	par->chan[1].par = par;
+	par->chan[2].par = par;
+
+	par->chan[0].ddc_base = 0x3e;
+	nvidia_setup_i2c_bus(&par->chan[0], "BUS1");
+
+	par->chan[1].ddc_base = 0x36;
+	nvidia_setup_i2c_bus(&par->chan[1], "BUS2");
+
+	par->chan[2].ddc_base = 0x50;
+	nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
+}
+
+void nvidia_delete_i2c_busses(struct nvidia_par *par)
+{
+	if (par->chan[0].par)
+		i2c_bit_del_bus(&par->chan[0].adapter);
+	par->chan[0].par = NULL;
+
+	if (par->chan[1].par)
+		i2c_bit_del_bus(&par->chan[1].adapter);
+	par->chan[1].par = NULL;
+
+	if (par->chan[2].par)
+		i2c_bit_del_bus(&par->chan[2].adapter);
+	par->chan[2].par = NULL;
+
+}
+
+static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
+{
+	u8 start = 0x0;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = 0x50,
+		 .len = 1,
+		 .buf = &start,
+		 }, {
+		     .addr = 0x50,
+		     .flags = I2C_M_RD,
+		     .len = EDID_LENGTH,
+		     },
+	};
+	u8 *buf;
+
+	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!buf) {
+		dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n");
+		return NULL;
+	}
+	msgs[1].buf = buf;
+
+	if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
+		return buf;
+	dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n");
+	kfree(buf);
+	return NULL;
+}
+
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+{
+	u8 *edid = NULL;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		/* Do the real work */
+		edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]);
+		if (edid)
+			break;
+	}
+	if (out_edid)
+		*out_edid = edid;
+	if (!edid)
+		return 1;
+
+	return 0;
+}
diff -puN /dev/null drivers/video/nvidia/nvidia.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nvidia.c	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,1725 @@
+/*
+ * linux/drivers/video/nvidia/nvidia.c - nVidia fb driver
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+
+#ifndef CONFIG_PCI		/* sanity check */
+#error This driver requires PCI support.
+#endif
+
+#undef CONFIG_FB_NVIDIA_DEBUG
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define NVTRACE          printk
+#else
+#define NVTRACE          if (0) printk
+#endif
+
+#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __FUNCTION__)
+#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __FUNCTION__)
+
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define assert(expr) \
+	if (!(expr)) { \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+	#expr,__FILE__,__FUNCTION__,__LINE__); \
+	BUG(); \
+	}
+#else
+#define assert(expr)
+#endif
+
+#define PFX "nvidiafb: "
+
+/* HW cursor parameters */
+#define MAX_CURS		32
+
+static struct pci_device_id nvidiafb_pci_tbl[] = {
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0252,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0313,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0316,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0317,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x031D,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x031E,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x031F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0329,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x032F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0345,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0349,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x034B,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x034F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x00c0,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A_LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_GO1400,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x00cd,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_1400,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0142,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0143,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0144,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0145,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0146,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0147,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0148,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0149,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x014b,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x14c,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x014d,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0160,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0162,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0163,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0165,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0169,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016b,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016c,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016d,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016e,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0210,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x021d,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x021e,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0220,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0221,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0222,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0228,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}			/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
+
+/* command line data, set in nvidiafb_setup() */
+static int flatpanel __initdata = -1;	/* Autodetect later */
+static int forceCRTC __initdata = -1;
+static int hwcur __initdata = 0;
+static int noaccel __initdata = 0;
+static int noscale __initdata = 0;
+static int paneltweak __initdata = 0;
+#ifdef CONFIG_MTRR
+static int nomtrr __initdata = 0;
+#endif
+
+static char *mode_option __initdata = NULL;
+
+static struct fb_fix_screeninfo __initdata nvidiafb_fix = {
+	.type = FB_TYPE_PACKED_PIXELS,
+	.xpanstep = 8,
+	.ypanstep = 1,
+};
+
+static struct fb_var_screeninfo __initdata nvidiafb_default_var = {
+	.xres = 640,
+	.yres = 480,
+	.xres_virtual = 640,
+	.yres_virtual = 480,
+	.bits_per_pixel = 8,
+	.red = {0, 8, 0},
+	.green = {0, 8, 0},
+	.blue = {0, 8, 0},
+	.transp = {0, 0, 0},
+	.activate = FB_ACTIVATE_NOW,
+	.height = -1,
+	.width = -1,
+	.pixclock = 39721,
+	.left_margin = 40,
+	.right_margin = 24,
+	.upper_margin = 32,
+	.lower_margin = 11,
+	.hsync_len = 96,
+	.vsync_len = 2,
+	.vmode = FB_VMODE_NONINTERLACED
+};
+
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_PMAC_BACKLIGHT
+
+static int nvidia_backlight_levels[] = {
+	0x158,
+	0x192,
+	0x1c6,
+	0x200,
+	0x234,
+	0x268,
+	0x2a2,
+	0x2d6,
+	0x310,
+	0x344,
+	0x378,
+	0x3b2,
+	0x3e6,
+	0x41a,
+	0x454,
+	0x534,
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * Backlight operations
+ *
+ * ------------------------------------------------------------------------- */
+
+static int nvidia_set_backlight_enable(int on, int level, void *data)
+{
+	struct nvidia_par *par = (struct nvidia_par *)data;
+	u32 tmp_pcrt, tmp_pmc, fpcontrol;
+
+	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+	fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+	if (on && (level > BACKLIGHT_OFF)) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31);	// backlight bit
+		tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
+	}
+
+	if (on)
+		fpcontrol |= par->fpSyncs;
+	else
+		fpcontrol |= 0x20000022;
+
+	NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+	NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+	NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+	return 0;
+}
+
+static int nvidia_set_backlight_level(int level, void *data)
+{
+	return nvidia_set_backlight_enable(1, level, data);
+}
+
+static struct backlight_controller nvidia_backlight_controller = {
+	nvidia_set_backlight_enable,
+	nvidia_set_backlight_level
+};
+
+#endif				/* CONFIG_PMAC_BACKLIGHT */
+
+static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
+				       u16 bg, u16 fg, u32 w, u32 h)
+{
+	int i, j, k = 0;
+	u32 b, tmp;
+	u32 *data = (u32 *) data8;
+
+	w = (w + 1) & ~1;
+
+	for (i = 0; i < h; i++) {
+		b = *data++;
+		reverse_order(&b);
+
+		for (j = 0; j < w / 2; j++) {
+			tmp = 0;
+#if defined (__BIG_ENDIAN)
+			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
+			b <<= 1;
+			tmp |= (b & (1 << 31)) ? fg : bg;
+			b <<= 1;
+#else
+			tmp = (b & 1) ? fg : bg;
+			b >>= 1;
+			tmp |= (b & 1) ? fg << 16 : bg << 16;
+			b >>= 1;
+#endif
+			NV_WR32(&par->CURSOR[k++], 0, tmp);
+		}
+		k += (MAX_CURS - w) / 2;
+	}
+}
+
+static void nvidia_write_clut(struct nvidia_par *par,
+			      u8 regnum, u8 red, u8 green, u8 blue)
+{
+	NVWriteDacMask(par, 0xff);
+	NVWriteDacWriteAddr(par, regnum);
+	NVWriteDacData(par, red);
+	NVWriteDacData(par, green);
+	NVWriteDacData(par, blue);
+}
+
+static void nvidia_read_clut(struct nvidia_par *par,
+			     u8 regnum, u8 * red, u8 * green, u8 * blue)
+{
+	NVWriteDacMask(par, 0xff);
+	NVWriteDacReadAddr(par, regnum);
+	*red = NVReadDacData(par);
+	*green = NVReadDacData(par);
+	*blue = NVReadDacData(par);
+}
+
+static int nvidia_panel_tweak(struct nvidia_par *par,
+			      struct _riva_hw_state *state)
+{
+	int tweak = 0;
+
+   if (par->paneltweak) {
+	   tweak = par->paneltweak;
+   } else {
+	   /* begin flat panel hacks */
+	   /* This is unfortunate, but some chips need this register
+	      tweaked or else you get artifacts where adjacent pixels are
+	      swapped.  There are no hard rules for what to set here so all
+	      we can do is experiment and apply hacks. */
+
+	   if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
+		   /* At least one NV34 laptop needs this workaround. */
+		   tweak = -1;
+	   }
+
+	   if((par->Chipset & 0xfff0) == 0x0310) {
+		   tweak = 1;
+	   }
+	   /* end flat panel hacks */
+   }
+
+   return tweak;
+}
+
+static void nvidia_save_vga(struct nvidia_par *par,
+			    struct _riva_hw_state *state)
+{
+	int i;
+
+	NVTRACE_ENTER();
+	NVLockUnlock(par, 0);
+
+	NVUnloadStateExt(par, state);
+
+	state->misc_output = NVReadMiscOut(par);
+
+	for (i = 0; i < NUM_CRT_REGS; i++)
+		state->crtc[i] = NVReadCrtc(par, i);
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		state->attr[i] = NVReadAttr(par, i);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		state->gra[i] = NVReadGr(par, i);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		state->seq[i] = NVReadSeq(par, i);
+	NVTRACE_LEAVE();
+}
+
+static void nvidia_write_regs(struct nvidia_par *par)
+{
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i;
+
+	NVTRACE_ENTER();
+	NVWriteCrtc(par, 0x11, 0x00);
+
+	NVLockUnlock(par, 0);
+
+	NVLoadStateExt(par, state);
+
+	NVWriteMiscOut(par, state->misc_output);
+
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		switch (i) {
+		case 0x19:
+		case 0x20 ... 0x40:
+			break;
+		default:
+			NVWriteCrtc(par, i, state->crtc[i]);
+		}
+	}
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		NVWriteAttr(par, i, state->attr[i]);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		NVWriteGr(par, i, state->gra[i]);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		NVWriteSeq(par, i, state->seq[i]);
+	NVTRACE_LEAVE();
+}
+
+static int nvidia_calc_regs(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i, depth = fb_get_color_depth(info);
+	int h_display = info->var.xres / 8 - 1;
+	int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
+	int h_end = (info->var.xres + info->var.right_margin +
+		     info->var.hsync_len) / 8 - 1;
+	int h_total = (info->var.xres + info->var.right_margin +
+		       info->var.hsync_len + info->var.left_margin) / 8 - 5;
+	int h_blank_s = h_display;
+	int h_blank_e = h_total + 4;
+	int v_display = info->var.yres - 1;
+	int v_start = info->var.yres + info->var.lower_margin - 1;
+	int v_end = (info->var.yres + info->var.lower_margin +
+		     info->var.vsync_len) - 1;
+	int v_total = (info->var.yres + info->var.lower_margin +
+		       info->var.vsync_len + info->var.upper_margin) - 2;
+	int v_blank_s = v_display;
+	int v_blank_e = v_total + 1;
+
+	/*
+	 * Set all CRTC values.
+	 */
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		v_total |= 1;
+
+	if (par->FlatPanel == 1) {
+		v_start = v_total - 3;
+		v_end = v_total - 2;
+		v_blank_s = v_start;
+		h_start = h_total - 5;
+		h_end = h_total - 2;
+		h_blank_e = h_total + 4;
+	}
+
+	state->crtc[0x0] = Set8Bits(h_total);
+	state->crtc[0x1] = Set8Bits(h_display);
+	state->crtc[0x2] = Set8Bits(h_blank_s);
+	state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
+		| SetBit(7);
+	state->crtc[0x4] = Set8Bits(h_start);
+	state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
+		| SetBitField(h_end, 4: 0, 4:0);
+	state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
+	state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
+		| SetBitField(v_display, 8: 8, 1:1)
+		| SetBitField(v_start, 8: 8, 2:2)
+		| SetBitField(v_blank_s, 8: 8, 3:3)
+		| SetBit(4)
+		| SetBitField(v_total, 9: 9, 5:5)
+		| SetBitField(v_display, 9: 9, 6:6)
+		| SetBitField(v_start, 9: 9, 7:7);
+	state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
+		| SetBit(6)
+		| ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
+	state->crtc[0x10] = Set8Bits(v_start);
+	state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
+	state->crtc[0x12] = Set8Bits(v_display);
+	state->crtc[0x13] = ((info->var.xres_virtual / 8) *
+			     (info->var.bits_per_pixel / 8));
+	state->crtc[0x15] = Set8Bits(v_blank_s);
+	state->crtc[0x16] = Set8Bits(v_blank_e);
+
+	state->attr[0x10] = 0x01;
+
+	if (par->Television)
+		state->attr[0x11] = 0x00;
+
+	state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
+		| SetBitField(v_blank_s, 10: 10, 3:3)
+		| SetBitField(v_start, 10: 10, 2:2)
+		| SetBitField(v_display, 10: 10, 1:1)
+		| SetBitField(v_total, 10: 10, 0:0);
+
+	state->horiz = SetBitField(h_total, 8: 8, 0:0)
+		| SetBitField(h_display, 8: 8, 1:1)
+		| SetBitField(h_blank_s, 8: 8, 2:2)
+		| SetBitField(h_start, 8: 8, 3:3);
+
+	state->extra = SetBitField(v_total, 11: 11, 0:0)
+		| SetBitField(v_display, 11: 11, 2:2)
+		| SetBitField(v_start, 11: 11, 4:4)
+		| SetBitField(v_blank_s, 11: 11, 6:6);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED) {
+		h_total = (h_total >> 1) & ~1;
+		state->interlace = Set8Bits(h_total);
+		state->horiz |= SetBitField(h_total, 8: 8, 4:4);
+	} else {
+		state->interlace = 0xff;	/* interlace off */
+	}
+
+	/*
+	 * Calculate the extended registers.
+	 */
+
+	if (depth < 24)
+		i = depth;
+	else
+		i = 32;
+
+	if (par->Architecture >= NV_ARCH_10)
+		par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
+						       par->CursorStart);
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		state->misc_output &= ~0x40;
+	else
+		state->misc_output |= 0x40;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		state->misc_output &= ~0x80;
+	else
+		state->misc_output |= 0x80;
+
+	NVCalcStateExt(par, state, i, info->var.xres_virtual,
+		       info->var.xres, info->var.yres_virtual,
+		       1000000000 / info->var.pixclock, info->var.vmode);
+
+	state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
+	if (par->FlatPanel == 1) {
+		state->pixel |= (1 << 7);
+
+		if (!par->fpScaler || (par->fpWidth <= info->var.xres)
+		    || (par->fpHeight <= info->var.yres)) {
+			state->scale |= (1 << 8);
+		}
+
+		if (!par->crtcSync_read) {
+			state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
+			par->crtcSync_read = 1;
+		}
+
+		par->PanelTweak = nvidia_panel_tweak(par, state);
+	}
+
+	state->vpll = state->pll;
+	state->vpll2 = state->pll;
+	state->vpllB = state->pllB;
+	state->vpll2B = state->pllB;
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
+
+	if (par->CRTCnumber) {
+		state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
+		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
+		state->crtcOwner = 3;
+		state->pllsel |= 0x20000800;
+		state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
+		if (par->twoStagePLL)
+			state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
+	} else if (par->twoHeads) {
+		state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
+		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
+		state->crtcOwner = 0;
+		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+		if (par->twoStagePLL)
+			state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+	}
+
+	state->cursorConfig = 0x00000100;
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		state->cursorConfig |= (1 << 4);
+
+	if (par->alphaCursor) {
+		if ((par->Chipset & 0x0ff0) != 0x0110)
+			state->cursorConfig |= 0x04011000;
+		else
+			state->cursorConfig |= 0x14011000;
+		state->general |= (1 << 29);
+	} else
+		state->cursorConfig |= 0x02000000;
+
+	if (par->twoHeads) {
+		if ((par->Chipset & 0x0ff0) == 0x0110) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
+			    ~0x00010000;
+			if (par->FPDither)
+				state->dither |= 0x00010000;
+		} else {
+			state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
+			if (par->FPDither)
+				state->dither |= 1;
+		}
+	}
+
+	state->timingH = 0;
+	state->timingV = 0;
+	state->displayV = info->var.xres;
+
+	return 0;
+}
+
+static void nvidia_init_vga(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i;
+
+	for (i = 0; i < 0x10; i++)
+		state->attr[i] = i;
+	state->attr[0x10] = 0x41;
+	state->attr[0x11] = 0x01;
+	state->attr[0x12] = 0x0f;
+	state->attr[0x13] = 0x00;
+	state->attr[0x14] = 0x00;
+
+	memset(state->crtc, 0x00, NUM_CRT_REGS);
+	state->crtc[0x0a] = 0x20;
+	state->crtc[0x17] = 0xe3;
+	state->crtc[0x18] = 0xff;
+	state->crtc[0x28] = 0x40;
+
+	memset(state->gra, 0x00, NUM_GRC_REGS);
+	state->gra[0x05] = 0x40;
+	state->gra[0x06] = 0x05;
+	state->gra[0x07] = 0x0f;
+	state->gra[0x08] = 0xff;
+
+	state->seq[0x00] = 0x03;
+	state->seq[0x01] = 0x01;
+	state->seq[0x02] = 0x0f;
+	state->seq[0x03] = 0x00;
+	state->seq[0x04] = 0x0e;
+
+	state->misc_output = 0xeb;
+}
+
+static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct nvidia_par *par = info->par;
+	u8 data[MAX_CURS * MAX_CURS / 8];
+	u16 fg, bg;
+	int i, set = cursor->set;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return soft_cursor(info, cursor);
+
+	NVShowHideCursor(par, 0);
+
+	if (par->cursor_reset) {
+		set = FB_CUR_SETALL;
+		par->cursor_reset = 0;
+	}
+
+	if (set & FB_CUR_SETSIZE)
+		memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+
+	if (set & FB_CUR_SETPOS) {
+		u32 xx, yy, temp;
+
+		yy = cursor->image.dy - info->var.yoffset;
+		xx = cursor->image.dx - info->var.xoffset;
+		temp = xx & 0xFFFF;
+		temp |= yy << 16;
+
+		NV_WR32(par->PRAMDAC, 0x0000300, temp);
+	}
+
+	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		u32 s_pitch = (cursor->image.width + 7) >> 3;
+		u32 d_pitch = MAX_CURS / 8;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 *src;
+
+		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+
+		if (src) {
+			switch (cursor->rop) {
+			case ROP_XOR:
+				for (i = 0; i < s_pitch * cursor->image.height;
+				     i++)
+					src[i] = dat[i] ^ msk[i];
+				break;
+			case ROP_COPY:
+			default:
+				for (i = 0; i < s_pitch * cursor->image.height;
+				     i++)
+					src[i] = dat[i] & msk[i];
+				break;
+			}
+
+			fb_sysmove_buf_aligned(info, &info->pixmap, data,
+					       d_pitch, src, s_pitch,
+					       cursor->image.height);
+
+			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+			    ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+			    ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
+
+			fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+			    ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+			    ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
+
+			NVLockUnlock(par, 0);
+
+			nvidiafb_load_cursor_image(par, data, bg, fg,
+						   cursor->image.width,
+						   cursor->image.height);
+			kfree(src);
+		}
+	}
+
+	if (cursor->enable)
+		NVShowHideCursor(par, 1);
+
+	return 0;
+}
+
+static int nvidiafb_set_par(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	NVTRACE_ENTER();
+
+	NVLockUnlock(par, 1);
+	if (!par->FlatPanel || (info->var.bits_per_pixel != 24) ||
+	    !par->twoHeads)
+		par->FPDither = 0;
+
+	nvidia_init_vga(info);
+	nvidia_calc_regs(info);
+	nvidia_write_regs(par);
+
+	NVLockUnlock(par, 0);
+	if (par->twoHeads) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
+		NVLockUnlock(par, 0);
+	}
+
+	NVWriteCrtc(par, 0x11, 0x00);
+	info->fix.line_length = (info->var.xres_virtual *
+				 info->var.bits_per_pixel) >> 3;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	if (info->var.accel_flags) {
+		info->fbops->fb_imageblit = nvidiafb_imageblit;
+		info->fbops->fb_fillrect = nvidiafb_fillrect;
+		info->fbops->fb_copyarea = nvidiafb_copyarea;
+		info->fbops->fb_sync = nvidiafb_sync;
+		info->pixmap.scan_align = 4;
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		NVResetGraphics(info);
+	} else {
+		info->fbops->fb_imageblit = cfb_imageblit;
+		info->fbops->fb_fillrect = cfb_fillrect;
+		info->fbops->fb_copyarea = cfb_copyarea;
+		info->fbops->fb_sync = NULL;
+		info->pixmap.scan_align = 1;
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
+	par->cursor_reset = 1;
+
+	NVWriteCrtc(par, 0x11, 0xff);
+
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int i;
+
+	NVTRACE_ENTER();
+	if (regno >= (1 << info->var.green.length))
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		((u32 *) info->pseudo_palette)[regno] =
+		    (regno << info->var.red.offset) |
+		    (regno << info->var.green.offset) |
+		    (regno << info->var.blue.offset);
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	case 16:
+		if (info->var.green.length == 5) {
+			for (i = 0; i < 8; i++) {
+				nvidia_write_clut(par, regno * 8 + i, red >> 8,
+						  green >> 8, blue >> 8);
+			}
+		} else {
+			u8 r, g, b;
+
+			if (regno < 32) {
+				for (i = 0; i < 8; i++) {
+					nvidia_write_clut(par, regno * 8 + i,
+							  red >> 8, green >> 8,
+							  blue >> 8);
+				}
+			}
+
+			nvidia_read_clut(par, regno * 4, &r, &g, &b);
+
+			for (i = 0; i < 4; i++)
+				nvidia_write_clut(par, regno * 4 + i, r,
+						  green >> 8, b);
+		}
+		break;
+	case 32:
+		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int nvidiafb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int memlen, vramlen, mode_valid = 0;
+	int pitch, err = 0;
+
+	NVTRACE_ENTER();
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	var->xres &= ~7;
+	var->xres_virtual &= ~7;
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else
+		var->bits_per_pixel = 32;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:
+		var->green.length = (var->green.length < 6) ? 5 : 6;
+		var->red.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 6 - var->green.length;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 5 + var->green.length;
+		var->transp.offset = (5 + var->red.offset) & 15;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		break;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+		mode_valid = 1;
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			fb_videomode_to_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
+					      par->fpHeight < var->yres))
+		return -EINVAL;
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	vramlen = info->fix.smem_len;
+	pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
+	memlen = pitch * var->yres_virtual;
+
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen / pitch;
+
+		if (var->yres_virtual < var->yres) {
+			var->yres_virtual = var->yres;
+			var->xres_virtual = vramlen / var->yres_virtual;
+			var->xres_virtual /= var->bits_per_pixel / 8;
+			pitch = (var->xres_virtual *
+				 var->bits_per_pixel + 7) / 8;
+			memlen = pitch * var->yres;
+
+			if (var->xres_virtual < var->xres) {
+				printk("nvidiafb: required video memory, "
+				       "%d bytes, for %dx%d-%d (virtual) "
+				       "is out of range\n",
+				       memlen, var->xres_virtual,
+				       var->yres_virtual, var->bits_per_pixel);
+				err = -ENOMEM;
+			}
+		}
+	}
+
+	if (var->accel_flags) {
+		if (var->yres_virtual > 0x7fff)
+			var->yres_virtual = 0x7fff;
+		if (var->xres_virtual > 0x7fff)
+			var->xres_virtual = 0x7fff;
+	}
+
+	var->xres_virtual &= ~8;
+
+	NVTRACE_LEAVE();
+
+	return err;
+}
+
+static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 total;
+
+	total = info->var.yoffset * info->fix.line_length + info->var.xoffset;
+
+	NVSetStartAddress(par, total);
+
+	return 0;
+}
+
+static int nvidiafb_blank(int blank, struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	unsigned char tmp, vesa;
+
+	tmp = NVReadSeq(par, 0x01) & ~0x20;	/* screen on/off */
+	vesa = NVReadCrtc(par, 0x1a) & ~0xc0;	/* sync on/off */
+
+	NVTRACE_ENTER();
+
+	if (blank)
+		tmp |= 0x20;
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		vesa |= 0x80;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		vesa |= 0x40;
+		break;
+	case FB_BLANK_POWERDOWN:
+		vesa |= 0xc0;
+		break;
+	}
+
+	NVWriteSeq(par, 0x01, tmp);
+	NVWriteCrtc(par, 0x1a, vesa);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (par->FlatPanel && _machine == _MACH_Pmac) {
+		set_backlight_enable(!blank);
+	}
+#endif
+
+	NVTRACE_LEAVE();
+
+	return 0;
+}
+
+static struct fb_ops nvidia_fb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = nvidiafb_check_var,
+	.fb_set_par     = nvidiafb_set_par,
+	.fb_setcolreg   = nvidiafb_setcolreg,
+	.fb_pan_display = nvidiafb_pan_display,
+	.fb_blank       = nvidiafb_blank,
+	.fb_fillrect    = nvidiafb_fillrect,
+	.fb_copyarea    = nvidiafb_copyarea,
+	.fb_imageblit   = nvidiafb_imageblit,
+	.fb_cursor      = nvidiafb_cursor,
+	.fb_sync        = nvidiafb_sync,
+};
+
+static int __devinit nvidia_set_fbinfo(struct fb_info *info)
+{
+	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode modedb;
+	struct nvidia_par *par = info->par;
+	int lpitch;
+
+	NVTRACE_ENTER();
+	info->flags = FBINFO_DEFAULT
+	    | FBINFO_HWACCEL_IMAGEBLIT
+	    | FBINFO_HWACCEL_FILLRECT
+	    | FBINFO_HWACCEL_COPYAREA
+	    | FBINFO_HWACCEL_YPAN | FBINFO_MISC_MODESWITCHLATE;
+
+	fb_videomode_to_modelist(info->monspecs.modedb,
+				 info->monspecs.modedb_len, &info->modelist);
+	fb_var_to_videomode(&modedb, &nvidiafb_default_var);
+
+	if (specs->modedb != NULL) {
+		/* get preferred timing */
+		if (specs->misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = specs->modedb[i];
+					break;
+				}
+			}
+		} else {
+			/* otherwise, get first mode in database */
+			modedb = specs->modedb[0];
+		}
+
+		fb_videomode_to_var(&nvidiafb_default_var, &modedb);
+		nvidiafb_default_var.bits_per_pixel = 8;
+	}
+
+	if (mode_option)
+		fb_find_mode(&nvidiafb_default_var, info, mode_option,
+			     specs->modedb, specs->modedb_len, &modedb, 8);
+
+	info->var = nvidiafb_default_var;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	info->pseudo_palette = par->pseudo_palette;
+	fb_alloc_cmap(&info->cmap, 256, 0);
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual *
+		((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len / lpitch;
+
+	info->pixmap.scan_align = 4;
+	info->pixmap.buf_align = 4;
+	info->pixmap.size = 8 * 1024;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (!hwcur)
+		info->fbops->fb_cursor = soft_cursor;
+	info->var.accel_flags = (!noaccel);
+	par->FpScale = (!noscale);
+	par->paneltweak = paneltweak;
+
+	switch (par->Architecture) {
+	case NV_ARCH_04:
+		info->fix.accel = FB_ACCEL_NV4;
+		break;
+	case NV_ARCH_10:
+		info->fix.accel = FB_ACCEL_NV_10;
+		break;
+	case NV_ARCH_20:
+		info->fix.accel = FB_ACCEL_NV_20;
+		break;
+	case NV_ARCH_30:
+		info->fix.accel = FB_ACCEL_NV_30;
+		break;
+	case NV_ARCH_40:
+		info->fix.accel = FB_ACCEL_NV_40;
+		break;
+	}
+
+	NVTRACE_LEAVE();
+
+	return nvidiafb_check_var(&info->var, info);
+}
+
+static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+{
+	u32 arch = 0;
+
+	switch (pd->device & 0x0ff0) {
+	case 0x0100:		/* GeForce 256 */
+	case 0x0110:		/* GeForce2 MX */
+	case 0x0150:		/* GeForce2 */
+	case 0x0170:		/* GeForce4 MX */
+	case 0x0180:		/* GeForce4 MX (8x AGP) */
+	case 0x01A0:		/* nForce */
+	case 0x01F0:		/* nForce2 */
+		arch = NV_ARCH_10;
+		break;
+	case 0x0200:		/* GeForce3 */
+	case 0x0250:		/* GeForce4 Ti */
+	case 0x0280:		/* GeForce4 Ti (8x AGP) */
+		arch = NV_ARCH_20;
+		break;
+	case 0x0300:		/* GeForceFX 5800 */
+	case 0x0310:		/* GeForceFX 5600 */
+	case 0x0320:		/* GeForceFX 5200 */
+	case 0x0330:		/* GeForceFX 5900 */
+	case 0x0340:		/* GeForceFX 5700 */
+		arch = NV_ARCH_30;
+		break;
+	case 0x0040:
+	case 0x00C0:
+	case 0x0120:
+	case 0x0130:
+	case 0x0140:
+	case 0x0160:
+	case 0x01D0:
+	case 0x0090:
+	case 0x0210:
+	case 0x0220:
+	case 0x0230:
+		arch = NV_ARCH_40;
+		break;
+	case 0x0020:		/* TNT, TNT2 */
+		arch = NV_ARCH_04;
+		break;
+	default:		/* unknown architecture */
+		break;
+	}
+
+	return arch;
+}
+
+static int __devinit nvidiafb_probe(struct pci_dev *pd,
+				    const struct pci_device_id *ent)
+{
+	struct nvidia_par *par;
+	struct fb_info *info;
+	unsigned short cmd;
+
+
+	NVTRACE_ENTER();
+	assert(pd != NULL);
+
+	info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
+
+	if (!info)
+		goto err_out;
+
+	par = (struct nvidia_par *)info->par;
+	par->pci_dev = pd;
+
+	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+
+	if (info->pixmap.addr == NULL)
+		goto err_out_kfree;
+
+	memset(info->pixmap.addr, 0, 8 * 1024);
+
+	if (pci_enable_device(pd)) {
+		printk(KERN_ERR PFX "cannot enable PCI device\n");
+		goto err_out_enable;
+	}
+
+	if (pci_request_regions(pd, "nvidiafb")) {
+		printk(KERN_ERR PFX "cannot request PCI regions\n");
+		goto err_out_request;
+	}
+
+	par->Architecture = nvidia_get_arch(pd);
+
+	par->Chipset = (pd->vendor << 16) | pd->device;
+	printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
+
+#ifdef CONFIG_PCI_NAMES
+	printk(KERN_INFO PFX "%s\n", pd->pretty_name);
+#endif
+
+	if (par->Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		goto err_out_free_base0;
+	}
+
+	sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+	par->FlatPanel = flatpanel;
+
+	if (flatpanel == 1)
+		printk(KERN_INFO PFX "flatpanel support enabled\n");
+
+	par->CRTCnumber = forceCRTC;
+
+	/* enable IO and mem if not already done */
+	pci_read_config_word(pd, PCI_COMMAND, &cmd);
+	cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	pci_write_config_word(pd, PCI_COMMAND, cmd);
+
+	nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
+	nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
+	nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
+
+	par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
+
+	if (!par->REGS) {
+		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+		goto err_out_free_base0;
+	}
+
+	NVCommonSetup(info);
+
+	par->FbAddress = nvidiafb_fix.smem_start;
+	par->FbMapSize = par->RamAmountKBytes * 1024;
+	par->FbUsableSize = par->FbMapSize - (128 * 1024);
+	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
+	    16 * 1024;
+	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
+	nvidiafb_fix.smem_len = par->FbUsableSize;
+
+	if (!info->screen_base) {
+		printk(KERN_ERR PFX "cannot ioremap FB base\n");
+		goto err_out_free_base1;
+	}
+
+	par->FbStart = info->screen_base;
+
+#ifdef CONFIG_MTRR
+	if (!nomtrr) {
+		par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
+					  par->FbMapSize, MTRR_TYPE_WRCOMB, 1);
+		if (par->mtrr.vram < 0) {
+			printk(KERN_ERR PFX "unable to setup MTRR\n");
+		} else {
+			par->mtrr.vram_valid = 1;
+			/* let there be speed */
+			printk(KERN_INFO PFX "MTRR set to ON\n");
+		}
+	}
+#endif				/* CONFIG_MTRR */
+
+	info->fbops = &nvidia_fb_ops;
+	info->fix = nvidiafb_fix;
+
+	if (nvidia_set_fbinfo(info) < 0) {
+		printk(KERN_ERR PFX "error setting initial video mode\n");
+		goto err_out_iounmap_fb;
+	}
+
+	nvidia_save_vga(par, &par->SavedReg);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
+		goto err_out_iounmap_fb;
+	}
+
+	pci_set_drvdata(pd, info);
+
+	printk(KERN_INFO PFX
+	       "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
+	       info->fix.id,
+	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (par->FlatPanel && _machine == _MACH_Pmac)
+		register_backlight_controller(&nvidia_backlight_controller,
+					      par, "mnca");
+#endif
+	NVTRACE_LEAVE();
+	return 0;
+
+      err_out_iounmap_fb:
+	iounmap(info->screen_base);
+      err_out_free_base1:
+	fb_destroy_modedb(info->monspecs.modedb);
+	iounmap(par->REGS);
+      err_out_free_base0:
+	pci_release_regions(pd);
+      err_out_request:
+	pci_disable_device(pd);
+      err_out_enable:
+	kfree(info->pixmap.addr);
+      err_out_kfree:
+	framebuffer_release(info);
+      err_out:
+	return -ENODEV;
+}
+
+static void __exit nvidiafb_remove(struct pci_dev *pd)
+{
+	struct fb_info *info = pci_get_drvdata(pd);
+	struct nvidia_par *par = info->par;
+
+	NVTRACE_ENTER();
+	if (!info)
+		return;
+
+	unregister_framebuffer(info);
+#ifdef CONFIG_MTRR
+	if (par->mtrr.vram_valid)
+		mtrr_del(par->mtrr.vram, info->fix.smem_start,
+			 info->fix.smem_len);
+#endif				/* CONFIG_MTRR */
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	iounmap(par->REGS);
+	iounmap(info->screen_base);
+	pci_release_regions(pd);
+	pci_disable_device(pd);
+	kfree(info->pixmap.addr);
+	framebuffer_release(info);
+	pci_set_drvdata(pd, NULL);
+	NVTRACE_LEAVE();
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+int __init nvidiafb_setup(char *options)
+{
+	char *this_opt;
+
+	NVTRACE_ENTER();
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "forceCRTC", 9)) {
+			char *p;
+
+			p = this_opt + 9;
+			if (!*p || !*(++p))
+				continue;
+			forceCRTC = *p - '0';
+			if (forceCRTC < 0 || forceCRTC > 1)
+				forceCRTC = -1;
+		} else if (!strncmp(this_opt, "flatpanel", 9)) {
+			flatpanel = 1;
+		} else if (!strncmp(this_opt, "hwcur", 5)) {
+			hwcur = 1;
+		} else if (!strncmp(this_opt, "noaccel", 6)) {
+			noaccel = 1;
+		} else if (!strncmp(this_opt, "noscale", 7)) {
+			noscale = 1;
+		} else if (!strncmp(this_opt, "paneltweak:", 11)) {
+			paneltweak = simple_strtoul(this_opt+11, NULL, 0);
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else
+			mode_option = this_opt;
+	}
+	NVTRACE_LEAVE();
+	return 0;
+}
+#endif				/* !MODULE */
+
+static struct pci_driver nvidiafb_driver = {
+	.name = "nvidiafb",
+	.id_table = nvidiafb_pci_tbl,
+	.probe = nvidiafb_probe,
+	.remove = __exit_p(nvidiafb_remove),
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+int __devinit nvidiafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("nvidiafb", &option))
+		return -ENODEV;
+	nvidiafb_setup(option);
+#endif
+	return pci_register_driver(&nvidiafb_driver);
+}
+
+module_init(nvidiafb_init);
+
+#ifdef MODULE
+static void __exit nvidiafb_exit(void)
+{
+	pci_unregister_driver(&nvidiafb_driver);
+}
+
+module_exit(nvidiafb_exit);
+
+module_param(flatpanel, int, 0);
+MODULE_PARM_DESC(flatpanel,
+		 "Enables experimental flat panel support for some chipsets. "
+		 "(0 or 1=enabled) (default=0)");
+module_param(hwcur, int, 0);
+MODULE_PARM_DESC(hwcur,
+		 "Enables hardware cursor implementation. (0 or 1=enabled) "
+		 "(default=0)");
+module_param(noaccel, int, 0);
+MODULE_PARM_DESC(noaccel,
+		 "Disables hardware acceleration. (0 or 1=disable) "
+		 "(default=0)");
+module_param(noscale, int, 0);
+MODULE_PARM_DESC(noscale,
+		 "Disables screen scaleing. (0 or 1=disable) "
+		 "(default=0, do scaling)");
+module_param(paneltweak, int, 0);
+MODULE_PARM_DESC(paneltweak,
+		 "Tweak display settings for flatpanels. "
+		 "(default=0, no tweaks)");
+module_param(forceCRTC, int, 0);
+MODULE_PARM_DESC(forceCRTC,
+		 "Forces usage of a particular CRTC in case autodetection "
+		 "fails. (0 or 1) (default=autodetect)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
+		 "(default=0)");
+#endif
+
+MODULE_AUTHOR("Antonino Daplas");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
+
diff -puN /dev/null drivers/video/nvidia/nv_local.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_local.h	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,98 @@
+/***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING 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 SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+#ifndef __NV_LOCAL_H__
+#define __NV_LOCAL_H__
+
+/*
+ * This file includes any environment or machine specific values to access the
+ * HW.  Put all affected includes, typdefs, etc. here so the riva_hw.* files
+ * can stay generic in nature.
+ */
+
+/*
+ * HW access macros.  These assume memory-mapped I/O, and not normal I/O space.
+ */
+#define NV_WR08(p,i,d)  (__raw_writeb((d), (void __iomem *)(p) + (i)))
+#define NV_RD08(p,i)    (__raw_readb((void __iomem *)(p) + (i)))
+#define NV_WR16(p,i,d)  (__raw_writew((d), (void __iomem *)(p) + (i)))
+#define NV_RD16(p,i)    (__raw_readw((void __iomem *)(p) + (i)))
+#define NV_WR32(p,i,d)  (__raw_writel((d), (void __iomem *)(p) + (i)))
+#define NV_RD32(p,i)    (__raw_readl((void __iomem *)(p) + (i)))
+
+/* VGA I/O is now always done through MMIO */
+#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
+#define VGA_RD08(p,i)   (readb((void __iomem *)(p) + (i)))
+
+#define NVDmaNext(par, data) \
+     NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data))
+
+#define NVDmaStart(par, tag, size) {          \
+     if((par)->dmaFree <= (size))             \
+        NVDmaWait(par, size);                 \
+     NVDmaNext(par, ((size) << 18) | (tag));  \
+     (par)->dmaFree -= ((size) + 1);          \
+}
+
+#if defined(__i386__)
+#define _NV_FENCE() outb(0, 0x3D0);
+#else
+#define _NV_FENCE() mb();
+#endif
+
+#define WRITE_PUT(par, data) {                   \
+  volatile u8 scratch;                           \
+  _NV_FENCE()                                    \
+  scratch = NV_RD08((par)->FbStart, 0);          \
+  NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
+  mb();                                          \
+}
+
+#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
+
+#define reverse_order(l)        \
+do {                            \
+	u8 *a = (u8 *)(l);      \
+	*a = byte_rev[*a], a++; \
+	*a = byte_rev[*a], a++; \
+	*a = byte_rev[*a], a++; \
+	*a = byte_rev[*a];      \
+} while(0)
+
+#endif				/* __NV_LOCAL_H__ */
diff -puN /dev/null drivers/video/nvidia/nv_of.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_of.c	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,59 @@
+/*
+ * linux/drivers/video/nvidia/nv_of.c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+void nvidia_create_i2c_busses(struct nvidia_par *par) {}
+void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
+
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+{
+	struct device_node *dp;
+	unsigned char *pedid = NULL;
+	unsigned char *disptype = NULL;
+	static char *propnames[] = {
+		"DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+	int i;
+
+	dp = pci_device_to_OF_node(par->pci_dev);
+	for (; dp != NULL; dp = dp->child) {
+		disptype = (unsigned char *)get_property(dp, "display-type", NULL);
+		if (disptype == NULL)
+			continue;
+		if (strncmp(disptype, "LCD", 3) != 0)
+			continue;
+		for (i = 0; propnames[i] != NULL; ++i) {
+			pedid = (unsigned char *)
+				get_property(dp, propnames[i], NULL);
+			if (pedid != NULL) {
+				*out_edid = pedid;
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
diff -puN /dev/null drivers/video/nvidia/nv_proto.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_proto.h	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,61 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.10 2003/07/31 20:24:29 mvojkovi Exp $ */
+
+#ifndef __NV_PROTO_H__
+#define __NV_PROTO_H__
+
+/* in nv_setup.c */
+void NVCommonSetup(struct fb_info *info);
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadCrtc(struct nvidia_par *par, u8 index);
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadGr(struct nvidia_par *par, u8 index);
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadSeq(struct nvidia_par *par, u8 index);
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadAttr(struct nvidia_par *par, u8 index);
+void NVWriteMiscOut(struct nvidia_par *par, u8 value);
+u8 NVReadMiscOut(struct nvidia_par *par);
+void NVEnablePalette(struct nvidia_par *par);
+void NVDisablePalette(struct nvidia_par *par);
+void NVWriteDacMask(struct nvidia_par *par, u8 value);
+u8 NVReadDacMask(struct nvidia_par *par);
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacData(struct nvidia_par *par, u8 value);
+u8 NVReadDacData(struct nvidia_par *par);
+
+/* in nv_hw.c */
+void NVCalcStateExt(struct nvidia_par *par, struct _riva_hw_state *,
+		    int, int, int, int, int, int);
+void NVLoadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVUnloadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVSetStartAddress(struct nvidia_par *par, u32);
+int NVShowHideCursor(struct nvidia_par *par, int);
+void NVLockUnlock(struct nvidia_par *par, int);
+
+/* in nvidia-i2c.c */
+#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
+void nvidia_create_i2c_busses(struct nvidia_par *par);
+void nvidia_delete_i2c_busses(struct nvidia_par *par);
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
+			       u8 ** out_edid);
+#else
+#define nvidia_create_i2c_busses(...)
+#define nvidia_delete_i2c_busses(...)
+#define nvidia_probe_i2c_connector(p, c, edid) \
+do {                                           \
+	*(edid) = NULL;                        \
+} while(0)
+#endif
+
+/* in nv_accel.c */
+extern void NVResetGraphics(struct fb_info *info);
+extern void nvidiafb_copyarea(struct fb_info *info,
+			      const struct fb_copyarea *region);
+extern void nvidiafb_fillrect(struct fb_info *info,
+			      const struct fb_fillrect *rect);
+extern void nvidiafb_imageblit(struct fb_info *info,
+			       const struct fb_image *image);
+extern int nvidiafb_sync(struct fb_info *info);
+extern u8 byte_rev[256];
+#endif				/* __NV_PROTO_H__ */
diff -puN /dev/null drivers/video/nvidia/nv_setup.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_setup.c	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,622 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING 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 SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+#include <video/vga.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+/*
+ * Override VGA I/O routines.
+ */
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+	VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
+}
+u8 NVReadCrtc(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+	return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
+}
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_GFX_I, index);
+	VGA_WR08(par->PVIO, VGA_GFX_D, value);
+}
+u8 NVReadGr(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PVIO, VGA_GFX_I, index);
+	return (VGA_RD08(par->PVIO, VGA_GFX_D));
+}
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+	VGA_WR08(par->PVIO, VGA_SEQ_D, value);
+}
+u8 NVReadSeq(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+	return (VGA_RD08(par->PVIO, VGA_SEQ_D));
+}
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+	VGA_WR08(par->PCIO, VGA_ATT_W, value);
+}
+u8 NVReadAttr(struct nvidia_par *par, u8 index)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+	return (VGA_RD08(par->PCIO, VGA_ATT_R));
+}
+void NVWriteMiscOut(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_MIS_W, value);
+}
+u8 NVReadMiscOut(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PVIO, VGA_MIS_R));
+}
+void NVEnablePalette(struct nvidia_par *par)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00);
+	par->paletteEnabled = 1;
+}
+void NVDisablePalette(struct nvidia_par *par)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20);
+	par->paletteEnabled = 0;
+}
+void NVWriteDacMask(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
+}
+u8 NVReadDacMask(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
+}
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_IR, value);
+}
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_IW, value);
+}
+void NVWriteDacData(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_D, value);
+}
+u8 NVReadDacData(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PDIO, VGA_PEL_D));
+}
+
+static int NVIsConnected(struct nvidia_par *par, int output)
+{
+	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
+	u32 reg52C, reg608;
+	int present;
+
+	if (output)
+		PRAMDAC += 0x800;
+
+	reg52C = NV_RD32(PRAMDAC, 0x052C);
+	reg608 = NV_RD32(PRAMDAC, 0x0608);
+
+	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
+	msleep(1);
+	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
+
+	NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
+	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
+		0x00001000);
+
+	msleep(1);
+
+	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
+
+	if (present)
+		printk("nvidiafb: CRTC%i found\n", output);
+	else
+		printk("nvidiafb: CRTC%i not found\n", output);
+
+	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
+		0x0000EFFF);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C);
+	NV_WR32(PRAMDAC, 0x0608, reg608);
+
+	return present;
+}
+
+static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
+{
+	if (head) {
+		par->PCIO = par->PCIO0 + 0x2000;
+		par->PCRTC = par->PCRTC0 + 0x800;
+		par->PRAMDAC = par->PRAMDAC0 + 0x800;
+		par->PDIO = par->PDIO0 + 0x2000;
+	} else {
+		par->PCIO = par->PCIO0;
+		par->PCRTC = par->PCRTC0;
+		par->PRAMDAC = par->PRAMDAC0;
+		par->PDIO = par->PDIO0;
+	}
+}
+
+static void nv4GetConfig(struct nvidia_par *par)
+{
+	if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
+		par->RamAmountKBytes =
+		    ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
+		    1024 * 2;
+	} else {
+		switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
+		case 0:
+			par->RamAmountKBytes = 1024 * 32;
+			break;
+		case 1:
+			par->RamAmountKBytes = 1024 * 4;
+			break;
+		case 2:
+			par->RamAmountKBytes = 1024 * 8;
+			break;
+		case 3:
+		default:
+			par->RamAmountKBytes = 1024 * 16;
+			break;
+		}
+	}
+	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
+	    14318 : 13500;
+	par->CURSOR = &par->PRAMIN[0x1E00];
+	par->MinVClockFreqKHz = 12000;
+	par->MaxVClockFreqKHz = 350000;
+}
+
+static void nv10GetConfig(struct nvidia_par *par)
+{
+	struct pci_dev *dev;
+	u32 implementation = par->Chipset & 0x0ff0;
+
+#ifdef __BIG_ENDIAN
+	/* turn on big endian register access */
+	if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
+		NV_WR32(par->PMC, 0x0004, 0x01000001);
+		mb();
+	}
+#endif
+
+	dev = pci_find_slot(0, 1);
+	if ((par->Chipset && 0xffff) == 0x01a0) {
+		int amt = 0;
+
+		pci_read_config_dword(dev, 0x7c, &amt);
+		par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+	} else if ((par->Chipset & 0xffff) == 0x01f0) {
+		int amt = 0;
+
+		pci_read_config_dword(dev, 0x84, &amt);
+		par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+	} else {
+		par->RamAmountKBytes =
+		    (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
+	}
+
+	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
+	    14318 : 13500;
+
+	if (par->twoHeads && (implementation != 0x0110)) {
+		if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
+			par->CrystalFreqKHz = 27000;
+	}
+
+	par->CursorStart = (par->RamAmountKBytes - 96) * 1024;
+	par->CURSOR = NULL;	/* can't set this here */
+	par->MinVClockFreqKHz = 12000;
+	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
+}
+
+void NVCommonSetup(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct fb_var_screeninfo var;
+	u16 implementation = par->Chipset & 0x0ff0;
+	u8 *edidA = NULL, *edidB = NULL;
+	struct fb_monspecs monitorA, monitorB;
+	struct fb_monspecs *monA = NULL, *monB = NULL;
+	int mobile = 0;
+	int tvA = 0;
+	int tvB = 0;
+	int FlatPanel = -1;	/* really means the CRTC is slaved */
+	int Television = 0;
+
+	par->PRAMIN = par->REGS + (0x00710000 / 4);
+	par->PCRTC0 = par->REGS + (0x00600000 / 4);
+	par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
+	par->PFB = par->REGS + (0x00100000 / 4);
+	par->PFIFO = par->REGS + (0x00002000 / 4);
+	par->PGRAPH = par->REGS + (0x00400000 / 4);
+	par->PEXTDEV = par->REGS + (0x00101000 / 4);
+	par->PTIMER = par->REGS + (0x00009000 / 4);
+	par->PMC = par->REGS + (0x00000000 / 4);
+	par->FIFO = par->REGS + (0x00800000 / 4);
+
+	/* 8 bit registers */
+	par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
+	par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
+	par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
+
+	par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
+	    (implementation != 0x0100) &&
+	    (implementation != 0x0150) &&
+	    (implementation != 0x01A0) && (implementation != 0x0200);
+
+	par->fpScaler = (par->FpScale && par->twoHeads &&
+			 (implementation != 0x0110));
+
+	par->twoStagePLL = (implementation == 0x0310) ||
+	    (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
+
+	par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
+	    (implementation != 0x0100);
+
+	par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
+
+	/* look for known laptop chips */
+	switch (par->Chipset & 0xffff) {
+	case 0x0112:
+	case 0x0174:
+	case 0x0175:
+	case 0x0176:
+	case 0x0177:
+	case 0x0179:
+	case 0x017C:
+	case 0x017D:
+	case 0x0186:
+	case 0x0187:
+	case 0x018D:
+	case 0x0286:
+	case 0x028C:
+	case 0x0316:
+	case 0x0317:
+	case 0x031A:
+	case 0x031B:
+	case 0x031C:
+	case 0x031D:
+	case 0x031E:
+	case 0x031F:
+	case 0x0324:
+	case 0x0325:
+	case 0x0328:
+	case 0x0329:
+	case 0x032C:
+	case 0x032D:
+	case 0x0347:
+	case 0x0348:
+	case 0x0349:
+	case 0x034B:
+	case 0x034C:
+	case 0x0160:
+	case 0x0166:
+	case 0x00C8:
+	case 0x00CC:
+	case 0x0144:
+	case 0x0146:
+	case 0x0147:
+	case 0x0148:
+		mobile = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (par->Architecture == NV_ARCH_04)
+		nv4GetConfig(par);
+	else
+		nv10GetConfig(par);
+
+	NVSelectHeadRegisters(par, 0);
+
+	NVLockUnlock(par, 0);
+
+	par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
+
+	par->Television = 0;
+
+	nvidia_create_i2c_busses(par);
+	if (!par->twoHeads) {
+		par->CRTCnumber = 0;
+		nvidia_probe_i2c_connector(par, 1, &edidA);
+		if (edidA && !fb_parse_edid(edidA, &var)) {
+			printk("nvidiafb: EDID found from BUS1\n");
+			monA = &monitorA;
+			fb_edid_to_monspecs(edidA, monA);
+			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+
+			/* NV4 doesn't support FlatPanels */
+			if ((par->Chipset & 0x0fff) <= 0x0020)
+				FlatPanel = 0;
+		} else {
+			VGA_WR08(par->PCIO, 0x03D4, 0x28);
+			if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
+				VGA_WR08(par->PCIO, 0x03D4, 0x33);
+				if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
+					Television = 1;
+				FlatPanel = 1;
+			} else {
+				FlatPanel = 0;
+			}
+			printk("nvidiafb: HW is currently programmed for %s\n",
+			       FlatPanel ? (Television ? "TV" : "DFP") :
+			       "CRT");
+		}
+
+		if (par->FlatPanel == -1) {
+			par->FlatPanel = FlatPanel;
+			par->Television = Television;
+		} else {
+			printk("nvidiafb: Forcing display type to %s as "
+			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
+		}
+	} else {
+		u8 outputAfromCRTC, outputBfromCRTC;
+		int CRTCnumber = -1;
+		u8 slaved_on_A, slaved_on_B;
+		int analog_on_A, analog_on_B;
+		u32 oldhead;
+		u8 cr44;
+
+		if (implementation != 0x0110) {
+			if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
+				outputAfromCRTC = 1;
+			else
+				outputAfromCRTC = 0;
+			if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
+				outputBfromCRTC = 1;
+			else
+				outputBfromCRTC = 0;
+			analog_on_A = NVIsConnected(par, 0);
+			analog_on_B = NVIsConnected(par, 1);
+		} else {
+			outputAfromCRTC = 0;
+			outputBfromCRTC = 1;
+			analog_on_A = 0;
+			analog_on_B = 0;
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		cr44 = VGA_RD08(par->PCIO, 0x03D5);
+
+		VGA_WR08(par->PCIO, 0x03D5, 3);
+		NVSelectHeadRegisters(par, 1);
+		NVLockUnlock(par, 0);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x28);
+		slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+		if (slaved_on_B) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x33);
+			tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, 0);
+		NVSelectHeadRegisters(par, 0);
+		NVLockUnlock(par, 0);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x28);
+		slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+		if (slaved_on_A) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x33);
+			tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+		}
+
+		oldhead = NV_RD32(par->PCRTC0, 0x00000860);
+		NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
+
+		nvidia_probe_i2c_connector(par, 1, &edidA);
+		if (edidA && !fb_parse_edid(edidA, &var)) {
+			printk("nvidiafb: EDID found from BUS1\n");
+			monA = &monitorA;
+			fb_edid_to_monspecs(edidA, monA);
+		}
+
+		nvidia_probe_i2c_connector(par, 2, &edidB);
+		if (edidB && !fb_parse_edid(edidB, &var)) {
+			printk("nvidiafb: EDID found from BUS2\n");
+			monB = &monitorB;
+			fb_edid_to_monspecs(edidB, monB);
+		}
+
+		if (slaved_on_A && !tvA) {
+			CRTCnumber = 0;
+			FlatPanel = 1;
+			printk("nvidiafb: CRTC 0 is currently programmed for "
+			       "DFP\n");
+		} else if (slaved_on_B && !tvB) {
+			CRTCnumber = 1;
+			FlatPanel = 1;
+			printk("nvidiafb: CRTC 1 is currently programmed "
+			       "for DFP\n");
+		} else if (analog_on_A) {
+			CRTCnumber = outputAfromCRTC;
+			FlatPanel = 0;
+			printk("nvidiafb: CRTC %i appears to have a "
+			       "CRT attached\n", CRTCnumber);
+		} else if (analog_on_B) {
+			CRTCnumber = outputBfromCRTC;
+			FlatPanel = 0;
+			printk("nvidiafb: CRTC %i"
+			       "appears to have a "
+			       "CRT attached\n", CRTCnumber);
+		} else if (slaved_on_A) {
+			CRTCnumber = 0;
+			FlatPanel = 1;
+			Television = 1;
+			printk("nvidiafb: CRTC 0 is currently programmed "
+			       "for TV\n");
+		} else if (slaved_on_B) {
+			CRTCnumber = 1;
+			FlatPanel = 1;
+			Television = 1;
+			printk("nvidiafb: CRTC 1 is currently programmed for "
+			       "TV\n");
+		} else if (monA) {
+			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+		} else if (monB) {
+			FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
+		}
+
+		if (par->FlatPanel == -1) {
+			if (FlatPanel != -1) {
+				par->FlatPanel = FlatPanel;
+				par->Television = Television;
+			} else {
+				printk("nvidiafb: Unable to detect display "
+				       "type...\n");
+				if (mobile) {
+					printk("...On a laptop, assuming "
+					       "DFP\n");
+					par->FlatPanel = 1;
+				} else {
+					printk("...Using default of CRT\n");
+					par->FlatPanel = 0;
+				}
+			}
+		} else {
+			printk("nvidiafb: Forcing display type to %s as "
+			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
+		}
+
+		if (par->CRTCnumber == -1) {
+			if (CRTCnumber != -1)
+				par->CRTCnumber = CRTCnumber;
+			else {
+				printk("nvidiafb: Unable to detect which "
+				       "CRTCNumber...\n");
+				if (par->FlatPanel)
+					par->CRTCnumber = 1;
+				else
+					par->CRTCnumber = 0;
+				printk("...Defaulting to CRTCNumber %i\n",
+				       par->CRTCnumber);
+			}
+		} else {
+			printk("nvidiafb: Forcing CRTCNumber %i as "
+			       "specified\n", par->CRTCnumber);
+		}
+
+		if (monA) {
+			if (((monA->input & FB_DISP_DDI) &&
+			     par->FlatPanel) ||
+			    ((!(monA->input & FB_DISP_DDI)) &&
+			     !par->FlatPanel)) {
+				if (monB) {
+					fb_destroy_modedb(monB->modedb);
+					monB = NULL;
+				}
+			} else {
+				fb_destroy_modedb(monA->modedb);
+				monA = NULL;
+			}
+		}
+
+		if (monB) {
+			if (((monB->input & FB_DISP_DDI) &&
+			     !par->FlatPanel) ||
+			    ((!(monB->input & FB_DISP_DDI)) &&
+			     par->FlatPanel)) {
+				fb_destroy_modedb(monB->modedb);
+				monB = NULL;
+			} else
+				monA = monB;
+		}
+
+		if (implementation == 0x0110)
+			cr44 = par->CRTCnumber * 0x3;
+
+		NV_WR32(par->PCRTC0, 0x00000860, oldhead);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, cr44);
+		NVSelectHeadRegisters(par, par->CRTCnumber);
+	}
+
+	printk("nvidiafb: Using %s on CRTC %i\n",
+	       par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
+	       par->CRTCnumber);
+
+	if (par->FlatPanel && !par->Television) {
+		par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
+		par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
+		par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
+
+		printk("Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
+	}
+
+	if (monA)
+		info->monspecs = *monA;
+
+	kfree(edidA);
+	kfree(edidB);
+}
diff -puN /dev/null drivers/video/nvidia/nv_type.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/video/nvidia/nv_type.h	2005-02-24 23:15:31.000000000 -0800
@@ -0,0 +1,174 @@
+#ifndef __NV_TYPE_H__
+#define __NV_TYPE_H__
+
+#include <linux/fb.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
+#define NV_ARCH_04  0x04
+#define NV_ARCH_10  0x10
+#define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
+
+#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1)  << (b))
+#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
+#define SetBF(mask,value) ((value) << (0?mask))
+#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
+#define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
+#define SetBit(n) (1<<(n))
+#define Set8Bits(value) ((value)&0xff)
+
+#define V_DBLSCAN  1
+
+typedef struct {
+	int bitsPerPixel;
+	int depth;
+	int displayWidth;
+	int weight;
+} NVFBLayout;
+
+#define NUM_SEQ_REGS		0x05
+#define NUM_CRT_REGS		0x41
+#define NUM_GRC_REGS		0x09
+#define NUM_ATC_REGS		0x15
+
+struct nvidia_par;
+
+struct nvidia_i2c_chan {
+	struct nvidia_par *par;
+	unsigned long ddc_base;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+};
+
+typedef struct _riva_hw_state {
+	u8 attr[NUM_ATC_REGS];
+	u8 crtc[NUM_CRT_REGS];
+	u8 gra[NUM_GRC_REGS];
+	u8 seq[NUM_SEQ_REGS];
+	u8 misc_output;
+	u32 bpp;
+	u32 width;
+	u32 height;
+	u32 interlace;
+	u32 repaint0;
+	u32 repaint1;
+	u32 screen;
+	u32 scale;
+	u32 dither;
+	u32 extra;
+	u32 fifo;
+	u32 pixel;
+	u32 horiz;
+	u32 arbitration0;
+	u32 arbitration1;
+	u32 pll;
+	u32 pllB;
+	u32 vpll;
+	u32 vpll2;
+	u32 vpllB;
+	u32 vpll2B;
+	u32 pllsel;
+	u32 general;
+	u32 crtcOwner;
+	u32 head;
+	u32 head2;
+	u32 config;
+	u32 cursorConfig;
+	u32 cursor0;
+	u32 cursor1;
+	u32 cursor2;
+	u32 timingH;
+	u32 timingV;
+	u32 displayV;
+	u32 crtcSync;
+} RIVA_HW_STATE;
+
+struct riva_regs {
+	RIVA_HW_STATE ext;
+};
+
+struct nvidia_par {
+	RIVA_HW_STATE SavedReg;
+	RIVA_HW_STATE ModeReg;
+	RIVA_HW_STATE *CurrentState;
+	u32 pseudo_palette[16];
+	struct pci_dev *pci_dev;
+	u32 Architecture;
+	u32 CursorStart;
+	int Chipset;
+	int bus;
+	unsigned long FbAddress;
+	u8 __iomem *FbStart;
+	u32 FbMapSize;
+	u32 FbUsableSize;
+	u32 ScratchBufferSize;
+	u32 ScratchBufferStart;
+	int FpScale;
+	u32 MinVClockFreqKHz;
+	u32 MaxVClockFreqKHz;
+	u32 CrystalFreqKHz;
+	u32 RamAmountKBytes;
+	u32 IOBase;
+	NVFBLayout CurrentLayout;
+	int cursor_reset;
+	int lockup;
+	int videoKey;
+	int FlatPanel;
+	int FPDither;
+	int Television;
+	int CRTCnumber;
+	int alphaCursor;
+	int twoHeads;
+	int twoStagePLL;
+	int fpScaler;
+	int fpWidth;
+	int fpHeight;
+	int PanelTweak;
+	int paneltweak;
+	u32 crtcSync_read;
+	u32 fpSyncs;
+	u32 dmaPut;
+	u32 dmaCurrent;
+	u32 dmaFree;
+	u32 dmaMax;
+	u32 __iomem *dmaBase;
+	u32 currentRop;
+	int WaitVSyncPossible;
+	int BlendingPossible;
+	u32 paletteEnabled;
+	u32 forceCRTC;
+	u8 DDCBase;
+#ifdef CONFIG_MTRR
+	struct {
+		int vram;
+		int vram_valid;
+	} mtrr;
+#endif
+	struct nvidia_i2c_chan chan[3];
+
+	volatile u32 __iomem *REGS;
+	volatile u32 __iomem *PCRTC0;
+	volatile u32 __iomem *PCRTC;
+	volatile u32 __iomem *PRAMDAC0;
+	volatile u32 __iomem *PFB;
+	volatile u32 __iomem *PFIFO;
+	volatile u32 __iomem *PGRAPH;
+	volatile u32 __iomem *PEXTDEV;
+	volatile u32 __iomem *PTIMER;
+	volatile u32 __iomem *PMC;
+	volatile u32 __iomem *PRAMIN;
+	volatile u32 __iomem *FIFO;
+	volatile u32 __iomem *CURSOR;
+	volatile u8 __iomem *PCIO0;
+	volatile u8 __iomem *PCIO;
+	volatile u8 __iomem *PVIO;
+	volatile u8 __iomem *PDIO0;
+	volatile u8 __iomem *PDIO;
+	volatile u32 __iomem *PRAMDAC;
+};
+
+#endif				/* __NV_TYPE_H__ */
diff -puN include/linux/fb.h~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets include/linux/fb.h
--- 25/include/linux/fb.h~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets	2005-02-24 23:15:31.000000000 -0800
+++ 25-akpm/include/linux/fb.h	2005-02-24 23:15:31.000000000 -0800
@@ -103,7 +103,10 @@
 #define FB_ACCEL_SIS_GLAMOUR_2  40	/* SiS 315, 650, 740		*/
 #define FB_ACCEL_SIS_XABRE      41	/* SiS 330 ("Xabre")		*/
 #define FB_ACCEL_I830           42      /* Intel 830M/845G/85x/865G     */
-
+#define FB_ACCEL_NV_10          43      /* nVidia Arch 10               */
+#define FB_ACCEL_NV_20          44      /* nVidia Arch 20               */
+#define FB_ACCEL_NV_30          45      /* nVidia Arch 30               */
+#define FB_ACCEL_NV_40          46      /* nVidia Arch 40               */
 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
diff -puN include/linux/pci_ids.h~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets include/linux/pci_ids.h
--- 25/include/linux/pci_ids.h~nvidiafb-add-update-framebuffer-driver-for-nvidia-chipsets	2005-02-24 23:15:31.000000000 -0800
+++ 25-akpm/include/linux/pci_ids.h	2005-02-24 23:15:31.000000000 -0800
@@ -1098,6 +1098,7 @@
 #define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
 #define PCI_DEVICE_ID_NVIDIA_TNT2		0x0028
 #define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
+#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN        0x002a
 #define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
 #define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE	0x0035
@@ -1105,6 +1106,11 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_10		0x0037
 #define PCI_DEVICE_ID_NVIDIA_NVENET_11		0x0038
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2	0x003e
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800       0x0041
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE    0x0042
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT    0x0045
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000     0x004E
 #define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS	0x0052
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE	0x0053
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA	0x0054
@@ -1122,6 +1128,12 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_5		0x008c
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
 #define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
+#define PCI_DEVICE_ID_GEFORCE_6800A             0x00c1
+#define PCI_DEVICE_ID_GEFORCE_6800A_LE          0x00c2
+#define PCI_DEVICE_ID_GEFORCE_GO_6800           0x00c8
+#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA     0x00c9
+#define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
+#define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3		0x00d1
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO		0x00da
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS	0x00d4
@@ -1142,21 +1154,43 @@
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO	0x0112
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT	0x0140
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600	0x0141
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL	0x0145
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540	0x014E
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200	0x014F
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200    0x0164
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250    0x0166
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1  0x0167
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1  0x0168
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460	0x0170
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440	0x0171
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420	0x0172
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE	0x0173
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO	0x0174
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO	0x0175
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO    0x0177
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL	0x0178
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_200	0x017A
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL	0x017B
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL	0x017C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO    0x0186
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO    0x0187
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL    0x0188
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC    0x0189
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS    0x018A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL    0x018B
 #define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
 #define PCI_DEVICE_ID_NVIDIA_NFORCE		0x01a4
 #define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO		0x01b1
@@ -1168,13 +1202,61 @@
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
 #define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC		0x0203
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B      0x0211
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE   0x0212
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT   0x0215
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600	0x0250
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400	0x0251
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200	0x0253
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL	0x0258
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL	0x0259
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL	0x025B
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200	0x0329
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800	0x0280
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO       0x0286
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL        0x0288
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL        0x0289
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL       0x028C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA  0x0301
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800        0x0302
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000         0x0308
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000         0x0309
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA  0x0311
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600        0x0312
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE      0x0314
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600      0x031A
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650      0x031B
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700        0x031C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200        0x0320
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA  0x0321
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1      0x0322
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE      0x0323
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200      0x0324
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250      0x0325
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500        0x0326
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100        0x0327
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32   0x0328
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200	    0x0329
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI     0x032A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500          0x032B
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300      0x032C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100      0x032D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA  0x0330
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900        0x0331
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT      0x0332
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA  0x0333
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT      0x0334
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000         0x0338
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700          0x033F
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA  0x0341
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700        0x0342
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE      0x0343
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE      0x0344
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1    0x0347
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2    0x0348
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000       0x034C
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
_
