All of lore.kernel.org
 help / color / mirror / Atom feed
* [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
@ 2023-05-23  9:44 Jai Luthra
  2023-05-23  9:44 ` [master/kirkstone][RESEND PATCH 2/2] v4l-utils: Add multistream and RGB-IR support Jai Luthra
  2023-05-23 11:48 ` [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Devarsh Thakkar
  0 siblings, 2 replies; 8+ messages in thread
From: Jai Luthra @ 2023-05-23  9:44 UTC (permalink / raw)
  To: meta-arago
  Cc: Ryan Eatmon, Denys Dmytriyenko, Gyan Gupta,
	Sai Sree Kartheek Adivi, Rahul T R, Devarsh Thakkar, Jai Luthra

An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
layer for kirkstone.

TI's 6.1 based kernel has backported multistream routing APIs [1] from
upstream kernel, which requires a few patches to v4l-utils [2] that only
apply cleanly on top of v1.23.0.

Thus we override the recipe in this layer to the latest (v1.23.0) found
from meta-oe master.

Link: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
Link: https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
 ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
 ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
 ...iginal-patch-export-mediactl-headers.patch | 24 +++++
 .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
 .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++
 5 files changed, 236 insertions(+)
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb

diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
new file mode 100644
index 00000000..8ac8fbe1
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
@@ -0,0 +1,44 @@
+From 0d5c0e9a75eca43667b0e29155b635e50622b66a Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Fri, 27 Feb 2015 21:55:36 +0000
+Subject: [PATCH] Revert "media-ctl: Don't install libmediactl and
+
+ libv4l2subdev"
+
+This reverts commit 0911dce53b08b0df3066be2c75f67e8a314d8729.
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+Conflicts:
+	utils/media-ctl/Makefile.am
+
+---
+ utils/media-ctl/Makefile.am | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
+index c48c8d6..e255e16 100644
+--- a/utils/media-ctl/Makefile.am
++++ b/utils/media-ctl/Makefile.am
+@@ -1,8 +1,7 @@
+-noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
+-
++lib_LTLIBRARIES = libmediactl.la libv4l2subdev.la
+ libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
+-libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
+-libmediactl_la_LDFLAGS = -static $(LIBUDEV_LIBS)
++libmediactl_la_CFLAGS = $(LIBUDEV_CFLAGS)
++libmediactl_la_LDFLAGS = $(LIBUDEV_LIBS)
+ 
+ media-bus-format-names.h: ../../include/linux/media-bus-format.h
+ 	$(AM_V_GEN) sed -e '/#define MEDIA_BUS_FMT/ ! d; s/.*FMT_//; /FIXED/ d; s/\t.*//; s/.*/{ \"&\", MEDIA_BUS_FMT_& },/;' \
+@@ -18,9 +17,6 @@ CLEANFILES = $(BUILT_SOURCES)
+ nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
+ libv4l2subdev_la_SOURCES = libv4l2subdev.c
+ libv4l2subdev_la_LIBADD = libmediactl.la
+-libv4l2subdev_la_CFLAGS = -static
+-libv4l2subdev_la_LDFLAGS = -static
+-
+ mediactl_includedir=$(includedir)/mediactl
+ noinst_HEADERS = mediactl.h v4l2subdev.h
+ 
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
new file mode 100644
index 00000000..52fc2d7a
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
@@ -0,0 +1,21 @@
+From 320b8378ee30eb5e0fe83a8b397f822f2f88a4c1 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sun, 1 Mar 2015 22:25:07 +0000
+Subject: [PATCH] %% original patch: mediactl-pkgconfig.patch
+
+---
+ utils/media-ctl/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
+index e255e16..ff7b417 100644
+--- a/utils/media-ctl/Makefile.am
++++ b/utils/media-ctl/Makefile.am
+@@ -20,6 +20,7 @@ libv4l2subdev_la_LIBADD = libmediactl.la
+ mediactl_includedir=$(includedir)/mediactl
+ noinst_HEADERS = mediactl.h v4l2subdev.h
+ 
++pkgconfig_DATA = libmediactl.pc
+ bin_PROGRAMS = media-ctl
+ media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
+ media_ctl_LDADD = libmediactl.la libv4l2subdev.la
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
new file mode 100644
index 00000000..39dc3383
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
@@ -0,0 +1,24 @@
+From f7109d6b2fcb291824d795071c04a492d9fbc45b Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sun, 1 Mar 2015 22:25:07 +0000
+Subject: [PATCH] %% original patch: export-mediactl-headers.patch
+
+---
+ utils/media-ctl/Makefile.am | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
+index ff7b417..6ce656f 100644
+--- a/utils/media-ctl/Makefile.am
++++ b/utils/media-ctl/Makefile.am
+@@ -17,8 +17,8 @@ CLEANFILES = $(BUILT_SOURCES)
+ nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
+ libv4l2subdev_la_SOURCES = libv4l2subdev.c
+ libv4l2subdev_la_LIBADD = libmediactl.la
+-mediactl_includedir=$(includedir)/mediactl
+-noinst_HEADERS = mediactl.h v4l2subdev.h
++otherincludedir = $(includedir)/mediactl
++otherinclude_HEADERS = mediactl.h v4l2subdev.h
+ 
+ pkgconfig_DATA = libmediactl.pc
+ bin_PROGRAMS = media-ctl
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
new file mode 100644
index 00000000..fb844acb
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
@@ -0,0 +1,60 @@
+From 6e7e52de7afe29597016952a7317faf9c3ea3268 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 30 Nov 2019 18:50:34 -0800
+Subject: [PATCH] Do not use getsubopt
+
+POSIX says that behavior when subopts list is empty is undefined.
+musl libs will set value to NULL which leads to crash.
+
+Simply avoid getsubopt, since we cannot rely on it.
+
+Imported from Alpine Linux
+
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+
+Adapt patch to 1.23.0.
+
+(v4l-utils rev fd544473800d02e90bc289434cc44e5aa8fadd0f).
+
+%% original patch: 0007-Do-not-use-getsubopt.patch
+
+Signed-off-by: Daniel Gomez <daniel@qtec.com>
+---
+ utils/v4l2-ctl/v4l2-ctl-common.cpp | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp
+index d77f7104..838c297d 100644
+--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
++++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
+@@ -994,15 +994,17 @@ static bool parse_subset(char *optarg)
+ 
+ static bool parse_next_subopt(char **subs, char **value)
+ {
+-	static char *const subopts[] = {
+-	    nullptr
+-	};
+-	int opt = v4l_getsubopt(subs, subopts, value);
++	char *p = *subs;
++	*value = *subs;
+ 
+-	if (opt < 0 || *value)
+-		return false;
+-	fprintf(stderr, "Missing suboption value\n");
+-	return true;
++	while (*p && *p != ',')
++		p++;
++
++	if (*p)
++		*p++ = '\0';
++
++	*subs = p;
++	return false;
+ }
+ 
+ void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
+-- 
+2.35.1
+
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
new file mode 100644
index 00000000..21a08022
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
@@ -0,0 +1,87 @@
+SUMMARY = "v4l2 and IR applications"
+LICENSE = "GPL-2.0-only & LGPL-2.1-only"
+LIC_FILES_CHKSUM = "file://COPYING;md5=48da9957849056017dc568bbc43d8975 \
+                    file://COPYING.libv4l;md5=d749e86a105281d7a44c2328acebc4b0"
+PROVIDES = "libv4l media-ctl"
+
+DEPENDS = "jpeg \
+           ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'virtual/libx11', '', d)} \
+           ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \
+           ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa-lib', '', d)} \
+           ${@bb.utils.contains_any('PACKAGECONFIG', 'qv4l2 qvidcap', 'qtbase qtbase-native', '', d)}"
+
+DEPENDS:append:libc-musl = " argp-standalone"
+DEPENDS:append:class-target = " udev"
+LDFLAGS:append = " -pthread"
+# v4l2 explicitly sets _FILE_OFFSET_BITS=32 to get access to
+# both 32 and 64 bit file APIs.  But it does not handle the time side?
+# Needs further investigation
+GLIBC_64BIT_TIME_FLAGS = ""
+
+inherit autotools gettext pkgconfig
+
+PACKAGECONFIG ??= "media-ctl"
+PACKAGECONFIG[media-ctl] = "--enable-v4l-utils,--disable-v4l-utils,,"
+PACKAGECONFIG[qv4l2] = ",--disable-qv4l2"
+PACKAGECONFIG[qvidcap] = ",--disable-qvidcap"
+
+SRC_URI = "\
+    git://git.linuxtv.org/v4l-utils.git;protocol=https;branch=master \
+    file://0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch \
+    file://0002-original-patch-mediactl-pkgconfig.patch \
+    file://0003-original-patch-export-mediactl-headers.patch \
+    file://0004-Do-not-use-getsubopt.patch \
+"
+
+SRCREV = "9431e4b26b4842d1401e80ada9f14593dca3a94c"
+
+PV .= "+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+do_configure:prepend() {
+    cd ${S}; ./bootstrap.sh; cd -
+}
+
+EXTRA_OECONF = "--enable-shared --with-udevdir=${base_libdir}/udev \
+                --disable-v4l2-compliance-32 --disable-v4l2-ctl-32"
+
+VIRTUAL-RUNTIME_ir-keytable-keymaps ?= "rc-keymaps"
+
+PACKAGES =+ "media-ctl ir-keytable rc-keymaps libv4l libv4l-dev qv4l2 qvidcap"
+
+RPROVIDES:${PN}-dbg += "libv4l-dbg"
+
+FILES:media-ctl = "${bindir}/media-ctl ${libdir}/libmediactl.so.*"
+FILES:qv4l2 = "\
+    ${bindir}/qv4l2 \
+    ${datadir}/applications/qv4l2.desktop \
+    ${datadir}/icons/hicolor/*/apps/qv4l2.* \
+"
+FILES:qvidcap = "\
+    ${bindir}/qvidcap \
+    ${datadir}/applications/qvidcap.desktop \
+    ${datadir}/icons/hicolor/*/apps/qvidcap.* \
+"
+
+FILES:ir-keytable = "${bindir}/ir-keytable ${base_libdir}/udev/rules.d/*-infrared.rules"
+RDEPENDS:ir-keytable += "${VIRTUAL-RUNTIME_ir-keytable-keymaps}"
+RDEPENDS:qv4l2 += "\
+    ${@bb.utils.contains('PACKAGECONFIG', 'qv4l2', 'qtbase', '', d)}"
+RDEPENDS:qvidcap += "\
+    ${@bb.utils.contains('PACKAGECONFIG', 'qvidcap', 'qtbase', '', d)}"
+
+FILES:rc-keymaps = "${sysconfdir}/rc* ${base_libdir}/udev/rc*"
+
+FILES:${PN} = "${bindir} ${sbindir}"
+
+FILES:libv4l += "${libdir}/libv4l*${SOLIBS} ${libdir}/libv4l/*.so ${libdir}/libv4l/plugins/*.so \
+                 ${libdir}/libdvbv5*${SOLIBS} \
+                 ${libdir}/libv4l/*-decomp"
+
+FILES:libv4l-dev += "${includedir} ${libdir}/pkgconfig \
+                     ${libdir}/libv4l*${SOLIBSDEV} ${libdir}/*.la \
+                     ${libdir}/v4l*${SOLIBSDEV} ${libdir}/libv4l/*.la ${libdir}/libv4l/plugins/*.la"
+
+PARALLEL_MAKE:class-native = ""
+BBCLASSEXTEND = "native"
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [master/kirkstone][RESEND PATCH 2/2] v4l-utils: Add multistream and RGB-IR support
  2023-05-23  9:44 [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Jai Luthra
@ 2023-05-23  9:44 ` Jai Luthra
  2023-05-23 11:48 ` [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Devarsh Thakkar
  1 sibling, 0 replies; 8+ messages in thread
From: Jai Luthra @ 2023-05-23  9:44 UTC (permalink / raw)
  To: meta-arago
  Cc: Ryan Eatmon, Denys Dmytriyenko, Gyan Gupta,
	Sai Sree Kartheek Adivi, Rahul T R, Devarsh Thakkar, Jai Luthra

Apply patches for routing and multistream APIs, and the new 4x4 RGB-IR
bayer format used by the OV2312 camera sensor in TI's 6.1 linux kernel.

Signed-off-by: Jai Luthra <j-luthra@ti.com>
---
 ...-add-support-for-RGBIr-bayer-formats.patch |   62 +
 ...-ctl-Add-routing-and-streams-support.patch |  619 ++++++++++
 ...l-add-support-for-routes-and-streams.patch | 1022 +++++++++++++++++
 ...nce-add-routing-and-streams-multiple.patch |  460 ++++++++
 .../v4l-utils/v4l-utils_1.23.0.bb             |    4 +
 5 files changed, 2167 insertions(+)
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-media-ctl-add-support-for-RGBIr-bayer-formats.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-v4l2-ctl-Add-routing-and-streams-support.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-media-ctl-add-support-for-routes-and-streams.patch
 create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-v4l2-ctl-compliance-add-routing-and-streams-multiple.patch

diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-media-ctl-add-support-for-RGBIr-bayer-formats.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-media-ctl-add-support-for-RGBIr-bayer-formats.patch
new file mode 100644
index 00000000..00f54456
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-media-ctl-add-support-for-RGBIr-bayer-formats.patch
@@ -0,0 +1,62 @@
+From 26e2a60d29456a9cc6acb16ea19039414808bc5e Mon Sep 17 00:00:00 2001
+From: Jai Luthra <j-luthra@ti.com>
+Date: Tue, 5 Jul 2022 16:23:39 +0530
+Subject: [PATCH] media-ctl: add support for RGBIr bayer formats
+
+Signed-off-by: Jai Luthra <j-luthra@ti.com>
+---
+ include/linux/media-bus-format.h | 10 +++++++++-
+ include/linux/videodev2.h        |  9 +++++++++
+ 2 files changed, 18 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/media-bus-format.h b/include/linux/media-bus-format.h
+index ca9a24c8..cbdf3798 100644
+--- a/include/linux/media-bus-format.h
++++ b/include/linux/media-bus-format.h
+@@ -117,7 +117,7 @@
+ #define MEDIA_BUS_FMT_YUV16_1X48		0x202a
+ #define MEDIA_BUS_FMT_UYYVYY16_0_5X48		0x202b
+ 
+-/* Bayer - next is	0x3021 */
++/* Bayer - next is	0x3029 */
+ #define MEDIA_BUS_FMT_SBGGR8_1X8		0x3001
+ #define MEDIA_BUS_FMT_SGBRG8_1X8		0x3013
+ #define MEDIA_BUS_FMT_SGRBG8_1X8		0x3002
+@@ -150,6 +150,14 @@
+ #define MEDIA_BUS_FMT_SGBRG16_1X16		0x301e
+ #define MEDIA_BUS_FMT_SGRBG16_1X16		0x301f
+ #define MEDIA_BUS_FMT_SRGGB16_1X16		0x3020
++#define MEDIA_BUS_FMT_SRGGI10_1X10		0x3021
++#define MEDIA_BUS_FMT_SGRIG10_1X10		0x3022
++#define MEDIA_BUS_FMT_SBGGI10_1X10		0x3023
++#define MEDIA_BUS_FMT_SGBIG10_1X10		0x3024
++#define MEDIA_BUS_FMT_SGIRG10_1X10		0x3025
++#define MEDIA_BUS_FMT_SIGGR10_1X10		0x3026
++#define MEDIA_BUS_FMT_SGIBG10_1X10		0x3027
++#define MEDIA_BUS_FMT_SIGGB10_1X10		0x3028
+ 
+ /* JPEG compressed formats - next is	0x4002 */
+ #define MEDIA_BUS_FMT_JPEG_1X8			0x4001
+diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
+index 5eb96692..093104ab 100644
+--- a/include/linux/videodev2.h
++++ b/include/linux/videodev2.h
+@@ -682,6 +682,15 @@ struct v4l2_pix_format {
+ #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16  GBGB.. RGRG.. */
+ #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16  GRGR.. BGBG.. */
+ #define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16  RGRG.. GBGB.. */
++	/* 10bit raw bayer with IR (4x4) */
++#define V4L2_PIX_FMT_SRGGI10 v4l2_fourcc('R', 'G', 'I', '0') /* 10 RGBG.. GIrGIr.. */
++#define V4L2_PIX_FMT_SGRIG10 v4l2_fourcc('G', 'R', 'I', '0') /* 10 GRGB.. IrGIrG.. */
++#define V4L2_PIX_FMT_SBGGI10 v4l2_fourcc('B', 'G', 'I', '0') /* 10 BGRG.. GIrGIr.. */
++#define V4L2_PIX_FMT_SGBIG10 v4l2_fourcc('G', 'B', 'I', '0') /* 10 GBGR.. IrGIrG.. */
++#define V4L2_PIX_FMT_SGIRG10 v4l2_fourcc('G', 'I', 'R', '0') /* 10 GIrGIr.. RGBG.. */
++#define V4L2_PIX_FMT_SIGGR10 v4l2_fourcc('I', 'G', 'R', '0') /* 10 IrGIrG.. GRGB.. */
++#define V4L2_PIX_FMT_SGIBG10 v4l2_fourcc('G', 'I', 'B', '0') /* 10 GIrGIr.. BGRG.. */
++#define V4L2_PIX_FMT_SIGGB10 v4l2_fourcc('I', 'G', 'B', '0') /* 10 IrGIrG.. GBGR.. */
+ 
+ /* HSV formats */
+ #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3')
+-- 
+2.40.0
+
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-v4l2-ctl-Add-routing-and-streams-support.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-v4l2-ctl-Add-routing-and-streams-support.patch
new file mode 100644
index 00000000..90f15485
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-v4l2-ctl-Add-routing-and-streams-support.patch
@@ -0,0 +1,619 @@
+From 3b57a10f899403acd877683ca0247f2a9eba8850 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Date: Fri, 10 Feb 2023 13:55:44 +0200
+Subject: [PATCH 1/3] v4l2-ctl: Add routing and streams support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add support to get and set subdev routes and to get and set
+configurations per stream.
+
+Based on work from Jacopo Mondi <jacopo@jmondi.org> and
+Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+---
+ utils/v4l2-ctl/v4l2-ctl-subdev.cpp | 288 +++++++++++++++++++++++++----
+ utils/v4l2-ctl/v4l2-ctl.cpp        |   2 +
+ utils/v4l2-ctl/v4l2-ctl.h          |   2 +
+ 3 files changed, 259 insertions(+), 33 deletions(-)
+
+diff --git a/utils/v4l2-ctl/v4l2-ctl-subdev.cpp b/utils/v4l2-ctl/v4l2-ctl-subdev.cpp
+index 33cc1342..81236451 100644
+--- a/utils/v4l2-ctl/v4l2-ctl-subdev.cpp
++++ b/utils/v4l2-ctl/v4l2-ctl-subdev.cpp
+@@ -1,5 +1,13 @@
+ #include "v4l2-ctl.h"
+ 
++#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
++
++/*
++ * The max value comes from a check in the kernel source code
++ * drivers/media/v4l2-core/v4l2-ioctl.c check_array_args()
++ */
++#define NUM_ROUTES_MAX 256
++
+ struct mbus_name {
+ 	const char *name;
+ 	__u32 code;
+@@ -19,45 +27,57 @@ static const struct mbus_name mbus_names[] = {
+ #define SelectionFlags 		(1L<<4)
+ 
+ static __u32 list_mbus_codes_pad;
++static __u32 list_mbus_codes_stream = 0;
+ static __u32 get_fmt_pad;
++static __u32 get_fmt_stream = 0;
+ static __u32 get_sel_pad;
++static __u32 get_sel_stream = 0;
+ static __u32 get_fps_pad;
++static __u32 get_fps_stream = 0;
+ static int get_sel_target = -1;
+ static unsigned int set_selection;
+ static struct v4l2_subdev_selection vsel;
+ static unsigned int set_fmt;
+ static __u32 set_fmt_pad;
++static __u32 set_fmt_stream = 0;
+ static struct v4l2_mbus_framefmt ffmt;
+ static struct v4l2_subdev_frame_size_enum frmsize;
+ static struct v4l2_subdev_frame_interval_enum frmival;
+ static __u32 set_fps_pad;
++static __u32 set_fps_stream = 0;
+ static double set_fps;
++static struct v4l2_subdev_routing routing;
++static struct v4l2_subdev_route routes[NUM_ROUTES_MAX];
+ 
+ void subdev_usage()
+ {
+ 	printf("\nSub-Device options:\n"
+-	       "  --list-subdev-mbus-codes <pad>\n"
++	       "  --list-subdev-mbus-codes pad=<pad>,stream=<stream>\n"
+ 	       "                      display supported mediabus codes for this pad (0 is default)\n"
+ 	       "                      [VIDIOC_SUBDEV_ENUM_MBUS_CODE]\n"
+-	       "  --list-subdev-framesizes pad=<pad>,code=<code>\n"
++	       "  --list-subdev-framesizes pad=<pad>,stream=<stream>,code=<code>\n"
+ 	       "                     list supported framesizes for this pad and code\n"
+ 	       "                     [VIDIOC_SUBDEV_ENUM_FRAME_SIZE]\n"
+ 	       "                     <code> is the value of the mediabus code\n"
+-	       "  --list-subdev-frameintervals pad=<pad>,width=<w>,height=<h>,code=<code>\n"
++	       "  --list-subdev-frameintervals pad=<pad>,stream=<stream>,width=<w>,height=<h>,code=<code>\n"
+ 	       "                     list supported frame intervals for this pad and code and\n"
+ 	       "                     the given width and height [VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL]\n"
+ 	       "                     <code> is the value of the mediabus code\n"
+-	       "  --get-subdev-fmt [<pad>]\n"
+-	       "     		     query the frame format for the given pad [VIDIOC_SUBDEV_G_FMT]\n"
+-	       "  --get-subdev-selection pad=<pad>,target=<target>\n"
++	       "  --get-subdev-fmt pad=<pad>,stream=<stream>\n"
++	       "     		     query the frame format for the given pad and optional stream [VIDIOC_SUBDEV_G_FMT]\n"
++	       "		     <pad> the pad to get the format from\n"
++	       "		     <stream> the stream to get the format from (0 if not specified)\n"
++	       "  --get-subdev-selection pad=<pad>,stream=<stream>,target=<target>\n"
+ 	       "                     query the frame selection rectangle [VIDIOC_SUBDEV_G_SELECTION]\n"
+ 	       "                     See --set-subdev-selection command for the valid <target> values.\n"
+-	       "  --get-subdev-fps [<pad>]\n"
++	       "  --get-subdev-fps pad=<pad>,stream=<stream>\n"
+ 	       "                     query the frame rate [VIDIOC_SUBDEV_G_FRAME_INTERVAL]\n"
+ 	       "  --set-subdev-fmt   (for testing only, otherwise use media-ctl)\n"
+-	       "  --try-subdev-fmt pad=<pad>,width=<w>,height=<h>,code=<code>,field=<f>,colorspace=<c>,\n"
++	       "  --try-subdev-fmt pad=<pad>,stream=<stream>,width=<w>,height=<h>,code=<code>,field=<f>,colorspace=<c>,\n"
+ 	       "                   xfer=<xf>,ycbcr=<y>,hsv=<hsv>,quantization=<q>\n"
+-	       "                     set the frame format [VIDIOC_SUBDEV_S_FMT]\n"
++	       "                     set the frame format for the given pad and optional stream [VIDIOC_SUBDEV_S_FMT]\n"
++	       "                     <pad> the pad to get the format from\n"
++	       "                     <stream> the stream to get the format from (0 if not specified)\n"
+ 	       "                     <code> is the value of the mediabus code\n"
+ 	       "                     <f> can be one of the following field layouts:\n"
+ 	       "                       any, none, top, bottom, interlaced, seq_tb, seq_bt,\n"
+@@ -74,14 +94,30 @@ void subdev_usage()
+ 	       "                     <q> can be one of the following quantization methods:\n"
+ 	       "                       default, full-range, lim-range\n"
+ 	       "  --set-subdev-selection (for testing only, otherwise use media-ctl)\n"
+-	       "  --try-subdev-selection pad=<pad>,target=<target>,flags=<flags>,\n"
++	       "  --try-subdev-selection pad=<pad>,stream=<stream>,target=<target>,flags=<flags>,\n"
+ 	       "                         top=<x>,left=<y>,width=<w>,height=<h>\n"
+ 	       "                     set the video capture selection rectangle [VIDIOC_SUBDEV_S_SELECTION]\n"
+ 	       "                     target=crop|crop_bounds|crop_default|compose|compose_bounds|\n"
+ 	       "                            compose_default|compose_padded|native_size\n"
+ 	       "                     flags=le|ge|keep-config\n"
+-	       "  --set-subdev-fps pad=<pad>,fps=<fps> (for testing only, otherwise use media-ctl)\n"
++	       "  --set-subdev-fps pad=<pad>,stream=<stream>,fps=<fps> (for testing only, otherwise use media-ctl)\n"
+ 	       "                     set the frame rate [VIDIOC_SUBDEV_S_FRAME_INTERVAL]\n"
++	       "  --get-routing      Print the route topology\n"
++	       "  --set-routing <routes>\n"
++	       "                     Comma-separated list of route descriptors to setup\n"
++	       "\n"
++	       "Routes are defined as\n"
++	       "	routes		= route { ',' route } ;\n"
++	       "	route		= sink '->' source '[' flags ']' ;\n"
++	       "	sink		= sink-pad '/' sink-stream ;\n"
++	       "	source		= source-pad '/' source-stream ;\n"
++	       "\n"
++	       "where\n"
++	       "	sink-pad	= Pad numeric identifier for sink\n"
++	       "	sink-stream	= Stream numeric identifier for sink\n"
++	       "	source-pad	= Pad numeric identifier for source\n"
++	       "	source-stream	= Stream numeric identifier for source\n"
++	       "	flags		= Route flags (0: inactive, 1: active)\n"
+ 	       );
+ }
+ 
+@@ -91,14 +127,33 @@ void subdev_cmd(int ch, char *optarg)
+ 
+ 	switch (ch) {
+ 	case OptListSubDevMBusCodes:
+-		if (optarg)
+-			list_mbus_codes_pad = strtoul(optarg, nullptr, 0);
++		subs = optarg;
++		while (subs && *subs != '\0') {
++			static constexpr const char *subopts[] = {
++				"pad",
++				"stream",
++				nullptr
++			};
++
++			switch (parse_subopt(&subs, subopts, &value)) {
++			case 0:
++				list_mbus_codes_pad = strtoul(value, nullptr, 0);
++				break;
++			case 1:
++				list_mbus_codes_stream = strtoul(value, nullptr, 0);
++				break;
++			default:
++				subdev_usage();
++				std::exit(EXIT_FAILURE);
++			}
++		}
+ 		break;
+ 	case OptListSubDevFrameSizes:
+ 		subs = optarg;
+ 		while (*subs != '\0') {
+ 			static constexpr const char *subopts[] = {
+ 				"pad",
++				"stream",
+ 				"code",
+ 				nullptr
+ 			};
+@@ -108,6 +163,9 @@ void subdev_cmd(int ch, char *optarg)
+ 				frmsize.pad = strtoul(value, nullptr, 0);
+ 				break;
+ 			case 1:
++				frmsize.stream = strtoul(value, nullptr, 0);
++				break;
++			case 2:
+ 				frmsize.code = strtoul(value, nullptr, 0);
+ 				break;
+ 			default:
+@@ -121,6 +179,7 @@ void subdev_cmd(int ch, char *optarg)
+ 		while (*subs != '\0') {
+ 			static constexpr const char *subopts[] = {
+ 				"pad",
++				"stream",
+ 				"code",
+ 				"width",
+ 				"height",
+@@ -132,12 +191,15 @@ void subdev_cmd(int ch, char *optarg)
+ 				frmival.pad = strtoul(value, nullptr, 0);
+ 				break;
+ 			case 1:
+-				frmival.code = strtoul(value, nullptr, 0);
++				frmival.stream = strtoul(value, nullptr, 0);
+ 				break;
+ 			case 2:
+-				frmival.width = strtoul(value, nullptr, 0);
++				frmival.code = strtoul(value, nullptr, 0);
+ 				break;
+ 			case 3:
++				frmival.width = strtoul(value, nullptr, 0);
++				break;
++			case 4:
+ 				frmival.height = strtoul(value, nullptr, 0);
+ 				break;
+ 			default:
+@@ -147,14 +209,33 @@ void subdev_cmd(int ch, char *optarg)
+ 		}
+ 		break;
+ 	case OptGetSubDevFormat:
+-		if (optarg)
+-			get_fmt_pad = strtoul(optarg, nullptr, 0);
++		subs = optarg;
++		while (subs && *subs != '\0') {
++			static constexpr const char *subopts[] = {
++				"pad",
++				"stream",
++				nullptr
++			};
++
++			switch (parse_subopt(&subs, subopts, &value)) {
++			case 0:
++				get_fmt_pad = strtoul(value, nullptr, 0);
++				break;
++			case 1:
++				get_fmt_stream = strtoul(value, nullptr, 0);
++				break;
++			default:
++				subdev_usage();
++				std::exit(EXIT_FAILURE);
++			}
++		}
+ 		break;
+ 	case OptGetSubDevSelection:
+ 		subs = optarg;
+ 		while (*subs != '\0') {
+ 			static constexpr const char *subopts[] = {
+ 				"pad",
++				"stream",
+ 				"target",
+ 				nullptr
+ 			};
+@@ -165,6 +246,9 @@ void subdev_cmd(int ch, char *optarg)
+ 				get_sel_pad = strtoul(value, nullptr, 0);
+ 				break;
+ 			case 1:
++				get_sel_stream = strtoul(value, nullptr, 0);
++				break;
++			case 2:
+ 				if (parse_selection_target(value, target)) {
+ 					fprintf(stderr, "Unknown selection target\n");
+ 					subdev_usage();
+@@ -179,8 +263,26 @@ void subdev_cmd(int ch, char *optarg)
+ 		}
+ 		break;
+ 	case OptGetSubDevFPS:
+-		if (optarg)
+-			get_fps_pad = strtoul(optarg, nullptr, 0);
++		subs = optarg;
++		while (subs && *subs != '\0') {
++			static constexpr const char *subopts[] = {
++				"pad",
++				"stream",
++				nullptr
++			};
++
++			switch (parse_subopt(&subs, subopts, &value)) {
++			case 0:
++				get_fps_pad = strtoul(value, nullptr, 0);
++				break;
++			case 1:
++				get_fps_stream = strtoul(value, nullptr, 0);
++				break;
++			default:
++				subdev_usage();
++				std::exit(EXIT_FAILURE);
++			}
++		}
+ 		break;
+ 	case OptSetSubDevFormat:
+ 	case OptTrySubDevFormat:
+@@ -198,6 +300,7 @@ void subdev_cmd(int ch, char *optarg)
+ 				"quantization",
+ 				"xfer",
+ 				"pad",
++				"stream",
+ 				nullptr
+ 			};
+ 
+@@ -244,6 +347,9 @@ void subdev_cmd(int ch, char *optarg)
+ 			case 9:
+ 				set_fmt_pad = strtoul(value, nullptr, 0);
+ 				break;
++			case 10:
++				set_fmt_stream = strtoul(value, nullptr, 0);
++				break;
+ 			default:
+ 				fprintf(stderr, "Unknown option\n");
+ 				subdev_usage();
+@@ -264,6 +370,7 @@ void subdev_cmd(int ch, char *optarg)
+ 				"width",
+ 				"height",
+ 				"pad",
++				"stream",
+ 				nullptr
+ 			};
+ 
+@@ -298,6 +405,9 @@ void subdev_cmd(int ch, char *optarg)
+ 			case 6:
+ 				vsel.pad = strtoul(value, nullptr, 0);
+ 				break;
++			case 7:
++				vsel.stream = strtoul(value, nullptr, 0);
++				break;
+ 			default:
+ 				fprintf(stderr, "Unknown option\n");
+ 				subdev_usage();
+@@ -311,6 +421,7 @@ void subdev_cmd(int ch, char *optarg)
+ 		while (*subs != '\0') {
+ 			static constexpr const char *subopts[] = {
+ 				"pad",
++				"stream",
+ 				"fps",
+ 				nullptr
+ 			};
+@@ -320,6 +431,9 @@ void subdev_cmd(int ch, char *optarg)
+ 				set_fps_pad = strtoul(value, nullptr, 0);
+ 				break;
+ 			case 1:
++				set_fps_stream = strtoul(value, nullptr, 0);
++				break;
++			case 2:
+ 				set_fps = strtod(value, nullptr);
+ 				break;
+ 			default:
+@@ -329,6 +443,47 @@ void subdev_cmd(int ch, char *optarg)
+ 			}
+ 		}
+ 		break;
++	case OptSetRouting: {
++		struct v4l2_subdev_route *r;
++		char *end, *ref, *tok;
++		unsigned int flags;
++
++		memset(&routing, 0, sizeof(routing));
++		memset(routes, 0, sizeof(routes[0]) * NUM_ROUTES_MAX);
++		routing.which = V4L2_SUBDEV_FORMAT_ACTIVE;
++		routing.num_routes = 0;
++		routing.routes = (__u64)routes;
++
++		if (!optarg)
++			break;
++
++		r = (v4l2_subdev_route *)routing.routes;
++		ref = end = strdup(optarg);
++		while ((tok = strsep(&end, ",")) != NULL) {
++			if (sscanf(tok, "%u/%u -> %u/%u [%u]",
++				   &r->sink_pad, &r->sink_stream,
++				   &r->source_pad, &r->source_stream,
++				   &flags) != 5) {
++				free(ref);
++				fprintf(stderr, "Invalid route information specified\n");
++				subdev_usage();
++				std::exit(EXIT_FAILURE);
++			}
++
++			if (flags & ~(V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
++				fprintf(stderr, "Invalid route flags specified: %#x\n", flags);
++				subdev_usage();
++				std::exit(EXIT_FAILURE);
++			}
++
++			r->flags = flags;
++
++			r++;
++			routing.num_routes++;
++		}
++		free(ref);
++		break;
++	}
+ 	default:
+ 		break;
+ 	}
+@@ -394,6 +549,7 @@ void subdev_set(cv4l_fd &_fd)
+ 
+ 		memset(&fmt, 0, sizeof(fmt));
+ 		fmt.pad = set_fmt_pad;
++		fmt.stream = set_fmt_stream;
+ 		fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ 
+ 		if (doioctl(fd, VIDIOC_SUBDEV_G_FMT, &fmt) == 0) {
+@@ -430,7 +586,7 @@ void subdev_set(cv4l_fd &_fd)
+ 			else
+ 				fmt.which = V4L2_SUBDEV_FORMAT_TRY;
+ 
+-			printf("ioctl: VIDIOC_SUBDEV_S_FMT (pad=%u)\n", fmt.pad);
++			printf("ioctl: VIDIOC_SUBDEV_S_FMT (pad=%u,stream=%u)\n", fmt.pad, fmt.stream);
+ 			ret = doioctl(fd, VIDIOC_SUBDEV_S_FMT, &fmt);
+ 			if (ret == 0 && (verbose || !options[OptSetSubDevFormat]))
+ 				print_framefmt(fmt.format);
+@@ -441,6 +597,7 @@ void subdev_set(cv4l_fd &_fd)
+ 
+ 		memset(&sel, 0, sizeof(sel));
+ 		sel.pad = vsel.pad;
++		sel.stream = vsel.stream;
+ 		sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ 		sel.target = vsel.target;
+ 
+@@ -461,7 +618,7 @@ void subdev_set(cv4l_fd &_fd)
+ 			else
+ 				sel.which = V4L2_SUBDEV_FORMAT_TRY;
+ 
+-			printf("ioctl: VIDIOC_SUBDEV_S_SELECTION (pad=%u)\n", sel.pad);
++			printf("ioctl: VIDIOC_SUBDEV_S_SELECTION (pad=%u,stream=%u)\n", sel.pad, sel.stream);
+ 			int ret = doioctl(fd, VIDIOC_SUBDEV_S_SELECTION, &sel);
+ 			if (ret == 0 && (verbose || !options[OptSetSubDevSelection]))
+ 				print_subdev_selection(sel);
+@@ -472,6 +629,7 @@ void subdev_set(cv4l_fd &_fd)
+ 
+ 		memset(&fival, 0, sizeof(fival));
+ 		fival.pad = set_fps_pad;
++		fival.stream = set_fps_stream;
+ 
+ 		if (set_fps <= 0) {
+ 			fprintf(stderr, "invalid fps %f\n", set_fps);
+@@ -482,7 +640,7 @@ void subdev_set(cv4l_fd &_fd)
+ 		fival.interval.denominator = static_cast<uint32_t>(set_fps * fival.interval.numerator);
+ 		printf("Note: --set-subdev-fps is only for testing.\n"
+ 		       "Normally media-ctl is used to configure the video pipeline.\n");
+-		printf("ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL (pad=%u)\n", fival.pad);
++		printf("ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL (pad=%u,stream=%u)\n", fival.pad, fival.stream);
+ 		if (doioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival) == 0) {
+ 			if (!fival.interval.denominator || !fival.interval.numerator)
+ 				printf("\tFrames per second: invalid (%d/%d)\n",
+@@ -493,6 +651,55 @@ void subdev_set(cv4l_fd &_fd)
+ 					fival.interval.denominator, fival.interval.numerator);
+ 		}
+ 	}
++	if (options[OptSetRouting]) {
++		if (doioctl(fd, VIDIOC_SUBDEV_S_ROUTING, &routing) == 0)
++			printf("Routing set\n");
++	}
++}
++
++struct flag_name {
++	__u32 flag;
++	const char *name;
++};
++
++static void print_flags(const struct flag_name *flag_names, unsigned int num_entries, __u32 flags)
++{
++	bool first = true;
++	unsigned int i;
++
++	for (i = 0; i < num_entries; i++) {
++		if (!(flags & flag_names[i].flag))
++			continue;
++		if (!first)
++			printf(",");
++		printf("%s", flag_names[i].name);
++		flags &= ~flag_names[i].flag;
++		first = false;
++	}
++
++	if (flags) {
++		if (!first)
++			printf(",");
++		printf("0x%x", flags);
++	}
++}
++
++static void print_routes(const struct v4l2_subdev_routing *r)
++{
++	unsigned int i;
++	struct v4l2_subdev_route *routes = (struct v4l2_subdev_route *)r->routes;
++
++	static const struct flag_name route_flags[] = {
++		{ V4L2_SUBDEV_ROUTE_FL_ACTIVE, "ACTIVE" },
++	};
++
++	for (i = 0; i < r->num_routes; i++) {
++		printf("%d/%d -> %d/%d [",
++		       routes[i].sink_pad, routes[i].sink_stream,
++		       routes[i].source_pad, routes[i].source_stream);
++		print_flags(route_flags, ARRAY_SIZE(route_flags), routes[i].flags);
++		printf("]\n");
++	}
+ }
+ 
+ void subdev_get(cv4l_fd &_fd)
+@@ -505,8 +712,9 @@ void subdev_get(cv4l_fd &_fd)
+ 		memset(&fmt, 0, sizeof(fmt));
+ 		fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ 		fmt.pad = get_fmt_pad;
++		fmt.stream = get_fmt_stream;
+ 
+-		printf("ioctl: VIDIOC_SUBDEV_G_FMT (pad=%u)\n", fmt.pad);
++		printf("ioctl: VIDIOC_SUBDEV_G_FMT (pad=%u, stream=%u)\n", fmt.pad, fmt.stream);
+ 		if (doioctl(fd, VIDIOC_SUBDEV_G_FMT, &fmt) == 0)
+ 			print_framefmt(fmt.format);
+ 	}
+@@ -518,8 +726,9 @@ void subdev_get(cv4l_fd &_fd)
+ 		memset(&sel, 0, sizeof(sel));
+ 		sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ 		sel.pad = get_sel_pad;
++		sel.stream = get_sel_stream;
+ 
+-		printf("ioctl: VIDIOC_SUBDEV_G_SELECTION (pad=%u)\n", sel.pad);
++		printf("ioctl: VIDIOC_SUBDEV_G_SELECTION (pad=%u,stream=%u)\n", sel.pad, sel.stream);
+ 		if (options[OptAll] || get_sel_target == -1) {
+ 			while (valid_seltarget_at_idx(idx)) {
+ 				sel.target = seltarget_at_idx(idx);
+@@ -538,8 +747,9 @@ void subdev_get(cv4l_fd &_fd)
+ 
+ 		memset(&fival, 0, sizeof(fival));
+ 		fival.pad = get_fps_pad;
++		fival.stream = get_fps_stream;
+ 
+-		printf("ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL (pad=%u)\n", fival.pad);
++		printf("ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL (pad=%u,stream=%u)\n", fival.pad, fival.stream);
+ 		if (doioctl(fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &fival) == 0) {
+ 			if (!fival.interval.denominator || !fival.interval.numerator)
+ 				printf("\tFrames per second: invalid (%d/%d)\n",
+@@ -550,6 +760,17 @@ void subdev_get(cv4l_fd &_fd)
+ 					fival.interval.denominator, fival.interval.numerator);
+ 		}
+ 	}
++
++	if (options[OptGetRouting]) {
++		memset(&routing, 0, sizeof(routing));
++		memset(routes, 0, sizeof(routes[0]) * NUM_ROUTES_MAX);
++		routing.which = V4L2_SUBDEV_FORMAT_ACTIVE;
++		routing.num_routes = NUM_ROUTES_MAX;
++		routing.routes = (__u64)routes;
++
++		if (doioctl(fd, VIDIOC_SUBDEV_G_ROUTING, &routing) == 0)
++			print_routes(&routing);
++	}
+ }
+ 
+ static void print_mbus_code(__u32 code)
+@@ -566,11 +787,12 @@ static void print_mbus_code(__u32 code)
+ 		printf("\t0x%04x", code);
+ }
+ 
+-static void print_mbus_codes(int fd, __u32 pad)
++static void print_mbus_codes(int fd, __u32 pad, __u32 stream)
+ {
+ 	struct v4l2_subdev_mbus_code_enum mbus_code = {};
+ 
+ 	mbus_code.pad = pad;
++	mbus_code.stream = stream;
+ 	mbus_code.which = V4L2_SUBDEV_FORMAT_TRY;
+ 
+ 	for (;;) {
+@@ -623,13 +845,13 @@ void subdev_list(cv4l_fd &_fd)
+ 	int fd = _fd.g_fd();
+ 
+ 	if (options[OptListSubDevMBusCodes]) {
+-		printf("ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=%u)\n",
+-		       list_mbus_codes_pad);
+-		print_mbus_codes(fd, list_mbus_codes_pad);
++		printf("ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=%u,stream=%u)\n",
++		       list_mbus_codes_pad, list_mbus_codes_stream);
++		print_mbus_codes(fd, list_mbus_codes_pad, list_mbus_codes_stream);
+ 	}
+ 	if (options[OptListSubDevFrameSizes]) {
+-		printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=%u)\n",
+-		       frmsize.pad);
++		printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=%u,stream=%u)\n",
++		       frmsize.pad, frmsize.stream);
+ 		frmsize.index = 0;
+ 		frmsize.which = V4L2_SUBDEV_FORMAT_TRY;
+ 		while (test_ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &frmsize) >= 0) {
+@@ -638,8 +860,8 @@ void subdev_list(cv4l_fd &_fd)
+ 		}
+ 	}
+ 	if (options[OptListSubDevFrameIntervals]) {
+-		printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=%u)\n",
+-		       frmival.pad);
++		printf("ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=%u,stream=%u)\n",
++		       frmival.pad, frmival.stream);
+ 		frmival.index = 0;
+ 		frmival.which = V4L2_SUBDEV_FORMAT_TRY;
+ 		while (test_ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &frmival) >= 0) {
+diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
+index 8585278f..1cfb50f7 100644
+--- a/utils/v4l2-ctl/v4l2-ctl.cpp
++++ b/utils/v4l2-ctl/v4l2-ctl.cpp
+@@ -64,6 +64,8 @@ static struct option long_options[] = {
+ 	{"get-fmt-video-out", no_argument, nullptr, OptGetVideoOutFormat},
+ 	{"set-fmt-video-out", required_argument, nullptr, OptSetVideoOutFormat},
+ 	{"try-fmt-video-out", required_argument, nullptr, OptTryVideoOutFormat},
++	{"set-routing", required_argument, 0, OptSetRouting},
++	{"get-routing", no_argument, 0, OptGetRouting},
+ 	{"help", no_argument, nullptr, OptHelp},
+ 	{"help-tuner", no_argument, nullptr, OptHelpTuner},
+ 	{"help-io", no_argument, nullptr, OptHelpIO},
+diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
+index 70a80ade..51a68b92 100644
+--- a/utils/v4l2-ctl/v4l2-ctl.h
++++ b/utils/v4l2-ctl/v4l2-ctl.h
+@@ -197,6 +197,8 @@ enum Option {
+ 	OptInfoEdid,
+ 	OptShowEdid,
+ 	OptFixEdidChecksums,
++	OptSetRouting,
++	OptGetRouting,
+ 	OptFreqSeek,
+ 	OptEncoderCmd,
+ 	OptTryEncoderCmd,
+-- 
+2.40.0
+
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-media-ctl-add-support-for-routes-and-streams.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-media-ctl-add-support-for-routes-and-streams.patch
new file mode 100644
index 00000000..b2d4eded
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-media-ctl-add-support-for-routes-and-streams.patch
@@ -0,0 +1,1022 @@
+From 868c176e0de433777d5eed3e6d6d8dc03b9145a6 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Date: Fri, 10 Feb 2023 13:55:45 +0200
+Subject: [PATCH 2/3] media-ctl: add support for routes and streams
+
+Add support to get and set subdev routes and to get and set
+configurations per stream.
+
+Based on work from Sakari Ailus <sakari.ailus@linux.intel.com>.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+---
+ utils/media-ctl/libmediactl.c   |  41 +++++
+ utils/media-ctl/libv4l2subdev.c | 283 ++++++++++++++++++++++++++++----
+ utils/media-ctl/media-ctl.c     | 121 ++++++++++++--
+ utils/media-ctl/mediactl.h      |  16 ++
+ utils/media-ctl/options.c       |  15 +-
+ utils/media-ctl/options.h       |   1 +
+ utils/media-ctl/v4l2subdev.h    |  58 ++++++-
+ 7 files changed, 478 insertions(+), 57 deletions(-)
+
+diff --git a/utils/media-ctl/libmediactl.c b/utils/media-ctl/libmediactl.c
+index 1fd6525b..537365d0 100644
+--- a/utils/media-ctl/libmediactl.c
++++ b/utils/media-ctl/libmediactl.c
+@@ -876,6 +876,47 @@ struct media_pad *media_parse_pad(struct media_device *media,
+ 	return &entity->pads[pad];
+ }
+ 
++struct media_pad *media_parse_pad_stream(struct media_device *media,
++					 const char *p, unsigned int *stream,
++					 char **endp)
++{
++	struct media_pad *pad;
++	const char *orig_p = p;
++	char *ep;
++
++	pad = media_parse_pad(media, p, &ep);
++	if (pad == NULL)
++		return NULL;
++
++	p = ep;
++
++	if (*p == '/') {
++		unsigned int s;
++
++		p++;
++
++		s = strtoul(p, &ep, 10);
++
++		if (ep == p) {
++			printf("Unable to parse stream: '%s'\n", orig_p);
++			if (endp)
++				*endp = (char*)p;
++			return NULL;
++		}
++
++		*stream = s;
++
++		p++;
++	} else {
++		*stream = 0;
++	}
++
++	if (endp)
++		*endp = (char*)p;
++
++	return pad;
++}
++
+ struct media_link *media_parse_link(struct media_device *media,
+ 				    const char *p, char **endp)
+ {
+diff --git a/utils/media-ctl/libv4l2subdev.c b/utils/media-ctl/libv4l2subdev.c
+index 63bb3d75..d203e5b4 100644
+--- a/utils/media-ctl/libv4l2subdev.c
++++ b/utils/media-ctl/libv4l2subdev.c
+@@ -64,7 +64,7 @@ void v4l2_subdev_close(struct media_entity *entity)
+ }
+ 
+ int v4l2_subdev_get_format(struct media_entity *entity,
+-	struct v4l2_mbus_framefmt *format, unsigned int pad,
++	struct v4l2_mbus_framefmt *format, unsigned int pad, unsigned int stream,
+ 	enum v4l2_subdev_format_whence which)
+ {
+ 	struct v4l2_subdev_format fmt;
+@@ -76,6 +76,7 @@ int v4l2_subdev_get_format(struct media_entity *entity,
+ 
+ 	memset(&fmt, 0, sizeof(fmt));
+ 	fmt.pad = pad;
++	fmt.stream = stream;
+ 	fmt.which = which;
+ 
+ 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
+@@ -88,6 +89,7 @@ int v4l2_subdev_get_format(struct media_entity *entity,
+ 
+ int v4l2_subdev_set_format(struct media_entity *entity,
+ 	struct v4l2_mbus_framefmt *format, unsigned int pad,
++	unsigned int stream,
+ 	enum v4l2_subdev_format_whence which)
+ {
+ 	struct v4l2_subdev_format fmt;
+@@ -99,6 +101,7 @@ int v4l2_subdev_set_format(struct media_entity *entity,
+ 
+ 	memset(&fmt, 0, sizeof(fmt));
+ 	fmt.pad = pad;
++	fmt.stream = stream;
+ 	fmt.which = which;
+ 	fmt.format = *format;
+ 
+@@ -111,8 +114,8 @@ int v4l2_subdev_set_format(struct media_entity *entity,
+ }
+ 
+ int v4l2_subdev_get_selection(struct media_entity *entity,
+-	struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+-	enum v4l2_subdev_format_whence which)
++	struct v4l2_rect *rect, unsigned int pad, unsigned int stream,
++	unsigned int target, enum v4l2_subdev_format_whence which)
+ {
+ 	union {
+ 		struct v4l2_subdev_selection sel;
+@@ -150,8 +153,8 @@ int v4l2_subdev_get_selection(struct media_entity *entity,
+ }
+ 
+ int v4l2_subdev_set_selection(struct media_entity *entity,
+-	struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+-	enum v4l2_subdev_format_whence which)
++	struct v4l2_rect *rect, unsigned int pad, unsigned int stream,
++	unsigned int target, enum v4l2_subdev_format_whence which)
+ {
+ 	union {
+ 		struct v4l2_subdev_selection sel;
+@@ -165,6 +168,7 @@ int v4l2_subdev_set_selection(struct media_entity *entity,
+ 
+ 	memset(&u.sel, 0, sizeof(u.sel));
+ 	u.sel.pad = pad;
++	u.sel.stream = stream;
+ 	u.sel.target = target;
+ 	u.sel.which = which;
+ 	u.sel.r = *rect;
+@@ -179,6 +183,7 @@ int v4l2_subdev_set_selection(struct media_entity *entity,
+ 
+ 	memset(&u.crop, 0, sizeof(u.crop));
+ 	u.crop.pad = pad;
++	u.crop.stream = stream;
+ 	u.crop.which = which;
+ 	u.crop.rect = *rect;
+ 
+@@ -190,6 +195,69 @@ int v4l2_subdev_set_selection(struct media_entity *entity,
+ 	return 0;
+ }
+ 
++int v4l2_subdev_set_routing(struct media_entity *entity,
++			    struct v4l2_subdev_route *routes,
++			    unsigned int num_routes)
++{
++	struct v4l2_subdev_routing routing = {
++		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
++		.routes = (uintptr_t)routes,
++		.num_routes = num_routes,
++	};
++	int ret;
++
++	ret = v4l2_subdev_open(entity);
++	if (ret < 0)
++		return ret;
++
++	ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_ROUTING, &routing);
++	if (ret == -1)
++		return -errno;
++
++	return 0;
++}
++
++int v4l2_subdev_get_routing(struct media_entity *entity,
++			    struct v4l2_subdev_route **routes,
++			    unsigned int *num_routes)
++{
++	struct v4l2_subdev_routing routing = { 0 };
++	struct v4l2_subdev_route *r;
++	int ret;
++
++	ret = v4l2_subdev_open(entity);
++	if (ret < 0)
++		return ret;
++
++	routing.which = V4L2_SUBDEV_FORMAT_ACTIVE;
++
++	ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_ROUTING, &routing);
++	if (ret == -1 && errno != ENOSPC)
++		return -errno;
++
++	if (!routing.num_routes) {
++		*routes = NULL;
++		*num_routes = 0;
++		return 0;
++	}
++
++	r = calloc(routing.num_routes, sizeof(*r));
++	if (!r)
++		return -ENOMEM;
++
++	routing.routes = (uintptr_t)r;
++	ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_ROUTING, &routing);
++	if (ret) {
++		free(r);
++		return ret;
++	}
++
++	*num_routes = routing.num_routes;
++	*routes = r;
++
++	return 0;
++}
++
+ int v4l2_subdev_get_dv_timings_caps(struct media_entity *entity,
+ 	struct v4l2_dv_timings_cap *caps)
+ {
+@@ -264,7 +332,7 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity,
+ 
+ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ 				   struct v4l2_fract *interval,
+-				   unsigned int pad)
++				   unsigned int pad, unsigned int stream)
+ {
+ 	struct v4l2_subdev_frame_interval ival;
+ 	int ret;
+@@ -275,6 +343,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ 
+ 	memset(&ival, 0, sizeof(ival));
+ 	ival.pad = pad;
++	ival.stream = stream;
+ 
+ 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &ival);
+ 	if (ret < 0)
+@@ -286,7 +355,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ 
+ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ 				   struct v4l2_fract *interval,
+-				   unsigned int pad)
++				   unsigned int pad, unsigned int stream)
+ {
+ 	struct v4l2_subdev_frame_interval ival;
+ 	int ret;
+@@ -297,6 +366,7 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ 
+ 	memset(&ival, 0, sizeof(ival));
+ 	ival.pad = pad;
++	ival.stream = stream;
+ 	ival.interval = *interval;
+ 
+ 	ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
+@@ -307,6 +377,155 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ 	return 0;
+ }
+ 
++static int v4l2_subdev_parse_setup_route(struct media_device *media,
++					 struct v4l2_subdev_route *r,
++					 const char *p, char **endp)
++{
++	char *end;
++
++	/* sink pad/stream */
++
++	r->sink_pad = strtoul(p, &end, 10);
++
++	if (*end != '/') {
++		media_dbg(media, "Expected '/'\n");
++		return -EINVAL;
++	}
++
++	p = end + 1;
++
++	r->sink_stream = strtoul(p, &end, 10);
++
++	for (; isspace(*end); ++end);
++
++	if (end[0] != '-' || end[1] != '>') {
++		media_dbg(media, "Expected '->'\n");
++		return -EINVAL;
++	}
++	p = end + 2;
++
++	/* source pad/stream */
++
++	r->source_pad = strtoul(p, &end, 10);
++
++	if (*end != '/') {
++		media_dbg(media, "Expected '/'\n");
++		return -EINVAL;
++	}
++
++	p = end + 1;
++
++	r->source_stream = strtoul(p, &end, 10);
++
++	/* flags */
++
++	for (; isspace(*end); ++end);
++
++	if (*end != '[') {
++		media_dbg(media, "Expected '['\n");
++		return -EINVAL;
++	}
++
++	for (end++; isspace(*end); ++end);
++
++	p = end;
++
++	r->flags = strtoul(p, &end, 0);
++
++	if (r->flags & ~(V4L2_SUBDEV_ROUTE_FL_ACTIVE)) {
++		media_dbg(media, "Bad route flags %#x\n", r->flags);
++		return -EINVAL;
++	}
++
++	for (; isspace(*end); ++end);
++
++	if (*end != ']') {
++		media_dbg(media, "Expected ']'\n");
++		return -EINVAL;
++	}
++	end++;
++
++	*endp = end;
++
++	return 0;
++}
++
++int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p)
++{
++	struct media_entity *entity;
++	struct v4l2_subdev_route *routes;
++	unsigned int num_routes;
++	char *end;
++	int ret;
++	int i;
++
++	entity = media_parse_entity(media, p, &end);
++	if (!entity)
++		return -EINVAL;
++
++	p = end;
++
++	if (*p != '[') {
++		media_dbg(media, "Expected '['\n");
++		return -EINVAL;
++	}
++
++	p++;
++
++	routes = calloc(256, sizeof(routes[0]));
++	if (!routes)
++		return -ENOMEM;
++
++	num_routes = 0;
++
++	while (*p != 0) {
++		struct v4l2_subdev_route *r = &routes[num_routes];
++
++		ret = v4l2_subdev_parse_setup_route(media, r, p, &end);
++		if (ret)
++			goto out;
++
++		p = end;
++
++		num_routes++;
++
++		if (*p == ',') {
++			p++;
++			continue;
++		}
++
++		break;
++	}
++
++	if (*p != ']') {
++		media_dbg(media, "Expected ']'\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++	for (i = 0; i < num_routes; ++i) {
++		struct v4l2_subdev_route *r = &routes[i];
++
++		media_dbg(entity->media,
++			  "Setting up route %s : %u/%u -> %u/%u, flags 0x%8.8x\n",
++			  entity->info.name,
++			  r->sink_pad, r->sink_stream,
++			  r->source_pad, r->source_stream,
++			  r->flags);
++	}
++
++	ret = v4l2_subdev_set_routing(entity, routes, num_routes);
++	if (ret) {
++		printf("VIDIOC_SUBDEV_S_ROUTING failed: %d\n", ret);
++		goto out;
++	}
++
++out:
++	free(routes);
++
++	return ret;
++}
++
+ static int v4l2_subdev_parse_format(struct media_device *media,
+ 				    struct v4l2_mbus_framefmt *format,
+ 				    const char *p, char **endp)
+@@ -442,7 +661,8 @@ static bool strhazit(const char *str, const char **p)
+ }
+ 
+ static struct media_pad *v4l2_subdev_parse_pad_format(
+-	struct media_device *media, struct v4l2_mbus_framefmt *format,
++	struct media_device *media, unsigned int *stream,
++	struct v4l2_mbus_framefmt *format,
+ 	struct v4l2_rect *crop, struct v4l2_rect *compose,
+ 	struct v4l2_fract *interval, const char *p, char **endp)
+ {
+@@ -453,7 +673,7 @@ static struct media_pad *v4l2_subdev_parse_pad_format(
+ 
+ 	for (; isspace(*p); ++p);
+ 
+-	pad = media_parse_pad(media, p, &end);
++	pad = media_parse_pad_stream(media, p, stream, &end);
+ 	if (pad == NULL) {
+ 		*endp = end;
+ 		return NULL;
+@@ -675,6 +895,7 @@ static struct media_pad *v4l2_subdev_parse_pad_format(
+ }
+ 
+ static int set_format(struct media_pad *pad,
++		      unsigned int stream,
+ 		      struct v4l2_mbus_framefmt *format)
+ {
+ 	int ret;
+@@ -683,12 +904,12 @@ static int set_format(struct media_pad *pad,
+ 		return 0;
+ 
+ 	media_dbg(pad->entity->media,
+-		  "Setting up format %s %ux%u on pad %s/%u\n",
++		  "Setting up format %s %ux%u on pad %s/%u/%u\n",
+ 		  v4l2_subdev_pixelcode_to_string(format->code),
+ 		  format->width, format->height,
+-		  pad->entity->info.name, pad->index);
++		  pad->entity->info.name, pad->index, stream);
+ 
+-	ret = v4l2_subdev_set_format(pad->entity, format, pad->index,
++	ret = v4l2_subdev_set_format(pad->entity, format, pad->index, stream,
+ 				     V4L2_SUBDEV_FORMAT_ACTIVE);
+ 	if (ret < 0) {
+ 		media_dbg(pad->entity->media,
+@@ -705,8 +926,8 @@ static int set_format(struct media_pad *pad,
+ 	return 0;
+ }
+ 
+-static int set_selection(struct media_pad *pad, unsigned int target,
+-			 struct v4l2_rect *rect)
++static int set_selection(struct media_pad *pad, unsigned int stream,
++			 unsigned int target, struct v4l2_rect *rect)
+ {
+ 	int ret;
+ 
+@@ -714,11 +935,11 @@ static int set_selection(struct media_pad *pad, unsigned int target,
+ 		return 0;
+ 
+ 	media_dbg(pad->entity->media,
+-		  "Setting up selection target %u rectangle (%u,%u)/%ux%u on pad %s/%u\n",
++		  "Setting up selection target %u rectangle (%u,%u)/%ux%u on pad %s/%u/%u\n",
+ 		  target, rect->left, rect->top, rect->width, rect->height,
+-		  pad->entity->info.name, pad->index);
++		  pad->entity->info.name, pad->index, stream);
+ 
+-	ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index,
++	ret = v4l2_subdev_set_selection(pad->entity, rect, pad->index, stream,
+ 					target, V4L2_SUBDEV_FORMAT_ACTIVE);
+ 	if (ret < 0) {
+ 		media_dbg(pad->entity->media,
+@@ -734,7 +955,7 @@ static int set_selection(struct media_pad *pad, unsigned int target,
+ 	return 0;
+ }
+ 
+-static int set_frame_interval(struct media_pad *pad,
++static int set_frame_interval(struct media_pad *pad, unsigned int stream,
+ 			      struct v4l2_fract *interval)
+ {
+ 	int ret;
+@@ -743,11 +964,12 @@ static int set_frame_interval(struct media_pad *pad,
+ 		return 0;
+ 
+ 	media_dbg(pad->entity->media,
+-		  "Setting up frame interval %u/%u on pad %s/%u\n",
++		  "Setting up frame interval %u/%u on pad %s/%u/%u\n",
+ 		  interval->numerator, interval->denominator,
+-		  pad->entity->info.name, pad->index);
++		  pad->entity->info.name, pad->index, stream);
+ 
+-	ret = v4l2_subdev_set_frame_interval(pad->entity, interval, pad->index);
++	ret = v4l2_subdev_set_frame_interval(pad->entity, interval, pad->index,
++					     stream);
+ 	if (ret < 0) {
+ 		media_dbg(pad->entity->media,
+ 			  "Unable to set frame interval: %s (%d)",
+@@ -770,11 +992,13 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
+ 	struct v4l2_rect crop = { -1, -1, -1, -1 };
+ 	struct v4l2_rect compose = crop;
+ 	struct v4l2_fract interval = { 0, 0 };
++	unsigned int stream;
+ 	unsigned int i;
+ 	char *end;
+ 	int ret;
+ 
+-	pad = v4l2_subdev_parse_pad_format(media, &format, &crop, &compose,
++	pad = v4l2_subdev_parse_pad_format(media, &stream,
++					   &format, &crop, &compose,
+ 					   &interval, p, &end);
+ 	if (pad == NULL) {
+ 		media_print_streampos(media, p, end);
+@@ -783,30 +1007,29 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
+ 	}
+ 
+ 	if (pad->flags & MEDIA_PAD_FL_SINK) {
+-		ret = set_format(pad, &format);
++		ret = set_format(pad, stream, &format);
+ 		if (ret < 0)
+ 			return ret;
+ 	}
+ 
+-	ret = set_selection(pad, V4L2_SEL_TGT_CROP, &crop);
++	ret = set_selection(pad, stream, V4L2_SEL_TGT_CROP, &crop);
+ 	if (ret < 0)
+ 		return ret;
+ 
+-	ret = set_selection(pad, V4L2_SEL_TGT_COMPOSE, &compose);
++	ret = set_selection(pad, stream, V4L2_SEL_TGT_COMPOSE, &compose);
+ 	if (ret < 0)
+ 		return ret;
+ 
+ 	if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+-		ret = set_format(pad, &format);
++		ret = set_format(pad, stream, &format);
+ 		if (ret < 0)
+ 			return ret;
+ 	}
+ 
+-	ret = set_frame_interval(pad, &interval);
++	ret = set_frame_interval(pad, stream, &interval);
+ 	if (ret < 0)
+ 		return ret;
+ 
+-
+ 	/* If the pad is an output pad, automatically set the same format and
+ 	 * frame interval on the remote subdev input pads, if any.
+ 	 */
+@@ -821,9 +1044,9 @@ static int v4l2_subdev_parse_setup_format(struct media_device *media,
+ 			if (link->source == pad &&
+ 			    link->sink->entity->info.type == MEDIA_ENT_T_V4L2_SUBDEV) {
+ 				remote_format = format;
+-				set_format(link->sink, &remote_format);
++				set_format(link->sink, stream, &remote_format);
+ 
+-				ret = set_frame_interval(link->sink, &interval);
++				ret = set_frame_interval(link->sink, stream, &interval);
+ 				if (ret < 0 && ret != -EINVAL && ret != -ENOTTY)
+ 					return ret;
+ 			}
+diff --git a/utils/media-ctl/media-ctl.c b/utils/media-ctl/media-ctl.c
+index 84ee7a83..831136a0 100644
+--- a/utils/media-ctl/media-ctl.c
++++ b/utils/media-ctl/media-ctl.c
+@@ -28,6 +28,7 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <stdbool.h>
++#include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -75,23 +76,43 @@ static void print_flags(const struct flag_name *flag_names, unsigned int num_ent
+ 	}
+ }
+ 
++static void v4l2_subdev_print_routes(struct media_entity *entity,
++				     struct v4l2_subdev_route *routes,
++				     unsigned int num_routes)
++{
++	unsigned int i;
++
++	for (i = 0; i < num_routes; i++) {
++		const struct v4l2_subdev_route *r = &routes[i];
++
++		if (i == 0)
++			printf("\troutes:\n");
++
++		printf("\t\t%u/%u -> %u/%u [%s]\n",
++		       r->sink_pad, r->sink_stream,
++		       r->source_pad, r->source_stream,
++		       r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE ? "ACTIVE" : "INACTIVE");
++	}
++}
++
+ static void v4l2_subdev_print_format(struct media_entity *entity,
+-	unsigned int pad, enum v4l2_subdev_format_whence which)
++	unsigned int pad, unsigned int stream,
++	enum v4l2_subdev_format_whence which)
+ {
+ 	struct v4l2_mbus_framefmt format;
+ 	struct v4l2_fract interval = { 0, 0 };
+ 	struct v4l2_rect rect;
+ 	int ret;
+ 
+-	ret = v4l2_subdev_get_format(entity, &format, pad, which);
++	ret = v4l2_subdev_get_format(entity, &format, pad, stream, which);
+ 	if (ret != 0)
+ 		return;
+ 
+-	ret = v4l2_subdev_get_frame_interval(entity, &interval, pad);
++	ret = v4l2_subdev_get_frame_interval(entity, &interval, pad, stream);
+ 	if (ret != 0 && ret != -ENOTTY && ret != -EINVAL)
+ 		return;
+ 
+-	printf("\t\t[fmt:%s/%ux%u",
++	printf("\t\t[stream:%u fmt:%s/%ux%u", stream,
+ 	       v4l2_subdev_pixelcode_to_string(format.code),
+ 	       format.width, format.height);
+ 
+@@ -118,28 +139,28 @@ static void v4l2_subdev_print_format(struct media_entity *entity,
+ 			       v4l2_subdev_quantization_to_string(format.quantization));
+ 	}
+ 
+-	ret = v4l2_subdev_get_selection(entity, &rect, pad,
++	ret = v4l2_subdev_get_selection(entity, &rect, pad, stream,
+ 					V4L2_SEL_TGT_CROP_BOUNDS,
+ 					which);
+ 	if (ret == 0)
+ 		printf("\n\t\t crop.bounds:(%u,%u)/%ux%u", rect.left, rect.top,
+ 		       rect.width, rect.height);
+ 
+-	ret = v4l2_subdev_get_selection(entity, &rect, pad,
++	ret = v4l2_subdev_get_selection(entity, &rect, pad, stream,
+ 					V4L2_SEL_TGT_CROP,
+ 					which);
+ 	if (ret == 0)
+ 		printf("\n\t\t crop:(%u,%u)/%ux%u", rect.left, rect.top,
+ 		       rect.width, rect.height);
+ 
+-	ret = v4l2_subdev_get_selection(entity, &rect, pad,
++	ret = v4l2_subdev_get_selection(entity, &rect, pad, stream,
+ 					V4L2_SEL_TGT_COMPOSE_BOUNDS,
+ 					which);
+ 	if (ret == 0)
+ 		printf("\n\t\t compose.bounds:(%u,%u)/%ux%u",
+ 		       rect.left, rect.top, rect.width, rect.height);
+ 
+-	ret = v4l2_subdev_get_selection(entity, &rect, pad,
++	ret = v4l2_subdev_get_selection(entity, &rect, pad, stream,
+ 					V4L2_SEL_TGT_COMPOSE,
+ 					which);
+ 	if (ret == 0)
+@@ -455,16 +476,58 @@ static void media_print_topology_dot(struct media_device *media)
+ }
+ 
+ static void media_print_pad_text(struct media_entity *entity,
+-				 const struct media_pad *pad)
++				 const struct media_pad *pad,
++				 struct v4l2_subdev_route *routes,
++				 unsigned int num_routes)
+ {
++	unsigned int i;
++	uint64_t printed_streams_mask;
++
+ 	if (media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ 		return;
+ 
+-	v4l2_subdev_print_format(entity, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE);
+-	v4l2_subdev_print_pad_dv(entity, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE);
++	if (!routes) {
++		v4l2_subdev_print_format(entity, pad->index, 0, V4L2_SUBDEV_FORMAT_ACTIVE);
++		v4l2_subdev_print_pad_dv(entity, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE);
++
++		if (pad->flags & MEDIA_PAD_FL_SOURCE)
++			v4l2_subdev_print_subdev_dv(entity);
++
++		return;
++	}
++
++	printed_streams_mask = 0;
++
++	for (i = 0; i < num_routes; ++i) {
++		const struct v4l2_subdev_route *r = &routes[i];
++		unsigned int stream;
+ 
+-	if (pad->flags & MEDIA_PAD_FL_SOURCE)
+-		v4l2_subdev_print_subdev_dv(entity);
++		if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
++			continue;
++
++		if (pad->flags & MEDIA_PAD_FL_SINK) {
++			if (r->sink_pad != pad->index)
++				continue;
++
++			stream = r->sink_stream;
++		} else {
++			if (r->source_pad != pad->index)
++				continue;
++
++			stream = r->source_stream;
++		}
++
++		if (printed_streams_mask & (1 << stream))
++			continue;
++
++		v4l2_subdev_print_format(entity, pad->index, stream, V4L2_SUBDEV_FORMAT_ACTIVE);
++		v4l2_subdev_print_pad_dv(entity, pad->index, V4L2_SUBDEV_FORMAT_ACTIVE);
++
++		if (pad->flags & MEDIA_PAD_FL_SOURCE)
++			v4l2_subdev_print_subdev_dv(entity);
++
++		printed_streams_mask |= (1 << stream);
++	}
+ }
+ 
+ static void media_print_topology_text_entity(struct media_device *media,
+@@ -480,11 +543,17 @@ static void media_print_topology_text_entity(struct media_device *media,
+ 	unsigned int num_links = media_entity_get_links_count(entity);
+ 	unsigned int j, k;
+ 	unsigned int padding;
++	struct v4l2_subdev_route *routes = NULL;
++	unsigned int num_routes = 0;
++
++	if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV)
++		v4l2_subdev_get_routing(entity, &routes, &num_routes);
+ 
+ 	padding = printf("- entity %u: ", info->id);
+-	printf("%s (%u pad%s, %u link%s)\n", info->name,
++	printf("%s (%u pad%s, %u link%s, %u route%s)\n", info->name,
+ 	       info->pads, info->pads > 1 ? "s" : "",
+-	       num_links, num_links > 1 ? "s" : "");
++	       num_links, num_links > 1 ? "s" : "",
++	       num_routes, num_routes > 1 ? "s" : "");
+ 	printf("%*ctype %s subtype %s flags %x\n", padding, ' ',
+ 	       media_entity_type_to_string(info->type),
+ 	       media_entity_subtype_to_string(info->type),
+@@ -492,12 +561,15 @@ static void media_print_topology_text_entity(struct media_device *media,
+ 	if (devname)
+ 		printf("%*cdevice node name %s\n", padding, ' ', devname);
+ 
++	if (media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV)
++		v4l2_subdev_print_routes(entity, routes, num_routes);
++
+ 	for (j = 0; j < info->pads; j++) {
+ 		const struct media_pad *pad = media_entity_get_pad(entity, j);
+ 
+ 		printf("\tpad%u: %s\n", j, media_pad_type_to_string(pad->flags));
+ 
+-		media_print_pad_text(entity, pad);
++		media_print_pad_text(entity, pad, routes, num_routes);
+ 
+ 		for (k = 0; k < num_links; k++) {
+ 			const struct media_link *link = media_entity_get_link(entity, k);
+@@ -521,6 +593,8 @@ static void media_print_topology_text_entity(struct media_device *media,
+ 		}
+ 	}
+ 	printf("\n");
++
++	free(routes);
+ }
+ 
+ static void media_print_topology_text(struct media_device *media)
+@@ -594,14 +668,16 @@ int main(int argc, char **argv)
+ 
+ 	if (media_opts.fmt_pad) {
+ 		struct media_pad *pad;
++		unsigned int stream;
++		char *p;
+ 
+-		pad = media_parse_pad(media, media_opts.fmt_pad, NULL);
++		pad = media_parse_pad_stream(media, media_opts.fmt_pad, &stream, &p);
+ 		if (pad == NULL) {
+ 			printf("Pad '%s' not found\n", media_opts.fmt_pad);
+ 			goto out;
+ 		}
+ 
+-		v4l2_subdev_print_format(pad->entity, pad->index,
++		v4l2_subdev_print_format(pad->entity, pad->index, stream,
+ 					 V4L2_SUBDEV_FORMAT_ACTIVE);
+ 	}
+ 
+@@ -685,6 +761,15 @@ int main(int argc, char **argv)
+ 		}
+ 	}
+ 
++	if (media_opts.routes) {
++		ret = v4l2_subdev_parse_setup_routes(media, media_opts.routes);
++		if (ret) {
++			printf("Unable to setup routes: %s (%d)\n",
++			       strerror(-ret), -ret);
++			goto out;
++		}
++	}
++
+ 	if (media_opts.interactive) {
+ 		while (1) {
+ 			char buffer[32];
+diff --git a/utils/media-ctl/mediactl.h b/utils/media-ctl/mediactl.h
+index af360518..c0fc2962 100644
+--- a/utils/media-ctl/mediactl.h
++++ b/utils/media-ctl/mediactl.h
+@@ -394,6 +394,22 @@ struct media_entity *media_parse_entity(struct media_device *media,
+ struct media_pad *media_parse_pad(struct media_device *media,
+ 				  const char *p, char **endp);
+ 
++/**
++ * @brief Parse string to a pad and stream on the media device.
++ * @param media - media device.
++ * @param p - input string
++ * @param stream - pointer to uint where the stream number is stored
++ * @param endp - pointer to string where parsing ended
++ *
++ * Parse NULL terminated string describing a pad and stream and return its struct
++ * media_pad instance and the stream number.
++ *
++ * @return Pointer to struct media_pad on success, NULL on failure.
++ */
++struct media_pad *media_parse_pad_stream(struct media_device *media,
++					 const char *p, unsigned int *stream,
++					 char **endp);
++
+ /**
+  * @brief Parse string to a link on the media device.
+  * @param media - media device.
+diff --git a/utils/media-ctl/options.c b/utils/media-ctl/options.c
+index 6d30d3dc..58ddec3c 100644
+--- a/utils/media-ctl/options.c
++++ b/utils/media-ctl/options.c
+@@ -63,6 +63,7 @@ static void usage(const char *argv0)
+ 	printf("    --get-v4l2 pad	Print the active format on a given pad\n");
+ 	printf("    --get-dv pad        Print detected and current DV timings on a given pad\n");
+ 	printf("    --set-dv pad	Configure DV timings on a given pad\n");
++	printf("-R, --set-routes routes Configure routes on a given subdev entity\n");
+ 	printf("-h, --help		Show verbose help and exit\n");
+ 	printf("-i, --interactive	Modify links interactively\n");
+ 	printf("-l, --links links	Comma-separated list of link descriptors to setup\n");
+@@ -78,7 +79,7 @@ static void usage(const char *argv0)
+ 	printf("Links and formats are defined as\n");
+ 	printf("\tlinks           = link { ',' link } ;\n");
+ 	printf("\tlink            = pad '->' pad '[' flags ']' ;\n");
+-	printf("\tpad             = entity ':' pad-number ;\n");
++	printf("\tpad             = entity ':' pad-number { '/' stream-number } ;\n");
+ 	printf("\tentity          = entity-number | ( '\"' entity-name '\"' ) ;\n");
+ 	printf("\n");
+ 	printf("\tv4l2            = pad '[' v4l2-properties ']' ;\n");
+@@ -95,11 +96,16 @@ static void usage(const char *argv0)
+ 	printf("\trectangle       = '(' left ',' top, ')' '/' size ;\n");
+ 	printf("\tsize            = width 'x' height ;\n");
+ 	printf("\n");
++	printf("\troutes          = entity '[' route { ',' route } ']' ;\n");
++	printf("\troute           = pad-number '/' stream-number '->' pad-number '/' stream-number '[' route-flags ']' ;\n");
++	printf("\n");
+ 	printf("where the fields are\n");
+ 	printf("\tentity-number   Entity numeric identifier\n");
+ 	printf("\tentity-name     Entity name (string) \n");
+ 	printf("\tpad-number      Pad numeric identifier\n");
++	printf("\tstream-number   Stream numeric identifier\n");
+ 	printf("\tflags           Link flags (0: inactive, 1: active)\n");
++	printf("\troute-flags     Route flags (bitmask of route flags: active - 0x1, immutable - 0x2, source - 0x4)\n");
+ 	printf("\tfcc             Format FourCC\n");
+ 	printf("\twidth           Image width in pixels\n");
+ 	printf("\theight          Image height in pixels\n");
+@@ -152,6 +158,7 @@ static struct option opts[] = {
+ 	{"get-v4l2", 1, 0, OPT_GET_FORMAT},
+ 	{"get-dv", 1, 0, OPT_GET_DV},
+ 	{"set-dv", 1, 0, OPT_SET_DV},
++	{"set-routes", 1, 0, 'R'},
+ 	{"help", 0, 0, 'h'},
+ 	{"interactive", 0, 0, 'i'},
+ 	{"links", 1, 0, 'l'},
+@@ -237,7 +244,7 @@ int parse_cmdline(int argc, char **argv)
+ 	}
+ 
+ 	/* parse options */
+-	while ((opt = getopt_long(argc, argv, "d:e:f:hil:prvV:",
++	while ((opt = getopt_long(argc, argv, "d:e:f:hil:prvV:R:",
+ 				  opts, NULL)) != -1) {
+ 		switch (opt) {
+ 		case 'd':
+@@ -283,6 +290,10 @@ int parse_cmdline(int argc, char **argv)
+ 			media_opts.verbose = 1;
+ 			break;
+ 
++		case 'R':
++			media_opts.routes = optarg;
++			break;
++
+ 		case OPT_PRINT_DOT:
+ 			media_opts.print_dot = 1;
+ 			break;
+diff --git a/utils/media-ctl/options.h b/utils/media-ctl/options.h
+index b1751f56..8796f1b6 100644
+--- a/utils/media-ctl/options.h
++++ b/utils/media-ctl/options.h
+@@ -38,6 +38,7 @@ struct media_options
+ 	const char *fmt_pad;
+ 	const char *get_dv_pad;
+ 	const char *dv_pad;
++	const char *routes;
+ };
+ 
+ extern struct media_options media_opts;
+diff --git a/utils/media-ctl/v4l2subdev.h b/utils/media-ctl/v4l2subdev.h
+index a1813911..a8a6e7ad 100644
+--- a/utils/media-ctl/v4l2subdev.h
++++ b/utils/media-ctl/v4l2subdev.h
+@@ -64,7 +64,7 @@ void v4l2_subdev_close(struct media_entity *entity);
+  * @return 0 on success, or a negative error code on failure.
+  */
+ int v4l2_subdev_get_format(struct media_entity *entity,
+-	struct v4l2_mbus_framefmt *format, unsigned int pad,
++	struct v4l2_mbus_framefmt *format, unsigned int pad, unsigned int stream,
+ 	enum v4l2_subdev_format_whence which);
+ 
+ /**
+@@ -86,6 +86,7 @@ int v4l2_subdev_get_format(struct media_entity *entity,
+  */
+ int v4l2_subdev_set_format(struct media_entity *entity,
+ 	struct v4l2_mbus_framefmt *format, unsigned int pad,
++	unsigned int stream,
+ 	enum v4l2_subdev_format_whence which);
+ 
+ /**
+@@ -107,8 +108,8 @@ int v4l2_subdev_set_format(struct media_entity *entity,
+  * @return 0 on success, or a negative error code on failure.
+  */
+ int v4l2_subdev_get_selection(struct media_entity *entity,
+-	struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+-	enum v4l2_subdev_format_whence which);
++	struct v4l2_rect *rect, unsigned int pad, unsigned int stream,
++	unsigned int target, enum v4l2_subdev_format_whence which);
+ 
+ /**
+  * @brief Set a selection rectangle on a pad.
+@@ -129,8 +130,40 @@ int v4l2_subdev_get_selection(struct media_entity *entity,
+  * @return 0 on success, or a negative error code on failure.
+  */
+ int v4l2_subdev_set_selection(struct media_entity *entity,
+-	struct v4l2_rect *rect, unsigned int pad, unsigned int target,
+-	enum v4l2_subdev_format_whence which);
++	struct v4l2_rect *rect, unsigned int pad, unsigned int stream,
++	unsigned int target, enum v4l2_subdev_format_whence which);
++
++/**
++ * @brief Get the routing table of a subdev media entity.
++ * @param entity - subdev-device media entity.
++ * @param routes - routes of the subdev.
++ * @param num_routes - number of routes.
++ *
++ * Get the routes of @a entity and return them in an allocated array in @a routes
++ * and the number of routes in @a num_routes.
++ *
++ * The caller is responsible for freeing the routes array after use.
++ *
++ * @return 0 on success, or a negative error code on failure.
++ */
++int v4l2_subdev_get_routing(struct media_entity *entity,
++			    struct v4l2_subdev_route **routes,
++			    unsigned int *num_routes);
++
++/**
++ * @brief Set the routing table of a subdev media entity.
++ * @param entity - subdev-device media entity.
++ * @param routes - routes of the subdev.
++ * @param num_routes - number of routes.
++ *
++ * Set the routes of @a entity. The routes are given in @a routes with the
++ * length of @a num_routes.
++ *
++ * @return 0 on success, or a negative error code on failure.
++ */
++int v4l2_subdev_set_routing(struct media_entity *entity,
++			    struct v4l2_subdev_route *route,
++			    unsigned int num_routes);
+ 
+ /**
+  * @brief Query the digital video capabilities of a pad.
+@@ -200,7 +233,7 @@ int v4l2_subdev_set_dv_timings(struct media_entity *entity,
+  */
+ 
+ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+-	struct v4l2_fract *interval, unsigned int pad);
++	struct v4l2_fract *interval, unsigned int pad, unsigned int stream);
+ 
+ /**
+  * @brief Set the frame interval on a sub-device.
+@@ -217,7 +250,7 @@ int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+  * @return 0 on success, or a negative error code on failure.
+  */
+ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+-	struct v4l2_fract *interval, unsigned int pad);
++	struct v4l2_fract *interval, unsigned int pad, unsigned int stream);
+ 
+ /**
+  * @brief Parse a string and apply format, crop and frame interval settings.
+@@ -235,6 +268,17 @@ int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+  */
+ int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p);
+ 
++/**
++ * @brief Parse a string and apply route settings.
++ * @param media - media device.
++ * @param p - input string
++ *
++ * Parse string @a p and apply route settings to a subdev.
++ *
++ * @return 0 on success, or a negative error code on failure.
++ */
++int v4l2_subdev_parse_setup_routes(struct media_device *media, const char *p);
++
+ /**
+  * @brief Convert media bus pixel code to string.
+  * @param code - input string
+-- 
+2.40.0
+
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-v4l2-ctl-compliance-add-routing-and-streams-multiple.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-v4l2-ctl-compliance-add-routing-and-streams-multiple.patch
new file mode 100644
index 00000000..32eeb02a
--- /dev/null
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-v4l2-ctl-compliance-add-routing-and-streams-multiple.patch
@@ -0,0 +1,460 @@
+From 2866c81d2597f47ed976928bc9c27942bbf095f0 Mon Sep 17 00:00:00 2001
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Date: Fri, 10 Feb 2023 13:55:46 +0200
+Subject: [PATCH 3/3] v4l2-ctl/compliance: add routing and streams multiplexed
+ streams
+
+Add basic support for routing and streams.
+
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+---
+ utils/v4l2-compliance/v4l2-compliance.cpp   | 120 ++++++++++++++++----
+ utils/v4l2-compliance/v4l2-compliance.h     |   8 +-
+ utils/v4l2-compliance/v4l2-test-subdevs.cpp |  43 ++++++-
+ 3 files changed, 137 insertions(+), 34 deletions(-)
+
+diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
+index 8aebae2e..63b5fbbb 100644
+--- a/utils/v4l2-compliance/v4l2-compliance.cpp
++++ b/utils/v4l2-compliance/v4l2-compliance.cpp
+@@ -1224,6 +1224,10 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
+ 	if (node.is_subdev()) {
+ 		bool has_source = false;
+ 		bool has_sink = false;
++		struct v4l2_subdev_routing sd_routing[2] = {};
++		struct v4l2_subdev_route sd_routes[2][256] = {};
++		bool has_routes = !!(subdevcap.capabilities & V4L2_SUBDEV_CAP_STREAMS);
++		int ret;
+ 
+ 		node.frame_interval_pad = -1;
+ 		node.enum_frame_interval_pad = -1;
+@@ -1235,6 +1239,22 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
+ 		}
+ 		node.is_passthrough_subdev = has_source && has_sink;
+ 
++		if (has_routes) {
++			for (unsigned which = V4L2_SUBDEV_FORMAT_TRY;
++				which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) {
++
++				sd_routing[which].which = which;
++				sd_routing[which].routes = (__u64)sd_routes[which];
++				sd_routing[which].num_routes = 256;
++
++				ret = doioctl(&node, VIDIOC_SUBDEV_G_ROUTING, &sd_routing[which]);
++				if (ret) {
++					fail("VIDIOC_SUBDEV_G_ROUTING: failed to get routing\n");
++					sd_routing[which].num_routes = 0;
++				}
++			}
++		}
++
+ 		for (unsigned pad = 0; pad < node.entity.pads; pad++) {
+ 			printf("Sub-Device ioctls (%s Pad %u):\n",
+ 			       (node.pads[pad].flags & MEDIA_PAD_FL_SINK) ?
+@@ -1244,32 +1264,82 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
+ 			node.has_subdev_enum_fival = 0;
+ 			for (unsigned which = V4L2_SUBDEV_FORMAT_TRY;
+ 			     which <= V4L2_SUBDEV_FORMAT_ACTIVE; which++) {
+-				printf("\ttest %s VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: %s\n",
+-				       which ? "Active" : "Try",
+-				       ok(testSubDevEnum(&node, which, pad)));
+-				printf("\ttest %s VIDIOC_SUBDEV_G/S_FMT: %s\n",
+-				       which ? "Active" : "Try",
+-				       ok(testSubDevFormat(&node, which, pad)));
+-				printf("\ttest %s VIDIOC_SUBDEV_G/S_SELECTION/CROP: %s\n",
+-				       which ? "Active" : "Try",
+-				       ok(testSubDevSelection(&node, which, pad)));
+-				if (which)
+-					printf("\ttest VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: %s\n",
+-					       ok(testSubDevFrameInterval(&node, pad)));
++				struct v4l2_subdev_routing dummy_routing;
++				struct v4l2_subdev_route dummy_routes[1];
++
++				const struct v4l2_subdev_routing *routing;
++				const struct v4l2_subdev_route *routes;
++
++				if (has_routes) {
++					routing = &sd_routing[which];
++					routes = sd_routes[which];
++				} else {
++					dummy_routing.num_routes = 1;
++					dummy_routing.routes = (__u64)&dummy_routes;
++					dummy_routes[0].source_pad = pad;
++					dummy_routes[0].source_stream = 0;
++					dummy_routes[0].sink_pad = pad;
++					dummy_routes[0].sink_stream = 0;
++					dummy_routes[0].flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE;
++
++					routing = &dummy_routing;
++					routes = dummy_routes;
++				}
++
++				for (unsigned i = 0; i < routing->num_routes; ++i) {
++					const struct v4l2_subdev_route *r = &routes[i];
++					unsigned stream;
++
++					if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
++						continue;
++
++					if ((node.pads[pad].flags & MEDIA_PAD_FL_SINK) &&
++					    (r->sink_pad == pad))
++						stream = r->sink_stream;
++					else if ((node.pads[pad].flags & MEDIA_PAD_FL_SOURCE) &&
++					    (r->source_pad == pad))
++						stream = r->source_stream;
++					else
++						continue;
++
++					printf("\t%s Stream %u\n",which ? "Active" : "Try",
++					       stream);
++
++					printf("\ttest %s VIDIOC_SUBDEV_ENUM_MBUS_CODE/FRAME_SIZE/FRAME_INTERVAL: %s\n",
++					       which ? "Active" : "Try",
++					       ok(testSubDevEnum(&node, which, pad, stream)));
++					printf("\ttest %s VIDIOC_SUBDEV_G/S_FMT: %s\n",
++					       which ? "Active" : "Try",
++					       ok(testSubDevFormat(&node, which, pad, stream)));
++					printf("\ttest %s VIDIOC_SUBDEV_G/S_SELECTION/CROP: %s\n",
++					       which ? "Active" : "Try",
++					       ok(testSubDevSelection(&node, which, pad, stream)));
++					if (which)
++						printf("\ttest VIDIOC_SUBDEV_G/S_FRAME_INTERVAL: %s\n",
++						       ok(testSubDevFrameInterval(&node, pad, stream)));
++				}
++			}
++
++			/*
++			 * These tests do not make sense for subdevs with multiplexed streams,
++			 * as the try & active cases may have different routing and thus different
++			 * behavior.
++			 */
++			if (!has_routes) {
++				if (node.has_subdev_enum_code && node.has_subdev_enum_code < 3)
++					fail("VIDIOC_SUBDEV_ENUM_MBUS_CODE: try/active mismatch\n");
++				if (node.has_subdev_enum_fsize && node.has_subdev_enum_fsize < 3)
++					fail("VIDIOC_SUBDEV_ENUM_FRAME_SIZE: try/active mismatch\n");
++				if (node.has_subdev_enum_fival && node.has_subdev_enum_fival < 3)
++					fail("VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: try/active mismatch\n");
++				if (node.has_subdev_fmt && node.has_subdev_fmt < 3)
++					fail("VIDIOC_SUBDEV_G/S_FMT: try/active mismatch\n");
++				if (node.has_subdev_selection && node.has_subdev_selection < 3)
++					fail("VIDIOC_SUBDEV_G/S_SELECTION: try/active mismatch\n");
++				if (node.has_subdev_selection &&
++				    node.has_subdev_selection != node.has_subdev_fmt)
++					fail("VIDIOC_SUBDEV_G/S_SELECTION: fmt/selection mismatch\n");
+ 			}
+-			if (node.has_subdev_enum_code && node.has_subdev_enum_code < 3)
+-				fail("VIDIOC_SUBDEV_ENUM_MBUS_CODE: try/active mismatch\n");
+-			if (node.has_subdev_enum_fsize && node.has_subdev_enum_fsize < 3)
+-				fail("VIDIOC_SUBDEV_ENUM_FRAME_SIZE: try/active mismatch\n");
+-			if (node.has_subdev_enum_fival && node.has_subdev_enum_fival < 3)
+-				fail("VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: try/active mismatch\n");
+-			if (node.has_subdev_fmt && node.has_subdev_fmt < 3)
+-				fail("VIDIOC_SUBDEV_G/S_FMT: try/active mismatch\n");
+-			if (node.has_subdev_selection && node.has_subdev_selection < 3)
+-				fail("VIDIOC_SUBDEV_G/S_SELECTION: try/active mismatch\n");
+-			if (node.has_subdev_selection &&
+-			    node.has_subdev_selection != node.has_subdev_fmt)
+-				fail("VIDIOC_SUBDEV_G/S_SELECTION: fmt/selection mismatch\n");
+ 			printf("\n");
+ 		}
+ 	}
+diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h
+index e574c06c..67b3521e 100644
+--- a/utils/v4l2-compliance/v4l2-compliance.h
++++ b/utils/v4l2-compliance/v4l2-compliance.h
+@@ -373,10 +373,10 @@ int testDecoder(struct node *node);
+ 
+ // SubDev ioctl tests
+ int testSubDevCap(struct node *node);
+-int testSubDevEnum(struct node *node, unsigned which, unsigned pad);
+-int testSubDevFormat(struct node *node, unsigned which, unsigned pad);
+-int testSubDevSelection(struct node *node, unsigned which, unsigned pad);
+-int testSubDevFrameInterval(struct node *node, unsigned pad);
++int testSubDevEnum(struct node *node, unsigned which, unsigned pad, unsigned stream);
++int testSubDevFormat(struct node *node, unsigned which, unsigned pad, unsigned stream);
++int testSubDevSelection(struct node *node, unsigned which, unsigned pad, unsigned stream);
++int testSubDevFrameInterval(struct node *node, unsigned pad, unsigned stream);
+ 
+ // Buffer ioctl tests
+ int testReqBufs(struct node *node);
+diff --git a/utils/v4l2-compliance/v4l2-test-subdevs.cpp b/utils/v4l2-compliance/v4l2-test-subdevs.cpp
+index f3d85771..07192bda 100644
+--- a/utils/v4l2-compliance/v4l2-test-subdevs.cpp
++++ b/utils/v4l2-compliance/v4l2-test-subdevs.cpp
+@@ -25,7 +25,7 @@
+ 
+ #include "v4l2-compliance.h"
+ 
+-#define VALID_SUBDEV_CAPS (V4L2_SUBDEV_CAP_RO_SUBDEV)
++#define VALID_SUBDEV_CAPS (V4L2_SUBDEV_CAP_RO_SUBDEV | V4L2_SUBDEV_CAP_STREAMS)
+ 
+ int testSubDevCap(struct node *node)
+ {
+@@ -54,6 +54,7 @@ static int testSubDevEnumFrameInterval(struct node *node, unsigned which,
+ 	memset(&fie, 0, sizeof(fie));
+ 	fie.which = which;
+ 	fie.pad = pad;
++	fie.stream = 0;
+ 	fie.code = code;
+ 	fie.width = width;
+ 	fie.height = height;
+@@ -83,6 +84,7 @@ static int testSubDevEnumFrameInterval(struct node *node, unsigned which,
+ 	memset(&fie, 0xff, sizeof(fie));
+ 	fie.which = which;
+ 	fie.pad = pad;
++	fie.stream = 0;
+ 	fie.code = code;
+ 	fie.width = width;
+ 	fie.height = height;
+@@ -128,6 +130,7 @@ static int testSubDevEnumFrameSize(struct node *node, unsigned which,
+ 	memset(&fse, 0, sizeof(fse));
+ 	fse.which = which;
+ 	fse.pad = pad;
++	fse.stream = 0;
+ 	fse.code = code;
+ 	ret = doioctl(node, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &fse);
+ 	node->has_subdev_enum_fsize |= (ret != ENOTTY) << which;
+@@ -137,6 +140,7 @@ static int testSubDevEnumFrameSize(struct node *node, unsigned which,
+ 		memset(&fie, 0, sizeof(fie));
+ 		fie.which = which;
+ 		fie.pad = pad;
++		fie.stream = 0;
+ 		fie.code = code;
+ 		fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &fie) != ENOTTY);
+ 		return ret;
+@@ -152,6 +156,7 @@ static int testSubDevEnumFrameSize(struct node *node, unsigned which,
+ 	memset(&fse, 0xff, sizeof(fse));
+ 	fse.which = which;
+ 	fse.pad = pad;
++	fse.stream = 0;
+ 	fse.code = code;
+ 	fse.index = 0;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &fse));
+@@ -195,7 +200,7 @@ static int testSubDevEnumFrameSize(struct node *node, unsigned which,
+ 	return 0;
+ }
+ 
+-int testSubDevEnum(struct node *node, unsigned which, unsigned pad)
++int testSubDevEnum(struct node *node, unsigned which, unsigned pad, unsigned stream)
+ {
+ 	struct v4l2_subdev_mbus_code_enum mbus_core_enum;
+ 	unsigned num_codes;
+@@ -204,6 +209,7 @@ int testSubDevEnum(struct node *node, unsigned which, unsigned pad)
+ 	memset(&mbus_core_enum, 0, sizeof(mbus_core_enum));
+ 	mbus_core_enum.which = which;
+ 	mbus_core_enum.pad = pad;
++	mbus_core_enum.stream = stream;
+ 	ret = doioctl(node, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbus_core_enum);
+ 	node->has_subdev_enum_code |= (ret != ENOTTY) << which;
+ 	if (ret == ENOTTY) {
+@@ -214,8 +220,10 @@ int testSubDevEnum(struct node *node, unsigned which, unsigned pad)
+ 		memset(&fie, 0, sizeof(fie));
+ 		fse.which = which;
+ 		fse.pad = pad;
++		fse.stream = stream;
+ 		fie.which = which;
+ 		fie.pad = pad;
++		fie.stream = stream;
+ 		fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &fse) != ENOTTY);
+ 		fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, &fie) != ENOTTY);
+ 		return ret;
+@@ -226,16 +234,19 @@ int testSubDevEnum(struct node *node, unsigned which, unsigned pad)
+ 	mbus_core_enum.index = ~0;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbus_core_enum) != EINVAL);
+ 	mbus_core_enum.pad = node->entity.pads;
++	mbus_core_enum.stream = stream;
+ 	mbus_core_enum.index = 0;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbus_core_enum) != EINVAL);
+ 	memset(&mbus_core_enum, 0xff, sizeof(mbus_core_enum));
+ 	mbus_core_enum.which = which;
+ 	mbus_core_enum.pad = pad;
++	mbus_core_enum.stream = stream;
+ 	mbus_core_enum.index = 0;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_ENUM_MBUS_CODE, &mbus_core_enum));
+ 	fail_on_test(check_0(mbus_core_enum.reserved, sizeof(mbus_core_enum.reserved)));
+ 	fail_on_test(mbus_core_enum.code == ~0U);
+ 	fail_on_test(mbus_core_enum.pad != pad);
++	fail_on_test(mbus_core_enum.stream != stream);
+ 	fail_on_test(mbus_core_enum.index);
+ 	fail_on_test(mbus_core_enum.which != which);
+ 	do {
+@@ -252,6 +263,7 @@ int testSubDevEnum(struct node *node, unsigned which, unsigned pad)
+ 		fail_on_test(!mbus_core_enum.code);
+ 		fail_on_test(mbus_core_enum.which != which);
+ 		fail_on_test(mbus_core_enum.pad != pad);
++		fail_on_test(mbus_core_enum.stream != stream);
+ 		fail_on_test(mbus_core_enum.index != i);
+ 
+ 		ret = testSubDevEnumFrameSize(node, which, pad, mbus_core_enum.code);
+@@ -260,7 +272,7 @@ int testSubDevEnum(struct node *node, unsigned which, unsigned pad)
+ 	return 0;
+ }
+ 
+-int testSubDevFrameInterval(struct node *node, unsigned pad)
++int testSubDevFrameInterval(struct node *node, unsigned pad, unsigned stream)
+ {
+ 	struct v4l2_subdev_frame_interval fival;
+ 	struct v4l2_fract ival;
+@@ -268,6 +280,7 @@ int testSubDevFrameInterval(struct node *node, unsigned pad)
+ 
+ 	memset(&fival, 0xff, sizeof(fival));
+ 	fival.pad = pad;
++	fival.stream = stream;
+ 	ret = doioctl(node, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &fival);
+ 	if (ret == ENOTTY) {
+ 		fail_on_test(node->enum_frame_interval_pad >= 0);
+@@ -279,6 +292,7 @@ int testSubDevFrameInterval(struct node *node, unsigned pad)
+ 	node->frame_interval_pad = pad;
+ 	fail_on_test(check_0(fival.reserved, sizeof(fival.reserved)));
+ 	fail_on_test(fival.pad != pad);
++	fail_on_test(fival.stream != stream);
+ 	fail_on_test(!fival.interval.numerator);
+ 	fail_on_test(!fival.interval.denominator);
+ 	fail_on_test(fival.interval.numerator == ~0U || fival.interval.denominator == ~0U);
+@@ -290,20 +304,25 @@ int testSubDevFrameInterval(struct node *node, unsigned pad)
+ 	}
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival));
+ 	fail_on_test(fival.pad != pad);
++	fail_on_test(fival.stream != stream);
+ 	fail_on_test(ival.numerator != fival.interval.numerator);
+ 	fail_on_test(ival.denominator != fival.interval.denominator);
+ 	fail_on_test(check_0(fival.reserved, sizeof(fival.reserved)));
+ 	memset(&fival, 0, sizeof(fival));
+ 	fival.pad = pad;
++	fival.stream = stream;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &fival));
+ 	fail_on_test(fival.pad != pad);
++	fail_on_test(fival.stream != stream);
+ 	fail_on_test(ival.numerator != fival.interval.numerator);
+ 	fail_on_test(ival.denominator != fival.interval.denominator);
+ 
+ 	fival.pad = node->entity.pads;
++	fival.stream = stream;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_FRAME_INTERVAL, &fival) != EINVAL);
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival) != EINVAL);
+ 	fival.pad = pad;
++	fival.stream = stream;
+ 	fival.interval = ival;
+ 	fival.interval.numerator = 0;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &fival));
+@@ -340,7 +359,7 @@ static int checkMBusFrameFmt(struct node *node, struct v4l2_mbus_framefmt &fmt)
+ 	return 0;
+ }
+ 
+-int testSubDevFormat(struct node *node, unsigned which, unsigned pad)
++int testSubDevFormat(struct node *node, unsigned which, unsigned pad, unsigned stream)
+ {
+ 	struct v4l2_subdev_format fmt;
+ 	struct v4l2_subdev_format s_fmt;
+@@ -349,6 +368,7 @@ int testSubDevFormat(struct node *node, unsigned which, unsigned pad)
+ 	memset(&fmt, 0, sizeof(fmt));
+ 	fmt.which = which;
+ 	fmt.pad = pad;
++	fmt.stream = stream;
+ 	ret = doioctl(node, VIDIOC_SUBDEV_G_FMT, &fmt);
+ 	node->has_subdev_fmt |= (ret != ENOTTY) << which;
+ 	if (ret == ENOTTY) {
+@@ -359,14 +379,17 @@ int testSubDevFormat(struct node *node, unsigned which, unsigned pad)
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_FMT, &fmt) != EINVAL);
+ 	fmt.which = 0;
+ 	fmt.pad = node->entity.pads;
++	fmt.stream = stream;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_FMT, &fmt) != EINVAL);
+ 	memset(&fmt, 0xff, sizeof(fmt));
+ 	fmt.which = which;
+ 	fmt.pad = pad;
++	fmt.stream = stream;
+ 	fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_FMT, &fmt));
+ 	fail_on_test(check_0(fmt.reserved, sizeof(fmt.reserved)));
+ 	fail_on_test(fmt.which != which);
+ 	fail_on_test(fmt.pad != pad);
++	fail_on_test(fmt.stream != stream);
+ 	fail_on_test(checkMBusFrameFmt(node, fmt.format));
+ 	s_fmt = fmt;
+ 	memset(s_fmt.reserved, 0xff, sizeof(s_fmt.reserved));
+@@ -379,6 +402,7 @@ int testSubDevFormat(struct node *node, unsigned which, unsigned pad)
+ 	fail_on_test(ret && ret != ENOTTY);
+ 	fail_on_test(s_fmt.which != which);
+ 	fail_on_test(s_fmt.pad != pad);
++	fail_on_test(s_fmt.stream != stream);
+ 	if (ret) {
+ 		warn("VIDIOC_SUBDEV_G_FMT is supported but not VIDIOC_SUBDEV_S_FMT\n");
+ 		return 0;
+@@ -423,7 +447,7 @@ static target_info targets[] = {
+ 	{ ~0U },
+ };
+ 
+-int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
++int testSubDevSelection(struct node *node, unsigned which, unsigned pad, unsigned stream)
+ {
+ 	struct v4l2_subdev_selection sel;
+ 	struct v4l2_subdev_selection s_sel;
+@@ -435,10 +459,12 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 	targets[V4L2_SEL_TGT_NATIVE_SIZE].readonly = is_sink;
+ 	memset(&crop, 0, sizeof(crop));
+ 	crop.pad = pad;
++	crop.stream = stream;
+ 	crop.which = which;
+ 	memset(&sel, 0, sizeof(sel));
+ 	sel.which = which;
+ 	sel.pad = pad;
++	sel.stream = stream;
+ 	sel.target = V4L2_SEL_TGT_CROP;
+ 	ret = doioctl(node, VIDIOC_SUBDEV_G_SELECTION, &sel);
+ 	node->has_subdev_selection |= (ret != ENOTTY) << which;
+@@ -451,6 +477,7 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 	fail_on_test(check_0(crop.reserved, sizeof(crop.reserved)));
+ 	fail_on_test(crop.which != which);
+ 	fail_on_test(crop.pad != pad);
++	fail_on_test(crop.stream != stream);
+ 	fail_on_test(memcmp(&crop.rect, &sel.r, sizeof(sel.r)));
+ 
+ 	for (unsigned tgt = 0; targets[tgt].target != ~0U; tgt++) {
+@@ -458,6 +485,7 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 		memset(&sel, 0xff, sizeof(sel));
+ 		sel.which = which;
+ 		sel.pad = pad;
++		sel.stream = stream;
+ 		sel.target = tgt;
+ 		ret = doioctl(node, VIDIOC_SUBDEV_G_SELECTION, &sel);
+ 		targets[tgt].found = !ret;
+@@ -469,6 +497,7 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 		fail_on_test(check_0(sel.reserved, sizeof(sel.reserved)));
+ 		fail_on_test(sel.which != which);
+ 		fail_on_test(sel.pad != pad);
++		fail_on_test(sel.stream != stream);
+ 		fail_on_test(sel.target != tgt);
+ 		fail_on_test(!sel.r.width);
+ 		fail_on_test(sel.r.width == ~0U);
+@@ -480,9 +509,11 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 		fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_SELECTION, &sel) != EINVAL);
+ 		sel.which = 0;
+ 		sel.pad = node->entity.pads;
++		sel.stream = stream;
+ 		fail_on_test(doioctl(node, VIDIOC_SUBDEV_G_SELECTION, &sel) != EINVAL);
+ 		sel.which = which;
+ 		sel.pad = pad;
++		sel.stream = stream;
+ 		s_sel = sel;
+ 		memset(s_sel.reserved, 0xff, sizeof(s_sel.reserved));
+ 		ret = doioctl(node, VIDIOC_SUBDEV_S_SELECTION, &s_sel);
+@@ -496,6 +527,7 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 				fail_on_test(check_0(crop.reserved, sizeof(crop.reserved)));
+ 				fail_on_test(crop.which != which);
+ 				fail_on_test(crop.pad != pad);
++				fail_on_test(crop.stream != stream);
+ 				fail_on_test(memcmp(&crop.rect, &sel.r, sizeof(sel.r)));
+ 			}
+ 		}
+@@ -504,6 +536,7 @@ int testSubDevSelection(struct node *node, unsigned which, unsigned pad)
+ 		fail_on_test(!ret && targets[tgt].readonly);
+ 		fail_on_test(s_sel.which != which);
+ 		fail_on_test(s_sel.pad != pad);
++		fail_on_test(s_sel.stream != stream);
+ 		if (ret && !targets[tgt].readonly && tgt != V4L2_SEL_TGT_NATIVE_SIZE)
+ 			warn("VIDIOC_SUBDEV_G_SELECTION is supported for target %u but not VIDIOC_SUBDEV_S_SELECTION\n", tgt);
+ 		if (ret)
+-- 
+2.40.0
+
diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
index 21a08022..1c157ed5 100644
--- a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
+++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
@@ -31,6 +31,10 @@ SRC_URI = "\
     file://0002-original-patch-mediactl-pkgconfig.patch \
     file://0003-original-patch-export-mediactl-headers.patch \
     file://0004-Do-not-use-getsubopt.patch \
+    file://0001-v4l2-ctl-Add-routing-and-streams-support.patch \
+    file://0002-media-ctl-add-support-for-routes-and-streams.patch \
+    file://0003-v4l2-ctl-compliance-add-routing-and-streams-multiple.patch \
+    file://0001-media-ctl-add-support-for-RGBIr-bayer-formats.patch \
 "
 
 SRCREV = "9431e4b26b4842d1401e80ada9f14593dca3a94c"
-- 
2.40.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
  2023-05-23  9:44 [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Jai Luthra
  2023-05-23  9:44 ` [master/kirkstone][RESEND PATCH 2/2] v4l-utils: Add multistream and RGB-IR support Jai Luthra
@ 2023-05-23 11:48 ` Devarsh Thakkar
  2023-05-23 13:18   ` Jai Luthra
  2023-05-23 15:36   ` Ryan Eatmon
  1 sibling, 2 replies; 8+ messages in thread
From: Devarsh Thakkar @ 2023-05-23 11:48 UTC (permalink / raw)
  To: Jai Luthra, meta-arago
  Cc: Ryan Eatmon, Denys Dmytriyenko, Gyan Gupta,
	Sai Sree Kartheek Adivi, Rahul T R, Bajjuri, Praneeth,
	Raghavendra, Vignesh, Bhatia, Aradhya, Nori, Sekhar, Khasim,
	Syed Mohammed

Hi Jai,

Thanks for the patch.

On 23/05/23 15:14, Jai Luthra wrote:
> An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
> layer for kirkstone.
> 
> TI's 6.1 based kernel has backported multistream routing APIs [1] from
> upstream kernel, which requires a few patches to v4l-utils [2] that only
> apply cleanly on top of v1.23.0.
> 
> Thus we override the recipe in this layer to the latest (v1.23.0) found
> from meta-oe master.
> 
> Link: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
> Link: https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
> Signed-off-by: Jai Luthra <j-luthra@ti.com>
> ---
>  ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
>  ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
>  ...iginal-patch-export-mediactl-headers.patch | 24 +++++
>  .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
>  .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++

As per my opinion, not a good idea to bump up package version than default
package version shipped by kirkstone i.e. 1.22.1
(meta-oe/recipes-multimedia/v4l2apps/v4l-utils_1.22.1.bb)

As a general rule of thumb, there could be other layers (for e.g. added by
vendors) having bbappends assuming shipped package version same as in
kirkstone and also build time and runtime dependencies w.r.t other packages
are guaranted if all packages stay with same version as shipped by kirkstone
and with this new recipe I believe we are kind of deviating from that
protection and so my suggestion is to rebase on top of existing package
version i.e. 1.22.1

Regards
Devarsh

>  5 files changed, 236 insertions(+)
>  create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>  create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>  create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>  create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>  create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb


> 
> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
> new file mode 100644
> index 00000000..8ac8fbe1
> --- /dev/null
> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
> @@ -0,0 +1,44 @@
> +From 0d5c0e9a75eca43667b0e29155b635e50622b66a Mon Sep 17 00:00:00 2001
> +From: Khem Raj <raj.khem@gmail.com>
> +Date: Fri, 27 Feb 2015 21:55:36 +0000
> +Subject: [PATCH] Revert "media-ctl: Don't install libmediactl and
> +
> + libv4l2subdev"
> +
> +This reverts commit 0911dce53b08b0df3066be2c75f67e8a314d8729.
> +
> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
> +
> +Conflicts:
> +	utils/media-ctl/Makefile.am
> +
> +---
> + utils/media-ctl/Makefile.am | 10 +++-------
> + 1 file changed, 3 insertions(+), 7 deletions(-)
> +
> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
> +index c48c8d6..e255e16 100644
> +--- a/utils/media-ctl/Makefile.am
> ++++ b/utils/media-ctl/Makefile.am
> +@@ -1,8 +1,7 @@
> +-noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
> +-
> ++lib_LTLIBRARIES = libmediactl.la libv4l2subdev.la
> + libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
> +-libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
> +-libmediactl_la_LDFLAGS = -static $(LIBUDEV_LIBS)
> ++libmediactl_la_CFLAGS = $(LIBUDEV_CFLAGS)
> ++libmediactl_la_LDFLAGS = $(LIBUDEV_LIBS)
> + 
> + media-bus-format-names.h: ../../include/linux/media-bus-format.h
> + 	$(AM_V_GEN) sed -e '/#define MEDIA_BUS_FMT/ ! d; s/.*FMT_//; /FIXED/ d; s/\t.*//; s/.*/{ \"&\", MEDIA_BUS_FMT_& },/;' \
> +@@ -18,9 +17,6 @@ CLEANFILES = $(BUILT_SOURCES)
> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
> + libv4l2subdev_la_LIBADD = libmediactl.la
> +-libv4l2subdev_la_CFLAGS = -static
> +-libv4l2subdev_la_LDFLAGS = -static
> +-
> + mediactl_includedir=$(includedir)/mediactl
> + noinst_HEADERS = mediactl.h v4l2subdev.h
> + 
> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
> new file mode 100644
> index 00000000..52fc2d7a
> --- /dev/null
> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
> @@ -0,0 +1,21 @@
> +From 320b8378ee30eb5e0fe83a8b397f822f2f88a4c1 Mon Sep 17 00:00:00 2001
> +From: Khem Raj <raj.khem@gmail.com>
> +Date: Sun, 1 Mar 2015 22:25:07 +0000
> +Subject: [PATCH] %% original patch: mediactl-pkgconfig.patch
> +
> +---
> + utils/media-ctl/Makefile.am | 1 +
> + 1 file changed, 1 insertion(+)
> +
> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
> +index e255e16..ff7b417 100644
> +--- a/utils/media-ctl/Makefile.am
> ++++ b/utils/media-ctl/Makefile.am
> +@@ -20,6 +20,7 @@ libv4l2subdev_la_LIBADD = libmediactl.la
> + mediactl_includedir=$(includedir)/mediactl
> + noinst_HEADERS = mediactl.h v4l2subdev.h
> + 
> ++pkgconfig_DATA = libmediactl.pc
> + bin_PROGRAMS = media-ctl
> + media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
> + media_ctl_LDADD = libmediactl.la libv4l2subdev.la
> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
> new file mode 100644
> index 00000000..39dc3383
> --- /dev/null
> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
> @@ -0,0 +1,24 @@
> +From f7109d6b2fcb291824d795071c04a492d9fbc45b Mon Sep 17 00:00:00 2001
> +From: Khem Raj <raj.khem@gmail.com>
> +Date: Sun, 1 Mar 2015 22:25:07 +0000
> +Subject: [PATCH] %% original patch: export-mediactl-headers.patch
> +
> +---
> + utils/media-ctl/Makefile.am | 4 ++--
> + 1 file changed, 2 insertions(+), 2 deletions(-)
> +
> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
> +index ff7b417..6ce656f 100644
> +--- a/utils/media-ctl/Makefile.am
> ++++ b/utils/media-ctl/Makefile.am
> +@@ -17,8 +17,8 @@ CLEANFILES = $(BUILT_SOURCES)
> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
> + libv4l2subdev_la_LIBADD = libmediactl.la
> +-mediactl_includedir=$(includedir)/mediactl
> +-noinst_HEADERS = mediactl.h v4l2subdev.h
> ++otherincludedir = $(includedir)/mediactl
> ++otherinclude_HEADERS = mediactl.h v4l2subdev.h
> + 
> + pkgconfig_DATA = libmediactl.pc
> + bin_PROGRAMS = media-ctl
> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
> new file mode 100644
> index 00000000..fb844acb
> --- /dev/null
> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
> @@ -0,0 +1,60 @@
> +From 6e7e52de7afe29597016952a7317faf9c3ea3268 Mon Sep 17 00:00:00 2001
> +From: Khem Raj <raj.khem@gmail.com>
> +Date: Sat, 30 Nov 2019 18:50:34 -0800
> +Subject: [PATCH] Do not use getsubopt
> +
> +POSIX says that behavior when subopts list is empty is undefined.
> +musl libs will set value to NULL which leads to crash.
> +
> +Simply avoid getsubopt, since we cannot rely on it.
> +
> +Imported from Alpine Linux
> +
> +Upstream-Status: Pending
> +
> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
> +
> +Adapt patch to 1.23.0.
> +
> +(v4l-utils rev fd544473800d02e90bc289434cc44e5aa8fadd0f).
> +
> +%% original patch: 0007-Do-not-use-getsubopt.patch
> +
> +Signed-off-by: Daniel Gomez <daniel@qtec.com>
> +---
> + utils/v4l2-ctl/v4l2-ctl-common.cpp | 18 ++++++++++--------
> + 1 file changed, 10 insertions(+), 8 deletions(-)
> +
> +diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp
> +index d77f7104..838c297d 100644
> +--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
> ++++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
> +@@ -994,15 +994,17 @@ static bool parse_subset(char *optarg)
> + 
> + static bool parse_next_subopt(char **subs, char **value)
> + {
> +-	static char *const subopts[] = {
> +-	    nullptr
> +-	};
> +-	int opt = v4l_getsubopt(subs, subopts, value);
> ++	char *p = *subs;
> ++	*value = *subs;
> + 
> +-	if (opt < 0 || *value)
> +-		return false;
> +-	fprintf(stderr, "Missing suboption value\n");
> +-	return true;
> ++	while (*p && *p != ',')
> ++		p++;
> ++
> ++	if (*p)
> ++		*p++ = '\0';
> ++
> ++	*subs = p;
> ++	return false;
> + }
> + 
> + void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
> +-- 
> +2.35.1
> +
> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
> new file mode 100644
> index 00000000..21a08022
> --- /dev/null
> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
> @@ -0,0 +1,87 @@
> +SUMMARY = "v4l2 and IR applications"
> +LICENSE = "GPL-2.0-only & LGPL-2.1-only"
> +LIC_FILES_CHKSUM = "file://COPYING;md5=48da9957849056017dc568bbc43d8975 \
> +                    file://COPYING.libv4l;md5=d749e86a105281d7a44c2328acebc4b0"
> +PROVIDES = "libv4l media-ctl"
> +
> +DEPENDS = "jpeg \
> +           ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'virtual/libx11', '', d)} \
> +           ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \
> +           ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa-lib', '', d)} \
> +           ${@bb.utils.contains_any('PACKAGECONFIG', 'qv4l2 qvidcap', 'qtbase qtbase-native', '', d)}"
> +
> +DEPENDS:append:libc-musl = " argp-standalone"
> +DEPENDS:append:class-target = " udev"
> +LDFLAGS:append = " -pthread"
> +# v4l2 explicitly sets _FILE_OFFSET_BITS=32 to get access to
> +# both 32 and 64 bit file APIs.  But it does not handle the time side?
> +# Needs further investigation
> +GLIBC_64BIT_TIME_FLAGS = ""
> +
> +inherit autotools gettext pkgconfig
> +
> +PACKAGECONFIG ??= "media-ctl"
> +PACKAGECONFIG[media-ctl] = "--enable-v4l-utils,--disable-v4l-utils,,"
> +PACKAGECONFIG[qv4l2] = ",--disable-qv4l2"
> +PACKAGECONFIG[qvidcap] = ",--disable-qvidcap"
> +
> +SRC_URI = "\
> +    git://git.linuxtv.org/v4l-utils.git;protocol=https;branch=master \
> +    file://0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch \
> +    file://0002-original-patch-mediactl-pkgconfig.patch \
> +    file://0003-original-patch-export-mediactl-headers.patch \
> +    file://0004-Do-not-use-getsubopt.patch \
> +"
> +
> +SRCREV = "9431e4b26b4842d1401e80ada9f14593dca3a94c"
> +
> +PV .= "+git${SRCPV}"
> +
> +S = "${WORKDIR}/git"
> +
> +do_configure:prepend() {
> +    cd ${S}; ./bootstrap.sh; cd -
> +}
> +
> +EXTRA_OECONF = "--enable-shared --with-udevdir=${base_libdir}/udev \
> +                --disable-v4l2-compliance-32 --disable-v4l2-ctl-32"
> +
> +VIRTUAL-RUNTIME_ir-keytable-keymaps ?= "rc-keymaps"
> +
> +PACKAGES =+ "media-ctl ir-keytable rc-keymaps libv4l libv4l-dev qv4l2 qvidcap"
> +
> +RPROVIDES:${PN}-dbg += "libv4l-dbg"
> +
> +FILES:media-ctl = "${bindir}/media-ctl ${libdir}/libmediactl.so.*"
> +FILES:qv4l2 = "\
> +    ${bindir}/qv4l2 \
> +    ${datadir}/applications/qv4l2.desktop \
> +    ${datadir}/icons/hicolor/*/apps/qv4l2.* \
> +"
> +FILES:qvidcap = "\
> +    ${bindir}/qvidcap \
> +    ${datadir}/applications/qvidcap.desktop \
> +    ${datadir}/icons/hicolor/*/apps/qvidcap.* \
> +"
> +
> +FILES:ir-keytable = "${bindir}/ir-keytable ${base_libdir}/udev/rules.d/*-infrared.rules"
> +RDEPENDS:ir-keytable += "${VIRTUAL-RUNTIME_ir-keytable-keymaps}"
> +RDEPENDS:qv4l2 += "\
> +    ${@bb.utils.contains('PACKAGECONFIG', 'qv4l2', 'qtbase', '', d)}"
> +RDEPENDS:qvidcap += "\
> +    ${@bb.utils.contains('PACKAGECONFIG', 'qvidcap', 'qtbase', '', d)}"
> +
> +FILES:rc-keymaps = "${sysconfdir}/rc* ${base_libdir}/udev/rc*"
> +
> +FILES:${PN} = "${bindir} ${sbindir}"
> +
> +FILES:libv4l += "${libdir}/libv4l*${SOLIBS} ${libdir}/libv4l/*.so ${libdir}/libv4l/plugins/*.so \
> +                 ${libdir}/libdvbv5*${SOLIBS} \
> +                 ${libdir}/libv4l/*-decomp"
> +
> +FILES:libv4l-dev += "${includedir} ${libdir}/pkgconfig \
> +                     ${libdir}/libv4l*${SOLIBSDEV} ${libdir}/*.la \
> +                     ${libdir}/v4l*${SOLIBSDEV} ${libdir}/libv4l/*.la ${libdir}/libv4l/plugins/*.la"
> +
> +PARALLEL_MAKE:class-native = ""
> +BBCLASSEXTEND = "native"


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
  2023-05-23 11:48 ` [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Devarsh Thakkar
@ 2023-05-23 13:18   ` Jai Luthra
  2023-05-24 12:41     ` Devarsh Thakkar
  2023-05-23 15:36   ` Ryan Eatmon
  1 sibling, 1 reply; 8+ messages in thread
From: Jai Luthra @ 2023-05-23 13:18 UTC (permalink / raw)
  To: Devarsh Thakkar
  Cc: meta-arago, Ryan Eatmon, Denys Dmytriyenko, Gyan Gupta,
	Sai Sree Kartheek Adivi, Rahul T R, Bajjuri, Praneeth,
	Raghavendra, Vignesh, Bhatia, Aradhya, Nori, Sekhar, Khasim,
	Syed Mohammed

[-- Attachment #1: Type: text/plain, Size: 3592 bytes --]

Hi Devarsh,

Thanks for the review,

On May 23, 2023 at 17:18:39 +0530, Devarsh Thakkar wrote:
> Hi Jai,
> 
> Thanks for the patch.
> 
> On 23/05/23 15:14, Jai Luthra wrote:
> > An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
> > layer for kirkstone.
> > 
> > TI's 6.1 based kernel has backported multistream routing APIs [1] from
> > upstream kernel, which requires a few patches to v4l-utils [2] that only
> > apply cleanly on top of v1.23.0.
> > 
> > Thus we override the recipe in this layer to the latest (v1.23.0) found
> > from meta-oe master.
> > 
> > Link: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
> > Link: https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
> > Signed-off-by: Jai Luthra <j-luthra@ti.com>
> > ---
> >  ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
> >  ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
> >  ...iginal-patch-export-mediactl-headers.patch | 24 +++++
> >  .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
> >  .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++
> 
> As per my opinion, not a good idea to bump up package version than default
> package version shipped by kirkstone i.e. 1.22.1
> (meta-oe/recipes-multimedia/v4l2apps/v4l-utils_1.22.1.bb)
> 
> As a general rule of thumb, there could be other layers (for e.g. added by
> vendors) having bbappends assuming shipped package version same as in
> kirkstone and also build time and runtime dependencies w.r.t other packages
> are guaranted if all packages stay with same version as shipped by kirkstone
> and with this new recipe I believe we are kind of deviating from that
> protection and so my suggestion is to rebase on top of existing package
> version i.e. 1.22.1

I agree that it makes sense to keep packages pinned to a version for a 
particular release (dunfell/kirkstone) for stability and compatibility 
with other dependencies.

The only issue here is multi-stream support requires a large chunk of 
changes to v4l2 userspace APIs, affecting the most commonly used tools 
for setting up the camera pipeline (media-ctl) and capturing frames 
(v4l2-ctl).

While these changes are merged in linux upstream and backported to TI's 
6.1 branch, the corresponding v4l-utils changes are still under review 
upstream.

There are two options I see here:


    1. We bump up the v4l-utils recipe in our distribution to a 
    relatively recent git commit (v1.23.0-9431e4b26b) which is in sync 
    with TI baseline kernel, and apply only the patches for the extra 
    features TI uses on top.

    We also ensure it works well with the dependencies (mainly libc) 
    provided by rest of the kirkstone layers (so far no issues seen in 
    my tests)


    2. We backport these patches to v1.22.1, which was tagged almost 
    **two years ago** in Oct 2021; while the kernel is on 6.1 (Jan 2023) 
    and using multistream APIs from 6.3/6.4/still-under-review.

    We will also have to sync with the latest kernel headers and 
    extensively test that we don't break some ioctl or are missing 
    bugfixes to v4l-utils from the past two years, as the kernel 
    developer(s) for the newer features would not have tested against 
    the old release.


That's why I chose option 1 in the current series as an exception to the 
thumb rule. Let me know if it is a complete no-go to override a recipe 
here.

> 
> Regards
> Devarsh

Thanks,
Jai

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
  2023-05-23 11:48 ` [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Devarsh Thakkar
  2023-05-23 13:18   ` Jai Luthra
@ 2023-05-23 15:36   ` Ryan Eatmon
  2023-05-24 11:14     ` Devarsh Thakkar
  1 sibling, 1 reply; 8+ messages in thread
From: Ryan Eatmon @ 2023-05-23 15:36 UTC (permalink / raw)
  To: Devarsh Thakkar, Jai Luthra, meta-arago
  Cc: Denys Dmytriyenko, Gyan Gupta, Sai Sree Kartheek Adivi,
	Rahul T R, Bajjuri, Praneeth, Raghavendra, Vignesh, Bhatia,
	Aradhya, Nori, Sekhar, Khasim, Syed Mohammed



On 5/23/2023 6:48 AM, Devarsh Thakkar wrote:
> Hi Jai,
> 
> Thanks for the patch.
> 
> On 23/05/23 15:14, Jai Luthra wrote:
>> An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
>> layer for kirkstone.
>>
>> TI's 6.1 based kernel has backported multistream routing APIs [1] from
>> upstream kernel, which requires a few patches to v4l-utils [2] that only
>> apply cleanly on top of v1.23.0.
>>
>> Thus we override the recipe in this layer to the latest (v1.23.0) found
>> from meta-oe master.
>>
>> Link: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
>> Link: https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
>> Signed-off-by: Jai Luthra <j-luthra@ti.com>
>> ---
>>   ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
>>   ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
>>   ...iginal-patch-export-mediactl-headers.patch | 24 +++++
>>   .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
>>   .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++
> 
> As per my opinion, not a good idea to bump up package version than default
> package version shipped by kirkstone i.e. 1.22.1
> (meta-oe/recipes-multimedia/v4l2apps/v4l-utils_1.22.1.bb)
> 
> As a general rule of thumb, there could be other layers (for e.g. added by
> vendors) having bbappends assuming shipped package version same as in
> kirkstone and also build time and runtime dependencies w.r.t other packages
> are guaranted if all packages stay with same version as shipped by kirkstone
> and with this new recipe I believe we are kind of deviating from that
> protection and so my suggestion is to rebase on top of existing package
> version i.e. 1.22.1

If you were talking about meta-ti then I would 100% agree with you, but 
this is meta-arago.  And as a distribution layer, we are perfectly 
within our purvue to advance to a later version of a tool beyond what 
the other upstream repos are at, or change config files, etc...

Meta-ti as a BSP layer needs to play nice in the sandbox with other 
layers and not change versions without guards.

If you wanted to be extra careful you could include the guards in arago 
as well, but since arago is not a yocto compliant layer it is not 
strictly needed at this time.


> Regards
> Devarsh
> 
>>   5 files changed, 236 insertions(+)
>>   create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>   create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>   create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>   create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>   create mode 100644 meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
> 
> 
>>
>> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>> new file mode 100644
>> index 00000000..8ac8fbe1
>> --- /dev/null
>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>> @@ -0,0 +1,44 @@
>> +From 0d5c0e9a75eca43667b0e29155b635e50622b66a Mon Sep 17 00:00:00 2001
>> +From: Khem Raj <raj.khem@gmail.com>
>> +Date: Fri, 27 Feb 2015 21:55:36 +0000
>> +Subject: [PATCH] Revert "media-ctl: Don't install libmediactl and
>> +
>> + libv4l2subdev"
>> +
>> +This reverts commit 0911dce53b08b0df3066be2c75f67e8a314d8729.
>> +
>> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
>> +
>> +Conflicts:
>> +	utils/media-ctl/Makefile.am
>> +
>> +---
>> + utils/media-ctl/Makefile.am | 10 +++-------
>> + 1 file changed, 3 insertions(+), 7 deletions(-)
>> +
>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>> +index c48c8d6..e255e16 100644
>> +--- a/utils/media-ctl/Makefile.am
>> ++++ b/utils/media-ctl/Makefile.am
>> +@@ -1,8 +1,7 @@
>> +-noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
>> +-
>> ++lib_LTLIBRARIES = libmediactl.la libv4l2subdev.la
>> + libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
>> +-libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
>> +-libmediactl_la_LDFLAGS = -static $(LIBUDEV_LIBS)
>> ++libmediactl_la_CFLAGS = $(LIBUDEV_CFLAGS)
>> ++libmediactl_la_LDFLAGS = $(LIBUDEV_LIBS)
>> +
>> + media-bus-format-names.h: ../../include/linux/media-bus-format.h
>> + 	$(AM_V_GEN) sed -e '/#define MEDIA_BUS_FMT/ ! d; s/.*FMT_//; /FIXED/ d; s/\t.*//; s/.*/{ \"&\", MEDIA_BUS_FMT_& },/;' \
>> +@@ -18,9 +17,6 @@ CLEANFILES = $(BUILT_SOURCES)
>> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
>> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
>> + libv4l2subdev_la_LIBADD = libmediactl.la
>> +-libv4l2subdev_la_CFLAGS = -static
>> +-libv4l2subdev_la_LDFLAGS = -static
>> +-
>> + mediactl_includedir=$(includedir)/mediactl
>> + noinst_HEADERS = mediactl.h v4l2subdev.h
>> +
>> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>> new file mode 100644
>> index 00000000..52fc2d7a
>> --- /dev/null
>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>> @@ -0,0 +1,21 @@
>> +From 320b8378ee30eb5e0fe83a8b397f822f2f88a4c1 Mon Sep 17 00:00:00 2001
>> +From: Khem Raj <raj.khem@gmail.com>
>> +Date: Sun, 1 Mar 2015 22:25:07 +0000
>> +Subject: [PATCH] %% original patch: mediactl-pkgconfig.patch
>> +
>> +---
>> + utils/media-ctl/Makefile.am | 1 +
>> + 1 file changed, 1 insertion(+)
>> +
>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>> +index e255e16..ff7b417 100644
>> +--- a/utils/media-ctl/Makefile.am
>> ++++ b/utils/media-ctl/Makefile.am
>> +@@ -20,6 +20,7 @@ libv4l2subdev_la_LIBADD = libmediactl.la
>> + mediactl_includedir=$(includedir)/mediactl
>> + noinst_HEADERS = mediactl.h v4l2subdev.h
>> +
>> ++pkgconfig_DATA = libmediactl.pc
>> + bin_PROGRAMS = media-ctl
>> + media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
>> + media_ctl_LDADD = libmediactl.la libv4l2subdev.la
>> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>> new file mode 100644
>> index 00000000..39dc3383
>> --- /dev/null
>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>> @@ -0,0 +1,24 @@
>> +From f7109d6b2fcb291824d795071c04a492d9fbc45b Mon Sep 17 00:00:00 2001
>> +From: Khem Raj <raj.khem@gmail.com>
>> +Date: Sun, 1 Mar 2015 22:25:07 +0000
>> +Subject: [PATCH] %% original patch: export-mediactl-headers.patch
>> +
>> +---
>> + utils/media-ctl/Makefile.am | 4 ++--
>> + 1 file changed, 2 insertions(+), 2 deletions(-)
>> +
>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>> +index ff7b417..6ce656f 100644
>> +--- a/utils/media-ctl/Makefile.am
>> ++++ b/utils/media-ctl/Makefile.am
>> +@@ -17,8 +17,8 @@ CLEANFILES = $(BUILT_SOURCES)
>> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
>> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
>> + libv4l2subdev_la_LIBADD = libmediactl.la
>> +-mediactl_includedir=$(includedir)/mediactl
>> +-noinst_HEADERS = mediactl.h v4l2subdev.h
>> ++otherincludedir = $(includedir)/mediactl
>> ++otherinclude_HEADERS = mediactl.h v4l2subdev.h
>> +
>> + pkgconfig_DATA = libmediactl.pc
>> + bin_PROGRAMS = media-ctl
>> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>> new file mode 100644
>> index 00000000..fb844acb
>> --- /dev/null
>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>> @@ -0,0 +1,60 @@
>> +From 6e7e52de7afe29597016952a7317faf9c3ea3268 Mon Sep 17 00:00:00 2001
>> +From: Khem Raj <raj.khem@gmail.com>
>> +Date: Sat, 30 Nov 2019 18:50:34 -0800
>> +Subject: [PATCH] Do not use getsubopt
>> +
>> +POSIX says that behavior when subopts list is empty is undefined.
>> +musl libs will set value to NULL which leads to crash.
>> +
>> +Simply avoid getsubopt, since we cannot rely on it.
>> +
>> +Imported from Alpine Linux
>> +
>> +Upstream-Status: Pending
>> +
>> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
>> +
>> +Adapt patch to 1.23.0.
>> +
>> +(v4l-utils rev fd544473800d02e90bc289434cc44e5aa8fadd0f).
>> +
>> +%% original patch: 0007-Do-not-use-getsubopt.patch
>> +
>> +Signed-off-by: Daniel Gomez <daniel@qtec.com>
>> +---
>> + utils/v4l2-ctl/v4l2-ctl-common.cpp | 18 ++++++++++--------
>> + 1 file changed, 10 insertions(+), 8 deletions(-)
>> +
>> +diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp
>> +index d77f7104..838c297d 100644
>> +--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
>> ++++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
>> +@@ -994,15 +994,17 @@ static bool parse_subset(char *optarg)
>> +
>> + static bool parse_next_subopt(char **subs, char **value)
>> + {
>> +-	static char *const subopts[] = {
>> +-	    nullptr
>> +-	};
>> +-	int opt = v4l_getsubopt(subs, subopts, value);
>> ++	char *p = *subs;
>> ++	*value = *subs;
>> +
>> +-	if (opt < 0 || *value)
>> +-		return false;
>> +-	fprintf(stderr, "Missing suboption value\n");
>> +-	return true;
>> ++	while (*p && *p != ',')
>> ++		p++;
>> ++
>> ++	if (*p)
>> ++		*p++ = '\0';
>> ++
>> ++	*subs = p;
>> ++	return false;
>> + }
>> +
>> + void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
>> +--
>> +2.35.1
>> +
>> diff --git a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>> new file mode 100644
>> index 00000000..21a08022
>> --- /dev/null
>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>> @@ -0,0 +1,87 @@
>> +SUMMARY = "v4l2 and IR applications"
>> +LICENSE = "GPL-2.0-only & LGPL-2.1-only"
>> +LIC_FILES_CHKSUM = "file://COPYING;md5=48da9957849056017dc568bbc43d8975 \
>> +                    file://COPYING.libv4l;md5=d749e86a105281d7a44c2328acebc4b0"
>> +PROVIDES = "libv4l media-ctl"
>> +
>> +DEPENDS = "jpeg \
>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'virtual/libx11', '', d)} \
>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \
>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa-lib', '', d)} \
>> +           ${@bb.utils.contains_any('PACKAGECONFIG', 'qv4l2 qvidcap', 'qtbase qtbase-native', '', d)}"
>> +
>> +DEPENDS:append:libc-musl = " argp-standalone"
>> +DEPENDS:append:class-target = " udev"
>> +LDFLAGS:append = " -pthread"
>> +# v4l2 explicitly sets _FILE_OFFSET_BITS=32 to get access to
>> +# both 32 and 64 bit file APIs.  But it does not handle the time side?
>> +# Needs further investigation
>> +GLIBC_64BIT_TIME_FLAGS = ""
>> +
>> +inherit autotools gettext pkgconfig
>> +
>> +PACKAGECONFIG ??= "media-ctl"
>> +PACKAGECONFIG[media-ctl] = "--enable-v4l-utils,--disable-v4l-utils,,"
>> +PACKAGECONFIG[qv4l2] = ",--disable-qv4l2"
>> +PACKAGECONFIG[qvidcap] = ",--disable-qvidcap"
>> +
>> +SRC_URI = "\
>> +    git://git.linuxtv.org/v4l-utils.git;protocol=https;branch=master \
>> +    file://0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch \
>> +    file://0002-original-patch-mediactl-pkgconfig.patch \
>> +    file://0003-original-patch-export-mediactl-headers.patch \
>> +    file://0004-Do-not-use-getsubopt.patch \
>> +"
>> +
>> +SRCREV = "9431e4b26b4842d1401e80ada9f14593dca3a94c"
>> +
>> +PV .= "+git${SRCPV}"
>> +
>> +S = "${WORKDIR}/git"
>> +
>> +do_configure:prepend() {
>> +    cd ${S}; ./bootstrap.sh; cd -
>> +}
>> +
>> +EXTRA_OECONF = "--enable-shared --with-udevdir=${base_libdir}/udev \
>> +                --disable-v4l2-compliance-32 --disable-v4l2-ctl-32"
>> +
>> +VIRTUAL-RUNTIME_ir-keytable-keymaps ?= "rc-keymaps"
>> +
>> +PACKAGES =+ "media-ctl ir-keytable rc-keymaps libv4l libv4l-dev qv4l2 qvidcap"
>> +
>> +RPROVIDES:${PN}-dbg += "libv4l-dbg"
>> +
>> +FILES:media-ctl = "${bindir}/media-ctl ${libdir}/libmediactl.so.*"
>> +FILES:qv4l2 = "\
>> +    ${bindir}/qv4l2 \
>> +    ${datadir}/applications/qv4l2.desktop \
>> +    ${datadir}/icons/hicolor/*/apps/qv4l2.* \
>> +"
>> +FILES:qvidcap = "\
>> +    ${bindir}/qvidcap \
>> +    ${datadir}/applications/qvidcap.desktop \
>> +    ${datadir}/icons/hicolor/*/apps/qvidcap.* \
>> +"
>> +
>> +FILES:ir-keytable = "${bindir}/ir-keytable ${base_libdir}/udev/rules.d/*-infrared.rules"
>> +RDEPENDS:ir-keytable += "${VIRTUAL-RUNTIME_ir-keytable-keymaps}"
>> +RDEPENDS:qv4l2 += "\
>> +    ${@bb.utils.contains('PACKAGECONFIG', 'qv4l2', 'qtbase', '', d)}"
>> +RDEPENDS:qvidcap += "\
>> +    ${@bb.utils.contains('PACKAGECONFIG', 'qvidcap', 'qtbase', '', d)}"
>> +
>> +FILES:rc-keymaps = "${sysconfdir}/rc* ${base_libdir}/udev/rc*"
>> +
>> +FILES:${PN} = "${bindir} ${sbindir}"
>> +
>> +FILES:libv4l += "${libdir}/libv4l*${SOLIBS} ${libdir}/libv4l/*.so ${libdir}/libv4l/plugins/*.so \
>> +                 ${libdir}/libdvbv5*${SOLIBS} \
>> +                 ${libdir}/libv4l/*-decomp"
>> +
>> +FILES:libv4l-dev += "${includedir} ${libdir}/pkgconfig \
>> +                     ${libdir}/libv4l*${SOLIBSDEV} ${libdir}/*.la \
>> +                     ${libdir}/v4l*${SOLIBSDEV} ${libdir}/libv4l/*.la ${libdir}/libv4l/plugins/*.la"
>> +
>> +PARALLEL_MAKE:class-native = ""
>> +BBCLASSEXTEND = "native"

-- 
Ryan Eatmon                reatmon@ti.com
-----------------------------------------
Texas Instruments, Inc.  -  LCPD  -  MGTS


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
  2023-05-23 15:36   ` Ryan Eatmon
@ 2023-05-24 11:14     ` Devarsh Thakkar
  2023-05-24 13:44       ` Ryan Eatmon
  0 siblings, 1 reply; 8+ messages in thread
From: Devarsh Thakkar @ 2023-05-24 11:14 UTC (permalink / raw)
  To: Ryan Eatmon, Jai Luthra, meta-arago
  Cc: Denys Dmytriyenko, Gyan Gupta, Sai Sree Kartheek Adivi,
	Rahul T R, Bajjuri, Praneeth, Raghavendra, Vignesh, Bhatia,
	Aradhya, Nori, Sekhar, Khasim, Syed Mohammed

Hi Ryan,

Thanks for the feedback,

On 23/05/23 21:06, Ryan Eatmon wrote:
> 
> 
> On 5/23/2023 6:48 AM, Devarsh Thakkar wrote:
>> Hi Jai,
>>
>> Thanks for the patch.
>>
>> On 23/05/23 15:14, Jai Luthra wrote:
>>> An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
>>> layer for kirkstone.
>>>
>>> TI's 6.1 based kernel has backported multistream routing APIs [1] from
>>> upstream kernel, which requires a few patches to v4l-utils [2] that only
>>> apply cleanly on top of v1.23.0.
>>>
>>> Thus we override the recipe in this layer to the latest (v1.23.0) found
>>> from meta-oe master.
>>>
>>> Link:
>>> https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
>>> Link:
>>> https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
>>> Signed-off-by: Jai Luthra <j-luthra@ti.com>
>>> ---
>>>   ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
>>>   ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
>>>   ...iginal-patch-export-mediactl-headers.patch | 24 +++++
>>>   .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
>>>   .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++
>>
>> As per my opinion, not a good idea to bump up package version than default
>> package version shipped by kirkstone i.e. 1.22.1
>> (meta-oe/recipes-multimedia/v4l2apps/v4l-utils_1.22.1.bb)
>>
>> As a general rule of thumb, there could be other layers (for e.g. added by
>> vendors) having bbappends assuming shipped package version same as in
>> kirkstone and also build time and runtime dependencies w.r.t other packages
>> are guaranted if all packages stay with same version as shipped by kirkstone
>> and with this new recipe I believe we are kind of deviating from that
>> protection and so my suggestion is to rebase on top of existing package
>> version i.e. 1.22.1
> 
> If you were talking about meta-ti then I would 100% agree with you, but this
> is meta-arago.  And as a distribution layer, we are perfectly within our
> purvue to advance to a later version of a tool beyond what the other upstream
> repos are at, or change config files, etc...
> 
> Meta-ti as a BSP layer needs to play nice in the sandbox with other layers and
> not change versions without guards.
> 

I am not sure what exactly you mean by guards, is it possible to share an
example? Also I think we did change linux kernel version to 6.1 in meta-ti
from the one supported in kirkstone (which I believe was 5.18) although that
has its set of advantages since it is latest LTS.

> If you wanted to be extra careful you could include the guards in arago as
> well, but since arago is not a yocto compliant layer it is not strictly needed
> at this time.
> 
> 

I think the crux of the issue here is gap between v4l-utils version (which is
1.22.1 released couple of years back as Jai mentioned ) in kirkstone and the
linux version being used which is 6.1 (which got released this year) requiring
us to bump up v4l-utils to match the latest features added in 6.1 and this is
because since we bumped up linux version to 6.1 from official kirkstone
supported version which I think is 5.18.

But I agree with Jai and you that it's better to bump up the recipe version
directly since anyway kernel version is bumped up and latest v4l-utils is a
better match.

On a sidenote is it fine if we try and decide to bump up gstreamer version too
from 1.20.5 to 1.22 series which was released this year since it has more
features and compatible to kernel version 6.1 ?

Regards
Devarsh
>> Regards
>> Devarsh
>>
>>>   5 files changed, 236 insertions(+)
>>>   create mode 100644
>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>>   create mode 100644
>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>>   create mode 100644
>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>>   create mode 100644
>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>>   create mode 100644
>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>
>>
>>>
>>> diff --git
>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>> new file mode 100644
>>> index 00000000..8ac8fbe1
>>> --- /dev/null
>>> +++
>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>> @@ -0,0 +1,44 @@
>>> +From 0d5c0e9a75eca43667b0e29155b635e50622b66a Mon Sep 17 00:00:00 2001
>>> +From: Khem Raj <raj.khem@gmail.com>
>>> +Date: Fri, 27 Feb 2015 21:55:36 +0000
>>> +Subject: [PATCH] Revert "media-ctl: Don't install libmediactl and
>>> +
>>> + libv4l2subdev"
>>> +
>>> +This reverts commit 0911dce53b08b0df3066be2c75f67e8a314d8729.
>>> +
>>> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
>>> +
>>> +Conflicts:
>>> +    utils/media-ctl/Makefile.am
>>> +
>>> +---
>>> + utils/media-ctl/Makefile.am | 10 +++-------
>>> + 1 file changed, 3 insertions(+), 7 deletions(-)
>>> +
>>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>>> +index c48c8d6..e255e16 100644
>>> +--- a/utils/media-ctl/Makefile.am
>>> ++++ b/utils/media-ctl/Makefile.am
>>> +@@ -1,8 +1,7 @@
>>> +-noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
>>> +-
>>> ++lib_LTLIBRARIES = libmediactl.la libv4l2subdev.la
>>> + libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
>>> +-libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
>>> +-libmediactl_la_LDFLAGS = -static $(LIBUDEV_LIBS)
>>> ++libmediactl_la_CFLAGS = $(LIBUDEV_CFLAGS)
>>> ++libmediactl_la_LDFLAGS = $(LIBUDEV_LIBS)
>>> +
>>> + media-bus-format-names.h: ../../include/linux/media-bus-format.h
>>> +     $(AM_V_GEN) sed -e '/#define MEDIA_BUS_FMT/ ! d; s/.*FMT_//; /FIXED/
>>> d; s/\t.*//; s/.*/{ \"&\", MEDIA_BUS_FMT_& },/;' \
>>> +@@ -18,9 +17,6 @@ CLEANFILES = $(BUILT_SOURCES)
>>> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
>>> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
>>> + libv4l2subdev_la_LIBADD = libmediactl.la
>>> +-libv4l2subdev_la_CFLAGS = -static
>>> +-libv4l2subdev_la_LDFLAGS = -static
>>> +-
>>> + mediactl_includedir=$(includedir)/mediactl
>>> + noinst_HEADERS = mediactl.h v4l2subdev.h
>>> +
>>> diff --git
>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>> new file mode 100644
>>> index 00000000..52fc2d7a
>>> --- /dev/null
>>> +++
>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>> @@ -0,0 +1,21 @@
>>> +From 320b8378ee30eb5e0fe83a8b397f822f2f88a4c1 Mon Sep 17 00:00:00 2001
>>> +From: Khem Raj <raj.khem@gmail.com>
>>> +Date: Sun, 1 Mar 2015 22:25:07 +0000
>>> +Subject: [PATCH] %% original patch: mediactl-pkgconfig.patch
>>> +
>>> +---
>>> + utils/media-ctl/Makefile.am | 1 +
>>> + 1 file changed, 1 insertion(+)
>>> +
>>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>>> +index e255e16..ff7b417 100644
>>> +--- a/utils/media-ctl/Makefile.am
>>> ++++ b/utils/media-ctl/Makefile.am
>>> +@@ -20,6 +20,7 @@ libv4l2subdev_la_LIBADD = libmediactl.la
>>> + mediactl_includedir=$(includedir)/mediactl
>>> + noinst_HEADERS = mediactl.h v4l2subdev.h
>>> +
>>> ++pkgconfig_DATA = libmediactl.pc
>>> + bin_PROGRAMS = media-ctl
>>> + media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
>>> + media_ctl_LDADD = libmediactl.la libv4l2subdev.la
>>> diff --git
>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>> new file mode 100644
>>> index 00000000..39dc3383
>>> --- /dev/null
>>> +++
>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>> @@ -0,0 +1,24 @@
>>> +From f7109d6b2fcb291824d795071c04a492d9fbc45b Mon Sep 17 00:00:00 2001
>>> +From: Khem Raj <raj.khem@gmail.com>
>>> +Date: Sun, 1 Mar 2015 22:25:07 +0000
>>> +Subject: [PATCH] %% original patch: export-mediactl-headers.patch
>>> +
>>> +---
>>> + utils/media-ctl/Makefile.am | 4 ++--
>>> + 1 file changed, 2 insertions(+), 2 deletions(-)
>>> +
>>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>>> +index ff7b417..6ce656f 100644
>>> +--- a/utils/media-ctl/Makefile.am
>>> ++++ b/utils/media-ctl/Makefile.am
>>> +@@ -17,8 +17,8 @@ CLEANFILES = $(BUILT_SOURCES)
>>> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
>>> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
>>> + libv4l2subdev_la_LIBADD = libmediactl.la
>>> +-mediactl_includedir=$(includedir)/mediactl
>>> +-noinst_HEADERS = mediactl.h v4l2subdev.h
>>> ++otherincludedir = $(includedir)/mediactl
>>> ++otherinclude_HEADERS = mediactl.h v4l2subdev.h
>>> +
>>> + pkgconfig_DATA = libmediactl.pc
>>> + bin_PROGRAMS = media-ctl
>>> diff --git
>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>> new file mode 100644
>>> index 00000000..fb844acb
>>> --- /dev/null
>>> +++
>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>> @@ -0,0 +1,60 @@
>>> +From 6e7e52de7afe29597016952a7317faf9c3ea3268 Mon Sep 17 00:00:00 2001
>>> +From: Khem Raj <raj.khem@gmail.com>
>>> +Date: Sat, 30 Nov 2019 18:50:34 -0800
>>> +Subject: [PATCH] Do not use getsubopt
>>> +
>>> +POSIX says that behavior when subopts list is empty is undefined.
>>> +musl libs will set value to NULL which leads to crash.
>>> +
>>> +Simply avoid getsubopt, since we cannot rely on it.
>>> +
>>> +Imported from Alpine Linux
>>> +
>>> +Upstream-Status: Pending
>>> +
>>> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
>>> +
>>> +Adapt patch to 1.23.0.
>>> +
>>> +(v4l-utils rev fd544473800d02e90bc289434cc44e5aa8fadd0f).
>>> +
>>> +%% original patch: 0007-Do-not-use-getsubopt.patch
>>> +
>>> +Signed-off-by: Daniel Gomez <daniel@qtec.com>
>>> +---
>>> + utils/v4l2-ctl/v4l2-ctl-common.cpp | 18 ++++++++++--------
>>> + 1 file changed, 10 insertions(+), 8 deletions(-)
>>> +
>>> +diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>> b/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>> +index d77f7104..838c297d 100644
>>> +--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>> ++++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>> +@@ -994,15 +994,17 @@ static bool parse_subset(char *optarg)
>>> +
>>> + static bool parse_next_subopt(char **subs, char **value)
>>> + {
>>> +-    static char *const subopts[] = {
>>> +-        nullptr
>>> +-    };
>>> +-    int opt = v4l_getsubopt(subs, subopts, value);
>>> ++    char *p = *subs;
>>> ++    *value = *subs;
>>> +
>>> +-    if (opt < 0 || *value)
>>> +-        return false;
>>> +-    fprintf(stderr, "Missing suboption value\n");
>>> +-    return true;
>>> ++    while (*p && *p != ',')
>>> ++        p++;
>>> ++
>>> ++    if (*p)
>>> ++        *p++ = '\0';
>>> ++
>>> ++    *subs = p;
>>> ++    return false;
>>> + }
>>> +
>>> + void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
>>> +--
>>> +2.35.1
>>> +
>>> diff --git
>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>> new file mode 100644
>>> index 00000000..21a08022
>>> --- /dev/null
>>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>> @@ -0,0 +1,87 @@
>>> +SUMMARY = "v4l2 and IR applications"
>>> +LICENSE = "GPL-2.0-only & LGPL-2.1-only"
>>> +LIC_FILES_CHKSUM = "file://COPYING;md5=48da9957849056017dc568bbc43d8975 \
>>> +                   
>>> file://COPYING.libv4l;md5=d749e86a105281d7a44c2328acebc4b0"
>>> +PROVIDES = "libv4l media-ctl"
>>> +
>>> +DEPENDS = "jpeg \
>>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'x11',
>>> 'virtual/libx11', '', d)} \
>>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd',
>>> '', d)} \
>>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa-lib', '',
>>> d)} \
>>> +           ${@bb.utils.contains_any('PACKAGECONFIG', 'qv4l2 qvidcap',
>>> 'qtbase qtbase-native', '', d)}"
>>> +
>>> +DEPENDS:append:libc-musl = " argp-standalone"
>>> +DEPENDS:append:class-target = " udev"
>>> +LDFLAGS:append = " -pthread"
>>> +# v4l2 explicitly sets _FILE_OFFSET_BITS=32 to get access to
>>> +# both 32 and 64 bit file APIs.  But it does not handle the time side?
>>> +# Needs further investigation
>>> +GLIBC_64BIT_TIME_FLAGS = ""
>>> +
>>> +inherit autotools gettext pkgconfig
>>> +
>>> +PACKAGECONFIG ??= "media-ctl"
>>> +PACKAGECONFIG[media-ctl] = "--enable-v4l-utils,--disable-v4l-utils,,"
>>> +PACKAGECONFIG[qv4l2] = ",--disable-qv4l2"
>>> +PACKAGECONFIG[qvidcap] = ",--disable-qvidcap"
>>> +
>>> +SRC_URI = "\
>>> +    git://git.linuxtv.org/v4l-utils.git;protocol=https;branch=master \
>>> +    file://0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch \
>>> +    file://0002-original-patch-mediactl-pkgconfig.patch \
>>> +    file://0003-original-patch-export-mediactl-headers.patch \
>>> +    file://0004-Do-not-use-getsubopt.patch \
>>> +"
>>> +
>>> +SRCREV = "9431e4b26b4842d1401e80ada9f14593dca3a94c"
>>> +
>>> +PV .= "+git${SRCPV}"
>>> +
>>> +S = "${WORKDIR}/git"
>>> +
>>> +do_configure:prepend() {
>>> +    cd ${S}; ./bootstrap.sh; cd -
>>> +}
>>> +
>>> +EXTRA_OECONF = "--enable-shared --with-udevdir=${base_libdir}/udev \
>>> +                --disable-v4l2-compliance-32 --disable-v4l2-ctl-32"
>>> +
>>> +VIRTUAL-RUNTIME_ir-keytable-keymaps ?= "rc-keymaps"
>>> +
>>> +PACKAGES =+ "media-ctl ir-keytable rc-keymaps libv4l libv4l-dev qv4l2
>>> qvidcap"
>>> +
>>> +RPROVIDES:${PN}-dbg += "libv4l-dbg"
>>> +
>>> +FILES:media-ctl = "${bindir}/media-ctl ${libdir}/libmediactl.so.*"
>>> +FILES:qv4l2 = "\
>>> +    ${bindir}/qv4l2 \
>>> +    ${datadir}/applications/qv4l2.desktop \
>>> +    ${datadir}/icons/hicolor/*/apps/qv4l2.* \
>>> +"
>>> +FILES:qvidcap = "\
>>> +    ${bindir}/qvidcap \
>>> +    ${datadir}/applications/qvidcap.desktop \
>>> +    ${datadir}/icons/hicolor/*/apps/qvidcap.* \
>>> +"
>>> +
>>> +FILES:ir-keytable = "${bindir}/ir-keytable
>>> ${base_libdir}/udev/rules.d/*-infrared.rules"
>>> +RDEPENDS:ir-keytable += "${VIRTUAL-RUNTIME_ir-keytable-keymaps}"
>>> +RDEPENDS:qv4l2 += "\
>>> +    ${@bb.utils.contains('PACKAGECONFIG', 'qv4l2', 'qtbase', '', d)}"
>>> +RDEPENDS:qvidcap += "\
>>> +    ${@bb.utils.contains('PACKAGECONFIG', 'qvidcap', 'qtbase', '', d)}"
>>> +
>>> +FILES:rc-keymaps = "${sysconfdir}/rc* ${base_libdir}/udev/rc*"
>>> +
>>> +FILES:${PN} = "${bindir} ${sbindir}"
>>> +
>>> +FILES:libv4l += "${libdir}/libv4l*${SOLIBS} ${libdir}/libv4l/*.so
>>> ${libdir}/libv4l/plugins/*.so \
>>> +                 ${libdir}/libdvbv5*${SOLIBS} \
>>> +                 ${libdir}/libv4l/*-decomp"
>>> +
>>> +FILES:libv4l-dev += "${includedir} ${libdir}/pkgconfig \
>>> +                     ${libdir}/libv4l*${SOLIBSDEV} ${libdir}/*.la \
>>> +                     ${libdir}/v4l*${SOLIBSDEV} ${libdir}/libv4l/*.la
>>> ${libdir}/libv4l/plugins/*.la"
>>> +
>>> +PARALLEL_MAKE:class-native = ""
>>> +BBCLASSEXTEND = "native"
> 


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
  2023-05-23 13:18   ` Jai Luthra
@ 2023-05-24 12:41     ` Devarsh Thakkar
  0 siblings, 0 replies; 8+ messages in thread
From: Devarsh Thakkar @ 2023-05-24 12:41 UTC (permalink / raw)
  To: Jai Luthra
  Cc: meta-arago, Ryan Eatmon, Denys Dmytriyenko, Gyan Gupta,
	Sai Sree Kartheek Adivi, Rahul T R, Bajjuri, Praneeth,
	Raghavendra, Vignesh, Bhatia, Aradhya, Nori, Sekhar, Khasim,
	Syed Mohammed

Hi Jai,

On 23/05/23 18:48, Jai Luthra wrote:
> Hi Devarsh,
> 
> Thanks for the review,
> 
> On May 23, 2023 at 17:18:39 +0530, Devarsh Thakkar wrote:
>> Hi Jai,
>>
>> Thanks for the patch.
>>
>> On 23/05/23 15:14, Jai Luthra wrote:
>>> An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
>>> layer for kirkstone.
>>>
>>> TI's 6.1 based kernel has backported multistream routing APIs [1] from
>>> upstream kernel, which requires a few patches to v4l-utils [2] that only
>>> apply cleanly on top of v1.23.0.
>>>
>>> Thus we override the recipe in this layer to the latest (v1.23.0) found
>>> from meta-oe master.
>>>
>>> Link: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
>>> Link: https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
>>> Signed-off-by: Jai Luthra <j-luthra@ti.com>
>>> ---
>>>  ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
>>>  ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
>>>  ...iginal-patch-export-mediactl-headers.patch | 24 +++++
>>>  .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
>>>  .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++
>>
>> As per my opinion, not a good idea to bump up package version than default
>> package version shipped by kirkstone i.e. 1.22.1
>> (meta-oe/recipes-multimedia/v4l2apps/v4l-utils_1.22.1.bb)
>>
>> As a general rule of thumb, there could be other layers (for e.g. added by
>> vendors) having bbappends assuming shipped package version same as in
>> kirkstone and also build time and runtime dependencies w.r.t other packages
>> are guaranted if all packages stay with same version as shipped by kirkstone
>> and with this new recipe I believe we are kind of deviating from that
>> protection and so my suggestion is to rebase on top of existing package
>> version i.e. 1.22.1
> 
> I agree that it makes sense to keep packages pinned to a version for a 
> particular release (dunfell/kirkstone) for stability and compatibility 
> with other dependencies.
> 
> The only issue here is multi-stream support requires a large chunk of 
> changes to v4l2 userspace APIs, affecting the most commonly used tools 
> for setting up the camera pipeline (media-ctl) and capturing frames 
> (v4l2-ctl).
> 
> While these changes are merged in linux upstream and backported to TI's 
> 6.1 branch, the corresponding v4l-utils changes are still under review 
> upstream.
> 
> There are two options I see here:
> 
> 
>     1. We bump up the v4l-utils recipe in our distribution to a 
>     relatively recent git commit (v1.23.0-9431e4b26b) which is in sync 
>     with TI baseline kernel, and apply only the patches for the extra 
>     features TI uses on top.
> 
>     We also ensure it works well with the dependencies (mainly libc) 
>     provided by rest of the kirkstone layers (so far no issues seen in 
>     my tests)
> 
> 
>     2. We backport these patches to v1.22.1, which was tagged almost 
>     **two years ago** in Oct 2021; while the kernel is on 6.1 (Jan 2023) 
>     and using multistream APIs from 6.3/6.4/still-under-review.
> 
>     We will also have to sync with the latest kernel headers and 
>     extensively test that we don't break some ioctl or are missing 
>     bugfixes to v4l-utils from the past two years, as the kernel 
>     developer(s) for the newer features would not have tested against 
>     the old release.
> 
> 
> That's why I chose option 1 in the current series as an exception to the 
> thumb rule. Let me know if it is a complete no-go to override a recipe 
> here.
> 

Thanks for sharing this details, as discussed in other thread
https://lore.kernel.org/all/1f00c11f-f413-c015-c2fd-24afb475295b@ti.com/
I think v4l-utils is behind since we bumped up kernel to 6.1 so agreed that we
should bump up v4l-utils too.

If possible, I would suggest to go with latest stable version of v4l-utils to
minimize local patch list to apply in new recipe.

Regards
Devarsh

>>
>> Regards
>> Devarsh
> 
> Thanks,
> Jai


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0
  2023-05-24 11:14     ` Devarsh Thakkar
@ 2023-05-24 13:44       ` Ryan Eatmon
  0 siblings, 0 replies; 8+ messages in thread
From: Ryan Eatmon @ 2023-05-24 13:44 UTC (permalink / raw)
  To: Devarsh Thakkar, Jai Luthra, meta-arago
  Cc: Denys Dmytriyenko, Gyan Gupta, Sai Sree Kartheek Adivi,
	Rahul T R, Bajjuri, Praneeth, Raghavendra, Vignesh, Bhatia,
	Aradhya, Nori, Sekhar, Khasim, Syed Mohammed



On 5/24/2023 6:14 AM, Devarsh Thakkar wrote:
> Hi Ryan,
> 
> Thanks for the feedback,
> 
> On 23/05/23 21:06, Ryan Eatmon wrote:
>>
>>
>> On 5/23/2023 6:48 AM, Devarsh Thakkar wrote:
>>> Hi Jai,
>>>
>>> Thanks for the patch.
>>>
>>> On 23/05/23 15:14, Jai Luthra wrote:
>>>> An older recipe (v1.22.0) is present in the meta-openembedded/meta-oe
>>>> layer for kirkstone.
>>>>
>>>> TI's 6.1 based kernel has backported multistream routing APIs [1] from
>>>> upstream kernel, which requires a few patches to v4l-utils [2] that only
>>>> apply cleanly on top of v1.23.0.
>>>>
>>>> Thus we override the recipe in this layer to the latest (v1.23.0) found
>>>> from meta-oe master.
>>>>
>>>> Link:
>>>> https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/log/?h=ca55d70b41e [1]
>>>> Link:
>>>> https://lore.kernel.org/all/20230210115546.199809-1-tomi.valkeinen@ideasonboard.com/ [2]
>>>> Signed-off-by: Jai Luthra <j-luthra@ti.com>
>>>> ---
>>>>    ...-Don-t-install-libmediactl-and-libv4.patch | 44 ++++++++++
>>>>    ...02-original-patch-mediactl-pkgconfig.patch | 21 +++++
>>>>    ...iginal-patch-export-mediactl-headers.patch | 24 +++++
>>>>    .../v4l-utils/0004-Do-not-use-getsubopt.patch | 60 +++++++++++++
>>>>    .../v4l-utils/v4l-utils_1.23.0.bb             | 87 +++++++++++++++++++
>>>
>>> As per my opinion, not a good idea to bump up package version than default
>>> package version shipped by kirkstone i.e. 1.22.1
>>> (meta-oe/recipes-multimedia/v4l2apps/v4l-utils_1.22.1.bb)
>>>
>>> As a general rule of thumb, there could be other layers (for e.g. added by
>>> vendors) having bbappends assuming shipped package version same as in
>>> kirkstone and also build time and runtime dependencies w.r.t other packages
>>> are guaranted if all packages stay with same version as shipped by kirkstone
>>> and with this new recipe I believe we are kind of deviating from that
>>> protection and so my suggestion is to rebase on top of existing package
>>> version i.e. 1.22.1
>>
>> If you were talking about meta-ti then I would 100% agree with you, but this
>> is meta-arago.  And as a distribution layer, we are perfectly within our
>> purvue to advance to a later version of a tool beyond what the other upstream
>> repos are at, or change config files, etc...
>>
>> Meta-ti as a BSP layer needs to play nice in the sandbox with other layers and
>> not change versions without guards.
>>
> 
> I am not sure what exactly you mean by guards, is it possible to share an
> example? Also I think we did change linux kernel version to 6.1 in meta-ti
> from the one supported in kirkstone (which I believe was 5.18) although that
> has its set of advantages since it is latest LTS.

Check out the recent patch that Denys submitted for meta-ti kirkstone 
for optee.  Basically, hide any changes we make to something that is 
upstream behind an override so that the change only applies when 
building one our machine targets.

https://lists.yoctoproject.org/g/meta-ti/message/16574


>> If you wanted to be extra careful you could include the guards in arago as
>> well, but since arago is not a yocto compliant layer it is not strictly needed
>> at this time.
>>
>>
> 
> I think the crux of the issue here is gap between v4l-utils version (which is
> 1.22.1 released couple of years back as Jai mentioned ) in kirkstone and the
> linux version being used which is 6.1 (which got released this year) requiring
> us to bump up v4l-utils to match the latest features added in 6.1 and this is
> because since we bumped up linux version to 6.1 from official kirkstone
> supported version which I think is 5.18.
> 
> But I agree with Jai and you that it's better to bump up the recipe version
> directly since anyway kernel version is bumped up and latest v4l-utils is a
> better match.
> 
> On a sidenote is it fine if we try and decide to bump up gstreamer version too
> from 1.20.5 to 1.22 series which was released this year since it has more
> features and compatible to kernel version 6.1 ?

I would be fine with that.


> Regards
> Devarsh
>>> Regards
>>> Devarsh
>>>
>>>>    5 files changed, 236 insertions(+)
>>>>    create mode 100644
>>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>>>    create mode 100644
>>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>>>    create mode 100644
>>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>>>    create mode 100644
>>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>>>    create mode 100644
>>>> meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>>
>>>
>>>>
>>>> diff --git
>>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>>> new file mode 100644
>>>> index 00000000..8ac8fbe1
>>>> --- /dev/null
>>>> +++
>>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch
>>>> @@ -0,0 +1,44 @@
>>>> +From 0d5c0e9a75eca43667b0e29155b635e50622b66a Mon Sep 17 00:00:00 2001
>>>> +From: Khem Raj <raj.khem@gmail.com>
>>>> +Date: Fri, 27 Feb 2015 21:55:36 +0000
>>>> +Subject: [PATCH] Revert "media-ctl: Don't install libmediactl and
>>>> +
>>>> + libv4l2subdev"
>>>> +
>>>> +This reverts commit 0911dce53b08b0df3066be2c75f67e8a314d8729.
>>>> +
>>>> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
>>>> +
>>>> +Conflicts:
>>>> +    utils/media-ctl/Makefile.am
>>>> +
>>>> +---
>>>> + utils/media-ctl/Makefile.am | 10 +++-------
>>>> + 1 file changed, 3 insertions(+), 7 deletions(-)
>>>> +
>>>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>>>> +index c48c8d6..e255e16 100644
>>>> +--- a/utils/media-ctl/Makefile.am
>>>> ++++ b/utils/media-ctl/Makefile.am
>>>> +@@ -1,8 +1,7 @@
>>>> +-noinst_LTLIBRARIES = libmediactl.la libv4l2subdev.la
>>>> +-
>>>> ++lib_LTLIBRARIES = libmediactl.la libv4l2subdev.la
>>>> + libmediactl_la_SOURCES = libmediactl.c mediactl-priv.h
>>>> +-libmediactl_la_CFLAGS = -static $(LIBUDEV_CFLAGS)
>>>> +-libmediactl_la_LDFLAGS = -static $(LIBUDEV_LIBS)
>>>> ++libmediactl_la_CFLAGS = $(LIBUDEV_CFLAGS)
>>>> ++libmediactl_la_LDFLAGS = $(LIBUDEV_LIBS)
>>>> +
>>>> + media-bus-format-names.h: ../../include/linux/media-bus-format.h
>>>> +     $(AM_V_GEN) sed -e '/#define MEDIA_BUS_FMT/ ! d; s/.*FMT_//; /FIXED/
>>>> d; s/\t.*//; s/.*/{ \"&\", MEDIA_BUS_FMT_& },/;' \
>>>> +@@ -18,9 +17,6 @@ CLEANFILES = $(BUILT_SOURCES)
>>>> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
>>>> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
>>>> + libv4l2subdev_la_LIBADD = libmediactl.la
>>>> +-libv4l2subdev_la_CFLAGS = -static
>>>> +-libv4l2subdev_la_LDFLAGS = -static
>>>> +-
>>>> + mediactl_includedir=$(includedir)/mediactl
>>>> + noinst_HEADERS = mediactl.h v4l2subdev.h
>>>> +
>>>> diff --git
>>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>>> new file mode 100644
>>>> index 00000000..52fc2d7a
>>>> --- /dev/null
>>>> +++
>>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0002-original-patch-mediactl-pkgconfig.patch
>>>> @@ -0,0 +1,21 @@
>>>> +From 320b8378ee30eb5e0fe83a8b397f822f2f88a4c1 Mon Sep 17 00:00:00 2001
>>>> +From: Khem Raj <raj.khem@gmail.com>
>>>> +Date: Sun, 1 Mar 2015 22:25:07 +0000
>>>> +Subject: [PATCH] %% original patch: mediactl-pkgconfig.patch
>>>> +
>>>> +---
>>>> + utils/media-ctl/Makefile.am | 1 +
>>>> + 1 file changed, 1 insertion(+)
>>>> +
>>>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>>>> +index e255e16..ff7b417 100644
>>>> +--- a/utils/media-ctl/Makefile.am
>>>> ++++ b/utils/media-ctl/Makefile.am
>>>> +@@ -20,6 +20,7 @@ libv4l2subdev_la_LIBADD = libmediactl.la
>>>> + mediactl_includedir=$(includedir)/mediactl
>>>> + noinst_HEADERS = mediactl.h v4l2subdev.h
>>>> +
>>>> ++pkgconfig_DATA = libmediactl.pc
>>>> + bin_PROGRAMS = media-ctl
>>>> + media_ctl_SOURCES = media-ctl.c options.c options.h tools.h
>>>> + media_ctl_LDADD = libmediactl.la libv4l2subdev.la
>>>> diff --git
>>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>>> new file mode 100644
>>>> index 00000000..39dc3383
>>>> --- /dev/null
>>>> +++
>>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0003-original-patch-export-mediactl-headers.patch
>>>> @@ -0,0 +1,24 @@
>>>> +From f7109d6b2fcb291824d795071c04a492d9fbc45b Mon Sep 17 00:00:00 2001
>>>> +From: Khem Raj <raj.khem@gmail.com>
>>>> +Date: Sun, 1 Mar 2015 22:25:07 +0000
>>>> +Subject: [PATCH] %% original patch: export-mediactl-headers.patch
>>>> +
>>>> +---
>>>> + utils/media-ctl/Makefile.am | 4 ++--
>>>> + 1 file changed, 2 insertions(+), 2 deletions(-)
>>>> +
>>>> +diff --git a/utils/media-ctl/Makefile.am b/utils/media-ctl/Makefile.am
>>>> +index ff7b417..6ce656f 100644
>>>> +--- a/utils/media-ctl/Makefile.am
>>>> ++++ b/utils/media-ctl/Makefile.am
>>>> +@@ -17,8 +17,8 @@ CLEANFILES = $(BUILT_SOURCES)
>>>> + nodist_libv4l2subdev_la_SOURCES = $(BUILT_SOURCES)
>>>> + libv4l2subdev_la_SOURCES = libv4l2subdev.c
>>>> + libv4l2subdev_la_LIBADD = libmediactl.la
>>>> +-mediactl_includedir=$(includedir)/mediactl
>>>> +-noinst_HEADERS = mediactl.h v4l2subdev.h
>>>> ++otherincludedir = $(includedir)/mediactl
>>>> ++otherinclude_HEADERS = mediactl.h v4l2subdev.h
>>>> +
>>>> + pkgconfig_DATA = libmediactl.pc
>>>> + bin_PROGRAMS = media-ctl
>>>> diff --git
>>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>>> new file mode 100644
>>>> index 00000000..fb844acb
>>>> --- /dev/null
>>>> +++
>>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils/0004-Do-not-use-getsubopt.patch
>>>> @@ -0,0 +1,60 @@
>>>> +From 6e7e52de7afe29597016952a7317faf9c3ea3268 Mon Sep 17 00:00:00 2001
>>>> +From: Khem Raj <raj.khem@gmail.com>
>>>> +Date: Sat, 30 Nov 2019 18:50:34 -0800
>>>> +Subject: [PATCH] Do not use getsubopt
>>>> +
>>>> +POSIX says that behavior when subopts list is empty is undefined.
>>>> +musl libs will set value to NULL which leads to crash.
>>>> +
>>>> +Simply avoid getsubopt, since we cannot rely on it.
>>>> +
>>>> +Imported from Alpine Linux
>>>> +
>>>> +Upstream-Status: Pending
>>>> +
>>>> +Signed-off-by: Khem Raj <raj.khem@gmail.com>
>>>> +
>>>> +Adapt patch to 1.23.0.
>>>> +
>>>> +(v4l-utils rev fd544473800d02e90bc289434cc44e5aa8fadd0f).
>>>> +
>>>> +%% original patch: 0007-Do-not-use-getsubopt.patch
>>>> +
>>>> +Signed-off-by: Daniel Gomez <daniel@qtec.com>
>>>> +---
>>>> + utils/v4l2-ctl/v4l2-ctl-common.cpp | 18 ++++++++++--------
>>>> + 1 file changed, 10 insertions(+), 8 deletions(-)
>>>> +
>>>> +diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>>> b/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>>> +index d77f7104..838c297d 100644
>>>> +--- a/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>>> ++++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp
>>>> +@@ -994,15 +994,17 @@ static bool parse_subset(char *optarg)
>>>> +
>>>> + static bool parse_next_subopt(char **subs, char **value)
>>>> + {
>>>> +-    static char *const subopts[] = {
>>>> +-        nullptr
>>>> +-    };
>>>> +-    int opt = v4l_getsubopt(subs, subopts, value);
>>>> ++    char *p = *subs;
>>>> ++    *value = *subs;
>>>> +
>>>> +-    if (opt < 0 || *value)
>>>> +-        return false;
>>>> +-    fprintf(stderr, "Missing suboption value\n");
>>>> +-    return true;
>>>> ++    while (*p && *p != ',')
>>>> ++        p++;
>>>> ++
>>>> ++    if (*p)
>>>> ++        *p++ = '\0';
>>>> ++
>>>> ++    *subs = p;
>>>> ++    return false;
>>>> + }
>>>> +
>>>> + void common_cmd(const std::string &media_bus_info, int ch, char *optarg)
>>>> +--
>>>> +2.35.1
>>>> +
>>>> diff --git
>>>> a/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>>> b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>>> new file mode 100644
>>>> index 00000000..21a08022
>>>> --- /dev/null
>>>> +++ b/meta-arago-extras/recipes-multimedia/v4l-utils/v4l-utils_1.23.0.bb
>>>> @@ -0,0 +1,87 @@
>>>> +SUMMARY = "v4l2 and IR applications"
>>>> +LICENSE = "GPL-2.0-only & LGPL-2.1-only"
>>>> +LIC_FILES_CHKSUM = "file://COPYING;md5=48da9957849056017dc568bbc43d8975 \
>>>> +
>>>> file://COPYING.libv4l;md5=d749e86a105281d7a44c2328acebc4b0"
>>>> +PROVIDES = "libv4l media-ctl"
>>>> +
>>>> +DEPENDS = "jpeg \
>>>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'x11',
>>>> 'virtual/libx11', '', d)} \
>>>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd',
>>>> '', d)} \
>>>> +           ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa-lib', '',
>>>> d)} \
>>>> +           ${@bb.utils.contains_any('PACKAGECONFIG', 'qv4l2 qvidcap',
>>>> 'qtbase qtbase-native', '', d)}"
>>>> +
>>>> +DEPENDS:append:libc-musl = " argp-standalone"
>>>> +DEPENDS:append:class-target = " udev"
>>>> +LDFLAGS:append = " -pthread"
>>>> +# v4l2 explicitly sets _FILE_OFFSET_BITS=32 to get access to
>>>> +# both 32 and 64 bit file APIs.  But it does not handle the time side?
>>>> +# Needs further investigation
>>>> +GLIBC_64BIT_TIME_FLAGS = ""
>>>> +
>>>> +inherit autotools gettext pkgconfig
>>>> +
>>>> +PACKAGECONFIG ??= "media-ctl"
>>>> +PACKAGECONFIG[media-ctl] = "--enable-v4l-utils,--disable-v4l-utils,,"
>>>> +PACKAGECONFIG[qv4l2] = ",--disable-qv4l2"
>>>> +PACKAGECONFIG[qvidcap] = ",--disable-qvidcap"
>>>> +
>>>> +SRC_URI = "\
>>>> +    git://git.linuxtv.org/v4l-utils.git;protocol=https;branch=master \
>>>> +    file://0001-Revert-media-ctl-Don-t-install-libmediactl-and-libv4.patch \
>>>> +    file://0002-original-patch-mediactl-pkgconfig.patch \
>>>> +    file://0003-original-patch-export-mediactl-headers.patch \
>>>> +    file://0004-Do-not-use-getsubopt.patch \
>>>> +"
>>>> +
>>>> +SRCREV = "9431e4b26b4842d1401e80ada9f14593dca3a94c"
>>>> +
>>>> +PV .= "+git${SRCPV}"
>>>> +
>>>> +S = "${WORKDIR}/git"
>>>> +
>>>> +do_configure:prepend() {
>>>> +    cd ${S}; ./bootstrap.sh; cd -
>>>> +}
>>>> +
>>>> +EXTRA_OECONF = "--enable-shared --with-udevdir=${base_libdir}/udev \
>>>> +                --disable-v4l2-compliance-32 --disable-v4l2-ctl-32"
>>>> +
>>>> +VIRTUAL-RUNTIME_ir-keytable-keymaps ?= "rc-keymaps"
>>>> +
>>>> +PACKAGES =+ "media-ctl ir-keytable rc-keymaps libv4l libv4l-dev qv4l2
>>>> qvidcap"
>>>> +
>>>> +RPROVIDES:${PN}-dbg += "libv4l-dbg"
>>>> +
>>>> +FILES:media-ctl = "${bindir}/media-ctl ${libdir}/libmediactl.so.*"
>>>> +FILES:qv4l2 = "\
>>>> +    ${bindir}/qv4l2 \
>>>> +    ${datadir}/applications/qv4l2.desktop \
>>>> +    ${datadir}/icons/hicolor/*/apps/qv4l2.* \
>>>> +"
>>>> +FILES:qvidcap = "\
>>>> +    ${bindir}/qvidcap \
>>>> +    ${datadir}/applications/qvidcap.desktop \
>>>> +    ${datadir}/icons/hicolor/*/apps/qvidcap.* \
>>>> +"
>>>> +
>>>> +FILES:ir-keytable = "${bindir}/ir-keytable
>>>> ${base_libdir}/udev/rules.d/*-infrared.rules"
>>>> +RDEPENDS:ir-keytable += "${VIRTUAL-RUNTIME_ir-keytable-keymaps}"
>>>> +RDEPENDS:qv4l2 += "\
>>>> +    ${@bb.utils.contains('PACKAGECONFIG', 'qv4l2', 'qtbase', '', d)}"
>>>> +RDEPENDS:qvidcap += "\
>>>> +    ${@bb.utils.contains('PACKAGECONFIG', 'qvidcap', 'qtbase', '', d)}"
>>>> +
>>>> +FILES:rc-keymaps = "${sysconfdir}/rc* ${base_libdir}/udev/rc*"
>>>> +
>>>> +FILES:${PN} = "${bindir} ${sbindir}"
>>>> +
>>>> +FILES:libv4l += "${libdir}/libv4l*${SOLIBS} ${libdir}/libv4l/*.so
>>>> ${libdir}/libv4l/plugins/*.so \
>>>> +                 ${libdir}/libdvbv5*${SOLIBS} \
>>>> +                 ${libdir}/libv4l/*-decomp"
>>>> +
>>>> +FILES:libv4l-dev += "${includedir} ${libdir}/pkgconfig \
>>>> +                     ${libdir}/libv4l*${SOLIBSDEV} ${libdir}/*.la \
>>>> +                     ${libdir}/v4l*${SOLIBSDEV} ${libdir}/libv4l/*.la
>>>> ${libdir}/libv4l/plugins/*.la"
>>>> +
>>>> +PARALLEL_MAKE:class-native = ""
>>>> +BBCLASSEXTEND = "native"
>>

-- 
Ryan Eatmon                reatmon@ti.com
-----------------------------------------
Texas Instruments, Inc.  -  LCPD  -  MGTS


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-05-24 13:44 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-23  9:44 [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Jai Luthra
2023-05-23  9:44 ` [master/kirkstone][RESEND PATCH 2/2] v4l-utils: Add multistream and RGB-IR support Jai Luthra
2023-05-23 11:48 ` [master/kirkstone][RESEND PATCH 1/2] v4l-utils: Add recipe for v1.23.0 Devarsh Thakkar
2023-05-23 13:18   ` Jai Luthra
2023-05-24 12:41     ` Devarsh Thakkar
2023-05-23 15:36   ` Ryan Eatmon
2023-05-24 11:14     ` Devarsh Thakkar
2023-05-24 13:44       ` Ryan Eatmon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.