diff --git a/drivers/media/platform/rockchip/isp/csi.c b/drivers/media/platform/rockchip/isp/csi.c index a3e9b4f3fdef..c904763a5827 100644 --- a/drivers/media/platform/rockchip/isp/csi.c +++ b/drivers/media/platform/rockchip/isp/csi.c @@ -447,6 +447,8 @@ void rkisp_trigger_read_back(struct rkisp_csi_device *csi, u8 dma2frm) } /* not using isp V_START irq to generate sof event */ csi->filt_state[CSI_F_VS] = dma2frm + 1; + if (dma2frm) + csi->read_bak = true; writel(SW_CSI2RX_EN | SW_DMA_2FRM_MODE(dma2frm) | readl(addr), addr); } diff --git a/drivers/media/platform/rockchip/isp/csi.h b/drivers/media/platform/rockchip/isp/csi.h index 2566bcc87cfa..16ddbe3e2766 100644 --- a/drivers/media/platform/rockchip/isp/csi.h +++ b/drivers/media/platform/rockchip/isp/csi.h @@ -76,6 +76,7 @@ struct rkisp_csi_device { u8 filt_state[CSI_F_MAX]; u8 tx_first[HDR_DMA_MAX]; u8 memory; + bool read_bak; }; int rkisp_register_csi_subdev(struct rkisp_device *dev, diff --git a/drivers/media/platform/rockchip/isp/isp_stats.c b/drivers/media/platform/rockchip/isp/isp_stats.c index eb893201acaa..f51cffdb1c57 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.c +++ b/drivers/media/platform/rockchip/isp/isp_stats.c @@ -156,6 +156,7 @@ rkisp_stats_vb2_start_streaming(struct vb2_queue *queue, { struct rkisp_isp_stats_vdev *stats_vdev = queue->drv_priv; + stats_vdev->ops->rdbk_enable(stats_vdev, false); stats_vdev->streamon = true; kfifo_reset(&stats_vdev->rd_kfifo); tasklet_enable(&stats_vdev->rd_tasklet); @@ -231,6 +232,11 @@ static void rkisp_uninit_stats_vdev(struct rkisp_isp_stats_vdev *stats_vdev) rkisp_uninit_stats_vdev_v2x(stats_vdev); } +void rkisp_stats_rdbk_enable(struct rkisp_isp_stats_vdev *stats_vdev, bool en) +{ + stats_vdev->ops->rdbk_enable(stats_vdev, en); +} + void rkisp_stats_first_ddr_config(struct rkisp_isp_stats_vdev *stats_vdev) { if (stats_vdev->dev->isp_ver >= ISP_V20) diff --git a/drivers/media/platform/rockchip/isp/isp_stats.h b/drivers/media/platform/rockchip/isp/isp_stats.h index 04da0cd7df5d..2b5e2c645a3d 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats.h +++ b/drivers/media/platform/rockchip/isp/isp_stats.h @@ -33,6 +33,7 @@ struct rkisp_isp_stats_ops { u32 isp_mis, u32 isp3a_ris); void (*send_meas)(struct rkisp_isp_stats_vdev *stats_vdev, struct rkisp_isp_readout_work *meas_work); + void (*rdbk_enable)(struct rkisp_isp_stats_vdev *stats_vdev, bool en); }; /* @@ -63,8 +64,14 @@ struct rkisp_isp_stats_vdev { u32 rd_buf_idx; u32 wr_buf_idx; bool rd_stats_from_ddr; + + bool rdbk_mode; + u32 isp_rdbk; + u32 isp3a_rdbk; }; +void rkisp_stats_rdbk_enable(struct rkisp_isp_stats_vdev *stats_vdev, bool en); + void rkisp_stats_first_ddr_config(struct rkisp_isp_stats_vdev *stats_vdev); void rkisp_stats_isr(struct rkisp_isp_stats_vdev *stats_vdev, diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v1x.c b/drivers/media/platform/rockchip/isp/isp_stats_v1x.c index fb7d9ccfd1bb..dce904b5f7c5 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v1x.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v1x.c @@ -385,9 +385,15 @@ unlock: spin_unlock(&stats_vdev->irq_lock); } +static void +rkisp_stats_rdbk_enable_v1x(struct rkisp_isp_stats_vdev *stats_vdev, bool en) +{ +} + static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .isr_hdl = rkisp1_stats_isr_v1x, .send_meas = rkisp1_stats_send_meas_v1x, + .rdbk_enable = rkisp_stats_rdbk_enable_v1x, }; void rkisp_init_stats_vdev_v1x(struct rkisp_isp_stats_vdev *stats_vdev) diff --git a/drivers/media/platform/rockchip/isp/isp_stats_v2x.c b/drivers/media/platform/rockchip/isp/isp_stats_v2x.c index 5269c823f67b..1cf612b148f1 100644 --- a/drivers/media/platform/rockchip/isp/isp_stats_v2x.c +++ b/drivers/media/platform/rockchip/isp/isp_stats_v2x.c @@ -1269,6 +1269,56 @@ rkisp_stats_send_meas_v2x(struct rkisp_isp_stats_vdev *stats_vdev, } } +static void +rkisp_stats_clr_3a_isr(struct rkisp_isp_stats_vdev *stats_vdev, + u32 isp_ris, u32 isp3a_ris) +{ + struct rkisp_stats_v2x_ops *ops = + (struct rkisp_stats_v2x_ops *)stats_vdev->priv_ops; + + if (isp_ris & ISP2X_SIAWB_DONE) + ops->get_siawb_meas(stats_vdev, NULL); + + if (isp_ris & ISP2X_SIAF_FIN) + ops->get_siaf_meas(stats_vdev, NULL); + + if (isp_ris & ISP2X_YUVAE_END) + ops->get_yuvae_meas(stats_vdev, NULL); + + if (isp_ris & ISP2X_SIHST_RDY) + ops->get_sihst_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWAWB) + ops->get_rawawb_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWAF) + ops->get_rawaf_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWAE_BIG) + ops->get_rawaebig1_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWHIST_BIG) + ops->get_rawhstbig1_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWAE_CH0) + ops->get_rawaelite_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWAE_CH1) + ops->get_rawaebig2_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWAE_CH2) + ops->get_rawaebig3_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWHIST_CH0) + ops->get_rawhstlite_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWHIST_CH1) + ops->get_rawhstbig2_meas(stats_vdev, NULL); + + if (isp3a_ris & ISP2X_3A_RAWHIST_CH2) + ops->get_rawhstbig3_meas(stats_vdev, NULL); +} + static void rkisp_stats_isr_v2x(struct rkisp_isp_stats_vdev *stats_vdev, u32 isp_ris, u32 isp3a_ris) @@ -1282,6 +1332,7 @@ rkisp_stats_isr_v2x(struct rkisp_isp_stats_vdev *stats_vdev, ISP2X_3A_RAWAE_CH2 | ISP2X_3A_RAWHIST_BIG | ISP2X_3A_RAWHIST_CH0 | ISP2X_3A_RAWHIST_CH1 | ISP2X_3A_RAWHIST_CH2 | ISP2X_3A_RAWAF_SUM | ISP2X_3A_RAWAF_LUM | ISP2X_3A_RAWAF | ISP2X_3A_RAWAWB; + u32 hdl_ris, hdl_3aris, unhdl_ris, unhdl_3aris; u32 wr_buf_idx; #ifdef LOG_ISR_EXE_TIME @@ -1326,11 +1377,24 @@ rkisp_stats_isr_v2x(struct rkisp_isp_stats_vdev *stats_vdev, stats_vdev->dev->base_addr + MI_SWS_3A_WR_BASE); } - if ((isp_ris & iq_isr_mask) || (isp3a_ris & iq_3a_mask)) { + hdl_ris = isp_ris; + hdl_3aris = isp3a_ris; + unhdl_ris = 0; + unhdl_3aris = 0; + if (stats_vdev->rdbk_mode) { + hdl_ris = isp_ris & ~stats_vdev->isp_rdbk; + hdl_3aris = isp3a_ris & ~stats_vdev->isp3a_rdbk; + unhdl_ris = isp_ris & stats_vdev->isp_rdbk; + unhdl_3aris = isp3a_ris & stats_vdev->isp3a_rdbk; + stats_vdev->isp_rdbk |= hdl_ris; + stats_vdev->isp3a_rdbk |= hdl_3aris; + } + + if ((hdl_ris & iq_isr_mask) || (hdl_3aris & iq_3a_mask)) { work.readout = RKISP_ISP_READOUT_MEAS; work.frame_id = cur_frame_id; - work.isp_ris = isp_ris; - work.isp3a_ris = isp3a_ris; + work.isp_ris = hdl_ris; + work.isp3a_ris = hdl_3aris; work.timestamp = ktime_get_ns(); if (!kfifo_is_full(&stats_vdev->rd_kfifo)) @@ -1343,6 +1407,8 @@ rkisp_stats_isr_v2x(struct rkisp_isp_stats_vdev *stats_vdev, tasklet_schedule(&stats_vdev->rd_tasklet); } + rkisp_stats_clr_3a_isr(stats_vdev, unhdl_ris, unhdl_3aris); + #ifdef LOG_ISR_EXE_TIME if (isp_ris & iq_isr_mask) { unsigned int diff_us = @@ -1360,9 +1426,21 @@ unlock: spin_unlock(&stats_vdev->irq_lock); } +static void +rkisp_stats_rdbk_enable_v2x(struct rkisp_isp_stats_vdev *stats_vdev, bool en) +{ + if (!en) { + stats_vdev->isp_rdbk = 0; + stats_vdev->isp3a_rdbk = 0; + } + + stats_vdev->rdbk_mode = en; +} + static struct rkisp_isp_stats_ops rkisp_isp_stats_ops_tbl = { .isr_hdl = rkisp_stats_isr_v2x, .send_meas = rkisp_stats_send_meas_v2x, + .rdbk_enable = rkisp_stats_rdbk_enable_v2x, }; void rkisp_stats_first_ddr_config_v2x(struct rkisp_isp_stats_vdev *stats_vdev) diff --git a/drivers/media/platform/rockchip/isp/rkisp.c b/drivers/media/platform/rockchip/isp/rkisp.c index 697bb554a1d8..37bdbd25b77e 100644 --- a/drivers/media/platform/rockchip/isp/rkisp.c +++ b/drivers/media/platform/rockchip/isp/rkisp.c @@ -1866,6 +1866,10 @@ void rkisp_isp_isr(unsigned int isp_mis, /* start edge of v_sync */ if (isp_mis & CIF_ISP_V_START) { /* filt v_sync when frame read back mode */ + if (dev->csi_dev.read_bak) { + dev->csi_dev.read_bak = false; + rkisp_stats_rdbk_enable(&dev->stats_vdev, true); + } if (dev->csi_dev.filt_state[CSI_F_VS]) { dev->csi_dev.filt_state[CSI_F_VS]--; goto vs_skip; @@ -1960,6 +1964,9 @@ vs_skip: readl(base + CIF_ISP_RIS)); rkisp_stats_isr(&dev->stats_vdev, irq, isp3a_mis); + + if ((isp_mis & CIF_ISP_FRAME) && dev->stats_vdev.rdbk_mode) + rkisp_stats_rdbk_enable(&dev->stats_vdev, false); } /*