aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/component.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2019-02-07 18:27:57 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2019-02-08 10:58:03 -0500
commit3521ee994bca90c57b539e106ff7e12a839aa8ea (patch)
tree0153e5c92433680a59b3207b4a0c2f786bfce3e2 /drivers/base/component.c
parent4d69c80e0d0fd8cf12d985841eb0fce5c29819ad (diff)
components: multiple components for a device
Component framework is extended to support multiple components for a struct device. These will be matched with different masters based on its sub component value. We are introducing this, as I915 needs two different components with different subcomponent value, which will be matched to two different component masters(Audio and HDCP) based on the subcomponent values. v2: Add documenation. v3: Rebase on top of updated documenation. v4: Review from Rafael: - Remove redundant "This" from kerneldoc (also in the previous patch) - Streamline the logic in find_component() a bit. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v1 code) Signed-off-by: Ramalingam C <ramalingam.c@intel.com> (v1 commit message) Cc: Ramalingam C <ramalingam.c@intel.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Rafael J. Wysocki <rafael@kernel.org> Cc: Jaroslav Kysela <perex@perex.cz> Cc: Takashi Iwai <tiwai@suse.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20190207232759.14553-2-daniel.vetter@ffwll.ch
Diffstat (limited to 'drivers/base/component.c')
-rw-r--r--drivers/base/component.c158
1 files changed, 121 insertions, 37 deletions
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 1624c2a892a5..7dbc41cccd58 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -47,6 +47,7 @@ struct component;
47struct component_match_array { 47struct component_match_array {
48 void *data; 48 void *data;
49 int (*compare)(struct device *, void *); 49 int (*compare)(struct device *, void *);
50 int (*compare_typed)(struct device *, int, void *);
50 void (*release)(struct device *, void *); 51 void (*release)(struct device *, void *);
51 struct component *component; 52 struct component *component;
52 bool duplicate; 53 bool duplicate;
@@ -74,6 +75,7 @@ struct component {
74 bool bound; 75 bool bound;
75 76
76 const struct component_ops *ops; 77 const struct component_ops *ops;
78 int subcomponent;
77 struct device *dev; 79 struct device *dev;
78}; 80};
79 81
@@ -158,7 +160,7 @@ static struct master *__master_find(struct device *dev,
158} 160}
159 161
160static struct component *find_component(struct master *master, 162static struct component *find_component(struct master *master,
161 int (*compare)(struct device *, void *), void *compare_data) 163 struct component_match_array *mc)
162{ 164{
163 struct component *c; 165 struct component *c;
164 166
@@ -166,7 +168,11 @@ static struct component *find_component(struct master *master,
166 if (c->master && c->master != master) 168 if (c->master && c->master != master)
167 continue; 169 continue;
168 170
169 if (compare(c->dev, compare_data)) 171 if (mc->compare && mc->compare(c->dev, mc->data))
172 return c;
173
174 if (mc->compare_typed &&
175 mc->compare_typed(c->dev, c->subcomponent, mc->data))
170 return c; 176 return c;
171 } 177 }
172 178
@@ -192,7 +198,7 @@ static int find_components(struct master *master)
192 if (match->compare[i].component) 198 if (match->compare[i].component)
193 continue; 199 continue;
194 200
195 c = find_component(master, mc->compare, mc->data); 201 c = find_component(master, mc);
196 if (!c) { 202 if (!c) {
197 ret = -ENXIO; 203 ret = -ENXIO;
198 break; 204 break;
@@ -327,29 +333,12 @@ static int component_match_realloc(struct device *dev,
327 return 0; 333 return 0;
328} 334}
329 335
330/** 336static void __component_match_add(struct device *master,
331 * component_match_add_release - add a component match with release callback
332 * @master: device with the aggregate driver
333 * @matchptr: pointer to the list of component matches
334 * @release: release function for @compare_data
335 * @compare: compare function to match against all components
336 * @compare_data: opaque pointer passed to the @compare function
337 *
338 * Adds a new component match to the list stored in @matchptr, which the @master
339 * aggregate driver needs to function. The list of component matches pointed to
340 * by @matchptr must be initialized to NULL before adding the first match.
341 *
342 * The allocated match list in @matchptr is automatically released using devm
343 * actions, where upon @release will be called to free any references held by
344 * @compare_data, e.g. when @compare_data is a &device_node that must be
345 * released with of_node_put().
346 *
347 * See also component_match_add().
348 */
349void component_match_add_release(struct device *master,
350 struct component_match **matchptr, 337 struct component_match **matchptr,
351 void (*release)(struct device *, void *), 338 void (*release)(struct device *, void *),
352 int (*compare)(struct device *, void *), void *compare_data) 339 int (*compare)(struct device *, void *),
340 int (*compare_typed)(struct device *, int, void *),
341 void *compare_data)
353{ 342{
354 struct component_match *match = *matchptr; 343 struct component_match *match = *matchptr;
355 344
@@ -381,13 +370,69 @@ void component_match_add_release(struct device *master,
381 } 370 }
382 371
383 match->compare[match->num].compare = compare; 372 match->compare[match->num].compare = compare;
373 match->compare[match->num].compare_typed = compare_typed;
384 match->compare[match->num].release = release; 374 match->compare[match->num].release = release;
385 match->compare[match->num].data = compare_data; 375 match->compare[match->num].data = compare_data;
386 match->compare[match->num].component = NULL; 376 match->compare[match->num].component = NULL;
387 match->num++; 377 match->num++;
388} 378}
379
380/**
381 * component_match_add_release - add a component match with release callback
382 * @master: device with the aggregate driver
383 * @matchptr: pointer to the list of component matches
384 * @release: release function for @compare_data
385 * @compare: compare function to match against all components
386 * @compare_data: opaque pointer passed to the @compare function
387 *
388 * Adds a new component match to the list stored in @matchptr, which the @master
389 * aggregate driver needs to function. The list of component matches pointed to
390 * by @matchptr must be initialized to NULL before adding the first match. This
391 * only matches against components added with component_add().
392 *
393 * The allocated match list in @matchptr is automatically released using devm
394 * actions, where upon @release will be called to free any references held by
395 * @compare_data, e.g. when @compare_data is a &device_node that must be
396 * released with of_node_put().
397 *
398 * See also component_match_add() and component_match_add_typed().
399 */
400void component_match_add_release(struct device *master,
401 struct component_match **matchptr,
402 void (*release)(struct device *, void *),
403 int (*compare)(struct device *, void *), void *compare_data)
404{
405 __component_match_add(master, matchptr, release, compare, NULL,
406 compare_data);
407}
389EXPORT_SYMBOL(component_match_add_release); 408EXPORT_SYMBOL(component_match_add_release);
390 409
410/**
411 * component_match_add_typed - add a compent match for a typed component
412 * @master: device with the aggregate driver
413 * @matchptr: pointer to the list of component matches
414 * @compare_typed: compare function to match against all typed components
415 * @compare_data: opaque pointer passed to the @compare function
416 *
417 * Adds a new component match to the list stored in @matchptr, which the @master
418 * aggregate driver needs to function. The list of component matches pointed to
419 * by @matchptr must be initialized to NULL before adding the first match. This
420 * only matches against components added with component_add_typed().
421 *
422 * The allocated match list in @matchptr is automatically released using devm
423 * actions.
424 *
425 * See also component_match_add_release() and component_match_add_typed().
426 */
427void component_match_add_typed(struct device *master,
428 struct component_match **matchptr,
429 int (*compare_typed)(struct device *, int, void *), void *compare_data)
430{
431 __component_match_add(master, matchptr, NULL, NULL, compare_typed,
432 compare_data);
433}
434EXPORT_SYMBOL(component_match_add_typed);
435
391static void free_master(struct master *master) 436static void free_master(struct master *master)
392{ 437{
393 struct component_match *match = master->match; 438 struct component_match *match = master->match;
@@ -616,19 +661,8 @@ int component_bind_all(struct device *master_dev, void *data)
616} 661}
617EXPORT_SYMBOL_GPL(component_bind_all); 662EXPORT_SYMBOL_GPL(component_bind_all);
618 663
619/** 664static int __component_add(struct device *dev, const struct component_ops *ops,
620 * component_add - register a component 665 int subcomponent)
621 * @dev: component device
622 * @ops: component callbacks
623 *
624 * Register a new component for @dev. Functions in @ops will be called when the
625 * aggregate driver is ready to bind the overall driver by calling
626 * component_bind_all(). See also &struct component_ops.
627 *
628 * The component needs to be unregistered at driver unload/disconnect by calling
629 * component_del().
630 */
631int component_add(struct device *dev, const struct component_ops *ops)
632{ 666{
633 struct component *component; 667 struct component *component;
634 int ret; 668 int ret;
@@ -639,6 +673,7 @@ int component_add(struct device *dev, const struct component_ops *ops)
639 673
640 component->ops = ops; 674 component->ops = ops;
641 component->dev = dev; 675 component->dev = dev;
676 component->subcomponent = subcomponent;
642 677
643 dev_dbg(dev, "adding component (ops %ps)\n", ops); 678 dev_dbg(dev, "adding component (ops %ps)\n", ops);
644 679
@@ -657,6 +692,55 @@ int component_add(struct device *dev, const struct component_ops *ops)
657 692
658 return ret < 0 ? ret : 0; 693 return ret < 0 ? ret : 0;
659} 694}
695
696/**
697 * component_add_typed - register a component
698 * @dev: component device
699 * @ops: component callbacks
700 * @subcomponent: nonzero identifier for subcomponents
701 *
702 * Register a new component for @dev. Functions in @ops will be call when the
703 * aggregate driver is ready to bind the overall driver by calling
704 * component_bind_all(). See also &struct component_ops.
705 *
706 * @subcomponent must be nonzero and is used to differentiate between multiple
707 * components registerd on the same device @dev. These components are match
708 * using component_match_add_typed().
709 *
710 * The component needs to be unregistered at driver unload/disconnect by
711 * calling component_del().
712 *
713 * See also component_add().
714 */
715int component_add_typed(struct device *dev, const struct component_ops *ops,
716 int subcomponent)
717{
718 if (WARN_ON(subcomponent == 0))
719 return -EINVAL;
720
721 return __component_add(dev, ops, subcomponent);
722}
723EXPORT_SYMBOL_GPL(component_add_typed);
724
725/**
726 * component_add - register a component
727 * @dev: component device
728 * @ops: component callbacks
729 *
730 * Register a new component for @dev. Functions in @ops will be called when the
731 * aggregate driver is ready to bind the overall driver by calling
732 * component_bind_all(). See also &struct component_ops.
733 *
734 * The component needs to be unregistered at driver unload/disconnect by
735 * calling component_del().
736 *
737 * See also component_add_typed() for a variant that allows multipled different
738 * components on the same device.
739 */
740int component_add(struct device *dev, const struct component_ops *ops)
741{
742 return __component_add(dev, ops, 0);
743}
660EXPORT_SYMBOL_GPL(component_add); 744EXPORT_SYMBOL_GPL(component_add);
661 745
662/** 746/**