[PATCH] ASoC: qcom: audioreach: support multichannel PCM formats

From: Zhangfei Gao

Date: Wed Oct 21 2026 - 06:27:53 EST


AudioReach currently rejects PCM streams with more than four channels in
the PCM and shared-memory media format paths.

Extend the default channel map to support PCM streams with up to eight
channels and relax the PCM and shared-memory media format validation
accordingly.

Signed-off-by: Zhangfei Gao <zhangfei.gao@xxxxxxxxxxxxxxxx>
---
sound/soc/qcom/qdsp6/audioreach.c | 74 ++++++++++++++++++++++++++-----
1 file changed, 62 insertions(+), 12 deletions(-)

diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index d2dc5d37bccf..626cfbca79c8 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -308,20 +308,70 @@ EXPORT_SYMBOL_GPL(audioreach_alloc_apm_cmd_pkt);

void audioreach_set_default_channel_mapping(u8 *ch_map, int num_channels)
{
- if (num_channels == 1) {
- ch_map[0] = PCM_CHANNEL_FL;
- } else if (num_channels == 2) {
- ch_map[0] = PCM_CHANNEL_FL;
- ch_map[1] = PCM_CHANNEL_FR;
- } else if (num_channels == 4) {
- ch_map[0] = PCM_CHANNEL_FL;
- ch_map[1] = PCM_CHANNEL_FR;
- ch_map[2] = PCM_CHANNEL_LS;
- ch_map[3] = PCM_CHANNEL_RS;
+ memset(ch_map, 0, AR_PCM_MAX_NUM_CHANNEL);
+
+ switch (num_channels) {
+ case 1:
+ ch_map[0] = PCM_CHANNEL_FL;
+ break;
+ case 2:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ break;
+ case 3:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_FC;
+ break;
+ case 4:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_LS;
+ ch_map[3] = PCM_CHANNEL_RS;
+ break;
+ case 5:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_FC;
+ ch_map[3] = PCM_CHANNEL_LS;
+ ch_map[4] = PCM_CHANNEL_RS;
+ break;
+ case 6:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_LFE;
+ ch_map[3] = PCM_CHANNEL_FC;
+ ch_map[4] = PCM_CHANNEL_LS;
+ ch_map[5] = PCM_CHANNEL_RS;
+ break;
+ case 7:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_LFE;
+ ch_map[3] = PCM_CHANNEL_FC;
+ ch_map[4] = PCM_CHANNEL_LS;
+ ch_map[5] = PCM_CHANNEL_RS;
+ ch_map[6] = PCM_CHANNEL_CS;
+ break;
+ case 8:
+ ch_map[0] = PCM_CHANNEL_FL;
+ ch_map[1] = PCM_CHANNEL_FR;
+ ch_map[2] = PCM_CHANNEL_LFE;
+ ch_map[3] = PCM_CHANNEL_FC;
+ ch_map[4] = PCM_CHANNEL_LS;
+ ch_map[5] = PCM_CHANNEL_RS;
+ ch_map[6] = PCM_CHANNEL_LB;
+ ch_map[7] = PCM_CHANNEL_RB;
+ break;
}
}
EXPORT_SYMBOL_GPL(audioreach_set_default_channel_mapping);

+static bool audioreach_channels_supported(u32 num_channels)
+{
+ return num_channels >= 1 && num_channels <= AR_PCM_MAX_NUM_CHANNEL;
+}
+
static void apm_populate_container_config(struct apm_container_obj *cfg,
const struct audioreach_container *cont)
{
@@ -1185,7 +1235,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
int payload_size;
int i, j;

- if (num_channels > 4) {
+ if (!audioreach_channels_supported(num_channels)) {
dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
return -EINVAL;
}
@@ -1275,7 +1325,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
int i, j;
void *p;

- if (num_channels > 4) {
+ if (!audioreach_channels_supported(num_channels)) {
dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
return -EINVAL;
}
--
2.43.0