]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - sound/soc/soc-topology.c
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / sound / soc / soc-topology.c
index fa27d0fca6dce10ed8befc8df9cdf7406dbcac75..3fd5d9c867b9b5d30c39eee8d615849d094630b6 100644 (file)
 #define SOC_TPLG_PASS_START    SOC_TPLG_PASS_MANIFEST
 #define SOC_TPLG_PASS_END      SOC_TPLG_PASS_LINK
 
-/*
- * Old version of ABI structs, supported for backward compatibility.
- */
-
-/* Manifest v4 */
-struct snd_soc_tplg_manifest_v4 {
-       __le32 size;            /* in bytes of this structure */
-       __le32 control_elems;   /* number of control elements */
-       __le32 widget_elems;    /* number of widget elements */
-       __le32 graph_elems;     /* number of graph elements */
-       __le32 pcm_elems;       /* number of PCM elements */
-       __le32 dai_link_elems;  /* number of DAI link elements */
-       struct snd_soc_tplg_private priv;
-} __packed;
-
-/* Stream Capabilities v4 */
-struct snd_soc_tplg_stream_caps_v4 {
-       __le32 size;            /* in bytes of this structure */
-       char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-       __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */
-       __le32 rates;           /* supported rates SNDRV_PCM_RATE_* */
-       __le32 rate_min;        /* min rate */
-       __le32 rate_max;        /* max rate */
-       __le32 channels_min;    /* min channels */
-       __le32 channels_max;    /* max channels */
-       __le32 periods_min;     /* min number of periods */
-       __le32 periods_max;     /* max number of periods */
-       __le32 period_size_min; /* min period size bytes */
-       __le32 period_size_max; /* max period size bytes */
-       __le32 buffer_size_min; /* min buffer size bytes */
-       __le32 buffer_size_max; /* max buffer size bytes */
-} __packed;
-
-/* PCM v4 */
-struct snd_soc_tplg_pcm_v4 {
-       __le32 size;            /* in bytes of this structure */
-       char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-       char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-       __le32 pcm_id;          /* unique ID - used to match with DAI link */
-       __le32 dai_id;          /* unique ID - used to match */
-       __le32 playback;        /* supports playback mode */
-       __le32 capture;         /* supports capture mode */
-       __le32 compress;        /* 1 = compressed; 0 = PCM */
-       struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */
-       __le32 num_streams;     /* number of streams */
-       struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */
-} __packed;
-
-/* Physical link config v4 */
-struct snd_soc_tplg_link_config_v4 {
-       __le32 size;            /* in bytes of this structure */
-       __le32 id;              /* unique ID - used to match */
-       struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */
-       __le32 num_streams;     /* number of streams */
-} __packed;
-
 /* topology context */
 struct soc_tplg {
        const struct firmware *fw;
@@ -513,7 +457,7 @@ static void remove_widget(struct snd_soc_component *comp,
         */
        if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) {
                /* enumerated widget mixer */
-               for (i = 0; i < w->num_kcontrols; i++) {
+               for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) {
                        struct snd_kcontrol *kcontrol = w->kcontrols[i];
                        struct soc_enum *se =
                                (struct soc_enum *)kcontrol->private_value;
@@ -530,7 +474,7 @@ static void remove_widget(struct snd_soc_component *comp,
                }
        } else {
                /* volume mixer or bytes controls */
-               for (i = 0; i < w->num_kcontrols; i++) {
+               for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) {
                        struct snd_kcontrol *kcontrol = w->kcontrols[i];
 
                        if (dobj->widget.kcontrol_type
@@ -1325,8 +1269,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create(
                        ec->hdr.name);
 
                kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL);
-               if (kc[i].name == NULL)
+               if (kc[i].name == NULL) {
+                       kfree(se);
                        goto err_se;
+               }
                kc[i].private_value = (long)se;
                kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
                kc[i].access = ec->hdr.access;
@@ -1442,8 +1388,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create(
                        be->hdr.name, be->hdr.access);
 
                kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL);
-               if (kc[i].name == NULL)
+               if (kc[i].name == NULL) {
+                       kfree(sbe);
                        goto err;
+               }
                kc[i].private_value = (long)sbe;
                kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
                kc[i].access = be->hdr.access;
@@ -1750,6 +1698,9 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
                set_stream_info(stream, caps);
        }
 
+       if (pcm->compress)
+               dai_drv->compress_new = snd_soc_new_compress;
+
        /* pass control to component driver for optional further init */
        ret = soc_tplg_dai_load(tplg, dai_drv);
        if (ret < 0) {
@@ -2002,6 +1953,21 @@ static void set_link_hw_format(struct snd_soc_dai_link *link,
 
                link->dai_fmt = hw_config->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 
+               /* clock gating */
+               switch (hw_config->clock_gated) {
+               case SND_SOC_TPLG_DAI_CLK_GATE_GATED:
+                       link->dai_fmt |= SND_SOC_DAIFMT_GATED;
+                       break;
+
+               case SND_SOC_TPLG_DAI_CLK_GATE_CONT:
+                       link->dai_fmt |= SND_SOC_DAIFMT_CONT;
+                       break;
+
+               default:
+                       /* ignore the value */
+                       break;
+               }
+
                /* clock signal polarity */
                invert_bclk = hw_config->invert_bclk;
                invert_fsync = hw_config->invert_fsync;
@@ -2015,13 +1981,15 @@ static void set_link_hw_format(struct snd_soc_dai_link *link,
                        link->dai_fmt |= SND_SOC_DAIFMT_IB_IF;
 
                /* clock masters */
-               bclk_master = hw_config->bclk_master;
-               fsync_master = hw_config->fsync_master;
-               if (!bclk_master && !fsync_master)
+               bclk_master = (hw_config->bclk_master ==
+                              SND_SOC_TPLG_BCLK_CM);
+               fsync_master = (hw_config->fsync_master ==
+                               SND_SOC_TPLG_FSYNC_CM);
+               if (bclk_master && fsync_master)
                        link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
-               else if (bclk_master && !fsync_master)
-                       link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
                else if (!bclk_master && fsync_master)
+                       link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
+               else if (bclk_master && !fsync_master)
                        link->dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
                else
                        link->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
@@ -2289,8 +2257,11 @@ static int manifest_new_ver(struct soc_tplg *tplg,
        *manifest = NULL;
 
        if (src->size != sizeof(*src_v4)) {
-               dev_err(tplg->dev, "ASoC: invalid manifest size\n");
-               return -EINVAL;
+               dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n",
+                        src->size);
+               if (src->size)
+                       return -EINVAL;
+               src->size = sizeof(*src_v4);
        }
 
        dev_warn(tplg->dev, "ASoC: old version of manifest\n");
@@ -2576,7 +2547,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
 
                        /* match index */
                        if (dobj->index != index &&
-                               dobj->index != SND_SOC_TPLG_INDEX_ALL)
+                               index != SND_SOC_TPLG_INDEX_ALL)
                                continue;
 
                        switch (dobj->type) {