From: "Rámon van Raaij" <ramon@vanraaij.eu>
To: linux-sound@vger.kernel.org
Cc: alsa-devel@alsa-project.org, Takashi Iwai <tiwai@suse.de>,
Shenghao Ding <shenghao-ding@ti.com>
Subject: [BUG] ALSA: hda: snd_hda_scodec_tas2781_i2c: DSP firmware silently fails to load at cold boot (Lenovo Yoga Pro 9 16IMH9)
Date: Fri, 01 May 2026 19:56:33 +0200 [thread overview]
Message-ID: <20260501175633.bug1-ramon@vanraaij.eu> (raw)
Machine: Lenovo Yoga Pro 9 16IMH9 (board SSID 83DN)
Kernel: 7.0.3-zen1-1-zen (linux-zen)
Codec: Realtek ALC287, subsystem ID 17aa:38d6
Amps: 4x TI TAS2781, ACPI HID TIAS2781, I2C bus i2c-4
(I2C controller: PCI 0000:00:15.2, Intel Designware)
Fixup: ALC287_FIXUP_TAS2781_I2C (applied correctly via HDA_CODEC_QUIRK 17aa:38d6)
PROBLEM
-------
At cold boot the built-in speakers produce ~10-15% of normal volume.
The TAS2781 amplifiers are powered and the HDA component bind succeeds:
snd_hda_codec_alc269 ehdaudio0D0: bound i2c-TIAS2781:00
(ops tas2781_hda_comp_ops [snd_hda_scodec_tas2781_i2c])
However, the DSP firmware (TAS2XXX38D6.bin) is not loaded. The ALSA
control "Speaker Force Firmware Load" -- which is only registered after
a successful firmware load inside tas2781_hda_comp_bind() -- is absent:
$ amixer -c sofhdadsp cget name="Speaker Force Firmware Load"
amixer: Cannot find the given element from control sysdefault:0
No error is logged to dmesg. The driver continues without DSP calibration
data, leaving the amplifiers at uncalibrated default gain.
The issue does NOT occur after S3 suspend/resume. After resume, a
modprobe -r / modprobe cycle restores full speaker volume.
ROOT CAUSE
----------
The BIOS initialises the TAS2781 amps during POST and leaves them in a
hardware state incompatible with the kernel firmware load sequence. The
request_firmware_nowait() call in the bind path silently fails when called
against hardware in this BIOS-initialised state.
Critical observation: a PCI-level power cycle of the I2C controller
(0000:00:15.2) reliably resolves the issue:
echo 1 > /sys/bus/pci/devices/0000:00:15.2/remove
sleep 2
echo 1 > /sys/bus/pci/rescan
After this sequence ACPI gates the I2C controller power rail (D3cold),
resetting the TAS2781 amps to factory state. On rescan, i2c_designware
and snd_hda_scodec_tas2781_i2c re-probe, DSP firmware loads, and
"Speaker Force Firmware Load" appears in amixer.
A plain modprobe -r / modprobe cycle WITHOUT the PCI power cycle does
NOT fix the issue, confirming this is a hardware state problem, not a
module loading or firmware subsystem timing race.
WORKAROUND
----------
The following systemd service (After=sound.target,
Before=display-manager.service) reliably restores correct volume on
every boot. It must run before PipeWire opens the device; hot-removing
the PCI device while WirePlumber has an active ALSA handle causes a
SIGSEGV in snd_hctl_elem_get_interface (libasound).
[Service]
Type=oneshot
ExecStartPre=/bin/sleep 2
ExecStart=/bin/bash -c 'echo 1 > /sys/bus/pci/devices/0000:00:15.2/remove'
ExecStart=/bin/sleep 2
ExecStart=/bin/bash -c 'echo 1 > /sys/bus/pci/rescan'
ExecStart=/bin/bash -c 'modprobe snd_hda_scodec_tas2781_i2c || true'
ExecStart=/bin/sleep 5
RemainAfterExit=yes
SUGGESTED FIX
-------------
The driver should detect a failed firmware load in tas2781_hda_comp_bind()
and either:
a) Perform a hardware reset sequence on the TAS2781 amps (e.g. via an
ACPI power state transition on the I2C controller) before retrying, or
b) Schedule a deferred retry after the firmware subsystem has fully
settled, with a fallback hardware reset if the retry also fails.
The fix should live in tas2781_hda_comp_bind() or the
request_firmware_nowait() completion callback in
snd_hda_scodec_tas2781_i2c.
Signed-off-by: Rámon van Raaij <ramon@vanraaij.eu>
reply other threads:[~2026-05-01 17:56 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260501175633.bug1-ramon@vanraaij.eu \
--to=ramon@vanraaij.eu \
--cc=alsa-devel@alsa-project.org \
--cc=linux-sound@vger.kernel.org \
--cc=shenghao-ding@ti.com \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox