media: bcm2835-unicam: Add support for VIDIOC_[S|G]_SELECTION
authorDave Stevenson <dave.stevenson@raspberrypi.com>
Wed, 29 Apr 2020 15:45:02 +0000 (16:45 +0100)
committerDom Cobley <popcornmix@gmail.com>
Mon, 21 Mar 2022 16:04:01 +0000 (16:04 +0000)
Sensors are now reflecting cropping and scaling parameters through
the selection API, therefore Unicam needs to forward the requests
through to the subdev.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
drivers/media/platform/bcm2835/bcm2835-unicam.c

index d4684fb2797fd1d3d49ff4092487b4ec546aa0fc..0e1d525a0b353a3ccc5d61a770c325e7dd294e88 100644 (file)
@@ -1898,6 +1898,39 @@ static int unicam_g_edid(struct file *file, void *priv, struct v4l2_edid *edid)
        return v4l2_subdev_call(dev->sensor, pad, get_edid, edid);
 }
 
+static int unicam_s_selection(struct file *file, void *priv,
+                             struct v4l2_selection *sel)
+{
+       struct unicam_node *node = video_drvdata(file);
+       struct unicam_device *dev = node->dev;
+       struct v4l2_subdev_selection sdsel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = sel->target,
+               .flags = sel->flags,
+               .r = sel->r,
+       };
+
+       return v4l2_subdev_call(dev->sensor, pad, set_selection, NULL, &sdsel);
+}
+
+static int unicam_g_selection(struct file *file, void *priv,
+                             struct v4l2_selection *sel)
+{
+       struct unicam_node *node = video_drvdata(file);
+       struct unicam_device *dev = node->dev;
+       struct v4l2_subdev_selection sdsel = {
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+               .target = sel->target,
+       };
+       int ret;
+
+       ret = v4l2_subdev_call(dev->sensor, pad, get_selection, NULL, &sdsel);
+       if (!ret)
+               sel->r = sdsel.r;
+
+       return ret;
+}
+
 static int unicam_enum_framesizes(struct file *file, void *priv,
                                  struct v4l2_frmsizeenum *fsize)
 {
@@ -2218,6 +2251,9 @@ static const struct v4l2_ioctl_ops unicam_ioctl_ops = {
        .vidioc_enum_framesizes         = unicam_enum_framesizes,
        .vidioc_enum_frameintervals     = unicam_enum_frameintervals,
 
+       .vidioc_g_selection             = unicam_g_selection,
+       .vidioc_s_selection             = unicam_s_selection,
+
        .vidioc_g_parm                  = unicam_g_parm,
        .vidioc_s_parm                  = unicam_s_parm,
 
@@ -2446,6 +2482,14 @@ static int register_node(struct unicam_device *unicam, struct unicam_node *node,
            !v4l2_subdev_has_op(unicam->sensor, pad, enum_frame_size))
                v4l2_disable_ioctl(&node->video_dev, VIDIOC_ENUM_FRAMESIZES);
 
+       if (node->pad_id == METADATA_PAD ||
+           !v4l2_subdev_has_op(unicam->sensor, pad, set_selection))
+               v4l2_disable_ioctl(&node->video_dev, VIDIOC_S_SELECTION);
+
+       if (node->pad_id == METADATA_PAD ||
+           !v4l2_subdev_has_op(unicam->sensor, pad, get_selection))
+               v4l2_disable_ioctl(&node->video_dev, VIDIOC_G_SELECTION);
+
        ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
        if (ret) {
                unicam_err(unicam, "Unable to register video device.\n");