* [PATCH v7 01/13] ASoC: qcom: q6apm: move component registration to unmanaged version
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-24 18:04 ` Mark Brown
2026-03-23 22:38 ` [PATCH v7 02/13] ASoC: qcom: q6apm: remove child devices when apm is removed Srinivas Kandagatla
` (11 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 970b08c89bb3..fece0e3def23 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -747,7 +747,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;
@@ -756,6 +756,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;
@@ -820,6 +825,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] 24+ messages in thread* Re: [PATCH v7 01/13] ASoC: qcom: q6apm: move component registration to unmanaged version
2026-03-23 22:38 ` [PATCH v7 01/13] ASoC: qcom: q6apm: move component registration to unmanaged version Srinivas Kandagatla
@ 2026-03-24 18:04 ` Mark Brown
2026-03-25 11:36 ` Srinivas Kandagatla
0 siblings, 1 reply; 24+ messages in thread
From: Mark Brown @ 2026-03-24 18:04 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: 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, val,
mailingradian
[-- Attachment #1: Type: text/plain, Size: 776 bytes --]
On Mon, Mar 23, 2026 at 10:38:33PM +0000, Srinivas Kandagatla wrote:
> --- a/sound/soc/qcom/qdsp6/q6apm.c
> +++ b/sound/soc/qcom/qdsp6/q6apm.c
> @@ -747,7 +747,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;
> @@ -756,6 +756,11 @@ static int apm_probe(gpr_device_t *gdev)
> return of_platform_populate(dev->of_node, NULL, NULL, dev);
> }
Given that of_platform_populate() can fail we now need unwinding for the
component registration here with the removal of devm_
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v7 01/13] ASoC: qcom: q6apm: move component registration to unmanaged version
2026-03-24 18:04 ` Mark Brown
@ 2026-03-25 11:36 ` Srinivas Kandagatla
0 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-25 11:36 UTC (permalink / raw)
To: Mark Brown, Srinivas Kandagatla
Cc: 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, val,
mailingradian
On 3/24/26 6:04 PM, Mark Brown wrote:
> On Mon, Mar 23, 2026 at 10:38:33PM +0000, Srinivas Kandagatla wrote:
>
>> --- a/sound/soc/qcom/qdsp6/q6apm.c
>> +++ b/sound/soc/qcom/qdsp6/q6apm.c
>> @@ -747,7 +747,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;
>> @@ -756,6 +756,11 @@ static int apm_probe(gpr_device_t *gdev)
>> return of_platform_populate(dev->of_node, NULL, NULL, dev);
>> }
>
> Given that of_platform_populate() can fail we now need unwinding for the
Yes, will fix that in next spin.
--srini
> component registration here with the removal of devm_
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v7 02/13] ASoC: qcom: q6apm: remove child devices when apm is removed
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 01/13] ASoC: qcom: q6apm: move component registration to unmanaged version Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 03/13] ASoC: qcom: qdsp6: topology: check widget type before accessing data Srinivas Kandagatla
` (10 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 fece0e3def23..1fbcbbf3123d 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -753,7 +753,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] 24+ messages in thread* [PATCH v7 03/13] ASoC: qcom: qdsp6: topology: check widget type before accessing data
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 01/13] ASoC: qcom: q6apm: move component registration to unmanaged version Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 02/13] ASoC: qcom: q6apm: remove child devices when apm is removed Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens Srinivas Kandagatla
` (9 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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] 24+ messages in thread* [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (2 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 03/13] ASoC: qcom: qdsp6: topology: check widget type before accessing data Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-24 18:25 ` Mark Brown
2026-03-23 22:38 ` [PATCH v7 05/13] ASoC: qcom: q6apm-dai: reset queue ptr on trigger stop Srinivas Kandagatla
` (8 subsequent siblings)
12 siblings, 1 reply; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 5be37eeea329..ba64117b8cfe 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] 24+ messages in thread* Re: [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens
2026-03-23 22:38 ` [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens Srinivas Kandagatla
@ 2026-03-24 18:25 ` Mark Brown
2026-03-24 18:47 ` Mark Brown
2026-03-25 11:33 ` Srinivas Kandagatla
0 siblings, 2 replies; 24+ messages in thread
From: Mark Brown @ 2026-03-24 18:25 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: 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, val,
mailingradian, Stable
[-- Attachment #1: Type: text/plain, Size: 580 bytes --]
On Mon, Mar 23, 2026 at 10:38:36PM +0000, Srinivas Kandagatla wrote:
> As prepare can be called mulitple times, this can result in multiple
> graph opens for playback path.
> */
> - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
This is an array of APM_PORT_MAX elements but we have DAI IDs in the DT
bindings over that and now we're using the DAI ID to index into the
array (I didn't check for existing instances...). This might be
impossible due to system design though.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens
2026-03-24 18:25 ` Mark Brown
@ 2026-03-24 18:47 ` Mark Brown
2026-03-25 11:33 ` Srinivas Kandagatla
1 sibling, 0 replies; 24+ messages in thread
From: Mark Brown @ 2026-03-24 18:47 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: 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, val,
mailingradian, Stable
[-- Attachment #1: Type: text/plain, Size: 793 bytes --]
On Tue, Mar 24, 2026 at 06:25:42PM +0000, Mark Brown wrote:
> On Mon, Mar 23, 2026 at 10:38:36PM +0000, Srinivas Kandagatla wrote:
> > As prepare can be called mulitple times, this can result in multiple
> > graph opens for playback path.
> > */
> > - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> > + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
> This is an array of APM_PORT_MAX elements but we have DAI IDs in the DT
> bindings over that and now we're using the DAI ID to index into the
> array (I didn't check for existing instances...). This might be
> impossible due to system design though.
Ah, found an update later in the series so it's OK in the end. A
potential bisection issue but hopefully not the end of the world.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens
2026-03-24 18:25 ` Mark Brown
2026-03-24 18:47 ` Mark Brown
@ 2026-03-25 11:33 ` Srinivas Kandagatla
2026-03-25 11:56 ` Mark Brown
1 sibling, 1 reply; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-25 11:33 UTC (permalink / raw)
To: Mark Brown, Srinivas Kandagatla
Cc: 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, val,
mailingradian, Stable
On 3/24/26 6:25 PM, Mark Brown wrote:
> On Mon, Mar 23, 2026 at 10:38:36PM +0000, Srinivas Kandagatla wrote:
>> As prepare can be called mulitple times, this can result in multiple
>> graph opens for playback path.
>
>> */
>> - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
>> + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
>
> This is an array of APM_PORT_MAX elements but we have DAI IDs in the DT
> bindings over that and now we're using the DAI ID to index into the
The driver has dai->id indexing the array in most places, and that is
how it has been for a while. This is one of the problem which last patch
is trying to address doing a check on the range. At somepoint we need to
move to dynamic allocation tbh.
--srini
> array (I didn't check for existing instances...). This might be
> impossible due to system design though.
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens
2026-03-25 11:33 ` Srinivas Kandagatla
@ 2026-03-25 11:56 ` Mark Brown
0 siblings, 0 replies; 24+ messages in thread
From: Mark Brown @ 2026-03-25 11:56 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: 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, val,
mailingradian, Stable
[-- Attachment #1: Type: text/plain, Size: 944 bytes --]
On Wed, Mar 25, 2026 at 11:33:45AM +0000, Srinivas Kandagatla wrote:
> On 3/24/26 6:25 PM, Mark Brown wrote:
> > On Mon, Mar 23, 2026 at 10:38:36PM +0000, Srinivas Kandagatla wrote:
> >> - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> >> + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
> > This is an array of APM_PORT_MAX elements but we have DAI IDs in the DT
> > bindings over that and now we're using the DAI ID to index into the
> The driver has dai->id indexing the array in most places, and that is
> how it has been for a while. This is one of the problem which last patch
> is trying to address doing a check on the range. At somepoint we need to
> move to dynamic allocation tbh.
Yeah, I saw it was a bit shaky all over. I think having the array size
bumps earlier might help at least make it clearer things are OK, but
dynamic structures of some kind would indeed be ideal.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v7 05/13] ASoC: qcom: q6apm-dai: reset queue ptr on trigger stop
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (3 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 04/13] ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 06/13] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids Srinivas Kandagatla
` (7 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 306e928e7b49..292be457764f 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 1fbcbbf3123d..9d4cbe29cf94 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] 24+ messages in thread* [PATCH v7 06/13] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (4 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 05/13] ASoC: qcom: q6apm-dai: reset queue ptr on trigger stop Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 07/13] ASoC: qcom: qdsp6: lpass-ports: add support for LPASS LPI MI2S dais Srinivas Kandagatla
` (6 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, Srinivas Kandagatla,
Krzysztof Kozlowski
Add new dai ids entries for LPASS LPI MI2S and SENARY MI2S audio lines.
Co-developed-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Signed-off-by: Mohammad Rafi Shaik <mohammad.rafi.shaik@oss.qualcomm.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../bindings/sound/qcom,q6dsp-lpass-ports.yaml | 5 ++++-
include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h | 12 ++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml
index 08c618e7e428..2b27d6c8f58f 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml
@@ -126,13 +126,16 @@ patternProperties:
reg:
contains:
# MI2S DAI ID range PRIMARY_MI2S_RX - QUATERNARY_MI2S_TX and
- # QUINARY_MI2S_RX - QUINARY_MI2S_TX
+ # QUINARY_MI2S_RX - QUINARY_MI2S_TX and
+ # LPI_MI2S_RX_0 - SENARY_MI2S_TX
items:
oneOf:
- minimum: 16
maximum: 23
- minimum: 127
maximum: 128
+ - minimum: 137
+ maximum: 148
then:
required:
- qcom,sd-lines
diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
index 6d1ce7f5da51..45850f2d4342 100644
--- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
+++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
@@ -140,6 +140,18 @@
#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 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] 24+ messages in thread* [PATCH v7 07/13] ASoC: qcom: qdsp6: lpass-ports: add support for LPASS LPI MI2S dais
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (5 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 06/13] ASoC: dt-bindings: qcom: add LPASS LPI MI2S dai ids Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 08/13] ASoC: qcom: q6dsp: Add Senary MI2S audio interface support Srinivas Kandagatla
` (5 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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] 24+ messages in thread* [PATCH v7 08/13] ASoC: qcom: q6dsp: Add Senary MI2S audio interface support
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (6 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 07/13] ASoC: qcom: qdsp6: lpass-ports: add support for LPASS LPI MI2S dais Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 09/13] ASoC: qcom: common: validate cpu dai id during parsing Srinivas Kandagatla
` (4 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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>
Tested-by: Val Packett <val@packett.cool> # sm7325-motorola-dubai
---
sound/soc/qcom/qdsp6/q6afe-dai.c | 6 +++++
sound/soc/qcom/qdsp6/q6afe.c | 8 +++++++
sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c | 29 ++++++++++++++++++++++++
3 files changed, 43 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..40237267fda0 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,
@@ -1777,6 +1783,8 @@ struct q6afe_port *q6afe_port_get_from_id(struct device *dev, int id)
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
case AFE_PORT_ID_QUINARY_MI2S_RX:
case AFE_PORT_ID_QUINARY_MI2S_TX:
+ case AFE_PORT_ID_SENARY_MI2S_RX:
+ case AFE_PORT_ID_SENARY_MI2S_TX:
cfg_type = AFE_PARAM_ID_I2S_CONFIG;
break;
case AFE_PORT_ID_PRIMARY_TDM_RX ... AFE_PORT_ID_QUINARY_TDM_TX_7:
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] 24+ messages in thread* [PATCH v7 09/13] ASoC: qcom: common: validate cpu dai id during parsing
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (7 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 08/13] ASoC: qcom: q6dsp: Add Senary MI2S audio interface support Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 10/13] ASoC: qcom: qdapm-lpass-dai: correct the error message Srinivas Kandagatla
` (3 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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..cf1f3a767cee 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] 24+ messages in thread* [PATCH v7 10/13] ASoC: qcom: qdapm-lpass-dai: correct the error message
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (8 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 09/13] ASoC: qcom: common: validate cpu dai id during parsing Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 11/13] ASoC: qcom: q6apm-lpass-dai: move graph start to trigger Srinivas Kandagatla
` (2 subsequent siblings)
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 ba64117b8cfe..87f6db12003e 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] 24+ messages in thread* [PATCH v7 11/13] ASoC: qcom: q6apm-lpass-dai: move graph start to trigger
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (9 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 10/13] ASoC: qcom: qdapm-lpass-dai: correct the error message Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 12/13] ASoC: qcom: qdsp6: remove search for module iid in hot path Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP Srinivas Kandagatla
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 87f6db12003e..e904066484d5 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] 24+ messages in thread* [PATCH v7 12/13] ASoC: qcom: qdsp6: remove search for module iid in hot path
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (10 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 11/13] ASoC: qcom: q6apm-lpass-dai: move graph start to trigger Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-23 22:38 ` [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP Srinivas Kandagatla
12 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 292be457764f..86d6438bd9fd 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 e904066484d5..006b283484d9 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 9d4cbe29cf94..c874dae53163 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] 24+ messages in thread* [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
2026-03-23 22:38 [PATCH v7 00/13] ASoC: qcom: q6dsp: few fixes and enhancements Srinivas Kandagatla
` (11 preceding siblings ...)
2026-03-23 22:38 ` [PATCH v7 12/13] ASoC: qcom: qdsp6: remove search for module iid in hot path Srinivas Kandagatla
@ 2026-03-23 22:38 ` Srinivas Kandagatla
2026-03-24 19:09 ` Mark Brown
2026-03-24 20:25 ` kernel test robot
12 siblings, 2 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-23 22:38 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, val, mailingradian, 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 | 110 ++++++++++++++++++---
sound/soc/qcom/qdsp6/q6apm.c | 158 ++++++++++++++++++++----------
sound/soc/qcom/qdsp6/q6apm.h | 14 +--
5 files changed, 212 insertions(+), 135 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 86d6438bd9fd..ae5318e0aa3b 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);
@@ -416,9 +415,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 +467,97 @@ 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;
+
+ 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;
+ ret = q6apm_dai_memory_map(component, substream, graph_id);
+ if (ret) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
+ q6apm_unmap_memory_fixed_region(component->dev, graph_id);
+
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void q6apm_dai_memory_unmap(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *soc_prtd;
+ struct snd_soc_dai *cpu_dai;
+ int graph_id;
+
+ soc_prtd = snd_soc_substream_to_rtd(substream);
+ if (!soc_prtd)
+ return;
+
+ cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0);
+ if (!cpu_dai)
+ return;
+
+ graph_id = cpu_dai->driver->id;
+ q6apm_unmap_memory_fixed_region(component->dev, graph_id);
+}
+
+static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+
+ substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ if (substream)
+ q6apm_dai_memory_unmap(component, substream);
- return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
+ substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (substream)
+ q6apm_dai_memory_unmap(component, substream);
}
static int q6apm_dai_compr_open(struct snd_soc_component *component,
@@ -530,7 +616,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 +766,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 +921,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
.close = q6apm_dai_close,
.prepare = q6apm_dai_prepare,
.pcm_new = q6apm_dai_pcm_new,
+ .pcm_free = q6apm_dai_pcm_free,
.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 c874dae53163..1889d50df862 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -200,13 +200,53 @@ 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)
+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;
+
+ if (info->mem_map_handle)
+ return 0;
+
+ /* 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,46 +288,48 @@ 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 audioreach_graph_data *data;
- int rc;
+ 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);
- if (dir == SNDRV_PCM_STREAM_PLAYBACK)
- data = &graph->rx_data;
- else
- data = &graph->tx_data;
+ info = idr_find(&apm->graph_info_idr, graph_id);
+ if (!info)
+ return -ENODEV;
- if (!data->mem_map_handle)
+ if (!info->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;
+ 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);
- rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
+int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
+{
+ struct audioreach_graph_data *data;
+
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+ data = &graph->rx_data;
+ else
+ data = &graph->tx_data;
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)
{
@@ -429,7 +471,7 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
write_buffer->buf_size = len;
write_buffer->timestamp_lsw = lsw_ts;
write_buffer->timestamp_msw = msw_ts;
- write_buffer->mem_map_handle = graph->rx_data.mem_map_handle;
+ write_buffer->mem_map_handle = graph->info->mem_map_handle;
write_buffer->flags = wflags;
graph->rx_data.dsp_buf++;
@@ -463,7 +505,7 @@ int q6apm_read(struct q6apm_graph *graph)
read_buffer->buf_addr_lsw = lower_32_bits(ab->phys);
read_buffer->buf_addr_msw = upper_32_bits(ab->phys);
- read_buffer->mem_map_handle = port->mem_map_handle;
+ read_buffer->mem_map_handle = graph->info->mem_map_handle;
read_buffer->buf_size = ab->size;
port->dsp_buf++;
@@ -494,7 +536,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 +570,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 +600,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:
@@ -779,7 +798,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;
@@ -796,6 +817,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:
@@ -810,10 +832,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..909fc337fd28 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -78,7 +78,6 @@ struct audioreach_graph_data {
struct audio_buffer *buf;
uint32_t num_periods;
uint32_t dsp_buf;
- uint32_t mem_map_handle;
atomic_t hw_ptr;
};
@@ -134,11 +133,14 @@ 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);
+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] 24+ messages in thread* Re: [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
2026-03-23 22:38 ` [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP Srinivas Kandagatla
@ 2026-03-24 19:09 ` Mark Brown
2026-03-25 11:43 ` Srinivas Kandagatla
2026-03-24 20:25 ` kernel test robot
1 sibling, 1 reply; 24+ messages in thread
From: Mark Brown @ 2026-03-24 19:09 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: 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, val,
mailingradian
[-- Attachment #1: Type: text/plain, Size: 1274 bytes --]
On Mon, Mar 23, 2026 at 10:38:45PM +0000, Srinivas Kandagatla wrote:
> 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.
> static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
> + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
> + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
> + ret = q6apm_dai_memory_map(component, substream, graph_id);
> + if (ret) {
> + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
> + q6apm_unmap_memory_fixed_region(component->dev, graph_id);
This looks like it's handling bidirectional DAIs but...
> +int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys,
> + size_t sz)
> +{
> + info = idr_find(&apm->graph_info_idr, graph_id);
> + if (!info)
> + return -ENODEV;
> +
> + if (info->mem_map_handle)
> + return 0;
...we have one memory map handle per graph ID, silently ignoring
attempts to add a second one?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
2026-03-24 19:09 ` Mark Brown
@ 2026-03-25 11:43 ` Srinivas Kandagatla
0 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-25 11:43 UTC (permalink / raw)
To: Mark Brown, Srinivas Kandagatla
Cc: 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, val,
mailingradian
On 3/24/26 7:09 PM, Mark Brown wrote:
> On Mon, Mar 23, 2026 at 10:38:45PM +0000, Srinivas Kandagatla wrote:
>> 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.
>
>> static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
>
>> + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
>> + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
>> + ret = q6apm_dai_memory_map(component, substream, graph_id);
>> + if (ret) {
>> + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
>> + q6apm_unmap_memory_fixed_region(component->dev, graph_id);
>
> This looks like it's handling bidirectional DAIs but...
TBH, we only have one dai and one direction per graph, this check was
added for completeness.
We can not have bi-directional dais, as all the be-dais are uni-directional.
>
>> +int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys,
>> + size_t sz)
>> +{
>
>> + info = idr_find(&apm->graph_info_idr, graph_id);
>> + if (!info)
>> + return -ENODEV;
>> +
>> + if (info->mem_map_handle)
>> + return 0;
>
> ...we have one memory map handle per graph ID, silently ignoring
> attempts to add a second one?
there is no second one.
--srini
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
2026-03-23 22:38 ` [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP Srinivas Kandagatla
2026-03-24 19:09 ` Mark Brown
@ 2026-03-24 20:25 ` kernel test robot
2026-03-25 11:45 ` Srinivas Kandagatla
1 sibling, 1 reply; 24+ messages in thread
From: kernel test robot @ 2026-03-24 20:25 UTC (permalink / raw)
To: Srinivas Kandagatla, broonie, robh, krzk+dt, conor+dt
Cc: oe-kbuild-all, mohammad.rafi.shaik, linux-sound, lgirdwood, perex,
tiwai, johan, dmitry.baryshkov, konrad.dybcio, linux-arm-msm,
devicetree, linux-kernel, srini, val, mailingradian,
Srinivas Kandagatla
Hi Srinivas,
kernel test robot noticed the following build warnings:
[auto build test WARNING on broonie-sound/for-next]
[also build test WARNING on next-20260324]
[cannot apply to robh/for-next tiwai-sound/for-next tiwai-sound/for-linus linus/master v7.0-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Srinivas-Kandagatla/ASoC-qcom-q6apm-move-component-registration-to-unmanaged-version/20260324-160527
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
patch link: https://lore.kernel.org/r/20260323223845.2126142-14-srinivas.kandagatla%40oss.qualcomm.com
patch subject: [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20260325/202603250417.fEMbsde2-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260325/202603250417.fEMbsde2-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603250417.fEMbsde2-lkp@intel.com/
All warnings (new ones prefixed by >>):
sound/soc/qcom/qdsp6/q6apm.c: In function 'q6apm_free_fragments':
>> sound/soc/qcom/qdsp6/q6apm.c:321:39: warning: variable 'data' set but not used [-Wunused-but-set-variable]
321 | struct audioreach_graph_data *data;
| ^~~~
vim +/data +321 sound/soc/qcom/qdsp6/q6apm.c
25ab80db6b133c Srinivas Kandagatla 2021-10-26 318
ab4c5c6ed2ed1e Srinivas Kandagatla 2026-03-23 319 int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
25ab80db6b133c Srinivas Kandagatla 2021-10-26 320 {
25ab80db6b133c Srinivas Kandagatla 2021-10-26 @321 struct audioreach_graph_data *data;
25ab80db6b133c Srinivas Kandagatla 2021-10-26 322
25ab80db6b133c Srinivas Kandagatla 2021-10-26 323 if (dir == SNDRV_PCM_STREAM_PLAYBACK)
25ab80db6b133c Srinivas Kandagatla 2021-10-26 324 data = &graph->rx_data;
25ab80db6b133c Srinivas Kandagatla 2021-10-26 325 else
25ab80db6b133c Srinivas Kandagatla 2021-10-26 326 data = &graph->tx_data;
25ab80db6b133c Srinivas Kandagatla 2021-10-26 327
25ab80db6b133c Srinivas Kandagatla 2021-10-26 328 audioreach_graph_free_buf(graph);
25ab80db6b133c Srinivas Kandagatla 2021-10-26 329
ab4c5c6ed2ed1e Srinivas Kandagatla 2026-03-23 330 return 0;
25ab80db6b133c Srinivas Kandagatla 2021-10-26 331 }
ab4c5c6ed2ed1e Srinivas Kandagatla 2026-03-23 332 EXPORT_SYMBOL_GPL(q6apm_free_fragments);
25ab80db6b133c Srinivas Kandagatla 2021-10-26 333
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 24+ messages in thread* Re: [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
2026-03-24 20:25 ` kernel test robot
@ 2026-03-25 11:45 ` Srinivas Kandagatla
0 siblings, 0 replies; 24+ messages in thread
From: Srinivas Kandagatla @ 2026-03-25 11:45 UTC (permalink / raw)
To: kernel test robot, Srinivas Kandagatla, broonie, robh, krzk+dt,
conor+dt
Cc: oe-kbuild-all, mohammad.rafi.shaik, linux-sound, lgirdwood, perex,
tiwai, johan, dmitry.baryshkov, konrad.dybcio, linux-arm-msm,
devicetree, linux-kernel, srini, val, mailingradian
On 3/24/26 8:25 PM, kernel test robot wrote:
> Hi Srinivas,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on broonie-sound/for-next]
> [also build test WARNING on next-20260324]
> [cannot apply to robh/for-next tiwai-sound/for-next tiwai-sound/for-linus linus/master v7.0-rc5]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Srinivas-Kandagatla/ASoC-qcom-q6apm-move-component-registration-to-unmanaged-version/20260324-160527
> base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
> patch link: https://lore.kernel.org/r/20260323223845.2126142-14-srinivas.kandagatla%40oss.qualcomm.com
> patch subject: [PATCH v7 13/13] ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
> config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20260325/202603250417.fEMbsde2-lkp@intel.com/config)
> compiler: m68k-linux-gcc (GCC) 15.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260325/202603250417.fEMbsde2-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202603250417.fEMbsde2-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> sound/soc/qcom/qdsp6/q6apm.c: In function 'q6apm_free_fragments':
>>> sound/soc/qcom/qdsp6/q6apm.c:321:39: warning: variable 'data' set but not used [-Wunused-but-set-variable]
Looks like some last minute cleanup added this warning, will fix this in
next spin, thanks for reporting this.
--srini
> 321 | struct audioreach_graph_data *data;
> | ^~~~
>
>
> vim +/data +321 sound/soc/qcom/qdsp6/q6apm.c
>
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 318
> ab4c5c6ed2ed1e Srinivas Kandagatla 2026-03-23 319 int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 320 {
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 @321 struct audioreach_graph_data *data;
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 322
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 323 if (dir == SNDRV_PCM_STREAM_PLAYBACK)
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 324 data = &graph->rx_data;
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 325 else
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 326 data = &graph->tx_data;
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 327
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 328 audioreach_graph_free_buf(graph);
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 329
> ab4c5c6ed2ed1e Srinivas Kandagatla 2026-03-23 330 return 0;
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 331 }
> ab4c5c6ed2ed1e Srinivas Kandagatla 2026-03-23 332 EXPORT_SYMBOL_GPL(q6apm_free_fragments);
> 25ab80db6b133c Srinivas Kandagatla 2021-10-26 333
>
^ permalink raw reply [flat|nested] 24+ messages in thread