1bb5cdf8dSAndrew F. Davis /* 2bb5cdf8dSAndrew F. Davis * OMAP Display Subsystem Base 3bb5cdf8dSAndrew F. Davis * 4bb5cdf8dSAndrew F. Davis * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ 5bb5cdf8dSAndrew F. Davis * 6bb5cdf8dSAndrew F. Davis * This program is free software; you can redistribute it and/or modify 7bb5cdf8dSAndrew F. Davis * it under the terms of the GNU General Public License version 2 as 8bb5cdf8dSAndrew F. Davis * published by the Free Software Foundation. 9bb5cdf8dSAndrew F. Davis * 10bb5cdf8dSAndrew F. Davis * This program is distributed in the hope that it will be useful, but 11bb5cdf8dSAndrew F. Davis * WITHOUT ANY WARRANTY; without even the implied warranty of 12bb5cdf8dSAndrew F. Davis * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13bb5cdf8dSAndrew F. Davis * General Public License for more details. 14bb5cdf8dSAndrew F. Davis */ 15bb5cdf8dSAndrew F. Davis 16a99ac0d9STomi Valkeinen #include <linux/kernel.h> 176a7c5a22SLaurent Pinchart #include <linux/list.h> 18a99ac0d9STomi Valkeinen #include <linux/module.h> 196a7c5a22SLaurent Pinchart #include <linux/mutex.h> 201e08c822SPeter Ujfalusi #include <linux/of.h> 211e08c822SPeter Ujfalusi #include <linux/of_graph.h> 2279107f27SLaurent Pinchart #include <linux/platform_device.h> 23d3541ca8SLaurent Pinchart 24d3541ca8SLaurent Pinchart #include "dss.h" 251e08c822SPeter Ujfalusi #include "omapdss.h" 26a99ac0d9STomi Valkeinen 2772877cf3SLaurent Pinchart static struct dss_device *dss_device; 287c299716STomi Valkeinen 2972877cf3SLaurent Pinchart struct dss_device *omapdss_get_dss(void) 307c299716STomi Valkeinen { 3172877cf3SLaurent Pinchart return dss_device; 327c299716STomi Valkeinen } 3372877cf3SLaurent Pinchart EXPORT_SYMBOL(omapdss_get_dss); 347c299716STomi Valkeinen 3572877cf3SLaurent Pinchart void omapdss_set_dss(struct dss_device *dss) 367c299716STomi Valkeinen { 3772877cf3SLaurent Pinchart dss_device = dss; 387c299716STomi Valkeinen } 3972877cf3SLaurent Pinchart EXPORT_SYMBOL(omapdss_set_dss); 407c299716STomi Valkeinen 4150638ae5SLaurent Pinchart struct dispc_device *dispc_get_dispc(struct dss_device *dss) 4250638ae5SLaurent Pinchart { 4350638ae5SLaurent Pinchart return dss->dispc; 4450638ae5SLaurent Pinchart } 4550638ae5SLaurent Pinchart EXPORT_SYMBOL(dispc_get_dispc); 4650638ae5SLaurent Pinchart 47d3541ca8SLaurent Pinchart const struct dispc_ops *dispc_get_ops(struct dss_device *dss) 488a13398cSTomi Valkeinen { 49d3541ca8SLaurent Pinchart return dss->dispc_ops; 508a13398cSTomi Valkeinen } 518a13398cSTomi Valkeinen EXPORT_SYMBOL(dispc_get_ops); 528a13398cSTomi Valkeinen 536a7c5a22SLaurent Pinchart 546a7c5a22SLaurent Pinchart /* ----------------------------------------------------------------------------- 556a7c5a22SLaurent Pinchart * OMAP DSS Devices Handling 566a7c5a22SLaurent Pinchart */ 576a7c5a22SLaurent Pinchart 586a7c5a22SLaurent Pinchart static LIST_HEAD(omapdss_devices_list); 596a7c5a22SLaurent Pinchart static DEFINE_MUTEX(omapdss_devices_lock); 606a7c5a22SLaurent Pinchart 616a7c5a22SLaurent Pinchart void omapdss_device_register(struct omap_dss_device *dssdev) 626a7c5a22SLaurent Pinchart { 636a7c5a22SLaurent Pinchart mutex_lock(&omapdss_devices_lock); 646a7c5a22SLaurent Pinchart list_add_tail(&dssdev->list, &omapdss_devices_list); 656a7c5a22SLaurent Pinchart mutex_unlock(&omapdss_devices_lock); 666a7c5a22SLaurent Pinchart } 67de57e9dbSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_register); 686a7c5a22SLaurent Pinchart 696a7c5a22SLaurent Pinchart void omapdss_device_unregister(struct omap_dss_device *dssdev) 706a7c5a22SLaurent Pinchart { 716a7c5a22SLaurent Pinchart mutex_lock(&omapdss_devices_lock); 726a7c5a22SLaurent Pinchart list_del(&dssdev->list); 736a7c5a22SLaurent Pinchart mutex_unlock(&omapdss_devices_lock); 746a7c5a22SLaurent Pinchart } 75de57e9dbSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_unregister); 766a7c5a22SLaurent Pinchart 779184f8d9SLaurent Pinchart static bool omapdss_device_is_registered(struct device_node *node) 789184f8d9SLaurent Pinchart { 799184f8d9SLaurent Pinchart struct omap_dss_device *dssdev; 809184f8d9SLaurent Pinchart bool found = false; 819184f8d9SLaurent Pinchart 829184f8d9SLaurent Pinchart mutex_lock(&omapdss_devices_lock); 839184f8d9SLaurent Pinchart 849184f8d9SLaurent Pinchart list_for_each_entry(dssdev, &omapdss_devices_list, list) { 859184f8d9SLaurent Pinchart if (dssdev->dev->of_node == node) { 869184f8d9SLaurent Pinchart found = true; 879184f8d9SLaurent Pinchart break; 889184f8d9SLaurent Pinchart } 899184f8d9SLaurent Pinchart } 909184f8d9SLaurent Pinchart 919184f8d9SLaurent Pinchart mutex_unlock(&omapdss_devices_lock); 929184f8d9SLaurent Pinchart return found; 939184f8d9SLaurent Pinchart } 949184f8d9SLaurent Pinchart 95c1dfe721SLaurent Pinchart struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev) 96c1dfe721SLaurent Pinchart { 97c1dfe721SLaurent Pinchart if (!try_module_get(dssdev->owner)) 98c1dfe721SLaurent Pinchart return NULL; 99c1dfe721SLaurent Pinchart 100c1dfe721SLaurent Pinchart if (get_device(dssdev->dev) == NULL) { 101c1dfe721SLaurent Pinchart module_put(dssdev->owner); 102c1dfe721SLaurent Pinchart return NULL; 103c1dfe721SLaurent Pinchart } 104c1dfe721SLaurent Pinchart 105c1dfe721SLaurent Pinchart return dssdev; 106c1dfe721SLaurent Pinchart } 107c1dfe721SLaurent Pinchart EXPORT_SYMBOL(omapdss_device_get); 108c1dfe721SLaurent Pinchart 109c1dfe721SLaurent Pinchart void omapdss_device_put(struct omap_dss_device *dssdev) 110c1dfe721SLaurent Pinchart { 111c1dfe721SLaurent Pinchart put_device(dssdev->dev); 112c1dfe721SLaurent Pinchart module_put(dssdev->owner); 113c1dfe721SLaurent Pinchart } 114c1dfe721SLaurent Pinchart EXPORT_SYMBOL(omapdss_device_put); 115c1dfe721SLaurent Pinchart 116ce69aac8SLaurent Pinchart struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node) 117e10bd354SLaurent Pinchart { 118e10bd354SLaurent Pinchart struct omap_dss_device *dssdev; 119e10bd354SLaurent Pinchart 120e10bd354SLaurent Pinchart list_for_each_entry(dssdev, &omapdss_devices_list, list) { 121ce69aac8SLaurent Pinchart if (dssdev->dev->of_node == node) 122c1dfe721SLaurent Pinchart return omapdss_device_get(dssdev); 123e10bd354SLaurent Pinchart } 124e10bd354SLaurent Pinchart 125e10bd354SLaurent Pinchart return NULL; 126e10bd354SLaurent Pinchart } 127e10bd354SLaurent Pinchart 128b9f4d2ebSLaurent Pinchart /* 12919b4200dSLaurent Pinchart * Search for the next output device starting at @from. Release the reference to 13019b4200dSLaurent Pinchart * the @from device, and acquire a reference to the returned device if found. 131b9f4d2ebSLaurent Pinchart */ 13219b4200dSLaurent Pinchart struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from) 133b9f4d2ebSLaurent Pinchart { 134b9f4d2ebSLaurent Pinchart struct omap_dss_device *dssdev; 135b9f4d2ebSLaurent Pinchart struct list_head *list; 136b9f4d2ebSLaurent Pinchart 137b9f4d2ebSLaurent Pinchart mutex_lock(&omapdss_devices_lock); 138b9f4d2ebSLaurent Pinchart 139b9f4d2ebSLaurent Pinchart if (list_empty(&omapdss_devices_list)) { 140b9f4d2ebSLaurent Pinchart dssdev = NULL; 141b9f4d2ebSLaurent Pinchart goto done; 142b9f4d2ebSLaurent Pinchart } 143b9f4d2ebSLaurent Pinchart 144b9f4d2ebSLaurent Pinchart /* 145b9f4d2ebSLaurent Pinchart * Start from the from entry if given or from omapdss_devices_list 146b9f4d2ebSLaurent Pinchart * otherwise. 147b9f4d2ebSLaurent Pinchart */ 148b9f4d2ebSLaurent Pinchart list = from ? &from->list : &omapdss_devices_list; 149b9f4d2ebSLaurent Pinchart 150b9f4d2ebSLaurent Pinchart list_for_each_entry(dssdev, list, list) { 151b9f4d2ebSLaurent Pinchart /* 152b9f4d2ebSLaurent Pinchart * Stop if we reach the omapdss_devices_list, that's the end of 153b9f4d2ebSLaurent Pinchart * the list. 154b9f4d2ebSLaurent Pinchart */ 155b9f4d2ebSLaurent Pinchart if (&dssdev->list == &omapdss_devices_list) { 156b9f4d2ebSLaurent Pinchart dssdev = NULL; 157b9f4d2ebSLaurent Pinchart goto done; 158b9f4d2ebSLaurent Pinchart } 159b9f4d2ebSLaurent Pinchart 16030b71761SLaurent Pinchart if (dssdev->id && 16130b71761SLaurent Pinchart (dssdev->next || dssdev->bridge || dssdev->panel)) 162b9f4d2ebSLaurent Pinchart goto done; 163b9f4d2ebSLaurent Pinchart } 164b9f4d2ebSLaurent Pinchart 165b9f4d2ebSLaurent Pinchart dssdev = NULL; 166b9f4d2ebSLaurent Pinchart 167b9f4d2ebSLaurent Pinchart done: 168b9f4d2ebSLaurent Pinchart if (from) 169c1dfe721SLaurent Pinchart omapdss_device_put(from); 170b9f4d2ebSLaurent Pinchart if (dssdev) 171c1dfe721SLaurent Pinchart omapdss_device_get(dssdev); 172b9f4d2ebSLaurent Pinchart 173b9f4d2ebSLaurent Pinchart mutex_unlock(&omapdss_devices_lock); 174b9f4d2ebSLaurent Pinchart return dssdev; 175b9f4d2ebSLaurent Pinchart } 17619b4200dSLaurent Pinchart EXPORT_SYMBOL(omapdss_device_next_output); 177b9f4d2ebSLaurent Pinchart 178b49a2139SLaurent Pinchart static bool omapdss_device_is_connected(struct omap_dss_device *dssdev) 179b49a2139SLaurent Pinchart { 180df6682b4SLaurent Pinchart return dssdev->dss; 181b49a2139SLaurent Pinchart } 182b49a2139SLaurent Pinchart 183f324b279SLaurent Pinchart int omapdss_device_connect(struct dss_device *dss, 184f324b279SLaurent Pinchart struct omap_dss_device *src, 185ec727e3fSLaurent Pinchart struct omap_dss_device *dst) 186ec727e3fSLaurent Pinchart { 187fb557171SLaurent Pinchart int ret; 188fb557171SLaurent Pinchart 18979107f27SLaurent Pinchart dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n", 19079107f27SLaurent Pinchart src ? dev_name(src->dev) : "NULL", 19179107f27SLaurent Pinchart dst ? dev_name(dst->dev) : "NULL"); 19279107f27SLaurent Pinchart 19379107f27SLaurent Pinchart if (!dst) { 19479107f27SLaurent Pinchart /* 19579107f27SLaurent Pinchart * The destination is NULL when the source is connected to a 19630b71761SLaurent Pinchart * bridge or panel instead of a DSS device. Stop here, we will 19730b71761SLaurent Pinchart * attach the bridge or panel later when we will have a DRM 19830b71761SLaurent Pinchart * encoder. 19979107f27SLaurent Pinchart */ 20030b71761SLaurent Pinchart return src && (src->bridge || src->panel) ? 0 : -EINVAL; 20179107f27SLaurent Pinchart } 2021f507968SLaurent Pinchart 203511afb44SLaurent Pinchart if (omapdss_device_is_connected(dst)) 2041f507968SLaurent Pinchart return -EBUSY; 2051f507968SLaurent Pinchart 206511afb44SLaurent Pinchart dst->dss = dss; 207f324b279SLaurent Pinchart 208511afb44SLaurent Pinchart ret = dst->ops->connect(src, dst); 209f324b279SLaurent Pinchart if (ret < 0) { 210511afb44SLaurent Pinchart dst->dss = NULL; 211fb557171SLaurent Pinchart return ret; 212f324b279SLaurent Pinchart } 213fb557171SLaurent Pinchart 214fb557171SLaurent Pinchart return 0; 215ec727e3fSLaurent Pinchart } 216ec727e3fSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_connect); 217ec727e3fSLaurent Pinchart 218ec727e3fSLaurent Pinchart void omapdss_device_disconnect(struct omap_dss_device *src, 219ec727e3fSLaurent Pinchart struct omap_dss_device *dst) 220ec727e3fSLaurent Pinchart { 22179107f27SLaurent Pinchart struct dss_device *dss = src ? src->dss : dst->dss; 22279107f27SLaurent Pinchart 22379107f27SLaurent Pinchart dev_dbg(&dss->pdev->dev, "disconnect(%s, %s)\n", 22479107f27SLaurent Pinchart src ? dev_name(src->dev) : "NULL", 22579107f27SLaurent Pinchart dst ? dev_name(dst->dev) : "NULL"); 22679107f27SLaurent Pinchart 22779107f27SLaurent Pinchart if (!dst) { 22830b71761SLaurent Pinchart WARN_ON(!src->bridge && !src->panel); 22979107f27SLaurent Pinchart return; 23079107f27SLaurent Pinchart } 2311f507968SLaurent Pinchart 232511afb44SLaurent Pinchart if (!dst->id && !omapdss_device_is_connected(dst)) { 2330dbfc396SLaurent Pinchart WARN_ON(!dst->display); 2341f507968SLaurent Pinchart return; 2351f507968SLaurent Pinchart } 2361f507968SLaurent Pinchart 2373be0f15bSLaurent Pinchart WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED); 2383be0f15bSLaurent Pinchart 239511afb44SLaurent Pinchart dst->ops->disconnect(src, dst); 240511afb44SLaurent Pinchart dst->dss = NULL; 241ec727e3fSLaurent Pinchart } 242ec727e3fSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_disconnect); 243ec727e3fSLaurent Pinchart 24419b4200dSLaurent Pinchart void omapdss_device_pre_enable(struct omap_dss_device *dssdev) 24519b4200dSLaurent Pinchart { 24619b4200dSLaurent Pinchart if (!dssdev) 24719b4200dSLaurent Pinchart return; 24819b4200dSLaurent Pinchart 24919b4200dSLaurent Pinchart omapdss_device_pre_enable(dssdev->next); 25019b4200dSLaurent Pinchart 25119b4200dSLaurent Pinchart if (dssdev->ops->pre_enable) 25219b4200dSLaurent Pinchart dssdev->ops->pre_enable(dssdev); 25319b4200dSLaurent Pinchart } 25419b4200dSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_pre_enable); 25519b4200dSLaurent Pinchart 25619b4200dSLaurent Pinchart void omapdss_device_enable(struct omap_dss_device *dssdev) 25719b4200dSLaurent Pinchart { 25819b4200dSLaurent Pinchart if (!dssdev) 25919b4200dSLaurent Pinchart return; 26019b4200dSLaurent Pinchart 26119b4200dSLaurent Pinchart if (dssdev->ops->enable) 26219b4200dSLaurent Pinchart dssdev->ops->enable(dssdev); 26319b4200dSLaurent Pinchart 26419b4200dSLaurent Pinchart omapdss_device_enable(dssdev->next); 26519b4200dSLaurent Pinchart 26619b4200dSLaurent Pinchart dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 26719b4200dSLaurent Pinchart } 26819b4200dSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_enable); 26919b4200dSLaurent Pinchart 27019b4200dSLaurent Pinchart void omapdss_device_disable(struct omap_dss_device *dssdev) 27119b4200dSLaurent Pinchart { 27219b4200dSLaurent Pinchart if (!dssdev) 27319b4200dSLaurent Pinchart return; 27419b4200dSLaurent Pinchart 27519b4200dSLaurent Pinchart omapdss_device_disable(dssdev->next); 27619b4200dSLaurent Pinchart 27719b4200dSLaurent Pinchart if (dssdev->ops->disable) 27819b4200dSLaurent Pinchart dssdev->ops->disable(dssdev); 27919b4200dSLaurent Pinchart } 28019b4200dSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_disable); 28119b4200dSLaurent Pinchart 28219b4200dSLaurent Pinchart void omapdss_device_post_disable(struct omap_dss_device *dssdev) 28319b4200dSLaurent Pinchart { 28419b4200dSLaurent Pinchart if (!dssdev) 28519b4200dSLaurent Pinchart return; 28619b4200dSLaurent Pinchart 28719b4200dSLaurent Pinchart if (dssdev->ops->post_disable) 28819b4200dSLaurent Pinchart dssdev->ops->post_disable(dssdev); 28919b4200dSLaurent Pinchart 29019b4200dSLaurent Pinchart omapdss_device_post_disable(dssdev->next); 29119b4200dSLaurent Pinchart 29219b4200dSLaurent Pinchart dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 29319b4200dSLaurent Pinchart } 29419b4200dSLaurent Pinchart EXPORT_SYMBOL_GPL(omapdss_device_post_disable); 29519b4200dSLaurent Pinchart 2966a7c5a22SLaurent Pinchart /* ----------------------------------------------------------------------------- 2976a7c5a22SLaurent Pinchart * Components Handling 2986a7c5a22SLaurent Pinchart */ 2996a7c5a22SLaurent Pinchart 3006a7c5a22SLaurent Pinchart static struct list_head omapdss_comp_list; 3016a7c5a22SLaurent Pinchart 3026a7c5a22SLaurent Pinchart struct omapdss_comp_node { 3036a7c5a22SLaurent Pinchart struct list_head list; 3046a7c5a22SLaurent Pinchart struct device_node *node; 3056a7c5a22SLaurent Pinchart bool dss_core_component; 306*4e17763cSLaurent Pinchart const char *compat; 3076a7c5a22SLaurent Pinchart }; 3086a7c5a22SLaurent Pinchart 3091e08c822SPeter Ujfalusi static bool omapdss_list_contains(const struct device_node *node) 3101e08c822SPeter Ujfalusi { 3111e08c822SPeter Ujfalusi struct omapdss_comp_node *comp; 3121e08c822SPeter Ujfalusi 3131e08c822SPeter Ujfalusi list_for_each_entry(comp, &omapdss_comp_list, list) { 3141e08c822SPeter Ujfalusi if (comp->node == node) 3151e08c822SPeter Ujfalusi return true; 3161e08c822SPeter Ujfalusi } 3171e08c822SPeter Ujfalusi 3181e08c822SPeter Ujfalusi return false; 3191e08c822SPeter Ujfalusi } 3201e08c822SPeter Ujfalusi 3211e08c822SPeter Ujfalusi static void omapdss_walk_device(struct device *dev, struct device_node *node, 3221e08c822SPeter Ujfalusi bool dss_core) 3231e08c822SPeter Ujfalusi { 324*4e17763cSLaurent Pinchart struct omapdss_comp_node *comp; 3251e08c822SPeter Ujfalusi struct device_node *n; 326*4e17763cSLaurent Pinchart const char *compat; 327*4e17763cSLaurent Pinchart int ret; 3281e08c822SPeter Ujfalusi 329*4e17763cSLaurent Pinchart ret = of_property_read_string(node, "compatible", &compat); 330*4e17763cSLaurent Pinchart if (ret < 0) 331*4e17763cSLaurent Pinchart return; 332*4e17763cSLaurent Pinchart 333*4e17763cSLaurent Pinchart comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL); 3341e08c822SPeter Ujfalusi if (comp) { 3351e08c822SPeter Ujfalusi comp->node = node; 3361e08c822SPeter Ujfalusi comp->dss_core_component = dss_core; 337*4e17763cSLaurent Pinchart comp->compat = compat; 3381e08c822SPeter Ujfalusi list_add(&comp->list, &omapdss_comp_list); 3391e08c822SPeter Ujfalusi } 3401e08c822SPeter Ujfalusi 3411e08c822SPeter Ujfalusi /* 3421e08c822SPeter Ujfalusi * of_graph_get_remote_port_parent() prints an error if there is no 3431e08c822SPeter Ujfalusi * port/ports node. To avoid that, check first that there's the node. 3441e08c822SPeter Ujfalusi */ 3451e08c822SPeter Ujfalusi n = of_get_child_by_name(node, "ports"); 3461e08c822SPeter Ujfalusi if (!n) 3471e08c822SPeter Ujfalusi n = of_get_child_by_name(node, "port"); 3481e08c822SPeter Ujfalusi if (!n) 3491e08c822SPeter Ujfalusi return; 3501e08c822SPeter Ujfalusi 3511e08c822SPeter Ujfalusi of_node_put(n); 3521e08c822SPeter Ujfalusi 3531e08c822SPeter Ujfalusi n = NULL; 3541e08c822SPeter Ujfalusi while ((n = of_graph_get_next_endpoint(node, n)) != NULL) { 3551e08c822SPeter Ujfalusi struct device_node *pn = of_graph_get_remote_port_parent(n); 3561e08c822SPeter Ujfalusi 3571e08c822SPeter Ujfalusi if (!pn) 3581e08c822SPeter Ujfalusi continue; 3591e08c822SPeter Ujfalusi 3601e08c822SPeter Ujfalusi if (!of_device_is_available(pn) || omapdss_list_contains(pn)) { 3611e08c822SPeter Ujfalusi of_node_put(pn); 3621e08c822SPeter Ujfalusi continue; 3631e08c822SPeter Ujfalusi } 3641e08c822SPeter Ujfalusi 3651e08c822SPeter Ujfalusi omapdss_walk_device(dev, pn, false); 3661e08c822SPeter Ujfalusi } 3671e08c822SPeter Ujfalusi } 3681e08c822SPeter Ujfalusi 3691e08c822SPeter Ujfalusi void omapdss_gather_components(struct device *dev) 3701e08c822SPeter Ujfalusi { 3711e08c822SPeter Ujfalusi struct device_node *child; 3721e08c822SPeter Ujfalusi 3731e08c822SPeter Ujfalusi INIT_LIST_HEAD(&omapdss_comp_list); 3741e08c822SPeter Ujfalusi 3751e08c822SPeter Ujfalusi omapdss_walk_device(dev, dev->of_node, true); 3761e08c822SPeter Ujfalusi 377*4e17763cSLaurent Pinchart for_each_available_child_of_node(dev->of_node, child) 3781e08c822SPeter Ujfalusi omapdss_walk_device(dev, child, true); 3791e08c822SPeter Ujfalusi } 3801e08c822SPeter Ujfalusi EXPORT_SYMBOL(omapdss_gather_components); 3811e08c822SPeter Ujfalusi 3821e08c822SPeter Ujfalusi static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp) 3831e08c822SPeter Ujfalusi { 3841e08c822SPeter Ujfalusi if (comp->dss_core_component) 3851e08c822SPeter Ujfalusi return true; 386*4e17763cSLaurent Pinchart if (!strstarts(comp->compat, "omapdss,")) 387*4e17763cSLaurent Pinchart return true; 3889184f8d9SLaurent Pinchart if (omapdss_device_is_registered(comp->node)) 3891e08c822SPeter Ujfalusi return true; 3901e08c822SPeter Ujfalusi 3911e08c822SPeter Ujfalusi return false; 3921e08c822SPeter Ujfalusi } 3931e08c822SPeter Ujfalusi 3941e08c822SPeter Ujfalusi bool omapdss_stack_is_ready(void) 3951e08c822SPeter Ujfalusi { 3961e08c822SPeter Ujfalusi struct omapdss_comp_node *comp; 3971e08c822SPeter Ujfalusi 3981e08c822SPeter Ujfalusi list_for_each_entry(comp, &omapdss_comp_list, list) { 3991e08c822SPeter Ujfalusi if (!omapdss_component_is_loaded(comp)) 4001e08c822SPeter Ujfalusi return false; 4011e08c822SPeter Ujfalusi } 4021e08c822SPeter Ujfalusi 4031e08c822SPeter Ujfalusi return true; 4041e08c822SPeter Ujfalusi } 4051e08c822SPeter Ujfalusi EXPORT_SYMBOL(omapdss_stack_is_ready); 4061e08c822SPeter Ujfalusi 407a99ac0d9STomi Valkeinen MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 408a99ac0d9STomi Valkeinen MODULE_DESCRIPTION("OMAP Display Subsystem Base"); 409a99ac0d9STomi Valkeinen MODULE_LICENSE("GPL v2"); 410