intelfb: fixup p calculation
[safe/jmp/linux-2.6] / drivers / video / intelfb / intelfbdrv.c
index 0799b99..9e83664 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * intelfb
  *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM
- * integrated graphics chips.
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
+ * 945G/945GM integrated graphics chips.
  *
  * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
  *                   2004 Sylvain Meyer
+ *                   2006 David Airlie
  *
  * This driver consists of two parts.  The first part (intelfbdrv.c) provides
  * the basic fbdev interfaces, is derived in part from the radeonfb and
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
-#include <linux/version.h>
 
 #include <asm/io.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);
@@ -161,9 +158,8 @@ static int intelfb_cursor(struct fb_info *info,
 
 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 intelfb_ioctl(struct fb_info *info,
+                        unsigned int cmd, unsigned long arg);
 
 static int __devinit intelfb_pci_register(struct pci_dev *pdev,
                                          const struct pci_device_id *ent);
@@ -187,6 +183,8 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
        { 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 },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
        { 0, }
 };
 
@@ -474,9 +472,9 @@ cleanup(struct intelfb_info *dinfo)
        if (dinfo->aperture.virtual)
                iounmap((void __iomem *)dinfo->aperture.virtual);
 
-       if (dinfo->mmio_base_phys)
+       if (dinfo->flag & INTELFB_MMIO_ACQUIRED)
                release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
-       if (dinfo->aperture.physical)
+       if (dinfo->flag & INTELFB_FB_ACQUIRED)
                release_mem_region(dinfo->aperture.physical,
                                   dinfo->aperture.size);
        framebuffer_release(dinfo->info);
@@ -551,11 +549,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) ||
-                       (ent->device == PCI_DEVICE_ID_INTEL_915GM)) {
+           (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
+           (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
+           (ent->device == PCI_DEVICE_ID_INTEL_945GM)) {
                aperture_bar = 2;
                mmio_bar = 0;
-               /* Disable HW cursor on 915G/M (not implemented yet) */
-               hwcursor = 0;
        }
        dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
        dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
@@ -573,6 +571,9 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                cleanup(dinfo);
                return -ENODEV;
        }
+
+       dinfo->flag |= INTELFB_FB_ACQUIRED;
+
        if (!request_mem_region(dinfo->mmio_base_phys,
                                INTEL_REG_SIZE,
                                INTELFB_MODULE_NAME)) {
@@ -581,11 +582,12 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENODEV;
        }
 
+       dinfo->flag |= INTELFB_MMIO_ACQUIRED;
+
        /* Get the chipset info. */
        dinfo->pci_chipset = pdev->device;
 
-       if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset,
-                                 &dinfo->mobile)) {
+       if (intelfbhw_get_chipset(pdev, dinfo)) {
                cleanup(dinfo);
                return -ENODEV;
        }
@@ -1092,7 +1094,17 @@ intelfb_set_fbinfo(struct intelfb_info *dinfo)
                return 1;
 
        info->pixmap.scan_align = 1;
-
+       strcpy(info->fix.id, dinfo->name);
+       info->fix.smem_start = dinfo->fb.physical;
+       info->fix.smem_len = dinfo->fb.size;
+       info->fix.type = FB_TYPE_PACKED_PIXELS;
+       info->fix.type_aux = 0;
+       info->fix.xpanstep = 8;
+       info->fix.ypanstep = 1;
+       info->fix.ywrapstep = 0;
+       info->fix.mmio_start = dinfo->mmio_base_phys;
+       info->fix.mmio_len = INTEL_REG_SIZE;
+       info->fix.accel = FB_ACCEL_I830;
        update_dinfo(dinfo, &info->var);
 
        return 0;
@@ -1110,7 +1122,8 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
        dinfo->yres = var->xres;
        dinfo->pixclock = var->pixclock;
 
-       intelfb_get_fix(&dinfo->info->fix, dinfo->info);
+       dinfo->info->fix.visual = dinfo->visual;
+       dinfo->info->fix.line_length = dinfo->pitch;
 
        switch (dinfo->bpp) {
        case 8:
@@ -1140,30 +1153,6 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
 
 /* fbops functions */
 
-static int
-intelfb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
-{
-       struct intelfb_info *dinfo = GET_DINFO(info);
-
-       DBG_MSG("intelfb_get_fix\n");
-
-       memset(fix, 0, sizeof(*fix));
-       strcpy(fix->id, dinfo->name);
-       fix->smem_start = dinfo->fb.physical;
-       fix->smem_len = dinfo->fb.size;
-       fix->type = FB_TYPE_PACKED_PIXELS;
-       fix->type_aux = 0;
-       fix->visual = dinfo->visual;
-       fix->xpanstep = 8;
-       fix->ypanstep = 1;
-       fix->ywrapstep = 0;
-       fix->line_length = dinfo->pitch;
-       fix->mmio_start = dinfo->mmio_base_phys;
-       fix->mmio_len = INTEL_REG_SIZE;
-       fix->accel = FB_ACCEL_I830;
-       return 0;
-}
-
 /***************************************************************
  *                       fbdev interface                       *
  ***************************************************************/
@@ -1346,33 +1335,35 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
        if (regno > 255)
                return 1;
 
-       switch (dinfo->depth) {
-       case 8:
-               {
-                       red >>= 8;
-                       green >>= 8;
-                       blue >>= 8;
+       if (dinfo->depth == 8) {
+               red >>= 8;
+               green >>= 8;
+               blue >>= 8;
 
-                       intelfbhw_setcolreg(dinfo, regno, red, green, blue,
-                                           transp);
+               intelfbhw_setcolreg(dinfo, regno, red, green, blue,
+                                   transp);
+       }
+
+       if (regno < 16) {
+               switch (dinfo->depth) {
+               case 15:
+                       dinfo->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
+                               ((green & 0xf800) >>  6) |
+                               ((blue & 0xf800) >> 11);
+                       break;
+               case 16:
+                       dinfo->pseudo_palette[regno] = (red & 0xf800) |
+                               ((green & 0xfc00) >>  5) |
+                               ((blue  & 0xf800) >> 11);
+                       break;
+               case 24:
+                       dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+                               (green & 0xff00) |
+                               ((blue  & 0xff00) >> 8);
+                       break;
                }
-               break;
-       case 15:
-               dinfo->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
-                                              ((green & 0xf800) >>  6) |
-                                              ((blue & 0xf800) >> 11);
-               break;
-       case 16:
-               dinfo->pseudo_palette[regno] = (red & 0xf800) |
-                                              ((green & 0xfc00) >>  5) |
-                                              ((blue  & 0xf800) >> 11);
-               break;
-       case 24:
-               dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
-                                              (green & 0xff00) |
-                                              ((blue  & 0xff00) >> 8);
-               break;
        }
+
        return 0;
 }
 
@@ -1392,8 +1383,7 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 
 /* When/if we have our own ioctls. */
 static int
-intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-             unsigned long arg, struct fb_info *info)
+intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
        int retval = 0;
 
@@ -1479,7 +1469,7 @@ static int
 intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
         struct intelfb_info *dinfo = GET_DINFO(info);
-
+       u32 physical;
 #if VERBOSE > 0
        DBG_MSG("intelfb_cursor\n");
 #endif
@@ -1490,7 +1480,10 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        intelfbhw_cursor_hide(dinfo);
 
        /* If XFree killed the cursor - restore it */
-       if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) {
+       physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
+                  (dinfo->cursor.offset << 12);
+
+       if (INREG(CURSOR_A_BASEADDR) != physical) {
                u32 fg, bg;
 
                DBG_MSG("the cursor was killed - restore it !!\n");