xref: /openbmc/linux/drivers/gpu/drm/omapdrm/dss/base.c (revision 1e08c822689c39bd86d2154490f89265329e9c58)
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