r = i2c_transfer(client->adapter, &msg, 1); if (r < 0) {
dev_err(&client->dev, "write failed, error %d\n", r); return r;
}
return 0;
}
/* * Calculate status word and write it to the device based on current * values of V4L2 controls. It is assumed that the stored V4L2 control * values are properly limited and rounded.
*/ staticint ad5820_update_hw(struct ad5820_device *coil)
{
u16 status;
status = RAMP_US_TO_CODE(coil->focus_ramp_time);
status |= coil->focus_ramp_mode
? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR;
status |= coil->focus_absolute << AD5820_DAC_SHIFT;
if (coil->standby)
status |= AD5820_POWER_DOWN;
return ad5820_write(coil, status);
}
/* * Power handling
*/ staticint ad5820_power_off(struct ad5820_device *coil, bool standby)
{ int ret = 0, ret2;
/* * Go to standby first as real power off my be denied by the hardware * (single power line control for both coil and sensor).
*/ if (standby) {
coil->standby = true;
ret = ad5820_update_hw(coil);
}
gpiod_set_value_cansleep(coil->enable_gpio, 0);
ret2 = regulator_disable(coil->vana); if (ret) return ret; return ret2;
}
staticint ad5820_power_on(struct ad5820_device *coil, bool restore)
{ int ret;
ret = regulator_enable(coil->vana); if (ret < 0) return ret;
gpiod_set_value_cansleep(coil->enable_gpio, 1);
if (restore) { /* Restore the hardware settings. */
coil->standby = false;
ret = ad5820_update_hw(coil); if (ret) goto fail;
} return 0;
/* * V4L2_CID_FOCUS_ABSOLUTE * * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA] * for focus position, because it is meaningless for user. Meaningful * would be to use focus distance or even its inverse, but since the * driver doesn't have sufficiently knowledge to do the conversion, we * will just use abstract codes here. In any case, smaller value = focus * position farther from camera. The default zero value means focus at * infinity, and also least current consumption.
*/
v4l2_ctrl_new_std(&coil->ctrls, &ad5820_ctrl_ops,
V4L2_CID_FOCUS_ABSOLUTE, 0, 1023, 1, 0);
staticint
ad5820_set_power(struct v4l2_subdev *subdev, int on)
{ struct ad5820_device *coil = to_ad5820_device(subdev); int ret = 0;
mutex_lock(&coil->power_lock);
/* * If the power count is modified from 0 to != 0 or from != 0 to 0, * update the power state.
*/ if (coil->power_count == !on) {
ret = on ? ad5820_power_on(coil, true) :
ad5820_power_off(coil, true); if (ret < 0) goto done;
}
/* Update the power count. */
coil->power_count += on ? 1 : -1;
WARN_ON(coil->power_count < 0);
staticint ad5820_probe(struct i2c_client *client)
{ struct ad5820_device *coil; int ret;
coil = devm_kzalloc(&client->dev, sizeof(*coil), GFP_KERNEL); if (!coil) return -ENOMEM;
coil->vana = devm_regulator_get(&client->dev, "VANA"); if (IS_ERR(coil->vana)) return dev_err_probe(&client->dev, PTR_ERR(coil->vana), "could not get regulator for vana\n");
coil->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
GPIOD_OUT_LOW); if (IS_ERR(coil->enable_gpio)) return dev_err_probe(&client->dev, PTR_ERR(coil->enable_gpio), "could not get enable gpio\n");
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.