ASoC: Intel: Skylake: Clean up of driver resources in suspend
authorDharageswari R <dharageswari.r@intel.com>
Fri, 3 Jun 2016 12:59:39 +0000 (18:29 +0530)
committerMark Brown <broonie@kernel.org>
Tue, 7 Jun 2016 13:19:11 +0000 (14:19 +0100)
On suspend firmware is re-initialized so resources are reset inside
firmware. Driver should also clear the firmware counters at this time.

Signed-off-by: Dharageswari R <dharageswari.r@intel.com>
Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-sst-ipc.h
sound/soc/intel/skylake/skl-sst.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h

index ff04917..1590bef 100644 (file)
@@ -1197,9 +1197,17 @@ static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
 static int skl_platform_soc_probe(struct snd_soc_platform *platform)
 {
        struct hdac_ext_bus *ebus = dev_get_drvdata(platform->dev);
+       struct skl *skl = ebus_to_skl(ebus);
+       int ret;
 
-       if (ebus->ppcap)
-               return skl_tplg_init(platform, ebus);
+       if (ebus->ppcap) {
+               ret = skl_tplg_init(platform, ebus);
+               if (ret < 0) {
+                       dev_err(platform->dev, "Failed to init topology!\n");
+                       return ret;
+               }
+               skl->platform = platform;
+       }
 
        return 0;
 }
index 7b55182..9f24261 100644 (file)
@@ -139,5 +139,6 @@ void skl_ipc_int_disable(struct sst_dsp *dsp);
 bool skl_ipc_int_status(struct sst_dsp *dsp);
 void skl_ipc_free(struct sst_generic_ipc *ipc);
 int skl_ipc_init(struct device *dev, struct skl_sst *skl);
+void skl_clear_module_cnt(struct sst_dsp *ctx);
 
 #endif /* __SKL_IPC_H */
index 6021fa6..4cabae5 100644 (file)
@@ -379,6 +379,16 @@ static int skl_unload_module(struct sst_dsp *ctx, u16 mod_id)
        return ret;
 }
 
+void skl_clear_module_cnt(struct sst_dsp *ctx)
+{
+       struct skl_module_table *module;
+
+       list_for_each_entry(module, &ctx->module_list, list) {
+               module->usage_cnt = 0;
+       }
+}
+EXPORT_SYMBOL_GPL(skl_clear_module_cnt);
+
 static void skl_clear_module_table(struct sst_dsp *ctx)
 {
        struct skl_module_table *module, *tmp;
index 67b1ab5..263c03d 100644 (file)
@@ -1557,6 +1557,55 @@ static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt,
        }
 }
 
+static void skl_clear_pin_config(struct snd_soc_platform *platform,
+                               struct snd_soc_dapm_widget *w)
+{
+       int i;
+       struct skl_module_cfg *mconfig;
+       struct skl_pipe *pipe;
+
+       if (!strncmp(w->dapm->component->name, platform->component.name,
+                                       strlen(platform->component.name))) {
+               mconfig = w->priv;
+               pipe = mconfig->pipe;
+               for (i = 0; i < mconfig->max_in_queue; i++) {
+                       mconfig->m_in_pin[i].in_use = false;
+                       mconfig->m_in_pin[i].pin_state = SKL_PIN_UNBIND;
+               }
+               for (i = 0; i < mconfig->max_out_queue; i++) {
+                       mconfig->m_out_pin[i].in_use = false;
+                       mconfig->m_out_pin[i].pin_state = SKL_PIN_UNBIND;
+               }
+               pipe->state = SKL_PIPE_INVALID;
+               mconfig->m_state = SKL_MODULE_UNINIT;
+       }
+}
+
+void skl_cleanup_resources(struct skl *skl)
+{
+       struct skl_sst *ctx = skl->skl_sst;
+       struct snd_soc_platform *soc_platform = skl->platform;
+       struct snd_soc_dapm_widget *w;
+       struct snd_soc_card *card;
+
+       if (soc_platform == NULL)
+               return;
+
+       card = soc_platform->component.card;
+       if (!card || !card->instantiated)
+               return;
+
+       skl->resource.mem = 0;
+       skl->resource.mcps = 0;
+
+       list_for_each_entry(w, &card->widgets, list) {
+               if (is_skl_dsp_widget_type(w) && (w->priv != NULL))
+                       skl_clear_pin_config(soc_platform, w);
+       }
+
+       skl_clear_module_cnt(ctx->dsp);
+}
+
 /*
  * Topology core widget load callback
  *
index cb3eb41..c0f5d55 100644 (file)
@@ -201,6 +201,7 @@ static int _skl_suspend(struct hdac_ext_bus *ebus)
        skl_enable_miscbdcge(bus->dev, false);
        snd_hdac_bus_enter_link_reset(bus);
        skl_enable_miscbdcge(bus->dev, true);
+       skl_cleanup_resources(skl);
 
        return 0;
 }
index 25b8d48..9064e5b 100644 (file)
@@ -67,6 +67,7 @@ struct skl {
        unsigned int init_failed:1; /* delayed init failed */
        struct platform_device *dmic_dev;
        struct platform_device *i2s_dev;
+       struct snd_soc_platform *platform;
 
        struct nhlt_acpi_table *nhlt; /* nhlt ptr */
        struct skl_sst *skl_sst; /* sst skl ctx */
@@ -121,4 +122,5 @@ int skl_init_dsp(struct skl *skl);
 int skl_free_dsp(struct skl *skl);
 int skl_suspend_dsp(struct skl *skl);
 int skl_resume_dsp(struct skl *skl);
+void skl_cleanup_resources(struct skl *skl);
 #endif /* __SOUND_SOC_SKL_H */