[media] V4L: soc-camera: add selection API host operations
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Fri, 22 Jun 2012 16:40:08 +0000 (13:40 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 20:37:39 +0000 (17:37 -0300)
Add .get_selection() and .set_selection() soc-camera host driver
operations. Additionally check, that the user is not trying to change the
output sizes during a running capture.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/platform/soc_camera.c
include/media/soc_camera.h

index f94055505d70ac874164f72c07544250a5393ddf..6da8e5db4d2ba01dd9eec32fe81632952d0fc0cb 100644 (file)
@@ -924,6 +924,65 @@ static int soc_camera_s_crop(struct file *file, void *fh,
        return ret;
 }
 
+static int soc_camera_g_selection(struct file *file, void *fh,
+                                 struct v4l2_selection *s)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+       /* With a wrong type no need to try to fall back to cropping */
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (!ici->ops->get_selection)
+               return -ENOTTY;
+
+       return ici->ops->get_selection(icd, s);
+}
+
+static int soc_camera_s_selection(struct file *file, void *fh,
+                                 struct v4l2_selection *s)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       int ret;
+
+       /* In all these cases cropping emulation will not help */
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           (s->target != V4L2_SEL_TGT_COMPOSE_ACTIVE &&
+            s->target != V4L2_SEL_TGT_CROP_ACTIVE))
+               return -EINVAL;
+
+       if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+               /* No output size change during a running capture! */
+               if (is_streaming(ici, icd) &&
+                   (icd->user_width != s->r.width ||
+                    icd->user_height != s->r.height))
+                       return -EBUSY;
+
+               /*
+                * Only one user is allowed to change the output format, touch
+                * buffers, start / stop streaming, poll for data
+                */
+               if (icd->streamer && icd->streamer != file)
+                       return -EBUSY;
+       }
+
+       if (!ici->ops->set_selection)
+               return -ENOTTY;
+
+       ret = ici->ops->set_selection(icd, s);
+       if (!ret &&
+           s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+               icd->user_width = s->r.width;
+               icd->user_height = s->r.height;
+               if (!icd->streamer)
+                       icd->streamer = file;
+       }
+
+       return ret;
+}
+
 static int soc_camera_g_parm(struct file *file, void *fh,
                             struct v4l2_streamparm *a)
 {
@@ -1407,6 +1466,8 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
        .vidioc_cropcap          = soc_camera_cropcap,
        .vidioc_g_crop           = soc_camera_g_crop,
        .vidioc_s_crop           = soc_camera_s_crop,
+       .vidioc_g_selection      = soc_camera_g_selection,
+       .vidioc_s_selection      = soc_camera_s_selection,
        .vidioc_g_parm           = soc_camera_g_parm,
        .vidioc_s_parm           = soc_camera_s_parm,
        .vidioc_g_chip_ident     = soc_camera_g_chip_ident,
index 982bfc948414365ca01d7ed26cddf8f8501458cc..435e7b8ad1c3dff462457b4ffbe04473bf95cf1c 100644 (file)
@@ -86,6 +86,8 @@ struct soc_camera_host_ops {
        int (*cropcap)(struct soc_camera_device *, struct v4l2_cropcap *);
        int (*get_crop)(struct soc_camera_device *, struct v4l2_crop *);
        int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *);
+       int (*get_selection)(struct soc_camera_device *, struct v4l2_selection *);
+       int (*set_selection)(struct soc_camera_device *, struct v4l2_selection *);
        /*
         * The difference to .set_crop() is, that .set_livecrop is not allowed
         * to change the output sizes