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 <errno.h> 21c72fcc34Sopenharmony_ci#include <stdio.h> 22c72fcc34Sopenharmony_ci#include <alsa/asoundlib.h> 23c72fcc34Sopenharmony_ci#include "topology.h" 24c72fcc34Sopenharmony_ci#include "pre-processor.h" 25c72fcc34Sopenharmony_ci 26c72fcc34Sopenharmony_ciint tplg_build_base_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 27c72fcc34Sopenharmony_ci snd_config_t *parent, bool skip_name) 28c72fcc34Sopenharmony_ci{ 29c72fcc34Sopenharmony_ci snd_config_t *top, *parent_obj, *cfg, *dest; 30c72fcc34Sopenharmony_ci const char *parent_name; 31c72fcc34Sopenharmony_ci 32c72fcc34Sopenharmony_ci /* find parent section config */ 33c72fcc34Sopenharmony_ci top = tplg_object_get_section(tplg_pp, parent); 34c72fcc34Sopenharmony_ci if (!top) 35c72fcc34Sopenharmony_ci return -EINVAL; 36c72fcc34Sopenharmony_ci 37c72fcc34Sopenharmony_ci parent_obj = tplg_object_get_instance_config(tplg_pp, parent); 38c72fcc34Sopenharmony_ci 39c72fcc34Sopenharmony_ci /* get parent name */ 40c72fcc34Sopenharmony_ci parent_name = tplg_object_get_name(tplg_pp, parent_obj); 41c72fcc34Sopenharmony_ci if (!parent_name) 42c72fcc34Sopenharmony_ci return 0; 43c72fcc34Sopenharmony_ci 44c72fcc34Sopenharmony_ci /* find parent config with name */ 45c72fcc34Sopenharmony_ci dest = tplg_find_config(top, parent_name); 46c72fcc34Sopenharmony_ci if (!dest) { 47c72fcc34Sopenharmony_ci SNDERR("Cannot find parent config %s\n", parent_name); 48c72fcc34Sopenharmony_ci return -EINVAL; 49c72fcc34Sopenharmony_ci } 50c72fcc34Sopenharmony_ci 51c72fcc34Sopenharmony_ci /* build config from template and add to parent */ 52c72fcc34Sopenharmony_ci return tplg_build_object_from_template(tplg_pp, obj_cfg, &cfg, dest, skip_name); 53c72fcc34Sopenharmony_ci} 54c72fcc34Sopenharmony_ci 55c72fcc34Sopenharmony_ciint tplg_build_scale_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 56c72fcc34Sopenharmony_ci snd_config_t *parent) 57c72fcc34Sopenharmony_ci{ 58c72fcc34Sopenharmony_ci return tplg_build_base_object(tplg_pp, obj_cfg, parent, true); 59c72fcc34Sopenharmony_ci} 60c72fcc34Sopenharmony_ci 61c72fcc34Sopenharmony_ciint tplg_build_ops_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 62c72fcc34Sopenharmony_ci snd_config_t *parent) 63c72fcc34Sopenharmony_ci{ 64c72fcc34Sopenharmony_ci return tplg_build_base_object(tplg_pp, obj_cfg, parent, false); 65c72fcc34Sopenharmony_ci} 66c72fcc34Sopenharmony_ci 67c72fcc34Sopenharmony_ciint tplg_build_channel_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 68c72fcc34Sopenharmony_ci snd_config_t *parent) 69c72fcc34Sopenharmony_ci{ 70c72fcc34Sopenharmony_ci return tplg_build_base_object(tplg_pp, obj_cfg, parent, false); 71c72fcc34Sopenharmony_ci} 72c72fcc34Sopenharmony_ci 73c72fcc34Sopenharmony_ciint tplg_build_text_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 74c72fcc34Sopenharmony_ci snd_config_t *parent) 75c72fcc34Sopenharmony_ci{ 76c72fcc34Sopenharmony_ci snd_config_t *cfg; 77c72fcc34Sopenharmony_ci const char *name; 78c72fcc34Sopenharmony_ci int ret; 79c72fcc34Sopenharmony_ci 80c72fcc34Sopenharmony_ci cfg = tplg_object_get_instance_config(tplg_pp, obj_cfg); 81c72fcc34Sopenharmony_ci 82c72fcc34Sopenharmony_ci name = tplg_object_get_name(tplg_pp, cfg); 83c72fcc34Sopenharmony_ci if (!name) 84c72fcc34Sopenharmony_ci return -EINVAL; 85c72fcc34Sopenharmony_ci 86c72fcc34Sopenharmony_ci ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &cfg, NULL, false); 87c72fcc34Sopenharmony_ci if (ret < 0) 88c72fcc34Sopenharmony_ci return ret; 89c72fcc34Sopenharmony_ci 90c72fcc34Sopenharmony_ci return tplg_parent_update(tplg_pp, parent, "texts", name); 91c72fcc34Sopenharmony_ci} 92c72fcc34Sopenharmony_ci 93c72fcc34Sopenharmony_ciint tplg_build_tlv_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 94c72fcc34Sopenharmony_ci snd_config_t *parent) 95c72fcc34Sopenharmony_ci{ 96c72fcc34Sopenharmony_ci snd_config_t *cfg; 97c72fcc34Sopenharmony_ci const char *name; 98c72fcc34Sopenharmony_ci int ret; 99c72fcc34Sopenharmony_ci 100c72fcc34Sopenharmony_ci cfg = tplg_object_get_instance_config(tplg_pp, obj_cfg); 101c72fcc34Sopenharmony_ci 102c72fcc34Sopenharmony_ci name = tplg_object_get_name(tplg_pp, cfg); 103c72fcc34Sopenharmony_ci if (!name) 104c72fcc34Sopenharmony_ci return -EINVAL; 105c72fcc34Sopenharmony_ci 106c72fcc34Sopenharmony_ci ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &cfg, NULL, false); 107c72fcc34Sopenharmony_ci if (ret < 0) 108c72fcc34Sopenharmony_ci return ret; 109c72fcc34Sopenharmony_ci 110c72fcc34Sopenharmony_ci return tplg_parent_update(tplg_pp, parent, "tlv", name); 111c72fcc34Sopenharmony_ci} 112c72fcc34Sopenharmony_ci 113c72fcc34Sopenharmony_cistatic int tplg_build_control(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 114c72fcc34Sopenharmony_ci snd_config_t *parent, char *type) 115c72fcc34Sopenharmony_ci{ 116c72fcc34Sopenharmony_ci snd_config_t *cfg, *obj; 117c72fcc34Sopenharmony_ci const char *name; 118c72fcc34Sopenharmony_ci int ret; 119c72fcc34Sopenharmony_ci 120c72fcc34Sopenharmony_ci obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); 121c72fcc34Sopenharmony_ci 122c72fcc34Sopenharmony_ci /* get control name */ 123c72fcc34Sopenharmony_ci ret = snd_config_search(obj, "name", &cfg); 124c72fcc34Sopenharmony_ci if (ret < 0) 125c72fcc34Sopenharmony_ci return 0; 126c72fcc34Sopenharmony_ci 127c72fcc34Sopenharmony_ci ret = snd_config_get_string(cfg, &name); 128c72fcc34Sopenharmony_ci if (ret < 0) 129c72fcc34Sopenharmony_ci return ret; 130c72fcc34Sopenharmony_ci 131c72fcc34Sopenharmony_ci ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &cfg, NULL, false); 132c72fcc34Sopenharmony_ci if (ret < 0) 133c72fcc34Sopenharmony_ci return ret; 134c72fcc34Sopenharmony_ci 135c72fcc34Sopenharmony_ci ret = tplg_add_object_data(tplg_pp, obj_cfg, cfg, NULL); 136c72fcc34Sopenharmony_ci if (ret < 0) 137c72fcc34Sopenharmony_ci SNDERR("Failed to add data section for %s\n", name); 138c72fcc34Sopenharmony_ci 139c72fcc34Sopenharmony_ci return tplg_parent_update(tplg_pp, parent, type, name); 140c72fcc34Sopenharmony_ci} 141c72fcc34Sopenharmony_ci 142c72fcc34Sopenharmony_ciint tplg_build_mixer_control(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 143c72fcc34Sopenharmony_ci snd_config_t *parent) 144c72fcc34Sopenharmony_ci{ 145c72fcc34Sopenharmony_ci return tplg_build_control(tplg_pp, obj_cfg, parent, "mixer"); 146c72fcc34Sopenharmony_ci} 147c72fcc34Sopenharmony_ci 148c72fcc34Sopenharmony_ciint tplg_build_bytes_control(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 149c72fcc34Sopenharmony_ci snd_config_t *parent) 150c72fcc34Sopenharmony_ci{ 151c72fcc34Sopenharmony_ci return tplg_build_control(tplg_pp, obj_cfg, parent, "bytes"); 152c72fcc34Sopenharmony_ci} 153c72fcc34Sopenharmony_ci 154c72fcc34Sopenharmony_ciint tplg_build_enum_control(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 155c72fcc34Sopenharmony_ci snd_config_t *parent) 156c72fcc34Sopenharmony_ci{ 157c72fcc34Sopenharmony_ci return tplg_build_control(tplg_pp, obj_cfg, parent, "enum"); 158c72fcc34Sopenharmony_ci} 159c72fcc34Sopenharmony_ci 160c72fcc34Sopenharmony_ci/* 161c72fcc34Sopenharmony_ci * Widget names for pipeline endpoints can be of the following type: 162c72fcc34Sopenharmony_ci * "class.<constructor args separated by .> ex: pga.0.1, buffer.1.1 etc 163c72fcc34Sopenharmony_ci * Optionally, the index argument for a widget can be omitted and will be substituted with 164c72fcc34Sopenharmony_ci * the index from the route: ex: pga..0, host..playback etc 165c72fcc34Sopenharmony_ci */ 166c72fcc34Sopenharmony_cistatic int tplg_pp_get_widget_name(struct tplg_pre_processor *tplg_pp, 167c72fcc34Sopenharmony_ci const char *string, long index, char **widget) 168c72fcc34Sopenharmony_ci{ 169c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 170c72fcc34Sopenharmony_ci snd_config_t *temp_cfg, *child, *class_cfg, *n; 171c72fcc34Sopenharmony_ci char *class_name, *args, *widget_name; 172c72fcc34Sopenharmony_ci int ret; 173c72fcc34Sopenharmony_ci 174c72fcc34Sopenharmony_ci /* get class name */ 175c72fcc34Sopenharmony_ci args = strchr(string, '.'); 176c72fcc34Sopenharmony_ci if (!args) { 177c72fcc34Sopenharmony_ci SNDERR("Error getting class name for %s\n", string); 178c72fcc34Sopenharmony_ci return -EINVAL; 179c72fcc34Sopenharmony_ci } 180c72fcc34Sopenharmony_ci 181c72fcc34Sopenharmony_ci class_name = calloc(1, strlen(string) - strlen(args) + 1); 182c72fcc34Sopenharmony_ci if (!class_name) 183c72fcc34Sopenharmony_ci return -ENOMEM; 184c72fcc34Sopenharmony_ci 185c72fcc34Sopenharmony_ci snprintf(class_name, strlen(string) - strlen(args) + 1, "%s", string); 186c72fcc34Sopenharmony_ci 187c72fcc34Sopenharmony_ci /* create config with Widget class type */ 188c72fcc34Sopenharmony_ci ret = snd_config_make(&temp_cfg, "Widget", SND_CONFIG_TYPE_COMPOUND); 189c72fcc34Sopenharmony_ci if (ret < 0) { 190c72fcc34Sopenharmony_ci free(class_name); 191c72fcc34Sopenharmony_ci return ret; 192c72fcc34Sopenharmony_ci } 193c72fcc34Sopenharmony_ci 194c72fcc34Sopenharmony_ci /* create config with class name and add it to the Widget config */ 195c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, class_name, SND_CONFIG_TYPE_COMPOUND, temp_cfg); 196c72fcc34Sopenharmony_ci if (ret < 0) { 197c72fcc34Sopenharmony_ci free(class_name); 198c72fcc34Sopenharmony_ci return ret; 199c72fcc34Sopenharmony_ci } 200c72fcc34Sopenharmony_ci 201c72fcc34Sopenharmony_ci /* get class definition for widget */ 202c72fcc34Sopenharmony_ci class_cfg = tplg_class_lookup(tplg_pp, temp_cfg); 203c72fcc34Sopenharmony_ci snd_config_delete(temp_cfg); 204c72fcc34Sopenharmony_ci if (!class_cfg) { 205c72fcc34Sopenharmony_ci free(class_name); 206c72fcc34Sopenharmony_ci return -EINVAL; 207c72fcc34Sopenharmony_ci } 208c72fcc34Sopenharmony_ci 209c72fcc34Sopenharmony_ci /* get constructor for class */ 210c72fcc34Sopenharmony_ci ret = snd_config_search(class_cfg, "attributes.constructor", &temp_cfg); 211c72fcc34Sopenharmony_ci if (ret < 0) { 212c72fcc34Sopenharmony_ci SNDERR("No arguments in class for widget %s\n", string); 213c72fcc34Sopenharmony_ci free(class_name); 214c72fcc34Sopenharmony_ci return ret; 215c72fcc34Sopenharmony_ci } 216c72fcc34Sopenharmony_ci 217c72fcc34Sopenharmony_ci widget_name = strdup(class_name); 218c72fcc34Sopenharmony_ci free(class_name); 219c72fcc34Sopenharmony_ci if (!widget_name) 220c72fcc34Sopenharmony_ci return -ENOMEM; 221c72fcc34Sopenharmony_ci 222c72fcc34Sopenharmony_ci /* construct widget name using the constructor argument values */ 223c72fcc34Sopenharmony_ci snd_config_for_each(i, next, temp_cfg) { 224c72fcc34Sopenharmony_ci const char *id; 225c72fcc34Sopenharmony_ci char *arg, *remaining, *temp; 226c72fcc34Sopenharmony_ci 227c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 228c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &id) < 0) 229c72fcc34Sopenharmony_ci continue; 230c72fcc34Sopenharmony_ci 231c72fcc34Sopenharmony_ci if (!args) { 232c72fcc34Sopenharmony_ci SNDERR("insufficient arugments for widget %s\n", string); 233c72fcc34Sopenharmony_ci ret = -EINVAL; 234c72fcc34Sopenharmony_ci goto err; 235c72fcc34Sopenharmony_ci } 236c72fcc34Sopenharmony_ci 237c72fcc34Sopenharmony_ci remaining = strchr(args + 1, '.'); 238c72fcc34Sopenharmony_ci if (remaining) { 239c72fcc34Sopenharmony_ci arg = calloc(1, strlen(args + 1) - strlen(remaining) + 1); 240c72fcc34Sopenharmony_ci if (!arg) { 241c72fcc34Sopenharmony_ci ret = -ENOMEM; 242c72fcc34Sopenharmony_ci goto err; 243c72fcc34Sopenharmony_ci } 244c72fcc34Sopenharmony_ci snprintf(arg, strlen(args + 1) - strlen(remaining) + 1, "%s", args + 1); 245c72fcc34Sopenharmony_ci } else { 246c72fcc34Sopenharmony_ci arg = calloc(1, strlen(args + 1) + 1); 247c72fcc34Sopenharmony_ci if (!arg) { 248c72fcc34Sopenharmony_ci ret = -ENOMEM; 249c72fcc34Sopenharmony_ci goto err; 250c72fcc34Sopenharmony_ci } 251c72fcc34Sopenharmony_ci 252c72fcc34Sopenharmony_ci snprintf(arg, strlen(args + 1) + 1, "%s", args + 1); 253c72fcc34Sopenharmony_ci } 254c72fcc34Sopenharmony_ci 255c72fcc34Sopenharmony_ci /* if no index provided, substitue with route index */ 256c72fcc34Sopenharmony_ci if (!strcmp(arg, "") && !strcmp(id, "index")) { 257c72fcc34Sopenharmony_ci free(arg); 258c72fcc34Sopenharmony_ci arg = tplg_snprintf("%ld", index); 259c72fcc34Sopenharmony_ci if (!arg) { 260c72fcc34Sopenharmony_ci ret = -ENOMEM; 261c72fcc34Sopenharmony_ci free(arg); 262c72fcc34Sopenharmony_ci goto err; 263c72fcc34Sopenharmony_ci } 264c72fcc34Sopenharmony_ci } 265c72fcc34Sopenharmony_ci 266c72fcc34Sopenharmony_ci temp = tplg_snprintf("%s.%s", widget_name, arg); 267c72fcc34Sopenharmony_ci if (!temp) { 268c72fcc34Sopenharmony_ci ret = -ENOMEM; 269c72fcc34Sopenharmony_ci free(arg); 270c72fcc34Sopenharmony_ci goto err; 271c72fcc34Sopenharmony_ci } 272c72fcc34Sopenharmony_ci 273c72fcc34Sopenharmony_ci free(widget_name); 274c72fcc34Sopenharmony_ci widget_name = temp; 275c72fcc34Sopenharmony_ci free(arg); 276c72fcc34Sopenharmony_ci if (remaining) 277c72fcc34Sopenharmony_ci args = remaining; 278c72fcc34Sopenharmony_ci else 279c72fcc34Sopenharmony_ci args = NULL; 280c72fcc34Sopenharmony_ci } 281c72fcc34Sopenharmony_ci 282c72fcc34Sopenharmony_ci *widget = widget_name; 283c72fcc34Sopenharmony_ci return 0; 284c72fcc34Sopenharmony_ci 285c72fcc34Sopenharmony_cierr: 286c72fcc34Sopenharmony_ci free(widget_name); 287c72fcc34Sopenharmony_ci return ret; 288c72fcc34Sopenharmony_ci} 289c72fcc34Sopenharmony_ci 290c72fcc34Sopenharmony_ciint tplg_build_dapm_route_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 291c72fcc34Sopenharmony_ci snd_config_t *parent) 292c72fcc34Sopenharmony_ci{ 293c72fcc34Sopenharmony_ci snd_config_t *top, *obj, *cfg, *route, *child, *parent_obj; 294c72fcc34Sopenharmony_ci const char *name, *wname; 295c72fcc34Sopenharmony_ci const char *parent_name = "Endpoint"; 296c72fcc34Sopenharmony_ci char *src_widget_name, *sink_widget_name, *line_str, *route_name; 297c72fcc34Sopenharmony_ci const char *control = ""; 298c72fcc34Sopenharmony_ci long index = 0; 299c72fcc34Sopenharmony_ci int ret; 300c72fcc34Sopenharmony_ci 301c72fcc34Sopenharmony_ci obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); 302c72fcc34Sopenharmony_ci 303c72fcc34Sopenharmony_ci ret = snd_config_get_id(obj, &name); 304c72fcc34Sopenharmony_ci if (ret < 0) 305c72fcc34Sopenharmony_ci return -EINVAL; 306c72fcc34Sopenharmony_ci 307c72fcc34Sopenharmony_ci /* endpoint connections at the top-level conf have no parent */ 308c72fcc34Sopenharmony_ci if (parent) { 309c72fcc34Sopenharmony_ci parent_obj = tplg_object_get_instance_config(tplg_pp, parent); 310c72fcc34Sopenharmony_ci 311c72fcc34Sopenharmony_ci ret = snd_config_get_id(parent_obj, &parent_name); 312c72fcc34Sopenharmony_ci if (ret < 0) 313c72fcc34Sopenharmony_ci return -EINVAL; 314c72fcc34Sopenharmony_ci } 315c72fcc34Sopenharmony_ci 316c72fcc34Sopenharmony_ci tplg_pp_debug("Building DAPM route object: '%s' ...", name); 317c72fcc34Sopenharmony_ci 318c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->output_cfg, "SectionGraph", &top); 319c72fcc34Sopenharmony_ci if (ret < 0) { 320c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&top, "SectionGraph", 321c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_COMPOUND, tplg_pp->output_cfg); 322c72fcc34Sopenharmony_ci if (ret < 0) { 323c72fcc34Sopenharmony_ci SNDERR("Error creating 'SectionGraph' config\n"); 324c72fcc34Sopenharmony_ci return ret; 325c72fcc34Sopenharmony_ci } 326c72fcc34Sopenharmony_ci } 327c72fcc34Sopenharmony_ci 328c72fcc34Sopenharmony_ci /* get route index */ 329c72fcc34Sopenharmony_ci ret = snd_config_search(obj, "index", &cfg); 330c72fcc34Sopenharmony_ci if (ret >= 0) { 331c72fcc34Sopenharmony_ci ret = snd_config_get_integer(cfg, &index); 332c72fcc34Sopenharmony_ci if (ret < 0) { 333c72fcc34Sopenharmony_ci SNDERR("Invalid index route %s\n", name); 334c72fcc34Sopenharmony_ci return ret; 335c72fcc34Sopenharmony_ci } 336c72fcc34Sopenharmony_ci } 337c72fcc34Sopenharmony_ci 338c72fcc34Sopenharmony_ci /* get source widget name */ 339c72fcc34Sopenharmony_ci ret = snd_config_search(obj, "source", &cfg); 340c72fcc34Sopenharmony_ci if (ret < 0) { 341c72fcc34Sopenharmony_ci SNDERR("No source for route %s\n", name); 342c72fcc34Sopenharmony_ci return ret; 343c72fcc34Sopenharmony_ci } 344c72fcc34Sopenharmony_ci 345c72fcc34Sopenharmony_ci ret = snd_config_get_string(cfg, &wname); 346c72fcc34Sopenharmony_ci if (ret < 0) { 347c72fcc34Sopenharmony_ci SNDERR("Invalid name for source in route %s\n", name); 348c72fcc34Sopenharmony_ci return ret; 349c72fcc34Sopenharmony_ci } 350c72fcc34Sopenharmony_ci 351c72fcc34Sopenharmony_ci ret = tplg_pp_get_widget_name(tplg_pp, wname, index, &src_widget_name); 352c72fcc34Sopenharmony_ci if (ret < 0) { 353c72fcc34Sopenharmony_ci SNDERR("error getting widget name for %s\n", wname); 354c72fcc34Sopenharmony_ci return ret; 355c72fcc34Sopenharmony_ci } 356c72fcc34Sopenharmony_ci 357c72fcc34Sopenharmony_ci /* get sink widget name */ 358c72fcc34Sopenharmony_ci ret = snd_config_search(obj, "sink", &cfg); 359c72fcc34Sopenharmony_ci if (ret < 0) { 360c72fcc34Sopenharmony_ci SNDERR("No sink for route %s\n", name); 361c72fcc34Sopenharmony_ci free(src_widget_name); 362c72fcc34Sopenharmony_ci return ret; 363c72fcc34Sopenharmony_ci } 364c72fcc34Sopenharmony_ci 365c72fcc34Sopenharmony_ci ret = snd_config_get_string(cfg, &wname); 366c72fcc34Sopenharmony_ci if (ret < 0) { 367c72fcc34Sopenharmony_ci SNDERR("Invalid name for sink in route %s\n", name); 368c72fcc34Sopenharmony_ci free(src_widget_name); 369c72fcc34Sopenharmony_ci return ret; 370c72fcc34Sopenharmony_ci } 371c72fcc34Sopenharmony_ci 372c72fcc34Sopenharmony_ci ret = tplg_pp_get_widget_name(tplg_pp, wname, index, &sink_widget_name); 373c72fcc34Sopenharmony_ci if (ret < 0) { 374c72fcc34Sopenharmony_ci SNDERR("error getting widget name for %s\n", wname); 375c72fcc34Sopenharmony_ci free(src_widget_name); 376c72fcc34Sopenharmony_ci return ret; 377c72fcc34Sopenharmony_ci } 378c72fcc34Sopenharmony_ci 379c72fcc34Sopenharmony_ci /* get control name */ 380c72fcc34Sopenharmony_ci ret = snd_config_search(obj, "control", &cfg); 381c72fcc34Sopenharmony_ci if (ret >= 0) { 382c72fcc34Sopenharmony_ci ret = snd_config_get_string(cfg, &control); 383c72fcc34Sopenharmony_ci if (ret < 0) { 384c72fcc34Sopenharmony_ci SNDERR("Invalid control name for route %s\n", name); 385c72fcc34Sopenharmony_ci goto err; 386c72fcc34Sopenharmony_ci } 387c72fcc34Sopenharmony_ci } 388c72fcc34Sopenharmony_ci 389c72fcc34Sopenharmony_ci /* add route */ 390c72fcc34Sopenharmony_ci route_name = tplg_snprintf("%s.%s", parent_name, name); 391c72fcc34Sopenharmony_ci if (!route_name) { 392c72fcc34Sopenharmony_ci ret = -ENOMEM; 393c72fcc34Sopenharmony_ci goto err; 394c72fcc34Sopenharmony_ci } 395c72fcc34Sopenharmony_ci 396c72fcc34Sopenharmony_ci ret = snd_config_make(&route, route_name, SND_CONFIG_TYPE_COMPOUND); 397c72fcc34Sopenharmony_ci free(route_name); 398c72fcc34Sopenharmony_ci if (ret < 0) { 399c72fcc34Sopenharmony_ci SNDERR("Error creating route config for %s %d\n", name, ret); 400c72fcc34Sopenharmony_ci goto err; 401c72fcc34Sopenharmony_ci } 402c72fcc34Sopenharmony_ci 403c72fcc34Sopenharmony_ci ret = snd_config_add(top, route); 404c72fcc34Sopenharmony_ci if (ret < 0) { 405c72fcc34Sopenharmony_ci SNDERR("Error adding route config for %s %d\n", name, ret); 406c72fcc34Sopenharmony_ci goto err; 407c72fcc34Sopenharmony_ci } 408c72fcc34Sopenharmony_ci 409c72fcc34Sopenharmony_ci /* add index */ 410c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, "index", SND_CONFIG_TYPE_INTEGER, route); 411c72fcc34Sopenharmony_ci if (ret < 0) { 412c72fcc34Sopenharmony_ci SNDERR("Error creating index config for %s\n", name); 413c72fcc34Sopenharmony_ci goto err; 414c72fcc34Sopenharmony_ci } 415c72fcc34Sopenharmony_ci 416c72fcc34Sopenharmony_ci ret = snd_config_set_integer(child, index); 417c72fcc34Sopenharmony_ci if (ret < 0) { 418c72fcc34Sopenharmony_ci SNDERR("Error setting index config for %s\n", name); 419c72fcc34Sopenharmony_ci goto err; 420c72fcc34Sopenharmony_ci } 421c72fcc34Sopenharmony_ci 422c72fcc34Sopenharmony_ci /* add lines */ 423c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&cfg, "lines", SND_CONFIG_TYPE_COMPOUND, route); 424c72fcc34Sopenharmony_ci if (ret < 0) { 425c72fcc34Sopenharmony_ci SNDERR("Error creating lines config for %s\n", name); 426c72fcc34Sopenharmony_ci goto err; 427c72fcc34Sopenharmony_ci } 428c72fcc34Sopenharmony_ci 429c72fcc34Sopenharmony_ci /* add route string */ 430c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, "0", SND_CONFIG_TYPE_STRING, cfg); 431c72fcc34Sopenharmony_ci if (ret < 0) { 432c72fcc34Sopenharmony_ci SNDERR("Error creating lines config for %s\n", name); 433c72fcc34Sopenharmony_ci goto err; 434c72fcc34Sopenharmony_ci } 435c72fcc34Sopenharmony_ci 436c72fcc34Sopenharmony_ci line_str = tplg_snprintf("%s, %s, %s", sink_widget_name, control, src_widget_name); 437c72fcc34Sopenharmony_ci if (!line_str) { 438c72fcc34Sopenharmony_ci ret = -ENOMEM; 439c72fcc34Sopenharmony_ci goto err; 440c72fcc34Sopenharmony_ci } 441c72fcc34Sopenharmony_ci 442c72fcc34Sopenharmony_ci /* set the line string */ 443c72fcc34Sopenharmony_ci ret = snd_config_set_string(child, line_str); 444c72fcc34Sopenharmony_ci free(line_str); 445c72fcc34Sopenharmony_ci if (ret < 0) 446c72fcc34Sopenharmony_ci SNDERR("Error creating lines config for %s\n", name); 447c72fcc34Sopenharmony_cierr: 448c72fcc34Sopenharmony_ci free(src_widget_name); 449c72fcc34Sopenharmony_ci free(sink_widget_name); 450c72fcc34Sopenharmony_ci return ret; 451c72fcc34Sopenharmony_ci} 452