mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
camera: ois: read ois data in vsync irq thread
when vsync arrived, ois data has updated. read it in the vsync thread. Change-Id: I1bde6a76cf85d051cdd72bdff7a6df91364c906c Signed-off-by: liuwang2 <[email protected]> Reviewed-on: https://gerrit.mot.com/2143947 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: XiaoFeng Wang <[email protected]> Reviewed-by: Long Cheng <[email protected]> Reviewed-by: Zhichao Chen <[email protected]> Submit-Approved: Jira Key
This commit is contained in:
parent
8c97d184f6
commit
eb14c6118f
3 changed files with 161 additions and 108 deletions
|
|
@ -112,8 +112,9 @@ 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->previous_timestamp = 0;
|
||||
o_ctrl->current_timestamp = 0;
|
||||
o_ctrl->prev_timestamp = 0;
|
||||
o_ctrl->curr_timestamp = 0;
|
||||
o_ctrl->is_first_vsync = 1;
|
||||
|
||||
soc_private =
|
||||
(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
|
||||
|
|
@ -573,28 +574,6 @@ release_firmware:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cam_ois_write_dw(struct cam_ois_ctrl_t *o_ctrl)
|
||||
{
|
||||
struct cam_sensor_i2c_reg_setting i2c_reg_setting = {NULL,1,CAMERA_SENSOR_I2C_TYPE_WORD,CAMERA_SENSOR_I2C_TYPE_WORD,0};
|
||||
struct cam_sensor_i2c_reg_array i2c_write_settings = {0x70DA,0x0000,0,0};
|
||||
int32_t rc = 0;
|
||||
|
||||
if (!o_ctrl) {
|
||||
CAM_ERR(CAM_OIS, "Invalid Args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c_reg_setting.reg_setting = &(i2c_write_settings);
|
||||
|
||||
rc = camera_io_dev_write(&(o_ctrl->io_master_info),
|
||||
&(i2c_reg_setting));
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_OIS,
|
||||
"Failed in Applying i2c wrt settings");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* cam_ois_pkt_parse - Parse csl packet
|
||||
* @o_ctrl: ctrl structure
|
||||
|
|
@ -1164,10 +1143,8 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
|
|||
uint8_t *read_buff = NULL;
|
||||
uint32_t buff_length = 0;
|
||||
uint32_t read_length = 0;
|
||||
uint32_t i, size;
|
||||
uint8_t packetCounter = 0;
|
||||
uint32_t k = 0, remain_len = 0, read_len = 0;
|
||||
unsigned long flags;
|
||||
uint32_t size;
|
||||
unsigned long rem_jiffies = 0;
|
||||
|
||||
if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {
|
||||
rc = -EINVAL;
|
||||
|
|
@ -1235,82 +1212,46 @@ static int cam_ois_pkt_parse(struct cam_ois_ctrl_t *o_ctrl, void *arg)
|
|||
return rc;
|
||||
}
|
||||
} else if (i2c_list->op_code == CAM_SENSOR_I2C_READ_SEQ) {
|
||||
#define READ_BTYE 0xE
|
||||
read_buff = i2c_list->i2c_settings.read_buff;
|
||||
buff_length = i2c_list->i2c_settings.read_buff_len;
|
||||
read_length = i2c_list->i2c_settings.size;
|
||||
remain_len = read_length;
|
||||
read_len = READ_BTYE;
|
||||
packetCounter = 0;
|
||||
|
||||
if (read_length > buff_length) {
|
||||
CAM_ERR(CAM_SENSOR,
|
||||
"Invalid buffer size, readLen: %d, bufLen: %d",
|
||||
read_length, buff_length);
|
||||
delete_request(&i2c_read_settings);
|
||||
return -EINVAL;
|
||||
}
|
||||
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) && (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,
|
||||
read_buff + k*READ_BTYE,
|
||||
i2c_list->i2c_settings.addr_type,
|
||||
i2c_list->i2c_settings.data_type,
|
||||
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;
|
||||
}
|
||||
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 (k == 0 && read_buff[1] == 0) {
|
||||
CAM_WARN(CAM_OIS,"No-fatal: sample data is zero, break the loop read");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(timestampBufLen < sizeof(uint64_t)) {
|
||||
CAM_ERR(CAM_OIS, "Buffer not large enough for timestamp");
|
||||
delete_request(&i2c_read_settings);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!rc){
|
||||
if (read_buff[1] == 0){
|
||||
CAM_WARN(CAM_OIS,"No-fatal: header is zero, break the read");
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
} else if ((read_buff[1] != 0) && (packetCounter == 0)) {
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
mutex_lock(&(o_ctrl->vsync_mutex));
|
||||
memcpy((void *)timestampBuf,
|
||||
(void *)&o_ctrl->prev_timestamp,
|
||||
sizeof(uint64_t));
|
||||
|
||||
if(timestampBufLen < sizeof(uint64_t)) {
|
||||
CAM_ERR(CAM_OIS, "Buffer not large enough for timestamp");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
rc = cam_ois_write_dw(o_ctrl);
|
||||
usleep_range(1000, 1010);
|
||||
if (!rc){
|
||||
read_buff += i2c_list->i2c_settings.size;
|
||||
packetCounter--;
|
||||
} else {
|
||||
CAM_ERR(CAM_OIS,"Write failed rc: %d", rc);
|
||||
break;
|
||||
}
|
||||
} while(packetCounter);
|
||||
memcpy((void *)read_buff,
|
||||
(void *)o_ctrl->ois_data,
|
||||
sizeof(o_ctrl->ois_data));
|
||||
mutex_unlock(&(o_ctrl->vsync_mutex));
|
||||
} else if (i2c_list->op_code == CAM_SENSOR_I2C_POLL) {
|
||||
size = i2c_list->i2c_settings.size;
|
||||
for (i = 0; i < size; i++) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,28 @@
|
|||
#include "cam_debug_util.h"
|
||||
#include "camera_main.h"
|
||||
|
||||
static int cam_ois_clear_data_ready(struct cam_ois_ctrl_t *o_ctrl)
|
||||
{
|
||||
struct cam_sensor_i2c_reg_setting i2c_reg_setting = {NULL,1,CAMERA_SENSOR_I2C_TYPE_WORD,CAMERA_SENSOR_I2C_TYPE_WORD,0};
|
||||
struct cam_sensor_i2c_reg_array i2c_write_settings = {0x70DA,0x0000,0,0};
|
||||
int32_t rc = 0;
|
||||
|
||||
if (!o_ctrl) {
|
||||
CAM_ERR(CAM_OIS, "Invalid Args");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i2c_reg_setting.reg_setting = &(i2c_write_settings);
|
||||
|
||||
rc = camera_io_dev_write(&(o_ctrl->io_master_info), &(i2c_reg_setting));
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_OIS, "Failed in Applying i2c wrt settings");
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_OIS,"Clear data-ready success");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_ois_subdev_close_internal(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
|
|
@ -271,28 +293,109 @@ static int cam_ois_i2c_driver_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t ois_vsync_irq_handler(int irq, void *data)
|
||||
static irqreturn_t cam_ois_vsync_irq_thread(int irq, void *data)
|
||||
{
|
||||
struct cam_ois_ctrl_t *o_ctrl = data;
|
||||
int rc;
|
||||
uint64_t qtime_ns = 0;
|
||||
int rc = 0, handled = IRQ_NONE;
|
||||
uint64_t qtime_ns;
|
||||
uint8_t *read_buff, packet_cnt, sample_cnt;
|
||||
uint32_t k, read_len;
|
||||
|
||||
if (!mutex_trylock(&o_ctrl->vsync_mutex)) {
|
||||
CAM_ERR(CAM_OIS, "try lock fail, skip this irq");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
if (o_ctrl->cam_ois_state < CAM_OIS_CONFIG) {
|
||||
CAM_WARN(CAM_OIS, "Not in right state to read OIS: %d", o_ctrl->cam_ois_state);
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
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;
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_OIS, "vsync sof timestamp is %lld", qtime_ns);
|
||||
|
||||
spin_lock(&o_ctrl->ois_lock);
|
||||
o_ctrl->prev_timestamp = o_ctrl->curr_timestamp;
|
||||
o_ctrl->curr_timestamp = qtime_ns;
|
||||
|
||||
o_ctrl->previous_timestamp = o_ctrl->current_timestamp;
|
||||
o_ctrl->current_timestamp = qtime_ns;
|
||||
// when the first vsync arrived, clear data-ready, and return.
|
||||
if (o_ctrl->is_first_vsync) {
|
||||
o_ctrl->is_first_vsync = 0;
|
||||
rc = cam_ois_clear_data_ready(o_ctrl);
|
||||
udelay(1000);
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
spin_unlock(&o_ctrl->ois_lock);
|
||||
memset(o_ctrl->ois_data, 0, sizeof(o_ctrl->ois_data));
|
||||
read_buff = o_ctrl->ois_data;
|
||||
packet_cnt = 0;
|
||||
sample_cnt = 0;
|
||||
|
||||
return IRQ_HANDLED;
|
||||
do {
|
||||
// SM6375: CCI_VERSION_1_2_9 can only support read 0xE bytes data one time.
|
||||
// Each loop read max supported bytes(0xE). One packet(62 bytes) need 5 times loop read.
|
||||
for (k = 0; k < PACKET_BYTE/READ_BYTE + 1; k++) {
|
||||
if (k == PACKET_BYTE/READ_BYTE)
|
||||
read_len = PACKET_BYTE%READ_BYTE;
|
||||
else
|
||||
read_len = READ_BYTE;
|
||||
|
||||
rc = camera_io_dev_read_seq(
|
||||
&o_ctrl->io_master_info,
|
||||
PACKET_ADDR + k*READ_BYTE/2,
|
||||
read_buff + k*READ_BYTE,
|
||||
CAMERA_SENSOR_I2C_TYPE_WORD,
|
||||
CAMERA_SENSOR_I2C_TYPE_WORD,
|
||||
read_len);
|
||||
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_OIS, "Failed: seq read I2C settings: %d", rc);
|
||||
goto release_mutex;
|
||||
}
|
||||
|
||||
if (k == 0 && packet_cnt == 0) {
|
||||
sample_cnt = read_buff[1];
|
||||
if (sample_cnt != 0) {
|
||||
packet_cnt = (sample_cnt + 9)/10;
|
||||
CAM_DBG(CAM_OIS,"sample data = 0x%x, packet_cnt = %d", sample_cnt, packet_cnt);
|
||||
} else {
|
||||
CAM_WARN(CAM_OIS,"No-fatal: sample data is zero, break the loop read");
|
||||
goto release_mutex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sample_cnt > 10 && packet_cnt > 1) {
|
||||
CAM_DBG(CAM_OIS,"more than 1 packet, clear data-ready and read next packet");
|
||||
rc = cam_ois_clear_data_ready(o_ctrl);
|
||||
udelay(1000);
|
||||
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_OIS,"Write failed rc: %d", rc);
|
||||
goto release_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
packet_cnt--;
|
||||
read_buff += PACKET_BYTE;
|
||||
} while(packet_cnt);
|
||||
|
||||
release_mutex:
|
||||
if (rc < 0) {
|
||||
memset(o_ctrl->ois_data, 0, sizeof(o_ctrl->ois_data));
|
||||
handled = IRQ_NONE;
|
||||
} else
|
||||
handled = IRQ_HANDLED;
|
||||
|
||||
mutex_unlock(&(o_ctrl->vsync_mutex));
|
||||
|
||||
complete(&o_ctrl->ois_data_complete);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int cam_ois_component_bind(struct device *dev,
|
||||
|
|
@ -356,7 +459,8 @@ 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);
|
||||
mutex_init(&(o_ctrl->vsync_mutex));
|
||||
init_completion(&o_ctrl->ois_data_complete);
|
||||
|
||||
if (o_ctrl->is_ois_vsync_irq_supported) {
|
||||
o_ctrl->vsync_irq = platform_get_irq_optional(pdev, 0);
|
||||
|
|
@ -367,7 +471,7 @@ static int cam_ois_component_bind(struct device *dev,
|
|||
rc = devm_request_threaded_irq(dev,
|
||||
o_ctrl->vsync_irq,
|
||||
NULL,
|
||||
ois_vsync_irq_handler,
|
||||
cam_ois_vsync_irq_thread,
|
||||
(IRQF_TRIGGER_RISING | IRQF_ONESHOT),
|
||||
"ois-vsync-irq",
|
||||
o_ctrl);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
#define DEFINE_MSM_MUTEX(mutexname) \
|
||||
static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
|
||||
|
||||
#define PACKET_ADDR 0x70B0
|
||||
#define PACKET_BYTE 62
|
||||
#define MAX_PACKET 3
|
||||
#define READ_BYTE 0xE
|
||||
|
||||
enum cam_ois_state {
|
||||
CAM_OIS_INIT,
|
||||
CAM_OIS_ACQUIRE,
|
||||
|
|
@ -142,12 +147,15 @@ 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 previous_timestamp;
|
||||
uint64_t current_timestamp;
|
||||
uint64_t prev_timestamp;
|
||||
uint64_t curr_timestamp;
|
||||
struct cam_ois_opcode opcode;
|
||||
bool is_ois_vsync_irq_supported;
|
||||
int vsync_irq;
|
||||
spinlock_t ois_lock;
|
||||
struct mutex vsync_mutex;
|
||||
struct completion ois_data_complete;
|
||||
bool is_first_vsync;
|
||||
uint8_t ois_data[PACKET_BYTE*MAX_PACKET];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue