From 0167dbd6aebe8a17f105384e285618d22b685774 Mon Sep 17 00:00:00 2001 From: florent pirou Date: Tue, 9 Jun 2026 12:28:56 +0000 Subject: [PATCH 1/3] refactor(dkms): reindex and organize all OOT patches * enforce consistent patch namespacing and indexing * offset ipu6 patch quilt index `--start-number=0050` * offset ipu7 patch quilt index `--start-number=0100` Signed-off-by: florent pirou --- dkms-kernel-source.sh | 94 +- ...ia-pci-ipu7-Add-D4XX-support-to-IPU7.patch | 79 - ...n-conditional-for-symbol-namespace-.patch} | 171 +- ...disable-src_pad-validation-for-dkms.patch} | 12 +- ...52-ipu6-isys-kernel-6.18-api-compat.patch} | 18 +- ...ideo-let-v4l2-set-default-colorspace.patch | 25 + ...u6-dkms-add-isys-makefile-adaptation.patch | 63 + ...6-isys-add-d4xx-pixel-format-support.patch | 144 ++ ...-lt6911uxc-2-pads-linked-to-ipu-2-po.patch | 80 + ...force-START-then-CAPTURE-distinct-st.patch | 294 +++ ...virtual-channels-on-16-csi2-input-vi.patch | 27 + ...deo-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch | 1206 +++++++++++++ ...u7-isys-csi2-get-link-frequency-from.patch | 52 - ...isys-csi2-get-link-frequency-from-pa.patch | 82 + ...urce-pad-according-to-csi2-ep-fwnod.patch} | 30 +- ...csi2-fwnode-ep-when-destroying-v4l2.patch} | 11 +- ...deo-let-v4l2-set-default-colorspace.patch} | 20 +- ...odules-suffix-versioning-same-as-dkm.patch | 73 + ...7-isys-add-d4xx-pixel-format-support.patch | 126 ++ ...e-HW_ERR_BAD_FRAME_DIM-led-expected-.patch | 28 + ...able-cphy-dphy-5-4-bits-vc-extension.patch | 39 + ...virtual-channels-on-16-csi2-input-vi.patch | 29 + ...deo-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch | 1588 +++++++++++++++++ ...1-dkms-v4l2-core-makefile-adaptation.patch | 37 + ...kms-disable-tuner-build-in-v4l2-core.patch | 24 + ...a-set-v4l2_subdev_enable_streams_api.patch | 27 + ...atch => 0004-ipu-bridge-port-to-bkc.patch} | 11 + patches/6.12/0005-ipu-bridge-makefile.patch | 42 + ...tch => 0006-ipu-bridge-bkc-backport.patch} | 29 +- .../6.12/0007-ipu-bridge-add-sensors.patch | 30 + .../0008-media-mc-Add-INTERNAL-pad-flag.patch | 79 + patches/6.12/0040-ipu-bridge-makefile.patch | 37 - patches/6.12/0042-ipu-bridge-add-sensor.patch | 23 - ...-dkms-v4l2-core-makefile-adaptation.patch} | 6 +- ...ms-disable-tuner-build-in-v4l2-core.patch} | 11 +- ...-set-v4l2_subdev_enable_streams_api.patch} | 5 +- patches/6.17/0004-ipu-bridge-makefile.patch | 42 + ...tch => 0005-ipu-bridge-bkc-backport.patch} | 13 + .../6.17/0006-ipu-bridge-add-sensors.patch | 30 + ...0007-media-mc-Add-INTERNAL-pad-flag.patch} | 16 +- patches/6.17/0040-ipu-bridge-makefile.patch | 38 - patches/6.17/0042-ipu-bridge-add-sensor.patch | 23 - ...-dkms-v4l2-core-makefile-adaptation.patch} | 16 +- ...ms-disable-tuner-build-in-v4l2-core.patch} | 16 +- ...2-subdev-Make-struct-v4l2_subdev_str.patch | 95 + ...Fix-error-handling-on-steps-after-f.patch} | 14 +- ...a-set-v4l2_subdev_enable_streams_api.patch | 14 +- patches/6.18/0006-ipu-bridge-makefile.patch | 42 + ...tch => 0007-ipu-bridge-bkc-backport.patch} | 19 +- .../6.18/0008-ipu-bridge-add-sensors.patch | 30 + .../0009-media-mc-Add-INTERNAL-pad-flag.patch | 79 + patches/6.18/0040-ipu-bridge-makefile.patch | 37 - patches/6.18/0042-ipu-bridge-add-sensor.patch | 23 - ...1-dkms-v4l2-core-makefile-adaptation.patch | 37 + ...kms-disable-tuner-build-in-v4l2-core.patch | 24 + ...a-set-v4l2_subdev_enable_streams_api.patch | 26 + patches/7.0/0004-ipu-bridge-makefile.patch | 42 + .../7.0/0005-ipu-bridge-bkc-backport.patch | 86 + patches/7.0/0006-ipu-bridge-add-sensors.patch | 30 + .../0007-media-mc-Add-INTERNAL-pad-flag.patch | 79 + 60 files changed, 4963 insertions(+), 560 deletions(-) delete mode 100644 patches/0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch rename patches/{0052-module-version-conditional-symbol-namespace.patch => 0050-module-Add-version-conditional-for-symbol-namespace-.patch} (72%) rename patches/{0053-ipu6-isys-disable-src_pad-validation-for-dkms.patch => 0051-ipu6-isys-disable-src_pad-validation-for-dkms.patch} (77%) rename patches/{6.18/0054-ipu6-isys-api-compat.patch => 0052-ipu6-isys-kernel-6.18-api-compat.patch} (76%) create mode 100644 patches/0053-isys-video-let-v4l2-set-default-colorspace.patch create mode 100644 patches/0054-ipu6-dkms-add-isys-makefile-adaptation.patch create mode 100644 patches/0055-ipu6-isys-add-d4xx-pixel-format-support.patch create mode 100644 patches/0056-Revert-ipu6-isys-lt6911uxc-2-pads-linked-to-ipu-2-po.patch create mode 100644 patches/0057-ipu6-isys-video-force-START-then-CAPTURE-distinct-st.patch create mode 100644 patches/0058-ipu6-isys-allow-virtual-channels-on-16-csi2-input-vi.patch create mode 100644 patches/0059-ipu6-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch delete mode 100644 patches/0064-media-ipu7-isys-csi2-get-link-frequency-from.patch create mode 100644 patches/0100-media-ipu7-ipu7-isys-csi2-get-link-frequency-from-pa.patch rename patches/{0065-media-ipu7-get-source-pad-according-to-csi2-.patch => 0101-media-ipu7-get-source-pad-according-to-csi2-ep-fwnod.patch} (78%) rename patches/{0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch => 0102-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch} (80%) rename patches/{0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch => 0103-isys-video-let-v4l2-set-default-colorspace.patch} (51%) create mode 100644 patches/0104-ipu7-isys-make-modules-suffix-versioning-same-as-dkm.patch create mode 100644 patches/0105-ipu7-isys-add-d4xx-pixel-format-support.patch create mode 100644 patches/0106-isys-queue-ignore-HW_ERR_BAD_FRAME_DIM-led-expected-.patch create mode 100644 patches/0107-ipu7-isys-enable-cphy-dphy-5-4-bits-vc-extension.patch create mode 100644 patches/0108-ipu7-isys-allow-virtual-channels-on-16-csi2-input-vi.patch create mode 100644 patches/0109-ipu7-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch create mode 100644 patches/6.12/0001-dkms-v4l2-core-makefile-adaptation.patch create mode 100644 patches/6.12/0002-dkms-disable-tuner-build-in-v4l2-core.patch create mode 100644 patches/6.12/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch rename patches/6.12/{0039-ipu-bridge-port-to-bkc.patch => 0004-ipu-bridge-port-to-bkc.patch} (71%) create mode 100644 patches/6.12/0005-ipu-bridge-makefile.patch rename patches/6.12/{0041-ipu-bridge-bkc-backport.patch => 0006-ipu-bridge-bkc-backport.patch} (85%) create mode 100644 patches/6.12/0007-ipu-bridge-add-sensors.patch create mode 100644 patches/6.12/0008-media-mc-Add-INTERNAL-pad-flag.patch delete mode 100644 patches/6.12/0040-ipu-bridge-makefile.patch delete mode 100644 patches/6.12/0042-ipu-bridge-add-sensor.patch rename patches/6.17/{0004-dkms-v4l2-core-makefile-adaptation.patch => 0001-dkms-v4l2-core-makefile-adaptation.patch} (89%) rename patches/6.17/{0009-dkms-disable-tuner-build-in-v4l2-core.patch => 0002-dkms-disable-tuner-build-in-v4l2-core.patch} (69%) rename patches/6.17/{0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch => 0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch} (82%) create mode 100644 patches/6.17/0004-ipu-bridge-makefile.patch rename patches/6.17/{0041-ipu-bridge-bkc-backport.patch => 0005-ipu-bridge-bkc-backport.patch} (86%) create mode 100644 patches/6.17/0006-ipu-bridge-add-sensors.patch rename patches/6.17/{0063-media-mc-Add-INTERNAL-pad-flag.patch => 0007-media-mc-Add-INTERNAL-pad-flag.patch} (87%) delete mode 100644 patches/6.17/0040-ipu-bridge-makefile.patch delete mode 100644 patches/6.17/0042-ipu-bridge-add-sensor.patch rename patches/6.18/{0004-dkms-v4l2-core-makefile-adaptation.patch => 0001-dkms-v4l2-core-makefile-adaptation.patch} (74%) rename patches/6.18/{0009-dkms-disable-tuner-build-in-v4l2-core.patch => 0002-dkms-disable-tuner-build-in-v4l2-core.patch} (56%) create mode 100644 patches/6.18/0003-Revert-media-v4l2-subdev-Make-struct-v4l2_subdev_str.patch rename patches/{6.17/0062-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch => 6.18/0004-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch} (90%) create mode 100644 patches/6.18/0006-ipu-bridge-makefile.patch rename patches/6.18/{0041-ipu-bridge-bkc-backport.patch => 0007-ipu-bridge-bkc-backport.patch} (83%) create mode 100644 patches/6.18/0008-ipu-bridge-add-sensors.patch create mode 100644 patches/6.18/0009-media-mc-Add-INTERNAL-pad-flag.patch delete mode 100644 patches/6.18/0040-ipu-bridge-makefile.patch delete mode 100644 patches/6.18/0042-ipu-bridge-add-sensor.patch create mode 100644 patches/7.0/0001-dkms-v4l2-core-makefile-adaptation.patch create mode 100644 patches/7.0/0002-dkms-disable-tuner-build-in-v4l2-core.patch create mode 100644 patches/7.0/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch create mode 100644 patches/7.0/0004-ipu-bridge-makefile.patch create mode 100644 patches/7.0/0005-ipu-bridge-bkc-backport.patch create mode 100644 patches/7.0/0006-ipu-bridge-add-sensors.patch create mode 100644 patches/7.0/0007-media-mc-Add-INTERNAL-pad-flag.patch diff --git a/dkms-kernel-source.sh b/dkms-kernel-source.sh index 5edece5d..2ef95a77 100755 --- a/dkms-kernel-source.sh +++ b/dkms-kernel-source.sh @@ -1,49 +1,53 @@ #!/bin/bash -if [[ -z "${kernelver:-}" ]]; then - kernelver="$(uname -r)" -fi - -major=$(echo "$kernelver" | cut -d- -f1| cut -d. -f1) -minor=$(echo "$kernelver" | cut -d- -f1| cut -d. -f2) -patch=$(echo "$kernelver" | cut -d- -f1| cut -d. -f3) - -if ! [[ "$major" =~ ^[0-9]+$ ]]; then major=0; fi -if ! [[ "$minor" =~ ^[0-9]+$ ]]; then minor=0; fi -if ! [[ "$patch" =~ ^[0-9]+$ ]]; then patch=0; fi - -echo "Downloading major $major minor $minor patch $patch" -if (( patch != 0 )); then - kernelprefix="linux-$major.$minor.$patch" -else - kernelprefix="linux-$major.$minor" -fi - -tarball="${kernelprefix}.tar.xz" -url="https://mirrors.edge.kernel.org/pub/linux/kernel/v${major}.x/${tarball}" - -need_dl=1 -if [[ -s "$tarball" ]] && xz -t "$tarball" 2>/dev/null; then - local_size=$(stat -c %s "$tarball") - remote_size=$(curl -fsSLI "$url" 2>/dev/null \ - | awk 'BEGIN{IGNORECASE=1} /^content-length:/ {gsub("\r",""); print $2}' \ - | tail -1) - if [[ -n "$remote_size" && "$local_size" == "$remote_size" ]]; then - echo "dkms-kernel-source.sh: reusing cached ${tarball} (${local_size} bytes)" - need_dl=0 +KVERS=("6.12.0" "6.17.0" "6.18.0" "7.0.0") + +for KVER in "${KVERS[@]}"; do + + [[ -d $KVER ]] && continue + + major=$(echo "$KVER" | cut -d- -f1| cut -d. -f1) + minor=$(echo "$KVER" | cut -d- -f1| cut -d. -f2) + patch=$(echo "$KVER" | cut -d- -f1| cut -d. -f3) + + if ! [[ "$major" =~ ^[0-9]+$ ]]; then major=0; fi + if ! [[ "$minor" =~ ^[0-9]+$ ]]; then minor=0; fi + if ! [[ "$patch" =~ ^[0-9]+$ ]]; then patch=0; fi + + echo "Downloading major $major minor $minor patch $patch" + if (( patch != 0 )); then + kernelprefix="linux-$major.$minor.$patch" + else + kernelprefix="linux-$major.$minor" + fi + + tarball="${kernelprefix}.tar.xz" + url="https://mirrors.edge.kernel.org/pub/linux/kernel/v${major}.x/${tarball}" + + need_dl=1 + if [[ -s "$tarball" ]] && xz -t "$tarball" 2>/dev/null; then + local_size=$(stat -c %s "$tarball") + remote_size=$(curl -fsSLI "$url" 2>/dev/null \ + | awk 'BEGIN{IGNORECASE=1} /^content-length:/ {gsub("\r",""); print $2}' \ + | tail -1) + if [[ -n "$remote_size" && "$local_size" == "$remote_size" ]]; then + echo "dkms-kernel-source.sh: reusing cached ${tarball} (${local_size} bytes)" + need_dl=0 + fi + fi + + if (( need_dl )); then + echo "Downloading $url" + wget --no-check-certificate -q --show-progress -N "$url" -O "$tarball" || { + echo "dkms-kernel-source.sh: failed to download ${url}" >&2 + return 1 + } + echo $@ + for arg in "$@"; do + echo "Extracting: $kernelprefix/$arg" + tar -xvf "$kernelprefix.tar.xz" "$kernelprefix/$arg" \ + --xform="s,^${kernelprefix//./\\.}/,$major.$minor.0/," + done + rm -rf "$kernelprefix.tar.xz" fi -fi - -if (( need_dl )); then - echo "Downloading $url" - wget --no-check-certificate -q --show-progress -N "$url" -O "$tarball" || { - echo "dkms-kernel-source.sh: failed to download ${url}" >&2 - return 1 - } -fi - -for arg in "$@"; do - echo "Extracting: $kernelprefix/$arg" - tar -xvf "$kernelprefix.tar.xz" "$kernelprefix/$arg" \ - --xform="s,^${kernelprefix//./\\.}/,$major.$minor.0/," done diff --git a/patches/0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch b/patches/0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch deleted file mode 100644 index 38b94a41..00000000 --- a/patches/0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch +++ /dev/null @@ -1,79 +0,0 @@ ---- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c -+++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c -@@ -46,6 +46,8 @@ static const u32 csi2_supported_codes[] = { - MEDIA_BUS_FMT_SGBRG8_1X8, - MEDIA_BUS_FMT_SGRBG8_1X8, - MEDIA_BUS_FMT_SRGGB8_1X8, -+ MEDIA_BUS_FMT_VYUY8_1X16, /* D4XX specific */ -+ MEDIA_BUS_FMT_Y8_1X8, /* D4XX specific */ - 0, - }; - ---- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h -+++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h -@@ -20,7 +20,7 @@ struct ipu7_isys_stream; - #define INVALID_VC_ID -1 - #define IPU7_NR_OF_CSI2_SINK_PADS 1U - #define IPU7_CSI2_PAD_SINK 0U --#define IPU7_NR_OF_CSI2_SRC_PADS 8U -+#define IPU7_NR_OF_CSI2_SRC_PADS 16U /* D4XX specific */ - #define IPU7_CSI2_PAD_SRC 1U - #define IPU7_NR_OF_CSI2_PADS (IPU7_NR_OF_CSI2_SINK_PADS + \ - IPU7_NR_OF_CSI2_SRC_PADS) ---- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c -+++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c -@@ -28,6 +28,8 @@ unsigned int ipu7_isys_mbus_code_to_mipi(u32 code) - return MIPI_CSI2_DT_RGB888; - case MEDIA_BUS_FMT_YUYV10_1X20: - return MIPI_CSI2_DT_YUV422_10B; -+ case MEDIA_BUS_FMT_VYUY8_1X16: /* D4XX specific */ -+ return MIPI_CSI2_DT_YUV422_8B; - case MEDIA_BUS_FMT_UYVY8_1X16: - case MEDIA_BUS_FMT_YUYV8_1X16: - return MIPI_CSI2_DT_YUV422_8B; -@@ -46,6 +48,7 @@ unsigned int ipu7_isys_mbus_code_to_mipi(u32 code) - case MEDIA_BUS_FMT_SGBRG8_1X8: - case MEDIA_BUS_FMT_SGRBG8_1X8: - case MEDIA_BUS_FMT_SRGGB8_1X8: -+ case MEDIA_BUS_FMT_Y8_1X8: /* D4XX specific */ - return MIPI_CSI2_DT_RAW8; - default: - WARN_ON(1); ---- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c -+++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c -@@ -82,7 +82,7 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { - {V4L2_PIX_FMT_UYVY, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, - IPU_INSYS_FRAME_FORMAT_UYVY}, - {V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16, -- IPU_INSYS_FRAME_FORMAT_YUYV}, -+ IPU_INSYS_FRAME_FORMAT_UYVY}, /* D4XX fix for incorrect RGB stream */ - {V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, - IPU_INSYS_FRAME_FORMAT_RGB565}, - {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, -@@ -91,6 +91,15 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { - IPU_INSYS_FRAME_FORMAT_RGB565}, - {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, - IPU_INSYS_FRAME_FORMAT_RGBA888}, -+ /* D4XX specific */ -+ {V4L2_PIX_FMT_Z16, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, -+ IPU_INSYS_FRAME_FORMAT_UYVY}, -+ {V4L2_PIX_FMT_Y8I, 16, 16, MEDIA_BUS_FMT_VYUY8_1X16, -+ IPU_INSYS_FRAME_FORMAT_UYVY}, -+ {V4L2_PIX_FMT_Y12I, 32, 24, MEDIA_BUS_FMT_RGB888_1X24, -+ IPU_INSYS_FRAME_FORMAT_RGBA888}, -+ {V4L2_PIX_FMT_GREY, 8, 8, MEDIA_BUS_FMT_Y8_1X8, -+ IPU_INSYS_FRAME_FORMAT_RAW8}, - }; - - static int video_open(struct file *file) ---- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h -+++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h -@@ -45,7 +45,7 @@ struct ipu7_isys_stream; - #define IPU_ISYS_NUM_RECV_QUEUE 1U - - #define IPU_ISYS_MIN_WIDTH 2U --#define IPU_ISYS_MIN_HEIGHT 2U -+#define IPU_ISYS_MIN_HEIGHT 1U /* D4XX specific */ - #define IPU_ISYS_MAX_WIDTH 8160U - #define IPU_ISYS_MAX_HEIGHT 8190U - diff --git a/patches/0052-module-version-conditional-symbol-namespace.patch b/patches/0050-module-Add-version-conditional-for-symbol-namespace-.patch similarity index 72% rename from patches/0052-module-version-conditional-symbol-namespace.patch rename to patches/0050-module-Add-version-conditional-for-symbol-namespace-.patch index 9f75c98d..d2e4ff88 100644 --- a/patches/0052-module-version-conditional-symbol-namespace.patch +++ b/patches/0050-module-Add-version-conditional-for-symbol-namespace-.patch @@ -1,46 +1,34 @@ -From e82bcd12246eed133513993db7422afb9cce6a7d Mon Sep 17 00:00:00 2001 -From: Peter Zijlstra -Date: Mon, 19 Jan 2026 11:41:13 -0700 -Subject: [PATCH 52/52] module: Add version conditional for symbol namespace +From 4b8d6b18b9431191c4c2cc9d2db1197641c29946 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:31:44 -0700 +Subject: [PATCH 50/59] module: Add version conditional for symbol namespace syntax Handle the namespace syntax change between kernel 6.12 and 6.17. In 6.17+, EXPORT_SYMBOL_NS_GPL requires quoted namespace strings. +Signed-off-by: florent pirou --- - .../media/pci/intel/ipu6/ipu6-buttress.c | 70 ++++++++++++++++--- - .../drivers/media/pci/intel/ipu6/ipu6-cpd.c | 12 +++- - .../drivers/media/pci/intel/ipu6/ipu6-dma.c | 54 ++++++++++++--- - .../media/pci/intel/ipu6/ipu6-fw-com.c | 55 ++++++++++++--- - .../drivers/media/pci/intel/ipu6/ipu6-isys.c | 6 +- - .../drivers/media/pci/intel/ipu6/ipu6-mmu.c | 12 +++- - .../drivers/media/pci/intel/ipu6/ipu6.c | 8 ++- + .../media/pci/intel/ipu6/ipu6-buttress.c | 28 ++++++++++++++ + .../drivers/media/pci/intel/ipu6/ipu6-cpd.c | 8 ++++ + .../drivers/media/pci/intel/ipu6/ipu6-dma.c | 36 ++++++++++++++++++ + .../media/pci/intel/ipu6/ipu6-fw-com.c | 37 +++++++++++++++++++ + .../drivers/media/pci/intel/ipu6/ipu6-isys.c | 6 +++ + .../drivers/media/pci/intel/ipu6/ipu6-mmu.c | 8 ++++ + .../drivers/media/pci/intel/ipu6/ipu6.c | 8 ++++ .../drivers/media/pci/intel/ipu6/ipu6.h | 1 + - 8 files changed, 180 insertions(+), 38 deletions(-) + 8 files changed, 132 insertions(+) -diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h -index a1b2e3c..b2c3d4e 100644 ---- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h -+++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - - #include "ipu6-buttress.h" - diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-buttress.c -index fc18cc6..dc5dbe5 100644 +index fc18cc6..2b89dd9 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-buttress.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-buttress.c @@ -508,7 +508,11 @@ bool ipu6_buttress_auth_done(struct ipu6_device *isp) return val == BUTTRESS_SECURITY_CTL_AUTH_DONE; } --EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, "INTEL_IPU6"); +#endif @@ -51,9 +39,8 @@ index fc18cc6..dc5dbe5 100644 return ret; } --EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, "INTEL_IPU6"); +#endif @@ -64,9 +51,8 @@ index fc18cc6..dc5dbe5 100644 dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0); sg_free_table(sgt); } --EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, "INTEL_IPU6"); +#endif @@ -77,9 +63,8 @@ index fc18cc6..dc5dbe5 100644 return -ETIMEDOUT; } --EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, "INTEL_IPU6"); +#endif @@ -90,9 +75,8 @@ index fc18cc6..dc5dbe5 100644 WARN_ON_ONCE(1); return -1; } --EXPORT_SYMBOL_NS_GPL(ipu6_get_i2c_bus_id, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_get_i2c_bus_id, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_get_i2c_bus_id, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_get_i2c_bus_id, "INTEL_IPU6"); +#endif @@ -103,9 +87,8 @@ index fc18cc6..dc5dbe5 100644 } local_irq_restore(flags); } --EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, "INTEL_IPU6"); +#endif @@ -116,9 +99,8 @@ index fc18cc6..dc5dbe5 100644 */ return div_u64(ns, isp->buttress.ref_clk); } --EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, "INTEL_IPU6"); +#endif @@ -126,16 +108,15 @@ index fc18cc6..dc5dbe5 100644 void ipu6_buttress_restore(struct ipu6_device *isp) { diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-cpd.c -index 21c1c12..fd81dc2 100644 +index 21c1c12..ef5ea74 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-cpd.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-cpd.c @@ -216,14 +216,22 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src) return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, "INTEL_IPU6"); +#endif @@ -145,9 +126,8 @@ index 21c1c12..fd81dc2 100644 ipu6_dma_free(adev, adev->pkg_dir_size, adev->pkg_dir, adev->pkg_dir_dma_addr, 0); } --EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, "INTEL_IPU6"); +#endif @@ -155,16 +135,15 @@ index 21c1c12..fd81dc2 100644 static int ipu6_cpd_validate_cpd(struct ipu6_device *isp, const void *cpd, unsigned long cpd_size, diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-dma.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-dma.c -index b71f66b..aa3e1f7 100644 +index 3887de7..0dc050b 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-dma.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-dma.c @@ -130,7 +130,11 @@ void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle, vaddr = info->vaddr + offset; clflush_cache_range(vaddr, size); } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, "INTEL_IPU6"); +#endif @@ -175,9 +154,8 @@ index b71f66b..aa3e1f7 100644 for_each_sg(sglist, sg, nents, i) clflush_cache_range(page_to_virt(sg_page(sg)), sg->length); } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, "INTEL_IPU6"); +#endif @@ -186,74 +164,68 @@ index b71f66b..aa3e1f7 100644 { ipu6_dma_sync_sg(sys, sgt->sgl, sgt->orig_nents); } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, "INTEL_IPU6"); +#endif void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size, dma_addr_t *dma_handle, gfp_t gfp, -@@ -239,7 +251,11 @@ out_kfree: +@@ -241,7 +253,11 @@ out_kfree: return NULL; } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, "INTEL_IPU6"); +#endif void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr, dma_addr_t dma_handle, unsigned long attrs) -@@ -292,7 +308,11 @@ void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr, +@@ -294,7 +310,11 @@ void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr, kfree(info); } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, "INTEL_IPU6"); +#endif int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma, void *addr, dma_addr_t iova, size_t size, -@@ -369,7 +389,11 @@ void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, +@@ -371,7 +391,11 @@ void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, mmu->tlb_invalidate(mmu); __free_iova(&mmu->dmap->iovad, iova); } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, "INTEL_IPU6"); +#endif int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist, int nents, enum dma_data_direction dir, -@@ -434,7 +458,11 @@ out_fail: +@@ -436,7 +460,11 @@ out_fail: return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, "INTEL_IPU6"); +#endif int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, enum dma_data_direction dir, unsigned long attrs) -@@ -449,14 +477,22 @@ int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, +@@ -451,14 +479,22 @@ int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt, return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, "INTEL_IPU6"); +#endif @@ -263,9 +235,8 @@ index b71f66b..aa3e1f7 100644 { ipu6_dma_unmap_sg(sys, sgt->sgl, sgt->nents, dir, attrs); } --EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, "INTEL_IPU6"); +#endif @@ -273,7 +244,7 @@ index b71f66b..aa3e1f7 100644 /* * Create scatter-list for the already allocated DMA buffer diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-com.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-com.c -index 45738f3..7a9fcd9 100644 +index 45738f3..947b281 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-com.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-com.c @@ -10,6 +10,7 @@ @@ -288,9 +259,8 @@ index 45738f3..7a9fcd9 100644 return ctx; } --EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, "INTEL_IPU6"); +#endif @@ -301,9 +271,8 @@ index 45738f3..7a9fcd9 100644 return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, "INTEL_IPU6"); +#endif @@ -314,9 +283,8 @@ index 45738f3..7a9fcd9 100644 return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, "INTEL_IPU6"); +#endif @@ -327,9 +295,8 @@ index 45738f3..7a9fcd9 100644 kfree(ctx); return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, "INTEL_IPU6"); +#endif @@ -340,9 +307,8 @@ index 45738f3..7a9fcd9 100644 return state == SYSCOM_STATE_READY; } --EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, "INTEL_IPU6"); +#endif @@ -353,9 +319,8 @@ index 45738f3..7a9fcd9 100644 return (void *)(q->host_address + index * q->token_size); } --EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, "INTEL_IPU6"); +#endif @@ -366,9 +331,8 @@ index 45738f3..7a9fcd9 100644 writel(wr, q_dmem + FW_COM_WR_REG); } --EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, "INTEL_IPU6"); +#endif @@ -379,9 +343,8 @@ index 45738f3..7a9fcd9 100644 return (void *)(q->host_address + rd * q->token_size); } --EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, "INTEL_IPU6"); +#endif @@ -392,18 +355,16 @@ index 45738f3..7a9fcd9 100644 writel(rd, q_dmem + FW_COM_RD_REG); } --EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, "INTEL_IPU6"); +#endif diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c -index 412afd0..79780d3 100644 +index 415ff06..236526d 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c -@@ -1773,6 +1773,11 @@ MODULE_AUTHOR("Bingbu Cao "); - MODULE_AUTHOR("Yunliang Ding "); +@@ -1772,5 +1772,11 @@ MODULE_AUTHOR("Yunliang Ding "); MODULE_AUTHOR("Hongju Wang "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Intel IPU6 input system driver"); @@ -414,17 +375,17 @@ index 412afd0..79780d3 100644 +MODULE_IMPORT_NS("INTEL_IPU6"); +MODULE_IMPORT_NS("INTEL_IPU_BRIDGE"); +#endif ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-mmu.c -index 57298ac..dc4b4e0 100644 +index 57298ac..ea73dd5 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-mmu.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-mmu.c @@ -518,7 +518,11 @@ int ipu6_mmu_hw_init(struct ipu6_mmu *mmu) return 0; } --EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, "INTEL_IPU6"); +#endif @@ -435,9 +396,8 @@ index 57298ac..dc4b4e0 100644 mmu->ready = false; spin_unlock_irqrestore(&mmu->ready_lock, flags); } --EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, "INTEL_IPU6"); +#endif @@ -445,16 +405,15 @@ index 57298ac..dc4b4e0 100644 static struct ipu6_dma_mapping *alloc_dma_mapping(struct ipu6_device *isp) { diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c -index 67894a3..6341775 100644 +index 738232e..0acc06a 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c @@ -302,7 +302,11 @@ void ipu6_configure_spc(struct ipu6_device *isp, ipu6_pkg_dir_configure_spc(isp, hw_variant, pkg_dir_idx, base, pkg_dir, pkg_dir_dma_addr); } --EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6); + EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6); +#else +EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, "INTEL_IPU6"); +#endif @@ -465,14 +424,26 @@ index 67894a3..6341775 100644 module_pci_driver(ipu6_pci_driver); --MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 17, 0) -+MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); + MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); +#else +MODULE_IMPORT_NS("INTEL_IPU_BRIDGE"); +#endif MODULE_AUTHOR("Sakari Ailus "); MODULE_AUTHOR("Tianshu Qiu "); MODULE_AUTHOR("Bingbu Cao "); +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h +index baad7f8..b76ab9d 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + #include "ipu6-buttress.h" + -- 2.43.0 + diff --git a/patches/0053-ipu6-isys-disable-src_pad-validation-for-dkms.patch b/patches/0051-ipu6-isys-disable-src_pad-validation-for-dkms.patch similarity index 77% rename from patches/0053-ipu6-isys-disable-src_pad-validation-for-dkms.patch rename to patches/0051-ipu6-isys-disable-src_pad-validation-for-dkms.patch index 21fd7677..71e00679 100644 --- a/patches/0053-ipu6-isys-disable-src_pad-validation-for-dkms.patch +++ b/patches/0051-ipu6-isys-disable-src_pad-validation-for-dkms.patch @@ -1,15 +1,18 @@ -Subject: [PATCH] ipu6: isys: disable src_pad validation for dkms +From 46c5925361ba73ccf75e28e6aa9d5c6fedfe6eec Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 08:26:40 -0700 +Subject: [PATCH 51/59] ipu6: isys: disable src_pad validation for dkms src_pad field is added by VTG to support UXC use case in BKC kernel. Hence, this patch is only applicable to BKC kernel header file. -Signed-off-by: Khai Wen, Ng +Signed-off-by: florent pirou --- - .../drivers/media/pci/intel/ipu6/ipu6-isys.c | 6 +++--- + ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c -index 415ff067e..f4bc8ca12 100644 +index 236526d..639eff0 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c @@ -175,7 +175,7 @@ isys_complete_ext_device_registration(struct ipu6_isys *isys, @@ -41,3 +44,4 @@ index 415ff067e..f4bc8ca12 100644 return ret; -- 2.43.0 + diff --git a/patches/6.18/0054-ipu6-isys-api-compat.patch b/patches/0052-ipu6-isys-kernel-6.18-api-compat.patch similarity index 76% rename from patches/6.18/0054-ipu6-isys-api-compat.patch rename to patches/0052-ipu6-isys-kernel-6.18-api-compat.patch index 16ac74ad..b70fdc7b 100644 --- a/patches/6.18/0054-ipu6-isys-api-compat.patch +++ b/patches/0052-ipu6-isys-kernel-6.18-api-compat.patch @@ -1,5 +1,16 @@ +From 2a6e46f02437f06647eba21d83122a48599ec376 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 2 Jun 2026 17:42:52 +0000 +Subject: [PATCH 52/59] ipu6-isys: kernel 6.18 api compat + +Signed-off-by: florent pirou +--- + .../drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 4 ++++ + .../drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 12 ++++++++++++ + 2 files changed, 16 insertions(+) + diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c -index 5f2f836ef..fc58fe5a0 100644 +index 5f2f836..fc58fe5 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c @@ -98,7 +98,11 @@ s64 ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 *csi2) @@ -15,7 +26,7 @@ index 5f2f836ef..fc58fe5a0 100644 static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c -index 927d92ea9..426cf3b48 100644 +index 927d92e..426cf3b 100644 --- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c @@ -1063,6 +1063,17 @@ static u32 get_remote_pad_stream(struct media_pad *r_pad) @@ -44,3 +55,6 @@ index 927d92ea9..426cf3b48 100644 v4l2_subdev_unlock_state(state); +-- +2.43.0 + diff --git a/patches/0053-isys-video-let-v4l2-set-default-colorspace.patch b/patches/0053-isys-video-let-v4l2-set-default-colorspace.patch new file mode 100644 index 00000000..fb0edd3e --- /dev/null +++ b/patches/0053-isys-video-let-v4l2-set-default-colorspace.patch @@ -0,0 +1,25 @@ +From 9e926e3af72b5958271571be24a15b4789ceece8 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Sat, 14 Feb 2026 14:04:59 -0700 +Subject: [PATCH 53/59] isys-video: let v4l2 set default colorspace + +Signed-off-by: florent pirou +--- + ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +index 426cf3b..be767a3 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +@@ -288,7 +288,6 @@ static void __ipu6_isys_vidioc_try_fmt_vid_cap(struct ipu6_isys_video *av, + &f->fmt.pix.bytesperline, &f->fmt.pix.sizeimage); + + f->fmt.pix.field = V4L2_FIELD_NONE; +- f->fmt.pix.colorspace = V4L2_COLORSPACE_RAW; + f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + f->fmt.pix.quantization = V4L2_QUANTIZATION_DEFAULT; + f->fmt.pix.xfer_func = V4L2_XFER_FUNC_DEFAULT; +-- +2.43.0 + diff --git a/patches/0054-ipu6-dkms-add-isys-makefile-adaptation.patch b/patches/0054-ipu6-dkms-add-isys-makefile-adaptation.patch new file mode 100644 index 00000000..ae6f4bbc --- /dev/null +++ b/patches/0054-ipu6-dkms-add-isys-makefile-adaptation.patch @@ -0,0 +1,63 @@ +From 9a6501fd451f7584172019dba52b4318a507cf18 Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Mon, 12 Jan 2026 03:45:03 -0700 +Subject: [PATCH 54/59] ipu6-dkms: add isys makefile adaptation + +*ipu6-isys: compile ISYS RESET and ACPI PDATA support + +Signed-off-by: Florent Pirou +--- + ipu6-drivers/drivers/media/pci/intel/ipu6/Makefile | 13 +++++++++++++ + ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c | 1 + + .../drivers/media/pci/intel/ipu6/psys/ipu-psys.c | 1 + + 3 files changed, 15 insertions(+) + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/Makefile b/ipu6-drivers/drivers/media/pci/intel/ipu6/Makefile +index 67c13c9..5ac7944 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/Makefile ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/Makefile +@@ -1,5 +1,16 @@ + # SPDX-License-Identifier: GPL-2.0-only + ++KERNEL_VERSION := $(shell echo $(KERNELRELEASE) | sed 's/[^0-9.]*\([0-9]\.[0-9]*\)\..*/\1.0/') ++ ++CC := ${CC} -I ${M}/../../../../../../include -I ${M}/../../../../../../$(KERNEL_VERSION)/include-overrides -DCONFIG_DEBUG_FS -DCONFIG_INTEL_IPU_ACPI -DCONFIG_INTEL_IPU6_ACPI -DCONFIG_VIDEO_INTEL_IPU6_ISYS_RESET -DCONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ ++KBUILD_EXTRA_SYMBOLS += ${M}/../../../../../../Module.symvers ++ ++ccflags-y := -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" ++ ++export EXTERNAL_BUILD = 1 ++export CONFIG_VIDEO_INTEL_IPU6 = m ++ + intel-ipu6-y := ipu6.o \ + ipu6-bus.o \ + ipu6-dma.o \ +@@ -22,4 +33,6 @@ intel-ipu6-isys-y := ipu6-isys.o \ + ipu6-isys-dwc-phy.o + + obj-$(CONFIG_VIDEO_INTEL_IPU6) += intel-ipu6-isys.o ++ ++subdir-ccflags-y += -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" + obj-$(CONFIG_VIDEO_INTEL_IPU6) += psys/ +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c +index 0acc06a..42646bc 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6.c +@@ -971,3 +971,4 @@ MODULE_AUTHOR("Yunliang Ding "); + MODULE_AUTHOR("Hongju Wang "); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Intel IPU6 PCI driver"); ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/psys/ipu-psys.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/psys/ipu-psys.c +index 6423238..66c1c28 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/psys/ipu-psys.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/psys/ipu-psys.c +@@ -2749,3 +2749,4 @@ MODULE_IMPORT_NS(INTEL_IPU6); + MODULE_IMPORT_NS("DMA_BUF"); + MODULE_IMPORT_NS("INTEL_IPU6"); + #endif ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +-- +2.43.0 + diff --git a/patches/0055-ipu6-isys-add-d4xx-pixel-format-support.patch b/patches/0055-ipu6-isys-add-d4xx-pixel-format-support.patch new file mode 100644 index 00000000..563e0430 --- /dev/null +++ b/patches/0055-ipu6-isys-add-d4xx-pixel-format-support.patch @@ -0,0 +1,144 @@ +From db7bb683c6d09d3489a304d8335061fa6aad644b Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:50:59 -0700 +Subject: [PATCH 55/59] ipu6-isys : add d4xx pixel format support + +Signed-off-by: florent pirou +--- + .../drivers/media/pci/intel/ipu6/ipu6-fw-isys.h | 1 + + .../drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 4 ++++ + .../drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c | 6 ++++++ + .../drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 11 +++++++++++ + ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.h | 4 ++-- + 5 files changed, 24 insertions(+), 2 deletions(-) + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h +index 545180c..0ec08ee 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h +@@ -209,6 +209,7 @@ enum ipu6_fw_isys_frame_format_type { + IPU6_FW_ISYS_FRAME_FORMAT_RGBA888, /* 32 bit RGBA, 1 plane, A=Alpha */ + IPU6_FW_ISYS_FRAME_FORMAT_QPLANE6, /* Internal, for advanced ISP */ + IPU6_FW_ISYS_FRAME_FORMAT_BINARY_8, /* byte stream, used for jpeg. */ ++ IPU6_FW_ISYS_FRAME_FORMAT_VYUY, /* 16 bit YUV 422, VYUY interleaved */ + N_IPU6_FW_ISYS_FRAME_FORMAT + }; + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +index fc58fe5..e80985c 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +@@ -26,10 +26,13 @@ + #include "ipu6-platform-isys-csi2-reg.h" + + static const u32 csi2_supported_codes[] = { ++ MEDIA_BUS_FMT_Y8_1X8, ++ MEDIA_BUS_FMT_Y10_1X10, + MEDIA_BUS_FMT_RGB565_1X16, + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_UYVY8_1X16, + MEDIA_BUS_FMT_YUYV8_1X16, ++ MEDIA_BUS_FMT_VYUY8_1X16, + MEDIA_BUS_FMT_SBGGR10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, +@@ -47,6 +50,7 @@ static const u32 csi2_supported_codes[] = { + MEDIA_BUS_FMT_META_12, + MEDIA_BUS_FMT_META_16, + MEDIA_BUS_FMT_META_24, ++ MEDIA_BUS_FMT_FIXED, + 0 + }; + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c +index 0a06de5..76c7e43 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-subdev.c +@@ -26,6 +26,8 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code) + case MEDIA_BUS_FMT_UYVY8_1X16: + case MEDIA_BUS_FMT_YUYV8_1X16: + case MEDIA_BUS_FMT_META_16: ++ case MEDIA_BUS_FMT_Y10_1X10: ++ case MEDIA_BUS_FMT_VYUY8_1X16: + return 16; + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: +@@ -44,6 +46,7 @@ unsigned int ipu6_isys_mbus_code_to_bpp(u32 code) + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + case MEDIA_BUS_FMT_META_8: ++ case MEDIA_BUS_FMT_Y8_1X8: + return 8; + default: + WARN_ON(1); +@@ -60,6 +63,8 @@ unsigned int ipu6_isys_mbus_code_to_mipi(u32 code) + return MIPI_CSI2_DT_RGB888; + case MEDIA_BUS_FMT_UYVY8_1X16: + case MEDIA_BUS_FMT_YUYV8_1X16: ++ case MEDIA_BUS_FMT_Y10_1X10: ++ case MEDIA_BUS_FMT_VYUY8_1X16: + return MIPI_CSI2_DT_YUV422_8B; + case MEDIA_BUS_FMT_SBGGR16_1X16: + case MEDIA_BUS_FMT_SGBRG16_1X16: +@@ -80,6 +85,7 @@ unsigned int ipu6_isys_mbus_code_to_mipi(u32 code) + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: ++ case MEDIA_BUS_FMT_Y8_1X8: + return MIPI_CSI2_DT_RAW8; + default: + /* return unavailable MIPI data type - 0x3f */ +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +index be767a3..d9cd3a3 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +@@ -40,6 +40,14 @@ + #include "ipu6-platform-regs.h" + + const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { ++ { V4L2_PIX_FMT_GREY, 8, 8, MEDIA_BUS_FMT_Y8_1X8, ++ IPU6_FW_ISYS_FRAME_FORMAT_RAW8 }, ++ { V4L2_PIX_FMT_Y10, 16, 10, MEDIA_BUS_FMT_Y10_1X10, ++ IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, ++ { V4L2_PIX_FMT_Y8I, 16, 16, MEDIA_BUS_FMT_VYUY8_1X16, ++ IPU6_FW_ISYS_FRAME_FORMAT_UYVY}, ++ { V4L2_PIX_FMT_Z16, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, ++ IPU6_FW_ISYS_FRAME_FORMAT_UYVY}, + { V4L2_PIX_FMT_SBGGR12, 16, 12, MEDIA_BUS_FMT_SBGGR12_1X12, + IPU6_FW_ISYS_FRAME_FORMAT_RAW16 }, + { V4L2_PIX_FMT_SGBRG12, 16, 12, MEDIA_BUS_FMT_SGBRG12_1X12, +@@ -86,6 +94,8 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { + IPU6_FW_ISYS_FRAME_FORMAT_YUYV}, + { V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, + IPU6_FW_ISYS_FRAME_FORMAT_RGB565 }, ++ { V4L2_PIX_FMT_Y12I, 32, 24, MEDIA_BUS_FMT_RGB888_1X24, ++ IPU6_FW_ISYS_FRAME_FORMAT_RGBA888 }, + { V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, + IPU6_FW_ISYS_FRAME_FORMAT_RGBA888 }, + { V4L2_META_FMT_GENERIC_8, 8, 8, MEDIA_BUS_FMT_META_8, +@@ -96,6 +106,7 @@ const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { + IPU6_FW_ISYS_FRAME_FORMAT_RAW12, true }, + { V4L2_META_FMT_GENERIC_CSI2_16, 16, 16, MEDIA_BUS_FMT_META_16, + IPU6_FW_ISYS_FRAME_FORMAT_RAW16, true }, ++ { V4L2_META_FMT_D4XX, 8, 8, MEDIA_BUS_FMT_FIXED, 0 }, + }; + + static int video_open(struct file *file) +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.h +index 4c7ba6e..6a425c8 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.h +@@ -43,8 +43,8 @@ struct ipu6_bus_device; + #define IPU6_ISYS_SIZE_PROXY_SEND_QUEUE 5 + #define IPU6_ISYS_NUM_RECV_QUEUE 1 + +-#define IPU6_ISYS_MIN_WIDTH 2U +-#define IPU6_ISYS_MIN_HEIGHT 2U ++#define IPU6_ISYS_MIN_WIDTH 1U ++#define IPU6_ISYS_MIN_HEIGHT 1U + #define IPU6_ISYS_MAX_WIDTH 4672U + #define IPU6_ISYS_MAX_HEIGHT 3416U + +-- +2.43.0 + diff --git a/patches/0056-Revert-ipu6-isys-lt6911uxc-2-pads-linked-to-ipu-2-po.patch b/patches/0056-Revert-ipu6-isys-lt6911uxc-2-pads-linked-to-ipu-2-po.patch new file mode 100644 index 00000000..822457fd --- /dev/null +++ b/patches/0056-Revert-ipu6-isys-lt6911uxc-2-pads-linked-to-ipu-2-po.patch @@ -0,0 +1,80 @@ +From 4759fd5e10e9b92e4e73b318619115270583cddc Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Mon, 19 Jan 2026 09:02:23 -0700 +Subject: [PATCH 56/59] Revert "ipu6-isys: lt6911uxc 2 pads linked to ipu 2 + ports for split mode" + +This reverts commit b1c889b6240723d849da32f615ed8945d08d4e21. + +Change Description: +single camera in bios setting, pprval for dummy port. +create software node and link connection in ipu-brige. +match the connection and port num in v4l2-async. +finally create the media links. + +Signed-off-by: Chen Meng J +Signed-off-by: Florent Pirou +--- + .../drivers/media/pci/intel/ipu6/ipu6-isys.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c +index 639eff0..526c916 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c +@@ -158,7 +158,9 @@ static int isys_isr_one(struct ipu6_bus_device *adev); + static int + isys_complete_ext_device_registration(struct ipu6_isys *isys, + struct v4l2_subdev *sd, ++#if 0 + s16 src_pad, ++#endif + struct ipu6_isys_csi2_config *csi2) + { + struct device *dev = &isys->adev->auxdev.dev; +@@ -175,6 +177,7 @@ isys_complete_ext_device_registration(struct ipu6_isys *isys, + ret = -ENOENT; + goto unregister_subdev; + } ++ + #if 0 + if (src_pad >= 0) + i = (unsigned int)src_pad; +@@ -187,6 +190,7 @@ isys_complete_ext_device_registration(struct ipu6_isys *isys, + goto unregister_subdev; + } + #endif ++ + ret = media_create_pad_link(&sd->entity, i, + &isys->csi2[csi2->port].asd.sd.entity, + 0, MEDIA_LNK_FL_ENABLED | +@@ -273,8 +277,12 @@ static int isys_register_ext_subdev(struct ipu6_isys *isys, + if (!sd_info->csi2) + return 0; + ++#if 0 + /* src_pad is useless for non MIPI split case. Set it to '-1'.*/ + return isys_complete_ext_device_registration(isys, sd, -1, sd_info->csi2); ++#else ++ return isys_complete_ext_device_registration(isys, sd, sd_info->csi2); ++#endif + + skip_put_adapter: + i2c_put_adapter(adapter); +@@ -1008,9 +1016,13 @@ static int isys_notifier_bound(struct v4l2_async_notifier *notifier, + + dev_dbg(&isys->adev->auxdev.dev, "bind %s nlanes is %d port is %d\n", + sd->name, s_asd->csi2.nlanes, s_asd->csi2.port); ++#if 0 + ret = isys_complete_ext_device_registration(isys, sd, + -1, + &s_asd->csi2); ++#else ++ ret = isys_complete_ext_device_registration(isys, sd, &s_asd->csi2); ++#endif + if (ret) + return ret; + +-- +2.43.0 + diff --git a/patches/0057-ipu6-isys-video-force-START-then-CAPTURE-distinct-st.patch b/patches/0057-ipu6-isys-video-force-START-then-CAPTURE-distinct-st.patch new file mode 100644 index 00000000..81621498 --- /dev/null +++ b/patches/0057-ipu6-isys-video-force-START-then-CAPTURE-distinct-st.patch @@ -0,0 +1,294 @@ +From 400b766dcbce3c427000211d9e02cda26f8c20e3 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Mon, 23 Mar 2026 04:43:04 -0700 +Subject: [PATCH 57/59] ipu6-isys: video: force START then CAPTURE distinct + start_stream_firmware commands + +Change introduced at [start_stream_firmware](https://github.com/intel/ipu6-drivers/commit/f310264660de132ed7dd7634cca8c03714a774ad#diff-5d8bb31c30c9393a0d7b5d59f0389db65f8189d9270aea922df3564c0614cb25R1907) +hands-up sending multiple concurrent/overlapping stream_capture commands +to the IPU6 firmware at several point in time. +.e.g. STREAM_CAPTURE_ACK to STREAM_CAPTURE_DONE overlaps +in the STREAM_START_AND_CAPTURE_ACK to STREAM_START_AND_CAPTURE_DONE interval. + +Reverting the start_stream_firmware to a 2-phase approach +limit this stream_capture accumulation to max two commands +sent the IPU6 firmware at any given point of time. + +* isys-video : remove START_AND_CAPTURE to avoid multi streams start race-conditions +* isys-video: add stream stop and close state message transition +* isys-video : add timeout on initial STREAM_CAPTURE + +Signed-off-by: florent pirou +--- + .../media/pci/intel/ipu6/ipu6-fw-isys.h | 1 + + .../media/pci/intel/ipu6/ipu6-isys-queue.c | 7 +- + .../media/pci/intel/ipu6/ipu6-isys-video.c | 97 +++++++++++-------- + .../media/pci/intel/ipu6/ipu6-isys-video.h | 1 + + .../drivers/media/pci/intel/ipu6/ipu6-isys.c | 2 + + 5 files changed, 61 insertions(+), 47 deletions(-) + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h +index 0ec08ee..e08b239 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-fw-isys.h +@@ -65,6 +65,7 @@ struct ipu6_isys; + */ + #define IPU6_ISYS_OPEN_RETRY 2000 + #define IPU6_ISYS_CLOSE_RETRY 2000 ++#define IPU6_ISYS_CAPTURE_TIMEOUT_JIFFIES msecs_to_jiffies(2) + #define IPU6_FW_CALL_TIMEOUT_JIFFIES msecs_to_jiffies(2000) + #ifdef CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET + #define IPU6_LIB_CALL_TIMEOUT_JIFFIES_RESET msecs_to_jiffies(200) +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c +index 67cf253..60346a6 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c +@@ -1023,13 +1023,8 @@ void ipu6_isys_queue_buf_ready(struct ipu6_isys_stream *stream, + ivb = vb2_buffer_to_ipu6_isys_video_buffer(vvb); + addr = ivb->dma_addr; + +- if (info->pin.addr != addr) { +- if (first) +- dev_err(dev, "Unexpected buffer address %pad\n", +- &addr); +- first = false; ++ if (info->pin.addr != addr) + continue; +- } + + if (info->error_info.error == + IPU6_FW_ISYS_ERROR_HW_REPORTED_STR2MMIO) { +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +index d9cd3a3..a4e9617 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +@@ -564,7 +564,7 @@ bool is_support_vc(struct ipu6_isys_video *av) + } + + #endif +-static int start_stream_firmware(struct ipu6_isys_video *av, ++int start_stream_firmware(struct ipu6_isys_video *av, + struct ipu6_isys_buffer_list *bl) + { + struct ipu6_fw_isys_stream_cfg_data_abi *stream_cfg; +@@ -644,23 +644,11 @@ static int start_stream_firmware(struct ipu6_isys_video *av, + } + + reinit_completion(&stream->stream_start_completion); +-#ifdef CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET +- if(bl && is_support_vc(av)) { +-#else +- if (bl) { +-#endif +- send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START_AND_CAPTURE; +- ipu6_fw_isys_dump_frame_buff_set(dev, buf, +- stream_cfg->nof_output_pins); +- ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, +- buf, msg->dma_addr, +- sizeof(*buf), send_type); +- } else { +- send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START; +- ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, +- send_type); +- } ++ dev_dbg(dev, "start stream: start\n"); + ++ send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_START; ++ ret = ipu6_fw_isys_simple_cmd(av->isys, stream->stream_handle, ++ send_type); + if (ret < 0) { + dev_err(dev, "can't start streaming (%d)\n", ret); + goto out_stream_close; +@@ -680,7 +668,11 @@ static int start_stream_firmware(struct ipu6_isys_video *av, + } + #ifdef CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET + if (bl && !is_support_vc(av)) { +- dev_dbg(dev, "start stream: capture\n"); ++#else ++ if (bl) { ++#endif ++ reinit_completion(&stream->stream_initialcapture_completion); ++ dev_dbg(dev, "start stream: initial capture\n"); + send_type = IPU6_FW_ISYS_SEND_TYPE_STREAM_CAPTURE; + ipu6_fw_isys_dump_frame_buff_set(dev, buf, stream_cfg->nof_output_pins); + ret = ipu6_fw_isys_complex_cmd(av->isys, stream->stream_handle, +@@ -692,14 +684,21 @@ static int start_stream_firmware(struct ipu6_isys_video *av, + dev_err(dev, "can't queue buffers (%d)\n", ret); + goto out_stream_close; + } ++ ++ tout = wait_for_completion_timeout(&stream->stream_initialcapture_completion, ++ IPU6_ISYS_CAPTURE_TIMEOUT_JIFFIES); ++ if (!tout) { ++ dev_warn(dev, "start initial capture time out\n"); ++ } else if (stream->error) { ++ dev_warn(dev, "start initial capture error: %d\n", stream->error); ++ } else { ++ dev_dbg(dev, "start initial capture : complete\n"); ++ } ++ ret = 0; + } + else + dev_dbg(dev, "start stream: complete\n"); + +-#else +- dev_dbg(dev, "start stream: complete\n"); +-#endif +- + return 0; + + out_stream_close: +@@ -728,7 +727,7 @@ out_put_stream_opened: + return ret; + } + +-static void stop_streaming_firmware(struct ipu6_isys_video *av) ++int stop_streaming_firmware(struct ipu6_isys_video *av) + { + struct device *dev = &av->isys->adev->auxdev.dev; + struct ipu6_isys_stream *stream = av->stream; +@@ -741,7 +740,7 @@ static void stop_streaming_firmware(struct ipu6_isys_video *av) + + if (ret < 0) { + dev_err(dev, "can't stop stream (%d)\n", ret); +- return; ++ return -EIO; + } + + tout = wait_for_completion_timeout(&stream->stream_stop_completion, +@@ -750,15 +749,23 @@ static void stop_streaming_firmware(struct ipu6_isys_video *av) + #else + IPU6_FW_CALL_TIMEOUT_JIFFIES); + #endif +- if (!tout) +- dev_warn(dev, "stream stop time out\n"); +- else if (stream->error) +- dev_warn(dev, "stream stop error: %d\n", stream->error); +- else +- dev_dbg(dev, "stop stream: complete\n"); ++ if (!tout) { ++ dev_err(dev, "stream stop time out for entity %s\n", ++ av->vdev.entity.name); ++ ret = -ETIMEDOUT; ++ } else if (stream->error) { ++ dev_err(dev, "stream stop failed for entity %s with error %d\n", ++ av->vdev.entity.name, stream->error); ++ ret = -EIO; ++ } else { ++ dev_dbg(dev, "stop stream complete for entity %s\n", ++ av->vdev.entity.name); ++ ret = 0; ++ } ++ return ret; + } + +-static void close_streaming_firmware(struct ipu6_isys_video *av) ++int close_streaming_firmware(struct ipu6_isys_video *av) + { + struct ipu6_isys_stream *stream = av->stream; + struct device *dev = &av->isys->adev->auxdev.dev; +@@ -770,7 +777,7 @@ static void close_streaming_firmware(struct ipu6_isys_video *av) + IPU6_FW_ISYS_SEND_TYPE_STREAM_CLOSE); + if (ret < 0) { + dev_err(dev, "can't close stream (%d)\n", ret); +- return; ++ return -EIO; + } + + tout = wait_for_completion_timeout(&stream->stream_close_completion, +@@ -779,12 +786,19 @@ static void close_streaming_firmware(struct ipu6_isys_video *av) + #else + IPU6_FW_CALL_TIMEOUT_JIFFIES); + #endif +- if (!tout) +- dev_warn(dev, "stream close time out\n"); +- else if (stream->error) +- dev_warn(dev, "stream close error: %d\n", stream->error); +- else +- dev_dbg(dev, "close stream: complete\n"); ++ if (!tout) { ++ dev_err(dev, "stream close time out for entity %s\n", ++ av->vdev.entity.name); ++ ret = -ETIMEDOUT; ++ } else if (stream->error) { ++ dev_err(dev, "stream close failed for entity %s with error %d\n", ++ av->vdev.entity.name, stream->error); ++ ret = -EIO; ++ } else { ++ dev_dbg(dev, "close stream complete for entity %s\n", ++ av->vdev.entity.name); ++ ret = 0; ++ } + + #ifdef CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET + stream->last_sequence = atomic_read(&stream->sequence); +@@ -793,6 +807,7 @@ static void close_streaming_firmware(struct ipu6_isys_video *av) + + #endif + put_stream_opened(av); ++ return ret; + } + + int ipu6_isys_video_prepare_stream(struct ipu6_isys_video *av, +@@ -1118,7 +1133,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, + r_pad = media_pad_remote_pad_first(&av->pad); + r_stream = get_remote_pad_stream(r_pad); + if (!state) { +- stop_streaming_firmware(av); ++ ret = stop_streaming_firmware(av); + + /* stop sub-device which connects with video */ + dev_dbg(dev, "disable streams %s pad:%d mask:0x%llx for %s\n", +@@ -1132,7 +1147,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, + return ret; + } + +- close_streaming_firmware(av); ++ ret = close_streaming_firmware(av); + } else { + ret = start_stream_firmware(av, bl); + if (ret) { +@@ -1158,7 +1173,7 @@ int ipu6_isys_video_set_streaming(struct ipu6_isys_video *av, int state, + return 0; + + out_media_entity_stop_streaming_firmware: +- stop_streaming_firmware(av); ++ ret = stop_streaming_firmware(av); + + return ret; + } +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h +index 5fa1643..a2ddcea 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h +@@ -68,6 +68,7 @@ struct ipu6_isys_stream { + struct completion stream_open_completion; + struct completion stream_close_completion; + struct completion stream_start_completion; ++ struct completion stream_initialcapture_completion; + struct completion stream_stop_completion; + struct ipu6_isys *isys; + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c +index 526c916..3460cf1 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys.c +@@ -370,6 +370,7 @@ static void isys_stream_init(struct ipu6_isys *isys) + mutex_init(&isys->streams[i].mutex); + init_completion(&isys->streams[i].stream_open_completion); + init_completion(&isys->streams[i].stream_close_completion); ++ init_completion(&isys->streams[i].stream_initialcapture_completion); + init_completion(&isys->streams[i].stream_start_completion); + init_completion(&isys->streams[i].stream_stop_completion); + INIT_LIST_HEAD(&isys->streams[i].queues); +@@ -1711,6 +1712,7 @@ static int isys_isr_one(struct ipu6_bus_device *adev) + + break; + case IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK: ++ complete(&stream->stream_initialcapture_completion); + break; + case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE: + case IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE: +-- +2.43.0 + diff --git a/patches/0058-ipu6-isys-allow-virtual-channels-on-16-csi2-input-vi.patch b/patches/0058-ipu6-isys-allow-virtual-channels-on-16-csi2-input-vi.patch new file mode 100644 index 00000000..6b224e56 --- /dev/null +++ b/patches/0058-ipu6-isys-allow-virtual-channels-on-16-csi2-input-vi.patch @@ -0,0 +1,27 @@ +From dcf39f6d5cfcf6702bf9f83cac8688234ed4f584 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Fri, 23 Jan 2026 16:55:59 -0700 +Subject: [PATCH 58/59] ipu6-isys : allow virtual-channels on 16 csi2 input + video capture + +Signed-off-by: florent pirou +--- + ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h +index ea609dd..3b4328b 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h +@@ -21,7 +21,7 @@ struct ipu6_isys_stream; + #define INVALID_VC_ID -1 + #define NR_OF_CSI2_SINK_PADS 1 + #define CSI2_PAD_SINK 0 +-#define NR_OF_CSI2_SRC_PADS 8 ++#define NR_OF_CSI2_SRC_PADS 16 + #define CSI2_PAD_SRC 1 + #define NR_OF_CSI2_PADS (NR_OF_CSI2_SINK_PADS + NR_OF_CSI2_SRC_PADS) + +-- +2.43.0 + diff --git a/patches/0059-ipu6-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch b/patches/0059-ipu6-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch new file mode 100644 index 00000000..9a077ece --- /dev/null +++ b/patches/0059-ipu6-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch @@ -0,0 +1,1206 @@ +From cda612b6406031a8ba437cc4df8f8510813f1291 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Fri, 23 Jan 2026 18:42:59 -0700 +Subject: [PATCH 59/59] ipu6-isys: add video VIDIOC_S_EXT_CTRLS callbacks by + streamid + +* isys-video: add video VIDIOC_S_EXT_CTRLS callbacks by streamid +* isys-csi: add graph walk subdev to get frame desc by streamid +* isys-video: add V4L2_CID_IPU definitions + +Signed-off-by: florent pirou +--- + .../media/pci/intel/ipu6/ipu6-isys-csi2.c | 314 ++++++++- + .../media/pci/intel/ipu6/ipu6-isys-csi2.h | 8 +- + .../pci/intel/ipu6/ipu6-isys-video-ext.h | 52 ++ + .../media/pci/intel/ipu6/ipu6-isys-video.c | 622 +++++++++++++++++- + .../media/pci/intel/ipu6/ipu6-isys-video.h | 4 + + 5 files changed, 992 insertions(+), 8 deletions(-) + create mode 100644 ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video-ext.h + +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +index e80985c..657f671 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +@@ -84,24 +84,36 @@ static const struct ipu6_csi2_error dphy_rx_errors[] = { + s64 ipu6_isys_csi2_get_link_freq(struct ipu6_isys_csi2 *csi2) + { + struct media_pad *src_pad; ++ struct v4l2_subdev_state *s_state; + struct v4l2_subdev *ext_sd; + struct device *dev; ++ int ret = -EPIPE; + + if (!csi2) + return -EINVAL; + ++ s_state = v4l2_subdev_get_unlocked_active_state(&csi2->asd.sd); ++ if (!s_state) ++ return ret; ++ + dev = &csi2->isys->adev->auxdev.dev; +- src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); ++ src_pad = media_pad_remote_pad_first(&csi2->asd.sd.entity.pads[CSI2_PAD_SINK]); + if (IS_ERR(src_pad)) { +- dev_err(dev, "can't get source pad of %s (%ld)\n", +- csi2->asd.sd.name, PTR_ERR(src_pad)); +- return PTR_ERR(src_pad); ++ dev_err(dev, ++ "can't get source pad of %s\n", ++ csi2->asd.sd.name); ++ return -EINVAL; + } + + ext_sd = media_entity_to_v4l2_subdev(src_pad->entity); + if (WARN(!ext_sd, "Failed to get subdev for %s\n", csi2->asd.sd.name)) + return -ENODEV; + ++ dev_dbg(dev, ++ "%s:%u -> %s:%u\n", ++ csi2->asd.sd.name, CSI2_PAD_SINK, ++ ext_sd->name, src_pad->index); ++ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 18, 0) + return v4l2_get_link_freq(src_pad, 0, 0); + #else +@@ -353,6 +365,146 @@ static int ipu6_isys_csi2_set_stream(struct v4l2_subdev *sd, + return ret; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++static int ipu6_isys_csi2_link_validate(struct media_link *link) ++{ ++ ++ struct v4l2_subdev *sd = ++ media_entity_to_v4l2_subdev(link->sink->entity); ++ struct device *dev = sd->entity.graph_obj.mdev->dev; ++ struct ipu6_isys_subdev *asd; ++ struct ipu6_isys_csi2 *csi2; ++ struct v4l2_subdev_state *s_state; ++ struct v4l2_mbus_framefmt *s_fmt; ++ struct v4l2_subdev *s_sd; ++ struct media_pad *s_pad; ++ u32 s_stream, code; ++ int ret = -EPIPE; ++ ++ if (!link->source->entity) ++ return ret; ++ ++ asd = to_ipu6_isys_subdev(sd); ++ csi2 = to_ipu6_isys_csi2(asd); ++ dev = &asd->isys->adev->auxdev.dev; ++ ++ s_sd = media_entity_to_v4l2_subdev(link->source->entity); ++ s_state = v4l2_subdev_get_unlocked_active_state(s_sd); ++ if (!s_state) ++ return ret; ++ ++ dev_dbg(dev, "%s: validating link \"%s\":%u -> \"%s\"\n",__func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name); ++ ++ return 0; ++} ++ ++static int ipu6_isys_csi2_streams_by_sources(struct ipu6_isys_csi2 *csi2, ++ u32 pad, u32 stream, bool on) ++{ ++ struct media_entity *entity = &csi2->asd.sd.entity; ++ struct media_device *mdev = entity->graph_obj.mdev; ++ struct device *dev = &csi2->isys->adev->auxdev.dev; ++ struct v4l2_subdev *sd = NULL; ++ struct v4l2_subdev_state *v4l2_state; ++ struct media_graph graph; ++ struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; ++ struct v4l2_mbus_frame_desc desc; ++ unsigned int i; ++ int ret; ++ ++ if (!mdev) ++ return -EPIPE; ++ ++ mutex_lock(&mdev->graph_mutex); ++ if (media_graph_walk_init(&graph, mdev)) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s: walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_VID_MUX) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->get_frame_desc) ++ continue; ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ ret = sd->ops->pad->get_frame_desc(sd, pad, &desc); ++ if (ret) ++ continue; ++ ++ if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) ++ continue; ++ ++ for (i = 0; i < desc.num_entries; i++) { ++ if (stream == desc.entry[i].stream) { ++ desc_entry = &desc.entry[i]; ++ break; ++ } ++ } ++ ++ if (!desc_entry) ++ continue; ++ ++ if (desc_entry->bus.csi2.vc >= NR_OF_CSI2_VC) ++ continue; ++ ++ ++ dev_dbg(dev, "%s: found %s subdev stream:%u vc/dt:%u/0x%x\n", __func__, ++ sd->name, ++ desc_entry->stream, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->disable_streams || !sd->ops->pad->enable_streams) ++ break; ++ ++ v4l2_state = v4l2_subdev_get_unlocked_active_state(sd); ++ if (!v4l2_state) ++ break; ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (on) ++ ret = sd->ops->pad->enable_streams(sd, v4l2_state, pad, BIT_ULL(stream)); ++ else ++ ret = sd->ops->pad->disable_streams(sd, v4l2_state, pad, BIT_ULL(stream)); ++ if (ret) ++ break; ++ ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++ return 0; ++ } ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++ ++error_graph_walk_source: ++ return -EINVAL; ++} ++#endif ++ + /* + * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set + * of streams. +@@ -392,6 +544,14 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd, + if (ret) + return ret; + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ if (!ipu6_isys_csi2_streams_by_sources(csi2, sink_pad, sink_stream, true)) { ++ csi2->stream_count++; ++ return 0; ++ } ++ dev_dbg(&csi2->isys->adev->auxdev.dev, ++ "remote stream on fallback\n"); ++#endif + r_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); + r_sd = media_entity_to_v4l2_subdev(r_pad->entity); + +@@ -429,6 +589,15 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd, + if (ret) + return ret; + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ if (!ipu6_isys_csi2_streams_by_sources(csi2, sink_pad, sink_stream, false)) { ++ if (--csi2->stream_count) ++ return 0; ++ goto ret; ++ } ++ dev_dbg(&csi2->isys->adev->auxdev.dev, ++ "remote stream off fallback\n"); ++#endif + r_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); + r_sd = media_entity_to_v4l2_subdev(r_pad->entity); + +@@ -436,7 +605,7 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd, + + if (--csi2->stream_count) + return 0; +- ++ret: + dev_dbg(&csi2->isys->adev->auxdev.dev, + "stream off CSI2-%u with %u lanes\n", csi2->port, csi2->nlanes); + +@@ -552,7 +721,11 @@ static const struct v4l2_subdev_ops csi2_sd_ops = { + }; + + static const struct media_entity_operations csi2_entity_ops = { ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ .link_validate = ipu6_isys_csi2_link_validate, ++#else + .link_validate = v4l2_subdev_link_validate, ++#endif + .has_pad_interdep = v4l2_subdev_has_pad_interdep, + }; + +@@ -702,3 +875,134 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, + #endif + return 0; + } ++ ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++int ipu6_isys_csi2_walk_remote_desc(u32 source_stream, ++ struct ipu6_isys_csi2 *csi2, ++ struct media_entity *source_entity, ++ struct v4l2_mbus_frame_desc_entry *entry, ++ int *nr_queues) ++{ ++ struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; ++ struct device *dev = &csi2->isys->adev->auxdev.dev; ++ struct v4l2_mbus_frame_desc desc; ++ struct v4l2_subdev *source; ++ struct media_pad *pad; ++ struct media_graph graph; ++ struct media_entity *entity; ++ struct media_device *mdev; ++ struct v4l2_subdev *sd; ++ unsigned int pad_id; ++ u32 stream_id = source_stream; ++ unsigned int i; ++ int ret; ++ ++#ifdef CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET ++ csi2->is_multiple = false; ++#endif ++ ++ source = media_entity_to_v4l2_subdev(source_entity); ++ if (!source) ++ return -EPIPE; ++ ++ pad = media_pad_remote_pad_first(&csi2->asd.pad[CSI2_PAD_SINK]); ++ if (!pad) ++ return -EPIPE; ++ ++ dev_dbg(dev, "%s: source pad/stream:%u/%u\n", __func__,pad->index, source_stream); ++ pad_id = pad->index; ++ entity = source_entity; ++ mdev = entity->graph_obj.mdev; ++ if (!mdev) { ++ ret = -EPIPE; ++ goto error_graph_walk_source; ++ } ++ ++ mutex_lock(&mdev->graph_mutex); ++ ret = media_graph_walk_init(&graph, mdev); ++ if (ret) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s: walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_CAM_SENSOR) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->get_frame_desc) ++ continue; ++ ++ dev_dbg(dev, "%s(): %s pad/stream: %u/%u\n", ++ __func__, ++ sd->name, ++ pad_id, ++ source_stream); ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ ret = sd->ops->pad->get_frame_desc(sd, pad_id, &desc); ++ if (ret) ++ continue; ++ ++ ret = -EINVAL; ++ ++ if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) ++ continue; ++ ++ for (i = 0; i < desc.num_entries; i++) { ++ if (source_stream == desc.entry[i].stream) { ++ desc_entry = &desc.entry[i]; ++ break; ++ } ++ } ++ ++ if (!desc_entry) ++ continue; ++ ++ if (desc_entry->bus.csi2.vc >= NR_OF_CSI2_VC) ++ continue; ++ ++ *entry = *desc_entry; ++ ++ for (i = 0; i < desc.num_entries; i++) { ++ if (desc_entry->bus.csi2.vc == desc.entry[i].bus.csi2.vc) ++ (*nr_queues)++; ++ } ++ ++ dev_dbg(dev, "%s: found frame desc stream:%u vc/dt:%u/0x%x\n", __func__, ++ desc_entry->stream, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ ++ ret = 0; ++ break; ++ } ++ ++#ifdef CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET ++ csi2->is_multiple = true; ++ dev_dbg(dev, "set csi2->is_multiple is true.\n"); ++#endif ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++error_graph_walk_source: ++ return ret; ++} ++#endif +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h +index 3b4328b..f5ef4d4 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.h +@@ -81,5 +81,11 @@ int ipu6_isys_csi2_get_remote_desc(u32 source_stream, + struct media_entity *source_entity, + struct v4l2_mbus_frame_desc_entry *entry, + int *nr_queues); +- ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++int ipu6_isys_csi2_walk_remote_desc(u32 source_stream, ++ struct ipu6_isys_csi2 *csi2, ++ struct media_entity *source_entity, ++ struct v4l2_mbus_frame_desc_entry *entry, ++ int *nr_queues); ++#endif + #endif /* IPU6_ISYS_CSI2_H */ +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video-ext.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video-ext.h +new file mode 100644 +index 0000000..66fee7f +--- /dev/null ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video-ext.h +@@ -0,0 +1,52 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 - 2025 Intel Corporation ++ */ ++ ++#define V4L2_CID_IPU_BASE (V4L2_CID_USER_BASE + 0x1080) ++ ++#define V4L2_CID_IPU_STORE_CSI2_HEADER (V4L2_CID_IPU_BASE + 2) ++#define V4L2_CID_IPU_ISYS_COMPRESSION (V4L2_CID_IPU_BASE + 3) ++ ++#define V4L2_CID_IPU_QUERY_SUB_STREAM (V4L2_CID_IPU_BASE + 4) ++#define V4L2_CID_IPU_SET_SUB_STREAM (V4L2_CID_IPU_BASE + 5) ++ ++#define V4L2_CID_IPU_ENUMERATE_LINK (V4L2_CID_IPU_BASE + 6) ++ ++#define VIDIOC_IPU_GET_DRIVER_VERSION \ ++ _IOWR('v', BASE_VIDIOC_PRIVATE + 3, uint32_t) ++ ++enum ipu6_isys_enum_link_state { ++ IPU6_ISYS_LINK_STATE_DISABLED = 0, ++ IPU6_ISYS_LINK_STATE_ENABLED = 1, ++ IPU6_ISYS_LINK_STATE_DONE = 2, ++ IPU6_ISYS_LINK_STATE_MD = 3, ++ IPU6_ISYS_LINK_STATE_MAX, ++}; ++ ++static struct media_pad *other_pad(struct media_pad *pad); ++bool has_src_pad_stream_active(struct v4l2_subdev *sd, u32 stream, u32 pad); ++bool get_src_pad_by_src_stream(struct v4l2_subdev *sd, u32 stream, u32 *s_pad); ++ ++/* needed for callback */ ++extern int ipu6_isys_inherit_ctrls(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu6_isys_set_fmt_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu6_isys_enum_frameintervals_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu6_isys_enum_fmt_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu6_isys_enum_framesizes_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu6_isys_set_parm_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu6_isys_get_parm_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++ ++extern int media_pipeline_enumerate_by_stream_cb( ++ struct ipu6_isys_video *av, ++ int (*cb_fn)(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, ++ void *data), ++ void *data); +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +index a4e9617..d7a62f9 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +@@ -37,6 +37,9 @@ + #include "ipu6-isys-csi2.h" + #include "ipu6-isys-queue.h" + #include "ipu6-isys-video.h" ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++#include "ipu6-isys-video-ext.h" ++#endif + #include "ipu6-platform-regs.h" + + const struct ipu6_isys_pixelformat ipu6_isys_pfmts[] = { +@@ -122,7 +125,11 @@ static int video_open(struct file *file) + return -EIO; + } + mutex_unlock(&isys->mutex); +- ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ /* ipu_isys inherit remote sd ctrls */ ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_ENABLED && media_pad_remote_pad_first(&av->pad)) ++ media_pipeline_enumerate_by_stream_cb(av, ipu6_isys_inherit_ctrls, NULL); ++#endif + return v4l2_fh_open(file); + } + +@@ -188,7 +195,50 @@ static int ipu6_isys_vidioc_enum_fmt(struct file *file, void *fh, + struct v4l2_fmtdesc *f) + { + unsigned int i, num_found; ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ struct ipu6_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_mbus_code_enum mce; ++ int ret=-EINVAL; + ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DONE) { ++ ++ mce.index = f->index; ++ mce.pad = 0; ++ ++ /* poll remote sensors */ ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu6_isys_enum_fmt_subdev, &mce); ++ if (!ret) { ++ ret=-EINVAL; ++ for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { ++ if ((ipu6_isys_pfmts[i].is_meta && ++ f->type != V4L2_BUF_TYPE_META_CAPTURE) || ++ (!ipu6_isys_pfmts[i].is_meta && ++ f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) ++ continue; ++ ++ if (f->mbus_code && f->mbus_code != mce.code) ++ continue; ++ ++ if (mce.code != ipu6_isys_pfmts[i].code) ++ continue; ++ ++ /* Code found */ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "%s: sd_mbus:0x%x, sd_code::0x%x\n", ++ __func__, ++ ipu6_isys_pfmts[i].code, ++ ipu6_isys_pfmts[i].pixelformat); ++ ++ f->flags = 0; ++ f->pixelformat = ipu6_isys_pfmts[i].pixelformat; ++ ++ return 0; ++ } ++ } ++ return ret; ++ } ++#endif + for (i = 0, num_found = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { + if ((ipu6_isys_pfmts[i].is_meta && + f->type != V4L2_BUF_TYPE_META_CAPTURE) || +@@ -217,6 +267,48 @@ static int ipu6_isys_vidioc_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) + { + unsigned int i; ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ struct ipu6_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_size_enum fse; ++ int ret = -EINVAL; ++ ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DONE) { ++ ++ for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { ++ if (fsize->pixel_format != ipu6_isys_pfmts[i].pixelformat) ++ continue; ++ ++ fse.code = ipu6_isys_pfmts[i].code; ++ fse.index = fsize->index; ++ ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu6_isys_enum_framesizes_subdev, &fse); ++ if (ret) ++ continue; ++ ++ if (!fse.max_width && !fse.max_height) { ++ fsize->discrete.width = 0; ++ fsize->discrete.height = 0; ++ return -EINVAL; ++ } ++ ++ /* Code found */ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "%s: sd_mbus:0x%x, sd_code::0x%x, WxH:%ux%u\n", ++ __func__, ++ ipu6_isys_pfmts[i].code, ++ ipu6_isys_pfmts[i].pixelformat, ++ fse.max_width, ++ fse.max_height); ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; ++ fsize->discrete.width = fse.max_width; ++ fsize->discrete.height = fse.max_height; ++ return 0; ++ } ++ return -EINVAL; ++ } ++#endif + + if (fsize->index > 0) + return -EINVAL; +@@ -239,6 +331,169 @@ static int ipu6_isys_vidioc_enum_framesizes(struct file *file, void *fh, + return -EINVAL; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++/* extended v4l2_ctrl_ops */ ++static int ipu6_isys_video_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ipu6_isys_video *av = ctrl->priv; ++ struct ipu6_isys *isys = av->isys; ++ mutex_lock(&isys->mutex); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_IPU_ENUMERATE_LINK: ++ av->enum_link_state = ctrl->val; ++ break; ++ } ++ ++ mutex_unlock(&isys->mutex); ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops ipu6_isys_video_ctrl_ops = { ++ .s_ctrl = ipu6_isys_video_s_ctrl, ++}; ++ ++static const struct v4l2_ctrl_config ipu6_isys_video_enum_link = { ++ .ops = &ipu6_isys_video_ctrl_ops, ++ .id = V4L2_CID_IPU_ENUMERATE_LINK, ++ .name = "Enumerate graph link", ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .min = 0, ++ .max = IPU6_ISYS_LINK_STATE_MAX, ++ .step = 1, ++ .def = 0, ++}; ++ ++/* extended v4l2_ioctl_ops */ ++static struct media_pad *other_pad(struct media_pad *pad) ++{ ++ struct media_link *link; ++ ++ list_for_each_entry(link, &pad->entity->links, list) { ++ if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) ++ != MEDIA_LNK_FL_DATA_LINK) ++ continue; ++ ++ return link->source == pad ? link->sink : link->source; ++ } ++ ++ WARN_ON(1); ++ return NULL; ++} ++ ++static int ipu6_isys_get_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct ipu6_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_interval fi; ++ int ret = -ENOLINK; ++ ++ a->parm.capture.timeperframe.numerator = 1; ++ a->parm.capture.timeperframe.denominator = 30; ++ ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DISABLED) ++ return 0; ++ ++ if (media_pad_remote_pad_first(&av->pad)) { ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu6_isys_get_parm_subdev, &fi); ++ ++ if (!ret) { ++ a->parm.capture.timeperframe.numerator = fi.interval.numerator; ++ a->parm.capture.timeperframe.denominator = fi.interval.denominator; ++ } ++ } ++ return ret; ++} ++ ++static int ipu6_isys_set_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct ipu6_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_interval fi; ++ int ret = -ENOLINK; ++ ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DISABLED) ++ return 0; ++ ++ fi.interval.numerator = a->parm.capture.timeperframe.numerator; ++ fi.interval.denominator = a->parm.capture.timeperframe.denominator; ++ ++ if (media_pad_remote_pad_first(&av->pad)) ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu6_isys_set_parm_subdev, &fi); ++ ++ return ret; ++} ++ ++static int ipu6_isys_enum_frameintervals(struct file *file, void *fh, ++ struct v4l2_frmivalenum *intervals) ++{ ++ struct ipu6_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_interval_enum fie; ++ unsigned int i, num_found; ++ int ret=-EINVAL; ++ ++ /* poll remote sensors */ ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DONE) { ++ ++ for (i = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { ++ if (intervals->pixel_format != ipu6_isys_pfmts[i].pixelformat) ++ continue; ++ ++ fie.code = ipu6_isys_pfmts[i].code; ++ fie.index = intervals->index; ++ fie.width = intervals->width; ++ fie.height = intervals->height; ++ ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu6_isys_enum_frameintervals_subdev, &fie); ++ if (ret) ++ continue; ++ ++ if (!fie.interval.numerator && ++ !fie.interval.denominator) { ++ intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ intervals->discrete.numerator = 1; ++ intervals->discrete.denominator = 30; ++ return -EINVAL; ++ } ++ ++ /* Code found */ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "%s: sd_mbus:0x%x,sd_code::0x%x,WxH:%ux%u,fps:%u/%u\n", ++ __func__, ++ ipu6_isys_pfmts[i].code, ++ ipu6_isys_pfmts[i].pixelformat, ++ fie.width, fie.height, ++ fie.interval.numerator,fie.interval.denominator); ++ ++ intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ intervals->discrete.numerator = fie.interval.numerator; ++ intervals->discrete.denominator = fie.interval.denominator; ++ return 0; ++ } ++ return -EINVAL; ++ } ++ ++ if (intervals->index > 0) ++ return -EINVAL; ++ ++ for (i = 0, num_found = 0; i < ARRAY_SIZE(ipu6_isys_pfmts); i++) { ++ if (intervals->pixel_format != ipu6_isys_pfmts[i].pixelformat) ++ continue; ++ ++ /* Code found */ ++ intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ intervals->discrete.numerator = 1; ++ intervals->discrete.denominator = 30; ++ ++ return 0; ++ } ++ return -EINVAL; ++} ++#endif ++ + static int ipu6_isys_vidioc_g_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *f) + { +@@ -314,6 +569,30 @@ static int ipu6_isys_vidioc_try_fmt_vid_cap(struct file *file, void *fh, + + __ipu6_isys_vidioc_try_fmt_vid_cap(av, f); + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DONE) ++ { ++ int ret = 0; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .pad = 0, ++ }; ++ struct v4l2_mbus_framefmt format = { ++ .width = f->fmt.pix.width, ++ .height = f->fmt.pix.height, ++ .code = ipu6_isys_get_isys_format(f->fmt.pix.pixelformat, 0)->code, ++ .field = f->fmt.pix.field, ++ .colorspace = f->fmt.pix.colorspace, ++ .ycbcr_enc = f->fmt.pix.ycbcr_enc, ++ .quantization = f->fmt.pix.quantization, ++ .xfer_func = f->fmt.pix.xfer_func, ++ }; ++ fmt.format = format; ++ ret = media_pipeline_enumerate_by_stream_cb(av, ipu6_isys_set_fmt_subdev, &fmt); ++ if (ret) ++ return -EINVAL; ++ } ++#endif + return 0; + } + +@@ -343,7 +622,50 @@ static int ipu6_isys_vidioc_s_fmt_vid_cap(struct file *file, void *fh, + { + struct ipu6_isys_video *av = video_drvdata(file); + ++#ifndef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS + ipu6_isys_vidioc_try_fmt_vid_cap(file, fh, f); ++#else ++ struct media_pad *source_pad = media_pad_remote_pad_first(&av->pad); ++ struct media_pad *remote_pad = source_pad; ++ struct v4l2_subdev *sd = NULL; ++ ++ if (vb2_is_busy(&av->aq.vbq)) ++ return -EBUSY; ++ ++ __ipu6_isys_vidioc_try_fmt_vid_cap(av, f); ++ ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DONE) { ++ ++ int ret = 0; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .pad = 0, ++ }; ++ struct v4l2_mbus_framefmt format = { ++ .width = f->fmt.pix.width, ++ .height = f->fmt.pix.height, ++ .code = ipu6_isys_get_isys_format(f->fmt.pix.pixelformat, 0)->code, ++ .field = f->fmt.pix.field, ++ .colorspace = f->fmt.pix.colorspace, ++ .ycbcr_enc = f->fmt.pix.ycbcr_enc, ++ .quantization = f->fmt.pix.quantization, ++ .xfer_func = f->fmt.pix.xfer_func, ++ }; ++ fmt.format = format; ++ ret = media_pipeline_enumerate_by_stream_cb(av, ipu6_isys_set_fmt_subdev, &fmt); ++ if (ret) ++ return -EINVAL; ++ ++ /* TODO: set format for CSI-2 ++ do { ++ // Non-subdev nodes can be safely ignored here. ++ if (!is_media_entity_v4l2_subdev(remote_pad->entity)) ++ continue; ++ // Set only for IPU CSI entities ++ } while ((remote_pad = media_pad_remote_pad_first(&remote_pad->entity->pads[0]))); ++ */ ++ } ++#endif + av->pix_fmt = f->fmt.pix; + + return 0; +@@ -1178,6 +1500,266 @@ out_media_entity_stop_streaming_firmware: + return ret; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++int ipu6_isys_set_fmt_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_format *fmt = ++ (struct v4l2_subdev_format *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->set_fmt) ++ ret = sd->ops->pad->set_fmt(sd, NULL, fmt); ++ ++ return ret; ++} ++ ++int ipu6_isys_get_parm_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_interval *fi = ++ (struct v4l2_subdev_frame_interval *)data; ++ struct v4l2_subdev_state *state = v4l2_subdev_get_unlocked_active_state(sd); ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->get_frame_interval) ++ ret = sd->ops->pad->get_frame_interval(sd, state, fi); ++ ++ return ret; ++} ++ ++int ipu6_isys_set_parm_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_interval *fi = ++ (struct v4l2_subdev_frame_interval *)data; ++ struct v4l2_subdev_state *state = v4l2_subdev_get_unlocked_active_state(sd); ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->set_frame_interval) ++ ret = sd->ops->pad->set_frame_interval(sd, state, fi); ++ ++ return ret; ++} ++ ++int ipu6_isys_enum_fmt_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_mbus_code_enum *mce = ++ (struct v4l2_subdev_mbus_code_enum *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->enum_mbus_code) ++ ret = sd->ops->pad->enum_mbus_code(sd, NULL, mce); ++ ++ return ret; ++} ++ ++int ipu6_isys_enum_framesizes_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_size_enum *fse = ++ (struct v4l2_subdev_frame_size_enum *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->enum_frame_size) ++ ret = sd->ops->pad->enum_frame_size(sd, NULL, fse); ++ ++ return ret; ++} ++ ++int ipu6_isys_enum_frameintervals_subdev(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_interval_enum *fie = ++ (struct v4l2_subdev_frame_interval_enum *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->enum_frame_interval) ++ ret = sd->ops->pad->enum_frame_interval(sd, NULL, fie); ++ ++ return ret; ++} ++ ++int ipu6_isys_inherit_ctrls(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ ret = v4l2_ctrl_add_handler(&av->ctrl_handler, ++ sd->ctrl_handler, NULL, true); ++ return ret; ++} ++ ++bool has_src_pad_stream_active(struct v4l2_subdev *sd, u32 stream, u32 pad) ++{ ++ struct v4l2_subdev_state *state; ++ struct v4l2_subdev_route *routes; ++ bool has_active_source_stream = false; ++ unsigned int i; ++ ++ state = v4l2_subdev_lock_and_get_active_state(sd); ++ if (!state) ++ return has_active_source_stream; ++ ++ dev_dbg(sd->dev, "%s(): check %s pad/stream: %u/%u has V4L2_SUBDEV_ROUTE_FL_ACTIVE flag\n", ++ __func__, ++ sd->name, ++ pad, ++ stream); ++ routes = state->routing.routes; ++ for (i = 0; i < state->routing.num_routes; i++) { ++ dev_dbg(sd->dev, "%s(): %s pad/stream: %u/%u flags=0x%x\n", ++ __func__, ++ sd->name, ++ routes[i].source_pad, ++ routes[i].source_stream, ++ routes[i].flags); ++ if (routes[i].source_pad == pad && ++ routes[i].source_stream == stream && ++ routes[i].flags == V4L2_SUBDEV_ROUTE_FL_ACTIVE) { ++ dev_dbg(sd->dev, "%s(): %s pad/stream: %u/%u has V4L2_SUBDEV_ROUTE_FL_ACTIVE flag\n", ++ __func__, ++ sd->name, ++ routes[i].source_pad, ++ routes[i].source_stream); ++ has_active_source_stream = true; ++ break; ++ } ++ } ++ ++ v4l2_subdev_unlock_state(state); ++ ++ return has_active_source_stream; ++} ++ ++bool get_src_pad_by_src_stream(struct v4l2_subdev *sd, u32 stream, u32 *s_pad) ++{ ++ struct v4l2_subdev_state *state; ++ struct v4l2_subdev_route *routes; ++ bool has_source_pad = false; ++ unsigned int i; ++ ++ if (!s_pad) ++ return has_source_pad; ++ ++ state = v4l2_subdev_lock_and_get_active_state(sd); ++ if (!state) ++ return has_source_pad; ++ ++ routes = state->routing.routes; ++ for (i = 0; i < state->routing.num_routes; i++) { ++ if (routes[i].source_stream == stream) { ++ dev_dbg(sd->dev, "%s(): Found %s pad/stream: %u/%u\n", ++ __func__, ++ sd->name, ++ routes[i].source_pad, ++ stream); ++ *s_pad = routes[i].source_pad; ++ has_source_pad = true; ++ break; ++ } ++ } ++ ++ v4l2_subdev_unlock_state(state); ++ return has_source_pad; ++} ++ ++int media_pipeline_enumerate_by_stream_cb( ++ struct ipu6_isys_video *av, ++ int (*cb_fn)(struct ipu6_isys_video *av, ++ struct v4l2_subdev *sd, ++ void *data), ++ void *data) ++{ ++ int i; ++ struct media_graph graph; ++ struct media_entity *entity = &av->vdev.entity; ++ struct media_device *mdev = entity->graph_obj.mdev; ++ struct device *dev = entity->graph_obj.mdev->dev; ++ struct media_pad *remote_pad = media_pad_remote_pad_unique(&av->pad); ++ struct ipu6_isys_stream *stream = av->stream; ++ struct ipu6_isys_subdev *asd; ++ struct v4l2_subdev *sd; ++ unsigned int pad_id; ++ u32 stream_id; ++ int ret = -ENOLINK; ++ ++ if (!remote_pad) { ++ dev_err(dev, ++ "%s:%d no remote pad found\n", ++ __func__, __LINE__); ++ goto error_graph_walk_source; ++ } ++ ++ pad_id = remote_pad->index; ++ sd = media_entity_to_v4l2_subdev(remote_pad->entity); ++ if(!sd) { ++ dev_err(dev, ++ "%s():%d no stream found on remote pad %u\n", ++ __func__, __LINE__, pad_id); ++ goto error_graph_walk_source; ++ } ++ stream_id = ipu6_isys_get_src_stream_by_src_pad(sd, pad_id); ++ dev_dbg(dev, ++ "%s(): Check %s (vc=%u) inheritence from %s pad/stream %u/%u\n", ++ __func__, av->vdev.name, av->vc, ++ sd->name, pad_id, stream_id); ++ ++ mutex_lock(&mdev->graph_mutex); ++ ret = media_graph_walk_init(&graph, mdev); ++ if (ret) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s(): walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_CAM_SENSOR) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with src pad on same stream id */ ++ if(!get_src_pad_by_src_stream(sd, stream_id, &pad_id)) ++ continue; ++ ++ /* access only subdevices on source stream active route */ ++ if(!has_src_pad_stream_active(sd, stream_id, pad_id)) ++ continue; ++ ++ dev_dbg(dev, "%s(): %s pad/stream: %u/%u\n", ++ __func__, ++ sd->name, ++ pad_id, ++ stream_id); ++ ++ /* call function once */ ++ ret = cb_fn(av, sd, data); ++ break; ++ } ++ av->enum_link_state = IPU6_ISYS_LINK_STATE_DONE; ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++error_graph_walk_source: ++ return ret; ++} ++#endif ++ + static const struct v4l2_ioctl_ops ipu6_v4l2_ioctl_ops = { + .vidioc_querycap = ipu6_isys_vidioc_querycap, + .vidioc_enum_fmt_vid_cap = ipu6_isys_vidioc_enum_fmt, +@@ -1198,6 +1780,11 @@ static const struct v4l2_ioctl_ops ipu6_v4l2_ioctl_ops = { + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_expbuf = vb2_ioctl_expbuf, ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ .vidioc_g_parm = ipu6_isys_get_parm, ++ .vidioc_s_parm = ipu6_isys_set_parm, ++ .vidioc_enum_frameintervals = ipu6_isys_enum_frameintervals, ++#endif + }; + + static const struct media_entity_operations entity_ops = { +@@ -1339,6 +1926,14 @@ int ipu6_isys_setup_video(struct ipu6_isys_video *av, + av->source_stream = route->sink_stream; + v4l2_subdev_unlock_state(state); + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ if (av->enum_link_state == IPU6_ISYS_LINK_STATE_DONE) ++ ret = ipu6_isys_csi2_walk_remote_desc(route->sink_stream, ++ to_ipu6_isys_csi2(asd), ++ *source_entity, &entry, ++ nr_queues); ++ else ++#endif + ret = ipu6_isys_csi2_get_remote_desc(av->source_stream, + to_ipu6_isys_csi2(asd), + *source_entity, &entry, +@@ -1443,9 +2038,29 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av) + if (ret) + goto out_media_entity_cleanup; + ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ /* create v4l2 ctrl for capture video node */ ++ ret = v4l2_ctrl_handler_init(&av->ctrl_handler, 0); ++ if (ret) { ++ dev_err(&av->isys->adev->auxdev.dev, ++ "failed to init v4l2 ctrl handler for %s\n", av->vdev.name); ++ goto out_ctrl_handler_cleanup; ++ } ++ v4l2_ctrl_new_custom(&av->ctrl_handler, &ipu6_isys_video_enum_link, av); ++ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "ext-ctrls: %s: set video_enum_link\n", av->vdev.name); ++ ++ av->vdev.ctrl_handler = &av->ctrl_handler; ++ return ret; ++ ++out_ctrl_handler_cleanup: ++ v4l2_ctrl_handler_free(&av->ctrl_handler); ++#else + return ret; ++#endif + +-out_media_entity_cleanup: ++ out_media_entity_cleanup: + vb2_video_unregister_device(&av->vdev); + media_entity_cleanup(&av->vdev.entity); + +@@ -1460,6 +2075,9 @@ out_free_watermark: + + void ipu6_isys_video_cleanup(struct ipu6_isys_video *av) + { ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ v4l2_ctrl_handler_free(&av->ctrl_handler); ++#endif + vb2_video_unregister_device(&av->vdev); + media_entity_cleanup(&av->vdev.entity); + mutex_destroy(&av->mutex); +diff --git a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h +index a2ddcea..01009a6 100644 +--- a/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h ++++ b/ipu6-drivers/drivers/media/pci/intel/ipu6/ipu6-isys-video.h +@@ -110,6 +110,10 @@ struct ipu6_isys_video { + unsigned int skipframe; + unsigned int start_streaming; + #endif ++#ifdef CONFIG_VIDEO_INTEL_IPU6_EXT_CTRLS ++ struct v4l2_ctrl_handler ctrl_handler; ++ unsigned int enum_link_state; /* state for link enumeration by vc */ ++#endif + }; + + #define ipu6_isys_queue_to_video(__aq) \ +-- +2.43.0 + diff --git a/patches/0064-media-ipu7-isys-csi2-get-link-frequency-from.patch b/patches/0064-media-ipu7-isys-csi2-get-link-frequency-from.patch deleted file mode 100644 index dd263e4a..00000000 --- a/patches/0064-media-ipu7-isys-csi2-get-link-frequency-from.patch +++ /dev/null @@ -1,52 +0,0 @@ -From b46c88f66951b03e155b98985f28b3d86e413179 Mon Sep 17 00:00:00 2001 -From: "Yew, Chang Ching" -Date: Thu, 22 Jan 2026 08:05:37 +0800 -Subject: media: ipu7: ipu7-isys-csi2: get link frequency from pad - -In case driver does not have v4l2-control that stores link frequency, -try to retrieve link frequency from pad - -Signed-off-by: Yew, Chang Ching ---- - ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c -index 9c16ae9a0e5bd..60e7856a5e2f9 100644 ---- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c -+++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c -@@ -51,6 +51,8 @@ static const u32 csi2_supported_codes[] = { - s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) - { - struct media_pad *src_pad; -+ struct v4l2_subdev *ext_sd; -+ s64 ret; - - src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); - if (IS_ERR(src_pad)) { -@@ -60,7 +62,21 @@ s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) - return PTR_ERR(src_pad); - } - -- return v4l2_get_link_freq(src_pad, 0, 0); -+ ext_sd = media_entity_to_v4l2_subdev(src_pad->entity); -+ if (WARN(!ext_sd, "Failed to get subdev for %s\n", csi2->asd.sd.name)) -+ return -ENODEV; -+ -+ ret = v4l2_get_link_freq(ext_sd->ctrl_handler, 0, 0); -+ if (ret < 0) { -+ ret = v4l2_get_link_freq(src_pad, 0, 0); -+ if (ret < 0) { -+ dev_err(csi2->asd.sd.dev, -+ "Failed to get link frequency for %s\n", -+ csi2->asd.sd.name); -+ return ret; -+ } -+ } -+ return ret; - } - - static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, --- -2.51.1 - diff --git a/patches/0100-media-ipu7-ipu7-isys-csi2-get-link-frequency-from-pa.patch b/patches/0100-media-ipu7-ipu7-isys-csi2-get-link-frequency-from-pa.patch new file mode 100644 index 00000000..ca1e17eb --- /dev/null +++ b/patches/0100-media-ipu7-ipu7-isys-csi2-get-link-frequency-from-pa.patch @@ -0,0 +1,82 @@ +From 28c302a28b8df599567eb13d8b7a6937f169b3bd Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 2 Jun 2026 18:16:11 +0000 +Subject: [PATCH 100/109] media: ipu7: ipu7-isys-csi2: get link frequency from + pad + +In case driver does not have v4l2-control that stores link frequency, +try to retrieve link frequency from pad + +Signed-off-by: Yew, Chang Ching +Signed-off-by: florent pirou +--- + .../media/pci/intel/ipu7/ipu7-isys-csi2.c | 35 ++++++++----------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c +index 6ba21c3..356020f 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c +@@ -49,35 +49,19 @@ static const u32 csi2_supported_codes[] = { + 0, + }; + +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0) +-s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) +-{ +- struct media_pad *src_pad; +- +- src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); +- if (IS_ERR(src_pad)) { +- dev_err(&csi2->isys->adev->auxdev.dev, +- "can't get source pad of %s (%ld)\n", +- csi2->asd.sd.name, PTR_ERR(src_pad)); +- return PTR_ERR(src_pad); +- } +- +- return v4l2_get_link_freq(src_pad, 0, 0); +-} +-#else + s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) + { + struct media_pad *src_pad; + struct v4l2_subdev *ext_sd; +- struct device *dev; ++ s64 ret; + + if (!csi2) + return -EINVAL; + +- dev = &csi2->isys->adev->auxdev.dev; + src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); + if (IS_ERR(src_pad)) { +- dev_err(dev, "can't get source pad of %s (%ld)\n", ++ dev_err(&csi2->isys->adev->auxdev.dev, ++ "can't get source pad of %s (%ld)\n", + csi2->asd.sd.name, PTR_ERR(src_pad)); + return PTR_ERR(src_pad); + } +@@ -86,9 +70,18 @@ s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) + if (WARN(!ext_sd, "Failed to get subdev for %s\n", csi2->asd.sd.name)) + return -ENODEV; + +- return v4l2_get_link_freq(ext_sd->ctrl_handler, 0, 0); ++ ret = v4l2_get_link_freq(ext_sd->ctrl_handler, 0, 0); ++ if (ret < 0) { ++ ret = v4l2_get_link_freq(src_pad, 0, 0); ++ if (ret < 0) { ++ dev_err(csi2->asd.sd.dev, ++ "Failed to get link frequency for %s\n", ++ csi2->asd.sd.name); ++ return ret; ++ } ++ } ++ return ret; + } +-#endif + + static int csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, + struct v4l2_event_subscription *sub) +-- +2.43.0 + diff --git a/patches/0065-media-ipu7-get-source-pad-according-to-csi2-.patch b/patches/0101-media-ipu7-get-source-pad-according-to-csi2-ep-fwnod.patch similarity index 78% rename from patches/0065-media-ipu7-get-source-pad-according-to-csi2-.patch rename to patches/0101-media-ipu7-get-source-pad-according-to-csi2-ep-fwnod.patch index 9ebbc4b8..aaabfd5a 100644 --- a/patches/0065-media-ipu7-get-source-pad-according-to-csi2-.patch +++ b/patches/0101-media-ipu7-get-source-pad-according-to-csi2-ep-fwnod.patch @@ -1,20 +1,22 @@ -From ed73cafe221b2466def6568ba92f66d53a365207 Mon Sep 17 00:00:00 2001 -From: "Yew, Chang Ching" -Date: Thu, 22 Jan 2026 08:08:39 +0800 -Subject: media: ipu7: get source pad according to csi2 ep fwnode +From 5f4d88561e89d6581b5a02ccd27e2d142c3814bf Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Mon, 8 Jun 2026 06:20:27 +0000 +Subject: [PATCH 101/109] media: ipu7: get source pad according to csi2 ep + fwnode Signed-off-by: He, Pengpeng Signed-off-by: Yew, Chang Ching +Signed-off-by: florent pirou --- - ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c | 50 +++++++++++++++++++------- - ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h | 1 + - 2 files changed, 39 insertions(+), 12 deletions(-) + .../drivers/media/pci/intel/ipu7/ipu7-isys.c | 49 ++++++++++++++----- + .../drivers/media/pci/intel/ipu7/ipu7-isys.h | 1 + + 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c -index 2bd8968a78cdf..74c45c3e7b5e4 100644 +index bf4dfe1..e13087c 100644 --- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c +++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c -@@ -55,23 +55,49 @@ isys_complete_ext_device_registration(struct ipu7_isys *isys, +@@ -59,23 +59,49 @@ isys_complete_ext_device_registration(struct ipu7_isys *isys, struct ipu7_isys_csi2_config *csi2) { struct device *dev = &isys->adev->auxdev.dev; @@ -74,7 +76,7 @@ index 2bd8968a78cdf..74c45c3e7b5e4 100644 &isys->csi2[csi2->port].asd.sd.entity, 0, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); -@@ -226,8 +252,7 @@ static int isys_notifier_init(struct ipu7_isys *isys) +@@ -351,8 +377,7 @@ static int isys_notifier_init(struct ipu7_isys *isys) s_asd->csi2.port = vep.base.port; s_asd->csi2.nlanes = vep.bus.mipi_csi2.num_data_lanes; s_asd->csi2.bus_type = vep.bus_type; @@ -85,17 +87,17 @@ index 2bd8968a78cdf..74c45c3e7b5e4 100644 continue; diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h -index 17d4d56301691..55afb5b6e2d94 100644 +index c950f24..d1cdd3e 100644 --- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h +++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h -@@ -141,6 +141,7 @@ struct ipu7_isys_csi2_config { +@@ -157,6 +157,7 @@ struct ipu7_isys_csi2_config { unsigned int nlanes; unsigned int port; enum v4l2_mbus_type bus_type; + struct fwnode_handle *ep; }; - struct sensor_async_sd { + struct ipu7_isys_subdev_i2c_info { -- -2.51.1 +2.43.0 diff --git a/patches/0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch b/patches/0102-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch similarity index 80% rename from patches/0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch rename to patches/0102-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch index cabc96a6..a506e32c 100644 --- a/patches/0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch +++ b/patches/0102-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch @@ -1,7 +1,8 @@ -From c15faaa1927bd9aa2a690822cc147e12f47a10cd Mon Sep 17 00:00:00 2001 +From 53541e34946b2dd82ac02e4dc418a0d8bec42681 Mon Sep 17 00:00:00 2001 From: hepengpx Date: Wed, 17 Dec 2025 15:22:07 +0800 -Subject: media: ipu7: Clean csi2 fwnode ep when destroying v4l2_async_connection +Subject: [PATCH 102/109] media: ipu7: Clean csi2 fwnode ep when destroying + v4l2_async_connection Signed-off-by: hepengpx Signed-off-by: Yew, Chang Ching @@ -10,10 +11,10 @@ Signed-off-by: Yew, Chang Ching 1 file changed, 9 insertions(+) diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c -index 74c45c3e7b5e4..d3de8ba02e9d6 100644 +index e13087c..3d876f4 100644 --- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c +++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c -@@ -202,9 +202,18 @@ static int isys_notifier_complete(struct v4l2_async_notifier *notifier) +@@ -326,9 +326,18 @@ static int isys_notifier_complete(struct v4l2_async_notifier *notifier) return v4l2_device_register_subdev_nodes(&isys->v4l2_dev); } @@ -33,5 +34,5 @@ index 74c45c3e7b5e4..d3de8ba02e9d6 100644 static int isys_notifier_init(struct ipu7_isys *isys) -- -2.51.1 +2.43.0 diff --git a/patches/0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch b/patches/0103-isys-video-let-v4l2-set-default-colorspace.patch similarity index 51% rename from patches/0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch rename to patches/0103-isys-video-let-v4l2-set-default-colorspace.patch index d049d8c2..1eb40ae2 100644 --- a/patches/0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch +++ b/patches/0103-isys-video-let-v4l2-set-default-colorspace.patch @@ -1,25 +1,15 @@ -From 57304c286317ece4c0a74a52c4733486c57444ce Mon May 4 23:35:11 2026 -From: "Ng, Khai Wen" -Date: Mon, 04 May 2026 23:35:11 +0800 -Subject: media: ipu7-isys: let v4l2 set default colorspace - -Forcing f->fmt.pix.colorspace to V4L2_COLORSPACE_RAW in -__ipu_isys_vidioc_try_fmt_vid_cap() overrides the colorspace propagated -from the connected sensor sub-device. For non-Bayer sensors (e.g. UYVY -output from the D4XX RGB stream) this causes v4l2src and other -userspace clients to reject the negotiated format because the -round-tripped colorimetry does not match what they requested. - -Drop the hardcoded assignment so the colorspace value supplied by -userspace (or already present on the buffer) is preserved. +From 892371f0157c97e11272a1515da9c64b06790c3b Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Mon, 19 Jan 2026 10:38:25 -0700 +Subject: [PATCH 103/109] isys-video: let v4l2 set default colorspace Signed-off-by: Florent Pirou -Signed-off-by: Ng, Khai Wen --- ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c +index 3078cf2..95a0d7b 100644 --- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c +++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c @@ -257,7 +257,6 @@ static void __ipu_isys_vidioc_try_fmt_vid_cap(struct ipu7_isys_video *av, diff --git a/patches/0104-ipu7-isys-make-modules-suffix-versioning-same-as-dkm.patch b/patches/0104-ipu7-isys-make-modules-suffix-versioning-same-as-dkm.patch new file mode 100644 index 00000000..308c353f --- /dev/null +++ b/patches/0104-ipu7-isys-make-modules-suffix-versioning-same-as-dkm.patch @@ -0,0 +1,73 @@ +From 19bc62bbae0255e5be751a4a81a82a954ac9b8c0 Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Sat, 17 Jan 2026 02:10:39 -0700 +Subject: [PATCH 104/109] ipu7-isys: make modules suffix versioning same as + dkms + +Signed-off-by: Florent Pirou +--- + ipu7-drivers/drivers/media/pci/intel/ipu7/Makefile | 12 ++++++++++++ + .../drivers/media/pci/intel/ipu7/ipu7-isys.c | 1 + + ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7.c | 1 + + .../drivers/media/pci/intel/ipu7/psys/ipu-psys.c | 1 + + 4 files changed, 15 insertions(+) + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/Makefile b/ipu7-drivers/drivers/media/pci/intel/ipu7/Makefile +index 3c35ca5..14bb16e 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/Makefile ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/Makefile +@@ -1,5 +1,15 @@ + # SPDX-License-Identifier: GPL-2.0 + # Copyright (c) 2017 - 2025 Intel Corporation. ++KERNEL_VERSION := $(shell echo $(KERNELRELEASE) | sed 's/[^0-9.]*\([0-9]\.[0-9]*\)\..*/\1.0/') ++ ++CC := ${CC} -I ${M}/include -I ${M}/$(KERNEL_VERSION)/include-overrides -DCONFIG_DEBUG_FS -DCONFIG_INTEL_IPU_ACPI -DCONFIG_VIDEO_INTEL_IPU7_ISYS_RESET -DCONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ ++KBUILD_EXTRA_SYMBOLS += ${M}/Module.symvers ++ ++ccflags-y += -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" ++ ++export EXTERNAL_BUILD = 1 ++export CONFIG_VIDEO_INTEL_IPU7=m + + is_kernel_lt_6_10 = $(shell if [ $$(printf "6.10\n$(KERNELVERSION)" | sort -V | head -n1) != "6.10" ]; then echo 1; fi) + ifeq ($(is_kernel_lt_6_10), 1) +@@ -29,6 +39,8 @@ intel-ipu7-isys-objs += ipu7-isys.o \ + + obj-$(CONFIG_VIDEO_INTEL_IPU7) += intel-ipu7-isys.o + ++subdir-ccflags-y += -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" ++ + obj-$(CONFIG_VIDEO_INTEL_IPU7) += psys/ + + ccflags-y += -I$(src)/ +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c +index 3d876f4..26504ae 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.c +@@ -1574,3 +1574,4 @@ MODULE_IMPORT_NS("INTEL_IPU_BRIDGE"); + MODULE_IMPORT_NS(INTEL_IPU7); + MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); + #endif ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7.c +index 18aebd0..785af1f 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7.c +@@ -2880,3 +2880,4 @@ MODULE_AUTHOR("Qingwu Zhang "); + MODULE_AUTHOR("Intel"); + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Intel ipu7 pci driver"); ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/psys/ipu-psys.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/psys/ipu-psys.c +index 838f0b2..b5ff06a 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/psys/ipu-psys.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/psys/ipu-psys.c +@@ -1554,3 +1554,4 @@ MODULE_IMPORT_NS("DMA_BUF"); + MODULE_IMPORT_NS(INTEL_IPU7); + MODULE_IMPORT_NS(DMA_BUF); + #endif ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +-- +2.43.0 + diff --git a/patches/0105-ipu7-isys-add-d4xx-pixel-format-support.patch b/patches/0105-ipu7-isys-add-d4xx-pixel-format-support.patch new file mode 100644 index 00000000..5a45923d --- /dev/null +++ b/patches/0105-ipu7-isys-add-d4xx-pixel-format-support.patch @@ -0,0 +1,126 @@ +From fadce7803bf0c9ef195d7f83958f8c6e4fffd2aa Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Sat, 17 Jan 2026 02:08:28 -0700 +Subject: [PATCH 105/109] ipu7-isys : add d4xx pixel format support + +Signed-off-by: Florent Pirou +--- + .../drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c | 3 +++ + .../drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c | 5 ++++- + .../drivers/media/pci/intel/ipu7/ipu7-isys-video.c | 13 +++++++++++++ + .../drivers/media/pci/intel/ipu7/ipu7-isys.h | 4 ++-- + 4 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c +index 356020f..e9c435e 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c +@@ -28,11 +28,13 @@ + #include "ipu7-isys-csi-phy.h" + + static const u32 csi2_supported_codes[] = { ++ MEDIA_BUS_FMT_Y8_1X8, + MEDIA_BUS_FMT_Y10_1X10, + MEDIA_BUS_FMT_RGB565_1X16, + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_UYVY8_1X16, + MEDIA_BUS_FMT_YUYV8_1X16, ++ MEDIA_BUS_FMT_VYUY8_1X16, + MEDIA_BUS_FMT_YUYV10_1X20, + MEDIA_BUS_FMT_SBGGR10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, +@@ -46,6 +48,7 @@ static const u32 csi2_supported_codes[] = { + MEDIA_BUS_FMT_SGBRG8_1X8, + MEDIA_BUS_FMT_SGRBG8_1X8, + MEDIA_BUS_FMT_SRGGB8_1X8, ++ MEDIA_BUS_FMT_FIXED, + 0, + }; + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c +index 67a7760..4cbcaee 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-subdev.c +@@ -19,6 +19,7 @@ + #include "ipu7-isys.h" + #include "ipu7-isys-subdev.h" + ++ + unsigned int ipu7_isys_mbus_code_to_mipi(u32 code) + { + switch (code) { +@@ -30,13 +31,14 @@ unsigned int ipu7_isys_mbus_code_to_mipi(u32 code) + return MIPI_CSI2_DT_YUV422_10B; + case MEDIA_BUS_FMT_UYVY8_1X16: + case MEDIA_BUS_FMT_YUYV8_1X16: ++ case MEDIA_BUS_FMT_Y10_1X10: ++ case MEDIA_BUS_FMT_VYUY8_1X16: + return MIPI_CSI2_DT_YUV422_8B; + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: + case MEDIA_BUS_FMT_SGRBG12_1X12: + case MEDIA_BUS_FMT_SRGGB12_1X12: + return MIPI_CSI2_DT_RAW12; +- case MEDIA_BUS_FMT_Y10_1X10: + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: +@@ -46,6 +48,7 @@ unsigned int ipu7_isys_mbus_code_to_mipi(u32 code) + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: ++ case MEDIA_BUS_FMT_Y8_1X8: + return MIPI_CSI2_DT_RAW8; + default: + WARN_ON(1); +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c +index 95a0d7b..a1ab842 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c +@@ -41,6 +41,16 @@ + #include "ipu7-platform-regs.h" + + const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { ++ { V4L2_PIX_FMT_GREY, 8, 8, MEDIA_BUS_FMT_Y8_1X8, ++ IPU_INSYS_FRAME_FORMAT_RAW8 }, ++ { V4L2_PIX_FMT_Y10, 16, 10, MEDIA_BUS_FMT_Y10_1X10, ++ IPU_INSYS_FRAME_FORMAT_RAW16 }, ++ {V4L2_PIX_FMT_YUYV, 16, 16, MEDIA_BUS_FMT_YUYV8_1X16, ++ IPU_INSYS_FRAME_FORMAT_UYVY}, ++ { V4L2_PIX_FMT_Y8I, 16, 16, MEDIA_BUS_FMT_VYUY8_1X16, ++ IPU_INSYS_FRAME_FORMAT_UYVY}, ++ { V4L2_PIX_FMT_Z16, 16, 16, MEDIA_BUS_FMT_UYVY8_1X16, ++ IPU_INSYS_FRAME_FORMAT_UYVY}, + {V4L2_PIX_FMT_SBGGR12, 16, 12, MEDIA_BUS_FMT_SBGGR12_1X12, + IPU_INSYS_FRAME_FORMAT_RAW16}, + {V4L2_PIX_FMT_SGBRG12, 16, 12, MEDIA_BUS_FMT_SGBRG12_1X12, +@@ -87,8 +97,11 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { + IPU_INSYS_FRAME_FORMAT_YUYV}, + {V4L2_PIX_FMT_RGB565, 16, 16, MEDIA_BUS_FMT_RGB565_1X16, + IPU_INSYS_FRAME_FORMAT_RGB565}, ++ {V4L2_PIX_FMT_Y12I, 32, 24, MEDIA_BUS_FMT_RGB888_1X24, ++ IPU_INSYS_FRAME_FORMAT_RGBA888}, + {V4L2_PIX_FMT_BGR24, 24, 24, MEDIA_BUS_FMT_RGB888_1X24, + IPU_INSYS_FRAME_FORMAT_RGBA888}, ++ {V4L2_META_FMT_D4XX, 8, 8, MEDIA_BUS_FMT_FIXED, 0}, + }; + + static int video_open(struct file *file) +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h +index d1cdd3e..21f33f2 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys.h +@@ -43,8 +43,8 @@ struct dentry; + #define IPU_ISYS_SIZE_SEND_QUEUE 40U + #define IPU_ISYS_NUM_RECV_QUEUE 1U + +-#define IPU_ISYS_MIN_WIDTH 2U +-#define IPU_ISYS_MIN_HEIGHT 2U ++#define IPU_ISYS_MIN_WIDTH 1U ++#define IPU_ISYS_MIN_HEIGHT 1U + #define IPU_ISYS_MAX_WIDTH 8160U + #define IPU_ISYS_MAX_HEIGHT 8190U + +-- +2.43.0 + diff --git a/patches/0106-isys-queue-ignore-HW_ERR_BAD_FRAME_DIM-led-expected-.patch b/patches/0106-isys-queue-ignore-HW_ERR_BAD_FRAME_DIM-led-expected-.patch new file mode 100644 index 00000000..13b14965 --- /dev/null +++ b/patches/0106-isys-queue-ignore-HW_ERR_BAD_FRAME_DIM-led-expected-.patch @@ -0,0 +1,28 @@ +From 4052f0697c64e9d2df7be908e653fa442b9095cb Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Sun, 26 Apr 2026 09:52:35 -0700 +Subject: [PATCH 106/109] isys-queue : ignore HW_ERR_BAD_FRAME_DIM led expected + buffers noise" + +--- + ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-queue.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-queue.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-queue.c +index 06d280e..61748f0 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-queue.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-queue.c +@@ -1120,10 +1120,6 @@ void ipu7_isys_queue_buf_ready(struct ipu7_isys_stream *stream, + addr = ivb->dma_addr; + + if (info->pin.addr != addr) { +- if (first) +- dev_err(dev, "Unexpected buffer address %pad\n", +- &addr); +- + first = false; + continue; + } +-- +2.43.0 + diff --git a/patches/0107-ipu7-isys-enable-cphy-dphy-5-4-bits-vc-extension.patch b/patches/0107-ipu7-isys-enable-cphy-dphy-5-4-bits-vc-extension.patch new file mode 100644 index 00000000..fdb19ccf --- /dev/null +++ b/patches/0107-ipu7-isys-enable-cphy-dphy-5-4-bits-vc-extension.patch @@ -0,0 +1,39 @@ +From fe4442b22ed63c0af32a1f2d5126e6508335744e Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Wed, 6 May 2026 08:53:02 -0700 +Subject: [PATCH 107/109] ipu7-isys: enable cphy/dphy 5/4-bits vc-extension + +VC_EXTENSION register activates extra bits for virtual channel. +The Virtual Channel Extension (VCX) field is common to both options, +but is a 2-bit field for D-PHY and a 3-bit field for C-PHY. + +Signed-off-by: florent pirou +--- + .../drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c +index a56aeec..5bdbd28 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c +@@ -272,10 +272,15 @@ static int __dids_config(struct ipu7_isys_csi2 *csi2, u32 id, u8 vc, u8 dt) + u8 lo, hi; + int ret; + +- dev_dbg(&isys->adev->auxdev.dev, "config CSI-%u with vc:%u dt:0x%02x\n", ++#ifdef CONFIG_INTEL_IPU_VC_EXT ++ dev_info(&isys->adev->auxdev.dev, "config CSI-%u with vc_ext:%u [vc_msb:%u vc_lsb:%u] dt:0x%02x\n", ++ id, vc, vc & GENMASK(4, 2), vc & GENMASK(1, 0), dt); ++#else ++ dev_info(&isys->adev->auxdev.dev, "config CSI-%u with vc:%u dt:0x%02x\n", + id, vc, dt); +- ++#endif + dwc_csi_write(isys, id, VC_EXTENSION, 0x0); ++ + n = find_first_zero_bit(data_ids, N_DATA_IDS); + if (n == N_DATA_IDS) + return -ENOSPC; +-- +2.43.0 + diff --git a/patches/0108-ipu7-isys-allow-virtual-channels-on-16-csi2-input-vi.patch b/patches/0108-ipu7-isys-allow-virtual-channels-on-16-csi2-input-vi.patch new file mode 100644 index 00000000..3efbf944 --- /dev/null +++ b/patches/0108-ipu7-isys-allow-virtual-channels-on-16-csi2-input-vi.patch @@ -0,0 +1,29 @@ +From 46dd46e12dd0fb7f6a69bc23f3d30d2c1e0204c5 Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Sat, 17 Jan 2026 02:05:34 -0700 +Subject: [PATCH 108/109] ipu7-isys : allow virtual-channels on 16 csi2 input + video capture + +* ipu7-isys : extend per csi2 video captures v4l2 to 16 sensors input streams + +Signed-off-by: Florent Pirou +--- + ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h +index 6c23b80..dfca0d2 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h +@@ -20,7 +20,7 @@ struct ipu7_isys_stream; + #define INVALID_VC_ID -1 + #define IPU7_NR_OF_CSI2_SINK_PADS 1U + #define IPU7_CSI2_PAD_SINK 0U +-#define IPU7_NR_OF_CSI2_SRC_PADS 8U ++#define IPU7_NR_OF_CSI2_SRC_PADS 16U + #define IPU7_CSI2_PAD_SRC 1U + #define IPU7_NR_OF_CSI2_PADS (IPU7_NR_OF_CSI2_SINK_PADS + \ + IPU7_NR_OF_CSI2_SRC_PADS) +-- +2.43.0 + diff --git a/patches/0109-ipu7-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch b/patches/0109-ipu7-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch new file mode 100644 index 00000000..cb17ae5b --- /dev/null +++ b/patches/0109-ipu7-isys-add-video-VIDIOC_S_EXT_CTRLS-callbacks-by-.patch @@ -0,0 +1,1588 @@ +From 787f019a6c893cd594ff55a2ddc5595c7a363d1a Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 10:31:00 -0700 +Subject: [PATCH 109/109] ipu7-isys: add video VIDIOC_S_EXT_CTRLS callbacks by + streamid + +* isys-video: add video VIDIOC_S_EXT_CTRLS callbacks by streamid +* isys-csi: add graph walk subdev to get frame desc by streamid +* isys-csi: add graph walk subdev to enable/disable streams by streamid +* isys-video: add V4L2_CID_IPU definitions + +Signed-off-by: florent pirou +--- + .../media/pci/intel/ipu7/ipu7-isys-csi-phy.c | 85 ++- + .../media/pci/intel/ipu7/ipu7-isys-csi-phy.h | 4 + + .../media/pci/intel/ipu7/ipu7-isys-csi2.c | 459 ++++++++++++- + .../media/pci/intel/ipu7/ipu7-isys-csi2.h | 11 + + .../pci/intel/ipu7/ipu7-isys-video-ext.h | 61 ++ + .../media/pci/intel/ipu7/ipu7-isys-video.c | 624 +++++++++++++++++- + .../media/pci/intel/ipu7/ipu7-isys-video.h | 4 + + 7 files changed, 1238 insertions(+), 10 deletions(-) + create mode 100644 ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video-ext.h + +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c +index 5bdbd28..1224f3b 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.c +@@ -22,6 +22,9 @@ + #include "ipu7-isys-csi2-regs.h" + #include "ipu7-platform-regs.h" + #include "ipu7-isys-csi-phy.h" ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++#include "ipu7-isys-video-ext.h" ++#endif + + #define PORT_A 0U + #define PORT_B 1U +@@ -282,6 +285,10 @@ static int __dids_config(struct ipu7_isys_csi2 *csi2, u32 id, u8 vc, u8 dt) + dwc_csi_write(isys, id, VC_EXTENSION, 0x0); + + n = find_first_zero_bit(data_ids, N_DATA_IDS); ++ ++ dev_dbg(&isys->adev->auxdev.dev, "config CSI-%u with n/data_ids:%u/%p\n", ++ id, n, data_ids); ++ + if (n == N_DATA_IDS) + return -ENOSPC; + +@@ -302,7 +309,17 @@ static int __dids_config(struct ipu7_isys_csi2 *csi2, u32 id, u8 vc, u8 dt) + return 0; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++/* ++ * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set ++ * of streams. ++ */ ++#define CSI2_SUBDEV_MAX_STREAM_ID 63 ++static int ipu7_isys_csi_ctrl_dids_config(struct ipu7_isys_csi2 *csi2, u32 id, ++ struct v4l2_subdev_state *state, u64 streams_mask) ++#else + static int ipu7_isys_csi_ctrl_dids_config(struct ipu7_isys_csi2 *csi2, u32 id) ++#endif + { + struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; + struct device *dev = &csi2->isys->adev->auxdev.dev; +@@ -314,9 +331,52 @@ static int ipu7_isys_csi_ctrl_dids_config(struct ipu7_isys_csi2 *csi2, u32 id) + + pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); + if (IS_ERR(pad)) { ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ ret = ipu7_isys_csi2_walk_unique_remote_desc(state, csi2, ++ &csi2->asd.sd.entity, ++ &desc); ++ if (!ret) { ++ ++ ret = -EINVAL; ++ for (i = 0; i < desc.num_entries; i++) { ++ desc_entry = &desc.entry[i]; ++ ++ dev_dbg(dev, "%s: stream:%u, mbus:%x, vc/dt:%u/%x\n", ++ __func__, ++ desc_entry->stream, ++ desc_entry->pixelcode, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ ++ if (desc_entry->bus.csi2.vc < IPU7_NR_OF_CSI2_VC) { ++ ++ ret = __dids_config(csi2, id, desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ if (ret) { ++ dev_warn(dev, "failed to set frame descriptor: %d\n", ret); ++ continue; ++ } ++ } ++ } ++ } ++ ++ if (!ret) ++ return ret; ++ ++fallback: ++ pad = media_pad_remote_pad_first(&csi2->asd.sd.entity.pads[IPU7_CSI2_PAD_SINK]); ++ dev_warn(dev, "fallback on %s first remote pad\n", ++ csi2->asd.sd.name); ++ if (IS_ERR(pad)) { ++ dev_warn(dev, "can't get first remote pad of %s (%ld)\n", ++ csi2->asd.sd.name, PTR_ERR(pad)); ++ return PTR_ERR(pad); ++ } ++#else + dev_warn(dev, "can't get remote source pad of %s (%ld)\n", + csi2->asd.sd.name, PTR_ERR(pad)); + return PTR_ERR(pad); ++#endif + } + + ext_sd = media_entity_to_v4l2_subdev(pad->entity); +@@ -335,11 +395,21 @@ static int ipu7_isys_csi_ctrl_dids_config(struct ipu7_isys_csi2 *csi2, u32 id) + + for (i = 0; i < desc.num_entries; i++) { + desc_entry = &desc.entry[i]; ++ ++ dev_dbg(dev, "%s: stream:%u, mbus:%x, vc/dt:%u/%x\n", ++ __func__, ++ desc_entry->stream, ++ desc_entry->pixelcode, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ + if (desc_entry->bus.csi2.vc < IPU7_NR_OF_CSI2_VC) { + ret = __dids_config(csi2, id, desc_entry->bus.csi2.vc, + desc_entry->bus.csi2.dt); +- if (ret) ++ if (ret) { ++ dev_warn(dev, "failed to set frame descriptor: %d\n", ret); + return ret; ++ } + } + } + +@@ -964,7 +1034,12 @@ static int ipu7_isys_phy_config(struct ipu7_isys *isys, u8 id, u8 lanes, + return 0; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++int ipu7_isys_csi_phy_powerup(struct ipu7_isys_csi2 *csi2, ++ struct v4l2_subdev_state *state, u64 streams_mask) ++#else + int ipu7_isys_csi_phy_powerup(struct ipu7_isys_csi2 *csi2) ++#endif + { + struct ipu7_isys *isys = csi2->isys; + u32 lanes = csi2->nlanes; +@@ -996,7 +1071,11 @@ int ipu7_isys_csi_phy_powerup(struct ipu7_isys_csi2 *csi2) + } + + ipu7_isys_csi_ctrl_cfg(csi2); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ ipu7_isys_csi_ctrl_dids_config(csi2, id, state, streams_mask); ++#else + ipu7_isys_csi_ctrl_dids_config(csi2, id); ++#endif + + ret = ipu7_isys_phy_config(isys, id, lanes, aggregation); + if (ret < 0) +@@ -1045,4 +1124,8 @@ void ipu7_isys_csi_phy_powerdown(struct ipu7_isys_csi2 *csi2) + if (!is_ipu7(isys->adev->isp->hw_ver) && + csi2->nlanes > 2U && csi2->port == PORT_A) + ipu7_isys_csi_phy_reset(isys, PORT_B); ++ ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ bitmap_clear(data_ids, 0, N_DATA_IDS); ++#endif + } +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.h +index dfdcb61..7e36837 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.h ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi-phy.h +@@ -11,6 +11,10 @@ struct ipu7_isys; + #define PHY_MODE_DPHY 0U + #define PHY_MODE_CPHY 1U + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++int ipu7_isys_csi_phy_powerup(struct ipu7_isys_csi2 *csi2, struct v4l2_subdev_state *state, u64 streams_mask); ++#else + int ipu7_isys_csi_phy_powerup(struct ipu7_isys_csi2 *csi2); ++#endif + void ipu7_isys_csi_phy_powerdown(struct ipu7_isys_csi2 *csi2); + #endif +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c +index e9c435e..b9a0c92 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.c +@@ -26,6 +26,9 @@ + #include "ipu7-isys-csi2.h" + #include "ipu7-isys-csi2-regs.h" + #include "ipu7-isys-csi-phy.h" ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++#include "ipu7-isys-video-ext.h" ++#endif + + static const u32 csi2_supported_codes[] = { + MEDIA_BUS_FMT_Y8_1X8, +@@ -55,24 +58,36 @@ static const u32 csi2_supported_codes[] = { + s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) + { + struct media_pad *src_pad; ++ struct v4l2_subdev_state *s_state; + struct v4l2_subdev *ext_sd; +- s64 ret; ++ struct device *dev; ++ int ret = -EPIPE; + + if (!csi2) + return -EINVAL; + +- src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); ++ s_state = v4l2_subdev_get_unlocked_active_state(&csi2->asd.sd); ++ if (!s_state) ++ return ret; ++ ++ dev = &csi2->isys->adev->auxdev.dev; ++ src_pad = media_pad_remote_pad_first(&csi2->asd.sd.entity.pads[IPU7_CSI2_PAD_SINK]); + if (IS_ERR(src_pad)) { + dev_err(&csi2->isys->adev->auxdev.dev, +- "can't get source pad of %s (%ld)\n", +- csi2->asd.sd.name, PTR_ERR(src_pad)); +- return PTR_ERR(src_pad); ++ "can't get source pad of %s\n", ++ csi2->asd.sd.name); ++ return -EINVAL; + } + + ext_sd = media_entity_to_v4l2_subdev(src_pad->entity); + if (WARN(!ext_sd, "Failed to get subdev for %s\n", csi2->asd.sd.name)) + return -ENODEV; + ++ dev_dbg(&csi2->isys->adev->auxdev.dev, ++ "%s:%u -> %s:%u\n", ++ csi2->asd.sd.name, IPU7_CSI2_PAD_SINK, ++ ext_sd->name, src_pad->index); ++ + ret = v4l2_get_link_freq(ext_sd->ctrl_handler, 0, 0); + if (ret < 0) { + ret = v4l2_get_link_freq(src_pad, 0, 0); +@@ -175,7 +190,12 @@ static void ipu7_isys_csi2_disable_stream(struct ipu7_isys_csi2 *csi2) + csi2_irq_disable(csi2); + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++static int ipu7_isys_csi2_enable_stream(struct ipu7_isys_csi2 *csi2, ++ struct v4l2_subdev_state *state, u64 streams_mask) ++#else + static int ipu7_isys_csi2_enable_stream(struct ipu7_isys_csi2 *csi2) ++#endif + { + struct ipu7_isys *isys = csi2->isys; + struct device *dev = &isys->adev->auxdev.dev; +@@ -201,7 +221,11 @@ static int ipu7_isys_csi2_enable_stream(struct ipu7_isys_csi2 *csi2) + writel(CSI_SENSOR_INPUT, isys_base + offset + CSI2_ADPL_INPUT_MODE); + writel(1, isys_base + offset + CSI2_ADPL_CSI_RX_ERR_IRQ_CLEAR_EN); + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ ret = ipu7_isys_csi_phy_powerup(csi2, state, streams_mask); ++#else + ret = ipu7_isys_csi_phy_powerup(csi2); ++#endif + if (ret) { + dev_err(dev, "CSI-%d PHY power up failed %d\n", port, ret); + return ret; +@@ -302,6 +326,146 @@ static int ipu7_isys_csi2_get_sel(struct v4l2_subdev *sd, + return ret; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++static int ipu7_isys_csi2_link_validate(struct media_link *link) ++{ ++ ++ struct v4l2_subdev *sd = ++ media_entity_to_v4l2_subdev(link->sink->entity); ++ struct device *dev = sd->entity.graph_obj.mdev->dev; ++ struct ipu7_isys_subdev *asd; ++ struct ipu7_isys_csi2 *csi2; ++ struct v4l2_subdev_state *s_state; ++ struct v4l2_mbus_framefmt *s_fmt; ++ struct v4l2_subdev *s_sd; ++ struct media_pad *s_pad; ++ u32 s_stream, code; ++ int ret = -EPIPE; ++ ++ if (!link->source->entity) ++ return ret; ++ ++ asd = to_ipu7_isys_subdev(sd); ++ csi2 = to_ipu7_isys_csi2(asd); ++ dev = &asd->isys->adev->auxdev.dev; ++ ++ s_sd = media_entity_to_v4l2_subdev(link->source->entity); ++ s_state = v4l2_subdev_get_unlocked_active_state(s_sd); ++ if (!s_state) ++ return ret; ++ ++ dev_dbg(dev, "%s: validating link \"%s\":%u -> \"%s\"\n",__func__, ++ link->source->entity->name, link->source->index, ++ link->sink->entity->name); ++ ++ return 0; ++} ++ ++int ipu7_isys_csi2_streams_by_sources(struct ipu7_isys_csi2 *csi2, ++ u32 pad, u32 stream, bool on) ++{ ++ struct media_entity *entity = &csi2->asd.sd.entity; ++ struct media_device *mdev = entity->graph_obj.mdev; ++ struct device *dev = &csi2->isys->adev->auxdev.dev; ++ struct v4l2_subdev *sd = NULL; ++ struct v4l2_subdev_state *v4l2_state; ++ struct media_graph graph; ++ struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; ++ struct v4l2_mbus_frame_desc desc; ++ unsigned int i; ++ int ret; ++ ++ if (!mdev) ++ return -EPIPE; ++ ++ mutex_lock(&mdev->graph_mutex); ++ if (media_graph_walk_init(&graph, mdev)) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s: walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_VID_MUX) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->get_frame_desc) ++ continue; ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ ret = sd->ops->pad->get_frame_desc(sd, pad, &desc); ++ if (ret) ++ continue; ++ ++ if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) ++ continue; ++ ++ for (i = 0; i < desc.num_entries; i++) { ++ if (stream == desc.entry[i].stream) { ++ desc_entry = &desc.entry[i]; ++ break; ++ } ++ } ++ ++ if (!desc_entry) ++ continue; ++ ++ if (desc_entry->bus.csi2.vc >= IPU7_NR_OF_CSI2_VC) ++ continue; ++ ++ ++ dev_dbg(dev, "%s: found %s subdev stream:%u vc/dt:%u/0x%x\n", __func__, ++ sd->name, ++ desc_entry->stream, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->disable_streams || !sd->ops->pad->enable_streams) ++ break; ++ ++ v4l2_state = v4l2_subdev_get_unlocked_active_state(sd); ++ if (!v4l2_state) ++ break; ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (on) ++ ret = sd->ops->pad->enable_streams(sd, v4l2_state, pad, BIT_ULL(stream)); ++ else ++ ret = sd->ops->pad->disable_streams(sd, v4l2_state, pad, BIT_ULL(stream)); ++ if (ret) ++ break; ++ ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++ return 0; ++ } ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++ ++error_graph_walk_source: ++ return -EINVAL; ++} ++#endif ++ + /* + * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set + * of streams. +@@ -323,7 +487,11 @@ static int ipu7_isys_csi2_enable_streams(struct v4l2_subdev *sd, + dev_dbg(&csi2->isys->adev->auxdev.dev, + "stream on CSI2-%u with %u lanes\n", csi2->port, + csi2->nlanes); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ ret = ipu7_isys_csi2_enable_stream(csi2, state, streams_mask); ++#else + ret = ipu7_isys_csi2_enable_stream(csi2); ++#endif + if (ret) + return ret; + } +@@ -338,6 +506,14 @@ static int ipu7_isys_csi2_enable_streams(struct v4l2_subdev *sd, + if (ret) + return ret; + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ if (!ipu7_isys_csi2_streams_by_sources(csi2, sink_pad, sink_stream, true)) { ++ csi2->stream_count++; ++ return 0; ++ } ++ dev_dbg(&csi2->isys->adev->auxdev.dev, ++ "remote stream on fallback\n"); ++#endif + rp = media_pad_remote_pad_first(&sd->entity.pads[IPU7_CSI2_PAD_SINK]); + r_sd = media_entity_to_v4l2_subdev(rp->entity); + +@@ -375,6 +551,15 @@ static int ipu7_isys_csi2_disable_streams(struct v4l2_subdev *sd, + if (ret) + return ret; + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ if (!ipu7_isys_csi2_streams_by_sources(csi2, sink_pad, sink_stream, false)) { ++ if (--csi2->stream_count) ++ return 0; ++ goto ret; ++ } ++ dev_dbg(&csi2->isys->adev->auxdev.dev, ++ "remote stream off fallback\n"); ++#endif + rp = media_pad_remote_pad_first(&sd->entity.pads[IPU7_CSI2_PAD_SINK]); + r_sd = media_entity_to_v4l2_subdev(rp->entity); + +@@ -382,7 +567,7 @@ static int ipu7_isys_csi2_disable_streams(struct v4l2_subdev *sd, + + if (--csi2->stream_count) + return 0; +- ++ret: + dev_dbg(&csi2->isys->adev->auxdev.dev, + "stream off CSI2-%u with %u lanes\n", csi2->port, csi2->nlanes); + +@@ -408,7 +593,11 @@ static const struct v4l2_subdev_ops csi2_sd_ops = { + }; + + static const struct media_entity_operations csi2_entity_ops = { ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ .link_validate = ipu7_isys_csi2_link_validate, ++#else + .link_validate = v4l2_subdev_link_validate, ++#endif + .has_pad_interdep = v4l2_subdev_has_pad_interdep, + }; + +@@ -564,3 +753,261 @@ int ipu7_isys_csi2_get_remote_desc(u32 source_stream, + + return 0; + } ++ ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++int ipu7_isys_csi2_walk_remote_desc_by_stream(u32 source_stream, ++ struct ipu7_isys_csi2 *csi2, ++ struct media_entity *source_entity, ++ struct v4l2_mbus_frame_desc_entry *entry, ++ int *nr_queues) ++{ ++ struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; ++ struct device *dev = &csi2->isys->adev->auxdev.dev; ++ struct v4l2_mbus_frame_desc desc; ++ struct v4l2_subdev *source; ++ struct media_pad *pad; ++ struct media_graph graph; ++ struct media_entity *entity; ++ struct media_device *mdev; ++ struct v4l2_subdev *sd; ++ unsigned int pad_id; ++ u32 stream_id = source_stream; ++ unsigned int i; ++ int ret; ++ ++ source = media_entity_to_v4l2_subdev(source_entity); ++ if (!source) ++ return -EPIPE; ++ ++ pad = media_pad_remote_pad_first(&csi2->asd.pad[IPU7_CSI2_PAD_SINK]); ++ if (!pad) ++ return -EPIPE; ++ ++ dev_dbg(dev, "%s: source pad/stream:%u/%u\n", __func__,pad->index, source_stream); ++ pad_id = pad->index; ++ entity = source_entity; ++ mdev = entity->graph_obj.mdev; ++ if (!mdev) { ++ ret = -EPIPE; ++ goto error_graph_walk_source; ++ } ++ ++ mutex_lock(&mdev->graph_mutex); ++ ret = media_graph_walk_init(&graph, mdev); ++ if (ret) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s: walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_VID_MUX) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->get_frame_desc) ++ continue; ++ ++ dev_dbg(dev, "%s(): %s pad/stream: %u/%u\n", ++ __func__, ++ sd->name, ++ pad_id, ++ source_stream); ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ ret = sd->ops->pad->get_frame_desc(sd, pad_id, &desc); ++ if (ret) ++ continue; ++ ++ ret = -EINVAL; ++ ++ if (desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) ++ continue; ++ ++ for (i = 0; i < desc.num_entries; i++) { ++ if (source_stream == desc.entry[i].stream) { ++ desc_entry = &desc.entry[i]; ++ break; ++ } ++ } ++ ++ if (!desc_entry) ++ continue; ++ ++ if (desc_entry->bus.csi2.vc >= IPU7_NR_OF_CSI2_VC) ++ continue; ++ ++ *entry = *desc_entry; ++ ++ for (i = 0; i < desc.num_entries; i++) { ++ if (desc_entry->bus.csi2.vc == desc.entry[i].bus.csi2.vc) ++ (*nr_queues)++; ++ } ++ ++ dev_dbg(dev, "%s: found frame desc stream:%u vc/dt:%u/0x%x\n", __func__, ++ desc_entry->stream, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ ++ ret = 0; ++ break; ++ } ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++error_graph_walk_source: ++ return ret; ++} ++ ++int ipu7_isys_csi2_walk_unique_remote_desc(struct v4l2_subdev_state *state, ++ struct ipu7_isys_csi2 *csi2, ++ struct media_entity *source_entity, ++ struct v4l2_mbus_frame_desc *desc) ++{ ++ struct v4l2_mbus_frame_desc_entry *desc_entry = NULL; ++ struct device *dev = &csi2->isys->adev->auxdev.dev; ++ struct v4l2_mbus_frame_desc _desc; ++ struct v4l2_subdev *source; ++ struct media_pad *pad; ++ struct media_graph graph; ++ struct media_entity *entity; ++ struct media_device *mdev; ++ struct v4l2_subdev *sd; ++ struct v4l2_subdev_route *routes; ++ unsigned int pad_id; ++ unsigned int i, j; ++ int ret, skip = 0; ++ ++ if (!desc) ++ return -EPIPE; ++ ++ source = media_entity_to_v4l2_subdev(source_entity); ++ if (!source) ++ return -EPIPE; ++ ++ pad = media_pad_remote_pad_first(&csi2->asd.pad[IPU7_CSI2_PAD_SINK]); ++ if (!pad) ++ return -EPIPE; ++ ++ pad_id = pad->index; ++ entity = source_entity; ++ mdev = entity->graph_obj.mdev; ++ if (!mdev) { ++ ret = -EPIPE; ++ goto error_graph_walk_source; ++ } ++ ++ mutex_lock(&mdev->graph_mutex); ++ ret = media_graph_walk_init(&graph, mdev); ++ if (ret) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s: walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_VID_MUX) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with get_frame_desc callback */ ++ if (!sd->ops || !sd->ops->pad || !sd->ops->pad->get_frame_desc) ++ continue; ++ ++ /* v4l2_subdev_call doesn't call, access directly */ ++ ret = sd->ops->pad->get_frame_desc(sd, pad_id, &_desc); ++ if (ret) ++ continue; ++ ++ if (_desc.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) ++ continue; ++ ++ routes = state->routing.routes; ++ for (i = 0; i < _desc.num_entries; i++) { ++ ++ desc_entry = &_desc.entry[i]; ++ ++ skip = 0; ++ for (j = 0; j < state->routing.num_routes; j++) { ++ ++ /* ignore inactive routes */ ++ if (routes[j].source_stream == desc_entry->stream && ++ routes[j].flags != V4L2_SUBDEV_ROUTE_FL_ACTIVE) { ++ skip = 1; ++ break; ++ } ++ } ++ if (skip) ++ continue; ++ ++ for (j = 0; j < desc->num_entries; j++) { ++ ++ /* ignore duplicates frame desc */ ++ if (desc_entry->pixelcode == desc->entry[j].pixelcode && ++ desc_entry->bus.csi2.vc == desc->entry[j].bus.csi2.vc && ++ desc_entry->bus.csi2.dt == desc->entry[j].bus.csi2.dt) { ++ skip = 1; ++ break; ++ } ++ } ++ if (skip) ++ continue; ++ ++ /* don't exceed v4l2 api */ ++ if (desc->num_entries >= V4L2_FRAME_DESC_ENTRY_MAX) ++ continue; ++ ++ dev_dbg(dev, "%s: found frame desc stream:%u vc/dt:%u/0x%x\n", __func__, ++ desc_entry->stream, ++ desc_entry->bus.csi2.vc, ++ desc_entry->bus.csi2.dt); ++ ++ desc->entry[desc->num_entries] = *desc_entry; ++ desc->num_entries++; ++ } ++ } ++ ++ desc->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; ++ ++ if (desc->num_entries) ++ ret = 0; ++ else ++ ret = -EINVAL; ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++error_graph_walk_source: ++ return ret; ++} ++#endif +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h +index dfca0d2..7397de2 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-csi2.h +@@ -61,4 +61,15 @@ int ipu7_isys_csi2_get_remote_desc(u32 source_stream, + struct media_entity *source_entity, + struct v4l2_mbus_frame_desc_entry *entry, + int *nr_queues); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++int ipu7_isys_csi2_walk_remote_desc_by_stream(u32 source_stream, ++ struct ipu7_isys_csi2 *csi2, ++ struct media_entity *source_entity, ++ struct v4l2_mbus_frame_desc_entry *entry, ++ int *nr_queues); ++int ipu7_isys_csi2_walk_unique_remote_desc(struct v4l2_subdev_state *state, ++ struct ipu7_isys_csi2 *csi2, ++ struct media_entity *source_entity, ++ struct v4l2_mbus_frame_desc *desc); ++#endif + #endif /* IPU7_ISYS_CSI2_H */ +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video-ext.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video-ext.h +new file mode 100644 +index 0000000..7487242 +--- /dev/null ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video-ext.h +@@ -0,0 +1,61 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 - 2025 Intel Corporation ++ */ ++ ++#ifndef IPU7_ISYS_VIDEO_EXT_H ++#define IPU7_ISYS_VIDEO_EXT_H ++ ++#define V4L2_CID_IPU_BASE (V4L2_CID_USER_BASE + 0x1080) ++ ++#define V4L2_CID_IPU_STORE_CSI2_HEADER (V4L2_CID_IPU_BASE + 2) ++#define V4L2_CID_IPU_ISYS_COMPRESSION (V4L2_CID_IPU_BASE + 3) ++ ++#define V4L2_CID_IPU_QUERY_SUB_STREAM (V4L2_CID_IPU_BASE + 4) ++#define V4L2_CID_IPU_SET_SUB_STREAM (V4L2_CID_IPU_BASE + 5) ++ ++#define V4L2_CID_IPU_ENUMERATE_LINK (V4L2_CID_IPU_BASE + 6) ++ ++#define VIDIOC_IPU_GET_DRIVER_VERSION \ ++ _IOWR('v', BASE_VIDIOC_PRIVATE + 3, uint32_t) ++ ++enum ipu7_isys_enum_link_state { ++ IPU7_ISYS_LINK_STATE_DISABLED = 0, ++ IPU7_ISYS_LINK_STATE_ENABLED = 1, ++ IPU7_ISYS_LINK_STATE_DONE = 2, ++ IPU7_ISYS_LINK_STATE_MD = 3, ++ IPU7_ISYS_LINK_STATE_MAX, ++}; ++ ++static struct media_pad *other_pad(struct media_pad *pad); ++bool has_src_pad_stream_active(struct v4l2_subdev *sd, u32 stream, u32 pad); ++bool get_src_pad_by_src_stream(struct v4l2_subdev *sd, u32 stream, u32 *s_pad); ++ ++/* needed for callback */ ++extern int ipu7_isys_inherit_ctrls(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu7_isys_set_fmt_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu7_isys_enum_frameintervals_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu7_isys_enum_fmt_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu7_isys_enum_framesizes_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu7_isys_set_parm_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++extern int ipu7_isys_get_parm_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data); ++ ++extern int media_pipeline_enumerate_by_stream_cb( ++ struct ipu7_isys_video *av, ++ int (*cb_fn)(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, ++ void *data), ++ void *data); ++ ++extern int ipu7_isys_csi2_streams_by_sources(struct ipu7_isys_csi2 *csi2, ++ u32 pad, u32 stream, bool on); ++ ++ ++#endif /* IPU7_ISYS_VIDEO_EXT_H */ +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c +index a1ab842..ac336bf 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.c +@@ -38,6 +38,9 @@ + #include "ipu7-fw-isys.h" + #include "ipu7-isys.h" + #include "ipu7-isys-video.h" ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++#include "ipu7-isys-video-ext.h" ++#endif + #include "ipu7-platform-regs.h" + + const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { +@@ -106,8 +109,8 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { + + static int video_open(struct file *file) + { +-#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET + struct ipu7_isys_video *av = video_drvdata(file); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET + struct ipu7_isys *isys = av->isys; + struct ipu7_bus_device *adev = isys->adev; + +@@ -119,6 +122,11 @@ static int video_open(struct file *file) + } + mutex_unlock(&isys->reset_mutex); + ++#endif ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ /* ipu_isys inherit remote sd ctrls */ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_ENABLED && media_pad_remote_pad_first(&av->pad)) ++ media_pipeline_enumerate_by_stream_cb(av, ipu7_isys_inherit_ctrls, NULL); + #endif + return v4l2_fh_open(file); + } +@@ -143,6 +151,7 @@ static int video_release(struct file *file) + } + + #endif ++ + const struct ipu7_isys_pixelformat *ipu7_isys_get_isys_format(u32 pixelformat) + { + unsigned int i; +@@ -172,7 +181,47 @@ static int ipu7_isys_vidioc_enum_fmt(struct file *file, void *fh, + struct v4l2_fmtdesc *f) + { + unsigned int i, num_found; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ struct ipu7_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_mbus_code_enum mce; ++ int ret=-EINVAL; ++ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DONE) { + ++ mce.index = f->index; ++ mce.pad = 0; ++ ++ /* poll remote sensors */ ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu7_isys_enum_fmt_subdev, &mce); ++ if (!ret) { ++ ret=-EINVAL; ++ for (i = 0; i < ARRAY_SIZE(ipu7_isys_pfmts); i++) { ++ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ continue; ++ ++ if (f->mbus_code && f->mbus_code != mce.code) ++ continue; ++ ++ if (mce.code != ipu7_isys_pfmts[i].code) ++ continue; ++ ++ /* Code found */ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "%s: sd_mbus:0x%x, sd_code::0x%x\n", ++ __func__, ++ ipu7_isys_pfmts[i].code, ++ ipu7_isys_pfmts[i].pixelformat); ++ ++ f->flags = 0; ++ f->pixelformat = ipu7_isys_pfmts[i].pixelformat; ++ ++ return 0; ++ } ++ } ++ return ret; ++ } ++#endif + for (i = 0, num_found = 0; i < ARRAY_SIZE(ipu7_isys_pfmts); i++) { + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + continue; +@@ -198,6 +247,48 @@ static int ipu7_isys_vidioc_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) + { + unsigned int i; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ struct ipu7_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_size_enum fse; ++ int ret = -EINVAL; ++ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DONE) { ++ ++ for (i = 0; i < ARRAY_SIZE(ipu7_isys_pfmts); i++) { ++ if (fsize->pixel_format != ipu7_isys_pfmts[i].pixelformat) ++ continue; ++ ++ fse.code = ipu7_isys_pfmts[i].code; ++ fse.index = fsize->index; ++ ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu7_isys_enum_framesizes_subdev, &fse); ++ if (ret) ++ continue; ++ ++ if (!fse.max_width && !fse.max_height) { ++ fsize->discrete.width = 0; ++ fsize->discrete.height = 0; ++ return -EINVAL; ++ } ++ ++ /* Code found */ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "%s: sd_mbus:0x%x, sd_code::0x%x, WxH:%ux%u\n", ++ __func__, ++ ipu7_isys_pfmts[i].code, ++ ipu7_isys_pfmts[i].pixelformat, ++ fse.max_width, ++ fse.max_height); ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; ++ fsize->discrete.width = fse.max_width; ++ fsize->discrete.height = fse.max_height; ++ return 0; ++ } ++ return -EINVAL; ++ } ++#endif + + if (fsize->index > 0) + return -EINVAL; +@@ -220,6 +311,169 @@ static int ipu7_isys_vidioc_enum_framesizes(struct file *file, void *fh, + return -EINVAL; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++/* extended v4l2_ctrl_ops */ ++static int ipu7_isys_video_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct ipu7_isys_video *av = ctrl->priv; ++ struct ipu7_isys *isys = av->isys; ++ mutex_lock(&isys->mutex); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_IPU_ENUMERATE_LINK: ++ av->enum_link_state = ctrl->val; ++ break; ++ } ++ ++ mutex_unlock(&isys->mutex); ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops ipu7_isys_video_ctrl_ops = { ++ .s_ctrl = ipu7_isys_video_s_ctrl, ++}; ++ ++static const struct v4l2_ctrl_config ipu7_isys_video_enum_link = { ++ .ops = &ipu7_isys_video_ctrl_ops, ++ .id = V4L2_CID_IPU_ENUMERATE_LINK, ++ .name = "Enumerate graph link", ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .min = 0, ++ .max = IPU7_ISYS_LINK_STATE_MAX, ++ .step = 1, ++ .def = 0, ++}; ++ ++/* extended v4l2_ioctl_ops */ ++static struct media_pad *other_pad(struct media_pad *pad) ++{ ++ struct media_link *link; ++ ++ list_for_each_entry(link, &pad->entity->links, list) { ++ if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) ++ != MEDIA_LNK_FL_DATA_LINK) ++ continue; ++ ++ return link->source == pad ? link->sink : link->source; ++ } ++ ++ WARN_ON(1); ++ return NULL; ++} ++ ++static int ipu7_isys_get_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct ipu7_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_interval fi; ++ int ret = -ENOLINK; ++ ++ a->parm.capture.timeperframe.numerator = 1; ++ a->parm.capture.timeperframe.denominator = 30; ++ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DISABLED) ++ return 0; ++ ++ if (media_pad_remote_pad_first(&av->pad)) { ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu7_isys_get_parm_subdev, &fi); ++ ++ if (!ret) { ++ a->parm.capture.timeperframe.numerator = fi.interval.numerator; ++ a->parm.capture.timeperframe.denominator = fi.interval.denominator; ++ } ++ } ++ return ret; ++} ++ ++static int ipu7_isys_set_parm(struct file *file, void *fh, ++ struct v4l2_streamparm *a) ++{ ++ struct ipu7_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_interval fi; ++ int ret = -ENOLINK; ++ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DISABLED) ++ return 0; ++ ++ fi.interval.numerator = a->parm.capture.timeperframe.numerator; ++ fi.interval.denominator = a->parm.capture.timeperframe.denominator; ++ ++ if (media_pad_remote_pad_first(&av->pad)) ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu7_isys_set_parm_subdev, &fi); ++ ++ return ret; ++} ++ ++static int ipu7_isys_enum_frameintervals(struct file *file, void *fh, ++ struct v4l2_frmivalenum *intervals) ++{ ++ struct ipu7_isys_video *av = video_drvdata(file); ++ struct v4l2_subdev_frame_interval_enum fie; ++ unsigned int i, num_found; ++ int ret=-EINVAL; ++ ++ /* poll remote sensors */ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DONE) { ++ ++ for (i = 0; i < ARRAY_SIZE(ipu7_isys_pfmts); i++) { ++ if (intervals->pixel_format != ipu7_isys_pfmts[i].pixelformat) ++ continue; ++ ++ fie.code = ipu7_isys_pfmts[i].code; ++ fie.index = intervals->index; ++ fie.width = intervals->width; ++ fie.height = intervals->height; ++ ++ ret = media_pipeline_enumerate_by_stream_cb(av, ++ ipu7_isys_enum_frameintervals_subdev, &fie); ++ if (ret) ++ continue; ++ ++ if (!fie.interval.numerator && ++ !fie.interval.denominator) { ++ intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ intervals->discrete.numerator = 1; ++ intervals->discrete.denominator = 30; ++ return -EINVAL; ++ } ++ ++ /* Code found */ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "%s: sd_mbus:0x%x,sd_code::0x%x,WxH:%ux%u,fps:%u/%u\n", ++ __func__, ++ ipu7_isys_pfmts[i].code, ++ ipu7_isys_pfmts[i].pixelformat, ++ fie.width, fie.height, ++ fie.interval.numerator,fie.interval.denominator); ++ ++ intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ intervals->discrete.numerator = fie.interval.numerator; ++ intervals->discrete.denominator = fie.interval.denominator; ++ return 0; ++ } ++ return -EINVAL; ++ } ++ ++ if (intervals->index > 0) ++ return -EINVAL; ++ ++ for (i = 0, num_found = 0; i < ARRAY_SIZE(ipu7_isys_pfmts); i++) { ++ if (intervals->pixel_format != ipu7_isys_pfmts[i].pixelformat) ++ continue; ++ ++ /* Code found */ ++ intervals->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ intervals->discrete.numerator = 1; ++ intervals->discrete.denominator = 30; ++ ++ return 0; ++ } ++ return -EINVAL; ++} ++#endif ++ + static int ipu7_isys_vidioc_g_fmt_vid_cap(struct file *file, void *fh, + struct v4l2_format *f) + { +@@ -285,6 +539,30 @@ static int ipu7_isys_vidioc_try_fmt_vid_cap(struct file *file, void *fh, + + __ipu_isys_vidioc_try_fmt_vid_cap(av, f); + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DONE) ++ { ++ int ret = 0; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .pad = 0, ++ }; ++ struct v4l2_mbus_framefmt format = { ++ .width = f->fmt.pix.width, ++ .height = f->fmt.pix.height, ++ .code = ipu7_isys_get_isys_format(f->fmt.pix.pixelformat)->code, ++ .field = f->fmt.pix.field, ++ .colorspace = f->fmt.pix.colorspace, ++ .ycbcr_enc = f->fmt.pix.ycbcr_enc, ++ .quantization = f->fmt.pix.quantization, ++ .xfer_func = f->fmt.pix.xfer_func, ++ }; ++ fmt.format = format; ++ ret = media_pipeline_enumerate_by_stream_cb(av, ipu7_isys_set_fmt_subdev, &fmt); ++ if (ret) ++ return -EINVAL; ++ } ++#endif + return 0; + } + +@@ -293,9 +571,51 @@ static int ipu7_isys_vidioc_s_fmt_vid_cap(struct file *file, void *fh, + { + struct ipu7_isys_video *av = video_drvdata(file); + ++#ifndef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS + ipu7_isys_vidioc_try_fmt_vid_cap(file, fh, f); +- av->pix_fmt = f->fmt.pix; ++#else ++ struct media_pad *source_pad = media_pad_remote_pad_first(&av->pad); ++ struct media_pad *remote_pad = source_pad; ++ struct v4l2_subdev *sd = NULL; + ++ if (vb2_is_busy(&av->aq.vbq)) ++ return -EBUSY; ++ ++ __ipu_isys_vidioc_try_fmt_vid_cap(av, f); ++ ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DONE) { ++ ++ int ret = 0; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .pad = 0, ++ }; ++ struct v4l2_mbus_framefmt format = { ++ .width = f->fmt.pix.width, ++ .height = f->fmt.pix.height, ++ .code = ipu7_isys_get_isys_format(f->fmt.pix.pixelformat)->code, ++ .field = f->fmt.pix.field, ++ .colorspace = f->fmt.pix.colorspace, ++ .ycbcr_enc = f->fmt.pix.ycbcr_enc, ++ .quantization = f->fmt.pix.quantization, ++ .xfer_func = f->fmt.pix.xfer_func, ++ }; ++ fmt.format = format; ++ ret = media_pipeline_enumerate_by_stream_cb(av, ipu7_isys_set_fmt_subdev, &fmt); ++ if (ret) ++ return -EINVAL; ++ ++ /* TODO: set format for CSI-2 ++ do { ++ // Non-subdev nodes can be safely ignored here. ++ if (!is_media_entity_v4l2_subdev(remote_pad->entity)) ++ continue; ++ // Set only for IPU CSI entities ++ } while ((remote_pad = media_pad_remote_pad_first(&remote_pad->entity->pads[0]))); ++ */ ++ } ++#endif ++ av->pix_fmt = f->fmt.pix; + return 0; + } + +@@ -376,7 +696,9 @@ static int link_validate(struct media_link *link) + } + + v4l2_subdev_unlock_state(s_state); +- ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ //av->enum_link_state = IPU7_ISYS_LINK_STATE_DONE; ++#endif + return 0; + unlock: + v4l2_subdev_unlock_state(s_state); +@@ -927,6 +1249,266 @@ out_media_entity_stop_streaming_firmware: + return ret; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++int ipu7_isys_set_fmt_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_format *fmt = ++ (struct v4l2_subdev_format *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->set_fmt) ++ ret = sd->ops->pad->set_fmt(sd, NULL, fmt); ++ ++ return ret; ++} ++ ++int ipu7_isys_get_parm_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_interval *fi = ++ (struct v4l2_subdev_frame_interval *)data; ++ struct v4l2_subdev_state *state = v4l2_subdev_get_unlocked_active_state(sd); ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->get_frame_interval) ++ ret = sd->ops->pad->get_frame_interval(sd, state, fi); ++ ++ return ret; ++} ++ ++int ipu7_isys_set_parm_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_interval *fi = ++ (struct v4l2_subdev_frame_interval *)data; ++ struct v4l2_subdev_state *state = v4l2_subdev_get_unlocked_active_state(sd); ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->set_frame_interval) ++ ret = sd->ops->pad->set_frame_interval(sd, state, fi); ++ ++ return ret; ++} ++ ++int ipu7_isys_enum_fmt_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_mbus_code_enum *mce = ++ (struct v4l2_subdev_mbus_code_enum *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->enum_mbus_code) ++ ret = sd->ops->pad->enum_mbus_code(sd, NULL, mce); ++ ++ return ret; ++} ++ ++int ipu7_isys_enum_framesizes_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_size_enum *fse = ++ (struct v4l2_subdev_frame_size_enum *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->enum_frame_size) ++ ret = sd->ops->pad->enum_frame_size(sd, NULL, fse); ++ ++ return ret; ++} ++ ++int ipu7_isys_enum_frameintervals_subdev(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ struct v4l2_subdev_frame_interval_enum *fie = ++ (struct v4l2_subdev_frame_interval_enum *)data; ++ /* v4l2_subdev_call doesn't call, access directly */ ++ if (sd && sd->ops && sd->ops->pad && sd->ops->pad->enum_frame_interval) ++ ret = sd->ops->pad->enum_frame_interval(sd, NULL, fie); ++ ++ return ret; ++} ++ ++int ipu7_isys_inherit_ctrls(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, void *data) ++{ ++ int ret = 0; ++ ret = v4l2_ctrl_add_handler(&av->ctrl_handler, ++ sd->ctrl_handler, NULL, true); ++ return ret; ++} ++ ++bool has_src_pad_stream_active(struct v4l2_subdev *sd, u32 stream, u32 pad) ++{ ++ struct v4l2_subdev_state *state; ++ struct v4l2_subdev_route *routes; ++ bool has_active_source_stream = false; ++ unsigned int i; ++ ++ state = v4l2_subdev_lock_and_get_active_state(sd); ++ if (!state) ++ return has_active_source_stream; ++ ++ dev_dbg(sd->dev, "%s(): check %s pad/stream: %u/%u has V4L2_SUBDEV_ROUTE_FL_ACTIVE flag\n", ++ __func__, ++ sd->name, ++ pad, ++ stream); ++ routes = state->routing.routes; ++ for (i = 0; i < state->routing.num_routes; i++) { ++ dev_dbg(sd->dev, "%s(): %s pad/stream: %u/%u flags=0x%x\n", ++ __func__, ++ sd->name, ++ routes[i].source_pad, ++ routes[i].source_stream, ++ routes[i].flags); ++ if (routes[i].source_pad == pad && ++ routes[i].source_stream == stream && ++ routes[i].flags == V4L2_SUBDEV_ROUTE_FL_ACTIVE) { ++ dev_dbg(sd->dev, "%s(): %s pad/stream: %u/%u has V4L2_SUBDEV_ROUTE_FL_ACTIVE flag\n", ++ __func__, ++ sd->name, ++ routes[i].source_pad, ++ routes[i].source_stream); ++ has_active_source_stream = true; ++ break; ++ } ++ } ++ ++ v4l2_subdev_unlock_state(state); ++ ++ return has_active_source_stream; ++} ++ ++bool get_src_pad_by_src_stream(struct v4l2_subdev *sd, u32 stream, u32 *s_pad) ++{ ++ struct v4l2_subdev_state *state; ++ struct v4l2_subdev_route *routes; ++ bool has_source_pad = false; ++ unsigned int i; ++ ++ if (!s_pad) ++ return has_source_pad; ++ ++ state = v4l2_subdev_lock_and_get_active_state(sd); ++ if (!state) ++ return has_source_pad; ++ ++ routes = state->routing.routes; ++ for (i = 0; i < state->routing.num_routes; i++) { ++ if (routes[i].source_stream == stream) { ++ dev_dbg(sd->dev, "%s(): Found %s pad/stream: %u/%u\n", ++ __func__, ++ sd->name, ++ routes[i].source_pad, ++ stream); ++ *s_pad = routes[i].source_pad; ++ has_source_pad = true; ++ break; ++ } ++ } ++ ++ v4l2_subdev_unlock_state(state); ++ return has_source_pad; ++} ++ ++int media_pipeline_enumerate_by_stream_cb( ++ struct ipu7_isys_video *av, ++ int (*cb_fn)(struct ipu7_isys_video *av, ++ struct v4l2_subdev *sd, ++ void *data), ++ void *data) ++{ ++ int i; ++ struct media_graph graph; ++ struct media_entity *entity = &av->vdev.entity; ++ struct media_device *mdev = entity->graph_obj.mdev; ++ struct device *dev = entity->graph_obj.mdev->dev; ++ struct media_pad *remote_pad = media_pad_remote_pad_unique(&av->pad); ++ struct ipu7_isys_stream *stream = av->stream; ++ struct ipu7_isys_subdev *asd; ++ struct v4l2_subdev *sd; ++ unsigned int pad_id; ++ u32 stream_id; ++ int ret = -ENOLINK; ++ ++ if (!remote_pad) { ++ dev_err(dev, ++ "%s:%d no remote pad found\n", ++ __func__, __LINE__); ++ goto error_graph_walk_source; ++ } ++ ++ pad_id = remote_pad->index; ++ sd = media_entity_to_v4l2_subdev(remote_pad->entity); ++ if(!sd) { ++ dev_err(dev, ++ "%s():%d no stream found on remote pad %u\n", ++ __func__, __LINE__, pad_id); ++ goto error_graph_walk_source; ++ } ++ stream_id = ipu7_isys_get_src_stream_by_src_pad(sd, pad_id); ++ dev_dbg(dev, ++ "%s(): Check %s (vc=%u) inheritence from %s pad/stream %u/%u\n", ++ __func__, av->vdev.name, av->vc, ++ sd->name, pad_id, stream_id); ++ ++ mutex_lock(&mdev->graph_mutex); ++ ret = media_graph_walk_init(&graph, mdev); ++ if (ret) ++ goto error_graph_walk_start_enum; ++ ++ media_graph_walk_start(&graph, entity); ++ while ((entity = media_graph_walk_next(&graph))) { ++ dev_dbg(dev, ++ "%s(): walk entity name: %s, type:%x, func:%x\n", ++ __func__, ++ entity->name, ++ entity->obj_type, ++ entity->function); ++ ++ sd = (entity->obj_type == MEDIA_ENTITY_TYPE_V4L2_SUBDEV && \ ++ entity->function == MEDIA_ENT_F_CAM_SENSOR) \ ++ ? media_entity_to_v4l2_subdev(entity) : NULL; ++ ++ if (!sd) ++ continue; ++ if (!strlen(sd->name)) ++ continue; ++ ++ /* pre-filter sub-devices */ ++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS)) ++ continue; ++ ++ /* access only subdevices with src pad on same stream id */ ++ if(!get_src_pad_by_src_stream(sd, stream_id, &pad_id)) ++ continue; ++ ++ /* access only subdevices on source stream active route */ ++ if(!has_src_pad_stream_active(sd, stream_id, pad_id)) ++ continue; ++ ++ dev_dbg(dev, "%s(): %s pad/stream: %u/%u\n", ++ __func__, ++ sd->name, ++ pad_id, ++ stream_id); ++ ++ /* call function once */ ++ ret = cb_fn(av, sd, data); ++ break; ++ } ++ av->enum_link_state = IPU7_ISYS_LINK_STATE_DONE; ++ ++error_graph_walk_start_enum: ++ media_graph_walk_cleanup(&graph); ++ mutex_unlock(&mdev->graph_mutex); ++error_graph_walk_source: ++ return ret; ++} ++#endif ++ + static const struct v4l2_ioctl_ops ipu7_v4l2_ioctl_ops = { + .vidioc_querycap = ipu7_isys_vidioc_querycap, + .vidioc_enum_fmt_vid_cap = ipu7_isys_vidioc_enum_fmt, +@@ -943,6 +1525,11 @@ static const struct v4l2_ioctl_ops ipu7_v4l2_ioctl_ops = { + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_expbuf = vb2_ioctl_expbuf, ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ .vidioc_g_parm = ipu7_isys_get_parm, ++ .vidioc_s_parm = ipu7_isys_set_parm, ++ .vidioc_enum_frameintervals = ipu7_isys_enum_frameintervals, ++#endif + }; + + static const struct media_entity_operations entity_ops = { +@@ -1083,6 +1670,14 @@ int ipu7_isys_setup_video(struct ipu7_isys_video *av, + + v4l2_subdev_unlock_state(state); + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ if (av->enum_link_state == IPU7_ISYS_LINK_STATE_DONE) ++ ret = ipu7_isys_csi2_walk_remote_desc_by_stream(route->sink_stream, ++ to_ipu7_isys_csi2(asd), ++ *source_entity, &entry, ++ nr_queues); ++ else ++#endif + ret = ipu7_isys_csi2_get_remote_desc(route->sink_stream, + to_ipu7_isys_csi2(asd), + *source_entity, &entry, +@@ -1180,7 +1775,27 @@ int ipu7_isys_video_init(struct ipu7_isys_video *av) + if (ret) + goto out_media_entity_cleanup; + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ /* create v4l2 ctrl for capture video node */ ++ ret = v4l2_ctrl_handler_init(&av->ctrl_handler, 0); ++ if (ret) { ++ dev_err(&av->isys->adev->auxdev.dev, ++ "failed to init v4l2 ctrl handler for %s\n", av->vdev.name); ++ goto out_ctrl_handler_cleanup; ++ } ++ v4l2_ctrl_new_custom(&av->ctrl_handler, &ipu7_isys_video_enum_link, av); ++ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "ext-ctrls: %s: set video_enum_link\n", av->vdev.name); ++ ++ av->vdev.ctrl_handler = &av->ctrl_handler; ++ return ret; ++ ++out_ctrl_handler_cleanup: ++ v4l2_ctrl_handler_free(&av->ctrl_handler); ++#else + return ret; ++#endif + + out_media_entity_cleanup: + vb2_video_unregister_device(&av->vdev); +@@ -1197,6 +1812,9 @@ out_mutex_destroy: + + void ipu7_isys_video_cleanup(struct ipu7_isys_video *av) + { ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ v4l2_ctrl_handler_free(&av->ctrl_handler); ++#endif + vb2_video_unregister_device(&av->vdev); + media_entity_cleanup(&av->vdev.entity); + mutex_destroy(&av->mutex); +diff --git a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.h b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.h +index e6d1da2..c36be8d 100644 +--- a/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.h ++++ b/ipu7-drivers/drivers/media/pci/intel/ipu7/ipu7-isys-video.h +@@ -97,6 +97,10 @@ struct ipu7_isys_video { + unsigned int skipframe; + unsigned int start_streaming; + #endif ++#ifdef CONFIG_VIDEO_INTEL_IPU7_EXT_CTRLS ++ struct v4l2_ctrl_handler ctrl_handler; ++ unsigned int enum_link_state; /* state for link enumeration by vc */ ++#endif + }; + + #define ipu7_isys_queue_to_video(__aq) \ +-- +2.43.0 + diff --git a/patches/6.12/0001-dkms-v4l2-core-makefile-adaptation.patch b/patches/6.12/0001-dkms-v4l2-core-makefile-adaptation.patch new file mode 100644 index 00000000..a414962a --- /dev/null +++ b/patches/6.12/0001-dkms-v4l2-core-makefile-adaptation.patch @@ -0,0 +1,37 @@ +From ad68c243c09ea361be847ab7e6ef66c634ff6c8b Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Mon, 17 Nov 2025 07:44:33 -0700 +Subject: [PATCH 1/8] dkms : v4l2-core makefile adaptation + +Signed-off-by: florent pirou +--- + 6.12.0/drivers/media/v4l2-core/Makefile | 3 +++ + 6.12.0/drivers/media/v4l2-core/v4l2-dev.c | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/6.12.0/drivers/media/v4l2-core/Makefile b/6.12.0/drivers/media/v4l2-core/Makefile +index 2177b9d..82c235f 100644 +--- a/6.12.0/drivers/media/v4l2-core/Makefile ++++ b/6.12.0/drivers/media/v4l2-core/Makefile +@@ -2,6 +2,9 @@ + # + # Makefile for the V4L2 core + # ++# ipu7-dkms appendix ++CC := ${CC} -I ${M}/../../../include-overrides -I ${M}/../tuners -I ${M}/../dvb-core -I ${M}/../dvb-frontends ++ccflags-y := -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" + + ccflags-y += -I$(srctree)/drivers/media/dvb-frontends + ccflags-y += -I$(srctree)/drivers/media/tuners +diff --git a/6.12.0/drivers/media/v4l2-core/v4l2-dev.c b/6.12.0/drivers/media/v4l2-core/v4l2-dev.c +index 3d7711c..7b3e462 100644 +--- a/6.12.0/drivers/media/v4l2-core/v4l2-dev.c ++++ b/6.12.0/drivers/media/v4l2-core/v4l2-dev.c +@@ -1231,3 +1231,4 @@ MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab , Bill Dirks, + MODULE_DESCRIPTION("Video4Linux2 core driver"); + MODULE_LICENSE("GPL"); + MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +-- +2.43.0 + diff --git a/patches/6.12/0002-dkms-disable-tuner-build-in-v4l2-core.patch b/patches/6.12/0002-dkms-disable-tuner-build-in-v4l2-core.patch new file mode 100644 index 00000000..d65b3cd8 --- /dev/null +++ b/patches/6.12/0002-dkms-disable-tuner-build-in-v4l2-core.patch @@ -0,0 +1,24 @@ +From d71f79d88c67e8f9ba14f924a56f0d0aa9cd95fa Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:14:15 -0700 +Subject: [PATCH 2/8] dkms: disable tuner build in v4l2-core + +Signed-off-by: florent pirou +--- + 6.12.0/drivers/media/v4l2-core/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/6.12.0/drivers/media/v4l2-core/Makefile b/6.12.0/drivers/media/v4l2-core/Makefile +index 82c235f..e5880ff 100644 +--- a/6.12.0/drivers/media/v4l2-core/Makefile ++++ b/6.12.0/drivers/media/v4l2-core/Makefile +@@ -36,5 +36,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o + obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o + obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o + +-obj-$(CONFIG_VIDEO_TUNER) += tuner.o ++# obj-$(CONFIG_VIDEO_TUNER) += tuner.o + obj-$(CONFIG_VIDEO_DEV) += v4l2-dv-timings.o videodev.o +-- +2.43.0 + diff --git a/patches/6.12/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch b/patches/6.12/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch new file mode 100644 index 00000000..3db00112 --- /dev/null +++ b/patches/6.12/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch @@ -0,0 +1,27 @@ +From 48b8c627f42bb64610be862f91b94bc8d1f4ee9a Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Mon, 17 Nov 2025 07:45:23 -0700 +Subject: [PATCH 3/8] drivers: media: set v4l2_subdev_enable_streams_api + +Signed-off-by: hepengpx +Signed-off-by: florent pirou +--- + 6.12.0/drivers/media/v4l2-core/v4l2-subdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/6.12.0/drivers/media/v4l2-core/v4l2-subdev.c b/6.12.0/drivers/media/v4l2-core/v4l2-subdev.c +index 3a4ba08..f535929 100644 +--- a/6.12.0/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/6.12.0/drivers/media/v4l2-core/v4l2-subdev.c +@@ -32,7 +32,7 @@ + * 'v4l2_subdev_enable_streams_api' to 1 below. + */ + +-static bool v4l2_subdev_enable_streams_api; ++static bool v4l2_subdev_enable_streams_api = true; + #endif + + /* +-- +2.43.0 + diff --git a/patches/6.12/0039-ipu-bridge-port-to-bkc.patch b/patches/6.12/0004-ipu-bridge-port-to-bkc.patch similarity index 71% rename from patches/6.12/0039-ipu-bridge-port-to-bkc.patch rename to patches/6.12/0004-ipu-bridge-port-to-bkc.patch index d4c0fab2..19ab1d6d 100644 --- a/patches/6.12/0039-ipu-bridge-port-to-bkc.patch +++ b/patches/6.12/0004-ipu-bridge-port-to-bkc.patch @@ -1,5 +1,13 @@ +From 780162d2dffa271a07441891ad4b7032be69342e Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:56:24 -0700 +Subject: [PATCH 4/8] ipu-bridge : port to bkc + +Signed-off-by: florent pirou +--- 6.12.0/drivers/media/pci/intel/ipu-bridge.c | 2 ++ 1 file changed, 2 insertions(+) + diff --git a/6.12.0/drivers/media/pci/intel/ipu-bridge.c b/6.12.0/drivers/media/pci/intel/ipu-bridge.c index a0e9a71..4e921c7 100644 --- a/6.12.0/drivers/media/pci/intel/ipu-bridge.c @@ -13,3 +21,6 @@ index a0e9a71..4e921c7 100644 /* Omnivision OV8865 */ IPU_SENSOR_CONFIG("INT347A", 1, 360000000), /* Omnivision OV7251 */ +-- +2.43.0 + diff --git a/patches/6.12/0005-ipu-bridge-makefile.patch b/patches/6.12/0005-ipu-bridge-makefile.patch new file mode 100644 index 00000000..6c12afef --- /dev/null +++ b/patches/6.12/0005-ipu-bridge-makefile.patch @@ -0,0 +1,42 @@ +From 3d96753e47c339c218afe74c5ea5bb2f7d0e8c82 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:57:25 -0700 +Subject: [PATCH 5/8] ipu-bridge : makefile + +Signed-off-by: florent pirou +--- + 6.12.0/drivers/media/pci/intel/Kconfig | 5 ----- + 6.12.0/drivers/media/pci/intel/Makefile | 5 +---- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/6.12.0/drivers/media/pci/intel/Kconfig b/6.12.0/drivers/media/pci/intel/Kconfig +index d9fcddc..3fa2b72 100644 +--- a/6.12.0/drivers/media/pci/intel/Kconfig ++++ b/6.12.0/drivers/media/pci/intel/Kconfig +@@ -1,9 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only +- +-source "drivers/media/pci/intel/ipu3/Kconfig" +-source "drivers/media/pci/intel/ipu6/Kconfig" +-source "drivers/media/pci/intel/ivsc/Kconfig" +- + config IPU_BRIDGE + tristate "Intel IPU Bridge" + depends on ACPI || COMPILE_TEST +diff --git a/6.12.0/drivers/media/pci/intel/Makefile b/6.12.0/drivers/media/pci/intel/Makefile +index 3a2cc65..16dc2d2 100644 +--- a/6.12.0/drivers/media/pci/intel/Makefile ++++ b/6.12.0/drivers/media/pci/intel/Makefile +@@ -2,7 +2,4 @@ + # + # Makefile for the IPU drivers + # +-obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +-obj-y += ipu3/ +-obj-y += ivsc/ +-obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ ++obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +\ No newline at end of file +-- +2.43.0 + diff --git a/patches/6.12/0041-ipu-bridge-bkc-backport.patch b/patches/6.12/0006-ipu-bridge-bkc-backport.patch similarity index 85% rename from patches/6.12/0041-ipu-bridge-bkc-backport.patch rename to patches/6.12/0006-ipu-bridge-bkc-backport.patch index cae8d352..a8e05562 100644 --- a/patches/6.12/0041-ipu-bridge-bkc-backport.patch +++ b/patches/6.12/0006-ipu-bridge-bkc-backport.patch @@ -1,10 +1,18 @@ - 6.12.0/drivers/media/pci/intel/ipu-bridge.c | 102 ++++++++++++++++++++++++---- - 1 file changed, 89 insertions(+), 13 deletions(-) +From 5cda1781801b8a15984f40cf43f9bfebd560dd09 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:58:38 -0700 +Subject: [PATCH 6/8] ipu-bridge : bkc backport + +Signed-off-by: florent pirou +--- + 6.12.0/drivers/media/pci/intel/ipu-bridge.c | 100 +++++++++++++++++--- + 1 file changed, 87 insertions(+), 13 deletions(-) + diff --git a/6.12.0/drivers/media/pci/intel/ipu-bridge.c b/6.12.0/drivers/media/pci/intel/ipu-bridge.c -index a0e9a71..4e4f86a 100644 +index 4e921c7..4e4f86a 100644 --- a/6.12.0/drivers/media/pci/intel/ipu-bridge.c +++ b/6.12.0/drivers/media/pci/intel/ipu-bridge.c -@@ -83,6 +85,17 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { +@@ -85,6 +85,17 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { IPU_SENSOR_CONFIG("OVTI2680", 1, 331200000), /* Omnivision OV8856 */ IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000), @@ -22,7 +30,7 @@ index a0e9a71..4e4f86a 100644 }; static const struct ipu_property_names prop_names = { -@@ -313,6 +326,7 @@ int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor) +@@ -315,6 +326,7 @@ int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor) } sensor->link = ssdb.link; @@ -30,7 +38,7 @@ index a0e9a71..4e4f86a 100644 sensor->lanes = ssdb.lanes; sensor->mclkspeed = ssdb.mclkspeed; sensor->rotation = ipu_bridge_parse_rotation(adev, &ssdb); -@@ -472,18 +486,49 @@ static void ipu_bridge_init_swnode_group(struct ipu_sensor *sensor) +@@ -474,18 +486,49 @@ static void ipu_bridge_init_swnode_group(struct ipu_sensor *sensor) } } @@ -85,7 +93,7 @@ index a0e9a71..4e4f86a 100644 nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT( sensor->node_names.endpoint, &nodes[SWNODE_SENSOR_PORT], -@@ -664,7 +709,7 @@ static void ipu_bridge_unregister_sensors(struct ipu_bridge *bridge) +@@ -666,7 +709,7 @@ static void ipu_bridge_unregister_sensors(struct ipu_bridge *bridge) } static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg, @@ -94,7 +102,7 @@ index a0e9a71..4e4f86a 100644 { struct fwnode_handle *fwnode, *primary; struct ipu_sensor *sensor; -@@ -691,31 +736,53 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg, +@@ -693,31 +736,53 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg, if (ret) goto err_put_adev; @@ -154,7 +162,7 @@ index a0e9a71..4e4f86a 100644 ret = ipu_bridge_instantiate_ivsc(sensor); if (ret) -@@ -748,7 +815,16 @@ static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge) +@@ -750,7 +815,16 @@ static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge) const struct ipu_sensor_config *cfg = &ipu_supported_sensors[i]; @@ -172,3 +180,6 @@ index a0e9a71..4e4f86a 100644 if (ret) goto err_unregister_sensors; } +-- +2.43.0 + diff --git a/patches/6.12/0007-ipu-bridge-add-sensors.patch b/patches/6.12/0007-ipu-bridge-add-sensors.patch new file mode 100644 index 00000000..18bf9b76 --- /dev/null +++ b/patches/6.12/0007-ipu-bridge-add-sensors.patch @@ -0,0 +1,30 @@ +From 4f6348286d71d460fafcd03796095b10d8af1758 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:59:32 -0700 +Subject: [PATCH 7/8] ipu-bridge : add sensors + +Signed-off-by: florent pirou +--- + 6.12.0/drivers/media/pci/intel/ipu-bridge.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/6.12.0/drivers/media/pci/intel/ipu-bridge.c b/6.12.0/drivers/media/pci/intel/ipu-bridge.c +index 4e4f86a..66983ff 100644 +--- a/6.12.0/drivers/media/pci/intel/ipu-bridge.c ++++ b/6.12.0/drivers/media/pci/intel/ipu-bridge.c +@@ -47,6 +47,12 @@ + * Please keep the list sorted by ACPI HID. + */ + static const struct ipu_sensor_config ipu_supported_sensors[] = { ++ /* D3 Embedded ISX031 */ ++ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), ++ /* LI AR0830 */ ++ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), ++ /* Innodisk AR0822 */ ++ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), + /* Himax HM11B1 */ + IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000), + /* Himax HM2170 */ +-- +2.43.0 + diff --git a/patches/6.12/0008-media-mc-Add-INTERNAL-pad-flag.patch b/patches/6.12/0008-media-mc-Add-INTERNAL-pad-flag.patch new file mode 100644 index 00000000..285dd0e9 --- /dev/null +++ b/patches/6.12/0008-media-mc-Add-INTERNAL-pad-flag.patch @@ -0,0 +1,79 @@ +From 062c348d329bbdd40bd17e5eead11c182921246a Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Tue, 9 Jun 2026 11:33:50 +0000 +Subject: [PATCH 8/8] media: mc: Add INTERNAL pad flag + +Internal sink pads will be used as routing endpoints in V4L2 [GS]_ROUTING +IOCTLs, to indicate that the stream begins in the entity. Internal sink +pads are pads that have both SINK and INTERNAL flags set. + +Also prevent creating links to pads that have been flagged as internal and +initialising SOURCE pads with INTERNAL flag set. + +Signed-off-by: Sakari Ailus +Reviewed-by: Tomi Valkeinen +Reviewed-by: Laurent Pinchart +Reviewed-by: Mirela Rabulea +--- + 6.12.0/drivers/media/mc/mc-entity.c | 15 +++++++++++---- + 6.12.0/include/uapi/linux/media.h | 1 + + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/6.12.0/drivers/media/mc/mc-entity.c b/6.12.0/drivers/media/mc/mc-entity.c +index 96dd0f6..a197c14 100644 +--- a/6.12.0/drivers/media/mc/mc-entity.c ++++ b/6.12.0/drivers/media/mc/mc-entity.c +@@ -209,11 +209,16 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, + mutex_lock(&mdev->graph_mutex); + + media_entity_for_each_pad(entity, iter) { ++ const u32 pad_flags = iter->flags & (MEDIA_PAD_FL_SINK | ++ MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_INTERNAL); ++ + iter->entity = entity; + iter->index = i++; + +- if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK | +- MEDIA_PAD_FL_SOURCE)) != 1) { ++ if (pad_flags != MEDIA_PAD_FL_SINK && ++ pad_flags != (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL) && ++ pad_flags != MEDIA_PAD_FL_SOURCE) { + ret = -EINVAL; + break; + } +@@ -1118,7 +1123,8 @@ int media_get_pad_index(struct media_entity *entity, u32 pad_type, + + for (i = 0; i < entity->num_pads; i++) { + if ((entity->pads[i].flags & +- (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type) ++ (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_INTERNAL)) != pad_type) + continue; + + if (entity->pads[i].sig_type == sig_type) +@@ -1146,7 +1152,8 @@ media_create_pad_link(struct media_entity *source, u16 source_pad, + return -EINVAL; + if (WARN_ON(!(source->pads[source_pad].flags & MEDIA_PAD_FL_SOURCE))) + return -EINVAL; +- if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK))) ++ if (WARN_ON(source->pads[source_pad].flags & MEDIA_PAD_FL_INTERNAL) || ++ WARN_ON(sink->pads[sink_pad].flags & MEDIA_PAD_FL_INTERNAL)) + return -EINVAL; + + link = media_add_link(&source->links); +diff --git a/6.12.0/include/uapi/linux/media.h b/6.12.0/include/uapi/linux/media.h +index 1c80b1d..80cfd12 100644 +--- a/6.12.0/include/uapi/linux/media.h ++++ b/6.12.0/include/uapi/linux/media.h +@@ -208,6 +208,7 @@ struct media_entity_desc { + #define MEDIA_PAD_FL_SINK (1U << 0) + #define MEDIA_PAD_FL_SOURCE (1U << 1) + #define MEDIA_PAD_FL_MUST_CONNECT (1U << 2) ++#define MEDIA_PAD_FL_INTERNAL (1U << 3) + + struct media_pad_desc { + __u32 entity; /* entity ID */ +-- +2.43.0 + diff --git a/patches/6.12/0040-ipu-bridge-makefile.patch b/patches/6.12/0040-ipu-bridge-makefile.patch deleted file mode 100644 index 62bca464..00000000 --- a/patches/6.12/0040-ipu-bridge-makefile.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Yew, Chang Ching -Date: Mon, 9 Mar 2026.17:30:00 +0800 -Subject: [PATCH] ipu-bridge: Add scaling direct MIPI HIDS for v6.12 - -Signed-off-by: Yew, Chang Ching ---- - 6.12.0/drivers/media/pci/intel/Kconfig | 5 - - 6.12.0/drivers/media/pci/intel/Makefile | 5 +- - 3 files changed, 187 insertions(+), 38 deletions(-) -diff --git b/6.12.0/drivers/media/pci/intel/Kconfig a/6.12.0/drivers/media/pci/intel/Kconfig -index d9fcddc..3fa2b72 100644 ---- b/6.12.0/drivers/media/pci/intel/Kconfig -+++ a/6.12.0/drivers/media/pci/intel/Kconfig -@@ -1,9 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0-only -- --source "drivers/media/pci/intel/ipu3/Kconfig" --source "drivers/media/pci/intel/ipu6/Kconfig" --source "drivers/media/pci/intel/ivsc/Kconfig" -- - config IPU_BRIDGE - tristate "Intel IPU Bridge" - depends on ACPI || COMPILE_TEST -diff --git b/6.12.0/drivers/media/pci/intel/Makefile a/6.12.0/drivers/media/pci/intel/Makefile -index 3a2cc65..16dc2d2 100644 ---- b/6.12.0/drivers/media/pci/intel/Makefile -+++ a/6.12.0/drivers/media/pci/intel/Makefile -@@ -2,7 +2,4 @@ - # - # Makefile for the IPU drivers - # --obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o --obj-y += ipu3/ --obj-y += ivsc/ --obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ -+obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o -\ No newline at end of file diff --git a/patches/6.12/0042-ipu-bridge-add-sensor.patch b/patches/6.12/0042-ipu-bridge-add-sensor.patch deleted file mode 100644 index c7f2e3d7..00000000 --- a/patches/6.12/0042-ipu-bridge-add-sensor.patch +++ /dev/null @@ -1,23 +0,0 @@ - 6.12.0/drivers/media/pci/intel/ipu-bridge.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) -diff --git a/6.12.0/drivers/media/pci/intel/ipu-bridge.c b/6.12.0/drivers/media/pci/intel/ipu-bridge.c -index 4e4f86a..e680967 100644 ---- a/6.12.0/drivers/media/pci/intel/ipu-bridge.c -+++ b/6.12.0/drivers/media/pci/intel/ipu-bridge.c -@@ -91,6 +91,16 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { - IPU_SENSOR_CONFIG("INTC10C5", 0), - /* Lontium lt6911uxc */ - IPU_SENSOR_CONFIG("INTC10B1", 0), -+ /* D3 Embedded ISX031 */ -+ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), -+ /* LI AR0830 */ -+ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), -+ /* Innodisk AR0822 */ -+ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), -+ /* LI IMX415 */ -+ IPU_SENSOR_CONFIG("IMXSN415", 1, 445500000), -+ /* LI IMX586 */ -+ IPU_SENSOR_CONFIG("IMXSN586", 1, 1000000000), - }; - - static const struct ipu_sensor_config ipu_supported_sensors_dummy[] = { diff --git a/patches/6.17/0004-dkms-v4l2-core-makefile-adaptation.patch b/patches/6.17/0001-dkms-v4l2-core-makefile-adaptation.patch similarity index 89% rename from patches/6.17/0004-dkms-v4l2-core-makefile-adaptation.patch rename to patches/6.17/0001-dkms-v4l2-core-makefile-adaptation.patch index 9db07e09..9bd519dc 100644 --- a/patches/6.17/0004-dkms-v4l2-core-makefile-adaptation.patch +++ b/patches/6.17/0001-dkms-v4l2-core-makefile-adaptation.patch @@ -1,7 +1,7 @@ -From 9097a7b8bcb983c7afc812af26eb7d313200f849 Mon Sep 17 00:00:00 2001 +From cd79d7876722199c877a711f90f3ed67fb4b7aea Mon Sep 17 00:00:00 2001 From: florent pirou Date: Mon, 17 Nov 2025 07:44:33 -0700 -Subject: [PATCH 4/8] dkms : v4l2-core makefile adaptation 6.17 +Subject: [PATCH 1/7] dkms : v4l2-core makefile adaptation Signed-off-by: florent pirou --- @@ -10,7 +10,7 @@ Signed-off-by: florent pirou 2 files changed, 4 insertions(+) diff --git a/6.17.0/drivers/media/v4l2-core/Makefile b/6.17.0/drivers/media/v4l2-core/Makefile -index 2177b9d..82c235f 100644 +index 2177b9d..fc41f58 100644 --- a/6.17.0/drivers/media/v4l2-core/Makefile +++ b/6.17.0/drivers/media/v4l2-core/Makefile @@ -2,6 +2,9 @@ diff --git a/patches/6.17/0009-dkms-disable-tuner-build-in-v4l2-core.patch b/patches/6.17/0002-dkms-disable-tuner-build-in-v4l2-core.patch similarity index 69% rename from patches/6.17/0009-dkms-disable-tuner-build-in-v4l2-core.patch rename to patches/6.17/0002-dkms-disable-tuner-build-in-v4l2-core.patch index 9259b5d8..34bdd4c4 100644 --- a/patches/6.17/0009-dkms-disable-tuner-build-in-v4l2-core.patch +++ b/patches/6.17/0002-dkms-disable-tuner-build-in-v4l2-core.patch @@ -1,6 +1,7 @@ -From: Khai Wen, Ng -Date: Wed, 12 Feb 2026 11:08:00 +0800 -Subject: [PATCH] dkms: disable tuner build in v4l2-core 6.17 +From 732765f6daf368e7cf6eba36524afda1aaea8521 Mon Sep 17 00:00:00 2001 +From: "Khai Wen, Ng" +Date: Thu, 12 Feb 2026 11:08:00 +0800 +Subject: [PATCH 2/7] dkms: disable tuner build in v4l2-core Disable CONFIG_VIDEO_TUNER build as tuner dependencies (mt20xx.h, etc.) are not available in the DKMS build environment. @@ -11,10 +12,10 @@ Signed-off-by: Khai Wen, Ng 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/6.17.0/drivers/media/v4l2-core/Makefile b/6.17.0/drivers/media/v4l2-core/Makefile -index 2177b9d..de5ac11 100644 +index fc41f58..623b065 100644 --- a/6.17.0/drivers/media/v4l2-core/Makefile +++ b/6.17.0/drivers/media/v4l2-core/Makefile -@@ -33,5 +33,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o +@@ -36,5 +36,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o diff --git a/patches/6.17/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch b/patches/6.17/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch similarity index 82% rename from patches/6.17/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch rename to patches/6.17/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch index 9d7099f4..b1658da3 100644 --- a/patches/6.17/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch +++ b/patches/6.17/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch @@ -1,8 +1,7 @@ -From 33750bc14545f84d7c26168b956e960b6427b005 Mon Sep 17 00:00:00 2001 +From a1b6b9625960363b91a7b1086c15c1e6c190f4b0 Mon Sep 17 00:00:00 2001 From: florent pirou Date: Mon, 17 Nov 2025 07:45:23 -0700 -Subject: [PATCH 5/8] drivers: media: set v4l2_subdev_enable_streams_api=true - for WA 6.17 +Subject: [PATCH 3/7] drivers: media: set v4l2_subdev_enable_streams_api Signed-off-by: hepengpx Signed-off-by: florent pirou diff --git a/patches/6.17/0004-ipu-bridge-makefile.patch b/patches/6.17/0004-ipu-bridge-makefile.patch new file mode 100644 index 00000000..a57a749c --- /dev/null +++ b/patches/6.17/0004-ipu-bridge-makefile.patch @@ -0,0 +1,42 @@ +From 5efb16baee18cfae48e06d4396c781fc7ec7bd54 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 06:08:59 -0700 +Subject: [PATCH 4/7] ipu-bridge : makefile + +Signed-off-by: florent pirou +--- + 6.17.0/drivers/media/pci/intel/Kconfig | 5 ----- + 6.17.0/drivers/media/pci/intel/Makefile | 5 +---- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/6.17.0/drivers/media/pci/intel/Kconfig b/6.17.0/drivers/media/pci/intel/Kconfig +index d9fcddc..3fa2b72 100644 +--- a/6.17.0/drivers/media/pci/intel/Kconfig ++++ b/6.17.0/drivers/media/pci/intel/Kconfig +@@ -1,9 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only +- +-source "drivers/media/pci/intel/ipu3/Kconfig" +-source "drivers/media/pci/intel/ipu6/Kconfig" +-source "drivers/media/pci/intel/ivsc/Kconfig" +- + config IPU_BRIDGE + tristate "Intel IPU Bridge" + depends on ACPI || COMPILE_TEST +diff --git a/6.17.0/drivers/media/pci/intel/Makefile b/6.17.0/drivers/media/pci/intel/Makefile +index 3a2cc65..16dc2d2 100644 +--- a/6.17.0/drivers/media/pci/intel/Makefile ++++ b/6.17.0/drivers/media/pci/intel/Makefile +@@ -2,7 +2,4 @@ + # + # Makefile for the IPU drivers + # +-obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +-obj-y += ipu3/ +-obj-y += ivsc/ +-obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ ++obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +\ No newline at end of file +-- +2.43.0 + diff --git a/patches/6.17/0041-ipu-bridge-bkc-backport.patch b/patches/6.17/0005-ipu-bridge-bkc-backport.patch similarity index 86% rename from patches/6.17/0041-ipu-bridge-bkc-backport.patch rename to patches/6.17/0005-ipu-bridge-bkc-backport.patch index 928c14e8..d2b0800b 100644 --- a/patches/6.17/0041-ipu-bridge-bkc-backport.patch +++ b/patches/6.17/0005-ipu-bridge-bkc-backport.patch @@ -1,3 +1,13 @@ +From de6c96ede10f21a40391f39089ca7ac8595cec04 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 07:52:11 -0700 +Subject: [PATCH 5/7] ipu-bridge : bkc backport + +Signed-off-by: florent pirou +--- + 6.17.0/drivers/media/pci/intel/ipu-bridge.c | 25 ++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + diff --git a/6.17.0/drivers/media/pci/intel/ipu-bridge.c b/6.17.0/drivers/media/pci/intel/ipu-bridge.c index 4e57935..3c947d1 100644 --- a/6.17.0/drivers/media/pci/intel/ipu-bridge.c @@ -71,3 +81,6 @@ index 4e57935..3c947d1 100644 } static void ipu_bridge_init_swnode_names(struct ipu_sensor *sensor) +-- +2.43.0 + diff --git a/patches/6.17/0006-ipu-bridge-add-sensors.patch b/patches/6.17/0006-ipu-bridge-add-sensors.patch new file mode 100644 index 00000000..28e065c4 --- /dev/null +++ b/patches/6.17/0006-ipu-bridge-add-sensors.patch @@ -0,0 +1,30 @@ +From 3ac92b7c62a9c45260e1aee19c14232fad92c7b3 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 07:55:49 -0700 +Subject: [PATCH 6/7] ipu-bridge : add sensors + +Signed-off-by: florent pirou +--- + 6.17.0/drivers/media/pci/intel/ipu-bridge.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/6.17.0/drivers/media/pci/intel/ipu-bridge.c b/6.17.0/drivers/media/pci/intel/ipu-bridge.c +index 3c947d1..e9c8422 100644 +--- a/6.17.0/drivers/media/pci/intel/ipu-bridge.c ++++ b/6.17.0/drivers/media/pci/intel/ipu-bridge.c +@@ -51,6 +51,12 @@ + * Please keep the list sorted by ACPI HID. + */ + static const struct ipu_sensor_config ipu_supported_sensors[] = { ++ /* D3 Embedded ISX031 */ ++ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), ++ /* LI AR0830 */ ++ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), ++ /* Innodisk AR0822 */ ++ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), + /* Himax HM11B1 */ + IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000), + /* Himax HM2170 */ +-- +2.43.0 + diff --git a/patches/6.17/0063-media-mc-Add-INTERNAL-pad-flag.patch b/patches/6.17/0007-media-mc-Add-INTERNAL-pad-flag.patch similarity index 87% rename from patches/6.17/0063-media-mc-Add-INTERNAL-pad-flag.patch rename to patches/6.17/0007-media-mc-Add-INTERNAL-pad-flag.patch index bcd36508..0ec05197 100644 --- a/patches/6.17/0063-media-mc-Add-INTERNAL-pad-flag.patch +++ b/patches/6.17/0007-media-mc-Add-INTERNAL-pad-flag.patch @@ -1,7 +1,7 @@ -From 8ca39c83ce030a6bf6826b230b91408d5a74c9d1 Mon Sep 17 00:00:00 2001 +From d64ce376d97539a49ea366c354f8fd05e484c05b Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 14 Nov 2025 16:51:41 +0200 -Subject: [PATCH 5/5] media: mc: Add INTERNAL pad flag +Subject: [PATCH 7/7] media: mc: Add INTERNAL pad flag Internal sink pads will be used as routing endpoints in V4L2 [GS]_ROUTING IOCTLs, to indicate that the stream begins in the entity. Internal sink @@ -15,12 +15,12 @@ Reviewed-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Reviewed-by: Mirela Rabulea --- - 6.17.0/drivers/media/mc/mc-entity.c | 15 ++++++++++++--- - 6.17.0/include/uapi/linux/media.h | 1 + - 3 files changed, 22 insertions(+), 3 deletions(-) + 6.17.0/drivers/media/mc/mc-entity.c | 15 ++++++++++++--- + 6.17.0/include/uapi/linux/media.h | 1 + + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/6.17.0/drivers/media/mc/mc-entity.c b/6.17.0/drivers/media/mc/mc-entity.c -index 307920c8b3549..928613d60e8f3 100644 +index 0455909..04d69f0 100644 --- a/6.17.0/drivers/media/mc/mc-entity.c +++ b/6.17.0/drivers/media/mc/mc-entity.c @@ -209,11 +209,16 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, @@ -63,7 +63,7 @@ index 307920c8b3549..928613d60e8f3 100644 link = media_add_link(&source->links); if (link == NULL) diff --git a/6.17.0/include/uapi/linux/media.h b/6.17.0/include/uapi/linux/media.h -index 1c80b1d6bbaf3..80cfd12a43fc1 100644 +index 1c80b1d..80cfd12 100644 --- a/6.17.0/include/uapi/linux/media.h +++ b/6.17.0/include/uapi/linux/media.h @@ -208,6 +208,7 @@ struct media_entity_desc { @@ -75,5 +75,5 @@ index 1c80b1d6bbaf3..80cfd12a43fc1 100644 struct media_pad_desc { __u32 entity; /* entity ID */ -- -2.51.1 +2.43.0 diff --git a/patches/6.17/0040-ipu-bridge-makefile.patch b/patches/6.17/0040-ipu-bridge-makefile.patch deleted file mode 100644 index 5d152b0d..00000000 --- a/patches/6.17/0040-ipu-bridge-makefile.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Yew, Chang Ching -Date: Tue, 3 Mar 2026 17:30:00 +0800 -Subject: [PATCH] ipu-bridge: Add scaling direct MIPI HIDS - -Signed-off-by: Yew, Chang Ching ---- - 6.17.0/drivers/media/pci/intel/Kconfig | 5 - - 6.17.0/drivers/media/pci/intel/Makefile | 5 +- - 3 files changed, 173 insertions(+), 10 deletions(-) - -diff --git b/6.17.0/drivers/media/pci/intel/Kconfig a/6.17.0/drivers/media/pci/intel/Kconfig -index d9fcddc..3fa2b72 100644 ---- b/6.17.0/drivers/media/pci/intel/Kconfig -+++ a/6.17.0/drivers/media/pci/intel/Kconfig -@@ -1,9 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0-only -- --source "drivers/media/pci/intel/ipu3/Kconfig" --source "drivers/media/pci/intel/ipu6/Kconfig" --source "drivers/media/pci/intel/ivsc/Kconfig" -- - config IPU_BRIDGE - tristate "Intel IPU Bridge" - depends on ACPI || COMPILE_TEST -diff --git b/6.17.0/drivers/media/pci/intel/Makefile a/6.17.0/drivers/media/pci/intel/Makefile -index 3a2cc65..16dc2d2 100644 ---- b/6.17.0/drivers/media/pci/intel/Makefile -+++ a/6.17.0/drivers/media/pci/intel/Makefile -@@ -2,7 +2,4 @@ - # - # Makefile for the IPU drivers - # --obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o --obj-y += ipu3/ --obj-y += ivsc/ --obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ -+obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o -\ No newline at end of file diff --git a/patches/6.17/0042-ipu-bridge-add-sensor.patch b/patches/6.17/0042-ipu-bridge-add-sensor.patch deleted file mode 100644 index c23b706a..00000000 --- a/patches/6.17/0042-ipu-bridge-add-sensor.patch +++ /dev/null @@ -1,23 +0,0 @@ - 6.17.0/drivers/media/pci/intel/ipu-bridge.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) -diff --git a/6.17.0/drivers/media/pci/intel/ipu-bridge.c b/6.17.0/drivers/media/pci/intel/ipu-bridge.c -index 3c947d1..36e8f10 100644 ---- a/6.17.0/drivers/media/pci/intel/ipu-bridge.c -+++ b/6.17.0/drivers/media/pci/intel/ipu-bridge.c -@@ -97,6 +97,16 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { - IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000), - /* Lontium lt6911gxd */ - IPU_SENSOR_CONFIG("INTC1124", 0), -+ /* D3 Embedded ISX031 */ -+ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), -+ /* LI AR0830 */ -+ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), -+ /* Innodisk AR0822 */ -+ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), -+ /* LI IMX415 */ -+ IPU_SENSOR_CONFIG("IMXSN415", 1, 445500000), -+ /* LI IMX586 */ -+ IPU_SENSOR_CONFIG("IMXSN586", 1, 1000000000), - }; - - static const struct ipu_property_names prop_names = { diff --git a/patches/6.18/0004-dkms-v4l2-core-makefile-adaptation.patch b/patches/6.18/0001-dkms-v4l2-core-makefile-adaptation.patch similarity index 74% rename from patches/6.18/0004-dkms-v4l2-core-makefile-adaptation.patch rename to patches/6.18/0001-dkms-v4l2-core-makefile-adaptation.patch index 71057524..09b28bc7 100644 --- a/patches/6.18/0004-dkms-v4l2-core-makefile-adaptation.patch +++ b/patches/6.18/0001-dkms-v4l2-core-makefile-adaptation.patch @@ -1,9 +1,9 @@ -From 9097a7b8bcb983c7afc812af26eb7d313200f849 Mon Sep 17 00:00:00 2001 -From: florent pirou -Date: Mon, 17 Nov 2025 07:44:33 -0700 -Subject: [PATCH 4/8] dkms : v4l2-core makefile adaptation 6.18 +From 32d276024d1ce27950b778562f964898f5b7f636 Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Fri, 16 Jan 2026 03:20:05 -0700 +Subject: [PATCH 1/9] dkms : v4l2-core makefile adaptation -Signed-off-by: florent pirou +Signed-off-by: Florent Pirou --- 6.18.0/drivers/media/v4l2-core/Makefile | 3 +++ 6.18.0/drivers/media/v4l2-core/v4l2-dev.c | 1 + @@ -17,17 +17,17 @@ index 2177b9d..82c235f 100644 # # Makefile for the V4L2 core # -+# dkms appendix ++# ipu7-dkms appendix +CC := ${CC} -I ${M}/../../../include-overrides -I ${M}/../tuners -I ${M}/../dvb-core -I ${M}/../dvb-frontends +ccflags-y := -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" ccflags-y += -I$(srctree)/drivers/media/dvb-frontends ccflags-y += -I$(srctree)/drivers/media/tuners diff --git a/6.18.0/drivers/media/v4l2-core/v4l2-dev.c b/6.18.0/drivers/media/v4l2-core/v4l2-dev.c -index c369235..1997370 100644 +index 10a126e..96cc91d 100644 --- a/6.18.0/drivers/media/v4l2-core/v4l2-dev.c +++ b/6.18.0/drivers/media/v4l2-core/v4l2-dev.c -@@ -1245,3 +1245,4 @@ MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab , Bill Dirks, +@@ -1256,3 +1256,4 @@ MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab , Bill Dirks, MODULE_DESCRIPTION("Video4Linux2 core driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); diff --git a/patches/6.18/0009-dkms-disable-tuner-build-in-v4l2-core.patch b/patches/6.18/0002-dkms-disable-tuner-build-in-v4l2-core.patch similarity index 56% rename from patches/6.18/0009-dkms-disable-tuner-build-in-v4l2-core.patch rename to patches/6.18/0002-dkms-disable-tuner-build-in-v4l2-core.patch index 44a47b46..452bd00f 100644 --- a/patches/6.18/0009-dkms-disable-tuner-build-in-v4l2-core.patch +++ b/patches/6.18/0002-dkms-disable-tuner-build-in-v4l2-core.patch @@ -1,20 +1,18 @@ -From: Khai Wen, Ng -Date: Wed, 12 Feb 2026 11:08:00 +0800 -Subject: [PATCH] dkms: disable tuner build in v4l2-core 6.18 +From 134f11d7c2d204e30ff2414cc3e793e1aaa5c0f1 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:14:28 -0700 +Subject: [PATCH 2/9] dkms: disable tuner build in v4l2-core -Disable CONFIG_VIDEO_TUNER build as tuner dependencies (mt20xx.h, etc.) -are not available in the DKMS build environment. - -Signed-off-by: Khai Wen, Ng +Signed-off-by: florent pirou --- 6.18.0/drivers/media/v4l2-core/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/6.18.0/drivers/media/v4l2-core/Makefile b/6.18.0/drivers/media/v4l2-core/Makefile -index 2177b9d..de5ac11 100644 +index 82c235f..e5880ff 100644 --- a/6.18.0/drivers/media/v4l2-core/Makefile +++ b/6.18.0/drivers/media/v4l2-core/Makefile -@@ -33,5 +33,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o +@@ -36,5 +36,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o diff --git a/patches/6.18/0003-Revert-media-v4l2-subdev-Make-struct-v4l2_subdev_str.patch b/patches/6.18/0003-Revert-media-v4l2-subdev-Make-struct-v4l2_subdev_str.patch new file mode 100644 index 00000000..299ba2c5 --- /dev/null +++ b/patches/6.18/0003-Revert-media-v4l2-subdev-Make-struct-v4l2_subdev_str.patch @@ -0,0 +1,95 @@ +From 0e574c2a201f1cdff247a4feaa7447dff2fe4490 Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Fri, 16 Jan 2026 10:10:16 -0700 +Subject: [PATCH 3/9] Revert "media: v4l2-subdev: Make struct + v4l2_subdev_stream_config private" + +This reverts commit 5195b777552d2e2fa735c6cad75797efa132bd60. + +Signed-off-by: Florent Pirou +--- + 6.18.0/drivers/media/v4l2-core/v4l2-subdev.c | 24 ------------------- + 6.18.0/include/media/v4l2-subdev.h | 25 +++++++++++++++++++- + 2 files changed, 24 insertions(+), 25 deletions(-) + +diff --git a/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c b/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c +index 25e66bf..4f64ac1 100644 +--- a/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c +@@ -26,30 +26,6 @@ + #include + #include + +-/** +- * struct v4l2_subdev_stream_config - Used for storing stream configuration. +- * +- * @pad: pad number +- * @stream: stream number +- * @enabled: has the stream been enabled with v4l2_subdev_enable_streams() +- * @fmt: &struct v4l2_mbus_framefmt +- * @crop: &struct v4l2_rect to be used for crop +- * @compose: &struct v4l2_rect to be used for compose +- * @interval: frame interval +- * +- * This structure stores configuration for a stream. +- */ +-struct v4l2_subdev_stream_config { +- u32 pad; +- u32 stream; +- bool enabled; +- +- struct v4l2_mbus_framefmt fmt; +- struct v4l2_rect crop; +- struct v4l2_rect compose; +- struct v4l2_fract interval; +-}; +- + #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) + /* + * The Streams API is an experimental feature. To use the Streams API, set +diff --git a/6.18.0/include/media/v4l2-subdev.h b/6.18.0/include/media/v4l2-subdev.h +index e0bb58c..ad37aaf 100644 +--- a/6.18.0/include/media/v4l2-subdev.h ++++ b/6.18.0/include/media/v4l2-subdev.h +@@ -36,7 +36,6 @@ struct v4l2_event_subscription; + struct v4l2_fh; + struct v4l2_subdev; + struct v4l2_subdev_fh; +-struct v4l2_subdev_stream_config; + struct tuner_setup; + struct v4l2_mbus_frame_desc; + struct led_classdev; +@@ -684,6 +683,30 @@ struct v4l2_subdev_pad_config { + struct v4l2_fract interval; + }; + ++/** ++ * struct v4l2_subdev_stream_config - Used for storing stream configuration. ++ * ++ * @pad: pad number ++ * @stream: stream number ++ * @enabled: has the stream been enabled with v4l2_subdev_enable_streams() ++ * @fmt: &struct v4l2_mbus_framefmt ++ * @crop: &struct v4l2_rect to be used for crop ++ * @compose: &struct v4l2_rect to be used for compose ++ * @interval: frame interval ++ * ++ * This structure stores configuration for a stream. ++ */ ++struct v4l2_subdev_stream_config { ++ u32 pad; ++ u32 stream; ++ bool enabled; ++ ++ struct v4l2_mbus_framefmt fmt; ++ struct v4l2_rect crop; ++ struct v4l2_rect compose; ++ struct v4l2_fract interval; ++}; ++ + /** + * struct v4l2_subdev_stream_configs - A collection of stream configs. + * +-- +2.43.0 + diff --git a/patches/6.17/0062-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch b/patches/6.18/0004-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch similarity index 90% rename from patches/6.17/0062-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch rename to patches/6.18/0004-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch index fe8c0316..7b8e78fe 100644 --- a/patches/6.17/0062-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch +++ b/patches/6.18/0004-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch @@ -1,7 +1,7 @@ -From 6b7a8bf64caba09b3b26b377641e2246ffbff13b Mon Sep 17 00:00:00 2001 +From 277dc50650ea9f8e6f1a856e3c82468b611b70f6 Mon Sep 17 00:00:00 2001 From: "Yew, Chang Ching" Date: Thu, 27 Nov 2025 02:49:53 +0800 -Subject: [PATCH 4/5] media: v4l2-async: Fix error handling on steps after +Subject: [PATCH 4/9] media: v4l2-async: Fix error handling on steps after finding a match Once an async connection is found to be matching with an fwnode, a @@ -24,11 +24,11 @@ Fix these specific issues: Signed-off-by: Sakari Ailus --- - 6.17.0/drivers/media/v4l2-core/v4l2-async.c | 45 +++++++++++++++++++--------- + 6.17.0/drivers/media/v4l2-core/v4l2-async.c | 45 ++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/6.17.0/drivers/media/v4l2-core/v4l2-async.c b/6.17.0/drivers/media/v4l2-core/v4l2-async.c -index ee884a8221fbd..1c08bba9ecb91 100644 +index ee884a8..1c08bba 100644 --- a/6.17.0/drivers/media/v4l2-core/v4l2-async.c +++ b/6.17.0/drivers/media/v4l2-core/v4l2-async.c @@ -343,7 +343,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, @@ -82,7 +82,7 @@ index ee884a8221fbd..1c08bba9ecb91 100644 } /* Test all async sub-devices in a notifier for a match. */ -@@ -445,6 +453,10 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier) +@@ -445,6 +453,10 @@ again: if (ret < 0) return ret; @@ -106,7 +106,7 @@ index ee884a8221fbd..1c08bba9ecb91 100644 ret = v4l2_async_nf_try_complete(notifier); if (ret) -@@ -853,9 +869,10 @@ int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module) +@@ -853,9 +869,10 @@ err_unbind: if (subdev_notifier) v4l2_async_nf_unbind_all_subdevs(subdev_notifier); @@ -120,5 +120,5 @@ index ee884a8221fbd..1c08bba9ecb91 100644 sd->owner = NULL; -- -2.51.1 +2.43.0 diff --git a/patches/6.18/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch b/patches/6.18/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch index 7898fe71..988ffc63 100644 --- a/patches/6.18/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch +++ b/patches/6.18/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch @@ -1,17 +1,15 @@ -From 33750bc14545f84d7c26168b956e960b6427b005 Mon Sep 17 00:00:00 2001 -From: florent pirou -Date: Mon, 17 Nov 2025 07:45:23 -0700 -Subject: [PATCH 5/8] drivers: media: set v4l2_subdev_enable_streams_api=true - for WA 6.18 +From 7f1a6a024fc7c66a152b45ebd1215cc16029b6b4 Mon Sep 17 00:00:00 2001 +From: Florent Pirou +Date: Fri, 16 Jan 2026 03:22:26 -0700 +Subject: [PATCH 5/9] drivers: media: set v4l2_subdev_enable_streams_api -Signed-off-by: hepengpx -Signed-off-by: florent pirou +Signed-off-by: Florent Pirou --- 6.18.0/drivers/media/v4l2-core/v4l2-subdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c b/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c -index 4fd25fe..60a0556 100644 +index 4f64ac1..b2b7125 100644 --- a/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c +++ b/6.18.0/drivers/media/v4l2-core/v4l2-subdev.c @@ -32,7 +32,7 @@ diff --git a/patches/6.18/0006-ipu-bridge-makefile.patch b/patches/6.18/0006-ipu-bridge-makefile.patch new file mode 100644 index 00000000..3b0776ac --- /dev/null +++ b/patches/6.18/0006-ipu-bridge-makefile.patch @@ -0,0 +1,42 @@ +From 344f74896aa8864b89221553bc1a5a7c0d36a9b7 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 06:09:09 -0700 +Subject: [PATCH 6/9] ipu-bridge : makefile + +Signed-off-by: florent pirou +--- + 6.18.0/drivers/media/pci/intel/Kconfig | 5 ----- + 6.18.0/drivers/media/pci/intel/Makefile | 5 +---- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/6.18.0/drivers/media/pci/intel/Kconfig b/6.18.0/drivers/media/pci/intel/Kconfig +index d9fcddc..3fa2b72 100644 +--- a/6.18.0/drivers/media/pci/intel/Kconfig ++++ b/6.18.0/drivers/media/pci/intel/Kconfig +@@ -1,9 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only +- +-source "drivers/media/pci/intel/ipu3/Kconfig" +-source "drivers/media/pci/intel/ipu6/Kconfig" +-source "drivers/media/pci/intel/ivsc/Kconfig" +- + config IPU_BRIDGE + tristate "Intel IPU Bridge" + depends on ACPI || COMPILE_TEST +diff --git a/6.18.0/drivers/media/pci/intel/Makefile b/6.18.0/drivers/media/pci/intel/Makefile +index 3a2cc65..16dc2d2 100644 +--- a/6.18.0/drivers/media/pci/intel/Makefile ++++ b/6.18.0/drivers/media/pci/intel/Makefile +@@ -2,7 +2,4 @@ + # + # Makefile for the IPU drivers + # +-obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +-obj-y += ipu3/ +-obj-y += ivsc/ +-obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ ++obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +\ No newline at end of file +-- +2.43.0 + diff --git a/patches/6.18/0041-ipu-bridge-bkc-backport.patch b/patches/6.18/0007-ipu-bridge-bkc-backport.patch similarity index 83% rename from patches/6.18/0041-ipu-bridge-bkc-backport.patch rename to patches/6.18/0007-ipu-bridge-bkc-backport.patch index 6f9d9dc7..aac0714d 100644 --- a/patches/6.18/0041-ipu-bridge-bkc-backport.patch +++ b/patches/6.18/0007-ipu-bridge-bkc-backport.patch @@ -1,5 +1,15 @@ +From 1640a4ba61ab5d78821bfd53595b71259dda2a32 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 07:52:42 -0700 +Subject: [PATCH 7/9] ipu-bridge : bkc backport + +Signed-off-by: florent pirou +--- + 6.18.0/drivers/media/pci/intel/ipu-bridge.c | 25 ++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + diff --git a/6.18.0/drivers/media/pci/intel/ipu-bridge.c b/6.18.0/drivers/media/pci/intel/ipu-bridge.c -index 4e57935..3c947d1 100644 +index 4e57935..1c60df1 100644 --- a/6.18.0/drivers/media/pci/intel/ipu-bridge.c +++ b/6.18.0/drivers/media/pci/intel/ipu-bridge.c @@ -35,6 +35,9 @@ @@ -65,9 +75,12 @@ index 4e57935..3c947d1 100644 + * 1. keep fwnode property list no change. + * 2. IPU driver needs to get bus_type from remote sensor ep. + */ -+ sensor->ipu_properties[2] = PROPERTY_ENTRY_U32 -+ (sensor->prop_names.bus_type, ++ sensor->ipu_properties[2] = PROPERTY_ENTRY_U32( ++ sensor->prop_names.bus_type, + bus_type); } static void ipu_bridge_init_swnode_names(struct ipu_sensor *sensor) +-- +2.43.0 + diff --git a/patches/6.18/0008-ipu-bridge-add-sensors.patch b/patches/6.18/0008-ipu-bridge-add-sensors.patch new file mode 100644 index 00000000..6128590b --- /dev/null +++ b/patches/6.18/0008-ipu-bridge-add-sensors.patch @@ -0,0 +1,30 @@ +From 5270e764ec9d5171a0fba8adabaeb645baad066f Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 07:56:02 -0700 +Subject: [PATCH 8/9] ipu-bridge : add sensors + +Signed-off-by: florent pirou +--- + 6.18.0/drivers/media/pci/intel/ipu-bridge.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/6.18.0/drivers/media/pci/intel/ipu-bridge.c b/6.18.0/drivers/media/pci/intel/ipu-bridge.c +index 1c60df1..88bec73 100644 +--- a/6.18.0/drivers/media/pci/intel/ipu-bridge.c ++++ b/6.18.0/drivers/media/pci/intel/ipu-bridge.c +@@ -51,6 +51,12 @@ + * Please keep the list sorted by ACPI HID. + */ + static const struct ipu_sensor_config ipu_supported_sensors[] = { ++ /* D3 Embedded ISX031 */ ++ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), ++ /* LI AR0830 */ ++ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), ++ /* Innodisk AR0822 */ ++ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), + /* Himax HM11B1 */ + IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000), + /* Himax HM2170 */ +-- +2.43.0 + diff --git a/patches/6.18/0009-media-mc-Add-INTERNAL-pad-flag.patch b/patches/6.18/0009-media-mc-Add-INTERNAL-pad-flag.patch new file mode 100644 index 00000000..f70d8243 --- /dev/null +++ b/patches/6.18/0009-media-mc-Add-INTERNAL-pad-flag.patch @@ -0,0 +1,79 @@ +From d2168c161693e5d97daa060228f08f1a507892b8 Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Tue, 9 Jun 2026 11:48:48 +0000 +Subject: [PATCH 9/9] media: mc: Add INTERNAL pad flag + +Internal sink pads will be used as routing endpoints in V4L2 [GS]_ROUTING +IOCTLs, to indicate that the stream begins in the entity. Internal sink +pads are pads that have both SINK and INTERNAL flags set. + +Also prevent creating links to pads that have been flagged as internal and +initialising SOURCE pads with INTERNAL flag set. + +Signed-off-by: Sakari Ailus +Reviewed-by: Tomi Valkeinen +Reviewed-by: Laurent Pinchart +Reviewed-by: Mirela Rabulea +--- + 6.18.0/drivers/media/mc/mc-entity.c | 15 ++++++++++++--- + 6.18.0/include/uapi/linux/media.h | 1 + + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/6.18.0/drivers/media/mc/mc-entity.c b/6.18.0/drivers/media/mc/mc-entity.c +index 9519a53..df20356 100644 +--- a/6.18.0/drivers/media/mc/mc-entity.c ++++ b/6.18.0/drivers/media/mc/mc-entity.c +@@ -209,11 +209,16 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, + mutex_lock(&mdev->graph_mutex); + + media_entity_for_each_pad(entity, iter) { ++ const u32 pad_flags = iter->flags & (MEDIA_PAD_FL_SINK | ++ MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_INTERNAL); ++ + iter->entity = entity; + iter->index = i++; + +- if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK | +- MEDIA_PAD_FL_SOURCE)) != 1) { ++ if (pad_flags != MEDIA_PAD_FL_SINK && ++ pad_flags != (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL) && ++ pad_flags != MEDIA_PAD_FL_SOURCE) { + ret = -EINVAL; + break; + } +@@ -1118,7 +1123,8 @@ int media_get_pad_index(struct media_entity *entity, u32 pad_type, + + for (i = 0; i < entity->num_pads; i++) { + if ((entity->pads[i].flags & +- (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type) ++ (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_INTERNAL)) != pad_type) + continue; + + if (entity->pads[i].sig_type == sig_type) +@@ -1148,6 +1154,9 @@ media_create_pad_link(struct media_entity *source, u16 source_pad, + return -EINVAL; + if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK))) + return -EINVAL; ++ if (WARN_ON(source->pads[source_pad].flags & MEDIA_PAD_FL_INTERNAL) || ++ WARN_ON(sink->pads[sink_pad].flags & MEDIA_PAD_FL_INTERNAL)) ++ return -EINVAL; + + link = media_add_link(&source->links); + if (link == NULL) +diff --git a/6.18.0/include/uapi/linux/media.h b/6.18.0/include/uapi/linux/media.h +index 1c80b1d..80cfd12 100644 +--- a/6.18.0/include/uapi/linux/media.h ++++ b/6.18.0/include/uapi/linux/media.h +@@ -208,6 +208,7 @@ struct media_entity_desc { + #define MEDIA_PAD_FL_SINK (1U << 0) + #define MEDIA_PAD_FL_SOURCE (1U << 1) + #define MEDIA_PAD_FL_MUST_CONNECT (1U << 2) ++#define MEDIA_PAD_FL_INTERNAL (1U << 3) + + struct media_pad_desc { + __u32 entity; /* entity ID */ +-- +2.43.0 + diff --git a/patches/6.18/0040-ipu-bridge-makefile.patch b/patches/6.18/0040-ipu-bridge-makefile.patch deleted file mode 100644 index f40da596..00000000 --- a/patches/6.18/0040-ipu-bridge-makefile.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Yew, Chang Ching -Date: Tue, 3 Mar 2026 17:30:00 +0800 -Subject: [PATCH] ipu-bridge: Add scaling direct MIPI HIDS - -Signed-off-by: Yew, Chang Ching ---- - 6.18.0/drivers/media/pci/intel/Kconfig | 5 - - 6.18.0/drivers/media/pci/intel/Makefile | 5 +- - 2 files changed, 1 insertion(+), 9 deletions(-) - -diff --git b/6.18.0/drivers/media/pci/intel/Kconfig a/6.18.0/drivers/media/pci/intel/Kconfig -index d9fcddc..3fa2b72 100644 ---- b/6.18.0/drivers/media/pci/intel/Kconfig -+++ a/6.18.0/drivers/media/pci/intel/Kconfig -@@ -1,9 +1,4 @@ - # SPDX-License-Identifier: GPL-2.0-only -- --source "drivers/media/pci/intel/ipu3/Kconfig" --source "drivers/media/pci/intel/ipu6/Kconfig" --source "drivers/media/pci/intel/ivsc/Kconfig" -- - config IPU_BRIDGE - tristate "Intel IPU Bridge" - depends on ACPI || COMPILE_TEST -diff --git b/6.18.0/drivers/media/pci/intel/Makefile a/6.18.0/drivers/media/pci/intel/Makefile -index 3a2cc65..16dc2d2 100644 ---- b/6.18.0/drivers/media/pci/intel/Makefile -+++ a/6.18.0/drivers/media/pci/intel/Makefile -@@ -2,7 +2,4 @@ - # - # Makefile for the IPU drivers - # --obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o --obj-y += ipu3/ --obj-y += ivsc/ --obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ -+obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o diff --git a/patches/6.18/0042-ipu-bridge-add-sensor.patch b/patches/6.18/0042-ipu-bridge-add-sensor.patch deleted file mode 100644 index 751491a6..00000000 --- a/patches/6.18/0042-ipu-bridge-add-sensor.patch +++ /dev/null @@ -1,23 +0,0 @@ - 6.18.0/drivers/media/pci/intel/ipu-bridge.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) -diff --git a/6.18.0/drivers/media/pci/intel/ipu-bridge.c b/6.18.0/drivers/media/pci/intel/ipu-bridge.c -index 3c947d1..36e8f10 100644 ---- a/6.18.0/drivers/media/pci/intel/ipu-bridge.c -+++ b/6.18.0/drivers/media/pci/intel/ipu-bridge.c -@@ -97,6 +97,16 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { - IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000), - /* Lontium lt6911gxd */ - IPU_SENSOR_CONFIG("INTC1124", 0), -+ /* D3 Embedded ISX031 */ -+ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), -+ /* LI AR0830 */ -+ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), -+ /* Innodisk AR0822 */ -+ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), -+ /* LI IMX415 */ -+ IPU_SENSOR_CONFIG("IMXSN415", 1, 445500000), -+ /* LI IMX586 */ -+ IPU_SENSOR_CONFIG("IMXSN586", 1, 1000000000), - }; - - static const struct ipu_property_names prop_names = { diff --git a/patches/7.0/0001-dkms-v4l2-core-makefile-adaptation.patch b/patches/7.0/0001-dkms-v4l2-core-makefile-adaptation.patch new file mode 100644 index 00000000..97dd16c3 --- /dev/null +++ b/patches/7.0/0001-dkms-v4l2-core-makefile-adaptation.patch @@ -0,0 +1,37 @@ +From 50b6f0728cc235f0b13eb9d3b26654b952a9d6e0 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:09:24 -0700 +Subject: [PATCH 1/7] dkms : v4l2-core makefile adaptation + +Signed-off-by: florent pirou +--- + 7.0.0/drivers/media/v4l2-core/Makefile | 3 +++ + 7.0.0/drivers/media/v4l2-core/v4l2-dev.c | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/7.0.0/drivers/media/v4l2-core/Makefile b/7.0.0/drivers/media/v4l2-core/Makefile +index 329f0ea..e7bcbf4 100644 +--- a/7.0.0/drivers/media/v4l2-core/Makefile ++++ b/7.0.0/drivers/media/v4l2-core/Makefile +@@ -2,6 +2,9 @@ + # + # Makefile for the V4L2 core + # ++# ipu7-dkms appendix ++CC := ${CC} -I ${M}/../../../include-overrides -I ${M}/../tuners -I ${M}/../dvb-core -I ${M}/../dvb-frontends ++ccflags-y := -DDRIVER_VERSION_SUFFIX=\"${DRIVER_VERSION_SUFFIX}\" + + ccflags-y += -I$(srctree)/drivers/media/dvb-frontends + ccflags-y += -I$(srctree)/drivers/media/tuners +diff --git a/7.0.0/drivers/media/v4l2-core/v4l2-dev.c b/7.0.0/drivers/media/v4l2-core/v4l2-dev.c +index 6ce623a..6a7394c 100644 +--- a/7.0.0/drivers/media/v4l2-core/v4l2-dev.c ++++ b/7.0.0/drivers/media/v4l2-core/v4l2-dev.c +@@ -1256,3 +1256,4 @@ MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab , Bill Dirks, + MODULE_DESCRIPTION("Video4Linux2 core driver"); + MODULE_LICENSE("GPL"); + MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); ++MODULE_VERSION(DRIVER_VERSION_SUFFIX); +-- +2.43.0 + diff --git a/patches/7.0/0002-dkms-disable-tuner-build-in-v4l2-core.patch b/patches/7.0/0002-dkms-disable-tuner-build-in-v4l2-core.patch new file mode 100644 index 00000000..ffa83cd6 --- /dev/null +++ b/patches/7.0/0002-dkms-disable-tuner-build-in-v4l2-core.patch @@ -0,0 +1,24 @@ +From bef04fed10de12d09b16b47e6bf386b3f7c0c8a4 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:14:40 -0700 +Subject: [PATCH 2/7] dkms: disable tuner build in v4l2-core + +Signed-off-by: florent pirou +--- + 7.0.0/drivers/media/v4l2-core/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/7.0.0/drivers/media/v4l2-core/Makefile b/7.0.0/drivers/media/v4l2-core/Makefile +index e7bcbf4..6ae8206 100644 +--- a/7.0.0/drivers/media/v4l2-core/Makefile ++++ b/7.0.0/drivers/media/v4l2-core/Makefile +@@ -37,5 +37,5 @@ obj-$(CONFIG_V4L2_JPEG_HELPER) += v4l2-jpeg.o + obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o + obj-$(CONFIG_V4L2_VP9) += v4l2-vp9.o + +-obj-$(CONFIG_VIDEO_TUNER) += tuner.o ++# obj-$(CONFIG_VIDEO_TUNER) += tuner.o + obj-$(CONFIG_VIDEO_DEV) += v4l2-dv-timings.o videodev.o +-- +2.43.0 + diff --git a/patches/7.0/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch b/patches/7.0/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch new file mode 100644 index 00000000..2e220acd --- /dev/null +++ b/patches/7.0/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch @@ -0,0 +1,26 @@ +From a9274d07c5c9921c70ba1fb3189e88fc30b55baa Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 05:10:52 -0700 +Subject: [PATCH 3/7] drivers: media: set v4l2_subdev_enable_streams_api + +Signed-off-by: florent pirou +--- + 7.0.0/drivers/media/v4l2-core/v4l2-subdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/7.0.0/drivers/media/v4l2-core/v4l2-subdev.c b/7.0.0/drivers/media/v4l2-core/v4l2-subdev.c +index 32e6f60..9cf0075 100644 +--- a/7.0.0/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/7.0.0/drivers/media/v4l2-core/v4l2-subdev.c +@@ -56,7 +56,7 @@ struct v4l2_subdev_stream_config { + * 'v4l2_subdev_enable_streams_api' to 1 below. + */ + +-static bool v4l2_subdev_enable_streams_api; ++static bool v4l2_subdev_enable_streams_api = true; + #endif + + /* +-- +2.43.0 + diff --git a/patches/7.0/0004-ipu-bridge-makefile.patch b/patches/7.0/0004-ipu-bridge-makefile.patch new file mode 100644 index 00000000..d0c7a345 --- /dev/null +++ b/patches/7.0/0004-ipu-bridge-makefile.patch @@ -0,0 +1,42 @@ +From 66007828b8112c7615e2e9d5bfea528300f99467 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 06:09:20 -0700 +Subject: [PATCH 4/7] ipu-bridge : makefile + +Signed-off-by: florent pirou +--- + 7.0.0/drivers/media/pci/intel/Kconfig | 5 ----- + 7.0.0/drivers/media/pci/intel/Makefile | 5 +---- + 2 files changed, 1 insertion(+), 9 deletions(-) + +diff --git a/7.0.0/drivers/media/pci/intel/Kconfig b/7.0.0/drivers/media/pci/intel/Kconfig +index 3f14ca1..99e9869 100644 +--- a/7.0.0/drivers/media/pci/intel/Kconfig ++++ b/7.0.0/drivers/media/pci/intel/Kconfig +@@ -1,9 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only +- +-source "drivers/media/pci/intel/ipu3/Kconfig" +-source "drivers/media/pci/intel/ipu6/Kconfig" +-source "drivers/media/pci/intel/ivsc/Kconfig" +- + config IPU_BRIDGE + tristate "Intel IPU Bridge" + depends on ACPI +diff --git a/7.0.0/drivers/media/pci/intel/Makefile b/7.0.0/drivers/media/pci/intel/Makefile +index 3a2cc65..16dc2d2 100644 +--- a/7.0.0/drivers/media/pci/intel/Makefile ++++ b/7.0.0/drivers/media/pci/intel/Makefile +@@ -2,7 +2,4 @@ + # + # Makefile for the IPU drivers + # +-obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +-obj-y += ipu3/ +-obj-y += ivsc/ +-obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ ++obj-$(CONFIG_IPU_BRIDGE) += ipu-bridge.o +\ No newline at end of file +-- +2.43.0 + diff --git a/patches/7.0/0005-ipu-bridge-bkc-backport.patch b/patches/7.0/0005-ipu-bridge-bkc-backport.patch new file mode 100644 index 00000000..423a25a1 --- /dev/null +++ b/patches/7.0/0005-ipu-bridge-bkc-backport.patch @@ -0,0 +1,86 @@ +From 87f7af1244756dc4e987e4d1628b2f0f083b58d1 Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 07:52:55 -0700 +Subject: [PATCH 5/7] ipu-bridge : bkc backport + +Signed-off-by: florent pirou +--- + 7.0.0/drivers/media/pci/intel/ipu-bridge.c | 25 +++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/7.0.0/drivers/media/pci/intel/ipu-bridge.c b/7.0.0/drivers/media/pci/intel/ipu-bridge.c +index 32cc95a..7d0614c 100644 +--- a/7.0.0/drivers/media/pci/intel/ipu-bridge.c ++++ b/7.0.0/drivers/media/pci/intel/ipu-bridge.c +@@ -36,6 +36,9 @@ + */ + #define IVSC_DEV_NAME "intel_vsc" + ++#define PHY_MODE_DPHY 0 ++#define PHY_MODE_CPHY 1 ++ + /* + * Extend this array with ACPI Hardware IDs of devices known to be working + * plus the number of link-frequencies expected by their drivers, along with +@@ -97,6 +100,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { + IPU_SENSOR_CONFIG("SONY471A", 1, 200000000), + /* Toshiba T4KA3 */ + IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000), ++ /* Lontium lt6911gxd */ ++ IPU_SENSOR_CONFIG("INTC1124", 0), + }; + + /* +@@ -345,6 +350,7 @@ int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor) + + sensor->link = ssdb.link; + sensor->lanes = ssdb.lanes; ++ sensor->phyconfig = ssdb.phyconfig; + sensor->mclkspeed = ssdb.mclkspeed; + sensor->rotation = ipu_bridge_parse_rotation(adev, &ssdb); + sensor->orientation = ipu_bridge_parse_orientation(adev); +@@ -363,6 +369,7 @@ static void ipu_bridge_create_fwnode_properties( + { + struct ipu_property_names *names = &sensor->prop_names; + struct software_node *nodes = sensor->swnodes; ++ u8 bus_type; + + sensor->prop_names = prop_names; + +@@ -420,9 +427,16 @@ static void ipu_bridge_create_fwnode_properties( + PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); + } + ++ if (sensor->phyconfig == PHY_MODE_DPHY) ++ bus_type = V4L2_FWNODE_BUS_TYPE_CSI2_DPHY; ++ else if (sensor->phyconfig == PHY_MODE_CPHY) ++ bus_type = V4L2_FWNODE_BUS_TYPE_CSI2_CPHY; ++ else ++ bus_type = V4L2_FWNODE_BUS_TYPE_GUESS; ++ + sensor->ep_properties[0] = PROPERTY_ENTRY_U32( + sensor->prop_names.bus_type, +- V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); ++ bus_type); + sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN( + sensor->prop_names.data_lanes, + bridge->data_lanes, sensor->lanes); +@@ -442,6 +456,15 @@ static void ipu_bridge_create_fwnode_properties( + sensor->ipu_properties[1] = PROPERTY_ENTRY_REF_ARRAY( + sensor->prop_names.remote_endpoint, + sensor->remote_ref); ++ ++ /* ++ * TODO: Remove the bus_type property for IPU ++ * 1. keep fwnode property list no change. ++ * 2. IPU driver needs to get bus_type from remote sensor ep. ++ */ ++ sensor->ipu_properties[2] = PROPERTY_ENTRY_U32( ++ sensor->prop_names.bus_type, ++ bus_type); + } + + static void ipu_bridge_init_swnode_names(struct ipu_sensor *sensor) +-- +2.43.0 + diff --git a/patches/7.0/0006-ipu-bridge-add-sensors.patch b/patches/7.0/0006-ipu-bridge-add-sensors.patch new file mode 100644 index 00000000..733a9d55 --- /dev/null +++ b/patches/7.0/0006-ipu-bridge-add-sensors.patch @@ -0,0 +1,30 @@ +From 47ad6baddd9d25ff88b24f0c52a52a5402514fcf Mon Sep 17 00:00:00 2001 +From: florent pirou +Date: Tue, 28 Apr 2026 07:56:15 -0700 +Subject: [PATCH 6/7] ipu-bridge : add sensors + +Signed-off-by: florent pirou +--- + 7.0.0/drivers/media/pci/intel/ipu-bridge.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/7.0.0/drivers/media/pci/intel/ipu-bridge.c b/7.0.0/drivers/media/pci/intel/ipu-bridge.c +index 7d0614c..21c379f 100644 +--- a/7.0.0/drivers/media/pci/intel/ipu-bridge.c ++++ b/7.0.0/drivers/media/pci/intel/ipu-bridge.c +@@ -52,6 +52,12 @@ + * Please keep the list sorted by ACPI HID. + */ + static const struct ipu_sensor_config ipu_supported_sensors[] = { ++ /* D3 Embedded ISX031 */ ++ IPU_SENSOR_CONFIG("INTC113C", 1, 300000000), ++ /* LI AR0830 */ ++ IPU_SENSOR_CONFIG("LIAR0830", 1, 600000000), ++ /* Innodisk AR0822 */ ++ IPU_SENSOR_CONFIG("EV8MOOM1", 1, 600000000), + /* Himax HM11B1 */ + IPU_SENSOR_CONFIG("HIMX11B1", 1, 384000000), + /* Himax HM2170 */ +-- +2.43.0 + diff --git a/patches/7.0/0007-media-mc-Add-INTERNAL-pad-flag.patch b/patches/7.0/0007-media-mc-Add-INTERNAL-pad-flag.patch new file mode 100644 index 00000000..c3edd883 --- /dev/null +++ b/patches/7.0/0007-media-mc-Add-INTERNAL-pad-flag.patch @@ -0,0 +1,79 @@ +From 9d5374cb175b20a0913ce142d08a7e170cd0be98 Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Tue, 9 Jun 2026 11:50:19 +0000 +Subject: [PATCH 7/7] media: mc: Add INTERNAL pad flag + +Internal sink pads will be used as routing endpoints in V4L2 [GS]_ROUTING +IOCTLs, to indicate that the stream begins in the entity. Internal sink +pads are pads that have both SINK and INTERNAL flags set. + +Also prevent creating links to pads that have been flagged as internal and +initialising SOURCE pads with INTERNAL flag set. + +Signed-off-by: Sakari Ailus +Reviewed-by: Tomi Valkeinen +Reviewed-by: Laurent Pinchart +Reviewed-by: Mirela Rabulea +--- + 7.0.0/drivers/media/mc/mc-entity.c | 15 ++++++++++++--- + 7.0.0/include/uapi/linux/media.h | 1 + + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/7.0.0/drivers/media/mc/mc-entity.c b/7.0.0/drivers/media/mc/mc-entity.c +index 3fa0bc6..7938f78 100644 +--- a/7.0.0/drivers/media/mc/mc-entity.c ++++ b/7.0.0/drivers/media/mc/mc-entity.c +@@ -209,11 +209,16 @@ int media_entity_pads_init(struct media_entity *entity, u16 num_pads, + mutex_lock(&mdev->graph_mutex); + + media_entity_for_each_pad(entity, iter) { ++ const u32 pad_flags = iter->flags & (MEDIA_PAD_FL_SINK | ++ MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_INTERNAL); ++ + iter->entity = entity; + iter->index = i++; + +- if (hweight32(iter->flags & (MEDIA_PAD_FL_SINK | +- MEDIA_PAD_FL_SOURCE)) != 1) { ++ if (pad_flags != MEDIA_PAD_FL_SINK && ++ pad_flags != (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_INTERNAL) && ++ pad_flags != MEDIA_PAD_FL_SOURCE) { + ret = -EINVAL; + break; + } +@@ -1118,7 +1123,8 @@ int media_get_pad_index(struct media_entity *entity, u32 pad_type, + + for (i = 0; i < entity->num_pads; i++) { + if ((entity->pads[i].flags & +- (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type) ++ (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE | ++ MEDIA_PAD_FL_INTERNAL)) != pad_type) + continue; + + if (entity->pads[i].sig_type == sig_type) +@@ -1148,6 +1154,9 @@ media_create_pad_link(struct media_entity *source, u16 source_pad, + return -EINVAL; + if (WARN_ON(!(sink->pads[sink_pad].flags & MEDIA_PAD_FL_SINK))) + return -EINVAL; ++ if (WARN_ON(source->pads[source_pad].flags & MEDIA_PAD_FL_INTERNAL) || ++ WARN_ON(sink->pads[sink_pad].flags & MEDIA_PAD_FL_INTERNAL)) ++ return -EINVAL; + + link = media_add_link(&source->links); + if (link == NULL) +diff --git a/7.0.0/include/uapi/linux/media.h b/7.0.0/include/uapi/linux/media.h +index 1c80b1d..80cfd12 100644 +--- a/7.0.0/include/uapi/linux/media.h ++++ b/7.0.0/include/uapi/linux/media.h +@@ -208,6 +208,7 @@ struct media_entity_desc { + #define MEDIA_PAD_FL_SINK (1U << 0) + #define MEDIA_PAD_FL_SOURCE (1U << 1) + #define MEDIA_PAD_FL_MUST_CONNECT (1U << 2) ++#define MEDIA_PAD_FL_INTERNAL (1U << 3) + + struct media_pad_desc { + __u32 entity; /* entity ID */ +-- +2.43.0 + From 02078653bc5f963fecbb81a1d8a562f04855170b Mon Sep 17 00:00:00 2001 From: florent pirou Date: Wed, 10 Jun 2026 17:28:10 +0000 Subject: [PATCH 2/3] SQUASHME: dkms(refactor): add namespacing Signed-off-by: florent pirou --- dkms.conf | 251 ++++++++++++++++++++++-------------------------------- 1 file changed, 102 insertions(+), 149 deletions(-) diff --git a/dkms.conf b/dkms.conf index d4edaf42..6e752ea6 100644 --- a/dkms.conf +++ b/dkms.conf @@ -8,12 +8,20 @@ CLEAN="make KERNELRELEASE=$kernelver KERNEL_SRC=$kernel_source_dir clean" AUTOINSTALL="yes" BUILD_EXCLUSIVE_KERNEL="^(6\.(12|17|18)([-.+].*|[a-z].*)?|7\.0([-.+].*|[a-z].*)?)$" +#Extract kernel version substring that is used to identify source directory for kernel modules +# i.e 6.12.8-intel-ese-experimental-lts-rt ==> 6.12.0 +# i.e 6.17.0-oem-1011 ==> 6.17.0 +# i.e 6.17rt-intel ==> 6.17.0 +# i.e 6.18.6-intel-ese-experimental-lts-rt ==> 6.18.0 +SELECTED_KERNEL=$(echo $kernelver | cut -d- -f1 | sed -r 's/([0-9]+\.[0-9]+).*/\1.0/g') KERNEL_VER=$(echo $kernelver | cut -d. -f1) KERNEL_PATCH=$(echo $kernelver | cut -d. -f2 | cut -d- -f1) MODULE_PATH="drivers/media/i2c" MODULE_DEST="/kernel/drivers/media/i2c/" +BUILD_EXCLUSIVE_CONFIG="CONFIG_VIDEO_V4L2_I2C" + POST_ADD="dkms-kernel-source.sh" j=0 @@ -21,16 +29,46 @@ j=0 # Patches for supported kernels # V4L2 core patches -POST_ADD+=" drivers/media/v4l2-core" +POST_ADD+=" drivers/media/v4l2-core drivers/media/mc include/uapi/linux/media.h drivers/media/pci/intel/Kconfig drivers/media/pci/intel/Makefile drivers/media/pci/intel/ipu-bridge.c" + +# V4L2 core patches for 6.12 +PATCH[$j]="6.12/0001-dkms-v4l2-core-makefile-adaptation.patch" +PATCH_MATCH[$j]="^(6.1[2])" +PATCH[$((++j))]="6.12/0002-dkms-disable-tuner-build-in-v4l2-core.patch" +PATCH_MATCH[$j]="^(6.1[2])" +PATCH[$((++j))]="6.12/0003-drivers-media-set-v4l2_subdev_enable_streams_api.patch" +PATCH_MATCH[$j]="^(6.1[2])" +# ipu-bridge patches for 6.12 +PATCH[$((++j))]="6.12/0004-ipu-bridge-port-to-bkc.patch" +PATCH_MATCH[$j]="^(6.1[2]-intel)" +PATCH[$((++j))]="6.12/0005-ipu-bridge-makefile.patch" +PATCH_MATCH[$j]="^(6.1[2])" +PATCH[$((++j))]="6.12/0006-ipu-bridge-bkc-backport.patch" +PATCH_MATCH[$j]="^(6.1[2])" +PATCH[$((++j))]="6.12/0007-ipu-bridge-add-sensor.patch" +PATCH_MATCH[$j]="^(6.1[2])" +# media-controller patches backport 6.12 +PATCH[$((++j))]="6.12/0008-media-mc-Add-INTERNAL-pad-flag.patch" +PATCH_MATCH[$j]="^(6.1[2])" # V4L2 core patches for 6.17 -PATCH[$j]="6.17/0004-dkms-v4l2-core-makefile-adaptation.patch" +PATCH[$j]="6.17/0001-dkms-v4l2-core-makefile-adaptation.patch" +PATCH_MATCH[$j]="^(6.1[7])" +PATCH[$((++j))]="6.17/0002-drivers-media-set-v4l2_subdev_enable_streams_api.patch" +PATCH_MATCH[$j]="^(6.1[7])" +PATCH[$((++j))]="6.17/0003-dkms-disable-tuner-build-in-v4l2-core.patch" +PATCH_MATCH[$j]="^(6.1[7])" +PATCH[$((++j))]="6.17/0004-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch" PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.17/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch" +# ipu-bridge patches for Linux 6.17 +PATCH[$((++j))]="6.17/0040-ipu-bridge-makefile.patch" PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.17/0009-dkms-disable-tuner-build-in-v4l2-core.patch" +PATCH[$((++j))]="6.17/0041-ipu-bridge-bkc-backport.patch" PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.17/0062-media-v4l2-async-Fix-error-handling-on-steps-after-f.patch" +PATCH[$((++j))]="6.17/0042-ipu-bridge-add-sensor.patch" +PATCH_MATCH[$j]="^(6.1[7])" +# media-controller patches backport 6.17 +PATCH[$((++j))]="6.17/0063-media-mc-Add-INTERNAL-pad-flag.patch" PATCH_MATCH[$j]="^(6.1[7])" # V4L2 core patches for 6.18 @@ -40,59 +78,52 @@ PATCH[$((++j))]="6.18/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patc PATCH_MATCH[$j]="^(6.1[8])" PATCH[$((++j))]="6.18/0009-dkms-disable-tuner-build-in-v4l2-core.patch" PATCH_MATCH[$j]="^(6.1[8])" - -# V4L2 core patches for 7.0 -PATCH[$((++j))]="7.0/0004-dkms-v4l2-core-makefile-adaptation.patch" -PATCH_MATCH[$j]="^(7\.0)" -PATCH[$((++j))]="7.0/0005-drivers-media-set-v4l2_subdev_enable_streams_api.patch" -PATCH_MATCH[$j]="^(7\.0)" -PATCH[$((++j))]="0052-module-version-conditional-symbol-namespace.patch" -PATCH_MATCH[$j]="^(6.1[278]|7\.0)" -PATCH[$((++j))]="0053-ipu6-isys-disable-src_pad-validation-for-dkms.patch" -PATCH_MATCH[$j]="^(6.1[78])" -PATCH[$((++j))]="6.18/0054-ipu6-isys-api-compat.patch" -PATCH_MATCH[$j]="^(6.1[8])" -PATCH[$((++j))]="7.0/0055-ipu6-k7-api-compat.patch" -PATCH_MATCH[$j]="^(7\.0)" -PATCH[$((++j))]="0101-media-ipu6-isys-let-v4l2-set-default-colorspace.patch" -PATCH_MATCH[$j]="^(6.1[78]|7\.0)" - -# IPU7 drivers -PATCH[$((++j))]="0064-media-ipu7-isys-csi2-get-link-frequency-from.patch" -PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="0065-media-ipu7-get-source-pad-according-to-csi2-.patch" -PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.18/0065-media-ipu7-get-source-pad-according-to-csi2-.patch" +# ipu-bridge patches for Linux 6.18 +PATCH[$((++j))]="6.18/0040-ipu-bridge-makefile.patch" PATCH_MATCH[$j]="^(6.1[8])" -PATCH[$((++j))]="7.0/0065-media-ipu7-get-source-pad-according-to-csi2-.patch" -PATCH_MATCH[$j]="^(7\.0)" -PATCH[$((++j))]="0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch" -PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.18/0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch" +PATCH[$((++j))]="6.18/0041-ipu-bridge-bkc-backport.patch" PATCH_MATCH[$j]="^(6.1[8])" -PATCH[$((++j))]="7.0/0066-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch" -PATCH_MATCH[$j]="^(7\.0)" -PATCH[$((++j))]="0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch" -PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.18/0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch" +PATCH[$((++j))]="6.18/0042-ipu-bridge-add-sensor.patch" PATCH_MATCH[$j]="^(6.1[8])" -PATCH[$((++j))]="7.0/0100-media-ipu7-isys-let-v4l2-set-default-colorspace.patch" -PATCH_MATCH[$j]="^(7\.0)" - -POST_ADD+=" drivers/media/mc include/uapi/linux/media.h" +# media-controller patches backport 6.18 PATCH[$((++j))]="6.17/0063-media-mc-Add-INTERNAL-pad-flag.patch" -PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.18/0063-media-mc-Add-INTERNAL-pad-flag.patch" PATCH_MATCH[$j]="^(6.1[8])" -PATCH[$((++j))]="7.0/0063-media-mc-Add-INTERNAL-pad-flag.patch" -PATCH_MATCH[$j]="^(7\.0)" -PATCH[$((++j))]="0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch" -PATCH_MATCH[$j]="^(6.1[7])" -PATCH[$((++j))]="6.18/0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch" -PATCH_MATCH[$j]="^(6.1[8])" -PATCH[$((++j))]="7.0/0006-media-pci-ipu7-Add-D4XX-support-to-IPU7.patch" -PATCH_MATCH[$j]="^(7\.0)" +# IPU6 drivers OoT patches +PATCH[$((++j))]="0050-module-Add-version-conditional-for-symbol-namespace-.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0051-ipu6-isys-disable-src_pad-validation-for-dkms.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0052-ipu6-isys-kernel-6.18-api-compat.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0053-isys-video-let-v4l2-set-default-colorspace.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0054-ipu6-dkms-add-isys-makefile-adaptation.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0055-ipu6-isys-add-d4xx-pixel-format-support.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0056-Revert-ipu6-isys-lt6911uxc-2-pads-linked-to-ipu-2-po.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0057-ipu6-isys-video-force-START-then-CAPTURE-distinct-st.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" + +# IPU7 drivers OoT patches +PATCH[$((++j))]="0100-media-ipu7-ipu7-isys-csi2-get-link-frequency-from-pa.patch" +PATCH_MATCH[$j]="^(6.1[78])|^(7.[0])" +PATCH[$((++j))]="0101-media-ipu7-get-source-pad-according-to-csi2-ep-fwnod.patch" +PATCH_MATCH[$j]="^(6.1[78])|^(7.[0])" +PATCH[$((++j))]="0102-media-ipu7-Clean-csi2-fwnode-ep-when-destroying-v4l2.patch" +PATCH_MATCH[$j]="^(6.1[78])|^(7.[0])" +PATCH[$((++j))]="0103-isys-video-let-v4l2-set-default-colorspace.patch" +PATCH_MATCH[$j]="^(6.1[78])|^(7.[0])" +PATCH[$((++j))]="0104-ipu7-isys-make-modules-suffix-versioning-same-as-dkm.patch" +PATCH_MATCH[$j]="^(6.1[78])|^(7.[0])" +PATCH[$((++j))]="0105-ipu7-isys-add-d4xx-pixel-format-support.patch" +PATCH_MATCH[$j]="^(6.1[78])|^(7.[0])" +PATCH[$((++j))]="0106-isys-queue-ignore-HW_ERR_BAD_FRAME_DIM-led-expected-.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" +PATCH[$((++j))]="0107-ipu7-isys-enable-cphy-dphy-5-4-bits-vc-extension.patch" +PATCH_MATCH[$j]="^(6.1[278])|^(7.[0])" i=0 @@ -194,6 +225,12 @@ BUILT_MODULE_NAME[$((++i))]="max9296a" BUILT_MODULE_LOCATION[$i]="drivers/media/i2c/maxim-serdes" DEST_MODULE_LOCATION[$i]="/updates" STRIP[$i]=no + +BUILT_MODULE_NAME[$((++i))]="d4xx" +BUILT_MODULE_LOCATION[$i]="drivers/media/i2c" +DEST_MODULE_LOCATION[$i]="/updates" +STRIP[$i]=no + fi BUILT_MODULE_NAME[$((++i))]="intel-ipu6" @@ -211,25 +248,24 @@ BUILT_MODULE_LOCATION[$i]="ipu6-drivers/drivers/media/pci/intel/ipu6/psys" DEST_MODULE_LOCATION[$i]="/updates" STRIP[$i]=no -if [ "$KERNEL_VER" -eq 6 ] && [ "$KERNEL_PATCH" -eq 12 ]; then -POST_ADD+=" drivers/media/pci/intel/Kconfig drivers/media/pci/intel/Makefile drivers/media/pci/intel/ipu-bridge.c" -PATCH[$((++j))]="6.12/0039-ipu-bridge-port-to-bkc.patch" -PATCH_MATCH[$j]="^(6.1[2]-intel)" -PATCH[$((++j))]="6.12/0040-ipu-bridge-makefile.patch" -PATCH_MATCH[$j]="^(6.1[2])" -PATCH[$((++j))]="6.12/0041-ipu-bridge-bkc-backport.patch" -PATCH_MATCH[$j]="^(6.1[2])" -PATCH[$((++j))]="6.12/0042-ipu-bridge-add-sensor.patch" -PATCH_MATCH[$j]="^(6.1[2])" - BUILT_MODULE_NAME[$((++i))]="ipu-bridge" -BUILT_MODULE_LOCATION[$i]="6.12.0/drivers/media/pci/intel" +BUILT_MODULE_LOCATION[$i]="${SELECTED_KERNEL}/drivers/media/pci/intel" DEST_MODULE_LOCATION[$i]="/updates" STRIP[$i]=no -fi +BUILT_MODULE_NAME[$((++i))]="videodev" +BUILT_MODULE_LOCATION[$i]="${SELECTED_KERNEL}/drivers/media/v4l2-core/" +DEST_MODULE_NAME[$i]="videodev" +DEST_MODULE_LOCATION[$i]="/updates" +STRIP[$i]=no + +BUILT_MODULE_NAME[$((++i))]="mc" +BUILT_MODULE_LOCATION[$i]="${SELECTED_KERNEL}/drivers/media/mc/" +DEST_MODULE_NAME[$i]="mc" +DEST_MODULE_LOCATION[$i]="/updates" +STRIP[$i]=no -if ([ "$KERNEL_VER" -eq 6 ] && ([ "$KERNEL_PATCH" -eq 17 ] || [ "$KERNEL_PATCH" -eq 18 ])) || ([ "$KERNEL_VER" -eq 7 ] && [ "$KERNEL_PATCH" -eq 0 ]); then +if [ "$KERNEL_VER" -ge 6 ] && [ "$KERNEL_PATCH" -ge 17 ]; then # IPU7 drivers from submodule BUILT_MODULE_NAME[$((++i))]="intel-ipu7" @@ -247,87 +283,4 @@ BUILT_MODULE_LOCATION[$i]="ipu7-drivers/drivers/media/pci/intel/ipu7/psys" DEST_MODULE_LOCATION[$i]="/updates" STRIP[$i]=no -POST_ADD+=" drivers/media/pci/intel/Kconfig drivers/media/pci/intel/Makefile drivers/media/pci/intel/ipu-bridge.c" - -# Version-specific ipu-bridge patches and modules -if [ "$KERNEL_PATCH" -eq 17 ]; then - PATCH[$((++j))]="6.17/0040-ipu-bridge-makefile.patch" - PATCH_MATCH[$j]="^(6.1[7])" - PATCH[$((++j))]="6.17/0041-ipu-bridge-bkc-backport.patch" - PATCH_MATCH[$j]="^(6.1[7])" - PATCH[$((++j))]="6.17/0042-ipu-bridge-add-sensor.patch" - PATCH_MATCH[$j]="^(6.1[7])" - - BUILT_MODULE_NAME[$((++i))]="ipu-bridge" - BUILT_MODULE_LOCATION[$i]="6.17.0/drivers/media/pci/intel" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no - - BUILT_MODULE_NAME[$((++i))]="videodev" - BUILT_MODULE_LOCATION[$i]="6.17.0/drivers/media/v4l2-core/" - DEST_MODULE_NAME[$i]="videodev" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no - - BUILT_MODULE_NAME[$((++i))]="mc" - BUILT_MODULE_LOCATION[$i]="6.17.0/drivers/media/mc/" - DEST_MODULE_NAME[$i]="mc" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no -elif [ "$KERNEL_PATCH" -eq 18 ]; then - PATCH[$((++j))]="6.18/0040-ipu-bridge-makefile.patch" - PATCH_MATCH[$j]="^(6.1[8])" - PATCH[$((++j))]="6.18/0041-ipu-bridge-bkc-backport.patch" - PATCH_MATCH[$j]="^(6.1[8])" - PATCH[$((++j))]="6.18/0042-ipu-bridge-add-sensor.patch" - PATCH_MATCH[$j]="^(6.1[8])" - - BUILT_MODULE_NAME[$((++i))]="ipu-bridge" - BUILT_MODULE_LOCATION[$i]="6.18.0/drivers/media/pci/intel" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no - - BUILT_MODULE_NAME[$((++i))]="videodev" - BUILT_MODULE_LOCATION[$i]="6.18.0/drivers/media/v4l2-core/" - DEST_MODULE_NAME[$i]="videodev" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no - - BUILT_MODULE_NAME[$((++i))]="mc" - BUILT_MODULE_LOCATION[$i]="6.18.0/drivers/media/mc/" - DEST_MODULE_NAME[$i]="mc" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no -else - # Kernel 7.0 path: uses extracted 7.0.0 tree - PATCH[$((++j))]="7.0/0040-ipu-bridge-makefile.patch" - PATCH_MATCH[$j]="^(7\.0)" - PATCH[$((++j))]="7.0/0041-ipu-bridge-bkc-backport.patch" - PATCH_MATCH[$j]="^(7\.0)" - PATCH[$((++j))]="7.0/0042-ipu-bridge-add-sensor.patch" - PATCH_MATCH[$j]="^(7\.0)" - - BUILT_MODULE_NAME[$((++i))]="ipu-bridge" - BUILT_MODULE_LOCATION[$i]="7.0.0/drivers/media/pci/intel" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no - - BUILT_MODULE_NAME[$((++i))]="videodev" - BUILT_MODULE_LOCATION[$i]="7.0.0/drivers/media/v4l2-core/" - DEST_MODULE_NAME[$i]="videodev" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no - - BUILT_MODULE_NAME[$((++i))]="mc" - BUILT_MODULE_LOCATION[$i]="7.0.0/drivers/media/mc/" - DEST_MODULE_NAME[$i]="mc" - DEST_MODULE_LOCATION[$i]="/updates" - STRIP[$i]=no fi - -fi - -BUILT_MODULE_NAME[$((++i))]="d4xx" -BUILT_MODULE_LOCATION[$i]="drivers/media/i2c" -DEST_MODULE_LOCATION[$i]="/updates" -STRIP[$i]=no \ No newline at end of file From 1d5dc645af9f75c698a0bb31df41ca2bfa3332c4 Mon Sep 17 00:00:00 2001 From: florent pirou Date: Wed, 10 Jun 2026 15:22:21 +0000 Subject: [PATCH 3/3] SQUASHME: makefile: remove hardcoded kernel versioning Signed-off-by: florent pirou --- Makefile | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 67ed2bde..24c578c9 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,6 @@ subdir-ccflags-$(CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET) += -DCONFIG_VIDEO_INTEL_IPU LINUXINCLUDE := -I$(src)/include $(LINUXINCLUDE) ccflags-y := -I$(src)/include -ifneq (,$(filter 1,$(KERNEL_EQ_6_17) $(KERNEL_EQ_6_18) $(KERNEL_EQ_7_0))) # IPU7 driver configs export CONFIG_VIDEO_INTEL_IPU7=m export CONFIG_VIDEO_INTEL_IPU6=m @@ -97,43 +96,21 @@ subdir-ccflags-y += -DIPU8_INSYS_NEW_ABI subdir-ccflags-y += -DCONFIG_VIDEO_INTEL_IPU7 subdir-ccflags-y += -DCONFIG_VIDEO_INTEL_IPU6 +ifneq (,$(filter 1,$(KERNEL_EQ_6_17) $(KERNEL_EQ_6_18) $(KERNEL_EQ_7_0))) # Build IPU7 drivers from submodule obj-m += ipu7-drivers/drivers/media/pci/intel/ipu7/ +endif # Build IPU6 drivers from submodule obj-m += ipu6-drivers/drivers/media/pci/intel/ipu6/ -# Select extracted kernel tree based on running kernel -ifeq ($(KERNEL_EQ_7_0),1) -KERNEL_MEDIA_TREE := 7.0.0 -else ifeq ($(KERNEL_EQ_6_18),1) -KERNEL_MEDIA_TREE := 6.18.0 -else -KERNEL_MEDIA_TREE := 6.17.0 -endif - # Build V4L2 core module -obj-m += $(KERNEL_MEDIA_TREE)/drivers/media/v4l2-core/ -obj-m += $(KERNEL_MEDIA_TREE)/drivers/media/mc/ -LINUXINCLUDE := -I$(src)/$(KERNEL_MEDIA_TREE)/include/uapi -I$(src)/$(KERNEL_MEDIA_TREE)/include $(LINUXINCLUDE) +obj-m += $(KERNEL_VERSION)/drivers/media/v4l2-core/ +obj-m += $(KERNEL_VERSION)/drivers/media/mc/ +LINUXINCLUDE := -I$(src)/$(KERNEL_VERSION)/include/uapi -I$(src)/$(KERNEL_VERSION)/include $(LINUXINCLUDE) # Build ipu-bridge module -obj-m += $(KERNEL_MEDIA_TREE)/drivers/media/pci/intel/ - -else ifeq ($(KERNEL_EQ_6_12),1) -# IPU6 driver configs -export CONFIG_VIDEO_INTEL_IPU6=m -export CONFIG_VIDEO_INTEL_IPU6_ISYS_RESET=y - -subdir-ccflags-y += -DCONFIG_VIDEO_INTEL_IPU6 - -# Build IPU6 drivers from submodule -obj-m += ipu6-drivers/drivers/media/pci/intel/ipu6/ - -# Build ipu-bridge module -obj-m += 6.12.0/drivers/media/pci/intel/ - -endif +obj-m += $(KERNEL_VERSION)/drivers/media/pci/intel/ obj-y += drivers/media/platform/intel/ obj-m += drivers/media/i2c/