ASoC: wm_adsp: Correct region base typo in wm_halo_setup_algs
[sfrench/cifs-2.6.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/ctype.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/init.h>
17 #include <linux/delay.h>
18 #include <linux/firmware.h>
19 #include <linux/list.h>
20 #include <linux/pm.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/regmap.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/slab.h>
25 #include <linux/vmalloc.h>
26 #include <linux/workqueue.h>
27 #include <linux/debugfs.h>
28 #include <sound/core.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/soc.h>
32 #include <sound/jack.h>
33 #include <sound/initval.h>
34 #include <sound/tlv.h>
35
36 #include "wm_adsp.h"
37
38 #define adsp_crit(_dsp, fmt, ...) \
39         dev_crit(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
40 #define adsp_err(_dsp, fmt, ...) \
41         dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
42 #define adsp_warn(_dsp, fmt, ...) \
43         dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
44 #define adsp_info(_dsp, fmt, ...) \
45         dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
46 #define adsp_dbg(_dsp, fmt, ...) \
47         dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
48
49 #define compr_err(_obj, fmt, ...) \
50         adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
51                  ##__VA_ARGS__)
52 #define compr_dbg(_obj, fmt, ...) \
53         adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
54                  ##__VA_ARGS__)
55
56 #define ADSP1_CONTROL_1                   0x00
57 #define ADSP1_CONTROL_2                   0x02
58 #define ADSP1_CONTROL_3                   0x03
59 #define ADSP1_CONTROL_4                   0x04
60 #define ADSP1_CONTROL_5                   0x06
61 #define ADSP1_CONTROL_6                   0x07
62 #define ADSP1_CONTROL_7                   0x08
63 #define ADSP1_CONTROL_8                   0x09
64 #define ADSP1_CONTROL_9                   0x0A
65 #define ADSP1_CONTROL_10                  0x0B
66 #define ADSP1_CONTROL_11                  0x0C
67 #define ADSP1_CONTROL_12                  0x0D
68 #define ADSP1_CONTROL_13                  0x0F
69 #define ADSP1_CONTROL_14                  0x10
70 #define ADSP1_CONTROL_15                  0x11
71 #define ADSP1_CONTROL_16                  0x12
72 #define ADSP1_CONTROL_17                  0x13
73 #define ADSP1_CONTROL_18                  0x14
74 #define ADSP1_CONTROL_19                  0x16
75 #define ADSP1_CONTROL_20                  0x17
76 #define ADSP1_CONTROL_21                  0x18
77 #define ADSP1_CONTROL_22                  0x1A
78 #define ADSP1_CONTROL_23                  0x1B
79 #define ADSP1_CONTROL_24                  0x1C
80 #define ADSP1_CONTROL_25                  0x1E
81 #define ADSP1_CONTROL_26                  0x20
82 #define ADSP1_CONTROL_27                  0x21
83 #define ADSP1_CONTROL_28                  0x22
84 #define ADSP1_CONTROL_29                  0x23
85 #define ADSP1_CONTROL_30                  0x24
86 #define ADSP1_CONTROL_31                  0x26
87
88 /*
89  * ADSP1 Control 19
90  */
91 #define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
92 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
93 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
94
95
96 /*
97  * ADSP1 Control 30
98  */
99 #define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
100 #define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
101 #define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
102 #define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
103 #define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
104 #define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
105 #define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
106 #define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
107 #define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
108 #define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
109 #define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
110 #define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
111 #define ADSP1_START                       0x0001  /* DSP1_START */
112 #define ADSP1_START_MASK                  0x0001  /* DSP1_START */
113 #define ADSP1_START_SHIFT                      0  /* DSP1_START */
114 #define ADSP1_START_WIDTH                      1  /* DSP1_START */
115
116 /*
117  * ADSP1 Control 31
118  */
119 #define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
120 #define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
121 #define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
122
123 #define ADSP2_CONTROL                     0x0
124 #define ADSP2_CLOCKING                    0x1
125 #define ADSP2V2_CLOCKING                  0x2
126 #define ADSP2_STATUS1                     0x4
127 #define ADSP2_WDMA_CONFIG_1               0x30
128 #define ADSP2_WDMA_CONFIG_2               0x31
129 #define ADSP2V2_WDMA_CONFIG_2             0x32
130 #define ADSP2_RDMA_CONFIG_1               0x34
131
132 #define ADSP2_SCRATCH0                    0x40
133 #define ADSP2_SCRATCH1                    0x41
134 #define ADSP2_SCRATCH2                    0x42
135 #define ADSP2_SCRATCH3                    0x43
136
137 #define ADSP2V2_SCRATCH0_1                0x40
138 #define ADSP2V2_SCRATCH2_3                0x42
139
140 /*
141  * ADSP2 Control
142  */
143
144 #define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
145 #define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
146 #define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
147 #define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
148 #define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
149 #define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
150 #define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
151 #define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
152 #define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
153 #define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
154 #define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
155 #define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
156 #define ADSP2_START                       0x0001  /* DSP1_START */
157 #define ADSP2_START_MASK                  0x0001  /* DSP1_START */
158 #define ADSP2_START_SHIFT                      0  /* DSP1_START */
159 #define ADSP2_START_WIDTH                      1  /* DSP1_START */
160
161 /*
162  * ADSP2 clocking
163  */
164 #define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
165 #define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
166 #define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
167
168 /*
169  * ADSP2V2 clocking
170  */
171 #define ADSP2V2_CLK_SEL_MASK             0x70000  /* CLK_SEL_ENA */
172 #define ADSP2V2_CLK_SEL_SHIFT                 16  /* CLK_SEL_ENA */
173 #define ADSP2V2_CLK_SEL_WIDTH                  3  /* CLK_SEL_ENA */
174
175 #define ADSP2V2_RATE_MASK                 0x7800  /* DSP_RATE */
176 #define ADSP2V2_RATE_SHIFT                    11  /* DSP_RATE */
177 #define ADSP2V2_RATE_WIDTH                     4  /* DSP_RATE */
178
179 /*
180  * ADSP2 Status 1
181  */
182 #define ADSP2_RAM_RDY                     0x0001
183 #define ADSP2_RAM_RDY_MASK                0x0001
184 #define ADSP2_RAM_RDY_SHIFT                    0
185 #define ADSP2_RAM_RDY_WIDTH                    1
186
187 /*
188  * ADSP2 Lock support
189  */
190 #define ADSP2_LOCK_CODE_0                    0x5555
191 #define ADSP2_LOCK_CODE_1                    0xAAAA
192
193 #define ADSP2_WATCHDOG                       0x0A
194 #define ADSP2_BUS_ERR_ADDR                   0x52
195 #define ADSP2_REGION_LOCK_STATUS             0x64
196 #define ADSP2_LOCK_REGION_1_LOCK_REGION_0    0x66
197 #define ADSP2_LOCK_REGION_3_LOCK_REGION_2    0x68
198 #define ADSP2_LOCK_REGION_5_LOCK_REGION_4    0x6A
199 #define ADSP2_LOCK_REGION_7_LOCK_REGION_6    0x6C
200 #define ADSP2_LOCK_REGION_9_LOCK_REGION_8    0x6E
201 #define ADSP2_LOCK_REGION_CTRL               0x7A
202 #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR    0x7C
203
204 #define ADSP2_REGION_LOCK_ERR_MASK           0x8000
205 #define ADSP2_SLAVE_ERR_MASK                 0x4000
206 #define ADSP2_WDT_TIMEOUT_STS_MASK           0x2000
207 #define ADSP2_CTRL_ERR_PAUSE_ENA             0x0002
208 #define ADSP2_CTRL_ERR_EINT                  0x0001
209
210 #define ADSP2_BUS_ERR_ADDR_MASK              0x00FFFFFF
211 #define ADSP2_XMEM_ERR_ADDR_MASK             0x0000FFFF
212 #define ADSP2_PMEM_ERR_ADDR_MASK             0x7FFF0000
213 #define ADSP2_PMEM_ERR_ADDR_SHIFT            16
214 #define ADSP2_WDT_ENA_MASK                   0xFFFFFFFD
215
216 #define ADSP2_LOCK_REGION_SHIFT              16
217
218 #define ADSP_MAX_STD_CTRL_SIZE               512
219
220 #define WM_ADSP_ACKED_CTL_TIMEOUT_MS         100
221 #define WM_ADSP_ACKED_CTL_N_QUICKPOLLS       10
222 #define WM_ADSP_ACKED_CTL_MIN_VALUE          0
223 #define WM_ADSP_ACKED_CTL_MAX_VALUE          0xFFFFFF
224
225 /*
226  * Event control messages
227  */
228 #define WM_ADSP_FW_EVENT_SHUTDOWN            0x000001
229
230 /*
231  * HALO system info
232  */
233 #define HALO_AHBM_WINDOW_DEBUG_0             0x02040
234 #define HALO_AHBM_WINDOW_DEBUG_1             0x02044
235
236 /*
237  * HALO core
238  */
239 #define HALO_SCRATCH1                        0x005c0
240 #define HALO_SCRATCH2                        0x005c8
241 #define HALO_SCRATCH3                        0x005d0
242 #define HALO_SCRATCH4                        0x005d8
243 #define HALO_CCM_CORE_CONTROL                0x41000
244 #define HALO_CORE_SOFT_RESET                 0x00010
245 #define HALO_WDT_CONTROL                     0x47000
246
247 /*
248  * HALO MPU banks
249  */
250 #define HALO_MPU_XMEM_ACCESS_0               0x43000
251 #define HALO_MPU_YMEM_ACCESS_0               0x43004
252 #define HALO_MPU_WINDOW_ACCESS_0             0x43008
253 #define HALO_MPU_XREG_ACCESS_0               0x4300C
254 #define HALO_MPU_YREG_ACCESS_0               0x43014
255 #define HALO_MPU_XMEM_ACCESS_1               0x43018
256 #define HALO_MPU_YMEM_ACCESS_1               0x4301C
257 #define HALO_MPU_WINDOW_ACCESS_1             0x43020
258 #define HALO_MPU_XREG_ACCESS_1               0x43024
259 #define HALO_MPU_YREG_ACCESS_1               0x4302C
260 #define HALO_MPU_XMEM_ACCESS_2               0x43030
261 #define HALO_MPU_YMEM_ACCESS_2               0x43034
262 #define HALO_MPU_WINDOW_ACCESS_2             0x43038
263 #define HALO_MPU_XREG_ACCESS_2               0x4303C
264 #define HALO_MPU_YREG_ACCESS_2               0x43044
265 #define HALO_MPU_XMEM_ACCESS_3               0x43048
266 #define HALO_MPU_YMEM_ACCESS_3               0x4304C
267 #define HALO_MPU_WINDOW_ACCESS_3             0x43050
268 #define HALO_MPU_XREG_ACCESS_3               0x43054
269 #define HALO_MPU_YREG_ACCESS_3               0x4305C
270 #define HALO_MPU_XM_VIO_ADDR                 0x43100
271 #define HALO_MPU_XM_VIO_STATUS               0x43104
272 #define HALO_MPU_YM_VIO_ADDR                 0x43108
273 #define HALO_MPU_YM_VIO_STATUS               0x4310C
274 #define HALO_MPU_PM_VIO_ADDR                 0x43110
275 #define HALO_MPU_PM_VIO_STATUS               0x43114
276 #define HALO_MPU_LOCK_CONFIG                 0x43140
277
278 /*
279  * HALO_AHBM_WINDOW_DEBUG_1
280  */
281 #define HALO_AHBM_CORE_ERR_ADDR_MASK         0x0fffff00
282 #define HALO_AHBM_CORE_ERR_ADDR_SHIFT                 8
283 #define HALO_AHBM_FLAGS_ERR_MASK             0x000000ff
284
285 /*
286  * HALO_CCM_CORE_CONTROL
287  */
288 #define HALO_CORE_EN                        0x00000001
289
290 /*
291  * HALO_CORE_SOFT_RESET
292  */
293 #define HALO_CORE_SOFT_RESET_MASK           0x00000001
294
295 /*
296  * HALO_WDT_CONTROL
297  */
298 #define HALO_WDT_EN_MASK                    0x00000001
299
300 /*
301  * HALO_MPU_?M_VIO_STATUS
302  */
303 #define HALO_MPU_VIO_STS_MASK               0x007e0000
304 #define HALO_MPU_VIO_STS_SHIFT                      17
305 #define HALO_MPU_VIO_ERR_WR_MASK            0x00008000
306 #define HALO_MPU_VIO_ERR_SRC_MASK           0x00007fff
307 #define HALO_MPU_VIO_ERR_SRC_SHIFT                   0
308
309 static struct wm_adsp_ops wm_adsp1_ops;
310 static struct wm_adsp_ops wm_adsp2_ops[];
311 static struct wm_adsp_ops wm_halo_ops;
312
313 struct wm_adsp_buf {
314         struct list_head list;
315         void *buf;
316 };
317
318 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
319                                              struct list_head *list)
320 {
321         struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
322
323         if (buf == NULL)
324                 return NULL;
325
326         buf->buf = vmalloc(len);
327         if (!buf->buf) {
328                 kfree(buf);
329                 return NULL;
330         }
331         memcpy(buf->buf, src, len);
332
333         if (list)
334                 list_add_tail(&buf->list, list);
335
336         return buf;
337 }
338
339 static void wm_adsp_buf_free(struct list_head *list)
340 {
341         while (!list_empty(list)) {
342                 struct wm_adsp_buf *buf = list_first_entry(list,
343                                                            struct wm_adsp_buf,
344                                                            list);
345                 list_del(&buf->list);
346                 vfree(buf->buf);
347                 kfree(buf);
348         }
349 }
350
351 #define WM_ADSP_FW_MBC_VSS  0
352 #define WM_ADSP_FW_HIFI     1
353 #define WM_ADSP_FW_TX       2
354 #define WM_ADSP_FW_TX_SPK   3
355 #define WM_ADSP_FW_RX       4
356 #define WM_ADSP_FW_RX_ANC   5
357 #define WM_ADSP_FW_CTRL     6
358 #define WM_ADSP_FW_ASR      7
359 #define WM_ADSP_FW_TRACE    8
360 #define WM_ADSP_FW_SPK_PROT 9
361 #define WM_ADSP_FW_MISC     10
362
363 #define WM_ADSP_NUM_FW      11
364
365 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
366         [WM_ADSP_FW_MBC_VSS] =  "MBC/VSS",
367         [WM_ADSP_FW_HIFI] =     "MasterHiFi",
368         [WM_ADSP_FW_TX] =       "Tx",
369         [WM_ADSP_FW_TX_SPK] =   "Tx Speaker",
370         [WM_ADSP_FW_RX] =       "Rx",
371         [WM_ADSP_FW_RX_ANC] =   "Rx ANC",
372         [WM_ADSP_FW_CTRL] =     "Voice Ctrl",
373         [WM_ADSP_FW_ASR] =      "ASR Assist",
374         [WM_ADSP_FW_TRACE] =    "Dbg Trace",
375         [WM_ADSP_FW_SPK_PROT] = "Protection",
376         [WM_ADSP_FW_MISC] =     "Misc",
377 };
378
379 struct wm_adsp_system_config_xm_hdr {
380         __be32 sys_enable;
381         __be32 fw_id;
382         __be32 fw_rev;
383         __be32 boot_status;
384         __be32 watchdog;
385         __be32 dma_buffer_size;
386         __be32 rdma[6];
387         __be32 wdma[8];
388         __be32 build_job_name[3];
389         __be32 build_job_number;
390 };
391
392 struct wm_halo_system_config_xm_hdr {
393         __be32 halo_heartbeat;
394         __be32 build_job_name[3];
395         __be32 build_job_number;
396 };
397
398 struct wm_adsp_alg_xm_struct {
399         __be32 magic;
400         __be32 smoothing;
401         __be32 threshold;
402         __be32 host_buf_ptr;
403         __be32 start_seq;
404         __be32 high_water_mark;
405         __be32 low_water_mark;
406         __be64 smoothed_power;
407 };
408
409 struct wm_adsp_host_buf_coeff_v1 {
410         __be32 host_buf_ptr;            /* Host buffer pointer */
411         __be32 versions;                /* Version numbers */
412         __be32 name[4];                 /* The buffer name */
413 };
414
415 struct wm_adsp_buffer {
416         __be32 buf1_base;               /* Base addr of first buffer area */
417         __be32 buf1_size;               /* Size of buf1 area in DSP words */
418         __be32 buf2_base;               /* Base addr of 2nd buffer area */
419         __be32 buf1_buf2_size;          /* Size of buf1+buf2 in DSP words */
420         __be32 buf3_base;               /* Base addr of buf3 area */
421         __be32 buf_total_size;          /* Size of buf1+buf2+buf3 in DSP words */
422         __be32 high_water_mark;         /* Point at which IRQ is asserted */
423         __be32 irq_count;               /* bits 1-31 count IRQ assertions */
424         __be32 irq_ack;                 /* acked IRQ count, bit 0 enables IRQ */
425         __be32 next_write_index;        /* word index of next write */
426         __be32 next_read_index;         /* word index of next read */
427         __be32 error;                   /* error if any */
428         __be32 oldest_block_index;      /* word index of oldest surviving */
429         __be32 requested_rewind;        /* how many blocks rewind was done */
430         __be32 reserved_space;          /* internal */
431         __be32 min_free;                /* min free space since stream start */
432         __be32 blocks_written[2];       /* total blocks written (64 bit) */
433         __be32 words_written[2];        /* total words written (64 bit) */
434 };
435
436 struct wm_adsp_compr;
437
438 struct wm_adsp_compr_buf {
439         struct list_head list;
440         struct wm_adsp *dsp;
441         struct wm_adsp_compr *compr;
442
443         struct wm_adsp_buffer_region *regions;
444         u32 host_buf_ptr;
445
446         u32 error;
447         u32 irq_count;
448         int read_index;
449         int avail;
450         int host_buf_mem_type;
451
452         char *name;
453 };
454
455 struct wm_adsp_compr {
456         struct list_head list;
457         struct wm_adsp *dsp;
458         struct wm_adsp_compr_buf *buf;
459
460         struct snd_compr_stream *stream;
461         struct snd_compressed_buffer size;
462
463         u32 *raw_buf;
464         unsigned int copied_total;
465
466         unsigned int sample_rate;
467
468         const char *name;
469 };
470
471 #define WM_ADSP_DATA_WORD_SIZE         3
472
473 #define WM_ADSP_MIN_FRAGMENTS          1
474 #define WM_ADSP_MAX_FRAGMENTS          256
475 #define WM_ADSP_MIN_FRAGMENT_SIZE      (64 * WM_ADSP_DATA_WORD_SIZE)
476 #define WM_ADSP_MAX_FRAGMENT_SIZE      (4096 * WM_ADSP_DATA_WORD_SIZE)
477
478 #define WM_ADSP_ALG_XM_STRUCT_MAGIC    0x49aec7
479
480 #define HOST_BUFFER_FIELD(field) \
481         (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
482
483 #define ALG_XM_FIELD(field) \
484         (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
485
486 #define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER     1
487
488 #define HOST_BUF_COEFF_COMPAT_VER_MASK          0xFF00
489 #define HOST_BUF_COEFF_COMPAT_VER_SHIFT         8
490
491 static int wm_adsp_buffer_init(struct wm_adsp *dsp);
492 static int wm_adsp_buffer_free(struct wm_adsp *dsp);
493
494 struct wm_adsp_buffer_region {
495         unsigned int offset;
496         unsigned int cumulative_size;
497         unsigned int mem_type;
498         unsigned int base_addr;
499 };
500
501 struct wm_adsp_buffer_region_def {
502         unsigned int mem_type;
503         unsigned int base_offset;
504         unsigned int size_offset;
505 };
506
507 static const struct wm_adsp_buffer_region_def default_regions[] = {
508         {
509                 .mem_type = WMFW_ADSP2_XM,
510                 .base_offset = HOST_BUFFER_FIELD(buf1_base),
511                 .size_offset = HOST_BUFFER_FIELD(buf1_size),
512         },
513         {
514                 .mem_type = WMFW_ADSP2_XM,
515                 .base_offset = HOST_BUFFER_FIELD(buf2_base),
516                 .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size),
517         },
518         {
519                 .mem_type = WMFW_ADSP2_YM,
520                 .base_offset = HOST_BUFFER_FIELD(buf3_base),
521                 .size_offset = HOST_BUFFER_FIELD(buf_total_size),
522         },
523 };
524
525 struct wm_adsp_fw_caps {
526         u32 id;
527         struct snd_codec_desc desc;
528         int num_regions;
529         const struct wm_adsp_buffer_region_def *region_defs;
530 };
531
532 static const struct wm_adsp_fw_caps ctrl_caps[] = {
533         {
534                 .id = SND_AUDIOCODEC_BESPOKE,
535                 .desc = {
536                         .max_ch = 8,
537                         .sample_rates = { 16000 },
538                         .num_sample_rates = 1,
539                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
540                 },
541                 .num_regions = ARRAY_SIZE(default_regions),
542                 .region_defs = default_regions,
543         },
544 };
545
546 static const struct wm_adsp_fw_caps trace_caps[] = {
547         {
548                 .id = SND_AUDIOCODEC_BESPOKE,
549                 .desc = {
550                         .max_ch = 8,
551                         .sample_rates = {
552                                 4000, 8000, 11025, 12000, 16000, 22050,
553                                 24000, 32000, 44100, 48000, 64000, 88200,
554                                 96000, 176400, 192000
555                         },
556                         .num_sample_rates = 15,
557                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
558                 },
559                 .num_regions = ARRAY_SIZE(default_regions),
560                 .region_defs = default_regions,
561         },
562 };
563
564 static const struct {
565         const char *file;
566         int compr_direction;
567         int num_caps;
568         const struct wm_adsp_fw_caps *caps;
569         bool voice_trigger;
570 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
571         [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
572         [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
573         [WM_ADSP_FW_TX] =       { .file = "tx" },
574         [WM_ADSP_FW_TX_SPK] =   { .file = "tx-spk" },
575         [WM_ADSP_FW_RX] =       { .file = "rx" },
576         [WM_ADSP_FW_RX_ANC] =   { .file = "rx-anc" },
577         [WM_ADSP_FW_CTRL] =     {
578                 .file = "ctrl",
579                 .compr_direction = SND_COMPRESS_CAPTURE,
580                 .num_caps = ARRAY_SIZE(ctrl_caps),
581                 .caps = ctrl_caps,
582                 .voice_trigger = true,
583         },
584         [WM_ADSP_FW_ASR] =      { .file = "asr" },
585         [WM_ADSP_FW_TRACE] =    {
586                 .file = "trace",
587                 .compr_direction = SND_COMPRESS_CAPTURE,
588                 .num_caps = ARRAY_SIZE(trace_caps),
589                 .caps = trace_caps,
590         },
591         [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
592         [WM_ADSP_FW_MISC] =     { .file = "misc" },
593 };
594
595 struct wm_coeff_ctl_ops {
596         int (*xget)(struct snd_kcontrol *kcontrol,
597                     struct snd_ctl_elem_value *ucontrol);
598         int (*xput)(struct snd_kcontrol *kcontrol,
599                     struct snd_ctl_elem_value *ucontrol);
600 };
601
602 struct wm_coeff_ctl {
603         const char *name;
604         const char *fw_name;
605         struct wm_adsp_alg_region alg_region;
606         struct wm_coeff_ctl_ops ops;
607         struct wm_adsp *dsp;
608         unsigned int enabled:1;
609         struct list_head list;
610         void *cache;
611         unsigned int offset;
612         size_t len;
613         unsigned int set:1;
614         struct soc_bytes_ext bytes_ext;
615         unsigned int flags;
616         unsigned int type;
617 };
618
619 static const char *wm_adsp_mem_region_name(unsigned int type)
620 {
621         switch (type) {
622         case WMFW_ADSP1_PM:
623                 return "PM";
624         case WMFW_HALO_PM_PACKED:
625                 return "PM_PACKED";
626         case WMFW_ADSP1_DM:
627                 return "DM";
628         case WMFW_ADSP2_XM:
629                 return "XM";
630         case WMFW_HALO_XM_PACKED:
631                 return "XM_PACKED";
632         case WMFW_ADSP2_YM:
633                 return "YM";
634         case WMFW_HALO_YM_PACKED:
635                 return "YM_PACKED";
636         case WMFW_ADSP1_ZM:
637                 return "ZM";
638         default:
639                 return NULL;
640         }
641 }
642
643 #ifdef CONFIG_DEBUG_FS
644 static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
645 {
646         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
647
648         kfree(dsp->wmfw_file_name);
649         dsp->wmfw_file_name = tmp;
650 }
651
652 static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
653 {
654         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
655
656         kfree(dsp->bin_file_name);
657         dsp->bin_file_name = tmp;
658 }
659
660 static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
661 {
662         kfree(dsp->wmfw_file_name);
663         kfree(dsp->bin_file_name);
664         dsp->wmfw_file_name = NULL;
665         dsp->bin_file_name = NULL;
666 }
667
668 static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
669                                          char __user *user_buf,
670                                          size_t count, loff_t *ppos)
671 {
672         struct wm_adsp *dsp = file->private_data;
673         ssize_t ret;
674
675         mutex_lock(&dsp->pwr_lock);
676
677         if (!dsp->wmfw_file_name || !dsp->booted)
678                 ret = 0;
679         else
680                 ret = simple_read_from_buffer(user_buf, count, ppos,
681                                               dsp->wmfw_file_name,
682                                               strlen(dsp->wmfw_file_name));
683
684         mutex_unlock(&dsp->pwr_lock);
685         return ret;
686 }
687
688 static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
689                                         char __user *user_buf,
690                                         size_t count, loff_t *ppos)
691 {
692         struct wm_adsp *dsp = file->private_data;
693         ssize_t ret;
694
695         mutex_lock(&dsp->pwr_lock);
696
697         if (!dsp->bin_file_name || !dsp->booted)
698                 ret = 0;
699         else
700                 ret = simple_read_from_buffer(user_buf, count, ppos,
701                                               dsp->bin_file_name,
702                                               strlen(dsp->bin_file_name));
703
704         mutex_unlock(&dsp->pwr_lock);
705         return ret;
706 }
707
708 static const struct {
709         const char *name;
710         const struct file_operations fops;
711 } wm_adsp_debugfs_fops[] = {
712         {
713                 .name = "wmfw_file_name",
714                 .fops = {
715                         .open = simple_open,
716                         .read = wm_adsp_debugfs_wmfw_read,
717                 },
718         },
719         {
720                 .name = "bin_file_name",
721                 .fops = {
722                         .open = simple_open,
723                         .read = wm_adsp_debugfs_bin_read,
724                 },
725         },
726 };
727
728 static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
729                                   struct snd_soc_component *component)
730 {
731         struct dentry *root = NULL;
732         int i;
733
734         if (!component->debugfs_root) {
735                 adsp_err(dsp, "No codec debugfs root\n");
736                 goto err;
737         }
738
739         root = debugfs_create_dir(dsp->name, component->debugfs_root);
740
741         if (!root)
742                 goto err;
743
744         if (!debugfs_create_bool("booted", 0444, root, &dsp->booted))
745                 goto err;
746
747         if (!debugfs_create_bool("running", 0444, root, &dsp->running))
748                 goto err;
749
750         if (!debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id))
751                 goto err;
752
753         if (!debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version))
754                 goto err;
755
756         for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
757                 if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
758                                          0444, root, dsp,
759                                          &wm_adsp_debugfs_fops[i].fops))
760                         goto err;
761         }
762
763         dsp->debugfs_root = root;
764         return;
765
766 err:
767         debugfs_remove_recursive(root);
768         adsp_err(dsp, "Failed to create debugfs\n");
769 }
770
771 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
772 {
773         wm_adsp_debugfs_clear(dsp);
774         debugfs_remove_recursive(dsp->debugfs_root);
775 }
776 #else
777 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
778                                          struct snd_soc_component *component)
779 {
780 }
781
782 static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
783 {
784 }
785
786 static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp,
787                                                  const char *s)
788 {
789 }
790
791 static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp,
792                                                 const char *s)
793 {
794 }
795
796 static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
797 {
798 }
799 #endif
800
801 int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
802                    struct snd_ctl_elem_value *ucontrol)
803 {
804         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
805         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
806         struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
807
808         ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
809
810         return 0;
811 }
812 EXPORT_SYMBOL_GPL(wm_adsp_fw_get);
813
814 int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
815                    struct snd_ctl_elem_value *ucontrol)
816 {
817         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
818         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
819         struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
820         int ret = 0;
821
822         if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
823                 return 0;
824
825         if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
826                 return -EINVAL;
827
828         mutex_lock(&dsp[e->shift_l].pwr_lock);
829
830         if (dsp[e->shift_l].booted || !list_empty(&dsp[e->shift_l].compr_list))
831                 ret = -EBUSY;
832         else
833                 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
834
835         mutex_unlock(&dsp[e->shift_l].pwr_lock);
836
837         return ret;
838 }
839 EXPORT_SYMBOL_GPL(wm_adsp_fw_put);
840
841 const struct soc_enum wm_adsp_fw_enum[] = {
842         SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
843         SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
844         SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
845         SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
846         SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
847         SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
848         SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
849 };
850 EXPORT_SYMBOL_GPL(wm_adsp_fw_enum);
851
852 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
853                                                         int type)
854 {
855         int i;
856
857         for (i = 0; i < dsp->num_mems; i++)
858                 if (dsp->mem[i].type == type)
859                         return &dsp->mem[i];
860
861         return NULL;
862 }
863
864 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
865                                           unsigned int offset)
866 {
867         switch (mem->type) {
868         case WMFW_ADSP1_PM:
869                 return mem->base + (offset * 3);
870         case WMFW_ADSP1_DM:
871         case WMFW_ADSP2_XM:
872         case WMFW_ADSP2_YM:
873         case WMFW_ADSP1_ZM:
874                 return mem->base + (offset * 2);
875         default:
876                 WARN(1, "Unknown memory region type");
877                 return offset;
878         }
879 }
880
881 static unsigned int wm_halo_region_to_reg(struct wm_adsp_region const *mem,
882                                           unsigned int offset)
883 {
884         switch (mem->type) {
885         case WMFW_ADSP2_XM:
886         case WMFW_ADSP2_YM:
887                 return mem->base + (offset * 4);
888         case WMFW_HALO_XM_PACKED:
889         case WMFW_HALO_YM_PACKED:
890                 return (mem->base + (offset * 3)) & ~0x3;
891         case WMFW_HALO_PM_PACKED:
892                 return mem->base + (offset * 5);
893         default:
894                 WARN(1, "Unknown memory region type");
895                 return offset;
896         }
897 }
898
899 static void wm_adsp_read_fw_status(struct wm_adsp *dsp,
900                                    int noffs, unsigned int *offs)
901 {
902         unsigned int i;
903         int ret;
904
905         for (i = 0; i < noffs; ++i) {
906                 ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]);
907                 if (ret) {
908                         adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
909                         return;
910                 }
911         }
912 }
913
914 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
915 {
916         unsigned int offs[] = {
917                 ADSP2_SCRATCH0, ADSP2_SCRATCH1, ADSP2_SCRATCH2, ADSP2_SCRATCH3,
918         };
919
920         wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
921
922         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
923                  offs[0], offs[1], offs[2], offs[3]);
924 }
925
926 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp)
927 {
928         unsigned int offs[] = { ADSP2V2_SCRATCH0_1, ADSP2V2_SCRATCH2_3 };
929
930         wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
931
932         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
933                  offs[0] & 0xFFFF, offs[0] >> 16,
934                  offs[1] & 0xFFFF, offs[1] >> 16);
935 }
936
937 static void wm_halo_show_fw_status(struct wm_adsp *dsp)
938 {
939         unsigned int offs[] = {
940                 HALO_SCRATCH1, HALO_SCRATCH2, HALO_SCRATCH3, HALO_SCRATCH4,
941         };
942
943         wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
944
945         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
946                  offs[0], offs[1], offs[2], offs[3]);
947 }
948
949 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
950 {
951         return container_of(ext, struct wm_coeff_ctl, bytes_ext);
952 }
953
954 static int wm_coeff_base_reg(struct wm_coeff_ctl *ctl, unsigned int *reg)
955 {
956         const struct wm_adsp_alg_region *alg_region = &ctl->alg_region;
957         struct wm_adsp *dsp = ctl->dsp;
958         const struct wm_adsp_region *mem;
959
960         mem = wm_adsp_find_region(dsp, alg_region->type);
961         if (!mem) {
962                 adsp_err(dsp, "No base for region %x\n",
963                          alg_region->type);
964                 return -EINVAL;
965         }
966
967         *reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset);
968
969         return 0;
970 }
971
972 static int wm_coeff_info(struct snd_kcontrol *kctl,
973                          struct snd_ctl_elem_info *uinfo)
974 {
975         struct soc_bytes_ext *bytes_ext =
976                 (struct soc_bytes_ext *)kctl->private_value;
977         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
978
979         switch (ctl->type) {
980         case WMFW_CTL_TYPE_ACKED:
981                 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
982                 uinfo->value.integer.min = WM_ADSP_ACKED_CTL_MIN_VALUE;
983                 uinfo->value.integer.max = WM_ADSP_ACKED_CTL_MAX_VALUE;
984                 uinfo->value.integer.step = 1;
985                 uinfo->count = 1;
986                 break;
987         default:
988                 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
989                 uinfo->count = ctl->len;
990                 break;
991         }
992
993         return 0;
994 }
995
996 static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
997                                         unsigned int event_id)
998 {
999         struct wm_adsp *dsp = ctl->dsp;
1000         u32 val = cpu_to_be32(event_id);
1001         unsigned int reg;
1002         int i, ret;
1003
1004         ret = wm_coeff_base_reg(ctl, &reg);
1005         if (ret)
1006                 return ret;
1007
1008         adsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n",
1009                  event_id, ctl->alg_region.alg,
1010                  wm_adsp_mem_region_name(ctl->alg_region.type), ctl->offset);
1011
1012         ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
1013         if (ret) {
1014                 adsp_err(dsp, "Failed to write %x: %d\n", reg, ret);
1015                 return ret;
1016         }
1017
1018         /*
1019          * Poll for ack, we initially poll at ~1ms intervals for firmwares
1020          * that respond quickly, then go to ~10ms polls. A firmware is unlikely
1021          * to ack instantly so we do the first 1ms delay before reading the
1022          * control to avoid a pointless bus transaction
1023          */
1024         for (i = 0; i < WM_ADSP_ACKED_CTL_TIMEOUT_MS;) {
1025                 switch (i) {
1026                 case 0 ... WM_ADSP_ACKED_CTL_N_QUICKPOLLS - 1:
1027                         usleep_range(1000, 2000);
1028                         i++;
1029                         break;
1030                 default:
1031                         usleep_range(10000, 20000);
1032                         i += 10;
1033                         break;
1034                 }
1035
1036                 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
1037                 if (ret) {
1038                         adsp_err(dsp, "Failed to read %x: %d\n", reg, ret);
1039                         return ret;
1040                 }
1041
1042                 if (val == 0) {
1043                         adsp_dbg(dsp, "Acked control ACKED at poll %u\n", i);
1044                         return 0;
1045                 }
1046         }
1047
1048         adsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n",
1049                   reg, ctl->alg_region.alg,
1050                   wm_adsp_mem_region_name(ctl->alg_region.type),
1051                   ctl->offset);
1052
1053         return -ETIMEDOUT;
1054 }
1055
1056 static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
1057                                   const void *buf, size_t len)
1058 {
1059         struct wm_adsp *dsp = ctl->dsp;
1060         void *scratch;
1061         int ret;
1062         unsigned int reg;
1063
1064         ret = wm_coeff_base_reg(ctl, &reg);
1065         if (ret)
1066                 return ret;
1067
1068         scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
1069         if (!scratch)
1070                 return -ENOMEM;
1071
1072         ret = regmap_raw_write(dsp->regmap, reg, scratch,
1073                                len);
1074         if (ret) {
1075                 adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
1076                          len, reg, ret);
1077                 kfree(scratch);
1078                 return ret;
1079         }
1080         adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
1081
1082         kfree(scratch);
1083
1084         return 0;
1085 }
1086
1087 static int wm_coeff_put(struct snd_kcontrol *kctl,
1088                         struct snd_ctl_elem_value *ucontrol)
1089 {
1090         struct soc_bytes_ext *bytes_ext =
1091                 (struct soc_bytes_ext *)kctl->private_value;
1092         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1093         char *p = ucontrol->value.bytes.data;
1094         int ret = 0;
1095
1096         mutex_lock(&ctl->dsp->pwr_lock);
1097
1098         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1099                 ret = -EPERM;
1100         else
1101                 memcpy(ctl->cache, p, ctl->len);
1102
1103         ctl->set = 1;
1104         if (ctl->enabled && ctl->dsp->running)
1105                 ret = wm_coeff_write_control(ctl, p, ctl->len);
1106
1107         mutex_unlock(&ctl->dsp->pwr_lock);
1108
1109         return ret;
1110 }
1111
1112 static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
1113                             const unsigned int __user *bytes, unsigned int size)
1114 {
1115         struct soc_bytes_ext *bytes_ext =
1116                 (struct soc_bytes_ext *)kctl->private_value;
1117         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1118         int ret = 0;
1119
1120         mutex_lock(&ctl->dsp->pwr_lock);
1121
1122         if (copy_from_user(ctl->cache, bytes, size)) {
1123                 ret = -EFAULT;
1124         } else {
1125                 ctl->set = 1;
1126                 if (ctl->enabled && ctl->dsp->running)
1127                         ret = wm_coeff_write_control(ctl, ctl->cache, size);
1128                 else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1129                         ret = -EPERM;
1130         }
1131
1132         mutex_unlock(&ctl->dsp->pwr_lock);
1133
1134         return ret;
1135 }
1136
1137 static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
1138                               struct snd_ctl_elem_value *ucontrol)
1139 {
1140         struct soc_bytes_ext *bytes_ext =
1141                 (struct soc_bytes_ext *)kctl->private_value;
1142         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1143         unsigned int val = ucontrol->value.integer.value[0];
1144         int ret;
1145
1146         if (val == 0)
1147                 return 0;       /* 0 means no event */
1148
1149         mutex_lock(&ctl->dsp->pwr_lock);
1150
1151         if (ctl->enabled && ctl->dsp->running)
1152                 ret = wm_coeff_write_acked_control(ctl, val);
1153         else
1154                 ret = -EPERM;
1155
1156         mutex_unlock(&ctl->dsp->pwr_lock);
1157
1158         return ret;
1159 }
1160
1161 static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
1162                                  void *buf, size_t len)
1163 {
1164         struct wm_adsp *dsp = ctl->dsp;
1165         void *scratch;
1166         int ret;
1167         unsigned int reg;
1168
1169         ret = wm_coeff_base_reg(ctl, &reg);
1170         if (ret)
1171                 return ret;
1172
1173         scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
1174         if (!scratch)
1175                 return -ENOMEM;
1176
1177         ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
1178         if (ret) {
1179                 adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
1180                          len, reg, ret);
1181                 kfree(scratch);
1182                 return ret;
1183         }
1184         adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
1185
1186         memcpy(buf, scratch, len);
1187         kfree(scratch);
1188
1189         return 0;
1190 }
1191
1192 static int wm_coeff_get(struct snd_kcontrol *kctl,
1193                         struct snd_ctl_elem_value *ucontrol)
1194 {
1195         struct soc_bytes_ext *bytes_ext =
1196                 (struct soc_bytes_ext *)kctl->private_value;
1197         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1198         char *p = ucontrol->value.bytes.data;
1199         int ret = 0;
1200
1201         mutex_lock(&ctl->dsp->pwr_lock);
1202
1203         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1204                 if (ctl->enabled && ctl->dsp->running)
1205                         ret = wm_coeff_read_control(ctl, p, ctl->len);
1206                 else
1207                         ret = -EPERM;
1208         } else {
1209                 if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1210                         ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1211
1212                 memcpy(p, ctl->cache, ctl->len);
1213         }
1214
1215         mutex_unlock(&ctl->dsp->pwr_lock);
1216
1217         return ret;
1218 }
1219
1220 static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
1221                             unsigned int __user *bytes, unsigned int size)
1222 {
1223         struct soc_bytes_ext *bytes_ext =
1224                 (struct soc_bytes_ext *)kctl->private_value;
1225         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1226         int ret = 0;
1227
1228         mutex_lock(&ctl->dsp->pwr_lock);
1229
1230         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1231                 if (ctl->enabled && ctl->dsp->running)
1232                         ret = wm_coeff_read_control(ctl, ctl->cache, size);
1233                 else
1234                         ret = -EPERM;
1235         } else {
1236                 if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1237                         ret = wm_coeff_read_control(ctl, ctl->cache, size);
1238         }
1239
1240         if (!ret && copy_to_user(bytes, ctl->cache, size))
1241                 ret = -EFAULT;
1242
1243         mutex_unlock(&ctl->dsp->pwr_lock);
1244
1245         return ret;
1246 }
1247
1248 static int wm_coeff_get_acked(struct snd_kcontrol *kcontrol,
1249                               struct snd_ctl_elem_value *ucontrol)
1250 {
1251         /*
1252          * Although it's not useful to read an acked control, we must satisfy
1253          * user-side assumptions that all controls are readable and that a
1254          * write of the same value should be filtered out (it's valid to send
1255          * the same event number again to the firmware). We therefore return 0,
1256          * meaning "no event" so valid event numbers will always be a change
1257          */
1258         ucontrol->value.integer.value[0] = 0;
1259
1260         return 0;
1261 }
1262
1263 struct wmfw_ctl_work {
1264         struct wm_adsp *dsp;
1265         struct wm_coeff_ctl *ctl;
1266         struct work_struct work;
1267 };
1268
1269 static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
1270 {
1271         unsigned int out, rd, wr, vol;
1272
1273         if (len > ADSP_MAX_STD_CTRL_SIZE) {
1274                 rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1275                 wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
1276                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
1277
1278                 out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
1279         } else {
1280                 rd = SNDRV_CTL_ELEM_ACCESS_READ;
1281                 wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
1282                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
1283
1284                 out = 0;
1285         }
1286
1287         if (in) {
1288                 if (in & WMFW_CTL_FLAG_READABLE)
1289                         out |= rd;
1290                 if (in & WMFW_CTL_FLAG_WRITEABLE)
1291                         out |= wr;
1292                 if (in & WMFW_CTL_FLAG_VOLATILE)
1293                         out |= vol;
1294         } else {
1295                 out |= rd | wr | vol;
1296         }
1297
1298         return out;
1299 }
1300
1301 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
1302 {
1303         struct snd_kcontrol_new *kcontrol;
1304         int ret;
1305
1306         if (!ctl || !ctl->name)
1307                 return -EINVAL;
1308
1309         kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
1310         if (!kcontrol)
1311                 return -ENOMEM;
1312
1313         kcontrol->name = ctl->name;
1314         kcontrol->info = wm_coeff_info;
1315         kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1316         kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
1317         kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
1318         kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len);
1319
1320         switch (ctl->type) {
1321         case WMFW_CTL_TYPE_ACKED:
1322                 kcontrol->get = wm_coeff_get_acked;
1323                 kcontrol->put = wm_coeff_put_acked;
1324                 break;
1325         default:
1326                 if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1327                         ctl->bytes_ext.max = ctl->len;
1328                         ctl->bytes_ext.get = wm_coeff_tlv_get;
1329                         ctl->bytes_ext.put = wm_coeff_tlv_put;
1330                 } else {
1331                         kcontrol->get = wm_coeff_get;
1332                         kcontrol->put = wm_coeff_put;
1333                 }
1334                 break;
1335         }
1336
1337         ret = snd_soc_add_component_controls(dsp->component, kcontrol, 1);
1338         if (ret < 0)
1339                 goto err_kcontrol;
1340
1341         kfree(kcontrol);
1342
1343         return 0;
1344
1345 err_kcontrol:
1346         kfree(kcontrol);
1347         return ret;
1348 }
1349
1350 static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
1351 {
1352         struct wm_coeff_ctl *ctl;
1353         int ret;
1354
1355         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1356                 if (!ctl->enabled || ctl->set)
1357                         continue;
1358                 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1359                         continue;
1360
1361                 /*
1362                  * For readable controls populate the cache from the DSP memory.
1363                  * For non-readable controls the cache was zero-filled when
1364                  * created so we don't need to do anything.
1365                  */
1366                 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
1367                         ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1368                         if (ret < 0)
1369                                 return ret;
1370                 }
1371         }
1372
1373         return 0;
1374 }
1375
1376 static int wm_coeff_sync_controls(struct wm_adsp *dsp)
1377 {
1378         struct wm_coeff_ctl *ctl;
1379         int ret;
1380
1381         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1382                 if (!ctl->enabled)
1383                         continue;
1384                 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
1385                         ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
1386                         if (ret < 0)
1387                                 return ret;
1388                 }
1389         }
1390
1391         return 0;
1392 }
1393
1394 static void wm_adsp_signal_event_controls(struct wm_adsp *dsp,
1395                                           unsigned int event)
1396 {
1397         struct wm_coeff_ctl *ctl;
1398         int ret;
1399
1400         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1401                 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT)
1402                         continue;
1403
1404                 if (!ctl->enabled)
1405                         continue;
1406
1407                 ret = wm_coeff_write_acked_control(ctl, event);
1408                 if (ret)
1409                         adsp_warn(dsp,
1410                                   "Failed to send 0x%x event to alg 0x%x (%d)\n",
1411                                   event, ctl->alg_region.alg, ret);
1412         }
1413 }
1414
1415 static void wm_adsp_ctl_work(struct work_struct *work)
1416 {
1417         struct wmfw_ctl_work *ctl_work = container_of(work,
1418                                                       struct wmfw_ctl_work,
1419                                                       work);
1420
1421         wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl);
1422         kfree(ctl_work);
1423 }
1424
1425 static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl)
1426 {
1427         kfree(ctl->cache);
1428         kfree(ctl->name);
1429         kfree(ctl);
1430 }
1431
1432 static int wm_adsp_create_control(struct wm_adsp *dsp,
1433                                   const struct wm_adsp_alg_region *alg_region,
1434                                   unsigned int offset, unsigned int len,
1435                                   const char *subname, unsigned int subname_len,
1436                                   unsigned int flags, unsigned int type)
1437 {
1438         struct wm_coeff_ctl *ctl;
1439         struct wmfw_ctl_work *ctl_work;
1440         char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1441         const char *region_name;
1442         int ret;
1443
1444         region_name = wm_adsp_mem_region_name(alg_region->type);
1445         if (!region_name) {
1446                 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type);
1447                 return -EINVAL;
1448         }
1449
1450         switch (dsp->fw_ver) {
1451         case 0:
1452         case 1:
1453                 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x",
1454                          dsp->name, region_name, alg_region->alg);
1455                 subname = NULL; /* don't append subname */
1456                 break;
1457         case 2:
1458                 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1459                                 "%s%c %.12s %x", dsp->name, *region_name,
1460                                 wm_adsp_fw_text[dsp->fw], alg_region->alg);
1461                 break;
1462         default:
1463                 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1464                                 "%s %.12s %x", dsp->name,
1465                                 wm_adsp_fw_text[dsp->fw], alg_region->alg);
1466                 break;
1467         }
1468
1469         if (subname) {
1470                 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
1471                 int skip = 0;
1472
1473                 if (dsp->component->name_prefix)
1474                         avail -= strlen(dsp->component->name_prefix) + 1;
1475
1476                 /* Truncate the subname from the start if it is too long */
1477                 if (subname_len > avail)
1478                         skip = subname_len - avail;
1479
1480                 snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
1481                          " %.*s", subname_len - skip, subname + skip);
1482         }
1483
1484         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1485                 if (!strcmp(ctl->name, name)) {
1486                         if (!ctl->enabled)
1487                                 ctl->enabled = 1;
1488                         return 0;
1489                 }
1490         }
1491
1492         ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
1493         if (!ctl)
1494                 return -ENOMEM;
1495         ctl->fw_name = wm_adsp_fw_text[dsp->fw];
1496         ctl->alg_region = *alg_region;
1497         ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
1498         if (!ctl->name) {
1499                 ret = -ENOMEM;
1500                 goto err_ctl;
1501         }
1502         ctl->enabled = 1;
1503         ctl->set = 0;
1504         ctl->ops.xget = wm_coeff_get;
1505         ctl->ops.xput = wm_coeff_put;
1506         ctl->dsp = dsp;
1507
1508         ctl->flags = flags;
1509         ctl->type = type;
1510         ctl->offset = offset;
1511         ctl->len = len;
1512         ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
1513         if (!ctl->cache) {
1514                 ret = -ENOMEM;
1515                 goto err_ctl_name;
1516         }
1517
1518         list_add(&ctl->list, &dsp->ctl_list);
1519
1520         if (flags & WMFW_CTL_FLAG_SYS)
1521                 return 0;
1522
1523         ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
1524         if (!ctl_work) {
1525                 ret = -ENOMEM;
1526                 goto err_ctl_cache;
1527         }
1528
1529         ctl_work->dsp = dsp;
1530         ctl_work->ctl = ctl;
1531         INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
1532         schedule_work(&ctl_work->work);
1533
1534         return 0;
1535
1536 err_ctl_cache:
1537         kfree(ctl->cache);
1538 err_ctl_name:
1539         kfree(ctl->name);
1540 err_ctl:
1541         kfree(ctl);
1542
1543         return ret;
1544 }
1545
1546 struct wm_coeff_parsed_alg {
1547         int id;
1548         const u8 *name;
1549         int name_len;
1550         int ncoeff;
1551 };
1552
1553 struct wm_coeff_parsed_coeff {
1554         int offset;
1555         int mem_type;
1556         const u8 *name;
1557         int name_len;
1558         int ctl_type;
1559         int flags;
1560         int len;
1561 };
1562
1563 static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1564 {
1565         int length;
1566
1567         switch (bytes) {
1568         case 1:
1569                 length = **pos;
1570                 break;
1571         case 2:
1572                 length = le16_to_cpu(*((__le16 *)*pos));
1573                 break;
1574         default:
1575                 return 0;
1576         }
1577
1578         if (str)
1579                 *str = *pos + bytes;
1580
1581         *pos += ((length + bytes) + 3) & ~0x03;
1582
1583         return length;
1584 }
1585
1586 static int wm_coeff_parse_int(int bytes, const u8 **pos)
1587 {
1588         int val = 0;
1589
1590         switch (bytes) {
1591         case 2:
1592                 val = le16_to_cpu(*((__le16 *)*pos));
1593                 break;
1594         case 4:
1595                 val = le32_to_cpu(*((__le32 *)*pos));
1596                 break;
1597         default:
1598                 break;
1599         }
1600
1601         *pos += bytes;
1602
1603         return val;
1604 }
1605
1606 static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data,
1607                                       struct wm_coeff_parsed_alg *blk)
1608 {
1609         const struct wmfw_adsp_alg_data *raw;
1610
1611         switch (dsp->fw_ver) {
1612         case 0:
1613         case 1:
1614                 raw = (const struct wmfw_adsp_alg_data *)*data;
1615                 *data = raw->data;
1616
1617                 blk->id = le32_to_cpu(raw->id);
1618                 blk->name = raw->name;
1619                 blk->name_len = strlen(raw->name);
1620                 blk->ncoeff = le32_to_cpu(raw->ncoeff);
1621                 break;
1622         default:
1623                 blk->id = wm_coeff_parse_int(sizeof(raw->id), data);
1624                 blk->name_len = wm_coeff_parse_string(sizeof(u8), data,
1625                                                       &blk->name);
1626                 wm_coeff_parse_string(sizeof(u16), data, NULL);
1627                 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data);
1628                 break;
1629         }
1630
1631         adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
1632         adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
1633         adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1634 }
1635
1636 static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
1637                                         struct wm_coeff_parsed_coeff *blk)
1638 {
1639         const struct wmfw_adsp_coeff_data *raw;
1640         const u8 *tmp;
1641         int length;
1642
1643         switch (dsp->fw_ver) {
1644         case 0:
1645         case 1:
1646                 raw = (const struct wmfw_adsp_coeff_data *)*data;
1647                 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
1648
1649                 blk->offset = le16_to_cpu(raw->hdr.offset);
1650                 blk->mem_type = le16_to_cpu(raw->hdr.type);
1651                 blk->name = raw->name;
1652                 blk->name_len = strlen(raw->name);
1653                 blk->ctl_type = le16_to_cpu(raw->ctl_type);
1654                 blk->flags = le16_to_cpu(raw->flags);
1655                 blk->len = le32_to_cpu(raw->len);
1656                 break;
1657         default:
1658                 tmp = *data;
1659                 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
1660                 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
1661                 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
1662                 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp,
1663                                                       &blk->name);
1664                 wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
1665                 wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
1666                 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
1667                 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
1668                 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
1669
1670                 *data = *data + sizeof(raw->hdr) + length;
1671                 break;
1672         }
1673
1674         adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
1675         adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
1676         adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name);
1677         adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
1678         adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
1679         adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1680 }
1681
1682 static int wm_adsp_check_coeff_flags(struct wm_adsp *dsp,
1683                                 const struct wm_coeff_parsed_coeff *coeff_blk,
1684                                 unsigned int f_required,
1685                                 unsigned int f_illegal)
1686 {
1687         if ((coeff_blk->flags & f_illegal) ||
1688             ((coeff_blk->flags & f_required) != f_required)) {
1689                 adsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n",
1690                          coeff_blk->flags, coeff_blk->ctl_type);
1691                 return -EINVAL;
1692         }
1693
1694         return 0;
1695 }
1696
1697 static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
1698                                const struct wmfw_region *region)
1699 {
1700         struct wm_adsp_alg_region alg_region = {};
1701         struct wm_coeff_parsed_alg alg_blk;
1702         struct wm_coeff_parsed_coeff coeff_blk;
1703         const u8 *data = region->data;
1704         int i, ret;
1705
1706         wm_coeff_parse_alg(dsp, &data, &alg_blk);
1707         for (i = 0; i < alg_blk.ncoeff; i++) {
1708                 wm_coeff_parse_coeff(dsp, &data, &coeff_blk);
1709
1710                 switch (coeff_blk.ctl_type) {
1711                 case SNDRV_CTL_ELEM_TYPE_BYTES:
1712                         break;
1713                 case WMFW_CTL_TYPE_ACKED:
1714                         if (coeff_blk.flags & WMFW_CTL_FLAG_SYS)
1715                                 continue;       /* ignore */
1716
1717                         ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
1718                                                 WMFW_CTL_FLAG_VOLATILE |
1719                                                 WMFW_CTL_FLAG_WRITEABLE |
1720                                                 WMFW_CTL_FLAG_READABLE,
1721                                                 0);
1722                         if (ret)
1723                                 return -EINVAL;
1724                         break;
1725                 case WMFW_CTL_TYPE_HOSTEVENT:
1726                         ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
1727                                                 WMFW_CTL_FLAG_SYS |
1728                                                 WMFW_CTL_FLAG_VOLATILE |
1729                                                 WMFW_CTL_FLAG_WRITEABLE |
1730                                                 WMFW_CTL_FLAG_READABLE,
1731                                                 0);
1732                         if (ret)
1733                                 return -EINVAL;
1734                         break;
1735                 case WMFW_CTL_TYPE_HOST_BUFFER:
1736                         ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
1737                                                 WMFW_CTL_FLAG_SYS |
1738                                                 WMFW_CTL_FLAG_VOLATILE |
1739                                                 WMFW_CTL_FLAG_READABLE,
1740                                                 0);
1741                         if (ret)
1742                                 return -EINVAL;
1743                         break;
1744                 default:
1745                         adsp_err(dsp, "Unknown control type: %d\n",
1746                                  coeff_blk.ctl_type);
1747                         return -EINVAL;
1748                 }
1749
1750                 alg_region.type = coeff_blk.mem_type;
1751                 alg_region.alg = alg_blk.id;
1752
1753                 ret = wm_adsp_create_control(dsp, &alg_region,
1754                                              coeff_blk.offset,
1755                                              coeff_blk.len,
1756                                              coeff_blk.name,
1757                                              coeff_blk.name_len,
1758                                              coeff_blk.flags,
1759                                              coeff_blk.ctl_type);
1760                 if (ret < 0)
1761                         adsp_err(dsp, "Failed to create control: %.*s, %d\n",
1762                                  coeff_blk.name_len, coeff_blk.name, ret);
1763         }
1764
1765         return 0;
1766 }
1767
1768 static unsigned int wm_adsp1_parse_sizes(struct wm_adsp *dsp,
1769                                          const char * const file,
1770                                          unsigned int pos,
1771                                          const struct firmware *firmware)
1772 {
1773         const struct wmfw_adsp1_sizes *adsp1_sizes;
1774
1775         adsp1_sizes = (void *)&firmware->data[pos];
1776
1777         adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
1778                  le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
1779                  le32_to_cpu(adsp1_sizes->zm));
1780
1781         return pos + sizeof(*adsp1_sizes);
1782 }
1783
1784 static unsigned int wm_adsp2_parse_sizes(struct wm_adsp *dsp,
1785                                          const char * const file,
1786                                          unsigned int pos,
1787                                          const struct firmware *firmware)
1788 {
1789         const struct wmfw_adsp2_sizes *adsp2_sizes;
1790
1791         adsp2_sizes = (void *)&firmware->data[pos];
1792
1793         adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
1794                  le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
1795                  le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm));
1796
1797         return pos + sizeof(*adsp2_sizes);
1798 }
1799
1800 static bool wm_adsp_validate_version(struct wm_adsp *dsp, unsigned int version)
1801 {
1802         switch (version) {
1803         case 0:
1804                 adsp_warn(dsp, "Deprecated file format %d\n", version);
1805                 return true;
1806         case 1:
1807         case 2:
1808                 return true;
1809         default:
1810                 return false;
1811         }
1812 }
1813
1814 static bool wm_halo_validate_version(struct wm_adsp *dsp, unsigned int version)
1815 {
1816         switch (version) {
1817         case 3:
1818                 return true;
1819         default:
1820                 return false;
1821         }
1822 }
1823
1824 static int wm_adsp_load(struct wm_adsp *dsp)
1825 {
1826         LIST_HEAD(buf_list);
1827         const struct firmware *firmware;
1828         struct regmap *regmap = dsp->regmap;
1829         unsigned int pos = 0;
1830         const struct wmfw_header *header;
1831         const struct wmfw_adsp1_sizes *adsp1_sizes;
1832         const struct wmfw_footer *footer;
1833         const struct wmfw_region *region;
1834         const struct wm_adsp_region *mem;
1835         const char *region_name;
1836         char *file, *text = NULL;
1837         struct wm_adsp_buf *buf;
1838         unsigned int reg;
1839         int regions = 0;
1840         int ret, offset, type;
1841
1842         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1843         if (file == NULL)
1844                 return -ENOMEM;
1845
1846         snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name,
1847                  wm_adsp_fw[dsp->fw].file);
1848         file[PAGE_SIZE - 1] = '\0';
1849
1850         ret = request_firmware(&firmware, file, dsp->dev);
1851         if (ret != 0) {
1852                 adsp_err(dsp, "Failed to request '%s'\n", file);
1853                 goto out;
1854         }
1855         ret = -EINVAL;
1856
1857         pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1858         if (pos >= firmware->size) {
1859                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
1860                          file, firmware->size);
1861                 goto out_fw;
1862         }
1863
1864         header = (void *)&firmware->data[0];
1865
1866         if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
1867                 adsp_err(dsp, "%s: invalid magic\n", file);
1868                 goto out_fw;
1869         }
1870
1871         if (!dsp->ops->validate_version(dsp, header->ver)) {
1872                 adsp_err(dsp, "%s: unknown file format %d\n",
1873                          file, header->ver);
1874                 goto out_fw;
1875         }
1876
1877         adsp_info(dsp, "Firmware version: %d\n", header->ver);
1878         dsp->fw_ver = header->ver;
1879
1880         if (header->core != dsp->type) {
1881                 adsp_err(dsp, "%s: invalid core %d != %d\n",
1882                          file, header->core, dsp->type);
1883                 goto out_fw;
1884         }
1885
1886         pos = sizeof(*header);
1887         pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
1888
1889         footer = (void *)&firmware->data[pos];
1890         pos += sizeof(*footer);
1891
1892         if (le32_to_cpu(header->len) != pos) {
1893                 adsp_err(dsp, "%s: unexpected header length %d\n",
1894                          file, le32_to_cpu(header->len));
1895                 goto out_fw;
1896         }
1897
1898         adsp_dbg(dsp, "%s: timestamp %llu\n", file,
1899                  le64_to_cpu(footer->timestamp));
1900
1901         while (pos < firmware->size &&
1902                sizeof(*region) < firmware->size - pos) {
1903                 region = (void *)&(firmware->data[pos]);
1904                 region_name = "Unknown";
1905                 reg = 0;
1906                 text = NULL;
1907                 offset = le32_to_cpu(region->offset) & 0xffffff;
1908                 type = be32_to_cpu(region->type) & 0xff;
1909
1910                 switch (type) {
1911                 case WMFW_NAME_TEXT:
1912                         region_name = "Firmware name";
1913                         text = kzalloc(le32_to_cpu(region->len) + 1,
1914                                        GFP_KERNEL);
1915                         break;
1916                 case WMFW_ALGORITHM_DATA:
1917                         region_name = "Algorithm";
1918                         ret = wm_adsp_parse_coeff(dsp, region);
1919                         if (ret != 0)
1920                                 goto out_fw;
1921                         break;
1922                 case WMFW_INFO_TEXT:
1923                         region_name = "Information";
1924                         text = kzalloc(le32_to_cpu(region->len) + 1,
1925                                        GFP_KERNEL);
1926                         break;
1927                 case WMFW_ABSOLUTE:
1928                         region_name = "Absolute";
1929                         reg = offset;
1930                         break;
1931                 case WMFW_ADSP1_PM:
1932                 case WMFW_ADSP1_DM:
1933                 case WMFW_ADSP2_XM:
1934                 case WMFW_ADSP2_YM:
1935                 case WMFW_ADSP1_ZM:
1936                 case WMFW_HALO_PM_PACKED:
1937                 case WMFW_HALO_XM_PACKED:
1938                 case WMFW_HALO_YM_PACKED:
1939                         mem = wm_adsp_find_region(dsp, type);
1940                         if (!mem) {
1941                                 adsp_err(dsp, "No region of type: %x\n", type);
1942                                 goto out_fw;
1943                         }
1944
1945                         region_name = wm_adsp_mem_region_name(type);
1946                         reg = dsp->ops->region_to_reg(mem, offset);
1947                         break;
1948                 default:
1949                         adsp_warn(dsp,
1950                                   "%s.%d: Unknown region type %x at %d(%x)\n",
1951                                   file, regions, type, pos, pos);
1952                         break;
1953                 }
1954
1955                 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
1956                          regions, le32_to_cpu(region->len), offset,
1957                          region_name);
1958
1959                 if (le32_to_cpu(region->len) >
1960                     firmware->size - pos - sizeof(*region)) {
1961                         adsp_err(dsp,
1962                                  "%s.%d: %s region len %d bytes exceeds file length %zu\n",
1963                                  file, regions, region_name,
1964                                  le32_to_cpu(region->len), firmware->size);
1965                         ret = -EINVAL;
1966                         goto out_fw;
1967                 }
1968
1969                 if (text) {
1970                         memcpy(text, region->data, le32_to_cpu(region->len));
1971                         adsp_info(dsp, "%s: %s\n", file, text);
1972                         kfree(text);
1973                         text = NULL;
1974                 }
1975
1976                 if (reg) {
1977                         buf = wm_adsp_buf_alloc(region->data,
1978                                                 le32_to_cpu(region->len),
1979                                                 &buf_list);
1980                         if (!buf) {
1981                                 adsp_err(dsp, "Out of memory\n");
1982                                 ret = -ENOMEM;
1983                                 goto out_fw;
1984                         }
1985
1986                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
1987                                                      le32_to_cpu(region->len));
1988                         if (ret != 0) {
1989                                 adsp_err(dsp,
1990                                         "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
1991                                         file, regions,
1992                                         le32_to_cpu(region->len), offset,
1993                                         region_name, ret);
1994                                 goto out_fw;
1995                         }
1996                 }
1997
1998                 pos += le32_to_cpu(region->len) + sizeof(*region);
1999                 regions++;
2000         }
2001
2002         ret = regmap_async_complete(regmap);
2003         if (ret != 0) {
2004                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
2005                 goto out_fw;
2006         }
2007
2008         if (pos > firmware->size)
2009                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2010                           file, regions, pos - firmware->size);
2011
2012         wm_adsp_debugfs_save_wmfwname(dsp, file);
2013
2014 out_fw:
2015         regmap_async_complete(regmap);
2016         wm_adsp_buf_free(&buf_list);
2017         release_firmware(firmware);
2018         kfree(text);
2019 out:
2020         kfree(file);
2021
2022         return ret;
2023 }
2024
2025 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp,
2026                                   const struct wm_adsp_alg_region *alg_region)
2027 {
2028         struct wm_coeff_ctl *ctl;
2029
2030         list_for_each_entry(ctl, &dsp->ctl_list, list) {
2031                 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] &&
2032                     alg_region->alg == ctl->alg_region.alg &&
2033                     alg_region->type == ctl->alg_region.type) {
2034                         ctl->alg_region.base = alg_region->base;
2035                 }
2036         }
2037 }
2038
2039 static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
2040                                const struct wm_adsp_region *mem,
2041                                unsigned int pos, unsigned int len)
2042 {
2043         void *alg;
2044         unsigned int reg;
2045         int ret;
2046         __be32 val;
2047
2048         if (n_algs == 0) {
2049                 adsp_err(dsp, "No algorithms\n");
2050                 return ERR_PTR(-EINVAL);
2051         }
2052
2053         if (n_algs > 1024) {
2054                 adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs);
2055                 return ERR_PTR(-EINVAL);
2056         }
2057
2058         /* Read the terminator first to validate the length */
2059         reg = dsp->ops->region_to_reg(mem, pos + len);
2060
2061         ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
2062         if (ret != 0) {
2063                 adsp_err(dsp, "Failed to read algorithm list end: %d\n",
2064                         ret);
2065                 return ERR_PTR(ret);
2066         }
2067
2068         if (be32_to_cpu(val) != 0xbedead)
2069                 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n",
2070                           reg, be32_to_cpu(val));
2071
2072         /* Convert length from DSP words to bytes */
2073         len *= sizeof(u32);
2074
2075         alg = kzalloc(len, GFP_KERNEL | GFP_DMA);
2076         if (!alg)
2077                 return ERR_PTR(-ENOMEM);
2078
2079         reg = dsp->ops->region_to_reg(mem, pos);
2080
2081         ret = regmap_raw_read(dsp->regmap, reg, alg, len);
2082         if (ret != 0) {
2083                 adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
2084                 kfree(alg);
2085                 return ERR_PTR(ret);
2086         }
2087
2088         return alg;
2089 }
2090
2091 static struct wm_adsp_alg_region *
2092         wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id)
2093 {
2094         struct wm_adsp_alg_region *alg_region;
2095
2096         list_for_each_entry(alg_region, &dsp->alg_regions, list) {
2097                 if (id == alg_region->alg && type == alg_region->type)
2098                         return alg_region;
2099         }
2100
2101         return NULL;
2102 }
2103
2104 static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp,
2105                                                         int type, __be32 id,
2106                                                         __be32 base)
2107 {
2108         struct wm_adsp_alg_region *alg_region;
2109
2110         alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL);
2111         if (!alg_region)
2112                 return ERR_PTR(-ENOMEM);
2113
2114         alg_region->type = type;
2115         alg_region->alg = be32_to_cpu(id);
2116         alg_region->base = be32_to_cpu(base);
2117
2118         list_add_tail(&alg_region->list, &dsp->alg_regions);
2119
2120         if (dsp->fw_ver > 0)
2121                 wm_adsp_ctl_fixup_base(dsp, alg_region);
2122
2123         return alg_region;
2124 }
2125
2126 static void wm_adsp_free_alg_regions(struct wm_adsp *dsp)
2127 {
2128         struct wm_adsp_alg_region *alg_region;
2129
2130         while (!list_empty(&dsp->alg_regions)) {
2131                 alg_region = list_first_entry(&dsp->alg_regions,
2132                                               struct wm_adsp_alg_region,
2133                                               list);
2134                 list_del(&alg_region->list);
2135                 kfree(alg_region);
2136         }
2137 }
2138
2139 static void wmfw_parse_id_header(struct wm_adsp *dsp,
2140                                  struct wmfw_id_hdr *fw, int nalgs)
2141 {
2142         dsp->fw_id = be32_to_cpu(fw->id);
2143         dsp->fw_id_version = be32_to_cpu(fw->ver);
2144
2145         adsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n",
2146                   dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16,
2147                   (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
2148                   nalgs);
2149 }
2150
2151 static void wmfw_v3_parse_id_header(struct wm_adsp *dsp,
2152                                     struct wmfw_v3_id_hdr *fw, int nalgs)
2153 {
2154         dsp->fw_id = be32_to_cpu(fw->id);
2155         dsp->fw_id_version = be32_to_cpu(fw->ver);
2156         dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id);
2157
2158         adsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n",
2159                   dsp->fw_id, dsp->fw_vendor_id,
2160                   (dsp->fw_id_version & 0xff0000) >> 16,
2161                   (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
2162                   nalgs);
2163 }
2164
2165 static int wm_adsp_create_regions(struct wm_adsp *dsp, __be32 id, int nregions,
2166                                 int *type, __be32 *base)
2167 {
2168         struct wm_adsp_alg_region *alg_region;
2169         int i;
2170
2171         for (i = 0; i < nregions; i++) {
2172                 alg_region = wm_adsp_create_region(dsp, type[i], id, base[i]);
2173                 if (IS_ERR(alg_region))
2174                         return PTR_ERR(alg_region);
2175         }
2176
2177         return 0;
2178 }
2179
2180 static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
2181 {
2182         struct wmfw_adsp1_id_hdr adsp1_id;
2183         struct wmfw_adsp1_alg_hdr *adsp1_alg;
2184         struct wm_adsp_alg_region *alg_region;
2185         const struct wm_adsp_region *mem;
2186         unsigned int pos, len;
2187         size_t n_algs;
2188         int i, ret;
2189
2190         mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
2191         if (WARN_ON(!mem))
2192                 return -EINVAL;
2193
2194         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id,
2195                               sizeof(adsp1_id));
2196         if (ret != 0) {
2197                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
2198                          ret);
2199                 return ret;
2200         }
2201
2202         n_algs = be32_to_cpu(adsp1_id.n_algs);
2203
2204         wmfw_parse_id_header(dsp, &adsp1_id.fw, n_algs);
2205
2206         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
2207                                            adsp1_id.fw.id, adsp1_id.zm);
2208         if (IS_ERR(alg_region))
2209                 return PTR_ERR(alg_region);
2210
2211         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
2212                                            adsp1_id.fw.id, adsp1_id.dm);
2213         if (IS_ERR(alg_region))
2214                 return PTR_ERR(alg_region);
2215
2216         /* Calculate offset and length in DSP words */
2217         pos = sizeof(adsp1_id) / sizeof(u32);
2218         len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32);
2219
2220         adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2221         if (IS_ERR(adsp1_alg))
2222                 return PTR_ERR(adsp1_alg);
2223
2224         for (i = 0; i < n_algs; i++) {
2225                 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
2226                           i, be32_to_cpu(adsp1_alg[i].alg.id),
2227                           (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
2228                           (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
2229                           be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
2230                           be32_to_cpu(adsp1_alg[i].dm),
2231                           be32_to_cpu(adsp1_alg[i].zm));
2232
2233                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
2234                                                    adsp1_alg[i].alg.id,
2235                                                    adsp1_alg[i].dm);
2236                 if (IS_ERR(alg_region)) {
2237                         ret = PTR_ERR(alg_region);
2238                         goto out;
2239                 }
2240                 if (dsp->fw_ver == 0) {
2241                         if (i + 1 < n_algs) {
2242                                 len = be32_to_cpu(adsp1_alg[i + 1].dm);
2243                                 len -= be32_to_cpu(adsp1_alg[i].dm);
2244                                 len *= 4;
2245                                 wm_adsp_create_control(dsp, alg_region, 0,
2246                                                      len, NULL, 0, 0,
2247                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2248                         } else {
2249                                 adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
2250                                           be32_to_cpu(adsp1_alg[i].alg.id));
2251                         }
2252                 }
2253
2254                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
2255                                                    adsp1_alg[i].alg.id,
2256                                                    adsp1_alg[i].zm);
2257                 if (IS_ERR(alg_region)) {
2258                         ret = PTR_ERR(alg_region);
2259                         goto out;
2260                 }
2261                 if (dsp->fw_ver == 0) {
2262                         if (i + 1 < n_algs) {
2263                                 len = be32_to_cpu(adsp1_alg[i + 1].zm);
2264                                 len -= be32_to_cpu(adsp1_alg[i].zm);
2265                                 len *= 4;
2266                                 wm_adsp_create_control(dsp, alg_region, 0,
2267                                                      len, NULL, 0, 0,
2268                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2269                         } else {
2270                                 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
2271                                           be32_to_cpu(adsp1_alg[i].alg.id));
2272                         }
2273                 }
2274         }
2275
2276 out:
2277         kfree(adsp1_alg);
2278         return ret;
2279 }
2280
2281 static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
2282 {
2283         struct wmfw_adsp2_id_hdr adsp2_id;
2284         struct wmfw_adsp2_alg_hdr *adsp2_alg;
2285         struct wm_adsp_alg_region *alg_region;
2286         const struct wm_adsp_region *mem;
2287         unsigned int pos, len;
2288         size_t n_algs;
2289         int i, ret;
2290
2291         mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
2292         if (WARN_ON(!mem))
2293                 return -EINVAL;
2294
2295         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id,
2296                               sizeof(adsp2_id));
2297         if (ret != 0) {
2298                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
2299                          ret);
2300                 return ret;
2301         }
2302
2303         n_algs = be32_to_cpu(adsp2_id.n_algs);
2304
2305         wmfw_parse_id_header(dsp, &adsp2_id.fw, n_algs);
2306
2307         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
2308                                            adsp2_id.fw.id, adsp2_id.xm);
2309         if (IS_ERR(alg_region))
2310                 return PTR_ERR(alg_region);
2311
2312         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
2313                                            adsp2_id.fw.id, adsp2_id.ym);
2314         if (IS_ERR(alg_region))
2315                 return PTR_ERR(alg_region);
2316
2317         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
2318                                            adsp2_id.fw.id, adsp2_id.zm);
2319         if (IS_ERR(alg_region))
2320                 return PTR_ERR(alg_region);
2321
2322         /* Calculate offset and length in DSP words */
2323         pos = sizeof(adsp2_id) / sizeof(u32);
2324         len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32);
2325
2326         adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2327         if (IS_ERR(adsp2_alg))
2328                 return PTR_ERR(adsp2_alg);
2329
2330         for (i = 0; i < n_algs; i++) {
2331                 adsp_info(dsp,
2332                           "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
2333                           i, be32_to_cpu(adsp2_alg[i].alg.id),
2334                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
2335                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
2336                           be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
2337                           be32_to_cpu(adsp2_alg[i].xm),
2338                           be32_to_cpu(adsp2_alg[i].ym),
2339                           be32_to_cpu(adsp2_alg[i].zm));
2340
2341                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
2342                                                    adsp2_alg[i].alg.id,
2343                                                    adsp2_alg[i].xm);
2344                 if (IS_ERR(alg_region)) {
2345                         ret = PTR_ERR(alg_region);
2346                         goto out;
2347                 }
2348                 if (dsp->fw_ver == 0) {
2349                         if (i + 1 < n_algs) {
2350                                 len = be32_to_cpu(adsp2_alg[i + 1].xm);
2351                                 len -= be32_to_cpu(adsp2_alg[i].xm);
2352                                 len *= 4;
2353                                 wm_adsp_create_control(dsp, alg_region, 0,
2354                                                      len, NULL, 0, 0,
2355                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2356                         } else {
2357                                 adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
2358                                           be32_to_cpu(adsp2_alg[i].alg.id));
2359                         }
2360                 }
2361
2362                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
2363                                                    adsp2_alg[i].alg.id,
2364                                                    adsp2_alg[i].ym);
2365                 if (IS_ERR(alg_region)) {
2366                         ret = PTR_ERR(alg_region);
2367                         goto out;
2368                 }
2369                 if (dsp->fw_ver == 0) {
2370                         if (i + 1 < n_algs) {
2371                                 len = be32_to_cpu(adsp2_alg[i + 1].ym);
2372                                 len -= be32_to_cpu(adsp2_alg[i].ym);
2373                                 len *= 4;
2374                                 wm_adsp_create_control(dsp, alg_region, 0,
2375                                                      len, NULL, 0, 0,
2376                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2377                         } else {
2378                                 adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
2379                                           be32_to_cpu(adsp2_alg[i].alg.id));
2380                         }
2381                 }
2382
2383                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
2384                                                    adsp2_alg[i].alg.id,
2385                                                    adsp2_alg[i].zm);
2386                 if (IS_ERR(alg_region)) {
2387                         ret = PTR_ERR(alg_region);
2388                         goto out;
2389                 }
2390                 if (dsp->fw_ver == 0) {
2391                         if (i + 1 < n_algs) {
2392                                 len = be32_to_cpu(adsp2_alg[i + 1].zm);
2393                                 len -= be32_to_cpu(adsp2_alg[i].zm);
2394                                 len *= 4;
2395                                 wm_adsp_create_control(dsp, alg_region, 0,
2396                                                      len, NULL, 0, 0,
2397                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2398                         } else {
2399                                 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
2400                                           be32_to_cpu(adsp2_alg[i].alg.id));
2401                         }
2402                 }
2403         }
2404
2405 out:
2406         kfree(adsp2_alg);
2407         return ret;
2408 }
2409
2410 static int wm_halo_create_regions(struct wm_adsp *dsp, __be32 id,
2411                                   __be32 xm_base, __be32 ym_base)
2412 {
2413         int types[] = {
2414                 WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED,
2415                 WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED
2416         };
2417         __be32 bases[] = { xm_base, xm_base, ym_base, ym_base };
2418
2419         return wm_adsp_create_regions(dsp, id, ARRAY_SIZE(types), types, bases);
2420 }
2421
2422 static int wm_halo_setup_algs(struct wm_adsp *dsp)
2423 {
2424         struct wmfw_halo_id_hdr halo_id;
2425         struct wmfw_halo_alg_hdr *halo_alg;
2426         const struct wm_adsp_region *mem;
2427         unsigned int pos, len;
2428         size_t n_algs;
2429         int i, ret;
2430
2431         mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
2432         if (WARN_ON(!mem))
2433                 return -EINVAL;
2434
2435         ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id,
2436                               sizeof(halo_id));
2437         if (ret != 0) {
2438                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
2439                          ret);
2440                 return ret;
2441         }
2442
2443         n_algs = be32_to_cpu(halo_id.n_algs);
2444
2445         wmfw_v3_parse_id_header(dsp, &halo_id.fw, n_algs);
2446
2447         ret = wm_halo_create_regions(dsp, halo_id.fw.id,
2448                                      halo_id.xm_base, halo_id.ym_base);
2449         if (ret)
2450                 return ret;
2451
2452         /* Calculate offset and length in DSP words */
2453         pos = sizeof(halo_id) / sizeof(u32);
2454         len = (sizeof(*halo_alg) * n_algs) / sizeof(u32);
2455
2456         halo_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2457         if (IS_ERR(halo_alg))
2458                 return PTR_ERR(halo_alg);
2459
2460         for (i = 0; i < n_algs; i++) {
2461                 adsp_info(dsp,
2462                           "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
2463                           i, be32_to_cpu(halo_alg[i].alg.id),
2464                           (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
2465                           (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
2466                           be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
2467                           be32_to_cpu(halo_alg[i].xm_base),
2468                           be32_to_cpu(halo_alg[i].ym_base));
2469
2470                 ret = wm_halo_create_regions(dsp, halo_alg[i].alg.id,
2471                                              halo_alg[i].xm_base,
2472                                              halo_alg[i].ym_base);
2473                 if (ret)
2474                         goto out;
2475         }
2476
2477 out:
2478         kfree(halo_alg);
2479         return ret;
2480 }
2481
2482 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
2483 {
2484         LIST_HEAD(buf_list);
2485         struct regmap *regmap = dsp->regmap;
2486         struct wmfw_coeff_hdr *hdr;
2487         struct wmfw_coeff_item *blk;
2488         const struct firmware *firmware;
2489         const struct wm_adsp_region *mem;
2490         struct wm_adsp_alg_region *alg_region;
2491         const char *region_name;
2492         int ret, pos, blocks, type, offset, reg;
2493         char *file;
2494         struct wm_adsp_buf *buf;
2495
2496         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
2497         if (file == NULL)
2498                 return -ENOMEM;
2499
2500         snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name,
2501                  wm_adsp_fw[dsp->fw].file);
2502         file[PAGE_SIZE - 1] = '\0';
2503
2504         ret = request_firmware(&firmware, file, dsp->dev);
2505         if (ret != 0) {
2506                 adsp_warn(dsp, "Failed to request '%s'\n", file);
2507                 ret = 0;
2508                 goto out;
2509         }
2510         ret = -EINVAL;
2511
2512         if (sizeof(*hdr) >= firmware->size) {
2513                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
2514                         file, firmware->size);
2515                 goto out_fw;
2516         }
2517
2518         hdr = (void *)&firmware->data[0];
2519         if (memcmp(hdr->magic, "WMDR", 4) != 0) {
2520                 adsp_err(dsp, "%s: invalid magic\n", file);
2521                 goto out_fw;
2522         }
2523
2524         switch (be32_to_cpu(hdr->rev) & 0xff) {
2525         case 1:
2526                 break;
2527         default:
2528                 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
2529                          file, be32_to_cpu(hdr->rev) & 0xff);
2530                 ret = -EINVAL;
2531                 goto out_fw;
2532         }
2533
2534         adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
2535                 (le32_to_cpu(hdr->ver) >> 16) & 0xff,
2536                 (le32_to_cpu(hdr->ver) >>  8) & 0xff,
2537                 le32_to_cpu(hdr->ver) & 0xff);
2538
2539         pos = le32_to_cpu(hdr->len);
2540
2541         blocks = 0;
2542         while (pos < firmware->size &&
2543                sizeof(*blk) < firmware->size - pos) {
2544                 blk = (void *)(&firmware->data[pos]);
2545
2546                 type = le16_to_cpu(blk->type);
2547                 offset = le16_to_cpu(blk->offset);
2548
2549                 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
2550                          file, blocks, le32_to_cpu(blk->id),
2551                          (le32_to_cpu(blk->ver) >> 16) & 0xff,
2552                          (le32_to_cpu(blk->ver) >>  8) & 0xff,
2553                          le32_to_cpu(blk->ver) & 0xff);
2554                 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
2555                          file, blocks, le32_to_cpu(blk->len), offset, type);
2556
2557                 reg = 0;
2558                 region_name = "Unknown";
2559                 switch (type) {
2560                 case (WMFW_NAME_TEXT << 8):
2561                 case (WMFW_INFO_TEXT << 8):
2562                         break;
2563                 case (WMFW_ABSOLUTE << 8):
2564                         /*
2565                          * Old files may use this for global
2566                          * coefficients.
2567                          */
2568                         if (le32_to_cpu(blk->id) == dsp->fw_id &&
2569                             offset == 0) {
2570                                 region_name = "global coefficients";
2571                                 mem = wm_adsp_find_region(dsp, type);
2572                                 if (!mem) {
2573                                         adsp_err(dsp, "No ZM\n");
2574                                         break;
2575                                 }
2576                                 reg = dsp->ops->region_to_reg(mem, 0);
2577
2578                         } else {
2579                                 region_name = "register";
2580                                 reg = offset;
2581                         }
2582                         break;
2583
2584                 case WMFW_ADSP1_DM:
2585                 case WMFW_ADSP1_ZM:
2586                 case WMFW_ADSP2_XM:
2587                 case WMFW_ADSP2_YM:
2588                 case WMFW_HALO_XM_PACKED:
2589                 case WMFW_HALO_YM_PACKED:
2590                 case WMFW_HALO_PM_PACKED:
2591                         adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
2592                                  file, blocks, le32_to_cpu(blk->len),
2593                                  type, le32_to_cpu(blk->id));
2594
2595                         mem = wm_adsp_find_region(dsp, type);
2596                         if (!mem) {
2597                                 adsp_err(dsp, "No base for region %x\n", type);
2598                                 break;
2599                         }
2600
2601                         alg_region = wm_adsp_find_alg_region(dsp, type,
2602                                                 le32_to_cpu(blk->id));
2603                         if (alg_region) {
2604                                 reg = alg_region->base;
2605                                 reg = dsp->ops->region_to_reg(mem, reg);
2606                                 reg += offset;
2607                         } else {
2608                                 adsp_err(dsp, "No %x for algorithm %x\n",
2609                                          type, le32_to_cpu(blk->id));
2610                         }
2611                         break;
2612
2613                 default:
2614                         adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
2615                                  file, blocks, type, pos);
2616                         break;
2617                 }
2618
2619                 if (reg) {
2620                         if (le32_to_cpu(blk->len) >
2621                             firmware->size - pos - sizeof(*blk)) {
2622                                 adsp_err(dsp,
2623                                          "%s.%d: %s region len %d bytes exceeds file length %zu\n",
2624                                          file, blocks, region_name,
2625                                          le32_to_cpu(blk->len),
2626                                          firmware->size);
2627                                 ret = -EINVAL;
2628                                 goto out_fw;
2629                         }
2630
2631                         buf = wm_adsp_buf_alloc(blk->data,
2632                                                 le32_to_cpu(blk->len),
2633                                                 &buf_list);
2634                         if (!buf) {
2635                                 adsp_err(dsp, "Out of memory\n");
2636                                 ret = -ENOMEM;
2637                                 goto out_fw;
2638                         }
2639
2640                         adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
2641                                  file, blocks, le32_to_cpu(blk->len),
2642                                  reg);
2643                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
2644                                                      le32_to_cpu(blk->len));
2645                         if (ret != 0) {
2646                                 adsp_err(dsp,
2647                                         "%s.%d: Failed to write to %x in %s: %d\n",
2648                                         file, blocks, reg, region_name, ret);
2649                         }
2650                 }
2651
2652                 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
2653                 blocks++;
2654         }
2655
2656         ret = regmap_async_complete(regmap);
2657         if (ret != 0)
2658                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
2659
2660         if (pos > firmware->size)
2661                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2662                           file, blocks, pos - firmware->size);
2663
2664         wm_adsp_debugfs_save_binname(dsp, file);
2665
2666 out_fw:
2667         regmap_async_complete(regmap);
2668         release_firmware(firmware);
2669         wm_adsp_buf_free(&buf_list);
2670 out:
2671         kfree(file);
2672         return ret;
2673 }
2674
2675 static int wm_adsp_create_name(struct wm_adsp *dsp)
2676 {
2677         char *p;
2678
2679         if (!dsp->name) {
2680                 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d",
2681                                            dsp->num);
2682                 if (!dsp->name)
2683                         return -ENOMEM;
2684         }
2685
2686         if (!dsp->fwf_name) {
2687                 p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL);
2688                 if (!p)
2689                         return -ENOMEM;
2690
2691                 dsp->fwf_name = p;
2692                 for (; *p != 0; ++p)
2693                         *p = tolower(*p);
2694         }
2695
2696         return 0;
2697 }
2698
2699 static int wm_adsp_common_init(struct wm_adsp *dsp)
2700 {
2701         int ret;
2702
2703         ret = wm_adsp_create_name(dsp);
2704         if (ret)
2705                 return ret;
2706
2707         INIT_LIST_HEAD(&dsp->alg_regions);
2708         INIT_LIST_HEAD(&dsp->ctl_list);
2709         INIT_LIST_HEAD(&dsp->compr_list);
2710         INIT_LIST_HEAD(&dsp->buffer_list);
2711
2712         mutex_init(&dsp->pwr_lock);
2713
2714         return 0;
2715 }
2716
2717 int wm_adsp1_init(struct wm_adsp *dsp)
2718 {
2719         dsp->ops = &wm_adsp1_ops;
2720
2721         return wm_adsp_common_init(dsp);
2722 }
2723 EXPORT_SYMBOL_GPL(wm_adsp1_init);
2724
2725 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
2726                    struct snd_kcontrol *kcontrol,
2727                    int event)
2728 {
2729         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2730         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
2731         struct wm_adsp *dsp = &dsps[w->shift];
2732         struct wm_coeff_ctl *ctl;
2733         int ret;
2734         unsigned int val;
2735
2736         dsp->component = component;
2737
2738         mutex_lock(&dsp->pwr_lock);
2739
2740         switch (event) {
2741         case SND_SOC_DAPM_POST_PMU:
2742                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2743                                    ADSP1_SYS_ENA, ADSP1_SYS_ENA);
2744
2745                 /*
2746                  * For simplicity set the DSP clock rate to be the
2747                  * SYSCLK rate rather than making it configurable.
2748                  */
2749                 if (dsp->sysclk_reg) {
2750                         ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
2751                         if (ret != 0) {
2752                                 adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
2753                                 ret);
2754                                 goto err_mutex;
2755                         }
2756
2757                         val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
2758
2759                         ret = regmap_update_bits(dsp->regmap,
2760                                                  dsp->base + ADSP1_CONTROL_31,
2761                                                  ADSP1_CLK_SEL_MASK, val);
2762                         if (ret != 0) {
2763                                 adsp_err(dsp, "Failed to set clock rate: %d\n",
2764                                          ret);
2765                                 goto err_mutex;
2766                         }
2767                 }
2768
2769                 ret = wm_adsp_load(dsp);
2770                 if (ret != 0)
2771                         goto err_ena;
2772
2773                 ret = wm_adsp1_setup_algs(dsp);
2774                 if (ret != 0)
2775                         goto err_ena;
2776
2777                 ret = wm_adsp_load_coeff(dsp);
2778                 if (ret != 0)
2779                         goto err_ena;
2780
2781                 /* Initialize caches for enabled and unset controls */
2782                 ret = wm_coeff_init_control_caches(dsp);
2783                 if (ret != 0)
2784                         goto err_ena;
2785
2786                 /* Sync set controls */
2787                 ret = wm_coeff_sync_controls(dsp);
2788                 if (ret != 0)
2789                         goto err_ena;
2790
2791                 dsp->booted = true;
2792
2793                 /* Start the core running */
2794                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2795                                    ADSP1_CORE_ENA | ADSP1_START,
2796                                    ADSP1_CORE_ENA | ADSP1_START);
2797
2798                 dsp->running = true;
2799                 break;
2800
2801         case SND_SOC_DAPM_PRE_PMD:
2802                 dsp->running = false;
2803                 dsp->booted = false;
2804
2805                 /* Halt the core */
2806                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2807                                    ADSP1_CORE_ENA | ADSP1_START, 0);
2808
2809                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
2810                                    ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
2811
2812                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2813                                    ADSP1_SYS_ENA, 0);
2814
2815                 list_for_each_entry(ctl, &dsp->ctl_list, list)
2816                         ctl->enabled = 0;
2817
2818
2819                 wm_adsp_free_alg_regions(dsp);
2820                 break;
2821
2822         default:
2823                 break;
2824         }
2825
2826         mutex_unlock(&dsp->pwr_lock);
2827
2828         return 0;
2829
2830 err_ena:
2831         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2832                            ADSP1_SYS_ENA, 0);
2833 err_mutex:
2834         mutex_unlock(&dsp->pwr_lock);
2835
2836         return ret;
2837 }
2838 EXPORT_SYMBOL_GPL(wm_adsp1_event);
2839
2840 static int wm_adsp2v2_enable_core(struct wm_adsp *dsp)
2841 {
2842         unsigned int val;
2843         int ret, count;
2844
2845         /* Wait for the RAM to start, should be near instantaneous */
2846         for (count = 0; count < 10; ++count) {
2847                 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
2848                 if (ret != 0)
2849                         return ret;
2850
2851                 if (val & ADSP2_RAM_RDY)
2852                         break;
2853
2854                 usleep_range(250, 500);
2855         }
2856
2857         if (!(val & ADSP2_RAM_RDY)) {
2858                 adsp_err(dsp, "Failed to start DSP RAM\n");
2859                 return -EBUSY;
2860         }
2861
2862         adsp_dbg(dsp, "RAM ready after %d polls\n", count);
2863
2864         return 0;
2865 }
2866
2867 static int wm_adsp2_enable_core(struct wm_adsp *dsp)
2868 {
2869         int ret;
2870
2871         ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2872                                        ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2873         if (ret != 0)
2874                 return ret;
2875
2876         return wm_adsp2v2_enable_core(dsp);
2877 }
2878
2879 static int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions)
2880 {
2881         struct regmap *regmap = dsp->regmap;
2882         unsigned int code0, code1, lock_reg;
2883
2884         if (!(lock_regions & WM_ADSP2_REGION_ALL))
2885                 return 0;
2886
2887         lock_regions &= WM_ADSP2_REGION_ALL;
2888         lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0;
2889
2890         while (lock_regions) {
2891                 code0 = code1 = 0;
2892                 if (lock_regions & BIT(0)) {
2893                         code0 = ADSP2_LOCK_CODE_0;
2894                         code1 = ADSP2_LOCK_CODE_1;
2895                 }
2896                 if (lock_regions & BIT(1)) {
2897                         code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT;
2898                         code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT;
2899                 }
2900                 regmap_write(regmap, lock_reg, code0);
2901                 regmap_write(regmap, lock_reg, code1);
2902                 lock_regions >>= 2;
2903                 lock_reg += 2;
2904         }
2905
2906         return 0;
2907 }
2908
2909 static int wm_adsp2_enable_memory(struct wm_adsp *dsp)
2910 {
2911         return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2912                                   ADSP2_MEM_ENA, ADSP2_MEM_ENA);
2913 }
2914
2915 static void wm_adsp2_disable_memory(struct wm_adsp *dsp)
2916 {
2917         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2918                            ADSP2_MEM_ENA, 0);
2919 }
2920
2921 static void wm_adsp2_disable_core(struct wm_adsp *dsp)
2922 {
2923         regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2924         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2925         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2926
2927         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2928                            ADSP2_SYS_ENA, 0);
2929 }
2930
2931 static void wm_adsp2v2_disable_core(struct wm_adsp *dsp)
2932 {
2933         regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2934         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2935         regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
2936 }
2937
2938 static void wm_adsp_boot_work(struct work_struct *work)
2939 {
2940         struct wm_adsp *dsp = container_of(work,
2941                                            struct wm_adsp,
2942                                            boot_work);
2943         int ret;
2944
2945         mutex_lock(&dsp->pwr_lock);
2946
2947         if (dsp->ops->enable_memory) {
2948                 ret = dsp->ops->enable_memory(dsp);
2949                 if (ret != 0)
2950                         goto err_mutex;
2951         }
2952
2953         if (dsp->ops->enable_core) {
2954                 ret = dsp->ops->enable_core(dsp);
2955                 if (ret != 0)
2956                         goto err_mem;
2957         }
2958
2959         ret = wm_adsp_load(dsp);
2960         if (ret != 0)
2961                 goto err_ena;
2962
2963         ret = dsp->ops->setup_algs(dsp);
2964         if (ret != 0)
2965                 goto err_ena;
2966
2967         ret = wm_adsp_load_coeff(dsp);
2968         if (ret != 0)
2969                 goto err_ena;
2970
2971         /* Initialize caches for enabled and unset controls */
2972         ret = wm_coeff_init_control_caches(dsp);
2973         if (ret != 0)
2974                 goto err_ena;
2975
2976         if (dsp->ops->disable_core)
2977                 dsp->ops->disable_core(dsp);
2978
2979         dsp->booted = true;
2980
2981         mutex_unlock(&dsp->pwr_lock);
2982
2983         return;
2984
2985 err_ena:
2986         if (dsp->ops->disable_core)
2987                 dsp->ops->disable_core(dsp);
2988 err_mem:
2989         if (dsp->ops->disable_memory)
2990                 dsp->ops->disable_memory(dsp);
2991 err_mutex:
2992         mutex_unlock(&dsp->pwr_lock);
2993 }
2994
2995 static int wm_halo_configure_mpu(struct wm_adsp *dsp, unsigned int lock_regions)
2996 {
2997         struct reg_sequence config[] = {
2998                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0x5555 },
2999                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0xAAAA },
3000                 { dsp->base + HALO_MPU_XMEM_ACCESS_0,   0xFFFFFFFF },
3001                 { dsp->base + HALO_MPU_YMEM_ACCESS_0,   0xFFFFFFFF },
3002                 { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions },
3003                 { dsp->base + HALO_MPU_XREG_ACCESS_0,   lock_regions },
3004                 { dsp->base + HALO_MPU_YREG_ACCESS_0,   lock_regions },
3005                 { dsp->base + HALO_MPU_XMEM_ACCESS_1,   0xFFFFFFFF },
3006                 { dsp->base + HALO_MPU_YMEM_ACCESS_1,   0xFFFFFFFF },
3007                 { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions },
3008                 { dsp->base + HALO_MPU_XREG_ACCESS_1,   lock_regions },
3009                 { dsp->base + HALO_MPU_YREG_ACCESS_1,   lock_regions },
3010                 { dsp->base + HALO_MPU_XMEM_ACCESS_2,   0xFFFFFFFF },
3011                 { dsp->base + HALO_MPU_YMEM_ACCESS_2,   0xFFFFFFFF },
3012                 { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions },
3013                 { dsp->base + HALO_MPU_XREG_ACCESS_2,   lock_regions },
3014                 { dsp->base + HALO_MPU_YREG_ACCESS_2,   lock_regions },
3015                 { dsp->base + HALO_MPU_XMEM_ACCESS_3,   0xFFFFFFFF },
3016                 { dsp->base + HALO_MPU_YMEM_ACCESS_3,   0xFFFFFFFF },
3017                 { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions },
3018                 { dsp->base + HALO_MPU_XREG_ACCESS_3,   lock_regions },
3019                 { dsp->base + HALO_MPU_YREG_ACCESS_3,   lock_regions },
3020                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0 },
3021         };
3022
3023         return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config));
3024 }
3025
3026 int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq)
3027 {
3028         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3029         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3030         struct wm_adsp *dsp = &dsps[w->shift];
3031         int ret;
3032
3033         ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING,
3034                                  ADSP2_CLK_SEL_MASK,
3035                                  freq << ADSP2_CLK_SEL_SHIFT);
3036         if (ret)
3037                 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
3038
3039         return ret;
3040 }
3041 EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk);
3042
3043 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
3044                            struct snd_ctl_elem_value *ucontrol)
3045 {
3046         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3047         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3048         struct soc_mixer_control *mc =
3049                 (struct soc_mixer_control *)kcontrol->private_value;
3050         struct wm_adsp *dsp = &dsps[mc->shift - 1];
3051
3052         ucontrol->value.integer.value[0] = dsp->preloaded;
3053
3054         return 0;
3055 }
3056 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get);
3057
3058 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
3059                            struct snd_ctl_elem_value *ucontrol)
3060 {
3061         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3062         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3063         struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
3064         struct soc_mixer_control *mc =
3065                 (struct soc_mixer_control *)kcontrol->private_value;
3066         struct wm_adsp *dsp = &dsps[mc->shift - 1];
3067         char preload[32];
3068
3069         snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name);
3070
3071         dsp->preloaded = ucontrol->value.integer.value[0];
3072
3073         if (ucontrol->value.integer.value[0])
3074                 snd_soc_component_force_enable_pin(component, preload);
3075         else
3076                 snd_soc_component_disable_pin(component, preload);
3077
3078         snd_soc_dapm_sync(dapm);
3079
3080         flush_work(&dsp->boot_work);
3081
3082         return 0;
3083 }
3084 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
3085
3086 static void wm_adsp_stop_watchdog(struct wm_adsp *dsp)
3087 {
3088         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG,
3089                            ADSP2_WDT_ENA_MASK, 0);
3090 }
3091
3092 static void wm_halo_stop_watchdog(struct wm_adsp *dsp)
3093 {
3094         regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL,
3095                            HALO_WDT_EN_MASK, 0);
3096 }
3097
3098 int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
3099                         struct snd_kcontrol *kcontrol, int event)
3100 {
3101         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3102         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3103         struct wm_adsp *dsp = &dsps[w->shift];
3104         struct wm_coeff_ctl *ctl;
3105
3106         switch (event) {
3107         case SND_SOC_DAPM_PRE_PMU:
3108                 queue_work(system_unbound_wq, &dsp->boot_work);
3109                 break;
3110         case SND_SOC_DAPM_PRE_PMD:
3111                 mutex_lock(&dsp->pwr_lock);
3112
3113                 wm_adsp_debugfs_clear(dsp);
3114
3115                 dsp->fw_id = 0;
3116                 dsp->fw_id_version = 0;
3117
3118                 dsp->booted = false;
3119
3120                 if (dsp->ops->disable_memory)
3121                         dsp->ops->disable_memory(dsp);
3122
3123                 list_for_each_entry(ctl, &dsp->ctl_list, list)
3124                         ctl->enabled = 0;
3125
3126                 wm_adsp_free_alg_regions(dsp);
3127
3128                 mutex_unlock(&dsp->pwr_lock);
3129
3130                 adsp_dbg(dsp, "Shutdown complete\n");
3131                 break;