* [PATCH v3 01/14] ASoC: qcom: q6apm: move component registration to unmanaged version
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
@ 2026-03-04 13:06 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 02/14] ASoC: qcom: q6apm: remove child devices when apm is removed Srinivas Kandagatla
` (13 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:06 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
q6apm component registers dais dynamically from ASoC toplology, which
are allocated using device managed version apis. Allocating both
component and dynamic dais using managed version could lead to incorrect
free ordering, dai will be freed while component still holding references
to it.
Fix this issue by moving component to unmanged version so
that the dai pointers are only freeded after the component is removed.
==================================================================
BUG: KASAN: slab-use-after-free in snd_soc_del_component_unlocked+0x3d4/0x400 [snd_soc_core]
Read of size 8 at addr ffff00084493a6e8 by task kworker/u48:0/3426
Tainted: [W]=WARN
Hardware name: LENOVO 21N2ZC5PUS/21N2ZC5PUS, BIOS N42ET57W (1.31 ) 08/08/2024
Workqueue: pdr_notifier_wq pdr_notifier_work [pdr_interface]
Call trace:
show_stack+0x28/0x7c (C)
dump_stack_lvl+0x60/0x80
print_report+0x160/0x4b4
kasan_report+0xac/0xfc
__asan_report_load8_noabort+0x20/0x34
snd_soc_del_component_unlocked+0x3d4/0x400 [snd_soc_core]
snd_soc_unregister_component_by_driver+0x50/0x88 [snd_soc_core]
devm_component_release+0x30/0x5c [snd_soc_core]
devres_release_all+0x13c/0x210
device_unbind_cleanup+0x20/0x190
device_release_driver_internal+0x350/0x468
device_release_driver+0x18/0x30
bus_remove_device+0x1a0/0x35c
device_del+0x314/0x7f0
device_unregister+0x20/0xbc
apr_remove_device+0x5c/0x7c [apr]
device_for_each_child+0xd8/0x160
apr_pd_status+0x7c/0xa8 [apr]
pdr_notifier_work+0x114/0x240 [pdr_interface]
process_one_work+0x500/0xb70
worker_thread+0x630/0xfb0
kthread+0x370/0x6c0
ret_from_fork+0x10/0x20
Allocated by task 77:
kasan_save_stack+0x40/0x68
kasan_save_track+0x20/0x40
kasan_save_alloc_info+0x44/0x58
__kasan_kmalloc+0xbc/0xdc
__kmalloc_node_track_caller_noprof+0x1f4/0x620
devm_kmalloc+0x7c/0x1c8
snd_soc_register_dai+0x50/0x4f0 [snd_soc_core]
soc_tplg_pcm_elems_load+0x55c/0x1eb8 [snd_soc_core]
snd_soc_tplg_component_load+0x4f8/0xb60 [snd_soc_core]
audioreach_tplg_init+0x124/0x1fc [snd_q6apm]
q6apm_audio_probe+0x10/0x1c [snd_q6apm]
snd_soc_component_probe+0x5c/0x118 [snd_soc_core]
soc_probe_component+0x44c/0xaf0 [snd_soc_core]
snd_soc_bind_card+0xad0/0x2370 [snd_soc_core]
snd_soc_register_card+0x3b0/0x4c0 [snd_soc_core]
devm_snd_soc_register_card+0x50/0xc8 [snd_soc_core]
x1e80100_platform_probe+0x208/0x368 [snd_soc_x1e80100]
platform_probe+0xc0/0x188
really_probe+0x188/0x804
__driver_probe_device+0x158/0x358
driver_probe_device+0x60/0x190
__device_attach_driver+0x16c/0x2a8
bus_for_each_drv+0x100/0x194
__device_attach+0x174/0x380
device_initial_probe+0x14/0x20
bus_probe_device+0x124/0x154
deferred_probe_work_func+0x140/0x220
process_one_work+0x500/0xb70
worker_thread+0x630/0xfb0
kthread+0x370/0x6c0
ret_from_fork+0x10/0x20
Freed by task 3426:
kasan_save_stack+0x40/0x68
kasan_save_track+0x20/0x40
__kasan_save_free_info+0x4c/0x80
__kasan_slab_free+0x78/0xa0
kfree+0x100/0x4a4
devres_release_all+0x144/0x210
device_unbind_cleanup+0x20/0x190
device_release_driver_internal+0x350/0x468
device_release_driver+0x18/0x30
bus_remove_device+0x1a0/0x35c
device_del+0x314/0x7f0
device_unregister+0x20/0xbc
apr_remove_device+0x5c/0x7c [apr]
device_for_each_child+0xd8/0x160
apr_pd_status+0x7c/0xa8 [apr]
pdr_notifier_work+0x114/0x240 [pdr_interface]
process_one_work+0x500/0xb70
worker_thread+0x630/0xfb0
kthread+0x370/0x6c0
ret_from_fork+0x10/0x20
Fixes: 5477518b8a0e ("ASoC: qdsp6: audioreach: add q6apm support")
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index 44841fde3856..a4c662be52e0 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -746,7 +746,7 @@ static int apm_probe(gpr_device_t *gdev)
q6apm_get_apm_state(apm);
- ret = devm_snd_soc_register_component(dev, &q6apm_audio_component, NULL, 0);
+ ret = snd_soc_register_component(dev, &q6apm_audio_component, NULL, 0);
if (ret < 0) {
dev_err(dev, "failed to register q6apm: %d\n", ret);
return ret;
@@ -755,6 +755,11 @@ static int apm_probe(gpr_device_t *gdev)
return of_platform_populate(dev->of_node, NULL, NULL, dev);
}
+static void apm_remove(gpr_device_t *gdev)
+{
+ snd_soc_unregister_component(&gdev->dev);
+}
+
struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph, uint32_t mid)
{
struct audioreach_graph_info *info = graph->info;
@@ -819,6 +824,7 @@ MODULE_DEVICE_TABLE(of, apm_device_id);
static gpr_driver_t apm_driver = {
.probe = apm_probe,
+ .remove = apm_remove,
.gpr_callback = apm_callback,
.driver = {
.name = "qcom-apm",
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 02/14] ASoC: qcom: q6apm: remove child devices when apm is removed
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
2026-03-04 13:06 ` [PATCH v3 01/14] ASoC: qcom: q6apm: move component registration to unmanaged version Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 03/14] ASoC: qcom: qdsp6: topology: check widget type before accessing data Srinivas Kandagatla
` (12 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
looks like q6apm driver does not remove the child driver q6apm-dai and
q6apm-bedais when the this driver is removed.
Fix this by using a manage version of of_platfom_populate.
With this change when the dsp is shutdown all the devices associated with
q6apm will now be removed.
Fixes: 5477518b8a0e ("ASoC: qdsp6: audioreach: add q6apm support")
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index a4c662be52e0..ebd5e3ac0366 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -752,7 +752,7 @@ static int apm_probe(gpr_device_t *gdev)
return ret;
}
- return of_platform_populate(dev->of_node, NULL, NULL, dev);
+ return devm_of_platform_populate(dev);
}
static void apm_remove(gpr_device_t *gdev)
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 03/14] ASoC: qcom: qdsp6: topology: check widget type before accessing data
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
2026-03-04 13:06 ` [PATCH v3 01/14] ASoC: qcom: q6apm: move component registration to unmanaged version Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 02/14] ASoC: qcom: q6apm: remove child devices when apm is removed Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 04/14] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens Srinivas Kandagatla
` (11 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Check widget type before accessing the private data, as this could a
virtual widget which is no associated with a dsp graph, container and
module. Accessing witout check could lead to incorrect memory access.
Fixes: 36ad9bf1d93d ("ASoC: qdsp6: audioreach: add topology support")
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/topology.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c
index e732fac9b8ca..1f69fba6de26 100644
--- a/sound/soc/qcom/qdsp6/topology.c
+++ b/sound/soc/qcom/qdsp6/topology.c
@@ -952,9 +952,6 @@ static int audioreach_widget_unload(struct snd_soc_component *scomp,
struct audioreach_container *cont;
struct audioreach_module *mod;
- mod = dobj->private;
- cont = mod->container;
-
if (w->id == snd_soc_dapm_mixer) {
/* virtual widget */
struct snd_ar_control *scontrol = dobj->private;
@@ -963,6 +960,11 @@ static int audioreach_widget_unload(struct snd_soc_component *scomp,
kfree(scontrol);
return 0;
}
+ mod = dobj->private;
+ if (!mod)
+ return 0;
+
+ cont = mod->container;
mutex_lock(&apm->lock);
idr_remove(&apm->modules_idr, mod->instance_id);
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 04/14] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (2 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 03/14] ASoC: qcom: qdsp6: topology: check widget type before accessing data Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 05/14] ASoC: qcom: q6apm-dai: reset queue ptr on trigger stop Srinivas Kandagatla
` (10 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla, Stable
As prepare can be called mulitple times, this can result in multiple
graph opens for playback path.
This will result in a memory leaks, fix this by adding a check before
opening.
Fixes: be1fae62cf25 ("ASoC: q6apm-lpass-dai: close graph on prepare errors")
Cc: Stable@vger.kernel.org
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index 528756f1332b..f68d4b4974f3 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
* It is recommend to load DSP with source graph first and then sink
* graph, so sequence for playback and capture will be different
*/
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
if (IS_ERR(graph)) {
dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 05/14] ASoC: qcom: q6apm-dai: reset queue ptr on trigger stop
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (3 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 04/14] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids Srinivas Kandagatla
` (9 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla, Stable
Reset queue pointer on SNDRV_PCM_TRIGGER_STOP event to be inline
with resetting appl_ptr. Without this we will end up with a queue_ptr
out of sync and driver could try to send data that is not ready yet.
Fix this by resetting the queue_ptr.
Fixes: 3d4a4411aa8bb ("ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs")
Cc: Stable@vger.kernel.org
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm-dai.c | 1 +
sound/soc/qcom/qdsp6/q6apm.c | 2 ++
2 files changed, 3 insertions(+)
diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
index de3bdac3e791..3eff45b241c9 100644
--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
@@ -317,6 +317,7 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
case SNDRV_PCM_TRIGGER_STOP:
/* TODO support be handled via SoftPause Module */
prtd->state = Q6APM_STREAM_STOPPED;
+ prtd->queue_ptr = 0;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index ebd5e3ac0366..f190ad5e912a 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -215,6 +215,8 @@ int q6apm_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, phys_a
mutex_lock(&graph->lock);
+ data->dsp_buf = 0;
+
if (data->buf) {
mutex_unlock(&graph->lock);
return 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (4 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 05/14] ASoC: qcom: q6apm-dai: reset queue ptr on trigger stop Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-05 7:21 ` Krzysztof Kozlowski
2026-03-05 7:54 ` Krzysztof Kozlowski
2026-03-04 13:07 ` [PATCH v3 07/14] ASoC: qcom: qdsp6: lpass-ports: add support for LPASS LPI MI2S dais Srinivas Kandagatla
` (8 subsequent siblings)
14 siblings, 2 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Add new dai ids entries for LPASS LPI MI2S lines.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
index 6d1ce7f5da51..e27a31ece1f2 100644
--- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
+++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
@@ -140,6 +140,16 @@
#define DISPLAY_PORT_RX_6 134
#define DISPLAY_PORT_RX_7 135
#define USB_RX 136
+#define LPI_MI2S_RX_0 137
+#define LPI_MI2S_TX_0 138
+#define LPI_MI2S_RX_1 139
+#define LPI_MI2S_TX_1 140
+#define LPI_MI2S_RX_2 141
+#define LPI_MI2S_TX_2 142
+#define LPI_MI2S_RX_3 143
+#define LPI_MI2S_TX_3 144
+#define LPI_MI2S_RX_4 145
+#define LPI_MI2S_TX_4 146
#define LPASS_CLK_ID_PRI_MI2S_IBIT 1
#define LPASS_CLK_ID_PRI_MI2S_EBIT 2
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids
2026-03-04 13:07 ` [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids Srinivas Kandagatla
@ 2026-03-05 7:21 ` Krzysztof Kozlowski
2026-03-05 7:54 ` Krzysztof Kozlowski
1 sibling, 0 replies; 20+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-05 7:21 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: broonie, robh, krzk+dt, conor+dt, mohammad.rafi.shaik,
linux-sound, lgirdwood, perex, tiwai, johan, dmitry.baryshkov,
konrad.dybcio, linux-arm-msm, devicetree, linux-kernel, srini
On Wed, Mar 04, 2026 at 01:07:04PM +0000, Srinivas Kandagatla wrote:
> Add new dai ids entries for LPASS LPI MI2S lines.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
> ---
> include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids
2026-03-04 13:07 ` [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids Srinivas Kandagatla
2026-03-05 7:21 ` Krzysztof Kozlowski
@ 2026-03-05 7:54 ` Krzysztof Kozlowski
1 sibling, 0 replies; 20+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-05 7:54 UTC (permalink / raw)
To: Srinivas Kandagatla, broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini
On 04/03/2026 14:07, Srinivas Kandagatla wrote:
> Add new dai ids entries for LPASS LPI MI2S lines.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
> ---
> include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
> index 6d1ce7f5da51..e27a31ece1f2 100644
> --- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
> +++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
> @@ -140,6 +140,16 @@
> #define DISPLAY_PORT_RX_6 134
> #define DISPLAY_PORT_RX_7 135
> #define USB_RX 136
> +#define LPI_MI2S_RX_0 137
> +#define LPI_MI2S_TX_0 138
> +#define LPI_MI2S_RX_1 139
> +#define LPI_MI2S_TX_1 140
> +#define LPI_MI2S_RX_2 141
> +#define LPI_MI2S_TX_2 142
> +#define LPI_MI2S_RX_3 143
> +#define LPI_MI2S_TX_3 144
> +#define LPI_MI2S_RX_4 145
> +#define LPI_MI2S_TX_4 146
And no need to update the bindings? See Richard's patches.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 07/14] ASoC: qcom: qdsp6: lpass-ports: add support for LPASS LPI MI2S dais
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (5 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 06/14] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 08/14] ASoC: dt-bindings: qcom,q6dsp-lpass-ports: Add Senary MI2S port Srinivas Kandagatla
` (7 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Add support for LPASS LPI MI2S dais in the dai-driver, these dais are
used in Monaco based platform devices.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c | 47 ++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
index 4eed54b071a5..d31388ed3ccf 100644
--- a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
+++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
@@ -96,6 +96,42 @@
.id = did, \
}
+#define Q6AFE_MI2S_RX_DAI(pre, did) { \
+ .playback = { \
+ .stream_name = pre" MI2S Playback", \
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_176400, \
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels_min = 1, \
+ .channels_max = 8, \
+ .rate_min = 8000, \
+ .rate_max = 176400, \
+ }, \
+ .name = #did, \
+ .id = did, \
+ }
+
+#define Q6AFE_MI2S_TX_DAI(pre, did) { \
+ .capture = { \
+ .stream_name = pre" MI2S Capture", \
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_176400, \
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels_min = 1, \
+ .channels_max = 8, \
+ .rate_min = 8000, \
+ .rate_max = 176400, \
+ }, \
+ .name = #did, \
+ .id = did, \
+ }
+
static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {
{
.playback = {
@@ -484,6 +520,16 @@ static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {
.id = QUINARY_MI2S_TX,
.name = "QUIN_MI2S_TX",
},
+ Q6AFE_MI2S_RX_DAI("LPI RX0", LPI_MI2S_RX_0),
+ Q6AFE_MI2S_RX_DAI("LPI RX1", LPI_MI2S_RX_1),
+ Q6AFE_MI2S_RX_DAI("LPI RX2", LPI_MI2S_RX_2),
+ Q6AFE_MI2S_RX_DAI("LPI RX3", LPI_MI2S_RX_3),
+ Q6AFE_MI2S_RX_DAI("LPI RX4", LPI_MI2S_RX_4),
+ Q6AFE_MI2S_TX_DAI("LPI TX0", LPI_MI2S_TX_0),
+ Q6AFE_MI2S_TX_DAI("LPI TX1", LPI_MI2S_TX_1),
+ Q6AFE_MI2S_TX_DAI("LPI TX2", LPI_MI2S_TX_2),
+ Q6AFE_MI2S_TX_DAI("LPI TX3", LPI_MI2S_TX_3),
+ Q6AFE_MI2S_TX_DAI("LPI TX4", LPI_MI2S_TX_4),
Q6AFE_TDM_PB_DAI("Primary", 0, PRIMARY_TDM_RX_0),
Q6AFE_TDM_PB_DAI("Primary", 1, PRIMARY_TDM_RX_1),
Q6AFE_TDM_PB_DAI("Primary", 2, PRIMARY_TDM_RX_2),
@@ -636,6 +682,7 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev,
break;
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
+ case LPI_MI2S_RX_0 ... LPI_MI2S_TX_4:
q6dsp_audio_fe_dais[i].ops = cfg->q6i2s_ops;
break;
case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7:
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 08/14] ASoC: dt-bindings: qcom,q6dsp-lpass-ports: Add Senary MI2S port
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (6 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 07/14] ASoC: qcom: qdsp6: lpass-ports: add support for LPASS LPI MI2S dais Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-05 7:23 ` Krzysztof Kozlowski
2026-03-04 13:07 ` [PATCH v3 09/14] ASoC: qcom: q6dsp: Add Senary MI2S audio interface support Srinivas Kandagatla
` (6 subsequent siblings)
14 siblings, 1 reply; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
From: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Qualcomm platforms support the Senary MI2S interface for audio playback
and capture. Add a new definitions for the Senary MI2S RX and TX ports,
which are required for boards that utilize the Senary MI2S interface
for audio routing.
Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
index e27a31ece1f2..45850f2d4342 100644
--- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
+++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
@@ -150,6 +150,8 @@
#define LPI_MI2S_TX_3 144
#define LPI_MI2S_RX_4 145
#define LPI_MI2S_TX_4 146
+#define SENARY_MI2S_RX 147
+#define SENARY_MI2S_TX 148
#define LPASS_CLK_ID_PRI_MI2S_IBIT 1
#define LPASS_CLK_ID_PRI_MI2S_EBIT 2
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 08/14] ASoC: dt-bindings: qcom,q6dsp-lpass-ports: Add Senary MI2S port
2026-03-04 13:07 ` [PATCH v3 08/14] ASoC: dt-bindings: qcom,q6dsp-lpass-ports: Add Senary MI2S port Srinivas Kandagatla
@ 2026-03-05 7:23 ` Krzysztof Kozlowski
0 siblings, 0 replies; 20+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-05 7:23 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: broonie, robh, krzk+dt, conor+dt, mohammad.rafi.shaik,
linux-sound, lgirdwood, perex, tiwai, johan, dmitry.baryshkov,
konrad.dybcio, linux-arm-msm, devicetree, linux-kernel, srini
On Wed, Mar 04, 2026 at 01:07:06PM +0000, Srinivas Kandagatla wrote:
> From: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
>
> Qualcomm platforms support the Senary MI2S interface for audio playback
> and capture. Add a new definitions for the Senary MI2S RX and TX ports,
> which are required for boards that utilize the Senary MI2S interface
> for audio routing.
>
This should be squashed. Adding IDs in multiple patches is pointless -
it's one logical change. Plus patch is so trivial and obvious that even
preserving authorship cannot be used as an argument.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 09/14] ASoC: qcom: q6dsp: Add Senary MI2S audio interface support
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (7 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 08/14] ASoC: dt-bindings: qcom,q6dsp-lpass-ports: Add Senary MI2S port Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 10/14] ASoC: qcom: common: validate cpu dai id during parsing Srinivas Kandagatla
` (5 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
From: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Introduces support for the Senary MI2S audio interface in the Qualcomm
q6dsp. Add new AFE port IDs for Senary MI2S RX and TX and include the
necessary mappings in the port configuration to allow audio routing
over the Senary MI2S interface.
Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6afe-dai.c | 6 +++++
sound/soc/qcom/qdsp6/q6afe.c | 6 +++++
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c | 29 ++++++++++++++++++++++++
3 files changed, 41 insertions(+)
diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c
index 0f47aadaabe1..a0d21034a626 100644
--- a/sound/soc/qcom/qdsp6/q6afe-dai.c
+++ b/sound/soc/qcom/qdsp6/q6afe-dai.c
@@ -409,6 +409,7 @@ static int q6afe_dai_prepare(struct snd_pcm_substream *substream,
q6afe_slim_port_prepare(dai_data->port[dai->id],
&dai_data->port_config[dai->id].slim);
break;
+ case SENARY_MI2S_RX ... SENARY_MI2S_TX:
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
rc = q6afe_i2s_port_prepare(dai_data->port[dai->id],
@@ -540,6 +541,7 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
{"Tertiary MI2S Playback", NULL, "TERT_MI2S_RX"},
{"Quaternary MI2S Playback", NULL, "QUAT_MI2S_RX"},
{"Quinary MI2S Playback", NULL, "QUIN_MI2S_RX"},
+ {"Senary MI2S Playback", NULL, "SEN_MI2S_RX"},
{"Primary TDM0 Playback", NULL, "PRIMARY_TDM_RX_0"},
{"Primary TDM1 Playback", NULL, "PRIMARY_TDM_RX_1"},
@@ -636,6 +638,7 @@ static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
{"SEC_MI2S_TX", NULL, "Secondary MI2S Capture"},
{"QUAT_MI2S_TX", NULL, "Quaternary MI2S Capture"},
{"QUIN_MI2S_TX", NULL, "Quinary MI2S Capture"},
+ {"SEN_MI2S_TX", NULL, "Senary MI2S Capture"},
{"WSA_CODEC_DMA_RX_0 Playback", NULL, "WSA_CODEC_DMA_RX_0"},
{"WSA_CODEC_DMA_TX_0", NULL, "WSA_CODEC_DMA_TX_0 Capture"},
@@ -770,6 +773,8 @@ static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SEN_MI2S_RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SEN_MI2S_TX", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_MI2S_RX", NULL,
0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_TX", NULL,
@@ -1037,6 +1042,7 @@ static void of_q6afe_parse_dai_data(struct device *dev,
switch (id) {
/* MI2S specific properties */
+ case SENARY_MI2S_RX ... SENARY_MI2S_TX:
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
priv = &data->priv[id];
diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
index 43d877322bae..7bd40e32f758 100644
--- a/sound/soc/qcom/qdsp6/q6afe.c
+++ b/sound/soc/qcom/qdsp6/q6afe.c
@@ -130,6 +130,8 @@
#define AFE_PORT_ID_QUATERNARY_MI2S_TX 0x1007
#define AFE_PORT_ID_QUINARY_MI2S_RX 0x1016
#define AFE_PORT_ID_QUINARY_MI2S_TX 0x1017
+#define AFE_PORT_ID_SENARY_MI2S_RX 0x1018
+#define AFE_PORT_ID_SENARY_MI2S_TX 0x1019
/* Start of the range of port IDs for TDM devices. */
#define AFE_PORT_ID_TDM_PORT_RANGE_START 0x9000
@@ -718,6 +720,10 @@ static struct afe_port_map port_maps[AFE_PORT_MAX] = {
QUINARY_MI2S_RX, 1, 1},
[QUINARY_MI2S_TX] = { AFE_PORT_ID_QUINARY_MI2S_TX,
QUINARY_MI2S_TX, 0, 1},
+ [SENARY_MI2S_RX] = { AFE_PORT_ID_SENARY_MI2S_RX,
+ SENARY_MI2S_RX, 1, 1},
+ [SENARY_MI2S_TX] = { AFE_PORT_ID_SENARY_MI2S_TX,
+ SENARY_MI2S_TX, 0, 1},
[PRIMARY_TDM_RX_0] = { AFE_PORT_ID_PRIMARY_TDM_RX,
PRIMARY_TDM_RX_0, 1, 1},
[PRIMARY_TDM_TX_0] = { AFE_PORT_ID_PRIMARY_TDM_TX,
diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
index d31388ed3ccf..e5cd82f77b55 100644
--- a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
+++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
@@ -519,6 +519,34 @@ static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {
},
.id = QUINARY_MI2S_TX,
.name = "QUIN_MI2S_TX",
+ }, {
+ .playback = {
+ .stream_name = "Senary MI2S Playback",
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ },
+ .id = SENARY_MI2S_RX,
+ .name = "SEN_MI2S_RX",
+ }, {
+ .capture = {
+ .stream_name = "Senary MI2S Capture",
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ },
+ .id = SENARY_MI2S_TX,
+ .name = "SEN_MI2S_TX",
},
Q6AFE_MI2S_RX_DAI("LPI RX0", LPI_MI2S_RX_0),
Q6AFE_MI2S_RX_DAI("LPI RX1", LPI_MI2S_RX_1),
@@ -680,6 +708,7 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev,
case SLIMBUS_0_RX ... SLIMBUS_6_TX:
q6dsp_audio_fe_dais[i].ops = cfg->q6slim_ops;
break;
+ case SENARY_MI2S_RX ... SENARY_MI2S_TX:
case QUINARY_MI2S_RX ... QUINARY_MI2S_TX:
case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX:
case LPI_MI2S_RX_0 ... LPI_MI2S_TX_4:
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 10/14] ASoC: qcom: common: validate cpu dai id during parsing
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (8 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 09/14] ASoC: qcom: q6dsp: Add Senary MI2S audio interface support Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 11/14] ASoC: qcom: qdapm-lpass-dai: correct the error message Srinivas Kandagatla
` (4 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
lpass ports numbers have been added but the afe/apm driver never got
updated with new max port value that it uses to store dai specific data.
There are more than one places these values are cached and always become
out of sync.
This will result in array out of bounds and weird driver behaviour.
To catch such issues, first add a single place where we can define max
port and second add a check in common parsing code which can error
out before corrupting the memory with out of bounds array access.
This should help both avoid and catch these type of mistakes in future.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/common.c | 6 ++++++
sound/soc/qcom/common.h | 3 +++
sound/soc/qcom/lpass.h | 3 ++-
sound/soc/qcom/qdsp6/q6afe.h | 3 ++-
sound/soc/qcom/qdsp6/q6apm.h | 3 ++-
5 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index 7ee60a58a336..878b42babcc3 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -120,6 +120,12 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
link->id = args.args[0];
+ if (link->id > LPASS_MAX_PORT) {
+ dev_err(dev, "%s: Invalid cpu dai id %d\n", link->name, link->id);
+ ret = -EINVAL;
+ goto err;
+ }
+
if (platform) {
link->platforms->of_node = of_parse_phandle(platform,
"sound-dai",
diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h
index 1b8d3f90bffa..ee6662885593 100644
--- a/sound/soc/qcom/common.h
+++ b/sound/soc/qcom/common.h
@@ -4,8 +4,11 @@
#ifndef __QCOM_SND_COMMON_H__
#define __QCOM_SND_COMMON_H__
+#include <dt-bindings/sound/qcom,q6afe.h>
#include <sound/soc.h>
+#define LPASS_MAX_PORT (SENARY_MI2S_TX + 1)
+
int qcom_snd_parse_of(struct snd_soc_card *card);
int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
struct snd_soc_jack *jack, bool *jack_setup);
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
index de3ec6f594c1..68b71039b981 100644
--- a/sound/soc/qcom/lpass.h
+++ b/sound/soc/qcom/lpass.h
@@ -14,10 +14,11 @@
#include <linux/regmap.h>
#include <dt-bindings/sound/qcom,lpass.h>
#include <dt-bindings/sound/qcom,q6afe.h>
+#include "common.h"
#include "lpass-hdmi.h"
#define LPASS_AHBIX_CLOCK_FREQUENCY 131072000
-#define LPASS_MAX_PORTS (DISPLAY_PORT_RX_7 + 1)
+#define LPASS_MAX_PORTS (LPASS_MAX_PORT)
#define LPASS_MAX_MI2S_PORTS (8)
#define LPASS_MAX_DMA_CHANNELS (8)
#define LPASS_MAX_HDMI_DMA_CHANNELS (4)
diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h
index a29abe4ce436..0b8c3ec1315c 100644
--- a/sound/soc/qcom/qdsp6/q6afe.h
+++ b/sound/soc/qcom/qdsp6/q6afe.h
@@ -2,8 +2,9 @@
#ifndef __Q6AFE_H__
#define __Q6AFE_H__
+#include "../common.h"
-#define AFE_PORT_MAX 137
+#define AFE_PORT_MAX (LPASS_MAX_PORT)
#define MSM_AFE_PORT_TYPE_RX 0
#define MSM_AFE_PORT_TYPE_TX 1
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h
index 7ce08b401e31..5cf538397841 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -14,9 +14,10 @@
#include <linux/of_platform.h>
#include <linux/jiffies.h>
#include <linux/soc/qcom/apr.h>
+#include "../common.h"
#include "audioreach.h"
-#define APM_PORT_MAX 127
+#define APM_PORT_MAX LPASS_MAX_PORT
#define APM_PORT_MAX_AUDIO_CHAN_CNT 8
#define PCM_CHANNEL_NULL 0
#define PCM_CHANNEL_FL 1 /* Front left channel. */
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 11/14] ASoC: qcom: qdapm-lpass-dai: correct the error message
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (9 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 10/14] ASoC: qcom: common: validate cpu dai id during parsing Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 12/14] ASoC: qcom: q6apm-lpass-dai: move graph start to trigger Srinivas Kandagatla
` (3 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Fix the error message to reflect the actual graph stop error
instead of graph close error.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index f68d4b4974f3..472b2114c81e 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -150,7 +150,7 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct
rc = q6apm_graph_stop(dai_data->graph[dai->id]);
dai_data->is_port_started[dai->id] = false;
if (rc < 0)
- dev_err(dai->dev, "fail to close APM port (%d)\n", rc);
+ dev_err(dai->dev, "failed to stop APM port (%d)\n", rc);
}
if (dai_data->graph[dai->id]) {
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 12/14] ASoC: qcom: q6apm-lpass-dai: move graph start to trigger
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (10 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 11/14] ASoC: qcom: qdapm-lpass-dai: correct the error message Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 13/14] ASoC: qcom: qdsp6: remove search for module iid in hot path Srinivas Kandagatla
` (2 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Start the graph at trigger callback. Staring the graph at prepare does
not make sense as there is no data transfer at this point.
Moving this to trigger will also help cope situation where pipewire
is not happy if display port is not connected during start.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 40 +++++++++++++++++--------
1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index 472b2114c81e..70e283671f43 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -159,6 +159,31 @@ static void q6apm_lpass_dai_shutdown(struct snd_pcm_substream *substream, struct
}
}
+static int q6apm_lpass_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!dai_data->is_port_started[dai->id]) {
+ ret = q6apm_graph_start(dai_data->graph[dai->id]);
+ if (ret < 0)
+ dev_err(dai->dev, "Failed to start APM port %d\n", dai->id);
+ else
+ dai_data->is_port_started[dai->id] = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{
struct q6apm_lpass_dai_data *dai_data = dev_get_drvdata(dai->dev);
@@ -171,10 +196,6 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
q6apm_graph_stop(dai_data->graph[dai->id]);
dai_data->is_port_started[dai->id] = false;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- q6apm_graph_close(dai_data->graph[dai->id]);
- dai_data->graph[dai->id] = NULL;
- }
}
/**
@@ -203,14 +224,6 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
dev_err(dai->dev, "Failed to prepare Graph %d\n", rc);
goto err;
}
-
- rc = q6apm_graph_start(dai_data->graph[dai->id]);
- if (rc < 0) {
- dev_err(dai->dev, "Failed to start APM port %d\n", dai->id);
- goto err;
- }
- dai_data->is_port_started[dai->id] = true;
-
return 0;
err:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -254,6 +267,7 @@ static const struct snd_soc_dai_ops q6dma_ops = {
.shutdown = q6apm_lpass_dai_shutdown,
.set_channel_map = q6dma_set_channel_map,
.hw_params = q6dma_hw_params,
+ .trigger = q6apm_lpass_dai_trigger,
};
static const struct snd_soc_dai_ops q6i2s_ops = {
@@ -263,6 +277,7 @@ static const struct snd_soc_dai_ops q6i2s_ops = {
.set_channel_map = q6dma_set_channel_map,
.hw_params = q6dma_hw_params,
.set_fmt = q6i2s_set_fmt,
+ .trigger = q6apm_lpass_dai_trigger,
};
static const struct snd_soc_dai_ops q6hdmi_ops = {
@@ -271,6 +286,7 @@ static const struct snd_soc_dai_ops q6hdmi_ops = {
.shutdown = q6apm_lpass_dai_shutdown,
.hw_params = q6hdmi_hw_params,
.set_fmt = q6i2s_set_fmt,
+ .trigger = q6apm_lpass_dai_trigger,
};
static const struct snd_soc_component_driver q6apm_lpass_dai_component = {
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 13/14] ASoC: qcom: qdsp6: remove search for module iid in hot path
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (11 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 12/14] ASoC: qcom: q6apm-lpass-dai: move graph start to trigger Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-04 13:07 ` [PATCH v3 14/14] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP Srinivas Kandagatla
2026-03-05 13:48 ` [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Richard Acayan
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Remove searching for Shared Memory module instance id on every
read/write call, this is un-necessary if we can cache the shared
memory module instance id per PCM graph.
Add new member to graph struct to store shared memory module
instance id to avoid searching for this in hot path.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/q6apm-dai.c | 5 +++--
sound/soc/qcom/qdsp6/q6apm-lpass-dais.c | 4 ++--
sound/soc/qcom/qdsp6/q6apm.c | 14 +++++++++-----
sound/soc/qcom/qdsp6/q6apm.h | 3 ++-
4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
index 3eff45b241c9..bdd4cc458acd 100644
--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
@@ -355,7 +355,7 @@ static int q6apm_dai_open(struct snd_soc_component *component,
spin_lock_init(&prtd->lock);
prtd->substream = substream;
- prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id);
+ prtd->graph = q6apm_graph_open(dev, event_handler, prtd, graph_id, substream->stream);
if (IS_ERR(prtd->graph)) {
dev_err(dev, "%s: Could not allocate memory\n", __func__);
ret = PTR_ERR(prtd->graph);
@@ -496,7 +496,8 @@ static int q6apm_dai_compr_open(struct snd_soc_component *component,
return -ENOMEM;
prtd->cstream = stream;
- prtd->graph = q6apm_graph_open(dev, event_handler_compr, prtd, graph_id);
+ prtd->graph = q6apm_graph_open(dev, event_handler_compr, prtd, graph_id,
+ SNDRV_PCM_STREAM_PLAYBACK);
if (IS_ERR(prtd->graph)) {
ret = PTR_ERR(prtd->graph);
kfree(prtd);
diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
index 70e283671f43..aceb2ac9bac8 100644
--- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
+++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
@@ -203,7 +203,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
* graph, so sequence for playback and capture will be different
*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
- graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
+ graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream);
if (IS_ERR(graph)) {
dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
rc = PTR_ERR(graph);
@@ -240,7 +240,7 @@ static int q6apm_lpass_dai_startup(struct snd_pcm_substream *substream, struct s
int graph_id = dai->id;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
+ graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id, substream->stream);
if (IS_ERR(graph)) {
dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
return PTR_ERR(graph);
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index f190ad5e912a..7ef6ae0b1759 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -411,12 +411,11 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
{
struct apm_data_cmd_wr_sh_mem_ep_data_buffer_v2 *write_buffer;
struct audio_buffer *ab;
- int iid = q6apm_graph_get_rx_shmem_module_iid(graph);
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*write_buffer),
DATA_CMD_WR_SH_MEM_EP_DATA_BUFFER_V2,
graph->rx_data.dsp_buf | (len << APM_WRITE_TOKEN_LEN_SHIFT),
- graph->port->id, iid);
+ graph->port->id, graph->shm_iid);
if (IS_ERR(pkt))
return PTR_ERR(pkt);
@@ -449,11 +448,10 @@ int q6apm_read(struct q6apm_graph *graph)
struct data_cmd_rd_sh_mem_ep_data_buffer_v2 *read_buffer;
struct audioreach_graph_data *port;
struct audio_buffer *ab;
- int iid = q6apm_graph_get_tx_shmem_module_iid(graph);
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_pkt(sizeof(*read_buffer),
DATA_CMD_RD_SH_MEM_EP_DATA_BUFFER_V2,
- graph->tx_data.dsp_buf, graph->port->id, iid);
+ graph->tx_data.dsp_buf, graph->port->id, graph->shm_iid);
if (IS_ERR(pkt))
return PTR_ERR(pkt);
@@ -604,7 +602,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
}
struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
- void *priv, int graph_id)
+ void *priv, int graph_id, int dir)
{
struct q6apm *apm = dev_get_drvdata(dev->parent);
struct audioreach_graph *ar_graph;
@@ -631,6 +629,12 @@ struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
graph->id = ar_graph->id;
graph->dev = dev;
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+ graph->shm_iid = q6apm_graph_get_rx_shmem_module_iid(graph);
+ else
+ graph->shm_iid = q6apm_graph_get_tx_shmem_module_iid(graph);
+
+
mutex_init(&graph->lock);
init_waitqueue_head(&graph->cmd_wait);
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h
index 5cf538397841..7c646ffcf956 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -99,6 +99,7 @@ struct q6apm_graph {
void *priv;
q6apm_cb cb;
uint32_t id;
+ uint32_t shm_iid;
struct device *dev;
struct q6apm *apm;
gpr_port_t *port;
@@ -113,7 +114,7 @@ struct q6apm_graph {
/* Graph Operations */
struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
- void *priv, int graph_id);
+ void *priv, int graph_id, int dir);
int q6apm_graph_close(struct q6apm_graph *graph);
int q6apm_graph_prepare(struct q6apm_graph *graph);
int q6apm_graph_start(struct q6apm_graph *graph);
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v3 14/14] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (12 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 13/14] ASoC: qcom: qdsp6: remove search for module iid in hot path Srinivas Kandagatla
@ 2026-03-04 13:07 ` Srinivas Kandagatla
2026-03-05 13:48 ` [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Richard Acayan
14 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-04 13:07 UTC (permalink / raw)
To: broonie, robh, krzk+dt, conor+dt
Cc: mohammad.rafi.shaik, linux-sound, lgirdwood, perex, tiwai, johan,
dmitry.baryshkov, konrad.dybcio, linux-arm-msm, devicetree,
linux-kernel, srini, Srinivas Kandagatla
Buffers are allocated on pcm_new and mapped in the dsp on every
prepare call, which is inefficient and unnecessary.
Add new functions q6apm_[un]map_memory_fixed_region to map it on
to dsp only once after allocation.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/audioreach.c | 60 ------------
sound/soc/qcom/qdsp6/audioreach.h | 5 +-
sound/soc/qcom/qdsp6/q6apm-dai.c | 95 +++++++++++++++---
sound/soc/qcom/qdsp6/q6apm.c | 157 ++++++++++++++++++++----------
sound/soc/qcom/qdsp6/q6apm.h | 15 ++-
5 files changed, 203 insertions(+), 129 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index 241c3b4479c6..b2975eebab71 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -1396,66 +1396,6 @@ void audioreach_graph_free_buf(struct q6apm_graph *graph)
}
EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
-int audioreach_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, size_t period_sz,
- unsigned int periods, bool is_contiguous)
-{
- struct apm_shared_map_region_payload *mregions;
- struct apm_cmd_shared_mem_map_regions *cmd;
- uint32_t num_regions, buf_sz, payload_size;
- struct audioreach_graph_data *data;
- struct gpr_pkt *pkt __free(kfree) = NULL;
- void *p;
- int i;
-
- if (dir == SNDRV_PCM_STREAM_PLAYBACK)
- data = &graph->rx_data;
- else
- data = &graph->tx_data;
-
- if (is_contiguous) {
- num_regions = 1;
- buf_sz = period_sz * periods;
- } else {
- buf_sz = period_sz;
- num_regions = periods;
- }
-
- /* DSP expects size should be aligned to 4K */
- buf_sz = ALIGN(buf_sz, 4096);
-
- payload_size = sizeof(*cmd) + (sizeof(*mregions) * num_regions);
-
- pkt = audioreach_alloc_apm_pkt(payload_size, APM_CMD_SHARED_MEM_MAP_REGIONS, dir,
- graph->port->id);
- if (IS_ERR(pkt))
- return PTR_ERR(pkt);
-
- p = (void *)pkt + GPR_HDR_SIZE;
- cmd = p;
- cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
- cmd->num_regions = num_regions;
-
- cmd->property_flag = 0x0;
-
- mregions = p + sizeof(*cmd);
-
- mutex_lock(&graph->lock);
-
- for (i = 0; i < num_regions; i++) {
- struct audio_buffer *ab;
-
- ab = &data->buf[i];
- mregions->shm_addr_lsw = lower_32_bits(ab->phys);
- mregions->shm_addr_msw = upper_32_bits(ab->phys);
- mregions->mem_size_bytes = buf_sz;
- ++mregions;
- }
- mutex_unlock(&graph->lock);
-
- return audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
-}
-EXPORT_SYMBOL_GPL(audioreach_map_memory_regions);
-
int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
{
struct data_cmd_wr_sh_mem_ep_eos *eos;
diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h
index 89f172aab8c0..6ddc287f0fb4 100644
--- a/sound/soc/qcom/qdsp6/audioreach.h
+++ b/sound/soc/qcom/qdsp6/audioreach.h
@@ -722,6 +722,7 @@ struct audioreach_connection {
struct audioreach_graph_info {
int id;
+ uint32_t mem_map_handle;
uint32_t num_sub_graphs;
struct list_head sg_list;
/* DPCM connection from FE Graph to BE graph */
@@ -838,10 +839,6 @@ int audioreach_tplg_init(struct snd_soc_component *component);
/* Module specific */
void audioreach_graph_free_buf(struct q6apm_graph *graph);
-int audioreach_map_memory_regions(struct q6apm_graph *graph,
- unsigned int dir, size_t period_sz,
- unsigned int periods,
- bool is_contiguous);
int audioreach_send_cmd_sync(struct device *dev, gpr_device_t *gdev, struct gpr_ibasic_rsp_result_t *result,
struct mutex *cmd_lock, gpr_port_t *port, wait_queue_head_t *cmd_wait,
struct gpr_pkt *pkt, uint32_t rsp_opcode);
diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
index bdd4cc458acd..f4a9098fde10 100644
--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
@@ -228,11 +228,10 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
cfg.bit_width = prtd->bits_per_sample;
cfg.fmt = SND_AUDIOCODEC_PCM;
audioreach_set_default_channel_mapping(cfg.channel_map, runtime->channels);
-
if (prtd->state) {
/* clear the previous setup if any */
q6apm_graph_stop(prtd->graph);
- q6apm_unmap_memory_regions(prtd->graph, substream->stream);
+ q6apm_free_fragments(prtd->graph, substream->stream);
}
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
@@ -247,8 +246,8 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
if (ret < 0)
dev_err(dev, "%s: CMD Format block failed\n", __func__);
- ret = q6apm_map_memory_regions(prtd->graph, substream->stream, prtd->phys,
- (prtd->pcm_size / prtd->periods), prtd->periods);
+ ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys,
+ (prtd->pcm_size / prtd->periods), prtd->periods);
if (ret < 0) {
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
@@ -403,6 +402,8 @@ static int q6apm_dai_open(struct snd_soc_component *component,
else
prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
+ q6apm_set_memory_map_handle(prtd->graph, substream->stream);
+
return 0;
err:
kfree(prtd);
@@ -416,9 +417,10 @@ static int q6apm_dai_close(struct snd_soc_component *component,
struct snd_pcm_runtime *runtime = substream->runtime;
struct q6apm_dai_rtd *prtd = runtime->private_data;
- if (prtd->state) { /* only stop graph that is started */
+ if (prtd->state) {
+ /* only stop graph that is started */
q6apm_graph_stop(prtd->graph);
- q6apm_unmap_memory_regions(prtd->graph, substream->stream);
+ q6apm_free_fragments(prtd->graph, substream->stream);
}
q6apm_graph_close(prtd->graph);
@@ -467,11 +469,80 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component,
return 0;
}
+static int q6apm_dai_memory_map(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int graph_id)
+{
+ struct q6apm_dai_data *pdata;
+ struct device *dev = component->dev;
+ phys_addr_t phys;
+ int ret;
+
+ pdata = snd_soc_component_get_drvdata(component);
+ if (!pdata) {
+ dev_err(component->dev, "Drv data not found ..\n");
+ return -EINVAL;
+ }
+
+ if (pdata->sid < 0)
+ phys = substream->dma_buffer.addr;
+ else
+ phys = substream->dma_buffer.addr | (pdata->sid << 32);
+
+ ret = q6apm_map_memory_fixed_region(dev, graph_id, phys, BUFFER_BYTES_MAX);
+ if (ret < 0)
+ dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
+
+ return ret;
+}
+
static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
{
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct snd_pcm *pcm = rtd->pcm;
int size = BUFFER_BYTES_MAX;
+ int graph_id, ret;
+ struct snd_pcm_substream *substream;
+
+ graph_id = cpu_dai->driver->id;
- return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
+ ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
+ if (ret)
+ return ret;
+
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ ret = q6apm_dai_memory_map(component, substream, graph_id);
+ if (ret)
+ return ret;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ q6apm_dai_memory_map(component, substream, graph_id);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void q6apm_dai_pcm_destruct(struct snd_soc_component *component, struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_soc_pcm_runtime *soc_prtd;
+ struct snd_soc_dai *cpu_dai;
+ int graph_id;
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
+ substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ else
+ substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+
+ soc_prtd = snd_soc_substream_to_rtd(substream);
+ cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0);
+
+ graph_id = cpu_dai->driver->id;
+ q6apm_unmap_memory_fixed_region(component->dev, graph_id);
}
static int q6apm_dai_compr_open(struct snd_soc_component *component,
@@ -530,7 +601,8 @@ static int q6apm_dai_compr_free(struct snd_soc_component *component,
struct q6apm_dai_rtd *prtd = runtime->private_data;
q6apm_graph_stop(prtd->graph);
- q6apm_unmap_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK);
+ q6apm_free_fragments(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK);
+ q6apm_unmap_memory_fixed_region(component->dev, prtd->graph->id);
q6apm_graph_close(prtd->graph);
snd_dma_free_pages(&prtd->dma_buffer);
prtd->graph = NULL;
@@ -679,9 +751,9 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
if (ret)
return ret;
- ret = q6apm_map_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK,
- prtd->phys, (prtd->pcm_size / prtd->periods),
- prtd->periods);
+ ret = q6apm_alloc_fragments(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK,
+ prtd->phys, (prtd->pcm_size / prtd->periods),
+ prtd->periods);
if (ret < 0)
return -ENOMEM;
@@ -834,6 +906,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
.close = q6apm_dai_close,
.prepare = q6apm_dai_prepare,
.pcm_construct = q6apm_dai_pcm_new,
+ .pcm_destruct = q6apm_dai_pcm_destruct,
.hw_params = q6apm_dai_hw_params,
.pointer = q6apm_dai_pointer,
.trigger = q6apm_dai_trigger,
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index 7ef6ae0b1759..286b3d2c589d 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -200,13 +200,59 @@ int q6apm_graph_media_format_shmem(struct q6apm_graph *graph,
}
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_shmem);
-int q6apm_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys,
- size_t period_sz, unsigned int periods)
+void q6apm_set_memory_map_handle(struct q6apm_graph *graph, unsigned int dir)
+{
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+ graph->rx_data.mem_map_handle = graph->info->mem_map_handle;
+ else
+ graph->tx_data.mem_map_handle = graph->info->mem_map_handle;
+}
+EXPORT_SYMBOL_GPL(q6apm_set_memory_map_handle);
+
+int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys,
+ size_t sz)
+{
+ struct audioreach_graph_info *info;
+ struct q6apm *apm = dev_get_drvdata(dev->parent);
+ struct apm_shared_map_region_payload *mregions;
+ struct apm_cmd_shared_mem_map_regions *cmd;
+ int payload_size = sizeof(*cmd) + (sizeof(*mregions));
+ uint32_t buf_sz;
+ void *p;
+ struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size,
+ APM_CMD_SHARED_MEM_MAP_REGIONS, graph_id);
+ if (IS_ERR(pkt))
+ return PTR_ERR(pkt);
+
+ info = idr_find(&apm->graph_info_idr, graph_id);
+ if (!info)
+ return -ENODEV;
+
+ /* DSP expects size should be aligned to 4K */
+ buf_sz = ALIGN(sz, 4096);
+
+ p = (void *)pkt + GPR_HDR_SIZE;
+ cmd = p;
+ cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
+ cmd->num_regions = 1;
+ cmd->property_flag = 0x0;
+
+ mregions = p + sizeof(*cmd);
+
+ mregions->shm_addr_lsw = lower_32_bits(phys);
+ mregions->shm_addr_msw = upper_32_bits(phys);
+ mregions->mem_size_bytes = buf_sz;
+
+ return q6apm_send_cmd_sync(apm, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
+}
+EXPORT_SYMBOL_GPL(q6apm_map_memory_fixed_region);
+
+int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys,
+ size_t period_sz, unsigned int periods)
{
struct audioreach_graph_data *data;
struct audio_buffer *buf;
int cnt;
- int rc;
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
data = &graph->rx_data;
@@ -248,21 +294,37 @@ int q6apm_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, phys_a
mutex_unlock(&graph->lock);
- rc = audioreach_map_memory_regions(graph, dir, period_sz, periods, 1);
- if (rc < 0) {
- dev_err(graph->dev, "Memory_map_regions failed\n");
- audioreach_graph_free_buf(graph);
- }
-
- return rc;
+ return 0;
}
-EXPORT_SYMBOL_GPL(q6apm_map_memory_regions);
+EXPORT_SYMBOL_GPL(q6apm_alloc_fragments);
-int q6apm_unmap_memory_regions(struct q6apm_graph *graph, unsigned int dir)
+int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
{
struct apm_cmd_shared_mem_unmap_regions *cmd;
+ struct q6apm *apm = dev_get_drvdata(dev->parent);
+ struct audioreach_graph_info *info;
+ struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd),
+ APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id);
+ if (IS_ERR(pkt))
+ return PTR_ERR(pkt);
+
+ info = idr_find(&apm->graph_info_idr, graph_id);
+ if (!info)
+ return -ENODEV;
+
+ if (!info->mem_map_handle)
+ return 0;
+
+ cmd = (void *)pkt + GPR_HDR_SIZE;
+ cmd->mem_map_handle = info->mem_map_handle;
+
+ return q6apm_send_cmd_sync(apm, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
+}
+EXPORT_SYMBOL_GPL(q6apm_unmap_memory_fixed_region);
+
+int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
+{
struct audioreach_graph_data *data;
- int rc;
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
data = &graph->rx_data;
@@ -272,22 +334,11 @@ int q6apm_unmap_memory_regions(struct q6apm_graph *graph, unsigned int dir)
if (!data->mem_map_handle)
return 0;
- struct gpr_pkt *pkt __free(kfree) =
- audioreach_alloc_apm_pkt(sizeof(*cmd), APM_CMD_SHARED_MEM_UNMAP_REGIONS,
- dir, graph->port->id);
- if (IS_ERR(pkt))
- return PTR_ERR(pkt);
-
- cmd = (void *)pkt + GPR_HDR_SIZE;
- cmd->mem_map_handle = data->mem_map_handle;
-
- rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
-
audioreach_graph_free_buf(graph);
- return rc;
+ return 0;
}
-EXPORT_SYMBOL_GPL(q6apm_unmap_memory_regions);
+EXPORT_SYMBOL_GPL(q6apm_free_fragments);
int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples)
{
@@ -494,7 +545,6 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
{
struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
struct data_cmd_rsp_wr_sh_mem_ep_data_buffer_done_v2 *done;
- struct apm_cmd_rsp_shared_mem_map_regions *rsp;
const struct gpr_ibasic_rsp_result_t *result;
struct q6apm_graph *graph = priv;
const struct gpr_hdr *hdr = &data->hdr;
@@ -529,18 +579,6 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
done->buf_addr_msw);
}
- break;
- case APM_CMD_RSP_SHARED_MEM_MAP_REGIONS:
- graph->result.opcode = hdr->opcode;
- graph->result.status = 0;
- rsp = data->payload;
-
- if (hdr->token == SNDRV_PCM_STREAM_PLAYBACK)
- graph->rx_data.mem_map_handle = rsp->mem_map_handle;
- else
- graph->tx_data.mem_map_handle = rsp->mem_map_handle;
-
- wake_up(&graph->cmd_wait);
break;
case DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2:
if (!graph->ar_graph)
@@ -571,16 +609,6 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
break;
case GPR_BASIC_RSP_RESULT:
switch (result->opcode) {
- case APM_CMD_SHARED_MEM_UNMAP_REGIONS:
- graph->result.opcode = result->opcode;
- graph->result.status = 0;
- if (hdr->token == SNDRV_PCM_STREAM_PLAYBACK)
- graph->rx_data.mem_map_handle = 0;
- else
- graph->tx_data.mem_map_handle = 0;
-
- wake_up(&graph->cmd_wait);
- break;
case APM_CMD_SHARED_MEM_MAP_REGIONS:
case DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT:
case APM_CMD_SET_CFG:
@@ -778,7 +806,9 @@ struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph, ui
static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
{
gpr_device_t *gdev = priv;
+ struct audioreach_graph_info *info;
struct q6apm *apm = dev_get_drvdata(&gdev->dev);
+ struct apm_cmd_rsp_shared_mem_map_regions *rsp;
struct device *dev = &gdev->dev;
struct gpr_ibasic_rsp_result_t *result;
const struct gpr_hdr *hdr = &data->hdr;
@@ -795,6 +825,7 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
break;
case GPR_BASIC_RSP_RESULT:
switch (result->opcode) {
+ case APM_CMD_SHARED_MEM_MAP_REGIONS:
case APM_CMD_GRAPH_START:
case APM_CMD_GRAPH_OPEN:
case APM_CMD_GRAPH_PREPARE:
@@ -809,10 +840,38 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
result->opcode);
wake_up(&apm->wait);
break;
+ case APM_CMD_SHARED_MEM_UNMAP_REGIONS:
+ apm->result.opcode = hdr->opcode;
+ apm->result.status = 0;
+ rsp = data->payload;
+
+ info = idr_find(&apm->graph_info_idr, hdr->token);
+ if (info)
+ info->mem_map_handle = 0;
+ else
+ dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status,
+ result->opcode);
+
+ wake_up(&apm->wait);
+ break;
default:
break;
}
break;
+ case APM_CMD_RSP_SHARED_MEM_MAP_REGIONS:
+ apm->result.opcode = hdr->opcode;
+ apm->result.status = 0;
+ rsp = data->payload;
+
+ info = idr_find(&apm->graph_info_idr, hdr->token);
+ if (info)
+ info->mem_map_handle = rsp->mem_map_handle;
+ else
+ dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status,
+ result->opcode);
+
+ wake_up(&apm->wait);
+ break;
default:
break;
}
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h
index 7c646ffcf956..67acbf0ce178 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -134,11 +134,16 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
uint32_t lsw_ts, uint32_t wflags);
/* Memory Map related */
-int q6apm_map_memory_regions(struct q6apm_graph *graph,
- unsigned int dir, phys_addr_t phys,
- size_t period_sz, unsigned int periods);
-int q6apm_unmap_memory_regions(struct q6apm_graph *graph,
- unsigned int dir);
+int q6apm_map_memory_fixed_region(struct device *dev,
+ unsigned int graph_id, phys_addr_t phys,
+ size_t sz);
+void q6apm_set_memory_map_handle(struct q6apm_graph *graph,
+ unsigned int dir);
+int q6apm_alloc_fragments(struct q6apm_graph *graph,
+ unsigned int dir, phys_addr_t phys,
+ size_t period_sz, unsigned int periods);
+int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir);
+int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id);
/* Helpers */
int q6apm_send_cmd_sync(struct q6apm *apm, struct gpr_pkt *pkt,
uint32_t rsp_opcode);
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements
2026-03-04 13:06 [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (13 preceding siblings ...)
2026-03-04 13:07 ` [PATCH v3 14/14] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP Srinivas Kandagatla
@ 2026-03-05 13:48 ` Richard Acayan
2026-03-06 10:54 ` Srinivas Kandagatla
14 siblings, 1 reply; 20+ messages in thread
From: Richard Acayan @ 2026-03-05 13:48 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: broonie, robh, krzk+dt, conor+dt, mohammad.rafi.shaik,
linux-sound, lgirdwood, perex, tiwai, johan, dmitry.baryshkov,
konrad.dybcio, linux-arm-msm, devicetree, linux-kernel, srini
On Wed, Mar 04, 2026 at 01:06:58PM +0000, Srinivas Kandagatla wrote:
> This patchset contains few fixes for the bugs hit during testing with
> Monza EVK platform
> - around array out of bounds access on dai ids which keep extending but
> the drivers seems to have hardcoded some numbers, fix this and clean
> the mess up
> - fix few issues discovered while trying to shut down dsp.
> - flooding rpmsg with write requests due to not resetting queue pointer,
> fix this resetting the pointer in trigger stop.
> - possible multiple graph opens which can result in open failures.
>
> Apart from this few new enhancements to the dsp side
> - add new LPI MI2S and senary dai entries
Is the LPI MI2S on Q6AFE? I don't see the AFE port ID.
It sounds different from INT_MI2S so I can rebase my patches to depend
on this series.
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements
2026-03-05 13:48 ` [PATCH v3 00/14] ASoC: qcom: q6dsp: few fixes and enhancements Richard Acayan
@ 2026-03-06 10:54 ` Srinivas Kandagatla
0 siblings, 0 replies; 20+ messages in thread
From: Srinivas Kandagatla @ 2026-03-06 10:54 UTC (permalink / raw)
To: Richard Acayan
Cc: broonie, robh, krzk+dt, conor+dt, mohammad.rafi.shaik,
linux-sound, lgirdwood, perex, tiwai, johan, dmitry.baryshkov,
konrad.dybcio, linux-arm-msm, devicetree, linux-kernel, srini
On 3/5/26 1:48 PM, Richard Acayan wrote:
> On Wed, Mar 04, 2026 at 01:06:58PM +0000, Srinivas Kandagatla wrote:
>> This patchset contains few fixes for the bugs hit during testing with
>> Monza EVK platform
>> - around array out of bounds access on dai ids which keep extending but
>> the drivers seems to have hardcoded some numbers, fix this and clean
>> the mess up
>> - fix few issues discovered while trying to shut down dsp.
>> - flooding rpmsg with write requests due to not resetting queue pointer,
>> fix this resetting the pointer in trigger stop.
>> - possible multiple graph opens which can result in open failures.
>>
>> Apart from this few new enhancements to the dsp side
>> - add new LPI MI2S and senary dai entries
>
> Is the LPI MI2S on Q6AFE? I don't see the AFE port ID.
I think the older SOCs did not have this I guess,
>
> It sounds different from INT_MI2S so I can rebase my patches to depend
> on this series.
That would be wonderful
Sending out v4 soon!
--srini
^ permalink raw reply [flat|nested] 20+ messages in thread