mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user