]> git.alsa-project.org Git - alsa-lib.git/commitdiff
topology: Parse and build private data for PCM
authorMengdong Lin <mengdong.lin@linux.intel.com>
Thu, 3 Nov 2016 23:08:12 +0000 (07:08 +0800)
committerTakashi Iwai <tiwai@suse.de>
Sat, 5 Nov 2016 15:41:55 +0000 (16:41 +0100)
Users can define private for PCM (FE DAI & DAI links) elements by both
text conf file and C API:

- Text conf file may define multiple data blocks for a PCM and they will
  be merged in building phase;

- Add private data to C API template of PCM object.

Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/topology.h
src/topology/pcm.c

index 8f3e1471811fd9d28eea4c1030b154ad72f02317..dbd18b38f95f081d5d977b9c468657fc3447a657 100644 (file)
@@ -612,6 +612,8 @@ extern "C" {
  *     symmetric_rates                 "true"
  *     symmetric_channels              "true"
  *     symmetric_sample_bits           "false"
+ *
+ *     data "name"                     # optional private data
  * }
  * </pre>
  *
@@ -901,6 +903,7 @@ struct snd_tplg_pcm_template {
        struct snd_tplg_stream_caps_template *caps[2]; /*!< playback & capture for DAI */
        unsigned int flag_mask; /*!< bitmask of flags to configure */
        unsigned int flags;     /*!< flag value SND_SOC_TPLG_LNK_FLGBIT_* */
+       struct snd_soc_tplg_private *priv;      /*!< private data */
        int num_streams;        /*!< number of supported configs */
        struct snd_tplg_stream_template stream[0]; /*!< supported configs */
 };
index 77b760566d8cb06c71328afd4efa9279f7c62041..3f54e9496849b5bd1984b0ea2cf23d1434ddc6a2 100644 (file)
@@ -73,12 +73,32 @@ static int tplg_build_stream_caps(snd_tplg_t *tplg,
 /* build a PCM (FE DAI & DAI link) element */
 static int build_pcm(snd_tplg_t *tplg, struct tplg_elem *elem)
 {
+       struct tplg_ref *ref;
+       struct list_head *base, *pos;
        int err;
 
        err = tplg_build_stream_caps(tplg, elem->id, elem->pcm->caps);
                if (err < 0)
                        return err;
 
+       /* merge private data from the referenced data elements */
+       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;
+               }
+               if (!ref->elem) {
+                       SNDERR("error: cannot find '%s' referenced by"
+                               " PCM '%s'\n", ref->id, elem->id);
+                       return -EINVAL;
+               } else if (err < 0)
+                       return err;
+       }
+
        return 0;
 }
 
@@ -394,7 +414,7 @@ static int parse_flag(snd_config_t *n, unsigned int mask_in,
        return 0;
 }
 
-/* Parse pcm (for front end DAI & DAI link) */
+/* 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)
 {
@@ -501,6 +521,7 @@ int tplg_parse_be(snd_tplg_t *tplg,
        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);
        if (!elem)
@@ -540,6 +561,13 @@ int tplg_parse_be(snd_tplg_t *tplg,
                        tplg_dbg("\t%s: %d\n", id, link->id);
                        continue;
                }
+
+               if (strcmp(id, "data") == 0) {
+                       err = tplg_parse_data_refs(n, elem);
+                       if (err < 0)
+                               return err;
+                       continue;
+               }
        }
 
        return 0;
@@ -633,10 +661,11 @@ static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps,
        caps->sig_bits = caps_tpl->sig_bits;
 }
 
+/* Add a PCM element (FE DAI & DAI link) from C API */
 int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
 {
        struct snd_tplg_pcm_template *pcm_tpl = t->pcm;
-       struct snd_soc_tplg_pcm *pcm;
+       struct snd_soc_tplg_pcm *pcm, *_pcm;
        struct tplg_elem *elem;
        int i;
 
@@ -675,6 +704,25 @@ int tplg_add_pcm_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
        for (i = 0; i < pcm_tpl->num_streams; i++)
                tplg_add_stream_object(&pcm->stream[i], &pcm_tpl->stream[i]);
 
+       /* private data */
+       if (pcm_tpl->priv != NULL && pcm_tpl->priv->size) {
+               tplg_dbg("\t priv data size %d\n", pcm_tpl->priv->size);
+               _pcm = realloc(pcm,
+                       elem->size + pcm_tpl->priv->size);
+               if (!_pcm) {
+                       tplg_elem_free(elem);
+                       return -ENOMEM;
+               }
+
+               pcm = _pcm;
+               elem->pcm = pcm;
+               elem->size += pcm_tpl->priv->size;
+
+               memcpy(pcm->priv.data, pcm_tpl->priv->data,
+                       pcm_tpl->priv->size);
+               pcm->priv.size = pcm_tpl->priv->size;
+       }
+
        return 0;
 }