From 9999e48639b3cecb08ffb37358bcba3b48161b29 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 08:50:17 +0000
Subject: [PATCH] add ax88772_rst

---
 kernel/drivers/media/platform/rockchip/isp/dev.c |  481 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 404 insertions(+), 77 deletions(-)

diff --git a/kernel/drivers/media/platform/rockchip/isp/dev.c b/kernel/drivers/media/platform/rockchip/isp/dev.c
index 64a4e74..ebf4a8c 100644
--- a/kernel/drivers/media/platform/rockchip/isp/dev.c
+++ b/kernel/drivers/media/platform/rockchip/isp/dev.c
@@ -45,13 +45,13 @@
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/regmap.h>
-#include <dt-bindings/soc/rockchip-system-status.h>
 #include <soc/rockchip/rockchip-system-status.h>
 #include "common.h"
 #include "isp_ispp.h"
 #include "regs.h"
 #include "rkisp.h"
 #include "version.h"
+#include "csi.h"
 
 #define RKISP_VERNO_LEN		10
 
@@ -62,6 +62,14 @@
 bool rkisp_monitor;
 module_param_named(monitor, rkisp_monitor, bool, 0644);
 MODULE_PARM_DESC(monitor, "rkisp abnormal restart monitor");
+
+bool rkisp_irq_dbg;
+module_param_named(irq_dbg, rkisp_irq_dbg, bool, 0644);
+MODULE_PARM_DESC(irq_dbg, "rkisp interrupt runtime");
+
+static bool rkisp_rdbk_auto;
+module_param_named(rdbk_auto, rkisp_rdbk_auto, bool, 0644);
+MODULE_PARM_DESC(irq_dbg, "rkisp and vicap auto readback mode");
 
 static bool rkisp_clk_dbg;
 module_param_named(clk_dbg, rkisp_clk_dbg, bool, 0644);
@@ -78,6 +86,10 @@
 static unsigned int rkisp_wait_line;
 module_param_named(wait_line, rkisp_wait_line, uint, 0644);
 MODULE_PARM_DESC(wait_line, "rkisp wait line to buf done early");
+
+static unsigned int rkisp_wrap_line;
+module_param_named(wrap_line, rkisp_wrap_line, uint, 0644);
+MODULE_PARM_DESC(wrap_line, "rkisp wrap line for mpp");
 
 static DEFINE_MUTEX(rkisp_dev_mutex);
 static LIST_HEAD(rkisp_device_list);
@@ -126,7 +138,7 @@
 	p->num_subdevs = 0;
 	memset(p->subdevs, 0, sizeof(p->subdevs));
 
-	if (!(dev->isp_inp & (INP_CSI | INP_DVP | INP_LVDS)))
+	if (!(dev->isp_inp & (INP_CSI | INP_DVP | INP_LVDS | INP_CIF)))
 		return 0;
 
 	while (1) {
@@ -164,21 +176,35 @@
 {
 	struct rkisp_device *dev = container_of(p, struct rkisp_device, pipe);
 	struct rkisp_hw_dev *hw_dev = dev->hw_dev;
-	u32 w = hw_dev->max_in.w ? hw_dev->max_in.w : dev->isp_sdev.in_frm.width;
 	struct v4l2_subdev *sd;
 	struct v4l2_ctrl *ctrl;
-	u64 data_rate;
-	int i;
+	u64 data_rate = 0;
+	int i, fps;
 
-	if (dev->isp_inp & (INP_RAWRD0 | INP_RAWRD1 | INP_RAWRD2 | INP_CIF)) {
-		for (i = 0; i < hw_dev->num_clk_rate_tbl; i++) {
-			if (w <= hw_dev->clk_rate_tbl[i].refer_data)
-				break;
+	hw_dev->isp_size[dev->dev_id].is_on = true;
+	if (hw_dev->is_runing) {
+		if (dev->isp_ver >= ISP_V30 && !rkisp_clk_dbg)
+			hw_dev->is_dvfs = true;
+		return 0;
+	}
+
+	if (dev->isp_inp & (INP_RAWRD0 | INP_RAWRD1 | INP_RAWRD2) ||
+	    (dev->is_pre_on && hw_dev->dev_num > 1)) {
+		if (dev->isp_ver < ISP_V30 || dev->is_pre_on) {
+			/* isp with mipi no support dvfs, calculate max data rate */
+			for (i = 0; i < hw_dev->dev_num; i++) {
+				fps = hw_dev->isp_size[i].fps;
+				if (!fps)
+					fps = 30;
+				data_rate += (fps * hw_dev->isp_size[i].size);
+			}
+		} else {
+			i = dev->dev_id;
+			fps = hw_dev->isp_size[i].fps;
+			if (!fps)
+				fps = 30;
+			data_rate = fps * hw_dev->isp_size[i].size;
 		}
-		if (!hw_dev->is_single)
-			i++;
-		if (i > hw_dev->num_clk_rate_tbl - 1)
-			i = hw_dev->num_clk_rate_tbl - 1;
 		goto end;
 	}
 
@@ -187,22 +213,25 @@
 		return 0;
 	}
 
-	/* find the subdev of active sensor */
+	/* find the subdev of active sensor or vicap itf */
 	sd = p->subdevs[0];
 	for (i = 0; i < p->num_subdevs; i++) {
 		sd = p->subdevs[i];
-		if (sd->entity.function == MEDIA_ENT_F_CAM_SENSOR)
+		if (sd->entity.function == MEDIA_ENT_F_CAM_SENSOR ||
+		    sd->entity.function == MEDIA_ENT_F_PROC_VIDEO_COMPOSER)
 			break;
 	}
 
 	if (i == p->num_subdevs) {
 		v4l2_warn(&dev->v4l2_dev, "No active sensor\n");
+		hw_dev->isp_size[dev->dev_id].is_on = false;
 		return -EPIPE;
 	}
 
 	ctrl = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_PIXEL_RATE);
 	if (!ctrl) {
 		v4l2_warn(&dev->v4l2_dev, "No pixel rate control in subdev\n");
+		hw_dev->isp_size[dev->dev_id].is_on = false;
 		return -EPIPE;
 	}
 
@@ -210,7 +239,10 @@
 	data_rate = v4l2_ctrl_g_ctrl_int64(ctrl) *
 		    dev->isp_sdev.in_fmt.bus_width;
 	data_rate >>= 3;
+end:
 	do_div(data_rate, 1000 * 1000);
+	if (hw_dev->unite == ISP_UNITE_ONE)
+		data_rate *= 4;
 
 	/* increase 25% margin */
 	data_rate += data_rate >> 2;
@@ -221,10 +253,15 @@
 			break;
 	if (i == hw_dev->num_clk_rate_tbl)
 		i--;
-end:
+
 	/* set isp clock rate */
 	rkisp_set_clk_rate(hw_dev->clks[0], hw_dev->clk_rate_tbl[i].clk_rate * 1000000UL);
-	dev_dbg(hw_dev->dev, "set isp clk = %luHz\n", clk_get_rate(hw_dev->clks[0]));
+	if (hw_dev->unite == ISP_UNITE_TWO)
+		rkisp_set_clk_rate(hw_dev->clks[5], hw_dev->clk_rate_tbl[i].clk_rate * 1000000UL);
+	/* aclk equal to core clk */
+	if (dev->isp_ver == ISP_V32)
+		rkisp_set_clk_rate(hw_dev->clks[1], hw_dev->clk_rate_tbl[i].clk_rate * 1000000UL);
+	dev_info(hw_dev->dev, "set isp clk = %luHz\n", clk_get_rate(hw_dev->clks[0]));
 
 	return 0;
 }
@@ -245,22 +282,35 @@
 	if (prepare) {
 		ret = __isp_pipeline_prepare(p, me);
 		if (ret < 0)
-			return ret;
+			goto err;
 	}
 
 	ret = __isp_pipeline_s_isp_clk(p);
 	if (ret < 0)
-		return ret;
+		goto err;
+
+	if (!dev->hw_dev->monitor.is_en)
+		dev->hw_dev->monitor.is_en = rkisp_monitor;
 
 	if (dev->isp_inp & (INP_CSI | INP_RAWRD0 | INP_RAWRD1 | INP_RAWRD2 | INP_CIF))
 		rkisp_csi_config_patch(dev);
 	return 0;
+err:
+	atomic_dec(&p->power_cnt);
+	return ret;
 }
 
 static int rkisp_pipeline_close(struct rkisp_pipeline *p)
 {
-	atomic_dec(&p->power_cnt);
+	struct rkisp_device *dev = container_of(p, struct rkisp_device, pipe);
 
+	if (atomic_dec_return(&p->power_cnt))
+		return 0;
+
+	rkisp_rx_buf_pool_free(dev);
+	dev->hw_dev->isp_size[dev->dev_id].is_on = false;
+	if (dev->hw_dev->is_runing && (dev->isp_ver >= ISP_V30) && !rkisp_clk_dbg)
+		dev->hw_dev->is_dvfs = true;
 	return 0;
 }
 
@@ -271,7 +321,7 @@
 static int rkisp_pipeline_set_stream(struct rkisp_pipeline *p, bool on)
 {
 	struct rkisp_device *dev = container_of(p, struct rkisp_device, pipe);
-	int i, ret;
+	int i, ret, open_num = 0;
 
 	if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
 	    (!on && atomic_dec_return(&p->stream_cnt) > 0))
@@ -281,17 +331,36 @@
 		if (dev->vs_irq >= 0)
 			enable_irq(dev->vs_irq);
 		rockchip_set_system_status(SYS_STATUS_ISP);
-		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, true);
+		ret = v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, true);
+		if (ret < 0)
+			goto err;
 		/* phy -> sensor */
 		for (i = 0; i < p->num_subdevs; ++i) {
+			if ((dev->vicap_in.merge_num > 1) &&
+			    (p->subdevs[i]->entity.function == MEDIA_ENT_F_CAM_SENSOR))
+				continue;
 			ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
 			if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 				goto err_stream_off;
 		}
 	} else {
+		for (i = 0; i < dev->hw_dev->dev_num; i++) {
+			if (dev->hw_dev->isp_size[i].is_on)
+				open_num++;
+		}
+		if (dev->hw_dev->monitor.is_en && open_num == 1) {
+			dev->hw_dev->monitor.is_en = 0;
+			dev->hw_dev->monitor.state = ISP_STOP;
+			if (!completion_done(&dev->hw_dev->monitor.cmpl))
+				complete(&dev->hw_dev->monitor.cmpl);
+		}
 		/* sensor -> phy */
-		for (i = p->num_subdevs - 1; i >= 0; --i)
+		for (i = p->num_subdevs - 1; i >= 0; --i) {
+			if ((dev->vicap_in.merge_num > 1) &&
+			    (p->subdevs[i]->entity.function == MEDIA_ENT_F_CAM_SENSOR))
+				continue;
 			v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
+		}
 		if (dev->vs_irq >= 0)
 			disable_irq(dev->vs_irq);
 		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
@@ -304,7 +373,9 @@
 	for (--i; i >= 0; --i)
 		v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
 	v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
+err:
 	rockchip_clear_system_status(SYS_STATUS_ISP);
+	atomic_dec_return(&p->stream_cnt);
 	return ret;
 }
 
@@ -320,7 +391,7 @@
 	for (s = 0; s < dev->num_sensors; ++s) {
 		struct rkisp_sensor_info *sensor = &dev->sensors[s];
 		u32 type = sensor->sd->entity.function;
-		bool en = s ? 0 : MEDIA_LNK_FL_ENABLED;
+		bool en = s ? 0 : true;
 
 		for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
 			if (sensor->sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)
@@ -342,8 +413,8 @@
 			ret = media_create_pad_link(&sensor->sd->entity, pad,
 				&dev->isp_sdev.sd.entity, RKISP_ISP_PAD_SINK, en);
 		} else {
-			v4l2_subdev_call(sensor->sd, video,
-					 g_mbus_config, &sensor->mbus);
+			v4l2_subdev_call(sensor->sd, pad,
+					 get_mbus_config, 0, &sensor->mbus);
 			if (sensor->mbus.type == V4L2_MBUS_CCP2) {
 				/* mipi-phy lvds link -> isp */
 				dev->isp_inp = INP_LVDS;
@@ -366,16 +437,27 @@
 	return ret;
 }
 
-static int _set_pipeline_default_fmt(struct rkisp_device *dev)
+static int _set_pipeline_default_fmt(struct rkisp_device *dev, bool is_init)
 {
 	struct v4l2_subdev *isp;
 	struct v4l2_subdev_format fmt;
 	struct v4l2_subdev_selection sel;
-	u32 width, height, code;
+	u32 i, width, height, code;
 
+	memset(&sel, 0, sizeof(sel));
+	memset(&fmt, 0, sizeof(fmt));
 	isp = &dev->isp_sdev.sd;
 
-	fmt = dev->active_sensor->fmt[0];
+	if (dev->active_sensor) {
+		fmt = dev->active_sensor->fmt[0];
+		if (!is_init &&
+		    fmt.format.code == dev->isp_sdev.in_frm.code &&
+		    fmt.format.width == dev->isp_sdev.in_frm.width &&
+		    fmt.format.height == dev->isp_sdev.in_frm.height)
+			return 0;
+	} else {
+		fmt.format = dev->isp_sdev.in_frm;
+	}
 	code = fmt.format.code;
 	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
 	fmt.pad = RKISP_ISP_PAD_SINK;
@@ -411,7 +493,7 @@
 		rkisp_set_stream_def_fmt(dev, RKISP_STREAM_SP,
 					 width, height, V4L2_PIX_FMT_NV12);
 	if ((dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) &&
-	    dev->isp_inp == INP_CSI) {
+	    dev->isp_inp == INP_CSI && dev->active_sensor) {
 		width = dev->active_sensor->fmt[1].format.width;
 		height = dev->active_sensor->fmt[1].format.height;
 		code = dev->active_sensor->fmt[1].format.code;
@@ -431,12 +513,49 @@
 			width, height, rkisp_mbus_pixelcode_to_v4l2(code));
 	}
 
-	if (dev->isp_ver == ISP_V20 && dev->isp_inp == INP_CSI) {
+	if (dev->isp_ver == ISP_V20 &&
+	    dev->isp_inp == INP_CSI && dev->active_sensor) {
 		width = dev->active_sensor->fmt[2].format.width;
 		height = dev->active_sensor->fmt[2].format.height;
 		code = dev->active_sensor->fmt[2].format.code;
 		rkisp_set_stream_def_fmt(dev, RKISP_STREAM_DMATX1,
 			width, height, rkisp_mbus_pixelcode_to_v4l2(code));
+	}
+
+	if (dev->isp_ver == ISP_V30) {
+		struct v4l2_pix_format_mplane pixm = {
+			.width = width,
+			.height = height,
+			.pixelformat = rkisp_mbus_pixelcode_to_v4l2(code),
+		};
+
+		for (i = RKISP_STREAM_RAWRD0; i <= RKISP_STREAM_RAWRD2; i++)
+			rkisp_dmarx_set_fmt(&dev->dmarx_dev.stream[i], pixm);
+		rkisp_set_stream_def_fmt(dev, RKISP_STREAM_FBC,
+					 width, height, V4L2_PIX_FMT_FBC0);
+#ifdef RKISP_STREAM_BP_EN
+		rkisp_set_stream_def_fmt(dev, RKISP_STREAM_BP,
+					 width, height, V4L2_PIX_FMT_NV12);
+#endif
+	}
+
+	if (dev->isp_ver == ISP_V32 || dev->isp_ver == ISP_V32_L) {
+		struct v4l2_pix_format_mplane pixm = {
+			.width = width,
+			.height = height,
+			.pixelformat = rkisp_mbus_pixelcode_to_v4l2(code),
+		};
+
+		rkisp_dmarx_set_fmt(&dev->dmarx_dev.stream[RKISP_STREAM_RAWRD0], pixm);
+		rkisp_dmarx_set_fmt(&dev->dmarx_dev.stream[RKISP_STREAM_RAWRD2], pixm);
+		if (dev->isp_ver == ISP_V32) {
+			rkisp_set_stream_def_fmt(dev, RKISP_STREAM_BP,
+						 width, height, V4L2_PIX_FMT_NV12);
+			rkisp_set_stream_def_fmt(dev, RKISP_STREAM_MPDS,
+						 width / 4, height / 4, V4L2_PIX_FMT_NV12);
+			rkisp_set_stream_def_fmt(dev, RKISP_STREAM_BPDS,
+						 width / 4, height / 4, V4L2_PIX_FMT_NV12);
+		}
 	}
 	return 0;
 }
@@ -456,13 +575,16 @@
 	if (ret < 0)
 		goto unlock;
 
-	ret = rkisp_update_sensor_info(dev);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "update sensor failed\n");
-		goto unlock;
+	if (dev->isp_inp) {
+		ret = rkisp_update_sensor_info(dev);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "update sensor failed\n");
+			goto unlock;
+		}
+		dev->is_hw_link = true;
 	}
 
-	ret = _set_pipeline_default_fmt(dev);
+	ret = _set_pipeline_default_fmt(dev, true);
 	if (ret < 0)
 		goto unlock;
 
@@ -470,6 +592,8 @@
 
 unlock:
 	mutex_unlock(&dev->media_dev.graph_mutex);
+	if (!ret && dev->is_thunderboot)
+		schedule_work(&dev->cap_dev.fast_work);
 	return ret;
 }
 
@@ -521,9 +645,28 @@
 	return 0;
 }
 
+static void subdev_notifier_unbind(struct v4l2_async_notifier *notifier,
+				   struct v4l2_subdev *subdev,
+				   struct v4l2_async_subdev *asd)
+{
+	struct rkisp_device *isp_dev = container_of(notifier, struct rkisp_device, notifier);
+	struct rkisp_isp_subdev *isp_sdev = &isp_dev->isp_sdev;
+	struct v4l2_subdev *isp_sd = &isp_sdev->sd;
+	int i;
+
+	for (i = 0; i < isp_dev->num_sensors; i++) {
+		if (isp_dev->sensors[i].sd == subdev) {
+			media_entity_call(&isp_sd->entity, link_setup,
+				isp_sd->entity.pads, subdev->entity.pads, 0);
+			isp_dev->sensors[i].sd = NULL;
+		}
+	}
+}
+
 static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
 	.bound = subdev_notifier_bound,
 	.complete = subdev_notifier_complete,
+	.unbind = subdev_notifier_unbind,
 };
 
 static int isp_subdev_notifier(struct rkisp_device *isp_dev)
@@ -532,14 +675,13 @@
 	struct device *dev = isp_dev->dev;
 	int ret;
 
+	v4l2_async_notifier_init(ntf);
+
 	ret = v4l2_async_notifier_parse_fwnode_endpoints(
 		dev, ntf, sizeof(struct rkisp_async_subdev),
 		rkisp_fwnode_parse);
 	if (ret < 0)
 		return ret;
-
-	if (!ntf->num_subdevs)
-		return -ENODEV;	/* no endpoint */
 
 	ntf->ops = &subdev_notifier_ops;
 
@@ -588,10 +730,6 @@
 	if (ret < 0) {
 		v4l2_err(&dev->v4l2_dev,
 			 "Failed to register subdev notifier(%d)\n", ret);
-		/* maybe use dmarx to input image */
-		ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
-		if (ret == 0)
-			return 0;
 		goto err_unreg_luma_vdev;
 	}
 
@@ -688,12 +826,17 @@
 					      sizeof(struct rkisp_thunderboot_resmem_head),
 					      DMA_BIDIRECTIONAL);
 	ret = dma_mapping_error(dev, isp_dev->resmem_addr);
-
 	isp_dev->is_thunderboot = true;
-	atomic_inc(&isp_dev->hw_dev->tb_ref);
-
-	dev_info(dev, "Allocated reserved memory, paddr: 0x%x\n",
-		(u32)isp_dev->resmem_pa);
+	isp_dev->is_rtt_suspend = false;
+	isp_dev->is_rtt_first = true;
+	if (device_property_read_bool(dev, "rtt-suspend")) {
+		isp_dev->is_rtt_suspend = true;
+		if (!isp_dev->hw_dev->is_thunderboot) {
+			isp_dev->is_thunderboot = false;
+			isp_dev->is_rtt_first = false;
+		}
+	}
+	dev_info(dev, "Allocated reserved memory, paddr: 0x%x\n", (u32)isp_dev->resmem_pa);
 	return ret;
 }
 
@@ -702,41 +845,49 @@
 	struct device *dev = &pdev->dev;
 	struct v4l2_device *v4l2_dev;
 	struct rkisp_device *isp_dev;
-	int i, ret;
+	int i, ret, mult = 1;
 
-	sprintf(rkisp_version, "v%02x.%02x.%02x",
-		RKISP_DRIVER_VERSION >> 16,
-		(RKISP_DRIVER_VERSION & 0xff00) >> 8,
-		RKISP_DRIVER_VERSION & 0x00ff);
+	snprintf(rkisp_version, sizeof(rkisp_version),
+		 "v%02x.%02x.%02x",
+		 RKISP_DRIVER_VERSION >> 16,
+		 (RKISP_DRIVER_VERSION & 0xff00) >> 8,
+		 RKISP_DRIVER_VERSION & 0x00ff);
 
 	dev_info(dev, "rkisp driver version: %s\n", rkisp_version);
 
 	isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
 	if (!isp_dev)
 		return -ENOMEM;
-	isp_dev->sw_base_addr = devm_kzalloc(dev, RKISP_ISP_SW_MAX_SIZE, GFP_KERNEL);
-	if (!isp_dev->sw_base_addr)
-		return -ENOMEM;
 
 	dev_set_drvdata(dev, isp_dev);
 	isp_dev->dev = dev;
+	ret = rkisp_attach_hw(isp_dev);
+	if (ret)
+		return ret;
+
+	if (isp_dev->hw_dev->unite)
+		mult = 2;
+	isp_dev->sw_base_addr = devm_kzalloc(dev, RKISP_ISP_SW_MAX_SIZE * mult, GFP_KERNEL);
+	if (!isp_dev->sw_base_addr)
+		return -ENOMEM;
 
 	ret = rkisp_vs_irq_parse(dev);
 	if (ret)
 		return ret;
 
-	ret = rkisp_attach_hw(isp_dev);
+	snprintf(isp_dev->media_dev.model, sizeof(isp_dev->media_dev.model),
+		 "%s%d", DRIVER_NAME, isp_dev->dev_id);
+	if (!isp_dev->hw_dev->unite)
+		strscpy(isp_dev->name, dev_name(dev), sizeof(isp_dev->name));
+	else
+		snprintf(isp_dev->name, sizeof(isp_dev->name),
+			 "%s%d", "rkisp-unite", isp_dev->dev_id);
+	strscpy(isp_dev->media_dev.driver_name, isp_dev->name,
+		sizeof(isp_dev->media_dev.driver_name));
+
+	ret = rkisp_get_reserved_mem(isp_dev);
 	if (ret)
 		return ret;
-
-	sprintf(isp_dev->media_dev.model, "%s%d",
-		DRIVER_NAME, isp_dev->dev_id);
-
-	if (isp_dev->hw_dev->is_thunderboot) {
-		ret = rkisp_get_reserved_mem(isp_dev);
-		if (ret)
-			return ret;
-	}
 
 	mutex_init(&isp_dev->apilock);
 	mutex_init(&isp_dev->iqlock);
@@ -755,9 +906,6 @@
 		}
 	}
 
-	strscpy(isp_dev->name, dev_name(dev), sizeof(isp_dev->name));
-	strscpy(isp_dev->media_dev.driver_name, isp_dev->name,
-		sizeof(isp_dev->media_dev.driver_name));
 	isp_dev->media_dev.dev = dev;
 	isp_dev->media_dev.ops = &rkisp_media_ops;
 
@@ -780,11 +928,13 @@
 		goto err_unreg_v4l2_dev;
 	}
 
+	pm_runtime_enable(dev);
 	/* create & register platefom subdev (from of_node) */
 	ret = rkisp_register_platform_subdevs(isp_dev);
-	if (ret < 0)
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "Failed to register platform subdevs:%d\n", ret);
 		goto err_unreg_media_dev;
-
+	}
 	rkisp_wait_line = 0;
 	of_property_read_u32(dev->of_node, "wait-line", &rkisp_wait_line);
 
@@ -793,10 +943,7 @@
 	mutex_lock(&rkisp_dev_mutex);
 	list_add_tail(&isp_dev->list, &rkisp_device_list);
 	mutex_unlock(&rkisp_dev_mutex);
-
-	pm_runtime_enable(dev);
-	if (isp_dev->hw_dev->is_thunderboot && isp_dev->is_thunderboot)
-		pm_runtime_get_noresume(isp_dev->hw_dev->dev);
+	isp_dev->is_probe_end = true;
 	return 0;
 
 err_unreg_media_dev:
@@ -810,11 +957,17 @@
 {
 	struct rkisp_device *isp_dev = platform_get_drvdata(pdev);
 
+	isp_dev->is_hw_link = false;
+	isp_dev->hw_dev->isp[isp_dev->dev_id] = NULL;
+
 	pm_runtime_disable(&pdev->dev);
 
 	rkisp_proc_cleanup(isp_dev);
 	media_device_unregister(&isp_dev->media_dev);
+	v4l2_async_notifier_unregister(&isp_dev->notifier);
+	v4l2_async_notifier_cleanup(&isp_dev->notifier);
 	v4l2_device_unregister(&isp_dev->v4l2_dev);
+	v4l2_ctrl_handler_free(&isp_dev->ctrl_handler);
 	rkisp_unregister_luma_vdev(&isp_dev->luma_vdev);
 	rkisp_unregister_params_vdev(&isp_dev->params_vdev);
 	rkisp_unregister_stats_vdev(&isp_dev->stats_vdev);
@@ -843,7 +996,21 @@
 	struct rkisp_device *isp_dev = dev_get_drvdata(dev);
 	int ret;
 
+	/* power on to config default format from sensor */
+	if (isp_dev->isp_inp & (INP_CSI | INP_DVP | INP_LVDS | INP_CIF) &&
+	    rkisp_update_sensor_info(isp_dev) >= 0)
+		_set_pipeline_default_fmt(isp_dev, false);
+
+	if (isp_dev->hw_dev->is_assigned_clk)
+		rkisp_clk_dbg = true;
+
+	if (isp_dev->hw_dev->unite == ISP_UNITE_ONE &&
+	    !(isp_dev->isp_inp & INP_RAWRD2))
+		rkisp_rdbk_auto = true;
+
 	isp_dev->cap_dev.wait_line = rkisp_wait_line;
+	isp_dev->cap_dev.wrap_line = rkisp_wrap_line;
+	isp_dev->is_rdbk_auto = rkisp_rdbk_auto;
 	mutex_lock(&isp_dev->hw_dev->dev_lock);
 	ret = pm_runtime_get_sync(isp_dev->hw_dev->dev);
 	mutex_unlock(&isp_dev->hw_dev->dev_lock);
@@ -860,9 +1027,168 @@
 late_initcall_sync(rkisp_clr_unready_dev);
 #endif
 
+static int rkisp_pm_prepare(struct device *dev)
+{
+	struct rkisp_device *isp_dev = dev_get_drvdata(dev);
+	struct rkisp_hw_dev *hw = isp_dev->hw_dev;
+	struct rkisp_pipeline *p = &isp_dev->pipe;
+	unsigned long lock_flags = 0;
+	int i, on = 0, time = 100;
+
+	if (isp_dev->isp_state & ISP_STOP) {
+		if (pm_runtime_active(dev) &&
+		    rkisp_link_sensor(isp_dev->isp_inp)) {
+			struct v4l2_subdev *mipi_sensor = NULL;
+
+			rkisp_get_remote_mipi_sensor(isp_dev, &mipi_sensor, MEDIA_ENT_F_CAM_SENSOR);
+			if (mipi_sensor)
+				v4l2_subdev_call(mipi_sensor, core, s_power, 0);
+		}
+		return 0;
+	}
+
+	isp_dev->suspend_sync = false;
+	isp_dev->is_suspend = true;
+	if (rkisp_link_sensor(isp_dev->isp_inp)) {
+		for (i = p->num_subdevs - 1; i >= 0; i--)
+			v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
+	} else if (isp_dev->isp_inp & INP_CIF && !(IS_HDR_RDBK(isp_dev->rd_mode))) {
+		v4l2_subdev_call(p->subdevs[0], core, ioctl, RKISP_VICAP_CMD_QUICK_STREAM, &on);
+	}
+	if (IS_HDR_RDBK(isp_dev->rd_mode)) {
+		spin_lock_irqsave(&hw->rdbk_lock, lock_flags);
+		if (!hw->is_idle && hw->cur_dev_id == isp_dev->dev_id)
+			isp_dev->suspend_sync = true;
+		spin_unlock_irqrestore(&hw->rdbk_lock, lock_flags);
+	}
+
+	if (isp_dev->suspend_sync) {
+		wait_for_completion_timeout(&isp_dev->pm_cmpl, msecs_to_jiffies(time));
+		isp_dev->suspend_sync = false;
+	}
+
+	if (rkisp_link_sensor(isp_dev->isp_inp)) {
+		for (i = p->num_subdevs - 1; i >= 0; i--)
+			v4l2_subdev_call(p->subdevs[i], core, s_power, 0);
+	}
+	return 0;
+}
+
+static void rkisp_pm_complete(struct device *dev)
+{
+	struct rkisp_device *isp_dev = dev_get_drvdata(dev);
+	struct rkisp_hw_dev *hw = isp_dev->hw_dev;
+	struct rkisp_pipeline *p = &isp_dev->pipe;
+	struct rkisp_stream *stream;
+	int i, on = 1, rd_mode = isp_dev->rd_mode;
+	u32 val;
+
+	if (isp_dev->isp_state & ISP_STOP) {
+		if (pm_runtime_active(dev) &&
+		    rkisp_link_sensor(isp_dev->isp_inp)) {
+			struct v4l2_subdev *mipi_sensor = NULL;
+
+			rkisp_get_remote_mipi_sensor(isp_dev, &mipi_sensor, MEDIA_ENT_F_CAM_SENSOR);
+			if (mipi_sensor)
+				v4l2_subdev_call(mipi_sensor, core, s_power, 1);
+		}
+		return;
+	}
+
+	if (isp_dev->is_rtt_suspend) {
+		rkisp_save_tb_info(isp_dev);
+		v4l2_info(&isp_dev->v4l2_dev,
+			  "tb info en:%d comp:%d cnt:%d w:%d h:%d cam:%d idx:%d mode:%d\n",
+			  isp_dev->tb_head.enable, isp_dev->tb_head.complete,
+			  isp_dev->tb_head.frm_total, isp_dev->tb_head.width,
+			  isp_dev->tb_head.height, isp_dev->tb_head.camera_num,
+			  isp_dev->tb_head.camera_index, isp_dev->tb_head.rtt_mode);
+		isp_dev->is_first_double = false;
+		switch (isp_dev->tb_head.rtt_mode) {
+		case RKISP_RTT_MODE_ONE_FRAME:
+			isp_dev->is_first_double = true;
+			/* switch to readback mode */
+			switch (rd_mode) {
+			case HDR_LINEX3_DDR:
+				isp_dev->rd_mode = HDR_RDBK_FRAME3;
+				break;
+			case HDR_LINEX2_DDR:
+				isp_dev->rd_mode = HDR_RDBK_FRAME2;
+				break;
+			default:
+				isp_dev->rd_mode = HDR_RDBK_FRAME1;
+			}
+			break;
+		case RKISP_RTT_MODE_MULTI_FRAME:
+		default:
+			if (isp_dev->tb_head.rtt_mode != RKISP_RTT_MODE_MULTI_FRAME)
+				v4l2_warn(&isp_dev->v4l2_dev,
+					  "invalid rtt mode:%d, change to mode:%d\n",
+					  isp_dev->tb_head.rtt_mode, RKISP_RTT_MODE_MULTI_FRAME);
+			if (!hw->is_single)
+				break;
+			/* switch to online mode for single sensor */
+			switch (rd_mode) {
+			case HDR_RDBK_FRAME3:
+				isp_dev->rd_mode = HDR_LINEX3_DDR;
+				break;
+			case HDR_RDBK_FRAME2:
+				isp_dev->rd_mode = HDR_LINEX2_DDR;
+				break;
+			default:
+				isp_dev->rd_mode = HDR_NORMAL;
+			}
+		}
+		isp_dev->hdr.op_mode = isp_dev->rd_mode;
+		if (rd_mode != isp_dev->rd_mode && hw->cur_dev_id == isp_dev->dev_id) {
+			rkisp_unite_write(isp_dev, CSI2RX_CTRL0,
+					  SW_IBUF_OP_MODE(isp_dev->rd_mode), true);
+			if (IS_HDR_RDBK(isp_dev->rd_mode))
+				rkisp_unite_set_bits(isp_dev, CTRL_SWS_CFG, 0,
+						     SW_MPIP_DROP_FRM_DIS, true);
+			else
+				rkisp_unite_clear_bits(isp_dev, CTRL_SWS_CFG,
+						       SW_MPIP_DROP_FRM_DIS, true);
+		}
+	}
+
+	isp_dev->is_suspend = false;
+	isp_dev->isp_state = ISP_START | ISP_FRAME_END;
+	if (!hw->is_single && hw->is_multi_overflow)
+		hw->pre_dev_id++;
+	if (isp_dev->is_suspend_one_frame && !hw->is_multi_overflow)
+		isp_dev->is_first_double = true;
+	if (hw->isp_ver > ISP_V20) {
+		val = ISP3X_YNR_FST_FRAME | ISP3X_CNR_FST_FRAME |
+		      ISP3X_DHAZ_FST_FRAME | ISP3X_ADRC_FST_FRAME;
+		if (hw->isp_ver == ISP_V32)
+			val |= ISP32_SHP_FST_FRAME;
+		rkisp_unite_set_bits(isp_dev, ISP3X_ISP_CTRL1, 0, val, false);
+	}
+	for (i = 0; i < RKISP_MAX_STREAM; i++) {
+		stream = &isp_dev->cap_dev.stream[i];
+		if (i == RKISP_STREAM_VIR || !stream->streaming || !stream->curr_buf)
+			continue;
+		/* skip first frame due to hw no reference frame information */
+		if (isp_dev->is_first_double)
+			stream->skip_frame = 1;
+	}
+	if (hw->cur_dev_id == isp_dev->dev_id)
+		rkisp_rdbk_trigger_event(isp_dev, T_CMD_QUEUE, NULL);
+
+	if (rkisp_link_sensor(isp_dev->isp_inp)) {
+		for (i = 0; i < p->num_subdevs; i++)
+			v4l2_subdev_call(p->subdevs[i], core, s_power, 1);
+		for (i = 0; i < p->num_subdevs; i++)
+			v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
+	} else if (isp_dev->isp_inp & INP_CIF && !(IS_HDR_RDBK(isp_dev->rd_mode))) {
+		v4l2_subdev_call(p->subdevs[0], core, ioctl, RKISP_VICAP_CMD_QUICK_STREAM, &on);
+	}
+}
+
 static const struct dev_pm_ops rkisp_plat_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-				pm_runtime_force_resume)
+	.prepare = rkisp_pm_prepare,
+	.complete = rkisp_pm_complete,
 	SET_RUNTIME_PM_OPS(rkisp_runtime_suspend, rkisp_runtime_resume, NULL)
 };
 
@@ -888,3 +1214,4 @@
 MODULE_AUTHOR("Rockchip Camera/ISP team");
 MODULE_DESCRIPTION("Rockchip ISP platform driver");
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);

--
Gitblit v1.6.2