All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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: link
Be 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.