Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
f76ee892 TV |
2 | /* |
3 | * Copyright (C) 2013 Texas Instruments | |
4 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> | |
f76ee892 TV |
5 | */ |
6 | ||
7 | #include <linux/device.h> | |
8 | #include <linux/err.h> | |
9 | #include <linux/module.h> | |
10 | #include <linux/of.h> | |
5161b96d | 11 | #include <linux/of_graph.h> |
f76ee892 TV |
12 | #include <linux/seq_file.h> |
13 | ||
62d9e44e | 14 | #include <video/omapfb_dss.h> |
f76ee892 TV |
15 | |
16 | #include "dss.h" | |
17 | ||
18 | struct device_node * | |
19 | omapdss_of_get_next_port(const struct device_node *parent, | |
20 | struct device_node *prev) | |
21 | { | |
22 | struct device_node *port = NULL; | |
23 | ||
24 | if (!parent) | |
25 | return NULL; | |
26 | ||
27 | if (!prev) { | |
28 | struct device_node *ports; | |
29 | /* | |
30 | * It's the first call, we have to find a port subnode | |
31 | * within this node or within an optional 'ports' node. | |
32 | */ | |
33 | ports = of_get_child_by_name(parent, "ports"); | |
34 | if (ports) | |
35 | parent = ports; | |
36 | ||
37 | port = of_get_child_by_name(parent, "port"); | |
38 | ||
39 | /* release the 'ports' node */ | |
40 | of_node_put(ports); | |
41 | } else { | |
42 | struct device_node *ports; | |
43 | ||
44 | ports = of_get_parent(prev); | |
45 | if (!ports) | |
46 | return NULL; | |
47 | ||
48 | do { | |
49 | port = of_get_next_child(ports, prev); | |
50 | if (!port) { | |
51 | of_node_put(ports); | |
52 | return NULL; | |
53 | } | |
54 | prev = port; | |
a6f13af4 | 55 | } while (!of_node_name_eq(port, "port")); |
f76ee892 TV |
56 | |
57 | of_node_put(ports); | |
58 | } | |
59 | ||
60 | return port; | |
61 | } | |
62 | EXPORT_SYMBOL_GPL(omapdss_of_get_next_port); | |
63 | ||
64 | struct device_node * | |
65 | omapdss_of_get_next_endpoint(const struct device_node *parent, | |
66 | struct device_node *prev) | |
67 | { | |
68 | struct device_node *ep = NULL; | |
69 | ||
70 | if (!parent) | |
71 | return NULL; | |
72 | ||
73 | do { | |
74 | ep = of_get_next_child(parent, prev); | |
75 | if (!ep) | |
76 | return NULL; | |
77 | prev = ep; | |
a6f13af4 | 78 | } while (!of_node_name_eq(ep, "endpoint")); |
f76ee892 TV |
79 | |
80 | return ep; | |
81 | } | |
82 | EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); | |
83 | ||
84 | struct device_node *dss_of_port_get_parent_device(struct device_node *port) | |
85 | { | |
86 | struct device_node *np; | |
87 | int i; | |
88 | ||
89 | if (!port) | |
90 | return NULL; | |
91 | ||
92 | np = of_get_parent(port); | |
93 | ||
94 | for (i = 0; i < 2 && np; ++i) { | |
95 | struct property *prop; | |
96 | ||
97 | prop = of_find_property(np, "compatible", NULL); | |
98 | ||
99 | if (prop) | |
100 | return np; | |
101 | ||
102 | np = of_get_next_parent(np); | |
103 | } | |
104 | ||
105 | return NULL; | |
106 | } | |
107 | ||
108 | u32 dss_of_port_get_port_number(struct device_node *port) | |
109 | { | |
110 | int r; | |
111 | u32 reg; | |
112 | ||
113 | r = of_property_read_u32(port, "reg", ®); | |
114 | if (r) | |
115 | reg = 0; | |
116 | ||
117 | return reg; | |
118 | } | |
119 | ||
120 | static struct device_node *omapdss_of_get_remote_port(const struct device_node *node) | |
121 | { | |
122 | struct device_node *np; | |
123 | ||
5161b96d | 124 | np = of_graph_get_remote_endpoint(node); |
f76ee892 TV |
125 | if (!np) |
126 | return NULL; | |
127 | ||
128 | np = of_get_next_parent(np); | |
129 | ||
130 | return np; | |
131 | } | |
132 | ||
f76ee892 TV |
133 | struct omap_dss_device * |
134 | omapdss_of_find_source_for_first_ep(struct device_node *node) | |
135 | { | |
136 | struct device_node *ep; | |
137 | struct device_node *src_port; | |
138 | struct omap_dss_device *src; | |
139 | ||
ada5caa4 | 140 | ep = of_graph_get_endpoint_by_regs(node, 0, -1); |
f76ee892 TV |
141 | if (!ep) |
142 | return ERR_PTR(-EINVAL); | |
143 | ||
144 | src_port = omapdss_of_get_remote_port(ep); | |
145 | if (!src_port) { | |
146 | of_node_put(ep); | |
147 | return ERR_PTR(-EINVAL); | |
148 | } | |
149 | ||
150 | of_node_put(ep); | |
151 | ||
152 | src = omap_dss_find_output_by_port_node(src_port); | |
153 | ||
154 | of_node_put(src_port); | |
155 | ||
156 | return src ? src : ERR_PTR(-EPROBE_DEFER); | |
157 | } | |
158 | EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep); |