1 #include <linux/component.h> 2 #include <linux/export.h> 3 #include <linux/list.h> 4 #include <linux/of_graph.h> 5 #include <drm/drmP.h> 6 #include <drm/drm_bridge.h> 7 #include <drm/drm_crtc.h> 8 #include <drm/drm_encoder.h> 9 #include <drm/drm_panel.h> 10 #include <drm/drm_of.h> 11 12 static void drm_release_of(struct device *dev, void *data) 13 { 14 of_node_put(data); 15 } 16 17 /** 18 * drm_of_crtc_port_mask - find the mask of a registered CRTC by port OF node 19 * @dev: DRM device 20 * @port: port OF node 21 * 22 * Given a port OF node, return the possible mask of the corresponding 23 * CRTC within a device's list of CRTCs. Returns zero if not found. 24 */ 25 uint32_t drm_of_crtc_port_mask(struct drm_device *dev, 26 struct device_node *port) 27 { 28 unsigned int index = 0; 29 struct drm_crtc *tmp; 30 31 drm_for_each_crtc(tmp, dev) { 32 if (tmp->port == port) 33 return 1 << index; 34 35 index++; 36 } 37 38 return 0; 39 } 40 EXPORT_SYMBOL(drm_of_crtc_port_mask); 41 42 /** 43 * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port 44 * @dev: DRM device 45 * @port: encoder port to scan for endpoints 46 * 47 * Scan all endpoints attached to a port, locate their attached CRTCs, 48 * and generate the DRM mask of CRTCs which may be attached to this 49 * encoder. 50 * 51 * See Documentation/devicetree/bindings/graph.txt for the bindings. 52 */ 53 uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 54 struct device_node *port) 55 { 56 struct device_node *remote_port, *ep; 57 uint32_t possible_crtcs = 0; 58 59 for_each_endpoint_of_node(port, ep) { 60 remote_port = of_graph_get_remote_port(ep); 61 if (!remote_port) { 62 of_node_put(ep); 63 return 0; 64 } 65 66 possible_crtcs |= drm_of_crtc_port_mask(dev, remote_port); 67 68 of_node_put(remote_port); 69 } 70 71 return possible_crtcs; 72 } 73 EXPORT_SYMBOL(drm_of_find_possible_crtcs); 74 75 /** 76 * drm_of_component_match_add - Add a component helper OF node match rule 77 * @master: master device 78 * @matchptr: component match pointer 79 * @compare: compare function used for matching component 80 * @node: of_node 81 */ 82 void drm_of_component_match_add(struct device *master, 83 struct component_match **matchptr, 84 int (*compare)(struct device *, void *), 85 struct device_node *node) 86 { 87 of_node_get(node); 88 component_match_add_release(master, matchptr, drm_release_of, 89 compare, node); 90 } 91 EXPORT_SYMBOL_GPL(drm_of_component_match_add); 92 93 /** 94 * drm_of_component_probe - Generic probe function for a component based master 95 * @dev: master device containing the OF node 96 * @compare_of: compare function used for matching components 97 * @master_ops: component master ops to be used 98 * 99 * Parse the platform device OF node and bind all the components associated 100 * with the master. Interface ports are added before the encoders in order to 101 * satisfy their .bind requirements 102 * See Documentation/devicetree/bindings/graph.txt for the bindings. 103 * 104 * Returns zero if successful, or one of the standard error codes if it fails. 105 */ 106 int drm_of_component_probe(struct device *dev, 107 int (*compare_of)(struct device *, void *), 108 const struct component_master_ops *m_ops) 109 { 110 struct device_node *ep, *port, *remote; 111 struct component_match *match = NULL; 112 int i; 113 114 if (!dev->of_node) 115 return -EINVAL; 116 117 /* 118 * Bind the crtc's ports first, so that drm_of_find_possible_crtcs() 119 * called from encoder's .bind callbacks works as expected 120 */ 121 for (i = 0; ; i++) { 122 port = of_parse_phandle(dev->of_node, "ports", i); 123 if (!port) 124 break; 125 126 if (of_device_is_available(port->parent)) 127 drm_of_component_match_add(dev, &match, compare_of, 128 port); 129 130 of_node_put(port); 131 } 132 133 if (i == 0) { 134 dev_err(dev, "missing 'ports' property\n"); 135 return -ENODEV; 136 } 137 138 if (!match) { 139 dev_err(dev, "no available port\n"); 140 return -ENODEV; 141 } 142 143 /* 144 * For bound crtcs, bind the encoders attached to their remote endpoint 145 */ 146 for (i = 0; ; i++) { 147 port = of_parse_phandle(dev->of_node, "ports", i); 148 if (!port) 149 break; 150 151 if (!of_device_is_available(port->parent)) { 152 of_node_put(port); 153 continue; 154 } 155 156 for_each_child_of_node(port, ep) { 157 remote = of_graph_get_remote_port_parent(ep); 158 if (!remote || !of_device_is_available(remote)) { 159 of_node_put(remote); 160 continue; 161 } else if (!of_device_is_available(remote->parent)) { 162 dev_warn(dev, "parent device of %pOF is not available\n", 163 remote); 164 of_node_put(remote); 165 continue; 166 } 167 168 drm_of_component_match_add(dev, &match, compare_of, 169 remote); 170 of_node_put(remote); 171 } 172 of_node_put(port); 173 } 174 175 return component_master_add_with_match(dev, m_ops, match); 176 } 177 EXPORT_SYMBOL(drm_of_component_probe); 178 179 /* 180 * drm_of_encoder_active_endpoint - return the active encoder endpoint 181 * @node: device tree node containing encoder input ports 182 * @encoder: drm_encoder 183 * 184 * Given an encoder device node and a drm_encoder with a connected crtc, 185 * parse the encoder endpoint connecting to the crtc port. 186 */ 187 int drm_of_encoder_active_endpoint(struct device_node *node, 188 struct drm_encoder *encoder, 189 struct of_endpoint *endpoint) 190 { 191 struct device_node *ep; 192 struct drm_crtc *crtc = encoder->crtc; 193 struct device_node *port; 194 int ret; 195 196 if (!node || !crtc) 197 return -EINVAL; 198 199 for_each_endpoint_of_node(node, ep) { 200 port = of_graph_get_remote_port(ep); 201 of_node_put(port); 202 if (port == crtc->port) { 203 ret = of_graph_parse_endpoint(ep, endpoint); 204 of_node_put(ep); 205 return ret; 206 } 207 } 208 209 return -EINVAL; 210 } 211 EXPORT_SYMBOL_GPL(drm_of_encoder_active_endpoint); 212 213 /* 214 * drm_of_find_panel_or_bridge - return connected panel or bridge device 215 * @np: device tree node containing encoder output ports 216 * @panel: pointer to hold returned drm_panel 217 * @bridge: pointer to hold returned drm_bridge 218 * 219 * Given a DT node's port and endpoint number, find the connected node and 220 * return either the associated struct drm_panel or drm_bridge device. Either 221 * @panel or @bridge must not be NULL. 222 * 223 * Returns zero if successful, or one of the standard error codes if it fails. 224 */ 225 int drm_of_find_panel_or_bridge(const struct device_node *np, 226 int port, int endpoint, 227 struct drm_panel **panel, 228 struct drm_bridge **bridge) 229 { 230 int ret = -EPROBE_DEFER; 231 struct device_node *remote; 232 233 if (!panel && !bridge) 234 return -EINVAL; 235 if (panel) 236 *panel = NULL; 237 238 remote = of_graph_get_remote_node(np, port, endpoint); 239 if (!remote) 240 return -ENODEV; 241 242 if (panel) { 243 *panel = of_drm_find_panel(remote); 244 if (*panel) 245 ret = 0; 246 } 247 248 /* No panel found yet, check for a bridge next. */ 249 if (bridge) { 250 if (ret) { 251 *bridge = of_drm_find_bridge(remote); 252 if (*bridge) 253 ret = 0; 254 } else { 255 *bridge = NULL; 256 } 257 258 } 259 260 of_node_put(remote); 261 return ret; 262 } 263 EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); 264