diff --git a/drivers/media/platform/rockchip/isp/dev.h b/drivers/media/platform/rockchip/isp/dev.h index 41381783f2a3..c641eba2e9ac 100644 --- a/drivers/media/platform/rockchip/isp/dev.h +++ b/drivers/media/platform/rockchip/isp/dev.h @@ -311,6 +311,8 @@ struct rkisp_device { bool is_suspend_one_frame; bool is_aiisp_en; bool is_aiisp_upd; + bool is_aiisp_stopping; + bool is_aiisp_stop; bool is_aiisp_sync; bool is_aiisp_yuv; bool is_frm_rd; @@ -322,6 +324,8 @@ struct rkisp_device { struct rkisp_vicap_sof vicap_sof; u32 hdr_wrap_line; + u32 aiisp_stop_seq; + u8 multi_mode; u8 multi_index; u8 rawaf_irq_cnt; diff --git a/drivers/media/platform/rockchip/isp/isp_params.c b/drivers/media/platform/rockchip/isp/isp_params.c index 151ac7b3b468..efbf9221835a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.c +++ b/drivers/media/platform/rockchip/isp/isp_params.c @@ -312,6 +312,10 @@ static void rkisp_params_vb2_stop_streaming(struct vb2_queue *vq) params_vdev->is_first_cfg = false; } dev->is_aiisp_yuv = false; + dev->is_aiisp_en = false; + dev->is_aiisp_stop = false; + dev->is_aiisp_stopping = false; + memset(&dev->aiisp_cfg, 0, sizeof(dev->aiisp_cfg)); dev->fpn_cfg.en = 0; if (dev->fpn_cfg.buf) { vfree(dev->fpn_cfg.buf); diff --git a/drivers/media/platform/rockchip/isp/isp_params.h b/drivers/media/platform/rockchip/isp/isp_params.h index cec291be2d3b..ffb76c28a824 100644 --- a/drivers/media/platform/rockchip/isp/isp_params.h +++ b/drivers/media/platform/rockchip/isp/isp_params.h @@ -59,6 +59,7 @@ struct rkisp_isp_params_ops { int (*aiisp_start)(struct rkisp_isp_params_vdev *params_vdev, struct rkisp_aiisp_st *st); int (*get_aiawb_buffd)(struct rkisp_isp_params_vdev *params_vdev, void *arg); void (*vpsl_update_regs)(struct rkisp_isp_params_vdev *params_vdev); + void (*aiisp_switch)(struct rkisp_isp_params_vdev *params_vdev, bool on); }; /* diff --git a/drivers/media/platform/rockchip/isp/isp_params_v35.c b/drivers/media/platform/rockchip/isp/isp_params_v35.c index 27ef82b18d1d..184e4695b50a 100644 --- a/drivers/media/platform/rockchip/isp/isp_params_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_params_v35.c @@ -4459,13 +4459,14 @@ isp_ai_config(struct rkisp_isp_params_vdev *params_vdev, u32 i, val; val = isp3_param_read(params_vdev, ISP35_AI_CTRL, id); - val &= (ISP35_AIISP_EN | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + val &= (ISP35_AIISP_EN | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN); val |= //!!arg->aiisp_raw12_msb << 2 | (arg->aiisp_gain_mode & 0x3) << 4 | !!arg->aiisp_curve_en << 6 | - !!arg->aipre_iir_en << 8 | + //!!arg->aipre_iir_en << 8 | //!!arg->aipre_iir2ddr_en << 9 | - !!arg->aipre_gain_en << 10 | + //!!arg->aipre_gain_en << 10 | //!!arg->aipre_gain2ddr_en << 11 | !!arg->aipre_yraw_sel << 12 | !!arg->aipre_nl_ddr_mode << 13 | @@ -4525,7 +4526,8 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) if (en == !!(ctrl & ISP35_MODULE_EN)) return; - ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + ctrl &= ~(ISP35_AIISP_ST | ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN); if (en) { if (priv->buf_aipre_gain[0].mem_priv) { priv->aipre_gain_idx = 0; @@ -4534,15 +4536,21 @@ isp_ai_enable(struct rkisp_isp_params_vdev *params_vdev, bool en, u32 id) isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, id); val = priv->aipre_gain_stride; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_STRIDE, id); - ctrl |= ISP35_AIPRE_GIAN2DDR_EN; + ctrl |= ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIPRE_GAIN_EN; } if (priv->buf_vpsl[0].mem_priv) { + if (priv->yraw_sel) + ctrl |= ISP35_AIPRE_IIR_EN; vpsl_update_buf(params_vdev, priv->pbuf_vpsl, true); priv->vpsl_cur_idx = priv->vpsl_idx; + if (params_vdev->dev->is_aiisp_sync) + params_vdev->dev->irq_ends_mask |= ISP_FRAME_VPSL; } ctrl |= ISP35_AIPRE_ITS_FORCE_UPD; if (params_vdev->dev->is_aiisp_en) ctrl |= ISP35_AIISP_EN; + else if (params_vdev->dev->is_aiisp_stop) + ctrl &= ~(ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIPRE_GAIN_EN | ISP35_AIPRE_IIR_EN); } else { ctrl &= ~ISP35_AIISP_EN; params_vdev->dev->irq_ends_mask &= ~ISP_FRAME_VPSL; @@ -5991,6 +5999,7 @@ rkisp_params_aiisp_update_buf(struct rkisp_isp_params_vdev *params_vdev) val = priv->pbuf_aipre_gain->dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); + priv->aipre_gain_cur_idx = priv->pbuf_aipre_gain->index; if (params_vdev->dev->hw_dev->is_single) { val = isp3_param_read(params_vdev, ISP35_AI_CTRL, 0); @@ -6273,6 +6282,100 @@ rkisp_vpsl_update_regs_v35(struct rkisp_isp_params_vdev *params_vdev) writel(VPSL_MI_FORCE_UPD, base + VPSL_MI_WR_INIT); } +static void +rkisp_params_aiisp_switch_v35(struct rkisp_isp_params_vdev *params_vdev, bool on) +{ + struct rkisp_device *dev = params_vdev->dev; + struct rkisp_isp_stats_vdev *stats_vdev = &dev->stats_vdev; + struct rkisp_isp_params_val_v35 *priv = params_vdev->priv_val; + struct isp35_isp_params_cfg *params; + struct rkisp_buffer *params_buf; + unsigned long flags = 0; + u32 val; + + v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev, + "%s on:%d\n", __func__, on); + if (!on) { + spin_lock_irqsave(¶ms_vdev->config_lock, flags); + while (!list_empty(¶ms_vdev->params_be)) { + params_buf = list_first_entry(¶ms_vdev->params_be, struct rkisp_buffer, queue); + list_del(¶ms_buf->queue); + params = params_buf->vaddr[0]; + __isp_isr_meas_config(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_other_config(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_other_en(params_vdev, params, RKISP_PARAMS_LAT, 0); + __isp_isr_meas_en(params_vdev, params, RKISP_PARAMS_LAT, 0); + params->module_cfg_update = 0; + vb2_buffer_done(¶ms_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + } + spin_unlock_irqrestore(¶ms_vdev->config_lock, flags); + + val = rkisp_read(dev, ISP35_AI_CTRL, false); + val &= ~(ISP35_AIISP_ST | ISP35_AIISP_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN | + ISP35_AIPRE_IIR2DDR_EN | ISP35_AIPRE_GIAN2DDR_EN); + val |= ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + val &= ~ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + + val = rkisp_read(dev, ISP3X_MI_BAY3D_IIR_RD_BASE_SHD, true); + rkisp_write(dev, ISP3X_MI_BAY3D_IIR_WR_BASE, val, false); + if (dev->hw_dev->is_single) { + val = ISP3X_BAY3D_IIRSELF_UPD | ISP3X_BAY3D_RDSELF_UPD | + ISP3X_GAINSELF_UPD; + rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, false); + } + + rkisp_stats_first_ddr_config(stats_vdev); + rkisp_stats_next_ddr_config(stats_vdev); + + val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); + val &= ~ISP35_BAYER_UPD_FE_EN; + rkisp_write(dev, ISP3X_ISP_CTRL1, val, false); + + val = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; + rkisp_clear_bits(dev, CIF_ISP_IMSC, val, false); + } else { + val = rkisp_read(dev, ISP3X_ISP_CTRL1, false); + val |= ISP35_BAYER_PAT_FE(params_vdev->raw_type) | ISP35_BAYER_UPD_FE_EN; + rkisp_write(dev, ISP3X_ISP_CTRL1, val, false); + + if (priv->pbuf_bay3d_iir) { + val = priv->pbuf_bay3d_iir->dma_addr; + rkisp_write(dev, ISP3X_MI_BAY3D_IIR_WR_BASE, val, false); + if (dev->hw_dev->is_single) { + val = ISP3X_BAY3D_IIRSELF_UPD | ISP3X_BAY3D_RDSELF_UPD | + ISP3X_GAINSELF_UPD; + rkisp_set_bits(dev, MI_WR_CTRL2, 0, val, false); + } + } + + spin_lock_irqsave(&stats_vdev->rd_lock, flags); + if (stats_vdev->cur_buf) { + list_add_tail(&stats_vdev->cur_buf->queue, &stats_vdev->stat); + stats_vdev->cur_buf = NULL; + } + if (stats_vdev->nxt_buf) { + list_add_tail(&stats_vdev->nxt_buf->queue, &stats_vdev->stat); + stats_vdev->nxt_buf = NULL; + } + spin_unlock_irqrestore(&stats_vdev->rd_lock, flags); + rkisp_stats_first_ddr_config(stats_vdev); + + val = rkisp_read(dev, ISP35_AI_CTRL, false); + val &= ~ISP35_AIISP_ST; + val |= ISP35_AIPRE_GIAN2DDR_EN | ISP35_AIISP_EN | + ISP35_AIPRE_IIR_EN | ISP35_AIPRE_GAIN_EN | + ISP35_AIISP_RAW12_MSB | ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + val &= ~ISP35_AIPRE_ITS_FORCE_UPD; + rkisp_write(dev, ISP35_AI_CTRL, val, false); + + params_vdev->cur_fe_frame_id = params_vdev->cur_frame_id; + } +} + static void rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) { @@ -6286,7 +6389,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) params_vdev->rdbk_times--; if (!params_vdev->rdbk_times) { - if (!dev->is_aiisp_en && priv->bay3d_iir_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->bay3d_iir_cnt > 1) { priv->pbuf_bay3d_iir = &priv->buf_bay3d_iir[priv->bay3d_iir_idx]; priv->bay3d_iir_cur_idx = priv->bay3d_iir_idx; i = (priv->bay3d_iir_idx + 1) % priv->bay3d_iir_cnt; @@ -6334,7 +6437,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_CUR_WR_BASE, i); } } - if (!dev->is_aiisp_en && priv->aipre_gain_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->aipre_gain_cnt > 1) { priv->pbuf_aipre_gain = &priv->buf_aipre_gain[priv->aipre_gain_idx]; priv->aipre_gain_cur_idx = priv->aipre_gain_idx; i = (priv->aipre_gain_idx + 1) % priv->aipre_gain_cnt; @@ -6343,7 +6446,7 @@ rkisp_params_isr_v35(struct rkisp_isp_params_vdev *params_vdev, u32 isp_mis) val = priv->buf_aipre_gain[i].dma_addr; isp3_param_write(params_vdev, val, ISP35_AI_PRE_GAIN_WR_BASE, 0); } - if (!dev->is_aiisp_en && priv->vpsl_cnt > 1) { + if (!dev->is_aiisp_en && !dev->is_aiisp_stop && priv->vpsl_cnt > 1) { priv->pbuf_vpsl = &priv->buf_vpsl[priv->vpsl_idx]; priv->vpsl_cur_idx = priv->vpsl_idx; i = (priv->vpsl_idx + 1) % priv->vpsl_cnt; @@ -6425,6 +6528,7 @@ static struct rkisp_isp_params_ops rkisp_isp_params_ops_tbl = { .aiisp_event = rkisp_params_aiisp_event_v35, .aiisp_start = rkisp_params_aiisp_start_v35, .vpsl_update_regs = rkisp_vpsl_update_regs_v35, + .aiisp_switch = rkisp_params_aiisp_switch_v35, }; int rkisp_init_params_vdev_v35(struct rkisp_isp_params_vdev *params_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_sditf.c b/drivers/media/platform/rockchip/isp/isp_sditf.c index 3b2fd1088532..14315191f569 100644 --- a/drivers/media/platform/rockchip/isp/isp_sditf.c +++ b/drivers/media/platform/rockchip/isp/isp_sditf.c @@ -64,7 +64,8 @@ static int rkisp_sditf_s_stream(struct v4l2_subdev *sd, int on) if (ret < 0) goto pipe_close; sditf->is_on = true; - dev->irq_ends_mask |= ISP_FRAME_VPSS; + if (!dev->is_aiisp_sync) + dev->irq_ends_mask |= ISP_FRAME_VPSS; goto unlock; } sditf->is_on = false; diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v35.c b/drivers/media/platform/rockchip/isp/isp_stats_v35.c index e3ef0c607b74..29036ccb311d 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v35.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v35.c @@ -812,7 +812,9 @@ rkisp_stats_first_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_get_stat_size_v35(stats_vdev, &size); stats_vdev->stats_buf[0].is_need_vaddr = true; stats_vdev->stats_buf[0].size = size; - if (rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0])) + if (!stats_vdev->stats_buf[0].mem_priv) + rkisp_alloc_buffer(dev, &stats_vdev->stats_buf[0]); + if (!stats_vdev->stats_buf[0].vaddr) v4l2_warn(&dev->v4l2_dev, "stats alloc buf fail\n"); else memset(stats_vdev->stats_buf[0].vaddr, 0, size); @@ -823,12 +825,14 @@ rkisp_stats_first_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) if (dev->hw_dev->is_single) rkisp_unite_set_bits(dev, ISP3X_SWS_CFG, 0, ISP3X_3A_DDR_WRITE_EN, false); val = rkisp_read(dev, ISP39_W3A_CTRL0, false); + val &= ~(ISP39_W3A_AUTO_CLR_EN | ISP35_W3A_FORCE_UPD_F); val |= ISP39_W3A_EN | ISP39_W3A_FORCE_UPD; if (!dev->is_aiisp_en) val |= ISP39_W3A_AUTO_CLR_EN; else val |= ISP35_W3A_FORCE_UPD_F; - if (pdaf_vdev && pdaf_vdev->streaming) { + if (pdaf_vdev && pdaf_vdev->streaming && + !(dev->isp_state & ISP_START)) { val |= ISP39_W3A_PDAF_EN; rkisp_pdaf_update_buf(dev); if (pdaf_vdev->next_buf) { @@ -857,7 +861,8 @@ rkisp_stats_next_ddr_config_v35(struct rkisp_isp_stats_vdev *stats_vdev) if (hw->is_single) { if (!dev->is_aiisp_en) rkisp_stats_update_buf(stats_vdev); - if (pdaf_vdev && pdaf_vdev->streaming) + if (pdaf_vdev && pdaf_vdev->streaming && + !(dev->isp_state & ISP_START)) rkisp_pdaf_update_buf(dev); } } diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 8e7ded42ad6d..0217f8ebd5c6 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -758,6 +758,8 @@ static void rkisp_check_mi_ends_mask(struct rkisp_device *dev) dev->irq_ends_mask |= ISP_FRAME_LDC; else dev->irq_ends_mask &= ~ISP_FRAME_LDC; + if (dev->sditf_dev && dev->sditf_dev->is_on) + dev->irq_ends_mask |= ISP_FRAME_VPSS; } /* @@ -834,7 +836,6 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo dev->isp_sdev.quantization); rkisp_params_cfg(params_vdev, cur_frame_id, RKISP_PARAMS_IMD); rkisp_config_cmsk(dev); - rkisp_config_aiisp(dev); if (!dev->is_aiisp_en || (dev->is_aiisp_sync && !dev->is_first_frame)) rkisp_stream_frame_start(dev, 0); @@ -1358,11 +1359,13 @@ static void rkisp_frame_end_idle(struct rkisp_device *dev) if (!(dev->irq_ends_mask & val)) { u32 state = dev->isp_state; struct rkisp_stream *s; + bool sditf_off = true; if (dev->sditf_dev && !dev->sditf_dev->is_on) dev->isp_state = ISP_STOP; - - for (val = 0; val < RKISP_STREAM_VIR; val++) { + else if (dev->sditf_dev && dev->sditf_dev->is_on) + sditf_off = false; + for (val = 0; val < RKISP_STREAM_VIR && sditf_off; val++) { s = &dev->cap_dev.stream[val]; dev->isp_state = ISP_STOP; if (s->streaming) { @@ -1427,6 +1430,15 @@ static void rkisp_back_end_idle(struct rkisp_device *dev) rkisp_rdbk_aiisp_event(dev, T_CMD_END, NULL); if (dev->isp_state == ISP_STOP && dev->hw_dev->is_idle) wake_up(&dev->sync_onoff); + if (dev->is_aiisp_stopping && dev->hw_dev->is_be_idle && + dev->aiisp_stop_seq == dev->dmarx_dev.cur_be_frame.id) { + dev->is_aiisp_en = false; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, false); + dev->is_aiisp_stopping = false; + dev->is_aiisp_stop = true; + rkisp_vicap_hw_link(dev, true); + } } void rkisp_check_idle(struct rkisp_device *dev, u32 irq) @@ -1463,15 +1475,19 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq) spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags); if (isp_front_end) { - if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) + if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) { + rkisp_config_aiisp(dev); return; + } rkisp_front_end_idle(dev); } if (isp_back_end) rkisp_back_end_idle(dev); if (isp_frame_end) { - if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) + if (hw->is_single && !IS_HDR_RDBK(dev->rd_mode)) { + rkisp_config_aiisp(dev); return; + } rkisp_frame_end_idle(dev); } } @@ -1972,7 +1988,7 @@ static int rkisp_config_isp(struct rkisp_device *dev) u32 acq_mult = 0; u32 acq_prop = 0; u32 extend_line = 0; - u32 width, height, val; + u32 width, height; sensor = dev->active_sensor; in_fmt = &dev->isp_sdev.in_fmt; @@ -2077,31 +2093,19 @@ static int rkisp_config_isp(struct rkisp_device *dev) /* Acquisition Size */ rkisp_unite_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left, false); rkisp_unite_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top, false); - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = (acq_mult * width) | (acq_mult * width) << 16; - else - val = acq_mult * width; - rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * width, false); /* ISP Out Area differ with ACQ is only FIFO, so don't crop in this */ rkisp_unite_write(dev, CIF_ISP_OUT_H_OFFS, 0, true); rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true); - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = width | width << 16; - else - val = width; - rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, width, false); if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced) { rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, height / 2, false); rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, height / 2, false); } else { - if (dev->isp_ver == ISP_V35 && dev->is_aiisp_en) - val = (height + extend_line) | (height + extend_line) << 16; - else - val = height + extend_line; - rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, val, false); - rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, val, false); + rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, height + extend_line, false); + rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, height + extend_line, false); } /* interrupt mask */ @@ -3963,11 +3967,37 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) irq = ISP39_AIISP_LINECNT_DONE; if (dev->aiisp_cfg.rd_linecnt) irq |= ISP3X_OUT_FRM_QUARTER; - if (dev->is_aiisp_en) - en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; - irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER; - en_mask = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + if (!(dev->isp_state & ISP_START) && dev->is_aiisp_stop) + goto unlock; + + if (dev->is_aiisp_en && !dev->aiisp_cfg.mode) { + if (!IS_HDR_RDBK(dev->rd_mode)) { + dev->is_aiisp_stopping = true; + dev->aiisp_stop_seq = dev->dmarx_dev.cur_frame.id; + goto unlock; + } else { + dev->is_aiisp_en = false; + irq = 0; + } + } else if (!dev->is_aiisp_en && dev->aiisp_cfg.mode) { + dev->is_aiisp_en = true; + dev->is_aiisp_stop = false; + if (dev->params_vdev.ops->aiisp_switch) + dev->params_vdev.ops->aiisp_switch(&dev->params_vdev, true); + } + + if (dev->is_aiisp_en) { + irq |= ISP3X_BAY3D_FRM_END; + if (!dev->is_aiisp_sync) + dev->irq_f_ends_mask |= ISP_FRAME_BNR; + en = (dev->isp_ver == ISP_V39) ? ISP39_AIISP_EN : ISP35_AIISP_EN; + } + irq_mask = ISP39_AIISP_LINECNT_DONE | ISP3X_OUT_FRM_QUARTER | ISP3X_BAY3D_FRM_END; + if (dev->isp_ver == ISP_V39) + en_mask = ISP39_AIISP_EN; + else + en_mask = ISP35_AIISP_EN | ISP35_AIISP_ST; if (dev->aiisp_cfg.rd_linecnt >= h) rd_line = h - 1; @@ -3981,6 +4011,7 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) rkisp_write(dev, ISP32_ISP_IRQ_CFG0, rd_line, false); rkisp_write(dev, ISP32_ISP_IRQ_CFG1, wr_line, false); rkisp_write(dev, ISP39_SLICE_ST_CTRL, 0, false); + rkisp_write(dev, CIF_ISP_ICR, irq_mask, false); rkisp_set_bits(dev, CIF_ISP_IMSC, irq_mask, irq, false); if (dev->isp_ver == ISP_V39) rkisp_set_bits(dev, ISP3X_MI_RD_CTRL2, en_mask, en, false); @@ -3988,6 +4019,8 @@ static void rkisp_config_aiisp(struct rkisp_device *dev) rkisp_set_bits(dev, ISP35_AI_CTRL, en_mask, en, false); unlock: spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); + if (dev->is_aiisp_stopping) + rkisp_vicap_hw_link(dev, false); } static int rkisp_set_aiisp_linecnt(struct rkisp_device *dev, @@ -3998,7 +4031,11 @@ static int rkisp_set_aiisp_linecnt(struct rkisp_device *dev, if (dev->isp_ver != ISP_V39 && dev->isp_ver != ISP_V35) return -EINVAL; spin_lock_irqsave(&dev->aiisp_lock, lock_flags); - dev->is_aiisp_en = !!cfg->mode; + if (!(dev->isp_state & ISP_START)) { + if (!cfg->mode && cfg->wr_linecnt && cfg->rd_linecnt) + dev->is_aiisp_stop = true; + dev->is_aiisp_en = !!cfg->mode; + } dev->is_aiisp_upd = true; dev->aiisp_cfg = *cfg; spin_unlock_irqrestore(&dev->aiisp_lock, lock_flags); @@ -4273,7 +4310,7 @@ static int rkisp_vicap_sof(struct rkisp_device *dev, struct rkisp_vicap_sof *sof spin_lock_irqsave(&dev->rdbk_lock, flag); if (!IS_HDR_RDBK(dev->rd_mode) && sof->sequence - dev->dmarx_dev.cur_frame.id > 1) { - v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev, + v4l2_dbg(4, rkisp_debug, &dev->v4l2_dev, "vicap sof %d, isp sof %d\n", sof->sequence, dev->dmarx_dev.cur_frame.id); dev->dmarx_dev.cur_frame.id = sof->sequence - 1; @@ -5266,10 +5303,8 @@ vs_skip: if ((isp_mis & CIF_ISP_FRAME) && dev->stats_vdev.rdbk_mode) rkisp_stats_rdbk_enable(&dev->stats_vdev, false); - if (!IS_HDR_RDBK(dev->hdr.op_mode)) { - rkisp_config_aiisp(dev); + if (!IS_HDR_RDBK(dev->hdr.op_mode)) rkisp_config_cmsk(dev); - } } if (isp_mis & CIF_ISP_FRAME) {