Commit b4e28166 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

media: atomisp-ov2722: use v4l2_find_nearest_size()

Instead of reinventing the wheel, use v4l2_find_nearest_size()
in order to get the closest resolution.

This should address a bug where the wrong resolution was
selected.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent b7573661
......@@ -557,7 +557,7 @@ static int ov2722_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
ret = ov2722_g_fnumber_range(&dev->sd, &ctrl->val);
break;
case V4L2_CID_LINK_FREQ:
val = ov2722_res[dev->fmt_idx].mipi_freq;
val = dev->res->mipi_freq;
if (val == 0)
return -EINVAL;
......@@ -782,76 +782,6 @@ static int ov2722_s_power(struct v4l2_subdev *sd, int on)
return ret;
}
/*
* distance - calculate the distance
* @res: resolution
* @w: width
* @h: height
*
* Get the gap between resolution and w/h.
* res->width/height smaller than w/h wouldn't be considered.
* Returns the value of gap or -1 if fail.
*/
#define LARGEST_ALLOWED_RATIO_MISMATCH 800
static int distance(struct ov2722_resolution *res, u32 w, u32 h)
{
unsigned int w_ratio = (res->width << 13) / w;
unsigned int h_ratio;
int match;
if (h == 0)
return -1;
h_ratio = (res->height << 13) / h;
if (h_ratio == 0)
return -1;
match = abs(((w_ratio << 13) / h_ratio) - 8192);
if ((w_ratio < 8192) || (h_ratio < 8192) ||
(match > LARGEST_ALLOWED_RATIO_MISMATCH))
return -1;
return w_ratio + h_ratio;
}
/* Return the nearest higher resolution index */
static int nearest_resolution_index(int w, int h)
{
int i;
int idx = -1;
int dist;
int min_dist = INT_MAX;
struct ov2722_resolution *tmp_res = NULL;
for (i = 0; i < N_RES; i++) {
tmp_res = &ov2722_res[i];
dist = distance(tmp_res, w, h);
if (dist == -1)
continue;
if (dist < min_dist) {
min_dist = dist;
idx = i;
}
}
return idx;
}
static int get_resolution_index(int w, int h)
{
int i;
for (i = 0; i < N_RES; i++) {
if (w != ov2722_res[i].width)
continue;
if (h != ov2722_res[i].height)
continue;
return i;
}
return -1;
}
/* TODO: remove it. */
static int startup(struct v4l2_subdev *sd)
{
......@@ -866,7 +796,7 @@ static int startup(struct v4l2_subdev *sd)
return ret;
}
ret = ov2722_write_reg_array(client, ov2722_res[dev->fmt_idx].regs);
ret = ov2722_write_reg_array(client, dev->res->regs);
if (ret) {
dev_err(&client->dev, "ov2722 write register err.\n");
return ret;
......@@ -882,9 +812,9 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt = &format->format;
struct ov2722_device *dev = to_ov2722_sensor(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2722_resolution *res;
struct camera_mipi_info *ov2722_info = NULL;
int ret = 0;
int idx;
if (format->pad)
return -EINVAL;
......@@ -895,15 +825,16 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd,
return -EINVAL;
mutex_lock(&dev->input_lock);
idx = nearest_resolution_index(fmt->width, fmt->height);
if (idx == -1) {
/* return the largest resolution */
fmt->width = ov2722_res[N_RES - 1].width;
fmt->height = ov2722_res[N_RES - 1].height;
} else {
fmt->width = ov2722_res[idx].width;
fmt->height = ov2722_res[idx].height;
}
res = v4l2_find_nearest_size(ov2722_res_preview,
ARRAY_SIZE(ov2722_res_preview), width,
height, fmt->width, fmt->height);
if (!res)
res = &ov2722_res_preview[N_RES - 1];
fmt->width = res->width;
fmt->height = res->height;
dev->res = res;
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
sd_state->pads->try_fmt = *fmt;
......@@ -911,15 +842,9 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd,
return 0;
}
dev->fmt_idx = get_resolution_index(fmt->width, fmt->height);
if (dev->fmt_idx == -1) {
dev_err(&client->dev, "get resolution fail\n");
mutex_unlock(&dev->input_lock);
return -EINVAL;
}
dev->pixels_per_line = ov2722_res[dev->fmt_idx].pixels_per_line;
dev->lines_per_frame = ov2722_res[dev->fmt_idx].lines_per_frame;
dev->pixels_per_line = dev->res->pixels_per_line;
dev->lines_per_frame = dev->res->lines_per_frame;
ret = startup(sd);
if (ret) {
......@@ -950,8 +875,7 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd,
}
}
ret = ov2722_get_intg_factor(client, ov2722_info,
&ov2722_res[dev->fmt_idx]);
ret = ov2722_get_intg_factor(client, ov2722_info, dev->res);
if (ret)
dev_err(&client->dev, "failed to get integration_factor\n");
......@@ -972,8 +896,8 @@ static int ov2722_get_fmt(struct v4l2_subdev *sd,
if (!fmt)
return -EINVAL;
fmt->width = ov2722_res[dev->fmt_idx].width;
fmt->height = ov2722_res[dev->fmt_idx].height;
fmt->width = dev->res->width;
fmt->height = dev->res->height;
fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
return 0;
......@@ -1098,7 +1022,7 @@ static int ov2722_g_frame_interval(struct v4l2_subdev *sd,
struct ov2722_device *dev = to_ov2722_sensor(sd);
interval->interval.numerator = 1;
interval->interval.denominator = ov2722_res[dev->fmt_idx].fps;
interval->interval.denominator = dev->res->fps;
return 0;
}
......@@ -1136,7 +1060,7 @@ static int ov2722_g_skip_frames(struct v4l2_subdev *sd, u32 *frames)
struct ov2722_device *dev = to_ov2722_sensor(sd);
mutex_lock(&dev->input_lock);
*frames = ov2722_res[dev->fmt_idx].skip_frames;
*frames = dev->res->skip_frames;
mutex_unlock(&dev->input_lock);
return 0;
......@@ -1220,7 +1144,7 @@ static int ov2722_probe(struct i2c_client *client)
mutex_init(&dev->input_lock);
dev->fmt_idx = 0;
dev->res = &ov2722_res_preview[0];
v4l2_i2c_subdev_init(&dev->sd, client, &ov2722_ops);
ovpdev = gmin_camera_platform_data(&dev->sd,
......
......@@ -201,14 +201,13 @@ struct ov2722_device {
struct media_pad pad;
struct v4l2_mbus_framefmt format;
struct mutex input_lock;
struct ov2722_resolution *res;
struct camera_sensor_platform_data *platform_data;
int vt_pix_clk_freq_mhz;
int fmt_idx;
int run_mode;
u16 pixels_per_line;
u16 lines_per_frame;
u8 res;
u8 type;
struct v4l2_ctrl_handler ctrl_handler;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment