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

Commit 9591ccfd authored by Zhaohong Chen's avatar Zhaohong Chen Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: sensor: Add support for multiple slave address



Add support for program multiple slave addresses
in a i2c sensor sequence.

CRs-Fixed: 2660303
Change-Id: Idbb1c6c77ed0494c3e22cb14055ea7a613772c5a
Signed-off-by: default avatarZhaohong Chen <zhaohong@codeaurora.org>
parent a908dbc7
Loading
Loading
Loading
Loading
+124 −44
Original line number Diff line number Diff line
@@ -278,12 +278,99 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
	return rc;
}

static int32_t cam_sensor_restore_slave_info(struct cam_sensor_ctrl_t *s_ctrl)
{
	int32_t rc = 0;

	switch (s_ctrl->io_master_info.master_type) {
	case CCI_MASTER:
		s_ctrl->io_master_info.cci_client->sid =
			(s_ctrl->sensordata->slave_info.sensor_slave_addr >> 1);
		s_ctrl->io_master_info.cci_client->i2c_freq_mode =
			s_ctrl->sensordata->slave_info.i2c_freq_mode;
		break;

	case I2C_MASTER:
		s_ctrl->io_master_info.client->addr =
			 s_ctrl->sensordata->slave_info.sensor_slave_addr;
		break;

	case SPI_MASTER:
		break;

	default:
		CAM_ERR(CAM_SENSOR, "Invalid master type: %d",
				s_ctrl->io_master_info.master_type);
		rc = -EINVAL;
		break;
	}

	return rc;
}

static int32_t cam_sensor_update_i2c_info(struct cam_cmd_i2c_info *i2c_info,
	struct cam_sensor_ctrl_t *s_ctrl,
	bool isInit)
{
	int32_t rc = 0;
	struct cam_sensor_cci_client   *cci_client = NULL;

	switch (s_ctrl->io_master_info.master_type) {
	case CCI_MASTER:
		cci_client = s_ctrl->io_master_info.cci_client;
		if (!cci_client) {
			CAM_ERR(CAM_SENSOR, "failed: cci_client %pK",
				cci_client);
			return -EINVAL;
		}
		cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;
		cci_client->sid = i2c_info->slave_addr >> 1;
		cci_client->retries = 3;
		cci_client->id_map = 0;
		cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
		CAM_DBG(CAM_SENSOR, " Master: %d sid: 0x%x freq_mode: %d",
			cci_client->cci_i2c_master, i2c_info->slave_addr,
			i2c_info->i2c_freq_mode);
		break;

	case I2C_MASTER:
		s_ctrl->io_master_info.client->addr = i2c_info->slave_addr;
		break;

	case SPI_MASTER:
		break;

	default:
		CAM_ERR(CAM_SENSOR, "Invalid master type: %d",
			s_ctrl->io_master_info.master_type);
		rc = -EINVAL;
		break;
	}

	if (isInit) {
		s_ctrl->sensordata->slave_info.sensor_slave_addr =
			i2c_info->slave_addr;
		s_ctrl->sensordata->slave_info.i2c_freq_mode =
			i2c_info->i2c_freq_mode;
	}

	return rc;
}

static int32_t cam_sensor_i2c_modes_util(
	struct camera_io_master *io_master_info,
	struct cam_sensor_ctrl_t *s_ctrl,
	struct i2c_settings_list *i2c_list)
{
	int32_t rc = 0;
	uint32_t i, size;
	struct camera_io_master *io_master_info;

	if (s_ctrl == NULL) {
		CAM_ERR(CAM_SENSOR, "Invalid args");
		return -EINVAL;
	}

	io_master_info = &s_ctrl->io_master_info;

	if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_RANDOM) {
		rc = camera_io_dev_write(io_master_info,
@@ -333,39 +420,20 @@ static int32_t cam_sensor_i2c_modes_util(
				return rc;
			}
		}
	} else if (i2c_list->op_code == CAM_SENSOR_I2C_SET_I2C_INFO) {
		rc = cam_sensor_update_i2c_info(&i2c_list->slave_info,
			s_ctrl,
			false);
	} else if ((i2c_list->op_code == CAM_SENSOR_I2C_READ_RANDOM) ||
		(i2c_list->op_code == CAM_SENSOR_I2C_READ_SEQ)) {
		rc = cam_sensor_i2c_read_data(
			&s_ctrl->i2c_data.read_settings,
			&s_ctrl->io_master_info);
	}

	return rc;
}

int32_t cam_sensor_update_i2c_info(struct cam_cmd_i2c_info *i2c_info,
	struct cam_sensor_ctrl_t *s_ctrl)
{
	int32_t rc = 0;
	struct cam_sensor_cci_client   *cci_client = NULL;

	if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
		cci_client = s_ctrl->io_master_info.cci_client;
		if (!cci_client) {
			CAM_ERR(CAM_SENSOR, "failed: cci_client %pK",
				cci_client);
			return -EINVAL;
		}
		cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;
		cci_client->sid = i2c_info->slave_addr >> 1;
		cci_client->retries = 3;
		cci_client->id_map = 0;
		cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
		CAM_DBG(CAM_SENSOR, " Master: %d sid: %d freq_mode: %d",
			cci_client->cci_i2c_master, i2c_info->slave_addr,
			i2c_info->i2c_freq_mode);
	}

	s_ctrl->sensordata->slave_info.sensor_slave_addr =
		i2c_info->slave_addr;
	return rc;
}

int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info,
	struct cam_sensor_ctrl_t *s_ctrl)
{
@@ -411,7 +479,7 @@ int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
			return -EINVAL;
		}
		i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
		rc = cam_sensor_update_i2c_info(i2c_info, s_ctrl);
		rc = cam_sensor_update_i2c_info(i2c_info, s_ctrl, true);
		if (rc < 0) {
			CAM_ERR(CAM_SENSOR, "Failed in Updating the i2c Info");
			return rc;
@@ -989,12 +1057,13 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
		}

		if (s_ctrl->i2c_data.read_settings.is_settings_valid) {
			rc = cam_sensor_i2c_read_data(
				&s_ctrl->i2c_data.read_settings,
				&s_ctrl->io_master_info);
			rc = cam_sensor_apply_settings(s_ctrl, 0,
				CAM_SENSOR_PACKET_OPCODE_SENSOR_READ);
			if (rc < 0) {
				CAM_ERR(CAM_SENSOR, "cannot read data: %d", rc);
				delete_request(&s_ctrl->i2c_data.read_settings);
				CAM_ERR(CAM_SENSOR,
					"cannot apply read settings");
				delete_request(
					&s_ctrl->i2c_data.read_settings);
				goto release_mutex;
			}
			rc = delete_request(
@@ -1005,6 +1074,11 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
				goto release_mutex;
			}
		}

		CAM_DBG(CAM_SENSOR,
			"CAM_CONFIG_DEV done sensor_id:0x%x,sensor_slave_addr:0x%x",
			s_ctrl->sensordata->slave_info.sensor_id,
			s_ctrl->sensordata->slave_info.sensor_slave_addr);
	}
		break;
	default:
@@ -1101,8 +1175,7 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
	int rc;
	struct cam_sensor_power_ctrl_t *power_info;
	struct cam_camera_slave_info *slave_info;
	struct cam_hw_soc_info *soc_info =
		&s_ctrl->soc_info;
	struct cam_hw_soc_info *soc_info;

	if (!s_ctrl) {
		CAM_ERR(CAM_SENSOR, "failed: %pK", s_ctrl);
@@ -1117,6 +1190,8 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
		return -EINVAL;
	}

	soc_info = &s_ctrl->soc_info;

	if (s_ctrl->bob_pwm_switch) {
		rc = cam_sensor_bob_pwm_mode_switch(soc_info,
			s_ctrl->bob_reg_index, true);
@@ -1205,6 +1280,10 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
			i2c_set = &s_ctrl->i2c_data.streamoff_settings;
			break;
		}
		case CAM_SENSOR_PACKET_OPCODE_SENSOR_READ: {
			i2c_set = &s_ctrl->i2c_data.read_settings;
			break;
		}
		case CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE:
		case CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE:
		default:
@@ -1213,14 +1292,13 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
		if (i2c_set->is_settings_valid == 1) {
			list_for_each_entry(i2c_list,
				&(i2c_set->list_head), list) {
				rc = cam_sensor_i2c_modes_util(
					&(s_ctrl->io_master_info),
				rc = cam_sensor_i2c_modes_util(s_ctrl,
					i2c_list);
				if (rc < 0) {
					CAM_ERR(CAM_SENSOR,
						"Failed to apply settings: %d",
						rc);
					return rc;
					goto EXIT_RESTORE;
				}
			}
		}
@@ -1231,14 +1309,13 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
			i2c_set->request_id == req_id) {
			list_for_each_entry(i2c_list,
				&(i2c_set->list_head), list) {
				rc = cam_sensor_i2c_modes_util(
					&(s_ctrl->io_master_info),
				rc = cam_sensor_i2c_modes_util(s_ctrl,
					i2c_list);
				if (rc < 0) {
					CAM_ERR(CAM_SENSOR,
						"Failed to apply settings: %d",
						rc);
					return rc;
					goto EXIT_RESTORE;
				}
			}
		} else {
@@ -1268,7 +1345,7 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
		}

		if (!del_req_id)
			return rc;
			goto EXIT_RESTORE;

		CAM_DBG(CAM_SENSOR, "top: %llu, del_req_id:%llu",
			top, del_req_id);
@@ -1289,6 +1366,9 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
		}
	}

EXIT_RESTORE:
	(void)cam_sensor_restore_slave_info(s_ctrl);

	return rc;
}

+5 −2
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_CMN_HEADER_
@@ -223,7 +223,8 @@ enum cam_sensor_i2c_cmd_type {
	CAM_SENSOR_I2C_WRITE_SEQ,
	CAM_SENSOR_I2C_READ_RANDOM,
	CAM_SENSOR_I2C_READ_SEQ,
	CAM_SENSOR_I2C_POLL
	CAM_SENSOR_I2C_POLL,
	CAM_SENSOR_I2C_SET_I2C_INFO
};

struct common_header {
@@ -288,6 +289,7 @@ struct cam_sensor_i2c_seq_reg {
struct i2c_settings_list {
	struct cam_sensor_i2c_reg_setting i2c_settings;
	struct cam_sensor_i2c_seq_reg seq_settings;
	struct cam_cmd_i2c_info slave_info;
	enum cam_sensor_i2c_cmd_type op_code;
	struct list_head list;
};
@@ -323,6 +325,7 @@ struct cam_camera_slave_info {
	uint16_t sensor_id_reg_addr;
	uint16_t sensor_id;
	uint16_t sensor_id_mask;
	uint8_t  i2c_freq_mode;
};

struct msm_sensor_init_params {
+19 −26
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>
@@ -368,36 +368,23 @@ static int32_t cam_sensor_handle_continuous_read(
}

static int cam_sensor_handle_slave_info(
	struct camera_io_master *io_master,
	uint32_t *cmd_buf)
	uint32_t *cmd_buf,
	struct i2c_settings_array *i2c_reg_settings,
	struct list_head **list_ptr)
{
	int rc = 0;
	struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
	struct i2c_settings_list  *i2c_list;

	if (io_master == NULL || cmd_buf == NULL) {
		CAM_ERR(CAM_SENSOR, "Invalid args");
		return -EINVAL;
	i2c_list =
		cam_sensor_get_i2c_ptr(i2c_reg_settings, 1);
	if (!i2c_list || !i2c_list->i2c_settings.reg_setting) {
		CAM_ERR(CAM_SENSOR, "Failed in allocating mem for list");
		return -ENOMEM;
	}

	switch (io_master->master_type) {
	case CCI_MASTER:
		io_master->cci_client->sid = (i2c_info->slave_addr >> 1);
		io_master->cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
		break;

	case I2C_MASTER:
		io_master->client->addr = i2c_info->slave_addr;
		break;

	case SPI_MASTER:
		break;

	default:
		CAM_ERR(CAM_SENSOR, "Invalid master type: %d",
			io_master->master_type);
		rc = -EINVAL;
		break;
	}
	i2c_list->op_code = CAM_SENSOR_I2C_SET_I2C_INFO;
	i2c_list->slave_info = *i2c_info;

	return rc;
}
@@ -617,7 +604,7 @@ int cam_sensor_i2c_command_parser(
					goto end;
				}
				rc = cam_sensor_handle_slave_info(
					io_master, cmd_buf);
					cmd_buf, i2c_reg_settings, &list);
				if (rc) {
					CAM_ERR(CAM_SENSOR,
					"Handle slave info failed with rc: %d",
@@ -809,6 +796,12 @@ int32_t cam_sensor_i2c_read_data(

	list_for_each_entry(i2c_list,
		&(i2c_settings->list_head), list) {
		if (i2c_list->op_code == CAM_SENSOR_I2C_SET_I2C_INFO) {
			CAM_DBG(CAM_SENSOR,
				"CAM_SENSOR_I2C_SET_I2C_INFO continue");
			continue;
		}

		read_buff = i2c_list->i2c_settings.read_buff;
		buff_length = i2c_list->i2c_settings.read_buff_len;
		if ((read_buff == NULL) || (buff_length == 0)) {