diff options
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.patch | 615 |
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 @@ +From e5b8af4e36ca5e922dd2b881d6c215e9d4d30a6f Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Wed, 9 Dec 2009 12:38:49 +0100 +Subject: [PATCH 04/43] v4l: subdev: Add device node support + +Create a device node named subdevX for every registered subdev. + +As the device node is registered before the subdev core::s_config +function is called, return -EGAIN on open until initialization +completes. + +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@nokia.com> +--- + Documentation/video4linux/v4l2-framework.txt | 18 +++++++ + drivers/media/radio/radio-si4713.c | 2 +- + drivers/media/video/Makefile | 2 +- + drivers/media/video/cafe_ccic.c | 2 +- + drivers/media/video/davinci/vpfe_capture.c | 2 +- + drivers/media/video/davinci/vpif_capture.c | 2 +- + drivers/media/video/davinci/vpif_display.c | 2 +- + drivers/media/video/ivtv/ivtv-i2c.c | 2 +- + drivers/media/video/s5p-fimc/fimc-capture.c | 2 +- + drivers/media/video/sh_vou.c | 2 +- + drivers/media/video/soc_camera.c | 2 +- + drivers/media/video/v4l2-common.c | 15 +++++- + drivers/media/video/v4l2-dev.c | 27 ++++------ + drivers/media/video/v4l2-device.c | 24 +++++++++- + drivers/media/video/v4l2-ioctl.c | 2 +- + drivers/media/video/v4l2-subdev.c | 66 ++++++++++++++++++++++++++ + include/media/v4l2-common.h | 5 +- + include/media/v4l2-dev.h | 18 ++++++- + include/media/v4l2-ioctl.h | 3 + + include/media/v4l2-subdev.h | 16 ++++++- + 20 files changed, 176 insertions(+), 38 deletions(-) + create mode 100644 drivers/media/video/v4l2-subdev.c + +diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt +index f22f35c..4c9185a 100644 +--- a/Documentation/video4linux/v4l2-framework.txt ++++ b/Documentation/video4linux/v4l2-framework.txt +@@ -319,6 +319,24 @@ controlled through GPIO pins. This distinction is only relevant when setting + up the device, but once the subdev is registered it is completely transparent. + + ++V4L2 sub-device userspace API ++----------------------------- ++ ++Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2 ++sub-devices can also be controlled directly by userspace applications. ++ ++When a sub-device is registered, a device node named v4l-subdevX can be created ++in /dev. If the sub-device supports direct userspace configuration it must set ++the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered. ++ ++For I2C and SPI sub-devices, the v4l2_device driver can disable registration of ++the device node if it wants to control the sub-device on its own. In that case ++it must set the v4l2_i2c_new_subdev_board or v4l2_spi_new_subdev enable_devnode ++argument to 0. Setting the argument to 1 will only enable device node ++registration if the sub-device driver has set the V4L2_SUBDEV_FL_HAS_DEVNODE ++flag. ++ ++ + I2C sub-device drivers + ---------------------- + +diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c +index 726d367..f7c942f 100644 +--- a/drivers/media/radio/radio-si4713.c ++++ b/drivers/media/radio/radio-si4713.c +@@ -293,7 +293,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev) + } + + sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, +- pdata->subdev_board_info, NULL); ++ pdata->subdev_board_info, NULL, 0); + if (!sd) { + dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n"); + rval = -ENODEV; +diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile +index af79d47..adc1bd5 100644 +--- a/drivers/media/video/Makefile ++++ b/drivers/media/video/Makefile +@@ -11,7 +11,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o + omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o + + videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ +- v4l2-event.o v4l2-ctrls.o ++ v4l2-event.o v4l2-ctrls.o v4l2-subdev.o + + # V4L2 core modules + +diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c +index 6e23add..f932da1 100644 +--- a/drivers/media/video/cafe_ccic.c ++++ b/drivers/media/video/cafe_ccic.c +@@ -2073,7 +2073,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, + info.platform_data = &sensor_cfg; + + cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev, +- &cam->i2c_adapter, &info, NULL); ++ &cam->i2c_adapter, &info, NULL, 0); + if (cam->sensor == NULL) { + ret = -ENODEV; + goto out_smbus; +diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c +index 7333a9b..bfc2a47 100644 +--- a/drivers/media/video/davinci/vpfe_capture.c ++++ b/drivers/media/video/davinci/vpfe_capture.c +@@ -1987,7 +1987,7 @@ static __init int vpfe_probe(struct platform_device *pdev) + v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev, + i2c_adap, + &sdinfo->board_info, +- NULL); ++ NULL, 0); + if (vpfe_dev->sd[i]) { + v4l2_info(&vpfe_dev->v4l2_dev, + "v4l2 sub device %s registered\n", +diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c +index 193abab..d2228e0 100644 +--- a/drivers/media/video/davinci/vpif_capture.c ++++ b/drivers/media/video/davinci/vpif_capture.c +@@ -2014,7 +2014,7 @@ static __init int vpif_probe(struct platform_device *pdev) + v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, + i2c_adap, + &subdevdata->board_info, +- NULL); ++ NULL, 0); + + if (!vpif_obj.sd[i]) { + vpif_err("Error registering v4l2 subdevice\n"); +diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c +index 412c65d..060c049 100644 +--- a/drivers/media/video/davinci/vpif_display.c ++++ b/drivers/media/video/davinci/vpif_display.c +@@ -1555,7 +1555,7 @@ static __init int vpif_probe(struct platform_device *pdev) + vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev, + i2c_adap, + &subdevdata[i].board_info, +- NULL); ++ NULL, 0); + if (!vpif_obj.sd[i]) { + vpif_err("Error registering v4l2 subdevice\n"); + goto probe_subdev_out; +diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c +index 6651a6c..3d3b62d 100644 +--- a/drivers/media/video/ivtv/ivtv-i2c.c ++++ b/drivers/media/video/ivtv/ivtv-i2c.c +@@ -277,7 +277,7 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) + info.platform_data = &pdata; + + sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, &info, +- NULL); ++ NULL, 0); + } else { + sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, + adap, type, hw_addrs[idx], NULL); +diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c +index 2f50080..b237daa 100644 +--- a/drivers/media/video/s5p-fimc/fimc-capture.c ++++ b/drivers/media/video/s5p-fimc/fimc-capture.c +@@ -44,7 +44,7 @@ static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc, + return ERR_PTR(-ENOMEM); + + sd = v4l2_i2c_new_subdev_board(&vid_cap->v4l2_dev, i2c_adap, +- isp_info->board_info, NULL); ++ isp_info->board_info, NULL, 0); + if (!sd) { + v4l2_err(&vid_cap->v4l2_dev, "failed to acquire subdev\n"); + return NULL; +diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c +index 07cf0c6..c50f0f5 100644 +--- a/drivers/media/video/sh_vou.c ++++ b/drivers/media/video/sh_vou.c +@@ -1409,7 +1409,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev) + goto ereset; + + subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap, +- vou_pdata->board_info, NULL); ++ vou_pdata->board_info, NULL, 0); + if (!subdev) { + ret = -ENOMEM; + goto ei2cnd; +diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c +index 052bd6d..5afb601 100644 +--- a/drivers/media/video/soc_camera.c ++++ b/drivers/media/video/soc_camera.c +@@ -896,7 +896,7 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, + icl->board_info->platform_data = icd; + + subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, +- icl->board_info, NULL); ++ icl->board_info, NULL, 0); + if (!subdev) + goto ei2cnd; + +diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c +index e007e61..ffee794 100644 +--- a/drivers/media/video/v4l2-common.c ++++ b/drivers/media/video/v4l2-common.c +@@ -369,7 +369,7 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); + /* Load an i2c sub-device. */ + struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, struct i2c_board_info *info, +- const unsigned short *probe_addrs) ++ const unsigned short *probe_addrs, int enable_devnode) + { + struct v4l2_subdev *sd = NULL; + struct i2c_client *client; +@@ -399,9 +399,12 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, + if (!try_module_get(client->driver->driver.owner)) + goto error; + sd = i2c_get_clientdata(client); ++ if (!enable_devnode) ++ sd->flags &= ~V4L2_SUBDEV_FL_HAS_DEVNODE; + + /* Register with the v4l2_device which increases the module's + use count as well. */ ++ sd->initialized = 0; + if (v4l2_device_register_subdev(v4l2_dev, sd)) + sd = NULL; + /* Decrease the module use count to match the first try_module_get. */ +@@ -416,6 +419,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, + if (err && err != -ENOIOCTLCMD) { + v4l2_device_unregister_subdev(sd); + sd = NULL; ++ } else { ++ sd->initialized = 1; + } + } + +@@ -440,7 +445,8 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, + strlcpy(info.type, client_type, sizeof(info.type)); + info.addr = addr; + +- return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs); ++ return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs, ++ 0); + } + EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev); + +@@ -510,7 +516,8 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, + EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); + + struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, +- struct spi_master *master, struct spi_board_info *info) ++ struct spi_master *master, struct spi_board_info *info, ++ int enable_devnode) + { + struct v4l2_subdev *sd = NULL; + struct spi_device *spi = NULL; +@@ -529,6 +536,8 @@ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, + goto error; + + sd = spi_get_drvdata(spi); ++ if (!enable_devnode) ++ sd->flags &= ~V4L2_SUBDEV_FL_HAS_DEVNODE; + + /* Register with the v4l2_device which increases the module's + use count as well. */ +diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c +index 359e232..f22bd41 100644 +--- a/drivers/media/video/v4l2-dev.c ++++ b/drivers/media/video/v4l2-dev.c +@@ -408,13 +408,14 @@ static int get_index(struct video_device *vdev) + } + + /** +- * video_register_device - register video4linux devices ++ * __video_register_device - register video4linux devices + * @vdev: video device structure we want to register + * @type: type of device to register + * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... + * -1 == first free) + * @warn_if_nr_in_use: warn if the desired device node number + * was already in use and another number was chosen instead. ++ * @owner: module that owns the video device node + * + * The registration code assigns minor numbers and device node numbers + * based on the requested type and registers the new device node with +@@ -431,9 +432,11 @@ static int get_index(struct video_device *vdev) + * %VFL_TYPE_VBI - Vertical blank data (undecoded) + * + * %VFL_TYPE_RADIO - A radio card ++ * ++ * %VFL_TYPE_SUBDEV - A subdevice + */ +-static int __video_register_device(struct video_device *vdev, int type, int nr, +- int warn_if_nr_in_use) ++int __video_register_device(struct video_device *vdev, int type, int nr, ++ int warn_if_nr_in_use, struct module *owner) + { + int i = 0; + int ret; +@@ -466,6 +469,9 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, + case VFL_TYPE_RADIO: + name_base = "radio"; + break; ++ case VFL_TYPE_SUBDEV: ++ name_base = "v4l-subdev"; ++ break; + default: + printk(KERN_ERR "%s called with unknown type: %d\n", + __func__, type); +@@ -549,7 +555,7 @@ static int __video_register_device(struct video_device *vdev, int type, int nr, + goto cleanup; + } + vdev->cdev->ops = &v4l2_fops; +- vdev->cdev->owner = vdev->fops->owner; ++ vdev->cdev->owner = owner; + ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); + if (ret < 0) { + printk(KERN_ERR "%s: cdev_add failed\n", __func__); +@@ -598,18 +604,7 @@ cleanup: + vdev->minor = -1; + return ret; + } +- +-int video_register_device(struct video_device *vdev, int type, int nr) +-{ +- return __video_register_device(vdev, type, nr, 1); +-} +-EXPORT_SYMBOL(video_register_device); +- +-int video_register_device_no_warn(struct video_device *vdev, int type, int nr) +-{ +- return __video_register_device(vdev, type, nr, 0); +-} +-EXPORT_SYMBOL(video_register_device_no_warn); ++EXPORT_SYMBOL(__video_register_device); + + /** + * video_unregister_device - unregister a video4linux device +diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c +index 7fe6f92..97e84df 100644 +--- a/drivers/media/video/v4l2-device.c ++++ b/drivers/media/video/v4l2-device.c +@@ -117,24 +117,43 @@ EXPORT_SYMBOL_GPL(v4l2_device_unregister); + int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, + struct v4l2_subdev *sd) + { ++ struct video_device *vdev; + int err; + + /* Check for valid input */ + if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) + return -EINVAL; ++ + /* Warn if we apparently re-register a subdev */ + WARN_ON(sd->v4l2_dev != NULL); ++ + if (!try_module_get(sd->owner)) + return -ENODEV; ++ + /* This just returns 0 if either of the two args is NULL */ + err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler); + if (err) + return err; ++ + sd->v4l2_dev = v4l2_dev; + spin_lock(&v4l2_dev->lock); + list_add_tail(&sd->list, &v4l2_dev->subdevs); + spin_unlock(&v4l2_dev->lock); +- return 0; ++ ++ /* Register the device node. */ ++ vdev = &sd->devnode; ++ strlcpy(vdev->name, sd->name, sizeof(vdev->name)); ++ vdev->parent = v4l2_dev->dev; ++ vdev->fops = &v4l2_subdev_fops; ++ vdev->release = video_device_release_empty; ++ if (sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) { ++ err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1, ++ sd->owner); ++ if (err < 0) ++ v4l2_device_unregister_subdev(sd); ++ } ++ ++ return err; + } + EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); + +@@ -143,10 +162,13 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) + /* return if it isn't registered */ + if (sd == NULL || sd->v4l2_dev == NULL) + return; ++ + spin_lock(&sd->v4l2_dev->lock); + list_del(&sd->list); + spin_unlock(&sd->v4l2_dev->lock); + sd->v4l2_dev = NULL; ++ + module_put(sd->owner); ++ video_unregister_device(&sd->devnode); + } + EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); +diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c +index 1e01554..4137e4c 100644 +--- a/drivers/media/video/v4l2-ioctl.c ++++ b/drivers/media/video/v4l2-ioctl.c +@@ -413,7 +413,7 @@ static unsigned long cmd_input_size(unsigned int cmd) + } + } + +-static long ++long + __video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + v4l2_kioctl func) + { +diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c +new file mode 100644 +index 0000000..00bd4b1 +--- /dev/null ++++ b/drivers/media/video/v4l2-subdev.c +@@ -0,0 +1,66 @@ ++/* ++ * V4L2 subdevice support. ++ * ++ * Copyright (C) 2010 Nokia Corporation ++ * ++ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include <linux/types.h> ++#include <linux/ioctl.h> ++#include <linux/videodev2.h> ++ ++#include <media/v4l2-device.h> ++#include <media/v4l2-ioctl.h> ++ ++static int subdev_open(struct file *file) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); ++ ++ if (!sd->initialized) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++static int subdev_close(struct file *file) ++{ ++ return 0; ++} ++ ++static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) ++{ ++ switch (cmd) { ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ return 0; ++} ++ ++static long subdev_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return __video_usercopy(file, cmd, arg, subdev_do_ioctl); ++} ++ ++const struct v4l2_file_operations v4l2_subdev_fops = { ++ .owner = THIS_MODULE, ++ .open = subdev_open, ++ .unlocked_ioctl = subdev_ioctl, ++ .release = subdev_close, ++}; +diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h +index 565fb32..ef8965d 100644 +--- a/include/media/v4l2-common.h ++++ b/include/media/v4l2-common.h +@@ -146,7 +146,7 @@ struct i2c_board_info; + + struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, + struct i2c_adapter *adapter, struct i2c_board_info *info, +- const unsigned short *probe_addrs); ++ const unsigned short *probe_addrs, int enable_devnode); + + /* Initialize an v4l2_subdev with data from an i2c_client struct */ + void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, +@@ -179,7 +179,8 @@ struct spi_device; + /* Load an spi module and return an initialized v4l2_subdev struct. + The client_type argument is the name of the chip that's on the adapter. */ + struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, +- struct spi_master *master, struct spi_board_info *info); ++ struct spi_master *master, struct spi_board_info *info, ++ int enable_devnode); + + /* Initialize an v4l2_subdev with data from an spi_device struct */ + void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, +diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h +index 15802a0..4fe6831 100644 +--- a/include/media/v4l2-dev.h ++++ b/include/media/v4l2-dev.h +@@ -21,7 +21,8 @@ + #define VFL_TYPE_GRABBER 0 + #define VFL_TYPE_VBI 1 + #define VFL_TYPE_RADIO 2 +-#define VFL_TYPE_MAX 3 ++#define VFL_TYPE_SUBDEV 3 ++#define VFL_TYPE_MAX 4 + + struct v4l2_ioctl_callbacks; + struct video_device; +@@ -102,15 +103,26 @@ struct video_device + /* dev to video-device */ + #define to_video_device(cd) container_of(cd, struct video_device, dev) + ++int __must_check __video_register_device(struct video_device *vdev, int type, ++ int nr, int warn_if_nr_in_use, struct module *owner); ++ + /* Register video devices. Note that if video_register_device fails, + the release() callback of the video_device structure is *not* called, so + the caller is responsible for freeing any data. Usually that means that + you call video_device_release() on failure. */ +-int __must_check video_register_device(struct video_device *vdev, int type, int nr); ++static inline int __must_check video_register_device(struct video_device *vdev, ++ int type, int nr) ++{ ++ return __video_register_device(vdev, type, nr, 1, vdev->fops->owner); ++} + + /* Same as video_register_device, but no warning is issued if the desired + device node number was already in use. */ +-int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr); ++static inline int __must_check video_register_device_no_warn( ++ struct video_device *vdev, int type, int nr) ++{ ++ return __video_register_device(vdev, type, nr, 0, vdev->fops->owner); ++} + + /* Unregister video devices. Will do nothing if vdev == NULL or + video_is_registered() returns false. */ +diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h +index 06daa6e..abb64d0 100644 +--- a/include/media/v4l2-ioctl.h ++++ b/include/media/v4l2-ioctl.h +@@ -316,6 +316,9 @@ extern long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, + unsigned long arg); + #endif + ++extern long __video_usercopy(struct file *file, unsigned int cmd, ++ unsigned long arg, v4l2_kioctl func); ++ + /* Include support for obsoleted stuff */ + extern long video_usercopy(struct file *file, unsigned int cmd, + unsigned long arg, v4l2_kioctl func); +diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h +index b636444..de181db 100644 +--- a/include/media/v4l2-subdev.h ++++ b/include/media/v4l2-subdev.h +@@ -22,6 +22,7 @@ + #define _V4L2_SUBDEV_H + + #include <media/v4l2-common.h> ++#include <media/v4l2-dev.h> + #include <media/v4l2-mediabus.h> + + /* generic v4l2_device notify callback notification values */ +@@ -418,9 +419,11 @@ struct v4l2_subdev_ops { + #define V4L2_SUBDEV_NAME_SIZE 32 + + /* Set this flag if this subdev is a i2c device. */ +-#define V4L2_SUBDEV_FL_IS_I2C (1U << 0) ++#define V4L2_SUBDEV_FL_IS_I2C (1U << 0) + /* Set this flag if this subdev is a spi device. */ +-#define V4L2_SUBDEV_FL_IS_SPI (1U << 1) ++#define V4L2_SUBDEV_FL_IS_SPI (1U << 1) ++/* Set this flag if this subdev needs a device node. */ ++#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2) + + /* Each instance of a subdev driver should create this struct, either + stand-alone or embedded in a larger struct. +@@ -440,8 +443,16 @@ struct v4l2_subdev { + /* pointer to private data */ + void *dev_priv; + void *host_priv; ++ /* subdev device node */ ++ struct video_device devnode; ++ unsigned int initialized; + }; + ++#define vdev_to_v4l2_subdev(vdev) \ ++ container_of(vdev, struct v4l2_subdev, devnode) ++ ++extern const struct v4l2_file_operations v4l2_subdev_fops; ++ + static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p) + { + sd->dev_priv = p; +@@ -474,6 +485,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd, + sd->grp_id = 0; + sd->dev_priv = NULL; + sd->host_priv = NULL; ++ sd->initialized = 1; + } + + /* Call an ops of a v4l2_subdev, doing the right checks against +-- +1.6.6.1 + |