[PATCH 4.19 044/205] media: ov5640: fix restore of last mode set

From: Greg Kroah-Hartman
Date: Mon Nov 19 2018 - 11:32:05 EST


4.19-stable review patch. If anyone has any objections, please let me know.

------------------

From: Hugues Fruchet <hugues.fruchet@xxxxxx>

[ Upstream commit 985cdcb08a0488558d1005139596b64d73bee267 ]

Mode setting depends on last mode set, in particular
because of exposure calculation when downscale mode
change between subsampling and scaling.
At stream on the last mode was wrongly set to current mode,
so no change was detected and exposure calculation
was not made, fix this.

Signed-off-by: Hugues Fruchet <hugues.fruchet@xxxxxx>
Reviewed-by: Jacopo Mondi <jacopo@xxxxxxxxxx>
Tested-by: Jacopo Mondi <jacopo@xxxxxxxxxx>
Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@xxxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/media/i2c/ov5640.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -226,6 +226,7 @@ struct ov5640_dev {
bool pending_fmt_change;

const struct ov5640_mode_info *current_mode;
+ const struct ov5640_mode_info *last_mode;
enum ov5640_frame_rate current_fr;
struct v4l2_fract frame_interval;

@@ -1614,10 +1615,10 @@ static int ov5640_set_mode_direct(struct
return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure);
}

-static int ov5640_set_mode(struct ov5640_dev *sensor,
- const struct ov5640_mode_info *orig_mode)
+static int ov5640_set_mode(struct ov5640_dev *sensor)
{
const struct ov5640_mode_info *mode = sensor->current_mode;
+ const struct ov5640_mode_info *orig_mode = sensor->last_mode;
enum ov5640_downsize_mode dn_mode, orig_dn_mode;
s32 exposure;
int ret;
@@ -1674,6 +1675,7 @@ static int ov5640_set_mode(struct ov5640
return ret;

sensor->pending_mode_change = false;
+ sensor->last_mode = mode;

return 0;
}
@@ -1690,6 +1692,7 @@ static int ov5640_restore_mode(struct ov
ret = ov5640_load_regs(sensor, &ov5640_mode_init_data);
if (ret < 0)
return ret;
+ sensor->last_mode = &ov5640_mode_init_data;

ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
(ilog2(OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT) << 2) |
@@ -1698,7 +1701,7 @@ static int ov5640_restore_mode(struct ov
return ret;

/* now restore the last capture mode */
- ret = ov5640_set_mode(sensor, &ov5640_mode_init_data);
+ ret = ov5640_set_mode(sensor);
if (ret < 0)
return ret;

@@ -2545,7 +2548,7 @@ static int ov5640_s_stream(struct v4l2_s

if (sensor->streaming == !enable) {
if (enable && sensor->pending_mode_change) {
- ret = ov5640_set_mode(sensor, sensor->current_mode);
+ ret = ov5640_set_mode(sensor);
if (ret)
goto out;
}
@@ -2668,6 +2671,7 @@ static int ov5640_probe(struct i2c_clien
sensor->current_fr = OV5640_30_FPS;
sensor->current_mode =
&ov5640_mode_data[OV5640_30_FPS][OV5640_MODE_VGA_640_480];
+ sensor->last_mode = sensor->current_mode;

sensor->ae_target = 52;