# MIPI CSI-2 Camera Application Note ## Introduction This application note describes the MIPI CSI-2 camera subsystem of the MR-NavQ95 vehicle computer (based on the NXP i.MX 95 applications processor) and shows how to bring up, capture from, and stream a camera on the board. It covers the camera data path, the supported sensors, the physical connection, the device-tree overlay selection performed in U-Boot, and the capture / streaming software on the Linux (Cortex-A55) side. It is intended for engineers integrating a camera into a robotics application on MR-NavQ95, whether the frames are consumed for streaming, for display, or as an input to on-device inference. ## Camera subsystem architecture On i.MX 95, image data flows from the sensor through the MIPI CSI-2 receiver, is processed by the on-chip Image Signal Processor (ISP, the "NEO" pipeline), scaled/converted by the Image Sensing Interface (ISI), and written to system memory as V4L2 buffers. From memory the frames are consumed by libcamera / GStreamer (for streaming, encode or display) or by robotics software such as a ROS2 node or the Vision Pipeline feeding the Neutron NPU. ```{image} resources/csi_pipeline.svg :alt: MIPI CSI-2 camera data path on i.MX 95 :width: 600px :align: center ``` Key i.MX 95 camera capabilities relevant to MR-NavQ95: - 2× MIPI CSI-2 4-lane receivers — one of them is muxed with the MIPI-DSI display interface. On MR-NavQ95 these are exposed on the CSI-B2B and DSICSI-B2B connectors. - On-chip ISP (NEO) — Bayer debayering, auto-exposure / auto-white-balance / auto-focus, and RAW→YUV conversion at up to ~500 Mpx/s. - ISI — hardware scale, crop and color-space conversion; produces NV12 (and other) formats for downstream use. - Up to 8 concurrent streams via CSI-2 virtual channels. ## Supported sensors | Sensor | Module | Adapter | dtbo | |---|---|---|---| | imx219 | RPi Camera Module 2 | 22→15-pin | `imx95-navq-(dsi)csi-imx219.dtbo` | | imx708 | RPi Camera Module 3 | 22→15-pin | `imx95-navq-(dsi)csi-imx708.dtbo` | | imx477 | RPi HQ Camera (lens req.) | 22→15-pin | `imx95-navq-(dsi)csi-imx477.dtbo` | | os08a20 | EXPI-os08a20 | none (22-pin direct) | `imx95-navq-(dsi)csi-os08a20.dtbo` | > Note: P/N MR-RPICAM3 is available as an accessory from NXP.com. This is also readily available online from other sources of Raspberry Pi cameras. ## Setup ### Connect camera cable Note: Inserting the cable in the wrong way will damage the camera or the board. Check carefully the images below. 1. imx219, imx708, imx477 All cameras are using the same connector (15 pins) and needs the 22 pins to 15 pins adapter (orange cable).
All cameras are using the same cable orientation. imx708/imx219: ```{image} resources/imx708_cable.jpg :alt: Cable orientation :width: 600px :align: center ``` imx477 (needs lens | not built-in the module): ```{image} resources/imx477_cable.jpg :alt: Cable orientation :width: 600px :align: center ``` Cable type: same side pins. 2. EXPI-os08a20 ```{image} resources/os08a20_cable.jpg :alt: Cable orientation :width: 600px :align: center ``` Cable type: opposite or same side pins. The OS08A20 uses a 22 pins connector directly, no adapter needed. Its connector has pins on top and bottom. !!!ALWAYS make sure to match pin 22 from the camera with pin 1 on the board!!! ### U-Boot configuration The camera is enabled by loading the matching device-tree overlay (dtbo) at boot. Two environment variables select the overlay per connector: `csi_b2b` for the CSI connector and `dsicsi_b2b` for the DSICSI connector. Set the one that matches the connector the camera is plugged into; set the other to `none` if nothing is connected there. In U-boot: ```bash ls mmc 0 # list all dtbo files; use mmc 0 for eMMC and mmc 1 for SD card setenv csi_b2b imx95-navq-csi-imx708.dtbo # the dtbo of the connected camera; if none is available, enter 'none' instead of a dtbo file name setenv dsicsi_b2b imx95-navq-dsicsi-disp-7inch.dtbo # the dtbo of the connected camera; if none is available, enter 'none' instead of a dtbo file name saveenv boot ``` Set the variable based on which connector is in use: DSICSI or CSI Note: Remove the MR-NAVQ95E-CAM module to see connector name ```{image} resources/csi_dsicsi_adapters.jpg :alt: CSI/DSICSI adapters :width: 600px :align: center ``` ## Usage ### Verify the camera is detected After booting with the overlay applied, confirm the sensor enumerated on the Linux side before streaming. Use libcamera's `cam` tool — it lists only the camera(s), whereas `v4l2-ctl`/`media-ctl` also enumerate every other multimedia device (ISP, VPU, etc.) and are confusing to read. Export the pipeline match list first: ```bash export LIBCAMERA_PIPELINES_MATCH_LIST='nxp/neo,imx8-isi,uvcvideo' cam -l # or: cam --list-devices ``` If the camera does not appear, re-check the cable orientation and that the correct dtbo is set for the connector in use (see Troubleshooting). ### RTSP server + client If no display is connected, use RTSP server to stream video to another device. Both devices must be in the same network (can be pinged each other). ### Navq (RTSP server) For all cameras: ```bash export LIBCAMERA_PIPELINES_MATCH_LIST='nxp/neo,imx8-isi,uvcvideo' test-launch "libcamerasrc ! video/x-raw,format=NV12 ! videoconvert ! v4l2h264enc ! h264parse ! rtph264pay name=pay0 pt=96" ``` Note: Different resolutions can be achieved by adding `,width=X,height=Y` to the video/x-raw caps, check the camera capabilities. `LIBCAMERA_PIPELINES_MATCH_LIST` tells libcamera which pipeline handlers to try, in order: `nxp/neo` (the i.MX 95 ISP/NEO pipeline), `imx8-isi` (ISI-only path, no ISP) and `uvcvideo` (USB webcams). Encoding uses the hardware H.264 encoder via `v4l2h264enc`. ### External machine (RTSP client) 1. Install GStreamer + Add-Ons ```bash sudo apt install -y gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav ``` 2. Connect to RTSP Stream ```bash gst-launch-1.0 rtspsrc location=rtsp://:8554/test latency=100 ! rtph264depay ! avdec_h264 ! autovideosink ``` ## Multi-camera and dual CSI-2 i.MX 95 exposes two MIPI CSI-2 4-lane receivers, so two cameras can run concurrently: one on the CSI connector and one on the DSICSI connector. Set both `csi_b2b` and `dsicsi_b2b` to the matching overlays. Note the DSI/CSI mux: the DSICSI port is shared with the MIPI-DSI display, so using it for a second camera precludes a MIPI-DSI panel on that port. Virtual channels allow up to 8 logical streams over the CSI-2 links. ## Integration with the robotics stack Once frames land in system memory as V4L2 buffers they can be consumed by robotics software as well as by libcamera/GStreamer: - ROS2 — a camera node publishes frames on a ROS2 topic for the rest of the navigation / perception graph. - Vision Pipeline — the GStreamer + NNStreamer pipeline pre-processes frames and runs inference on the Neutron NPU (e.g. detection / segmentation) directly from the camera stream. ## References - i.MX Linux Reference Manual: -> chapters 6.1, 6.7 - EXPI-OS08A20 camera module and board user guide (UG10244) — - libcamera documentation — - GStreamer documentation —