From patchwork Sun Sep 26 16:13:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 210102 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o8QGDbTb012041 for ; Sun, 26 Sep 2010 16:13:37 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757519Ab0IZQNc (ORCPT ); Sun, 26 Sep 2010 12:13:32 -0400 Received: from perceval.irobotique.be ([92.243.18.41]:36175 "EHLO perceval.irobotique.be" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757452Ab0IZQN1 (ORCPT ); Sun, 26 Sep 2010 12:13:27 -0400 Received: from localhost.localdomain (unknown [91.178.4.71]) by perceval.irobotique.be (Postfix) with ESMTPSA id F156935D11; Sun, 26 Sep 2010 16:13:23 +0000 (UTC) From: Laurent Pinchart To: linux-media@vger.kernel.org Cc: sakari.ailus@maxwell.research.nokia.com, g.liakhovetski@gmx.de Subject: [RFC/PATCH 5/9] v4l: Create v4l2 subdev file handle structure Date: Sun, 26 Sep 2010 18:13:28 +0200 Message-Id: <1285517612-20230-6-git-send-email-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 1.7.2.2 In-Reply-To: <1285517612-20230-1-git-send-email-laurent.pinchart@ideasonboard.com> References: <1285517612-20230-1-git-send-email-laurent.pinchart@ideasonboard.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sun, 26 Sep 2010 16:13:37 +0000 (UTC) diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 731dc12..d2891c1 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -30,38 +30,66 @@ #include #include +static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) +{ + /* Allocate probe format and crop in the same memory block */ + fh->probe_fmt = kzalloc((sizeof(*fh->probe_fmt) + + sizeof(*fh->probe_crop)) * sd->entity.num_pads, + GFP_KERNEL); + if (fh->probe_fmt == NULL) + return -ENOMEM; + + fh->probe_crop = (struct v4l2_rect *) + (fh->probe_fmt + sd->entity.num_pads); + + return 0; +} + +static void subdev_fh_free(struct v4l2_subdev_fh *fh) +{ + kfree(fh->probe_fmt); + fh->probe_fmt = NULL; + fh->probe_crop = NULL; +} + 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; struct media_entity *entity; - struct v4l2_fh *vfh = NULL; int ret; if (!sd->initialized) return -EAGAIN; - 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 (sd->v4l2_dev->mdev) { entity = media_entity_get(&sd->entity); if (!entity) { @@ -73,11 +101,10 @@ static int subdev_open(struct file *file) 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; } @@ -87,15 +114,16 @@ static int subdev_close(struct file *file) struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct v4l2_fh *vfh = file->private_data; + struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh); if (sd->v4l2_dev->mdev) media_entity_put(&sd->entity); - 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; } @@ -104,7 +132,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: @@ -132,13 +160,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 57ef74f..212fc54 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 */ @@ -469,6 +470,30 @@ 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; + struct v4l2_mbus_framefmt *probe_fmt; + struct v4l2_rect *probe_crop; +}; + +#define to_v4l2_subdev_fh(fh) \ + container_of(fh, struct v4l2_subdev_fh, vfh) + +static inline struct v4l2_mbus_framefmt * +v4l2_subdev_get_probe_format(struct v4l2_subdev_fh *fh, unsigned int pad) +{ + return &fh->probe_fmt[pad]; +} + +static inline struct v4l2_rect * +v4l2_subdev_get_probe_crop(struct v4l2_subdev_fh *fh, unsigned int pad) +{ + return &fh->probe_crop[pad]; +} + extern const struct v4l2_file_operations v4l2_subdev_fops; static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)