IRQ-only ACPI lookup changes the first CS35L57 speaker ID on Dell XPS 16 DA16260
We traced a reproducible GPIO descriptor polarity leak that changes amplifier firmware/preset selection with boot order. This is being reported here because the demonstrated consequence is incorrect/inconsistent speaker-ID reads on supported SOF/SoundWire hardware; the apparent repair belongs in GPIO/ACPI core, rather than SOF DSP firmware. Please help route it to the relevant maintainers if a different tracker is preferred.
Hardware/software: Dell XPS 16 DA16260, board 0H2HX9, BIOS 1.9.0, subsystem 1028:0DBA; four CS35L57 Rev B2 amps; Omarchy/Arch linux-ptl 7.2.3.arch1-1 (7.2.3-arch1-1-ptl), SOF 2.14.1.1, amplifier firmware 4.5.9. The matched base source is Arch commit ca40b66e4eff7d3c69be5416a322067a63a01a80; retained package patches concern display. No GPIO source changes were made for the trace.
Shared resources and reproducible consequence
ACPI exposes \\_SB.GPI1, offset 20 (runtime INTC10BC:01 / GPP_F_20) as:
- active-high, shared, input-only GpioIo for the four
spk-id-gpios consumers;
- active-low wake GpioInt for INTC10E1/CVSS camera enumeration.
With audio initialized first, all four physical and logical reads are 0. With audio deliberately deferred until camera enumeration/initialization, all physical reads are still 0, but the first amp returns logical 1 and the other three return 0. Firmware request names track those IDs. This is not evidence that ID0 or ID1 correctly identifies every physical speaker supplier.
Trace sequence (monotonic seconds)
Read-only early kprobes and GPIO tracepoints captured the same underlying descriptor through this sequence:
| Time |
Event |
State/result |
| 13.523527–13.523558 |
I2C core i2c_acpi_get_irq() → acpi_dev_gpio_irq_wake_get_by() → gpiod_configure_flags() |
Descriptor flags 0 → 0x40: ACTIVE_LOW set without a GPIO request/free lifetime |
| 13.529075–13.529097 |
Vendor cvs_common_probe() repeats IRQ-only wake lookup |
ACTIVE_LOW remains set |
| 15.279663–15.279695 |
First amp, link2/unit2, requests spk-id |
0x640 → 0x641; stale polarity survives successful request |
| 15.279697–15.279743 |
Amp active-high input configuration |
Lookup lflags=0x40 means GPIO_PULL_DISABLE, not ACTIVE_LOW; descriptor becomes 0x8641 and retains ACTIVE_LOW |
| 15.279744–15.279752 |
Read |
GPIO tracepoint raw 0; consumer logical result 1 |
| 15.279753–15.279755 |
Free |
0x8641 → 0x600; ACTIVE_LOW clears |
| 15.292520 / 15.307241 / 15.318463 |
Remaining amps read the same descriptor |
Each raw 0, logical 0 |
The trace contains 74 retained events, zero missed kretprobes, zero per-CPU dropped/overrun events, and no event-pairing errors. Raw traces, ACPI extraction, input hashes, matched source, and independent agent analysis are retained for targeted follow-up; full machine logs have not been uploaded.
Source mechanism and proposed repair direction
At the matched source revision:
acpi_dev_gpio_irq_wake_get_by() derives logical ACTIVE_LOW from GpioInt and calls gpiod_configure_flags() while obtaining an IRQ, without a GPIO acquisition lifetime.
gpiod_request_commit() does not reset this polarity. gpiod_configure_flags() sets ACTIVE_LOW when requested but does not clear it for an active-high consumer.
cs35l56_get_speaker_id() uses the normal logical GPIO API and releases the input; free clears polarity, explaining the first-consumer-only result.
Expected behavior: an IRQ-number lookup should preserve an independent GpioIo consumer’s logical polarity. A repair should separate IRQ-only physical configuration from logical consumer polarity while retaining direction, bias, debounce, IRQ trigger and wake behavior. It needs regression coverage for both lookup orders and an already-owned active-low input. No general repair has been implemented or validated yet. Unconditionally clearing polarity or changing all CS35L56/57 ID reads to raw values would not be a justified generic fix.
The first setter is I2C enumeration, before CVS; removing only the explicit CVS lookup will not fix this trace. The installed vendor CVS driver already uses IRQ-only wake acquisition, so the recent CVS GPIO-ownership correction does not eliminate this polarity side effect.
Separate audio observations
Right-heavy playback persisted with either boot order and after a verified factory FG left-woofer coefficient override. Therefore this polarity defect is not established as the cause of that imbalance. Aggregate DAI trigger sequencing in PR #5924 separately produced balanced centering in two initialized patched boots, with a baseline reversal and documented profile/volume qualifications. One other boot failed amp GPIO acquisition with -EBUSY; its failure-time owner is unknown and that is not proof of this polarity mechanism.
Attribution: Codex using Astra Ultra performed the programmatic investigation and prepared this post on the account owner’s behalf. Listening observations were supplied by the laptop owner; automated digital checks are not presented as acoustic measurements.
IRQ-only ACPI lookup changes the first CS35L57 speaker ID on Dell XPS 16 DA16260
We traced a reproducible GPIO descriptor polarity leak that changes amplifier firmware/preset selection with boot order. This is being reported here because the demonstrated consequence is incorrect/inconsistent speaker-ID reads on supported SOF/SoundWire hardware; the apparent repair belongs in GPIO/ACPI core, rather than SOF DSP firmware. Please help route it to the relevant maintainers if a different tracker is preferred.
Hardware/software: Dell XPS 16 DA16260, board 0H2HX9, BIOS 1.9.0, subsystem 1028:0DBA; four CS35L57 Rev B2 amps; Omarchy/Arch
linux-ptl 7.2.3.arch1-1(7.2.3-arch1-1-ptl), SOF 2.14.1.1, amplifier firmware 4.5.9. The matched base source is Arch commitca40b66e4eff7d3c69be5416a322067a63a01a80; retained package patches concern display. No GPIO source changes were made for the trace.Shared resources and reproducible consequence
ACPI exposes
\\_SB.GPI1, offset 20 (runtime INTC10BC:01 / GPP_F_20) as:spk-id-gpiosconsumers;With audio initialized first, all four physical and logical reads are 0. With audio deliberately deferred until camera enumeration/initialization, all physical reads are still 0, but the first amp returns logical 1 and the other three return 0. Firmware request names track those IDs. This is not evidence that ID0 or ID1 correctly identifies every physical speaker supplier.
Trace sequence (monotonic seconds)
Read-only early kprobes and GPIO tracepoints captured the same underlying descriptor through this sequence:
i2c_acpi_get_irq()→acpi_dev_gpio_irq_wake_get_by()→gpiod_configure_flags()cvs_common_probe()repeats IRQ-only wake lookupspk-idlflags=0x40means GPIO_PULL_DISABLE, not ACTIVE_LOW; descriptor becomes 0x8641 and retains ACTIVE_LOWThe trace contains 74 retained events, zero missed kretprobes, zero per-CPU dropped/overrun events, and no event-pairing errors. Raw traces, ACPI extraction, input hashes, matched source, and independent agent analysis are retained for targeted follow-up; full machine logs have not been uploaded.
Source mechanism and proposed repair direction
At the matched source revision:
acpi_dev_gpio_irq_wake_get_by()derives logical ACTIVE_LOW from GpioInt and callsgpiod_configure_flags()while obtaining an IRQ, without a GPIO acquisition lifetime.gpiod_request_commit()does not reset this polarity.gpiod_configure_flags()sets ACTIVE_LOW when requested but does not clear it for an active-high consumer.cs35l56_get_speaker_id()uses the normal logical GPIO API and releases the input; free clears polarity, explaining the first-consumer-only result.Expected behavior: an IRQ-number lookup should preserve an independent GpioIo consumer’s logical polarity. A repair should separate IRQ-only physical configuration from logical consumer polarity while retaining direction, bias, debounce, IRQ trigger and wake behavior. It needs regression coverage for both lookup orders and an already-owned active-low input. No general repair has been implemented or validated yet. Unconditionally clearing polarity or changing all CS35L56/57 ID reads to raw values would not be a justified generic fix.
The first setter is I2C enumeration, before CVS; removing only the explicit CVS lookup will not fix this trace. The installed vendor CVS driver already uses IRQ-only wake acquisition, so the recent CVS GPIO-ownership correction does not eliminate this polarity side effect.
Separate audio observations
Right-heavy playback persisted with either boot order and after a verified factory FG left-woofer coefficient override. Therefore this polarity defect is not established as the cause of that imbalance. Aggregate DAI trigger sequencing in PR #5924 separately produced balanced centering in two initialized patched boots, with a baseline reversal and documented profile/volume qualifications. One other boot failed amp GPIO acquisition with -EBUSY; its failure-time owner is unknown and that is not proof of this polarity mechanism.
Attribution: Codex using Astra Ultra performed the programmatic investigation and prepared this post on the account owner’s behalf. Listening observations were supplied by the laptop owner; automated digital checks are not presented as acoustic measurements.