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

Commit 2ad24ad8 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: cci: Add serialization of requests from diff i2c freq modes"

parents 15b22fe0 abbc1b36
Loading
Loading
Loading
Loading
+123 −41
Original line number Diff line number Diff line
@@ -885,20 +885,39 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,

	soc_info = &cci_dev->soc_info;
	base = soc_info->reg_map[0].mem_base;
	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);

	/*
	 * Todo: If there is a change in frequency of operation
	 * Wait for previos transaction to complete
	 */
	mutex_lock(&cci_dev->cci_master_info[master].mutex);
	if (cci_dev->cci_master_info[master].is_first_req) {
		cci_dev->cci_master_info[master].is_first_req = false;
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else if (c_ctrl->cci_info->i2c_freq_mode
		!= cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
		cci_dev->cci_master_info[master].freq_ref_cnt++;
		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	}

	/* Set the I2C Frequency */
	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
		goto rel_mutex;
		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
		goto rel_master;
	}
	mutex_unlock(&cci_dev->cci_master_info[master].mutex);

	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
	/*
	 * 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
@@ -909,24 +928,24 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
		master, queue);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
		CAM_ERR(CAM_CCI, "More than max retries");
		goto rel_mutex;
		goto rel_mutex_q;
	}

	if (read_cfg->data == NULL) {
		CAM_ERR(CAM_CCI, "Data ptr is NULL");
		goto rel_mutex;
		goto rel_mutex_q;
	}

	if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
		CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
			read_cfg->addr_type);
		rc = -EINVAL;
		goto rel_mutex;
		goto rel_mutex_q;
	}

	CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
@@ -938,14 +957,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_LOCK_CMD;
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -957,21 +976,21 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_UNLOCK_CMD;
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1002,7 +1021,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
			cam_cci_dump_registers(cci_dev, master, queue);
#endif
			cam_cci_flush_queue(cci_dev, master);
			goto rel_mutex;
			goto rel_mutex_q;
		}

		read_words = cam_io_r_mb(base +
@@ -1083,7 +1102,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
						master, queue);
				#endif
					cam_cci_flush_queue(cci_dev, master);
				goto rel_mutex;
				goto rel_mutex_q;
			}
			break;
		}
@@ -1092,8 +1111,15 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
	CAM_DBG(CAM_CCI, "Burst read successful words_read %d",
		total_read_words);

rel_mutex:
rel_mutex_q:
	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
rel_master:
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
		up(&cci_dev->cci_master_info[master].master_sem);
	else
		cci_dev->cci_master_info[master].freq_ref_cnt--;
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	return rc;
}

@@ -1125,20 +1151,38 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
	soc_info = &cci_dev->soc_info;
	base = soc_info->reg_map[0].mem_base;

	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);

	/*
	 * Todo: If there is a change in frequency of operation
	 * Wait for previos transaction to complete
	 */
	mutex_lock(&cci_dev->cci_master_info[master].mutex);
	if (cci_dev->cci_master_info[master].is_first_req) {
		cci_dev->cci_master_info[master].is_first_req = false;
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else if (c_ctrl->cci_info->i2c_freq_mode
		!= cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
		cci_dev->cci_master_info[master].freq_ref_cnt++;
		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	}

	/* Set the I2C Frequency */
	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
		goto rel_mutex;
		goto rel_master;
	}
	mutex_unlock(&cci_dev->cci_master_info[master].mutex);

	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
	/*
	 * 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
@@ -1149,17 +1193,17 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
		master, queue);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
		CAM_ERR(CAM_CCI, "More than max retries");
		goto rel_mutex;
		goto rel_mutex_q;
	}

	if (read_cfg->data == NULL) {
		CAM_ERR(CAM_CCI, "Data ptr is NULL");
		goto rel_mutex;
		goto rel_mutex_q;
	}

	CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
@@ -1172,21 +1216,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_LOCK_CMD;
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
		CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
			read_cfg->addr_type);
		rc = -EINVAL;
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
@@ -1198,21 +1242,21 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = CCI_I2C_UNLOCK_CMD;
	rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
	if (rc < 0) {
		CAM_DBG(CAM_CCI, "failed rc: %d", rc);
		goto rel_mutex;
		goto rel_mutex_q;
	}

	val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
@@ -1240,7 +1284,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
			"wait_for_completion_timeout rc = %d FIFO buf_lvl: 0x%x",
			rc, val);
		cam_cci_flush_queue(cci_dev, master);
		goto rel_mutex;
		goto rel_mutex_q;
	} else {
		rc = 0;
	}
@@ -1253,7 +1297,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
			read_words, exp_words);
		memset(read_cfg->data, 0, read_cfg->num_byte);
		rc = -EINVAL;
		goto rel_mutex;
		goto rel_mutex_q;
	}
	index = 0;
	CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
@@ -1277,8 +1321,15 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
		}
		read_words--;
	}
rel_mutex:
rel_mutex_q:
	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
rel_master:
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
		up(&cci_dev->cci_master_info[master].master_sem);
	else
		cci_dev->cci_master_info[master].freq_ref_cnt--;
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	return rc;
}

@@ -1302,12 +1353,36 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
		c_ctrl->cci_info->id_map);

	mutex_lock(&cci_dev->cci_master_info[master].mutex);
	if (cci_dev->cci_master_info[master].is_first_req) {
		cci_dev->cci_master_info[master].is_first_req = false;
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else if (c_ctrl->cci_info->i2c_freq_mode
		!= cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
		cci_dev->cci_master_info[master].freq_ref_cnt++;
		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	}

	/* Set the I2C Frequency */
	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
		return rc;
		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
		goto ERROR;
	}
	mutex_unlock(&cci_dev->cci_master_info[master].mutex);
	/*
	 * 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
@@ -1319,18 +1394,25 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
			rc);
		return rc;
		goto ERROR;
	}
	if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
		CAM_ERR(CAM_CCI, "More than max retries");
		return rc;
		goto ERROR;
	}
	rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "failed rc: %d", rc);
		return rc;
		goto ERROR;
	}

ERROR:
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
		up(&cci_dev->cci_master_info[master].master_sem);
	else
		cci_dev->cci_master_info[master].freq_ref_cnt--;
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	return rc;
}

+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/semaphore.h>
#include <media/cam_sensor.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
@@ -137,6 +138,10 @@ struct cam_cci_master_info {
	struct completion report_q[NUM_QUEUES];
	atomic_t done_pending[NUM_QUEUES];
	spinlock_t lock_q[NUM_QUEUES];
	spinlock_t freq_cnt;
	struct semaphore master_sem;
	bool is_first_req;
	uint16_t freq_ref_cnt;
};

struct cam_cci_clk_params_t {
+3 −0
Original line number Diff line number Diff line
@@ -189,7 +189,10 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)

	for (i = 0; i < NUM_MASTERS; i++) {
		new_cci_dev->cci_master_info[i].status = 0;
		new_cci_dev->cci_master_info[i].is_first_req = true;
		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
		sema_init(&new_cci_dev->cci_master_info[i].master_sem, 1);
		spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt);
		init_completion(
			&new_cci_dev->cci_master_info[i].reset_complete);
		init_completion(