diff options
Diffstat (limited to 'drivers/video')
-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); |