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