aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_adsp.c
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2014-11-14 10:40:45 -0500
committerMark Brown <broonie@kernel.org>2014-11-14 12:32:25 -0500
commitcdcd7f7287532131d2075dd45f15aaf39dcfe983 (patch)
tree5eb097491d1878e41b2eb1a7e001d3e834a92557 /sound/soc/codecs/wm_adsp.c
parentf114040e3ea6e07372334ade75d1ee0775c355e1 (diff)
ASoC: wm_adsp: Use vmalloc to allocate firmware download buffer
Use vmalloc to allocate the buffer for firmware/coefficient download and rely on the SPI core to split this up into DMA-able chunks. This should give better performance and means we no longer need to manually split the download into page size chunks to avoid allocating overly large continuous memory regions. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/wm_adsp.c')
-rw-r--r--sound/soc/codecs/wm_adsp.c56
1 files changed, 22 insertions, 34 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index f412a9911a75..0a08ef5e27c8 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -21,6 +21,7 @@
21#include <linux/regmap.h> 21#include <linux/regmap.h>
22#include <linux/regulator/consumer.h> 22#include <linux/regulator/consumer.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/vmalloc.h>
24#include <linux/workqueue.h> 25#include <linux/workqueue.h>
25#include <sound/core.h> 26#include <sound/core.h>
26#include <sound/pcm.h> 27#include <sound/pcm.h>
@@ -169,11 +170,12 @@ static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
169 if (buf == NULL) 170 if (buf == NULL)
170 return NULL; 171 return NULL;
171 172
172 buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA); 173 buf->buf = vmalloc(len);
173 if (!buf->buf) { 174 if (!buf->buf) {
174 kfree(buf); 175 vfree(buf);
175 return NULL; 176 return NULL;
176 } 177 }
178 memcpy(buf->buf, src, len);
177 179
178 if (list) 180 if (list)
179 list_add_tail(&buf->list, list); 181 list_add_tail(&buf->list, list);
@@ -188,7 +190,7 @@ static void wm_adsp_buf_free(struct list_head *list)
188 struct wm_adsp_buf, 190 struct wm_adsp_buf,
189 list); 191 list);
190 list_del(&buf->list); 192 list_del(&buf->list);
191 kfree(buf->buf); 193 vfree(buf->buf);
192 kfree(buf); 194 kfree(buf);
193 } 195 }
194} 196}
@@ -684,38 +686,24 @@ static int wm_adsp_load(struct wm_adsp *dsp)
684 } 686 }
685 687
686 if (reg) { 688 if (reg) {
687 size_t to_write = PAGE_SIZE; 689 buf = wm_adsp_buf_alloc(region->data,
688 size_t remain = le32_to_cpu(region->len); 690 le32_to_cpu(region->len),
689 const u8 *data = region->data; 691 &buf_list);
690 692 if (!buf) {
691 while (remain > 0) { 693 adsp_err(dsp, "Out of memory\n");
692 if (remain < PAGE_SIZE) 694 ret = -ENOMEM;
693 to_write = remain; 695 goto out_fw;
694 696 }
695 buf = wm_adsp_buf_alloc(data,
696 to_write,
697 &buf_list);
698 if (!buf) {
699 adsp_err(dsp, "Out of memory\n");
700 ret = -ENOMEM;
701 goto out_fw;
702 }
703
704 ret = regmap_raw_write_async(regmap, reg,
705 buf->buf,
706 to_write);
707 if (ret != 0) {
708 adsp_err(dsp,
709 "%s.%d: Failed to write %zd bytes at %d in %s: %d\n",
710 file, regions,
711 to_write, offset,
712 region_name, ret);
713 goto out_fw;
714 }
715 697
716 data += to_write; 698 ret = regmap_raw_write_async(regmap, reg, buf->buf,
717 reg += to_write / 2; 699 le32_to_cpu(region->len));
718 remain -= to_write; 700 if (ret != 0) {
701 adsp_err(dsp,
702 "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
703 file, regions,
704 le32_to_cpu(region->len), offset,
705 region_name, ret);
706 goto out_fw;
719 } 707 }
720 } 708 }
721 709