ASoC: topology: unload physical dai link in remove
authorBard liao <yung-chuan.liao@linux.intel.com>
Fri, 1 Feb 2019 17:07:40 +0000 (11:07 -0600)
committerMark Brown <broonie@kernel.org>
Mon, 4 Feb 2019 10:59:30 +0000 (11:59 +0100)
soc_tplg_link_config() will find the physical dai link and call
soc_tplg_dai_link_load() to load the BE dai link. Currently remove_link()
is only used to remove the FE dai link which is created by the topology.
The BE dai link cannot however be unloaded in snd_soc_tplg_component
_remove(), which is problematic if anything needs to be released or
reinitialized.

This patch aligns the definitions of dynamic types with the existing
UAPI and adds a new remove_backend_link() routine to unload the the BE
dai link when snd_soc_tplg_component_remove() is invoked.

Signed-off-by: Bard liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/soc-topology.h
sound/soc/soc-topology.c

index 8c43cfc..5223896 100644 (file)
@@ -45,6 +45,7 @@ enum snd_soc_dobj_type {
        SND_SOC_DOBJ_DAI_LINK,
        SND_SOC_DOBJ_PCM,
        SND_SOC_DOBJ_CODEC_LINK,
+       SND_SOC_DOBJ_BACKEND_LINK,
 };
 
 /* dynamic control object */
index 23d4213..246d2a2 100644 (file)
@@ -557,6 +557,25 @@ static void remove_link(struct snd_soc_component *comp,
        kfree(link);
 }
 
+/* unload dai link */
+static void remove_backend_link(struct snd_soc_component *comp,
+       struct snd_soc_dobj *dobj, int pass)
+{
+       if (pass != SOC_TPLG_PASS_LINK)
+               return;
+
+       if (dobj->ops && dobj->ops->link_unload)
+               dobj->ops->link_unload(comp, dobj);
+
+       /*
+        * We don't free the link here as what remove_link() do since BE
+        * links are not allocated by topology.
+        * We however need to reset the dobj type to its initial values
+        */
+       dobj->type = SND_SOC_DOBJ_NONE;
+       list_del(&dobj->list);
+}
+
 /* bind a kcontrol to it's IO handlers */
 static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr,
        struct snd_kcontrol_new *k,
@@ -2163,6 +2182,12 @@ static int soc_tplg_link_config(struct soc_tplg *tplg,
                return ret;
        }
 
+       /* for unloading it in snd_soc_tplg_component_remove */
+       link->dobj.index = tplg->index;
+       link->dobj.ops = tplg->ops;
+       link->dobj.type = SND_SOC_DOBJ_BACKEND_LINK;
+       list_add(&link->dobj.list, &tplg->comp->dobj_list);
+
        return 0;
 }
 
@@ -2649,6 +2674,13 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
                        case SND_SOC_DOBJ_DAI_LINK:
                                remove_link(comp, dobj, pass);
                                break;
+                       case SND_SOC_DOBJ_BACKEND_LINK:
+                               /*
+                                * call link_unload ops if extra
+                                * deinitialization is needed.
+                                */
+                               remove_backend_link(comp, dobj, pass);
+                               break;
                        default:
                                dev_err(comp->dev, "ASoC: invalid component type %d for removal\n",
                                        dobj->type);