Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCHv13 7/7] drm_modes: add of_videomode helpers
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Add helper to get drm_display_mode from devicetree.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/drm_modes.c |   34 +++++++++++++++++++++++++++++++++-
 include/drm/drmP.h          |    6 ++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 0073b27..2d6edfa 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -35,7 +35,7 @@
 #include <linux/export.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
-#include <linux/videomode.h>
+#include <linux/of_videomode.h>
 
 /**
  * drm_mode_debug_printmodeline - debug print a mode
@@ -541,6 +541,38 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
 EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
 #endif
 
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+/**
+ * of_get_drm_display_mode - get a drm_display_mode from devicetree
+ * @np: device_node with the timing specification
+ * @dmode: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings and
+ * work with that instead.
+ */
+int of_get_drm_display_mode(struct device_node *np,
+			    struct drm_display_mode *dmode, unsigned int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	drm_display_mode_from_videomode(&vm, dmode);
+
+	pr_info("%s: got %dx%d display mode from %s\n", __func__, vm.hactive,
+		vm.vactive, np->name);
+	drm_mode_debug_printmodeline(dmode);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
+#endif
+
 /**
  * drm_mode_set_name - set the name on a mode
  * @mode: name will be set in this mode
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3d0ccaa..84ecabd 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -86,6 +86,7 @@ struct drm_file;
 struct drm_device;
 
 struct videomode;
+struct device_node;
 #include <drm/drm_os_linux.h>
 #include <drm/drm_hashtab.h>
 #include <drm/drm_mm.h>
@@ -1459,6 +1460,11 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
 extern int drm_display_mode_from_videomode(const struct videomode *vm,
 					   struct drm_display_mode *dmode);
 #endif
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+extern int of_get_drm_display_mode(struct device_node *np,
+				   struct drm_display_mode *dmode,
+				   unsigned int index);
+#endif
 
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 6/7] drm_modes: add videomode helpers
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Add conversion from videomode to drm_display_mode

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/drm_modes.c |   37 +++++++++++++++++++++++++++++++++++++
 include/drm/drmP.h          |    6 ++++++
 2 files changed, 43 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 59450f3..0073b27 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -35,6 +35,7 @@
 #include <linux/export.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <linux/videomode.h>
 
 /**
  * drm_mode_debug_printmodeline - debug print a mode
@@ -504,6 +505,42 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
 }
 EXPORT_SYMBOL(drm_gtf_mode);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+int drm_display_mode_from_videomode(const struct videomode *vm,
+				    struct drm_display_mode *dmode)
+{
+	dmode->hdisplay = vm->hactive;
+	dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
+	dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
+	dmode->htotal = dmode->hsync_end + vm->hback_porch;
+
+	dmode->vdisplay = vm->vactive;
+	dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
+	dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
+	dmode->vtotal = dmode->vsync_end + vm->vback_porch;
+
+	dmode->clock = vm->pixelclock / 1000;
+
+	dmode->flags = 0;
+	if (vm->hah)
+		dmode->flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		dmode->flags |= DRM_MODE_FLAG_NHSYNC;
+	if (vm->vah)
+		dmode->flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		dmode->flags |= DRM_MODE_FLAG_NVSYNC;
+	if (vm->interlaced)
+		dmode->flags |= DRM_MODE_FLAG_INTERLACE;
+	if (vm->doublescan)
+		dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
+	drm_mode_set_name(dmode);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
+#endif
+
 /**
  * drm_mode_set_name - set the name on a mode
  * @mode: name will be set in this mode
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3fd8280..3d0ccaa 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -85,6 +85,7 @@ struct module;
 struct drm_file;
 struct drm_device;
 
+struct videomode;
 #include <drm/drm_os_linux.h>
 #include <drm/drm_hashtab.h>
 #include <drm/drm_mm.h>
@@ -1454,6 +1455,11 @@ extern struct drm_display_mode *
 drm_mode_create_from_cmdline_mode(struct drm_device *dev,
 				  struct drm_cmdline_mode *cmd);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+extern int drm_display_mode_from_videomode(const struct videomode *vm,
+					   struct drm_display_mode *dmode);
+#endif
+
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
 extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 5/7] fbmon: add of_videomode helpers
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Add helper to get fb_videomode from devicetree.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/fbmon.c |   42 +++++++++++++++++++++++++++++++++++++++++-
 include/linux/fb.h    |    6 ++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index a6a564d..cd0a035 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -31,7 +31,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <video/edid.h>
-#include <linux/videomode.h>
+#include <linux/of_videomode.h>
 #ifdef CONFIG_PPC_OF
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -1416,6 +1416,46 @@ int fb_videomode_from_videomode(const struct videomode *vm,
 EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
 #endif
 
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+static inline void dump_fb_videomode(const struct fb_videomode *m)
+{
+	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
+		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
+		 m->right_margin, m->upper_margin, m->lower_margin,
+		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+
+/**
+ * of_get_fb_videomode - get a fb_videomode from devicetree
+ * @np: device_node with the timing specification
+ * @fb: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings ond
+ * work with that instead.
+ */
+int of_get_fb_videomode(const struct device_node *np, struct fb_videomode *fb,
+			unsigned int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	fb_videomode_from_videomode(&vm, fb);
+
+	pr_info("%s: got %dx%d display mode from %s\n", __func__, vm.hactive,
+		vm.vactive, np->name);
+	dump_fb_videomode(fb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_fb_videomode);
+#endif
 
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 4404ec2..43a2f81 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -20,6 +20,7 @@ struct fb_info;
 struct device;
 struct file;
 struct videomode;
+struct device_node;
 
 /* Definitions below are used in the parsed monitor specs */
 #define FB_DPMS_ACTIVE_OFF	1
@@ -715,6 +716,11 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
 
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+extern int of_get_fb_videomode(const struct device_node *np,
+			       struct fb_videomode *fb,
+			       unsigned int index);
+#endif
 #if IS_ENABLED(CONFIG_VIDEOMODE)
 extern int fb_videomode_from_videomode(const struct videomode *vm,
 				       struct fb_videomode *fbmode);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 4/7] fbmon: add videomode helpers
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Add a function to convert from the generic videomode to a fb_videomode.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/video/fbmon.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fb.h    |    6 ++++++
 2 files changed, 50 insertions(+)

diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index cef6557..a6a564d 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <video/edid.h>
+#include <linux/videomode.h>
 #ifdef CONFIG_PPC_OF
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -1373,6 +1374,49 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
 	kfree(timings);
 	return err;
 }
+
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+int fb_videomode_from_videomode(const struct videomode *vm,
+				struct fb_videomode *fbmode)
+{
+	unsigned int htotal, vtotal;
+
+	fbmode->xres = vm->hactive;
+	fbmode->left_margin = vm->hback_porch;
+	fbmode->right_margin = vm->hfront_porch;
+	fbmode->hsync_len = vm->hsync_len;
+
+	fbmode->yres = vm->vactive;
+	fbmode->upper_margin = vm->vback_porch;
+	fbmode->lower_margin = vm->vfront_porch;
+	fbmode->vsync_len = vm->vsync_len;
+
+	fbmode->pixclock = KHZ2PICOS(vm->pixelclock / 1000);
+
+	fbmode->sync = 0;
+	fbmode->vmode = 0;
+	if (vm->hah)
+		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (vm->vah)
+		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	if (vm->interlaced)
+		fbmode->vmode |= FB_VMODE_INTERLACED;
+	if (vm->doublescan)
+		fbmode->vmode |= FB_VMODE_DOUBLE;
+	fbmode->flag = 0;
+
+	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
+		 vm->hsync_len;
+	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
+		 vm->vsync_len;
+	fbmode->refresh = vm->pixelclock / (htotal * vtotal);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
+#endif
+
+
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c7a9571..4404ec2 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -19,6 +19,7 @@ struct vm_area_struct;
 struct fb_info;
 struct device;
 struct file;
+struct videomode;
 
 /* Definitions below are used in the parsed monitor specs */
 #define FB_DPMS_ACTIVE_OFF	1
@@ -714,6 +715,11 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+extern int fb_videomode_from_videomode(const struct videomode *vm,
+				       struct fb_videomode *fbmode);
+#endif
+
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 3/7] video: add of helper for display timings/videomode
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	David Airlie, Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, Philipp Zabel, Guennady Liakhovetski,
	linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

This adds support for reading display timings from DT into a struct
display_timings. The of_display_timing implementation supports multiple
subnodes. All children are read into an array, that can be queried.

If no native mode is specified, the first subnode will be used.

For cases, where the graphics drivers knows, there can be only one
mode description or where the driver only supports one mode, a helper
function of_get_videomode is added, that gets a struct videomode from DT.
(As this function is implemented in an expensive fashion, it should only
be used in the aforementioned case).

This also demonstrates how of_display_timings may be utilized.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../devicetree/bindings/video/display-timings.txt  |  107 ++++++++++
 drivers/video/Kconfig                              |   15 ++
 drivers/video/Makefile                             |    2 +
 drivers/video/of_display_timing.c                  |  223 ++++++++++++++++++++
 drivers/video/of_videomode.c                       |   48 +++++
 include/linux/of_display_timings.h                 |   20 ++
 include/linux/of_videomode.h                       |   18 ++
 7 files changed, 433 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/display-timings.txt
 create mode 100644 drivers/video/of_display_timing.c
 create mode 100644 drivers/video/of_videomode.c
 create mode 100644 include/linux/of_display_timings.h
 create mode 100644 include/linux/of_videomode.h

diff --git a/Documentation/devicetree/bindings/video/display-timings.txt b/Documentation/devicetree/bindings/video/display-timings.txt
new file mode 100644
index 0000000..2b25d58
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/display-timings.txt
@@ -0,0 +1,107 @@
+display-timings bindings
+============
+
+display-timings node
+--------------------
+
+required properties:
+ - none
+
+optional properties:
+ - native-mode: The native mode for the display, in case multiple modes are
+		provided. When omitted, assume the first node is the native.
+
+timings subnode
+---------------
+
+required properties:
+ - hactive, vactive: Display resolution
+ - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
+   in pixels
+   vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
+   lines
+ - clock-frequency: display clock in Hz
+
+optional properties:
+ - hsync-active: Hsync pulse is active low/high/ignored
+ - vsync-active: Vsync pulse is active low/high/ignored
+ - de-active: Data-Enable pulse is active low/high/ignored
+ - pixelclk-inverted: pixelclock is inverted (active on falling edge)/
+				non-inverted (active on rising edge)/
+				     ignored (ignore property)
+ - interlaced (bool): boolean to enable interlaced mode
+ - doublescan (bool): boolean to enable doublescan mode
+ - doubleclk (bool)
+
+All the optional properties that are not bool follow the following logic:
+    <1>: high active
+    <0>: low active
+    omitted: not used on hardware
+
+There are different ways of describing the capabilities of a display. The devicetree
+representation corresponds to the one commonly found in datasheets for displays.
+If a display supports multiple signal timings, the native-mode can be specified.
+
+The parameters are defined as
+
+  +----------+---------------------------------------------+----------+-------+
+  |          |                ↑                            |          |       |
+  |          |                |vback_porch                 |          |       |
+  |          |                ↓                            |          |       |
+  +----------###############################################----------+-------+
+  |          #                ↑                            #          |       |
+  |          #                |                            #          |       |
+  |  hback   #                |                            #  hfront  | hsync |
+  |   porch  #                |       hactive              #  porch   |  len  |
+  |<-------->#<---------------+--------------------------->#<-------->|<----->|
+  |          #                |                            #          |       |
+  |          #                |vactive                     #          |       |
+  |          #                |                            #          |       |
+  |          #                ↓                            #          |       |
+  +----------###############################################----------+-------+
+  |          |                ↑                            |          |       |
+  |          |                |vfront_porch                |          |       |
+  |          |                ↓                            |          |       |
+  +----------+---------------------------------------------+----------+-------+
+  |          |                ↑                            |          |       |
+  |          |                |vsync_len                   |          |       |
+  |          |                ↓                            |          |       |
+  +----------+---------------------------------------------+----------+-------+
+
+
+Example:
+
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 1080p24 {
+			/* 1920x1080p24 */
+			clock-frequency = <52000000>;
+			hactive = <1920>;
+			vactive = <1080>;
+			hfront-porch = <25>;
+			hback-porch = <25>;
+			hsync-len = <25>;
+			vback-porch = <2>;
+			vfront-porch = <2>;
+			vsync-len = <2>;
+			hsync-active = <1>;
+		};
+	};
+
+Every required property also supports the use of ranges, so the commonly used
+datasheet description with <min typ max>-tuples can be used.
+
+Example:
+
+	timing1: timing {
+		/* 1920x1080p24 */
+		clock-frequency = <148500000>;
+		hactive = <1920>;
+		vactive = <1080>;
+		hsync-len = <0 44 60>;
+		hfront-porch = <80 88 95>;
+		hback-porch = <100 148 160>;
+		vfront-porch = <0 4 6>;
+		vback-porch = <0 36 50>;
+		vsync-len = <0 5 6>;
+	};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 2a23b18..c5b7bcf 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -39,6 +39,21 @@ config DISPLAY_TIMING
 config VIDEOMODE
        bool
 
+config OF_DISPLAY_TIMING
+	bool "Enable OF display timing support"
+	depends on OF
+	select DISPLAY_TIMING
+	help
+	  helper to parse display timings from the devicetree
+
+config OF_VIDEOMODE
+	bool "Enable OF videomode support"
+	depends on OF
+	select VIDEOMODE
+	select OF_DISPLAY_TIMING
+	help
+	  helper to get videomodes from the devicetree
+
 menuconfig FB
 	tristate "Support for frame buffer devices"
 	---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index fc30439..b936b00 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -168,4 +168,6 @@ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
 obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
+obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
 obj-$(CONFIG_VIDEOMODE) += videomode.o
+obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
new file mode 100644
index 0000000..645f43d
--- /dev/null
+++ b/drivers/video/of_display_timing.c
@@ -0,0 +1,223 @@
+/*
+ * OF helpers for parsing display timings
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/of_display_timings.h>
+
+/**
+ * parse_property - parse timing_entry from device_node
+ * @np: device_node with the property
+ * @name: name of the property
+ * @result: will be set to the return value
+ *
+ * DESCRIPTION:
+ * Every display_timing can be specified with either just the typical value or
+ * a range consisting of min/typ/max. This function helps handling this
+ **/
+static int parse_property(const struct device_node *np, const char *name,
+			  struct timing_entry *result)
+{
+	struct property *prop;
+	int length, cells, ret;
+
+	prop = of_find_property(np, name, &length);
+	if (!prop) {
+		pr_err("%s: could not find property %s\n", __func__, name);
+		return -EINVAL;
+	}
+
+	cells = length / sizeof(u32);
+	if (cells = 1) {
+		ret = of_property_read_u32(np, name, &result->typ);
+		result->min = result->typ;
+		result->max = result->typ;
+	} else if (cells = 3) {
+		ret = of_property_read_u32_array(np, name, &result->min, cells);
+	} else {
+		pr_err("%s: illegal timing specification in %s\n", __func__,
+			name);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * of_get_display_timing - parse display_timing entry from device_node
+ * @np: device_node with the properties
+ **/
+static struct display_timing *of_get_display_timing(const struct device_node
+						    *np)
+{
+	struct display_timing *dt;
+	int ret = 0;
+
+	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
+	if (!dt) {
+		pr_err("%s: could not allocate display_timing struct\n",
+			__func__);
+		return NULL;
+	}
+
+	ret |= parse_property(np, "hback-porch", &dt->hback_porch);
+	ret |= parse_property(np, "hfront-porch", &dt->hfront_porch);
+	ret |= parse_property(np, "hactive", &dt->hactive);
+	ret |= parse_property(np, "hsync-len", &dt->hsync_len);
+	ret |= parse_property(np, "vback-porch", &dt->vback_porch);
+	ret |= parse_property(np, "vfront-porch", &dt->vfront_porch);
+	ret |= parse_property(np, "vactive", &dt->vactive);
+	ret |= parse_property(np, "vsync-len", &dt->vsync_len);
+	ret |= parse_property(np, "clock-frequency", &dt->pixelclock);
+
+	of_property_read_u32(np, "vsync-active", &dt->vsync_pol_active);
+	of_property_read_u32(np, "hsync-active", &dt->hsync_pol_active);
+	of_property_read_u32(np, "de-active", &dt->de_pol_active);
+	of_property_read_u32(np, "pixelclk-inverted", &dt->pixelclk_pol);
+	dt->interlaced = of_property_read_bool(np, "interlaced");
+	dt->doublescan = of_property_read_bool(np, "doublescan");
+
+	if (ret) {
+		pr_err("%s: error reading timing properties\n", __func__);
+		kfree(dt);
+		return NULL;
+	}
+
+	return dt;
+}
+
+/**
+ * of_get_display_timings - parse all display_timing entries from a device_node
+ * @np: device_node with the subnodes
+ **/
+struct display_timings *of_get_display_timings(struct device_node *np)
+{
+	struct device_node *timings_np;
+	struct device_node *entry;
+	struct device_node *native_mode;
+	struct display_timings *disp;
+
+	if (!np) {
+		pr_err("%s: no devicenode given\n", __func__);
+		return NULL;
+	}
+
+	timings_np = of_find_node_by_name(np, "display-timings");
+	if (!timings_np) {
+		pr_err("%s: could not find display-timings node\n", __func__);
+		return NULL;
+	}
+
+	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+	if (!disp) {
+		pr_err("%s: could not allocate struct disp'\n", __func__);
+		goto dispfail;
+	}
+
+	entry = of_parse_phandle(timings_np, "native-mode", 0);
+	/* assume first child as native mode if none provided */
+	if (!entry)
+		entry = of_get_next_child(np, NULL);
+	/* if there is no child, it is useless to go on */
+	if (!entry) {
+		pr_err("%s: no timing specifications given\n", __func__);
+		goto entryfail;
+	}
+
+	pr_info("%s: using %s as default timing\n", __func__, entry->name);
+
+	native_mode = entry;
+
+	disp->num_timings = of_get_child_count(timings_np);
+	if (disp->num_timings = 0) {
+		/* should never happen, as entry was already found above */
+		pr_err("%s: no timings specified\n", __func__);
+		goto entryfail;
+	}
+
+	disp->timings = kzalloc(sizeof(struct display_timing *) * disp->num_timings,
+				GFP_KERNEL);
+	if (!disp->timings) {
+		pr_err("%s: could not allocate timings array\n", __func__);
+		goto entryfail;
+	}
+
+	disp->num_timings = 0;
+	disp->native_mode = 0;
+
+	for_each_child_of_node(timings_np, entry) {
+		struct display_timing *dt;
+
+		dt = of_get_display_timing(entry);
+		if (!dt) {
+			/*
+			 * to not encourage wrong devicetrees, fail in case of
+			 * an error
+			 */
+			pr_err("%s: error in timing %d\n", __func__,
+			       disp->num_timings + 1);
+			goto timingfail;
+		}
+
+		if (native_mode = entry)
+			disp->native_mode = disp->num_timings;
+
+		disp->timings[disp->num_timings] = dt;
+		disp->num_timings++;
+	}
+	of_node_put(timings_np);
+	/*
+	 * native_mode points to the device_node returned by of_parse_phandle
+	 * therefore call of_node_put on it
+	 */
+	of_node_put(native_mode);
+
+	if (disp->num_timings > 0)
+		pr_info("%s: got %d timings. Using timing #%d as default\n",
+			__func__, disp->num_timings, disp->native_mode + 1);
+	else {
+		pr_err("%s: no valid timings specified\n", __func__);
+		display_timings_release(disp);
+		return NULL;
+	}
+	return disp;
+
+timingfail:
+	if (native_mode)
+		of_node_put(native_mode);
+	display_timings_release(disp);
+entryfail:
+	if (disp)
+		kfree(disp);
+dispfail:
+	of_node_put(timings_np);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_get_display_timings);
+
+/**
+ * of_display_timings_exists - check if a display-timings node is provided
+ * @np: device_node with the timing
+ **/
+int of_display_timings_exists(const struct device_node *np)
+{
+	struct device_node *timings_np;
+
+	if (!np)
+		return -EINVAL;
+
+	timings_np = of_parse_phandle(np, "display-timings", 0);
+	if (!timings_np)
+		return -EINVAL;
+
+	of_node_put(timings_np);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(of_display_timings_exists);
diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
new file mode 100644
index 0000000..358aa56
--- /dev/null
+++ b/drivers/video/of_videomode.c
@@ -0,0 +1,48 @@
+/*
+ * generic videomode helper
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/of.h>
+#include <linux/of_display_timings.h>
+#include <linux/of_videomode.h>
+#include <linux/export.h>
+
+/**
+ * of_get_videomode - get the videomode #<index> from devicetree
+ * @np - devicenode with the display_timings
+ * @vm - set to return value
+ * @index - index into list of display_timings
+ * DESCRIPTION:
+ * Get a list of all display timings and put the one
+ * specified by index into *vm. This function should only be used, if
+ * only one videomode is to be retrieved. A driver that needs to work
+ * with multiple/all videomodes should work with
+ * of_get_display_timings instead.
+ **/
+int of_get_videomode(struct device_node *np, struct videomode *vm,
+		     int index)
+{
+	struct display_timings *disp;
+	int ret;
+
+	disp = of_get_display_timings(np);
+	if (!disp) {
+		pr_err("%s: no timings specified\n", __func__);
+		return -EINVAL;
+	}
+
+	if (index = OF_USE_NATIVE_MODE)
+		index = disp->native_mode;
+
+	ret = videomode_from_timing(disp, vm, index);
+	if (ret)
+		return ret;
+
+	display_timings_release(disp);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_videomode);
diff --git a/include/linux/of_display_timings.h b/include/linux/of_display_timings.h
new file mode 100644
index 0000000..b3e3455
--- /dev/null
+++ b/include/linux/of_display_timings.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * display timings of helpers
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_DISPLAY_TIMINGS_H
+#define __LINUX_OF_DISPLAY_TIMINGS_H
+
+#include <linux/display_timing.h>
+#include <linux/of.h>
+
+#define OF_USE_NATIVE_MODE -1
+
+struct display_timings *of_get_display_timings(struct device_node *np);
+int of_display_timings_exists(const struct device_node *np);
+
+#endif
diff --git a/include/linux/of_videomode.h b/include/linux/of_videomode.h
new file mode 100644
index 0000000..a72ad78
--- /dev/null
+++ b/include/linux/of_videomode.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * videomode of-helpers
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_VIDEOMODE_H
+#define __LINUX_OF_VIDEOMODE_H
+
+#include <linux/videomode.h>
+#include <linux/of.h>
+
+int of_get_videomode(struct device_node *np, struct videomode *vm,
+		     int index);
+
+#endif /* __LINUX_OF_VIDEOMODE_H */
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 2/7] video: add display_timing and videomode
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

Add display_timing structure and the according helper functions. This allows
the description of a display via its supported timing parameters.

Also, add helper functions to convert from display timings to a generic videomode
structure.

The struct display_timing specifies all needed parameters to describe the signal
properties of a display in one mode. This includes
	- ranges for signals that may have min-, max- and typical values
	- single integers for signals that can be on, off or are ignored
	- booleans for signals that are either on or off

As a display may support multiple modes like this, a struct display_timings is
added, that holds all given struct display_timing pointers and declares the
native mode of the display.

Although a display may state that a signal can be in a range, it is driven with
fixed values that indicate a videomode. Therefore graphic drivers don't need all
the information of struct display_timing, but would generate a videomode from
the given set of supported signal timings and work with that.

The video subsystems all define their own structs that describe a mode and work
with that (e.g. fb_videomode or drm_display_mode). To slowly replace all those
various structures and allow code reuse across those subsystems, add struct
videomode as a generic description.

This patch only includes the most basic fields in struct videomode. All missing
fields that are needed to have a really generic video mode description can be
added at a later stage.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/Kconfig          |    6 +++
 drivers/video/Makefile         |    2 +
 drivers/video/display_timing.c |   24 ++++++++++
 drivers/video/videomode.c      |   45 +++++++++++++++++
 include/linux/display_timing.h |  104 ++++++++++++++++++++++++++++++++++++++++
 include/linux/videomode.h      |   52 ++++++++++++++++++++
 6 files changed, 233 insertions(+)
 create mode 100644 drivers/video/display_timing.c
 create mode 100644 drivers/video/videomode.c
 create mode 100644 include/linux/display_timing.h
 create mode 100644 include/linux/videomode.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d08d799..2a23b18 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -33,6 +33,12 @@ config VIDEO_OUTPUT_CONTROL
 	  This framework adds support for low-level control of the video 
 	  output switch.
 
+config DISPLAY_TIMING
+       bool
+
+config VIDEOMODE
+       bool
+
 menuconfig FB
 	tristate "Support for frame buffer devices"
 	---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 23e948e..fc30439 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -167,3 +167,5 @@ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
+obj-$(CONFIG_VIDEOMODE) += videomode.o
diff --git a/drivers/video/display_timing.c b/drivers/video/display_timing.c
new file mode 100644
index 0000000..ac9bbbc
--- /dev/null
+++ b/drivers/video/display_timing.c
@@ -0,0 +1,24 @@
+/*
+ * generic display timing functions
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/display_timing.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+
+void display_timings_release(struct display_timings *disp)
+{
+	if (disp->timings) {
+		unsigned int i;
+
+		for (i = 0; i < disp->num_timings; i++)
+			kfree(disp->timings[i]);
+		kfree(disp->timings);
+	}
+	kfree(disp);
+}
+EXPORT_SYMBOL_GPL(display_timings_release);
diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c
new file mode 100644
index 0000000..86a8558
--- /dev/null
+++ b/drivers/video/videomode.c
@@ -0,0 +1,45 @@
+/*
+ * generic display timing functions
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/display_timing.h>
+#include <linux/kernel.h>
+#include <linux/videomode.h>
+
+int videomode_from_timing(const struct display_timings *disp,
+			  struct videomode *vm, unsigned int index)
+{
+	struct display_timing *dt;
+
+	dt = display_timings_get(disp, index);
+	if (!dt)
+		return -EINVAL;
+
+	vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP);
+	vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
+	vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
+	vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
+	vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
+
+	vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
+	vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
+	vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
+	vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
+
+	vm->vah = dt->vsync_pol_active;
+	vm->hah = dt->hsync_pol_active;
+	vm->de = dt->de_pol_active;
+	vm->pixelclk_pol = dt->pixelclk_pol;
+
+	vm->interlaced = dt->interlaced;
+	vm->doublescan = dt->doublescan;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(videomode_from_timing);
diff --git a/include/linux/display_timing.h b/include/linux/display_timing.h
new file mode 100644
index 0000000..b8922ea
--- /dev/null
+++ b/include/linux/display_timing.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * description of display timings
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_DISPLAY_TIMINGS_H
+#define __LINUX_DISPLAY_TIMINGS_H
+
+#include <linux/types.h>
+
+/*
+ * A single signal can be specified via a range with a typical value, that lies
+ * somewhere inbetween. Do not use an array, to prevent any confusion about the
+ * meaning of every entry.
+ */
+struct timing_entry {
+	u32 min;
+	u32 typ;
+	u32 max;
+};
+
+enum timing_entry_index {
+	TE_MIN = 0,
+	TE_TYP = 1,
+	TE_MAX = 2,
+};
+
+/*
+ * Single "mode" entry. This describes one set of signal timings a display can
+ * have in one setting. This struct can later be converted to struct videomode
+ * (see include/linux/videomode.h). As each timing_entry can be defined as a
+ * range, one struct display_timing may become multiple struct videomodes.
+ */
+struct display_timing {
+	struct timing_entry pixelclock;
+
+	struct timing_entry hactive;
+	struct timing_entry hfront_porch;
+	struct timing_entry hback_porch;
+	struct timing_entry hsync_len;
+
+	struct timing_entry vactive;
+	struct timing_entry vfront_porch;
+	struct timing_entry vback_porch;
+	struct timing_entry vsync_len;
+
+	unsigned int vsync_pol_active;
+	unsigned int hsync_pol_active;
+	unsigned int de_pol_active;
+	unsigned int pixelclk_pol;
+	bool interlaced;
+	bool doublescan;
+};
+
+/*
+ * This describes all timing settings a display provides.
+ * The native_mode is the default setting for this display. It can be specified
+ * in the devicetree or will be the first that is provided. Drivers that can
+ * handle multiple videomode should work with this struct and convert each entry
+ * to the desired end result.
+ */
+struct display_timings {
+	unsigned int num_timings;
+	unsigned int native_mode;
+
+	struct display_timing **timings;
+};
+
+/* get value specified by index from struct timing_entry */
+static inline u32 display_timing_get_value(const struct timing_entry *te,
+					   enum timing_entry_index index)
+{
+	switch (index) {
+	case TE_MIN:
+		return te->min;
+		break;
+	case TE_TYP:
+		return te->typ;
+		break;
+	case TE_MAX:
+		return te->max;
+		break;
+	default:
+		return te->typ;
+	}
+}
+
+/* get one entry from struct display_timings */
+static inline struct display_timing *display_timings_get(const struct
+							 display_timings *disp,
+							 unsigned int index)
+{
+	if (disp->num_timings > index)
+		return disp->timings[index];
+	else
+		return NULL;
+}
+
+void display_timings_release(struct display_timings *disp);
+
+#endif
diff --git a/include/linux/videomode.h b/include/linux/videomode.h
new file mode 100644
index 0000000..41749f2
--- /dev/null
+++ b/include/linux/videomode.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * generic videomode description
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_VIDEOMODE_H
+#define __LINUX_VIDEOMODE_H
+
+struct display_timings;
+
+/*
+ * Subsystem independent description of a videomode.
+ * Can be generated from struct display_timing.
+ */
+struct videomode {
+	u32 pixelclock;		/* pixelclock in Hz */
+
+	u32 hactive;
+	u32 hfront_porch;
+	u32 hback_porch;
+	u32 hsync_len;
+
+	u32 vactive;
+	u32 vfront_porch;
+	u32 vback_porch;
+	u32 vsync_len;
+
+	u32 hah;		/* hsync active high */
+	u32 vah;		/* vsync active high */
+	u32 de;			/* data enable */
+	u32 pixelclk_pol;
+
+	bool interlaced;
+	bool doublescan;
+};
+
+/**
+ * videomode_from_timing - convert display timing to videomode
+ * @disp: structure with all possible timing entries
+ * @vm: return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function converts a struct display_timing to a struct videomode.
+ */
+int videomode_from_timing(const struct display_timings *disp,
+			  struct videomode *vm, unsigned int index);
+
+#endif
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 1/7] viafb: rename display_timing to via_display_timing
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1353600015-6974-1-git-send-email-s.trumtrar-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>

The struct display_timing is specific to the via subsystem. The naming leads to
collisions with the new struct display_timing, that is supposed to be a shared
struct between different subsystems.
To clean this up, prepend the existing struct with the subsystem it is specific
to.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/video/via/hw.c              |    6 +++---
 drivers/video/via/hw.h              |    2 +-
 drivers/video/via/lcd.c             |    2 +-
 drivers/video/via/share.h           |    2 +-
 drivers/video/via/via_modesetting.c |    8 ++++----
 drivers/video/via/via_modesetting.h |    6 +++---
 6 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 898590d..5563c67 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1467,10 +1467,10 @@ void viafb_set_vclock(u32 clk, int set_iga)
 	via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
 }
 
-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres)
 {
-	struct display_timing timing;
+	struct via_display_timing timing;
 	u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
 
 	timing.hor_addr = cxres;
@@ -1491,7 +1491,7 @@ struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres, int iga)
 {
-	struct display_timing crt_reg = var_to_timing(var,
+	struct via_display_timing crt_reg = var_to_timing(var,
 		cxres ? cxres : var->xres, cyres ? cyres : var->yres);
 
 	if (iga = IGA1)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 6be243c..c3f2572 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -637,7 +637,7 @@ extern int viafb_LCD_ON;
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
 
-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres);
 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres, int iga);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 1650379..022b0df 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -549,7 +549,7 @@ void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
 	int panel_hres = plvds_setting_info->lcd_panel_hres;
 	int panel_vres = plvds_setting_info->lcd_panel_vres;
 	u32 clock;
-	struct display_timing timing;
+	struct via_display_timing timing;
 	struct fb_var_screeninfo panel_var;
 	const struct fb_videomode *mode_crt_table, *panel_crt_table;
 
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 3158dfc..65c65c6 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -319,7 +319,7 @@ struct crt_mode_table {
 	int refresh_rate;
 	int h_sync_polarity;
 	int v_sync_polarity;
-	struct display_timing crtc;
+	struct via_display_timing crtc;
 };
 
 struct io_reg {
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
index 0e431ae..0b414b0 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/via/via_modesetting.c
@@ -30,9 +30,9 @@
 #include "debug.h"
 
 
-void via_set_primary_timing(const struct display_timing *timing)
+void via_set_primary_timing(const struct via_display_timing *timing)
 {
-	struct display_timing raw;
+	struct via_display_timing raw;
 
 	raw.hor_total = timing->hor_total / 8 - 5;
 	raw.hor_addr = timing->hor_addr / 8 - 1;
@@ -88,9 +88,9 @@ void via_set_primary_timing(const struct display_timing *timing)
 	via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
 }
 
-void via_set_secondary_timing(const struct display_timing *timing)
+void via_set_secondary_timing(const struct via_display_timing *timing)
 {
-	struct display_timing raw;
+	struct via_display_timing raw;
 
 	raw.hor_total = timing->hor_total - 1;
 	raw.hor_addr = timing->hor_addr - 1;
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
index 06e09fe..f6a6503 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/via/via_modesetting.h
@@ -33,7 +33,7 @@
 #define VIA_PITCH_MAX	0x3FF8
 
 
-struct display_timing {
+struct via_display_timing {
 	u16 hor_total;
 	u16 hor_addr;
 	u16 hor_blank_start;
@@ -49,8 +49,8 @@ struct display_timing {
 };
 
 
-void via_set_primary_timing(const struct display_timing *timing);
-void via_set_secondary_timing(const struct display_timing *timing);
+void via_set_primary_timing(const struct via_display_timing *timing);
+void via_set_secondary_timing(const struct via_display_timing *timing);
 void via_set_primary_address(u32 addr);
 void via_set_secondary_address(u32 addr);
 void via_set_primary_pitch(u32 pitch);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv13 0/7] of: add display helper
From: Steffen Trumtrar @ 2012-11-22 16:00 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Tomi Valkeinen,
	Laurent Pinchart, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	Guennady Liakhovetski, linux-media-u79uwXL29TY76Z2rM5mHXA

Hi!

Changes since v12:
	- rename struct display_timing to via_display_timing in via subsystem
	- fix refreshrate calculation
	- fix "const struct *" warnings
		(reported by: "Manjunathappa, Prakash" <prakash.pm@ti.com>)
	- some CodingStyle fixes
	- rewrite parts of commit messages and display-timings.txt
	- let display_timing_get_value get all values instead of just typical

Regards,
Steffen

Steffen Trumtrar (7):
  viafb: rename display_timing to via_display_timing
  video: add display_timing and videomode
  video: add of helper for display timings/videomode
  fbmon: add videomode helpers
  fbmon: add of_videomode helpers
  drm_modes: add videomode helpers
  drm_modes: add of_videomode helpers

 .../devicetree/bindings/video/display-timings.txt  |  107 ++++++++++
 drivers/gpu/drm/drm_modes.c                        |   69 ++++++
 drivers/video/Kconfig                              |   21 ++
 drivers/video/Makefile                             |    4 +
 drivers/video/display_timing.c                     |   24 +++
 drivers/video/fbmon.c                              |   84 ++++++++
 drivers/video/of_display_timing.c                  |  223 ++++++++++++++++++++
 drivers/video/of_videomode.c                       |   48 +++++
 drivers/video/via/hw.c                             |    6 +-
 drivers/video/via/hw.h                             |    2 +-
 drivers/video/via/lcd.c                            |    2 +-
 drivers/video/via/share.h                          |    2 +-
 drivers/video/via/via_modesetting.c                |    8 +-
 drivers/video/via/via_modesetting.h                |    6 +-
 drivers/video/videomode.c                          |   45 ++++
 include/drm/drmP.h                                 |   12 ++
 include/linux/display_timing.h                     |  104 +++++++++
 include/linux/fb.h                                 |   12 ++
 include/linux/of_display_timings.h                 |   20 ++
 include/linux/of_videomode.h                       |   18 ++
 include/linux/videomode.h                          |   52 +++++
 21 files changed, 856 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/video/display-timings.txt
 create mode 100644 drivers/video/display_timing.c
 create mode 100644 drivers/video/of_display_timing.c
 create mode 100644 drivers/video/of_videomode.c
 create mode 100644 drivers/video/videomode.c
 create mode 100644 include/linux/display_timing.h
 create mode 100644 include/linux/of_display_timings.h
 create mode 100644 include/linux/of_videomode.h
 create mode 100644 include/linux/videomode.h

-- 
1.7.10.4


^ permalink raw reply

* Re: [PATCH 2/2] OMAP: DSS: panel-n8x0: register the DSS driver after SPI probe
From: Aaro Koskinen @ 2012-11-22 15:56 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev
In-Reply-To: <50AE4306.60203@ti.com>

On Thu, Nov 22, 2012 at 05:21:42PM +0200, Tomi Valkeinen wrote:
> On 2012-11-22 17:17, Aaro Koskinen wrote:
> > On Thu, Nov 22, 2012 at 02:18:57PM +0200, Tomi Valkeinen wrote:
> >> On 2012-11-21 21:48, Aaro Koskinen wrote:
> >>> Register the DSS driver after SPI probe. This simplifies the
> >>> initialization. This is similar to what is being done e.g.
> >>> in panel-acx565akm.
> >>
> >> Is this a fix? The description sounds like it's just a cleanup.
> > 
> > Yes, it's a cleanup. I should have sent it separately, sorry.
> 
> Ok. Did you actually manage to test it?

Yes, the patch works but there are still issues and I can't get the
display yet alive:

[    4.081390] n8x0_panel display0: invalid s1d1374x revision 00
[    4.087738] omapfb omapfb: Failed to enable display 'lcd'
[    4.093475] omapfb omapfb: failed to initialize default display

For some reason all the blizzard_read_reg()s return just zeroes. I have
set up the panel_reset and ctrl_pwrdown GPIOs (30, 15) according to the
Maemo kernel, but maybe there's still more initializations I need to do
from the board file...

> I haven't tested N800 for ages, as I don't have a serial console for
> my N800, and last times I've tried I didn't manage to get it to boot.

It works. I use busybox/dropbear/USB networking to get a "console".

A.

^ permalink raw reply

* Re: [PATCH 2/2] OMAP: DSS: panel-n8x0: register the DSS driver after SPI probe
From: Tomi Valkeinen @ 2012-11-22 15:21 UTC (permalink / raw)
  To: Aaro Koskinen; +Cc: linux-omap, linux-fbdev
In-Reply-To: <20121122151728.GA13187@blackmetal.musicnaut.iki.fi>

[-- Attachment #1: Type: text/plain, Size: 915 bytes --]

On 2012-11-22 17:17, Aaro Koskinen wrote:
> On Thu, Nov 22, 2012 at 02:18:57PM +0200, Tomi Valkeinen wrote:
>> Hi,
>>
>> On 2012-11-21 21:48, Aaro Koskinen wrote:
>>> Register the DSS driver after SPI probe. This simplifies the
>>> initialization. This is similar to what is being done e.g.
>>> in panel-acx565akm.
>>
>> Is this a fix? The description sounds like it's just a cleanup.
> 
> Yes, it's a cleanup. I should have sent it separately, sorry.

Ok. Did you actually manage to test it? I haven't tested N800 for ages,
as I don't have a serial console for my N800, and last times I've tried
I didn't manage to get it to boot.

>> The first patch in the series needs to be sent for the next -rc, right?
> 
> Yes, it's fixing regression. There are OMAP2 boards with display
> configured (e.g. board-apollon) and those will see probe failing.

Ok, I'll queue it for next -rc.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* Re: [PATCH 2/2] OMAP: DSS: panel-n8x0: register the DSS driver after SPI probe
From: Aaro Koskinen @ 2012-11-22 15:17 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: linux-omap, linux-fbdev
In-Reply-To: <50AE1831.90308@ti.com>

On Thu, Nov 22, 2012 at 02:18:57PM +0200, Tomi Valkeinen wrote:
> Hi,
> 
> On 2012-11-21 21:48, Aaro Koskinen wrote:
> > Register the DSS driver after SPI probe. This simplifies the
> > initialization. This is similar to what is being done e.g.
> > in panel-acx565akm.
> 
> Is this a fix? The description sounds like it's just a cleanup.

Yes, it's a cleanup. I should have sent it separately, sorry.

> The first patch in the series needs to be sent for the next -rc, right?

Yes, it's fixing regression. There are OMAP2 boards with display
configured (e.g. board-apollon) and those will see probe failing.

A.

^ permalink raw reply

* Re: [GIT PULL FOR v3.8] SH Mobile LCDC patches
From: Laurent Pinchart @ 2012-11-22 15:01 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <2641878.cGkiV3BMeH@avalon>

[-- Attachment #1: Type: text/plain, Size: 3341 bytes --]

Hi Tomi,

On Thursday 22 November 2012 16:50:35 Tomi Valkeinen wrote:
> On 2012-11-22 16:39, Laurent Pinchart wrote:
> > Hi Tomi,
> > 
> > Thank you for taking care of pull requests for the v3.8 merge window.
> > Here's one already :-)
> > 
> > The following changes since commit
> > f4a75d2eb7b1e2206094b901be09adb31ba63681:
> >   Linux 3.7-rc6 (2012-11-16 17:42:40 -0800)
> > 
> > are available in the git repository at:
> >   git://linuxtv.org/pinchartl/fbdev.git lcdc-next
> > 
> > Hideki EIRAKU (1):
> >  fbdev: sh_mobile_lcdc: use dma_mmap_coherent
> > 
> > Laurent Pinchart (19):
> >  fbdev: sh_mobile_lcdc: Get display dimensions from the channel structure
> >  fbdev: sh_mobile_lcdc: Rename mode argument to modes
> >  fbdev: sh_mobile_lcdc: Remove priv argument from channel and overlay init
> >  ARM: mach-shmobile: ag5evm: Add LCDC tx_dev field to platform data
> >  fbdev: sh_mipi_dsi: Add channel field to platform data
> >  ARM: mach-shmobile: Initiliaze the new sh_mipi_dsi_info channel field
> >  fbdev: sh_mipi_dsi: Use the sh_mipi_dsi_info channel field
> >  fbdev: sh_mipi_dsi: Use the LCDC entity default mode
> >  fbdev: sh_mipi_dsi: Remove last reference to LCDC platform data
> >  ARM: mach-shmobile: Remove the unused sh_mipi_dsi_info lcd_chan field
> >  fbdev: sh_mipi_dsi: Remove the unused sh_mipi_dsi_info lcd_chan field
> >  fbdev: sh_mobile_lcdc: Store the backlight brightness internally
> >  ARM: mach-shmobile: mackerel: Removed unused get_brightness callback
> >  sh: ap325rxa: Remove unused get_brightness LCDC callback
> >  sh: ecovec24: Remove unused get_brightness LCDC callback
> >  fbdev: sh_mobile_lcdc: Remove unused get_brightness pdata callback
> >  ARM: mach-shmobile: ag5evm: Use the backlight API for brightness control
> >  sh: kfr2r09: Use the backlight API for brightness control
> >  fbdev: sh_mobile_lcdc: Make sh_mobile_lcdc_sys_bus_ops static
> >  
> >  arch/arm/mach-shmobile/board-ag5evm.c       |  198 ++++++++++++----------
> >  arch/arm/mach-shmobile/board-ap4evb.c       |    4 +-
> >  arch/arm/mach-shmobile/board-mackerel.c     |    6 -
> >  arch/sh/boards/mach-ap325rxa/setup.c        |    6 -
> >  arch/sh/boards/mach-ecovec24/setup.c        |    6 -
> >  arch/sh/boards/mach-kfr2r09/lcd_wqvga.c     |   16 +--
> >  arch/sh/boards/mach-kfr2r09/setup.c         |    7 +-
> >  arch/sh/include/mach-kfr2r09/mach/kfr2r09.h |    6 +-
> >  drivers/video/sh_mipi_dsi.c                 |   69 ++++------
> >  drivers/video/sh_mobile_lcdcfb.c            |   74 +++++++----
> >  drivers/video/sh_mobile_lcdcfb.h            |    1 +
> >  include/video/sh_mipi_dsi.h                 |    4 +-
> >  include/video/sh_mobile_lcdc.h              |    1 -
> >  13 files changed, 192 insertions(+), 206 deletions(-)
> 
> Well, this does look a bit scary. It's more arch changes than fb
> changes... But all the arch patches seem to be acked by somebody else,
> presumably somebody maintaining the arch stuff, so I guess it's ok if
> these cannot go separately through arm/sh tree.

I forgot to mention that this pull request has been submitted previously, and 
the arch changes can indeed go through fbdev. They need to be interleaved with 
the fbdev changes to avoid bisection breakages.

Sorry for sending you such a scary beast as your first pull request :-)

-- 
Regards,

Laurent Pinchart

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* Re: [GIT PULL FOR v3.8] SH Mobile LCDC patches
From: Tomi Valkeinen @ 2012-11-22 14:50 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <2641878.cGkiV3BMeH@avalon>

[-- Attachment #1: Type: text/plain, Size: 3024 bytes --]

On 2012-11-22 16:39, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for taking care of pull requests for the v3.8 merge window. Here's 
> one already :-)
> 
> The following changes since commit f4a75d2eb7b1e2206094b901be09adb31ba63681:
> 
>   Linux 3.7-rc6 (2012-11-16 17:42:40 -0800)
> 
> are available in the git repository at:
>   git://linuxtv.org/pinchartl/fbdev.git lcdc-next
> 
> Hideki EIRAKU (1):
>       fbdev: sh_mobile_lcdc: use dma_mmap_coherent
> 
> Laurent Pinchart (19):
>       fbdev: sh_mobile_lcdc: Get display dimensions from the channel structure
>       fbdev: sh_mobile_lcdc: Rename mode argument to modes
>       fbdev: sh_mobile_lcdc: Remove priv argument from channel and overlay 
> init
>       ARM: mach-shmobile: ag5evm: Add LCDC tx_dev field to platform data
>       fbdev: sh_mipi_dsi: Add channel field to platform data
>       ARM: mach-shmobile: Initiliaze the new sh_mipi_dsi_info channel field
>       fbdev: sh_mipi_dsi: Use the sh_mipi_dsi_info channel field
>       fbdev: sh_mipi_dsi: Use the LCDC entity default mode
>       fbdev: sh_mipi_dsi: Remove last reference to LCDC platform data
>       ARM: mach-shmobile: Remove the unused sh_mipi_dsi_info lcd_chan field
>       fbdev: sh_mipi_dsi: Remove the unused sh_mipi_dsi_info lcd_chan field
>       fbdev: sh_mobile_lcdc: Store the backlight brightness internally
>       ARM: mach-shmobile: mackerel: Removed unused get_brightness callback
>       sh: ap325rxa: Remove unused get_brightness LCDC callback
>       sh: ecovec24: Remove unused get_brightness LCDC callback
>       fbdev: sh_mobile_lcdc: Remove unused get_brightness pdata callback
>       ARM: mach-shmobile: ag5evm: Use the backlight API for brightness control
>       sh: kfr2r09: Use the backlight API for brightness control
>       fbdev: sh_mobile_lcdc: Make sh_mobile_lcdc_sys_bus_ops static
> 
>  arch/arm/mach-shmobile/board-ag5evm.c       |  198 ++++++++++++++------------
>  arch/arm/mach-shmobile/board-ap4evb.c       |    4 +-
>  arch/arm/mach-shmobile/board-mackerel.c     |    6 -
>  arch/sh/boards/mach-ap325rxa/setup.c        |    6 -
>  arch/sh/boards/mach-ecovec24/setup.c        |    6 -
>  arch/sh/boards/mach-kfr2r09/lcd_wqvga.c     |   16 +--
>  arch/sh/boards/mach-kfr2r09/setup.c         |    7 +-
>  arch/sh/include/mach-kfr2r09/mach/kfr2r09.h |    6 +-
>  drivers/video/sh_mipi_dsi.c                 |   69 ++++------
>  drivers/video/sh_mobile_lcdcfb.c            |   74 +++++++----
>  drivers/video/sh_mobile_lcdcfb.h            |    1 +
>  include/video/sh_mipi_dsi.h                 |    4 +-
>  include/video/sh_mobile_lcdc.h              |    1 -
>  13 files changed, 192 insertions(+), 206 deletions(-)

Well, this does look a bit scary. It's more arch changes than fb
changes... But all the arch patches seem to be acked by somebody else,
presumably somebody maintaining the arch stuff, so I guess it's ok if
these cannot go separately through arm/sh tree.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* [GIT PULL FOR v3.8] SH Mobile LCDC patches
From: Laurent Pinchart @ 2012-11-22 14:39 UTC (permalink / raw)
  To: linux-fbdev

Hi Tomi,

Thank you for taking care of pull requests for the v3.8 merge window. Here's 
one already :-)

The following changes since commit f4a75d2eb7b1e2206094b901be09adb31ba63681:

  Linux 3.7-rc6 (2012-11-16 17:42:40 -0800)

are available in the git repository at:
  git://linuxtv.org/pinchartl/fbdev.git lcdc-next

Hideki EIRAKU (1):
      fbdev: sh_mobile_lcdc: use dma_mmap_coherent

Laurent Pinchart (19):
      fbdev: sh_mobile_lcdc: Get display dimensions from the channel structure
      fbdev: sh_mobile_lcdc: Rename mode argument to modes
      fbdev: sh_mobile_lcdc: Remove priv argument from channel and overlay 
init
      ARM: mach-shmobile: ag5evm: Add LCDC tx_dev field to platform data
      fbdev: sh_mipi_dsi: Add channel field to platform data
      ARM: mach-shmobile: Initiliaze the new sh_mipi_dsi_info channel field
      fbdev: sh_mipi_dsi: Use the sh_mipi_dsi_info channel field
      fbdev: sh_mipi_dsi: Use the LCDC entity default mode
      fbdev: sh_mipi_dsi: Remove last reference to LCDC platform data
      ARM: mach-shmobile: Remove the unused sh_mipi_dsi_info lcd_chan field
      fbdev: sh_mipi_dsi: Remove the unused sh_mipi_dsi_info lcd_chan field
      fbdev: sh_mobile_lcdc: Store the backlight brightness internally
      ARM: mach-shmobile: mackerel: Removed unused get_brightness callback
      sh: ap325rxa: Remove unused get_brightness LCDC callback
      sh: ecovec24: Remove unused get_brightness LCDC callback
      fbdev: sh_mobile_lcdc: Remove unused get_brightness pdata callback
      ARM: mach-shmobile: ag5evm: Use the backlight API for brightness control
      sh: kfr2r09: Use the backlight API for brightness control
      fbdev: sh_mobile_lcdc: Make sh_mobile_lcdc_sys_bus_ops static

 arch/arm/mach-shmobile/board-ag5evm.c       |  198 ++++++++++++++------------
 arch/arm/mach-shmobile/board-ap4evb.c       |    4 +-
 arch/arm/mach-shmobile/board-mackerel.c     |    6 -
 arch/sh/boards/mach-ap325rxa/setup.c        |    6 -
 arch/sh/boards/mach-ecovec24/setup.c        |    6 -
 arch/sh/boards/mach-kfr2r09/lcd_wqvga.c     |   16 +--
 arch/sh/boards/mach-kfr2r09/setup.c         |    7 +-
 arch/sh/include/mach-kfr2r09/mach/kfr2r09.h |    6 +-
 drivers/video/sh_mipi_dsi.c                 |   69 ++++------
 drivers/video/sh_mobile_lcdcfb.c            |   74 +++++++----
 drivers/video/sh_mobile_lcdcfb.h            |    1 +
 include/video/sh_mipi_dsi.h                 |    4 +-
 include/video/sh_mobile_lcdc.h              |    1 -
 13 files changed, 192 insertions(+), 206 deletions(-)

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* Temporary fbdev maintainership for 3.8 merge window
From: Tomi Valkeinen @ 2012-11-22 14:21 UTC (permalink / raw)
  To: linux-fbdev

[-- Attachment #1: Type: text/plain, Size: 909 bytes --]

Hi Florian, all,

Florian told me he's very busy for the time being, and this probably
last at least until sometime early December. The merge window is coming
near, and instead of everybody sending their fbdev related patches
directly to Linus, I offer my services as a temporary fbdev maintainer
for the next merge window.

Florian, say if this is not what you intended (the details were left a
bit open in our private emails).

I don't have the capacity to really review much of the patches, so I'd
probably only pull things that are quite clear or specific to one
particular driver.

If you have just a few patches, I can apply them directly. If you have
more, please send a proper pull request to me.

If you still have some fbdev related fixes for 3.7, send them very soon,
as the next -rc may be the last. I'm planning to send a pull request
with omapdss fixes tomorrow.

 Tomi


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* Re: [PATCH 0/5] OMAPFB: use dma_alloc instead of omap's vram
From: Tomi Valkeinen @ 2012-11-22 13:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPFyZi52e+BPLFQoSn_scdru=MP2NeBUNUkHnym8W3t90JW2jA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 625 bytes --]

Hi,

On 2012-11-21 16:22, Jello huang wrote:
> HI Tomi,
> we need  one rank of cma to allocate the memory for driver in kernel
> space .And the default CMA is for allocating memory frome usespace.So
> if we allocate the memory from the
> default CMA zone ,there maybe introduce fragmention to the default CMA
> zone.The kernel space memory donot touch the memory from userspace

Can you elaborate a bit? I didn't understand your point. Are you saying
each kernel driver that uses dma_alloc should have their own CMA zone?
That doesn't make sense...

How do you allocate CMA memory from userspace?

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* Re: [PATCHv9 1/3] Runtime Interpreted Power Sequences
From: Grant Likely @ 2012-11-22 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121121151209.GA4048@avionic-0098.adnet.avionic-design.de>

On Wed, Nov 21, 2012 at 3:12 PM, Thierry Reding
<thierry.reding@avionic-design.de> wrote:
> On Thu, Nov 22, 2012 at 12:02:47AM +0900, Alexandre Courbot wrote:
>> Mmmm so maybe I am misinterpreting things, but it looks like we
>> have just buried the power sequences here, haven't we?
>
> I don't think so. In fact I was just starting to think that maybe for
> Tegra we could have a generic panel driver which used power sequences
> to abstract away the pin differences for powering up the panel. Since
> most likely that will be where the differences are there is a lot of
> potential to factor things out into sequences.
>
> Perhaps what we may want to postpone for now is the DT representation
> since that's what Tomi and Grant seem to be mostly opposed to.

Don't give up. I'm am being cautions and trying to think of all the
implications because that is what I have to do as a maintainer. I'm
not opposed to the feature but I need a good level of confidence that
it has been fully thought out.

g.

--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCHv9 1/3] Runtime Interpreted Power Sequences
From: Grant Likely @ 2012-11-22 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <13540495.epaCf4JVn9@percival>

On Wed, 21 Nov 2012 13:23:06 +0900, Alex Courbot <acourbot@nvidia.com> wrote:
> Hi Grant,
> 
> On Wednesday 21 November 2012 05:54:29 Grant Likely wrote:
> > > With the advent of the device tree and of ARM kernels that are not
> > > board-tied, we cannot rely on these board-specific hooks anymore but
> > 
> > This isn't strictly true. It is still perfectly fine to have board
> > specific code when necessary. However, there is strong encouragement to
> > enable that code in device drivers as much as possible and new board
> > files need to have very strong justification.
> 
> But doesn't introducing board-specific code into the kernel just defeats the 
> purpose of the DT? If we extend this logic, we are heading straight back to 
> board-definition files. To a lesser extent than before I agree, but the problem 
> is fundamentally the same.

There is *always* board specific code. There is always something fiddly
enough, complex enough, or just plain ugly enough that it is best
handled in C code. The trick is to make the board-specific stuff the
exception, not the rule.

When you can factor out common behavour (like you are doing here), then
it is a really good candidate for a common binding, but still please
always ask yourself the question is this going to make things better or
worse in the long run.

> > I'm thinking about the scripts as trivial-to-parse ascii strings that
> > have a very simple set of commands. The commands use resources already
> > defined in the node. ie. 'g0' refers to the first entry in the gpios
> > property. 'r0' for the regulator, 'p0' for the pwms, 'd' means delay. By
> > no means take this as the format to use, it is just an example off the
> > top of my head, but it is already way easier to work with than putting
> > each command into a node.
> 
> I'd argue that this opens the door wide open towards having a complete 
> interpreter in the device tree. At least DT nodes restrict what we can do 
> conveniently.

I disagree... see below.

> > The trick is still to define a syntax that doesn't fall apart when it
> > needs to be extended. I would also like to get opinions on whether or
> > not conditionals or loops should be supported (ie. loop waiting for a
> > status to change). If they should then we need to be a lot more careful
> > about the design (and due to my aforementioned nervousness, somebody may
> > need to get me therapy).
> 
> That's IMHO the main argument in favor of using DT nodes here (the syntax 
> extension, not your therapy).

hahaha :-)

> They can be extended simply by adding properties 
> to them, and I was relying on this to make power seqs extensible while keeping 
> things consistent (and backward-compatible). For instance, when we want to 
> support voltage setting in regulators we can just add a "voltage" property for 
> that.
> 
> So to sum up the pros of the current node-base representation:
> - give a "data like" representation of powering sequences (what they should 
> be, actually)
> - puts sanity barriers for not turning power seqs into a real code interpreter
> - easily extensible
> 
> There are probably a few cons, the numbering of steps being one, but at least 
> we don't need to design a new DSL and care too much about extensibility which 
> is, in the nodes case, built-in and free.

No matter how it is encoded, this *IS* a new DSL. Using nodes and
properties doesn't change that. Extensibility is no more built-in and
free with nodes that it is with another encoding. If there aren't clear
guidelines on how to extend it then we'll get weird stuff. For example,
even with the nodes case someone might do this:

	step3 {
		type = "loop";
		count = 10;
		step1 {
			type = "gpio";
			gpio = <&gpio 1>;
			value = 1;
		};
		step2 {
			type = "delay";
			value = 10000;
		};
		step3 {
			type = "gpio";
			gpio = <&gpio 1>;
			value = 0;
		};
		step4 {
			type = "delay";
			value = 10000;
		};
	};

And even while cringing as I type the above, I also have to consider
that looping may just be a valid use case for sequences.

And even here, a very simple sequence fragment required 22 lines of
code.

Next, I'm concerned about where these will show up. Say for instance
there needs to be a power sequence added to an spi bus node. Already spi
bus child nodes have a defined meaning; they are spi slaves. How then
should the sequence be attached to the spi bus?

> If that makes you feel better, maybe we can try and fix what is wrong with the 
> current bindings instead of introducing a new language that will be, by 
> nature, more complex to handle and difficult to extend without breaking things?

Okay, here are 3 concrete objections with the proposed binding:
- The syntax concerns of it being too verbose and it effectively uses
  line numbers for ordering (Do you remember fighting with BASIC?).
- There are many devices that won't be able to use the binding because
  they already have a meaning for child nodes
- I think resources should be declared separate from the sequence based
  on the assumption that multiple steps will be operating on the same
  resource.

I do think that each sequence should be contained within a single
property, but I'm open to other suggestions.

g.

^ permalink raw reply

* Re: [PATCHv9 1/3] Runtime Interpreted Power Sequences
From: Grant Likely @ 2012-11-22 13:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4275468.QAmZy3xUK6@percival>

On Wed, Nov 21, 2012 at 10:00 AM, Alex Courbot <acourbot@nvidia.com> wrote:
> On Wednesday 21 November 2012 16:48:45 Tomi Valkeinen wrote:
>> If the power-off sequence disables a regulator that was supposed to be
>> enabled by the power-on sequence (but wasn't enabled because of an
>> error), the regulator_disable is still called when the driver runs the
>> power-off sequence, isn't it? Regulator enables and disables are ref
>> counted, and the enables should match the disables.
>
> And there collapses my theory.
>
>> > Failures might be better handled if sequences have some "recovery policy"
>> > about what to do when they fail, as mentioned in the link above. As you
>> > pointed out, the driver might not always know enough about the resources
>> > involved to do the right thing.
>>
>> Yes, I think such recovery policy would be needed.
>
> Indeed, from your last paragraph this makes even more sense now.
>
> Oh, and I noticed I forgot to reply to this:
>
>> This I didn't understand. Doesn't "<&pwm 2 xyz>" point to a single
>> device, no matter where and how many times it's used?
>
> That's true - however when dereferencing the phandle, the underlying framework
> will try to acquire the PWM, which will result in failure if the same resource
> is referenced several times.
>
> One could compare the phandles to avoid this, but in your example you must
> know that for PWMs the "xyz" part is not relevant for comparison.
>
> This makes referencing of resources by name much easier to implement and more
> elegant with respect to frameworks leveraging.

I would rather (at least for how the DT bindings settle out) see the
design separate the resource references from the sequence. ie. Declare
which resources are used by a device's sequences all in one place and
have the commands index into that.

g.

^ permalink raw reply

* [PATCH] video: mxsfb: fix typo: 'FAILING' instead of 'FALLING'
From: Lothar Waßmann @ 2012-11-22 12:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1353588555-13168-1-git-send-email-LW@KARO-electronics.de>


Signed-off-by: Lothar Waßmann <LW@KARO-electronics.de>
---
 arch/arm/mach-mxs/mach-mxs.c |    6 +++---
 drivers/video/mxsfb.c        |    6 +++---
 include/linux/mxsfb.h        |    2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index d61b915..6c17cb7 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -42,7 +42,7 @@ static struct fb_videomode mx23evk_video_modes[] = {
 		.hsync_len	= 1,
 		.vsync_len	= 1,
 		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
-				  FB_SYNC_DOTCLK_FAILING_ACT,
+				  FB_SYNC_DOTCLK_FALLING_ACT,
 	},
 };
 
@@ -60,7 +60,7 @@ static struct fb_videomode mx28evk_video_modes[] = {
 		.hsync_len	= 10,
 		.vsync_len	= 10,
 		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
-				  FB_SYNC_DOTCLK_FAILING_ACT,
+				  FB_SYNC_DOTCLK_FALLING_ACT,
 	},
 };
 
@@ -96,7 +96,7 @@ static struct fb_videomode apx4devkit_video_modes[] = {
 		.vsync_len	= 3,
 		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
 				  FB_SYNC_DATA_ENABLE_HIGH_ACT |
-				  FB_SYNC_DOTCLK_FAILING_ACT,
+				  FB_SYNC_DOTCLK_FALLING_ACT,
 	},
 };
 
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index f2a49ef..eb45d32 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -107,7 +107,7 @@
 #define VDCTRL0_ENABLE_PRESENT		(1 << 28)
 #define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
 #define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FAILING	(1 << 25)
+#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
 #define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
 #define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
 #define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
@@ -458,8 +458,8 @@ static int mxsfb_set_par(struct fb_info *fb_info)
 		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
 	if (fb_info->var.sync & FB_SYNC_DATA_ENABLE_HIGH_ACT)
 		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
-	if (fb_info->var.sync & FB_SYNC_DOTCLK_FAILING_ACT)
-		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING;
+	if (fb_info->var.sync & FB_SYNC_DOTCLK_FALLING_ACT)
+		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
 
 	writel(vdctrl0, host->base + LCDC_VDCTRL0);
 
diff --git a/include/linux/mxsfb.h b/include/linux/mxsfb.h
index f14943d..a9eca68 100644
--- a/include/linux/mxsfb.h
+++ b/include/linux/mxsfb.h
@@ -25,7 +25,7 @@
 #define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
 
 #define FB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
-#define FB_SYNC_DOTCLK_FAILING_ACT	(1 << 7) /* failing/negtive edge sampling */
+#define FB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* falling/negative edge sampling */
 
 struct mxsfb_platform_data {
 	struct fb_videomode *mode_list;
-- 
1.7.2.5


^ permalink raw reply related

* [BUGFIX PATCH] video: mxsfb: fix crash when unblanking the display
From: Lothar Waßmann @ 2012-11-22 12:49 UTC (permalink / raw)
  To: linux-arm-kernel

The VDCTRL4 register does not provide the MXS SET/CLR/TOGGLE feature.
The write in mxsfb_disable_controller() sets the data_cnt for the LCD
DMA to 0 which obviously means the max. count for the LCD DMA and
leads to overwriting arbitrary memory when the display is unblanked.

Note: I already sent this patch in December 2011 but noone picked it up obviously.

Signed-off-by: Lothar Waßmann <LW@KARO-electronics.de>
---
 drivers/video/mxsfb.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 49619b4..f2a49ef 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -369,7 +369,8 @@ static void mxsfb_disable_controller(struct fb_info *fb_info)
 		loop--;
 	}
 
-	writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR);
+	reg = readl(host->base + LCDC_VDCTRL4);
+	writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4);
 
 	clk_disable_unprepare(host->clk);
 
-- 
1.7.2.5


^ permalink raw reply related

* Re: [PATCH 2/2] OMAP: DSS: panel-n8x0: register the DSS driver after SPI probe
From: Tomi Valkeinen @ 2012-11-22 12:18 UTC (permalink / raw)
  To: Aaro Koskinen; +Cc: linux-omap, linux-fbdev
In-Reply-To: <1353527332-5216-2-git-send-email-aaro.koskinen@iki.fi>

[-- Attachment #1: Type: text/plain, Size: 352 bytes --]

Hi,

On 2012-11-21 21:48, Aaro Koskinen wrote:
> Register the DSS driver after SPI probe. This simplifies the
> initialization. This is similar to what is being done e.g.
> in panel-acx565akm.

Is this a fix? The description sounds like it's just a cleanup. The
first patch in the series needs to be sent for the next -rc, right?

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* Re: [PATCH v12 3/6] fbmon: add videomode helpers
From: Steffen Trumtrar @ 2012-11-22 11:23 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA, David Airlie, Sascha Hauer,
	Florian Tobias Schandinat,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Guennady Liakhovetski,
	Tomi Valkeinen, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	linux-media-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <2254661.PBsclu7Klj@avalon>

On Thu, Nov 22, 2012 at 10:07:07AM +0100, Laurent Pinchart wrote:
> On Thursday 22 November 2012 09:53:42 Sascha Hauer wrote:
> > On Thu, Nov 22, 2012 at 09:50:10AM +0100, Laurent Pinchart wrote:
> > > On Thursday 22 November 2012 07:20:00 Sascha Hauer wrote:
> > > > On Wed, Nov 21, 2012 at 11:02:44PM +0100, Laurent Pinchart wrote:
> > > > > Hi Steffen,
> > > > > 
> > > > > > +
> > > > > > +	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
> > > > > > +		 vm->hsync_len;
> > > > > > +	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
> > > > > > +		 vm->vsync_len;
> > > > > > +	fbmode->refresh = (vm->pixelclock * 1000) / (htotal * vtotal);
> > > > > 
> > > > > This will fail if vm->pixelclock >= ((1 << 32) / 1000). The easiest
> > > > > solution is probably to use 64-bit computation.
> > > > 
> > > > You have displays with a pixelclock > 4GHz?
> > > 
> > > vm->pixelclock is expressed in Hz. vm->pixelclock * 1000 will thus
> > > overflow if the clock frequency is >= ~4.3 MHz. I have displays with a
> > > clock frequency higher than that :-)
> > 
> > If vm->pixelclock is in Hz, then the * 1000 above is wrong.
> 
> My bad, I though refresh was expressed in mHz. So yes, the above computation 
> is wrong.
>

Okay. I will fix that with the next version...

> BTW it seems that the refreshrate field in struct videomode isn't used. It 
> should then be removed.
> 

...and remove this field.

> I've just realized that the struct videomode fields are not documented. 
> kerneldoc in include/linux/videomode.h would be a good addition.
> 

Regards,
Steffen

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: [PATCHv9 1/3] Runtime Interpreted Power Sequences
From: Alexandre Courbot @ 2012-11-22  9:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdaNmBpfONDpt7zFqLaqfiGm+ELpO-v5gZmM0rEi_AzijQ@mail.gmail.com>

On Thu, Nov 22, 2012 at 5:57 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
> I have the same (limited by experience) opinion. Working sort of
> near som audio drivers I have understood that power sequencing
> is a big issue not only for things like this backlight example, but
> even more so in the area of audio to avoid clicks and pops.
>
> Is it correct to assume that this library will be useful also for ALSA
> SoC type of devices?

There should be nothing against that - provided ALSA's needs remain
similar to the current set of actions (regulators, gpios, ...) it
should be perfectly usable. Can you think of any usage that involves
more than dumb regulator/gpio manipulation?

If power seqs are to be used this way (as opposed to through the DT),
it will become urgent to implement that gpio handlers library we were
talking about in another thread, as we don't want to have GPIO numbers
hard-coded into the sequences.

Alex.

^ permalink raw reply

* [PATCH v2] video console: add a driver for lcd2s character display
From: Lars Poeschel @ 2012-11-22  9:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Lars Poeschel, FlorianSchandinat, mathieu.poirier, linux-fbdev,
	linux-kernel
In-Reply-To: <201211201611.28646.arnd@arndb.de>

From: Lars Poeschel <poeschel@lemonage.de>

This driver allows to use a lcd2s 20x4 character display as
a linux console output device.

Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 drivers/video/console/Kconfig    |   10 ++
 drivers/video/console/Makefile   |    1 +
 drivers/video/console/lcd2scon.c |  360 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 371 insertions(+)
 create mode 100644 drivers/video/console/lcd2scon.c

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index e2c96d0..44fc3bf 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -129,6 +129,16 @@ config STI_CONSOLE
           machines.  Say Y here to build support for it into your kernel.
           The alternative is to use your primary serial port as a console.
 
+config LCD2S_CONSOLE
+        tristate "lcd2s 20x4 character display over I2C console"
+        depends on I2C
+        default n
+        help
+          This is a driver that lets you use the lcd2s 20x4 character display
+          from modtronix engineering as a console output device. The display
+          is a simple single color character display. You have to connect it
+          to an I2C bus.
+
 config FONTS
 	bool "Select compiled-in fonts"
 	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index a862e91..74d5993 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -23,6 +23,7 @@ font-objs += $(font-objs-y)
 obj-$(CONFIG_DUMMY_CONSOLE)       += dummycon.o
 obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
 obj-$(CONFIG_STI_CONSOLE)         += sticon.o sticore.o font.o
+obj-$(CONFIG_LCD2S_CONSOLE)       += lcd2scon.o
 obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
 obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
 obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o
diff --git a/drivers/video/console/lcd2scon.c b/drivers/video/console/lcd2scon.c
new file mode 100644
index 0000000..c139811
--- /dev/null
+++ b/drivers/video/console/lcd2scon.c
@@ -0,0 +1,360 @@
+/*
+ *  console driver for LCD2S 4x20 character displays connected through i2c.
+ *
+ *  This is a driver allowing you to use a LCD2S 4x20 from modtronix
+ *  engineering as console output device.
+ *
+ *  (C) 2012 by Lemonage Software GmbH
+ *  Author: Lars Poeschel <poeschel@lemonage.de>
+ *  All rights reserved.
+ *
+ *  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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console_struct.h>
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include <linux/i2c.h>
+
+#define LCD2S_CMD_CUR_BLINK_OFF		0x10
+#define LCD2S_CMD_CUR_UL_OFF		0x11
+#define LCD2S_CMD_DISPLAY_OFF		0x12
+#define LCD2S_CMD_CUR_BLINK_ON		0x18
+#define LCD2S_CMD_CUR_UL_ON		0x19
+#define LCD2S_CMD_DISPLAY_ON		0x1a
+#define LCD2S_CMD_BACKLIGHT_OFF		0x20
+#define LCD2S_CMD_BACKLIGHT_ON		0x28
+#define LCD2S_CMD_WRITE			0x80
+#define LCD2S_CMD_SHIFT_UP		0x87
+#define LCD2S_CMD_SHIFT_DOWN		0x88
+#define LCD2S_CMD_CUR_ADDR		0x89
+#define LCD2S_CMD_CUR_POS		0x8a
+#define LCD2S_CMD_CUR_RESET		0x8b
+#define LCD2S_CMD_CLEAR			0x8c
+
+#define LCD2S_FIRST			8
+#define LCD2S_LAST			9
+
+#define LCD2S_ROWS			4
+#define LCD2S_COLS			20
+
+struct lcd2s_data {
+	struct i2c_client *i2c;
+	int row;
+	int col;
+	unsigned int cur_blink:1;
+	unsigned int cur_ul:1;
+};
+
+static struct lcd2s_data lcd2s;
+
+static void lcd2s_set_cursor(int row, int col)
+{
+	u8 buf[] = { LCD2S_CMD_CUR_POS, row + 1, col + 1};
+
+	if (row = lcd2s.row && col = lcd2s.col)
+		return;
+
+	i2c_master_send(lcd2s.i2c, buf, sizeof(buf));
+	lcd2s.row = row;
+	lcd2s.col = col;
+}
+
+static void lcd2s_reset_cursor(void)
+{
+	i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CUR_RESET);
+	lcd2s.row = 0;
+	lcd2s.col = 0;
+}
+
+static void lcd2s_increase_cursor(struct vc_data *con, int inc)
+{
+	lcd2s.col += inc;
+	if ((lcd2s.col / con->vc_cols) >= 1) {
+		lcd2s.row += (lcd2s.col / con->vc_cols);
+		lcd2s.col %= con->vc_cols;
+	}
+}
+
+static void lcd2s_cursor_ul_on(void)
+{
+	if (!lcd2s.cur_ul) {
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CUR_UL_ON);
+		lcd2s.cur_ul = 1;
+	}
+}
+
+static void lcd2s_cursor_ul_off(void)
+{
+	if (lcd2s.cur_ul) {
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CUR_UL_OFF);
+		lcd2s.cur_ul = 0;
+	}
+}
+
+static void lcd2s_cursor_blink_on(void)
+{
+	if (!lcd2s.cur_blink) {
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CUR_BLINK_ON);
+		lcd2s.cur_blink = 1;
+	}
+}
+
+static void lcd2s_cursor_blink_off(void)
+{
+	if (lcd2s.cur_blink) {
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CUR_BLINK_OFF);
+		lcd2s.cur_blink = 0;
+	}
+}
+
+static const char *lcd2s_startup(void)
+{
+	return "lcd2s console";
+}
+
+
+/*
+ * init is set if console is currently allocated during init
+ */
+static void lcd2s_init(struct vc_data *con, int init)
+{
+	lcd2s.cur_blink = 0;
+	lcd2s.cur_ul = 0;
+
+	/* turn display on */
+	i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_DISPLAY_ON);
+	i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_BACKLIGHT_ON);
+	i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CLEAR);
+	lcd2s_cursor_ul_on();
+	lcd2s_reset_cursor();
+
+	con->vc_can_do_color = 0;
+	con->vc_hi_font_mask = 0;
+
+	if (init) {
+		con->vc_rows = LCD2S_ROWS;
+		con->vc_cols = LCD2S_COLS;
+	} else
+		vc_resize(con, LCD2S_COLS, LCD2S_ROWS);
+}
+
+static void lcd2s_deinit(struct vc_data *con)
+{
+	i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_DISPLAY_OFF);
+	i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_BACKLIGHT_OFF);
+	lcd2s_cursor_blink_off();
+	lcd2s_cursor_ul_off();
+}
+
+static void lcd2s_clear(struct vc_data *con, int s_row, int s_col,
+			int height, int width)
+{
+	u8 buf[width];
+	int i;
+
+	if (width <= 0 || height <= 0)
+		return;
+
+	/* if the whole display is to clear, we have a single command */
+	if (s_col = 0 && s_row = 0 &&
+		height >= con->vc_rows - 1 && width >= con->vc_cols - 1) {
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_CLEAR);
+		return;
+	}
+
+	for (i = 0; i <= width; i++)
+		buf[i] = ' ';
+
+	for (i = s_col; i <= height; i++) {
+		lcd2s_set_cursor(s_row, i);
+		i2c_master_send(lcd2s.i2c, buf, width);
+	}
+}
+
+static void lcd2s_putc(struct vc_data *con, int data, int row, int col)
+{
+	u8 buf[] = {LCD2S_CMD_WRITE, data};
+
+	lcd2s_set_cursor(row, col);
+
+	i2c_master_send(lcd2s.i2c, buf, sizeof(buf));
+	lcd2s_increase_cursor(con, 1);
+}
+
+static void lcd2s_putcs(struct vc_data *con, const unsigned short *buf,
+			int len, int row, int col)
+{
+	u8 *i2c_buf;
+	int i;
+
+	i2c_buf = kzalloc(len + 1, GFP_KERNEL);
+	if (!i2c_buf)
+		return;
+
+	lcd2s_set_cursor(row, col);
+
+	i2c_buf[0] = LCD2S_CMD_WRITE;
+	for (i = 0; i < len ; i++)
+		i2c_buf[i + 1] = buf[i];
+
+	i2c_master_send(lcd2s.i2c, i2c_buf, len + 1);
+	kfree(i2c_buf);
+	lcd2s_increase_cursor(con, len);
+}
+
+static void lcd2s_cursor(struct vc_data *con, int mode)
+{
+	switch (mode) {
+	case CM_ERASE:
+		lcd2s_cursor_blink_off();
+		lcd2s_cursor_ul_off();
+		break;
+	case CM_MOVE:
+	case CM_DRAW:
+		lcd2s_set_cursor(con->vc_y, con->vc_x);
+
+		switch (con->vc_cursor_type & CUR_HWMASK) {
+		case CUR_UNDERLINE:
+			lcd2s_cursor_ul_on();
+			lcd2s_cursor_blink_off();
+			break;
+		case CUR_NONE:
+			lcd2s_cursor_blink_off();
+			lcd2s_cursor_ul_off();
+			break;
+		default:
+			lcd2s_cursor_blink_on();
+			lcd2s_cursor_ul_off();
+			break;
+		}
+		break;
+	}
+}
+
+static int lcd2s_scroll(struct vc_data *con, int top, int bot,
+			int dir, int lines)
+{
+	/* we can only scroll the whole display */
+	if (top = 0 && bot = con->vc_rows) {
+		while (lines--) {
+			switch (dir) {
+			case SM_UP:
+				i2c_smbus_write_byte(lcd2s.i2c,
+					LCD2S_CMD_SHIFT_UP);
+				break;
+			case SM_DOWN:
+				i2c_smbus_write_byte(lcd2s.i2c,
+					LCD2S_CMD_SHIFT_DOWN);
+				break;
+			}
+		}
+		return 0;
+	}
+	return 1;
+}
+
+static void lcd2s_bmove(struct vc_data *conp, int s_row, int s_col,
+			int d_row, int d_col, int height, int width)
+{
+}
+
+static int lcd2s_switch(struct vc_data *con)
+{
+	return 1;
+}
+
+static int lcd2s_blank(struct vc_data *con, int blank, int mode_switch)
+{
+	switch (blank) {
+	case 0:		/* unblank */
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_DISPLAY_ON);
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_BACKLIGHT_ON);
+		break;
+	case 1:		/* normal blanking */
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_DISPLAY_OFF);
+		i2c_smbus_write_byte(lcd2s.i2c, LCD2S_CMD_BACKLIGHT_OFF);
+		break;
+	}
+	return 0;
+}
+
+static int lcd2s_set_palette(struct vc_data *con, unsigned char *table)
+{
+	return -EINVAL;
+}
+
+static int lcd2s_scrolldelta(struct vc_data *con, int lines)
+{
+	return 0;
+}
+
+static struct consw lcd2s_con = {
+	.owner			= THIS_MODULE,
+	.con_startup		= lcd2s_startup,
+	.con_init		= lcd2s_init,
+	.con_deinit		= lcd2s_deinit,
+	.con_clear		= lcd2s_clear,
+	.con_putc		= lcd2s_putc,
+	.con_putcs		= lcd2s_putcs,
+	.con_cursor		= lcd2s_cursor,
+	.con_scroll		= lcd2s_scroll,
+	.con_bmove		= lcd2s_bmove,
+	.con_switch		= lcd2s_switch,
+	.con_blank		= lcd2s_blank,
+	.con_set_palette	= lcd2s_set_palette,
+	.con_scrolldelta	= lcd2s_scrolldelta,
+};
+
+static int __devinit lcd2s_i2c_probe(struct i2c_client *i2c,
+				const struct i2c_device_id *id)
+{
+	if (!i2c_check_functionality(i2c->adapter,
+			I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+			I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
+		return -EIO;
+
+	lcd2s.i2c = i2c;
+
+	take_over_console(&lcd2s_con, LCD2S_FIRST, LCD2S_LAST, 1);
+
+	return 0;
+}
+
+static __devexit int lcd2s_i2c_remove(struct i2c_client *i2c)
+{
+	/* unregister from console subsystem */
+	unregister_con_driver(&lcd2s_con);
+	return 0;
+}
+
+static const struct i2c_device_id lcd2s_i2c_id[] = {
+	{ "lcd2s", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lcd2s_i2c_id);
+
+static struct i2c_driver lcd2s_i2c_driver = {
+	.driver = {
+		.name = "lcd2s",
+		.owner = THIS_MODULE,
+	},
+	.probe = lcd2s_i2c_probe,
+	.remove = __devexit_p(lcd2s_i2c_remove),
+	.id_table = lcd2s_i2c_id,
+};
+
+module_i2c_driver(lcd2s_i2c_driver)
+
+MODULE_DESCRIPTION("LCD2S character display console driver");
+MODULE_AUTHOR("Lars Poeschel");
+MODULE_LICENSE("GPL");
-- 
1.7.10.4


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox