Skip to content

Commit e6d50e4

Browse files
Amadeusz Sławińskibroonie
authored andcommitted
ASoC: Intel: avs: Improve topology parsing of dynamic strings
Current mechanism replaces "%d" present in some routes and widget names with SSP number. However there are also configurations which make use of TDM number, in which case expected behavior would be to have string in form of SSP:TDM - see implementation of avs_i2s_platform_register() in sound/soc/intel/avs/pcm.c. Implement custom function, which parses string and make use of it when parsing topology. While at it make sure that we generate dynamic names only if there is no multiple SSPs or TDMs defined. Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Link: https://lore.kernel.org/r/20231012083514.492626-4-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 7a6debe commit e6d50e4

File tree

1 file changed

+80
-22
lines changed

1 file changed

+80
-22
lines changed

sound/soc/intel/avs/topology.c

Lines changed: 80 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "avs.h"
1616
#include "control.h"
1717
#include "topology.h"
18+
#include "utils.h"
1819

1920
/* Get pointer to vendor array at the specified offset. */
2021
#define avs_tplg_vendor_array_at(array, offset) \
@@ -371,22 +372,50 @@ parse_audio_format_bitfield(struct snd_soc_component *comp, void *elem, void *ob
371372
return 0;
372373
}
373374

375+
static int avs_ssp_sprint(char *buf, size_t size, const char *fmt, int port, int tdm)
376+
{
377+
char *needle = strstr(fmt, "%d");
378+
int retsize;
379+
380+
/*
381+
* If there is %d present in fmt string it should be replaced by either
382+
* SSP or SSP:TDM, where SSP and TDM are numbers, all other formatting
383+
* will be ignored.
384+
*/
385+
if (needle) {
386+
retsize = scnprintf(buf, min_t(size_t, size, needle - fmt + 1), "%s", fmt);
387+
retsize += scnprintf(buf + retsize, size - retsize, "%d", port);
388+
if (tdm)
389+
retsize += scnprintf(buf + retsize, size - retsize, ":%d", tdm);
390+
retsize += scnprintf(buf + retsize, size - retsize, "%s", needle + 2);
391+
return retsize;
392+
}
393+
394+
return snprintf(buf, size, "%s", fmt);
395+
}
396+
374397
static int parse_link_formatted_string(struct snd_soc_component *comp, void *elem,
375398
void *object, u32 offset)
376399
{
377400
struct snd_soc_tplg_vendor_string_elem *tuple = elem;
378401
struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
379402
char *val = (char *)((u8 *)object + offset);
403+
int ssp_port, tdm_slot;
380404

381405
/*
382406
* Dynamic naming - string formats, e.g.: ssp%d - supported only for
383407
* topologies describing single device e.g.: an I2S codec on SSP0.
384408
*/
385-
if (hweight_long(mach->mach_params.i2s_link_mask) != 1)
409+
if (!avs_mach_singular_ssp(mach))
410+
return avs_parse_string_token(comp, elem, object, offset);
411+
412+
ssp_port = avs_mach_ssp_port(mach);
413+
if (!avs_mach_singular_tdm(mach, ssp_port))
386414
return avs_parse_string_token(comp, elem, object, offset);
387415

388-
snprintf(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string,
389-
__ffs(mach->mach_params.i2s_link_mask));
416+
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
417+
418+
avs_ssp_sprint(val, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, tuple->string, ssp_port, tdm_slot);
390419

391420
return 0;
392421
}
@@ -813,6 +842,7 @@ static void
813842
assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcfg_ext *cfg)
814843
{
815844
struct snd_soc_acpi_mach *mach;
845+
int ssp_port, tdm_slot;
816846

817847
if (!guid_equal(&cfg->type, &AVS_COPIER_MOD_UUID))
818848
return;
@@ -826,11 +856,22 @@ assign_copier_gtw_instance(struct snd_soc_component *comp, struct avs_tplg_modcf
826856
return;
827857
}
828858

859+
/* If topology sets value don't overwrite it */
860+
if (cfg->copier.vindex.i2s.instance)
861+
return;
862+
829863
mach = dev_get_platdata(comp->card->dev);
830864

831-
/* Automatic assignment only when board describes single SSP. */
832-
if (hweight_long(mach->mach_params.i2s_link_mask) == 1 && !cfg->copier.vindex.i2s.instance)
833-
cfg->copier.vindex.i2s.instance = __ffs(mach->mach_params.i2s_link_mask);
865+
if (!avs_mach_singular_ssp(mach))
866+
return;
867+
ssp_port = avs_mach_ssp_port(mach);
868+
869+
if (!avs_mach_singular_tdm(mach, ssp_port))
870+
return;
871+
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
872+
873+
cfg->copier.vindex.i2s.instance = ssp_port;
874+
cfg->copier.vindex.i2s.time_slot = tdm_slot;
834875
}
835876

836877
static int avs_tplg_parse_modcfg_ext(struct snd_soc_component *comp,
@@ -1381,20 +1422,24 @@ static int avs_route_load(struct snd_soc_component *comp, int index,
13811422
struct snd_soc_acpi_mach *mach = dev_get_platdata(comp->card->dev);
13821423
size_t len = SNDRV_CTL_ELEM_ID_NAME_MAXLEN;
13831424
char buf[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1384-
u32 port;
1425+
int ssp_port, tdm_slot;
13851426

13861427
/* See parse_link_formatted_string() for dynamic naming when(s). */
1387-
if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1388-
port = __ffs(mach->mach_params.i2s_link_mask);
1389-
1390-
snprintf(buf, len, route->source, port);
1391-
strscpy((char *)route->source, buf, len);
1392-
snprintf(buf, len, route->sink, port);
1393-
strscpy((char *)route->sink, buf, len);
1394-
if (route->control) {
1395-
snprintf(buf, len, route->control, port);
1396-
strscpy((char *)route->control, buf, len);
1397-
}
1428+
if (!avs_mach_singular_ssp(mach))
1429+
return 0;
1430+
ssp_port = avs_mach_ssp_port(mach);
1431+
1432+
if (!avs_mach_singular_tdm(mach, ssp_port))
1433+
return 0;
1434+
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
1435+
1436+
avs_ssp_sprint(buf, len, route->source, ssp_port, tdm_slot);
1437+
strscpy((char *)route->source, buf, len);
1438+
avs_ssp_sprint(buf, len, route->sink, ssp_port, tdm_slot);
1439+
strscpy((char *)route->sink, buf, len);
1440+
if (route->control) {
1441+
avs_ssp_sprint(buf, len, route->control, ssp_port, tdm_slot);
1442+
strscpy((char *)route->control, buf, len);
13981443
}
13991444

14001445
return 0;
@@ -1408,6 +1453,7 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
14081453
struct avs_tplg_path_template *template;
14091454
struct avs_soc_component *acomp = to_avs_soc_component(comp);
14101455
struct avs_tplg *tplg;
1456+
int ssp_port, tdm_slot;
14111457

14121458
if (!le32_to_cpu(dw->priv.size))
14131459
return 0;
@@ -1419,16 +1465,28 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
14191465

14201466
tplg = acomp->tplg;
14211467
mach = dev_get_platdata(comp->card->dev);
1468+
if (!avs_mach_singular_ssp(mach))
1469+
goto static_name;
1470+
ssp_port = avs_mach_ssp_port(mach);
14221471

14231472
/* See parse_link_formatted_string() for dynamic naming when(s). */
1424-
if (hweight_long(mach->mach_params.i2s_link_mask) == 1) {
1473+
if (avs_mach_singular_tdm(mach, ssp_port)) {
1474+
/* size is based on possible %d -> SSP:TDM, where SSP and TDM < 10 + '\0' */
1475+
size_t size = strlen(dw->name) + 2;
1476+
char *buf;
1477+
1478+
tdm_slot = avs_mach_ssp_tdm(mach, ssp_port);
1479+
1480+
buf = kmalloc(size, GFP_KERNEL);
1481+
if (!buf)
1482+
return -ENOMEM;
1483+
avs_ssp_sprint(buf, size, dw->name, ssp_port, tdm_slot);
14251484
kfree(w->name);
14261485
/* w->name is freed later by soc_tplg_dapm_widget_create() */
1427-
w->name = kasprintf(GFP_KERNEL, dw->name, __ffs(mach->mach_params.i2s_link_mask));
1428-
if (!w->name)
1429-
return -ENOMEM;
1486+
w->name = buf;
14301487
}
14311488

1489+
static_name:
14321490
template = avs_tplg_path_template_create(comp, tplg, dw->priv.array,
14331491
le32_to_cpu(dw->priv.size));
14341492
if (IS_ERR(template)) {

0 commit comments

Comments
 (0)