[PATCH] intelfb: extend partial support of i915G to include i915GM
[safe/jmp/linux-2.6] / drivers / video / intelfb / intelfbdrv.c
index 6a05b70..e6d75b9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * intelfb
  *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM
  * integrated graphics chips.
  *
  * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
 #include <linux/pagemap.h>
 #include <linux/version.h>
 
 #endif
 
 #include "intelfb.h"
-#include "intelfbdrv.h"
 #include "intelfbhw.h"
 
+static void __devinit get_initial_mode(struct intelfb_info *dinfo);
+static void update_dinfo(struct intelfb_info *dinfo,
+                        struct fb_var_screeninfo *var);
+static int intelfb_get_fix(struct fb_fix_screeninfo *fix,
+                          struct fb_info *info);
+
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+                            struct fb_info *info);
+static int intelfb_set_par(struct fb_info *info);
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                            unsigned blue, unsigned transp,
+                            struct fb_info *info);
+
+static int intelfb_blank(int blank, struct fb_info *info);
+static int intelfb_pan_display(struct fb_var_screeninfo *var,
+                              struct fb_info *info);
+
+static void intelfb_fillrect(struct fb_info *info,
+                            const struct fb_fillrect *rect);
+static void intelfb_copyarea(struct fb_info *info,
+                            const struct fb_copyarea *region);
+static void intelfb_imageblit(struct fb_info *info,
+                             const struct fb_image *image);
+static int intelfb_cursor(struct fb_info *info,
+                          struct fb_cursor *cursor);
+
+static int intelfb_sync(struct fb_info *info);
+
+static int intelfb_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg,
+                        struct fb_info *info);
+
+static int __devinit intelfb_pci_register(struct pci_dev *pdev,
+                                         const struct pci_device_id *ent);
+static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
+static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
+
 /*
  * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
  * mobile chipsets from being registered.
@@ -154,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
        { 0, }
 };
 
@@ -178,7 +211,7 @@ static struct fb_ops intel_fb_ops = {
 
 /* PCI driver module table */
 static struct pci_driver intelfb_driver = {
-       .name =         "Intel(R) " SUPPORTED_CHIPSETS " Framebuffer Driver",
+       .name =         "intelfb",
        .id_table =     intelfb_pci_table,
        .probe =        intelfb_pci_register,
        .remove =       __devexit_p(intelfb_pci_unregister)
@@ -192,22 +225,25 @@ MODULE_DESCRIPTION(
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
 
-static int accel        __initdata = 1;
-static int vram         __initdata = 4;
-static int hwcursor     __initdata = 1;
-static int mtrr         __initdata = 1;
-static int fixed        __initdata = 0;
-static int noinit       __initdata = 0;
-static int noregister   __initdata = 0;
-static int probeonly    __initdata = 0;
-static int idonly       __initdata = 0;
-static int bailearly    __initdata = 0;
-static char *mode       __initdata = NULL;
+static int accel        = 1;
+static int vram         = 4;
+static int hwcursor     = 0;
+static int mtrr         = 1;
+static int fixed        = 0;
+static int noinit       = 0;
+static int noregister   = 0;
+static int probeonly    = 0;
+static int idonly       = 0;
+static int bailearly    = 0;
+static int voffset     = 48;
+static char *mode       = NULL;
 
 module_param(accel, bool, S_IRUGO);
-MODULE_PARM_DESC(accel, "Enable console acceleration");
+MODULE_PARM_DESC(accel, "Enable hardware acceleration");
 module_param(vram, int, S_IRUGO);
 MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
+module_param(voffset, int, S_IRUGO);
+MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
 module_param(hwcursor, bool, S_IRUGO);
 MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
 module_param(mtrr, bool, S_IRUGO);
@@ -459,7 +495,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct intelfb_info *dinfo;
-       int i, j, err, dvo;
+       int i, err, dvo;
        int aperture_size, stolen_size;
        struct agp_kern_info gtt_info;
        int agp_memtype;
@@ -467,6 +503,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct agp_bridge_data *bridge;
        int aperture_bar = 0;
        int mmio_bar = 1;
+       int offset;
 
        DBG_MSG("intelfb_pci_register\n");
 
@@ -513,10 +550,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        /* Set base addresses. */
-       if (ent->device == PCI_DEVICE_ID_INTEL_915G) {
+       if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
+                       (ent->device == PCI_DEVICE_ID_INTEL_915GM)) {
                aperture_bar = 2;
                mmio_bar = 0;
-               /* Disable HW cursor on 915G (not implemented yet) */
+               /* Disable HW cursor on 915G/M (not implemented yet) */
                hwcursor = 0;
        }
        dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
@@ -543,23 +581,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
-       /* Map the fb and MMIO regions */
-       dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
-               (dinfo->aperture.physical, dinfo->aperture.size);
-       if (!dinfo->aperture.virtual) {
-               ERR_MSG("Cannot remap FB region.\n");
-               cleanup(dinfo);
-               return -ENODEV;
-       }
-       dinfo->mmio_base =
-               (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
-                                              INTEL_REG_SIZE);
-       if (!dinfo->mmio_base) {
-               ERR_MSG("Cannot remap MMIO region.\n");
-               cleanup(dinfo);
-               return -ENODEV;
-       }
-
        /* Get the chipset info. */
        dinfo->pci_chipset = pdev->device;
 
@@ -623,22 +644,46 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
+       if (MB(voffset) < stolen_size)
+               offset = (stolen_size >> 12);
+       else
+               offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
        /* set the mem offsets - set them after the already used pages */
        if (dinfo->accel) {
-               dinfo->ring.offset = (stolen_size >> 12)
-                       + gtt_info.current_memory;
+               dinfo->ring.offset = offset + gtt_info.current_memory;
        }
        if (dinfo->hwcursor) {
-               dinfo->cursor.offset = (stolen_size >> 12) +
+               dinfo->cursor.offset = offset +
                        + gtt_info.current_memory + (dinfo->ring.size >> 12);
        }
        if (dinfo->fbmem_gart) {
-               dinfo->fb.offset = (stolen_size >> 12) +
+               dinfo->fb.offset = offset +
                        + gtt_info.current_memory + (dinfo->ring.size >> 12)
                        + (dinfo->cursor.size >> 12);
        }
 
        /* Allocate memories (which aren't stolen) */
+       /* Map the fb and MMIO regions */
+       /* ioremap only up to the end of used aperture */
+       dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
+               (dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)
+                + dinfo->fb.size);
+       if (!dinfo->aperture.virtual) {
+               ERR_MSG("Cannot remap FB region.\n");
+               cleanup(dinfo);
+               return -ENODEV;
+       }
+
+       dinfo->mmio_base =
+               (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
+                                              INTEL_REG_SIZE);
+       if (!dinfo->mmio_base) {
+               ERR_MSG("Cannot remap MMIO region.\n");
+               cleanup(dinfo);
+               return -ENODEV;
+       }
+
        if (dinfo->accel) {
                if (!(dinfo->gtt_ring_mem =
                      agp_allocate_memory(bridge, dinfo->ring.size >> 12,
@@ -797,13 +842,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (bailearly == 5)
                bailout(dinfo);
 
-       for (i = 0; i < 16; i++) {
-               j = color_table[i];
-               dinfo->palette[i].red = default_red[j];
-               dinfo->palette[i].green = default_grn[j];
-               dinfo->palette[i].blue = default_blu[j];
-       }
-
        if (bailearly == 6)
                bailout(dinfo);
 
@@ -1047,6 +1085,7 @@ intelfb_set_fbinfo(struct intelfb_info *dinfo)
 
        info->pixmap.size = 64*1024;
        info->pixmap.buf_align = 8;
+       info->pixmap.access_align = 32;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
        if (intelfb_init_var(dinfo))
@@ -1257,7 +1296,7 @@ intelfb_set_par(struct fb_info *info)
 
        intelfb_blank(FB_BLANK_POWERDOWN, info);
 
-       if (dinfo->accel)
+       if (ACCEL(dinfo, info))
                intelfbhw_2d_stop(dinfo);
 
        memcpy(hw, &dinfo->save_state, sizeof(*hw));
@@ -1273,7 +1312,7 @@ intelfb_set_par(struct fb_info *info)
 
        update_dinfo(dinfo, &info->var);
 
-       if (dinfo->accel)
+       if (ACCEL(dinfo, info))
                intelfbhw_2d_start(dinfo);
 
        intelfb_pan_display(&info->var, info);
@@ -1314,10 +1353,6 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                        green >>= 8;
                        blue >>= 8;
 
-                       dinfo->palette[regno].red = red;
-                       dinfo->palette[regno].green = green;
-                       dinfo->palette[regno].blue = blue;
-
                        intelfbhw_setcolreg(dinfo, regno, red, green, blue,
                                            transp);
                }