Merge pull request #418 from omacom/fix/ipu7-camera-linux-7.2-cvs

Fix Intel IPU7 camera on Linux 7.2 by adopting the CVS V4L2 bridge
This commit is contained in:
Spencer Bull authored and GitHub committed 2026-09-13 12:36:39 -05:00
commit c8799259ea
7 files changed
+300 -6

No files matched your search

@@ -0,0 +1,77 @@
From f167239b3ecf242ae081767892cb0a4c54bad496 Mon Sep 17 00:00:00 2001
From: Arun T <arun.t@intel.com>
Date: Thu, 2 Jul 2026 06:19:35 +0530
Subject: [PATCH] Enable ov08x40 CVS for support upstream cvs driver
Linux 7.2 wires the Intel CVS (Computer Vision Sensing) controller into
the IPU media graph as a bridge entity named "Intel CVS" that sits between
the sensor and the IPU CSI2 receiver (ipu-bridge commit c6b1b34b5090,
in-tree driver drivers/media/i2c/cvs). Teach MediaControl to route the
sensor -> CSI2 link through that entity when it is present, and to find
the sensor's I2C bus through it. Kernels without the entity are unaffected.
Upstream: https://github.com/intel/ipu7-camera-hal/commit/f167239b3ecf242ae081767892cb0a4c54bad496
(only the src/ part; the ipu8 config changes are not needed for ipu75xa)
---
src/v4l2/MediaControl.cpp | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/src/v4l2/MediaControl.cpp b/src/v4l2/MediaControl.cpp
index 0b2cc33..807d4f4 100644
--- a/src/v4l2/MediaControl.cpp
+++ b/src/v4l2/MediaControl.cpp
@@ -63,6 +63,7 @@ struct MediaEntity {
char devname[32];
};
+static const string icvsName = "Intel CVS";
MediaControl* MediaControl::sInstance = nullptr;
Mutex MediaControl::sLock;
@@ -983,6 +984,33 @@ int MediaControl::mediaCtlSetup(int cameraId, MediaCtlConf* mc, int width, int h
}
}
+ MediaEntity* icvs = getEntityByName(icvsName.c_str());
+ if (icvs) {
+ for (uint32_t i = 0; i < icvs->numLinks; ++i) {
+ if (icvs->links[i].sink->entity == icvs) {
+ MediaEntity* sensor = icvs->links[i].source->entity;
+ int sensor_entity_id = sensor->info.id;
+ LOG1("@%s, found %s -> %s", __func__, sensor->info.name, icvsName.c_str());
+ for (McLink& link : mc->links) {
+ if (link.srcEntity == sensor_entity_id && link.sinkEntity != static_cast<int>(icvs->info.id)) {
+ LOG1("@%s, skip %s, link %s -> %s", __func__, link.srcEntityName.c_str(),
+ icvsName.c_str(), link.sinkEntityName.c_str());
+ link.srcEntity = icvs->info.id;
+ link.srcEntityName = icvsName;
+ for (uint32_t j = 0; j < icvs->info.pads; ++j) {
+ if (icvs->pads[j].flags & MEDIA_PAD_FL_SOURCE) {
+ link.srcPad = j;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
/* Set link in format Configuration */
ret = setMediaMcLink(mc->links);
CheckAndLogError(ret != OK, ret, "set MediaCtlConf McLink failed: ret = %d", ret);
@@ -1127,6 +1155,9 @@ int MediaControl::getI2CBusAddress(const string& sensorEntityName, const string&
for (int i = 0; i < linksCount; i++) {
if (strcmp(links[i].sink->entity->info.name, sinkEntityName.c_str()) == 0) {
entityName = entity.info.name;
+ if (strcmp(entityName, icvsName.c_str()) == 0) {
+ return getI2CBusAddress(sensorEntityName, icvsName, i2cBus);
+ }
break;
}
}
--
2.55.0
@@ -0,0 +1,32 @@
From: Spencer Bull <spencer@omarchy.org>
Subject: [PATCH] ipu75xa: set Intel CVS pad formats for ov08x40
On Linux 7.2 the "Intel CVS" bridge entity sits between ov08x40 and the
IPU7 CSI2 receiver. Its sink pad format must be set to the sensor format
(the source pad mirrors the sink) or link validation fails at stream-on.
Mirrors the upstream ipu8 change in ipu7-camera-hal commit f167239b3ecf.
Only formats are added; links stay sensor -> CSI2 in the config because
MediaControl rewrites them through the bridge at runtime, so this config
also keeps working on kernels without the CVS entity (a format entry for
a missing entity is logged and skipped).
---
diff --git i/config/linux/ipu75xa/sensors/ov08x40-uf.json w/config/linux/ipu75xa/sensors/ov08x40-uf.json
index ff31df5..483bf1d 100644
--- i/config/linux/ipu75xa/sensors/ov08x40-uf.json
+++ w/config/linux/ipu75xa/sensors/ov08x40-uf.json
@@ -31,6 +31,14 @@
"name": "ov08x40 $I2CBUS", "pad": 0, "width": 3856, "height": 2176,
"format": "V4L2_MBUS_FMT_SGRBG10_1X10"
},
+ {
+ "name": "Intel CVS", "pad": 0, "width": 3856, "height": 2176,
+ "format": "V4L2_MBUS_FMT_SGRBG10_1X10"
+ },
+ {
+ "name": "Intel CVS", "pad": 1, "width": 3856, "height": 2176,
+ "format": "V4L2_MBUS_FMT_SGRBG10_1X10"
+ },
{
"name": "Intel IPU7 CSI2 $CSI_PORT", "pad": 0, "width": 3856, "height": 2176,
"format": "V4L2_MBUS_FMT_SGRBG10_1X10"
@@ -0,0 +1,83 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Junjie Cao <junjie.cao@intel.com>
Date: Tue, 08 Sep 2026 18:57:17 +0800
Subject: [PATCH] media: i2c: cvs: Get the wake IRQ without claiming the GPIO
Message-ID: <20260908105717.496232-1-junjie.cao@intel.com>
Link: https://patchwork.linuxtv.org/project/linux-media/patch/20260908105717.496232-1-junjie.cao@intel.com/
The wake line is only used as an IRQ source, yet the driver requests
it with devm_gpiod_get() before the I2C handshake. Where ipu-bridge
does not expose the CSI endpoints, CSI init returns -EPROBE_DEFER and
every retry claims the line again for the length of the handshake.
On the Dell XPS 14 DA14260 (Panther Lake) the four CS35L57 amplifiers
read their speaker ID from one GpioIo (DSDT decoded in the second
link):
GpioIo (Shared, PullNone, 0, 0, IoRestrictionInputOnly,
"\_SB.GPI1", 0, ResourceConsumer,,) {20}
A request that lands while another consumer holds the line fails, and
cs35l56 does not retry:
cs35l56 sdw:0:2:01fa:3557:01:2: error -EBUSY: Failed to get spk-id-gpios
All four fail on Fedora 7.1.13, the first Fedora 7.1 kernel with the
driver enabled; the same board on 7.1.12 without it creates the card.
The second link shows the same failure on openSUSE 7.2.2, whose
config also enables the driver.
The INTC10E1 _CRS of this machine has not been decoded. The vendor
driver in intel/vision-drivers requests req, resp and rst the same
way but maps wake to an IRQ with acpi_dev_gpio_irq_get_by() without
requesting it, and on another DA14260 (board 0VRKYR, BIOS 1.8.2) a
build of it is bound while the amplifiers probe. The wake entry is
the line that differs.
Take the IRQ from the GpioInt entry the same way, as the I2C core
does for client->irq; this also applies the trigger type from _CRS.
The driver binds as a platform device too, hence the explicit lookup.
Fixes: 8e2b43d2c10b ("media: i2c: cvs: Add driver of Intel Computer Vision Sensing Controller(CVS)")
Cc: stable@vger.kernel.org
Link: https://bugzilla.redhat.com/show_bug.cgi?id=2529031
Link: https://github.com/thesofproject/sof/issues/11152
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
---
drivers/media/i2c/cvs/core.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/drivers/media/i2c/cvs/core.c b/drivers/media/i2c/cvs/core.c
index d4a3b9c3bab1e..8d857bbd8ab51 100644
--- a/drivers/media/i2c/cvs/core.c
+++ b/drivers/media/i2c/cvs/core.c
@@ -725,8 +725,6 @@ static int cvs_core_probe(struct device *dev, struct i2c_client *i2c)
}
if (ctx->res == ICVS_FULLCAP) {
- struct gpio_desc *wake;
-
ctx->rst = devm_gpiod_get(dev, "rst", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->rst)) {
ret = dev_err_probe(dev, PTR_ERR(ctx->rst),
@@ -734,14 +732,12 @@ static int cvs_core_probe(struct device *dev, struct i2c_client *i2c)
goto err_put_ipu;
}
- wake = devm_gpiod_get(dev, "wake", GPIOD_IN);
- if (IS_ERR(wake)) {
- ret = dev_err_probe(dev, PTR_ERR(wake),
- "failed to get wake GPIO\n");
- goto err_put_ipu;
- }
-
- ctx->irq = gpiod_to_irq(wake);
+ /*
+ * Do not request the line: another device's _CRS may list
+ * the same pin, and its driver would then fail with -EBUSY.
+ */
+ ctx->irq = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev),
+ "wake", 0);
if (ctx->irq < 0) {
ret = dev_err_probe(dev, ctx->irq,
"failed to get wake IRQ\n");
+59 -6
View File
@@ -1,8 +1,8 @@
# Maintainer: Omarchy <packages@omarchy.org>
pkgname=intel-ipu7-camera
pkgver=1.0.5
pkgrel=2
pkgver=1.0.6
pkgrel=1
pkgdesc="Intel IPU7 MIPI camera stack for Hurrican/Performance (OV08X40 + hardware ISP)"
arch=('x86_64')
url="https://github.com/TsaiGaggery/hurrican_omarchy_enabling"
@@ -37,16 +37,42 @@ _ipu7_camera_bins_commit="403c67db6b279dd02752f11db6a34552f31a3ac5"
_ipu7_camera_hal_commit="b1f6ebef12111fb5da0133b144d69dd9b001836c"
_icamerasrc_commit="4fb31db76b618aae72184c59314b839dedb42689"
# Linux 7.2 moved the Intel CVS (Computer Vision Sensing) controller into the
# IPU media graph: ipu-bridge now places it between the sensor and the IPU
# CSI2 receiver as an "Intel CVS" V4L2 bridge sub-device, provided by the
# in-tree drivers/media/i2c/cvs driver. The legacy vision-drivers misc driver
# has no such sub-device, so on 7.2 the sensor never joins the graph and the
# HAL finds no camera. We ship the in-tree driver as a DKMS module
# for 7.2+ kernels (Arch-derived kernel configs cannot enable it: the option
# is hidden behind MEDIA_HIDE_ANCILLARY_SUBDRV) and keep vision-drivers for
# older kernels. Both dkms.conf files carry matching BUILD_EXCLUSIVE_KERNEL.
#
# 0007 is the upstream fix for the audio regression on the Dell XPS 14
# DA14260: the driver requested its "wake" GPIO, which shares a pin with the
# CS35L57 amplifiers' speaker-ID GpioIo, so every cs35l56 probe failed with
# -EBUSY and the sound card never appeared. Drop it once the stable tag
# fetched below contains the fix.
_intel_cvs_kernel_tag="v7.2.5"
_intel_cvs_url="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/drivers/media/i2c/cvs"
source=(
"ipu7-drivers::git+https://github.com/intel/ipu7-drivers.git#commit=${_ipu7_drivers_commit}"
"vision-drivers::git+https://github.com/intel/vision-drivers.git#commit=${_vision_drivers_commit}"
"ipu7-camera-bins::git+https://github.com/intel/ipu7-camera-bins.git#commit=${_ipu7_camera_bins_commit}"
"ipu7-camera-hal::git+https://github.com/intel/ipu7-camera-hal.git#commit=${_ipu7_camera_hal_commit}"
"icamerasrc::git+https://github.com/intel/icamerasrc.git#commit=${_icamerasrc_commit}"
"intel-cvs-core.c::${_intel_cvs_url}/core.c?h=${_intel_cvs_kernel_tag}"
"intel-cvs-v4l2.c::${_intel_cvs_url}/v4l2.c?h=${_intel_cvs_kernel_tag}"
"intel-cvs-icvs.h::${_intel_cvs_url}/icvs.h?h=${_intel_cvs_kernel_tag}"
"0004-ipu7-psys-register-device-bus.patch"
"0003-icvs-set-rgbcamera_pwrup_host-0-for-Panther-Lake.patch"
"0005-camhal-MediaControl-route-through-Intel-CVS-bridge.patch"
"0006-camhal-ipu75xa-ov08x40-Intel-CVS-formats.patch"
"0007-media-i2c-cvs-get-the-wake-irq-without-claiming-the-gpio.patch"
"dkms-ipu7-drivers.conf"
"dkms-vision-drivers.conf"
"dkms-intel-cvs.conf"
"intel-cvs-Makefile"
"camera-deps.conf"
"v4l2loopback-modprobe.conf"
"camera-init.service"
@@ -62,10 +88,14 @@ source=(
"v4l2-relayd-ipu7-override.conf"
)
sha256sums=(
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
'b4a90ad1815c02e4cadc1b5ad6c576ae0b150cb365c68d2c934cf964a995d91f'
'e988014f54b1b5183e9ef43b602d73bbc2c991f19a8d503560a8cdba112b76c6'
'6dcd5201fb78766a440038c8eba2cc8c3892064ba829065e2269c30dc1905983'
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
'SKIP' 'SKIP' 'SKIP'
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP'
'SKIP'
)
prepare() {
@@ -79,6 +109,20 @@ prepare() {
git am "${srcdir}/0003-icvs-set-rgbcamera_pwrup_host-0-for-Panther-Lake.patch"
fi
# Route the media graph through the Linux 7.2 "Intel CVS" bridge entity
cd "${srcdir}/ipu7-camera-hal"
patch -Np1 -i "${srcdir}/0005-camhal-MediaControl-route-through-Intel-CVS-bridge.patch"
patch -Np1 -i "${srcdir}/0006-camhal-ipu75xa-ov08x40-Intel-CVS-formats.patch"
# Intel CVS: take the wake IRQ without claiming the GPIO (shared with the
# speaker-ID line on the XPS 14). makepkg symlinks plain downloads into
# srcdir and patch refuses to touch a symlink, so patch a real copy. The
# patch is against a/drivers/media/i2c/cvs/core.c, hence -p5.
cp --remove-destination "$(readlink -f "${srcdir}/intel-cvs-core.c")" \
"${srcdir}/intel-cvs-core.c"
patch -p5 -F0 --no-backup-if-mismatch "${srcdir}/intel-cvs-core.c" \
< "${srcdir}/0007-media-i2c-cvs-get-the-wake-irq-without-claiming-the-gpio.patch"
# Stage proprietary libs/headers for build-time use
local staging="${srcdir}/staging"
rm -rf "${staging}"
@@ -145,13 +189,22 @@ package() {
install -Dm644 "${srcdir}/dkms-ipu7-drivers.conf" "${ipu7_dkms_dir}/dkms.conf"
sed -i "s/@PKGVER@/${pkgver}/" "${ipu7_dkms_dir}/dkms.conf"
# DKMS: Vision drivers (CVS)
# DKMS: legacy Vision drivers (CVS misc driver), kernels before 7.2
local cvs_dkms_dir="${pkgdir}/usr/src/vision-drivers-${pkgver}"
install -dm755 "${cvs_dkms_dir}"
cp -r "${srcdir}/vision-drivers/"* "${cvs_dkms_dir}/"
install -Dm644 "${srcdir}/dkms-vision-drivers.conf" "${cvs_dkms_dir}/dkms.conf"
sed -i "s/@PKGVER@/${pkgver}/" "${cvs_dkms_dir}/dkms.conf"
# DKMS: in-tree Linux 7.2 Intel CVS V4L2 bridge driver, kernels 7.2+
local icvs_dkms_dir="${pkgdir}/usr/src/intel-cvs-${pkgver}"
install -Dm644 "${srcdir}/intel-cvs-core.c" "${icvs_dkms_dir}/core.c"
install -Dm644 "${srcdir}/intel-cvs-v4l2.c" "${icvs_dkms_dir}/v4l2.c"
install -Dm644 "${srcdir}/intel-cvs-icvs.h" "${icvs_dkms_dir}/icvs.h"
install -Dm644 "${srcdir}/intel-cvs-Makefile" "${icvs_dkms_dir}/Makefile"
install -Dm644 "${srcdir}/dkms-intel-cvs.conf" "${icvs_dkms_dir}/dkms.conf"
sed -i "s/@PKGVER@/${pkgver}/" "${icvs_dkms_dir}/dkms.conf"
# Firmware
install -dm755 "${pkgdir}/usr/lib/firmware/intel/ipu"
install -Dm644 "${srcdir}/ipu7-camera-bins/lib/firmware/intel/ipu/"*.bin \
@@ -0,0 +1,26 @@
# Intel CVS (Computer Vision Sensing) CSI-2 bridge driver.
#
# Copy of the in-tree Linux 7.2 driver (drivers/media/i2c/cvs) plus the
# upstream wake-IRQ fix carried by the PKGBUILD, built out of tree so it
# exists on every 7.2+ kernel regardless of the kernel's Kconfig.
# Arch-derived configs cannot enable VIDEO_INTEL_CVS at all: it lives under
# the "Miscellaneous helper chips" menu, which is hidden by
# MEDIA_HIDE_ANCILLARY_SUBDRV unless CONFIG_EXPERT is set.
#
# 7.2's ipu-bridge inserts the CVS device between the sensor and the IPU
# CSI2 receiver, so the IPU only sees the sensor once a driver registers
# this V4L2 bridge sub-device. Kernels before 7.2 keep using the legacy
# misc driver from vision-drivers (see dkms-vision-drivers.conf).
PACKAGE_NAME="intel-cvs"
PACKAGE_VERSION="@PKGVER@"
AUTOINSTALL="yes"
# 7.2 and later only (regex, so the pacman dkms hook also honours it)
BUILD_EXCLUSIVE_KERNEL="^(7\.([2-9]|[1-9][0-9]+)\.|([8-9]|[1-9][0-9]+)\.)"
BUILT_MODULE_NAME[0]="intel_cvs"
BUILT_MODULE_LOCATION[0]=""
DEST_MODULE_LOCATION[0]="/updates"
MAKE[0]="make KERNEL_SRC=${kernel_source_dir}"
CLEAN="make KERNEL_SRC=${kernel_source_dir} clean"
@@ -1,7 +1,15 @@
# Legacy Intel CVS misc driver (no V4L2 bridge). Only for kernels before
# 7.2: from 7.2 on, ipu-bridge routes the sensor through a CVS V4L2 bridge
# sub-device, which this driver does not provide, and it would displace the
# in-tree intel_cvs module of the same name. 7.2+ kernels use intel-cvs
# (see dkms-intel-cvs.conf) instead.
PACKAGE_NAME="vision-drivers"
PACKAGE_VERSION="@PKGVER@"
AUTOINSTALL="yes"
# Before 7.2 only (regex, so the pacman dkms hook also honours it)
BUILD_EXCLUSIVE_KERNEL="^([0-6]\.|7\.[01]\.)"
BUILT_MODULE_NAME[0]="intel_cvs"
BUILT_MODULE_LOCATION[0]=""
DEST_MODULE_LOCATION[0]="/updates"
@@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-only
# Out-of-tree build of the in-tree Linux 7.2 Intel CVS driver
# (drivers/media/i2c/cvs). Sources are kernel files plus the upstream
# wake-IRQ fix carried by the PKGBUILD.
KERNELRELEASE ?= $(shell uname -r)
KERNEL_SRC ?= /lib/modules/$(KERNELRELEASE)/build
obj-m := intel_cvs.o
intel_cvs-y := core.o v4l2.o
all:
$(MAKE) -C $(KERNEL_SRC) M=$(CURDIR) modules
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(CURDIR) clean