return 0;
}
+static int avs_parse_nhlt_config_size(struct snd_soc_component *comp, void *elem, void *object,
+ u32 offset)
+{
+ struct snd_soc_tplg_vendor_value_elem *tuple = elem;
+ struct acpi_nhlt_config **blob = (struct acpi_nhlt_config **)((u8 *)object + offset);
+ u32 size;
+
+ size = le32_to_cpu(tuple->value);
+ *blob = devm_kzalloc(comp->card->dev, struct_size(*blob, capabilities, size), GFP_KERNEL);
+ if (!*blob)
+ return -ENOMEM;
+
+ (*blob)->capabilities_size = size;
+ return 0;
+}
+
static int
parse_dictionary_header(struct snd_soc_component *comp,
struct snd_soc_tplg_vendor_array *tuples,
static int avs_tplg_parse_initial_configs(struct snd_soc_component *comp,
struct snd_soc_tplg_vendor_array *tuples,
- u32 block_size)
+ u32 block_size, u32 *offset)
{
struct avs_soc_component *acomp = to_avs_soc_component(comp);
struct avs_tplg *tplg = acomp->tplg;
int ret, i;
+ *offset = 0;
+
/* Parse tuple section telling how many init configs there are. */
ret = parse_dictionary_header(comp, tuples, (void **)&tplg->init_configs,
&tplg->num_init_configs,
return ret;
block_size -= le32_to_cpu(tuples->size);
+ *offset += le32_to_cpu(tuples->size);
/* With header parsed, move on to parsing entries. */
tuples = avs_tplg_vendor_array_next(tuples);
*/
tmp = avs_tplg_vendor_array_next(tuples);
esize = le32_to_cpu(tuples->size) + le32_to_cpu(tmp->size);
+ *offset += esize;
ret = parse_dictionary_entries(comp, tuples, esize, config, 1, sizeof(*config),
AVS_TKN_INIT_CONFIG_ID_U32,
/* handle raw data section */
init_config_data = (void *)tuples + esize;
esize = config->length;
+ *offset += esize;
config->data = devm_kmemdup(comp->card->dev, init_config_data, esize, GFP_KERNEL);
if (!config->data)
return 0;
}
+static const struct avs_tplg_token_parser mod_nhlt_config_parsers[] = {
+ {
+ .token = AVS_TKN_NHLT_CONFIG_ID_U32,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .offset = offsetof(struct avs_tplg_nhlt_config, id),
+ .parse = avs_parse_word_token,
+ },
+ {
+ .token = AVS_TKN_NHLT_CONFIG_SIZE_U32,
+ .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
+ .offset = offsetof(struct avs_tplg_nhlt_config, blob),
+ .parse = avs_parse_nhlt_config_size,
+ },
+};
+
+static int avs_tplg_parse_nhlt_configs(struct snd_soc_component *comp,
+ struct snd_soc_tplg_vendor_array *tuples,
+ u32 block_size)
+{
+ struct avs_soc_component *acomp = to_avs_soc_component(comp);
+ struct avs_tplg *tplg = acomp->tplg;
+ int ret, i;
+
+ /* Parse the header section to know how many entries there are. */
+ ret = parse_dictionary_header(comp, tuples, (void **)&tplg->nhlt_configs,
+ &tplg->num_nhlt_configs,
+ sizeof(*tplg->nhlt_configs),
+ AVS_TKN_MANIFEST_NUM_NHLT_CONFIGS_U32);
+ if (ret)
+ return ret;
+
+ block_size -= le32_to_cpu(tuples->size);
+ /* With the header parsed, move on to parsing entries. */
+ tuples = avs_tplg_vendor_array_next(tuples);
+
+ for (i = 0; i < tplg->num_nhlt_configs && block_size > 0; i++) {
+ struct avs_tplg_nhlt_config *config;
+ u32 esize;
+
+ config = &tplg->nhlt_configs[i];
+ esize = le32_to_cpu(tuples->size);
+
+ ret = parse_dictionary_entries(comp, tuples, esize, config, 1, sizeof(*config),
+ AVS_TKN_NHLT_CONFIG_ID_U32,
+ mod_nhlt_config_parsers,
+ ARRAY_SIZE(mod_nhlt_config_parsers));
+ if (ret)
+ return ret;
+ /* With tuples parsed, the blob shall be allocated. */
+ if (!config->blob)
+ return -EINVAL;
+
+ /* Consume the raw data and move to the next entry. */
+ memcpy(config->blob->capabilities, (u8 *)tuples + esize,
+ config->blob->capabilities_size);
+ esize += config->blob->capabilities_size;
+
+ block_size -= esize;
+ tuples = avs_tplg_vendor_array_at(tuples, esize);
+ }
+
+ return 0;
+}
+
static int avs_route_load(struct snd_soc_component *comp, int index,
struct snd_soc_dapm_route *route)
{
tuples = avs_tplg_vendor_array_at(tuples, offset);
/* Initial configs dictionary. */
- ret = avs_tplg_parse_initial_configs(comp, tuples, remaining);
+ ret = avs_tplg_parse_initial_configs(comp, tuples, remaining, &offset);
if (ret < 0)
return ret;
- return 0;
+ remaining -= offset;
+ tuples = avs_tplg_vendor_array_at(tuples, offset);
+
+ ret = avs_tplg_vendor_array_lookup(tuples, remaining,
+ AVS_TKN_MANIFEST_NUM_NHLT_CONFIGS_U32, &offset);
+ if (ret == -ENOENT)
+ return 0;
+ if (ret) {
+ dev_err(comp->dev, "NHLT config lookup failed: %d\n", ret);
+ return ret;
+ }
+
+ tuples = avs_tplg_vendor_array_at(tuples, offset);
+
+ /* NHLT configs dictionary. */
+ return avs_tplg_parse_nhlt_configs(comp, tuples, remaining);
}
enum {