fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / video / matrox / matroxfb_base.c
index 1388470..cb2aa40 100644 (file)
  *
  */
 
-/* make checkconfig does not check included files... */
-#include <linux/config.h>
 #include <linux/version.h>
 
+#define __OLD_VIDIOC_
+
 #include "matroxfb_base.h"
 #include "matroxfb_misc.h"
 #include "matroxfb_accel.h"
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_PPC_PMAC
+#include <asm/machdep.h>
 unsigned char nvram_read_byte(int);
 static int default_vmode = VMODE_NVRAM;
 static int default_cmode = CMODE_NVRAM;
@@ -158,9 +159,9 @@ static void update_crtc2(WPMINFO unsigned int pos) {
 
        /* Make sure that displays are compatible */
        if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel)
-                && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
-                && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
-                ) {
+                && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
+                && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
+                ) {
                switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
                        case 16:
                        case 32:
@@ -197,7 +198,7 @@ static void matroxfb_crtc1_panpos(WPMINFO2) {
        }
 }
 
-static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t matrox_irq(int irq, void *dev_id)
 {
        u_int32_t status;
        int handled = 0;
@@ -224,7 +225,7 @@ static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp)
 
 int matroxfb_enable_irq(WPMINFO int reenable) {
        u_int32_t bm;
-       
+
        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
                bm = 0x220;
        else
@@ -232,7 +233,7 @@ int matroxfb_enable_irq(WPMINFO int reenable) {
 
        if (!test_and_set_bit(0, &ACCESS_FBINFO(irq_flags))) {
                if (request_irq(ACCESS_FBINFO(pcidev)->irq, matrox_irq,
-                               SA_SHIRQ, "matroxfb", MINFO)) {
+                               IRQF_SHARED, "matroxfb", MINFO)) {
                        clear_bit(0, &ACCESS_FBINFO(irq_flags));
                        return -EINVAL;
                }
@@ -241,7 +242,7 @@ int matroxfb_enable_irq(WPMINFO int reenable) {
                mga_outl(M_IEN, mga_inl(M_IEN) | bm);
        } else if (reenable) {
                u_int32_t ien;
-               
+
                ien = mga_inl(M_IEN);
                if ((ien & bm) != bm) {
                        printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
@@ -264,7 +265,6 @@ static void matroxfb_disable_irq(WPMINFO2) {
 }
 
 int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
-       wait_queue_t __wait;
        struct matrox_vsync *vs;
        unsigned int cnt;
        int ret;
@@ -286,7 +286,6 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
        if (ret) {
                return ret;
        }
-        init_waitqueue_entry(&__wait, current);
 
        cnt = vs->cnt;
        ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
@@ -349,7 +348,7 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
                mga_setr(M_EXTVGA_INDEX, 0x00, p2);
        }
        matroxfb_DAC_unlock_irqrestore(flags);
-       
+
        update_crtc2(PMINFO pos);
 
        CRITEND
@@ -392,7 +391,7 @@ static void matroxfb_remove(WPMINFO int dummy) {
 static int matroxfb_open(struct fb_info *info, int user)
 {
        MINFO_FROM_INFO(info);
-       
+
        DBG_LOOP(__FUNCTION__)
 
        if (ACCESS_FBINFO(dead)) {
@@ -408,7 +407,7 @@ static int matroxfb_open(struct fb_info *info, int user)
 static int matroxfb_release(struct fb_info *info, int user)
 {
        MINFO_FROM_INFO(info);
-       
+
        DBG_LOOP(__FUNCTION__)
 
        if (user) {
@@ -500,10 +499,6 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
        } else {
                xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp);
        }
-       if (!xres_new) return 0;
-       if (xres != xres_new) {
-               printk(KERN_INFO "matroxfb: cannot set xres to %d, rounded up to %d\n", xres, xres_new);
-       }
        return xres_new;
 }
 
@@ -835,6 +830,7 @@ static int matroxfb_set_par(struct fb_info *info)
                        matrox_cfbX_init(PMINFO2);
                }
        }
+       ACCESS_FBINFO(initialized) = 1;
        return 0;
 }
 
@@ -859,7 +855,7 @@ static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank)
                vblank->flags |= FB_VBLANK_VBLANKING;
        if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
                vblank->flags |= FB_VBLANK_HAVE_COUNT;
-               /* Only one writer, aligned int value... 
+               /* Only one writer, aligned int value...
                   it should work without lock and without atomic_t */
                vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt;
        }
@@ -870,12 +866,12 @@ static struct matrox_altout panellink_output = {
        .name    = "Panellink output",
 };
 
-static int matroxfb_ioctl(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg,
-                         struct fb_info *info)
+static int matroxfb_ioctl(struct fb_info *info,
+                         unsigned int cmd, unsigned long arg)
 {
+       void __user *argp = (void __user *)arg;
        MINFO_FROM_INFO(info);
-       
+
        DBG(__FUNCTION__)
 
        if (ACCESS_FBINFO(dead)) {
@@ -891,7 +887,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                err = matroxfb_get_vblank(PMINFO &vblank);
                                if (err)
                                        return err;
-                               if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank)))
+                               if (copy_to_user(argp, &vblank, sizeof(vblank)))
                                        return -EFAULT;
                                return 0;
                        }
@@ -899,7 +895,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                        {
                                u_int32_t crt;
 
-                               if (get_user(crt, (u_int32_t *)arg))
+                               if (get_user(crt, (u_int32_t __user *)arg))
                                        return -EFAULT;
 
                                return matroxfb_wait_for_sync(PMINFO crt);
@@ -910,7 +906,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                struct matrox_altout *oproc;
                                int val;
 
-                               if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
+                               if (copy_from_user(&mom, argp, sizeof(mom)))
                                        return -EFAULT;
                                if (mom.output >= MATROXFB_MAX_OUTPUTS)
                                        return -ENXIO;
@@ -960,7 +956,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                struct matrox_altout *oproc;
                                int val;
 
-                               if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom)))
+                               if (copy_from_user(&mom, argp, sizeof(mom)))
                                        return -EFAULT;
                                if (mom.output >= MATROXFB_MAX_OUTPUTS)
                                        return -ENXIO;
@@ -975,7 +971,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                up_read(&ACCESS_FBINFO(altout.lock));
                                if (val)
                                        return val;
-                               if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom)))
+                               if (copy_to_user(argp, &mom, sizeof(mom)))
                                        return -EFAULT;
                                return 0;
                        }
@@ -985,7 +981,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                int i;
                                int changes;
 
-                               if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp)))
+                               if (copy_from_user(&tmp, argp, sizeof(tmp)))
                                        return -EFAULT;
                                for (i = 0; i < 32; i++) {
                                        if (tmp & (1 << i)) {
@@ -1040,7 +1036,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                                conn |= 1 << i;
                                        }
                                }
-                               if (put_user(conn, (u_int32_t*)arg))
+                               if (put_user(conn, (u_int32_t __user *)arg))
                                        return -EFAULT;
                                return 0;
                        }
@@ -1065,7 +1061,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                        if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
                                                conn &= ~MATROXFB_OUTPUT_CONN_DFP;
                                }
-                               if (put_user(conn, (u_int32_t*)arg))
+                               if (put_user(conn, (u_int32_t __user *)arg))
                                        return -EFAULT;
                                return 0;
                        }
@@ -1079,31 +1075,31 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                                conn |= 1 << i;
                                        }
                                }
-                               if (put_user(conn, (u_int32_t*)arg))
+                               if (put_user(conn, (u_int32_t __user *)arg))
                                        return -EFAULT;
                                return 0;
                        }
                case VIDIOC_QUERYCAP:
                        {
                                struct v4l2_capability r;
-                               
+
                                memset(&r, 0, sizeof(r));
                                strcpy(r.driver, "matroxfb");
                                strcpy(r.card, "Matrox");
                                sprintf(r.bus_info, "PCI:%s", pci_name(ACCESS_FBINFO(pcidev)));
                                r.version = KERNEL_VERSION(1,0,0);
                                r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
-                               if (copy_to_user((void*)arg, &r, sizeof(r)))
+                               if (copy_to_user(argp, &r, sizeof(r)))
                                        return -EFAULT;
                                return 0;
-                               
+
                        }
                case VIDIOC_QUERYCTRL:
                        {
                                struct v4l2_queryctrl qctrl;
                                int err;
 
-                               if (copy_from_user(&qctrl, (struct v4l2_queryctrl*)arg, sizeof(qctrl)))
+                               if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
                                        return -EFAULT;
 
                                down_read(&ACCESS_FBINFO(altout).lock);
@@ -1116,7 +1112,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                }
                                up_read(&ACCESS_FBINFO(altout).lock);
                                if (err >= 0 &&
-                                   copy_to_user((struct v4l2_queryctrl*)arg, &qctrl, sizeof(qctrl)))
+                                   copy_to_user(argp, &qctrl, sizeof(qctrl)))
                                        return -EFAULT;
                                return err;
                        }
@@ -1125,7 +1121,7 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                struct v4l2_control ctrl;
                                int err;
 
-                               if (copy_from_user(&ctrl, (struct v4l2_control*)arg, sizeof(ctrl)))
+                               if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
                                        return -EFAULT;
 
                                down_read(&ACCESS_FBINFO(altout).lock);
@@ -1138,16 +1134,17 @@ static int matroxfb_ioctl(struct inode *inode, struct file *file,
                                }
                                up_read(&ACCESS_FBINFO(altout).lock);
                                if (err >= 0 &&
-                                   copy_to_user((struct v4l2_control*)arg, &ctrl, sizeof(ctrl)))
+                                   copy_to_user(argp, &ctrl, sizeof(ctrl)))
                                        return -EFAULT;
                                return err;
                        }
+               case VIDIOC_S_CTRL_OLD:
                case VIDIOC_S_CTRL:
                        {
                                struct v4l2_control ctrl;
                                int err;
 
-                               if (copy_from_user(&ctrl, (struct v4l2_control*)arg, sizeof(ctrl)))
+                               if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
                                        return -EFAULT;
 
                                down_read(&ACCESS_FBINFO(altout).lock);
@@ -1180,11 +1177,11 @@ static int matroxfb_blank(int blank, struct fb_info *info)
                return 1;
 
        switch (blank) {
-               case 1:  seq = 0x20; crtc = 0x00; break; /* works ??? */
-               case 2:  seq = 0x20; crtc = 0x10; break;
-               case 3:  seq = 0x20; crtc = 0x20; break;
-               case 4:  seq = 0x20; crtc = 0x30; break;
-               default: seq = 0x00; crtc = 0x00; break;
+       case FB_BLANK_NORMAL:  seq = 0x20; crtc = 0x00; break; /* works ??? */
+       case FB_BLANK_VSYNC_SUSPEND:  seq = 0x20; crtc = 0x10; break;
+       case FB_BLANK_HSYNC_SUSPEND:  seq = 0x20; crtc = 0x20; break;
+       case FB_BLANK_POWERDOWN:  seq = 0x20; crtc = 0x30; break;
+       default: seq = 0x00; crtc = 0x00; break;
        }
 
        CRITBEGIN
@@ -1272,6 +1269,7 @@ static unsigned int maxclk;               /* "matrox:maxclk:xxxxM" */
 static int dfp;                                /* "matrox:dfp */
 static int dfp_type = -1;              /* "matrox:dfp:xxx */
 static int memtype = -1;               /* "matrox:memtype:xxx" */
+static char outputs[8];                        /* "matrox:outputs:xxx" */
 
 #ifndef MODULE
 static char videomode[64];             /* "matrox:mode:xxxxx" or "matrox:xxxxx" */
@@ -1281,7 +1279,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
        vaddr_t vm;
        unsigned int offs;
        unsigned int offs2;
-       unsigned char store;
+       unsigned char orig;
        unsigned char bytes[32];
        unsigned char* tmp;
 
@@ -1294,18 +1292,15 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
        if (maxSize > 0x2000000) maxSize = 0x2000000;
 
        mga_outb(M_EXTVGA_INDEX, 0x03);
-       mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+       orig = mga_inb(M_EXTVGA_DATA);
+       mga_outb(M_EXTVGA_DATA, orig | 0x80);
 
-       store = mga_readb(vm, 0x1234);
        tmp = bytes;
        for (offs = 0x100000; offs < maxSize; offs += 0x200000)
                *tmp++ = mga_readb(vm, offs);
        for (offs = 0x100000; offs < maxSize; offs += 0x200000)
                mga_writeb(vm, offs, 0x02);
-       if (ACCESS_FBINFO(features.accel.has_cacheflush))
-               mga_outb(M_CACHEFLUSH, 0x00);
-       else
-               mga_writeb(vm, 0x1234, 0x99);
+       mga_outb(M_CACHEFLUSH, 0x00);
        for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
                if (mga_readb(vm, offs) != 0x02)
                        break;
@@ -1316,10 +1311,9 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
        tmp = bytes;
        for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
                mga_writeb(vm, offs2, *tmp++);
-       mga_writeb(vm, 0x1234, store);
 
        mga_outb(M_EXTVGA_INDEX, 0x03);
-       mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+       mga_outb(M_EXTVGA_DATA, orig);
 
        *realSize = offs - 0x100000;
 #ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -1342,7 +1336,7 @@ static struct video_board vbMillennium2A  = {0x1000000, 0x0800000, FB_ACCEL_MATRO
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
 static struct video_board vbMystique           = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG,     &matrox_mystique};
 #endif /* CONFIG_FB_MATROX_MYSTIQUE */
-#ifdef CONFIG_FB_MATROX_G100
+#ifdef CONFIG_FB_MATROX_G
 static struct video_board vbG100               = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100,       &matrox_G100};
 static struct video_board vbG200               = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200,       &matrox_G100};
 #ifdef CONFIG_FB_MATROX_32MB
@@ -1425,8 +1419,22 @@ static struct board {
                MGA_1164,
                &vbMystique,
                "Mystique 220 (PCI)"},
+       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_MYS_AGP,   0x02,
+               0,                      0,
+               DEVF_VIDEO64BIT | DEVF_CROSS4MB,
+               180000,
+               MGA_1064,
+               &vbMystique,
+               "Mystique (AGP)"},
+       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_MYS_AGP,   0xFF,
+               0,                      0,
+               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               220000,
+               MGA_1164,
+               &vbMystique,
+               "Mystique 220 (AGP)"},
 #endif
-#ifdef CONFIG_FB_MATROX_G100
+#ifdef CONFIG_FB_MATROX_G
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_MM,   0xFF,
                0,                      0,
                DEVF_G100,
@@ -1537,12 +1545,50 @@ static struct fb_videomode defaultmode = {
 
 static int hotplug = 0;
 
+static void setDefaultOutputs(WPMINFO2) {
+       unsigned int i;
+       const char* ptr;
+
+       ACCESS_FBINFO(outputs[0]).default_src = MATROXFB_SRC_CRTC1;
+       if (ACCESS_FBINFO(devflags.g450dac)) {
+               ACCESS_FBINFO(outputs[1]).default_src = MATROXFB_SRC_CRTC1;
+               ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1;
+       } else if (dfp) {
+               ACCESS_FBINFO(outputs[2]).default_src = MATROXFB_SRC_CRTC1;
+       }
+       ptr = outputs;
+       for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
+               char c = *ptr++;
+
+               if (c == 0) {
+                       break;
+               }
+               if (c == '0') {
+                       ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_NONE;
+               } else if (c == '1') {
+                       ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC1;
+               } else if (c == '2' && ACCESS_FBINFO(devflags.crtc2)) {
+                       ACCESS_FBINFO(outputs[i]).default_src = MATROXFB_SRC_CRTC2;
+               } else {
+                       printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
+                       break;
+               }
+       }
+       /* Nullify this option for subsequent adapters */
+       outputs[0] = 0;
+}
+
 static int initMatrox2(WPMINFO struct board* b){
        unsigned long ctrlptr_phys = 0;
        unsigned long video_base_phys = 0;
        unsigned int memsize;
        int err;
 
+       static struct pci_device_id intel_82437[] = {
+               { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437) },
+               { },
+       };
+
        DBG(__FUNCTION__)
 
        /* set default values... */
@@ -1577,20 +1623,18 @@ static int initMatrox2(WPMINFO struct board* b){
        ACCESS_FBINFO(devflags.crtc2) = (b->flags & DEVF_CRTC2) != 0;
        ACCESS_FBINFO(devflags.maven_capable) = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
        ACCESS_FBINFO(devflags.dualhead) = (b->flags & DEVF_DUALHEAD) != 0;
+       ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
+       ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0;
+       ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
+       ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
+       setDefaultOutputs(PMINFO2);
        if (b->flags & DEVF_PANELLINK_CAPABLE) {
                ACCESS_FBINFO(outputs[2]).data = MINFO;
                ACCESS_FBINFO(outputs[2]).output = &panellink_output;
-               if (dfp)
-                       ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_CRTC1;
-               else
-                       ACCESS_FBINFO(outputs[2]).src = MATROXFB_SRC_NONE;
+               ACCESS_FBINFO(outputs[2]).src = ACCESS_FBINFO(outputs[2]).default_src;
                ACCESS_FBINFO(outputs[2]).mode = MATROXFB_OUTPUT_MODE_MONITOR;
                ACCESS_FBINFO(devflags.panellink) = 1;
        }
-       ACCESS_FBINFO(devflags.dfp_type) = dfp_type;
-       ACCESS_FBINFO(devflags.g450dac) = (b->flags & DEVF_G450DAC) != 0;
-       ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
-       ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
 
        if (ACCESS_FBINFO(capable.cross4MB) < 0)
                ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
@@ -1647,9 +1691,9 @@ static int initMatrox2(WPMINFO struct board* b){
                pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd);
                mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
                mga_option |= MX_OPTION_BSWAP;
-                /* disable palette snooping */
-                cmd &= ~PCI_COMMAND_VGA_PALETTE;
-               if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, NULL)) {
+               /* disable palette snooping */
+               cmd &= ~PCI_COMMAND_VGA_PALETTE;
+               if (pci_dev_present(intel_82437)) {
                        if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) {
                                printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
                        }
@@ -1678,7 +1722,6 @@ static int initMatrox2(WPMINFO struct board* b){
        }
        ACCESS_FBINFO(devflags.ydstorg) = 0;
 
-       ACCESS_FBINFO(fbcon.currcon) = -1;
        ACCESS_FBINFO(video.base) = video_base_phys;
        ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len);
        if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable)
@@ -1717,6 +1760,12 @@ static int initMatrox2(WPMINFO struct board* b){
        ACCESS_FBINFO(fbcon.pseudo_palette) = ACCESS_FBINFO(cmap);
        /* after __init time we are like module... no logo */
        ACCESS_FBINFO(fbcon.flags) = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT;
+       ACCESS_FBINFO(fbcon.flags) |= FBINFO_PARTIAL_PAN_OK |    /* Prefer panning for scroll under MC viewer/edit */
+                                     FBINFO_HWACCEL_COPYAREA |  /* We have hw-assisted bmove */
+                                     FBINFO_HWACCEL_FILLRECT |  /* And fillrect */
+                                     FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
+                                     FBINFO_HWACCEL_XPAN |      /* And we support both horizontal */
+                                     FBINFO_HWACCEL_YPAN;       /* And vertical panning */
        ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
        fb_alloc_cmap(&ACCESS_FBINFO(fbcon.cmap), 256, 1);
 
@@ -1761,12 +1810,12 @@ static int initMatrox2(WPMINFO struct board* b){
 
                if (fv) {
                        tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
-                                 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
+                                 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
                        if ((tmp < fh) || (fh == 0)) fh = tmp;
                }
                if (fh) {
                        tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
-                                 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
+                                 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
                        if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
                }
                tmp = (maxclk + 499) / 500;
@@ -1786,7 +1835,7 @@ static int initMatrox2(WPMINFO struct board* b){
        /* FIXME: Where to move this?! */
 #if defined(CONFIG_PPC_PMAC)
 #ifndef MODULE
-       if (_machine == _MACH_Pmac) {
+       if (machine_is(powermac)) {
                struct fb_var_screeninfo var;
                if (default_vmode <= 0 || default_vmode > VMODE_MAX)
                        default_vmode = VMODE_640_480_60;
@@ -1813,6 +1862,15 @@ static int initMatrox2(WPMINFO struct board* b){
                                                        to yres_virtual * xres_virtual < 2^32 */
        }
        matroxfb_init_fix(PMINFO2);
+       ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+       matroxfb_update_fix(PMINFO2);
+       /* Normalize values (namely yres_virtual) */
+       matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
+       /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
+        * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
+        * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
+        * anyway. But we at least tried... */
+       ACCESS_FBINFO(fbcon.var) = vesafb_defined;
        err = -EINVAL;
 
        printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
@@ -1824,18 +1882,24 @@ static int initMatrox2(WPMINFO struct board* b){
 /* We do not have to set currcon to 0... register_framebuffer do it for us on first console
  * and we do not want currcon == 0 for subsequent framebuffers */
 
+       ACCESS_FBINFO(fbcon).device = &ACCESS_FBINFO(pcidev)->dev;
        if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) {
                goto failVideoIO;
        }
        printk("fb%d: %s frame buffer device\n",
               ACCESS_FBINFO(fbcon.node), ACCESS_FBINFO(fbcon.fix.id));
-       if (ACCESS_FBINFO(fbcon.currcon) < 0) {
-               /* there is no console on this fb... but we have to initialize hardware
-                * until someone tells me what is proper thing to do */
+
+       /* there is no console on this fb... but we have to initialize hardware
+        * until someone tells me what is proper thing to do */
+       if (!ACCESS_FBINFO(initialized)) {
                printk(KERN_INFO "fb%d: initializing hardware\n",
-                       ACCESS_FBINFO(fbcon.node));
+                      ACCESS_FBINFO(fbcon.node));
+               /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
+                * already before, so register_framebuffer works correctly. */
+               vesafb_defined.activate |= FB_ACTIVATE_FORCE;
                fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
        }
+
        return 0;
 failVideoIO:;
        matroxfb_g450_shutdown(PMINFO2);
@@ -1850,8 +1914,8 @@ fail:;
        return err;
 }
 
-LIST_HEAD(matroxfb_list);
-LIST_HEAD(matroxfb_driver_list);
+static LIST_HEAD(matroxfb_list);
+static LIST_HEAD(matroxfb_driver_list);
 
 #define matroxfb_l(x) list_entry(x, struct matrox_fb_info, next_fb)
 #define matroxfb_driver_l(x) list_entry(x, struct matroxfb_driver, node)
@@ -1952,11 +2016,11 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
        }
        /* not match... */
        if (!b->vendor)
-               return -1;
+               return -ENODEV;
        if (dev > 0) {
                /* not requested one... */
                dev--;
-               return -1;
+               return -ENODEV;
        }
        pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
        if (pci_enable_device(pdev)) {
@@ -1964,7 +2028,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
        }
 
 #ifdef CONFIG_FB_MATROX_MULTIHEAD
-       minfo = (struct matrox_fb_info*)kmalloc(sizeof(*minfo), GFP_KERNEL);
+       minfo = kmalloc(sizeof(*minfo), GFP_KERNEL);
        if (!minfo)
                return -1;
 #else
@@ -2047,7 +2111,7 @@ static struct pci_device_id matroxfb_devices[] = {
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_MYS,
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
 #endif
-#ifdef CONFIG_FB_MATROX_G100
+#ifdef CONFIG_FB_MATROX_G
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_MM,
                PCI_ANY_ID,     PCI_ANY_ID,     0, 0, 0},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,
@@ -2213,10 +2277,13 @@ static void __init matroxfb_init_params(void) {
        }
 }
 
-static void __init matrox_init(void) {
+static int __init matrox_init(void) {
+       int err;
+
        matroxfb_init_params();
-       pci_register_driver(&matroxfb_driver);
+       err = pci_register_driver(&matroxfb_driver);
        dev = -1;       /* accept all new devices... */
+       return err;
 }
 
 /* **************************** exit-time only **************************** */
@@ -2229,7 +2296,7 @@ static void __exit matrox_done(void) {
 
 /* ************************* init in-kernel code ************************** */
 
-int __init matroxfb_setup(char *options) {
+static int __init matroxfb_setup(char *options) {
        char *this_opt;
 
        DBG(__FUNCTION__)
@@ -2288,10 +2355,12 @@ int __init matroxfb_setup(char *options) {
                        mem = simple_strtoul(this_opt+4, NULL, 0);
                else if (!strncmp(this_opt, "mode:", 5))
                        strlcpy(videomode, this_opt+5, sizeof(videomode));
+               else if (!strncmp(this_opt, "outputs:", 8))
+                       strlcpy(outputs, this_opt+8, sizeof(outputs));
                else if (!strncmp(this_opt, "dfp:", 4)) {
                        dfp_type = simple_strtoul(this_opt+4, NULL, 0);
                        dfp = 1;
-               }       
+               }
 #ifdef CONFIG_PPC_PMAC
                else if (!strncmp(this_opt, "vmode:", 6)) {
                        unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
@@ -2368,21 +2437,30 @@ int __init matroxfb_setup(char *options) {
 
 static int __initdata initialized = 0;
 
-int __init matroxfb_init(void)
+static int __init matroxfb_init(void)
 {
+       char *option = NULL;
+       int err = 0;
+
        DBG(__FUNCTION__)
 
+       if (fb_get_options("matroxfb", &option))
+               return -ENODEV;
+       matroxfb_setup(option);
+
        if (disabled)
                return -ENXIO;
        if (!initialized) {
                initialized = 1;
-               matrox_init();
+               err = matrox_init();
        }
        hotplug = 1;
        /* never return failure, user can hotplug matrox later... */
-       return 0;
+       return err;
 }
 
+module_init(matroxfb_init);
+
 #else
 
 /* *************************** init module code **************************** */
@@ -2391,82 +2469,86 @@ MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
 MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(mem, "i");
+module_param(mem, int, 0);
 MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
-MODULE_PARM(disabled, "i");
+module_param(disabled, int, 0);
 MODULE_PARM_DESC(disabled, "Disabled (0 or 1=disabled) (default=0)");
-MODULE_PARM(noaccel, "i");
+module_param(noaccel, int, 0);
 MODULE_PARM_DESC(noaccel, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
-MODULE_PARM(nopan, "i");
+module_param(nopan, int, 0);
 MODULE_PARM_DESC(nopan, "Disable pan on startup (0 or 1=disabled) (default=0)");
-MODULE_PARM(no_pci_retry, "i");
+module_param(no_pci_retry, int, 0);
 MODULE_PARM_DESC(no_pci_retry, "PCI retries enabled (0 or 1=disabled) (default=0)");
-MODULE_PARM(novga, "i");
+module_param(novga, int, 0);
 MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
-MODULE_PARM(nobios, "i");
+module_param(nobios, int, 0);
 MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
-MODULE_PARM(noinit, "i");
+module_param(noinit, int, 0);
 MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
-MODULE_PARM(memtype, "i");
+module_param(memtype, int, 0);
 MODULE_PARM_DESC(memtype, "Memory type for G200/G400 (see Documentation/fb/matroxfb.txt for explanation) (default=3 for G200, 0 for G400)");
-MODULE_PARM(mtrr, "i");
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0);
 MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
-MODULE_PARM(sgram, "i");
+#endif
+module_param(sgram, int, 0);
 MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
-MODULE_PARM(inv24, "i");
+module_param(inv24, int, 0);
 MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
-MODULE_PARM(inverse, "i");
+module_param(inverse, int, 0);
 MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
 #ifdef CONFIG_FB_MATROX_MULTIHEAD
-MODULE_PARM(dev, "i");
+module_param(dev, int, 0);
 MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
 #else
-MODULE_PARM(dev, "i");
+module_param(dev, int, 0);
 MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)");
 #endif
-MODULE_PARM(vesa, "i");
+module_param(vesa, int, 0);
 MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
-MODULE_PARM(xres, "i");
+module_param(xres, int, 0);
 MODULE_PARM_DESC(xres, "Horizontal resolution (px), overrides xres from vesa (default=vesa)");
-MODULE_PARM(yres, "i");
+module_param(yres, int, 0);
 MODULE_PARM_DESC(yres, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
-MODULE_PARM(upper, "i");
+module_param(upper, int, 0);
 MODULE_PARM_DESC(upper, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
-MODULE_PARM(lower, "i");
+module_param(lower, int, 0);
 MODULE_PARM_DESC(lower, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
-MODULE_PARM(vslen, "i");
+module_param(vslen, int, 0);
 MODULE_PARM_DESC(vslen, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
-MODULE_PARM(left, "i");
+module_param(left, int, 0);
 MODULE_PARM_DESC(left, "Left blank space (px), overrides left from vesa (default=vesa)");
-MODULE_PARM(right, "i");
+module_param(right, int, 0);
 MODULE_PARM_DESC(right, "Right blank space (px), overrides right from vesa (default=vesa)");
-MODULE_PARM(hslen, "i");
+module_param(hslen, int, 0);
 MODULE_PARM_DESC(hslen, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
-MODULE_PARM(pixclock, "i");
+module_param(pixclock, int, 0);
 MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
-MODULE_PARM(sync, "i");
+module_param(sync, int, 0);
 MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
-MODULE_PARM(depth, "i");
+module_param(depth, int, 0);
 MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
-MODULE_PARM(maxclk, "i");
+module_param(maxclk, int, 0);
 MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
-MODULE_PARM(fh, "i");
+module_param(fh, int, 0);
 MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
-MODULE_PARM(fv, "i");
+module_param(fv, int, 0);
 MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
 "You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n");
-MODULE_PARM(grayscale, "i");
+module_param(grayscale, int, 0);
 MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
-MODULE_PARM(cross4MB, "i");
+module_param(cross4MB, int, 0);
 MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
-MODULE_PARM(dfp, "i");
+module_param(dfp, int, 0);
 MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
-MODULE_PARM(dfp_type, "i");
+module_param(dfp_type, int, 0);
 MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
+module_param_string(outputs, outputs, sizeof(outputs), 0);
+MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)");
 #ifdef CONFIG_PPC_PMAC
-MODULE_PARM(vmode, "i");
+module_param_named(vmode, default_vmode, int, 0);
 MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
-MODULE_PARM(cmode, "i");
+module_param_named(cmode, default_cmode, int, 0);
 MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)");
 #endif