struct ak73xx_chipdef {
u8 reg_position;
u8 reg_cont;
u8 shift_pos;
u8 mode_active;
u8 mode_standby; bool has_standby; /* Some chips may not have standby mode */
u16 focus_pos_max; /* * This sets the minimum granularity for the focus positions. * A value of 1 gives maximum accuracy for a desired focus position
*/
u16 focus_steps; /* * 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.
*/
u16 ctrl_steps;
u16 ctrl_delay_us; /* * The vcm may take time (tDELAY) to power on and start taking * I2C messages.
*/
u16 power_delay_us;
};
for (i = 0; i < ARRAY_SIZE(ak7375_supply_names); i++)
ak7375_dev->supplies[i].supply = ak7375_supply_names[i];
ret = devm_regulator_bulk_get(&client->dev,
ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies); if (ret) {
dev_err_probe(&client->dev, ret, "Failed to get regulators\n"); return ret;
}
/* * This function sets the vcm position, so it consumes least current * The lens position is gradually moved in units of ctrl_steps, * to make the movements smoothly.
*/ staticint __maybe_unused ak7375_vcm_suspend(struct device *dev)
{ struct v4l2_subdev *sd = dev_get_drvdata(dev); struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd); conststruct ak73xx_chipdef *cdef = ak7375_dev->cdef; int ret, val;
if (!ak7375_dev->active) return 0;
for (val = ak7375_dev->focus->val & ~(cdef->ctrl_steps - 1);
val >= 0; val -= cdef->ctrl_steps) {
ret = ak7375_i2c_write(ak7375_dev, cdef->reg_position,
val << cdef->shift_pos, 2); if (ret)
dev_err_once(dev, "%s I2C failure: %d\n",
__func__, ret);
usleep_range(cdef->ctrl_delay_us, cdef->ctrl_delay_us + 10);
}
if (cdef->has_standby) {
ret = ak7375_i2c_write(ak7375_dev, cdef->reg_cont,
cdef->mode_standby, 1); if (ret)
dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
}
ret = regulator_bulk_disable(ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies); if (ret) return ret;
ak7375_dev->active = false;
return 0;
}
/* * 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 ctrl_steps, * to make the movements smoothly.
*/ staticint __maybe_unused ak7375_vcm_resume(struct device *dev)
{ struct v4l2_subdev *sd = dev_get_drvdata(dev); struct ak7375_device *ak7375_dev = sd_to_ak7375_vcm(sd); conststruct ak73xx_chipdef *cdef = ak7375_dev->cdef; int ret, val;
if (ak7375_dev->active) return 0;
ret = regulator_bulk_enable(ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies); if (ret) return ret;
/* Wait for vcm to become ready */
usleep_range(cdef->power_delay_us, cdef->power_delay_us + 500);
ret = ak7375_i2c_write(ak7375_dev, cdef->reg_cont,
cdef->mode_active, 1); if (ret) {
dev_err(dev, "%s I2C failure: %d\n", __func__, ret); return ret;
}
for (val = ak7375_dev->focus->val % cdef->ctrl_steps;
val <= ak7375_dev->focus->val;
val += cdef->ctrl_steps) {
ret = ak7375_i2c_write(ak7375_dev, cdef->reg_position,
val << cdef->shift_pos, 2); if (ret)
dev_err_ratelimited(dev, "%s I2C failure: %d\n",
__func__, ret);
usleep_range(cdef->ctrl_delay_us, cdef->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.