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