From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB

---
 kernel/drivers/media/platform/rockchip/isp/rkisp.c |  721 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 405 insertions(+), 316 deletions(-)

diff --git a/kernel/drivers/media/platform/rockchip/isp/rkisp.c b/kernel/drivers/media/platform/rockchip/isp/rkisp.c
index 1d69fab..ac40adf 100644
--- a/kernel/drivers/media/platform/rockchip/isp/rkisp.c
+++ b/kernel/drivers/media/platform/rockchip/isp/rkisp.c
@@ -87,12 +87,6 @@
 
 static void rkisp_config_cmsk(struct rkisp_device *dev);
 
-struct backup_reg {
-	const u32 base;
-	const u32 shd;
-	u32 val;
-};
-
 static inline struct rkisp_device *sd_to_isp_dev(struct v4l2_subdev *sd)
 {
 	return container_of(sd->v4l2_dev, struct rkisp_device, v4l2_dev);
@@ -213,17 +207,16 @@
 		max_h = CIF_ISP_INPUT_H_MAX_V21;
 		break;
 	case ISP_V30:
-		if (dev->hw_dev->is_unite) {
-			max_w = CIF_ISP_INPUT_W_MAX_V30_UNITE;
-			max_h = CIF_ISP_INPUT_H_MAX_V30_UNITE;
-		} else {
-			max_w = CIF_ISP_INPUT_W_MAX_V30;
-			max_h = CIF_ISP_INPUT_H_MAX_V30;
-		}
+		max_w = dev->hw_dev->unite ?
+			CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30;
+		max_h = dev->hw_dev->unite ?
+			CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30;
 		break;
 	case ISP_V32:
-		max_w = CIF_ISP_INPUT_W_MAX_V32;
-		max_h = CIF_ISP_INPUT_H_MAX_V32;
+		max_w = dev->hw_dev->unite ?
+			CIF_ISP_INPUT_W_MAX_V32_UNITE : CIF_ISP_INPUT_W_MAX_V32;
+		max_h = dev->hw_dev->unite ?
+			CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32;
 		break;
 	case ISP_V32_L:
 		max_w = CIF_ISP_INPUT_W_MAX_V32_L;
@@ -518,7 +511,9 @@
 	do_div(data_rate, 1000 * 1000);
 	/* increase margin: 25% * num */
 	data_rate += (data_rate >> 2) * num;
-
+	/* one frame two-run, data double */
+	if (hw->is_multi_overflow && num > 1)
+		data_rate *= 2;
 	/* compare with isp clock adjustment table */
 	for (i = 0; i < hw->num_clk_rate_tbl; i++)
 		if (data_rate <= hw->clk_rate_tbl[i].clk_rate)
@@ -528,7 +523,7 @@
 
 	/* set isp clock rate */
 	rkisp_set_clk_rate(hw->clks[0], hw->clk_rate_tbl[i].clk_rate * 1000000UL);
-	if (hw->is_unite)
+	if (hw->unite == ISP_UNITE_TWO)
 		rkisp_set_clk_rate(hw->clks[5], hw->clk_rate_tbl[i].clk_rate * 1000000UL);
 	/* aclk equal to core clk */
 	if (dev->isp_ver == ISP_V32)
@@ -541,48 +536,39 @@
 	struct rkisp_hw_dev *hw = dev->hw_dev;
 
 	if (on) {
-		/* enable bay3d and mi */
+		/* enable mi */
 		rkisp_update_regs(dev, ISP3X_MI_WR_CTRL, ISP3X_MI_WR_CTRL);
 		rkisp_update_regs(dev, ISP3X_ISP_CTRL1, ISP3X_ISP_CTRL1);
-		if (dev->isp_ver == ISP_V21) {
-			rkisp_update_regs(dev, ISP21_BAY3D_CTRL, ISP21_BAY3D_CTRL);
-		} else if (dev->isp_ver == ISP_V30) {
+		if (dev->isp_ver == ISP_V30) {
 			rkisp_update_regs(dev, ISP3X_MPFBC_CTRL, ISP3X_MPFBC_CTRL);
 			rkisp_update_regs(dev, ISP3X_MI_BP_WR_CTRL, ISP3X_MI_BP_WR_CTRL);
-			rkisp_update_regs(dev, ISP3X_BAY3D_CTRL, ISP3X_BAY3D_CTRL);
 			rkisp_update_regs(dev, ISP3X_SWS_CFG, ISP3X_SWS_CFG);
 		} else if (dev->isp_ver == ISP_V32) {
 			rkisp_update_regs(dev, ISP3X_MI_BP_WR_CTRL, ISP3X_MI_BP_WR_CTRL);
 			rkisp_update_regs(dev, ISP32_MI_BPDS_WR_CTRL, ISP32_MI_BPDS_WR_CTRL);
 			rkisp_update_regs(dev, ISP32_MI_MPDS_WR_CTRL, ISP32_MI_MPDS_WR_CTRL);
-			rkisp_update_regs(dev, ISP3X_BAY3D_CTRL, ISP3X_BAY3D_CTRL);
 		}
 	} else {
-		/* disabled bay3d and mi. rv1106 sdmmc workaround, 3a_wr no close */
+		/* disabled mi. rv1106 sdmmc workaround, 3a_wr no close */
 		writel(CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN,
 		       hw->base_addr + ISP3X_MI_WR_CTRL);
-		if (dev->isp_ver == ISP_V21) {
-			writel(0, hw->base_addr + ISP21_BAY3D_CTRL);
-		} else if (dev->isp_ver == ISP_V30) {
+		if (dev->isp_ver == ISP_V30) {
 			writel(0, hw->base_addr + ISP3X_MPFBC_CTRL);
 			writel(0, hw->base_addr + ISP3X_MI_BP_WR_CTRL);
-			writel(0, hw->base_addr + ISP3X_BAY3D_CTRL);
 			writel(0xc, hw->base_addr + ISP3X_SWS_CFG);
-			if (hw->is_unite) {
+			if (hw->unite == ISP_UNITE_TWO) {
 				writel(0, hw->base_next_addr + ISP3X_MI_WR_CTRL);
 				writel(0, hw->base_next_addr + ISP3X_MPFBC_CTRL);
 				writel(0, hw->base_next_addr + ISP3X_MI_BP_WR_CTRL);
-				writel(0, hw->base_next_addr + ISP3X_BAY3D_CTRL);
 				writel(0xc, hw->base_next_addr + ISP3X_SWS_CFG);
 			}
 		} else if (dev->isp_ver == ISP_V32) {
 			writel(0, hw->base_addr + ISP3X_MI_BP_WR_CTRL);
 			writel(0, hw->base_addr + ISP32_MI_BPDS_WR_CTRL);
 			writel(0, hw->base_addr + ISP32_MI_MPDS_WR_CTRL);
-			writel(0, hw->base_addr + ISP3X_BAY3D_CTRL);
 		}
 	}
-	rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true, hw->is_unite);
+	rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true);
 }
 
 /*
@@ -602,7 +588,8 @@
 	hw->cur_dev_id = dev->dev_id;
 	rkisp_dmarx_get_frame(dev, &cur_frame_id, NULL, NULL, true);
 
-	if (hw->is_multi_overflow && is_try)
+	/* isp process the same frame */
+	if (is_try)
 		goto run_next;
 
 	val = 0;
@@ -632,13 +619,12 @@
 	}
 
 	if (rd_mode != dev->rd_mode) {
-		rkisp_unite_set_bits(dev, ISP_HDRMGE_BASE, ISP_HDRMGE_MODE_MASK,
-				     val, false, hw->is_unite);
+		rkisp_unite_set_bits(dev, ISP_HDRMGE_BASE, ISP_HDRMGE_MODE_MASK, val, false);
 		dev->skip_frame = 2;
 		is_upd = true;
 	}
 
-	if (dev->isp_ver == ISP_V20 && dev->dmarx_dev.trigger == T_MANUAL && !is_try) {
+	if (dev->isp_ver == ISP_V20 && dev->dmarx_dev.trigger == T_MANUAL) {
 		if (dev->rd_mode != rd_mode && dev->br_dev.en) {
 			tmp = dev->isp_sdev.in_crop.height;
 			val = rkisp_read(dev, CIF_DUAL_CROP_CTRL, false);
@@ -659,12 +645,15 @@
 	}
 	dev->rd_mode = rd_mode;
 
-	rkisp_params_first_cfg(&dev->params_vdev, &dev->isp_sdev.in_fmt,
-			       dev->isp_sdev.quantization);
-	rkisp_params_cfg(params_vdev, cur_frame_id);
-	rkisp_config_cmsk(dev);
-	rkisp_stream_frame_start(dev, 0);
-	if (!hw->is_single && !is_try) {
+	if (hw->unite != ISP_UNITE_ONE || dev->unite_index == ISP_UNITE_LEFT) {
+		rkisp_params_first_cfg(&dev->params_vdev, &dev->isp_sdev.in_fmt,
+				       dev->isp_sdev.quantization);
+		rkisp_params_cfg(params_vdev, cur_frame_id);
+		rkisp_config_cmsk(dev);
+		rkisp_stream_frame_start(dev, 0);
+	}
+
+	if (!hw->is_single) {
 		/* multi sensor need to reset isp resize mode if scale up */
 		val = 0;
 		if (rkisp_read(dev, ISP3X_MAIN_RESIZE_CTRL, true) & 0xf0)
@@ -700,7 +689,7 @@
 		} else {
 			if (dev->isp_ver == ISP_V32_L)
 				rkisp_write(dev, ISP32_SELF_SCALE_UPDATE, ISP32_SCALE_FORCE_UPD, true);
-			rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true, hw->is_unite);
+			rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true);
 		}
 		/* sensor mode & index */
 		if (dev->isp_ver >= ISP_V21) {
@@ -711,7 +700,7 @@
 			else
 				val |= ISP21_SENSOR_MODE(dev->multi_mode);
 			writel(val, hw->base_addr + ISP_ACQ_H_OFFS);
-			if (hw->is_unite)
+			if (hw->unite == ISP_UNITE_TWO)
 				writel(val, hw->base_next_addr + ISP_ACQ_H_OFFS);
 			v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
 				 "sensor mode:%d index:%d | 0x%x\n",
@@ -731,36 +720,98 @@
 	else
 		dev->rdbk_cnt_x1++;
 	dev->rdbk_cnt++;
-
-	rkisp_params_cfgsram(params_vdev);
-	params_vdev->rdbk_times = dma2frm + 1;
+	if (dev->isp_ver == ISP_V20)
+		params_vdev->rdbk_times = dma2frm + 1;
 
 run_next:
-	if (hw->is_multi_overflow && !dev->is_first_double) {
-		stats_vdev->rdbk_drop = false;
-		if (dev->sw_rd_cnt) {
-			rkisp_multi_overflow_hdl(dev, false);
-			params_vdev->rdbk_times += dev->sw_rd_cnt;
-			stats_vdev->rdbk_drop = true;
-			is_upd = true;
-		} else if (is_try) {
+	rkisp_params_cfgsram(params_vdev, true);
+	stats_vdev->rdbk_drop = false;
+	if (dev->is_frame_double) {
+		is_upd = true;
+		if (is_try) {
+			/* the frame second running to on mi */
 			rkisp_multi_overflow_hdl(dev, true);
-			is_upd = true;
+			rkisp_update_regs(dev, ISP_LDCH_BASE, ISP_LDCH_BASE);
+
+			val = ISP3X_YNR_FST_FRAME | ISP3X_DHAZ_FST_FRAME | ISP3X_CNR_FST_FRAME;
+			if (dev->isp_ver == ISP_V32)
+				val |= ISP32_SHP_FST_FRAME;
+			else
+				val |= ISP3X_CNR_FST_FRAME;
+			rkisp_unite_clear_bits(dev, ISP3X_ISP_CTRL1, val, false);
+			val = rkisp_read_reg_cache(dev, ISP3X_DRC_IIRWG_GAIN);
+			writel(val, hw->base_addr + ISP3X_DRC_IIRWG_GAIN);
+			if (hw->unite == ISP_UNITE_TWO)
+				writel(val, hw->base_next_addr + ISP3X_DRC_IIRWG_GAIN);
+			val = rkisp_read_reg_cache(dev, ISP3X_DRC_EXPLRATIO);
+			writel(val, hw->base_addr + ISP3X_DRC_EXPLRATIO);
+			if (hw->unite == ISP_UNITE_TWO)
+				writel(val, hw->base_next_addr + ISP3X_DRC_EXPLRATIO);
+			val = rkisp_read_reg_cache(dev, ISP3X_YNR_GLOBAL_CTRL);
+			writel(val, hw->base_addr + ISP3X_YNR_GLOBAL_CTRL);
+			if (hw->unite == ISP_UNITE_TWO)
+				writel(val, hw->base_next_addr + ISP3X_YNR_GLOBAL_CTRL);
+			if (dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) {
+				val = rkisp_read_reg_cache(dev, ISP3X_CNR_CTRL);
+				writel(val, hw->base_addr + ISP3X_CNR_CTRL);
+				if (hw->unite == ISP_UNITE_TWO)
+					writel(val, hw->base_next_addr + ISP3X_CNR_CTRL);
+			}
+		} else {
+			/* the frame first running to off mi to save bandwidth */
+			rkisp_multi_overflow_hdl(dev, false);
+
+			/* FST_FRAME no to read sram thumb */
+			val = ISP3X_YNR_FST_FRAME | ISP3X_DHAZ_FST_FRAME;
+			if (dev->isp_ver == ISP_V32)
+				val |= ISP32_SHP_FST_FRAME;
+			else
+				val |= ISP3X_CNR_FST_FRAME;
+			rkisp_unite_set_bits(dev, ISP3X_ISP_CTRL1, 0, val, false);
+			/* ADRC low iir thumb weight for first sensor switch */
+			val = rkisp_read_reg_cache(dev, ISP3X_DRC_IIRWG_GAIN);
+			val &= ~ISP3X_DRC_IIR_WEIGHT_MASK;
+			writel(val, hw->base_addr + ISP3X_DRC_IIRWG_GAIN);
+			if (hw->unite == ISP_UNITE_TWO)
+				writel(val, hw->base_next_addr + ISP3X_DRC_IIRWG_GAIN);
+			/* ADRC iir5x5 and cur3x3 weight */
+			val = rkisp_read_reg_cache(dev, ISP3X_DRC_EXPLRATIO);
+			val &= ~ISP3X_DRC_WEIPRE_FRAME_MASK;
+			writel(val, hw->base_addr + ISP3X_DRC_EXPLRATIO);
+			if (hw->unite == ISP_UNITE_TWO)
+				writel(val, hw->base_next_addr + ISP3X_DRC_EXPLRATIO);
+			/* YNR_THUMB_MIX_CUR_EN for thumb read addr to 0 */
+			val = rkisp_read_reg_cache(dev, ISP3X_YNR_GLOBAL_CTRL);
+			val |= ISP3X_YNR_THUMB_MIX_CUR_EN;
+			writel(val, hw->base_addr + ISP3X_YNR_GLOBAL_CTRL);
+			if (hw->unite == ISP_UNITE_TWO)
+				writel(val, hw->base_next_addr + ISP3X_YNR_GLOBAL_CTRL);
+			if (dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) {
+				/* CNR_THUMB_MIX_CUR_EN for thumb read addr to 0 */
+				val = rkisp_read_reg_cache(dev, ISP3X_CNR_CTRL);
+				val |= ISP3X_CNR_THUMB_MIX_CUR_EN;
+				writel(val, hw->base_addr + ISP3X_CNR_CTRL);
+				if (hw->unite == ISP_UNITE_TWO)
+					writel(val, hw->base_next_addr + ISP3X_CNR_CTRL);
+			}
+			stats_vdev->rdbk_drop = true;
 		}
 	}
 
-	/* read 3d lut at frame end */
+	/* disable isp force update to read 3dlut
+	 * 3dlut auto update at frame end for single sensor
+	 */
 	if (hw->is_single && is_upd &&
 	    rkisp_read_reg_cache(dev, ISP_3DLUT_UPDATE) & 0x1) {
-		rkisp_unite_write(dev, ISP_3DLUT_UPDATE, 0, true, hw->is_unite);
+		rkisp_unite_write(dev, ISP_3DLUT_UPDATE, 0, true);
 		is_3dlut_upd = true;
 	}
 	if (is_upd) {
 		val = rkisp_read(dev, ISP_CTRL, false);
 		val |= CIF_ISP_CTRL_ISP_CFG_UPD;
-		rkisp_unite_write(dev, ISP_CTRL, val, true, hw->is_unite);
+		rkisp_unite_write(dev, ISP_CTRL, val, true);
 		/* bayer pat after ISP_CFG_UPD for multi sensor to read lsc r/g/b table */
-		rkisp_update_regs(dev, ISP_ACQ_PROP, ISP_ACQ_PROP);
+		rkisp_update_regs(dev, ISP3X_ISP_CTRL1, ISP3X_ISP_CTRL1);
 		/* fix ldch multi sensor case:
 		 * ldch will pre-read data when en and isp force upd or frame end,
 		 * udelay for ldch pre-read data.
@@ -771,12 +822,12 @@
 			udelay(50);
 			val &= ~(BIT(0) | BIT(31));
 			writel(val, hw->base_addr + ISP_LDCH_BASE);
-			if (hw->is_unite)
+			if (hw->unite == ISP_UNITE_TWO)
 				writel(val, hw->base_next_addr + ISP_LDCH_BASE);
 		}
 	}
 	if (is_3dlut_upd)
-		rkisp_unite_write(dev, ISP_3DLUT_UPDATE, 1, true, hw->is_unite);
+		rkisp_unite_write(dev, ISP_3DLUT_UPDATE, 1, true);
 
 	/* if output stream enable, wait it end */
 	val = rkisp_read(dev, CIF_MI_CTRL_SHD, true);
@@ -807,11 +858,13 @@
 	val &= ~SW_IBUF_OP_MODE(0xf);
 	tmp = SW_IBUF_OP_MODE(dev->rd_mode);
 	val |= tmp | SW_CSI2RX_EN | SW_DMA_2FRM_MODE(dma2frm);
+	if (dev->isp_ver > ISP_V20)
+		dma2frm = dev->sw_rd_cnt;
 	v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
-		 "readback frame:%d time:%d 0x%x\n",
-		 cur_frame_id, dma2frm + 1, val);
+		 "readback frame:%d time:%d 0x%x try:%d\n",
+		 cur_frame_id, dma2frm + 1, val, is_try);
 	if (!hw->is_shutdown)
-		rkisp_unite_write(dev, CSI2RX_CTRL0, val, true, hw->is_unite);
+		rkisp_unite_write(dev, CSI2RX_CTRL0, val, true);
 }
 
 static void rkisp_fast_switch_rx_buf(struct rkisp_device *dev, bool is_current)
@@ -819,6 +872,9 @@
 	struct rkisp_stream *stream;
 	struct rkisp_buffer *buf;
 	u32 i, val;
+
+	if (!dev->is_rtt_first)
+		return;
 
 	for (i = RKISP_STREAM_RAWRD0; i < RKISP_MAX_DMARX_STREAM; i++) {
 		stream = &dev->dmarx_dev.stream[i];
@@ -865,6 +921,12 @@
 			isp = dev;
 			is_try = true;
 			times = 0;
+			if (hw->unite == ISP_UNITE_ONE) {
+				if (dev->sw_rd_cnt < 2)
+					isp->unite_index = ISP_UNITE_RIGHT;
+				if (!hw->is_multi_overflow || (dev->sw_rd_cnt & 0x1))
+					is_try = false;
+			}
 			goto end;
 		}
 		hw->is_idle = true;
@@ -878,11 +940,16 @@
 		goto end;
 	if (!IS_HDR_RDBK(dev->rd_mode))
 		goto end;
+	if (dev->is_suspend) {
+		if (dev->suspend_sync)
+			complete(&dev->pm_cmpl);
+		goto end;
+	}
 
 	for (i = 0; i < hw->dev_num; i++) {
 		isp = hw->isp[i];
 		if (!isp ||
-		    (isp && !(isp->isp_state & ISP_START)))
+		    (isp && (!(isp->isp_state & ISP_START) || isp->is_suspend)))
 			continue;
 		rkisp_rdbk_trigger_event(isp, T_CMD_LEN, &len[i]);
 		if (max < len[i]) {
@@ -892,7 +959,7 @@
 	}
 
 	/* wait 2 frame to start isp for fast */
-	if (dev->is_pre_on && max == 1 && !atomic_read(&dev->isp_sdev.frm_sync_seq))
+	if (dev->is_rtt_first && max == 1 && !atomic_read(&dev->isp_sdev.frm_sync_seq))
 		goto end;
 
 	if (max) {
@@ -914,17 +981,42 @@
 		times = t.times;
 		hw->cur_dev_id = id;
 		hw->is_idle = false;
+		/* this frame will read count by isp */
 		isp->sw_rd_cnt = 0;
-		if (hw->is_multi_overflow && (hw->pre_dev_id != id)) {
+		/* frame double for multi camera resolution out of hardware limit
+		 * first for HW save this camera information, and second to output image
+		 */
+		isp->is_frame_double = false;
+		if (hw->is_multi_overflow &&
+		    (hw->unite == ISP_UNITE_ONE ||
+		     (hw->pre_dev_id != -1 && hw->pre_dev_id != id))) {
+			isp->is_frame_double = true;
 			isp->sw_rd_cnt = 1;
 			times = 0;
 		}
-		if (isp->is_pre_on && t.frame_id == 0) {
+		/* resolution out of hardware limit
+		 * frame is vertically divided into left and right
+		 */
+		isp->unite_index = ISP_UNITE_LEFT;
+		if (hw->unite == ISP_UNITE_ONE) {
+			isp->sw_rd_cnt *= 2;
+			isp->sw_rd_cnt += 1;
+		}
+		/* first frame handle twice for thunderboot
+		 * first output stats to AIQ and wait new params to run second
+		 */
+		if (isp->is_rtt_first && t.frame_id == 0) {
 			isp->is_first_double = true;
 			isp->skip_frame = 1;
-			isp->sw_rd_cnt = 0;
+			if (hw->unite != ISP_UNITE_ONE) {
+				isp->sw_rd_cnt = 0;
+				isp->is_frame_double = false;
+			}
 			rkisp_fast_switch_rx_buf(isp, false);
+		} else {
+			isp->is_rtt_first = false;
 		}
+		isp->params_vdev.rdbk_times = isp->sw_rd_cnt + 1;
 	}
 end:
 	spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags);
@@ -982,12 +1074,6 @@
 {
 	u32 val = 0;
 
-	if (dev->hw_dev->is_multi_overflow &&
-	    dev->sw_rd_cnt &&
-	    irq & ISP_FRAME_END &&
-	    !dev->is_first_double)
-		goto end;
-
 	dev->irq_ends |= (irq & dev->irq_ends_mask);
 	v4l2_dbg(3, rkisp_debug, &dev->v4l2_dev,
 		 "%s irq:0x%x ends:0x%x mask:0x%x\n",
@@ -1002,8 +1088,12 @@
 	    !IS_HDR_RDBK(dev->rd_mode))
 		return;
 
+	if (dev->sw_rd_cnt)
+		goto end;
+
 	if (dev->is_first_double) {
 		rkisp_fast_switch_rx_buf(dev, true);
+		dev->is_rtt_first = false;
 		dev->skip_frame = 0;
 		dev->irq_ends = 0;
 		return;
@@ -1068,26 +1158,25 @@
 {
 	struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
 	u32 width = out_crop->width, mult = 1;
-	bool is_unite = dev->hw_dev->is_unite;
+	u32 unite = dev->hw_dev->unite;
 
 	/* isp2.0 no ism */
 	if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21 ||
 	    dev->isp_ver == ISP_V32_L)
 		return;
 
-	if (is_unite)
+	if (unite)
 		width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
-	rkisp_unite_write(dev, CIF_ISP_IS_RECENTER, 0, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_IS_MAX_DX, 0, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_IS_MAX_DY, 0, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_IS_DISPLACE, 0, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_IS_H_OFFS, out_crop->left, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_IS_V_OFFS, out_crop->top, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_IS_H_SIZE, width, false, is_unite);
+	rkisp_unite_write(dev, CIF_ISP_IS_RECENTER, 0, false);
+	rkisp_unite_write(dev, CIF_ISP_IS_MAX_DX, 0, false);
+	rkisp_unite_write(dev, CIF_ISP_IS_MAX_DY, 0, false);
+	rkisp_unite_write(dev, CIF_ISP_IS_DISPLACE, 0, false);
+	rkisp_unite_write(dev, CIF_ISP_IS_H_OFFS, out_crop->left, false);
+	rkisp_unite_write(dev, CIF_ISP_IS_V_OFFS, out_crop->top, false);
+	rkisp_unite_write(dev, CIF_ISP_IS_H_SIZE, width, false);
 	if (dev->cap_dev.stream[RKISP_STREAM_SP].interlaced)
 		mult = 2;
-	rkisp_unite_write(dev, CIF_ISP_IS_V_SIZE, out_crop->height / mult,
-			  false, is_unite);
+	rkisp_unite_write(dev, CIF_ISP_IS_V_SIZE, out_crop->height / mult, false);
 
 	if (dev->isp_ver == ISP_V30 || dev->isp_ver == ISP_V32)
 		return;
@@ -1096,86 +1185,19 @@
 	rkisp_write(dev, CIF_ISP_IS_CTRL, 1, false);
 }
 
-static int rkisp_reset_handle_v2x(struct rkisp_device *dev)
+static int rkisp_reset_handle(struct rkisp_device *dev)
 {
-	void __iomem *base = dev->base_addr;
-	void *reg_buf = NULL;
-	u32 *reg, *reg1, i;
-	struct backup_reg backup[] = {
-		{
-			.base = MI_MP_WR_Y_BASE,
-			.shd = MI_MP_WR_Y_BASE_SHD,
-		}, {
-			.base = MI_MP_WR_CB_BASE,
-			.shd = MI_MP_WR_CB_BASE_SHD,
-		}, {
-			.base = MI_MP_WR_CR_BASE,
-			.shd = MI_MP_WR_CR_BASE_SHD,
-		}, {
-			.base = MI_SP_WR_Y_BASE,
-			.shd = MI_SP_WR_Y_BASE_SHD,
-		}, {
-			.base = MI_SP_WR_CB_BASE,
-			.shd = MI_SP_WR_CB_BASE_AD_SHD,
-		}, {
-			.base = MI_SP_WR_CR_BASE,
-			.shd = MI_SP_WR_CR_BASE_AD_SHD,
-		}, {
-			.base = MI_RAW0_WR_BASE,
-			.shd = MI_RAW0_WR_BASE_SHD,
-		}, {
-			.base = MI_RAW1_WR_BASE,
-			.shd = MI_RAW1_WR_BASE_SHD,
-		}, {
-			.base = MI_RAW2_WR_BASE,
-			.shd = MI_RAW2_WR_BASE_SHD,
-		}, {
-			.base = MI_RAW3_WR_BASE,
-			.shd = MI_RAW3_WR_BASE_SHD,
-		}, {
-			.base = MI_RAW0_RD_BASE,
-			.shd = MI_RAW0_RD_BASE_SHD,
-		}, {
-			.base = MI_RAW1_RD_BASE,
-			.shd = MI_RAW1_RD_BASE_SHD,
-		}, {
-			.base = MI_RAW2_RD_BASE,
-			.shd = MI_RAW2_RD_BASE_SHD,
-		}, {
-			.base = MI_GAIN_WR_BASE,
-			.shd = MI_GAIN_WR_BASE_SHD,
-		}
-	};
-
-	reg_buf = kzalloc(RKISP_ISP_SW_REG_SIZE, GFP_KERNEL);
-	if (!reg_buf)
-		return -ENOMEM;
+	u32 val;
 
 	dev_info(dev->dev, "%s enter\n", __func__);
+	rkisp_hw_reg_save(dev->hw_dev);
 
-	memcpy_fromio(reg_buf, base, RKISP_ISP_SW_REG_SIZE);
 	rkisp_soft_reset(dev->hw_dev, true);
 
-	/* process special reg */
-	reg = reg_buf + ISP_CTRL;
-	*reg &= ~(CIF_ISP_CTRL_ISP_ENABLE |
-		  CIF_ISP_CTRL_ISP_INFORM_ENABLE |
-		  CIF_ISP_CTRL_ISP_CFG_UPD);
-	reg = reg_buf + MI_WR_INIT;
-	*reg = 0;
-	reg = reg_buf + CSI2RX_CTRL0;
-	*reg &= ~SW_CSI2RX_EN;
-	/* skip mmu range */
-	memcpy_toio(base, reg_buf, ISP21_MI_BAY3D_RD_BASE_SHD);
-	memcpy_toio(base + CSI2RX_CTRL0, reg_buf + CSI2RX_CTRL0,
-		    RKISP_ISP_SW_REG_SIZE - CSI2RX_CTRL0);
-	/* config shd_reg to base_reg */
-	for (i = 0; i < ARRAY_SIZE(backup); i++) {
-		reg = reg_buf + backup[i].base;
-		reg1 = reg_buf + backup[i].shd;
-		backup[i].val = *reg;
-		writel(*reg1, base + backup[i].base);
-	}
+	rkisp_hw_reg_restore(dev->hw_dev);
+
+	val = CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR;
+	rkisp_unite_set_bits(dev, CIF_ISP_IMSC, 0, val, true);
 
 	/* clear state */
 	dev->isp_err_cnt = 0;
@@ -1183,40 +1205,12 @@
 	rkisp_set_state(&dev->isp_state, ISP_FRAME_END);
 	dev->hw_dev->monitor.state = ISP_FRAME_END;
 
-	/* update module */
-	reg = reg_buf + DUAL_CROP_CTRL;
-	if (*reg & 0xf)
-		writel(*reg | CIF_DUAL_CROP_CFG_UPD, base + DUAL_CROP_CTRL);
-	reg = reg_buf + SELF_RESIZE_CTRL;
-	if (*reg & 0xf)
-		writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + SELF_RESIZE_CTRL);
-	reg = reg_buf + MAIN_RESIZE_CTRL;
-	if (*reg & 0xf)
-		writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + MAIN_RESIZE_CTRL);
-
-	/* update mi and isp, base_reg will update to shd_reg */
-	force_cfg_update(dev);
-	reg = reg_buf + ISP_CTRL;
-	*reg |= CIF_ISP_CTRL_ISP_ENABLE |
-		CIF_ISP_CTRL_ISP_INFORM_ENABLE |
-		CIF_ISP_CTRL_ISP_CFG_UPD;
-	writel(*reg, base + ISP_CTRL);
-	udelay(50);
-	/* config base_reg */
-	for (i = 0; i < ARRAY_SIZE(backup); i++)
-		writel(backup[i].val, base + backup[i].base);
-	/* mpfbc base_reg = shd_reg, write is base but read is shd */
-	if (dev->isp_ver == ISP_V20)
-		writel(rkisp_read_reg_cache(dev, ISP_MPFBC_HEAD_PTR),
-		       base + ISP_MPFBC_HEAD_PTR);
-	rkisp_set_bits(dev, CIF_ISP_IMSC, 0, CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR, true);
 	if (IS_HDR_RDBK(dev->hdr.op_mode)) {
 		if (!dev->hw_dev->is_idle)
 			rkisp_trigger_read_back(dev, 1, 0, true);
 		else
 			rkisp_rdbk_trigger_event(dev, T_CMD_QUEUE, NULL);
 	}
-	kfree(reg_buf);
 	dev_info(dev->dev, "%s exit\n", __func__);
 	return 0;
 }
@@ -1230,11 +1224,6 @@
 	struct rkisp_pipeline *p;
 	int ret, i, j, timeout = 5, mipi_irq_cnt = 0;
 
-	if (!monitor->reset_handle) {
-		monitor->is_en = false;
-		return;
-	}
-
 	dev_info(hw->dev, "%s enter\n", __func__);
 	while (!(monitor->state & ISP_STOP) && monitor->is_en) {
 		ret = wait_for_completion_timeout(&monitor->cmpl,
@@ -1242,8 +1231,11 @@
 		/* isp stop to exit
 		 * isp err to reset
 		 * mipi err wait isp idle, then reset
+		 * online vicap if isp err, notify vicap reset, then vicap notify isp reset
+		 * by ioctl RKISP_VICAP_CMD_SET_STREAM
 		 */
 		if (monitor->state & ISP_STOP ||
+		    monitor->state & ISP_CIF_RESET ||
 		    (ret && !(monitor->state & ISP_ERROR)) ||
 		    (!ret &&
 		     monitor->state & ISP_FRAME_END &&
@@ -1292,10 +1284,22 @@
 
 		/* restart isp */
 		isp = hw->isp[hw->cur_dev_id];
-		ret = monitor->reset_handle(isp);
-		if (ret) {
-			monitor->is_en = false;
-			break;
+		if (!IS_HDR_RDBK(isp->hdr.op_mode) && isp->isp_ver >= ISP_V30) {
+			struct v4l2_subdev *remote = NULL;
+			struct v4l2_subdev *isp_subdev = NULL;
+
+			isp_subdev = &(isp->isp_sdev.sd);
+			remote = get_remote_sensor(isp_subdev);
+			v4l2_subdev_call(remote, core, ioctl,
+				RKISP_VICAP_CMD_SET_RESET, NULL);
+			monitor->state |= ISP_CIF_RESET;
+			continue;
+		} else {
+			ret = rkisp_reset_handle(isp);
+			if (ret) {
+				monitor->is_en = false;
+				break;
+			}
 		}
 
 		for (i = 0; i < hw->dev_num; i++) {
@@ -1329,9 +1333,6 @@
 	struct rkisp_monitor *monitor = &dev->hw_dev->monitor;
 
 	monitor->dev = dev->hw_dev;
-	monitor->reset_handle = NULL;
-	if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21)
-		monitor->reset_handle = rkisp_reset_handle_v2x;
 
 	init_completion(&monitor->cmpl);
 	INIT_WORK(&monitor->work, rkisp_restart_monitor);
@@ -1389,20 +1390,18 @@
 
 	for (i = 0; i < 9; i++)
 		rkisp_unite_write(dev, CIF_ISP_CC_COEFF_0 + i * 4,
-				  *(coeff + i), false, dev->hw_dev->is_unite);
+				  *(coeff + i), false);
 
 	val = rkisp_read_reg_cache(dev, CIF_ISP_CTRL);
 
 	if (dev->isp_sdev.quantization == V4L2_QUANTIZATION_FULL_RANGE)
 		rkisp_unite_write(dev, CIF_ISP_CTRL, val |
 				  CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
-				  CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA,
-				  false, dev->hw_dev->is_unite);
+				  CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA, false);
 	else
 		rkisp_unite_write(dev, CIF_ISP_CTRL, val &
 				  ~(CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA |
-				  CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA),
-				  false, dev->hw_dev->is_unite);
+				  CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA), false);
 }
 
 static void rkisp_config_cmsk_single(struct rkisp_device *dev,
@@ -1498,6 +1497,7 @@
 			left.win[0].win_en &= ~BIT(i);
 			left.win[1].win_en &= ~BIT(i);
 			left.win[2].win_en &= ~BIT(i);
+			right.win[i].h_offs = h_offs - w + RKMOUDLE_UNITE_EXTEND_PIXEL;
 		} else {
 			/* cmsk window at dual isp */
 			left.win[i].h_size = ALIGN(w - h_offs, 8);
@@ -1601,7 +1601,7 @@
 	cfg = dev->cmsk_cfg;
 	spin_unlock_irqrestore(&dev->cmsk_lock, lock_flags);
 
-	if (!dev->hw_dev->is_unite)
+	if (!dev->hw_dev->unite)
 		rkisp_config_cmsk_single(dev, &cfg);
 	else
 		rkisp_config_cmsk_dual(dev, &cfg);
@@ -1616,7 +1616,7 @@
 	struct ispsd_out_fmt *out_fmt;
 	struct v4l2_rect *in_crop;
 	struct rkisp_sensor_info *sensor;
-	bool is_unite = dev->hw_dev->is_unite;
+	bool is_unite = !!dev->hw_dev->unite;
 	u32 isp_ctrl = 0;
 	u32 irq_mask = 0;
 	u32 signal = 0;
@@ -1646,22 +1646,20 @@
 			    in_fmt->mbus_code == MEDIA_BUS_FMT_Y10_1X10 ||
 			    in_fmt->mbus_code == MEDIA_BUS_FMT_Y12_1X12) {
 				if (dev->isp_ver >= ISP_V20)
-					rkisp_unite_write(dev, ISP_DEBAYER_CONTROL,
-							  0, false, is_unite);
+					rkisp_unite_write(dev, ISP_DEBAYER_CONTROL, 0, false);
 				else
 					rkisp_write(dev, CIF_ISP_DEMOSAIC,
-						CIF_ISP_DEMOSAIC_BYPASS |
-						CIF_ISP_DEMOSAIC_TH(0xc), false);
+						    CIF_ISP_DEMOSAIC_BYPASS |
+						    CIF_ISP_DEMOSAIC_TH(0xc), false);
 			} else {
 				if (dev->isp_ver >= ISP_V20)
 					rkisp_unite_write(dev, ISP_DEBAYER_CONTROL,
 							  SW_DEBAYER_EN |
 							  SW_DEBAYER_FILTER_G_EN |
-							  SW_DEBAYER_FILTER_C_EN,
-							  false, is_unite);
+							  SW_DEBAYER_FILTER_C_EN, false);
 				else
 					rkisp_write(dev, CIF_ISP_DEMOSAIC,
-						CIF_ISP_DEMOSAIC_TH(0xc), false);
+						    CIF_ISP_DEMOSAIC_TH(0xc), false);
 			}
 
 			if (sensor && sensor->mbus.type == V4L2_MBUS_BT656)
@@ -1714,38 +1712,31 @@
 	if (rkisp_read_reg_cache(dev, CIF_ISP_CTRL) & ISP32_MIR_ENABLE)
 		isp_ctrl |= ISP32_MIR_ENABLE;
 
-	rkisp_unite_write(dev, CIF_ISP_CTRL, isp_ctrl, false, is_unite);
+	rkisp_unite_write(dev, CIF_ISP_CTRL, isp_ctrl, false);
 	acq_prop |= signal | in_fmt->yuv_seq |
 		CIF_ISP_ACQ_PROP_BAYER_PAT(in_fmt->bayer_pat) |
 		CIF_ISP_ACQ_PROP_FIELD_SEL_ALL;
-	rkisp_unite_write(dev, CIF_ISP_ACQ_PROP, acq_prop, false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true, is_unite);
+	rkisp_unite_write(dev, CIF_ISP_ACQ_PROP, acq_prop, false);
+	rkisp_unite_write(dev, CIF_ISP_ACQ_NR_FRAMES, 0, true);
 
 	if (is_unite)
 		width = width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
 	/* Acquisition Size */
-	rkisp_unite_write(dev, CIF_ISP_ACQ_H_OFFS, acq_mult * in_crop->left,
-			  false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_ACQ_V_OFFS, in_crop->top,
-			  false, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_ACQ_H_SIZE, acq_mult * width,
-			  false, is_unite);
+	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);
+	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, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true, is_unite);
-	rkisp_unite_write(dev, CIF_ISP_OUT_H_SIZE, width, false, is_unite);
+	rkisp_unite_write(dev, CIF_ISP_OUT_H_OFFS, 0, true);
+	rkisp_unite_write(dev, CIF_ISP_OUT_V_OFFS, 0, true);
+	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, in_crop->height / 2,
-				  false, is_unite);
-		rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height / 2,
-				  false, is_unite);
+		rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height / 2, false);
+		rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height / 2, false);
 	} else {
-		rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height + extend_line,
-				  false, is_unite);
-		rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height + extend_line,
-				  false, is_unite);
+		rkisp_unite_write(dev, CIF_ISP_ACQ_V_SIZE, in_crop->height + extend_line, false);
+		rkisp_unite_write(dev, CIF_ISP_OUT_V_SIZE, in_crop->height + extend_line, false);
 	}
 
 	/* interrupt mask */
@@ -1754,7 +1745,7 @@
 		irq_mask |= ISP2X_LSC_LUT_ERR;
 	if (dev->is_pre_on)
 		irq_mask |= CIF_ISP_FRAME_IN;
-	rkisp_unite_write(dev, CIF_ISP_IMSC, irq_mask, true, is_unite);
+	rkisp_unite_write(dev, CIF_ISP_IMSC, irq_mask, true);
 
 	if ((dev->isp_ver == ISP_V20 ||
 	     dev->isp_ver == ISP_V21) &&
@@ -1909,8 +1900,7 @@
 	if (dev->isp_ver == ISP_V32)
 		dpcl |= BIT(0);
 
-	rkisp_unite_set_bits(dev, CIF_VI_DPCL, 0, dpcl, true,
-			     dev->hw_dev->is_unite);
+	rkisp_unite_set_bits(dev, CIF_VI_DPCL, 0, dpcl, true);
 	return ret;
 }
 
@@ -2007,9 +1997,9 @@
 
 	v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
 		 "%s refcnt:%d\n", __func__,
-		 atomic_read(&dev->hw_dev->refcnt));
+		 atomic_read(&hw->refcnt));
 
-	if (atomic_read(&dev->hw_dev->refcnt) > 1)
+	if (atomic_read(&hw->refcnt) > 1)
 		goto end;
 	/*
 	 * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
@@ -2065,7 +2055,7 @@
 
 	val = readl(base + CIF_ISP_CTRL);
 	writel(val | CIF_ISP_CTRL_ISP_CFG_UPD, base + CIF_ISP_CTRL);
-	if (hw->is_unite)
+	if (hw->unite == ISP_UNITE_TWO)
 		rkisp_next_write(dev, CIF_ISP_CTRL,
 				 val | CIF_ISP_CTRL_ISP_CFG_UPD, true);
 
@@ -2082,11 +2072,11 @@
 		safe_rate = hw->clk_rate_tbl[0].clk_rate * 1000000UL;
 		if (old_rate > safe_rate) {
 			rkisp_set_clk_rate(hw->clks[0], safe_rate);
-			if (hw->is_unite)
+			if (hw->unite == ISP_UNITE_TWO)
 				rkisp_set_clk_rate(hw->clks[5], safe_rate);
 			udelay(100);
 		}
-		rkisp_soft_reset(dev->hw_dev, false);
+		rkisp_soft_reset(hw, false);
 	}
 
 	if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) {
@@ -2097,18 +2087,20 @@
 		writel(0, base + CIF_ISP_CSI0_MASK3);
 	} else if (dev->isp_ver >= ISP_V20) {
 		writel(0, base + CSI2RX_CSI2_RESETN);
-		if (hw->is_unite)
+		if (hw->unite == ISP_UNITE_TWO)
 			rkisp_next_write(dev, CSI2RX_CSI2_RESETN, 0, true);
 	}
 
 	hw->is_dvfs = false;
 	hw->is_runing = false;
-	dev->hw_dev->is_idle = true;
-	dev->hw_dev->is_mi_update = false;
+	hw->is_idle = true;
+	hw->is_mi_update = false;
+	hw->pre_dev_id = -1;
 end:
 	dev->irq_ends_mask = 0;
 	dev->hdr.op_mode = 0;
 	dev->sw_rd_cnt = 0;
+	dev->stats_vdev.rdbk_drop = false;
 	rkisp_set_state(&dev->isp_state, ISP_STOP);
 
 	if (dev->isp_ver >= ISP_V20)
@@ -2154,12 +2146,9 @@
 			val = dev->isp_sdev.out_crop.height / 15;
 			val = dev->cap_dev.wait_line / val;
 			val = ISP3X_RAWAF_INELINE0(val) | ISP3X_RAWAF_INTLINE0_EN;
-			rkisp_unite_write(dev, ISP3X_RAWAF_INT_LINE,
-				val, false, dev->hw_dev->is_unite);
-			rkisp_unite_set_bits(dev, ISP_ISP3A_IMSC, 0,
-				ISP2X_3A_RAWAF, false, dev->hw_dev->is_unite);
-			rkisp_unite_clear_bits(dev, CIF_ISP_IMSC,
-				ISP2X_LSC_LUT_ERR, false, dev->hw_dev->is_unite);
+			rkisp_unite_write(dev, ISP3X_RAWAF_INT_LINE, val, false);
+			rkisp_unite_set_bits(dev, ISP_ISP3A_IMSC, 0, ISP2X_3A_RAWAF, false);
+			rkisp_unite_clear_bits(dev, CIF_ISP_IMSC, ISP2X_LSC_LUT_ERR, false);
 			dev->rawaf_irq_cnt = 0;
 		}
 	}
@@ -2187,12 +2176,11 @@
 		val |= NOC_HURRY_PRIORITY(2) | NOC_HURRY_W_MODE(2) | NOC_HURRY_R_MODE(1);
 	if (atomic_read(&dev->hw_dev->refcnt) > 1)
 		is_direct = false;
-	rkisp_unite_write(dev, CIF_ISP_CTRL, val, is_direct, dev->hw_dev->is_unite);
+	rkisp_unite_write(dev, CIF_ISP_CTRL, val, is_direct);
 	rkisp_clear_reg_cache_bits(dev, CIF_ISP_CTRL, CIF_ISP_CTRL_ISP_CFG_UPD);
 
 	dev->isp_err_cnt = 0;
 	dev->isp_isr_cnt = 0;
-	dev->isp_state = ISP_START | ISP_FRAME_END;
 	dev->irq_ends_mask |= ISP_FRAME_END;
 	dev->irq_ends = 0;
 
@@ -2668,14 +2656,16 @@
 				max_h = CIF_ISP_INPUT_H_MAX_V21;
 				break;
 			case ISP_V30:
-				max_w = dev->hw_dev->is_unite ?
+				max_w = dev->hw_dev->unite ?
 					CIF_ISP_INPUT_W_MAX_V30_UNITE : CIF_ISP_INPUT_W_MAX_V30;
-				max_h = dev->hw_dev->is_unite ?
+				max_h = dev->hw_dev->unite ?
 					CIF_ISP_INPUT_H_MAX_V30_UNITE : CIF_ISP_INPUT_H_MAX_V30;
 				break;
 			case ISP_V32:
-				max_w = CIF_ISP_INPUT_W_MAX_V32;
-				max_h = CIF_ISP_INPUT_H_MAX_V32;
+				max_w = dev->hw_dev->unite ?
+					CIF_ISP_INPUT_W_MAX_V32_UNITE : CIF_ISP_INPUT_W_MAX_V32;
+				max_h = dev->hw_dev->unite ?
+					CIF_ISP_INPUT_H_MAX_V32_UNITE : CIF_ISP_INPUT_H_MAX_V32;
 				break;
 			case ISP_V32_L:
 				max_w = CIF_ISP_INPUT_W_MAX_V32_L;
@@ -2865,6 +2855,7 @@
 {
 	struct rkisp_device *isp_dev = sd_to_isp_dev(sd);
 	struct rkisp_hw_dev *hw_dev = isp_dev->hw_dev;
+	int ret;
 
 	if (!on) {
 		if (IS_HDR_RDBK(isp_dev->rd_mode)) {
@@ -2877,10 +2868,13 @@
 					wake_up(&s->done);
 			}
 		}
-		wait_event_timeout(isp_dev->sync_onoff,
-				   isp_dev->isp_state & ISP_STOP ||
-				   !IS_HDR_RDBK(isp_dev->rd_mode),
-				   msecs_to_jiffies(50));
+		ret = wait_event_timeout(isp_dev->sync_onoff,
+					 isp_dev->isp_state & ISP_STOP ||
+					 !IS_HDR_RDBK(isp_dev->rd_mode),
+					 msecs_to_jiffies(500));
+		if (!ret)
+			v4l2_warn(&isp_dev->v4l2_dev, "%s wait timeout, mode:%d state:0x%x\n",
+				  __func__, isp_dev->rd_mode, isp_dev->isp_state);
 		rkisp_isp_stop(isp_dev);
 		atomic_dec(&hw_dev->refcnt);
 		rkisp_params_stream_stop(&isp_dev->params_vdev);
@@ -2901,6 +2895,7 @@
 	rkisp_config_cif(isp_dev);
 	rkisp_isp_start(isp_dev);
 	rkisp_global_update_mi(isp_dev);
+	isp_dev->isp_state = ISP_START | ISP_FRAME_END;
 	rkisp_rdbk_trigger_event(isp_dev, T_CMD_QUEUE, NULL);
 	return 0;
 }
@@ -2936,7 +2931,7 @@
 	u32 val = pool->buf.buff_addr[RKISP_PLANE_Y];
 
 	rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false);
-	if (dev->hw_dev->is_unite) {
+	if (dev->hw_dev->unite == ISP_UNITE_TWO) {
 		u32 offs = stream->out_fmt.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL;
 
 		if (stream->memory)
@@ -3054,7 +3049,8 @@
 
 	pool->dbufs = dbufs;
 	v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
-		 "%s type:0x%x dbufs[%d]:%p", __func__, dbufs->type, i, dbufs);
+		 "%s type:0x%x first:%d dbufs[%d]:%p", __func__,
+		 dbufs->type, dbufs->is_first, i, dbufs);
 
 	if (dbufs->is_resmem) {
 		dma = dbufs->dma;
@@ -3412,11 +3408,64 @@
 	if (dev->is_bigmode)
 		mode |= RKISP_ISP_BIGMODE;
 	info->mode = mode;
-	if (dev->hw_dev->is_unite)
+	if (dev->hw_dev->unite)
 		info->act_width = in_crop->width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
 	else
 		info->act_width = in_crop->width;
 	info->act_height = in_crop->height;
+	return 0;
+}
+
+static int rkisp_set_work_mode_by_vicap(struct rkisp_device *isp_dev,
+					struct rkisp_vicap_mode *vicap_mode)
+{
+	struct rkisp_hw_dev *hw = isp_dev->hw_dev;
+	int rd_mode = isp_dev->rd_mode;
+
+	isp_dev->is_suspend_one_frame = false;
+	if (vicap_mode->rdbk_mode == RKISP_VICAP_ONLINE) {
+		if (!hw->is_single)
+			return -EINVAL;
+		/* switch to online mode for single sensor */
+		switch (rd_mode) {
+		case HDR_RDBK_FRAME3:
+			isp_dev->rd_mode = HDR_LINEX3_DDR;
+			break;
+		case HDR_RDBK_FRAME2:
+			isp_dev->rd_mode = HDR_LINEX2_DDR;
+			break;
+		default:
+			isp_dev->rd_mode = HDR_NORMAL;
+		}
+	} else if (vicap_mode->rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
+		   vicap_mode->rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME) {
+		/* switch to readback mode */
+		switch (rd_mode) {
+		case HDR_LINEX3_DDR:
+			isp_dev->rd_mode = HDR_RDBK_FRAME3;
+			break;
+		case HDR_LINEX2_DDR:
+			isp_dev->rd_mode = HDR_RDBK_FRAME2;
+			break;
+		default:
+			isp_dev->rd_mode = HDR_RDBK_FRAME1;
+		}
+		if (vicap_mode->rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)
+			isp_dev->is_suspend_one_frame = true;
+	} else {
+		return -EINVAL;
+	}
+	isp_dev->hdr.op_mode = isp_dev->rd_mode;
+	if (rd_mode != isp_dev->rd_mode && hw->cur_dev_id == isp_dev->dev_id) {
+		rkisp_unite_write(isp_dev, CSI2RX_CTRL0,
+				  SW_IBUF_OP_MODE(isp_dev->rd_mode), true);
+		if (IS_HDR_RDBK(isp_dev->rd_mode))
+			rkisp_unite_set_bits(isp_dev, CTRL_SWS_CFG, 0,
+					     SW_MPIP_DROP_FRM_DIS, true);
+		else
+			rkisp_unite_clear_bits(isp_dev, CTRL_SWS_CFG,
+					       SW_MPIP_DROP_FRM_DIS, true);
+	}
 	return 0;
 }
 
@@ -3445,7 +3494,7 @@
 		rkisp_get_info(isp_dev, arg);
 		break;
 	case RKISP_CMD_GET_TB_HEAD_V32:
-		if (isp_dev->tb_head.complete != RKISP_TB_OK || !isp_dev->is_pre_on) {
+		if (isp_dev->tb_head.complete != RKISP_TB_OK) {
 			ret = -EINVAL;
 			break;
 		}
@@ -3543,6 +3592,16 @@
 			isp_dev->hw_dev->is_multi_overflow = false;
 			rkisp_hw_enum_isp_size(isp_dev->hw_dev);
 		}
+		break;
+	case RKISP_VICAP_CMD_SET_STREAM:
+		ret = rkisp_reset_handle(isp_dev);
+		if (!ret) {
+			if (isp_dev->hw_dev->monitor.state & ISP_CIF_RESET)
+				isp_dev->hw_dev->monitor.state &= ~ISP_CIF_RESET;
+		}
+		break;
+	case RKISP_VICAP_CMD_MODE:
+		ret = rkisp_set_work_mode_by_vicap(isp_dev, arg);
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -3646,6 +3705,9 @@
 	case RKISP_CMD_MULTI_DEV_FORCE_ENUM:
 		ret = rkisp_ioctl(sd, cmd, NULL);
 		break;
+	case RKISP_VICAP_CMD_SET_STREAM:
+		ret = rkisp_ioctl(sd, cmd, NULL);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 	}
@@ -3699,7 +3761,7 @@
 	struct ispsd_in_fmt *in_fmt = &isp_sd->in_fmt;
 	struct ispsd_out_fmt *out_fmt = &isp_sd->out_fmt;
 
-	*in_fmt = rkisp_isp_input_formats[0];
+	*in_fmt = rkisp_isp_input_formats[8];
 	in_frm->width = RKISP_DEFAULT_WIDTH;
 	in_frm->height = RKISP_DEFAULT_HEIGHT;
 	in_frm->code = in_fmt->mbus_code;
@@ -3765,6 +3827,7 @@
 	atomic_set(&isp_sdev->frm_sync_seq, 0);
 	rkisp_monitor_init(isp_dev);
 	INIT_WORK(&isp_dev->rdbk_work, rkisp_rdbk_work);
+	init_completion(&isp_dev->pm_cmpl);
 	return 0;
 err_cleanup_media_entity:
 	media_entity_cleanup(&sd->entity);
@@ -3804,9 +3867,54 @@
 	(cond) ? 0 : -ETIMEDOUT; \
 })
 
+void rkisp_save_tb_info(struct rkisp_device *isp_dev)
+{
+	struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
+	void *resmem_va = phys_to_virt(isp_dev->resmem_pa);
+	struct rkisp_thunderboot_resmem_head *head = resmem_va;
+	int size = 0, offset = 0;
+	void *param = NULL;
+
+	switch (isp_dev->isp_ver) {
+	case ISP_V32:
+		size = sizeof(struct rkisp32_thunderboot_resmem_head);
+		offset = size * isp_dev->dev_id;
+		break;
+	default:
+		break;
+	}
+
+	if (size && size < isp_dev->resmem_size) {
+		dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr + offset,
+					size, DMA_FROM_DEVICE);
+		if (isp_dev->is_rtt_first)
+			params_vdev->is_first_cfg = true;
+		if (isp_dev->isp_ver == ISP_V32) {
+			struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset;
+
+			param = &tmp->cfg;
+			head = &tmp->head;
+			v4l2_info(&isp_dev->v4l2_dev,
+				  "tb param module en:0x%llx upd:0x%llx cfg upd:0x%llx\n",
+				  tmp->cfg.module_en_update,
+				  tmp->cfg.module_ens,
+				  tmp->cfg.module_cfg_update);
+		}
+		if (param && (isp_dev->isp_state & ISP_STOP))
+			params_vdev->ops->save_first_param(params_vdev, param);
+	} else if (size > isp_dev->resmem_size) {
+		v4l2_err(&isp_dev->v4l2_dev,
+			 "resmem size:%zu no enough for head:%d\n",
+			 isp_dev->resmem_size, size);
+		head->complete = RKISP_TB_NG;
+	}
+	memcpy(&isp_dev->tb_head, head, sizeof(*head));
+}
+
 #ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
 void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
 {
+	struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
 	struct rkisp_hw_dev *hw = isp_dev->hw_dev;
 	struct rkisp_thunderboot_resmem_head *head;
 	enum rkisp_tb_state tb_state;
@@ -3815,19 +3923,20 @@
 	if (!isp_dev->is_thunderboot)
 		return;
 
+	if (isp_dev->isp_ver == ISP_V32 && params_vdev->is_first_cfg)
+		goto end;
+
 	resmem_va = phys_to_virt(isp_dev->resmem_pa);
 	head = (struct rkisp_thunderboot_resmem_head *)resmem_va;
 	dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr,
 				sizeof(struct rkisp_thunderboot_resmem_head),
 				DMA_FROM_DEVICE);
 
-	shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 200 * USEC_PER_MSEC);
+	shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 400 * USEC_PER_MSEC);
 	if (head->complete != RKISP_TB_OK) {
 		v4l2_err(&isp_dev->v4l2_dev, "wait thunderboot over timeout\n");
 	} else {
-		struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
-		void *param = NULL;
-		u32 size = 0, offset = 0, timeout = 50;
+		int i, timeout = 50;
 
 		/* wait for all isp dev to register */
 		if (head->camera_num > 1) {
@@ -3837,48 +3946,23 @@
 					break;
 				usleep_range(200, 210);
 			}
-		}
-
-		switch (isp_dev->isp_ver) {
-		case ISP_V32:
-			size = sizeof(struct rkisp32_thunderboot_resmem_head);
-			offset = size * isp_dev->dev_id;
-			break;
-		default:
-			break;
-		}
-
-		if (size && size < isp_dev->resmem_size) {
-			dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr + offset,
-						size, DMA_FROM_DEVICE);
-			params_vdev->is_first_cfg = true;
-			if (isp_dev->isp_ver == ISP_V32) {
-				struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset;
-
-				param = &tmp->cfg;
-				head = &tmp->head;
-				v4l2_info(&isp_dev->v4l2_dev,
-					  "tb param module en:0x%llx upd:0x%llx cfg upd:0x%llx\n",
-					  tmp->cfg.module_en_update,
-					  tmp->cfg.module_ens,
-					  tmp->cfg.module_cfg_update);
+			if (head->camera_num > hw->dev_num) {
+				v4l2_err(&isp_dev->v4l2_dev,
+					 "thunderboot invalid camera num:%d, dev num:%d\n",
+					 head->camera_num, hw->dev_num);
+				goto end;
 			}
-			if (param)
-				params_vdev->ops->save_first_param(params_vdev, param);
-		} else if (size > isp_dev->resmem_size) {
-			v4l2_err(&isp_dev->v4l2_dev,
-				 "resmem size:%zu no enough for head:%d\n",
-				 isp_dev->resmem_size, size);
-			head->complete = RKISP_TB_NG;
 		}
+		for (i = 0; i < head->camera_num; i++)
+			rkisp_save_tb_info(hw->isp[i]);
 	}
-	memcpy(&isp_dev->tb_head, head, sizeof(*head));
+end:
+	head = &isp_dev->tb_head;
 	v4l2_info(&isp_dev->v4l2_dev,
-		  "thunderboot info: %d, %d, %d, %d, %d, %d | %d %d\n",
+		  "tb info en:%d comp:%d cnt:%d w:%d h:%d cam:%d idx:%d\n",
 		  head->enable,
 		  head->complete,
 		  head->frm_total,
-		  head->hdr_mode,
 		  head->width,
 		  head->height,
 		  head->camera_num,
@@ -4005,7 +4089,7 @@
 		   struct rkisp_device *dev)
 {
 	struct rkisp_hw_dev *hw = dev->hw_dev;
-	void __iomem *base = !hw->is_unite ?
+	void __iomem *base = hw->unite != ISP_UNITE_TWO ?
 		hw->base_addr : hw->base_next_addr;
 	unsigned int isp_mis_tmp = 0;
 	unsigned int isp_err = 0;
@@ -4026,7 +4110,7 @@
 	if (isp3a_mis & ISP2X_3A_RAWAE_BIG && dev->params_vdev.rdbk_times > 0)
 		writel(BIT(31), base + RAWAE_BIG1_BASE + RAWAE_BIG_CTRL);
 
-	if (hw->is_unite) {
+	if (hw->unite == ISP_UNITE_TWO) {
 		u32 val = rkisp_read(dev, ISP3X_ISP_RIS, true);
 
 		if (val) {
@@ -4057,9 +4141,14 @@
 		}
 
 		if (IS_HDR_RDBK(dev->hdr.op_mode)) {
-			/* read 3d lut at isp readback */
-			if (!dev->hw_dev->is_single)
-				rkisp_write(dev, ISP_3DLUT_UPDATE, 0, true);
+			/* disabled frame end to read 3dlut for multi sensor
+			 * 3dlut will update at isp readback
+			 */
+			if (!dev->hw_dev->is_single) {
+				writel(0, hw->base_addr + ISP_3DLUT_UPDATE);
+				if (hw->unite == ISP_UNITE_TWO)
+					writel(0, hw->base_next_addr + ISP_3DLUT_UPDATE);
+			}
 			rkisp_stats_rdbk_enable(&dev->stats_vdev, true);
 			goto vs_skip;
 		}
@@ -4087,7 +4176,7 @@
 		if (isp_mis & CIF_ISP_FRAME)
 			sof_event_later = true;
 		if (dev->vs_irq < 0 && !sof_event_later) {
-			dev->isp_sdev.frm_timestamp = ktime_get_ns();
+			dev->isp_sdev.frm_timestamp = rkisp_time_get_ns(dev);
 			rkisp_isp_queue_event_sof(&dev->isp_sdev);
 			rkisp_stream_frame_start(dev, isp_mis);
 		}
@@ -4155,7 +4244,7 @@
 	/* sampled input frame is complete */
 	if (isp_mis & CIF_ISP_FRAME_IN) {
 		dev->isp_sdev.dbg.interval =
-			ktime_get_ns() - dev->isp_sdev.dbg.timestamp;
+			rkisp_time_get_ns(dev) - dev->isp_sdev.dbg.timestamp;
 		rkisp_set_state(&dev->isp_state, ISP_FRAME_IN);
 		writel(CIF_ISP_FRAME_IN, base + CIF_ISP_ICR);
 		isp_mis_tmp = readl(base + CIF_ISP_MIS);
@@ -4169,7 +4258,7 @@
 		dev->rawaf_irq_cnt = 0;
 		if (!dev->is_pre_on || !IS_HDR_RDBK(dev->rd_mode))
 			dev->isp_sdev.dbg.interval =
-				ktime_get_ns() - dev->isp_sdev.dbg.timestamp;
+				rkisp_time_get_ns(dev) - dev->isp_sdev.dbg.timestamp;
 		/* Clear Frame In (ISP) */
 		rkisp_set_state(&dev->isp_state, ISP_FRAME_END);
 		writel(CIF_ISP_FRAME, base + CIF_ISP_ICR);
@@ -4189,7 +4278,7 @@
 			u64 tmp = dev->isp_sdev.dbg.interval +
 					dev->isp_sdev.dbg.timestamp;
 
-			dev->isp_sdev.dbg.timestamp = ktime_get_ns();
+			dev->isp_sdev.dbg.timestamp = rkisp_time_get_ns(dev);
 			/* v-blank: frame(N)start - frame(N-1)end */
 			dev->isp_sdev.dbg.delay = dev->isp_sdev.dbg.timestamp - tmp;
 		}
@@ -4241,7 +4330,7 @@
 
 	/* cur frame end and next frame start irq togeter */
 	if (dev->vs_irq < 0 && sof_event_later) {
-		dev->isp_sdev.frm_timestamp = ktime_get_ns();
+		dev->isp_sdev.frm_timestamp = rkisp_time_get_ns(dev);
 		rkisp_isp_queue_event_sof(&dev->isp_sdev);
 		rkisp_stream_frame_start(dev, isp_mis);
 	}

--
Gitblit v1.6.2