From: David Herrmann <dh.herrmann@gmail.com> To: dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org, Dave Airlie <airlied@gmail.com>, linux-fbdev@vger.kernel.org, Stephen Warren <swarren@nvidia.com>, Olof Johansson <olof@lixom.net>, David Herrmann <dh.herrmann@gmail.com> Subject: [RFC 2/6] x86: provide platform-devices for boot-framebuffers Date: Tue, 25 Jun 2013 00:27:25 +0200 [thread overview] Message-ID: <1372112849-670-3-git-send-email-dh.herrmann@gmail.com> (raw) In-Reply-To: <1372112849-670-1-git-send-email-dh.herrmann@gmail.com> The current situation regarding boot-framebuffers (VGA, VESA/VBE, EFI) on x86 causes troubles when loading multiple fbdev drivers. The global "struct screen_info" does not provide any state-tracking about which drivers use the FBs. request_mem_region() theoretically works, but unfortunately vesafb/efifb ignore it due to quirks for broken boards. Avoid this by creating a "platform-framebuffer" device with a pointer to the "struct screen_info" as platform-data. Drivers can now create platform-drivers and the driver-core will refuse multiple drivers being active simultaneously. We keep the screen_info available for backwards-compatibility. Drivers can be converted in follow-up patches. Apart from "platform-framebuffer" devices, this also introduces a compatibility option for "simple-framebuffer" drivers which recently got introduced for OF based systems. If CONFIG_X86_SYSFB is selected, we try to match the screen_info against a simple-framebuffer supported format. If we succeed, we create a "simple-framebuffer" device instead of a platform-framebuffer. This allows to reuse the simplefb.c driver across architectures and also to introduce a SimpleDRM driver. There is no need to have vesafb.c, efifb.c, simplefb.c and more just to have architecture specific quirks in their setup-routines. Instead, we now move the architecture specific quirks into x86-setup and provide a generic simple-framebuffer. For backwards-compatibility (if strange formats are used), we still allow vesafb/efifb to be loaded simultaneously and pick up all remaining devices. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> --- arch/x86/Kconfig | 18 ++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/sysfb.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 arch/x86/kernel/sysfb.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fe120da..8eb06b5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2255,6 +2255,24 @@ config RAPIDIO source "drivers/rapidio/Kconfig" +config X86_SYSFB + bool "Mark VGA/VBE/EFI FB as generic system framebuffer" + help + Firmwares often provide initial graphics framebuffers so the BIOS, + bootloader or kernel can show basic video-output during boot for + user-guidance and debugging. Historically, x86 used the VESA BIOS + Extensions and EFI-framebuffers for this, which are mostly limited + to x86. However, a generic system-framebuffer initialization emerged + recently on some non-x86 architectures. + This option, if enabled, marks VGA/VBE/EFI framebuffers as generic + framebuffers so the new generic system-framebuffer drivers can be + used on x86. + + This breaks any x86-only driver like efifb, vesafb, uvesafb, which + will not work if this is selected. + + If unsure, say N. + endmenu diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 7bd3bd3..1e1005a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o +obj-y += sysfb.o obj-$(CONFIG_PERF_EVENTS) += perf_regs.o diff --git a/arch/x86/kernel/sysfb.c b/arch/x86/kernel/sysfb.c new file mode 100644 index 0000000..8272958 --- /dev/null +++ b/arch/x86/kernel/sysfb.c @@ -0,0 +1,157 @@ +/* + * Generic System Framebuffers on x86 + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* + * Simple-Framebuffer support for x86 systems + * Create a platform-device for any available boot framebuffer. The + * simple-framebuffer platform device is already available on DT systems, so + * this module parses the global "screen_info" object and creates a suitable + * platform device compatible with the "simple-framebuffer" DT object. If + * the framebuffer is incompatible, we instead create a "platform-framebuffer" + * device and pass the screen_info as platform_data. This allows legacy drivers + * to pick these devices up without messing with simple-framebuffer drivers. + * + * If CONFIG_X86_SYSFB is not selected, we never register "simple-framebuffer" + * platform devices, but only use "platform-framebuffer" devices for + * backwards compatibility. + * + * TODO: We set the dev_id field of all platform-devices to 0. This allows + * other x86 OF/DT parsers to create such devices, too. However, they must + * start at offset 1 for this to work. + */ + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/platform_data/simplefb.h> +#include <linux/platform_device.h> +#include <linux/screen_info.h> + +#ifdef CONFIG_X86_SYSFB + +static const char simplefb_resname[] = "BOOTFB"; + +static const struct simplefb_format formats[] = { + SIMPLEFB_FORMATS +}; + +static bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode) +{ + const struct simplefb_format *f; + __u8 type; + unsigned int i; + + /* TODO: apply quirks from efifb.c here before probing the devices */ + + type = si->orig_video_isVGA; + if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI) + return false; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + f = &formats[i]; + if (si->lfb_depth == f->bits_per_pixel && + si->red_size == f->red.length && + si->red_pos == f->red.offset && + si->green_size == f->green.length && + si->green_pos == f->green.offset && + si->blue_size == f->blue.length && + si->blue_pos == f->blue.offset && + si->rsvd_size == f->transp.length && + si->rsvd_pos == f->transp.offset) { + strlcpy(mode->format, f->name, sizeof(mode->format)); + mode->width = si->lfb_width; + mode->height = si->lfb_height; + mode->stride = si->lfb_linelength; + return true; + } + } + + return false; +} + +static int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode) +{ + struct platform_device *pd; + struct resource memres; + unsigned long len; + + /* don't use lfb_size as it may contain the whole VMEM instead of only + * the part that is occupied by the framebuffer */ + len = mode->height * mode->stride; + len = PAGE_ALIGN(len); + if (len > si->lfb_size << 16) { + printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n"); + return -EINVAL; + } + + /* setup IORESOURCE_MEM as framebuffer memory */ + memset(&memres, 0, sizeof(memres)); + memres.flags = IORESOURCE_MEM; + memres.name = simplefb_resname; + memres.start = si->lfb_base; + memres.end = si->lfb_base + len - 1; + if (memres.end <= memres.start) + return -EINVAL; + + pd = platform_device_register_resndata(NULL, + "simple-framebuffer", 0, + &memres, 1, + mode, sizeof(*mode)); + if (IS_ERR(pd)) + return PTR_ERR(pd); + + return 0; +} + +#else /* CONFIG_X86_SYSFB */ + +static bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode) +{ + return false; +} + +static int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode) +{ + return -EINVAL; +} + +#endif /* CONFIG_X86_SYSFB */ + +static __init int add_sysfb(void) +{ + const struct screen_info *si = &screen_info; + struct simplefb_platform_data mode; + struct platform_device *pd; + bool compatible = false; + int ret; + + compatible = parse_mode(si, &mode); + + ret = -ENODEV; + if (compatible) + ret = create_simplefb(si, &mode); + + if (ret) { + pd = platform_device_register_resndata(NULL, + "platform-framebuffer", 0, + NULL, 0, si, sizeof(*si)); + ret = IS_ERR(pd) ? PTR_ERR(pd) : 0; + } + + return ret; +} +device_initcall(add_sysfb); -- 1.8.3.1
WARNING: multiple messages have this Message-ID (diff)
From: David Herrmann <dh.herrmann@gmail.com> To: dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org, Dave Airlie <airlied@gmail.com>, linux-fbdev@vger.kernel.org, Stephen Warren <swarren@nvidia.com>, Olof Johansson <olof@lixom.net>, David Herrmann <dh.herrmann@gmail.com> Subject: [RFC 2/6] x86: provide platform-devices for boot-framebuffers Date: Mon, 24 Jun 2013 22:27:25 +0000 [thread overview] Message-ID: <1372112849-670-3-git-send-email-dh.herrmann@gmail.com> (raw) In-Reply-To: <1372112849-670-1-git-send-email-dh.herrmann@gmail.com> The current situation regarding boot-framebuffers (VGA, VESA/VBE, EFI) on x86 causes troubles when loading multiple fbdev drivers. The global "struct screen_info" does not provide any state-tracking about which drivers use the FBs. request_mem_region() theoretically works, but unfortunately vesafb/efifb ignore it due to quirks for broken boards. Avoid this by creating a "platform-framebuffer" device with a pointer to the "struct screen_info" as platform-data. Drivers can now create platform-drivers and the driver-core will refuse multiple drivers being active simultaneously. We keep the screen_info available for backwards-compatibility. Drivers can be converted in follow-up patches. Apart from "platform-framebuffer" devices, this also introduces a compatibility option for "simple-framebuffer" drivers which recently got introduced for OF based systems. If CONFIG_X86_SYSFB is selected, we try to match the screen_info against a simple-framebuffer supported format. If we succeed, we create a "simple-framebuffer" device instead of a platform-framebuffer. This allows to reuse the simplefb.c driver across architectures and also to introduce a SimpleDRM driver. There is no need to have vesafb.c, efifb.c, simplefb.c and more just to have architecture specific quirks in their setup-routines. Instead, we now move the architecture specific quirks into x86-setup and provide a generic simple-framebuffer. For backwards-compatibility (if strange formats are used), we still allow vesafb/efifb to be loaded simultaneously and pick up all remaining devices. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> --- arch/x86/Kconfig | 18 ++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/sysfb.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 arch/x86/kernel/sysfb.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fe120da..8eb06b5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2255,6 +2255,24 @@ config RAPIDIO source "drivers/rapidio/Kconfig" +config X86_SYSFB + bool "Mark VGA/VBE/EFI FB as generic system framebuffer" + help + Firmwares often provide initial graphics framebuffers so the BIOS, + bootloader or kernel can show basic video-output during boot for + user-guidance and debugging. Historically, x86 used the VESA BIOS + Extensions and EFI-framebuffers for this, which are mostly limited + to x86. However, a generic system-framebuffer initialization emerged + recently on some non-x86 architectures. + This option, if enabled, marks VGA/VBE/EFI framebuffers as generic + framebuffers so the new generic system-framebuffer drivers can be + used on x86. + + This breaks any x86-only driver like efifb, vesafb, uvesafb, which + will not work if this is selected. + + If unsure, say N. + endmenu diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 7bd3bd3..1e1005a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o +obj-y += sysfb.o obj-$(CONFIG_PERF_EVENTS) += perf_regs.o diff --git a/arch/x86/kernel/sysfb.c b/arch/x86/kernel/sysfb.c new file mode 100644 index 0000000..8272958 --- /dev/null +++ b/arch/x86/kernel/sysfb.c @@ -0,0 +1,157 @@ +/* + * Generic System Framebuffers on x86 + * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@gmail.com> + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* + * Simple-Framebuffer support for x86 systems + * Create a platform-device for any available boot framebuffer. The + * simple-framebuffer platform device is already available on DT systems, so + * this module parses the global "screen_info" object and creates a suitable + * platform device compatible with the "simple-framebuffer" DT object. If + * the framebuffer is incompatible, we instead create a "platform-framebuffer" + * device and pass the screen_info as platform_data. This allows legacy drivers + * to pick these devices up without messing with simple-framebuffer drivers. + * + * If CONFIG_X86_SYSFB is not selected, we never register "simple-framebuffer" + * platform devices, but only use "platform-framebuffer" devices for + * backwards compatibility. + * + * TODO: We set the dev_id field of all platform-devices to 0. This allows + * other x86 OF/DT parsers to create such devices, too. However, they must + * start at offset 1 for this to work. + */ + +#include <linux/err.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/platform_data/simplefb.h> +#include <linux/platform_device.h> +#include <linux/screen_info.h> + +#ifdef CONFIG_X86_SYSFB + +static const char simplefb_resname[] = "BOOTFB"; + +static const struct simplefb_format formats[] = { + SIMPLEFB_FORMATS +}; + +static bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode) +{ + const struct simplefb_format *f; + __u8 type; + unsigned int i; + + /* TODO: apply quirks from efifb.c here before probing the devices */ + + type = si->orig_video_isVGA; + if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI) + return false; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + f = &formats[i]; + if (si->lfb_depth = f->bits_per_pixel && + si->red_size = f->red.length && + si->red_pos = f->red.offset && + si->green_size = f->green.length && + si->green_pos = f->green.offset && + si->blue_size = f->blue.length && + si->blue_pos = f->blue.offset && + si->rsvd_size = f->transp.length && + si->rsvd_pos = f->transp.offset) { + strlcpy(mode->format, f->name, sizeof(mode->format)); + mode->width = si->lfb_width; + mode->height = si->lfb_height; + mode->stride = si->lfb_linelength; + return true; + } + } + + return false; +} + +static int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode) +{ + struct platform_device *pd; + struct resource memres; + unsigned long len; + + /* don't use lfb_size as it may contain the whole VMEM instead of only + * the part that is occupied by the framebuffer */ + len = mode->height * mode->stride; + len = PAGE_ALIGN(len); + if (len > si->lfb_size << 16) { + printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n"); + return -EINVAL; + } + + /* setup IORESOURCE_MEM as framebuffer memory */ + memset(&memres, 0, sizeof(memres)); + memres.flags = IORESOURCE_MEM; + memres.name = simplefb_resname; + memres.start = si->lfb_base; + memres.end = si->lfb_base + len - 1; + if (memres.end <= memres.start) + return -EINVAL; + + pd = platform_device_register_resndata(NULL, + "simple-framebuffer", 0, + &memres, 1, + mode, sizeof(*mode)); + if (IS_ERR(pd)) + return PTR_ERR(pd); + + return 0; +} + +#else /* CONFIG_X86_SYSFB */ + +static bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode) +{ + return false; +} + +static int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode) +{ + return -EINVAL; +} + +#endif /* CONFIG_X86_SYSFB */ + +static __init int add_sysfb(void) +{ + const struct screen_info *si = &screen_info; + struct simplefb_platform_data mode; + struct platform_device *pd; + bool compatible = false; + int ret; + + compatible = parse_mode(si, &mode); + + ret = -ENODEV; + if (compatible) + ret = create_simplefb(si, &mode); + + if (ret) { + pd = platform_device_register_resndata(NULL, + "platform-framebuffer", 0, + NULL, 0, si, sizeof(*si)); + ret = IS_ERR(pd) ? PTR_ERR(pd) : 0; + } + + return ret; +} +device_initcall(add_sysfb); -- 1.8.3.1
next prev parent reply other threads:[~2013-06-24 22:28 UTC|newest] Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top 2013-06-24 22:27 [RFC 0/6] SimpleDRM Driver (was: dvbe driver) David Herrmann 2013-06-24 22:27 ` David Herrmann 2013-06-24 22:27 ` [RFC 1/6] fbdev: simplefb: add init through platform_data David Herrmann 2013-06-24 22:27 ` David Herrmann 2013-06-26 20:39 ` Stephen Warren 2013-06-26 20:39 ` Stephen Warren 2013-06-28 10:03 ` David Herrmann 2013-06-28 10:03 ` David Herrmann 2013-06-24 22:27 ` David Herrmann [this message] 2013-06-24 22:27 ` [RFC 2/6] x86: provide platform-devices for boot-framebuffers David Herrmann 2013-06-26 20:49 ` Stephen Warren 2013-06-26 20:49 ` Stephen Warren 2013-06-28 10:11 ` David Herrmann 2013-06-28 10:11 ` David Herrmann 2013-07-01 15:48 ` Stephen Warren 2013-07-01 15:48 ` Stephen Warren 2013-06-24 22:27 ` [RFC 3/6] drm: add SimpleDRM driver David Herrmann 2013-06-24 22:27 ` David Herrmann 2013-06-25 1:05 ` Andy Lutomirski 2013-06-25 1:05 ` Andy Lutomirski 2013-06-28 9:59 ` David Herrmann 2013-06-28 9:59 ` David Herrmann 2013-06-26 20:58 ` Stephen Warren 2013-06-26 20:58 ` Stephen Warren 2013-06-28 10:01 ` David Herrmann 2013-06-28 10:01 ` David Herrmann 2013-06-24 22:27 ` [RFC 4/6] drm: simpledrm: add fbdev fallback support David Herrmann 2013-06-24 22:27 ` David Herrmann 2013-06-26 20:59 ` Stephen Warren 2013-06-26 20:59 ` Stephen Warren 2013-06-28 10:14 ` David Herrmann 2013-06-28 10:14 ` David Herrmann 2013-06-24 22:27 ` [RFC 5/6] drm: add helpers to kick out firmware drivers David Herrmann 2013-06-24 22:27 ` David Herrmann 2013-06-24 22:27 ` [RFC 6/6] drm: nouveau: kick out firmware drivers during probe David Herrmann 2013-06-24 22:27 ` David Herrmann 2013-06-26 21:30 ` [RFC 0/6] SimpleDRM Driver (was: dvbe driver) Stephen Warren 2013-06-26 21:30 ` Stephen Warren 2013-06-28 10:43 ` David Herrmann 2013-06-28 10:43 ` David Herrmann
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1372112849-670-3-git-send-email-dh.herrmann@gmail.com \ --to=dh.herrmann@gmail.com \ --cc=airlied@gmail.com \ --cc=dri-devel@lists.freedesktop.org \ --cc=linux-fbdev@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=olof@lixom.net \ --cc=swarren@nvidia.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.