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 d2663140d005..ff18135c2d52 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_core.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_core.c @@ -112,7 +112,8 @@ static int cam_ois_power_up(struct cam_ois_ctrl_t *o_ctrl) &o_ctrl->soc_info; struct cam_ois_soc_private *soc_private; struct cam_sensor_power_ctrl_t *power_info; - o_ctrl->prevTimeStamp = 0; + o_ctrl->previous_timestamp = 0; + o_ctrl->current_timestamp = 0; soc_private = (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private; @@ -1157,7 +1158,6 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) struct i2c_settings_array i2c_read_settings; uintptr_t buf_addr = 0x0; size_t buf_size = 0; - uint64_t timestamp, qtime_ns; uint8_t *timestampBuf; uint32_t timestampBufLen; struct i2c_settings_list *i2c_list; @@ -1167,6 +1167,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) uint32_t i, size; uint8_t packetCounter = 0; uint32_t k = 0, remain_len = 0, read_len = 0; + unsigned long flags; if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) { rc = -EINVAL; @@ -1251,7 +1252,7 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) do { // SM6375: CCI_VERSION_1_2_9 can only support read 0xE bytes data one time. // Each loop read max supported bytes(0xE), to save read time. - for (k = 0; k < read_length/READ_BTYE + 1; k++) { + for (k = 0; (k < read_length/READ_BTYE + 1) && (read_len != 0); k++) { rc = camera_io_dev_read_seq( &o_ctrl->io_master_info, i2c_list->i2c_settings.reg_setting[0].reg_addr + k*READ_BTYE/2, @@ -1261,33 +1262,26 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) read_len); remain_len -= read_len; read_len = remain_len > READ_BTYE ? READ_BTYE:remain_len; + + if (rc < 0) { + CAM_ERR(CAM_OIS, "Failed: seq read I2C settings: %d", rc); + delete_request(&i2c_read_settings); + return rc; + } + + if (k == 0 && read_buff[1] == 0) { + CAM_WARN(CAM_OIS,"No-fatal: sample data is zero, break the loop read"); + break; + } } - if (rc < 0) { - CAM_ERR(CAM_SENSOR, - "failed: seq read I2C settings: %d", - rc); - delete_request(&i2c_read_settings); - return rc; - } if (!rc){ if (read_buff[1] == 0){ - CAM_ERR(CAM_OIS,"Header is zero, break the read"); + CAM_WARN(CAM_OIS,"No-fatal: header is zero, break the read"); rc = -EINVAL; break; } else if ((read_buff[1] != 0) && (packetCounter == 0)) { - //TODO: change to use interrupt - timestamp = o_ctrl->prevTimeStamp; - - rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns); - if (rc < 0) { - CAM_ERR(CAM_SENSOR, "failed to get qtimer rc:%d"); - return rc; - } - - o_ctrl->prevTimeStamp = qtime_ns; - 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]; @@ -1297,7 +1291,12 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg) CAM_ERR(CAM_OIS, "Buffer not large enough for timestamp"); return -EINVAL; } - memcpy((void *)timestampBuf, (void *)×tamp, sizeof(uint64_t)); + + spin_lock_irqsave(&o_ctrl->ois_lock, flags); + memcpy((void *)timestampBuf, + (void *)&o_ctrl->previous_timestamp, + sizeof(uint64_t)); + spin_unlock_irqrestore(&o_ctrl->ois_lock, flags); packetCounter = (read_buff[1] + 9)/10; } 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 aa771b3bd14d..02ef393d348b 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.c @@ -271,6 +271,30 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client) return 0; } +static irqreturn_t ois_vsync_irq_handler(int irq, void *data) +{ + struct cam_ois_ctrl_t *o_ctrl = data; + int rc; + uint64_t qtime_ns = 0; + + rc = cam_sensor_util_get_current_qtimer_ns(&qtime_ns); + if (rc < 0) { + CAM_ERR(CAM_OIS, "failed to get qtimer rc:%d"); + return IRQ_NONE; + } + + CAM_DBG(CAM_OIS, "vsync sof timestamp is %lld", qtime_ns); + + spin_lock(&o_ctrl->ois_lock); + + o_ctrl->previous_timestamp = o_ctrl->current_timestamp; + o_ctrl->current_timestamp = qtime_ns; + + spin_unlock(&o_ctrl->ois_lock); + + return IRQ_HANDLED; +} + static int cam_ois_component_bind(struct device *dev, struct device *master_dev, void *data) { @@ -331,6 +355,30 @@ static int cam_ois_component_bind(struct device *dev, platform_set_drvdata(pdev, o_ctrl); o_ctrl->cam_ois_state = CAM_OIS_INIT; + + spin_lock_init(&o_ctrl->ois_lock); + + if (o_ctrl->is_ois_vsync_irq_supported) { + o_ctrl->vsync_irq = platform_get_irq_optional(pdev, 0); + + 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, + ois_vsync_irq_handler, + (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 + CAM_DBG(CAM_OIS, "request ois-vsync IRQ success"); + } else + CAM_ERR(CAM_OIS, "failed: to get ois-vsync IRQ"); + } + CAM_DBG(CAM_OIS, "Component bound successfully"); return rc; unreg_subdev: 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 3097f36c2763..aad789519799 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_dev.h @@ -142,8 +142,12 @@ struct cam_ois_ctrl_t { uint8_t ois_fw_inc_addr; uint8_t ois_fw_addr_type; uint8_t ois_fw_data_type; - uint64_t prevTimeStamp; + uint64_t previous_timestamp; + uint64_t current_timestamp; struct cam_ois_opcode opcode; + bool is_ois_vsync_irq_supported; + int vsync_irq; + spinlock_t ois_lock; }; /** diff --git a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c index 510c81d9e9f3..59af6b297bd2 100644 --- a/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c +++ b/drivers/cam_sensor_module/cam_ois/cam_ois_soc.c @@ -34,6 +34,14 @@ static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl) o_ctrl->ois_device_type); return -EINVAL; } + + if (!of_property_read_bool(of_node, "vsync-irq-support")) { + o_ctrl->is_ois_vsync_irq_supported = false; + } else { + o_ctrl->is_ois_vsync_irq_supported = true; + } + CAM_DBG(CAM_OIS, "is_ois_vsync_irq_supported %d", o_ctrl->is_ois_vsync_irq_supported); + rc = cam_soc_util_get_dt_properties(soc_info); if (rc < 0) { CAM_ERR(CAM_OIS, "cam_soc_util_get_dt_properties rc %d",