mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-24 21:54:34 -04:00
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:
parent
eb0fb12d7f
commit
38d2fda173
4 changed files with 276 additions and 9 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue