OSDN Git Service

media: i2c: ov2685: Add .get_selection() support
authorLuca Weiss <luca@z3ntu.xyz>
Wed, 1 Feb 2023 17:07:01 +0000 (18:07 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Mon, 20 Mar 2023 14:58:55 +0000 (15:58 +0100)
Add support for the .get_selection() pad operation to the ov2685 sensor
driver.

Report the native sensor size (pixel array), the crop bounds (readable
pixel array area) and the current and default analog crop rectangles.

Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/i2c/ov2685.c

index f1cea31..fdf3e06 100644 (file)
@@ -56,6 +56,9 @@
 #define OV2685_REG_VALUE_16BIT         2
 #define OV2685_REG_VALUE_24BIT         3
 
+#define OV2685_NATIVE_WIDTH            1616
+#define OV2685_NATIVE_HEIGHT           1216
+
 #define OV2685_LANES                   1
 #define OV2685_BITS_PER_SAMPLE         10
 
@@ -78,6 +81,7 @@ struct ov2685_mode {
        u32 exp_def;
        u32 hts_def;
        u32 vts_def;
+       const struct v4l2_rect *analog_crop;
        const struct regval *reg_list;
 };
 
@@ -231,6 +235,13 @@ static const int ov2685_test_pattern_val[] = {
        OV2685_TEST_PATTERN_COLOR_SQUARE,
 };
 
+static const struct v4l2_rect ov2685_analog_crop = {
+       .left   = 8,
+       .top    = 8,
+       .width  = 1600,
+       .height = 1200,
+};
+
 static const struct ov2685_mode supported_modes[] = {
        {
                .width = 1600,
@@ -238,6 +249,7 @@ static const struct ov2685_mode supported_modes[] = {
                .exp_def = 0x04ee,
                .hts_def = 0x06a4,
                .vts_def = 0x050e,
+               .analog_crop = &ov2685_analog_crop,
                .reg_list = ov2685_1600x1200_regs,
        },
 };
@@ -384,6 +396,53 @@ static int ov2685_enum_frame_sizes(struct v4l2_subdev *sd,
        return 0;
 }
 
+static const struct v4l2_rect *
+__ov2685_get_pad_crop(struct ov2685 *ov2685,
+                     struct v4l2_subdev_state *state, unsigned int pad,
+                     enum v4l2_subdev_format_whence which)
+{
+       const struct ov2685_mode *mode = ov2685->cur_mode;
+
+       switch (which) {
+       case V4L2_SUBDEV_FORMAT_TRY:
+               return v4l2_subdev_get_try_crop(&ov2685->subdev, state, pad);
+       case V4L2_SUBDEV_FORMAT_ACTIVE:
+               return mode->analog_crop;
+       }
+
+       return NULL;
+}
+
+static int ov2685_get_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_state *sd_state,
+                               struct v4l2_subdev_selection *sel)
+{
+       struct ov2685 *ov2685 = to_ov2685(sd);
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP:
+               mutex_lock(&ov2685->mutex);
+               sel->r = *__ov2685_get_pad_crop(ov2685, sd_state, sel->pad,
+                               sel->which);
+               mutex_unlock(&ov2685->mutex);
+               break;
+       case V4L2_SEL_TGT_NATIVE_SIZE:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               sel->r.top = 0;
+               sel->r.left = 0;
+               sel->r.width = OV2685_NATIVE_WIDTH;
+               sel->r.height = OV2685_NATIVE_HEIGHT;
+               break;
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r = ov2685_analog_crop;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /* Calculate the delay in us by clock rate and clock cycles */
 static inline u32 ov2685_cal_delay(u32 cycles)
 {
@@ -592,6 +651,8 @@ static const struct v4l2_subdev_pad_ops ov2685_pad_ops = {
        .enum_frame_size = ov2685_enum_frame_sizes,
        .get_fmt = ov2685_get_fmt,
        .set_fmt = ov2685_set_fmt,
+       .get_selection = ov2685_get_selection,
+       .set_selection = ov2685_get_selection,
 };
 
 static const struct v4l2_subdev_ops ov2685_subdev_ops = {