summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev/riva
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-02-13 15:31:38 +0200
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-17 08:10:19 +0300
commitf7018c21350204c4cf628462f229d44d03545254 (patch)
tree408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/fbdev/riva
parentc26ef3eb3c11274bad1b64498d0a134f85755250 (diff)
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related files, directories for backlight, console, linux logo, lots of fbdev device drivers, fbdev framework files. Make some order into the chaos by creating drivers/video/fbdev directory, and move all fbdev related files there. No functionality is changed, although I guess it is possible that some subtle Makefile build order related issue could be created by this patch. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Rob Clark <robdclark@gmail.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/fbdev/riva')
-rw-r--r--drivers/video/fbdev/riva/Makefile11
-rw-r--r--drivers/video/fbdev/riva/fbdev.c2230
-rw-r--r--drivers/video/fbdev/riva/nv_driver.c422
-rw-r--r--drivers/video/fbdev/riva/nv_type.h58
-rw-r--r--drivers/video/fbdev/riva/nvreg.h188
-rw-r--r--drivers/video/fbdev/riva/riva_hw.c2268
-rw-r--r--drivers/video/fbdev/riva/riva_hw.h563
-rw-r--r--drivers/video/fbdev/riva/riva_tbl.h1008
-rw-r--r--drivers/video/fbdev/riva/rivafb-i2c.c166
-rw-r--r--drivers/video/fbdev/riva/rivafb.h77
10 files changed, 6991 insertions, 0 deletions
diff --git a/drivers/video/fbdev/riva/Makefile b/drivers/video/fbdev/riva/Makefile
new file mode 100644
index 000000000000..8898c9915b02
--- /dev/null
+++ b/drivers/video/fbdev/riva/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Riva framebuffer driver
+#
+
+obj-$(CONFIG_FB_RIVA) += rivafb.o
+
+rivafb-objs := fbdev.o riva_hw.o nv_driver.o
+
+ifdef CONFIG_FB_RIVA_I2C
+ rivafb-objs += rivafb-i2c.o
+endif
diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c
new file mode 100644
index 000000000000..8a8d7f060784
--- /dev/null
+++ b/drivers/video/fbdev/riva/fbdev.c
@@ -0,0 +1,2230 @@
+/*
+ * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
+ *
+ * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
+ *
+ * Copyright 1999-2000 Jeff Garzik
+ *
+ * Contributors:
+ *
+ * Ani Joshi: Lots of debugging and cleanup work, really helped
+ * get the driver going
+ *
+ * Ferenc Bakonyi: Bug fixes, cleanup, modularization
+ *
+ * Jindrich Makovicka: Accel code help, hw cursor, mtrr
+ *
+ * Paul Richards: Bug fixes, updates
+ *
+ * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
+ * Includes riva_hw.c from nVidia, see copyright below.
+ * KGI code provided the basis for state storage, init, and mode switching.
+ *
+ * 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.
+ *
+ * Known bugs and issues:
+ * restoring text mode fails
+ * doublescan modes are broken
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/backlight.h>
+#include <linux/bitrev.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/machdep.h>
+#include <asm/backlight.h>
+#endif
+
+#include "rivafb.h"
+#include "nvreg.h"
+
+/* version number of this driver */
+#define RIVAFB_VERSION "0.9.5b"
+
+/* ------------------------------------------------------------------------- *
+ *
+ * various helpful macros and constants
+ *
+ * ------------------------------------------------------------------------- */
+#ifdef CONFIG_FB_RIVA_DEBUG
+#define NVTRACE printk
+#else
+#define NVTRACE if(0) printk
+#endif
+
+#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __func__)
+#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __func__)
+
+#ifdef CONFIG_FB_RIVA_DEBUG
+#define assert(expr) \
+ if(!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+ #expr,__FILE__,__func__,__LINE__); \
+ BUG(); \
+ }
+#else
+#define assert(expr)
+#endif
+
+#define PFX "rivafb: "
+
+/* macro that allows you to set overflow bits */
+#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
+#define SetBit(n) (1<<(n))
+#define Set8Bits(value) ((value)&0xff)
+
+/* HW cursor parameters */
+#define MAX_CURS 32
+
+/* ------------------------------------------------------------------------- *
+ *
+ * prototypes
+ *
+ * ------------------------------------------------------------------------- */
+
+static int rivafb_blank(int blank, struct fb_info *info);
+
+/* ------------------------------------------------------------------------- *
+ *
+ * card identification
+ *
+ * ------------------------------------------------------------------------- */
+
+static struct pci_device_id rivafb_pci_tbl[] = {
+ { PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 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_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 },
+ // NF2/IGP version, GeForce 4 MX, NV18
+ { PCI_VENDOR_ID_NVIDIA, 0x01f0,
+ 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_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_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_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_GEFORCE_FX_GO_5200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0, } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
+
+/* ------------------------------------------------------------------------- *
+ *
+ * global variables
+ *
+ * ------------------------------------------------------------------------- */
+
+/* command line data, set in rivafb_setup() */
+static int flatpanel = -1; /* Autodetect later */
+static int forceCRTC = -1;
+static bool noaccel = 0;
+#ifdef CONFIG_MTRR
+static bool nomtrr = 0;
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int backlight = 1;
+#else
+static int backlight = 0;
+#endif
+
+static char *mode_option = NULL;
+static bool strictmode = 0;
+
+static struct fb_fix_screeninfo rivafb_fix = {
+ .type = FB_TYPE_PACKED_PIXELS,
+ .xpanstep = 1,
+ .ypanstep = 1,
+};
+
+static struct fb_var_screeninfo rivafb_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
+};
+
+/* from GGI */
+static const struct riva_regs reg_template = {
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x01, 0x0F, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CRT */
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, /* 0x10 */
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, /* 0x40 */
+ },
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */
+ 0xFF},
+ {0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */
+ 0xEB /* MISC */
+};
+
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_FB_RIVA_BACKLIGHT
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)
+
+static int riva_bl_get_level_brightness(struct riva_par *par,
+ int level)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int nlevel;
+
+ /* Get and convert the value */
+ /* No locking on bl_curve since accessing a single value */
+ nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;
+
+ if (nlevel < 0)
+ nlevel = 0;
+ else if (nlevel < MIN_LEVEL)
+ nlevel = MIN_LEVEL;
+ else if (nlevel > MAX_LEVEL)
+ nlevel = MAX_LEVEL;
+
+ return nlevel;
+}
+
+static int riva_bl_update_status(struct backlight_device *bd)
+{
+ struct riva_par *par = bl_get_data(bd);
+ U032 tmp_pcrt, tmp_pmc;
+ int level;
+
+ if (bd->props.power != FB_BLANK_UNBLANK ||
+ bd->props.fb_blank != FB_BLANK_UNBLANK)
+ level = 0;
+ else
+ level = bd->props.brightness;
+
+ tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF;
+ tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC;
+ if(level > 0) {
+ tmp_pcrt |= 0x1;
+ tmp_pmc |= (1 << 31); /* backlight bit */
+ tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
+ }
+ NV_WR32(par->riva.PCRTC0, 0x081C, tmp_pcrt);
+ NV_WR32(par->riva.PMC, 0x10F0, tmp_pmc);
+
+ return 0;
+}
+
+static int riva_bl_get_brightness(struct backlight_device *bd)
+{
+ return bd->props.brightness;
+}
+
+static const struct backlight_ops riva_bl_ops = {
+ .get_brightness = riva_bl_get_brightness,
+ .update_status = riva_bl_update_status,
+};
+
+static void riva_bl_init(struct riva_par *par)
+{
+ struct backlight_properties props;
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ struct backlight_device *bd;
+ char name[12];
+
+ if (!par->FlatPanel)
+ return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (!machine_is(powermac) ||
+ !pmac_has_backlight_type("mnca"))
+ return;
+#endif
+
+ snprintf(name, sizeof(name), "rivabl%d", info->node);
+
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_RAW;
+ props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
+ bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
+ &props);
+ if (IS_ERR(bd)) {
+ info->bl_dev = NULL;
+ printk(KERN_WARNING "riva: Backlight registration failed\n");
+ goto error;
+ }
+
+ info->bl_dev = bd;
+ fb_bl_default_curve(info, 0,
+ MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,
+ FB_BACKLIGHT_MAX);
+
+ bd->props.brightness = bd->props.max_brightness;
+ bd->props.power = FB_BLANK_UNBLANK;
+ backlight_update_status(bd);
+
+ printk("riva: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ return;
+}
+
+static void riva_bl_exit(struct fb_info *info)
+{
+ struct backlight_device *bd = info->bl_dev;
+
+ backlight_device_unregister(bd);
+ printk("riva: Backlight unloaded\n");
+}
+#else
+static inline void riva_bl_init(struct riva_par *par) {}
+static inline void riva_bl_exit(struct fb_info *info) {}
+#endif /* CONFIG_FB_RIVA_BACKLIGHT */
+
+/* ------------------------------------------------------------------------- *
+ *
+ * MMIO access macros
+ *
+ * ------------------------------------------------------------------------- */
+
+static inline void CRTCout(struct riva_par *par, unsigned char index,
+ unsigned char val)
+{
+ VGA_WR08(par->riva.PCIO, 0x3d4, index);
+ VGA_WR08(par->riva.PCIO, 0x3d5, val);
+}
+
+static inline unsigned char CRTCin(struct riva_par *par,
+ unsigned char index)
+{
+ VGA_WR08(par->riva.PCIO, 0x3d4, index);
+ return (VGA_RD08(par->riva.PCIO, 0x3d5));
+}
+
+static inline void GRAout(struct riva_par *par, unsigned char index,
+ unsigned char val)
+{
+ VGA_WR08(par->riva.PVIO, 0x3ce, index);
+ VGA_WR08(par->riva.PVIO, 0x3cf, val);
+}
+
+static inline unsigned char GRAin(struct riva_par *par,
+ unsigned char index)
+{
+ VGA_WR08(par->riva.PVIO, 0x3ce, index);
+ return (VGA_RD08(par->riva.PVIO, 0x3cf));
+}
+
+static inline void SEQout(struct riva_par *par, unsigned char index,
+ unsigned char val)
+{
+ VGA_WR08(par->riva.PVIO, 0x3c4, index);
+ VGA_WR08(par->riva.PVIO, 0x3c5, val);
+}
+
+static inline unsigned char SEQin(struct riva_par *par,
+ unsigned char index)
+{
+ VGA_WR08(par->riva.PVIO, 0x3c4, index);
+ return (VGA_RD08(par->riva.PVIO, 0x3c5));
+}
+
+static inline void ATTRout(struct riva_par *par, unsigned char index,
+ unsigned char val)
+{
+ VGA_WR08(par->riva.PCIO, 0x3c0, index);
+ VGA_WR08(par->riva.PCIO, 0x3c0, val);
+}
+
+static inline unsigned char ATTRin(struct riva_par *par,
+ unsigned char index)
+{
+ VGA_WR08(par->riva.PCIO, 0x3c0, index);
+ return (VGA_RD08(par->riva.PCIO, 0x3c1));
+}
+
+static inline void MISCout(struct riva_par *par, unsigned char val)
+{
+ VGA_WR08(par->riva.PVIO, 0x3c2, val);
+}
+
+static inline unsigned char MISCin(struct riva_par *par)
+{
+ return (VGA_RD08(par->riva.PVIO, 0x3cc));
+}
+
+static inline void reverse_order(u32 *l)
+{
+ u8 *a = (u8 *)l;
+ a[0] = bitrev8(a[0]);
+ a[1] = bitrev8(a[1]);
+ a[2] = bitrev8(a[2]);
+ a[3] = bitrev8(a[3]);
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * cursor stuff
+ *
+ * ------------------------------------------------------------------------- */
+
+/**
+ * rivafb_load_cursor_image - load cursor image to hardware
+ * @data: address to monochrome bitmap (1 = foreground color, 0 = background)
+ * @par: pointer to private data
+ * @w: width of cursor image in pixels
+ * @h: height of cursor image in scanlines
+ * @bg: background color (ARGB1555) - alpha bit determines opacity
+ * @fg: foreground color (ARGB1555)
+ *
+ * DESCRIPTiON:
+ * Loads cursor image based on a monochrome source and mask bitmap. The
+ * image bits determines the color of the pixel, 0 for background, 1 for
+ * foreground. Only the affected region (as determined by @w and @h
+ * parameters) will be updated.
+ *
+ * CALLED FROM:
+ * rivafb_cursor()
+ */
+static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
+ u16 bg, u16 fg, u32 w, u32 h)
+{
+ int i, j, k = 0;
+ u32 b, tmp;
+ u32 *data = (u32 *)data8;
+ bg = le16_to_cpu(bg);
+ fg = le16_to_cpu(fg);
+
+ 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
+ writel(tmp, &par->riva.CURSOR[k++]);
+ }
+ k += (MAX_CURS - w)/2;
+ }
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * general utility functions
+ *
+ * ------------------------------------------------------------------------- */
+
+/**
+ * riva_wclut - set CLUT entry
+ * @chip: pointer to RIVA_HW_INST object
+ * @regnum: register number
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ *
+ * DESCRIPTION:
+ * Sets color register @regnum.
+ *
+ * CALLED FROM:
+ * rivafb_setcolreg()
+ */
+static void riva_wclut(RIVA_HW_INST *chip,
+ unsigned char regnum, unsigned char red,
+ unsigned char green, unsigned char blue)
+{
+ VGA_WR08(chip->PDIO, 0x3c8, regnum);
+ VGA_WR08(chip->PDIO, 0x3c9, red);
+ VGA_WR08(chip->PDIO, 0x3c9, green);
+ VGA_WR08(chip->PDIO, 0x3c9, blue);
+}
+
+/**
+ * riva_rclut - read fromCLUT register
+ * @chip: pointer to RIVA_HW_INST object
+ * @regnum: register number
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ *
+ * DESCRIPTION:
+ * Reads red, green, and blue from color register @regnum.
+ *
+ * CALLED FROM:
+ * rivafb_setcolreg()
+ */
+static void riva_rclut(RIVA_HW_INST *chip,
+ unsigned char regnum, unsigned char *red,
+ unsigned char *green, unsigned char *blue)
+{
+
+ VGA_WR08(chip->PDIO, 0x3c7, regnum);
+ *red = VGA_RD08(chip->PDIO, 0x3c9);
+ *green = VGA_RD08(chip->PDIO, 0x3c9);
+ *blue = VGA_RD08(chip->PDIO, 0x3c9);
+}
+
+/**
+ * riva_save_state - saves current chip state
+ * @par: pointer to riva_par object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Saves current chip state to @regs.
+ *
+ * CALLED FROM:
+ * rivafb_probe()
+ */
+/* from GGI */
+static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
+{
+ int i;
+
+ NVTRACE_ENTER();
+ par->riva.LockUnlock(&par->riva, 0);
+
+ par->riva.UnloadStateExt(&par->riva, &regs->ext);
+
+ regs->misc_output = MISCin(par);
+
+ for (i = 0; i < NUM_CRT_REGS; i++)
+ regs->crtc[i] = CRTCin(par, i);
+
+ for (i = 0; i < NUM_ATC_REGS; i++)
+ regs->attr[i] = ATTRin(par, i);
+
+ for (i = 0; i < NUM_GRC_REGS; i++)
+ regs->gra[i] = GRAin(par, i);
+
+ for (i = 0; i < NUM_SEQ_REGS; i++)
+ regs->seq[i] = SEQin(par, i);
+ NVTRACE_LEAVE();
+}
+
+/**
+ * riva_load_state - loads current chip state
+ * @par: pointer to riva_par object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Loads chip state from @regs.
+ *
+ * CALLED FROM:
+ * riva_load_video_mode()
+ * rivafb_probe()
+ * rivafb_remove()
+ */
+/* from GGI */
+static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
+{
+ RIVA_HW_STATE *state = &regs->ext;
+ int i;
+
+ NVTRACE_ENTER();
+ CRTCout(par, 0x11, 0x00);
+
+ par->riva.LockUnlock(&par->riva, 0);
+
+ par->riva.LoadStateExt(&par->riva, state);
+
+ MISCout(par, regs->misc_output);
+
+ for (i = 0; i < NUM_CRT_REGS; i++) {
+ switch (i) {
+ case 0x19:
+ case 0x20 ... 0x40:
+ break;
+ default:
+ CRTCout(par, i, regs->crtc[i]);
+ }
+ }
+
+ for (i = 0; i < NUM_ATC_REGS; i++)
+ ATTRout(par, i, regs->attr[i]);
+
+ for (i = 0; i < NUM_GRC_REGS; i++)
+ GRAout(par, i, regs->gra[i]);
+
+ for (i = 0; i < NUM_SEQ_REGS; i++)
+ SEQout(par, i, regs->seq[i]);
+ NVTRACE_LEAVE();
+}
+
+/**
+ * riva_load_video_mode - calculate timings
+ * @info: pointer to fb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Calculate some timings and then send em off to riva_load_state().
+ *
+ * CALLED FROM:
+ * rivafb_set_par()
+ */
+static int riva_load_video_mode(struct fb_info *info)
+{
+ int bpp, width, hDisplaySize, hDisplay, hStart,
+ hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
+ int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
+ int rc;
+ struct riva_par *par = info->par;
+ struct riva_regs newmode;
+
+ NVTRACE_ENTER();
+ /* time to calculate */
+ rivafb_blank(FB_BLANK_NORMAL, info);
+
+ bpp = info->var.bits_per_pixel;
+ if (bpp == 16 && info->var.green.length == 5)
+ bpp = 15;
+ width = info->var.xres_virtual;
+ hDisplaySize = info->var.xres;
+ hDisplay = (hDisplaySize / 8) - 1;
+ hStart = (hDisplaySize + info->var.right_margin) / 8 - 1;
+ hEnd = (hDisplaySize + info->var.right_margin +
+ info->var.hsync_len) / 8 - 1;
+ hTotal = (hDisplaySize + info->var.right_margin +
+ info->var.hsync_len + info->var.left_margin) / 8 - 5;
+ hBlankStart = hDisplay;
+ hBlankEnd = hTotal + 4;
+
+ height = info->var.yres_virtual;
+ vDisplay = info->var.yres - 1;
+ vStart = info->var.yres + info->var.lower_margin - 1;
+ vEnd = info->var.yres + info->var.lower_margin +
+ info->var.vsync_len - 1;
+ vTotal = info->var.yres + info->var.lower_margin +
+ info->var.vsync_len + info->var.upper_margin + 2;
+ vBlankStart = vDisplay;
+ vBlankEnd = vTotal + 1;
+ dotClock = 1000000000 / info->var.pixclock;
+
+ memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
+
+ if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ vTotal |= 1;
+
+ if (par->FlatPanel) {
+ vStart = vTotal - 3;
+ vEnd = vTotal - 2;
+ vBlankStart = vStart;
+ hStart = hTotal - 3;
+ hEnd = hTotal - 2;
+ hBlankEnd = hTotal + 4;
+ }
+
+ newmode.crtc[0x0] = Set8Bits (hTotal);
+ newmode.crtc[0x1] = Set8Bits (hDisplay);
+ newmode.crtc[0x2] = Set8Bits (hBlankStart);
+ newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
+ newmode.crtc[0x4] = Set8Bits (hStart);
+ newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7)
+ | SetBitField (hEnd, 4: 0, 4:0);
+ newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
+ newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
+ | SetBitField (vDisplay, 8: 8, 1:1)
+ | SetBitField (vStart, 8: 8, 2:2)
+ | SetBitField (vBlankStart, 8: 8, 3:3)
+ | SetBit (4)
+ | SetBitField (vTotal, 9: 9, 5:5)
+ | SetBitField (vDisplay, 9: 9, 6:6)
+ | SetBitField (vStart, 9: 9, 7:7);
+ newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5)
+ | SetBit (6);
+ newmode.crtc[0x10] = Set8Bits (vStart);
+ newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
+ | SetBit (5);
+ newmode.crtc[0x12] = Set8Bits (vDisplay);
+ newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8);
+ newmode.crtc[0x15] = Set8Bits (vBlankStart);
+ newmode.crtc[0x16] = Set8Bits (vBlankEnd);
+
+ newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
+ | SetBitField(vBlankStart,10:10,3:3)
+ | SetBitField(vStart,10:10,2:2)
+ | SetBitField(vDisplay,10:10,1:1)
+ | SetBitField(vTotal,10:10,0:0);
+ newmode.ext.horiz = SetBitField(hTotal,8:8,0:0)
+ | SetBitField(hDisplay,8:8,1:1)
+ | SetBitField(hBlankStart,8:8,2:2)
+ | SetBitField(hStart,8:8,3:3);
+ newmode.ext.extra = SetBitField(vTotal,11:11,0:0)
+ | SetBitField(vDisplay,11:11,2:2)
+ | SetBitField(vStart,11:11,4:4)
+ | SetBitField(vBlankStart,11:11,6:6);
+
+ if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ int tmp = (hTotal >> 1) & ~1;
+ newmode.ext.interlace = Set8Bits(tmp);
+ newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4);
+ } else
+ newmode.ext.interlace = 0xff; /* interlace off */
+
+ if (par->riva.Architecture >= NV_ARCH_10)
+ par->riva.CURSOR = (U032 __iomem *)(info->screen_base + par->riva.CursorStart);
+
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ newmode.misc_output &= ~0x40;
+ else
+ newmode.misc_output |= 0x40;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ newmode.misc_output &= ~0x80;
+ else
+ newmode.misc_output |= 0x80;
+
+ rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width,
+ hDisplaySize, height, dotClock);
+ if (rc)
+ goto out;
+
+ newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) &
+ 0xfff000ff;
+ if (par->FlatPanel == 1) {
+ newmode.ext.pixel |= (1 << 7);
+ newmode.ext.scale |= (1 << 8);
+ }
+ if (par->SecondCRTC) {
+ newmode.ext.head = NV_RD32(par->riva.PCRTC0, 0x00000860) &
+ ~0x00001000;
+ newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) |
+ 0x00001000;
+ newmode.ext.crtcOwner = 3;
+ newmode.ext.pllsel |= 0x20000800;
+ newmode.ext.vpll2 = newmode.ext.vpll;
+ } else if (par->riva.twoHeads) {
+ newmode.ext.head = NV_RD32(par->riva.PCRTC0, 0x00000860) |
+ 0x00001000;
+ newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) &
+ ~0x00001000;
+ newmode.ext.crtcOwner = 0;
+ newmode.ext.vpll2 = NV_RD32(par->riva.PRAMDAC0, 0x00000520);
+ }
+ if (par->FlatPanel == 1) {
+ newmode.ext.pixel |= (1 << 7);
+ newmode.ext.scale |= (1 << 8);
+ }
+ newmode.ext.cursorConfig = 0x02000100;
+ par->current_state = newmode;
+ riva_load_state(par, &par->current_state);
+ par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
+
+out:
+ rivafb_blank(FB_BLANK_UNBLANK, info);
+ NVTRACE_LEAVE();
+
+ return rc;
+}
+
+static void riva_update_var(struct fb_var_screeninfo *var,
+ const struct fb_videomode *modedb)
+{
+ NVTRACE_ENTER();
+ var->xres = var->xres_virtual = modedb->xres;
+ var->yres = modedb->yres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+ var->xoffset = var->yoffset = 0;
+ var->pixclock = modedb->pixclock;
+ var->left_margin = modedb->left_margin;
+ var->right_margin = modedb->right_margin;
+ var->upper_margin = modedb->upper_margin;
+ var->lower_margin = modedb->lower_margin;
+ var->hsync_len = modedb->hsync_len;
+ var->vsync_len = modedb->vsync_len;
+ var->sync = modedb->sync;
+ var->vmode = modedb->vmode;
+ NVTRACE_LEAVE();
+}
+
+/**
+ * rivafb_do_maximize -
+ * @info: pointer to fb_info object containing info for current riva board
+ * @var:
+ * @nom:
+ * @den:
+ *
+ * DESCRIPTION:
+ * .
+ *
+ * RETURNS:
+ * -EINVAL on failure, 0 on success
+ *
+ *
+ * CALLED FROM:
+ * rivafb_check_var()
+ */
+static int rivafb_do_maximize(struct fb_info *info,
+ struct fb_var_screeninfo *var,
+ int nom, int den)
+{
+ static struct {
+ int xres, yres;
+ } modes[] = {
+ {1600, 1280},
+ {1280, 1024},
+ {1024, 768},
+ {800, 600},
+ {640, 480},
+ {-1, -1}
+ };
+ int i;
+
+ NVTRACE_ENTER();
+ /* use highest possible virtual resolution */
+ if (var->xres_virtual == -1 && var->yres_virtual == -1) {
+ printk(KERN_WARNING PFX
+ "using maximum available virtual resolution\n");
+ for (i = 0; modes[i].xres != -1; i++) {
+ if (modes[i].xres * nom / den * modes[i].yres <
+ info->fix.smem_len)
+ break;
+ }
+ if (modes[i].xres == -1) {
+ printk(KERN_ERR PFX
+ "could not find a virtual resolution that fits into video memory!!\n");
+ NVTRACE("EXIT - EINVAL error\n");
+ return -EINVAL;
+ }
+ var->xres_virtual = modes[i].xres;
+ var->yres_virtual = modes[i].yres;
+
+ printk(KERN_INFO PFX
+ "virtual resolution set to maximum of %dx%d\n",
+ var->xres_virtual, var->yres_virtual);
+ } else if (var->xres_virtual == -1) {
+ var->xres_virtual = (info->fix.smem_len * den /
+ (nom * var->yres_virtual)) & ~15;
+ printk(KERN_WARNING PFX
+ "setting virtual X resolution to %d\n", var->xres_virtual);
+ } else if (var->yres_virtual == -1) {
+ var->xres_virtual = (var->xres_virtual + 15) & ~15;
+ var->yres_virtual = info->fix.smem_len * den /
+ (nom * var->xres_virtual);
+ printk(KERN_WARNING PFX
+ "setting virtual Y resolution to %d\n", var->yres_virtual);
+ } else {
+ var->xres_virtual = (var->xres_virtual + 15) & ~15;
+ if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
+ printk(KERN_ERR PFX
+ "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ NVTRACE("EXIT - EINVAL error\n");
+ return -EINVAL;
+ }
+ }
+
+ if (var->xres_virtual * nom / den >= 8192) {
+ printk(KERN_WARNING PFX
+ "virtual X resolution (%d) is too high, lowering to %d\n",
+ var->xres_virtual, 8192 * den / nom - 16);
+ var->xres_virtual = 8192 * den / nom - 16;
+ }
+
+ if (var->xres_virtual < var->xres) {
+ printk(KERN_ERR PFX
+ "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
+ return -EINVAL;
+ }
+
+ if (var->yres_virtual < var->yres) {
+ printk(KERN_ERR PFX
+ "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
+ return -EINVAL;
+ }
+ if (var->yres_virtual > 0x7fff/nom)
+ var->yres_virtual = 0x7fff/nom;
+ if (var->xres_virtual > 0x7fff/nom)
+ var->xres_virtual = 0x7fff/nom;
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static void
+riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
+{
+ RIVA_FIFO_FREE(par->riva, Patt, 4);
+ NV_WR32(&par->riva.Patt->Color0, 0, clr0);
+ NV_WR32(&par->riva.Patt->Color1, 0, clr1);
+ NV_WR32(par->riva.Patt->Monochrome, 0, pat0);
+ NV_WR32(par->riva.Patt->Monochrome, 4, pat1);
+}
+
+/* acceleration routines */
+static inline void wait_for_idle(struct riva_par *par)
+{
+ while (par->riva.Busy(&par->riva));
+}
+
+/*
+ * Set ROP. Translate X rop into ROP3. Internal routine.
+ */
+static void
+riva_set_rop_solid(struct riva_par *par, int rop)
+{
+ riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+ RIVA_FIFO_FREE(par->riva, Rop, 1);
+ NV_WR32(&par->riva.Rop->Rop3, 0, rop);
+
+}
+
+static void riva_setup_accel(struct fb_info *info)
+{
+ struct riva_par *par = info->par;
+
+ RIVA_FIFO_FREE(par->riva, Clip, 2);
+ NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
+ NV_WR32(&par->riva.Clip->WidthHeight, 0,
+ (info->var.xres_virtual & 0xffff) |
+ (info->var.yres_virtual << 16));
+ riva_set_rop_solid(par, 0xcc);
+ wait_for_idle(par);
+}
+
+/**
+ * riva_get_cmap_len - query current color map length
+ * @var: standard kernel fb changeable data
+ *
+ * DESCRIPTION:
+ * Get current color map length.
+ *
+ * RETURNS:
+ * Length of color map
+ *
+ * CALLED FROM:
+ * rivafb_setcolreg()
+ */
+static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+ int rc = 256; /* reasonable default */
+
+ switch (var->green.length) {
+ case 8:
+ rc = 256; /* 256 entries (2^8), 8 bpp and RGB8888 */
+ break;
+ case 5:
+ rc = 32; /* 32 entries (2^5), 16 bpp, RGB555 */
+ break;
+ case 6:
+ rc = 64; /* 64 entries (2^6), 16 bpp, RGB565 */
+ break;
+ default:
+ /* should not occur */
+ break;
+ }
+ return rc;
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer operations
+ *
+ * ------------------------------------------------------------------------- */
+
+static int rivafb_open(struct fb_info *info, int user)
+{
+ struct riva_par *par = info->par;
+
+ NVTRACE_ENTER();
+ mutex_lock(&par->open_lock);
+ if (!par->ref_count) {
+#ifdef CONFIG_X86
+ memset(&par->state, 0, sizeof(struct vgastate));
+ par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
+ /* save the DAC for Riva128 */
+ if (par->riva.Architecture == NV_ARCH_03)
+ par->state.flags |= VGA_SAVE_CMAP;
+ save_vga(&par->state);
+#endif
+ /* vgaHWunlock() + riva unlock (0x7F) */
+ CRTCout(par, 0x11, 0xFF);
+ par->riva.LockUnlock(&par->riva, 0);
+
+ riva_save_state(par, &par->initial_state);
+ }
+ par->ref_count++;
+ mutex_unlock(&par->open_lock);
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static int rivafb_release(struct fb_info *info, int user)
+{
+ struct riva_par *par = info->par;
+
+ NVTRACE_ENTER();
+ mutex_lock(&par->open_lock);
+ if (!par->ref_count) {
+ mutex_unlock(&par->open_lock);
+ return -EINVAL;
+ }
+ if (par->ref_count == 1) {
+ par->riva.LockUnlock(&par->riva, 0);
+ par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
+ riva_load_state(par, &par->initial_state);
+#ifdef CONFIG_X86
+ restore_vga(&par->state);
+#endif
+ par->riva.LockUnlock(&par->riva, 1);
+ }
+ par->ref_count--;
+ mutex_unlock(&par->open_lock);
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ const struct fb_videomode *mode;
+ struct riva_par *par = info->par;
+ int nom, den; /* translating from pixels->bytes */
+ int mode_valid = 0;
+
+ NVTRACE_ENTER();
+ switch (var->bits_per_pixel) {
+ case 1 ... 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->bits_per_pixel = 8;
+ nom = den = 1;
+ break;
+ case 9 ... 15:
+ var->green.length = 5;
+ /* fall through */
+ case 16:
+ var->bits_per_pixel = 16;
+ /* The Riva128 supports RGB555 only */
+ if (par->riva.Architecture == NV_ARCH_03)
+ var->green.length = 5;
+ if (var->green.length == 5) {
+ /* 0rrrrrgg gggbbbbb */
+ var->red.offset = 10;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 5;
+ var->blue.length = 5;
+ } else {
+ /* rrrrrggg gggbbbbb */
+ var->red.offset = 11;
+ var->green.offset = 5;
+ var->blue.offset = 0;
+ var->red.length = 5;
+ var->green.length = 6;
+ var->blue.length = 5;
+ }
+ nom = 2;
+ den = 1;
+ break;
+ case 17 ... 32:
+ var->red.length = var->green.length = var->blue.length = 8;
+ var->bits_per_pixel = 32;
+ var->red.offset = 16;
+ var->green.offset = 8;
+ var->blue.offset = 0;
+ nom = 4;
+ den = 1;
+ break;
+ default:
+ printk(KERN_ERR PFX
+ "mode %dx%dx%d rejected...color depth not supported.\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ NVTRACE("EXIT, returning -EINVAL\n");
+ return -EINVAL;
+ }
+
+ if (!strictmode) {
+ if (!info->monspecs.vfmax || !info->monspecs.hfmax ||
+ !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) {
+ mode = fb_find_best_mode(var, &info->modelist);
+ if (mode) {
+ riva_update_var(var, mode);
+ mode_valid = 1;
+ }
+ }
+
+ if (!mode_valid && info->monspecs.modedb_len)
+ return -EINVAL;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual <= var->yres)
+ var->yres_virtual = -1;
+ if (rivafb_do_maximize(info, var, nom, den) < 0)
+ return -EINVAL;
+
+ /* truncate xoffset and yoffset to maximum if too high */
+ if (var->xoffset > var->xres_virtual - var->xres)
+ var->xoffset = var->xres_virtual - var->xres - 1;
+
+ if (var->yoffset > var->yres_virtual - var->yres)
+ var->yoffset = var->yres_virtual - var->yres - 1;
+
+ var->red.msb_right =
+ var->green.msb_right =
+ var->blue.msb_right =
+ var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static int rivafb_set_par(struct fb_info *info)
+{
+ struct riva_par *par = info->par;
+ int rc = 0;
+
+ NVTRACE_ENTER();
+ /* vgaHWunlock() + riva unlock (0x7F) */
+ CRTCout(par, 0x11, 0xFF);
+ par->riva.LockUnlock(&par->riva, 0);
+ rc = riva_load_video_mode(info);
+ if (rc)
+ goto out;
+ if(!(info->flags & FBINFO_HWACCEL_DISABLED))
+ riva_setup_accel(info);
+
+ par->cursor_reset = 1;
+ 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->flags & FBINFO_HWACCEL_DISABLED)
+ info->pixmap.scan_align = 1;
+ else
+ info->pixmap.scan_align = 4;
+
+out:
+ NVTRACE_LEAVE();
+ return rc;
+}
+
+/**
+ * rivafb_pan_display
+ * @var: standard kernel fb changeable data
+ * @con: TODO
+ * @info: pointer to fb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `xoffset' and `yoffset' fields of the `var' structure.
+ * If the values don't fit, return -EINVAL.
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int rivafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct riva_par *par = info->par;
+ unsigned int base;
+
+ NVTRACE_ENTER();
+ base = var->yoffset * info->fix.line_length + var->xoffset;
+ par->riva.SetStartAddress(&par->riva, base);
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static int rivafb_blank(int blank, struct fb_info *info)
+{
+ struct riva_par *par= info->par;
+ unsigned char tmp, vesa;
+
+ tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
+ vesa = CRTCin(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;
+ }
+
+ SEQout(par, 0x01, tmp);
+ CRTCout(par, 0x1a, vesa);
+
+ NVTRACE_LEAVE();
+
+ return 0;
+}
+
+/**
+ * rivafb_setcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to fb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * fbcmap.c:fb_set_cmap()
+ */
+static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct riva_par *par = info->par;
+ RIVA_HW_INST *chip = &par->riva;
+ int i;
+
+ if (regno >= riva_get_cmap_len(&info->var))
+ 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);
+ /*
+ * The Riva128 2D engine requires color information in
+ * TrueColor format even if framebuffer is in DirectColor
+ */
+ if (par->riva.Architecture == NV_ARCH_03) {
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ par->palette[regno] = ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
+ break;
+ case 32:
+ par->palette[regno] = ((red & 0xff00) << 8) |
+ ((green & 0xff00)) |
+ ((blue & 0xff00) >> 8);
+ break;
+ }
+ }
+ }
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ /* "transparent" stuff is completely ignored. */
+ riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
+ break;
+ case 16:
+ if (info->var.green.length == 5) {
+ for (i = 0; i < 8; i++) {
+ riva_wclut(chip, regno*8+i, red >> 8,
+ green >> 8, blue >> 8);
+ }
+ } else {
+ u8 r, g, b;
+
+ if (regno < 32) {
+ for (i = 0; i < 8; i++) {
+ riva_wclut(chip, regno*8+i,
+ red >> 8, green >> 8,
+ blue >> 8);
+ }
+ }
+ riva_rclut(chip, regno*4, &r, &g, &b);
+ for (i = 0; i < 4; i++)
+ riva_wclut(chip, regno*4+i, r,
+ green >> 8, b);
+ }
+ break;
+ case 32:
+ riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ return 0;
+}
+
+/**
+ * rivafb_fillrect - hardware accelerated color fill function
+ * @info: pointer to fb_info structure
+ * @rect: pointer to fb_fillrect structure
+ *
+ * DESCRIPTION:
+ * This function fills up a region of framebuffer memory with a solid
+ * color with a choice of two different ROP's, copy or invert.
+ *
+ * CALLED FROM:
+ * framebuffer hook
+ */
+static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+ struct riva_par *par = info->par;
+ u_int color, rop = 0;
+
+ if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
+ cfb_fillrect(info, rect);
+ return;
+ }
+
+ if (info->var.bits_per_pixel == 8)
+ color = rect->color;
+ else {
+ if (par->riva.Architecture != NV_ARCH_03)
+ color = ((u32 *)info->pseudo_palette)[rect->color];
+ else
+ color = par->palette[rect->color];
+ }
+
+ switch (rect->rop) {
+ case ROP_XOR:
+ rop = 0x66;
+ break;
+ case ROP_COPY:
+ default:
+ rop = 0xCC;
+ break;
+ }
+
+ riva_set_rop_solid(par, rop);
+
+ RIVA_FIFO_FREE(par->riva, Bitmap, 1);
+ NV_WR32(&par->riva.Bitmap->Color1A, 0, color);
+
+ RIVA_FIFO_FREE(par->riva, Bitmap, 2);
+ NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].TopLeft, 0,
+ (rect->dx << 16) | rect->dy);
+ mb();
+ NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].WidthHeight, 0,
+ (rect->width << 16) | rect->height);
+ mb();
+ riva_set_rop_solid(par, 0xcc);
+
+}
+
+/**
+ * rivafb_copyarea - hardware accelerated blit function
+ * @info: pointer to fb_info structure
+ * @region: pointer to fb_copyarea structure
+ *
+ * DESCRIPTION:
+ * This copies an area of pixels from one location to another
+ *
+ * CALLED FROM:
+ * framebuffer hook
+ */
+static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+ struct riva_par *par = info->par;
+
+ if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
+ cfb_copyarea(info, region);
+ return;
+ }
+
+ RIVA_FIFO_FREE(par->riva, Blt, 3);
+ NV_WR32(&par->riva.Blt->TopLeftSrc, 0,
+ (region->sy << 16) | region->sx);
+ NV_WR32(&par->riva.Blt->TopLeftDst, 0,
+ (region->dy << 16) | region->dx);
+ mb();
+ NV_WR32(&par->riva.Blt->WidthHeight, 0,
+ (region->height << 16) | region->width);
+ mb();
+}
+
+static inline void convert_bgcolor_16(u32 *col)
+{
+ *col = ((*col & 0x0000F800) << 8)
+ | ((*col & 0x00007E0) << 5)
+ | ((*col & 0x0000001F) << 3)
+ | 0xFF000000;
+ mb();
+}
+
+/**
+ * rivafb_imageblit: hardware accelerated color expand function
+ * @info: pointer to fb_info structure
+ * @image: pointer to fb_image structure
+ *
+ * DESCRIPTION:
+ * If the source is a monochrome bitmap, the function fills up a a region
+ * of framebuffer memory with pixels whose color is determined by the bit
+ * setting of the bitmap, 1 - foreground, 0 - background.
+ *
+ * If the source is not a monochrome bitmap, color expansion is not done.
+ * In this case, it is channeled to a software function.
+ *
+ * CALLED FROM:
+ * framebuffer hook
+ */
+static void rivafb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+ struct riva_par *par = info->par;
+ u32 fgx = 0, bgx = 0, width, tmp;
+ u8 *cdat = (u8 *) image->data;
+ volatile u32 __iomem *d;
+ int i, size;
+
+ if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) {
+ cfb_imageblit(info, image);
+ return;
+ }
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ fgx = image->fg_color;
+ bgx = image->bg_color;
+ break;
+ case 16:
+ case 32:
+ if (par->riva.Architecture != NV_ARCH_03) {
+ fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
+ bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
+ } else {
+ fgx = par->palette[image->fg_color];
+ bgx = par->palette[image->bg_color];
+ }
+ if (info->var.green.length == 6)
+ convert_bgcolor_16(&bgx);
+ break;
+ }
+
+ RIVA_FIFO_FREE(par->riva, Bitmap, 7);
+ NV_WR32(&par->riva.Bitmap->ClipE.TopLeft, 0,
+ (image->dy << 16) | (image->dx & 0xFFFF));
+ NV_WR32(&par->riva.Bitmap->ClipE.BottomRight, 0,
+ (((image->dy + image->height) << 16) |
+ ((image->dx + image->width) & 0xffff)));
+ NV_WR32(&par->riva.Bitmap->Color0E, 0, bgx);
+ NV_WR32(&par->riva.Bitmap->Color1E, 0, fgx);
+ NV_WR32(&par->riva.Bitmap->WidthHeightInE, 0,
+ (image->height << 16) | ((image->width + 31) & ~31));
+ NV_WR32(&par->riva.Bitmap->WidthHeightOutE, 0,
+ (image->height << 16) | ((image->width + 31) & ~31));
+ NV_WR32(&par->riva.Bitmap->PointE, 0,
+ (image->dy << 16) | (image->dx & 0xFFFF));
+
+ d = &par->riva.Bitmap->MonochromeData01E;
+
+ width = (image->width + 31)/32;
+ size = width * image->height;
+ while (size >= 16) {
+ RIVA_FIFO_FREE(par->riva, Bitmap, 16);
+ for (i = 0; i < 16; i++) {
+ tmp = *((u32 *)cdat);
+ cdat = (u8 *)((u32 *)cdat + 1);
+ reverse_order(&tmp);
+ NV_WR32(d, i*4, tmp);
+ }
+ size -= 16;
+ }
+ if (size) {
+ RIVA_FIFO_FREE(par->riva, Bitmap, size);
+ for (i = 0; i < size; i++) {
+ tmp = *((u32 *) cdat);
+ cdat = (u8 *)((u32 *)cdat + 1);
+ reverse_order(&tmp);
+ NV_WR32(d, i*4, tmp);
+ }
+ }
+}
+
+/**
+ * rivafb_cursor - hardware cursor function
+ * @info: pointer to info structure
+ * @cursor: pointer to fbcursor structure
+ *
+ * DESCRIPTION:
+ * A cursor function that supports displaying a cursor image via hardware.
+ * Within the kernel, copy and invert rops are supported. If exported
+ * to user space, only the copy rop will be supported.
+ *
+ * CALLED FROM
+ * framebuffer hook
+ */
+static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct riva_par *par = info->par;
+ u8 data[MAX_CURS * MAX_CURS/8];
+ int i, set = cursor->set;
+ u16 fg, bg;
+
+ if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+ return -ENXIO;
+
+ par->riva.ShowHideCursor(&par->riva, 0);
+
+ if (par->cursor_reset) {
+ set = FB_CUR_SETALL;
+ par->cursor_reset = 0;
+ }
+
+ if (set & FB_CUR_SETSIZE)
+ memset_io(par->riva.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->riva.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_pad_aligned_buffer(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;
+
+ par->riva.LockUnlock(&par->riva, 0);
+
+ rivafb_load_cursor_image(par, data, bg, fg,
+ cursor->image.width,
+ cursor->image.height);
+ kfree(src);
+ }
+ }
+
+ if (cursor->enable)
+ par->riva.ShowHideCursor(&par->riva, 1);
+
+ return 0;
+}
+
+static int rivafb_sync(struct fb_info *info)
+{
+ struct riva_par *par = info->par;
+
+ wait_for_idle(par);
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization helper functions
+ *
+ * ------------------------------------------------------------------------- */
+
+/* kernel interface */
+static struct fb_ops riva_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = rivafb_open,
+ .fb_release = rivafb_release,
+ .fb_check_var = rivafb_check_var,
+ .fb_set_par = rivafb_set_par,
+ .fb_setcolreg = rivafb_setcolreg,
+ .fb_pan_display = rivafb_pan_display,
+ .fb_blank = rivafb_blank,
+ .fb_fillrect = rivafb_fillrect,
+ .fb_copyarea = rivafb_copyarea,
+ .fb_imageblit = rivafb_imageblit,
+ .fb_cursor = rivafb_cursor,
+ .fb_sync = rivafb_sync,
+};
+
+static int riva_set_fbinfo(struct fb_info *info)
+{
+ unsigned int cmap_len;
+ struct riva_par *par = info->par;
+
+ NVTRACE_ENTER();
+ info->flags = FBINFO_DEFAULT
+ | FBINFO_HWACCEL_XPAN
+ | FBINFO_HWACCEL_YPAN
+ | FBINFO_HWACCEL_COPYAREA
+ | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_IMAGEBLIT;
+
+ /* Accel seems to not work properly on NV30 yet...*/
+ if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
+ printk(KERN_DEBUG PFX "disabling acceleration\n");
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ }
+
+ info->var = rivafb_default_var;
+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+ info->pseudo_palette = par->pseudo_palette;
+
+ cmap_len = riva_get_cmap_len(&info->var);
+ fb_alloc_cmap(&info->cmap, cmap_len, 0);
+
+ info->pixmap.size = 8 * 1024;
+ info->pixmap.buf_align = 4;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->var.yres_virtual = -1;
+ NVTRACE_LEAVE();
+ return (rivafb_check_var(&info->var, info));
+}
+
+#ifdef CONFIG_PPC_OF
+static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
+{
+ struct riva_par *par = info->par;
+ struct device_node *dp;
+ const unsigned char *pedid = NULL;
+ const unsigned char *disptype = NULL;
+ static char *propnames[] = {
+ "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+ int i;
+
+ NVTRACE_ENTER();
+ dp = pci_device_to_OF_node(pd);
+ for (; dp != NULL; dp = dp->child) {
+ disptype = of_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 = of_get_property(dp, propnames[i], NULL);
+ if (pedid != NULL) {
+ par->EDID = (unsigned char *)pedid;
+ NVTRACE("LCD found.\n");
+ return 1;
+ }
+ }
+ }
+ NVTRACE_LEAVE();
+ return 0;
+}
+#endif /* CONFIG_PPC_OF */
+
+#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
+static int riva_get_EDID_i2c(struct fb_info *info)
+{
+ struct riva_par *par = info->par;
+ struct fb_var_screeninfo var;
+ int i;
+
+ NVTRACE_ENTER();
+ riva_create_i2c_busses(par);
+ for (i = 0; i < 3; i++) {
+ if (!par->chan[i].par)
+ continue;
+ riva_probe_i2c_connector(par, i, &par->EDID);
+ if (par->EDID && !fb_parse_edid(par->EDID, &var)) {
+ printk(PFX "Found EDID Block from BUS %i\n", i);
+ break;
+ }
+ }
+
+ NVTRACE_LEAVE();
+ return (par->EDID) ? 1 : 0;
+}
+#endif /* CONFIG_FB_RIVA_I2C */
+
+static void riva_update_default_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct fb_monspecs *specs = &info->monspecs;
+ struct fb_videomode modedb;
+
+ NVTRACE_ENTER();
+ /* respect mode options */
+ if (mode_option) {
+ fb_find_mode(var, info, mode_option,
+ specs->modedb, specs->modedb_len,
+ NULL, 8);
+ } else if (specs->modedb != NULL) {
+ /* get first mode in database as fallback */
+ modedb = specs->modedb[0];
+ /* get preferred timing */
+ if (info->monspecs.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;
+ }
+ }
+ }
+ var->bits_per_pixel = 8;
+ riva_update_var(var, &modedb);
+ }
+ NVTRACE_LEAVE();
+}
+
+
+static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
+{
+ NVTRACE_ENTER();
+#ifdef CONFIG_PPC_OF
+ if (!riva_get_EDID_OF(info, pdev))
+ printk(PFX "could not retrieve EDID from OF\n");
+#elif defined(CONFIG_FB_RIVA_I2C)
+ if (!riva_get_EDID_i2c(info))
+ printk(PFX "could not retrieve EDID from DDC/I2C\n");
+#endif
+ NVTRACE_LEAVE();
+}
+
+
+static void riva_get_edidinfo(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &rivafb_default_var;
+ struct riva_par *par = info->par;
+
+ fb_edid_to_monspecs(par->EDID, &info->monspecs);
+ fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
+ &info->modelist);
+ riva_update_default_var(var, info);
+
+ /* if user specified flatpanel, we respect that */
+ if (info->monspecs.input & FB_DISP_DDI)
+ par->FlatPanel = 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * PCI bus
+ *
+ * ------------------------------------------------------------------------- */
+
+static u32 riva_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 0x0020: /* TNT, TNT2 */
+ arch = NV_ARCH_04;
+ break;
+ case 0x0010: /* Riva128 */
+ arch = NV_ARCH_03;
+ break;
+ default: /* unknown architecture */
+ break;
+ }
+ return arch;
+}
+
+static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
+{
+ struct riva_par *default_par;
+ struct fb_info *info;
+ int ret;
+
+ NVTRACE_ENTER();
+ assert(pd != NULL);
+
+ info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev);
+ if (!info) {
+ printk (KERN_ERR PFX "could not allocate memory\n");
+ ret = -ENOMEM;
+ goto err_ret;
+ }
+ default_par = info->par;
+ default_par->pdev = pd;
+
+ info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
+ if (info->pixmap.addr == NULL) {
+ ret = -ENOMEM;
+ goto err_framebuffer_release;
+ }
+
+ ret = pci_enable_device(pd);
+ if (ret < 0) {
+ printk(KERN_ERR PFX "cannot enable PCI device\n");
+ goto err_free_pixmap;
+ }
+
+ ret = pci_request_regions(pd, "rivafb");
+ if (ret < 0) {
+ printk(KERN_ERR PFX "cannot request PCI regions\n");
+ goto err_disable_device;
+ }
+
+ mutex_init(&default_par->open_lock);
+ default_par->riva.Architecture = riva_get_arch(pd);
+
+ default_par->Chipset = (pd->vendor << 16) | pd->device;
+ printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
+
+ if(default_par->riva.Architecture == 0) {
+ printk(KERN_ERR PFX "unknown NV_ARCH\n");
+ ret=-ENODEV;
+ goto err_release_region;
+ }
+ if(default_par->riva.Architecture == NV_ARCH_10 ||
+ default_par->riva.Architecture == NV_ARCH_20 ||
+ default_par->riva.Architecture == NV_ARCH_30) {
+ sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+ } else {
+ sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture);
+ }
+
+ default_par->FlatPanel = flatpanel;
+ if (flatpanel == 1)
+ printk(KERN_INFO PFX "flatpanel support enabled\n");
+ default_par->forceCRTC = forceCRTC;
+
+ rivafb_fix.mmio_len = pci_resource_len(pd, 0);
+ rivafb_fix.smem_len = pci_resource_len(pd, 1);
+
+ {
+ /* enable IO and mem if not already done */
+ unsigned short cmd;
+
+ pci_read_config_word(pd, PCI_COMMAND, &cmd);
+ cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ pci_write_config_word(pd, PCI_COMMAND, cmd);
+ }
+
+ rivafb_fix.mmio_start = pci_resource_start(pd, 0);
+ rivafb_fix.smem_start = pci_resource_start(pd, 1);
+
+ default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
+ rivafb_fix.mmio_len);
+ if (!default_par->ctrl_base) {
+ printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+ ret = -EIO;
+ goto err_release_region;
+ }
+
+ switch (default_par->riva.Architecture) {
+ case NV_ARCH_03:
+ /* Riva128's PRAMIN is in the "framebuffer" space
+ * Since these cards were never made with more than 8 megabytes
+ * we can safely allocate this separately.
+ */
+ default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
+ if (!default_par->riva.PRAMIN) {
+ printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
+ ret = -EIO;
+ goto err_iounmap_ctrl_base;
+ }
+ break;
+ case NV_ARCH_04:
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ default_par->riva.PCRTC0 =
+ (u32 __iomem *)(default_par->ctrl_base + 0x00600000);
+ default_par->riva.PRAMIN =
+ (u32 __iomem *)(default_par->ctrl_base + 0x00710000);
+ break;
+ }
+ riva_common_setup(default_par);
+
+ if (default_par->riva.Architecture == NV_ARCH_03) {
+ default_par->riva.PCRTC = default_par->riva.PCRTC0
+ = default_par->riva.PGRAPH;
+ }
+
+ rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
+ default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
+ info->screen_base = ioremap(rivafb_fix.smem_start,
+ rivafb_fix.smem_len);
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "cannot ioremap FB base\n");
+ ret = -EIO;
+ goto err_iounmap_pramin;
+ }
+
+#ifdef CONFIG_MTRR
+ if (!nomtrr) {
+ default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
+ rivafb_fix.smem_len,
+ MTRR_TYPE_WRCOMB, 1);
+ if (default_par->mtrr.vram < 0) {
+ printk(KERN_ERR PFX "unable to setup MTRR\n");
+ } else {
+ default_par->mtrr.vram_valid = 1;
+ /* let there be speed */
+ printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
+ }
+ }
+#endif /* CONFIG_MTRR */
+
+ info->fbops = &riva_fb_ops;
+ info->fix = rivafb_fix;
+ riva_get_EDID(info, pd);
+ riva_get_edidinfo(info);
+
+ ret=riva_set_fbinfo(info);
+ if (ret < 0) {
+ printk(KERN_ERR PFX "error setting initial video mode\n");
+ goto err_iounmap_screen_base;
+ }
+
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
+ pci_set_drvdata(pd, info);
+
+ if (backlight)
+ riva_bl_init(info->par);
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ printk(KERN_ERR PFX
+ "error registering riva framebuffer\n");
+ goto err_iounmap_screen_base;
+ }
+
+ printk(KERN_INFO PFX
+ "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
+ info->fix.id,
+ RIVAFB_VERSION,
+ info->fix.smem_len / (1024 * 1024),
+ info->fix.smem_start);
+
+ NVTRACE_LEAVE();
+ return 0;
+
+err_iounmap_screen_base:
+#ifdef CONFIG_FB_RIVA_I2C
+ riva_delete_i2c_busses(info->par);
+#endif
+ iounmap(info->screen_base);
+err_iounmap_pramin:
+ if (default_par->riva.Architecture == NV_ARCH_03)
+ iounmap(default_par->riva.PRAMIN);
+err_iounmap_ctrl_base:
+ iounmap(default_par->ctrl_base);
+err_release_region:
+ pci_release_regions(pd);
+err_disable_device:
+err_free_pixmap:
+ kfree(info->pixmap.addr);
+err_framebuffer_release:
+ framebuffer_release(info);
+err_ret:
+ return ret;
+}
+
+static void rivafb_remove(struct pci_dev *pd)
+{
+ struct fb_info *info = pci_get_drvdata(pd);
+ struct riva_par *par = info->par;
+
+ NVTRACE_ENTER();
+
+#ifdef CONFIG_FB_RIVA_I2C
+ riva_delete_i2c_busses(par);
+ kfree(par->EDID);
+#endif
+
+ unregister_framebuffer(info);
+
+ riva_bl_exit(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(par->ctrl_base);
+ iounmap(info->screen_base);
+ if (par->riva.Architecture == NV_ARCH_03)
+ iounmap(par->riva.PRAMIN);
+ pci_release_regions(pd);
+ kfree(info->pixmap.addr);
+ framebuffer_release(info);
+ NVTRACE_LEAVE();
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+static int rivafb_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, "backlight:", 10)) {
+ backlight = simple_strtoul(this_opt+10, NULL, 0);
+#ifdef CONFIG_MTRR
+ } else if (!strncmp(this_opt, "nomtrr", 6)) {
+ nomtrr = 1;
+#endif
+ } else if (!strncmp(this_opt, "strictmode", 10)) {
+ strictmode = 1;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ } else
+ mode_option = this_opt;
+ }
+ NVTRACE_LEAVE();
+ return 0;
+}
+#endif /* !MODULE */
+
+static struct pci_driver rivafb_driver = {
+ .name = "rivafb",
+ .id_table = rivafb_pci_tbl,
+ .probe = rivafb_probe,
+ .remove = rivafb_remove,
+};
+
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+static int rivafb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("rivafb", &option))
+ return -ENODEV;
+ rivafb_setup(option);
+#endif
+ return pci_register_driver(&rivafb_driver);
+}
+
+
+module_init(rivafb_init);
+
+static void __exit rivafb_exit(void)
+{
+ pci_unregister_driver(&rivafb_driver);
+}
+
+module_exit(rivafb_exit);
+
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+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(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_param(strictmode, bool, 0);
+MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
+
+MODULE_AUTHOR("Ani Joshi, maintainer");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/riva/nv_driver.c b/drivers/video/fbdev/riva/nv_driver.c
new file mode 100644
index 000000000000..f3694cf17e58
--- /dev/null
+++ b/drivers/video/fbdev/riva/nv_driver.c
@@ -0,0 +1,422 @@
+/* $XConsortium: nv_driver.c /main/3 1996/10/28 05:13:37 kaleb $ */
+/*
+ * Copyright 1996-1997 David J. McKay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
+ */
+
+/* Hacked together from mga driver and 3.3.4 NVIDIA driver by Jarno Paananen
+ <jpaana@s2.org> */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_setup.c,v 1.18 2002/08/0
+5 20:47:06 mvojkovi Exp $ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include "nv_type.h"
+#include "rivafb.h"
+#include "nvreg.h"
+
+#define PFX "rivafb: "
+
+static inline unsigned char MISCin(struct riva_par *par)
+{
+ return (VGA_RD08(par->riva.PVIO, 0x3cc));
+}
+
+static Bool
+riva_is_connected(struct riva_par *par, Bool second)
+{
+ volatile U032 __iomem *PRAMDAC = par->riva.PRAMDAC0;
+ U032 reg52C, reg608;
+ Bool present;
+
+ if(second) PRAMDAC += 0x800;
+
+ reg52C = NV_RD32(PRAMDAC, 0x052C);
+ reg608 = NV_RD32(PRAMDAC, 0x0608);
+
+ NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
+
+ NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
+ mdelay(1);
+ NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
+
+ NV_WR32(par->riva.PRAMDAC0, 0x0610, 0x94050140);
+ NV_WR32(par->riva.PRAMDAC0, 0x0608, 0x00001000);
+
+ mdelay(1);
+
+ present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? TRUE : FALSE;
+
+ NV_WR32(par->riva.PRAMDAC0, 0x0608,
+ NV_RD32(par->riva.PRAMDAC0, 0x0608) & 0x0000EFFF);
+
+ NV_WR32(PRAMDAC, 0x052C, reg52C);
+ NV_WR32(PRAMDAC, 0x0608, reg608);
+
+ return present;
+}
+
+static void
+riva_override_CRTC(struct riva_par *par)
+{
+ printk(KERN_INFO PFX
+ "Detected CRTC controller %i being used\n",
+ par->SecondCRTC ? 1 : 0);
+
+ if(par->forceCRTC != -1) {
+ printk(KERN_INFO PFX
+ "Forcing usage of CRTC %i\n", par->forceCRTC);
+ par->SecondCRTC = par->forceCRTC;
+ }
+}
+
+static void
+riva_is_second(struct riva_par *par)
+{
+ if (par->FlatPanel == 1) {
+ switch(par->Chipset & 0xffff) {
+ case 0x0174:
+ case 0x0175:
+ case 0x0176:
+ case 0x0177:
+ case 0x0179:
+ case 0x017C:
+ case 0x017D:
+ case 0x0186:
+ case 0x0187:
+ /* this might not be a good default for the chips below */
+ 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:
+ par->SecondCRTC = TRUE;
+ break;
+ default:
+ par->SecondCRTC = FALSE;
+ break;
+ }
+ } else {
+ if(riva_is_connected(par, 0)) {
+
+ if (NV_RD32(par->riva.PRAMDAC0, 0x0000052C) & 0x100)
+ par->SecondCRTC = TRUE;
+ else
+ par->SecondCRTC = FALSE;
+ } else
+ if (riva_is_connected(par, 1)) {
+ if(NV_RD32(par->riva.PRAMDAC0, 0x0000252C) & 0x100)
+ par->SecondCRTC = TRUE;
+ else
+ par->SecondCRTC = FALSE;
+ } else /* default */
+ par->SecondCRTC = FALSE;
+ }
+ riva_override_CRTC(par);
+}
+
+unsigned long riva_get_memlen(struct riva_par *par)
+{
+ RIVA_HW_INST *chip = &par->riva;
+ unsigned long memlen = 0;
+ unsigned int chipset = par->Chipset;
+ struct pci_dev* dev;
+ u32 amt;
+
+ switch (chip->Architecture) {
+ case NV_ARCH_03:
+ if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) {
+ if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
+ && ((NV_RD32(chip->PMC, 0x00000000)&0x0F)>=0x02)) {
+ /*
+ * SDRAM 128 ZX.
+ */
+ switch (NV_RD32(chip->PFB,0x00000000) & 0x03) {
+ case 2:
+ memlen = 1024 * 4;
+ break;
+ case 1:
+ memlen = 1024 * 2;
+ break;
+ default:
+ memlen = 1024 * 8;
+ break;
+ }
+ } else {
+ memlen = 1024 * 8;
+ }
+ } else {
+ /*
+ * SGRAM 128.
+ */
+ switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) {
+ case 0:
+ memlen = 1024 * 8;
+ break;
+ case 2:
+ memlen = 1024 * 4;
+ break;
+ default:
+ memlen = 1024 * 2;
+ break;
+ }
+ }
+ break;
+ case NV_ARCH_04:
+ if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100) {
+ memlen = ((NV_RD32(chip->PFB, 0x00000000)>>12)&0x0F) *
+ 1024 * 2 + 1024 * 2;
+ } else {
+ switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003) {
+ case 0:
+ memlen = 1024 * 32;
+ break;
+ case 1:
+ memlen = 1024 * 4;
+ break;
+ case 2:
+ memlen = 1024 * 8;
+ break;
+ case 3:
+ default:
+ memlen = 1024 * 16;
+ break;
+ }
+ }
+ break;
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ if(chipset == NV_CHIP_IGEFORCE2) {
+
+ dev = pci_get_bus_and_slot(0, 1);
+ pci_read_config_dword(dev, 0x7C, &amt);
+ pci_dev_put(dev);
+ memlen = (((amt >> 6) & 31) + 1) * 1024;
+ } else if (chipset == NV_CHIP_0x01F0) {
+ dev = pci_get_bus_and_slot(0, 1);
+ pci_read_config_dword(dev, 0x84, &amt);
+ pci_dev_put(dev);
+ memlen = (((amt >> 4) & 127) + 1) * 1024;
+ } else {
+ switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) &
+ 0x000000FF){
+ case 0x02:
+ memlen = 1024 * 2;
+ break;
+ case 0x04:
+ memlen = 1024 * 4;
+ break;
+ case 0x08:
+ memlen = 1024 * 8;
+ break;
+ case 0x10:
+ memlen = 1024 * 16;
+ break;
+ case 0x20:
+ memlen = 1024 * 32;
+ break;
+ case 0x40:
+ memlen = 1024 * 64;
+ break;
+ case 0x80:
+ memlen = 1024 * 128;
+ break;
+ default:
+ memlen = 1024 * 16;
+ break;
+ }
+ }
+ break;
+ }
+ return memlen;
+}
+
+unsigned long riva_get_maxdclk(struct riva_par *par)
+{
+ RIVA_HW_INST *chip = &par->riva;
+ unsigned long dclk = 0;
+
+ switch (chip->Architecture) {
+ case NV_ARCH_03:
+ if (NV_RD32(chip->PFB, 0x00000000) & 0x00000020) {
+ if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
+ && ((NV_RD32(chip->PMC,0x00000000)&0x0F) >= 0x02)) {
+ /*
+ * SDRAM 128 ZX.
+ */
+ dclk = 800000;
+ } else {
+ dclk = 1000000;
+ }
+ } else {
+ /*
+ * SGRAM 128.
+ */
+ dclk = 1000000;
+ }
+ break;
+ case NV_ARCH_04:
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003) {
+ case 3:
+ dclk = 800000;
+ break;
+ default:
+ dclk = 1000000;
+ break;
+ }
+ break;
+ }
+ return dclk;
+}
+
+void
+riva_common_setup(struct riva_par *par)
+{
+ par->riva.EnableIRQ = 0;
+ par->riva.PRAMDAC0 =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00680000);
+ par->riva.PFB =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00100000);
+ par->riva.PFIFO =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00002000);
+ par->riva.PGRAPH =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00400000);
+ par->riva.PEXTDEV =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00101000);
+ par->riva.PTIMER =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00009000);
+ par->riva.PMC =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00000000);
+ par->riva.FIFO =
+ (volatile U032 __iomem *)(par->ctrl_base + 0x00800000);
+ par->riva.PCIO0 = par->ctrl_base + 0x00601000;
+ par->riva.PDIO0 = par->ctrl_base + 0x00681000;
+ par->riva.PVIO = par->ctrl_base + 0x000C0000;
+
+ par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0;
+
+ if (par->FlatPanel == -1) {
+ switch (par->Chipset & 0xffff) {
+ case 0x0112: /* known laptop chips */
+ case 0x0174:
+ case 0x0175:
+ case 0x0176:
+ case 0x0177:
+ case 0x0179:
+ case 0x017C:
+ case 0x017D:
+ case 0x0186:
+ case 0x0187:
+ 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:
+ printk(KERN_INFO PFX
+ "On a laptop. Assuming Digital Flat Panel\n");
+ par->FlatPanel = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (par->Chipset & 0x0ff0) {
+ case 0x0110:
+ if (par->Chipset == NV_CHIP_GEFORCE2_GO)
+ par->SecondCRTC = TRUE;
+#if defined(__powerpc__)
+ if (par->FlatPanel == 1)
+ par->SecondCRTC = TRUE;
+#endif
+ riva_override_CRTC(par);
+ break;
+ case 0x0170:
+ case 0x0180:
+ case 0x01F0:
+ case 0x0250:
+ case 0x0280:
+ case 0x0300:
+ case 0x0310:
+ case 0x0320:
+ case 0x0330:
+ case 0x0340:
+ riva_is_second(par);
+ break;
+ default:
+ break;
+ }
+
+ if (par->SecondCRTC) {
+ par->riva.PCIO = par->riva.PCIO0 + 0x2000;
+ par->riva.PCRTC = par->riva.PCRTC0 + 0x800;
+ par->riva.PRAMDAC = par->riva.PRAMDAC0 + 0x800;
+ par->riva.PDIO = par->riva.PDIO0 + 0x2000;
+ } else {
+ par->riva.PCIO = par->riva.PCIO0;
+ par->riva.PCRTC = par->riva.PCRTC0;
+ par->riva.PRAMDAC = par->riva.PRAMDAC0;
+ par->riva.PDIO = par->riva.PDIO0;
+ }
+
+ if (par->FlatPanel == -1) {
+ /* Fix me, need x86 DDC code */
+ par->FlatPanel = 0;
+ }
+ par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE;
+
+ RivaGetConfig(&par->riva, par->Chipset);
+}
+
diff --git a/drivers/video/fbdev/riva/nv_type.h b/drivers/video/fbdev/riva/nv_type.h
new file mode 100644
index 000000000000..a69480c9a67c
--- /dev/null
+++ b/drivers/video/fbdev/riva/nv_type.h
@@ -0,0 +1,58 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_type.h,v 1.35 2002/08/05 20:47:06 mvojkovi Exp $ */
+
+#ifndef __NV_STRUCT_H__
+#define __NV_STRUCT_H__
+
+#define NV_CHIP_RIVA_128 ((PCI_VENDOR_ID_NVIDIA_SGS << 16)| PCI_DEVICE_ID_NVIDIA_RIVA128)
+#define NV_CHIP_TNT ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT)
+#define NV_CHIP_TNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_TNT2)
+#define NV_CHIP_UTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UTNT2)
+#define NV_CHIP_VTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_VTNT2)
+#define NV_CHIP_UVTNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_UVTNT2)
+#define NV_CHIP_ITNT2 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_ITNT2)
+#define NV_CHIP_GEFORCE_256 ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_256)
+#define NV_CHIP_GEFORCE_DDR ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR)
+#define NV_CHIP_QUADRO ((PCI_VENDOR_ID_NVIDIA << 16)| PCI_DEVICE_ID_NVIDIA_QUADRO)
+#define NV_CHIP_GEFORCE2_MX ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX)
+#define NV_CHIP_GEFORCE2_MX_100 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX_100)
+#define NV_CHIP_QUADRO2_MXR ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR)
+#define NV_CHIP_GEFORCE2_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO)
+#define NV_CHIP_GEFORCE2_GTS ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS)
+#define NV_CHIP_GEFORCE2_TI ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_TI)
+#define NV_CHIP_GEFORCE2_ULTRA ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA)
+#define NV_CHIP_QUADRO2_PRO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO)
+#define NV_CHIP_GEFORCE4_MX_460 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460)
+#define NV_CHIP_GEFORCE4_MX_440 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440)
+#define NV_CHIP_GEFORCE4_MX_420 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420)
+#define NV_CHIP_GEFORCE4_440_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO)
+#define NV_CHIP_GEFORCE4_420_GO ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO)
+#define NV_CHIP_GEFORCE4_420_GO_M32 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32)
+#define NV_CHIP_QUADRO4_500XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL)
+#define NV_CHIP_GEFORCE4_440_GO_M64 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64)
+#define NV_CHIP_QUADRO4_200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_200)
+#define NV_CHIP_QUADRO4_550XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL)
+#define NV_CHIP_QUADRO4_500_GOGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL)
+#define NV_CHIP_0x0180 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0180)
+#define NV_CHIP_0x0181 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0181)
+#define NV_CHIP_0x0182 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0182)
+#define NV_CHIP_0x0188 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0188)
+#define NV_CHIP_0x018A ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018A)
+#define NV_CHIP_0x018B ((PCI_VENDOR_ID_NVIDIA << 16) | 0x018B)
+#define NV_CHIP_IGEFORCE2 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_IGEFORCE2)
+#define NV_CHIP_0x01F0 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x01F0)
+#define NV_CHIP_GEFORCE3 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3)
+#define NV_CHIP_GEFORCE3_TI_200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_200)
+#define NV_CHIP_GEFORCE3_TI_500 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE3_TI_500)
+#define NV_CHIP_QUADRO_DCC ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO_DCC)
+#define NV_CHIP_GEFORCE4_TI_4600 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600)
+#define NV_CHIP_GEFORCE4_TI_4400 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400)
+#define NV_CHIP_GEFORCE4_TI_4200 ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200)
+#define NV_CHIP_QUADRO4_900XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL)
+#define NV_CHIP_QUADRO4_750XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL)
+#define NV_CHIP_QUADRO4_700XGL ((PCI_VENDOR_ID_NVIDIA << 16) | PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL)
+#define NV_CHIP_0x0280 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0280)
+#define NV_CHIP_0x0281 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0281)
+#define NV_CHIP_0x0288 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0288)
+#define NV_CHIP_0x0289 ((PCI_VENDOR_ID_NVIDIA << 16) | 0x0289)
+
+#endif /* __NV_STRUCT_H__ */
diff --git a/drivers/video/fbdev/riva/nvreg.h b/drivers/video/fbdev/riva/nvreg.h
new file mode 100644
index 000000000000..abfc167ae8d8
--- /dev/null
+++ b/drivers/video/fbdev/riva/nvreg.h
@@ -0,0 +1,188 @@
+/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */
+/*
+ * Copyright 1996-1997 David J. McKay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/nvreg.h,v 3.2.2.1 1998/01/18 10:35:36 hohndel Exp $ */
+
+#ifndef __NVREG_H_
+#define __NVREG_H_
+
+/* Little macro to construct bitmask for contiguous ranges of bits */
+#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
+#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
+
+/* Macro to set specific bitfields (mask has to be a macro x:y) ! */
+#define SetBF(mask,value) ((value) << (0?mask))
+#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
+
+#define MaskAndSetBF(var,mask,value) (var)=(((var)&(~MASKEXPAND(mask)) \
+ | SetBF(mask,value)))
+
+#define DEVICE_BASE(device) (0?NV##_##device)
+#define DEVICE_SIZE(device) ((1?NV##_##device) - DEVICE_BASE(device)+1)
+
+/* This is where we will have to have conditional compilation */
+#define DEVICE_ACCESS(device,reg) \
+ nvCONTROL[(NV_##device##_##reg)/4]
+
+#define DEVICE_WRITE(device,reg,value) DEVICE_ACCESS(device,reg)=(value)
+#define DEVICE_READ(device,reg) DEVICE_ACCESS(device,reg)
+#define DEVICE_PRINT(device,reg) \
+ ErrorF("NV_"#device"_"#reg"=#%08lx\n",DEVICE_ACCESS(device,reg))
+#define DEVICE_DEF(device,mask,value) \
+ SetBF(NV_##device##_##mask,NV_##device##_##mask##_##value)
+#define DEVICE_VALUE(device,mask,value) SetBF(NV_##device##_##mask,value)
+#define DEVICE_MASK(device,mask) MASKEXPAND(NV_##device##_##mask)
+
+#define PDAC_Write(reg,value) DEVICE_WRITE(PDAC,reg,value)
+#define PDAC_Read(reg) DEVICE_READ(PDAC,reg)
+#define PDAC_Print(reg) DEVICE_PRINT(PDAC,reg)
+#define PDAC_Def(mask,value) DEVICE_DEF(PDAC,mask,value)
+#define PDAC_Val(mask,value) DEVICE_VALUE(PDAC,mask,value)
+#define PDAC_Mask(mask) DEVICE_MASK(PDAC,mask)
+
+#define PFB_Write(reg,value) DEVICE_WRITE(PFB,reg,value)
+#define PFB_Read(reg) DEVICE_READ(PFB,reg)
+#define PFB_Print(reg) DEVICE_PRINT(PFB,reg)
+#define PFB_Def(mask,value) DEVICE_DEF(PFB,mask,value)
+#define PFB_Val(mask,value) DEVICE_VALUE(PFB,mask,value)
+#define PFB_Mask(mask) DEVICE_MASK(PFB,mask)
+
+#define PRM_Write(reg,value) DEVICE_WRITE(PRM,reg,value)
+#define PRM_Read(reg) DEVICE_READ(PRM,reg)
+#define PRM_Print(reg) DEVICE_PRINT(PRM,reg)
+#define PRM_Def(mask,value) DEVICE_DEF(PRM,mask,value)
+#define PRM_Val(mask,value) DEVICE_VALUE(PRM,mask,value)
+#define PRM_Mask(mask) DEVICE_MASK(PRM,mask)
+
+#define PGRAPH_Write(reg,value) DEVICE_WRITE(PGRAPH,reg,value)
+#define PGRAPH_Read(reg) DEVICE_READ(PGRAPH,reg)
+#define PGRAPH_Print(reg) DEVICE_PRINT(PGRAPH,reg)
+#define PGRAPH_Def(mask,value) DEVICE_DEF(PGRAPH,mask,value)
+#define PGRAPH_Val(mask,value) DEVICE_VALUE(PGRAPH,mask,value)
+#define PGRAPH_Mask(mask) DEVICE_MASK(PGRAPH,mask)
+
+#define PDMA_Write(reg,value) DEVICE_WRITE(PDMA,reg,value)
+#define PDMA_Read(reg) DEVICE_READ(PDMA,reg)
+#define PDMA_Print(reg) DEVICE_PRINT(PDMA,reg)
+#define PDMA_Def(mask,value) DEVICE_DEF(PDMA,mask,value)
+#define PDMA_Val(mask,value) DEVICE_VALUE(PDMA,mask,value)
+#define PDMA_Mask(mask) DEVICE_MASK(PDMA,mask)
+
+#define PTIMER_Write(reg,value) DEVICE_WRITE(PTIMER,reg,value)
+#define PTIMER_Read(reg) DEVICE_READ(PTIMER,reg)
+#define PTIMER_Print(reg) DEVICE_PRINT(PTIMER,reg)
+#define PTIMER_Def(mask,value) DEVICE_DEF(PTIMER,mask,value)
+#define PTIMER_Val(mask,value) DEVICE_VALUE(PTIEMR,mask,value)
+#define PTIMER_Mask(mask) DEVICE_MASK(PTIMER,mask)
+
+#define PEXTDEV_Write(reg,value) DEVICE_WRITE(PEXTDEV,reg,value)
+#define PEXTDEV_Read(reg) DEVICE_READ(PEXTDEV,reg)
+#define PEXTDEV_Print(reg) DEVICE_PRINT(PEXTDEV,reg)
+#define PEXTDEV_Def(mask,value) DEVICE_DEF(PEXTDEV,mask,value)
+#define PEXTDEV_Val(mask,value) DEVICE_VALUE(PEXTDEV,mask,value)
+#define PEXTDEV_Mask(mask) DEVICE_MASK(PEXTDEV,mask)
+
+#define PFIFO_Write(reg,value) DEVICE_WRITE(PFIFO,reg,value)
+#define PFIFO_Read(reg) DEVICE_READ(PFIFO,reg)
+#define PFIFO_Print(reg) DEVICE_PRINT(PFIFO,reg)
+#define PFIFO_Def(mask,value) DEVICE_DEF(PFIFO,mask,value)
+#define PFIFO_Val(mask,value) DEVICE_VALUE(PFIFO,mask,value)
+#define PFIFO_Mask(mask) DEVICE_MASK(PFIFO,mask)
+
+#define PRAM_Write(reg,value) DEVICE_WRITE(PRAM,reg,value)
+#define PRAM_Read(reg) DEVICE_READ(PRAM,reg)
+#define PRAM_Print(reg) DEVICE_PRINT(PRAM,reg)
+#define PRAM_Def(mask,value) DEVICE_DEF(PRAM,mask,value)
+#define PRAM_Val(mask,value) DEVICE_VALUE(PRAM,mask,value)
+#define PRAM_Mask(mask) DEVICE_MASK(PRAM,mask)
+
+#define PRAMFC_Write(reg,value) DEVICE_WRITE(PRAMFC,reg,value)
+#define PRAMFC_Read(reg) DEVICE_READ(PRAMFC,reg)
+#define PRAMFC_Print(reg) DEVICE_PRINT(PRAMFC,reg)
+#define PRAMFC_Def(mask,value) DEVICE_DEF(PRAMFC,mask,value)
+#define PRAMFC_Val(mask,value) DEVICE_VALUE(PRAMFC,mask,value)
+#define PRAMFC_Mask(mask) DEVICE_MASK(PRAMFC,mask)
+
+#define PMC_Write(reg,value) DEVICE_WRITE(PMC,reg,value)
+#define PMC_Read(reg) DEVICE_READ(PMC,reg)
+#define PMC_Print(reg) DEVICE_PRINT(PMC,reg)
+#define PMC_Def(mask,value) DEVICE_DEF(PMC,mask,value)
+#define PMC_Val(mask,value) DEVICE_VALUE(PMC,mask,value)
+#define PMC_Mask(mask) DEVICE_MASK(PMC,mask)
+
+#define PMC_Write(reg,value) DEVICE_WRITE(PMC,reg,value)
+#define PMC_Read(reg) DEVICE_READ(PMC,reg)
+#define PMC_Print(reg) DEVICE_PRINT(PMC,reg)
+#define PMC_Def(mask,value) DEVICE_DEF(PMC,mask,value)
+#define PMC_Val(mask,value) DEVICE_VALUE(PMC,mask,value)
+#define PMC_Mask(mask) DEVICE_MASK(PMC,mask)
+
+
+#define PBUS_Write(reg,value) DEVICE_WRITE(PBUS,reg,value)
+#define PBUS_Read(reg) DEVICE_READ(PBUS,reg)
+#define PBUS_Print(reg) DEVICE_PRINT(PBUS,reg)
+#define PBUS_Def(mask,value) DEVICE_DEF(PBUS,mask,value)
+#define PBUS_Val(mask,value) DEVICE_VALUE(PBUS,mask,value)
+#define PBUS_Mask(mask) DEVICE_MASK(PBUS,mask)
+
+
+#define PRAMDAC_Write(reg,value) DEVICE_WRITE(PRAMDAC,reg,value)
+#define PRAMDAC_Read(reg) DEVICE_READ(PRAMDAC,reg)
+#define PRAMDAC_Print(reg) DEVICE_PRINT(PRAMDAC,reg)
+#define PRAMDAC_Def(mask,value) DEVICE_DEF(PRAMDAC,mask,value)
+#define PRAMDAC_Val(mask,value) DEVICE_VALUE(PRAMDAC,mask,value)
+#define PRAMDAC_Mask(mask) DEVICE_MASK(PRAMDAC,mask)
+
+
+#define PDAC_ReadExt(reg) \
+ ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\
+ (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\
+ (PDAC_Read(INDEX_DATA)))
+
+#define PDAC_WriteExt(reg,value)\
+ ((PDAC_Write(INDEX_LO,(NV_PDAC_EXT_##reg) & 0xff)),\
+ (PDAC_Write(INDEX_HI,((NV_PDAC_EXT_##reg) >> 8) & 0xff)),\
+ (PDAC_Write(INDEX_DATA,(value))))
+
+#define CRTC_Write(index,value) outb((index), 0x3d4); outb(value, 0x3d5)
+#define CRTC_Read(index) (outb(index, 0x3d4),inb(0x3d5))
+
+#define PCRTC_Write(index,value) CRTC_Write(NV_PCRTC_##index,value)
+#define PCRTC_Read(index) CRTC_Read(NV_PCRTC_##index)
+
+#define PCRTC_Def(mask,value) DEVICE_DEF(PCRTC,mask,value)
+#define PCRTC_Val(mask,value) DEVICE_VALUE(PCRTC,mask,value)
+#define PCRTC_Mask(mask) DEVICE_MASK(PCRTC,mask)
+
+#define SR_Write(index,value) outb(0x3c4,(index));outb(0x3c5,value)
+#define SR_Read(index) (outb(0x3c4,index),inb(0x3c5))
+
+extern volatile unsigned *nvCONTROL;
+
+typedef enum {NV1,NV3,NV4,NumNVChips} NVChipType;
+
+NVChipType GetChipType(void);
+
+#endif
+
+
diff --git a/drivers/video/fbdev/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c
new file mode 100644
index 000000000000..78fdbf5178d7
--- /dev/null
+++ b/drivers/video/fbdev/riva/riva_hw.c
@@ -0,0 +1,2268 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 1993-1999 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 -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.33 2002/08/05 20:47:06 mvojkovi Exp $ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include "riva_hw.h"
+#include "riva_tbl.h"
+#include "nv_type.h"
+
+/*
+ * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
+ * operate identically (except TNT has more memory and better 3D quality.
+ */
+static int nv3Busy
+(
+ RIVA_HW_INST *chip
+)
+{
+ return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
+ NV_RD32(&chip->PGRAPH[0x000006B0/4], 0) & 0x01);
+}
+static int nv4Busy
+(
+ RIVA_HW_INST *chip
+)
+{
+ return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
+ NV_RD32(&chip->PGRAPH[0x00000700/4], 0) & 0x01);
+}
+static int nv10Busy
+(
+ RIVA_HW_INST *chip
+)
+{
+ return ((NV_RD32(&chip->Rop->FifoFree, 0) < chip->FifoEmptyCount) ||
+ NV_RD32(&chip->PGRAPH[0x00000700/4], 0) & 0x01);
+}
+
+static void vgaLockUnlock
+(
+ RIVA_HW_INST *chip,
+ int Lock
+)
+{
+ U008 cr11;
+ VGA_WR08(chip->PCIO, 0x3D4, 0x11);
+ cr11 = VGA_RD08(chip->PCIO, 0x3D5);
+ if(Lock) cr11 |= 0x80;
+ else cr11 &= ~0x80;
+ VGA_WR08(chip->PCIO, 0x3D5, cr11);
+}
+static void nv3LockUnlock
+(
+ RIVA_HW_INST *chip,
+ int Lock
+)
+{
+ VGA_WR08(chip->PVIO, 0x3C4, 0x06);
+ VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57);
+ vgaLockUnlock(chip, Lock);
+}
+static void nv4LockUnlock
+(
+ RIVA_HW_INST *chip,
+ int Lock
+)
+{
+ VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
+ VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+ vgaLockUnlock(chip, Lock);
+}
+
+static int ShowHideCursor
+(
+ RIVA_HW_INST *chip,
+ int ShowHide
+)
+{
+ int cursor;
+ cursor = chip->CurrentState->cursor1;
+ chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
+ (ShowHide & 0x01);
+ VGA_WR08(chip->PCIO, 0x3D4, 0x31);
+ VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
+ return (cursor & 0x01);
+}
+
+/****************************************************************************\
+* *
+* The video arbitration routines calculate some "magic" numbers. Fixes *
+* the snow seen when accessing the framebuffer without it. *
+* It just works (I hope). *
+* *
+\****************************************************************************/
+
+#define DEFAULT_GR_LWM 100
+#define DEFAULT_VID_LWM 100
+#define DEFAULT_GR_BURST_SIZE 256
+#define DEFAULT_VID_BURST_SIZE 128
+#define VIDEO 0
+#define GRAPHICS 1
+#define MPORT 2
+#define ENGINE 3
+#define GFIFO_SIZE 320
+#define GFIFO_SIZE_128 256
+#define MFIFO_SIZE 120
+#define VFIFO_SIZE 256
+
+typedef struct {
+ int gdrain_rate;
+ int vdrain_rate;
+ int mdrain_rate;
+ int gburst_size;
+ int vburst_size;
+ char vid_en;
+ char gr_en;
+ int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm;
+ int by_gfacc;
+ char vid_only_once;
+ char gr_only_once;
+ char first_vacc;
+ char first_gacc;
+ char first_macc;
+ int vocc;
+ int gocc;
+ int mocc;
+ char cur;
+ char engine_en;
+ char converged;
+ int priority;
+} nv3_arb_info;
+typedef struct {
+ int graphics_lwm;
+ int video_lwm;
+ int graphics_burst_size;
+ int video_burst_size;
+ int graphics_hi_priority;
+ int media_hi_priority;
+ int rtl_values;
+ int valid;
+} nv3_fifo_info;
+typedef struct {
+ char pix_bpp;
+ char enable_video;
+ char gr_during_vid;
+ char enable_mp;
+ int memory_width;
+ int video_scale;
+ int pclk_khz;
+ int mclk_khz;
+ int mem_page_miss;
+ int mem_latency;
+ char mem_aligned;
+} nv3_sim_state;
+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;
+ u32 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 int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
+{
+ int iter = 0;
+ int tmp;
+ int vfsize, mfsize, gfsize;
+ int mburst_size = 32;
+ int mmisses, gmisses, vmisses;
+ int misses;
+ int vlwm, glwm, mlwm;
+ int last, next, cur;
+ int max_gfsize ;
+ long ns;
+
+ vlwm = 0;
+ glwm = 0;
+ mlwm = 0;
+ vfsize = 0;
+ gfsize = 0;
+ cur = ainfo->cur;
+ mmisses = 2;
+ gmisses = 2;
+ vmisses = 2;
+ if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128;
+ else max_gfsize = GFIFO_SIZE;
+ max_gfsize = GFIFO_SIZE;
+ while (1)
+ {
+ if (ainfo->vid_en)
+ {
+ if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc;
+ if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ;
+ ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
+ vfsize = ns * ainfo->vdrain_rate / 1000000;
+ vfsize = ainfo->wcvlwm - ainfo->vburst_size + vfsize;
+ }
+ if (state->enable_mp)
+ {
+ if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc;
+ }
+ if (ainfo->gr_en)
+ {
+ if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
+ if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
+ ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
+ gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
+ gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
+ }
+ mfsize = 0;
+ if (!state->gr_during_vid && ainfo->vid_en)
+ if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once)
+ next = VIDEO;
+ else if (ainfo->mocc < 0)
+ next = MPORT;
+ else if (ainfo->gocc< ainfo->by_gfacc)
+ next = GRAPHICS;
+ else return (0);
+ else switch (ainfo->priority)
+ {
+ case VIDEO:
+ if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
+ next = VIDEO;
+ else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
+ next = GRAPHICS;
+ else if (ainfo->mocc<0)
+ next = MPORT;
+ else return (0);
+ break;
+ case GRAPHICS:
+ if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
+ next = GRAPHICS;
+ else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
+ next = VIDEO;
+ else if (ainfo->mocc<0)
+ next = MPORT;
+ else return (0);
+ break;
+ default:
+ if (ainfo->mocc<0)
+ next = MPORT;
+ else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
+ next = GRAPHICS;
+ else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
+ next = VIDEO;
+ else return (0);
+ break;
+ }
+ last = cur;
+ cur = next;
+ iter++;
+ switch (cur)
+ {
+ case VIDEO:
+ if (last==cur) misses = 0;
+ else if (ainfo->first_vacc) misses = vmisses;
+ else misses = 1;
+ ainfo->first_vacc = 0;
+ if (last!=cur)
+ {
+ ns = 1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
+ vlwm = ns * ainfo->vdrain_rate/ 1000000;
+ vlwm = ainfo->vocc - vlwm;
+ }
+ ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz;
+ ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000;
+ ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000;
+ ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000;
+ break;
+ case GRAPHICS:
+ if (last==cur) misses = 0;
+ else if (ainfo->first_gacc) misses = gmisses;
+ else misses = 1;
+ ainfo->first_gacc = 0;
+ if (last!=cur)
+ {
+ ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ;
+ glwm = ns * ainfo->gdrain_rate/1000000;
+ glwm = ainfo->gocc - glwm;
+ }
+ ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
+ ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
+ ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000;
+ ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000;
+ break;
+ default:
+ if (last==cur) misses = 0;
+ else if (ainfo->first_macc) misses = mmisses;
+ else misses = 1;
+ ainfo->first_macc = 0;
+ ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz;
+ ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
+ ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000;
+ ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000;
+ break;
+ }
+ if (iter>100)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
+ tmp = ns * ainfo->gdrain_rate/1000000;
+ if (abs(ainfo->gburst_size) + ((abs(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
+ tmp = ns * ainfo->vdrain_rate/1000000;
+ if (abs(ainfo->vburst_size) + (abs(ainfo->wcvlwm + 32) & ~0xf) - tmp> VFIFO_SIZE)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ if (abs(ainfo->gocc) > max_gfsize)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ if (abs(ainfo->vocc) > VFIFO_SIZE)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ if (abs(ainfo->mocc) > MFIFO_SIZE)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ if (abs(vfsize) > VFIFO_SIZE)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ if (abs(gfsize) > max_gfsize)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ if (abs(mfsize) > MFIFO_SIZE)
+ {
+ ainfo->converged = 0;
+ return (1);
+ }
+ }
+}
+static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
+{
+ long ens, vns, mns, gns;
+ int mmisses, gmisses, vmisses, eburst_size, mburst_size;
+ int refresh_cycle;
+
+ refresh_cycle = 0;
+ refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5;
+ mmisses = 2;
+ if (state->mem_aligned) gmisses = 2;
+ else gmisses = 3;
+ vmisses = 2;
+ eburst_size = state->memory_width * 1;
+ mburst_size = 32;
+ gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
+ ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
+ ainfo->wcmocc = 0;
+ ainfo->wcgocc = 0;
+ ainfo->wcvocc = 0;
+ ainfo->wcvlwm = 0;
+ ainfo->wcglwm = 0;
+ ainfo->engine_en = 1;
+ ainfo->converged = 1;
+ if (ainfo->engine_en)
+ {
+ ens = 1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz;
+ ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0;
+ ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0;
+ ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0;
+ ainfo->cur = ENGINE;
+ ainfo->first_vacc = 1;
+ ainfo->first_gacc = 1;
+ ainfo->first_macc = 1;
+ nv3_iterate(res_info, state,ainfo);
+ }
+ if (state->enable_mp)
+ {
+ mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
+ ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000;
+ ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000;
+ ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000;
+ ainfo->cur = MPORT;
+ ainfo->first_vacc = 1;
+ ainfo->first_gacc = 1;
+ ainfo->first_macc = 0;
+ nv3_iterate(res_info, state,ainfo);
+ }
+ if (ainfo->gr_en)
+ {
+ ainfo->first_vacc = 1;
+ ainfo->first_gacc = 0;
+ ainfo->first_macc = 1;
+ gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
+ ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000;
+ ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0;
+ ainfo->mocc = state->enable_mp ? 0-gns*ainfo->mdrain_rate/1000000: 0;
+ ainfo->cur = GRAPHICS;
+ nv3_iterate(res_info, state,ainfo);
+ }
+ if (ainfo->vid_en)
+ {
+ ainfo->first_vacc = 0;
+ ainfo->first_gacc = 1;
+ ainfo->first_macc = 1;
+ vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
+ ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000;
+ ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0;
+ ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ;
+ ainfo->cur = VIDEO;
+ nv3_iterate(res_info, state, ainfo);
+ }
+ if (ainfo->converged)
+ {
+ res_info->graphics_lwm = (int)abs(ainfo->wcglwm) + 16;
+ res_info->video_lwm = (int)abs(ainfo->wcvlwm) + 32;
+ res_info->graphics_burst_size = ainfo->gburst_size;
+ res_info->video_burst_size = ainfo->vburst_size;
+ res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS);
+ res_info->media_hi_priority = (ainfo->priority == MPORT);
+ if (res_info->video_lwm > 160)
+ {
+ res_info->graphics_lwm = 256;
+ res_info->video_lwm = 128;
+ res_info->graphics_burst_size = 64;
+ res_info->video_burst_size = 64;
+ res_info->graphics_hi_priority = 0;
+ res_info->media_hi_priority = 0;
+ ainfo->converged = 0;
+ return (0);
+ }
+ if (res_info->video_lwm > 128)
+ {
+ res_info->video_lwm = 128;
+ }
+ return (1);
+ }
+ else
+ {
+ res_info->graphics_lwm = 256;
+ res_info->video_lwm = 128;
+ res_info->graphics_burst_size = 64;
+ res_info->video_burst_size = 64;
+ res_info->graphics_hi_priority = 0;
+ res_info->media_hi_priority = 0;
+ return (0);
+ }
+}
+static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
+{
+ int done, g,v, p;
+
+ done = 0;
+ for (p=0; p < 2; p++)
+ {
+ for (g=128 ; g > 32; g= g>> 1)
+ {
+ for (v=128; v >=32; v = v>> 1)
+ {
+ ainfo->priority = p;
+ ainfo->gburst_size = g;
+ ainfo->vburst_size = v;
+ done = nv3_arb(res_info, state,ainfo);
+ if (done && (g==128))
+ if ((res_info->graphics_lwm + g) > 256)
+ done = 0;
+ if (done)
+ goto Done;
+ }
+ }
+ }
+
+ Done:
+ return done;
+}
+static void nv3CalcArbitration
+(
+ nv3_fifo_info * res_info,
+ nv3_sim_state * state
+)
+{
+ nv3_fifo_info save_info;
+ nv3_arb_info ainfo;
+ char res_gr, res_vid;
+
+ ainfo.gr_en = 1;
+ ainfo.vid_en = state->enable_video;
+ ainfo.vid_only_once = 0;
+ ainfo.gr_only_once = 0;
+ ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
+ ainfo.vdrain_rate = (int) state->pclk_khz * 2;
+ if (state->video_scale != 0)
+ ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
+ ainfo.mdrain_rate = 33000;
+ res_info->rtl_values = 0;
+ if (!state->gr_during_vid && state->enable_video)
+ {
+ ainfo.gr_only_once = 1;
+ ainfo.gr_en = 1;
+ ainfo.gdrain_rate = 0;
+ res_vid = nv3_get_param(res_info, state, &ainfo);
+ res_vid = ainfo.converged;
+ save_info.video_lwm = res_info->video_lwm;
+ save_info.video_burst_size = res_info->video_burst_size;
+ ainfo.vid_en = 1;
+ ainfo.vid_only_once = 1;
+ ainfo.gr_en = 1;
+ ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
+ ainfo.vdrain_rate = 0;
+ res_gr = nv3_get_param(res_info, state, &ainfo);
+ res_gr = ainfo.converged;
+ res_info->video_lwm = save_info.video_lwm;
+ res_info->video_burst_size = save_info.video_burst_size;
+ res_info->valid = res_gr & res_vid;
+ }
+ else
+ {
+ if (!ainfo.gr_en) ainfo.gdrain_rate = 0;
+ if (!ainfo.vid_en) ainfo.vdrain_rate = 0;
+ res_gr = nv3_get_param(res_info, state, &ainfo);
+ res_info->valid = ainfo.converged;
+ }
+}
+static void nv3UpdateArbitrationSettings
+(
+ unsigned VClk,
+ unsigned pixelDepth,
+ unsigned *burst,
+ unsigned *lwm,
+ RIVA_HW_INST *chip
+)
+{
+ nv3_fifo_info fifo_data;
+ nv3_sim_state sim_data;
+ unsigned int M, N, P, pll, MClk;
+
+ pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
+ M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+ MClk = (N * chip->CrystalFreqKHz / M) >> P;
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 0;
+ sim_data.enable_mp = 0;
+ sim_data.video_scale = 1;
+ sim_data.memory_width = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 0x10) ?
+ 128 : 64;
+ sim_data.memory_width = 128;
+
+ sim_data.mem_latency = 9;
+ sim_data.mem_aligned = 1;
+ sim_data.mem_page_miss = 11;
+ sim_data.gr_during_vid = 0;
+ sim_data.pclk_khz = VClk;
+ sim_data.mclk_khz = MClk;
+ nv3CalcArbitration(&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;
+ }
+ else
+ {
+ *lwm = 0x24;
+ *burst = 0x2;
+ }
+}
+static void nv4CalcArbitration
+(
+ nv4_fifo_info *fifo,
+ nv4_sim_state *arb
+)
+{
+ int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
+ 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;
+ int craw, vraw;
+
+ 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;
+ color_key_enable = arb->gr_during_vid;
+ bpp = arb->pix_bpp;
+ align = arb->mem_aligned;
+ 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--;
+ }
+ }
+ craw = clwm;
+ vraw = vlwm;
+ 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,
+ RIVA_HW_INST *chip
+)
+{
+ nv4_fifo_info fifo_data;
+ nv4_sim_state sim_data;
+ unsigned int M, N, P, pll, MClk, NVClk, cfg1;
+
+ pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
+ M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+ MClk = (N * chip->CrystalFreqKHz / M) >> P;
+ pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
+ M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+ NVClk = (N * chip->CrystalFreqKHz / M) >> P;
+ cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 0;
+ sim_data.enable_mp = 0;
+ sim_data.memory_width = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 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, cas,width, video_enable, color_key_enable, bpp, align;
+ int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+ int nvclk_fill, us_extra;
+ 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, video_drain_rate, crtc_drain_rate;
+ int vus_m, vus_n, vus_p;
+ int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm;
+ int clwm_rnd_down;
+ int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2;
+ int pclks_2_top_fifo, 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;
+ cas = arb->mem_latency;
+ width = arb->memory_width/64;
+ video_enable = arb->enable_video;
+ color_key_enable = arb->gr_during_vid;
+ bpp = arb->pix_bpp;
+ align = arb->mem_aligned;
+ mp_enable = arb->enable_mp;
+ clwm = 0;
+ vlwm = 1024;
+
+ cbs = 512;
+ vbs = 512;
+
+ pclks = 4; /* lwm detect. */
+
+ nvclks = 3; /* lwm -> sync. */
+ nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
+
+ mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */
+
+ 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;
+ }
+
+ nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */
+ 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;
+ us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+ us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
+ us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
+ us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
+ us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
+ us_pipe = us_m + us_n + us_p;
+ us_pipe_min = us_m_min + us_n + us_p;
+ us_extra = 0;
+
+ vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+ vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */
+ vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */
+ vus_pipe = vus_m + vus_n + vus_p;
+
+ if(video_enable) {
+ video_drain_rate = pclk_freq * 4; /* MB/s */
+ 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;
+
+ us_video = vpm_us + vus_m; /* Video has separate read return path */
+
+ cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
+ us_crt =
+ us_video /* Wait for video */
+ +cpm_us /* CRT Page miss */
+ +us_m + us_n +us_p /* other latency */
+ ;
+
+ clwm = us_crt * crtc_drain_rate/(1000*1000);
+ clwm++; /* fixed point <= float_point - 1. Fixes that */
+ } else {
+ crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/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);
+ clwm++; /* fixed point <= float_point - 1. Fixes that */
+
+ /*
+ //
+ // Another concern, only for high pclks so don't do this
+ // with video:
+ // What happens if the latency to fetch the cbs is so large that
+ // fifo empties. In that case we need to have an alternate clwm value
+ // based off the total burst fetch
+ //
+ us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+ us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
+ clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
+ clwm_mt ++;
+ if(clwm_mt > clwm)
+ clwm = clwm_mt;
+ */
+ /* Finally, a heuristic check when width == 64 bits */
+ if(width == 1){
+ nvclk_fill = nvclk_freq * 8;
+ if(crtc_drain_rate * 100 >= nvclk_fill * 102)
+ clwm = 0xfff; /*Large number to fail */
+
+ else if(crtc_drain_rate * 100 >= nvclk_fill * 98) {
+ clwm = 1024;
+ cbs = 512;
+ us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+ }
+ }
+ }
+
+
+ /*
+ 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;
+ pclks_2_top_fifo = (1024-clwm)/(8*width);
+
+ /* 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) {
+ found = 1; /* Can't adjust anymore! */
+ } else {
+ cbs = cbs/2; /* reduce the burst size */
+ }
+ } else {
+ min_mclk_extra--;
+ }
+ } else {
+ if (clwm > 1023){ /* Have some margin */
+ fifo->valid = 0;
+ found = 0;
+ if(min_mclk_extra == 0)
+ found = 1; /* Can't adjust anymore! */
+ else
+ min_mclk_extra--;
+ }
+ }
+ craw = clwm;
+
+ 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;
+
+ /* printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
+ fifo->video_lwm = 1024; fifo->video_burst_size = 512;
+ }
+}
+static void nv10UpdateArbitrationSettings
+(
+ unsigned VClk,
+ unsigned pixelDepth,
+ unsigned *burst,
+ unsigned *lwm,
+ RIVA_HW_INST *chip
+)
+{
+ nv10_fifo_info fifo_data;
+ nv10_sim_state sim_data;
+ unsigned int M, N, P, pll, MClk, NVClk, cfg1;
+
+ pll = NV_RD32(&chip->PRAMDAC0[0x00000504/4], 0);
+ M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+ MClk = (N * chip->CrystalFreqKHz / M) >> P;
+ pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
+ M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+ NVClk = (N * chip->CrystalFreqKHz / M) >> P;
+ cfg1 = NV_RD32(&chip->PFB[0x00000204/4], 0);
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 0;
+ sim_data.enable_mp = 0;
+ sim_data.memory_type = (NV_RD32(&chip->PFB[0x00000200/4], 0) & 0x01) ?
+ 1 : 0;
+ sim_data.memory_width = (NV_RD32(&chip->PEXTDEV[0x00000000/4], 0) & 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 nForceUpdateArbitrationSettings
+(
+ unsigned VClk,
+ unsigned pixelDepth,
+ unsigned *burst,
+ unsigned *lwm,
+ RIVA_HW_INST *chip
+)
+{
+ nv10_fifo_info fifo_data;
+ nv10_sim_state sim_data;
+ unsigned int M, N, P, pll, MClk, NVClk;
+ unsigned int uMClkPostDiv;
+ struct pci_dev *dev;
+
+ dev = pci_get_bus_and_slot(0, 3);
+ pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+ pci_dev_put(dev);
+ uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
+
+ if(!uMClkPostDiv) uMClkPostDiv = 4;
+ MClk = 400000 / uMClkPostDiv;
+
+ pll = NV_RD32(&chip->PRAMDAC0[0x00000500/4], 0);
+ M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
+ NVClk = (N * chip->CrystalFreqKHz / M) >> P;
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 0;
+ sim_data.enable_mp = 0;
+
+ dev = pci_get_bus_and_slot(0, 1);
+ pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+ pci_dev_put(dev);
+ sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
+
+ sim_data.memory_width = 64;
+ 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 int CalcVClock
+(
+ int clockIn,
+ int *clockOut,
+ int *mOut,
+ int *nOut,
+ int *pOut,
+ RIVA_HW_INST *chip
+)
+{
+ unsigned lowM, highM, highP;
+ unsigned DeltaNew, DeltaOld;
+ unsigned VClk, Freq;
+ unsigned M, N, P;
+
+ DeltaOld = 0xFFFFFFFF;
+
+ VClk = (unsigned)clockIn;
+
+ if (chip->CrystalFreqKHz == 13500)
+ {
+ lowM = 7;
+ highM = 13 - (chip->Architecture == NV_ARCH_03);
+ }
+ else
+ {
+ lowM = 8;
+ highM = 14 - (chip->Architecture == NV_ARCH_03);
+ }
+
+ highP = 4 - (chip->Architecture == NV_ARCH_03);
+ for (P = 0; P <= highP; P ++)
+ {
+ Freq = VClk << P;
+ if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz))
+ {
+ for (M = lowM; M <= highM; M++)
+ {
+ N = (VClk << P) * M / chip->CrystalFreqKHz;
+ if(N <= 255) {
+ Freq = (chip->CrystalFreqKHz * N / M) >> P;
+ if (Freq > VClk)
+ DeltaNew = Freq - VClk;
+ else
+ DeltaNew = VClk - Freq;
+ if (DeltaNew < DeltaOld)
+ {
+ *mOut = M;
+ *nOut = N;
+ *pOut = P;
+ *clockOut = Freq;
+ DeltaOld = DeltaNew;
+ }
+ }
+ }
+ }
+ }
+
+ /* non-zero: M/N/P/clock values assigned. zero: error (not set) */
+ return (DeltaOld != 0xFFFFFFFF);
+}
+/*
+ * Calculate extended mode parameters (SVGA) and save in a
+ * mode state structure.
+ */
+int CalcStateExt
+(
+ RIVA_HW_INST *chip,
+ RIVA_HW_STATE *state,
+ int bpp,
+ int width,
+ int hDisplaySize,
+ int height,
+ int dotClock
+)
+{
+ int pixelDepth;
+ int uninitialized_var(VClk),uninitialized_var(m),
+ uninitialized_var(n), uninitialized_var(p);
+
+ /*
+ * 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 (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip))
+ return -EINVAL;
+
+ switch (chip->Architecture)
+ {
+ case NV_ARCH_03:
+ nv3UpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1),
+ chip);
+ state->cursor0 = 0x00;
+ state->cursor1 = 0x78;
+ state->cursor2 = 0x00000000;
+ state->pllsel = 0x10010100;
+ state->config = ((width + 31)/32)
+ | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
+ | 0x1000;
+ state->general = 0x00100100;
+ state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
+ break;
+ case NV_ARCH_04:
+ nv4UpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1),
+ chip);
+ state->cursor0 = 0x00;
+ state->cursor1 = 0xFC;
+ 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:
+ if((chip->Chipset == NV_CHIP_IGEFORCE2) ||
+ (chip->Chipset == NV_CHIP_0x01F0))
+ {
+ nForceUpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1),
+ chip);
+ } else {
+ nv10UpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1),
+ chip);
+ }
+ state->cursor0 = 0x80 | (chip->CursorStart >> 17);
+ state->cursor1 = (chip->CursorStart >> 11) << 2;
+ state->cursor2 = chip->CursorStart >> 24;
+ state->pllsel = 0x10000700;
+ state->config = NV_RD32(&chip->PFB[0x00000200/4], 0);
+ state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+ state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+ break;
+ }
+
+ /* Paul Richards: below if block borks things in kernel for some reason */
+ /* Tony: Below is needed to set hardware in DirectColor */
+ if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
+ state->general |= 0x00000030;
+
+ state->vpll = (p << 16) | (n << 8) | m;
+ state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
+ state->pixel = pixelDepth > 2 ? 3 : pixelDepth;
+ state->offset0 =
+ state->offset1 =
+ state->offset2 =
+ state->offset3 = 0;
+ state->pitch0 =
+ state->pitch1 =
+ state->pitch2 =
+ state->pitch3 = pixelDepth * width;
+
+ return 0;
+}
+/*
+ * Load fixed function state and pre-calculated/stored state.
+ */
+#if 0
+#define LOAD_FIXED_STATE(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev)/8; i++) \
+ chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1]
+#define LOAD_FIXED_STATE_8BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++) \
+ chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1]
+#define LOAD_FIXED_STATE_15BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++) \
+ chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1]
+#define LOAD_FIXED_STATE_16BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++) \
+ chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1]
+#define LOAD_FIXED_STATE_32BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++) \
+ chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
+#endif
+
+#define LOAD_FIXED_STATE(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev)/8; i++) \
+ NV_WR32(&chip->dev[tbl##Table##dev[i][0]], 0, tbl##Table##dev[i][1])
+#define LOAD_FIXED_STATE_8BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++) \
+ NV_WR32(&chip->dev[tbl##Table##dev##_8BPP[i][0]], 0, tbl##Table##dev##_8BPP[i][1])
+#define LOAD_FIXED_STATE_15BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++) \
+ NV_WR32(&chip->dev[tbl##Table##dev##_15BPP[i][0]], 0, tbl##Table##dev##_15BPP[i][1])
+#define LOAD_FIXED_STATE_16BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++) \
+ NV_WR32(&chip->dev[tbl##Table##dev##_16BPP[i][0]], 0, tbl##Table##dev##_16BPP[i][1])
+#define LOAD_FIXED_STATE_32BPP(tbl,dev) \
+ for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++) \
+ NV_WR32(&chip->dev[tbl##Table##dev##_32BPP[i][0]], 0, tbl##Table##dev##_32BPP[i][1])
+
+static void UpdateFifoState
+(
+ RIVA_HW_INST *chip
+)
+{
+ int i;
+
+ switch (chip->Architecture)
+ {
+ case NV_ARCH_04:
+ LOAD_FIXED_STATE(nv4,FIFO);
+ chip->Tri03 = NULL;
+ chip->Tri05 = (RivaTexturedTriangle05 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ /*
+ * Initialize state for the RivaTriangle3D05 routines.
+ */
+ LOAD_FIXED_STATE(nv10tri05,PGRAPH);
+ LOAD_FIXED_STATE(nv10,FIFO);
+ chip->Tri03 = NULL;
+ chip->Tri05 = (RivaTexturedTriangle05 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ }
+}
+static void LoadStateExt
+(
+ RIVA_HW_INST *chip,
+ RIVA_HW_STATE *state
+)
+{
+ int i;
+
+ /*
+ * Load HW fixed function state.
+ */
+ LOAD_FIXED_STATE(Riva,PMC);
+ LOAD_FIXED_STATE(Riva,PTIMER);
+ switch (chip->Architecture)
+ {
+ case NV_ARCH_03:
+ /*
+ * Make sure frame buffer config gets set before loading PRAMIN.
+ */
+ NV_WR32(chip->PFB, 0x00000200, state->config);
+ LOAD_FIXED_STATE(nv3,PFIFO);
+ LOAD_FIXED_STATE(nv3,PRAMIN);
+ LOAD_FIXED_STATE(nv3,PGRAPH);
+ switch (state->bpp)
+ {
+ case 15:
+ case 16:
+ LOAD_FIXED_STATE_15BPP(nv3,PRAMIN);
+ LOAD_FIXED_STATE_15BPP(nv3,PGRAPH);
+ chip->Tri03 = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ case 24:
+ case 32:
+ LOAD_FIXED_STATE_32BPP(nv3,PRAMIN);
+ LOAD_FIXED_STATE_32BPP(nv3,PGRAPH);
+ chip->Tri03 = NULL;
+ break;
+ case 8:
+ default:
+ LOAD_FIXED_STATE_8BPP(nv3,PRAMIN);
+ LOAD_FIXED_STATE_8BPP(nv3,PGRAPH);
+ chip->Tri03 = NULL;
+ break;
+ }
+ for (i = 0x00000; i < 0x00800; i++)
+ NV_WR32(&chip->PRAMIN[0x00000502 + i], 0, (i << 12) | 0x03);
+ NV_WR32(chip->PGRAPH, 0x00000630, state->offset0);
+ NV_WR32(chip->PGRAPH, 0x00000634, state->offset1);
+ NV_WR32(chip->PGRAPH, 0x00000638, state->offset2);
+ NV_WR32(chip->PGRAPH, 0x0000063C, state->offset3);
+ NV_WR32(chip->PGRAPH, 0x00000650, state->pitch0);
+ NV_WR32(chip->PGRAPH, 0x00000654, state->pitch1);
+ NV_WR32(chip->PGRAPH, 0x00000658, state->pitch2);
+ NV_WR32(chip->PGRAPH, 0x0000065C, state->pitch3);
+ break;
+ case NV_ARCH_04:
+ /*
+ * Make sure frame buffer config gets set before loading PRAMIN.
+ */
+ NV_WR32(chip->PFB, 0x00000200, state->config);
+ LOAD_FIXED_STATE(nv4,PFIFO);
+ LOAD_FIXED_STATE(nv4,PRAMIN);
+ LOAD_FIXED_STATE(nv4,PGRAPH);
+ switch (state->bpp)
+ {
+ case 15:
+ LOAD_FIXED_STATE_15BPP(nv4,PRAMIN);
+ LOAD_FIXED_STATE_15BPP(nv4,PGRAPH);
+ chip->Tri03 = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ case 16:
+ LOAD_FIXED_STATE_16BPP(nv4,PRAMIN);
+ LOAD_FIXED_STATE_16BPP(nv4,PGRAPH);
+ chip->Tri03 = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ case 24:
+ case 32:
+ LOAD_FIXED_STATE_32BPP(nv4,PRAMIN);
+ LOAD_FIXED_STATE_32BPP(nv4,PGRAPH);
+ chip->Tri03 = NULL;
+ break;
+ case 8:
+ default:
+ LOAD_FIXED_STATE_8BPP(nv4,PRAMIN);
+ LOAD_FIXED_STATE_8BPP(nv4,PGRAPH);
+ chip->Tri03 = NULL;
+ break;
+ }
+ NV_WR32(chip->PGRAPH, 0x00000640, state->offset0);
+ NV_WR32(chip->PGRAPH, 0x00000644, state->offset1);
+ NV_WR32(chip->PGRAPH, 0x00000648, state->offset2);
+ NV_WR32(chip->PGRAPH, 0x0000064C, state->offset3);
+ NV_WR32(chip->PGRAPH, 0x00000670, state->pitch0);
+ NV_WR32(chip->PGRAPH, 0x00000674, state->pitch1);
+ NV_WR32(chip->PGRAPH, 0x00000678, state->pitch2);
+ NV_WR32(chip->PGRAPH, 0x0000067C, state->pitch3);
+ break;
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ if(chip->twoHeads) {
+ VGA_WR08(chip->PCIO, 0x03D4, 0x44);
+ VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner);
+ chip->LockUnlock(chip, 0);
+ }
+
+ LOAD_FIXED_STATE(nv10,PFIFO);
+ LOAD_FIXED_STATE(nv10,PRAMIN);
+ LOAD_FIXED_STATE(nv10,PGRAPH);
+ switch (state->bpp)
+ {
+ case 15:
+ LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
+ LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
+ chip->Tri03 = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ case 16:
+ LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
+ LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
+ chip->Tri03 = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ break;
+ case 24:
+ case 32:
+ LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
+ LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
+ chip->Tri03 = NULL;
+ break;
+ case 8:
+ default:
+ LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
+ LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
+ chip->Tri03 = NULL;
+ break;
+ }
+
+ if(chip->Architecture == NV_ARCH_10) {
+ NV_WR32(chip->PGRAPH, 0x00000640, state->offset0);
+ NV_WR32(chip->PGRAPH, 0x00000644, state->offset1);
+ NV_WR32(chip->PGRAPH, 0x00000648, state->offset2);
+ NV_WR32(chip->PGRAPH, 0x0000064C, state->offset3);
+ NV_WR32(chip->PGRAPH, 0x00000670, state->pitch0);
+ NV_WR32(chip->PGRAPH, 0x00000674, state->pitch1);
+ NV_WR32(chip->PGRAPH, 0x00000678, state->pitch2);
+ NV_WR32(chip->PGRAPH, 0x0000067C, state->pitch3);
+ NV_WR32(chip->PGRAPH, 0x00000680, state->pitch3);
+ } else {
+ NV_WR32(chip->PGRAPH, 0x00000820, state->offset0);
+ NV_WR32(chip->PGRAPH, 0x00000824, state->offset1);
+ NV_WR32(chip->PGRAPH, 0x00000828, state->offset2);
+ NV_WR32(chip->PGRAPH, 0x0000082C, state->offset3);
+ NV_WR32(chip->PGRAPH, 0x00000850, state->pitch0);
+ NV_WR32(chip->PGRAPH, 0x00000854, state->pitch1);
+ NV_WR32(chip->PGRAPH, 0x00000858, state->pitch2);
+ NV_WR32(chip->PGRAPH, 0x0000085C, state->pitch3);
+ NV_WR32(chip->PGRAPH, 0x00000860, state->pitch3);
+ NV_WR32(chip->PGRAPH, 0x00000864, state->pitch3);
+ NV_WR32(chip->PGRAPH, 0x000009A4, NV_RD32(chip->PFB, 0x00000200));
+ NV_WR32(chip->PGRAPH, 0x000009A8, NV_RD32(chip->PFB, 0x00000204));
+ }
+ if(chip->twoHeads) {
+ NV_WR32(chip->PCRTC0, 0x00000860, state->head);
+ NV_WR32(chip->PCRTC0, 0x00002860, state->head2);
+ }
+ NV_WR32(chip->PRAMDAC, 0x00000404, NV_RD32(chip->PRAMDAC, 0x00000404) | (1 << 25));
+
+ NV_WR32(chip->PMC, 0x00008704, 1);
+ NV_WR32(chip->PMC, 0x00008140, 0);
+ NV_WR32(chip->PMC, 0x00008920, 0);
+ NV_WR32(chip->PMC, 0x00008924, 0);
+ NV_WR32(chip->PMC, 0x00008908, 0x01ffffff);
+ NV_WR32(chip->PMC, 0x0000890C, 0x01ffffff);
+ NV_WR32(chip->PMC, 0x00001588, 0);
+
+ NV_WR32(chip->PFB, 0x00000240, 0);
+ NV_WR32(chip->PFB, 0x00000250, 0);
+ NV_WR32(chip->PFB, 0x00000260, 0);
+ NV_WR32(chip->PFB, 0x00000270, 0);
+ NV_WR32(chip->PFB, 0x00000280, 0);
+ NV_WR32(chip->PFB, 0x00000290, 0);
+ NV_WR32(chip->PFB, 0x000002A0, 0);
+ NV_WR32(chip->PFB, 0x000002B0, 0);
+
+ NV_WR32(chip->PGRAPH, 0x00000B00, NV_RD32(chip->PFB, 0x00000240));
+ NV_WR32(chip->PGRAPH, 0x00000B04, NV_RD32(chip->PFB, 0x00000244));
+ NV_WR32(chip->PGRAPH, 0x00000B08, NV_RD32(chip->PFB, 0x00000248));
+ NV_WR32(chip->PGRAPH, 0x00000B0C, NV_RD32(chip->PFB, 0x0000024C));
+ NV_WR32(chip->PGRAPH, 0x00000B10, NV_RD32(chip->PFB, 0x00000250));
+ NV_WR32(chip->PGRAPH, 0x00000B14, NV_RD32(chip->PFB, 0x00000254));
+ NV_WR32(chip->PGRAPH, 0x00000B18, NV_RD32(chip->PFB, 0x00000258));
+ NV_WR32(chip->PGRAPH, 0x00000B1C, NV_RD32(chip->PFB, 0x0000025C));
+ NV_WR32(chip->PGRAPH, 0x00000B20, NV_RD32(chip->PFB, 0x00000260));
+ NV_WR32(chip->PGRAPH, 0x00000B24, NV_RD32(chip->PFB, 0x00000264));
+ NV_WR32(chip->PGRAPH, 0x00000B28, NV_RD32(chip->PFB, 0x00000268));
+ NV_WR32(chip->PGRAPH, 0x00000B2C, NV_RD32(chip->PFB, 0x0000026C));
+ NV_WR32(chip->PGRAPH, 0x00000B30, NV_RD32(chip->PFB, 0x00000270));
+ NV_WR32(chip->PGRAPH, 0x00000B34, NV_RD32(chip->PFB, 0x00000274));
+ NV_WR32(chip->PGRAPH, 0x00000B38, NV_RD32(chip->PFB, 0x00000278));
+ NV_WR32(chip->PGRAPH, 0x00000B3C, NV_RD32(chip->PFB, 0x0000027C));
+ NV_WR32(chip->PGRAPH, 0x00000B40, NV_RD32(chip->PFB, 0x00000280));
+ NV_WR32(chip->PGRAPH, 0x00000B44, NV_RD32(chip->PFB, 0x00000284));
+ NV_WR32(chip->PGRAPH, 0x00000B48, NV_RD32(chip->PFB, 0x00000288));
+ NV_WR32(chip->PGRAPH, 0x00000B4C, NV_RD32(chip->PFB, 0x0000028C));
+ NV_WR32(chip->PGRAPH, 0x00000B50, NV_RD32(chip->PFB, 0x00000290));
+ NV_WR32(chip->PGRAPH, 0x00000B54, NV_RD32(chip->PFB, 0x00000294));
+ NV_WR32(chip->PGRAPH, 0x00000B58, NV_RD32(chip->PFB, 0x00000298));
+ NV_WR32(chip->PGRAPH, 0x00000B5C, NV_RD32(chip->PFB, 0x0000029C));
+ NV_WR32(chip->PGRAPH, 0x00000B60, NV_RD32(chip->PFB, 0x000002A0));
+ NV_WR32(chip->PGRAPH, 0x00000B64, NV_RD32(chip->PFB, 0x000002A4));
+ NV_WR32(chip->PGRAPH, 0x00000B68, NV_RD32(chip->PFB, 0x000002A8));
+ NV_WR32(chip->PGRAPH, 0x00000B6C, NV_RD32(chip->PFB, 0x000002AC));
+ NV_WR32(chip->PGRAPH, 0x00000B70, NV_RD32(chip->PFB, 0x000002B0));
+ NV_WR32(chip->PGRAPH, 0x00000B74, NV_RD32(chip->PFB, 0x000002B4));
+ NV_WR32(chip->PGRAPH, 0x00000B78, NV_RD32(chip->PFB, 0x000002B8));
+ NV_WR32(chip->PGRAPH, 0x00000B7C, NV_RD32(chip->PFB, 0x000002BC));
+ NV_WR32(chip->PGRAPH, 0x00000F40, 0x10000000);
+ NV_WR32(chip->PGRAPH, 0x00000F44, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000008);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000200);
+ for (i = 0; i < (3*16); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000800);
+ for (i = 0; i < (16*16); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F40, 0x30000000);
+ NV_WR32(chip->PGRAPH, 0x00000F44, 0x00000004);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006400);
+ for (i = 0; i < (59*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006800);
+ for (i = 0; i < (47*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00006C00);
+ for (i = 0; i < (3*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007000);
+ for (i = 0; i < (19*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007400);
+ for (i = 0; i < (12*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00007800);
+ for (i = 0; i < (12*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00004400);
+ for (i = 0; i < (8*4); i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000000);
+ for (i = 0; i < 16; i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+ NV_WR32(chip->PGRAPH, 0x00000F50, 0x00000040);
+ for (i = 0; i < 4; i++)
+ NV_WR32(chip->PGRAPH, 0x00000F54, 0x00000000);
+
+ NV_WR32(chip->PCRTC, 0x00000810, state->cursorConfig);
+
+ if(chip->flatPanel) {
+ if((chip->Chipset & 0x0ff0) == 0x0110) {
+ NV_WR32(chip->PRAMDAC, 0x0528, state->dither);
+ } else
+ if((chip->Chipset & 0x0ff0) >= 0x0170) {
+ NV_WR32(chip->PRAMDAC, 0x083C, state->dither);
+ }
+
+ VGA_WR08(chip->PCIO, 0x03D4, 0x53);
+ VGA_WR08(chip->PCIO, 0x03D5, 0);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x54);
+ VGA_WR08(chip->PCIO, 0x03D5, 0);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x21);
+ VGA_WR08(chip->PCIO, 0x03D5, 0xfa);
+ }
+
+ VGA_WR08(chip->PCIO, 0x03D4, 0x41);
+ VGA_WR08(chip->PCIO, 0x03D5, state->extra);
+ }
+ LOAD_FIXED_STATE(Riva,FIFO);
+ UpdateFifoState(chip);
+ /*
+ * Load HW mode state.
+ */
+ VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+ VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+ VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+ VGA_WR08(chip->PCIO, 0x03D5, state->screen);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+ VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+ VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+ VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+ VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+ VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+ VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
+ VGA_WR08(chip->PCIO, 0x03D5, state->cursor2);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x39);
+ VGA_WR08(chip->PCIO, 0x03D5, state->interlace);
+
+ if(!chip->flatPanel) {
+ NV_WR32(chip->PRAMDAC0, 0x00000508, state->vpll);
+ NV_WR32(chip->PRAMDAC0, 0x0000050C, state->pllsel);
+ if(chip->twoHeads)
+ NV_WR32(chip->PRAMDAC0, 0x00000520, state->vpll2);
+ } else {
+ NV_WR32(chip->PRAMDAC, 0x00000848 , state->scale);
+ }
+ NV_WR32(chip->PRAMDAC, 0x00000600 , state->general);
+
+ /*
+ * Turn off VBlank enable and reset.
+ */
+ NV_WR32(chip->PCRTC, 0x00000140, 0);
+ NV_WR32(chip->PCRTC, 0x00000100, chip->VBlankBit);
+ /*
+ * Set interrupt enable.
+ */
+ NV_WR32(chip->PMC, 0x00000140, chip->EnableIRQ & 0x01);
+ /*
+ * Set current state pointer.
+ */
+ chip->CurrentState = state;
+ /*
+ * Reset FIFO free and empty counts.
+ */
+ chip->FifoFreeCount = 0;
+ /* Free count from first subchannel */
+ chip->FifoEmptyCount = NV_RD32(&chip->Rop->FifoFree, 0);
+}
+static void UnloadStateExt
+(
+ RIVA_HW_INST *chip,
+ RIVA_HW_STATE *state
+)
+{
+ /*
+ * Save current HW state.
+ */
+ VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+ state->repaint0 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+ state->repaint1 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+ state->screen = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+ state->pixel = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+ state->horiz = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+ state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+ state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+ state->cursor0 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+ state->cursor1 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
+ state->cursor2 = VGA_RD08(chip->PCIO, 0x03D5);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x39);
+ state->interlace = VGA_RD08(chip->PCIO, 0x03D5);
+ state->vpll = NV_RD32(chip->PRAMDAC0, 0x00000508);
+ state->vpll2 = NV_RD32(chip->PRAMDAC0, 0x00000520);
+ state->pllsel = NV_RD32(chip->PRAMDAC0, 0x0000050C);
+ state->general = NV_RD32(chip->PRAMDAC, 0x00000600);
+ state->scale = NV_RD32(chip->PRAMDAC, 0x00000848);
+ state->config = NV_RD32(chip->PFB, 0x00000200);
+ switch (chip->Architecture)
+ {
+ case NV_ARCH_03:
+ state->offset0 = NV_RD32(chip->PGRAPH, 0x00000630);
+ state->offset1 = NV_RD32(chip->PGRAPH, 0x00000634);
+ state->offset2 = NV_RD32(chip->PGRAPH, 0x00000638);
+ state->offset3 = NV_RD32(chip->PGRAPH, 0x0000063C);
+ state->pitch0 = NV_RD32(chip->PGRAPH, 0x00000650);
+ state->pitch1 = NV_RD32(chip->PGRAPH, 0x00000654);
+ state->pitch2 = NV_RD32(chip->PGRAPH, 0x00000658);
+ state->pitch3 = NV_RD32(chip->PGRAPH, 0x0000065C);
+ break;
+ case NV_ARCH_04:
+ state->offset0 = NV_RD32(chip->PGRAPH, 0x00000640);
+ state->offset1 = NV_RD32(chip->PGRAPH, 0x00000644);
+ state->offset2 = NV_RD32(chip->PGRAPH, 0x00000648);
+ state->offset3 = NV_RD32(chip->PGRAPH, 0x0000064C);
+ state->pitch0 = NV_RD32(chip->PGRAPH, 0x00000670);
+ state->pitch1 = NV_RD32(chip->PGRAPH, 0x00000674);
+ state->pitch2 = NV_RD32(chip->PGRAPH, 0x00000678);
+ state->pitch3 = NV_RD32(chip->PGRAPH, 0x0000067C);
+ break;
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ state->offset0 = NV_RD32(chip->PGRAPH, 0x00000640);
+ state->offset1 = NV_RD32(chip->PGRAPH, 0x00000644);
+ state->offset2 = NV_RD32(chip->PGRAPH, 0x00000648);
+ state->offset3 = NV_RD32(chip->PGRAPH, 0x0000064C);
+ state->pitch0 = NV_RD32(chip->PGRAPH, 0x00000670);
+ state->pitch1 = NV_RD32(chip->PGRAPH, 0x00000674);
+ state->pitch2 = NV_RD32(chip->PGRAPH, 0x00000678);
+ state->pitch3 = NV_RD32(chip->PGRAPH, 0x0000067C);
+ if(chip->twoHeads) {
+ state->head = NV_RD32(chip->PCRTC0, 0x00000860);
+ state->head2 = NV_RD32(chip->PCRTC0, 0x00002860);
+ VGA_WR08(chip->PCIO, 0x03D4, 0x44);
+ state->crtcOwner = VGA_RD08(chip->PCIO, 0x03D5);
+ }
+ VGA_WR08(chip->PCIO, 0x03D4, 0x41);
+ state->extra = VGA_RD08(chip->PCIO, 0x03D5);
+ state->cursorConfig = NV_RD32(chip->PCRTC, 0x00000810);
+
+ if((chip->Chipset & 0x0ff0) == 0x0110) {
+ state->dither = NV_RD32(chip->PRAMDAC, 0x0528);
+ } else
+ if((chip->Chipset & 0x0ff0) >= 0x0170) {
+ state->dither = NV_RD32(chip->PRAMDAC, 0x083C);
+ }
+ break;
+ }
+}
+static void SetStartAddress
+(
+ RIVA_HW_INST *chip,
+ unsigned start
+)
+{
+ NV_WR32(chip->PCRTC, 0x800, start);
+}
+
+static void SetStartAddress3
+(
+ RIVA_HW_INST *chip,
+ unsigned start
+)
+{
+ int offset = start >> 2;
+ int pan = (start & 3) << 1;
+ unsigned char tmp;
+
+ /*
+ * Unlock extended registers.
+ */
+ chip->LockUnlock(chip, 0);
+ /*
+ * Set start address.
+ */
+ VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
+ offset >>= 8;
+ VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
+ offset >>= 8;
+ VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+ VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
+ VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+ VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
+ /*
+ * 4 pixel pan register.
+ */
+ offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
+ VGA_WR08(chip->PCIO, 0x3C0, 0x13);
+ VGA_WR08(chip->PCIO, 0x3C0, pan);
+}
+static void nv3SetSurfaces2D
+(
+ RIVA_HW_INST *chip,
+ unsigned surf0,
+ unsigned surf1
+)
+{
+ RivaSurface __iomem *Surface =
+ (RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+ RIVA_FIFO_FREE(*chip,Tri03,5);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
+ NV_WR32(&Surface->Offset, 0, surf0);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
+ NV_WR32(&Surface->Offset, 0, surf1);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000013);
+}
+static void nv4SetSurfaces2D
+(
+ RIVA_HW_INST *chip,
+ unsigned surf0,
+ unsigned surf1
+)
+{
+ RivaSurface __iomem *Surface =
+ (RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
+ NV_WR32(&Surface->Offset, 0, surf0);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
+ NV_WR32(&Surface->Offset, 0, surf1);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+static void nv10SetSurfaces2D
+(
+ RIVA_HW_INST *chip,
+ unsigned surf0,
+ unsigned surf1
+)
+{
+ RivaSurface __iomem *Surface =
+ (RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000003);
+ NV_WR32(&Surface->Offset, 0, surf0);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000004);
+ NV_WR32(&Surface->Offset, 0, surf1);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+static void nv3SetSurfaces3D
+(
+ RIVA_HW_INST *chip,
+ unsigned surf0,
+ unsigned surf1
+)
+{
+ RivaSurface __iomem *Surface =
+ (RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+ RIVA_FIFO_FREE(*chip,Tri03,5);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000005);
+ NV_WR32(&Surface->Offset, 0, surf0);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000006);
+ NV_WR32(&Surface->Offset, 0, surf1);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000013);
+}
+static void nv4SetSurfaces3D
+(
+ RIVA_HW_INST *chip,
+ unsigned surf0,
+ unsigned surf1
+)
+{
+ RivaSurface __iomem *Surface =
+ (RivaSurface __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000005);
+ NV_WR32(&Surface->Offset, 0, surf0);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000006);
+ NV_WR32(&Surface->Offset, 0, surf1);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+static void nv10SetSurfaces3D
+(
+ RIVA_HW_INST *chip,
+ unsigned surf0,
+ unsigned surf1
+)
+{
+ RivaSurface3D __iomem *Surfaces3D =
+ (RivaSurface3D __iomem *)&(chip->FIFO[0x0000E000/4]);
+
+ RIVA_FIFO_FREE(*chip,Tri03,4);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000007);
+ NV_WR32(&Surfaces3D->RenderBufferOffset, 0, surf0);
+ NV_WR32(&Surfaces3D->ZBufferOffset, 0, surf1);
+ NV_WR32(&chip->FIFO[0x00003800], 0, 0x80000014);
+}
+
+/****************************************************************************\
+* *
+* Probe RIVA Chip Configuration *
+* *
+\****************************************************************************/
+
+static void nv3GetConfig
+(
+ RIVA_HW_INST *chip
+)
+{
+ /*
+ * Fill in chip configuration.
+ */
+ if (NV_RD32(&chip->PFB[0x00000000/4], 0) & 0x00000020)
+ {
+ if (((NV_RD32(chip->PMC, 0x00000000) & 0xF0) == 0x20)
+ && ((NV_RD32(chip->PMC, 0x00000000) & 0x0F) >= 0x02))
+ {
+ /*
+ * SDRAM 128 ZX.
+ */
+ chip->RamBandwidthKBytesPerSec = 800000;
+ switch (NV_RD32(chip->PFB, 0x00000000) & 0x03)
+ {
+ case 2:
+ chip->RamAmountKBytes = 1024 * 4;
+ break;
+ case 1:
+ chip->RamAmountKBytes = 1024 * 2;
+ break;
+ default:
+ chip->RamAmountKBytes = 1024 * 8;
+ break;
+ }
+ }
+ else
+ {
+ chip->RamBandwidthKBytesPerSec = 1000000;
+ chip->RamAmountKBytes = 1024 * 8;
+ }
+ }
+ else
+ {
+ /*
+ * SGRAM 128.
+ */
+ chip->RamBandwidthKBytesPerSec = 1000000;
+ switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003)
+ {
+ case 0:
+ chip->RamAmountKBytes = 1024 * 8;
+ break;
+ case 2:
+ chip->RamAmountKBytes = 1024 * 4;
+ break;
+ default:
+ chip->RamAmountKBytes = 1024 * 2;
+ break;
+ }
+ }
+ chip->CrystalFreqKHz = (NV_RD32(chip->PEXTDEV, 0x00000000) & 0x00000040) ? 14318 : 13500;
+ chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
+ chip->VBlankBit = 0x00000100;
+ chip->MaxVClockFreqKHz = 256000;
+ /*
+ * Set chip functions.
+ */
+ chip->Busy = nv3Busy;
+ chip->ShowHideCursor = ShowHideCursor;
+ chip->LoadStateExt = LoadStateExt;
+ chip->UnloadStateExt = UnloadStateExt;
+ chip->SetStartAddress = SetStartAddress3;
+ chip->SetSurfaces2D = nv3SetSurfaces2D;
+ chip->SetSurfaces3D = nv3SetSurfaces3D;
+ chip->LockUnlock = nv3LockUnlock;
+}
+static void nv4GetConfig
+(
+ RIVA_HW_INST *chip
+)
+{
+ /*
+ * Fill in chip configuration.
+ */
+ if (NV_RD32(chip->PFB, 0x00000000) & 0x00000100)
+ {
+ chip->RamAmountKBytes = ((NV_RD32(chip->PFB, 0x00000000) >> 12) & 0x0F) * 1024 * 2
+ + 1024 * 2;
+ }
+ else
+ {
+ switch (NV_RD32(chip->PFB, 0x00000000) & 0x00000003)
+ {
+ case 0:
+ chip->RamAmountKBytes = 1024 * 32;
+ break;
+ case 1:
+ chip->RamAmountKBytes = 1024 * 4;
+ break;
+ case 2:
+ chip->RamAmountKBytes = 1024 * 8;
+ break;
+ case 3:
+ default:
+ chip->RamAmountKBytes = 1024 * 16;
+ break;
+ }
+ }
+ switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003)
+ {
+ case 3:
+ chip->RamBandwidthKBytesPerSec = 800000;
+ break;
+ default:
+ chip->RamBandwidthKBytesPerSec = 1000000;
+ break;
+ }
+ chip->CrystalFreqKHz = (NV_RD32(chip->PEXTDEV, 0x00000000) & 0x00000040) ? 14318 : 13500;
+ chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
+ chip->VBlankBit = 0x00000001;
+ chip->MaxVClockFreqKHz = 350000;
+ /*
+ * Set chip functions.
+ */
+ chip->Busy = nv4Busy;
+ chip->ShowHideCursor = ShowHideCursor;
+ chip->LoadStateExt = LoadStateExt;
+ chip->UnloadStateExt = UnloadStateExt;
+ chip->SetStartAddress = SetStartAddress;
+ chip->SetSurfaces2D = nv4SetSurfaces2D;
+ chip->SetSurfaces3D = nv4SetSurfaces3D;
+ chip->LockUnlock = nv4LockUnlock;
+}
+static void nv10GetConfig
+(
+ RIVA_HW_INST *chip,
+ unsigned int chipset
+)
+{
+ struct pci_dev* dev;
+ u32 amt;
+
+#ifdef __BIG_ENDIAN
+ /* turn on big endian register access */
+ if(!(NV_RD32(chip->PMC, 0x00000004) & 0x01000001))
+ NV_WR32(chip->PMC, 0x00000004, 0x01000001);
+#endif
+
+ /*
+ * Fill in chip configuration.
+ */
+ if(chipset == NV_CHIP_IGEFORCE2) {
+ dev = pci_get_bus_and_slot(0, 1);
+ pci_read_config_dword(dev, 0x7C, &amt);
+ pci_dev_put(dev);
+ chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+ } else if(chipset == NV_CHIP_0x01F0) {
+ dev = pci_get_bus_and_slot(0, 1);
+ pci_read_config_dword(dev, 0x84, &amt);
+ pci_dev_put(dev);
+ chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+ } else {
+ switch ((NV_RD32(chip->PFB, 0x0000020C) >> 20) & 0x000000FF)
+ {
+ case 0x02:
+ chip->RamAmountKBytes = 1024 * 2;
+ break;
+ case 0x04:
+ chip->RamAmountKBytes = 1024 * 4;
+ break;
+ case 0x08:
+ chip->RamAmountKBytes = 1024 * 8;
+ break;
+ case 0x10:
+ chip->RamAmountKBytes = 1024 * 16;
+ break;
+ case 0x20:
+ chip->RamAmountKBytes = 1024 * 32;
+ break;
+ case 0x40:
+ chip->RamAmountKBytes = 1024 * 64;
+ break;
+ case 0x80:
+ chip->RamAmountKBytes = 1024 * 128;
+ break;
+ default:
+ chip->RamAmountKBytes = 1024 * 16;
+ break;
+ }
+ }
+ switch ((NV_RD32(chip->PFB, 0x00000000) >> 3) & 0x00000003)
+ {
+ case 3:
+ chip->RamBandwidthKBytesPerSec = 800000;
+ break;
+ default:
+ chip->RamBandwidthKBytesPerSec = 1000000;
+ break;
+ }
+ chip->CrystalFreqKHz = (NV_RD32(chip->PEXTDEV, 0x0000) & (1 << 6)) ?
+ 14318 : 13500;
+
+ switch (chipset & 0x0ff0) {
+ case 0x0170:
+ case 0x0180:
+ case 0x01F0:
+ case 0x0250:
+ case 0x0280:
+ case 0x0300:
+ case 0x0310:
+ case 0x0320:
+ case 0x0330:
+ case 0x0340:
+ if(NV_RD32(chip->PEXTDEV, 0x0000) & (1 << 22))
+ chip->CrystalFreqKHz = 27000;
+ break;
+ default:
+ break;
+ }
+
+ chip->CursorStart = (chip->RamAmountKBytes - 128) * 1024;
+ chip->CURSOR = NULL; /* can't set this here */
+ chip->VBlankBit = 0x00000001;
+ chip->MaxVClockFreqKHz = 350000;
+ /*
+ * Set chip functions.
+ */
+ chip->Busy = nv10Busy;
+ chip->ShowHideCursor = ShowHideCursor;
+ chip->LoadStateExt = LoadStateExt;
+ chip->UnloadStateExt = UnloadStateExt;
+ chip->SetStartAddress = SetStartAddress;
+ chip->SetSurfaces2D = nv10SetSurfaces2D;
+ chip->SetSurfaces3D = nv10SetSurfaces3D;
+ chip->LockUnlock = nv4LockUnlock;
+
+ switch(chipset & 0x0ff0) {
+ case 0x0110:
+ case 0x0170:
+ case 0x0180:
+ case 0x01F0:
+ case 0x0250:
+ case 0x0280:
+ case 0x0300:
+ case 0x0310:
+ case 0x0320:
+ case 0x0330:
+ case 0x0340:
+ chip->twoHeads = TRUE;
+ break;
+ default:
+ chip->twoHeads = FALSE;
+ break;
+ }
+}
+int RivaGetConfig
+(
+ RIVA_HW_INST *chip,
+ unsigned int chipset
+)
+{
+ /*
+ * Save this so future SW know whats it's dealing with.
+ */
+ chip->Version = RIVA_SW_VERSION;
+ /*
+ * Chip specific configuration.
+ */
+ switch (chip->Architecture)
+ {
+ case NV_ARCH_03:
+ nv3GetConfig(chip);
+ break;
+ case NV_ARCH_04:
+ nv4GetConfig(chip);
+ break;
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ nv10GetConfig(chip, chipset);
+ break;
+ default:
+ return (-1);
+ }
+ chip->Chipset = chipset;
+ /*
+ * Fill in FIFO pointers.
+ */
+ chip->Rop = (RivaRop __iomem *)&(chip->FIFO[0x00000000/4]);
+ chip->Clip = (RivaClip __iomem *)&(chip->FIFO[0x00002000/4]);
+ chip->Patt = (RivaPattern __iomem *)&(chip->FIFO[0x00004000/4]);
+ chip->Pixmap = (RivaPixmap __iomem *)&(chip->FIFO[0x00006000/4]);
+ chip->Blt = (RivaScreenBlt __iomem *)&(chip->FIFO[0x00008000/4]);
+ chip->Bitmap = (RivaBitmap __iomem *)&(chip->FIFO[0x0000A000/4]);
+ chip->Line = (RivaLine __iomem *)&(chip->FIFO[0x0000C000/4]);
+ chip->Tri03 = (RivaTexturedTriangle03 __iomem *)&(chip->FIFO[0x0000E000/4]);
+ return (0);
+}
+
diff --git a/drivers/video/fbdev/riva/riva_hw.h b/drivers/video/fbdev/riva/riva_hw.h
new file mode 100644
index 000000000000..c2769f73e0b2
--- /dev/null
+++ b/drivers/video/fbdev/riva/riva_hw.h
@@ -0,0 +1,563 @@
+/***************************************************************************\
+|* *|
+|* Copyright 1993-1999 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 -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.21 2002/10/14 18:22:46 mvojkovi Exp $ */
+#ifndef __RIVA_HW_H__
+#define __RIVA_HW_H__
+#define RIVA_SW_VERSION 0x00010003
+
+#ifndef Bool
+typedef int Bool;
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * Typedefs to force certain sized values.
+ */
+typedef unsigned char U008;
+typedef unsigned short U016;
+typedef unsigned int U032;
+
+/*
+ * HW access macros.
+ */
+#include <asm/io.h>
+
+#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)))
+
+#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
+#define VGA_RD08(p,i) (readb((void __iomem *)(p) + (i)))
+
+/*
+ * Define different architectures.
+ */
+#define NV_ARCH_03 0x03
+#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
+
+/***************************************************************************\
+* *
+* FIFO registers. *
+* *
+\***************************************************************************/
+
+/*
+ * Raster OPeration. Windows style ROP3.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BB];
+ U032 Rop3;
+} RivaRop;
+/*
+ * 8X8 Monochrome pattern.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BD];
+ U032 Shape;
+ U032 reserved03[0x001];
+ U032 Color0;
+ U032 Color1;
+ U032 Monochrome[2];
+} RivaPattern;
+/*
+ * Scissor clip rectangle.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BB];
+ U032 TopLeft;
+ U032 WidthHeight;
+} RivaClip;
+/*
+ * 2D filled rectangle.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop[1];
+#endif
+ U032 reserved01[0x0BC];
+ U032 Color;
+ U032 reserved03[0x03E];
+ U032 TopLeft;
+ U032 WidthHeight;
+} RivaRectangle;
+/*
+ * 2D screen-screen BLT.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BB];
+ U032 TopLeftSrc;
+ U032 TopLeftDst;
+ U032 WidthHeight;
+} RivaScreenBlt;
+/*
+ * 2D pixel BLT.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop[1];
+#endif
+ U032 reserved01[0x0BC];
+ U032 TopLeft;
+ U032 WidthHeight;
+ U032 WidthHeightIn;
+ U032 reserved02[0x03C];
+ U032 Pixels;
+} RivaPixmap;
+/*
+ * Filled rectangle combined with monochrome expand. Useful for glyphs.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BB];
+ U032 reserved03[(0x040)-1];
+ U032 Color1A;
+ struct
+ {
+ U032 TopLeft;
+ U032 WidthHeight;
+ } UnclippedRectangle[64];
+ U032 reserved04[(0x080)-3];
+ struct
+ {
+ U032 TopLeft;
+ U032 BottomRight;
+ } ClipB;
+ U032 Color1B;
+ struct
+ {
+ U032 TopLeft;
+ U032 BottomRight;
+ } ClippedRectangle[64];
+ U032 reserved05[(0x080)-5];
+ struct
+ {
+ U032 TopLeft;
+ U032 BottomRight;
+ } ClipC;
+ U032 Color1C;
+ U032 WidthHeightC;
+ U032 PointC;
+ U032 MonochromeData1C;
+ U032 reserved06[(0x080)+121];
+ struct
+ {
+ U032 TopLeft;
+ U032 BottomRight;
+ } ClipD;
+ U032 Color1D;
+ U032 WidthHeightInD;
+ U032 WidthHeightOutD;
+ U032 PointD;
+ U032 MonochromeData1D;
+ U032 reserved07[(0x080)+120];
+ struct
+ {
+ U032 TopLeft;
+ U032 BottomRight;
+ } ClipE;
+ U032 Color0E;
+ U032 Color1E;
+ U032 WidthHeightInE;
+ U032 WidthHeightOutE;
+ U032 PointE;
+ U032 MonochromeData01E;
+} RivaBitmap;
+/*
+ * 3D textured, Z buffered triangle.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BC];
+ U032 TextureOffset;
+ U032 TextureFormat;
+ U032 TextureFilter;
+ U032 FogColor;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+ U032 Control;
+ U032 AlphaTest;
+ U032 reserved02[0x339];
+ U032 FogAndIndex;
+ U032 Color;
+ float ScreenX;
+ float ScreenY;
+ float ScreenZ;
+ float EyeM;
+ float TextureS;
+ float TextureT;
+} RivaTexturedTriangle03;
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BB];
+ U032 ColorKey;
+ U032 TextureOffset;
+ U032 TextureFormat;
+ U032 TextureFilter;
+ U032 Blend;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+ U032 Control;
+ U032 FogColor;
+ U032 reserved02[0x39];
+ struct
+ {
+ float ScreenX;
+ float ScreenY;
+ float ScreenZ;
+ float EyeM;
+ U032 Color;
+ U032 Specular;
+ float TextureS;
+ float TextureT;
+ } Vertex[16];
+ U032 DrawTriangle3D;
+} RivaTexturedTriangle05;
+/*
+ * 2D line.
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop[1];
+#endif
+ U032 reserved01[0x0BC];
+ U032 Color; /* source color 0304-0307*/
+ U032 Reserved02[0x03e];
+ struct { /* start aliased methods in array 0400- */
+ U032 point0; /* y_x S16_S16 in pixels 0- 3*/
+ U032 point1; /* y_x S16_S16 in pixels 4- 7*/
+ } Lin[16]; /* end of aliased methods in array -047f*/
+ struct { /* start aliased methods in array 0480- */
+ U032 point0X; /* in pixels, 0 at left 0- 3*/
+ U032 point0Y; /* in pixels, 0 at top 4- 7*/
+ U032 point1X; /* in pixels, 0 at left 8- b*/
+ U032 point1Y; /* in pixels, 0 at top c- f*/
+ } Lin32[8]; /* end of aliased methods in array -04ff*/
+ U032 PolyLin[32]; /* y_x S16_S16 in pixels 0500-057f*/
+ struct { /* start aliased methods in array 0580- */
+ U032 x; /* in pixels, 0 at left 0- 3*/
+ U032 y; /* in pixels, 0 at top 4- 7*/
+ } PolyLin32[16]; /* end of aliased methods in array -05ff*/
+ struct { /* start aliased methods in array 0600- */
+ U032 color; /* source color 0- 3*/
+ U032 point; /* y_x S16_S16 in pixels 4- 7*/
+ } ColorPolyLin[16]; /* end of aliased methods in array -067f*/
+} RivaLine;
+/*
+ * 2D/3D surfaces
+ */
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BE];
+ U032 Offset;
+} RivaSurface;
+typedef volatile struct
+{
+ U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+ U032 FifoFree;
+#else
+ U016 FifoFree;
+ U016 Nop;
+#endif
+ U032 reserved01[0x0BD];
+ U032 Pitch;
+ U032 RenderBufferOffset;
+ U032 ZBufferOffset;
+} RivaSurface3D;
+
+/***************************************************************************\
+* *
+* Virtualized RIVA H/W interface. *
+* *
+\***************************************************************************/
+
+#define FP_ENABLE 1
+#define FP_DITHER 2
+
+struct _riva_hw_inst;
+struct _riva_hw_state;
+/*
+ * Virtialized chip interface. Makes RIVA 128 and TNT look alike.
+ */
+typedef struct _riva_hw_inst
+{
+ /*
+ * Chip specific settings.
+ */
+ U032 Architecture;
+ U032 Version;
+ U032 Chipset;
+ U032 CrystalFreqKHz;
+ U032 RamAmountKBytes;
+ U032 MaxVClockFreqKHz;
+ U032 RamBandwidthKBytesPerSec;
+ U032 EnableIRQ;
+ U032 IO;
+ U032 VBlankBit;
+ U032 FifoFreeCount;
+ U032 FifoEmptyCount;
+ U032 CursorStart;
+ U032 flatPanel;
+ Bool twoHeads;
+ /*
+ * Non-FIFO registers.
+ */
+ volatile U032 __iomem *PCRTC0;
+ volatile U032 __iomem *PCRTC;
+ volatile U032 __iomem *PRAMDAC0;
+ volatile U032 __iomem *PFB;
+ volatile U032 __iomem *PFIFO;
+ volatile U032 __iomem *PGRAPH;
+ volatile U032 __iomem *PEXTDEV;
+ volatile U032 __iomem *PTIMER;
+ volatile U032 __iomem *PMC;
+ volatile U032 __iomem *PRAMIN;
+ volatile U032 __iomem *FIFO;
+ volatile U032 __iomem *CURSOR;
+ volatile U008 __iomem *PCIO0;
+ volatile U008 __iomem *PCIO;
+ volatile U008 __iomem *PVIO;
+ volatile U008 __iomem *PDIO0;
+ volatile U008 __iomem *PDIO;
+ volatile U032 __iomem *PRAMDAC;
+ /*
+ * Common chip functions.
+ */
+ int (*Busy)(struct _riva_hw_inst *);
+ void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
+ void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
+ void (*SetStartAddress)(struct _riva_hw_inst *,U032);
+ void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032);
+ void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032);
+ int (*ShowHideCursor)(struct _riva_hw_inst *,int);
+ void (*LockUnlock)(struct _riva_hw_inst *, int);
+ /*
+ * Current extended mode settings.
+ */
+ struct _riva_hw_state *CurrentState;
+ /*
+ * FIFO registers.
+ */
+ RivaRop __iomem *Rop;
+ RivaPattern __iomem *Patt;
+ RivaClip __iomem *Clip;
+ RivaPixmap __iomem *Pixmap;
+ RivaScreenBlt __iomem *Blt;
+ RivaBitmap __iomem *Bitmap;
+ RivaLine __iomem *Line;
+ RivaTexturedTriangle03 __iomem *Tri03;
+ RivaTexturedTriangle05 __iomem *Tri05;
+} RIVA_HW_INST;
+/*
+ * Extended mode state information.
+ */
+typedef struct _riva_hw_state
+{
+ U032 bpp;
+ U032 width;
+ U032 height;
+ U032 interlace;
+ U032 repaint0;
+ U032 repaint1;
+ U032 screen;
+ U032 scale;
+ U032 dither;
+ U032 extra;
+ U032 pixel;
+ U032 horiz;
+ U032 arbitration0;
+ U032 arbitration1;
+ U032 vpll;
+ U032 vpll2;
+ U032 pllsel;
+ U032 general;
+ U032 crtcOwner;
+ U032 head;
+ U032 head2;
+ U032 config;
+ U032 cursorConfig;
+ U032 cursor0;
+ U032 cursor1;
+ U032 cursor2;
+ U032 offset0;
+ U032 offset1;
+ U032 offset2;
+ U032 offset3;
+ U032 pitch0;
+ U032 pitch1;
+ U032 pitch2;
+ U032 pitch3;
+} RIVA_HW_STATE;
+
+/*
+ * function prototypes
+ */
+
+extern int CalcStateExt
+(
+ RIVA_HW_INST *chip,
+ RIVA_HW_STATE *state,
+ int bpp,
+ int width,
+ int hDisplaySize,
+ int height,
+ int dotClock
+);
+
+/*
+ * External routines.
+ */
+int RivaGetConfig(RIVA_HW_INST *, unsigned int);
+/*
+ * FIFO Free Count. Should attempt to yield processor if RIVA is busy.
+ */
+
+#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \
+{ \
+ while ((hwinst).FifoFreeCount < (cnt)) { \
+ mb();mb(); \
+ (hwinst).FifoFreeCount = NV_RD32(&(hwinst).hwptr->FifoFree, 0) >> 2; \
+ } \
+ (hwinst).FifoFreeCount -= (cnt); \
+}
+#endif /* __RIVA_HW_H__ */
+
diff --git a/drivers/video/fbdev/riva/riva_tbl.h b/drivers/video/fbdev/riva/riva_tbl.h
new file mode 100644
index 000000000000..7ee7d72932d4
--- /dev/null
+++ b/drivers/video/fbdev/riva/riva_tbl.h
@@ -0,0 +1,1008 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 1993-1999 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 -- nVidia is allowing a liberal interpretation of
+ * the documentation restriction above, to merely say that this nVidia's
+ * copyright and disclaimer should be included with all code derived
+ * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.9 2002/01/30 01:35:03 mvojkovi Exp $ */
+
+
+/*
+ * RIVA Fixed Functionality Init Tables.
+ */
+static unsigned RivaTablePMC[][2] =
+{
+ {0x00000050, 0x00000000},
+ {0x00000080, 0xFFFF00FF},
+ {0x00000080, 0xFFFFFFFF}
+};
+static unsigned RivaTablePTIMER[][2] =
+{
+ {0x00000080, 0x00000008},
+ {0x00000084, 0x00000003},
+ {0x00000050, 0x00000000},
+ {0x00000040, 0xFFFFFFFF}
+};
+static unsigned RivaTableFIFO[][2] =
+{
+ {0x00000000, 0x80000000},
+ {0x00000800, 0x80000001},
+ {0x00001000, 0x80000002},
+ {0x00001800, 0x80000010},
+ {0x00002000, 0x80000011},
+ {0x00002800, 0x80000012},
+ {0x00003000, 0x80000016},
+ {0x00003800, 0x80000013}
+};
+static unsigned nv3TablePFIFO[][2] =
+{
+ {0x00000140, 0x00000000},
+ {0x00000480, 0x00000000},
+ {0x00000490, 0x00000000},
+ {0x00000494, 0x00000000},
+ {0x00000481, 0x00000000},
+ {0x00000084, 0x00000000},
+ {0x00000086, 0x00002000},
+ {0x00000085, 0x00002200},
+ {0x00000484, 0x00000000},
+ {0x0000049C, 0x00000000},
+ {0x00000104, 0x00000000},
+ {0x00000108, 0x00000000},
+ {0x00000100, 0x00000000},
+ {0x000004A0, 0x00000000},
+ {0x000004A4, 0x00000000},
+ {0x000004A8, 0x00000000},
+ {0x000004AC, 0x00000000},
+ {0x000004B0, 0x00000000},
+ {0x000004B4, 0x00000000},
+ {0x000004B8, 0x00000000},
+ {0x000004BC, 0x00000000},
+ {0x00000050, 0x00000000},
+ {0x00000040, 0xFFFFFFFF},
+ {0x00000480, 0x00000001},
+ {0x00000490, 0x00000001},
+ {0x00000140, 0x00000001}
+};
+static unsigned nv3TablePGRAPH[][2] =
+{
+ {0x00000020, 0x1230001F},
+ {0x00000021, 0x10113000},
+ {0x00000022, 0x1131F101},
+ {0x00000023, 0x0100F531},
+ {0x00000060, 0x00000000},
+ {0x00000065, 0x00000000},
+ {0x00000068, 0x00000000},
+ {0x00000069, 0x00000000},
+ {0x0000006A, 0x00000000},
+ {0x0000006B, 0x00000000},
+ {0x0000006C, 0x00000000},
+ {0x0000006D, 0x00000000},
+ {0x0000006E, 0x00000000},
+ {0x0000006F, 0x00000000},
+ {0x000001A8, 0x00000000},
+ {0x00000440, 0xFFFFFFFF},
+ {0x00000480, 0x00000001},
+ {0x000001A0, 0x00000000},
+ {0x000001A2, 0x00000000},
+ {0x0000018A, 0xFFFFFFFF},
+ {0x00000190, 0x00000000},
+ {0x00000142, 0x00000000},
+ {0x00000154, 0x00000000},
+ {0x00000155, 0xFFFFFFFF},
+ {0x00000156, 0x00000000},
+ {0x00000157, 0xFFFFFFFF},
+ {0x00000064, 0x10010002},
+ {0x00000050, 0x00000000},
+ {0x00000051, 0x00000000},
+ {0x00000040, 0xFFFFFFFF},
+ {0x00000041, 0xFFFFFFFF},
+ {0x00000440, 0xFFFFFFFF},
+ {0x000001A9, 0x00000001}
+};
+static unsigned nv3TablePGRAPH_8BPP[][2] =
+{
+ {0x000001AA, 0x00001111}
+};
+static unsigned nv3TablePGRAPH_15BPP[][2] =
+{
+ {0x000001AA, 0x00002222}
+};
+static unsigned nv3TablePGRAPH_32BPP[][2] =
+{
+ {0x000001AA, 0x00003333}
+};
+static unsigned nv3TablePRAMIN[][2] =
+{
+ {0x00000500, 0x00010000},
+ {0x00000501, 0x007FFFFF},
+ {0x00000200, 0x80000000},
+ {0x00000201, 0x00C20341},
+ {0x00000204, 0x80000001},
+ {0x00000205, 0x00C50342},
+ {0x00000208, 0x80000002},
+ {0x00000209, 0x00C60343},
+ {0x0000020C, 0x80000003},
+ {0x0000020D, 0x00DC0348},
+ {0x00000210, 0x80000004},
+ {0x00000211, 0x00DC0349},
+ {0x00000214, 0x80000005},
+ {0x00000215, 0x00DC034A},
+ {0x00000218, 0x80000006},
+ {0x00000219, 0x00DC034B},
+ {0x00000240, 0x80000010},
+ {0x00000241, 0x00D10344},
+ {0x00000244, 0x80000011},
+ {0x00000245, 0x00D00345},
+ {0x00000248, 0x80000012},
+ {0x00000249, 0x00CC0346},
+ {0x0000024C, 0x80000013},
+ {0x0000024D, 0x00D70347},
+ {0x00000258, 0x80000016},
+ {0x00000259, 0x00CA034C},
+ {0x00000D05, 0x00000000},
+ {0x00000D06, 0x00000000},
+ {0x00000D07, 0x00000000},
+ {0x00000D09, 0x00000000},
+ {0x00000D0A, 0x00000000},
+ {0x00000D0B, 0x00000000},
+ {0x00000D0D, 0x00000000},
+ {0x00000D0E, 0x00000000},
+ {0x00000D0F, 0x00000000},
+ {0x00000D11, 0x00000000},
+ {0x00000D12, 0x00000000},
+ {0x00000D13, 0x00000000},
+ {0x00000D15, 0x00000000},
+ {0x00000D16, 0x00000000},
+ {0x00000D17, 0x00000000},
+ {0x00000D19, 0x00000000},
+ {0x00000D1A, 0x00000000},
+ {0x00000D1B, 0x00000000},
+ {0x00000D1D, 0x00000140},
+ {0x00000D1E, 0x00000000},
+ {0x00000D1F, 0x00000000},
+ {0x00000D20, 0x10100200},
+ {0x00000D21, 0x00000000},
+ {0x00000D22, 0x00000000},
+ {0x00000D23, 0x00000000},
+ {0x00000D24, 0x10210200},
+ {0x00000D25, 0x00000000},
+ {0x00000D26, 0x00000000},
+ {0x00000D27, 0x00000000},
+ {0x00000D28, 0x10420200},
+ {0x00000D29, 0x00000000},
+ {0x00000D2A, 0x00000000},
+ {0x00000D2B, 0x00000000},
+ {0x00000D2C, 0x10830200},
+ {0x00000D2D, 0x00000000},
+ {0x00000D2E, 0x00000000},
+ {0x00000D2F, 0x00000000},
+ {0x00000D31, 0x00000000},
+ {0x00000D32, 0x00000000},
+ {0x00000D33, 0x00000000}
+};
+static unsigned nv3TablePRAMIN_8BPP[][2] =
+{
+ /* 0xXXXXX3XX For MSB mono format */
+ /* 0xXXXXX2XX For LSB mono format */
+ {0x00000D04, 0x10110203},
+ {0x00000D08, 0x10110203},
+ {0x00000D0C, 0x1011020B},
+ {0x00000D10, 0x10118203},
+ {0x00000D14, 0x10110203},
+ {0x00000D18, 0x10110203},
+ {0x00000D1C, 0x10419208},
+ {0x00000D30, 0x10118203}
+};
+static unsigned nv3TablePRAMIN_15BPP[][2] =
+{
+ /* 0xXXXXX2XX For MSB mono format */
+ /* 0xXXXXX3XX For LSB mono format */
+ {0x00000D04, 0x10110200},
+ {0x00000D08, 0x10110200},
+ {0x00000D0C, 0x10110208},
+ {0x00000D10, 0x10118200},
+ {0x00000D14, 0x10110200},
+ {0x00000D18, 0x10110200},
+ {0x00000D1C, 0x10419208},
+ {0x00000D30, 0x10118200}
+};
+static unsigned nv3TablePRAMIN_32BPP[][2] =
+{
+ /* 0xXXXXX3XX For MSB mono format */
+ /* 0xXXXXX2XX For LSB mono format */
+ {0x00000D04, 0x10110201},
+ {0x00000D08, 0x10110201},
+ {0x00000D0C, 0x10110209},
+ {0x00000D10, 0x10118201},
+ {0x00000D14, 0x10110201},
+ {0x00000D18, 0x10110201},
+ {0x00000D1C, 0x10419208},
+ {0x00000D30, 0x10118201}
+};
+static unsigned nv4TableFIFO[][2] =
+{
+ {0x00003800, 0x80000014}
+};
+static unsigned nv4TablePFIFO[][2] =
+{
+ {0x00000140, 0x00000000},
+ {0x00000480, 0x00000000},
+ {0x00000494, 0x00000000},
+ {0x00000481, 0x00000000},
+ {0x0000048B, 0x00000000},
+ {0x00000400, 0x00000000},
+ {0x00000414, 0x00000000},
+ {0x00000084, 0x03000100},
+ {0x00000085, 0x00000110},
+ {0x00000086, 0x00000112},
+ {0x00000143, 0x0000FFFF},
+ {0x00000496, 0x0000FFFF},
+ {0x00000050, 0x00000000},
+ {0x00000040, 0xFFFFFFFF},
+ {0x00000415, 0x00000001},
+ {0x00000480, 0x00000001},
+ {0x00000494, 0x00000001},
+ {0x00000495, 0x00000001},
+ {0x00000140, 0x00000001}
+};
+static unsigned nv4TablePGRAPH[][2] =
+{
+ {0x00000020, 0x1231C001},
+ {0x00000021, 0x72111101},
+ {0x00000022, 0x11D5F071},
+ {0x00000023, 0x10D4FF31},
+ {0x00000060, 0x00000000},
+ {0x00000068, 0x00000000},
+ {0x00000070, 0x00000000},
+ {0x00000078, 0x00000000},
+ {0x00000061, 0x00000000},
+ {0x00000069, 0x00000000},
+ {0x00000071, 0x00000000},
+ {0x00000079, 0x00000000},
+ {0x00000062, 0x00000000},
+ {0x0000006A, 0x00000000},
+ {0x00000072, 0x00000000},
+ {0x0000007A, 0x00000000},
+ {0x00000063, 0x00000000},
+ {0x0000006B, 0x00000000},
+ {0x00000073, 0x00000000},
+ {0x0000007B, 0x00000000},
+ {0x00000064, 0x00000000},
+ {0x0000006C, 0x00000000},
+ {0x00000074, 0x00000000},
+ {0x0000007C, 0x00000000},
+ {0x00000065, 0x00000000},
+ {0x0000006D, 0x00000000},
+ {0x00000075, 0x00000000},
+ {0x0000007D, 0x00000000},
+ {0x00000066, 0x00000000},
+ {0x0000006E, 0x00000000},
+ {0x00000076, 0x00000000},
+ {0x0000007E, 0x00000000},
+ {0x00000067, 0x00000000},
+ {0x0000006F, 0x00000000},
+ {0x00000077, 0x00000000},
+ {0x0000007F, 0x00000000},
+ {0x00000058, 0x00000000},
+ {0x00000059, 0x00000000},
+ {0x0000005A, 0x00000000},
+ {0x0000005B, 0x00000000},
+ {0x00000196, 0x00000000},
+ {0x000001A1, 0x01FFFFFF},
+ {0x00000197, 0x00000000},
+ {0x000001A2, 0x01FFFFFF},
+ {0x00000198, 0x00000000},
+ {0x000001A3, 0x01FFFFFF},
+ {0x00000199, 0x00000000},
+ {0x000001A4, 0x01FFFFFF},
+ {0x00000050, 0x00000000},
+ {0x00000040, 0xFFFFFFFF},
+ {0x0000005C, 0x10010100},
+ {0x000001C4, 0xFFFFFFFF},
+ {0x000001C8, 0x00000001},
+ {0x00000204, 0x00000000},
+ {0x000001C3, 0x00000001}
+};
+static unsigned nv4TablePGRAPH_8BPP[][2] =
+{
+ {0x000001C9, 0x00111111},
+ {0x00000186, 0x00001010},
+ {0x0000020C, 0x03020202}
+};
+static unsigned nv4TablePGRAPH_15BPP[][2] =
+{
+ {0x000001C9, 0x00226222},
+ {0x00000186, 0x00002071},
+ {0x0000020C, 0x09080808}
+};
+static unsigned nv4TablePGRAPH_16BPP[][2] =
+{
+ {0x000001C9, 0x00556555},
+ {0x00000186, 0x000050C2},
+ {0x0000020C, 0x0C0B0B0B}
+};
+static unsigned nv4TablePGRAPH_32BPP[][2] =
+{
+ {0x000001C9, 0x0077D777},
+ {0x00000186, 0x000070E5},
+ {0x0000020C, 0x0E0D0D0D}
+};
+static unsigned nv4TablePRAMIN[][2] =
+{
+ {0x00000000, 0x80000010},
+ {0x00000001, 0x80011145},
+ {0x00000002, 0x80000011},
+ {0x00000003, 0x80011146},
+ {0x00000004, 0x80000012},
+ {0x00000005, 0x80011147},
+ {0x00000006, 0x80000013},
+ {0x00000007, 0x80011148},
+ {0x00000008, 0x80000014},
+ {0x00000009, 0x80011149},
+ {0x0000000A, 0x80000015},
+ {0x0000000B, 0x8001114A},
+ {0x0000000C, 0x80000016},
+ {0x0000000D, 0x8001114F},
+ {0x00000020, 0x80000000},
+ {0x00000021, 0x80011142},
+ {0x00000022, 0x80000001},
+ {0x00000023, 0x80011143},
+ {0x00000024, 0x80000002},
+ {0x00000025, 0x80011144},
+ {0x00000026, 0x80000003},
+ {0x00000027, 0x8001114B},
+ {0x00000028, 0x80000004},
+ {0x00000029, 0x8001114C},
+ {0x0000002A, 0x80000005},
+ {0x0000002B, 0x8001114D},
+ {0x0000002C, 0x80000006},
+ {0x0000002D, 0x8001114E},
+ {0x00000500, 0x00003000},
+ {0x00000501, 0x01FFFFFF},
+ {0x00000502, 0x00000002},
+ {0x00000503, 0x00000002},
+ {0x00000508, 0x01008043},
+ {0x0000050A, 0x00000000},
+ {0x0000050B, 0x00000000},
+ {0x0000050C, 0x01008019},
+ {0x0000050E, 0x00000000},
+ {0x0000050F, 0x00000000},
+#if 1
+ {0x00000510, 0x01008018},
+#else
+ {0x00000510, 0x01008044},
+#endif
+ {0x00000512, 0x00000000},
+ {0x00000513, 0x00000000},
+ {0x00000514, 0x01008021},
+ {0x00000516, 0x00000000},
+ {0x00000517, 0x00000000},
+ {0x00000518, 0x0100805F},
+ {0x0000051A, 0x00000000},
+ {0x0000051B, 0x00000000},
+#if 1
+ {0x0000051C, 0x0100804B},
+#else
+ {0x0000051C, 0x0100804A},
+#endif
+ {0x0000051E, 0x00000000},
+ {0x0000051F, 0x00000000},
+ {0x00000520, 0x0100A048},
+ {0x00000521, 0x00000D01},
+ {0x00000522, 0x11401140},
+ {0x00000523, 0x00000000},
+ {0x00000524, 0x0300A054},
+ {0x00000525, 0x00000D01},
+ {0x00000526, 0x11401140},
+ {0x00000527, 0x00000000},
+ {0x00000528, 0x0300A055},
+ {0x00000529, 0x00000D01},
+ {0x0000052A, 0x11401140},
+ {0x0000052B, 0x00000000},
+ {0x0000052C, 0x00000058},
+ {0x0000052E, 0x11401140},
+ {0x0000052F, 0x00000000},
+ {0x00000530, 0x00000059},
+ {0x00000532, 0x11401140},
+ {0x00000533, 0x00000000},
+ {0x00000534, 0x0000005A},
+ {0x00000536, 0x11401140},
+ {0x00000537, 0x00000000},
+ {0x00000538, 0x0000005B},
+ {0x0000053A, 0x11401140},
+ {0x0000053B, 0x00000000},
+ {0x0000053C, 0x0300A01C},
+ {0x0000053E, 0x11401140},
+ {0x0000053F, 0x00000000}
+};
+static unsigned nv4TablePRAMIN_8BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000302},
+ {0x0000050D, 0x00000302},
+ {0x00000511, 0x00000202},
+ {0x00000515, 0x00000302},
+ {0x00000519, 0x00000302},
+ {0x0000051D, 0x00000302},
+ {0x0000052D, 0x00000302},
+ {0x0000052E, 0x00000302},
+ {0x00000535, 0x00000000},
+ {0x00000539, 0x00000000},
+ {0x0000053D, 0x00000302}
+};
+static unsigned nv4TablePRAMIN_15BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000902},
+ {0x0000050D, 0x00000902},
+ {0x00000511, 0x00000802},
+ {0x00000515, 0x00000902},
+ {0x00000519, 0x00000902},
+ {0x0000051D, 0x00000902},
+ {0x0000052D, 0x00000902},
+ {0x0000052E, 0x00000902},
+ {0x00000535, 0x00000702},
+ {0x00000539, 0x00000702},
+ {0x0000053D, 0x00000902}
+};
+static unsigned nv4TablePRAMIN_16BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000C02},
+ {0x0000050D, 0x00000C02},
+ {0x00000511, 0x00000B02},
+ {0x00000515, 0x00000C02},
+ {0x00000519, 0x00000C02},
+ {0x0000051D, 0x00000C02},
+ {0x0000052D, 0x00000C02},
+ {0x0000052E, 0x00000C02},
+ {0x00000535, 0x00000702},
+ {0x00000539, 0x00000702},
+ {0x0000053D, 0x00000C02}
+};
+static unsigned nv4TablePRAMIN_32BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000E02},
+ {0x0000050D, 0x00000E02},
+ {0x00000511, 0x00000D02},
+ {0x00000515, 0x00000E02},
+ {0x00000519, 0x00000E02},
+ {0x0000051D, 0x00000E02},
+ {0x0000052D, 0x00000E02},
+ {0x0000052E, 0x00000E02},
+ {0x00000535, 0x00000E02},
+ {0x00000539, 0x00000E02},
+ {0x0000053D, 0x00000E02}
+};
+static unsigned nv10TableFIFO[][2] =
+{
+ {0x00003800, 0x80000014}
+};
+static unsigned nv10TablePFIFO[][2] =
+{
+ {0x00000140, 0x00000000},
+ {0x00000480, 0x00000000},
+ {0x00000494, 0x00000000},
+ {0x00000481, 0x00000000},
+ {0x0000048B, 0x00000000},
+ {0x00000400, 0x00000000},
+ {0x00000414, 0x00000000},
+ {0x00000084, 0x03000100},
+ {0x00000085, 0x00000110},
+ {0x00000086, 0x00000112},
+ {0x00000143, 0x0000FFFF},
+ {0x00000496, 0x0000FFFF},
+ {0x00000050, 0x00000000},
+ {0x00000040, 0xFFFFFFFF},
+ {0x00000415, 0x00000001},
+ {0x00000480, 0x00000001},
+ {0x00000494, 0x00000001},
+ {0x00000495, 0x00000001},
+ {0x00000140, 0x00000001}
+};
+static unsigned nv10TablePGRAPH[][2] =
+{
+ {0x00000020, 0x0003FFFF},
+ {0x00000021, 0x00118701},
+ {0x00000022, 0x24F82AD9},
+ {0x00000023, 0x55DE0030},
+ {0x00000020, 0x00000000},
+ {0x00000024, 0x00000000},
+ {0x00000058, 0x00000000},
+ {0x00000060, 0x00000000},
+ {0x00000068, 0x00000000},
+ {0x00000070, 0x00000000},
+ {0x00000078, 0x00000000},
+ {0x00000059, 0x00000000},
+ {0x00000061, 0x00000000},
+ {0x00000069, 0x00000000},
+ {0x00000071, 0x00000000},
+ {0x00000079, 0x00000000},
+ {0x0000005A, 0x00000000},
+ {0x00000062, 0x00000000},
+ {0x0000006A, 0x00000000},
+ {0x00000072, 0x00000000},
+ {0x0000007A, 0x00000000},
+ {0x0000005B, 0x00000000},
+ {0x00000063, 0x00000000},
+ {0x0000006B, 0x00000000},
+ {0x00000073, 0x00000000},
+ {0x0000007B, 0x00000000},
+ {0x0000005C, 0x00000000},
+ {0x00000064, 0x00000000},
+ {0x0000006C, 0x00000000},
+ {0x00000074, 0x00000000},
+ {0x0000007C, 0x00000000},
+ {0x0000005D, 0x00000000},
+ {0x00000065, 0x00000000},
+ {0x0000006D, 0x00000000},
+ {0x00000075, 0x00000000},
+ {0x0000007D, 0x00000000},
+ {0x0000005E, 0x00000000},
+ {0x00000066, 0x00000000},
+ {0x0000006E, 0x00000000},
+ {0x00000076, 0x00000000},
+ {0x0000007E, 0x00000000},
+ {0x0000005F, 0x00000000},
+ {0x00000067, 0x00000000},
+ {0x0000006F, 0x00000000},
+ {0x00000077, 0x00000000},
+ {0x0000007F, 0x00000000},
+ {0x00000053, 0x00000000},
+ {0x00000054, 0x00000000},
+ {0x00000055, 0x00000000},
+ {0x00000056, 0x00000000},
+ {0x00000057, 0x00000000},
+ {0x00000196, 0x00000000},
+ {0x000001A1, 0x01FFFFFF},
+ {0x00000197, 0x00000000},
+ {0x000001A2, 0x01FFFFFF},
+ {0x00000198, 0x00000000},
+ {0x000001A3, 0x01FFFFFF},
+ {0x00000199, 0x00000000},
+ {0x000001A4, 0x01FFFFFF},
+ {0x0000019A, 0x00000000},
+ {0x000001A5, 0x01FFFFFF},
+ {0x0000019B, 0x00000000},
+ {0x000001A6, 0x01FFFFFF},
+ {0x00000050, 0x01111111},
+ {0x00000040, 0xFFFFFFFF},
+ {0x00000051, 0x10010100},
+ {0x000001C5, 0xFFFFFFFF},
+ {0x000001C8, 0x00000001},
+ {0x00000204, 0x00000000},
+ {0x000001C4, 0x00000001}
+};
+static unsigned nv10TablePGRAPH_8BPP[][2] =
+{
+ {0x000001C9, 0x00111111},
+ {0x00000186, 0x00001010},
+ {0x0000020C, 0x03020202}
+};
+static unsigned nv10TablePGRAPH_15BPP[][2] =
+{
+ {0x000001C9, 0x00226222},
+ {0x00000186, 0x00002071},
+ {0x0000020C, 0x09080808}
+};
+static unsigned nv10TablePGRAPH_16BPP[][2] =
+{
+ {0x000001C9, 0x00556555},
+ {0x00000186, 0x000050C2},
+ {0x0000020C, 0x000B0B0C}
+};
+static unsigned nv10TablePGRAPH_32BPP[][2] =
+{
+ {0x000001C9, 0x0077D777},
+ {0x00000186, 0x000070E5},
+ {0x0000020C, 0x0E0D0D0D}
+};
+static unsigned nv10tri05TablePGRAPH[][2] =
+{
+ {(0x00000E00/4), 0x00000000},
+ {(0x00000E04/4), 0x00000000},
+ {(0x00000E08/4), 0x00000000},
+ {(0x00000E0C/4), 0x00000000},
+ {(0x00000E10/4), 0x00001000},
+ {(0x00000E14/4), 0x00001000},
+ {(0x00000E18/4), 0x4003ff80},
+ {(0x00000E1C/4), 0x00000000},
+ {(0x00000E20/4), 0x00000000},
+ {(0x00000E24/4), 0x00000000},
+ {(0x00000E28/4), 0x00000000},
+ {(0x00000E2C/4), 0x00000000},
+ {(0x00000E30/4), 0x00080008},
+ {(0x00000E34/4), 0x00080008},
+ {(0x00000E38/4), 0x00000000},
+ {(0x00000E3C/4), 0x00000000},
+ {(0x00000E40/4), 0x00000000},
+ {(0x00000E44/4), 0x00000000},
+ {(0x00000E48/4), 0x00000000},
+ {(0x00000E4C/4), 0x00000000},
+ {(0x00000E50/4), 0x00000000},
+ {(0x00000E54/4), 0x00000000},
+ {(0x00000E58/4), 0x00000000},
+ {(0x00000E5C/4), 0x00000000},
+ {(0x00000E60/4), 0x00000000},
+ {(0x00000E64/4), 0x10000000},
+ {(0x00000E68/4), 0x00000000},
+ {(0x00000E6C/4), 0x00000000},
+ {(0x00000E70/4), 0x00000000},
+ {(0x00000E74/4), 0x00000000},
+ {(0x00000E78/4), 0x00000000},
+ {(0x00000E7C/4), 0x00000000},
+ {(0x00000E80/4), 0x00000000},
+ {(0x00000E84/4), 0x00000000},
+ {(0x00000E88/4), 0x08000000},
+ {(0x00000E8C/4), 0x00000000},
+ {(0x00000E90/4), 0x00000000},
+ {(0x00000E94/4), 0x00000000},
+ {(0x00000E98/4), 0x00000000},
+ {(0x00000E9C/4), 0x4B7FFFFF},
+ {(0x00000EA0/4), 0x00000000},
+ {(0x00000EA4/4), 0x00000000},
+ {(0x00000EA8/4), 0x00000000},
+ {(0x00000F00/4), 0x07FF0800},
+ {(0x00000F04/4), 0x07FF0800},
+ {(0x00000F08/4), 0x07FF0800},
+ {(0x00000F0C/4), 0x07FF0800},
+ {(0x00000F10/4), 0x07FF0800},
+ {(0x00000F14/4), 0x07FF0800},
+ {(0x00000F18/4), 0x07FF0800},
+ {(0x00000F1C/4), 0x07FF0800},
+ {(0x00000F20/4), 0x07FF0800},
+ {(0x00000F24/4), 0x07FF0800},
+ {(0x00000F28/4), 0x07FF0800},
+ {(0x00000F2C/4), 0x07FF0800},
+ {(0x00000F30/4), 0x07FF0800},
+ {(0x00000F34/4), 0x07FF0800},
+ {(0x00000F38/4), 0x07FF0800},
+ {(0x00000F3C/4), 0x07FF0800},
+ {(0x00000F40/4), 0x10000000},
+ {(0x00000F44/4), 0x00000000},
+ {(0x00000F50/4), 0x00006740},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F50/4), 0x00006750},
+ {(0x00000F54/4), 0x40000000},
+ {(0x00000F54/4), 0x40000000},
+ {(0x00000F54/4), 0x40000000},
+ {(0x00000F54/4), 0x40000000},
+ {(0x00000F50/4), 0x00006760},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00006770},
+ {(0x00000F54/4), 0xC5000000},
+ {(0x00000F54/4), 0xC5000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00006780},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x000067A0},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F50/4), 0x00006AB0},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F50/4), 0x00006AC0},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00006C10},
+ {(0x00000F54/4), 0xBF800000},
+ {(0x00000F50/4), 0x00007030},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00007040},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00007050},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00007060},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00007070},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00007080},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00007090},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x000070A0},
+ {(0x00000F54/4), 0x7149F2CA},
+ {(0x00000F50/4), 0x00006A80},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F50/4), 0x00006AA0},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00000040},
+ {(0x00000F54/4), 0x00000005},
+ {(0x00000F50/4), 0x00006400},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x4B7FFFFF},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00006410},
+ {(0x00000F54/4), 0xC5000000},
+ {(0x00000F54/4), 0xC5000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00006420},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x00006430},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x000064C0},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F54/4), 0x477FFFFF},
+ {(0x00000F54/4), 0x3F800000},
+ {(0x00000F50/4), 0x000064D0},
+ {(0x00000F54/4), 0xC5000000},
+ {(0x00000F54/4), 0xC5000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x000064E0},
+ {(0x00000F54/4), 0xC4FFF000},
+ {(0x00000F54/4), 0xC4FFF000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F50/4), 0x000064F0},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F54/4), 0x00000000},
+ {(0x00000F40/4), 0x30000000},
+ {(0x00000F44/4), 0x00000004},
+ {(0x00000F48/4), 0x10000000},
+ {(0x00000F4C/4), 0x00000000}
+};
+static unsigned nv10TablePRAMIN[][2] =
+{
+ {0x00000000, 0x80000010},
+ {0x00000001, 0x80011145},
+ {0x00000002, 0x80000011},
+ {0x00000003, 0x80011146},
+ {0x00000004, 0x80000012},
+ {0x00000005, 0x80011147},
+ {0x00000006, 0x80000013},
+ {0x00000007, 0x80011148},
+ {0x00000008, 0x80000014},
+ {0x00000009, 0x80011149},
+ {0x0000000A, 0x80000015},
+ {0x0000000B, 0x8001114A},
+ {0x0000000C, 0x80000016},
+ {0x0000000D, 0x80011150},
+ {0x00000020, 0x80000000},
+ {0x00000021, 0x80011142},
+ {0x00000022, 0x80000001},
+ {0x00000023, 0x80011143},
+ {0x00000024, 0x80000002},
+ {0x00000025, 0x80011144},
+ {0x00000026, 0x80000003},
+ {0x00000027, 0x8001114B},
+ {0x00000028, 0x80000004},
+ {0x00000029, 0x8001114C},
+ {0x0000002A, 0x80000005},
+ {0x0000002B, 0x8001114D},
+ {0x0000002C, 0x80000006},
+ {0x0000002D, 0x8001114E},
+ {0x0000002E, 0x80000007},
+ {0x0000002F, 0x8001114F},
+ {0x00000500, 0x00003000},
+ {0x00000501, 0x01FFFFFF},
+ {0x00000502, 0x00000002},
+ {0x00000503, 0x00000002},
+#ifdef __BIG_ENDIAN
+ {0x00000508, 0x01088043},
+#else
+ {0x00000508, 0x01008043},
+#endif
+ {0x0000050A, 0x00000000},
+ {0x0000050B, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x0000050C, 0x01088019},
+#else
+ {0x0000050C, 0x01008019},
+#endif
+ {0x0000050E, 0x00000000},
+ {0x0000050F, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000510, 0x01088018},
+#else
+ {0x00000510, 0x01008018},
+#endif
+ {0x00000512, 0x00000000},
+ {0x00000513, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000514, 0x01088021},
+#else
+ {0x00000514, 0x01008021},
+#endif
+ {0x00000516, 0x00000000},
+ {0x00000517, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000518, 0x0108805F},
+#else
+ {0x00000518, 0x0100805F},
+#endif
+ {0x0000051A, 0x00000000},
+ {0x0000051B, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x0000051C, 0x0108804B},
+#else
+ {0x0000051C, 0x0100804B},
+#endif
+ {0x0000051E, 0x00000000},
+ {0x0000051F, 0x00000000},
+ {0x00000520, 0x0100A048},
+ {0x00000521, 0x00000D01},
+ {0x00000522, 0x11401140},
+ {0x00000523, 0x00000000},
+ {0x00000524, 0x0300A094},
+ {0x00000525, 0x00000D01},
+ {0x00000526, 0x11401140},
+ {0x00000527, 0x00000000},
+ {0x00000528, 0x0300A095},
+ {0x00000529, 0x00000D01},
+ {0x0000052A, 0x11401140},
+ {0x0000052B, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x0000052C, 0x00080058},
+#else
+ {0x0000052C, 0x00000058},
+#endif
+ {0x0000052E, 0x11401140},
+ {0x0000052F, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000530, 0x00080059},
+#else
+ {0x00000530, 0x00000059},
+#endif
+ {0x00000532, 0x11401140},
+ {0x00000533, 0x00000000},
+ {0x00000534, 0x0000005A},
+ {0x00000536, 0x11401140},
+ {0x00000537, 0x00000000},
+ {0x00000538, 0x0000005B},
+ {0x0000053A, 0x11401140},
+ {0x0000053B, 0x00000000},
+ {0x0000053C, 0x00000093},
+ {0x0000053E, 0x11401140},
+ {0x0000053F, 0x00000000},
+#ifdef __BIG_ENDIAN
+ {0x00000540, 0x0308A01C},
+#else
+ {0x00000540, 0x0300A01C},
+#endif
+ {0x00000542, 0x11401140},
+ {0x00000543, 0x00000000}
+};
+static unsigned nv10TablePRAMIN_8BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000302},
+ {0x0000050D, 0x00000302},
+ {0x00000511, 0x00000202},
+ {0x00000515, 0x00000302},
+ {0x00000519, 0x00000302},
+ {0x0000051D, 0x00000302},
+ {0x0000052D, 0x00000302},
+ {0x0000052E, 0x00000302},
+ {0x00000535, 0x00000000},
+ {0x00000539, 0x00000000},
+ {0x0000053D, 0x00000000},
+ {0x00000541, 0x00000302}
+};
+static unsigned nv10TablePRAMIN_15BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000902},
+ {0x0000050D, 0x00000902},
+ {0x00000511, 0x00000802},
+ {0x00000515, 0x00000902},
+ {0x00000519, 0x00000902},
+ {0x0000051D, 0x00000902},
+ {0x0000052D, 0x00000902},
+ {0x0000052E, 0x00000902},
+ {0x00000535, 0x00000902},
+ {0x00000539, 0x00000902},
+ {0x0000053D, 0x00000902},
+ {0x00000541, 0x00000902}
+};
+static unsigned nv10TablePRAMIN_16BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000C02},
+ {0x0000050D, 0x00000C02},
+ {0x00000511, 0x00000B02},
+ {0x00000515, 0x00000C02},
+ {0x00000519, 0x00000C02},
+ {0x0000051D, 0x00000C02},
+ {0x0000052D, 0x00000C02},
+ {0x0000052E, 0x00000C02},
+ {0x00000535, 0x00000C02},
+ {0x00000539, 0x00000C02},
+ {0x0000053D, 0x00000C02},
+ {0x00000541, 0x00000C02}
+};
+static unsigned nv10TablePRAMIN_32BPP[][2] =
+{
+ /* 0xXXXXXX01 For MSB mono format */
+ /* 0xXXXXXX02 For LSB mono format */
+ {0x00000509, 0x00000E02},
+ {0x0000050D, 0x00000E02},
+ {0x00000511, 0x00000D02},
+ {0x00000515, 0x00000E02},
+ {0x00000519, 0x00000E02},
+ {0x0000051D, 0x00000E02},
+ {0x0000052D, 0x00000E02},
+ {0x0000052E, 0x00000E02},
+ {0x00000535, 0x00000E02},
+ {0x00000539, 0x00000E02},
+ {0x0000053D, 0x00000E02},
+ {0x00000541, 0x00000E02}
+};
+
diff --git a/drivers/video/fbdev/riva/rivafb-i2c.c b/drivers/video/fbdev/riva/rivafb-i2c.c
new file mode 100644
index 000000000000..6a183375ced1
--- /dev/null
+++ b/drivers/video/fbdev/riva/rivafb-i2c.c
@@ -0,0 +1,166 @@
+/*
+ * linux/drivers/video/riva/fbdev-i2c.c - nVidia i2c
+ *
+ * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on radeonfb-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/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include <linux/jiffies.h>
+
+#include <asm/io.h>
+
+#include "rivafb.h"
+#include "../edid.h"
+
+static void riva_gpio_setscl(void* data, int state)
+{
+ struct riva_i2c_chan *chan = data;
+ struct riva_par *par = chan->par;
+ u32 val;
+
+ VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+ val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
+
+ if (state)
+ val |= 0x20;
+ else
+ val &= ~0x20;
+
+ VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+ VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
+}
+
+static void riva_gpio_setsda(void* data, int state)
+{
+ struct riva_i2c_chan *chan = data;
+ struct riva_par *par = chan->par;
+ u32 val;
+
+ VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+ val = VGA_RD08(par->riva.PCIO, 0x3d5) & 0xf0;
+
+ if (state)
+ val |= 0x10;
+ else
+ val &= ~0x10;
+
+ VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base + 1);
+ VGA_WR08(par->riva.PCIO, 0x3d5, val | 0x1);
+}
+
+static int riva_gpio_getscl(void* data)
+{
+ struct riva_i2c_chan *chan = data;
+ struct riva_par *par = chan->par;
+ u32 val = 0;
+
+ VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
+ if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04)
+ val = 1;
+
+ return val;
+}
+
+static int riva_gpio_getsda(void* data)
+{
+ struct riva_i2c_chan *chan = data;
+ struct riva_par *par = chan->par;
+ u32 val = 0;
+
+ VGA_WR08(par->riva.PCIO, 0x3d4, chan->ddc_base);
+ if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x08)
+ val = 1;
+
+ return val;
+}
+
+static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name,
+ unsigned int i2c_class)
+{
+ int rc;
+
+ strcpy(chan->adapter.name, name);
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.class = i2c_class;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->par->pdev->dev;
+ chan->algo.setsda = riva_gpio_setsda;
+ chan->algo.setscl = riva_gpio_setscl;
+ chan->algo.getsda = riva_gpio_getsda;
+ chan->algo.getscl = riva_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 */
+ riva_gpio_setsda(chan, 1);
+ riva_gpio_setscl(chan, 1);
+ udelay(20);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ dev_dbg(&chan->par->pdev->dev, "I2C bus %s registered.\n", name);
+ else {
+ dev_warn(&chan->par->pdev->dev,
+ "Failed to register I2C bus %s.\n", name);
+ chan->par = NULL;
+ }
+
+ return rc;
+}
+
+void riva_create_i2c_busses(struct riva_par *par)
+{
+ par->chan[0].par = par;
+ par->chan[1].par = par;
+ par->chan[2].par = par;
+
+ par->chan[0].ddc_base = 0x36;
+ par->chan[1].ddc_base = 0x3e;
+ par->chan[2].ddc_base = 0x50;
+ riva_setup_i2c_bus(&par->chan[0], "BUS1", I2C_CLASS_HWMON);
+ riva_setup_i2c_bus(&par->chan[1], "BUS2", 0);
+ riva_setup_i2c_bus(&par->chan[2], "BUS3", 0);
+}
+
+void riva_delete_i2c_busses(struct riva_par *par)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (!par->chan[i].par)
+ continue;
+ i2c_del_adapter(&par->chan[i].adapter);
+ par->chan[i].par = NULL;
+ }
+}
+
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid)
+{
+ u8 *edid = NULL;
+
+ if (par->chan[conn].par)
+ edid = fb_ddc_read(&par->chan[conn].adapter);
+
+ if (out_edid)
+ *out_edid = edid;
+ if (!edid)
+ return 1;
+
+ return 0;
+}
+
diff --git a/drivers/video/fbdev/riva/rivafb.h b/drivers/video/fbdev/riva/rivafb.h
new file mode 100644
index 000000000000..d9f107b704c6
--- /dev/null
+++ b/drivers/video/fbdev/riva/rivafb.h
@@ -0,0 +1,77 @@
+#ifndef __RIVAFB_H
+#define __RIVAFB_H
+
+#include <linux/fb.h>
+#include <video/vga.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "riva_hw.h"
+
+/* GGI compatibility macros */
+#define NUM_SEQ_REGS 0x05
+#define NUM_CRT_REGS 0x41
+#define NUM_GRC_REGS 0x09
+#define NUM_ATC_REGS 0x15
+
+/* I2C */
+#define DDC_SCL_READ_MASK (1 << 2)
+#define DDC_SCL_WRITE_MASK (1 << 5)
+#define DDC_SDA_READ_MASK (1 << 3)
+#define DDC_SDA_WRITE_MASK (1 << 4)
+
+/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
+ * From KGI originally. */
+struct riva_regs {
+ u8 attr[NUM_ATC_REGS];
+ u8 crtc[NUM_CRT_REGS];
+ u8 gra[NUM_GRC_REGS];
+ u8 seq[NUM_SEQ_REGS];
+ u8 misc_output;
+ RIVA_HW_STATE ext;
+};
+
+struct riva_par;
+
+struct riva_i2c_chan {
+ struct riva_par *par;
+ unsigned long ddc_base;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+
+struct riva_par {
+ RIVA_HW_INST riva; /* interface to riva_hw.c */
+ u32 pseudo_palette[16]; /* default palette */
+ u32 palette[16]; /* for Riva128 */
+ u8 __iomem *ctrl_base; /* virtual control register base addr */
+ unsigned dclk_max; /* max DCLK */
+
+ struct riva_regs initial_state; /* initial startup video mode */
+ struct riva_regs current_state;
+#ifdef CONFIG_X86
+ struct vgastate state;
+#endif
+ struct mutex open_lock;
+ unsigned int ref_count;
+ unsigned char *EDID;
+ unsigned int Chipset;
+ int forceCRTC;
+ Bool SecondCRTC;
+ int FlatPanel;
+ struct pci_dev *pdev;
+ int cursor_reset;
+#ifdef CONFIG_MTRR
+ struct { int vram; int vram_valid; } mtrr;
+#endif
+ struct riva_i2c_chan chan[3];
+};
+
+void riva_common_setup(struct riva_par *);
+unsigned long riva_get_memlen(struct riva_par *);
+unsigned long riva_get_maxdclk(struct riva_par *);
+void riva_delete_i2c_busses(struct riva_par *par);
+void riva_create_i2c_busses(struct riva_par *par);
+int riva_probe_i2c_connector(struct riva_par *par, int conn, u8 **out_edid);
+
+#endif /* __RIVAFB_H */