1a99ac0d9STomi Valkeinen #include <linux/kernel.h> 2a99ac0d9STomi Valkeinen #include <linux/module.h> 3*1e08c822SPeter Ujfalusi #include <linux/of.h> 4*1e08c822SPeter Ujfalusi #include <linux/of_graph.h> 5*1e08c822SPeter Ujfalusi #include <linux/list.h> 6*1e08c822SPeter Ujfalusi #include "omapdss.h" 7a99ac0d9STomi Valkeinen 87c299716STomi Valkeinen static bool dss_initialized; 98a13398cSTomi Valkeinen static const struct dispc_ops *ops; 107c299716STomi Valkeinen 11*1e08c822SPeter Ujfalusi static struct list_head omapdss_comp_list; 12*1e08c822SPeter Ujfalusi 13*1e08c822SPeter Ujfalusi struct omapdss_comp_node { 14*1e08c822SPeter Ujfalusi struct list_head list; 15*1e08c822SPeter Ujfalusi struct device_node *node; 16*1e08c822SPeter Ujfalusi bool dss_core_component; 17*1e08c822SPeter Ujfalusi }; 18*1e08c822SPeter Ujfalusi 197c299716STomi Valkeinen void omapdss_set_is_initialized(bool set) 207c299716STomi Valkeinen { 217c299716STomi Valkeinen dss_initialized = set; 227c299716STomi Valkeinen } 237c299716STomi Valkeinen EXPORT_SYMBOL(omapdss_set_is_initialized); 247c299716STomi Valkeinen 257c299716STomi Valkeinen bool omapdss_is_initialized(void) 267c299716STomi Valkeinen { 277c299716STomi Valkeinen return dss_initialized; 287c299716STomi Valkeinen } 297c299716STomi Valkeinen EXPORT_SYMBOL(omapdss_is_initialized); 307c299716STomi Valkeinen 318a13398cSTomi Valkeinen void dispc_set_ops(const struct dispc_ops *o) 328a13398cSTomi Valkeinen { 338a13398cSTomi Valkeinen ops = o; 348a13398cSTomi Valkeinen } 358a13398cSTomi Valkeinen EXPORT_SYMBOL(dispc_set_ops); 368a13398cSTomi Valkeinen 378a13398cSTomi Valkeinen const struct dispc_ops *dispc_get_ops(void) 388a13398cSTomi Valkeinen { 398a13398cSTomi Valkeinen return ops; 408a13398cSTomi Valkeinen } 418a13398cSTomi Valkeinen EXPORT_SYMBOL(dispc_get_ops); 428a13398cSTomi Valkeinen 43*1e08c822SPeter Ujfalusi static bool omapdss_list_contains(const struct device_node *node) 44*1e08c822SPeter Ujfalusi { 45*1e08c822SPeter Ujfalusi struct omapdss_comp_node *comp; 46*1e08c822SPeter Ujfalusi 47*1e08c822SPeter Ujfalusi list_for_each_entry(comp, &omapdss_comp_list, list) { 48*1e08c822SPeter Ujfalusi if (comp->node == node) 49*1e08c822SPeter Ujfalusi return true; 50*1e08c822SPeter Ujfalusi } 51*1e08c822SPeter Ujfalusi 52*1e08c822SPeter Ujfalusi return false; 53*1e08c822SPeter Ujfalusi } 54*1e08c822SPeter Ujfalusi 55*1e08c822SPeter Ujfalusi static void omapdss_walk_device(struct device *dev, struct device_node *node, 56*1e08c822SPeter Ujfalusi bool dss_core) 57*1e08c822SPeter Ujfalusi { 58*1e08c822SPeter Ujfalusi struct device_node *n; 59*1e08c822SPeter Ujfalusi struct omapdss_comp_node *comp = devm_kzalloc(dev, sizeof(*comp), 60*1e08c822SPeter Ujfalusi GFP_KERNEL); 61*1e08c822SPeter Ujfalusi 62*1e08c822SPeter Ujfalusi if (comp) { 63*1e08c822SPeter Ujfalusi comp->node = node; 64*1e08c822SPeter Ujfalusi comp->dss_core_component = dss_core; 65*1e08c822SPeter Ujfalusi list_add(&comp->list, &omapdss_comp_list); 66*1e08c822SPeter Ujfalusi } 67*1e08c822SPeter Ujfalusi 68*1e08c822SPeter Ujfalusi /* 69*1e08c822SPeter Ujfalusi * of_graph_get_remote_port_parent() prints an error if there is no 70*1e08c822SPeter Ujfalusi * port/ports node. To avoid that, check first that there's the node. 71*1e08c822SPeter Ujfalusi */ 72*1e08c822SPeter Ujfalusi n = of_get_child_by_name(node, "ports"); 73*1e08c822SPeter Ujfalusi if (!n) 74*1e08c822SPeter Ujfalusi n = of_get_child_by_name(node, "port"); 75*1e08c822SPeter Ujfalusi if (!n) 76*1e08c822SPeter Ujfalusi return; 77*1e08c822SPeter Ujfalusi 78*1e08c822SPeter Ujfalusi of_node_put(n); 79*1e08c822SPeter Ujfalusi 80*1e08c822SPeter Ujfalusi n = NULL; 81*1e08c822SPeter Ujfalusi while ((n = of_graph_get_next_endpoint(node, n)) != NULL) { 82*1e08c822SPeter Ujfalusi struct device_node *pn = of_graph_get_remote_port_parent(n); 83*1e08c822SPeter Ujfalusi 84*1e08c822SPeter Ujfalusi if (!pn) 85*1e08c822SPeter Ujfalusi continue; 86*1e08c822SPeter Ujfalusi 87*1e08c822SPeter Ujfalusi if (!of_device_is_available(pn) || omapdss_list_contains(pn)) { 88*1e08c822SPeter Ujfalusi of_node_put(pn); 89*1e08c822SPeter Ujfalusi continue; 90*1e08c822SPeter Ujfalusi } 91*1e08c822SPeter Ujfalusi 92*1e08c822SPeter Ujfalusi omapdss_walk_device(dev, pn, false); 93*1e08c822SPeter Ujfalusi } 94*1e08c822SPeter Ujfalusi } 95*1e08c822SPeter Ujfalusi 96*1e08c822SPeter Ujfalusi void omapdss_gather_components(struct device *dev) 97*1e08c822SPeter Ujfalusi { 98*1e08c822SPeter Ujfalusi struct device_node *child; 99*1e08c822SPeter Ujfalusi 100*1e08c822SPeter Ujfalusi INIT_LIST_HEAD(&omapdss_comp_list); 101*1e08c822SPeter Ujfalusi 102*1e08c822SPeter Ujfalusi omapdss_walk_device(dev, dev->of_node, true); 103*1e08c822SPeter Ujfalusi 104*1e08c822SPeter Ujfalusi for_each_available_child_of_node(dev->of_node, child) { 105*1e08c822SPeter Ujfalusi if (!of_find_property(child, "compatible", NULL)) 106*1e08c822SPeter Ujfalusi continue; 107*1e08c822SPeter Ujfalusi 108*1e08c822SPeter Ujfalusi omapdss_walk_device(dev, child, true); 109*1e08c822SPeter Ujfalusi } 110*1e08c822SPeter Ujfalusi } 111*1e08c822SPeter Ujfalusi EXPORT_SYMBOL(omapdss_gather_components); 112*1e08c822SPeter Ujfalusi 113*1e08c822SPeter Ujfalusi static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp) 114*1e08c822SPeter Ujfalusi { 115*1e08c822SPeter Ujfalusi if (comp->dss_core_component) 116*1e08c822SPeter Ujfalusi return true; 117*1e08c822SPeter Ujfalusi if (omapdss_component_is_display(comp->node)) 118*1e08c822SPeter Ujfalusi return true; 119*1e08c822SPeter Ujfalusi if (omapdss_component_is_output(comp->node)) 120*1e08c822SPeter Ujfalusi return true; 121*1e08c822SPeter Ujfalusi 122*1e08c822SPeter Ujfalusi return false; 123*1e08c822SPeter Ujfalusi } 124*1e08c822SPeter Ujfalusi 125*1e08c822SPeter Ujfalusi bool omapdss_stack_is_ready(void) 126*1e08c822SPeter Ujfalusi { 127*1e08c822SPeter Ujfalusi struct omapdss_comp_node *comp; 128*1e08c822SPeter Ujfalusi 129*1e08c822SPeter Ujfalusi list_for_each_entry(comp, &omapdss_comp_list, list) { 130*1e08c822SPeter Ujfalusi if (!omapdss_component_is_loaded(comp)) 131*1e08c822SPeter Ujfalusi return false; 132*1e08c822SPeter Ujfalusi } 133*1e08c822SPeter Ujfalusi 134*1e08c822SPeter Ujfalusi return true; 135*1e08c822SPeter Ujfalusi } 136*1e08c822SPeter Ujfalusi EXPORT_SYMBOL(omapdss_stack_is_ready); 137*1e08c822SPeter Ujfalusi 138a99ac0d9STomi Valkeinen MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 139a99ac0d9STomi Valkeinen MODULE_DESCRIPTION("OMAP Display Subsystem Base"); 140a99ac0d9STomi Valkeinen MODULE_LICENSE("GPL v2"); 141