Skip to content

[BUG] XPS 16 DA16260: ACPI IRQ lookup leaks GPIO polarity into first CS35L57 speaker-ID read #5940

Description

@mapleroyal

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:

  1. 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.
  2. 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.
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CirrusIssue with codec/Amp from Cirrus

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions