diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-03-20 10:09:19 +0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-03-20 10:13:50 +0400 |
commit | 17d5ca91cfc59ae91da5ff9da74ab09a9a2a17d9 (patch) | |
tree | a45f944e15a2600ec20ca4ec11b23d4641095e8e /arch/arm/mach-omap2/display.c | |
parent | b7e4ab50418d5b34ab0dae95193dd71190e1fb50 (diff) | |
parent | c86907b59f505863ec7839471e889330982a596e (diff) | |
download | linux-17d5ca91cfc59ae91da5ff9da74ab09a9a2a17d9.tar.xz |
Merge branch '3.15/dss-dt' into 3.15/fbdev
Merge OMAP DSS DT support
Diffstat (limited to 'arch/arm/mach-omap2/display.c')
-rw-r--r-- | arch/arm/mach-omap2/display.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 93ebb4007ea9..16d33d831287 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -23,6 +23,9 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/slab.h> #include <video/omapdss.h> #include "omap_hwmod.h" @@ -551,3 +554,166 @@ int omap_dss_reset(struct omap_hwmod *oh) return r; } + +/* list of 'compatible' nodes to convert to omapdss specific */ +static const char * const dss_compat_conv_list[] __initconst = { + "composite-connector", + "dvi-connector", + "hdmi-connector", + "panel-dpi", + "panel-dsi-cm", + "sony,acx565akm", + "svideo-connector", + "ti,tfp410", + "ti,tpd12s015", +}; + +/* prepend compatible string with "omapdss," */ +static __init void omapdss_omapify_node(struct device_node *node, + const char *compat) +{ + char *new_compat; + struct property *prop; + + new_compat = kasprintf(GFP_KERNEL, "omapdss,%s", compat); + + prop = kzalloc(sizeof(*prop), GFP_KERNEL); + + if (!prop) { + pr_err("omapdss_omapify_node: kzalloc failed\n"); + return; + } + + prop->name = "compatible"; + prop->value = new_compat; + prop->length = strlen(new_compat) + 1; + + of_update_property(node, prop); +} + +/* + * As omapdss panel drivers are omapdss specific, but we want to define the + * DT-data in generic manner, we convert the compatible strings of the panel + * nodes from "panel-foo" to "omapdss,panel-foo". This way we can have both + * correct DT data and omapdss specific drivers. + * + * When we get generic panel drivers to the kernel, this will be removed. + */ +void __init omapdss_early_init_of(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dss_compat_conv_list); ++i) { + const char *compat = dss_compat_conv_list[i]; + struct device_node *node = NULL; + + while ((node = of_find_compatible_node(node, NULL, compat))) { + if (!of_device_is_available(node)) + continue; + + omapdss_omapify_node(node, compat); + } + } +} + +struct device_node * __init omapdss_find_dss_of_node(void) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "ti,omap2-dss"); + if (node) + return node; + + node = of_find_compatible_node(NULL, NULL, "ti,omap3-dss"); + if (node) + return node; + + node = of_find_compatible_node(NULL, NULL, "ti,omap4-dss"); + if (node) + return node; + + return NULL; +} + +int __init omapdss_init_of(void) +{ + int r; + enum omapdss_version ver; + struct device_node *node; + struct platform_device *pdev; + + static struct omap_dss_board_info board_data = { + .dsi_enable_pads = omap_dsi_enable_pads, + .dsi_disable_pads = omap_dsi_disable_pads, + .set_min_bus_tput = omap_dss_set_min_bus_tput, + }; + + /* only create dss helper devices if dss is enabled in the .dts */ + + node = omapdss_find_dss_of_node(); + if (!node) + return 0; + + if (!of_device_is_available(node)) + return 0; + + ver = omap_display_get_version(); + + if (ver == OMAPDSS_VER_UNKNOWN) { + pr_err("DSS not supported on this SoC\n"); + return -ENODEV; + } + + pdev = of_find_device_by_node(node); + + if (!pdev) { + pr_err("Unable to find DSS platform device\n"); + return -ENODEV; + } + + r = of_platform_populate(node, NULL, NULL, &pdev->dev); + if (r) { + pr_err("Unable to populate DSS submodule devices\n"); + return r; + } + + board_data.version = ver; + + omap_display_device.dev.platform_data = &board_data; + + r = platform_device_register(&omap_display_device); + if (r < 0) { + pr_err("Unable to register omapdss device\n"); + return r; + } + + /* create DRM device */ + r = omap_init_drm(); + if (r < 0) { + pr_err("Unable to register omapdrm device\n"); + return r; + } + + /* create vrfb device */ + r = omap_init_vrfb(); + if (r < 0) { + pr_err("Unable to register omapvrfb device\n"); + return r; + } + + /* create FB device */ + r = omap_init_fb(); + if (r < 0) { + pr_err("Unable to register omapfb device\n"); + return r; + } + + /* create V4L2 display device */ + r = omap_init_vout(); + if (r < 0) { + pr_err("Unable to register omap_vout device\n"); + return r; + } + + return 0; +} |