hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/media/v4l2-core/v4l2-device.c
....@@ -1,31 +1,15 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 V4L2 device support.
34
45 Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
56
6
- This program is free software; you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation; either version 2 of the License, or
9
- (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with this program; if not, write to the Free Software
18
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
197 */
208
219 #include <linux/types.h>
2210 #include <linux/ioctl.h>
2311 #include <linux/module.h>
24
-#include <linux/i2c.h>
2512 #include <linux/slab.h>
26
-#if defined(CONFIG_SPI)
27
-#include <linux/spi/spi.h>
28
-#endif
2913 #include <linux/videodev2.h>
3014 #include <media/v4l2-device.h>
3115 #include <media/v4l2-ctrls.h>
....@@ -114,37 +98,10 @@
11498 /* Unregister subdevs */
11599 list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
116100 v4l2_device_unregister_subdev(sd);
117
-#if IS_ENABLED(CONFIG_I2C)
118
- if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
119
- struct i2c_client *client = v4l2_get_subdevdata(sd);
120
-
121
- /*
122
- * We need to unregister the i2c client
123
- * explicitly. We cannot rely on
124
- * i2c_del_adapter to always unregister
125
- * clients for us, since if the i2c bus is a
126
- * platform bus, then it is never deleted.
127
- *
128
- * Device tree or ACPI based devices must not
129
- * be unregistered as they have not been
130
- * registered by us, and would not be
131
- * re-created by just probing the V4L2 driver.
132
- */
133
- if (client &&
134
- !client->dev.of_node && !client->dev.fwnode)
135
- i2c_unregister_device(client);
136
- continue;
137
- }
138
-#endif
139
-#if defined(CONFIG_SPI)
140
- if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) {
141
- struct spi_device *spi = v4l2_get_subdevdata(sd);
142
-
143
- if (spi && !spi->dev.of_node && !spi->dev.fwnode)
144
- spi_unregister_device(spi);
145
- continue;
146
- }
147
-#endif
101
+ if (sd->flags & V4L2_SUBDEV_FL_IS_I2C)
102
+ v4l2_i2c_subdev_unregister(sd);
103
+ else if (sd->flags & V4L2_SUBDEV_FL_IS_SPI)
104
+ v4l2_spi_subdev_unregister(sd);
148105 }
149106 /* Mark as unregistered, thus preventing duplicate unregistrations */
150107 v4l2_dev->name[0] = '\0';
....@@ -154,9 +111,6 @@
154111 int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
155112 struct v4l2_subdev *sd)
156113 {
157
-#if defined(CONFIG_MEDIA_CONTROLLER)
158
- struct media_entity *entity = &sd->entity;
159
-#endif
160114 int err;
161115
162116 /* Check for valid input */
....@@ -178,14 +132,15 @@
178132
179133 sd->v4l2_dev = v4l2_dev;
180134 /* This just returns 0 if either of the two args is NULL */
181
- err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL);
135
+ err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler,
136
+ NULL, true);
182137 if (err)
183138 goto error_module;
184139
185140 #if defined(CONFIG_MEDIA_CONTROLLER)
186141 /* Register the entity. */
187142 if (v4l2_dev->mdev) {
188
- err = media_device_register_entity(v4l2_dev->mdev, entity);
143
+ err = media_device_register_entity(v4l2_dev->mdev, &sd->entity);
189144 if (err < 0)
190145 goto error_module;
191146 }
....@@ -205,7 +160,7 @@
205160
206161 error_unregister:
207162 #if defined(CONFIG_MEDIA_CONTROLLER)
208
- media_device_unregister_entity(entity);
163
+ media_device_unregister_entity(&sd->entity);
209164 #endif
210165 error_module:
211166 if (!sd->owner_v4l2_dev)
....@@ -215,14 +170,24 @@
215170 }
216171 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
217172
173
+static void v4l2_subdev_release(struct v4l2_subdev *sd)
174
+{
175
+ struct module *owner = !sd->owner_v4l2_dev ? sd->owner : NULL;
176
+
177
+ if (sd->internal_ops && sd->internal_ops->release)
178
+ sd->internal_ops->release(sd);
179
+ sd->devnode = NULL;
180
+ module_put(owner);
181
+}
182
+
218183 static void v4l2_device_release_subdev_node(struct video_device *vdev)
219184 {
220
- struct v4l2_subdev *sd = video_get_drvdata(vdev);
221
- sd->devnode = NULL;
185
+ v4l2_subdev_release(video_get_drvdata(vdev));
222186 kfree(vdev);
223187 }
224188
225
-int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
189
+int __v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev,
190
+ bool read_only)
226191 {
227192 struct video_device *vdev;
228193 struct v4l2_subdev *sd;
....@@ -245,11 +210,14 @@
245210 }
246211
247212 video_set_drvdata(vdev, sd);
248
- strlcpy(vdev->name, sd->name, sizeof(vdev->name));
213
+ strscpy(vdev->name, sd->name, sizeof(vdev->name));
214
+ vdev->dev_parent = sd->dev;
249215 vdev->v4l2_dev = v4l2_dev;
250216 vdev->fops = &v4l2_subdev_fops;
251217 vdev->release = v4l2_device_release_subdev_node;
252218 vdev->ctrl_handler = sd->ctrl_handler;
219
+ if (read_only)
220
+ set_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags);
253221 err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
254222 sd->owner);
255223 if (err < 0) {
....@@ -287,7 +255,7 @@
287255
288256 return err;
289257 }
290
-EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
258
+EXPORT_SYMBOL_GPL(__v4l2_device_register_subdev_nodes);
291259
292260 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
293261 {
....@@ -316,8 +284,9 @@
316284 media_device_unregister_entity(&sd->entity);
317285 }
318286 #endif
319
- video_unregister_device(sd->devnode);
320
- if (!sd->owner_v4l2_dev)
321
- module_put(sd->owner);
287
+ if (sd->devnode)
288
+ video_unregister_device(sd->devnode);
289
+ else
290
+ v4l2_subdev_release(sd);
322291 }
323292 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);