소스 검색

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 <[email protected]>
Sureshnaidu Laveti 5 년 전
부모
커밋
893a5afdbf

+ 109 - 1
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));

+ 3 - 1
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];

+ 2 - 1
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 {

+ 83 - 1
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 <linux/kernel.h>
+#include <clocksource/arm_arch_timer.h>
 #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,

+ 15 - 1
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,