The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/3] ASoC: tas2783: fix stereo split and resume on a two-amp pair
@ 2026-08-09 10:15 Ville Saarinen
  2026-08-09 10:16 ` [PATCH 1/3] ASoC: tas2783: let regmap-sdw-mbq poll for deferred transactions Ville Saarinen
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Ville Saarinen @ 2026-08-09 10:15 UTC (permalink / raw)
  To: Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang
  Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	linux-sound, linux-kernel

Three fixes for the SoundWire TAS2783 driver, found while bringing up an
HP OmniBook X Flip 14-kc0xxx, which carries two TAS2783 amplifiers
aggregated on one link. Two of the three are not board-specific: as far as
I can tell any machine with an aggregated TAS2783 pair is affected today.

Patch 1 makes deferred SDCA writes work. A Function answering
COMMAND_IGNORED has deferred the transaction, and regmap-sdw-mbq is
supposed to poll Entity-0 Function Status and retry -- but this driver
neither makes that status register readable nor sets the poll interval and
deadline, so the poll is skipped and the retry is instantaneous. Every
deferred write fails by construction with -ENODATA.

Patch 2 makes an aggregated pair render stereo. Both amplifiers currently
play the same channel, so right-channel content is inaudible. The SDCA
control that would select the channel, the UDMPU23 Cluster Index, turns
out not to be implemented on this part -- a genuine device read of it
returns -ENODATA -- so the split is done host-side, by claiming a single
channel per amplifier and dropping the pair out of the SoundWire core's
mirror mode. That is exposed as a boolean "RX Single Channel Switch",
off by default, so the change is opt-in from the machine's UCM profile.

The switch deliberately does not name a side. sdw_compute_slave_ports()
advances the payload offset by the popcount of ch_mask and never looks at
which bit is set, so a driver cannot choose which channel an amplifier
renders; that follows from the amplifier's position in the slave iteration
order, i.e. from the machine driver's codec order. An earlier version of
this series exposed an rt1316/rt1318-style "RX Channel Select" enum with
Left/Right values, and I am glad it did not go out: those values were
measured to be inert, and the control would have promised an ABI the bus
allocator cannot honour.

Patch 3 stops the amplifiers losing their firmware tuning on resume.
Firmware is downloaded with sdw_nwrite_no_pm(), which bypasses the regmap
cache, so the cache keeps stale reg_defaults for every firmware-owned
register; the regcache_sync() on resume then writes those defaults back
over live firmware values. On the affected machine the speakers are dead
after every system resume and stay dead until reboot.

Patch 3 is the one I would most like reviewed on its own merits. It is the
smallest of the three, it is not specific to a stereo pair, and its
symptom is severe.

The three are independent and can be taken separately, though patch 2
builds on the mbq configuration touched by patch 1.

Testing
=======

All three are running on the affected machine and the whole stack works
from a cold boot with no manual steps, including across suspend/resume.

Patch 2 was measured rather than judged by ear: a 1 kHz tone that is
left-only for its first half and right-only for its second, played as one
continuous stream, isolating each amplifier by muting the other and
capturing on the machine's internal DMIC array, with every condition
normalised against both amplifiers muted. Each run was verified from the
kernel log to have re-run hw_params with the setting under test, since the
switch is read at hw_params and a sink that never suspends will not pick
up a change. Numbers are in that patch's changelog; briefly, with the
switch on each amplifier carries one side and the other side sits within
0.4 dB of the muted floor, and with it off both amplifiers render the same
left channel. Ear tests on this hardware are unreliable -- the two
speakers are close enough together that localisation gave a confidently
wrong answer more than once.

Patch 3's mechanism was confirmed by cache-bypassing debugfs register
reads taken while the amplifiers were dead, showing all 12 firmware-owned
registers reverted to their defaults. The fix has been through one
suspend/resume cycle with the speakers still working; that confirmation is
behavioural and I have not re-read the registers after a resume on the
fixed build.

Caveats
=======

The hardware testing above was done on v7.1.6 with clang. The three
patches apply to the master commit named below and have been compile-
tested there with gcc and W=1, with no new warnings; the series adds
exactly two new external references, regcache_drop_region (EXPORT_SYMBOL_
GPL) and snd_ctl_boolean_mono_info (EXPORT_SYMBOL), established by diffing
nm -u output against the unpatched objects. They have not been run on a
master kernel. I have exactly one TAS2783 machine, so the stereo split in
patch 2 is verified on one board with two amplifiers and nothing else.

Tool disclosure, per Documentation/process/generated-content.rst
================================================================

This work was done in extended interactive sessions with Claude (Anthropic,
model claude-opus-5) acting as a coding and debugging assistant, and a
substantial amount of the analysis and of the patch text originated with
it. All three patches carry an Assisted-by tag as described in
Documentation/process/coding-assistants.rst.

The division of work:

  - The assistant did the register-level analysis, read the relevant core
    code, formed the hypotheses, wrote the driver changes and the
    measurement harness, and drafted the changelogs.
  - I ran everything needing root or physical access, rebooted into each
    build, and ran the acoustic measurements.
  - No single prompt produced these patches. It was iterative over roughly
    a day, and a fair number of the assistant's intermediate conclusions
    were wrong: that one amplifier was dead, that the firmware page-0
    configuration set the channel, that the Cluster Index could be made to
    work from the driver, and -- latest and most relevant to what you are
    reading -- that an enum could assign a specific side to each
    amplifier. That last one survived into a fully drafted patch whose
    changelog claimed a per-side assignment, and was caught only by
    re-reading the bus allocator and then measuring both amplifiers set to
    the same value. Each wrong turn was discarded only because it was
    measured. The dead ends around the Cluster Index are summarised in
    patch 2's changelog, because they are the reason the split is done
    host-side.

I have reviewed all three patches, I understand what they do, and I take
responsibility for them.

Ville Saarinen (3):
  ASoC: tas2783: let regmap-sdw-mbq poll for deferred transactions
  ASoC: tas2783: add RX Single Channel Switch to split a two-amp stereo
    pair
  ASoC: tas2783: drop firmware-owned registers from the regmap cache

 sound/soc/codecs/tas2783-sdw.c | 157 +++++++++++++++++++++++++++++++++
 1 file changed, 157 insertions(+)


base-commit: 06cf61899d6498b33e4b7c87d99d5bd471ccc375
-- 
2.55.0



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-08-09 17:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-09 10:15 [PATCH 0/3] ASoC: tas2783: fix stereo split and resume on a two-amp pair Ville Saarinen
2026-08-09 10:16 ` [PATCH 1/3] ASoC: tas2783: let regmap-sdw-mbq poll for deferred transactions Ville Saarinen
2026-08-09 14:05   ` Pierre-Louis Bossart
2026-08-09 17:41     ` Ville Saarinen
2026-08-09 10:16 ` [PATCH 2/3] ASoC: tas2783: add RX Single Channel Switch to split a two-amp stereo pair Ville Saarinen
2026-08-09 10:16 ` [PATCH 3/3] ASoC: tas2783: drop firmware-owned registers from the regmap cache Ville Saarinen
2026-08-09 10:36 ` [PATCH 0/3] ASoC: tas2783: fix stereo split and resume on a two-amp pair Ville Saarinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox