1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013 Texas Instruments 4 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 5 */ 6 7 #include <linux/device.h> 8 #include <linux/err.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/of_graph.h> 12 #include <linux/seq_file.h> 13 14 #include <video/omapfb_dss.h> 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; 55 } while (!of_node_name_eq(port, "port")); 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; 78 } while (!of_node_name_eq(ep, "endpoint")); 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 124 np = of_graph_get_remote_endpoint(node); 125 if (!np) 126 return NULL; 127 128 np = of_get_next_parent(np); 129 130 return np; 131 } 132 133 struct device_node * 134 omapdss_of_get_first_endpoint(const struct device_node *parent) 135 { 136 struct device_node *port, *ep; 137 138 port = omapdss_of_get_next_port(parent, NULL); 139 140 if (!port) 141 return NULL; 142 143 ep = omapdss_of_get_next_endpoint(port, NULL); 144 145 of_node_put(port); 146 147 return ep; 148 } 149 EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint); 150 151 struct omap_dss_device * 152 omapdss_of_find_source_for_first_ep(struct device_node *node) 153 { 154 struct device_node *ep; 155 struct device_node *src_port; 156 struct omap_dss_device *src; 157 158 ep = omapdss_of_get_first_endpoint(node); 159 if (!ep) 160 return ERR_PTR(-EINVAL); 161 162 src_port = omapdss_of_get_remote_port(ep); 163 if (!src_port) { 164 of_node_put(ep); 165 return ERR_PTR(-EINVAL); 166 } 167 168 of_node_put(ep); 169 170 src = omap_dss_find_output_by_port_node(src_port); 171 172 of_node_put(src_port); 173 174 return src ? src : ERR_PTR(-EPROBE_DEFER); 175 } 176 EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep); 177