Re: [RFC PATCH] ASoC: qcom: q6apm-lpass-dais: start the graph at prepare
From: Jorijn van der Graaf
Date: Wed Jul 08 2026 - 17:59:42 EST
[ +Cc Dmitry Baryshkov and Jianfeng Liu for the drm/msm/dp DP-audio
context, and Mohammad Rafi Shaik for the MI2S clock series test
report below ]
On Wed, Jul 08, 2026 at 03:05:39PM +0100, Mark Brown wrote:
> On Sun, Jul 05, 2026 at 05:38:30AM +0200, Jorijn van der Graaf wrote:
>
> > Sending as RFC because this changes when the port starts clocking for
> > every AudioReach platform, and I may be missing the reason the start
> > was placed in trigger rather than prepare in the first place:
>
> > - Is there a downside to starting the graph at prepare on AudioReach
> > (power, pop/click, or DSP-side constraints)? The legacy q6afe stack
> > has started its ports at the end of prepare all along, and the FE
> > side of AudioReach already starts its graph in q6apm_dai_prepare().
>
> There was previously a move in the opposite direction in b54a38af7138
> (ASoC: qcom: q6apm-lpass-dai: move graph start to trigger) - the commit
> there mentions some issues with PipeWire?
Thanks, that's exactly the context I was missing - I had checked the
state of the file on the submission base but not the history of the
lines I was moving. Having read up on it now: b54a38af7138 fixes a real
problem, and this patch as-is would reintroduce it for the DisplayPort
DAIs. Here is what I found.
Since 98a8920e7b07 ("drm/msm/dp: reuse generic HDMI codec
implementation", v6.16) the msm DP audio configuration runs from
hdmi-codec's .prepare (drm_hdmi_audio_helper wires .prepare but not
.hw_params). Within a BE link the CPU DAI prepares before the codec
DAI, so a prepare-time q6apm_graph_start() asks the DSP to start
DISPLAY_PORT_RX before the DP controller's audio engine is configured,
and the DSP rejects it. DP audio on AudioReach platforms was reported
broken this way from v6.16 until b54a38af7138 went in:
https://lore.kernel.org/all/20250925040530.20731-1-liujianfeng1994@xxxxxxxxx/
That thread also has Jianfeng Liu's proposed DRM-side fix (wiring
.hw_params to the same helper), which Srinivas was fine with but Dmitry
argued is incorrect since the IEC 958 channel status isn't known at
hw_params time; as far as I can see it never landed, and the thread
ends with Dmitry noting his understanding that the issue should be
fixed by what became b54a38af7138. The legacy q6afe stack, which starts
its port at prepare, hit the same ordering problem on
qcm6490-fairphone-fp5:
https://lore.kernel.org/all/DD8PK8AI24P7.YK0OGVYC0QFM@xxxxxxxxxxxxx/
b54a38af7138's commit message itself also cites PipeWire being unhappy
when the DP is not connected during start - presumably because with the
start at trigger, an open-but-idle DP PCM never attempts it.
I cannot exercise the DP path on my hardware - the FP6 has no DP audio
DAI link, so my testing (PipeWire, playback and capture) only covers
MI2S and codec DMA.
I also tested whether the in-flight "ASoC: qcom: qdsp6: Add MI2S clock
control" series can solve the aw88261 case without touching the graph
start:
https://lore.kernel.org/all/20260706132009.1496321-1-mohammad.rafi.shaik@xxxxxxxxxxxxxxxx/
I carried it onto the v7.1.2-based tree my board runs, wired the
FP6's Senary MI2S DAI to the q6prm SEN_MI2S_IBIT clock ("bclk" in the
new dai@ subnode) and enabled the machine-level bclk vote. The
plumbing works as intended - during the stream clk_summary shows the
clock enabled at the right rate (1536000 for 48 kHz 2ch S16) - but
the amplifiers still report "no clocks" (SYSST) through their
power-up check at prepare and fail to start. On this platform, at
least for Senary MI2S, the interface only drives the pads once the
graph has started, so the clock vote alone does not help a codec
that needs the bit clock before APM_CMD_GRAPH_START; conversely,
with the graph started at prepare the same codec powers up with no
clock vote at all. Happy to share the details in that series' thread
if useful (its patch 3/3 also overlaps the Senary set_fmt one-liner
I sent for sc8280xp, which I would coordinate there).
So for v2 I would keep the two behaviours apart per interface type:
start the graph at the end of prepare only for the MI2S DAIs
(q6i2s_ops), where an external codec like aw88261 needs the bit clock
running before the DAPM power-up sequence and where q6afe has always
started the port at prepare. b54a38af7138's other point - that there is
no data transfer yet at prepare - still holds there, but for these
interfaces the early start is about the clocking, not the data. The
trigger-time start stays unchanged for the DP/HDMI DAIs (q6hdmi_ops,
where the prepare-time start is exactly what broke) and the codec DMA
DAIs (q6dma_ops - codecs clocked from the LPASS macros or SoundWire,
not from the port). That also supersedes my note under the fold about
dropping the trigger callback in a respin: it stays, as the only start
path for the DP/HDMI and codec DMA DAIs.
Srinivas, since b54a38af7138 is yours: does that split sound
reasonable, or is there a DSP-side reason the MI2S ports should not
start at prepare either? And since I cannot test the DP side, it would
be great if someone with DP-capable AudioReach hardware (an X Elite
laptop or a QCS6490 board) could give v2 a spin there.
Thanks,
Jorijn