Jetson Orin NX custom MIPI CSI-2 sensor: RS300 starts streaming, MIPI clock toggles, but VI times out with PHY_INTR phy:0 cil:0

Hello!

I’m bringing up a custom MIPI CSI-2 camera sensor on a Jetson Orin NX running kernel 5.15.148-tegra. The sensor is an RS300 thermal camera connected through a MIPI expansion/breakout setup.

The driver probes and binds successfully, the media graph is enabled, and the sensor driver reports that streaming starts successfully. However, I never receive frames. The VI times out repeatedly, and RTCPU tracing shows PHY_INTR on phy:0 cil:0.

Hardware / setup:

  • Platform: Jetson Orin NX

  • Kernel: 5.15.148-tegra

  • Sensor: RS300, I2C address 0x3c

  • Video node: /dev/video0

  • Current test mode: 640x900, YUYV, 30 fps

  • CSI route in DT: CSI0 / serial_a / port-index = <0> / bus-width = <2>

  • Physical connection path: Jetson MIPI → MIPI expansion/breakout board → jumper wires → sensor breakout

  • I confirmed the MIPI clock pair toggles after the stream command is sent.

Media graph:

media-ctl -p | grep -iE 'rs300|nvcsi|vi-output|ENABLED'

Output:

- entity 1: 13e00000.host1x:nvcsi@15a00000- (2 pads, 2 links, 0 routes)
        <- "rs300 16-003c":0 [ENABLED]
        -> "vi-output, rs300 16-003c":0 [ENABLED]
- entity 4: rs300 16-003c (1 pad, 1 link, 0 routes)
        -> "13e00000.host1x:nvcsi@15a00000-":0 [ENABLED]
- entity 6: vi-output, rs300 16-003c (1 pad, 1 link)
        <- "13e00000.host1x:nvcsi@15a00000-":1 [ENABLED]

V4L2 state:

v4l2-ctl -d /dev/video0 --all

Relevant output:

Driver name      : tegra-video
Card type        : vi-output, rs300 16-003c
Video input      : 0 (Camera 0: ok)

Format Video Capture:
    Width/Height      : 640/900
    Pixel Format      : 'YUYV' (YUYV 4:2:2)
    Bytes per Line    : 1280
    Size Image        : 1152000

Streaming Parameters Video Capture:
    Frames per second : 30.000 (30/1)

The RS300 driver logs show that the sensor powers on, mode is set, and the stream command succeeds:

rs300 16-003c: rs300_ops: power_on() enter
rs300 16-003c: rs300_ops: power_on() leave ok (state=ON)
rs300 16-003c: rs300_ops: set_mode() enter mode_prop_idx=0
rs300 16-003c: rs300_ops: set_mode() leave ok idx=0
rs300 16-003c: rs300: start_streaming() enter
rs300 16-003c: rs300: vd_stream_start()
rs300 16-003c: rs300: VD start bytes path=0x00 src=0x16 dst=0x03 fps=0x1e 640x900
rs300 16-003c: RS300 Stream Started Successfully
rs300 16-003c: rs300: streaming 640x900 @ 30 fps (VD)

But VI times out:

tegra-camrtc-capture-vi tegra-capture-vi: uncorr_err: request timed out after 2500 ms
tegra-camrtc-capture-vi tegra-capture-vi: err_rec: attempting to reset the capture channel
tegra-camrtc-capture-vi tegra-capture-vi: err_rec: successfully reset the capture channel

RTCPU trace shows repeated PHY interrupts:

rtcpu_nvcsi_intr: class:GLOBAL type:PHY_INTR0 phy:0 cil:0 st:0 vc:0 status:0x00000004
rtcpu_nvcsi_intr: class:CORRECTABLE_ERR type:PHY_INTR phy:0 cil:0 st:0 vc:0 status:0x00000004

Sometimes during shutdown I also see:

rtcpu_nvcsi_intr: class:GLOBAL type:PHY_INTR0 phy:0 cil:0 st:0 vc:0 status:0x00000080
rtcpu_nvcsi_intr: class:CORRECTABLE_ERR type:PHY_INTR phy:0 cil:0 st:0 vc:0 status:0x00000080

I do not see CHANSEL_NOMATCH, SHORT_FRAME, FS, or FE in the trace, only PHY-level interrupts and then VI timeout.

Current relevant DT settings:

mode0 {
    mclk_khz = "24000";
    num_lanes = "2";
    tegra_sinterface = "serial_a";
    phy_mode = "DPHY";
    discontinuous_clk = "no";
    cil_settletime = "0";
    lane_polarity = "0";

    mode_type = "yuv";
    pixel_phase = "yuyv";
    csi_pixel_bit_depth = "16";
    dynamic_pixel_bit_depth = "16";

    active_w = "640";
    active_h = "900";
    line_length = "1280";
    pix_clk_hz = "69120000";
    embedded_metadata_height = "0";

    framerate_factor = "1000000";
    min_framerate = "1000000";
    max_framerate = "30000000";
    default_framerate = "30000000";
};

ports {
    port@0 {
        reg = <0>;
        rs300_cam0_out: endpoint {
            status = "okay";
            port-index = <0>;
            bus-width = <2>;
            data-lanes = <1 2>;
            remote-endpoint = <&rs300_nvcsi_in0>;
        };
    };
};

nvcsi@15a00000 {
    channel@0 {
        reg = <0>;
        status = "okay";

        ports {
            port@0 {
                reg = <0>;
                rs300_nvcsi_in0: endpoint@0 {
                    port-index = <0>;
                    bus-width = <2>;
                    remote-endpoint = <&rs300_cam0_out>;
                };
            };

            port@1 {
                reg = <1>;
                rs300_nvcsi_out0: endpoint@1 {
                    remote-endpoint = <&rs300_vi_in0>;
                };
            };
        };
    };
};

Things I have already tried:

  • Confirmed media graph links are enabled.

  • Confirmed /dev/video0 reports 640x900 YUYV @ 30 fps.

  • Fixed the sensor stream command from 60 fps to 30 fps; driver now sends fps=0x1e.

  • Tried discontinuous_clk = "yes" and "no"; no fix.

  • Tried several lane_polarity values:

    • 0 gives mostly PHY_INTR status=0x04

    • 1 gave 0x80

    • 2 and 6 gave 0x44

  • Tried data-lanes = <2 1>; no improvement.

  • Confirmed MIPI clock toggles after the stream command.

  • Tried cil_settletime = "10", but the board became unreachable during boot, so I reverted to cil_settletime = "0".

Questions:

  1. Does PHY_INTR phy:0 cil:0 status=0x00000004 indicate that the Tegra D-PHY is seeing activity but failing to decode valid CSI-2 packets?

  2. Is the absence of CHANSEL_NOMATCH, FS, FE, or SHORT_FRAME a strong sign this is still a physical-layer / lane / signal-integrity issue rather than datatype or frame-size mismatch?

  3. Are there specific meanings for PHY_INTR status=0x04, 0x44, and 0x80 on Orin NX?

  4. Are there additional NVCSI/RTCPU trace events or debugfs nodes I should enable to distinguish between bad signal integrity, wrong lane mapping, P/N polarity issue, and wrong VC/datatype?

  5. Given that the current connection uses a MIPI expansion/breakout board plus jumper wires, is it expected that the receiver might see clock/PHY activity but still fail with PHY_INTR due to signal integrity?

Any guidance on how to interpret these PHY interrupt status bits or what to test next would be appreciated.

Thanks!

Hello,

Thanks for visiting the NVIDIA Developer Forums.
To ensure better visibility and support, I’ve moved your post to the Jetson category where it’s more appropriate

Cheers,
Tom

hello ayun,

according to VI tracing logs.
– the error code 0x04 and 0x44 indicate there’re more than one bit error has detected on data-lane;
The receiver saw an invalid or corrupted Start Of Transmission (SOT) on data lane 0 (multi‑bit SOT error).
– the error code 0x80 means LP sequence error. normally, it should follow by LP11->LP01->LP00->LP11 sequence. it’s more like a hardware issue.

please do configure lane_polarity, since CSI0 D1 and CSI1 D0 P/N will always been swizzled for P/N.
you may have lane_polarity = "6"; for your camera configuration.

please double check Sensor Pixel Clock, which must be set correctly to avoid potential issues.
FYI, I usually using sensor CSI lane output rate for calculation.
for instance, pixel_clk_hz = sensor data rate per lane (Mbps) * number of lanes / bits per pixel.

Hi Jerry! Thanks for the reply.
I was able to capture frames after changing lane_polarity to 6!
I want to note that a lot of my errors were coming from bad hardware (using jumper wires and an expansion board instead of a FPC) so you were right about that too.

Thanks for your help!