aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/intelfb/intelfbdrv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/intelfb/intelfbdrv.c')
-rw-r--r--drivers/video/intelfb/intelfbdrv.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 995b47c165a7..076fa56be192 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1,11 +1,12 @@
1/* 1/*
2 * intelfb 2 * intelfb
3 * 3 *
4 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM 4 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
5 * integrated graphics chips. 5 * 945G/945GM integrated graphics chips.
6 * 6 *
7 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> 7 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
8 * 2004 Sylvain Meyer 8 * 2004 Sylvain Meyer
9 * 2006 David Airlie
9 * 10 *
10 * This driver consists of two parts. The first part (intelfbdrv.c) provides 11 * This driver consists of two parts. The first part (intelfbdrv.c) provides
11 * the basic fbdev interfaces, is derived in part from the radeonfb and 12 * the basic fbdev interfaces, is derived in part from the radeonfb and
@@ -131,6 +132,7 @@
131 132
132#include "intelfb.h" 133#include "intelfb.h"
133#include "intelfbhw.h" 134#include "intelfbhw.h"
135#include "../edid.h"
134 136
135static void __devinit get_initial_mode(struct intelfb_info *dinfo); 137static void __devinit get_initial_mode(struct intelfb_info *dinfo);
136static void update_dinfo(struct intelfb_info *dinfo, 138static void update_dinfo(struct intelfb_info *dinfo,
@@ -182,6 +184,8 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
182 { 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 }, 184 { 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 },
183 { 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 }, 185 { 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 },
184 { 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 }, 186 { 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 },
187 { 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 },
188 { 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 },
185 { 0, } 189 { 0, }
186}; 190};
187 191
@@ -261,7 +265,7 @@ MODULE_PARM_DESC(mode,
261 265
262#ifndef MODULE 266#ifndef MODULE
263#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name))) 267#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
264#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0) 268#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
265#define OPT_STRVAL(opt, name) (opt + strlen(name)) 269#define OPT_STRVAL(opt, name) (opt + strlen(name))
266 270
267static __inline__ char * 271static __inline__ char *
@@ -546,11 +550,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
546 550
547 /* Set base addresses. */ 551 /* Set base addresses. */
548 if ((ent->device == PCI_DEVICE_ID_INTEL_915G) || 552 if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
549 (ent->device == PCI_DEVICE_ID_INTEL_915GM)) { 553 (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
554 (ent->device == PCI_DEVICE_ID_INTEL_945G) ||
555 (ent->device == PCI_DEVICE_ID_INTEL_945GM)) {
550 aperture_bar = 2; 556 aperture_bar = 2;
551 mmio_bar = 0; 557 mmio_bar = 0;
552 /* Disable HW cursor on 915G/M (not implemented yet) */
553 hwcursor = 0;
554 } 558 }
555 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar); 559 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
556 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar); 560 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar);
@@ -584,8 +588,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
584 /* Get the chipset info. */ 588 /* Get the chipset info. */
585 dinfo->pci_chipset = pdev->device; 589 dinfo->pci_chipset = pdev->device;
586 590
587 if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset, 591 if (intelfbhw_get_chipset(pdev, dinfo)) {
588 &dinfo->mobile)) {
589 cleanup(dinfo); 592 cleanup(dinfo);
590 return -ENODEV; 593 return -ENODEV;
591 } 594 }
@@ -1029,17 +1032,44 @@ intelfb_init_var(struct intelfb_info *dinfo)
1029 sizeof(struct fb_var_screeninfo)); 1032 sizeof(struct fb_var_screeninfo));
1030 msrc = 5; 1033 msrc = 5;
1031 } else { 1034 } else {
1035 const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
1036 u8 *edid_d = NULL;
1037
1038 if (edid_s) {
1039 edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL);
1040
1041 if (edid_d) {
1042 memcpy(edid_d, edid_s, EDID_LENGTH);
1043 fb_edid_to_monspecs(edid_d,
1044 &dinfo->info->monspecs);
1045 kfree(edid_d);
1046 }
1047 }
1048
1032 if (mode) { 1049 if (mode) {
1050 printk("intelfb: Looking for mode in private "
1051 "database\n");
1033 msrc = fb_find_mode(var, dinfo->info, mode, 1052 msrc = fb_find_mode(var, dinfo->info, mode,
1034 vesa_modes, VESA_MODEDB_SIZE, 1053 dinfo->info->monspecs.modedb,
1054 dinfo->info->monspecs.modedb_len,
1035 NULL, 0); 1055 NULL, 0);
1036 if (msrc) 1056
1037 msrc |= 8; 1057 if (msrc && msrc > 1) {
1058 printk("intelfb: No mode in private database, "
1059 "intelfb: looking for mode in global "
1060 "database ");
1061 msrc = fb_find_mode(var, dinfo->info, mode,
1062 NULL, 0, NULL, 0);
1063
1064 if (msrc)
1065 msrc |= 8;
1066 }
1067
1038 } 1068 }
1069
1039 if (!msrc) { 1070 if (!msrc) {
1040 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE, 1071 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
1041 vesa_modes, VESA_MODEDB_SIZE, 1072 NULL, 0, NULL, 0);
1042 NULL, 0);
1043 } 1073 }
1044 } 1074 }
1045 1075
@@ -1139,7 +1169,10 @@ update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
1139 } 1169 }
1140 1170
1141 /* Make sure the line length is a aligned correctly. */ 1171 /* Make sure the line length is a aligned correctly. */
1142 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT); 1172 if (IS_I9XX(dinfo))
1173 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
1174 else
1175 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
1143 1176
1144 if (FIXED_MODE(dinfo)) 1177 if (FIXED_MODE(dinfo))
1145 dinfo->pitch = dinfo->initial_pitch; 1178 dinfo->pitch = dinfo->initial_pitch;
@@ -1162,16 +1195,33 @@ intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1162 struct fb_var_screeninfo v; 1195 struct fb_var_screeninfo v;
1163 struct intelfb_info *dinfo; 1196 struct intelfb_info *dinfo;
1164 static int first = 1; 1197 static int first = 1;
1198 int i;
1199 /* Good pitches to allow tiling. Don't care about pitches < 1024. */
1200 static const int pitches[] = {
1201 128 * 8,
1202 128 * 16,
1203 128 * 32,
1204 128 * 64,
1205 0
1206 };
1165 1207
1166 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags); 1208 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
1167 1209
1168 dinfo = GET_DINFO(info); 1210 dinfo = GET_DINFO(info);
1169 1211
1212 /* update the pitch */
1170 if (intelfbhw_validate_mode(dinfo, var) != 0) 1213 if (intelfbhw_validate_mode(dinfo, var) != 0)
1171 return -EINVAL; 1214 return -EINVAL;
1172 1215
1173 v = *var; 1216 v = *var;
1174 1217
1218 for (i = 0; pitches[i] != 0; i++) {
1219 if (pitches[i] >= v.xres_virtual) {
1220 v.xres_virtual = pitches[i];
1221 break;
1222 }
1223 }
1224
1175 /* Check for a supported bpp. */ 1225 /* Check for a supported bpp. */
1176 if (v.bits_per_pixel <= 8) { 1226 if (v.bits_per_pixel <= 8) {
1177 v.bits_per_pixel = 8; 1227 v.bits_per_pixel = 8;
@@ -1467,7 +1517,7 @@ static int
1467intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) 1517intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1468{ 1518{
1469 struct intelfb_info *dinfo = GET_DINFO(info); 1519 struct intelfb_info *dinfo = GET_DINFO(info);
1470 1520 u32 physical;
1471#if VERBOSE > 0 1521#if VERBOSE > 0
1472 DBG_MSG("intelfb_cursor\n"); 1522 DBG_MSG("intelfb_cursor\n");
1473#endif 1523#endif
@@ -1478,7 +1528,10 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1478 intelfbhw_cursor_hide(dinfo); 1528 intelfbhw_cursor_hide(dinfo);
1479 1529
1480 /* If XFree killed the cursor - restore it */ 1530 /* If XFree killed the cursor - restore it */
1481 if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) { 1531 physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
1532 (dinfo->cursor.offset << 12);
1533
1534 if (INREG(CURSOR_A_BASEADDR) != physical) {
1482 u32 fg, bg; 1535 u32 fg, bg;
1483 1536
1484 DBG_MSG("the cursor was killed - restore it !!\n"); 1537 DBG_MSG("the cursor was killed - restore it !!\n");