Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 893a5afd authored by Sureshnaidu Laveti's avatar Sureshnaidu Laveti Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarSureshnaidu Laveti <lsuresh@codeaurora.org>
parent 1af3ec8d
Loading
Loading
Loading
Loading
+109 −1
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
/* 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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
// 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
Original line number Diff line number Diff line
/* 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,