]> git.alsa-project.org Git - alsa-lib.git/commitdiff
topology: Add C API support for PCM
authorMengdong Lin <mengdong.lin@linux.intel.com>
Thu, 5 Nov 2015 12:49:36 +0000 (20:49 +0800)
committerJaroslav Kysela <perex@perex.cz>
Thu, 5 Nov 2015 13:53:24 +0000 (14:53 +0100)
PCM objects can be added by C API. And this is used to create FE DAIs
and DAI links in kernel.

Signed-off-by: Mengdong Lin <mengdong.lin@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
include/topology.h
src/topology/parser.c
src/topology/pcm.c

index ccd69d7ae2d5115f05d9d5b88a7716c461120e79..b631871e14446426025ed76f98bf6d337289a035 100644 (file)
@@ -660,6 +660,41 @@ struct snd_tplg_stream_template {
        int channels;           /*!< number of channels */
 };
 
+/** \struct snd_tplg_stream_caps_template
+ * \brief Stream Capabilities.
+ */
+struct snd_tplg_stream_caps_template {
+       const char *name;       /*!< name of the stream caps */
+       __le64 formats; /*!< supported formats SNDRV_PCM_FMTBIT_* */
+       unsigned int rates;     /*!< supported rates SNDRV_PCM_RATE_* */
+       unsigned int rate_min;  /*!< min rate */
+       unsigned int rate_max;  /*!< max rate */
+       unsigned int channels_min;      /*!< min channels */
+       unsigned int channels_max;      /*!< max channels */
+       unsigned int periods_min;       /*!< min number of periods */
+       unsigned int periods_max;       /*!< max number of periods */
+       unsigned int period_size_min;   /*!< min period size bytes */
+       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 */
+};
+
+/** \struct snd_tplg_pcm_template
+ * \brief Template type for PCM (FE DAI & DAI links).
+ */
+struct snd_tplg_pcm_template {
+       const char *pcm_name;   /*!< PCM stream name */
+       const char *dai_name;   /*!< DAI name */
+       unsigned int pcm_id;    /*!< unique ID - used to match */
+       unsigned int dai_id;    /*!< unique ID - used to match */
+       unsigned int playback;  /*!< supports playback mode */
+       unsigned int capture;   /*!< supports capture mode */
+       unsigned int compress;  /*!< 1 = compressed; 0 = PCM */
+       struct snd_tplg_stream_caps_template *caps[2]; /*!< playback & capture for DAI */
+       int num_streams;        /*!< number of supported configs */
+       struct snd_tplg_stream_template stream[0]; /*!< supported configs */
+};
+
 /** \struct snd_tplg_link_template
  * \brief Template type for BE and CC DAI Links.
  */
@@ -684,6 +719,7 @@ typedef struct snd_tplg_obj_template {
                struct snd_tplg_bytes_template *bytes_ctl;      /*!< Bytes control */
                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_link_template *link;            /*!< BE and CC Links */
        };
 } snd_tplg_obj_template_t;
index 1851459f44b6b2dd76d32fa4e272ee77b1550d19..80a0ae08148b4cb23d30624ecade743a3f4874ff 100644 (file)
@@ -311,6 +311,8 @@ int snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
                return tplg_add_widget_object(tplg, t);
        case SND_TPLG_TYPE_DAPM_GRAPH:
                return tplg_add_graph_object(tplg, t);
+       case SND_TPLG_TYPE_PCM:
+               return tplg_add_pcm_object(tplg, t);
        case SND_TPLG_TYPE_BE:
        case SND_TPLG_TYPE_CC:
                return tplg_add_link_object(tplg, t);
index c2b2b9818ce097c696efbec15937dab98ae653d5..9b7e402e942410c4068fab0e071cffdd20a0444a 100644 (file)
@@ -95,6 +95,9 @@ int tplg_build_pcm(snd_tplg_t *tplg, unsigned int type)
                err = tplg_build_pcm_caps(tplg, elem);
                if (err < 0)
                        return err;
+
+               /* add PCM to manifest */
+               tplg->manifest.pcm_elems++;
        }
 
        return 0;
@@ -494,6 +497,68 @@ static void tplg_add_stream_object(struct snd_soc_tplg_stream *strm,
        strm->channels = strm_tpl->channels;
 }
 
+static void tplg_add_stream_caps(struct snd_soc_tplg_stream_caps *caps,
+       struct snd_tplg_stream_caps_template *caps_tpl)
+{
+       elem_copy_text(caps->name, caps_tpl->name,
+               SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+
+       caps->formats = caps_tpl->formats;
+       caps->rates = caps_tpl->rates;
+       caps->rate_min = caps_tpl->rate_min;
+       caps->rate_max = caps_tpl->rate_max;
+       caps->channels_min = caps_tpl->channels_min;
+       caps->channels_max = caps_tpl->channels_max;
+       caps->periods_min = caps_tpl->periods_min;
+       caps->periods_max = caps_tpl->periods_max;
+       caps->period_size_min = caps_tpl->period_size_min;
+       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;
+}
+
+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 tplg_elem *elem;
+       int i;
+
+       tplg_dbg("PCM: %s, DAI %s\n", pcm_tpl->pcm_name, pcm_tpl->dai_name);
+
+       if (pcm_tpl->num_streams > SND_SOC_TPLG_STREAM_CONFIG_MAX)
+               return -EINVAL;
+
+       elem = tplg_elem_new_common(tplg, NULL, pcm_tpl->pcm_name,
+               SND_TPLG_TYPE_PCM);
+       if (!elem)
+               return -ENOMEM;
+
+       pcm = elem->pcm;
+       pcm->size = elem->size;
+
+       elem_copy_text(pcm->pcm_name, pcm_tpl->pcm_name,
+               SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+       elem_copy_text(pcm->dai_name, pcm_tpl->dai_name,
+               SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
+       pcm->pcm_id = pcm_tpl->pcm_id;
+       pcm->dai_id = pcm_tpl->dai_id;
+       pcm->playback = pcm_tpl->playback;
+       pcm->capture = pcm_tpl->capture;
+       pcm->compress = pcm_tpl->compress;
+
+       for (i = 0; i < 2; i++) {
+               if (pcm_tpl->caps[i])
+                       tplg_add_stream_caps(&pcm->caps[i], pcm_tpl->caps[i]);
+       }
+
+       pcm->num_streams = pcm_tpl->num_streams;
+       for (i = 0; i < pcm->num_streams; i++)
+               tplg_add_stream_object(&pcm->stream[i], &pcm_tpl->stream[i]);
+
+       return 0;
+}
+
 int tplg_add_link_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t)
 {
        struct snd_tplg_link_template *link = t->link;