From: Antti Koskipaa <antti.koski...@nokia.com>

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 <antti.koski...@nokia.com>
---
 drivers/media/video/v4l2-subdev.c |   36 ++++++++++++++++++++++++++++++++++--
 include/linux/v4l2-subdev.h       |   12 ++++++++++++
 include/media/v4l2-subdev.h       |   11 +++++++++++
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/media/video/v4l2-subdev.c 
b/drivers/media/video/v4l2-subdev.c
index 8ddb2fb..ad4b95e 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -30,11 +30,16 @@
 
 static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
 {
-       fh->probe_fmt = kzalloc(sizeof(*fh->probe_fmt) *
-                               sd->entity.num_pads, GFP_KERNEL);
+       /* 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;
 }
 
@@ -42,6 +47,7 @@ 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)
@@ -188,6 +194,32 @@ static long subdev_do_ioctl(struct file *file, unsigned 
int cmd, void *arg)
                                        format->which);
        }
 
+       case VIDIOC_SUBDEV_G_CROP: {
+               struct v4l2_subdev_pad_crop *crop = arg;
+
+               if (crop->which != V4L2_SUBDEV_FORMAT_PROBE &&
+                   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_pad_crop *crop = arg;
+
+               if (crop->which != V4L2_SUBDEV_FORMAT_PROBE &&
+                   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_pad_mbus_code_enum *code = arg;
 
diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h
index e3362aa..5738e81 100644
--- a/include/linux/v4l2-subdev.h
+++ b/include/linux/v4l2-subdev.h
@@ -36,6 +36,16 @@ struct v4l2_subdev_pad_format {
 };
 
 /**
+ * struct v4l2_subdev_pad_crop
+ */
+struct v4l2_subdev_pad_crop {
+       __u32 pad;
+       __u32 which;
+       struct v4l2_rect rect;
+       __u32 reserved[10];
+};
+
+/**
  * struct v4l2_subdev_pad_mbus_code_enum
  */
 struct v4l2_subdev_pad_mbus_code_enum {
@@ -86,5 +96,7 @@ struct v4l2_subdev_frame_interval_enum {
                        _IOWR('V', 9, struct v4l2_subdev_frame_size_enum)
 #define VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
                        _IOWR('V', 10, struct v4l2_subdev_frame_interval_enum)
+#define VIDIOC_SUBDEV_S_CROP   _IOWR('V', 11, struct v4l2_subdev_pad_crop)
+#define VIDIOC_SUBDEV_G_CROP   _IOWR('V', 12, struct v4l2_subdev_pad_crop)
 
 #endif
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 58ef923..41183ab 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -419,6 +419,10 @@ struct v4l2_subdev_pad_ops {
        int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                       unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                       enum v4l2_subdev_format which);
+       int (*set_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_pad_crop *crop);
+       int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_pad_crop *crop);
 };
 
 struct v4l2_subdev_ops {
@@ -478,6 +482,7 @@ struct v4l2_subdev {
 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)  \
@@ -489,6 +494,12 @@ 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)
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to