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/hw.c | 951 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 743 insertions(+), 208 deletions(-) diff --git a/kernel/drivers/media/platform/rockchip/isp/hw.c b/kernel/drivers/media/platform/rockchip/isp/hw.c index 60aa895..5b0f291 100644 --- a/kernel/drivers/media/platform/rockchip/isp/hw.c +++ b/kernel/drivers/media/platform/rockchip/isp/hw.c @@ -9,13 +9,14 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_graph.h> #include <linux/of_platform.h> #include <linux/of_reserved_mem.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <media/videobuf2-dma-contig.h> +#include <media/videobuf2-cma-sg.h> #include <media/videobuf2-dma-sg.h> #include <soc/rockchip/rockchip_iommu.h> @@ -33,6 +34,12 @@ * | * rkisp_hw */ + +struct backup_reg { + const u32 base; + const u32 shd; + u32 val; +}; struct isp_irqs_data { const char *name; @@ -72,6 +79,38 @@ ISP_RAWHIST_BIG3_BASE, ISP_YUVAE_CTRL, ISP_RAWAF_CTRL, ISP21_RAWAWB_CTRL, }; + u32 v30_reg[] = { + ISP3X_VI_ISP_PATH, ISP3X_IMG_EFF_CTRL, ISP3X_CMSK_CTRL0, + ISP3X_CCM_CTRL, ISP3X_CPROC_CTRL, ISP3X_DUAL_CROP_CTRL, + ISP3X_GAMMA_OUT_CTRL, ISP3X_SELF_RESIZE_CTRL, ISP3X_MAIN_RESIZE_CTRL, + ISP3X_LSC_CTRL, ISP3X_DEBAYER_CONTROL, ISP3X_CAC_CTRL, + ISP3X_YNR_GLOBAL_CTRL, ISP3X_CNR_CTRL, ISP3X_SHARP_EN, + ISP3X_BAY3D_CTRL, ISP3X_GIC_CONTROL, ISP3X_BLS_CTRL, + ISP3X_DPCC0_MODE, ISP3X_DPCC1_MODE, ISP3X_DPCC2_MODE, + ISP3X_HDRMGE_CTRL, ISP3X_DRC_CTRL0, ISP3X_BAYNR_CTRL, + ISP3X_LDCH_STS, ISP3X_DHAZ_CTRL, ISP3X_3DLUT_CTRL, + ISP3X_GAIN_CTRL, ISP3X_RAWAE_LITE_CTRL, ISP3X_RAWAE_BIG1_BASE, + ISP3X_RAWAE_BIG2_BASE, ISP3X_RAWAE_BIG3_BASE, ISP3X_RAWHIST_LITE_CTRL, + ISP3X_RAWHIST_BIG1_BASE, ISP3X_RAWHIST_BIG2_BASE, ISP3X_RAWHIST_BIG3_BASE, + ISP3X_RAWAF_CTRL, ISP3X_RAWAWB_CTRL, + }; + u32 v32_reg[] = { + ISP3X_VI_ISP_PATH, ISP3X_IMG_EFF_CTRL, ISP3X_CMSK_CTRL0, + ISP3X_CCM_CTRL, ISP3X_CPROC_CTRL, ISP3X_DUAL_CROP_CTRL, + ISP3X_GAMMA_OUT_CTRL, ISP3X_SELF_RESIZE_CTRL, ISP3X_MAIN_RESIZE_CTRL, + ISP32_BP_RESIZE_BASE, ISP3X_MI_BP_WR_CTRL, ISP32_MI_MPDS_WR_CTRL, + ISP32_MI_BPDS_WR_CTRL, ISP32_MI_WR_WRAP_CTRL, + ISP3X_LSC_CTRL, ISP3X_DEBAYER_CONTROL, ISP3X_CAC_CTRL, + ISP3X_YNR_GLOBAL_CTRL, ISP3X_CNR_CTRL, ISP3X_SHARP_EN, + ISP3X_BAY3D_CTRL, ISP3X_GIC_CONTROL, ISP3X_BLS_CTRL, + ISP3X_DPCC0_MODE, ISP3X_DPCC1_MODE, ISP3X_DPCC2_MODE, + ISP3X_HDRMGE_CTRL, ISP3X_DRC_CTRL0, ISP3X_BAYNR_CTRL, + ISP3X_LDCH_STS, ISP3X_DHAZ_CTRL, ISP3X_3DLUT_CTRL, + ISP3X_GAIN_CTRL, ISP3X_RAWAE_LITE_CTRL, ISP3X_RAWAE_BIG1_BASE, + ISP3X_RAWAE_BIG2_BASE, ISP3X_RAWAE_BIG3_BASE, ISP3X_RAWHIST_LITE_CTRL, + ISP3X_RAWHIST_BIG1_BASE, ISP3X_RAWHIST_BIG2_BASE, ISP3X_RAWHIST_BIG3_BASE, + ISP3X_RAWAF_CTRL, ISP3X_RAWAWB_CTRL, + }; u32 i, *flag, *reg, size; switch (dev->isp_ver) { @@ -83,6 +122,15 @@ reg = v21_reg; size = ARRAY_SIZE(v21_reg); break; + case ISP_V30: + reg = v30_reg; + size = ARRAY_SIZE(v30_reg); + break; + case ISP_V32: + case ISP_V32_L: + reg = v32_reg; + size = ARRAY_SIZE(v32_reg); + break; default: return; } @@ -90,6 +138,10 @@ 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->unite) { + flag += RKISP_ISP_SW_MAX_SIZE / 4; + *flag = SW_REG_CACHE; + } } } @@ -98,39 +150,55 @@ 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->unite != ISP_UNITE_TWO ? + hw_dev->base_addr : hw_dev->base_next_addr; + ktime_t t = 0; + s64 us; if (hw_dev->is_thunderboot) return IRQ_HANDLED; + if (rkisp_irq_dbg) + t = ktime_get(); + if (hw_dev->isp_ver == ISP_V13 || hw_dev->isp_ver == ISP_V12) { u32 err1, err2, err3; - err1 = readl(hw_dev->base_addr + CIF_ISP_CSI0_ERR1); - err2 = readl(hw_dev->base_addr + CIF_ISP_CSI0_ERR2); - err3 = readl(hw_dev->base_addr + CIF_ISP_CSI0_ERR3); + err1 = readl(base + CIF_ISP_CSI0_ERR1); + err2 = readl(base + CIF_ISP_CSI0_ERR2); + err3 = readl(base + CIF_ISP_CSI0_ERR3); if (err1 || err2 || err3) rkisp_mipi_v13_isr(err1, err2, err3, isp); - } else if (hw_dev->isp_ver == ISP_V20 || hw_dev->isp_ver == ISP_V21) { + } else if (hw_dev->isp_ver >= ISP_V20) { u32 phy, packet, overflow, state; - state = readl(hw_dev->base_addr + CSI2RX_ERR_STAT); - phy = readl(hw_dev->base_addr + CSI2RX_ERR_PHY); - packet = readl(hw_dev->base_addr + CSI2RX_ERR_PACKET); - overflow = readl(hw_dev->base_addr + CSI2RX_ERR_OVERFLOW); + state = readl(base + CSI2RX_ERR_STAT); + phy = readl(base + CSI2RX_ERR_PHY); + packet = readl(base + CSI2RX_ERR_PACKET); + overflow = readl(base + CSI2RX_ERR_OVERFLOW); if (phy | packet | overflow | state) { if (hw_dev->isp_ver == ISP_V20) rkisp_mipi_v20_isr(phy, packet, overflow, state, isp); - else + else if (hw_dev->isp_ver == ISP_V21) rkisp_mipi_v21_isr(phy, packet, overflow, state, isp); + else if (hw_dev->isp_ver == ISP_V30) + rkisp_mipi_v30_isr(phy, packet, overflow, state, isp); + else + rkisp_mipi_v32_isr(phy, packet, overflow, state, isp); } } else { - u32 mis_val = readl(hw_dev->base_addr + CIF_MIPI_MIS); + u32 mis_val = readl(base + CIF_MIPI_MIS); if (mis_val) rkisp_mipi_isr(mis_val, isp); } + if (rkisp_irq_dbg) { + us = ktime_us_delta(ktime_get(), t); + v4l2_dbg(0, rkisp_debug, &isp->v4l2_dev, + "%s %lldus\n", __func__, us); + } return IRQ_HANDLED; } @@ -139,13 +207,20 @@ 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->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; + ktime_t t = 0; + s64 us; if (hw_dev->is_thunderboot) return IRQ_HANDLED; - mis_val = readl(hw_dev->base_addr + CIF_MI_MIS); + if (rkisp_irq_dbg) + t = ktime_get(); + + mis_val = readl(base + CIF_MI_MIS); if (mis_val) { if (mis_val & ~tx_isr) rkisp_mi_isr(mis_val & ~tx_isr, isp); @@ -153,6 +228,12 @@ isp = hw_dev->isp[hw_dev->mipi_dev_id]; rkisp_mi_isr(mis_val & tx_isr, isp); } + } + + if (rkisp_irq_dbg) { + us = ktime_us_delta(ktime_get(), t); + v4l2_dbg(0, rkisp_debug, &isp->v4l2_dev, + "%s:0x%x %lldus\n", __func__, mis_val, us); } return IRQ_HANDLED; } @@ -162,17 +243,29 @@ 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->unite != ISP_UNITE_TWO ? + hw_dev->base_addr : hw_dev->base_next_addr; unsigned int mis_val, mis_3a = 0; + ktime_t t = 0; + s64 us; if (hw_dev->is_thunderboot) return IRQ_HANDLED; - mis_val = readl(hw_dev->base_addr + CIF_ISP_MIS); - if (hw_dev->isp_ver == ISP_V20 || hw_dev->isp_ver == ISP_V21) - mis_3a = readl(hw_dev->base_addr + ISP_ISP3A_MIS); + if (rkisp_irq_dbg) + t = ktime_get(); + + mis_val = readl(base + CIF_ISP_MIS); + if (hw_dev->isp_ver >= ISP_V20) + mis_3a = readl(base + ISP_ISP3A_MIS); if (mis_val || mis_3a) rkisp_isp_isr(mis_val, mis_3a, isp); + if (rkisp_irq_dbg) { + us = ktime_us_delta(ktime_get(), t); + v4l2_dbg(0, rkisp_debug, &isp->v4l2_dev, + "%s:0x%x %lldus\n", __func__, mis_val, us); + } return IRQ_HANDLED; } @@ -184,7 +277,7 @@ unsigned int mis_val, mis_3a = 0; mis_val = readl(hw_dev->base_addr + CIF_ISP_MIS); - if (hw_dev->isp_ver == ISP_V20 || hw_dev->isp_ver == ISP_V21) + if (hw_dev->isp_ver >= ISP_V20) mis_3a = readl(hw_dev->base_addr + ISP_ISP3A_MIS); if (mis_val || mis_3a) rkisp_isp_isr(mis_val, mis_3a, isp); @@ -261,42 +354,196 @@ return 0; } -static const char * const rk1808_isp_clks[] = { - "clk_isp", - "aclk_isp", - "hclk_isp", - "pclk_isp", -}; +void rkisp_hw_reg_save(struct rkisp_hw_dev *dev) +{ + void *buf = dev->sw_reg; -static const char * const rk3288_isp_clks[] = { - "clk_isp", - "aclk_isp", - "hclk_isp", - "pclk_isp_in", - "sclk_isp_jpe", -}; + 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); + } +} -static const char * const rk3326_isp_clks[] = { - "clk_isp", - "aclk_isp", - "hclk_isp", - "pclk_isp", -}; +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, + } + }; -static const char * const rk3368_isp_clks[] = { - "clk_isp", - "aclk_isp", - "hclk_isp", - "pclk_isp", -}; + for (i = 0; i <= !!dev->unite; i++) { + if (dev->unite != ISP_UNITE_TWO && i) + break; -static const char * const rk3399_isp_clks[] = { - "clk_isp", + 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", "hclk_isp", - "aclk_isp_wrap", - "hclk_isp_wrap", - "pclk_isp_wrap" }; static const char * const rk3568_isp_clks[] = { @@ -305,35 +552,54 @@ "hclk_isp", }; +static const char * const rk3588_isp_clks[] = { + "clk_isp_core", + "aclk_isp", + "hclk_isp", + "clk_isp_core_marvin", + "clk_isp_core_vicap", +}; + +static const char * const rk3588_isp_unite_clks[] = { + "clk_isp_core0", + "aclk_isp0", + "hclk_isp0", + "clk_isp_core_marvin0", + "clk_isp_core_vicap0", + "clk_isp_core1", + "aclk_isp1", + "hclk_isp1", + "clk_isp_core_marvin1", + "clk_isp_core_vicap1", +}; + +static const char * const rv1106_isp_clks[] = { + "clk_isp_core", + "aclk_isp", + "hclk_isp", + "clk_isp_core_vicap", +}; + static const char * const rv1126_isp_clks[] = { "clk_isp", "aclk_isp", "hclk_isp", }; -/* isp clock adjustment table (MHz) */ -static const struct isp_clk_info rk1808_isp_clk_rate[] = { - {300, }, {400, }, {500, }, {600, } -}; - -/* isp clock adjustment table (MHz) */ -static const struct isp_clk_info rk3288_isp_clk_rate[] = { - {150, }, {384, }, {500, }, {594, } -}; - -/* isp clock adjustment table (MHz) */ -static const struct isp_clk_info rk3326_isp_clk_rate[] = { - {300, }, {347, }, {400, }, {520, }, {600, } -}; - -/* isp clock adjustment table (MHz) */ -static const struct isp_clk_info rk3368_isp_clk_rate[] = { - {300, }, {400, }, {600, } -}; - -/* isp clock adjustment table (MHz) */ -static const struct isp_clk_info rk3399_isp_clk_rate[] = { - {300, }, {400, }, {600, } +static const struct isp_clk_info rk3562_isp_clk_rate[] = { + { + .clk_rate = 300, + .refer_data = 1920, //width + }, { + .clk_rate = 400, + .refer_data = 2688, + }, { + .clk_rate = 500, + .refer_data = 3072, + }, { + .clk_rate = 600, + .refer_data = 3840, + } }; static const struct isp_clk_info rk3568_isp_clk_rate[] = { @@ -348,6 +614,41 @@ .refer_data = 3072, }, { .clk_rate = 600, + .refer_data = 3840, + } +}; + +static const struct isp_clk_info rk3588_isp_clk_rate[] = { + { + .clk_rate = 300, + .refer_data = 1920, //width + }, { + .clk_rate = 400, + .refer_data = 2688, + }, { + .clk_rate = 500, + .refer_data = 3072, + }, { + .clk_rate = 600, + .refer_data = 3840, + }, { + .clk_rate = 702, + .refer_data = 4672, + } +}; + +static const struct isp_clk_info rv1106_isp_clk_rate[] = { + { + .clk_rate = 200, + .refer_data = 1920, //width + }, { + .clk_rate = 200, + .refer_data = 2688, + }, { + .clk_rate = 350, + .refer_data = 3072, + }, { + .clk_rate = 440, .refer_data = 3840, } }; @@ -371,31 +672,25 @@ } }; -static struct isp_irqs_data rk1808_isp_irqs[] = { +static struct isp_irqs_data rk3562_isp_irqs[] = { {"isp_irq", isp_irq_hdl}, {"mi_irq", mi_irq_hdl}, {"mipi_irq", mipi_irq_hdl} -}; - -static struct isp_irqs_data rk3288_isp_irqs[] = { - {"isp_irq", irq_handler} -}; - -static struct isp_irqs_data rk3326_isp_irqs[] = { - {"isp_irq", isp_irq_hdl}, - {"mi_irq", mi_irq_hdl}, - {"mipi_irq", mipi_irq_hdl} -}; - -static struct isp_irqs_data rk3368_isp_irqs[] = { - {"isp_irq", irq_handler} -}; - -static struct isp_irqs_data rk3399_isp_irqs[] = { - {"isp_irq", irq_handler} }; static struct isp_irqs_data rk3568_isp_irqs[] = { + {"isp_irq", isp_irq_hdl}, + {"mi_irq", mi_irq_hdl}, + {"mipi_irq", mipi_irq_hdl} +}; + +static struct isp_irqs_data rk3588_isp_irqs[] = { + {"isp_irq", isp_irq_hdl}, + {"mi_irq", mi_irq_hdl}, + {"mipi_irq", mipi_irq_hdl} +}; + +static struct isp_irqs_data rv1106_isp_irqs[] = { {"isp_irq", isp_irq_hdl}, {"mi_irq", mi_irq_hdl}, {"mipi_irq", mipi_irq_hdl} @@ -407,6 +702,17 @@ {"mipi_irq", mipi_irq_hdl} }; +static const struct isp_match_data rv1106_isp_match_data = { + .clks = rv1106_isp_clks, + .num_clks = ARRAY_SIZE(rv1106_isp_clks), + .isp_ver = ISP_V32, + .clk_rate_tbl = rv1106_isp_clk_rate, + .num_clk_rate_tbl = ARRAY_SIZE(rv1106_isp_clk_rate), + .irqs = rv1106_isp_irqs, + .num_irqs = ARRAY_SIZE(rv1106_isp_irqs), + .unite = false, +}; + static const struct isp_match_data rv1126_isp_match_data = { .clks = rv1126_isp_clks, .num_clks = ARRAY_SIZE(rv1126_isp_clks), @@ -414,57 +720,19 @@ .clk_rate_tbl = rv1126_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rv1126_isp_clk_rate), .irqs = rv1126_isp_irqs, - .num_irqs = ARRAY_SIZE(rv1126_isp_irqs) + .num_irqs = ARRAY_SIZE(rv1126_isp_irqs), + .unite = false, }; -static const struct isp_match_data rk1808_isp_match_data = { - .clks = rk1808_isp_clks, - .num_clks = ARRAY_SIZE(rk1808_isp_clks), - .isp_ver = ISP_V13, - .clk_rate_tbl = rk1808_isp_clk_rate, - .num_clk_rate_tbl = ARRAY_SIZE(rk1808_isp_clk_rate), - .irqs = rk1808_isp_irqs, - .num_irqs = ARRAY_SIZE(rk1808_isp_irqs) -}; - -static const struct isp_match_data rk3288_isp_match_data = { - .clks = rk3288_isp_clks, - .num_clks = ARRAY_SIZE(rk3288_isp_clks), - .isp_ver = ISP_V10, - .clk_rate_tbl = rk3288_isp_clk_rate, - .num_clk_rate_tbl = ARRAY_SIZE(rk3288_isp_clk_rate), - .irqs = rk3288_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3288_isp_irqs) -}; - -static const struct isp_match_data rk3326_isp_match_data = { - .clks = rk3326_isp_clks, - .num_clks = ARRAY_SIZE(rk3326_isp_clks), - .isp_ver = ISP_V12, - .clk_rate_tbl = rk3326_isp_clk_rate, - .num_clk_rate_tbl = ARRAY_SIZE(rk3326_isp_clk_rate), - .irqs = rk3326_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3326_isp_irqs) -}; - -static const struct isp_match_data rk3368_isp_match_data = { - .clks = rk3368_isp_clks, - .num_clks = ARRAY_SIZE(rk3368_isp_clks), - .isp_ver = ISP_V10_1, - .clk_rate_tbl = rk3368_isp_clk_rate, - .num_clk_rate_tbl = ARRAY_SIZE(rk3368_isp_clk_rate), - .irqs = rk3368_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3368_isp_irqs) -}; - -static const struct isp_match_data rk3399_isp_match_data = { - .clks = rk3399_isp_clks, - .num_clks = ARRAY_SIZE(rk3399_isp_clks), - .isp_ver = ISP_V10, - .clk_rate_tbl = rk3399_isp_clk_rate, - .num_clk_rate_tbl = ARRAY_SIZE(rk3399_isp_clk_rate), - .irqs = rk3399_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3399_isp_irqs) +static const struct isp_match_data rk3562_isp_match_data = { + .clks = rk3562_isp_clks, + .num_clks = ARRAY_SIZE(rk3562_isp_clks), + .isp_ver = ISP_V32_L, + .clk_rate_tbl = rk3562_isp_clk_rate, + .num_clk_rate_tbl = ARRAY_SIZE(rk3562_isp_clk_rate), + .irqs = rk3562_isp_irqs, + .num_irqs = ARRAY_SIZE(rk3562_isp_irqs), + .unite = false, }; static const struct isp_match_data rk3568_isp_match_data = { @@ -474,32 +742,66 @@ .clk_rate_tbl = rk3568_isp_clk_rate, .num_clk_rate_tbl = ARRAY_SIZE(rk3568_isp_clk_rate), .irqs = rk3568_isp_irqs, - .num_irqs = ARRAY_SIZE(rk3568_isp_irqs) + .num_irqs = ARRAY_SIZE(rk3568_isp_irqs), + .unite = false, +}; + +static const struct isp_match_data rk3588_isp_match_data = { + .clks = rk3588_isp_clks, + .num_clks = ARRAY_SIZE(rk3588_isp_clks), + .isp_ver = ISP_V30, + .clk_rate_tbl = rk3588_isp_clk_rate, + .num_clk_rate_tbl = ARRAY_SIZE(rk3588_isp_clk_rate), + .irqs = rk3588_isp_irqs, + .num_irqs = ARRAY_SIZE(rk3588_isp_irqs), + .unite = false, +}; + +static const struct isp_match_data rk3588_isp_unite_match_data = { + .clks = rk3588_isp_unite_clks, + .num_clks = ARRAY_SIZE(rk3588_isp_unite_clks), + .isp_ver = ISP_V30, + .clk_rate_tbl = rk3588_isp_clk_rate, + .num_clk_rate_tbl = ARRAY_SIZE(rk3588_isp_clk_rate), + .irqs = rk3588_isp_irqs, + .num_irqs = ARRAY_SIZE(rk3588_isp_irqs), + .unite = true, }; static const struct of_device_id rkisp_hw_of_match[] = { +#ifdef CONFIG_CPU_RK3562 { - .compatible = "rockchip,rk1808-rkisp1", - .data = &rk1808_isp_match_data, - }, { - .compatible = "rockchip,rk3288-rkisp1", - .data = &rk3288_isp_match_data, - }, { - .compatible = "rockchip,rk3326-rkisp1", - .data = &rk3326_isp_match_data, - }, { - .compatible = "rockchip,rk3368-rkisp1", - .data = &rk3368_isp_match_data, - }, { - .compatible = "rockchip,rk3399-rkisp1", - .data = &rk3399_isp_match_data, - }, { + .compatible = "rockchip,rk3562-rkisp", + .data = &rk3562_isp_match_data, + }, +#endif +#ifdef CONFIG_CPU_RK3568 + { .compatible = "rockchip,rk3568-rkisp", .data = &rk3568_isp_match_data, + }, +#endif +#ifdef CONFIG_CPU_RK3588 + { + .compatible = "rockchip,rk3588-rkisp", + .data = &rk3588_isp_match_data, }, { + .compatible = "rockchip,rk3588-rkisp-unite", + .data = &rk3588_isp_unite_match_data, + }, +#endif +#ifdef CONFIG_CPU_RV1106 + { + .compatible = "rockchip,rv1106-rkisp", + .data = &rv1106_isp_match_data, + }, +#endif +#ifdef CONFIG_CPU_RV1126 + { .compatible = "rockchip,rv1126-rkisp", .data = &rv1126_isp_match_data, }, +#endif {}, }; @@ -524,12 +826,23 @@ void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure) { void __iomem *base = dev->base_addr; + u32 val, iccl0, iccl1, clk_ctrl0, clk_ctrl1; + + /* record clk config and recover */ + iccl0 = readl(base + CIF_ICCL); + clk_ctrl0 = readl(base + CTRL_VI_ISP_CLK_CTRL); + 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); + } if (is_secure) { /* if isp working, cru reset isn't secure. * isp soft reset first to protect isp reset. */ writel(0xffff, base + CIF_IRCL); + if (dev->unite == ISP_UNITE_TWO) + writel(0xffff, dev->base_next_addr + CIF_IRCL); udelay(10); } @@ -543,13 +856,47 @@ /* reset for Dehaze */ if (dev->isp_ver == ISP_V20) writel(CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601, base + CIF_ISP_CTRL); - writel(0xffff, base + CIF_IRCL); + val = 0xffff; + if (dev->isp_ver == ISP_V32) { + val = 0x3fffffff; + rv1106_sdmmc_get_lock(); + } + writel(val, base + CIF_IRCL); + if (dev->isp_ver == ISP_V32) + rv1106_sdmmc_put_lock(); + if (dev->unite == ISP_UNITE_TWO) + writel(0xffff, dev->base_next_addr + CIF_IRCL); udelay(10); /* refresh iommu after reset */ if (dev->is_mmu) { rockchip_iommu_disable(dev->dev); rockchip_iommu_enable(dev->dev); + } + + writel(iccl0, base + CIF_ICCL); + writel(clk_ctrl0, base + CTRL_VI_ISP_CLK_CTRL); + 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); + } + + /* default config */ + if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) { + /* disable csi_rx interrupt */ + writel(0, dev->base_addr + CIF_ISP_CSI0_CTRL0); + writel(0, dev->base_addr + CIF_ISP_CSI0_MASK1); + writel(0, dev->base_addr + CIF_ISP_CSI0_MASK2); + writel(0, dev->base_addr + CIF_ISP_CSI0_MASK3); + } else if (dev->isp_ver == ISP_V32) { + /* disable down samplling default */ + writel(ISP32_DS_DS_DIS, dev->base_addr + ISP32_MI_MPDS_WR_CTRL); + writel(ISP32_DS_DS_DIS, dev->base_addr + ISP32_MI_BPDS_WR_CTRL); + + writel(0, dev->base_addr + ISP32_BLS_ISP_OB_PREDGAIN); + writel(0x37, dev->base_addr + ISP32_MI_WR_WRAP_CTRL); + } else if (dev->isp_ver == ISP_V32_L) { + writel(0, dev->base_addr + ISP32_BLS_ISP_OB_PREDGAIN); } } @@ -560,10 +907,18 @@ CIF_ICCL_SRSZ_CLK | CIF_ICCL_JPEG_CLK | CIF_ICCL_MI_CLK | CIF_ICCL_IE_CLK | CIF_ICCL_MIPI_CLK | CIF_ICCL_DCROP_CLK; - if (dev->isp_ver == ISP_V20 && on) + if ((dev->isp_ver == ISP_V20 || dev->isp_ver >= ISP_V30) && on) val |= ICCL_MPFBC_CLK; - + if (dev->isp_ver >= ISP_V32) { + val |= ISP32_BRSZ_CLK_ENABLE | BIT(0) | BIT(16); + if (dev->isp_ver == ISP_V32) + rv1106_sdmmc_get_lock(); + } writel(val, dev->base_addr + CIF_ICCL); + if (dev->isp_ver == ISP_V32) + rv1106_sdmmc_put_lock(); + 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) { val = !on ? 0 : @@ -573,7 +928,7 @@ CIF_CLK_CTRL_CP | CIF_CLK_CTRL_IE; writel(val, dev->base_addr + CIF_VI_ISP_CLK_CTRL_V12); - } else if (dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V21) { + } else if (dev->isp_ver >= ISP_V20) { val = !on ? 0 : CLK_CTRL_MI_LDC | CLK_CTRL_MI_MP | CLK_CTRL_MI_JPEG | CLK_CTRL_MI_DP | @@ -582,9 +937,18 @@ CLK_CTRL_MI_READ | CLK_CTRL_MI_RAWRD | CLK_CTRL_ISP_RAW; - if (dev->isp_ver == ISP_V20 && on) + if (dev->isp_ver >= ISP_V30) + val = 0; + + if ((dev->isp_ver == ISP_V20 || dev->isp_ver == ISP_V30) && on) val |= CLK_CTRL_ISP_3A; + if (dev->isp_ver == ISP_V32) + rv1106_sdmmc_get_lock(); writel(val, dev->base_addr + CTRL_VI_ISP_CLK_CTRL); + if (dev->isp_ver == ISP_V32) + rv1106_sdmmc_put_lock(); + if (dev->unite == ISP_UNITE_TWO) + writel(val, dev->base_next_addr + CTRL_VI_ISP_CLK_CTRL); } } @@ -616,25 +980,52 @@ } } - rkisp_set_clk_rate(dev->clks[0], - dev->clk_rate_tbl[0].clk_rate * 1000000UL); rkisp_soft_reset(dev, false); isp_config_clk(dev, true); - - if (dev->isp_ver == ISP_V12 || dev->isp_ver == ISP_V13) { - /* disable csi_rx interrupt */ - writel(0, dev->base_addr + CIF_ISP_CSI0_CTRL0); - writel(0, dev->base_addr + CIF_ISP_CSI0_MASK1); - writel(0, dev->base_addr + CIF_ISP_CSI0_MASK2); - writel(0, dev->base_addr + CIF_ISP_CSI0_MASK3); - } - return 0; err: for (--i; i >= 0; --i) if (!IS_ERR(dev->clks[i])) clk_disable_unprepare(dev->clks[i]); return ret; +} + +static int rkisp_get_sram(struct rkisp_hw_dev *hw_dev) +{ + struct device *dev = hw_dev->dev; + struct rkisp_sram *sram = &hw_dev->sram; + struct device_node *np; + struct resource res; + int ret, size; + + sram->size = 0; + np = of_parse_phandle(dev->of_node, "rockchip,sram", 0); + if (!np) { + dev_warn(dev, "no find phandle sram\n"); + return -ENODEV; + } + + ret = of_address_to_resource(np, 0, &res); + of_node_put(np); + if (ret) { + dev_err(dev, "get sram res error\n"); + return ret; + } + size = resource_size(&res); + sram->dma_addr = dma_map_resource(dev, res.start, size, DMA_BIDIRECTIONAL, 0); + if (dma_mapping_error(dev, sram->dma_addr)) + return -ENOMEM; + sram->size = size; + dev_info(dev, "get sram size:%d\n", size); + return 0; +} + +static void rkisp_put_sram(struct rkisp_hw_dev *hw_dev) +{ + if (hw_dev->sram.size) + dma_unmap_resource(hw_dev->dev, hw_dev->sram.dma_addr, + hw_dev->sram.size, DMA_BIDIRECTIONAL, 0); + hw_dev->sram.size = 0; } static int rkisp_hw_probe(struct platform_device *pdev) @@ -645,27 +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; + 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); - hw_dev->max_in.w = 0; - hw_dev->max_in.h = 0; - hw_dev->max_in.fps = 0; - of_property_read_u32_array(node, "max-input", &hw_dev->max_in.w, 3); - 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"); @@ -689,9 +1082,51 @@ goto err; } - rkisp_monitor = device_property_read_bool(dev, "rockchip,restart-monitor-en"); + hw_dev->base_next_addr = NULL; + if (match_data->unite) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "get next resource failed\n"); + ret = -EINVAL; + goto err; + } + hw_dev->base_next_addr = devm_ioremap_resource(dev, res); + if (PTR_ERR(hw_dev->base_next_addr) == -EBUSY) { + resource_size_t offset = res->start; + resource_size_t size = resource_size(res); - match_data = match->data; + hw_dev->base_next_addr = devm_ioremap(dev, offset, size); + } + + if (IS_ERR(hw_dev->base_next_addr)) { + dev_err(dev, "ioremap next failed\n"); + ret = PTR_ERR(hw_dev->base_next_addr); + goto err; + } + } + + 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; hw_dev->pdev = pdev; @@ -702,13 +1137,21 @@ for (i = 0; i < match_data->num_clks; i++) { struct clk *clk = devm_clk_get(dev, match_data->clks[i]); - if (IS_ERR(clk)) - dev_dbg(dev, "failed to get %s\n", match_data->clks[i]); + if (IS_ERR(clk)) { + dev_err(dev, "failed to get %s\n", match_data->clks[i]); + ret = PTR_ERR(clk); + goto err; + } hw_dev->clks[i] = clk; } hw_dev->num_clks = match_data->num_clks; 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)) { @@ -722,14 +1165,17 @@ else hw_dev->is_feature_on = false; + rkisp_get_sram(hw_dev); + hw_dev->dev_num = 0; + hw_dev->dev_link_num = 0; hw_dev->cur_dev_id = 0; hw_dev->mipi_dev_id = 0; - hw_dev->isp_ver = match_data->isp_ver; + hw_dev->pre_dev_id = -1; + hw_dev->is_multi_overflow = false; mutex_init(&hw_dev->dev_lock); spin_lock_init(&hw_dev->rdbk_lock); atomic_set(&hw_dev->refcnt, 0); - atomic_set(&hw_dev->tb_ref, 0); spin_lock_init(&hw_dev->buf_lock); INIT_LIST_HEAD(&hw_dev->list); INIT_LIST_HEAD(&hw_dev->rpt_list); @@ -738,29 +1184,19 @@ hw_dev->is_single = true; hw_dev->is_mi_update = false; hw_dev->is_dma_contig = true; - hw_dev->is_dma_sg_ops = false; + hw_dev->is_dma_sg_ops = true; hw_dev->is_buf_init = false; hw_dev->is_shutdown = false; hw_dev->is_mmu = is_iommu_enable(dev); ret = of_reserved_mem_device_init(dev); if (ret) { is_mem_reserved = false; - if (!hw_dev->is_mmu) dev_info(dev, "No reserved memory region. default cma area!\n"); - else - hw_dev->is_dma_contig = false; } - if (is_mem_reserved) { - /* reserved memory using rdma_sg */ - hw_dev->mem_ops = &vb2_rdma_sg_memops; - hw_dev->is_dma_sg_ops = true; - } else if (hw_dev->is_mmu) { - hw_dev->mem_ops = &vb2_dma_sg_memops; - hw_dev->is_dma_sg_ops = true; - } else { - hw_dev->mem_ops = &vb2_dma_contig_memops; - } + if (hw_dev->is_mmu && !is_mem_reserved) + hw_dev->is_dma_contig = false; + hw_dev->mem_ops = &vb2_cma_sg_memops; pm_runtime_enable(dev); @@ -773,6 +1209,7 @@ { struct rkisp_hw_dev *hw_dev = platform_get_drvdata(pdev); + rkisp_put_sram(hw_dev); pm_runtime_disable(&pdev->dev); mutex_destroy(&hw_dev->dev_lock); return 0; @@ -783,47 +1220,134 @@ struct rkisp_hw_dev *hw_dev = platform_get_drvdata(pdev); hw_dev->is_shutdown = true; - if (pm_runtime_active(&pdev->dev)) + if (pm_runtime_active(&pdev->dev)) { writel(0xffff, hw_dev->base_addr + CIF_IRCL); + if (hw_dev->unite == ISP_UNITE_TWO) + writel(0xffff, hw_dev->base_next_addr + CIF_IRCL); + } dev_info(&pdev->dev, "%s\n", __func__); } static int __maybe_unused rkisp_runtime_suspend(struct device *dev) { struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev); + int i; + 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); +} + +void rkisp_hw_enum_isp_size(struct rkisp_hw_dev *hw_dev) +{ + struct rkisp_device *isp; + u32 w, h, i; + + if (!hw_dev->max_in.is_fix) { + hw_dev->max_in.w = 0; + hw_dev->max_in.h = 0; + } + hw_dev->dev_link_num = 0; + hw_dev->is_single = true; + hw_dev->is_multi_overflow = false; + hw_dev->is_frm_buf = false; + for (i = 0; i < hw_dev->dev_num; i++) { + isp = hw_dev->isp[i]; + if (!isp || (isp && !isp->is_hw_link)) + continue; + if (hw_dev->dev_link_num++) + hw_dev->is_single = false; + w = isp->isp_sdev.in_crop.width; + h = isp->isp_sdev.in_crop.height; + 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; + hw_dev->isp_size[i].size = w * h; + if (!hw_dev->max_in.is_fix) { + if (hw_dev->max_in.w < w) + hw_dev->max_in.w = w; + if (hw_dev->max_in.h < h) + 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)) + continue; + rkisp_params_check_bigmode(&isp->params_vdev); + } } static int __maybe_unused rkisp_runtime_resume(struct device *dev) { 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->unite ? 2 : 1; int ret, i; + void *buf; ret = pinctrl_pm_select_default_state(dev); if (ret < 0) return ret; enable_sys_clk(hw_dev); + if (dev->power.runtime_status) { + if (!hw_dev->is_assigned_clk) { + unsigned long rate = hw_dev->clk_rate_tbl[0].clk_rate * 1000000UL; - for (i = 0; i < hw_dev->dev_num; i++) { - void *buf = hw_dev->isp[i]->sw_base_addr; - - memset(buf, 0, RKISP_ISP_SW_MAX_SIZE); - memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE); - default_sw_reg_flag(hw_dev->isp[i]); + 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); + } + 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; + } + } } - hw_dev->monitor.is_en = rkisp_monitor; return 0; } static const struct dev_pm_ops rkisp_hw_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) - 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 = { @@ -851,4 +1375,15 @@ return ret; } +static void __exit rkisp_hw_drv_exit(void) +{ + platform_driver_unregister(&rkisp_plat_drv); + platform_driver_unregister(&rkisp_hw_drv); +} + +#if defined(CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP) && !defined(CONFIG_INITCALL_ASYNC) +subsys_initcall(rkisp_hw_drv_init); +#else module_init(rkisp_hw_drv_init); +#endif +module_exit(rkisp_hw_drv_exit); -- Gitblit v1.6.2