* [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; 23+ 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] 23+ 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-16 15:05 ` 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, 2 replies; 23+ 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] 23+ 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 2026-06-16 15:05 ` Srinivas Kandagatla 1 sibling, 1 reply; 23+ 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] 23+ 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; 23+ 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] 23+ 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 2026-06-15 13:54 ` Neil Armstrong 0 siblings, 1 reply; 23+ 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] 23+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map 2026-06-15 9:36 ` Srinivas Kandagatla @ 2026-06-15 13:54 ` Neil Armstrong 2026-06-16 14:59 ` Srinivas Kandagatla 0 siblings, 1 reply; 23+ messages in thread From: Neil Armstrong @ 2026-06-15 13:54 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 On 6/15/26 11:36, Srinivas Kandagatla wrote: > 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 > So I did all the changes as you suggested: Resurected Krzk's serie: https://patch.msgid.link/20231019153541.49753-1-krzysztof.kozlowski@linaro.org Adapted/Fixes it to apply on v7.1: https://gitlab.com/superna9999/linux/-/commit/fd8cf1922d10175c5bcd8cf2a444c5825392d994 https://gitlab.com/superna9999/linux/-/commit/0c4e89e167b9ca9c7b500577c030e550ec2a6e73 https://gitlab.com/superna9999/linux/-/commit/6364a0a45a3f0985b872d9f504e9ea1d1f3f2a35 ``` +#define WSA2_CODEC_DMA_RX_0 147 +#define WSA2_CODEC_DMA_TX_0 148 +#define WSA2_CODEC_DMA_RX_1 149 +#define WSA2_CODEC_DMA_TX_1 150 +#define WSA2_CODEC_DMA_TX_2 151 ``` https://gitlab.com/superna9999/linux/-/commit/9bd0ce21f73df92fb35e3db7ef570f561a106478 DT: https://gitlab.com/superna9999/linux/-/commit/2fc270860e3b77ccae28e0c38228cba3e39ea78a ``` - sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>; + sound-dai = <&q6apmbedai WSA2_CODEC_DMA_RX_0>; }; ``` Topology, copied the SM8550-HDK into a new one, dropped I2S and changed all WSA to WSA and added the WSA defines: https://github.com/superna9999/audioreach-topology/commit/12adc76859cde606c67e5a95df204b8d407038df ``` +define(`WSA2_CODEC_DMA_RX_0', `147') dnl +define(`WSA2_CODEC_DMA_TX_0', `148') dnl +define(`WSA2_CODEC_DMA_RX_1', `149') dnl +define(`WSA2_CODEC_DMA_TX_1', `150') dnl +define(`WSA2_CODEC_DMA_TX_2', `151') dnl ``` Extract of the SM8650-APS2.m4 concerning WSA2: ``` ... +dnl WSA Playback +DEVICE_SG_ADD(audioreach/subgraph-device-codec-dma-playback.m4, `WSA2_CODEC_DMA_RX_0', WSA2_CODEC_DMA_RX_0, + `S16_LE', 48000, 48000, 2, 2, + LPAIF_INTF_TYPE_WSA2, CODEC_INTF_IDX_RX0, 0, DATA_FORMAT_FIXED_POINT, + 0x00004006, 0x00004006, 0x00006050) +dnl ... +STREAM_DEVICE_PLAYBACK_MIXER(WSA2_CODEC_DMA_RX_0, ``WSA2_CODEC_DMA_RX_0'', ``MultiMedia1'', ``MultiMedia2'', ``MultiMedia5'') ... +STREAM_DEVICE_PLAYBACK_ROUTE(WSA2_CODEC_DMA_RX_0, ``WSA2_CODEC_DMA_RX_0 Audio Mixer'', ``MultiMedia1, stream0.logger1'', ``MultiMedia2, stream1.logger1'', ``MultiMedia5, stream4.logger1'') ... ``` On device, all sets up without errors: ``` [ 20.710228] qcom-apm gprsvc:service:2:1: CMD timeout for [1001021] opcode [ 20.720234] platform 6800000.remoteproc:glink-edge:gpr:service@1:dais: Adding to iommu group 30 [ 20.763797] va_macro 6d44000.codec: qcom,dmic-sample-rate dt entry missing [ 20.791279] wsa_macro 6aa0000.codec: using zero-initialized flat cache, this may cause unexpected behavior [ 20.912445] wcd939x_codec audio-codec: bound sdw:2:0:0217:010e:00:4 (ops wcd_sdw_component_ops [snd_soc_wcd_common]) [ 20.923343] wcd939x_codec audio-codec: bound sdw:3:0:0217:010e:00:3 (ops wcd_sdw_component_ops [snd_soc_wcd_common]) [ 20.960741] snd-sc8280xp sound: ASoC: Parent card not yet available, widget card binding deferred [ 20.972182] va_macro 6d44000.codec: supply vdd-micb not found, using dummy regulator [ 20.985751] ALSA: Control name 'stream0.vol_ctrl0 MultiMedia1 Playback Volume' truncated to 'stream0.vol_ctrl0 MultiMedia1 Playback Volu' [ 20.998589] ALSA: Control name 'stream1.vol_ctrl1 MultiMedia2 Playback Volume' truncated to 'stream1.vol_ctrl1 MultiMedia2 Playback Volu' [ 21.011536] ALSA: Control name 'stream4.vol_ctrl4 MultiMedia5 Playback Volume' truncated to 'stream4.vol_ctrl4 MultiMedia5 Playback Volu' [ 21.026510] input: SM8650-APS2 Headset Jack as /devices/platform/sound/sound/card0/input7 [ 21.035151] input: SM8650-APS2 DP0 Jack as /devices/platform/sound/sound/card0/input8 ``` Available mixer elements: ``` # amixer | grep WSA Simple mixer control 'SpkrLeft WSA MODE',0 Simple mixer control 'SpkrRight WSA MODE',0 Simple mixer control 'WSA RX0 MUX',0 Simple mixer control 'WSA RX1 MUX',0 Simple mixer control 'WSA RX_MIX EC0_MUX',0 Simple mixer control 'WSA RX_MIX EC1_MUX',0 Simple mixer control 'WSA RX_MIX0 MUX',0 Simple mixer control 'WSA RX_MIX1 MUX',0 Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1',0 Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia2',0 Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia5',0 Simple mixer control 'WSA_AIF_VI Mixer WSA_SPKR_VI_1',0 Simple mixer control 'WSA_AIF_VI Mixer WSA_SPKR_VI_2',0 Simple mixer control 'WSA_COMP1',0 Simple mixer control 'WSA_COMP2',0 Simple mixer control 'WSA_RX0 Digital',0 Simple mixer control 'WSA_RX0 Digital Mute',0 Simple mixer control 'WSA_RX0 EC_HQ',0 Simple mixer control 'WSA_RX0 INP0',0 Simple mixer control 'WSA_RX0 INP1',0 Simple mixer control 'WSA_RX0 INP2',0 Simple mixer control 'WSA_RX0 INT0 SIDETONE MIX',0 Simple mixer control 'WSA_RX0 MIX INP',0 Simple mixer control 'WSA_RX0_MIX Digital',0 Simple mixer control 'WSA_RX0_MIX Digital Mute',0 Simple mixer control 'WSA_RX1 Digital',0 Simple mixer control 'WSA_RX1 Digital Mute',0 Simple mixer control 'WSA_RX1 EC_HQ',0 Simple mixer control 'WSA_RX1 INP0',0 Simple mixer control 'WSA_RX1 INP1',0 Simple mixer control 'WSA_RX1 INP2',0 Simple mixer control 'WSA_RX1 MIX INP',0 Simple mixer control 'WSA_RX1_MIX Digital',0 Simple mixer control 'WSA_RX1_MIX Digital Mute',0 Simple mixer control 'WSA_Softclip0 Enable',0 Simple mixer control 'WSA_Softclip1 Enable',0 ``` I setup the speaker with (no errors): ``` amixer -c 0 cset name='SpkrLeft PA Volume' 20 amixer -c 0 cset name='SpkrRight PA Volume' 20 amixer -c 0 cset name='WSA RX0 MUX' AIF1_PB amixer -c 0 cset name='WSA RX1 MUX' AIF1_PB amixer -c 0 cset name='WSA_RX0 INP0' RX0 amixer -c 0 cset name='WSA_RX1 INP0' RX1 amixer -c 0 cset name='SpkrLeft DAC Switch' 1 amixer -c 0 cset name='SpkrRight DAC Switch' 1 amixer -c 0 cset name='WSA_RX0 Digital Volume' 85 amixer -c 0 cset name='WSA_RX1 Digital Volume' 85 ``` and finally: ``` amixer -c 0 cset name='WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' 1 numid=216,iface=MIXER,name='WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' ; type=BOOLEAN,access=rw------,values=2 : values=on,off ``` When playing sound, it just timeouts, no printed errors: ``` # speaker-test -D plughw:0,0 -c 2 speaker-test 1.2.14 Playback device is plughw:0,0 Stream parameters are 48000Hz, S16_LE, 2 channels Using 16 octaves of pink noise Rate set to 48000Hz (requested 48000Hz) Buffer size range from 960 to 130560 Period size range from 480 to 16320 Periods = 4 was set period_size = 12000 was set buffer_size = 48000 0 - Front Left Write error: -5,Input/output error xrun_recovery failed: -5,Input/output error Transfer failed: Input/output error ``` Neil > > --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] 23+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map 2026-06-15 13:54 ` Neil Armstrong @ 2026-06-16 14:59 ` Srinivas Kandagatla 2026-06-16 15:12 ` Neil Armstrong 0 siblings, 1 reply; 23+ messages in thread From: Srinivas Kandagatla @ 2026-06-16 14:59 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 2:54 PM, Neil Armstrong wrote: > On 6/15/26 11:36, Srinivas Kandagatla wrote: >> 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 >> > > So I did all the changes as you suggested: > > Resurected Krzk's serie: https:// > patch.msgid.link/20231019153541.49753-1-krzysztof.kozlowski@linaro.org > > Adapted/Fixes it to apply on v7.1: > https://gitlab.com/superna9999/linux/-/commit/ > fd8cf1922d10175c5bcd8cf2a444c5825392d994 > https://gitlab.com/superna9999/linux/-/ > commit/0c4e89e167b9ca9c7b500577c030e550ec2a6e73 > https://gitlab.com/superna9999/linux/-/ > commit/6364a0a45a3f0985b872d9f504e9ea1d1f3f2a35 > > ``` > +#define WSA2_CODEC_DMA_RX_0 147 > +#define WSA2_CODEC_DMA_TX_0 148 > +#define WSA2_CODEC_DMA_RX_1 149 > +#define WSA2_CODEC_DMA_TX_1 150 > +#define WSA2_CODEC_DMA_TX_2 151 > ``` > > https://gitlab.com/superna9999/linux/-/ > commit/9bd0ce21f73df92fb35e3db7ef570f561a106478 > > DT: > https://gitlab.com/superna9999/linux/-/ > commit/2fc270860e3b77ccae28e0c38228cba3e39ea78a > > ``` > - sound-dai = <&q6apmbedai > WSA_CODEC_DMA_RX_0>; > + sound-dai = <&q6apmbedai > WSA2_CODEC_DMA_RX_0>; > }; > ``` > > Topology, copied the SM8550-HDK into a new one, dropped I2S and changed > all WSA to WSA > and added the WSA defines: > https://github.com/superna9999/audioreach-topology/ > commit/12adc76859cde606c67e5a95df204b8d407038df > > > ``` > +define(`WSA2_CODEC_DMA_RX_0', `147') dnl > +define(`WSA2_CODEC_DMA_TX_0', `148') dnl > +define(`WSA2_CODEC_DMA_RX_1', `149') dnl > +define(`WSA2_CODEC_DMA_TX_1', `150') dnl > +define(`WSA2_CODEC_DMA_TX_2', `151') dnl > ``` > > Extract of the SM8650-APS2.m4 concerning WSA2: > ``` > ... > +dnl WSA Playback > +DEVICE_SG_ADD(audioreach/subgraph-device-codec-dma-playback.m4, > `WSA2_CODEC_DMA_RX_0', WSA2_CODEC_DMA_RX_0, > + `S16_LE', 48000, 48000, 2, 2, > + LPAIF_INTF_TYPE_WSA2, CODEC_INTF_IDX_RX0, 0, > DATA_FORMAT_FIXED_POINT, > + 0x00004006, 0x00004006, 0x00006050) > +dnl > ... > +STREAM_DEVICE_PLAYBACK_MIXER(WSA2_CODEC_DMA_RX_0, > ``WSA2_CODEC_DMA_RX_0'', ``MultiMedia1'', ``MultiMedia2'', ``MultiMedia5'') > ... > +STREAM_DEVICE_PLAYBACK_ROUTE(WSA2_CODEC_DMA_RX_0, ``WSA2_CODEC_DMA_RX_0 > Audio Mixer'', ``MultiMedia1, stream0.logger1'', ``MultiMedia2, > stream1.logger1'', ``MultiMedia5, stream4.logger1'') > ... > ``` > > On device, all sets up without errors: > ``` > [ 20.710228] qcom-apm gprsvc:service:2:1: CMD timeout for [1001021] > opcode > [ 20.720234] platform 6800000.remoteproc:glink- > edge:gpr:service@1:dais: Adding to iommu group 30 > [ 20.763797] va_macro 6d44000.codec: qcom,dmic-sample-rate dt entry > missing > [ 20.791279] wsa_macro 6aa0000.codec: using zero-initialized flat > cache, this may cause unexpected behavior > [ 20.912445] wcd939x_codec audio-codec: bound sdw:2:0:0217:010e:00:4 > (ops wcd_sdw_component_ops [snd_soc_wcd_common]) > [ 20.923343] wcd939x_codec audio-codec: bound sdw:3:0:0217:010e:00:3 > (ops wcd_sdw_component_ops [snd_soc_wcd_common]) > [ 20.960741] snd-sc8280xp sound: ASoC: Parent card not yet available, > widget card binding deferred > [ 20.972182] va_macro 6d44000.codec: supply vdd-micb not found, using > dummy regulator > [ 20.985751] ALSA: Control name 'stream0.vol_ctrl0 MultiMedia1 > Playback Volume' truncated to 'stream0.vol_ctrl0 MultiMedia1 Playback Volu' > [ 20.998589] ALSA: Control name 'stream1.vol_ctrl1 MultiMedia2 > Playback Volume' truncated to 'stream1.vol_ctrl1 MultiMedia2 Playback Volu' > [ 21.011536] ALSA: Control name 'stream4.vol_ctrl4 MultiMedia5 > Playback Volume' truncated to 'stream4.vol_ctrl4 MultiMedia5 Playback Volu' > [ 21.026510] input: SM8650-APS2 Headset Jack as /devices/platform/ > sound/sound/card0/input7 > [ 21.035151] input: SM8650-APS2 DP0 Jack as /devices/platform/sound/ > sound/card0/input8 > ``` > > Available mixer elements: > ``` > # amixer | grep WSA > Simple mixer control 'SpkrLeft WSA MODE',0 > Simple mixer control 'SpkrRight WSA MODE',0 > Simple mixer control 'WSA RX0 MUX',0 > Simple mixer control 'WSA RX1 MUX',0 > Simple mixer control 'WSA RX_MIX EC0_MUX',0 > Simple mixer control 'WSA RX_MIX EC1_MUX',0 > Simple mixer control 'WSA RX_MIX0 MUX',0 > Simple mixer control 'WSA RX_MIX1 MUX',0 > Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1',0 > Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia2',0 > Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia5',0 > Simple mixer control 'WSA_AIF_VI Mixer WSA_SPKR_VI_1',0 > Simple mixer control 'WSA_AIF_VI Mixer WSA_SPKR_VI_2',0 > Simple mixer control 'WSA_COMP1',0 > Simple mixer control 'WSA_COMP2',0 > Simple mixer control 'WSA_RX0 Digital',0 > Simple mixer control 'WSA_RX0 Digital Mute',0 > Simple mixer control 'WSA_RX0 EC_HQ',0 > Simple mixer control 'WSA_RX0 INP0',0 > Simple mixer control 'WSA_RX0 INP1',0 > Simple mixer control 'WSA_RX0 INP2',0 > Simple mixer control 'WSA_RX0 INT0 SIDETONE MIX',0 > Simple mixer control 'WSA_RX0 MIX INP',0 > Simple mixer control 'WSA_RX0_MIX Digital',0 > Simple mixer control 'WSA_RX0_MIX Digital Mute',0 > Simple mixer control 'WSA_RX1 Digital',0 > Simple mixer control 'WSA_RX1 Digital Mute',0 > Simple mixer control 'WSA_RX1 EC_HQ',0 > Simple mixer control 'WSA_RX1 INP0',0 > Simple mixer control 'WSA_RX1 INP1',0 > Simple mixer control 'WSA_RX1 INP2',0 > Simple mixer control 'WSA_RX1 MIX INP',0 > Simple mixer control 'WSA_RX1_MIX Digital',0 > Simple mixer control 'WSA_RX1_MIX Digital Mute',0 > Simple mixer control 'WSA_Softclip0 Enable',0 > Simple mixer control 'WSA_Softclip1 Enable',0 > ``` > > I setup the speaker with (no errors): > ``` > amixer -c 0 cset name='SpkrLeft PA Volume' 20 > amixer -c 0 cset name='SpkrRight PA Volume' 20 > amixer -c 0 cset name='WSA RX0 MUX' AIF1_PB > amixer -c 0 cset name='WSA RX1 MUX' AIF1_PB > amixer -c 0 cset name='WSA_RX0 INP0' RX0 > amixer -c 0 cset name='WSA_RX1 INP0' RX1 > amixer -c 0 cset name='SpkrLeft DAC Switch' 1 > amixer -c 0 cset name='SpkrRight DAC Switch' 1 > amixer -c 0 cset name='WSA_RX0 Digital Volume' 85 > amixer -c 0 cset name='WSA_RX1 Digital Volume' 85 > ``` > > and finally: > ``` > amixer -c 0 cset name='WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' 1 > numid=216,iface=MIXER,name='WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' > ; type=BOOLEAN,access=rw------,values=2 > : values=on,off > > ``` > > When playing sound, it just timeouts, no printed errors: > ``` > # speaker-test -D plughw:0,0 -c 2 > > speaker-test 1.2.14 > > Playback device is plughw:0,0 > Stream parameters are 48000Hz, S16_LE, 2 channels > Using 16 octaves of pink noise > Rate set to 48000Hz (requested 48000Hz) > Buffer size range from 960 to 130560 > Period size range from 480 to 16320 > Periods = 4 > was set period_size = 12000 > was set buffer_size = 48000 > 0 - Front Left > Write error: -5,Input/output error > xrun_recovery failed: -5,Input/output error > Transfer failed: Input/output error > ``` Thanks Neil for trying this out, I had pretty much simillar behavoir on Glymur device too, My understanding was that there are some codec DMA instances where we can use 2 channels as default for WSA2. But on Glymur all the DMA instances are 8 channel wide. Am trying to check internally to see if its actually doable to get this working with the ch1 and ch2 mask. Am working on this to get more details on what it takes to get this working. Only concern with this patch is that the channel mapping, which does not reflect the channel mask. can you confirm that in your working setup you have chmask as 0xC0 and channel_map setup for ch1 and ch2? From DSP docs: https://github.com/AudioReach/audioreach-engine/blob/master/fwk/api/modules/media_fmt_api_basic.h#L780 Channel[i] mapping describes channel i. Each element i of the array describes channel i inside the buffer where i is less than num_channels. An unused channel is set to 0. So unused channels should be set to zero, but the patch padding the channels starting form zero. -srini > > Neil > >> >> --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] 23+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map 2026-06-16 14:59 ` Srinivas Kandagatla @ 2026-06-16 15:12 ` Neil Armstrong 2026-06-16 18:52 ` Srinivas Kandagatla 0 siblings, 1 reply; 23+ messages in thread From: Neil Armstrong @ 2026-06-16 15:12 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 On 6/16/26 16:59, Srinivas Kandagatla wrote: > > > On 6/15/26 2:54 PM, Neil Armstrong wrote: >> On 6/15/26 11:36, Srinivas Kandagatla wrote: >>> 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 >>> >> >> So I did all the changes as you suggested: >> >> Resurected Krzk's serie: https:// >> patch.msgid.link/20231019153541.49753-1-krzysztof.kozlowski@linaro.org >> >> Adapted/Fixes it to apply on v7.1: >> https://gitlab.com/superna9999/linux/-/commit/ >> fd8cf1922d10175c5bcd8cf2a444c5825392d994 >> https://gitlab.com/superna9999/linux/-/ >> commit/0c4e89e167b9ca9c7b500577c030e550ec2a6e73 >> https://gitlab.com/superna9999/linux/-/ >> commit/6364a0a45a3f0985b872d9f504e9ea1d1f3f2a35 >> >> ``` >> +#define WSA2_CODEC_DMA_RX_0 147 >> +#define WSA2_CODEC_DMA_TX_0 148 >> +#define WSA2_CODEC_DMA_RX_1 149 >> +#define WSA2_CODEC_DMA_TX_1 150 >> +#define WSA2_CODEC_DMA_TX_2 151 >> ``` >> >> https://gitlab.com/superna9999/linux/-/ >> commit/9bd0ce21f73df92fb35e3db7ef570f561a106478 >> >> DT: >> https://gitlab.com/superna9999/linux/-/ >> commit/2fc270860e3b77ccae28e0c38228cba3e39ea78a >> >> ``` >> - sound-dai = <&q6apmbedai >> WSA_CODEC_DMA_RX_0>; >> + sound-dai = <&q6apmbedai >> WSA2_CODEC_DMA_RX_0>; >> }; >> ``` >> >> Topology, copied the SM8550-HDK into a new one, dropped I2S and changed >> all WSA to WSA >> and added the WSA defines: >> https://github.com/superna9999/audioreach-topology/ >> commit/12adc76859cde606c67e5a95df204b8d407038df >> >> >> ``` >> +define(`WSA2_CODEC_DMA_RX_0', `147') dnl >> +define(`WSA2_CODEC_DMA_TX_0', `148') dnl >> +define(`WSA2_CODEC_DMA_RX_1', `149') dnl >> +define(`WSA2_CODEC_DMA_TX_1', `150') dnl >> +define(`WSA2_CODEC_DMA_TX_2', `151') dnl >> ``` >> >> Extract of the SM8650-APS2.m4 concerning WSA2: >> ``` >> ... >> +dnl WSA Playback >> +DEVICE_SG_ADD(audioreach/subgraph-device-codec-dma-playback.m4, >> `WSA2_CODEC_DMA_RX_0', WSA2_CODEC_DMA_RX_0, >> + `S16_LE', 48000, 48000, 2, 2, >> + LPAIF_INTF_TYPE_WSA2, CODEC_INTF_IDX_RX0, 0, >> DATA_FORMAT_FIXED_POINT, >> + 0x00004006, 0x00004006, 0x00006050) >> +dnl >> ... >> +STREAM_DEVICE_PLAYBACK_MIXER(WSA2_CODEC_DMA_RX_0, >> ``WSA2_CODEC_DMA_RX_0'', ``MultiMedia1'', ``MultiMedia2'', ``MultiMedia5'') >> ... >> +STREAM_DEVICE_PLAYBACK_ROUTE(WSA2_CODEC_DMA_RX_0, ``WSA2_CODEC_DMA_RX_0 >> Audio Mixer'', ``MultiMedia1, stream0.logger1'', ``MultiMedia2, >> stream1.logger1'', ``MultiMedia5, stream4.logger1'') >> ... >> ``` >> >> On device, all sets up without errors: >> ``` >> [ 20.710228] qcom-apm gprsvc:service:2:1: CMD timeout for [1001021] >> opcode >> [ 20.720234] platform 6800000.remoteproc:glink- >> edge:gpr:service@1:dais: Adding to iommu group 30 >> [ 20.763797] va_macro 6d44000.codec: qcom,dmic-sample-rate dt entry >> missing >> [ 20.791279] wsa_macro 6aa0000.codec: using zero-initialized flat >> cache, this may cause unexpected behavior >> [ 20.912445] wcd939x_codec audio-codec: bound sdw:2:0:0217:010e:00:4 >> (ops wcd_sdw_component_ops [snd_soc_wcd_common]) >> [ 20.923343] wcd939x_codec audio-codec: bound sdw:3:0:0217:010e:00:3 >> (ops wcd_sdw_component_ops [snd_soc_wcd_common]) >> [ 20.960741] snd-sc8280xp sound: ASoC: Parent card not yet available, >> widget card binding deferred >> [ 20.972182] va_macro 6d44000.codec: supply vdd-micb not found, using >> dummy regulator >> [ 20.985751] ALSA: Control name 'stream0.vol_ctrl0 MultiMedia1 >> Playback Volume' truncated to 'stream0.vol_ctrl0 MultiMedia1 Playback Volu' >> [ 20.998589] ALSA: Control name 'stream1.vol_ctrl1 MultiMedia2 >> Playback Volume' truncated to 'stream1.vol_ctrl1 MultiMedia2 Playback Volu' >> [ 21.011536] ALSA: Control name 'stream4.vol_ctrl4 MultiMedia5 >> Playback Volume' truncated to 'stream4.vol_ctrl4 MultiMedia5 Playback Volu' >> [ 21.026510] input: SM8650-APS2 Headset Jack as /devices/platform/ >> sound/sound/card0/input7 >> [ 21.035151] input: SM8650-APS2 DP0 Jack as /devices/platform/sound/ >> sound/card0/input8 >> ``` >> >> Available mixer elements: >> ``` >> # amixer | grep WSA >> Simple mixer control 'SpkrLeft WSA MODE',0 >> Simple mixer control 'SpkrRight WSA MODE',0 >> Simple mixer control 'WSA RX0 MUX',0 >> Simple mixer control 'WSA RX1 MUX',0 >> Simple mixer control 'WSA RX_MIX EC0_MUX',0 >> Simple mixer control 'WSA RX_MIX EC1_MUX',0 >> Simple mixer control 'WSA RX_MIX0 MUX',0 >> Simple mixer control 'WSA RX_MIX1 MUX',0 >> Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1',0 >> Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia2',0 >> Simple mixer control 'WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia5',0 >> Simple mixer control 'WSA_AIF_VI Mixer WSA_SPKR_VI_1',0 >> Simple mixer control 'WSA_AIF_VI Mixer WSA_SPKR_VI_2',0 >> Simple mixer control 'WSA_COMP1',0 >> Simple mixer control 'WSA_COMP2',0 >> Simple mixer control 'WSA_RX0 Digital',0 >> Simple mixer control 'WSA_RX0 Digital Mute',0 >> Simple mixer control 'WSA_RX0 EC_HQ',0 >> Simple mixer control 'WSA_RX0 INP0',0 >> Simple mixer control 'WSA_RX0 INP1',0 >> Simple mixer control 'WSA_RX0 INP2',0 >> Simple mixer control 'WSA_RX0 INT0 SIDETONE MIX',0 >> Simple mixer control 'WSA_RX0 MIX INP',0 >> Simple mixer control 'WSA_RX0_MIX Digital',0 >> Simple mixer control 'WSA_RX0_MIX Digital Mute',0 >> Simple mixer control 'WSA_RX1 Digital',0 >> Simple mixer control 'WSA_RX1 Digital Mute',0 >> Simple mixer control 'WSA_RX1 EC_HQ',0 >> Simple mixer control 'WSA_RX1 INP0',0 >> Simple mixer control 'WSA_RX1 INP1',0 >> Simple mixer control 'WSA_RX1 INP2',0 >> Simple mixer control 'WSA_RX1 MIX INP',0 >> Simple mixer control 'WSA_RX1_MIX Digital',0 >> Simple mixer control 'WSA_RX1_MIX Digital Mute',0 >> Simple mixer control 'WSA_Softclip0 Enable',0 >> Simple mixer control 'WSA_Softclip1 Enable',0 >> ``` >> >> I setup the speaker with (no errors): >> ``` >> amixer -c 0 cset name='SpkrLeft PA Volume' 20 >> amixer -c 0 cset name='SpkrRight PA Volume' 20 >> amixer -c 0 cset name='WSA RX0 MUX' AIF1_PB >> amixer -c 0 cset name='WSA RX1 MUX' AIF1_PB >> amixer -c 0 cset name='WSA_RX0 INP0' RX0 >> amixer -c 0 cset name='WSA_RX1 INP0' RX1 >> amixer -c 0 cset name='SpkrLeft DAC Switch' 1 >> amixer -c 0 cset name='SpkrRight DAC Switch' 1 >> amixer -c 0 cset name='WSA_RX0 Digital Volume' 85 >> amixer -c 0 cset name='WSA_RX1 Digital Volume' 85 >> ``` >> >> and finally: >> ``` >> amixer -c 0 cset name='WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' 1 >> numid=216,iface=MIXER,name='WSA2_CODEC_DMA_RX_0 Audio Mixer MultiMedia1' >> ; type=BOOLEAN,access=rw------,values=2 >> : values=on,off >> >> ``` >> >> When playing sound, it just timeouts, no printed errors: >> ``` >> # speaker-test -D plughw:0,0 -c 2 >> >> speaker-test 1.2.14 >> >> Playback device is plughw:0,0 >> Stream parameters are 48000Hz, S16_LE, 2 channels >> Using 16 octaves of pink noise >> Rate set to 48000Hz (requested 48000Hz) >> Buffer size range from 960 to 130560 >> Period size range from 480 to 16320 >> Periods = 4 >> was set period_size = 12000 >> was set buffer_size = 48000 >> 0 - Front Left >> Write error: -5,Input/output error >> xrun_recovery failed: -5,Input/output error >> Transfer failed: Input/output error >> ``` > > Thanks Neil for trying this out, I had pretty much simillar behavoir on > Glymur device too, My understanding was that there are some codec DMA > instances where we can use 2 channels as default for WSA2. > > But on Glymur all the DMA instances are 8 channel wide. Am trying to > check internally to see if its actually doable to get this working with > the ch1 and ch2 mask. > > Am working on this to get more details on what it takes to get this working. > > > Only concern with this patch is that the channel mapping, which does not > reflect the channel mask. can you confirm that in your working setup you > have chmask as 0xC0 and channel_map setup for ch1 and ch2? Yeah 0xC0 for active_channels_mask and channel_mapping = { PCM_CHANNEL_FL, PCM_CHANNEL_FR }; I tried to keep the leading 0, but since the channel_mapping table is allocated with the size of the num_channels parameter, you can ony have 2 entries. > > From DSP docs: > https://github.com/AudioReach/audioreach-engine/blob/master/fwk/api/modules/media_fmt_api_basic.h#L780 > > Channel[i] mapping describes channel i. Each element i of the array > describes channel i inside the buffer where i is less than num_channels. > An unused channel is set to 0. > > > So unused channels should be set to zero, but the patch padding the > channels starting form zero. My understanding in my trial and error is that the DSP will map each entry of the channel_mapping to the active_channels_mask bits in order so you can have a non linear active_channels_mask like b10101010 which has 4 channels active and pass a channel_mapping table with 4 entries. The is what I implemented here, and it gives a lot of flexibility on how to connect speakers to the interface. Neil > > -srini > > >> >> Neil >> >>> >>> --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] 23+ messages in thread
* Re: [PATCH 1/4] ASoC: qcom: audioreach: compute active channel maps from channel_map 2026-06-16 15:12 ` Neil Armstrong @ 2026-06-16 18:52 ` Srinivas Kandagatla 0 siblings, 0 replies; 23+ messages in thread From: Srinivas Kandagatla @ 2026-06-16 18:52 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/16/26 4:12 PM, Neil Armstrong wrote: > On 6/16/26 16:59, Srinivas Kandagatla wrote: >> >> >> On 6/15/26 2:54 PM, Neil Armstrong wrote: >>> On 6/15/26 11:36, Srinivas Kandagatla wrote: >>>> 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>; >>>>>> > > Yeah 0xC0 for active_channels_mask and channel_mapping = > { PCM_CHANNEL_FL, PCM_CHANNEL_FR }; > > I tried to keep the leading 0, but since the channel_mapping table is > allocated with > the size of the num_channels parameter, you can ony have 2 entries. > >> >> From DSP docs: >> https://github.com/AudioReach/audioreach-engine/blob/master/fwk/api/ >> modules/media_fmt_api_basic.h#L780 >> >> Channel[i] mapping describes channel i. Each element i of the array >> describes channel i inside the buffer where i is less than num_channels. >> An unused channel is set to 0. >> >> >> So unused channels should be set to zero, but the patch padding the >> channels starting form zero. > > My understanding in my trial and error is that the DSP will map each > entry of the channel_mapping to the active_channels_mask bits in order > so you can have a non linear active_channels_mask like b10101010 which > has 4 channels active and pass a channel_mapping table with 4 entries. > You are correct, I was mis-interpreting some of the comments from modules/media_fmt_api_basic.h specially the channel map comment. Also confirmed this internally so we are good, I tested this on T14s, Tested-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> --srini > The is what I implemented here, and it gives a lot of flexibility on how > to connect speakers to the interface. > > Neil ^ permalink raw reply [flat|nested] 23+ 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-16 15:05 ` Srinivas Kandagatla 1 sibling, 0 replies; 23+ messages in thread From: Srinivas Kandagatla @ 2026-06-16 15:05 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, Prasad Kumpatla Cc: kancy2333, linux-sound, linux-arm-msm, linux-kernel, devicetree, Srinivas Kandagatla +add Prasad to comment on dsp side. 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 | > \-------------------------------------------------/ > > 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; > ^ permalink raw reply [flat|nested] 23+ 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-16 18:54 ` 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, 2 replies; 23+ 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] 23+ 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 2026-06-15 15:53 ` Neil Armstrong 2026-06-16 18:54 ` Srinivas Kandagatla 1 sibling, 1 reply; 23+ 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] 23+ messages in thread
* Re: [PATCH 2/4] ASoC: qcom: sc8280xp: add Ayaneo Pocket S2 card with special WSA channel mapping 2026-06-15 8:42 ` Srinivas Kandagatla @ 2026-06-15 15:53 ` Neil Armstrong 0 siblings, 0 replies; 23+ messages in thread From: Neil Armstrong @ 2026-06-15 15:53 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 On 6/15/26 10:42, Srinivas Kandagatla wrote: > 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. I would prefer, could you help me understand how to use it ? > >> + * __________________________________________________ >> + * | 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? No, because the only way we found to play on the WSA2 speakers is to pass set active_channels_mask 0x1100 with lpaif_type to LPAIF_INTF_TYPE_WSA. I followed your advice to play with the channel map, here's the result. > > 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. It's unrelated, I don't need to change the mapping from userspace. Thanks, Neil > > --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] 23+ 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 @ 2026-06-16 18:54 ` Srinivas Kandagatla 1 sibling, 0 replies; 23+ messages in thread From: Srinivas Kandagatla @ 2026-06-16 18:54 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/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> > --- lgtm, Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> --srini > 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}, > ^ permalink raw reply [flat|nested] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ 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; 23+ 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] 23+ messages in thread
end of thread, other threads:[~2026-06-16 18:54 UTC | newest] Thread overview: 23+ 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-15 13:54 ` Neil Armstrong 2026-06-16 14:59 ` Srinivas Kandagatla 2026-06-16 15:12 ` Neil Armstrong 2026-06-16 18:52 ` Srinivas Kandagatla 2026-06-16 15:05 ` 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-15 15:53 ` Neil Armstrong 2026-06-16 18:54 ` 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