1
2#include <linux/component.h>
3#include <linux/export.h>
4#include <linux/list.h>
5#include <linux/of_graph.h>
6
7#include <drm/drm_bridge.h>
8#include <drm/drm_crtc.h>
9#include <drm/drm_device.h>
10#include <drm/drm_encoder.h>
11#include <drm/drm_of.h>
12#include <drm/drm_panel.h>
13
14
15
16
17
18
19
20
21static void drm_release_of(struct device *dev, void *data)
22{
23 of_node_put(data);
24}
25
26
27
28
29
30
31
32
33
34uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
35 struct device_node *port)
36{
37 unsigned int index = 0;
38 struct drm_crtc *tmp;
39
40 drm_for_each_crtc(tmp, dev) {
41 if (tmp->port == port)
42 return 1 << index;
43
44 index++;
45 }
46
47 return 0;
48}
49EXPORT_SYMBOL(drm_of_crtc_port_mask);
50
51
52
53
54
55
56
57
58
59
60
61
62uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
63 struct device_node *port)
64{
65 struct device_node *remote_port, *ep;
66 uint32_t possible_crtcs = 0;
67
68 for_each_endpoint_of_node(port, ep) {
69 remote_port = of_graph_get_remote_port(ep);
70 if (!remote_port) {
71 of_node_put(ep);
72 return 0;
73 }
74
75 possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port);
76
77 of_node_put(remote_port);
78 }
79
80 return possible_crtcs;
81}
82EXPORT_SYMBOL(drm_of_find_possible_crtcs);
83
84
85
86
87
88
89
90
91void drm_of_component_match_add(struct device *master,
92 struct component_match **matchptr,
93 int (*compare)(struct device *, void *),
94 struct device_node *node)
95{
96 of_node_get(node);
97 component_match_add_release(master, matchptr, drm_release_of,
98 compare, node);
99}
100EXPORT_SYMBOL_GPL(drm_of_component_match_add);
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115int drm_of_component_probe(struct device *dev,
116 int (*compare_of)(struct device *, void *),
117 const struct component_master_ops *m_ops)
118{
119 struct device_node *ep, *port, *remote;
120 struct component_match *match = NULL;
121 int i;
122
123 if (!dev->of_node)
124 return -EINVAL;
125
126
127
128
129
130 for (i = 0; ; i++) {
131 port = of_parse_phandle(dev->of_node, "ports", i);
132 if (!port)
133 break;
134
135 if (of_device_is_available(port->parent))
136 drm_of_component_match_add(dev, &match, compare_of,
137 port);
138
139 of_node_put(port);
140 }
141
142 if (i == 0) {
143 dev_err(dev, "missing 'ports' property\n");
144 return -ENODEV;
145 }
146
147 if (!match) {
148 dev_err(dev, "no available port\n");
149 return -ENODEV;
150 }
151
152
153
154
155 for (i = 0; ; i++) {
156 port = of_parse_phandle(dev->of_node, "ports", i);
157 if (!port)
158 break;
159
160 if (!of_device_is_available(port->parent)) {
161 of_node_put(port);
162 continue;
163 }
164
165 for_each_child_of_node(port, ep) {
166 remote = of_graph_get_remote_port_parent(ep);
167 if (!remote || !of_device_is_available(remote)) {
168 of_node_put(remote);
169 continue;
170 } else if (!of_device_is_available(remote->parent)) {
171 dev_warn(dev, "parent device of %pOF is not available\n",
172 remote);
173 of_node_put(remote);
174 continue;
175 }
176
177 drm_of_component_match_add(dev, &match, compare_of,
178 remote);
179 of_node_put(remote);
180 }
181 of_node_put(port);
182 }
183
184 return component_master_add_with_match(dev, m_ops, match);
185}
186EXPORT_SYMBOL(drm_of_component_probe);
187
188
189
190
191
192
193
194
195
196int drm_of_encoder_active_endpoint(struct device_node *node,
197 struct drm_encoder *encoder,
198 struct of_endpoint *endpoint)
199{
200 struct device_node *ep;
201 struct drm_crtc *crtc = encoder->crtc;
202 struct device_node *port;
203 int ret;
204
205 if (!node || !crtc)
206 return -EINVAL;
207
208 for_each_endpoint_of_node(node, ep) {
209 port = of_graph_get_remote_port(ep);
210 of_node_put(port);
211 if (port == crtc->port) {
212 ret = of_graph_parse_endpoint(ep, endpoint);
213 of_node_put(ep);
214 return ret;
215 }
216 }
217
218 return -EINVAL;
219}
220EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint);
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236int drm_of_find_panel_or_bridge(const struct device_node *np,
237 int port, int endpoint,
238 struct drm_panel **panel,
239 struct drm_bridge **bridge)
240{
241 int ret = -EPROBE_DEFER;
242 struct device_node *remote;
243
244 if (!panel && !bridge)
245 return -EINVAL;
246 if (panel)
247 *panel = NULL;
248
249
250
251
252
253
254
255 if (!of_graph_is_present(np))
256 return -ENODEV;
257
258 remote = of_graph_get_remote_node(np, port, endpoint);
259 if (!remote)
260 return -ENODEV;
261
262 if (panel) {
263 *panel = of_drm_find_panel(remote);
264 if (!IS_ERR(*panel))
265 ret = 0;
266 else
267 *panel = NULL;
268 }
269
270
271 if (bridge) {
272 if (ret) {
273 *bridge = of_drm_find_bridge(remote);
274 if (*bridge)
275 ret = 0;
276 } else {
277 *bridge = NULL;
278 }
279
280 }
281
282 of_node_put(remote);
283 return ret;
284}
285EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge);
286
287enum drm_of_lvds_pixels {
288 DRM_OF_LVDS_EVEN = BIT(0),
289 DRM_OF_LVDS_ODD = BIT(1),
290};
291
292static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node)
293{
294 bool even_pixels =
295 of_property_read_bool(port_node, "dual-lvds-even-pixels");
296 bool odd_pixels =
297 of_property_read_bool(port_node, "dual-lvds-odd-pixels");
298
299 return (even_pixels ? DRM_OF_LVDS_EVEN : 0) |
300 (odd_pixels ? DRM_OF_LVDS_ODD : 0);
301}
302
303static int drm_of_lvds_get_remote_pixels_type(
304 const struct device_node *port_node)
305{
306 struct device_node *endpoint = NULL;
307 int pixels_type = -EPIPE;
308
309 for_each_child_of_node(port_node, endpoint) {
310 struct device_node *remote_port;
311 int current_pt;
312
313 if (!of_node_name_eq(endpoint, "endpoint"))
314 continue;
315
316 remote_port = of_graph_get_remote_port(endpoint);
317 if (!remote_port) {
318 of_node_put(remote_port);
319 return -EPIPE;
320 }
321
322 current_pt = drm_of_lvds_get_port_pixels_type(remote_port);
323 of_node_put(remote_port);
324 if (pixels_type < 0)
325 pixels_type = current_pt;
326
327
328
329
330
331
332
333
334 if (!current_pt || pixels_type != current_pt)
335 return -EINVAL;
336 }
337
338 return pixels_type;
339}
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1,
372 const struct device_node *port2)
373{
374 int remote_p1_pt, remote_p2_pt;
375
376 if (!port1 || !port2)
377 return -EINVAL;
378
379 remote_p1_pt = drm_of_lvds_get_remote_pixels_type(port1);
380 if (remote_p1_pt < 0)
381 return remote_p1_pt;
382
383 remote_p2_pt = drm_of_lvds_get_remote_pixels_type(port2);
384 if (remote_p2_pt < 0)
385 return remote_p2_pt;
386
387
388
389
390
391
392 if (remote_p1_pt + remote_p2_pt != DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD)
393 return -EINVAL;
394
395 return remote_p1_pt == DRM_OF_LVDS_EVEN ?
396 DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS :
397 DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
398}
399EXPORT_SYMBOL_GPL(drm_of_lvds_get_dual_link_pixel_order);
400