diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c index 8154c7695d67..2c5b66db9e67 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -116,6 +116,8 @@ static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl) o_ctrl->prev_timestamp = 0; o_ctrl->curr_timestamp = 0; o_ctrl->is_first_vsync = 1; + o_ctrl->is_video_mode = false; + o_ctrl->is_need_eis_data = false; o_ctrl->q_timer_cnt = QTIMER_SAMPLE_TIME*10*2; o_ctrl->mono_timestamp = 0; @@ -289,6 +291,13 @@ static int cam_ois_apply_settings(struct cam_ois_ctrl_t *o_ctrl, "Failed in Applying i2c wrt settings"); return rc; } + if (o_ctrl->ic_name != NULL && strstr(o_ctrl->ic_name, "aw86006")) { + if (i2c_list->i2c_settings.reg_setting[0].reg_addr == AW86006_PACKET_ENABLE && + i2c_list->i2c_settings.reg_setting[0].reg_data == 0x01) + o_ctrl->is_video_mode = true; + else + o_ctrl->is_video_mode = false; + } } else if (i2c_list->op_code == CAM_SENSOR_I2C_WRITE_SEQ) { rc = camera_io_dev_write_continuous( &(o_ctrl->io_master_info), @@ -938,6 +947,9 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) o_ctrl->cam_ois_state); return rc; } + + o_ctrl->is_need_eis_data = false; + offset = (uint32_t *)&csl_packet->payload; offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); cmd_desc = (struct cam_cmd_buf_desc *)(offset); @@ -1361,6 +1373,131 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) } break; } + case CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_AW86006: { + struct cam_buf_io_cfg *io_cfg; + struct cam_buf_io_cfg *timestamp_io_cfg; + struct i2c_settings_array i2c_read_settings; + uintptr_t buf_addr = 0x0; + size_t buf_size = 0; + uint8_t *timestampBuf; + uint32_t timestampBufLen; + struct i2c_settings_list *i2c_list; + uint8_t *read_buff = NULL; + uint32_t buff_length = 0; + uint32_t read_length = 0; + unsigned long rem_jiffies = 0; + + o_ctrl->is_need_eis_data = true; + + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { + rc = -EINVAL; + CAM_WARN(CAM_OIS, + "Not in right state to read OIS: %d", + o_ctrl->cam_ois_state); + return rc; + } + CAM_DBG(CAM_OIS, "number of I/O configs: %d:", + csl_packet->num_io_configs); + if (csl_packet->num_io_configs < 2) { + CAM_ERR(CAM_OIS, "Not enough I/O Configs"); + rc = -EINVAL; + return rc; + } + + INIT_LIST_HEAD(&(i2c_read_settings.list_head)); + + io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) + &csl_packet->payload + + csl_packet->io_configs_offset); + + if (io_cfg == NULL) { + CAM_ERR(CAM_OIS, "I/O config is invalid(NULL)"); + rc = -EINVAL; + return rc; + } + + timestamp_io_cfg = &io_cfg[1]; + + if (timestamp_io_cfg == NULL) { + CAM_ERR(CAM_OIS, "timestamp I/O config is invalid(NULL)"); + rc = -EINVAL; + return rc; + } + + offset = (uint32_t *)&csl_packet->payload; + offset += (csl_packet->cmd_buf_offset / sizeof(uint32_t)); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + if (cmd_desc == NULL) { + CAM_ERR(CAM_OIS, "cmd desc is invalid(NULL)"); + rc = -EINVAL; + return rc; + } + + i2c_read_settings.is_settings_valid = 1; + i2c_read_settings.request_id = 0; + rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info, + &i2c_read_settings, + cmd_desc, 1, io_cfg); + if (rc < 0) { + CAM_ERR(CAM_OIS, "OIS read pkt parsing failed: %d", rc); + return rc; + } + + list_for_each_entry(i2c_list, + &(i2c_read_settings.list_head), list) { + if (i2c_list->op_code == CAM_SENSOR_I2C_READ_SEQ) { + read_buff = i2c_list->i2c_settings.read_buff; + buff_length = i2c_list->i2c_settings.read_buff_len; + read_length = i2c_list->i2c_settings.size; + + CAM_DBG(CAM_OIS, "buff_length = %d, read_length = %d", buff_length, read_length); + + if (read_length > buff_length || buff_length < RING_BUFFER_LEN) { + CAM_ERR(CAM_SENSOR, + "Invalid buffer size, readLen: %d, bufLen: %d", + read_length, buff_length); + delete_request(&i2c_read_settings); + return -EINVAL; + } + + rc = cam_mem_get_cpu_buf(timestamp_io_cfg->mem_handle[0], + &buf_addr, &buf_size); + timestampBuf = (uint8_t *)buf_addr + timestamp_io_cfg->offsets[0]; + timestampBufLen = buf_size - timestamp_io_cfg->offsets[0]; + + if(timestampBufLen < sizeof(uint64_t)) { + CAM_ERR(CAM_OIS, "Buffer not large enough for timestamp"); + delete_request(&i2c_read_settings); + return -EINVAL; + } + + rem_jiffies = wait_for_completion_timeout(&o_ctrl->ois_data_complete, + msecs_to_jiffies(120)); + if (rem_jiffies == 0) { + CAM_ERR(CAM_OIS, "Wait ois data completion timeout 120 ms"); + delete_request(&i2c_read_settings); + return -ETIMEDOUT; + } + + mutex_lock(&(o_ctrl->vsync_mutex)); + memcpy((void *)timestampBuf, (void *)&o_ctrl->prev_timestamp, sizeof(uint64_t)); + + if (o_ctrl->ring_buff_size <= buff_length) + memcpy((void *)read_buff, (void *)o_ctrl->ring_buff, o_ctrl->ring_buff_size); + else + memcpy((void *)read_buff, (void *)o_ctrl->ring_buff, buff_length); + + mutex_unlock(&(o_ctrl->vsync_mutex)); + } + } + rc = delete_request(&i2c_read_settings); + if (rc < 0) { + CAM_ERR(CAM_OIS, + "Failed in deleting the read settings"); + return rc; + } + break; + } case CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_DONGWOON_QTIMER: { struct cam_buf_io_cfg *io_cfg; struct cam_buf_io_cfg *timestamp_io_cfg; diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c index f19832eaa824..63c507a2993d 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -296,6 +296,105 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client) return 0; } +static irqreturn_t cam_aw86006_ois_vsync_irq_thread(int irq, void *data) +{ + struct cam_ois_ctrl_t *o_ctrl = data; + int rc = -EINVAL, handled = IRQ_NONE, sample_cnt = 0, delay_time = 0; + uint64_t mono_time_ns; + struct timespec64 ts; + uint8_t *read_buff; + uint32_t k, read_len; + + if (!o_ctrl) { + CAM_ERR(CAM_OIS, "Invalid Args"); + return IRQ_NONE; + } + + if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { + CAM_WARN(CAM_OIS, "Not in right state to read Eis data: %d", o_ctrl->cam_ois_state); + return IRQ_NONE; + } + + if (o_ctrl->is_video_mode == false || + o_ctrl->is_need_eis_data == false) { + CAM_DBG(CAM_OIS, "No need to read Eis data: %d %d", o_ctrl->is_video_mode, o_ctrl->is_need_eis_data); + return IRQ_NONE; + } + + if (!mutex_trylock(&o_ctrl->vsync_mutex)) { + CAM_WARN(CAM_OIS, "try to get mutex fail, skip this irq"); + return IRQ_NONE; + } + + ktime_get_boottime_ts64(&ts); + mono_time_ns = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec); + + CAM_DBG(CAM_OIS, "aw86006 ois vsync sof mono timestamp is %lld", mono_time_ns); + + o_ctrl->prev_timestamp = o_ctrl->curr_timestamp; + o_ctrl->curr_timestamp = mono_time_ns; + + // when the first vsync arrived, return + if (o_ctrl->is_first_vsync) { + o_ctrl->is_first_vsync = 0; + rc = -EINVAL; + goto release_mutex; + } + + memset(o_ctrl->ring_buff, 0, o_ctrl->ring_buff_size); + read_buff = o_ctrl->ring_buff; + + for (k = 0; k < RING_BUFFER_LEN/READ_BYTE + 1; k++) { + if (k == RING_BUFFER_LEN/READ_BYTE) + read_len = RING_BUFFER_LEN%READ_BYTE; + else + read_len = READ_BYTE; + + if (read_len == 0) { + CAM_WARN(CAM_OIS, "read length is 0, break loop read"); + break; + } + + rc = camera_io_dev_ois_read_seq( + &o_ctrl->io_master_info, + AW86006_PACKET_ADDR, + read_buff + k*READ_BYTE, + CAMERA_SENSOR_I2C_TYPE_WORD, + CAMERA_SENSOR_I2C_TYPE_BYTE, + read_len); + + if (rc < 0) { + CAM_ERR(CAM_OIS, "failed to read ois data: %d", rc); + goto release_mutex; + } + } + + sample_cnt = read_buff[0]; + delay_time = read_buff[1]; + + CAM_DBG(CAM_OIS,"sample_cnt = %d, delay_time = %d (100 us)", sample_cnt, delay_time); + + if (sample_cnt == 0 || sample_cnt > AW86006_MAX_SAMPLE) { + CAM_WARN(CAM_OIS,"sample_cnt %d is invalid, skip the data", sample_cnt); + rc = -EINVAL; + goto release_mutex; + } + +release_mutex: + if (rc < 0) { + memset(o_ctrl->ring_buff, 0, o_ctrl->ring_buff_size); + handled = IRQ_NONE; + } else + handled = IRQ_HANDLED; + + mutex_unlock(&(o_ctrl->vsync_mutex)); + + if (rc >= 0) + complete(&o_ctrl->ois_data_complete); + + return handled; +} + static irqreturn_t cam_ois_vsync_irq_thread(int irq, void *data) { struct cam_ois_ctrl_t *o_ctrl = data; @@ -463,11 +562,16 @@ static int cam_ois_component_bind(struct device *dev, o_ctrl->soc_info.dev_name = pdev->name; o_ctrl->ois_device_type = MSM_CAMERA_PLATFORM_DEVICE; - o_ctrl->ois_data_size = PACKET_BYTE*MAX_PACKET; + o_ctrl->ring_buff_size = RING_BUFFER_LEN; + o_ctrl->ring_buff = kzalloc(o_ctrl->ring_buff_size, GFP_KERNEL); + if (!o_ctrl->ring_buff) + goto free_o_ctrl; + + o_ctrl->ois_data_size = PACKET_BYTE*MAX_PACKET; o_ctrl->ois_data = kzalloc(o_ctrl->ois_data_size, GFP_KERNEL); if (!o_ctrl->ois_data) - goto free_o_ctrl; + goto free_ring_buff; o_ctrl->io_master_info.master_type = CCI_MASTER; o_ctrl->io_master_info.cci_client = kzalloc( @@ -524,13 +628,24 @@ static int cam_ois_component_bind(struct device *dev, if (o_ctrl->vsync_irq > 0) { CAM_DBG(CAM_OIS, "get ois-vsync irq: %d", o_ctrl->vsync_irq); - rc = devm_request_threaded_irq(dev, - o_ctrl->vsync_irq, - NULL, - cam_ois_vsync_irq_thread, - (IRQF_TRIGGER_RISING | IRQF_ONESHOT), - "ois-vsync-irq", - o_ctrl); + if (o_ctrl->ic_name != NULL && strstr(o_ctrl->ic_name, "aw86006")) { + rc = devm_request_threaded_irq(dev, + o_ctrl->vsync_irq, + NULL, + cam_aw86006_ois_vsync_irq_thread, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), + "aw86006-vsync-irq", + o_ctrl); + } else { + rc = devm_request_threaded_irq(dev, + o_ctrl->vsync_irq, + NULL, + cam_ois_vsync_irq_thread, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), + "ois-vsync-irq", + o_ctrl); + } + if (rc != 0) CAM_ERR(CAM_OIS, "failed: to request ois-vsync IRQ %d, rc %d", o_ctrl->vsync_irq, rc); else @@ -549,6 +664,8 @@ free_cci_client: kfree(o_ctrl->io_master_info.cci_client); free_ois_data: kfree(o_ctrl->ois_data); +free_ring_buff: + kfree(o_ctrl->ring_buff); free_o_ctrl: kfree(o_ctrl); return rc; @@ -590,6 +707,7 @@ static void cam_ois_component_unbind(struct device *dev, kfree(o_ctrl->soc_info.soc_private); kfree(o_ctrl->io_master_info.cci_client); kfree(o_ctrl->ois_data); + kfree(o_ctrl->ring_buff); platform_set_drvdata(pdev, NULL); v4l2_set_subdevdata(&o_ctrl->v4l2_dev_str.sd, NULL); kfree(o_ctrl); diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h index 45ec896baa48..9427cbff4623 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -37,6 +37,13 @@ #define QTIMER_SAMPLE_TIME 2 #define QTIMER_MAX_SAMPLE 20 +/* AW86006 EIS */ +#define RING_BUFFER_LEN 42 +#define AW86006_PACKET_ENABLE 0x0003 +#define AW86006_PACKET_ADDR 0x0006 +#define AW86006_MAX_SAMPLE 10 + + enum cam_ois_state { CAM_OIS_INIT, CAM_OIS_ACQUIRE, @@ -179,6 +186,10 @@ struct cam_ois_ctrl_t { struct work_struct aw_fw_update_work; struct mutex aw_ois_mutex; struct awrw_ctrl *awrw_ctrl; + uint8_t *ring_buff; + int ring_buff_size; + bool is_video_mode; + bool is_need_eis_data; }; /** diff --git a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index b6678389397e..13131a75a94d 100644 --- a/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -178,6 +178,7 @@ enum cam_ois_packet_opcodes { CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_ROHM, CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_DONGWOON, CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_DONGWOON_QTIMER, + CAM_OIS_PACKET_OPCODE_ACTIVE_OIS_AW86006, CAM_OIS_PACKET_OPCODE_OIS_GYRO_OFFSET };