#define DW9714_NAME "dw9714" #define DW9714_MAX_FOCUS_POS 1023 /* * This sets the minimum granularity for the focus positions. * A value of 1 gives maximum accuracy for a desired focus position
*/ #define DW9714_FOCUS_STEPS 1 /* * This acts as the minimum granularity of lens movement. * Keep this value power of 2, so the control steps can be * uniformly adjusted for gradual lens movement, with desired * number of control steps.
*/ #define DW9714_CTRL_STEPS 16 #define DW9714_CTRL_DELAY_US 1000 /* * S[3:2] = 0x00, codes per step for "Linear Slope Control" * S[1:0] = 0x00, step period
*/ #define DW9714_DEFAULT_S 0x0 #define DW9714_VAL(data, s) ((data) << 4 | (s))
staticint dw9714_probe(struct i2c_client *client)
{ struct dw9714_device *dw9714_dev; int rval;
dw9714_dev = devm_kzalloc(&client->dev, sizeof(*dw9714_dev),
GFP_KERNEL); if (!dw9714_dev) return -ENOMEM;
dw9714_dev->vcc = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(dw9714_dev->vcc)) return PTR_ERR(dw9714_dev->vcc);
dw9714_dev->powerdown_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
GPIOD_OUT_HIGH); if (IS_ERR(dw9714_dev->powerdown_gpio)) return dev_err_probe(&client->dev,
PTR_ERR(dw9714_dev->powerdown_gpio), "could not get powerdown gpio\n");
rval = dw9714_power_up(dw9714_dev); if (rval) return dev_err_probe(&client->dev, rval, "failed to power up: %d\n", rval);
pm_runtime_disable(&client->dev); if (!pm_runtime_status_suspended(&client->dev)) {
ret = dw9714_power_down(dw9714_dev); if (ret) {
dev_err(&client->dev, "Failed to power down: %d\n", ret);
}
}
pm_runtime_set_suspended(&client->dev);
dw9714_subdev_cleanup(dw9714_dev);
}
/* * This function sets the vcm position, so it consumes least current * The lens position is gradually moved in units of DW9714_CTRL_STEPS, * to make the movements smoothly.
*/ staticint __maybe_unused dw9714_vcm_suspend(struct device *dev)
{ struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd); int ret, val;
if (pm_runtime_suspended(&client->dev)) return 0;
for (val = dw9714_dev->current_val & ~(DW9714_CTRL_STEPS - 1);
val >= 0; val -= DW9714_CTRL_STEPS) {
ret = dw9714_i2c_write(client,
DW9714_VAL(val, DW9714_DEFAULT_S)); if (ret)
dev_err_once(dev, "%s I2C failure: %d", __func__, ret);
usleep_range(DW9714_CTRL_DELAY_US, DW9714_CTRL_DELAY_US + 10);
}
ret = dw9714_power_down(dw9714_dev); if (ret)
dev_err(dev, "Failed to power down: %d\n", ret);
return ret;
}
/* * This function sets the vcm position to the value set by the user * through v4l2_ctrl_ops s_ctrl handler * The lens position is gradually moved in units of DW9714_CTRL_STEPS, * to make the movements smoothly.
*/ staticint __maybe_unused dw9714_vcm_resume(struct device *dev)
{ struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct dw9714_device *dw9714_dev = sd_to_dw9714_vcm(sd); int ret, val;
if (pm_runtime_suspended(&client->dev)) return 0;
ret = dw9714_power_up(dw9714_dev); if (ret) {
dev_err(dev, "Failed to power up: %d\n", ret); return ret;
}
for (val = dw9714_dev->current_val % DW9714_CTRL_STEPS;
val < dw9714_dev->current_val + DW9714_CTRL_STEPS - 1;
val += DW9714_CTRL_STEPS) {
ret = dw9714_i2c_write(client,
DW9714_VAL(val, DW9714_DEFAULT_S)); if (ret)
dev_err_ratelimited(dev, "%s I2C failure: %d",
__func__, ret);
usleep_range(DW9714_CTRL_DELAY_US, DW9714_CTRL_DELAY_US + 10);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.