Commit 228abe73ad67665d71eacd6a8a347dd76b0115ae

Authored by Linus Torvalds

Merge branch 'x86-fb-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fb changes from Ingo Molnar:
 "This tree includes preparatory patches for SimpleDRM driver support,
  by David Herrmann.  They clean up x86 framebuffer support by creating
  simplefb devices wherever possible.  More background can be found at

     http://lwn.net/Articles/558104/"

* 'x86-fb-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  fbdev: fbcon: select VT_HW_CONSOLE_BINDING
  fbdev: efifb: bind to efi-framebuffer
  fbdev: vesafb: bind to platform-framebuffer device
  fbdev: simplefb: add common x86 RGB formats
  x86: sysfb: move EFI quirks from efifb to sysfb
  x86: provide platform-devices for boot-framebuffers
  fbdev: simplefb: mark as fw and allocate apertures
  fbdev: simplefb: add init through platform_data

Showing 12 changed files Side-by-side Diff

... ... @@ -2270,6 +2270,32 @@
2270 2270  
2271 2271 source "drivers/rapidio/Kconfig"
2272 2272  
  2273 +config X86_SYSFB
  2274 + bool "Mark VGA/VBE/EFI FB as generic system framebuffer"
  2275 + help
  2276 + Firmwares often provide initial graphics framebuffers so the BIOS,
  2277 + bootloader or kernel can show basic video-output during boot for
  2278 + user-guidance and debugging. Historically, x86 used the VESA BIOS
  2279 + Extensions and EFI-framebuffers for this, which are mostly limited
  2280 + to x86.
  2281 + This option, if enabled, marks VGA/VBE/EFI framebuffers as generic
  2282 + framebuffers so the new generic system-framebuffer drivers can be
  2283 + used on x86. If the framebuffer is not compatible with the generic
  2284 + modes, it is adverticed as fallback platform framebuffer so legacy
  2285 + drivers like efifb, vesafb and uvesafb can pick it up.
  2286 + If this option is not selected, all system framebuffers are always
  2287 + marked as fallback platform framebuffers as usual.
  2288 +
  2289 + Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will
  2290 + not be able to pick up generic system framebuffers if this option
  2291 + is selected. You are highly encouraged to enable simplefb as
  2292 + replacement if you select this option. simplefb can correctly deal
  2293 + with generic system framebuffers. But you should still keep vesafb
  2294 + and others enabled as fallback if a system framebuffer is
  2295 + incompatible with simplefb.
  2296 +
  2297 + If unsure, say Y.
  2298 +
2273 2299 endmenu
2274 2300  
2275 2301  
arch/x86/include/asm/sysfb.h
  1 +#ifndef _ARCH_X86_KERNEL_SYSFB_H
  2 +#define _ARCH_X86_KERNEL_SYSFB_H
  3 +
  4 +/*
  5 + * Generic System Framebuffers on x86
  6 + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify it
  9 + * under the terms of the GNU General Public License as published by the Free
  10 + * Software Foundation; either version 2 of the License, or (at your option)
  11 + * any later version.
  12 + */
  13 +
  14 +#include <linux/kernel.h>
  15 +#include <linux/platform_data/simplefb.h>
  16 +#include <linux/screen_info.h>
  17 +
  18 +enum {
  19 + M_I17, /* 17-Inch iMac */
  20 + M_I20, /* 20-Inch iMac */
  21 + M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
  22 + M_I24, /* 24-Inch iMac */
  23 + M_I24_8_1, /* 24-Inch iMac, 8,1th gen */
  24 + M_I24_10_1, /* 24-Inch iMac, 10,1th gen */
  25 + M_I27_11_1, /* 27-Inch iMac, 11,1th gen */
  26 + M_MINI, /* Mac Mini */
  27 + M_MINI_3_1, /* Mac Mini, 3,1th gen */
  28 + M_MINI_4_1, /* Mac Mini, 4,1th gen */
  29 + M_MB, /* MacBook */
  30 + M_MB_2, /* MacBook, 2nd rev. */
  31 + M_MB_3, /* MacBook, 3rd rev. */
  32 + M_MB_5_1, /* MacBook, 5th rev. */
  33 + M_MB_6_1, /* MacBook, 6th rev. */
  34 + M_MB_7_1, /* MacBook, 7th rev. */
  35 + M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
  36 + M_MBA, /* MacBook Air */
  37 + M_MBA_3, /* Macbook Air, 3rd rev */
  38 + M_MBP, /* MacBook Pro */
  39 + M_MBP_2, /* MacBook Pro 2nd gen */
  40 + M_MBP_2_2, /* MacBook Pro 2,2nd gen */
  41 + M_MBP_SR, /* MacBook Pro (Santa Rosa) */
  42 + M_MBP_4, /* MacBook Pro, 4th gen */
  43 + M_MBP_5_1, /* MacBook Pro, 5,1th gen */
  44 + M_MBP_5_2, /* MacBook Pro, 5,2th gen */
  45 + M_MBP_5_3, /* MacBook Pro, 5,3rd gen */
  46 + M_MBP_6_1, /* MacBook Pro, 6,1th gen */
  47 + M_MBP_6_2, /* MacBook Pro, 6,2th gen */
  48 + M_MBP_7_1, /* MacBook Pro, 7,1th gen */
  49 + M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
  50 + M_UNKNOWN /* placeholder */
  51 +};
  52 +
  53 +struct efifb_dmi_info {
  54 + char *optname;
  55 + unsigned long base;
  56 + int stride;
  57 + int width;
  58 + int height;
  59 + int flags;
  60 +};
  61 +
  62 +#ifdef CONFIG_EFI
  63 +
  64 +extern struct efifb_dmi_info efifb_dmi_list[];
  65 +void sysfb_apply_efi_quirks(void);
  66 +
  67 +#else /* CONFIG_EFI */
  68 +
  69 +static inline void sysfb_apply_efi_quirks(void)
  70 +{
  71 +}
  72 +
  73 +#endif /* CONFIG_EFI */
  74 +
  75 +#ifdef CONFIG_X86_SYSFB
  76 +
  77 +bool parse_mode(const struct screen_info *si,
  78 + struct simplefb_platform_data *mode);
  79 +int create_simplefb(const struct screen_info *si,
  80 + const struct simplefb_platform_data *mode);
  81 +
  82 +#else /* CONFIG_X86_SYSFB */
  83 +
  84 +static inline bool parse_mode(const struct screen_info *si,
  85 + struct simplefb_platform_data *mode)
  86 +{
  87 + return false;
  88 +}
  89 +
  90 +static inline int create_simplefb(const struct screen_info *si,
  91 + const struct simplefb_platform_data *mode)
  92 +{
  93 + return -EINVAL;
  94 +}
  95 +
  96 +#endif /* CONFIG_X86_SYSFB */
  97 +
  98 +#endif /* _ARCH_X86_KERNEL_SYSFB_H */
arch/x86/kernel/Makefile
... ... @@ -103,6 +103,9 @@
103 103 obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
104 104 obj-$(CONFIG_OF) += devicetree.o
105 105 obj-$(CONFIG_UPROBES) += uprobes.o
  106 +obj-y += sysfb.o
  107 +obj-$(CONFIG_X86_SYSFB) += sysfb_simplefb.o
  108 +obj-$(CONFIG_EFI) += sysfb_efi.o
106 109  
107 110 obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
108 111 obj-$(CONFIG_TRACING) += tracepoint.o
arch/x86/kernel/sysfb.c
  1 +/*
  2 + * Generic System Framebuffers on x86
  3 + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of the GNU General Public License as published by the Free
  7 + * Software Foundation; either version 2 of the License, or (at your option)
  8 + * any later version.
  9 + */
  10 +
  11 +/*
  12 + * Simple-Framebuffer support for x86 systems
  13 + * Create a platform-device for any available boot framebuffer. The
  14 + * simple-framebuffer platform device is already available on DT systems, so
  15 + * this module parses the global "screen_info" object and creates a suitable
  16 + * platform device compatible with the "simple-framebuffer" DT object. If
  17 + * the framebuffer is incompatible, we instead create a legacy
  18 + * "vesa-framebuffer", "efi-framebuffer" or "platform-framebuffer" device and
  19 + * pass the screen_info as platform_data. This allows legacy drivers
  20 + * to pick these devices up without messing with simple-framebuffer drivers.
  21 + * The global "screen_info" is still valid at all times.
  22 + *
  23 + * If CONFIG_X86_SYSFB is not selected, we never register "simple-framebuffer"
  24 + * platform devices, but only use legacy framebuffer devices for
  25 + * backwards compatibility.
  26 + *
  27 + * TODO: We set the dev_id field of all platform-devices to 0. This allows
  28 + * other x86 OF/DT parsers to create such devices, too. However, they must
  29 + * start at offset 1 for this to work.
  30 + */
  31 +
  32 +#include <linux/err.h>
  33 +#include <linux/init.h>
  34 +#include <linux/kernel.h>
  35 +#include <linux/mm.h>
  36 +#include <linux/platform_data/simplefb.h>
  37 +#include <linux/platform_device.h>
  38 +#include <linux/screen_info.h>
  39 +#include <asm/sysfb.h>
  40 +
  41 +static __init int sysfb_init(void)
  42 +{
  43 + struct screen_info *si = &screen_info;
  44 + struct simplefb_platform_data mode;
  45 + struct platform_device *pd;
  46 + const char *name;
  47 + bool compatible;
  48 + int ret;
  49 +
  50 + sysfb_apply_efi_quirks();
  51 +
  52 + /* try to create a simple-framebuffer device */
  53 + compatible = parse_mode(si, &mode);
  54 + if (compatible) {
  55 + ret = create_simplefb(si, &mode);
  56 + if (!ret)
  57 + return 0;
  58 + }
  59 +
  60 + /* if the FB is incompatible, create a legacy framebuffer device */
  61 + if (si->orig_video_isVGA == VIDEO_TYPE_EFI)
  62 + name = "efi-framebuffer";
  63 + else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
  64 + name = "vesa-framebuffer";
  65 + else
  66 + name = "platform-framebuffer";
  67 +
  68 + pd = platform_device_register_resndata(NULL, name, 0,
  69 + NULL, 0, si, sizeof(*si));
  70 + return IS_ERR(pd) ? PTR_ERR(pd) : 0;
  71 +}
  72 +
  73 +/* must execute after PCI subsystem for EFI quirks */
  74 +device_initcall(sysfb_init);
arch/x86/kernel/sysfb_efi.c
  1 +/*
  2 + * Generic System Framebuffers on x86
  3 + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
  4 + *
  5 + * EFI Quirks Copyright (c) 2006 Edgar Hucek <gimli@dark-green.com>
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify it
  8 + * under the terms of the GNU General Public License as published by the Free
  9 + * Software Foundation; either version 2 of the License, or (at your option)
  10 + * any later version.
  11 + */
  12 +
  13 +/*
  14 + * EFI Quirks
  15 + * Several EFI systems do not correctly advertise their boot framebuffers.
  16 + * Hence, we use this static table of known broken machines and fix up the
  17 + * information so framebuffer drivers can load corectly.
  18 + */
  19 +
  20 +#include <linux/dmi.h>
  21 +#include <linux/err.h>
  22 +#include <linux/init.h>
  23 +#include <linux/kernel.h>
  24 +#include <linux/mm.h>
  25 +#include <linux/pci.h>
  26 +#include <linux/screen_info.h>
  27 +#include <video/vga.h>
  28 +#include <asm/sysfb.h>
  29 +
  30 +enum {
  31 + OVERRIDE_NONE = 0x0,
  32 + OVERRIDE_BASE = 0x1,
  33 + OVERRIDE_STRIDE = 0x2,
  34 + OVERRIDE_HEIGHT = 0x4,
  35 + OVERRIDE_WIDTH = 0x8,
  36 +};
  37 +
  38 +struct efifb_dmi_info efifb_dmi_list[] = {
  39 + [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
  40 + [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
  41 + [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
  42 + [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
  43 + [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
  44 + [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
  45 + [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
  46 + [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
  47 + [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
  48 + [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
  49 + [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
  50 + [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
  51 + [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
  52 + [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
  53 + [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
  54 + /* 11" Macbook Air 3,1 passes the wrong stride */
  55 + [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
  56 + [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
  57 + [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
  58 + [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
  59 + [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
  60 + [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
  61 + [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
  62 + [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
  63 + [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
  64 + [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
  65 + [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
  66 + [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
  67 + [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
  68 + [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
  69 +};
  70 +
  71 +#define choose_value(dmivalue, fwvalue, field, flags) ({ \
  72 + typeof(fwvalue) _ret_ = fwvalue; \
  73 + if ((flags) & (field)) \
  74 + _ret_ = dmivalue; \
  75 + else if ((fwvalue) == 0) \
  76 + _ret_ = dmivalue; \
  77 + _ret_; \
  78 + })
  79 +
  80 +static int __init efifb_set_system(const struct dmi_system_id *id)
  81 +{
  82 + struct efifb_dmi_info *info = id->driver_data;
  83 +
  84 + if (info->base == 0 && info->height == 0 && info->width == 0 &&
  85 + info->stride == 0)
  86 + return 0;
  87 +
  88 + /* Trust the bootloader over the DMI tables */
  89 + if (screen_info.lfb_base == 0) {
  90 +#if defined(CONFIG_PCI)
  91 + struct pci_dev *dev = NULL;
  92 + int found_bar = 0;
  93 +#endif
  94 + if (info->base) {
  95 + screen_info.lfb_base = choose_value(info->base,
  96 + screen_info.lfb_base, OVERRIDE_BASE,
  97 + info->flags);
  98 +
  99 +#if defined(CONFIG_PCI)
  100 + /* make sure that the address in the table is actually
  101 + * on a VGA device's PCI BAR */
  102 +
  103 + for_each_pci_dev(dev) {
  104 + int i;
  105 + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
  106 + continue;
  107 + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
  108 + resource_size_t start, end;
  109 +
  110 + start = pci_resource_start(dev, i);
  111 + if (start == 0)
  112 + break;
  113 + end = pci_resource_end(dev, i);
  114 + if (screen_info.lfb_base >= start &&
  115 + screen_info.lfb_base < end) {
  116 + found_bar = 1;
  117 + }
  118 + }
  119 + }
  120 + if (!found_bar)
  121 + screen_info.lfb_base = 0;
  122 +#endif
  123 + }
  124 + }
  125 + if (screen_info.lfb_base) {
  126 + screen_info.lfb_linelength = choose_value(info->stride,
  127 + screen_info.lfb_linelength, OVERRIDE_STRIDE,
  128 + info->flags);
  129 + screen_info.lfb_width = choose_value(info->width,
  130 + screen_info.lfb_width, OVERRIDE_WIDTH,
  131 + info->flags);
  132 + screen_info.lfb_height = choose_value(info->height,
  133 + screen_info.lfb_height, OVERRIDE_HEIGHT,
  134 + info->flags);
  135 + if (screen_info.orig_video_isVGA == 0)
  136 + screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
  137 + } else {
  138 + screen_info.lfb_linelength = 0;
  139 + screen_info.lfb_width = 0;
  140 + screen_info.lfb_height = 0;
  141 + screen_info.orig_video_isVGA = 0;
  142 + return 0;
  143 + }
  144 +
  145 + printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x "
  146 + "(%dx%d, stride %d)\n", id->ident,
  147 + screen_info.lfb_base, screen_info.lfb_width,
  148 + screen_info.lfb_height, screen_info.lfb_linelength);
  149 +
  150 + return 1;
  151 +}
  152 +
  153 +#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
  154 + { \
  155 + efifb_set_system, \
  156 + name, \
  157 + { \
  158 + DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
  159 + DMI_MATCH(DMI_PRODUCT_NAME, name) \
  160 + }, \
  161 + &efifb_dmi_list[enumid] \
  162 + }
  163 +
  164 +static const struct dmi_system_id efifb_dmi_system_table[] __initconst = {
  165 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
  166 + /* At least one of these two will be right; maybe both? */
  167 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
  168 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
  169 + /* At least one of these two will be right; maybe both? */
  170 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
  171 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
  172 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
  173 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
  174 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
  175 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
  176 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
  177 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
  178 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
  179 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
  180 + /* At least one of these two will be right; maybe both? */
  181 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
  182 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
  183 + /* At least one of these two will be right; maybe both? */
  184 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
  185 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
  186 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
  187 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
  188 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
  189 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
  190 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
  191 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
  192 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
  193 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
  194 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
  195 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
  196 + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
  197 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
  198 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
  199 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
  200 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
  201 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
  202 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
  203 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
  204 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
  205 + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
  206 + {},
  207 +};
  208 +
  209 +__init void sysfb_apply_efi_quirks(void)
  210 +{
  211 + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
  212 + !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
  213 + dmi_check_system(efifb_dmi_system_table);
  214 +}
arch/x86/kernel/sysfb_simplefb.c
  1 +/*
  2 + * Generic System Framebuffers on x86
  3 + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com>
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of the GNU General Public License as published by the Free
  7 + * Software Foundation; either version 2 of the License, or (at your option)
  8 + * any later version.
  9 + */
  10 +
  11 +/*
  12 + * simple-framebuffer probing
  13 + * Try to convert "screen_info" into a "simple-framebuffer" compatible mode.
  14 + * If the mode is incompatible, we return "false" and let the caller create
  15 + * legacy nodes instead.
  16 + */
  17 +
  18 +#include <linux/err.h>
  19 +#include <linux/init.h>
  20 +#include <linux/kernel.h>
  21 +#include <linux/mm.h>
  22 +#include <linux/platform_data/simplefb.h>
  23 +#include <linux/platform_device.h>
  24 +#include <linux/screen_info.h>
  25 +#include <asm/sysfb.h>
  26 +
  27 +static const char simplefb_resname[] = "BOOTFB";
  28 +static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
  29 +
  30 +/* try parsing x86 screen_info into a simple-framebuffer mode struct */
  31 +__init bool parse_mode(const struct screen_info *si,
  32 + struct simplefb_platform_data *mode)
  33 +{
  34 + const struct simplefb_format *f;
  35 + __u8 type;
  36 + unsigned int i;
  37 +
  38 + type = si->orig_video_isVGA;
  39 + if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI)
  40 + return false;
  41 +
  42 + for (i = 0; i < ARRAY_SIZE(formats); ++i) {
  43 + f = &formats[i];
  44 + if (si->lfb_depth == f->bits_per_pixel &&
  45 + si->red_size == f->red.length &&
  46 + si->red_pos == f->red.offset &&
  47 + si->green_size == f->green.length &&
  48 + si->green_pos == f->green.offset &&
  49 + si->blue_size == f->blue.length &&
  50 + si->blue_pos == f->blue.offset &&
  51 + si->rsvd_size == f->transp.length &&
  52 + si->rsvd_pos == f->transp.offset) {
  53 + mode->format = f->name;
  54 + mode->width = si->lfb_width;
  55 + mode->height = si->lfb_height;
  56 + mode->stride = si->lfb_linelength;
  57 + return true;
  58 + }
  59 + }
  60 +
  61 + return false;
  62 +}
  63 +
  64 +__init int create_simplefb(const struct screen_info *si,
  65 + const struct simplefb_platform_data *mode)
  66 +{
  67 + struct platform_device *pd;
  68 + struct resource res;
  69 + unsigned long len;
  70 +
  71 + /* don't use lfb_size as it may contain the whole VMEM instead of only
  72 + * the part that is occupied by the framebuffer */
  73 + len = mode->height * mode->stride;
  74 + len = PAGE_ALIGN(len);
  75 + if (len > si->lfb_size << 16) {
  76 + printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
  77 + return -EINVAL;
  78 + }
  79 +
  80 + /* setup IORESOURCE_MEM as framebuffer memory */
  81 + memset(&res, 0, sizeof(res));
  82 + res.flags = IORESOURCE_MEM;
  83 + res.name = simplefb_resname;
  84 + res.start = si->lfb_base;
  85 + res.end = si->lfb_base + len - 1;
  86 + if (res.end <= res.start)
  87 + return -EINVAL;
  88 +
  89 + pd = platform_device_register_resndata(NULL, "simple-framebuffer", 0,
  90 + &res, 1, mode, sizeof(*mode));
  91 + if (IS_ERR(pd))
  92 + return PTR_ERR(pd);
  93 +
  94 + return 0;
  95 +}
drivers/video/Kconfig
... ... @@ -2457,7 +2457,7 @@
2457 2457  
2458 2458 config FB_SIMPLE
2459 2459 bool "Simple framebuffer support"
2460   - depends on (FB = y) && OF
  2460 + depends on (FB = y)
2461 2461 select FB_CFB_FILLRECT
2462 2462 select FB_CFB_COPYAREA
2463 2463 select FB_CFB_IMAGEBLIT
... ... @@ -2469,8 +2469,7 @@
2469 2469 pre-allocated frame buffer surface.
2470 2470  
2471 2471 Configuration re: surface address, size, and format must be provided
2472   - through device tree, or potentially plain old platform data in the
2473   - future.
  2472 + through device tree, or plain old platform data.
2474 2473  
2475 2474 source "drivers/video/omap/Kconfig"
2476 2475 source "drivers/video/omap2/Kconfig"
drivers/video/console/Kconfig
... ... @@ -92,7 +92,8 @@
92 92  
93 93 config FRAMEBUFFER_CONSOLE
94 94 tristate "Framebuffer Console support"
95   - depends on FB
  95 + depends on FB && !UML
  96 + select VT_HW_CONSOLE_BINDING
96 97 select CRC32
97 98 select FONT_SUPPORT
98 99 help
drivers/video/efifb.c
... ... @@ -15,6 +15,7 @@
15 15 #include <linux/dmi.h>
16 16 #include <linux/pci.h>
17 17 #include <video/vga.h>
  18 +#include <asm/sysfb.h>
18 19  
19 20 static bool request_mem_succeeded = false;
20 21  
... ... @@ -38,223 +39,6 @@
38 39 .visual = FB_VISUAL_TRUECOLOR,
39 40 };
40 41  
41   -enum {
42   - M_I17, /* 17-Inch iMac */
43   - M_I20, /* 20-Inch iMac */
44   - M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
45   - M_I24, /* 24-Inch iMac */
46   - M_I24_8_1, /* 24-Inch iMac, 8,1th gen */
47   - M_I24_10_1, /* 24-Inch iMac, 10,1th gen */
48   - M_I27_11_1, /* 27-Inch iMac, 11,1th gen */
49   - M_MINI, /* Mac Mini */
50   - M_MINI_3_1, /* Mac Mini, 3,1th gen */
51   - M_MINI_4_1, /* Mac Mini, 4,1th gen */
52   - M_MB, /* MacBook */
53   - M_MB_2, /* MacBook, 2nd rev. */
54   - M_MB_3, /* MacBook, 3rd rev. */
55   - M_MB_5_1, /* MacBook, 5th rev. */
56   - M_MB_6_1, /* MacBook, 6th rev. */
57   - M_MB_7_1, /* MacBook, 7th rev. */
58   - M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
59   - M_MBA, /* MacBook Air */
60   - M_MBA_3, /* Macbook Air, 3rd rev */
61   - M_MBP, /* MacBook Pro */
62   - M_MBP_2, /* MacBook Pro 2nd gen */
63   - M_MBP_2_2, /* MacBook Pro 2,2nd gen */
64   - M_MBP_SR, /* MacBook Pro (Santa Rosa) */
65   - M_MBP_4, /* MacBook Pro, 4th gen */
66   - M_MBP_5_1, /* MacBook Pro, 5,1th gen */
67   - M_MBP_5_2, /* MacBook Pro, 5,2th gen */
68   - M_MBP_5_3, /* MacBook Pro, 5,3rd gen */
69   - M_MBP_6_1, /* MacBook Pro, 6,1th gen */
70   - M_MBP_6_2, /* MacBook Pro, 6,2th gen */
71   - M_MBP_7_1, /* MacBook Pro, 7,1th gen */
72   - M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
73   - M_UNKNOWN /* placeholder */
74   -};
75   -
76   -#define OVERRIDE_NONE 0x0
77   -#define OVERRIDE_BASE 0x1
78   -#define OVERRIDE_STRIDE 0x2
79   -#define OVERRIDE_HEIGHT 0x4
80   -#define OVERRIDE_WIDTH 0x8
81   -
82   -static struct efifb_dmi_info {
83   - char *optname;
84   - unsigned long base;
85   - int stride;
86   - int width;
87   - int height;
88   - int flags;
89   -} dmi_list[] __initdata = {
90   - [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
91   - [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
92   - [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
93   - [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
94   - [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
95   - [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
96   - [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
97   - [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
98   - [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
99   - [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
100   - [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
101   - [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
102   - [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
103   - [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
104   - [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
105   - /* 11" Macbook Air 3,1 passes the wrong stride */
106   - [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
107   - [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
108   - [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
109   - [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
110   - [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
111   - [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
112   - [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
113   - [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
114   - [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
115   - [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
116   - [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
117   - [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
118   - [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
119   - [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
120   -};
121   -
122   -static int set_system(const struct dmi_system_id *id);
123   -
124   -#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
125   - { set_system, name, { \
126   - DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
127   - DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
128   - &dmi_list[enumid] }
129   -
130   -static const struct dmi_system_id dmi_system_table[] __initconst = {
131   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
132   - /* At least one of these two will be right; maybe both? */
133   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
134   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
135   - /* At least one of these two will be right; maybe both? */
136   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
137   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
138   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
139   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
140   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
141   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
142   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
143   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
144   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
145   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
146   - /* At least one of these two will be right; maybe both? */
147   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
148   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
149   - /* At least one of these two will be right; maybe both? */
150   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
151   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
152   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
153   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
154   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
155   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
156   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
157   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
158   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
159   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
160   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
161   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
162   - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
163   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
164   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
165   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
166   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
167   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
168   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
169   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
170   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
171   - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
172   - {},
173   -};
174   -
175   -#define choose_value(dmivalue, fwvalue, field, flags) ({ \
176   - typeof(fwvalue) _ret_ = fwvalue; \
177   - if ((flags) & (field)) \
178   - _ret_ = dmivalue; \
179   - else if ((fwvalue) == 0) \
180   - _ret_ = dmivalue; \
181   - _ret_; \
182   - })
183   -
184   -static int set_system(const struct dmi_system_id *id)
185   -{
186   - struct efifb_dmi_info *info = id->driver_data;
187   -
188   - if (info->base == 0 && info->height == 0 && info->width == 0
189   - && info->stride == 0)
190   - return 0;
191   -
192   - /* Trust the bootloader over the DMI tables */
193   - if (screen_info.lfb_base == 0) {
194   -#if defined(CONFIG_PCI)
195   - struct pci_dev *dev = NULL;
196   - int found_bar = 0;
197   -#endif
198   - if (info->base) {
199   - screen_info.lfb_base = choose_value(info->base,
200   - screen_info.lfb_base, OVERRIDE_BASE,
201   - info->flags);
202   -
203   -#if defined(CONFIG_PCI)
204   - /* make sure that the address in the table is actually
205   - * on a VGA device's PCI BAR */
206   -
207   - for_each_pci_dev(dev) {
208   - int i;
209   - if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
210   - continue;
211   - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
212   - resource_size_t start, end;
213   -
214   - start = pci_resource_start(dev, i);
215   - if (start == 0)
216   - break;
217   - end = pci_resource_end(dev, i);
218   - if (screen_info.lfb_base >= start &&
219   - screen_info.lfb_base < end) {
220   - found_bar = 1;
221   - }
222   - }
223   - }
224   - if (!found_bar)
225   - screen_info.lfb_base = 0;
226   -#endif
227   - }
228   - }
229   - if (screen_info.lfb_base) {
230   - screen_info.lfb_linelength = choose_value(info->stride,
231   - screen_info.lfb_linelength, OVERRIDE_STRIDE,
232   - info->flags);
233   - screen_info.lfb_width = choose_value(info->width,
234   - screen_info.lfb_width, OVERRIDE_WIDTH,
235   - info->flags);
236   - screen_info.lfb_height = choose_value(info->height,
237   - screen_info.lfb_height, OVERRIDE_HEIGHT,
238   - info->flags);
239   - if (screen_info.orig_video_isVGA == 0)
240   - screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
241   - } else {
242   - screen_info.lfb_linelength = 0;
243   - screen_info.lfb_width = 0;
244   - screen_info.lfb_height = 0;
245   - screen_info.orig_video_isVGA = 0;
246   - return 0;
247   - }
248   -
249   - printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x "
250   - "(%dx%d, stride %d)\n", id->ident,
251   - screen_info.lfb_base, screen_info.lfb_width,
252   - screen_info.lfb_height, screen_info.lfb_linelength);
253   -
254   -
255   - return 1;
256   -}
257   -
258 42 static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
259 43 unsigned blue, unsigned transp,
260 44 struct fb_info *info)
... ... @@ -312,7 +96,7 @@
312 96 default_vga = pdev;
313 97 }
314 98  
315   -static int __init efifb_setup(char *options)
  99 +static int efifb_setup(char *options)
316 100 {
317 101 char *this_opt;
318 102 int i;
... ... @@ -323,12 +107,12 @@
323 107 if (!*this_opt) continue;
324 108  
325 109 for (i = 0; i < M_UNKNOWN; i++) {
326   - if (!strcmp(this_opt, dmi_list[i].optname) &&
327   - dmi_list[i].base != 0) {
328   - screen_info.lfb_base = dmi_list[i].base;
329   - screen_info.lfb_linelength = dmi_list[i].stride;
330   - screen_info.lfb_width = dmi_list[i].width;
331   - screen_info.lfb_height = dmi_list[i].height;
  110 + if (!strcmp(this_opt, efifb_dmi_list[i].optname) &&
  111 + efifb_dmi_list[i].base != 0) {
  112 + screen_info.lfb_base = efifb_dmi_list[i].base;
  113 + screen_info.lfb_linelength = efifb_dmi_list[i].stride;
  114 + screen_info.lfb_width = efifb_dmi_list[i].width;
  115 + screen_info.lfb_height = efifb_dmi_list[i].height;
332 116 }
333 117 }
334 118 if (!strncmp(this_opt, "base:", 5))
335 119  
336 120  
... ... @@ -369,14 +153,29 @@
369 153 return 0;
370 154 }
371 155  
372   -static int __init efifb_probe(struct platform_device *dev)
  156 +static int efifb_probe(struct platform_device *dev)
373 157 {
374 158 struct fb_info *info;
375 159 int err;
376 160 unsigned int size_vmode;
377 161 unsigned int size_remap;
378 162 unsigned int size_total;
  163 + char *option = NULL;
379 164  
  165 + if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
  166 + return -ENODEV;
  167 +
  168 + if (fb_get_options("efifb", &option))
  169 + return -ENODEV;
  170 + efifb_setup(option);
  171 +
  172 + /* We don't get linelength from UGA Draw Protocol, only from
  173 + * EFI Graphics Protocol. So if it's not in DMI, and it's not
  174 + * passed in from the user, we really can't use the framebuffer.
  175 + */
  176 + if (!screen_info.lfb_linelength)
  177 + return -ENODEV;
  178 +
380 179 if (!screen_info.lfb_depth)
381 180 screen_info.lfb_depth = 32;
382 181 if (!screen_info.pages)
383 182  
384 183  
... ... @@ -539,56 +338,13 @@
539 338 }
540 339  
541 340 static struct platform_driver efifb_driver = {
542   - .driver = {
543   - .name = "efifb",
  341 + .driver = {
  342 + .name = "efi-framebuffer",
  343 + .owner = THIS_MODULE,
544 344 },
  345 + .probe = efifb_probe,
545 346 };
546 347  
547   -static struct platform_device efifb_device = {
548   - .name = "efifb",
549   -};
550   -
551   -static int __init efifb_init(void)
552   -{
553   - int ret;
554   - char *option = NULL;
555   -
556   - if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
557   - !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
558   - dmi_check_system(dmi_system_table);
559   -
560   - if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
561   - return -ENODEV;
562   -
563   - if (fb_get_options("efifb", &option))
564   - return -ENODEV;
565   - efifb_setup(option);
566   -
567   - /* We don't get linelength from UGA Draw Protocol, only from
568   - * EFI Graphics Protocol. So if it's not in DMI, and it's not
569   - * passed in from the user, we really can't use the framebuffer.
570   - */
571   - if (!screen_info.lfb_linelength)
572   - return -ENODEV;
573   -
574   - ret = platform_device_register(&efifb_device);
575   - if (ret)
576   - return ret;
577   -
578   - /*
579   - * This is not just an optimization. We will interfere
580   - * with a real driver if we get reprobed, so don't allow
581   - * it.
582   - */
583   - ret = platform_driver_probe(&efifb_driver, efifb_probe);
584   - if (ret) {
585   - platform_device_unregister(&efifb_device);
586   - return ret;
587   - }
588   -
589   - return ret;
590   -}
591   -module_init(efifb_init);
592   -
  348 +module_platform_driver(efifb_driver);
593 349 MODULE_LICENSE("GPL");
drivers/video/simplefb.c
... ... @@ -24,6 +24,7 @@
24 24 #include <linux/fb.h>
25 25 #include <linux/io.h>
26 26 #include <linux/module.h>
  27 +#include <linux/platform_data/simplefb.h>
27 28 #include <linux/platform_device.h>
28 29  
29 30 static struct fb_fix_screeninfo simplefb_fix = {
30 31  
... ... @@ -73,19 +74,8 @@
73 74 .fb_imageblit = cfb_imageblit,
74 75 };
75 76  
76   -struct simplefb_format {
77   - const char *name;
78   - u32 bits_per_pixel;
79   - struct fb_bitfield red;
80   - struct fb_bitfield green;
81   - struct fb_bitfield blue;
82   - struct fb_bitfield transp;
83   -};
  77 +static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS;
84 78  
85   -static struct simplefb_format simplefb_formats[] = {
86   - { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} },
87   -};
88   -
89 79 struct simplefb_params {
90 80 u32 width;
91 81 u32 height;
... ... @@ -139,6 +129,33 @@
139 129 return 0;
140 130 }
141 131  
  132 +static int simplefb_parse_pd(struct platform_device *pdev,
  133 + struct simplefb_params *params)
  134 +{
  135 + struct simplefb_platform_data *pd = pdev->dev.platform_data;
  136 + int i;
  137 +
  138 + params->width = pd->width;
  139 + params->height = pd->height;
  140 + params->stride = pd->stride;
  141 +
  142 + params->format = NULL;
  143 + for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
  144 + if (strcmp(pd->format, simplefb_formats[i].name))
  145 + continue;
  146 +
  147 + params->format = &simplefb_formats[i];
  148 + break;
  149 + }
  150 +
  151 + if (!params->format) {
  152 + dev_err(&pdev->dev, "Invalid format value\n");
  153 + return -EINVAL;
  154 + }
  155 +
  156 + return 0;
  157 +}
  158 +
142 159 static int simplefb_probe(struct platform_device *pdev)
143 160 {
144 161 int ret;
... ... @@ -149,7 +166,12 @@
149 166 if (fb_get_options("simplefb", NULL))
150 167 return -ENODEV;
151 168  
152   - ret = simplefb_parse_dt(pdev, &params);
  169 + ret = -ENODEV;
  170 + if (pdev->dev.platform_data)
  171 + ret = simplefb_parse_pd(pdev, &params);
  172 + else if (pdev->dev.of_node)
  173 + ret = simplefb_parse_dt(pdev, &params);
  174 +
153 175 if (ret)
154 176 return ret;
155 177  
156 178  
... ... @@ -180,8 +202,16 @@
180 202 info->var.blue = params.format->blue;
181 203 info->var.transp = params.format->transp;
182 204  
  205 + info->apertures = alloc_apertures(1);
  206 + if (!info->apertures) {
  207 + framebuffer_release(info);
  208 + return -ENOMEM;
  209 + }
  210 + info->apertures->ranges[0].base = info->fix.smem_start;
  211 + info->apertures->ranges[0].size = info->fix.smem_len;
  212 +
183 213 info->fbops = &simplefb_ops;
184   - info->flags = FBINFO_DEFAULT;
  214 + info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE;
185 215 info->screen_base = devm_ioremap(&pdev->dev, info->fix.smem_start,
186 216 info->fix.smem_len);
187 217 if (!info->screen_base) {
drivers/video/vesafb.c
... ... @@ -29,7 +29,7 @@
29 29  
30 30 /* --------------------------------------------------------------------- */
31 31  
32   -static struct fb_var_screeninfo vesafb_defined __initdata = {
  32 +static struct fb_var_screeninfo vesafb_defined = {
33 33 .activate = FB_ACTIVATE_NOW,
34 34 .height = -1,
35 35 .width = -1,
... ... @@ -40,7 +40,7 @@
40 40 .vmode = FB_VMODE_NONINTERLACED,
41 41 };
42 42  
43   -static struct fb_fix_screeninfo vesafb_fix __initdata = {
  43 +static struct fb_fix_screeninfo vesafb_fix = {
44 44 .id = "VESA VGA",
45 45 .type = FB_TYPE_PACKED_PIXELS,
46 46 .accel = FB_ACCEL_NONE,
... ... @@ -48,8 +48,8 @@
48 48  
49 49 static int inverse __read_mostly;
50 50 static int mtrr __read_mostly; /* disable mtrr */
51   -static int vram_remap __initdata; /* Set amount of memory to be used */
52   -static int vram_total __initdata; /* Set total amount of memory */
  51 +static int vram_remap; /* Set amount of memory to be used */
  52 +static int vram_total; /* Set total amount of memory */
53 53 static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */
54 54 static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */
55 55 static void (*pmi_start)(void) __read_mostly;
... ... @@ -192,7 +192,7 @@
192 192 .fb_imageblit = cfb_imageblit,
193 193 };
194 194  
195   -static int __init vesafb_setup(char *options)
  195 +static int vesafb_setup(char *options)
196 196 {
197 197 char *this_opt;
198 198  
199 199  
200 200  
... ... @@ -226,14 +226,19 @@
226 226 return 0;
227 227 }
228 228  
229   -static int __init vesafb_probe(struct platform_device *dev)
  229 +static int vesafb_probe(struct platform_device *dev)
230 230 {
231 231 struct fb_info *info;
232 232 int i, err;
233 233 unsigned int size_vmode;
234 234 unsigned int size_remap;
235 235 unsigned int size_total;
  236 + char *option = NULL;
236 237  
  238 + /* ignore error return of fb_get_options */
  239 + fb_get_options("vesafb", &option);
  240 + vesafb_setup(option);
  241 +
237 242 if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
238 243 return -ENODEV;
239 244  
240 245  
241 246  
... ... @@ -496,41 +501,13 @@
496 501 }
497 502  
498 503 static struct platform_driver vesafb_driver = {
499   - .driver = {
500   - .name = "vesafb",
  504 + .driver = {
  505 + .name = "vesa-framebuffer",
  506 + .owner = THIS_MODULE,
501 507 },
  508 + .probe = vesafb_probe,
502 509 };
503 510  
504   -static struct platform_device *vesafb_device;
505   -
506   -static int __init vesafb_init(void)
507   -{
508   - int ret;
509   - char *option = NULL;
510   -
511   - /* ignore error return of fb_get_options */
512   - fb_get_options("vesafb", &option);
513   - vesafb_setup(option);
514   -
515   - vesafb_device = platform_device_alloc("vesafb", 0);
516   - if (!vesafb_device)
517   - return -ENOMEM;
518   -
519   - ret = platform_device_add(vesafb_device);
520   - if (!ret) {
521   - ret = platform_driver_probe(&vesafb_driver, vesafb_probe);
522   - if (ret)
523   - platform_device_del(vesafb_device);
524   - }
525   -
526   - if (ret) {
527   - platform_device_put(vesafb_device);
528   - vesafb_device = NULL;
529   - }
530   -
531   - return ret;
532   -}
533   -module_init(vesafb_init);
534   -
  511 +module_platform_driver(vesafb_driver);
535 512 MODULE_LICENSE("GPL");
include/linux/platform_data/simplefb.h
  1 +/*
  2 + * simplefb.h - Simple Framebuffer Device
  3 + *
  4 + * Copyright (C) 2013 David Herrmann <dh.herrmann@gmail.com>
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + */
  11 +
  12 +#ifndef __PLATFORM_DATA_SIMPLEFB_H__
  13 +#define __PLATFORM_DATA_SIMPLEFB_H__
  14 +
  15 +#include <drm/drm_fourcc.h>
  16 +#include <linux/fb.h>
  17 +#include <linux/kernel.h>
  18 +
  19 +/* format array, use it to initialize a "struct simplefb_format" array */
  20 +#define SIMPLEFB_FORMATS \
  21 +{ \
  22 + { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 }, \
  23 + { "x1r5g5b5", 16, {10, 5}, {5, 5}, {0, 5}, {0, 0}, DRM_FORMAT_XRGB1555 }, \
  24 + { "a1r5g5b5", 16, {10, 5}, {5, 5}, {0, 5}, {15, 1}, DRM_FORMAT_ARGB1555 }, \
  25 + { "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 }, \
  26 + { "x8r8g8b8", 32, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_XRGB8888 }, \
  27 + { "a8r8g8b8", 32, {16, 8}, {8, 8}, {0, 8}, {24, 8}, DRM_FORMAT_ARGB8888 }, \
  28 + { "x2r10g10b10", 32, {20, 10}, {10, 10}, {0, 10}, {0, 0}, DRM_FORMAT_XRGB2101010 }, \
  29 + { "a2r10g10b10", 32, {20, 10}, {10, 10}, {0, 10}, {30, 2}, DRM_FORMAT_ARGB2101010 }, \
  30 +}
  31 +
  32 +/*
  33 + * Data-Format for Simple-Framebuffers
  34 + * @name: unique 0-terminated name that can be used to identify the mode
  35 + * @red,green,blue: Offsets and sizes of the single RGB parts
  36 + * @transp: Offset and size of the alpha bits. length=0 means no alpha
  37 + * @fourcc: 32bit DRM four-CC code (see drm_fourcc.h)
  38 + */
  39 +struct simplefb_format {
  40 + const char *name;
  41 + u32 bits_per_pixel;
  42 + struct fb_bitfield red;
  43 + struct fb_bitfield green;
  44 + struct fb_bitfield blue;
  45 + struct fb_bitfield transp;
  46 + u32 fourcc;
  47 +};
  48 +
  49 +/*
  50 + * Simple-Framebuffer description
  51 + * If the arch-boot code creates simple-framebuffers without DT support, it
  52 + * can pass the width, height, stride and format via this platform-data object.
  53 + * The framebuffer location must be given as IORESOURCE_MEM resource.
  54 + * @format must be a format as described in "struct simplefb_format" above.
  55 + */
  56 +struct simplefb_platform_data {
  57 + u32 width;
  58 + u32 height;
  59 + u32 stride;
  60 + const char *format;
  61 +};
  62 +
  63 +#endif /* __PLATFORM_DATA_SIMPLEFB_H__ */