2007-11-29 08:21:55 +08:00
|
|
|
/*
|
|
|
|
* Framebuffer driver for EFI/UEFI based system
|
|
|
|
*
|
|
|
|
* (c) 2006 Edgar Hucek <gimli@dark-green.com>
|
|
|
|
* Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/fb.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/screen_info.h>
|
2008-10-16 13:03:43 +08:00
|
|
|
#include <linux/dmi.h>
|
2010-09-23 04:05:04 +08:00
|
|
|
#include <linux/pci.h>
|
2007-11-29 08:21:55 +08:00
|
|
|
#include <video/vga.h>
|
|
|
|
|
2011-05-26 22:13:32 +08:00
|
|
|
static bool request_mem_succeeded = false;
|
|
|
|
|
2012-04-17 04:26:05 +08:00
|
|
|
static struct pci_dev *default_vga;
|
|
|
|
|
2010-08-11 09:02:28 +08:00
|
|
|
static struct fb_var_screeninfo efifb_defined __devinitdata = {
|
2007-11-29 08:21:55 +08:00
|
|
|
.activate = FB_ACTIVATE_NOW,
|
|
|
|
.height = -1,
|
|
|
|
.width = -1,
|
|
|
|
.right_margin = 32,
|
|
|
|
.upper_margin = 16,
|
|
|
|
.lower_margin = 4,
|
|
|
|
.vsync_len = 4,
|
|
|
|
.vmode = FB_VMODE_NONINTERLACED,
|
|
|
|
};
|
|
|
|
|
2010-08-11 09:02:28 +08:00
|
|
|
static struct fb_fix_screeninfo efifb_fix __devinitdata = {
|
2007-11-29 08:21:55 +08:00
|
|
|
.id = "EFI VGA",
|
|
|
|
.type = FB_TYPE_PACKED_PIXELS,
|
|
|
|
.accel = FB_ACCEL_NONE,
|
|
|
|
.visual = FB_VISUAL_TRUECOLOR,
|
|
|
|
};
|
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
enum {
|
|
|
|
M_I17, /* 17-Inch iMac */
|
|
|
|
M_I20, /* 20-Inch iMac */
|
|
|
|
M_I20_SR, /* 20-Inch iMac (Santa Rosa) */
|
|
|
|
M_I24, /* 24-Inch iMac */
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
M_I24_8_1, /* 24-Inch iMac, 8,1th gen */
|
|
|
|
M_I24_10_1, /* 24-Inch iMac, 10,1th gen */
|
|
|
|
M_I27_11_1, /* 27-Inch iMac, 11,1th gen */
|
2008-10-16 13:03:43 +08:00
|
|
|
M_MINI, /* Mac Mini */
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
M_MINI_3_1, /* Mac Mini, 3,1th gen */
|
|
|
|
M_MINI_4_1, /* Mac Mini, 4,1th gen */
|
2008-10-16 13:03:43 +08:00
|
|
|
M_MB, /* MacBook */
|
|
|
|
M_MB_2, /* MacBook, 2nd rev. */
|
|
|
|
M_MB_3, /* MacBook, 3rd rev. */
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
M_MB_5_1, /* MacBook, 5th rev. */
|
|
|
|
M_MB_6_1, /* MacBook, 6th rev. */
|
|
|
|
M_MB_7_1, /* MacBook, 7th rev. */
|
2008-10-16 13:03:43 +08:00
|
|
|
M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */
|
|
|
|
M_MBA, /* MacBook Air */
|
2011-04-07 01:34:59 +08:00
|
|
|
M_MBA_3, /* Macbook Air, 3rd rev */
|
2008-10-16 13:03:43 +08:00
|
|
|
M_MBP, /* MacBook Pro */
|
|
|
|
M_MBP_2, /* MacBook Pro 2nd gen */
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
M_MBP_2_2, /* MacBook Pro 2,2nd gen */
|
2008-10-16 13:03:43 +08:00
|
|
|
M_MBP_SR, /* MacBook Pro (Santa Rosa) */
|
|
|
|
M_MBP_4, /* MacBook Pro, 4th gen */
|
drivers/video/efifb.c: support framebuffer for NVIDIA 9400M in MacBook Pro 5,1
Description of patch:
---------------------
This is a patch for the EFI framebuffer driver to enable the framebuffer
of the NVIDIA 9400M as found in MacBook Pro (MBP) 5,1 and up. The
framebuffer of the NVIDIA graphic cards are located at the following
addresses in memory:
9400M: 0xC0010000
9600M GT: 0xB0030000
The patch delivered right here only provides the memory location of the
framebuffer of the 9400M device. The 9600M GT is not covered. It is
assumed that the 9400M is used when powered up the MBP.
The information which device is currently powered and in use is stored in
the 64 bytes large EFI variable "gpu-power-prefs". More specifically,
byte 0x3B indicates whether 9600M GT (0x00) or 9400M (0x01) is online.
The PCI bus IDs are the following:
9400M: PCI 03:00:00
9600M GT: PCI 02:00:00
The EFI variables can be easily read-out and manipulated with "rEFIt", an
MBP specific bootloader tool. For more information on how handle rEFIt
and EFI variables please consult "http://refit.sourceforge.net" and
"http://ubuntuforums.org/archive/index.php/t-1076879.html".
IMPORTANT NOTE: The information on how to activate the 9400M device given
at "ubuntuforums.org" is not correct, since it states
gpu-power-prefs[0x3B] = 0x00 -> 9400M (PCI 02:00:00)
gpu-power-prefs[0x3B] = 0x01 -> 9600M GT (PCI 03:00:00)
Actually, the assignment of the values and the PCI bus IDs are swapped.
Suggestions:
------------
To cover framebuffers of both 9400M and 9600M GT, I would suggest to
implement a conditional on "gpu-power-prefs". Depending on the value of
byte 0x3B, the according framebuffer is selected. However, this requires
kernel access to the EFI variables.
[akpm@linux-foundation.org: rename optname, per Peter Jones]
Signed-off-by: Thomas Gerlach <t.m.gerlach@freenet.de>
Acked-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-04-24 01:17:50 +08:00
|
|
|
M_MBP_5_1, /* MacBook Pro, 5,1th gen */
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
M_MBP_5_2, /* MacBook Pro, 5,2th gen */
|
|
|
|
M_MBP_5_3, /* MacBook Pro, 5,3rd gen */
|
|
|
|
M_MBP_6_1, /* MacBook Pro, 6,1th gen */
|
|
|
|
M_MBP_6_2, /* MacBook Pro, 6,2th gen */
|
|
|
|
M_MBP_7_1, /* MacBook Pro, 7,1th gen */
|
2011-03-31 08:12:22 +08:00
|
|
|
M_MBP_8_2, /* MacBook Pro, 8,2nd gen */
|
2008-10-16 13:03:43 +08:00
|
|
|
M_UNKNOWN /* placeholder */
|
|
|
|
};
|
|
|
|
|
2011-04-07 01:34:58 +08:00
|
|
|
#define OVERRIDE_NONE 0x0
|
|
|
|
#define OVERRIDE_BASE 0x1
|
|
|
|
#define OVERRIDE_STRIDE 0x2
|
|
|
|
#define OVERRIDE_HEIGHT 0x4
|
|
|
|
#define OVERRIDE_WIDTH 0x8
|
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
static struct efifb_dmi_info {
|
|
|
|
char *optname;
|
|
|
|
unsigned long base;
|
|
|
|
int stride;
|
|
|
|
int width;
|
|
|
|
int height;
|
2011-04-07 01:34:58 +08:00
|
|
|
int flags;
|
2010-08-11 09:02:28 +08:00
|
|
|
} dmi_list[] __initdata = {
|
2011-04-07 01:34:58 +08:00
|
|
|
[M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */
|
|
|
|
[M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE },
|
|
|
|
[M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */
|
|
|
|
[M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
|
|
|
|
[M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE },
|
|
|
|
[M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE },
|
|
|
|
[M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE },
|
|
|
|
[M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE },
|
|
|
|
[M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
|
|
|
|
[M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
|
|
|
|
[M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
|
|
|
|
[M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
|
|
|
|
[M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
|
|
|
|
[M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
|
2011-04-07 01:34:59 +08:00
|
|
|
/* 11" Macbook Air 3,1 passes the wrong stride */
|
|
|
|
[M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE },
|
2011-04-07 01:34:58 +08:00
|
|
|
[M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */
|
|
|
|
[M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
|
|
|
|
[M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
|
|
|
|
[M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE },
|
|
|
|
[M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE },
|
|
|
|
[M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE },
|
|
|
|
[M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE },
|
|
|
|
[M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
|
2008-10-16 13:03:43 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int set_system(const struct dmi_system_id *id);
|
|
|
|
|
|
|
|
#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
|
|
|
|
{ set_system, name, { \
|
|
|
|
DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
|
|
|
|
DMI_MATCH(DMI_PRODUCT_NAME, name) }, \
|
|
|
|
&dmi_list[enumid] }
|
|
|
|
|
2010-08-11 09:02:28 +08:00
|
|
|
static const struct dmi_system_id dmi_system_table[] __initconst = {
|
2008-10-16 13:03:43 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17),
|
|
|
|
/* At least one of these two will be right; maybe both? */
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20),
|
|
|
|
/* At least one of these two will be right; maybe both? */
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR),
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1),
|
2008-10-16 13:03:43 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI),
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1),
|
2008-10-16 13:03:43 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB),
|
|
|
|
/* At least one of these two will be right; maybe both? */
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB),
|
|
|
|
/* At least one of these two will be right; maybe both? */
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB),
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1),
|
2008-10-16 13:03:43 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA),
|
2011-04-07 01:34:59 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3),
|
2008-10-16 13:03:43 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2),
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2),
|
2008-10-16 13:03:43 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
|
drivers/video/efifb.c: support framebuffer for NVIDIA 9400M in MacBook Pro 5,1
Description of patch:
---------------------
This is a patch for the EFI framebuffer driver to enable the framebuffer
of the NVIDIA 9400M as found in MacBook Pro (MBP) 5,1 and up. The
framebuffer of the NVIDIA graphic cards are located at the following
addresses in memory:
9400M: 0xC0010000
9600M GT: 0xB0030000
The patch delivered right here only provides the memory location of the
framebuffer of the 9400M device. The 9600M GT is not covered. It is
assumed that the 9400M is used when powered up the MBP.
The information which device is currently powered and in use is stored in
the 64 bytes large EFI variable "gpu-power-prefs". More specifically,
byte 0x3B indicates whether 9600M GT (0x00) or 9400M (0x01) is online.
The PCI bus IDs are the following:
9400M: PCI 03:00:00
9600M GT: PCI 02:00:00
The EFI variables can be easily read-out and manipulated with "rEFIt", an
MBP specific bootloader tool. For more information on how handle rEFIt
and EFI variables please consult "http://refit.sourceforge.net" and
"http://ubuntuforums.org/archive/index.php/t-1076879.html".
IMPORTANT NOTE: The information on how to activate the 9400M device given
at "ubuntuforums.org" is not correct, since it states
gpu-power-prefs[0x3B] = 0x00 -> 9400M (PCI 02:00:00)
gpu-power-prefs[0x3B] = 0x01 -> 9600M GT (PCI 03:00:00)
Actually, the assignment of the values and the PCI bus IDs are swapped.
Suggestions:
------------
To cover framebuffers of both 9400M and 9600M GT, I would suggest to
implement a conditional on "gpu-power-prefs". Depending on the value of
byte 0x3B, the according framebuffer is selected. However, this requires
kernel access to the EFI variables.
[akpm@linux-foundation.org: rename optname, per Peter Jones]
Signed-off-by: Thomas Gerlach <t.m.gerlach@freenet.de>
Acked-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-04-24 01:17:50 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
|
efifb: support the EFI framebuffer on more Apple hardware
Enable the EFI framebuffer on 14 more Macs, including the iMac11,1
iMac10,1 iMac8,1 Macmini3,1 Macmini4,1 MacBook5,1 MacBook6,1 MacBook7,1
MacBookPro2,2 MacBookPro5,2 MacBookPro5,3 MacBookPro6,1 MacBookPro6,2 and
MacBookPro7,1
Information gathered from various user submissions.
https://bugzilla.redhat.com/show_bug.cgi?id=528232
http://ubuntuforums.org/showthread.php?t=1557326
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Luke Macken <lmacken@redhat.com>
Signed-off-by: Peter Jones <pjones@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-23 04:05:04 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2),
|
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1),
|
2011-03-31 08:12:22 +08:00
|
|
|
EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2),
|
2008-10-16 13:03:43 +08:00
|
|
|
{},
|
|
|
|
};
|
|
|
|
|
2011-04-07 01:34:58 +08:00
|
|
|
#define choose_value(dmivalue, fwvalue, field, flags) ({ \
|
|
|
|
typeof(fwvalue) _ret_ = fwvalue; \
|
|
|
|
if ((flags) & (field)) \
|
|
|
|
_ret_ = dmivalue; \
|
|
|
|
else if ((fwvalue) == 0) \
|
|
|
|
_ret_ = dmivalue; \
|
|
|
|
_ret_; \
|
|
|
|
})
|
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
static int set_system(const struct dmi_system_id *id)
|
|
|
|
{
|
|
|
|
struct efifb_dmi_info *info = id->driver_data;
|
|
|
|
|
2011-04-07 01:34:58 +08:00
|
|
|
if (info->base == 0 && info->height == 0 && info->width == 0
|
|
|
|
&& info->stride == 0)
|
|
|
|
return 0;
|
2008-10-16 13:03:43 +08:00
|
|
|
|
|
|
|
/* Trust the bootloader over the DMI tables */
|
2010-09-23 04:05:04 +08:00
|
|
|
if (screen_info.lfb_base == 0) {
|
|
|
|
#if defined(CONFIG_PCI)
|
|
|
|
struct pci_dev *dev = NULL;
|
|
|
|
int found_bar = 0;
|
|
|
|
#endif
|
2011-04-07 01:34:58 +08:00
|
|
|
if (info->base) {
|
|
|
|
screen_info.lfb_base = choose_value(info->base,
|
|
|
|
screen_info.lfb_base, OVERRIDE_BASE,
|
|
|
|
info->flags);
|
2008-10-16 13:03:43 +08:00
|
|
|
|
2010-09-23 04:05:04 +08:00
|
|
|
#if defined(CONFIG_PCI)
|
2011-04-07 01:34:58 +08:00
|
|
|
/* make sure that the address in the table is actually
|
|
|
|
* on a VGA device's PCI BAR */
|
|
|
|
|
|
|
|
for_each_pci_dev(dev) {
|
|
|
|
int i;
|
|
|
|
if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
|
|
|
|
continue;
|
|
|
|
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
|
|
|
resource_size_t start, end;
|
|
|
|
|
|
|
|
start = pci_resource_start(dev, i);
|
|
|
|
if (start == 0)
|
|
|
|
break;
|
|
|
|
end = pci_resource_end(dev, i);
|
|
|
|
if (screen_info.lfb_base >= start &&
|
|
|
|
screen_info.lfb_base < end) {
|
|
|
|
found_bar = 1;
|
|
|
|
}
|
2010-09-23 04:05:04 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-07 01:34:58 +08:00
|
|
|
if (!found_bar)
|
|
|
|
screen_info.lfb_base = 0;
|
2010-09-23 04:05:04 +08:00
|
|
|
#endif
|
2011-04-07 01:34:58 +08:00
|
|
|
}
|
2010-09-23 04:05:04 +08:00
|
|
|
}
|
|
|
|
if (screen_info.lfb_base) {
|
2011-04-07 01:34:58 +08:00
|
|
|
screen_info.lfb_linelength = choose_value(info->stride,
|
|
|
|
screen_info.lfb_linelength, OVERRIDE_STRIDE,
|
|
|
|
info->flags);
|
|
|
|
screen_info.lfb_width = choose_value(info->width,
|
|
|
|
screen_info.lfb_width, OVERRIDE_WIDTH,
|
|
|
|
info->flags);
|
|
|
|
screen_info.lfb_height = choose_value(info->height,
|
|
|
|
screen_info.lfb_height, OVERRIDE_HEIGHT,
|
|
|
|
info->flags);
|
2010-09-23 04:05:04 +08:00
|
|
|
if (screen_info.orig_video_isVGA == 0)
|
|
|
|
screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
|
|
|
|
} else {
|
|
|
|
screen_info.lfb_linelength = 0;
|
|
|
|
screen_info.lfb_width = 0;
|
|
|
|
screen_info.lfb_height = 0;
|
|
|
|
screen_info.orig_video_isVGA = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
2011-04-07 01:34:58 +08:00
|
|
|
|
2011-04-19 17:47:15 +08:00
|
|
|
printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x "
|
2011-04-07 01:34:58 +08:00
|
|
|
"(%dx%d, stride %d)\n", id->ident,
|
2011-04-19 17:47:15 +08:00
|
|
|
screen_info.lfb_base, screen_info.lfb_width,
|
2011-04-07 01:34:58 +08:00
|
|
|
screen_info.lfb_height, screen_info.lfb_linelength);
|
|
|
|
|
|
|
|
|
2010-09-23 04:05:04 +08:00
|
|
|
return 1;
|
2008-10-16 13:03:43 +08:00
|
|
|
}
|
|
|
|
|
2007-11-29 08:21:55 +08:00
|
|
|
static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
|
|
|
unsigned blue, unsigned transp,
|
|
|
|
struct fb_info *info)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Set a single color register. The values supplied are
|
|
|
|
* already rounded down to the hardware's capabilities
|
|
|
|
* (according to the entries in the `var' structure). Return
|
|
|
|
* != 0 for invalid regno.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (regno >= info->cmap.len)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (regno < 16) {
|
|
|
|
red >>= 8;
|
|
|
|
green >>= 8;
|
|
|
|
blue >>= 8;
|
|
|
|
((u32 *)(info->pseudo_palette))[regno] =
|
|
|
|
(red << info->var.red.offset) |
|
|
|
|
(green << info->var.green.offset) |
|
|
|
|
(blue << info->var.blue.offset);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-23 04:44:22 +08:00
|
|
|
static void efifb_destroy(struct fb_info *info)
|
|
|
|
{
|
|
|
|
if (info->screen_base)
|
|
|
|
iounmap(info->screen_base);
|
2011-05-26 22:13:32 +08:00
|
|
|
if (request_mem_succeeded)
|
|
|
|
release_mem_region(info->apertures->ranges[0].base,
|
|
|
|
info->apertures->ranges[0].size);
|
2010-02-23 04:44:22 +08:00
|
|
|
framebuffer_release(info);
|
|
|
|
}
|
|
|
|
|
2007-11-29 08:21:55 +08:00
|
|
|
static struct fb_ops efifb_ops = {
|
|
|
|
.owner = THIS_MODULE,
|
2010-02-23 04:44:22 +08:00
|
|
|
.fb_destroy = efifb_destroy,
|
2007-11-29 08:21:55 +08:00
|
|
|
.fb_setcolreg = efifb_setcolreg,
|
|
|
|
.fb_fillrect = cfb_fillrect,
|
|
|
|
.fb_copyarea = cfb_copyarea,
|
|
|
|
.fb_imageblit = cfb_imageblit,
|
|
|
|
};
|
|
|
|
|
2012-04-17 04:26:05 +08:00
|
|
|
struct pci_dev *vga_default_device(void)
|
|
|
|
{
|
|
|
|
return default_vga;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vga_set_default_device(struct pci_dev *pdev)
|
|
|
|
{
|
|
|
|
default_vga = pdev;
|
|
|
|
}
|
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
static int __init efifb_setup(char *options)
|
|
|
|
{
|
|
|
|
char *this_opt;
|
|
|
|
int i;
|
2012-04-17 04:26:05 +08:00
|
|
|
struct pci_dev *dev = NULL;
|
2008-10-16 13:03:43 +08:00
|
|
|
|
2012-04-17 04:26:05 +08:00
|
|
|
if (options && *options) {
|
|
|
|
while ((this_opt = strsep(&options, ",")) != NULL) {
|
|
|
|
if (!*this_opt) continue;
|
2008-10-16 13:03:43 +08:00
|
|
|
|
2012-04-17 04:26:05 +08:00
|
|
|
for (i = 0; i < M_UNKNOWN; i++) {
|
|
|
|
if (!strcmp(this_opt, dmi_list[i].optname) &&
|
|
|
|
dmi_list[i].base != 0) {
|
|
|
|
screen_info.lfb_base = dmi_list[i].base;
|
|
|
|
screen_info.lfb_linelength = dmi_list[i].stride;
|
|
|
|
screen_info.lfb_width = dmi_list[i].width;
|
|
|
|
screen_info.lfb_height = dmi_list[i].height;
|
|
|
|
}
|
2008-10-16 13:03:43 +08:00
|
|
|
}
|
2012-04-17 04:26:05 +08:00
|
|
|
if (!strncmp(this_opt, "base:", 5))
|
|
|
|
screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0);
|
|
|
|
else if (!strncmp(this_opt, "stride:", 7))
|
|
|
|
screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4;
|
|
|
|
else if (!strncmp(this_opt, "height:", 7))
|
|
|
|
screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0);
|
|
|
|
else if (!strncmp(this_opt, "width:", 6))
|
|
|
|
screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0);
|
2008-10-16 13:03:43 +08:00
|
|
|
}
|
|
|
|
}
|
2012-04-17 04:26:05 +08:00
|
|
|
|
|
|
|
for_each_pci_dev(dev) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i=0; i < DEVICE_COUNT_RESOURCE; i++) {
|
|
|
|
resource_size_t start, end;
|
|
|
|
|
|
|
|
if (!(pci_resource_flags(dev, i) & IORESOURCE_MEM))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
start = pci_resource_start(dev, i);
|
|
|
|
end = pci_resource_end(dev, i);
|
|
|
|
|
|
|
|
if (!start || !end)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (screen_info.lfb_base >= start &&
|
|
|
|
(screen_info.lfb_base + screen_info.lfb_size) < end)
|
|
|
|
default_vga = dev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-26 22:13:34 +08:00
|
|
|
static int __init efifb_probe(struct platform_device *dev)
|
2007-11-29 08:21:55 +08:00
|
|
|
{
|
|
|
|
struct fb_info *info;
|
|
|
|
int err;
|
|
|
|
unsigned int size_vmode;
|
|
|
|
unsigned int size_remap;
|
|
|
|
unsigned int size_total;
|
2008-10-16 13:03:43 +08:00
|
|
|
|
|
|
|
if (!screen_info.lfb_depth)
|
|
|
|
screen_info.lfb_depth = 32;
|
|
|
|
if (!screen_info.pages)
|
|
|
|
screen_info.pages = 1;
|
2009-04-14 05:39:44 +08:00
|
|
|
if (!screen_info.lfb_base) {
|
|
|
|
printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
printk(KERN_INFO "efifb: probing for efifb\n");
|
2008-10-16 13:03:43 +08:00
|
|
|
|
|
|
|
/* just assume they're all unset if any are */
|
|
|
|
if (!screen_info.blue_size) {
|
|
|
|
screen_info.blue_size = 8;
|
|
|
|
screen_info.blue_pos = 0;
|
|
|
|
screen_info.green_size = 8;
|
|
|
|
screen_info.green_pos = 8;
|
|
|
|
screen_info.red_size = 8;
|
|
|
|
screen_info.red_pos = 16;
|
|
|
|
screen_info.rsvd_size = 8;
|
|
|
|
screen_info.rsvd_pos = 24;
|
|
|
|
}
|
2007-11-29 08:21:55 +08:00
|
|
|
|
|
|
|
efifb_fix.smem_start = screen_info.lfb_base;
|
|
|
|
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
|
|
|
|
efifb_defined.xres = screen_info.lfb_width;
|
|
|
|
efifb_defined.yres = screen_info.lfb_height;
|
|
|
|
efifb_fix.line_length = screen_info.lfb_linelength;
|
|
|
|
|
|
|
|
/* size_vmode -- that is the amount of memory needed for the
|
|
|
|
* used video mode, i.e. the minimum amount of
|
|
|
|
* memory we need. */
|
|
|
|
size_vmode = efifb_defined.yres * efifb_fix.line_length;
|
|
|
|
|
|
|
|
/* size_total -- all video memory we have. Used for
|
|
|
|
* entries, ressource allocation and bounds
|
|
|
|
* checking. */
|
|
|
|
size_total = screen_info.lfb_size;
|
|
|
|
if (size_total < size_vmode)
|
|
|
|
size_total = size_vmode;
|
|
|
|
|
|
|
|
/* size_remap -- the amount of video memory we are going to
|
|
|
|
* use for efifb. With modern cards it is no
|
|
|
|
* option to simply use size_total as that
|
|
|
|
* wastes plenty of kernel address space. */
|
|
|
|
size_remap = size_vmode * 2;
|
|
|
|
if (size_remap > size_total)
|
|
|
|
size_remap = size_total;
|
2008-10-16 13:03:43 +08:00
|
|
|
if (size_remap % PAGE_SIZE)
|
|
|
|
size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE);
|
2007-11-29 08:21:55 +08:00
|
|
|
efifb_fix.smem_len = size_remap;
|
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) {
|
2011-05-26 22:13:32 +08:00
|
|
|
request_mem_succeeded = true;
|
2008-10-16 13:03:43 +08:00
|
|
|
} else {
|
2007-11-29 08:21:55 +08:00
|
|
|
/* We cannot make this fatal. Sometimes this comes from magic
|
|
|
|
spaces our resource handlers simply don't know about */
|
|
|
|
printk(KERN_WARNING
|
|
|
|
"efifb: cannot reserve video memory at 0x%lx\n",
|
|
|
|
efifb_fix.smem_start);
|
2008-10-16 13:03:43 +08:00
|
|
|
}
|
2007-11-29 08:21:55 +08:00
|
|
|
|
|
|
|
info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
|
|
|
|
if (!info) {
|
2008-10-16 13:03:43 +08:00
|
|
|
printk(KERN_ERR "efifb: cannot allocate framebuffer\n");
|
2007-11-29 08:21:55 +08:00
|
|
|
err = -ENOMEM;
|
|
|
|
goto err_release_mem;
|
|
|
|
}
|
|
|
|
info->pseudo_palette = info->par;
|
|
|
|
info->par = NULL;
|
|
|
|
|
2010-05-16 23:27:03 +08:00
|
|
|
info->apertures = alloc_apertures(1);
|
|
|
|
if (!info->apertures) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto err_release_fb;
|
|
|
|
}
|
|
|
|
info->apertures->ranges[0].base = efifb_fix.smem_start;
|
|
|
|
info->apertures->ranges[0].size = size_remap;
|
2009-06-17 06:34:38 +08:00
|
|
|
|
2011-05-26 22:13:31 +08:00
|
|
|
info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len);
|
2007-11-29 08:21:55 +08:00
|
|
|
if (!info->screen_base) {
|
|
|
|
printk(KERN_ERR "efifb: abort, cannot ioremap video memory "
|
|
|
|
"0x%x @ 0x%lx\n",
|
|
|
|
efifb_fix.smem_len, efifb_fix.smem_start);
|
|
|
|
err = -EIO;
|
2008-10-16 13:03:43 +08:00
|
|
|
goto err_release_fb;
|
2007-11-29 08:21:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, "
|
|
|
|
"using %dk, total %dk\n",
|
|
|
|
efifb_fix.smem_start, info->screen_base,
|
|
|
|
size_remap/1024, size_total/1024);
|
|
|
|
printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
|
|
|
|
efifb_defined.xres, efifb_defined.yres,
|
|
|
|
efifb_defined.bits_per_pixel, efifb_fix.line_length,
|
|
|
|
screen_info.pages);
|
|
|
|
|
|
|
|
efifb_defined.xres_virtual = efifb_defined.xres;
|
|
|
|
efifb_defined.yres_virtual = efifb_fix.smem_len /
|
|
|
|
efifb_fix.line_length;
|
|
|
|
printk(KERN_INFO "efifb: scrolling: redraw\n");
|
|
|
|
efifb_defined.yres_virtual = efifb_defined.yres;
|
|
|
|
|
|
|
|
/* some dummy values for timing to make fbset happy */
|
|
|
|
efifb_defined.pixclock = 10000000 / efifb_defined.xres *
|
|
|
|
1000 / efifb_defined.yres;
|
|
|
|
efifb_defined.left_margin = (efifb_defined.xres / 8) & 0xf8;
|
|
|
|
efifb_defined.hsync_len = (efifb_defined.xres / 8) & 0xf8;
|
|
|
|
|
|
|
|
efifb_defined.red.offset = screen_info.red_pos;
|
|
|
|
efifb_defined.red.length = screen_info.red_size;
|
|
|
|
efifb_defined.green.offset = screen_info.green_pos;
|
|
|
|
efifb_defined.green.length = screen_info.green_size;
|
|
|
|
efifb_defined.blue.offset = screen_info.blue_pos;
|
|
|
|
efifb_defined.blue.length = screen_info.blue_size;
|
|
|
|
efifb_defined.transp.offset = screen_info.rsvd_pos;
|
|
|
|
efifb_defined.transp.length = screen_info.rsvd_size;
|
|
|
|
|
|
|
|
printk(KERN_INFO "efifb: %s: "
|
|
|
|
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
|
|
|
|
"Truecolor",
|
|
|
|
screen_info.rsvd_size,
|
|
|
|
screen_info.red_size,
|
|
|
|
screen_info.green_size,
|
|
|
|
screen_info.blue_size,
|
|
|
|
screen_info.rsvd_pos,
|
|
|
|
screen_info.red_pos,
|
|
|
|
screen_info.green_pos,
|
|
|
|
screen_info.blue_pos);
|
|
|
|
|
|
|
|
efifb_fix.ypanstep = 0;
|
|
|
|
efifb_fix.ywrapstep = 0;
|
|
|
|
|
|
|
|
info->fbops = &efifb_ops;
|
|
|
|
info->var = efifb_defined;
|
|
|
|
info->fix = efifb_fix;
|
2009-06-17 06:34:38 +08:00
|
|
|
info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE;
|
2007-11-29 08:21:55 +08:00
|
|
|
|
2008-10-16 13:03:43 +08:00
|
|
|
if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) {
|
|
|
|
printk(KERN_ERR "efifb: cannot allocate colormap\n");
|
2007-11-29 08:21:55 +08:00
|
|
|
goto err_unmap;
|
|
|
|
}
|
2008-10-16 13:03:43 +08:00
|
|
|
if ((err = register_framebuffer(info)) < 0) {
|
|
|
|
printk(KERN_ERR "efifb: cannot register framebuffer\n");
|
2007-11-29 08:21:55 +08:00
|
|
|
goto err_fb_dealoc;
|
|
|
|
}
|
|
|
|
printk(KERN_INFO "fb%d: %s frame buffer device\n",
|
2008-10-16 13:03:43 +08:00
|
|
|
info->node, info->fix.id);
|
2007-11-29 08:21:55 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_fb_dealoc:
|
|
|
|
fb_dealloc_cmap(&info->cmap);
|
|
|
|
err_unmap:
|
|
|
|
iounmap(info->screen_base);
|
2008-10-16 13:03:43 +08:00
|
|
|
err_release_fb:
|
2007-11-29 08:21:55 +08:00
|
|
|
framebuffer_release(info);
|
|
|
|
err_release_mem:
|
2011-05-26 22:13:32 +08:00
|
|
|
if (request_mem_succeeded)
|
2008-10-16 13:03:43 +08:00
|
|
|
release_mem_region(efifb_fix.smem_start, size_total);
|
2007-11-29 08:21:55 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct platform_driver efifb_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "efifb",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct platform_device efifb_device = {
|
|
|
|
.name = "efifb",
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init efifb_init(void)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-10-16 13:03:43 +08:00
|
|
|
char *option = NULL;
|
2007-11-29 08:21:55 +08:00
|
|
|
|
2009-04-01 06:25:50 +08:00
|
|
|
dmi_check_system(dmi_system_table);
|
|
|
|
|
2007-11-29 08:21:55 +08:00
|
|
|
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
|
|
|
|
return -ENODEV;
|
2008-10-16 13:03:43 +08:00
|
|
|
|
|
|
|
if (fb_get_options("efifb", &option))
|
|
|
|
return -ENODEV;
|
|
|
|
efifb_setup(option);
|
|
|
|
|
|
|
|
/* We don't get linelength from UGA Draw Protocol, only from
|
|
|
|
* EFI Graphics Protocol. So if it's not in DMI, and it's not
|
|
|
|
* passed in from the user, we really can't use the framebuffer.
|
|
|
|
*/
|
|
|
|
if (!screen_info.lfb_linelength)
|
|
|
|
return -ENODEV;
|
2007-11-29 08:21:55 +08:00
|
|
|
|
2011-05-26 22:13:34 +08:00
|
|
|
ret = platform_device_register(&efifb_device);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
2007-11-29 08:21:55 +08:00
|
|
|
|
2011-05-26 22:13:34 +08:00
|
|
|
/*
|
|
|
|
* This is not just an optimization. We will interfere
|
|
|
|
* with a real driver if we get reprobed, so don't allow
|
|
|
|
* it.
|
|
|
|
*/
|
|
|
|
ret = platform_driver_probe(&efifb_driver, efifb_probe);
|
|
|
|
if (ret) {
|
2011-06-12 18:52:33 +08:00
|
|
|
platform_device_unregister(&efifb_device);
|
2011-05-26 22:13:34 +08:00
|
|
|
return ret;
|
2007-11-29 08:21:55 +08:00
|
|
|
}
|
2011-05-26 22:13:34 +08:00
|
|
|
|
2007-11-29 08:21:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
module_init(efifb_init);
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|