media: rk-isp10: Fix AE information is not correct when updating exposure by each frame

Change-Id: Ibec00465ff42f2e985e9d2ec6b54bb2294830484
Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
This commit is contained in:
Hu Kejun
2018-09-14 11:03:51 +08:00
committed by Tao Huang
parent 4199db0812
commit 79a732a593
3 changed files with 154 additions and 58 deletions

View File

@@ -1527,28 +1527,12 @@ static void cif_isp10_select_jpeg_tables(
cif_ioread32(dev->config.base_addr + CIF_JPE_AC_TABLE_SELECT));
}
static int cif_isp10_config_img_src(
static int cif_isp10_config_img_src_exps(
struct cif_isp10_device *dev)
{
int ret = 0;
struct isp_supplemental_sensor_mode_data sensor_mode;
cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
ret = cif_isp10_img_src_set_state(dev,
CIF_ISP10_IMG_SRC_STATE_SW_STNDBY);
if (IS_ERR_VALUE(ret))
goto err;
if (!dev->sp_stream.updt_cfg &&
!dev->mp_stream.updt_cfg)
return 0;
ret = cif_isp10_pltfrm_g_interface_config(dev->img_src,
&dev->config.cam_itf);
if (IS_ERR_VALUE(ret))
goto err;
ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
RK_VIDIOC_SENSOR_MODE_DATA, &sensor_mode);
if (IS_ERR_VALUE(ret)) {
@@ -1568,6 +1552,36 @@ static int cif_isp10_config_img_src(
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX] =
sensor_mode.exposure_valid_frame[VALID_FR_EXP_G_INDEX];
}
return ret;
}
static int cif_isp10_config_img_src(
struct cif_isp10_device *dev)
{
int ret = 0;
cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
ret = cif_isp10_img_src_set_state(dev,
CIF_ISP10_IMG_SRC_STATE_SW_STNDBY);
if (IS_ERR_VALUE(ret))
goto err;
if (!dev->sp_stream.updt_cfg &&
!dev->mp_stream.updt_cfg)
return 0;
ret = cif_isp10_pltfrm_g_interface_config(dev->img_src,
&dev->config.cam_itf);
if (IS_ERR_VALUE(ret))
goto err;
if (!dev->img_src_exps.inited) {
cif_isp10_config_img_src_exps(dev);
dev->img_src_exps.inited = true;
}
cif_isp10_pltfrm_pr_dbg(dev->dev,
"cam_itf: (type: 0x%x, dphy: %d, vc: %d, nb_lanes: %d, bitrate: %d)",
dev->config.cam_itf.type,
@@ -5022,6 +5036,7 @@ static int cif_isp10_start(
unsigned int ret;
struct vb2_buffer *vb, *n;
unsigned long flags;
unsigned int i;
cif_isp10_pltfrm_pr_dbg(dev->dev,
"SP state = %s, MP state = %s, DMA state = %s, img_src state = %s, start_sp = %d, start_mp = %d\n",
@@ -5106,7 +5121,6 @@ static int cif_isp10_start(
RK_VIDIOC_SENSOR_MODE_DATA,
&dev->img_src_exps.data[0].data);
dev->img_src_exps.data[0].v_frame_id = 0;
dev->img_src_exps.data[1].v_frame_id = 0;
dev->img_src_exps.data[0].data.isp_input_width =
dev->config.isp_config.input->defrect.width;
dev->img_src_exps.data[0].data.isp_input_height =
@@ -5120,8 +5134,11 @@ static int cif_isp10_start(
dev->config.isp_config.output.width;
dev->img_src_exps.data[0].data.isp_output_height =
dev->config.isp_config.output.height;
memcpy(&dev->img_src_exps.data[1], &dev->img_src_exps.data[0],
sizeof(dev->img_src_exps.data[0]));
for (i = 1; i < CIF_ISP10_IMG_SRC_DATA_NUM; i++)
dev->img_src_exps.data[i] = dev->img_src_exps.data[0];
dev->img_src_exps.exp_idx = 0;
mutex_unlock(&dev->img_src_exps.mutex);
cif_isp10_pltfrm_rtrace_printf(dev->dev,
@@ -5439,6 +5456,8 @@ static void cif_isp10_vs_work(struct work_struct *work)
container_of(work, struct cif_isp10_isp_vs_work, work);
struct cif_isp10_device *dev = vs_wk->dev;
unsigned int v_frame_id;
unsigned char exp_idx, i;
struct isp_supplemental_sensor_mode_data sensor_data;
switch (vs_wk->cmd) {
case CIF_ISP10_VS_EXP: {
@@ -5453,13 +5472,31 @@ static void cif_isp10_vs_work(struct work_struct *work)
cif_isp10_pltfrm_pr_err(dev->dev,
"dev->img_src is NULL\n");
if (dev->img_src_exps.data[0].v_frame_id <
dev->img_src_exps.data[1].v_frame_id)
new_data = &dev->img_src_exps.data[0];
else
new_data = &dev->img_src_exps.data[1];
mutex_lock(&dev->img_src_exps.mutex);
cif_isp10_img_src_ioctl(dev->img_src,
RK_VIDIOC_SENSOR_MODE_DATA,
&sensor_data);
exp_idx = dev->img_src_exps.exp_idx;
if (((dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] + 2) ==
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX])) {
new_data = &dev->img_src_exps.data[exp_idx];
v_frame_id = dev->isp_dev.frame_id +
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX];
if (v_frame_id == new_data->v_frame_id)
new_data->data.exp_time = sensor_data.exp_time;
} else if ((dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] ==
(dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX] + 2))) {
new_data = &dev->img_src_exps.data[exp_idx];
v_frame_id = dev->isp_dev.frame_id +
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX];
if (v_frame_id == new_data->v_frame_id)
new_data->data.gain = sensor_data.gain;
}
exp_idx = (exp_idx + 1) % CIF_ISP10_IMG_SRC_DATA_NUM;
new_data = &dev->img_src_exps.data[exp_idx];
if (exp_ctrl->ctrls->id == V4L2_CID_EXPOSURE)
v_frame_id = dev->isp_dev.frame_id +
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX];
@@ -5467,15 +5504,15 @@ static void cif_isp10_vs_work(struct work_struct *work)
v_frame_id = dev->isp_dev.frame_id +
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX];
if (v_frame_id == dev->img_src_exps.data[0].v_frame_id)
new_data = &dev->img_src_exps.data[0];
if (v_frame_id == dev->img_src_exps.data[1].v_frame_id)
new_data = &dev->img_src_exps.data[1];
for (i = 0; i < CIF_ISP10_IMG_SRC_DATA_NUM; i++) {
if (v_frame_id == dev->img_src_exps.data[i].v_frame_id) {
exp_idx = i;
new_data = &dev->img_src_exps.data[i];
}
}
new_data->v_frame_id = v_frame_id;
cif_isp10_img_src_ioctl(dev->img_src,
RK_VIDIOC_SENSOR_MODE_DATA,
&new_data->data);
new_data->data = sensor_data;
new_data->data.isp_input_width =
dev->config.isp_config.input->defrect.width;
new_data->data.isp_input_height =
@@ -5489,6 +5526,8 @@ static void cif_isp10_vs_work(struct work_struct *work)
dev->config.isp_config.output.width;
new_data->data.isp_output_height =
dev->config.isp_config.output.height;
dev->img_src_exps.exp_idx = exp_idx;
mutex_unlock(&dev->img_src_exps.mutex);
/*
@@ -5546,34 +5585,43 @@ static int cif_isp10_vs_work_cmd(
}
}
static struct cif_isp10_img_src_exp *cif_isp10_get_last_exp(
struct cif_isp10_device *dev)
{
struct cif_isp10_img_src_exp *exp = NULL;
if (!list_empty(&dev->img_src_exps.list)) {
exp = list_last_entry(&dev->img_src_exps.list,
struct cif_isp10_img_src_exp,
list);
}
return exp;
}
/* Public Functions */
void cif_isp10_sensor_mode_data_sync(
struct cif_isp10_device *dev,
unsigned int frame_id,
struct isp_supplemental_sensor_mode_data *data)
{
struct cif_isp10_img_src_data *last_data;
struct cif_isp10_img_src_data *new_data;
struct cif_isp10_img_src_data *match_data;
unsigned int i;
unsigned char exp_idx;
mutex_lock(&dev->img_src_exps.mutex);
if (dev->img_src_exps.data[0].v_frame_id <
dev->img_src_exps.data[1].v_frame_id) {
last_data = &dev->img_src_exps.data[0];
new_data = &dev->img_src_exps.data[1];
} else {
last_data = &dev->img_src_exps.data[1];
new_data = &dev->img_src_exps.data[0];
exp_idx = dev->img_src_exps.exp_idx;
exp_idx = (exp_idx + 1) % CIF_ISP10_IMG_SRC_DATA_NUM;
match_data = &dev->img_src_exps.data[exp_idx];
for (i = 0; i < CIF_ISP10_IMG_SRC_DATA_NUM; i++) {
if (frame_id >= dev->img_src_exps.data[exp_idx].v_frame_id)
match_data = &dev->img_src_exps.data[exp_idx];
exp_idx = (exp_idx + 1) % CIF_ISP10_IMG_SRC_DATA_NUM;
}
if (frame_id >= new_data->v_frame_id) {
memcpy(data,
&new_data->data,
sizeof(struct isp_supplemental_sensor_mode_data));
} else {
memcpy(data,
&last_data->data,
sizeof(struct isp_supplemental_sensor_mode_data));
}
memcpy(data, &match_data->data,
sizeof(struct isp_supplemental_sensor_mode_data));
mutex_unlock(&dev->img_src_exps.mutex);
}
@@ -6058,6 +6106,7 @@ struct cif_isp10_device *cif_isp10_create(
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] = 4;
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX] = 4;
dev->img_src_exps.inited = false;
mutex_init(&dev->img_src_exps.mutex);
memset(&dev->img_src_exps.data, 0x00, sizeof(dev->img_src_exps.data));
spin_lock_init(&dev->img_src_exps.lock);
@@ -6245,15 +6294,21 @@ int cif_isp10_s_exp(
{
struct cif_isp10_img_src_ctrl *ctrl_exp_t = NULL, *ctrl_exp_g = NULL;
struct cif_isp10_img_src_exp *exp = NULL, *exp_t = NULL, *exp_g = NULL;
struct cif_isp10_img_src_exp *last_exp = NULL;
unsigned long lock_flags;
int retval, i, exp_cnt;
int retval, i, j, exp_cnt, val;
if (!dev->vs_wq)
return -ENODEV;
if (!dev->img_src_exps.inited) {
cif_isp10_config_img_src_exps(dev);
dev->img_src_exps.inited = true;
}
if (dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] ==
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX]) {
exp = kmalloc(sizeof(struct cif_isp10_img_src_exp), GFP_KERNEL);
exp = kmalloc(sizeof(*exp), GFP_KERNEL);
if (!exp) {
retval = -ENOMEM;
goto failed;
@@ -6263,24 +6318,60 @@ int cif_isp10_s_exp(
spin_lock_irqsave(&dev->img_src_exps.lock, lock_flags);
list_add_tail(&exp->list, &dev->img_src_exps.list);
spin_unlock_irqrestore(&dev->img_src_exps.lock, lock_flags);
} else if (((dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] + 2) ==
dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX]) ||
(dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_T_INDEX] ==
(dev->img_src_exps.exp_valid_frms[VALID_FR_EXP_G_INDEX] + 2))) {
exp = kmalloc(sizeof(*exp), GFP_KERNEL);
if (!exp) {
retval = -ENOMEM;
goto failed;
}
exp->exp = *exp_ctrl;
spin_lock_irqsave(&dev->img_src_exps.lock, lock_flags);
last_exp = cif_isp10_get_last_exp(dev);
if (last_exp) {
for (i = 0; i < last_exp->exp.cnt; i++) {
for (j = 0; j < exp->exp.cnt; j++) {
if (last_exp->exp.ctrls[i].id ==
exp->exp.ctrls[j].id) {
val = last_exp->exp.ctrls[i].val;
last_exp->exp.ctrls[i].val =
exp->exp.ctrls[j].val;
exp->exp.ctrls[j].val = val;
}
}
}
list_replace(&last_exp->list, &exp->list);
list_add_tail(&last_exp->list, &dev->img_src_exps.list);
spin_unlock_irqrestore(&dev->img_src_exps.lock, lock_flags);
} else {
spin_unlock_irqrestore(&dev->img_src_exps.lock, lock_flags);
kfree(exp);
exp = NULL;
goto TIME_GAIN_DIVIDE;
}
} else {
exp_t = kmalloc(sizeof(struct cif_isp10_img_src_exp), GFP_KERNEL);
TIME_GAIN_DIVIDE:
exp_t = kmalloc(sizeof(*exp_t), GFP_KERNEL);
if (!exp_t) {
retval = -ENOMEM;
goto failed;
}
ctrl_exp_t = kmalloc(sizeof(struct cif_isp10_img_src_ctrl) * 2, GFP_KERNEL);
ctrl_exp_t = kmalloc(sizeof(*ctrl_exp_t) * 2, GFP_KERNEL);
if (!ctrl_exp_t) {
retval = -ENOMEM;
goto failed;
}
exp_g = kmalloc(sizeof(struct cif_isp10_img_src_exp), GFP_KERNEL);
exp_g = kmalloc(sizeof(*exp_g), GFP_KERNEL);
if (!exp_g) {
retval = -ENOMEM;
goto failed;
}
ctrl_exp_g = kmalloc(sizeof(struct cif_isp10_img_src_ctrl)*2, GFP_KERNEL);
ctrl_exp_g = kmalloc(sizeof(*ctrl_exp_g)*2, GFP_KERNEL);
if (!ctrl_exp_g) {
retval = -ENOMEM;
goto failed;

View File

@@ -242,6 +242,8 @@ enum cif_isp10_image_effect {
(!CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt) ||\
!CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt))
#define CIF_ISP10_IMG_SRC_DATA_NUM 6
enum cif_isp10_pix_fmt {
/* YUV */
CIF_YUV400 = 0x10008000,
@@ -568,8 +570,10 @@ struct cif_isp10_img_src_exps {
struct list_head list;
struct mutex mutex; /* protect frm_exp */
struct cif_isp10_img_src_data data[2];
struct cif_isp10_img_src_data data[CIF_ISP10_IMG_SRC_DATA_NUM];
unsigned char exp_idx;
unsigned char exp_valid_frms[2];
bool inited;
};
enum cif_isp10_isp_vs_cmd {

View File

@@ -1053,6 +1053,7 @@ static int cif_isp10_v4l2_open(
/* First open of the device, so initialize everything */
node->owner = NULL;
dev->img_src_exps.inited = false;
cif_isp10_init_vb2_queue(to_vb2_queue(file), dev, buf_type);
vdev->queue = to_vb2_queue(file);