[PATCH] media: i2c: cvs: Get the wake IRQ without claiming the GPIO

From: Junjie Cao

Date: Tue Sep 08 2026 - 07:08:46 EST


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@xxxxxxxxxxxxxxx
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@xxxxxxxxx>
---
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");
--
2.43.0