Re: cs35l41-hda: PUP_DONE times out on ASUS UX3405CA (SSID 10431A63)

Luqman H <[email protected]>
Newsgroups org.alsa-project.alsa-devel
Message-ID <CA+Mr_5Udw+Q0aSVJpi=0r3x_g=KizPCkTc6WdfUL9hUUi0hyjA@mail.gmail.com>
Subject: Re: cs35l41-hda: PUP_DONE times out on ASUS UX3405CA (SSID
10431A63)

Please disregard this report - it is resolved by an ASUS BIOS update, and my
diagnosis pointed in the wrong direction.

Updating from BIOS UX3405CA.314 (2025-11-20) to UX3405CA.315 (2026-01-21)
fixed it completely. The internal speakers work normally, and there have
been
zero PUP_DONE timeouts since, including across a suspend/resume cycle -
which
previously always resulted in the amps failing again:

  cs35l41-hda ...hda.0: Asserting Reset
  cs35l41-hda ...hda.0: Calibration applied: R0=10390
  cs35l41-hda ...hda.1: Calibration applied: R0=10440
  cs35l41-hda ...hda.0: Firmware Loaded - Type: spk-prot, Gain: 19
  cs35l41-hda ...hda.1: Firmware Loaded - Type: spk-prot, Gain: 19

Two corrections to my original mail:

1. I stated that UX3405CA.314 was the latest BIOS available from ASUS. That
   was wrong - .315 existed and is what fixes this. Apologies for the
   misleading information.

2. I suggested raising the 100 ms PUP_DONE bound in cs35l41_global_enable().
   Please do not act on that on my account. The cause was platform firmware,
   not the kernel timeout, and patching the timeout would have papered over
an
   ASUS ACPI/firmware bug rather than fixing it.

The observation that PUP_DONE was asserting after the timeout still stands
as
a description of what the old BIOS did, but it was a symptom, not the bug.

For anyone else hitting this on a UX3405CA: update the BIOS to .315 or later
before investigating anything on the kernel side.

Sorry for the noise, and thanks for your time.

Luqman

On Wed, Aug 5, 2026 at 1:11 PM [email protected] <[email protected]> wrote:

> Hi,
>
> Both CS35L41 amps driving the internal speakers on an ASUS Zenbook 14
> UX3405CA fail every power-up with:
>
>   cs35l41-hda spi0-CSC3551:00-cs35l41-hda.0: Failed waiting for
> CS35L41_PUP_DONE_MASK: -110
>   cs35l41-hda spi0-CSC3551:00-cs35l41-hda.1: Failed waiting for
> CS35L41_PUP_DONE_MASK: -110
>
> The internal speakers are completely silent. HDMI and Bluetooth are
> unaffected.
>
> Reading the amp registers during a failing playback shows that PUP_DONE
> *does* eventually assert - the amps are not faulting, they are just
> slower to bring up external boost than the 100 ms the driver allows.
> Details and evidence below.
>
>
> ROOT CAUSE EVIDENCE
> ===================
>
> Registers captured during a failing playback. Playback started, the
> PUP_DONE timeout was logged at 11:15:26, registers were read at
> 11:15:28:
>
>   Register              amp .0 (L)   amp .1 (R)
>   --------------------  -----------  -----------
>   PWR_CTRL1             00000001     00000001
>   IRQ1_STATUS1          01400001     01400000
>   IRQ1_RAW_STATUS1      41406001     40406000
>   IRQ1_MASK1            7ffd7e3f     7ffd7e3f
>   GPIO_STATUS1          00000001     00000000
>   GPIO_PAD_CONTROL      02010000     02000000
>   AMP_GAIN_CTRL         00000273     00000273
>   AMP_ERR_VOL           00000000     00000000
>   VPBR_STATUS           00000000     00000000
>   VBBR_STATUS           00000000     00000000
>   PROTECT_REL_ERR_IGN   00000000     00000000
>
> IRQ1_STATUS1 has bit 24 set on both amps, and CS35L41_PUP_DONE_MASK is
> 0x01000000 - bit 24. Power-up completed.
>
> That can only be a late assertion. In the CS35L41_EXT_BOOST branch of
> cs35l41_global_enable() the failure path returns without clearing the
> status; only the success path clears it:
>
>     ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1,
> int_status,
>                                    int_status & CS35L41_PUP_DONE_MASK,
> 1000, 100000);
>     if (ret) {
>             dev_err(dev, "Failed waiting for CS35L41_PUP_DONE_MASK:
> %d\n", ret);
>             cs35l41_test_key_lock(dev, regmap);
>             return ret;                 /* <-- status not cleared */
>     }
>     regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PUP_DONE_MASK);
>
> Every attempt on this machine takes the failure path, so nothing ever
> clears bit 24. The only way it can be set is for the amp to have
> asserted PUP_DONE some time after the 100 ms poll expired.
>
> No fault bit is set - not bit 6 (BST_OVP_ERR), 7 (BST_DCM_UVP_ERR), 8
> (BST_SHORT_ERR), 15 (TEMP_WARN), 17 (TEMP_ERR) or 31 (AMP_SHORT_ERR).
> PWR_CTRL1 = 1 confirms GLOBAL_EN is set, and GPIO_STATUS1 = 1 on amp .0
> confirms the VSPK switch is actually being driven.
>
> I should be clear that this is an inference from the code path that
> never clears the bit, not a direct observation of the bit changing. I
> could not time the assertion: because the failure path never clears it,
> it cannot be re-armed without rebooting for a clean baseline.
>
>
> NO FAULT INTERRUPT HAS EVER FIRED
> =================================
>
> Consistent with the above, the amps have never raised an interrupt.
> Setup is correct on both sides: all 12 handlers (6 per amp) are
> registered, cs35l41_configure_interrupt() does not emit its "IRQ Config
> Failed" warning, and IRQ1_MASK1 = 0x7ffd7e3f leaves all six fault
> interrupts unmasked at the chip. The parent GPIO interrupt is
> level-triggered on hwirq 207.
>
> Yet every counter is zero after hours of uptime:
>
>   177:  0 ... 0  intel-gpio  207  cs35l41 IRQ1 Controller, cs35l41 IRQ1
> Controller
>   197:  0 ... 0  cs35l41 IRQ1 Controller    0  Boost Overvoltage Error
>   198:  0 ... 0  cs35l41 IRQ1 Controller    1  Boost Undervoltage Error
>   199:  0 ... 0  cs35l41 IRQ1 Controller    2  Boost Inductor Short
> Error
>   200:  0 ... 0  cs35l41 IRQ1 Controller    3  Temperature Warning
>   201:  0 ... 0  cs35l41 IRQ1 Controller    4  Temperature Error
>   202:  0 ... 0  cs35l41 IRQ1 Controller    5  Amp Short
>           (identical block for the second amp, 203-208)
>
> I initially read this as a misrouted interrupt line. I no longer think
> so - the register evidence says the part simply does not consider
> itself
> faulted, so there is nothing for it to report.
>
>
> HARDWARE
> ========
>
>   Machine:         ASUS Zenbook 14 UX3405CA (DMI board UX3405CA)
>   BIOS:            UX3405CA.314, 11/20/2025 (latest from ASUS)
>   SoC:             Intel Core Ultra 200H
>   HDA codec:       Realtek ALC294
>   Amps:            2x Cirrus Logic CS35L41 (35a40) Revision B2, on SPI
>   SSID:            10431A63
>   ALSA components: HDA:8086281d,80860101,00100000
>                    HDA:10ec0294,10431a63,00100004
>                    cfg-dmics:2 iec61937-pcm:5,4,3
>
>
> SOFTWARE
> ========
>
>   Distribution:    Fedora 44
>   Kernel:          7.1.5-201.fc44.x86_64
>   linux-firmware:  20260622-1.fc44
>   alsa-lib:        1.2.16.1
>   PipeWire:        1.6.8 / WirePlumber 0.5.14
>   Driver stack:    snd_soc_skl_hda_dsp (SOF) + cs35l41-hda over SPI
>
> Earlier 7.1.x kernels showed a milder symptom (see HISTORY); I cannot
> confirm whether the PUP_DONE error was present there.
>
>
> REPRODUCES ON A CLEAN COLD BOOT
> ===============================
>
> Firmware loads correctly and both amps bind, then power-up fails two
> seconds later:
>
>   10:48:46  ...hda.0: Calibration applied: R0=10390
>   10:48:46  ...hda.0: Firmware Loaded - Type: spk-prot, Gain: 19
>   10:48:46  ...hda.0: CS35L41 Bound - SSID: 10431A63, BST: 1, VSPK: 1,
> CH: L, FW EN: 1, SPKID: 1
>   10:48:46  ...hda.1: Calibration applied: R0=10440
>   10:48:46  ...hda.1: Firmware Loaded - Type: spk-prot, Gain: 19
>   10:48:46  ...hda.1: CS35L41 Bound - SSID: 10431A63, BST: 1, VSPK: 0,
> CH: R, FW EN: 1, SPKID: 1
>   10:48:47  ...hda.0: Failed waiting for CS35L41_PUP_DONE_MASK: -110
>   10:48:47  ...hda.1: Failed waiting for CS35L41_PUP_DONE_MASK: -110
>
> Fully reproducible and permanent from boot. On an earlier boot the
> first
> failure came 11 s after boot and the only suspend/resume cycle happened
> four hours later, so suspend is not the trigger.
>
>
> BEHAVIOUR WITH THE DSP FIRMWARE ABSENT
> ======================================
>
> At one point the amps ended up running with no DSP firmware (see the
> secondary bug below). In that state the behaviour changed
> informatively:
>
>   - PUP_DONE no longer timed out at all, across ~20 minutes of repeated
>     playback.
>   - The speakers did produce sound, for roughly the first 4 seconds.
>   - After that they went silent and stayed silent, with playback still
>     running and no kernel message of any kind.
>   - Reproduced deliberately with six 2-second pink-noise bursts, 1 s
>     apart, at 100% volume: only the first two were audible.
>
> "Forced Mute Status" was polled every 2 s across a 20 s playback and
> stayed off on both amps.
>
>
> PLATFORM _DSD IS COMPLETE AND CORRECTLY APPLIED
> ===============================================
>
> I dumped and decompiled the platform ACPI to check whether the _DSD was
> at fault. It is not. Device (SPK1) in SSDT17 declares:
>
>     Name (_HID, "CSC3551")
>     Name (_SUB, "10431A63")
>
>     Name (_DSD, Package (0x02)
>     {
>         ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
>         Package (0x06)
>         {
>             Package (0x02) { "cirrus,dev-index",        Package (0x02)
> { Zero, One } },
>             Package (0x02) { "reset-gpios",             Package (0x08)
> { ^SPK1, , One, Zero, Zero,
>
>   ^SPK1, , One, Zero, Zero } },
>             Package (0x02) { "cirrus,speaker-position", Package (0x02)
> { Zero, One } },
>             Package (0x02) { "cirrus,boost-type",       Package (0x02)
> { One, One } },
>             Package (0x02) { "cirrus,gpio1-func",       Package (0x02)
> { One, Zero } },
>             Package (0x02) { "cirrus,gpio2-func",       Package (0x02)
> { 0x02, 0x02 } }
>         }
>     })
>
> Every value matches the driver's bind messages and the chip registers:
>
>   Property                 Value    Meaning
> Confirmed by
>   -----------------------  -------  -------------------------------  --
> --------------------
>   cirrus,boost-type        {1, 1}   CS35L41_EXT_BOOST
> BST: 1 in bind log
>   cirrus,gpio1-func        {1, 0}   CS35L41_GPIO1_GPIO / HIZ
> VSPK: 1 / VSPK: 0
>   cirrus,gpio2-func        {2, 2}   CS35L41_GPIO2_INT_OPEN_DRAIN
> IRQ registered, level
>   cirrus,speaker-position  {0, 1}   Left / Right
> CH: L / CH: R
>   reset-gpios              idx 1    shared reset
> "Reset line busy..."
>
> GPIO_PAD_CONTROL reads 0x02010000 on amp .0 (GP2 = 2, GP1 = 1) and
> 0x02000000 on amp .1 (GP2 = 2, GP1 = 0), exactly as declared.
>
> So unlike 103C89C6 and 103C8B63 - where cs35l41_hda_property.c carries
> comments about ACPI declaring the wrong boost type - there is no
> evident
> mis-declaration here to override.
>
>
> NOTE ON THE DRIVER PROPERTY TABLE
> =================================
>
> In sound/hda/codecs/side-codecs/cs35l41_hda_property.c (formerly
> sound/pci/hda/), the entry is:
>
>     { "CSC3551", "10431A63", missing_speaker_id_gpio2 },
>
> identical in v7.0, v7.1 and master. Of the 40 ASUS 1043* SSIDs in that
> file, 10431A63 is the only one not handled by generic_dsd_config, and
> the only one with no cs35l41_config_table entry.
>
> There is no cirrus,speaker-id-gpios in the platform _DSD, which is
> presumably why the quirk exists - it supplies one from GPIO resource
> index 2. Decoding the raw _CRS gives five GPIO resources:
>
>   idx 0  GpioIo   pin 72
>   idx 1  GpioIo   pin 208   reset line referenced by reset-gpios
>   idx 2  GpioIo   pin 206   claimed by the quirk as speaker-id
>   idx 3  GpioIo   pin 207
>   idx 4  GpioInt  pin 207   level-triggered; matches intel-gpio 207
>
> Pin 207 appears twice, as a GpioIo at index 3 and as the GpioInt at
> index 4. I cannot verify from here whether index 2 is the correct
> speaker-id resource on the CA variant; given the quirk appears to have
> been authored for the closely related UX3405MA, that may be worth
> confirming.
>
> Also worth noting: "Using extra _DSD properties, bypassing _DSD in
> ACPI"
> is printed whenever cs35l41_add_dsd_properties() succeeds, but on the
> missing_speaker_id_gpio2 path the platform _DSD is still parsed by
> cs35l41_hda_parse_acpi(). The message overstates what happened and
> initially misled my own diagnosis.
>
>
> HISTORY
> =======
>
> This machine previously showed a milder form of the same problem:
> playback cut out for a fraction of a second roughly every 1 s, and a
> reboot restored clean audio for a while. No kernel error was logged at
> all then. If the cause is a marginal boost ramp against a fixed 100 ms
> bound, that earlier intermittent behaviour fits: sometimes boost made
> the deadline, sometimes not. It has since degraded to failing every
> time.
>
>
> RULED OUT
> =========
>
> None of these changed the behaviour:
>
>   - CPU governor (powersave -> performance)
>   - snd_hda_intel power_save = 0
>   - PipeWire quantum locked to 1024/2048
>   - WirePlumber node suspension disabled
>   - PipeWire RT scheduling (verified: SCHED_RR prio 60 via rtkit)
>   - SMI storms (0 per turbostat)
>   - Scheduler latency (no gaps > 30 ms over 15 s)
>   - CS35L41 runtime PM (forced power/control=on on both SPI devices)
>   - BIOS and linux-firmware both at latest available versions
>
> Mixer state during failure is correct throughout: ALSA Master 100% on,
> Speaker 90% on, SOF Pre/Post Mixer Analog 100% at 0.00 dB, PipeWire
> sink
> routed to Speaker and unmuted.
>
>
> SUGGESTED DIRECTION
> ===================
>
> The 100 ms bound in cs35l41_global_enable() looks too short for this
> platform's external boost. A longer timeout, or a per-platform bound,
> would likely fix this machine.
>
> If you can supply a debug patch that timestamps the assertion - or
> simply raises the timeout so I can report whether audio returns - I am
> glad to build and test it. I can also read back further registers or
> provide any other debug output on request.
>
>
> SECONDARY BUG: FIRMWARE LOOKUP FAILS AFTER A PCI REBIND
> =======================================================
>
> Probably unrelated, but found along the way. Unbinding and rebinding
> the
> audio controller:
>
>   echo 0000:00:1f.3 > /sys/bus/pci/drivers/sof-audio-pci-intel-
> mtl/unbind
>   echo 0000:00:1f.3 > /sys/bus/pci/drivers/sof-audio-pci-intel-mtl/bind
>
> rebuilds the sound card successfully, but the amps then cannot find
> their firmware:
>
>   cs35l41-hda ...hda.0: Falling back to default firmware.
>   cs35l41-hda ...hda.0: Unable to find firmware and tuning
>   cs35l41-hda ...hda.0: Cannot Initialize Firmware. Error: -2
>
> With firmware_loader dynamic debug enabled, the requested names are:
>
>   fw-cirrus/cs35l41--spk-prot-10431a63-spkid1-r0.wmfw
>   fw-cirrus/cs35l41--spk-prot-10431a63-r0.wmfw
>   fw-cirrus/cs35l41--spk-prot-10431a63-spkid1.wmfw
>   fw-cirrus/cs35l41--spk-prot-10431a63.wmfw
>   fw-cirrus/cs35l41--spk-prot.wmfw
>
> Note the doubled hyphen. SSID (10431a63), speaker id (spkid1) and amp
> name (r0) are all still correct - what is missing is dsp_name, i.e.
> cs35l41->cs_dsp.name, which should be dsp1. It is empty after the
> rebind, so cs35l41_request_firmware_file() builds cs35l41--spk-prot-...
> instead of cs35l41-dsp1-spk-prot-..., and every candidate misses,
> including the generic fallback (cirrus/cs35l41-dsp1-spk-prot.wmfw.xz is
> present on disk).
>
> A runtime reload via the "L0/R0 DSP1 Firmware Load" ALSA controls fails
> the same way, so the amps cannot recover their firmware without a
> reboot.
>
> Separately, unbinding the HDA codec alone:
>
>   echo ehdaudio0D0 >
> /sys/bus/hdaudio/drivers/snd_hda_codec_alc269/unbind
>
> tears down the entire SOF card, and the subsequent bind fails with
> "No such device".
>
>
> Happy to provide the full regmap dumps, the decompiled SSDT, or
> anything
> else useful.
>
> Thanks,
> Luqman
>


-- 
Luqman
~ Sent from the web
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.