static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
{
··············
rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
&pdev->id); //获取设备资源信息
CDBG("cell-index %d, rc %d\n", pdev->id, rc);
if (rc < 0) {
kfree(msm_actuator_t);
pr_err("failed rc %d\n", rc);
return rc;
}
/*初始化msm_actuator_t*/
msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
msm_actuator_t->actuator_mutex = &msm_actuator_mutex; //互斥锁
msm_actuator_t->cam_name = pdev->id;
/* Set platform device handle */
msm_actuator_t->pdev = pdev;
/* Set device type as platform device */
msm_actuator_t->act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
msm_actuator_t->i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
msm_actuator_t->i2c_client.cci_client = kzalloc(sizeof(
struct msm_camera_cci_client), GFP_KERNEL);
if (!msm_actuator_t->i2c_client.cci_client) {
kfree(msm_actuator_t->vreg_cfg.cam_vreg);
kfree(msm_actuator_t);
pr_err("failed no memory\n");
return -ENOMEM;
}
cci_client = msm_actuator_t->i2c_client.cci_client;
cci_client->cci_subdev = msm_cci_get_subdev();
cci_client->cci_i2c_master = msm_actuator_t->cci_master;
v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
msm_actuator_t->act_v4l2_subdev_ops);
v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
msm_actuator_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
msm_actuator_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(msm_actuator_t->msm_sd.sd.name,
ARRAY_SIZE(msm_actuator_t->msm_sd.sd.name), "msm_actuator");
media_entity_init(&msm_actuator_t->msm_sd.sd.entity, 0, NULL, 0);
msm_actuator_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
msm_actuator_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
msm_actuator_t->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
msm_sd_register(&msm_actuator_t->msm_sd);
msm_actuator_t->actuator_state = ACT_DISABLE_STATE;
msm_cam_copy_v4l2_subdev_fops(&msm_actuator_v4l2_subdev_fops);
#ifdef CONFIG_COMPAT
msm_actuator_v4l2_subdev_fops.compat_ioctl32 =
msm_actuator_subdev_fops_ioctl;
#endif
msm_actuator_t->msm_sd.sd.devnode->fops =
&msm_actuator_v4l2_subdev_fops;
CDBG("Exit\n");
return rc;
}
static struct msm_actuator msm_vcm_actuator_table = {
.act_type = ACTUATOR_VCM, //类型:音圈马达
.func_tbl = {
.actuator_init_step_table = msm_actuator_init_step_table,
.actuator_move_focus = msm_actuator_move_focus,
.actuator_write_focus = msm_actuator_write_focus,
.actuator_set_default_focus = msm_actuator_set_default_focus,
.actuator_init_focus = msm_actuator_init_focus,
.actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
.actuator_set_position = msm_actuator_set_position,
.actuator_park_lens = msm_actuator_park_lens,
},
};
msm_actuator_init_step_table()函数主要是初始化step_table:
1、先通过ADC多少位确定max_code_size,例如10位的就是1024;
2、a_ctrl->step_position_table = NULL;清空位置表并重新设置;
3、
cur_code = set_info->af_tuning_params.initial_code;设置最初的编码;
4、其他
msm_actuator_move_focus:主要是计算出位置,然后通过i2c发送命令移动焦距:
rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_write_table_w_microdelay(
&a_ctrl->i2c_client, ®_setting);
msm_actuator_write_focus:
Write code based on damping_code_step in a loop
msm_actuator_set_default_focus设置默认的焦距:
rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl, move_params);
|
static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl,
int16_t next_lens_position, uint32_t hw_params, uint16_t delay)
{
struct msm_actuator_reg_params_t *write_arr = a_ctrl->reg_tbl;
uint32_t hw_dword = hw_params;
uint16_t i2c_byte1 = 0, i2c_byte2 = 0;
uint16_t value = 0;
uint32_t size = a_ctrl->reg_tbl_size, i = 0;
struct msm_camera_i2c_reg_array *i2c_tbl = a_ctrl->i2c_reg_tbl;
CDBG("Enter\n");
for (i = 0; i < size; i++) {
/* check that the index into i2c_tbl cannot grow larger that
the allocated size of i2c_tbl */
if ((a_ctrl->total_steps + 1) < (a_ctrl->i2c_tbl_index)) {
break;
}
//先是判断是否属于DAC类型,如果不属于,则有:
i2c_byte1 = write_arr[i].reg_addr;
i2c_byte2 = (hw_dword & write_arr[i].hw_mask) >>write_arr[i].hw_shift;
这个说明不属于DAC所以直接简第一位进行地址,第二位通过上面运算得到数据value作为byte2
如果属于DAC类型,
value = (next_lens_position <<
write_arr[i].data_shift) |
((hw_dword & write_arr[i].hw_mask) >>
write_arr[i].hw_shift);
然后判断是其寄存器地址是否等于0xFFF,如果不等于0xFFFF,则说明不是具体的某个寄存器,则:
i2c_byte1 = write_arr[i].reg_addr; i2c_byte2 = value;
如果DAC的寄存器不止一个的时候,i2c_byte2 = value & 0xFF;先存放到
i2c_tbl中,然后第二个(貌似这里最多都只支持两个集训器)
如果寄存器的地址就是0xFFFF的时候,i2c_byte1 = (value & 0xFF00) >> 8;i2c_byte2 = value & 0xFF;高八位作为地址,第八位作为数据传输
代码实现见如下:
if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
value = (next_lens_position <<
write_arr[i].data_shift) |
((hw_dword & write_arr[i].hw_mask) >>
write_arr[i].hw_shift);
if (write_arr[i].reg_addr != 0xFFFF) {
i2c_byte1 = write_arr[i].reg_addr;
i2c_byte2 = value;
if (size != (i+1)) {
i2c_byte2 = value & 0xFF;
CDBG("byte1:0x%x, byte2:0x%x\n",
i2c_byte1, i2c_byte2);
i2c_tbl[a_ctrl->i2c_tbl_index].
reg_addr = i2c_byte1;
i2c_tbl[a_ctrl->i2c_tbl_index].
reg_data = i2c_byte2;
i2c_tbl[a_ctrl->i2c_tbl_index].
delay = 0;
a_ctrl->i2c_tbl_index++;
i++;
i2c_byte1 = write_arr[i].reg_addr;
i2c_byte2 = (value & 0xFF00) >> 8;
}
} else {
i2c_byte1 = (value & 0xFF00) >> 8;
i2c_byte2 = value & 0xFF;
}
}
else {
i2c_byte1 = write_arr[i].reg_addr;
i2c_byte2 = (hw_dword & write_arr[i].hw_mask) >>
write_arr[i].hw_shift;
}
CDBG("i2c_byte1:0x%x, i2c_byte2:0x%x\n", i2c_byte1, i2c_byte2);
i2c_tbl[a_ctrl->i2c_tbl_index].reg_addr = i2c_byte1;
i2c_tbl[a_ctrl->i2c_tbl_index].reg_data = i2c_byte2;
i2c_tbl[a_ctrl->i2c_tbl_index].delay = delay;
a_ctrl->i2c_tbl_index++;
}
CDBG("Exit\n");
}
|