{
return tplg_build_base_object(tplg_pp, obj_cfg, parent, false);
}
+
+static int tplg_update_pcm_object(struct tplg_pre_processor *tplg_pp,
+ snd_config_t *obj_cfg, snd_config_t *parent)
+{
+ snd_config_t *top, *parent_obj, *obj, *dest, *cfg, *pcm, *child;
+ const char *parent_name, *item_name, *direction;
+ int ret;
+
+ /* get object name */
+ obj = tplg_object_get_instance_config(tplg_pp, obj_cfg);
+ item_name = tplg_object_get_name(tplg_pp, obj);
+ if (!item_name)
+ return -EINVAL;
+
+ /* get direction */
+ ret = snd_config_search(obj, "direction", &cfg);
+ if (ret < 0) {
+ SNDERR("no direction attribute in %s\n", item_name);
+ return ret;
+ }
+
+ ret = snd_config_get_string(cfg, &direction);
+ if (ret < 0) {
+ SNDERR("Invalid direction attribute in %s\n", item_name);
+ return ret;
+ }
+
+ /* add to parent section */
+ top = tplg_object_get_section(tplg_pp, parent);
+ if (!top) {
+ SNDERR("Cannot find parent for %s\n", item_name);
+ return -EINVAL;
+ }
+
+ parent_obj = tplg_object_get_instance_config(tplg_pp, parent);
+
+ /* get parent name. if parent has no name, skip adding config */
+ parent_name = tplg_object_get_name(tplg_pp, parent_obj);
+ if (!parent_name)
+ return 0;
+
+ /* find parent config with name */
+ dest = tplg_find_config(top, parent_name);
+ if (!dest) {
+ SNDERR("Cannot find parent section %s\n", parent_name);
+ return -EINVAL;
+ }
+
+ ret = snd_config_search(dest, "pcm", &pcm);
+ if (ret < 0) {
+ ret = tplg_config_make_add(&pcm, "pcm", SND_CONFIG_TYPE_COMPOUND, dest);
+ if (ret < 0) {
+ SNDERR("Error creating pcm config in %s\n", parent_name);
+ return ret;
+ }
+ }
+
+ ret = snd_config_search(pcm, direction, &cfg);
+ if (ret >= 0) {
+ SNDERR("pcm.%s exists already in %s\n", direction, parent_name);
+ return -EEXIST;
+ }
+
+ ret = tplg_config_make_add(&cfg, direction, SND_CONFIG_TYPE_COMPOUND, pcm);
+
+ if (ret >= 0)
+ ret = tplg_config_make_add(&child, "capabilities", SND_CONFIG_TYPE_STRING, cfg);
+
+ if (ret >= 0)
+ ret = snd_config_set_string(child, item_name);
+
+ return ret;
+}
+
+int tplg_build_pcm_caps_object(struct tplg_pre_processor *tplg_pp,
+ snd_config_t *obj_cfg, snd_config_t *parent)
+{
+ snd_config_t *caps;
+ int ret;
+
+ ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &caps, NULL, false);
+ if (ret < 0)
+ return ret;
+
+ /* add pcm capabilities to parent */
+ return tplg_update_pcm_object(tplg_pp, obj_cfg, parent);
+}
return ret;
}
+const struct config_template_items pcm_caps_config = {
+ .int_config_ids = {"rate_min", "rate_max", "channels_min", "channels_max", "periods_min",
+ "periods_max", "period_size_min", "period_size_max", "buffer_size_min",
+ "buffer_size_max", "sig_bits"},
+ .string_config_ids = {"formats", "rates"},
+};
+
const struct config_template_items fe_dai_config = {
.int_config_ids = {"id"},
};
&bytes_control_config},
{"Dai", "", "SectionBE", &tplg_build_generic_object, &be_dai_config},
{"PCM", "pcm", "SectionPCM", &tplg_build_generic_object, &pcm_config},
+ {"PCM", "pcm_caps", "SectionPCMCapabilities", &tplg_build_pcm_caps_object,
+ &pcm_caps_config},
};
static const struct build_function_map *tplg_object_get_map(struct tplg_pre_processor *tplg_pp,