diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig index bab998c4179a..3bc4aa35887e 100644 --- a/drivers/media/platform/ti/Kconfig +++ b/drivers/media/platform/ti/Kconfig @@ -67,7 +67,8 @@ config VIDEO_TI_J721E_CSI2RX tristate "TI J721E CSI2RX wrapper layer driver" depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API depends on MEDIA_SUPPORT && MEDIA_CONTROLLER - depends on (PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX) || COMPILE_TEST + depends on VIDEO_CADENCE_CSI2RX + depends on PHY_CADENCE_DPHY_RX || COMPILE_TEST depends on ARCH_K3 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c index 094cf40ee492..3992f8b754b7 100644 --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #define SHIM_DMACNTX 0x20 #define SHIM_DMACNTX_EN BIT(31) #define SHIM_DMACNTX_YUV422 GENMASK(27, 26) +#define SHIM_DMACNTX_DUAL_PCK_CFG BIT(24) #define SHIM_DMACNTX_SIZE GENMASK(21, 20) #define SHIM_DMACNTX_FMT GENMASK(5, 0) #define SHIM_DMACNTX_YUV422_MODE_11 3 @@ -40,6 +42,7 @@ #define SHIM_PSI_CFG0_SRC_TAG GENMASK(15, 0) #define SHIM_PSI_CFG0_DST_TAG GENMASK(31, 16) +#define TI_CSI2RX_MAX_PIX_PER_CLK 4 #define PSIL_WORD_SIZE_BYTES 16 /* * There are no hard limits on the width or height. The DMA engine can handle @@ -110,6 +113,7 @@ struct ti_csi2rx_dev { struct v4l2_format v_fmt; struct ti_csi2rx_dma dma; u32 sequence; + u8 pix_per_clk; }; static const struct ti_csi2rx_fmt ti_csi2rx_formats[] = { @@ -485,6 +489,26 @@ static int ti_csi2rx_notifier_register(struct ti_csi2rx_dev *csi) return 0; } +/* Request maximum possible pixels per clock from the bridge */ +static void ti_csi2rx_request_max_ppc(struct ti_csi2rx_dev *csi) +{ + u8 ppc = TI_CSI2RX_MAX_PIX_PER_CLK; + struct media_pad *pad; + int ret; + + pad = media_entity_remote_source_pad_unique(&csi->vdev.entity); + if (!pad) + return; + + ret = cdns_csi2rx_negotiate_ppc(csi->source, pad->index, &ppc); + if (ret) { + dev_warn(csi->dev, "NUM_PIXELS negotiation failed: %d\n", ret); + csi->pix_per_clk = 1; + } else { + csi->pix_per_clk = ppc; + } +} + static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) { const struct ti_csi2rx_fmt *fmt; @@ -496,6 +520,9 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) reg = SHIM_CNTL_PIX_RST; writel(reg, csi->shim + SHIM_CNTL); + /* Negotiate pixel count from the source */ + ti_csi2rx_request_max_ppc(csi); + reg = SHIM_DMACNTX_EN; reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt); @@ -524,14 +551,18 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) case V4L2_PIX_FMT_YVYU: reg |= FIELD_PREP(SHIM_DMACNTX_YUV422, SHIM_DMACNTX_YUV422_MODE_11); + /* Multiple pixels are handled differently for packed YUV */ + if (csi->pix_per_clk == 2) + reg |= SHIM_DMACNTX_DUAL_PCK_CFG; + reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); break; default: - /* Ignore if not YUV 4:2:2 */ + /* By default we change the shift size for multiple pixels */ + reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, + fmt->size + (csi->pix_per_clk >> 1)); break; } - reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); - writel(reg, csi->shim + SHIM_DMACNTX); reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |