Skip to content

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

Open

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

  1. ujfalusi commented on Sep 14, 2026

    @ujfalusi
    Collaborator

    @thesofproject/cirrus , can you take a look?

  2. charleskeepax commented on Sep 14, 2026

    @charleskeepax

    @mapleroyal Could you please describe the problem you actually have? I see a lot of description but very little actual explanation of the problems you are experiencing. Is it that you have unbalanced audio between the left and right channels?

  3. mapleroyal commented on Sep 14, 2026

    @mapleroyal
    Author

    @mapleroyal Could you please describe the problem you actually have? I see a lot of description but very little actual explanation of the problems you are experiencing. Is it that you have unbalanced audio between the left and right channels?

    Yes, unbalanced (strongly right heavy) exactly the same way on two identical 2026 XPS 16 machines.

  4. charleskeepax commented on Sep 14, 2026

    @charleskeepax

    Could you attach a dmesg just after boot so I can have a quick check and see if it looks like the amps booted correctly?

  5. mapleroyal commented on Sep 14, 2026

    @mapleroyal
    Author

    @charleskeepax Here are the full early-boot kernel logs, with downloadable text files:

    These are preserved journalctl -k -b -o short-monotonic captures from shortly after the September 13 evening test boots (September 14 UTC), rather than direct dmesg output or a fresh reboot today. Both include the initial kernel messages and full amp initialization. Ordinary music had already been played before collection; these are not strictly pre-playback captures.

    Both run 7.2.3-arch1-1-ptl using our diagnostic boot entries: rebuilt baseline SOF common module versus the adapted #5924 sequencing patch. Neither has a GPIO-core fix. The baseline selects spkid0 for all four amps; the patched boot selects spkid1 for link2/unit2 and spkid0 for the other three. Both logs contain firmware v4.5.9 and “Calibration applied” messages for all four amps. The differing presets are a qualification to this comparison, not an isolated test of the GPIO issue.

    No log lines were removed. Privacy substitutions are marked; firmware filenames, tuning IDs, GPIO messages, warnings and taints remain. Details are in the linked README.

    Prepared and uploaded by Codex using Astra Ultra, on my behalf; listening reports are mine.

  6. charleskeepax commented on Sep 14, 2026

    @charleskeepax

    Well certainly it appears to be loading different tuning in each log, interesting that the one that loads mismatch tunings is the one that sounds better. Our understanding here was that the spkid should match on both sides.

    Could you share a copy of the change that gets you from one state to the other?
    Also could you attach an ACPI dump from your machine?

  7. simontrimmer commented on Sep 14, 2026

    @simontrimmer
    Collaborator

    Also, could you check whether you are running the latest available BIOS for your system? I may be reading your SKU wrong but https://www.dell.com/support/product-details/en-uk/product/xps-da16260-laptop/drivers?driverid=V9F7P&driveros=w2021&ld=V9F7P

    (^ grab the acpi dump for Charles before updating it please! Bonus points for updating it and then grabbing another)

  8. mapleroyal commented on Sep 15, 2026

    @mapleroyal
    Author

    @charleskeepax The patch improved the left/right volume balance on the replacement laptop. The speakers still have a different tone: the left sounds more “eee,” the right more “ooo.” I heard that tone difference on both XPS units. It may be a tuning issue, but the strong right-heavy balance was the problem we were focusing on.

    Here is the exact patch, adapted from #5924. It changes SOF stream start/stop ordering; it does not change tuning files or speaker-ID logic. The different tuning selections happened across reboots, rather than being an intentional part of the patch. We are not claiming the mismatched IDs are correct.

    Here is the ACPI dump from BIOS 1.9.0, captured today before updating. Only the Windows product-key table has been omitted.

    Posted with help from Codex/Astra Ultra; listening observations are mine.

  9. mapleroyal commented on Sep 15, 2026

    @mapleroyal
    Author

    @simontrimmer You're right—we're still on 1.9.0. The Dell release you linked is 1.11.0, released September 9.

    We've saved the ACPI dump before updating. We plan to update to 1.11.0, then post a new dump and report whether the audio changes.

  10. mapleroyal commented on Sep 15, 2026

    @mapleroyal
    Author

    @charleskeepax @simontrimmer BIOS 1.11.0 is now installed. Audio still sounds centered with the same patched kernel (7.2.3-arch1-1-ptl-audio), and all four amps initialized successfully.

    The speaker-ID GPIO definitions and selected speaker IDs are unchanged after the update.

    Both dumps omit only the Windows product-key table (MSDM).

    Prepared and posted with Codex (Astra Ultra); the listening result is mine.

  11. charleskeepax commented on Sep 18, 2026

    @charleskeepax

    Hi, still investigating here, a couple extra bits of debug that would also be useful:

    Could you grab the output of "cat /sys/kernel/debug/gpio"?

    Could you get into the state where the audio is unbalanced. Then play a 500Hz tone with the balance set all the way to the left and then to the right. Then play a 7000Hz tone with the balance set all the way to each side. Do you clearly hear all the tones or is one of the four missing?

  12. mapleroyal commented on Sep 18, 2026

    @mapleroyal
    Author

    I've already done this experiment so I won't repeat it, but all tones across the full range are audible.

    The left sounds more "vvv" or "eee" vs the right sounding more "ooo" or "mmm" given the same exact tone or white/pink/brown noise.

    Left is quieter on lower tones, and as the tones get higher they both begin to sound more similarly loud. But they never sound similarly "tuned"—I always get the eee/vvv characteristic on the left side, which I would describe as "shallow" vs the ooo/mmm characteristic on the right side which I would describe as "full".

    This is the output of your command, on the newest omarchy kernel (came out yesterday or the day before) with the fix applied that causes things to load in the correct order so the left and right speakers play at the same volume:

    ~ ✗ sudo cat /sys/kernel/debug/gpio
    [sudo] password for user1:
    gpiochip0: 48 GPIOs, parent: platform/INTC10BC:00, INTC10BC:00:
    
    gpiochip1: 51 GPIOs, parent: platform/INTC10BC:01, INTC10BC:01:
     gpio-20  (                    |interrupt           ) in  lo IRQ
     gpio-36  (                    |rst                 ) out hi
    
    gpiochip2: 85 GPIOs, parent: platform/INTC10BC:02, INTC10BC:02:
     gpio-55  (                    |ir_flood            ) out lo
    
    gpiochip3: 8 GPIOs, parent: platform/INTC10BC:03, INTC10BC:03:
    
    gpiochip4: 72 GPIOs, parent: platform/INTC10BC:04, INTC10BC:04:
    
    gpiochip5: 64 GPIOs, parent: auxiliary/usbio.usbio-gpio.0, INTC10E2:00, can sleep:
     gpio-0   (                    |req                 ) out ?
     gpio-1   (                    |dvdd                ) out ?
     gpio-2   (                    |privacy             ) out ?
     gpio-4   (                    |reset               ) out ?   ACTIVE LOW
     gpio-5   (                    |clk-enable          ) out ?
     gpio-7   (                    |resp                ) in  hi
     gpio-10  (                    |avdd                ) out ?
    

    I'm out of Astra usage until monday so I'm restricted to dumb models until then. Since I don't trust the dumber models to manage my machine, I won't be able to do any complex stuff until monday.

  13. charleskeepax commented on Sep 22, 2026

    @charleskeepax

    Apologies for the delay we are still investigating here, we think there might be an issue with the GPIO specified in the ACPI for the speaker ID. Could you try the following steps and report the output (probably needs to be done as root/sudo-ed):

    Check GPP_E_20 is on pin 46:
    cat /sys/kernel/debug/pinctrl/INTC10BC:01/pins

    Check chip1 is INTC10BC:01:
    cat /sys/class/gpio/chip1/label

    Export GPIO:
    echo 46 > /sys/class/gpio/chip1/export

    Check value:
    cat /sys/class/gpio/chip1/gpio46/value

  14. mapleroyal commented on Sep 22, 2026

    @mapleroyal
    Author

    @charleskeepax This is from Astra Ultra. Let me know if it isn't what you need:

    Confirmed: GPP_E_20 is pin 46 on INTC10BC:01, and it reads 1. This is on BIOS 1.11.0 and kernel 7.2.5-3.1-omarchy-audio, with our existing SOF sequencing fix.

    This kernel has CONFIG_GPIO_SYSFS disabled, so the /sys/class/gpio/... paths aren't available. I used the GPIO character-device interface to check the label and read the same pin. It was already an unused GPIO input; the temporary request was released afterward, and its configuration was unchanged.

    Command output
    $ uname -r
    7.2.5-3.1-omarchy-audio
    
    $ cat /sys/class/dmi/id/bios_version
    1.11.0
    
    $ rg 'CONFIG_GPIO_SYSFS|CONFIG_GPIO_CDEV' /usr/lib/modules/7.2.5-3.1-omarchy-audio/build/.config
    # CONFIG_GPIO_SYSFS is not set
    CONFIG_GPIO_CDEV=y
    CONFIG_GPIO_CDEV_V1=y
    
    Contents of /sys/kernel/debug/pinctrl/INTC10BC:01/pins (requested listing):
    registered pins: 51
    pin 0 (GPP_F_0) 0:INTC10BC:01 mode 1 0x44000700 0x0003c042 0x00000000 [ACPI]
    pin 1 (GPP_F_1) 1:INTC10BC:01 mode 1 0x44000700 0x0003f043 0x00000000 [ACPI]
    pin 2 (GPP_F_2) 2:INTC10BC:01 mode 1 0x44000700 0x0003c044 0x00000000 [ACPI]
    pin 3 (GPP_F_3) 3:INTC10BC:01 mode 1 0x44000700 0x0003f045 0x00000000 [ACPI]
    pin 4 (GPP_F_4) 4:INTC10BC:01 mode 1 0x44000700 0x0003c046 0x00000000 [ACPI]
    pin 5 (GPP_F_5) 5:INTC10BC:01 mode 3 0x44000f00 0x0003c047 0x00000000 [ACPI]
    pin 6 (GPP_F_6) 6:INTC10BC:01 GPIO 0x44000300 0x00000048 0x00000000
    pin 7 (GPP_F_7) 7:INTC10BC:01 GPIO 0x44000300 0x0003c049 0x00000000
    pin 8 (GPP_F_8) 8:INTC10BC:01 GPIO 0x44000300 0x0003c04a 0x00000000
    pin 9 (GPP_F_9) 9:INTC10BC:01 mode 4 0x44001302 0x0003c04b 0x00000000 [ACPI]
    pin 10 (GPP_F_10) 10:INTC10BC:01 GPIO 0x44000300 0x0000004c 0x00000000
    pin 11 (GPP_F_11) 11:INTC10BC:01 GPIO 0x44000300 0x0003c04d 0x00000000
    pin 12 (GPP_F_12) 12:INTC10BC:01 mode 8 0x44002302 0x0000004e 0x00000000 [ACPI]
    pin 13 (GPP_F_13) 13:INTC10BC:01 mode 8 0x44002302 0x0000004f 0x00000000 [ACPI]
    pin 14 (GPP_F_14) 14:INTC10BC:01 GPIO 0x44000300 0x0003c050 0x00000000
    pin 15 (GPP_F_15) 15:INTC10BC:01 GPIO 0x44000300 0x0003c051 0x00000000
    pin 16 (GPP_F_16) 16:INTC10BC:01 GPIO 0x84000201 0x0003c052 0x00000000
    pin 17 (GPP_F_17) 17:INTC10BC:01 GPIO 0x44000300 0x0003c053 0x00000000
    pin 18 (GPP_F_18) 18:INTC10BC:01 GPIO 0x80100102 0x0003c054 0x00000000
    pin 19 (GPP_F_19) 19:INTC10BC:01 GPIO 0x44000300 0x00000055 0x00000000
    pin 20 (GPP_F_20) 20:INTC10BC:01 GPIO 0x82800100 0x00000056 0x00000000
    pin 21 (GPP_F_21) 21:INTC10BC:01 GPIO 0x44000200 0x00000057 0x00000000 [ACPI]
    pin 22 (GPP_F_22) 22:INTC10BC:01 GPIO 0x84000100 0x0003c058 0x00000000
    pin 23 (GPP_F_23) 23:INTC10BC:01 GPIO 0x84000100 0x00000059 0x00000000
    pin 24 (GPP_F_24) 24:INTC10BC:01 GPIO 0x40000300 0x00003c00 0x00000000 [ACPI]
    pin 25 (GPP_F_25) 25:INTC10BC:01 mode 8 0x40002300 0x00000000 0x00000000 [ACPI]
    pin 26 (GPP_E_0) 26:INTC10BC:01 GPIO 0x44000300 0x0000005a 0x00000000 [ACPI]
    pin 27 (GPP_E_1) 27:INTC10BC:01 GPIO 0x84000102 0x0003c05b 0x00000000
    pin 28 (GPP_E_2) 28:INTC10BC:01 mode 2 0x44000b02 0x0003c05c 0x00000000 [ACPI]
    pin 29 (GPP_E_3) 29:INTC10BC:01 GPIO 0x84000201 0x0000005d 0x00000000
    pin 30 (GPP_E_4) 30:INTC10BC:01 GPIO 0x44000300 0x0000005e 0x00000000 [ACPI]
    pin 31 (GPP_E_5) 31:INTC10BC:01 mode 4 0x44001300 0x0003c05f 0x00000000 [ACPI]
    pin 32 (GPP_E_6) 32:INTC10BC:01 GPIO 0x44000300 0x00000060 0x00000800
    pin 33 (GPP_E_7) 33:INTC10BC:01 GPIO 0x44000300 0x00000061 0x00000000
    pin 34 (GPP_E_8) 34:INTC10BC:01 GPIO 0x44000300 0x00000062 0x00000000
    pin 35 (GPP_E_9) 35:INTC10BC:01 mode 1 0x44000702 0x00000063 0x00000800 [ACPI]
    pin 36 (GPP_E_10) 36:INTC10BC:01 GPIO 0x84000201 0x00000064 0x00000000
    pin 37 (GPP_E_11) 37:INTC10BC:01 GPIO 0x84000100 0x0003c065 0x00000000
    pin 38 (GPP_E_12) 38:INTC10BC:01 mode 8 0x44002302 0x00000066 0x00000000 [ACPI]
    pin 39 (GPP_E_13) 39:INTC10BC:01 mode 8 0x44002302 0x00000067 0x00000000 [ACPI]
    pin 40 (GPP_E_14) 40:INTC10BC:01 GPIO 0x44000300 0x0003c068 0x00000000
    pin 41 (GPP_E_15) 41:INTC10BC:01 GPIO 0x44000300 0x0003c069 0x00000000
    pin 42 (GPP_E_16) 42:INTC10BC:01 GPIO 0x44000300 0x0003c06a 0x00000000
    pin 43 (GPP_E_17) 43:INTC10BC:01 GPIO 0x84000201 0x0003c06b 0x00000000
    pin 44 (GPP_E_18) 44:INTC10BC:01 GPIO 0x80100102 0x0003c06c 0x00000000
    pin 45 (GPP_E_19) 45:INTC10BC:01 GPIO 0x84000100 0x0003c06d 0x00000000
    pin 46 (GPP_E_20) 46:INTC10BC:01 GPIO 0x84000102 0x0003c06e 0x00000000
    pin 47 (GPP_E_21) 47:INTC10BC:01 mode 1 0x04000702 0x0003c06f 0x00000000 [ACPI]
    pin 48 (GPP_E_22) 48:INTC10BC:01 GPIO 0x44000300 0x0003c070 0x00000000
    pin 49 (GPP_E_23) 49:INTC10BC:01 mode 1 0x40000702 0x0003f000 0x00000000 [ACPI]
    pin 50 (GPP_E_24) 50:INTC10BC:01 GPIO 0x40000300 0x00000000 0x00000000 [ACPI]
    
    Contents of /sys/kernel/debug/pinctrl/INTC10BC:01/gpio-ranges:
    GPIO ranges handled:
    0: INTC10BC:01 GPIOS [560 - 585] PINS [0 - 25]
    26: INTC10BC:01 GPIOS [586 - 610] PINS [26 - 50]
    
    Equivalent GPIO character-device check (/dev/gpiochip1, offset 46):
    # ./read-pin46 --read-verified-input
    chip: gpiochip1
    label: INTC10BC:01
    lines: 51
    offset: 46
    name: 
    consumer: 
    flags: 0x4
    value: 1 (active-high; physical level)
    released: yes; ownership/flags unchanged
    
    Pin configuration before:
    pin 46 (GPP_E_20) 46:INTC10BC:01 GPIO 0x84000102 0x0003c06e 0x00000000
    Pin configuration after:
    pin 46 (GPP_E_20) 46:INTC10BC:01 GPIO 0x84000102 0x0003c06e 0x00000000
    
  15. charleskeepax commented on Sep 23, 2026

    @charleskeepax

    Thank you, looks like your system should be loading the spkid1 tunes. As a test, could you symlink all the spkid0 tunes such that they point across to the spkid1 tunes? That way it shouldn't matter what the incorrect GPIO reads the system will load the tune for your hardware ie. spkid1. Then could you reboot, retest and report back if that helps with the audio issues you have been experiencing?

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