Orin NX: corrupted "rainbow" stream on CIL-A partitions (port-index 0 & 2) of both bricks, CIL-B clean — is a brick lane_swizzle needed?

Hi,

We have a reproducible CSI-2 corruption that follows the NVCSI CIL-A partition exactly,
and we would like guidance on the correct brick lane configuration (lane_swizzle) or the next
diagnostic step.

Setup

  • Carrier: Connect Tech Boson for Orin (NGX020)

  • Module: Jetson Orin NX 16GB

  • L4T 36.4.4 / JetPack 6.2.1, kernel 5.15.148-tegra (Connect Tech BSP ORIN-NX-NANO-36.4.4-V005)

  • Sensors: 4x Allied Vision Alvium 1800 C-511c, MIPI CSI-2, each in 2-lane mode
    (num_lanes = “2”, avt_csi2 driver)

  • Capture: V4L2 / GStreamer with bypass_mode=0 (not Argus)

Symptom
Four identical cameras, identical device-tree mode entries. Two ports stream a perfect image
(verified: correct geometry, correct colors, zero artifacts). The other two ports produce heavy
per-line color-streak (“rainbow”) corruption on every frame — scene geometry is faintly
recognizable, so the packet stream arrives, but the pixel data is scrambled line by line.

Swapping cameras between connectors keeps the fault on the same two connectors, so the cameras are not the cause.

The corruption maps 1:1 to the CIL-A partition of BOTH bricks:

tegra_sinterface port-index partition result
serial_a 0 brick0 CIL-A CORRUPTED
serial_c 2 brick1 CIL-A CORRUPTED
serial_b 1 brick0 CIL-B clean
serial_d 3 brick1 CIL-B clean

On this carrier the CIL-A ports are the x4-capable connectors and route through an on-board
MIPI switch; the CIL-B ports are direct x2 routes. All four run at link-frequency 750 MHz,
discontinuous_clk = “no”, cil_settletime = “0”.

VI errors while streaming the corrupted ports

The attached rtcpu trace (10-buffer capture on the corrupted port) shows a continuous storm of
correctable stream errors on the CIL-A partition itself — about 10,500 lines of
rtcpu_nvcsi_intr: class:CORRECTABLE_ERR type:STREAM_VC phy:0 cil:0 status:0x00000004
— plus CSIMUX_FRAME errors (data 0x…00600060 / 0x…00e00060), CHANSEL_SHORT_FRAME and
CHANSEL_FAULT (data 0x470100) events. The clean CIL-B ports do not generate this storm.

tegra-camrtc-capture-vi tegra-capture-vi: corr_err: discarding frame N, flags: 0, err_data 0x400061

(PIXEL_MISSING_LE + PIXEL_RUNAWAY + VI_PFSD_FAULT; occasionally err_data 0x20000 / FORCE_FE).
The per-line color streaking looks like data-lane byte mis-interleave on the CIL-A half of the
brick.

Already tried — no fix (all verified with GStreamer captures):

  • cil_settletime = “0” is our default. Any value > 0 blanks the stream to all-zero frames on
    these ports, at both 750 MHz and 200 MHz.
  • link-frequency sweep 750 → 375 → 200 MHz: corruption reduces but never clears (sensor driver floors at ~196.4 MHz).
  • deskew_initial_enable = “true” on the CIL-A ports: no change.
  • Clock boost per your usual recipe (nvpmodel -m 0, jetson_clocks, bpmp mrq_rate_locked=1 and rate=max_rate for vi/isp/nvcsi/emc — confirmed vi 832 MHz, nvcsi 642.9 MHz, emc 3199 MHz): no change.
  • All 8 lane_polarity values, both MIPI-switch positions, data-lane reorder in the endpoint,
    every pixel format the camera offers, byte-order/offset reinterpretation of the raw buffer:
    no change.

A similar report on this forum (“Corrupted Camera stream with 4 lane MIPI port in Orin NX
series” — Connect Tech carrier, CSI0+CSI1 corrupted while CSI2+CSI3 clean with the same
camera) was solved by cil_settletime = “0”. Our tree already has that, and the corruption
remains, which is why we suspect a CIL-A lane-order issue rather than timing.

Questions

  1. When a brick’s CIL-A partition is used in 2-lane DPHY mode on Orin NX, is a non-zero
    brick_config.lane_swizzle (csi5 NVCSI_PHY brick config) ever required? How is the correct swizzle value determined for CIL-A vs CIL-B?
  2. Is there any device-tree or V4L2 mechanism to set the brick lane swizzle, or is patching
    csi5_fops.c the only way?
  3. Given err_data 0x400061 with otherwise healthy frame delivery, do you agree this points to
    lane/byte mis-ordering at the PHY level, or is there another known cause we should chase?
  4. We have the rtcpu trace log captured while streaming a corrupted port
    (modprobe rtcpu_debug + tegra_rtcpu/freertos/camera_common events) — attached. What should we look for?

Attachments: device tree source, rtcpu trace log, sample frame from a clean port and a
corrupted port (same scene, same camera model, same settings).

rtcpu_trace_CSI0.txt (1.7 MB)

device_tree_v7_dts.txt (319.5 KB)

Thanks!

If you follow the design guide shouldn’t need to set the lane_swizzle.

Maybe boost the clocks to try.

sudo su
echo 1 > /sys/kernel/debug/bpmp/debug/clk/vi/mrq_rate_locked
echo 1 > /sys/kernel/debug/bpmp/debug/clk/isp/mrq_rate_locked
echo 1 > /sys/kernel/debug/bpmp/debug/clk/nvcsi/mrq_rate_locked
echo 1 > /sys/kernel/debug/bpmp/debug/clk/emc/mrq_rate_locked
cat /sys/kernel/debug/bpmp/debug/clk/vi/max_rate |tee /sys/kernel/debug/bpmp/debug/clk/vi/rate
cat /sys/kernel/debug/bpmp/debug/clk/isp/max_rate | tee  /sys/kernel/debug/bpmp/debug/clk/isp/rate
cat /sys/kernel/debug/bpmp/debug/clk/nvcsi/max_rate | tee /sys/kernel/debug/bpmp/debug/clk/nvcsi/rate
cat /sys/kernel/debug/bpmp/debug/clk/emc/max_rate | tee /sys/kernel/debug/bpmp/debug/clk/emc/rate

echo on > /sys/devices/platform/*rtcpu/power/control

Hi ShaneCCC, thanks for the reply.

The clock boost was already in the “Already tried” list of the original post — we re-confirmed it again today with your exact commands: vi locked at 832 MHz, nvcsi at 642.9 MHz, emc at 3199 MHz. No change in the corruption.

We also tried the one item we hadn’t: echo on > /sys/devices/platform/*rtcpu/power/control. Measured quantitatively: 12 corr_err events during a 10-frame capture both before and after — no change.

On the design guide / lane_swizzle point: agreed, and we verified it empirically. We temporarily exposed brick_config.lane_swizzle as a runtime module parameter and swept ALL 24 NVCSI lane permutations on the corrupted port: only the identity mappings (0x00/0x01) deliver any data at all, and every permutation that moves the A lanes kills the stream. So the logical lane order is already correct and no swizzle is needed — consistent with what you said. lane_polarity is also correct per the official bit map (6 on the brick0 ports to compensate the module’s CSI0_D1/CSI1_D0 P/N inversions, 0 on brick1).

Since the original post we also decoded the rtcpu trace (attached in the OP):

  • ~10,500 lines of rtcpu_nvcsi_intr: class:CORRECTABLE_ERR type:STREAM_VC phy:0 cil:0 status:0x00000004 in a 10-frame capture. status 0x4 = PD_CRC (packet payload CRC failed). With 512 lines per frame this is approximately ONE payload CRC error PER LINE.
  • CSIMUX_FRAME data 0x00600060 / 0x00e00060 = PH single-bit error repaired by ECC (bit21) + payload CRC error (bit22) (+ line short, bit23), per the elinux Camera_BringUp decode.
  • dmesg err_data 0x20000 = PD_CRC_ERR.

So the signature is: on every HS burst (every line), the packet header takes single-bit hits that ECC repairs, and the payload CRC fails — on the CIL-A partitions of BOTH bricks, while both CIL-B partitions are perfectly clean with the same cameras. This looks like marginal physical-layer RX margin on the CIL-A routing of the carrier (which we are pursuing with the vendor in parallel).

Question: before we push this fully to the carrier vendor — is there an official, supported way to add RX-side margin on a specific CIL partition? Specifically:

  1. Can the CIL-A receiver equalization (CTLE, e.g. NVCSI_CIL_A_CTLE_CONTROL, default 0x888) be tuned via device tree or BSP configuration?
  2. Is there a supported way to adjust the DPHY clock/data trimmers (DPHY_INADJ) per partition?
  3. Any other RX compensation you would recommend for a carrier path that is marginal at 1.5 Gbps/lane but works at lower rates?

Thanks!