]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
media: iris: Add support for G/S_SELECTION for encoder video device
authorDikshita Agarwal <quic_dikshita@quicinc.com>
Mon, 25 Aug 2025 07:00:43 +0000 (12:30 +0530)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Wed, 10 Sep 2025 07:02:37 +0000 (09:02 +0200)
Add support for G/S_SELECTION V4L2 ioctls for the encoder video
device with necessary hooks. This allows userspace to query and
configure rectangular selection areas such as crop.

Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # X1E80100
Reviewed-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # x1e80100-crd
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/platform/qcom/iris/iris_venc.c
drivers/media/platform/qcom/iris/iris_venc.h
drivers/media/platform/qcom/iris/iris_vidc.c

index 384b30555546f2a0677e49400f177b96611f866b..71960a0e903d114be7a9e797089c3dee2fab2545 100644 (file)
@@ -300,3 +300,29 @@ int iris_venc_subscribe_event(struct iris_inst *inst,
                return -EINVAL;
        }
 }
+
+int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s)
+{
+       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return -EINVAL;
+
+       switch (s->target) {
+       case V4L2_SEL_TGT_CROP:
+               s->r.left = 0;
+               s->r.top = 0;
+
+               if (s->r.width > inst->fmt_src->fmt.pix_mp.width ||
+                   s->r.height > inst->fmt_src->fmt.pix_mp.height)
+                       return -EINVAL;
+
+               inst->crop.left = s->r.left;
+               inst->crop.top = s->r.top;
+               inst->crop.width = s->r.width;
+               inst->crop.height = s->r.height;
+               inst->fmt_dst->fmt.pix_mp.width = inst->crop.width;
+               inst->fmt_dst->fmt.pix_mp.height = inst->crop.height;
+               return iris_venc_s_fmt_output(inst, inst->fmt_dst);
+       default:
+               return -EINVAL;
+       }
+}
index 2d9614ae18e8a2318df6673fbeae5ee33c99b596..72c6e25d87113baa6d2219ae478b7d7df1aed7bf 100644 (file)
@@ -15,5 +15,6 @@ int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f);
 int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
 int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat);
 int iris_venc_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
+int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s);
 
 #endif
index 5d9b36858e9317b1eddac12004432229e18967a7..b134ae710d9e1d02bc52db2e9356fdc4f668a387 100644 (file)
@@ -460,29 +460,64 @@ static int iris_g_selection(struct file *filp, void *fh, struct v4l2_selection *
 {
        struct iris_inst *inst = iris_get_inst(filp);
 
-       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           inst->domain == DECODER)
                return -EINVAL;
 
-       switch (s->target) {
-       case V4L2_SEL_TGT_CROP_BOUNDS:
-       case V4L2_SEL_TGT_CROP_DEFAULT:
-       case V4L2_SEL_TGT_CROP:
-       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-       case V4L2_SEL_TGT_COMPOSE_PADDED:
-       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-       case V4L2_SEL_TGT_COMPOSE:
+       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           inst->domain == ENCODER)
+               return -EINVAL;
+
+       if (inst->domain == DECODER) {
+               switch (s->target) {
+               case V4L2_SEL_TGT_CROP_BOUNDS:
+               case V4L2_SEL_TGT_CROP_DEFAULT:
+               case V4L2_SEL_TGT_CROP:
+               case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               case V4L2_SEL_TGT_COMPOSE_PADDED:
+               case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               case V4L2_SEL_TGT_COMPOSE:
+                       s->r.left = inst->crop.left;
+                       s->r.top = inst->crop.top;
+                       s->r.width = inst->crop.width;
+                       s->r.height = inst->crop.height;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else if (inst->domain == ENCODER) {
+               switch (s->target) {
+               case V4L2_SEL_TGT_CROP_BOUNDS:
+               case V4L2_SEL_TGT_CROP_DEFAULT:
+                       s->r.width = inst->fmt_src->fmt.pix_mp.width;
+                       s->r.height = inst->fmt_src->fmt.pix_mp.height;
+                       break;
+               case V4L2_SEL_TGT_CROP:
+                       s->r.width = inst->crop.width;
+                       s->r.height = inst->crop.height;
+                       break;
+               default:
+                       return -EINVAL;
+               }
                s->r.left = inst->crop.left;
                s->r.top = inst->crop.top;
-               s->r.width = inst->crop.width;
-               s->r.height = inst->crop.height;
-               break;
-       default:
-               return -EINVAL;
        }
 
        return 0;
 }
 
+static int iris_s_selection(struct file *filp, void *fh, struct v4l2_selection *s)
+{
+       struct iris_inst *inst = iris_get_inst(filp);
+
+       if (inst->domain == DECODER)
+               return -EINVAL;
+       else if (inst->domain == ENCODER)
+               return iris_venc_s_selection(inst, s);
+
+       return -EINVAL;
+}
+
 static int iris_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
 {
        struct iris_inst *inst = container_of(fh, struct iris_inst, fh);
@@ -589,6 +624,8 @@ static const struct v4l2_ioctl_ops iris_v4l2_ioctl_ops_enc = {
        .vidioc_querycap                = iris_querycap,
        .vidioc_subscribe_event         = iris_subscribe_event,
        .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
+       .vidioc_g_selection             = iris_g_selection,
+       .vidioc_s_selection             = iris_s_selection,
 };
 
 void iris_init_ops(struct iris_core *core)