linux-omap 2.6.37: sync with OE .dev
[glsdk/meta-ti-glsdk.git] / recipes-bsp / linux / linux-omap / media / 0004-v4l-subdev-Add-device-node-support.patch
1 From e5b8af4e36ca5e922dd2b881d6c215e9d4d30a6f Mon Sep 17 00:00:00 2001
2 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3 Date: Wed, 9 Dec 2009 12:38:49 +0100
4 Subject: [PATCH 04/43] v4l: subdev: Add device node support
6 Create a device node named subdevX for every registered subdev.
8 As the device node is registered before the subdev core::s_config
9 function is called, return -EGAIN on open until initialization
10 completes.
12 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
13 Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com>
14 ---
15  Documentation/video4linux/v4l2-framework.txt |   18 +++++++
16  drivers/media/radio/radio-si4713.c           |    2 +-
17  drivers/media/video/Makefile                 |    2 +-
18  drivers/media/video/cafe_ccic.c              |    2 +-
19  drivers/media/video/davinci/vpfe_capture.c   |    2 +-
20  drivers/media/video/davinci/vpif_capture.c   |    2 +-
21  drivers/media/video/davinci/vpif_display.c   |    2 +-
22  drivers/media/video/ivtv/ivtv-i2c.c          |    2 +-
23  drivers/media/video/s5p-fimc/fimc-capture.c  |    2 +-
24  drivers/media/video/sh_vou.c                 |    2 +-
25  drivers/media/video/soc_camera.c             |    2 +-
26  drivers/media/video/v4l2-common.c            |   15 +++++-
27  drivers/media/video/v4l2-dev.c               |   27 ++++------
28  drivers/media/video/v4l2-device.c            |   24 +++++++++-
29  drivers/media/video/v4l2-ioctl.c             |    2 +-
30  drivers/media/video/v4l2-subdev.c            |   66 ++++++++++++++++++++++++++
31  include/media/v4l2-common.h                  |    5 +-
32  include/media/v4l2-dev.h                     |   18 ++++++-
33  include/media/v4l2-ioctl.h                   |    3 +
34  include/media/v4l2-subdev.h                  |   16 ++++++-
35  20 files changed, 176 insertions(+), 38 deletions(-)
36  create mode 100644 drivers/media/video/v4l2-subdev.c
38 diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
39 index f22f35c..4c9185a 100644
40 --- a/Documentation/video4linux/v4l2-framework.txt
41 +++ b/Documentation/video4linux/v4l2-framework.txt
42 @@ -319,6 +319,24 @@ controlled through GPIO pins. This distinction is only relevant when setting
43  up the device, but once the subdev is registered it is completely transparent.
44  
45  
46 +V4L2 sub-device userspace API
47 +-----------------------------
48 +
49 +Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2
50 +sub-devices can also be controlled directly by userspace applications.
51 +
52 +When a sub-device is registered, a device node named v4l-subdevX can be created
53 +in /dev. If the sub-device supports direct userspace configuration it must set
54 +the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered.
55 +
56 +For I2C and SPI sub-devices, the v4l2_device driver can disable registration of
57 +the device node if it wants to control the sub-device on its own. In that case
58 +it must set the v4l2_i2c_new_subdev_board or v4l2_spi_new_subdev enable_devnode
59 +argument to 0. Setting the argument to 1 will only enable device node
60 +registration if the sub-device driver has set the V4L2_SUBDEV_FL_HAS_DEVNODE
61 +flag.
62 +
63 +
64  I2C sub-device drivers
65  ----------------------
66  
67 diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
68 index 726d367..f7c942f 100644
69 --- a/drivers/media/radio/radio-si4713.c
70 +++ b/drivers/media/radio/radio-si4713.c
71 @@ -293,7 +293,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
72         }
73  
74         sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
75 -                                       pdata->subdev_board_info, NULL);
76 +                                       pdata->subdev_board_info, NULL, 0);
77         if (!sd) {
78                 dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
79                 rval = -ENODEV;
80 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
81 index af79d47..adc1bd5 100644
82 --- a/drivers/media/video/Makefile
83 +++ b/drivers/media/video/Makefile
84 @@ -11,7 +11,7 @@ stkwebcam-objs        :=      stk-webcam.o stk-sensor.o
85  omap2cam-objs  :=      omap24xxcam.o omap24xxcam-dma.o
86  
87  videodev-objs  :=      v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
88 -                       v4l2-event.o v4l2-ctrls.o
89 +                       v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
90  
91  # V4L2 core modules
92  
93 diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
94 index 6e23add..f932da1 100644
95 --- a/drivers/media/video/cafe_ccic.c
96 +++ b/drivers/media/video/cafe_ccic.c
97 @@ -2073,7 +2073,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
98         info.platform_data = &sensor_cfg;
99  
100         cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
101 -                       &cam->i2c_adapter, &info, NULL);
102 +                       &cam->i2c_adapter, &info, NULL, 0);
103         if (cam->sensor == NULL) {
104                 ret = -ENODEV;
105                 goto out_smbus;
106 diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
107 index 7333a9b..bfc2a47 100644
108 --- a/drivers/media/video/davinci/vpfe_capture.c
109 +++ b/drivers/media/video/davinci/vpfe_capture.c
110 @@ -1987,7 +1987,7 @@ static __init int vpfe_probe(struct platform_device *pdev)
111                         v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,
112                                                   i2c_adap,
113                                                   &sdinfo->board_info,
114 -                                                 NULL);
115 +                                                 NULL, 0);
116                 if (vpfe_dev->sd[i]) {
117                         v4l2_info(&vpfe_dev->v4l2_dev,
118                                   "v4l2 sub device %s registered\n",
119 diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
120 index 193abab..d2228e0 100644
121 --- a/drivers/media/video/davinci/vpif_capture.c
122 +++ b/drivers/media/video/davinci/vpif_capture.c
123 @@ -2014,7 +2014,7 @@ static __init int vpif_probe(struct platform_device *pdev)
124                         v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
125                                                   i2c_adap,
126                                                   &subdevdata->board_info,
127 -                                                 NULL);
128 +                                                 NULL, 0);
129  
130                 if (!vpif_obj.sd[i]) {
131                         vpif_err("Error registering v4l2 subdevice\n");
132 diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
133 index 412c65d..060c049 100644
134 --- a/drivers/media/video/davinci/vpif_display.c
135 +++ b/drivers/media/video/davinci/vpif_display.c
136 @@ -1555,7 +1555,7 @@ static __init int vpif_probe(struct platform_device *pdev)
137                 vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
138                                                 i2c_adap,
139                                                 &subdevdata[i].board_info,
140 -                                               NULL);
141 +                                               NULL, 0);
142                 if (!vpif_obj.sd[i]) {
143                         vpif_err("Error registering v4l2 subdevice\n");
144                         goto probe_subdev_out;
145 diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
146 index 6651a6c..3d3b62d 100644
147 --- a/drivers/media/video/ivtv/ivtv-i2c.c
148 +++ b/drivers/media/video/ivtv/ivtv-i2c.c
149 @@ -277,7 +277,7 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
150                 info.platform_data = &pdata;
151  
152                 sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, &info,
153 -                                              NULL);
154 +                                              NULL, 0);
155         } else {
156                 sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
157                                 adap, type, hw_addrs[idx], NULL);
158 diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
159 index 2f50080..b237daa 100644
160 --- a/drivers/media/video/s5p-fimc/fimc-capture.c
161 +++ b/drivers/media/video/s5p-fimc/fimc-capture.c
162 @@ -44,7 +44,7 @@ static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
163                 return ERR_PTR(-ENOMEM);
164  
165         sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap,
166 -                                      isp_info->board_info, NULL);
167 +                                      isp_info->board_info, NULL, 0);
168         if (!sd) {
169                 v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n");
170                 return NULL;
171 diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c
172 index 07cf0c6..c50f0f5 100644
173 --- a/drivers/media/video/sh_vou.c
174 +++ b/drivers/media/video/sh_vou.c
175 @@ -1409,7 +1409,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
176                 goto ereset;
177  
178         subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap,
179 -                       vou_pdata->board_info, NULL);
180 +                       vou_pdata->board_info, NULL, 0);
181         if (!subdev) {
182                 ret = -ENOMEM;
183                 goto ei2cnd;
184 diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
185 index 052bd6d..5afb601 100644
186 --- a/drivers/media/video/soc_camera.c
187 +++ b/drivers/media/video/soc_camera.c
188 @@ -896,7 +896,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd,
189         icl->board_info->platform_data = icd;
190  
191         subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap,
192 -                               icl->board_info, NULL);
193 +                               icl->board_info, NULL, 0);
194         if (!subdev)
195                 goto ei2cnd;
196  
197 diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
198 index e007e61..ffee794 100644
199 --- a/drivers/media/video/v4l2-common.c
200 +++ b/drivers/media/video/v4l2-common.c
201 @@ -369,7 +369,7 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
202  /* Load an i2c sub-device. */
203  struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
204                 struct i2c_adapter *adapter, struct i2c_board_info *info,
205 -               const unsigned short *probe_addrs)
206 +               const unsigned short *probe_addrs, int enable_devnode)
207  {
208         struct v4l2_subdev *sd = NULL;
209         struct i2c_client *client;
210 @@ -399,9 +399,12 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
211         if (!try_module_get(client->driver->driver.owner))
212                 goto error;
213         sd = i2c_get_clientdata(client);
214 +       if (!enable_devnode)
215 +               sd->flags &= ~V4L2_SUBDEV_FL_HAS_DEVNODE;
216  
217         /* Register with the v4l2_device which increases the module's
218            use count as well. */
219 +       sd->initialized = 0;
220         if (v4l2_device_register_subdev(v4l2_dev, sd))
221                 sd = NULL;
222         /* Decrease the module use count to match the first try_module_get. */
223 @@ -416,6 +419,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
224                 if (err && err != -ENOIOCTLCMD) {
225                         v4l2_device_unregister_subdev(sd);
226                         sd = NULL;
227 +               } else {
228 +                       sd->initialized = 1;
229                 }
230         }
231  
232 @@ -440,7 +445,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
233         strlcpy(info.type, client_type, sizeof(info.type));
234         info.addr = addr;
235  
236 -       return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
237 +       return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs,
238 +                                        0);
239  }
240  EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
241  
242 @@ -510,7 +516,8 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
243  EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
244  
245  struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
246 -               struct spi_master *master, struct spi_board_info *info)
247 +               struct spi_master *master, struct spi_board_info *info,
248 +               int enable_devnode)
249  {
250         struct v4l2_subdev *sd = NULL;
251         struct spi_device *spi = NULL;
252 @@ -529,6 +536,8 @@ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
253                 goto error;
254  
255         sd = spi_get_drvdata(spi);
256 +       if (!enable_devnode)
257 +               sd->flags &= ~V4L2_SUBDEV_FL_HAS_DEVNODE;
258  
259         /* Register with the v4l2_device which increases the module's
260            use count as well. */
261 diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
262 index 359e232..f22bd41 100644
263 --- a/drivers/media/video/v4l2-dev.c
264 +++ b/drivers/media/video/v4l2-dev.c
265 @@ -408,13 +408,14 @@ static int get_index(struct video_device *vdev)
266  }
267  
268  /**
269 - *     video_register_device - register video4linux devices
270 + *     __video_register_device - register video4linux devices
271   *     @vdev: video device structure we want to register
272   *     @type: type of device to register
273   *     @nr:   which device node number (0 == /dev/video0, 1 == /dev/video1, ...
274   *             -1 == first free)
275   *     @warn_if_nr_in_use: warn if the desired device node number
276   *            was already in use and another number was chosen instead.
277 + *     @owner: module that owns the video device node
278   *
279   *     The registration code assigns minor numbers and device node numbers
280   *     based on the requested type and registers the new device node with
281 @@ -431,9 +432,11 @@ static int get_index(struct video_device *vdev)
282   *     %VFL_TYPE_VBI - Vertical blank data (undecoded)
283   *
284   *     %VFL_TYPE_RADIO - A radio card
285 + *
286 + *     %VFL_TYPE_SUBDEV - A subdevice
287   */
288 -static int __video_register_device(struct video_device *vdev, int type, int nr,
289 -               int warn_if_nr_in_use)
290 +int __video_register_device(struct video_device *vdev, int type, int nr,
291 +               int warn_if_nr_in_use, struct module *owner)
292  {
293         int i = 0;
294         int ret;
295 @@ -466,6 +469,9 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
296         case VFL_TYPE_RADIO:
297                 name_base = "radio";
298                 break;
299 +       case VFL_TYPE_SUBDEV:
300 +               name_base = "v4l-subdev";
301 +               break;
302         default:
303                 printk(KERN_ERR "%s called with unknown type: %d\n",
304                        __func__, type);
305 @@ -549,7 +555,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
306                 goto cleanup;
307         }
308         vdev->cdev->ops = &v4l2_fops;
309 -       vdev->cdev->owner = vdev->fops->owner;
310 +       vdev->cdev->owner = owner;
311         ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
312         if (ret < 0) {
313                 printk(KERN_ERR "%s: cdev_add failed\n", __func__);
314 @@ -598,18 +604,7 @@ cleanup:
315         vdev->minor = -1;
316         return ret;
317  }
319 -int video_register_device(struct video_device *vdev, int type, int nr)
320 -{
321 -       return __video_register_device(vdev, type, nr, 1);
322 -}
323 -EXPORT_SYMBOL(video_register_device);
325 -int video_register_device_no_warn(struct video_device *vdev, int type, int nr)
326 -{
327 -       return __video_register_device(vdev, type, nr, 0);
328 -}
329 -EXPORT_SYMBOL(video_register_device_no_warn);
330 +EXPORT_SYMBOL(__video_register_device);
331  
332  /**
333   *     video_unregister_device - unregister a video4linux device
334 diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
335 index 7fe6f92..97e84df 100644
336 --- a/drivers/media/video/v4l2-device.c
337 +++ b/drivers/media/video/v4l2-device.c
338 @@ -117,24 +117,43 @@ EXPORT_SYMBOL_GPL(v4l2_device_unregister);
339  int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
340                                                 struct v4l2_subdev *sd)
341  {
342 +       struct video_device *vdev;
343         int err;
344  
345         /* Check for valid input */
346         if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
347                 return -EINVAL;
349         /* Warn if we apparently re-register a subdev */
350         WARN_ON(sd->v4l2_dev != NULL);
352         if (!try_module_get(sd->owner))
353                 return -ENODEV;
355         /* This just returns 0 if either of the two args is NULL */
356         err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
357         if (err)
358                 return err;
360         sd->v4l2_dev = v4l2_dev;
361         spin_lock(&v4l2_dev->lock);
362         list_add_tail(&sd->list, &v4l2_dev->subdevs);
363         spin_unlock(&v4l2_dev->lock);
364 -       return 0;
366 +       /* Register the device node. */
367 +       vdev = &sd->devnode;
368 +       strlcpy(vdev->name, sd->name, sizeof(vdev->name));
369 +       vdev->parent = v4l2_dev->dev;
370 +       vdev->fops = &v4l2_subdev_fops;
371 +       vdev->release = video_device_release_empty;
372 +       if (sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) {
373 +               err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
374 +                                             sd->owner);
375 +               if (err < 0)
376 +                       v4l2_device_unregister_subdev(sd);
377 +       }
379 +       return err;
380  }
381  EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
382  
383 @@ -143,10 +162,13 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
384         /* return if it isn't registered */
385         if (sd == NULL || sd->v4l2_dev == NULL)
386                 return;
388         spin_lock(&sd->v4l2_dev->lock);
389         list_del(&sd->list);
390         spin_unlock(&sd->v4l2_dev->lock);
391         sd->v4l2_dev = NULL;
393         module_put(sd->owner);
394 +       video_unregister_device(&sd->devnode);
395  }
396  EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
397 diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
398 index 1e01554..4137e4c 100644
399 --- a/drivers/media/video/v4l2-ioctl.c
400 +++ b/drivers/media/video/v4l2-ioctl.c
401 @@ -413,7 +413,7 @@ static unsigned long cmd_input_size(unsigned int cmd)
402         }
403  }
404  
405 -static long
406 +long
407  __video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
408                 v4l2_kioctl func)
409  {
410 diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
411 new file mode 100644
412 index 0000000..00bd4b1
413 --- /dev/null
414 +++ b/drivers/media/video/v4l2-subdev.c
415 @@ -0,0 +1,66 @@
416 +/*
417 + *  V4L2 subdevice support.
418 + *
419 + *  Copyright (C) 2010 Nokia Corporation
420 + *
421 + *  Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
422 + *
423 + *  This program is free software; you can redistribute it and/or modify
424 + *  it under the terms of the GNU General Public License as published by
425 + *  the Free Software Foundation.
426 + *
427 + *  This program is distributed in the hope that it will be useful,
428 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
429 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
430 + *  GNU General Public License for more details.
431 + *
432 + *  You should have received a copy of the GNU General Public License
433 + *  along with this program; if not, write to the Free Software
434 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
435 + */
437 +#include <linux/types.h>
438 +#include <linux/ioctl.h>
439 +#include <linux/videodev2.h>
441 +#include <media/v4l2-device.h>
442 +#include <media/v4l2-ioctl.h>
444 +static int subdev_open(struct file *file)
445 +{
446 +       struct video_device *vdev = video_devdata(file);
447 +       struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
449 +       if (!sd->initialized)
450 +               return -EAGAIN;
452 +       return 0;
453 +}
455 +static int subdev_close(struct file *file)
456 +{
457 +       return 0;
458 +}
460 +static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
461 +{
462 +       switch (cmd) {
463 +       default:
464 +               return -ENOIOCTLCMD;
465 +       }
467 +       return 0;
468 +}
470 +static long subdev_ioctl(struct file *file, unsigned int cmd,
471 +       unsigned long arg)
472 +{
473 +       return __video_usercopy(file, cmd, arg, subdev_do_ioctl);
474 +}
476 +const struct v4l2_file_operations v4l2_subdev_fops = {
477 +       .owner = THIS_MODULE,
478 +       .open = subdev_open,
479 +       .unlocked_ioctl = subdev_ioctl,
480 +       .release = subdev_close,
481 +};
482 diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
483 index 565fb32..ef8965d 100644
484 --- a/include/media/v4l2-common.h
485 +++ b/include/media/v4l2-common.h
486 @@ -146,7 +146,7 @@ struct i2c_board_info;
487  
488  struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
489                 struct i2c_adapter *adapter, struct i2c_board_info *info,
490 -               const unsigned short *probe_addrs);
491 +               const unsigned short *probe_addrs, int enable_devnode);
492  
493  /* Initialize an v4l2_subdev with data from an i2c_client struct */
494  void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
495 @@ -179,7 +179,8 @@ struct spi_device;
496  /* Load an spi module and return an initialized v4l2_subdev struct.
497     The client_type argument is the name of the chip that's on the adapter. */
498  struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
499 -               struct spi_master *master, struct spi_board_info *info);
500 +               struct spi_master *master, struct spi_board_info *info,
501 +               int enable_devnode);
502  
503  /* Initialize an v4l2_subdev with data from an spi_device struct */
504  void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
505 diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
506 index 15802a0..4fe6831 100644
507 --- a/include/media/v4l2-dev.h
508 +++ b/include/media/v4l2-dev.h
509 @@ -21,7 +21,8 @@
510  #define VFL_TYPE_GRABBER       0
511  #define VFL_TYPE_VBI           1
512  #define VFL_TYPE_RADIO         2
513 -#define VFL_TYPE_MAX           3
514 +#define VFL_TYPE_SUBDEV                3
515 +#define VFL_TYPE_MAX           4
516  
517  struct v4l2_ioctl_callbacks;
518  struct video_device;
519 @@ -102,15 +103,26 @@ struct video_device
520  /* dev to video-device */
521  #define to_video_device(cd) container_of(cd, struct video_device, dev)
522  
523 +int __must_check __video_register_device(struct video_device *vdev, int type,
524 +               int nr, int warn_if_nr_in_use, struct module *owner);
526  /* Register video devices. Note that if video_register_device fails,
527     the release() callback of the video_device structure is *not* called, so
528     the caller is responsible for freeing any data. Usually that means that
529     you call video_device_release() on failure. */
530 -int __must_check video_register_device(struct video_device *vdev, int type, int nr);
531 +static inline int __must_check video_register_device(struct video_device *vdev,
532 +               int type, int nr)
533 +{
534 +       return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
535 +}
536  
537  /* Same as video_register_device, but no warning is issued if the desired
538     device node number was already in use. */
539 -int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr);
540 +static inline int __must_check video_register_device_no_warn(
541 +               struct video_device *vdev, int type, int nr)
542 +{
543 +       return __video_register_device(vdev, type, nr, 0, vdev->fops->owner);
544 +}
545  
546  /* Unregister video devices. Will do nothing if vdev == NULL or
547     video_is_registered() returns false. */
548 diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
549 index 06daa6e..abb64d0 100644
550 --- a/include/media/v4l2-ioctl.h
551 +++ b/include/media/v4l2-ioctl.h
552 @@ -316,6 +316,9 @@ extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd,
553                                 unsigned long arg);
554  #endif
555  
556 +extern long __video_usercopy(struct file *file, unsigned int cmd,
557 +                               unsigned long arg, v4l2_kioctl func);
559  /* Include support for obsoleted stuff */
560  extern long video_usercopy(struct file *file, unsigned int cmd,
561                                 unsigned long arg, v4l2_kioctl func);
562 diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
563 index b636444..de181db 100644
564 --- a/include/media/v4l2-subdev.h
565 +++ b/include/media/v4l2-subdev.h
566 @@ -22,6 +22,7 @@
567  #define _V4L2_SUBDEV_H
568  
569  #include <media/v4l2-common.h>
570 +#include <media/v4l2-dev.h>
571  #include <media/v4l2-mediabus.h>
572  
573  /* generic v4l2_device notify callback notification values */
574 @@ -418,9 +419,11 @@ struct v4l2_subdev_ops {
575  #define V4L2_SUBDEV_NAME_SIZE 32
576  
577  /* Set this flag if this subdev is a i2c device. */
578 -#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
579 +#define V4L2_SUBDEV_FL_IS_I2C                  (1U << 0)
580  /* Set this flag if this subdev is a spi device. */
581 -#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
582 +#define V4L2_SUBDEV_FL_IS_SPI                  (1U << 1)
583 +/* Set this flag if this subdev needs a device node. */
584 +#define V4L2_SUBDEV_FL_HAS_DEVNODE             (1U << 2)
585  
586  /* Each instance of a subdev driver should create this struct, either
587     stand-alone or embedded in a larger struct.
588 @@ -440,8 +443,16 @@ struct v4l2_subdev {
589         /* pointer to private data */
590         void *dev_priv;
591         void *host_priv;
592 +       /* subdev device node */
593 +       struct video_device devnode;
594 +       unsigned int initialized;
595  };
596  
597 +#define vdev_to_v4l2_subdev(vdev) \
598 +       container_of(vdev, struct v4l2_subdev, devnode)
600 +extern const struct v4l2_file_operations v4l2_subdev_fops;
602  static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
603  {
604         sd->dev_priv = p;
605 @@ -474,6 +485,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd,
606         sd->grp_id = 0;
607         sd->dev_priv = NULL;
608         sd->host_priv = NULL;
609 +       sd->initialized = 1;
610  }
611  
612  /* Call an ops of a v4l2_subdev, doing the right checks against
613 -- 
614 1.6.6.1