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

---
 kernel/drivers/media/platform/rockchip/isp/hw.c |  350 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 295 insertions(+), 55 deletions(-)

diff --git a/kernel/drivers/media/platform/rockchip/isp/hw.c b/kernel/drivers/media/platform/rockchip/isp/hw.c
index e6e4d9a..5b0f291 100644
--- a/kernel/drivers/media/platform/rockchip/isp/hw.c
+++ b/kernel/drivers/media/platform/rockchip/isp/hw.c
@@ -35,6 +35,12 @@
  *                     rkisp_hw
  */
 
+struct backup_reg {
+	const u32 base;
+	const u32 shd;
+	u32 val;
+};
+
 struct isp_irqs_data {
 	const char *name;
 	irqreturn_t (*irq_hdl)(int irq, void *ctx);
@@ -132,7 +138,7 @@
 	for (i = 0; i < size; i++) {
 		flag = dev->sw_base_addr + reg[i] + RKISP_ISP_SW_REG_SIZE;
 		*flag = SW_REG_CACHE;
-		if (dev->hw_dev->is_unite) {
+		if (dev->hw_dev->unite) {
 			flag += RKISP_ISP_SW_MAX_SIZE / 4;
 			*flag = SW_REG_CACHE;
 		}
@@ -144,7 +150,7 @@
 	struct device *dev = ctx;
 	struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
 	struct rkisp_device *isp = hw_dev->isp[hw_dev->mipi_dev_id];
-	void __iomem *base = !hw_dev->is_unite ?
+	void __iomem *base = hw_dev->unite != ISP_UNITE_TWO ?
 		hw_dev->base_addr : hw_dev->base_next_addr;
 	ktime_t t = 0;
 	s64 us;
@@ -201,7 +207,7 @@
 	struct device *dev = ctx;
 	struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
 	struct rkisp_device *isp = hw_dev->isp[hw_dev->cur_dev_id];
-	void __iomem *base = !hw_dev->is_unite ?
+	void __iomem *base = hw_dev->unite != ISP_UNITE_TWO ?
 		hw_dev->base_addr : hw_dev->base_next_addr;
 	u32 mis_val, tx_isr = MI_RAW0_WR_FRAME | MI_RAW1_WR_FRAME |
 		MI_RAW2_WR_FRAME | MI_RAW3_WR_FRAME;
@@ -237,7 +243,7 @@
 	struct device *dev = ctx;
 	struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
 	struct rkisp_device *isp = hw_dev->isp[hw_dev->cur_dev_id];
-	void __iomem *base = !hw_dev->is_unite ?
+	void __iomem *base = hw_dev->unite != ISP_UNITE_TWO ?
 		hw_dev->base_addr : hw_dev->base_next_addr;
 	unsigned int mis_val, mis_3a = 0;
 	ktime_t t = 0;
@@ -348,6 +354,192 @@
 	return 0;
 }
 
+void rkisp_hw_reg_save(struct rkisp_hw_dev *dev)
+{
+	void *buf = dev->sw_reg;
+
+	memcpy_fromio(buf, dev->base_addr, RKISP_ISP_SW_REG_SIZE);
+	if (dev->unite == ISP_UNITE_TWO) {
+		buf += RKISP_ISP_SW_REG_SIZE;
+		memcpy_fromio(buf, dev->base_next_addr, RKISP_ISP_SW_REG_SIZE);
+	}
+}
+
+void rkisp_hw_reg_restore(struct rkisp_hw_dev *dev)
+{
+	struct rkisp_device *isp = dev->isp[dev->cur_dev_id];
+	void __iomem *base = dev->base_addr;
+	void *reg_buf = dev->sw_reg;
+	u32 val, *reg, *reg1, i, j;
+	u32 self_upd_reg[] = {
+		ISP21_BAY3D_BASE, ISP21_DRC_BASE, ISP3X_BAY3D_CTRL,
+		ISP_DHAZ_CTRL, ISP3X_3DLUT_BASE, ISP_RAWAE_LITE_BASE,
+		RAWAE_BIG1_BASE, RAWAE_BIG2_BASE, RAWAE_BIG3_BASE,
+		ISP_RAWHIST_LITE_BASE, ISP_RAWHIST_BIG1_BASE,
+		ISP_RAWHIST_BIG2_BASE, ISP_RAWHIST_BIG3_BASE,
+		ISP_RAWAF_BASE, ISP_RAWAWB_BASE, ISP_LDCH_BASE,
+		ISP3X_CAC_BASE,
+	};
+	struct backup_reg backup[] = {
+		{
+			.base = MI_MP_WR_Y_BASE,
+			.shd = MI_MP_WR_Y_BASE_SHD,
+		}, {
+			.base = MI_MP_WR_CB_BASE,
+			.shd = MI_MP_WR_CB_BASE_SHD,
+		}, {
+			.base = MI_MP_WR_CR_BASE,
+			.shd = MI_MP_WR_CR_BASE_SHD,
+		}, {
+			.base = MI_SP_WR_Y_BASE,
+			.shd = MI_SP_WR_Y_BASE_SHD,
+		}, {
+			.base = MI_SP_WR_CB_BASE,
+			.shd = MI_SP_WR_CB_BASE_AD_SHD,
+		}, {
+			.base = MI_SP_WR_CR_BASE,
+			.shd = MI_SP_WR_CR_BASE_AD_SHD,
+		}, {
+			.base = ISP3X_MI_BP_WR_Y_BASE,
+			.shd = ISP3X_MI_BP_WR_Y_BASE_SHD,
+		}, {
+			.base = ISP3X_MI_BP_WR_CB_BASE,
+			.shd = ISP3X_MI_BP_WR_CB_BASE_SHD,
+		}, {
+			.base = ISP32_MI_MPDS_WR_Y_BASE,
+			.shd = ISP32_MI_MPDS_WR_Y_BASE_SHD,
+		}, {
+			.base = ISP32_MI_MPDS_WR_CB_BASE,
+			.shd = ISP32_MI_MPDS_WR_CB_BASE_SHD,
+		}, {
+			.base = ISP32_MI_BPDS_WR_Y_BASE,
+			.shd = ISP32_MI_BPDS_WR_Y_BASE_SHD,
+		}, {
+			.base = ISP32_MI_BPDS_WR_CB_BASE,
+			.shd = ISP32_MI_BPDS_WR_CB_BASE_SHD,
+		}, {
+			.base = MI_RAW0_WR_BASE,
+			.shd = MI_RAW0_WR_BASE_SHD,
+		}, {
+			.base = MI_RAW1_WR_BASE,
+			.shd = MI_RAW1_WR_BASE_SHD,
+		}, {
+			.base = MI_RAW2_WR_BASE,
+			.shd = MI_RAW2_WR_BASE_SHD,
+		}, {
+			.base = MI_RAW3_WR_BASE,
+			.shd = MI_RAW3_WR_BASE_SHD,
+		}, {
+			.base = MI_RAW0_RD_BASE,
+			.shd = MI_RAW0_RD_BASE_SHD,
+		}, {
+			.base = MI_RAW1_RD_BASE,
+			.shd = MI_RAW1_RD_BASE_SHD,
+		}, {
+			.base = MI_RAW2_RD_BASE,
+			.shd = MI_RAW2_RD_BASE_SHD,
+		}, {
+			.base = MI_GAIN_WR_BASE,
+			.shd = MI_GAIN_WR_BASE_SHD,
+		}
+	};
+
+	for (i = 0; i <= !!dev->unite; i++) {
+		if (dev->unite != ISP_UNITE_TWO && i)
+			break;
+
+		if (i) {
+			reg_buf += RKISP_ISP_SW_REG_SIZE;
+			base = dev->base_next_addr;
+		}
+
+		/* process special reg */
+		for (j = 0; j < ARRAY_SIZE(self_upd_reg); j++) {
+			reg = reg_buf + self_upd_reg[j];
+			*reg &= ~ISP21_SELF_FORCE_UPD;
+			if (self_upd_reg[j] == ISP3X_3DLUT_BASE && *reg & ISP_3DLUT_EN) {
+				reg = reg_buf + ISP3X_3DLUT_UPDATE;
+				*reg = 1;
+			}
+		}
+		reg = reg_buf + ISP_CTRL;
+		*reg &= ~(CIF_ISP_CTRL_ISP_ENABLE |
+			  CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+			  CIF_ISP_CTRL_ISP_CFG_UPD);
+		reg = reg_buf + MI_WR_INIT;
+		*reg = 0;
+		reg = reg_buf + CSI2RX_CTRL0;
+		*reg &= ~SW_CSI2RX_EN;
+		for (j = 0; j < RKISP_ISP_SW_REG_SIZE; j += 4) {
+			/* skip table RAM */
+			if ((j > ISP3X_LSC_CTRL && j < ISP3X_LSC_XGRAD_01) ||
+			    (j > ISP32_CAC_OFFSET && j < ISP3X_CAC_RO_CNT) ||
+			    (j > ISP3X_3DLUT_UPDATE && j < ISP3X_GAIN_BASE) ||
+			    (j == 0x4840 || j == 0x4a80 || j == 0x4b40 || j == 0x5660))
+				continue;
+			/* skip mmu range */
+			if (dev->isp_ver < ISP_V30 &&
+			    j > ISP21_MI_BAY3D_RD_BASE_SHD && j < CSI2RX_CTRL0)
+				continue;
+			/* reg value of read diff to write */
+			if (j == ISP_MPFBC_CTRL ||
+			    j == ISP32_ISP_AWB1_GAIN_G || j == ISP32_ISP_AWB1_GAIN_RB)
+				reg = isp->sw_base_addr + j;
+			else
+				reg = reg_buf + j;
+			writel(*reg, base + j);
+		}
+
+		/* config shd_reg to base_reg */
+		for (j = 0; j < ARRAY_SIZE(backup); j++) {
+			reg = reg_buf + backup[j].base;
+			reg1 = reg_buf + backup[j].shd;
+			backup[j].val = *reg;
+			writel(*reg1, base + backup[j].base);
+		}
+
+		/* update module */
+		reg = reg_buf + DUAL_CROP_CTRL;
+		if (*reg & 0xf)
+			writel(*reg | CIF_DUAL_CROP_CFG_UPD, base + DUAL_CROP_CTRL);
+		reg = reg_buf + SELF_RESIZE_CTRL;
+		if (*reg & 0xf) {
+			if (dev->isp_ver == ISP_V32_L)
+				writel(*reg | ISP32_SCALE_FORCE_UPD, base + ISP32_SELF_SCALE_UPDATE);
+			else
+				writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + SELF_RESIZE_CTRL);
+		}
+		reg = reg_buf + MAIN_RESIZE_CTRL;
+		if (*reg & 0xf)
+			writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + MAIN_RESIZE_CTRL);
+		reg = reg_buf + ISP32_BP_RESIZE_CTRL;
+		if (*reg & 0xf)
+			writel(*reg | CIF_RSZ_CTRL_CFG_UPD, base + ISP32_BP_RESIZE_CTRL);
+
+		/* update mi and isp, base_reg will update to shd_reg */
+		writel(CIF_MI_INIT_SOFT_UPD, base + MI_WR_INIT);
+
+		/* config base_reg */
+		for (j = 0; j < ARRAY_SIZE(backup); j++)
+			writel(backup[j].val, base + backup[j].base);
+		/* base_reg = shd_reg, write is base but read is shd */
+		val = rkisp_read_reg_cache(isp, ISP_MPFBC_HEAD_PTR);
+		writel(val, base + ISP_MPFBC_HEAD_PTR);
+		val = rkisp_read_reg_cache(isp, MI_SWS_3A_WR_BASE);
+		writel(val, base + MI_SWS_3A_WR_BASE);
+	}
+
+	rkisp_params_cfgsram(&isp->params_vdev, false);
+
+	reg = reg_buf + ISP_CTRL;
+	*reg |= CIF_ISP_CTRL_ISP_ENABLE |
+		CIF_ISP_CTRL_ISP_CFG_UPD |
+		CIF_ISP_CTRL_ISP_INFORM_ENABLE;
+	writel(*reg, dev->base_addr + ISP_CTRL);
+	if (dev->unite == ISP_UNITE_TWO)
+		writel(*reg, dev->base_next_addr + ISP_CTRL);
+}
+
 static const char * const rk3562_isp_clks[] = {
 	"clk_isp_core",
 	"aclk_isp",
@@ -455,6 +647,9 @@
 	}, {
 		.clk_rate = 350,
 		.refer_data = 3072,
+	}, {
+		.clk_rate = 440,
+		.refer_data = 3840,
 	}
 };
 
@@ -636,7 +831,7 @@
 	/* record clk config and recover */
 	iccl0 = readl(base + CIF_ICCL);
 	clk_ctrl0 = readl(base + CTRL_VI_ISP_CLK_CTRL);
-	if (dev->is_unite) {
+	if (dev->unite == ISP_UNITE_TWO) {
 		iccl1 = readl(dev->base_next_addr + CIF_ICCL);
 		clk_ctrl1 = readl(dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL);
 	}
@@ -646,7 +841,7 @@
 		 * isp soft reset first to protect isp reset.
 		 */
 		writel(0xffff, base + CIF_IRCL);
-		if (dev->is_unite)
+		if (dev->unite == ISP_UNITE_TWO)
 			writel(0xffff, dev->base_next_addr + CIF_IRCL);
 		udelay(10);
 	}
@@ -669,7 +864,7 @@
 	writel(val, base + CIF_IRCL);
 	if (dev->isp_ver == ISP_V32)
 		rv1106_sdmmc_put_lock();
-	if (dev->is_unite)
+	if (dev->unite == ISP_UNITE_TWO)
 		writel(0xffff, dev->base_next_addr + CIF_IRCL);
 	udelay(10);
 
@@ -681,7 +876,7 @@
 
 	writel(iccl0, base + CIF_ICCL);
 	writel(clk_ctrl0, base + CTRL_VI_ISP_CLK_CTRL);
-	if (dev->is_unite) {
+	if (dev->unite == ISP_UNITE_TWO) {
 		writel(iccl1, dev->base_next_addr + CIF_ICCL);
 		writel(clk_ctrl1, dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL);
 	}
@@ -722,7 +917,7 @@
 	writel(val, dev->base_addr + CIF_ICCL);
 	if (dev->isp_ver == ISP_V32)
 		rv1106_sdmmc_put_lock();
-	if (dev->is_unite)
+	if (dev->unite == ISP_UNITE_TWO)
 		writel(val, dev->base_next_addr + CIF_ICCL);
 
 	if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) {
@@ -752,7 +947,7 @@
 		writel(val, dev->base_addr + CTRL_VI_ISP_CLK_CTRL);
 		if (dev->isp_ver == ISP_V32)
 			rv1106_sdmmc_put_lock();
-		if (dev->is_unite)
+		if (dev->unite == ISP_UNITE_TWO)
 			writel(val, dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL);
 	}
 }
@@ -776,7 +971,6 @@
 static int enable_sys_clk(struct rkisp_hw_dev *dev)
 {
 	int i, ret = -EINVAL;
-	unsigned long rate;
 
 	for (i = 0; i < dev->num_clks; i++) {
 		if (!IS_ERR(dev->clks[i])) {
@@ -786,10 +980,6 @@
 		}
 	}
 
-	rate = dev->clk_rate_tbl[0].clk_rate * 1000000UL;
-	rkisp_set_clk_rate(dev->clks[0], rate);
-	if (dev->is_unite)
-		rkisp_set_clk_rate(dev->clks[5], rate);
 	rkisp_soft_reset(dev, false);
 	isp_config_clk(dev, true);
 	return 0;
@@ -846,33 +1036,29 @@
 	struct device *dev = &pdev->dev;
 	struct rkisp_hw_dev *hw_dev;
 	struct resource *res;
-	int i, ret;
+	int i, ret, mult = 1;
 	bool is_mem_reserved = true;
+	u32 clk_rate = 0;
 
 	match = of_match_node(rkisp_hw_of_match, node);
 	if (IS_ERR(match))
 		return PTR_ERR(match);
+	match_data = match->data;
 
 	hw_dev = devm_kzalloc(dev, sizeof(*hw_dev), GFP_KERNEL);
 	if (!hw_dev)
 		return -ENOMEM;
 
-	match_data = match->data;
-	hw_dev->is_unite = match_data->unite;
+	if (match_data->unite)
+		mult = 2;
+	hw_dev->sw_reg = devm_kzalloc(dev, RKISP_ISP_SW_REG_SIZE * mult, GFP_KERNEL);
+	if (!hw_dev->sw_reg)
+		return -ENOMEM;
 	dev_set_drvdata(dev, hw_dev);
 	hw_dev->dev = dev;
 	hw_dev->is_thunderboot = IS_ENABLED(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP);
 	dev_info(dev, "is_thunderboot: %d\n", hw_dev->is_thunderboot);
-	memset(&hw_dev->max_in, 0, sizeof(hw_dev->max_in));
-	if (!of_property_read_u32_array(node, "max-input", &hw_dev->max_in.w, 3)) {
-		hw_dev->max_in.is_fix = true;
-		if (hw_dev->is_unite) {
-			hw_dev->max_in.w /= 2;
-			hw_dev->max_in.w += RKMOUDLE_UNITE_EXTEND_PIXEL;
-		}
-	}
-	dev_info(dev, "max input:%dx%d@%dfps\n",
-		 hw_dev->max_in.w, hw_dev->max_in.h, hw_dev->max_in.fps);
+
 	hw_dev->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
 	if (IS_ERR(hw_dev->grf))
 		dev_warn(dev, "Missing rockchip,grf property\n");
@@ -919,6 +1105,27 @@
 		}
 	}
 
+	hw_dev->isp_ver = match_data->isp_ver;
+	if (match_data->unite) {
+		hw_dev->unite = ISP_UNITE_TWO;
+	} else if (device_property_read_bool(dev, "rockchip,unite-en")) {
+		hw_dev->unite = ISP_UNITE_ONE;
+		hw_dev->base_next_addr = hw_dev->base_addr;
+	} else {
+		hw_dev->unite = ISP_UNITE_NONE;
+	}
+
+	memset(&hw_dev->max_in, 0, sizeof(hw_dev->max_in));
+	if (!of_property_read_u32_array(node, "max-input", &hw_dev->max_in.w, 3)) {
+		hw_dev->max_in.is_fix = true;
+		if (hw_dev->unite) {
+			hw_dev->max_in.w /= 2;
+			hw_dev->max_in.w += RKMOUDLE_UNITE_EXTEND_PIXEL;
+		}
+	}
+	dev_info(dev, "max input:%dx%d@%dfps\n",
+		 hw_dev->max_in.w, hw_dev->max_in.h, hw_dev->max_in.fps);
+
 	rkisp_monitor = device_property_read_bool(dev, "rockchip,restart-monitor-en");
 	hw_dev->mipi_irq = -1;
 
@@ -941,6 +1148,11 @@
 	hw_dev->clk_rate_tbl = match_data->clk_rate_tbl;
 	hw_dev->num_clk_rate_tbl = match_data->num_clk_rate_tbl;
 
+	hw_dev->is_assigned_clk = false;
+	ret = of_property_read_u32(node, "assigned-clock-rates", &clk_rate);
+	if (!ret && clk_rate)
+		hw_dev->is_assigned_clk = true;
+
 	hw_dev->reset = devm_reset_control_array_get(dev, false, false);
 	if (IS_ERR(hw_dev->reset)) {
 		dev_dbg(dev, "failed to get reset\n");
@@ -959,10 +1171,8 @@
 	hw_dev->dev_link_num = 0;
 	hw_dev->cur_dev_id = 0;
 	hw_dev->mipi_dev_id = 0;
-	hw_dev->pre_dev_id = 0;
+	hw_dev->pre_dev_id = -1;
 	hw_dev->is_multi_overflow = false;
-	hw_dev->isp_ver = match_data->isp_ver;
-	hw_dev->is_unite = match_data->unite;
 	mutex_init(&hw_dev->dev_lock);
 	spin_lock_init(&hw_dev->rdbk_lock);
 	atomic_set(&hw_dev->refcnt, 0);
@@ -1012,7 +1222,7 @@
 	hw_dev->is_shutdown = true;
 	if (pm_runtime_active(&pdev->dev)) {
 		writel(0xffff, hw_dev->base_addr + CIF_IRCL);
-		if (hw_dev->is_unite)
+		if (hw_dev->unite == ISP_UNITE_TWO)
 			writel(0xffff, hw_dev->base_next_addr + CIF_IRCL);
 	}
 	dev_info(&pdev->dev, "%s\n", __func__);
@@ -1021,11 +1231,23 @@
 static int __maybe_unused rkisp_runtime_suspend(struct device *dev)
 {
 	struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
+	int i;
 
-	hw_dev->dev_link_num = 0;
-	hw_dev->is_single = true;
-	hw_dev->is_multi_overflow = false;
-	hw_dev->is_frm_buf = false;
+	hw_dev->is_idle = true;
+	if (dev->power.runtime_status) {
+		hw_dev->dev_link_num = 0;
+		hw_dev->is_single = true;
+		hw_dev->is_multi_overflow = false;
+		hw_dev->is_frm_buf = false;
+	} else {
+		/* system suspend */
+		for (i = 0; i < hw_dev->dev_num; i++) {
+			if (hw_dev->isp_size[i].is_on) {
+				rkisp_hw_reg_save(hw_dev);
+				break;
+			}
+		}
+	}
 	disable_sys_clk(hw_dev);
 	return pinctrl_pm_select_sleep_state(dev);
 }
@@ -1035,7 +1257,6 @@
 	struct rkisp_device *isp;
 	u32 w, h, i;
 
-	memset(hw_dev->isp_size, 0, sizeof(hw_dev->isp_size));
 	if (!hw_dev->max_in.is_fix) {
 		hw_dev->max_in.w = 0;
 		hw_dev->max_in.h = 0;
@@ -1052,7 +1273,7 @@
 			hw_dev->is_single = false;
 		w = isp->isp_sdev.in_crop.width;
 		h = isp->isp_sdev.in_crop.height;
-		if (hw_dev->is_unite)
+		if (hw_dev->unite)
 			w = w / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
 		hw_dev->isp_size[i].w = w;
 		hw_dev->isp_size[i].h = h;
@@ -1064,6 +1285,8 @@
 				hw_dev->max_in.h = h;
 		}
 	}
+	if (hw_dev->unite == ISP_UNITE_ONE)
+		hw_dev->is_single = false;
 	for (i = 0; i < hw_dev->dev_num; i++) {
 		isp = hw_dev->isp[i];
 		if (!isp || (isp && !isp->is_hw_link))
@@ -1077,7 +1300,7 @@
 	struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
 	void __iomem *base = hw_dev->base_addr;
 	struct rkisp_device *isp;
-	int mult = hw_dev->is_unite ? 2 : 1;
+	int mult = hw_dev->unite ? 2 : 1;
 	int ret, i;
 	void *buf;
 
@@ -1086,28 +1309,45 @@
 		return ret;
 
 	enable_sys_clk(hw_dev);
-	for (i = 0; i < hw_dev->dev_num; i++) {
-		isp = hw_dev->isp[i];
-		if (!isp || !isp->sw_base_addr)
-			continue;
-		buf = isp->sw_base_addr;
-		memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult);
-		memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE);
-		if (hw_dev->is_unite) {
-			buf += RKISP_ISP_SW_MAX_SIZE;
-			base = hw_dev->base_next_addr;
-			memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE);
+	if (dev->power.runtime_status) {
+		if (!hw_dev->is_assigned_clk) {
+			unsigned long rate = hw_dev->clk_rate_tbl[0].clk_rate * 1000000UL;
+
+			rkisp_set_clk_rate(hw_dev->clks[0], rate);
+			if (hw_dev->unite == ISP_UNITE_TWO)
+				rkisp_set_clk_rate(hw_dev->clks[5], rate);
 		}
-		default_sw_reg_flag(hw_dev->isp[i]);
+		for (i = 0; i < hw_dev->dev_num; i++) {
+			isp = hw_dev->isp[i];
+			if (!isp || !isp->sw_base_addr)
+				continue;
+			buf = isp->sw_base_addr;
+			memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult);
+			memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE);
+			if (hw_dev->unite) {
+				buf += RKISP_ISP_SW_MAX_SIZE;
+				base = hw_dev->base_next_addr;
+				memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE);
+			}
+			default_sw_reg_flag(hw_dev->isp[i]);
+		}
+		rkisp_hw_enum_isp_size(hw_dev);
+		hw_dev->monitor.is_en = rkisp_monitor;
+	} else {
+		/* system resume */
+		for (i = 0; i < hw_dev->dev_num; i++) {
+			if (hw_dev->isp_size[i].is_on) {
+				rkisp_hw_reg_restore(hw_dev);
+				break;
+			}
+		}
 	}
-	rkisp_hw_enum_isp_size(hw_dev);
-	hw_dev->monitor.is_en = rkisp_monitor;
 	return 0;
 }
 
 static const struct dev_pm_ops rkisp_hw_pm_ops = {
-	SET_RUNTIME_PM_OPS(rkisp_runtime_suspend,
-			   rkisp_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(rkisp_runtime_suspend, rkisp_runtime_resume, NULL)
 };
 
 static struct platform_driver rkisp_hw_drv = {

--
Gitblit v1.6.2