|
@@ -609,19 +609,42 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
|
|
|
struct cam_cci_clk_params_t *clk_params = NULL;
|
|
|
enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
|
|
|
enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;
|
|
|
- struct cam_hw_soc_info *soc_info =
|
|
|
- &cci_dev->soc_info;
|
|
|
- void __iomem *base = soc_info->reg_map[0].mem_base;
|
|
|
+ void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base;
|
|
|
+ struct cam_cci_master_info *cci_master =
|
|
|
+ &cci_dev->cci_master_info[master];
|
|
|
|
|
|
if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) {
|
|
|
CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
+ /*
|
|
|
+ * If no change in i2c freq, then acquire semaphore only for the first
|
|
|
+ * i2c transaction to indicate I2C transaction is in progress, else
|
|
|
+ * always try to acquire semaphore, to make sure that no other I2C
|
|
|
+ * transaction is in progress.
|
|
|
+ */
|
|
|
+ mutex_lock(&cci_master->mutex);
|
|
|
+ if (i2c_freq_mode == cci_dev->i2c_freq_mode[master]) {
|
|
|
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d", master,
|
|
|
+ i2c_freq_mode);
|
|
|
+ spin_lock(&cci_master->freq_cnt_lock);
|
|
|
+ if (cci_master->freq_ref_cnt == 0)
|
|
|
+ down(&cci_master->master_sem);
|
|
|
+ cci_master->freq_ref_cnt++;
|
|
|
+ spin_unlock(&cci_master->freq_cnt_lock);
|
|
|
+ mutex_unlock(&cci_master->mutex);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
|
|
|
+ master, cci_dev->i2c_freq_mode[master], i2c_freq_mode);
|
|
|
+ down(&cci_master->master_sem);
|
|
|
+
|
|
|
+ spin_lock(&cci_master->freq_cnt_lock);
|
|
|
+ cci_master->freq_ref_cnt++;
|
|
|
+ spin_unlock(&cci_master->freq_cnt_lock);
|
|
|
|
|
|
clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];
|
|
|
|
|
|
- if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode)
|
|
|
- return 0;
|
|
|
if (master == MASTER_0) {
|
|
|
cam_io_w_mb(clk_params->hw_thigh << 16 |
|
|
|
clk_params->hw_tlow,
|
|
@@ -655,6 +678,7 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
|
|
|
}
|
|
|
cci_dev->i2c_freq_mode[master] = i2c_freq_mode;
|
|
|
|
|
|
+ mutex_unlock(&cci_master->mutex);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -938,42 +962,19 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- soc_info = &cci_dev->soc_info;
|
|
|
- base = soc_info->reg_map[0].mem_base;
|
|
|
-
|
|
|
- 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);
|
|
|
- mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
|
|
- goto rel_master;
|
|
|
+ return rc;
|
|
|
}
|
|
|
- mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
|
|
|
|
|
mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
|
|
|
reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
|
|
|
+
|
|
|
+ soc_info = &cci_dev->soc_info;
|
|
|
+ base = soc_info->reg_map[0].mem_base;
|
|
|
+
|
|
|
/*
|
|
|
* 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
|
|
@@ -1198,13 +1199,11 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
|
|
|
|
|
|
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)
|
|
|
+
|
|
|
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
|
|
|
+ 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);
|
|
|
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -1234,42 +1233,19 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- soc_info = &cci_dev->soc_info;
|
|
|
- base = soc_info->reg_map[0].mem_base;
|
|
|
-
|
|
|
- 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_master;
|
|
|
+ return rc;
|
|
|
}
|
|
|
- mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
|
|
|
|
|
mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
|
|
|
reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
|
|
|
+
|
|
|
+ soc_info = &cci_dev->soc_info;
|
|
|
+ base = soc_info->reg_map[0].mem_base;
|
|
|
+
|
|
|
/*
|
|
|
* 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
|
|
@@ -1425,13 +1401,11 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
|
|
|
}
|
|
|
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)
|
|
|
+
|
|
|
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
|
|
|
+ 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);
|
|
|
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -1455,37 +1429,12 @@ 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);
|
|
|
- mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
|
|
- goto ERROR;
|
|
|
+ return rc;
|
|
|
}
|
|
|
- mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
|
|
-
|
|
|
reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
|
|
|
/*
|
|
|
* Call validate queue to make sure queue is empty before starting.
|
|
@@ -1515,12 +1464,10 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
|
|
|
}
|
|
|
|
|
|
ERROR:
|
|
|
- spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
|
|
|
- if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
|
|
|
+ spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
|
|
|
+ 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);
|
|
|
+ spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
|
|
|
return rc;
|
|
|
}
|
|
|
|