* [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2
@ 2026-06-10 7:41 Neil Armstrong
2026-06-10 7:41 ` [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map Neil Armstrong
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: Neil Armstrong @ 2026-06-10 7:41 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Neil Armstrong, Srinivas Kandagatla
The Qualcom SM8650 based Ayaneo Pocket S2 gaming device has a set
of 2 WSA speakers connected on the WSA2 lines.
But the Audioreach DSP only handles WSA2 in pair with the WSA
interface by using the upper bits of the active_channels_mask
for WSA2 and the lower bits for WSA:
__________________________________________________
| Bits | 3 | 2 | 1 | 0 |
---------------------------------------------------
| Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
---------------------------------------------------
Setting only the WSA2 upper bits is perfectly valid and
functional but the current Audioreach code builds the bitmask
from the channels count with:
active_channels_mask = (1 << num_channels) - 1;
In order to enable the WSA2 bits the channel count should be 4,
but the lower WSA bits are then also enabled and the DSP errors
out when trying to play on the disabled WSA interface.
A solution would've been to add a fake WSA2 topology element which
would be translated into the top bits only, but it's not clean and
add some special exceptions in the generic Audioreach code.
The solution suggested by Srinivas is to use the channel mapping to
set this bitmask.
This works but makes all the other calls using the channel mapping fail
because the DSP requires the channel_mapping table to start from index 0
and using num_channel length in order to apply the mapping on the
active_channels_mask bits in order.
So if you have an active_channels_mask like:
_______________________
| Bits | 3 | 2 | 1 | 0 |
-------------------------
| Mask | 1 | 1 | 0 | 0 |
------------------------
And the channel mapping:
_________________________________
| Channel | 3 | 2 | 1 | 0 |
-----------------------------------
| Mapping | FR | FL | NULL | NULL |
-----------------------------------
Will need to be converted to:
____________________
| Channel | 1 | 0 |
---------------------
| Mapping | FR | FL |
---------------------
And the DSP will map FR on WSA2 Ch2 and FL on WSA2 Ch1 as:
_________________________________
| Line | WSA2 Ch2 | WSA2 Ch1 |
----------------------------------
| Mapping | FR | FL |
----------------------------------
So we need to skip the empty channel mapping entries in all other
users of the channel_map to build valid channel_mapping tables.
This should not break any other usecases since the default channel
mapping always start from index 0, and will add flexibilty to allow
some special non linear mapping for other interfaces as well.
Finally we add a special prepare callback for the Ayaneo PS2 sound card
which sets the custom channel mapping for the WSA interface to make audio
work properly on the gaming device.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Neil Armstrong (4):
ASoC: qcom: audioreach: compute active channel maps from channel_map
ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping
arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard
ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card
.../devicetree/bindings/sound/qcom,sm8250.yaml | 1 +
.../boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts | 2 +-
sound/soc/qcom/qdsp6/audioreach.c | 47 ++++++++++++++----
sound/soc/qcom/sc8280xp.c | 56 ++++++++++++++++++++++
4 files changed, 95 insertions(+), 11 deletions(-)
---
base-commit: 1ed783a6906ab62a54d631ff3e8c5cba0f4f4b54
change-id: 20260609-topic-sm8650-ayaneo-pocket-s2-wsa2-fix-eb90567f6ca5
Best regards,
--
Neil Armstrong <neil.armstrong@linaro.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map
2026-06-10 7:41 [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Neil Armstrong
@ 2026-06-10 7:41 ` Neil Armstrong
2026-06-15 8:38 ` Srinivas Kandagatla
2026-06-10 7:41 ` [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping Neil Armstrong
` (3 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2026-06-10 7:41 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Neil Armstrong, Srinivas Kandagatla
The Qualcom SM8650 based Ayaneo Pocket S2 gaming device has a set
of 2 WSA speakers connected on the WSA2 lines.
But the Audioreach DSP only handles WSA2 in pair with the WSA
interface by using the upper bits of the active_channels_mask
for WSA2 and the lower bits for WSA:
/-------------------------------------------------\
| Bits | 3 | 2 | 1 | 0 |
|-------------------------------------------------|
| Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
\-------------------------------------------------/
Setting only the WSA2 upper bits is perfectly valid and
functional but the current Audioreach code builds the bitmask
from the channels count with:
active_channels_mask = (1 << num_channels) - 1;
In order to enable the WSA2 bits the channel count should be 4,
but the lower WSA bits are then also enabled and the DSP errors
out when trying to play on the disabled WSA interface.
A solution would've been to add a fake WSA2 topology element which
would be translated into the top bits only, but it's not clean and
add some special exceptions in the generic Audioreach code.
The solution suggested by Srinivas is to use the channel mapping to
set this bitmask.
This works but makes all the other calls using the channel mapping fail
because the DSP requires the channel_mapping table to start from index 0
and using num_channel length in order to apply the mapping on the
active_channels_mask bits in order.
So we need to skip the empty channel mapping entries in all other
users of the channel_map to build valid channel_mapping tables.
This should not break any other usecases since the default channel
mapping always start from index 0, and will add flexibilty to allow
some special non linear mapping for other interfaces as well.
Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
sound/soc/qcom/qdsp6/audioreach.c | 47 ++++++++++++++++++++++++++++++---------
1 file changed, 37 insertions(+), 10 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index a13f753eff98..9b80cfa56e8a 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -703,6 +703,7 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
int pm_sz = APM_HW_EP_PMODE_CFG_PSIZE;
int size = ic_sz + ep_sz + fs_sz + pm_sz;
void *p;
+ int i;
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0);
if (IS_ERR(pkt))
@@ -741,7 +742,12 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
intf_cfg->cfg.lpaif_type = module->hw_interface_type;
intf_cfg->cfg.intf_index = module->hw_interface_idx;
- intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1;
+ intf_cfg->cfg.active_channels_mask = 0;
+ /* Convert the physical channel mapping into a bit field */
+ for (i = 0; i < AR_PCM_MAX_NUM_CHANNEL; i++)
+ if (cfg->channel_map[i])
+ intf_cfg->cfg.active_channels_mask |= BIT(i);
+
p += ic_sz;
pm_cfg = p;
@@ -840,7 +846,7 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
uint32_t num_channels = cfg->num_channels;
int payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) +
APM_MODULE_PARAM_DATA_SIZE;
- int i;
+ int i, j;
void *p;
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
@@ -860,8 +866,12 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
media_format->sample_rate = cfg->sample_rate;
media_format->bit_width = cfg->bit_width;
media_format->num_channels = cfg->num_channels;
- for (i = 0; i < num_channels; i++)
- media_format->channel_mapping[i] = cfg->channel_map[i];
+ /* Convert the physical mapping to a logical mapping of the channels */
+ for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) {
+ if (!cfg->channel_map[i])
+ continue;
+ media_format->channel_mapping[j++] = cfg->channel_map[i];
+ }
return q6apm_send_cmd_sync(graph->apm, pkt, 0);
}
@@ -1080,6 +1090,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
struct apm_pcm_module_media_fmt_cmd *cfg;
struct apm_module_param_data *param_data;
int payload_size;
+ int i, j;
if (num_channels > 4) {
dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
@@ -1113,7 +1124,12 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
media_cfg->num_channels = mcfg->num_channels;
media_cfg->q_factor = mcfg->bit_width - 1;
media_cfg->bits_per_sample = mcfg->bit_width;
- memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
+ /* Convert the physical mapping to a logical mapping of the channels */
+ for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < mcfg->num_channels; i++) {
+ if (!mcfg->channel_map[i])
+ continue;
+ media_cfg->channel_mapping[j++] = mcfg->channel_map[i];
+ }
return q6apm_send_cmd_sync(graph->apm, pkt, 0);
}
@@ -1127,6 +1143,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
struct payload_media_fmt_pcm *cfg;
struct media_format *header;
int rc, payload_size;
+ int i, j;
void *p;
if (num_channels > 4) {
@@ -1166,7 +1183,12 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
cfg->q_factor = mcfg->bit_width - 1;
cfg->endianness = PCM_LITTLE_ENDIAN;
cfg->num_channels = mcfg->num_channels;
- memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
+ /* Convert the physical mapping to a logical mapping of the channels */
+ for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) {
+ if (!mcfg->channel_map[i])
+ continue;
+ cfg->channel_mapping[j++] = mcfg->channel_map[i];
+ }
} else {
rc = audioreach_set_compr_media_format(header, p, mcfg);
if (rc)
@@ -1243,7 +1265,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
struct apm_module_sp_vi_ex_mode_cfg *ex_cfg;
int op_sz, cm_sz, ex_sz;
struct apm_module_param_data *param_data;
- int rc, i, payload_size;
+ int rc, i, payload_size, j;
struct gpr_pkt *pkt;
void *p;
@@ -1284,14 +1306,19 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
param_data->param_size = cm_sz - APM_MODULE_PARAM_DATA_SIZE;
cm_cfg->cfg.num_channels = num_channels * 2;
- for (i = 0; i < num_channels; i++) {
+ /* Convert the physical mapping to a logical mapping of the channels */
+ for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < num_channels; i++) {
+ if (!mcfg->channel_map[i])
+ continue;
/*
* Map speakers into Vsense and then Isense of each channel.
* E.g. for PCM_CHANNEL_FL and PCM_CHANNEL_FR to:
* [1, 2, 3, 4]
*/
- cm_cfg->cfg.channel_mapping[2 * i] = (mcfg->channel_map[i] - 1) * 2 + 1;
- cm_cfg->cfg.channel_mapping[2 * i + 1] = (mcfg->channel_map[i] - 1) * 2 + 2;
+ cm_cfg->cfg.channel_mapping[2 * j] = (mcfg->channel_map[i] - 1) * 2 + 1;
+ cm_cfg->cfg.channel_mapping[2 * j + 1] = (mcfg->channel_map[i] - 1) * 2 + 2;
+
+ ++j;
}
p += cm_sz;
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping
2026-06-10 7:41 [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Neil Armstrong
2026-06-10 7:41 ` [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map Neil Armstrong
@ 2026-06-10 7:41 ` Neil Armstrong
2026-06-15 8:42 ` Srinivas Kandagatla
2026-06-10 7:41 ` [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard Neil Armstrong
` (2 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2026-06-10 7:41 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Neil Armstrong
The WSA Speakers are connected on the WSA2 interface, but the
WSA and WSA2 links are handled as a single dai and DSP interface, so
we need to specify the channel mapping of the Ayaneo Pocket S2 for the
WSA dai in order to have functional playback and avoid DSP errors.
Let's add a special entry for the Ayaneo Pocket S2 adding a prepare
callback in order to set the proper channel mapping.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
sound/soc/qcom/sc8280xp.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
index 1f3afc6d015c..2f1688c9f317 100644
--- a/sound/soc/qcom/sc8280xp.c
+++ b/sound/soc/qcom/sc8280xp.c
@@ -14,6 +14,7 @@
#include "qdsp6/q6afe.h"
#include "qdsp6/q6apm.h"
#include "qdsp6/q6prm.h"
+#include "qdsp6/q6dsp-common.h"
#include "common.h"
#include "sdw.h"
@@ -49,6 +50,7 @@ struct snd_soc_common {
bool codec_sysclk_set;
bool mi2s_mclk_enable;
bool mi2s_bclk_enable;
+ int (*snd_prepare)(struct snd_pcm_substream *substream);
};
struct sc8280xp_snd_data {
@@ -193,12 +195,58 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+/*
+ * WSA and WSA2 are handled as a single interface with the
+ * following channels mask:
+ * __________________________________________________
+ * | Bits | 3 | 2 | 1 | 0 |
+ * ---------------------------------------------------
+ * | Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
+ * ---------------------------------------------------
+ *
+ * The Ayaneo Pocket S2 speakers are connected only to
+ * the WSA2 interface and the WSA interface is not enabled.
+ *
+ * Set the channel mapping on the WSA2 channels only.
+ */
+static const unsigned int ayaneo_ps2_channels_mapping[] = {
+ 0, /* WSA Ch1 */
+ 0, /* WSA Ch2 */
+ PCM_CHANNEL_FL, /* WSA2 Ch1 */
+ PCM_CHANNEL_FR /* WSA2 Ch2 */
+};
+
+static int ayaneo_ps2_snd_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ unsigned int channels = substream->runtime->channels;
+
+ if (cpu_dai->id != WSA_CODEC_DMA_RX_0)
+ return 0;
+
+ if (channels != 2)
+ return -EINVAL;
+
+ return snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
+ ARRAY_SIZE(ayaneo_ps2_channels_mapping),
+ ayaneo_ps2_channels_mapping);
+}
+
static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
+ if (data->snd_soc_common_priv->snd_prepare) {
+ int ret;
+
+ ret = data->snd_soc_common_priv->snd_prepare(substream);
+ if (ret)
+ return ret;
+ }
+
return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
}
@@ -273,6 +321,13 @@ static int sc8280xp_platform_probe(struct platform_device *pdev)
return devm_snd_soc_register_card(dev, card);
}
+static struct snd_soc_common ayaneo_ps2_priv_data = {
+ .driver_name = "ayaneo-ps2",
+ .dapm_widgets = sc8280xp_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets),
+ .snd_prepare = ayaneo_ps2_snd_prepare,
+};
+
static struct snd_soc_common kaanapali_priv_data = {
.driver_name = "kaanapali",
.dapm_widgets = sc8280xp_dapm_widgets,
@@ -341,6 +396,7 @@ static struct snd_soc_common sm8750_priv_data = {
};
static const struct of_device_id snd_sc8280xp_dt_match[] = {
+ {.compatible = "ayaneo,pocket-s2-sndcard", .data = &ayaneo_ps2_priv_data},
{.compatible = "qcom,kaanapali-sndcard", .data = &kaanapali_priv_data},
{.compatible = "qcom,qcm6490-idp-sndcard", .data = &qcm6490_priv_data},
{.compatible = "qcom,qcs615-sndcard", .data = &qcs615_priv_data},
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard
2026-06-10 7:41 [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Neil Armstrong
2026-06-10 7:41 ` [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map Neil Armstrong
2026-06-10 7:41 ` [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping Neil Armstrong
@ 2026-06-10 7:41 ` Neil Armstrong
2026-06-12 7:57 ` Dmitry Baryshkov
2026-06-10 7:41 ` [PATCH 4/4] ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card Neil Armstrong
2026-06-10 10:12 ` [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Mark Brown
4 siblings, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2026-06-10 7:41 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Neil Armstrong
Switch to the ayaneo,pocket-s2-sndcard since the hardware layout
is incompatible with the default SM8650 generic sound card.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
index 0dc994f4e48d..508d1445bf21 100644
--- a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
@@ -221,7 +221,7 @@ upd720201_vdd33_reg: upd720201-vdd33-regulator {
};
sound {
- compatible = "qcom,sm8650-sndcard", "qcom,sm8450-sndcard";
+ compatible = "ayaneo,pocket-s2-sndcard";
model = "SM8650-APS2";
audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT",
"SpkrRight IN", "WSA_SPK2 OUT",
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/4] ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card
2026-06-10 7:41 [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Neil Armstrong
` (2 preceding siblings ...)
2026-06-10 7:41 ` [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard Neil Armstrong
@ 2026-06-10 7:41 ` Neil Armstrong
2026-06-11 9:04 ` Krzysztof Kozlowski
2026-06-10 10:12 ` [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Mark Brown
4 siblings, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2026-06-10 7:41 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Neil Armstrong
Document the bindings for the sound card on the Ayaneo Pocket S2
which uses the special speaker connection incompatible with
the default SM8650 sound card.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
index 15f38622b98b..1fc458276ab3 100644
--- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml
@@ -29,6 +29,7 @@ properties:
- qcom,sm8750-sndcard
- const: qcom,sm8450-sndcard
- enum:
+ - ayaneo,pocket-s2-sndcard
- fairphone,fp4-sndcard
- fairphone,fp5-sndcard
- qcom,apq8096-sndcard
--
2.34.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2
2026-06-10 7:41 [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Neil Armstrong
` (3 preceding siblings ...)
2026-06-10 7:41 ` [PATCH 4/4] ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card Neil Armstrong
@ 2026-06-10 10:12 ` Mark Brown
2026-06-10 11:52 ` Neil Armstrong
4 siblings, 1 reply; 16+ messages in thread
From: Mark Brown @ 2026-06-10 10:12 UTC (permalink / raw)
To: Neil Armstrong
Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, kancy2333, linux-sound, linux-arm-msm, linux-kernel,
devicetree, Srinivas Kandagatla
[-- Attachment #1: Type: text/plain, Size: 209 bytes --]
On Wed, Jun 10, 2026 at 09:41:44AM +0200, Neil Armstrong wrote:
> ---
> base-commit: 1ed783a6906ab62a54d631ff3e8c5cba0f4f4b54
I don't seem to have this, it doesn't seem to be anything from my tree
or -next.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2
2026-06-10 10:12 ` [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Mark Brown
@ 2026-06-10 11:52 ` Neil Armstrong
0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2026-06-10 11:52 UTC (permalink / raw)
To: Mark Brown
Cc: Srinivas Kandagatla, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, kancy2333, linux-sound, linux-arm-msm, linux-kernel,
devicetree, Srinivas Kandagatla
On 6/10/26 12:12, Mark Brown wrote:
> On Wed, Jun 10, 2026 at 09:41:44AM +0200, Neil Armstrong wrote:
>
>> ---
>> base-commit: 1ed783a6906ab62a54d631ff3e8c5cba0f4f4b54
>
> I don't seem to have this, it doesn't seem to be anything from my tree
> or -next.
Sorry I forgot to add the dependency, it's based on v7.1-rc7 and depends on [1] for the sc8280xp card data.
[1] https://lore.kernel.org/all/20260608023011.942228-1-mohammad.rafi.shaik@oss.qualcomm.com/
Neil
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/4] ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card
2026-06-10 7:41 ` [PATCH 4/4] ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card Neil Armstrong
@ 2026-06-11 9:04 ` Krzysztof Kozlowski
0 siblings, 0 replies; 16+ messages in thread
From: Krzysztof Kozlowski @ 2026-06-11 9:04 UTC (permalink / raw)
To: Neil Armstrong
Cc: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, kancy2333, linux-sound,
linux-arm-msm, linux-kernel, devicetree
On Wed, Jun 10, 2026 at 09:41:48AM +0200, Neil Armstrong wrote:
> Document the bindings for the sound card on the Ayaneo Pocket S2
> which uses the special speaker connection incompatible with
> the default SM8650 sound card.
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
Please organize the patch documenting the compatible (DT bindings)
before the patch using that compatible.
See also: https://elixir.bootlin.com/linux/v6.14-rc6/source/Documentation/devicetree/bindings/submitting-patches.rst#L46
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard
2026-06-10 7:41 ` [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard Neil Armstrong
@ 2026-06-12 7:57 ` Dmitry Baryshkov
2026-06-12 7:59 ` Neil Armstrong
0 siblings, 1 reply; 16+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 7:57 UTC (permalink / raw)
To: Neil Armstrong
Cc: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, kancy2333, linux-sound,
linux-arm-msm, linux-kernel, devicetree
On Wed, Jun 10, 2026 at 09:41:47AM +0200, Neil Armstrong wrote:
> Switch to the ayaneo,pocket-s2-sndcard since the hardware layout
> is incompatible with the default SM8650 generic sound card.
Incompatible, how?
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
> index 0dc994f4e48d..508d1445bf21 100644
> --- a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
> +++ b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
> @@ -221,7 +221,7 @@ upd720201_vdd33_reg: upd720201-vdd33-regulator {
> };
>
> sound {
> - compatible = "qcom,sm8650-sndcard", "qcom,sm8450-sndcard";
> + compatible = "ayaneo,pocket-s2-sndcard";
> model = "SM8650-APS2";
> audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT",
> "SpkrRight IN", "WSA_SPK2 OUT",
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard
2026-06-12 7:57 ` Dmitry Baryshkov
@ 2026-06-12 7:59 ` Neil Armstrong
2026-06-12 8:23 ` Dmitry Baryshkov
0 siblings, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2026-06-12 7:59 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, kancy2333, linux-sound,
linux-arm-msm, linux-kernel, devicetree
On 6/12/26 09:57, Dmitry Baryshkov wrote:
> On Wed, Jun 10, 2026 at 09:41:47AM +0200, Neil Armstrong wrote:
>> Switch to the ayaneo,pocket-s2-sndcard since the hardware layout
>> is incompatible with the default SM8650 generic sound card.
>
> Incompatible, how?
As explained on the cover letter, the WAS speakers are not connected
on the same lines as the other devices handled by this card.
Neil
>
>>
>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>> ---
>> arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
>> index 0dc994f4e48d..508d1445bf21 100644
>> --- a/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
>> +++ b/arch/arm64/boot/dts/qcom/sm8650-ayaneo-pocket-s2.dts
>> @@ -221,7 +221,7 @@ upd720201_vdd33_reg: upd720201-vdd33-regulator {
>> };
>>
>> sound {
>> - compatible = "qcom,sm8650-sndcard", "qcom,sm8450-sndcard";
>> + compatible = "ayaneo,pocket-s2-sndcard";
>> model = "SM8650-APS2";
>> audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT",
>> "SpkrRight IN", "WSA_SPK2 OUT",
>>
>> --
>> 2.34.1
>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard
2026-06-12 7:59 ` Neil Armstrong
@ 2026-06-12 8:23 ` Dmitry Baryshkov
2026-06-12 8:30 ` Neil Armstrong
0 siblings, 1 reply; 16+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 8:23 UTC (permalink / raw)
To: Neil Armstrong
Cc: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, kancy2333, linux-sound,
linux-arm-msm, linux-kernel, devicetree
On Fri, Jun 12, 2026 at 09:59:02AM +0200, Neil Armstrong wrote:
> On 6/12/26 09:57, Dmitry Baryshkov wrote:
> > On Wed, Jun 10, 2026 at 09:41:47AM +0200, Neil Armstrong wrote:
> > > Switch to the ayaneo,pocket-s2-sndcard since the hardware layout
> > > is incompatible with the default SM8650 generic sound card.
> >
> > Incompatible, how?
>
> As explained on the cover letter, the WAS speakers are not connected
> on the same lines as the other devices handled by this card.
The cover letter isn't recorded in the Git history. Somebody looking at
the commit in a year should not have to look in the mail archive to
understand what is incompatible.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard
2026-06-12 8:23 ` Dmitry Baryshkov
@ 2026-06-12 8:30 ` Neil Armstrong
0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2026-06-12 8:30 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, kancy2333, linux-sound,
linux-arm-msm, linux-kernel, devicetree
On 6/12/26 10:23, Dmitry Baryshkov wrote:
> On Fri, Jun 12, 2026 at 09:59:02AM +0200, Neil Armstrong wrote:
>> On 6/12/26 09:57, Dmitry Baryshkov wrote:
>>> On Wed, Jun 10, 2026 at 09:41:47AM +0200, Neil Armstrong wrote:
>>>> Switch to the ayaneo,pocket-s2-sndcard since the hardware layout
>>>> is incompatible with the default SM8650 generic sound card.
>>>
>>> Incompatible, how?
>>
>> As explained on the cover letter, the WAS speakers are not connected
>> on the same lines as the other devices handled by this card.
>
> The cover letter isn't recorded in the Git history. Somebody looking at
> the commit in a year should not have to look in the mail archive to
> understand what is incompatible.
Will update the commit message aligned with the bindings change.
Neil
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map
2026-06-10 7:41 ` [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map Neil Armstrong
@ 2026-06-15 8:38 ` Srinivas Kandagatla
2026-06-15 9:31 ` Neil Armstrong
0 siblings, 1 reply; 16+ messages in thread
From: Srinivas Kandagatla @ 2026-06-15 8:38 UTC (permalink / raw)
To: Neil Armstrong, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Srinivas Kandagatla
On 6/10/26 8:41 AM, Neil Armstrong wrote:
> The Qualcom SM8650 based Ayaneo Pocket S2 gaming device has a set
> of 2 WSA speakers connected on the WSA2 lines.
>
> But the Audioreach DSP only handles WSA2 in pair with the WSA
> interface by using the upper bits of the active_channels_mask
> for WSA2 and the lower bits for WSA:
>
> /-------------------------------------------------\
> | Bits | 3 | 2 | 1 | 0 |
> |-------------------------------------------------|
> | Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
> \-------------------------------------------------/
>
No, this is not totally correct, if the setup only has WSA2, then
channel 0 and 1 should be WSA2 channels.
What is the backend dai id that is in DT, it should be
sound-dai = <&q6apmbedai WSA2_CODEC_DMA_RX_0>;
I also noticed that you are using
https://github.com/linux-msm/audioreach-topology/blob/main/SM8550-HDK.m4
which has WSA as backend dai, that is not correct, you should have WSA2.
> Setting only the WSA2 upper bits is perfectly valid and
> functional but the current Audioreach code builds the bitmask
> from the channels count with:
> active_channels_mask = (1 << num_channels) - 1;
>
> In order to enable the WSA2 bits the channel count should be 4,
> but the lower WSA bits are then also enabled and the DSP errors
> out when trying to play on the disabled WSA interface.
>
> A solution would've been to add a fake WSA2 topology element which
> would be translated into the top bits only, but it's not clean and
> add some special exceptions in the generic Audioreach code.
>
> The solution suggested by Srinivas is to use the channel mapping to
> set this bitmask.
>
> This works but makes all the other calls using the channel mapping fail
> because the DSP requires the channel_mapping table to start from index 0
> and using num_channel length in order to apply the mapping on the
> active_channels_mask bits in order.
>
> So we need to skip the empty channel mapping entries in all other
> users of the channel_map to build valid channel_mapping tables.
>
> This should not break any other usecases since the default channel
> mapping always start from index 0, and will add flexibilty to allow
> some special non linear mapping for other interfaces as well.
>
> Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> sound/soc/qcom/qdsp6/audioreach.c | 47 ++++++++++++++++++++++++++++++---------
> 1 file changed, 37 insertions(+), 10 deletions(-)
>
> diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
> index a13f753eff98..9b80cfa56e8a 100644
> --- a/sound/soc/qcom/qdsp6/audioreach.c
> +++ b/sound/soc/qcom/qdsp6/audioreach.c
> @@ -703,6 +703,7 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
> int pm_sz = APM_HW_EP_PMODE_CFG_PSIZE;
> int size = ic_sz + ep_sz + fs_sz + pm_sz;
> void *p;
> + int i;
>
> struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0);
> if (IS_ERR(pkt))
> @@ -741,7 +742,12 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
>
> intf_cfg->cfg.lpaif_type = module->hw_interface_type;
> intf_cfg->cfg.intf_index = module->hw_interface_idx;
> - intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1;
> + intf_cfg->cfg.active_channels_mask = 0;
> + /* Convert the physical channel mapping into a bit field */
> + for (i = 0; i < AR_PCM_MAX_NUM_CHANNEL; i++)
> + if (cfg->channel_map[i])
> + intf_cfg->cfg.active_channels_mask |= BIT(i);
> +
This one looks good, this should be a bug fix patch.
> p += ic_sz;
>
> pm_cfg = p;
> @@ -840,7 +846,7 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
> uint32_t num_channels = cfg->num_channels;
> int payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) +
> APM_MODULE_PARAM_DATA_SIZE;
> - int i;
> + int i, j;
> void *p;
>
> struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
> @@ -860,8 +866,12 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
> media_format->sample_rate = cfg->sample_rate;
> media_format->bit_width = cfg->bit_width;
> media_format->num_channels = cfg->num_channels;
> - for (i = 0; i < num_channels; i++)
> - media_format->channel_mapping[i] = cfg->channel_map[i];
> + /* Convert the physical mapping to a logical mapping of the channels */
> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) {
> + if (!cfg->channel_map[i])
> + continue;
> + media_format->channel_mapping[j++] = cfg->channel_map[i];
Each element i of the channel_mapping[i] array, describes the channel i
inside the buffer where i is less than num_channels. An unused channel
is set to 0.
For some reason I get impression that user is trying to set a 4 channels
instead of 2 channel.
Can you fix the backend-dai id and play it directly on WSA2 instead of WSA.
Or was there a reason for not doing it otherwise?
--srini
> + }
>
> return q6apm_send_cmd_sync(graph->apm, pkt, 0);
> }
> @@ -1080,6 +1090,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
> struct apm_pcm_module_media_fmt_cmd *cfg;
> struct apm_module_param_data *param_data;
> int payload_size;
> + int i, j;
>
> if (num_channels > 4) {
> dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
> @@ -1113,7 +1124,12 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
> media_cfg->num_channels = mcfg->num_channels;
> media_cfg->q_factor = mcfg->bit_width - 1;
> media_cfg->bits_per_sample = mcfg->bit_width;
> - memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
> + /* Convert the physical mapping to a logical mapping of the channels */
> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < mcfg->num_channels; i++) {
> + if (!mcfg->channel_map[i])
> + continue;
> + media_cfg->channel_mapping[j++] = mcfg->channel_map[i];
> + }
>
> return q6apm_send_cmd_sync(graph->apm, pkt, 0);
> }
> @@ -1127,6 +1143,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
> struct payload_media_fmt_pcm *cfg;
> struct media_format *header;
> int rc, payload_size;
> + int i, j;
> void *p;
>
> if (num_channels > 4) {
> @@ -1166,7 +1183,12 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
> cfg->q_factor = mcfg->bit_width - 1;
> cfg->endianness = PCM_LITTLE_ENDIAN;
> cfg->num_channels = mcfg->num_channels;
> - memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
> + /* Convert the physical mapping to a logical mapping of the channels */
> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) {
> + if (!mcfg->channel_map[i])
> + continue;
> + cfg->channel_mapping[j++] = mcfg->channel_map[i];
> + }
> } else {
> rc = audioreach_set_compr_media_format(header, p, mcfg);
> if (rc)
> @@ -1243,7 +1265,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
> struct apm_module_sp_vi_ex_mode_cfg *ex_cfg;
> int op_sz, cm_sz, ex_sz;
> struct apm_module_param_data *param_data;
> - int rc, i, payload_size;
> + int rc, i, payload_size, j;
> struct gpr_pkt *pkt;
> void *p;
>
> @@ -1284,14 +1306,19 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
> param_data->param_size = cm_sz - APM_MODULE_PARAM_DATA_SIZE;
>
> cm_cfg->cfg.num_channels = num_channels * 2;
> - for (i = 0; i < num_channels; i++) {
> + /* Convert the physical mapping to a logical mapping of the channels */
> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < num_channels; i++) {
> + if (!mcfg->channel_map[i])
> + continue;
> /*
> * Map speakers into Vsense and then Isense of each channel.
> * E.g. for PCM_CHANNEL_FL and PCM_CHANNEL_FR to:
> * [1, 2, 3, 4]
> */
> - cm_cfg->cfg.channel_mapping[2 * i] = (mcfg->channel_map[i] - 1) * 2 + 1;
> - cm_cfg->cfg.channel_mapping[2 * i + 1] = (mcfg->channel_map[i] - 1) * 2 + 2;
> + cm_cfg->cfg.channel_mapping[2 * j] = (mcfg->channel_map[i] - 1) * 2 + 1;
> + cm_cfg->cfg.channel_mapping[2 * j + 1] = (mcfg->channel_map[i] - 1) * 2 + 2;
> +
> + ++j;
> }
>
> p += cm_sz;
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping
2026-06-10 7:41 ` [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping Neil Armstrong
@ 2026-06-15 8:42 ` Srinivas Kandagatla
0 siblings, 0 replies; 16+ messages in thread
From: Srinivas Kandagatla @ 2026-06-15 8:42 UTC (permalink / raw)
To: Neil Armstrong, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree
Thanks Neil for the patch.
On 6/10/26 8:41 AM, Neil Armstrong wrote:
> The WSA Speakers are connected on the WSA2 interface, but the
> WSA and WSA2 links are handled as a single dai and DSP interface, so
> we need to specify the channel mapping of the Ayaneo Pocket S2 for the
> WSA dai in order to have functional playback and avoid DSP errors.
>
> Let's add a special entry for the Ayaneo Pocket S2 adding a prepare
> callback in order to set the proper channel mapping.
>
> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
> sound/soc/qcom/sc8280xp.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 56 insertions(+)
>
> diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
> index 1f3afc6d015c..2f1688c9f317 100644
> --- a/sound/soc/qcom/sc8280xp.c
> +++ b/sound/soc/qcom/sc8280xp.c
> @@ -14,6 +14,7 @@
> #include "qdsp6/q6afe.h"
> #include "qdsp6/q6apm.h"
> #include "qdsp6/q6prm.h"
> +#include "qdsp6/q6dsp-common.h"
> #include "common.h"
> #include "sdw.h"
>
> @@ -49,6 +50,7 @@ struct snd_soc_common {
> bool codec_sysclk_set;
> bool mi2s_mclk_enable;
> bool mi2s_bclk_enable;
> + int (*snd_prepare)(struct snd_pcm_substream *substream);
> };
>
> struct sc8280xp_snd_data {
> @@ -193,12 +195,58 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream,
> return 0;
> }
>
> +/*
> + * WSA and WSA2 are handled as a single interface with the
> + * following channels mask:
It should not be handled as single interface in this case, you could use
WSA2 as it is.
> + * __________________________________________________
> + * | Bits | 3 | 2 | 1 | 0 |
> + * ---------------------------------------------------
> + * | Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
> + * ---------------------------------------------------
> + *
> + * The Ayaneo Pocket S2 speakers are connected only to
> + * the WSA2 interface and the WSA interface is not enabled.
> + *
> + * Set the channel mapping on the WSA2 channels only.
> + */
> +static const unsigned int ayaneo_ps2_channels_mapping[] = {
> + 0, /* WSA Ch1 */
> + 0, /* WSA Ch2 */
> + PCM_CHANNEL_FL, /* WSA2 Ch1 */
> + PCM_CHANNEL_FR /* WSA2 Ch2 */
> +};
So we are are playing 4 channels on a 2 channel speakers?
There is also a patch by Abel, on allowing userspace/ucm to set the
channel map for WSA at https://lkml.org/lkml/2026/6/10/1002
Its worth having a look.
--srini
> +
> +static int ayaneo_ps2_snd_prepare(struct snd_pcm_substream *substream)
> +{
> + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
> + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
> + unsigned int channels = substream->runtime->channels;
> +
> + if (cpu_dai->id != WSA_CODEC_DMA_RX_0)
> + return 0;
> +
> + if (channels != 2)
> + return -EINVAL;
> +
> + return snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
> + ARRAY_SIZE(ayaneo_ps2_channels_mapping),
> + ayaneo_ps2_channels_mapping);
> +}
> +
> static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream)
> {
> struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
> struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
> struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
>
> + if (data->snd_soc_common_priv->snd_prepare) {
> + int ret;
> +
> + ret = data->snd_soc_common_priv->snd_prepare(substream);
> + if (ret)
> + return ret;
> + }
> +
> return qcom_snd_sdw_prepare(substream, &data->stream_prepared[cpu_dai->id]);
> }
>
> @@ -273,6 +321,13 @@ static int sc8280xp_platform_probe(struct platform_device *pdev)
> return devm_snd_soc_register_card(dev, card);
> }
>
> +static struct snd_soc_common ayaneo_ps2_priv_data = {
> + .driver_name = "ayaneo-ps2",
> + .dapm_widgets = sc8280xp_dapm_widgets,
> + .num_dapm_widgets = ARRAY_SIZE(sc8280xp_dapm_widgets),
> + .snd_prepare = ayaneo_ps2_snd_prepare,
> +};
> +
> static struct snd_soc_common kaanapali_priv_data = {
> .driver_name = "kaanapali",
> .dapm_widgets = sc8280xp_dapm_widgets,
> @@ -341,6 +396,7 @@ static struct snd_soc_common sm8750_priv_data = {
> };
>
> static const struct of_device_id snd_sc8280xp_dt_match[] = {
> + {.compatible = "ayaneo,pocket-s2-sndcard", .data = &ayaneo_ps2_priv_data},
> {.compatible = "qcom,kaanapali-sndcard", .data = &kaanapali_priv_data},
> {.compatible = "qcom,qcm6490-idp-sndcard", .data = &qcm6490_priv_data},
> {.compatible = "qcom,qcs615-sndcard", .data = &qcs615_priv_data},
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map
2026-06-15 8:38 ` Srinivas Kandagatla
@ 2026-06-15 9:31 ` Neil Armstrong
2026-06-15 9:36 ` Srinivas Kandagatla
0 siblings, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2026-06-15 9:31 UTC (permalink / raw)
To: Srinivas Kandagatla, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree,
Srinivas Kandagatla
On 6/15/26 10:38, Srinivas Kandagatla wrote:
>
>
> On 6/10/26 8:41 AM, Neil Armstrong wrote:
>> The Qualcom SM8650 based Ayaneo Pocket S2 gaming device has a set
>> of 2 WSA speakers connected on the WSA2 lines.
>>
>> But the Audioreach DSP only handles WSA2 in pair with the WSA
>> interface by using the upper bits of the active_channels_mask
>> for WSA2 and the lower bits for WSA:
>>
>> /-------------------------------------------------\
>> | Bits | 3 | 2 | 1 | 0 |
>> |-------------------------------------------------|
>> | Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
>> \-------------------------------------------------/
>>
> No, this is not totally correct, if the setup only has WSA2, then
> channel 0 and 1 should be WSA2 channels.
>
> What is the backend dai id that is in DT, it should be
>
> sound-dai = <&q6apmbedai WSA2_CODEC_DMA_RX_0>;
>
> I also noticed that you are using
> https://github.com/linux-msm/audioreach-topology/blob/main/SM8550-HDK.m4
> which has WSA as backend dai, that is not correct, you should have WSA2.
So I did try that, and DSP would error out when using the LPAIF_INTF_TYPE_WSA2,
but I'm retrying from scratch right now.
Thanks,
Neil
>
>
>> Setting only the WSA2 upper bits is perfectly valid and
>> functional but the current Audioreach code builds the bitmask
>> from the channels count with:
>> active_channels_mask = (1 << num_channels) - 1;
>>
>> In order to enable the WSA2 bits the channel count should be 4,
>> but the lower WSA bits are then also enabled and the DSP errors
>> out when trying to play on the disabled WSA interface.
>>
>> A solution would've been to add a fake WSA2 topology element which
>> would be translated into the top bits only, but it's not clean and
>> add some special exceptions in the generic Audioreach code.
>>
>> The solution suggested by Srinivas is to use the channel mapping to
>> set this bitmask.
>>
>> This works but makes all the other calls using the channel mapping fail
>> because the DSP requires the channel_mapping table to start from index 0
>> and using num_channel length in order to apply the mapping on the
>> active_channels_mask bits in order.
>>
>> So we need to skip the empty channel mapping entries in all other
>> users of the channel_map to build valid channel_mapping tables.
>>
>> This should not break any other usecases since the default channel
>> mapping always start from index 0, and will add flexibilty to allow
>> some special non linear mapping for other interfaces as well.
>>
>> Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>> ---
>> sound/soc/qcom/qdsp6/audioreach.c | 47 ++++++++++++++++++++++++++++++---------
>> 1 file changed, 37 insertions(+), 10 deletions(-)
>>
>> diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
>> index a13f753eff98..9b80cfa56e8a 100644
>> --- a/sound/soc/qcom/qdsp6/audioreach.c
>> +++ b/sound/soc/qcom/qdsp6/audioreach.c
>> @@ -703,6 +703,7 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
>> int pm_sz = APM_HW_EP_PMODE_CFG_PSIZE;
>> int size = ic_sz + ep_sz + fs_sz + pm_sz;
>> void *p;
>> + int i;
>>
>> struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0);
>> if (IS_ERR(pkt))
>> @@ -741,7 +742,12 @@ static int audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
>>
>> intf_cfg->cfg.lpaif_type = module->hw_interface_type;
>> intf_cfg->cfg.intf_index = module->hw_interface_idx;
>> - intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1;
>> + intf_cfg->cfg.active_channels_mask = 0;
>> + /* Convert the physical channel mapping into a bit field */
>> + for (i = 0; i < AR_PCM_MAX_NUM_CHANNEL; i++)
>> + if (cfg->channel_map[i])
>> + intf_cfg->cfg.active_channels_mask |= BIT(i);
>> +
>
> This one looks good, this should be a bug fix patch.
>
>> p += ic_sz;
>>
>> pm_cfg = p;
>> @@ -840,7 +846,7 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
>> uint32_t num_channels = cfg->num_channels;
>> int payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) +
>> APM_MODULE_PARAM_DATA_SIZE;
>> - int i;
>> + int i, j;
>> void *p;
>>
>> struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
>> @@ -860,8 +866,12 @@ static int audioreach_mfc_set_media_format(struct q6apm_graph *graph,
>> media_format->sample_rate = cfg->sample_rate;
>> media_format->bit_width = cfg->bit_width;
>> media_format->num_channels = cfg->num_channels;
>> - for (i = 0; i < num_channels; i++)
>> - media_format->channel_mapping[i] = cfg->channel_map[i];
>> + /* Convert the physical mapping to a logical mapping of the channels */
>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) {
>> + if (!cfg->channel_map[i])
>> + continue;
>> + media_format->channel_mapping[j++] = cfg->channel_map[i];
> Each element i of the channel_mapping[i] array, describes the channel i
> inside the buffer where i is less than num_channels. An unused channel
> is set to 0.
>
> For some reason I get impression that user is trying to set a 4 channels
> instead of 2 channel.
>
> Can you fix the backend-dai id and play it directly on WSA2 instead of WSA.
> Or was there a reason for not doing it otherwise?
>
> --srini
>
>> + }
>>
>> return q6apm_send_cmd_sync(graph->apm, pkt, 0);
>> }
>> @@ -1080,6 +1090,7 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
>> struct apm_pcm_module_media_fmt_cmd *cfg;
>> struct apm_module_param_data *param_data;
>> int payload_size;
>> + int i, j;
>>
>> if (num_channels > 4) {
>> dev_err(graph->dev, "Error: Invalid channels (%d)!\n", num_channels);
>> @@ -1113,7 +1124,12 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
>> media_cfg->num_channels = mcfg->num_channels;
>> media_cfg->q_factor = mcfg->bit_width - 1;
>> media_cfg->bits_per_sample = mcfg->bit_width;
>> - memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
>> + /* Convert the physical mapping to a logical mapping of the channels */
>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < mcfg->num_channels; i++) {
>> + if (!mcfg->channel_map[i])
>> + continue;
>> + media_cfg->channel_mapping[j++] = mcfg->channel_map[i];
>> + }
>>
>> return q6apm_send_cmd_sync(graph->apm, pkt, 0);
>> }
>> @@ -1127,6 +1143,7 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
>> struct payload_media_fmt_pcm *cfg;
>> struct media_format *header;
>> int rc, payload_size;
>> + int i, j;
>> void *p;
>>
>> if (num_channels > 4) {
>> @@ -1166,7 +1183,12 @@ static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
>> cfg->q_factor = mcfg->bit_width - 1;
>> cfg->endianness = PCM_LITTLE_ENDIAN;
>> cfg->num_channels = mcfg->num_channels;
>> - memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg->num_channels);
>> + /* Convert the physical mapping to a logical mapping of the channels */
>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg->num_channels; i++) {
>> + if (!mcfg->channel_map[i])
>> + continue;
>> + cfg->channel_mapping[j++] = mcfg->channel_map[i];
>> + }
>> } else {
>> rc = audioreach_set_compr_media_format(header, p, mcfg);
>> if (rc)
>> @@ -1243,7 +1265,7 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
>> struct apm_module_sp_vi_ex_mode_cfg *ex_cfg;
>> int op_sz, cm_sz, ex_sz;
>> struct apm_module_param_data *param_data;
>> - int rc, i, payload_size;
>> + int rc, i, payload_size, j;
>> struct gpr_pkt *pkt;
>> void *p;
>>
>> @@ -1284,14 +1306,19 @@ static int audioreach_speaker_protection_vi(struct q6apm_graph *graph,
>> param_data->param_size = cm_sz - APM_MODULE_PARAM_DATA_SIZE;
>>
>> cm_cfg->cfg.num_channels = num_channels * 2;
>> - for (i = 0; i < num_channels; i++) {
>> + /* Convert the physical mapping to a logical mapping of the channels */
>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < num_channels; i++) {
>> + if (!mcfg->channel_map[i])
>> + continue;
>> /*
>> * Map speakers into Vsense and then Isense of each channel.
>> * E.g. for PCM_CHANNEL_FL and PCM_CHANNEL_FR to:
>> * [1, 2, 3, 4]
>> */
>> - cm_cfg->cfg.channel_mapping[2 * i] = (mcfg->channel_map[i] - 1) * 2 + 1;
>> - cm_cfg->cfg.channel_mapping[2 * i + 1] = (mcfg->channel_map[i] - 1) * 2 + 2;
>> + cm_cfg->cfg.channel_mapping[2 * j] = (mcfg->channel_map[i] - 1) * 2 + 1;
>> + cm_cfg->cfg.channel_mapping[2 * j + 1] = (mcfg->channel_map[i] - 1) * 2 + 2;
>> +
>> + ++j;
>> }
>>
>> p += cm_sz;
>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map
2026-06-15 9:31 ` Neil Armstrong
@ 2026-06-15 9:36 ` Srinivas Kandagatla
0 siblings, 0 replies; 16+ messages in thread
From: Srinivas Kandagatla @ 2026-06-15 9:36 UTC (permalink / raw)
To: Neil Armstrong, Srinivas Kandagatla, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree
On 6/15/26 10:31 AM, Neil Armstrong wrote:
> On 6/15/26 10:38, Srinivas Kandagatla wrote:
>>
>>
>> On 6/10/26 8:41 AM, Neil Armstrong wrote:
>>> The Qualcom SM8650 based Ayaneo Pocket S2 gaming device has a set
>>> of 2 WSA speakers connected on the WSA2 lines.
>>>
>>> But the Audioreach DSP only handles WSA2 in pair with the WSA
>>> interface by using the upper bits of the active_channels_mask
>>> for WSA2 and the lower bits for WSA:
>>>
>>> /-------------------------------------------------\
>>> | Bits | 3 | 2 | 1 | 0 |
>>> |-------------------------------------------------|
>>> | Line | WSA2 Ch2 | WSA2 Ch1 | WSA Ch2 | WSA Ch1 |
>>> \-------------------------------------------------/
>>>
>> No, this is not totally correct, if the setup only has WSA2, then
>> channel 0 and 1 should be WSA2 channels.
>>
>> What is the backend dai id that is in DT, it should be
>>
>> sound-dai = <&q6apmbedai WSA2_CODEC_DMA_RX_0>;
>>
>> I also noticed that you are using
>> https://github.com/linux-msm/audioreach-topology/blob/main/SM8550-HDK.m4
>> which has WSA as backend dai, that is not correct, you should have WSA2.
>
> So I did try that, and DSP would error out when using the
> LPAIF_INTF_TYPE_WSA2,
> but I'm retrying from scratch right now.
Please share the failure logs, we need to change
1. dt : bedai id, codec dais with correct soundwire wsa2 instance, the
routes.
2. tplg
--srini
>
> Thanks,
> Neil
>
>>
>>
>>> Setting only the WSA2 upper bits is perfectly valid and
>>> functional but the current Audioreach code builds the bitmask
>>> from the channels count with:
>>> active_channels_mask = (1 << num_channels) - 1;
>>>
>>> In order to enable the WSA2 bits the channel count should be 4,
>>> but the lower WSA bits are then also enabled and the DSP errors
>>> out when trying to play on the disabled WSA interface.
>>>
>>> A solution would've been to add a fake WSA2 topology element which
>>> would be translated into the top bits only, but it's not clean and
>>> add some special exceptions in the generic Audioreach code.
>>>
>>> The solution suggested by Srinivas is to use the channel mapping to
>>> set this bitmask.
>>>
>>> This works but makes all the other calls using the channel mapping fail
>>> because the DSP requires the channel_mapping table to start from index 0
>>> and using num_channel length in order to apply the mapping on the
>>> active_channels_mask bits in order.
>>>
>>> So we need to skip the empty channel mapping entries in all other
>>> users of the channel_map to build valid channel_mapping tables.
>>>
>>> This should not break any other usecases since the default channel
>>> mapping always start from index 0, and will add flexibilty to allow
>>> some special non linear mapping for other interfaces as well.
>>>
>>> Suggested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
>>> Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
>>> ---
>>> sound/soc/qcom/qdsp6/audioreach.c | 47 ++++++++++++++++++++++++++++
>>> ++---------
>>> 1 file changed, 37 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/
>>> qdsp6/audioreach.c
>>> index a13f753eff98..9b80cfa56e8a 100644
>>> --- a/sound/soc/qcom/qdsp6/audioreach.c
>>> +++ b/sound/soc/qcom/qdsp6/audioreach.c
>>> @@ -703,6 +703,7 @@ static int
>>> audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
>>> int pm_sz = APM_HW_EP_PMODE_CFG_PSIZE;
>>> int size = ic_sz + ep_sz + fs_sz + pm_sz;
>>> void *p;
>>> + int i;
>>> struct gpr_pkt *pkt __free(kfree) =
>>> audioreach_alloc_apm_cmd_pkt(size, APM_CMD_SET_CFG, 0);
>>> if (IS_ERR(pkt))
>>> @@ -741,7 +742,12 @@ static int
>>> audioreach_codec_dma_set_media_format(struct q6apm_graph *graph,
>>> intf_cfg->cfg.lpaif_type = module->hw_interface_type;
>>> intf_cfg->cfg.intf_index = module->hw_interface_idx;
>>> - intf_cfg->cfg.active_channels_mask = (1 << cfg->num_channels) - 1;
>>> + intf_cfg->cfg.active_channels_mask = 0;
>>> + /* Convert the physical channel mapping into a bit field */
>>> + for (i = 0; i < AR_PCM_MAX_NUM_CHANNEL; i++)
>>> + if (cfg->channel_map[i])
>>> + intf_cfg->cfg.active_channels_mask |= BIT(i);
>>> +
>>
>> This one looks good, this should be a bug fix patch.
>>
>>> p += ic_sz;
>>> pm_cfg = p;
>>> @@ -840,7 +846,7 @@ static int audioreach_mfc_set_media_format(struct
>>> q6apm_graph *graph,
>>> uint32_t num_channels = cfg->num_channels;
>>> int payload_size = APM_MFC_CFG_PSIZE(media_format, num_channels) +
>>> APM_MODULE_PARAM_DATA_SIZE;
>>> - int i;
>>> + int i, j;
>>> void *p;
>>> struct gpr_pkt *pkt __free(kfree) =
>>> audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
>>> @@ -860,8 +866,12 @@ static int
>>> audioreach_mfc_set_media_format(struct q6apm_graph *graph,
>>> media_format->sample_rate = cfg->sample_rate;
>>> media_format->bit_width = cfg->bit_width;
>>> media_format->num_channels = cfg->num_channels;
>>> - for (i = 0; i < num_channels; i++)
>>> - media_format->channel_mapping[i] = cfg->channel_map[i];
>>> + /* Convert the physical mapping to a logical mapping of the
>>> channels */
>>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg-
>>> >num_channels; i++) {
>>> + if (!cfg->channel_map[i])
>>> + continue;
>>> + media_format->channel_mapping[j++] = cfg->channel_map[i];
>> Each element i of the channel_mapping[i] array, describes the channel i
>> inside the buffer where i is less than num_channels. An unused channel
>> is set to 0.
>>
>> For some reason I get impression that user is trying to set a 4 channels
>> instead of 2 channel.
>>
>> Can you fix the backend-dai id and play it directly on WSA2 instead of
>> WSA.
>> Or was there a reason for not doing it otherwise?
>>
>> --srini
>>
>>> + }
>>> return q6apm_send_cmd_sync(graph->apm, pkt, 0);
>>> }
>>> @@ -1080,6 +1090,7 @@ static int
>>> audioreach_pcm_set_media_format(struct q6apm_graph *graph,
>>> struct apm_pcm_module_media_fmt_cmd *cfg;
>>> struct apm_module_param_data *param_data;
>>> int payload_size;
>>> + int i, j;
>>> if (num_channels > 4) {
>>> dev_err(graph->dev, "Error: Invalid channels (%d)!\n",
>>> num_channels);
>>> @@ -1113,7 +1124,12 @@ static int
>>> audioreach_pcm_set_media_format(struct q6apm_graph *graph,
>>> media_cfg->num_channels = mcfg->num_channels;
>>> media_cfg->q_factor = mcfg->bit_width - 1;
>>> media_cfg->bits_per_sample = mcfg->bit_width;
>>> - memcpy(media_cfg->channel_mapping, mcfg->channel_map, mcfg-
>>> >num_channels);
>>> + /* Convert the physical mapping to a logical mapping of the
>>> channels */
>>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < mcfg-
>>> >num_channels; i++) {
>>> + if (!mcfg->channel_map[i])
>>> + continue;
>>> + media_cfg->channel_mapping[j++] = mcfg->channel_map[i];
>>> + }
>>> return q6apm_send_cmd_sync(graph->apm, pkt, 0);
>>> }
>>> @@ -1127,6 +1143,7 @@ static int
>>> audioreach_shmem_set_media_format(struct q6apm_graph *graph,
>>> struct payload_media_fmt_pcm *cfg;
>>> struct media_format *header;
>>> int rc, payload_size;
>>> + int i, j;
>>> void *p;
>>> if (num_channels > 4) {
>>> @@ -1166,7 +1183,12 @@ static int
>>> audioreach_shmem_set_media_format(struct q6apm_graph *graph,
>>> cfg->q_factor = mcfg->bit_width - 1;
>>> cfg->endianness = PCM_LITTLE_ENDIAN;
>>> cfg->num_channels = mcfg->num_channels;
>>> - memcpy(cfg->channel_mapping, mcfg->channel_map, mcfg-
>>> >num_channels);
>>> + /* Convert the physical mapping to a logical mapping of the
>>> channels */
>>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j < cfg-
>>> >num_channels; i++) {
>>> + if (!mcfg->channel_map[i])
>>> + continue;
>>> + cfg->channel_mapping[j++] = mcfg->channel_map[i];
>>> + }
>>> } else {
>>> rc = audioreach_set_compr_media_format(header, p, mcfg);
>>> if (rc)
>>> @@ -1243,7 +1265,7 @@ static int
>>> audioreach_speaker_protection_vi(struct q6apm_graph *graph,
>>> struct apm_module_sp_vi_ex_mode_cfg *ex_cfg;
>>> int op_sz, cm_sz, ex_sz;
>>> struct apm_module_param_data *param_data;
>>> - int rc, i, payload_size;
>>> + int rc, i, payload_size, j;
>>> struct gpr_pkt *pkt;
>>> void *p;
>>> @@ -1284,14 +1306,19 @@ static int
>>> audioreach_speaker_protection_vi(struct q6apm_graph *graph,
>>> param_data->param_size = cm_sz - APM_MODULE_PARAM_DATA_SIZE;
>>> cm_cfg->cfg.num_channels = num_channels * 2;
>>> - for (i = 0; i < num_channels; i++) {
>>> + /* Convert the physical mapping to a logical mapping of the
>>> channels */
>>> + for (i = 0, j = 0; i < AR_PCM_MAX_NUM_CHANNEL && j <
>>> num_channels; i++) {
>>> + if (!mcfg->channel_map[i])
>>> + continue;
>>> /*
>>> * Map speakers into Vsense and then Isense of each channel.
>>> * E.g. for PCM_CHANNEL_FL and PCM_CHANNEL_FR to:
>>> * [1, 2, 3, 4]
>>> */
>>> - cm_cfg->cfg.channel_mapping[2 * i] = (mcfg->channel_map[i] -
>>> 1) * 2 + 1;
>>> - cm_cfg->cfg.channel_mapping[2 * i + 1] = (mcfg-
>>> >channel_map[i] - 1) * 2 + 2;
>>> + cm_cfg->cfg.channel_mapping[2 * j] = (mcfg->channel_map[i] -
>>> 1) * 2 + 1;
>>> + cm_cfg->cfg.channel_mapping[2 * j + 1] = (mcfg-
>>> >channel_map[i] - 1) * 2 + 2;
>>> +
>>> + ++j;
>>> }
>>> p += cm_sz;
>>>
>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-06-15 9:36 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 7:41 [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Neil Armstrong
2026-06-10 7:41 ` [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map Neil Armstrong
2026-06-15 8:38 ` Srinivas Kandagatla
2026-06-15 9:31 ` Neil Armstrong
2026-06-15 9:36 ` Srinivas Kandagatla
2026-06-10 7:41 ` [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping Neil Armstrong
2026-06-15 8:42 ` Srinivas Kandagatla
2026-06-10 7:41 ` [PATCH 3/4] arm64: dts: qcom: sm8650-ayaneo-pocket-s2: switch sound card to ayaneo,pocket-s2-sndcard Neil Armstrong
2026-06-12 7:57 ` Dmitry Baryshkov
2026-06-12 7:59 ` Neil Armstrong
2026-06-12 8:23 ` Dmitry Baryshkov
2026-06-12 8:30 ` Neil Armstrong
2026-06-10 7:41 ` [PATCH 4/4] ASoC: dt-bindings: qcom,sm8250: Add Ayaneo Pocket S2 sound card Neil Armstrong
2026-06-11 9:04 ` Krzysztof Kozlowski
2026-06-10 10:12 ` [PATCH 0/4] sound: qcom: audioreach: support WSA speakers only on WSA2 Mark Brown
2026-06-10 11:52 ` Neil Armstrong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox