diff mbox

[RFC,03/10] video: display: Add Device Tree bindings

Message ID 1366211842-21497-4-git-send-email-pawel.moll@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pawel Moll April 17, 2013, 3:17 p.m. UTC
Modelled after the common clock solution, the bindings
are based on the idea of display entity "providers" and
"consumers".

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 .../devicetree/bindings/video/display-bindings.txt |   75 +++++++++++++++++
 drivers/video/display/display-core.c               |   84 ++++++++++++++++++++
 include/video/display.h                            |   11 +++
 3 files changed, 170 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/display-bindings.txt
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/video/display-bindings.txt b/Documentation/devicetree/bindings/video/display-bindings.txt
new file mode 100644
index 0000000..6d8b888
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/display-bindings.txt
@@ -0,0 +1,75 @@ 
+[this is an RFC]
+
+Common Display Framework define a display entity (eg. LCD panel),
+being a sink for video data generated by a video signal generator
+(eg.  LCD controller/driver).
+
+This set of bindings allow to represent connections between them
+in the Device Tree.
+
+Devices nodes representing display sinks are called "display
+providers" and nodes representing display sources are called
+"display consumers".
+
+Notice that in both cases a device represented by a node can
+provide or consume more than one display entity. For example
+a LCD controller can be able to driver more than one LCD
+panel at the same time, while a panel (or a special signal
+multiplexer) may have more than one input (sink) and switch
+between them.
+
+== Display provider ==
+
+Required properties:
+
+* #clock-cells:	Number of cells in the display specifier. Typically
+		0 for nodes providing single display entity and 1
+		for nodes providing multiple displays.
+
+Example:
+			dvi-output: dvi-output@0 {
+				#display-cells = <0>;
+			};
+
+== Display consumer ==
+
+Required properties:
+
+* display:	List of phandle and clock specifier pairs, one pair
+		for each display (sink). Note: if the display provider
+		specifies '0' for #display-cells, then only the phandle
+		portion of the pair will appear.
+
+Example:
+
+			display-driver {
+				display = <&dvi-output>;
+			};
+
+== Larger example ==
+
+			clcd@10020000 {
+				compatible = "arm,pl111", "arm,primecell";
+				reg = <0x10020000 0x1000>;
+				interrupts = <0 44 4>;
+				clocks = <&oscclk1>, <&oscclk2>;
+				clock-names = "clcdclk", "apb_pclk";
+				label = "V2P-CA9 CLCD";
+				display = <&v2m_muxfpga 0xf>;
+				max-hactive = <1024>;
+				max-vactive = <768>;
+				max-bpp = <16>;
+			};
+
+			v2m_muxfpga: muxfpga@0 {
+				compatible = "arm,vexpress-muxfpga";
+				arm,vexpress-sysreg,func = <7 0>;
+				#display-cells = <1>;
+				display = <&v2m_dvimode>;
+			};
+
+			v2m_dvimode: dvimode@0 {
+				compatible = "arm,vexpress-dvimode";
+				arm,vexpress-sysreg,func = <11 0>;
+				#display-cells = <0>;
+			};
diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
index 4b8e45a..9827a5d 100644
--- a/drivers/video/display/display-core.c
+++ b/drivers/video/display/display-core.c
@@ -15,6 +15,7 @@ 
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 #include <video/display.h>
 #include <video/videomode.h>
@@ -230,6 +231,89 @@  void display_entity_put(struct display_entity *entity)
 }
 EXPORT_SYMBOL_GPL(display_entity_put);
 
+#if defined(CONFIG_OF)
+struct of_display_entity_provider {
+	struct list_head list;
+	struct device_node *node;
+	struct display_entity *(*get)(struct of_phandle_args *spec, void *data);
+	void *data;
+};
+
+static LIST_HEAD(of_display_entity_providers);
+static DEFINE_MUTEX(of_display_entity_providers_lock);
+
+int of_display_entity_add_provider(struct device_node *node,
+		struct display_entity *(*get)(struct of_phandle_args *spec,
+		void *data), void *data)
+{
+	struct of_display_entity_provider *provider =
+			kzalloc(sizeof(*provider), GFP_KERNEL);
+
+	if (!provider)
+		return -ENOMEM;
+
+	provider->node = of_node_get(node);
+	provider->get = get;
+	provider->data = data;
+
+	mutex_lock(&of_display_entity_providers_lock);
+	list_add(&provider->list, &of_display_entity_providers);
+	mutex_unlock(&of_display_entity_providers_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_display_entity_add_provider);
+
+struct display_entity *of_display_entity_provider_simple_get(
+		struct of_phandle_args *spec, void *data)
+{
+	return data;
+}
+EXPORT_SYMBOL_GPL(of_display_entity_provider_simple_get);
+
+void of_display_entity_remove_provider(struct device_node *node)
+{
+	struct of_display_entity_provider *provider, *p;
+
+	mutex_lock(&of_display_entity_providers_lock);
+	list_for_each_entry_safe(provider, p, &of_display_entity_providers,
+			list) {
+		if (provider->node == node) {
+			list_del(&provider->list);
+			of_node_put(provider->node);
+			kfree(node);
+			break;
+		}
+	}
+	mutex_unlock(&of_display_entity_providers_lock);
+}
+EXPORT_SYMBOL_GPL(of_display_entity_remove_provider);
+
+struct display_entity *of_display_entity_get(struct device_node *node,
+		int index)
+{
+	struct of_phandle_args spec;
+	struct of_display_entity_provider *provider;
+	struct display_entity *entity = NULL;
+
+	if (of_parse_phandle_with_args(node, "display", "#display-cells",
+			index, &spec) != 0)
+		return NULL;
+
+	mutex_lock(&of_display_entity_providers_lock);
+	list_for_each_entry(provider, &of_display_entity_providers, list) {
+		if (provider->node == spec.np) {
+			entity = provider->get(&spec, provider->data);
+			break;
+		}
+	}
+	mutex_unlock(&of_display_entity_providers_lock);
+
+	return entity;
+}
+EXPORT_SYMBOL_GPL(of_display_entity_get);
+#endif
+
 static int display_entity_notifier_match(struct display_entity *entity,
 				struct display_entity_notifier *notifier)
 {
diff --git a/include/video/display.h b/include/video/display.h
index 64f84d5..7fe8b2f 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -16,6 +16,7 @@ 
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/of.h>
 
 /* -----------------------------------------------------------------------------
  * Display Entity
@@ -149,4 +150,14 @@  void display_entity_unregister_notifier(struct display_entity_notifier *notifier
 #define display_entity_register(display_entity) \
 	__display_entity_register(display_entity, THIS_MODULE)
 
+struct display_entity *of_display_entity_get(struct device_node *node,
+		int index);
+
+int of_display_entity_add_provider(struct device_node *node,
+		struct display_entity *(*get)(struct of_phandle_args *spec,
+		void *data), void *data);
+void of_display_entity_remove_provider(struct device_node *node);
+struct display_entity *of_display_entity_provider_simple_get(
+		struct of_phandle_args *spec, void *data);
+
 #endif /* __DISPLAY_H__ */