Required hw:
There are more pipeline allowed from imx8mp media subsystem in this article we present
- isp pipeline
- isi pipeline
The ISP IP cores in the Rockchip RK3399 (known as the "Rockchip ISP1") and in the NXP i.MX8MP have the same origin, and have slightly diverged over time as they are now independently developed (afaik) by Rockchip and VeriSilicon. The latter is marketed under the name "ISP8000Nano", and is close enough to the RK3399 ISP that it can easily be supported by the same driver. [Paul Elder paul.elder@ideasonboard.com]
Tested media topology:
media-ctl --print-dot > graph.dot
dot -Tpng graph.dot > graph.png
Working on top of Ideas on Board mainline branch ideasonboard/v6.2/isp I collect some patches from mailing list to enable HDMI on imx8mp-evk comes from Pengutronix in particular the following branch pengutronix-imx8mp-hdmi. Cherry-picking a bit I collect all the patchset required to enable ISI + ISP + HDMI on imx8mp into the following branch from Avnet Software and Service team avs-sas tm/media_stage/master/master/alvium_drv Thanks all for the work!
Based on the following two commit Jacopo Mondi debix-a and Laurent Pinchart. We develop the imx8mp-evk-isp0-ov5640.dtbo all the work is done under Linux version 6.3.0-rc4 mainline kernel.
Boot the kernel using U-Boot with the following cmds to enable minisastocsi ov5640 board support:
setenv serverip 10.0.0.1
setenv ipaddr 10.0.0.100
setenv fdtovaddr 0x430c0000
setenv resize_dim 60000
setenv bootargs console=ttymxc1,115200 debug rootwait root=/dev/nfs ip=10.0.0.100:::::eth0 nfsroot=10.0.0.1:/targetfs,v4,tcp rw
setenv bootcmd "tftp $kernel_addr_r Image; tftpboot $fdt_addr_r imx8mp-evk.dtb; tftp $fdtovaddr imx8mp-evk-isp0-ov5640.dtbo; fdt addr $fdt_addr_r; fdt resize $resize_dim; fdt apply $fdtovaddr; booti $kernel_addr_r - $fdt_addr_r;""
Then
boot
Note: As rootfs image we adopt multimedia-libcamera-image this to enable libcamera stuff into our rootfs using Yocto layer from NXP vendor.
bitbake multimedia-libcamera-image
To configure i.mx8mp Media topology in the right way we use the following cmds:
# MEDIA CONFIGURATION
# query sensor color format
v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-mbus-codes 0
# query csis-32e40000.csi color format
v4l2-ctl -d /dev/v4l-subdev2 --list-subdev-mbus-codes 1
# query rkisp1_isp color format
v4l2-ctl -d /dev/v4l-subdev0 --list-subdev-mbus-codes 2
# query rkisp1_resizer_mainpath color format
v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes 1
# query rkisp1_mainpath color format
v4l2-ctl --device=/dev/video0 --list-formats
# SETUP TOPOLOGY LINKS
media-ctl --links "'ov5640 1-003c':0->'csis-32e40000.csi':0[1]"
media-ctl --links "'csis-32e40000.csi':1->'rkisp1_isp':0[1]"
media-ctl --links "'rkisp1_isp':2->'rkisp1_resizer_mainpath':0[1]"
media-ctl --links "'rkisp1_resizer_mainpath':1->'rkisp1_mainpath':0[1]"
# SET SGRBG8 FORMAT 640X480
media-ctl --set-v4l2 "'ov5640 1-003c':0[fmt:SBGGR8_1X8/2592x1944@1/30 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range]"
media-ctl --set-v4l2 "'csis-32e40000.csi':0[fmt:SBGGR8_1X8/2592x1944 field:none colorspace:rec709 xfer:srgb quantization:full-range]"
media-ctl --set-v4l2 "'csis-32e40000.csi':1[fmt:SBGGR8_1X8/2592x1944 field:none colorspace:rec709 xfer:srgb quantization:full-range]"
media-ctl --set-v4l2 "'rkisp1_isp':0[fmt:SBGGR8_1X8/2592x1944 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:full-range]"
media-ctl --set-v4l2 "'rkisp1_isp':0[crop:(0,0)/2592x1944]"
media-ctl --set-v4l2 "'rkisp1_isp':2[fmt:YUYV8_2X8/2592x1944 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:lim-range]"
media-ctl --set-v4l2 "'rkisp1_isp':2[crop:(0,0)/2592x1944]"
media-ctl --set-v4l2 "'rkisp1_resizer_mainpath':0[fmt:YUYV8_2X8/2592x1944 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:lim-range]"
media-ctl --set-v4l2 "'rkisp1_resizer_mainpath':0[crop:(0,0)/2592x1944]"
media-ctl --set-v4l2 "'rkisp1_resizer_mainpath':1[fmt:YUYV8_2X8/640x480 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:lim-range]"
v4l2-ctl --device /dev/video0 --list-formats-ext
v4l2-ctl --device /dev/video0 --list-framesizes=UYVY
v4l2-ctl --device /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=UYVY
With obtain the following Topology configuration:
root@imx8mp-lpddr4-evk:~# media-ctl -p
Media controller API version 6.2.0
Media device information
------------------------
driver rkisp1
model rkisp1
serial
bus info platform:rkisp1
hw revision 0xe
driver version 6.2.0
Device topology
- entity 1: rkisp1_isp (4 pads, 4 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[fmt:SBGGR8_1X8/2592x1944 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/2592x1944
crop:(0,0)/2592x1944]
<- "csis-32e40000.csi":1 [ENABLED]
pad1: Sink
[fmt:unknown/0x0 field:none]
<- "rkisp1_params":0 [ENABLED,IMMUTABLE]
pad2: Source
[fmt:YUYV8_2X8/2592x1944 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:lim-range
crop.bounds:(0,0)/2592x1944
crop:(0,0)/2592x1944]
-> "rkisp1_resizer_mainpath":0 [ENABLED]
pad3: Source
[fmt:unknown/0x0 field:none]
-> "rkisp1_stats":0 [ENABLED,IMMUTABLE]
- entity 6: rkisp1_resizer_mainpath (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[fmt:YUYV8_2X8/2592x1944 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:lim-range
crop.bounds:(0,0)/2592x1944
crop:(0,0)/2592x1944]
<- "rkisp1_isp":2 [ENABLED]
pad1: Source
[fmt:YUYV8_2X8/640x480 field:none colorspace:rec709 xfer:srgb ycbcr:601 quantization:lim-range]
-> "rkisp1_mainpath":0 [ENABLED,IMMUTABLE]
- entity 9: rkisp1_mainpath (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "rkisp1_resizer_mainpath":1 [ENABLED,IMMUTABLE]
- entity 13: rkisp1_stats (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video1
pad0: Sink
<- "rkisp1_isp":3 [ENABLED,IMMUTABLE]
- entity 17: rkisp1_params (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video2
pad0: Source
-> "rkisp1_isp":1 [ENABLED,IMMUTABLE]
- entity 29: csis-32e40000.csi (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[fmt:SBGGR8_1X8/2592x1944 field:none colorspace:rec709 xfer:srgb quantization:full-range]
<- "ov5640 1-003c":0 [ENABLED]
pad1: Source
[fmt:SBGGR8_1X8/2592x1944 field:none colorspace:rec709 xfer:srgb quantization:full-range]
-> "rkisp1_isp":0 [ENABLED]
- entity 34: ov5640 1-003c (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[fmt:SBGGR8_1X8/2592x1944@1/30 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/2624x1964
crop:(0,0)/2624x1952]
-> "csis-32e40000.csi":0 [ENABLED]
To get some frames on the first stage bring-up we use v4l2-ctl with the following cmds:
# GET SOME FRAMES
v4l2-ctl --verbose --device /dev/video0 --stream-mmap --stream-to=frame.raw --stream-count=15 --set-fmt-video=width=640,height=480 --stream-to=./frame.raw
# DISPLAY FRAMES CAPTURED
sudo cp /targetfs/home/root/frame.raw .
convert -size 640x480 -depth 16 uyvy:frame.raw frame.png
gimp frame.png
Raw frames can be checke also using YUView tool
Another way to get fram from ov5640 camera senso is using GStreamer with the following cmd:
gst-launch-1.0 v4l2src io-mode=dmabuf blocksize=76800 ! video/x-raw,format=UYVY,width=640,height=480,framerate=30/1 ! videoconvert ! fbdevsink sync=false
Some test are done using Libcamera below some good cmds:
gst-launch-1.0 libcamerasrc camera-name="/base/soc\@0/bus\@30800000/i2c\@30a30000/ov5640\@3c" ! video/x-raw,format=UYVY,width=640,height=480,framerate=30/1 ! videoconvert ! fbdevsink sync=false
cam -c 1 -C --file=frame.raw
The Image Sensing Interface (ISI) combines image processing pipelines with DMA engines to process and capture frames originating from a variety of sources. The inputs to the ISI go through Pixel Link interfaces, and their number and nature is SoC-dependent. They coverboth capture interfaces (MIPI CSI-2 RX, HDMI RX) and memory inputs. [Laurent Pinchartl laurent.pinchart@ideasonboard.com]
Tested media topology:
media-ctl --print-dot > graph.dot
dot -Tpng graph.dot > graph.png
Working on top of Ideas on Board mainline branch ideasonboard/v6.2/isi I collect some patches from mailing list to enable HDMI on imx8mp-evk comes from Pengutronix in particular the following branch pengutronix-imx8mp-hdmi. Cherry-picking a bit I collect all the patchset required to enable ISI + ISP + HDMI on imx8mp into the following branch from Avnet Software and Service team avs-sas tm/media_stage/master/master/alvium_drv Thanks all for the work!
Based on the following two commit Jacopo Mondi debix-a and Laurent Pinchart. We develop the imx8mp-evk-isi0-ov5640.dtbo all the work is done under Linux version 6.3.0-rc4 mainline kernel.
Boot the kernel using U-Boot with the following cmds to enable minisastocsi ov5640 board support:
setenv serverip 10.0.0.1
setenv ipaddr 10.0.0.100
setenv fdtovaddr 0x430c0000
setenv resize_dim 60000
setenv bootargs console=ttymxc1,115200 debug rootwait root=/dev/nfs ip=10.0.0.100:::::eth0 nfsroot=10.0.0.1:/targetfs,v4,tcp rw
setenv bootcmd "tftp $kernel_addr_r Image; tftpboot $fdt_addr_r imx8mp-evk.dtb; tftp $fdtovaddr imx8mp-evk-isi0-ov5640.dtbo; fdt addr $fdt_addr_r; fdt resize $resize_dim; fdt apply $fdtovaddr; booti $kernel_addr_r - $fdt_addr_r;"
Then
boot
Note: As rootfs image we adopt multimedia-libcamera-image this to enable libcamera stuff into our rootfs using Yocto layer from NXP vendor.
bitbake multimedia-libcamera-image
To configure i.mx8mp Media topology in the right way we use the following cmds:
# MEDIA CONFIGURATION
# query sensor color format
v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-mbus-codes 0
# query csis-32e40000.csi color format
v4l2-ctl -d /dev/v4l-subdev2 --list-subdev-mbus-codes 0
# query crossbar color format
v4l2-ctl -d /dev/v4l-subdev0 --list-subdev-mbus-codes 1
# query mxc_isi.0 color format
v4l2-ctl -d /dev/v4l-subdev1 --list-subdev-mbus-codes 0
# query mxc_isi.0.capture color format
v4l2-ctl -d /dev/video0 --list-formats-ext
# SETUP TOPOLOGY LINKS
media-ctl --links "'ov5640 1-003c':0->'csis-32e40000.csi':0[1]"
media-ctl --links "'csis-32e40000.csi':1->'crossbar':0[1]"
media-ctl --links "'crossbar':3->'mxc_isi.0':0[1]"
media-ctl --links "'mxc_isi.0':1->'mxc_isi.0.capture':0[1]"
# SET UYVY8 FORMAT 1920x1080
media-ctl -d /dev/media0 --set-v4l2 '"ov5640 1-003c":0[fmt:UYVY8_1X16/1920x1080@1/30 field:none]'
media-ctl -d /dev/media0 --set-v4l2 '"csis-32e40000.csi":0[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]'
media-ctl -d /dev/media0 --set-v4l2 '"crossbar":0[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]'
media-ctl -d /dev/media0 --set-v4l2 '"mxc_isi.0":0[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]'
v4l2-ctl --device /dev/video0 --list-formats-ext
v4l2-ctl --device /dev/video0 --list-framesizes=YUYV
v4l2-ctl --device /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=YUYV
With obtain the following Topology configuration:
root@imx8mp-lpddr4-evk:~# media-ctl -p
Media controller API version 6.3.0
Media device information
------------------------
driver mxc-isi
model FSL Capture Media Device
serial
bus info platform:32e00000.isi
hw revision 0x0
driver version 6.3.0
Device topology
- entity 1: crossbar (5 pads, 4 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]
<- "csis-32e40000.csi":1 [ENABLED,IMMUTABLE]
pad1: Sink
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
pad2: Sink
<- "mxc_isi.output":0 [ENABLED,IMMUTABLE]
pad3: Source
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]
-> "mxc_isi.0":0 [ENABLED,IMMUTABLE]
pad4: Source
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
-> "mxc_isi.1":0 [ENABLED,IMMUTABLE]
- entity 7: mxc_isi.0 (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg
compose.bounds:(0,0)/1920x1080
compose:(0,0)/1920x1080]
<- "crossbar":3 [ENABLED,IMMUTABLE]
pad1: Source
[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 10: 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 18: mxc_isi.1 (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[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":4 [ENABLED,IMMUTABLE]
pad1: Source
[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.1.capture":0 [ENABLED,IMMUTABLE]
- entity 21: mxc_isi.1.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video1
pad0: Sink
<- "mxc_isi.1":1 [ENABLED,IMMUTABLE]
- entity 29: mxc_isi.output (1 pad, 1 link)
type Node subtype V4L flags 0
pad0: Source
-> "crossbar":2 [ENABLED,IMMUTABLE]
- entity 36: csis-32e40000.csi (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev3
pad0: Sink
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]
<- "ov5640 1-003c":0 [ENABLED]
pad1: Source
[fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg]
-> "crossbar":0 [ENABLED,IMMUTABLE]
- entity 41: ov5640 1-003c (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev4
pad0: Source
[fmt:UYVY8_1X16/1920x1080@1/30 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/2624x1964
crop:(336,434)/1952x1088]
-> "csis-32e40000.csi":0 [ENABLED]
To get some frames on the first stage bring-up we use v4l2-ctl with the following cmds:
# GET SOME FRAMES
v4l2-ctl --verbose --device /dev/video0 --stream-mmap --stream-to=frame.raw --stream-count=15 --set-fmt-video=width=1920,height=1080 --stream-to=./frame.raw
# DISPLAY FRAMES CAPTURED
sudo cp /targetfs/home/root/frame.raw .
convert -size 1920x1080 -depth 16 uyvy:frame.raw frame.png
gimp frame.png
Raw frames can be checke also using YUView tool
Another way to get fram from ov5640 camera sensor is using GStreamer with the following cmd:
gst-launch-1.0 v4l2src io-mode=dmabuf blocksize=76800 ! video/x-raw,format=YUY2,width=1920,height=1080,framerate=30/1 ! videoconvert ! fbdevsink sync=false
Some test are done using Libcamera below some good cmds:
gst-launch-1.0 libcamerasrc camera-name="/base/soc\@0/bus\@30800000/i2c\@30a30000/ov5640\@3c" ! video/x-raw,format=YUY2,width=1920,height=1080,framerate=30/1 ! videoconvert ! fbdevsink sync=false
cam -c 1 -C --file=frame.raw
Some References:
ref https://github.com/IENT/YUView/releases/tag/v.2.13
ref https://www.marcusfolkesson.se/blog/v4l2-and-media-controller/
ref http://trac.gateworks.com/wiki/linux/v4l2#capturingvideoframes
ref https://www.linux4sam.org/bin/view/Linux4SAM/MediaController
ref https://www.kernel.org/doc/html/v5.0/media/uapi/v4l/crop.html
ref https://www.phytec.de/no/cdocuments/?doc=IwCgG
ref https://www.kernel.org/doc/html/v5.0/media/kapi/mc-core.html
ref https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/colorspaces.html
ref https://git.libcamera.org/libcamera/jmondi/libcamera.git