staging: vc04_services: isp: Fixup g/s_selection implementation
authorNaushir Patuck <naush@raspberrypi.com>
Tue, 19 May 2020 14:56:47 +0000 (15:56 +0100)
committerpopcornmix <popcornmix@gmail.com>
Wed, 1 Jul 2020 15:34:17 +0000 (16:34 +0100)
Add V4L2_SEL_TGT_CROP_DEFAULT and V4L2_SEL_TGT_CROP_BOUND targets.
Disable the appropriate ioctls for the meta capture nodes - this now
passes v4l2-compliance tests.

Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
drivers/staging/vc04_services/bcm2835-isp/bcm2835-v4l2-isp.c

index bc86354..8347199 100644 (file)
@@ -1006,15 +1006,32 @@ static int bcm2835_isp_node_s_selection(struct file *file, void *fh,
        if (!s->r.width || !s->r.height)
                return -EINVAL;
 
-       /* Adjust the crop window if goes outside the frame dimensions. */
-       s->r.left = min((unsigned int)max(s->r.left, 0),
-                       node->q_data.width - MIN_DIM);
-       s->r.top = min((unsigned int)max(s->r.top, 0),
-                      node->q_data.height - MIN_DIM);
-       s->r.width = max(min(s->r.width, node->q_data.width - s->r.left),
-                        MIN_DIM);
-       s->r.height = max(min(s->r.height, node->q_data.height - s->r.top),
-                         MIN_DIM);
+       /* We can only set crop on the input. */
+       switch (s->target) {
+       case V4L2_SEL_TGT_CROP:
+               /*
+                * Adjust the crop window if it goes outside of the frame
+                * dimensions.
+                */
+               s->r.left = min((unsigned int)max(s->r.left, 0),
+                               node->q_data.width - MIN_DIM);
+               s->r.top = min((unsigned int)max(s->r.top, 0),
+                              node->q_data.height - MIN_DIM);
+               s->r.width = max(min(s->r.width,
+                                    node->q_data.width - s->r.left), MIN_DIM);
+               s->r.height = max(min(s->r.height,
+                                     node->q_data.height - s->r.top), MIN_DIM);
+               break;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               /* Default (i.e. no) crop window. */
+               s->r.left = 0;
+               s->r.top = 0;
+               s->r.width = node->q_data.width;
+               s->r.height = node->q_data.height;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        crop.rect.x = s->r.left;
        crop.rect.y = s->r.top;
@@ -1029,33 +1046,40 @@ static int bcm2835_isp_node_s_selection(struct file *file, void *fh,
 static int bcm2835_isp_node_g_selection(struct file *file, void *fh,
                                        struct v4l2_selection *s)
 {
+       struct mmal_parameter_crop crop;
        struct bcm2835_isp_node *node = video_drvdata(file);
-       struct bcm2835_isp_dev *dev = node_get_dev(node);
        struct vchiq_mmal_port *port = get_port_data(node);
-       struct mmal_parameter_crop crop;
+       struct bcm2835_isp_dev *dev = node_get_dev(node);
        u32 crop_size = sizeof(crop);
        int ret;
 
-       /* This return value is required for V4L2 compliance. */
-       if (node_is_stats(node))
-               return -ENOTTY;
-
        /* We can only return out an input crop. */
-       if (s->target != V4L2_SEL_TGT_CROP)
-               return -EINVAL;
-
-       ret = vchiq_mmal_port_parameter_get(dev->mmal_instance, port,
-                                           MMAL_PARAMETER_CROP,
-                                           &crop, &crop_size);
-       if (!ret)
-               return -EINVAL;
-
-       s->r.left = crop.rect.x;
-       s->r.top = crop.rect.y;
-       s->r.width = crop.rect.width;
-       s->r.height = crop.rect.height;
+       switch (s->target) {
+       case V4L2_SEL_TGT_CROP:
+               ret = vchiq_mmal_port_parameter_get(dev->mmal_instance, port,
+                                                   MMAL_PARAMETER_CROP,
+                                                   &crop, &crop_size);
+               if (!ret) {
+                       s->r.left = crop.rect.x;
+                       s->r.top = crop.rect.y;
+                       s->r.width = crop.rect.width;
+                       s->r.height = crop.rect.height;
+               }
+               break;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               /* Default (i.e. no) crop window. */
+               s->r.left = 0;
+               s->r.top = 0;
+               s->r.width = node->q_data.width;
+               s->r.height = node->q_data.height;
+               ret = 0;
+               break;
+       default:
+               ret =  -EINVAL;
+       }
 
-       return 0;
+       return ret;
 }
 
 static int bcm3285_isp_subscribe_event(struct v4l2_fh *fh,
@@ -1218,6 +1242,8 @@ static int register_node(struct bcm2835_isp_dev *dev,
                node->vfl_dir = VFL_DIR_RX;
                node->name = "stats";
                v4l2_disable_ioctl(&node->vfd, VIDIOC_S_CTRL);
+               v4l2_disable_ioctl(&node->vfd, VIDIOC_S_SELECTION);
+               v4l2_disable_ioctl(&node->vfd, VIDIOC_G_SELECTION);
                break;
        }