Skip to content

Commit a150345

Browse files
bardliaobroonie
authored andcommitted
ASoC: SOF: ipc4-topology: add SoundWire/ALH aggregation support
Some SoundWire hardware topologies rely on different amplifiers or capture devices connected on different links. These devices need to be 'aggregated', remain synchronized and be handled as a single logical device. In the IPC3 solution, the aggregation for amplifiers was handled by a firmware 'demux' component. In the IPC4 solution, the demux component is not needed, the gateway component can handle multiple ALH/DMA transfers at the same time. This change makes the topology slightly more complicated in that only one ALH DAI will be connected in the topology with the gateway. The other DAIs that are part of the 'aggregated' dailink are not shown in the DAPM graph as connected to the gateway, but they will however be activated thanks to a feature in soc-dapm.c where events are forwarded to all DAIs in the dailink (see soc_dapm_stream_event). The topology also sets the same stream name for all widgets, dais and dailinks, so a search for the stream name helps identify cases where SoundWire/ALH aggregation is needed. Signed-off-by: Bard Liao <[email protected]> Reviewed-by: Pierre-Louis Bossart <[email protected]> Reviewed-by: Ranjani Sridharan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 30ac498 commit a150345

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

sound/soc/sof/ipc4-topology.c

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#define SOF_IPC4_GAIN_PARAM_ID 0
2020
#define SOF_IPC4_TPLG_ABI_SIZE 6
2121

22+
static DEFINE_IDA(alh_group_ida);
23+
2224
static const struct sof_topology_token ipc4_sched_tokens[] = {
2325
{SOF_TKN_SCHED_LP_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
2426
offsetof(struct sof_ipc4_pipeline, lp_mode)}
@@ -478,14 +480,24 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget)
478480
switch (ipc4_copier->dai_type) {
479481
case SOF_DAI_INTEL_ALH:
480482
{
483+
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
481484
struct sof_ipc4_alh_configuration_blob *blob;
485+
struct snd_sof_widget *w;
482486

483487
blob = kzalloc(sizeof(*blob), GFP_KERNEL);
484488
if (!blob) {
485489
ret = -ENOMEM;
486490
goto err;
487491
}
488492

493+
list_for_each_entry(w, &sdev->widget_list, list) {
494+
if (w->widget->sname &&
495+
strcmp(w->widget->sname, swidget->widget->sname))
496+
continue;
497+
498+
blob->alh_cfg.count++;
499+
}
500+
489501
ipc4_copier->copier_config = (uint32_t *)blob;
490502
ipc4_copier->data.gtw_cfg.config_length = sizeof(*blob) >> 2;
491503
break;
@@ -844,6 +856,17 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
844856
struct snd_sof_dai *dai = swidget->private;
845857

846858
ipc4_copier = dai->private;
859+
if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
860+
struct sof_ipc4_alh_configuration_blob *blob;
861+
unsigned int group_id;
862+
863+
blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
864+
if (blob->alh_cfg.count > 1) {
865+
group_id = SOF_IPC4_NODE_INDEX(ipc4_copier->data.gtw_cfg.node_id) -
866+
ALH_MULTI_GTW_BASE;
867+
ida_free(&alh_group_ida, group_id);
868+
}
869+
}
847870
}
848871

849872
if (ipc4_copier) {
@@ -973,6 +996,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
973996
struct sof_ipc4_copier_data *copier_data;
974997
struct snd_pcm_hw_params *ref_params;
975998
struct sof_ipc4_copier *ipc4_copier;
999+
struct snd_sof_dai *dai;
9761000
struct snd_mask *fmt;
9771001
int out_sample_valid_bits;
9781002
size_t ref_audio_fmt_size;
@@ -1022,7 +1046,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
10221046
case snd_soc_dapm_dai_in:
10231047
case snd_soc_dapm_dai_out:
10241048
{
1025-
struct snd_sof_dai *dai = swidget->private;
1049+
dai = swidget->private;
10261050

10271051
ipc4_copier = (struct sof_ipc4_copier *)dai->private;
10281052
copier_data = &ipc4_copier->data;
@@ -1077,22 +1101,56 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
10771101
*/
10781102
if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
10791103
struct sof_ipc4_alh_configuration_blob *blob;
1104+
struct sof_ipc4_copier_data *alh_data;
1105+
struct sof_ipc4_copier *alh_copier;
1106+
struct snd_sof_widget *w;
1107+
u32 ch_mask = 0;
10801108
u32 ch_map;
10811109
int i;
10821110

10831111
blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
1084-
/* TODO: add aggregation mode support */
1085-
blob->alh_cfg.count = 1;
1086-
blob->alh_cfg.mapping[0].alh_id = copier_data->gtw_cfg.node_id;
1112+
10871113
blob->gw_attr.lp_buffer_alloc = 0;
10881114

10891115
/* Get channel_mask from ch_map */
10901116
ch_map = copier_data->base_config.audio_fmt.ch_map;
10911117
for (i = 0; ch_map; i++) {
10921118
if ((ch_map & 0xf) != 0xf)
1093-
blob->alh_cfg.mapping[0].channel_mask |= BIT(i);
1119+
ch_mask |= BIT(i);
10941120
ch_map >>= 4;
10951121
}
1122+
1123+
/*
1124+
* Set each gtw_cfg.node_id to blob->alh_cfg.mapping[]
1125+
* for all widgets with the same stream name
1126+
*/
1127+
i = 0;
1128+
list_for_each_entry(w, &sdev->widget_list, list) {
1129+
if (w->widget->sname &&
1130+
strcmp(w->widget->sname, swidget->widget->sname))
1131+
continue;
1132+
1133+
dai = w->private;
1134+
alh_copier = (struct sof_ipc4_copier *)dai->private;
1135+
alh_data = &alh_copier->data;
1136+
blob->alh_cfg.mapping[i].alh_id = alh_data->gtw_cfg.node_id;
1137+
blob->alh_cfg.mapping[i].channel_mask = ch_mask;
1138+
i++;
1139+
}
1140+
if (blob->alh_cfg.count > 1) {
1141+
int group_id;
1142+
1143+
group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT,
1144+
GFP_KERNEL);
1145+
1146+
if (group_id < 0)
1147+
return group_id;
1148+
1149+
/* add multi-gateway base */
1150+
group_id += ALH_MULTI_GTW_BASE;
1151+
copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
1152+
copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(group_id);
1153+
}
10961154
}
10971155
}
10981156
}

sound/soc/sof/ipc4-topology.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@
4242

4343
#define ALH_MAX_NUMBER_OF_GTW 16
4444

45+
/*
46+
* The base of multi-gateways. Multi-gateways addressing starts from
47+
* ALH_MULTI_GTW_BASE and there are ALH_MULTI_GTW_COUNT multi-sources
48+
* and ALH_MULTI_GTW_COUNT multi-sinks available.
49+
* Addressing is continuous from ALH_MULTI_GTW_BASE to
50+
* ALH_MULTI_GTW_BASE + ALH_MULTI_GTW_COUNT - 1.
51+
*/
52+
#define ALH_MULTI_GTW_BASE 0x50
53+
/* A magic number from FW */
54+
#define ALH_MULTI_GTW_COUNT 8
55+
4556
/**
4657
* struct sof_ipc4_pipeline - pipeline config data
4758
* @priority: Priority of this pipeline

0 commit comments

Comments
 (0)