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 <mengdong.lin@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Mengdong Lin 2016-11-06 13:13:46 +08:00 committed by Takashi Iwai
parent f5b275b24c
commit 6b4d775b97
4 changed files with 84 additions and 7 deletions

View file

@ -927,6 +927,33 @@ struct snd_tplg_pcm_template {
struct snd_tplg_stream_template stream[0]; /*!< supported configs */ 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 /** \struct snd_tplg_link_template
* \brief Template type for BE and CC DAI Links. * \brief Template type for BE and CC DAI Links.
*/ */
@ -934,7 +961,11 @@ struct snd_tplg_link_template {
const char *name; /*!< link name */ const char *name; /*!< link name */
int id; /*!< unique ID - used to match with existing BE and CC links */ int id; /*!< unique ID - used to match with existing BE and CC links */
int num_streams; /*!< number of configs */ 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 /** \struct snd_tplg_obj_template

View file

@ -193,6 +193,7 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,
obj_size = sizeof(struct snd_soc_tplg_pcm); obj_size = sizeof(struct snd_soc_tplg_pcm);
break; break;
case SND_TPLG_TYPE_BE: case SND_TPLG_TYPE_BE:
case SND_TPLG_TYPE_LINK:
list_add_tail(&elem->list, &tplg->be_list); list_add_tail(&elem->list, &tplg->be_list);
obj_size = sizeof(struct snd_soc_tplg_link_config); obj_size = sizeof(struct snd_soc_tplg_link_config);
break; break;

View file

@ -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); return tplg_add_graph_object(tplg, t);
case SND_TPLG_TYPE_PCM: case SND_TPLG_TYPE_PCM:
return tplg_add_pcm_object(tplg, t); return tplg_add_pcm_object(tplg, t);
case SND_TPLG_TYPE_LINK:
case SND_TPLG_TYPE_BE: case SND_TPLG_TYPE_BE:
case SND_TPLG_TYPE_CC: case SND_TPLG_TYPE_CC:
return tplg_add_link_object(tplg, t); return tplg_add_link_object(tplg, t);

View file

@ -168,7 +168,7 @@ static int build_link(snd_tplg_t *tplg, struct tplg_elem *elem)
return 0; return 0;
} }
/* build BE/CC DAI link configurations */ /* build physical DAI link configurations */
int tplg_build_links(snd_tplg_t *tplg, unsigned int type) int tplg_build_links(snd_tplg_t *tplg, unsigned int type)
{ {
struct list_head *base, *pos; struct list_head *base, *pos;
@ -176,6 +176,7 @@ int tplg_build_links(snd_tplg_t *tplg, unsigned int type)
int err = 0; int err = 0;
switch (type) { switch (type) {
case SND_TPLG_TYPE_LINK:
case SND_TPLG_TYPE_BE: case SND_TPLG_TYPE_BE:
base = &tplg->be_list; base = &tplg->be_list;
break; break;
@ -189,11 +190,6 @@ int tplg_build_links(snd_tplg_t *tplg, unsigned int type)
list_for_each(pos, base) { list_for_each(pos, base) {
elem = list_entry(pos, struct tplg_elem, list); 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); err = build_link(tplg, elem);
if (err < 0) if (err < 0)
return err; return err;
@ -741,6 +737,47 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
return 0; 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 */ /* Add a physical DAI link element from C API */
int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) 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++) for (i = 0; i < link->num_streams; i++)
tplg_add_stream_object(&link->stream[i], &link_tpl->stream[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; return 0;
} }