Commit acd25e22 authored by Daniel Scally's avatar Daniel Scally Committed by Mauro Carvalho Chehab
Browse files

media: i2c: Add .get_selection() support to ov8865



The ov8865 driver's v4l2_subdev_pad_ops currently does not include
.get_selection() - add support for that callback.

Signed-off-by: default avatarDaniel Scally <djrscally@gmail.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 73dcffeb
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
@@ -450,6 +450,15 @@
#define OV8865_PRE_CTRL0_PATTERN_COLOR_SQUARES	2
#define OV8865_PRE_CTRL0_PATTERN_BLACK		3

/* Pixel Array */

#define OV8865_NATIVE_WIDTH			3296
#define OV8865_NATIVE_HEIGHT			2528
#define OV8865_ACTIVE_START_TOP			32
#define OV8865_ACTIVE_START_LEFT		80
#define OV8865_ACTIVE_WIDTH			3264
#define OV8865_ACTIVE_HEIGHT			2448

/* Macros */

#define ov8865_subdev_sensor(s) \
@@ -2756,12 +2765,67 @@ static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev,
	return 0;
}

static void
__ov8865_get_pad_crop(struct ov8865_sensor *sensor,
		      struct v4l2_subdev_state *state, unsigned int pad,
		      enum v4l2_subdev_format_whence which, struct v4l2_rect *r)
{
	const struct ov8865_mode *mode = sensor->state.mode;

	switch (which) {
	case V4L2_SUBDEV_FORMAT_TRY:
		*r = *v4l2_subdev_get_try_crop(&sensor->subdev, state, pad);
		break;
	case V4L2_SUBDEV_FORMAT_ACTIVE:
		r->height = mode->output_size_y;
		r->width = mode->output_size_x;
		r->top = (OV8865_NATIVE_HEIGHT - mode->output_size_y) / 2;
		r->left = (OV8865_NATIVE_WIDTH - mode->output_size_x) / 2;
		break;
	}
}

static int ov8865_get_selection(struct v4l2_subdev *subdev,
				struct v4l2_subdev_state *state,
				struct v4l2_subdev_selection *sel)
{
	struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);

	switch (sel->target) {
	case V4L2_SEL_TGT_CROP:
		mutex_lock(&sensor->mutex);
			__ov8865_get_pad_crop(sensor, state, sel->pad,
					      sel->which, &sel->r);
		mutex_unlock(&sensor->mutex);
		break;
	case V4L2_SEL_TGT_NATIVE_SIZE:
		sel->r.top = 0;
		sel->r.left = 0;
		sel->r.width = OV8865_NATIVE_WIDTH;
		sel->r.height = OV8865_NATIVE_HEIGHT;
		break;
	case V4L2_SEL_TGT_CROP_BOUNDS:
	case V4L2_SEL_TGT_CROP_DEFAULT:
		sel->r.top = OV8865_ACTIVE_START_TOP;
		sel->r.left = OV8865_ACTIVE_START_LEFT;
		sel->r.width = OV8865_ACTIVE_WIDTH;
		sel->r.height = OV8865_ACTIVE_HEIGHT;
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = {
	.enum_mbus_code		= ov8865_enum_mbus_code,
	.get_fmt		= ov8865_get_fmt,
	.set_fmt		= ov8865_set_fmt,
	.enum_frame_size	= ov8865_enum_frame_size,
	.enum_frame_interval	= ov8865_enum_frame_interval,
	.get_selection		= ov8865_get_selection,
	.set_selection		= ov8865_get_selection,
};

static const struct v4l2_subdev_ops ov8865_subdev_ops = {