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: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Dave Stevenson 2020-11-19 17:32:34 +01:00 committed by Mauro Carvalho Chehab
parent d7d6074ecd
commit 14f70a3232
1 changed files with 70 additions and 22 deletions

View File

@ -59,25 +59,14 @@
#define VAL_TERM 0xfe #define VAL_TERM 0xfe
#define REG_DLY 0xffff #define REG_DLY 0xffff
#define OV5647_ROW_START 0x01 /* OV5647 native and active pixel array size */
#define OV5647_ROW_START_MIN 0 #define OV5647_NATIVE_WIDTH 2624U
#define OV5647_ROW_START_MAX 2004 #define OV5647_NATIVE_HEIGHT 1956U
#define OV5647_ROW_START_DEF 54
#define OV5647_COLUMN_START 0x02 #define OV5647_PIXEL_ARRAY_LEFT 16U
#define OV5647_COLUMN_START_MIN 0 #define OV5647_PIXEL_ARRAY_TOP 16U
#define OV5647_COLUMN_START_MAX 2750 #define OV5647_PIXEL_ARRAY_WIDTH 2592U
#define OV5647_COLUMN_START_DEF 16 #define OV5647_PIXEL_ARRAY_HEIGHT 1944U
#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
struct regval_list { struct regval_list {
u16 addr; u16 addr;
@ -86,6 +75,7 @@ struct regval_list {
struct ov5647_mode { struct ov5647_mode {
struct v4l2_mbus_framefmt format; struct v4l2_mbus_framefmt format;
struct v4l2_rect crop;
const struct regval_list *reg_list; const struct regval_list *reg_list;
unsigned int num_regs; unsigned int num_regs;
}; };
@ -224,6 +214,12 @@ static const struct ov5647_mode ov5647_8bit_modes[] = {
.width = 640, .width = 640,
.height = 480 .height = 480
}, },
.crop = {
.left = OV5647_PIXEL_ARRAY_LEFT,
.top = OV5647_PIXEL_ARRAY_TOP,
.width = 1280,
.height = 960,
},
.reg_list = ov5647_640x480, .reg_list = ov5647_640x480,
.num_regs = ARRAY_SIZE(ov5647_640x480) .num_regs = ARRAY_SIZE(ov5647_640x480)
}, },
@ -511,6 +507,20 @@ static const struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
#endif #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) static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
{ {
struct ov5647 *sensor = to_sensor(sd); struct ov5647 *sensor = to_sensor(sd);
@ -580,11 +590,49 @@ static int ov5647_set_get_fmt(struct v4l2_subdev *sd,
return 0; 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 = { static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
.enum_mbus_code = ov5647_enum_mbus_code, .enum_mbus_code = ov5647_enum_mbus_code,
.enum_frame_size = ov5647_enum_frame_size, .enum_frame_size = ov5647_enum_frame_size,
.set_fmt = ov5647_set_get_fmt, .set_fmt = ov5647_set_get_fmt,
.get_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 = { 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); v4l2_subdev_get_try_format(sd, fh->pad, 0);
struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->pad, 0); struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->pad, 0);
crop->left = OV5647_COLUMN_START_DEF; crop->left = OV5647_PIXEL_ARRAY_LEFT;
crop->top = OV5647_ROW_START_DEF; crop->top = OV5647_PIXEL_ARRAY_TOP;
crop->width = OV5647_WINDOW_WIDTH_DEF; crop->width = OV5647_PIXEL_ARRAY_WIDTH;
crop->height = OV5647_WINDOW_HEIGHT_DEF; crop->height = OV5647_PIXEL_ARRAY_HEIGHT;
*format = OV5647_DEFAULT_FORMAT; *format = OV5647_DEFAULT_FORMAT;