Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'drm-devel' and 'component-for-driver' into armada-drm

+255 -38
+160 -38
drivers/base/component.c
··· 18 18 #include <linux/mutex.h> 19 19 #include <linux/slab.h> 20 20 21 + struct component_match { 22 + size_t alloc; 23 + size_t num; 24 + struct { 25 + void *data; 26 + int (*fn)(struct device *, void *); 27 + } compare[0]; 28 + }; 29 + 21 30 struct master { 22 31 struct list_head node; 23 32 struct list_head components; ··· 34 25 35 26 const struct component_master_ops *ops; 36 27 struct device *dev; 28 + struct component_match *match; 37 29 }; 38 30 39 31 struct component { ··· 79 69 c->master = NULL; 80 70 } 81 71 72 + /* 73 + * Add a component to a master, finding the component via the compare 74 + * function and compare data. This is safe to call for duplicate matches 75 + * and will not result in the same component being added multiple times. 76 + */ 82 77 int component_master_add_child(struct master *master, 83 78 int (*compare)(struct device *, void *), void *compare_data) 84 79 { ··· 91 76 int ret = -ENXIO; 92 77 93 78 list_for_each_entry(c, &component_list, node) { 94 - if (c->master) 79 + if (c->master && c->master != master) 95 80 continue; 96 81 97 82 if (compare(c->dev, compare_data)) { 98 - component_attach_master(master, c); 83 + if (!c->master) 84 + component_attach_master(master, c); 99 85 ret = 0; 100 86 break; 101 87 } ··· 105 89 return ret; 106 90 } 107 91 EXPORT_SYMBOL_GPL(component_master_add_child); 92 + 93 + static int find_components(struct master *master) 94 + { 95 + struct component_match *match = master->match; 96 + size_t i; 97 + int ret = 0; 98 + 99 + if (!match) { 100 + /* 101 + * Search the list of components, looking for components that 102 + * belong to this master, and attach them to the master. 103 + */ 104 + return master->ops->add_components(master->dev, master); 105 + } 106 + 107 + /* 108 + * Scan the array of match functions and attach 109 + * any components which are found to this master. 110 + */ 111 + for (i = 0; i < match->num; i++) { 112 + ret = component_master_add_child(master, 113 + match->compare[i].fn, 114 + match->compare[i].data); 115 + if (ret) 116 + break; 117 + } 118 + return ret; 119 + } 108 120 109 121 /* Detach all attached components from this master */ 110 122 static void master_remove_components(struct master *master) ··· 157 113 static int try_to_bring_up_master(struct master *master, 158 114 struct component *component) 159 115 { 160 - int ret = 0; 116 + int ret; 161 117 162 - if (!master->bound) { 163 - /* 164 - * Search the list of components, looking for components that 165 - * belong to this master, and attach them to the master. 166 - */ 167 - if (master->ops->add_components(master->dev, master)) { 168 - /* Failed to find all components */ 169 - master_remove_components(master); 170 - ret = 0; 171 - goto out; 172 - } 118 + if (master->bound) 119 + return 0; 173 120 174 - if (component && component->master != master) { 175 - master_remove_components(master); 176 - ret = 0; 177 - goto out; 178 - } 179 - 180 - if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) { 181 - ret = -ENOMEM; 182 - goto out; 183 - } 184 - 185 - /* Found all components */ 186 - ret = master->ops->bind(master->dev); 187 - if (ret < 0) { 188 - devres_release_group(master->dev, NULL); 189 - dev_info(master->dev, "master bind failed: %d\n", ret); 190 - master_remove_components(master); 191 - goto out; 192 - } 193 - 194 - master->bound = true; 195 - ret = 1; 121 + /* 122 + * Search the list of components, looking for components that 123 + * belong to this master, and attach them to the master. 124 + */ 125 + if (find_components(master)) { 126 + /* Failed to find all components */ 127 + ret = 0; 128 + goto out; 196 129 } 130 + 131 + if (component && component->master != master) { 132 + ret = 0; 133 + goto out; 134 + } 135 + 136 + if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) { 137 + ret = -ENOMEM; 138 + goto out; 139 + } 140 + 141 + /* Found all components */ 142 + ret = master->ops->bind(master->dev); 143 + if (ret < 0) { 144 + devres_release_group(master->dev, NULL); 145 + dev_info(master->dev, "master bind failed: %d\n", ret); 146 + goto out; 147 + } 148 + 149 + master->bound = true; 150 + return 1; 151 + 197 152 out: 153 + master_remove_components(master); 198 154 199 155 return ret; 200 156 } ··· 224 180 master_remove_components(master); 225 181 } 226 182 227 - int component_master_add(struct device *dev, 228 - const struct component_master_ops *ops) 183 + static size_t component_match_size(size_t num) 184 + { 185 + return offsetof(struct component_match, compare[num]); 186 + } 187 + 188 + static struct component_match *component_match_realloc(struct device *dev, 189 + struct component_match *match, size_t num) 190 + { 191 + struct component_match *new; 192 + 193 + if (match && match->alloc == num) 194 + return match; 195 + 196 + new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL); 197 + if (!new) 198 + return ERR_PTR(-ENOMEM); 199 + 200 + if (match) { 201 + memcpy(new, match, component_match_size(min(match->num, num))); 202 + devm_kfree(dev, match); 203 + } else { 204 + new->num = 0; 205 + } 206 + 207 + new->alloc = num; 208 + 209 + return new; 210 + } 211 + 212 + /* 213 + * Add a component to be matched. 214 + * 215 + * The match array is first created or extended if necessary. 216 + */ 217 + void component_match_add(struct device *dev, struct component_match **matchptr, 218 + int (*compare)(struct device *, void *), void *compare_data) 219 + { 220 + struct component_match *match = *matchptr; 221 + 222 + if (IS_ERR(match)) 223 + return; 224 + 225 + if (!match || match->num == match->alloc) { 226 + size_t new_size = match ? match->alloc + 16 : 15; 227 + 228 + match = component_match_realloc(dev, match, new_size); 229 + 230 + *matchptr = match; 231 + 232 + if (IS_ERR(match)) 233 + return; 234 + } 235 + 236 + match->compare[match->num].fn = compare; 237 + match->compare[match->num].data = compare_data; 238 + match->num++; 239 + } 240 + EXPORT_SYMBOL(component_match_add); 241 + 242 + int component_master_add_with_match(struct device *dev, 243 + const struct component_master_ops *ops, 244 + struct component_match *match) 229 245 { 230 246 struct master *master; 231 247 int ret; 248 + 249 + if (ops->add_components && match) 250 + return -EINVAL; 251 + 252 + if (match) { 253 + /* Reallocate the match array for its true size */ 254 + match = component_match_realloc(dev, match, match->num); 255 + if (IS_ERR(match)) 256 + return PTR_ERR(match); 257 + } 232 258 233 259 master = kzalloc(sizeof(*master), GFP_KERNEL); 234 260 if (!master) ··· 306 192 307 193 master->dev = dev; 308 194 master->ops = ops; 195 + master->match = match; 309 196 INIT_LIST_HEAD(&master->components); 310 197 311 198 /* Add to the list of available masters. */ ··· 323 208 mutex_unlock(&component_mutex); 324 209 325 210 return ret < 0 ? ret : 0; 211 + } 212 + EXPORT_SYMBOL_GPL(component_master_add_with_match); 213 + 214 + int component_master_add(struct device *dev, 215 + const struct component_master_ops *ops) 216 + { 217 + return component_master_add_with_match(dev, ops, NULL); 326 218 } 327 219 EXPORT_SYMBOL_GPL(component_master_add); 328 220
+1
drivers/gpu/drm/Makefile
··· 20 20 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o 21 21 drm-$(CONFIG_PCI) += ati_pcigart.o 22 22 drm-$(CONFIG_DRM_PANEL) += drm_panel.o 23 + drm-$(CONFIG_OF) += drm_of.o 23 24 24 25 drm-usb-y := drm_usb.o 25 26
+67
drivers/gpu/drm/drm_of.c
··· 1 + #include <linux/export.h> 2 + #include <linux/list.h> 3 + #include <linux/of_graph.h> 4 + #include <drm/drmP.h> 5 + #include <drm/drm_crtc.h> 6 + #include <drm/drm_of.h> 7 + 8 + /** 9 + * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node 10 + * @dev: DRM device 11 + * @port: port OF node 12 + * 13 + * Given a port OF node, return the possible mask of the corresponding 14 + * CRTC within a device's list of CRTCs. Returns zero if not found. 15 + */ 16 + static uint32_t drm_crtc_port_mask(struct drm_device *dev, 17 + struct device_node *port) 18 + { 19 + unsigned int index = 0; 20 + struct drm_crtc *tmp; 21 + 22 + list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { 23 + if (tmp->port == port) 24 + return 1 << index; 25 + 26 + index++; 27 + } 28 + 29 + return 0; 30 + } 31 + 32 + /** 33 + * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port 34 + * @dev: DRM device 35 + * @port: encoder port to scan for endpoints 36 + * 37 + * Scan all endpoints attached to a port, locate their attached CRTCs, 38 + * and generate the DRM mask of CRTCs which may be attached to this 39 + * encoder. 40 + * 41 + * See Documentation/devicetree/bindings/graph.txt for the bindings. 42 + */ 43 + uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 44 + struct device_node *port) 45 + { 46 + struct device_node *remote_port, *ep = NULL; 47 + uint32_t possible_crtcs = 0; 48 + 49 + do { 50 + ep = of_graph_get_next_endpoint(port, ep); 51 + if (!ep) 52 + break; 53 + 54 + remote_port = of_graph_get_remote_port(ep); 55 + if (!remote_port) { 56 + of_node_put(ep); 57 + return 0; 58 + } 59 + 60 + possible_crtcs |= drm_crtc_port_mask(dev, remote_port); 61 + 62 + of_node_put(remote_port); 63 + } while (1); 64 + 65 + return possible_crtcs; 66 + } 67 + EXPORT_SYMBOL(drm_of_find_possible_crtcs);
+2
include/drm/drm_crtc.h
··· 41 41 struct drm_object_properties; 42 42 struct drm_file; 43 43 struct drm_clip_rect; 44 + struct device_node; 44 45 45 46 #define DRM_MODE_OBJECT_CRTC 0xcccccccc 46 47 #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 ··· 315 314 */ 316 315 struct drm_crtc { 317 316 struct drm_device *dev; 317 + struct device_node *port; 318 318 struct list_head head; 319 319 320 320 /**
+18
include/drm/drm_of.h
··· 1 + #ifndef __DRM_OF_H__ 2 + #define __DRM_OF_H__ 3 + 4 + struct drm_device; 5 + struct device_node; 6 + 7 + #ifdef CONFIG_OF 8 + extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 9 + struct device_node *port); 10 + #else 11 + static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 12 + struct device_node *port) 13 + { 14 + return 0; 15 + } 16 + #endif 17 + 18 + #endif /* __DRM_OF_H__ */
+7
include/linux/component.h
··· 29 29 int component_master_add_child(struct master *master, 30 30 int (*compare)(struct device *, void *), void *compare_data); 31 31 32 + struct component_match; 33 + 34 + int component_master_add_with_match(struct device *, 35 + const struct component_master_ops *, struct component_match *); 36 + void component_match_add(struct device *, struct component_match **, 37 + int (*compare)(struct device *, void *), void *compare_data); 38 + 32 39 #endif