* ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
@ 2026-07-27 9:33 Andrey Golovko
2026-07-27 14:08 ` Pierre-Louis Bossart
0 siblings, 1 reply; 6+ messages in thread
From: Andrey Golovko @ 2026-07-27 9:33 UTC (permalink / raw)
To: Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, linux-sound
Cc: Mark Brown, Liam Girdwood, Vinod Koul, Pierre-Louis Bossart,
Bard Liao, Vijendar Mukunda, Mario Limonciello, Antoine Monnet,
linux-kernel
Hi,
On an ASUS ProArt PX13 HN7306EAC (Ryzen AI MAX+ 395, AMD ACP rev 0x70,
two TAS2783 at unique_id 0x8/0xB plus RT721 on SoundWire link 1), audio
is silent after resume from s2idle whenever the platform actually reaches
S0i3. Playback runs with no error whatsoever - no XRUN at first, no
prepare failure, no bus error - and the speakers stay quiet until the PCM
is fully torn down and recreated.
This is with v7.2-rc4 plus 5893013efabb ("ASoC: amd: ps: disable MSI on
resume in ACP PCI driver"), which is what makes the peripherals re-attach
at all on this board [1], and with a local fix that drops the stale
tas2783 regcache on re-attach [2]. Both are necessary here; neither is
sufficient.
I measured where the audio stops, and the answer is not where I expected.
1. The ACP side is healthy
--------------------------
I dumped the ACP registers that the driver programs (ring buffer address
and size, FIFO address and size, DMA size, watermark, stream enable, plus
the SoundWire manager block) during actual playback, once in the silent
state after resume and once after the workaround restored audio.
72 of 78 registers are bit-identical. The only differences are
ACP_EXTERNAL_INTR_CNTL (one extra bit, 0x10000 = PDM_DMA_INTR_MASK, i.e.
the digital mics, unrelated to this stream) and the last immediate
command/response pair on the bus.
That is expected: acp63_sdw_pcm_resume() reprograms the PTE, the ring
buffer, the watermark and the DMA interrupt masks for every live
substream on system resume. The ACP DMA configuration is restored
correctly.
2. The DMA is running at the correct rate while silent
------------------------------------------------------
Sampling ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR every 500 ms during silent
playback:
0x000002FBF880 +96064
0x000002FD6F80 +96000
0x000002FEE6C0 +96064
0x000003005E00 +96064
0x00000301D500 +96000
96000 bytes per 500 ms = 192000 B/s = 48000 Hz x 2 ch x 2 bytes, exactly
nominal. The ACP is fetching the buffer and feeding the SoundWire FIFO
the whole time the speakers are silent.
3. The peripheral port never finishes preparing
-----------------------------------------------
Dumping /sys/kernel/debug/soundwire/master-0-1/sdw:*/registers during
playback, silent state versus working state, the entire difference across
all three peripherals is two registers - and it is the same register on
both amplifiers:
DP1 0x104 (DPn_PrepareStatus): silent = 0x3 working = 0x0
with DPn_PrepareCtrl (0x105) = 0x3 and DPn_ChannelEn = 0x3 in both cases.
(The third difference is SCP_Int1 on one amp, i.e. transient interrupt
status.)
Per the core's own reading of that register - "Poll for NOT_PREPARED==0"
in sdw_prep_deprep_slave_ports() - a set bit means the channel is *not*
prepared. So after the power gate both amps sit with both channels
unprepared, indefinitely, while the manager streams data at them.
4. Why nothing complains
------------------------
tas2783-sdw declares simple_ch_prep_sm, so the core skips its entire
prepare block: it neither writes DPn_PrepareCtrl nor polls
DPn_PrepareStatus. The driver writes DPn_PrepareCtrl itself from
tas_port_prep() - as the comment there says, "TAS2783 requires explicit
port prepare during playback stream setup even when simple_ch_prep_sm is
enabled. Without this, the port fails to enter the prepared state
resulting in no audio output" - but nobody ever checks whether the port
actually reached the prepared state.
The result is a completely silent failure: the stream is enabled, the DMA
runs, the log is clean, and there is no sound.
What restores it is a full teardown: hw_free (which de-prepares the port,
writing DPn_PrepareCtrl = 0) followed by hw_params and a fresh prepare.
Re-preparing without the de-prepare - which is what a plain userspace
resume does - leaves DPn_PrepareStatus stuck. On this board I work around
it by cycling the card profile after every resume, which forces that
teardown.
Questions
---------
- Should TAS2783 declare simple_ch_prep_sm at all? The port evidently
does not prepare instantaneously, which is the premise of that
property; letting the core do its normal write-and-poll would at least
turn this into a visible error instead of silence.
- If the property is correct, should tas_port_prep() poll
DPn_PrepareStatus after writing DPn_PrepareCtrl, mirroring what the
core does?
- Either way: why does a fresh prepare not complete after the device has
lost power, when a de-prepare followed by a prepare does? If the amp
needs the port explicitly de-prepared before it will accept a new
prepare after a power cycle, that sequencing has to happen somewhere
on resume.
Happy to test patches, dump additional registers, or run traces on this
hardware.
[1] https://lore.kernel.org/all/466a905d-8203-46d2-bfe4-a3b3f9b5d68b@montane.tech/
[2] https://lore.kernel.org/all/bb5064629ada99fa5163621f72fbd27f@gmail.com/
Thanks,
Andrey
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
2026-07-27 9:33 ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13) Andrey Golovko
@ 2026-07-27 14:08 ` Pierre-Louis Bossart
2026-07-28 7:31 ` Holalu Yogendra, Niranjan
0 siblings, 1 reply; 6+ messages in thread
From: Pierre-Louis Bossart @ 2026-07-27 14:08 UTC (permalink / raw)
To: Andrey Golovko, Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang,
linux-sound
Cc: Mark Brown, Liam Girdwood, Vinod Koul, Bard Liao,
Vijendar Mukunda, Mario Limonciello, Antoine Monnet, linux-kernel,
Niranjan H Y
On 7/27/26 11:33, Andrey Golovko wrote:
> Hi,
>
> On an ASUS ProArt PX13 HN7306EAC (Ryzen AI MAX+ 395, AMD ACP rev 0x70,
> two TAS2783 at unique_id 0x8/0xB plus RT721 on SoundWire link 1), audio
> is silent after resume from s2idle whenever the platform actually reaches
> S0i3. Playback runs with no error whatsoever - no XRUN at first, no
> prepare failure, no bus error - and the speakers stay quiet until the PCM
> is fully torn down and recreated.
>
> This is with v7.2-rc4 plus 5893013efabb ("ASoC: amd: ps: disable MSI on
> resume in ACP PCI driver"), which is what makes the peripherals re-attach
> at all on this board [1], and with a local fix that drops the stale
> tas2783 regcache on re-attach [2]. Both are necessary here; neither is
> sufficient.
>
> I measured where the audio stops, and the answer is not where I expected.
>
> 1. The ACP side is healthy
> --------------------------
> I dumped the ACP registers that the driver programs (ring buffer address
> and size, FIFO address and size, DMA size, watermark, stream enable, plus
> the SoundWire manager block) during actual playback, once in the silent
> state after resume and once after the workaround restored audio.
>
> 72 of 78 registers are bit-identical. The only differences are
> ACP_EXTERNAL_INTR_CNTL (one extra bit, 0x10000 = PDM_DMA_INTR_MASK, i.e.
> the digital mics, unrelated to this stream) and the last immediate
> command/response pair on the bus.
>
> That is expected: acp63_sdw_pcm_resume() reprograms the PTE, the ring
> buffer, the watermark and the DMA interrupt masks for every live
> substream on system resume. The ACP DMA configuration is restored
> correctly.
>
> 2. The DMA is running at the correct rate while silent
> ------------------------------------------------------
> Sampling ACP_P1_AUDIO1_TX_LINEARPOSITIONCNTR every 500 ms during silent
> playback:
>
> 0x000002FBF880 +96064
> 0x000002FD6F80 +96000
> 0x000002FEE6C0 +96064
> 0x000003005E00 +96064
> 0x00000301D500 +96000
>
> 96000 bytes per 500 ms = 192000 B/s = 48000 Hz x 2 ch x 2 bytes, exactly
> nominal. The ACP is fetching the buffer and feeding the SoundWire FIFO
> the whole time the speakers are silent.
>
> 3. The peripheral port never finishes preparing
> -----------------------------------------------
> Dumping /sys/kernel/debug/soundwire/master-0-1/sdw:*/registers during
> playback, silent state versus working state, the entire difference across
> all three peripherals is two registers - and it is the same register on
> both amplifiers:
>
> DP1 0x104 (DPn_PrepareStatus): silent = 0x3 working = 0x0
>
> with DPn_PrepareCtrl (0x105) = 0x3 and DPn_ChannelEn = 0x3 in both cases.
> (The third difference is SCP_Int1 on one amp, i.e. transient interrupt
> status.)
>
> Per the core's own reading of that register - "Poll for NOT_PREPARED==0"
> in sdw_prep_deprep_slave_ports() - a set bit means the channel is *not*
> prepared. So after the power gate both amps sit with both channels
> unprepared, indefinitely, while the manager streams data at them.
>
> 4. Why nothing complains
> ------------------------
> tas2783-sdw declares simple_ch_prep_sm, so the core skips its entire
> prepare block: it neither writes DPn_PrepareCtrl nor polls
> DPn_PrepareStatus. The driver writes DPn_PrepareCtrl itself from
> tas_port_prep() - as the comment there says, "TAS2783 requires explicit
> port prepare during playback stream setup even when simple_ch_prep_sm is
> enabled. Without this, the port fails to enter the prepared state
> resulting in no audio output" - but nobody ever checks whether the port
> actually reached the prepared state.
>
> The result is a completely silent failure: the stream is enabled, the DMA
> runs, the log is clean, and there is no sound.
>
> What restores it is a full teardown: hw_free (which de-prepares the port,
> writing DPn_PrepareCtrl = 0) followed by hw_params and a fresh prepare.
> Re-preparing without the de-prepare - which is what a plain userspace
> resume does - leaves DPn_PrepareStatus stuck. On this board I work around
> it by cycling the card profile after every resume, which forces that
> teardown.
Just to be clear: are you referring to a scenario where audio playback
is on-going, the device does a system suspend during the audio playback
due to a user request, and on resume audio is supposed to restart playing?
That's not an easy capability to test/automate. When I worked with
Intel, we had scripts to force a suspend-resume with aplay running in
the background. They worked most of the time except when they didn't...
> Questions
> ---------
> - Should TAS2783 declare simple_ch_prep_sm at all? The port evidently
> does not prepare instantaneously, which is the premise of that
> property; letting the core do its normal write-and-poll would at least
> turn this into a visible error instead of silence.
> - If the property is correct, should tas_port_prep() poll
> DPn_PrepareStatus after writing DPn_PrepareCtrl, mirroring what the
> core does?
It'd be surprising, these registers are typically updated quickly and if
the sequence works for one playback it should work timing wise after resume.
Anyways, adding Niranjan H Y who contributed the patch "ASoC: tas2783A:
add explicit port prepare handling". The topic of this prepare bit was
discussed in the thread "SoundWire: Allow Prepare command for
Simplified_CP_SM" and we ended-up with the use of this port_prep
callback. IIRC the use of the simple_ch_prep_sm was due to Windows/BIOS
precedent.
Note that there was a change in the full port-prepare programming
sequence, we've since stopped using this interrupt due to other deadlock
problems (see "soundwire: stream: Poll for DP prepare to avoid interrupt
deadlock"). It could very well be that this driver can now use the full
state machine, who knows.
> - Either way: why does a fresh prepare not complete after the device has
> lost power, when a de-prepare followed by a prepare does? If the amp
> needs the port explicitly de-prepared before it will accept a new
> prepare after a power cycle, that sequencing has to happen somewhere
> on resume.
It could be that the use of the port_prep callback is restricted to the
initial stream setup. I am not sure if that stream callback is invoked a
second time after a suspend-resume cycle, this driver is the only one
who makes use of that callback...
Alternatively it could be that something else remains stuck and prevents
the port prepare sequence from completing.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
2026-07-27 14:08 ` Pierre-Louis Bossart
@ 2026-07-28 7:31 ` Holalu Yogendra, Niranjan
2026-08-07 5:21 ` Andrey Golovko
0 siblings, 1 reply; 6+ messages in thread
From: Holalu Yogendra, Niranjan @ 2026-07-28 7:31 UTC (permalink / raw)
To: Andrey Golovko
Cc: Mark Brown, Liam Girdwood, Vinod Koul, Bard Liao,
Vijendar Mukunda, Mario Limonciello, Antoine Monnet,
linux-kernel@vger.kernel.org, Pierre-Louis Bossart, Lu, Kevin,
Ding, Shenghao, Xu, Baojun, Wang, Sen,
linux-sound@vger.kernel.org
> On 19:39-20260727, Pierre-Louis Bossart wrote:
> Subject: Re: ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
>
> >On 7/27/26 11:33, Andrey Golovko wrote:
> > Questions
> > ---------
> > - Should TAS2783 declare simple_ch_prep_sm at all? The port evidently
> > does not prepare instantaneously, which is the premise of that
> > property; letting the core do its normal write-and-poll would at least
> > turn this into a visible error instead of silence.
> > - If the property is correct, should tas_port_prep() poll
> > DPn_PrepareStatus after writing DPn_PrepareCtrl, mirroring what the
> > core does?
We need to use the same BIOS between Windows and Linux, the BIOS sets the device as Simplified_CP_SM.
The device expects the DPn_PrepareCtrl bits to be set to be functional - but doesn't update DPn_PrepareStatus.
If the device is configured as generic CP_SM, the DPn_PrepareStatus bits will not be updated.
Hence we end up with port prepare fail errors even for normal scenario where it could produce audio.
So, the changes were added in the codec driver to explicitly write DPn_PrepareCtrl even in simplified CP_SM
and ignore the DPn_PrepareStatus.
Regards
Niranjan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
2026-07-28 7:31 ` Holalu Yogendra, Niranjan
@ 2026-08-07 5:21 ` Andrey Golovko
2026-08-12 18:24 ` Andrey Golovko
0 siblings, 1 reply; 6+ messages in thread
From: Andrey Golovko @ 2026-08-07 5:21 UTC (permalink / raw)
To: Holalu Yogendra, Niranjan, Pierre-Louis Bossart
Cc: Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, Mark Brown,
Liam Girdwood, Vinod Koul, Bard Liao, Vijendar Mukunda,
Mario Limonciello, Antoine Monnet, linux-sound, linux-kernel
Hi Niranjan, Pierre-Louis,
thanks to both - answers and new data inline.
Pierre-Louis wrote:
> Just to be clear: are you referring to a scenario where audio playback
> is on-going, the device does a system suspend during the audio playback
> due to a user request, and on resume audio is supposed to restart
> playing?
Not necessarily on-going playback - that's the point that makes this
hit ordinary users. PipeWire keeps the PCM substream open the whole
session, so the substream survives the suspend regardless of whether
anything was audibly playing. After resume, even a stream started
*fresh* by an application plays into that surviving substream and is
silent. The only way to get sound back is to force the substream
through hw_free + hw_params (I cycle the card profile, which PipeWire
translates into exactly that).
So the reproduction is deterministic and needs no aplay-in-background
race: boot, let PipeWire open the device, systemctl suspend for
>= 1 min (enough for amd_pmc to report real S0i3 residency; without
residency the bug does not reproduce), resume, start any playback.
Silent every time here.
> It could be that the use of the port_prep callback is restricted to the
> initial stream setup. I am not sure if that stream callback is invoked a
> second time after a suspend-resume cycle
I can answer that with a trace rather than a guess, with one caveat:
stock ps-sdw-dma.c advertises SNDRV_PCM_INFO_RESUME, so a plain resume
takes TRIGGER_RESUME and skips the prepare path entirely - no stream
callbacks at all. With a local patch dropping INFO_RESUME (so userspace
does a full snd_pcm_prepare recovery), the resume-spanning ftrace shows
the complete sequence running after resume: sdw_prepare_stream ->
sdw_prep_deprep_slave_ports -> tas_port_prep() invoked again, 4 calls
(2 amps x 2 callbacks), DPn_PrepareCtrl written with the right masks,
then enable. So the callback *is* invoked on the recovery path - and
the amps are still silent.
The one thing that separates every silent case from every working case
in my traces is the de-prepare: the working path (hw_free) writes
DPn_PrepareCtrl = 0 first, then a fresh prepare writes 3. The silent
path re-writes 3 over 3. After the device has lost power and been
re-initialized (SW_RESET + firmware re-download on re-attach), a
rewrite of the same value evidently does not re-arm anything; the
0 -> 3 edge does.
Niranjan wrote:
> The device expects the DPn_PrepareCtrl bits to be set to be functional -
> but doesn't update DPn_PrepareStatus.
Thanks, that explains the design - I'll withdraw the "port prepare
never completes" framing then, since it leaned on reading
DPn_PrepareStatus, and per your description those bits are not to be
interpreted in Simplified_CP_SM.
One empirical note, for what it's worth: on this hardware 0x104 is not
static. Across all my dumps, on both amplifiers, it reads 0x3 in every
silent state and 0x0 in every working state, tracking the audible state
exactly. I'm not suggesting polling it - just that on this part the
register does reflect something about the port state.
Which leaves the practical question for TI:
After the amplifier loses power while the manager is power-gated
(attach as UNINITIALIZED, SW_RESET, firmware re-download), what does
the device need before a port prepare takes effect again? Empirically
writing DPn_PrepareCtrl = 0 and then 3 works, while writing 3 alone
does not. If the 0 -> 3 sequence is genuinely required, where should
it live - tas_port_prep() unconditionally de-preparing before
preparing, or the codec driver de-preparing its ports as part of the
re-attach re-init?
If TI can confirm the required sequence I'm happy to write and test the
patch on this hardware - I already have the register dumps and traces
automated.
Thanks,
Andrey
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
2026-08-07 5:21 ` Andrey Golovko
@ 2026-08-12 18:24 ` Andrey Golovko
2026-08-12 21:29 ` Andrey Golovko
0 siblings, 1 reply; 6+ messages in thread
From: Andrey Golovko @ 2026-08-12 18:24 UTC (permalink / raw)
To: Holalu Yogendra, Niranjan, Pierre-Louis Bossart
Cc: Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, Mark Brown,
Liam Girdwood, Vinod Koul, Bard Liao, Vijendar Mukunda,
Mario Limonciello, Antoine Monnet, Robin Everaars, Ville Saarinen,
linux-sound, linux-kernel
I have the root cause, and it is neither the host DMA nor the data port
itself: after the peripheral loses power in S0i3 its SDCA Power Domain
Entity PDE23 comes back at PS3, and a Data Port cannot complete channel
preparation while the Function is powered down. The only place the driver
powers PDE23 on is tas_sdw_hw_params(), which the resume path never calls.
Below is the evidence, and at the end a question about where the fix
belongs, which I do not think I should answer alone.
Test setup: ASUS ProArt PX13 HN7306EAC, AMD ACP7.0, two TAS2783 at unique
0x8/0xB plus an rt721-sdca on link 1. Kernel: broonie/sound for-next
(7.2.0-rc6 base) with b627da430357, Peter Ujfalusi's two tas2783
reg_defaults fixes, the regcache sort fixes, Antoine's stereo patch and
three unrelated display fixes. One s2idle cycle with 99.98 s of S0i3
residency out of 105 s of sleep, i.e. the ACP island really was
power-gated.
After resume, with no workaround service running: all three peripherals
Attached, both amps re-download firmware, MSI is re-disabled by
5893013efabb, suspend_stats clean, zero errors of any kind in the log --
and no audio, until the PCM is fully torn down and re-created.
The host side is not at fault, and I was wrong in July
=====================================================
I dumped the ACP and SoundWire manager registers in the silent state and
again after a card-profile cycle had restored audio (78 registers, mmap of
the PCI BAR). The playback stream configuration is identical in both:
ACP_P1_AUDIO1_TX_RINGBUFADDR 0x048E0000 both
ACP_P1_AUDIO1_TX_RINGBUFSIZE 0x00008000 both
ACP_P1_AUDIO1_TX_FIFOADDR/SIZE 0x700/0x100 both
ACP_P1_AUDIO1_TX_DMA_SIZE 0x00000040 both
ACP_P1_AUDIO1_TX_INTR_WATERMARK 0x00001000 both
ACP70_SW1_AUDIO1_TX_EN 0x00000001 both
The only meaningful difference is the linear position counter, and it
shows the DMA is running in the silent state too: 0x017F9440 = 25.1 MB,
which at 48 kHz/2ch/S16 is ~131 s, matching the time since resume.
This retracts what I suggested in July, that ACP loses its SoundWire DMA
ring-buffer configuration across S0i3 and would need it reprogrammed in
.prepare. That hypothesis is wrong: the registers are already correct
while there is no sound.
The peripheral reports the failure correctly
============================================
Slave-side registers, silent versus working, taken during playback:
DP1 PortCtrl (0x102) 0x20 both
DP1 BlockCtrl1 (0x103) 0x0f both
bank SampleCtrl/Offset/HCtrl (0x122..0x126) identical
DPn_PrepareStatus (0x104) amp 0x8: 0x1 silent, 0x0 working
amp 0xB: 0x2 silent, 0x0 working
Niranjan, this is the point you doubted on 28 July: the device does update
DPn_PrepareStatus, and it does so per channel -- each amp reports exactly
the channel it owns as not prepared, 0x1 for the one on channel 0 and 0x2
for the one on channel 1 (single-channel masks, per Antoine's patch). The
transport parameters are intact. Only the prepare state is lost.
Minimal reproduction, no ALSA involved
======================================
With a debug module that talks to the peripherals through
sdw_write_no_pm()/sdw_read_no_pm() only, in the silent state after resume:
1. PrepareCtrl (0x105) already holds the channel mask, so writing the
same value again changes nothing: PrepareStatus stays 0x1/0x2.
2. PrepareCtrl <= 0 clears PrepareStatus to 0x0 immediately. De-prepare
works, and the device is answering us.
3. PrepareCtrl <= mask sets PrepareStatus to the mask again, and it
never clears. I polled for 50 ms, the same way
sdw_prep_deprep_slave_port() does.
4. PDE23 Requested and Actual Power State both read 0x3, i.e. PS3.
5. Write PDE23 Requested = PS0. Actual reads 0x0 immediately. Repeat
step 3 and PrepareStatus clears within 1 ms. Audio is back, without
touching the PCM, without hw_params, without re-enumeration.
So the port is not broken and the state machine is not stuck: it is
waiting for power that nobody restores.
Why nothing is logged
=====================
tas_sdw_hw_params() writes PDE23 Requested = PS0, with a retry loop whose
comment already states the dependency:
/*
* Sometimes, there is error returned during power on.
* So added retry logic to ensure power on so that
* port prepare succeeds
*/
and tas_sdw_pcm_hw_free() writes PS3 on the way out. After S0i3 the
peripheral is back at its register defaults, where PDE23 is PS3. Userspace
resumes the surviving PCM with TRIGGER_RESUME rather than tearing it down,
so hw_params never runs, so PDE23 is never powered up again.
The silence is total because tas2783 sets simple_ch_prep_sm, and
sdw_prep_deprep_slave_port() then skips both the PrepareCtrl write and the
NOT_PREPARED poll. The driver compensates with tas_port_prep(), whose
comment says the same thing -- "the port fails to enter the prepared state
resulting in no audio output" -- but that callback only runs during a real
prepare. Nobody ever asks the peripheral whether it is ready, so a port
that never prepares looks exactly like a healthy one.
Pierre-Louis, this also answers your question from 27 July about whether
playback is ongoing during suspend: it does not matter. What matters is
that a PCM stays open across the cycle, which PipeWire does by default on
an idle sink.
Where should this be fixed?
===========================
Three candidates, and I would rather hear TI and the maintainers than pick
one myself:
(a) ACP stops advertising SNDRV_PCM_INFO_RESUME on the SoundWire DMA
PCMs. That flag promises a resume with no stream re-setup, which
SoundWire cannot honour when the peripheral loses power; Intel's
SoundWire DMA does not set it. Userspace would then have to do a full
hw_free/hw_params recovery, which restores PDE23 as a side effect. I
have this patch and will report whether it is sufficient on its own
on a tree that carries everything above.
(b) tas2783 restores the SDCA power state itself, in
tas2783_sdca_dev_resume() or on the uninitialised re-attach path,
when a stream is active. This makes the codec track stream state that
ASoC already owns, which I do not much like.
(c) The SoundWire core stops letting a stream continue silently across a
peripheral that went UNATTACHED and came back: mark the runtime as
needing re-prepare, and fail loudly if it is not.
My own preference is (a), because the promise in the PCM flag is the thing
that is actually untrue. But (a) fixes it by making userspace do the right
thing, which is not the same as the kernel keeping its own state
consistent, so I may well be missing the intended design.
One more question for TI while we are here: given that tas2783 needs an
explicit PrepareCtrl write anyway, and has tas_port_prep() for exactly
that reason, is simple_ch_prep_sm the right property to declare? Dropping
it would put the core back in charge of the write and, more importantly,
of the NOT_PREPARED poll -- which would have turned this silent failure
into a "Chn prep failed for port 1" error line months ago.
Happy to test patches, and to run the register-level probe again on any
variant that is useful.
Thanks,
Andrey
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13)
2026-08-12 18:24 ` Andrey Golovko
@ 2026-08-12 21:29 ` Andrey Golovko
0 siblings, 0 replies; 6+ messages in thread
From: Andrey Golovko @ 2026-08-12 21:29 UTC (permalink / raw)
To: Holalu Yogendra, Niranjan, Pierre-Louis Bossart
Cc: Shenghao Ding, Kevin Lu, Baojun Xu, Sen Wang, Mark Brown,
Liam Girdwood, Vinod Koul, Bard Liao, Vijendar Mukunda,
Mario Limonciello, Antoine Monnet, Robin Everaars, Ville Saarinen,
linux-sound, linux-kernel
Answering my own question from a few hours ago, since I said I would
report back on option (a) and the answer turned out to be more definite
than I expected: (a) cannot work, and (b) is enough on its own.
A patch is posted here:
https://lore.kernel.org/all/20260813001500.9218-1-andrey.golovko@gmail.com/
(a) does not work, and not by a small margin
============================================
I built a kernel with SNDRV_PCM_INFO_RESUME dropped from the SoundWire
DMA PCMs and nothing else changed. Still silent after resume. The
register state says why:
DPn_PrepareStatus 0x1 / 0x2 still not prepared
ChannelEn now in bank 1 so the stream really was re-prepared
PDE23 req=0x3 act=0x3
So dropping the flag did make userspace stop trying to resume the stream
in place: the port was prepared afresh, the bank flipped, PrepareCtrl was
written. It just did not help, because after resume userspace calls
snd_pcm_prepare(), which reaches .prepare and sdw_prepare_stream() and
never hw_params() again -- ALSA only requires hw_params() after
hw_free(). The Function power-up lives in tas_sdw_hw_params(), so it is
skipped on every recovery path, flag or no flag.
That is worth stating plainly because it kills a whole family of fixes:
no PCM capability flag and no change of userspace behaviour can put the
power-up back, as long as it sits on a callback that recovery does not
re-run.
(b) is enough
=============
The patch powers PDE23 up in tas_port_prep(), in the PRE_PREP case,
immediately before the PrepareCtrl write that function already does. The
dependency is thereby satisfied on every path that prepares a port,
which is what the hardware actually requires.
No ACP change is involved: the tested kernel does not carry the
INFO_RESUME patch. Same machine, s2idle for 8 min 51 s with 526 s of S0i3
residency, px13-audio-restore workaround service disabled:
PDE23 req=0x0 act=0x0 DPn_PrepareStatus 0x0 / 0x0 audio after
resume, with no user intervention at all
Two remarks
===========
Niranjan, Shenghao -- the hw_free() path still writes PS3, and with this
patch the power-up now happens in port prepare while the power-down stays
in hw_free(). That asymmetry works, but if you would rather have the
power-down move to the POST_DEPREP case for symmetry, say so and I will
respin. I left it alone because hw_free() is also the point where the
stream is removed from the slave, and I did not want to change the
power-down timing while fixing the power-up.
Pierre-Louis, my question about simple_ch_prep_sm from the previous mail
stands, and this result sharpens it: the failure was silent for months
only because the core skips the NOT_PREPARED poll for this codec. Had it
polled, sdw_prep_deprep_slave_port() would have printed "Chn prep failed
for port 1" on the first resume. Whatever happens to this patch, TI may
want to reconsider that property.
Thanks,
Andrey
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-12 21:29 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 9:33 ASoC: tas2783-sdw: port prepare never completes after S0i3, no audio and no error (AMD ACP7.0, ASUS ProArt PX13) Andrey Golovko
2026-07-27 14:08 ` Pierre-Louis Bossart
2026-07-28 7:31 ` Holalu Yogendra, Niranjan
2026-08-07 5:21 ` Andrey Golovko
2026-08-12 18:24 ` Andrey Golovko
2026-08-12 21:29 ` Andrey Golovko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox