Merge remote-tracking branches 'asoc/topic/adav80x', 'asoc/topic/adsp', 'asoc/topic...
[cascardo/linux.git] / sound / soc / codecs / wm_adsp.c
index f412a99..720d6e8 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/workqueue.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -169,11 +170,12 @@ static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
        if (buf == NULL)
                return NULL;
 
-       buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA);
+       buf->buf = vmalloc(len);
        if (!buf->buf) {
-               kfree(buf);
+               vfree(buf);
                return NULL;
        }
+       memcpy(buf->buf, src, len);
 
        if (list)
                list_add_tail(&buf->list, list);
@@ -188,7 +190,7 @@ static void wm_adsp_buf_free(struct list_head *list)
                                                           struct wm_adsp_buf,
                                                           list);
                list_del(&buf->list);
-               kfree(buf->buf);
+               vfree(buf->buf);
                kfree(buf);
        }
 }
@@ -684,38 +686,24 @@ static int wm_adsp_load(struct wm_adsp *dsp)
                }
 
                if (reg) {
-                       size_t to_write = PAGE_SIZE;
-                       size_t remain = le32_to_cpu(region->len);
-                       const u8 *data = region->data;
-
-                       while (remain > 0) {
-                               if (remain < PAGE_SIZE)
-                                       to_write = remain;
-
-                               buf = wm_adsp_buf_alloc(data,
-                                                       to_write,
-                                                       &buf_list);
-                               if (!buf) {
-                                       adsp_err(dsp, "Out of memory\n");
-                                       ret = -ENOMEM;
-                                       goto out_fw;
-                               }
-
-                               ret = regmap_raw_write_async(regmap, reg,
-                                                            buf->buf,
-                                                            to_write);
-                               if (ret != 0) {
-                                       adsp_err(dsp,
-                                               "%s.%d: Failed to write %zd bytes at %d in %s: %d\n",
-                                               file, regions,
-                                               to_write, offset,
-                                               region_name, ret);
-                                       goto out_fw;
-                               }
+                       buf = wm_adsp_buf_alloc(region->data,
+                                               le32_to_cpu(region->len),
+                                               &buf_list);
+                       if (!buf) {
+                               adsp_err(dsp, "Out of memory\n");
+                               ret = -ENOMEM;
+                               goto out_fw;
+                       }
 
-                               data += to_write;
-                               reg += to_write / 2;
-                               remain -= to_write;
+                       ret = regmap_raw_write_async(regmap, reg, buf->buf,
+                                                    le32_to_cpu(region->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+                                       file, regions,
+                                       le32_to_cpu(region->len), offset,
+                                       region_name, ret);
+                               goto out_fw;
                        }
                }
 
@@ -1065,8 +1053,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
                                  be32_to_cpu(adsp1_alg[i].zm));
 
                        region = kzalloc(sizeof(*region), GFP_KERNEL);
-                       if (!region)
-                               return -ENOMEM;
+                       if (!region) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                        region->type = WMFW_ADSP1_DM;
                        region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
                        region->base = be32_to_cpu(adsp1_alg[i].dm);
@@ -1083,8 +1073,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
                        }
 
                        region = kzalloc(sizeof(*region), GFP_KERNEL);
-                       if (!region)
-                               return -ENOMEM;
+                       if (!region) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                        region->type = WMFW_ADSP1_ZM;
                        region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
                        region->base = be32_to_cpu(adsp1_alg[i].zm);
@@ -1113,8 +1105,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
                                  be32_to_cpu(adsp2_alg[i].zm));
 
                        region = kzalloc(sizeof(*region), GFP_KERNEL);
-                       if (!region)
-                               return -ENOMEM;
+                       if (!region) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                        region->type = WMFW_ADSP2_XM;
                        region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
                        region->base = be32_to_cpu(adsp2_alg[i].xm);
@@ -1131,8 +1125,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
                        }
 
                        region = kzalloc(sizeof(*region), GFP_KERNEL);
-                       if (!region)
-                               return -ENOMEM;
+                       if (!region) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                        region->type = WMFW_ADSP2_YM;
                        region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
                        region->base = be32_to_cpu(adsp2_alg[i].ym);
@@ -1149,8 +1145,10 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
                        }
 
                        region = kzalloc(sizeof(*region), GFP_KERNEL);
-                       if (!region)
-                               return -ENOMEM;
+                       if (!region) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
                        region->type = WMFW_ADSP2_ZM;
                        region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
                        region->base = be32_to_cpu(adsp2_alg[i].zm);
@@ -1355,6 +1353,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                          file, blocks, pos - firmware->size);
 
 out_fw:
+       regmap_async_complete(regmap);
        release_firmware(firmware);
        wm_adsp_buf_free(&buf_list);
 out:
@@ -1594,13 +1593,6 @@ static void wm_adsp2_boot_work(struct work_struct *work)
        if (ret != 0)
                goto err;
 
-       ret = regmap_update_bits_async(dsp->regmap,
-                                      dsp->base + ADSP2_CONTROL,
-                                      ADSP2_CORE_ENA,
-                                      ADSP2_CORE_ENA);
-       if (ret != 0)
-               goto err;
-
        dsp->running = true;
 
        return;
@@ -1650,8 +1642,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
 
                ret = regmap_update_bits(dsp->regmap,
                                         dsp->base + ADSP2_CONTROL,
-                                        ADSP2_START,
-                                        ADSP2_START);
+                                        ADSP2_CORE_ENA | ADSP2_START,
+                                        ADSP2_CORE_ENA | ADSP2_START);
                if (ret != 0)
                        goto err;
                break;