Loading drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_core.c +559 −73 Original line number Diff line number Diff line Loading @@ -498,6 +498,23 @@ static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev, return len; } static int32_t cam_cci_calc_cmd_len_sync(enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type) { uint32_t len = 0; uint8_t data_len = 0, addr_len = 0; addr_len = cam_cci_convert_type_to_num_bytes(addr_type); data_len = cam_cci_convert_type_to_num_bytes(data_type); len = data_len + addr_len; len += 1; /*add i2c WR command*/ len = len/4 + 1; return len; } static uint32_t cam_cci_cycles_per_ms(unsigned long clk) { uint32_t cycles_per_us; Loading Loading @@ -865,6 +882,206 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev, return rc; } static int32_t cam_cci_data_queue_sync(struct cci_device *cci_dev, struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, enum cci_i2c_sync sync_en) { struct cam_hw_soc_info *soc_info = &cci_dev->soc_info; void __iomem *base = soc_info->reg_map[0].mem_base; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; struct ais_sensor_cmd_i2c_wr_array *wr_cfg = &c_ctrl->cfg.cci_wr_sync.wr_cfg[0]; unsigned long flags; uint32_t wr_cfg_idx = 0, i, val, read_val, delay, reg_offset, cmd = 0; uint16_t len = 0, k = 0, h = 0, j = 0, wr_count = 0; uint8_t data[12]; int32_t rc = 0; cci_dev->cci_wait_sync_cfg.cid = c_ctrl->cfg.cci_wr_sync.sync_cfg.cid; cci_dev->cci_wait_sync_cfg.csid = c_ctrl->cfg.cci_wr_sync.sync_cfg.csid; cci_dev->valid_sync = 1; CAM_ERR(CAM_CCI, "AIS_SENSOR_I2C_SET_SYNC_PARMS cid %d csid %d", cci_dev->cci_wait_sync_cfg.csid, c_ctrl->cci_info->id_map); cam_io_w_mb(cci_dev->cci_wait_sync_cfg.cid, base + CCI_SET_CID_SYNC_TIMER_ADDR + cci_dev->cci_wait_sync_cfg.csid * CCI_SET_CID_SYNC_TIMER_OFFSET); spin_lock_irqsave(&cci_dev->cci_master_info[master].lock_q[queue], flags); atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0); spin_unlock_irqrestore(&cci_dev->cci_master_info[master].lock_q[queue], flags); reg_offset = master * 0x200 + queue * 0x100; //first set PARAM to appropriate CSID val = CCI_I2C_SET_PARAM_CMD | ((wr_cfg->i2c_config.slave_addr >> 1) << 4) | c_ctrl->cci_info->retries << 16 | c_ctrl->cci_info->id_map << 18; CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset, val); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); CAM_ERR(CAM_CCI, "sid 0x%x cnt %d addr_type %d data_type %d", wr_cfg->i2c_config.slave_addr, wr_cfg->count, wr_cfg->addr_type, wr_cfg->data_type); //sync command if (sync_en == MSM_SYNC_ENABLE && cci_dev->valid_sync) { val = CCI_I2C_WAIT_SYNC_CMD | ((c_ctrl->cfg.cci_wr_sync.sync_cfg.line) << 4); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); } rc = cam_cci_lock_queue(cci_dev, master, queue, 1); if (rc < 0) { CAM_ERR(CAM_CCI, "failed line %d", rc); return rc; } for (wr_cfg_idx = 0; wr_cfg_idx < c_ctrl->cfg.cci_wr_sync.num_wr_cfg; wr_cfg_idx++) { wr_cfg = &c_ctrl->cfg.cci_wr_sync.wr_cfg[wr_cfg_idx]; if (wr_cfg_idx != 0) { val = CCI_I2C_SET_PARAM_CMD | ((wr_cfg->i2c_config.slave_addr >> 1) << 4) | c_ctrl->cci_info->retries << 16 | c_ctrl->cci_info->id_map << 18; CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset, val); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); CAM_ERR(CAM_CCI, "sid 0x%x cnt %d addr_type %d data_type %d", wr_cfg->i2c_config.slave_addr, wr_cfg->count, wr_cfg->addr_type, wr_cfg->data_type); } for (wr_count = 0; wr_count < wr_cfg->count; wr_count++) { len = cam_cci_calc_cmd_len_sync(wr_cfg->addr_type, wr_cfg->data_type); if (len <= 0) { CAM_ERR(CAM_CCI, "failed"); return -EINVAL; } CAM_DBG(CAM_CCI, "%d addr 0x%x data 0x%x delay 0x%x", wr_count, wr_cfg->wr_array[wr_count].reg_addr, wr_cfg->wr_array[wr_count].reg_data, wr_cfg->wr_array[wr_count].delay); delay = wr_cfg->wr_array[wr_count].delay; i = 0; data[i++] = CCI_I2C_WRITE_CMD; /* * in case of multiple command * MSM_CCI_I2C_WRITE : * address is not continuous, * so update address for a new packet. * MSM_CCI_I2C_WRITE_SEQ : * address is continuous, need to keep * the incremented address for a * new packet */ /* either byte or word addr&data */ if (wr_cfg->addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) data[i++] = wr_cfg->wr_array[wr_count].reg_addr; else { data[i++] = (wr_cfg->wr_array[wr_count].reg_addr & 0xFF00) >> 8; data[i++] = wr_cfg->wr_array[wr_count].reg_addr & 0x00FF; } if (wr_cfg->data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) data[i++] = wr_cfg->wr_array[wr_count].reg_data; else { data[i++] = (wr_cfg->wr_array[wr_count].reg_data & 0xFF00) >> 8; data[i++] = wr_cfg->wr_array[wr_count].reg_data & 0x00FF; } data[0] |= ((i-1) << 4); len = ((i-1)/4) + 1; read_val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); for (h = 0, k = 0; h < len; h++) { cmd = 0; for (j = 0; (j < 4 && k < i); j++) cmd |= (data[k++] << (j * 8)); CAM_DBG(CAM_CCI, "LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d", cmd, queue, len, read_val); cam_io_w_mb(cmd, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + master * 0x200 + queue * 0x100); read_val += 1; cam_io_w_mb(read_val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); } if ((delay > 0) && (delay < CCI_MAX_DELAY)) { cmd = (uint32_t)((delay * cci_dev->cycles_per_us) / 0x100); cmd <<= 4; cmd |= CCI_I2C_WAIT_CMD; CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd); cam_io_w_mb(cmd, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + master * 0x200 + queue * 0x100); read_val += 1; cam_io_w_mb(read_val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); } } } rc = cam_cci_transfer_end(cci_dev, master, queue); if (rc < 0) { CAM_ERR(CAM_CCI, "failed rc %d", rc); return rc; } return rc; } static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl) { Loading Loading @@ -1424,6 +1641,92 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd, return rc; } static int32_t cam_cci_i2c_write_sync(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, enum cci_i2c_sync sync_en) { int32_t rc = 0; struct cci_device *cci_dev; enum cci_i2c_master_t master; cci_dev = v4l2_get_subdevdata(sd); if (cci_dev->cci_state != CCI_STATE_ENABLED) { CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state); return -EINVAL; } master = c_ctrl->cci_info->cci_i2c_master; CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d", 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 == true) { 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; } 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 * avoid overflow / underflow of queue */ rc = cam_cci_validate_queue(cci_dev, cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1, master, queue); if (rc < 0) { CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc); goto ERROR; } if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { CAM_ERR(CAM_CCI, "More than max retries"); goto ERROR; } rc = cam_cci_data_queue_sync(cci_dev, c_ctrl, queue, sync_en); if (rc < 0) { CAM_ERR(CAM_CCI, "failed rc: %d", 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; } static void cam_cci_write_async_helper(struct work_struct *work) { int rc; Loading Loading @@ -1658,6 +1961,12 @@ static int32_t cam_cci_write(struct v4l2_subdev *sd, SYNC_QUEUE, MSM_SYNC_ENABLE); mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]); break; case MSM_CCI_I2C_WRITE_SYNC_ARRAY: mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]); rc = cam_cci_i2c_write_sync(sd, c_ctrl, SYNC_QUEUE, MSM_SYNC_ENABLE); mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]); break; case MSM_CCI_I2C_WRITE_SYNC: rc = cam_cci_i2c_write_async(sd, c_ctrl, SYNC_QUEUE, MSM_SYNC_ENABLE); Loading Loading @@ -1694,6 +2003,7 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, { int32_t rc = 0; struct cci_device *cci_dev = v4l2_get_subdevdata(sd); CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); switch (cci_ctrl->cmd) { Loading @@ -1716,6 +2026,7 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, case MSM_CCI_I2C_WRITE_SYNC: case MSM_CCI_I2C_WRITE_ASYNC: case MSM_CCI_I2C_WRITE_SYNC_BLOCK: case MSM_CCI_I2C_WRITE_SYNC_ARRAY: rc = cam_cci_write(sd, cci_ctrl); break; case MSM_CCI_GPIO_WRITE: Loading Loading @@ -1743,7 +2054,7 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, struct cam_cci_ctrl cci_ctrl; if (!cci_dev || !arg) { CAM_ERR(CAM_SENSOR, "s_ctrl is NULL"); CAM_ERR(CAM_CCI, "s_ctrl is NULL"); return -EINVAL; } Loading @@ -1751,12 +2062,17 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, if (cmd->op_code != AIS_SENSOR_I2C_POWER_DOWN) { if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { CAM_ERR(CAM_SENSOR, "Invalid handle type: %d", CAM_ERR(CAM_CCI, "Invalid handle type: %d", cmd->handle_type); return -EINVAL; } } cci_ctrl.cci_info = kzalloc(sizeof(struct cam_sensor_cci_client), GFP_KERNEL); if (!cci_ctrl.cci_info) return -ENOMEM; switch (cmd->op_code) { case CAM_QUERY_CAP: { struct cam_sensor_query_cap sensor_cap; Loading @@ -1764,7 +2080,7 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, sensor_cap.slot_info = cci_dev->soc_info.index; if (copy_to_user(u64_to_user_ptr(cmd->handle), &sensor_cap, sizeof(struct cam_sensor_query_cap))) { CAM_ERR(CAM_SENSOR, "Failed Copy to User"); CAM_ERR(CAM_CCI, "Failed Copy to User"); rc = -EFAULT; } } Loading @@ -1775,122 +2091,166 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, rc = copy_from_user(&cci_pwrup, (void __user *) cmd->handle, sizeof(cci_pwrup)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_dev->cci_debug.cci_i2c_master = cci_pwrup.master; cci_dev->cci_debug.retries = cci_pwrup.retries; cci_ctrl.cci_info->cci_i2c_master = cci_pwrup.master; cci_ctrl.cci_info->retries = cci_pwrup.retries; cci_ctrl.cci_info = &cci_dev->cci_debug; cci_ctrl.cmd = MSM_CCI_INIT; rc = cam_cci_core_cfg(sd, &cci_ctrl); } break; case AIS_SENSOR_I2C_POWER_DOWN: { cci_ctrl.cci_info = &cci_dev->cci_debug; struct ais_sensor_cmd_i2c_pwrdown cci_pwrdown; rc = copy_from_user(&cci_pwrdown, (void __user *) cmd->handle, sizeof(cci_pwrdown)); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_ctrl.cci_info->cci_i2c_master = cci_pwrdown.master; cci_ctrl.cci_info->retries = cci_pwrdown.retries; cci_ctrl.cmd = MSM_CCI_RELEASE; rc = cam_cci_core_cfg(sd, &cci_ctrl); } break; case AIS_SENSOR_I2C_READ: { struct ais_sensor_cmd_i2c_read i2c_read; struct ais_cci_cmd_t cci_cmd; unsigned char buf[CAMERA_SENSOR_I2C_TYPE_MAX]; struct cam_cci_ctrl cci_ctrl; rc = copy_from_user(&i2c_read, (void __user *) cmd->handle, sizeof(i2c_read)); rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } if (i2c_read.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_read.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || i2c_read.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_read.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) return rc; if (cci_cmd.cmd.i2c_read.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_read.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || cci_cmd.cmd.i2c_read.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_read.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) goto error; cci_dev->cci_debug.sid = i2c_read.i2c_config.slave_addr >> 1; cci_dev->cci_debug.i2c_freq_mode = i2c_read.i2c_config.i2c_freq_mode; cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cci_info->sid = cci_cmd.cmd.i2c_read.i2c_config.slave_addr >> 1; cci_ctrl.cci_info = &cci_dev->cci_debug; cci_ctrl.cmd = MSM_CCI_I2C_READ; cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = i2c_read.addr_type; cci_ctrl.cfg.cci_i2c_read_cfg.data_type = i2c_read.data_type; cci_ctrl.cfg.cci_i2c_read_cfg.addr = i2c_read.reg_addr; cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = cci_cmd.cmd.i2c_read.addr_type; cci_ctrl.cfg.cci_i2c_read_cfg.data_type = cci_cmd.cmd.i2c_read.data_type; cci_ctrl.cfg.cci_i2c_read_cfg.addr = cci_cmd.cmd.i2c_read.reg_addr; cci_ctrl.cfg.cci_i2c_read_cfg.data = buf; cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = i2c_read.data_type; cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = cci_cmd.cmd.i2c_read.data_type; rc = cam_cci_core_cfg(sd, &cci_ctrl); if (i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) i2c_read.reg_data = buf[0]; else if (i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_WORD) i2c_read.reg_data = buf[0] << 8 | buf[1]; else if (i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_3B) i2c_read.reg_data = buf[0] << 16 | buf[1] << 8 | buf[2]; if (cci_cmd.cmd.i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) cci_cmd.cmd.i2c_read.reg_data = buf[0]; else if (cci_cmd.cmd.i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_WORD) cci_cmd.cmd.i2c_read.reg_data = buf[0] << 8 | buf[1]; else if (cci_cmd.cmd.i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_3B) cci_cmd.cmd.i2c_read.reg_data = buf[0] << 16 | buf[1] << 8 | buf[2]; else i2c_read.reg_data = buf[0] << 24 | buf[1] << 16 | cci_cmd.cmd.i2c_read.reg_data = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; CAM_DBG(CAM_SENSOR, "Read 0x%x : 0x%x <- 0x%x", i2c_read.i2c_config.slave_addr, i2c_read.reg_addr, i2c_read.reg_data); CAM_DBG(CAM_CCI, "Read 0x%x : 0x%x <- 0x%x", cci_cmd.cmd.i2c_read.i2c_config.slave_addr, cci_cmd.cmd.i2c_read.reg_addr, cci_cmd.cmd.i2c_read.reg_data); if (copy_to_user((void __user *) cmd->handle, &i2c_read, sizeof(i2c_read))) { CAM_ERR(CAM_SENSOR, "Failed Copy to User"); if (copy_to_user((void __user *) cmd->handle, &cci_cmd, sizeof(cci_cmd))) { CAM_ERR(CAM_CCI, "Failed Copy to User"); rc = -EFAULT; } } break; case AIS_SENSOR_I2C_WRITE: { struct ais_sensor_cmd_i2c_wr i2c_write; struct ais_cci_cmd_t cci_cmd; struct cam_sensor_i2c_reg_array reg_setting; rc = copy_from_user(&i2c_write, (void __user *) cmd->handle, sizeof(i2c_write)); rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } if (i2c_write.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_write.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || i2c_write.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_write.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) return rc; if (cci_cmd.cmd.i2c_write.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_write.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || cci_cmd.cmd.i2c_write.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_write.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) goto error; cci_dev->cci_debug.sid = i2c_write.i2c_config.slave_addr >> 1; cci_dev->cci_debug.i2c_freq_mode = i2c_write.i2c_config.i2c_freq_mode; cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cci_info->sid = cci_cmd.cmd.i2c_write.i2c_config.slave_addr >> 1; cci_ctrl.cci_info = &cci_dev->cci_debug; cci_ctrl.cmd = MSM_CCI_I2C_WRITE; reg_setting.reg_addr = i2c_write.wr_payload.reg_addr; reg_setting.reg_data = i2c_write.wr_payload.reg_data; reg_setting.delay = i2c_write.wr_payload.delay; reg_setting.reg_addr = cci_cmd.cmd.i2c_write.wr_payload.reg_addr; reg_setting.reg_data = cci_cmd.cmd.i2c_write.wr_payload.reg_data; reg_setting.delay = cci_cmd.cmd.i2c_write.wr_payload.delay; reg_setting.data_mask = 0; cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = i2c_write.addr_type; cci_ctrl.cfg.cci_i2c_write_cfg.data_type = i2c_write.data_type; cci_ctrl.cfg.cci_i2c_write_cfg.reg_setting = ®_setting; cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = cci_cmd.cmd.i2c_write.addr_type; cci_ctrl.cfg.cci_i2c_write_cfg.data_type = cci_cmd.cmd.i2c_write.data_type; cci_ctrl.cfg.cci_i2c_write_cfg.reg_setting = ®_setting; cci_ctrl.cfg.cci_i2c_write_cfg.size = 1; cci_ctrl.cfg.cci_i2c_write_cfg.delay = 0; CAM_DBG(CAM_SENSOR, CAM_DBG(CAM_CCI, "Write 0x%x, 0x%x <- 0x%x [%d, %d]", i2c_write.i2c_config.slave_addr, i2c_write.wr_payload.reg_addr, i2c_write.wr_payload.reg_data, i2c_write.addr_type, i2c_write.data_type); cci_cmd.cmd.i2c_write.i2c_config.slave_addr, cci_cmd.cmd.i2c_write.wr_payload.reg_addr, cci_cmd.cmd.i2c_write.wr_payload.reg_data, cci_cmd.cmd.i2c_write.addr_type, cci_cmd.cmd.i2c_write.data_type); rc = cam_cci_core_cfg(sd, &cci_ctrl); Loading @@ -1900,11 +2260,137 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, usleep_range(reg_setting.delay * 1000, (reg_setting.delay * 1000) + 1000); } break; case AIS_SENSOR_I2C_WRITE_ARRAY_SYNC: { struct ais_cci_cmd_t cci_cmd; struct ais_sensor_i2c_wr_payload *wr_array; int i; CAM_ERR(CAM_CCI, "AIS_SENSOR_I2C_WRITE_ARRAY_SYNC"); rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cci_info->id_map = cci_cmd.cmd.wr_sync.sync_cfg.csid; cci_ctrl.cmd = MSM_CCI_I2C_WRITE_SYNC_ARRAY; cci_ctrl.cfg.cci_wr_sync.sync_cfg.cid = cci_cmd.cmd.wr_sync.sync_cfg.cid; cci_ctrl.cfg.cci_wr_sync.sync_cfg.csid = cci_cmd.cmd.wr_sync.sync_cfg.csid; cci_ctrl.cfg.cci_wr_sync.sync_cfg.line = cci_cmd.cmd.wr_sync.sync_cfg.line; cci_ctrl.cfg.cci_wr_sync.sync_cfg.delay = cci_cmd.cmd.wr_sync.sync_cfg.delay; cci_ctrl.cfg.cci_wr_sync.num_wr_cfg = cci_cmd.cmd.wr_sync.num_wr_cfg; CAM_ERR(CAM_CCI, "write_cmd_cnt %d", cci_cmd.cmd.wr_sync.num_wr_cfg); for (i = 0; i < cci_cmd.cmd.wr_sync.num_wr_cfg; i++) { wr_array = kcalloc( cci_cmd.cmd.wr_sync.wr_cfg[i].count, (sizeof(struct ais_sensor_i2c_wr_payload)), GFP_KERNEL); if (!wr_array) { rc = -ENOMEM; goto error; } copy_from_user(wr_array, (void __user *) (cci_cmd.cmd.wr_sync.wr_cfg[i].wr_array), cci_cmd.cmd.wr_sync.wr_cfg[i].count * sizeof(struct ais_sensor_i2c_wr_payload)); cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].wr_array = wr_array; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i] .i2c_config.slave_addr = cci_cmd.cmd.wr_sync.wr_cfg[i] .i2c_config.slave_addr; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].addr_type = cci_cmd.cmd.wr_sync.wr_cfg[i].addr_type; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].data_type = cci_cmd.cmd.wr_sync.wr_cfg[i].data_type; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].count = cci_cmd.cmd.wr_sync.wr_cfg[i].count; } rc = cam_cci_core_cfg(sd, &cci_ctrl); for (i = 0; i < cci_cmd.cmd.wr_sync.num_wr_cfg; i++) kfree(cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].wr_array); } break; case AIS_SENSOR_I2C_SET_SYNC_PARMS:{ struct ais_cci_cmd_t cci_cmd; rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cfg.cci_wait_sync_cfg.cid = cci_cmd.cmd.wr_sync.sync_cfg.cid; cci_ctrl.cfg.cci_wait_sync_cfg.csid = cci_cmd.cmd.wr_sync.sync_cfg.csid; cci_ctrl.cfg.cci_wait_sync_cfg.line = cci_cmd.cmd.wr_sync.sync_cfg.line; cci_ctrl.cfg.cci_wait_sync_cfg.delay = cci_cmd.cmd.wr_sync.sync_cfg.delay; cci_ctrl.cmd = MSM_CCI_SET_SYNC_CID; CAM_ERR(CAM_CCI, "AIS_SENSOR_I2C_SET_SYNC_PARMS cid %d csid %d", cci_ctrl.cfg.cci_wait_sync_cfg.cid, cci_ctrl.cfg.cci_wait_sync_cfg.csid); rc = cam_cci_core_cfg(sd, &cci_ctrl); } break; } error: kfree(cci_ctrl.cci_info); return rc; } drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_dev.c +0 −3 Original line number Diff line number Diff line Loading @@ -430,9 +430,6 @@ static int cam_cci_platform_probe(struct platform_device *pdev) g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; mutex_init(&(new_cci_dev->init_mutex)); new_cci_dev->cci_debug.cci_device = soc_info->index; new_cci_dev->cci_debug.cci_subdev = g_cci_subdev[soc_info->index]; CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); cam_register_subdev_fops(&cci_v4l2_subdev_fops); Loading drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_dev.h +8 −1 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ enum cam_cci_cmd_type { MSM_CCI_GPIO_WRITE, MSM_CCI_I2C_WRITE_SYNC, MSM_CCI_I2C_WRITE_SYNC_BLOCK, MSM_CCI_I2C_WRITE_SYNC_ARRAY, }; enum cci_i2c_queue_t { Loading Loading @@ -217,6 +218,12 @@ struct cam_sensor_cci_client { uint16_t cci_device; }; struct cam_sensor_cci_sync_info { enum i2c_freq_mode i2c_freq_mode; uint16_t sid; }; /** * struct cci_device * @pdev: Platform device Loading Loading @@ -283,7 +290,6 @@ struct cci_device { bool is_burst_read; uint32_t irqs_disabled; struct mutex init_mutex; struct cam_sensor_cci_client cci_debug; }; struct cam_cci_ctrl { Loading @@ -295,6 +301,7 @@ struct cam_cci_ctrl { struct cam_cci_read_cfg cci_i2c_read_cfg; struct cam_cci_wait_sync_cfg cci_wait_sync_cfg; struct cam_cci_gpio_cfg gpio_cfg; struct ais_sensor_wr_sync cci_wr_sync; } cfg; }; Loading include/uapi/media/ais_sensor.h +49 −5 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_core.c +559 −73 Original line number Diff line number Diff line Loading @@ -498,6 +498,23 @@ static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev, return len; } static int32_t cam_cci_calc_cmd_len_sync(enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type) { uint32_t len = 0; uint8_t data_len = 0, addr_len = 0; addr_len = cam_cci_convert_type_to_num_bytes(addr_type); data_len = cam_cci_convert_type_to_num_bytes(data_type); len = data_len + addr_len; len += 1; /*add i2c WR command*/ len = len/4 + 1; return len; } static uint32_t cam_cci_cycles_per_ms(unsigned long clk) { uint32_t cycles_per_us; Loading Loading @@ -865,6 +882,206 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev, return rc; } static int32_t cam_cci_data_queue_sync(struct cci_device *cci_dev, struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, enum cci_i2c_sync sync_en) { struct cam_hw_soc_info *soc_info = &cci_dev->soc_info; void __iomem *base = soc_info->reg_map[0].mem_base; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; struct ais_sensor_cmd_i2c_wr_array *wr_cfg = &c_ctrl->cfg.cci_wr_sync.wr_cfg[0]; unsigned long flags; uint32_t wr_cfg_idx = 0, i, val, read_val, delay, reg_offset, cmd = 0; uint16_t len = 0, k = 0, h = 0, j = 0, wr_count = 0; uint8_t data[12]; int32_t rc = 0; cci_dev->cci_wait_sync_cfg.cid = c_ctrl->cfg.cci_wr_sync.sync_cfg.cid; cci_dev->cci_wait_sync_cfg.csid = c_ctrl->cfg.cci_wr_sync.sync_cfg.csid; cci_dev->valid_sync = 1; CAM_ERR(CAM_CCI, "AIS_SENSOR_I2C_SET_SYNC_PARMS cid %d csid %d", cci_dev->cci_wait_sync_cfg.csid, c_ctrl->cci_info->id_map); cam_io_w_mb(cci_dev->cci_wait_sync_cfg.cid, base + CCI_SET_CID_SYNC_TIMER_ADDR + cci_dev->cci_wait_sync_cfg.csid * CCI_SET_CID_SYNC_TIMER_OFFSET); spin_lock_irqsave(&cci_dev->cci_master_info[master].lock_q[queue], flags); atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0); spin_unlock_irqrestore(&cci_dev->cci_master_info[master].lock_q[queue], flags); reg_offset = master * 0x200 + queue * 0x100; //first set PARAM to appropriate CSID val = CCI_I2C_SET_PARAM_CMD | ((wr_cfg->i2c_config.slave_addr >> 1) << 4) | c_ctrl->cci_info->retries << 16 | c_ctrl->cci_info->id_map << 18; CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset, val); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); CAM_ERR(CAM_CCI, "sid 0x%x cnt %d addr_type %d data_type %d", wr_cfg->i2c_config.slave_addr, wr_cfg->count, wr_cfg->addr_type, wr_cfg->data_type); //sync command if (sync_en == MSM_SYNC_ENABLE && cci_dev->valid_sync) { val = CCI_I2C_WAIT_SYNC_CMD | ((c_ctrl->cfg.cci_wr_sync.sync_cfg.line) << 4); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); } rc = cam_cci_lock_queue(cci_dev, master, queue, 1); if (rc < 0) { CAM_ERR(CAM_CCI, "failed line %d", rc); return rc; } for (wr_cfg_idx = 0; wr_cfg_idx < c_ctrl->cfg.cci_wr_sync.num_wr_cfg; wr_cfg_idx++) { wr_cfg = &c_ctrl->cfg.cci_wr_sync.wr_cfg[wr_cfg_idx]; if (wr_cfg_idx != 0) { val = CCI_I2C_SET_PARAM_CMD | ((wr_cfg->i2c_config.slave_addr >> 1) << 4) | c_ctrl->cci_info->retries << 16 | c_ctrl->cci_info->id_map << 18; CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x", CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset, val); cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); CAM_ERR(CAM_CCI, "sid 0x%x cnt %d addr_type %d data_type %d", wr_cfg->i2c_config.slave_addr, wr_cfg->count, wr_cfg->addr_type, wr_cfg->data_type); } for (wr_count = 0; wr_count < wr_cfg->count; wr_count++) { len = cam_cci_calc_cmd_len_sync(wr_cfg->addr_type, wr_cfg->data_type); if (len <= 0) { CAM_ERR(CAM_CCI, "failed"); return -EINVAL; } CAM_DBG(CAM_CCI, "%d addr 0x%x data 0x%x delay 0x%x", wr_count, wr_cfg->wr_array[wr_count].reg_addr, wr_cfg->wr_array[wr_count].reg_data, wr_cfg->wr_array[wr_count].delay); delay = wr_cfg->wr_array[wr_count].delay; i = 0; data[i++] = CCI_I2C_WRITE_CMD; /* * in case of multiple command * MSM_CCI_I2C_WRITE : * address is not continuous, * so update address for a new packet. * MSM_CCI_I2C_WRITE_SEQ : * address is continuous, need to keep * the incremented address for a * new packet */ /* either byte or word addr&data */ if (wr_cfg->addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) data[i++] = wr_cfg->wr_array[wr_count].reg_addr; else { data[i++] = (wr_cfg->wr_array[wr_count].reg_addr & 0xFF00) >> 8; data[i++] = wr_cfg->wr_array[wr_count].reg_addr & 0x00FF; } if (wr_cfg->data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) data[i++] = wr_cfg->wr_array[wr_count].reg_data; else { data[i++] = (wr_cfg->wr_array[wr_count].reg_data & 0xFF00) >> 8; data[i++] = wr_cfg->wr_array[wr_count].reg_data & 0x00FF; } data[0] |= ((i-1) << 4); len = ((i-1)/4) + 1; read_val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); for (h = 0, k = 0; h < len; h++) { cmd = 0; for (j = 0; (j < 4 && k < i); j++) cmd |= (data[k++] << (j * 8)); CAM_DBG(CAM_CCI, "LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d", cmd, queue, len, read_val); cam_io_w_mb(cmd, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + master * 0x200 + queue * 0x100); read_val += 1; cam_io_w_mb(read_val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); } if ((delay > 0) && (delay < CCI_MAX_DELAY)) { cmd = (uint32_t)((delay * cci_dev->cycles_per_us) / 0x100); cmd <<= 4; cmd |= CCI_I2C_WAIT_CMD; CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd); cam_io_w_mb(cmd, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + master * 0x200 + queue * 0x100); read_val += 1; cam_io_w_mb(read_val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); } } } rc = cam_cci_transfer_end(cci_dev, master, queue); if (rc < 0) { CAM_ERR(CAM_CCI, "failed rc %d", rc); return rc; } return rc; } static int32_t cam_cci_burst_read(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl) { Loading Loading @@ -1424,6 +1641,92 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd, return rc; } static int32_t cam_cci_i2c_write_sync(struct v4l2_subdev *sd, struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue, enum cci_i2c_sync sync_en) { int32_t rc = 0; struct cci_device *cci_dev; enum cci_i2c_master_t master; cci_dev = v4l2_get_subdevdata(sd); if (cci_dev->cci_state != CCI_STATE_ENABLED) { CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state); return -EINVAL; } master = c_ctrl->cci_info->cci_i2c_master; CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d", 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 == true) { 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; } 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 * avoid overflow / underflow of queue */ rc = cam_cci_validate_queue(cci_dev, cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1, master, queue); if (rc < 0) { CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc); goto ERROR; } if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) { CAM_ERR(CAM_CCI, "More than max retries"); goto ERROR; } rc = cam_cci_data_queue_sync(cci_dev, c_ctrl, queue, sync_en); if (rc < 0) { CAM_ERR(CAM_CCI, "failed rc: %d", 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; } static void cam_cci_write_async_helper(struct work_struct *work) { int rc; Loading Loading @@ -1658,6 +1961,12 @@ static int32_t cam_cci_write(struct v4l2_subdev *sd, SYNC_QUEUE, MSM_SYNC_ENABLE); mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]); break; case MSM_CCI_I2C_WRITE_SYNC_ARRAY: mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]); rc = cam_cci_i2c_write_sync(sd, c_ctrl, SYNC_QUEUE, MSM_SYNC_ENABLE); mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]); break; case MSM_CCI_I2C_WRITE_SYNC: rc = cam_cci_i2c_write_async(sd, c_ctrl, SYNC_QUEUE, MSM_SYNC_ENABLE); Loading Loading @@ -1694,6 +2003,7 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, { int32_t rc = 0; struct cci_device *cci_dev = v4l2_get_subdevdata(sd); CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd); switch (cci_ctrl->cmd) { Loading @@ -1716,6 +2026,7 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd, case MSM_CCI_I2C_WRITE_SYNC: case MSM_CCI_I2C_WRITE_ASYNC: case MSM_CCI_I2C_WRITE_SYNC_BLOCK: case MSM_CCI_I2C_WRITE_SYNC_ARRAY: rc = cam_cci_write(sd, cci_ctrl); break; case MSM_CCI_GPIO_WRITE: Loading Loading @@ -1743,7 +2054,7 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, struct cam_cci_ctrl cci_ctrl; if (!cci_dev || !arg) { CAM_ERR(CAM_SENSOR, "s_ctrl is NULL"); CAM_ERR(CAM_CCI, "s_ctrl is NULL"); return -EINVAL; } Loading @@ -1751,12 +2062,17 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, if (cmd->op_code != AIS_SENSOR_I2C_POWER_DOWN) { if (cmd->handle_type != CAM_HANDLE_USER_POINTER) { CAM_ERR(CAM_SENSOR, "Invalid handle type: %d", CAM_ERR(CAM_CCI, "Invalid handle type: %d", cmd->handle_type); return -EINVAL; } } cci_ctrl.cci_info = kzalloc(sizeof(struct cam_sensor_cci_client), GFP_KERNEL); if (!cci_ctrl.cci_info) return -ENOMEM; switch (cmd->op_code) { case CAM_QUERY_CAP: { struct cam_sensor_query_cap sensor_cap; Loading @@ -1764,7 +2080,7 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, sensor_cap.slot_info = cci_dev->soc_info.index; if (copy_to_user(u64_to_user_ptr(cmd->handle), &sensor_cap, sizeof(struct cam_sensor_query_cap))) { CAM_ERR(CAM_SENSOR, "Failed Copy to User"); CAM_ERR(CAM_CCI, "Failed Copy to User"); rc = -EFAULT; } } Loading @@ -1775,122 +2091,166 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, rc = copy_from_user(&cci_pwrup, (void __user *) cmd->handle, sizeof(cci_pwrup)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_dev->cci_debug.cci_i2c_master = cci_pwrup.master; cci_dev->cci_debug.retries = cci_pwrup.retries; cci_ctrl.cci_info->cci_i2c_master = cci_pwrup.master; cci_ctrl.cci_info->retries = cci_pwrup.retries; cci_ctrl.cci_info = &cci_dev->cci_debug; cci_ctrl.cmd = MSM_CCI_INIT; rc = cam_cci_core_cfg(sd, &cci_ctrl); } break; case AIS_SENSOR_I2C_POWER_DOWN: { cci_ctrl.cci_info = &cci_dev->cci_debug; struct ais_sensor_cmd_i2c_pwrdown cci_pwrdown; rc = copy_from_user(&cci_pwrdown, (void __user *) cmd->handle, sizeof(cci_pwrdown)); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_ctrl.cci_info->cci_i2c_master = cci_pwrdown.master; cci_ctrl.cci_info->retries = cci_pwrdown.retries; cci_ctrl.cmd = MSM_CCI_RELEASE; rc = cam_cci_core_cfg(sd, &cci_ctrl); } break; case AIS_SENSOR_I2C_READ: { struct ais_sensor_cmd_i2c_read i2c_read; struct ais_cci_cmd_t cci_cmd; unsigned char buf[CAMERA_SENSOR_I2C_TYPE_MAX]; struct cam_cci_ctrl cci_ctrl; rc = copy_from_user(&i2c_read, (void __user *) cmd->handle, sizeof(i2c_read)); rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } if (i2c_read.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_read.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || i2c_read.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_read.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) return rc; if (cci_cmd.cmd.i2c_read.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_read.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || cci_cmd.cmd.i2c_read.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_read.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) goto error; cci_dev->cci_debug.sid = i2c_read.i2c_config.slave_addr >> 1; cci_dev->cci_debug.i2c_freq_mode = i2c_read.i2c_config.i2c_freq_mode; cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cci_info->sid = cci_cmd.cmd.i2c_read.i2c_config.slave_addr >> 1; cci_ctrl.cci_info = &cci_dev->cci_debug; cci_ctrl.cmd = MSM_CCI_I2C_READ; cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = i2c_read.addr_type; cci_ctrl.cfg.cci_i2c_read_cfg.data_type = i2c_read.data_type; cci_ctrl.cfg.cci_i2c_read_cfg.addr = i2c_read.reg_addr; cci_ctrl.cfg.cci_i2c_read_cfg.addr_type = cci_cmd.cmd.i2c_read.addr_type; cci_ctrl.cfg.cci_i2c_read_cfg.data_type = cci_cmd.cmd.i2c_read.data_type; cci_ctrl.cfg.cci_i2c_read_cfg.addr = cci_cmd.cmd.i2c_read.reg_addr; cci_ctrl.cfg.cci_i2c_read_cfg.data = buf; cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = i2c_read.data_type; cci_ctrl.cfg.cci_i2c_read_cfg.num_byte = cci_cmd.cmd.i2c_read.data_type; rc = cam_cci_core_cfg(sd, &cci_ctrl); if (i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) i2c_read.reg_data = buf[0]; else if (i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_WORD) i2c_read.reg_data = buf[0] << 8 | buf[1]; else if (i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_3B) i2c_read.reg_data = buf[0] << 16 | buf[1] << 8 | buf[2]; if (cci_cmd.cmd.i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) cci_cmd.cmd.i2c_read.reg_data = buf[0]; else if (cci_cmd.cmd.i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_WORD) cci_cmd.cmd.i2c_read.reg_data = buf[0] << 8 | buf[1]; else if (cci_cmd.cmd.i2c_read.data_type == CAMERA_SENSOR_I2C_TYPE_3B) cci_cmd.cmd.i2c_read.reg_data = buf[0] << 16 | buf[1] << 8 | buf[2]; else i2c_read.reg_data = buf[0] << 24 | buf[1] << 16 | cci_cmd.cmd.i2c_read.reg_data = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; CAM_DBG(CAM_SENSOR, "Read 0x%x : 0x%x <- 0x%x", i2c_read.i2c_config.slave_addr, i2c_read.reg_addr, i2c_read.reg_data); CAM_DBG(CAM_CCI, "Read 0x%x : 0x%x <- 0x%x", cci_cmd.cmd.i2c_read.i2c_config.slave_addr, cci_cmd.cmd.i2c_read.reg_addr, cci_cmd.cmd.i2c_read.reg_data); if (copy_to_user((void __user *) cmd->handle, &i2c_read, sizeof(i2c_read))) { CAM_ERR(CAM_SENSOR, "Failed Copy to User"); if (copy_to_user((void __user *) cmd->handle, &cci_cmd, sizeof(cci_cmd))) { CAM_ERR(CAM_CCI, "Failed Copy to User"); rc = -EFAULT; } } break; case AIS_SENSOR_I2C_WRITE: { struct ais_sensor_cmd_i2c_wr i2c_write; struct ais_cci_cmd_t cci_cmd; struct cam_sensor_i2c_reg_array reg_setting; rc = copy_from_user(&i2c_write, (void __user *) cmd->handle, sizeof(i2c_write)); rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_SENSOR, "Failed Copying from user"); CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } if (i2c_write.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_write.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || i2c_write.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || i2c_write.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) return rc; if (cci_cmd.cmd.i2c_write.addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_write.addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || cci_cmd.cmd.i2c_write.data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || cci_cmd.cmd.i2c_write.data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) goto error; cci_dev->cci_debug.sid = i2c_write.i2c_config.slave_addr >> 1; cci_dev->cci_debug.i2c_freq_mode = i2c_write.i2c_config.i2c_freq_mode; cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cci_info->sid = cci_cmd.cmd.i2c_write.i2c_config.slave_addr >> 1; cci_ctrl.cci_info = &cci_dev->cci_debug; cci_ctrl.cmd = MSM_CCI_I2C_WRITE; reg_setting.reg_addr = i2c_write.wr_payload.reg_addr; reg_setting.reg_data = i2c_write.wr_payload.reg_data; reg_setting.delay = i2c_write.wr_payload.delay; reg_setting.reg_addr = cci_cmd.cmd.i2c_write.wr_payload.reg_addr; reg_setting.reg_data = cci_cmd.cmd.i2c_write.wr_payload.reg_data; reg_setting.delay = cci_cmd.cmd.i2c_write.wr_payload.delay; reg_setting.data_mask = 0; cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = i2c_write.addr_type; cci_ctrl.cfg.cci_i2c_write_cfg.data_type = i2c_write.data_type; cci_ctrl.cfg.cci_i2c_write_cfg.reg_setting = ®_setting; cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = cci_cmd.cmd.i2c_write.addr_type; cci_ctrl.cfg.cci_i2c_write_cfg.data_type = cci_cmd.cmd.i2c_write.data_type; cci_ctrl.cfg.cci_i2c_write_cfg.reg_setting = ®_setting; cci_ctrl.cfg.cci_i2c_write_cfg.size = 1; cci_ctrl.cfg.cci_i2c_write_cfg.delay = 0; CAM_DBG(CAM_SENSOR, CAM_DBG(CAM_CCI, "Write 0x%x, 0x%x <- 0x%x [%d, %d]", i2c_write.i2c_config.slave_addr, i2c_write.wr_payload.reg_addr, i2c_write.wr_payload.reg_data, i2c_write.addr_type, i2c_write.data_type); cci_cmd.cmd.i2c_write.i2c_config.slave_addr, cci_cmd.cmd.i2c_write.wr_payload.reg_addr, cci_cmd.cmd.i2c_write.wr_payload.reg_data, cci_cmd.cmd.i2c_write.addr_type, cci_cmd.cmd.i2c_write.data_type); rc = cam_cci_core_cfg(sd, &cci_ctrl); Loading @@ -1900,11 +2260,137 @@ int32_t cam_cci_core_cam_ctrl(struct v4l2_subdev *sd, usleep_range(reg_setting.delay * 1000, (reg_setting.delay * 1000) + 1000); } break; case AIS_SENSOR_I2C_WRITE_ARRAY_SYNC: { struct ais_cci_cmd_t cci_cmd; struct ais_sensor_i2c_wr_payload *wr_array; int i; CAM_ERR(CAM_CCI, "AIS_SENSOR_I2C_WRITE_ARRAY_SYNC"); rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cci_info->id_map = cci_cmd.cmd.wr_sync.sync_cfg.csid; cci_ctrl.cmd = MSM_CCI_I2C_WRITE_SYNC_ARRAY; cci_ctrl.cfg.cci_wr_sync.sync_cfg.cid = cci_cmd.cmd.wr_sync.sync_cfg.cid; cci_ctrl.cfg.cci_wr_sync.sync_cfg.csid = cci_cmd.cmd.wr_sync.sync_cfg.csid; cci_ctrl.cfg.cci_wr_sync.sync_cfg.line = cci_cmd.cmd.wr_sync.sync_cfg.line; cci_ctrl.cfg.cci_wr_sync.sync_cfg.delay = cci_cmd.cmd.wr_sync.sync_cfg.delay; cci_ctrl.cfg.cci_wr_sync.num_wr_cfg = cci_cmd.cmd.wr_sync.num_wr_cfg; CAM_ERR(CAM_CCI, "write_cmd_cnt %d", cci_cmd.cmd.wr_sync.num_wr_cfg); for (i = 0; i < cci_cmd.cmd.wr_sync.num_wr_cfg; i++) { wr_array = kcalloc( cci_cmd.cmd.wr_sync.wr_cfg[i].count, (sizeof(struct ais_sensor_i2c_wr_payload)), GFP_KERNEL); if (!wr_array) { rc = -ENOMEM; goto error; } copy_from_user(wr_array, (void __user *) (cci_cmd.cmd.wr_sync.wr_cfg[i].wr_array), cci_cmd.cmd.wr_sync.wr_cfg[i].count * sizeof(struct ais_sensor_i2c_wr_payload)); cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].wr_array = wr_array; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i] .i2c_config.slave_addr = cci_cmd.cmd.wr_sync.wr_cfg[i] .i2c_config.slave_addr; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].addr_type = cci_cmd.cmd.wr_sync.wr_cfg[i].addr_type; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].data_type = cci_cmd.cmd.wr_sync.wr_cfg[i].data_type; cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].count = cci_cmd.cmd.wr_sync.wr_cfg[i].count; } rc = cam_cci_core_cfg(sd, &cci_ctrl); for (i = 0; i < cci_cmd.cmd.wr_sync.num_wr_cfg; i++) kfree(cci_ctrl.cfg.cci_wr_sync.wr_cfg[i].wr_array); } break; case AIS_SENSOR_I2C_SET_SYNC_PARMS:{ struct ais_cci_cmd_t cci_cmd; rc = copy_from_user(&cci_cmd, (void __user *) cmd->handle, sizeof(cci_cmd)); if (rc < 0) { CAM_ERR(CAM_CCI, "Failed Copying from user"); goto error; } cci_ctrl.cci_info->i2c_freq_mode = cci_cmd.cci_client.i2c_freq_mode; cci_ctrl.cci_info->cci_i2c_master = cci_cmd.cci_client.cci_i2c_master; cci_ctrl.cci_info->timeout = cci_cmd.cci_client.timeout; cci_ctrl.cci_info->retries = cci_cmd.cci_client.retries; cci_ctrl.cfg.cci_wait_sync_cfg.cid = cci_cmd.cmd.wr_sync.sync_cfg.cid; cci_ctrl.cfg.cci_wait_sync_cfg.csid = cci_cmd.cmd.wr_sync.sync_cfg.csid; cci_ctrl.cfg.cci_wait_sync_cfg.line = cci_cmd.cmd.wr_sync.sync_cfg.line; cci_ctrl.cfg.cci_wait_sync_cfg.delay = cci_cmd.cmd.wr_sync.sync_cfg.delay; cci_ctrl.cmd = MSM_CCI_SET_SYNC_CID; CAM_ERR(CAM_CCI, "AIS_SENSOR_I2C_SET_SYNC_PARMS cid %d csid %d", cci_ctrl.cfg.cci_wait_sync_cfg.cid, cci_ctrl.cfg.cci_wait_sync_cfg.csid); rc = cam_cci_core_cfg(sd, &cci_ctrl); } break; } error: kfree(cci_ctrl.cci_info); return rc; }
drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_dev.c +0 −3 Original line number Diff line number Diff line Loading @@ -430,9 +430,6 @@ static int cam_cci_platform_probe(struct platform_device *pdev) g_cci_subdev[soc_info->index] = &new_cci_dev->v4l2_dev_str.sd; mutex_init(&(new_cci_dev->init_mutex)); new_cci_dev->cci_debug.cci_device = soc_info->index; new_cci_dev->cci_debug.cci_subdev = g_cci_subdev[soc_info->index]; CAM_INFO(CAM_CCI, "Device Type :%d", soc_info->index); cam_register_subdev_fops(&cci_v4l2_subdev_fops); Loading
drivers/media/platform/msm/ais/cam_sensor_module/cam_cci/cam_cci_dev.h +8 −1 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ enum cam_cci_cmd_type { MSM_CCI_GPIO_WRITE, MSM_CCI_I2C_WRITE_SYNC, MSM_CCI_I2C_WRITE_SYNC_BLOCK, MSM_CCI_I2C_WRITE_SYNC_ARRAY, }; enum cci_i2c_queue_t { Loading Loading @@ -217,6 +218,12 @@ struct cam_sensor_cci_client { uint16_t cci_device; }; struct cam_sensor_cci_sync_info { enum i2c_freq_mode i2c_freq_mode; uint16_t sid; }; /** * struct cci_device * @pdev: Platform device Loading Loading @@ -283,7 +290,6 @@ struct cci_device { bool is_burst_read; uint32_t irqs_disabled; struct mutex init_mutex; struct cam_sensor_cci_client cci_debug; }; struct cam_cci_ctrl { Loading @@ -295,6 +301,7 @@ struct cam_cci_ctrl { struct cam_cci_read_cfg cci_i2c_read_cfg; struct cam_cci_wait_sync_cfg cci_wait_sync_cfg; struct cam_cci_gpio_cfg gpio_cfg; struct ais_sensor_wr_sync cci_wr_sync; } cfg; }; Loading
include/uapi/media/ais_sensor.h +49 −5 File changed.Preview size limit exceeded, changes collapsed. Show changes