aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/efifb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/efifb.c')
-rw-r--r--drivers/video/efifb.c154
1 files changed, 94 insertions, 60 deletions
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 70477c2e4b61..4eb38db36e4b 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -53,6 +53,7 @@ enum {
53 M_MB_7_1, /* MacBook, 7th rev. */ 53 M_MB_7_1, /* MacBook, 7th rev. */
54 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ 54 M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
55 M_MBA, /* MacBook Air */ 55 M_MBA, /* MacBook Air */
56 M_MBA_3, /* Macbook Air, 3rd rev */
56 M_MBP, /* MacBook Pro */ 57 M_MBP, /* MacBook Pro */
57 M_MBP_2, /* MacBook Pro 2nd gen */ 58 M_MBP_2, /* MacBook Pro 2nd gen */
58 M_MBP_2_2, /* MacBook Pro 2,2nd gen */ 59 M_MBP_2_2, /* MacBook Pro 2,2nd gen */
@@ -64,43 +65,54 @@ enum {
64 M_MBP_6_1, /* MacBook Pro, 6,1th gen */ 65 M_MBP_6_1, /* MacBook Pro, 6,1th gen */
65 M_MBP_6_2, /* MacBook Pro, 6,2th gen */ 66 M_MBP_6_2, /* MacBook Pro, 6,2th gen */
66 M_MBP_7_1, /* MacBook Pro, 7,1th gen */ 67 M_MBP_7_1, /* MacBook Pro, 7,1th gen */
68 M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
67 M_UNKNOWN /* placeholder */ 69 M_UNKNOWN /* placeholder */
68}; 70};
69 71
72#define OVERRIDE_NONE 0x0
73#define OVERRIDE_BASE 0x1
74#define OVERRIDE_STRIDE 0x2
75#define OVERRIDE_HEIGHT 0x4
76#define OVERRIDE_WIDTH 0x8
77
70static struct efifb_dmi_info { 78static struct efifb_dmi_info {
71 char *optname; 79 char *optname;
72 unsigned long base; 80 unsigned long base;
73 int stride; 81 int stride;
74 int width; 82 int width;
75 int height; 83 int height;
84 int flags;
76} dmi_list[] __initdata = { 85} dmi_list[] __initdata = {
77 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, 86 [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
78 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ 87 [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
79 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, 88 [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
80 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ 89 [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
81 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, 90 [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
82 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, 91 [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
83 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, 92 [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
84 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, 93 [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
85 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, 94 [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
86 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, 95 [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
87 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, 96 [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
88 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, 97 [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
89 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, 98 [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
90 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, 99 [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
91 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, 100 [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
92 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, 101 /* 11" Macbook Air 3,1 passes the wrong stride */
93 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ 102 [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
94 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, 103 [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
95 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, 104 [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
96 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, 105 [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
97 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, 106 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
98 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, 107 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
99 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, 108 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
100 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, 109 [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
101 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, 110 [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
102 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, 111 [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
103 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } 112 [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
113 [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
114 [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
115 [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
104}; 116};
105 117
106static int set_system(const struct dmi_system_id *id); 118static int set_system(const struct dmi_system_id *id);
@@ -138,6 +150,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
138 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), 150 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), 151 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
140 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), 152 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
153 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
141 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), 154 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
142 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), 155 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), 156 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
@@ -151,19 +164,26 @@ static const struct dmi_system_id dmi_system_table[] __initconst = {
151 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), 164 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), 165 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), 166 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
167 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
154 {}, 168 {},
155}; 169};
156 170
171#define choose_value(dmivalue, fwvalue, field, flags) ({ \
172 typeof(fwvalue) _ret_ = fwvalue; \
173 if ((flags) & (field)) \
174 _ret_ = dmivalue; \
175 else if ((fwvalue) == 0) \
176 _ret_ = dmivalue; \
177 _ret_; \
178 })
179
157static int set_system(const struct dmi_system_id *id) 180static int set_system(const struct dmi_system_id *id)
158{ 181{
159 struct efifb_dmi_info *info = id->driver_data; 182 struct efifb_dmi_info *info = id->driver_data;
160 if (info->base == 0)
161 return 0;
162 183
163 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " 184 if (info->base == 0 && info->height == 0 && info->width == 0
164 "(%dx%d, stride %d)\n", id->ident, 185 && info->stride == 0)
165 (void *)info->base, info->width, info->height, 186 return 0;
166 info->stride);
167 187
168 /* Trust the bootloader over the DMI tables */ 188 /* Trust the bootloader over the DMI tables */
169 if (screen_info.lfb_base == 0) { 189 if (screen_info.lfb_base == 0) {
@@ -171,40 +191,47 @@ static int set_system(const struct dmi_system_id *id)
171 struct pci_dev *dev = NULL; 191 struct pci_dev *dev = NULL;
172 int found_bar = 0; 192 int found_bar = 0;
173#endif 193#endif
174 screen_info.lfb_base = info->base; 194 if (info->base) {
195 screen_info.lfb_base = choose_value(info->base,
196 screen_info.lfb_base, OVERRIDE_BASE,
197 info->flags);
175 198
176#if defined(CONFIG_PCI) 199#if defined(CONFIG_PCI)
177 /* make sure that the address in the table is actually on a 200 /* make sure that the address in the table is actually
178 * VGA device's PCI BAR */ 201 * on a VGA device's PCI BAR */
179 202
180 for_each_pci_dev(dev) { 203 for_each_pci_dev(dev) {
181 int i; 204 int i;
182 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) 205 if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
183 continue; 206 continue;
184 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 207 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
185 resource_size_t start, end; 208 resource_size_t start, end;
186 209
187 start = pci_resource_start(dev, i); 210 start = pci_resource_start(dev, i);
188 if (start == 0) 211 if (start == 0)
189 break; 212 break;
190 end = pci_resource_end(dev, i); 213 end = pci_resource_end(dev, i);
191 if (screen_info.lfb_base >= start && 214 if (screen_info.lfb_base >= start &&
192 screen_info.lfb_base < end) { 215 screen_info.lfb_base < end) {
193 found_bar = 1; 216 found_bar = 1;
217 }
194 } 218 }
195 } 219 }
196 } 220 if (!found_bar)
197 if (!found_bar) 221 screen_info.lfb_base = 0;
198 screen_info.lfb_base = 0;
199#endif 222#endif
223 }
200 } 224 }
201 if (screen_info.lfb_base) { 225 if (screen_info.lfb_base) {
202 if (screen_info.lfb_linelength == 0) 226 screen_info.lfb_linelength = choose_value(info->stride,
203 screen_info.lfb_linelength = info->stride; 227 screen_info.lfb_linelength, OVERRIDE_STRIDE,
204 if (screen_info.lfb_width == 0) 228 info->flags);
205 screen_info.lfb_width = info->width; 229 screen_info.lfb_width = choose_value(info->width,
206 if (screen_info.lfb_height == 0) 230 screen_info.lfb_width, OVERRIDE_WIDTH,
207 screen_info.lfb_height = info->height; 231 info->flags);
232 screen_info.lfb_height = choose_value(info->height,
233 screen_info.lfb_height, OVERRIDE_HEIGHT,
234 info->flags);
208 if (screen_info.orig_video_isVGA == 0) 235 if (screen_info.orig_video_isVGA == 0)
209 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; 236 screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
210 } else { 237 } else {
@@ -214,6 +241,13 @@ static int set_system(const struct dmi_system_id *id)
214 screen_info.orig_video_isVGA = 0; 241 screen_info.orig_video_isVGA = 0;
215 return 0; 242 return 0;
216 } 243 }
244
245 printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p "
246 "(%dx%d, stride %d)\n", id->ident,
247 (void *)screen_info.lfb_base, screen_info.lfb_width,
248 screen_info.lfb_height, screen_info.lfb_linelength);
249
250
217 return 1; 251 return 1;
218} 252}
219 253