Merge "msm: camera: Enhance CCI error handling"
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
index 642df76..591c464 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
@@ -43,10 +43,6 @@
#define CCI_IRQ_MASK_0_RMSK 0x7fff7ff7
#define CCI_IRQ_CLEAR_0_ADDR 0x00000c08
#define CCI_IRQ_STATUS_0_ADDR 0x00000c0c
-#define CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR_BMSK 0x40000000
-#define CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR_BMSK 0x20000000
-#define CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERR_BMSK 0x10000000
-#define CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERR_BMSK 0x8000000
#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK_BMSK 0x4000000
#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK 0x2000000
#define CCI_IRQ_STATUS_0_RST_DONE_ACK_BMSK 0x1000000
@@ -55,6 +51,8 @@
#define CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK 0x1000
#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_GLOBAL_CLEAR_CMD_ADDR 0x00000c00
#endif /* __MSM_CAM_CCI_HWREG__ */
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 9300ce0..3409b3e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -271,6 +271,21 @@
master = c_ctrl->cci_info->cci_i2c_master;
read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
mutex_lock(&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_read call. This is to
+ * avoid overflow / underflow of queue
+ */
+ rc = msm_cci_validate_queue(cci_dev,
+ cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1,
+ master, queue);
+ if (rc < 0) {
+ pr_err("%s:%d Initial validataion failed rc %d\n", __func__,
+ __LINE__, rc);
+ goto ERROR;
+ }
+
CDBG("%s master %d, queue %d\n", __func__, master, queue);
CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
@@ -450,6 +465,21 @@
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);
+
+ /*
+ * 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
+ * avoid overflow / underflow of queue
+ */
+ rc = msm_cci_validate_queue(cci_dev,
+ cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1,
+ master, queue);
+ if (rc < 0) {
+ pr_err("%s:%d Initial validataion failed rc %d\n", __func__,
+ __LINE__, rc);
+ goto ERROR;
+ }
+
val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
c_ctrl->cci_info->retries << 16 |
c_ctrl->cci_info->id_map << 18;
@@ -694,16 +724,6 @@
(irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK)) {
cci_dev->cci_master_info[MASTER_1].status = 0;
complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
- } else if ((irq & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERR_BMSK) ||
- (irq & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERR_BMSK)) {
- cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
- msm_camera_io_w(CCI_M0_HALT_REQ_RMSK,
- cci_dev->base + CCI_HALT_REQ_ADDR);
- } else if ((irq & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR_BMSK) ||
- (irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR_BMSK)) {
- cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
- msm_camera_io_w(CCI_M1_HALT_REQ_RMSK,
- cci_dev->base + CCI_HALT_REQ_ADDR);
} else if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) {
cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
msm_camera_io_w(CCI_M0_RESET_RMSK,
@@ -712,6 +732,16 @@
cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE;
msm_camera_io_w(CCI_M1_RESET_RMSK,
cci_dev->base + CCI_RESET_CMD_ADDR);
+ } else if (irq & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) {
+ pr_err("%s:%d MASTER_0 error %x\n", __func__, __LINE__, irq);
+ cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
+ msm_camera_io_w(CCI_M0_HALT_REQ_RMSK,
+ cci_dev->base + CCI_HALT_REQ_ADDR);
+ } else if (irq & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) {
+ pr_err("%s:%d MASTER_1 error %x\n", __func__, __LINE__, irq);
+ cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
+ msm_camera_io_w(CCI_M1_HALT_REQ_RMSK,
+ cci_dev->base + CCI_HALT_REQ_ADDR);
} else {
pr_err("%s unhandled irq 0x%x\n", __func__, irq);
cci_dev->cci_master_info[MASTER_0].status = 0;