mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Juergen Beisert <jbe@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 03/11] Bring in dynamic videomode selection at runtime
Date: Fri, 22 Oct 2010 18:53:17 +0200	[thread overview]
Message-ID: <1287766405-1646-4-git-send-email-jbe@pengutronix.de> (raw)
In-Reply-To: <1287766405-1646-1-git-send-email-jbe@pengutronix.de>

This patch mostly rewrites all parts of /drivers/video/fb.c. As it changes
the API to the drivers, it must be done in one step to keep the repository
bisectable. But to do it in one step makes the patches itself unreadable.

So, I decided to do it in a few steps, only for the review. All patches marked
with a "step n of m" should be merged, prior the final commit into the
repository.

This step brings in the required functions for dynamic videomode selection at
runtime, but keep the old functions untouched (the new ones are commented out).

This is patch 1 of 7 to keep the repository bisectable.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
---
 drivers/video/Kconfig |   23 +++++
 drivers/video/fb.c    |  251 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fb.h          |   40 ++++++++
 3 files changed, 314 insertions(+), 0 deletions(-)

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 7a89a3f..e6ecfc8 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -5,6 +5,29 @@ menuconfig VIDEO
 
 if VIDEO
 
+comment "runtime options"
+
+config VIDEO_DELAY_ENABLING
+	bool "Delayed enabling"
+	help
+	  Say 'y' here to delay enabling video output. This is useful to first
+	  fill the framebuffer (splash screen for example) prior enabling the
+	  video device.
+          This entry adds the "enable" parameter to the video device, to enable
+	  or disable video output at runtime.
+
+config VIDEO_DELAY_INIT
+	bool "Delayed initialization"
+	select VIDEO_DELAY_ENABLING
+	help
+	  If the platform supports more than one video mode say 'y' her to delay
+	  the initialization of the video device until any kind of barebox's
+          shell code sets up the correct mode at runtime.
+          This entry adds the "mode" parameter to the video device, to setup
+          the desired videomode prior enabling it at runtime.
+
+comment "drivers"
+
 config DRIVER_VIDEO_IMX
 	bool "i.MX framebuffer driver"
 	depends on ARCH_IMX1 || ARCH_IMX21 || ARCH_IMX25 || ARCH_IMX27
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index f9a425e..c2934f6 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -1,3 +1,4 @@
+#include <init.h>
 #include <common.h>
 #include <fb.h>
 #include <errno.h>
@@ -5,6 +6,8 @@
 #include <getopt.h>
 #include <fcntl.h>
 #include <fs.h>
+#include <malloc.h>
+#include <xfuncs.h>
 
 static int fb_ioctl(struct cdev* cdev, int req, void *data)
 {
@@ -57,6 +60,141 @@ static int fb_enable_set(struct device_d *dev, struct param_d *param,
 	return 0;
 }
 
+#if 0
+#ifdef CONFIG_VIDEO_DELAY_INIT
+static int fb_check_if_already_initialized(struct device_d *fb_dev)
+{
+	struct cdev *cdev = fb_dev->priv;
+	struct fb_info *info = cdev->priv;
+
+	if (info->active_mode != NULL) {
+		pr_err("Video mode '%s' is already set. Cannot change colour depth anymore.\n", info->active_mode->name);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+static int fb_cdepth_set(struct device_d *fb_dev, struct param_d *param, const char *val)
+{
+	struct cdev *cdev = fb_dev->priv;
+	struct fb_info *info = cdev->priv;
+	unsigned cdepth;
+	int rc;
+
+	rc = fb_check_if_already_initialized(fb_dev);
+	if (rc != 0)
+		return rc;
+
+	cdepth = simple_strtoul(val, NULL, 0);
+	if (cdepth != 0)
+		info->bits_per_pixel = cdepth;
+	else
+		return -EINVAL;
+
+	return dev_param_set_generic(fb_dev, param, val);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_DELAY_ENABLING
+static int fb_enable_set(struct device_d *fb_dev, struct param_d *param, const char *val)
+{
+	struct cdev *cdev = fb_dev->priv;
+	struct fb_info *info = cdev->priv;
+	struct fb_host *host = fb_dev->platform_data;
+	int enable;
+	char *new;
+
+	if (!val)
+		return dev_param_set_generic(fb_dev, param, NULL);
+
+	enable = simple_strtoul(val, NULL, 0);
+
+	if (info->enabled == !!enable)
+		return 0;
+
+	if (enable) {
+		(host->fb_enable)(info);
+		new = "1";
+	} else {
+		(host->fb_disable)(info);
+		new = "0";
+	}
+
+	info->enabled = !!enable;
+
+	return dev_param_set_generic(fb_dev, param, new);
+}
+#endif
+
+static void fb_list_modes(struct fb_host *host)
+{
+	unsigned u;
+
+	if (host->mode_cnt == 0)
+		return;
+
+	printf(" Supported video mode(s):\n");
+	for (u = 0; u < host->mode_cnt; u++)
+		printf("  '%s'\n", host->mode[u].name);
+}
+
+static int fb_activate_mode(struct device_d *fb_dev, const struct fb_videomode *mode)
+{
+	struct cdev *cdev = fb_dev->priv;
+	struct fb_info *info = cdev->priv;
+	struct fb_host *host = fb_dev->platform_data;
+	int rc;
+
+	rc = (host->fb_mode)(info, mode);
+	if (rc != 0)
+		return rc;
+
+	info->active_mode = mode;
+	/*
+	 * At this point of time we know the remaining information we need
+	 * for the cdev and fb_info structure.
+	 */
+	cdev->size = fb_dev->size;
+	info->xres = mode->xres;
+	info->yres = mode->yres;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_DELAY_INIT
+static int fb_mode_set(struct device_d *fb_dev, struct param_d *param, const char *name)
+{
+	struct fb_host *host = fb_dev->platform_data;
+	unsigned u;
+	int rc;
+
+	pr_debug("%s called\n", __func__);
+
+	rc = fb_check_if_already_initialized(fb_dev);
+	if (rc != 0)
+		return rc;
+
+	/* Search for the requested video mode by name */
+	for (u = 0; u < host->mode_cnt; u++) {
+		if (!strcmp(host->mode[u].name, name))
+			break;
+	}
+	if (u >= host->mode_cnt) {
+		fb_list_modes(host);	/* no mode with 'name' found */
+		return -ENODEV;
+	} else {
+		rc = fb_activate_mode(fb_dev, &host->mode[u]);
+	}
+
+	if (rc == 0)
+		dev_param_set_generic(fb_dev, param, name);
+
+	return rc;
+}
+#endif
+#endif
+
 static struct file_operations fb_ops = {
 	.read	= mem_read,
 	.write	= mem_write,
@@ -65,6 +203,119 @@ static struct file_operations fb_ops = {
 	.ioctl	= fb_ioctl,
 };
 
+#if 0
+static int add_fb_parameter(struct device_d *fb_dev)
+{
+#ifdef CONFIG_VIDEO_DELAY_INIT
+	struct cdev *cdev = fb_dev->priv;
+	struct fb_info *info = cdev->priv;
+	char cd[10];
+
+	/** @todo provide base address parameter for the user */
+
+	dev_add_param(fb_dev, "cdepth", fb_cdepth_set, NULL, 0);
+	if (info->bits_per_pixel == 0) {
+		dev_set_param(fb_dev, "cdepth", "16");
+		info->bits_per_pixel = 16;
+	} else {
+		sprintf(cd, "%u", info->bits_per_pixel);
+		dev_set_param(fb_dev, "cdepth", cd);
+	}
+	dev_add_param(fb_dev, "mode", fb_mode_set, NULL, 0);
+	/* default is 'none' for delayed video mode setup */
+#endif
+#ifdef CONFIG_VIDEO_DELAY_ENABLING
+	dev_add_param(fb_dev, "enable", fb_enable_set, NULL, 0);
+	/* default is 'off' for delayed video output */
+#endif
+	return 0;
+}
+
+struct framebuffer_desc {
+	struct cdev cdev;
+	struct fb_info info;
+};
+
+static int fb_probe(struct device_d *fb_dev)
+{
+	int id = get_free_deviceid("fb");
+	struct cdev *cdev;
+	struct fb_info *info;
+	struct fb_host *host = fb_dev->platform_data;
+
+	cdev = xzalloc(sizeof(struct framebuffer_desc));
+	info = (struct fb_info*)&cdev[1];
+
+	fb_dev->priv = cdev;	/* pointer forward */
+	cdev->dev = fb_dev;	/* pointer backward */
+
+	cdev->ops = &fb_ops;
+	cdev->name = asprintf("fb%d", id);
+
+	cdev->size = fb_dev->size;	/* use the default if any */
+	cdev->priv = info;
+
+	info->host = host;
+	info->fb_dev = fb_dev;
+
+	/* setup defaults */
+	if (host->bits_per_pixel != 0)
+		info->bits_per_pixel = host->bits_per_pixel;
+	else
+		info->bits_per_pixel = 16;	/* means RGB565 */
+
+	/* add params on demand */
+	add_fb_parameter(fb_dev);
+
+	devfs_create(cdev);
+#ifndef CONFIG_VIDEO_DELAY_INIT
+	/* initialize video mode immediately (the first one) */
+	fb_activate_mode(fb_dev, &host->mode[0]);
+#endif
+#ifndef CONFIG_VIDEO_DELAY_ENABLING
+	/* enable video output immediately */
+	(host->fb_enable)(info);
+#endif
+	return 0;
+}
+
+static struct driver_d fb_driver = {
+	.name	= "framebuffer",
+	.probe	= fb_probe,
+};
+
+static int framebuffer_init(void)
+{
+	return register_driver(&fb_driver);
+}
+
+device_initcall(framebuffer_init);
+
+struct device_d *register_framebuffer(struct fb_host *host, void *base, unsigned size)
+{
+	struct device_d *fb_dev;
+	int rc;
+
+	fb_dev = xzalloc(sizeof(struct device_d));
+
+	strcpy(fb_dev->name, fb_driver.name);
+	fb_dev->platform_data = (void*)host;
+
+	/* setup the defaults for this framebuffer if given */
+	fb_dev->size = size;
+	fb_dev->map_base = (unsigned long)base;
+
+	rc = register_device(fb_dev);
+	if (rc != 0) {
+		pr_debug("Cannot register framebuffer device\n");
+		free(fb_dev);
+		return NULL;
+	}
+
+	return fb_dev;
+}
+#endif
+
 int register_framebuffer(struct fb_info *info)
 {
 	int id = get_free_deviceid("fb");
diff --git a/include/fb.h b/include/fb.h
index 218b244..96edc24 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -85,6 +85,46 @@ struct fb_ops {
 	void (*fb_disable)(struct fb_info *info);
 };
 
+#if 0
+struct fb_host {
+	const struct fb_videomode *mode;
+	unsigned mode_cnt;
+
+	struct device_d *hw_dev;
+
+	/* callbacks into the video hardware driver */
+	int (*fb_setcolreg)(struct fb_info*, unsigned, unsigned, unsigned, unsigned, unsigned);
+	int (*fb_mode)(struct fb_info*, const struct fb_videomode*);
+	void (*fb_enable)(struct fb_info*);
+	void (*fb_disable)(struct fb_info*);
+
+	unsigned bits_per_pixel;
+};
+
+struct fb_info {
+	struct fb_host *host;
+	struct device_d *fb_dev;
+	const struct fb_videomode *active_mode;
+
+	u32 xres;			/* visible resolution		*/
+	u32 yres;
+	u32 bits_per_pixel;		/* guess what			*/
+
+	u32 grayscale;			/* != 0 Graylevels instead of colors */
+
+	struct fb_bitfield red;		/* bitfield in fb mem if true color, */
+	struct fb_bitfield green;	/* else only length is significant */
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;	/* transparency			*/
+
+#ifdef CONFIG_VIDEO_DELAY_ENABLING
+	int enabled;
+#endif
+};
+
+struct device_d *register_framebuffer(struct fb_host*, void*, unsigned);
+#endif
+
 struct fb_info {
 	struct fb_videomode *mode;
 
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2010-10-22 16:53 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-22 16:53 Add dynamic video initialization to barebox Juergen Beisert
2010-10-22 16:53 ` [PATCH 01/11] imx: Separate framebuffer platformdata and the videomode Juergen Beisert
2010-10-22 17:46   ` Sascha Hauer
2010-10-23 10:31     ` Juergen Beisert
2010-10-22 16:53 ` [PATCH 02/11] Add more flags for sync control Juergen Beisert
2010-10-22 16:53 ` Juergen Beisert [this message]
2010-10-22 17:41   ` [PATCH 03/11] Bring in dynamic videomode selection at runtime Sascha Hauer
2010-10-23 10:35     ` Juergen Beisert
2010-10-22 16:53 ` [PATCH 04/11] Remove the old videomode functions Juergen Beisert
2010-10-22 16:53 ` [PATCH 05/11] Add verbose framebuffer device info Juergen Beisert
2010-10-22 16:53 ` [PATCH 06/11] Adapt the existing imx fb driver to support runtime videomode selection Juergen Beisert
2010-10-22 16:53 ` [PATCH 07/11] Adapt the existing imx-ipu " Juergen Beisert
2010-10-22 17:43   ` Sascha Hauer
2010-10-23 10:36     ` Juergen Beisert
2010-10-22 16:53 ` [PATCH 08/11] Add a video driver for S3C2440 bases platforms Juergen Beisert
2010-10-22 18:56   ` Sascha Hauer
2010-10-23 10:37     ` Juergen Beisert
2010-10-22 16:53 ` [PATCH 09/11] STM378x: Add video driver for this platform Juergen Beisert
2010-10-22 18:59   ` Sascha Hauer
2010-10-23 10:40     ` Juergen Beisert
2010-10-22 16:53 ` [PATCH 10/11] Remove variable size restrictions Juergen Beisert
2010-10-22 16:53 ` [PATCH 11/11] Add doxygen documentation to the framebfuffer code Juergen Beisert
2010-11-19 12:50 [PATCHv3] Add dynamic video initialization to barebox Juergen Beisert
2010-11-19 12:50 ` [PATCH 03/11] Bring in dynamic videomode selection at runtime Juergen Beisert

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=1287766405-1646-4-git-send-email-jbe@pengutronix.de \
    --to=jbe@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox