From 2cf876942e67e418d4da6598af8277500f99cab6 Mon Sep 17 00:00:00 2001 From: Hu Kejun Date: Fri, 23 Feb 2024 12:20:58 +0800 Subject: [PATCH] media: i2c: lens: fix motor is closed after execute v4l2-ctl Signed-off-by: Hu Kejun Change-Id: I76060b416f4ce84cc1881c952ec1d6ca46eeede2 --- drivers/media/i2c/ces6301.c | 61 +++++++++++++++++-------------- drivers/media/i2c/dw9763.c | 69 +++++++++++++++++++---------------- drivers/media/i2c/dw9800v.c | 72 ++++++++++++++++++++----------------- 3 files changed, 111 insertions(+), 91 deletions(-) diff --git a/drivers/media/i2c/ces6301.c b/drivers/media/i2c/ces6301.c index 95391d6acb99..d0c69e09423b 100644 --- a/drivers/media/i2c/ces6301.c +++ b/drivers/media/i2c/ces6301.c @@ -65,6 +65,8 @@ struct ces6301_device { struct regulator *supply; struct i2c_client *client; bool power_on; + + atomic_t open_cnt; }; struct TimeTabel_s { @@ -532,22 +534,24 @@ static int ces6301_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return rval; } - ces6301_init(client); + if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) { + ces6301_init(client); - dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n", - __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); - move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS); - while (dac <= dev_vcm->current_lens_pos) { - ces6301_set_dac(dev_vcm, dac); - usleep_range(move_time, move_time + 1000); - dac += CES6301_GRADUAL_MOVELENS_STEPS; - if (dac >= dev_vcm->current_lens_pos) - break; - } + dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n", + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); + move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS); + while (dac <= dev_vcm->current_lens_pos) { + ces6301_set_dac(dev_vcm, dac); + usleep_range(move_time, move_time + 1000); + dac += CES6301_GRADUAL_MOVELENS_STEPS; + if (dac >= dev_vcm->current_lens_pos) + break; + } - if (dac > dev_vcm->current_lens_pos) { - dac = dev_vcm->current_lens_pos; - ces6301_set_dac(dev_vcm, dac); + if (dac > dev_vcm->current_lens_pos) { + dac = dev_vcm->current_lens_pos; + ces6301_set_dac(dev_vcm, dac); + } } return 0; @@ -560,20 +564,22 @@ static int ces6301_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) int dac = dev_vcm->current_lens_pos; unsigned int move_time; - dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n", - __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); - move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS); - while (dac >= 0) { - ces6301_set_dac(dev_vcm, dac); - usleep_range(move_time, move_time + 1000); - dac -= CES6301_GRADUAL_MOVELENS_STEPS; - if (dac <= 0) - break; - } + if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) { + dev_dbg(&client->dev, "%s: current_lens_pos %d, current_related_pos %d\n", + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); + move_time = 1000 * ces6301_move_time(dev_vcm, CES6301_GRADUAL_MOVELENS_STEPS); + while (dac >= 0) { + ces6301_set_dac(dev_vcm, dac); + usleep_range(move_time, move_time + 1000); + dac -= CES6301_GRADUAL_MOVELENS_STEPS; + if (dac <= 0) + break; + } - if (dac < 0) { - dac = 0; - ces6301_set_dac(dev_vcm, dac); + if (dac < 0) { + dac = 0; + ces6301_set_dac(dev_vcm, dac); + } } pm_runtime_put(sd->dev); @@ -1053,6 +1059,7 @@ static int ces6301_probe(struct i2c_client *client, ces6301_dev->end_move_tv = ns_to_kernel_old_timeval(ktime_get_ns()); ces6301_dev->vcm_movefull_t = ces6301_move_time(ces6301_dev, CES6301_MAX_REG); + atomic_set(&ces6301_dev->open_cnt, 0); pm_runtime_enable(&client->dev); add_sysfs_interfaces(&client->dev); diff --git a/drivers/media/i2c/dw9763.c b/drivers/media/i2c/dw9763.c index d238f59da106..d3d0173fb90e 100644 --- a/drivers/media/i2c/dw9763.c +++ b/drivers/media/i2c/dw9763.c @@ -77,6 +77,8 @@ struct dw9763_device { struct mutex lock; struct regulator *supply; bool power_on; + + atomic_t open_cnt; }; static inline struct dw9763_device *to_dw9763_vcm(struct v4l2_ctrl *ctrl) @@ -405,23 +407,25 @@ static int dw9763_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) return rval; } - dw9763_init(client); + if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) { + dw9763_init(client); - v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", - __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); + v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); - move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS); - while (dac <= dev_vcm->current_lens_pos) { - dw9763_set_dac(dev_vcm, dac); - usleep_range(move_time, move_time + 100); - dac += DW9763_GRADUAL_MOVELENS_STEPS; - if (dac > dev_vcm->current_lens_pos) - break; - } + move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS); + while (dac <= dev_vcm->current_lens_pos) { + dw9763_set_dac(dev_vcm, dac); + usleep_range(move_time, move_time + 100); + dac += DW9763_GRADUAL_MOVELENS_STEPS; + if (dac > dev_vcm->current_lens_pos) + break; + } - if (dac > dev_vcm->current_lens_pos) { - dac = dev_vcm->current_lens_pos; - dw9763_set_dac(dev_vcm, dac); + if (dac > dev_vcm->current_lens_pos) { + dac = dev_vcm->current_lens_pos; + dw9763_set_dac(dev_vcm, dac); + } } #ifdef CONFIG_PM @@ -444,27 +448,29 @@ static int dw9763_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) atomic_read(&sd->dev->power.usage_count)); #endif - v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", - __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); + if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) { + v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); - dac -= DW9763_GRADUAL_MOVELENS_STEPS; - move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS); - while (dac >= DW9763_GRADUAL_MOVELENS_STEPS) { - dw9763_set_dac(dev_vcm, dac); - usleep_range(move_time, move_time + 1000); dac -= DW9763_GRADUAL_MOVELENS_STEPS; - if (dac <= 0) - break; - } + move_time = 1000 * dw9763_move_time(dev_vcm, DW9763_GRADUAL_MOVELENS_STEPS); + while (dac >= DW9763_GRADUAL_MOVELENS_STEPS) { + dw9763_set_dac(dev_vcm, dac); + usleep_range(move_time, move_time + 1000); + dac -= DW9763_GRADUAL_MOVELENS_STEPS; + if (dac <= 0) + break; + } - if (dac < DW9763_GRADUAL_MOVELENS_STEPS) { - dac = DW9763_GRADUAL_MOVELENS_STEPS / 2; - dw9763_set_dac(dev_vcm, dac); + if (dac < DW9763_GRADUAL_MOVELENS_STEPS) { + dac = DW9763_GRADUAL_MOVELENS_STEPS / 2; + dw9763_set_dac(dev_vcm, dac); + } + /* set to power down mode */ + ret = dw9763_write_reg(client, 0x02, 1, 0x01); + if (ret) + dev_err(&client->dev, "failed to set power down mode!\n"); } - /* set to power down mode */ - ret = dw9763_write_reg(client, 0x02, 1, 0x01); - if (ret) - dev_err(&client->dev, "failed to set power down mode!\n"); pm_runtime_put(sd->dev); #ifdef CONFIG_PM @@ -926,6 +932,7 @@ static int dw9763_probe(struct i2c_client *client, dw9763_dev->vcm_movefull_t = dw9763_move_time(dw9763_dev, DW9763_MAX_REG); + atomic_set(&dw9763_dev->open_cnt, 0); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); diff --git a/drivers/media/i2c/dw9800v.c b/drivers/media/i2c/dw9800v.c index 79a2a5691566..f6468f45075a 100644 --- a/drivers/media/i2c/dw9800v.c +++ b/drivers/media/i2c/dw9800v.c @@ -85,6 +85,7 @@ struct dw9800v_device { struct i2c_client *client; bool power_on; + atomic_t open_cnt; }; static inline struct dw9800v_device *to_dw9800v_vcm(struct v4l2_ctrl *ctrl) @@ -426,24 +427,27 @@ static int dw9800v_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) pm_runtime_put_noidle(sd->dev); return rval; } - dw9800v_init(client); - usleep_range(1000, 1200); - v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", - __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); + if (dev_vcm->power_on && atomic_inc_return(&dev_vcm->open_cnt) == 1) { + dw9800v_init(client); - move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS); - while (dac <= dev_vcm->current_lens_pos) { - dw9800v_set_dac(dev_vcm, dac); - usleep_range(move_time, move_time + 1000); - dac += DW9800V_GRADUAL_MOVELENS_STEPS; - if (dac >= dev_vcm->current_lens_pos) - break; - } + usleep_range(1000, 1200); + v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); - if (dac > dev_vcm->current_lens_pos) { - dac = dev_vcm->current_lens_pos; - dw9800v_set_dac(dev_vcm, dac); + move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS); + while (dac <= dev_vcm->current_lens_pos) { + dw9800v_set_dac(dev_vcm, dac); + usleep_range(move_time, move_time + 1000); + dac += DW9800V_GRADUAL_MOVELENS_STEPS; + if (dac >= dev_vcm->current_lens_pos) + break; + } + + if (dac > dev_vcm->current_lens_pos) { + dac = dev_vcm->current_lens_pos; + dw9800v_set_dac(dev_vcm, dac); + } } #ifdef CONFIG_PM @@ -465,23 +469,25 @@ static int dw9800v_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) v4l2_info(sd, "%s: enter, power.usage_count(%d)!\n", __func__, atomic_read(&sd->dev->power.usage_count)); #endif - v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", - __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); - move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS); - while (dac >= DW9800V_GRADUAL_MOVELENS_STEPS) { - dw9800v_set_dac(dev_vcm, dac); - usleep_range(move_time, move_time + 1000); - dac -= DW9800V_GRADUAL_MOVELENS_STEPS; - if (dac <= 0) - break; - } + if (dev_vcm->power_on && atomic_dec_return(&dev_vcm->open_cnt) == 0) { + v4l2_dbg(1, debug, sd, "%s: current_lens_pos %d, current_related_pos %d\n", + __func__, dev_vcm->current_lens_pos, dev_vcm->current_related_pos); + move_time = dw9800v_move_time(dev_vcm, DW9800V_GRADUAL_MOVELENS_STEPS); + while (dac >= DW9800V_GRADUAL_MOVELENS_STEPS) { + dw9800v_set_dac(dev_vcm, dac); + usleep_range(move_time, move_time + 1000); + dac -= DW9800V_GRADUAL_MOVELENS_STEPS; + if (dac <= 0) + break; + } - if (dac < DW9800V_GRADUAL_MOVELENS_STEPS) { - dac = DW9800V_GRADUAL_MOVELENS_STEPS; - dw9800v_set_dac(dev_vcm, dac); + if (dac < DW9800V_GRADUAL_MOVELENS_STEPS) { + dac = DW9800V_GRADUAL_MOVELENS_STEPS; + dw9800v_set_dac(dev_vcm, dac); + } + /* set to power down mode */ + dw9800v_write_reg(client, 0x02, 1, 0x01); } - /* set to power down mode */ - dw9800v_write_reg(client, 0x02, 1, 0x01); pm_runtime_put(sd->dev); @@ -926,6 +932,8 @@ static int dw9800v_probe(struct i2c_client *client, dw9800v_dev->vcm_movefull_t = dw9800v_move_time(dw9800v_dev, DW9800V_MAX_REG); + atomic_set(&dw9800v_dev->open_cnt, 0); + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); @@ -943,14 +951,12 @@ err_power_off: return ret; } -static int dw9800v_remove(struct i2c_client *client) +static void dw9800v_remove(struct i2c_client *client) { struct dw9800v_device *dw9800v_dev = i2c_get_clientdata(client); pm_runtime_disable(&client->dev); dw9800v_subdev_cleanup(dw9800v_dev); - - return 0; } static int dw9800v_init(struct i2c_client *client)