···1818#include <linux/mutex.h>1919#include <linux/slab.h>20202121+struct component_match {2222+ size_t alloc;2323+ size_t num;2424+ struct {2525+ void *data;2626+ int (*fn)(struct device *, void *);2727+ } compare[0];2828+};2929+2130struct master {2231 struct list_head node;2332 struct list_head components;···34253526 const struct component_master_ops *ops;3627 struct device *dev;2828+ struct component_match *match;3729};38303931struct component {···7969 c->master = NULL;8070}81717272+/*7373+ * Add a component to a master, finding the component via the compare7474+ * function and compare data. This is safe to call for duplicate matches7575+ * and will not result in the same component being added multiple times.7676+ */8277int component_master_add_child(struct master *master,8378 int (*compare)(struct device *, void *), void *compare_data)8479{···9176 int ret = -ENXIO;92779378 list_for_each_entry(c, &component_list, node) {9494- if (c->master)7979+ if (c->master && c->master != master)9580 continue;96819782 if (compare(c->dev, compare_data)) {9898- component_attach_master(master, c);8383+ if (!c->master)8484+ component_attach_master(master, c);9985 ret = 0;10086 break;10187 }···10589 return ret;10690}10791EXPORT_SYMBOL_GPL(component_master_add_child);9292+9393+static int find_components(struct master *master)9494+{9595+ struct component_match *match = master->match;9696+ size_t i;9797+ int ret = 0;9898+9999+ if (!match) {100100+ /*101101+ * Search the list of components, looking for components that102102+ * belong to this master, and attach them to the master.103103+ */104104+ return master->ops->add_components(master->dev, master);105105+ }106106+107107+ /*108108+ * Scan the array of match functions and attach109109+ * any components which are found to this master.110110+ */111111+ for (i = 0; i < match->num; i++) {112112+ ret = component_master_add_child(master,113113+ match->compare[i].fn,114114+ match->compare[i].data);115115+ if (ret)116116+ break;117117+ }118118+ return ret;119119+}108120109121/* Detach all attached components from this master */110122static void master_remove_components(struct master *master)···157113static int try_to_bring_up_master(struct master *master,158114 struct component *component)159115{160160- int ret = 0;116116+ int ret;161117162162- if (!master->bound) {163163- /*164164- * Search the list of components, looking for components that165165- * belong to this master, and attach them to the master.166166- */167167- if (master->ops->add_components(master->dev, master)) {168168- /* Failed to find all components */169169- master_remove_components(master);170170- ret = 0;171171- goto out;172172- }118118+ if (master->bound)119119+ return 0;173120174174- if (component && component->master != master) {175175- master_remove_components(master);176176- ret = 0;177177- goto out;178178- }179179-180180- if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {181181- ret = -ENOMEM;182182- goto out;183183- }184184-185185- /* Found all components */186186- ret = master->ops->bind(master->dev);187187- if (ret < 0) {188188- devres_release_group(master->dev, NULL);189189- dev_info(master->dev, "master bind failed: %d\n", ret);190190- master_remove_components(master);191191- goto out;192192- }193193-194194- master->bound = true;195195- ret = 1;121121+ /*122122+ * Search the list of components, looking for components that123123+ * belong to this master, and attach them to the master.124124+ */125125+ if (find_components(master)) {126126+ /* Failed to find all components */127127+ ret = 0;128128+ goto out;196129 }130130+131131+ if (component && component->master != master) {132132+ ret = 0;133133+ goto out;134134+ }135135+136136+ if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {137137+ ret = -ENOMEM;138138+ goto out;139139+ }140140+141141+ /* Found all components */142142+ ret = master->ops->bind(master->dev);143143+ if (ret < 0) {144144+ devres_release_group(master->dev, NULL);145145+ dev_info(master->dev, "master bind failed: %d\n", ret);146146+ goto out;147147+ }148148+149149+ master->bound = true;150150+ return 1;151151+197152out:153153+ master_remove_components(master);198154199155 return ret;200156}···224180 master_remove_components(master);225181}226182227227-int component_master_add(struct device *dev,228228- const struct component_master_ops *ops)183183+static size_t component_match_size(size_t num)184184+{185185+ return offsetof(struct component_match, compare[num]);186186+}187187+188188+static struct component_match *component_match_realloc(struct device *dev,189189+ struct component_match *match, size_t num)190190+{191191+ struct component_match *new;192192+193193+ if (match && match->alloc == num)194194+ return match;195195+196196+ new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);197197+ if (!new)198198+ return ERR_PTR(-ENOMEM);199199+200200+ if (match) {201201+ memcpy(new, match, component_match_size(min(match->num, num)));202202+ devm_kfree(dev, match);203203+ } else {204204+ new->num = 0;205205+ }206206+207207+ new->alloc = num;208208+209209+ return new;210210+}211211+212212+/*213213+ * Add a component to be matched.214214+ *215215+ * The match array is first created or extended if necessary.216216+ */217217+void component_match_add(struct device *dev, struct component_match **matchptr,218218+ int (*compare)(struct device *, void *), void *compare_data)219219+{220220+ struct component_match *match = *matchptr;221221+222222+ if (IS_ERR(match))223223+ return;224224+225225+ if (!match || match->num == match->alloc) {226226+ size_t new_size = match ? match->alloc + 16 : 15;227227+228228+ match = component_match_realloc(dev, match, new_size);229229+230230+ *matchptr = match;231231+232232+ if (IS_ERR(match))233233+ return;234234+ }235235+236236+ match->compare[match->num].fn = compare;237237+ match->compare[match->num].data = compare_data;238238+ match->num++;239239+}240240+EXPORT_SYMBOL(component_match_add);241241+242242+int component_master_add_with_match(struct device *dev,243243+ const struct component_master_ops *ops,244244+ struct component_match *match)229245{230246 struct master *master;231247 int ret;248248+249249+ if (ops->add_components && match)250250+ return -EINVAL;251251+252252+ if (match) {253253+ /* Reallocate the match array for its true size */254254+ match = component_match_realloc(dev, match, match->num);255255+ if (IS_ERR(match))256256+ return PTR_ERR(match);257257+ }232258233259 master = kzalloc(sizeof(*master), GFP_KERNEL);234260 if (!master)···306192307193 master->dev = dev;308194 master->ops = ops;195195+ master->match = match;309196 INIT_LIST_HEAD(&master->components);310197311198 /* Add to the list of available masters. */···323208 mutex_unlock(&component_mutex);324209325210 return ret < 0 ? ret : 0;211211+}212212+EXPORT_SYMBOL_GPL(component_master_add_with_match);213213+214214+int component_master_add(struct device *dev,215215+ const struct component_master_ops *ops)216216+{217217+ return component_master_add_with_match(dev, ops, NULL);326218}327219EXPORT_SYMBOL_GPL(component_master_add);328220
···11+#include <linux/export.h>22+#include <linux/list.h>33+#include <linux/of_graph.h>44+#include <drm/drmP.h>55+#include <drm/drm_crtc.h>66+#include <drm/drm_of.h>77+88+/**99+ * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node1010+ * @dev: DRM device1111+ * @port: port OF node1212+ *1313+ * Given a port OF node, return the possible mask of the corresponding1414+ * CRTC within a device's list of CRTCs. Returns zero if not found.1515+ */1616+static uint32_t drm_crtc_port_mask(struct drm_device *dev,1717+ struct device_node *port)1818+{1919+ unsigned int index = 0;2020+ struct drm_crtc *tmp;2121+2222+ list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {2323+ if (tmp->port == port)2424+ return 1 << index;2525+2626+ index++;2727+ }2828+2929+ return 0;3030+}3131+3232+/**3333+ * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port3434+ * @dev: DRM device3535+ * @port: encoder port to scan for endpoints3636+ *3737+ * Scan all endpoints attached to a port, locate their attached CRTCs,3838+ * and generate the DRM mask of CRTCs which may be attached to this3939+ * encoder.4040+ *4141+ * See Documentation/devicetree/bindings/graph.txt for the bindings.4242+ */4343+uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,4444+ struct device_node *port)4545+{4646+ struct device_node *remote_port, *ep = NULL;4747+ uint32_t possible_crtcs = 0;4848+4949+ do {5050+ ep = of_graph_get_next_endpoint(port, ep);5151+ if (!ep)5252+ break;5353+5454+ remote_port = of_graph_get_remote_port(ep);5555+ if (!remote_port) {5656+ of_node_put(ep);5757+ return 0;5858+ }5959+6060+ possible_crtcs |= drm_crtc_port_mask(dev, remote_port);6161+6262+ of_node_put(remote_port);6363+ } while (1);6464+6565+ return possible_crtcs;6666+}6767+EXPORT_SYMBOL(drm_of_find_possible_crtcs);