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

Commit fe014bb4 authored by Rajesh Bondugula's avatar Rajesh Bondugula Committed by Matt Wagantall
Browse files

msm: camera: sensor: Add client specific I2C frequency



Each slave can have a different I2C frequency.
The frequency is configured for each
write / read if changed.

Change-Id: I6ae71686d41e85c8686d6871d7870b178da5905d
Signed-off-by: default avatarRajesh Bondugula <rajeshb@codeaurora.org>
Signed-off-by: default avatarXu Han <hanxu@codeaurora.org>
parent 8f9e9539
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1178,6 +1178,8 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl,
		cci_client->retries = 3;
		cci_client->id_map = 0;
		cci_client->cci_i2c_master = a_ctrl->cci_master;
		cci_client->i2c_freq_mode =
			set_info->actuator_params.i2c_freq_mode;
	} else {
		a_ctrl->i2c_client.client->addr =
			set_info->actuator_params.i2c_addr;
@@ -1474,6 +1476,10 @@ static long msm_actuator_subdev_do_ioctl(
			actuator_data.cfg.set_info.actuator_params.i2c_addr =
				u32->cfg.set_info.actuator_params.i2c_addr;

			actuator_data.cfg.set_info.actuator_params.
				i2c_freq_mode =
				u32->cfg.set_info.actuator_params.i2c_freq_mode;

			actuator_data.cfg.set_info.actuator_params
				.i2c_addr_type =
				u32->cfg.set_info.actuator_params.i2c_addr_type;
+27 −10
Original line number Diff line number Diff line
@@ -52,17 +52,22 @@ static struct v4l2_subdev *g_cci_subdev;

static struct msm_cam_clk_info cci_clk_info[CCI_NUM_CLK_CASES][CCI_NUM_CLK_MAX];

static void msm_cci_set_clk_param(struct cci_device *cci_dev,
static int32_t msm_cci_set_clk_param(struct cci_device *cci_dev,
	struct msm_camera_cci_ctrl *c_ctrl)
{
	struct msm_cci_clk_params_t *clk_params = NULL;
	enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
	enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;

	if (cci_dev->master_clk_init[master])
		return;
	clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];

	if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) {
		pr_err("%s:%d invalid i2c_freq_mode = %d",
			__func__, __LINE__, i2c_freq_mode);
		return -EINVAL;
	}
	if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode)
		return 0;
	if (MASTER_0 == master) {
		msm_camera_io_w_mb(clk_params->hw_thigh << 16 |
			clk_params->hw_tlow,
@@ -94,8 +99,8 @@ static void msm_cci_set_clk_param(struct cci_device *cci_dev,
			clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
			cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR);
	}
	cci_dev->master_clk_init[master] = 1;
	return;
	cci_dev->i2c_freq_mode[master] = i2c_freq_mode;
	return 0;
}

static void msm_cci_flush_queue(struct cci_device *cci_dev,
@@ -717,6 +722,14 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd,
	read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);

	/* Set the I2C Frequency */
	rc = msm_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		pr_err("%s:%d msm_cci_set_clk_param failed rc = %d\n",
			__func__, __LINE__, rc);
		return rc;
	}

	/*
	 * Call validate queue to make sure queue is empty before starting.
	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -937,6 +950,13 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd,
		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
		c_ctrl->cci_info->id_map);

	/* Set the I2C Frequency */
	rc = msm_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		pr_err("%s:%d msm_cci_set_clk_param failed rc = %d\n",
			__func__, __LINE__, rc);
		return rc;
	}
	/*
	 * Call validate queue to make sure queue is empty before starting.
	 * If this call fails, don't proceed with i2c_write call. This is to
@@ -1174,7 +1194,6 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd,
		CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
		master = c_ctrl->cci_info->cci_i2c_master;
		CDBG("%s:%d master %d\n", __func__, __LINE__, master);
		msm_cci_set_clk_param(cci_dev, c_ctrl);
		if (master < MASTER_MAX && master >= 0) {
			mutex_lock(&cci_dev->cci_master_info[master].mutex);
			flush_workqueue(cci_dev->write_wq[master]);
@@ -1275,8 +1294,7 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd,
		goto reset_complete_failed;
	}
	for (i = 0; i < MASTER_MAX; i++)
		cci_dev->master_clk_init[i] = 0;
	msm_cci_set_clk_param(cci_dev, c_ctrl);
		cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES;
	msm_camera_io_w_mb(CCI_IRQ_MASK_0_RMSK,
		cci_dev->base + CCI_IRQ_MASK_0_ADDR);
	msm_camera_io_w_mb(CCI_IRQ_MASK_0_RMSK,
@@ -1367,8 +1385,7 @@ static int32_t msm_cci_release(struct v4l2_subdev *sd)
	msm_camera_request_gpio_table(cci_dev->cci_gpio_tbl,
		cci_dev->cci_gpio_tbl_size, 0);
	for (i = 0; i < MASTER_MAX; i++)
		cci_dev->master_clk_init[i] = 0;

		cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES;
	cci_dev->cci_state = CCI_STATE_DISABLED;
	cci_dev->cycles_per_us = 0;
	cci_dev->cci_clk_src = 0;
+1 −1
Original line number Diff line number Diff line
@@ -164,10 +164,10 @@ struct cci_device {
	struct msm_camera_cci_i2c_queue_info
		cci_i2c_queue_info[NUM_MASTERS][NUM_QUEUES];
	struct msm_camera_cci_master_info cci_master_info[NUM_MASTERS];
	enum i2c_freq_mode_t i2c_freq_mode[NUM_MASTERS];
	struct msm_cci_clk_params_t cci_clk_params[I2C_MAX_MODES];
	struct gpio *cci_gpio_tbl;
	uint8_t cci_gpio_tbl_size;
	uint8_t master_clk_init[MASTER_MAX];
	struct msm_pinctrl_info cci_pinctrl;
	uint8_t cci_pinctrl_status;
	uint32_t cycles_per_us;
+15 −0
Original line number Diff line number Diff line
@@ -1058,6 +1058,20 @@ static int msm_eeprom_platform_probe(struct platform_device *pdev)
		return rc;
	}

	rc = of_property_read_u32(of_node, "qcom,i2c-freq-mode",
		&e_ctrl->i2c_freq_mode);
	CDBG("qcom,i2c_freq_mode %d, rc %d\n", e_ctrl->i2c_freq_mode, rc);
	if (rc < 0) {
		pr_err("%s qcom,i2c-freq-mode read fail. Setting to 0 %d\n",
			__func__, rc);
		e_ctrl->i2c_freq_mode = 0;
	}

	if (e_ctrl->i2c_freq_mode >= I2C_MAX_MODES) {
		pr_err("%s:%d invalid i2c_freq_mode = %d\n", __func__, __LINE__,
			e_ctrl->i2c_freq_mode);
		return -EINVAL;
	}
	/* Set platform device handle */
	e_ctrl->pdev = pdev;
	/* Set device type as platform device */
@@ -1097,6 +1111,7 @@ static int msm_eeprom_platform_probe(struct platform_device *pdev)
	cci_client = e_ctrl->i2c_client.cci_client;
	cci_client->cci_subdev = msm_cci_get_subdev();
	cci_client->cci_i2c_master = e_ctrl->cci_master;
	cci_client->i2c_freq_mode = e_ctrl->i2c_freq_mode;
	cci_client->sid = eb_info->i2c_slaveaddr >> 1;
	cci_client->retries = 3;
	cci_client->id_map = 0;
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,7 @@ struct msm_eeprom_ctrl_t {
	enum msm_camera_device_type_t eeprom_device_type;
	struct msm_sd_subdev msm_sd;
	enum cci_i2c_master_t cci_master;
	enum i2c_freq_mode_t i2c_freq_mode;

	struct msm_camera_i2c_client i2c_client;
	struct msm_eeprom_memory_block_t cal_data;
Loading