Hi, Louis: Louis Kuo <louis.kuo@xxxxxxxxxxxx> 於 2020年4月10日 週五 下午3:18寫道: > > This patch adds Mediatek's sensor interface driver. Sensor interface driver > is a MIPI-CSI2 host driver, namely, a HW camera interface controller. It > support a widely adopted, simple, high-speed protocol primarily intended for > point-to-point image and video transmission between cameras and host > devices. The mtk-isp directory will contain drivers for multiple IP blocks > found in Mediatek ISP system. It will include ISP Pass 1 driver, sensor interface > driver, DIP driver and face detection driver. > > Signed-off-by: Louis Kuo <louis.kuo@xxxxxxxxxxxx> > --- > drivers/media/platform/Makefile | 1 + > drivers/media/platform/mtk-isp/Kconfig | 18 + > drivers/media/platform/mtk-isp/Makefile | 3 + > .../media/platform/mtk-isp/seninf/Makefile | 5 + > drivers/media/platform/mtk-isp/seninf/TODO | 18 + > .../platform/mtk-isp/seninf/mtk_seninf.c | 1173 +++++++++++++ > .../platform/mtk-isp/seninf/mtk_seninf_reg.h | 1491 +++++++++++++++++ > .../mtk-isp/seninf/mtk_seninf_rx_reg.h | 1398 ++++++++++++++++ > 8 files changed, 4107 insertions(+) > create mode 100644 drivers/media/platform/mtk-isp/Kconfig > create mode 100644 drivers/media/platform/mtk-isp/Makefile > create mode 100644 drivers/media/platform/mtk-isp/seninf/Makefile > create mode 100644 drivers/media/platform/mtk-isp/seninf/TODO > create mode 100644 drivers/media/platform/mtk-isp/seninf/mtk_seninf.c > create mode 100644 drivers/media/platform/mtk-isp/seninf/mtk_seninf_reg.h > create mode 100644 drivers/media/platform/mtk-isp/seninf/mtk_seninf_rx_reg.h > [snip] > + > +static void mtk_seninf_set_dphy(struct mtk_seninf *priv, unsigned int seninf) > +{ > + void __iomem *pmipi_rx_base = priv->csi2_rx[CFG_CSI_PORT_0]; > + unsigned int port = priv->port; > + void __iomem *pmipi_rx = priv->csi2_rx[port]; > + void __iomem *pmipi_rx_conf = priv->base + 0x1000 * seninf; > + > + /* Set analog phy mode to DPHY */ > + if (is_cdphy_combo(port)) > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, RG_CSI0A_CPHY_EN, 0); > + /* 4D1C: MIPIRX_ANALOG_A_BASE = 0x00001A42 */ > + if (is_4d1c(port)) { > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L0_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L0_CKSEL, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L1_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L1_CKSEL, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L2_CKMODE_EN, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L2_CKSEL, 1); > + } else {/* MIPIRX_ANALOG_BASE = 0x102 */ > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L0_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L0_CKSEL, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L1_CKMODE_EN, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L1_CKSEL, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L2_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_DPHY_L2_CKSEL, 0); > + } > + if (is_cdphy_combo(port)) > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, RG_CSI0B_CPHY_EN, 0); > + > + /* Only 4d1c need set CSIB: MIPIRX_ANALOG_B_BASE = 0x00001242 */ > + if (is_4d1c(port)) { > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L0_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L0_CKSEL, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L1_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L1_CKSEL, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L2_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L2_CKSEL, 1); > + } else {/* MIPIRX_ANALOG_BASE = 0x102 */ > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L0_CKSEL, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L1_CKMODE_EN, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L1_CKSEL, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L2_CKMODE_EN, 0); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_DPHY_L2_CKSEL, 0); > + } > + /* Byte clock invert */ > + SENINF_BITS(pmipi_rx, MIPI_RX_ANAA8_CSI0A, > + RG_CSI0A_CDPHY_L0_T0_BYTECK_INVERT, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANAA8_CSI0A, > + RG_CSI0A_DPHY_L1_BYTECK_INVERT, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANAA8_CSI0A, > + RG_CSI0A_CDPHY_L2_T1_BYTECK_INVERT, 1); > + > + if (is_4d1c(port)) { > + SENINF_BITS(pmipi_rx, MIPI_RX_ANAA8_CSI0B, > + RG_CSI0B_CDPHY_L0_T0_BYTECK_INVERT, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANAA8_CSI0B, > + RG_CSI0B_DPHY_L1_BYTECK_INVERT, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANAA8_CSI0B, > + RG_CSI0B_CDPHY_L2_T1_BYTECK_INVERT, 1); > + } > + > + /* Start ANA EQ tuning */ > + if (is_cdphy_combo(port)) { > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI0A, > + RG_CSI0A_L0_T0AB_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI0A, > + RG_CSI0A_L0_T0AB_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI0A, > + RG_CSI0A_L1_T1AB_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI0A, > + RG_CSI0A_L1_T1AB_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA20_CSI0A, > + RG_CSI0A_L2_T1BC_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA20_CSI0A, > + RG_CSI0A_L2_T1BC_EQ_BW, 1); > + > + if (is_4d1c(port)) { /* 4d1c */ > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI0B, > + RG_CSI0B_L0_T0AB_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI0B, > + RG_CSI0B_L0_T0AB_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI0B, > + RG_CSI0B_L1_T1AB_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI0B, > + RG_CSI0B_L1_T1AB_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA20_CSI0B, > + RG_CSI0B_L2_T1BC_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA20_CSI0B, > + RG_CSI0B_L2_T1BC_EQ_BW, 1); > + } > + } else { > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1A, > + RG_CSI1A_L0_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1A, > + RG_CSI1A_L0_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1A, > + RG_CSI1A_L1_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1A, > + RG_CSI1A_L1_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI1A, > + RG_CSI1A_L2_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI1A, > + RG_CSI1A_L2_EQ_BW, 1); > + > + if (is_4d1c(port)) { /* 4d1c */ > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1B, > + RG_CSI1B_L0_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1B, > + RG_CSI1B_L0_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1B, > + RG_CSI1B_L1_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA18_CSI1B, > + RG_CSI1B_L1_EQ_BW, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI1B, > + RG_CSI1B_L2_EQ_IS, 1); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA1C_CSI1B, > + RG_CSI1B_L2_EQ_BW, 1); > + } > + } > + > + /* End ANA EQ tuning */ > + writel(0x90, pmipi_rx_base + MIPI_RX_ANA40_CSI0A); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA24_CSI0A, > + RG_CSI0A_RESERVE, 0x40); > + if (is_4d1c(port)) > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA24_CSI0B, > + RG_CSI0B_RESERVE, 0x40); > + SENINF_BITS(pmipi_rx, MIPI_RX_WRAPPER80_CSI0A, > + CSR_CSI_RST_MODE, 0); > + if (is_4d1c(port)) > + SENINF_BITS(pmipi_rx, MIPI_RX_WRAPPER80_CSI0B, > + CSR_CSI_RST_MODE, 0); > + /* ANA power on */ > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_BG_CORE_EN, 1); > + if (is_4d1c(port)) > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_BG_CORE_EN, 1); > + usleep_range(20, 40); > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0A, > + RG_CSI0A_BG_LPF_EN, 1); > + if (is_4d1c(port)) > + SENINF_BITS(pmipi_rx, MIPI_RX_ANA00_CSI0B, > + RG_CSI0B_BG_LPF_EN, 1); > + > + udelay(1); > + /* 4d1c: MIPIRX_CONFIG_CSI_BASE = 0xC9000000; */ > + if (is_4d1c(port)) { > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN0_MUX, 1); > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN1_MUX, 2); > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN2_MUX, 0); > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN3_MUX, 3); > + } else { /* 2d1c: MIPIRX_CONFIG_CSI_BASE = 0xE4000000; */ > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN0_MUX, 0); > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN1_MUX, 1); > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN2_MUX, 2); > + SENINF_BITS(pmipi_rx_conf, MIPI_RX_CON24_CSI0, > + CSI0_BIST_LN3_MUX, 3); > + } > +} I think the phy control part should be placed in drivers/phy/mediatek/. In [1], device csis point to a device mipi_phy. csis' driver is in [2], and mipi_phy's driver is in [3] [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/exynos4.dtsi?h=v5.6 [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/media/platform/exynos4-is/mipi-csis.c?h=v5.6 [3] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/samsung/phy-exynos-mipi-video.c?h=v5.6 Regards, Chun-Kuang.