diff options
Diffstat (limited to 'sound/soc/intel/sst-firmware.c')
-rw-r--r-- | sound/soc/intel/sst-firmware.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c index f7687107cf7f..3bb43dac892d 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; @@ -57,14 +59,8 @@ struct sst_fw *sst_fw_new(struct sst_dsp *dsp, sst_fw->private = private; sst_fw->size = fw->size; - err = dma_coerce_mask_and_coherent(dsp->dev, DMA_BIT_MASK(32)); - if (err < 0) { - kfree(sst_fw); - return NULL; - } - /* allocate DMA buffer to store FW data */ - sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size, + sst_fw->dma_buf = dma_alloc_coherent(dsp->dma_dev, sst_fw->size, &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL); if (!sst_fw->dma_buf) { dev_err(dsp->dev, "error: DMA alloc failed\n"); @@ -97,6 +93,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) { @@ -106,7 +138,7 @@ void sst_fw_free(struct sst_fw *sst_fw) list_del(&sst_fw->list); mutex_unlock(&dsp->mutex); - dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf, + dma_free_coherent(dsp->dma_dev, sst_fw->size, sst_fw->dma_buf, sst_fw->dmable_fw_paddr); kfree(sst_fw); } @@ -202,6 +234,9 @@ static int block_alloc_contiguous(struct sst_module *module, size -= block->size; } + list_for_each_entry(block, &tmp, list) + list_add(&block->module_list, &module->block_list); + list_splice(&tmp, &dsp->used_block_list); return 0; } @@ -247,8 +282,7 @@ static int block_alloc(struct sst_module *module, /* do we span > 1 blocks */ if (data->size > block->size) { ret = block_alloc_contiguous(module, data, - block->offset + block->size, - data->size - block->size); + block->offset, data->size); if (ret == 0) return ret; } @@ -344,7 +378,7 @@ static int block_alloc_fixed(struct sst_module *module, err = block_alloc_contiguous(module, data, block->offset + block->size, - data->size - block->size + data->offset - block->offset); + data->size - block->size); if (err < 0) return -ENOMEM; @@ -371,15 +405,10 @@ static int block_alloc_fixed(struct sst_module *module, if (data->offset >= block->offset && data->offset < block_end) { err = block_alloc_contiguous(module, data, - block->offset + block->size, - data->size - block->size); + block->offset, data->size); if (err < 0) return -ENOMEM; - /* add block */ - block->data_type = data->data_type; - list_move(&block->list, &dsp->used_block_list); - list_add(&block->module_list, &module->block_list); return 0; } @@ -505,9 +534,7 @@ struct sst_module *sst_mem_block_alloc_scratch(struct sst_dsp *dsp) /* calculate required scratch size */ list_for_each_entry(sst_module, &dsp->module_list, list) { - if (scratch->s.size > sst_module->s.size) - scratch->s.size = scratch->s.size; - else + if (scratch->s.size < sst_module->s.size) scratch->s.size = sst_module->s.size; } |