aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/intel/avs/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/intel/avs/dsp.c')
-rw-r--r--sound/soc/intel/avs/dsp.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c
index 53925eae92b3..3ff17bd22a5a 100644
--- a/sound/soc/intel/avs/dsp.c
+++ b/sound/soc/intel/avs/dsp.c
@@ -198,6 +198,7 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
u16 *instance_id)
{
struct avs_module_entry mentry;
+ bool was_loaded = false;
int ret, id;
id = avs_module_id_alloc(adev, module_id);
@@ -212,6 +213,16 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
if (ret)
goto err_mod_entry;
+ /* Load code into memory if this is the first instance. */
+ if (!id && !avs_module_entry_is_loaded(&mentry)) {
+ ret = avs_dsp_op(adev, transfer_mods, true, &mentry, 1);
+ if (ret) {
+ dev_err(adev->dev, "load modules failed: %d\n", ret);
+ goto err_mod_entry;
+ }
+ was_loaded = true;
+ }
+
ret = avs_ipc_init_instance(adev, module_id, id, ppl_instance_id,
core_id, domain, param, param_size);
if (ret) {
@@ -223,6 +234,8 @@ int avs_dsp_init_module(struct avs_dev *adev, u16 module_id, u8 ppl_instance_id,
return 0;
err_ipc:
+ if (was_loaded)
+ avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
avs_dsp_put_core(adev, core_id);
err_mod_entry:
avs_module_id_free(adev, module_id, id);
@@ -232,12 +245,25 @@ err_mod_entry:
void avs_dsp_delete_module(struct avs_dev *adev, u16 module_id, u16 instance_id,
u8 ppl_instance_id, u8 core_id)
{
+ struct avs_module_entry mentry;
+ int ret;
+
/* Modules not owned by any pipeline need to be freed explicitly. */
if (ppl_instance_id == INVALID_PIPELINE_ID)
avs_ipc_delete_instance(adev, module_id, instance_id);
avs_module_id_free(adev, module_id, instance_id);
+ ret = avs_get_module_id_entry(adev, module_id, &mentry);
+ /* Unload occupied memory if this was the last instance. */
+ if (!ret && mentry.type.load_type == AVS_MODULE_LOAD_TYPE_LOADABLE) {
+ if (avs_is_module_ida_empty(adev, module_id)) {
+ ret = avs_dsp_op(adev, transfer_mods, false, &mentry, 1);
+ if (ret)
+ dev_err(adev->dev, "unload modules failed: %d\n", ret);
+ }
+ }
+
avs_dsp_put_core(adev, core_id);
}