[PATCH 4/6] video: add a simple framebuffer driver

Andre Heider a.heider at gmail.com
Thu Oct 24 16:23:44 EDT 2013


This architecture independend driver implements a framebuffer driver
based on a raw memory region that may be rendered to.

It is the counterpart of the kernel driver with the same name.

Platforms can configure display devices to scan out from such a memory
region and set it up with a single function call.
Doing so provides a framebuffer driver for barebox and a configuration
of the corresponding kernel driver through device tree.

Signed-off-by: Andre Heider <a.heider at gmail.com>
---
 drivers/video/Kconfig    |  12 +++
 drivers/video/Makefile   |   1 +
 drivers/video/simplefb.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++
 include/video/simplefb.h |  21 +++++
 4 files changed, 258 insertions(+)
 create mode 100644 drivers/video/simplefb.c
 create mode 100644 include/video/simplefb.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0639d9c..9afa7e8 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -71,4 +71,16 @@ config DRIVER_VIDEO_PXA
 	  Add support for the frame buffer device found on the PXA270
 	  CPU.
 
+config DRIVER_VIDEO_SIMPLEFB
+	bool "Simple framebuffer support"
+	depends on OFTREE
+	depends on ARCH_BCM2835
+	help
+	  Say Y if you want support for a simple frame-buffer.
+
+	  This driver provides the framebuffer configuration to the kernel
+	  through device tree.
+
+	  The corresponding kernel driver has to be enabled to use this feature.
+
 endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 67169d1..0da7c2b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_DRIVER_VIDEO_S3C24XX) += s3c24xx.o
 obj-$(CONFIG_DRIVER_VIDEO_PXA) += pxa.o
 obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
 obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o
+obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb.o
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
new file mode 100644
index 0000000..f096c36
--- /dev/null
+++ b/drivers/video/simplefb.c
@@ -0,0 +1,224 @@
+/*
+ * SimpleFB driver
+ *
+ * Copyright (C) 2013 Andre Heider
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <xfuncs.h>
+#include <common.h>
+#include <init.h>
+#include <stdio.h>
+#include <driver.h>
+#include <fb.h>
+
+#include <video/simplefb.h>
+
+struct simplefb_platform_data {
+	u32 width;
+	u32 height;
+	u32 stride;
+	enum simplefb_format format;
+	struct fb_info fbi;
+	struct fb_videomode mode;
+};
+
+struct device_d *add_simplefb_device(u32 width, u32 height, u32 stride,
+					enum simplefb_format format,
+					resource_size_t start,
+					resource_size_t size)
+{
+	struct simplefb_platform_data *pdata;
+	struct device_d *dev;
+
+	pdata = xzalloc(sizeof *pdata);
+	pdata->width = width;
+	pdata->height = height;
+	pdata->stride = stride;
+	pdata->format = format;
+
+	dev = add_generic_device("simplefb", DEVICE_ID_SINGLE,
+					NULL, start, size,
+					IORESOURCE_MEM, pdata);
+
+	if (!dev)
+		free(pdata);
+
+	return dev;
+}
+
+struct simplefb_info {
+	enum simplefb_format id;
+	const char *compatible;
+	u32 bpp;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+};
+
+/*
+ * These values have to match the kernel's simplefb driver.
+ * See Documentation/devicetree/bindings/video/simple-framebuffer.txt
+ */
+static const struct simplefb_info simplefb_infos[] = {
+	{
+		.id		= SIMPLEFB_R5G6B5,
+		.compatible	= "r5g6b5",
+		.bpp		= 16,
+		.red		= { .length = 5, .offset = 11 },
+		.green		= { .length = 6, .offset = 5 },
+		.blue		= { .length = 5, .offset = 0 },
+	},
+};
+
+static const struct simplefb_info *simplefb_get_info(enum simplefb_format id)
+{
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(simplefb_infos); ++i)
+		if (simplefb_infos[i].id == id)
+			return &simplefb_infos[i];
+
+	return NULL;
+}
+
+static int simplefb_create_node(struct device_node *root,
+				const struct simplefb_platform_data *pdata,
+				const struct resource *res)
+{
+	const char compat[] = "simple-framebuffer";
+	const char disabled[] = "disabled";
+	const char okay[] = "okay";
+	const struct simplefb_info *info;
+	struct device_node *node;
+	u32 cells[2];
+	int ret;
+
+	info = simplefb_get_info(pdata->format);
+	if (!info)
+		return -EINVAL;
+
+	node = of_create_node(root, "/framebuffer");
+	if (!node)
+		return -ENOMEM;
+
+	ret = of_set_property(node, "status", disabled,
+				strlen(disabled) + 1, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = of_set_property(node, "compatible", compat, sizeof(compat), 1);
+	if (ret)
+		return ret;
+
+	cells[0] = cpu_to_be32(res->start);
+	cells[1] = cpu_to_be32(resource_size(res));
+	ret = of_set_property(node, "reg", cells, sizeof(cells[0]) * 2, 1);
+	if (ret < 0)
+		return ret;
+
+	cells[0] = cpu_to_be32(pdata->width);
+	ret = of_set_property(node, "width", cells, sizeof(cells[0]), 1);
+	if (ret < 0)
+		return ret;
+
+	cells[0] = cpu_to_be32(pdata->height);
+	ret = of_set_property(node, "height", cells, sizeof(cells[0]), 1);
+	if (ret < 0)
+		return ret;
+
+	cells[0] = cpu_to_be32(pdata->stride);
+	ret = of_set_property(node, "stride", cells, sizeof(cells[0]), 1);
+	if (ret < 0)
+		return ret;
+
+	ret = of_set_property(node, "format", info->compatible,
+				strlen(info->compatible) + 1, 1);
+	if (ret < 0)
+		return ret;
+
+	return of_set_property(node, "status", okay, strlen(okay) + 1, 1);
+}
+
+static int simplefb_of_fixup(struct device_node *root)
+{
+	struct device_d *dev;
+	struct simplefb_platform_data *pdata;
+	struct resource *res;
+
+	dev = get_device_by_name("simplefb");
+	if (!dev)
+		return 0;
+
+	pdata = dev->platform_data;
+	if (!pdata)
+		return 0;
+
+	res = dev_get_resource(dev, 0);
+	if (!res)
+		return 0;
+
+	simplefb_create_node(root, pdata, res);
+
+	return 0;
+}
+
+static void simplefb_enable(struct fb_info *info)
+{
+}
+
+static void simplefb_disable(struct fb_info *info)
+{
+}
+
+static struct fb_ops simplefb_ops = {
+	.fb_enable		= simplefb_enable,
+	.fb_disable		= simplefb_disable,
+};
+
+static int simplefb_probe(struct device_d *dev)
+{
+	struct simplefb_platform_data *pdata = dev->platform_data;
+	const struct simplefb_info *info;
+	struct resource *res;
+	int ret;
+
+	info = simplefb_get_info(pdata->format);
+	if (!info)
+		return -EINVAL;
+
+	res = dev_get_resource(dev, 0);
+	if (!res)
+		return -EINVAL;
+
+	pdata->fbi.fbops = &simplefb_ops;
+	pdata->fbi.screen_base = (void *)res->start;
+	pdata->fbi.xres = pdata->width;
+	pdata->fbi.yres = pdata->height;
+	pdata->fbi.bits_per_pixel = info->bpp;
+	pdata->fbi.stride = pdata->stride;
+	pdata->fbi.red = info->red;
+	pdata->fbi.green = info->green;
+	pdata->fbi.blue = info->blue;
+
+	pdata->fbi.mode = &pdata->mode;
+	pdata->fbi.mode->xres = pdata->width;
+	pdata->fbi.mode->yres = pdata->height;
+
+	ret = register_framebuffer(&pdata->fbi);
+	if (ret < 0)
+		return ret;
+
+	of_register_fixup(simplefb_of_fixup);
+
+	return 0;
+}
+
+static struct driver_d simplefb_driver = {
+	.name	= "simplefb",
+	.probe	= simplefb_probe,
+};
+device_platform_driver(simplefb_driver);
diff --git a/include/video/simplefb.h b/include/video/simplefb.h
new file mode 100644
index 0000000..5949046
--- /dev/null
+++ b/include/video/simplefb.h
@@ -0,0 +1,21 @@
+/*
+ * SimpleFB driver
+ *
+ * Copyright (C) 2013 Andre Heider
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef SIMPLEFB_H
+#define SIMPLEFB_H
+
+enum simplefb_format {
+	SIMPLEFB_R5G6B5
+};
+
+struct device_d *add_simplefb_device(u32 width, u32 height, u32 stride,
+					enum simplefb_format format,
+					resource_size_t start,
+					resource_size_t size);
+
+#endif
-- 
1.8.3.2




More information about the barebox mailing list