[alsa-devel] [PATCH 0/5] topology: Upgrade ABI to match kernel v4.8
From: Mengdong Lin mengdong.lin@linux.intel.com
Now the topology ABI version in kernel is 5, added types for BE (Backend) DAIs and sig_bits in stream caps. But the ABI version in alsa-lib is still 4, without above ABI update.
Since the kernel merge window is open and the remaining topology ABI update (v3 kernel patch series) cannot be accepted atm. So we use this series to fix the ABI mismatch between kernel v4.8 and user space, by adding types for BE DAIs and sig_bits to stream caps and pumping topolpgy ABI version to 5 as well.
This patch series also completes the support for BE DAIs.
Guneshwor Singh (3): topology: Parse BE DAIs in text conf file topology: Support configuring BE DAIs by C API topology: Export BE DAIs to the binary for kernel
Mengdong Lin (2): topology: ABI - Add the types for BE DAI topology: ABI - Add sig_bits to stream caps
include/sound/asoc.h | 35 ++++++- include/topology.h | 45 +++++++++ src/topology/builder.c | 11 +++ src/topology/data.c | 4 + src/topology/elem.c | 4 + src/topology/parser.c | 16 ++++ src/topology/pcm.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++ src/topology/tplg_local.h | 7 ++ 8 files changed, 358 insertions(+), 2 deletions(-)
From: Mengdong Lin mengdong.lin@linux.intel.com
Define the type and ABI struct for BE (Back End) DAIs. Add the number of BE DAIs to manifest, and add some reserved fields for future extensions. Kernel will use this ABI struct to configure existing BE DAIs registered by driver.
Pump the version number to 5.
Topology kernel driver will check size of ABI objects to detect version mismatch between user space and kernel.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/include/sound/asoc.h b/include/sound/asoc.h index abe49c5..2f88e83 100644 --- a/include/sound/asoc.h +++ b/include/sound/asoc.h @@ -74,7 +74,7 @@ #define SND_SOC_TPLG_NUM_TEXTS 16
/* ABI version */ -#define SND_SOC_TPLG_ABI_VERSION 0x4 +#define SND_SOC_TPLG_ABI_VERSION 0x5
/* Max size of TLV data */ #define SND_SOC_TPLG_TLV_SIZE 32 @@ -96,7 +96,8 @@ #define SND_SOC_TPLG_TYPE_CODEC_LINK 9 #define SND_SOC_TPLG_TYPE_BACKEND_LINK 10 #define SND_SOC_TPLG_TYPE_PDATA 11 -#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_PDATA +#define SND_SOC_TPLG_TYPE_BE_DAI 12 +#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_BE_DAI
/* vendor block IDs - please add new vendor types to end */ #define SND_SOC_TPLG_TYPE_VENDOR_FW 1000 @@ -115,6 +116,11 @@ #define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 #define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5
+/* BE DAI flags */ +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2) + /* * Block Header. * This header precedes all object and object arrays below. @@ -276,6 +282,8 @@ struct snd_soc_tplg_manifest { __le32 graph_elems; /* number of graph elements */ __le32 pcm_elems; /* number of PCM elements */ __le32 dai_link_elems; /* number of DAI link elements */ + __le32 be_dai_elems; /* number of BE DAI elements */ + __le32 reserved[20]; /* reserved for new ABI element types */ struct snd_soc_tplg_private priv; } __attribute__((packed));
@@ -441,4 +449,26 @@ struct snd_soc_tplg_link_config { struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ __le32 num_streams; /* number of streams */ } __attribute__((packed)); + +/* + * Describes SW/FW specific features of BE DAI. + * + * File block representation for BE DAI :- + * +-----------------------------------+-----+ + * | struct snd_soc_tplg_hdr | 1 | + * +-----------------------------------+-----+ + * | struct snd_soc_tplg_be_dai | N | + * +-----------------------------------+-----+ + */ +struct snd_soc_tplg_be_dai { + __le32 size; /* in bytes of this structure */ + char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; /* name - used to match */ + __le32 dai_id; /* unique ID - used to match */ + __le32 playback; /* supports playback mode */ + __le32 capture; /* supports capture mode */ + struct snd_soc_tplg_stream_caps caps[2]; /* playback and capture for DAI */ + __le32 flag_mask; /* bitmask of flags to configure */ + __le32 flags; /* SND_SOC_TPLG_DAI_FLGBIT_* */ + struct snd_soc_tplg_private priv; +} __attribute__((packed)); #endif
On Mon, Oct 03, 2016 at 11:03:50PM +0800, mengdong.lin@linux.intel.com wrote:
Pump the version number to 5.
So, we just had a user on IRC complaining that the last round of incompatible changes in v4.7 broke their laptop audio - they had a laptop that shipped with Linux and suddenly the topology file didn't work. I think that's an indication that at this point we have an ABI we need to maintain compatibility with rather than just break things. That doesn't explicitly affect this patch but does mean that the parsing code ought to cope which is likely to have some impact here.
Topology kernel driver will check size of ABI objects to detect version mismatch between user space and kernel.
The ABI wasn't explicitly reved which suggests that it's this that triggered the issue for the user.
+/* BE DAI flags */ +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
These don't seem specific to back ends, people can use topologies for DSPs on off-SoC devices which might also want to use these.
- __le32 be_dai_elems; /* number of BE DAI elements */
- __le32 reserved[20]; /* reserved for new ABI element types */
Thinking about the above I'm wondering if it doesn't make more sense to call these physical links rather than back ends - that term is going to be clearer to people who don't use DPCM.
On 10/06/2016 10:37 PM, Mark Brown wrote:
On Mon, Oct 03, 2016 at 11:03:50PM +0800, mengdong.lin@linux.intel.com wrote:
Pump the version number to 5.
So, we just had a user on IRC complaining that the last round of incompatible changes in v4.7 broke their laptop audio - they had a laptop that shipped with Linux and suddenly the topology file didn't work. I think that's an indication that at this point we have an ABI we need to maintain compatibility with rather than just break things. That doesn't explicitly affect this patch but does mean that the parsing code ought to cope which is likely to have some impact here.
Topology kernel driver will check size of ABI objects to detect version mismatch between user space and kernel.
The ABI wasn't explicitly reved which suggests that it's this that triggered the issue for the user.
Yes. Now if the kernel finds a mismatch of ABI object size, it will just return error and so old version of topology files cannot work. We'll try to support ABI version 4 and new versions in kernel. It seems topology have real users from version 4.
+/* BE DAI flags */ +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
These don't seem specific to back ends, people can use topologies for DSPs on off-SoC devices which might also want to use these.
Yes. Can we take them as generic flags for DAI and DAI links?
- __le32 be_dai_elems; /* number of BE DAI elements */
- __le32 reserved[20]; /* reserved for new ABI element types */
Thinking about the above I'm wondering if it doesn't make more sense to call these physical links rather than back ends - that term is going to be clearer to people who don't use DPCM.
May we call it a "phy_dai_elems", to indicate physical DAIs?
Now the ABI struct "snd_soc_tplg_be_dai" is already in kernel but no real users in user space. Can we rename it? Or add a new ABI struct?
Thanks Mengdong
On 10/06/2016 10:37 PM, Mark Brown wrote:
On Mon, Oct 03, 2016 at 11:03:50PM +0800, mengdong.lin@linux.intel.com wrote:
Pump the version number to 5.
So, we just had a user on IRC complaining that the last round of incompatible changes in v4.7 broke their laptop audio - they had a laptop that shipped with Linux and suddenly the topology file didn't work. I think that's an indication that at this point we have an ABI we need to maintain compatibility with rather than just break things. That doesn't explicitly affect this patch but does mean that the parsing code ought to cope which is likely to have some impact here.
Topology kernel driver will check size of ABI objects to detect version mismatch between user space and kernel.
The ABI wasn't explicitly reved which suggests that it's this that triggered the issue for the user.
I've submitted topology kernel patches v6 to solve the compatibility issue caused by ABI mismatch. Now the kernel can handle topology files generated by ABI v4, which is published by alsa-lib v1.1.0 in last November. Please review.
So we can hold on user space ABI updates until all kernel patches being reviewed and merged.
+/* BE DAI flags */ +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES (1 << 0) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS (1 << 1) +#define SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS (1 << 2)
These don't seem specific to back ends, people can use topologies for DSPs on off-SoC devices which might also want to use these.
'BE' is removed in the comments, in kernel side at first.
- __le32 be_dai_elems; /* number of BE DAI elements */
- __le32 reserved[20]; /* reserved for new ABI element types */
Thinking about the above I'm wondering if it doesn't make more sense to call these physical links rather than back ends - that term is going to be clearer to people who don't use DPCM.
"be_dai_elems" is renamed to "dai_elems" in kernel side at first, and this change is backward compatible.
Thanks Mengdong
From: Guneshwor Singh guneshwor.o.singh@intel.com
Add support for parsing BE (Back End) DAIs in the text configuration file. The syntax of BE DAIs is described in document in topology.h
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/include/topology.h b/include/topology.h index 0675b52..da45848 100644 --- a/include/topology.h +++ b/include/topology.h @@ -609,6 +609,33 @@ extern "C" { * } * </pre> * + * <h4>Back End DAI</h4> + * A BE (Back End) DAI is defined as a new section that can include a + * unique ID, playback and capture stream capabilities and optional flags. + * <br> Its PCM stream capablities are same as those for PCM objects, + * please refer to section 'PCM Capabilities'. + * + * <pre> + * SectionBEDAI."name" { + * + * index "1" # Index number + * + * id "0" # used for binding to the Backend DAI + * + * pcm."playback" { + * capabilities "capabilities1" # capabilities for playback + * } + * + * pcm."capture" { + * capabilities "capabilities2" # capabilities for capture + * } + * + * symmetric_rates "true" # optional flags + * symmetric_channels "true" + * symmetric_sample_bits "false" + * } + * </pre> + * * <h4>Manifest Private Data</h4> * Manfiest may have private data. Users need to define a manifest section * and add the references to 1 or multiple data sections. Please refer to @@ -644,6 +671,7 @@ enum snd_tplg_type { SND_TPLG_TYPE_PCM, /*!< PCM stream device */ SND_TPLG_TYPE_DAPM_WIDGET, /*!< DAPM widget */ SND_TPLG_TYPE_DAPM_GRAPH, /*!< DAPM graph elements */ + SND_TPLG_TYPE_BE_DAI, SND_TPLG_TYPE_BE, /*!< BE DAI link */ SND_TPLG_TYPE_CC, /*!< Hostless codec <-> codec link */ SND_TPLG_TYPE_MANIFEST, /*!< Topology manifest */ diff --git a/src/topology/data.c b/src/topology/data.c index 59bc970..4798086 100644 --- a/src/topology/data.c +++ b/src/topology/data.c @@ -46,6 +46,10 @@ struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem) priv = &elem->widget->priv; break;
+ case SND_TPLG_TYPE_BE_DAI: + priv = &elem->be_dai->priv; + break; + default: SNDERR("error: '%s': no support for private data for type %d\n", elem->id, elem->type); diff --git a/src/topology/elem.c b/src/topology/elem.c index 029c9ab..8b84257 100644 --- a/src/topology/elem.c +++ b/src/topology/elem.c @@ -189,6 +189,10 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg, list_add_tail(&elem->list, &tplg->pcm_list); obj_size = sizeof(struct snd_soc_tplg_pcm); break; + case SND_TPLG_TYPE_BE_DAI: + list_add_tail(&elem->list, &tplg->be_dai_list); + obj_size = sizeof(struct snd_soc_tplg_be_dai); + break; case SND_TPLG_TYPE_BE: list_add_tail(&elem->list, &tplg->be_list); obj_size = sizeof(struct snd_soc_tplg_link_config); diff --git a/src/topology/parser.c b/src/topology/parser.c index 3ab64f4..aa1b33e 100644 --- a/src/topology/parser.c +++ b/src/topology/parser.c @@ -133,6 +133,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) continue; }
+ if (strcmp(id, "SectionBEDAI") == 0) { + err = tplg_parse_compound(tplg, n, + tplg_parse_be_dai, NULL); + if (err < 0) + return err; + continue; + } + if (strcmp(id, "SectionBE") == 0) { err = tplg_parse_compound(tplg, n, tplg_parse_be, NULL); @@ -440,6 +448,7 @@ snd_tplg_t *snd_tplg_new(void) INIT_LIST_HEAD(&tplg->tlv_list); INIT_LIST_HEAD(&tplg->widget_list); INIT_LIST_HEAD(&tplg->pcm_list); + INIT_LIST_HEAD(&tplg->be_dai_list); INIT_LIST_HEAD(&tplg->be_list); INIT_LIST_HEAD(&tplg->cc_list); INIT_LIST_HEAD(&tplg->route_list); @@ -465,6 +474,7 @@ void snd_tplg_free(snd_tplg_t *tplg) tplg_elem_free_list(&tplg->tlv_list); tplg_elem_free_list(&tplg->widget_list); tplg_elem_free_list(&tplg->pcm_list); + tplg_elem_free_list(&tplg->be_dai_list); tplg_elem_free_list(&tplg->be_list); tplg_elem_free_list(&tplg->cc_list); tplg_elem_free_list(&tplg->route_list); diff --git a/src/topology/pcm.c b/src/topology/pcm.c index 0a90cb9..7e2f68f 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -266,6 +266,7 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, snd_config_t *n; struct tplg_elem *elem = private; struct snd_soc_tplg_pcm *pcm; + struct snd_soc_tplg_be_dai *be_dai; unsigned int *playback, *capture; struct snd_soc_tplg_stream_caps *caps; const char *id, *value; @@ -282,6 +283,14 @@ static int tplg_parse_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, capture = &pcm->capture; caps = pcm->caps; break; + + case SND_TPLG_TYPE_BE_DAI: + be_dai = elem->be_dai; + playback = &be_dai->playback; + capture = &be_dai->capture; + caps = be_dai->caps; + break; + default: return -EINVAL; } @@ -435,6 +444,123 @@ int tplg_parse_pcm(snd_tplg_t *tplg, return 0; }
+static int get_be_dai_flag(snd_config_t *n, + struct snd_soc_tplg_be_dai *be_dai, unsigned int mask) +{ + const char *val = NULL; + + if (snd_config_get_string(n, &val) < 0) + return -EINVAL; + + be_dai->flag_mask |= mask; + if (strcmp(val, "true") == 0) + be_dai->flags |= mask; + else + be_dai->flags &= ~mask; + + return 0; +} + +/* Parse back end DAI */ +int tplg_parse_be_dai(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) +{ + struct snd_soc_tplg_be_dai *be_dai; + struct tplg_elem *elem; + snd_config_iterator_t i, next; + snd_config_t *n; + const char *id, *val = NULL; + int err; + + elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_BE_DAI); + if (!elem) + return -ENOMEM; + + be_dai = elem->be_dai; + be_dai->size = elem->size; + elem_copy_text(be_dai->dai_name, elem->id, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + + tplg_dbg(" BE DAI: %s\n", elem->id); + + snd_config_for_each(i, next, cfg) { + + n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id) < 0) + continue; + + /* skip comments */ + if (strcmp(id, "comment") == 0) + continue; + if (id[0] == '#') + continue; + + if (strcmp(id, "index") == 0) { + if (snd_config_get_string(n, &val) < 0) + return -EINVAL; + + elem->index = atoi(val); + tplg_dbg("\t%s: %d\n", id, elem->index); + continue; + } + + if (strcmp(id, "id") == 0) { + if (snd_config_get_string(n, &val) < 0) + return -EINVAL; + + be_dai->dai_id = atoi(val); + tplg_dbg("\t%s: %d\n", id, be_dai->dai_id); + continue; + } + + /* stream capabilities */ + if (strcmp(id, "pcm") == 0) { + err = tplg_parse_compound(tplg, n, + tplg_parse_streams, elem); + if (err < 0) + return err; + continue; + } + + /* flags */ + if (strcmp(id, "symmetric_rates") == 0) { + err = get_be_dai_flag(n, be_dai, + SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES); + if (err < 0) + return err; + continue; + } + + if (strcmp(id, "symmetric_channels") == 0) { + err = get_be_dai_flag(n, be_dai, + SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS); + if (err < 0) + return err; + continue; + } + + if (strcmp(id, "symmetric_sample_bits") == 0) { + err = get_be_dai_flag(n, be_dai, + SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS); + if (err < 0) + return err; + continue; + } + + /* 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); + continue; + } + } + + return 0; +} + int tplg_parse_be(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED) { diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h index cfde4cc..e548ade 100644 --- a/src/topology/tplg_local.h +++ b/src/topology/tplg_local.h @@ -64,6 +64,7 @@ struct snd_tplg { struct list_head tlv_list; struct list_head widget_list; struct list_head pcm_list; + struct list_head be_dai_list; struct list_head be_list; struct list_head cc_list; struct list_head route_list; @@ -144,6 +145,7 @@ struct tplg_elem { struct snd_soc_tplg_bytes_control *bytes_ext; struct snd_soc_tplg_dapm_widget *widget; struct snd_soc_tplg_pcm *pcm; + struct snd_soc_tplg_be_dai *be_dai; struct snd_soc_tplg_link_config *be; struct snd_soc_tplg_link_config *cc; struct snd_soc_tplg_dapm_graph_elem *route; @@ -221,6 +223,9 @@ int tplg_parse_stream_caps(snd_tplg_t *tplg, int tplg_parse_pcm(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
+int tplg_parse_be_dai(snd_tplg_t *tplg, + snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); + int tplg_parse_be(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
From: Guneshwor Singh guneshwor.o.singh@intel.com
In addition to text conf file, BE (Back End) DAI configurations can also be added by C API. This patch defines the template to add BE DAI configurations from C API.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/include/topology.h b/include/topology.h index da45848..f98894f 100644 --- a/include/topology.h +++ b/include/topology.h @@ -894,6 +894,21 @@ struct snd_tplg_pcm_template { struct snd_tplg_stream_template stream[0]; /*!< supported configs */ };
+/** \struct snd_tplg_be_dai_template + * \brief Template type for Back End DAI. + */ +struct snd_tplg_be_dai_template { + const char *dai_name; /*!< DAI name */ + unsigned int dai_id; /*!< unique ID - used to match */ + unsigned int playback; /*!< supports playback mode */ + unsigned int capture; /*!< supports capture mode */ + struct snd_tplg_stream_caps_template *caps[2]; /*!< playback & capture for DAI */ + unsigned int flag_mask; /*!< bitmask of flags to configure */ + unsigned int flags; /*!< SND_SOC_TPLG_DAI_FLGBIT_* */ + struct snd_soc_tplg_private *priv; /*!< private data */ + +}; + /** \struct snd_tplg_link_template * \brief Template type for BE and CC DAI Links. */ @@ -919,6 +934,7 @@ typedef struct snd_tplg_obj_template { struct snd_tplg_enum_template *enum_ctl; /*!< Enum control */ struct snd_tplg_graph_template *graph; /*!< Graph elements */ struct snd_tplg_pcm_template *pcm; /*!< PCM elements */ + struct snd_tplg_be_dai_template *be_dai; /*!< BE DAI elements */ struct snd_tplg_link_template *link; /*!< BE and CC Links */ }; } snd_tplg_obj_template_t; diff --git a/src/topology/parser.c b/src/topology/parser.c index aa1b33e..02c19dd 100644 --- a/src/topology/parser.c +++ b/src/topology/parser.c @@ -355,6 +355,8 @@ 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_BE_DAI: + return tplg_add_be_dai_object(tplg, t); 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 7e2f68f..42efe4a 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -774,3 +774,58 @@ int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
return 0; } + +int tplg_add_be_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) +{ + struct snd_tplg_be_dai_template *be_tpl = t->be_dai; + struct snd_soc_tplg_be_dai *be, *_be; + struct tplg_elem *elem; + int i; + + tplg_dbg("BE DAI %s\n", be_tpl->dai_name); + + elem = tplg_elem_new_common(tplg, NULL, be_tpl->dai_name, + SND_TPLG_TYPE_BE_DAI); + if (!elem) + return -ENOMEM; + + be = elem->be_dai; + be->size = elem->size; + + elem_copy_text(be->dai_name, be_tpl->dai_name, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + be->dai_id = be_tpl->dai_id; + + /* stream caps */ + be->playback = be_tpl->playback; + be->capture = be_tpl->capture; + + for (i = 0; i < 2; i++) { + if (be_tpl->caps[i]) + tplg_add_stream_caps(&be->caps[i], be_tpl->caps[i]); + } + + /* flags */ + be->flag_mask = be_tpl->flag_mask; + be->flags = be_tpl->flags; + + /* private data */ + if (be_tpl->priv != NULL) { + _be = realloc(be, + elem->size + be_tpl->priv->size); + if (!_be) { + tplg_elem_free(elem); + return -ENOMEM; + } + + be = _be; + be->priv.size = be_tpl->priv->size; + + elem->be_dai = be; + elem->size += be->priv.size; + memcpy(be->priv.data, be_tpl->priv->data, + be->priv.size); + } + + return 0; +} diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h index e548ade..dab0162 100644 --- a/src/topology/tplg_local.h +++ b/src/topology/tplg_local.h @@ -293,3 +293,4 @@ int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type); int tplg_build_link_cfg(snd_tplg_t *tplg, unsigned int type); int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); +int tplg_add_be_dai_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
From: Guneshwor Singh guneshwor.o.singh@intel.com
Export the BE (back-end) DAI objects to the binary output file for kernel. For BE DAIs defined by the text conf file, find and merge their stream capablities before exporting.
Signed-off-by: Guneshwor Singh guneshwor.o.singh@intel.com Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/src/topology/builder.c b/src/topology/builder.c index b0ba54e..c1ba6a4 100644 --- a/src/topology/builder.c +++ b/src/topology/builder.c @@ -204,6 +204,9 @@ static int write_block(snd_tplg_t *tplg, struct list_head *base, case SND_TPLG_TYPE_DATA: return write_elem_block(tplg, base, size, SND_SOC_TPLG_TYPE_PDATA, "data"); + case SND_TPLG_TYPE_BE_DAI: + return write_elem_block(tplg, base, size, + SND_SOC_TPLG_TYPE_BE_DAI, "be_dai"); default: return -EINVAL; } @@ -293,6 +296,14 @@ int tplg_write_data(snd_tplg_t *tplg) return ret; }
+ /* write be dai elems */ + ret = write_block(tplg, &tplg->be_dai_list, + SND_TPLG_TYPE_BE_DAI); + if (ret < 0) { + SNDERR("failed to write be dai elems %d\n", ret); + return ret; + } + /* write be elems */ ret = write_block(tplg, &tplg->be_list, SND_TPLG_TYPE_BE); diff --git a/src/topology/parser.c b/src/topology/parser.c index 02c19dd..ff1c3cf 100644 --- a/src/topology/parser.c +++ b/src/topology/parser.c @@ -279,6 +279,10 @@ static int tplg_build_integ(snd_tplg_t *tplg) if (err < 0) return err;
+ err = tplg_build_be_dais(tplg, SND_TPLG_TYPE_BE_DAI); + if (err < 0) + return err; + err = tplg_build_link_cfg(tplg, SND_TPLG_TYPE_BE); if (err < 0) return err; diff --git a/src/topology/pcm.c b/src/topology/pcm.c index 42efe4a..65f7102 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -97,6 +97,62 @@ int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type) return 0; }
+static int tplg_build_be_dai(snd_tplg_t *tplg, struct tplg_elem *elem) +{ + struct tplg_ref *ref; + struct list_head *base, *pos; + int err = 0; + + /* get playback & capture stream caps */ + err = tplg_build_stream_caps(tplg, elem->id, elem->be_dai->caps); + if (err < 0) + return err; + + /* get private data */ + base = &elem->ref_list; + list_for_each(pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); + + if (ref->type == SND_TPLG_TYPE_DATA) { + err = tplg_copy_data(tplg, elem, ref); + if (err < 0) + return err; + } + } + + /* add BE DAI to manifest */ + tplg->manifest.be_dai_elems++; + + return 0; +} + + + +/* build BE DAIs*/ +int tplg_build_be_dais(snd_tplg_t *tplg, unsigned int type) +{ + struct list_head *base, *pos; + struct tplg_elem *elem; + int err = 0; + + base = &tplg->be_dai_list; + 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 = tplg_build_be_dai(tplg, elem); + if (err < 0) + return err; + } + + return 0; +} + static int tplg_build_stream_cfg(snd_tplg_t *tplg, struct snd_soc_tplg_stream *stream, int num_streams) { diff --git a/src/topology/tplg_local.h b/src/topology/tplg_local.h index dab0162..d90f313 100644 --- a/src/topology/tplg_local.h +++ b/src/topology/tplg_local.h @@ -290,6 +290,7 @@ int tplg_add_bytes(snd_tplg_t *tplg, struct snd_tplg_bytes_template *bytes_ctl, struct tplg_elem **e);
int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type); +int tplg_build_be_dais(snd_tplg_t *tplg, unsigned int type); int tplg_build_link_cfg(snd_tplg_t *tplg, unsigned int type); int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t); int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t);
From: Mengdong Lin mengdong.lin@linux.intel.com
Add sig_bits to stream caps and also add it to stream caps template of C API.
Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/include/sound/asoc.h b/include/sound/asoc.h index 2f88e83..752ce16 100644 --- a/include/sound/asoc.h +++ b/include/sound/asoc.h @@ -248,6 +248,7 @@ struct snd_soc_tplg_stream_caps { __le32 period_size_max; /* max period size bytes */ __le32 buffer_size_min; /* min buffer size bytes */ __le32 buffer_size_max; /* max buffer size bytes */ + __le32 sig_bits; /* number of bits of content */ } __attribute__((packed));
/* diff --git a/include/topology.h b/include/topology.h index f98894f..eec4a05 100644 --- a/include/topology.h +++ b/include/topology.h @@ -876,6 +876,7 @@ struct snd_tplg_stream_caps_template { unsigned int period_size_max; /*!< max period size bytes */ unsigned int buffer_size_min; /*!< min buffer size bytes */ unsigned int buffer_size_max; /*!< max buffer size bytes */ + unsigned int sig_bits; /*!< number of bits of content */ };
/** \struct snd_tplg_pcm_template diff --git a/src/topology/pcm.c b/src/topology/pcm.c index 65f7102..850704c 100644 --- a/src/topology/pcm.c +++ b/src/topology/pcm.c @@ -754,6 +754,7 @@ static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps, caps->period_size_max = caps_tpl->period_size_max; caps->buffer_size_min = caps_tpl->buffer_size_min; caps->buffer_size_max = caps_tpl->buffer_size_max; + caps->sig_bits = caps_tpl->sig_bits; }
int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
participants (3)
-
Mark Brown
-
Mengdong Lin
-
mengdong.lin@linux.intel.com