This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] AM6X: How Do I Fix Stream FIFO Overflow Errors in the CSI2RX Linux Driver with NUM_PIXELS?

Part Number: AM69


Tool/software:

There is a large amount of data being streamed to the CSI2RX, and the stream FIFOs are overflowing. How can I fix this issue?


  • The following example is based on the SK-AM69 (J784s4), ti-linux-6.6, as well as a camera that outputs SRGGB10 pixels.


    You can check whether a stream FIFO has overflowed by reading the CSIRX_error_irqs register.

    The following command reads the CSIRX_error_irqs register for the csi_rx_if0:

    root@am69a-sk:~# devmem2 0x04504028
    /dev/mem opened.
    Memory mapped at address 0xffff85cd0000.
    Read at address  0x04504028 (0xffff85cd0028): 0x00030100

    The register value shows that there is an overflow in streams 0 and 1, because bits 16 and 17 have been set.

    To prevent this issue, the stream FIFOs need to be emptied faster, therefore increasing the NUM_PIXELS value should resolve the issue. NUM_PIXELS controls how many pixels are removed from the FIFO per cycle.

    The value is found in the CSIRX_streamx_cfg register (where x is the stream number).

    In this hypothetical situation, we have a camera streaming pixels in a RAW10 format, which means the maximum value NUM_PIXELS can be set to is 1 (2 pixels per cycle). This is because 4 RAW10 pixels can't fit within 32 bits at a time; 2 is the next largest option.

    Setting the NUM_PIXELS value can be done within the cdns-csi2rx.c driver with the following patch:

    From 7df355bf18c4410b260c4d71466582de59b776ca Mon Sep 17 00:00:00 2001
    From: Jared McArthur <j-mcarthur@ti.com>
    Date: Tue, 18 Feb 2025 17:23:52 -0600
    Subject: [PATCH] media: cadence: csi2rx: Set NUM_PIXELS to 2 for each stream
    
    Signed-off-by: Jared McArthur <j-mcarthur@ti.com>
    ---
     drivers/media/platform/cadence/cdns-csi2rx.c | 4 +++-
     1 file changed, 3 insertions(+), 1 deletion(-)
    
    diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
    index 26b83cc47b5d..09e472d471e4 100644
    --- a/drivers/media/platform/cadence/cdns-csi2rx.c
    +++ b/drivers/media/platform/cadence/cdns-csi2rx.c
    @@ -53,6 +53,7 @@
     
     #define CSI2RX_STREAM_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x00c)
     #define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF		(1 << 8)
    +#define CSI2RX_STREAM_CFG_NUM_PIXELS_2			(1 << 4)
     
     #define CSI2RX_LANES_MAX	4
     #define CSI2RX_STREAMS_MAX	4
    @@ -318,7 +319,8 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
     
     		reset_control_deassert(csi2rx->pixel_rst[i]);
     
    -		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
    +		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF +
    +		       CSI2RX_STREAM_CFG_NUM_PIXELS_2,
     		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
     
     		writel(csi2rx->vc_select[i],
    -- 
    2.34.1
    

    This will cause the output of the camera to skip every other pixel.

    This happens, because you're sending two pixels in in every PSIL transaction. When that transaction reaches the DMA, it only takes 16 bits (the first pixel) and drops the other 16 bits. 

    Instead of pixels: 0, 1, 2, 3, 4, 5…
    You get pixels: 0, 2, 4, 6, 8…

    This results in lines that are half the width they should be and the doubled image that you see in the FAQ. If you had an image that was 10x10, you would actually get an image that is 5x10. When outputting to the 10x10 format, you have two 5x5 images in the top two quadrants and nothing in the bottom two.

    Q1: every even row (even pixels only) Q2: every odd row (even pixels only)
    Q3: nothing Q4: nothing

    One other value needs to be set to correctly unpack the data. This value is the SIZE_CFG value within the CSI_RX_IF_CNTX_CNTL_dmaCntx_i register, which controls the data size shift when unpacking.

    Reading the CSI_RX_IF_CNTX_CNTL_dmaCntx_i register, you can see the value of SIZE_CFG is usually set to 0b01 (16 bits), since the RAW10 pixels are sent in 16 bit packets:

    root@am69a-sk:~# devmem2 0x04500020
    /dev/mem opened.
    Memory mapped at address 0xffffa1e4c000.
    Read at address  0x04500020 (0xffffa1e4c020): 0x8010002B

    It will need to be set to 0b10 (32 bits) due to the changes we made to the NUM_PIXEL value. This can be done within the j721e-csi2rx.c shim with the following patch:

    From cc46fa811f5ac9722cb0b37774d787a185749318 Mon Sep 17 00:00:00 2001
    From: Jared McArthur <j-mcarthur@ti.com>
    Date: Tue, 18 Feb 2025 17:38:46 -0600
    Subject: [PATCH 2/2] media: ti: j721e-csi2rx: Set MEDIA_BUS_FMT_SRGGB10_1X10
     size to SHIM_DMACNTX_SIZE_32
    
    Signed-off-by: Jared McArthur <j-mcarthur@ti.com>
    ---
     drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
    index 7f239cbcb4f7..a576377f0eff 100644
    --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
    +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
    @@ -212,7 +212,7 @@ static const struct ti_csi2rx_fmt ti_csi2rx_formats[] = {
     		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
     		.csi_dt			= MIPI_CSI2_DT_RAW10,
     		.bpp			= 16,
    -		.size			= SHIM_DMACNTX_SIZE_16,
    +		.size			= SHIM_DMACNTX_SIZE_32,
     	}, {
     		.fourcc			= V4L2_PIX_FMT_SRGGI10,
     		.code			= MEDIA_BUS_FMT_SRGGI10_1X10,
    -- 
    2.34.1
    

    After these changes are applied, and the kernel is rebuilt, you should no longer observe stream FIFO overflow errors.