/*
* 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
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);
{ 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, }
};
/* 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);
/* 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;
}
}
/* 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;
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;
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;
}
/* 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;
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
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");