#define DW9807_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 DW9807_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 DW9807_CTRL_STEPS 16 #define DW9807_CTRL_DELAY_US 1000
#define DW9807_CTL_ADDR 0x02 /* * DW9807 separates two registers to control the VCM position. * One for MSB value, another is LSB value.
*/ #define DW9807_MSB_ADDR 0x03 #define DW9807_LSB_ADDR 0x04 #define DW9807_STATUS_ADDR 0x05 #define DW9807_MODE_ADDR 0x06 #define DW9807_RESONANCE_ADDR 0x07
ret = i2c_master_send(client, &status_addr, sizeof(status_addr)); if (ret < 0) {
dev_err(&client->dev, "I2C write STATUS address fail ret = %d\n",
ret); return ret;
}
ret = i2c_master_recv(client, &status_result, sizeof(status_result)); if (ret < 0) {
dev_err(&client->dev, "I2C read STATUS value fail ret = %d\n",
ret); return ret;
}
/* * According to the datasheet, need to check the bus status before we * write VCM position. This ensure that we really write the value * into the register
*/
ret = readx_poll_timeout(dw9807_i2c_check, client, val, val <= 0,
DW9807_CTRL_DELAY_US, MAX_RETRY * DW9807_CTRL_DELAY_US);
if (ret || val < 0) { if (ret) {
dev_warn(&client->dev, "Cannot do the write operation because VCM is busy\n");
}
return ret ? -EBUSY : val;
}
/* Write VCM position to registers */
ret = i2c_master_send(client, tx_data, sizeof(tx_data)); if (ret < 0) {
dev_err(&client->dev, "I2C write MSB fail ret=%d\n", ret);
/* * This function sets the vcm position, so it consumes least current * The lens position is gradually moved in units of DW9807_CTRL_STEPS, * to make the movements smoothly.
*/ staticint __maybe_unused dw9807_vcm_suspend(struct device *dev)
{ struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct dw9807_device *dw9807_dev = sd_to_dw9807_vcm(sd); constchar tx_data[2] = { DW9807_CTL_ADDR, 0x01 }; int ret, val;
for (val = dw9807_dev->current_val & ~(DW9807_CTRL_STEPS - 1);
val >= 0; val -= DW9807_CTRL_STEPS) {
ret = dw9807_set_dac(client, val); if (ret)
dev_err_once(dev, "%s I2C failure: %d", __func__, ret);
usleep_range(DW9807_CTRL_DELAY_US, DW9807_CTRL_DELAY_US + 10);
}
/* Power down */
ret = i2c_master_send(client, tx_data, sizeof(tx_data)); if (ret < 0) {
dev_err(&client->dev, "I2C write CTL fail ret = %d\n", ret); return ret;
}
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 DW9807_CTRL_STEPS, * to make the movements smoothly.
*/ staticint __maybe_unused dw9807_vcm_resume(struct device *dev)
{ struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct dw9807_device *dw9807_dev = sd_to_dw9807_vcm(sd); constchar tx_data[2] = { DW9807_CTL_ADDR, 0x00 }; int ret, val;
/* Power on */
ret = i2c_master_send(client, tx_data, sizeof(tx_data)); if (ret < 0) {
dev_err(&client->dev, "I2C write CTL fail ret = %d\n", ret); return ret;
}
for (val = dw9807_dev->current_val % DW9807_CTRL_STEPS;
val < dw9807_dev->current_val + DW9807_CTRL_STEPS - 1;
val += DW9807_CTRL_STEPS) {
ret = dw9807_set_dac(client, val); if (ret)
dev_err_ratelimited(dev, "%s I2C failure: %d",
__func__, ret);
usleep_range(DW9807_CTRL_DELAY_US, DW9807_CTRL_DELAY_US + 10);
}
return 0;
}
staticconststruct of_device_id dw9807_of_table[] = {
{ .compatible = "dongwoon,dw9807-vcm" }, /* Compatibility for older firmware, NEVER USE THIS IN FIRMWARE! */
{ .compatible = "dongwoon,dw9807" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw9807_of_table);
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.