From 03519b7e7ea531f5425be9d9bfe5f114e80951a0 Mon Sep 17 00:00:00 2001 From: Qing Xu Date: Thu, 20 Jan 2011 05:19:40 -0300 Subject: [media] V4L: add enum_mbus_fsizes video operation Add enum_mbus_fsizes V4L2 subdevice video operation. Signed-off-by: Qing Xu Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/media/v4l2-subdev.h') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index daf1e57d9b26..d4d74f9f2ff2 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -271,6 +271,8 @@ struct v4l2_subdev_video_ops { struct v4l2_dv_timings *timings); int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index, enum v4l2_mbus_pixelcode *code); + int (*enum_mbus_fsizes)(struct v4l2_subdev *sd, + struct v4l2_frmsizeenum *fsize); int (*g_mbus_fmt)(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt); int (*try_mbus_fmt)(struct v4l2_subdev *sd, -- cgit v1.2.3 From 0070d91e5b5ae594116202ab7d62d8264830b1cd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 31 May 2010 05:33:06 -0300 Subject: [media] v4l: subdev: Don't require core operations There's no reason to require subdevices to implement the core operations. Remove the check for non-NULL core operations when initializing the subdev. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/media/v4l2-subdev.h') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index d4d74f9f2ff2..da16d2f4a00b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -481,8 +481,7 @@ static inline void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) { INIT_LIST_HEAD(&sd->list); - /* ops->core MUST be set */ - BUG_ON(!ops || !ops->core); + BUG_ON(!ops); sd->ops = ops; sd->v4l2_dev = NULL; sd->flags = 0; -- cgit v1.2.3 From 2096a5dcf9704f5a86ecba37169eb813aaf0431c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:38:49 -0300 Subject: [media] 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 Signed-off-by: Vimarsh Zutshi Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 16 ++++++++ drivers/media/video/Makefile | 2 +- drivers/media/video/v4l2-dev.c | 27 +++++-------- drivers/media/video/v4l2-device.c | 37 +++++++++++++++++ drivers/media/video/v4l2-subdev.c | 60 ++++++++++++++++++++++++++++ include/media/v4l2-dev.h | 18 +++++++-- include/media/v4l2-device.h | 6 +++ include/media/v4l2-subdev.h | 14 ++++++- 8 files changed, 158 insertions(+), 22 deletions(-) create mode 100644 drivers/media/video/v4l2-subdev.c (limited to 'include/media/v4l2-subdev.h') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index f22f35c271f3..8b358710b2f7 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -319,6 +319,22 @@ 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. + +Device nodes named v4l-subdevX can be created in /dev to access sub-devices +directly. If a sub-device supports direct userspace configuration it must set +the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered. + +After registering sub-devices, the v4l2_device driver can create device nodes +for all registered sub-devices marked with V4L2_SUBDEV_FL_HAS_DEVNODE by calling +v4l2_device_register_subdev_nodes(). Those device nodes will be automatically +removed when sub-devices are unregistered. + + I2C sub-device drivers ---------------------- diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index ac54652396e3..7ea65163090e 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/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 341764a3a990..abe04ef38066 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 @@ -435,9 +436,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; @@ -469,6 +472,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); @@ -552,7 +558,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__); @@ -597,18 +603,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 ce64fe16bc60..8c0ad8b372d8 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -124,16 +124,20 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, /* 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; + sd->v4l2_dev = v4l2_dev; if (sd->internal_ops && sd->internal_ops->registered) { err = sd->internal_ops->registered(sd); if (err) return err; } + /* 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) { @@ -141,24 +145,57 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, sd->internal_ops->unregistered(sd); return err; } + spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); + return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); +int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) +{ + struct video_device *vdev; + struct v4l2_subdev *sd; + int err; + + /* Register a device node for every subdev marked with the + * V4L2_SUBDEV_FL_HAS_DEVNODE flag. + */ + list_for_each_entry(sd, &v4l2_dev->subdevs, list) { + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) + continue; + + vdev = &sd->devnode; + strlcpy(vdev->name, sd->name, sizeof(vdev->name)); + vdev->v4l2_dev = v4l2_dev; + vdev->fops = &v4l2_subdev_fops; + vdev->release = video_device_release_empty; + err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1, + sd->owner); + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes); + 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); if (sd->internal_ops && sd->internal_ops->unregistered) sd->internal_ops->unregistered(sd); sd->v4l2_dev = NULL; + + video_unregister_device(&sd->devnode); module_put(sd->owner); } EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c new file mode 100644 index 000000000000..037aa28a5ed1 --- /dev/null +++ b/drivers/media/video/v4l2-subdev.c @@ -0,0 +1,60 @@ +/* + * V4L2 subdevice support. + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Laurent Pinchart + * + * 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 +#include +#include + +#include +#include + +static int subdev_open(struct file *file) +{ + 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-dev.h b/include/media/v4l2-dev.h index 15802a067a12..4fe6831b1851 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-device.h b/include/media/v4l2-device.h index b16f307d471a..78b11e5a6db7 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -96,6 +96,12 @@ int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, wasn't registered. In that case it will do nothing. */ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); +/* Register device nodes for all subdev of the v4l2 device that are marked with + * the V4L2_SUBDEV_FL_HAS_DEVNODE flag. + */ +int __must_check +v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev); + /* Iterate over all subdevs. */ #define v4l2_device_for_each_subdev(sd, v4l2_dev) \ list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index da16d2f4a00b..474ef009fd3d 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -22,6 +22,7 @@ #define _V4L2_SUBDEV_H #include +#include #include /* generic v4l2_device notify callback notification values */ @@ -431,9 +432,11 @@ struct v4l2_subdev_internal_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. @@ -455,8 +458,15 @@ struct v4l2_subdev { /* pointer to private data */ void *dev_priv; void *host_priv; + /* subdev device node */ + struct video_device devnode; }; +#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; -- cgit v1.2.3 From 3dd5ee0801ee10e5632b40fd8d0495417b32910a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:38:52 -0300 Subject: [media] v4l: subdev: Uninline the v4l2_subdev_init function The function isn't small or performance sensitive enough to be inlined. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-subdev.c | 41 ++++++++++++++++++++++++++------------- include/media/v4l2-subdev.h | 15 ++------------ 2 files changed, 30 insertions(+), 26 deletions(-) (limited to 'include/media/v4l2-subdev.h') diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 037aa28a5ed1..460b33697c9b 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -1,22 +1,23 @@ /* - * V4L2 subdevice support. + * V4L2 sub-device * - * Copyright (C) 2010 Nokia Corporation + * Copyright (C) 2010 Nokia Corporation * - * Contact: Laurent Pinchart + * Contact: Laurent Pinchart + * Sakari Ailus * - * 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 free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 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. + * 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 + * 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 @@ -58,3 +59,17 @@ const struct v4l2_file_operations v4l2_subdev_fops = { .unlocked_ioctl = subdev_ioctl, .release = subdev_close, }; + +void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) +{ + INIT_LIST_HEAD(&sd->list); + BUG_ON(!ops); + sd->ops = ops; + sd->v4l2_dev = NULL; + sd->flags = 0; + sd->name[0] = '\0'; + sd->grp_id = 0; + sd->dev_priv = NULL; + sd->host_priv = NULL; +} +EXPORT_SYMBOL(v4l2_subdev_init); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 474ef009fd3d..3276065022ef 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -487,19 +487,8 @@ static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd) return sd->host_priv; } -static inline void v4l2_subdev_init(struct v4l2_subdev *sd, - const struct v4l2_subdev_ops *ops) -{ - INIT_LIST_HEAD(&sd->list); - BUG_ON(!ops); - sd->ops = ops; - sd->v4l2_dev = NULL; - sd->flags = 0; - sd->name[0] = '\0'; - sd->grp_id = 0; - sd->dev_priv = NULL; - sd->host_priv = NULL; -} +void v4l2_subdev_init(struct v4l2_subdev *sd, + const struct v4l2_subdev_ops *ops); /* Call an ops of a v4l2_subdev, doing the right checks against NULL pointers. -- cgit v1.2.3 From 02adb1cc765b8c29dc83c6602bda19003cce62f1 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 3 Mar 2010 12:49:38 -0300 Subject: [media] v4l: subdev: Events support Provide v4l2_subdevs with v4l2_event support. Subdev drivers only need very little to support events. Signed-off-by: Sakari Ailus Signed-off-by: David Cohen Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 18 +++++++ drivers/media/video/v4l2-subdev.c | 78 +++++++++++++++++++++++++++- include/media/v4l2-subdev.h | 10 ++++ 3 files changed, 105 insertions(+), 1 deletion(-) (limited to 'include/media/v4l2-subdev.h') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 1feecfc59c3d..eb8479565dc4 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -350,6 +350,24 @@ VIDIOC_TRY_EXT_CTRLS controls can be also be accessed through one (or several) V4L2 device nodes. +VIDIOC_DQEVENT +VIDIOC_SUBSCRIBE_EVENT +VIDIOC_UNSUBSCRIBE_EVENT + + The events ioctls are identical to the ones defined in V4L2. They + behave identically, with the only exception that they deal only with + events generated by the sub-device. Depending on the driver, those + events can also be reported by one (or several) V4L2 device nodes. + + Sub-device drivers that want to use events need to set the + V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize + v4l2_subdev::nevents to events queue depth before registering the + sub-device. After registration events can be queued as usual on the + v4l2_subdev::devnode device node. + + To properly support events, the poll() file operation is also + implemented. + I2C sub-device drivers ---------------------- diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index da10430051c0..0c67f5a278fb 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -20,21 +20,66 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include #include +#include +#include #include #include #include #include +#include +#include static int subdev_open(struct file *file) { + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_fh *vfh; + int ret; + + if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) { + vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); + if (vfh == NULL) + return -ENOMEM; + + ret = v4l2_fh_init(vfh, vdev); + if (ret) + goto err; + + ret = v4l2_event_init(vfh); + if (ret) + goto err; + + ret = v4l2_event_alloc(vfh, sd->nevents); + if (ret) + goto err; + + v4l2_fh_add(vfh); + file->private_data = vfh; + } + return 0; + +err: + if (vfh != NULL) { + v4l2_fh_exit(vfh); + kfree(vfh); + } + + return ret; } static int subdev_close(struct file *file) { + struct v4l2_fh *vfh = file->private_data; + + if (vfh != NULL) { + v4l2_fh_del(vfh); + v4l2_fh_exit(vfh); + kfree(vfh); + } + return 0; } @@ -42,6 +87,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_fh *fh = file->private_data; switch (cmd) { case VIDIOC_QUERYCTRL: @@ -65,6 +111,18 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_TRY_EXT_CTRLS: return v4l2_subdev_try_ext_ctrls(sd, arg); + case VIDIOC_DQEVENT: + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) + return -ENOIOCTLCMD; + + return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); + + case VIDIOC_SUBSCRIBE_EVENT: + return v4l2_subdev_call(sd, core, subscribe_event, fh, arg); + + case VIDIOC_UNSUBSCRIBE_EVENT: + return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg); + default: return -ENOIOCTLCMD; } @@ -78,11 +136,29 @@ static long subdev_ioctl(struct file *file, unsigned int cmd, return video_usercopy(file, cmd, arg, subdev_do_ioctl); } +static unsigned int subdev_poll(struct file *file, poll_table *wait) +{ + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_fh *fh = file->private_data; + + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) + return POLLERR; + + poll_wait(file, &fh->events->wait, wait); + + if (v4l2_event_pending(fh)) + return POLLPRI; + + return 0; +} + const struct v4l2_file_operations v4l2_subdev_fops = { .owner = THIS_MODULE, .open = subdev_open, .unlocked_ioctl = subdev_ioctl, .release = subdev_close, + .poll = subdev_poll, }; void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 3276065022ef..0f9937be53d2 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -37,6 +37,8 @@ struct v4l2_device; struct v4l2_ctrl_handler; +struct v4l2_event_subscription; +struct v4l2_fh; struct v4l2_subdev; struct tuner_setup; @@ -161,6 +163,10 @@ struct v4l2_subdev_core_ops { int (*s_power)(struct v4l2_subdev *sd, int on); int (*interrupt_service_routine)(struct v4l2_subdev *sd, u32 status, bool *handled); + int (*subscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); + int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub); }; /* s_mode: switch the tuner to a specific tuner mode. Replacement of s_radio. @@ -437,6 +443,8 @@ struct v4l2_subdev_internal_ops { #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) +/* Set this flag if this subdev generates events. */ +#define V4L2_SUBDEV_FL_HAS_EVENTS (1U << 3) /* Each instance of a subdev driver should create this struct, either stand-alone or embedded in a larger struct. @@ -460,6 +468,8 @@ struct v4l2_subdev { void *host_priv; /* subdev device node */ struct video_device devnode; + /* number of events to be allocated on open */ + unsigned int nevents; }; #define vdev_to_v4l2_subdev(vdev) \ -- cgit v1.2.3 From 61f5db549dde43fb91a8b337f3a4096e4076c2d9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:40:08 -0300 Subject: [media] v4l: Make v4l2_subdev inherit from media_entity V4L2 subdevices are media entities. As such they need to inherit from (include) the media_entity structure. When registering/unregistering the subdevice, the media entity is automatically registered/unregistered. The entity is acquired on device open and released on device close. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/v4l2-framework.txt | 23 ++++++++++++++++++ drivers/media/video/v4l2-device.c | 36 ++++++++++++++++++++++++---- drivers/media/video/v4l2-subdev.c | 28 ++++++++++++++++++++-- include/media/v4l2-subdev.h | 6 +++++ 4 files changed, 87 insertions(+), 6 deletions(-) (limited to 'include/media/v4l2-subdev.h') diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 062708169def..77d96f4e3f50 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -268,6 +268,26 @@ A sub-device driver initializes the v4l2_subdev struct using: Afterwards you need to initialize subdev->name with a unique name and set the module owner. This is done for you if you use the i2c helper functions. +If integration with the media framework is needed, you must initialize the +media_entity struct embedded in the v4l2_subdev struct (entity field) by +calling media_entity_init(): + + struct media_pad *pads = &my_sd->pads; + int err; + + err = media_entity_init(&sd->entity, npads, pads, 0); + +The pads array must have been previously initialized. There is no need to +manually set the struct media_entity type and name fields, but the revision +field must be initialized if needed. + +A reference to the entity will be automatically acquired/released when the +subdev device node (if any) is opened/closed. + +Don't forget to cleanup the media entity before the sub-device is destroyed: + + media_entity_cleanup(&sd->entity); + A device (bridge) driver needs to register the v4l2_subdev with the v4l2_device: @@ -277,6 +297,9 @@ This can fail if the subdev module disappeared before it could be registered. After this function was called successfully the subdev->dev field points to the v4l2_device. +If the v4l2_device parent device has a non-NULL mdev field, the sub-device +entity will be automatically registered with the media device. + You can unregister a sub-device using: v4l2_device_unregister_subdev(sd); diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index cfbd8a38991d..a1afda352d08 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -118,8 +118,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) EXPORT_SYMBOL_GPL(v4l2_device_unregister); int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, - struct v4l2_subdev *sd) + struct v4l2_subdev *sd) { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity *entity = &sd->entity; +#endif int err; /* Check for valid input */ @@ -147,6 +150,19 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, return err; } +#if defined(CONFIG_MEDIA_CONTROLLER) + /* Register the entity. */ + if (v4l2_dev->mdev) { + err = media_device_register_entity(v4l2_dev->mdev, entity); + if (err < 0) { + if (sd->internal_ops && sd->internal_ops->unregistered) + sd->internal_ops->unregistered(sd); + module_put(sd->owner); + return err; + } + } +#endif + spin_lock(&v4l2_dev->lock); list_add_tail(&sd->list, &v4l2_dev->subdevs); spin_unlock(&v4l2_dev->lock); @@ -177,25 +193,37 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) sd->owner); if (err < 0) return err; +#if defined(CONFIG_MEDIA_CONTROLLER) + sd->entity.v4l.major = VIDEO_MAJOR; + sd->entity.v4l.minor = vdev->minor; +#endif } - return 0; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes); void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) { + struct v4l2_device *v4l2_dev; + /* return if it isn't registered */ if (sd == NULL || sd->v4l2_dev == NULL) return; - spin_lock(&sd->v4l2_dev->lock); + v4l2_dev = sd->v4l2_dev; + + spin_lock(&v4l2_dev->lock); list_del(&sd->list); - spin_unlock(&sd->v4l2_dev->lock); + spin_unlock(&v4l2_dev->lock); + if (sd->internal_ops && sd->internal_ops->unregistered) sd->internal_ops->unregistered(sd); sd->v4l2_dev = NULL; +#if defined(CONFIG_MEDIA_CONTROLLER) + if (v4l2_dev->mdev) + media_device_unregister_entity(&sd->entity); +#endif video_unregister_device(&sd->devnode); module_put(sd->owner); } diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 0c67f5a278fb..85573638aa1e 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -35,7 +35,10 @@ static int subdev_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *vfh; +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity *entity; +#endif + struct v4l2_fh *vfh = NULL; int ret; if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) { @@ -58,11 +61,20 @@ static int subdev_open(struct file *file) v4l2_fh_add(vfh); file->private_data = vfh; } - +#if defined(CONFIG_MEDIA_CONTROLLER) + if (sd->v4l2_dev->mdev) { + entity = media_entity_get(&sd->entity); + if (!entity) { + ret = -EBUSY; + goto err; + } + } +#endif return 0; err: if (vfh != NULL) { + v4l2_fh_del(vfh); v4l2_fh_exit(vfh); kfree(vfh); } @@ -72,8 +84,16 @@ err: static int subdev_close(struct file *file) { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct video_device *vdev = video_devdata(file); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); +#endif struct v4l2_fh *vfh = file->private_data; +#if defined(CONFIG_MEDIA_CONTROLLER) + if (sd->v4l2_dev->mdev) + media_entity_put(&sd->entity); +#endif if (vfh != NULL) { v4l2_fh_del(vfh); v4l2_fh_exit(vfh); @@ -172,5 +192,9 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops) sd->grp_id = 0; sd->dev_priv = NULL; sd->host_priv = NULL; +#if defined(CONFIG_MEDIA_CONTROLLER) + sd->entity.name = sd->name; + sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV; +#endif } EXPORT_SYMBOL(v4l2_subdev_init); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 0f9937be53d2..6f51ce4d7ee7 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -21,6 +21,7 @@ #ifndef _V4L2_SUBDEV_H #define _V4L2_SUBDEV_H +#include #include #include #include @@ -450,6 +451,9 @@ struct v4l2_subdev_internal_ops { stand-alone or embedded in a larger struct. */ struct v4l2_subdev { +#if defined(CONFIG_MEDIA_CONTROLLER) + struct media_entity entity; +#endif struct list_head list; struct module *owner; u32 flags; @@ -472,6 +476,8 @@ struct v4l2_subdev { unsigned int nevents; }; +#define media_entity_to_v4l2_subdev(ent) \ + container_of(ent, struct v4l2_subdev, entity) #define vdev_to_v4l2_subdev(vdev) \ container_of(vdev, struct v4l2_subdev, devnode) -- cgit v1.2.3 From 7cd5a16b22af7dc92190a60f336b6854a6fcb99d Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Fri, 21 May 2010 06:04:24 -0300 Subject: [media] v4l: Create v4l2 subdev file handle structure Used for storing subdev information per file handle and hold V4L2 file handle. Signed-off-by: Stanimir Varbanov Signed-off-by: Antti Koskipaa Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 9 +++++ drivers/media/video/v4l2-subdev.c | 85 ++++++++++++++++++++++++++------------- include/media/v4l2-subdev.h | 29 +++++++++++++ 3 files changed, 96 insertions(+), 27 deletions(-) (limited to 'include/media/v4l2-subdev.h') diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 2466f2b2ecfa..6995940b633a 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -53,6 +53,15 @@ config VIDEO_V4L2_COMMON depends on (I2C || I2C=n) && VIDEO_DEV default (I2C || I2C=n) && VIDEO_DEV +config VIDEO_V4L2_SUBDEV_API + bool "V4L2 sub-device userspace API (EXPERIMENTAL)" + depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL + ---help--- + Enables the V4L2 sub-device pad-level userspace API used to configure + video format, size and frame rate between hardware blocks. + + This API is mostly used by camera interfaces in embedded platforms. + # # DVB Core # diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 85573638aa1e..6cef6ad3c9ce 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -31,36 +31,66 @@ #include #include +static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) +{ +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + /* Allocate try format and crop in the same memory block */ + fh->try_fmt = kzalloc((sizeof(*fh->try_fmt) + sizeof(*fh->try_crop)) + * sd->entity.num_pads, GFP_KERNEL); + if (fh->try_fmt == NULL) + return -ENOMEM; + + fh->try_crop = (struct v4l2_rect *) + (fh->try_fmt + sd->entity.num_pads); +#endif + return 0; +} + +static void subdev_fh_free(struct v4l2_subdev_fh *fh) +{ +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + kfree(fh->try_fmt); + fh->try_fmt = NULL; + fh->try_crop = NULL; +#endif +} + static int subdev_open(struct file *file) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct v4l2_subdev_fh *subdev_fh; #if defined(CONFIG_MEDIA_CONTROLLER) struct media_entity *entity; #endif - struct v4l2_fh *vfh = NULL; int ret; - if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) { - vfh = kzalloc(sizeof(*vfh), GFP_KERNEL); - if (vfh == NULL) - return -ENOMEM; + subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL); + if (subdev_fh == NULL) + return -ENOMEM; - ret = v4l2_fh_init(vfh, vdev); - if (ret) - goto err; + ret = subdev_fh_init(subdev_fh, sd); + if (ret) { + kfree(subdev_fh); + return ret; + } + + ret = v4l2_fh_init(&subdev_fh->vfh, vdev); + if (ret) + goto err; - ret = v4l2_event_init(vfh); + if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) { + ret = v4l2_event_init(&subdev_fh->vfh); if (ret) goto err; - ret = v4l2_event_alloc(vfh, sd->nevents); + ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents); if (ret) goto err; - - v4l2_fh_add(vfh); - file->private_data = vfh; } + + v4l2_fh_add(&subdev_fh->vfh); + file->private_data = &subdev_fh->vfh; #if defined(CONFIG_MEDIA_CONTROLLER) if (sd->v4l2_dev->mdev) { entity = media_entity_get(&sd->entity); @@ -70,14 +100,14 @@ static int subdev_open(struct file *file) } } #endif + return 0; err: - if (vfh != NULL) { - v4l2_fh_del(vfh); - v4l2_fh_exit(vfh); - kfree(vfh); - } + v4l2_fh_del(&subdev_fh->vfh); + v4l2_fh_exit(&subdev_fh->vfh); + subdev_fh_free(subdev_fh); + kfree(subdev_fh); return ret; } @@ -89,16 +119,17 @@ static int subdev_close(struct file *file) struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); #endif struct v4l2_fh *vfh = file->private_data; + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); #if defined(CONFIG_MEDIA_CONTROLLER) if (sd->v4l2_dev->mdev) media_entity_put(&sd->entity); #endif - if (vfh != NULL) { - v4l2_fh_del(vfh); - v4l2_fh_exit(vfh); - kfree(vfh); - } + v4l2_fh_del(vfh); + v4l2_fh_exit(vfh); + subdev_fh_free(subdev_fh); + kfree(subdev_fh); + file->private_data = NULL; return 0; } @@ -107,7 +138,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); - struct v4l2_fh *fh = file->private_data; + struct v4l2_fh *vfh = file->private_data; switch (cmd) { case VIDIOC_QUERYCTRL: @@ -135,13 +166,13 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) return -ENOIOCTLCMD; - return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); + return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK); case VIDIOC_SUBSCRIBE_EVENT: - return v4l2_subdev_call(sd, core, subscribe_event, fh, arg); + return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg); case VIDIOC_UNSUBSCRIBE_EVENT: - return v4l2_subdev_call(sd, core, unsubscribe_event, fh, arg); + return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg); default: return -ENOIOCTLCMD; diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 6f51ce4d7ee7..72f49eb3002b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -24,6 +24,7 @@ #include #include #include +#include #include /* generic v4l2_device notify callback notification values */ @@ -481,6 +482,34 @@ struct v4l2_subdev { #define vdev_to_v4l2_subdev(vdev) \ container_of(vdev, struct v4l2_subdev, devnode) +/* + * Used for storing subdev information per file handle + */ +struct v4l2_subdev_fh { + struct v4l2_fh vfh; +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + struct v4l2_mbus_framefmt *try_fmt; + struct v4l2_rect *try_crop; +#endif +}; + +#define to_v4l2_subdev_fh(fh) \ + container_of(fh, struct v4l2_subdev_fh, vfh) + +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) +static inline struct v4l2_mbus_framefmt * +v4l2_subdev_get_try_format(struct v4l2_subdev_fh *fh, unsigned int pad) +{ + return &fh->try_fmt[pad]; +} + +static inline struct v4l2_rect * +v4l2_subdev_get_try_crop(struct v4l2_subdev_fh *fh, unsigned int pad) +{ + return &fh->try_crop[pad]; +} +#endif + extern const struct v4l2_file_operations v4l2_subdev_fops; static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p) -- cgit v1.2.3 From f0beea8f46142ea7abd7ed3f44fd0967c603fae0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 1 Aug 2010 19:05:09 -0300 Subject: [media] v4l: subdev: Add new file operations V4L2 sub-devices store pad formats and crop settings in the file handle. To let drivers initialize those settings properly, add an open operation that is called when the subdev is opened as well as a corresponding close operation. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/v4l2-subdev.c | 16 +++++++++++++--- include/media/v4l2-subdev.h | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'include/media/v4l2-subdev.h') diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 6cef6ad3c9ce..bc763db385df 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -61,7 +61,7 @@ static int subdev_open(struct file *file) struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct v4l2_subdev_fh *subdev_fh; #if defined(CONFIG_MEDIA_CONTROLLER) - struct media_entity *entity; + struct media_entity *entity = NULL; #endif int ret; @@ -101,9 +101,19 @@ static int subdev_open(struct file *file) } #endif + if (sd->internal_ops && sd->internal_ops->open) { + ret = sd->internal_ops->open(sd, subdev_fh); + if (ret < 0) + goto err; + } + return 0; err: +#if defined(CONFIG_MEDIA_CONTROLLER) + if (entity) + media_entity_put(entity); +#endif v4l2_fh_del(&subdev_fh->vfh); v4l2_fh_exit(&subdev_fh->vfh); subdev_fh_free(subdev_fh); @@ -114,13 +124,13 @@ err: static int subdev_close(struct file *file) { -#if defined(CONFIG_MEDIA_CONTROLLER) struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); -#endif struct v4l2_fh *vfh = file->private_data; struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); + if (sd->internal_ops && sd->internal_ops->close) + sd->internal_ops->close(sd, subdev_fh); #if defined(CONFIG_MEDIA_CONTROLLER) if (sd->v4l2_dev->mdev) media_entity_put(&sd->entity); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 72f49eb3002b..f5dddacf8499 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -42,6 +42,7 @@ struct v4l2_ctrl_handler; struct v4l2_event_subscription; struct v4l2_fh; struct v4l2_subdev; +struct v4l2_subdev_fh; struct tuner_setup; /* decode_vbi_line */ @@ -431,10 +432,16 @@ struct v4l2_subdev_ops { * * unregistered: called when this subdev is unregistered. When called the * v4l2_dev field is still set to the correct v4l2_device. + * + * open: called when the subdev device node is opened by an application. + * + * close: called when the subdev device node is closed. */ struct v4l2_subdev_internal_ops { int (*registered)(struct v4l2_subdev *sd); void (*unregistered)(struct v4l2_subdev *sd); + int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh); + int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh); }; #define V4L2_SUBDEV_NAME_SIZE 32 -- cgit v1.2.3 From eb08f35480869f7a82e9be1f19bc4575452e7f98 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 08:39:52 -0300 Subject: [media] v4l: v4l2_subdev pad-level operations Add a v4l2_subdev_pad_ops structure for the operations that need to be performed at the pad level such as format-related operations. Pad format-related operations use v4l2_mbus_framefmt instead of v4l2_format. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/media/v4l2-subdev.h') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index f5dddacf8499..d4d3653426a9 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -413,6 +413,9 @@ struct v4l2_subdev_ir_ops { struct v4l2_subdev_ir_parameters *params); }; +struct v4l2_subdev_pad_ops { +}; + struct v4l2_subdev_ops { const struct v4l2_subdev_core_ops *core; const struct v4l2_subdev_tuner_ops *tuner; @@ -421,6 +424,7 @@ struct v4l2_subdev_ops { const struct v4l2_subdev_vbi_ops *vbi; const struct v4l2_subdev_ir_ops *ir; const struct v4l2_subdev_sensor_ops *sensor; + const struct v4l2_subdev_pad_ops *pad; }; /* -- cgit v1.2.3 From 333c8b97785d5afd5085ba3720b4d259623290f6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 15 Mar 2010 20:26:04 -0300 Subject: [media] v4l: v4l2_subdev userspace format API Add a userspace API to get, set and enumerate the media format on a subdev pad. The format at the output of a subdev usually depends on the format at its input(s). The try format operation is thus not suitable for probing format at individual pads, as it can't modify the device state and thus can't remember the format tried at the input to compute the output format. To fix the problem, pass an extra argument to the get/set format operations to select the 'try' or 'active' format. The try format is used when probing the subdev. Setting the try format must not change the device configuration but can store data for later reuse. Data storage is provided at the file-handle level so applications probing the subdev concurently won't interfere with each other. The active format is used when configuring the subdev. It's identical to the format handled by the usual get/set operations. Signed-off-by: Laurent Pinchart Signed-off-by: Stanimir Varbanov Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/Makefile | 5 +- Documentation/DocBook/media-entities.tmpl | 16 + Documentation/DocBook/v4l/dev-subdev.xml | 280 +++ Documentation/DocBook/v4l/subdev-formats.xml | 2416 ++++++++++++++++++++ Documentation/DocBook/v4l/v4l2.xml | 4 + Documentation/DocBook/v4l/vidioc-streamon.xml | 9 + .../DocBook/v4l/vidioc-subdev-enum-frame-size.xml | 154 ++ .../DocBook/v4l/vidioc-subdev-enum-mbus-code.xml | 119 + Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml | 180 ++ drivers/media/video/v4l2-subdev.c | 49 + include/linux/Kbuild | 1 + include/linux/v4l2-subdev.h | 90 + include/media/v4l2-subdev.h | 10 + 13 files changed, 3332 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/v4l/dev-subdev.xml create mode 100644 Documentation/DocBook/v4l/subdev-formats.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml create mode 100644 include/linux/v4l2-subdev.h (limited to 'include/media/v4l2-subdev.h') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 8b6e00a71034..2deb069aedf1 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -53,7 +53,10 @@ MAN := $(patsubst %.xml, %.9, $(BOOKS)) mandocs: $(MAN) build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \ - cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/ + cp $(srctree)/Documentation/DocBook/dvb/*.png \ + $(srctree)/Documentation/DocBook/v4l/*.gif \ + $(srctree)/Documentation/DocBook/v4l/*.png \ + $(objtree)/Documentation/DocBook/media/ xmldoclinks: ifneq ($(objtree),$(srctree)) diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index 121db1549244..dbb9cb2e1ec6 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -86,6 +86,10 @@ VIDIOC_S_PRIORITY"> VIDIOC_S_STD"> VIDIOC_S_TUNER"> +VIDIOC_SUBDEV_ENUM_FRAME_SIZE"> +VIDIOC_SUBDEV_ENUM_MBUS_CODE"> +VIDIOC_SUBDEV_G_FMT"> +VIDIOC_SUBDEV_S_FMT"> VIDIOC_TRY_ENCODER_CMD"> VIDIOC_TRY_EXT_CTRLS"> VIDIOC_TRY_FMT"> @@ -107,6 +111,7 @@ v4l2_field"> v4l2_frmivaltypes"> v4l2_frmsizetypes"> +v4l2_mbus_pixelcode"> v4l2_memory"> v4l2_mpeg_audio_ac3_bitrate"> v4l2_mpeg_audio_crc"> @@ -130,6 +135,7 @@ v4l2_mpeg_video_encoding"> v4l2_power_line_frequency"> v4l2_priority"> +v4l2_subdev_format_whence"> v4l2_tuner_type"> v4l2_preemphasis"> @@ -172,6 +178,7 @@ v4l2_hw_freq_seek"> v4l2_input"> v4l2_jpegcompression"> +v4l2_mbus_framefmt"> v4l2_modulator"> v4l2_mpeg_vbi_fmt_ivtv"> v4l2_output"> @@ -186,6 +193,9 @@ v4l2_sliced_vbi_cap"> v4l2_sliced_vbi_data"> v4l2_sliced_vbi_format"> +v4l2_subdev_frame_size_enum"> +v4l2_subdev_format"> +v4l2_subdev_mbus_code_enum"> v4l2_standard"> v4l2_streamparm"> v4l2_timecode"> @@ -215,6 +225,7 @@ ENXIO error code"> EMFILE error code"> EPERM error code"> +EPIPE error code"> ERANGE error code"> @@ -234,6 +245,7 @@ + @@ -319,6 +331,10 @@ + + + + diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml new file mode 100644 index 000000000000..fc62e65f45ef --- /dev/null +++ b/Documentation/DocBook/v4l/dev-subdev.xml @@ -0,0 +1,280 @@ + Sub-device Interface + + + Experimental + This is an experimental + interface and may change in the future. + + + The complex nature of V4L2 devices, where hardware is often made of + several integrated circuits that need to interact with each other in a + controlled way, leads to complex V4L2 drivers. The drivers usually reflect + the hardware model in software, and model the different hardware components + as software blocks called sub-devices. + + V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver + implements the media device API, they will automatically inherit from media + entities. Applications will be able to enumerate the sub-devices and discover + the hardware topology using the media entities, pads and links enumeration + API. + + In addition to make sub-devices discoverable, drivers can also choose + to make them directly configurable by applications. When both the sub-device + driver and the V4L2 device driver support this, sub-devices will feature a + character device node on which ioctls can be called to + + query, read and write sub-devices controls + subscribe and unsubscribe to events and retrieve them + negotiate image formats on individual pads + + + + Sub-device character device nodes, conventionally named + /dev/v4l-subdev*, use major number 81. + +
+ Controls + Most V4L2 controls are implemented by sub-device hardware. Drivers + usually merge all controls and expose them through video device nodes. + Applications can control all sub-devices through a single interface. + + Complex devices sometimes implement the same control in different + pieces of hardware. This situation is common in embedded platforms, where + both sensors and image processing hardware implement identical functions, + such as contrast adjustment, white balance or faulty pixels correction. As + the V4L2 controls API doesn't support several identical controls in a single + device, all but one of the identical controls are hidden. + + Applications can access those hidden controls through the sub-device + node with the V4L2 control API described in . The + ioctls behave identically as when issued on V4L2 device nodes, with the + exception that they deal only with controls implemented in the sub-device. + + + Depending on the driver, those controls might also be exposed through + one (or several) V4L2 device nodes. +
+ +
+ Events + V4L2 sub-devices can notify applications of events as described in + . The API behaves identically as when used on V4L2 + device nodes, with the exception that it only deals with events generated by + the sub-device. Depending on the driver, those events might also be reported + on one (or several) V4L2 device nodes. +
+ +
+ Pad-level Formats + + Pad-level formats are only applicable to very complex device that + need to expose low-level format configuration to user space. Generic V4L2 + applications do not need to use the API described in + this section. + + For the purpose of this section, the term + format means the combination of media bus data + format, frame width and frame height. + + Image formats are typically negotiated on video capture and output + devices using the cropping and scaling ioctls. + The driver is responsible for configuring every block in the video pipeline + according to the requested format at the pipeline input and/or + output. + + For complex devices, such as often found in embedded systems, + identical image sizes at the output of a pipeline can be achieved using + different hardware configurations. One such exemple is shown on + , where + image scaling can be performed on both the video sensor and the host image + processing hardware. + +
+ Image Format Negotation on Pipelines + + + + + + + + + High quality and high speed pipeline configuration + + +
+ + The sensor scaler is usually of less quality than the host scaler, but + scaling on the sensor is required to achieve higher frame rates. Depending + on the use case (quality vs. speed), the pipeline must be configured + differently. Applications need to configure the formats at every point in + the pipeline explicitly. + + Drivers that implement the media + API can expose pad-level image format configuration to applications. + When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and + &VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis. + + Applications are responsible for configuring coherent parameters on + the whole pipeline and making sure that connected pads have compatible + formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON; + time, and an &EPIPE; is then returned if the configuration is + invalid. + + Pad-level image format configuration support can be tested by calling + the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL; + pad-level format configuration is not supported by the sub-device. + +
+ Format Negotiation + + Acceptable formats on pads can (and usually do) depend on a number + of external parameters, such as formats on other pads, active links, or + even controls. Finding a combination of formats on all pads in a video + pipeline, acceptable to both application and driver, can't rely on formats + enumeration only. A format negotiation mechanism is required. + + Central to the format negotiation mechanism are the get/set format + operations. When called with the which argument + set to V4L2_SUBDEV_FORMAT_TRY, the + &VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of + formats parameters that are not connected to the hardware configuration. + Modifying those 'try' formats leaves the device state untouched (this + applies to both the software state stored in the driver and the hardware + state stored in the device itself). + + While not kept as part of the device state, try formats are stored + in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return + the last try format set on the same sub-device file + handle. Several applications querying the same sub-device at + the same time will thus not interact with each other. + + To find out whether a particular format is supported by the device, + applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if + needed, change the requested format based on + device requirements and return the possibly modified value. Applications + can then choose to try a different format or accept the returned value and + continue. + + Formats returned by the driver during a negotiation iteration are + guaranteed to be supported by the device. In particular, drivers guarantee + that a returned format will not be further changed if passed to an + &VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as + formats on other pads or links' configuration are not changed). + + Drivers automatically propagate formats inside sub-devices. When a + try or active format is set on a pad, corresponding formats on other pads + of the same sub-device can be modified by the driver. Drivers are free to + modify formats as required by the device. However, they should comply with + the following rules when possible: + + Formats should be propagated from sink pads to source pads. + Modifying a format on a source pad should not modify the format on any + sink pad. + Sub-devices that scale frames using variable scaling factors + should reset the scale factors to default values when sink pads formats + are modified. If the 1:1 scaling ratio is supported, this means that + source pads formats should be reset to the sink pads formats. + + + + Formats are not propagated across links, as that would involve + propagating them from one sub-device file handle to another. Applications + must then take care to configure both ends of every link explicitly with + compatible formats. Identical formats on the two ends of a link are + guaranteed to be compatible. Drivers are free to accept different formats + matching device requirements as being compatible. + + + shows a sample configuration sequence for the pipeline described in + (table + columns list entity names and pad numbers). + + + Sample Pipeline Configuration + + + + + + + + + + + Sensor/0 + Frontend/0 + Frontend/1 + Scaler/0 + Scaler/1 + + + + + Initial state + 2048x1536 + - + - + - + - + + + Configure frontend input + 2048x1536 + 2048x1536 + 2046x1534 + - + - + + + Configure scaler input + 2048x1536 + 2048x1536 + 2046x1534 + 2046x1534 + 2046x1534 + + + Configure scaler output + 2048x1536 + 2048x1536 + 2046x1534 + 2046x1534 + 1280x960 + + + +
+ + + + Initial state. The sensor output is set to its native 3MP + resolution. Resolutions on the host frontend and scaler input and output + pads are undefined. + The application configures the frontend input pad resolution to + 2048x1536. The driver propagates the format to the frontend output pad. + Note that the propagated output format can be different, as in this case, + than the input format, as the hardware might need to crop pixels (for + instance when converting a Bayer filter pattern to RGB or YUV). + The application configures the scaler input pad resolution to + 2046x1534 to match the frontend output resolution. The driver propagates + the format to the scaler output pad. + The application configures the scaler output pad resolution to + 1280x960. + + + + When satisfied with the try results, applications can set the active + formats by setting the which argument to + V4L2_SUBDEV_FORMAT_TRY. Active formats are changed + exactly as try formats by drivers. To avoid modifying the hardware state + during format negotiation, applications should negotiate try formats first + and then modify the active settings using the try formats returned during + the last negotiation iteration. This guarantees that the active format + will be applied as-is by the driver without being modified. + +
+ +
+ + &sub-subdev-formats; diff --git a/Documentation/DocBook/v4l/subdev-formats.xml b/Documentation/DocBook/v4l/subdev-formats.xml new file mode 100644 index 000000000000..0cae57207006 --- /dev/null +++ b/Documentation/DocBook/v4l/subdev-formats.xml @@ -0,0 +1,2416 @@ +
+ Media Bus Formats + + + struct <structname>v4l2_mbus_framefmt</structname> + + &cs-str; + + + __u32 + width + Image width, in pixels. + + + __u32 + height + Image height, in pixels. + + + __u32 + code + Format code, from &v4l2-mbus-pixelcode;. + + + __u32 + field + Field order, from &v4l2-field;. See + for details. + + + __u32 + colorspace + Image colorspace, from &v4l2-colorspace;. See + for details. + + + __u32 + reserved[7] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+ +
+ Media Bus Pixel Codes + + The media bus pixel codes describe image formats as flowing over + physical busses (both between separate physical components and inside SoC + devices). This should not be confused with the V4L2 pixel formats that + describe, using four character codes, image formats as stored in memory. + + + While there is a relationship between image formats on busses and + image formats in memory (a raw Bayer image won't be magically converted to + JPEG just by storing it to memory), there is no one-to-one correspondance + between them. + +
+ Packed RGB Formats + + Those formats transfer pixel data as red, green and blue components. + The format code is made of the following information. + + The red, green and blue components order code, as encoded in a + pixel sample. Possible values are RGB and BGR. + The number of bits per component, for each component. The values + can be different for all components. Common values are 555 and 565. + + The number of bus samples per pixel. Pixels that are wider than + the bus width must be transferred in multiple samples. Common values are + 1 and 2. + The bus width. + For formats where the total number of bits per pixel is smaller + than the number of bus samples per pixel times the bus width, a padding + value stating if the bytes are padded in their most high order bits + (PADHI) or low order bits (PADLO). + For formats where the number of bus samples per pixel is larger + than 1, an endianness value stating if the pixel is transferred MSB first + (BE) or LSB first (LE). + + + + For instance, a format where pixels are encoded as 5-bits red, 5-bits + green and 5-bit blue values padded on the high bit, transferred as 2 8-bit + samples per pixel with the most significant bits (padding, red and half of + the green value) transferred first will be named + V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE. + + + The following tables list existing packet RGB formats. + + + RGB formats + + + + + + + + + + + + + + + + Identifier + Code + + Data organization + + + + + Bit + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + + V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE + 0x1001 + + 0 + 0 + 0 + 0 + r3 + r2 + r1 + r0 + + + + + + g3 + g2 + g1 + g0 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE + 0x1002 + + g3 + g2 + g1 + g0 + b3 + b2 + b1 + b0 + + + + + + 0 + 0 + 0 + 0 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE + 0x1003 + + 0 + r4 + r3 + r2 + r1 + r0 + g4 + g3 + + + + + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE + 0x1004 + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + + + + 0 + r4 + r3 + r2 + r1 + r0 + g4 + g3 + + + V4L2_MBUS_FMT_BGR565_2X8_BE + 0x1005 + + b4 + b3 + b2 + b1 + b0 + g5 + g4 + g3 + + + + + + g2 + g1 + g0 + r4 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_BGR565_2X8_LE + 0x1006 + + g2 + g1 + g0 + r4 + r3 + r2 + r1 + r0 + + + + + + b4 + b3 + b2 + b1 + b0 + g5 + g4 + g3 + + + V4L2_MBUS_FMT_RGB565_2X8_BE + 0x1007 + + r4 + r3 + r2 + r1 + r0 + g5 + g4 + g3 + + + + + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_RGB565_2X8_LE + 0x1008 + + g2 + g1 + g0 + b4 + b3 + b2 + b1 + b0 + + + + + + r4 + r3 + r2 + r1 + r0 + g5 + g4 + g3 + + + +
+
+ +
+ Bayer Formats + + Those formats transfer pixel data as red, green and blue components. + The format code is made of the following information. + + The red, green and blue components order code, as encoded in a + pixel sample. The possible values are shown in . + The number of bits per pixel component. All components are + transferred on the same number of bits. Common values are 8, 10 and 12. + + If the pixel components are DPCM-compressed, a mention of the + DPCM compression and the number of bits per compressed pixel component. + + The number of bus samples per pixel. Pixels that are wider than + the bus width must be transferred in multiple samples. Common values are + 1 and 2. + The bus width. + For formats where the total number of bits per pixel is smaller + than the number of bus samples per pixel times the bus width, a padding + value stating if the bytes are padded in their most high order bits + (PADHI) or low order bits (PADLO). + For formats where the number of bus samples per pixel is larger + than 1, an endianness value stating if the pixel is transferred MSB first + (BE) or LSB first (LE). + + + + For instance, a format with uncompressed 10-bit Bayer components + arranged in a red, green, green, blue pattern transferred as 2 8-bit + samples per pixel with the least significant bits transferred first will + be named V4L2_MBUS_FMT_SRGGB10_2X8_PADHI_LE. + + +
+ Bayer Patterns + + + + + + + + + Bayer filter color patterns + + +
+ + The following table lists existing packet Bayer formats. The data + organization is given as an example for the first pixel only. + + + Bayer Formats + + + + + + + + + + + + + + + + + + + + Identifier + Code + + Data organization + + + + + Bit + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + + V4L2_MBUS_FMT_SBGGR8_1X8 + 0x3001 + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SGRBG8_1X8 + 0x3002 + + - + - + - + - + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 + 0x300b + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 + 0x300c + + - + - + - + - + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 + 0x3009 + + - + - + - + - + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 + 0x300d + + - + - + - + - + r7 + r6 + r5 + r4 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE + 0x3003 + + - + - + - + - + 0 + 0 + 0 + 0 + 0 + 0 + b9 + b8 + + + + + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE + 0x3004 + + - + - + - + - + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + + + + - + - + - + - + 0 + 0 + 0 + 0 + 0 + 0 + b9 + b8 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE + 0x3005 + + - + - + - + - + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + + + + + + - + - + - + - + b1 + b0 + 0 + 0 + 0 + 0 + 0 + 0 + + + V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE + 0x3006 + + - + - + - + - + b1 + b0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + - + - + - + - + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + + + V4L2_MBUS_FMT_SBGGR10_1X10 + 0x3007 + + - + - + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + V4L2_MBUS_FMT_SGBRG10_1X10 + 0x300e + + - + - + g9 + g8 + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SGRBG10_1X10 + 0x300a + + - + - + g9 + g8 + g7 + g6 + g5 + g4 + g3 + g2 + g1 + g0 + + + V4L2_MBUS_FMT_SRGGB10_1X10 + 0x300f + + - + - + r9 + r8 + r7 + r6 + r5 + r4 + r3 + r2 + r1 + r0 + + + V4L2_MBUS_FMT_SBGGR12_1X12 + 0x3008 + + b11 + b10 + b9 + b8 + b7 + b6 + b5 + b4 + b3 + b2 + b1 + b0 + + + +
+
+ +
+ Packed YUV Formats + + Those data formats transfer pixel data as (possibly downsampled) Y, U + and V components. The format code is made of the following information. + + The Y, U and V components order code, as transferred on the + bus. Possible values are YUYV, UYVY, YVYU and VYUY. + The number of bits per pixel component. All components are + transferred on the same number of bits. Common values are 8, 10 and 12. + + The number of bus samples per pixel. Pixels that are wider than + the bus width must be transferred in multiple samples. Common values are + 1, 1.5 (encoded as 1_5) and 2. + The bus width. When the bus width is larger than the number of + bits per pixel component, several components are packed in a single bus + sample. The components are ordered as specified by the order code, with + components on the left of the code transferred in the high order bits. + Common values are 8 and 16. + + + + + For instance, a format where pixels are encoded as 8-bit YUV values + downsampled to 4:2:2 and transferred as 2 8-bit bus samples per pixel in the + U, Y, V, Y order will be named V4L2_MBUS_FMT_UYVY8_2X8. + + + The following table lisst existing packet YUV formats. + + + YUV Formats + + + + + + + + + + + + + + + + + + + + + + + + + + + + Identifier + Code + + Data organization + + + + + Bit + 19 + 18 + 17 + 16 + 15 + 14 + 13 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0 + + + + + V4L2_MBUS_FMT_Y8_1X8 + 0x2001 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_UYVY8_1_5X8 + 0x2002 + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_VYUY8_1_5X8 + 0x2003 + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV8_1_5X8 + 0x2004 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU8_1_5X8 + 0x2005 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_UYVY8_2X8 + 0x2006 + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_VYUY8_2X8 + 0x2007 + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV8_2X8 + 0x2008 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU8_2X8 + 0x2009 + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_Y10_1X10 + 0x200a + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV10_2X10 + 0x200b + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU10_2X10 + 0x200c + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + - + - + - + - + - + - + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + - + - + - + - + - + - + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_UYVY8_1X16 + 0x200f + + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_VYUY8_1X16 + 0x2010 + + - + - + - + - + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + + + + - + - + - + - + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + + + V4L2_MBUS_FMT_YUYV8_1X16 + 0x2011 + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU8_1X16 + 0x2012 + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + - + - + - + - + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + V4L2_MBUS_FMT_YUYV10_1X20 + 0x200d + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + + + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + V4L2_MBUS_FMT_YVYU10_1X20 + 0x200e + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + v9 + v8 + v7 + v6 + v5 + v4 + v3 + v2 + v1 + v0 + + + + + + y9 + y8 + y7 + y6 + y5 + y4 + y3 + y2 + y1 + y0 + u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + + + +
+
+
+
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 7859d7d9da39..2ada2f86bb54 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -439,6 +439,7 @@ and discussions on the V4L mailing list.
&sub-dev-radio;
&sub-dev-rds;
&sub-dev-event;
+
&sub-dev-subdev;
@@ -506,6 +507,9 @@ and discussions on the V4L mailing list. &sub-reqbufs; &sub-s-hw-freq-seek; &sub-streamon; + &sub-subdev-enum-frame-size; + &sub-subdev-enum-mbus-code; + &sub-subdev-g-fmt; &sub-subscribe-event; &sub-mmap; diff --git a/Documentation/DocBook/v4l/vidioc-streamon.xml b/Documentation/DocBook/v4l/vidioc-streamon.xml index e42bff1f2c0a..75ed39bf4d2b 100644 --- a/Documentation/DocBook/v4l/vidioc-streamon.xml +++ b/Documentation/DocBook/v4l/vidioc-streamon.xml @@ -93,6 +93,15 @@ synchronize with other events. been allocated (memory mapping) or enqueued (output) yet. + + EPIPE + + The driver implements pad-level format configuration and + the pipeline configuration is invalid. + + + diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml new file mode 100644 index 000000000000..79ce42b7c60c --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml @@ -0,0 +1,154 @@ + + + ioctl VIDIOC_SUBDEV_ENUM_FRAME_SIZE + &manvol; + + + + VIDIOC_SUBDEV_ENUM_FRAME_SIZE + Enumerate media bus frame sizes + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_frame_size_enum * + argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_ENUM_FRAME_SIZE + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + This ioctl allows applications to enumerate all frame sizes + supported by a sub-device on the given pad for the given media bus format. + Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE; + ioctl. + + To enumerate frame sizes applications initialize the + pad, code and + index fields of the + &v4l2-subdev-mbus-code-enum; and call the + VIDIOC_SUBDEV_ENUM_FRAME_SIZE ioctl with a pointer to + the structure. Drivers fill the minimum and maximum frame sizes or return + an &EINVAL; if one of the input parameters is invalid. + + Sub-devices that only support discrete frame sizes (such as most + sensors) will return one or more frame sizes with identical minimum and + maximum values. + + Not all possible sizes in given [minimum, maximum] ranges need to be + supported. For instance, a scaler that uses a fixed-point scaling ratio + might not be able to produce every frame size between the minimum and + maximum values. Applications must use the &VIDIOC-SUBDEV-S-FMT; ioctl to + try the sub-device for an exact supported frame size. + + Available frame sizes may depend on the current 'try' formats at other + pads of the sub-device, as well as on the current active links and the + current values of V4L2 controls. See &VIDIOC-SUBDEV-G-FMT; for more + information about try formats. + + + struct <structname>v4l2_subdev_frame_size_enum</structname> + + &cs-str; + + + __u32 + index + Number of the format in the enumeration, set by the + application. + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + code + The media bus format code, as defined in + . + + + __u32 + min_width + Minimum frame width, in pixels. + + + __u32 + max_width + Maximum frame width, in pixels. + + + __u32 + min_height + Minimum frame height, in pixels. + + + __u32 + max_height + Maximum frame height, in pixels. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-subdev-frame-size-enum; pad + references a non-existing pad, the code is + invalid for the given pad or the index + field is out of bounds. + + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml new file mode 100644 index 000000000000..a6b3432449f6 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml @@ -0,0 +1,119 @@ + + + ioctl VIDIOC_SUBDEV_ENUM_MBUS_CODE + &manvol; + + + + VIDIOC_SUBDEV_ENUM_MBUS_CODE + Enumerate media bus formats + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_mbus_code_enum * + argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_ENUM_MBUS_CODE + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + To enumerate media bus formats available at a given sub-device pad + applications initialize the pad and + index fields of &v4l2-subdev-mbus-code-enum; and + call the VIDIOC_SUBDEV_ENUM_MBUS_CODE ioctl with a + pointer to this structure. Drivers fill the rest of the structure or return + an &EINVAL; if either the pad or + index are invalid. All media bus formats are + enumerable by beginning at index zero and incrementing by one until + EINVAL is returned. + + Available media bus formats may depend on the current 'try' formats + at other pads of the sub-device, as well as on the current active links. See + &VIDIOC-SUBDEV-G-FMT; for more information about the try formats. + + + struct <structname>v4l2_subdev_mbus_code_enum</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + index + Number of the format in the enumeration, set by the + application. + + + __u32 + code + The media bus format code, as defined in + . + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-subdev-mbus-code-enum; pad + references a non-existing pad, or the index + field is out of bounds. + + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml new file mode 100644 index 000000000000..f367c570c530 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml @@ -0,0 +1,180 @@ + + + ioctl VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT + &manvol; + + + + VIDIOC_SUBDEV_G_FMT + VIDIOC_SUBDEV_S_FMT + Get or set the data format on a subdev pad + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_format *argp + + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + These ioctls are used to negotiate the frame format at specific + subdev pads in the image pipeline. + + To retrieve the current format applications set the + pad field of a &v4l2-subdev-format; to the + desired pad number as reported by the media API and the + which field to + V4L2_SUBDEV_FORMAT_ACTIVE. When they call the + VIDIOC_SUBDEV_G_FMT ioctl with a pointer to this + structure the driver fills the members of the format + field. + + To change the current format applications set both the + pad and which fields + and all members of the format field. When they + call the VIDIOC_SUBDEV_S_FMT ioctl with a pointer to this + structure the driver verifies the requested format, adjusts it based on the + hardware capabilities and configures the device. Upon return the + &v4l2-subdev-format; contains the current format as would be returned by a + VIDIOC_SUBDEV_G_FMT call. + + Applications can query the device capabilities by setting the + which to + V4L2_SUBDEV_FORMAT_TRY. When set, 'try' formats are not + applied to the device by the driver, but are changed exactly as active + formats and stored in the sub-device file handle. Two applications querying + the same sub-device would thus not interact with each other. + + For instance, to try a format at the output pad of a sub-device, + applications would first set the try format at the sub-device input with the + VIDIOC_SUBDEV_S_FMT ioctl. They would then either + retrieve the default format at the output pad with the + VIDIOC_SUBDEV_G_FMT ioctl, or set the desired output + pad format with the VIDIOC_SUBDEV_S_FMT ioctl and check + the returned value. + + Try formats do not depend on active formats, but can depend on the + current links configuration or sub-device controls value. For instance, a + low-pass noise filter might crop pixels at the frame boundaries, modifying + its output frame size. + + Drivers must not return an error solely because the requested format + doesn't match the device capabilities. They must instead modify the format + to match what the hardware can provide. The modified format should be as + close as possible to the original request. + + + struct <structname>v4l2_subdev_format</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + which + Format to modified, from &v4l2-subdev-format-whence;. + + + &v4l2-mbus-framefmt; + format + Definition of an image format, see for details. + + + __u32 + reserved[8] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+ + + enum <structname>v4l2_subdev_format_whence</structname> + + &cs-def; + + + V4L2_SUBDEV_FORMAT_TRY + 0 + Try formats, used for querying device capabilities. + + + V4L2_SUBDEV_FORMAT_ACTIVE + 1 + Active formats, applied to the hardware. + + + +
+
+ + + &return-value; + + + + EBUSY + + The format can't be changed because the pad is currently busy. + This can be caused, for instance, by an active video stream on the + pad. The ioctl must not be retried without performing another action + to fix the problem first. Only returned by + VIDIOC_SUBDEV_S_FMT + + + + EINVAL + + The &v4l2-subdev-format; pad + references a non-existing pad, or the which + field references a non-existing format. + + + + +
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index bc763db385df..207cc5cceb29 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -149,6 +149,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct v4l2_fh *vfh = file->private_data; +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); +#endif switch (cmd) { case VIDIOC_QUERYCTRL: @@ -183,7 +186,53 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_UNSUBSCRIBE_EVENT: return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg); +#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + case VIDIOC_SUBDEV_G_FMT: { + struct v4l2_subdev_format *format = arg; + + if (format->which != V4L2_SUBDEV_FORMAT_TRY && + format->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (format->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format); + } + + case VIDIOC_SUBDEV_S_FMT: { + struct v4l2_subdev_format *format = arg; + + if (format->which != V4L2_SUBDEV_FORMAT_TRY && + format->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (format->pad >= sd->entity.num_pads) + return -EINVAL; + return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format); + } + + case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { + struct v4l2_subdev_mbus_code_enum *code = arg; + + if (code->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh, + code); + } + + case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: { + struct v4l2_subdev_frame_size_enum *fse = arg; + + if (fse->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh, + fse); + } +#endif default: return -ENOIOCTLCMD; } diff --git a/include/linux/Kbuild b/include/linux/Kbuild index c33f22a6a404..43918a34db9f 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -372,6 +372,7 @@ header-y += usbdevice_fs.h header-y += utime.h header-y += utsname.h header-y += v4l2-mediabus.h +header-y += v4l2-subdev.h header-y += veth.h header-y += vhost.h header-y += videodev2.h diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h new file mode 100644 index 000000000000..8dbb44873821 --- /dev/null +++ b/include/linux/v4l2-subdev.h @@ -0,0 +1,90 @@ +/* + * V4L2 subdev userspace API + * + * Copyright (C) 2010 Nokia Corporation + * + * Contacts: Laurent Pinchart + * Sakari Ailus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 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 + */ + +#ifndef __LINUX_V4L2_SUBDEV_H +#define __LINUX_V4L2_SUBDEV_H + +#include +#include +#include + +/** + * enum v4l2_subdev_format_whence - Media bus format type + * @V4L2_SUBDEV_FORMAT_TRY: try format, for negotiation only + * @V4L2_SUBDEV_FORMAT_ACTIVE: active format, applied to the device + */ +enum v4l2_subdev_format_whence { + V4L2_SUBDEV_FORMAT_TRY = 0, + V4L2_SUBDEV_FORMAT_ACTIVE = 1, +}; + +/** + * struct v4l2_subdev_format - Pad-level media bus format + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @format: media bus format (format code and frame size) + */ +struct v4l2_subdev_format { + __u32 which; + __u32 pad; + struct v4l2_mbus_framefmt format; + __u32 reserved[8]; +}; + +/** + * struct v4l2_subdev_mbus_code_enum - Media bus format enumeration + * @pad: pad number, as reported by the media API + * @index: format index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + */ +struct v4l2_subdev_mbus_code_enum { + __u32 pad; + __u32 index; + __u32 code; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_size_enum - Media bus format enumeration + * @pad: pad number, as reported by the media API + * @index: format index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + */ +struct v4l2_subdev_frame_size_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 min_width; + __u32 max_width; + __u32 min_height; + __u32 max_height; + __u32 reserved[9]; +}; + +#define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_ENUM_MBUS_CODE \ + _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ + _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) + +#endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index d4d3653426a9..4215650151be 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -21,6 +21,7 @@ #ifndef _V4L2_SUBDEV_H #define _V4L2_SUBDEV_H +#include #include #include #include @@ -414,6 +415,15 @@ struct v4l2_subdev_ir_ops { }; struct v4l2_subdev_pad_ops { + int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code); + int (*enum_frame_size)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_size_enum *fse); + int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format); + int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format); }; struct v4l2_subdev_ops { -- cgit v1.2.3 From 35c3017a29d278c4405a7f3ab30b814999d156d3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 5 May 2010 11:38:35 -0300 Subject: [media] v4l: v4l2_subdev userspace frame interval API The three new ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, VIDIOC_SUBDEV_G_FRAME_INTERVAL and VIDIOC_SUBDEV_S_FRAME_INTERVAL can be used to enumerate and configure a subdev's frame rate from userspace. Two new video::g/s_frame_interval subdev operations are introduced to support those ioctls. The existing video::g/s_parm operations are deprecated and shouldn't be used anymore. Signed-off-by: Laurent Pinchart Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 6 + Documentation/DocBook/v4l/v4l2.xml | 2 + .../v4l/vidioc-subdev-enum-frame-interval.xml | 152 +++++++++++++++++++++ .../DocBook/v4l/vidioc-subdev-g-frame-interval.xml | 141 +++++++++++++++++++ drivers/media/video/v4l2-subdev.c | 16 +++ include/linux/v4l2-subdev.h | 36 +++++ include/media/v4l2-subdev.h | 7 + 7 files changed, 360 insertions(+) create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml (limited to 'include/media/v4l2-subdev.h') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index dbb9cb2e1ec6..a95eb5783760 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -89,7 +89,9 @@ VIDIOC_SUBDEV_ENUM_FRAME_SIZE"> VIDIOC_SUBDEV_ENUM_MBUS_CODE"> VIDIOC_SUBDEV_G_FMT"> +VIDIOC_SUBDEV_G_FRAME_INTERVAL"> VIDIOC_SUBDEV_S_FMT"> +VIDIOC_SUBDEV_S_FRAME_INTERVAL"> VIDIOC_TRY_ENCODER_CMD"> VIDIOC_TRY_EXT_CTRLS"> VIDIOC_TRY_FMT"> @@ -193,6 +195,8 @@ v4l2_sliced_vbi_cap"> v4l2_sliced_vbi_data"> v4l2_sliced_vbi_format"> +v4l2_subdev_frame_interval"> +v4l2_subdev_frame_interval_enum"> v4l2_subdev_frame_size_enum"> v4l2_subdev_format"> v4l2_subdev_mbus_code_enum"> @@ -331,10 +335,12 @@ + + diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index 2ada2f86bb54..a436716ef3bc 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -507,9 +507,11 @@ and discussions on the V4L mailing list. &sub-reqbufs; &sub-s-hw-freq-seek; &sub-streamon; + &sub-subdev-enum-frame-interval; &sub-subdev-enum-frame-size; &sub-subdev-enum-mbus-code; &sub-subdev-g-fmt; + &sub-subdev-g-frame-interval; &sub-subscribe-event; &sub-mmap; diff --git a/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml new file mode 100644 index 000000000000..2f8f4f0a0235 --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml @@ -0,0 +1,152 @@ + + + ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL + &manvol; + + + + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL + Enumerate frame intervals + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_frame_interval_enum * + argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + This ioctl lets applications enumerate available frame intervals on a + given sub-device pad. Frame intervals only makes sense for sub-devices that + can control the frame period on their own. This includes, for instance, + image sensors and TV tuners. + + For the common use case of image sensors, the frame intervals + available on the sub-device output pad depend on the frame format and size + on the same pad. Applications must thus specify the desired format and size + when enumerating frame intervals. + + To enumerate frame intervals applications initialize the + index, pad, + code, width and + height fields of + &v4l2-subdev-frame-interval-enum; and call the + VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL ioctl with a pointer + to this structure. Drivers fill the rest of the structure or return + an &EINVAL; if one of the input fields is invalid. All frame intervals are + enumerable by beginning at index zero and incrementing by one until + EINVAL is returned. + + Available frame intervals may depend on the current 'try' formats + at other pads of the sub-device, as well as on the current active links. See + &VIDIOC-SUBDEV-G-FMT; for more information about the try formats. + + Sub-devices that support the frame interval enumeration ioctl should + implemented it on a single pad only. Its behaviour when supported on + multiple pads of the same sub-device is not defined. + + + struct <structname>v4l2_subdev_frame_interval_enum</structname> + + &cs-str; + + + __u32 + index + Number of the format in the enumeration, set by the + application. + + + __u32 + pad + Pad number as reported by the media controller API. + + + __u32 + code + The media bus format code, as defined in + . + + + __u32 + width + Frame width, in pixels. + + + __u32 + height + Frame height, in pixels. + + + &v4l2-fract; + interval + Period, in seconds, between consecutive video frames. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EINVAL + + The &v4l2-subdev-frame-interval-enum; + pad references a non-existing pad, one of + the code, width + or height fields are invalid for the given + pad or the index field is out of bounds. + + + + + +
diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml new file mode 100644 index 000000000000..0bc3ea22d31f --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml @@ -0,0 +1,141 @@ + + + ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL + &manvol; + + + + VIDIOC_SUBDEV_G_FRAME_INTERVAL + VIDIOC_SUBDEV_S_FRAME_INTERVAL + Get or set the frame interval on a subdev pad + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_frame_interval *argp + + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + These ioctls are used to get and set the frame interval at specific + subdev pads in the image pipeline. The frame interval only makes sense for + sub-devices that can control the frame period on their own. This includes, + for instance, image sensors and TV tuners. Sub-devices that don't support + frame intervals must not implement these ioctls. + + To retrieve the current frame interval applications set the + pad field of a &v4l2-subdev-frame-interval; to + the desired pad number as reported by the media controller API. When they + call the VIDIOC_SUBDEV_G_FRAME_INTERVAL ioctl with a + pointer to this structure the driver fills the members of the + interval field. + + To change the current frame interval applications set both the + pad field and all members of the + interval field. When they call the + VIDIOC_SUBDEV_S_FRAME_INTERVAL ioctl with a pointer to + this structure the driver verifies the requested interval, adjusts it based + on the hardware capabilities and configures the device. Upon return the + &v4l2-subdev-frame-interval; contains the current frame interval as would be + returned by a VIDIOC_SUBDEV_G_FRAME_INTERVAL call. + + + Drivers must not return an error solely because the requested interval + doesn't match the device capabilities. They must instead modify the interval + to match what the hardware can provide. The modified interval should be as + close as possible to the original request. + + Sub-devices that support the frame interval ioctls should implement + them on a single pad only. Their behaviour when supported on multiple pads + of the same sub-device is not defined. + + + struct <structname>v4l2_subdev_frame_interval</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media controller API. + + + &v4l2-fract; + interval + Period, in seconds, between consecutive video frames. + + + __u32 + reserved[9] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EBUSY + + The frame interval can't be changed because the pad is currently + busy. This can be caused, for instance, by an active video stream on + the pad. The ioctl must not be retried without performing another + action to fix the problem first. Only returned by + VIDIOC_SUBDEV_S_FRAME_INTERVAL + + + + EINVAL + + The &v4l2-subdev-frame-interval; pad + references a non-existing pad, or the pad doesn't support frame + intervals. + + + + +
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 207cc5cceb29..a4a12563ec3c 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -232,6 +232,22 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh, fse); } + + case VIDIOC_SUBDEV_G_FRAME_INTERVAL: + return v4l2_subdev_call(sd, video, g_frame_interval, arg); + + case VIDIOC_SUBDEV_S_FRAME_INTERVAL: + return v4l2_subdev_call(sd, video, s_frame_interval, arg); + + case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: { + struct v4l2_subdev_frame_interval_enum *fie = arg; + + if (fie->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh, + fie); + } #endif default: return -ENOIOCTLCMD; diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index 8dbb44873821..c55f9e9e1dd3 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -80,11 +80,47 @@ struct v4l2_subdev_frame_size_enum { __u32 reserved[9]; }; +/** + * struct v4l2_subdev_frame_interval - Pad-level frame rate + * @pad: pad number, as reported by the media API + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval { + __u32 pad; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + +/** + * struct v4l2_subdev_frame_interval_enum - Frame interval enumeration + * @pad: pad number, as reported by the media API + * @index: frame interval index during enumeration + * @code: format code (from enum v4l2_mbus_pixelcode) + * @width: frame width in pixels + * @height: frame height in pixels + * @interval: frame interval in seconds + */ +struct v4l2_subdev_frame_interval_enum { + __u32 index; + __u32 pad; + __u32 code; + __u32 width; + __u32 height; + struct v4l2_fract interval; + __u32 reserved[9]; +}; + #define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) #define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) +#define VIDIOC_SUBDEV_G_FRAME_INTERVAL \ + _IOWR('V', 21, struct v4l2_subdev_frame_interval) +#define VIDIOC_SUBDEV_S_FRAME_INTERVAL \ + _IOWR('V', 22, struct v4l2_subdev_frame_interval) #define VIDIOC_SUBDEV_ENUM_MBUS_CODE \ _IOWR('V', 2, struct v4l2_subdev_mbus_code_enum) #define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) +#define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ + _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) #endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 4215650151be..8b7a78a013c6 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -268,6 +268,10 @@ struct v4l2_subdev_video_ops { int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop); int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param); + int (*g_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval); + int (*s_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_frame_interval *interval); int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize); int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival); int (*enum_dv_presets) (struct v4l2_subdev *sd, @@ -420,6 +424,9 @@ struct v4l2_subdev_pad_ops { int (*enum_frame_size)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_frame_size_enum *fse); + int (*enum_frame_interval)(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_frame_interval_enum *fie); int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, -- cgit v1.2.3 From f6a5cb1be894468cdc69ec557d47f40c28f64642 Mon Sep 17 00:00:00 2001 From: Antti Koskipaa Date: Wed, 23 Jun 2010 05:03:42 -0300 Subject: [media] v4l: v4l2_subdev userspace crop API This patch adds the VIDIOC_SUBDEV_S_CROP and G_CROP ioctls to the userland API. CROPCAP is not implemented because it's redundant. Signed-off-by: Antti Koskipaa Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media-entities.tmpl | 4 + Documentation/DocBook/v4l/dev-subdev.xml | 33 +++++ Documentation/DocBook/v4l/v4l2.xml | 1 + Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml | 155 +++++++++++++++++++++ drivers/media/video/v4l2-subdev.c | 26 ++++ include/linux/v4l2-subdev.h | 15 ++ include/media/v4l2-subdev.h | 4 + 7 files changed, 238 insertions(+) create mode 100644 Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml (limited to 'include/media/v4l2-subdev.h') diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl index a95eb5783760..40158ee3d369 100644 --- a/Documentation/DocBook/media-entities.tmpl +++ b/Documentation/DocBook/media-entities.tmpl @@ -88,8 +88,10 @@ VIDIOC_S_TUNER"> VIDIOC_SUBDEV_ENUM_FRAME_SIZE"> VIDIOC_SUBDEV_ENUM_MBUS_CODE"> +VIDIOC_SUBDEV_G_CROP"> VIDIOC_SUBDEV_G_FMT"> VIDIOC_SUBDEV_G_FRAME_INTERVAL"> +VIDIOC_SUBDEV_S_CROP"> VIDIOC_SUBDEV_S_FMT"> VIDIOC_SUBDEV_S_FRAME_INTERVAL"> VIDIOC_TRY_ENCODER_CMD"> @@ -198,6 +200,7 @@ v4l2_subdev_frame_interval"> v4l2_subdev_frame_interval_enum"> v4l2_subdev_frame_size_enum"> +v4l2_subdev_crop"> v4l2_subdev_format"> v4l2_subdev_mbus_code_enum"> v4l2_standard"> @@ -339,6 +342,7 @@ + diff --git a/Documentation/DocBook/v4l/dev-subdev.xml b/Documentation/DocBook/v4l/dev-subdev.xml index fc62e65f45ef..e9eb8af0f303 100644 --- a/Documentation/DocBook/v4l/dev-subdev.xml +++ b/Documentation/DocBook/v4l/dev-subdev.xml @@ -275,6 +275,39 @@ +
+ Cropping and scaling + + Many sub-devices support cropping frames on their input or output + pads (or possible even on both). Cropping is used to select the area of + interest in an image, typically on a video sensor or video decoder. It can + also be used as part of digital zoom implementations to select the area of + the image that will be scaled up. + + Crop settings are defined by a crop rectangle and represented in a + &v4l2-rect; by the coordinates of the top left corner and the rectangle + size. Both the coordinates and sizes are expressed in pixels. + + The crop rectangle is retrieved and set using the + &VIDIOC-SUBDEV-G-CROP; and &VIDIOC-SUBDEV-S-CROP; ioctls. Like for pad + formats, drivers store try and active crop rectangles. The format + negotiation mechanism applies to crop settings as well. + + On input pads, cropping is applied relatively to the current pad + format. The pad format represents the image size as received by the + sub-device from the previous block in the pipeline, and the crop rectangle + represents the sub-image that will be transmitted further inside the + sub-device for processing. The crop rectangle be entirely containted + inside the input image size. + + Input crop rectangle are reset to their default value when the input + image format is modified. Drivers should use the input image size as the + crop rectangle default value, but hardware requirements may prevent this. + + + Cropping behaviour on output pads is not defined. + +
&sub-subdev-formats; diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml index a436716ef3bc..3a6e3b5c0944 100644 --- a/Documentation/DocBook/v4l/v4l2.xml +++ b/Documentation/DocBook/v4l/v4l2.xml @@ -510,6 +510,7 @@ and discussions on the V4L mailing list. &sub-subdev-enum-frame-interval; &sub-subdev-enum-frame-size; &sub-subdev-enum-mbus-code; + &sub-subdev-g-crop; &sub-subdev-g-fmt; &sub-subdev-g-frame-interval; &sub-subscribe-event; diff --git a/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml new file mode 100644 index 000000000000..06197323a8cc --- /dev/null +++ b/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml @@ -0,0 +1,155 @@ + + + ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP + &manvol; + + + + VIDIOC_SUBDEV_G_CROP + VIDIOC_SUBDEV_S_CROP + Get or set the crop rectangle on a subdev pad + + + + + + int ioctl + int fd + int request + struct v4l2_subdev_crop *argp + + + + + int ioctl + int fd + int request + const struct v4l2_subdev_crop *argp + + + + + + Arguments + + + + fd + + &fd; + + + + request + + VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP + + + + argp + + + + + + + + + Description + + + Experimental + This is an experimental + interface and may change in the future. + + + To retrieve the current crop rectangle applications set the + pad field of a &v4l2-subdev-crop; to the + desired pad number as reported by the media API and the + which field to + V4L2_SUBDEV_FORMAT_ACTIVE. They then call the + VIDIOC_SUBDEV_G_CROP ioctl with a pointer to this + structure. The driver fills the members of the rect + field or returns &EINVAL; if the input arguments are invalid, or if cropping + is not supported on the given pad. + + To change the current crop rectangle applications set both the + pad and which fields + and all members of the rect field. They then call + the VIDIOC_SUBDEV_S_CROP ioctl with a pointer to this + structure. The driver verifies the requested crop rectangle, adjusts it + based on the hardware capabilities and configures the device. Upon return + the &v4l2-subdev-crop; contains the current format as would be returned + by a VIDIOC_SUBDEV_G_CROP call. + + Applications can query the device capabilities by setting the + which to + V4L2_SUBDEV_FORMAT_TRY. When set, 'try' crop + rectangles are not applied to the device by the driver, but are mangled + exactly as active crop rectangles and stored in the sub-device file handle. + Two applications querying the same sub-device would thus not interact with + each other. + + Drivers must not return an error solely because the requested crop + rectangle doesn't match the device capabilities. They must instead modify + the rectangle to match what the hardware can provide. The modified format + should be as close as possible to the original request. + + + struct <structname>v4l2_subdev_crop</structname> + + &cs-str; + + + __u32 + pad + Pad number as reported by the media framework. + + + __u32 + which + Crop rectangle to get or set, from + &v4l2-subdev-format-whence;. + + + &v4l2-rect; + rect + Crop rectangle boundaries, in pixels. + + + __u32 + reserved[8] + Reserved for future extensions. Applications and drivers must + set the array to zero. + + + +
+
+ + + &return-value; + + + + EBUSY + + The crop rectangle can't be changed because the pad is currently + busy. This can be caused, for instance, by an active video stream on + the pad. The ioctl must not be retried without performing another + action to fix the problem first. Only returned by + VIDIOC_SUBDEV_S_CROP + + + + EINVAL + + The &v4l2-subdev-crop; pad + references a non-existing pad, the which + field references a non-existing format, or cropping is not supported + on the given subdev pad. + + + + +
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index a4a12563ec3c..6e76f734c780 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -213,6 +213,32 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format); } + case VIDIOC_SUBDEV_G_CROP: { + struct v4l2_subdev_crop *crop = arg; + + if (crop->which != V4L2_SUBDEV_FORMAT_TRY && + crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (crop->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop); + } + + case VIDIOC_SUBDEV_S_CROP: { + struct v4l2_subdev_crop *crop = arg; + + if (crop->which != V4L2_SUBDEV_FORMAT_TRY && + crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (crop->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop); + } + case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { struct v4l2_subdev_mbus_code_enum *code = arg; diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index c55f9e9e1dd3..ed29cbbebfef 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -50,6 +50,19 @@ struct v4l2_subdev_format { __u32 reserved[8]; }; +/** + * struct v4l2_subdev_crop - Pad-level crop settings + * @which: format type (from enum v4l2_subdev_format_whence) + * @pad: pad number, as reported by the media API + * @rect: pad crop rectangle boundaries + */ +struct v4l2_subdev_crop { + __u32 which; + __u32 pad; + struct v4l2_rect rect; + __u32 reserved[8]; +}; + /** * struct v4l2_subdev_mbus_code_enum - Media bus format enumeration * @pad: pad number, as reported by the media API @@ -122,5 +135,7 @@ struct v4l2_subdev_frame_interval_enum { _IOWR('V', 74, struct v4l2_subdev_frame_size_enum) #define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) +#define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop) +#define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop) #endif diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 8b7a78a013c6..edeaf398d480 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -431,6 +431,10 @@ struct v4l2_subdev_pad_ops { struct v4l2_subdev_format *format); int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *format); + int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_crop *crop); + int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_crop *crop); }; struct v4l2_subdev_ops { -- cgit v1.2.3 From f80a3ab083474670527df3ca849546a7059da766 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 16 Nov 2010 01:21:06 -0300 Subject: [media] v4l: Add subdev sensor g_skip_frames operation Some buggy sensors generate corrupt frames when the stream is started. This new operation return the number of corrupt frames to skip when starting the stream. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/media/v4l2-subdev.h') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index edeaf398d480..1562c4ff3a65 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -341,9 +341,13 @@ struct v4l2_subdev_vbi_ops { * This is needed for some sensors, which always corrupt * several top lines of the output image, or which send their * metadata in them. + * @g_skip_frames: number of frames to skip at stream start. This is needed for + * buggy sensors that generate faulty frames when they are + * turned on. */ struct v4l2_subdev_sensor_ops { int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines); + int (*g_skip_frames)(struct v4l2_subdev *sd, u32 *frames); }; /* -- cgit v1.2.3