mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* Video support for EfikaSB
@ 2015-07-09  7:24 Sascha Hauer
  2015-07-09  7:24 ` [PATCH 01/13] of: base: implement of_get_next_child Sascha Hauer
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

This series adds video support to the EfikaSB. Several infrastructure
additions are necessary for this. First the of_graph binding is introduced
to barebox which is necessary to describe the topology of the video
hardware in the device tree. With this we can describe the various
video encoders intern and extern to the SoC. Next we introduce the video
pipeline concept (VPL). This makes it possible to chain together the
different video encoders. It's possible to throw an ioctl into one
end of the chain and each encoder is responsible to handle the ioctl
and to pass it on to the next entitity in the chain. Support for the
MTL017 LVDS encoder found in the EfikaSB and support for simple panels
make this series complete.

Sascha

----------------------------------------------------------------
Sascha Hauer (13):
      of: base: implement of_get_next_child
      of: import of_graph functions
      of_graph: add of_graph_port_is_available
      ARM: i.MX51 Efikasb: Disable backlight earlier
      ARM: i.MX51 Efikasb: make more space for barebox
      ARM: i.MX51 Efikasb: update device tree
      video: Add Video Pipeline (VPL) support
      video: Add MTL017 LVDS encoder support
      video: Add missing prototype for display_timings_release
      video: ipuv3: remove unused variable
      video: ipuv3: Replace ipu_output with VPL
      video: ipuv3: match ipu_di_signal_cfg's clk_pol with its description
      video: Add simple-panel support

 arch/arm/boards/efika-mx-smartbook/board.c |   3 +-
 arch/arm/dts/imx51-genesi-efika-sb.dts     | 130 +++++++++-----
 drivers/of/base.c                          | 206 +++++++++++++++++++++
 drivers/video/Kconfig                      |  21 +++
 drivers/video/Makefile                     |   3 +
 drivers/video/imx-ipu-v3/Kconfig           |   1 +
 drivers/video/imx-ipu-v3/imx-hdmi.c        |  93 +++++-----
 drivers/video/imx-ipu-v3/imx-ipu-v3.h      |  25 +--
 drivers/video/imx-ipu-v3/imx-ldb.c         | 116 +++++++++---
 drivers/video/imx-ipu-v3/ipu-di.c          |   2 +-
 drivers/video/imx-ipu-v3/ipufb.c           | 144 ++++++---------
 drivers/video/mtl017.c                     | 280 +++++++++++++++++++++++++++++
 drivers/video/simple-panel.c               | 160 +++++++++++++++++
 drivers/video/vpl.c                        | 115 ++++++++++++
 include/fb.h                               |   2 +
 include/of.h                               |   8 +
 include/of_graph.h                         |  50 ++++++
 include/video/vpl.h                        |  46 +++++
 18 files changed, 1179 insertions(+), 226 deletions(-)
 create mode 100644 drivers/video/mtl017.c
 create mode 100644 drivers/video/simple-panel.c
 create mode 100644 drivers/video/vpl.c
 create mode 100644 include/of_graph.h
 create mode 100644 include/video/vpl.h

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/13] of: base: implement of_get_next_child
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 02/13] of: import of_graph functions Sascha Hauer
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/of/base.c | 17 +++++++++++++++++
 include/of.h      |  8 ++++++++
 2 files changed, 25 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3e40a48..0eb1d6b 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1570,6 +1570,23 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
 EXPORT_SYMBOL(of_get_next_available_child);
 
 /**
+ *	of_get_next_child - Iterate a node childs
+ *	@node:  parent node
+ *	@prev:  previous child of the parent node, or NULL to get first
+ *
+ *	Returns a node pointer with refcount incremented.
+ */
+struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev)
+{
+	prev = list_prepare_entry(prev, &node->children, parent_list);
+	list_for_each_entry_continue(prev, &node->children, parent_list)
+		return prev;
+	return NULL;
+}
+EXPORT_SYMBOL(of_get_next_available_child);
+
+/**
  *	of_get_child_count - Count child nodes of given parent node
  *	@parent:	parent node
  *
diff --git a/include/of.h b/include/of.h
index 1db210b..e0ebc39 100644
--- a/include/of.h
+++ b/include/of.h
@@ -153,6 +153,8 @@ extern int of_device_is_available(const struct device_node *device);
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_available_child(
 	const struct device_node *node, struct device_node *prev);
+struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev);
 extern int of_get_child_count(const struct device_node *parent);
 extern int of_get_available_child_count(const struct device_node *parent);
 extern struct device_node *of_get_child_by_name(const struct device_node *node,
@@ -308,6 +310,12 @@ static inline struct device_node *of_get_next_available_child(
 	return NULL;
 }
 
+static inline struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev)
+{
+	return NULL;
+}
+
 static inline int of_get_child_count(const struct device_node *parent)
 {
 	return -ENOSYS;
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 02/13] of: import of_graph functions
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
  2015-07-09  7:24 ` [PATCH 01/13] of: base: implement of_get_next_child Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 03/13] of_graph: add of_graph_port_is_available Sascha Hauer
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/of/base.c  | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/of_graph.h |  49 ++++++++++++++++
 2 files changed, 216 insertions(+)
 create mode 100644 include/of_graph.h

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 0eb1d6b..b2c4b23 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -25,6 +25,7 @@
 #include <init.h>
 #include <memory.h>
 #include <linux/sizes.h>
+#include <of_graph.h>
 #include <linux/ctype.h>
 #include <linux/amba/bus.h>
 #include <linux/err.h>
@@ -2043,3 +2044,169 @@ int of_device_disable_path(const char *path)
 
 	return of_device_disable(node);
 }
+
+/**
+ * of_graph_parse_endpoint() - parse common endpoint node properties
+ * @node: pointer to endpoint device_node
+ * @endpoint: pointer to the OF endpoint data structure
+ *
+ * The caller should hold a reference to @node.
+ */
+int of_graph_parse_endpoint(const struct device_node *node,
+			    struct of_endpoint *endpoint)
+{
+	struct device_node *port_node = of_get_parent(node);
+
+	if (!port_node)
+		pr_warn("%s(): endpoint %s has no parent node\n",
+			__func__, node->full_name);
+
+	memset(endpoint, 0, sizeof(*endpoint));
+
+	endpoint->local_node = node;
+	/*
+	 * It doesn't matter whether the two calls below succeed.
+	 * If they don't then the default value 0 is used.
+	 */
+	of_property_read_u32(port_node, "reg", &endpoint->port);
+	of_property_read_u32(node, "reg", &endpoint->id);
+
+	return 0;
+}
+EXPORT_SYMBOL(of_graph_parse_endpoint);
+
+/**
+ * of_graph_get_port_by_id() - get the port matching a given id
+ * @parent: pointer to the parent device node
+ * @id: id of the port
+ *
+ * Return: A 'port' node pointer with refcount incremented.
+ */
+struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id)
+{
+	struct device_node *port;
+
+	for_each_child_of_node(node, port) {
+		u32 port_id = 0;
+
+		if (strncmp(port->name, "port", 4) != 0)
+			continue;
+		of_property_read_u32(port, "reg", &port_id);
+		if (id == port_id)
+			return port;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(of_graph_get_port_by_id);
+
+/**
+ * of_graph_get_next_endpoint() - get next endpoint node
+ * @parent: pointer to the parent device node
+ * @prev: previous endpoint node, or NULL to get first
+ *
+ * Return: An 'endpoint' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is decremented.
+ */
+struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
+					struct device_node *prev)
+{
+	struct device_node *endpoint;
+	struct device_node *port;
+
+	if (!parent)
+		return NULL;
+
+	/*
+	 * Start by locating the port node. If no previous endpoint is specified
+	 * search for the first port node, otherwise get the previous endpoint
+	 * parent port node.
+	 */
+	if (!prev) {
+		struct device_node *node;
+
+		node = of_get_child_by_name(parent, "ports");
+		if (node)
+			parent = node;
+
+		port = of_get_child_by_name(parent, "port");
+		if (!port) {
+			pr_err("%s(): no port node found in %s\n",
+			       __func__, parent->full_name);
+			return NULL;
+		}
+	} else {
+		port = of_get_parent(prev);
+		if (!port) {
+			pr_warn("%s(): endpoint %s has no parent node\n",
+			      __func__, prev->full_name);
+			return NULL;
+		}
+	}
+
+	while (1) {
+		/*
+		 * Now that we have a port node, get the next endpoint by
+		 * getting the next child. If the previous endpoint is NULL this
+		 * will return the first child.
+		 */
+		endpoint = of_get_next_child(port, prev);
+		if (endpoint)
+			return endpoint;
+
+		/* No more endpoints under this port, try the next one. */
+		prev = NULL;
+
+		do {
+			port = of_get_next_child(parent, port);
+			if (!port)
+				return NULL;
+		} while (of_node_cmp(port->name, "port"));
+	}
+}
+EXPORT_SYMBOL(of_graph_get_next_endpoint);
+
+/**
+ * of_graph_get_remote_port_parent() - get remote port's parent node
+ * @node: pointer to a local endpoint device_node
+ *
+ * Return: Remote device node associated with remote endpoint node linked
+ *	   to @node.
+ */
+struct device_node *of_graph_get_remote_port_parent(
+			       const struct device_node *node)
+{
+	struct device_node *np;
+	unsigned int depth;
+
+	/* Get remote endpoint node. */
+	np = of_parse_phandle(node, "remote-endpoint", 0);
+
+	/* Walk 3 levels up only if there is 'ports' node. */
+	for (depth = 3; depth && np; depth--) {
+		np = np->parent;
+		if (depth == 2 && of_node_cmp(np->name, "ports"))
+			break;
+	}
+	return np;
+}
+EXPORT_SYMBOL(of_graph_get_remote_port_parent);
+
+/**
+ * of_graph_get_remote_port() - get remote port node
+ * @node: pointer to a local endpoint device_node
+ *
+ * Return: Remote port node associated with remote endpoint node linked
+ *	   to @node.
+ */
+struct device_node *of_graph_get_remote_port(const struct device_node *node)
+{
+	struct device_node *np;
+
+	/* Get remote endpoint node. */
+	np = of_parse_phandle(node, "remote-endpoint", 0);
+	if (!np)
+		return NULL;
+	return np->parent;
+}
+EXPORT_SYMBOL(of_graph_get_remote_port);
diff --git a/include/of_graph.h b/include/of_graph.h
new file mode 100644
index 0000000..fa037db
--- /dev/null
+++ b/include/of_graph.h
@@ -0,0 +1,49 @@
+/*
+ * OF graph binding parsing helpers
+ *
+ * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * Copyright (C) 2012 Renesas Electronics Corp.
+ * Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LINUX_OF_GRAPH_H
+#define __LINUX_OF_GRAPH_H
+
+/**
+ * struct of_endpoint - the OF graph endpoint data structure
+ * @port: identifier (value of reg property) of a port this endpoint belongs to
+ * @id: identifier (value of reg property) of this endpoint
+ * @local_node: pointer to device_node of this endpoint
+ */
+struct of_endpoint {
+	unsigned int port;
+	unsigned int id;
+	const struct device_node *local_node;
+};
+
+/**
+ * for_each_endpoint_of_node - iterate over every endpoint in a device node
+ * @parent: parent device node containing ports and endpoints
+ * @child: loop variable pointing to the current endpoint node
+ *
+ * When breaking out of the loop, of_node_put(child) has to be called manually.
+ */
+#define for_each_endpoint_of_node(parent, child) \
+	for (child = of_graph_get_next_endpoint(parent, NULL); child != NULL; \
+	     child = of_graph_get_next_endpoint(parent, child))
+
+int of_graph_parse_endpoint(const struct device_node *node,
+				struct of_endpoint *endpoint);
+struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
+struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
+					struct device_node *previous);
+struct device_node *of_graph_get_remote_port_parent(
+					const struct device_node *node);
+struct device_node *of_graph_get_remote_port(const struct device_node *node);
+
+#endif /* __LINUX_OF_GRAPH_H */
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 03/13] of_graph: add of_graph_port_is_available
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
  2015-07-09  7:24 ` [PATCH 01/13] of: base: implement of_get_next_child Sascha Hauer
  2015-07-09  7:24 ` [PATCH 02/13] of: import of_graph functions Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 04/13] ARM: i.MX51 Efikasb: Disable backlight earlier Sascha Hauer
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/of/base.c  | 22 ++++++++++++++++++++++
 include/of_graph.h |  1 +
 2 files changed, 23 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index b2c4b23..334b8a2 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2210,3 +2210,25 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
 	return np->parent;
 }
 EXPORT_SYMBOL(of_graph_get_remote_port);
+
+int of_graph_port_is_available(struct device_node *node)
+{
+	struct device_node *endpoint;
+	int available = 0;
+
+	for_each_child_of_node(node, endpoint) {
+		struct device_node *remote_parent;
+
+		remote_parent = of_graph_get_remote_port_parent(endpoint);
+		if (!remote_parent)
+			continue;
+
+		if (!of_device_is_available(remote_parent))
+			continue;
+
+		available = 1;
+	}
+
+	return available;
+}
+EXPORT_SYMBOL(of_graph_port_is_available);
diff --git a/include/of_graph.h b/include/of_graph.h
index fa037db..254dd2c 100644
--- a/include/of_graph.h
+++ b/include/of_graph.h
@@ -45,5 +45,6 @@ struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
 struct device_node *of_graph_get_remote_port_parent(
 					const struct device_node *node);
 struct device_node *of_graph_get_remote_port(const struct device_node *node);
+int of_graph_port_is_available(struct device_node *node);
 
 #endif /* __LINUX_OF_GRAPH_H */
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 04/13] ARM: i.MX51 Efikasb: Disable backlight earlier
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (2 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 03/13] of_graph: add of_graph_port_is_available Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 05/13] ARM: i.MX51 Efikasb: make more space for barebox Sascha Hauer
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Set the backlight enable gpio to disabled earlier during startup
to avoid flicker when the pinmux is configured but not yet the
enable gpio.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/boards/efika-mx-smartbook/board.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm/boards/efika-mx-smartbook/board.c b/arch/arm/boards/efika-mx-smartbook/board.c
index 4a38afd..f023d70 100644
--- a/arch/arm/boards/efika-mx-smartbook/board.c
+++ b/arch/arm/boards/efika-mx-smartbook/board.c
@@ -187,6 +187,7 @@ static int efikamx_usb_init(void)
 	gpio_direction_output(GPIO_WIFI_RESET, 0);
 	gpio_direction_output(GPIO_SMSC3317_RESET, 0);
 	gpio_direction_output(GPIO_HUB_RESET, 0);
+	gpio_direction_output(GPIO_BACKLIGHT_POWER, 1);
 
 	mdelay(10);
 
@@ -241,8 +242,6 @@ static int efikamx_late_init(void)
 
 	defaultenv_append_directory(defaultenv_efikasb);
 
-	gpio_direction_output(GPIO_BACKLIGHT_POWER, 1);
-
 	for (i = 0; i < ARRAY_SIZE(leds); i++)
 		led_gpio_register(&leds[i]);
 
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 05/13] ARM: i.MX51 Efikasb: make more space for barebox
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (3 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 04/13] ARM: i.MX51 Efikasb: Disable backlight earlier Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 06/13] ARM: i.MX51 Efikasb: update device tree Sascha Hauer
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/imx51-genesi-efika-sb.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/dts/imx51-genesi-efika-sb.dts b/arch/arm/dts/imx51-genesi-efika-sb.dts
index 26829d1..9772259 100644
--- a/arch/arm/dts/imx51-genesi-efika-sb.dts
+++ b/arch/arm/dts/imx51-genesi-efika-sb.dts
@@ -371,7 +371,7 @@
 
 	partition@0 {
 		label = "barebox-environment";
-		reg = <0x80000 0x80000>;
+		reg = <0xc0000 0x40000>;
 	};
 };
 
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 06/13] ARM: i.MX51 Efikasb: update device tree
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (4 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 05/13] ARM: i.MX51 Efikasb: make more space for barebox Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 07/13] video: Add Video Pipeline (VPL) support Sascha Hauer
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Use the correct display pins (which are DISP2* and not DISP1*) and
use the of_graph bindings to describe the video hardware.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/dts/imx51-genesi-efika-sb.dts | 128 ++++++++++++++++++++++-----------
 1 file changed, 87 insertions(+), 41 deletions(-)

diff --git a/arch/arm/dts/imx51-genesi-efika-sb.dts b/arch/arm/dts/imx51-genesi-efika-sb.dts
index 9772259..78cb1b7 100644
--- a/arch/arm/dts/imx51-genesi-efika-sb.dts
+++ b/arch/arm/dts/imx51-genesi-efika-sb.dts
@@ -90,12 +90,34 @@
 		mux-ext-port = <3>;
 	};
 
-	backlight {
+	backlight: backlight {
 		compatible = "pwm-backlight";
+		enable-gpios = <&gpio4 12 GPIO_ACTIVE_LOW>;
 		pwms = <&pwm1 0 78770>;
-		brightness-levels = <0 4 8 16 32 64 128 255>;
-		default-brightness-level = <6>;
-        };
+		brightness-levels = <0 1 2 4 8 16 32 64 128 255>;
+		default-brightness-level = <9>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight>;
+	};
+
+	panel {
+		compatible = "simple-panel";
+		backlight = <&backlight>;
+		enable-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+		ddc-i2c-bus = <&i2c2>;
+		enable-delay = <200>;
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&mtl017_out>;
+			};
+		};
+	};
+
+	lvds_reg: lvds_regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+	};
 };
 
 &ssi1 {
@@ -115,16 +137,17 @@
 				MX51_PAD_DI1_PIN12__GPIO3_1 0x80000000		/* WLAN switch */
 				MX51_PAD_EIM_A17__GPIO2_11  0x80000000		/* Bluetooth power */
 				MX51_PAD_EIM_A23__GPIO2_17 0x80000000		/* Audio amp enable, 1 = on */
-				MX51_PAD_CSI1_D8__GPIO3_12 0x80000000		/* LVDS enable, 1 = on */
-				MX51_PAD_GPIO1_2__GPIO1_2 0x80000000		/* Backlight PWM */
-				MX51_PAD_CSI2_D19__GPIO4_12 0x80000000		/* Backlight power, 0 = on */
-				MX51_PAD_DISPB2_SER_DIN__GPIO3_5 0x80000000	/* LVDS reset (1 = reset) */
-				MX51_PAD_DISPB2_SER_CLK__GPIO3_7 0x80000000	/* LVDS power, 1 = on */
-				MX51_PAD_CSI1_D9__GPIO3_13 0x80000000		/* LCD enable (1 = on */
 				MX51_PAD_NANDF_CS0__GPIO3_16 0x80000000		/* Camera power, 0 = on */
 				MX51_PAD_GPIO1_5__GPIO1_5 0x80000000		/* USB hub reset, 0 = reset */
 				MX51_PAD_EIM_D27__GPIO2_9  0x80000000		/* USB phy reset, 0 = reset */
 				MX51_PAD_CSPI1_RDY__GPIO4_26 0x80000000		/* Audio clk enable */
+				MX51_PAD_CSI2_D19__GPIO4_12 0x80000000		/* Backlight power, 0 = on */
+			>;
+		};
+
+		pinctrl_backlight: backlightgrp {
+			fsl,pins = <
+				MX51_PAD_GPIO1_2__PWM1_PWMO 0x80000000		/* Backlight PWM */
 			>;
 		};
 
@@ -187,34 +210,32 @@
 			>;
 		};
 
-		pinctrl_ipu_disp1: ipudisp1grp {
+		pinctrl_ipu_disp2: ipudisp2grp {
 			fsl,pins = <
-				MX51_PAD_DISP1_DAT0__DISP1_DAT0	0x5
-				MX51_PAD_DISP1_DAT1__DISP1_DAT1	0x5
-				MX51_PAD_DISP1_DAT2__DISP1_DAT2	0x5
-				MX51_PAD_DISP1_DAT3__DISP1_DAT3	0x5
-				MX51_PAD_DISP1_DAT4__DISP1_DAT4	0x5
-				MX51_PAD_DISP1_DAT5__DISP1_DAT5	0x5
-				MX51_PAD_DISP1_DAT6__DISP1_DAT6	0x5
-				MX51_PAD_DISP1_DAT7__DISP1_DAT7	0x5
-				MX51_PAD_DISP1_DAT8__DISP1_DAT8	0x5
-				MX51_PAD_DISP1_DAT9__DISP1_DAT9	0x5
-				MX51_PAD_DISP1_DAT10__DISP1_DAT10 0x5
-				MX51_PAD_DISP1_DAT11__DISP1_DAT11 0x5
-				MX51_PAD_DISP1_DAT12__DISP1_DAT12 0x5
-				MX51_PAD_DISP1_DAT13__DISP1_DAT13 0x5
-				MX51_PAD_DISP1_DAT14__DISP1_DAT14 0x5
-				MX51_PAD_DISP1_DAT15__DISP1_DAT15 0x5
-				MX51_PAD_DISP1_DAT16__DISP1_DAT16 0x5
-				MX51_PAD_DISP1_DAT17__DISP1_DAT17 0x5
-				MX51_PAD_DISP1_DAT18__DISP1_DAT18 0x5
-				MX51_PAD_DISP1_DAT19__DISP1_DAT19 0x5
-				MX51_PAD_DISP1_DAT20__DISP1_DAT20 0x5
-				MX51_PAD_DISP1_DAT21__DISP1_DAT21 0x5
-				MX51_PAD_DISP1_DAT22__DISP1_DAT22 0x5
-				MX51_PAD_DISP1_DAT23__DISP1_DAT23 0x5
-				MX51_PAD_DI1_PIN2__DI1_PIN2 0x5
-				MX51_PAD_DI1_PIN3__DI1_PIN3 0x5
+				MX51_PAD_DISP2_DAT0__DISP2_DAT0     0x5
+				MX51_PAD_DISP2_DAT1__DISP2_DAT1     0x5
+				MX51_PAD_DISP2_DAT2__DISP2_DAT2     0x5
+				MX51_PAD_DISP2_DAT3__DISP2_DAT3     0x5
+				MX51_PAD_DISP2_DAT4__DISP2_DAT4     0x5
+				MX51_PAD_DISP2_DAT5__DISP2_DAT5     0x5
+				MX51_PAD_DISP2_DAT6__DISP2_DAT6     0x5
+				MX51_PAD_DISP2_DAT7__DISP2_DAT7     0x5
+				MX51_PAD_DISP2_DAT8__DISP2_DAT8     0x5
+				MX51_PAD_DISP2_DAT9__DISP2_DAT9     0x5
+				MX51_PAD_DISP2_DAT10__DISP2_DAT10   0x5
+				MX51_PAD_DISP2_DAT11__DISP2_DAT11   0x5
+				MX51_PAD_DISP2_DAT12__DISP2_DAT12   0x5
+				MX51_PAD_DISP2_DAT13__DISP2_DAT13   0x5
+				MX51_PAD_DISP2_DAT14__DISP2_DAT14   0x5
+				MX51_PAD_DISP2_DAT15__DISP2_DAT15   0x5
+				MX51_PAD_DI2_PIN2__DI2_PIN2         0x5 /* hsync */
+				MX51_PAD_DI2_PIN3__DI2_PIN3         0x5 /* vsync */
+				MX51_PAD_DI2_DISP_CLK__DI2_DISP_CLK 0x5
+				MX51_PAD_DI_GP4__DI2_PIN15          0x5
+				MX51_PAD_CSI1_D8__GPIO3_12 0x80000000		/* LVDS enable, 1 = on */
+				MX51_PAD_DISPB2_SER_DIN__GPIO3_5 0x80000000	/* LVDS reset (1 = reset) */
+				MX51_PAD_DISPB2_SER_CLK__GPIO3_7 0x80000000	/* LVDS power, 1 = on */
+				MX51_PAD_CSI1_D9__GPIO3_13 0x80000000		/* LCD enable (1 = on */
 			>;
 		};
 
@@ -342,13 +363,38 @@
 	};
 
 	lvds: mtl017@3a {
+		#address-cells = <1>;
+		#size-cells = <0>;
 		compatible = "mtl017";
 		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_ipu_disp1>;
+		pinctrl-0 = <&pinctrl_ipu_disp2>;
+		enable-gpios =  <&gpio3 12 GPIO_ACTIVE_HIGH>;
+		reset-gpios =  <&gpio3 5 GPIO_ACTIVE_HIGH>;
+		vdd-supply = <&lvds_reg>;
 		reg = <0x3a>;
-		crtcs = <&ipu 1>;
-		edid-i2c = <&i2c2>;
-		interface-pix-fmt = "rgb565";
+
+		port@0 {
+			reg = <0>;
+
+			mtl017_in: endpoint {
+				remote-endpoint = <&ipu_di1_disp1>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			mtl017_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
+
+&ipu_di1 {
+	interface-pix-fmt = "rgb565";
+	endpoint {
+		remote-endpoint = <&mtl017_in>;
 	};
 };
 
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 07/13] video: Add Video Pipeline (VPL) support
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (5 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 06/13] ARM: i.MX51 Efikasb: update device tree Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 08/13] video: Add MTL017 LVDS encoder support Sascha Hauer
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Complex video pipelines are modelled with the of_graph bindings in
the devicetree. This patch adds a ioctl infrastructure to issue
commands to the remote endpoint of a of_graph. Currently defined
ioctls are prepare/unprepare, enable/disable and get_modes. This
is enough to control LVDS or HDMI encoder or simple panels.

A device node which contains of_graph endpoints can be registered
as a VPL entity. An entity can receive ioctls via the .ioctl callback
and also issue ioctls by calling vpl_ioctl. The core itself will never
iterate over the entire pipeline. Instead, the different VPL entities
should forward an ioctl to the next instance in the pipeline whenever
necessary.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/Kconfig  |   3 ++
 drivers/video/Makefile |   1 +
 drivers/video/vpl.c    | 115 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fb.h           |   1 +
 include/video/vpl.h    |  46 ++++++++++++++++++++
 5 files changed, 166 insertions(+)
 create mode 100644 drivers/video/vpl.c
 create mode 100644 include/video/vpl.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 8e6ae99..6d540a5 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -5,6 +5,9 @@ menuconfig VIDEO
 
 if VIDEO
 
+config VIDEO_VPL
+	bool
+
 config DRIVER_VIDEO_ATMEL
 	bool "Atmel LCDC framebuffer driver"
 	depends on ARCH_AT91
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 76fad5c..3aa544a 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_DRIVER_VIDEO_EDID) += edid.o
 obj-$(CONFIG_OFDEVICE) += of_display_timing.o
 obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT) += backlight.o
 obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT_PWM) += backlight-pwm.o
+obj-$(CONFIG_VIDEO_VPL) += vpl.o
 
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
diff --git a/drivers/video/vpl.c b/drivers/video/vpl.c
new file mode 100644
index 0000000..99ad180
--- /dev/null
+++ b/drivers/video/vpl.c
@@ -0,0 +1,115 @@
+/*
+ * Video pipeline (VPL) support for barebox
+ *
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt) "VPL: " fmt
+
+#include <common.h>
+#include <driver.h>
+#include <of_graph.h>
+#include <linux/list.h>
+#include <video/vpl.h>
+
+static LIST_HEAD(vpls);
+
+int vpl_register(struct vpl *vpl)
+{
+	list_add_tail(&vpl->list, &vpls);
+
+	pr_debug("%s: %s\n", __func__, vpl->node->full_name);
+
+	return 0;
+}
+
+struct vpl *of_find_vpl(struct device_node *node)
+{
+	struct vpl *vpl;
+
+	list_for_each_entry(vpl, &vpls, list)
+		if (vpl->node == node)
+			return vpl;
+
+	return NULL;
+}
+
+struct vpl *of_vpl_get(struct device_node *node, int port)
+{
+	node = of_graph_get_port_by_id(node, port);
+	if (!node)
+		return NULL;
+
+	pr_debug("%s: port: %s\n", __func__, node->full_name);
+
+	node = of_graph_get_remote_port_parent(node);
+	if (!node)
+		return NULL;
+
+	pr_debug("%s: remote port parent: %s\n", __func__, node->full_name);
+
+	return of_find_vpl(node);
+}
+
+int vpl_ioctl(struct vpl *vpl, unsigned int port,
+		unsigned int cmd, void *ptr)
+{
+	struct device_node *node, *endpoint;
+	int ret;
+
+	pr_debug("%s: %s port %d\n", __func__, vpl->node->full_name, port);
+
+	node = of_graph_get_port_by_id(vpl->node, port);
+	if (!node) {
+		pr_err("%s: no port %d on %s\n", __func__, port, vpl->node->full_name);
+		return -ENODEV;
+	}
+
+	for_each_child_of_node(node, endpoint) {
+		struct device_node *remote, *remote_parent;
+		struct vpl *remote_vpl;
+		u32 remote_port_id;
+
+		remote = of_graph_get_remote_port(endpoint);
+		if (!remote) {
+			pr_debug("%s: no remote for endpoint %s\n", __func__, endpoint->full_name);
+			continue;
+		}
+
+		of_property_read_u32(remote, "reg", &remote_port_id);
+
+		remote_parent = of_graph_get_remote_port_parent(endpoint);
+		if (!remote_parent) {
+			pr_debug("%s: no remote_parent\n", __func__);
+			return -ENODEV;
+		}
+
+		if (!of_device_is_available(remote_parent))
+			continue;
+
+		remote_vpl = of_find_vpl(remote_parent);
+		if (!remote_vpl) {
+			pr_debug("%s: cannot find remote vpl %s\n", __func__, remote->full_name);
+			continue;
+		}
+
+		ret = remote_vpl->ioctl(remote_vpl, remote_port_id, cmd, ptr);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/include/fb.h b/include/fb.h
index 2db6ad6..9e59b2a 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -99,6 +99,7 @@ struct display_timings {
 
 	unsigned int num_modes;
 	struct fb_videomode *modes;
+	void *edid;
 };
 
 struct i2c_adapter;
diff --git a/include/video/vpl.h b/include/video/vpl.h
new file mode 100644
index 0000000..846007f
--- /dev/null
+++ b/include/video/vpl.h
@@ -0,0 +1,46 @@
+#ifndef __VIDEO_VPL_H
+#define __VIDEO_VPL_H
+
+#include <fb.h>
+
+#define VPL_PREPARE		0x67660001
+#define VPL_UNPREPARE		0x67660002
+#define VPL_ENABLE		0x67660003
+#define VPL_DISABLE		0x67660004
+#define VPL_GET_VIDEOMODES	0x67660005
+
+struct vpl {
+	int (*ioctl)(struct vpl *, unsigned int port,
+			unsigned int cmd, void *ptr);
+	struct device_node *node;
+	struct list_head list;
+};
+
+int vpl_register(struct vpl *);
+int vpl_ioctl(struct vpl *, unsigned int port,
+		unsigned int cmd, void *ptr);
+
+struct vpl *of_vpl_get(struct device_node *node, int port);
+
+static inline int vpl_ioctl_prepare(struct vpl *vpl, unsigned int port,
+		struct fb_videomode *mode)
+{
+	return vpl_ioctl(vpl, port, VPL_PREPARE, mode);
+}
+
+static inline int vpl_ioctl_unprepare(struct vpl *vpl, unsigned int port)
+{
+	return vpl_ioctl(vpl, port, VPL_UNPREPARE, NULL);
+}
+
+static inline int vpl_ioctl_enable(struct vpl *vpl, unsigned int port)
+{
+	return vpl_ioctl(vpl, port, VPL_ENABLE, NULL);
+}
+
+static inline int vpl_ioctl_disable(struct vpl *vpl, unsigned int port)
+{
+	return vpl_ioctl(vpl, port, VPL_DISABLE, NULL);
+}
+
+#endif /* __VIDEO_VPL_H */
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 08/13] video: Add MTL017 LVDS encoder support
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (6 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 07/13] video: Add Video Pipeline (VPL) support Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 09/13] video: Add missing prototype for display_timings_release Sascha Hauer
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

The MTL017 is found on the Efika Smartbook. Not much is known about
this chip, so this driver only programs a register dump which is suitable
for some panels.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/Kconfig  |   9 ++
 drivers/video/Makefile |   1 +
 drivers/video/mtl017.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 290 insertions(+)
 create mode 100644 drivers/video/mtl017.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6d540a5..6637877 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -108,4 +108,13 @@ config DRIVER_VIDEO_BACKLIGHT_PWM
 	help
 	  Enable this to get support for backlight devices driven by a PWM.
 
+comment "Video encoder chips"
+
+config DRIVER_VIDEO_MTL017
+	bool "MTL017 LVDS encoder"
+	select VIDEO_VPL
+	help
+	  The MTL017 is a parallel to lvds video encoder chip found on the
+	  Efika MX Smartbook.
+
 endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 3aa544a..1e2109e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_OFDEVICE) += of_display_timing.o
 obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT) += backlight.o
 obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT_PWM) += backlight-pwm.o
 obj-$(CONFIG_VIDEO_VPL) += vpl.o
+obj-$(CONFIG_DRIVER_VIDEO_MTL017) += mtl017.o
 
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
diff --git a/drivers/video/mtl017.c b/drivers/video/mtl017.c
new file mode 100644
index 0000000..1a1f686
--- /dev/null
+++ b/drivers/video/mtl017.c
@@ -0,0 +1,280 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <regulator.h>
+#include <of_gpio.h>
+#include <gpio.h>
+#include <fb.h>
+#include <video/vpl.h>
+
+#include <i2c/i2c.h>
+
+struct mtl017 {
+	struct vpl vpl;
+	struct device_d *dev;
+	struct i2c_client *client;
+	u8 *regs;
+	int enable_gpio;
+	int enable_active_high;
+	int reset_gpio;
+	int reset_active_high;
+	struct regulator *regulator;
+};
+
+/*
+ * Unfortunately we know nothing about the mtl017 except the following
+ * register tables which are derived from the Efika kernel. The displays
+ * provide EDID data, but this does not work with the mtl017 or at least
+ * not with the below register settings, so we have to provide hardcoded
+ * modelines and use the EDID data only to match against the vendor/display.
+ */
+static u8 mtl017_44_54_tbl[] = {
+	/* 44M to 53.9M */
+	0x00, 0x20, 0xAF, 0x59, 0x2B, 0xDE, 0x51, 0x00,
+	0x00, 0x04, 0x17, 0x00, 0x58, 0x02, 0x00, 0x00,
+	0x00, 0x3B, 0x01, 0x08, 0x00, 0x1E, 0x01, 0x05,
+	0x00, 0x01, 0x72, 0x05, 0x32, 0x00, 0x00, 0x04,
+	0x00, 0x00, 0x20, 0xA8, 0x02, 0x12, 0x00, 0x58,
+	0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x02, 0x10, 0x01, 0x68, 0x03, 0xC2, 0x01,
+	0x4A, 0x03, 0x46, 0x00, 0xF1, 0x01, 0x5C, 0x04,
+	0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3A,
+	0x18, 0x4B, 0x29, 0x5C, 0xDE, 0xF6, 0xE0, 0x1C,
+	0x03, 0xFC, 0xE3, 0x1F, 0xF3, 0x75, 0x26, 0x45,
+	0x4A, 0x91, 0x8A, 0xFF, 0x3F, 0x83, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x4E, 0x48,
+	0x00, 0x01, 0x10, 0x01, 0x00, 0x00, 0x10, 0x04,
+	0x02, 0x1F, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00,
+	0x32, 0x00, 0x00, 0x04, 0x12, 0x00, 0x58, 0x02,
+	0x02, 0x7C, 0x04, 0x98, 0x02, 0x11, 0x78, 0x18,
+	0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+#define REGMAP_LENGTH (sizeof(mtl017_44_54_tbl) / sizeof(u8))
+#define BLOCK_TX_SIZE 32
+
+struct mtl017_panel_info {
+	char *manufacturer;
+	char *product_name;
+	struct fb_videomode *mode;
+	u8  *regs;
+};
+
+
+static struct fb_videomode auo_bw101aw02_mode = {
+	.name = "AUO B101AW02 1024x600",
+	.refresh = 60,
+	.xres = 1024,
+	.yres = 600,
+	.pixclock = 22800,
+	.left_margin = 80,
+	.right_margin = 40,
+	.upper_margin = 21,
+	.lower_margin = 21,
+	.hsync_len = 4,
+	.vsync_len = 4,
+	.vmode = FB_VMODE_NONINTERLACED,
+};
+
+static struct mtl017_panel_info panels[] = {
+	{
+		.manufacturer = "AUO",
+		.product_name = "B101AW02 V0",
+		.mode = &auo_bw101aw02_mode,
+		.regs = mtl017_44_54_tbl,
+	},
+	{
+		.manufacturer = "CMO",
+		.product_name = "N101L6-L0D",
+		.mode = &auo_bw101aw02_mode,
+		.regs = mtl017_44_54_tbl,
+	},
+};
+
+static int mtl017_get_videomodes(struct mtl017 *mtl017, struct display_timings *timings)
+{
+	int ret, i;
+
+	ret = vpl_ioctl(&mtl017->vpl, 1, VPL_GET_VIDEOMODES, timings);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(panels); i ++) {
+		if (memcmp(timings->edid + 0x71, panels[i].product_name,
+					strlen(panels[i].product_name)))
+			continue;
+
+		dev_dbg(mtl017->dev, "found LCD Panel: %s %s\n",
+				panels[i].manufacturer,
+				panels[i].product_name);
+		mtl017->regs = panels[i].regs;
+
+		timings->modes[0].name =  panels[i].mode->name;
+		timings->modes[0].refresh =  panels[i].mode->refresh;
+		timings->modes[0].xres =  panels[i].mode->xres;
+		timings->modes[0].yres =  panels[i].mode->yres;
+		timings->modes[0].pixclock =  panels[i].mode->pixclock;
+		timings->modes[0].left_margin =  panels[i].mode->left_margin;
+		timings->modes[0].right_margin =  panels[i].mode->right_margin;
+		timings->modes[0].upper_margin =  panels[i].mode->upper_margin;
+		timings->modes[0].lower_margin =  panels[i].mode->lower_margin;
+		timings->modes[0].hsync_len =  panels[i].mode->hsync_len;
+		timings->modes[0].vsync_len =  panels[i].mode->vsync_len;
+		timings->num_modes = 1;
+	}
+
+	return 0;
+}
+
+static int mtl017_enable(struct mtl017 *mtl017)
+{
+	int i;
+	int ret;
+	int retry = 5;
+	u8 *reg_tbl = mtl017->regs;
+
+	dev_dbg(mtl017->dev, "Initializing MTL017 LVDS Controller\n");
+
+	ret = regulator_enable(mtl017->regulator);
+	if (ret)
+		return ret;
+
+	gpio_direction_output(mtl017->reset_gpio, mtl017->reset_active_high);
+	mdelay(5);
+	gpio_direction_output(mtl017->reset_gpio, !mtl017->reset_active_high);
+	mdelay(5);
+	gpio_direction_output(mtl017->enable_gpio, mtl017->enable_active_high);
+
+	/* Write configuration table */
+	for (i = 0; i < REGMAP_LENGTH; i+=BLOCK_TX_SIZE) {
+retry:
+		mdelay(1);
+		ret = i2c_smbus_write_i2c_block_data(mtl017->client, i, BLOCK_TX_SIZE, &(reg_tbl[i]));
+		if (ret < 0) {
+			dev_warn(mtl017->dev, "failed to initialize: %d\n", ret);
+			if (retry-- > 0)
+				goto retry;
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int mtl017_ioctl(struct vpl *vpl, unsigned int port,
+			unsigned int cmd, void *ptr)
+{
+	struct mtl017 *mtl017 = container_of(vpl,
+			struct mtl017, vpl);
+	int ret = 0;
+
+	switch (cmd) {
+	case VPL_PREPARE:
+		dev_dbg(mtl017->dev, "VPL_PREPARE\n");
+		goto forward;
+	case VPL_ENABLE:
+		dev_dbg(mtl017->dev, "VPL_ENABLE\n");
+
+		ret = mtl017_enable(mtl017);
+		if (ret < 0)
+			break;
+
+		goto forward;
+	case VPL_DISABLE:
+		dev_dbg(mtl017->dev, "VPL_DISABLE\n");
+
+		goto forward;
+	case VPL_GET_VIDEOMODES:
+		dev_dbg(mtl017->dev, "VPL_GET_VIDEOMODES\n");
+
+		ret = mtl017_get_videomodes(mtl017, ptr);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+
+forward:
+	return vpl_ioctl(&mtl017->vpl, 1, cmd, ptr);
+}
+
+static int mtl017_probe(struct device_d *dev)
+{
+	struct mtl017 *mtl017;
+	int ret;
+	enum of_gpio_flags flags;
+
+	mtl017 = xzalloc(sizeof(struct mtl017));
+	mtl017->vpl.node = dev->device_node;
+	mtl017->vpl.ioctl = mtl017_ioctl;
+	mtl017->dev = dev;
+	mtl017->client = to_i2c_client(dev);
+	mtl017->regulator = regulator_get(dev, "vdd");
+
+	mtl017->enable_gpio = of_get_named_gpio_flags(dev->device_node,
+			"enable-gpios", 0, &flags);
+	if (gpio_is_valid(mtl017->enable_gpio)) {
+		if (!(flags & OF_GPIO_ACTIVE_LOW))
+			mtl017->enable_active_high = 1;
+	}
+
+	mtl017->reset_gpio = of_get_named_gpio_flags(dev->device_node,
+			"reset-gpios", 0, &flags);
+	if (gpio_is_valid(mtl017->reset_gpio)) {
+		if (!(flags & OF_GPIO_ACTIVE_LOW))
+			mtl017->reset_active_high = 1;
+	}
+
+	ret = vpl_register(&mtl017->vpl);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct driver_d twl_driver = {
+	.name  = "mtl017",
+	.probe = mtl017_probe,
+};
+
+static int mtl017_init(void)
+{
+	i2c_driver_register(&twl_driver);
+	return 0;
+}
+
+device_initcall(mtl017_init);
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 09/13] video: Add missing prototype for display_timings_release
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (7 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 08/13] video: Add MTL017 LVDS encoder support Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 10/13] video: ipuv3: remove unused variable Sascha Hauer
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/fb.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/fb.h b/include/fb.h
index 9e59b2a..ac36402 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -144,6 +144,7 @@ struct fb_info {
 };
 
 struct display_timings *of_get_display_timings(struct device_node *np);
+void display_timings_release(struct display_timings *);
 
 int register_framebuffer(struct fb_info *info);
 
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 10/13] video: ipuv3: remove unused variable
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (8 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 09/13] video: Add missing prototype for display_timings_release Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 11/13] video: ipuv3: Replace ipu_output with VPL Sascha Hauer
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/imx-ipu-v3/imx-ipu-v3.h | 1 -
 drivers/video/imx-ipu-v3/ipufb.c      | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/video/imx-ipu-v3/imx-ipu-v3.h b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
index 7c48a7c..d046aee 100644
--- a/drivers/video/imx-ipu-v3/imx-ipu-v3.h
+++ b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
@@ -44,7 +44,6 @@ struct ipu_di_signal_cfg {
 
 	u16 width;
 	u16 height;
-	u32 pixel_fmt;
 	u16 h_start_width;
 	u16 h_sync_width;
 	u16 h_end_width;
diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c
index 7ee4ae3..c032621 100644
--- a/drivers/video/imx-ipu-v3/ipufb.c
+++ b/drivers/video/imx-ipu-v3/ipufb.c
@@ -115,7 +115,6 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
 	sig_cfg.clk_pol = 1;
 	sig_cfg.width = mode->xres;
 	sig_cfg.height = mode->yres;
-	sig_cfg.pixel_fmt = out_pixel_fmt;
 	sig_cfg.h_start_width = mode->left_margin;
 	sig_cfg.h_sync_width = mode->hsync_len;
 	sig_cfg.h_end_width = mode->right_margin;
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 11/13] video: ipuv3: Replace ipu_output with VPL
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (9 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 10/13] video: ipuv3: remove unused variable Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 12/13] video: ipuv3: match ipu_di_signal_cfg's clk_pol with its description Sascha Hauer
  2015-07-09  7:24 ` [PATCH 13/13] video: Add simple-panel support Sascha Hauer
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

The ipuv3 makes heavy use of video encoders internally to the SoC but
also external encoders are common. Switch to VPL support to be able
to handle these properly.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/imx-ipu-v3/Kconfig      |   1 +
 drivers/video/imx-ipu-v3/imx-hdmi.c   |  93 +++++++++++-----------
 drivers/video/imx-ipu-v3/imx-ipu-v3.h |  24 ++----
 drivers/video/imx-ipu-v3/imx-ldb.c    | 116 +++++++++++++++++++++-------
 drivers/video/imx-ipu-v3/ipufb.c      | 141 ++++++++++++++--------------------
 5 files changed, 197 insertions(+), 178 deletions(-)

diff --git a/drivers/video/imx-ipu-v3/Kconfig b/drivers/video/imx-ipu-v3/Kconfig
index 2ca9132..386ff5b 100644
--- a/drivers/video/imx-ipu-v3/Kconfig
+++ b/drivers/video/imx-ipu-v3/Kconfig
@@ -1,6 +1,7 @@
 config DRIVER_VIDEO_IMX_IPUV3
 	bool "i.MX IPUv3 driver"
 	depends on ARCH_IMX
+	select VIDEO_VPL
 	help
 	  Support the IPUv3 found on Freescale i.MX51/53/6 SoCs
 
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c b/drivers/video/imx-ipu-v3/imx-hdmi.c
index e01bfe8..f5a2e3c 100644
--- a/drivers/video/imx-ipu-v3/imx-hdmi.c
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.c
@@ -23,6 +23,7 @@
 #include <asm-generic/div64.h>
 #include <linux/clk.h>
 #include <i2c/i2c.h>
+#include <video/vpl.h>
 #include <mach/imx6-regs.h>
 #include <mach/imx53-regs.h>
 
@@ -133,13 +134,13 @@ struct imx_hdmi {
 	bool phy_enabled;
 
 	struct regmap *regmap;
-	struct i2c_adapter *ddc;
+	struct device_node *ddc_node;;
 	void __iomem *regs;
 
 	unsigned int sample_rate;
 	int ratio;
 
-	struct ipu_output output;
+	struct vpl vpl;
 };
 
 static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
@@ -1011,7 +1012,7 @@ static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
 		hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
 }
 
-static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct fb_videomode *mode)
+static int imx_hdmi_setup(struct imx_hdmi *hdmi)
 {
 	int ret;
 
@@ -1134,43 +1135,58 @@ static struct of_device_id imx_hdmi_dt_ids[] = {
 	}
 };
 
-static int imx_hdmi_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+static int imx_hdmi_get_modes(struct imx_hdmi *hdmi, struct display_timings *timings)
 {
-	struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+	int ret = -ENOENT;
 
-	imx_hdmi_set_ipu_di_mux(hdmi, di);
+	if (hdmi->ddc_node) {
+		struct i2c_adapter *i2c;
 
-	return 0;
-}
+                i2c = of_find_i2c_adapter_by_node(hdmi->ddc_node);
+		if (!i2c)
+			return -ENODEV;
+		timings->edid = edid_read_i2c(i2c);
+		if (!timings->edid)
+			return -EINVAL;
 
-static int imx_hdmi_commit(struct ipu_output *output, struct fb_videomode *mode, int di)
-{
-	struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
-
-	imx_hdmi_setup(hdmi, mode);
+		ret = edid_to_display_timings(timings, timings->edid);
+	}
 
-	return 0;
+	return ret;
 }
 
-static int imx_hdmi_disable(struct ipu_output *output)
+static int imx_hdmi_ioctl(struct vpl *vpl, unsigned int port,
+		unsigned int cmd, void *data)
 {
-	struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
-
-	imx_hdmi_phy_disable(hdmi);
+	struct imx_hdmi *hdmi = container_of(vpl, struct imx_hdmi, vpl);
+	struct ipu_di_mode *mode;
+
+	switch (cmd) {
+	case VPL_ENABLE:
+		return imx_hdmi_setup(hdmi);
+	case VPL_DISABLE:
+		imx_hdmi_phy_disable(hdmi);
+		return 0;
+	case VPL_PREPARE:
+		imx_hdmi_set_ipu_di_mux(hdmi, port);
+		return 0;
+	case VPL_GET_VIDEOMODES:
+		return imx_hdmi_get_modes(hdmi, data);
+	case IMX_IPU_VPL_DI_MODE:
+		mode = data;
+
+		mode->di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+		mode->interface_pix_fmt = V4L2_PIX_FMT_RGB24;
+
+		return 0;
+	}
 
 	return 0;
 }
 
-static struct ipu_output_ops imx_hdmi_ops = {
-	.prepare = imx_hdmi_prepare,
-	.enable = imx_hdmi_commit,
-	.disable = imx_hdmi_disable,
-};
-
 static int imx_hdmi_probe(struct device_d *dev)
 {
 	struct device_node *np = dev->device_node;
-	struct device_node *ddc_node;
 	struct imx_hdmi *hdmi;
 	int ret;
 	const struct imx_hdmi_data *devtype;
@@ -1190,18 +1206,7 @@ static int imx_hdmi_probe(struct device_d *dev)
 	if (ret)
 		return ret;
 
-	if (IS_ENABLED(CONFIG_DRIVER_VIDEO_EDID)) {
-		ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
-		if (ddc_node) {
-			hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
-			if (!hdmi->ddc)
-				dev_dbg(hdmi->dev, "failed to read ddc node\n");
-		} else {
-			dev_dbg(hdmi->dev, "no ddc property found\n");
-		}
-
-		ddc_node = NULL;
-	}
+	hdmi->ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
 
 	hdmi->regs = dev_request_mem_region(dev, 0);
 	if (!hdmi->regs)
@@ -1269,15 +1274,11 @@ static int imx_hdmi_probe(struct device_d *dev)
 	/* Unmute interrupts */
 	hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
 
-	hdmi->output.ops = &imx_hdmi_ops;
-	hdmi->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
-	hdmi->output.out_pixel_fmt = V4L2_PIX_FMT_RGB24;
-	hdmi->output.name = asprintf("hdmi-0");
-	hdmi->output.ipu_mask = devtype->ipu_mask;
-	hdmi->output.edid_i2c_adapter = hdmi->ddc;
-	hdmi->output.modes = of_get_display_timings(np);
-
-	ipu_register_output(&hdmi->output);
+	hdmi->vpl.node = np;
+	hdmi->vpl.ioctl = imx_hdmi_ioctl;
+	ret = vpl_register(&hdmi->vpl);
+	if (ret)
+		return ret;
 
 	return 0;
 
diff --git a/drivers/video/imx-ipu-v3/imx-ipu-v3.h b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
index d046aee..783535e 100644
--- a/drivers/video/imx-ipu-v3/imx-ipu-v3.h
+++ b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
@@ -14,6 +14,7 @@
 
 #include <io.h>
 #include <fb.h>
+#include <video/vpl.h>
 #include <video/fourcc.h>
 
 struct ipu_soc;
@@ -318,26 +319,11 @@ struct ipu_client_platformdata {
 	struct device_node *device_node;
 };
 
-struct ipu_output;
-
-struct ipu_output_ops {
-	int (*prepare)(struct ipu_output *ipu_video_output, struct fb_videomode *mode, int di);
-	int (*enable)(struct ipu_output *ipu_video_output, struct fb_videomode *mode, int di);
-	int (*disable)(struct ipu_output *ipu_video_output);
-	int (*unprepare)(struct ipu_output *ipu_video_output);
-};
-
-struct ipu_output {
-	struct ipu_output_ops *ops;
-	struct list_head list;
-	unsigned int di_clkflags;
-	uint32_t out_pixel_fmt;
-	struct i2c_adapter *edid_i2c_adapter;
-	struct display_timings *modes;
-	char *name;
-	int ipu_mask;
+struct ipu_di_mode {
+	u32 di_clkflags;
+	u32 interface_pix_fmt;
 };
 
-int ipu_register_output(struct ipu_output *ouput);
+#define IMX_IPU_VPL_DI_MODE	0x12660001
 
 #endif /* __DRM_IPU_H__ */
diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
index a05bfad..db5f8b6 100644
--- a/drivers/video/imx-ipu-v3/imx-ldb.c
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -21,10 +21,13 @@
 #include <common.h>
 #include <fb.h>
 #include <io.h>
+#include <of_graph.h>
 #include <driver.h>
 #include <malloc.h>
 #include <errno.h>
 #include <init.h>
+#include <video/vpl.h>
+#include <mfd/imx6q-iomuxc-gpr.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <asm-generic/div64.h>
@@ -57,13 +60,17 @@ struct imx_ldb_channel {
 	int chno;
 	int mode_valid;
 	struct display_timings *modes;
-	struct ipu_output output;
+	struct device_node *remote;
+	struct vpl vpl;
+	int output_port;
+	int datawidth;
 };
 
 struct imx_ldb_data {
 	void __iomem *base;
 	int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di);
 	unsigned ipu_mask;
+	int have_mux;
 };
 
 struct imx_ldb {
@@ -102,16 +109,11 @@ static const int of_get_data_mapping(struct device_node *np)
 	return -EINVAL;
 }
 
-static int imx_ldb_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+static int imx_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, struct fb_videomode *mode,
+		int di)
 {
-	struct imx_ldb_channel *imx_ldb_ch = container_of(output, struct imx_ldb_channel, output);
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
 
-	if (PICOS2KHZ(mode->pixclock) > 85000) {
-		dev_warn(ldb->dev,
-			 "%s: mode exceeds 85 MHz pixel clock\n", __func__);
-	}
-
 	ldb->soc_data->prepare(imx_ldb_ch, di);
 
 	/* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
@@ -141,7 +143,20 @@ static int imx_ldb_prepare(struct ipu_output *output, struct fb_videomode *mode,
 
 	writel(ldb->ldb_ctrl, ldb->base);
 
-	return 0;
+	return vpl_ioctl(&imx_ldb_ch->vpl, imx_ldb_ch->output_port,
+			VPL_PREPARE, NULL);
+}
+
+static int imx_ldb_enable(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+	return vpl_ioctl(&imx_ldb_ch->vpl, imx_ldb_ch->output_port,
+				VPL_ENABLE, NULL);
+}
+
+static int imx_ldb_disable(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+	return vpl_ioctl(&imx_ldb_ch->vpl, imx_ldb_ch->output_port,
+			VPL_DISABLE, NULL);
 }
 
 static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
@@ -226,6 +241,7 @@ static struct imx_ldb_data imx_ldb_data_imx6q = {
 	.base = (void *)MX6_IOMUXC_BASE_ADDR + 0x8,
 	.prepare = imx6q_ldb_prepare,
 	.ipu_mask = 0xf,
+	.have_mux = 1,
 };
 
 static struct imx_ldb_data imx_ldb_data_imx53 = {
@@ -234,9 +250,42 @@ static struct imx_ldb_data imx_ldb_data_imx53 = {
 	.ipu_mask = 0x3,
 };
 
-static struct ipu_output_ops imx_ldb_ops = {
-	.prepare = imx_ldb_prepare,
-};
+static int imx_ldb_ioctl(struct vpl *vpl, unsigned int port,
+		unsigned int cmd, void *data)
+{
+	struct imx_ldb_channel *imx_ldb_ch = container_of(vpl,
+			struct imx_ldb_channel, vpl);
+	int ret;
+	struct ipu_di_mode *mode;
+
+	switch (cmd) {
+	case VPL_ENABLE:
+		ret = vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+		if (ret)
+			return ret;
+		return imx_ldb_enable(imx_ldb_ch, port);
+	case VPL_DISABLE:
+		ret = vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+		if (ret)
+			return ret;
+		return imx_ldb_disable(imx_ldb_ch, port);
+	case VPL_PREPARE:
+		ret = vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+		if (ret)
+			return ret;
+		return imx_ldb_prepare(imx_ldb_ch, data, port);
+	case IMX_IPU_VPL_DI_MODE:
+		mode = data;
+
+		mode->di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+		mode->interface_pix_fmt = (imx_ldb_ch->datawidth == 24) ?
+			V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
+
+		return 0;
+	default:
+		return vpl_ioctl(vpl, imx_ldb_ch->output_port, cmd, data);
+	}
+}
 
 static int imx_ldb_probe(struct device_d *dev)
 {
@@ -245,7 +294,6 @@ static int imx_ldb_probe(struct device_d *dev)
 	struct imx_ldb *imx_ldb;
 	int ret, i;
 	int dual = 0;
-	int datawidth;
 	int mapping;
 	const struct imx_ldb_data *devtype;
 
@@ -259,6 +307,8 @@ static int imx_ldb_probe(struct device_d *dev)
 
 	for_each_child_of_node(np, child) {
 		struct imx_ldb_channel *channel;
+		struct device_node *port;
+		struct device_node *endpoint;
 
 		ret = of_property_read_u32(child, "reg", &i);
 		if (ret || i < 0 || i > 1)
@@ -275,17 +325,37 @@ static int imx_ldb_probe(struct device_d *dev)
 		channel = &imx_ldb->channel[i];
 		channel->ldb = imx_ldb;
 		channel->chno = i;
+		channel->output_port = imx_ldb->soc_data->have_mux ? 4 : 1;
+
+		/* The output port is port@4 with mux or port@1 without mux */
+		port = of_graph_get_port_by_id(child, channel->output_port);
+		if (!port) {
+			dev_warn(dev, "No port found for %s\n", child->full_name);
+			continue;
+		}
 
-		ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
+		endpoint = of_get_child_by_name(port, "endpoint");
+		if (!endpoint) {
+			dev_warn(dev, "No endpoint found on %s\n", port->full_name);
+			continue;
+		}
+
+		channel->vpl.node = child;
+		channel->vpl.ioctl = &imx_ldb_ioctl;
+		ret = vpl_register(&channel->vpl);
+		if (ret)
+			return ret;
+
+		ret = of_property_read_u32(child, "fsl,data-width", &channel->datawidth);
 		if (ret)
-			datawidth = 0;
-		else if (datawidth != 18 && datawidth != 24)
+			channel->datawidth = 0;
+		else if (channel->datawidth != 18 && channel->datawidth != 24)
 			return -EINVAL;
 
 		mapping = of_get_data_mapping(child);
 		switch (mapping) {
 		case LVDS_BIT_MAP_SPWG:
-			if (datawidth == 24) {
+			if (channel->datawidth == 24) {
 				if (i == 0 || dual)
 					imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
 				if (i == 1 || dual)
@@ -293,7 +363,7 @@ static int imx_ldb_probe(struct device_d *dev)
 			}
 			break;
 		case LVDS_BIT_MAP_JEIDA:
-			if (datawidth == 18) {
+			if (channel->datawidth == 18) {
 				dev_err(dev, "JEIDA standard only supported in 24 bit\n");
 				return -EINVAL;
 			}
@@ -306,16 +376,6 @@ static int imx_ldb_probe(struct device_d *dev)
 			dev_err(dev, "data mapping not specified or invalid\n");
 			return -EINVAL;
 		}
-
-		channel->output.ops = &imx_ldb_ops;
-		channel->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
-		channel->output.out_pixel_fmt = (datawidth == 24) ?
-			V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
-		channel->output.modes = of_get_display_timings(child);
-		channel->output.name = asprintf("ldb-%d", i);
-		channel->output.ipu_mask = devtype->ipu_mask;
-
-		ipu_register_output(&channel->output);
 	}
 
 	return 0;
diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c
index c032621..74c4dba 100644
--- a/drivers/video/imx-ipu-v3/ipufb.c
+++ b/drivers/video/imx-ipu-v3/ipufb.c
@@ -19,6 +19,7 @@
 #include <malloc.h>
 #include <errno.h>
 #include <init.h>
+#include <of_graph.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <asm-generic/div64.h>
@@ -62,8 +63,9 @@ struct ipufb_info {
 	struct list_head	list;
 	char			*name;
 	int			id;
+	int			dino;
 
-	struct ipu_output	*output;
+	struct vpl	vpl;
 };
 
 static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
@@ -73,23 +75,6 @@ static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
 	return chan << bf->offset;
 }
 
-static LIST_HEAD(ipu_outputs);
-static LIST_HEAD(ipu_fbs);
-
-int ipu_register_output(struct ipu_output *ouput)
-{
-	list_add_tail(&ouput->list, &ipu_outputs);
-
-	return 0;
-}
-
-static int ipu_register_fb(struct ipufb_info *ipufb)
-{
-	list_add_tail(&ipufb->list, &ipu_fbs);
-
-	return 0;
-}
-
 int ipu_crtc_mode_set(struct ipufb_info *fbi,
 			       struct fb_videomode *mode,
 			       int x, int y)
@@ -97,14 +82,17 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
 	struct fb_info *info = &fbi->info;
 	int ret;
 	struct ipu_di_signal_cfg sig_cfg = {};
-	u32 out_pixel_fmt;
+	struct ipu_di_mode di_mode = {};
+	u32 interface_pix_fmt;
 
 	dev_info(fbi->dev, "%s: mode->xres: %d\n", __func__,
 			mode->xres);
 	dev_info(fbi->dev, "%s: mode->yres: %d\n", __func__,
 			mode->yres);
 
-	out_pixel_fmt = fbi->output->out_pixel_fmt;
+	vpl_ioctl(&fbi->vpl, 2 + fbi->dino, IMX_IPU_VPL_DI_MODE, &di_mode);
+	interface_pix_fmt = di_mode.interface_pix_fmt ?
+		di_mode.interface_pix_fmt : fbi->interface_pix_fmt;
 
 	if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
 		sig_cfg.Hsync_pol = 1;
@@ -123,7 +111,7 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
 	sig_cfg.v_sync_width = mode->vsync_len;
 	sig_cfg.v_end_width = mode->lower_margin;
 	sig_cfg.pixelclock = PICOS2KHZ(mode->pixclock) * 1000UL;
-	sig_cfg.clkflags = fbi->output->di_clkflags;
+	sig_cfg.clkflags = di_mode.di_clkflags;
 
 	sig_cfg.v_to_h_sync = 0;
 
@@ -131,7 +119,7 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
 	sig_cfg.vsync_pin = 3;
 
 	ret = ipu_dc_init_sync(fbi->dc, fbi->di, sig_cfg.interlaced,
-			out_pixel_fmt, mode->xres);
+			interface_pix_fmt, mode->xres);
 	if (ret) {
 		dev_err(fbi->dev,
 				"initializing display controller failed with %d\n",
@@ -170,31 +158,25 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
 static void ipufb_enable_controller(struct fb_info *info)
 {
 	struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
-	struct ipu_output *output = fbi->output;
 
-	if (output->ops->prepare)
-		output->ops->prepare(output, info->mode, fbi->id);
+	vpl_ioctl_prepare(&fbi->vpl, 2 + fbi->dino, info->mode);
 
 	ipu_crtc_mode_set(fbi, info->mode, 0, 0);
 
-	if (output->ops->enable)
-		output->ops->enable(output, info->mode, fbi->id);
+	vpl_ioctl_enable(&fbi->vpl, 2 + fbi->dino);
 }
 
 static void ipufb_disable_controller(struct fb_info *info)
 {
 	struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
-	struct ipu_output *output = fbi->output;
 
-	if (output->ops->disable)
-		output->ops->disable(output);
+	vpl_ioctl_disable(&fbi->vpl, 2 + fbi->dino);
 
 	ipu_plane_disable(fbi->plane[0]);
 	ipu_dc_disable_channel(fbi->dc);
 	ipu_di_disable(fbi->di);
 
-	if (output->ops->unprepare)
-		output->ops->unprepare(output);
+	vpl_ioctl_unprepare(&fbi->vpl, 2 + fbi->dino);
 }
 
 static int ipufb_activate_var(struct fb_info *info)
@@ -207,7 +189,7 @@ static int ipufb_activate_var(struct fb_info *info)
 	if (!fbi->info.screen_base)
 		return -ENOMEM;
 
-	memset(fbi->info.screen_base, 0, info->line_length * info->yres);
+	memset(fbi->info.screen_base, 0x0, info->line_length * info->yres);
 
 	return 0;
 }
@@ -218,56 +200,6 @@ static struct fb_ops ipufb_ops = {
 	.fb_activate_var = ipufb_activate_var,
 };
 
-static struct ipufb_info *ipu_output_find_di(struct ipu_output *output)
-{
-	struct ipufb_info *ipufb;
-
-	list_for_each_entry(ipufb, &ipu_fbs, list) {
-		if (!(output->ipu_mask & (1 << ipufb->id)))
-			continue;
-		if (ipufb->output)
-			continue;
-
-		return ipufb;
-	}
-
-	return NULL;
-}
-
-static int ipu_init(void)
-{
-	struct ipu_output *output;
-	struct ipufb_info *ipufb;
-	int ret;
-
-	list_for_each_entry(output, &ipu_outputs, list) {
-		pr_info("found output: %s\n", output->name);
-		ipufb = ipu_output_find_di(output);
-		if (!ipufb) {
-			pr_info("no di found for output %s\n", output->name);
-			continue;
-		}
-		pr_info("using di %s for output %s\n", ipufb->name, output->name);
-
-		ipufb->output = output;
-
-		ipufb->info.edid_i2c_adapter = output->edid_i2c_adapter;
-		if (output->modes) {
-			ipufb->info.modes.modes = output->modes->modes;
-			ipufb->info.modes.num_modes = output->modes->num_modes;
-		}
-
-		ret = register_framebuffer(&ipufb->info);
-		if (ret < 0) {
-			dev_err(ipufb->dev, "failed to register framebuffer\n");
-			return ret;
-		}
-	}
-
-	return 0;
-}
-late_initcall(ipu_init);
-
 static int ipu_get_resources(struct ipufb_info *fbi,
 		struct ipu_client_platformdata *pdata)
 {
@@ -310,6 +242,8 @@ static int ipufb_probe(struct device_d *dev)
 	int ret, ipuid;
 	struct ipu_client_platformdata *pdata = dev->platform_data;
 	struct ipu_rgb *ipu_rgb;
+	struct device_node *node;
+	const char *fmt;
 
 	fbi = xzalloc(sizeof(*fbi));
 	info = &fbi->info;
@@ -317,6 +251,7 @@ static int ipufb_probe(struct device_d *dev)
 	ipuid = of_alias_get_id(dev->parent->device_node, "ipu");
 	fbi->name = asprintf("ipu%d-di%d", ipuid + 1, pdata->di);
 	fbi->id = ipuid * 2 + pdata->di;
+	fbi->dino = pdata->di;
 
 	fbi->dev = dev;
 	info->priv = fbi;
@@ -336,7 +271,38 @@ static int ipufb_probe(struct device_d *dev)
 	if (ret)
 		return ret;
 
-	ret = ipu_register_fb(fbi);
+	node = of_graph_get_port_by_id(dev->parent->device_node, 2 + pdata->di);
+	if (node && of_graph_port_is_available(node)) {
+		dev_info(fbi->dev, "register vpl for %s\n", dev->parent->device_node->full_name);
+
+		fbi->vpl.node = dev->parent->device_node;
+		ret = vpl_register(&fbi->vpl);
+		if (ret)
+			return ret;
+
+		ret = of_property_read_string(node, "interface-pix-fmt", &fmt);
+		if (!ret) {
+			if (!strcmp(fmt, "rgb24"))
+				fbi->interface_pix_fmt = V4L2_PIX_FMT_RGB24;
+			else if (!strcmp(fmt, "rgb565"))
+				fbi->interface_pix_fmt = V4L2_PIX_FMT_RGB565;
+			else if (!strcmp(fmt, "bgr666"))
+				fbi->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
+			else if (!strcmp(fmt, "lvds666"))
+				fbi->interface_pix_fmt =
+					v4l2_fourcc('L', 'V', 'D', '6');
+		}
+
+		ret = vpl_ioctl(&fbi->vpl, 2 + fbi->dino, VPL_GET_VIDEOMODES, &info->modes);
+		if (ret)
+			return ret;
+
+		ret = register_framebuffer(info);
+		if (ret < 0) {
+			dev_err(fbi->dev, "failed to register framebuffer\n");
+			return ret;
+		}
+	}
 
 	return ret;
 }
@@ -350,4 +316,9 @@ static struct driver_d ipufb_driver = {
 	.probe		= ipufb_probe,
 	.remove		= ipufb_remove,
 };
-device_platform_driver(ipufb_driver);
+
+static int ipufb_register(void)
+{
+	return platform_driver_register(&ipufb_driver);
+}
+late_initcall(ipufb_register);
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 12/13] video: ipuv3: match ipu_di_signal_cfg's clk_pol with its description
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (10 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 11/13] video: ipuv3: Replace ipu_output with VPL Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  2015-07-09  7:24 ` [PATCH 13/13] video: Add simple-panel support Sascha Hauer
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

From this Linux commit:

commit 85de9d17c485c4196f74d45de2206d4802f8a3be
Author: Denis Carikli <denis@eukrea.com>
Date:   Mon Apr 7 14:44:43 2014 +0200

    imx-drm: match ipu_di_signal_cfg's clk_pol with its description.

    According to the datasheet, setting the di0_polarity_disp_clk
    field in the GENERAL di register sets the output clock polarity
    to active high.

    Signed-off-by: Denis Carikli <denis@eukrea.com>
    Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/imx-ipu-v3/ipu-di.c | 2 +-
 drivers/video/imx-ipu-v3/ipufb.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/imx-ipu-v3/ipu-di.c b/drivers/video/imx-ipu-v3/ipu-di.c
index e3338d0..8df9c9f 100644
--- a/drivers/video/imx-ipu-v3/ipu-di.c
+++ b/drivers/video/imx-ipu-v3/ipu-di.c
@@ -627,7 +627,7 @@ int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
 		}
 	}
 
-	if (!sig->clk_pol)
+	if (sig->clk_pol)
 		di_gen |= DI_GEN_POLARITY_DISP_CLK;
 
 	ipu_di_write(di, di_gen, DI_GENERAL);
diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c
index 74c4dba..e804c31 100644
--- a/drivers/video/imx-ipu-v3/ipufb.c
+++ b/drivers/video/imx-ipu-v3/ipufb.c
@@ -100,7 +100,7 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi,
 		sig_cfg.Vsync_pol = 1;
 
 	sig_cfg.enable_pol = 1;
-	sig_cfg.clk_pol = 1;
+	sig_cfg.clk_pol = 0;
 	sig_cfg.width = mode->xres;
 	sig_cfg.height = mode->yres;
 	sig_cfg.h_start_width = mode->left_margin;
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 13/13] video: Add simple-panel support
  2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
                   ` (11 preceding siblings ...)
  2015-07-09  7:24 ` [PATCH 12/13] video: ipuv3: match ipu_di_signal_cfg's clk_pol with its description Sascha Hauer
@ 2015-07-09  7:24 ` Sascha Hauer
  12 siblings, 0 replies; 14+ messages in thread
From: Sascha Hauer @ 2015-07-09  7:24 UTC (permalink / raw)
  To: Barebox List

This adds support for simple panels. These are panels which don't need
special handling but can have enable gpios and such. Unlike the Linux
kernel implementation this one is able to understand display-timings
nodes so that it's not necessary to keep a list of all known displays
with their corresponding timings in barebox.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/Kconfig        |   9 +++
 drivers/video/Makefile       |   1 +
 drivers/video/simple-panel.c | 160 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/video/simple-panel.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6637877..323fb77 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -117,4 +117,13 @@ config DRIVER_VIDEO_MTL017
 	  The MTL017 is a parallel to lvds video encoder chip found on the
 	  Efika MX Smartbook.
 
+config DRIVER_VIDEO_SIMPLE_PANEL
+	bool "Simple panel support"
+	select VIDEO_VPL
+	help
+	  This enabled support for simple panels, i.e. panels which consist of
+	  a mode definition and enable gpios in the devicetree. Unlike the
+	  Linux Kernel implementation this one is able to understand display-timings
+	  nodes so that it's not necessary to keep a list of all known displays
+	  with their corresponding timings in barebox.
 endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 1e2109e..eab6461 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT) += backlight.o
 obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT_PWM) += backlight-pwm.o
 obj-$(CONFIG_VIDEO_VPL) += vpl.o
 obj-$(CONFIG_DRIVER_VIDEO_MTL017) += mtl017.o
+obj-$(CONFIG_DRIVER_VIDEO_SIMPLE_PANEL) += simple-panel.o
 
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
 obj-$(CONFIG_DRIVER_VIDEO_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
diff --git a/drivers/video/simple-panel.c b/drivers/video/simple-panel.c
new file mode 100644
index 0000000..dceedc6
--- /dev/null
+++ b/drivers/video/simple-panel.c
@@ -0,0 +1,160 @@
+/*
+ * simple panel support for barebox
+ *
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <malloc.h>
+#include <init.h>
+#include <linux/err.h>
+#include <of.h>
+#include <fb.h>
+#include <gpio.h>
+#include <of_gpio.h>
+#include <video/backlight.h>
+#include <video/vpl.h>
+#include <i2c/i2c.h>
+
+struct simple_panel {
+	struct vpl vpl;
+	int enable_gpio;
+	int enable_active_high;
+	int enabled;
+	struct device_node *backlight_node;
+	struct backlight_device *backlight;
+	struct device_node *ddc_node;
+	int enable_delay;
+};
+
+static int simple_panel_enable(struct simple_panel *panel)
+{
+	int ret;
+
+	if (panel->backlight_node && !panel->backlight) {
+		panel->backlight = of_backlight_find(panel->backlight_node);
+		if (!panel->backlight)
+			return -ENODEV;
+	}
+
+	if (gpio_is_valid(panel->enable_gpio))
+		gpio_direction_output(panel->enable_gpio,
+			panel->enable_active_high);
+
+	if (panel->enable_delay)
+		mdelay(panel->enable_delay);
+
+	if (panel->backlight) {
+		ret = backlight_set_brightness_default(panel->backlight);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int simple_panel_disable(struct simple_panel *panel)
+{
+	if (panel->backlight)
+		backlight_set_brightness(panel->backlight, 0);
+
+	if (gpio_is_valid(panel->enable_gpio))
+		gpio_direction_output(panel->enable_gpio,
+			!panel->enable_active_high);
+
+	return 0;
+}
+
+static int simple_panel_get_modes(struct simple_panel *panel, struct display_timings *timings)
+{
+	int ret = -ENOENT;
+
+	if (panel->ddc_node) {
+		struct i2c_adapter *i2c;
+
+                i2c = of_find_i2c_adapter_by_node(panel->ddc_node);
+		if (!i2c)
+			return -ENODEV;
+		timings->edid = edid_read_i2c(i2c);
+		if (!timings->edid)
+			return -EINVAL;
+
+		ret = edid_to_display_timings(timings, timings->edid);
+	}
+
+	return ret;
+}
+
+static int simple_panel_ioctl(struct vpl *vpl, unsigned int port,
+			unsigned int cmd, void *ptr)
+{
+	struct simple_panel *panel = container_of(vpl,
+			struct simple_panel, vpl);
+
+	switch (cmd) {
+	case VPL_ENABLE:
+		return simple_panel_enable(panel);
+	case VPL_DISABLE:
+		return simple_panel_disable(panel);
+	case VPL_GET_VIDEOMODES:
+		return simple_panel_get_modes(panel, ptr);
+	default:
+		return -ENOSYS;
+	}
+}
+
+static int simple_panel_probe(struct device_d *dev)
+{
+	struct simple_panel *panel;
+	struct device_node *node = dev->device_node;
+	enum of_gpio_flags flags;
+	int ret;
+
+	panel = xzalloc(sizeof(*panel));
+
+	panel->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0, &flags);
+	panel->vpl.node = node;
+	panel->vpl.ioctl = simple_panel_ioctl;
+
+	if (gpio_is_valid(panel->enable_gpio)) {
+		if (!(flags & OF_GPIO_ACTIVE_LOW))
+			panel->enable_active_high = 1;
+	}
+
+	panel->ddc_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
+
+	of_property_read_u32(node, "enable-delay", &panel->enable_delay);
+
+	panel->backlight_node = of_parse_phandle(node, "backlight", 0);
+
+	ret = vpl_register(&panel->vpl);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static struct of_device_id simple_panel_of_ids[] = {
+	{ .compatible = "simple-panel", },
+	{ }
+};
+
+static struct driver_d simple_panel_driver = {
+	.name  = "simple-panel",
+	.probe = simple_panel_probe,
+	.of_compatible = DRV_OF_COMPAT(simple_panel_of_ids),
+};
+device_platform_driver(simple_panel_driver);
-- 
2.1.4


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

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-07-09  7:25 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-09  7:24 Video support for EfikaSB Sascha Hauer
2015-07-09  7:24 ` [PATCH 01/13] of: base: implement of_get_next_child Sascha Hauer
2015-07-09  7:24 ` [PATCH 02/13] of: import of_graph functions Sascha Hauer
2015-07-09  7:24 ` [PATCH 03/13] of_graph: add of_graph_port_is_available Sascha Hauer
2015-07-09  7:24 ` [PATCH 04/13] ARM: i.MX51 Efikasb: Disable backlight earlier Sascha Hauer
2015-07-09  7:24 ` [PATCH 05/13] ARM: i.MX51 Efikasb: make more space for barebox Sascha Hauer
2015-07-09  7:24 ` [PATCH 06/13] ARM: i.MX51 Efikasb: update device tree Sascha Hauer
2015-07-09  7:24 ` [PATCH 07/13] video: Add Video Pipeline (VPL) support Sascha Hauer
2015-07-09  7:24 ` [PATCH 08/13] video: Add MTL017 LVDS encoder support Sascha Hauer
2015-07-09  7:24 ` [PATCH 09/13] video: Add missing prototype for display_timings_release Sascha Hauer
2015-07-09  7:24 ` [PATCH 10/13] video: ipuv3: remove unused variable Sascha Hauer
2015-07-09  7:24 ` [PATCH 11/13] video: ipuv3: Replace ipu_output with VPL Sascha Hauer
2015-07-09  7:24 ` [PATCH 12/13] video: ipuv3: match ipu_di_signal_cfg's clk_pol with its description Sascha Hauer
2015-07-09  7:24 ` [PATCH 13/13] video: Add simple-panel support Sascha Hauer

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