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+
374397static 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
813842assign_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
836877static 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