@@ -1118,24 +1118,72 @@ static const struct avs_tplg_token_parser module_parsers[] = {
11181118 .offset = offsetof(struct avs_tplg_module , ctl_id ),
11191119 .parse = avs_parse_byte_token ,
11201120 },
1121+ {
1122+ .token = AVS_TKN_MOD_INIT_CONFIG_NUM_IDS_U32 ,
1123+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD ,
1124+ .offset = offsetof(struct avs_tplg_module , num_config_ids ),
1125+ .parse = avs_parse_byte_token ,
1126+ },
1127+ };
1128+
1129+ static const struct avs_tplg_token_parser init_config_parsers [] = {
1130+ {
1131+ .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32 ,
1132+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD ,
1133+ .offset = 0 ,
1134+ .parse = avs_parse_word_token ,
1135+ },
11211136};
11221137
11231138static struct avs_tplg_module *
11241139avs_tplg_module_create (struct snd_soc_component * comp , struct avs_tplg_pipeline * owner ,
11251140 struct snd_soc_tplg_vendor_array * tuples , u32 block_size )
11261141{
11271142 struct avs_tplg_module * module ;
1143+ u32 esize ;
11281144 int ret ;
11291145
1146+ /* See where config id block starts. */
1147+ ret = avs_tplg_vendor_entry_size (tuples , block_size ,
1148+ AVS_TKN_MOD_INIT_CONFIG_ID_U32 , & esize );
1149+ if (ret )
1150+ return ERR_PTR (ret );
1151+
11301152 module = devm_kzalloc (comp -> card -> dev , sizeof (* module ), GFP_KERNEL );
11311153 if (!module )
11321154 return ERR_PTR (- ENOMEM );
11331155
11341156 ret = avs_parse_tokens (comp , module , module_parsers ,
1135- ARRAY_SIZE (module_parsers ), tuples , block_size );
1157+ ARRAY_SIZE (module_parsers ), tuples , esize );
11361158 if (ret < 0 )
11371159 return ERR_PTR (ret );
11381160
1161+ block_size -= esize ;
1162+ /* Parse trailing config ids if any. */
1163+ if (block_size ) {
1164+ u32 num_config_ids = module -> num_config_ids ;
1165+ u32 * config_ids ;
1166+
1167+ if (!num_config_ids )
1168+ return ERR_PTR (- EINVAL );
1169+
1170+ config_ids = devm_kcalloc (comp -> card -> dev , num_config_ids , sizeof (* config_ids ),
1171+ GFP_KERNEL );
1172+ if (!config_ids )
1173+ return ERR_PTR (- ENOMEM );
1174+
1175+ tuples = avs_tplg_vendor_array_at (tuples , esize );
1176+ ret = parse_dictionary_entries (comp , tuples , block_size ,
1177+ config_ids , num_config_ids , sizeof (* config_ids ),
1178+ AVS_TKN_MOD_INIT_CONFIG_ID_U32 ,
1179+ init_config_parsers ,
1180+ ARRAY_SIZE (init_config_parsers ));
1181+ if (ret )
1182+ return ERR_PTR (ret );
1183+
1184+ module -> config_ids = config_ids ;
1185+ }
1186+
11391187 module -> owner = owner ;
11401188 INIT_LIST_HEAD (& module -> node );
11411189
@@ -1416,6 +1464,82 @@ avs_tplg_path_template_create(struct snd_soc_component *comp, struct avs_tplg *o
14161464 return template ;
14171465}
14181466
1467+ static const struct avs_tplg_token_parser mod_init_config_parsers [] = {
1468+ {
1469+ .token = AVS_TKN_MOD_INIT_CONFIG_ID_U32 ,
1470+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD ,
1471+ .offset = offsetof(struct avs_tplg_init_config , id ),
1472+ .parse = avs_parse_word_token ,
1473+ },
1474+ {
1475+ .token = AVS_TKN_INIT_CONFIG_PARAM_U8 ,
1476+ .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE ,
1477+ .offset = offsetof(struct avs_tplg_init_config , param ),
1478+ .parse = avs_parse_byte_token ,
1479+ },
1480+ {
1481+ .token = AVS_TKN_INIT_CONFIG_LENGTH_U32 ,
1482+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD ,
1483+ .offset = offsetof(struct avs_tplg_init_config , length ),
1484+ .parse = avs_parse_word_token ,
1485+ },
1486+ };
1487+
1488+ static int avs_tplg_parse_initial_configs (struct snd_soc_component * comp ,
1489+ struct snd_soc_tplg_vendor_array * tuples ,
1490+ u32 block_size )
1491+ {
1492+ struct avs_soc_component * acomp = to_avs_soc_component (comp );
1493+ struct avs_tplg * tplg = acomp -> tplg ;
1494+ int ret , i ;
1495+
1496+ /* Parse tuple section telling how many init configs there are. */
1497+ ret = parse_dictionary_header (comp , tuples , (void * * )& tplg -> init_configs ,
1498+ & tplg -> num_init_configs ,
1499+ sizeof (* tplg -> init_configs ),
1500+ AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32 );
1501+ if (ret )
1502+ return ret ;
1503+
1504+ block_size -= le32_to_cpu (tuples -> size );
1505+ /* With header parsed, move on to parsing entries. */
1506+ tuples = avs_tplg_vendor_array_next (tuples );
1507+
1508+ for (i = 0 ; i < tplg -> num_init_configs && block_size > 0 ; i ++ ) {
1509+ struct avs_tplg_init_config * config = & tplg -> init_configs [i ];
1510+ struct snd_soc_tplg_vendor_array * tmp ;
1511+ void * init_config_data ;
1512+ u32 esize ;
1513+
1514+ /*
1515+ * Usually to get section length we search for first token of next group of data,
1516+ * but in this case we can't as tuples are followed by raw data.
1517+ */
1518+ tmp = avs_tplg_vendor_array_next (tuples );
1519+ esize = le32_to_cpu (tuples -> size ) + le32_to_cpu (tmp -> size );
1520+
1521+ ret = parse_dictionary_entries (comp , tuples , esize , config , 1 , sizeof (* config ),
1522+ AVS_TKN_MOD_INIT_CONFIG_ID_U32 ,
1523+ mod_init_config_parsers ,
1524+ ARRAY_SIZE (mod_init_config_parsers ));
1525+
1526+ block_size -= esize ;
1527+
1528+ /* handle raw data section */
1529+ init_config_data = (void * )tuples + esize ;
1530+ esize = config -> length ;
1531+
1532+ config -> data = devm_kmemdup (comp -> card -> dev , init_config_data , esize , GFP_KERNEL );
1533+ if (!config -> data )
1534+ return - ENOMEM ;
1535+
1536+ tuples = init_config_data + esize ;
1537+ block_size -= esize ;
1538+ }
1539+
1540+ return 0 ;
1541+ }
1542+
14191543static int avs_route_load (struct snd_soc_component * comp , int index ,
14201544 struct snd_soc_dapm_route * route )
14211545{
@@ -1571,6 +1695,7 @@ static int avs_manifest(struct snd_soc_component *comp, int index,
15711695 struct snd_soc_tplg_vendor_array * tuples = manifest -> priv .array ;
15721696 struct avs_soc_component * acomp = to_avs_soc_component (comp );
15731697 size_t remaining = le32_to_cpu (manifest -> priv .size );
1698+ bool has_init_config = true;
15741699 u32 offset ;
15751700 int ret ;
15761701
@@ -1668,8 +1793,43 @@ static int avs_manifest(struct snd_soc_component *comp, int index,
16681793 remaining -= offset ;
16691794 tuples = avs_tplg_vendor_array_at (tuples , offset );
16701795
1796+ ret = avs_tplg_vendor_array_lookup (tuples , remaining ,
1797+ AVS_TKN_MANIFEST_NUM_CONDPATH_TMPLS_U32 , & offset );
1798+ if (ret ) {
1799+ dev_err (comp -> dev , "condpath lookup failed: %d\n" , ret );
1800+ return ret ;
1801+ }
1802+
16711803 /* Bindings dictionary. */
1672- return avs_tplg_parse_bindings (comp , tuples , remaining );
1804+ ret = avs_tplg_parse_bindings (comp , tuples , offset );
1805+ if (ret < 0 )
1806+ return ret ;
1807+
1808+ remaining -= offset ;
1809+ tuples = avs_tplg_vendor_array_at (tuples , offset );
1810+
1811+ ret = avs_tplg_vendor_array_lookup (tuples , remaining ,
1812+ AVS_TKN_MANIFEST_NUM_INIT_CONFIGS_U32 , & offset );
1813+ if (ret == - ENOENT ) {
1814+ dev_dbg (comp -> dev , "init config lookup failed: %d\n" , ret );
1815+ has_init_config = false;
1816+ } else if (ret ) {
1817+ dev_err (comp -> dev , "init config lookup failed: %d\n" , ret );
1818+ return ret ;
1819+ }
1820+
1821+ if (!has_init_config )
1822+ return 0 ;
1823+
1824+ remaining -= offset ;
1825+ tuples = avs_tplg_vendor_array_at (tuples , offset );
1826+
1827+ /* Initial configs dictionary. */
1828+ ret = avs_tplg_parse_initial_configs (comp , tuples , remaining );
1829+ if (ret < 0 )
1830+ return ret ;
1831+
1832+ return 0 ;
16731833}
16741834
16751835#define AVS_CONTROL_OPS_VOLUME 257
0 commit comments