media: i2c: lens: fix motor is closed after execute v4l2-ctl

Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
Change-Id: I76060b416f4ce84cc1881c952ec1d6ca46eeede2
This commit is contained in:
Hu Kejun
2024-02-23 12:20:58 +08:00
committed by Tao Huang
parent f2bcf24c33
commit 2cf876942e
3 changed files with 111 additions and 91 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)