1c72fcc34Sopenharmony_ci/*
2c72fcc34Sopenharmony_ci  Copyright(c) 2021 Intel Corporation
3c72fcc34Sopenharmony_ci  All rights reserved.
4c72fcc34Sopenharmony_ci
5c72fcc34Sopenharmony_ci  This program is free software; you can redistribute it and/or modify
6c72fcc34Sopenharmony_ci  it under the terms of version 2 of the GNU General Public License as
7c72fcc34Sopenharmony_ci  published by the Free Software Foundation.
8c72fcc34Sopenharmony_ci
9c72fcc34Sopenharmony_ci  This program is distributed in the hope that it will be useful, but
10c72fcc34Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
11c72fcc34Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c72fcc34Sopenharmony_ci  General Public License for more details.
13c72fcc34Sopenharmony_ci
14c72fcc34Sopenharmony_ci  You should have received a copy of the GNU General Public License
15c72fcc34Sopenharmony_ci  along with this program; if not, write to the Free Software
16c72fcc34Sopenharmony_ci  Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17c72fcc34Sopenharmony_ci  The full GNU General Public License is included in this distribution
18c72fcc34Sopenharmony_ci  in the file called LICENSE.GPL.
19c72fcc34Sopenharmony_ci*/
20c72fcc34Sopenharmony_ci#include "aconfig.h"
21c72fcc34Sopenharmony_ci#include <errno.h>
22c72fcc34Sopenharmony_ci#include <stdio.h>
23c72fcc34Sopenharmony_ci#include <alsa/asoundlib.h>
24c72fcc34Sopenharmony_ci#include "topology.h"
25c72fcc34Sopenharmony_ci#include "pre-processor.h"
26c72fcc34Sopenharmony_ci
27c72fcc34Sopenharmony_ciint tplg_build_hw_cfg_object(struct tplg_pre_processor *tplg_pp,
28c72fcc34Sopenharmony_ci			       snd_config_t *obj_cfg, snd_config_t *parent)
29c72fcc34Sopenharmony_ci{
30c72fcc34Sopenharmony_ci	snd_config_t *hw_cfg, *obj;
31c72fcc34Sopenharmony_ci	const char *name;
32c72fcc34Sopenharmony_ci	int ret;
33c72fcc34Sopenharmony_ci
34c72fcc34Sopenharmony_ci	obj = tplg_object_get_instance_config(tplg_pp, obj_cfg);
35c72fcc34Sopenharmony_ci
36c72fcc34Sopenharmony_ci	name = tplg_object_get_name(tplg_pp, obj);
37c72fcc34Sopenharmony_ci	if (!name)
38c72fcc34Sopenharmony_ci		return -EINVAL;
39c72fcc34Sopenharmony_ci
40c72fcc34Sopenharmony_ci	ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &hw_cfg, NULL, false);
41c72fcc34Sopenharmony_ci	if (ret < 0)
42c72fcc34Sopenharmony_ci		return ret;
43c72fcc34Sopenharmony_ci
44c72fcc34Sopenharmony_ci	return tplg_parent_update(tplg_pp, parent, "hw_configs", name);
45c72fcc34Sopenharmony_ci}
46c72fcc34Sopenharmony_ci
47c72fcc34Sopenharmony_ciint tplg_build_fe_dai_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg,
48c72fcc34Sopenharmony_ci			      snd_config_t *parent)
49c72fcc34Sopenharmony_ci{
50c72fcc34Sopenharmony_ci	return tplg_build_base_object(tplg_pp, obj_cfg, parent, false);
51c72fcc34Sopenharmony_ci}
52c72fcc34Sopenharmony_ci
53c72fcc34Sopenharmony_cistatic int tplg_update_pcm_object(struct tplg_pre_processor *tplg_pp,
54c72fcc34Sopenharmony_ci			       snd_config_t *obj_cfg, snd_config_t *parent)
55c72fcc34Sopenharmony_ci{
56c72fcc34Sopenharmony_ci	snd_config_t *top, *parent_obj, *obj, *dest, *cfg, *pcm, *child;
57c72fcc34Sopenharmony_ci	const char *parent_name, *item_name, *direction;
58c72fcc34Sopenharmony_ci	int ret;
59c72fcc34Sopenharmony_ci
60c72fcc34Sopenharmony_ci	/* get object name */
61c72fcc34Sopenharmony_ci	obj = tplg_object_get_instance_config(tplg_pp, obj_cfg);
62c72fcc34Sopenharmony_ci	item_name = tplg_object_get_name(tplg_pp, obj);
63c72fcc34Sopenharmony_ci	if (!item_name)
64c72fcc34Sopenharmony_ci		return -EINVAL;
65c72fcc34Sopenharmony_ci
66c72fcc34Sopenharmony_ci	/* get direction */
67c72fcc34Sopenharmony_ci	ret = snd_config_search(obj, "direction", &cfg);
68c72fcc34Sopenharmony_ci	if (ret < 0) {
69c72fcc34Sopenharmony_ci		SNDERR("no direction attribute in %s\n", item_name);
70c72fcc34Sopenharmony_ci		return ret;
71c72fcc34Sopenharmony_ci	}
72c72fcc34Sopenharmony_ci
73c72fcc34Sopenharmony_ci	ret = snd_config_get_string(cfg, &direction);
74c72fcc34Sopenharmony_ci	if (ret < 0) {
75c72fcc34Sopenharmony_ci		SNDERR("Invalid direction attribute in %s\n", item_name);
76c72fcc34Sopenharmony_ci		return ret;
77c72fcc34Sopenharmony_ci	}
78c72fcc34Sopenharmony_ci
79c72fcc34Sopenharmony_ci	/* add to parent section */
80c72fcc34Sopenharmony_ci	top = tplg_object_get_section(tplg_pp, parent);
81c72fcc34Sopenharmony_ci	if (!top) {
82c72fcc34Sopenharmony_ci		SNDERR("Cannot find parent for %s\n", item_name);
83c72fcc34Sopenharmony_ci		return -EINVAL;
84c72fcc34Sopenharmony_ci	}
85c72fcc34Sopenharmony_ci
86c72fcc34Sopenharmony_ci	parent_obj = tplg_object_get_instance_config(tplg_pp, parent);
87c72fcc34Sopenharmony_ci
88c72fcc34Sopenharmony_ci	/* get parent name. if parent has no name, skip adding config */
89c72fcc34Sopenharmony_ci	parent_name = tplg_object_get_name(tplg_pp, parent_obj);
90c72fcc34Sopenharmony_ci	if (!parent_name)
91c72fcc34Sopenharmony_ci		return 0;
92c72fcc34Sopenharmony_ci
93c72fcc34Sopenharmony_ci	/* find parent config with name */
94c72fcc34Sopenharmony_ci	dest = tplg_find_config(top, parent_name);
95c72fcc34Sopenharmony_ci	if (!dest) {
96c72fcc34Sopenharmony_ci		SNDERR("Cannot find parent section %s\n", parent_name);
97c72fcc34Sopenharmony_ci		return -EINVAL;
98c72fcc34Sopenharmony_ci	}
99c72fcc34Sopenharmony_ci
100c72fcc34Sopenharmony_ci	ret = snd_config_search(dest, "pcm", &pcm);
101c72fcc34Sopenharmony_ci	if (ret < 0) {
102c72fcc34Sopenharmony_ci		ret = tplg_config_make_add(&pcm, "pcm", SND_CONFIG_TYPE_COMPOUND, dest);
103c72fcc34Sopenharmony_ci		if (ret < 0) {
104c72fcc34Sopenharmony_ci			SNDERR("Error creating pcm config in %s\n", parent_name);
105c72fcc34Sopenharmony_ci			return ret;
106c72fcc34Sopenharmony_ci		}
107c72fcc34Sopenharmony_ci	}
108c72fcc34Sopenharmony_ci
109c72fcc34Sopenharmony_ci	ret = snd_config_search(pcm, direction, &cfg);
110c72fcc34Sopenharmony_ci	if (ret >= 0) {
111c72fcc34Sopenharmony_ci		SNDERR("pcm.%s exists already in %s\n", direction, parent_name);
112c72fcc34Sopenharmony_ci		return -EEXIST;
113c72fcc34Sopenharmony_ci	}
114c72fcc34Sopenharmony_ci
115c72fcc34Sopenharmony_ci	ret = tplg_config_make_add(&cfg, direction, SND_CONFIG_TYPE_COMPOUND, pcm);
116c72fcc34Sopenharmony_ci
117c72fcc34Sopenharmony_ci	if (ret >= 0)
118c72fcc34Sopenharmony_ci	ret = tplg_config_make_add(&child, "capabilities", SND_CONFIG_TYPE_STRING, cfg);
119c72fcc34Sopenharmony_ci
120c72fcc34Sopenharmony_ci	if (ret >= 0)
121c72fcc34Sopenharmony_ci	ret = snd_config_set_string(child, item_name);
122c72fcc34Sopenharmony_ci
123c72fcc34Sopenharmony_ci	return ret;
124c72fcc34Sopenharmony_ci}
125c72fcc34Sopenharmony_ci
126c72fcc34Sopenharmony_ciint tplg_build_pcm_caps_object(struct tplg_pre_processor *tplg_pp,
127c72fcc34Sopenharmony_ci			       snd_config_t *obj_cfg, snd_config_t *parent)
128c72fcc34Sopenharmony_ci{
129c72fcc34Sopenharmony_ci	snd_config_t *caps;
130c72fcc34Sopenharmony_ci	int ret;
131c72fcc34Sopenharmony_ci
132c72fcc34Sopenharmony_ci	ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &caps, NULL, false);
133c72fcc34Sopenharmony_ci	if (ret < 0)
134c72fcc34Sopenharmony_ci		return ret;
135c72fcc34Sopenharmony_ci
136c72fcc34Sopenharmony_ci	/* add pcm capabilities to parent */
137c72fcc34Sopenharmony_ci	return tplg_update_pcm_object(tplg_pp, obj_cfg, parent);
138c72fcc34Sopenharmony_ci}
139