~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/video/efifb.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

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