Commit 14f70a32 authored by Dave Stevenson's avatar Dave Stevenson Committed by Mauro Carvalho Chehab
Browse files

media: ov5647: Add support for get_selection()



Support the get_selection() pad operation to report the device
full pixel array size, the currently applied analogue crop rectangle and
the active pixel array dimensions.

Signed-off-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: default avatarJacopo Mondi <jacopo@jmondi.org>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent d7d6074e
Loading
Loading
Loading
Loading
+71 −23
Original line number Diff line number Diff line
@@ -59,25 +59,14 @@
#define VAL_TERM 0xfe
#define REG_DLY  0xffff

#define OV5647_ROW_START		0x01
#define OV5647_ROW_START_MIN		0
#define OV5647_ROW_START_MAX		2004
#define OV5647_ROW_START_DEF		54

#define OV5647_COLUMN_START		0x02
#define OV5647_COLUMN_START_MIN		0
#define OV5647_COLUMN_START_MAX		2750
#define OV5647_COLUMN_START_DEF		16

#define OV5647_WINDOW_HEIGHT		0x03
#define OV5647_WINDOW_HEIGHT_MIN	2
#define OV5647_WINDOW_HEIGHT_MAX	2006
#define OV5647_WINDOW_HEIGHT_DEF	1944

#define OV5647_WINDOW_WIDTH		0x04
#define OV5647_WINDOW_WIDTH_MIN		2
#define OV5647_WINDOW_WIDTH_MAX		2752
#define OV5647_WINDOW_WIDTH_DEF		2592
/* OV5647 native and active pixel array size */
#define OV5647_NATIVE_WIDTH		2624U
#define OV5647_NATIVE_HEIGHT		1956U

#define OV5647_PIXEL_ARRAY_LEFT		16U
#define OV5647_PIXEL_ARRAY_TOP		16U
#define OV5647_PIXEL_ARRAY_WIDTH	2592U
#define OV5647_PIXEL_ARRAY_HEIGHT	1944U

struct regval_list {
	u16 addr;
@@ -86,6 +75,7 @@ struct regval_list {

struct ov5647_mode {
	struct v4l2_mbus_framefmt	format;
	struct v4l2_rect		crop;
	const struct regval_list	*reg_list;
	unsigned int			num_regs;
};
@@ -224,6 +214,12 @@ static const struct ov5647_mode ov5647_8bit_modes[] = {
			.width		= 640,
			.height		= 480
		},
		.crop = {
			.left		= OV5647_PIXEL_ARRAY_LEFT,
			.top		= OV5647_PIXEL_ARRAY_TOP,
			.width		= 1280,
			.height		= 960,
		},
		.reg_list	= ov5647_640x480,
		.num_regs	= ARRAY_SIZE(ov5647_640x480)
	},
@@ -511,6 +507,20 @@ static const struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
#endif
};

static const struct v4l2_rect *
__ov5647_get_pad_crop(struct ov5647 *ov5647, struct v4l2_subdev_pad_config *cfg,
		      unsigned int pad, enum v4l2_subdev_format_whence which)
{
	switch (which) {
	case V4L2_SUBDEV_FORMAT_TRY:
		return v4l2_subdev_get_try_crop(&ov5647->sd, cfg, pad);
	case V4L2_SUBDEV_FORMAT_ACTIVE:
		return &ov5647->mode->crop;
	}

	return NULL;
}

static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
{
	struct ov5647 *sensor = to_sensor(sd);
@@ -580,11 +590,49 @@ static int ov5647_set_get_fmt(struct v4l2_subdev *sd,
	return 0;
}

static int ov5647_get_selection(struct v4l2_subdev *sd,
				struct v4l2_subdev_pad_config *cfg,
				struct v4l2_subdev_selection *sel)
{
	switch (sel->target) {
	case V4L2_SEL_TGT_CROP: {
		struct ov5647 *sensor = to_sensor(sd);

		mutex_lock(&sensor->lock);
		sel->r = *__ov5647_get_pad_crop(sensor, cfg, sel->pad,
						sel->which);
		mutex_unlock(&sensor->lock);

		return 0;
	}

	case V4L2_SEL_TGT_NATIVE_SIZE:
		sel->r.top = 0;
		sel->r.left = 0;
		sel->r.width = OV5647_NATIVE_WIDTH;
		sel->r.height = OV5647_NATIVE_HEIGHT;

		return 0;

	case V4L2_SEL_TGT_CROP_DEFAULT:
	case V4L2_SEL_TGT_CROP_BOUNDS:
		sel->r.top = OV5647_PIXEL_ARRAY_TOP;
		sel->r.left = OV5647_PIXEL_ARRAY_LEFT;
		sel->r.width = OV5647_PIXEL_ARRAY_WIDTH;
		sel->r.height = OV5647_PIXEL_ARRAY_HEIGHT;

		return 0;
	}

	return -EINVAL;
}

static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
	.enum_mbus_code		= ov5647_enum_mbus_code,
	.enum_frame_size	= ov5647_enum_frame_size,
	.set_fmt		= ov5647_set_get_fmt,
	.get_fmt		= ov5647_set_get_fmt,
	.get_selection		= ov5647_get_selection,
};

static const struct v4l2_subdev_ops ov5647_subdev_ops = {
@@ -630,10 +678,10 @@ static int ov5647_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
				v4l2_subdev_get_try_format(sd, fh->pad, 0);
	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->pad, 0);

	crop->left = OV5647_COLUMN_START_DEF;
	crop->top = OV5647_ROW_START_DEF;
	crop->width = OV5647_WINDOW_WIDTH_DEF;
	crop->height = OV5647_WINDOW_HEIGHT_DEF;
	crop->left = OV5647_PIXEL_ARRAY_LEFT;
	crop->top = OV5647_PIXEL_ARRAY_TOP;
	crop->width = OV5647_PIXEL_ARRAY_WIDTH;
	crop->height = OV5647_PIXEL_ARRAY_HEIGHT;

	*format = OV5647_DEFAULT_FORMAT;