diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:53:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:53:20 -0400 |
| commit | d90125bfe958ed0451c6b98f831c86aba08b43d5 (patch) | |
| tree | 3a9ea24091f958a92e1d0d12f5135e50adf71b31 | |
| parent | bfd189a8e944dd0b8135dea2c23ac399bbe34535 (diff) | |
| parent | 2abac1db3522d9f56c695d1b42e77f3e52d4c51a (diff) | |
Merge branch 'i915fb' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/intelfb-2.6
* 'i915fb' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/intelfb-2.6: (25 commits)
intelfb: fixup clock calculation debugging.
Removed hard coded EDID buffer size.
intelfb: use regular modedb table instead of VESA
intelfb: use firmware EDID for mode database
Revert "intelfb driver -- use the regular modedb table instead of the VESA"
intelfb: int option fix
sync modesetting code with X.org
intelfb: align with changes from my X driver.
intelfb driver -- use the regular modedb table instead of the VESA
Adds support for 256MB aperture on 945 chipsets to the intelfb driver
intelfb -- uses stride alignment of 64 on the 9xx chipsets.
intelfb: some cleanups for intelfbhw
intelfb: fixup pitch calculation like X does
intelfb: fixup p calculation
This patch makes a needlessly global struct static.
intelfb: add i945GM support
intelfb: fixup whitespace..
intelfb: add hw cursor support for i9xx
intelfb: make i915 modeset
intelfb: add support for i945G
...
| -rw-r--r-- | drivers/video/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/video/intelfb/intelfb.h | 16 | ||||
| -rw-r--r-- | drivers/video/intelfb/intelfbdrv.c | 85 | ||||
| -rw-r--r-- | drivers/video/intelfb/intelfbhw.c | 494 | ||||
| -rw-r--r-- | drivers/video/intelfb/intelfbhw.h | 25 |
5 files changed, 412 insertions, 210 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4587087d777a..5641498725d0 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -743,7 +743,7 @@ config FB_I810_I2C | |||
| 743 | 743 | ||
| 744 | config FB_INTEL | 744 | config FB_INTEL |
| 745 | tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" | 745 | tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)" |
| 746 | depends on FB && EXPERIMENTAL && PCI && X86_32 | 746 | depends on FB && EXPERIMENTAL && PCI && X86 |
| 747 | select AGP | 747 | select AGP |
| 748 | select AGP_INTEL | 748 | select AGP_INTEL |
| 749 | select FB_MODE_HELPERS | 749 | select FB_MODE_HELPERS |
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index da29d007f215..469b06c29180 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h | |||
| @@ -8,9 +8,9 @@ | |||
| 8 | 8 | ||
| 9 | 9 | ||
| 10 | /*** Version/name ***/ | 10 | /*** Version/name ***/ |
| 11 | #define INTELFB_VERSION "0.9.2" | 11 | #define INTELFB_VERSION "0.9.4" |
| 12 | #define INTELFB_MODULE_NAME "intelfb" | 12 | #define INTELFB_MODULE_NAME "intelfb" |
| 13 | #define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM" | 13 | #define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | /*** Debug/feature defines ***/ | 16 | /*** Debug/feature defines ***/ |
| @@ -52,11 +52,14 @@ | |||
| 52 | #define PCI_DEVICE_ID_INTEL_865G 0x2572 | 52 | #define PCI_DEVICE_ID_INTEL_865G 0x2572 |
| 53 | #define PCI_DEVICE_ID_INTEL_915G 0x2582 | 53 | #define PCI_DEVICE_ID_INTEL_915G 0x2582 |
| 54 | #define PCI_DEVICE_ID_INTEL_915GM 0x2592 | 54 | #define PCI_DEVICE_ID_INTEL_915GM 0x2592 |
| 55 | #define PCI_DEVICE_ID_INTEL_945G 0x2772 | ||
| 56 | #define PCI_DEVICE_ID_INTEL_945GM 0x27A2 | ||
| 55 | 57 | ||
| 56 | /* Size of MMIO region */ | 58 | /* Size of MMIO region */ |
| 57 | #define INTEL_REG_SIZE 0x80000 | 59 | #define INTEL_REG_SIZE 0x80000 |
| 58 | 60 | ||
| 59 | #define STRIDE_ALIGNMENT 16 | 61 | #define STRIDE_ALIGNMENT 16 |
| 62 | #define STRIDE_ALIGNMENT_I9XX 64 | ||
| 60 | 63 | ||
| 61 | #define PALETTE_8_ENTRIES 256 | 64 | #define PALETTE_8_ENTRIES 256 |
| 62 | 65 | ||
| @@ -125,7 +128,9 @@ enum intel_chips { | |||
| 125 | INTEL_855GME, | 128 | INTEL_855GME, |
| 126 | INTEL_865G, | 129 | INTEL_865G, |
| 127 | INTEL_915G, | 130 | INTEL_915G, |
| 128 | INTEL_915GM | 131 | INTEL_915GM, |
| 132 | INTEL_945G, | ||
| 133 | INTEL_945GM, | ||
| 129 | }; | 134 | }; |
| 130 | 135 | ||
| 131 | struct intelfb_hwstate { | 136 | struct intelfb_hwstate { |
| @@ -277,8 +282,13 @@ struct intelfb_info { | |||
| 277 | 282 | ||
| 278 | /* driver registered */ | 283 | /* driver registered */ |
| 279 | int registered; | 284 | int registered; |
| 285 | |||
| 286 | /* index into plls */ | ||
| 287 | int pll_index; | ||
| 280 | }; | 288 | }; |
| 281 | 289 | ||
| 290 | #define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM)) | ||
| 291 | |||
| 282 | /*** function prototypes ***/ | 292 | /*** function prototypes ***/ |
| 283 | 293 | ||
| 284 | extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); | 294 | extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var); |
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 | ||
| 135 | static void __devinit get_initial_mode(struct intelfb_info *dinfo); | 137 | static void __devinit get_initial_mode(struct intelfb_info *dinfo); |
| 136 | static void update_dinfo(struct intelfb_info *dinfo, | 138 | static 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 | ||
| 267 | static __inline__ char * | 271 | static __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 | |||
| 1467 | intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 1517 | intelfb_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"); |
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 624c4bc96f0d..426b7430b125 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
| @@ -40,68 +40,110 @@ | |||
| 40 | #include "intelfb.h" | 40 | #include "intelfb.h" |
| 41 | #include "intelfbhw.h" | 41 | #include "intelfbhw.h" |
| 42 | 42 | ||
| 43 | struct pll_min_max { | ||
| 44 | int min_m, max_m, min_m1, max_m1; | ||
| 45 | int min_m2, max_m2, min_n, max_n; | ||
| 46 | int min_p, max_p, min_p1, max_p1; | ||
| 47 | int min_vco, max_vco, p_transition_clk, ref_clk; | ||
| 48 | int p_inc_lo, p_inc_hi; | ||
| 49 | }; | ||
| 50 | |||
| 51 | #define PLLS_I8xx 0 | ||
| 52 | #define PLLS_I9xx 1 | ||
| 53 | #define PLLS_MAX 2 | ||
| 54 | |||
| 55 | static struct pll_min_max plls[PLLS_MAX] = { | ||
| 56 | { 108, 140, 18, 26, | ||
| 57 | 6, 16, 3, 16, | ||
| 58 | 4, 128, 0, 31, | ||
| 59 | 930000, 1400000, 165000, 48000, | ||
| 60 | 4, 2 }, //I8xx | ||
| 61 | |||
| 62 | { 75, 120, 10, 20, | ||
| 63 | 5, 9, 4, 7, | ||
| 64 | 5, 80, 1, 8, | ||
| 65 | 1400000, 2800000, 200000, 96000, | ||
| 66 | 10, 5 } //I9xx | ||
| 67 | }; | ||
| 68 | |||
| 43 | int | 69 | int |
| 44 | intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset, | 70 | intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo) |
| 45 | int *mobile) | ||
| 46 | { | 71 | { |
| 47 | u32 tmp; | 72 | u32 tmp; |
| 48 | 73 | if (!pdev || !dinfo) | |
| 49 | if (!pdev || !name || !chipset || !mobile) | ||
| 50 | return 1; | 74 | return 1; |
| 51 | 75 | ||
| 52 | switch (pdev->device) { | 76 | switch (pdev->device) { |
| 53 | case PCI_DEVICE_ID_INTEL_830M: | 77 | case PCI_DEVICE_ID_INTEL_830M: |
| 54 | *name = "Intel(R) 830M"; | 78 | dinfo->name = "Intel(R) 830M"; |
| 55 | *chipset = INTEL_830M; | 79 | dinfo->chipset = INTEL_830M; |
| 56 | *mobile = 1; | 80 | dinfo->mobile = 1; |
| 81 | dinfo->pll_index = PLLS_I8xx; | ||
| 57 | return 0; | 82 | return 0; |
| 58 | case PCI_DEVICE_ID_INTEL_845G: | 83 | case PCI_DEVICE_ID_INTEL_845G: |
| 59 | *name = "Intel(R) 845G"; | 84 | dinfo->name = "Intel(R) 845G"; |
| 60 | *chipset = INTEL_845G; | 85 | dinfo->chipset = INTEL_845G; |
| 61 | *mobile = 0; | 86 | dinfo->mobile = 0; |
| 87 | dinfo->pll_index = PLLS_I8xx; | ||
| 62 | return 0; | 88 | return 0; |
| 63 | case PCI_DEVICE_ID_INTEL_85XGM: | 89 | case PCI_DEVICE_ID_INTEL_85XGM: |
| 64 | tmp = 0; | 90 | tmp = 0; |
| 65 | *mobile = 1; | 91 | dinfo->mobile = 1; |
| 92 | dinfo->pll_index = PLLS_I8xx; | ||
| 66 | pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp); | 93 | pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp); |
| 67 | switch ((tmp >> INTEL_85X_VARIANT_SHIFT) & | 94 | switch ((tmp >> INTEL_85X_VARIANT_SHIFT) & |
| 68 | INTEL_85X_VARIANT_MASK) { | 95 | INTEL_85X_VARIANT_MASK) { |
| 69 | case INTEL_VAR_855GME: | 96 | case INTEL_VAR_855GME: |
| 70 | *name = "Intel(R) 855GME"; | 97 | dinfo->name = "Intel(R) 855GME"; |
| 71 | *chipset = INTEL_855GME; | 98 | dinfo->chipset = INTEL_855GME; |
| 72 | return 0; | 99 | return 0; |
| 73 | case INTEL_VAR_855GM: | 100 | case INTEL_VAR_855GM: |
| 74 | *name = "Intel(R) 855GM"; | 101 | dinfo->name = "Intel(R) 855GM"; |
| 75 | *chipset = INTEL_855GM; | 102 | dinfo->chipset = INTEL_855GM; |
| 76 | return 0; | 103 | return 0; |
| 77 | case INTEL_VAR_852GME: | 104 | case INTEL_VAR_852GME: |
| 78 | *name = "Intel(R) 852GME"; | 105 | dinfo->name = "Intel(R) 852GME"; |
| 79 | *chipset = INTEL_852GME; | 106 | dinfo->chipset = INTEL_852GME; |
| 80 | return 0; | 107 | return 0; |
| 81 | case INTEL_VAR_852GM: | 108 | case INTEL_VAR_852GM: |
| 82 | *name = "Intel(R) 852GM"; | 109 | dinfo->name = "Intel(R) 852GM"; |
| 83 | *chipset = INTEL_852GM; | 110 | dinfo->chipset = INTEL_852GM; |
| 84 | return 0; | 111 | return 0; |
| 85 | default: | 112 | default: |
| 86 | *name = "Intel(R) 852GM/855GM"; | 113 | dinfo->name = "Intel(R) 852GM/855GM"; |
| 87 | *chipset = INTEL_85XGM; | 114 | dinfo->chipset = INTEL_85XGM; |
| 88 | return 0; | 115 | return 0; |
| 89 | } | 116 | } |
| 90 | break; | 117 | break; |
| 91 | case PCI_DEVICE_ID_INTEL_865G: | 118 | case PCI_DEVICE_ID_INTEL_865G: |
| 92 | *name = "Intel(R) 865G"; | 119 | dinfo->name = "Intel(R) 865G"; |
| 93 | *chipset = INTEL_865G; | 120 | dinfo->chipset = INTEL_865G; |
| 94 | *mobile = 0; | 121 | dinfo->mobile = 0; |
| 122 | dinfo->pll_index = PLLS_I8xx; | ||
| 95 | return 0; | 123 | return 0; |
| 96 | case PCI_DEVICE_ID_INTEL_915G: | 124 | case PCI_DEVICE_ID_INTEL_915G: |
| 97 | *name = "Intel(R) 915G"; | 125 | dinfo->name = "Intel(R) 915G"; |
| 98 | *chipset = INTEL_915G; | 126 | dinfo->chipset = INTEL_915G; |
| 99 | *mobile = 0; | 127 | dinfo->mobile = 0; |
| 128 | dinfo->pll_index = PLLS_I9xx; | ||
| 100 | return 0; | 129 | return 0; |
| 101 | case PCI_DEVICE_ID_INTEL_915GM: | 130 | case PCI_DEVICE_ID_INTEL_915GM: |
| 102 | *name = "Intel(R) 915GM"; | 131 | dinfo->name = "Intel(R) 915GM"; |
| 103 | *chipset = INTEL_915GM; | 132 | dinfo->chipset = INTEL_915GM; |
| 104 | *mobile = 1; | 133 | dinfo->mobile = 1; |
| 134 | dinfo->pll_index = PLLS_I9xx; | ||
| 135 | return 0; | ||
| 136 | case PCI_DEVICE_ID_INTEL_945G: | ||
| 137 | dinfo->name = "Intel(R) 945G"; | ||
| 138 | dinfo->chipset = INTEL_945G; | ||
| 139 | dinfo->mobile = 0; | ||
| 140 | dinfo->pll_index = PLLS_I9xx; | ||
| 141 | return 0; | ||
| 142 | case PCI_DEVICE_ID_INTEL_945GM: | ||
| 143 | dinfo->name = "Intel(R) 945GM"; | ||
| 144 | dinfo->chipset = INTEL_945GM; | ||
| 145 | dinfo->mobile = 1; | ||
| 146 | dinfo->pll_index = PLLS_I9xx; | ||
| 105 | return 0; | 147 | return 0; |
| 106 | default: | 148 | default: |
| 107 | return 1; | 149 | return 1; |
| @@ -114,6 +156,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
| 114 | { | 156 | { |
| 115 | struct pci_dev *bridge_dev; | 157 | struct pci_dev *bridge_dev; |
| 116 | u16 tmp; | 158 | u16 tmp; |
| 159 | int stolen_overhead; | ||
| 117 | 160 | ||
| 118 | if (!pdev || !aperture_size || !stolen_size) | 161 | if (!pdev || !aperture_size || !stolen_size) |
| 119 | return 1; | 162 | return 1; |
| @@ -128,21 +171,41 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
| 128 | tmp = 0; | 171 | tmp = 0; |
| 129 | pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); | 172 | pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); |
| 130 | switch (pdev->device) { | 173 | switch (pdev->device) { |
| 131 | case PCI_DEVICE_ID_INTEL_830M: | 174 | case PCI_DEVICE_ID_INTEL_915G: |
| 132 | case PCI_DEVICE_ID_INTEL_845G: | 175 | case PCI_DEVICE_ID_INTEL_915GM: |
| 176 | case PCI_DEVICE_ID_INTEL_945G: | ||
| 177 | case PCI_DEVICE_ID_INTEL_945GM: | ||
| 178 | /* 915 and 945 chipsets support a 256MB aperture. | ||
| 179 | Aperture size is determined by inspected the | ||
| 180 | base address of the aperture. */ | ||
| 181 | if (pci_resource_start(pdev, 2) & 0x08000000) | ||
| 182 | *aperture_size = MB(128); | ||
| 183 | else | ||
| 184 | *aperture_size = MB(256); | ||
| 185 | break; | ||
| 186 | default: | ||
| 133 | if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) | 187 | if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) |
| 134 | *aperture_size = MB(64); | 188 | *aperture_size = MB(64); |
| 135 | else | 189 | else |
| 136 | *aperture_size = MB(128); | 190 | *aperture_size = MB(128); |
| 191 | break; | ||
| 192 | } | ||
| 193 | |||
| 194 | /* Stolen memory size is reduced by the GTT and the popup. | ||
| 195 | GTT is 1K per MB of aperture size, and popup is 4K. */ | ||
| 196 | stolen_overhead = (*aperture_size / MB(1)) + 4; | ||
| 197 | switch(pdev->device) { | ||
| 198 | case PCI_DEVICE_ID_INTEL_830M: | ||
| 199 | case PCI_DEVICE_ID_INTEL_845G: | ||
| 137 | switch (tmp & INTEL_830_GMCH_GMS_MASK) { | 200 | switch (tmp & INTEL_830_GMCH_GMS_MASK) { |
| 138 | case INTEL_830_GMCH_GMS_STOLEN_512: | 201 | case INTEL_830_GMCH_GMS_STOLEN_512: |
| 139 | *stolen_size = KB(512) - KB(132); | 202 | *stolen_size = KB(512) - KB(stolen_overhead); |
| 140 | return 0; | 203 | return 0; |
| 141 | case INTEL_830_GMCH_GMS_STOLEN_1024: | 204 | case INTEL_830_GMCH_GMS_STOLEN_1024: |
| 142 | *stolen_size = MB(1) - KB(132); | 205 | *stolen_size = MB(1) - KB(stolen_overhead); |
| 143 | return 0; | 206 | return 0; |
| 144 | case INTEL_830_GMCH_GMS_STOLEN_8192: | 207 | case INTEL_830_GMCH_GMS_STOLEN_8192: |
| 145 | *stolen_size = MB(8) - KB(132); | 208 | *stolen_size = MB(8) - KB(stolen_overhead); |
| 146 | return 0; | 209 | return 0; |
| 147 | case INTEL_830_GMCH_GMS_LOCAL: | 210 | case INTEL_830_GMCH_GMS_LOCAL: |
| 148 | ERR_MSG("only local memory found\n"); | 211 | ERR_MSG("only local memory found\n"); |
| @@ -157,28 +220,27 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | |||
| 157 | } | 220 | } |
| 158 | break; | 221 | break; |
| 159 | default: | 222 | default: |
| 160 | *aperture_size = MB(128); | ||
| 161 | switch (tmp & INTEL_855_GMCH_GMS_MASK) { | 223 | switch (tmp & INTEL_855_GMCH_GMS_MASK) { |
| 162 | case INTEL_855_GMCH_GMS_STOLEN_1M: | 224 | case INTEL_855_GMCH_GMS_STOLEN_1M: |
| 163 | *stolen_size = MB(1) - KB(132); | 225 | *stolen_size = MB(1) - KB(stolen_overhead); |
| 164 | return 0; | 226 | return 0; |
| 165 | case INTEL_855_GMCH_GMS_STOLEN_4M: | 227 | case INTEL_855_GMCH_GMS_STOLEN_4M: |
| 166 | *stolen_size = MB(4) - KB(132); | 228 | *stolen_size = MB(4) - KB(stolen_overhead); |
| 167 | return 0; | 229 | return 0; |
| 168 | case INTEL_855_GMCH_GMS_STOLEN_8M: | 230 | case INTEL_855_GMCH_GMS_STOLEN_8M: |
| 169 | *stolen_size = MB(8) - KB(132); | 231 | *stolen_size = MB(8) - KB(stolen_overhead); |
| 170 | return 0; | 232 | return 0; |
| 171 | case INTEL_855_GMCH_GMS_STOLEN_16M: | 233 | case INTEL_855_GMCH_GMS_STOLEN_16M: |
| 172 | *stolen_size = MB(16) - KB(132); | 234 | *stolen_size = MB(16) - KB(stolen_overhead); |
| 173 | return 0; | 235 | return 0; |
| 174 | case INTEL_855_GMCH_GMS_STOLEN_32M: | 236 | case INTEL_855_GMCH_GMS_STOLEN_32M: |
| 175 | *stolen_size = MB(32) - KB(132); | 237 | *stolen_size = MB(32) - KB(stolen_overhead); |
| 176 | return 0; | 238 | return 0; |
| 177 | case INTEL_915G_GMCH_GMS_STOLEN_48M: | 239 | case INTEL_915G_GMCH_GMS_STOLEN_48M: |
| 178 | *stolen_size = MB(48) - KB(132); | 240 | *stolen_size = MB(48) - KB(stolen_overhead); |
| 179 | return 0; | 241 | return 0; |
| 180 | case INTEL_915G_GMCH_GMS_STOLEN_64M: | 242 | case INTEL_915G_GMCH_GMS_STOLEN_64M: |
| 181 | *stolen_size = MB(64) - KB(132); | 243 | *stolen_size = MB(64) - KB(stolen_overhead); |
| 182 | return 0; | 244 | return 0; |
| 183 | case INTEL_855_GMCH_GMS_DISABLED: | 245 | case INTEL_855_GMCH_GMS_DISABLED: |
| 184 | ERR_MSG("video memory is disabled\n"); | 246 | ERR_MSG("video memory is disabled\n"); |
| @@ -529,12 +591,63 @@ intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
| 529 | } | 591 | } |
| 530 | 592 | ||
| 531 | 593 | ||
| 594 | static int calc_vclock3(int index, int m, int n, int p) | ||
| 595 | { | ||
| 596 | if (p == 0 || n == 0) | ||
| 597 | return 0; | ||
| 598 | return plls[index].ref_clk * m / n / p; | ||
| 599 | } | ||
| 600 | |||
| 601 | static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds) | ||
| 602 | { | ||
| 603 | struct pll_min_max *pll = &plls[index]; | ||
| 604 | u32 m, vco, p; | ||
| 605 | |||
| 606 | m = (5 * (m1 + 2)) + (m2 + 2); | ||
| 607 | n += 2; | ||
| 608 | vco = pll->ref_clk * m / n; | ||
| 609 | |||
| 610 | if (index == PLLS_I8xx) { | ||
| 611 | p = ((p1 + 2) * (1 << (p2 + 1))); | ||
| 612 | } else { | ||
| 613 | p = ((p1) * (p2 ? 5 : 10)); | ||
| 614 | } | ||
| 615 | return vco / p; | ||
| 616 | } | ||
| 617 | |||
| 618 | static void | ||
| 619 | intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2) | ||
| 620 | { | ||
| 621 | int p1, p2; | ||
| 622 | |||
| 623 | if (IS_I9XX(dinfo)) { | ||
| 624 | if (dpll & DPLL_P1_FORCE_DIV2) | ||
| 625 | p1 = 1; | ||
| 626 | else | ||
| 627 | p1 = (dpll >> DPLL_P1_SHIFT) & 0xff; | ||
| 628 | |||
| 629 | p1 = ffs(p1); | ||
| 630 | |||
| 631 | p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK; | ||
| 632 | } else { | ||
| 633 | if (dpll & DPLL_P1_FORCE_DIV2) | ||
| 634 | p1 = 0; | ||
| 635 | else | ||
| 636 | p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
| 637 | p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
| 638 | } | ||
| 639 | |||
| 640 | *o_p1 = p1; | ||
| 641 | *o_p2 = p2; | ||
| 642 | } | ||
| 643 | |||
| 644 | |||
| 532 | void | 645 | void |
| 533 | intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | 646 | intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) |
| 534 | { | 647 | { |
| 535 | #if REGDUMP | 648 | #if REGDUMP |
| 536 | int i, m1, m2, n, p1, p2; | 649 | int i, m1, m2, n, p1, p2; |
| 537 | 650 | int index = dinfo->pll_index; | |
| 538 | DBG_MSG("intelfbhw_print_hw_state\n"); | 651 | DBG_MSG("intelfbhw_print_hw_state\n"); |
| 539 | 652 | ||
| 540 | if (!hw || !dinfo) | 653 | if (!hw || !dinfo) |
| @@ -547,26 +660,22 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
| 547 | n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 660 | n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 548 | m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 661 | m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 549 | m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 662 | m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 550 | if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2) | 663 | |
| 551 | p1 = 0; | 664 | intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2); |
| 552 | else | 665 | |
| 553 | p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK; | ||
| 554 | p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK; | ||
| 555 | printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 666 | printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
| 556 | m1, m2, n, p1, p2); | 667 | m1, m2, n, p1, p2); |
| 557 | printk(" VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 668 | printk(" VGA0: clock is %d\n", |
| 669 | calc_vclock(index, m1, m2, n, p1, p2, 0)); | ||
| 558 | 670 | ||
| 559 | n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 671 | n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 560 | m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 672 | m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 561 | m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 673 | m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 562 | if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2) | 674 | |
| 563 | p1 = 0; | 675 | intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2); |
| 564 | else | ||
| 565 | p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK; | ||
| 566 | p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK; | ||
| 567 | printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 676 | printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
| 568 | m1, m2, n, p1, p2); | 677 | m1, m2, n, p1, p2); |
| 569 | printk(" VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 678 | printk(" VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
| 570 | 679 | ||
| 571 | printk(" DPLL_A: 0x%08x\n", hw->dpll_a); | 680 | printk(" DPLL_A: 0x%08x\n", hw->dpll_a); |
| 572 | printk(" DPLL_B: 0x%08x\n", hw->dpll_b); | 681 | printk(" DPLL_B: 0x%08x\n", hw->dpll_b); |
| @@ -578,34 +687,30 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
| 578 | n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 687 | n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 579 | m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 688 | m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 580 | m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 689 | m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 581 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | 690 | |
| 582 | p1 = 0; | 691 | intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2); |
| 583 | else | 692 | |
| 584 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
| 585 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
| 586 | printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 693 | printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
| 587 | m1, m2, n, p1, p2); | 694 | m1, m2, n, p1, p2); |
| 588 | printk(" PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 695 | printk(" PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
| 589 | 696 | ||
| 590 | n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 697 | n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 591 | m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 698 | m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 592 | m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; | 699 | m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK; |
| 593 | if (hw->dpll_a & DPLL_P1_FORCE_DIV2) | 700 | |
| 594 | p1 = 0; | 701 | intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2); |
| 595 | else | 702 | |
| 596 | p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK; | ||
| 597 | p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK; | ||
| 598 | printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", | 703 | printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n", |
| 599 | m1, m2, n, p1, p2); | 704 | m1, m2, n, p1, p2); |
| 600 | printk(" PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2)); | 705 | printk(" PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0)); |
| 601 | 706 | ||
| 602 | #if 0 | 707 | #if 0 |
| 603 | printk(" PALETTE_A:\n"); | 708 | printk(" PALETTE_A:\n"); |
| 604 | for (i = 0; i < PALETTE_8_ENTRIES) | 709 | for (i = 0; i < PALETTE_8_ENTRIES) |
| 605 | printk(" %3d: 0x%08x\n", i, hw->palette_a[i]; | 710 | printk(" %3d: 0x%08x\n", i, hw->palette_a[i]); |
| 606 | printk(" PALETTE_B:\n"); | 711 | printk(" PALETTE_B:\n"); |
| 607 | for (i = 0; i < PALETTE_8_ENTRIES) | 712 | for (i = 0; i < PALETTE_8_ENTRIES) |
| 608 | printk(" %3d: 0x%08x\n", i, hw->palette_b[i]; | 713 | printk(" %3d: 0x%08x\n", i, hw->palette_b[i]); |
| 609 | #endif | 714 | #endif |
| 610 | 715 | ||
| 611 | printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a); | 716 | printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a); |
| @@ -680,11 +785,11 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
| 680 | } | 785 | } |
| 681 | for (i = 0; i < 3; i++) { | 786 | for (i = 0; i < 3; i++) { |
| 682 | printk(" SWF3%d 0x%08x\n", i, | 787 | printk(" SWF3%d 0x%08x\n", i, |
| 683 | hw->swf3x[i]); | 788 | hw->swf3x[i]); |
| 684 | } | 789 | } |
| 685 | for (i = 0; i < 8; i++) | 790 | for (i = 0; i < 8; i++) |
| 686 | printk(" FENCE%d 0x%08x\n", i, | 791 | printk(" FENCE%d 0x%08x\n", i, |
| 687 | hw->fence[i]); | 792 | hw->fence[i]); |
| 688 | 793 | ||
| 689 | printk(" INSTPM 0x%08x\n", hw->instpm); | 794 | printk(" INSTPM 0x%08x\n", hw->instpm); |
| 690 | printk(" MEM_MODE 0x%08x\n", hw->mem_mode); | 795 | printk(" MEM_MODE 0x%08x\n", hw->mem_mode); |
| @@ -695,43 +800,58 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) | |||
| 695 | #endif | 800 | #endif |
| 696 | } | 801 | } |
| 697 | 802 | ||
| 803 | |||
| 804 | |||
| 698 | /* Split the M parameter into M1 and M2. */ | 805 | /* Split the M parameter into M1 and M2. */ |
| 699 | static int | 806 | static int |
| 700 | splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2) | 807 | splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2) |
| 701 | { | 808 | { |
| 702 | int m1, m2; | 809 | int m1, m2; |
| 703 | 810 | int testm; | |
| 704 | m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2; | 811 | struct pll_min_max *pll = &plls[index]; |
| 705 | if (m1 < MIN_M1) | 812 | |
| 706 | m1 = MIN_M1; | 813 | /* no point optimising too much - brute force m */ |
| 707 | if (m1 > MAX_M1) | 814 | for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) { |
| 708 | m1 = MAX_M1; | 815 | for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) { |
| 709 | m2 = m - 5 * (m1 + 2) - 2; | 816 | testm = (5 * (m1 + 2)) + (m2 + 2); |
| 710 | if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) { | 817 | if (testm == m) { |
| 711 | return 1; | 818 | *retm1 = (unsigned int)m1; |
| 712 | } else { | 819 | *retm2 = (unsigned int)m2; |
| 713 | *retm1 = (unsigned int)m1; | 820 | return 0; |
| 714 | *retm2 = (unsigned int)m2; | 821 | } |
| 715 | return 0; | 822 | } |
| 716 | } | 823 | } |
| 824 | return 1; | ||
| 717 | } | 825 | } |
| 718 | 826 | ||
| 719 | /* Split the P parameter into P1 and P2. */ | 827 | /* Split the P parameter into P1 and P2. */ |
| 720 | static int | 828 | static int |
| 721 | splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) | 829 | splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2) |
| 722 | { | 830 | { |
| 723 | int p1, p2; | 831 | int p1, p2; |
| 832 | struct pll_min_max *pll = &plls[index]; | ||
| 833 | |||
| 834 | if (index == PLLS_I9xx) { | ||
| 835 | p2 = (p % 10) ? 1 : 0; | ||
| 836 | |||
| 837 | p1 = p / (p2 ? 5 : 10); | ||
| 838 | |||
| 839 | *retp1 = (unsigned int)p1; | ||
| 840 | *retp2 = (unsigned int)p2; | ||
| 841 | return 0; | ||
| 842 | } | ||
| 724 | 843 | ||
| 725 | if (p % 4 == 0) | 844 | if (p % 4 == 0) |
| 726 | p2 = 1; | 845 | p2 = 1; |
| 727 | else | 846 | else |
| 728 | p2 = 0; | 847 | p2 = 0; |
| 729 | p1 = (p / (1 << (p2 + 1))) - 2; | 848 | p1 = (p / (1 << (p2 + 1))) - 2; |
| 730 | if (p % 4 == 0 && p1 < MIN_P1) { | 849 | if (p % 4 == 0 && p1 < pll->min_p1) { |
| 731 | p2 = 0; | 850 | p2 = 0; |
| 732 | p1 = (p / (1 << (p2 + 1))) - 2; | 851 | p1 = (p / (1 << (p2 + 1))) - 2; |
| 733 | } | 852 | } |
| 734 | if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) { | 853 | if (p1 < pll->min_p1 || p1 > pll->max_p1 || |
| 854 | (p1 + 2) * (1 << (p2 + 1)) != p) { | ||
| 735 | return 1; | 855 | return 1; |
| 736 | } else { | 856 | } else { |
| 737 | *retp1 = (unsigned int)p1; | 857 | *retp1 = (unsigned int)p1; |
| @@ -741,14 +861,15 @@ splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2) | |||
| 741 | } | 861 | } |
| 742 | 862 | ||
| 743 | static int | 863 | static int |
| 744 | calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | 864 | calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, |
| 745 | u32 *retp2, u32 *retclock) | 865 | u32 *retp2, u32 *retclock) |
| 746 | { | 866 | { |
| 747 | u32 m1, m2, n, p1, p2, n1; | 867 | u32 m1, m2, n, p1, p2, n1, testm; |
| 748 | u32 f_vco, p, p_best = 0, m, f_out; | 868 | u32 f_vco, p, p_best = 0, m, f_out = 0; |
| 749 | u32 err_max, err_target, err_best = 10000000; | 869 | u32 err_max, err_target, err_best = 10000000; |
| 750 | u32 n_best = 0, m_best = 0, f_best, f_err; | 870 | u32 n_best = 0, m_best = 0, f_best, f_err; |
| 751 | u32 p_min, p_max, p_inc, div_min, div_max; | 871 | u32 p_min, p_max, p_inc, div_max; |
| 872 | struct pll_min_max *pll = &plls[index]; | ||
| 752 | 873 | ||
| 753 | /* Accept 0.5% difference, but aim for 0.1% */ | 874 | /* Accept 0.5% difference, but aim for 0.1% */ |
| 754 | err_max = 5 * clock / 1000; | 875 | err_max = 5 * clock / 1000; |
| @@ -756,58 +877,56 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
| 756 | 877 | ||
| 757 | DBG_MSG("Clock is %d\n", clock); | 878 | DBG_MSG("Clock is %d\n", clock); |
| 758 | 879 | ||
| 759 | div_max = MAX_VCO_FREQ / clock; | 880 | div_max = pll->max_vco / clock; |
| 760 | div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock; | ||
| 761 | 881 | ||
| 762 | if (clock <= P_TRANSITION_CLOCK) | 882 | p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi; |
| 763 | p_inc = 4; | 883 | p_min = p_inc; |
| 764 | else | ||
| 765 | p_inc = 2; | ||
| 766 | p_min = ROUND_UP_TO(div_min, p_inc); | ||
| 767 | p_max = ROUND_DOWN_TO(div_max, p_inc); | 884 | p_max = ROUND_DOWN_TO(div_max, p_inc); |
| 768 | if (p_min < MIN_P) | 885 | if (p_min < pll->min_p) |
| 769 | p_min = 4; | 886 | p_min = pll->min_p; |
| 770 | if (p_max > MAX_P) | 887 | if (p_max > pll->max_p) |
| 771 | p_max = 128; | 888 | p_max = pll->max_p; |
| 772 | 889 | ||
| 773 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); | 890 | DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc); |
| 774 | 891 | ||
| 775 | p = p_min; | 892 | p = p_min; |
| 776 | do { | 893 | do { |
| 777 | if (splitp(p, &p1, &p2)) { | 894 | if (splitp(index, p, &p1, &p2)) { |
| 778 | WRN_MSG("cannot split p = %d\n", p); | 895 | WRN_MSG("cannot split p = %d\n", p); |
| 779 | p += p_inc; | 896 | p += p_inc; |
| 780 | continue; | 897 | continue; |
| 781 | } | 898 | } |
| 782 | n = MIN_N; | 899 | n = pll->min_n; |
| 783 | f_vco = clock * p; | 900 | f_vco = clock * p; |
| 784 | 901 | ||
| 785 | do { | 902 | do { |
| 786 | m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK; | 903 | m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk; |
| 787 | if (m < MIN_M) | 904 | if (m < pll->min_m) |
| 788 | m = MIN_M; | 905 | m = pll->min_m + 1; |
| 789 | if (m > MAX_M) | 906 | if (m > pll->max_m) |
| 790 | m = MAX_M; | 907 | m = pll->max_m - 1; |
| 791 | f_out = CALC_VCLOCK3(m, n, p); | 908 | for (testm = m - 1; testm <= m; testm++) { |
| 792 | if (splitm(m, &m1, &m2)) { | 909 | f_out = calc_vclock3(index, m, n, p); |
| 793 | WRN_MSG("cannot split m = %d\n", m); | 910 | if (splitm(index, testm, &m1, &m2)) { |
| 794 | n++; | 911 | WRN_MSG("cannot split m = %d\n", m); |
| 795 | continue; | 912 | n++; |
| 796 | } | 913 | continue; |
| 797 | if (clock > f_out) | 914 | } |
| 798 | f_err = clock - f_out; | 915 | if (clock > f_out) |
| 799 | else | 916 | f_err = clock - f_out; |
| 800 | f_err = f_out - clock; | 917 | else/* slightly bias the error for bigger clocks */ |
| 801 | 918 | f_err = f_out - clock + 1; | |
| 802 | if (f_err < err_best) { | 919 | |
| 803 | m_best = m; | 920 | if (f_err < err_best) { |
| 804 | n_best = n; | 921 | m_best = testm; |
| 805 | p_best = p; | 922 | n_best = n; |
| 806 | f_best = f_out; | 923 | p_best = p; |
| 807 | err_best = f_err; | 924 | f_best = f_out; |
| 925 | err_best = f_err; | ||
| 926 | } | ||
| 808 | } | 927 | } |
| 809 | n++; | 928 | n++; |
| 810 | } while ((n <= MAX_N) && (f_out >= clock)); | 929 | } while ((n <= pll->max_n) && (f_out >= clock)); |
| 811 | p += p_inc; | 930 | p += p_inc; |
| 812 | } while ((p <= p_max)); | 931 | } while ((p <= p_max)); |
| 813 | 932 | ||
| @@ -818,21 +937,22 @@ calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1, | |||
| 818 | m = m_best; | 937 | m = m_best; |
| 819 | n = n_best; | 938 | n = n_best; |
| 820 | p = p_best; | 939 | p = p_best; |
| 821 | splitm(m, &m1, &m2); | 940 | splitm(index, m, &m1, &m2); |
| 822 | splitp(p, &p1, &p2); | 941 | splitp(index, p, &p1, &p2); |
| 823 | n1 = n - 2; | 942 | n1 = n - 2; |
| 824 | 943 | ||
| 825 | DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " | 944 | DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), " |
| 826 | "f: %d (%d), VCO: %d\n", | 945 | "f: %d (%d), VCO: %d\n", |
| 827 | m, m1, m2, n, n1, p, p1, p2, | 946 | m, m1, m2, n, n1, p, p1, p2, |
| 828 | CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2), | 947 | calc_vclock3(index, m, n, p), |
| 829 | CALC_VCLOCK3(m, n, p) * p); | 948 | calc_vclock(index, m1, m2, n1, p1, p2, 0), |
| 949 | calc_vclock3(index, m, n, p) * p); | ||
| 830 | *retm1 = m1; | 950 | *retm1 = m1; |
| 831 | *retm2 = m2; | 951 | *retm2 = m2; |
| 832 | *retn = n1; | 952 | *retn = n1; |
| 833 | *retp1 = p1; | 953 | *retp1 = p1; |
| 834 | *retp2 = p2; | 954 | *retp2 = p2; |
| 835 | *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2); | 955 | *retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0); |
| 836 | 956 | ||
| 837 | return 0; | 957 | return 0; |
| 838 | } | 958 | } |
| @@ -860,6 +980,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
| 860 | u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive; | 980 | u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive; |
| 861 | u32 vsync_pol, hsync_pol; | 981 | u32 vsync_pol, hsync_pol; |
| 862 | u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf; | 982 | u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf; |
| 983 | u32 stride_alignment; | ||
| 863 | 984 | ||
| 864 | DBG_MSG("intelfbhw_mode_to_hw\n"); | 985 | DBG_MSG("intelfbhw_mode_to_hw\n"); |
| 865 | 986 | ||
| @@ -929,7 +1050,8 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
| 929 | /* Desired clock in kHz */ | 1050 | /* Desired clock in kHz */ |
| 930 | clock_target = 1000000000 / var->pixclock; | 1051 | clock_target = 1000000000 / var->pixclock; |
| 931 | 1052 | ||
| 932 | if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) { | 1053 | if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2, |
| 1054 | &n, &p1, &p2, &clock)) { | ||
| 933 | WRN_MSG("calc_pll_params failed\n"); | 1055 | WRN_MSG("calc_pll_params failed\n"); |
| 934 | return 1; | 1056 | return 1; |
| 935 | } | 1057 | } |
| @@ -949,7 +1071,14 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
| 949 | *dpll &= ~DPLL_P1_FORCE_DIV2; | 1071 | *dpll &= ~DPLL_P1_FORCE_DIV2; |
| 950 | *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | | 1072 | *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) | |
| 951 | (DPLL_P1_MASK << DPLL_P1_SHIFT)); | 1073 | (DPLL_P1_MASK << DPLL_P1_SHIFT)); |
| 952 | *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); | 1074 | |
| 1075 | if (IS_I9XX(dinfo)) { | ||
| 1076 | *dpll |= (p2 << DPLL_I9XX_P2_SHIFT); | ||
| 1077 | *dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT; | ||
| 1078 | } else { | ||
| 1079 | *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT); | ||
| 1080 | } | ||
| 1081 | |||
| 953 | *fp0 = (n << FP_N_DIVISOR_SHIFT) | | 1082 | *fp0 = (n << FP_N_DIVISOR_SHIFT) | |
| 954 | (m1 << FP_M1_DIVISOR_SHIFT) | | 1083 | (m1 << FP_M1_DIVISOR_SHIFT) | |
| 955 | (m2 << FP_M2_DIVISOR_SHIFT); | 1084 | (m2 << FP_M2_DIVISOR_SHIFT); |
| @@ -1054,7 +1183,7 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
| 1054 | *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) | | 1183 | *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) | |
| 1055 | (vactive << SRC_SIZE_VERT_SHIFT); | 1184 | (vactive << SRC_SIZE_VERT_SHIFT); |
| 1056 | 1185 | ||
| 1057 | hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8; | 1186 | hw->disp_a_stride = dinfo->pitch; |
| 1058 | DBG_MSG("pitch is %d\n", hw->disp_a_stride); | 1187 | DBG_MSG("pitch is %d\n", hw->disp_a_stride); |
| 1059 | 1188 | ||
| 1060 | hw->disp_a_base = hw->disp_a_stride * var->yoffset + | 1189 | hw->disp_a_base = hw->disp_a_stride * var->yoffset + |
| @@ -1063,9 +1192,11 @@ intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw, | |||
| 1063 | hw->disp_a_base += dinfo->fb.offset << 12; | 1192 | hw->disp_a_base += dinfo->fb.offset << 12; |
| 1064 | 1193 | ||
| 1065 | /* Check stride alignment. */ | 1194 | /* Check stride alignment. */ |
| 1066 | if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) { | 1195 | stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX : |
| 1196 | STRIDE_ALIGNMENT; | ||
| 1197 | if (hw->disp_a_stride % stride_alignment != 0) { | ||
| 1067 | WRN_MSG("display stride %d has bad alignment %d\n", | 1198 | WRN_MSG("display stride %d has bad alignment %d\n", |
| 1068 | hw->disp_a_stride, STRIDE_ALIGNMENT); | 1199 | hw->disp_a_stride, stride_alignment); |
| 1069 | return 1; | 1200 | return 1; |
| 1070 | } | 1201 | } |
| 1071 | 1202 | ||
| @@ -1087,6 +1218,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
| 1087 | u32 hsync_reg, htotal_reg, hblank_reg; | 1218 | u32 hsync_reg, htotal_reg, hblank_reg; |
| 1088 | u32 vsync_reg, vtotal_reg, vblank_reg; | 1219 | u32 vsync_reg, vtotal_reg, vblank_reg; |
| 1089 | u32 src_size_reg; | 1220 | u32 src_size_reg; |
| 1221 | u32 count, tmp_val[3]; | ||
| 1090 | 1222 | ||
| 1091 | /* Assume single pipe, display plane A, analog CRT. */ | 1223 | /* Assume single pipe, display plane A, analog CRT. */ |
| 1092 | 1224 | ||
| @@ -1155,6 +1287,27 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
| 1155 | src_size_reg = SRC_SIZE_A; | 1287 | src_size_reg = SRC_SIZE_A; |
| 1156 | } | 1288 | } |
| 1157 | 1289 | ||
| 1290 | /* turn off pipe */ | ||
| 1291 | tmp = INREG(pipe_conf_reg); | ||
| 1292 | tmp &= ~PIPECONF_ENABLE; | ||
| 1293 | OUTREG(pipe_conf_reg, tmp); | ||
| 1294 | |||
| 1295 | count = 0; | ||
| 1296 | do { | ||
| 1297 | tmp_val[count%3] = INREG(0x70000); | ||
| 1298 | if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2])) | ||
| 1299 | break; | ||
| 1300 | count++; | ||
| 1301 | udelay(1); | ||
| 1302 | if (count % 200 == 0) { | ||
| 1303 | tmp = INREG(pipe_conf_reg); | ||
| 1304 | tmp &= ~PIPECONF_ENABLE; | ||
| 1305 | OUTREG(pipe_conf_reg, tmp); | ||
| 1306 | } | ||
| 1307 | } while(count < 2000); | ||
| 1308 | |||
| 1309 | OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE); | ||
| 1310 | |||
| 1158 | /* Disable planes A and B. */ | 1311 | /* Disable planes A and B. */ |
| 1159 | tmp = INREG(DSPACNTR); | 1312 | tmp = INREG(DSPACNTR); |
| 1160 | tmp &= ~DISPPLANE_PLANE_ENABLE; | 1313 | tmp &= ~DISPPLANE_PLANE_ENABLE; |
| @@ -1163,19 +1316,21 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
| 1163 | tmp &= ~DISPPLANE_PLANE_ENABLE; | 1316 | tmp &= ~DISPPLANE_PLANE_ENABLE; |
| 1164 | OUTREG(DSPBCNTR, tmp); | 1317 | OUTREG(DSPBCNTR, tmp); |
| 1165 | 1318 | ||
| 1166 | /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ | 1319 | /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */ |
| 1167 | mdelay(20); | 1320 | mdelay(20); |
| 1168 | 1321 | ||
| 1322 | OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE); | ||
| 1323 | OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE); | ||
| 1324 | OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE); | ||
| 1325 | |||
| 1169 | /* Disable Sync */ | 1326 | /* Disable Sync */ |
| 1170 | tmp = INREG(ADPA); | 1327 | tmp = INREG(ADPA); |
| 1171 | tmp &= ~ADPA_DPMS_CONTROL_MASK; | 1328 | tmp &= ~ADPA_DPMS_CONTROL_MASK; |
| 1172 | tmp |= ADPA_DPMS_D3; | 1329 | tmp |= ADPA_DPMS_D3; |
| 1173 | OUTREG(ADPA, tmp); | 1330 | OUTREG(ADPA, tmp); |
| 1174 | 1331 | ||
| 1175 | /* turn off pipe */ | 1332 | /* do some funky magic - xyzzy */ |
| 1176 | tmp = INREG(pipe_conf_reg); | 1333 | OUTREG(0x61204, 0xabcd0000); |
| 1177 | tmp &= ~PIPECONF_ENABLE; | ||
| 1178 | OUTREG(pipe_conf_reg, tmp); | ||
| 1179 | 1334 | ||
| 1180 | /* turn off PLL */ | 1335 | /* turn off PLL */ |
| 1181 | tmp = INREG(dpll_reg); | 1336 | tmp = INREG(dpll_reg); |
| @@ -1183,30 +1338,31 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
| 1183 | OUTREG(dpll_reg, tmp); | 1338 | OUTREG(dpll_reg, tmp); |
| 1184 | 1339 | ||
| 1185 | /* Set PLL parameters */ | 1340 | /* Set PLL parameters */ |
| 1186 | OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE); | ||
| 1187 | OUTREG(fp0_reg, *fp0); | 1341 | OUTREG(fp0_reg, *fp0); |
| 1188 | OUTREG(fp1_reg, *fp1); | 1342 | OUTREG(fp1_reg, *fp1); |
| 1189 | 1343 | ||
| 1190 | /* Set pipe parameters */ | 1344 | /* Enable PLL */ |
| 1191 | OUTREG(hsync_reg, *hs); | 1345 | OUTREG(dpll_reg, *dpll); |
| 1192 | OUTREG(hblank_reg, *hb); | ||
| 1193 | OUTREG(htotal_reg, *ht); | ||
| 1194 | OUTREG(vsync_reg, *vs); | ||
| 1195 | OUTREG(vblank_reg, *vb); | ||
| 1196 | OUTREG(vtotal_reg, *vt); | ||
| 1197 | OUTREG(src_size_reg, *ss); | ||
| 1198 | 1346 | ||
| 1199 | /* Set DVOs B/C */ | 1347 | /* Set DVOs B/C */ |
| 1200 | OUTREG(DVOB, hw->dvob); | 1348 | OUTREG(DVOB, hw->dvob); |
| 1201 | OUTREG(DVOC, hw->dvoc); | 1349 | OUTREG(DVOC, hw->dvoc); |
| 1202 | 1350 | ||
| 1351 | /* undo funky magic */ | ||
| 1352 | OUTREG(0x61204, 0x00000000); | ||
| 1353 | |||
| 1203 | /* Set ADPA */ | 1354 | /* Set ADPA */ |
| 1355 | OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE); | ||
| 1204 | OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3); | 1356 | OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3); |
| 1205 | 1357 | ||
| 1206 | /* Enable PLL */ | 1358 | /* Set pipe parameters */ |
| 1207 | tmp = INREG(dpll_reg); | 1359 | OUTREG(hsync_reg, *hs); |
| 1208 | tmp |= DPLL_VCO_ENABLE; | 1360 | OUTREG(hblank_reg, *hb); |
| 1209 | OUTREG(dpll_reg, tmp); | 1361 | OUTREG(htotal_reg, *ht); |
| 1362 | OUTREG(vsync_reg, *vs); | ||
| 1363 | OUTREG(vblank_reg, *vb); | ||
| 1364 | OUTREG(vtotal_reg, *vt); | ||
| 1365 | OUTREG(src_size_reg, *ss); | ||
| 1210 | 1366 | ||
| 1211 | /* Enable pipe */ | 1367 | /* Enable pipe */ |
| 1212 | OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE); | 1368 | OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE); |
| @@ -1231,7 +1387,7 @@ intelfbhw_program_mode(struct intelfb_info *dinfo, | |||
| 1231 | OUTREG(DSPACNTR, | 1387 | OUTREG(DSPACNTR, |
| 1232 | hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); | 1388 | hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE); |
| 1233 | mdelay(1); | 1389 | mdelay(1); |
| 1234 | } | 1390 | } |
| 1235 | } | 1391 | } |
| 1236 | 1392 | ||
| 1237 | OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); | 1393 | OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE); |
| @@ -1616,7 +1772,7 @@ intelfbhw_cursor_init(struct intelfb_info *dinfo) | |||
| 1616 | DBG_MSG("intelfbhw_cursor_init\n"); | 1772 | DBG_MSG("intelfbhw_cursor_init\n"); |
| 1617 | #endif | 1773 | #endif |
| 1618 | 1774 | ||
| 1619 | if (dinfo->mobile) { | 1775 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
| 1620 | if (!dinfo->cursor.physical) | 1776 | if (!dinfo->cursor.physical) |
| 1621 | return; | 1777 | return; |
| 1622 | tmp = INREG(CURSOR_A_CONTROL); | 1778 | tmp = INREG(CURSOR_A_CONTROL); |
| @@ -1649,7 +1805,7 @@ intelfbhw_cursor_hide(struct intelfb_info *dinfo) | |||
| 1649 | #endif | 1805 | #endif |
| 1650 | 1806 | ||
| 1651 | dinfo->cursor_on = 0; | 1807 | dinfo->cursor_on = 0; |
| 1652 | if (dinfo->mobile) { | 1808 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
| 1653 | if (!dinfo->cursor.physical) | 1809 | if (!dinfo->cursor.physical) |
| 1654 | return; | 1810 | return; |
| 1655 | tmp = INREG(CURSOR_A_CONTROL); | 1811 | tmp = INREG(CURSOR_A_CONTROL); |
| @@ -1679,7 +1835,7 @@ intelfbhw_cursor_show(struct intelfb_info *dinfo) | |||
| 1679 | if (dinfo->cursor_blanked) | 1835 | if (dinfo->cursor_blanked) |
| 1680 | return; | 1836 | return; |
| 1681 | 1837 | ||
| 1682 | if (dinfo->mobile) { | 1838 | if (dinfo->mobile || IS_I9XX(dinfo)) { |
| 1683 | if (!dinfo->cursor.physical) | 1839 | if (!dinfo->cursor.physical) |
| 1684 | return; | 1840 | return; |
| 1685 | tmp = INREG(CURSOR_A_CONTROL); | 1841 | tmp = INREG(CURSOR_A_CONTROL); |
| @@ -1705,14 +1861,18 @@ intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y) | |||
| 1705 | #endif | 1861 | #endif |
| 1706 | 1862 | ||
| 1707 | /* | 1863 | /* |
| 1708 | * Sets the position. The coordinates are assumed to already | 1864 | * Sets the position. The coordinates are assumed to already |
| 1709 | * have any offset adjusted. Assume that the cursor is never | 1865 | * have any offset adjusted. Assume that the cursor is never |
| 1710 | * completely off-screen, and that x, y are always >= 0. | 1866 | * completely off-screen, and that x, y are always >= 0. |
| 1711 | */ | 1867 | */ |
| 1712 | 1868 | ||
| 1713 | tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | | 1869 | tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | |
| 1714 | ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | 1870 | ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); |
| 1715 | OUTREG(CURSOR_A_POSITION, tmp); | 1871 | OUTREG(CURSOR_A_POSITION, tmp); |
| 1872 | |||
| 1873 | if (IS_I9XX(dinfo)) { | ||
| 1874 | OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical); | ||
| 1875 | } | ||
| 1716 | } | 1876 | } |
| 1717 | 1877 | ||
| 1718 | void | 1878 | void |
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h index ba1920159f52..10acda098b71 100644 --- a/drivers/video/intelfb/intelfbhw.h +++ b/drivers/video/intelfb/intelfbhw.h | |||
| @@ -133,6 +133,7 @@ | |||
| 133 | #define DPLL_VGA_MODE_DISABLE (1 << 28) | 133 | #define DPLL_VGA_MODE_DISABLE (1 << 28) |
| 134 | #define DPLL_P2_MASK 1 | 134 | #define DPLL_P2_MASK 1 |
| 135 | #define DPLL_P2_SHIFT 23 | 135 | #define DPLL_P2_SHIFT 23 |
| 136 | #define DPLL_I9XX_P2_SHIFT 24 | ||
| 136 | #define DPLL_P1_FORCE_DIV2 (1 << 21) | 137 | #define DPLL_P1_FORCE_DIV2 (1 << 21) |
| 137 | #define DPLL_P1_MASK 0x1f | 138 | #define DPLL_P1_MASK 0x1f |
| 138 | #define DPLL_P1_SHIFT 16 | 139 | #define DPLL_P1_SHIFT 16 |
| @@ -155,29 +156,8 @@ | |||
| 155 | /* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ | 156 | /* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */ |
| 156 | /* Clock values are in units of kHz */ | 157 | /* Clock values are in units of kHz */ |
| 157 | #define PLL_REFCLK 48000 | 158 | #define PLL_REFCLK 48000 |
| 158 | #define MIN_VCO_FREQ 930000 | ||
| 159 | #define MAX_VCO_FREQ 1400000 | ||
| 160 | #define MIN_CLOCK 25000 | 159 | #define MIN_CLOCK 25000 |
| 161 | #define MAX_CLOCK 350000 | 160 | #define MAX_CLOCK 350000 |
| 162 | #define P_TRANSITION_CLOCK 165000 | ||
| 163 | #define MIN_M 108 | ||
| 164 | #define MAX_M 140 | ||
| 165 | #define MIN_M1 18 | ||
| 166 | #define MAX_M1 26 | ||
| 167 | #define MIN_M2 6 | ||
| 168 | #define MAX_M2 16 | ||
| 169 | #define MIN_P 4 | ||
| 170 | #define MAX_P 128 | ||
| 171 | #define MIN_P1 0 | ||
| 172 | #define MAX_P1 31 | ||
| 173 | #define MIN_N 3 | ||
| 174 | #define MAX_N 16 | ||
| 175 | |||
| 176 | #define CALC_VCLOCK(m1, m2, n, p1, p2) \ | ||
| 177 | ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \ | ||
| 178 | (((p1) + 2) * (1 << (p2 + 1)))) | ||
| 179 | |||
| 180 | #define CALC_VCLOCK3(m, n, p) ((PLL_REFCLK * (m) / (n)) / (p)) | ||
| 181 | 161 | ||
| 182 | /* Two pipes */ | 162 | /* Two pipes */ |
| 183 | #define PIPE_A 0 | 163 | #define PIPE_A 0 |
| @@ -522,8 +502,7 @@ | |||
| 522 | 502 | ||
| 523 | 503 | ||
| 524 | /* function protoypes */ | 504 | /* function protoypes */ |
| 525 | extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, | 505 | extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo); |
| 526 | int *chipset, int *mobile); | ||
| 527 | extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, | 506 | extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, |
| 528 | int *stolen_size); | 507 | int *stolen_size); |
| 529 | extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo); | 508 | extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo); |
