[go: nahoru, domu]

1/*
2    V4L2 device support.
3
4    Copyright (C) 2008  Hans Verkuil <hverkuil@xs4all.nl>
5
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
19 */
20
21#include <linux/types.h>
22#include <linux/ioctl.h>
23#include <linux/module.h>
24#include <linux/i2c.h>
25#include <linux/slab.h>
26#if defined(CONFIG_SPI)
27#include <linux/spi/spi.h>
28#endif
29#include <linux/videodev2.h>
30#include <media/v4l2-device.h>
31#include <media/v4l2-ctrls.h>
32
33int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
34{
35	if (v4l2_dev == NULL)
36		return -EINVAL;
37
38	INIT_LIST_HEAD(&v4l2_dev->subdevs);
39	spin_lock_init(&v4l2_dev->lock);
40	mutex_init(&v4l2_dev->ioctl_lock);
41	v4l2_prio_init(&v4l2_dev->prio);
42	kref_init(&v4l2_dev->ref);
43	get_device(dev);
44	v4l2_dev->dev = dev;
45	if (dev == NULL) {
46		/* If dev == NULL, then name must be filled in by the caller */
47		if (WARN_ON(!v4l2_dev->name[0]))
48			return -EINVAL;
49		return 0;
50	}
51
52	/* Set name to driver name + device name if it is empty. */
53	if (!v4l2_dev->name[0])
54		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
55			dev->driver->name, dev_name(dev));
56	if (!dev_get_drvdata(dev))
57		dev_set_drvdata(dev, v4l2_dev);
58	return 0;
59}
60EXPORT_SYMBOL_GPL(v4l2_device_register);
61
62static void v4l2_device_release(struct kref *ref)
63{
64	struct v4l2_device *v4l2_dev =
65		container_of(ref, struct v4l2_device, ref);
66
67	if (v4l2_dev->release)
68		v4l2_dev->release(v4l2_dev);
69}
70
71int v4l2_device_put(struct v4l2_device *v4l2_dev)
72{
73	return kref_put(&v4l2_dev->ref, v4l2_device_release);
74}
75EXPORT_SYMBOL_GPL(v4l2_device_put);
76
77int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
78						atomic_t *instance)
79{
80	int num = atomic_inc_return(instance) - 1;
81	int len = strlen(basename);
82
83	if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
84		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
85				"%s-%d", basename, num);
86	else
87		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
88				"%s%d", basename, num);
89	return num;
90}
91EXPORT_SYMBOL_GPL(v4l2_device_set_name);
92
93void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
94{
95	if (v4l2_dev->dev == NULL)
96		return;
97
98	if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
99		dev_set_drvdata(v4l2_dev->dev, NULL);
100	put_device(v4l2_dev->dev);
101	v4l2_dev->dev = NULL;
102}
103EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
104
105void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
106{
107	struct v4l2_subdev *sd, *next;
108
109	/* Just return if v4l2_dev is NULL or if it was already
110	 * unregistered before. */
111	if (v4l2_dev == NULL || !v4l2_dev->name[0])
112		return;
113	v4l2_device_disconnect(v4l2_dev);
114
115	/* Unregister subdevs */
116	list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
117		v4l2_device_unregister_subdev(sd);
118#if IS_ENABLED(CONFIG_I2C)
119		if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
120			struct i2c_client *client = v4l2_get_subdevdata(sd);
121
122			/* We need to unregister the i2c client explicitly.
123			   We cannot rely on i2c_del_adapter to always
124			   unregister clients for us, since if the i2c bus
125			   is a platform bus, then it is never deleted. */
126			if (client)
127				i2c_unregister_device(client);
128			continue;
129		}
130#endif
131#if defined(CONFIG_SPI)
132		if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) {
133			struct spi_device *spi = v4l2_get_subdevdata(sd);
134
135			if (spi)
136				spi_unregister_device(spi);
137			continue;
138		}
139#endif
140	}
141	/* Mark as unregistered, thus preventing duplicate unregistrations */
142	v4l2_dev->name[0] = '\0';
143}
144EXPORT_SYMBOL_GPL(v4l2_device_unregister);
145
146int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
147				struct v4l2_subdev *sd)
148{
149#if defined(CONFIG_MEDIA_CONTROLLER)
150	struct media_entity *entity = &sd->entity;
151#endif
152	int err;
153
154	/* Check for valid input */
155	if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
156		return -EINVAL;
157
158	/* Warn if we apparently re-register a subdev */
159	WARN_ON(sd->v4l2_dev != NULL);
160
161	/*
162	 * The reason to acquire the module here is to avoid unloading
163	 * a module of sub-device which is registered to a media
164	 * device. To make it possible to unload modules for media
165	 * devices that also register sub-devices, do not
166	 * try_module_get() such sub-device owners.
167	 */
168	sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
169		sd->owner == v4l2_dev->dev->driver->owner;
170
171	if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
172		return -ENODEV;
173
174	sd->v4l2_dev = v4l2_dev;
175	if (sd->internal_ops && sd->internal_ops->registered) {
176		err = sd->internal_ops->registered(sd);
177		if (err)
178			goto error_module;
179	}
180
181	/* This just returns 0 if either of the two args is NULL */
182	err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL);
183	if (err)
184		goto error_unregister;
185
186#if defined(CONFIG_MEDIA_CONTROLLER)
187	/* Register the entity. */
188	if (v4l2_dev->mdev) {
189		err = media_device_register_entity(v4l2_dev->mdev, entity);
190		if (err < 0)
191			goto error_unregister;
192	}
193#endif
194
195	spin_lock(&v4l2_dev->lock);
196	list_add_tail(&sd->list, &v4l2_dev->subdevs);
197	spin_unlock(&v4l2_dev->lock);
198
199	return 0;
200
201error_unregister:
202	if (sd->internal_ops && sd->internal_ops->unregistered)
203		sd->internal_ops->unregistered(sd);
204error_module:
205	if (!sd->owner_v4l2_dev)
206		module_put(sd->owner);
207	sd->v4l2_dev = NULL;
208	return err;
209}
210EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
211
212static void v4l2_device_release_subdev_node(struct video_device *vdev)
213{
214	struct v4l2_subdev *sd = video_get_drvdata(vdev);
215	sd->devnode = NULL;
216	kfree(vdev);
217}
218
219int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
220{
221	struct video_device *vdev;
222	struct v4l2_subdev *sd;
223	int err;
224
225	/* Register a device node for every subdev marked with the
226	 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
227	 */
228	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
229		if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
230			continue;
231
232		vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
233		if (!vdev) {
234			err = -ENOMEM;
235			goto clean_up;
236		}
237
238		video_set_drvdata(vdev, sd);
239		strlcpy(vdev->name, sd->name, sizeof(vdev->name));
240		vdev->v4l2_dev = v4l2_dev;
241		vdev->fops = &v4l2_subdev_fops;
242		vdev->release = v4l2_device_release_subdev_node;
243		vdev->ctrl_handler = sd->ctrl_handler;
244		err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
245					      sd->owner);
246		if (err < 0) {
247			kfree(vdev);
248			goto clean_up;
249		}
250#if defined(CONFIG_MEDIA_CONTROLLER)
251		sd->entity.info.v4l.major = VIDEO_MAJOR;
252		sd->entity.info.v4l.minor = vdev->minor;
253#endif
254		sd->devnode = vdev;
255	}
256	return 0;
257
258clean_up:
259	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
260		if (!sd->devnode)
261			break;
262		video_unregister_device(sd->devnode);
263	}
264
265	return err;
266}
267EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
268
269void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
270{
271	struct v4l2_device *v4l2_dev;
272
273	/* return if it isn't registered */
274	if (sd == NULL || sd->v4l2_dev == NULL)
275		return;
276
277	v4l2_dev = sd->v4l2_dev;
278
279	spin_lock(&v4l2_dev->lock);
280	list_del(&sd->list);
281	spin_unlock(&v4l2_dev->lock);
282
283	if (sd->internal_ops && sd->internal_ops->unregistered)
284		sd->internal_ops->unregistered(sd);
285	sd->v4l2_dev = NULL;
286
287#if defined(CONFIG_MEDIA_CONTROLLER)
288	if (v4l2_dev->mdev) {
289		media_entity_remove_links(&sd->entity);
290		media_device_unregister_entity(&sd->entity);
291	}
292#endif
293	video_unregister_device(sd->devnode);
294	if (!sd->owner_v4l2_dev)
295		module_put(sd->owner);
296}
297EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
298