From 68f7e5cb865d1fb56441d644ec3bb0d325b7944e Mon Sep 17 00:00:00 2001 From: wangshuo18 Date: Mon, 22 Mar 2021 20:32:52 +0800 Subject: [PATCH] cam: Add actuator standalone diver for vibrator. -To eliminate the resonance noise during system vibrator vibrating, set actuator to specified DAC position(480 on DW9714), then the resonance noise can be obviously improved. To achieve the conbination between vibrator and camera AF actuator,we implemnte: - Actuator separately control during camera power off. - Actuator policy to avoid vibrating disturb normal camera AF. port from (CR),fix berlna wide camera resonance noise issue. -Port from (CR): cam/actuator: Add CCI access lock to avoid conflicts. 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. -Port from (CR): cam/actuator: Create separate work queue for park lens. Park lens may cost more than 100ms for different camera modules, create seperate work queue for actuator to avoid park lens operation block system_wq too long. -Port from (CR): cam/actautor: Optimizing park lens for vibrating. Move lens to noise reduction postion after camera exited. -Port from (CR): cam/actuator: Avoid error releasing CCI/regulator. Avoid unbalanced aquire/release of CCI/regulator when actuator init failed. Due to when CCI init for vibrator failed, regulators had been released. -For new baseline sm8350,compile this standalone actuator diver into camera.ko Change-Id: If77d10badfb4147c467ebae238f4e6af317d466f Signed-off-by: wangshuo18 Reviewed-on: https://gerrit.mot.com/1906964 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Dawei Wang Reviewed-by: Darong Huang Reviewed-by: Long Cheng Reviewed-by: Xu Ji Reviewed-by: Jian Zhang Reviewed-by: Zhuoran Xu Reviewed-by: Bolei Shang Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/Makefile | 6 + .../cam_actuator/cam_actuator_core.c | 32 +- .../cam_actuator/cam_actuator_dev.h | 3 + .../cam_actuator/cam_actuator_soc.c | 9 + .../cam_actuator/mot_actuator.c | 1032 +++++++++++++++++ .../cam_actuator/mot_actuator.h | 35 + .../cam_actuator/mot_actuator_policy.c | 113 ++ .../cam_actuator/mot_actuator_policy.h | 20 + drivers/camera_main.c | 2 + include/uapi/camera/media/cam_req_mgr.h | 1 + 10 files changed, 1252 insertions(+), 1 deletion(-) create mode 100644 drivers/cam_sensor_module/cam_actuator/mot_actuator.c create mode 100644 drivers/cam_sensor_module/cam_actuator/mot_actuator.h create mode 100644 drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.c create mode 100644 drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.h 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