diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-async.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-async.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 85a6a34128a8..5bada202b2d3 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c | |||
@@ -22,10 +22,10 @@ | |||
22 | #include <media/v4l2-device.h> | 22 | #include <media/v4l2-device.h> |
23 | #include <media/v4l2-subdev.h> | 23 | #include <media/v4l2-subdev.h> |
24 | 24 | ||
25 | static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) | 25 | static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) |
26 | { | 26 | { |
27 | #if IS_ENABLED(CONFIG_I2C) | 27 | #if IS_ENABLED(CONFIG_I2C) |
28 | struct i2c_client *client = i2c_verify_client(dev); | 28 | struct i2c_client *client = i2c_verify_client(sd->dev); |
29 | return client && | 29 | return client && |
30 | asd->match.i2c.adapter_id == client->adapter->nr && | 30 | asd->match.i2c.adapter_id == client->adapter->nr && |
31 | asd->match.i2c.address == client->addr; | 31 | asd->match.i2c.address == client->addr; |
@@ -34,14 +34,24 @@ static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) | |||
34 | #endif | 34 | #endif |
35 | } | 35 | } |
36 | 36 | ||
37 | static bool match_devname(struct device *dev, struct v4l2_async_subdev *asd) | 37 | static bool match_devname(struct v4l2_subdev *sd, |
38 | struct v4l2_async_subdev *asd) | ||
38 | { | 39 | { |
39 | return !strcmp(asd->match.device_name.name, dev_name(dev)); | 40 | return !strcmp(asd->match.device_name.name, dev_name(sd->dev)); |
40 | } | 41 | } |
41 | 42 | ||
42 | static bool match_of(struct device *dev, struct v4l2_async_subdev *asd) | 43 | static bool match_of(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) |
43 | { | 44 | { |
44 | return dev->of_node == asd->match.of.node; | 45 | return sd->of_node == asd->match.of.node; |
46 | } | ||
47 | |||
48 | static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) | ||
49 | { | ||
50 | if (!asd->match.custom.match) | ||
51 | /* Match always */ | ||
52 | return true; | ||
53 | |||
54 | return asd->match.custom.match(sd->dev, asd); | ||
45 | } | 55 | } |
46 | 56 | ||
47 | static LIST_HEAD(subdev_list); | 57 | static LIST_HEAD(subdev_list); |
@@ -51,17 +61,14 @@ static DEFINE_MUTEX(list_lock); | |||
51 | static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, | 61 | static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, |
52 | struct v4l2_subdev *sd) | 62 | struct v4l2_subdev *sd) |
53 | { | 63 | { |
64 | bool (*match)(struct v4l2_subdev *, struct v4l2_async_subdev *); | ||
54 | struct v4l2_async_subdev *asd; | 65 | struct v4l2_async_subdev *asd; |
55 | bool (*match)(struct device *, struct v4l2_async_subdev *); | ||
56 | 66 | ||
57 | list_for_each_entry(asd, ¬ifier->waiting, list) { | 67 | list_for_each_entry(asd, ¬ifier->waiting, list) { |
58 | /* bus_type has been verified valid before */ | 68 | /* bus_type has been verified valid before */ |
59 | switch (asd->match_type) { | 69 | switch (asd->match_type) { |
60 | case V4L2_ASYNC_MATCH_CUSTOM: | 70 | case V4L2_ASYNC_MATCH_CUSTOM: |
61 | match = asd->match.custom.match; | 71 | match = match_custom; |
62 | if (!match) | ||
63 | /* Match always */ | ||
64 | return asd; | ||
65 | break; | 72 | break; |
66 | case V4L2_ASYNC_MATCH_DEVNAME: | 73 | case V4L2_ASYNC_MATCH_DEVNAME: |
67 | match = match_devname; | 74 | match = match_devname; |
@@ -79,7 +86,7 @@ static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier * | |||
79 | } | 86 | } |
80 | 87 | ||
81 | /* match cannot be NULL here */ | 88 | /* match cannot be NULL here */ |
82 | if (match(sd->dev, asd)) | 89 | if (match(sd, asd)) |
83 | return asd; | 90 | return asd; |
84 | } | 91 | } |
85 | 92 | ||
@@ -266,6 +273,14 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) | |||
266 | { | 273 | { |
267 | struct v4l2_async_notifier *notifier; | 274 | struct v4l2_async_notifier *notifier; |
268 | 275 | ||
276 | /* | ||
277 | * No reference taken. The reference is held by the device | ||
278 | * (struct v4l2_subdev.dev), and async sub-device does not | ||
279 | * exist independently of the device at any point of time. | ||
280 | */ | ||
281 | if (!sd->of_node && sd->dev) | ||
282 | sd->of_node = sd->dev->of_node; | ||
283 | |||
269 | mutex_lock(&list_lock); | 284 | mutex_lock(&list_lock); |
270 | 285 | ||
271 | INIT_LIST_HEAD(&sd->async_list); | 286 | INIT_LIST_HEAD(&sd->async_list); |