Loading drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +507 −1 Original line number Diff line number Diff line Loading @@ -34,12 +34,14 @@ static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl); static struct msm_actuator msm_vcm_actuator_table; static struct msm_actuator msm_piezo_actuator_table; static struct msm_actuator msm_hvcm_actuator_table; static struct msm_actuator msm_bivcm_actuator_table; static struct i2c_driver msm_actuator_i2c_driver; static struct msm_actuator *actuators[] = { &msm_vcm_actuator_table, &msm_piezo_actuator_table, &msm_hvcm_actuator_table, &msm_bivcm_actuator_table, }; static int32_t msm_actuator_piezo_set_default_focus( Loading Loading @@ -132,6 +134,213 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, CDBG("Exit\n"); } static int msm_actuator_bivcm_handle_i2c_ops( 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, reg_data = 0; uint32_t size = a_ctrl->reg_tbl_size, i = 0, j = 0; int32_t rc = 0; struct msm_camera_i2c_reg_array i2c_tbl; struct msm_camera_i2c_reg_setting reg_setting; enum msm_camera_i2c_reg_addr_type save_addr_type = a_ctrl->i2c_client.addr_type; for (i = 0; i < size; i++) { reg_setting.size = 1; switch (write_arr[i].reg_write_type) { case 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; } else { i2c_byte1 = (value & 0xFF00) >> 8; i2c_byte2 = value & 0xFF; } i2c_tbl.reg_addr = i2c_byte1; i2c_tbl.reg_data = i2c_byte2; i2c_tbl.delay = delay; a_ctrl->i2c_tbl_index++; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = a_ctrl->i2c_data_type; rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_WRITE: i2c_tbl.reg_data = write_arr[i].reg_data; i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_WRITE_DIR_REG: i2c_tbl.reg_data = hw_dword & 0xFFFF; i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_POLL: switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } for (j = 0; j < ACTUATOR_MAX_POLL_COUNT; j++) { rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll( &a_ctrl->i2c_client, write_arr[i].reg_addr, write_arr[i].reg_data, write_arr[i].data_type); if (rc == 1) continue; if (rc < 0) { pr_err("i2c poll error:%d\n", rc); return rc; } break; } if (j == ACTUATOR_MAX_POLL_COUNT) CDBG("%s:%d Poll register not as expected\n", __func__, __LINE__); break; case MSM_ACTUATOR_READ_WRITE: i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_read( &a_ctrl->i2c_client, write_arr[i].reg_addr, ®_data, write_arr[i].data_type); if (rc < 0) { pr_err("i2c poll error:%d\n", rc); return rc; } i2c_tbl.reg_addr = write_arr[i].reg_data; i2c_tbl.reg_data = reg_data; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_WRITE_HW_DAMP: i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.reg_data = (hw_dword & write_arr[i].hw_mask) >> write_arr[i].hw_shift; i2c_tbl.delay = 0; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = a_ctrl->i2c_data_type; rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; default: pr_err("%s:%d Invalid selection\n", __func__, __LINE__); return -EINVAL; } a_ctrl->i2c_client.addr_type = save_addr_type; } CDBG("Exit\n"); return rc; } static int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl, uint16_t size, struct reg_settings_t *settings) { Loading Loading @@ -229,6 +438,53 @@ static void msm_actuator_write_focus( CDBG("Exit\n"); } static int msm_actuator_bivcm_write_focus( struct msm_actuator_ctrl_t *a_ctrl, uint16_t curr_lens_pos, struct damping_params_t *damping_params, int8_t sign_direction, int16_t code_boundary) { int16_t next_lens_pos = 0; uint16_t damping_code_step = 0; uint16_t wait_time = 0; int32_t rc = 0; CDBG("Enter\n"); damping_code_step = damping_params->damping_step; wait_time = damping_params->damping_delay; /* Write code based on damping_code_step in a loop */ for (next_lens_pos = curr_lens_pos + (sign_direction * damping_code_step); (sign_direction * next_lens_pos) <= (sign_direction * code_boundary); next_lens_pos = (next_lens_pos + (sign_direction * damping_code_step))) { rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, next_lens_pos, damping_params->hw_params, wait_time); if (rc < 0) { pr_err("%s:%d msm_actuator_bivcm_handle_i2c_ops failed\n", __func__, __LINE__); return rc; } curr_lens_pos = next_lens_pos; } if (curr_lens_pos != code_boundary) { rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, code_boundary, damping_params->hw_params, wait_time); if (rc < 0) { pr_err("%s:%d msm_actuator_bivcm_handle_i2c_ops failed\n", __func__, __LINE__); return rc; } } CDBG("Exit\n"); return rc; } static int32_t msm_actuator_piezo_move_focus( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_move_params_t *move_params) Loading Loading @@ -368,6 +624,94 @@ static int32_t msm_actuator_move_focus( return rc; } static int32_t msm_actuator_bivcm_move_focus( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_move_params_t *move_params) { int32_t rc = 0; struct damping_params_t ringing_params_kernel; int8_t sign_dir = move_params->sign_dir; uint16_t step_boundary = 0; uint16_t target_step_pos = 0; uint16_t target_lens_pos = 0; int16_t dest_step_pos = move_params->dest_step_pos; uint16_t curr_lens_pos = 0; int dir = move_params->dir; int32_t num_steps = move_params->num_steps; if (copy_from_user(&ringing_params_kernel, &(move_params->ringing_params[a_ctrl->curr_region_index]), sizeof(struct damping_params_t))) { pr_err("copy_from_user failed\n"); return -EFAULT; } CDBG("called, dir %d, num_steps %d\n", dir, num_steps); if (dest_step_pos == a_ctrl->curr_step_pos) return rc; if ((sign_dir > MSM_ACTUATOR_MOVE_SIGNED_NEAR) || (sign_dir < MSM_ACTUATOR_MOVE_SIGNED_FAR)) { pr_err("Invalid sign_dir = %d\n", sign_dir); return -EFAULT; } if ((dir > MOVE_FAR) || (dir < MOVE_NEAR)) { pr_err("Invalid direction = %d\n", dir); return -EFAULT; } if (dest_step_pos > a_ctrl->total_steps) { pr_err("Step pos greater than total steps = %d\n", dest_step_pos); return -EFAULT; } curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos]; a_ctrl->i2c_tbl_index = 0; CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n", a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos); while (a_ctrl->curr_step_pos != dest_step_pos) { step_boundary = a_ctrl->region_params[a_ctrl->curr_region_index]. step_bound[dir]; if ((dest_step_pos * sign_dir) <= (step_boundary * sign_dir)) { target_step_pos = dest_step_pos; target_lens_pos = a_ctrl->step_position_table[target_step_pos]; rc = msm_actuator_bivcm_write_focus(a_ctrl, curr_lens_pos, &ringing_params_kernel, sign_dir, target_lens_pos); if (rc < 0) return rc; curr_lens_pos = target_lens_pos; } else { target_step_pos = step_boundary; target_lens_pos = a_ctrl->step_position_table[target_step_pos]; rc = msm_actuator_bivcm_write_focus(a_ctrl, curr_lens_pos, &ringing_params_kernel, sign_dir, target_lens_pos); if (rc < 0) return rc; curr_lens_pos = target_lens_pos; a_ctrl->curr_region_index += sign_dir; } a_ctrl->curr_step_pos = target_step_pos; } move_params->curr_lens_pos = curr_lens_pos; a_ctrl->i2c_tbl_index = 0; CDBG("Exit\n"); return rc; } static int32_t msm_actuator_park_lens(struct msm_actuator_ctrl_t *a_ctrl) { Loading Loading @@ -438,6 +782,129 @@ static int32_t msm_actuator_park_lens(struct msm_actuator_ctrl_t *a_ctrl) return 0; } static int32_t msm_actuator_bivcm_park_lens(struct msm_actuator_ctrl_t *a_ctrl) { int32_t rc = 0; uint16_t next_lens_pos = 0; a_ctrl->i2c_tbl_index = 0; if ((a_ctrl->curr_step_pos > a_ctrl->total_steps) || (!a_ctrl->park_lens.max_step) || (!a_ctrl->step_position_table) || (!a_ctrl->i2c_reg_tbl) || (!a_ctrl->func_tbl)) { pr_err("%s:%d Failed to park lens.\n", __func__, __LINE__); return 0; } if (a_ctrl->park_lens.max_step > a_ctrl->max_code_size) a_ctrl->park_lens.max_step = a_ctrl->max_code_size; next_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos]; while (next_lens_pos) { next_lens_pos = (next_lens_pos > a_ctrl->park_lens.max_step) ? (next_lens_pos - a_ctrl->park_lens.max_step) : 0; rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, next_lens_pos, a_ctrl->park_lens.hw_params, a_ctrl->park_lens.damping_delay); if (rc < 0) { pr_err("%s: Failed msm_actuator_bivcm_handle_i2c_ops %d\n", __func__, __LINE__); return rc; } a_ctrl->i2c_tbl_index = 0; /* Use typical damping time delay to avoid tick sound */ usleep_range(10000, 12000); } return 0; } static int32_t msm_actuator_bivcm_init_step_table( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_info_t *set_info) { int16_t code_per_step = 0; int16_t cur_code = 0; int16_t cur_code_se = 0; int16_t step_index = 0, region_index = 0; uint16_t step_boundary = 0; uint32_t max_code_size = 1; uint16_t data_size = set_info->actuator_params.data_size; uint16_t se_shift, mask = 0, i = 0; uint32_t qvalue = 0; CDBG("Enter\n"); for (; data_size > 0; data_size--) { max_code_size *= 2; mask |= (1 << i++); } se_shift = (sizeof(cur_code) * 8) - set_info->actuator_params.data_size; a_ctrl->max_code_size = max_code_size; kfree(a_ctrl->step_position_table); a_ctrl->step_position_table = NULL; if (set_info->af_tuning_params.total_steps > MAX_ACTUATOR_AF_TOTAL_STEPS) { pr_err("Max actuator totalsteps exceeded = %d\n", set_info->af_tuning_params.total_steps); return -EFAULT; } /* Fill step position table */ a_ctrl->step_position_table = kmalloc(sizeof(uint16_t) * (set_info->af_tuning_params.total_steps + 1), GFP_KERNEL); if (a_ctrl->step_position_table == NULL) return -ENOMEM; cur_code = set_info->af_tuning_params.initial_code; a_ctrl->step_position_table[step_index++] = cur_code; for (region_index = 0; region_index < a_ctrl->region_size; region_index++) { code_per_step = a_ctrl->region_params[region_index].code_per_step; step_boundary = a_ctrl->region_params[region_index]. step_bound[MOVE_NEAR]; qvalue = a_ctrl->region_params[region_index].qvalue; for (; step_index <= step_boundary; step_index++) { cur_code_se = cur_code << se_shift; cur_code_se >>= se_shift; if (qvalue > 1 && qvalue <= MAX_QVALUE) cur_code = step_index * code_per_step / qvalue; else cur_code = step_index * code_per_step; cur_code = (set_info->af_tuning_params.initial_code + cur_code) & mask; if (cur_code < max_code_size) a_ctrl->step_position_table[step_index] = cur_code; else { for (; step_index < set_info->af_tuning_params.total_steps; step_index++) a_ctrl-> step_position_table[ step_index] = max_code_size; } CDBG("step_position_table[%d] = %d\n", step_index, a_ctrl->step_position_table[step_index]); } } CDBG("Exit\n"); return 0; } static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_info_t *set_info) { Loading Loading @@ -502,7 +969,7 @@ static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl, step_index] = max_code_size; } CDBG("step_position_table[%d] = %d", step_index, CDBG("step_position_table[%d] = %d\n", step_index, a_ctrl->step_position_table[step_index]); } } Loading Loading @@ -626,6 +1093,31 @@ static int32_t msm_actuator_set_position( return rc; } static int32_t msm_actuator_bivcm_set_position( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_position_t *set_pos) { int32_t rc = 0; int32_t index; uint16_t next_lens_position; uint16_t delay; uint32_t hw_params = 0; CDBG("%s Enter %d\n", __func__, __LINE__); if (set_pos->number_of_steps == 0) return rc; a_ctrl->i2c_tbl_index = 0; for (index = 0; index < set_pos->number_of_steps; index++) { next_lens_position = set_pos->pos[index]; delay = set_pos->delay[index]; rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, next_lens_position, hw_params, delay); a_ctrl->i2c_tbl_index = 0; } CDBG("%s exit %d\n", __func__, __LINE__); return rc; } static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_info_t *set_info) { struct reg_settings_t *init_settings = NULL; Loading Loading @@ -1397,6 +1889,20 @@ static struct msm_actuator msm_hvcm_actuator_table = { }, }; static struct msm_actuator msm_bivcm_actuator_table = { .act_type = ACTUATOR_BIVCM, .func_tbl = { .actuator_init_step_table = msm_actuator_bivcm_init_step_table, .actuator_move_focus = msm_actuator_bivcm_move_focus, .actuator_write_focus = NULL, .actuator_set_default_focus = msm_actuator_set_default_focus, .actuator_init_focus = msm_actuator_init_focus, .actuator_parse_i2c_params = NULL, .actuator_set_position = msm_actuator_bivcm_set_position, .actuator_park_lens = msm_actuator_bivcm_park_lens, }, }; module_init(msm_actuator_init_module); MODULE_DESCRIPTION("MSM ACTUATOR"); MODULE_LICENSE("GPL v2"); drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h +1 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) #define MSM_ACTUATOT_MAX_VREGS (10) #define ACTUATOR_MAX_POLL_COUNT 10 struct msm_actuator_ctrl_t; Loading include/media/msm_camsensor_sdk.h +11 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ #define MAX_ACTUATOR_SCENARIO 8 #define MAX_ACT_MOD_NAME_SIZE 32 #define MAX_ACT_NAME_SIZE 32 #define MAX_ACTUATOR_INIT_SET 12 #define MAX_ACTUATOR_INIT_SET 120 #define MAX_I2C_REG_SET 12 #define MAX_NAME_SIZE 32 Loading Loading @@ -139,6 +139,10 @@ enum msm_actuator_addr_type { enum msm_actuator_write_type { MSM_ACTUATOR_WRITE_HW_DAMP, MSM_ACTUATOR_WRITE_DAC, MSM_ACTUATOR_WRITE, MSM_ACTUATOR_WRITE_DIR_REG, MSM_ACTUATOR_POLL, MSM_ACTUATOR_READ_WRITE, }; enum msm_actuator_i2c_operation { Loading @@ -150,6 +154,7 @@ enum actuator_type { ACTUATOR_VCM, ACTUATOR_PIEZO, ACTUATOR_HVCM, ACTUATOR_BIVCM, }; enum msm_flash_driver_type { Loading Loading @@ -278,8 +283,13 @@ struct msm_actuator_reg_params_t { uint16_t reg_addr; uint16_t hw_shift; uint16_t data_shift; uint16_t data_type; uint16_t addr_type; uint16_t reg_data; uint16_t delay; }; struct damping_params_t { uint32_t damping_step; uint32_t damping_delay; Loading include/uapi/media/msm_camera.h +10 −1 Original line number Diff line number Diff line Loading @@ -1702,6 +1702,8 @@ struct damping_params_t { enum actuator_type { ACTUATOR_VCM, ACTUATOR_PIEZO, ACTUATOR_HVCM, ACTUATOR_BIVCM, }; enum msm_actuator_data_type { Loading @@ -1717,6 +1719,10 @@ enum msm_actuator_addr_type { enum msm_actuator_write_type { MSM_ACTUATOR_WRITE_HW_DAMP, MSM_ACTUATOR_WRITE_DAC, MSM_ACTUATOR_WRITE, MSM_ACTUATOR_WRITE_DIR_REG, MSM_ACTUATOR_POLL, MSM_ACTUATOR_READ_WRITE, }; struct msm_actuator_reg_params_t { Loading @@ -1724,7 +1730,10 @@ struct msm_actuator_reg_params_t { uint32_t hw_mask; uint16_t reg_addr; uint16_t hw_shift; uint16_t data_shift; uint16_t data_type; uint16_t addr_type; uint16_t reg_data; uint16_t delay; }; struct reg_settings_t { Loading Loading
drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +507 −1 Original line number Diff line number Diff line Loading @@ -34,12 +34,14 @@ static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl); static struct msm_actuator msm_vcm_actuator_table; static struct msm_actuator msm_piezo_actuator_table; static struct msm_actuator msm_hvcm_actuator_table; static struct msm_actuator msm_bivcm_actuator_table; static struct i2c_driver msm_actuator_i2c_driver; static struct msm_actuator *actuators[] = { &msm_vcm_actuator_table, &msm_piezo_actuator_table, &msm_hvcm_actuator_table, &msm_bivcm_actuator_table, }; static int32_t msm_actuator_piezo_set_default_focus( Loading Loading @@ -132,6 +134,213 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, CDBG("Exit\n"); } static int msm_actuator_bivcm_handle_i2c_ops( 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, reg_data = 0; uint32_t size = a_ctrl->reg_tbl_size, i = 0, j = 0; int32_t rc = 0; struct msm_camera_i2c_reg_array i2c_tbl; struct msm_camera_i2c_reg_setting reg_setting; enum msm_camera_i2c_reg_addr_type save_addr_type = a_ctrl->i2c_client.addr_type; for (i = 0; i < size; i++) { reg_setting.size = 1; switch (write_arr[i].reg_write_type) { case 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; } else { i2c_byte1 = (value & 0xFF00) >> 8; i2c_byte2 = value & 0xFF; } i2c_tbl.reg_addr = i2c_byte1; i2c_tbl.reg_data = i2c_byte2; i2c_tbl.delay = delay; a_ctrl->i2c_tbl_index++; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = a_ctrl->i2c_data_type; rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_WRITE: i2c_tbl.reg_data = write_arr[i].reg_data; i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_WRITE_DIR_REG: i2c_tbl.reg_data = hw_dword & 0xFFFF; i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_POLL: switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } for (j = 0; j < ACTUATOR_MAX_POLL_COUNT; j++) { rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll( &a_ctrl->i2c_client, write_arr[i].reg_addr, write_arr[i].reg_data, write_arr[i].data_type); if (rc == 1) continue; if (rc < 0) { pr_err("i2c poll error:%d\n", rc); return rc; } break; } if (j == ACTUATOR_MAX_POLL_COUNT) CDBG("%s:%d Poll register not as expected\n", __func__, __LINE__); break; case MSM_ACTUATOR_READ_WRITE: i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; switch (write_arr[i].addr_type) { case MSM_ACTUATOR_BYTE_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR; break; case MSM_ACTUATOR_WORD_ADDR: a_ctrl->i2c_client.addr_type = MSM_CAMERA_I2C_WORD_ADDR; break; default: pr_err("Unsupport addr type: %d\n", write_arr[i].addr_type); break; } rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_read( &a_ctrl->i2c_client, write_arr[i].reg_addr, ®_data, write_arr[i].data_type); if (rc < 0) { pr_err("i2c poll error:%d\n", rc); return rc; } i2c_tbl.reg_addr = write_arr[i].reg_data; i2c_tbl.reg_data = reg_data; i2c_tbl.delay = write_arr[i].delay; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = write_arr[i].data_type; rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; case MSM_ACTUATOR_WRITE_HW_DAMP: i2c_tbl.reg_addr = write_arr[i].reg_addr; i2c_tbl.reg_data = (hw_dword & write_arr[i].hw_mask) >> write_arr[i].hw_shift; i2c_tbl.delay = 0; reg_setting.reg_setting = &i2c_tbl; reg_setting.data_type = a_ctrl->i2c_data_type; rc = a_ctrl->i2c_client. i2c_func_tbl->i2c_write_table_w_microdelay( &a_ctrl->i2c_client, ®_setting); if (rc < 0) { pr_err("i2c write error:%d\n", rc); return rc; } break; default: pr_err("%s:%d Invalid selection\n", __func__, __LINE__); return -EINVAL; } a_ctrl->i2c_client.addr_type = save_addr_type; } CDBG("Exit\n"); return rc; } static int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl, uint16_t size, struct reg_settings_t *settings) { Loading Loading @@ -229,6 +438,53 @@ static void msm_actuator_write_focus( CDBG("Exit\n"); } static int msm_actuator_bivcm_write_focus( struct msm_actuator_ctrl_t *a_ctrl, uint16_t curr_lens_pos, struct damping_params_t *damping_params, int8_t sign_direction, int16_t code_boundary) { int16_t next_lens_pos = 0; uint16_t damping_code_step = 0; uint16_t wait_time = 0; int32_t rc = 0; CDBG("Enter\n"); damping_code_step = damping_params->damping_step; wait_time = damping_params->damping_delay; /* Write code based on damping_code_step in a loop */ for (next_lens_pos = curr_lens_pos + (sign_direction * damping_code_step); (sign_direction * next_lens_pos) <= (sign_direction * code_boundary); next_lens_pos = (next_lens_pos + (sign_direction * damping_code_step))) { rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, next_lens_pos, damping_params->hw_params, wait_time); if (rc < 0) { pr_err("%s:%d msm_actuator_bivcm_handle_i2c_ops failed\n", __func__, __LINE__); return rc; } curr_lens_pos = next_lens_pos; } if (curr_lens_pos != code_boundary) { rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, code_boundary, damping_params->hw_params, wait_time); if (rc < 0) { pr_err("%s:%d msm_actuator_bivcm_handle_i2c_ops failed\n", __func__, __LINE__); return rc; } } CDBG("Exit\n"); return rc; } static int32_t msm_actuator_piezo_move_focus( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_move_params_t *move_params) Loading Loading @@ -368,6 +624,94 @@ static int32_t msm_actuator_move_focus( return rc; } static int32_t msm_actuator_bivcm_move_focus( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_move_params_t *move_params) { int32_t rc = 0; struct damping_params_t ringing_params_kernel; int8_t sign_dir = move_params->sign_dir; uint16_t step_boundary = 0; uint16_t target_step_pos = 0; uint16_t target_lens_pos = 0; int16_t dest_step_pos = move_params->dest_step_pos; uint16_t curr_lens_pos = 0; int dir = move_params->dir; int32_t num_steps = move_params->num_steps; if (copy_from_user(&ringing_params_kernel, &(move_params->ringing_params[a_ctrl->curr_region_index]), sizeof(struct damping_params_t))) { pr_err("copy_from_user failed\n"); return -EFAULT; } CDBG("called, dir %d, num_steps %d\n", dir, num_steps); if (dest_step_pos == a_ctrl->curr_step_pos) return rc; if ((sign_dir > MSM_ACTUATOR_MOVE_SIGNED_NEAR) || (sign_dir < MSM_ACTUATOR_MOVE_SIGNED_FAR)) { pr_err("Invalid sign_dir = %d\n", sign_dir); return -EFAULT; } if ((dir > MOVE_FAR) || (dir < MOVE_NEAR)) { pr_err("Invalid direction = %d\n", dir); return -EFAULT; } if (dest_step_pos > a_ctrl->total_steps) { pr_err("Step pos greater than total steps = %d\n", dest_step_pos); return -EFAULT; } curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos]; a_ctrl->i2c_tbl_index = 0; CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n", a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos); while (a_ctrl->curr_step_pos != dest_step_pos) { step_boundary = a_ctrl->region_params[a_ctrl->curr_region_index]. step_bound[dir]; if ((dest_step_pos * sign_dir) <= (step_boundary * sign_dir)) { target_step_pos = dest_step_pos; target_lens_pos = a_ctrl->step_position_table[target_step_pos]; rc = msm_actuator_bivcm_write_focus(a_ctrl, curr_lens_pos, &ringing_params_kernel, sign_dir, target_lens_pos); if (rc < 0) return rc; curr_lens_pos = target_lens_pos; } else { target_step_pos = step_boundary; target_lens_pos = a_ctrl->step_position_table[target_step_pos]; rc = msm_actuator_bivcm_write_focus(a_ctrl, curr_lens_pos, &ringing_params_kernel, sign_dir, target_lens_pos); if (rc < 0) return rc; curr_lens_pos = target_lens_pos; a_ctrl->curr_region_index += sign_dir; } a_ctrl->curr_step_pos = target_step_pos; } move_params->curr_lens_pos = curr_lens_pos; a_ctrl->i2c_tbl_index = 0; CDBG("Exit\n"); return rc; } static int32_t msm_actuator_park_lens(struct msm_actuator_ctrl_t *a_ctrl) { Loading Loading @@ -438,6 +782,129 @@ static int32_t msm_actuator_park_lens(struct msm_actuator_ctrl_t *a_ctrl) return 0; } static int32_t msm_actuator_bivcm_park_lens(struct msm_actuator_ctrl_t *a_ctrl) { int32_t rc = 0; uint16_t next_lens_pos = 0; a_ctrl->i2c_tbl_index = 0; if ((a_ctrl->curr_step_pos > a_ctrl->total_steps) || (!a_ctrl->park_lens.max_step) || (!a_ctrl->step_position_table) || (!a_ctrl->i2c_reg_tbl) || (!a_ctrl->func_tbl)) { pr_err("%s:%d Failed to park lens.\n", __func__, __LINE__); return 0; } if (a_ctrl->park_lens.max_step > a_ctrl->max_code_size) a_ctrl->park_lens.max_step = a_ctrl->max_code_size; next_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos]; while (next_lens_pos) { next_lens_pos = (next_lens_pos > a_ctrl->park_lens.max_step) ? (next_lens_pos - a_ctrl->park_lens.max_step) : 0; rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, next_lens_pos, a_ctrl->park_lens.hw_params, a_ctrl->park_lens.damping_delay); if (rc < 0) { pr_err("%s: Failed msm_actuator_bivcm_handle_i2c_ops %d\n", __func__, __LINE__); return rc; } a_ctrl->i2c_tbl_index = 0; /* Use typical damping time delay to avoid tick sound */ usleep_range(10000, 12000); } return 0; } static int32_t msm_actuator_bivcm_init_step_table( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_info_t *set_info) { int16_t code_per_step = 0; int16_t cur_code = 0; int16_t cur_code_se = 0; int16_t step_index = 0, region_index = 0; uint16_t step_boundary = 0; uint32_t max_code_size = 1; uint16_t data_size = set_info->actuator_params.data_size; uint16_t se_shift, mask = 0, i = 0; uint32_t qvalue = 0; CDBG("Enter\n"); for (; data_size > 0; data_size--) { max_code_size *= 2; mask |= (1 << i++); } se_shift = (sizeof(cur_code) * 8) - set_info->actuator_params.data_size; a_ctrl->max_code_size = max_code_size; kfree(a_ctrl->step_position_table); a_ctrl->step_position_table = NULL; if (set_info->af_tuning_params.total_steps > MAX_ACTUATOR_AF_TOTAL_STEPS) { pr_err("Max actuator totalsteps exceeded = %d\n", set_info->af_tuning_params.total_steps); return -EFAULT; } /* Fill step position table */ a_ctrl->step_position_table = kmalloc(sizeof(uint16_t) * (set_info->af_tuning_params.total_steps + 1), GFP_KERNEL); if (a_ctrl->step_position_table == NULL) return -ENOMEM; cur_code = set_info->af_tuning_params.initial_code; a_ctrl->step_position_table[step_index++] = cur_code; for (region_index = 0; region_index < a_ctrl->region_size; region_index++) { code_per_step = a_ctrl->region_params[region_index].code_per_step; step_boundary = a_ctrl->region_params[region_index]. step_bound[MOVE_NEAR]; qvalue = a_ctrl->region_params[region_index].qvalue; for (; step_index <= step_boundary; step_index++) { cur_code_se = cur_code << se_shift; cur_code_se >>= se_shift; if (qvalue > 1 && qvalue <= MAX_QVALUE) cur_code = step_index * code_per_step / qvalue; else cur_code = step_index * code_per_step; cur_code = (set_info->af_tuning_params.initial_code + cur_code) & mask; if (cur_code < max_code_size) a_ctrl->step_position_table[step_index] = cur_code; else { for (; step_index < set_info->af_tuning_params.total_steps; step_index++) a_ctrl-> step_position_table[ step_index] = max_code_size; } CDBG("step_position_table[%d] = %d\n", step_index, a_ctrl->step_position_table[step_index]); } } CDBG("Exit\n"); return 0; } static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_info_t *set_info) { Loading Loading @@ -502,7 +969,7 @@ static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl, step_index] = max_code_size; } CDBG("step_position_table[%d] = %d", step_index, CDBG("step_position_table[%d] = %d\n", step_index, a_ctrl->step_position_table[step_index]); } } Loading Loading @@ -626,6 +1093,31 @@ static int32_t msm_actuator_set_position( return rc; } static int32_t msm_actuator_bivcm_set_position( struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_position_t *set_pos) { int32_t rc = 0; int32_t index; uint16_t next_lens_position; uint16_t delay; uint32_t hw_params = 0; CDBG("%s Enter %d\n", __func__, __LINE__); if (set_pos->number_of_steps == 0) return rc; a_ctrl->i2c_tbl_index = 0; for (index = 0; index < set_pos->number_of_steps; index++) { next_lens_position = set_pos->pos[index]; delay = set_pos->delay[index]; rc = msm_actuator_bivcm_handle_i2c_ops(a_ctrl, next_lens_position, hw_params, delay); a_ctrl->i2c_tbl_index = 0; } CDBG("%s exit %d\n", __func__, __LINE__); return rc; } static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, struct msm_actuator_set_info_t *set_info) { struct reg_settings_t *init_settings = NULL; Loading Loading @@ -1397,6 +1889,20 @@ static struct msm_actuator msm_hvcm_actuator_table = { }, }; static struct msm_actuator msm_bivcm_actuator_table = { .act_type = ACTUATOR_BIVCM, .func_tbl = { .actuator_init_step_table = msm_actuator_bivcm_init_step_table, .actuator_move_focus = msm_actuator_bivcm_move_focus, .actuator_write_focus = NULL, .actuator_set_default_focus = msm_actuator_set_default_focus, .actuator_init_focus = msm_actuator_init_focus, .actuator_parse_i2c_params = NULL, .actuator_set_position = msm_actuator_bivcm_set_position, .actuator_park_lens = msm_actuator_bivcm_park_lens, }, }; module_init(msm_actuator_init_module); MODULE_DESCRIPTION("MSM ACTUATOR"); MODULE_LICENSE("GPL v2");
drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h +1 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) #define MSM_ACTUATOT_MAX_VREGS (10) #define ACTUATOR_MAX_POLL_COUNT 10 struct msm_actuator_ctrl_t; Loading
include/media/msm_camsensor_sdk.h +11 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ #define MAX_ACTUATOR_SCENARIO 8 #define MAX_ACT_MOD_NAME_SIZE 32 #define MAX_ACT_NAME_SIZE 32 #define MAX_ACTUATOR_INIT_SET 12 #define MAX_ACTUATOR_INIT_SET 120 #define MAX_I2C_REG_SET 12 #define MAX_NAME_SIZE 32 Loading Loading @@ -139,6 +139,10 @@ enum msm_actuator_addr_type { enum msm_actuator_write_type { MSM_ACTUATOR_WRITE_HW_DAMP, MSM_ACTUATOR_WRITE_DAC, MSM_ACTUATOR_WRITE, MSM_ACTUATOR_WRITE_DIR_REG, MSM_ACTUATOR_POLL, MSM_ACTUATOR_READ_WRITE, }; enum msm_actuator_i2c_operation { Loading @@ -150,6 +154,7 @@ enum actuator_type { ACTUATOR_VCM, ACTUATOR_PIEZO, ACTUATOR_HVCM, ACTUATOR_BIVCM, }; enum msm_flash_driver_type { Loading Loading @@ -278,8 +283,13 @@ struct msm_actuator_reg_params_t { uint16_t reg_addr; uint16_t hw_shift; uint16_t data_shift; uint16_t data_type; uint16_t addr_type; uint16_t reg_data; uint16_t delay; }; struct damping_params_t { uint32_t damping_step; uint32_t damping_delay; Loading
include/uapi/media/msm_camera.h +10 −1 Original line number Diff line number Diff line Loading @@ -1702,6 +1702,8 @@ struct damping_params_t { enum actuator_type { ACTUATOR_VCM, ACTUATOR_PIEZO, ACTUATOR_HVCM, ACTUATOR_BIVCM, }; enum msm_actuator_data_type { Loading @@ -1717,6 +1719,10 @@ enum msm_actuator_addr_type { enum msm_actuator_write_type { MSM_ACTUATOR_WRITE_HW_DAMP, MSM_ACTUATOR_WRITE_DAC, MSM_ACTUATOR_WRITE, MSM_ACTUATOR_WRITE_DIR_REG, MSM_ACTUATOR_POLL, MSM_ACTUATOR_READ_WRITE, }; struct msm_actuator_reg_params_t { Loading @@ -1724,7 +1730,10 @@ struct msm_actuator_reg_params_t { uint32_t hw_mask; uint16_t reg_addr; uint16_t hw_shift; uint16_t data_shift; uint16_t data_type; uint16_t addr_type; uint16_t reg_data; uint16_t delay; }; struct reg_settings_t { Loading