diff options
| -rw-r--r-- | drivers/video/efifb.c | 149 |
1 files changed, 88 insertions, 61 deletions
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index a9645b86a623..2359b6403a16 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
| @@ -68,41 +68,48 @@ enum { | |||
| 68 | M_UNKNOWN /* placeholder */ | 68 | M_UNKNOWN /* placeholder */ |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | #define OVERRIDE_NONE 0x0 | ||
| 72 | #define OVERRIDE_BASE 0x1 | ||
| 73 | #define OVERRIDE_STRIDE 0x2 | ||
| 74 | #define OVERRIDE_HEIGHT 0x4 | ||
| 75 | #define OVERRIDE_WIDTH 0x8 | ||
| 76 | |||
| 71 | static struct efifb_dmi_info { | 77 | static struct efifb_dmi_info { |
| 72 | char *optname; | 78 | char *optname; |
| 73 | unsigned long base; | 79 | unsigned long base; |
| 74 | int stride; | 80 | int stride; |
| 75 | int width; | 81 | int width; |
| 76 | int height; | 82 | int height; |
| 83 | int flags; | ||
| 77 | } dmi_list[] __initdata = { | 84 | } dmi_list[] __initdata = { |
| 78 | [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, | 85 | [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, |
| 79 | [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ | 86 | [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */ |
| 80 | [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, | 87 | [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, |
| 81 | [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ | 88 | [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */ |
| 82 | [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, | 89 | [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, |
| 83 | [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, | 90 | [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE }, |
| 84 | [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, | 91 | [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE }, |
| 85 | [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, | 92 | [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE }, |
| 86 | [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, | 93 | [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE }, |
| 87 | [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, | 94 | [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, |
| 88 | [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, | 95 | [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, |
| 89 | [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, | 96 | [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, |
| 90 | [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, | 97 | [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, |
| 91 | [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, | 98 | [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, |
| 92 | [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, | 99 | [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, |
| 93 | [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, | 100 | [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, |
| 94 | [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ | 101 | [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */ |
| 95 | [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, | 102 | [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, |
| 96 | [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, | 103 | [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, |
| 97 | [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, | 104 | [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, |
| 98 | [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, | 105 | [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, |
| 99 | [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, | 106 | [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, |
| 100 | [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, | 107 | [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, |
| 101 | [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, | 108 | [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, |
| 102 | [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, | 109 | [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE }, |
| 103 | [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, | 110 | [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, |
| 104 | [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900 }, | 111 | [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, |
| 105 | [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } | 112 | [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } |
| 106 | }; | 113 | }; |
| 107 | 114 | ||
| 108 | static int set_system(const struct dmi_system_id *id); | 115 | static int set_system(const struct dmi_system_id *id); |
| @@ -157,16 +164,22 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { | |||
| 157 | {}, | 164 | {}, |
| 158 | }; | 165 | }; |
| 159 | 166 | ||
| 167 | #define choose_value(dmivalue, fwvalue, field, flags) ({ \ | ||
| 168 | typeof(fwvalue) _ret_ = fwvalue; \ | ||
| 169 | if ((flags) & (field)) \ | ||
| 170 | _ret_ = dmivalue; \ | ||
| 171 | else if ((fwvalue) == 0) \ | ||
| 172 | _ret_ = dmivalue; \ | ||
| 173 | _ret_; \ | ||
| 174 | }) | ||
| 175 | |||
| 160 | static int set_system(const struct dmi_system_id *id) | 176 | static int set_system(const struct dmi_system_id *id) |
| 161 | { | 177 | { |
| 162 | struct efifb_dmi_info *info = id->driver_data; | 178 | struct efifb_dmi_info *info = id->driver_data; |
| 163 | if (info->base == 0) | ||
| 164 | return 0; | ||
| 165 | 179 | ||
| 166 | printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " | 180 | if (info->base == 0 && info->height == 0 && info->width == 0 |
| 167 | "(%dx%d, stride %d)\n", id->ident, | 181 | && info->stride == 0) |
| 168 | (void *)info->base, info->width, info->height, | 182 | return 0; |
| 169 | info->stride); | ||
| 170 | 183 | ||
| 171 | /* Trust the bootloader over the DMI tables */ | 184 | /* Trust the bootloader over the DMI tables */ |
| 172 | if (screen_info.lfb_base == 0) { | 185 | if (screen_info.lfb_base == 0) { |
| @@ -174,40 +187,47 @@ static int set_system(const struct dmi_system_id *id) | |||
| 174 | struct pci_dev *dev = NULL; | 187 | struct pci_dev *dev = NULL; |
| 175 | int found_bar = 0; | 188 | int found_bar = 0; |
| 176 | #endif | 189 | #endif |
| 177 | screen_info.lfb_base = info->base; | 190 | if (info->base) { |
| 191 | screen_info.lfb_base = choose_value(info->base, | ||
| 192 | screen_info.lfb_base, OVERRIDE_BASE, | ||
| 193 | info->flags); | ||
| 178 | 194 | ||
| 179 | #if defined(CONFIG_PCI) | 195 | #if defined(CONFIG_PCI) |
| 180 | /* make sure that the address in the table is actually on a | 196 | /* make sure that the address in the table is actually |
| 181 | * VGA device's PCI BAR */ | 197 | * on a VGA device's PCI BAR */ |
| 182 | 198 | ||
| 183 | for_each_pci_dev(dev) { | 199 | for_each_pci_dev(dev) { |
| 184 | int i; | 200 | int i; |
| 185 | if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) | 201 | if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) |
| 186 | continue; | 202 | continue; |
| 187 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 203 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
| 188 | resource_size_t start, end; | 204 | resource_size_t start, end; |
| 189 | 205 | ||
| 190 | start = pci_resource_start(dev, i); | 206 | start = pci_resource_start(dev, i); |
| 191 | if (start == 0) | 207 | if (start == 0) |
| 192 | break; | 208 | break; |
| 193 | end = pci_resource_end(dev, i); | 209 | end = pci_resource_end(dev, i); |
| 194 | if (screen_info.lfb_base >= start && | 210 | if (screen_info.lfb_base >= start && |
| 195 | screen_info.lfb_base < end) { | 211 | screen_info.lfb_base < end) { |
| 196 | found_bar = 1; | 212 | found_bar = 1; |
| 213 | } | ||
| 197 | } | 214 | } |
| 198 | } | 215 | } |
| 199 | } | 216 | if (!found_bar) |
| 200 | if (!found_bar) | 217 | screen_info.lfb_base = 0; |
| 201 | screen_info.lfb_base = 0; | ||
| 202 | #endif | 218 | #endif |
| 219 | } | ||
| 203 | } | 220 | } |
| 204 | if (screen_info.lfb_base) { | 221 | if (screen_info.lfb_base) { |
| 205 | if (screen_info.lfb_linelength == 0) | 222 | screen_info.lfb_linelength = choose_value(info->stride, |
| 206 | screen_info.lfb_linelength = info->stride; | 223 | screen_info.lfb_linelength, OVERRIDE_STRIDE, |
| 207 | if (screen_info.lfb_width == 0) | 224 | info->flags); |
| 208 | screen_info.lfb_width = info->width; | 225 | screen_info.lfb_width = choose_value(info->width, |
| 209 | if (screen_info.lfb_height == 0) | 226 | screen_info.lfb_width, OVERRIDE_WIDTH, |
| 210 | screen_info.lfb_height = info->height; | 227 | info->flags); |
| 228 | screen_info.lfb_height = choose_value(info->height, | ||
| 229 | screen_info.lfb_height, OVERRIDE_HEIGHT, | ||
| 230 | info->flags); | ||
| 211 | if (screen_info.orig_video_isVGA == 0) | 231 | if (screen_info.orig_video_isVGA == 0) |
| 212 | screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; | 232 | screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; |
| 213 | } else { | 233 | } else { |
| @@ -217,6 +237,13 @@ static int set_system(const struct dmi_system_id *id) | |||
| 217 | screen_info.orig_video_isVGA = 0; | 237 | screen_info.orig_video_isVGA = 0; |
| 218 | return 0; | 238 | return 0; |
| 219 | } | 239 | } |
| 240 | |||
| 241 | printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " | ||
| 242 | "(%dx%d, stride %d)\n", id->ident, | ||
| 243 | (void *)screen_info.lfb_base, screen_info.lfb_width, | ||
| 244 | screen_info.lfb_height, screen_info.lfb_linelength); | ||
| 245 | |||
| 246 | |||
| 220 | return 1; | 247 | return 1; |
| 221 | } | 248 | } |
| 222 | 249 | ||
