From: Laurent Pinchart <laurent.pinchart+rene...@ideasonboard.com>

Store the formats in per-entity request data. The get and set format
operations are completely handled by the V4L2 core with help of the try
format driver operation.

Signed-off-by: Laurent Pinchart <laurent.pinchart+rene...@ideasonboard.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 121 +++++++++++++++++++++++++++++++++++
 include/media/v4l2-dev.h             |  13 ++++
 2 files changed, 134 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index bf15580..533fac6 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1355,6 +1355,119 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops 
*ops,
        return ret;
 }
 
+#if defined(CONFIG_MEDIA_CONTROLLER)
+static void vdev_request_data_release(struct media_entity_request_data *data)
+{
+       struct video_device_request_data *vdata =
+               to_video_device_request_data(data);
+
+       kfree(vdata);
+}
+
+static int vdev_request_format(struct video_device *vdev, unsigned int req_id,
+                              struct media_device_request **_req,
+                              struct v4l2_pix_format_mplane **_fmt)
+{
+       struct media_entity_request_data *data;
+       struct video_device_request_data *vdata;
+       struct media_device_request *req;
+
+       if (!vdev->v4l2_dev || !vdev->v4l2_dev->mdev)
+               return -EINVAL;
+
+       req = media_device_request_find(vdev->v4l2_dev->mdev, req_id);
+       if (!req)
+               return -EINVAL;
+
+       *_req = req;
+
+       data = media_device_request_get_entity_data(req, &vdev->entity);
+       if (data) {
+               vdata = to_video_device_request_data(data);
+               *_fmt = &vdata->format;
+               return 0;
+       }
+
+       vdata = kzalloc(sizeof(*vdata), GFP_KERNEL);
+       if (!vdata) {
+               media_device_request_put(req);
+               return -ENOMEM;
+       }
+
+       vdata->data.release = vdev_request_data_release;
+
+       media_device_request_set_entity_data(req, &vdev->entity, &vdata->data);
+
+       *_fmt = &vdata->format;
+       return 0;
+}
+
+static int v4l_g_req_mplane_fmt(const struct v4l2_ioctl_ops *ops,
+                               struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct v4l2_pix_format_mplane *format;
+       struct media_device_request *req;
+       int ret;
+
+       ret = vdev_request_format(vdev, fmt->fmt.pix_mp.request,
+                                 &req, &format);
+       if (ret < 0)
+               return ret;
+
+       fmt->fmt.pix_mp = *format;
+       media_device_request_put(req);
+       return 0;
+}
+
+static int v4l_s_req_mplane_fmt(const struct v4l2_ioctl_ops *ops,
+                               struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       int (*try_op)(struct file *file, void *fh, struct v4l2_format *fmt);
+       struct video_device *vdev = video_devdata(file);
+       struct v4l2_pix_format_mplane *format;
+       struct media_device_request *req;
+       int ret;
+
+       if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               try_op = ops->vidioc_try_fmt_vid_cap_mplane;
+       else
+               try_op = ops->vidioc_try_fmt_vid_out_mplane;
+
+       if (unlikely(!try_op))
+               return -ENOSYS;
+
+       ret = try_op(file, fh, fmt);
+       if (ret < 0)
+               return ret;
+
+       ret = vdev_request_format(vdev, fmt->fmt.pix_mp.request,
+                                 &req, &format);
+       if (ret < 0)
+               return ret;
+
+       *format = fmt->fmt.pix_mp;
+       media_device_request_put(req);
+       return 0;
+}
+#else
+static int v4l_g_req_mplane_fmt(const struct v4l2_ioctl_ops *ops,
+                               struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       return -ENOSYS;
+}
+
+static int v4l_s_req_mplane_fmt(const struct v4l2_ioctl_ops *ops,
+                               struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       return -ENOSYS;
+}
+#endif
+
 static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
@@ -1402,6 +1515,8 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
                if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_g_fmt_vid_cap_mplane))
                        break;
+               if (p->fmt.pix_mp.request)
+                       return v4l_g_req_mplane_fmt(ops, file, fh, p);
                return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_g_fmt_vid_overlay))
@@ -1426,6 +1541,8 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
                if (unlikely(!is_tx || !is_vid || 
!ops->vidioc_g_fmt_vid_out_mplane))
                        break;
+               if (p->fmt.pix_mp.request)
+                       return v4l_g_req_mplane_fmt(ops, file, fh, p);
                return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!is_tx || !is_vid || 
!ops->vidioc_g_fmt_vid_out_overlay))
@@ -1480,6 +1597,8 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_s_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp);
+               if (p->fmt.pix_mp.request)
+                       return v4l_s_req_mplane_fmt(ops, file, fh, p);
                return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!is_rx || !is_vid || 
!ops->vidioc_s_fmt_vid_overlay))
@@ -1508,6 +1627,8 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!is_tx || !is_vid || 
!ops->vidioc_s_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp);
+               if (p->fmt.pix_mp.request)
+                       return v4l_s_req_mplane_fmt(ops, file, fh, p);
                return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!is_tx || !is_vid || 
!ops->vidioc_s_fmt_vid_out_overlay))
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 25a3190..19c7702 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -238,4 +238,17 @@ static inline int video_is_registered(struct video_device 
*vdev)
        return test_bit(V4L2_FL_REGISTERED, &vdev->flags);
 }
 
+#if defined(CONFIG_MEDIA_CONTROLLER)
+struct video_device_request_data {
+       struct media_entity_request_data data;
+       struct v4l2_pix_format_mplane format;
+};
+
+static inline struct video_device_request_data *
+to_video_device_request_data(struct media_entity_request_data *data)
+{
+       return container_of(data, struct video_device_request_data, data);
+}
+#endif
+
 #endif /* _V4L2_DEV_H */
-- 
1.9.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