From 6b4d775b9752031c9536dc7c19de72c5289bfd48 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Sun, 6 Nov 2016 13:13:46 +0800 Subject: topology: Parse HW configurations of physical DAI links defined by C API Add HW configurations to C API template of physical link configuration. Signed-off-by: Mengdong Lin Signed-off-by: Takashi Iwai --- include/topology.h | 33 +++++++++++++++++++++++++++++- src/topology/elem.c | 1 + src/topology/parser.c | 1 + src/topology/pcm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 84 insertions(+), 7 deletions(-) diff --git a/include/topology.h b/include/topology.h index 1fbaeb80..0978ccf1 100644 --- a/include/topology.h +++ b/include/topology.h @@ -927,6 +927,33 @@ struct snd_tplg_pcm_template { struct snd_tplg_stream_template stream[0]; /*!< supported configs */ }; + /** \struct snd_tplg_hw_config_template + * \brief Template type to describe a physical link runtime supported + * hardware config, i.e. hardware audio formats. + */ +struct snd_tplg_hw_config_template { + int id; /* unique ID - - used to match */ + unsigned int fmt; /* SND_SOC_DAI_FORMAT_ format value */ + unsigned char clock_gated; /* 1 if clock can be gated to save power */ + unsigned char invert_bclk; /* 1 for inverted BCLK, 0 for normal */ + unsigned char invert_fsync; /* 1 for inverted frame clock, 0 for normal */ + unsigned char bclk_master; /* 1 for master of BCLK, 0 for slave */ + unsigned char fsync_master; /* 1 for master of FSYNC, 0 for slave */ + unsigned char mclk_direction; /* 0 for input, 1 for output */ + unsigned short reserved; /* for 32bit alignment */ + unsigned int mclk_rate; /* MCLK or SYSCLK freqency in Hz */ + unsigned int bclk_rate; /* BCLK freqency in Hz */ + unsigned int fsync_rate; /* frame clock in Hz */ + unsigned int tdm_slots; /* number of TDM slots in use */ + unsigned int tdm_slot_width; /* width in bits for each slot */ + unsigned int tx_slots; /* bit mask for active Tx slots */ + unsigned int rx_slots; /* bit mask for active Rx slots */ + unsigned int tx_channels; /* number of Tx channels */ + unsigned int *tx_chanmap; /* array of slot number */ + unsigned int rx_channels; /* number of Rx channels */ + unsigned int *rx_chanmap; /* array of slot number */ +}; + /** \struct snd_tplg_link_template * \brief Template type for BE and CC DAI Links. */ @@ -934,7 +961,11 @@ struct snd_tplg_link_template { const char *name; /*!< link name */ int id; /*!< unique ID - used to match with existing BE and CC links */ int num_streams; /*!< number of configs */ - struct snd_tplg_stream_template stream[0]; /*!< supported configs */ + struct snd_tplg_stream_template *stream; /*!< supported configs */ + + struct snd_tplg_hw_config_template *hw_config; /*!< supported HW configs */ + int num_hw_configs; /* number of hw configs */ + int default_hw_config_id; /* default hw config ID for init */ }; /** \struct snd_tplg_obj_template diff --git a/src/topology/elem.c b/src/topology/elem.c index 724bf262..f7ff0706 100644 --- a/src/topology/elem.c +++ b/src/topology/elem.c @@ -193,6 +193,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, obj_size = sizeof(struct snd_soc_tplg_pcm); break; case SND_TPLG_TYPE_BE: + case SND_TPLG_TYPE_LINK: list_add_tail(&elem->list, &tplg->be_list); obj_size = sizeof(struct snd_soc_tplg_link_config); break; diff --git a/src/topology/parser.c b/src/topology/parser.c index ed5da877..238943c3 100644 --- a/src/topology/parser.c +++ b/src/topology/parser.c @@ -348,6 +348,7 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) return tplg_add_graph_object(tplg, t); case SND_TPLG_TYPE_PCM: return tplg_add_pcm_object(tplg, t); + case SND_TPLG_TYPE_LINK: case SND_TPLG_TYPE_BE: case SND_TPLG_TYPE_CC: return tplg_add_link_object(tplg, t); diff --git a/src/topology/pcm.c b/src/topology/pcm.c index 96a64e7e..7b67d918 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -168,7 +168,7 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem) return 0; } -/* build BE/CC DAI link configurations */ +/* build physical DAI link configurations */ int tplg_build_links(snd_tplg_t *tplg, unsigned int type) { struct list_head *base, *pos; @@ -176,6 +176,7 @@ int tplg_build_links(snd_tplg_t *tplg, unsigned int type) int err = 0; switch (type) { + case SND_TPLG_TYPE_LINK: case SND_TPLG_TYPE_BE: base = &tplg->be_list; break; @@ -189,11 +190,6 @@ int tplg_build_links(snd_tplg_t *tplg, unsigned int type) list_for_each(pos, base) { elem = list_entry(pos, struct tplg_elem, list); - if (elem->type != type) { - SNDERR("error: invalid elem '%s'\n", elem->id); - return -EINVAL; - } - err = build_link(tplg, elem); if (err < 0) return err; @@ -741,6 +737,47 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) return 0; } +/* Set link HW config from C API template */ +static int set_link_hw_config(struct snd_soc_tplg_hw_config *cfg, + struct snd_tplg_hw_config_template *tpl) +{ + int i; + + cfg->size = sizeof(*cfg); + cfg->id = tpl->id; + + cfg->fmt = tpl->fmt; + cfg->clock_gated = tpl->clock_gated; + cfg->invert_bclk = tpl->invert_bclk; + cfg->invert_fsync = tpl->invert_fsync; + cfg->bclk_master = tpl->bclk_master; + cfg->fsync_master = tpl->fsync_master; + cfg->mclk_direction = tpl->mclk_direction; + cfg->reserved = tpl->reserved; + cfg->mclk_rate = tpl->mclk_rate; + cfg->bclk_rate = tpl->bclk_rate; + cfg->fsync_rate = tpl->fsync_rate; + + cfg->tdm_slots = tpl->tdm_slots; + cfg->tdm_slot_width = tpl->tdm_slot_width; + cfg->tx_slots = tpl->tx_slots; + cfg->rx_slots = tpl->rx_slots; + + if (cfg->tx_channels > SND_SOC_TPLG_MAX_CHAN + || cfg->rx_channels > SND_SOC_TPLG_MAX_CHAN) + return -EINVAL; + + cfg->tx_channels = tpl->tx_channels; + for (i = 0; i < cfg->tx_channels; i++) + cfg->tx_chanmap[i] = tpl->tx_chanmap[i]; + + cfg->rx_channels = tpl->rx_channels; + for (i = 0; i < cfg->rx_channels; i++) + cfg->rx_chanmap[i] = tpl->rx_chanmap[i]; + + return 0; +} + /* Add a physical DAI link element from C API */ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) { @@ -771,5 +808,12 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) for (i = 0; i < link->num_streams; i++) tplg_add_stream_object(&link->stream[i], &link_tpl->stream[i]); + /* HW configs */ + if (link_tpl->num_hw_configs > SND_SOC_TPLG_HW_CONFIG_MAX) + return -EINVAL; + link->num_hw_configs = link_tpl->num_hw_configs; + link->default_hw_config_id = link_tpl->default_hw_config_id; + for (i = 0; i < link->num_hw_configs; i++) + set_link_hw_config(&link->hw_config[i], &link_tpl->hw_config[i]); return 0; } -- cgit v1.2.1