NXP FRDM i.MX 93 Board TEVS Camera Usage Guide

π Introductionβ
This article guides you on how to get started using TechNexion camera modules on the NXP FRDM i.MX 93 board.
πΈ Supported Camera Modulesβ
Camera Series | Products |
---|---|
TEVS | TEVS-AR0144 TEVS-AR0145 TEVS-AR0234 TEVS-AR0521 TEVS-AR0522 TEVS-AR0821 TEVS-AR0822 TEVS-AR1335 |

π§ Hardware Setup Instructionsβ
Connect the Adapter Board and Camera Cableβ
To set up the TechNexion camera, connect the adapter board and camera cable to the FPC 22-Pin connector on the board as shown in the image below.
The RPI 22-pin connector on the adapter board has two directions. Please make sure the pin definition matches the adapter board.
π§° Camera Installation Instructionsβ
We provide two methods to install camera drivers and device tree blobs. Depending on your needs, you can choose the most suitable method. If you are new to this, we recommend starting with Method 1. If you have a custom Linux kernel and device tree, you can try Method 2.
Method 1 - Using TechNexion Pre-built imageβ
Prepare Yocto demo image for testing TechNexion cameraβ
To test TechNexion TEVS Series cameras, you need a demo image that includes the required Device Tree Blobs (DTBs) and camera drivers. Pre-built demo images are available for download from TechNexion's server.
Download Link:β
π Supported Release List (Instructions for IMX93-FRDM)
Flashing the Imageβ
You can flash the image to an SD Card using the following methods:
Make sure your board is set to boot from SD card or eMMC.
Refer to the official NXP guide π Getting Started with the FRDM-IMX93
- For Windows Users
- For Linux Users
Method 2 - Build custom Linux kernel with camera driverβ
-
Download the camera driver and device tree blobs.
$ git clone https://github.com/TechNexion-Vision/nxp_evk_camera.git -b tn-imx_6.12.20_2.0.0-stable
-
Copy files to your kernel source code.
$ cd nxp_evk_camera/
~/nxp_evk_camera$ cp arch/arm64/boot/dts/freescale/imx93-11x11-frdm-tevs-rpi22.dtso <fetch_kernel_folder>/arch/arm64/boot/dts/freescale/ -
Modify the Makefile to add the driver.
$ cd <fetch_kernel_folder>/drivers/media/i2c/
~/<fetch_kernel_folder>/drivers/media/i2c/$ vi MakefileAdd this line to the Makefile.
obj-$(CONFIG_VIDEO_TEVS) += tevs/
You can refer to linux-tn-imx/drivers/media/i2c/Makefile
-
Modify Kconfig to add camera configuration.
~/<fetch_kernel_folder>/drivers/media/i2c/$ vi Kconfig
Add this part under "Camera sensor devices" menu in Kconfig.
config VIDEO_TEVS
tristate "TechNexion TEVS sensor support"
depends on OF
depends on GPIOLIB && I2C && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
select V4L2_FWNODE
default y
help
This is a Video4Linux2 sensor driver for the TechNexion
TEVS camera sensor with a MIPI CSI-2 interface.
You can refer to linux-tn-imx/drivers/media/i2c/Kconfig
-
Modify the Makefile to add the device tree.
$ cd <fetch_kernel_folder>/arch/arm64/boot/dts/freescale/
~/<fetch_kernel_folder>/arch/arm64/boot/dts/freescale/$ vi MakefileAdd these lines to the Makefile.
imx93-11x11-frdm-tevs-rpi22-dtbs := imx93-11x11-frdm.dtb imx93-11x11-frdm-tevs-rpi22.dtbo
dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-frdm-tevs-rpi22.dtb
You can refer to linux-tn-imx/arch/arm64/boot/dts/freescale/Makefile
-
Compile the kernel and module driver.
Finally, you can start compiling your new Image files, then copy and replace the Image files on the SD card.
πΈ Camera Testing Instructionsβ
Specify Camera DTBO in U-Bootβ
-
Connect the debug console cable to the baseboard (via USB-C).
-
Power on the board and interrupt the boot process. Keep pressing
Enter
when the following message appears:Hit any key to stop autoboot:
-
Specify the appropriate device tree for your camera using the
fdtfile
environment variable in U-Boot:
u-boot=> setenv fdtfile imx93-11x11-frdm-tevs-rpi22.dtb
- Save and continue the boot process:
u-boot=> saveenv
u-boot=> boot
ποΈ Setup the media controller before camera streamingβ
To verify that the camera has been properly connected and linked, use the media-ctl
command:
$ media-ctl -p
This will display media controller information, such as:
Media controller API version 6.12.34
Media device information
------------------------
driver mxc-isi
model FSL Capture Media Device
serial
bus info platform:4ae40000.isi
hw revision 0x0
driver version 6.12.34
Device topology
- entity 1: crossbar (3 pads, 3 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
<- "csidev-4ae00000.csi":1 [ENABLED,IMMUTABLE]
pad1: Sink
<- "mxc_isi.output":0 [ENABLED,IMMUTABLE]
pad2: Source
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
-> "mxc_isi.0":0 [ENABLED,IMMUTABLE]
- entity 5: mxc_isi.0 (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg xfer:srgb ycbcr:601 quantization:full-range
compose.bounds:(0,0)/1920x1080
compose:(0,0)/1920x1080]
<- "crossbar":2 [ENABLED,IMMUTABLE]
pad1: Source
[stream:0 fmt:YUV8_1X24/1920x1080 field:none colorspace:jpeg xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/1920x1080
crop:(0,0)/1920x1080]
-> "mxc_isi.0.capture":0 [ENABLED,IMMUTABLE]
- entity 8: mxc_isi.0.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "mxc_isi.0":1 [ENABLED,IMMUTABLE]
- entity 16: mxc_isi.output (1 pad, 1 link)
type Node subtype V4L flags 0
pad0: Source
-> "crossbar":1 [ENABLED,IMMUTABLE]
- entity 23: csidev-4ae00000.csi (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:smpte170m xfer:709 ycbcr:601 quantization:lim-range]
<- "tevs 2-0048":0 []
pad1: Source
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:smpte170m xfer:709 ycbcr:601 quantization:lim-range]
-> "crossbar":0 [ENABLED,IMMUTABLE]
- entity 28: tevs 2-0048 (1 pad, 1 link, 0 routes)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[stream:0 fmt:UYVY8_1X16/640x480@1/60 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/640x480
crop:(0,0)/640x480]
-> "csidev-4ae00000.csi":0 []
Showing the output as an image can make it easier to understand.

If you want to see the graph, you can use the --print-dot
option.
$ media-ctl --print-dot > graph.dot
$ dot -Tpng graph.dot > graph.png
# If you don't have the tool, you need to install it as follows.
# sudo apt-get install -y graphviz.
We can observe that the link between βtevs 2-0048 β to βcsidev-4ae00000.csi β is a dotted line. This means it's not available.
You need to enable the link between the TEVS and CSI device.
$ media-ctl -l "'tevs 2-0048':0 -> 'csidev-4ae00000.csi':0 [1]"
Set the resolution and format of all media entities to match the camera's output. This means all components in the media pipeline must align with the camera's output settings.
Use the v4l2-ctl
command to check the camera's supported formats, resolutions, and frame intervals.
# formats
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-mbus-codes
ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0,stream=0)
0x200f: MEDIA_BUS_FMT_UYVY8_1X16
0x300a: MEDIA_BUS_FMT_SGRBG10_1X10
0x3011: MEDIA_BUS_FMT_SGRBG12_1X12
# resolutions
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-framesize code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0,stream=0)
Size Range: 640x480 - 640x480
Size Range: 1280x720 - 1280x720
Size Range: 1280x960 - 1280x960
Size Range: 1920x1080 - 1920x1080
Size Range: 2560x1440 - 2560x1440
Size Range: 2592x1944 - 2592x1944
# frame interval of resolution
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=640,height=480,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.008s (120.000 fps)
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=1280,height=720,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.017s (60.000 fps)
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=1280,height=960,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.017s (60.000 fps)
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=1920,height=1080,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.017s (60.000 fps)
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=2560,height=1440,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.031s (32.000 fps)
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=2592,height=1944,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.042s (24.000 fps)
Set resolution to 1280Γ720 for example.
- Command Line
- Script
$ media-ctl -V "'crossbar':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
$ media-ctl -V "'mxc_isi.0':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
$ media-ctl -V "'csidev-4ae00000.csi':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
$ media-ctl -V "'tevs 2-0048':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
#!/bin/bash
# Define the format and resolution as a variable
mdev="/dev/media0"
mediactl="media-ctl -d $mdev"
cam="tevs 2-0048"
csi="csidev-4ae00000.csi"
isi="mxc_isi.0"
code="UYVY8_1X16"
width="1280"
height="720"
format="fmt:${code}/${width}x${height} field:none"
# Function to run media-ctl commands with error handling
echo "Reset media controller..."
$mediactl -r
echo "Set media controller..."
$mediactl -l "\"$cam\":0 -> \"$csi\":0 [1]"
$mediactl -V "\"$cam\":0 [$format]"
$mediactl -V "\"$csi\":0/0 [$format]"
$mediactl -V "\"crossbar\":0 [$format]"
$mediactl -V "\"$isi\":0 [$format]"
This script includes enabling the link between the TEVS and CSI device.
If using pre-built image, you can find the script in /root/media-config-set.sh
.
π₯ Start Camera Video Stream via GStreamerβ
π¬ Launch GStreamer Pipelineβ
Specify the capture device you just obtained and start GStreamer to get the video stream on screen.
Replace <res_w>
and <res_h>
with your selected resolution and screen dimensions:
$ gst-launch-1.0 v4l2src device=/dev/video0 ! \
"video/x-raw, format=YUY2, width=<res_w>, height=<res_h>" ! \
waylandsink sync=false
β Check Media Controllerβ
We can use media-ctl -p
to check the media controller again after setting the resolution and media link as shown below:
Media controller API version 6.12.34
Media device information
------------------------
driver mxc-isi
model FSL Capture Media Device
serial
bus info platform:4ae40000.isi
hw revision 0x0
driver version 6.12.34
Device topology
- entity 1: crossbar (3 pads, 3 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
<- "csidev-4ae00000.csi":1 [ENABLED,IMMUTABLE]
pad1: Sink
<- "mxc_isi.output":0 [ENABLED,IMMUTABLE]
pad2: Source
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
-> "mxc_isi.0":0 [ENABLED,IMMUTABLE]
- entity 5: mxc_isi.0 (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1280x720 field:none
compose.bounds:(0,0)/1280x720
compose:(0,0)/1280x720]
<- "crossbar":2 [ENABLED,IMMUTABLE]
pad1: Source
[stream:0 fmt:YUV8_1X24/1280x720 field:none colorspace:jpeg xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/1280x720
crop:(0,0)/1280x720]
-> "mxc_isi.0.capture":0 [ENABLED,IMMUTABLE]
- entity 8: mxc_isi.0.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "mxc_isi.0":1 [ENABLED,IMMUTABLE]
- entity 16: mxc_isi.output (1 pad, 1 link)
type Node subtype V4L flags 0
pad0: Source
-> "crossbar":1 [ENABLED,IMMUTABLE]
- entity 23: csidev-4ae00000.csi (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
<- "tevs 2-0048":0 [ENABLED]
pad1: Source
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
-> "crossbar":0 [ENABLED,IMMUTABLE]
- entity 28: tevs 2-0048 (1 pad, 1 link, 0 routes)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[stream:0 fmt:UYVY8_1X16/1280x720@1/60 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/1280x720
crop:(0,0)/1280x720]
-> "csidev-4ae00000.csi":0 [ENABLED]
π¨ Troubleshootingβ
Verify Camera Initializationβ
Use dmesg
to check if the TEVS camera module was initialized correctly.
$ dmesg -t | grep tevs
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
tevs 2-0048: tevs_probe() device node: tevs@48
tevs 2-0048: Version:25.3.0.2
tevs 2-0048: Product:TEVS-AR0144, HeaderVer:3, MIPI_Rate:800
tevs 2-0048: Chip ID: 0x0000
tevs 2-0048: probe success
Confirm Board and Camera DTBβ
Check if the correct DTB is loaded with a matching camera model.
$ dmesg -t | grep -i model
Machine model: NXP FRDM-IMX93
Check Available Video Devicesβ
Verify that the video devices are available.
$ v4l2-ctl --list-device
Example output:
mxc-isi-cap (platform:4ae40000.isi):
/dev/video0
/dev/video1
/dev/media0