new file mode 100644
@@ -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>;
+ };
@@ -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)
{
@@ -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__ */
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