aboutsummaryrefslogtreecommitdiff
path: root/drivers/video/nvidia
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/video/nvidia
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/video/nvidia')
-rw-r--r--drivers/video/nvidia/Makefile12
-rw-r--r--drivers/video/nvidia/nv_accel.c419
-rw-r--r--drivers/video/nvidia/nv_dma.h188
-rw-r--r--drivers/video/nvidia/nv_hw.c1593
-rw-r--r--drivers/video/nvidia/nv_i2c.c215
-rw-r--r--drivers/video/nvidia/nv_local.h107
-rw-r--r--drivers/video/nvidia/nv_of.c59
-rw-r--r--drivers/video/nvidia/nv_proto.h58
-rw-r--r--drivers/video/nvidia/nv_setup.c636
-rw-r--r--drivers/video/nvidia/nv_type.h174
-rw-r--r--drivers/video/nvidia/nvidia.c1729
11 files changed, 5190 insertions, 0 deletions
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
new file mode 100644
index 00000000000..690d37e8de5
--- /dev/null
+++ b/drivers/video/nvidia/Makefile
@@ -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 --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
new file mode 100644
index 00000000000..f377a29ec97
--- /dev/null
+++ b/drivers/video/nvidia/nv_accel.c
@@ -0,0 +1,419 @@
+ /***************************************************************************\
+|* *|
+|* 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. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#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;
+ }
+}
+
+static void NVDmaKickoff(struct nvidia_par *par)
+{
+ if (par->dmaCurrent != par->dmaPut) {
+ par->dmaPut = par->dmaCurrent;
+ WRITE_PUT(par, par->dmaPut);
+ }
+}
+
+static 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 j, k = 0;
+
+ width = (image->width + 31) & ~31;
+ dsize = (width * image->height) >> 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));
+
+ while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
+ NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0),
+ RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
+
+ for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
+ tmp = data[k++];
+ reverse_order(&tmp);
+ NVDmaNext(par, tmp);
+ }
+
+ dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
+ }
+
+ if (dsize) {
+ 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 --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
new file mode 100644
index 00000000000..a7ed1c0acbb
--- /dev/null
+++ b/drivers/video/nvidia/nv_dma.h
@@ -0,0 +1,188 @@
+
+ /***************************************************************************\
+|* *|
+|* 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. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#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 --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
new file mode 100644
index 00000000000..b989358437b
--- /dev/null
+++ b/drivers/video/nvidia/nv_hw.c
@@ -0,0 +1,1593 @@
+ /***************************************************************************\
+|* *|
+|* 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. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+/* $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 --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
new file mode 100644
index 00000000000..3757c1407c1
--- /dev/null
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -0,0 +1,215 @@
+/*
+ * 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);
+ chan->par = NULL;
+ }
+
+ 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;
+
+ if (!chan->par)
+ return NULL;
+
+ 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 --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
new file mode 100644
index 00000000000..9da320986f4
--- /dev/null
+++ b/drivers/video/nvidia/nv_local.h
@@ -0,0 +1,107 @@
+/***************************************************************************\
+|* *|
+|* 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. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#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) { \
+ _NV_FENCE() \
+ 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 --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
new file mode 100644
index 00000000000..7d12eb85310
--- /dev/null
+++ b/drivers/video/nvidia/nv_of.c
@@ -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 --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
new file mode 100644
index 00000000000..42847ce1b8d
--- /dev/null
+++ b/drivers/video/nvidia/nv_proto.h
@@ -0,0 +1,58 @@
+/* $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 NVWriteDacMask(struct nvidia_par *par, u8 value);
+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 --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
new file mode 100644
index 00000000000..0bbdca2e0f9
--- /dev/null
+++ b/drivers/video/nvidia/nv_setup.c
@@ -0,0 +1,636 @@
+ /***************************************************************************\
+|* *|
+|* 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. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#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));
+}
+#if 0
+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;
+}
+#endif /* 0 */
+void NVWriteDacMask(struct nvidia_par *par, u8 value)
+{
+ VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
+}
+#if 0
+u8 NVReadDacMask(struct nvidia_par *par)
+{
+ return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
+}
+#endif /* 0 */
+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 --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
new file mode 100644
index 00000000000..e4a5b1da71c
--- /dev/null
+++ b/drivers/video/nvidia/nv_type.h
@@ -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 --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
new file mode 100644
index 00000000000..3a6555a8aaa
--- /dev/null
+++ b/drivers/video/nvidia/nvidia.c
@@ -0,0 +1,1729 @@
+/*
+ * 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 __devinitdata = -1; /* Autodetect later */
+static int forceCRTC __devinitdata = -1;
+static int hwcur __devinitdata = 0;
+static int noaccel __devinitdata = 0;
+static int noscale __devinitdata = 0;
+static int paneltweak __devinitdata = 0;
+#ifdef CONFIG_MTRR
+static int nomtrr __devinitdata = 0;
+#endif
+
+static char *mode_option __devinitdata = NULL;
+
+static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
+ .type = FB_TYPE_PACKED_PIXELS,
+ .xpanstep = 8,
+ .ypanstep = 1,
+};
+
+static struct fb_var_screeninfo __devinitdata 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->var);
+ 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;
+
+ 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;
+
+ var->xres_virtual = (var->xres_virtual + 63) & ~63;
+
+ 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;
+ var->xres_virtual &= ~63;
+ 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 &= ~63;
+
+ 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;
+
+ 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);
+
+ 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;
+ par->FpScale = (!noscale);
+ par->paneltweak = paneltweak;
+
+ /* 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);
+ fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
+ err_out_free_base1:
+ 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 */
+
+ iounmap(info->screen_base);
+ fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
+ iounmap(par->REGS);
+ 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
+static int __devinit 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
+ *
+ * ------------------------------------------------------------------------- */
+
+static 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 */
+