diff --git a/drivers/media/platform/rk-isp10/cif_isp10.c b/drivers/media/platform/rk-isp10/cif_isp10.c index 35da32541029..3da63047f037 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.c +++ b/drivers/media/platform/rk-isp10/cif_isp10.c @@ -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; diff --git a/drivers/media/platform/rk-isp10/cif_isp10.h b/drivers/media/platform/rk-isp10/cif_isp10.h index f1265817991e..347f75f8c0a2 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.h +++ b/drivers/media/platform/rk-isp10/cif_isp10.h @@ -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 { diff --git a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c index 6742f438a731..d6a7cf3927ad 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c @@ -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);