Skip to content

X2MIPI / X2CSI Hardware and Driver Porting

X2MIPI (also X2CSI) bridges USB-C, HD, or DP video sources to MIPI CSI-2 so they can feed CSI receivers on Raspberry Pi, NVIDIA Jetson, Rockchip, and other SoCs. This page covers hardware notes, driver integration, and platform porting.

Resources, Hardware, and Support

Design resources, hardware PCBA purchase, and technical support are available through doc.ultrasemi.com.

1. Hardware Introduction

X2MIPI hardware supports several video-input to MIPI CSI-2 bridge applications:

  • USB-C to MIPI CSI
  • HD to MIPI CSI
  • DP to MIPI CSI

X2MIPI front view

X2MIPI side view

During hardware design and platform adaptation, confirm:

  • CSI lane count: commonly 2-lane or 4-lane; the SoC device tree must match the hardware.
  • I2C control: the driver talks to the bridge over I2C; the example address is 0x58.
  • Device-tree compatible: compatible = "ultrasemi,lk-x2mipi".
  • Input source and EDID: write EDID through a character device and read back input status / resolution.
  • Clock, power, and reset: add platform-specific resources for the real board.

2. Driver Porting

The driver is a Linux I2C V4L2 subdev driver. Key functions include:

  • Video input timing detection and V4L2 DV timings query.
  • MIPI CSI-2 output configuration from endpoint data-lanes or overlay parameters.
  • V4L2 subdev events for source-change cases.
  • EDID update and input-status readback through /dev/lk_x2mipi.

2.1 Raspberry Pi Porting

2.1.1 Raspberry Pi 3

Use a 15-pin 0.1" reverse FFC to the Raspberry Pi 3 CAMERA connector.

X2MIPI Raspberry Pi 3B+ reference design

Prefer kernel 6.12 or newer.

Clone the full lk_x2mipi tree onto the Pi, for example /home/lk_x2mipi/RaspberryPi3. The package is meant to build on-device. Typical layout:

text
lk_x2mipi/
├─ module/
│  ├─ Makefile
│  └─ lk_x2mipi.c
├─ overlay/
│  └─ lk_x2mipi-overlay.dts
└─ scripts/
   ├─ build.sh
   └─ install.sh

Install build dependencies:

bash
sudo apt update
sudo apt install -y bc bison flex libssl-dev make device-tree-compiler raspberrypi-kernel-headers
ls -l /lib/modules/$(uname -r)/build

Build and install:

bash
cd lk_x2mipi/RaspberryPi3
chmod +x scripts/*.sh
./scripts/build.sh
sudo ./scripts/install.sh

Outputs are module/lk_x2mipi.ko and overlay/lk_x2mipi.dtbo. The install script places the module under /lib/modules/$(uname -r)/extra/, runs depmod -a, and installs the overlay to /boot/overlays/ or /boot/firmware/overlays/.

Enable the overlay:

bash
sudo nano /boot/firmware/config.txt

In /boot/firmware/config.txt (or /boot/config.txt on some images):

ini
camera_auto_detect=0
dtoverlay=lk_x2mipi

Default overlay is 2-lane CSI. On CAM0:

ini
dtoverlay=lk_x2mipi,cam0

When the hardware uses four CSI data lanes:

ini
dtoverlay=lk_x2mipi,4lane

Media-controller mode when required:

ini
dtoverlay=lk_x2mipi,media-controller=1

After reboot, run the common checks below. If /dev/video0 is missing, confirm the system loads /boot/firmware/overlays/lk_x2mipi.dtbo, then rebuild and reinstall to replace any older overlay.

Common validation commands:

bash
dmesg | grep -i lk_x2mipi
v4l2-ctl --list-devices
media-ctl -p

Write EDID to the bridge:

bash
sudo dd if=/path/to/edid.bin of=/dev/lk_x2mipi bs=512 count=1
dmesg | grep -i "EDID updated"

Read resolution, frame rate, audio sample rate, and input-lock status:

bash
sudo dd if=/dev/lk_x2mipi bs=24 count=1 2>/dev/null | hexdump -C

When the read buffer is at least 24 bytes, the driver returns six int fields:

IndexFieldMeaning
0wDetected width in pixels
1hDetected height in pixels
2fpsEstimated frame rate
3audio_sampleAudio sample rate in Hz; 0 when unavailable or unknown
4changeWhether input-lock status changed since the previous read; 1 means changed
5rx_insertCurrent input lock or insertion status; 1 means signal present

2.1.2 Raspberry Pi 5

Use a 15-pin 0.1" to 22-pin 0.05" same-direction FFC to the Raspberry Pi 5 CAM/DISP connector.

Notes:

  • Verified on: Linux raspberrypi 6.18.39+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.18.39-1+rpt1 (2026-07-29) aarch64 GNU/Linux
  • Prefer kernel 6.12 or newer
  • Use the on-board CAM/DISP connector
  • RP1-CFE must match the MIPI link frequency; the current example uses 297 MHz (1920×1080P@30). To change the rate, update both link-frequencies in overlay/lk_x2mipi-overlay.dts and LK_X2MIPI_LINK_FREQ in lk_x2mipi.c
  • Mainline marks UYVY_2X8 as an invalid CSI-2 format (it is not transferred as two bytes). Replace RP1-CFE with a build that supports UYVY_2X8 before use

Clone the full lk_x2mipi tree, for example /home/lk_x2mipi/RaspberryPi5. Typical layout:

text
raspberrypi5/

├─ rp1-cfe-downstream.ko    # replacement driver

├─ module/
│  ├─ Makefile
│  └─ lk_x2mipi.c           # module source (builds lk_x2mipi.ko)
├─ overlay/
│  └─ lk_x2mipi-overlay.dts
└─ scripts/
   ├─ build.sh
   └─ install.sh

Install build dependencies:

bash
sudo apt update
sudo apt install -y bc bison flex libssl-dev make device-tree-compiler raspberrypi-kernel-headers
ls -l /lib/modules/$(uname -r)/build

Replace the RP1-CFE driver. The following removes the stock module and installs rp1-cfe-downstream.ko from the raspberrypi5 folder:

bash
sudo rm /lib/modules/$(uname -r)/kernel/drivers/media/platform/raspberrypi/rp1_cfe/rp1-cfe-downstream.ko.xz
sudo cp /home/lk_x2mipi/raspberrypi/raspberrypi5/rp1-cfe-downstream.ko /lib/modules/$(uname -r)/kernel/drivers/media/platform/raspberrypi/rp1_cfe/

Refresh module dependencies:

bash
sudo depmod -a

Build and install:

bash
cd lk_x2mipi/RaspberryPi5
chmod +x scripts/*.sh
./scripts/build.sh
sudo ./scripts/install.sh

Outputs are module/lk_x2mipi.ko and overlay/lk_x2mipi.dtbo. The install script places the module under /lib/modules/$(uname -r)/extra/, runs depmod -a, and installs the overlay to /boot/overlays/ or /boot/firmware/overlays/.

Enable the overlay:

bash
sudo nano /boot/firmware/config.txt

In /boot/firmware/config.txt (or /boot/config.txt):

ini
camera_auto_detect=0
dtoverlay=lk_x2mipi

Default overlay is 2-lane CSI. On CAM0:

ini
dtoverlay=lk_x2mipi,cam0

Four CSI data lanes when required by hardware:

ini
dtoverlay=lk_x2mipi,4lane

Validate after reboot:

bash
dmesg | grep -i lk_x2mipi
media-ctl -p
v4l2-ctl --list-devices

You should see media pipeline output with rp1-cfe and /dev/video0. If /dev/video0 is missing and rp1-cfe is absent from the list, re-check the overlay and RP1-CFE replacement.

dtoverlay=lk_x2mipi loads only /boot/firmware/overlays/lk_x2mipi.dtbo. If an older file is present, rerun ./scripts/build.sh and sudo ./scripts/install.sh to overwrite it.

Default MIPI configuration at probe

After a successful probe the driver programs MIPI once. Lane count comes from the active overlay endpoint:

  • Default dtoverlay=lk_x2mipi2-lane
  • dtoverlay=lk_x2mipi,4lane4-lane
Update EDID via character device

The driver creates:

  • /dev/lk_x2mipi

Write an EDID blob (up to 512 bytes) to push it to the bridge, for example:

bash
sudo dd if=/path/to/edid.bin of=/dev/lk_x2mipi bs=512 count=1

Check the update result:

bash
dmesg | grep -i "EDID updated"
Read current resolution and status (read)

A read(2) of at least 24 bytes on /dev/lk_x2mipi returns six little-endian int values in the legacy struct gsv_info layout (same endianness as the process):

IndexMeaning
0Width w (pixels)
1Height h
2Frame rate fps (from pixel clock and total rows/columns, rounded)
3Audio sample rate audio_sample (Hz; 0 if none/unknown)
4change: whether input-lock status changed since the previous read (1 = changed)
5rx_insert: input lock / insert status (1 = signal present)

Without valid timings (for example no source), read still succeeds but early fields may be 0.

Example (read 24 bytes and dump raw content):

bash
sudo dd if=/dev/lk_x2mipi bs=24 count=1 2>/dev/null | hexdump -C
Configure the media pipeline

Set DV timings (often subdev2; use the real index if different):

bash
v4l2-ctl -d /dev/v4l-subdev2 --set-dv-bt-timings query

Find the media device:

bash
M=$(for d in /dev/media*; do
  media-ctl -d $d -p 2>/dev/null | grep -q lk_x2mipi && echo $d && break
done)
echo MEDIA=$M

This prints the media device in use.

Reset the pipeline:

bash
sudo media-ctl -d $M -r

Disconnect the link to pisp-fe:

bash
sudo media-ctl -d $M -l "'csi2':4 -> 'pisp-fe':0 [0]"

Enable csi2 -> video0:

bash
sudo media-ctl -d $M -l "'csi2':4 -> 'rp1-cfe-csi2_ch0':0 [1]"

Set csi2 sink and source pad formats:

bash
sudo media-ctl -d $M -V "'csi2':0 [fmt:UYVY8_2X8/1920x1080 field:none colorspace:smpte170m]"
sudo media-ctl -d $M -V "'csi2':4 [fmt:UYVY8_2X8/1920x1080 field:none colorspace:smpte170m]"

Capture an image. Try grabbing one frame with:

bash
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=UYVY --stream-mmap=3 --stream-count=1 --stream-to=image_uyvy.yuv

Inspect the file:

bash
ls -l image_uyvy.yuv

At 1920×1080, the file size should be 4147200 bytes.

2.2 Jetson Porting

X2MIPI NVIDIA Jetson reference design

On Jetson/L4T, integrate the driver into the target kernel tree with a Kconfig + Makefile + C layout:

text
jetson/
├─ Kconfig
├─ Makefile
└─ lk_x2mipi.c

Kernel integration steps:

  1. Place the driver directory under a suitable path in the Jetson kernel tree.
  2. Add a source entry in the parent Kconfig.
  3. Add a subdirectory build entry in the parent Makefile, for example obj-y += lk_x2mipi/jetson/.
  4. Enable CONFIG_VIDEO_LK_X2MIPI_JETSON=y or CONFIG_VIDEO_LK_X2MIPI_JETSON=m.

The device tree should describe:

  • An I2C node with compatible = "ultrasemi,lk-x2mipi".
  • Address reg = <0x58>.
  • Endpoint links to the CSI receiver and matching remote-endpoint.
  • data-lanes for 2-lane or 4-lane MIPI.
  • Platform clock, power, and reset resources.

On some Jetson platforms, loading the module alone may not finish VI async bridge registration, so /dev/video0 never appears. After camera/VI adaptation, enable the VI bridge explicitly:

bash
sudo /sbin/insmod ./lk_x2mipi.ko vi_bridge=1

Validate against the target L4T release and camera_common integration before relying on this long term.

2.3 RK Porting

X2MIPI Rockchip RV1126B reference design

Rockchip platforms can use the generic Linux kernel driver flow (for example RV1126B and other SoCs with a MIPI CSI receiver):

text
linux/
├─ Kconfig
├─ Makefile
└─ lk_x2mipi.c

Kernel integration steps:

  1. Place the driver under the target kernel media/video tree.
  2. Add a source entry in the parent Kconfig.
  3. Add a subdirectory build entry in the parent Makefile, for example obj-y += lk_x2mipi/linux/.
  4. Enable CONFIG_VIDEO_LK_X2MIPI=y or CONFIG_VIDEO_LK_X2MIPI=m.

The device tree should include:

  • An I2C node with compatible = "ultrasemi,lk-x2mipi".
  • Address reg = <0x58>.
  • Endpoints matching the Rockchip CSI/D-PHY/ISP receive path.
  • data-lanes; the driver reads this at probe and programs the MIPI lane count.
  • Platform clock, power, reset, and pinctrl resources.

After deploying kernel, device tree, and image, run the common validation commands to confirm driver loading, media topology, and video-node creation.

Ultrasemi Technology Development Co., Ltd.
Contact us for audio/video product solutions and IC selection support.
Email: doc@ultrasemi.com · QQ: 2272715136 · WeChat/Mobile: +86 13342996846

Ultrasemi Technology Development Co., Ltd.
Contact us for audio/video product solutions and IC selection support.
Email: doc@ultrasemi.com · QQ: 2272715136 · WeChat/Mobile: +86 13342996846