[PATCH v3 29/31] media: synopsys: csi2: Add Image Pixel Interface (IPI) support for v150
From: Frank Li <Frank.Li@nxp.com>
Date: 2025-08-21 20:19:13
Also in:
imx, linux-devicetree, linux-media, linux-phy, linux-staging, lkml
Subsystem:
media input infrastructure (v4l/dvb), the rest · Maintainers:
Mauro Carvalho Chehab, Linus Torvalds
Add Image Pixel Interface (IPI) support for v150. Check the ipi_mode register to determine whether the hardware supports IPI. Signed-off-by: Frank Li <Frank.Li@nxp.com> --- drivers/media/platform/synopsys/mipi-csi2.c | 82 +++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/drivers/media/platform/synopsys/mipi-csi2.c b/drivers/media/platform/synopsys/mipi-csi2.c
index 695159f463f872ee0775c271b8e1c4e1d289de20..8ccd3d4960801cccd8d24647f726e4653955f90c 100644
--- a/drivers/media/platform/synopsys/mipi-csi2.c
+++ b/drivers/media/platform/synopsys/mipi-csi2.c@@ -40,6 +40,11 @@ struct dw_csi2_regs { u32 msk2; u32 phy_tst_ctrl0; u32 phy_tst_ctrl1; + u32 ipi_softrstn; + u32 ipi_datatype; + u32 ipi_vcid; + u32 ipi_mode; + u32 ipi_mem_flush; u32 int_st_main; u32 int_st_dphy_fatal; u32 int_msk_dphy_fatal;
@@ -90,6 +95,11 @@ static const struct dw_csi2_regs dw_csi2_v150 = { .phy_stopstate = DW_REG(0x4c), .phy_tst_ctrl0 = DW_REG(0x50), .phy_tst_ctrl1 = DW_REG(0x54), + .ipi_mode = DW_REG(0x80), + .ipi_vcid = DW_REG(0x84), + .ipi_datatype = DW_REG(0x88), + .ipi_mem_flush = DW_REG(0x8c), + .ipi_softrstn = DW_REG(0xa0), .int_st_dphy_fatal = DW_REG(0xe0), .int_msk_dphy_fatal = DW_REG(0xe4), .int_force_dphy_fatal = DW_REG(0xe8),
@@ -115,6 +125,31 @@ static const struct dw_csi2_regs dw_csi2_v150 = { #define INT_ST_MAIN_ERR_PHY BIT(16) #define INT_ST_MAIN_FATAL_ERR_IPI BIT(18) +#define IPI_VCID_VC(x) FIELD_PREP(GENMASK(1, 0), (x)) +#define IPI_VCID_VC_0_1(x) FIELD_PREP(GENMASK(3, 2), (x)) +#define IPI_VCID_VC_2 BIT(4) + +#define IPI_DATA_TYPE_DT(x) FIELD_PREP(GENMASK(5, 0), (x)) +#define IPI_DATA_TYPE_EMB_DATA_EN BIT(8) + +#define IPI_MODE_CONTROLLER BIT(1) +#define IPI_MODE_COLOR_MODE16 BIT(8) +#define IPI_MODE_CUT_THROUGH BIT(16) +#define IPI_MODE_ENABLE BIT(24) + +#define IPI_MEM_FLUSH_AUTO BIT(8) + +#define INT_ST_MAIN_FATAL_ERR_PHY BIT(0) +#define INT_ST_MAIN_FATAL_ERR_PKT BIT(1) +#define INT_ST_MAIN_FATAL_ERR_BNDRY_FRAMEL BIT(2) +#define INT_ST_MAIN_FATAL_ERR_SEQ_FRAME BIT(3) +#define INT_ST_MAIN_FATAL_ERR_CRC_FRAME BIT(4) +#define INT_ST_MAIN_FATAL_ERR_PLD_CRC BIT(5) +#define INT_ST_MAIN_ERR_DID BIT(6) +#define INT_ST_MAIN_ERR_ECC BIT(7) +#define INT_ST_MAIN_ERR_PHY BIT(16) +#define INT_ST_MAIN_FATAL_ERR_IPI BIT(18) + #define INT_MSK_DPHY_FATAL_ERR_SOT_LANE0 BIT(0) #define INT_MSK_DPHY_FATAL_ERR_SOT_LANE1 BIT(1)
@@ -449,6 +484,48 @@ static int dw_mipi_csi2_phy_prep(struct dw_mipi_csi2_dev *csi2, int bpp) return ret; } +static void dw_csi2_device_ipi_config(struct dw_mipi_csi2_dev *csi2) +{ + int dt = media_bus_fmt_to_csi2_dt(csi2->format_mbus.code); + u32 val; + + /* Do IPI soft reset */ + dw_writel(csi2, 0x0, ipi_softrstn); + dw_writel(csi2, 0x1, ipi_softrstn); + + /* Select virtual channel and data type to be processed by IPI */ + val = IPI_DATA_TYPE_DT(dt); + dw_writel(csi2, val, ipi_datatype); + + /* Set virtual channel 0 as default */ + val = IPI_VCID_VC(0); + dw_writel(csi2, val, ipi_vcid); + + /* + * Select IPI camera timing mode and allow the pixel stream + * to be non-continuous when pixel interface FIFO is empty + */ + val = dw_readl(csi2, ipi_mode); + val &= ~IPI_MODE_CONTROLLER; + val &= ~IPI_MODE_COLOR_MODE16; + val |= IPI_MODE_CUT_THROUGH; + dw_writel(csi2, val, ipi_mode); +} + +static void dw_csi2_ipi_enable(struct dw_mipi_csi2_dev *csi2) +{ + u32 val; + + /* Memory is automatically flushed at each Frame Start */ + val = IPI_MEM_FLUSH_AUTO; + dw_writel(csi2, val, ipi_mem_flush); + + /* Enable IPI */ + val = dw_readl(csi2, ipi_mode); + val |= IPI_MODE_ENABLE; + dw_writel(csi2, val, ipi_mode); +} + static void dw_csi2_enable_irq(struct dw_mipi_csi2_dev *csi2) { u32 val;
@@ -583,6 +660,11 @@ static int csi2_start(struct dw_mipi_csi2_dev *csi2, int bpp) if (ret) goto err_stop_upstream; + if (csi2->regs->ipi_mode) { + dw_csi2_device_ipi_config(csi2); + dw_csi2_ipi_enable(csi2); + } + dw_csi2_enable_irq(csi2); return 0;
--
2.34.1