mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-26 01:40:07 -05:00
topology: add snd_tplg_save()
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
4a0efdc873
commit
aa1bac2d04
14 changed files with 2165 additions and 260 deletions
|
|
@ -345,6 +345,13 @@ static int get_rate_value(const char* name)
|
|||
return SND_PCM_RATE_UNKNOWN;
|
||||
}
|
||||
|
||||
static const char *get_rate_name(int rate)
|
||||
{
|
||||
if (rate >= 0 && rate <= SND_PCM_RATE_LAST)
|
||||
return snd_pcm_rate_names[rate];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int split_rate(struct snd_soc_tplg_stream_caps *caps, char *str)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
|
@ -527,6 +534,80 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* save stream caps */
|
||||
int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_stream_caps *sc = elem->stream_caps;
|
||||
const char *s;
|
||||
unsigned int i;
|
||||
int err, first;
|
||||
|
||||
err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
|
||||
if (err >= 0 && sc->formats) {
|
||||
err = tplg_save_printf(dst, pfx, "\tformats '");
|
||||
first = 1;
|
||||
for (i = 0; err >= 0 && i < SND_PCM_FORMAT_LAST; i++) {
|
||||
if (sc->formats & (1ULL << i)) {
|
||||
s = snd_pcm_format_name(i);
|
||||
err = tplg_save_printf(dst, NULL, "%s%s",
|
||||
!first ? ", " : "", s);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, NULL, "'\n");
|
||||
}
|
||||
if (err >= 0 && sc->rates) {
|
||||
err = tplg_save_printf(dst, pfx, "\trates '");
|
||||
first = 1;
|
||||
for (i = 0; err >= 0 && i < SND_PCM_RATE_LAST; i++) {
|
||||
if (sc->rates & (1ULL << i)) {
|
||||
s = get_rate_name(i);
|
||||
err = tplg_save_printf(dst, NULL, "%s%s",
|
||||
!first ? ", " : "", s);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, NULL, "'\n");
|
||||
}
|
||||
if (err >= 0 && sc->rate_min)
|
||||
err = tplg_save_printf(dst, pfx, "\trate_min %u\n",
|
||||
sc->rate_min);
|
||||
if (err >= 0 && sc->rate_max)
|
||||
err = tplg_save_printf(dst, pfx, "\trate_max %u\n",
|
||||
sc->rate_max);
|
||||
if (err >= 0 && sc->channels_min)
|
||||
err = tplg_save_printf(dst, pfx, "\tchannels_min %u\n",
|
||||
sc->channels_min);
|
||||
if (err >= 0 && sc->channels_max)
|
||||
err = tplg_save_printf(dst, pfx, "\tchannels_max %u\n",
|
||||
sc->channels_max);
|
||||
if (err >= 0 && sc->periods_min)
|
||||
err = tplg_save_printf(dst, pfx, "\tperiods_min %u\n",
|
||||
sc->periods_min);
|
||||
if (err >= 0 && sc->periods_max)
|
||||
err = tplg_save_printf(dst, pfx, "\tperiods_max %u\n",
|
||||
sc->periods_max);
|
||||
if (err >= 0 && sc->period_size_min)
|
||||
err = tplg_save_printf(dst, pfx, "\tperiod_size_min %u\n",
|
||||
sc->period_size_min);
|
||||
if (err >= 0 && sc->period_size_max)
|
||||
err = tplg_save_printf(dst, pfx, "\tperiod_size_max %u\n",
|
||||
sc->period_size_max);
|
||||
if (err >= 0 && sc->buffer_size_min)
|
||||
err = tplg_save_printf(dst, pfx, "\tbuffer_size_min %u\n",
|
||||
sc->buffer_size_min);
|
||||
if (err >= 0 && sc->buffer_size_max)
|
||||
err = tplg_save_printf(dst, pfx, "\tbuffer_size_max %u\n",
|
||||
sc->buffer_size_max);
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse the caps and config of a pcm stream */
|
||||
static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
snd_config_t *cfg, void *private)
|
||||
|
|
@ -598,6 +679,61 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Save the caps and config of a pcm stream */
|
||||
int tplg_save_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
static const char *stream_ids[2] = {
|
||||
"playback",
|
||||
"capture"
|
||||
};
|
||||
static unsigned int stream_types[2] = {
|
||||
SND_SOC_TPLG_STREAM_PLAYBACK,
|
||||
SND_SOC_TPLG_STREAM_CAPTURE
|
||||
};
|
||||
struct snd_soc_tplg_stream_caps *caps;
|
||||
unsigned int streams[2], stream;
|
||||
const char *s;
|
||||
int err;
|
||||
|
||||
switch (elem->type) {
|
||||
case SND_TPLG_TYPE_PCM:
|
||||
streams[0] = elem->pcm->playback;
|
||||
streams[1] = elem->pcm->capture;
|
||||
caps = elem->pcm->caps;
|
||||
break;
|
||||
case SND_TPLG_TYPE_DAI:
|
||||
streams[0] = elem->dai->playback;
|
||||
streams[1] = elem->dai->capture;
|
||||
caps = elem->dai->caps;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (stream = 0; stream < 2; stream++) {
|
||||
if (streams[stream] == 0)
|
||||
continue;
|
||||
if (!caps)
|
||||
continue;
|
||||
s = caps[stream_types[stream]].name;
|
||||
if (s[0] == '\0')
|
||||
continue;
|
||||
err = tplg_save_printf(dst, pfx, "pcm.%s {\n", stream_ids[stream]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = tplg_save_printf(dst, pfx, "\tcapabilities '%s'\n", s);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse name and id of a front-end DAI (ie. cpu dai of a FE DAI link) */
|
||||
static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
snd_config_t *cfg, void *private)
|
||||
|
|
@ -633,6 +769,19 @@ static int tplg_parse_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Save the caps and config of a pcm stream */
|
||||
int tplg_save_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_pcm *pcm = elem->pcm;
|
||||
int err = 0;
|
||||
|
||||
if (pcm->dai_id > 0)
|
||||
err = tplg_save_printf(dst, pfx, "dai.0.id %u\n", pcm->dai_id);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* parse a flag bit of the given mask */
|
||||
static int parse_flag(snd_config_t *n, unsigned int mask_in,
|
||||
unsigned int *mask, unsigned int *flags)
|
||||
|
|
@ -652,6 +801,32 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int save_flags(unsigned int flags, unsigned int mask,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
static unsigned int flag_masks[3] = {
|
||||
SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES,
|
||||
SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS,
|
||||
SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS,
|
||||
};
|
||||
static const char *flag_ids[3] = {
|
||||
"symmetric_rates",
|
||||
"symmetric_channels",
|
||||
"symmetric_sample_bits",
|
||||
};
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; err >= 0 && i < ARRAY_SIZE(flag_masks); i++) {
|
||||
if (mask & flag_masks[i]) {
|
||||
unsigned int v = (flags & flag_masks[i]) ? 1 : 0;
|
||||
err = tplg_save_printf(dst, pfx, "%s %u\n",
|
||||
flag_ids[i], v);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse PCM (for front end DAI & DAI link) in text conf file */
|
||||
int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
void *private ATTRIBUTE_UNUSED)
|
||||
|
|
@ -748,7 +923,7 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
|
|||
|
||||
/* private data */
|
||||
if (strcmp(id, "data") == 0) {
|
||||
err = tplg_parse_data_refs(n, elem);
|
||||
err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
|
||||
if (err < 0)
|
||||
return err;
|
||||
continue;
|
||||
|
|
@ -758,6 +933,40 @@ int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* save PCM */
|
||||
int tplg_save_pcm(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_pcm *pcm = elem->pcm;
|
||||
char pfx2[16];
|
||||
int err;
|
||||
|
||||
snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
|
||||
err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
|
||||
if (err >= 0 && elem->index)
|
||||
err = tplg_save_printf(dst, pfx, "\tindex %u\n",
|
||||
elem->index);
|
||||
if (err >= 0 && pcm->pcm_id)
|
||||
err = tplg_save_printf(dst, pfx, "\tid %u\n",
|
||||
pcm->pcm_id);
|
||||
if (err >= 0 && pcm->compress)
|
||||
err = tplg_save_printf(dst, pfx, "\tcompress 1\n");
|
||||
snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
|
||||
if (err >= 0)
|
||||
err = tplg_save_fe_dai(tplg, elem, dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = tplg_save_streams(tplg, elem, dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = save_flags(pcm->flags, pcm->flag_mask, dst, pfx);
|
||||
if (err >= 0)
|
||||
err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
|
||||
"data", dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse physical DAI */
|
||||
int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
void *private ATTRIBUTE_UNUSED)
|
||||
|
|
@ -766,7 +975,7 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
|
|||
struct tplg_elem *elem;
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *n;
|
||||
const char *id, *val = NULL;
|
||||
const char *id;
|
||||
int err;
|
||||
|
||||
elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DAI);
|
||||
|
|
@ -851,11 +1060,9 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
|
|||
|
||||
/* private data */
|
||||
if (strcmp(id, "data") == 0) {
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
tplg_ref_add(elem, SND_TPLG_TYPE_DATA, val);
|
||||
tplg_dbg("\t%s: %s\n", id, val);
|
||||
err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
|
||||
if (err < 0)
|
||||
return err;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -863,55 +1070,55 @@ int tplg_parse_dai(snd_tplg_t *tplg, snd_config_t *cfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* save DAI */
|
||||
int tplg_save_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_dai *dai = elem->dai;
|
||||
char pfx2[16];
|
||||
int err;
|
||||
|
||||
if (!dai)
|
||||
return 0;
|
||||
snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
|
||||
err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
|
||||
if (err >= 0 && elem->index)
|
||||
err = tplg_save_printf(dst, pfx, "\tindex %u\n",
|
||||
elem->index);
|
||||
if (err >= 0 && dai->dai_id)
|
||||
err = tplg_save_printf(dst, pfx, "\tid %u\n",
|
||||
dai->dai_id);
|
||||
if (err >= 0 && dai->playback)
|
||||
err = tplg_save_printf(dst, pfx, "\tplayback %u\n",
|
||||
dai->playback);
|
||||
if (err >= 0 && dai->capture)
|
||||
err = tplg_save_printf(dst, pfx, "\tcapture %u\n",
|
||||
dai->capture);
|
||||
if (err >= 0)
|
||||
err = tplg_save_streams(tplg, elem, dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = save_flags(dai->flags, dai->flag_mask, dst, pfx);
|
||||
if (err >= 0)
|
||||
err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
|
||||
"data", dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* parse physical link runtime supported HW configs in text conf file */
|
||||
static int parse_hw_config_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
snd_config_t *cfg,
|
||||
struct tplg_elem *elem)
|
||||
{
|
||||
struct snd_soc_tplg_link_config *link = elem->link;
|
||||
snd_config_type_t type;
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *n;
|
||||
const char *id, *val = NULL;
|
||||
|
||||
if (snd_config_get_id(cfg, &id) < 0)
|
||||
return -EINVAL;
|
||||
type = snd_config_get_type(cfg);
|
||||
|
||||
/* refer to a single HW config */
|
||||
if (type == SND_CONFIG_TYPE_STRING) {
|
||||
if (snd_config_get_string(cfg, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
link->num_hw_configs = 1;
|
||||
return tplg_ref_add(elem, SND_TPLG_TYPE_HW_CONFIG, val);
|
||||
}
|
||||
|
||||
if (type != SND_CONFIG_TYPE_COMPOUND) {
|
||||
SNDERR("error: compound type expected for %s", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* refer to a list of HW configs */
|
||||
snd_config_for_each(i, next, cfg) {
|
||||
const char *val;
|
||||
int err;
|
||||
|
||||
n = snd_config_iterator_entry(i);
|
||||
if (snd_config_get_string(n, &val) < 0)
|
||||
continue;
|
||||
|
||||
if (link->num_hw_configs >= SND_SOC_TPLG_HW_CONFIG_MAX) {
|
||||
SNDERR("error: exceed max hw configs for link %s", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
link->num_hw_configs++;
|
||||
err = tplg_ref_add(elem, SND_TPLG_TYPE_HW_CONFIG, val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
int err;
|
||||
|
||||
err = tplg_parse_refs(cfg, elem, SND_TPLG_TYPE_HW_CONFIG);
|
||||
if (err < 0)
|
||||
return err;
|
||||
link->num_hw_configs = err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1007,7 +1214,7 @@ int tplg_parse_link(snd_tplg_t *tplg,
|
|||
|
||||
/* private data */
|
||||
if (strcmp(id, "data") == 0) {
|
||||
err = tplg_parse_data_refs(n, elem);
|
||||
err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
|
||||
if (err < 0)
|
||||
return err;
|
||||
continue;
|
||||
|
|
@ -1017,6 +1224,44 @@ int tplg_parse_link(snd_tplg_t *tplg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* save physical link */
|
||||
int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_link_config *link = elem->link;
|
||||
char pfx2[16];
|
||||
int err;
|
||||
|
||||
if (!link)
|
||||
return 0;
|
||||
snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
|
||||
err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
|
||||
if (err >= 0 && elem->index)
|
||||
err = tplg_save_printf(dst, pfx, "\tindex %u\n",
|
||||
elem->index);
|
||||
if (err >= 0 && link->id)
|
||||
err = tplg_save_printf(dst, pfx, "\tid %u\n",
|
||||
link->id);
|
||||
if (err >= 0 && link->stream_name[0])
|
||||
err = tplg_save_printf(dst, pfx, "\tstream_name '%s'\n",
|
||||
link->stream_name);
|
||||
if (err >= 0 && link->default_hw_config_id)
|
||||
err = tplg_save_printf(dst, pfx, "\tdefault_hw_conf_id %u\n",
|
||||
link->default_hw_config_id);
|
||||
if (err >= 0)
|
||||
err = save_flags(link->flags, link->flag_mask, dst, pfx);
|
||||
if (err >= 0)
|
||||
err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_HW_CONFIG,
|
||||
"hw_configs", dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_DATA,
|
||||
"data", dst, pfx2);
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Parse cc */
|
||||
int tplg_parse_cc(snd_tplg_t *tplg,
|
||||
snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)
|
||||
|
|
@ -1059,36 +1304,95 @@ int tplg_parse_cc(snd_tplg_t *tplg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* save CC */
|
||||
int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_link_config *link = elem->link;
|
||||
char pfx2[16];
|
||||
int err;
|
||||
|
||||
if (!link)
|
||||
return 0;
|
||||
snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
|
||||
err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
|
||||
if (err >= 0 && elem->index)
|
||||
err = tplg_save_printf(dst, pfx, "\tindex %u\n",
|
||||
elem->index);
|
||||
if (err >= 0 && link->id)
|
||||
err = tplg_save_printf(dst, pfx, "\tid %u\n",
|
||||
link->id);
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
struct audio_hw_format {
|
||||
unsigned int type;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static struct audio_hw_format audio_hw_formats[] = {
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_I2S,
|
||||
.name = "I2S",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_RIGHT_J,
|
||||
.name = "RIGHT_J",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_LEFT_J,
|
||||
.name = "LEFT_J",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_DSP_A,
|
||||
.name = "DSP_A",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_DSP_B,
|
||||
.name = "DSP_B",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_AC97,
|
||||
.name = "AC97",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_AC97,
|
||||
.name = "AC97",
|
||||
},
|
||||
{
|
||||
.type = SND_SOC_DAI_FORMAT_PDM,
|
||||
.name = "PDM",
|
||||
},
|
||||
};
|
||||
|
||||
static int get_audio_hw_format(const char *val)
|
||||
{
|
||||
if (!strlen(val))
|
||||
unsigned int i;
|
||||
|
||||
if (val[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(val, "I2S"))
|
||||
return SND_SOC_DAI_FORMAT_I2S;
|
||||
|
||||
if (!strcmp(val, "RIGHT_J"))
|
||||
return SND_SOC_DAI_FORMAT_RIGHT_J;
|
||||
|
||||
if (!strcmp(val, "LEFT_J"))
|
||||
return SND_SOC_DAI_FORMAT_LEFT_J;
|
||||
|
||||
if (!strcmp(val, "DSP_A"))
|
||||
return SND_SOC_DAI_FORMAT_DSP_A;
|
||||
|
||||
if (!strcmp(val, "DSP_B"))
|
||||
return SND_SOC_DAI_FORMAT_DSP_B;
|
||||
|
||||
if (!strcmp(val, "AC97"))
|
||||
return SND_SOC_DAI_FORMAT_AC97;
|
||||
|
||||
if (!strcmp(val, "PDM"))
|
||||
return SND_SOC_DAI_FORMAT_PDM;
|
||||
for (i = 0; i < ARRAY_SIZE(audio_hw_formats); i++)
|
||||
if (strcasecmp(audio_hw_formats[i].name, val) == 0)
|
||||
return audio_hw_formats[i].type;
|
||||
|
||||
SNDERR("error: invalid audio HW format %s\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const char *get_audio_hw_format_name(unsigned int type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(audio_hw_formats); i++)
|
||||
if (audio_hw_formats[i].type == type)
|
||||
return audio_hw_formats[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
|
||||
void *private ATTRIBUTE_UNUSED)
|
||||
{
|
||||
|
|
@ -1299,6 +1603,71 @@ int tplg_parse_hw_config(snd_tplg_t *tplg, snd_config_t *cfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* save hw config */
|
||||
int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
|
||||
struct tplg_elem *elem,
|
||||
char **dst, const char *pfx)
|
||||
{
|
||||
struct snd_soc_tplg_hw_config *hc = elem->hw_cfg;
|
||||
int err;
|
||||
|
||||
err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
|
||||
if (err >= 0 && hc->id)
|
||||
err = tplg_save_printf(dst, pfx, "\tid %u\n",
|
||||
hc->id);
|
||||
if (err >= 0 && hc->fmt)
|
||||
err = tplg_save_printf(dst, pfx, "\tformat '%s'\n",
|
||||
get_audio_hw_format_name(hc->fmt));
|
||||
if (err >= 0 && hc->bclk_master)
|
||||
err = tplg_save_printf(dst, pfx, "\tbclk '%s'\n",
|
||||
hc->bclk_master == SND_SOC_TPLG_BCLK_CS ?
|
||||
"codec_slave" : "codec_master");
|
||||
if (err >= 0 && hc->bclk_rate)
|
||||
err = tplg_save_printf(dst, pfx, "\tbclk_freq %u\n",
|
||||
hc->bclk_rate);
|
||||
if (err >= 0 && hc->invert_bclk)
|
||||
err = tplg_save_printf(dst, pfx, "\tbclk_invert 1\n");
|
||||
if (err >= 0 && hc->fsync_master)
|
||||
err = tplg_save_printf(dst, pfx, "\tfsync_master '%s'\n",
|
||||
hc->fsync_master == SND_SOC_TPLG_FSYNC_CS ?
|
||||
"codec_slave" : "codec_master");
|
||||
if (err >= 0 && hc->fsync_rate)
|
||||
err = tplg_save_printf(dst, pfx, "\tfsync_freq %u\n",
|
||||
hc->fsync_rate);
|
||||
if (err >= 0 && hc->invert_fsync)
|
||||
err = tplg_save_printf(dst, pfx, "\tfsync_invert 1\n");
|
||||
if (err >= 0 && hc->mclk_rate)
|
||||
err = tplg_save_printf(dst, pfx, "\tmclk_freq %u\n",
|
||||
hc->mclk_rate);
|
||||
if (err >= 0 && hc->mclk_direction)
|
||||
err = tplg_save_printf(dst, pfx, "\tmclk '%s'\n",
|
||||
hc->mclk_direction == SND_SOC_TPLG_MCLK_CI ?
|
||||
"codec_mclk_in" : "codec_mclk_out");
|
||||
if (err >= 0 && hc->clock_gated)
|
||||
err = tplg_save_printf(dst, pfx, "\tpm_gate_clocks 1\n");
|
||||
if (err >= 0 && hc->tdm_slots)
|
||||
err = tplg_save_printf(dst, pfx, "\ttdm_slots %u\n",
|
||||
hc->tdm_slots);
|
||||
if (err >= 0 && hc->tdm_slot_width)
|
||||
err = tplg_save_printf(dst, pfx, "\ttdm_slot_width %u\n",
|
||||
hc->tdm_slot_width);
|
||||
if (err >= 0 && hc->tx_slots)
|
||||
err = tplg_save_printf(dst, pfx, "\ttx_slots %u\n",
|
||||
hc->tx_slots);
|
||||
if (err >= 0 && hc->rx_slots)
|
||||
err = tplg_save_printf(dst, pfx, "\trx_slots %u\n",
|
||||
hc->rx_slots);
|
||||
if (err >= 0 && hc->tx_channels)
|
||||
err = tplg_save_printf(dst, pfx, "\ttx_channels %u\n",
|
||||
hc->tx_channels);
|
||||
if (err >= 0 && hc->rx_channels)
|
||||
err = tplg_save_printf(dst, pfx, "\trx_channels %u\n",
|
||||
hc->rx_channels);
|
||||
if (err >= 0)
|
||||
err = tplg_save_printf(dst, pfx, "}\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* copy stream object */
|
||||
static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm,
|
||||
struct snd_tplg_stream_template *strm_tpl)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue