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 at 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 --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 at 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 at 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 at 0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                               #display-cells = <1>;
+                               display = <&v2m_dvimode>;
+                       };
+
+                       v2m_dvimode: dvimode at 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__ */
-- 
1.7.10.4


Reply via email to