Skip to content

Commit

Permalink
media: ov5647: Advertise the correct exposure range
Browse files Browse the repository at this point in the history
Exposure is clipped by the VTS of the mode, so it needs to be updated
when this is changed.

Signed-off-by: Dave Stevenson <[email protected]>
Signed-off-by: Jacopo Mondi <[email protected]>
Signed-off-by: Sakari Ailus <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
6by9 authored and mchehab committed Jan 12, 2021
1 parent 2512c06 commit 646a024
Showing 1 changed file with 35 additions and 4 deletions.
39 changes: 35 additions & 4 deletions drivers/media/i2c/ov5647.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@
#define OV5647_VBLANK_MIN 4
#define OV5647_VTS_MAX 32767

#define OV5647_EXPOSURE_MIN 4
#define OV5647_EXPOSURE_STEP 1
#define OV5647_EXPOSURE_DEFAULT 1000
#define OV5647_EXPOSURE_MAX 65535

struct regval_list {
u16 addr;
u8 data;
Expand Down Expand Up @@ -107,6 +112,7 @@ struct ov5647 {
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *exposure;
};

static inline struct ov5647 *to_sensor(struct v4l2_subdev *sd)
Expand Down Expand Up @@ -1092,6 +1098,7 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt = &format->format;
const struct ov5647_mode *ov5647_mode_list;
struct ov5647 *sensor = to_sensor(sd);

const struct ov5647_mode *mode;
unsigned int num_modes;
unsigned int i;
Expand Down Expand Up @@ -1123,6 +1130,7 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd,
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_get_try_format(sd, cfg, format->pad) = mode->format;
} else {
int exposure_max, exposure_def;
int hblank, vblank;

sensor->mode = mode;
Expand All @@ -1138,6 +1146,13 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd,
OV5647_VTS_MAX - mode->format.height,
1, vblank);
__v4l2_ctrl_s_ctrl(sensor->vblank, vblank);

exposure_max = mode->vts - 4;
exposure_def = min(exposure_max, OV5647_EXPOSURE_DEFAULT);
__v4l2_ctrl_modify_range(sensor->exposure,
sensor->exposure->minimum,
exposure_max, sensor->exposure->step,
exposure_def);
}
*fmt = mode->format;
mutex_unlock(&sensor->lock);
Expand Down Expand Up @@ -1324,6 +1339,18 @@ static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl)

/* v4l2_ctrl_lock() locks our own mutex */

if (ctrl->id == V4L2_CID_VBLANK) {
int exposure_max, exposure_def;

/* Update max exposure while meeting expected vblanking */
exposure_max = sensor->mode->format.height + ctrl->val - 4;
exposure_def = min(exposure_max, OV5647_EXPOSURE_DEFAULT);
__v4l2_ctrl_modify_range(sensor->exposure,
sensor->exposure->minimum,
exposure_max, sensor->exposure->step,
exposure_def);
}

/*
* If the device is not powered up by the host driver do
* not apply any controls to H/W at this time. Instead
Expand Down Expand Up @@ -1369,7 +1396,7 @@ static const struct v4l2_ctrl_ops ov5647_ctrl_ops = {
static int ov5647_init_controls(struct ov5647 *sensor)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->sd);
int hblank;
int hblank, exposure_max, exposure_def;

v4l2_ctrl_handler_init(&sensor->ctrls, 8);

Expand All @@ -1383,9 +1410,13 @@ static int ov5647_init_controls(struct ov5647 *sensor)
V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL,
0, V4L2_EXPOSURE_MANUAL);

/* min: 4 lines; max: 0xffff lines; default: 1000 lines. */
v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
V4L2_CID_EXPOSURE, 4, 65535, 1, 1000);
exposure_max = sensor->mode->vts - 4;
exposure_def = min(exposure_max, OV5647_EXPOSURE_DEFAULT);
sensor->exposure = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
V4L2_CID_EXPOSURE,
OV5647_EXPOSURE_MIN,
exposure_max, OV5647_EXPOSURE_STEP,
exposure_def);

/* min: 16 = 1.0x; max (10 bits); default: 32 = 2.0x. */
v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
Expand Down

0 comments on commit 646a024

Please sign in to comment.