aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/efifb.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/video/efifb.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/video/efifb.c')
-rw-r--r--drivers/video/efifb.c188
1 files changed, 116 insertions, 72 deletions
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 70477c2e4b61..784139aed079 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -16,6 +16,8 @@
16#include <linux/pci.h> 16#include <linux/pci.h>
17#include <video/vga.h> 17#include <video/vga.h>
18 18
19static bool request_mem_succeeded = false;
20
19static struct fb_var_screeninfo efifb_defined __devinitdata = { 21static struct fb_var_screeninfo efifb_defined __devinitdata = {
20 .activate = FB_ACTIVATE_NOW, 22 .activate = FB_ACTIVATE_NOW,
21 .height = -1, 23 .height = -1,
@@ -53,6 +55,7 @@ enum {
53 M_MB_7_1, /* MacBook, 7th rev. */ 55 M_MB_7_1, /* MacBook, 7th rev. */
54 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ 56 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
55 M_MBA, /* MacBook Air */ 57 M_MBA, /* MacBook Air */
58 M_MBA_3, /* Macbook Air, 3rd rev */
56 M_MBP, /* MacBook Pro */ 59 M_MBP, /* MacBook Pro */
57 M_MBP_2, /* MacBook Pro 2nd gen */ 60 M_MBP_2, /* MacBook Pro 2nd gen */
58 M_MBP_2_2, /* MacBook Pro 2,2nd gen */ 61 M_MBP_2_2, /* MacBook Pro 2,2nd gen */
@@ -64,43 +67,54 @@ enum {
64 M_MBP_6_1, /* MacBook Pro, 6,1th gen */ 67 M_MBP_6_1, /* MacBook Pro, 6,1th gen */
65 M_MBP_6_2, /* MacBook Pro, 6,2th gen */ 68 M_MBP_6_2, /* MacBook Pro, 6,2th gen */
66 M_MBP_7_1, /* MacBook Pro, 7,1th gen */ 69 M_MBP_7_1, /* MacBook Pro, 7,1th gen */
70 M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
67 M_UNKNOWN /* placeholder */ 71 M_UNKNOWN /* placeholder */
68}; 72};
69 73
74#define OVERRIDE_NONE 0x0
75#define OVERRIDE_BASE 0x1
76#define OVERRIDE_STRIDE 0x2
77#define OVERRIDE_HEIGHT 0x4
78#define OVERRIDE_WIDTH 0x8
79
70static struct efifb_dmi_info { 80static struct efifb_dmi_info {
71 char *optname; 81 char *optname;
72 unsigned long base; 82 unsigned long base;
73 int stride; 83 int stride;
74 int width; 84 int width;
75 int height; 85 int height;
86 int flags;
76} dmi_list[] __initdata = { 87} dmi_list[] __initdata = {
77 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, 88 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
78 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ 89 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
79 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, 90 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
80 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ 91 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
81 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, 92 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
82 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, 93 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
83 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, 94 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
84 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, 95 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
85 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, 96 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
86 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, 97 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
87 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, 98 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
88 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, 99 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
89 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, 100 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
90 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, 101 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
91 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, 102 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
92 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, 103 /* 11" Macbook Air 3,1 passes the wrong stride */
93 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ 104 [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
94 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, 105 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
95 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, 106 [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
96 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, 107 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
97 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, 108 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
98 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, 109 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
99 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, 110 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
100 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, 111 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
101 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, 112 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
102 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, 113 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
103 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } 114 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
115 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
116 [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
117 [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
104}; 118};
105 119
106static int set_system(const struct dmi_system_id *id); 120static int set_system(const struct dmi_system_id *id);
@@ -138,6 +152,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
138 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), 152 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
139 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), 153 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
140 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), 154 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
155 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
141 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), 156 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
142 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), 157 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
143 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), 158 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
@@ -151,19 +166,26 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
151 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), 166 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
152 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), 167 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
153 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), 168 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
169 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
154 {}, 170 {},
155}; 171};
156 172
173#define choose_value(dmivalue, fwvalue, field, flags) ({ \
174 typeof(fwvalue) _ret_ = fwvalue; \
175 if ((flags) & (field)) \
176 _ret_ = dmivalue; \
177 else if ((fwvalue) == 0) \
178 _ret_ = dmivalue; \
179 _ret_; \
180 })
181
157static int set_system(const struct dmi_system_id *id) 182static int set_system(const struct dmi_system_id *id)
158{ 183{
159 struct efifb_dmi_info *info = id->driver_data; 184 struct efifb_dmi_info *info = id->driver_data;
160 if (info->base == 0)
161 return 0;
162 185
163 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " 186 if (info->base == 0 && info->height == 0 && info->width == 0
164 "(%dx%d, stride %d)\n", id->ident, 187 && info->stride == 0)
165 (void *)info->base, info->width, info->height, 188 return 0;
166 info->stride);
167 189
168 /* Trust the bootloader over the DMI tables */ 190 /* Trust the bootloader over the DMI tables */
169 if (screen_info.lfb_base == 0) { 191 if (screen_info.lfb_base == 0) {
@@ -171,40 +193,47 @@ static int set_system(const struct dmi_system_id *id)
171 struct pci_dev *dev = NULL; 193 struct pci_dev *dev = NULL;
172 int found_bar = 0; 194 int found_bar = 0;
173#endif 195#endif
174 screen_info.lfb_base = info->base; 196 if (info->base) {
197 screen_info.lfb_base = choose_value(info->base,
198 screen_info.lfb_base, OVERRIDE_BASE,
199 info->flags);
175 200
176#if defined(CONFIG_PCI) 201#if defined(CONFIG_PCI)
177 /* make sure that the address in the table is actually on a 202 /* make sure that the address in the table is actually
178 * VGA device's PCI BAR */ 203 * on a VGA device's PCI BAR */
179 204
180 for_each_pci_dev(dev) { 205 for_each_pci_dev(dev) {
181 int i; 206 int i;
182 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) 207 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
183 continue; 208 continue;
184 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 209 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
185 resource_size_t start, end; 210 resource_size_t start, end;
186 211
187 start = pci_resource_start(dev, i); 212 start = pci_resource_start(dev, i);
188 if (start == 0) 213 if (start == 0)
189 break; 214 break;
190 end = pci_resource_end(dev, i); 215 end = pci_resource_end(dev, i);
191 if (screen_info.lfb_base >= start && 216 if (screen_info.lfb_base >= start &&
192 screen_info.lfb_base < end) { 217 screen_info.lfb_base < end) {
193 found_bar = 1; 218 found_bar = 1;
219 }
194 } 220 }
195 } 221 }
196 } 222 if (!found_bar)
197 if (!found_bar) 223 screen_info.lfb_base = 0;
198 screen_info.lfb_base = 0;
199#endif 224#endif
225 }
200 } 226 }
201 if (screen_info.lfb_base) { 227 if (screen_info.lfb_base) {
202 if (screen_info.lfb_linelength == 0) 228 screen_info.lfb_linelength = choose_value(info->stride,
203 screen_info.lfb_linelength = info->stride; 229 screen_info.lfb_linelength, OVERRIDE_STRIDE,
204 if (screen_info.lfb_width == 0) 230 info->flags);
205 screen_info.lfb_width = info->width; 231 screen_info.lfb_width = choose_value(info->width,
206 if (screen_info.lfb_height == 0) 232 screen_info.lfb_width, OVERRIDE_WIDTH,
207 screen_info.lfb_height = info->height; 233 info->flags);
234 screen_info.lfb_height = choose_value(info->height,
235 screen_info.lfb_height, OVERRIDE_HEIGHT,
236 info->flags);
208 if (screen_info.orig_video_isVGA == 0) 237 if (screen_info.orig_video_isVGA == 0)
209 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; 238 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
210 } else { 239 } else {
@@ -214,6 +243,13 @@ static int set_system(const struct dmi_system_id *id)
214 screen_info.orig_video_isVGA = 0; 243 screen_info.orig_video_isVGA = 0;
215 return 0; 244 return 0;
216 } 245 }
246
247 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x "
248 "(%dx%d, stride %d)\n", id->ident,
249 screen_info.lfb_base, screen_info.lfb_width,
250 screen_info.lfb_height, screen_info.lfb_linelength);
251
252
217 return 1; 253 return 1;
218} 254}
219 255
@@ -247,7 +283,9 @@ static void efifb_destroy(struct fb_info *info)
247{ 283{
248 if (info->screen_base) 284 if (info->screen_base)
249 iounmap(info->screen_base); 285 iounmap(info->screen_base);
250 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); 286 if (request_mem_succeeded)
287 release_mem_region(info->apertures->ranges[0].base,
288 info->apertures->ranges[0].size);
251 framebuffer_release(info); 289 framebuffer_release(info);
252} 290}
253 291
@@ -292,14 +330,13 @@ static int __init efifb_setup(char *options)
292 return 0; 330 return 0;
293} 331}
294 332
295static int __devinit efifb_probe(struct platform_device *dev) 333static int __init efifb_probe(struct platform_device *dev)
296{ 334{
297 struct fb_info *info; 335 struct fb_info *info;
298 int err; 336 int err;
299 unsigned int size_vmode; 337 unsigned int size_vmode;
300 unsigned int size_remap; 338 unsigned int size_remap;
301 unsigned int size_total; 339 unsigned int size_total;
302 int request_succeeded = 0;
303 340
304 if (!screen_info.lfb_depth) 341 if (!screen_info.lfb_depth)
305 screen_info.lfb_depth = 32; 342 screen_info.lfb_depth = 32;
@@ -353,7 +390,7 @@ static int __devinit efifb_probe(struct platform_device *dev)
353 efifb_fix.smem_len = size_remap; 390 efifb_fix.smem_len = size_remap;
354 391
355 if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) { 392 if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
356 request_succeeded = 1; 393 request_mem_succeeded = true;
357 } else { 394 } else {
358 /* We cannot make this fatal. Sometimes this comes from magic 395 /* We cannot make this fatal. Sometimes this comes from magic
359 spaces our resource handlers simply don't know about */ 396 spaces our resource handlers simply don't know about */
@@ -379,7 +416,7 @@ static int __devinit efifb_probe(struct platform_device *dev)
379 info->apertures->ranges[0].base = efifb_fix.smem_start; 416 info->apertures->ranges[0].base = efifb_fix.smem_start;
380 info->apertures->ranges[0].size = size_remap; 417 info->apertures->ranges[0].size = size_remap;
381 418
382 info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); 419 info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
383 if (!info->screen_base) { 420 if (!info->screen_base) {
384 printk(KERN_ERR "efifb: abort, cannot ioremap video memory " 421 printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
385 "0x%x @ 0x%lx\n", 422 "0x%x @ 0x%lx\n",
@@ -457,13 +494,12 @@ err_unmap:
457err_release_fb: 494err_release_fb:
458 framebuffer_release(info); 495 framebuffer_release(info);
459err_release_mem: 496err_release_mem:
460 if (request_succeeded) 497 if (request_mem_succeeded)
461 release_mem_region(efifb_fix.smem_start, size_total); 498 release_mem_region(efifb_fix.smem_start, size_total);
462 return err; 499 return err;
463} 500}
464 501
465static struct platform_driver efifb_driver = { 502static struct platform_driver efifb_driver = {
466 .probe = efifb_probe,
467 .driver = { 503 .driver = {
468 .name = "efifb", 504 .name = "efifb",
469 }, 505 },
@@ -494,13 +530,21 @@ static int __init efifb_init(void)
494 if (!screen_info.lfb_linelength) 530 if (!screen_info.lfb_linelength)
495 return -ENODEV; 531 return -ENODEV;
496 532
497 ret = platform_driver_register(&efifb_driver); 533 ret = platform_device_register(&efifb_device);
534 if (ret)
535 return ret;
498 536
499 if (!ret) { 537 /*
500 ret = platform_device_register(&efifb_device); 538 * This is not just an optimization. We will interfere
501 if (ret) 539 * with a real driver if we get reprobed, so don't allow
502 platform_driver_unregister(&efifb_driver); 540 * it.
541 */
542 ret = platform_driver_probe(&efifb_driver, efifb_probe);
543 if (ret) {
544 platform_device_unregister(&efifb_device);
545 return ret;
503 } 546 }
547
504 return ret; 548 return ret;
505} 549}
506module_init(efifb_init); 550module_init(efifb_init);