[PATCH, RFC] displaymodes in devicetree
Mitch Bradley
wmb at firmworks.com
Thu Jun 28 02:16:12 EST 2012
On 6/27/2012 2:43 AM, Sascha Hauer wrote:
> Hi All,
>
> I'd like to have a possibility to describe fixed display modes in the
> devicetree. This topic has been discussed before here:
>
> https://lists.ozlabs.org/pipermail/linuxppc-dev/2010-February/080683.html
>
> The result at that time was that EDID data should be considered to use
> as this is a format that already exists. I want to come back to this
> topic since:
>
> - EDID data is a binary format and as such quite inconvenient to handle.
> There exist several tools to parse EDID data, but I'm not aware of any
> (open source) tool which can generate EDID data.
> - EDID blobs are hard to modify and hard to review in patches.
> - EDID is designed to describe multiple modes, but fixed displays
> usually only support a single fixed mode.
>
> There are several ways of describing the mode, for this patch I chose to
> use the format (and naming) used by the Linux Framebuffer Layer as this
> is the only description which does not allow for inconsistent modes. I
> added the most common flags like [v|h]sync_active_high. Others can be
> added, but these flags are pretty much agreed upon and won't be
> superseeded with other flags. The mode from the devicetree can be
> converted to the most common modes used in Linux, struct fb_videomode
> and struct drm_display_mode.
>
> Comments welcome
I like the general approach and the set of names. The separators inside
the names should be hyphen (-) not underscore (_), following the usual
device tree convention. The rationale for that convention is to follow
natural-language usage, not the identifier constraints of programming
languages based on algebraic expressions.
>
> Sascha
>
>
> 8<--------------------------------------------
>
> of: Add videomode helper
>
> This patch adds a helper function for parsing videomodes from the devicetree.
> The videomode is returned either as a struct drm_display_mode or a
> struct fb_videomode.
>
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
> .../devicetree/bindings/video/displaymode | 40 ++++++++
> drivers/of/Kconfig | 5 +
> drivers/of/Makefile | 1 +
> drivers/of/of_videomode.c | 108 ++++++++++++++++++++
> include/linux/of_videomode.h | 19 ++++
> 5 files changed, 173 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/video/displaymode
> create mode 100644 drivers/of/of_videomode.c
> create mode 100644 include/linux/of_videomode.h
>
> diff --git a/Documentation/devicetree/bindings/video/displaymode b/Documentation/devicetree/bindings/video/displaymode
> new file mode 100644
> index 0000000..303cfc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/video/displaymode
> @@ -0,0 +1,40 @@
> +videomode bindings
> +==================
> +
> +Required properties:
> + - xres, yres: Display resolution
> + - left_margin, right_margin, hsync_len: Horizontal Display timing parameters
> + in pixels
> + upper_margin, lower_margin, vsync_len: Vertical display timing parameters in
> + lines
> + - clock: displayclock in Hz
> +
> +Optional properties:
> + - width_mm, height_mm: Display dimensions in mm
> + - hsync_active_high (bool): Hsync pulse is active high
> + - vsync_active_high (bool): Vsync pulse is active high
> + - interlaced (bool): This is an interlaced mode
> + - doublescan (bool): This is a doublescan mode
> +
> +There are different ways of describing a display mode. The devicetree representation
> +corresponds to the one used by the Linux Framebuffer framework described here in
> +Documentation/fb/framebuffer.txt. This representation has been chosen because it's
> +the only format which does not allow for inconsistent parameters.Unlike the Framebuffer
> +framework the devicetree has the clock in Hz instead of ps.
> +
> +Example:
> +
> + display at 0 {
> + /* 1920x1080p24 */
> + clock = <52000000>;
> + xres = <1920>;
> + yres = <1080>;
> + left_margin = <25>;
> + right_margin = <25>;
> + hsync_len = <25>;
> + lower_margin = <2>;
> + upper_margin = <2>;
> + vsync_len = <2>;
> + hsync_active_high;
> + };
> +
> diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
> index dfba3e6..a3acaa3 100644
> --- a/drivers/of/Kconfig
> +++ b/drivers/of/Kconfig
> @@ -83,4 +83,9 @@ config OF_MTD
> depends on MTD
> def_bool y
>
> +config OF_VIDEOMODE
> + def_bool y
> + help
> + helper to parse videomodes from the devicetree
> +
> endmenu # OF
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index e027f44..80e6db3 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o
> obj-$(CONFIG_OF_PCI) += of_pci.o
> obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
> obj-$(CONFIG_OF_MTD) += of_mtd.o
> +obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
> diff --git a/drivers/of/of_videomode.c b/drivers/of/of_videomode.c
> new file mode 100644
> index 0000000..859aefb
> --- /dev/null
> +++ b/drivers/of/of_videomode.c
> @@ -0,0 +1,108 @@
> +/*
> + * OF helpers for parsing display modes
> + *
> + * Copyright (c) 2012 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
> + *
> + * This file is released under the GPLv2
> + */
> +#include <linux/of.h>
> +#include <linux/fb.h>
> +#include <linux/export.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +
> +int of_get_video_mode(struct device_node *np, struct drm_display_mode *dmode,
> + struct fb_videomode *fbmode)
> +{
> + int ret = 0;
> + u32 left_margin, xres, right_margin, hsync_len;
> + u32 upper_margin, yres, lower_margin, vsync_len;
> + u32 width_mm = 0, height_mm = 0;
> + u32 clock;
> + bool hah = false, vah = false, interlaced = false, doublescan = false;
> +
> + if (!np)
> + return -EINVAL;
> +
> + ret |= of_property_read_u32(np, "left_margin", &left_margin);
> + ret |= of_property_read_u32(np, "xres", &xres);
> + ret |= of_property_read_u32(np, "right_margin", &right_margin);
> + ret |= of_property_read_u32(np, "hsync_len", &hsync_len);
> + ret |= of_property_read_u32(np, "upper_margin", &upper_margin);
> + ret |= of_property_read_u32(np, "yres", &yres);
> + ret |= of_property_read_u32(np, "lower_margin", &lower_margin);
> + ret |= of_property_read_u32(np, "vsync_len", &vsync_len);
> + ret |= of_property_read_u32(np, "clock", &clock);
> + if (ret)
> + return -EINVAL;
> +
> + of_property_read_u32(np, "width_mm", &width_mm);
> + of_property_read_u32(np, "height_mm", &height_mm);
> +
> + hah = of_property_read_bool(np, "hsync_active_high");
> + vah = of_property_read_bool(np, "vsync_active_high");
> + interlaced = of_property_read_bool(np, "interlaced");
> + doublescan = of_property_read_bool(np, "doublescan");
> +
> + if (dmode) {
> + memset(dmode, 0, sizeof(*dmode));
> +
> + dmode->hdisplay = xres;
> + dmode->hsync_start = xres + right_margin;
> + dmode->hsync_end = xres + right_margin + hsync_len;
> + dmode->htotal = xres + right_margin + hsync_len + left_margin;
> +
> + dmode->vdisplay = yres;
> + dmode->vsync_start = yres + lower_margin;
> + dmode->vsync_end = yres + lower_margin + vsync_len;
> + dmode->vtotal = yres + lower_margin + vsync_len + upper_margin;
> +
> + dmode->width_mm = width_mm;
> + dmode->height_mm = height_mm;
> +
> + dmode->clock = clock / 1000;
> +
> + if (hah)
> + dmode->flags |= DRM_MODE_FLAG_PHSYNC;
> + else
> + dmode->flags |= DRM_MODE_FLAG_NHSYNC;
> + if (vah)
> + dmode->flags |= DRM_MODE_FLAG_PVSYNC;
> + else
> + dmode->flags |= DRM_MODE_FLAG_NVSYNC;
> + if (interlaced)
> + dmode->flags |= DRM_MODE_FLAG_INTERLACE;
> + if (doublescan)
> + dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
> +
> + drm_mode_set_name(dmode);
> + }
> +
> + if (fbmode) {
> + memset(fbmode, 0, sizeof(*fbmode));
> +
> + fbmode->xres = xres;
> + fbmode->left_margin = left_margin;
> + fbmode->right_margin = right_margin;
> + fbmode->hsync_len = hsync_len;
> +
> + fbmode->yres = yres;
> + fbmode->upper_margin = upper_margin;
> + fbmode->lower_margin = lower_margin;
> + fbmode->vsync_len = vsync_len;
> +
> + fbmode->pixclock = KHZ2PICOS(clock / 1000);
> +
> + if (hah)
> + fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
> + if (vah)
> + fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
> + if (interlaced)
> + fbmode->vmode |= FB_VMODE_INTERLACED;
> + if (doublescan)
> + fbmode->vmode |= FB_VMODE_DOUBLE;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(of_get_video_mode);
> diff --git a/include/linux/of_videomode.h b/include/linux/of_videomode.h
> new file mode 100644
> index 0000000..a988429
> --- /dev/null
> +++ b/include/linux/of_videomode.h
> @@ -0,0 +1,19 @@
> +/*
> + * Copyright 2012 Sascha Hauer <s.hauer at pengutronix.de>
> + *
> + * OF helpers for videomodes.
> + *
> + * This file is released under the GPLv2
> + */
> +
> +#ifndef __LINUX_OF_VIDEOMODE_H
> +#define __LINUX_OF_VIDEOMODE_H
> +
> +struct device_node;
> +struct fb_videomode;
> +struct drm_display_mode;
> +
> +int of_get_video_mode(struct device_node *np, struct drm_display_mode *dmode,
> + struct fb_videomode *fbmode);
> +
> +#endif /* __LINUX_OF_VIDEOMODE_H */
>
More information about the devicetree-discuss
mailing list