@@ -372,6 +372,26 @@ parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *ob
return 0;
}
+static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem,
+ void *object, u32 offset)
+{
+ struct snd_soc_tplg_vendor_string_elem *tuple = elem;
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
+ char *val = (char *)((u8 *)object + offset);
+
+ /*
+ * Dynamic naming - string formats, e.g.: ssp%d - supported only for
+ * topologies describing single device e.g.: an I2S codec on SSP0.
+ */
+ if (hweight_long(mach->link_mask) != 1)
+ return avs_parse_string_token(comp, elem, object, offset);
+
+ snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string,
+ __ffs(mach->link_mask));
+
+ return 0;
+}
+
static int
parse_dictionary_header(struct snd_soc_component *comp,
struct snd_soc_tplg_vendor_array *tuples,
@@ -928,7 +948,7 @@ static const struct avs_tplg_token_parser binding_parsers[] = {
.token = AVS_TKN_BINDING_TARGET_TPLG_NAME_STRING,
.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
.offset = offsetof(struct avs_tplg_binding, target_tplg_name),
- .parse = avs_parse_string_token,
+ .parse = parse_link_formatted_string,
},
{
.token = AVS_TKN_BINDING_TARGET_PATH_TMPL_ID_U32,
@@ -1323,6 +1343,31 @@ avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *o
return template;
}
+static int avs_route_load(struct snd_soc_component *comp, int index,
+ struct snd_soc_dapm_route *route)
+{
+ struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
+ size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
+ char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
+ u32 port;
+
+ /* See parse_link_formatted_string() for dynamic naming when(s). */
+ if (hweight_long(mach->link_mask) == 1) {
+ port = __ffs(mach->link_mask);
+
+ snprintf(buf, len, route->source, port);
+ strncpy((char *)route->source, buf, len);
+ snprintf(buf, len, route->sink, port);
+ strncpy((char *)route->sink, buf, len);
+ if (route->control) {
+ snprintf(buf, len, route->control, port);
+ strncpy((char *)route->control, buf, len);
+ }
+ }
+
+ return 0;
+}
+
static int avs_widget_load(struct snd_soc_component *comp, int index,
struct snd_soc_dapm_widget *w,
struct snd_soc_tplg_dapm_widget *dw)
@@ -1338,6 +1383,15 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
tplg = acomp->tplg;
mach = dev_get_platdata(comp->card->dev);
+ /* See parse_link_formatted_string() for dynamic naming when(s). */
+ if (hweight_long(mach->link_mask) == 1) {
+ kfree(w->name);
+ /* w->name is freed later by soc_tplg_dapm_widget_create() */
+ w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->link_mask));
+ if (!w->name)
+ return -ENOMEM;
+ }
+
template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
le32_to_cpu(dw->priv.size));
if (IS_ERR(template)) {
@@ -1380,7 +1434,7 @@ static const struct avs_tplg_token_parser manifest_parsers[] = {
.token = AVS_TKN_MANIFEST_NAME_STRING,
.type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
.offset = offsetof(struct avs_tplg, name),
- .parse = avs_parse_string_token,
+ .parse = parse_link_formatted_string,
},
{
.token = AVS_TKN_MANIFEST_VERSION_U32,
@@ -1498,6 +1552,7 @@ static int avs_manifest(struct snd_soc_component *comp, int index,
}
static struct snd_soc_tplg_ops avs_tplg_ops = {
+ .dapm_route_load = avs_route_load,
.widget_load = avs_widget_load,
.dai_load = avs_dai_load,
.link_load = avs_link_load,