mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'efi-next-for-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI updates from Ard Biesheuvel: - Quirk the broken EFI framebuffer geometry on the Valve Steam Deck - Capture the EDID information of the primary display also on non-x86 EFI systems when booting via the EFI stub. * tag 'efi-next-for-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: efi: Support EDID information sysfb: Move edid_info into sysfb_primary_display sysfb: Pass sysfb_primary_display to devices sysfb: Replace screen_info with sysfb_primary_display sysfb: Add struct sysfb_display_info efi: sysfb_efi: Reduce number of references to global screen_info efi: earlycon: Reduce number of references to global screen_info efi: sysfb_efi: Fix efidrmfb and simpledrmfb on Valve Steam Deck efi: sysfb_efi: Convert swap width and height quirk to a callback efi: sysfb_efi: Fix lfb_linelength calculation when applying quirks efi: sysfb_efi: Replace open coded swap with the macro
This commit is contained in:
@@ -38,7 +38,7 @@ PROVIDE(__efistub__end = _end);
|
||||
PROVIDE(__efistub___inittext_end = __inittext_end);
|
||||
PROVIDE(__efistub__edata = _edata);
|
||||
#if defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_SYSFB)
|
||||
PROVIDE(__efistub_screen_info = screen_info);
|
||||
PROVIDE(__efistub_sysfb_primary_display = sysfb_primary_display);
|
||||
#endif
|
||||
PROVIDE(__efistub__ctype = _ctype);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/early_ioremap.h>
|
||||
@@ -72,30 +72,31 @@ bool efi_poweroff_required(void)
|
||||
(acpi_gbl_reduced_hardware || acpi_no_s5);
|
||||
}
|
||||
|
||||
unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
|
||||
unsigned long __initdata primary_display_table = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
#if defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON)
|
||||
struct screen_info screen_info __section(".data");
|
||||
EXPORT_SYMBOL_GPL(screen_info);
|
||||
struct sysfb_display_info sysfb_primary_display __section(".data");
|
||||
EXPORT_SYMBOL_GPL(sysfb_primary_display);
|
||||
#endif
|
||||
|
||||
static void __init init_screen_info(void)
|
||||
static void __init init_primary_display(void)
|
||||
{
|
||||
struct screen_info *si;
|
||||
struct sysfb_display_info *dpy;
|
||||
|
||||
if (screen_info_table == EFI_INVALID_TABLE_ADDR)
|
||||
if (primary_display_table == EFI_INVALID_TABLE_ADDR)
|
||||
return;
|
||||
|
||||
si = early_memremap(screen_info_table, sizeof(*si));
|
||||
if (!si) {
|
||||
pr_err("Could not map screen_info config table\n");
|
||||
dpy = early_memremap(primary_display_table, sizeof(*dpy));
|
||||
if (!dpy) {
|
||||
pr_err("Could not map primary_display config table\n");
|
||||
return;
|
||||
}
|
||||
screen_info = *si;
|
||||
memset(si, 0, sizeof(*si));
|
||||
early_memunmap(si, sizeof(*si));
|
||||
sysfb_primary_display = *dpy;
|
||||
memset(dpy, 0, sizeof(*dpy));
|
||||
early_memunmap(dpy, sizeof(*dpy));
|
||||
|
||||
memblock_reserve(__screen_info_lfb_base(&screen_info), screen_info.lfb_size);
|
||||
memblock_reserve(__screen_info_lfb_base(&sysfb_primary_display.screen),
|
||||
sysfb_primary_display.screen.lfb_size);
|
||||
}
|
||||
|
||||
void __init efi_init(void)
|
||||
@@ -129,7 +130,7 @@ void __init efi_init(void)
|
||||
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_EARLYCON) || IS_ENABLED(CONFIG_SYSFB))
|
||||
init_screen_info();
|
||||
init_primary_display();
|
||||
|
||||
if (boot_memmap == EFI_INVALID_TABLE_ADDR)
|
||||
return;
|
||||
|
||||
@@ -12,7 +12,7 @@ __efistub_kernel_entry = kernel_entry;
|
||||
__efistub_kernel_asize = kernel_asize;
|
||||
__efistub_kernel_fsize = kernel_fsize;
|
||||
#if defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_SYSFB)
|
||||
__efistub_screen_info = screen_info;
|
||||
__efistub_sysfb_primary_display = sysfb_primary_display;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@ __efistub__end = _end;
|
||||
__efistub__edata = _edata;
|
||||
__efistub___init_text_end = __init_text_end;
|
||||
#if defined(CONFIG_EFI_EARLYCON) || defined(CONFIG_SYSFB)
|
||||
__efistub_screen_info = screen_info;
|
||||
__efistub_sysfb_primary_display = sysfb_primary_display;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/setup.h>
|
||||
@@ -303,7 +304,8 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
|
||||
params->hdr.hardware_subarch = boot_params.hdr.hardware_subarch;
|
||||
|
||||
/* Copying screen_info will do? */
|
||||
memcpy(¶ms->screen_info, &screen_info, sizeof(struct screen_info));
|
||||
memcpy(¶ms->screen_info, &sysfb_primary_display.screen,
|
||||
sizeof(sysfb_primary_display.screen));
|
||||
|
||||
/* Fill in memsize later */
|
||||
params->screen_info.ext_mem_k = 0;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/static_call.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/swiotlb.h>
|
||||
#include <linux/tboot.h>
|
||||
#include <linux/usb/xhci-dbgp.h>
|
||||
@@ -211,12 +212,9 @@ arch_initcall(init_x86_sysctl);
|
||||
/*
|
||||
* Setup options
|
||||
*/
|
||||
struct screen_info screen_info;
|
||||
EXPORT_SYMBOL(screen_info);
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
struct edid_info edid_info;
|
||||
EXPORT_SYMBOL_GPL(edid_info);
|
||||
#endif
|
||||
|
||||
struct sysfb_display_info sysfb_primary_display;
|
||||
EXPORT_SYMBOL(sysfb_primary_display);
|
||||
|
||||
extern int root_mountflags;
|
||||
|
||||
@@ -526,9 +524,9 @@ static void __init parse_setup_data(void)
|
||||
static void __init parse_boot_params(void)
|
||||
{
|
||||
ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev);
|
||||
screen_info = boot_params.screen_info;
|
||||
sysfb_primary_display.screen = boot_params.screen_info;
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
edid_info = boot_params.edid_info;
|
||||
sysfb_primary_display.edid = boot_params.edid_info;
|
||||
#endif
|
||||
#ifdef CONFIG_X86_32
|
||||
apm_info.bios = boot_params.apm_bios_info;
|
||||
@@ -1254,7 +1252,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
#ifdef CONFIG_VT
|
||||
#if defined(CONFIG_VGA_CONSOLE)
|
||||
if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
|
||||
vgacon_register_screen(&screen_info);
|
||||
vgacon_register_screen(&sysfb_primary_display.screen);
|
||||
#endif
|
||||
#endif
|
||||
x86_init.oem.banner();
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/vgaarb.h>
|
||||
|
||||
#include <asm/video.h>
|
||||
@@ -29,7 +29,7 @@ EXPORT_SYMBOL(pgprot_framebuffer);
|
||||
bool video_is_primary_device(struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_SCREEN_INFO
|
||||
struct screen_info *si = &screen_info;
|
||||
struct screen_info *si = &sysfb_primary_display.screen;
|
||||
struct resource res[SCREEN_INFO_MAX_RESOURCES];
|
||||
ssize_t i, numres;
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/early_ioremap.h>
|
||||
@@ -32,12 +32,13 @@ static void *efi_fb;
|
||||
*/
|
||||
static int __init efi_earlycon_remap_fb(void)
|
||||
{
|
||||
const struct screen_info *si = &sysfb_primary_display.screen;
|
||||
|
||||
/* bail if there is no bootconsole or it was unregistered already */
|
||||
if (!earlycon_console || !console_is_registered(earlycon_console))
|
||||
return 0;
|
||||
|
||||
efi_fb = memremap(fb_base, screen_info.lfb_size,
|
||||
fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
|
||||
efi_fb = memremap(fb_base, si->lfb_size, fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
|
||||
|
||||
return efi_fb ? 0 : -ENOMEM;
|
||||
}
|
||||
@@ -71,12 +72,12 @@ static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
|
||||
early_memunmap(addr, len);
|
||||
}
|
||||
|
||||
static void efi_earlycon_clear_scanline(unsigned int y)
|
||||
static void efi_earlycon_clear_scanline(unsigned int y, const struct screen_info *si)
|
||||
{
|
||||
unsigned long *dst;
|
||||
u16 len;
|
||||
|
||||
len = screen_info.lfb_linelength;
|
||||
len = si->lfb_linelength;
|
||||
dst = efi_earlycon_map(y*len, len);
|
||||
if (!dst)
|
||||
return;
|
||||
@@ -85,7 +86,7 @@ static void efi_earlycon_clear_scanline(unsigned int y)
|
||||
efi_earlycon_unmap(dst, len);
|
||||
}
|
||||
|
||||
static void efi_earlycon_scroll_up(void)
|
||||
static void efi_earlycon_scroll_up(const struct screen_info *si)
|
||||
{
|
||||
unsigned long *dst, *src;
|
||||
u16 maxlen = 0;
|
||||
@@ -99,8 +100,8 @@ static void efi_earlycon_scroll_up(void)
|
||||
}
|
||||
maxlen *= 4;
|
||||
|
||||
len = screen_info.lfb_linelength;
|
||||
height = screen_info.lfb_height;
|
||||
len = si->lfb_linelength;
|
||||
height = si->lfb_height;
|
||||
|
||||
for (i = 0; i < height - font->height; i++) {
|
||||
dst = efi_earlycon_map(i*len, len);
|
||||
@@ -120,7 +121,8 @@ static void efi_earlycon_scroll_up(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h)
|
||||
static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h,
|
||||
const struct screen_info *si)
|
||||
{
|
||||
const u32 color_black = 0x00000000;
|
||||
const u32 color_white = 0x00ffffff;
|
||||
@@ -145,13 +147,12 @@ static void efi_earlycon_write_char(u32 *dst, unsigned char c, unsigned int h)
|
||||
static void
|
||||
efi_earlycon_write(struct console *con, const char *str, unsigned int num)
|
||||
{
|
||||
struct screen_info *si;
|
||||
const struct screen_info *si = &sysfb_primary_display.screen;
|
||||
u32 cur_efi_x = efi_x;
|
||||
unsigned int len;
|
||||
const char *s;
|
||||
void *dst;
|
||||
|
||||
si = &screen_info;
|
||||
len = si->lfb_linelength;
|
||||
|
||||
while (num) {
|
||||
@@ -174,7 +175,7 @@ efi_earlycon_write(struct console *con, const char *str, unsigned int num)
|
||||
x = efi_x;
|
||||
|
||||
while (n-- > 0) {
|
||||
efi_earlycon_write_char(dst + x*4, *s, h);
|
||||
efi_earlycon_write_char(dst + x * 4, *s, h, si);
|
||||
x += font->width;
|
||||
s++;
|
||||
}
|
||||
@@ -207,10 +208,10 @@ efi_earlycon_write(struct console *con, const char *str, unsigned int num)
|
||||
cur_line_y = (cur_line_y + 1) % max_line_y;
|
||||
|
||||
efi_y -= font->height;
|
||||
efi_earlycon_scroll_up();
|
||||
efi_earlycon_scroll_up(si);
|
||||
|
||||
for (i = 0; i < font->height; i++)
|
||||
efi_earlycon_clear_scanline(efi_y + i);
|
||||
efi_earlycon_clear_scanline(efi_y + i, si);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,22 +227,21 @@ void __init efi_earlycon_reprobe(void)
|
||||
static int __init efi_earlycon_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
{
|
||||
struct screen_info *si;
|
||||
const struct screen_info *si = &sysfb_primary_display.screen;
|
||||
u16 xres, yres;
|
||||
u32 i;
|
||||
|
||||
fb_wb = opt && !strcmp(opt, "ram");
|
||||
|
||||
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) {
|
||||
if (si->orig_video_isVGA != VIDEO_TYPE_EFI) {
|
||||
fb_probed = true;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
fb_base = screen_info.lfb_base;
|
||||
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
|
||||
fb_base |= (u64)screen_info.ext_lfb_base << 32;
|
||||
fb_base = si->lfb_base;
|
||||
if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
|
||||
fb_base |= (u64)si->ext_lfb_base << 32;
|
||||
|
||||
si = &screen_info;
|
||||
xres = si->lfb_width;
|
||||
yres = si->lfb_height;
|
||||
|
||||
@@ -266,7 +266,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
|
||||
|
||||
efi_y -= font->height;
|
||||
for (i = 0; i < (yres - efi_y) / font->height; i++)
|
||||
efi_earlycon_scroll_up();
|
||||
efi_earlycon_scroll_up(si);
|
||||
|
||||
device->con->write = efi_earlycon_write;
|
||||
earlycon_console = device->con;
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
|
||||
unsigned long __initdata primary_display_table = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
static int __init is_memory(efi_memory_desc_t *md)
|
||||
{
|
||||
@@ -57,31 +57,31 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
|
||||
extern __weak const efi_config_table_type_t efi_arch_tables[];
|
||||
|
||||
/*
|
||||
* x86 defines its own screen_info and uses it even without EFI,
|
||||
* everything else can get it from here.
|
||||
* x86 defines its own instance of sysfb_primary_display and uses
|
||||
* it even without EFI, everything else can get them from here.
|
||||
*/
|
||||
#if !defined(CONFIG_X86) && (defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON))
|
||||
struct screen_info screen_info __section(".data");
|
||||
EXPORT_SYMBOL_GPL(screen_info);
|
||||
struct sysfb_display_info sysfb_primary_display __section(".data");
|
||||
EXPORT_SYMBOL_GPL(sysfb_primary_display);
|
||||
#endif
|
||||
|
||||
static void __init init_screen_info(void)
|
||||
static void __init init_primary_display(void)
|
||||
{
|
||||
struct screen_info *si;
|
||||
struct sysfb_display_info *dpy;
|
||||
|
||||
if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
|
||||
si = early_memremap(screen_info_table, sizeof(*si));
|
||||
if (!si) {
|
||||
pr_err("Could not map screen_info config table\n");
|
||||
if (primary_display_table != EFI_INVALID_TABLE_ADDR) {
|
||||
dpy = early_memremap(primary_display_table, sizeof(*dpy));
|
||||
if (!dpy) {
|
||||
pr_err("Could not map primary_display config table\n");
|
||||
return;
|
||||
}
|
||||
screen_info = *si;
|
||||
memset(si, 0, sizeof(*si));
|
||||
early_memunmap(si, sizeof(*si));
|
||||
sysfb_primary_display = *dpy;
|
||||
memset(dpy, 0, sizeof(*dpy));
|
||||
early_memunmap(dpy, sizeof(*dpy));
|
||||
|
||||
if (memblock_is_map_memory(screen_info.lfb_base))
|
||||
memblock_mark_nomap(screen_info.lfb_base,
|
||||
screen_info.lfb_size);
|
||||
if (memblock_is_map_memory(sysfb_primary_display.screen.lfb_base))
|
||||
memblock_mark_nomap(sysfb_primary_display.screen.lfb_base,
|
||||
sysfb_primary_display.screen.lfb_size);
|
||||
|
||||
if (IS_ENABLED(CONFIG_EFI_EARLYCON))
|
||||
efi_earlycon_reprobe();
|
||||
@@ -274,5 +274,5 @@ void __init efi_init(void)
|
||||
if (IS_ENABLED(CONFIG_X86) ||
|
||||
IS_ENABLED(CONFIG_SYSFB) ||
|
||||
IS_ENABLED(CONFIG_EFI_EARLYCON))
|
||||
init_screen_info();
|
||||
init_primary_display();
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR;
|
||||
static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR;
|
||||
static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
extern unsigned long screen_info_table;
|
||||
extern unsigned long primary_display_table;
|
||||
|
||||
struct mm_struct efi_mm = {
|
||||
.mm_mt = MTREE_INIT_EXT(mm_mt, MM_MT_FLAGS, efi_mm.mmap_lock),
|
||||
@@ -642,7 +642,7 @@ static const efi_config_table_type_t common_tables[] __initconst = {
|
||||
{LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID, &efi.unaccepted, "Unaccepted" },
|
||||
#endif
|
||||
#ifdef CONFIG_EFI_GENERIC_STUB
|
||||
{LINUX_EFI_SCREEN_INFO_TABLE_GUID, &screen_info_table },
|
||||
{LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID, &primary_display_table },
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
|
||||
$(call if_changed_rule,cc_o_c)
|
||||
|
||||
lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
|
||||
screen_info.o efi-stub-entry.o
|
||||
primary_display.o efi-stub-entry.o
|
||||
|
||||
lib-$(CONFIG_ARM) += arm32-stub.o
|
||||
lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
static unsigned long screen_info_offset;
|
||||
static unsigned long kernel_image_offset;
|
||||
|
||||
struct screen_info *alloc_screen_info(void)
|
||||
static void *kernel_image_addr(void *addr)
|
||||
{
|
||||
return addr + kernel_image_offset;
|
||||
}
|
||||
|
||||
struct sysfb_display_info *alloc_primary_display(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ARM))
|
||||
return __alloc_screen_info();
|
||||
return __alloc_primary_display();
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86) ||
|
||||
IS_ENABLED(CONFIG_EFI_EARLYCON) ||
|
||||
IS_ENABLED(CONFIG_SYSFB))
|
||||
return (void *)&screen_info + screen_info_offset;
|
||||
return kernel_image_addr(&sysfb_primary_display);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -73,7 +78,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
return status;
|
||||
}
|
||||
|
||||
screen_info_offset = image_addr - (unsigned long)image->image_base;
|
||||
kernel_image_offset = image_addr - (unsigned long)image->image_base;
|
||||
|
||||
status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
@@ -48,23 +48,33 @@
|
||||
static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
|
||||
static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
|
||||
|
||||
void __weak free_screen_info(struct screen_info *si)
|
||||
void __weak free_primary_display(struct sysfb_display_info *dpy)
|
||||
{ }
|
||||
|
||||
static struct sysfb_display_info *setup_primary_display(void)
|
||||
{
|
||||
}
|
||||
struct sysfb_display_info *dpy;
|
||||
struct screen_info *screen = NULL;
|
||||
struct edid_info *edid = NULL;
|
||||
efi_status_t status;
|
||||
|
||||
static struct screen_info *setup_graphics(void)
|
||||
{
|
||||
struct screen_info *si, tmp = {};
|
||||
|
||||
if (efi_setup_graphics(&tmp, NULL) != EFI_SUCCESS)
|
||||
dpy = alloc_primary_display();
|
||||
if (!dpy)
|
||||
return NULL;
|
||||
screen = &dpy->screen;
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
edid = &dpy->edid;
|
||||
#endif
|
||||
|
||||
si = alloc_screen_info();
|
||||
if (!si)
|
||||
return NULL;
|
||||
status = efi_setup_graphics(screen, edid);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto err_free_primary_display;
|
||||
|
||||
*si = tmp;
|
||||
return si;
|
||||
return dpy;
|
||||
|
||||
err_free_primary_display:
|
||||
free_primary_display(dpy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void install_memreserve_table(void)
|
||||
@@ -145,14 +155,14 @@ efi_status_t efi_stub_common(efi_handle_t handle,
|
||||
unsigned long image_addr,
|
||||
char *cmdline_ptr)
|
||||
{
|
||||
struct screen_info *si;
|
||||
struct sysfb_display_info *dpy;
|
||||
efi_status_t status;
|
||||
|
||||
status = check_platform_features();
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
si = setup_graphics();
|
||||
dpy = setup_primary_display();
|
||||
|
||||
efi_retrieve_eventlog();
|
||||
|
||||
@@ -172,7 +182,8 @@ efi_status_t efi_stub_common(efi_handle_t handle,
|
||||
|
||||
status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
|
||||
|
||||
free_screen_info(si);
|
||||
free_primary_display(dpy);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
struct edid_info;
|
||||
struct screen_info;
|
||||
struct sysfb_display_info;
|
||||
|
||||
extern bool efi_no5lvl;
|
||||
extern bool efi_nochunk;
|
||||
@@ -1175,9 +1176,9 @@ efi_enable_reset_attack_mitigation(void) { }
|
||||
|
||||
void efi_retrieve_eventlog(void);
|
||||
|
||||
struct screen_info *alloc_screen_info(void);
|
||||
struct screen_info *__alloc_screen_info(void);
|
||||
void free_screen_info(struct screen_info *si);
|
||||
struct sysfb_display_info *alloc_primary_display(void);
|
||||
struct sysfb_display_info *__alloc_primary_display(void);
|
||||
void free_primary_display(struct sysfb_display_info *dpy);
|
||||
|
||||
void efi_cache_sync_image(unsigned long image_base,
|
||||
unsigned long alloc_size);
|
||||
|
||||
56
drivers/firmware/efi/libstub/primary_display.c
Normal file
56
drivers/firmware/efi/libstub/primary_display.c
Normal file
@@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
/*
|
||||
* There are two ways of populating the core kernel's sysfb_primary_display
|
||||
* via the stub:
|
||||
*
|
||||
* - using a configuration table, which relies on the EFI init code to
|
||||
* locate the table and copy the contents; or
|
||||
*
|
||||
* - by linking directly to the core kernel's copy of the global symbol.
|
||||
*
|
||||
* The latter is preferred because it makes the EFIFB earlycon available very
|
||||
* early, but it only works if the EFI stub is part of the core kernel image
|
||||
* itself. The zboot decompressor can only use the configuration table
|
||||
* approach.
|
||||
*/
|
||||
|
||||
static efi_guid_t primary_display_guid = LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID;
|
||||
|
||||
struct sysfb_display_info *__alloc_primary_display(void)
|
||||
{
|
||||
struct sysfb_display_info *dpy;
|
||||
efi_status_t status;
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
|
||||
sizeof(*dpy), (void **)&dpy);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
memset(dpy, 0, sizeof(*dpy));
|
||||
|
||||
status = efi_bs_call(install_configuration_table,
|
||||
&primary_display_guid, dpy);
|
||||
if (status == EFI_SUCCESS)
|
||||
return dpy;
|
||||
|
||||
efi_bs_call(free_pool, dpy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_primary_display(struct sysfb_display_info *dpy)
|
||||
{
|
||||
if (!dpy)
|
||||
return;
|
||||
|
||||
efi_bs_call(install_configuration_table, &primary_display_guid, NULL);
|
||||
efi_bs_call(free_pool, dpy);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/screen_info.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
/*
|
||||
* There are two ways of populating the core kernel's struct screen_info via the stub:
|
||||
* - using a configuration table, like below, which relies on the EFI init code
|
||||
* to locate the table and copy the contents;
|
||||
* - by linking directly to the core kernel's copy of the global symbol.
|
||||
*
|
||||
* The latter is preferred because it makes the EFIFB earlycon available very
|
||||
* early, but it only works if the EFI stub is part of the core kernel image
|
||||
* itself. The zboot decompressor can only use the configuration table
|
||||
* approach.
|
||||
*/
|
||||
|
||||
static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID;
|
||||
|
||||
struct screen_info *__alloc_screen_info(void)
|
||||
{
|
||||
struct screen_info *si;
|
||||
efi_status_t status;
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
|
||||
sizeof(*si), (void **)&si);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
memset(si, 0, sizeof(*si));
|
||||
|
||||
status = efi_bs_call(install_configuration_table,
|
||||
&screen_info_guid, si);
|
||||
if (status == EFI_SUCCESS)
|
||||
return si;
|
||||
|
||||
efi_bs_call(free_pool, si);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_screen_info(struct screen_info *si)
|
||||
{
|
||||
if (!si)
|
||||
return;
|
||||
|
||||
efi_bs_call(install_configuration_table, &screen_info_guid, NULL);
|
||||
efi_bs_call(free_pool, si);
|
||||
}
|
||||
@@ -26,9 +26,9 @@ void __weak efi_cache_sync_image(unsigned long image_base,
|
||||
// executable code loaded into memory to be safe for execution.
|
||||
}
|
||||
|
||||
struct screen_info *alloc_screen_info(void)
|
||||
struct sysfb_display_info *alloc_primary_display(void)
|
||||
{
|
||||
return __alloc_screen_info();
|
||||
return __alloc_primary_display();
|
||||
}
|
||||
|
||||
asmlinkage efi_status_t __efiapi
|
||||
|
||||
@@ -92,7 +92,7 @@ void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
|
||||
})
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
static int __init efifb_set_system(const struct dmi_system_id *id)
|
||||
static int __init efifb_set_system(struct screen_info *si, const struct dmi_system_id *id)
|
||||
{
|
||||
struct efifb_dmi_info *info = id->driver_data;
|
||||
|
||||
@@ -101,14 +101,14 @@ static int __init efifb_set_system(const struct dmi_system_id *id)
|
||||
return 0;
|
||||
|
||||
/* Trust the bootloader over the DMI tables */
|
||||
if (screen_info.lfb_base == 0) {
|
||||
if (si->lfb_base == 0) {
|
||||
#if defined(CONFIG_PCI)
|
||||
struct pci_dev *dev = NULL;
|
||||
int found_bar = 0;
|
||||
#endif
|
||||
if (info->base) {
|
||||
screen_info.lfb_base = choose_value(info->base,
|
||||
screen_info.lfb_base, OVERRIDE_BASE,
|
||||
si->lfb_base = choose_value(info->base,
|
||||
si->lfb_base, OVERRIDE_BASE,
|
||||
info->flags);
|
||||
|
||||
#if defined(CONFIG_PCI)
|
||||
@@ -135,49 +135,53 @@ static int __init efifb_set_system(const struct dmi_system_id *id)
|
||||
|
||||
start = pci_resource_start(dev, i);
|
||||
end = pci_resource_end(dev, i);
|
||||
if (screen_info.lfb_base >= start &&
|
||||
screen_info.lfb_base < end) {
|
||||
if (si->lfb_base >= start && si->lfb_base < end) {
|
||||
found_bar = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found_bar)
|
||||
screen_info.lfb_base = 0;
|
||||
si->lfb_base = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (screen_info.lfb_base) {
|
||||
screen_info.lfb_linelength = choose_value(info->stride,
|
||||
screen_info.lfb_linelength, OVERRIDE_STRIDE,
|
||||
if (si->lfb_base) {
|
||||
si->lfb_linelength = choose_value(info->stride,
|
||||
si->lfb_linelength, OVERRIDE_STRIDE,
|
||||
info->flags);
|
||||
screen_info.lfb_width = choose_value(info->width,
|
||||
screen_info.lfb_width, OVERRIDE_WIDTH,
|
||||
si->lfb_width = choose_value(info->width,
|
||||
si->lfb_width, OVERRIDE_WIDTH,
|
||||
info->flags);
|
||||
screen_info.lfb_height = choose_value(info->height,
|
||||
screen_info.lfb_height, OVERRIDE_HEIGHT,
|
||||
si->lfb_height = choose_value(info->height,
|
||||
si->lfb_height, OVERRIDE_HEIGHT,
|
||||
info->flags);
|
||||
if (screen_info.orig_video_isVGA == 0)
|
||||
screen_info.orig_video_isVGA = VIDEO_TYPE_EFI;
|
||||
if (si->orig_video_isVGA == 0)
|
||||
si->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;
|
||||
si->lfb_linelength = 0;
|
||||
si->lfb_width = 0;
|
||||
si->lfb_height = 0;
|
||||
si->orig_video_isVGA = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "efifb: dmi detected %s - framebuffer at 0x%08x "
|
||||
"(%dx%d, stride %d)\n", id->ident,
|
||||
screen_info.lfb_base, screen_info.lfb_width,
|
||||
screen_info.lfb_height, screen_info.lfb_linelength);
|
||||
si->lfb_base, si->lfb_width,
|
||||
si->lfb_height, si->lfb_linelength);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init efifb_set_system_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
return efifb_set_system(&sysfb_primary_display.screen, id);
|
||||
}
|
||||
|
||||
#define EFIFB_DMI_SYSTEM_ID(vendor, name, enumid) \
|
||||
{ \
|
||||
efifb_set_system, \
|
||||
efifb_set_system_callback, \
|
||||
name, \
|
||||
{ \
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, vendor), \
|
||||
@@ -231,6 +235,44 @@ static const struct dmi_system_id efifb_dmi_system_table[] __initconst = {
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init efifb_swap_width_height(const struct dmi_system_id *id)
|
||||
{
|
||||
struct screen_info *si = &sysfb_primary_display.screen;
|
||||
u32 bpp = __screen_info_lfb_bits_per_pixel(si);
|
||||
|
||||
swap(si->lfb_width, si->lfb_height);
|
||||
si->lfb_linelength = bpp * si->lfb_width / BITS_PER_BYTE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct efifb_mode_fixup {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int linelength;
|
||||
};
|
||||
|
||||
static int __init
|
||||
efifb_check_and_swap_width_height(const struct dmi_system_id *id)
|
||||
{
|
||||
const struct efifb_mode_fixup *data = id->driver_data;
|
||||
struct screen_info *si = &sysfb_primary_display.screen;
|
||||
|
||||
if (data->width == si->lfb_width && data->height == si->lfb_height) {
|
||||
swap(si->lfb_width, si->lfb_height);
|
||||
si->lfb_linelength = data->linelength;
|
||||
si->lfb_size = data->linelength * data->width;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct efifb_mode_fixup efifb_steamdeck_mode_fixup __initconst = {
|
||||
.width = 1280,
|
||||
.height = 800,
|
||||
.linelength = 3328,
|
||||
};
|
||||
|
||||
/*
|
||||
* Some devices have a portrait LCD but advertise a landscape resolution (and
|
||||
* pitch). We simply swap width and height for these devices so that we can
|
||||
@@ -248,6 +290,7 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
|
||||
DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1HCN44WW"),
|
||||
},
|
||||
.callback = efifb_swap_width_height,
|
||||
},
|
||||
{
|
||||
/* Lenovo MIIX 320-10ICR with 800x1280 portrait screen */
|
||||
@@ -256,6 +299,7 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
|
||||
"Lenovo MIIX 320-10ICR"),
|
||||
},
|
||||
.callback = efifb_swap_width_height,
|
||||
},
|
||||
{
|
||||
/* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */
|
||||
@@ -264,6 +308,7 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
|
||||
"Lenovo ideapad D330-10IGM"),
|
||||
},
|
||||
.callback = efifb_swap_width_height,
|
||||
},
|
||||
{
|
||||
/* Lenovo IdeaPad Duet 3 10IGL5 with 1200x1920 portrait screen */
|
||||
@@ -272,6 +317,7 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
|
||||
"IdeaPad Duet 3 10IGL5"),
|
||||
},
|
||||
.callback = efifb_swap_width_height,
|
||||
},
|
||||
{
|
||||
/* Lenovo Yoga Book X91F / X91L */
|
||||
@@ -280,16 +326,38 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
|
||||
/* Non exact match to match F + L versions */
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
|
||||
},
|
||||
.callback = efifb_swap_width_height,
|
||||
},
|
||||
{
|
||||
/* Valve Steam Deck (Jupiter) */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
|
||||
},
|
||||
.callback = efifb_check_and_swap_width_height,
|
||||
.driver_data = (void *)&efifb_steamdeck_mode_fixup,
|
||||
},
|
||||
{
|
||||
/* Valve Steam Deck (Galileo) */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
|
||||
},
|
||||
.callback = efifb_check_and_swap_width_height,
|
||||
.driver_data = (void *)&efifb_steamdeck_mode_fixup,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
|
||||
static bool efifb_overlaps_pci_range(const struct screen_info *si,
|
||||
const struct of_pci_range *range)
|
||||
{
|
||||
u64 fb_base = screen_info.lfb_base;
|
||||
u64 fb_base = si->lfb_base;
|
||||
|
||||
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
|
||||
fb_base |= (u64)(unsigned long)screen_info.ext_lfb_base << 32;
|
||||
if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
|
||||
fb_base |= (u64)(unsigned long)si->ext_lfb_base << 32;
|
||||
|
||||
return fb_base >= range->cpu_addr &&
|
||||
fb_base < (range->cpu_addr + range->size);
|
||||
@@ -311,7 +379,7 @@ static struct device_node *find_pci_overlap_node(void)
|
||||
}
|
||||
|
||||
for_each_of_pci_range(&parser, &range)
|
||||
if (efifb_overlaps_pci_range(&range))
|
||||
if (efifb_overlaps_pci_range(&sysfb_primary_display.screen, &range))
|
||||
return np;
|
||||
}
|
||||
return NULL;
|
||||
@@ -349,25 +417,19 @@ static const struct fwnode_operations efifb_fwnode_ops = {
|
||||
|
||||
static struct fwnode_handle efifb_fwnode;
|
||||
|
||||
__init void sysfb_apply_efi_quirks(void)
|
||||
__init void sysfb_apply_efi_quirks(struct screen_info *si)
|
||||
{
|
||||
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
|
||||
!(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
|
||||
if (si->orig_video_isVGA != VIDEO_TYPE_EFI ||
|
||||
!(si->capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
|
||||
dmi_check_system(efifb_dmi_system_table);
|
||||
|
||||
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI &&
|
||||
dmi_check_system(efifb_dmi_swap_width_height)) {
|
||||
u16 temp = screen_info.lfb_width;
|
||||
|
||||
screen_info.lfb_width = screen_info.lfb_height;
|
||||
screen_info.lfb_height = temp;
|
||||
screen_info.lfb_linelength = 4 * screen_info.lfb_width;
|
||||
}
|
||||
if (si->orig_video_isVGA == VIDEO_TYPE_EFI)
|
||||
dmi_check_system(efifb_dmi_swap_width_height);
|
||||
}
|
||||
|
||||
__init void sysfb_set_efifb_fwnode(struct platform_device *pd)
|
||||
__init void sysfb_set_efifb_fwnode(const struct screen_info *si, struct platform_device *pd)
|
||||
{
|
||||
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
|
||||
if (si->orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
|
||||
fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
|
||||
pd->dev.fwnode = &efifb_fwnode;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ static bool sysfb_unregister(void)
|
||||
*/
|
||||
void sysfb_disable(struct device *dev)
|
||||
{
|
||||
struct screen_info *si = &screen_info;
|
||||
struct screen_info *si = &sysfb_primary_display.screen;
|
||||
struct device *parent;
|
||||
|
||||
mutex_lock(&disable_lock);
|
||||
@@ -92,7 +92,7 @@ EXPORT_SYMBOL_GPL(sysfb_disable);
|
||||
*/
|
||||
bool sysfb_handles_screen_info(void)
|
||||
{
|
||||
const struct screen_info *si = &screen_info;
|
||||
const struct screen_info *si = &sysfb_primary_display.screen;
|
||||
|
||||
return !!screen_info_video_type(si);
|
||||
}
|
||||
@@ -141,7 +141,8 @@ static struct device *sysfb_parent_dev(const struct screen_info *si)
|
||||
|
||||
static __init int sysfb_init(void)
|
||||
{
|
||||
struct screen_info *si = &screen_info;
|
||||
struct sysfb_display_info *dpy = &sysfb_primary_display;
|
||||
struct screen_info *si = &dpy->screen;
|
||||
struct device *parent;
|
||||
unsigned int type;
|
||||
struct simplefb_platform_data mode;
|
||||
@@ -155,7 +156,7 @@ static __init int sysfb_init(void)
|
||||
if (disabled)
|
||||
goto unlock_mutex;
|
||||
|
||||
sysfb_apply_efi_quirks();
|
||||
sysfb_apply_efi_quirks(si);
|
||||
|
||||
parent = sysfb_parent_dev(si);
|
||||
if (IS_ERR(parent)) {
|
||||
@@ -200,9 +201,9 @@ static __init int sysfb_init(void)
|
||||
|
||||
pd->dev.parent = parent;
|
||||
|
||||
sysfb_set_efifb_fwnode(pd);
|
||||
sysfb_set_efifb_fwnode(si, pd);
|
||||
|
||||
ret = platform_device_add_data(pd, si, sizeof(*si));
|
||||
ret = platform_device_add_data(pd, dpy, sizeof(*dpy));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ __init struct platform_device *sysfb_create_simplefb(const struct screen_info *s
|
||||
|
||||
pd->dev.parent = parent;
|
||||
|
||||
sysfb_set_efifb_fwnode(pd);
|
||||
sysfb_set_efifb_fwnode(si, pd);
|
||||
|
||||
ret = platform_device_add_resources(pd, &res, 1);
|
||||
if (ret)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <linux/efi.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <drm/clients/drm_client_setup.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include <video/edid.h>
|
||||
#include <video/pixel_format.h>
|
||||
|
||||
#include "drm_sysfb_helper.h"
|
||||
@@ -141,6 +140,7 @@ static const struct drm_mode_config_funcs efidrm_mode_config_funcs = {
|
||||
static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
const struct sysfb_display_info *dpy;
|
||||
const struct screen_info *si;
|
||||
const struct drm_format_info *format;
|
||||
int width, height, stride;
|
||||
@@ -160,9 +160,11 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
|
||||
size_t nformats;
|
||||
int ret;
|
||||
|
||||
si = dev_get_platdata(&pdev->dev);
|
||||
if (!si)
|
||||
dpy = dev_get_platdata(&pdev->dev);
|
||||
if (!dpy)
|
||||
return ERR_PTR(-ENODEV);
|
||||
si = &dpy->screen;
|
||||
|
||||
if (screen_info_video_type(si) != VIDEO_TYPE_EFI)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -204,8 +206,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
|
||||
&format->format, width, height, stride);
|
||||
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
if (drm_edid_header_is_valid(edid_info.dummy) == 8)
|
||||
sysfb->edid = edid_info.dummy;
|
||||
if (drm_edid_header_is_valid(dpy->edid.dummy) == 8)
|
||||
sysfb->edid = dpy->edid.dummy;
|
||||
#endif
|
||||
sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0);
|
||||
sysfb->fb_format = format;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <drm/clients/drm_client_setup.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include <video/edid.h>
|
||||
#include <video/pixel_format.h>
|
||||
#include <video/vga.h>
|
||||
|
||||
@@ -391,6 +390,7 @@ static const struct drm_mode_config_funcs vesadrm_mode_config_funcs = {
|
||||
static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
const struct sysfb_display_info *dpy;
|
||||
const struct screen_info *si;
|
||||
const struct drm_format_info *format;
|
||||
int width, height, stride;
|
||||
@@ -410,9 +410,11 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
|
||||
size_t nformats;
|
||||
int ret;
|
||||
|
||||
si = dev_get_platdata(&pdev->dev);
|
||||
if (!si)
|
||||
dpy = dev_get_platdata(&pdev->dev);
|
||||
if (!dpy)
|
||||
return ERR_PTR(-ENODEV);
|
||||
si = &dpy->screen;
|
||||
|
||||
if (screen_info_video_type(si) != VIDEO_TYPE_VLFB)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -471,8 +473,8 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv,
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
if (drm_edid_header_is_valid(edid_info.dummy) == 8)
|
||||
sysfb->edid = edid_info.dummy;
|
||||
if (drm_edid_header_is_valid(dpy->edid.dummy) == 8)
|
||||
sysfb->edid = dpy->edid.dummy;
|
||||
#endif
|
||||
sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0);
|
||||
sysfb->fb_format = format;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/panic_notifier.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -2340,8 +2340,8 @@ static void __maybe_unused vmbus_reserve_fb(void)
|
||||
if (efi_enabled(EFI_BOOT)) {
|
||||
/* Gen2 VM: get FB base from EFI framebuffer */
|
||||
if (IS_ENABLED(CONFIG_SYSFB)) {
|
||||
start = screen_info.lfb_base;
|
||||
size = max_t(__u32, screen_info.lfb_size, 0x800000);
|
||||
start = sysfb_primary_display.screen.lfb_base;
|
||||
size = max_t(__u32, sysfb_primary_display.screen.lfb_size, 0x800000);
|
||||
}
|
||||
} else {
|
||||
/* Gen1 VM: get FB base from PCI */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/acpi.h>
|
||||
@@ -557,7 +557,7 @@ EXPORT_SYMBOL(vga_put);
|
||||
static bool vga_is_firmware_default(struct pci_dev *pdev)
|
||||
{
|
||||
#if defined CONFIG_X86
|
||||
return pdev == screen_info_pci_dev(&screen_info);
|
||||
return pdev == screen_info_pci_dev(&sysfb_primary_display.screen);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -63,11 +63,13 @@ endif # HAS_IOMEM
|
||||
|
||||
config FIRMWARE_EDID
|
||||
bool "Enable firmware EDID"
|
||||
depends on X86
|
||||
depends on EFI_GENERIC_STUB || X86
|
||||
help
|
||||
This enables access to the EDID transferred from the firmware.
|
||||
On x86, this is from the VESA BIOS. DRM display drivers will
|
||||
be able to export the information to userspace.
|
||||
On EFI systems, the EDID comes from the same device as the
|
||||
primary GOP. On x86 with BIOS, it comes from the VESA BIOS.
|
||||
DRM display drivers will be able to export the information
|
||||
to userspace.
|
||||
|
||||
Also enable this if DDC/I2C transfers do not work for your driver
|
||||
and if you are using nvidiafb, i810fb or savagefb.
|
||||
|
||||
@@ -32,11 +32,13 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <video/edid.h>
|
||||
#include <linux/string_choices.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <video/of_videomode.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include "../edid.h"
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
/*
|
||||
* EDID parser
|
||||
@@ -1504,7 +1506,7 @@ const unsigned char *fb_firmware_edid(struct device *device)
|
||||
res = &dev->resource[PCI_ROM_RESOURCE];
|
||||
|
||||
if (res && res->flags & IORESOURCE_ROM_SHADOW)
|
||||
edid = edid_info.dummy;
|
||||
edid = sysfb_primary_display.edid.dummy;
|
||||
|
||||
return edid;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <linux/fb.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <video/vga.h>
|
||||
#include <asm/efi.h>
|
||||
#include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */
|
||||
@@ -345,6 +345,7 @@ ATTRIBUTE_GROUPS(efifb);
|
||||
|
||||
static int efifb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct sysfb_display_info *dpy;
|
||||
struct screen_info *si;
|
||||
struct fb_info *info;
|
||||
struct efifb_par *par;
|
||||
@@ -360,10 +361,11 @@ static int efifb_probe(struct platform_device *dev)
|
||||
* driver. We get a copy of the attached screen_info, so that we can
|
||||
* modify its values without affecting later drivers.
|
||||
*/
|
||||
si = dev_get_platdata(&dev->dev);
|
||||
if (!si)
|
||||
dpy = dev_get_platdata(&dev->dev);
|
||||
if (!dpy)
|
||||
return -ENODEV;
|
||||
si = devm_kmemdup(&dev->dev, si, sizeof(*si), GFP_KERNEL);
|
||||
|
||||
si = devm_kmemdup(&dev->dev, &dpy->screen, sizeof(*si), GFP_KERNEL);
|
||||
if (!si)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <video/vga.h>
|
||||
@@ -243,6 +243,7 @@ static int vesafb_setup(char *options)
|
||||
|
||||
static int vesafb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct sysfb_display_info *dpy;
|
||||
struct screen_info *si;
|
||||
struct fb_info *info;
|
||||
struct vesafb_par *par;
|
||||
@@ -257,10 +258,11 @@ static int vesafb_probe(struct platform_device *dev)
|
||||
* driver. We get a copy of the attached screen_info, so that we can
|
||||
* modify its values without affecting later drivers.
|
||||
*/
|
||||
si = dev_get_platdata(&dev->dev);
|
||||
if (!si)
|
||||
dpy = dev_get_platdata(&dev->dev);
|
||||
if (!dpy)
|
||||
return -ENODEV;
|
||||
si = devm_kmemdup(&dev->dev, si, sizeof(*si), GFP_KERNEL);
|
||||
|
||||
si = devm_kmemdup(&dev->dev, &dpy->screen, sizeof(*si), GFP_KERNEL);
|
||||
if (!si)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <video/vga.h>
|
||||
@@ -1305,15 +1305,17 @@ static const struct fb_ops vga16fb_ops = {
|
||||
|
||||
static int vga16fb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct sysfb_display_info *dpy;
|
||||
struct screen_info *si;
|
||||
struct fb_info *info;
|
||||
struct vga16fb_par *par;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
si = dev_get_platdata(&dev->dev);
|
||||
if (!si)
|
||||
dpy = dev_get_platdata(&dev->dev);
|
||||
if (!dpy)
|
||||
return -ENODEV;
|
||||
si = &dpy->screen;
|
||||
|
||||
ret = check_mode_supported(si);
|
||||
if (ret)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <linux/printk.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfb.h>
|
||||
|
||||
static struct pci_dev *screen_info_lfb_pdev;
|
||||
static size_t screen_info_lfb_bar;
|
||||
@@ -26,7 +27,7 @@ static bool __screen_info_relocation_is_valid(const struct screen_info *si, stru
|
||||
|
||||
void screen_info_apply_fixups(void)
|
||||
{
|
||||
struct screen_info *si = &screen_info;
|
||||
struct screen_info *si = &sysfb_primary_display.screen;
|
||||
|
||||
if (screen_info_lfb_pdev) {
|
||||
struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
|
||||
@@ -75,7 +76,7 @@ static void screen_info_fixup_lfb(struct pci_dev *pdev)
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
const struct resource *pr;
|
||||
const struct screen_info *si = &screen_info;
|
||||
const struct screen_info *si = &sysfb_primary_display.screen;
|
||||
|
||||
if (screen_info_lfb_pdev)
|
||||
return; // already found
|
||||
|
||||
@@ -406,11 +406,12 @@ void efi_native_runtime_setup(void);
|
||||
#define EFI_CC_FINAL_EVENTS_TABLE_GUID EFI_GUID(0xdd4a4648, 0x2de7, 0x4665, 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46)
|
||||
|
||||
/*
|
||||
* This GUID is used to pass to the kernel proper the struct screen_info
|
||||
* structure that was populated by the stub based on the GOP protocol instance
|
||||
* associated with ConOut
|
||||
* This GUIDs are used to pass to the kernel proper the primary
|
||||
* display that has been populated by the stub based on the GOP
|
||||
* instance associated with ConOut.
|
||||
*/
|
||||
#define LINUX_EFI_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
|
||||
#define LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
|
||||
|
||||
#define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989, 0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2)
|
||||
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
|
||||
#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
|
||||
|
||||
@@ -151,6 +151,4 @@ static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
|
||||
}
|
||||
#endif
|
||||
|
||||
extern struct screen_info screen_info;
|
||||
|
||||
#endif /* _SCREEN_INFO_H */
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_data/simplefb.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/platform_data/simplefb.h>
|
||||
#include <video/edid.h>
|
||||
|
||||
struct device;
|
||||
struct platform_device;
|
||||
@@ -60,6 +62,16 @@ struct efifb_dmi_info {
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct sysfb_display_info {
|
||||
struct screen_info screen;
|
||||
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
struct edid_info edid;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct sysfb_display_info sysfb_primary_display;
|
||||
|
||||
#ifdef CONFIG_SYSFB
|
||||
|
||||
void sysfb_disable(struct device *dev);
|
||||
@@ -82,16 +94,17 @@ static inline bool sysfb_handles_screen_info(void)
|
||||
#ifdef CONFIG_EFI
|
||||
|
||||
extern struct efifb_dmi_info efifb_dmi_list[];
|
||||
void sysfb_apply_efi_quirks(void);
|
||||
void sysfb_set_efifb_fwnode(struct platform_device *pd);
|
||||
void sysfb_apply_efi_quirks(struct screen_info *si);
|
||||
void sysfb_set_efifb_fwnode(const struct screen_info *si, struct platform_device *pd);
|
||||
|
||||
#else /* CONFIG_EFI */
|
||||
|
||||
static inline void sysfb_apply_efi_quirks(void)
|
||||
static inline void sysfb_apply_efi_quirks(struct screen_info *si)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void sysfb_set_efifb_fwnode(struct platform_device *pd)
|
||||
static inline void sysfb_set_efifb_fwnode(const struct screen_info *si,
|
||||
struct platform_device *pd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,4 @@
|
||||
|
||||
#include <uapi/video/edid.h>
|
||||
|
||||
#if defined(CONFIG_FIRMWARE_EDID)
|
||||
extern struct edid_info edid_info;
|
||||
#endif
|
||||
|
||||
#endif /* __linux_video_edid_h__ */
|
||||
|
||||
Reference in New Issue
Block a user