summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiam Girdwood <liam.r.girdwood@linux.intel.com>2014-05-05 17:31:37 +0100
committerMark Brown <broonie@linaro.org>2014-05-08 18:20:58 +0100
commit555f8a80c397b1a6ffccb294525df6ca2d721585 (patch)
tree121d1aacce9c327456e00d0bd80ce7c03ad79c75
parentdd1b94bf4920cc12545883faa43c014efbf61b1e (diff)
downloadop-kernel-dev-555f8a80c397b1a6ffccb294525df6ca2d721585.zip
op-kernel-dev-555f8a80c397b1a6ffccb294525df6ca2d721585.tar.gz
ASoC: Intel: Add support to unload/reload firmware modules.
Add some SST API calls to unload and reload firmware modules. This can be used by PM code to restore state and also allow modular FW to unload and release memory blocks. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/intel/sst-dsp-priv.h2
-rw-r--r--sound/soc/intel/sst-firmware.c38
2 files changed, 40 insertions, 0 deletions
diff --git a/sound/soc/intel/sst-dsp-priv.h b/sound/soc/intel/sst-dsp-priv.h
index fe8e81aa..cd4a3ca 100644
--- a/sound/soc/intel/sst-dsp-priv.h
+++ b/sound/soc/intel/sst-dsp-priv.h
@@ -283,6 +283,8 @@ struct sst_fw *sst_fw_new(struct sst_dsp *dsp,
const struct firmware *fw, void *private);
void sst_fw_free(struct sst_fw *sst_fw);
void sst_fw_free_all(struct sst_dsp *dsp);
+int sst_fw_reload(struct sst_fw *sst_fw);
+void sst_fw_unload(struct sst_fw *sst_fw);
/* Create/Free firmware modules */
struct sst_module *sst_module_new(struct sst_fw *sst_fw,
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c
index f24619a..0c74bf1 100644
--- a/sound/soc/intel/sst-firmware.c
+++ b/sound/soc/intel/sst-firmware.c
@@ -30,6 +30,8 @@
#include "sst-dsp.h"
#include "sst-dsp-priv.h"
+static void block_module_remove(struct sst_module *module);
+
static void sst_memcpy32(volatile void __iomem *dest, void *src, u32 bytes)
{
u32 i;
@@ -97,6 +99,42 @@ parse_err:
}
EXPORT_SYMBOL_GPL(sst_fw_new);
+int sst_fw_reload(struct sst_fw *sst_fw)
+{
+ struct sst_dsp *dsp = sst_fw->dsp;
+ int ret;
+
+ dev_dbg(dsp->dev, "reloading firmware\n");
+
+ /* call core specific FW paser to load FW data into DSP */
+ ret = dsp->ops->parse_fw(sst_fw);
+ if (ret < 0)
+ dev_err(dsp->dev, "error: parse fw failed %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sst_fw_reload);
+
+void sst_fw_unload(struct sst_fw *sst_fw)
+{
+ struct sst_dsp *dsp = sst_fw->dsp;
+ struct sst_module *module, *tmp;
+
+ dev_dbg(dsp->dev, "unloading firmware\n");
+
+ mutex_lock(&dsp->mutex);
+ list_for_each_entry_safe(module, tmp, &dsp->module_list, list) {
+ if (module->sst_fw == sst_fw) {
+ block_module_remove(module);
+ list_del(&module->list);
+ kfree(module);
+ }
+ }
+
+ mutex_unlock(&dsp->mutex);
+}
+EXPORT_SYMBOL_GPL(sst_fw_unload);
+
/* free single firmware object */
void sst_fw_free(struct sst_fw *sst_fw)
{
OpenPOWER on IntegriCloud