summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch615
1 files changed, 615 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch b/extras/recipes-kernel/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch
new file mode 100644
index 00000000..8fe2a9d6
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap/media/0004-v4l-subdev-Add-device-node-support.patch
@@ -0,0 +1,615 @@
1From e5b8af4e36ca5e922dd2b881d6c215e9d4d30a6f Mon Sep 17 00:00:00 2001
2From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
3Date: Wed, 9 Dec 2009 12:38:49 +0100
4Subject: [PATCH 04/43] v4l: subdev: Add device node support
5
6Create a device node named subdevX for every registered subdev.
7
8As the device node is registered before the subdev core::s_config
9function is called, return -EGAIN on open until initialization
10completes.
11
12Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
13Signed-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
37
38diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
39index 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
67diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
68index 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;
80diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
81index 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
93diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
94index 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;
106diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
107index 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",
119diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
120index 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");
132diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
133index 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;
145diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
146index 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);
158diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
159index 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;
171diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c
172index 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;
184diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
185index 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
197diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
198index 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. */
261diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
262index 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 }
318-
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);
324-
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
334diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
335index 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;
348+
349 /* Warn if we apparently re-register a subdev */
350 WARN_ON(sd->v4l2_dev != NULL);
351+
352 if (!try_module_get(sd->owner))
353 return -ENODEV;
354+
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;
359+
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;
365+
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+ }
378+
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;
387+
388 spin_lock(&sd->v4l2_dev->lock);
389 list_del(&sd->list);
390 spin_unlock(&sd->v4l2_dev->lock);
391 sd->v4l2_dev = NULL;
392+
393 module_put(sd->owner);
394+ video_unregister_device(&sd->devnode);
395 }
396 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
397diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
398index 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 {
410diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
411new file mode 100644
412index 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+ */
436+
437+#include <linux/types.h>
438+#include <linux/ioctl.h>
439+#include <linux/videodev2.h>
440+
441+#include <media/v4l2-device.h>
442+#include <media/v4l2-ioctl.h>
443+
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);
448+
449+ if (!sd->initialized)
450+ return -EAGAIN;
451+
452+ return 0;
453+}
454+
455+static int subdev_close(struct file *file)
456+{
457+ return 0;
458+}
459+
460+static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
461+{
462+ switch (cmd) {
463+ default:
464+ return -ENOIOCTLCMD;
465+ }
466+
467+ return 0;
468+}
469+
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+}
475+
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+};
482diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
483index 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,
505diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
506index 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);
525+
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. */
548diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
549index 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);
558+
559 /* Include support for obsoleted stuff */
560 extern long video_usercopy(struct file *file, unsigned int cmd,
561 unsigned long arg, v4l2_kioctl func);
562diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
563index 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)
599+
600+extern const struct v4l2_file_operations v4l2_subdev_fops;
601+
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--
6141.6.6.1
615