aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2016-05-03 15:07:10 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2017-04-03 05:36:40 -0400
commit1e08c822689c39bd86d2154490f89265329e9c58 (patch)
tree7508b57dbaec612b285135fb37ae8c66c08d1899
parent7c79e8d67fde332f1cda26c8a0845fa167815351 (diff)
drm/omap: dss: Support for detecting display stack readiness
When omapdss is loaded (all core components are in place) create a list of devices used in the display graph. This list later can be used by omapdrm via the omapdss_stack_is_ready() function to check that these components are loaded. Based on this information, omapdrm can defer probe in case when the omapdss stack is not ready yet. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/gpu/drm/omapdrm/dss/base.c107
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/omapdss.h3
3 files changed, 111 insertions, 0 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
index 7dd447e6c4d7..13e91faaf7a6 100644
--- a/drivers/gpu/drm/omapdrm/dss/base.c
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
@@ -1,9 +1,21 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/module.h> 2#include <linux/module.h>
3#include <linux/of.h>
4#include <linux/of_graph.h>
5#include <linux/list.h>
6#include "omapdss.h"
3 7
4static bool dss_initialized; 8static bool dss_initialized;
5static const struct dispc_ops *ops; 9static const struct dispc_ops *ops;
6 10
11static struct list_head omapdss_comp_list;
12
13struct omapdss_comp_node {
14 struct list_head list;
15 struct device_node *node;
16 bool dss_core_component;
17};
18
7void omapdss_set_is_initialized(bool set) 19void omapdss_set_is_initialized(bool set)
8{ 20{
9 dss_initialized = set; 21 dss_initialized = set;
@@ -28,6 +40,101 @@ const struct dispc_ops *dispc_get_ops(void)
28} 40}
29EXPORT_SYMBOL(dispc_get_ops); 41EXPORT_SYMBOL(dispc_get_ops);
30 42
43static bool omapdss_list_contains(const struct device_node *node)
44{
45 struct omapdss_comp_node *comp;
46
47 list_for_each_entry(comp, &omapdss_comp_list, list) {
48 if (comp->node == node)
49 return true;
50 }
51
52 return false;
53}
54
55static void omapdss_walk_device(struct device *dev, struct device_node *node,
56 bool dss_core)
57{
58 struct device_node *n;
59 struct omapdss_comp_node *comp = devm_kzalloc(dev, sizeof(*comp),
60 GFP_KERNEL);
61
62 if (comp) {
63 comp->node = node;
64 comp->dss_core_component = dss_core;
65 list_add(&comp->list, &omapdss_comp_list);
66 }
67
68 /*
69 * of_graph_get_remote_port_parent() prints an error if there is no
70 * port/ports node. To avoid that, check first that there's the node.
71 */
72 n = of_get_child_by_name(node, "ports");
73 if (!n)
74 n = of_get_child_by_name(node, "port");
75 if (!n)
76 return;
77
78 of_node_put(n);
79
80 n = NULL;
81 while ((n = of_graph_get_next_endpoint(node, n)) != NULL) {
82 struct device_node *pn = of_graph_get_remote_port_parent(n);
83
84 if (!pn)
85 continue;
86
87 if (!of_device_is_available(pn) || omapdss_list_contains(pn)) {
88 of_node_put(pn);
89 continue;
90 }
91
92 omapdss_walk_device(dev, pn, false);
93 }
94}
95
96void omapdss_gather_components(struct device *dev)
97{
98 struct device_node *child;
99
100 INIT_LIST_HEAD(&omapdss_comp_list);
101
102 omapdss_walk_device(dev, dev->of_node, true);
103
104 for_each_available_child_of_node(dev->of_node, child) {
105 if (!of_find_property(child, "compatible", NULL))
106 continue;
107
108 omapdss_walk_device(dev, child, true);
109 }
110}
111EXPORT_SYMBOL(omapdss_gather_components);
112
113static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp)
114{
115 if (comp->dss_core_component)
116 return true;
117 if (omapdss_component_is_display(comp->node))
118 return true;
119 if (omapdss_component_is_output(comp->node))
120 return true;
121
122 return false;
123}
124
125bool omapdss_stack_is_ready(void)
126{
127 struct omapdss_comp_node *comp;
128
129 list_for_each_entry(comp, &omapdss_comp_list, list) {
130 if (!omapdss_component_is_loaded(comp))
131 return false;
132 }
133
134 return true;
135}
136EXPORT_SYMBOL(omapdss_stack_is_ready);
137
31MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 138MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
32MODULE_DESCRIPTION("OMAP Display Subsystem Base"); 139MODULE_DESCRIPTION("OMAP Display Subsystem Base");
33MODULE_LICENSE("GPL v2"); 140MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 5eb2f1260547..ceb483650f8c 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1258,6 +1258,7 @@ static int dss_bind(struct device *dev)
1258 1258
1259 pm_set_vt_switch(0); 1259 pm_set_vt_switch(0);
1260 1260
1261 omapdss_gather_components(dev);
1261 omapdss_set_is_initialized(true); 1262 omapdss_set_is_initialized(true);
1262 1263
1263 return 0; 1264 return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 7e1feb935137..d5c369bd565c 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -939,4 +939,7 @@ const struct dispc_ops *dispc_get_ops(void);
939bool omapdss_component_is_display(struct device_node *node); 939bool omapdss_component_is_display(struct device_node *node);
940bool omapdss_component_is_output(struct device_node *node); 940bool omapdss_component_is_output(struct device_node *node);
941 941
942bool omapdss_stack_is_ready(void);
943void omapdss_gather_components(struct device *dev);
944
942#endif /* __OMAP_DRM_DSS_H */ 945#endif /* __OMAP_DRM_DSS_H */