diff --git a/drivers/Makefile b/drivers/Makefile index 7a7b0250f03f..c2349c1f090e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -172,6 +172,12 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \ cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \ cam_sensor_module/cam_res_mgr/cam_res_mgr.o +ifneq (,$(filter $(CONFIG_AF_NOISE_ELIMINATION), y m)) +camera-$(CONFIG_SPECTRA_SENSOR) += \ + cam_sensor_module/cam_actuator/mot_actuator.o \ + cam_sensor_module/cam_actuator/mot_actuator_policy.o +endif + camera-$(CONFIG_LEDS_QPNP_FLASH_V2) += \ cam_sensor_module/cam_flash/cam_flash_dev.o \ cam_sensor_module/cam_flash/cam_flash_core.o \ diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 722f91e334b3..cfa2f8e0d6a7 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -10,6 +10,9 @@ #include "cam_trace.h" #include "cam_common_util.h" #include "cam_packet_util.h" +#ifdef CONFIG_AF_NOISE_ELIMINATION +#include "mot_actuator_policy.h" +#endif int32_t cam_actuator_construct_default_power_setting( struct cam_sensor_power_ctrl_t *power_info) @@ -259,7 +262,13 @@ int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl, CAM_ERR(CAM_ACTUATOR, " Invalid settings"); return -EINVAL; } - +#ifdef CONFIG_AF_NOISE_ELIMINATION + /*Usually actuator initial setting will execute power down reset(PD), actuator can't respond + CCI access for a while after PD. Add lock to avoid access actuator while PD operation.*/ + if (a_ctrl->is_multi_user_supported) { + mot_actuator_lock(); + } +#endif list_for_each_entry(i2c_list, &(i2c_set->list_head), list) { rc = cam_actuator_i2c_modes_util( @@ -276,6 +285,14 @@ int32_t cam_actuator_apply_settings(struct cam_actuator_ctrl_t *a_ctrl, } } +#ifdef CONFIG_AF_NOISE_ELIMINATION + /*Usually actuator initial setting will execute power down reset(PD), actuator can't respond + CCI access for a while after PD. Add lock to avoid access actuator while PD operation.*/ + if (a_ctrl->is_multi_user_supported) { + mot_actuator_unlock(); + } +#endif + return rc; } @@ -582,6 +599,13 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, } } +#ifdef CONFIG_AF_NOISE_ELIMINATION + if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE && + a_ctrl->is_multi_user_supported == true) { + mot_actuator_get(ACTUATOR_CLIENT_CAMERA); + } +#endif + if (a_ctrl->cam_act_state == CAM_ACTUATOR_ACQUIRE) { rc = cam_actuator_power_up(a_ctrl); if (rc < 0) { @@ -595,6 +619,7 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, rc = cam_actuator_apply_settings(a_ctrl, &a_ctrl->i2c_data.init_settings); if (rc < 0) { + delete_request(&a_ctrl->i2c_data.init_settings); CAM_ERR(CAM_ACTUATOR, "Cannot apply Init settings"); goto end; } @@ -890,6 +915,11 @@ int32_t cam_actuator_driver_cmd(struct cam_actuator_ctrl_t *a_ctrl, } if (a_ctrl->cam_act_state == CAM_ACTUATOR_CONFIG) { +#ifdef CONFIG_AF_NOISE_ELIMINATION + if (a_ctrl->is_multi_user_supported == true) { + mot_actuator_put(ACTUATOR_CLIENT_CAMERA); + } +#endif rc = cam_actuator_power_down(a_ctrl); if (rc < 0) { CAM_ERR(CAM_ACTUATOR, diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h index 1ec575301cfc..5406e2c96e55 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h @@ -115,6 +115,9 @@ struct cam_actuator_ctrl_t { struct cam_actuator_query_cap act_info; struct actuator_intf_params bridge_intf; uint32_t last_flush_req; +#ifdef CONFIG_AF_NOISE_ELIMINATION + bool is_multi_user_supported; +#endif }; /** diff --git a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c index cb852423a228..7ef6b95595d2 100644 --- a/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c +++ b/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c @@ -34,6 +34,15 @@ int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl, of_node = soc_info->dev->of_node; +#ifdef CONFIG_AF_NOISE_ELIMINATION + if (!of_property_read_bool(of_node, "multi-user-support")) { + a_ctrl->is_multi_user_supported = false; + } else { + a_ctrl->is_multi_user_supported = true; + } + CAM_DBG(CAM_ACTUATOR, "multi-user-support %d", a_ctrl->is_multi_user_supported); +#endif + if (a_ctrl->io_master_info.master_type == CCI_MASTER) { rc = of_property_read_u32(of_node, "cci-master", &(a_ctrl->cci_i2c_master)); diff --git a/drivers/cam_sensor_module/cam_actuator/mot_actuator.c b/drivers/cam_sensor_module/cam_actuator/mot_actuator.c new file mode 100644 index 000000000000..e8fe296ca82d --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/mot_actuator.c @@ -0,0 +1,1032 @@ +/* + * Copyright (C) 2020 Motorola Mobility LLC. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cam_debug_util.h" +#include "cam_cci_dev.h" +#include "mot_actuator.h" +#include "mot_actuator_policy.h" +#include "cam_sensor_io.h" +#include "cam_req_mgr_dev.h" +/*=================ACTUATOR HW INFO====================*/ +#define DEVICE_NAME_LEN 32 +#define MAX_ACTUATOR_NUM 3 +#define REGULATOR_NAME_MAX_LEN 32 +#define ANDROIDBOOT_DEVICE_MAX_LEN 32 + +typedef enum { + MOT_ACTUATOR_INVALID, + MOT_ACTUATOR_FIRST, + MOT_ACTUATOR_GT9767 = MOT_ACTUATOR_FIRST, + MOT_ACTUATOR_GT9772, + MOT_ACTUATOR_DW9714, + MOT_ACTUATOR_NUM, +} mot_actuator_type; + +typedef enum { + REGULATOR_IOVDD, + REGULATOR_AFVDD, + REGULATOR_NUM, +} mot_regulator_type; + +typedef enum { + MOT_DEVICE_NIO, + MOT_DEVICE_BERLNA, + MOT_DEVICE_NUM, +} mot_dev_type; + +typedef struct { + uint16_t kneePoint; + uint16_t step; +} mot_park_lens_step; + +typedef struct { + struct cam_sensor_i2c_reg_setting *init_setting; + struct cam_sensor_i2c_reg_setting *dac_setting; +} mot_actuator_settings; + +typedef struct { + mot_actuator_type actuator_type; + uint16_t dac_pos; + uint16_t cci_addr; + uint16_t cci_dev; + uint16_t cci_master; + char *regulator_list[REGULATOR_NUM]; + uint32_t regulator_volt_uv[REGULATOR_NUM]; + bool park_lens_needed; +} mot_actuator_hw_info; + +typedef struct { + mot_dev_type dev_type; + uint16_t actuator_num; + char dev_name[DEVICE_NAME_LEN]; + mot_actuator_hw_info actuator_info[MAX_ACTUATOR_NUM]; +} mot_dev_info; + +/*Register settings of GT9767*/ //todo +static struct cam_sensor_i2c_reg_array mot_gt9767_init_setting[] ={ + {0x02, 0x00, 300}, + {0x06, 0x0A, 0}, + {0x07, 0x01, 0}, + {0x08, 0x43, 0}, +}; + +static struct cam_sensor_i2c_reg_array mot_gt9767_dac_setting[] ={ + {0x03, 0x3ff, 0} +}; + +static struct cam_sensor_i2c_reg_setting mot_gt9767_init_settings = { + .reg_setting = mot_gt9767_init_setting, + .size = ARRAY_SIZE(mot_gt9767_init_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_BYTE, +}; + +static struct cam_sensor_i2c_reg_setting mot_gt9767_dac_settings = { + .reg_setting = mot_gt9767_dac_setting, + .size = ARRAY_SIZE(mot_gt9767_dac_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_WORD, +}; + +/*Register settings of GT9772*/ +static struct cam_sensor_i2c_reg_array mot_gt9772_init_setting[] ={ + {0xED, 0xAB, 0}, + {0x02, 0x01, 0}, + {0x02, 0x00, 300}, + {0x06, 0x84, 0}, + {0x07, 0x01, 0}, + {0x08, 0x62, 0}, +}; + +static struct cam_sensor_i2c_reg_array mot_gt9772_dac_setting[] ={ + {0x03, 0x3ff, 0} +}; + +static struct cam_sensor_i2c_reg_setting mot_gt9772_init_settings = { + .reg_setting = mot_gt9772_init_setting, + .size = ARRAY_SIZE(mot_gt9772_init_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_BYTE, +}; + +static struct cam_sensor_i2c_reg_setting mot_gt9772_dac_settings = { + .reg_setting = mot_gt9772_dac_setting, + .size = ARRAY_SIZE(mot_gt9772_dac_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_WORD, +}; + +/*Register settings of DW9714*/ //todo +static struct cam_sensor_i2c_reg_array mot_dw9714_init_setting[] ={ + {0xED, 0xAB, 0}, + {0x02, 0x01, 0}, + {0x02, 0x00, 1000}, + {0x06, 0x84, 0}, + {0x07, 0x01, 0}, + {0x08, 0x78, 0}, +}; + +static struct cam_sensor_i2c_reg_array mot_dw9714_dac_setting[] ={ //todo + {0x03, 0x3ff, 0} +}; + +static struct cam_sensor_i2c_reg_setting mot_dw9714_init_settings = { + .reg_setting = mot_dw9714_init_setting, + .size = ARRAY_SIZE(mot_dw9714_init_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_BYTE, +}; + +static struct cam_sensor_i2c_reg_setting mot_dw9714_dac_settings = { + .reg_setting = mot_dw9714_dac_setting, + .size = ARRAY_SIZE(mot_dw9714_dac_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_WORD, +}; + +/*Register settings of all supported actuator types*/ +static mot_actuator_settings mot_actuator_list[MOT_ACTUATOR_NUM-1] = { + //MUST be sorted as definition order in above structure: mot_actuator_type + {&mot_gt9767_init_settings, &mot_gt9767_dac_settings}, + {&mot_gt9772_init_settings, &mot_gt9772_dac_settings}, + {&mot_dw9714_init_settings, &mot_dw9714_dac_settings}, +}; + +static const mot_dev_info mot_dev_list[MOT_DEVICE_NUM] = { + { + .dev_type = MOT_DEVICE_NIO, + .actuator_num = 1, + .dev_name = "nio", + .actuator_info = { + [0] = { + .actuator_type = MOT_ACTUATOR_GT9772, + .dac_pos = 400, + .cci_addr = 0x0c, + .cci_dev = 0x01, + .cci_master = 0x0, + .regulator_list = {"ldo7", "ldo5"}, + .regulator_volt_uv = {1800000, 2800000}, + .park_lens_needed = true, + }, + }, + }, + { + .dev_type = MOT_DEVICE_BERLNA, + .actuator_num = 1, + .dev_name = "berlna", + .actuator_info = { + [0] = { + .actuator_type = MOT_ACTUATOR_DW9714, + .dac_pos = 400, + .cci_addr = 0x0c, + .cci_dev = 0x01, + .cci_master = 0x01, + .regulator_list = {"ldo7", "ldo5"}, + .regulator_volt_uv = {1800000, 2800000}, + .park_lens_needed = true, + }, + }, + }, +}; + +static uint32_t mot_device_index = MOT_DEVICE_NUM; + +static char *bootargs_str; +static char androidboot_device[ANDROIDBOOT_DEVICE_MAX_LEN]; +int mot_actuator_get_bootarg(char *key, char **value) +{ + const char *bootargs_tmp = NULL; + char *idx = NULL; + char *kvpair = NULL; + int err = 1; + struct device_node *n = of_find_node_by_path("/chosen"); + size_t bootargs_tmp_len = 0; + + if (n == NULL) + goto err; + + if (of_property_read_string(n, "bootargs", &bootargs_tmp) != 0) + goto putnode; + + bootargs_tmp_len = strlen(bootargs_tmp); + if (!bootargs_str) { + /* The following operations need a non-const + * version of bootargs + */ + bootargs_str = kzalloc(bootargs_tmp_len + 1, GFP_KERNEL); + if (!bootargs_str) + goto putnode; + } + strlcpy(bootargs_str, bootargs_tmp, bootargs_tmp_len + 1); + + idx = strnstr(bootargs_str, key, strlen(bootargs_str)); + if (idx) { + kvpair = strsep(&idx, " "); + if (kvpair) + if (strsep(&kvpair, "=")) { + *value = strsep(&kvpair, " "); + if (*value) + err = 0; + } + } + +putnode: + of_node_put(n); +err: + return err; +} + +static int cam_select_actuator_by_device_name(void) +{ + char *str; + uint32_t i; + if (mot_actuator_get_bootarg("androidboot.device=", &str) == 0) + strlcpy(androidboot_device, str, ANDROIDBOOT_DEVICE_MAX_LEN); + + for (i=0; i= MOT_DEVICE_NUM) { + CAM_ERR(CAM_ACTUATOR, "UNKNOWN DEVICE:%s", str); + } + return 1; +} + +/*=================ACTUATOR RUNTIME====================*/ +#define VIBRATING_MAX_INTERVAL 2000//ms +#define PARK_LENS_MAX_STAGES 10 + +struct mot_actuator_ctrl_t { + struct cam_subdev v4l2_dev_str; + struct platform_device *pdev; + char device_name[20]; + struct workqueue_struct *mot_actuator_wq; + struct delayed_work delay_work; + struct mutex actuator_lock; +}; + +enum mot_actuator_state_e { + MOT_ACTUATOR_IDLE, + MOT_ACTUATOR_INITED, + MOT_ACTUATOR_STARTED, + MOT_ACTUATOR_RELEASED +}; + +typedef struct { + struct cam_sensor_cci_client client; + struct camera_io_master io_master; + struct regulator * regulators[REGULATOR_NUM]; + uint32_t safe_dac_pos; +} mot_actuator_runtime_type; + +static struct mot_actuator_ctrl_t mot_actuator_fctrl; +static enum mot_actuator_state_e mot_actuator_state = MOT_ACTUATOR_IDLE; +static mot_actuator_runtime_type mot_actuator_runtime[MAX_ACTUATOR_NUM]; +static uint32_t lens_safe_pos_dac = 0; +static uint32_t lens_park_pos = 100; +static mot_park_lens_step lens_park_table[PARK_LENS_MAX_STAGES] = { + {300, 60}, + {200, 40}, +}; +static bool runtime_inited = 0; + +static int mot_actuator_init_runtime(void) +{ + int i; + int regIdx; + + if (runtime_inited == true) { + CAM_DBG(CAM_ACTUATOR, "Runtime has been inited!!!"); + return 0; + } + + if (mot_device_index >= MOT_DEVICE_NUM) { + CAM_ERR(CAM_ACTUATOR, "INVALID DEVICE!!!"); + return -1; + } + + for (i = 0; i < mot_dev_list[mot_device_index].actuator_num; i++) { + if (mot_dev_list[mot_device_index].actuator_info[i].actuator_type == MOT_ACTUATOR_INVALID) { + CAM_DBG(CAM_ACTUATOR, "NO. %d actuator type is %d", + i, mot_dev_list[mot_device_index].actuator_info[i].actuator_type); + continue; + } + + /*Init actuators' CCI data*/ + mot_actuator_runtime[i].io_master.master_type = CCI_MASTER; + mot_actuator_runtime[i].io_master.cci_client = &mot_actuator_runtime[i].client; + mot_actuator_runtime[i].client.sid = mot_dev_list[mot_device_index].actuator_info[i].cci_addr; + mot_actuator_runtime[i].client.cci_device = mot_dev_list[mot_device_index].actuator_info[i].cci_dev; + mot_actuator_runtime[i].client.cci_i2c_master = mot_dev_list[mot_device_index].actuator_info[i].cci_master; + CAM_DBG(CAM_ACTUATOR, "NO. %d ACTUATOR sid:%x, cci_device:%d, cci_i2c_master:%d", + i, mot_actuator_runtime[i].client.sid, mot_actuator_runtime[i].client.cci_device, + mot_actuator_runtime[i].client.cci_i2c_master); + + /*Init actuators' DAC pos*/ + if (lens_safe_pos_dac != 0) { + mot_actuator_runtime[i].safe_dac_pos = lens_safe_pos_dac; + } else { + mot_actuator_runtime[i].safe_dac_pos = mot_dev_list[mot_device_index].actuator_info[i].dac_pos; + } + CAM_DBG(CAM_ACTUATOR, "ACTUATOR NO. %d, DAC pos: %d", i, mot_actuator_runtime[i].safe_dac_pos); + + /*Init actuators' regulators*/ + for (regIdx = 0; regIdx < REGULATOR_NUM; regIdx++) { + char *reg_name = mot_dev_list[mot_device_index].actuator_info[i].regulator_list[regIdx]; + if (reg_name[0] != '\0' && mot_actuator_runtime[i].regulators[regIdx] == NULL) { + mot_actuator_runtime[i].regulators[regIdx] = regulator_get(&mot_actuator_fctrl.v4l2_dev_str.pdev->dev, reg_name); + if (mot_actuator_runtime[i].regulators[regIdx] == NULL) { + CAM_DBG(CAM_ACTUATOR, "REGULATOR NO. %d of actuator %d IS NULL!", regIdx, i); + } else { + CAM_DBG(CAM_ACTUATOR, "REGULATOR GET SUCCESS:%p", mot_actuator_runtime[i].regulators[regIdx]); + regulator_set_voltage(mot_actuator_runtime[i].regulators[regIdx], + mot_dev_list[mot_device_index].actuator_info[i].regulator_volt_uv[regIdx], + mot_dev_list[mot_device_index].actuator_info[i].regulator_volt_uv[regIdx]); + } + } + } + } + + runtime_inited = true; + + return 0; +} + +static int32_t mot_actuator_apply_settings(struct camera_io_master *io_master_info, + struct cam_sensor_i2c_reg_setting *write_setting) +{ + /*Usually actuator initial setting will execute power down reset(PD), actuator can't respond + CCI access for a while after PD. Add lock to avoid access actuator while PD operation.*/ + int32_t ret = 0; + mot_actuator_lock(); + ret = camera_io_dev_write(io_master_info, write_setting); + mot_actuator_unlock(); + return ret; +} + +static struct cam_sensor_i2c_reg_setting *mot_actuator_get_init_settings(uint32_t index) +{ + uint32_t actuator_index = mot_dev_list[mot_device_index].actuator_info[index].actuator_type - MOT_ACTUATOR_FIRST; + return mot_actuator_list[actuator_index].init_setting; +} + +static struct cam_sensor_i2c_reg_setting *mot_actuator_get_dac_settings(uint32_t index) +{ + uint32_t actuator_index = mot_dev_list[mot_device_index].actuator_info[index].actuator_type - MOT_ACTUATOR_FIRST; + return mot_actuator_list[actuator_index].dac_setting; +} + +static int32_t mot_actuator_move_lens_by_dac(uint32_t index, uint32_t dac_value) +{ + struct cam_sensor_i2c_reg_setting *dac_setting = mot_actuator_get_dac_settings(index); + /*Fill the DAC value*/ + dac_setting->reg_setting[0].reg_data = dac_value; + CAM_DBG(CAM_ACTUATOR, "move lens to DAC pos: %d", dac_value); + return mot_actuator_apply_settings(&mot_actuator_runtime[index].io_master, dac_setting); +} + +static int32_t mot_actuator_power_on(uint32_t index) +{ + int i; + int ret = 0; + + for (i = 0; i < REGULATOR_NUM; i++) { + if (mot_actuator_runtime[index].regulators[i] != NULL) { + ret = regulator_enable(mot_actuator_runtime[index].regulators[i]); + CAM_DBG(CAM_ACTUATOR, "power on ret %d", ret); + } + } + + return ret; +} + +static int32_t mot_actuator_power_off(uint32_t index) +{ + int i; + int ret = 0; + + for (i = 0; i < REGULATOR_NUM; i++) { + if (mot_actuator_runtime[index].regulators[i] != NULL) { + ret = regulator_disable(mot_actuator_runtime[index].regulators[i]); + CAM_DBG(CAM_ACTUATOR, "power off ret %d", ret); + } + } + + return ret; +} + +int32_t mot_actuator_init_cci(uint32_t index) +{ + int32_t ret = 0; + + CAM_DBG(CAM_ACTUATOR, "init cci."); + ret = camera_io_init(&mot_actuator_runtime[index].io_master); + if (ret != 0) { + CAM_ERR(CAM_ACTUATOR, "init cci failed, ret=%d!!!", ret); + } + return ret; +} + +int32_t mot_actuator_release_cci(uint32_t index) +{ + int32_t ret = 0; + + CAM_DBG(CAM_ACTUATOR, "release cci."); + ret = camera_io_release(&mot_actuator_runtime[index].io_master); + if (ret != 0) { + CAM_ERR(CAM_ACTUATOR, "release cci failed, ret=%d!!!", ret); + } + return ret; +} + +static int32_t mot_actuator_vib_move_lens(uint32_t index) +{ + int32_t ret = 0; + + if (mot_device_index >= MOT_DEVICE_NUM || index > mot_dev_list[mot_device_index].actuator_num) { + CAM_ERR(CAM_ACTUATOR, "INVALID device!!!"); + return -1; + } + + if (mot_actuator_state <= MOT_ACTUATOR_IDLE || mot_actuator_state >= MOT_ACTUATOR_RELEASED) { + mot_actuator_init_runtime(); + mot_actuator_power_on(index); + ret = mot_actuator_init_cci(index); + if (ret == 0) { + ret = mot_actuator_apply_settings(&mot_actuator_runtime[index].io_master, mot_actuator_get_init_settings(index)); + if (ret == 0) { + CAM_DBG(CAM_ACTUATOR, "init acutator sucess", ret); + mot_actuator_state = MOT_ACTUATOR_INITED; + } else { + mot_actuator_release_cci(index); + CAM_ERR(CAM_ACTUATOR, "init acutator failed, ret=%d!!!", ret); + } + } else { + CAM_ERR(CAM_ACTUATOR, "init cci device failed, ret=%d!!!", ret); + } + + if (ret != 0) { + CAM_ERR(CAM_ACTUATOR, "init actuator encountered error, power off now. ret=%d", ret); + mot_actuator_power_off(index); + } + } + + if (ret == 0 && mot_actuator_state == MOT_ACTUATOR_INITED) { + /*Move lens to the specified position.*/ + unsigned int consumers = mot_actuator_get_consumers(); + + CAM_DBG(CAM_ACTUATOR, "actuator consumers: %d", consumers); + + if ((consumers & CLINET_VIBRATOR_MASK) == 0) { + mot_actuator_get(ACTUATOR_CLIENT_VIBRATOR); + } + + if (consumers == 0) { + /*Just move lens when camera off and before first vibrating*/ + ret = mot_actuator_move_lens_by_dac(index, mot_actuator_runtime[index].safe_dac_pos); + if (ret == 0) { + CAM_DBG(CAM_ACTUATOR, "actuator:%d is safe now, please start vibrating"); + } else { + CAM_ERR(CAM_ACTUATOR, "write dac failed, ret=%d!!!", ret); + } + } else { + CAM_DBG(CAM_ACTUATOR, "actuator is already in position."); + } + + mot_actuator_state = MOT_ACTUATOR_STARTED; + } else { + CAM_DBG(CAM_ACTUATOR, "May be already in position. state: %d ret=%d.", mot_actuator_state, ret); + } + + return ret; +} + +static int32_t mot_actuator_park_lens(uint32_t index) +{ + uint32_t cur_len_pos = mot_actuator_runtime[index].safe_dac_pos; + int stageIndex; + unsigned int consumers = 0; + int32_t ret = 0; + + if (mot_dev_list[mot_device_index].actuator_info[index].park_lens_needed == false) { + CAM_DBG(CAM_ACTUATOR, "Park lens is not needed."); + return 0; + } + + while (cur_len_pos > lens_park_pos) { + consumers = mot_actuator_get_consumers(); + if ((consumers & (~CLINET_VIBRATOR_MASK)) != 0) { + CAM_WARN(CAM_ACTUATOR, "Park lens was broken by other actuator requests."); + break; + } + + for (stageIndex=0; stageIndex= lens_park_table[stageIndex].kneePoint && lens_park_table[stageIndex].step > 0) { + cur_len_pos -= lens_park_table[stageIndex].step; + break; + } + } + + if (lens_park_table[stageIndex].step <= 0 && cur_len_pos > lens_park_pos) { + cur_len_pos -= 10; + } + + ret = mot_actuator_move_lens_by_dac(index, cur_len_pos); + + if (ret < 0 ) { + CAM_ERR(CAM_ACTUATOR, "Park Lens encounter CCI error, break now."); + break; + } + + if (cur_len_pos <= lens_park_pos) { + /*For skipping the last delay*/ + CAM_DBG(CAM_ACTUATOR, "Park lens done."); + break; + } + + usleep_range(10000, 12000); + } + + return 0; +} + +int mot_actuator_on_vibrate_start(void) +{ + bool is_exiting = false; + ktime_t start,end,duration; + start = ktime_get(); + cancel_delayed_work(&mot_actuator_fctrl.delay_work); + if (mutex_is_locked(&mot_actuator_fctrl.actuator_lock)) { + is_exiting = true; + } + mutex_lock(&mot_actuator_fctrl.actuator_lock); + if (is_exiting) { + CAM_WARN(CAM_ACTUATOR, "Wait 2~3ms to let CCI release done."); + usleep_range(2, 3); + } + mot_actuator_vib_move_lens(0); + mutex_unlock(&mot_actuator_fctrl.actuator_lock); + end = ktime_get(); + duration = ktime_sub(end, start); + duration /= 1000; + CAM_DBG(CAM_ACTUATOR, "Move lens delay: %dus", duration); + return 0; +} +EXPORT_SYMBOL(mot_actuator_on_vibrate_start); + +int mot_actuator_on_vibrate_stop(void) +{ + if (mot_actuator_fctrl.mot_actuator_wq != NULL) { + queue_delayed_work(mot_actuator_fctrl.mot_actuator_wq, + &mot_actuator_fctrl.delay_work, msecs_to_jiffies(VIBRATING_MAX_INTERVAL)); + } else { + //Dedicated work queue may create failed, use default one. + schedule_delayed_work(&mot_actuator_fctrl.delay_work, msecs_to_jiffies(VIBRATING_MAX_INTERVAL)); + } + return 0; +} +EXPORT_SYMBOL(mot_actuator_on_vibrate_stop); + +static int32_t mot_actuator_handle_exit(uint32_t arg) +{ + int rc = 0; + + return rc; +} + +static int32_t mot_actuator_handle_write(uint32_t arg) +{ + int rc = 0; + + if (mot_actuator_state != MOT_ACTUATOR_INITED) { + pr_err("%s: mot actuator is not initiated!!", __func__); + return -EINVAL; + } + + return rc; +} + +static void mot_actuator_handle_release(void) +{ + if (mot_actuator_state == MOT_ACTUATOR_RELEASED) { + pr_err("%s: Already released.", __func__); + return; + } + + if (mot_actuator_state == MOT_ACTUATOR_INITED) { + pr_debug("Disable AF power!"); + //regulator_disable(afVdd); + //regulator_disable(ioVdd); + } + pr_debug("%s: Vsync released.", __func__); + mot_actuator_state = MOT_ACTUATOR_RELEASED; + return; +} + +static int32_t mot_actuator_handle_cmd( + struct v4l2_subdev *sd, + uint32_t arg, + unsigned int cmd) +{ + int32_t rc=0; + + switch (cmd) { + case MOT_ACTUATOR_INIT: + /* init */ + mot_actuator_init_runtime(); + pr_debug("%s: MOT_ACTUATOR_INIT ret:%d", __func__, rc); + break; + case MOT_ACTUATOR_READ: + /* read */ + pr_debug("%s: MOT_ACTUATOR_READ ret:%d", __func__, rc); + break; + case MOT_ACTUATOR_WRITE: + /* write */ + mot_actuator_handle_write(arg); + pr_debug("%s: MOT_ACTUATOR_WRITE ret:%d", __func__, rc); + break; + case MOT_ACTUATOR_EXIT: + /* exit */ + mot_actuator_handle_exit(arg); + pr_debug("%s: MOT_ACTUATOR_EXIT ret:%d", __func__, rc); + break; + case MOT_ACTUATOR_RELEASE: + /* release */ + mot_actuator_handle_release(); + pr_debug("%s: MOT_ACTUATOR_RELEASE ret:%d", __func__, rc); + break; + default: + pr_err("%s: Unknown command (%d)\n", __func__, cmd); + rc = -EINVAL; + break; + } + + return rc; +} + +static long mot_actuator_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + pr_debug("%s cmd=%x, arg=%x\n", __func__, cmd, *(int *)arg); + + switch (cmd) { + case MOT_ACTUATOR_READ: + case MOT_ACTUATOR_WRITE: + case MOT_ACTUATOR_INIT: + case MOT_ACTUATOR_EXIT: + case MOT_ACTUATOR_RELEASE: + return mot_actuator_handle_cmd(sd, *(int *)arg, cmd); + default: + pr_err("%s Unsupported cmd=%x, arg=%x\n", __func__, cmd, arg); + pr_debug("%s supported cmd: %x, %x, %x, %x, %x\n", __func__, + MOT_ACTUATOR_READ, + MOT_ACTUATOR_WRITE, + MOT_ACTUATOR_INIT, + MOT_ACTUATOR_EXIT, + MOT_ACTUATOR_RELEASE); + return -ENOIOCTLCMD; + } +} + +#ifdef CONFIG_COMPAT +static long mot_actuator_ioctl32(struct v4l2_subdev *sd, + unsigned int cmd, unsigned long arg) +{ + int cmd_data; + int32_t rc = 0; + + if (copy_from_user(&cmd_data, (void __user *)arg, + sizeof(cmd_data))) { + pr_err("Failed to copy from user_ptr=%pK size=%zu", (void __user *)arg, sizeof(cmd_data)); + return -EFAULT; + } + + pr_debug("%s cmd=%x, arg=%x\n", __func__, cmd, arg); + + switch (cmd) { + case MOT_ACTUATOR_READ32: + cmd = MOT_ACTUATOR_READ; + break; + case MOT_ACTUATOR_WRITE32: + cmd = MOT_ACTUATOR_WRITE; + break; + case MOT_ACTUATOR_INIT32: + cmd = MOT_ACTUATOR_INIT; + break; + case MOT_ACTUATOR_EXIT32: + cmd = MOT_ACTUATOR_EXIT; + break; + case MOT_ACTUATOR_RELEASE32: + cmd = MOT_ACTUATOR_RELEASE; + break; + default: + pr_err("%s Unsupported cmd=%x, arg=%x\n", __func__, cmd, arg); + pr_debug("%s supported cmd: %x, %x, %x, %x, %x\n", __func__, + MOT_ACTUATOR_READ32, + MOT_ACTUATOR_WRITE32, + MOT_ACTUATOR_INIT32, + MOT_ACTUATOR_EXIT32, + MOT_ACTUATOR_RELEASE32); + return -ENOIOCTLCMD; + } + + rc = mot_actuator_ioctl(sd, cmd, (void *)&cmd_data); + + return rc; +} +#endif + +static struct v4l2_subdev_core_ops mot_actuator_subdev_core_ops = { + .ioctl = mot_actuator_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = mot_actuator_ioctl32, +#endif +}; + +static struct v4l2_subdev_ops mot_actuator_subdev_ops = { + .core = &mot_actuator_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops mot_actuator_internal_ops; + +static struct platform_device mot_actuator_device = { + .name = "mot_actuator", + .id = -1, +}; + +static void mot_actuator_delayed_process(struct work_struct *work) +{ + struct mot_actuator_ctrl_t *actuator_fctrl = container_of(work, + struct mot_actuator_ctrl_t, delay_work.work); + unsigned int consumers = 0; + int actuatorUsers = 0; + + mutex_lock(&actuator_fctrl->actuator_lock); + consumers = mot_actuator_get_consumers(); + if ((consumers & CLINET_VIBRATOR_MASK) != 0) { + actuatorUsers = mot_actuator_put(ACTUATOR_CLIENT_VIBRATOR); + } + if (mot_actuator_state >= MOT_ACTUATOR_INITED && mot_actuator_state < MOT_ACTUATOR_RELEASED) { + if ((consumers & (~CLINET_VIBRATOR_MASK)) == 0) { + //Only park lens when there's no other user holding actuator. + mot_actuator_park_lens(0); + } + mot_actuator_power_off(0); + mot_actuator_release_cci(0); + } + mot_actuator_state = MOT_ACTUATOR_RELEASED; + mutex_unlock(&actuator_fctrl->actuator_lock); +} + +static inline ssize_t msm_actuator_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + count = sprintf(buf, "\nmot_actuator_state: %d, device index: %d\n", mot_actuator_state, mot_device_index); + return count; +} + +static ssize_t msm_actuator_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + + if (kstrtouint(buf, 10, &input) != 0) { + retval = -EINVAL; + goto exit; + } + + if (input) { + CAM_DBG(CAM_ACTUATOR, "start actuator"); + mot_actuator_on_vibrate_start(); + } else { + CAM_DBG(CAM_ACTUATOR, "stop actuator"); + mot_actuator_on_vibrate_stop(); + } + retval = count; +exit: + return retval; +} + +//Tuning interface +static inline ssize_t mot_actuator_lens_park_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + count = sprintf(buf, "\n lens park pos: %d\n", lens_park_pos); + return count; +} + +static ssize_t mot_actuator_lens_park_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + + if (kstrtouint(buf, 10, &input) != 0) { + retval = -EINVAL; + goto exit; + } + + lens_park_pos = input; + + retval = count; +exit: + return retval; +} + +static inline ssize_t mot_actuator_safe_pos_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + count = sprintf(buf, "\n safe dac value steps: %d\n", lens_safe_pos_dac); + return count; +} + +static ssize_t mot_actuator_safe_pos_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + + if (kstrtouint(buf, 10, &input) != 0) { + retval = -EINVAL; + goto exit; + } + + lens_safe_pos_dac = input; + + retval = count; +exit: + return retval; +} + +static inline ssize_t mot_actuator_dump_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + count = mot_actuator_dump(buf); + return count; +} + +static ssize_t mot_actuator_dump_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return count; +} + + +static inline ssize_t mot_actuator_park_lens_table_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t count = 0; + int i; + count += sprintf(buf, "\n knee point step\n"); + for (i=0; i 0) { + for (index=0; indexv4l2_dev_str.internal_ops = &mot_actuator_internal_ops; + f_ctrl->v4l2_dev_str.ops = &mot_actuator_subdev_ops; + strlcpy(f_ctrl->device_name, MOT_ACTUATOR_NAME, sizeof(f_ctrl->device_name)); + f_ctrl->v4l2_dev_str.name = f_ctrl->device_name; + f_ctrl->v4l2_dev_str.sd_flags = + (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS); + f_ctrl->v4l2_dev_str.ent_function = CAM_MOT_ACTUATOR_TYPE; + f_ctrl->v4l2_dev_str.token = f_ctrl; + + platform_device_register(&mot_actuator_device); + f_ctrl->v4l2_dev_str.pdev = &mot_actuator_device; + + f_ctrl->mot_actuator_wq = NULL; + f_ctrl->mot_actuator_wq = create_singlethread_workqueue("mot_actuator_wq"); + if (f_ctrl->mot_actuator_wq == NULL) { + pr_err("%s: create work queue failed!!!", __func__); + } + + INIT_DELAYED_WORK(&f_ctrl->delay_work, mot_actuator_delayed_process); + mutex_init(&f_ctrl->actuator_lock); + + {//Debug/tuning interfaces + int i; + for (i=0; iv4l2_dev_str.pdev->dev.kobj, + &mot_actuator_attrs[i].attr); + } + } + + rc = cam_register_subdev(&(f_ctrl->v4l2_dev_str)); + if (rc) + pr_err("%s: Fail with cam_register_subdev rc: %d", __func__, rc); + + return rc; +} + +int mot_actuator_driver_init(void) +{ + pr_debug("%s\n", __func__); + + mot_actuator_init_subdev(&mot_actuator_fctrl); + cam_select_actuator_by_device_name(); + return 0; +} + +void mot_actuator_driver_exit(void) +{ + pr_debug("%s\n", __func__); + + cancel_delayed_work_sync(&mot_actuator_fctrl.delay_work); + if (mot_actuator_fctrl.mot_actuator_wq != NULL) { + flush_workqueue(mot_actuator_fctrl.mot_actuator_wq); + destroy_workqueue(mot_actuator_fctrl.mot_actuator_wq); + mot_actuator_fctrl.mot_actuator_wq = NULL; + } + cam_unregister_subdev(&mot_actuator_fctrl.v4l2_dev_str); +} + +MODULE_DESCRIPTION("MOT ACTUATOR"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_sensor_module/cam_actuator/mot_actuator.h b/drivers/cam_sensor_module/cam_actuator/mot_actuator.h new file mode 100644 index 000000000000..1a70aead7e67 --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/mot_actuator.h @@ -0,0 +1,35 @@ +#ifndef __MOT_ACTUATOR_H__ +#define __MOT_ACTUATOR_H__ + +#include +#include +#define MOT_ACTUATOR_NAME "mot_actuator" + +#define MOT_ACTUATOR_READ \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 50, int) +#define MOT_ACTUATOR_READ32 \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 50, int) + +#define MOT_ACTUATOR_WRITE \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 51, int) +#define MOT_ACTUATOR_WRITE32 \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 51, int) + +#define MOT_ACTUATOR_INIT \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 52, int) +#define MOT_ACTUATOR_INIT32 \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 52, int) + +#define MOT_ACTUATOR_RELEASE \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 53, int) +#define MOT_ACTUATOR_RELEASE32 \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 53, int) + +#define MOT_ACTUATOR_EXIT \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 54, int) +#define MOT_ACTUATOR_EXIT32 \ + _IOWR('X', BASE_VIDIOC_PRIVATE + 54, int) + +int mot_actuator_driver_init(void); +void mot_actuator_driver_exit(void); +#endif /*__MOT_ACTUATOR_H__*/ diff --git a/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.c b/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.c new file mode 100644 index 000000000000..b979927c1c9b --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2020 Motorola Mobility LLC. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include "cam_debug_util.h" +#include "mot_actuator_policy.h" + +extern int mot_actuator_on_vibrate_start(void); +extern int mot_actuator_on_vibrate_stop(void); + +static atomic_t mot_actuator_ref_count = ATOMIC_INIT(0); +static unsigned long mot_actuator_consumers = ATOMIC_INIT(0); +static struct mutex actuator_res_lock = __MUTEX_INITIALIZER(actuator_res_lock); + +int mot_actuator_get(mot_actuator_client user) +{ + if (user <= ACTUATOR_CLIENT_INVALID || user >= ACTUATOR_CLIENT_MAX) { + CAM_ERR(CAM_ACTUATOR, "INVALID CLIENT!!!"); + return 0; + } + + CAM_DBG(CAM_ACTUATOR, "Obtain actuator from: %d", user); + + test_and_set_bit(user, &mot_actuator_consumers); + + return atomic_add_return(1, &mot_actuator_ref_count); +} +EXPORT_SYMBOL(mot_actuator_get); + +int mot_actuator_put(mot_actuator_client user) +{ + unsigned long consumers = 0; + if (user <= ACTUATOR_CLIENT_INVALID || user >= ACTUATOR_CLIENT_MAX) { + CAM_ERR(CAM_ACTUATOR, "INVALID CLIENT!!!"); + return 0; + } + + CAM_DBG(CAM_ACTUATOR, "Release actuator from: %d", user); + + test_and_clear_bit(user, &mot_actuator_consumers); + + consumers = mot_actuator_get_consumers(); + if (((consumers & CLINET_VIBRATOR_MASK) == CLINET_VIBRATOR_MASK) && + (user != ACTUATOR_CLIENT_VIBRATOR)) { + //If only vibrator noise eliminator exists, move lens to required position + CAM_DBG(CAM_ACTUATOR, "Set actuator pos for vibrator"); + mot_actuator_on_vibrate_start(); + if ((mot_actuator_get_consumers() & CLINET_VIBRATOR_MASK) == 0) { + mot_actuator_on_vibrate_stop(); + } + } + + return atomic_sub_return(1, &mot_actuator_ref_count); +} +EXPORT_SYMBOL(mot_actuator_put); + +int mot_actuator_get_ref_count(void) +{ + return atomic_read(&mot_actuator_ref_count); +} +EXPORT_SYMBOL(mot_actuator_get_ref_count); + +unsigned int mot_actuator_get_consumers(void) +{ + return mot_actuator_consumers; +} +EXPORT_SYMBOL(mot_actuator_get_consumers); + +void mot_actuator_lock(void) +{ + mutex_lock(&actuator_res_lock); +} +EXPORT_SYMBOL(mot_actuator_lock); + +void mot_actuator_unlock(void) +{ + mutex_unlock(&actuator_res_lock); +} +EXPORT_SYMBOL(mot_actuator_unlock); + +ssize_t mot_actuator_dump(char *buf) +{ + int item_len = 0; + unsigned int consumers = mot_actuator_get_consumers(); + + item_len += sprintf(buf+item_len, "refCount: %d\n", mot_actuator_get_ref_count()); + item_len += sprintf(buf+item_len, "Consumers (0x%x):\n", consumers); + + if (consumers & CLINET_CAMERA_MASK) { + item_len += sprintf(buf+item_len, "camera"); + } + + if (consumers & CLINET_VIBRATOR_MASK) { + item_len += sprintf(buf+item_len, " vibrator"); + } + + item_len += sprintf(buf+item_len, "\n"); + + CAM_DBG(CAM_ACTUATOR, "ref cnt:%d, consumers:0x%x", mot_actuator_get_ref_count(), mot_actuator_get_consumers()); + return item_len; +} +EXPORT_SYMBOL(mot_actuator_dump); diff --git a/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.h b/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.h new file mode 100644 index 000000000000..3278546e0e3a --- /dev/null +++ b/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.h @@ -0,0 +1,20 @@ +#ifndef __MOT_ACTUATOR_POLICY_H__ +#define __MOT_ACTUATOR_POLICY_H__ + +typedef enum { + ACTUATOR_CLIENT_INVALID, + ACTUATOR_CLIENT_CAMERA, + ACTUATOR_CLIENT_VIBRATOR, + ACTUATOR_CLIENT_MAX +} mot_actuator_client; + +#define CLINET_CAMERA_MASK (0x01 << ACTUATOR_CLIENT_CAMERA) +#define CLINET_VIBRATOR_MASK (0x01 << ACTUATOR_CLIENT_VIBRATOR) + +int mot_actuator_get(mot_actuator_client user); +int mot_actuator_put(mot_actuator_client user); +void mot_actuator_lock(void); +void mot_actuator_unlock(void); +ssize_t mot_actuator_dump(char *buf); +unsigned int mot_actuator_get_consumers(void); +#endif /*__MOT_ACTUATOR_POLICY_H__*/ diff --git a/drivers/camera_main.c b/drivers/camera_main.c index f59be8dbe113..4e838c377473 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -20,6 +20,7 @@ #include "cam_cci_dev.h" #include "cam_sensor_dev.h" #include "cam_actuator_dev.h" +#include "mot_actuator.h" #include "cam_csiphy_dev.h" #include "cam_eeprom_dev.h" #include "cam_ois_dev.h" @@ -105,6 +106,7 @@ static const struct camera_submodule_component camera_sensor[] = { {&cam_cci_init_module, &cam_cci_exit_module}, {&cam_csiphy_init_module, &cam_csiphy_exit_module}, {&cam_actuator_driver_init, &cam_actuator_driver_exit}, + {&mot_actuator_driver_init, &mot_actuator_driver_exit}, {&cam_sensor_driver_init, &cam_sensor_driver_exit}, {&cam_eeprom_driver_init, &cam_eeprom_driver_exit}, {&cam_ois_driver_init, &cam_ois_driver_exit}, diff --git a/include/uapi/camera/media/cam_req_mgr.h b/include/uapi/camera/media/cam_req_mgr.h index 2ce529fdf82b..5d0700529652 100644 --- a/include/uapi/camera/media/cam_req_mgr.h +++ b/include/uapi/camera/media/cam_req_mgr.h @@ -32,6 +32,7 @@ #define CAM_CUSTOM_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 14) #define CAM_OPE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 15) #define CAM_TFE_DEVICE_TYPE (CAM_DEVICE_TYPE_BASE + 16) +#define CAM_MOT_ACTUATOR_TYPE (CAM_DEVICE_TYPE_BASE + 17) /* cam_req_mgr hdl info */ #define CAM_REQ_MGR_HDL_IDX_POS 8