Linux kernel V4L2 driver code for GMSL2 MAX9296 deserializer on Jetson, driver registration in terminal
gmsl2linux driverv4l2max9296kernel driverdevice treejetson

GMSL2 camera driver on Linux: V4L2, MAX9296 kernel driver, device tree

Aaron Angulo · · Updated

The GMSL2 camera driver stack on Linux involves multiple kernel drivers working in coordination, the MAX9296 deserializer driver, the serializer driver, and the sensor driver, with the V4L2 subdev framework tying them together. Understanding where each piece lives and how they communicate is the prerequisite for debugging when any part of it fails. This post covers the full driver architecture.

Key Insights

  • A GMSL2 camera driver on Linux is a chain of V4L2 subdevs: sensor → serializer → deserializer → NVCSI → VI
  • NVIDIA provides reference drivers for specific module/sensor combinations, everything else needs custom work
  • Probe success on the deserializer does not mean the V4L2 video node exists, that depends on the VI driver linking correctly
  • media-ctl -p is the fastest way to see the full pipeline state and identify broken links
  • The DTS must describe every node in the chain with correct compatible strings, I2C addresses, and port linkages

The V4L2 subdev chain for GMSL2

A GMSL2 camera on Jetson is not a single driver, it is a chain of V4L2 subdevices that must all probe successfully and link together before any capture is possible.

The chain, from camera to memory:

IMX390 (sensor subdev)
  → MAX9295A (serializer subdev)
    → MAX9296A (deserializer subdev)
      → NVCSI (CSI receiver subdev)
        → VI (Video Input capture node → /dev/videoN)

Each component is a separate Linux kernel driver. Each must probe successfully. Each must be linked to the next in the V4L2 media graph. If any link is broken, wrong DTS, wrong compatible string, missing regulator, the entire chain fails and no video node appears.

# View the media controller pipeline
sudo media-ctl -p

# Output shows all entities and their link state:
# - pad links between sensor, serializer, deserializer, NVCSI, VI
# - enabled (=>) vs disabled (->) links
# All links from sensor to VI must be enabled for capture to work

The kernel drivers involved

Each component in the chain has a corresponding kernel driver:

ComponentDriver locationCompatible string
IMX390 sensordrivers/media/i2c/imx390.c"sony,imx390"
MAX9295A serializerdrivers/media/i2c/max9295.c"maxim,max9295"
MAX9296A deserializerdrivers/media/i2c/max9296.c"maxim,max9296"
NVCSIdrivers/media/platform/tegra/camera/vi/channel.cTegra-internal
VIdrivers/media/platform/tegra/camera/vi/Tegra-internal

NVIDIA ships these drivers in the L4T kernel source for reference sensor combinations. For a custom sensor (not IMX390), you need to either port an existing driver or write a new one using the tegra-camera-platform sensor driver framework.

The NVCSI and VI drivers are Tegra-internal and are not modified for custom cameras, they are configured through the device tree and through V4L2 controls.

Device tree structure

The DTS for a GMSL2 setup declares every node in the chain. The NVCSI port binding connects the deserializer output to the Jetson capture hardware.

/* Binding the deserializer output to NVCSI port 0 */
nvcsi@15a00000 {
    num-lanes = <4>;
    ports {
        port@0 {
            reg = <0>;
            nvcsi_in0: endpoint@0 {
                remote-endpoint = <&max9296_csi_out0>;
                data-lanes = <0 1 2 3>;
            };
        };
    };
};

The remote-endpoint reference ties the deserializer output port to the NVCSI input port. Both sides must declare the same endpoint with reciprocal remote-endpoint references, if one side references a node that does not exist or has a typo in the label, the media controller cannot build the graph and the VI node does not appear.

Diagnosing probe failures

Work through this sequence when the driver fails to probe:

# 1. Check which drivers probed
sudo dmesg | grep -E "max929[56]|imx390|nvcsi|tegra-vi"

# 2. Check for deferred probe (dependency not ready)
sudo dmesg | grep "probe deferred"
# Common causes: GPIO not ready, regulator not ready, clock not ready

# 3. Check I2C bus accessibility
sudo i2cdetect -y 3  # Replace 3 with your camera I2C bus
# Should show 0x48 (MAX9296A), 0x40 (MAX9295A), sensor address

# 4. Check media graph
sudo media-ctl -p 2>/dev/null | head -60
# Verify all entities are present and links are correct

# 5. Check V4L2 devices
v4l2-ctl --list-devices
# Should show sensor entries if VI linked correctly

A common failure pattern: max9296 probe success in dmesg, but /dev/video0 does not exist. This means the MAX9296A driver probed but the VI driver could not link to the NVCSI. The fix is almost always a DTS error in the NVCSI port binding or the tegra-camera-platform drivernode entry.

Before the kernel driver can probe the sensor, the GMSL2 physical link between serializer and deserializer must be established. No link = no I2C tunnel = sensor probe deferred or failed. This step is often skipped in debugging, leading to time wasted on DTS changes that cannot fix a physical link problem.

Verify link lock by reading the MAX9296A status register directly over I2C:

# Replace 3 with your camera I2C bus number
sudo i2cget -y 3 0x48 0x13
ValueMeaning
0x00No lock — link not established
0x01LOCK bit set — physical layer locked, video not yet detected
0x09LOCK + VIDEO_LOCK — full link established, video flowing
0x0DLOCK + VIDEO_LOCK + additional flags — normal operating state

If i2cget returns 0x00 or hangs (no ACK from address 0x48):

  1. Check cable continuity — the GMSL2 coax must be intact and properly terminated. Use a multimeter on the center conductor.
  2. Check serializer power — the camera module VDD must be active before the GMSL2 link can establish. Verify your carrier board enables camera power before the kernel driver loads.
  3. Check cable length — MAX9296A at 6 Gbps is specified for up to 15m. Longer cables require switching to 3 Gbps mode (set in the serializer GMSL2 rate register).
  4. Try a shorter cable — cable impedance mismatch is a common issue on prototype boards; a known-good short cable isolates whether the problem is cable or hardware.

Only proceed to DTS and driver debugging once i2cget 0x48 0x13 returns a non-zero value showing link lock.

Common DTS errors that break probe

These are the DTS mistakes we see most often:

Wrong compatible string. The compatible string must exactly match the driver’s of_device_id table. "maxim,max9296" (not "max9296", not "maxim,max9296a").

Wrong I2C bus. The DTS node parent must be the correct I2C controller node. On Orin, camera I2C is typically on i2c@3180000 or i2c@31c0000, check the Orin TRM for which controller maps to your carrier board’s camera I2C pins.

Wrong drivernode devname. The tegra-camera-platform devname field must exactly match the I2C device name format: "imx390 3-001a" where 3 is the I2C bus number and 001a is the address in 4-digit hex.

Missing nvidia,gmsl-dser-device phandle. The serializer DTS node must reference the deserializer via this property so the driver knows which deserializer manages the I2C tunnel for this link.

For the full GMSL2 bring-up sequence, see GMSL2 camera bring-up on Jetson Orin: MAX9295/MAX9296 setup. For writing a custom driver on top of this infrastructure, see Writing a custom GMSL2 camera driver for Jetson. If you also need a custom V4L2 driver for the sensor itself, how to write a custom V4L2 camera driver for Jetson Orin covers the full kernel driver implementation.

NVIDIA’s Sensor Driver Programming Guide covering the V4L2 subdev framework for Jetson is in the Jetson Linux Developer Guide. The Linux media controller API documentation is at kernel.org.

GMSL1 vs GMSL2: which should you use for a new design?

GMSL1GMSL2
Max link speed3.12 Gbps6 Gbps
Max camera resolution~3 MP at 30fps~8 MP at 30fps
Typical cable lengthUp to 15mUp to 15m at 6 Gbps
Reverse channel (control)Yes (slower)Yes (higher bandwidth)
I2C tunnelYesYes, plus SPI
GPIO forwardingLimitedFull GPIO forwarding
Reference designMAX96705 + MAX9296MAX9295A + MAX9296A
NVIDIA reference driverL4T GMSL1 driversL4T GMSL2 drivers (IMX390)

For any new design, use GMSL2. The serializer/deserializer ecosystem is fully on GMSL2, NVIDIA’s reference drivers target GMSL2, and the resolution headroom handles current and next-generation sensors.

GMSL1 is appropriate only if you are maintaining an existing system with GMSL1 cameras already in production.

MAX9295A vs MAX96705: serializer selection guide

These two serializers appear in many Jetson camera designs and are frequently confused:

MAX9295AMAX96705
ProtocolGMSL2GMSL1
Link speedUp to 6 Gbps3.12 Gbps
Paired deserializerMAX9296AMAX9296 or MAX96712
I2C tunnelYesYes
SPI tunnelYesNo
GPIO channels6 bidirectional2
Package40-pin WLCSP32-pin TQFN
NVIDIA L4T referenceYes (with IMX390)Older L4T versions only

If you are starting a new design or driver project, choose MAX9295A + MAX9296A. NVIDIA’s L4T source includes reference drivers for this pair, and it is the combination covered by NVIDIA’s GMSL2 driver framework.

If you are working with an existing system using MAX96705, the bring-up process is similar but the L4T reference drivers target the GMSL2 pair. You will be adapting the GMSL1 driver structure, which is documented in older L4T kernel trees.

From zero to first frame: GMSL2 bring-up sequence

The fastest path to a first captured frame on a new GMSL2 setup:

  1. Power on and verify GMSL2 link locki2cget -y <bus> 0x48 0x13 must return non-zero
  2. Check I2C tunneli2cdetect -y <bus> should show the serializer address (0x40) and sensor address tunneled through the deserializer
  3. Boot with NVIDIA reference DTS — use the L4T reference DTS for MAX9295A/MAX9296A as a starting point
  4. Verify all subdevs probedmesg | grep -E "max929[56]|imx390|nvcsi" should show probe success for each
  5. Check media graphmedia-ctl -p should show all entities linked from sensor to VI
  6. Verify V4L2 nodev4l2-ctl --list-devices should show the sensor
  7. Capture a test framev4l2-ctl --stream-mmap -d /dev/video0 --count=1
  8. Decode and view — pipe the raw frame through ffmpeg or use v4l2-ctl --save-frames to verify image content

If step 4 fails (subdev probe error), the problem is DTS or power. If step 5 fails (media graph incomplete), the problem is the NVCSI port binding in DTS. If step 6 fails (no V4L2 node), the VI driver could not link — check for VI-side errors in dmesg.


NVIDIA Jetson Expert Support

Stuck on a Jetson bring-up?

We've debugged this failure mode before. BSP, device tree, camera pipelines, OTA, most blockers clear in the first session. No long retainers. No guessing.

Frequently Asked Questions

Does NVIDIA provide a GMSL2 kernel driver for Jetson?

NVIDIA provides reference GMSL2 drivers in L4T for specific camera modules tested with their devkits, primarily IMX390 and a few others with TIER IV and Leopard Imaging carrier boards. These drivers are in the L4T kernel source under drivers/media/i2c/. For custom cameras or non-reference carrier boards, these drivers require modification or a new driver is needed.

What V4L2 subdev nodes does a GMSL2 camera create on Jetson?

A working GMSL2 setup creates: /dev/videoN for the capture node, /dev/v4l-subdevN for the sensor subdev, /dev/v4l-subdevN+1 for the serializer subdev, and /dev/v4l-subdevN+2 for the deserializer subdev. The media controller graph connects these. Use media-ctl to view the pipeline and verify all subdevs are linked correctly.

How do I verify the MAX9296A deserializer kernel driver probed correctly?

Run sudo dmesg | grep -i max9296 after boot. A successful probe shows 'max9296 X-0048: probe success' or similar. If you see 'probe deferred' the driver is waiting for a dependency (often a GPIO or regulator). If you see 'probe failed', check the DTS compatible string, I2C bus address, and whether the chip is powered.

What is GMSL2 and how does it differ from GMSL1?

GMSL (Gigabit Multimedia Serial Link) is Maxim/ADI's protocol for transmitting video, control, and power over a single coaxial cable. GMSL1 runs at 3.12 Gbps and supports up to 3 MP at 30fps. GMSL2 runs at 6 Gbps (or 3 Gbps in legacy mode) and supports 8 MP at 30fps, bidirectional control at higher bandwidth, and improved EMI performance. For new designs, use GMSL2. GMSL1 is still in production systems but the serializer/deserializer ecosystem is shifting to GMSL2.

What is the difference between MAX9295A and MAX96705 serializers?

MAX9295A is a GMSL2 serializer supporting up to 6 Gbps, I2C/SPI control tunneling, and GPIO forwarding over the GMSL2 link. MAX96705 is a GMSL1 serializer running at 3.12 Gbps. They are not interoperable — a MAX9295A must pair with a MAX9296A deserializer; a MAX96705 must pair with a MAX9296 (GMSL1) or MAX96712 deserializer. For new designs, MAX9295A + MAX9296A is the standard GMSL2 pair.

My GMSL2 driver probes successfully but v4l2-ctl --list-devices shows nothing. Why?

Driver probe success means the chip initialized over I2C, it does not mean the V4L2 device node was created. The V4L2 video node is created by the VI (Video Input) driver when it successfully links to the NVCSI. If the NVCSI-to-VI link fails (wrong port, wrong DTS), the VI driver does not create the /dev/videoN node. Check dmesg for VI probe errors and verify the NVCSI port DTS binding references the correct deserializer output endpoint.

How do I verify GMSL2 link lock between serializer and deserializer?

Read the lock status register from the deserializer over I2C. For MAX9296A: i2cget -y <bus> 0x48 0x13 reads the link status register. Bit 0 = LOCK (1 = locked), bit 3 = VIDEO_LOCK (1 = video detected). A value of 0x09 or 0x0D indicates full lock. If LOCK is 0, check cable continuity, cable length (MAX9296A spec is up to 15m for 6Gbps), and power to the serializer. No lock means no I2C tunnel and no video — the kernel driver cannot probe the sensor if the GMSL2 link isn't established first.

Aarón Angulo, Co-Founder & CEO at ProventusNova

Written by

Aarón Angulo

Co-Founder & CEO · ProventusNova

Obsessed with client outcomes. Aarón ensures every engagement delivers real results, on time, on scope, no exceptions.

Connect on LinkedIn