Merge commit 'ed30f24e8d07d30aa3e69d1f508f4d7bd2e8ea14' of git://git.linaro.org/landi...
[firefly-linux-kernel-4.4.55.git] / sound / soc / codecs / wm_adsp.c
1 /*
2  * wm_adsp.c  --  Wolfson ADSP support
3  *
4  * Copyright 2012 Wolfson Microelectronics plc
5  *
6  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/firmware.h>
18 #include <linux/list.h>
19 #include <linux/pm.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/slab.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 #include <sound/jack.h>
29 #include <sound/initval.h>
30 #include <sound/tlv.h>
31
32 #include <linux/mfd/arizona/registers.h>
33
34 #include "arizona.h"
35 #include "wm_adsp.h"
36
37 #define adsp_crit(_dsp, fmt, ...) \
38         dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
39 #define adsp_err(_dsp, fmt, ...) \
40         dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
41 #define adsp_warn(_dsp, fmt, ...) \
42         dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
43 #define adsp_info(_dsp, fmt, ...) \
44         dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
45 #define adsp_dbg(_dsp, fmt, ...) \
46         dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
47
48 #define ADSP1_CONTROL_1                   0x00
49 #define ADSP1_CONTROL_2                   0x02
50 #define ADSP1_CONTROL_3                   0x03
51 #define ADSP1_CONTROL_4                   0x04
52 #define ADSP1_CONTROL_5                   0x06
53 #define ADSP1_CONTROL_6                   0x07
54 #define ADSP1_CONTROL_7                   0x08
55 #define ADSP1_CONTROL_8                   0x09
56 #define ADSP1_CONTROL_9                   0x0A
57 #define ADSP1_CONTROL_10                  0x0B
58 #define ADSP1_CONTROL_11                  0x0C
59 #define ADSP1_CONTROL_12                  0x0D
60 #define ADSP1_CONTROL_13                  0x0F
61 #define ADSP1_CONTROL_14                  0x10
62 #define ADSP1_CONTROL_15                  0x11
63 #define ADSP1_CONTROL_16                  0x12
64 #define ADSP1_CONTROL_17                  0x13
65 #define ADSP1_CONTROL_18                  0x14
66 #define ADSP1_CONTROL_19                  0x16
67 #define ADSP1_CONTROL_20                  0x17
68 #define ADSP1_CONTROL_21                  0x18
69 #define ADSP1_CONTROL_22                  0x1A
70 #define ADSP1_CONTROL_23                  0x1B
71 #define ADSP1_CONTROL_24                  0x1C
72 #define ADSP1_CONTROL_25                  0x1E
73 #define ADSP1_CONTROL_26                  0x20
74 #define ADSP1_CONTROL_27                  0x21
75 #define ADSP1_CONTROL_28                  0x22
76 #define ADSP1_CONTROL_29                  0x23
77 #define ADSP1_CONTROL_30                  0x24
78 #define ADSP1_CONTROL_31                  0x26
79
80 /*
81  * ADSP1 Control 19
82  */
83 #define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
84 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
85 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
86
87
88 /*
89  * ADSP1 Control 30
90  */
91 #define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
92 #define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
93 #define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
94 #define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
95 #define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
96 #define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
97 #define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
98 #define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
99 #define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
100 #define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
101 #define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
102 #define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
103 #define ADSP1_START                       0x0001  /* DSP1_START */
104 #define ADSP1_START_MASK                  0x0001  /* DSP1_START */
105 #define ADSP1_START_SHIFT                      0  /* DSP1_START */
106 #define ADSP1_START_WIDTH                      1  /* DSP1_START */
107
108 /*
109  * ADSP1 Control 31
110  */
111 #define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
112 #define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
113 #define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
114
115 #define ADSP2_CONTROL        0x0
116 #define ADSP2_CLOCKING       0x1
117 #define ADSP2_STATUS1        0x4
118 #define ADSP2_WDMA_CONFIG_1 0x30
119 #define ADSP2_WDMA_CONFIG_2 0x31
120 #define ADSP2_RDMA_CONFIG_1 0x34
121
122 /*
123  * ADSP2 Control
124  */
125
126 #define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
127 #define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
128 #define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
129 #define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
130 #define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
131 #define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
132 #define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
133 #define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
134 #define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
135 #define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
136 #define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
137 #define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
138 #define ADSP2_START                       0x0001  /* DSP1_START */
139 #define ADSP2_START_MASK                  0x0001  /* DSP1_START */
140 #define ADSP2_START_SHIFT                      0  /* DSP1_START */
141 #define ADSP2_START_WIDTH                      1  /* DSP1_START */
142
143 /*
144  * ADSP2 clocking
145  */
146 #define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
147 #define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
148 #define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
149
150 /*
151  * ADSP2 Status 1
152  */
153 #define ADSP2_RAM_RDY                     0x0001
154 #define ADSP2_RAM_RDY_MASK                0x0001
155 #define ADSP2_RAM_RDY_SHIFT                    0
156 #define ADSP2_RAM_RDY_WIDTH                    1
157
158 struct wm_adsp_buf {
159         struct list_head list;
160         void *buf;
161 };
162
163 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
164                                              struct list_head *list)
165 {
166         struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
167
168         if (buf == NULL)
169                 return NULL;
170
171         buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA);
172         if (!buf->buf) {
173                 kfree(buf);
174                 return NULL;
175         }
176
177         if (list)
178                 list_add_tail(&buf->list, list);
179
180         return buf;
181 }
182
183 static void wm_adsp_buf_free(struct list_head *list)
184 {
185         while (!list_empty(list)) {
186                 struct wm_adsp_buf *buf = list_first_entry(list,
187                                                            struct wm_adsp_buf,
188                                                            list);
189                 list_del(&buf->list);
190                 kfree(buf->buf);
191                 kfree(buf);
192         }
193 }
194
195 #define WM_ADSP_NUM_FW 4
196
197 #define WM_ADSP_FW_MBC_VSS 0
198 #define WM_ADSP_FW_TX      1
199 #define WM_ADSP_FW_TX_SPK  2
200 #define WM_ADSP_FW_RX_ANC  3
201
202 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
203         [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
204         [WM_ADSP_FW_TX] =      "Tx",
205         [WM_ADSP_FW_TX_SPK] =  "Tx Speaker",
206         [WM_ADSP_FW_RX_ANC] =  "Rx ANC",
207 };
208
209 static struct {
210         const char *file;
211 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
212         [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
213         [WM_ADSP_FW_TX] =      { .file = "tx" },
214         [WM_ADSP_FW_TX_SPK] =  { .file = "tx-spk" },
215         [WM_ADSP_FW_RX_ANC] =  { .file = "rx-anc" },
216 };
217
218 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
219                           struct snd_ctl_elem_value *ucontrol)
220 {
221         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
222         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
223         struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
224
225         ucontrol->value.integer.value[0] = adsp[e->shift_l].fw;
226
227         return 0;
228 }
229
230 static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
231                           struct snd_ctl_elem_value *ucontrol)
232 {
233         struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
234         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
235         struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
236
237         if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw)
238                 return 0;
239
240         if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
241                 return -EINVAL;
242
243         if (adsp[e->shift_l].running)
244                 return -EBUSY;
245
246         adsp[e->shift_l].fw = ucontrol->value.integer.value[0];
247
248         return 0;
249 }
250
251 static const struct soc_enum wm_adsp_fw_enum[] = {
252         SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
253         SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
254         SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
255         SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
256 };
257
258 const struct snd_kcontrol_new wm_adsp1_fw_controls[] = {
259         SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
260                      wm_adsp_fw_get, wm_adsp_fw_put),
261         SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
262                      wm_adsp_fw_get, wm_adsp_fw_put),
263         SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
264                      wm_adsp_fw_get, wm_adsp_fw_put),
265 };
266 EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls);
267
268 #if IS_ENABLED(CONFIG_SND_SOC_ARIZONA)
269 static const struct soc_enum wm_adsp2_rate_enum[] = {
270         SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
271                               ARIZONA_DSP1_RATE_SHIFT, 0xf,
272                               ARIZONA_RATE_ENUM_SIZE,
273                               arizona_rate_text, arizona_rate_val),
274         SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
275                               ARIZONA_DSP1_RATE_SHIFT, 0xf,
276                               ARIZONA_RATE_ENUM_SIZE,
277                               arizona_rate_text, arizona_rate_val),
278         SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
279                               ARIZONA_DSP1_RATE_SHIFT, 0xf,
280                               ARIZONA_RATE_ENUM_SIZE,
281                               arizona_rate_text, arizona_rate_val),
282         SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
283                               ARIZONA_DSP1_RATE_SHIFT, 0xf,
284                               ARIZONA_RATE_ENUM_SIZE,
285                               arizona_rate_text, arizona_rate_val),
286 };
287
288 const struct snd_kcontrol_new wm_adsp2_fw_controls[] = {
289         SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
290                      wm_adsp_fw_get, wm_adsp_fw_put),
291         SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]),
292         SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
293                      wm_adsp_fw_get, wm_adsp_fw_put),
294         SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]),
295         SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
296                      wm_adsp_fw_get, wm_adsp_fw_put),
297         SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]),
298         SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
299                      wm_adsp_fw_get, wm_adsp_fw_put),
300         SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]),
301 };
302 EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls);
303 #endif
304
305 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
306                                                         int type)
307 {
308         int i;
309
310         for (i = 0; i < dsp->num_mems; i++)
311                 if (dsp->mem[i].type == type)
312                         return &dsp->mem[i];
313
314         return NULL;
315 }
316
317 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region,
318                                           unsigned int offset)
319 {
320         switch (region->type) {
321         case WMFW_ADSP1_PM:
322                 return region->base + (offset * 3);
323         case WMFW_ADSP1_DM:
324                 return region->base + (offset * 2);
325         case WMFW_ADSP2_XM:
326                 return region->base + (offset * 2);
327         case WMFW_ADSP2_YM:
328                 return region->base + (offset * 2);
329         case WMFW_ADSP1_ZM:
330                 return region->base + (offset * 2);
331         default:
332                 WARN_ON(NULL != "Unknown memory region type");
333                 return offset;
334         }
335 }
336
337 static int wm_adsp_load(struct wm_adsp *dsp)
338 {
339         LIST_HEAD(buf_list);
340         const struct firmware *firmware;
341         struct regmap *regmap = dsp->regmap;
342         unsigned int pos = 0;
343         const struct wmfw_header *header;
344         const struct wmfw_adsp1_sizes *adsp1_sizes;
345         const struct wmfw_adsp2_sizes *adsp2_sizes;
346         const struct wmfw_footer *footer;
347         const struct wmfw_region *region;
348         const struct wm_adsp_region *mem;
349         const char *region_name;
350         char *file, *text;
351         struct wm_adsp_buf *buf;
352         unsigned int reg;
353         int regions = 0;
354         int ret, offset, type, sizes;
355
356         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
357         if (file == NULL)
358                 return -ENOMEM;
359
360         snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
361                  wm_adsp_fw[dsp->fw].file);
362         file[PAGE_SIZE - 1] = '\0';
363
364         ret = request_firmware(&firmware, file, dsp->dev);
365         if (ret != 0) {
366                 adsp_err(dsp, "Failed to request '%s'\n", file);
367                 goto out;
368         }
369         ret = -EINVAL;
370
371         pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
372         if (pos >= firmware->size) {
373                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
374                          file, firmware->size);
375                 goto out_fw;
376         }
377
378         header = (void*)&firmware->data[0];
379
380         if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
381                 adsp_err(dsp, "%s: invalid magic\n", file);
382                 goto out_fw;
383         }
384
385         if (header->ver != 0) {
386                 adsp_err(dsp, "%s: unknown file format %d\n",
387                          file, header->ver);
388                 goto out_fw;
389         }
390
391         if (header->core != dsp->type) {
392                 adsp_err(dsp, "%s: invalid core %d != %d\n",
393                          file, header->core, dsp->type);
394                 goto out_fw;
395         }
396
397         switch (dsp->type) {
398         case WMFW_ADSP1:
399                 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
400                 adsp1_sizes = (void *)&(header[1]);
401                 footer = (void *)&(adsp1_sizes[1]);
402                 sizes = sizeof(*adsp1_sizes);
403
404                 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
405                          file, le32_to_cpu(adsp1_sizes->dm),
406                          le32_to_cpu(adsp1_sizes->pm),
407                          le32_to_cpu(adsp1_sizes->zm));
408                 break;
409
410         case WMFW_ADSP2:
411                 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
412                 adsp2_sizes = (void *)&(header[1]);
413                 footer = (void *)&(adsp2_sizes[1]);
414                 sizes = sizeof(*adsp2_sizes);
415
416                 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
417                          file, le32_to_cpu(adsp2_sizes->xm),
418                          le32_to_cpu(adsp2_sizes->ym),
419                          le32_to_cpu(adsp2_sizes->pm),
420                          le32_to_cpu(adsp2_sizes->zm));
421                 break;
422
423         default:
424                 BUG_ON(NULL == "Unknown DSP type");
425                 goto out_fw;
426         }
427
428         if (le32_to_cpu(header->len) != sizeof(*header) +
429             sizes + sizeof(*footer)) {
430                 adsp_err(dsp, "%s: unexpected header length %d\n",
431                          file, le32_to_cpu(header->len));
432                 goto out_fw;
433         }
434
435         adsp_dbg(dsp, "%s: timestamp %llu\n", file,
436                  le64_to_cpu(footer->timestamp));
437
438         while (pos < firmware->size &&
439                pos - firmware->size > sizeof(*region)) {
440                 region = (void *)&(firmware->data[pos]);
441                 region_name = "Unknown";
442                 reg = 0;
443                 text = NULL;
444                 offset = le32_to_cpu(region->offset) & 0xffffff;
445                 type = be32_to_cpu(region->type) & 0xff;
446                 mem = wm_adsp_find_region(dsp, type);
447                 
448                 switch (type) {
449                 case WMFW_NAME_TEXT:
450                         region_name = "Firmware name";
451                         text = kzalloc(le32_to_cpu(region->len) + 1,
452                                        GFP_KERNEL);
453                         break;
454                 case WMFW_INFO_TEXT:
455                         region_name = "Information";
456                         text = kzalloc(le32_to_cpu(region->len) + 1,
457                                        GFP_KERNEL);
458                         break;
459                 case WMFW_ABSOLUTE:
460                         region_name = "Absolute";
461                         reg = offset;
462                         break;
463                 case WMFW_ADSP1_PM:
464                         BUG_ON(!mem);
465                         region_name = "PM";
466                         reg = wm_adsp_region_to_reg(mem, offset);
467                         break;
468                 case WMFW_ADSP1_DM:
469                         BUG_ON(!mem);
470                         region_name = "DM";
471                         reg = wm_adsp_region_to_reg(mem, offset);
472                         break;
473                 case WMFW_ADSP2_XM:
474                         BUG_ON(!mem);
475                         region_name = "XM";
476                         reg = wm_adsp_region_to_reg(mem, offset);
477                         break;
478                 case WMFW_ADSP2_YM:
479                         BUG_ON(!mem);
480                         region_name = "YM";
481                         reg = wm_adsp_region_to_reg(mem, offset);
482                         break;
483                 case WMFW_ADSP1_ZM:
484                         BUG_ON(!mem);
485                         region_name = "ZM";
486                         reg = wm_adsp_region_to_reg(mem, offset);
487                         break;
488                 default:
489                         adsp_warn(dsp,
490                                   "%s.%d: Unknown region type %x at %d(%x)\n",
491                                   file, regions, type, pos, pos);
492                         break;
493                 }
494
495                 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
496                          regions, le32_to_cpu(region->len), offset,
497                          region_name);
498
499                 if (text) {
500                         memcpy(text, region->data, le32_to_cpu(region->len));
501                         adsp_info(dsp, "%s: %s\n", file, text);
502                         kfree(text);
503                 }
504
505                 if (reg) {
506                         buf = wm_adsp_buf_alloc(region->data,
507                                                 le32_to_cpu(region->len),
508                                                 &buf_list);
509                         if (!buf) {
510                                 adsp_err(dsp, "Out of memory\n");
511                                 return -ENOMEM;
512                         }
513
514                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
515                                                      le32_to_cpu(region->len));
516                         if (ret != 0) {
517                                 adsp_err(dsp,
518                                         "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
519                                         file, regions,
520                                         le32_to_cpu(region->len), offset,
521                                         region_name, ret);
522                                 goto out_fw;
523                         }
524                 }
525
526                 pos += le32_to_cpu(region->len) + sizeof(*region);
527                 regions++;
528         }
529
530         ret = regmap_async_complete(regmap);
531         if (ret != 0) {
532                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
533                 goto out_fw;
534         }
535
536         if (pos > firmware->size)
537                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
538                           file, regions, pos - firmware->size);
539
540 out_fw:
541         regmap_async_complete(regmap);
542         wm_adsp_buf_free(&buf_list);
543         release_firmware(firmware);
544 out:
545         kfree(file);
546
547         return ret;
548 }
549
550 static int wm_adsp_setup_algs(struct wm_adsp *dsp)
551 {
552         struct regmap *regmap = dsp->regmap;
553         struct wmfw_adsp1_id_hdr adsp1_id;
554         struct wmfw_adsp2_id_hdr adsp2_id;
555         struct wmfw_adsp1_alg_hdr *adsp1_alg;
556         struct wmfw_adsp2_alg_hdr *adsp2_alg;
557         void *alg, *buf;
558         struct wm_adsp_alg_region *region;
559         const struct wm_adsp_region *mem;
560         unsigned int pos, term;
561         size_t algs, buf_size;
562         __be32 val;
563         int i, ret;
564
565         switch (dsp->type) {
566         case WMFW_ADSP1:
567                 mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
568                 break;
569         case WMFW_ADSP2:
570                 mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
571                 break;
572         default:
573                 mem = NULL;
574                 break;
575         }
576
577         if (mem == NULL) {
578                 BUG_ON(mem != NULL);
579                 return -EINVAL;
580         }
581
582         switch (dsp->type) {
583         case WMFW_ADSP1:
584                 ret = regmap_raw_read(regmap, mem->base, &adsp1_id,
585                                       sizeof(adsp1_id));
586                 if (ret != 0) {
587                         adsp_err(dsp, "Failed to read algorithm info: %d\n",
588                                  ret);
589                         return ret;
590                 }
591
592                 buf = &adsp1_id;
593                 buf_size = sizeof(adsp1_id);
594
595                 algs = be32_to_cpu(adsp1_id.algs);
596                 dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
597                 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
598                           dsp->fw_id,
599                           (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
600                           (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
601                           be32_to_cpu(adsp1_id.fw.ver) & 0xff,
602                           algs);
603
604                 region = kzalloc(sizeof(*region), GFP_KERNEL);
605                 if (!region)
606                         return -ENOMEM;
607                 region->type = WMFW_ADSP1_ZM;
608                 region->alg = be32_to_cpu(adsp1_id.fw.id);
609                 region->base = be32_to_cpu(adsp1_id.zm);
610                 list_add_tail(&region->list, &dsp->alg_regions);
611
612                 region = kzalloc(sizeof(*region), GFP_KERNEL);
613                 if (!region)
614                         return -ENOMEM;
615                 region->type = WMFW_ADSP1_DM;
616                 region->alg = be32_to_cpu(adsp1_id.fw.id);
617                 region->base = be32_to_cpu(adsp1_id.dm);
618                 list_add_tail(&region->list, &dsp->alg_regions);
619
620                 pos = sizeof(adsp1_id) / 2;
621                 term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
622                 break;
623
624         case WMFW_ADSP2:
625                 ret = regmap_raw_read(regmap, mem->base, &adsp2_id,
626                                       sizeof(adsp2_id));
627                 if (ret != 0) {
628                         adsp_err(dsp, "Failed to read algorithm info: %d\n",
629                                  ret);
630                         return ret;
631                 }
632
633                 buf = &adsp2_id;
634                 buf_size = sizeof(adsp2_id);
635
636                 algs = be32_to_cpu(adsp2_id.algs);
637                 dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
638                 adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
639                           dsp->fw_id,
640                           (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
641                           (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
642                           be32_to_cpu(adsp2_id.fw.ver) & 0xff,
643                           algs);
644
645                 region = kzalloc(sizeof(*region), GFP_KERNEL);
646                 if (!region)
647                         return -ENOMEM;
648                 region->type = WMFW_ADSP2_XM;
649                 region->alg = be32_to_cpu(adsp2_id.fw.id);
650                 region->base = be32_to_cpu(adsp2_id.xm);
651                 list_add_tail(&region->list, &dsp->alg_regions);
652
653                 region = kzalloc(sizeof(*region), GFP_KERNEL);
654                 if (!region)
655                         return -ENOMEM;
656                 region->type = WMFW_ADSP2_YM;
657                 region->alg = be32_to_cpu(adsp2_id.fw.id);
658                 region->base = be32_to_cpu(adsp2_id.ym);
659                 list_add_tail(&region->list, &dsp->alg_regions);
660
661                 region = kzalloc(sizeof(*region), GFP_KERNEL);
662                 if (!region)
663                         return -ENOMEM;
664                 region->type = WMFW_ADSP2_ZM;
665                 region->alg = be32_to_cpu(adsp2_id.fw.id);
666                 region->base = be32_to_cpu(adsp2_id.zm);
667                 list_add_tail(&region->list, &dsp->alg_regions);
668
669                 pos = sizeof(adsp2_id) / 2;
670                 term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
671                 break;
672
673         default:
674                 BUG_ON(NULL == "Unknown DSP type");
675                 return -EINVAL;
676         }
677
678         if (algs == 0) {
679                 adsp_err(dsp, "No algorithms\n");
680                 return -EINVAL;
681         }
682
683         if (algs > 1024) {
684                 adsp_err(dsp, "Algorithm count %zx excessive\n", algs);
685                 print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET,
686                                      buf, buf_size);
687                 return -EINVAL;
688         }
689
690         /* Read the terminator first to validate the length */
691         ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
692         if (ret != 0) {
693                 adsp_err(dsp, "Failed to read algorithm list end: %d\n",
694                         ret);
695                 return ret;
696         }
697
698         if (be32_to_cpu(val) != 0xbedead)
699                 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
700                           term, be32_to_cpu(val));
701
702         alg = kzalloc((term - pos) * 2, GFP_KERNEL | GFP_DMA);
703         if (!alg)
704                 return -ENOMEM;
705
706         ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2);
707         if (ret != 0) {
708                 adsp_err(dsp, "Failed to read algorithm list: %d\n",
709                         ret);
710                 goto out;
711         }
712
713         adsp1_alg = alg;
714         adsp2_alg = alg;
715
716         for (i = 0; i < algs; i++) {
717                 switch (dsp->type) {
718                 case WMFW_ADSP1:
719                         adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
720                                   i, be32_to_cpu(adsp1_alg[i].alg.id),
721                                   (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
722                                   (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
723                                   be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
724                                   be32_to_cpu(adsp1_alg[i].dm),
725                                   be32_to_cpu(adsp1_alg[i].zm));
726
727                         region = kzalloc(sizeof(*region), GFP_KERNEL);
728                         if (!region)
729                                 return -ENOMEM;
730                         region->type = WMFW_ADSP1_DM;
731                         region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
732                         region->base = be32_to_cpu(adsp1_alg[i].dm);
733                         list_add_tail(&region->list, &dsp->alg_regions);
734
735                         region = kzalloc(sizeof(*region), GFP_KERNEL);
736                         if (!region)
737                                 return -ENOMEM;
738                         region->type = WMFW_ADSP1_ZM;
739                         region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
740                         region->base = be32_to_cpu(adsp1_alg[i].zm);
741                         list_add_tail(&region->list, &dsp->alg_regions);
742                         break;
743
744                 case WMFW_ADSP2:
745                         adsp_info(dsp,
746                                   "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
747                                   i, be32_to_cpu(adsp2_alg[i].alg.id),
748                                   (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
749                                   (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
750                                   be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
751                                   be32_to_cpu(adsp2_alg[i].xm),
752                                   be32_to_cpu(adsp2_alg[i].ym),
753                                   be32_to_cpu(adsp2_alg[i].zm));
754
755                         region = kzalloc(sizeof(*region), GFP_KERNEL);
756                         if (!region)
757                                 return -ENOMEM;
758                         region->type = WMFW_ADSP2_XM;
759                         region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
760                         region->base = be32_to_cpu(adsp2_alg[i].xm);
761                         list_add_tail(&region->list, &dsp->alg_regions);
762
763                         region = kzalloc(sizeof(*region), GFP_KERNEL);
764                         if (!region)
765                                 return -ENOMEM;
766                         region->type = WMFW_ADSP2_YM;
767                         region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
768                         region->base = be32_to_cpu(adsp2_alg[i].ym);
769                         list_add_tail(&region->list, &dsp->alg_regions);
770
771                         region = kzalloc(sizeof(*region), GFP_KERNEL);
772                         if (!region)
773                                 return -ENOMEM;
774                         region->type = WMFW_ADSP2_ZM;
775                         region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
776                         region->base = be32_to_cpu(adsp2_alg[i].zm);
777                         list_add_tail(&region->list, &dsp->alg_regions);
778                         break;
779                 }
780         }
781
782 out:
783         kfree(alg);
784         return ret;
785 }
786
787 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
788 {
789         LIST_HEAD(buf_list);
790         struct regmap *regmap = dsp->regmap;
791         struct wmfw_coeff_hdr *hdr;
792         struct wmfw_coeff_item *blk;
793         const struct firmware *firmware;
794         const struct wm_adsp_region *mem;
795         struct wm_adsp_alg_region *alg_region;
796         const char *region_name;
797         int ret, pos, blocks, type, offset, reg;
798         char *file;
799         struct wm_adsp_buf *buf;
800         int tmp;
801
802         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
803         if (file == NULL)
804                 return -ENOMEM;
805
806         snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
807                  wm_adsp_fw[dsp->fw].file);
808         file[PAGE_SIZE - 1] = '\0';
809
810         ret = request_firmware(&firmware, file, dsp->dev);
811         if (ret != 0) {
812                 adsp_warn(dsp, "Failed to request '%s'\n", file);
813                 ret = 0;
814                 goto out;
815         }
816         ret = -EINVAL;
817
818         if (sizeof(*hdr) >= firmware->size) {
819                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
820                         file, firmware->size);
821                 goto out_fw;
822         }
823
824         hdr = (void*)&firmware->data[0];
825         if (memcmp(hdr->magic, "WMDR", 4) != 0) {
826                 adsp_err(dsp, "%s: invalid magic\n", file);
827                 goto out_fw;
828         }
829
830         switch (be32_to_cpu(hdr->rev) & 0xff) {
831         case 1:
832                 break;
833         default:
834                 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
835                          file, be32_to_cpu(hdr->rev) & 0xff);
836                 ret = -EINVAL;
837                 goto out_fw;
838         }
839
840         adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
841                 (le32_to_cpu(hdr->ver) >> 16) & 0xff,
842                 (le32_to_cpu(hdr->ver) >>  8) & 0xff,
843                 le32_to_cpu(hdr->ver) & 0xff);
844
845         pos = le32_to_cpu(hdr->len);
846
847         blocks = 0;
848         while (pos < firmware->size &&
849                pos - firmware->size > sizeof(*blk)) {
850                 blk = (void*)(&firmware->data[pos]);
851
852                 type = le16_to_cpu(blk->type);
853                 offset = le16_to_cpu(blk->offset);
854
855                 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
856                          file, blocks, le32_to_cpu(blk->id),
857                          (le32_to_cpu(blk->ver) >> 16) & 0xff,
858                          (le32_to_cpu(blk->ver) >>  8) & 0xff,
859                          le32_to_cpu(blk->ver) & 0xff);
860                 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
861                          file, blocks, le32_to_cpu(blk->len), offset, type);
862
863                 reg = 0;
864                 region_name = "Unknown";
865                 switch (type) {
866                 case (WMFW_NAME_TEXT << 8):
867                 case (WMFW_INFO_TEXT << 8):
868                         break;
869                 case (WMFW_ABSOLUTE << 8):
870                         /*
871                          * Old files may use this for global
872                          * coefficients.
873                          */
874                         if (le32_to_cpu(blk->id) == dsp->fw_id &&
875                             offset == 0) {
876                                 region_name = "global coefficients";
877                                 mem = wm_adsp_find_region(dsp, type);
878                                 if (!mem) {
879                                         adsp_err(dsp, "No ZM\n");
880                                         break;
881                                 }
882                                 reg = wm_adsp_region_to_reg(mem, 0);
883
884                         } else {
885                                 region_name = "register";
886                                 reg = offset;
887                         }
888                         break;
889
890                 case WMFW_ADSP1_DM:
891                 case WMFW_ADSP1_ZM:
892                 case WMFW_ADSP2_XM:
893                 case WMFW_ADSP2_YM:
894                         adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
895                                  file, blocks, le32_to_cpu(blk->len),
896                                  type, le32_to_cpu(blk->id));
897
898                         mem = wm_adsp_find_region(dsp, type);
899                         if (!mem) {
900                                 adsp_err(dsp, "No base for region %x\n", type);
901                                 break;
902                         }
903
904                         reg = 0;
905                         list_for_each_entry(alg_region,
906                                             &dsp->alg_regions, list) {
907                                 if (le32_to_cpu(blk->id) == alg_region->alg &&
908                                     type == alg_region->type) {
909                                         reg = alg_region->base;
910                                         reg = wm_adsp_region_to_reg(mem,
911                                                                     reg);
912                                         reg += offset;
913                                 }
914                         }
915
916                         if (reg == 0)
917                                 adsp_err(dsp, "No %x for algorithm %x\n",
918                                          type, le32_to_cpu(blk->id));
919                         break;
920
921                 default:
922                         adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
923                                  file, blocks, type, pos);
924                         break;
925                 }
926
927                 if (reg) {
928                         buf = wm_adsp_buf_alloc(blk->data,
929                                                 le32_to_cpu(blk->len),
930                                                 &buf_list);
931                         if (!buf) {
932                                 adsp_err(dsp, "Out of memory\n");
933                                 ret = -ENOMEM;
934                                 goto out_fw;
935                         }
936
937                         adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
938                                  file, blocks, le32_to_cpu(blk->len),
939                                  reg);
940                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
941                                                      le32_to_cpu(blk->len));
942                         if (ret != 0) {
943                                 adsp_err(dsp,
944                                         "%s.%d: Failed to write to %x in %s\n",
945                                         file, blocks, reg, region_name);
946                         }
947                 }
948
949                 tmp = le32_to_cpu(blk->len) % 4;
950                 if (tmp)
951                         pos += le32_to_cpu(blk->len) + (4 - tmp) + sizeof(*blk);
952                 else
953                         pos += le32_to_cpu(blk->len) + sizeof(*blk);
954
955                 blocks++;
956         }
957
958         ret = regmap_async_complete(regmap);
959         if (ret != 0)
960                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
961
962         if (pos > firmware->size)
963                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
964                           file, blocks, pos - firmware->size);
965
966 out_fw:
967         release_firmware(firmware);
968         wm_adsp_buf_free(&buf_list);
969 out:
970         kfree(file);
971         return ret;
972 }
973
974 int wm_adsp1_init(struct wm_adsp *adsp)
975 {
976         INIT_LIST_HEAD(&adsp->alg_regions);
977
978         return 0;
979 }
980 EXPORT_SYMBOL_GPL(wm_adsp1_init);
981
982 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
983                    struct snd_kcontrol *kcontrol,
984                    int event)
985 {
986         struct snd_soc_codec *codec = w->codec;
987         struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
988         struct wm_adsp *dsp = &dsps[w->shift];
989         int ret;
990         int val;
991
992         switch (event) {
993         case SND_SOC_DAPM_POST_PMU:
994                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
995                                    ADSP1_SYS_ENA, ADSP1_SYS_ENA);
996
997                 /*
998                  * For simplicity set the DSP clock rate to be the
999                  * SYSCLK rate rather than making it configurable.
1000                  */
1001                 if(dsp->sysclk_reg) {
1002                         ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
1003                         if (ret != 0) {
1004                                 adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
1005                                 ret);
1006                                 return ret;
1007                         }
1008
1009                         val = (val & dsp->sysclk_mask)
1010                                 >> dsp->sysclk_shift;
1011
1012                         ret = regmap_update_bits(dsp->regmap,
1013                                                  dsp->base + ADSP1_CONTROL_31,
1014                                                  ADSP1_CLK_SEL_MASK, val);
1015                         if (ret != 0) {
1016                                 adsp_err(dsp, "Failed to set clock rate: %d\n",
1017                                          ret);
1018                                 return ret;
1019                         }
1020                 }
1021
1022                 ret = wm_adsp_load(dsp);
1023                 if (ret != 0)
1024                         goto err;
1025
1026                 ret = wm_adsp_setup_algs(dsp);
1027                 if (ret != 0)
1028                         goto err;
1029
1030                 ret = wm_adsp_load_coeff(dsp);
1031                 if (ret != 0)
1032                         goto err;
1033
1034                 /* Start the core running */
1035                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1036                                    ADSP1_CORE_ENA | ADSP1_START,
1037                                    ADSP1_CORE_ENA | ADSP1_START);
1038                 break;
1039
1040         case SND_SOC_DAPM_PRE_PMD:
1041                 /* Halt the core */
1042                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1043                                    ADSP1_CORE_ENA | ADSP1_START, 0);
1044
1045                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
1046                                    ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
1047
1048                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1049                                    ADSP1_SYS_ENA, 0);
1050                 break;
1051
1052         default:
1053                 break;
1054         }
1055
1056         return 0;
1057
1058 err:
1059         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1060                            ADSP1_SYS_ENA, 0);
1061         return ret;
1062 }
1063 EXPORT_SYMBOL_GPL(wm_adsp1_event);
1064
1065 static int wm_adsp2_ena(struct wm_adsp *dsp)
1066 {
1067         unsigned int val;
1068         int ret, count;
1069
1070         ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1071                                  ADSP2_SYS_ENA, ADSP2_SYS_ENA);
1072         if (ret != 0)
1073                 return ret;
1074
1075         /* Wait for the RAM to start, should be near instantaneous */
1076         count = 0;
1077         do {
1078                 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
1079                                   &val);
1080                 if (ret != 0)
1081                         return ret;
1082         } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
1083
1084         if (!(val & ADSP2_RAM_RDY)) {
1085                 adsp_err(dsp, "Failed to start DSP RAM\n");
1086                 return -EBUSY;
1087         }
1088
1089         adsp_dbg(dsp, "RAM ready after %d polls\n", count);
1090         adsp_info(dsp, "RAM ready after %d polls\n", count);
1091
1092         return 0;
1093 }
1094
1095 int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1096                    struct snd_kcontrol *kcontrol, int event)
1097 {
1098         struct snd_soc_codec *codec = w->codec;
1099         struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1100         struct wm_adsp *dsp = &dsps[w->shift];
1101         struct wm_adsp_alg_region *alg_region;
1102         unsigned int val;
1103         int ret;
1104
1105         switch (event) {
1106         case SND_SOC_DAPM_POST_PMU:
1107                 /*
1108                  * For simplicity set the DSP clock rate to be the
1109                  * SYSCLK rate rather than making it configurable.
1110                  */
1111                 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
1112                 if (ret != 0) {
1113                         adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
1114                                  ret);
1115                         return ret;
1116                 }
1117                 val = (val & ARIZONA_SYSCLK_FREQ_MASK)
1118                         >> ARIZONA_SYSCLK_FREQ_SHIFT;
1119
1120                 ret = regmap_update_bits(dsp->regmap,
1121                                          dsp->base + ADSP2_CLOCKING,
1122                                          ADSP2_CLK_SEL_MASK, val);
1123                 if (ret != 0) {
1124                         adsp_err(dsp, "Failed to set clock rate: %d\n",
1125                                  ret);
1126                         return ret;
1127                 }
1128
1129                 if (dsp->dvfs) {
1130                         ret = regmap_read(dsp->regmap,
1131                                           dsp->base + ADSP2_CLOCKING, &val);
1132                         if (ret != 0) {
1133                                 dev_err(dsp->dev,
1134                                         "Failed to read clocking: %d\n", ret);
1135                                 return ret;
1136                         }
1137
1138                         if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
1139                                 ret = regulator_enable(dsp->dvfs);
1140                                 if (ret != 0) {
1141                                         dev_err(dsp->dev,
1142                                                 "Failed to enable supply: %d\n",
1143                                                 ret);
1144                                         return ret;
1145                                 }
1146
1147                                 ret = regulator_set_voltage(dsp->dvfs,
1148                                                             1800000,
1149                                                             1800000);
1150                                 if (ret != 0) {
1151                                         dev_err(dsp->dev,
1152                                                 "Failed to raise supply: %d\n",
1153                                                 ret);
1154                                         return ret;
1155                                 }
1156                         }
1157                 }
1158
1159                 ret = wm_adsp2_ena(dsp);
1160                 if (ret != 0)
1161                         return ret;
1162
1163                 ret = wm_adsp_load(dsp);
1164                 if (ret != 0)
1165                         goto err;
1166
1167                 ret = wm_adsp_setup_algs(dsp);
1168                 if (ret != 0)
1169                         goto err;
1170
1171                 ret = wm_adsp_load_coeff(dsp);
1172                 if (ret != 0)
1173                         goto err;
1174
1175                 ret = regmap_update_bits(dsp->regmap,
1176                                          dsp->base + ADSP2_CONTROL,
1177                                          ADSP2_CORE_ENA | ADSP2_START,
1178                                          ADSP2_CORE_ENA | ADSP2_START);
1179                 if (ret != 0)
1180                         goto err;
1181
1182                 dsp->running = true;
1183                 break;
1184
1185         case SND_SOC_DAPM_PRE_PMD:
1186                 dsp->running = false;
1187
1188                 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1189                                    ADSP2_SYS_ENA | ADSP2_CORE_ENA |
1190                                    ADSP2_START, 0);
1191
1192                 /* Make sure DMAs are quiesced */
1193                 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
1194                 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
1195                 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
1196
1197                 if (dsp->dvfs) {
1198                         ret = regulator_set_voltage(dsp->dvfs, 1200000,
1199                                                     1800000);
1200                         if (ret != 0)
1201                                 dev_warn(dsp->dev,
1202                                          "Failed to lower supply: %d\n",
1203                                          ret);
1204
1205                         ret = regulator_disable(dsp->dvfs);
1206                         if (ret != 0)
1207                                 dev_err(dsp->dev,
1208                                         "Failed to enable supply: %d\n",
1209                                         ret);
1210                 }
1211
1212                 while (!list_empty(&dsp->alg_regions)) {
1213                         alg_region = list_first_entry(&dsp->alg_regions,
1214                                                       struct wm_adsp_alg_region,
1215                                                       list);
1216                         list_del(&alg_region->list);
1217                         kfree(alg_region);
1218                 }
1219                 break;
1220
1221         default:
1222                 break;
1223         }
1224
1225         return 0;
1226 err:
1227         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1228                            ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
1229         return ret;
1230 }
1231 EXPORT_SYMBOL_GPL(wm_adsp2_event);
1232
1233 int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
1234 {
1235         int ret;
1236
1237         /*
1238          * Disable the DSP memory by default when in reset for a small
1239          * power saving.
1240          */
1241         ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
1242                                  ADSP2_MEM_ENA, 0);
1243         if (ret != 0) {
1244                 adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
1245                 return ret;
1246         }
1247
1248         INIT_LIST_HEAD(&adsp->alg_regions);
1249
1250         if (dvfs) {
1251                 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
1252                 if (IS_ERR(adsp->dvfs)) {
1253                         ret = PTR_ERR(adsp->dvfs);
1254                         dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
1255                         return ret;
1256                 }
1257
1258                 ret = regulator_enable(adsp->dvfs);
1259                 if (ret != 0) {
1260                         dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
1261                                 ret);
1262                         return ret;
1263                 }
1264
1265                 ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
1266                 if (ret != 0) {
1267                         dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
1268                                 ret);
1269                         return ret;
1270                 }
1271
1272                 ret = regulator_disable(adsp->dvfs);
1273                 if (ret != 0) {
1274                         dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
1275                                 ret);
1276                         return ret;
1277                 }
1278         }
1279
1280         return 0;
1281 }
1282 EXPORT_SYMBOL_GPL(wm_adsp2_init);