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/cif/capture.c | 2046 ++++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 1,611 insertions(+), 435 deletions(-)

diff --git a/kernel/drivers/media/platform/rockchip/cif/capture.c b/kernel/drivers/media/platform/rockchip/cif/capture.c
index 0a557bd..dfa9d8e 100644
--- a/kernel/drivers/media/platform/rockchip/cif/capture.c
+++ b/kernel/drivers/media/platform/rockchip/cif/capture.c
@@ -18,8 +18,8 @@
 #include <media/videobuf2-dma-contig.h>
 #include <media/videobuf2-dma-sg.h>
 #include <soc/rockchip/rockchip-system-status.h>
-#include <dt-bindings/soc/rockchip-system-status.h>
 #include <soc/rockchip/rockchip_iommu.h>
+#include <linux/rk-isp32-config.h>
 
 #include "dev.h"
 #include "mipi-csi2.h"
@@ -515,6 +515,10 @@
 		.csi_fmt_val	= CSI_WRDDR_TYPE_RGB888,
 		.field		= V4L2_FIELD_NONE,
 	}, {
+		.mbus_code	= MEDIA_BUS_FMT_GBR888_1X24,
+		.csi_fmt_val	= CSI_WRDDR_TYPE_RGB888,
+		.field		= V4L2_FIELD_NONE,
+	}, {
 		.mbus_code	= MEDIA_BUS_FMT_RGB565_1X16,
 		.csi_fmt_val	= CSI_WRDDR_TYPE_RGB565,
 		.field		= V4L2_FIELD_NONE,
@@ -611,6 +615,7 @@
 		break;
 	case MEDIA_BUS_FMT_RGB888_1X24:
 	case MEDIA_BUS_FMT_BGR888_1X24:
+	case MEDIA_BUS_FMT_GBR888_1X24:
 		if (output_fmt->fourcc == V4L2_PIX_FMT_RGB24 ||
 		    output_fmt->fourcc == V4L2_PIX_FMT_BGR24)
 			ret = 0;
@@ -671,7 +676,7 @@
 		break;
 	}
 	if (ret)
-		v4l2_err(&stream->cifdev->v4l2_dev,
+		v4l2_dbg(4, rkcif_debug, &stream->cifdev->v4l2_dev,
 			 "input mbus_code 0x%x, can't transform to %c%c%c%c\n",
 			 input_fmt->mbus_code,
 			 output_fmt->fourcc & 0xff,
@@ -801,6 +806,7 @@
 		return 0x1e;
 	case MEDIA_BUS_FMT_RGB888_1X24:
 	case MEDIA_BUS_FMT_BGR888_1X24:
+	case MEDIA_BUS_FMT_GBR888_1X24:
 		if (dsi_input) {
 			if (cmd_mode_en) /* dsi command mode*/
 				return 0x39;
@@ -847,11 +853,13 @@
 }
 
 const struct
-cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect,
+cif_input_fmt *rkcif_get_input_fmt(struct rkcif_device *dev, struct v4l2_rect *rect,
 			     u32 pad_id, struct csi_channel_info *csi_info)
 {
 	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *sd = dev->terminal_sensor.sd;
 	struct rkmodule_channel_info ch_info = {0};
+	struct rkmodule_capture_info capture_info;
 	int ret;
 	u32 i;
 
@@ -909,7 +917,26 @@
 	rect->top = 0;
 	rect->width = fmt.format.width;
 	rect->height = fmt.format.height;
-
+	ret = v4l2_subdev_call(sd,
+			       core, ioctl,
+			       RKMODULE_GET_CAPTURE_MODE,
+			       &capture_info);
+	if (!ret) {
+		if (capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
+		    dev->hw_dev->is_rk3588s2) {
+			for (i = 0; i < capture_info.multi_dev.dev_num; i++) {
+				if (capture_info.multi_dev.dev_idx[i] == 0)
+					capture_info.multi_dev.dev_idx[i] = 2;
+				else if (capture_info.multi_dev.dev_idx[i] == 2)
+					capture_info.multi_dev.dev_idx[i] = 4;
+				else if (capture_info.multi_dev.dev_idx[i] == 3)
+					capture_info.multi_dev.dev_idx[i] = 5;
+			}
+		}
+		csi_info->capture_info = capture_info;
+	} else {
+		csi_info->capture_info.mode = RKMODULE_CAPTURE_MODE_NONE;
+	}
 	for (i = 0; i < ARRAY_SIZE(in_fmts); i++)
 		if (fmt.format.code == in_fmts[i].mbus_code &&
 		    fmt.format.field == in_fmts[i].field)
@@ -1587,25 +1614,29 @@
 	return ret;
 }
 
-static void rkcif_rx_buffer_free(struct rkcif_stream *stream)
+static struct v4l2_subdev *get_rkisp_sd(struct sditf_priv *priv)
 {
 	struct media_pad *pad = NULL;
+
+	if (priv && priv->pads[0].entity->num_links) {
+		if (priv->is_combine_mode)
+			pad = media_entity_remote_pad(&priv->pads[1]);
+		else
+			pad = media_entity_remote_pad(&priv->pads[0]);
+		if (pad)
+			return media_entity_to_v4l2_subdev(pad->entity);
+	}
+	return NULL;
+}
+
+static void rkcif_rx_buffer_free(struct rkcif_stream *stream)
+{
 	struct v4l2_subdev *sd;
 	struct rkisp_rx_buf *dbufs;
 	struct rkcif_device *dev = stream->cifdev;
 
-	if (dev->sditf[0] && dev->sditf[0]->num_sensors != 0) {
-		if (dev->sditf[0]->is_combine_mode)
-			pad = media_entity_remote_pad(&dev->sditf[0]->pads[1]);
-		else
-			pad = media_entity_remote_pad(&dev->sditf[0]->pads[0]);
-	} else {
-		return;
-	}
-
-	if (pad)
-		sd = media_entity_to_v4l2_subdev(pad->entity);
-	else
+	sd = get_rkisp_sd(dev->sditf[0]);
+	if (!sd)
 		return;
 
 	while (!list_empty(&stream->rx_buf_head_vicap)) {
@@ -1619,31 +1650,23 @@
 	}
 }
 
-static void rkcif_s_rx_buffer(struct rkcif_device *dev, struct rkisp_rx_buf *dbufs)
+static void rkcif_s_rx_buffer(struct rkcif_stream *stream, struct rkisp_rx_buf *dbufs)
 {
-	struct media_pad *pad = NULL;
+	struct rkcif_device *dev = stream->cifdev;
 	struct v4l2_subdev *sd;
 	struct rkcif_rx_buffer *rx_buf = NULL;
 
-	if (dev->sditf[0]) {
-		if (dev->sditf[0]->is_combine_mode)
-			pad = media_entity_remote_pad(&dev->sditf[0]->pads[1]);
-		else
-			pad = media_entity_remote_pad(&dev->sditf[0]->pads[0]);
-	} else {
+	sd = get_rkisp_sd(dev->sditf[0]);
+	if (!sd)
 		return;
-	}
-	if (pad)
-		sd = media_entity_to_v4l2_subdev(pad->entity);
-	else
-		return;
-	if (dev->rdbk_debug &&
-	    dbufs->sequence < 15) {
+	if ((dev->rdbk_debug &&
+	     dbufs->sequence < 15) ||
+	    rkcif_debug == 3) {
 		rx_buf = to_cif_rx_buf(dbufs);
 		v4l2_info(&dev->v4l2_dev,
 			  "s_buf seq %d type %d, dma addr %x, %lld\n",
 			  dbufs->sequence, dbufs->type, (u32)rx_buf->dummy.dma_addr,
-			  ktime_get_ns());
+			  rkcif_time_get_ns(dev));
 	}
 	v4l2_subdev_call(sd, video, s_rx_buffer, dbufs, NULL);
 }
@@ -1668,6 +1691,20 @@
 	val &= ~(RKCIF_SKIP_EN(stream->id));
 	rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
 	stream->skip_info.skip_en = false;
+}
+
+static void rkcif_rdbk_with_tools(struct rkcif_stream *stream,
+				      struct rkcif_rx_buffer *active_buf)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&stream->tools_vdev->vbq_lock, flags);
+	if (stream->tools_vdev->state == RKCIF_STATE_STREAMING) {
+		list_add_tail(&active_buf->list, &stream->tools_vdev->buf_done_head);
+		if (!work_busy(&stream->tools_vdev->work))
+			schedule_work(&stream->tools_vdev->work);
+	}
+	spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
 }
 
 static void rkcif_rdbk_frame_end_toisp(struct rkcif_stream *stream,
@@ -1731,9 +1768,15 @@
 		}
 		dev->rdbk_rx_buf[RDBK_M]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence;
 		dev->rdbk_rx_buf[RDBK_S]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence;
-		rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_L]->dbufs);
-		rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_M]->dbufs);
-		rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_S]->dbufs);
+		rkcif_s_rx_buffer(&dev->stream[RDBK_L], &dev->rdbk_rx_buf[RDBK_L]->dbufs);
+		rkcif_s_rx_buffer(&dev->stream[RDBK_M], &dev->rdbk_rx_buf[RDBK_M]->dbufs);
+		rkcif_s_rx_buffer(&dev->stream[RDBK_S], &dev->rdbk_rx_buf[RDBK_S]->dbufs);
+		rkcif_rdbk_with_tools(&dev->stream[RDBK_L], dev->rdbk_rx_buf[RDBK_L]);
+		rkcif_rdbk_with_tools(&dev->stream[RDBK_M], dev->rdbk_rx_buf[RDBK_M]);
+		rkcif_rdbk_with_tools(&dev->stream[RDBK_S], dev->rdbk_rx_buf[RDBK_S]);
+		atomic_dec(&dev->stream[RDBK_L].buf_cnt);
+		atomic_dec(&dev->stream[RDBK_M].buf_cnt);
+		atomic_dec(&dev->stream[RDBK_S].buf_cnt);
 		dev->rdbk_rx_buf[RDBK_L] = NULL;
 		dev->rdbk_rx_buf[RDBK_M] = NULL;
 		dev->rdbk_rx_buf[RDBK_S] = NULL;
@@ -1770,8 +1813,12 @@
 			}
 		}
 		dev->rdbk_rx_buf[RDBK_M]->dbufs.sequence = dev->rdbk_rx_buf[RDBK_L]->dbufs.sequence;
-		rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_L]->dbufs);
-		rkcif_s_rx_buffer(dev, &dev->rdbk_rx_buf[RDBK_M]->dbufs);
+		rkcif_s_rx_buffer(&dev->stream[RDBK_L], &dev->rdbk_rx_buf[RDBK_L]->dbufs);
+		rkcif_s_rx_buffer(&dev->stream[RDBK_M], &dev->rdbk_rx_buf[RDBK_M]->dbufs);
+		rkcif_rdbk_with_tools(&dev->stream[RDBK_L], dev->rdbk_rx_buf[RDBK_L]);
+		rkcif_rdbk_with_tools(&dev->stream[RDBK_M], dev->rdbk_rx_buf[RDBK_M]);
+		atomic_dec(&dev->stream[RDBK_L].buf_cnt);
+		atomic_dec(&dev->stream[RDBK_M].buf_cnt);
 		dev->rdbk_rx_buf[RDBK_L] = NULL;
 		dev->rdbk_rx_buf[RDBK_M] = NULL;
 	}
@@ -1783,14 +1830,51 @@
 	spin_unlock_irqrestore(&dev->hdr_lock, flags);
 }
 
+static void rkcif_write_buff_addr_multi_dev_combine(struct rkcif_stream *stream,
+						    u32 frm_addr_y, u32 frm_addr_uv,
+						    u32 buff_addr_y, u32 buff_addr_cbcr,
+						    bool is_dummy_buf)
+{
+	struct rkcif_device *dev = stream->cifdev;
+	struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info;
+	u32 addr_y, addr_cbcr;
+	int addr_offset = 0;
+	int i = 0;
+	int tmp_host_index = dev->csi_host_idx;
+
+	for (i = 0; i < capture_info->multi_dev.dev_num; i++) {
+		if (is_dummy_buf) {
+			addr_y = buff_addr_y;
+		} else {
+			addr_offset = dev->channels[stream->id].left_virtual_width;
+			addr_y = buff_addr_y + addr_offset * i;
+		}
+		dev->csi_host_idx = capture_info->multi_dev.dev_idx[i];
+		rkcif_write_register(dev, frm_addr_y, addr_y);
+		if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW &&
+		    frm_addr_uv && buff_addr_cbcr) {
+			if (is_dummy_buf) {
+				addr_cbcr = buff_addr_cbcr;
+			} else {
+				addr_offset = dev->channels[stream->id].left_virtual_width;
+				addr_cbcr = buff_addr_cbcr + addr_offset * i;
+			}
+			rkcif_write_register(dev, frm_addr_uv, addr_cbcr);
+		}
+	}
+	dev->csi_host_idx = tmp_host_index;
+}
+
 static void rkcif_assign_new_buffer_init_toisp(struct rkcif_stream *stream,
 					       int channel_id)
 {
 	struct rkcif_device *dev = stream->cifdev;
 	struct rkcif_rx_buffer *rx_buf;
 	struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
+	struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info;
 	u32 frm0_addr_y;
 	u32 frm1_addr_y;
+	u32 buff_addr_y;
 	unsigned long flags;
 
 	if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
@@ -1817,9 +1901,18 @@
 		}
 	}
 
-	if (stream->curr_buf_toisp)
-		rkcif_write_register(dev, frm0_addr_y,
-				     stream->curr_buf_toisp->dummy.dma_addr);
+	if (stream->curr_buf_toisp) {
+		buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr;
+		if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream, frm0_addr_y, 0,
+								buff_addr_y, 0, false);
+		} else {
+			rkcif_write_register(dev, frm0_addr_y, buff_addr_y);
+		}
+	} else {
+		if (stream->lack_buf_cnt < 2)
+			stream->lack_buf_cnt++;
+	}
 
 	if (!stream->next_buf_toisp) {
 		if (!list_empty(&stream->rx_buf_head)) {
@@ -1836,12 +1929,41 @@
 		}
 	}
 
-	if (stream->next_buf_toisp)
-		rkcif_write_register(dev, frm1_addr_y,
-				     stream->next_buf_toisp->dummy.dma_addr);
+	if (stream->next_buf_toisp) {
+		buff_addr_y = stream->next_buf_toisp->dummy.dma_addr;
+		if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream, frm1_addr_y, 0,
+								buff_addr_y, 0, false);
+		} else {
+			rkcif_write_register(dev, frm1_addr_y, buff_addr_y);
+		}
+	} else {
+		if (stream->lack_buf_cnt < 2)
+			stream->lack_buf_cnt++;
+	}
 
 	spin_unlock_irqrestore(&stream->vbq_lock, flags);
 	stream->buf_owner = RKCIF_DMAEN_BY_ISP;
+}
+
+static void rkcif_dphy_quick_stream(struct rkcif_device *dev, int on)
+{
+	struct rkcif_pipeline *p = NULL;
+	int j = 0;
+
+	if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
+	    dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ||
+	    dev->active_sensor->mbus.type == V4L2_MBUS_CCP2) {
+		p = &dev->pipe;
+		for (j = 0; j < p->num_subdevs; j++) {
+			if (p->subdevs[j] != dev->terminal_sensor.sd &&
+			    p->subdevs[j] != dev->active_sensor->sd) {
+				v4l2_subdev_call(p->subdevs[j], core, ioctl,
+						 RKMODULE_SET_QUICK_STREAM, &on);
+				break;
+			}
+		}
+	}
 }
 
 static int rkcif_assign_new_buffer_update_toisp(struct rkcif_stream *stream,
@@ -1849,11 +1971,13 @@
 {
 	struct rkcif_device *dev = stream->cifdev;
 	struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
+	struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info;
 	struct rkcif_rx_buffer *buffer = NULL;
 	struct rkcif_rx_buffer *active_buf = NULL;
 	struct sditf_priv *priv = dev->sditf[0];
-	u32 frm_addr_y;
+	u32 frm_addr_y, buff_addr_y;
 	unsigned long flags;
+
 
 	if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
 	    mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
@@ -1866,13 +1990,19 @@
 			     get_dvp_reg_index_of_frm0_y_addr(channel_id) :
 			     get_dvp_reg_index_of_frm1_y_addr(channel_id);
 	}
+
 	spin_lock_irqsave(&stream->vbq_lock, flags);
+	if (stream->cur_skip_frame)
+		goto out_get_buf;
+	memset(&stream->toisp_buf_state, 0, sizeof(stream->toisp_buf_state));
 	if (!list_empty(&stream->rx_buf_head)) {
+		if (stream->curr_buf_toisp && stream->next_buf_toisp &&
+		    stream->curr_buf_toisp != stream->next_buf_toisp)
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_ROTATE;
+		else
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS;
 		if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
-			if (stream->curr_buf_toisp == stream->next_buf_toisp)
-				active_buf = NULL;
-			else
-				active_buf = stream->curr_buf_toisp;
+			active_buf = stream->curr_buf_toisp;
 
 			buffer = list_first_entry(&stream->rx_buf_head,
 						 struct rkcif_rx_buffer, list);
@@ -1887,22 +2017,24 @@
 					active_buf->dbufs.is_first = true;
 				active_buf->dbufs.sequence = stream->frame_idx - 1;
 				active_buf->dbufs.timestamp = stream->readout.fs_timestamp;
-				active_buf->fe_timestamp = ktime_get_ns();
+				active_buf->fe_timestamp = rkcif_time_get_ns(dev);
 				stream->last_frame_idx = stream->frame_idx;
-				if (dev->hdr.hdr_mode == NO_HDR)
-					rkcif_s_rx_buffer(dev, &active_buf->dbufs);
-				else
+				if (dev->hdr.hdr_mode == NO_HDR) {
+					rkcif_s_rx_buffer(stream, &active_buf->dbufs);
+					if (dev->is_support_tools && stream->tools_vdev)
+						rkcif_rdbk_with_tools(stream, active_buf);
+					atomic_dec(&stream->buf_cnt);
+				} else {
 					rkcif_rdbk_frame_end_toisp(stream, active_buf);
-				stream->buf_num_toisp--;
+				}
 			} else {
-				rkcif_s_rx_buffer(dev, &stream->next_buf_toisp->dbufs);
-				stream->buf_num_toisp--;
+				if (active_buf)
+					rkcif_s_rx_buffer(stream, &active_buf->dbufs);
+				if (dev->is_support_tools && stream->tools_vdev)
+					rkcif_rdbk_with_tools(stream, active_buf);
 			}
 		} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
-			if (stream->curr_buf_toisp == stream->next_buf_toisp)
-				active_buf = NULL;
-			else
-				active_buf = stream->next_buf_toisp;
+			active_buf = stream->next_buf_toisp;
 			buffer = list_first_entry(&stream->rx_buf_head,
 						 struct rkcif_rx_buffer, list);
 			if (buffer) {
@@ -1916,16 +2048,21 @@
 					active_buf->dbufs.is_first = true;
 				active_buf->dbufs.sequence = stream->frame_idx - 1;
 				active_buf->dbufs.timestamp = stream->readout.fs_timestamp;
-				active_buf->fe_timestamp = ktime_get_ns();
+				active_buf->fe_timestamp = rkcif_time_get_ns(dev);
 				stream->last_frame_idx = stream->frame_idx;
-				if (dev->hdr.hdr_mode == NO_HDR)
-					rkcif_s_rx_buffer(dev, &active_buf->dbufs);
-				else
+				if (dev->hdr.hdr_mode == NO_HDR) {
+					rkcif_s_rx_buffer(stream, &active_buf->dbufs);
+					if (dev->is_support_tools && stream->tools_vdev)
+						rkcif_rdbk_with_tools(stream, active_buf);
+					atomic_dec(&stream->buf_cnt);
+				} else {
 					rkcif_rdbk_frame_end_toisp(stream, active_buf);
-				stream->buf_num_toisp--;
+				}
 			} else {
-				rkcif_s_rx_buffer(dev, &stream->curr_buf_toisp->dbufs);
-				stream->buf_num_toisp--;
+				if (active_buf)
+					rkcif_s_rx_buffer(stream, &active_buf->dbufs);
+				if (dev->is_support_tools && stream->tools_vdev)
+					rkcif_rdbk_with_tools(stream, active_buf);
 			}
 		}
 		if (stream->lack_buf_cnt)
@@ -1938,10 +2075,8 @@
 		if (dev->hw_dev->dummy_buf.vaddr) {
 			if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
 				active_buf = stream->curr_buf_toisp;
-				stream->curr_buf_toisp = NULL;
 			} else {
 				active_buf = stream->next_buf_toisp;
-				stream->next_buf_toisp = NULL;
 			}
 		} else if (stream->curr_buf_toisp && stream->next_buf_toisp &&
 			   stream->curr_buf_toisp != stream->next_buf_toisp) {
@@ -1954,23 +2089,34 @@
 				stream->next_buf_toisp = stream->curr_buf_toisp;
 				buffer = stream->curr_buf_toisp;
 			}
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME;
 			if (stream->cifdev->rdbk_debug)
 				v4l2_info(&stream->cifdev->v4l2_dev,
 					  "stream[%d] hold buf %x\n",
 					  stream->id,
 					  (u32)stream->next_buf_toisp->dummy.dma_addr);
+		} else {
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS;
+			if (stream->is_single_cap) {
+				active_buf = stream->curr_buf_toisp;
+				stream->curr_buf_toisp = NULL;
+				stream->next_buf_toisp = NULL;
+			}
 		}
+
 		if (active_buf) {
 			if (stream->frame_idx == 1)
 				active_buf->dbufs.is_first = true;
 			active_buf->dbufs.sequence = stream->frame_idx - 1;
 			active_buf->dbufs.timestamp = stream->readout.fs_timestamp;
-			active_buf->fe_timestamp = ktime_get_ns();
+			active_buf->fe_timestamp = rkcif_time_get_ns(dev);
 			stream->last_frame_idx = stream->frame_idx;
-			if (dev->hdr.hdr_mode == NO_HDR)
-				rkcif_s_rx_buffer(dev, &active_buf->dbufs);
-			else
+			if (dev->hdr.hdr_mode == NO_HDR) {
+				rkcif_s_rx_buffer(stream, &active_buf->dbufs);
+				atomic_dec(&stream->buf_cnt);
+			} else {
 				rkcif_rdbk_frame_end_toisp(stream, active_buf);
+			}
 		} else {
 			if (stream->cifdev->rdbk_debug && dev->hw_dev->dummy_buf.vaddr)
 				v4l2_info(&stream->cifdev->v4l2_dev,
@@ -1978,13 +2124,19 @@
 					  stream->id,
 					  stream->frame_idx - 1);
 		}
+		if (dev->is_support_tools && stream->tools_vdev && active_buf)
+			rkcif_rdbk_with_tools(stream, active_buf);
 	}
-
 out_get_buf:
 	stream->frame_phase_cache = stream->frame_phase;
 	if (buffer) {
-		rkcif_write_register(dev, frm_addr_y,
-				     buffer->dummy.dma_addr);
+		buff_addr_y = buffer->dummy.dma_addr;
+		if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0,
+								buff_addr_y, 0, false);
+		} else {
+			rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+		}
 		if (dev->rdbk_debug > 1 &&
 		    stream->frame_idx < 15)
 			v4l2_info(&dev->v4l2_dev,
@@ -1994,8 +2146,13 @@
 				  frm_addr_y, (u32)buffer->dummy.dma_addr);
 	} else if (dev->hw_dev->dummy_buf.vaddr && priv &&
 		   priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
-		rkcif_write_register(dev, frm_addr_y,
-				     dev->hw_dev->dummy_buf.dma_addr);
+		buff_addr_y = dev->hw_dev->dummy_buf.dma_addr;
+		if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0,
+								buff_addr_y, 0, true);
+		} else {
+			rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+		}
 	}
 	spin_unlock_irqrestore(&stream->vbq_lock, flags);
 	return 0;
@@ -2018,16 +2175,20 @@
 	struct rkcif_device *dev = stream->cifdev;
 	struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
 	struct rkcif_rx_buffer *buffer = NULL;
+	struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info;
 	struct rkcif_rx_buffer *active_buf = NULL;
-	u32 frm_addr_y;
+	u32 frm_addr_y, buff_addr_y;
 	u32 vblank = 0;
 	u32 vblank_ns = 0;
 	u64 cur_time = 0;
 	int frame_phase = 0;
 	int frame_phase_next = 0;
-	bool is_early_update = false;
 
-	if (stream->curr_buf_toisp != stream->next_buf_toisp) {
+	if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_ROTATE ||
+	    (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_THESAME &&
+	     stream->toisp_buf_state.check_cnt >= 1) ||
+	    (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS &&
+	     stream->toisp_buf_state.check_cnt >= 2)) {
 		if (dev->rdbk_debug > 2 &&
 		    stream->frame_idx < 15)
 			v4l2_info(&dev->v4l2_dev,
@@ -2041,20 +2202,26 @@
 		dev->sensor_linetime = rkcif_get_linetime(stream);
 	vblank = rkcif_get_sensor_vblank(dev);
 	vblank_ns = vblank * dev->sensor_linetime;
-	cur_time = ktime_get_ns();
+	cur_time = rkcif_time_get_ns(dev);
 
-	if (dev->chip_id > CHIP_RK3568_CIF &&
-	    dev->hdr.hdr_mode == NO_HDR &&
-	    cur_time - stream->readout.fe_timestamp < (vblank_ns - 500000) &&
-	    stream->lack_buf_cnt == 2 &&
-	    stream->frame_idx > stream->last_frame_idx) {
-		is_early_update = true;
-		frame_phase = stream->frame_phase & CIF_CSI_FRAME0_READY ?
-			CIF_CSI_FRAME1_READY : CIF_CSI_FRAME0_READY;
-		frame_phase_next = stream->frame_phase & CIF_CSI_FRAME0_READY ?
-			CIF_CSI_FRAME0_READY : CIF_CSI_FRAME1_READY;
-	} else {
+	if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_THESAME) {
 		frame_phase = stream->frame_phase;
+	} else {
+		if (stream->toisp_buf_state.state == RKCIF_TOISP_BUF_LOSS &&
+		    stream->toisp_buf_state.check_cnt == 0 &&
+		    cur_time - stream->readout.fe_timestamp < (vblank_ns - 500000)) {
+			stream->toisp_buf_state.is_early_update = true;
+			frame_phase = stream->frame_phase & CIF_CSI_FRAME0_READY ?
+				CIF_CSI_FRAME1_READY : CIF_CSI_FRAME0_READY;
+			frame_phase_next = stream->frame_phase & CIF_CSI_FRAME0_READY ?
+				CIF_CSI_FRAME0_READY : CIF_CSI_FRAME1_READY;
+		} else {
+			if (stream->toisp_buf_state.check_cnt == 1 &&
+			    (!stream->toisp_buf_state.is_early_update))
+				return;
+			frame_phase = stream->frame_phase;
+			stream->toisp_buf_state.is_early_update = false;
+		}
 	}
 	if (dev->rdbk_debug > 2 &&
 	    stream->frame_idx < 15)
@@ -2082,8 +2249,15 @@
 			if (buffer) {
 				list_del(&buffer->list);
 				stream->curr_buf_toisp = buffer;
-				rkcif_write_register(dev, frm_addr_y,
-						     stream->curr_buf_toisp->dummy.dma_addr);
+				buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr;
+				if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+					rkcif_write_buff_addr_multi_dev_combine(stream,
+										frm_addr_y, 0,
+										buff_addr_y, 0,
+										false);
+				} else {
+					rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+				}
 				if (dev->rdbk_debug > 1 &&
 				    stream->frame_idx < 15)
 					v4l2_info(&dev->v4l2_dev,
@@ -2091,7 +2265,6 @@
 						  stream->id,
 						  stream->frame_idx - 1, frm_addr_y,
 						  (u32)stream->curr_buf_toisp->dummy.dma_addr);
-				stream->buf_num_toisp--;
 			}
 		} else if (frame_phase == CIF_CSI_FRAME1_READY) {
 			active_buf = stream->next_buf_toisp;
@@ -2100,8 +2273,15 @@
 			if (buffer) {
 				list_del(&buffer->list);
 				stream->next_buf_toisp = buffer;
-				rkcif_write_register(dev, frm_addr_y,
-						     stream->next_buf_toisp->dummy.dma_addr);
+				buff_addr_y = stream->next_buf_toisp->dummy.dma_addr;
+				if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+					rkcif_write_buff_addr_multi_dev_combine(stream,
+										frm_addr_y, 0,
+										buff_addr_y, 0,
+										false);
+				} else {
+					rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+				}
 				if (dev->rdbk_debug > 1 &&
 				    stream->frame_idx < 15)
 					v4l2_info(&dev->v4l2_dev,
@@ -2109,13 +2289,12 @@
 						  stream->id,
 						  stream->frame_idx - 1, frm_addr_y,
 						  (u32)stream->next_buf_toisp->dummy.dma_addr);
-				stream->buf_num_toisp--;
 			}
 		}
 		if (stream->lack_buf_cnt)
 			stream->lack_buf_cnt--;
 	}
-	if (is_early_update) {
+	if (stream->toisp_buf_state.is_early_update) {
 		if (dev->rdbk_debug > 1 &&
 		    stream->frame_idx < 15)
 			v4l2_info(&dev->v4l2_dev,
@@ -2131,7 +2310,7 @@
 			active_buf->dbufs.sequence = stream->frame_idx - 1;
 			active_buf->dbufs.timestamp = stream->readout.fs_timestamp;
 			stream->last_frame_idx = stream->frame_idx;
-			rkcif_s_rx_buffer(dev, &active_buf->dbufs);
+			rkcif_s_rx_buffer(stream, &active_buf->dbufs);
 		}
 		if (dev->hw_dev->dummy_buf.vaddr)
 			return;
@@ -2150,9 +2329,15 @@
 			stream->next_buf_toisp = stream->curr_buf_toisp;
 		else
 			stream->curr_buf_toisp = stream->next_buf_toisp;
-		rkcif_write_register(dev, frm_addr_y,
-				     stream->curr_buf_toisp->dummy.dma_addr);
+		buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr;
+		if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y, 0,
+								buff_addr_y, 0, false);
+		} else {
+			rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+		}
 	}
+	stream->toisp_buf_state.check_cnt++;
 }
 
 static void rkcif_assign_new_buffer_init(struct rkcif_stream *stream,
@@ -2162,10 +2347,12 @@
 	struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
 	u32 frm0_addr_y, frm0_addr_uv;
 	u32 frm1_addr_y, frm1_addr_uv;
+	u32 buff_addr_y, buff_addr_cbcr;
 	unsigned long flags;
 	struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
 	struct csi_channel_info *channel = &dev->channels[channel_id];
 
+	stream->lack_buf_cnt = 0;
 	if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
 	    mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
 	    mbus_cfg->type == V4L2_MBUS_CCP2) {
@@ -2187,21 +2374,45 @@
 			stream->curr_buf = list_first_entry(&stream->buf_head,
 							    struct rkcif_buffer,
 							    queue);
+			v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, "%s %d, stream[%d] buf idx %d\n",
+				 __func__, __LINE__, stream->id, stream->curr_buf->vb.vb2_buf.index);
 			list_del(&stream->curr_buf->queue);
 		}
 	}
 
 	if (stream->curr_buf) {
-		rkcif_write_register(dev, frm0_addr_y,
-				     stream->curr_buf->buff_addr[RKCIF_PLANE_Y]);
-		if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-			rkcif_write_register(dev, frm0_addr_uv,
-					     stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]);
+		buff_addr_y = stream->curr_buf->buff_addr[RKCIF_PLANE_Y];
+		buff_addr_cbcr = stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR];
+		if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream,
+								frm0_addr_y,
+								frm0_addr_uv,
+								buff_addr_y,
+								buff_addr_cbcr,
+								false);
+		} else {
+			rkcif_write_register(dev, frm0_addr_y,
+					     stream->curr_buf->buff_addr[RKCIF_PLANE_Y]);
+			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+				rkcif_write_register(dev, frm0_addr_uv,
+						     stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]);
+		}
 	} else {
 		if (dummy_buf->vaddr) {
-			rkcif_write_register(dev, frm0_addr_y, dummy_buf->dma_addr);
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm0_addr_uv, dummy_buf->dma_addr);
+			buff_addr_y = dummy_buf->dma_addr;
+			buff_addr_cbcr = dummy_buf->dma_addr;
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm0_addr_y,
+									frm0_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									true);
+			} else {
+				rkcif_write_register(dev, frm0_addr_y, buff_addr_y);
+				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+					rkcif_write_register(dev, frm0_addr_uv, buff_addr_cbcr);
+			}
 		} else {
 			if (stream->lack_buf_cnt < 2)
 				stream->lack_buf_cnt++;
@@ -2211,43 +2422,71 @@
 	if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
 		stream->next_buf = stream->curr_buf;
 		if (stream->next_buf) {
-			rkcif_write_register(dev, frm1_addr_y,
-					     stream->next_buf->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2));
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm1_addr_uv,
-						     stream->next_buf->buff_addr[RKCIF_PLANE_CBCR] + (channel->virtual_width / 2));
+			buff_addr_y = stream->next_buf->buff_addr[RKCIF_PLANE_Y];
+			buff_addr_cbcr = stream->next_buf->buff_addr[RKCIF_PLANE_CBCR];
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm1_addr_y,
+									frm1_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									false);
+			} else {
+				rkcif_write_register(dev, frm1_addr_y,
+						     buff_addr_y + (channel->virtual_width / 2));
+				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+					rkcif_write_register(dev, frm1_addr_uv,
+							     buff_addr_cbcr + (channel->virtual_width / 2));
+			}
 		}
 	} else {
 		if (!stream->next_buf) {
 			if (!list_empty(&stream->buf_head)) {
 				stream->next_buf = list_first_entry(&stream->buf_head,
 								    struct rkcif_buffer, queue);
+				v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev, "%s %d, stream[%d] buf idx %d\n",
+					 __func__, __LINE__, stream->id, stream->next_buf->vb.vb2_buf.index);
 				list_del(&stream->next_buf->queue);
+			} else if (stream->curr_buf) {
+				stream->next_buf = stream->curr_buf;
 			}
 		}
 
-		if (stream->next_buf) {
-			rkcif_write_register(dev, frm1_addr_y,
-					     stream->next_buf->buff_addr[RKCIF_PLANE_Y]);
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm1_addr_uv,
-						     stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]);
-		} else {
-			if (dummy_buf->vaddr) {
+		if (!stream->next_buf && dummy_buf->vaddr) {
+			buff_addr_y = dummy_buf->dma_addr;
+			buff_addr_cbcr = dummy_buf->dma_addr;
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm1_addr_y,
+									frm1_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									true);
+			} else {
 				rkcif_write_register(dev, frm1_addr_y, dummy_buf->dma_addr);
 				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
 					rkcif_write_register(dev, frm1_addr_uv, dummy_buf->dma_addr);
+			}
+
+		} else if (!stream->next_buf && stream->curr_buf) {
+			stream->next_buf = stream->curr_buf;
+			if (stream->lack_buf_cnt < 2)
+				stream->lack_buf_cnt++;
+		}
+		if (stream->next_buf) {
+			buff_addr_y = stream->next_buf->buff_addr[RKCIF_PLANE_Y];
+			buff_addr_cbcr = stream->next_buf->buff_addr[RKCIF_PLANE_CBCR];
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm1_addr_y,
+									frm1_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									false);
 			} else {
-				if (stream->curr_buf) {
-					stream->next_buf = stream->curr_buf;
-					rkcif_write_register(dev, frm1_addr_y,
-							     stream->next_buf->buff_addr[RKCIF_PLANE_Y]);
-					if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-						rkcif_write_register(dev, frm1_addr_uv,
-								     stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]);
-				}
-				if (stream->lack_buf_cnt < 2)
-					stream->lack_buf_cnt++;
+				rkcif_write_register(dev, frm1_addr_y, buff_addr_y);
+				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+					rkcif_write_register(dev, frm1_addr_uv, buff_addr_cbcr);
 			}
 		}
 	}
@@ -2295,6 +2534,7 @@
 	struct rkisp_rx_buf *dbufs = NULL;
 	struct dma_buf *dbuf = NULL;
 	int ret = 0;
+	u32 buff_addr_y, buff_addr_cbcr;
 	unsigned long flags;
 
 	if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
@@ -2315,19 +2555,9 @@
 			      get_dvp_reg_index_of_frm1_uv_addr(channel_id);
 	}
 
-	if (dev->hdr.hdr_mode != NO_HDR && stream->id != 0 && (!dev->rdbk_buf[RDBK_L])) {
+	if (stream->to_stop_dma && (stream->dma_en & RKCIF_DMAEN_BY_ISP)) {
 		v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "%s %d\n", __func__, __LINE__);
-		return -EINVAL;
-	}
-
-	if (stream->to_stop_dma) {
-		if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
-			v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "%s %d\n", __func__, __LINE__);
-			goto stop_dma;
-		} else {
-			v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "%s %d\n", __func__, __LINE__);
-			return -EINVAL;
-		}
+		goto stop_dma;
 	}
 
 	spin_lock_irqsave(&stream->vbq_lock, flags);
@@ -2347,8 +2577,8 @@
 				list_del(&stream->curr_buf->queue);
 				buffer = stream->curr_buf;
 				v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
-					 "stream[%d] update curr_buf 0x%x\n",
-					 stream->id, buffer->buff_addr[0]);
+					 "stream[%d] update curr_buf 0x%x, buf idx %d\n",
+					 stream->id, buffer->buff_addr[0], stream->curr_buf->vb.vb2_buf.index);
 			}
 		} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
 			if (!stream->next_buf)
@@ -2368,14 +2598,14 @@
 					list_del(&stream->next_buf->queue);
 					buffer = stream->next_buf;
 					v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
-						 "stream[%d] update next_buf 0x%x\n",
-						 stream->id, buffer->buff_addr[0]);
+						 "stream[%d] update next_buf 0x%x, buf idx %d\n",
+						 stream->id, buffer->buff_addr[0], stream->next_buf->vb.vb2_buf.index);
 				}
 			}
 		}
-	} else if (!(stream->dma_en & RKCIF_DMAEN_BY_ISP)) {
+	} else {
 		buffer = NULL;
-		if (dummy_buf->vaddr) {
+		if (!(stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP) && dummy_buf->vaddr) {
 			if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
 				stream->curr_buf  = NULL;
 			} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
@@ -2386,12 +2616,11 @@
 					stream->next_buf = NULL;
 				}
 			}
-		} else if (stream->curr_buf && stream->next_buf &&
-			   stream->curr_buf != stream->next_buf) {
-			if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
+		} else if (stream->curr_buf != stream->next_buf) {
+			if (stream->frame_phase == CIF_CSI_FRAME0_READY && stream->next_buf) {
 				stream->curr_buf = stream->next_buf;
 				buffer = stream->next_buf;
-			} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
+			} else if (stream->frame_phase == CIF_CSI_FRAME1_READY && stream->curr_buf) {
 				stream->next_buf = stream->curr_buf;
 				buffer = stream->curr_buf;
 			}
@@ -2407,19 +2636,37 @@
 	stream->frame_phase_cache = stream->frame_phase;
 
 	if (buffer) {
+		buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y];
+		buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR];
 		if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED &&
 		    stream->frame_phase == CIF_CSI_FRAME1_READY) {
-			rkcif_write_register(dev, frm_addr_y,
-					     buffer->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2));
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm_addr_uv,
-						     buffer->buff_addr[RKCIF_PLANE_CBCR] + (channel->virtual_width / 2));
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm_addr_y,
+									frm_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									false);
+			} else {
+				rkcif_write_register(dev, frm_addr_y,
+						     buff_addr_y + (channel->virtual_width / 2));
+				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+					rkcif_write_register(dev, frm_addr_uv,
+							     buff_addr_cbcr + (channel->virtual_width / 2));
+			}
 		} else {
-			rkcif_write_register(dev, frm_addr_y,
-					     buffer->buff_addr[RKCIF_PLANE_Y]);
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm_addr_uv,
-						     buffer->buff_addr[RKCIF_PLANE_CBCR]);
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm_addr_y,
+									frm_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									false);
+			} else {
+				rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+					rkcif_write_register(dev, frm_addr_uv, buff_addr_cbcr);
+			}
 		}
 		if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
 			if (stream->buf_replace_cnt < 2)
@@ -2438,50 +2685,7 @@
 				}
 			}
 			if (dbufs)
-				rkcif_s_rx_buffer(dev, dbufs);
-			stream->buf_num_toisp--;
-		}
-	} else {
-		if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
-			rkcif_write_register(dev, frm_addr_y,
-					     stream->curr_buf_toisp->dummy.dma_addr);
-			if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
-			    stream->next_buf)
-				dbuf = stream->next_buf->dbuf;
-			else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
-				 stream->curr_buf)
-				dbuf = stream->curr_buf->dbuf;
-
-			if (dbuf) {
-				list_for_each_entry(dbufs, &stream->rx_buf_head_vicap, list)
-					if (dbufs->dbuf == dbuf)
-						break;
-			} else {
-				dbufs = &stream->curr_buf_toisp->dbufs;
-			}
-			rkcif_s_rx_buffer(dev, dbufs);
-			stream->buf_num_toisp--;
-			if (stream->curr_buf && stream->frame_phase == CIF_CSI_FRAME0_READY) {
-				stream->curr_buf = NULL;
-				if (stream->buf_replace_cnt)
-					stream->buf_replace_cnt--;
-			} else if (stream->next_buf && stream->frame_phase == CIF_CSI_FRAME1_READY) {
-				stream->next_buf = NULL;
-				if (stream->buf_replace_cnt)
-					stream->buf_replace_cnt--;
-			}
-		} else if (dummy_buf->vaddr) {
-			rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr);
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr);
-			dev->err_state |= (RKCIF_ERR_ID0_NOT_BUF << stream->id);
-			dev->irq_stats.not_active_buf_cnt[stream->id]++;
-		} else {
-			ret = -EINVAL;
-			stream->curr_buf = NULL;
-			stream->next_buf = NULL;
-			dev->err_state |= (RKCIF_ERR_ID0_NOT_BUF << stream->id);
-			dev->irq_stats.not_active_buf_cnt[stream->id]++;
+				rkcif_s_rx_buffer(stream, dbufs);
 		}
 	}
 	spin_unlock_irqrestore(&stream->vbq_lock, flags);
@@ -2489,8 +2693,13 @@
 stop_dma:
 	if (stream->buf_replace_cnt) {
 		spin_lock_irqsave(&stream->vbq_lock, flags);
-		rkcif_write_register(dev, frm_addr_y,
-				     stream->curr_buf_toisp->dummy.dma_addr);
+		buff_addr_y = stream->curr_buf_toisp->dummy.dma_addr;
+		if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE)
+			rkcif_write_buff_addr_multi_dev_combine(stream,
+								frm_addr_y, 0,
+								buff_addr_y, 0, false);
+		else
+			rkcif_write_register(dev, frm_addr_y, buff_addr_y);
 		if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
 		    stream->next_buf)
 			dbuf = stream->next_buf->dbuf;
@@ -2506,16 +2715,13 @@
 			dbufs = &stream->curr_buf_toisp->dbufs;
 		}
 		if (dbufs)
-			rkcif_s_rx_buffer(dev, dbufs);
-		stream->buf_num_toisp--;
+			rkcif_s_rx_buffer(stream, dbufs);
 
 		if (stream->frame_phase == CIF_CSI_FRAME0_READY &&
 		    stream->curr_buf) {
-			list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
 			stream->curr_buf = NULL;
 		} else if (stream->frame_phase == CIF_CSI_FRAME1_READY &&
 			   stream->next_buf) {
-			list_add_tail(&stream->next_buf->queue, &stream->buf_head);
 			stream->next_buf = NULL;
 		}
 		stream->buf_replace_cnt--;
@@ -2587,8 +2793,10 @@
 	struct rkcif_device *dev = stream->cifdev;
 	struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
 	struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
+	struct rkmodule_capture_info *capture_info = &dev->channels[stream->id].capture_info;
 	struct rkcif_buffer *buffer = NULL;
 	u32 frm_addr_y, frm_addr_uv;
+	u32 buff_addr_y, buff_addr_cbcr;
 	int channel_id = stream->id;
 	int ret = 0;
 	unsigned long flags;
@@ -2619,16 +2827,35 @@
 	}
 	spin_unlock_irqrestore(&stream->vbq_lock, flags);
 	if (buffer) {
-		rkcif_write_register(dev, frm_addr_y,
-				     buffer->buff_addr[RKCIF_PLANE_Y]);
-		if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-			rkcif_write_register(dev, frm_addr_uv,
-					     buffer->buff_addr[RKCIF_PLANE_CBCR]);
+		buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y];
+		buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR];
+		if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			rkcif_write_buff_addr_multi_dev_combine(stream, frm_addr_y,
+								frm_addr_uv,
+								buff_addr_y,
+								buff_addr_cbcr,
+								false);
+		} else {
+			rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+				rkcif_write_register(dev, frm_addr_uv, buff_addr_cbcr);
+		}
 	} else {
 		if (dummy_buf->vaddr) {
-			rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr);
-			if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-				rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr);
+			buff_addr_y = dummy_buf->dma_addr;
+			buff_addr_cbcr = dummy_buf->dma_addr;
+			if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				rkcif_write_buff_addr_multi_dev_combine(stream,
+									frm_addr_y,
+									frm_addr_uv,
+									buff_addr_y,
+									buff_addr_cbcr,
+									true);
+			} else {
+				rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+				if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+					rkcif_write_register(dev, frm_addr_uv, buff_addr_cbcr);
+			}
 		} else {
 			if (dev->chip_id < CHIP_RK3588_CIF)
 				ret = -EINVAL;
@@ -2653,7 +2880,13 @@
 	int frame_phase = 0;
 
 	spin_lock_irqsave(&stream->vbq_lock, flags);
+	memset(&stream->toisp_buf_state, 0, sizeof(stream->toisp_buf_state));
 	if (!list_empty(&stream->rx_buf_head)) {
+		if (stream->curr_buf_toisp && stream->next_buf_toisp &&
+		    stream->curr_buf_toisp != stream->next_buf_toisp)
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_ROTATE;
+		else
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS;
 		if (stream->line_int_cnt % 2) {
 			buffer = list_first_entry(&stream->rx_buf_head,
 						 struct rkcif_rx_buffer, list);
@@ -2689,8 +2922,10 @@
 					  "stream[%d] hold buf %x\n",
 					  stream->id,
 					  (u32)stream->next_buf_toisp->dummy.dma_addr);
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_THESAME;
 		} else {
 			ret = -EINVAL;
+			stream->toisp_buf_state.state = RKCIF_TOISP_BUF_LOSS;
 		}
 	}
 	if (buffer) {
@@ -3163,6 +3398,7 @@
 				  struct csi_channel_info *channel)
 {
 	struct rkcif_device *dev = stream->cifdev;
+	struct sditf_priv *priv = dev->sditf[0];
 	const struct cif_output_fmt *fmt;
 	u32 fourcc;
 	int vc = dev->channels[stream->id].vc;
@@ -3187,7 +3423,7 @@
 			channel->crop_st_x = stream->crop[CROP_SRC_ACT].left;
 
 		channel->crop_st_y = stream->crop[CROP_SRC_ACT].top;
-		if (dev->sditf_cnt > 1 && dev->sditf_cnt <= RKCIF_MAX_SDITF)
+		if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF)
 			channel->crop_st_y *= dev->sditf_cnt;
 		channel->width = stream->crop[CROP_SRC_ACT].width;
 		channel->height = stream->crop[CROP_SRC_ACT].height;
@@ -3197,7 +3433,7 @@
 		channel->crop_en = 0;
 	}
 
-	if (dev->sditf_cnt > 1 && dev->sditf_cnt <= RKCIF_MAX_SDITF)
+	if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF)
 		channel->height *= dev->sditf_cnt;
 
 	fmt = rkcif_find_output_fmt(stream, stream->pixm.pixelformat);
@@ -3207,6 +3443,8 @@
 		return -EINVAL;
 	}
 
+	if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE)
+		channel->width /=  channel->capture_info.multi_dev.dev_num;
 	/*
 	 * for mipi or lvds, when enable compact, the virtual width of raw10/raw12
 	 * needs aligned with :ALIGN(bits_per_pixel * width / 8, 8), if enable 16bit mode
@@ -3216,9 +3454,19 @@
 	if (fmt->fmt_type == CIF_FMT_TYPE_RAW && stream->is_compact &&
 	    fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB888 &&
 	    fmt->csi_fmt_val != CSI_WRDDR_TYPE_RGB565) {
-		channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256);
+		if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			channel->virtual_width = ALIGN(channel->width * 2 * fmt->raw_bpp / 8, 256);
+			channel->left_virtual_width = channel->width * fmt->raw_bpp / 8;
+		} else {
+			channel->virtual_width = ALIGN(channel->width * fmt->raw_bpp / 8, 256);
+		}
 	} else {
-		channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
+		if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			channel->virtual_width = ALIGN(channel->width * 2 * fmt->bpp[0] / 8, 8);
+			channel->left_virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
+		} else {
+			channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
+		}
 	}
 
 	if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888 || channel->fmt_val == CSI_WRDDR_TYPE_RGB565)
@@ -3237,6 +3485,8 @@
 			channel->width *= 2;
 		}
 		channel->virtual_width *= 2;
+		if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE)
+			channel->left_virtual_width *= 2;
 	}
 	if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
 		channel->virtual_width *= 2;
@@ -3387,6 +3637,7 @@
 		val &= ~CSI_HIGH_ALIGN;
 	rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
 
+	dev->intr_mask = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_INTEN);
 	return 0;
 }
 
@@ -3585,15 +3836,18 @@
 
 /*config reg for rk3588*/
 static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
-				    struct csi_channel_info *channel,
-				    enum v4l2_mbus_type mbus_type, unsigned int mode)
+				       struct csi_channel_info *channel,
+				       enum v4l2_mbus_type mbus_type, unsigned int mode,
+				       int index)
 {
 	unsigned int val = 0x0;
 	struct rkcif_device *dev = stream->cifdev;
 	struct rkcif_stream *detect_stream = &dev->stream[0];
 	struct sditf_priv *priv = dev->sditf[0];
+	struct rkmodule_capture_info *capture_info = &channel->capture_info;
 	unsigned int wait_line = 0x3fff;
 	unsigned int dma_en = 0;
+	int offset = 0;
 
 	if (channel->id >= 4)
 		return -EINVAL;
@@ -3609,21 +3863,28 @@
 				 CSI_DMA_END_INTSTAT(channel->id) |
 				 CSI_LINE_INTSTAT_V1(channel->id)));
 
-	rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
-				CSI_START_INTEN(channel->id));
+	if (!(capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
+	      index < capture_info->multi_dev.dev_num - 1)) {
 
-	if (priv && priv->mode.rdbk_mode && detect_stream->is_line_wake_up) {
 		rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
-					CSI_LINE_INTEN_RK3588(channel->id));
-		wait_line = dev->wait_line;
-	}
-	rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1,
-			     wait_line << 16 | wait_line);
-	rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3,
-			     wait_line << 16 | wait_line);
+					CSI_START_INTEN(channel->id));
 
-	rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
-				CSI_DMA_END_INTEN(channel->id));
+		if (priv && priv->mode.rdbk_mode && detect_stream->is_line_wake_up) {
+			rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
+						CSI_LINE_INTEN_RK3588(channel->id));
+			wait_line = dev->wait_line;
+		}
+		rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1,
+				     wait_line << 16 | wait_line);
+		rkcif_write_register(dev, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3,
+				     wait_line << 16 | wait_line);
+
+		rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
+					CSI_DMA_END_INTEN(channel->id));
+
+		rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
+					CSI_ALL_ERROR_INTEN_V1);
+	}
 	if (stream->cifdev->id_use_cnt == 0) {
 		val = CIF_MIPI_LVDS_SW_PRESS_VALUE_RK3588(0x3) |
 			CIF_MIPI_LVDS_SW_PRESS_ENABLE |
@@ -3637,24 +3898,25 @@
 		else
 			val |= CIF_MIPI_LVDS_SW_SEL_LVDS_RV1106;
 		rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
-
-		rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
-					CSI_ALL_ERROR_INTEN_V1);
 	}
 #if IS_ENABLED(CONFIG_CPU_RV1106)
 	if (channel->id == 1)
 		rv1106_sdmmc_get_lock();
 #endif
+	if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
+	    priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE &&
+	    (dev->hdr.hdr_mode == NO_HDR ||
+	     (dev->hdr.hdr_mode == HDR_X2 && stream->id == 1) ||
+	     (dev->hdr.hdr_mode == HDR_X3 && stream->id == 2)))
+		offset = channel->capture_info.multi_dev.pixel_offset;
+
 	rkcif_write_register(dev, get_reg_index_of_id_ctrl1(channel->id),
-			     channel->width | (channel->height << 16));
+			     (channel->width + offset) | (channel->height << 16));
 
 #if IS_ENABLED(CONFIG_CPU_RV1106)
 	if (channel->id == 1)
 		rv1106_sdmmc_put_lock();
 #endif
-
-	rkcif_write_register(dev, get_reg_index_of_frm0_y_vlw(channel->id),
-			     channel->virtual_width);
 
 	if (channel->crop_en)
 		rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id),
@@ -3673,6 +3935,17 @@
 		rkcif_assign_new_buffer_pingpong_rockit(stream,
 							RKCIF_YUV_ADDR_STATE_INIT,
 							channel->id);
+
+	if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
+	    index == (capture_info->multi_dev.dev_num - 1) &&
+	    priv && priv->mode.rdbk_mode != RKISP_VICAP_ONLINE)
+		rkcif_write_register(dev, get_reg_index_of_id_crop_start(channel->id),
+				     channel->crop_st_y << 16 |
+				     (channel->crop_st_x + capture_info->multi_dev.pixel_offset));
+
+	rkcif_write_register(dev, get_reg_index_of_frm0_y_vlw(channel->id),
+			     channel->virtual_width);
+
 	if (stream->lack_buf_cnt == 2)
 		stream->dma_en = 0;
 
@@ -3735,7 +4008,25 @@
 	}
 	if (dev->chip_id >= CHIP_RV1106_CIF)
 		rkcif_modify_frame_skip_config(stream);
-	stream->cifdev->id_use_cnt++;
+	if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+		if (index == (capture_info->multi_dev.dev_num - 1))
+			stream->cifdev->id_use_cnt++;
+	} else {
+		stream->cifdev->id_use_cnt++;
+	}
+	if (!(capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
+	      index < capture_info->multi_dev.dev_num - 1)) {
+		if (mode == RKCIF_STREAM_MODE_CAPTURE)
+			rkcif_assign_new_buffer_pingpong(stream,
+						 RKCIF_YUV_ADDR_STATE_INIT,
+						 channel->id);
+		else if (mode == RKCIF_STREAM_MODE_TOISP ||
+			 mode == RKCIF_STREAM_MODE_TOISP_RDBK)
+			rkcif_assign_new_buffer_pingpong_toisp(stream,
+						       RKCIF_YUV_ADDR_STATE_INIT,
+						       channel->id);
+	}
+	dev->intr_mask = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_INTEN);
 	return 0;
 }
 
@@ -3747,6 +4038,7 @@
 	enum v4l2_mbus_type mbus_type = active_sensor->mbus.type;
 	struct csi_channel_info *channel;
 	u32 ret = 0;
+	int i;
 
 	if (stream->state < RKCIF_STATE_STREAMING) {
 		stream->frame_idx = 0;
@@ -3785,10 +4077,18 @@
 		} else if (mode == RKCIF_STREAM_MODE_ROCKIT) {
 			stream->dma_en |= RKCIF_DMAEN_BY_ROCKIT;
 		}
-		if (stream->cifdev->chip_id < CHIP_RK3588_CIF)
+		if (stream->cifdev->chip_id < CHIP_RK3588_CIF) {
 			rkcif_csi_channel_set(stream, channel, mbus_type);
-		else
-			rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode);
+		} else {
+			if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+				for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) {
+					dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i];
+					rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, i);
+				}
+			} else {
+				rkcif_csi_channel_set_v1(stream, channel, mbus_type, mode, 0);
+			}
+		}
 	} else {
 		if (stream->cifdev->chip_id >= CHIP_RK3588_CIF) {
 			if (mode == RKCIF_STREAM_MODE_CAPTURE) {
@@ -3828,7 +4128,9 @@
 	struct v4l2_mbus_config *mbus_cfg = &cif_dev->active_sensor->mbus;
 	u32 val;
 	int id;
+	int i = 0;
 
+	stream->cifdev->id_use_cnt--;
 	if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
 	    mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
 	    mbus_cfg->type == V4L2_MBUS_CCP2) {
@@ -3840,7 +4142,14 @@
 		else
 			val &= ~LVDS_ENABLE_CAPTURE;
 
-		rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(id), val);
+		if (cif_dev->channels[id].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			for (i = 0; i < cif_dev->channels[id].capture_info.multi_dev.dev_num; i++) {
+				cif_dev->csi_host_idx = cif_dev->channels[id].capture_info.multi_dev.dev_idx[i];
+				rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(id), val);
+			}
+		} else {
+			rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(id), val);
+		}
 
 		rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT,
 					CSI_START_INTSTAT(id) |
@@ -3859,8 +4168,16 @@
 			if (stream->cifdev->id_use_cnt == 0) {
 				rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN,
 						~CSI_ALL_ERROR_INTEN_V1);
-				rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL,
-						~CSI_ENABLE_CAPTURE);
+				if (cif_dev->channels[id].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+					for (i = 0; i < cif_dev->channels[id].capture_info.multi_dev.dev_num; i++) {
+						cif_dev->csi_host_idx = cif_dev->channels[id].capture_info.multi_dev.dev_idx[i];
+						rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL,
+									 ~CSI_ENABLE_CAPTURE);
+					}
+				} else {
+					rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_CTRL,
+								 ~CSI_ENABLE_CAPTURE);
+				}
 			}
 		}
 
@@ -3876,7 +4193,6 @@
 				rkcif_config_dvp_pin(cif_dev, false);
 		}
 	}
-	stream->cifdev->id_use_cnt--;
 	stream->state = RKCIF_STATE_READY;
 	stream->dma_en = 0;
 }
@@ -3955,7 +4271,7 @@
 		plane_fmt = &pixm->plane_fmt[i];
 		sizes[i] = plane_fmt->sizeimage / height * h;
 	}
-
+	stream->total_buf_num = *num_buffers;
 	v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "%s count %d, size %d, extended(%d, %d)\n",
 		 v4l2_type_names[queue->type], *num_buffers, sizes[0],
 		 is_extended, extend_line->is_extended);
@@ -3973,6 +4289,8 @@
 	u32 frm_addr_y = 0, frm_addr_uv = 0;
 	u32 frm0_addr_y = 0, frm0_addr_uv = 0;
 	u32 frm1_addr_y = 0, frm1_addr_uv = 0;
+	u32 buff_addr_y = 0, buff_addr_cbcr = 0;
+	struct rkmodule_capture_info *capture_info = &dev->channels[channel_id].capture_info;
 	unsigned long flags;
 	int frame_phase = 0;
 	bool is_dual_update_buf = false;
@@ -4039,22 +4357,51 @@
 			}
 			if (buffer) {
 				if (is_dual_update_buf) {
-					rkcif_write_register(dev, frm0_addr_y,
-							     buffer->buff_addr[RKCIF_PLANE_Y]);
-					if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-						rkcif_write_register(dev, frm0_addr_uv,
-								     buffer->buff_addr[RKCIF_PLANE_CBCR]);
-					rkcif_write_register(dev, frm1_addr_y,
-							     buffer->buff_addr[RKCIF_PLANE_Y]);
-					if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-						rkcif_write_register(dev, frm1_addr_uv,
-								     buffer->buff_addr[RKCIF_PLANE_CBCR]);
+					buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y];
+					buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR];
+					if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+						rkcif_write_buff_addr_multi_dev_combine(stream,
+											frm0_addr_y,
+											frm0_addr_uv,
+											buff_addr_y,
+											buff_addr_cbcr,
+											false);
+						rkcif_write_buff_addr_multi_dev_combine(stream,
+											frm1_addr_y,
+											frm1_addr_uv,
+											buff_addr_y,
+											buff_addr_cbcr,
+											false);
+					} else {
+						rkcif_write_register(dev, frm0_addr_y, buff_addr_y);
+						if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+							rkcif_write_register(dev,
+									     frm0_addr_uv,
+									     buff_addr_cbcr);
+						rkcif_write_register(dev, frm1_addr_y, buff_addr_y);
+						if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+							rkcif_write_register(dev,
+									     frm1_addr_uv,
+									     buff_addr_cbcr);
+					}
 				} else {
-					rkcif_write_register(dev, frm_addr_y,
-							     buffer->buff_addr[RKCIF_PLANE_Y]);
-					if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
-						rkcif_write_register(dev, frm_addr_uv,
-								     buffer->buff_addr[RKCIF_PLANE_CBCR]);
+
+					buff_addr_y = buffer->buff_addr[RKCIF_PLANE_Y];
+					buff_addr_cbcr = buffer->buff_addr[RKCIF_PLANE_CBCR];
+					if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+						rkcif_write_buff_addr_multi_dev_combine(stream,
+											frm_addr_y,
+											frm_addr_uv,
+											buff_addr_y,
+											buff_addr_cbcr,
+											false);
+					} else {
+						rkcif_write_register(dev, frm_addr_y, buff_addr_y);
+						if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
+							rkcif_write_register(dev,
+									     frm_addr_uv,
+									     buff_addr_cbcr);
+					}
 				}
 			}
 		} else {
@@ -4065,11 +4412,17 @@
 				if (stream->frame_phase_cache == CIF_CSI_FRAME0_READY) {
 					stream->curr_buf = list_first_entry(&stream->buf_head,
 									    struct rkcif_buffer, queue);
+					v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
+						 "%s %d, stream[%d] buf idx %d\n",
+						 __func__, __LINE__, stream->id, stream->curr_buf->vb.vb2_buf.index);
 					if (stream->curr_buf)
 						list_del(&stream->curr_buf->queue);
 				} else if (stream->frame_phase_cache == CIF_CSI_FRAME1_READY) {
 					stream->next_buf = list_first_entry(&stream->buf_head,
 									    struct rkcif_buffer, queue);
+					v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev,
+						 "%s %d, stream[%d] buf idx %d\n",
+						 __func__, __LINE__, stream->id, stream->next_buf->vb.vb2_buf.index);
 					if (stream->next_buf)
 						list_del(&stream->next_buf->queue);
 				}
@@ -4098,6 +4451,7 @@
 		}
 		if (stream->lack_buf_cnt)
 			stream->lack_buf_cnt--;
+
 	} else {
 		v4l2_info(&dev->v4l2_dev, "%s %d, state %d, curr_buf %p, next_buf %p\n",
 			  __func__, __LINE__, stream->state, stream->curr_buf, stream->next_buf);
@@ -4195,11 +4549,13 @@
 		list_add_tail(&dbufs->list, &stream->rx_buf_head_vicap);
 	}
 	if (stream->cifdev->workmode == RKCIF_WORKMODE_PINGPONG &&
-	    stream->lack_buf_cnt)
+	    stream->lack_buf_cnt &&
+	    stream->cur_stream_mode & RKCIF_STREAM_MODE_CAPTURE)
 		rkcif_check_buffer_update_pingpong(stream, stream->id);
 	v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev,
 		 "stream[%d] buf queue, index: %d, dma_addr 0x%x\n",
 		 stream->id, vb->index, cifbuf->buff_addr[0]);
+	atomic_inc(&stream->buf_cnt);
 }
 
 void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num)
@@ -4207,11 +4563,54 @@
 	struct rkcif_rx_buffer *buf;
 	struct rkcif_device *dev = stream->cifdev;
 	struct sditf_priv *priv = dev->sditf[0];
+	struct v4l2_subdev *sd;
 	int i = 0;
 	unsigned long flags;
+	phys_addr_t resmem_free_start;
+	phys_addr_t resmem_free_end;
+	u32 share_head_size = 0;
 
 	if (!priv)
 		return;
+
+	sd = get_rkisp_sd(dev->sditf[0]);
+	if (!sd)
+		return;
+
+	if (dev->is_rtt_suspend && dev->is_thunderboot) {
+		stream->curr_buf_toisp = NULL;
+		stream->next_buf_toisp = NULL;
+		INIT_LIST_HEAD(&stream->rx_buf_head);
+
+		for (i = 0; i < buf_num; i++) {
+			buf = &stream->rx_buf[i];
+			if (buf->dbufs.is_init)
+				v4l2_subdev_call(sd, core, ioctl,
+						 RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs);
+			buf->dummy.is_free = true;
+		}
+
+		if (IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP)) {
+			share_head_size = dev->thunderboot_sensor_num * sizeof(struct rkisp32_thunderboot_resmem_head);
+			if (share_head_size != dev->share_mem_size)
+				v4l2_info(&stream->cifdev->v4l2_dev,
+					  "share mem head error, rtt head size %d, arm head size %d\n",
+					  dev->share_mem_size, share_head_size);
+			resmem_free_start = dev->resmem_pa + share_head_size + dev->nr_buf_size;
+			resmem_free_end = dev->resmem_pa + dev->resmem_size;
+			v4l2_info(&stream->cifdev->v4l2_dev,
+				  "free reserved mem start 0x%x, end 0x%x, share_head_size 0x%x, nr_buf_size 0x%x\n",
+				  (u32)resmem_free_start, (u32)resmem_free_end, share_head_size, dev->nr_buf_size);
+			free_reserved_area(phys_to_virt(resmem_free_start),
+					   phys_to_virt(resmem_free_end),
+					   -1, "rkisp_thunderboot");
+		}
+		atomic_set(&stream->buf_cnt, 0);
+		stream->total_buf_num = 0;
+		stream->rx_buf_num = 0;
+
+		return;
+	}
 
 	spin_lock_irqsave(&stream->vbq_lock, flags);
 	stream->curr_buf_toisp = NULL;
@@ -4225,11 +4624,17 @@
 		buf = &stream->rx_buf[i];
 		if (buf->dummy.is_free)
 			continue;
+		if (buf->dbufs.is_init)
+			v4l2_subdev_call(sd, core, ioctl,
+					 RKISP_VICAP_CMD_RX_BUFFER_FREE, &buf->dbufs);
 		if (!dev->is_thunderboot)
 			rkcif_free_buffer(dev, &buf->dummy);
 		else
 			list_add_tail(&buf->list_free, &priv->buf_free_list);
+		atomic_dec(&stream->buf_cnt);
+		stream->total_buf_num--;
 	}
+	stream->rx_buf_num = 0;
 
 	if (dev->is_thunderboot) {
 		spin_unlock_irqrestore(&dev->buffree_lock, flags);
@@ -4240,6 +4645,7 @@
 		 "free rx_buf, buf_num %d\n", buf_num);
 }
 
+static void rkcif_get_resmem_head(struct rkcif_device *cif_dev);
 int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num)
 {
 	struct rkcif_device *dev = stream->cifdev;
@@ -4287,10 +4693,12 @@
 		dummy->is_need_vaddr = true;
 		dummy->is_need_dbuf = true;
 		if (dev->is_thunderboot) {
+			if (i == 0)
+				rkcif_get_resmem_head(dev);
 			buf->buf_idx = i;
 			ret = rkcif_alloc_reserved_mem_buf(dev, buf);
 			if (ret) {
-				priv->buf_num = i;
+				stream->rx_buf_num = i;
 				v4l2_info(&dev->v4l2_dev,
 					 "reserved mem support alloc buf num %d, require buf num %d\n",
 					 i, buf_num);
@@ -4303,7 +4711,7 @@
 		} else {
 			ret = rkcif_alloc_buffer(dev, dummy);
 			if (ret) {
-				priv->buf_num = i;
+				stream->rx_buf_num = i;
 				v4l2_info(&dev->v4l2_dev,
 					 "alloc buf num %d, require buf num %d\n",
 					 i, buf_num);
@@ -4319,16 +4727,17 @@
 			buf->dbufs.is_uncompact = false;
 		else
 			buf->dbufs.is_uncompact = true;
-		if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && i == 0) {
+		if (priv && i == 0) {
 			buf->dbufs.is_first = true;
-			rkcif_s_rx_buffer(dev, &buf->dbufs);
-			stream->buf_num_toisp--;
+			if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
+				rkcif_s_rx_buffer(stream, &buf->dbufs);
 		}
 		i++;
 		if (!dev->is_thunderboot && i >= buf_num) {
+			stream->rx_buf_num = buf_num;
 			break;
 		} else if (i >= RKISP_VICAP_BUF_CNT_MAX) {
-			priv->buf_num = i;
+			stream->rx_buf_num = i;
 			v4l2_info(&dev->v4l2_dev,
 				  "reserved mem alloc buf num %d\n", i);
 			break;
@@ -4337,8 +4746,9 @@
 			"init rx_buf,dma_addr 0x%llx size: 0x%x\n",
 			(u64)dummy->dma_addr, pixm->plane_fmt[0].sizeimage);
 	}
-	if (priv->buf_num) {
-		stream->buf_num_toisp = priv->buf_num;
+	if (stream->rx_buf_num) {
+		stream->total_buf_num = stream->rx_buf_num;
+		atomic_set(&stream->buf_cnt, stream->rx_buf_num);
 		return 0;
 	} else {
 		return -EINVAL;
@@ -4352,6 +4762,7 @@
 	struct rkcif_dummy_buffer *dummy_buf = &hw->dummy_buf;
 	struct rkcif_device *tmp_dev = NULL;
 	struct v4l2_subdev_frame_interval_enum fie;
+	struct v4l2_subdev_format fmt;
 	u32 max_size = 0;
 	u32 size = 0;
 	int ret = 0;
@@ -4369,7 +4780,9 @@
 						       pad, enum_frame_interval,
 						       NULL, &fie);
 				if (!ret) {
-					if (fie.code == MEDIA_BUS_FMT_RGB888_1X24)
+					if (fie.code == MEDIA_BUS_FMT_RGB888_1X24 ||
+					    fie.code == MEDIA_BUS_FMT_BGR888_1X24 ||
+					    fie.code == MEDIA_BUS_FMT_GBR888_1X24)
 						size = fie.width * fie.height * 3;
 					else
 						size = fie.width * fie.height * 2;
@@ -4386,6 +4799,23 @@
 			continue;
 		}
 	}
+
+	if (max_size == 0 && dev->terminal_sensor.sd) {
+		fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(dev->terminal_sensor.sd,
+				       pad, get_fmt, NULL, &fmt);
+		if (!ret) {
+			if (fmt.format.code == MEDIA_BUS_FMT_RGB888_1X24 ||
+			    fmt.format.code == MEDIA_BUS_FMT_BGR888_1X24 ||
+			    fmt.format.code == MEDIA_BUS_FMT_GBR888_1X24)
+				size = fmt.format.width  * fmt.format.height * 3;
+			else
+				size = fmt.format.width * fmt.format.height * 2;
+			if (size > max_size)
+				max_size = size;
+		}
+	}
+
 	dummy_buf->size = max_size;
 
 	dummy_buf->is_need_vaddr = true;
@@ -4583,7 +5013,7 @@
 				spin_lock_irqsave(&stream->fps_lock, flags);
 				fs_time = stream->readout.fs_timestamp;
 				spin_unlock_irqrestore(&stream->fps_lock, flags);
-				cur_time = ktime_get_ns();
+				cur_time = rkcif_time_get_ns(dev);
 				if (cur_time > fs_time &&
 				    cur_time - fs_time < (frame_time_ns - 10000000)) {
 					spin_lock_irqsave(&stream->vbq_lock, flags);
@@ -4621,14 +5051,16 @@
 	} else if (mode == RKCIF_STREAM_MODE_CAPTURE && stream->dma_en & RKCIF_DMAEN_BY_VICAP) {
 		//only stop dma
 		stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP;
+		stream->is_wait_dma_stop = true;
 		wait_event_timeout(stream->wq_stopped,
-				   stream->to_stop_dma != RKCIF_DMAEN_BY_VICAP,
+				   !stream->is_wait_dma_stop,
 				   msecs_to_jiffies(1000));
 	} else if (mode == RKCIF_STREAM_MODE_TOISP && stream->dma_en & RKCIF_DMAEN_BY_VICAP) {
 		//only stop dma
 		stream->to_stop_dma = RKCIF_DMAEN_BY_ISP;
+		stream->is_wait_dma_stop = true;
 		wait_event_timeout(stream->wq_stopped,
-				   stream->to_stop_dma != RKCIF_DMAEN_BY_ISP,
+				   !stream->is_wait_dma_stop,
 				   msecs_to_jiffies(1000));
 	}
 	if ((mode & RKCIF_STREAM_MODE_CAPTURE) == RKCIF_STREAM_MODE_CAPTURE) {
@@ -4641,12 +5073,12 @@
 			list_add_tail(&stream->next_buf->queue, &stream->buf_head);
 		spin_unlock_irqrestore(&stream->vbq_lock, flags);
 
-		stream->curr_buf = NULL;
-		stream->next_buf = NULL;
-
 		if (dev->hdr.hdr_mode == HDR_X2 ||
 		    dev->hdr.hdr_mode == HDR_X3)
 			rkcif_release_rdbk_buf(stream);
+
+		stream->curr_buf = NULL;
+		stream->next_buf = NULL;
 
 		rkcif_rx_buffer_free(stream);
 		list_for_each_entry(buf, &stream->buf_head, queue) {
@@ -4664,6 +5096,8 @@
 				vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 			}
 		}
+		stream->total_buf_num = 0;
+		atomic_set(&stream->buf_cnt, 0);
 		stream->lack_buf_cnt = 0;
 		stream->dma_en &= ~RKCIF_DMAEN_BY_VICAP;
 	}
@@ -4694,8 +5128,10 @@
 			}
 		}
 		mutex_unlock(&hw_dev->dev_lock);
-		if (dev->can_be_reset && dev->chip_id >= CHIP_RK3588_CIF)
+		if (dev->can_be_reset && dev->chip_id >= CHIP_RK3588_CIF) {
 			rkcif_do_soft_reset(dev);
+			atomic_set(&dev->streamoff_cnt, 0);
+		}
 		if (dev->can_be_reset && can_reset) {
 			dev->can_be_reset = false;
 			dev->reset_work_cancel = true;
@@ -4704,10 +5140,12 @@
 			dev->wait_line = 0;
 			stream->is_line_wake_up = false;
 		}
-		tasklet_disable(&stream->vb_done_tasklet);
+		if (can_reset && hw_dev->dummy_buf.vaddr)
+			rkcif_destroy_dummy_buf(stream);
 	}
-	if (can_reset && hw_dev->dummy_buf.vaddr)
-		rkcif_destroy_dummy_buf(stream);
+	if (mode == RKCIF_STREAM_MODE_CAPTURE)
+		tasklet_disable(&stream->vb_done_tasklet);
+
 	stream->cur_stream_mode &= ~mode;
 	INIT_LIST_HEAD(&stream->vb_done_list);
 	v4l2_info(&dev->v4l2_dev, "stream[%d] stopping finished, dma_en 0x%x\n", stream->id, stream->dma_en);
@@ -4981,6 +5419,7 @@
 			stream->crop_mask |= CROP_SRC_SENSOR_MASK;
 			dev->terminal_sensor.selection = input_sel;
 		} else {
+			stream->crop_mask &= ~CROP_SRC_SENSOR_MASK;
 			dev->terminal_sensor.selection.r = dev->terminal_sensor.raw_rect;
 		}
 	}
@@ -5001,8 +5440,10 @@
 			stream->crop[CROP_SRC_ACT].top = stream->crop[CROP_SRC_USR].top +
 							  stream->crop[CROP_SRC_SENSOR].top;
 		}
-	} else {
+	} else if (stream->crop_mask & CROP_SRC_SENSOR_MASK) {
 		stream->crop[CROP_SRC_ACT] = stream->crop[CROP_SRC_SENSOR];
+	} else {
+		stream->crop[CROP_SRC_ACT] = dev->terminal_sensor.raw_rect;
 	}
 }
 
@@ -5018,9 +5459,9 @@
 	struct v4l2_rect input, *crop;
 
 	if (dev->terminal_sensor.sd) {
-		stream->cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
-						   &input, stream->id,
-						   &dev->channels[stream->id]);
+		stream->cif_fmt_in = rkcif_get_input_fmt(dev,
+							 &input, stream->id,
+							 &dev->channels[stream->id]);
 		if (!stream->cif_fmt_in) {
 			v4l2_err(v4l2_dev, "Input fmt is invalid\n");
 			return -EINVAL;
@@ -5548,6 +5989,7 @@
 		rkcif_write_register(dev, CIF_REG_DVP_CTRL,
 				     AXI_BURST_16 | workmode | ENABLE_CAPTURE);
 	}
+	dev->intr_mask = rkcif_read_register(dev, CIF_REG_DVP_INTSTAT);
 #if IS_ENABLED(CONFIG_CPU_RV1106)
 	rv1106_sdmmc_put_lock();
 #endif
@@ -5562,6 +6004,7 @@
 {
 	struct rkcif_hw *hw = cifdev->hw_dev;
 	struct rkcif_device *dev;
+	struct sditf_priv *priv;
 	int i = 0, j = 0;
 	int ret = 0;
 	int count = 0;
@@ -5610,12 +6053,12 @@
 		else
 			sync_cfg.group = 0;
 	}
+	cifdev->sync_cfg = sync_cfg;
 	if (sync_cfg.type == NO_SYNC_MODE ||
 	    hw->sync_config[sync_cfg.group].is_attach) {
 		mutex_unlock(&hw->dev_lock);
 		return;
 	}
-	cifdev->sync_cfg = sync_cfg;
 
 	sync_config = &hw->sync_config[sync_cfg.group];
 	memset(sync_config, 0, sizeof(struct rkcif_multi_sync_config));
@@ -5639,26 +6082,31 @@
 			else
 				sync_cfg.group = 0;
 		} else {
-			for (j = 0; j < dev->sditf_cnt; j++) {
-				ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd,
-						core, ioctl,
-						RKMODULE_GET_SYNC_MODE,
-						&sync_type);
-				if (!ret && sync_type)
-					break;
+			priv = dev->sditf[0];
+			if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF) {
+				for (j = 0; j < dev->sditf_cnt; j++) {
+					ret |= v4l2_subdev_call(dev->sditf[j]->sensor_sd,
+							core, ioctl,
+							RKMODULE_GET_SYNC_MODE,
+							&sync_type);
+					if (!ret && sync_type) {
+						priv = dev->sditf[j];
+						break;
+					}
+				}
+				if (!ret)
+					sync_cfg.type = sync_type;
+				else
+					sync_cfg.type = NO_SYNC_MODE;
+				ret = v4l2_subdev_call(priv->sensor_sd,
+						       core, ioctl,
+						       RKMODULE_GET_GROUP_ID,
+						       &sync_group);
+				if (!ret && sync_group < RKCIF_MAX_GROUP)
+					sync_cfg.group = sync_group;
+				else
+					sync_cfg.group = 0;
 			}
-			if (!ret)
-				sync_cfg.type = sync_type;
-			else
-				sync_cfg.type = NO_SYNC_MODE;
-			ret = v4l2_subdev_call(dev->sditf[j]->sensor_sd,
-					       core, ioctl,
-					       RKMODULE_GET_GROUP_ID,
-					       &sync_group);
-			if (!ret && sync_group < RKCIF_MAX_GROUP)
-				sync_cfg.group = sync_group;
-			else
-				sync_cfg.group = 0;
 		}
 		if (sync_cfg.group == cifdev->sync_cfg.group) {
 			if (sync_cfg.type == EXTERNAL_MASTER_MODE) {
@@ -5681,6 +6129,11 @@
 				sync_config->sync_mask |= BIT(dev->csi_host_idx);
 			}
 			dev->sync_cfg = sync_cfg;
+		} else {
+			ret = v4l2_subdev_call(dev->terminal_sensor.sd,
+					       core, ioctl,
+					       RKMODULE_GET_SYNC_MODE,
+					       &sync_type);
 		}
 	}
 	if (sync_config->int_master.count == 1) {
@@ -5714,15 +6167,19 @@
 	struct rkcif_hw *hw_dev = dev->hw_dev;
 	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
 	struct rkcif_sensor_info *sensor_info = dev->active_sensor;
-	struct rkcif_sensor_info *terminal_sensor = &dev->terminal_sensor;
+	struct rkcif_sensor_info *terminal_sensor = NULL;
 	struct rkmodule_hdr_cfg hdr_cfg;
+	struct rkcif_csi_info csi_info = {0};
 	int rkmodule_stream_seq = RKMODULE_START_STREAM_DEFAULT;
 	int ret;
+	int i = 0;
+	u32 skip_frame = 0;
 
 	v4l2_info(&dev->v4l2_dev, "stream[%d] start streaming\n", stream->id);
 
 	rkcif_attach_sync_mode(dev);
 	mutex_lock(&dev->stream_lock);
+
 	if ((stream->cur_stream_mode & RKCIF_STREAM_MODE_CAPTURE) == mode) {
 		ret = -EBUSY;
 		v4l2_err(v4l2_dev, "stream in busy state\n");
@@ -5735,7 +6192,7 @@
 	else
 		stream->is_line_inten = false;
 
-	if (dev->active_sensor) {
+	if (!dev->active_sensor) {
 		ret = rkcif_update_sensor_info(stream);
 		if (ret < 0) {
 			v4l2_err(v4l2_dev,
@@ -5744,7 +6201,7 @@
 			goto out;
 		}
 	}
-
+	terminal_sensor = &dev->terminal_sensor;
 	if (terminal_sensor->sd) {
 		ret = v4l2_subdev_call(terminal_sensor->sd,
 				       core, ioctl,
@@ -5775,6 +6232,39 @@
 		goto destroy_buf;
 
 	mutex_lock(&hw_dev->dev_lock);
+	if (atomic_read(&dev->pipe.stream_cnt) == 0 &&
+	    dev->active_sensor &&
+	    (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
+	     dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ||
+	     dev->active_sensor->mbus.type == V4L2_MBUS_CCP2)) {
+		if (dev->channels[0].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
+			csi_info.csi_num = dev->channels[0].capture_info.multi_dev.dev_num;
+			if (csi_info.csi_num > RKCIF_MAX_CSI_NUM) {
+				v4l2_err(v4l2_dev,
+					 "csi num %d, max %d\n",
+					 csi_info.csi_num, RKCIF_MAX_CSI_NUM);
+				goto out;
+			}
+			for (i = 0; i < csi_info.csi_num; i++) {
+				csi_info.csi_idx[i] = dev->channels[0].capture_info.multi_dev.dev_idx[i];
+				if (dev->hw_dev->is_rk3588s2)
+					v4l2_info(v4l2_dev, "rk3588s2 combine mode attach to mipi%d\n",
+						  csi_info.csi_idx[i]);
+			}
+		} else {
+			csi_info.csi_num = 1;
+			dev->csi_host_idx = dev->csi_host_idx_def;
+			csi_info.csi_idx[0] = dev->csi_host_idx;
+		}
+		ret = v4l2_subdev_call(dev->active_sensor->sd,
+				       core, ioctl,
+				       RKCIF_CMD_SET_CSI_IDX,
+				       &csi_info);
+		if (ret)
+			v4l2_err(&dev->v4l2_dev, "set csi idx %d fail\n", dev->csi_host_idx);
+
+	}
+
 	if (((dev->active_sensor && dev->active_sensor->mbus.type == V4L2_MBUS_BT656) ||
 	     dev->is_use_dummybuf) &&
 	    (!dev->hw_dev->dummy_buf.vaddr) &&
@@ -5788,8 +6278,10 @@
 	}
 	mutex_unlock(&hw_dev->dev_lock);
 
-	if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
+	if (mode == RKCIF_STREAM_MODE_CAPTURE)
 		tasklet_enable(&stream->vb_done_tasklet);
+
+	if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
 		ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true);
 		if (ret < 0) {
 			v4l2_err(v4l2_dev, "open cif pipeline failed %d\n",
@@ -5807,8 +6299,17 @@
 		    rkmodule_stream_seq == RKMODULE_START_STREAM_FRONT) {
 			ret = dev->pipe.set_stream(&dev->pipe, true);
 			if (ret < 0)
-				goto runtime_put;
+				goto destroy_buf;
 		}
+		ret = v4l2_subdev_call(terminal_sensor->sd,
+				       core, ioctl,
+				       RKMODULE_GET_SKIP_FRAME,
+				       &skip_frame);
+		if (!ret && skip_frame < RKCIF_SKIP_FRAME_MAX)
+			stream->skip_frame = skip_frame;
+		else
+			stream->skip_frame = 0;
+		stream->cur_skip_frame = stream->skip_frame;
 	}
 	if (dev->chip_id >= CHIP_RK1808_CIF) {
 		if (dev->active_sensor  &&
@@ -5823,7 +6324,7 @@
 	}
 
 	if (ret < 0)
-		goto runtime_put;
+		goto destroy_buf;
 
 	if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
 		ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe);
@@ -5869,15 +6370,19 @@
 	rkcif_stream_stop(stream);
 pipe_stream_off:
 	dev->pipe.set_stream(&dev->pipe, false);
-runtime_put:
-	pm_runtime_put_sync(dev->dev);
+
 destroy_buf:
-	if (stream->next_buf)
-		vb2_buffer_done(&stream->next_buf->vb.vb2_buf,
-				VB2_BUF_STATE_QUEUED);
+	if (mode == RKCIF_STREAM_MODE_CAPTURE)
+		tasklet_disable(&stream->vb_done_tasklet);
 	if (stream->curr_buf)
-		vb2_buffer_done(&stream->curr_buf->vb.vb2_buf,
-				VB2_BUF_STATE_QUEUED);
+		list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
+	if (stream->next_buf &&
+	    stream->next_buf != stream->curr_buf)
+		list_add_tail(&stream->next_buf->queue, &stream->buf_head);
+
+	stream->curr_buf = NULL;
+	stream->next_buf = NULL;
+	atomic_set(&stream->buf_cnt, 0);
 	while (!list_empty(&stream->buf_head)) {
 		struct rkcif_buffer *buf;
 
@@ -5942,6 +6447,7 @@
 		  bool try)
 {
 	struct rkcif_device *dev = stream->cifdev;
+	struct sditf_priv *priv = dev->sditf[0];
 	const struct cif_output_fmt *fmt;
 	const struct cif_input_fmt *cif_fmt_in = NULL;
 	struct v4l2_rect input_rect;
@@ -5949,6 +6455,7 @@
 	u32 xsubs = 1, ysubs = 1, i;
 	struct rkmodule_hdr_cfg hdr_cfg;
 	struct rkcif_extend_info *extend_line = &stream->extend_line;
+	struct csi_channel_info *channel_info = &dev->channels[stream->id];
 	int ret;
 
 	for (i = 0; i < RKCIF_MAX_PLANE; i++)
@@ -5962,9 +6469,9 @@
 	input_rect.height = RKCIF_DEFAULT_HEIGHT;
 
 	if (dev->terminal_sensor.sd) {
-		cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
-					   &input_rect, stream->id,
-					   &dev->channels[stream->id]);
+		cif_fmt_in = rkcif_get_input_fmt(dev,
+						 &input_rect, stream->id,
+						 channel_info);
 		stream->cif_fmt_in = cif_fmt_in;
 	} else {
 		v4l2_err(&stream->cifdev->v4l2_dev,
@@ -6006,8 +6513,9 @@
 
 	planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
 
-	if (cif_fmt_in && (cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8 ||
-			   cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8))
+	if (cif_fmt_in &&
+	    (cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8 ||
+	     cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8))
 		stream->crop_enable = false;
 
 	for (i = 0; i < planes; i++) {
@@ -6032,7 +6540,7 @@
 			}
 		}
 
-		if (dev->sditf_cnt > 1 && dev->sditf_cnt <= RKCIF_MAX_SDITF)
+		if (priv && priv->is_combine_mode && dev->sditf_cnt <= RKCIF_MAX_SDITF)
 			height *= dev->sditf_cnt;
 
 		extend_line->pixm.height = height + RKMODULE_EXTEND_LINE;
@@ -6042,8 +6550,9 @@
 		 * to optimize reading and writing of ddr, aliged with 256.
 		 */
 		if (fmt->fmt_type == CIF_FMT_TYPE_RAW &&
-			(stream->cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8 ||
-			stream->cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8)) {
+		    cif_fmt_in &&
+		    (cif_fmt_in->mbus_code == MEDIA_BUS_FMT_EBD_1X8 ||
+		     cif_fmt_in->mbus_code == MEDIA_BUS_FMT_SPD_2X8)) {
 			stream->is_compact = false;
 		}
 
@@ -6157,6 +6666,7 @@
 
 	stream->is_high_align = false;
 	stream->is_finish_stop_dma = false;
+	stream->is_wait_dma_stop = false;
 
 	if (dev->chip_id == CHIP_RV1126_CIF ||
 	    dev->chip_id == CHIP_RV1126_CIF_LITE)
@@ -6184,6 +6694,11 @@
 	stream->buf_owner = 0;
 	stream->buf_replace_cnt = 0;
 	stream->is_stop_capture = false;
+	stream->is_single_cap = false;
+	atomic_set(&stream->buf_cnt, 0);
+	stream->rx_buf_num = 0;
+	init_completion(&stream->stop_complete);
+	stream->is_wait_stop_complete = false;
 }
 
 static int rkcif_fh_open(struct file *filp)
@@ -6329,9 +6844,9 @@
 	input_rect.height = RKCIF_DEFAULT_HEIGHT;
 
 	if (dev->terminal_sensor.sd)
-		get_input_fmt(dev->terminal_sensor.sd,
-			      &input_rect, stream->id,
-			      &csi_info);
+		rkcif_get_input_fmt(dev,
+				    &input_rect, stream->id,
+				    &csi_info);
 
 	if (dev->hw_dev->adapt_to_usbcamerahal) {
 		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
@@ -6410,7 +6925,7 @@
 		return -EINVAL;
 
 	if (dev->terminal_sensor.sd) {
-		cif_fmt_in = get_input_fmt(dev->terminal_sensor.sd,
+		cif_fmt_in = rkcif_get_input_fmt(dev,
 					   &input_rect, stream->id,
 					   &dev->channels[stream->id]);
 		stream->cif_fmt_in = cif_fmt_in;
@@ -6769,8 +7284,18 @@
 			skip_n);
 }
 
+static bool rkcif_check_can_be_online(struct rkcif_device *cif_dev)
+{
+	if (cif_dev->sditf[0] == NULL || cif_dev->sditf[0]->mode.name == NULL ||
+	    (cif_dev->chip_id == CHIP_RV1106_CIF &&
+	     strstr(cif_dev->sditf[0]->mode.name, "unite")))
+		return false;
+	return true;
+}
+
 static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
 			       enum rkmodule_reset_src reset_src);
+static bool rkcif_check_single_dev_stream_on(struct rkcif_hw *hw);
 
 static long rkcif_ioctl_default(struct file *file, void *fh,
 				bool valid_prio, unsigned int cmd, void *arg)
@@ -6782,6 +7307,13 @@
 	struct csi_channel_info csi_info;
 	struct rkcif_fps fps;
 	int reset_src;
+	struct rkcif_quick_stream_param *stream_param;
+	bool is_single_dev = false;
+	struct v4l2_subdev *sd;
+	int ret = -EINVAL;
+	int i = 0;
+	int stream_num = 0;
+	bool is_can_be_online = false;
 
 	switch (cmd) {
 	case RKCIF_CMD_GET_CSI_MEMORY_MODE:
@@ -6796,8 +7328,8 @@
 		break;
 	case RKCIF_CMD_SET_CSI_MEMORY_MODE:
 		if (dev->terminal_sensor.sd) {
-			in_fmt = get_input_fmt(dev->terminal_sensor.sd,
-					       &rect, 0, &csi_info);
+			in_fmt = rkcif_get_input_fmt(dev,
+						     &rect, 0, &csi_info);
 			if (in_fmt == NULL) {
 				v4l2_err(&dev->v4l2_dev, "can't get sensor input format\n");
 				return -EINVAL;
@@ -6830,6 +7362,91 @@
 	case RKCIF_CMD_SET_RESET:
 		reset_src = *(int *)arg;
 		return rkcif_do_reset_work(dev, reset_src);
+	case RKCIF_CMD_SET_QUICK_STREAM:
+		stream_param = (struct rkcif_quick_stream_param *)arg;
+		if (!dev->sditf[0])
+			return -EINVAL;
+		if (dev->hdr.hdr_mode == HDR_X2)
+			stream_num = 2;
+		else if (dev->hdr.hdr_mode == HDR_X3)
+			stream_num = 3;
+		else
+			stream_num = 1;
+		if (stream_param->on) {
+			for (i = 0; i < stream_num; i++)
+				dev->stream[i].cur_skip_frame = dev->stream[i].skip_frame;
+			is_single_dev = rkcif_check_single_dev_stream_on(dev->hw_dev);
+			is_can_be_online = rkcif_check_can_be_online(dev);
+			if (is_single_dev && is_can_be_online) {
+				for (i = 0; i < stream_num - 1; i++) {
+					dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP;
+					rkcif_enable_dma_capture(&dev->stream[i], true);
+				}
+				dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_ONLINE;
+				sditf_change_to_online(dev->sditf[0]);
+				sd = get_rkisp_sd(dev->sditf[0]);
+				if (sd)
+					ret = v4l2_subdev_call(sd, core, ioctl,
+							       RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode);
+				if (ret) {
+					v4l2_err(&dev->v4l2_dev, "set isp work mode online fail\n");
+					return -EINVAL;
+				}
+			} else {
+				sditf_disable_immediately(dev->sditf[0]);
+				dev->sditf[0]->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO;
+				sd = get_rkisp_sd(dev->sditf[0]);
+				if (sd)
+					ret = v4l2_subdev_call(sd, core, ioctl,
+							       RKISP_VICAP_CMD_MODE, &dev->sditf[0]->mode);
+				for (i = 0; i < stream_num; i++) {
+					if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
+						dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_ISP;
+					else
+						dev->stream[i].to_en_dma = RKCIF_DMAEN_BY_VICAP;
+					rkcif_enable_dma_capture(&dev->stream[i], true);
+				}
+			}
+			rkcif_dphy_quick_stream(dev, stream_param->on);
+			v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl,
+					 RKMODULE_SET_QUICK_STREAM, &stream_param->on);
+		} else {
+			if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
+				for (i = 0; i < stream_num - 1; i++) {
+					reinit_completion(&dev->stream[i].stop_complete);
+					dev->stream[i].is_wait_stop_complete = true;
+					dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_ISP;
+					wait_for_completion_timeout(&dev->stream[i].stop_complete,
+								    msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS));
+				}
+				stream->cifdev->sensor_state = stream_param->on;
+				stream->cifdev->sensor_state_change = true;
+				dev->stream[i].is_wait_stop_complete = true;
+				wait_for_completion_timeout(&dev->stream[i].stop_complete,
+							    msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS));
+			} else {
+				for (i = 0; i < stream_num; i++) {
+					dev->stream[i].is_wait_stop_complete = true;
+					reinit_completion(&dev->stream[i].stop_complete);
+					if (dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
+						dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_ISP;
+					else
+						dev->stream[i].to_stop_dma = RKCIF_DMAEN_BY_VICAP;
+					wait_for_completion_timeout(&dev->stream[i].stop_complete,
+								    msecs_to_jiffies(RKCIF_STOP_MAX_WAIT_TIME_MS));
+				}
+				rkcif_dphy_quick_stream(dev, stream_param->on);
+				v4l2_subdev_call(dev->terminal_sensor.sd, core, ioctl,
+						 RKMODULE_SET_QUICK_STREAM, &stream_param->on);
+			}
+			stream_param->frame_num = dev->stream[0].frame_idx - 1;
+			if (!dev->is_rtt_suspend) {
+				dev->resume_mode = stream_param->resume_mode;
+				v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
+					 "set resume mode %d\n", dev->resume_mode);
+			}
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -6876,6 +7493,7 @@
 	v4l2_dbg(2, rkcif_debug, &stream->cifdev->v4l2_dev,
 		 "stream[%d] vb done, index: %d, sequence %d\n", stream->id,
 		 vb_done->vb2_buf.index, vb_done->sequence);
+	atomic_dec(&stream->buf_cnt);
 }
 
 static void rkcif_tasklet_handle(unsigned long data)
@@ -7632,7 +8250,7 @@
 		timer->csi2_err_triggered_cnt++;
 		if (timer->csi2_err_triggered_cnt == 1) {
 			is_first_err = true;
-			timer->csi2_first_err_timestamp = ktime_get_ns();
+			timer->csi2_first_err_timestamp = rkcif_time_get_ns(dev);
 		}
 
 		is_assign_triggered = true;
@@ -7644,7 +8262,7 @@
 
 	if (!is_first_err) {
 		if (timer->csi2_err_triggered_cnt >= 1) {
-			cur_time = ktime_get_ns();
+			cur_time = rkcif_time_get_ns(dev);
 			diff_time = cur_time - timer->csi2_first_err_timestamp;
 			diff_time = div_u64(diff_time, 1000000);
 			if (diff_time >= timer->err_time_interval) {
@@ -7987,7 +8605,7 @@
 				v4l2_err(&dev->v4l2_dev,
 					 "s/m/l frame err, timestamp s:%lld m:%lld l:%lld\n",
 					 s_ts, m_ts, l_ts);
-				goto RDBK_FRM_UNMATCH;
+				return;
 			}
 
 			if ((m_ts - l_ts) > time || (s_ts - m_ts) > time) {
@@ -8008,7 +8626,7 @@
 					v4l2_err(&dev->v4l2_dev,
 						 "timestamp no match, s:%lld m:%lld l:%lld, fps:%d\n",
 						 s_ts, m_ts, l_ts, fps);
-					goto RDBK_FRM_UNMATCH;
+					return;
 				}
 			}
 			dev->rdbk_buf[RDBK_M]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence;
@@ -8037,7 +8655,7 @@
 				v4l2_err(&dev->v4l2_dev, "lost medium frames\n");
 			if (!dev->rdbk_buf[RDBK_S])
 				v4l2_err(&dev->v4l2_dev, "lost short frames\n");
-			goto RDBK_FRM_UNMATCH;
+			return;
 		}
 	} else if (dev->hdr.hdr_mode == HDR_X2) {
 		if (dev->rdbk_buf[RDBK_L] && dev->rdbk_buf[RDBK_M]) {
@@ -8048,7 +8666,7 @@
 				v4l2_err(&dev->v4l2_dev,
 					 "s/l frame err, timestamp s:%lld l:%lld\n",
 					 s_ts, l_ts);
-				goto RDBK_FRM_UNMATCH;
+				return;
 			}
 
 			if ((s_ts - l_ts) > time) {
@@ -8068,7 +8686,7 @@
 					v4l2_err(&dev->v4l2_dev,
 						 "timestamp no match, s:%lld l:%lld, fps:%d\n",
 						 s_ts, l_ts, fps);
-					goto RDBK_FRM_UNMATCH;
+					return;
 				}
 			}
 			dev->rdbk_buf[RDBK_M]->vb.sequence = dev->rdbk_buf[RDBK_L]->vb.sequence;
@@ -8092,27 +8710,8 @@
 				v4l2_err(&dev->v4l2_dev, "lost long frames\n");
 			if (!dev->rdbk_buf[RDBK_M])
 				v4l2_err(&dev->v4l2_dev, "lost short frames\n");
-			goto RDBK_FRM_UNMATCH;
+			return;
 		}
-	}
-
-	dev->rdbk_buf[RDBK_L] = NULL;
-	dev->rdbk_buf[RDBK_M] = NULL;
-	dev->rdbk_buf[RDBK_S] = NULL;
-	return;
-
-RDBK_FRM_UNMATCH:
-	if (dev->rdbk_buf[RDBK_L]) {
-		dev->rdbk_buf[RDBK_L]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
-		rkcif_buf_queue(&dev->rdbk_buf[RDBK_L]->vb.vb2_buf);
-	}
-	if (dev->rdbk_buf[RDBK_M]) {
-		dev->rdbk_buf[RDBK_M]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
-		rkcif_buf_queue(&dev->rdbk_buf[RDBK_M]->vb.vb2_buf);
-	}
-	if (dev->rdbk_buf[RDBK_S]) {
-		dev->rdbk_buf[RDBK_S]->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
-		rkcif_buf_queue(&dev->rdbk_buf[RDBK_S]->vb.vb2_buf);
 	}
 
 	dev->rdbk_buf[RDBK_L] = NULL;
@@ -8147,9 +8746,13 @@
 
 	if (active_buf) {
 		vb_done = &active_buf->vb;
-		vb_done->vb2_buf.timestamp = stream->readout.fs_timestamp;
+		if (cif_dev->chip_id < CHIP_RK3588_CIF &&
+		    cif_dev->active_sensor->mbus.type == V4L2_MBUS_BT656)
+			vb_done->vb2_buf.timestamp = stream->readout.fe_timestamp;
+		else
+			vb_done->vb2_buf.timestamp = stream->readout.fs_timestamp;
 		vb_done->sequence = stream->frame_idx - 1;
-		active_buf->fe_timestamp = ktime_get_ns();
+		active_buf->fe_timestamp = rkcif_time_get_ns(cif_dev);
 		if (stream->is_line_wake_up) {
 			spin_lock_irqsave(&stream->fps_lock, flags);
 			if (mode)
@@ -8161,6 +8764,19 @@
 		}
 		if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED)
 			vb_done->sequence /= 2;
+		if (stream->cur_skip_frame) {
+			rkcif_buf_queue(&active_buf->vb.vb2_buf);
+			return;
+		}
+	} else if (cif_dev->rdbk_buf[stream->id]) {
+		vb_done = &cif_dev->rdbk_buf[stream->id]->vb;
+		if (cif_dev->chip_id < CHIP_RK3588_CIF &&
+		    cif_dev->active_sensor->mbus.type == V4L2_MBUS_BT656)
+			vb_done->vb2_buf.timestamp = stream->readout.fe_timestamp;
+		else
+			vb_done->vb2_buf.timestamp = stream->readout.fs_timestamp;
+		vb_done->sequence = stream->frame_idx - 1;
+		cif_dev->rdbk_buf[stream->id]->fe_timestamp = rkcif_time_get_ns(cif_dev);
 	}
 
 	if (cif_dev->hdr.hdr_mode == NO_HDR || cif_dev->hdr.hdr_mode == HDR_COMPR) {
@@ -8184,7 +8800,7 @@
 		if (cif_dev->is_start_hdr) {
 			spin_lock_irqsave(&cif_dev->hdr_lock, flags);
 			if (mipi_id == RKCIF_STREAM_MIPI_ID0) {
-				if (cif_dev->rdbk_buf[RDBK_L]) {
+				if (cif_dev->rdbk_buf[RDBK_L] && active_buf) {
 					v4l2_err(&cif_dev->v4l2_dev,
 						 "multiple long data in %s frame,frm_idx:%d,state:0x%x\n",
 						 cif_dev->hdr.hdr_mode == HDR_X2 ? "hdr_x2" : "hdr_x3",
@@ -8197,7 +8813,7 @@
 				if (active_buf)
 					cif_dev->rdbk_buf[RDBK_L] = active_buf;
 			} else if (mipi_id == RKCIF_STREAM_MIPI_ID1) {
-				if (cif_dev->rdbk_buf[RDBK_M]) {
+				if (cif_dev->rdbk_buf[RDBK_M] && active_buf) {
 					v4l2_err(&cif_dev->v4l2_dev,
 						 "multiple %s frame,frm_idx:%d,state:0x%x\n",
 						 cif_dev->hdr.hdr_mode == HDR_X2 ? "short data in hdr_x2" : "medium data in hdr_x3",
@@ -8212,7 +8828,7 @@
 				if (cif_dev->hdr.hdr_mode == HDR_X2)
 					rkcif_rdbk_frame_end(stream);
 			} else if (mipi_id == RKCIF_STREAM_MIPI_ID2) {
-				if (cif_dev->rdbk_buf[RDBK_S]) {
+				if (cif_dev->rdbk_buf[RDBK_S] && active_buf) {
 					v4l2_err(&cif_dev->v4l2_dev,
 						 "multiple %s frame, frm_idx:%d,state:0x%x\n",
 						 cif_dev->hdr.hdr_mode == HDR_X2 ? "err short data in hdr_x3" : "short data in hdr_x3",
@@ -8308,8 +8924,10 @@
 	spin_lock_irqsave(&priv->cif_dev->buffree_lock, flags);
 	for (i = 0; i < priv->buf_num; i++) {
 		rx_buf = &stream->rx_buf[i];
-		if (rx_buf && (!rx_buf->dummy.is_free) && rx_buf != buf)
+		if (rx_buf && (!rx_buf->dummy.is_free) && rx_buf != buf) {
 			list_add_tail(&rx_buf->list_free, &priv->buf_free_list);
+			stream->total_buf_num--;
+		}
 	}
 	spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags);
 	schedule_work(&priv->buffree_work.work);
@@ -8377,13 +8995,15 @@
 			spin_unlock_irqrestore(&stream->vbq_lock, flags);
 			active_buf->dbufs.sequence = stream->frame_idx - 1;
 			active_buf->dbufs.timestamp = stream->readout.fs_timestamp;
-			active_buf->fe_timestamp = ktime_get_ns();
+			active_buf->fe_timestamp = rkcif_time_get_ns(stream->cifdev);
 			stream->last_frame_idx = stream->frame_idx;
-			if (stream->cifdev->hdr.hdr_mode == NO_HDR)
-				rkcif_s_rx_buffer(stream->cifdev, &active_buf->dbufs);
-			else
+			if (stream->cifdev->hdr.hdr_mode == NO_HDR) {
+				rkcif_s_rx_buffer(stream, &active_buf->dbufs);
+				if (stream->cifdev->is_support_tools && stream->tools_vdev)
+					rkcif_rdbk_with_tools(stream, active_buf);
+			} else {
 				rkcif_rdbk_frame_end_toisp(stream, active_buf);
-			stream->buf_num_toisp--;
+			}
 		}
 	}
 }
@@ -8395,7 +9015,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&stream->fps_lock, flags);
-	stream->readout.fe_timestamp = ktime_get_ns();
+	stream->readout.fe_timestamp = rkcif_time_get_ns(cif_dev);
 
 	if (cif_dev->inf_id == RKCIF_DVP) {
 		spin_unlock_irqrestore(&stream->fps_lock, flags);
@@ -8442,11 +9062,11 @@
 		if (stream->frame_phase & CIF_CSI_FRAME0_READY) {
 			if (stream->curr_buf)
 				active_buf = stream->curr_buf;
-			stream->fps_stats.frm0_timestamp = ktime_get_ns();
+			stream->fps_stats.frm0_timestamp = rkcif_time_get_ns(cif_dev);
 		} else if (stream->frame_phase & CIF_CSI_FRAME1_READY) {
 			if (stream->next_buf)
 				active_buf = stream->next_buf;
-			stream->fps_stats.frm1_timestamp = ktime_get_ns();
+			stream->fps_stats.frm1_timestamp = rkcif_time_get_ns(cif_dev);
 		}
 		spin_unlock_irqrestore(&stream->fps_lock, flags);
 	}
@@ -8455,8 +9075,8 @@
 
 	if (!stream->is_line_wake_up) {
 		ret = rkcif_assign_new_buffer_pingpong(stream,
-					 RKCIF_YUV_ADDR_STATE_UPDATE,
-					 mipi_id);
+						       RKCIF_YUV_ADDR_STATE_UPDATE,
+						       mipi_id);
 		if (ret && cif_dev->chip_id < CHIP_RK3588_CIF)
 			return;
 	} else {
@@ -8464,7 +9084,11 @@
 		if (ret && cif_dev->chip_id < CHIP_RK3588_CIF)
 			return;
 	}
-	if (!stream->is_line_wake_up && stream->dma_en & RKCIF_DMAEN_BY_VICAP)
+	if (cif_dev->chip_id < CHIP_RK3588_CIF &&
+	    cif_dev->active_sensor->mbus.type == V4L2_MBUS_BT656 &&
+	    stream->id != 0)
+		stream->frame_idx++;
+	if (!stream->is_line_wake_up)
 		rkcif_buf_done_prepare(stream, active_buf, mipi_id, 0);
 
 	if (cif_dev->chip_id == CHIP_RV1126_CIF ||
@@ -8486,9 +9110,9 @@
 
 	spin_lock(&stream->fps_lock);
 	if (stream->frame_phase & CIF_CSI_FRAME0_READY)
-		stream->fps_stats.frm0_timestamp = ktime_get_ns();
+		stream->fps_stats.frm0_timestamp = rkcif_time_get_ns(cif_dev);
 	else if (stream->frame_phase & CIF_CSI_FRAME1_READY)
-		stream->fps_stats.frm1_timestamp = ktime_get_ns();
+		stream->fps_stats.frm1_timestamp = rkcif_time_get_ns(cif_dev);
 	spin_unlock(&stream->fps_lock);
 
 	if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
@@ -8520,11 +9144,11 @@
 		if (stream->frame_phase & CIF_CSI_FRAME0_READY) {
 			if (stream->curr_buf_rockit)
 				active_buf = stream->curr_buf_rockit;
-			stream->fps_stats.frm0_timestamp = ktime_get_ns();
+			stream->fps_stats.frm0_timestamp = rkcif_time_get_ns(cif_dev);
 		} else if (stream->frame_phase & CIF_CSI_FRAME1_READY) {
 			if (stream->next_buf_rockit)
 				active_buf = stream->next_buf_rockit;
-			stream->fps_stats.frm1_timestamp = ktime_get_ns();
+			stream->fps_stats.frm1_timestamp = rkcif_time_get_ns(cif_dev);
 		}
 		spin_unlock_irqrestore(&stream->fps_lock, flags);
 	}
@@ -8581,6 +9205,15 @@
 	}
 }
 
+static void rkcif_toisp_set_stream(struct rkcif_device *dev, int on)
+{
+	struct v4l2_subdev *sd = get_rkisp_sd(dev->sditf[0]);
+
+	if (sd)
+		v4l2_subdev_call(sd, core, ioctl,
+				 RKISP_VICAP_CMD_SET_STREAM, &on);
+}
+
 static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
 			       enum rkmodule_reset_src reset_src)
 {
@@ -8590,6 +9223,7 @@
 	struct rkcif_sensor_info *terminal_sensor = &cif_dev->terminal_sensor;
 	struct rkcif_resume_info *resume_info = &cif_dev->reset_work.resume_info;
 	struct rkcif_timer *timer = &cif_dev->reset_watchdog_timer;
+	struct sditf_priv *priv = cif_dev->sditf[0];
 	int i, j, ret = 0;
 	u32 on, sof_cnt;
 	int capture_mode = 0;
@@ -8658,10 +9292,12 @@
 				 __func__, on ? "on" : "off", p->subdevs[i]->name);
 	}
 
-	for (i = 0; i < cif_dev->sditf_cnt; i++) {
-		if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd)
-			ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl,
-					       RKMODULE_SET_QUICK_STREAM, &on);
+	if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) {
+		for (i = 0; i < cif_dev->sditf_cnt; i++) {
+			if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd)
+				ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl,
+						       RKMODULE_SET_QUICK_STREAM, &on);
+		}
 	}
 
 	rockchip_clear_system_status(SYS_STATUS_CIF0);
@@ -8683,6 +9319,9 @@
 			goto unlock_stream;
 		}
 	}
+
+	if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
+		rkcif_toisp_set_stream(cif_dev, 1);
 
 	for (i = 0; i < j; i++) {
 		stream = resume_stream[i];
@@ -8756,10 +9395,12 @@
 				 p->subdevs[i]->name);
 	}
 
-	for (i = 0; i < cif_dev->sditf_cnt; i++) {
-		if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd)
-			v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl,
-					 RKMODULE_SET_QUICK_STREAM, &on);
+	if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) {
+		for (i = 0; i < cif_dev->sditf_cnt; i++) {
+			if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd)
+				v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core, ioctl,
+						 RKMODULE_SET_QUICK_STREAM, &on);
+		}
 	}
 
 	if (cif_dev->chip_id < CHIP_RK3588_CIF)
@@ -8820,7 +9461,7 @@
 	v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev, "diff_time:%lld,devi_t:%ld,devi_h:%d\n",
 		  diff_time, timer->line_end_cycle * deviation, deviation);
 
-	cur_time = ktime_get_ns();
+	cur_time = rkcif_time_get_ns(dev);
 	time_distance = timestamp0 > timestamp1 ?
 			cur_time - timestamp0 : cur_time - timestamp1;
 	time_distance = div_u64(time_distance, 1000);
@@ -8929,6 +9570,7 @@
 	timer->csi2_err_cnt_even = 0;
 	timer->csi2_err_fs_fe_cnt = 0;
 	timer->notifer_called_cnt = 0;
+	dev->is_toisp_reset = false;
 	for (i = 0; i < dev->num_channels; i++) {
 		stream = &dev->stream[i];
 		if (stream->state == RKCIF_STATE_STREAMING)
@@ -8938,10 +9580,10 @@
 	if (timer->is_ctrl_by_user) {
 		rkcif_send_reset_event(dev, timer->reset_src);
 	} else {
+		dev->reset_work.reset_src = timer->reset_src;
 		if (!schedule_work(&dev->reset_work.work))
 			v4l2_info(&dev->v4l2_dev,
 				  "schedule reset work failed\n");
-		dev->reset_work.reset_src = timer->reset_src;
 	}
 }
 
@@ -8955,6 +9597,15 @@
 	unsigned long flags;
 	int ret, is_reset = 0;
 	struct rkmodule_vicap_reset_info rst_info;
+
+	if (dev->is_toisp_reset) {
+		is_reset = 1;
+		timer->reset_src = RKCIF_RESET_SRC_ERR_ISP;
+	}
+	if (is_reset) {
+		rkcif_init_reset_work(timer);
+		return is_reset;
+	}
 
 	if (timer->last_buf_wakeup_cnt[stream->id] < stream->buf_wake_up_cnt &&
 	    check_cnt == 0) {
@@ -9329,6 +9980,7 @@
 	if (stream->buf_owner == RKCIF_DMAEN_BY_ISP)
 		stream->buf_owner = RKCIF_DMAEN_BY_ISP_TO_VICAP;
 
+	atomic_dec(&cif_dev->streamoff_cnt);
 	if (stream->dma_en) {
 		stream->dma_en |= stream->to_en_dma;
 		stream->to_en_dma = 0;
@@ -9399,7 +10051,7 @@
 		return -EINVAL;
 
 	stream->dma_en &= ~stream->to_stop_dma;
-
+	atomic_inc(&cif_dev->streamoff_cnt);
 	if (stream->dma_en != 0) {
 		if (stream->dma_en & RKCIF_DMAEN_BY_ISP)
 			stream->buf_owner = RKCIF_DMAEN_BY_ISP;
@@ -9437,6 +10089,11 @@
 		rkcif_write_register(cif_dev, CIF_REG_DVP_CTRL, val);
 	}
 	stream->to_stop_dma = 0;
+	v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev,
+		 "stream[%d] replace_cnt %d, y_addr 0x%x, 0x%x\n",
+		 stream->id, stream->buf_replace_cnt,
+		 rkcif_read_register(cif_dev, get_reg_index_of_frm0_y_addr(stream->id)),
+		 rkcif_read_register(cif_dev, get_reg_index_of_frm1_y_addr(stream->id)));
 	return 0;
 }
 
@@ -9490,6 +10147,7 @@
 	int i = 0;
 	u32 val = 0;
 	u64 cur_time = 0;
+	int on = 0;
 
 	for (i = 0; i < TOISP_CH_MAX; i++) {
 		ch = rkcif_g_toisp_ch(intstat_glb, index);
@@ -9507,7 +10165,30 @@
 				stream->stopping = false;
 				wake_up(&stream->wq_stopped);
 			}
-
+			if (stream->cifdev->sensor_state_change) {
+				rkcif_dphy_quick_stream(stream->cifdev, on);
+				stream->cifdev->sensor_work.on = stream->cifdev->sensor_state;
+				schedule_work(&stream->cifdev->sensor_work.work);
+				stream->cifdev->sensor_state_change = false;
+				if (stream->is_wait_stop_complete) {
+					stream->is_wait_stop_complete = false;
+					complete(&stream->stop_complete);
+				}
+			}
+			if (stream->is_single_cap && (!stream->cur_skip_frame) &&
+			    (stream->cifdev->hdr.hdr_mode == NO_HDR ||
+			    (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) ||
+			    (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2))) {
+				rkcif_dphy_quick_stream(stream->cifdev, on);
+				stream->cifdev->sensor_work.on = 0;
+				schedule_work(&stream->cifdev->sensor_work.work);
+				stream->is_single_cap = false;
+			}
+			if (stream->cur_skip_frame &&
+			    (stream->cifdev->hdr.hdr_mode == NO_HDR ||
+			     (stream->cifdev->hdr.hdr_mode == HDR_X2 && stream->id == 1) ||
+			     (stream->cifdev->hdr.hdr_mode == HDR_X3 && stream->id == 2)))
+				stream->cur_skip_frame--;
 			if (stream->cifdev->chip_id >= CHIP_RV1106_CIF)
 				rkcif_modify_frame_skip_config(stream);
 			if (stream->cifdev->rdbk_debug &&
@@ -9544,9 +10225,14 @@
 			if (stream->id == 0)
 				rkcif_send_sof(stream->cifdev);
 			stream->frame_idx++;
-			cur_time = ktime_get_ns();
+			cur_time = rkcif_time_get_ns(stream->cifdev);
 			stream->readout.readout_time = cur_time - stream->readout.fs_timestamp;
 			stream->readout.fs_timestamp = cur_time;
+			stream->buf_wake_up_cnt++;
+			if (stream->frame_idx % 2)
+				stream->fps_stats.frm0_timestamp = rkcif_time_get_ns(stream->cifdev);
+			else
+				stream->fps_stats.frm1_timestamp = rkcif_time_get_ns(stream->cifdev);
 			if (stream->cifdev->rdbk_debug &&
 			    stream->frame_idx < 15)
 				v4l2_info(&priv->cif_dev->v4l2_dev,
@@ -9616,15 +10302,16 @@
 
 	sync_config = &hw->sync_config[cif_dev->sync_cfg.group];
 	sync_config->sync_code |= BIT(cif_dev->csi_host_idx);
-	if (sync_config->sync_code != sync_config->sync_mask)
-		return -EINVAL;
-
 	v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
-		 "sync code 0x%x, mask 0x%x, update 0x%x, cache 0x%x\n",
+		 "sync code 0x%x, mask 0x%x, update 0x%x, cache 0x%x, timestamp %llu\n",
 		 sync_config->sync_code,
 		 sync_config->sync_mask,
 		 sync_config->update_code,
-		 sync_config->update_cache);
+		 sync_config->update_cache,
+		 detect_stream->readout.fs_timestamp);
+
+	if (sync_config->sync_code != sync_config->sync_mask)
+		return -EINVAL;
 
 	for (i = 0; i < sync_config->dev_cnt; i++) {
 		if (sync_config->mode == RKCIF_MASTER_MASTER) {
@@ -9670,7 +10357,7 @@
 	if (cif_dev->chip_id < CHIP_RK3588_CIF)
 		detect_stream->fs_cnt_in_single_frame++;
 	spin_lock_irqsave(&detect_stream->fps_lock, flags);
-	detect_stream->readout.fs_timestamp = ktime_get_ns();
+	detect_stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev);
 	spin_unlock_irqrestore(&detect_stream->fps_lock, flags);
 
 	if (cif_dev->sync_cfg.type != RKCIF_NOSYNC_MODE) {
@@ -9721,7 +10408,7 @@
 				  "stream[%d] sof %d %lld\n",
 				  detect_stream->id,
 				  detect_stream->frame_idx - 1,
-				  ktime_get_ns());
+				  rkcif_time_get_ns(cif_dev));
 	}
 }
 
@@ -9780,6 +10467,425 @@
 	return is_update;
 }
 
+static bool rkcif_check_single_dev_stream_on(struct rkcif_hw *hw)
+{
+	struct rkcif_device *cif_dev = NULL;
+	struct rkcif_stream *stream = NULL;
+	int i = 0, j = 0;
+	int stream_cnt = 0;
+
+	if (hw->dev_num == 1)
+		return true;
+	for (i = 0; i < hw->dev_num; i++) {
+		cif_dev = hw->cif_dev[i];
+		for (j = 0; j < RKCIF_MAX_STREAM_MIPI; j++) {
+			stream = &cif_dev->stream[j];
+			if (stream->state == RKCIF_STATE_STREAMING ||
+			    stream->state ==  RKCIF_STATE_RESET_IN_STREAMING) {
+				stream_cnt++;
+				break;
+			}
+		}
+	}
+	if (stream_cnt > 1)
+		return false;
+	return true;
+}
+
+static void rkcif_get_resmem_head(struct rkcif_device *cif_dev)
+{
+	void *resmem_va = phys_to_virt(cif_dev->resmem_pa);
+	struct rkisp_thunderboot_resmem_head *head = NULL;
+	int size = 0;
+	int offset = 0;
+	int ret = 0;
+	int cam_idx = 0;
+	char cam_idx_str[3] = {0};
+
+	if (!cif_dev->is_rtt_suspend)
+		return;
+	strscpy(cam_idx_str, cif_dev->terminal_sensor.sd->name + 1, 2);
+	cam_idx_str[2] = '\0';
+	ret = kstrtoint(cam_idx_str, 0, &cam_idx);
+	if (ret) {
+		v4l2_err(&cif_dev->v4l2_dev,
+			 "get camera index fail\n");
+		return;
+	}
+
+	if (cif_dev->chip_id == CHIP_RV1106_CIF) {
+		size = sizeof(struct rkisp32_thunderboot_resmem_head);
+		offset = size * cam_idx;
+	}
+	/* currently, thunderboot with mcu only run one camera */
+	offset = 0;
+
+	if (size && size < cif_dev->resmem_size) {
+		dma_sync_single_for_cpu(cif_dev->dev, cif_dev->resmem_addr + offset,
+					size, DMA_FROM_DEVICE);
+		if (cif_dev->chip_id == CHIP_RV1106_CIF) {
+			struct rkisp32_thunderboot_resmem_head *tmp = resmem_va + offset;
+
+			head = &tmp->head;
+			cif_dev->resume_mode = head->rtt_mode;
+			cif_dev->nr_buf_size = head->nr_buf_size;
+			cif_dev->share_mem_size = head->share_mem_size;
+			cif_dev->thunderboot_sensor_num = head->camera_num;
+		}
+	}
+	v4l2_err(&cif_dev->v4l2_dev,
+		 "get camera index %02x, resume_mode 0x%x, nr_buf_size %d\n",
+		 cam_idx, cif_dev->resume_mode, cif_dev->nr_buf_size);
+}
+
+static int rkcif_subdevs_set_power(struct rkcif_device *cif_dev, int on)
+{
+	struct sditf_priv *priv = cif_dev->sditf[0];
+	int ret = 0;
+	int i = 0;
+
+	if (cif_dev->terminal_sensor.sd)
+		ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
+				       core, s_power, on);
+	if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) {
+		for (i = 0; i < cif_dev->sditf_cnt; i++) {
+			if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd)
+				v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, core,
+						 s_power, on);
+		}
+	}
+	return ret;
+}
+
+static void rkcif_sensor_quick_streaming_cb(void *data)
+{
+	struct v4l2_subdev *subdevs = (struct v4l2_subdev *)data;
+	int on = 1;
+
+	v4l2_subdev_call(subdevs, core, ioctl,
+			 RKMODULE_SET_QUICK_STREAM, &on);
+}
+
+static int rkcif_subdevs_set_stream(struct rkcif_device *cif_dev, int on)
+{
+	struct rkcif_pipeline *p = &cif_dev->pipe;
+	struct rkcif_sensor_info *terminal_sensor = &cif_dev->terminal_sensor;
+	struct sditf_priv *priv = cif_dev->sditf[0];
+	int i = 0;
+	int ret = 0;
+
+	for (i = 0; i < p->num_subdevs; i++) {
+		if (p->subdevs[i] == terminal_sensor->sd && on)
+			rkcif_set_sof(cif_dev, cif_dev->stream[0].frame_idx);
+		if (p->subdevs[i] == terminal_sensor->sd &&
+		    cif_dev->chip_id == CHIP_RV1106_CIF) {
+			if (!rk_tb_mcu_is_done() && on) {
+				cif_dev->tb_client.data = p->subdevs[i];
+				cif_dev->tb_client.cb = rkcif_sensor_quick_streaming_cb;
+				rk_tb_client_register_cb(&cif_dev->tb_client);
+			} else {
+				ret = v4l2_subdev_call(p->subdevs[i], core, ioctl,
+						       RKMODULE_SET_QUICK_STREAM, &on);
+				if (ret)
+					v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+						 "%s:quick stream %s subdev:%s failed\n",
+						 __func__, on ? "on" : "off",
+						 p->subdevs[i]->name);
+			}
+		} else {
+			ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
+			if (ret)
+				v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+					 "%s:stream %s subdev:%s failed\n",
+					 __func__, on ? "on" : "off", p->subdevs[i]->name);
+		}
+	}
+
+	if (priv && priv->is_combine_mode && cif_dev->sditf_cnt <= RKCIF_MAX_SDITF) {
+		for (i = 0; i < cif_dev->sditf_cnt; i++) {
+			if (cif_dev->sditf[i] && cif_dev->sditf[i]->sensor_sd) {
+				ret = v4l2_subdev_call(cif_dev->sditf[i]->sensor_sd, video, s_stream, on);
+				if (ret)
+					v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+						 "%s:stream %s subdev:%s failed\n",
+						 __func__, on ? "on" : "off",
+						 cif_dev->sditf[i]->sensor_sd->name);
+			}
+		}
+	}
+	return ret;
+}
+
+int rkcif_stream_suspend(struct rkcif_device *cif_dev, int mode)
+{
+	struct rkcif_stream *stream = NULL;
+	struct rkcif_resume_info *resume_info = &cif_dev->reset_work.resume_info;
+	struct sditf_priv *priv = cif_dev->sditf[0];
+	int ret = 0;
+	int i = 0;
+	int sof_cnt = 0;
+	int on = 0;
+	int suspend_cnt = 0;
+
+	mutex_lock(&cif_dev->stream_lock);
+
+	if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && mode == RKCIF_RESUME_CIF)
+		goto out_suspend;
+
+	for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
+		stream = &cif_dev->stream[i];
+
+		if (stream->state == RKCIF_STATE_STREAMING) {
+			suspend_cnt++;
+			v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+				 "stream[%d] stopping\n", stream->id);
+			if (stream->dma_en) {
+				stream->stopping = true;
+				ret = wait_event_timeout(stream->wq_stopped,
+							 stream->state != RKCIF_STATE_STREAMING,
+							 msecs_to_jiffies(500));
+				if (!ret) {
+					rkcif_stream_stop(stream);
+					stream->stopping = false;
+				}
+			} else {
+				rkcif_stream_stop(stream);
+			}
+
+			if (stream->id == RKCIF_STREAM_MIPI_ID0) {
+				sof_cnt = rkcif_get_sof(cif_dev);
+				v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+					 "%s: stream[%d] sync frmid & csi_sof, frm_id:%d, csi_sof:%d\n",
+					 __func__,
+					 stream->id,
+					 stream->frame_idx,
+					 sof_cnt);
+
+				resume_info->frm_sync_seq = stream->frame_idx;
+			}
+
+			stream->state = RKCIF_STATE_RESET_IN_STREAMING;
+			stream->is_fs_fe_not_paired = false;
+			stream->fs_cnt_in_single_frame = 0;
+
+			v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+				 "%s stop stream[%d] in streaming, frm_id:%d, csi_sof:%d\n",
+				 __func__, stream->id, stream->frame_idx, rkcif_get_sof(cif_dev));
+
+		}
+	}
+
+	if (suspend_cnt == 0)
+		goto out_suspend;
+
+	if (!cif_dev->resume_mode)
+		rkcif_subdevs_set_power(cif_dev, on);
+
+	rkcif_subdevs_set_stream(cif_dev, on);
+
+out_suspend:
+	mutex_unlock(&cif_dev->stream_lock);
+	return 0;
+}
+
+int rkcif_stream_resume(struct rkcif_device *cif_dev, int mode)
+{
+	struct rkcif_stream *stream = NULL;
+	struct sditf_priv *priv = cif_dev->sditf[0];
+	struct v4l2_subdev *sd = NULL;
+	int ret = 0;
+	int i = 0;
+	u32 capture_mode = 0;
+	int on = 1;
+	int resume_cnt = 0;
+	unsigned long flags;
+	bool is_single_dev = false;
+	bool is_can_be_online = false;
+	struct rkisp_vicap_mode vicap_mode;
+
+	mutex_lock(&cif_dev->stream_lock);
+
+	rkcif_get_resmem_head(cif_dev);
+	is_single_dev = rkcif_check_single_dev_stream_on(cif_dev->hw_dev);
+	is_can_be_online = rkcif_check_can_be_online(cif_dev);
+	if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME) {
+		if (cif_dev->is_rtt_suspend) {
+			capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK;
+			if (priv)
+				priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO;
+		} else {
+			if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
+				if (cif_dev->chip_id == CHIP_RV1106_CIF) {
+					capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK;
+					priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO;
+				} else {
+					capture_mode = RKCIF_STREAM_MODE_TOISP;
+				}
+			} else if (priv &&
+				   (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
+				    priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME)) {
+				capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK;
+			} else {
+				capture_mode = RKCIF_STREAM_MODE_CAPTURE;
+			}
+		}
+	} else if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME) {
+		if (is_single_dev && is_can_be_online) {
+			capture_mode = RKCIF_STREAM_MODE_TOISP;
+			if (priv)
+				priv->mode.rdbk_mode = RKISP_VICAP_ONLINE;
+		} else {
+			if (cif_dev->is_thunderboot) {
+				capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK;
+				if (priv)
+					priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO;
+			} else {
+				capture_mode = RKCIF_STREAM_MODE_CAPTURE;
+				if (priv)
+					priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ;
+			}
+		}
+	} else {
+		if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
+			capture_mode = RKCIF_STREAM_MODE_TOISP;
+		else if (priv &&
+			 (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
+			  priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME))
+			capture_mode = RKCIF_STREAM_MODE_TOISP_RDBK;
+		else
+			capture_mode = RKCIF_STREAM_MODE_CAPTURE;
+	}
+	if (priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE && mode == RKCIF_RESUME_CIF)
+		goto out_resume;
+
+	for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
+		stream = &cif_dev->stream[i];
+		if (stream->state != RKCIF_STATE_RESET_IN_STREAMING)
+			continue;
+
+		stream->fs_cnt_in_single_frame = 0;
+		if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME)
+			stream->is_single_cap = true;
+		spin_lock_irqsave(&stream->vbq_lock, flags);
+		if (!priv || priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ) {
+			if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
+				if (stream->curr_buf == stream->next_buf) {
+					if (stream->curr_buf)
+						list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
+				} else {
+					if (stream->curr_buf)
+						list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
+					if (stream->next_buf)
+						list_add_tail(&stream->next_buf->queue, &stream->buf_head);
+				}
+				stream->curr_buf = NULL;
+				stream->next_buf = NULL;
+			}
+		} else {
+			if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
+				if (stream->curr_buf_toisp == stream->next_buf_toisp) {
+					if (stream->curr_buf_toisp)
+						list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
+				} else {
+					if (stream->curr_buf_toisp)
+						list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
+					if (stream->next_buf_toisp)
+						list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head);
+				}
+				stream->curr_buf_toisp = NULL;
+				stream->next_buf_toisp = NULL;
+			} else {
+				if (stream->curr_buf_toisp == stream->next_buf_toisp) {
+					if (stream->curr_buf_toisp)
+						list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
+				} else {
+					if (stream->curr_buf_toisp)
+						list_add_tail(&stream->curr_buf_toisp->list, &stream->rx_buf_head);
+					if (stream->next_buf_toisp)
+						list_add_tail(&stream->next_buf_toisp->list, &stream->rx_buf_head);
+				}
+				stream->curr_buf_toisp = NULL;
+				stream->next_buf_toisp = NULL;
+			}
+		}
+
+		spin_unlock_irqrestore(&stream->vbq_lock, flags);
+
+		if (priv) {
+			if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
+				sditf_change_to_online(priv);
+				if (cif_dev->resume_mode == RKISP_RTT_MODE_MULTI_FRAME &&
+				    stream->rx_buf_num &&
+				    (priv->hdr_cfg.hdr_mode == NO_HDR ||
+				     (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) ||
+				     (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2)))
+					rkcif_free_rx_buf(stream, priv->buf_num);
+				else if (!stream->rx_buf_num &&
+					 ((priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 0) ||
+					 (priv->hdr_cfg.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1))))
+					rkcif_init_rx_buf(stream, 1);
+			} else {
+				if (stream->is_single_cap && stream->id == 0) {
+					vicap_mode = priv->mode;
+					vicap_mode.rdbk_mode = RKISP_VICAP_RDBK_AUTO_ONE_FRAME;
+					sd = get_rkisp_sd(priv);
+					if (sd) {
+						ret = v4l2_subdev_call(sd, core, ioctl,
+								       RKISP_VICAP_CMD_MODE, &vicap_mode);
+						if (ret)
+							v4l2_err(&cif_dev->v4l2_dev,
+								 "set isp work mode rdbk aotu oneframe fail\n");
+
+					}
+				}
+				sditf_disable_immediately(priv);
+				if (!stream->rx_buf_num &&
+				    capture_mode == RKCIF_STREAM_MODE_TOISP_RDBK) {
+					if (cif_dev->resume_mode == RKISP_RTT_MODE_ONE_FRAME)
+						rkcif_init_rx_buf(stream, 1);
+					else
+						rkcif_init_rx_buf(stream, priv->buf_num);
+				}
+			}
+		}
+
+		stream->lack_buf_cnt = 0;
+		if (cif_dev->active_sensor  &&
+		    (cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
+		    cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ||
+		    cif_dev->active_sensor->mbus.type == V4L2_MBUS_CCP2))
+			ret = rkcif_csi_stream_start(stream, capture_mode);
+		else
+			ret = rkcif_stream_start(stream, capture_mode);
+		if (ret)
+			v4l2_err(&cif_dev->v4l2_dev, "%s:resume stream[%d] failed\n",
+				 __func__, stream->id);
+
+		resume_cnt++;
+		stream->cur_skip_frame = stream->skip_frame;
+		v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
+			 "resume stream[%d], frm_idx:%d, csi_sof:%d\n",
+			 stream->id, stream->frame_idx,
+			 rkcif_get_sof(cif_dev));
+	}
+
+	if (resume_cnt == 0)
+		goto out_resume;
+
+	if (!cif_dev->resume_mode)
+		rkcif_subdevs_set_power(cif_dev, on);
+
+	atomic_set(&cif_dev->streamoff_cnt, 0);
+	rkcif_subdevs_set_stream(cif_dev, on);
+
+	if (cif_dev->chip_id < CHIP_RK3588_CIF)
+		rkcif_start_luma(&cif_dev->luma_vdev,
+				 cif_dev->stream[RKCIF_STREAM_MIPI_ID0].cif_fmt_in);
+out_resume:
+	mutex_unlock(&cif_dev->stream_lock);
+	return 0;
+}
+
 void rkcif_err_print_work(struct work_struct *work)
 {
 	struct rkcif_err_state_work *err_state_work = container_of(work,
@@ -9795,7 +10901,7 @@
 	u64 cur_time = 0;
 	bool is_print = false;
 
-	cur_time = ktime_get_ns();
+	cur_time = rkcif_time_get_ns(dev);
 	if (err_state_work->last_timestamp == 0) {
 		is_print = true;
 	} else {
@@ -9839,10 +10945,18 @@
 		v4l2_err(&dev->v4l2_dev,
 			 "stream[3], frm0/frm1 end simultaneously,frm id:%d, cnt %llu\n",
 			 dev->stream[3].frame_idx, dev->irq_stats.trig_simult_cnt[3]);
-	if (err_state & RKCIF_ERR_SIZE)
-		v4l2_err(&dev->v4l2_dev,
-			 "ERROR: csi size err, intstat:0x%x, lastline:0x%x, cnt %llu\n",
-			 intstat, lastline, dev->irq_stats.csi_size_err_cnt);
+	if (err_state & RKCIF_ERR_SIZE) {
+		if (dev->chip_id >= CHIP_RK3588_CIF)
+			v4l2_err(&dev->v4l2_dev,
+				 "ERROR: csi size err, intstat:0x%x, size:0x%x,0x%x,0x%x,0x%x, cnt %llu\n",
+				 intstat, err_state_work->size_id0, err_state_work->size_id1,
+				 err_state_work->size_id2, err_state_work->size_id3,
+				 dev->irq_stats.csi_size_err_cnt);
+		else
+			v4l2_err(&dev->v4l2_dev,
+				 "ERROR: csi size err, intstat:0x%x, lastline:0x%x, cnt %llu\n",
+				 intstat, lastline, dev->irq_stats.csi_size_err_cnt);
+	}
 	if (err_state & RKCIF_ERR_OVERFLOW)
 		v4l2_err(&dev->v4l2_dev,
 			 "ERROR: csi fifo overflow, intstat:0x%x, lastline:0x%x, cnt %llu\n",
@@ -9876,6 +10990,7 @@
 	unsigned long flags;
 	bool is_update = false;
 	int ret = 0;
+	int on = 0;
 
 	if (!cif_dev->active_sensor)
 		return;
@@ -9896,13 +11011,22 @@
 		if (intstat) {
 			rkcif_write_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, intstat);
 			v4l2_dbg(2, rkcif_debug, &cif_dev->v4l2_dev,
-				 "intstat 0x%x\n",
-				 intstat);
+				 "intstat 0x%x\n", intstat);
 		} else {
 			return;
 		}
 
 		if (intstat & CSI_SIZE_ERR) {
+			if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
+				cif_dev->err_state_work.size_id0 = rkcif_read_register(cif_dev,
+					CIF_REG_MIPI_FRAME_SIZE_ID0);
+				cif_dev->err_state_work.size_id1 = rkcif_read_register(cif_dev,
+					CIF_REG_MIPI_FRAME_SIZE_ID1);
+				cif_dev->err_state_work.size_id2 = rkcif_read_register(cif_dev,
+					CIF_REG_MIPI_FRAME_SIZE_ID2);
+				cif_dev->err_state_work.size_id3 = rkcif_read_register(cif_dev,
+					CIF_REG_MIPI_FRAME_SIZE_ID3);
+			}
 			cif_dev->irq_stats.csi_size_err_cnt++;
 			cif_dev->err_state |= RKCIF_ERR_SIZE;
 			rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000);
@@ -9915,9 +11039,15 @@
 			return;
 		}
 
-		if (intstat & CSI_BANDWIDTH_LACK_V1) {
+		if (intstat & CSI_BANDWIDTH_LACK_V1 &&
+		    cif_dev->intr_mask & CSI_BANDWIDTH_LACK_V1) {
 			cif_dev->irq_stats.csi_bwidth_lack_cnt++;
 			cif_dev->err_state |= RKCIF_ERR_BANDWIDTH_LACK;
+			if (cif_dev->irq_stats.csi_bwidth_lack_cnt > 10) {
+				rkcif_write_register_and(cif_dev, CIF_REG_MIPI_LVDS_INTEN, ~(CSI_BANDWIDTH_LACK_V1));
+				cif_dev->intr_mask &= ~(CSI_BANDWIDTH_LACK_V1);
+				schedule_delayed_work(&cif_dev->work_deal_err, msecs_to_jiffies(1000));
+			}
 		}
 
 		if (intstat & CSI_ALL_ERROR_INTEN_V1) {
@@ -9972,7 +11102,19 @@
 					  stream->id,
 					  stream->frame_idx - 1,
 					  stream->frame_phase,
-					  ktime_get_ns());
+					  rkcif_time_get_ns(cif_dev));
+			if (stream->is_finish_stop_dma && stream->is_wait_dma_stop) {
+				stream->is_wait_dma_stop = false;
+				wake_up(&stream->wq_stopped);
+				stream->is_finish_stop_dma = false;
+				continue;
+			}
+
+			if (stream->is_finish_stop_dma && stream->is_wait_stop_complete) {
+				stream->is_finish_stop_dma = false;
+				stream->is_wait_stop_complete = false;
+				complete(&stream->stop_complete);
+			}
 
 			if (stream->crop_dyn_en)
 				rkcif_dynamic_crop(stream);
@@ -9982,13 +11124,42 @@
 					is_update = true;
 				else
 					is_update = rkcif_check_buffer_prepare(stream);
+				v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev,
+					 "dma capture by vicap, is_updata %d, group mode %d, dma_en %d\n",
+					 is_update, cif_dev->sync_cfg.type, stream->dma_en);
 				if (is_update)
 					rkcif_update_stream(cif_dev, stream, mipi_id);
 			} else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
+				v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev,
+					 "dma capture by isp, dma_en 0x%x\n",
+					 stream->dma_en);
 				rkcif_update_stream_toisp(cif_dev, stream, mipi_id);
 			} else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) {
+				v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev,
+					 "dma capture by rockit, dma_en 0x%x\n",
+					 stream->dma_en);
 				rkcif_update_stream_rockit(cif_dev, stream, mipi_id);
 			}
+			if (stream->is_single_cap && !stream->cur_skip_frame) {
+				if (stream->dma_en & RKCIF_DMAEN_BY_ISP)
+					stream->to_stop_dma = RKCIF_DMAEN_BY_ISP;
+				else if (stream->dma_en & RKCIF_DMAEN_BY_VICAP)
+					stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP;
+				else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT)
+					stream->to_stop_dma = RKCIF_DMAEN_BY_ROCKIT;
+				rkcif_stop_dma_capture(stream);
+				stream->is_single_cap = false;
+				if ((cif_dev->hdr.hdr_mode == NO_HDR && atomic_read(&cif_dev->streamoff_cnt) == 1) ||
+				    (cif_dev->hdr.hdr_mode == HDR_X2 && atomic_read(&cif_dev->streamoff_cnt) == 2) ||
+				    (cif_dev->hdr.hdr_mode == HDR_X3 && atomic_read(&cif_dev->streamoff_cnt) == 3)) {
+					rkcif_dphy_quick_stream(stream->cifdev, on);
+					cif_dev->sensor_work.on = 0;
+					schedule_work(&cif_dev->sensor_work.work);
+				}
+			}
+
+			if (stream->cur_skip_frame)
+				stream->cur_skip_frame--;
 
 			if (cif_dev->chip_id >= CHIP_RV1106_CIF)
 				rkcif_modify_frame_skip_config(stream);
@@ -10003,13 +11174,13 @@
 			}
 
 			spin_lock_irqsave(&stream->vbq_lock, flags);
-			if (stream->is_finish_stop_dma) {
-				wake_up(&stream->wq_stopped);
-				stream->is_finish_stop_dma = false;
-			}
-			if (!(stream->dma_en & RKCIF_DMAEN_BY_ISP) && stream->lack_buf_cnt == 2) {
+			if (!(stream->cur_stream_mode & RKCIF_STREAM_MODE_TOISP) &&
+			    stream->lack_buf_cnt == 2) {
 				stream->to_stop_dma = RKCIF_DMAEN_BY_VICAP;
 				rkcif_stop_dma_capture(stream);
+				v4l2_dbg(4, rkcif_debug, &cif_dev->v4l2_dev,
+					 "stream[%d] to stop dma, lack_buf_cnt %d\n",
+					 stream->id, stream->lack_buf_cnt);
 			}
 			spin_unlock_irqrestore(&stream->vbq_lock, flags);
 			if (stream->to_en_scale) {
@@ -10036,10 +11207,11 @@
 			if (intstat & CSI_START_INTSTAT(i)) {
 				stream = &cif_dev->stream[i];
 				if (i == 0) {
-					rkcif_deal_sof(cif_dev);
+					if (!stream->cur_skip_frame)
+						rkcif_deal_sof(cif_dev);
 				} else {
 					spin_lock_irqsave(&stream->fps_lock, flags);
-					stream->readout.fs_timestamp = ktime_get_ns();
+					stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev);
 					stream->frame_idx++;
 					spin_unlock_irqrestore(&stream->fps_lock, flags);
 				}
@@ -10070,7 +11242,8 @@
 						v4l2_info(&cif_dev->v4l2_dev,
 							  "line int %lld\n",
 							  stream->line_int_cnt);
-					if (cif_dev->sditf[0] && cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
+					if (cif_dev->sditf[0] && (cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO ||
+					    cif_dev->sditf[0]->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO_ONE_FRAME))
 						rkcif_line_wake_up_rdbk(stream, stream->id);
 					else
 						rkcif_line_wake_up(stream, stream->id);
@@ -10179,7 +11352,8 @@
 
 		if (intstat & DVP_FRAME0_START_ID0 || intstat & DVP_FRAME1_START_ID0) {
 			stream->is_in_vblank = false;
-			rkcif_deal_sof(cif_dev);
+			if (!stream->cur_skip_frame)
+				rkcif_deal_sof(cif_dev);
 		}
 
 		if (stream->crop_dyn_en)
@@ -10291,10 +11465,11 @@
 			if (intstat & CSI_START_INTSTAT(i)) {
 				stream = &cif_dev->stream[i];
 				if (i == 0) {
-					rkcif_deal_sof(cif_dev);
+					if (!stream->cur_skip_frame)
+						rkcif_deal_sof(cif_dev);
 				} else {
 					spin_lock_irqsave(&stream->fps_lock, flags);
-					stream->readout.fs_timestamp = ktime_get_ns();
+					stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev);
 					stream->frame_idx++;
 					spin_unlock_irqrestore(&stream->fps_lock, flags);
 				}
@@ -10421,9 +11596,9 @@
 
 				spin_lock_irqsave(&stream->fps_lock, flags);
 				if (stream->frame_phase & CIF_CSI_FRAME0_READY)
-					stream->fps_stats.frm0_timestamp = ktime_get_ns();
+					stream->fps_stats.frm0_timestamp = rkcif_time_get_ns(cif_dev);
 				else if (stream->frame_phase & CIF_CSI_FRAME1_READY)
-					stream->fps_stats.frm1_timestamp = ktime_get_ns();
+					stream->fps_stats.frm1_timestamp = rkcif_time_get_ns(cif_dev);
 				spin_unlock_irqrestore(&stream->fps_lock, flags);
 
 				ret = rkcif_assign_new_buffer_oneframe(stream,
@@ -10494,7 +11669,8 @@
 		    (cif_dev->dvp_sof_in_oneframe == 0)) {
 			if ((intstat & (PRE_INF_FRAME_END | PST_INF_FRAME_END)) == 0x0) {
 				if ((intstat & INTSTAT_ERR) == 0x0) {
-					rkcif_deal_sof(cif_dev);
+					if (!stream->cur_skip_frame)
+						rkcif_deal_sof(cif_dev);
 					int_en = rkcif_read_register(cif_dev, CIF_REG_DVP_INTEN);
 					int_en &= ~LINE_INT_EN;
 					rkcif_write_register(cif_dev, CIF_REG_DVP_INTEN, int_en);

--
Gitblit v1.6.2