1d5ac70f0Sopenharmony_ci/* 2d5ac70f0Sopenharmony_ci Copyright(c) 2014-2015 Intel Corporation 3d5ac70f0Sopenharmony_ci All rights reserved. 4d5ac70f0Sopenharmony_ci 5d5ac70f0Sopenharmony_ci This library is free software; you can redistribute it and/or modify 6d5ac70f0Sopenharmony_ci it under the terms of the GNU Lesser General Public License as 7d5ac70f0Sopenharmony_ci published by the Free Software Foundation; either version 2.1 of 8d5ac70f0Sopenharmony_ci the License, or (at your option) any later version. 9d5ac70f0Sopenharmony_ci 10d5ac70f0Sopenharmony_ci This program is distributed in the hope that it will be useful, 11d5ac70f0Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 12d5ac70f0Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13d5ac70f0Sopenharmony_ci GNU Lesser General Public License for more details. 14d5ac70f0Sopenharmony_ci 15d5ac70f0Sopenharmony_ci Authors: Mengdong Lin <mengdong.lin@intel.com> 16d5ac70f0Sopenharmony_ci Yao Jin <yao.jin@intel.com> 17d5ac70f0Sopenharmony_ci Liam Girdwood <liam.r.girdwood@linux.intel.com> 18d5ac70f0Sopenharmony_ci*/ 19d5ac70f0Sopenharmony_ci 20d5ac70f0Sopenharmony_ci#include "tplg_local.h" 21d5ac70f0Sopenharmony_ci 22d5ac70f0Sopenharmony_ci/* mapping of channel text names to types */ 23d5ac70f0Sopenharmony_cistatic const struct map_elem channel_map[] = { 24d5ac70f0Sopenharmony_ci {"mono", SNDRV_CHMAP_MONO}, /* mono stream */ 25d5ac70f0Sopenharmony_ci {"fl", SNDRV_CHMAP_FL}, /* front left */ 26d5ac70f0Sopenharmony_ci {"fr", SNDRV_CHMAP_FR}, /* front right */ 27d5ac70f0Sopenharmony_ci {"rl", SNDRV_CHMAP_RL}, /* rear left */ 28d5ac70f0Sopenharmony_ci {"rr", SNDRV_CHMAP_RR}, /* rear right */ 29d5ac70f0Sopenharmony_ci {"fc", SNDRV_CHMAP_FC}, /* front center */ 30d5ac70f0Sopenharmony_ci {"lfe", SNDRV_CHMAP_LFE}, /* LFE */ 31d5ac70f0Sopenharmony_ci {"sl", SNDRV_CHMAP_SL}, /* side left */ 32d5ac70f0Sopenharmony_ci {"sr", SNDRV_CHMAP_SR}, /* side right */ 33d5ac70f0Sopenharmony_ci {"rc", SNDRV_CHMAP_RC}, /* rear center */ 34d5ac70f0Sopenharmony_ci {"flc", SNDRV_CHMAP_FLC}, /* front left center */ 35d5ac70f0Sopenharmony_ci {"frc", SNDRV_CHMAP_FRC}, /* front right center */ 36d5ac70f0Sopenharmony_ci {"rlc", SNDRV_CHMAP_RLC}, /* rear left center */ 37d5ac70f0Sopenharmony_ci {"rrc", SNDRV_CHMAP_RRC}, /* rear right center */ 38d5ac70f0Sopenharmony_ci {"flw", SNDRV_CHMAP_FLW}, /* front left wide */ 39d5ac70f0Sopenharmony_ci {"frw", SNDRV_CHMAP_FRW}, /* front right wide */ 40d5ac70f0Sopenharmony_ci {"flh", SNDRV_CHMAP_FLH}, /* front left high */ 41d5ac70f0Sopenharmony_ci {"fch", SNDRV_CHMAP_FCH}, /* front center high */ 42d5ac70f0Sopenharmony_ci {"frh", SNDRV_CHMAP_FRH}, /* front right high */ 43d5ac70f0Sopenharmony_ci {"tc", SNDRV_CHMAP_TC}, /* top center */ 44d5ac70f0Sopenharmony_ci {"tfl", SNDRV_CHMAP_TFL}, /* top front left */ 45d5ac70f0Sopenharmony_ci {"tfr", SNDRV_CHMAP_TFR}, /* top front right */ 46d5ac70f0Sopenharmony_ci {"tfc", SNDRV_CHMAP_TFC}, /* top front center */ 47d5ac70f0Sopenharmony_ci {"trl", SNDRV_CHMAP_TRL}, /* top rear left */ 48d5ac70f0Sopenharmony_ci {"trr", SNDRV_CHMAP_TRR}, /* top rear right */ 49d5ac70f0Sopenharmony_ci {"trc", SNDRV_CHMAP_TRC}, /* top rear center */ 50d5ac70f0Sopenharmony_ci {"tflc", SNDRV_CHMAP_TFLC}, /* top front left center */ 51d5ac70f0Sopenharmony_ci {"tfrc", SNDRV_CHMAP_TFRC}, /* top front right center */ 52d5ac70f0Sopenharmony_ci {"tsl", SNDRV_CHMAP_TSL}, /* top side left */ 53d5ac70f0Sopenharmony_ci {"tsr", SNDRV_CHMAP_TSR}, /* top side right */ 54d5ac70f0Sopenharmony_ci {"llfe", SNDRV_CHMAP_LLFE}, /* left LFE */ 55d5ac70f0Sopenharmony_ci {"rlfe", SNDRV_CHMAP_RLFE}, /* right LFE */ 56d5ac70f0Sopenharmony_ci {"bc", SNDRV_CHMAP_BC}, /* bottom center */ 57d5ac70f0Sopenharmony_ci {"blc", SNDRV_CHMAP_BLC}, /* bottom left center */ 58d5ac70f0Sopenharmony_ci {"brc", SNDRV_CHMAP_BRC}, /* bottom right center */ 59d5ac70f0Sopenharmony_ci}; 60d5ac70f0Sopenharmony_ci 61d5ac70f0Sopenharmony_ci 62d5ac70f0Sopenharmony_cistatic int lookup_channel(const char *c) 63d5ac70f0Sopenharmony_ci{ 64d5ac70f0Sopenharmony_ci unsigned int i; 65d5ac70f0Sopenharmony_ci 66d5ac70f0Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(channel_map); i++) { 67d5ac70f0Sopenharmony_ci if (strcasecmp(channel_map[i].name, c) == 0) { 68d5ac70f0Sopenharmony_ci return channel_map[i].id; 69d5ac70f0Sopenharmony_ci } 70d5ac70f0Sopenharmony_ci } 71d5ac70f0Sopenharmony_ci 72d5ac70f0Sopenharmony_ci return -EINVAL; 73d5ac70f0Sopenharmony_ci} 74d5ac70f0Sopenharmony_ci 75d5ac70f0Sopenharmony_ciconst char *tplg_channel_name(int type) 76d5ac70f0Sopenharmony_ci{ 77d5ac70f0Sopenharmony_ci unsigned int i; 78d5ac70f0Sopenharmony_ci 79d5ac70f0Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(channel_map); i++) { 80d5ac70f0Sopenharmony_ci if (channel_map[i].id == type) 81d5ac70f0Sopenharmony_ci return channel_map[i].name; 82d5ac70f0Sopenharmony_ci } 83d5ac70f0Sopenharmony_ci 84d5ac70f0Sopenharmony_ci return NULL; 85d5ac70f0Sopenharmony_ci} 86d5ac70f0Sopenharmony_ci 87d5ac70f0Sopenharmony_ci/* Parse a channel mapping. */ 88d5ac70f0Sopenharmony_ciint tplg_parse_channel(snd_tplg_t *tplg, snd_config_t *cfg, 89d5ac70f0Sopenharmony_ci void *private) 90d5ac70f0Sopenharmony_ci{ 91d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 92d5ac70f0Sopenharmony_ci snd_config_t *n; 93d5ac70f0Sopenharmony_ci struct snd_soc_tplg_channel *channel = private; 94d5ac70f0Sopenharmony_ci const char *id; 95d5ac70f0Sopenharmony_ci int channel_id, value; 96d5ac70f0Sopenharmony_ci 97d5ac70f0Sopenharmony_ci if (tplg->channel_idx >= SND_SOC_TPLG_MAX_CHAN) 98d5ac70f0Sopenharmony_ci return -EINVAL; 99d5ac70f0Sopenharmony_ci 100d5ac70f0Sopenharmony_ci channel += tplg->channel_idx; 101d5ac70f0Sopenharmony_ci snd_config_get_id(cfg, &id); 102d5ac70f0Sopenharmony_ci tplg_dbg("\tChannel %s at index %d", id, tplg->channel_idx); 103d5ac70f0Sopenharmony_ci 104d5ac70f0Sopenharmony_ci channel_id = lookup_channel(id); 105d5ac70f0Sopenharmony_ci if (channel_id < 0) { 106d5ac70f0Sopenharmony_ci SNDERR("invalid channel %s", id); 107d5ac70f0Sopenharmony_ci return -EINVAL; 108d5ac70f0Sopenharmony_ci } 109d5ac70f0Sopenharmony_ci 110d5ac70f0Sopenharmony_ci channel->id = channel_id; 111d5ac70f0Sopenharmony_ci channel->size = sizeof(*channel); 112d5ac70f0Sopenharmony_ci tplg_dbg("\tChan %s = %d", id, channel->id); 113d5ac70f0Sopenharmony_ci 114d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, cfg) { 115d5ac70f0Sopenharmony_ci 116d5ac70f0Sopenharmony_ci n = snd_config_iterator_entry(i); 117d5ac70f0Sopenharmony_ci 118d5ac70f0Sopenharmony_ci /* get id */ 119d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 120d5ac70f0Sopenharmony_ci continue; 121d5ac70f0Sopenharmony_ci 122d5ac70f0Sopenharmony_ci /* get value */ 123d5ac70f0Sopenharmony_ci if (tplg_get_integer(n, &value, 0) < 0) 124d5ac70f0Sopenharmony_ci continue; 125d5ac70f0Sopenharmony_ci 126d5ac70f0Sopenharmony_ci if (strcmp(id, "reg") == 0) 127d5ac70f0Sopenharmony_ci channel->reg = value; 128d5ac70f0Sopenharmony_ci else if (strcmp(id, "shift") == 0) 129d5ac70f0Sopenharmony_ci channel->shift = value; 130d5ac70f0Sopenharmony_ci 131d5ac70f0Sopenharmony_ci tplg_dbg("\t\t%s = %d", id, value); 132d5ac70f0Sopenharmony_ci } 133d5ac70f0Sopenharmony_ci 134d5ac70f0Sopenharmony_ci tplg->channel_idx++; 135d5ac70f0Sopenharmony_ci return 0; 136d5ac70f0Sopenharmony_ci} 137d5ac70f0Sopenharmony_ci 138d5ac70f0Sopenharmony_ciint tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED, 139d5ac70f0Sopenharmony_ci struct snd_soc_tplg_channel *channel, 140d5ac70f0Sopenharmony_ci unsigned int count, struct tplg_buf *dst, 141d5ac70f0Sopenharmony_ci const char *pfx) 142d5ac70f0Sopenharmony_ci{ 143d5ac70f0Sopenharmony_ci struct snd_soc_tplg_channel *c; 144d5ac70f0Sopenharmony_ci const char *s; 145d5ac70f0Sopenharmony_ci unsigned int index; 146d5ac70f0Sopenharmony_ci int err; 147d5ac70f0Sopenharmony_ci 148d5ac70f0Sopenharmony_ci if (count == 0) 149d5ac70f0Sopenharmony_ci return 0; 150d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "channel {\n"); 151d5ac70f0Sopenharmony_ci for (index = 0; err >= 0 && index < count; index++) { 152d5ac70f0Sopenharmony_ci c = channel + index; 153d5ac70f0Sopenharmony_ci s = tplg_channel_name(c->id); 154d5ac70f0Sopenharmony_ci if (s == NULL) 155d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "\t%u", c->id); 156d5ac70f0Sopenharmony_ci else 157d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "\t%s", s); 158d5ac70f0Sopenharmony_ci if (err >= 0) 159d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, NULL, " {\n"); 160d5ac70f0Sopenharmony_ci if (err >= 0) 161d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "\t\treg %d\n", c->reg); 162d5ac70f0Sopenharmony_ci if (err >= 0 && c->shift > 0) 163d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "\t\tshift %u\n", c->shift); 164d5ac70f0Sopenharmony_ci if (err >= 0) 165d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "\t}\n"); 166d5ac70f0Sopenharmony_ci } 167d5ac70f0Sopenharmony_ci if (err >= 0) 168d5ac70f0Sopenharmony_ci err = tplg_save_printf(dst, pfx, "}\n"); 169d5ac70f0Sopenharmony_ci return err; 170d5ac70f0Sopenharmony_ci} 171