X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fintelfb%2Fintelfbdrv.c;h=664fc5cf962a42f6f18cda1c5dc9f87ee5c236d0;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=25f9a9a65c24938c23ebd3e0fb9ad164022baacd;hpb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;p=linux-2.6.git diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 25f9a9a65..664fc5cf9 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1,11 +1,12 @@ /* * intelfb * - * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G - * 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 * 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 @@ -107,26 +108,20 @@ * */ -#include #include #include #include #include #include -#include #include #include #include -#include -#include #include #include #include #include -#include -#include #include -#include +#include #include @@ -136,13 +131,13 @@ #include "intelfb.h" #include "intelfbhw.h" +#include "../edid.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_open(struct fb_info *info, int user); +static int intelfb_release(struct fb_info *info, int user); static int intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); static int intelfb_set_par(struct fb_info *info); @@ -165,9 +160,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); @@ -190,6 +184,9 @@ 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 }, + { 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, } }; @@ -199,6 +196,8 @@ static int num_registered = 0; /* fb ops */ static struct fb_ops intel_fb_ops = { .owner = THIS_MODULE, + .fb_open = intelfb_open, + .fb_release = intelfb_release, .fb_check_var = intelfb_check_var, .fb_set_par = intelfb_set_par, .fb_setcolreg = intelfb_setcolreg, @@ -214,7 +213,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) @@ -230,7 +229,7 @@ MODULE_DEVICE_TABLE(pci, intelfb_pci_table); static int accel = 1; static int vram = 4; -static int hwcursor = 1; +static int hwcursor = 0; static int mtrr = 1; static int fixed = 0; static int noinit = 0; @@ -238,12 +237,15 @@ 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); @@ -266,7 +268,7 @@ MODULE_PARM_DESC(mode, #ifndef MODULE #define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name))) -#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0) +#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0) #define OPT_STRVAL(opt, name) (opt + strlen(name)) static __inline__ char * @@ -448,6 +450,8 @@ cleanup(struct intelfb_info *dinfo) if (!dinfo) return; + intelfbhw_disable_irq(dinfo); + fb_dealloc_cmap(&dinfo->info->cmap); kfree(dinfo->info->pixmap.addr); @@ -469,14 +473,19 @@ cleanup(struct intelfb_info *dinfo) agp_free_memory(dinfo->gtt_ring_mem); } +#ifdef CONFIG_FB_INTEL_I2C + /* un-register I2C bus */ + intelfb_delete_i2c_busses(dinfo); +#endif + if (dinfo->mmio_base) iounmap((void __iomem *)dinfo->mmio_base); 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); @@ -495,7 +504,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; @@ -503,6 +512,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"); @@ -549,11 +559,12 @@ 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) || + (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 (not implemented yet) */ - hwcursor = 0; } dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar); dinfo->aperture.size = pci_resource_len(pdev, aperture_bar); @@ -571,6 +582,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)) { @@ -579,28 +593,12 @@ 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; - } + 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; } @@ -659,22 +657,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, @@ -695,7 +717,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) + (dinfo->ring.offset << 12); dinfo->ring.virtual = dinfo->aperture.virtual + (dinfo->ring.offset << 12); - dinfo->ring_head = dinfo->ring.virtual; + dinfo->ring_head = 0; } if (dinfo->hwcursor) { agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY @@ -754,18 +776,18 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) if (mtrr) set_mtrr(dinfo); - DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%x)\n", + DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n", dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size, - (u32 __iomem ) dinfo->fb.virtual); - DBG_MSG("MMIO: 0x%x/0x%x (0x%x)\n", + dinfo->fb.virtual); + DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n", dinfo->mmio_base_phys, INTEL_REG_SIZE, - (u32 __iomem) dinfo->mmio_base); - DBG_MSG("ring buffer: 0x%x/0x%x (0x%x)\n", + dinfo->mmio_base); + DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n", dinfo->ring.physical, dinfo->ring.size, - (u32 __iomem ) dinfo->ring.virtual); - DBG_MSG("HW cursor: 0x%x/0x%x (0x%x) (offset 0x%x) (phys 0x%x)\n", + dinfo->ring.virtual); + DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n", dinfo->cursor.physical, dinfo->cursor.size, - (u32 __iomem ) dinfo->cursor.virtual, dinfo->cursor.offset, + dinfo->cursor.virtual, dinfo->cursor.offset, dinfo->cursor.physical); DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, " @@ -833,12 +855,10 @@ 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]; - } +#ifdef CONFIG_FB_INTEL_I2C + /* register I2C bus */ + intelfb_create_i2c_busses(dinfo); +#endif if (bailearly == 6) bailout(dinfo); @@ -884,6 +904,13 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) } dinfo->registered = 1; + dinfo->open = 0; + + init_waitqueue_head(&dinfo->vsync.wait); + spin_lock_init(&dinfo->int_lock); + dinfo->irq_flags = 0; + dinfo->vsync.pan_display = 0; + dinfo->vsync.pan_offset = 0; return 0; @@ -1027,17 +1054,43 @@ intelfb_init_var(struct intelfb_info *dinfo) sizeof(struct fb_var_screeninfo)); msrc = 5; } else { + const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev); + u8 *edid_d = NULL; + + if (edid_s) { + edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL); + + if (edid_d) { + fb_edid_to_monspecs(edid_d, + &dinfo->info->monspecs); + kfree(edid_d); + } + } + if (mode) { + printk("intelfb: Looking for mode in private " + "database\n"); msrc = fb_find_mode(var, dinfo->info, mode, - vesa_modes, VESA_MODEDB_SIZE, + dinfo->info->monspecs.modedb, + dinfo->info->monspecs.modedb_len, NULL, 0); - if (msrc) - msrc |= 8; + + if (msrc && msrc > 1) { + printk("intelfb: No mode in private database, " + "intelfb: looking for mode in global " + "database "); + msrc = fb_find_mode(var, dinfo->info, mode, + NULL, 0, NULL, 0); + + if (msrc) + msrc |= 8; + } + } + if (!msrc) { msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE, - vesa_modes, VESA_MODEDB_SIZE, - NULL, 0); + NULL, 0, NULL, 0); } } @@ -1083,13 +1136,24 @@ 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)) 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; @@ -1107,7 +1171,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: @@ -1125,7 +1190,10 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var) } /* Make sure the line length is a aligned correctly. */ - dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT); + if (IS_I9XX(dinfo)) + dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX); + else + dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT); if (FIXED_MODE(dinfo)) dinfo->pitch = dinfo->initial_pitch; @@ -1137,33 +1205,37 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var) /* fbops functions */ +/*************************************************************** + * fbdev interface * + ***************************************************************/ + static int -intelfb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) +intelfb_open(struct fb_info *info, int user) { 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; + if (user) { + dinfo->open++; + } + return 0; } -/*************************************************************** - * fbdev interface * - ***************************************************************/ +static int +intelfb_release(struct fb_info *info, int user) +{ + struct intelfb_info *dinfo = GET_DINFO(info); + + if (user) { + dinfo->open--; + msleep(1); + if (!dinfo->open) { + intelfbhw_disable_irq(dinfo); + } + } + + return 0; +} static int intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) @@ -1172,16 +1244,33 @@ intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) struct fb_var_screeninfo v; struct intelfb_info *dinfo; static int first = 1; + int i; + /* Good pitches to allow tiling. Don't care about pitches < 1024. */ + static const int pitches[] = { + 128 * 8, + 128 * 16, + 128 * 32, + 128 * 64, + 0 + }; DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags); dinfo = GET_DINFO(info); + /* update the pitch */ if (intelfbhw_validate_mode(dinfo, var) != 0) return -EINVAL; v = *var; + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= v.xres_virtual) { + v.xres_virtual = pitches[i]; + break; + } + } + /* Check for a supported bpp. */ if (v.bits_per_pixel <= 8) { v.bits_per_pixel = 8; @@ -1293,7 +1382,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)); @@ -1309,7 +1398,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); @@ -1343,37 +1432,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; - dinfo->palette[regno].red = red; - dinfo->palette[regno].green = green; - dinfo->palette[regno].blue = blue; + 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; } @@ -1393,10 +1480,22 @@ 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; + struct intelfb_info *dinfo = GET_DINFO(info); + u32 pipe = 0; + + switch (cmd) { + case FBIO_WAITFORVSYNC: + if (get_user(pipe, (__u32 __user *)arg)) + return -EFAULT; + + retval = intelfbhw_wait_for_vsync(dinfo, pipe); + break; + default: + break; + } return retval; } @@ -1480,18 +1579,21 @@ 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 if (!dinfo->hwcursor) - return soft_cursor(info, cursor); + return -ENODEV; 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");