camera: ois: add aw86006 active eis

[detail]
aw86006 add active eis

Change-Id: I80b988becb9a47910251f9e80ebf0e40dbd856ac
Signed-off-by: liuwang2 <liuwang2@lenovo.com>
Reviewed-on: https://gerrit.mot.com/2263679
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: <zhaoxy41@motorola.com>
Reviewed-by: XiaoFeng Wang <wangxf32@lenovo.com>
Reviewed-by: <chenlj26@motorola.com>
Reviewed-by: Zhichao Chen <chenzc2@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
liuwang2 2022-05-09 18:09:20 +08:00 • committed by zhaoji1
commit 38d2fda173
4 changed files with 276 additions and 9 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;
};
/**

View file

@ -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
};