17c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying/* 27c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * Framebuffer driver for EFI/UEFI based system 37c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * 47c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * (c) 2006 Edgar Hucek <gimli@dark-green.com> 57c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * Original efi driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de> 67c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * 77c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying */ 87c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 97c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <linux/module.h> 107c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <linux/kernel.h> 117c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <linux/errno.h> 127c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <linux/fb.h> 137c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <linux/platform_device.h> 147c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <linux/screen_info.h> 157c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones#include <linux/dmi.h> 1685a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones#include <linux/pci.h> 177c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying#include <video/vga.h> 187c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 19da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirskistatic bool request_mem_succeeded = false; 20da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirski 21ec81c9cc2f58a3a9f9637c390ea83efe9f91abf7Henrik Kretzschmarstatic struct fb_var_screeninfo efifb_defined __devinitdata = { 227c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .activate = FB_ACTIVATE_NOW, 237c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .height = -1, 247c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .width = -1, 257c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .right_margin = 32, 267c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .upper_margin = 16, 277c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .lower_margin = 4, 287c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .vsync_len = 4, 297c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .vmode = FB_VMODE_NONINTERLACED, 307c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying}; 317c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 32ec81c9cc2f58a3a9f9637c390ea83efe9f91abf7Henrik Kretzschmarstatic struct fb_fix_screeninfo efifb_fix __devinitdata = { 337c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .id = "EFI VGA", 347c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .type = FB_TYPE_PACKED_PIXELS, 357c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .accel = FB_ACCEL_NONE, 367c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .visual = FB_VISUAL_TRUECOLOR, 377c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying}; 387c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 397c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jonesenum { 407c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_I17, /* 17-Inch iMac */ 417c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_I20, /* 20-Inch iMac */ 427c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_I20_SR, /* 20-Inch iMac (Santa Rosa) */ 437c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_I24, /* 24-Inch iMac */ 44a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_I24_8_1, /* 24-Inch iMac, 8,1th gen */ 45a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_I24_10_1, /* 24-Inch iMac, 10,1th gen */ 46a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_I27_11_1, /* 27-Inch iMac, 11,1th gen */ 477c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MINI, /* Mac Mini */ 48a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MINI_3_1, /* Mac Mini, 3,1th gen */ 49a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MINI_4_1, /* Mac Mini, 4,1th gen */ 507c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MB, /* MacBook */ 517c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MB_2, /* MacBook, 2nd rev. */ 527c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MB_3, /* MacBook, 3rd rev. */ 53a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MB_5_1, /* MacBook, 5th rev. */ 54a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MB_6_1, /* MacBook, 6th rev. */ 55a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MB_7_1, /* MacBook, 7th rev. */ 567c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ 577c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MBA, /* MacBook Air */ 5897fb85076c2d3adcc559dee577e0a3bf7215d48eMatthew Garrett M_MBA_3, /* Macbook Air, 3rd rev */ 597c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MBP, /* MacBook Pro */ 607c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MBP_2, /* MacBook Pro 2nd gen */ 61a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MBP_2_2, /* MacBook Pro 2,2nd gen */ 627c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MBP_SR, /* MacBook Pro (Santa Rosa) */ 637c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_MBP_4, /* MacBook Pro, 4th gen */ 648a3bdfe6cd841880a5d849c40f90093b3817f6e0Thomas Gerlach M_MBP_5_1, /* MacBook Pro, 5,1th gen */ 65a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MBP_5_2, /* MacBook Pro, 5,2th gen */ 66a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MBP_5_3, /* MacBook Pro, 5,3rd gen */ 67a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MBP_6_1, /* MacBook Pro, 6,1th gen */ 68a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MBP_6_2, /* MacBook Pro, 6,2th gen */ 69a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken M_MBP_7_1, /* MacBook Pro, 7,1th gen */ 70e9c5db0b8dce1bcdc99ad26e718230810d6b5cffDavidlohr Bueso M_MBP_8_2, /* MacBook Pro, 8,2nd gen */ 717c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones M_UNKNOWN /* placeholder */ 727c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones}; 737c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 7447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones#define OVERRIDE_NONE 0x0 7547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones#define OVERRIDE_BASE 0x1 7647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones#define OVERRIDE_STRIDE 0x2 7747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones#define OVERRIDE_HEIGHT 0x4 7847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones#define OVERRIDE_WIDTH 0x8 7947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 807c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jonesstatic struct efifb_dmi_info { 817c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones char *optname; 827c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones unsigned long base; 837c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones int stride; 847c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones int width; 857c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones int height; 8647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones int flags; 87ec81c9cc2f58a3a9f9637c390ea83efe9f91abf7Henrik Kretzschmar} dmi_list[] __initdata = { 8847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, 8947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */ 9047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, 9147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */ 9247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, 9347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE }, 9447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE }, 9547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE }, 9647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE }, 9747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, 9847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, 9947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, 10047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, 10147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, 10247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, 10397fb85076c2d3adcc559dee577e0a3bf7215d48eMatthew Garrett /* 11" Macbook Air 3,1 passes the wrong stride */ 10497fb85076c2d3adcc559dee577e0a3bf7215d48eMatthew Garrett [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE }, 10547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, 10647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */ 10747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, 10847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, 10947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, 11047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, 11147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, 11247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, 11347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, 11447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE }, 11547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, 11647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_MBP_8_2] = { "mbp82", 0x90010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, 11747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } 1187c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones}; 1197c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 1207c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jonesstatic int set_system(const struct dmi_system_id *id); 1217c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 1227c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \ 1237c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones { set_system, name, { \ 1247c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones DMI_MATCH(DMI_BIOS_VENDOR, vendor), \ 1257c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones DMI_MATCH(DMI_PRODUCT_NAME, name) }, \ 1267c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones &dmi_list[enumid] } 1277c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 128ec81c9cc2f58a3a9f9637c390ea83efe9f91abf7Henrik Kretzschmarstatic const struct dmi_system_id dmi_system_table[] __initconst = { 1297c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac4,1", M_I17), 1307c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* At least one of these two will be right; maybe both? */ 1317c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac5,1", M_I20), 1327c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac5,1", M_I20), 1337c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* At least one of these two will be right; maybe both? */ 1347c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24), 1357c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24), 1367c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR), 137a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1), 138a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1), 139a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1), 1407c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI), 141a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1), 142a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1), 1437c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB), 1447c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* At least one of these two will be right; maybe both? */ 1457c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB), 1467c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook2,1", M_MB), 1477c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* At least one of these two will be right; maybe both? */ 1487c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB), 1497c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB), 1507c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB), 151a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1), 152a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), 153a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), 1547c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), 15597fb85076c2d3adcc559dee577e0a3bf7215d48eMatthew Garrett EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3), 1567c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), 1577c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), 158a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), 1597c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2), 1607c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), 1617c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), 1627c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), 1638a3bdfe6cd841880a5d849c40f90093b3817f6e0Thomas Gerlach EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1), 164a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2), 165a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3), 166a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), 167a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), 168a5757c2a474a15f87e5baa9a4caacc31cde2bae6Luke Macken EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), 169e9c5db0b8dce1bcdc99ad26e718230810d6b5cffDavidlohr Bueso EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro8,2", M_MBP_8_2), 1707c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones {}, 1717c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones}; 1727c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 17347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones#define choose_value(dmivalue, fwvalue, field, flags) ({ \ 17447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones typeof(fwvalue) _ret_ = fwvalue; \ 17547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if ((flags) & (field)) \ 17647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones _ret_ = dmivalue; \ 17747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones else if ((fwvalue) == 0) \ 17847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones _ret_ = dmivalue; \ 17947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones _ret_; \ 18047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones }) 18147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 1827c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jonesstatic int set_system(const struct dmi_system_id *id) 1837c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones{ 1847c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones struct efifb_dmi_info *info = id->driver_data; 1857c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 18647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if (info->base == 0 && info->height == 0 && info->width == 0 18747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones && info->stride == 0) 18847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones return 0; 1897c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 1907c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* Trust the bootloader over the DMI tables */ 19185a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones if (screen_info.lfb_base == 0) { 19285a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones#if defined(CONFIG_PCI) 19385a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones struct pci_dev *dev = NULL; 19485a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones int found_bar = 0; 19585a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones#endif 19647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if (info->base) { 19747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_base = choose_value(info->base, 19847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_base, OVERRIDE_BASE, 19947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones info->flags); 2007c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 20185a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones#if defined(CONFIG_PCI) 20247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones /* make sure that the address in the table is actually 20347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones * on a VGA device's PCI BAR */ 20447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 20547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones for_each_pci_dev(dev) { 20647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones int i; 20747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) 20847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones continue; 20947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 21047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones resource_size_t start, end; 21147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 21247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones start = pci_resource_start(dev, i); 21347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if (start == 0) 21447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones break; 21547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones end = pci_resource_end(dev, i); 21647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if (screen_info.lfb_base >= start && 21747dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_base < end) { 21847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones found_bar = 1; 21947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones } 22085a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones } 22185a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones } 22247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones if (!found_bar) 22347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_base = 0; 22485a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones#endif 22547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones } 22685a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones } 22785a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones if (screen_info.lfb_base) { 22847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_linelength = choose_value(info->stride, 22947dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_linelength, OVERRIDE_STRIDE, 23047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones info->flags); 23147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_width = choose_value(info->width, 23247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_width, OVERRIDE_WIDTH, 23347dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones info->flags); 23447dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_height = choose_value(info->height, 23547dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_height, OVERRIDE_HEIGHT, 23647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones info->flags); 23785a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones if (screen_info.orig_video_isVGA == 0) 23885a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; 23985a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones } else { 24085a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones screen_info.lfb_linelength = 0; 24185a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones screen_info.lfb_width = 0; 24285a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones screen_info.lfb_height = 0; 24385a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones screen_info.orig_video_isVGA = 0; 24485a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones return 0; 24585a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones } 24647dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 247dc3e5b6a6e842116ec2436161adf31877f09b6b9Konstantin Khlebnikov printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x " 24847dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones "(%dx%d, stride %d)\n", id->ident, 249dc3e5b6a6e842116ec2436161adf31877f09b6b9Konstantin Khlebnikov screen_info.lfb_base, screen_info.lfb_width, 25047dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones screen_info.lfb_height, screen_info.lfb_linelength); 25147dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 25247dfe51f8f0b9540cbe15072cd352d9f3857d47fPeter Jones 25385a00d9bbfb4704fbf368944b1cb9fed8f1598c5Peter Jones return 1; 2547c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones} 2557c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 2567c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingstatic int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, 2577c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying unsigned blue, unsigned transp, 2587c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying struct fb_info *info) 2597c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying{ 2607c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying /* 2617c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * Set a single color register. The values supplied are 2627c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * already rounded down to the hardware's capabilities 2637c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * (according to the entries in the `var' structure). Return 2647c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * != 0 for invalid regno. 2657c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying */ 2667c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 2677c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (regno >= info->cmap.len) 2687c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying return 1; 2697c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 2707c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (regno < 16) { 2717c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying red >>= 8; 2727c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying green >>= 8; 2737c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying blue >>= 8; 2747c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying ((u32 *)(info->pseudo_palette))[regno] = 2757c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying (red << info->var.red.offset) | 2767c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying (green << info->var.green.offset) | 2777c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying (blue << info->var.blue.offset); 2787c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying } 2797c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying return 0; 2807c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying} 2817c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 28289f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarzstatic void efifb_destroy(struct fb_info *info) 28389f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz{ 28489f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz if (info->screen_base) 28589f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz iounmap(info->screen_base); 286da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirski if (request_mem_succeeded) 287da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirski release_mem_region(info->apertures->ranges[0].base, 288da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirski info->apertures->ranges[0].size); 28989f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz framebuffer_release(info); 29089f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz} 29189f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz 2927c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingstatic struct fb_ops efifb_ops = { 2937c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .owner = THIS_MODULE, 29489f3f2199084a160a3a45fa6d9af235696321758Marcin Slusarz .fb_destroy = efifb_destroy, 2957c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .fb_setcolreg = efifb_setcolreg, 2967c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .fb_fillrect = cfb_fillrect, 2977c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .fb_copyarea = cfb_copyarea, 2987c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .fb_imageblit = cfb_imageblit, 2997c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying}; 3007c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 3017c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jonesstatic int __init efifb_setup(char *options) 3027c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones{ 3037c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones char *this_opt; 3047c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones int i; 3057c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 3067c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!options || !*options) 3077c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones return 0; 3087c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 3097c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones while ((this_opt = strsep(&options, ",")) != NULL) { 3107c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!*this_opt) continue; 3117c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 3127c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones for (i = 0; i < M_UNKNOWN; i++) { 3137c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!strcmp(this_opt, dmi_list[i].optname) && 3147c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones dmi_list[i].base != 0) { 3157c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_base = dmi_list[i].base; 3167c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_linelength = dmi_list[i].stride; 3177c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_width = dmi_list[i].width; 3187c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_height = dmi_list[i].height; 3197c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones } 3207c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones } 3217c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!strncmp(this_opt, "base:", 5)) 3227c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_base = simple_strtoul(this_opt+5, NULL, 0); 3237c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones else if (!strncmp(this_opt, "stride:", 7)) 3247c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_linelength = simple_strtoul(this_opt+7, NULL, 0) * 4; 3257c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones else if (!strncmp(this_opt, "height:", 7)) 3267c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_height = simple_strtoul(this_opt+7, NULL, 0); 3277c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones else if (!strncmp(this_opt, "width:", 6)) 3287c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_width = simple_strtoul(this_opt+6, NULL, 0); 3297c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones } 3307c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones return 0; 3317c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones} 3327c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 333bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirskistatic int __init efifb_probe(struct platform_device *dev) 3347c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying{ 3357c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying struct fb_info *info; 3367c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying int err; 3377c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying unsigned int size_vmode; 3387c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying unsigned int size_remap; 3397c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying unsigned int size_total; 3407c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 3417c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!screen_info.lfb_depth) 3427c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.lfb_depth = 32; 3437c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!screen_info.pages) 3447c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.pages = 1; 345133bb070e94ab41d750c6f2160c8843e46f11b78Matthew Garrett if (!screen_info.lfb_base) { 346133bb070e94ab41d750c6f2160c8843e46f11b78Matthew Garrett printk(KERN_DEBUG "efifb: invalid framebuffer address\n"); 347133bb070e94ab41d750c6f2160c8843e46f11b78Matthew Garrett return -ENODEV; 348133bb070e94ab41d750c6f2160c8843e46f11b78Matthew Garrett } 349133bb070e94ab41d750c6f2160c8843e46f11b78Matthew Garrett printk(KERN_INFO "efifb: probing for efifb\n"); 3507c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 3517c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* just assume they're all unset if any are */ 3527c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!screen_info.blue_size) { 3537c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.blue_size = 8; 3547c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.blue_pos = 0; 3557c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.green_size = 8; 3567c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.green_pos = 8; 3577c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.red_size = 8; 3587c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.red_pos = 16; 3597c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.rsvd_size = 8; 3607c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones screen_info.rsvd_pos = 24; 3617c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones } 3627c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 3637c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.smem_start = screen_info.lfb_base; 3647c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.bits_per_pixel = screen_info.lfb_depth; 3657c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.xres = screen_info.lfb_width; 3667c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.yres = screen_info.lfb_height; 3677c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.line_length = screen_info.lfb_linelength; 3687c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 3697c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying /* size_vmode -- that is the amount of memory needed for the 3707c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * used video mode, i.e. the minimum amount of 3717c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * memory we need. */ 3727c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying size_vmode = efifb_defined.yres * efifb_fix.line_length; 3737c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 3747c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying /* size_total -- all video memory we have. Used for 3757c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * entries, ressource allocation and bounds 3767c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * checking. */ 3777c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying size_total = screen_info.lfb_size; 3787c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (size_total < size_vmode) 3797c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying size_total = size_vmode; 3807c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 3817c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying /* size_remap -- the amount of video memory we are going to 3827c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * use for efifb. With modern cards it is no 3837c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * option to simply use size_total as that 3847c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying * wastes plenty of kernel address space. */ 3857c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying size_remap = size_vmode * 2; 3867c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (size_remap > size_total) 3877c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying size_remap = size_total; 3887c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (size_remap % PAGE_SIZE) 3897c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones size_remap += PAGE_SIZE - (size_remap % PAGE_SIZE); 3907c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.smem_len = size_remap; 3917c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 3927c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (request_mem_region(efifb_fix.smem_start, size_remap, "efifb")) { 393da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirski request_mem_succeeded = true; 3947c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones } else { 3957c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying /* We cannot make this fatal. Sometimes this comes from magic 3967c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying spaces our resource handlers simply don't know about */ 3977c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_WARNING 3987c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying "efifb: cannot reserve video memory at 0x%lx\n", 3997c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.smem_start); 4007c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones } 4017c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4027c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); 4037c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (!info) { 4047c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones printk(KERN_ERR "efifb: cannot allocate framebuffer\n"); 4057c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying err = -ENOMEM; 4067c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying goto err_release_mem; 4077c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying } 4087c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying info->pseudo_palette = info->par; 4097c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying info->par = NULL; 4107c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4111471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz info->apertures = alloc_apertures(1); 4121471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz if (!info->apertures) { 4131471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz err = -ENOMEM; 4141471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz goto err_release_fb; 4151471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz } 4161471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz info->apertures->ranges[0].base = efifb_fix.smem_start; 4171471ca9aa71cd37b6a7476bb6f06a3a8622ea1bdMarcin Slusarz info->apertures->ranges[0].size = size_remap; 4184410f3910947dcea8672280b3adecd53cec4e85eDave Airlie 4193c004b4f7eab239e726c6dde0f6cfca46a96956bAndy Lutomirski info->screen_base = ioremap_wc(efifb_fix.smem_start, efifb_fix.smem_len); 4207c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (!info->screen_base) { 4217c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_ERR "efifb: abort, cannot ioremap video memory " 4227c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying "0x%x @ 0x%lx\n", 4237c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.smem_len, efifb_fix.smem_start); 4247c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying err = -EIO; 4257c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones goto err_release_fb; 4267c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying } 4277c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4287c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_INFO "efifb: framebuffer at 0x%lx, mapped to 0x%p, " 4297c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying "using %dk, total %dk\n", 4307c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.smem_start, info->screen_base, 4317c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying size_remap/1024, size_total/1024); 4327c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_INFO "efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n", 4337c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.xres, efifb_defined.yres, 4347c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.bits_per_pixel, efifb_fix.line_length, 4357c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.pages); 4367c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4377c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.xres_virtual = efifb_defined.xres; 4387c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.yres_virtual = efifb_fix.smem_len / 4397c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.line_length; 4407c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_INFO "efifb: scrolling: redraw\n"); 4417c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.yres_virtual = efifb_defined.yres; 4427c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4437c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying /* some dummy values for timing to make fbset happy */ 4447c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.pixclock = 10000000 / efifb_defined.xres * 4457c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 1000 / efifb_defined.yres; 4467c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.left_margin = (efifb_defined.xres / 8) & 0xf8; 4477c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.hsync_len = (efifb_defined.xres / 8) & 0xf8; 4487c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4497c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.red.offset = screen_info.red_pos; 4507c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.red.length = screen_info.red_size; 4517c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.green.offset = screen_info.green_pos; 4527c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.green.length = screen_info.green_size; 4537c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.blue.offset = screen_info.blue_pos; 4547c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.blue.length = screen_info.blue_size; 4557c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.transp.offset = screen_info.rsvd_pos; 4567c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_defined.transp.length = screen_info.rsvd_size; 4577c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4587c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_INFO "efifb: %s: " 4597c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", 4607c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying "Truecolor", 4617c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.rsvd_size, 4627c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.red_size, 4637c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.green_size, 4647c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.blue_size, 4657c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.rsvd_pos, 4667c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.red_pos, 4677c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.green_pos, 4687c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying screen_info.blue_pos); 4697c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4707c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.ypanstep = 0; 4717c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying efifb_fix.ywrapstep = 0; 4727c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4737c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying info->fbops = &efifb_ops; 4747c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying info->var = efifb_defined; 4757c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying info->fix = efifb_fix; 4764410f3910947dcea8672280b3adecd53cec4e85eDave Airlie info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; 4777c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4787c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { 4797c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones printk(KERN_ERR "efifb: cannot allocate colormap\n"); 4807c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying goto err_unmap; 4817c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying } 4827c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if ((err = register_framebuffer(info)) < 0) { 4837c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones printk(KERN_ERR "efifb: cannot register framebuffer\n"); 4847c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying goto err_fb_dealoc; 4857c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying } 4867c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying printk(KERN_INFO "fb%d: %s frame buffer device\n", 4877c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones info->node, info->fix.id); 4887c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying return 0; 4897c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 4907c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingerr_fb_dealoc: 4917c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying fb_dealloc_cmap(&info->cmap); 4927c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingerr_unmap: 4937c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying iounmap(info->screen_base); 4947c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Joneserr_release_fb: 4957c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying framebuffer_release(info); 4967c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingerr_release_mem: 497da0241f12bf785f74e57ad6d67abdf269216f76bAndy Lutomirski if (request_mem_succeeded) 4987c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones release_mem_region(efifb_fix.smem_start, size_total); 4997c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying return err; 5007c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying} 5017c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 5027c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingstatic struct platform_driver efifb_driver = { 5037c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .driver = { 5047c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .name = "efifb", 5057c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying }, 5067c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying}; 5077c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 5087c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingstatic struct platform_device efifb_device = { 5097c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying .name = "efifb", 5107c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying}; 5117c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 5127c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingstatic int __init efifb_init(void) 5137c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying{ 5147c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying int ret; 5157c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones char *option = NULL; 5167c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 517e14a685dfabf3ceeb366f1db1a22471b8f98a08bBrian Maly dmi_check_system(dmi_system_table); 518e14a685dfabf3ceeb366f1db1a22471b8f98a08bBrian Maly 5197c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) 5207c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying return -ENODEV; 5217c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 5227c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (fb_get_options("efifb", &option)) 5237c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones return -ENODEV; 5247c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones efifb_setup(option); 5257c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones 5267c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones /* We don't get linelength from UGA Draw Protocol, only from 5277c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones * EFI Graphics Protocol. So if it's not in DMI, and it's not 5287c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones * passed in from the user, we really can't use the framebuffer. 5297c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones */ 5307c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones if (!screen_info.lfb_linelength) 5317c08c9ae0c145807c0dae4a55f240fa3d4fd5262Peter Jones return -ENODEV; 5327c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 533bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski ret = platform_device_register(&efifb_device); 534bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski if (ret) 535bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski return ret; 5367c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 537bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski /* 538bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski * This is not just an optimization. We will interfere 539bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski * with a real driver if we get reprobed, so don't allow 540bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski * it. 541bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski */ 542bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski ret = platform_driver_probe(&efifb_driver, efifb_probe); 543bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski if (ret) { 544e6b8480cdf27953c3d13e6e34dd075f8287b02f0Wanlong Gao platform_device_unregister(&efifb_device); 545bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski return ret; 5467c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying } 547bb8b26627267a82c49f47fc52a0785f079a7b063Andy Lutomirski 5487c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying return ret; 5497c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying} 5507c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Yingmodule_init(efifb_init); 5517c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, Ying 5527c83172b98e569d9aabf947d8b3b089dadb2ff46Huang, YingMODULE_LICENSE("GPL"); 553