From 893a5afdbfcb8028d712da02f07b17d28261b63a Mon Sep 17 00:00:00 2001 From: Sureshnaidu Laveti Date: Wed, 15 Jul 2020 14:22:58 -0700 Subject: [PATCH] msm: camera: sensor: OIS lens position data infrastructure Add support to read OIS lens position data and current Qtimer value. Add support to write qtimer time stamp to OIS FW. CRs-Fixed: 2721489 Change-Id: I7a4f4d342ff41c72db892ea706d0cfd6d667d96d Signed-off-by: Sureshnaidu Laveti --- .../cam_sensor_module/cam_ois/cam_ois_core.c | 110 +++++++++++++++++- .../cam_sensor_module/cam_ois/cam_ois_dev.h | 4 +- .../cam_sensor_utils/cam_sensor_cmn_header.h | 3 +- .../cam_sensor_utils/cam_sensor_util.c | 84 ++++++++++++- .../cam_sensor_utils/cam_sensor_util.h | 16 ++- 5 files changed, 212 insertions(+), 5 deletions(-) diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 3ee402e266..fcd7a0e793 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -198,6 +198,49 @@ static int cam_ois_power_down(struct cam_ois_ctrl_t *o_ctrl) return rc; } +static int cam_ois_update_time(struct i2c_settings_array *i2c_set) +{ + struct i2c_settings_list *i2c_list; + int32_t rc = 0; + uint32_t size = 0; + uint32_t i = 0; + uint64_t qtime_ns = 0; + + if (i2c_set == NULL) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return -EINVAL; + } + + rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed to get current qtimer value: %d", + rc); + return rc; + } + + list_for_each_entry(i2c_list, + &(i2c_set->list_head), list) { + if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + size = i2c_list->i2c_settings.size; + /* qtimer is 8 bytes so validate here*/ + if (size < 8) { + CAM_ERR(CAM_OIS, "Invalid write time settings"); + return -EINVAL; + } + for (i = 0; i < size; i++) { + CAM_DBG(CAM_OIS, "time: reg_data[%d]: 0x%x", + i, (qtime_ns & 0xFF)); + i2c_list->i2c_settings.reg_setting[i].reg_data = + (qtime_ns & 0xFF); + qtime_ns >>= 8; + } + } + } + + return rc; +} + static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, struct i2c_settings_array *i2c_set) { @@ -225,6 +268,17 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, "Failed in Applying i2c wrt settings"); return rc; } + } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { + rc = camera_io_dev_write_continuous( + &(o_ctrl->io_master_info), + &(i2c_list->i2c_settings), + 0); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed to seq write I2C settings: %d", + rc); + return rc; + } } else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) { size = i2c_list->i2c_settings.size; for (i = 0; i < size; i++) { @@ -680,6 +734,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) &csl_packet->payload + csl_packet->io_configs_offset); + /* validate read data io config */ if (io_cfg == NULL) { CAM_ERR(CAM_OIS, "I/O config is invalid(NULL)"); rc = -EINVAL; @@ -693,7 +748,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) i2c_read_settings.request_id = 0; rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, &i2c_read_settings, - cmd_desc, 1, io_cfg); + cmd_desc, 1, &io_cfg[0]); if (rc < 0) { CAM_ERR(CAM_OIS, "OIS read pkt parsing failed: %d", rc); return rc; @@ -708,6 +763,17 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) return rc; } + if (csl_packet->num_io_configs > 1) { + rc = cam_sensor_util_write_qtimer_to_io_buffer( + &io_cfg[1]); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "write qtimer failed rc: %d", rc); + delete_request(&i2c_read_settings); + return rc; + } + } + rc = delete_request(&i2c_read_settings); if (rc < 0) { CAM_ERR(CAM_OIS, @@ -716,6 +782,48 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } break; } + case CAM_OIS_PACKET_OPCODE_WRITE_TIME: { + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { + rc = -EINVAL; + CAM_ERR(CAM_OIS, + "Not in right state to write time to OIS: %d", + o_ctrl->cam_ois_state); + return rc; + } + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + i2c_reg_settings = &(o_ctrl->i2c_time_data); + i2c_reg_settings->is_settings_valid = 1; + i2c_reg_settings->request_id = 0; + rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1, NULL); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc); + return rc; + } + + rc = cam_ois_update_time(i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, "Cannot update time"); + return rc; + } + + rc = cam_ois_apply_settings(o_ctrl, i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, "Cannot apply mode settings"); + return rc; + } + + rc = delete_request(i2c_reg_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Fail deleting Mode data: rc: %d", rc); + return rc; + } + break; + } default: CAM_ERR(CAM_OIS, "Invalid Opcode: %d", (csl_packet->header.op_code & 0xFFFFFF)); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index eb0a69d112..ddb585bc4f 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_OIS_DEV_H_ #define _CAM_OIS_DEV_H_ @@ -94,6 +94,7 @@ struct cam_ois_intf_params { * @bridge_intf : bridge interface params * @i2c_init_data : ois i2c init settings * @i2c_mode_data : ois i2c mode settings + * @i2c_time_data : ois i2c time write settings * @i2c_calib_data : ois i2c calib settings * @ois_device_type : ois device type * @cam_ois_state : ois_device_state @@ -116,6 +117,7 @@ struct cam_ois_ctrl_t { struct i2c_settings_array i2c_init_data; struct i2c_settings_array i2c_calib_data; struct i2c_settings_array i2c_mode_data; + struct i2c_settings_array i2c_time_data; enum msm_camera_device_type_t ois_device_type; enum cam_ois_state cam_ois_state; char ois_name[32]; diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index e18b4bb1c8..25ab72ae60 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -173,7 +173,8 @@ enum cam_eeprom_packet_opcodes { enum cam_ois_packet_opcodes { CAM_OIS_PACKET_OPCODE_INIT, CAM_OIS_PACKET_OPCODE_OIS_CONTROL, - CAM_OIS_PACKET_OPCODE_READ + CAM_OIS_PACKET_OPCODE_READ, + CAM_OIS_PACKET_OPCODE_WRITE_TIME }; enum msm_bus_perf_setting { diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 5903bc1ff5..7334c9accb 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include +#include #include "cam_sensor_util.h" #include "cam_mem_mgr.h" #include "cam_res_mgr_api.h" @@ -40,6 +41,29 @@ static struct i2c_settings_list* return tmp; } +int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns) +{ + uint64_t ticks = 0; + int32_t rc = 0; + + ticks = arch_timer_read_counter(); + if (ticks == 0) { + CAM_ERR(CAM_SENSOR, "qtimer returned 0, rc:%d", rc); + return -EINVAL; + } + + if (qtime_ns != NULL) { + *qtime_ns = mul_u64_u32_div(ticks, + QTIMER_MUL_FACTOR, QTIMER_DIV_FACTOR); + CAM_DBG(CAM_SENSOR, "Qtimer time: 0x%x", *qtime_ns); + } else { + CAM_ERR(CAM_SENSOR, "NULL pointer passed"); + return -EINVAL; + } + + return rc; +} + int32_t delete_request(struct i2c_settings_array *i2c_array) { struct i2c_settings_list *i2c_list = NULL, *i2c_next = NULL; @@ -277,6 +301,64 @@ static int32_t cam_sensor_get_io_buffer( return rc; } +int32_t cam_sensor_util_write_qtimer_to_io_buffer( + struct cam_buf_io_cfg *io_cfg) +{ + uintptr_t buf_addr = 0x0, target_buf = 0x0; + size_t buf_size = 0, target_size = 0; + int32_t rc = 0; + uint64_t qtime_ns = 0; + + if (io_cfg == NULL) { + CAM_ERR(CAM_SENSOR, + "Invalid args, io buf is NULL"); + return -EINVAL; + } + + if (io_cfg->direction == CAM_BUF_OUTPUT) { + rc = cam_mem_get_cpu_buf(io_cfg->mem_handle[0], + &buf_addr, &buf_size); + if ((rc < 0) || (!buf_addr)) { + CAM_ERR(CAM_SENSOR, + "invalid buffer, rc: %d, buf_addr: %pK", + rc, buf_addr); + return -EINVAL; + } + CAM_DBG(CAM_SENSOR, + "buf_addr: %pK, buf_size: %zu, offsetsize: %d", + (void *)buf_addr, buf_size, io_cfg->offsets[0]); + if (io_cfg->offsets[0] >= buf_size) { + CAM_ERR(CAM_SENSOR, + "invalid size:io_cfg->offsets[0]: %d, buf_size: %d", + io_cfg->offsets[0], buf_size); + return -EINVAL; + } + + target_buf = buf_addr + io_cfg->offsets[0]; + target_size = buf_size - io_cfg->offsets[0]; + + if (target_size < sizeof(uint64_t)) { + CAM_ERR(CAM_SENSOR, + "not enough size for qtimer, target_size:%d", + target_size); + return -EINVAL; + } + + rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, "failed to get qtimer rc:%d"); + return rc; + } + + memcpy((void *)target_buf, &qtime_ns, sizeof(uint64_t)); + } else { + CAM_ERR(CAM_SENSOR, "Invalid direction: %d", + io_cfg->direction); + rc = -EINVAL; + } + return rc; +} + static int32_t cam_sensor_handle_random_read( struct cam_cmd_i2c_random_rd *cmd_i2c_random_rd, struct i2c_settings_array *i2c_reg_settings, diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h index 3600b5636c..690b7189e7 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_SENSOR_UTIL_H_ @@ -21,6 +21,15 @@ #define INVALID_VREG 100 +/* + * Constant Factors needed to change QTimer ticks to nanoseconds + * QTimer Freq = 19.2 MHz + * Time(us) = ticks/19.2 + * Time(ns) = ticks/19.2 * 1000 + */ +#define QTIMER_MUL_FACTOR 10000 +#define QTIMER_DIV_FACTOR 192 + int cam_get_dt_power_setting_data(struct device_node *of_node, struct cam_hw_soc_info *soc_info, struct cam_sensor_power_ctrl_t *power_info); @@ -28,6 +37,11 @@ int cam_get_dt_power_setting_data(struct device_node *of_node, int msm_camera_pinctrl_init (struct msm_pinctrl_info *sensor_pctrl, struct device *dev); +int32_t cam_sensor_util_get_current_qtimer_ns(uint64_t *qtime_ns); + +int32_t cam_sensor_util_write_qtimer_to_io_buffer( + struct cam_buf_io_cfg *io_cfg); + int cam_sensor_i2c_command_parser(struct camera_io_master *io_master, struct i2c_settings_array *i2c_reg_settings, struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers,