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@xxxxxxx> --- .../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@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__ */ -- 1.7.10.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel