* [BUG] snd_hda_scodec_tas2781_i2c: parent I2C controller enters D3cold during idle, erasing amp register state
@ 2026-05-02 23:30 Rámon van Raaij
0 siblings, 0 replies; only message in thread
From: Rámon van Raaij @ 2026-05-02 23:30 UTC (permalink / raw)
To: linux-sound; +Cc: alsa-devel, Takashi Iwai, Shenghao Ding
Machine: Lenovo Yoga Pro 9 16IMH9 (board name 83DN)
Kernel: 7.0.3-zen1-1-zen (linux-zen)
Amps: 2x TI TAS2781, ACPI HID TIAS2781, I2C bus i2c-4
(I2C controller: PCI 0000:00:15.2, Intel DesignWare / Meteor Lake)
Related: <20260501175633.bug1-ramon@vanraaij.eu>
(DSP firmware fails at cold boot - separate issue, same hardware)
PROBLEM
-------
After approximately 5 minutes of audio inactivity the built-in speakers
drop to ~10-15% of normal volume. No dmesg message is emitted and no
driver error is reported. Audio continues to function at the low volume;
the issue is not a complete failure. The drop is not tied to display
power-off; it occurs during I2C bus inactivity regardless of display state.
ROOT CAUSE
----------
The TAS2781 amplifiers sit on a Synopsys DesignWare I2C bus whose parent
PCI device (0000:00:15.2) defaults to power/control=auto. During deep
idle the kernel runtime-suspends this controller. When the controller
enters D3cold (which ACPI can gate the power rail for), the entire I2C
bus loses power and all TAS2781 register state is erased.
This is distinct from the TAS2781 I2C device's own runtime-PM: pinning
the I2C device to power/control=on does not help because the power loss
comes from the parent PCI controller, not from the I2C device itself.
Confirmed by checking power state before and after idle:
# Before idle (volume normal):
$ cat /sys/bus/pci/devices/0000:00:15.2/power/runtime_status
active
$ cat /sys/bus/pci/devices/0000:00:15.2/power/control
auto
# After ~5 min audio inactivity (volume dropped to ~10-15%):
$ cat /sys/bus/pci/devices/0000:00:15.2/power/runtime_status
suspended
The timing (~5 min) corresponds to the system entering a deep idle
state during I2C bus inactivity, which allows the PCI controller to
runtime-suspend.
WORKAROUND
----------
Pinning the PCI controller to always-on prevents the volume drop:
echo on > /sys/bus/pci/devices/0000:00:15.2/power/control
Persistent via udev (ACTION=="add" alone is insufficient: i2c_designware
resets power/control back to auto after driver binding, so ACTION=="bind"
is also required):
ACTION=="add|bind", SUBSYSTEM=="pci", ENV{PCI_SLOT_NAME}=="0000:00:15.2", \
ATTR{power/control}="on"
This is a blunt workaround that prevents any runtime PM on the entire I2C
controller, which affects all devices on that bus.
SUGGESTED FIX
-------------
snd_hda_scodec_tas2781_i2c should hold a PM runtime reference on the
parent PCI device of its I2C controller during probe, preventing D3cold
for as long as the driver is bound. Something along the lines of:
/* In probe: */
pci_dev = to_pci_dev(client->adapter->dev.parent->parent);
pm_runtime_get_sync(&pci_dev->dev);
/* In remove: */
pm_runtime_put(&pci_dev->dev);
Alternatively a PCI quirk could set ACPI_COMPANION power flags to prevent
D3cold for PCI 8086:7e7a (the Meteor Lake DesignWare controller) on
platforms where TAS2781 amps are present.
Signed-off-by: Ramon van Raaij <ramon@vanraaij.eu>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-05-02 23:31 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-02 23:30 [BUG] snd_hda_scodec_tas2781_i2c: parent I2C controller enters D3cold during idle, erasing amp register state Rámon van Raaij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox