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

Commit 3e464e2b authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: cci: Fix burst read sequence" into dev/msm-4.14-camx

parents 88736017 cae5ae21
Loading
Loading
Loading
Loading
+80 −11
Original line number Diff line number Diff line
@@ -869,8 +869,8 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
	struct cam_cci_ctrl *c_ctrl)
{
	int32_t rc = 0;
	uint32_t val = 0, i = 0;
	unsigned long rem_jiffies;
	uint32_t val = 0, i = 0, j = 0;
	unsigned long rem_jiffies, flags;
	int32_t read_words = 0, exp_words = 0;
	int32_t index = 0, first_byte = 0, total_read_words = 0;
	enum cci_i2c_master_t master;
@@ -989,11 +989,13 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,

	val = 1 << ((master * 2) + queue);
	cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);

	exp_words = ((read_cfg->num_byte / 4) + 1);
	CAM_DBG(CAM_CCI, "waiting for threshold [exp_words %d]", exp_words);

	while (exp_words != total_read_words) {
	while (total_read_words != exp_words) {
		rem_jiffies = wait_for_completion_timeout(
			&cci_dev->cci_master_info[master].reset_complete,
			&cci_dev->cci_master_info[master].th_complete,
			CCI_TIMEOUT);
		if (!rem_jiffies) {
			rc = -ETIMEDOUT;
@@ -1012,6 +1014,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,

		read_words = cam_io_r_mb(base +
			CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
		if (read_words <= 0) {
			CAM_DBG(CAM_CCI, "FIFO Buffer lvl is 0");
			continue;
		}

		j++;
		CAM_DBG(CAM_CCI, "Iteration: %u read_words %d", j, read_words);

		total_read_words += read_words;
		while (read_words > 0) {
			val = cam_io_r_mb(base +
@@ -1033,8 +1043,55 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
			}
			read_words--;
		}

		CAM_DBG(CAM_CCI, "Iteraion:%u total_read_words %d",
			j, total_read_words);

		spin_lock_irqsave(&cci_dev->lock_status, flags);
		if (cci_dev->irq_status1) {
			CAM_DBG(CAM_CCI, "clear irq_status1:%x",
				cci_dev->irq_status1);
			cam_io_w_mb(cci_dev->irq_status1,
				base + CCI_IRQ_CLEAR_1_ADDR);
			cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
			cci_dev->irq_status1 = 0;
		}
		spin_unlock_irqrestore(&cci_dev->lock_status, flags);

		if (total_read_words == exp_words) {
		   /*
		    * This wait is for RD_DONE irq, if RD_DONE is
		    * triggered we will call complete on both threshold
		    * & read done waits. As part of the threshold wait
		    * we will be draining the entire buffer out. This
		    * wait is to compensate for the complete invoked for
		    * RD_DONE exclusively.
		    */
			rem_jiffies = wait_for_completion_timeout(
			&cci_dev->cci_master_info[master].reset_complete,
			CCI_TIMEOUT);
			if (!rem_jiffies) {
				rc = -ETIMEDOUT;
				val = cam_io_r_mb(base +
					CCI_I2C_M0_READ_BUF_LEVEL_ADDR +
					master * 0x100);
				CAM_ERR(CAM_CCI,
					"Failed to receive RD_DONE irq rc = %d FIFO buf_lvl:0x%x",
					rc, val);
				#ifdef DUMP_CCI_REGISTERS
					cam_cci_dump_registers(cci_dev,
						master, queue);
				#endif
					cam_cci_flush_queue(cci_dev, master);
				goto rel_mutex;
			}
			break;
		}
	}

	CAM_DBG(CAM_CCI, "Burst read successful words_read %d",
		total_read_words);

rel_mutex:
	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
	return rc;
@@ -1166,7 +1223,8 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,

	val = 1 << ((master * 2) + queue);
	cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
	CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
	CAM_DBG(CAM_CCI,
		"waiting_for_rd_done [exp_words: %d]", exp_words);

	rc = wait_for_completion_timeout(
		&cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
@@ -1221,7 +1279,6 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
	}
rel_mutex:
	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);

	return rc;
}

@@ -1400,23 +1457,34 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
	}

	read_bytes = read_cfg->num_byte;

	/*
	 * To avoid any conflicts due to back to back trigger of
	 * THRESHOLD irq's, we reinit the threshold wait before
	 * we load the burst read cmd.
	 */
	reinit_completion(&cci_dev->cci_master_info[master].th_complete);

	CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes);
	do {
		if (read_bytes > CCI_I2C_MAX_BYTE_COUNT)
		if (read_bytes >= CCI_I2C_MAX_BYTE_COUNT)
			read_cfg->num_byte = CCI_I2C_MAX_BYTE_COUNT;
		else
			read_cfg->num_byte = read_bytes;

		if (read_cfg->num_byte > CCI_READ_MAX)
		if (read_cfg->num_byte >= CCI_READ_MAX) {
			cci_dev->is_burst_read = true;
			rc = cam_cci_burst_read(sd, c_ctrl);
		else
		} else {
			cci_dev->is_burst_read = false;
			rc = cam_cci_read(sd, c_ctrl);

		}
		if (rc) {
			CAM_ERR(CAM_CCI, "failed to read rc:%d", rc);
			goto ERROR;
		}

		if (read_bytes > CCI_I2C_MAX_BYTE_COUNT) {
		if (read_bytes >= CCI_I2C_MAX_BYTE_COUNT) {
			read_cfg->addr += (CCI_I2C_MAX_BYTE_COUNT /
				read_cfg->data_type);
			read_cfg->data += CCI_I2C_MAX_BYTE_COUNT;
@@ -1427,6 +1495,7 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
	} while (read_bytes);

ERROR:
	cci_dev->is_burst_read = false;
	return rc;
}

+39 −13
Original line number Diff line number Diff line
@@ -67,15 +67,12 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
		&cci_dev->soc_info;
	void __iomem *base = soc_info->reg_map[0].mem_base;
	unsigned long flags;
	bool burst_read_assert = false;
	bool rd_done_th_assert = false;

	irq_status0 = cam_io_r_mb(base + CCI_IRQ_STATUS_0_ADDR);
	irq_status1 = cam_io_r_mb(base + CCI_IRQ_STATUS_1_ADDR);
	cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR);
	cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR);
	cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);

	CAM_DBG(CAM_CCI, "irq0:%x irq1:%x", irq_status0, irq_status1);

	if (irq_status0 & CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK) {
		if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) {
			cci_dev->cci_master_info[MASTER_0].reset_pending =
@@ -94,18 +91,23 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
	if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) &&
		(irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD)) {
		cci_dev->cci_master_info[MASTER_0].status = 0;
		rd_done_th_assert = true;
		complete(&cci_dev->cci_master_info[MASTER_0].th_complete);
		complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
		burst_read_assert = true;
	}
	if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) &&
		(!burst_read_assert)) {
		(!rd_done_th_assert)) {
		cci_dev->cci_master_info[MASTER_0].status = 0;
		rd_done_th_assert = true;
		if (cci_dev->is_burst_read)
			complete(
			&cci_dev->cci_master_info[MASTER_0].th_complete);
		complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
	}
	if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD) &&
		(!burst_read_assert)) {
		(!rd_done_th_assert)) {
		cci_dev->cci_master_info[MASTER_0].status = 0;
		complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
		complete(&cci_dev->cci_master_info[MASTER_0].th_complete);
	}
	if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK) {
		struct cam_cci_master_info *cci_master_info;
@@ -144,18 +146,23 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
	if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) &&
		(irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD)) {
		cci_dev->cci_master_info[MASTER_1].status = 0;
		rd_done_th_assert = true;
		complete(&cci_dev->cci_master_info[MASTER_1].th_complete);
		complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
		burst_read_assert = true;
	}
	if ((irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) &&
		(!burst_read_assert)) {
		(!rd_done_th_assert)) {
		cci_dev->cci_master_info[MASTER_1].status = 0;
		rd_done_th_assert = true;
		if (cci_dev->is_burst_read)
			complete(
			&cci_dev->cci_master_info[MASTER_1].th_complete);
		complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
	}
	if ((irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD) &&
		(!burst_read_assert)) {
		(!rd_done_th_assert)) {
		cci_dev->cci_master_info[MASTER_1].status = 0;
		complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
		complete(&cci_dev->cci_master_info[MASTER_1].th_complete);
	}
	if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK) {
		struct cam_cci_master_info *cci_master_info;
@@ -191,6 +198,12 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
			&cci_dev->cci_master_info[MASTER_1].lock_q[QUEUE_1],
			flags);
	}
	if (irq_status1 & CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE)
		CAM_DBG(CAM_CCI, "RD_PAUSE ON MASTER_0");

	if (irq_status1 & CCI_IRQ_STATUS_1_I2C_M1_RD_PAUSE)
		CAM_DBG(CAM_CCI, "RD_PAUSE ON MASTER_1");

	if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) {
		cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
		cam_io_w_mb(CCI_M0_RESET_RMSK,
@@ -213,6 +226,19 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
			base + CCI_HALT_REQ_ADDR);
		CAM_DBG(CAM_CCI, "MASTER_1 error 0x%x", irq_status0);
	}

	if ((rd_done_th_assert) || (!cci_dev->is_burst_read)) {
		cam_io_w_mb(irq_status1, base + CCI_IRQ_CLEAR_1_ADDR);
		CAM_DBG(CAM_CCI, "clear irq_status0:%x irq_status1:%x",
			irq_status0, irq_status1);
	} else {
		spin_lock_irqsave(&cci_dev->lock_status, flags);
		cci_dev->irq_status1 |= irq_status1;
		spin_unlock_irqrestore(&cci_dev->lock_status, flags);
	}

	cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR);
	cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
	return IRQ_HANDLED;
}

+9 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ struct cam_cci_master_info {
	uint8_t reset_pending;
	struct mutex mutex;
	struct completion reset_complete;
	struct completion th_complete;
	struct mutex mutex_q[NUM_QUEUES];
	struct completion report_q[NUM_QUEUES];
	atomic_t done_pending[NUM_QUEUES];
@@ -194,6 +195,11 @@ enum cam_cci_state_t {
 * @cci_wait_sync_cfg: CCI sync config
 * @cycles_per_us: Cycles per micro sec
 * @payload_size: CCI packet payload size
 * @irq_status1: Store irq_status1 to be cleared after
 *               draining FIFO buffer for burst read
 * @lock_status: to protect changes to irq_status1
 * @is_burst_read: Flag to determine if we are performing
 *                 a burst read operation or not
 */
struct cci_device {
	struct v4l2_subdev subdev;
@@ -218,6 +224,9 @@ struct cci_device {
	uint8_t payload_size;
	char device_name[20];
	uint32_t cpas_handle;
	uint32_t irq_status1;
	spinlock_t lock_status;
	bool is_burst_read;
};

enum cam_cci_i2c_cmd_type {
+3 −1
Original line number Diff line number Diff line
@@ -56,15 +56,17 @@
#define CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK                         0x10000
#define CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK                            0x1000
#define CCI_IRQ_STATUS_1_I2C_M1_RD_THRESHOLD                          0x100000
#define CCI_IRQ_STATUS_1_I2C_M1_RD_PAUSE                              0x200000
#define CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK                           0x100
#define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK                            0x10
#define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK                          0x18000EE6
#define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK                          0x60EE6000
#define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK                               0x1
#define CCI_IRQ_STATUS_1_I2C_M0_RD_THRESHOLD                           0x10000
#define CCI_IRQ_STATUS_1_I2C_M0_RD_PAUSE                               0x20000
#define CCI_I2C_M0_RD_THRESHOLD_ADDR                                0x00000120
#define CCI_I2C_M1_RD_THRESHOLD_ADDR                                0x00000220
#define CCI_I2C_RD_THRESHOLD_VALUE                                        0x38
#define CCI_I2C_RD_THRESHOLD_VALUE                                        0x30
#define CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR                               0x00000c00

#define DEBUG_TOP_REG_START                                                0x0
+3 −0
Original line number Diff line number Diff line
@@ -199,6 +199,8 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
		init_completion(
			&new_cci_dev->cci_master_info[i].reset_complete);
		init_completion(
			&new_cci_dev->cci_master_info[i].th_complete);

		for (j = 0; j < NUM_QUEUES; j++) {
			mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
@@ -208,6 +210,7 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
				&new_cci_dev->cci_master_info[i].lock_q[j]);
		}
	}
	spin_lock_init(&new_cci_dev->lock_status);
}

static void cam_cci_init_default_clk_params(struct cci_device *cci_dev,