[media] cx18: use core priority handling
[deliverable/linux.git] / drivers / media / video / v4l2-device.c
CommitLineData
2a1fcdf0
HV
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/i2c.h>
85e09219
DB
24#if defined(CONFIG_SPI)
25#include <linux/spi/spi.h>
26#endif
2a1fcdf0
HV
27#include <linux/videodev2.h>
28#include <media/v4l2-device.h>
11bbc1ca 29#include <media/v4l2-ctrls.h>
2a1fcdf0
HV
30
31int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
32{
3a63e449 33 if (v4l2_dev == NULL)
2a1fcdf0 34 return -EINVAL;
3a63e449 35
2a1fcdf0
HV
36 INIT_LIST_HEAD(&v4l2_dev->subdevs);
37 spin_lock_init(&v4l2_dev->lock);
879aa24d 38 mutex_init(&v4l2_dev->ioctl_lock);
0f62fd6a 39 v4l2_prio_init(&v4l2_dev->prio);
2a1fcdf0 40 v4l2_dev->dev = dev;
3a63e449
HV
41 if (dev == NULL) {
42 /* If dev == NULL, then name must be filled in by the caller */
43 WARN_ON(!v4l2_dev->name[0]);
44 return 0;
45 }
46
47 /* Set name to driver name + device name if it is empty. */
48 if (!v4l2_dev->name[0])
49 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
c3ef01ce 50 dev->driver->name, dev_name(dev));
95db3a60
LP
51 if (!dev_get_drvdata(dev))
52 dev_set_drvdata(dev, v4l2_dev);
2a1fcdf0
HV
53 return 0;
54}
55EXPORT_SYMBOL_GPL(v4l2_device_register);
56
102e7813
HV
57int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
58 atomic_t *instance)
59{
60 int num = atomic_inc_return(instance) - 1;
61 int len = strlen(basename);
62
63 if (basename[len - 1] >= '0' && basename[len - 1] <= '9')
64 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
65 "%s-%d", basename, num);
66 else
67 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
68 "%s%d", basename, num);
69 return num;
70}
71EXPORT_SYMBOL_GPL(v4l2_device_set_name);
72
ae6cfaac
HV
73void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
74{
95db3a60
LP
75 if (v4l2_dev->dev == NULL)
76 return;
77
78 if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
ae6cfaac 79 dev_set_drvdata(v4l2_dev->dev, NULL);
95db3a60 80 v4l2_dev->dev = NULL;
ae6cfaac
HV
81}
82EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
83
2a1fcdf0
HV
84void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
85{
86 struct v4l2_subdev *sd, *next;
87
3a63e449 88 if (v4l2_dev == NULL)
2a1fcdf0 89 return;
ae6cfaac
HV
90 v4l2_device_disconnect(v4l2_dev);
91
3a63e449 92 /* Unregister subdevs */
b5b2b7ed 93 list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
2a1fcdf0 94 v4l2_device_unregister_subdev(sd);
ef5b5168 95#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
b5b2b7ed
HV
96 if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
97 struct i2c_client *client = v4l2_get_subdevdata(sd);
98
99 /* We need to unregister the i2c client explicitly.
100 We cannot rely on i2c_del_adapter to always
101 unregister clients for us, since if the i2c bus
102 is a platform bus, then it is never deleted. */
103 if (client)
104 i2c_unregister_device(client);
672dcd54 105 continue;
b5b2b7ed 106 }
85e09219
DB
107#endif
108#if defined(CONFIG_SPI)
109 if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) {
110 struct spi_device *spi = v4l2_get_subdevdata(sd);
111
112 if (spi)
113 spi_unregister_device(spi);
672dcd54 114 continue;
85e09219 115 }
b7fd6067 116#endif
b5b2b7ed 117 }
2a1fcdf0
HV
118}
119EXPORT_SYMBOL_GPL(v4l2_device_unregister);
120
3a63e449 121int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
61f5db54 122 struct v4l2_subdev *sd)
2a1fcdf0 123{
61f5db54
LP
124#if defined(CONFIG_MEDIA_CONTROLLER)
125 struct media_entity *entity = &sd->entity;
126#endif
11bbc1ca
HV
127 int err;
128
2a1fcdf0 129 /* Check for valid input */
3a63e449 130 if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
2a1fcdf0 131 return -EINVAL;
2096a5dc 132
2a1fcdf0 133 /* Warn if we apparently re-register a subdev */
b0167600 134 WARN_ON(sd->v4l2_dev != NULL);
2096a5dc 135
2a1fcdf0
HV
136 if (!try_module_get(sd->owner))
137 return -ENODEV;
2096a5dc 138
45f6f84a
HV
139 sd->v4l2_dev = v4l2_dev;
140 if (sd->internal_ops && sd->internal_ops->registered) {
141 err = sd->internal_ops->registered(sd);
142 if (err)
143 return err;
144 }
2096a5dc 145
11bbc1ca
HV
146 /* This just returns 0 if either of the two args is NULL */
147 err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
45f6f84a
HV
148 if (err) {
149 if (sd->internal_ops && sd->internal_ops->unregistered)
150 sd->internal_ops->unregistered(sd);
11bbc1ca 151 return err;
45f6f84a 152 }
2096a5dc 153
61f5db54
LP
154#if defined(CONFIG_MEDIA_CONTROLLER)
155 /* Register the entity. */
156 if (v4l2_dev->mdev) {
157 err = media_device_register_entity(v4l2_dev->mdev, entity);
158 if (err < 0) {
159 if (sd->internal_ops && sd->internal_ops->unregistered)
160 sd->internal_ops->unregistered(sd);
161 module_put(sd->owner);
162 return err;
163 }
164 }
165#endif
166
3a63e449
HV
167 spin_lock(&v4l2_dev->lock);
168 list_add_tail(&sd->list, &v4l2_dev->subdevs);
169 spin_unlock(&v4l2_dev->lock);
2096a5dc 170
2a1fcdf0
HV
171 return 0;
172}
173EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
174
2096a5dc
LP
175int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
176{
177 struct video_device *vdev;
178 struct v4l2_subdev *sd;
179 int err;
180
181 /* Register a device node for every subdev marked with the
182 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
183 */
184 list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
185 if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
186 continue;
187
188 vdev = &sd->devnode;
189 strlcpy(vdev->name, sd->name, sizeof(vdev->name));
190 vdev->v4l2_dev = v4l2_dev;
191 vdev->fops = &v4l2_subdev_fops;
192 vdev->release = video_device_release_empty;
193 err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
194 sd->owner);
195 if (err < 0)
196 return err;
61f5db54
LP
197#if defined(CONFIG_MEDIA_CONTROLLER)
198 sd->entity.v4l.major = VIDEO_MAJOR;
199 sd->entity.v4l.minor = vdev->minor;
200#endif
2096a5dc 201 }
2096a5dc
LP
202 return 0;
203}
204EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
205
2a1fcdf0
HV
206void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
207{
61f5db54
LP
208 struct v4l2_device *v4l2_dev;
209
2a1fcdf0 210 /* return if it isn't registered */
b0167600 211 if (sd == NULL || sd->v4l2_dev == NULL)
2a1fcdf0 212 return;
2096a5dc 213
61f5db54
LP
214 v4l2_dev = sd->v4l2_dev;
215
216 spin_lock(&v4l2_dev->lock);
2a1fcdf0 217 list_del(&sd->list);
61f5db54
LP
218 spin_unlock(&v4l2_dev->lock);
219
45f6f84a
HV
220 if (sd->internal_ops && sd->internal_ops->unregistered)
221 sd->internal_ops->unregistered(sd);
b0167600 222 sd->v4l2_dev = NULL;
2096a5dc 223
61f5db54
LP
224#if defined(CONFIG_MEDIA_CONTROLLER)
225 if (v4l2_dev->mdev)
226 media_device_unregister_entity(&sd->entity);
227#endif
2096a5dc 228 video_unregister_device(&sd->devnode);
2a1fcdf0
HV
229 module_put(sd->owner);
230}
231EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
This page took 0.315171 seconds and 5 git commands to generate.