msm: camera: sensor: I2C poll implementation

Remove additional delay after poll.
Delay in ms is acounted during polling the register.
If read is successful and match fails,
then poll is non-fatal.

CRs-Fixed: 971014
Change-Id: I655a272bed125edc2dc60504640f1d57652a64e2
Signed-off-by: Rajesh Bondugula <rajeshb@codeaurora.org>
This commit is contained in:
Rajesh Bondugula 2016-02-02 17:07:07 -08:00 committed by David Keitel
parent db36660f6c
commit b15dc12577
6 changed files with 90 additions and 73 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -156,7 +156,7 @@ static int msm_actuator_bivcm_handle_i2c_ops(
uint32_t hw_dword = hw_params;
uint16_t i2c_byte1 = 0, i2c_byte2 = 0;
uint16_t value = 0, reg_data = 0;
uint32_t size = a_ctrl->reg_tbl_size, i = 0, j = 0;
uint32_t size = a_ctrl->reg_tbl_size, i = 0;
int32_t rc = 0;
struct msm_camera_i2c_reg_array i2c_tbl;
struct msm_camera_i2c_reg_setting reg_setting;
@ -266,23 +266,17 @@ static int msm_actuator_bivcm_handle_i2c_ops(
write_arr[i].addr_type);
break;
}
for (j = 0; j < ACTUATOR_MAX_POLL_COUNT; j++) {
rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
&a_ctrl->i2c_client,
write_arr[i].reg_addr,
write_arr[i].reg_data,
write_arr[i].data_type);
if (rc == 1)
continue;
if (rc < 0) {
pr_err("i2c poll error:%d\n", rc);
return rc;
}
break;
rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
&a_ctrl->i2c_client,
write_arr[i].reg_addr,
write_arr[i].reg_data,
write_arr[i].data_type,
write_arr[i].delay);
if (rc < 0) {
pr_err("i2c poll error:%d\n", rc);
return rc;
}
if (j == ACTUATOR_MAX_POLL_COUNT)
CDBG("%s:%d Poll register not as expected\n",
__func__, __LINE__);
break;
case MSM_ACTUATOR_READ_WRITE:
i2c_tbl.reg_addr = write_arr[i].reg_addr;
@ -386,13 +380,19 @@ static int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
settings[i].reg_addr,
settings[i].reg_data,
settings[i].data_type);
if (settings[i].delay > 20)
msleep(settings[i].delay);
else if (0 != settings[i].delay)
usleep_range(settings[i].delay * 1000,
(settings[i].delay * 1000) + 1000);
break;
case MSM_ACT_POLL:
rc = a_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
&a_ctrl->i2c_client,
settings[i].reg_addr,
settings[i].reg_data,
settings[i].data_type);
settings[i].data_type,
settings[i].delay);
break;
default:
pr_err("Unsupport i2c_operation: %d\n",
@ -400,9 +400,6 @@ static int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
break;
}
if (0 != settings[i].delay)
msleep(settings[i].delay);
if (rc < 0) {
pr_err("%s:%d fail addr = 0X%X, data = 0X%X, dt = %d",
__func__, __LINE__, settings[i].reg_addr,

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -194,8 +194,8 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl,
e_ctrl->i2c_client.addr_type = emap[j].poll.addr_t;
rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
&(e_ctrl->i2c_client), emap[j].poll.addr,
emap[j].poll.data, emap[j].poll.data_t);
msleep(emap[j].poll.delay);
emap[j].poll.data, emap[j].poll.data_t,
emap[j].poll.delay);
if (rc < 0) {
pr_err("%s: poll failed\n", __func__);
return rc;
@ -380,8 +380,8 @@ static int eeprom_parse_memory_map(struct msm_eeprom_ctrl_t *e_ctrl,
&(e_ctrl->i2c_client),
eeprom_map->mem_settings[i].reg_addr,
eeprom_map->mem_settings[i].reg_data,
eeprom_map->mem_settings[i].data_type);
msleep(eeprom_map->mem_settings[i].delay);
eeprom_map->mem_settings[i].data_type,
eeprom_map->mem_settings[i].delay);
if (rc < 0) {
pr_err("%s: poll failed\n",
__func__);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -18,10 +18,6 @@
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args)
#define I2C_COMPARE_MATCH 0
#define I2C_COMPARE_MISMATCH 1
#define I2C_POLL_MAX_ITERATION 20
int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t *data,
enum msm_camera_i2c_data_type data_type)
@ -384,14 +380,34 @@ static int32_t msm_camera_cci_i2c_compare(struct msm_camera_i2c_client *client,
int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
enum msm_camera_i2c_data_type data_type, uint32_t delay_ms)
{
int32_t rc;
int32_t i = 0;
S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
__func__, addr, data, data_type);
rc = msm_camera_cci_i2c_compare(client,
addr, data, data_type);
if (delay_ms > MAX_POLL_DELAY_MS) {
pr_err("%s:%d invalid delay = %d max_delay = %d\n",
__func__, __LINE__, delay_ms, MAX_POLL_DELAY_MS);
return -EINVAL;
}
for (i = 0; i < delay_ms; i++) {
rc = msm_camera_cci_i2c_compare(client,
addr, data, data_type);
if (!rc)
return rc;
usleep_range(1000, 1010);
}
/* If rc is 1 then read is successful but poll is failure */
if (rc == 1)
pr_err("%s:%d poll failed rc=%d(non-fatal)\n",
__func__, __LINE__, rc);
if (rc < 0)
pr_err("%s:%d poll failed rc=%d\n", __func__, __LINE__, rc);
return rc;
}
@ -465,7 +481,7 @@ int32_t msm_camera_cci_i2c_write_conf_tbl(
rc = msm_camera_cci_i2c_poll(client,
reg_conf_tbl->reg_addr,
reg_conf_tbl->reg_data,
reg_conf_tbl->dt);
reg_conf_tbl->dt, I2C_POLL_TIME_MS);
} else {
if (reg_conf_tbl->dt == 0)
dt = data_type;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -17,6 +17,12 @@
#include <media/v4l2-subdev.h>
#include <media/msm_cam_sensor.h>
#define I2C_POLL_TIME_MS 5
#define MAX_POLL_DELAY_MS 100
#define I2C_COMPARE_MATCH 0
#define I2C_COMPARE_MISMATCH 1
struct msm_camera_i2c_client {
struct msm_camera_i2c_fn_t *i2c_func_tbl;
struct i2c_client *client;
@ -47,7 +53,7 @@ struct msm_camera_i2c_fn_t {
enum msm_camera_i2c_data_type data_type);
int32_t (*i2c_poll)(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
enum msm_camera_i2c_data_type data_type, uint32_t delay_ms);
int32_t (*i2c_read_burst)(struct msm_camera_i2c_client *client,
uint32_t read_byte, uint8_t *buffer, uint32_t addr,
enum msm_camera_i2c_data_type data_type);
@ -111,7 +117,7 @@ int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
enum msm_camera_i2c_data_type data_type, uint32_t delay_ms);
int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t *data,
@ -144,6 +150,6 @@ int32_t msm_camera_qup_i2c_write_conf_tbl(
int32_t msm_camera_qup_i2c_poll(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
enum msm_camera_i2c_data_type data_type, uint32_t delay_ms);
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011, 2013-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011, 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -22,10 +22,6 @@
#define S_I2C_DBG(fmt, args...) do { } while (0)
#endif
#define I2C_COMPARE_MATCH 0
#define I2C_COMPARE_MISMATCH 1
#define I2C_POLL_MAX_ITERATION 20
static int32_t msm_camera_qup_i2c_rxdata(
struct msm_camera_i2c_client *dev_client, unsigned char *rxdata,
int data_length)
@ -342,8 +338,8 @@ int32_t msm_camera_qup_i2c_write_table_w_microdelay(
return rc;
}
static int32_t msm_camera_qup_i2c_compare(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
static int32_t msm_camera_qup_i2c_compare(
struct msm_camera_i2c_client *client, uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
@ -400,19 +396,30 @@ static int32_t msm_camera_qup_i2c_compare(struct msm_camera_i2c_client *client,
int32_t msm_camera_qup_i2c_poll(struct msm_camera_i2c_client *client,
uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
enum msm_camera_i2c_data_type data_type, uint32_t delay_ms)
{
int32_t rc;
int i;
S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
__func__, addr, data, data_type);
for (i = 0; i < I2C_POLL_MAX_ITERATION; i++) {
if (delay_ms > MAX_POLL_DELAY_MS) {
pr_err("%s:%d invalid delay = %d max_delay = %d\n",
__func__, __LINE__, delay_ms, MAX_POLL_DELAY_MS);
return -EINVAL;
}
for (i = 0; i < delay_ms; i++) {
rc = msm_camera_qup_i2c_compare(client,
addr, data, data_type);
if (rc == 0 || rc < 0)
if (rc < 0) {
pr_err("%s:%d qup_i2c_compare failed rc = %d", __func__,
__LINE__, rc);
break;
usleep_range(10000, 11000);
}
if (rc == I2C_COMPARE_MISMATCH)
break;
usleep_range(1000, 1010);
}
return rc;
}
@ -489,7 +496,7 @@ int32_t msm_camera_qup_i2c_write_conf_tbl(
rc = msm_camera_qup_i2c_poll(client,
reg_conf_tbl->reg_addr,
reg_conf_tbl->reg_data,
reg_conf_tbl->dt);
reg_conf_tbl->dt, I2C_POLL_TIME_MS);
} else {
if (reg_conf_tbl->dt == 0)
dt = data_type;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -26,8 +26,6 @@ DEFINE_MSM_MUTEX(msm_ois_mutex);
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#endif
#define MAX_POLL_COUNT 100
static struct v4l2_file_operations msm_ois_v4l2_subdev_fops;
static int32_t msm_ois_power_up(struct msm_ois_ctrl_t *o_ctrl);
static int32_t msm_ois_power_down(struct msm_ois_ctrl_t *o_ctrl);
@ -90,26 +88,25 @@ static int32_t msm_ois_write_settings(struct msm_ois_ctrl_t *o_ctrl,
settings[i].data_type);
break;
}
if (settings[i].delay > 20)
msleep(settings[i].delay);
else if (0 != settings[i].delay)
usleep_range(settings[i].delay * 1000,
(settings[i].delay * 1000) + 1000);
}
break;
case MSM_OIS_POLL: {
int32_t poll_count = 0;
switch (settings[i].data_type) {
case MSM_CAMERA_I2C_BYTE_DATA:
case MSM_CAMERA_I2C_WORD_DATA:
do {
rc = o_ctrl->i2c_client.i2c_func_tbl
->i2c_poll(&o_ctrl->i2c_client,
settings[i].reg_addr,
settings[i].reg_data,
settings[i].data_type);
if (poll_count++ > MAX_POLL_COUNT) {
pr_err("MSM_OIS_POLL failed");
break;
}
} while (rc != 0);
rc = o_ctrl->i2c_client.i2c_func_tbl
->i2c_poll(&o_ctrl->i2c_client,
settings[i].reg_addr,
settings[i].reg_data,
settings[i].data_type,
settings[i].delay);
break;
default:
@ -120,12 +117,6 @@ static int32_t msm_ois_write_settings(struct msm_ois_ctrl_t *o_ctrl,
}
}
if (settings[i].delay > 20)
msleep(settings[i].delay);
else if (0 != settings[i].delay)
usleep_range(settings[i].delay * 1000,
(settings[i].delay * 1000) + 1000);
if (rc < 0)
break;
}