diff --git a/techpack/camera-bengal/drivers/cam_cdm/cam_cdm_hw_core.c b/techpack/camera-bengal/drivers/cam_cdm/cam_cdm_hw_core.c index 0739bd25e983..b732d3d507f6 100644 --- a/techpack/camera-bengal/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/techpack/camera-bengal/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1363,8 +1363,6 @@ static void cam_hw_cdm_work(struct work_struct *work) CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); - } else { - CAM_ERR(CAM_CDM, "NULL payload"); } kfree(payload); payload = NULL; diff --git a/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_core.h b/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_core.h index c638f4f796ec..c62468fdf7d7 100644 --- a/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -14,7 +14,7 @@ #define CAM_REQ_MGR_MAX_LINKED_DEV 16 #define MAX_REQ_SLOTS 48 -#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 1000 +#define CAM_REQ_MGR_WATCHDOG_TIMEOUT 5000 #define CAM_REQ_MGR_WATCHDOG_TIMEOUT_DEFAULT 5000 #define CAM_REQ_MGR_WATCHDOG_TIMEOUT_MAX 50000 #define CAM_REQ_MGR_SCHED_REQ_TIMEOUT 1000 diff --git a/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.c b/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.c index a3eb168a6802..b52cdf4bbca2 100644 --- a/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -37,7 +37,7 @@ int cam_req_mgr_util_init(void) rc = -ENOMEM; goto hdl_tbl_alloc_failed; } - bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES_V2) * sizeof(long); + bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long); hdl_tbl_local->bitmap = kzalloc(bitmap_size, GFP_KERNEL); if (!hdl_tbl_local->bitmap) { rc = -ENOMEM; @@ -95,7 +95,7 @@ int cam_req_mgr_util_free_hdls(void) return -EINVAL; } - for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) { + for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) { if (hdl_tbl->hdl[i].state == HDL_ACTIVE) { CAM_WARN(CAM_CRM, "Dev handle = %x session_handle = %x", hdl_tbl->hdl[i].hdl_value, @@ -104,7 +104,7 @@ int cam_req_mgr_util_free_hdls(void) clear_bit(i, hdl_tbl->bitmap); } } - bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES_V2); + bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES); spin_unlock_bh(&hdl_tbl_lock); return 0; @@ -116,7 +116,7 @@ static int32_t cam_get_free_handle_index(void) idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits); - if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES || idx < 0) { CAM_ERR(CAM_CRM, "No free index found idx: %d", idx); return -ENOSR; } @@ -130,9 +130,9 @@ static void cam_dump_tbl_info(void) { int i; - for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) + for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) CAM_INFO_RATE_LIMIT_CUSTOM(CAM_CRM, CAM_RATE_LIMIT_INTERVAL_5SEC, - CAM_REQ_MGR_MAX_HANDLES_V2, + CAM_REQ_MGR_MAX_HANDLES, "session_hdl=%x hdl_value=%x type=%d state=%d dev_id=%lld", hdl_tbl->hdl[i].session_hdl, hdl_tbl->hdl[i].hdl_value, hdl_tbl->hdl[i].type, hdl_tbl->hdl[i].state, hdl_tbl->hdl[i].dev_id); @@ -266,7 +266,7 @@ void *cam_get_priv(int32_t dev_hdl, int handle_type) } idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); - if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES) { CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx: %d", idx); goto device_priv_fail; } @@ -338,7 +338,7 @@ void *cam_get_device_ops(int32_t dev_hdl) } idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); - if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES) { CAM_ERR(CAM_CRM, "Invalid idx"); goto device_ops_fail; } @@ -381,7 +381,7 @@ static int cam_destroy_hdl(int32_t dev_hdl, int dev_hdl_type) } idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl); - if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) { + if (idx >= CAM_REQ_MGR_MAX_HANDLES) { CAM_ERR(CAM_CRM, "Invalid idx %d", idx); goto destroy_hdl_fail; } diff --git a/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.h b/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.h index 7fbaad2447a0..952a9d6adb3e 100644 --- a/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.h +++ b/techpack/camera-bengal/drivers/cam_req_mgr/cam_req_mgr_util.h @@ -62,7 +62,7 @@ struct handle { * @bits: size of bit map in bits */ struct cam_req_mgr_util_hdl_tbl { - struct handle hdl[CAM_REQ_MGR_MAX_HANDLES_V2]; + struct handle hdl[CAM_REQ_MGR_MAX_HANDLES]; void *bitmap; size_t bits; }; diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/Makefile b/techpack/camera-bengal/drivers/cam_sensor_module/Makefile index 6925b3aba80f..09101db66208 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/Makefile +++ b/techpack/camera-bengal/drivers/cam_sensor_module/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_eeprom/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_ois/ obj-$(CONFIG_SPECTRA_CAMERA) += cam_flash/ +obj-$(CONFIG_CAMERA_FLASH_PWM) += cam_flash_pm6125_gpio/ diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/Makefile b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/Makefile index 7fcf2ffb2cda..232d5bbb316d 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/Makefile +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/Makefile @@ -12,3 +12,4 @@ ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_utils obj-$(CONFIG_SPECTRA_CAMERA) += cam_actuator_dev.o cam_actuator_core.o cam_actuator_soc.o +obj-$(CONFIG_AF_NOISE_ELIMINATION) += mot_actuator.o mot_actuator_policy.o diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c index 8159ea75a1eb..07086730eccd 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_core.c @@ -11,6 +11,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) @@ -253,7 +256,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( @@ -270,6 +279,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; } @@ -567,6 +584,13 @@ int32_t cam_actuator_i2c_pkt_parse(struct cam_actuator_ctrl_t *a_ctrl, cam_mem_put_cpu_buf(cmd_desc[i].mem_handle); } +#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) { @@ -860,6 +884,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/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h index e4bfaed4414f..be80bdd6eec9 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h +++ b/techpack/camera-bengal/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 intf_params bridge_intf; uint32_t last_flush_req; +#ifdef CONFIG_AF_NOISE_ELIMINATION + bool is_multi_user_supported; +#endif }; #endif /* _CAM_ACTUATOR_DEV_H_ */ diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c index 3ee629e3f1ca..13a824382636 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c +++ b/techpack/camera-bengal/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/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator.c new file mode 100644 index 000000000000..688c5e6e04bc --- /dev/null +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator.c @@ -0,0 +1,1189 @@ +/* + * 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 +#include "cam_debug_util.h" +#include "cam_cci_dev.h" +#include "mot_actuator.h" +#include "mot_actuator_policy.h" +#include "linux/pm_wakeup.h" + +/*=================ACTUATOR HW INFO====================*/ +#define DEVICE_NAME_LEN 32 +#define MAX_ACTUATOR_NUM 5 +#define REGULATOR_NAME_MAX_LEN 32 +#define LENS_MAX_STAGES 10 + +typedef enum { + MOT_ACTUATOR_INVALID, + MOT_ACTUATOR_FIRST, + MOT_ACTUATOR_GT9767 = MOT_ACTUATOR_FIRST, + MOT_ACTUATOR_GT9772, + MOT_ACTUATOR_DW9800V, + MOT_ACTUATOR_NUM, +} mot_actuator_type; + +typedef enum { + REGULATOR_IOVDD, + REGULATOR_AFVDD, + REGULATOR_NUM, +} mot_regulator_type; + +typedef enum { + MOT_DEVICE_NIO, + MOT_DEVICE_CAPRIP, + MOT_DEVICE_RHODE, + MOT_DEVICE_HAWAO, + MOT_DEVICE_DEVON, + MOT_DEVICE_NUM, +} mot_dev_type; + +typedef struct { + uint16_t kneePoint; + uint16_t step; +} mot_park_lens_step; + +typedef struct { + uint16_t kneePoint; + uint16_t step; +} mot_lens_step; + +typedef struct { + bool launch_lens_needed; + mot_lens_step launch_lens_step[LENS_MAX_STAGES]; +} mot_launch_lens; + +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 init_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_launch_lens launch_lens; +} mot_actuator_hw_info; + +typedef struct { + mot_dev_type dev_type; + char dev_name[DEVICE_NAME_LEN]; + mot_actuator_hw_info actuator_info[MAX_ACTUATOR_NUM]; +} mot_dev_info; + +/*Register settings of GT9767*/ +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, +}; + + +static struct cam_sensor_i2c_reg_array mot_dw9800v_init_setting[] ={ + {0x02, 0x01, 0}, + {0x02, 0x00, 100}, + {0x02, 0x02, 0}, + {0x06, 0x40, 0}, + {0x07, 0x79, 0}, +}; + +static struct cam_sensor_i2c_reg_array mot_dw9800v_dac_setting[] ={ + {0x03, 0x3ff, 0} +}; + +static struct cam_sensor_i2c_reg_setting mot_dw9800v_init_settings = { + .reg_setting = mot_dw9800v_init_setting, + .size = ARRAY_SIZE(mot_dw9800v_init_setting), + .addr_type = CAMERA_SENSOR_I2C_TYPE_BYTE, + .data_type = CAMERA_SENSOR_I2C_TYPE_BYTE, +}; + +static struct cam_sensor_i2c_reg_setting mot_dw9800v_dac_settings = { + .reg_setting = mot_dw9800v_dac_setting, + .size = ARRAY_SIZE(mot_dw9800v_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] = { + //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_dw9800v_init_settings, &mot_dw9800v_dac_settings}, +}; + +static const mot_dev_info mot_dev_list[MOT_DEVICE_NUM] = { + { + .dev_type = MOT_DEVICE_NIO, + .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_CAPRIP, + .dev_name = "caprip", + .actuator_info = { + [0] = { + .actuator_type = MOT_ACTUATOR_GT9767, + .dac_pos = 154, + .cci_addr = 0x0c, + .cci_dev = 0x00, + .cci_master = 0x0, + .regulator_list = {"pm8008_l7", "pm8008_l5"}, + .regulator_volt_uv = {1800000, 2800000}, + .park_lens_needed = false, + }, + }, + }, + { + .dev_type = MOT_DEVICE_RHODE, + .dev_name = "rhode", + .actuator_info = { + [0] = { + .actuator_type = MOT_ACTUATOR_DW9800V, + .dac_pos = 0, + .init_pos = 512, + .cci_addr = 0x0c, + .cci_dev = 0x00, + .cci_master = 0x0, + .regulator_list = {"ldo4", "ldo3"}, + .regulator_volt_uv = {1800000, 2800000}, + .park_lens_needed = true, + .launch_lens = { + .launch_lens_needed = true, + .launch_lens_step = { + {300, 150}, + {200, 100}, + {100, 62} + }, + }, + }, + }, + }, + { + .dev_type = MOT_DEVICE_HAWAO, + .dev_name = "hawao", + .actuator_info = { + [0] = { + .actuator_type = MOT_ACTUATOR_DW9800V, + .dac_pos = 0, + .init_pos = 512, + .cci_addr = 0x0c, + .cci_dev = 0x00, + .cci_master = 0x0, + .regulator_list = {"ldo7", "ldo5"}, + .regulator_volt_uv = {1800000, 2800000}, + .park_lens_needed = true, + .launch_lens = { + .launch_lens_needed = true, + .launch_lens_step = { + {300, 150}, + {200, 100}, + {100, 62} + }, + }, + }, + }, + }, + { + .dev_type = MOT_DEVICE_DEVON, + .dev_name = "devon", + .actuator_info = { + [0] = { + .actuator_type = MOT_ACTUATOR_DW9800V, + .dac_pos = 0, + .init_pos = 512, + .cci_addr = 0x0c, + .cci_dev = 0x00, + .cci_master = 0x0, + .regulator_list = {"camera_iovdd", "camera_main_afvdd"}, + .regulator_volt_uv = {1800000, 2800000}, + .park_lens_needed = true, + .launch_lens = { + .launch_lens_needed = true, + .launch_lens_step = { + {300, 150}, + {200, 100}, + {100, 62} + }, + }, + }, + }, + }, +}; + +static uint32_t mot_device_index = MOT_DEVICE_NUM; +static int cam_select_actuator_by_device_name(char *str) +{ + uint32_t i; + + for (i=0; i= MOT_DEVICE_NUM) { + CAM_ERR(CAM_ACTUATOR, "UNKNOWN DEVICE:%s", str); + } + return 1; +} +__setup("androidboot.device=", cam_select_actuator_by_device_name); + +/*=================ACTUATOR RUNTIME====================*/ +#define VIBRATING_MAX_INTERVAL 2000//ms +#define PARK_LENS_MAX_STAGES 10 +#define LAUNCH_LENS_MAX_STAGES LENS_MAX_STAGES + +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; + struct wakeup_source actuator_wakelock; +}; + +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 = 512; +static mot_park_lens_step lens_park_table[PARK_LENS_MAX_STAGES] = {}; +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 < MAX_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,rc = 0; + + CAM_DBG(CAM_ACTUATOR, "init cci."); + ret = camera_io_init(&mot_actuator_runtime[index].io_master); + if (ret != 0) { + rc = camera_io_release(&mot_actuator_runtime[index].io_master); + CAM_ERR(CAM_ACTUATOR, "init cci failed!!! ret=%d,release rc=%d. try again!", ret, rc); + /*delay 100ms and try again*/ + usleep_range(100000, 100100); + ret = camera_io_init(&mot_actuator_runtime[index].io_master); + if (ret != 0) { + rc = camera_io_release(&mot_actuator_runtime[index].io_master); + CAM_ERR(CAM_ACTUATOR, "try again init cci failed!!! ret=%d, release rc=%d", ret, rc); + } + } + 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_launch_lens(uint32_t index, uint32_t dac_value) +{ + uint32_t cur_len_pos = mot_dev_list[mot_device_index].actuator_info[index].init_pos; + uint32_t last_len_pos = 0; + int stageIndex; + unsigned int consumers = 0; + int32_t ret = 0; + uint32_t lens_launch_pos = dac_value; + mot_lens_step const *lens_launch_table = mot_dev_list[mot_device_index].actuator_info[index].launch_lens.launch_lens_step; + + if (mot_dev_list[mot_device_index].actuator_info[index].launch_lens.launch_lens_needed == false) { + CAM_DBG(CAM_ACTUATOR, "Launch lens is not needed."); + return 0; + } + while (cur_len_pos < lens_launch_pos) { + consumers = mot_actuator_get_consumers(); + if ((consumers & (~CLINET_VIBRATOR_MASK)) != 0) { + CAM_WARN(CAM_ACTUATOR, "Launch lens was broken by other actuator requests."); + break; + } + + for (stageIndex=0; stageIndex 0) { + cur_len_pos += lens_launch_table[stageIndex].step; + break; + } + } + + if (stageIndex == LAUNCH_LENS_MAX_STAGES && cur_len_pos < lens_launch_pos) { + cur_len_pos += 10; + } + + if(last_len_pos == cur_len_pos) + /*break the cycle when cur_len_pos didn't update*/ + break; + else + last_len_pos = cur_len_pos; + + ret = mot_actuator_move_lens_by_dac(index, cur_len_pos); + + if (ret < 0 ) { + CAM_ERR(CAM_ACTUATOR, "Launch Lens encounter CCI error, break now."); + break; + } + + if (cur_len_pos >= lens_launch_pos) { + /*For skipping the last delay*/ + CAM_DBG(CAM_ACTUATOR, "Launch lens done."); + break; + } + + usleep_range(2000, 3000); + } + + // from 512 to 0 + while (cur_len_pos > lens_launch_pos) { + consumers = mot_actuator_get_consumers(); + if ((consumers & (~CLINET_VIBRATOR_MASK)) != 0) { + CAM_WARN(CAM_ACTUATOR, "Launch lens was broken by other actuator requests."); + break; + } + + for (stageIndex = 0; stageIndex < LENS_MAX_STAGES; stageIndex++) { + if (lens_launch_table[stageIndex].kneePoint == 0 && lens_launch_table[stageIndex].step == 0) { + break; + } + + if (cur_len_pos >= lens_launch_table[stageIndex].kneePoint && lens_launch_table[stageIndex].step > 0) { + cur_len_pos -= lens_launch_table[stageIndex].step; + break; + } + } + + if (lens_launch_table[stageIndex].step == 0 && cur_len_pos > lens_launch_pos) { + cur_len_pos -= 10; + if (cur_len_pos < 10) + cur_len_pos = 0; + } + + ret = mot_actuator_move_lens_by_dac(index, cur_len_pos); + + if (ret < 0 ) { + CAM_ERR(CAM_ACTUATOR, "Launch Lens encounter CCI error, break now."); + break; + } + + if (cur_len_pos <= lens_launch_pos) { + /*For skipping the last delay*/ + CAM_DBG(CAM_ACTUATOR, "Launch lens done."); + break; + } + + usleep_range(10000, 12000); + } + return ret; +} + +static int32_t mot_actuator_vib_move_lens(uint32_t index) +{ + int32_t ret = 0; + unsigned int consumers = 0; + + if (mot_device_index >= MOT_DEVICE_NUM || index >= MAX_ACTUATOR_NUM) { + CAM_ERR(CAM_ACTUATOR, "INVALID device!!!"); + return -1; + } + + consumers = mot_actuator_get_consumers(); + + if (consumers & CLINET_CAMERA_MASK) { + /*Don't init actuator when camera on*/ + CAM_WARN(CAM_ACTUATOR, "Camera is holding actuator,don't init actuator for vibrator,consumers=%d",consumers); + } else 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.*/ + 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*/ + /*use launch_lens to move lens step-by-step,reduce TICK noise*/ + if (mot_dev_list[mot_device_index].actuator_info[index].launch_lens.launch_lens_needed == true) { + ret = mot_actuator_launch_lens(index, mot_actuator_runtime[index].safe_dac_pos); + usleep_range(10000, 12000); + }else { + ret = mot_actuator_move_lens_by_dac(index, mot_actuator_runtime[index].safe_dac_pos); + /*delay 10~12ms to wait lens move to specify location*/ + usleep_range(10000, 12000); + } + if (ret == 0) { + CAM_DBG(CAM_ACTUATOR, "actuator is safe now, safe_dac_pos:%d, please start vibrating.", + mot_actuator_runtime[index].safe_dac_pos); + } 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) +{ + ktime_t start,end,duration; + start = ktime_get(); + __pm_stay_awake(&mot_actuator_fctrl.actuator_wakelock); + cancel_delayed_work(&mot_actuator_fctrl.delay_work); + mutex_lock(&mot_actuator_fctrl.actuator_lock); + 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); + __pm_relax(&actuator_fctrl->actuator_wakelock); +} + +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); + memset(&f_ctrl->actuator_wakelock, 0, sizeof(f_ctrl->actuator_wakelock)); + f_ctrl->actuator_wakelock.name = "actuator_hold_wl"; + wakeup_source_add(&f_ctrl->actuator_wakelock); + + {//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; +} + +static int __init mot_actuator_init(void) +{ + pr_debug("%s\n", __func__); + + mot_actuator_init_subdev(&mot_actuator_fctrl); + + return 0; +} + +static void __exit mot_actuator_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); + __pm_relax(&mot_actuator_fctrl.actuator_wakelock); + wakeup_source_remove(&mot_actuator_fctrl.actuator_wakelock); +} + +module_init(mot_actuator_init); +module_exit(mot_actuator_exit); +MODULE_DESCRIPTION("MOT ACTUATOR"); +MODULE_LICENSE("GPL v2"); diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator.h new file mode 100644 index 000000000000..8acc5f0a7fbf --- /dev/null +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator.h @@ -0,0 +1,32 @@ +#ifndef __CAM_ACTUATOR_STANDALONE_H__ +#define __CAM_ACTUATOR_STANDALONE_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) +#endif /*__CAM_ACTUATOR_STANDALONE_H__*/ diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.c new file mode 100644 index 000000000000..b979927c1c9b --- /dev/null +++ b/techpack/camera-bengal/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/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_actuator/mot_actuator_policy.h new file mode 100644 index 000000000000..3278546e0e3a --- /dev/null +++ b/techpack/camera-bengal/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/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c index 4ce815b6394a..ebfb74499607 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.c @@ -27,6 +27,8 @@ struct v4l2_subdev *cam_cci_get_subdev(int cci_dev_index) return sub_device; } +EXPORT_SYMBOL(cam_cci_get_subdev); + static long cam_cci_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h index 00dabdfd6256..6b2d65896b38 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci/cam_cci_dev.h @@ -61,8 +61,8 @@ #define CCI_READ_MAX 256 #define CCI_READ_MAX_V_1_2 0xE #define CCI_I2C_READ_MAX_RETRIES 3 -#define CCI_I2C_MAX_READ 8192 -#define CCI_I2C_MAX_WRITE 8192 +#define CCI_I2C_MAX_READ 20480 +#define CCI_I2C_MAX_WRITE 20480 #define CCI_I2C_MAX_BYTE_COUNT 65535 #define CAMX_CCI_DEV_NAME "cam-cci-driver" diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c index 3e5b3c45ead2..f9713211b923 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_core.c @@ -34,6 +34,7 @@ static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl, struct cam_eeprom_memory_map_t *emap = block->map; struct cam_eeprom_soc_private *eb_info = NULL; uint8_t *memptr = block->mapdata; + uint32_t sz, sz_read; if (!e_ctrl) { CAM_ERR(CAM_EEPROM, "e_ctrl is NULL"); @@ -109,7 +110,7 @@ static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl, emap[j].mem.addr_type, emap[j].mem.data_type, emap[j].mem.valid_size); - if (rc < 0) { + if (rc) { CAM_ERR(CAM_EEPROM, "read failed rc %d", rc); return rc; @@ -117,6 +118,22 @@ static int cam_eeprom_read_memory(struct cam_eeprom_ctrl_t *e_ctrl, memptr += emap[j].mem.valid_size; } + if (emap[j].mem_rl.valid_size) { + for (sz = 0; sz < emap[j].mem_rl.valid_size; sz++) { + rc = camera_io_dev_read(&e_ctrl->io_master_info, + emap[j].mem_rl.addr, &sz_read, + emap[j].mem_rl.addr_type, + emap[j].mem_rl.data_type); + if (rc) { + CAM_ERR(CAM_EEPROM, "read failed rc %d", + rc); + return rc; + } + *memptr = (uint8_t)sz_read; + memptr++; + } + } + if (emap[j].pageen.valid_size) { i2c_reg_settings.addr_type = emap[j].pageen.addr_type; i2c_reg_settings.data_type = emap[j].pageen.data_type; @@ -426,6 +443,7 @@ static int32_t cam_eeprom_parse_memory_map( uint16_t cmd_length_in_bytes = 0; struct cam_cmd_i2c_random_wr *i2c_random_wr = NULL; struct cam_cmd_i2c_continuous_rd *i2c_cont_rd = NULL; + struct cam_cmd_i2c_random_rd *i2c_random_rd = NULL; struct cam_cmd_conditional_wait *i2c_poll = NULL; struct cam_cmd_unconditional_wait *i2c_uncond_wait = NULL; size_t validate_size = 0; @@ -436,6 +454,8 @@ static int32_t cam_eeprom_parse_memory_map( validate_size = sizeof(struct cam_cmd_i2c_random_wr); else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD) validate_size = sizeof(struct cam_cmd_i2c_continuous_rd); + else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD) + validate_size = sizeof(struct cam_cmd_i2c_random_rd); else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT) validate_size = sizeof(struct cam_cmd_unconditional_wait); @@ -502,6 +522,25 @@ static int32_t cam_eeprom_parse_memory_map( cmd_length_in_bytes; data->num_data += map[*num_map].mem.valid_size; break; + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD: + i2c_random_rd = (struct cam_cmd_i2c_random_rd *)cmd_buf; + cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_rd) - sizeof(int32_t); + + if (i2c_random_rd->header.count >= U32_MAX - data->num_data) { + CAM_ERR(CAM_EEPROM, + "int overflow on eeprom memory block"); + return -EINVAL; + } + map[*num_map].mem_rl.addr = i2c_random_rd->data_read[0].reg_data; + map[*num_map].mem_rl.addr_type = i2c_random_rd->header.addr_type; + map[*num_map].mem_rl.data_type = i2c_random_rd->header.data_type; + map[*num_map].mem_rl.valid_size = + i2c_random_rd->header.count; + cmd_buf += cmd_length_in_bytes / sizeof(int32_t); + processed_size += + cmd_length_in_bytes; + data->num_data += map[*num_map].mem_rl.valid_size; + break; case CAMERA_SENSOR_CMD_TYPE_WAIT: if (generic_op_code == CAMERA_SENSOR_WAIT_OP_HW_UCND || @@ -1034,6 +1073,7 @@ static int32_t cam_eeprom_init_pkt_parser(struct cam_eeprom_ctrl_t *e_ctrl, break; case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR: case CAMERA_SENSOR_CMD_TYPE_I2C_CONT_RD: + case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_RD: case CAMERA_SENSOR_CMD_TYPE_WAIT: num_map++; rc = cam_eeprom_parse_memory_map( diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h index 66f8aaddc958..9e2884178960 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h @@ -63,6 +63,7 @@ struct cam_eeprom_map_t { * @pageen : pageen memory * @poll : poll memory * @mem : mem + * @mem_rl : mem_rl: used for operation READ_LOOP * @saddr : slave addr * */ @@ -71,6 +72,7 @@ struct cam_eeprom_memory_map_t { struct cam_eeprom_map_t pageen; struct cam_eeprom_map_t poll; struct cam_eeprom_map_t mem; + struct cam_eeprom_map_t mem_rl; uint32_t saddr; }; diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/Makefile b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/Makefile index f3c68f296ed5..ea7b61719a8a 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/Makefile +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/Makefile @@ -6,6 +6,7 @@ ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_core ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_cpas/include ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_req_mgr ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io ccflags-y += -I$(srctree)/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_utils diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index 9007e5642fdd..c2253c9d92f1 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -11,6 +11,10 @@ #include "cam_res_mgr_api.h" #include "cam_common_util.h" #include "cam_packet_util.h" +#ifdef CONFIG_CAMERA_FLASH_PWM +#include "cam_sensor_util.h" +#include "../cam_flash_pm6125_gpio/pm6125_flash_gpio.h" +#endif static int cam_flash_prepare(struct cam_flash_ctrl *flash_ctrl, bool regulator_enable) @@ -507,6 +511,10 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) { int rc = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + struct cam_hw_soc_info soc_info = flash_ctrl->soc_info; + struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private; +#endif if (!flash_ctrl) { CAM_ERR(CAM_FLASH, "Flash control Null"); @@ -530,6 +538,13 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) flash_ctrl->flash_state = CAM_FLASH_STATE_CONFIG; } +#ifdef CONFIG_CAMERA_FLASH_PWM + + cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 0); + cam_res_mgr_gpio_free(soc_info.dev, soc_private->flash_gpio_enable); + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND, CAMERA_SENSOR_FLASH_OP_OFF, 0); +#endif + return 0; } @@ -538,6 +553,10 @@ static int cam_flash_low( struct cam_flash_frame_setting *flash_data) { int i = 0, rc = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + struct cam_hw_soc_info soc_info = flash_ctrl->soc_info; + struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private; +#endif if (!flash_data) { CAM_ERR(CAM_FLASH, "Flash Data Null"); @@ -555,6 +574,28 @@ static int cam_flash_low( if (rc) CAM_ERR(CAM_FLASH, "Fire Torch failed: %d", rc); +#ifdef CONFIG_CAMERA_FLASH_PWM + CAM_DBG(CAM_FLASH, "Flash low Triggered flash_data->led_current_ma[0] = %u", flash_data->led_current_ma[0]); + rc = cam_res_mgr_gpio_request(soc_info.dev, soc_private->flash_gpio_enable, 0, "CUSTOM_GPIO1"); + if(rc) { + CAM_ERR(CAM_FLASH, "gpio %d request fails", soc_private->flash_gpio_enable); + return rc; + } + + cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 0); +#ifdef CONFIG_DEVON_CAMERA_FLASH + cam_res_mgr_gpio_request(soc_info.dev, DEVON_CAMERA_PWM_GPIO, 0, "torch_enable"); + cam_res_mgr_gpio_set_value(DEVON_CAMERA_PWM_GPIO, 1); + usleep_range(5000,6000); + cam_res_mgr_gpio_set_value(DEVON_CAMERA_PWM_GPIO, 0); + cam_res_mgr_gpio_free(soc_info.dev, DEVON_CAMERA_PWM_GPIO); +#else + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, CAMERA_SENSOR_FLASH_OP_FIRELOW, FLASH_FIRE_LOW_MAXCURRENT); + usleep_range(5000,6000); +#endif + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, CAMERA_SENSOR_FLASH_OP_FIRELOW, flash_data->led_current_ma[0]); +#endif + return rc; } @@ -563,6 +604,10 @@ static int cam_flash_high( struct cam_flash_frame_setting *flash_data) { int i = 0, rc = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + struct cam_hw_soc_info soc_info = flash_ctrl->soc_info; + struct cam_flash_private_soc *soc_private = (struct cam_flash_private_soc *)soc_info.soc_private; +#endif if (!flash_data) { CAM_ERR(CAM_FLASH, "Flash Data Null"); @@ -580,6 +625,18 @@ static int cam_flash_high( if (rc) CAM_ERR(CAM_FLASH, "Fire Flash Failed: %d", rc); +#ifdef CONFIG_CAMERA_FLASH_PWM + CAM_DBG(CAM_FLASH, "Flash high Triggered flash_data->led_current_ma[0] = %u", flash_data->led_current_ma[0]); + rc = cam_res_mgr_gpio_request(soc_info.dev, soc_private->flash_gpio_enable, 0, "CUSTOM_GPIO1"); + if(rc) { + CAM_ERR(CAM_FLASH, "gpio %d request fails", soc_private->flash_gpio_enable); + return rc; + } + + cam_res_mgr_gpio_set_value(soc_private->flash_gpio_enable, 1); + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_ACTIVE, CAMERA_SENSOR_FLASH_OP_FIREHIGH, flash_data->led_current_ma[0]); +#endif + return rc; } @@ -1219,12 +1276,23 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) return rc; } +#ifdef CONFIG_CAMERA_FLASH_PWM + if (fctrl->func_tbl.power_ops) { + rc = fctrl->func_tbl.power_ops(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + } +#else rc = fctrl->func_tbl.power_ops(fctrl, true); if (rc) { CAM_ERR(CAM_FLASH, "Enable Regulator Failed rc = %d", rc); return rc; } +#endif rc = fctrl->func_tbl.apply_setting(fctrl, 0); if (rc) { @@ -1501,13 +1569,23 @@ int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) fctrl->is_regulator_enabled = false; fctrl->nrt_info.cmn_attr.cmd_type = CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_INFO; - +#ifdef CONFIG_CAMERA_FLASH_PWM + if (fctrl->func_tbl.power_ops) { + rc = fctrl->func_tbl.power_ops(fctrl, true); + if (rc) { + CAM_ERR(CAM_FLASH, + "Enable Regulator Failed rc = %d", rc); + return rc; + } + } +#else rc = fctrl->func_tbl.power_ops(fctrl, true); if (rc) { CAM_ERR(CAM_FLASH, "Enable Regulator Failed rc = %d", rc); return rc; } +#endif fctrl->flash_state = CAM_FLASH_STATE_CONFIG; @@ -1943,10 +2021,19 @@ void cam_flash_shutdown(struct cam_flash_ctrl *fctrl) "LED OFF FAILED: %d", rc); } +#ifdef CONFIG_CAMERA_FLASH_PWM + if (fctrl->func_tbl.power_ops) { + rc = fctrl->func_tbl.power_ops(fctrl, false); + if (rc) + CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", + rc); + } +#else rc = fctrl->func_tbl.power_ops(fctrl, false); if (rc) CAM_ERR(CAM_FLASH, "Power Down Failed rc: %d", rc); +#endif } rc = cam_flash_release_dev(fctrl); @@ -1979,3 +2066,104 @@ int cam_flash_apply_request(struct cam_req_mgr_apply_request *apply) return rc; } + +#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE +static int cam_flash_construct_power_vio_setting( + struct cam_sensor_power_ctrl_t *power_info) +{ + int rc = 0; + + power_info->power_setting_size = 3; + power_info->power_setting = + kzalloc(sizeof(struct cam_sensor_power_setting)*3, + GFP_KERNEL); + if (!power_info->power_setting) + return -ENOMEM; + + power_info->power_setting[0].seq_type = SENSOR_VIO; + power_info->power_setting[0].seq_val = CAM_VIO; + power_info->power_setting[0].config_val = 1; + power_info->power_setting[0].delay = 2; + power_info->power_setting[1].seq_type = SENSOR_CUSTOM_GPIO1; + power_info->power_setting[1].seq_val = 0; + power_info->power_setting[1].config_val = 1; + power_info->power_setting[1].delay = 0; + power_info->power_setting[2].seq_type = SENSOR_CUSTOM_GPIO2; + power_info->power_setting[2].seq_val = 0; + power_info->power_setting[2].config_val = 1; + power_info->power_setting[2].delay = 0; + + power_info->power_down_setting_size = 3; + power_info->power_down_setting = + kzalloc(sizeof(struct cam_sensor_power_setting)*3, + GFP_KERNEL); + if (!power_info->power_down_setting) { + rc = -ENOMEM; + goto free_power_settings; + } + + power_info->power_down_setting[0].seq_type = SENSOR_CUSTOM_GPIO2; + power_info->power_down_setting[0].seq_val = 0; + power_info->power_down_setting[0].config_val = 0; + power_info->power_down_setting[1].seq_type = SENSOR_CUSTOM_GPIO1; + power_info->power_down_setting[1].seq_val = 0; + power_info->power_down_setting[1].config_val = 0; + power_info->power_down_setting[2].seq_type = SENSOR_VIO; + power_info->power_down_setting[2].seq_val = CAM_VIO; + power_info->power_down_setting[2].config_val = 0; + return rc; + +free_power_settings: + kfree(power_info->power_setting); + power_info->power_setting = NULL; + power_info->power_setting_size = 0; + return rc; +} + +int cam_flash_fill_vreg_setting(struct cam_flash_ctrl *fctrl) +{ + int rc = 0; + + rc = cam_flash_construct_power_vio_setting( + &fctrl->power_info); + if (rc) { + CAM_ERR(CAM_FLASH, "Failed Flash Power VIO Setting: rc=%d\n", rc); + return rc; + } + rc = msm_camera_fill_vreg_params(&fctrl->soc_info, + fctrl->power_info.power_setting, + fctrl->power_info.power_setting_size); + if(rc) + { + CAM_ERR(CAM_FLASH, "Failed Flash Fill Power Up Params: rc=%d\n", rc); + return rc; + } + rc = msm_camera_fill_vreg_params(&fctrl->soc_info, + fctrl->power_info.power_down_setting, + fctrl->power_info.power_down_setting_size); + if(rc) + { + CAM_ERR(CAM_FLASH, "Failed Flash Fill Power Down Params: rc=%d\n", rc); + return rc; + } + return rc; +} + +int cam_flash_fill_i2c_default_setting(struct cam_flash_ctrl *fctrl, uint32_t slave_addr) +{ + int rc = 0; + + struct cam_cmd_i2c_info i2c_info={0}; + i2c_info.slave_addr = slave_addr; + i2c_info.i2c_freq_mode = I2C_STANDARD_MODE; + + rc = cam_flash_slaveInfo_pkt_parser( + fctrl, (uint32_t *)&i2c_info, sizeof(struct cam_cmd_i2c_info)); + if (rc < 0) { + CAM_ERR(CAM_FLASH, + "Failed parsing slave info: rc: %d", + rc); + } + return rc; +} +#endif diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.h index c382809dbb92..f76a3e2c8aae 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.h +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_core.h @@ -6,6 +6,10 @@ #ifndef _CAM_FLASH_CORE_H_ #define _CAM_FLASH_CORE_H_ +#ifdef CONFIG_DEVON_CAMERA_FLASH +#define DEVON_CAMERA_PWM_GPIO 1165 +#endif + #include #include "cam_flash_dev.h" diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 947117c3342a..9b5dfb0e7870 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -8,6 +8,9 @@ #include "cam_flash_soc.h" #include "cam_flash_core.h" #include "cam_common_util.h" +#ifdef CONFIG_CAMERA_FLASH_PWM +#include "pm6125_flash_gpio.h" +#endif static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, void *arg, struct cam_flash_private_soc *soc_private) @@ -126,8 +129,15 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, CAM_WARN(CAM_FLASH, "Failed in destroying the device Handle"); +#ifdef CONFIG_CAMERA_FLASH_PWM + if (fctrl->func_tbl.power_ops) { + if (fctrl->func_tbl.power_ops(fctrl, false)) + CAM_WARN(CAM_FLASH, "Power Down Failed"); + } +#else if (fctrl->func_tbl.power_ops(fctrl, false)) CAM_WARN(CAM_FLASH, "Power Down Failed"); +#endif fctrl->streamoff_count = 0; fctrl->flash_state = CAM_FLASH_STATE_INIT; @@ -135,6 +145,10 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, } case CAM_QUERY_CAP: { struct cam_flash_query_cap_info flash_cap = {0}; +#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE + uint32_t flash_iic_supplier[3]; + uint32_t flashid=0; +#endif CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); flash_cap.slot_info = fctrl->soc_info.index; @@ -150,6 +164,40 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, flash_cap.max_current_torch[i] = soc_private->torch_max_current[i]; +#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE + rc = of_property_read_u32_array(fctrl->of_node, "distinguish-flash-supplier", + flash_iic_supplier, 3); + if (!rc) { + CAM_DBG(CAM_FLASH, "Distinguish IIC Flash Supplier dev:0x%x addr:0x%x data:0x%x", + flash_iic_supplier[0],flash_iic_supplier[1],flash_iic_supplier[2]); + if (cam_flash_fill_vreg_setting(fctrl)){ + CAM_ERR(CAM_FLASH, "Flash Fill Vreg Failed"); + goto release_mutex; + } + if (fctrl->func_tbl.power_ops(fctrl, true)){ + CAM_ERR(CAM_FLASH, "Power Up Failed"); + goto release_mutex; + } + if (cam_flash_fill_i2c_default_setting(fctrl, flash_iic_supplier[0])){ + CAM_ERR(CAM_FLASH, "Failed Flash Fill I2C Setting rc =%d",rc); + goto release_mutex; + } + rc = camera_io_dev_read(&(fctrl->io_master_info), + flash_iic_supplier[1],&flashid, + CAMERA_SENSOR_I2C_TYPE_BYTE, + CAMERA_SENSOR_I2C_TYPE_BYTE); + CAM_DBG(CAM_FLASH, "flashid=%d",flashid); + if ((!rc) && (flashid == flash_iic_supplier[2])) + flash_cap.flash_supplier = 1; + else + flash_cap.flash_supplier = 0; + if (fctrl->func_tbl.power_ops(fctrl, false)){ + CAM_ERR(CAM_FLASH, "Power Down Failed"); + goto release_mutex; + } + } +#endif + if (copy_to_user(u64_to_user_ptr(cmd->handle), &flash_cap, sizeof(struct cam_flash_query_cap_info))) { CAM_ERR(CAM_FLASH, "Failed Copy to User"); @@ -316,6 +364,10 @@ static int cam_flash_platform_remove(struct platform_device *pdev) { struct cam_flash_ctrl *fctrl; +#ifdef CONFIG_CAMERA_FLASH_PWM + pm6125_flash_control_remove_device(&pdev->dev); +#endif + fctrl = platform_get_drvdata(pdev); if (!fctrl) { CAM_ERR(CAM_FLASH, "Flash device is NULL"); @@ -328,6 +380,9 @@ static int cam_flash_platform_remove(struct platform_device *pdev) mutex_unlock(&fctrl->flash_mutex); cam_unregister_subdev(&(fctrl->v4l2_dev_str)); platform_set_drvdata(pdev, NULL); +#ifdef CONFIG_CAMERA_FLASH_PWM + dev_set_drvdata(&pdev->dev, NULL); +#endif v4l2_set_subdevdata(&fctrl->v4l2_dev_str.sd, NULL); kfree(fctrl); @@ -431,6 +486,9 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) fctrl->of_node = pdev->dev.of_node; platform_set_drvdata(pdev, fctrl); +#ifdef CONFIG_CAMERA_FLASH_PWM + dev_set_drvdata(&pdev->dev, fctrl); +#endif rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info); if (rc) { @@ -512,7 +570,11 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) /* PMIC Flash */ fctrl->func_tbl.parser = cam_flash_pmic_pkt_parser; fctrl->func_tbl.apply_setting = cam_flash_pmic_apply_setting; +#ifdef CONFIG_CAMERA_FLASH_PWM + fctrl->func_tbl.power_ops = NULL; +#else fctrl->func_tbl.power_ops = cam_flash_pmic_power_ops; +#endif fctrl->func_tbl.flush_req = cam_flash_pmic_flush_request; } @@ -536,6 +598,10 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) fctrl->flash_state = CAM_FLASH_STATE_INIT; CAM_DBG(CAM_FLASH, "Probe success"); +#ifdef CONFIG_CAMERA_FLASH_PWM + pm6125_flash_control_create_device(&pdev->dev); +#endif + return rc; free_cci_resource: diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 28f2fa14e167..98a7dcf5393c 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -146,6 +146,9 @@ struct cam_flash_private_soc { uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; bool is_wled_flash; uint32_t flash_type; +#ifdef CONFIG_CAMERA_FLASH_PWM + uint32_t flash_gpio_enable; +#endif }; struct cam_flash_func_tbl { @@ -232,5 +235,9 @@ int cam_flash_pmic_flush_request(struct cam_flash_ctrl *fctrl, enum cam_flash_flush_type, uint64_t req_id); void cam_flash_shutdown(struct cam_flash_ctrl *fctrl); int cam_flash_release_dev(struct cam_flash_ctrl *fctrl); +#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE +int cam_flash_fill_i2c_default_setting(struct cam_flash_ctrl *fctrl, uint32_t slave_addr); +int cam_flash_fill_vreg_setting(struct cam_flash_ctrl *fctrl); +#endif #endif /*_CAM_FLASH_DEV_H_*/ diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 4b3ee2f62e73..f7e48acf9601 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -16,6 +16,10 @@ static int32_t cam_get_source_node_info( { int32_t rc = 0; uint32_t count = 0, i = 0; +#ifdef CONFIG_CAMERA_FLASH_PWM + int16_t gpio_array_size = 0; + uint16_t *gpio_array = NULL; +#endif struct device_node *flash_src_node = NULL; struct device_node *torch_src_node = NULL; struct device_node *switch_src_node = NULL; @@ -29,6 +33,27 @@ static int32_t cam_get_source_node_info( CAM_ERR(CAM_FLASH, "flash-type read failed rc=%d", rc); soc_private->flash_type = CAM_FLASH_TYPE_PMIC; } +#ifdef CONFIG_CAMERA_FLASH_PWM + else if(soc_private->flash_type == CAM_FLASH_TYPE_GPIO) { + gpio_array_size = of_gpio_count(of_node); + if (gpio_array_size == 1){ + gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL); + if (!gpio_array) { + CAM_ERR(CAM_FLASH, "flash gpio array alloc fail"); + } else { + for (i = 0; i < gpio_array_size; i++) { + gpio_array[i] = of_get_gpio(of_node, i); + CAM_DBG(CAM_FLASH, "flash dts gpio_array[%d] = %d name is %s %s", i, gpio_array[i], of_node->name, of_node->full_name); + } + soc_private->flash_gpio_enable = gpio_array[0]; + CAM_DBG(CAM_FLASH, "flash gpio enable %d",soc_private->flash_gpio_enable); + kfree(gpio_array); + } + } else { + CAM_ERR(CAM_FLASH, "flash should have two gpio, first is enable in flash dts, second control by flash pm6125"); + } + } +#endif switch_src_node = of_parse_phandle(of_node, "switch-source", 0); if (!switch_src_node) { diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/Makefile b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/Makefile new file mode 100644 index 000000000000..018066333259 --- /dev/null +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +ccflags-y += -I$(srctree)/techpack/camera/include/uapi +ccflags-y += -I$(srctree)/techpack/camera/include/uapi +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_cci +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_flash +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_res_mgr +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_io +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils + +obj-$(CONFIG_CAMERA_FLASH_PWM) += pm6125_flash_gpio.o diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.c new file mode 100644 index 000000000000..53f11bf2d006 --- /dev/null +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.c @@ -0,0 +1,309 @@ +/* + *Copyright (C) 2021 Motorola Mobility LLC, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 "pm6125_flash_gpio.h" + +#ifdef CONFIG_CAMERA_FLASH_PWM +#include "cam_flash_dev.h" +#include "cam_flash_soc.h" +#include "cam_flash_core.h" +#include "cam_common_util.h" +#include "cam_res_mgr_api.h" +#endif + + +/***************************************************************************** + * Data Structure + *****************************************************************************/ + +struct pwm_device *pwm; +#ifdef CONFIG_CAMERA_FLASH_PWM +static unsigned int flashlight_enable = CAMERA_SENSOR_FLASH_STATUS_OFF; +static unsigned int flashlight_brightness = 0; +#endif + +/***************************************************************************** + * Function + *****************************************************************************/ + +void pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE s, enum camera_flash_opcode opcode, u64 flash_current){ + struct pwm_state pstate; + int rc = 0; + u64 real_current = 0; + + pwm_get_state(pwm, &pstate); + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Status duty_cycle = %u, period = %u\n", + pstate.duty_cycle, pstate.period); + pstate.period = PM6125_PWM_PERIOD; + switch (s) { + case PM6125_FLASH_GPIO_STATE_ACTIVE: + switch (opcode) + { + case CAMERA_SENSOR_FLASH_OP_FIRELOW: + real_current = (flash_current > FLASH_FIRE_LOW_MAXCURRENT?FLASH_FIRE_LOW_MAXCURRENT:flash_current); + pstate.duty_cycle = PM6125_PWM_PERIOD * real_current / FLASH_FIRE_LOW_MAXCURRENT; + break; + case CAMERA_SENSOR_FLASH_OP_FIREHIGH: + real_current = (flash_current > FLASH_FIRE_HIGH_MAXCURRENT?FLASH_FIRE_HIGH_MAXCURRENT:flash_current); + pstate.duty_cycle = PM6125_PWM_PERIOD * real_current / FLASH_FIRE_HIGH_MAXCURRENT; + break; + default: + pstate.duty_cycle = PM6125_PWM_PERIOD; + break; + } + + pstate.enabled = true; + rc = pwm_apply_state(pwm, &pstate); + + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Active duty_cycle = %u, period = %u, opcode = %u, real_current = %u\n", + pstate.duty_cycle, pstate.period, opcode, real_current); + break; + case PM6125_FLASH_GPIO_STATE_SUSPEND: + pstate.enabled = false; + rc = pwm_apply_state(pwm, &pstate); + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Suspend"); + break; + default: + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Failed to control PWM use a err state!\n"); + } + + if(rc < 0) { + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Apply PWM state fail, rc = %d", rc); + } +} + +#ifdef CONFIG_CAMERA_FLASH_PWM +static ssize_t flashlight_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", flashlight_enable); +} + +static ssize_t flashlight_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct cam_flash_ctrl *fctrl = dev_get_drvdata(dev); + struct cam_flash_private_soc *soc_private = fctrl->soc_info.soc_private; + unsigned long state_to_set; + ssize_t ret = -EINVAL; + + CAM_INFO(CAM_FLASH, "Flash Enable Command: %s", buf); + ret = kstrtoul(buf, 10, &state_to_set); + if (ret) + return ret; + + if (CAMERA_SENSOR_FLASH_STATUS_OFF != state_to_set) { + // enable flash + if (CAMERA_SENSOR_FLASH_STATUS_OFF == flashlight_enable) { + ret = cam_res_mgr_gpio_request( + fctrl->soc_info.dev, + soc_private->flash_gpio_enable, 0, + "CUSTOM_GPIO1"); + if (ret) { + CAM_ERR(CAM_FLASH, "gpio %d request fails", + soc_private->flash_gpio_enable); + return ret; + } + } + + flashlight_enable = state_to_set; + cam_res_mgr_gpio_set_value( + soc_private->flash_gpio_enable, + flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH); + if (flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_LOW) { + pm6125_flash_gpio_select_state( + PM6125_FLASH_GPIO_STATE_ACTIVE, + CAMERA_SENSOR_FLASH_OP_FIRELOW, + FLASH_FIRE_LOW_MAXCURRENT); + usleep_range(5000, 6000); + } + pm6125_flash_gpio_select_state( + PM6125_FLASH_GPIO_STATE_ACTIVE, + flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH ? + CAMERA_SENSOR_FLASH_OP_FIREHIGH : + CAMERA_SENSOR_FLASH_OP_FIRELOW, + (u64)flashlight_brightness); + } + else { + // disable flash + if (CAMERA_SENSOR_FLASH_STATUS_OFF != flashlight_enable) { + cam_res_mgr_gpio_set_value( + soc_private->flash_gpio_enable, 0); + cam_res_mgr_gpio_free(fctrl->soc_info.dev, + soc_private->flash_gpio_enable); + } + flashlight_enable = CAMERA_SENSOR_FLASH_STATUS_OFF; + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND, + CAMERA_SENSOR_FLASH_OP_OFF, 0); + } + return size; +} + +static ssize_t flashlight_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", flashlight_brightness); +} + +static ssize_t flashlight_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct cam_flash_ctrl *fctrl = dev_get_drvdata(dev); + struct cam_flash_private_soc *soc_private = fctrl->soc_info.soc_private; + unsigned long brightness_to_set; + ssize_t ret = -EINVAL; + + CAM_INFO(CAM_FLASH, "Flash Brightness Command: %s", buf); + ret = kstrtoul(buf, 10, &brightness_to_set); + if (ret) + return ret; + + flashlight_brightness = brightness_to_set; + + switch (flashlight_enable) + { + case CAMERA_SENSOR_FLASH_STATUS_LOW: // CAMERA_SENSOR_FLASH_OP_FIRELOW + case CAMERA_SENSOR_FLASH_STATUS_HIGH: // CAMERA_SENSOR_FLASH_OP_FIREHIGH + + CAM_INFO(CAM_FLASH, "Flash Mode %s: %d", + flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH ? + "High" : + "Low", + flashlight_brightness); + + // disable first + cam_res_mgr_gpio_set_value( + soc_private->flash_gpio_enable, 0); + cam_res_mgr_gpio_free(fctrl->soc_info.dev, + soc_private->flash_gpio_enable); + pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE_SUSPEND, CAMERA_SENSOR_FLASH_OP_OFF, 0); + + // get handle + ret = cam_res_mgr_gpio_request( + fctrl->soc_info.dev, + soc_private->flash_gpio_enable, 0, + "CUSTOM_GPIO1"); + if (ret) { + CAM_ERR(CAM_FLASH, "gpio %d request fails", + soc_private->flash_gpio_enable); + return ret; + } + + cam_res_mgr_gpio_set_value( + soc_private->flash_gpio_enable, + flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH); + if (flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_LOW) { + pm6125_flash_gpio_select_state( + PM6125_FLASH_GPIO_STATE_ACTIVE, + CAMERA_SENSOR_FLASH_OP_FIRELOW, + FLASH_FIRE_LOW_MAXCURRENT); + usleep_range(5000, 6000); + } + pm6125_flash_gpio_select_state( + PM6125_FLASH_GPIO_STATE_ACTIVE, + flashlight_enable == CAMERA_SENSOR_FLASH_STATUS_HIGH ? + CAMERA_SENSOR_FLASH_OP_FIREHIGH : + CAMERA_SENSOR_FLASH_OP_FIRELOW, + (u64)flashlight_brightness); + break; + default: + CAM_INFO(CAM_FLASH, "flashlight had not been enable yet."); + break; + } + + return size; +} +static DEVICE_ATTR_RW(flashlight_enable); +static DEVICE_ATTR_RW(flashlight_brightness); +struct device_attribute *flashlight_attributes[] = { + &dev_attr_flashlight_enable, + &dev_attr_flashlight_brightness, +}; + +int pm6125_flash_control_create_device(struct device* dev) +{ + int i, ret = 0; + for (i = 0; i < ARRAY_SIZE(flashlight_attributes); i++) { + ret = device_create_file(dev, + flashlight_attributes[i]); + if (ret) { + dev_err(dev, "failed: sysfs file %s\n", + flashlight_attributes[i]->attr.name); + pm6125_flash_control_remove_device(dev); + return ret; + } + } + return 0; +} + +int pm6125_flash_control_remove_device(struct device* dev) +{ + int i; + for (i = 0; i < ARRAY_SIZE(flashlight_attributes); i++) { + device_remove_file(dev, flashlight_attributes[i]); + } + return 0; +} +#endif + +static int pm6125_flash_pwm_probe(struct platform_device *pdev) +{ + int rc = 0; + pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(pwm)) + return PTR_ERR(pwm); + return rc; +} + +static const struct of_device_id gpio_of_match[] = { + { .compatible = "qualcomm,pm6125_flash_gpio", }, + {}, +}; + +static struct platform_driver pm6125_flash_gpio_platform_driver = { + .probe = pm6125_flash_pwm_probe, + .driver = { + .name = "PM6125_FLASH_GPIO_DTS", + .of_match_table = gpio_of_match, + }, +}; + +static int __init pm6125_flash_gpio_init_module(void) +{ + if (platform_driver_register(&pm6125_flash_gpio_platform_driver)) { + PM6125_FLASH_PRINT("[pm6125_flash_gpio]Failed to register pm6125_flash_gpio_platform_driver!\n"); + return -1; + } + return 0; +} + +static void __exit pm6125_flash_gpio_exit_module(void) +{ + platform_driver_unregister(&pm6125_flash_gpio_platform_driver); +} + +module_init(pm6125_flash_gpio_init_module); +module_exit(pm6125_flash_gpio_exit_module); +MODULE_AUTHOR("liyang "); +MODULE_DESCRIPTION("CONTROL PM6125 FLASH GPIO Driver"); +MODULE_LICENSE("GPL"); diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.h new file mode 100644 index 000000000000..69ea3cc007b9 --- /dev/null +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_flash_pm6125_gpio/pm6125_flash_gpio.h @@ -0,0 +1,42 @@ +#ifndef _PM6125_FLASH_GPIO_H_ +#define _PM6125_FLASH_GPIO_H_ + +#include "../cam_sensor_utils/cam_sensor_cmn_header.h" + +#define PM6125_FLASH_PRINT pr_info //printk + +/* DTS state */ +typedef enum { + PM6125_FLASH_GPIO_STATE_ACTIVE, + PM6125_FLASH_GPIO_STATE_SUSPEND, + PM6125_FLASH_GPIO_STATE_MAX, /* for array size */ +} PM6125_FLASH_GPIO_STATE; + +#ifdef CONFIG_CAMERA_FLASH_PWM +enum{ + CAMERA_SENSOR_FLASH_STATUS_OFF, + CAMERA_SENSOR_FLASH_STATUS_LOW, + CAMERA_SENSOR_FLASH_STATUS_HIGH +}; +#endif + +#ifdef CONFIG_DEVON_CAMERA_FLASH +#define PM6125_PWM_PERIOD 50000 +#define FLASH_FIRE_HIGH_MAXCURRENT 1750 +#define FLASH_FIRE_LOW_MAXCURRENT 285 +#else +#define PM6125_PWM_PERIOD 50000 +#define FLASH_FIRE_HIGH_MAXCURRENT 1200 +#define FLASH_FIRE_LOW_MAXCURRENT 150 +#endif + +/***************************************************************************** + * Function Prototype + *****************************************************************************/ +extern void pm6125_flash_gpio_select_state(PM6125_FLASH_GPIO_STATE s, enum camera_flash_opcode opcode, u64 flash_current); + +#ifdef CONFIG_CAMERA_FLASH_PWM +extern int pm6125_flash_control_create_device(struct device* dev); +extern int pm6125_flash_control_remove_device(struct device* dev); +#endif +#endif /* _PM6125_FLASH_GPIO_H_*/ diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 58a927426d86..05fbc612b76a 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -477,7 +477,11 @@ int cam_res_mgr_gpio_request(struct device *dev, uint gpio, } EXPORT_SYMBOL(cam_res_mgr_gpio_request); +#ifdef CONFIG_CAMERA_FLASH_PWM +void cam_res_mgr_gpio_free(struct device *dev, uint gpio) +#else static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) +#endif { bool found = false; bool need_free = true; @@ -535,6 +539,9 @@ static void cam_res_mgr_gpio_free(struct device *dev, uint gpio) if (need_free) gpio_free(gpio); } +#ifdef CONFIG_CAMERA_FLASH_PWM +EXPORT_SYMBOL(cam_res_mgr_gpio_free); +#endif void cam_res_mgr_gpio_free_arry(struct device *dev, const struct gpio *array, size_t num) diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h index e259ba7f2c78..ba8c8d27e220 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr_api.h @@ -100,6 +100,20 @@ int cam_res_mgr_shared_pinctrl_post_init(void); int cam_res_mgr_gpio_request(struct device *dev, unsigned int gpio, unsigned long flags, const char *label); +#ifdef CONFIG_CAMERA_FLASH_PWM +/** + * @brief: Free a GPIO + * + * Free the GPIO and release corresponding gpio_res. + * + * @dev : Pointer to the device + * @gpio : A GPIO number + * + * @return Status of operation. Negative in case of error. Zero otherwise. + */ +void cam_res_mgr_gpio_free(struct device *dev, uint gpio); +#endif + /** * @brief: Free a array GPIO * diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 8f454f1a24f8..98b46cc70c81 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -617,6 +617,10 @@ void cam_sensor_shutdown(struct cam_sensor_ctrl_t *s_ctrl) int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl) { int rc = 0; +#ifdef CONFIG_CAM_SENSOR_PROBE_RETRY + int retries = 5; + bool matched = false; +#endif uint32_t chipid = 0; struct cam_camera_slave_info *slave_info; @@ -627,7 +631,28 @@ int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl) slave_info); return -EINVAL; } +#ifdef CONFIG_CAM_SENSOR_PROBE_RETRY + while (retries-- && !matched) { + rc = camera_io_dev_read( + &(s_ctrl->io_master_info), + slave_info->sensor_id_reg_addr, + &chipid, + s_ctrl->sensor_probe_addr_type, + s_ctrl->sensor_probe_data_type); + CAM_INFO(CAM_SENSOR, "read id: 0x%x expected id 0x%x:", + chipid, slave_info->sensor_id); + + if (cam_sensor_id_by_mask(s_ctrl, chipid) == slave_info->sensor_id) + matched = true; + + if (!matched && !retries) { + CAM_ERR(CAM_SENSOR, "Failed read id: 0x%x expected id 0x%x:", + chipid, slave_info->sensor_id); + return -ENODEV; + } + } +#else rc = camera_io_dev_read( &(s_ctrl->io_master_info), slave_info->sensor_id_reg_addr, @@ -643,6 +668,7 @@ int cam_sensor_match_id(struct cam_sensor_ctrl_t *s_ctrl) chipid, slave_info->sensor_id); return -ENODEV; } +#endif return rc; } diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h b/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h index def8be55bc8b..b7087eca8355 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h @@ -18,7 +18,7 @@ #define I2C_COMPARE_MATCH 0 #define I2C_COMPARE_MISMATCH 1 -#define I2C_REG_DATA_MAX (8*1024) +#define I2C_REG_DATA_MAX (20*1024) /** * @client: CCI client structure diff --git a/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c index 80c8cc8d9a48..3c020412a728 100644 --- a/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c +++ b/techpack/camera-bengal/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c @@ -7,7 +7,7 @@ #include "cam_sensor_i2c.h" #include "cam_sensor_io.h" -#define I2C_REG_DATA_MAX (8*1024) +#define I2C_REG_DATA_MAX (20*1024) #define I2C_REG_MAX_BUF_SIZE 8 static int32_t cam_qup_i2c_rxdata( diff --git a/techpack/camera-bengal/include/uapi/media/cam_req_mgr.h b/techpack/camera-bengal/include/uapi/media/cam_req_mgr.h index ebec0b04b916..5b877c882171 100644 --- a/techpack/camera-bengal/include/uapi/media/cam_req_mgr.h +++ b/techpack/camera-bengal/include/uapi/media/cam_req_mgr.h @@ -32,6 +32,9 @@ #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) +#ifdef CONFIG_AF_NOISE_ELIMINATION +#define CAM_MOT_ACTUATOR_TYPE (CAM_DEVICE_TYPE_BASE + 17) +#endif /* cam_req_mgr hdl info */ #define CAM_REQ_MGR_HDL_IDX_POS 8 diff --git a/techpack/camera-bengal/include/uapi/media/cam_sensor.h b/techpack/camera-bengal/include/uapi/media/cam_sensor.h index 9d16af961904..879307e22018 100644 --- a/techpack/camera-bengal/include/uapi/media/cam_sensor.h +++ b/techpack/camera-bengal/include/uapi/media/cam_sensor.h @@ -483,6 +483,9 @@ struct cam_flash_query_cap_info { uint32_t max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t flash_type; +#ifdef CONFIG_CAMERA_FLASH_IIC_COMPATIBLE + uint32_t flash_supplier; +#endif } __attribute__ ((packed)); #endif