37aa020f23f631c3635c0a925de1124db07b2177
[linux-2.6-microblaze.git] / sound / soc / codecs / wm_adsp.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * wm_adsp.c  --  Wolfson ADSP support
4  *
5  * Copyright 2012 Wolfson Microelectronics plc
6  *
7  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8  */
9
10 #include <linux/ctype.h>
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/init.h>
14 #include <linux/delay.h>
15 #include <linux/firmware.h>
16 #include <linux/list.h>
17 #include <linux/pm.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/slab.h>
22 #include <linux/vmalloc.h>
23 #include <linux/workqueue.h>
24 #include <linux/debugfs.h>
25 #include <sound/core.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/soc.h>
29 #include <sound/jack.h>
30 #include <sound/initval.h>
31 #include <sound/tlv.h>
32
33 #include "wm_adsp.h"
34
35 #define adsp_crit(_dsp, fmt, ...) \
36         dev_crit(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
37 #define adsp_err(_dsp, fmt, ...) \
38         dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
39 #define adsp_warn(_dsp, fmt, ...) \
40         dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
41 #define adsp_info(_dsp, fmt, ...) \
42         dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
43 #define adsp_dbg(_dsp, fmt, ...) \
44         dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
45
46 #define compr_err(_obj, fmt, ...) \
47         adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
48                  ##__VA_ARGS__)
49 #define compr_dbg(_obj, fmt, ...) \
50         adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
51                  ##__VA_ARGS__)
52
53 #define ADSP1_CONTROL_1                   0x00
54 #define ADSP1_CONTROL_2                   0x02
55 #define ADSP1_CONTROL_3                   0x03
56 #define ADSP1_CONTROL_4                   0x04
57 #define ADSP1_CONTROL_5                   0x06
58 #define ADSP1_CONTROL_6                   0x07
59 #define ADSP1_CONTROL_7                   0x08
60 #define ADSP1_CONTROL_8                   0x09
61 #define ADSP1_CONTROL_9                   0x0A
62 #define ADSP1_CONTROL_10                  0x0B
63 #define ADSP1_CONTROL_11                  0x0C
64 #define ADSP1_CONTROL_12                  0x0D
65 #define ADSP1_CONTROL_13                  0x0F
66 #define ADSP1_CONTROL_14                  0x10
67 #define ADSP1_CONTROL_15                  0x11
68 #define ADSP1_CONTROL_16                  0x12
69 #define ADSP1_CONTROL_17                  0x13
70 #define ADSP1_CONTROL_18                  0x14
71 #define ADSP1_CONTROL_19                  0x16
72 #define ADSP1_CONTROL_20                  0x17
73 #define ADSP1_CONTROL_21                  0x18
74 #define ADSP1_CONTROL_22                  0x1A
75 #define ADSP1_CONTROL_23                  0x1B
76 #define ADSP1_CONTROL_24                  0x1C
77 #define ADSP1_CONTROL_25                  0x1E
78 #define ADSP1_CONTROL_26                  0x20
79 #define ADSP1_CONTROL_27                  0x21
80 #define ADSP1_CONTROL_28                  0x22
81 #define ADSP1_CONTROL_29                  0x23
82 #define ADSP1_CONTROL_30                  0x24
83 #define ADSP1_CONTROL_31                  0x26
84
85 /*
86  * ADSP1 Control 19
87  */
88 #define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
89 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
90 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
91
92
93 /*
94  * ADSP1 Control 30
95  */
96 #define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
97 #define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
98 #define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
99 #define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
100 #define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
101 #define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
102 #define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
103 #define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
104 #define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
105 #define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
106 #define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
107 #define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
108 #define ADSP1_START                       0x0001  /* DSP1_START */
109 #define ADSP1_START_MASK                  0x0001  /* DSP1_START */
110 #define ADSP1_START_SHIFT                      0  /* DSP1_START */
111 #define ADSP1_START_WIDTH                      1  /* DSP1_START */
112
113 /*
114  * ADSP1 Control 31
115  */
116 #define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
117 #define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
118 #define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
119
120 #define ADSP2_CONTROL                     0x0
121 #define ADSP2_CLOCKING                    0x1
122 #define ADSP2V2_CLOCKING                  0x2
123 #define ADSP2_STATUS1                     0x4
124 #define ADSP2_WDMA_CONFIG_1               0x30
125 #define ADSP2_WDMA_CONFIG_2               0x31
126 #define ADSP2V2_WDMA_CONFIG_2             0x32
127 #define ADSP2_RDMA_CONFIG_1               0x34
128
129 #define ADSP2_SCRATCH0                    0x40
130 #define ADSP2_SCRATCH1                    0x41
131 #define ADSP2_SCRATCH2                    0x42
132 #define ADSP2_SCRATCH3                    0x43
133
134 #define ADSP2V2_SCRATCH0_1                0x40
135 #define ADSP2V2_SCRATCH2_3                0x42
136
137 /*
138  * ADSP2 Control
139  */
140
141 #define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
142 #define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
143 #define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
144 #define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
145 #define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
146 #define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
147 #define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
148 #define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
149 #define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
150 #define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
151 #define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
152 #define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
153 #define ADSP2_START                       0x0001  /* DSP1_START */
154 #define ADSP2_START_MASK                  0x0001  /* DSP1_START */
155 #define ADSP2_START_SHIFT                      0  /* DSP1_START */
156 #define ADSP2_START_WIDTH                      1  /* DSP1_START */
157
158 /*
159  * ADSP2 clocking
160  */
161 #define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
162 #define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
163 #define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
164
165 /*
166  * ADSP2V2 clocking
167  */
168 #define ADSP2V2_CLK_SEL_MASK             0x70000  /* CLK_SEL_ENA */
169 #define ADSP2V2_CLK_SEL_SHIFT                 16  /* CLK_SEL_ENA */
170 #define ADSP2V2_CLK_SEL_WIDTH                  3  /* CLK_SEL_ENA */
171
172 #define ADSP2V2_RATE_MASK                 0x7800  /* DSP_RATE */
173 #define ADSP2V2_RATE_SHIFT                    11  /* DSP_RATE */
174 #define ADSP2V2_RATE_WIDTH                     4  /* DSP_RATE */
175
176 /*
177  * ADSP2 Status 1
178  */
179 #define ADSP2_RAM_RDY                     0x0001
180 #define ADSP2_RAM_RDY_MASK                0x0001
181 #define ADSP2_RAM_RDY_SHIFT                    0
182 #define ADSP2_RAM_RDY_WIDTH                    1
183
184 /*
185  * ADSP2 Lock support
186  */
187 #define ADSP2_LOCK_CODE_0                    0x5555
188 #define ADSP2_LOCK_CODE_1                    0xAAAA
189
190 #define ADSP2_WATCHDOG                       0x0A
191 #define ADSP2_BUS_ERR_ADDR                   0x52
192 #define ADSP2_REGION_LOCK_STATUS             0x64
193 #define ADSP2_LOCK_REGION_1_LOCK_REGION_0    0x66
194 #define ADSP2_LOCK_REGION_3_LOCK_REGION_2    0x68
195 #define ADSP2_LOCK_REGION_5_LOCK_REGION_4    0x6A
196 #define ADSP2_LOCK_REGION_7_LOCK_REGION_6    0x6C
197 #define ADSP2_LOCK_REGION_9_LOCK_REGION_8    0x6E
198 #define ADSP2_LOCK_REGION_CTRL               0x7A
199 #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR    0x7C
200
201 #define ADSP2_REGION_LOCK_ERR_MASK           0x8000
202 #define ADSP2_ADDR_ERR_MASK                  0x4000
203 #define ADSP2_WDT_TIMEOUT_STS_MASK           0x2000
204 #define ADSP2_CTRL_ERR_PAUSE_ENA             0x0002
205 #define ADSP2_CTRL_ERR_EINT                  0x0001
206
207 #define ADSP2_BUS_ERR_ADDR_MASK              0x00FFFFFF
208 #define ADSP2_XMEM_ERR_ADDR_MASK             0x0000FFFF
209 #define ADSP2_PMEM_ERR_ADDR_MASK             0x7FFF0000
210 #define ADSP2_PMEM_ERR_ADDR_SHIFT            16
211 #define ADSP2_WDT_ENA_MASK                   0xFFFFFFFD
212
213 #define ADSP2_LOCK_REGION_SHIFT              16
214
215 #define ADSP_MAX_STD_CTRL_SIZE               512
216
217 #define WM_ADSP_ACKED_CTL_TIMEOUT_MS         100
218 #define WM_ADSP_ACKED_CTL_N_QUICKPOLLS       10
219 #define WM_ADSP_ACKED_CTL_MIN_VALUE          0
220 #define WM_ADSP_ACKED_CTL_MAX_VALUE          0xFFFFFF
221
222 /*
223  * Event control messages
224  */
225 #define WM_ADSP_FW_EVENT_SHUTDOWN            0x000001
226
227 /*
228  * HALO system info
229  */
230 #define HALO_AHBM_WINDOW_DEBUG_0             0x02040
231 #define HALO_AHBM_WINDOW_DEBUG_1             0x02044
232
233 /*
234  * HALO core
235  */
236 #define HALO_SCRATCH1                        0x005c0
237 #define HALO_SCRATCH2                        0x005c8
238 #define HALO_SCRATCH3                        0x005d0
239 #define HALO_SCRATCH4                        0x005d8
240 #define HALO_CCM_CORE_CONTROL                0x41000
241 #define HALO_CORE_SOFT_RESET                 0x00010
242 #define HALO_WDT_CONTROL                     0x47000
243
244 /*
245  * HALO MPU banks
246  */
247 #define HALO_MPU_XMEM_ACCESS_0               0x43000
248 #define HALO_MPU_YMEM_ACCESS_0               0x43004
249 #define HALO_MPU_WINDOW_ACCESS_0             0x43008
250 #define HALO_MPU_XREG_ACCESS_0               0x4300C
251 #define HALO_MPU_YREG_ACCESS_0               0x43014
252 #define HALO_MPU_XMEM_ACCESS_1               0x43018
253 #define HALO_MPU_YMEM_ACCESS_1               0x4301C
254 #define HALO_MPU_WINDOW_ACCESS_1             0x43020
255 #define HALO_MPU_XREG_ACCESS_1               0x43024
256 #define HALO_MPU_YREG_ACCESS_1               0x4302C
257 #define HALO_MPU_XMEM_ACCESS_2               0x43030
258 #define HALO_MPU_YMEM_ACCESS_2               0x43034
259 #define HALO_MPU_WINDOW_ACCESS_2             0x43038
260 #define HALO_MPU_XREG_ACCESS_2               0x4303C
261 #define HALO_MPU_YREG_ACCESS_2               0x43044
262 #define HALO_MPU_XMEM_ACCESS_3               0x43048
263 #define HALO_MPU_YMEM_ACCESS_3               0x4304C
264 #define HALO_MPU_WINDOW_ACCESS_3             0x43050
265 #define HALO_MPU_XREG_ACCESS_3               0x43054
266 #define HALO_MPU_YREG_ACCESS_3               0x4305C
267 #define HALO_MPU_XM_VIO_ADDR                 0x43100
268 #define HALO_MPU_XM_VIO_STATUS               0x43104
269 #define HALO_MPU_YM_VIO_ADDR                 0x43108
270 #define HALO_MPU_YM_VIO_STATUS               0x4310C
271 #define HALO_MPU_PM_VIO_ADDR                 0x43110
272 #define HALO_MPU_PM_VIO_STATUS               0x43114
273 #define HALO_MPU_LOCK_CONFIG                 0x43140
274
275 /*
276  * HALO_AHBM_WINDOW_DEBUG_1
277  */
278 #define HALO_AHBM_CORE_ERR_ADDR_MASK         0x0fffff00
279 #define HALO_AHBM_CORE_ERR_ADDR_SHIFT                 8
280 #define HALO_AHBM_FLAGS_ERR_MASK             0x000000ff
281
282 /*
283  * HALO_CCM_CORE_CONTROL
284  */
285 #define HALO_CORE_EN                        0x00000001
286
287 /*
288  * HALO_CORE_SOFT_RESET
289  */
290 #define HALO_CORE_SOFT_RESET_MASK           0x00000001
291
292 /*
293  * HALO_WDT_CONTROL
294  */
295 #define HALO_WDT_EN_MASK                    0x00000001
296
297 /*
298  * HALO_MPU_?M_VIO_STATUS
299  */
300 #define HALO_MPU_VIO_STS_MASK               0x007e0000
301 #define HALO_MPU_VIO_STS_SHIFT                      17
302 #define HALO_MPU_VIO_ERR_WR_MASK            0x00008000
303 #define HALO_MPU_VIO_ERR_SRC_MASK           0x00007fff
304 #define HALO_MPU_VIO_ERR_SRC_SHIFT                   0
305
306 static const struct wm_adsp_ops wm_adsp1_ops;
307 static const struct wm_adsp_ops wm_adsp2_ops[];
308 static const struct wm_adsp_ops wm_halo_ops;
309
310 struct wm_adsp_buf {
311         struct list_head list;
312         void *buf;
313 };
314
315 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
316                                              struct list_head *list)
317 {
318         struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
319
320         if (buf == NULL)
321                 return NULL;
322
323         buf->buf = vmalloc(len);
324         if (!buf->buf) {
325                 kfree(buf);
326                 return NULL;
327         }
328         memcpy(buf->buf, src, len);
329
330         if (list)
331                 list_add_tail(&buf->list, list);
332
333         return buf;
334 }
335
336 static void wm_adsp_buf_free(struct list_head *list)
337 {
338         while (!list_empty(list)) {
339                 struct wm_adsp_buf *buf = list_first_entry(list,
340                                                            struct wm_adsp_buf,
341                                                            list);
342                 list_del(&buf->list);
343                 vfree(buf->buf);
344                 kfree(buf);
345         }
346 }
347
348 #define WM_ADSP_FW_MBC_VSS  0
349 #define WM_ADSP_FW_HIFI     1
350 #define WM_ADSP_FW_TX       2
351 #define WM_ADSP_FW_TX_SPK   3
352 #define WM_ADSP_FW_RX       4
353 #define WM_ADSP_FW_RX_ANC   5
354 #define WM_ADSP_FW_CTRL     6
355 #define WM_ADSP_FW_ASR      7
356 #define WM_ADSP_FW_TRACE    8
357 #define WM_ADSP_FW_SPK_PROT 9
358 #define WM_ADSP_FW_SPK_CALI 10
359 #define WM_ADSP_FW_SPK_DIAG 11
360 #define WM_ADSP_FW_MISC     12
361
362 #define WM_ADSP_NUM_FW      13
363
364 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
365         [WM_ADSP_FW_MBC_VSS] =  "MBC/VSS",
366         [WM_ADSP_FW_HIFI] =     "MasterHiFi",
367         [WM_ADSP_FW_TX] =       "Tx",
368         [WM_ADSP_FW_TX_SPK] =   "Tx Speaker",
369         [WM_ADSP_FW_RX] =       "Rx",
370         [WM_ADSP_FW_RX_ANC] =   "Rx ANC",
371         [WM_ADSP_FW_CTRL] =     "Voice Ctrl",
372         [WM_ADSP_FW_ASR] =      "ASR Assist",
373         [WM_ADSP_FW_TRACE] =    "Dbg Trace",
374         [WM_ADSP_FW_SPK_PROT] = "Protection",
375         [WM_ADSP_FW_SPK_CALI] = "Calibration",
376         [WM_ADSP_FW_SPK_DIAG] = "Diagnostic",
377         [WM_ADSP_FW_MISC] =     "Misc",
378 };
379
380 struct wm_adsp_system_config_xm_hdr {
381         __be32 sys_enable;
382         __be32 fw_id;
383         __be32 fw_rev;
384         __be32 boot_status;
385         __be32 watchdog;
386         __be32 dma_buffer_size;
387         __be32 rdma[6];
388         __be32 wdma[8];
389         __be32 build_job_name[3];
390         __be32 build_job_number;
391 };
392
393 struct wm_halo_system_config_xm_hdr {
394         __be32 halo_heartbeat;
395         __be32 build_job_name[3];
396         __be32 build_job_number;
397 };
398
399 struct wm_adsp_alg_xm_struct {
400         __be32 magic;
401         __be32 smoothing;
402         __be32 threshold;
403         __be32 host_buf_ptr;
404         __be32 start_seq;
405         __be32 high_water_mark;
406         __be32 low_water_mark;
407         __be64 smoothed_power;
408 };
409
410 struct wm_adsp_host_buf_coeff_v1 {
411         __be32 host_buf_ptr;            /* Host buffer pointer */
412         __be32 versions;                /* Version numbers */
413         __be32 name[4];                 /* The buffer name */
414 };
415
416 struct wm_adsp_buffer {
417         __be32 buf1_base;               /* Base addr of first buffer area */
418         __be32 buf1_size;               /* Size of buf1 area in DSP words */
419         __be32 buf2_base;               /* Base addr of 2nd buffer area */
420         __be32 buf1_buf2_size;          /* Size of buf1+buf2 in DSP words */
421         __be32 buf3_base;               /* Base addr of buf3 area */
422         __be32 buf_total_size;          /* Size of buf1+buf2+buf3 in DSP words */
423         __be32 high_water_mark;         /* Point at which IRQ is asserted */
424         __be32 irq_count;               /* bits 1-31 count IRQ assertions */
425         __be32 irq_ack;                 /* acked IRQ count, bit 0 enables IRQ */
426         __be32 next_write_index;        /* word index of next write */
427         __be32 next_read_index;         /* word index of next read */
428         __be32 error;                   /* error if any */
429         __be32 oldest_block_index;      /* word index of oldest surviving */
430         __be32 requested_rewind;        /* how many blocks rewind was done */
431         __be32 reserved_space;          /* internal */
432         __be32 min_free;                /* min free space since stream start */
433         __be32 blocks_written[2];       /* total blocks written (64 bit) */
434         __be32 words_written[2];        /* total words written (64 bit) */
435 };
436
437 struct wm_adsp_compr;
438
439 struct wm_adsp_compr_buf {
440         struct list_head list;
441         struct wm_adsp *dsp;
442         struct wm_adsp_compr *compr;
443
444         struct wm_adsp_buffer_region *regions;
445         u32 host_buf_ptr;
446
447         u32 error;
448         u32 irq_count;
449         int read_index;
450         int avail;
451         int host_buf_mem_type;
452
453         char *name;
454 };
455
456 struct wm_adsp_compr {
457         struct list_head list;
458         struct wm_adsp *dsp;
459         struct wm_adsp_compr_buf *buf;
460
461         struct snd_compr_stream *stream;
462         struct snd_compressed_buffer size;
463
464         u32 *raw_buf;
465         unsigned int copied_total;
466
467         unsigned int sample_rate;
468
469         const char *name;
470 };
471
472 #define WM_ADSP_DATA_WORD_SIZE         3
473
474 #define WM_ADSP_MIN_FRAGMENTS          1
475 #define WM_ADSP_MAX_FRAGMENTS          256
476 #define WM_ADSP_MIN_FRAGMENT_SIZE      (64 * WM_ADSP_DATA_WORD_SIZE)
477 #define WM_ADSP_MAX_FRAGMENT_SIZE      (4096 * WM_ADSP_DATA_WORD_SIZE)
478
479 #define WM_ADSP_ALG_XM_STRUCT_MAGIC    0x49aec7
480
481 #define HOST_BUFFER_FIELD(field) \
482         (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
483
484 #define ALG_XM_FIELD(field) \
485         (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
486
487 #define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER     1
488
489 #define HOST_BUF_COEFF_COMPAT_VER_MASK          0xFF00
490 #define HOST_BUF_COEFF_COMPAT_VER_SHIFT         8
491
492 static int wm_adsp_buffer_init(struct wm_adsp *dsp);
493 static int wm_adsp_buffer_free(struct wm_adsp *dsp);
494
495 struct wm_adsp_buffer_region {
496         unsigned int offset;
497         unsigned int cumulative_size;
498         unsigned int mem_type;
499         unsigned int base_addr;
500 };
501
502 struct wm_adsp_buffer_region_def {
503         unsigned int mem_type;
504         unsigned int base_offset;
505         unsigned int size_offset;
506 };
507
508 static const struct wm_adsp_buffer_region_def default_regions[] = {
509         {
510                 .mem_type = WMFW_ADSP2_XM,
511                 .base_offset = HOST_BUFFER_FIELD(buf1_base),
512                 .size_offset = HOST_BUFFER_FIELD(buf1_size),
513         },
514         {
515                 .mem_type = WMFW_ADSP2_XM,
516                 .base_offset = HOST_BUFFER_FIELD(buf2_base),
517                 .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size),
518         },
519         {
520                 .mem_type = WMFW_ADSP2_YM,
521                 .base_offset = HOST_BUFFER_FIELD(buf3_base),
522                 .size_offset = HOST_BUFFER_FIELD(buf_total_size),
523         },
524 };
525
526 struct wm_adsp_fw_caps {
527         u32 id;
528         struct snd_codec_desc desc;
529         int num_regions;
530         const struct wm_adsp_buffer_region_def *region_defs;
531 };
532
533 static const struct wm_adsp_fw_caps ctrl_caps[] = {
534         {
535                 .id = SND_AUDIOCODEC_BESPOKE,
536                 .desc = {
537                         .max_ch = 8,
538                         .sample_rates = { 16000 },
539                         .num_sample_rates = 1,
540                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
541                 },
542                 .num_regions = ARRAY_SIZE(default_regions),
543                 .region_defs = default_regions,
544         },
545 };
546
547 static const struct wm_adsp_fw_caps trace_caps[] = {
548         {
549                 .id = SND_AUDIOCODEC_BESPOKE,
550                 .desc = {
551                         .max_ch = 8,
552                         .sample_rates = {
553                                 4000, 8000, 11025, 12000, 16000, 22050,
554                                 24000, 32000, 44100, 48000, 64000, 88200,
555                                 96000, 176400, 192000
556                         },
557                         .num_sample_rates = 15,
558                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
559                 },
560                 .num_regions = ARRAY_SIZE(default_regions),
561                 .region_defs = default_regions,
562         },
563 };
564
565 static const struct {
566         const char *file;
567         int compr_direction;
568         int num_caps;
569         const struct wm_adsp_fw_caps *caps;
570         bool voice_trigger;
571 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
572         [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
573         [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
574         [WM_ADSP_FW_TX] =       { .file = "tx" },
575         [WM_ADSP_FW_TX_SPK] =   { .file = "tx-spk" },
576         [WM_ADSP_FW_RX] =       { .file = "rx" },
577         [WM_ADSP_FW_RX_ANC] =   { .file = "rx-anc" },
578         [WM_ADSP_FW_CTRL] =     {
579                 .file = "ctrl",
580                 .compr_direction = SND_COMPRESS_CAPTURE,
581                 .num_caps = ARRAY_SIZE(ctrl_caps),
582                 .caps = ctrl_caps,
583                 .voice_trigger = true,
584         },
585         [WM_ADSP_FW_ASR] =      { .file = "asr" },
586         [WM_ADSP_FW_TRACE] =    {
587                 .file = "trace",
588                 .compr_direction = SND_COMPRESS_CAPTURE,
589                 .num_caps = ARRAY_SIZE(trace_caps),
590                 .caps = trace_caps,
591         },
592         [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
593         [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" },
594         [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" },
595         [WM_ADSP_FW_MISC] =     { .file = "misc" },
596 };
597
598 struct wm_coeff_ctl {
599         const char *name;
600         const char *fw_name;
601         /* Subname is needed to match with firmware */
602         const char *subname;
603         unsigned int subname_len;
604         struct wm_adsp_alg_region alg_region;
605         struct wm_adsp *dsp;
606         unsigned int enabled:1;
607         struct list_head list;
608         void *cache;
609         unsigned int offset;
610         size_t len;
611         unsigned int set:1;
612         struct soc_bytes_ext bytes_ext;
613         unsigned int flags;
614         snd_ctl_elem_type_t type;
615 };
616
617 static const char *wm_adsp_mem_region_name(unsigned int type)
618 {
619         switch (type) {
620         case WMFW_ADSP1_PM:
621                 return "PM";
622         case WMFW_HALO_PM_PACKED:
623                 return "PM_PACKED";
624         case WMFW_ADSP1_DM:
625                 return "DM";
626         case WMFW_ADSP2_XM:
627                 return "XM";
628         case WMFW_HALO_XM_PACKED:
629                 return "XM_PACKED";
630         case WMFW_ADSP2_YM:
631                 return "YM";
632         case WMFW_HALO_YM_PACKED:
633                 return "YM_PACKED";
634         case WMFW_ADSP1_ZM:
635                 return "ZM";
636         default:
637                 return NULL;
638         }
639 }
640
641 #ifdef CONFIG_DEBUG_FS
642 static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
643 {
644         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
645
646         kfree(dsp->wmfw_file_name);
647         dsp->wmfw_file_name = tmp;
648 }
649
650 static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
651 {
652         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
653
654         kfree(dsp->bin_file_name);
655         dsp->bin_file_name = tmp;
656 }
657
658 static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
659 {
660         kfree(dsp->wmfw_file_name);
661         kfree(dsp->bin_file_name);
662         dsp->wmfw_file_name = NULL;
663         dsp->bin_file_name = NULL;
664 }
665
666 static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
667                                          char __user *user_buf,
668                                          size_t count, loff_t *ppos)
669 {
670         struct wm_adsp *dsp = file->private_data;
671         ssize_t ret;
672
673         mutex_lock(&dsp->pwr_lock);
674
675         if (!dsp->wmfw_file_name || !dsp->booted)
676                 ret = 0;
677         else
678                 ret = simple_read_from_buffer(user_buf, count, ppos,
679                                               dsp->wmfw_file_name,
680                                               strlen(dsp->wmfw_file_name));
681
682         mutex_unlock(&dsp->pwr_lock);
683         return ret;
684 }
685
686 static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
687                                         char __user *user_buf,
688                                         size_t count, loff_t *ppos)
689 {
690         struct wm_adsp *dsp = file->private_data;
691         ssize_t ret;
692
693         mutex_lock(&dsp->pwr_lock);
694
695         if (!dsp->bin_file_name || !dsp->booted)
696                 ret = 0;
697         else
698                 ret = simple_read_from_buffer(user_buf, count, ppos,
699                                               dsp->bin_file_name,
700                                               strlen(dsp->bin_file_name));
701
702         mutex_unlock(&dsp->pwr_lock);
703         return ret;
704 }
705
706 static const struct {
707         const char *name;
708         const struct file_operations fops;
709 } wm_adsp_debugfs_fops[] = {
710         {
711                 .name = "wmfw_file_name",
712                 .fops = {
713                         .open = simple_open,
714                         .read = wm_adsp_debugfs_wmfw_read,
715                 },
716         },
717         {
718                 .name = "bin_file_name",
719                 .fops = {
720                         .open = simple_open,
721                         .read = wm_adsp_debugfs_bin_read,
722                 },
723         },
724 };
725
726 static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
727                                   struct snd_soc_component *component)
728 {
729         struct dentry *root = NULL;
730         int i;
731
732         root = debugfs_create_dir(dsp->name, component->debugfs_root);
733
734         debugfs_create_bool("booted", 0444, root, &dsp->booted);
735         debugfs_create_bool("running", 0444, root, &dsp->running);
736         debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id);
737         debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version);
738
739         for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i)
740                 debugfs_create_file(wm_adsp_debugfs_fops[i].name, 0444, root,
741                                     dsp, &wm_adsp_debugfs_fops[i].fops);
742
743         dsp->debugfs_root = root;
744 }
745
746 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
747 {
748         wm_adsp_debugfs_clear(dsp);
749         debugfs_remove_recursive(dsp->debugfs_root);
750 }
751 #else
752 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
753                                          struct snd_soc_component *component)
754 {
755 }
756
757 static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
758 {
759 }
760
761 static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp,
762                                                  const char *s)
763 {
764 }
765
766 static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp,
767                                                 const char *s)
768 {
769 }
770
771 static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
772 {
773 }
774 #endif
775
776 int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
777                    struct snd_ctl_elem_value *ucontrol)
778 {
779         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
780         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
781         struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
782
783         ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
784
785         return 0;
786 }
787 EXPORT_SYMBOL_GPL(wm_adsp_fw_get);
788
789 int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
790                    struct snd_ctl_elem_value *ucontrol)
791 {
792         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
793         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
794         struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
795         int ret = 0;
796
797         if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
798                 return 0;
799
800         if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
801                 return -EINVAL;
802
803         mutex_lock(&dsp[e->shift_l].pwr_lock);
804
805         if (dsp[e->shift_l].booted || !list_empty(&dsp[e->shift_l].compr_list))
806                 ret = -EBUSY;
807         else
808                 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
809
810         mutex_unlock(&dsp[e->shift_l].pwr_lock);
811
812         return ret;
813 }
814 EXPORT_SYMBOL_GPL(wm_adsp_fw_put);
815
816 const struct soc_enum wm_adsp_fw_enum[] = {
817         SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
818         SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
819         SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
820         SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
821         SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
822         SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
823         SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
824 };
825 EXPORT_SYMBOL_GPL(wm_adsp_fw_enum);
826
827 static const struct wm_adsp_region *wm_adsp_find_region(struct wm_adsp *dsp,
828                                                         int type)
829 {
830         int i;
831
832         for (i = 0; i < dsp->num_mems; i++)
833                 if (dsp->mem[i].type == type)
834                         return &dsp->mem[i];
835
836         return NULL;
837 }
838
839 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
840                                           unsigned int offset)
841 {
842         switch (mem->type) {
843         case WMFW_ADSP1_PM:
844                 return mem->base + (offset * 3);
845         case WMFW_ADSP1_DM:
846         case WMFW_ADSP2_XM:
847         case WMFW_ADSP2_YM:
848         case WMFW_ADSP1_ZM:
849                 return mem->base + (offset * 2);
850         default:
851                 WARN(1, "Unknown memory region type");
852                 return offset;
853         }
854 }
855
856 static unsigned int wm_halo_region_to_reg(struct wm_adsp_region const *mem,
857                                           unsigned int offset)
858 {
859         switch (mem->type) {
860         case WMFW_ADSP2_XM:
861         case WMFW_ADSP2_YM:
862                 return mem->base + (offset * 4);
863         case WMFW_HALO_XM_PACKED:
864         case WMFW_HALO_YM_PACKED:
865                 return (mem->base + (offset * 3)) & ~0x3;
866         case WMFW_HALO_PM_PACKED:
867                 return mem->base + (offset * 5);
868         default:
869                 WARN(1, "Unknown memory region type");
870                 return offset;
871         }
872 }
873
874 static void wm_adsp_read_fw_status(struct wm_adsp *dsp,
875                                    int noffs, unsigned int *offs)
876 {
877         unsigned int i;
878         int ret;
879
880         for (i = 0; i < noffs; ++i) {
881                 ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]);
882                 if (ret) {
883                         adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
884                         return;
885                 }
886         }
887 }
888
889 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
890 {
891         unsigned int offs[] = {
892                 ADSP2_SCRATCH0, ADSP2_SCRATCH1, ADSP2_SCRATCH2, ADSP2_SCRATCH3,
893         };
894
895         wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
896
897         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
898                  offs[0], offs[1], offs[2], offs[3]);
899 }
900
901 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp)
902 {
903         unsigned int offs[] = { ADSP2V2_SCRATCH0_1, ADSP2V2_SCRATCH2_3 };
904
905         wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
906
907         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
908                  offs[0] & 0xFFFF, offs[0] >> 16,
909                  offs[1] & 0xFFFF, offs[1] >> 16);
910 }
911
912 static void wm_halo_show_fw_status(struct wm_adsp *dsp)
913 {
914         unsigned int offs[] = {
915                 HALO_SCRATCH1, HALO_SCRATCH2, HALO_SCRATCH3, HALO_SCRATCH4,
916         };
917
918         wm_adsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
919
920         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
921                  offs[0], offs[1], offs[2], offs[3]);
922 }
923
924 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
925 {
926         return container_of(ext, struct wm_coeff_ctl, bytes_ext);
927 }
928
929 static int wm_coeff_base_reg(struct wm_coeff_ctl *ctl, unsigned int *reg)
930 {
931         const struct wm_adsp_alg_region *alg_region = &ctl->alg_region;
932         struct wm_adsp *dsp = ctl->dsp;
933         const struct wm_adsp_region *mem;
934
935         mem = wm_adsp_find_region(dsp, alg_region->type);
936         if (!mem) {
937                 adsp_err(dsp, "No base for region %x\n",
938                          alg_region->type);
939                 return -EINVAL;
940         }
941
942         *reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset);
943
944         return 0;
945 }
946
947 static int wm_coeff_info(struct snd_kcontrol *kctl,
948                          struct snd_ctl_elem_info *uinfo)
949 {
950         struct soc_bytes_ext *bytes_ext =
951                 (struct soc_bytes_ext *)kctl->private_value;
952         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
953
954         switch (ctl->type) {
955         case WMFW_CTL_TYPE_ACKED:
956                 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
957                 uinfo->value.integer.min = WM_ADSP_ACKED_CTL_MIN_VALUE;
958                 uinfo->value.integer.max = WM_ADSP_ACKED_CTL_MAX_VALUE;
959                 uinfo->value.integer.step = 1;
960                 uinfo->count = 1;
961                 break;
962         default:
963                 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
964                 uinfo->count = ctl->len;
965                 break;
966         }
967
968         return 0;
969 }
970
971 static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
972                                         unsigned int event_id)
973 {
974         struct wm_adsp *dsp = ctl->dsp;
975         __be32 val = cpu_to_be32(event_id);
976         unsigned int reg;
977         int i, ret;
978
979         ret = wm_coeff_base_reg(ctl, &reg);
980         if (ret)
981                 return ret;
982
983         adsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n",
984                  event_id, ctl->alg_region.alg,
985                  wm_adsp_mem_region_name(ctl->alg_region.type), ctl->offset);
986
987         ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
988         if (ret) {
989                 adsp_err(dsp, "Failed to write %x: %d\n", reg, ret);
990                 return ret;
991         }
992
993         /*
994          * Poll for ack, we initially poll at ~1ms intervals for firmwares
995          * that respond quickly, then go to ~10ms polls. A firmware is unlikely
996          * to ack instantly so we do the first 1ms delay before reading the
997          * control to avoid a pointless bus transaction
998          */
999         for (i = 0; i < WM_ADSP_ACKED_CTL_TIMEOUT_MS;) {
1000                 switch (i) {
1001                 case 0 ... WM_ADSP_ACKED_CTL_N_QUICKPOLLS - 1:
1002                         usleep_range(1000, 2000);
1003                         i++;
1004                         break;
1005                 default:
1006                         usleep_range(10000, 20000);
1007                         i += 10;
1008                         break;
1009                 }
1010
1011                 ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
1012                 if (ret) {
1013                         adsp_err(dsp, "Failed to read %x: %d\n", reg, ret);
1014                         return ret;
1015                 }
1016
1017                 if (val == 0) {
1018                         adsp_dbg(dsp, "Acked control ACKED at poll %u\n", i);
1019                         return 0;
1020                 }
1021         }
1022
1023         adsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n",
1024                   reg, ctl->alg_region.alg,
1025                   wm_adsp_mem_region_name(ctl->alg_region.type),
1026                   ctl->offset);
1027
1028         return -ETIMEDOUT;
1029 }
1030
1031 static int wm_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
1032                                    const void *buf, size_t len)
1033 {
1034         struct wm_adsp *dsp = ctl->dsp;
1035         void *scratch;
1036         int ret;
1037         unsigned int reg;
1038
1039         ret = wm_coeff_base_reg(ctl, &reg);
1040         if (ret)
1041                 return ret;
1042
1043         scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
1044         if (!scratch)
1045                 return -ENOMEM;
1046
1047         ret = regmap_raw_write(dsp->regmap, reg, scratch,
1048                                len);
1049         if (ret) {
1050                 adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
1051                          len, reg, ret);
1052                 kfree(scratch);
1053                 return ret;
1054         }
1055         adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
1056
1057         kfree(scratch);
1058
1059         return 0;
1060 }
1061
1062 static int wm_coeff_write_ctrl(struct wm_coeff_ctl *ctl,
1063                                const void *buf, size_t len)
1064 {
1065         int ret = 0;
1066
1067         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1068                 ret = -EPERM;
1069         else if (buf != ctl->cache)
1070                 memcpy(ctl->cache, buf, len);
1071
1072         ctl->set = 1;
1073         if (ctl->enabled && ctl->dsp->running)
1074                 ret = wm_coeff_write_ctrl_raw(ctl, buf, len);
1075
1076         return ret;
1077 }
1078
1079 static int wm_coeff_put(struct snd_kcontrol *kctl,
1080                         struct snd_ctl_elem_value *ucontrol)
1081 {
1082         struct soc_bytes_ext *bytes_ext =
1083                 (struct soc_bytes_ext *)kctl->private_value;
1084         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1085         char *p = ucontrol->value.bytes.data;
1086         int ret = 0;
1087
1088         mutex_lock(&ctl->dsp->pwr_lock);
1089         ret = wm_coeff_write_ctrl(ctl, p, ctl->len);
1090         mutex_unlock(&ctl->dsp->pwr_lock);
1091
1092         return ret;
1093 }
1094
1095 static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
1096                             const unsigned int __user *bytes, unsigned int size)
1097 {
1098         struct soc_bytes_ext *bytes_ext =
1099                 (struct soc_bytes_ext *)kctl->private_value;
1100         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1101         int ret = 0;
1102
1103         mutex_lock(&ctl->dsp->pwr_lock);
1104
1105         if (copy_from_user(ctl->cache, bytes, size))
1106                 ret = -EFAULT;
1107         else
1108                 ret = wm_coeff_write_ctrl(ctl, ctl->cache, size);
1109
1110         mutex_unlock(&ctl->dsp->pwr_lock);
1111
1112         return ret;
1113 }
1114
1115 static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
1116                               struct snd_ctl_elem_value *ucontrol)
1117 {
1118         struct soc_bytes_ext *bytes_ext =
1119                 (struct soc_bytes_ext *)kctl->private_value;
1120         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1121         unsigned int val = ucontrol->value.integer.value[0];
1122         int ret;
1123
1124         if (val == 0)
1125                 return 0;       /* 0 means no event */
1126
1127         mutex_lock(&ctl->dsp->pwr_lock);
1128
1129         if (ctl->enabled && ctl->dsp->running)
1130                 ret = wm_coeff_write_acked_control(ctl, val);
1131         else
1132                 ret = -EPERM;
1133
1134         mutex_unlock(&ctl->dsp->pwr_lock);
1135
1136         return ret;
1137 }
1138
1139 static int wm_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
1140                                   void *buf, size_t len)
1141 {
1142         struct wm_adsp *dsp = ctl->dsp;
1143         void *scratch;
1144         int ret;
1145         unsigned int reg;
1146
1147         ret = wm_coeff_base_reg(ctl, &reg);
1148         if (ret)
1149                 return ret;
1150
1151         scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
1152         if (!scratch)
1153                 return -ENOMEM;
1154
1155         ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
1156         if (ret) {
1157                 adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
1158                          len, reg, ret);
1159                 kfree(scratch);
1160                 return ret;
1161         }
1162         adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
1163
1164         memcpy(buf, scratch, len);
1165         kfree(scratch);
1166
1167         return 0;
1168 }
1169
1170 static int wm_coeff_read_ctrl(struct wm_coeff_ctl *ctl, void *buf, size_t len)
1171 {
1172         int ret = 0;
1173
1174         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
1175                 if (ctl->enabled && ctl->dsp->running)
1176                         return wm_coeff_read_ctrl_raw(ctl, buf, len);
1177                 else
1178                         return -EPERM;
1179         } else {
1180                 if (!ctl->flags && ctl->enabled && ctl->dsp->running)
1181                         ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
1182
1183                 if (buf != ctl->cache)
1184                         memcpy(buf, ctl->cache, len);
1185         }
1186
1187         return ret;
1188 }
1189
1190 static int wm_coeff_get(struct snd_kcontrol *kctl,
1191                         struct snd_ctl_elem_value *ucontrol)
1192 {
1193         struct soc_bytes_ext *bytes_ext =
1194                 (struct soc_bytes_ext *)kctl->private_value;
1195         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1196         char *p = ucontrol->value.bytes.data;
1197         int ret;
1198
1199         mutex_lock(&ctl->dsp->pwr_lock);
1200         ret = wm_coeff_read_ctrl(ctl, p, ctl->len);
1201         mutex_unlock(&ctl->dsp->pwr_lock);
1202
1203         return ret;
1204 }
1205
1206 static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
1207                             unsigned int __user *bytes, unsigned int size)
1208 {
1209         struct soc_bytes_ext *bytes_ext =
1210                 (struct soc_bytes_ext *)kctl->private_value;
1211         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
1212         int ret = 0;
1213
1214         mutex_lock(&ctl->dsp->pwr_lock);
1215
1216         ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, size);
1217
1218         if (!ret && copy_to_user(bytes, ctl->cache, size))
1219                 ret = -EFAULT;
1220
1221         mutex_unlock(&ctl->dsp->pwr_lock);
1222
1223         return ret;
1224 }
1225
1226 static int wm_coeff_get_acked(struct snd_kcontrol *kcontrol,
1227                               struct snd_ctl_elem_value *ucontrol)
1228 {
1229         /*
1230          * Although it's not useful to read an acked control, we must satisfy
1231          * user-side assumptions that all controls are readable and that a
1232          * write of the same value should be filtered out (it's valid to send
1233          * the same event number again to the firmware). We therefore return 0,
1234          * meaning "no event" so valid event numbers will always be a change
1235          */
1236         ucontrol->value.integer.value[0] = 0;
1237
1238         return 0;
1239 }
1240
1241 struct wmfw_ctl_work {
1242         struct wm_adsp *dsp;
1243         struct wm_coeff_ctl *ctl;
1244         struct work_struct work;
1245 };
1246
1247 static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
1248 {
1249         unsigned int out, rd, wr, vol;
1250
1251         if (len > ADSP_MAX_STD_CTRL_SIZE) {
1252                 rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
1253                 wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
1254                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
1255
1256                 out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
1257         } else {
1258                 rd = SNDRV_CTL_ELEM_ACCESS_READ;
1259                 wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
1260                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
1261
1262                 out = 0;
1263         }
1264
1265         if (in) {
1266                 out |= rd;
1267                 if (in & WMFW_CTL_FLAG_WRITEABLE)
1268                         out |= wr;
1269                 if (in & WMFW_CTL_FLAG_VOLATILE)
1270                         out |= vol;
1271         } else {
1272                 out |= rd | wr | vol;
1273         }
1274
1275         return out;
1276 }
1277
1278 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
1279 {
1280         struct snd_kcontrol_new *kcontrol;
1281         int ret;
1282
1283         if (!ctl || !ctl->name)
1284                 return -EINVAL;
1285
1286         kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
1287         if (!kcontrol)
1288                 return -ENOMEM;
1289
1290         kcontrol->name = ctl->name;
1291         kcontrol->info = wm_coeff_info;
1292         kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1293         kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
1294         kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
1295         kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len);
1296
1297         switch (ctl->type) {
1298         case WMFW_CTL_TYPE_ACKED:
1299                 kcontrol->get = wm_coeff_get_acked;
1300                 kcontrol->put = wm_coeff_put_acked;
1301                 break;
1302         default:
1303                 if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
1304                         ctl->bytes_ext.max = ctl->len;
1305                         ctl->bytes_ext.get = wm_coeff_tlv_get;
1306                         ctl->bytes_ext.put = wm_coeff_tlv_put;
1307                 } else {
1308                         kcontrol->get = wm_coeff_get;
1309                         kcontrol->put = wm_coeff_put;
1310                 }
1311                 break;
1312         }
1313
1314         ret = snd_soc_add_component_controls(dsp->component, kcontrol, 1);
1315         if (ret < 0)
1316                 goto err_kcontrol;
1317
1318         kfree(kcontrol);
1319
1320         return 0;
1321
1322 err_kcontrol:
1323         kfree(kcontrol);
1324         return ret;
1325 }
1326
1327 static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
1328 {
1329         struct wm_coeff_ctl *ctl;
1330         int ret;
1331
1332         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1333                 if (!ctl->enabled || ctl->set)
1334                         continue;
1335                 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1336                         continue;
1337
1338                 /*
1339                  * For readable controls populate the cache from the DSP memory.
1340                  * For non-readable controls the cache was zero-filled when
1341                  * created so we don't need to do anything.
1342                  */
1343                 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
1344                         ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
1345                         if (ret < 0)
1346                                 return ret;
1347                 }
1348         }
1349
1350         return 0;
1351 }
1352
1353 static int wm_coeff_sync_controls(struct wm_adsp *dsp)
1354 {
1355         struct wm_coeff_ctl *ctl;
1356         int ret;
1357
1358         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1359                 if (!ctl->enabled)
1360                         continue;
1361                 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
1362                         ret = wm_coeff_write_ctrl_raw(ctl, ctl->cache,
1363                                                       ctl->len);
1364                         if (ret < 0)
1365                                 return ret;
1366                 }
1367         }
1368
1369         return 0;
1370 }
1371
1372 static void wm_adsp_signal_event_controls(struct wm_adsp *dsp,
1373                                           unsigned int event)
1374 {
1375         struct wm_coeff_ctl *ctl;
1376         int ret;
1377
1378         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1379                 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT)
1380                         continue;
1381
1382                 if (!ctl->enabled)
1383                         continue;
1384
1385                 ret = wm_coeff_write_acked_control(ctl, event);
1386                 if (ret)
1387                         adsp_warn(dsp,
1388                                   "Failed to send 0x%x event to alg 0x%x (%d)\n",
1389                                   event, ctl->alg_region.alg, ret);
1390         }
1391 }
1392
1393 static void wm_adsp_ctl_work(struct work_struct *work)
1394 {
1395         struct wmfw_ctl_work *ctl_work = container_of(work,
1396                                                       struct wmfw_ctl_work,
1397                                                       work);
1398
1399         wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl);
1400         kfree(ctl_work);
1401 }
1402
1403 static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl)
1404 {
1405         kfree(ctl->cache);
1406         kfree(ctl->name);
1407         kfree(ctl->subname);
1408         kfree(ctl);
1409 }
1410
1411 static int wm_adsp_create_control(struct wm_adsp *dsp,
1412                                   const struct wm_adsp_alg_region *alg_region,
1413                                   unsigned int offset, unsigned int len,
1414                                   const char *subname, unsigned int subname_len,
1415                                   unsigned int flags, snd_ctl_elem_type_t type)
1416 {
1417         struct wm_coeff_ctl *ctl;
1418         struct wmfw_ctl_work *ctl_work;
1419         char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1420         const char *region_name;
1421         int ret;
1422
1423         region_name = wm_adsp_mem_region_name(alg_region->type);
1424         if (!region_name) {
1425                 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type);
1426                 return -EINVAL;
1427         }
1428
1429         switch (dsp->fw_ver) {
1430         case 0:
1431         case 1:
1432                 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %x",
1433                          dsp->name, region_name, alg_region->alg);
1434                 subname = NULL; /* don't append subname */
1435                 break;
1436         case 2:
1437                 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1438                                 "%s%c %.12s %x", dsp->name, *region_name,
1439                                 wm_adsp_fw_text[dsp->fw], alg_region->alg);
1440                 break;
1441         default:
1442                 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1443                                 "%s %.12s %x", dsp->name,
1444                                 wm_adsp_fw_text[dsp->fw], alg_region->alg);
1445                 break;
1446         }
1447
1448         if (subname) {
1449                 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
1450                 int skip = 0;
1451
1452                 if (dsp->component->name_prefix)
1453                         avail -= strlen(dsp->component->name_prefix) + 1;
1454
1455                 /* Truncate the subname from the start if it is too long */
1456                 if (subname_len > avail)
1457                         skip = subname_len - avail;
1458
1459                 snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
1460                          " %.*s", subname_len - skip, subname + skip);
1461         }
1462
1463         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1464                 if (!strcmp(ctl->name, name)) {
1465                         if (!ctl->enabled)
1466                                 ctl->enabled = 1;
1467                         return 0;
1468                 }
1469         }
1470
1471         ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
1472         if (!ctl)
1473                 return -ENOMEM;
1474         ctl->fw_name = wm_adsp_fw_text[dsp->fw];
1475         ctl->alg_region = *alg_region;
1476         ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
1477         if (!ctl->name) {
1478                 ret = -ENOMEM;
1479                 goto err_ctl;
1480         }
1481         if (subname) {
1482                 ctl->subname_len = subname_len;
1483                 ctl->subname = kmemdup(subname,
1484                                        strlen(subname) + 1, GFP_KERNEL);
1485                 if (!ctl->subname) {
1486                         ret = -ENOMEM;
1487                         goto err_ctl_name;
1488                 }
1489         }
1490         ctl->enabled = 1;
1491         ctl->set = 0;
1492         ctl->dsp = dsp;
1493
1494         ctl->flags = flags;
1495         ctl->type = type;
1496         ctl->offset = offset;
1497         ctl->len = len;
1498         ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
1499         if (!ctl->cache) {
1500                 ret = -ENOMEM;
1501                 goto err_ctl_subname;
1502         }
1503
1504         list_add(&ctl->list, &dsp->ctl_list);
1505
1506         if (flags & WMFW_CTL_FLAG_SYS)
1507                 return 0;
1508
1509         ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
1510         if (!ctl_work) {
1511                 ret = -ENOMEM;
1512                 goto err_list_del;
1513         }
1514
1515         ctl_work->dsp = dsp;
1516         ctl_work->ctl = ctl;
1517         INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
1518         schedule_work(&ctl_work->work);
1519
1520         return 0;
1521
1522 err_list_del:
1523         list_del(&ctl->list);
1524         kfree(ctl->cache);
1525 err_ctl_subname:
1526         kfree(ctl->subname);
1527 err_ctl_name:
1528         kfree(ctl->name);
1529 err_ctl:
1530         kfree(ctl);
1531
1532         return ret;
1533 }
1534
1535 struct wm_coeff_parsed_alg {
1536         int id;
1537         const u8 *name;
1538         int name_len;
1539         int ncoeff;
1540 };
1541
1542 struct wm_coeff_parsed_coeff {
1543         int offset;
1544         int mem_type;
1545         const u8 *name;
1546         int name_len;
1547         snd_ctl_elem_type_t ctl_type;
1548         int flags;
1549         int len;
1550 };
1551
1552 static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1553 {
1554         int length;
1555
1556         switch (bytes) {
1557         case 1:
1558                 length = **pos;
1559                 break;
1560         case 2:
1561                 length = le16_to_cpu(*((__le16 *)*pos));
1562                 break;
1563         default:
1564                 return 0;
1565         }
1566
1567         if (str)
1568                 *str = *pos + bytes;
1569
1570         *pos += ((length + bytes) + 3) & ~0x03;
1571
1572         return length;
1573 }
1574
1575 static int wm_coeff_parse_int(int bytes, const u8 **pos)
1576 {
1577         int val = 0;
1578
1579         switch (bytes) {
1580         case 2:
1581                 val = le16_to_cpu(*((__le16 *)*pos));
1582                 break;
1583         case 4:
1584                 val = le32_to_cpu(*((__le32 *)*pos));
1585                 break;
1586         default:
1587                 break;
1588         }
1589
1590         *pos += bytes;
1591
1592         return val;
1593 }
1594
1595 static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data,
1596                                       struct wm_coeff_parsed_alg *blk)
1597 {
1598         const struct wmfw_adsp_alg_data *raw;
1599
1600         switch (dsp->fw_ver) {
1601         case 0:
1602         case 1:
1603                 raw = (const struct wmfw_adsp_alg_data *)*data;
1604                 *data = raw->data;
1605
1606                 blk->id = le32_to_cpu(raw->id);
1607                 blk->name = raw->name;
1608                 blk->name_len = strlen(raw->name);
1609                 blk->ncoeff = le32_to_cpu(raw->ncoeff);
1610                 break;
1611         default:
1612                 blk->id = wm_coeff_parse_int(sizeof(raw->id), data);
1613                 blk->name_len = wm_coeff_parse_string(sizeof(u8), data,
1614                                                       &blk->name);
1615                 wm_coeff_parse_string(sizeof(u16), data, NULL);
1616                 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data);
1617                 break;
1618         }
1619
1620         adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
1621         adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
1622         adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1623 }
1624
1625 static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
1626                                         struct wm_coeff_parsed_coeff *blk)
1627 {
1628         const struct wmfw_adsp_coeff_data *raw;
1629         const u8 *tmp;
1630         int length;
1631
1632         switch (dsp->fw_ver) {
1633         case 0:
1634         case 1:
1635                 raw = (const struct wmfw_adsp_coeff_data *)*data;
1636                 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
1637
1638                 blk->offset = le16_to_cpu(raw->hdr.offset);
1639                 blk->mem_type = le16_to_cpu(raw->hdr.type);
1640                 blk->name = raw->name;
1641                 blk->name_len = strlen(raw->name);
1642                 blk->ctl_type = (__force snd_ctl_elem_type_t)le16_to_cpu(raw->ctl_type);
1643                 blk->flags = le16_to_cpu(raw->flags);
1644                 blk->len = le32_to_cpu(raw->len);
1645                 break;
1646         default:
1647                 tmp = *data;
1648                 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
1649                 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
1650                 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
1651                 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp,
1652                                                       &blk->name);
1653                 wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
1654                 wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
1655                 blk->ctl_type =
1656                         (__force snd_ctl_elem_type_t)wm_coeff_parse_int(sizeof(raw->ctl_type),
1657                                                                         &tmp);
1658                 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
1659                 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
1660
1661                 *data = *data + sizeof(raw->hdr) + length;
1662                 break;
1663         }
1664
1665         adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
1666         adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
1667         adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name);
1668         adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
1669         adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
1670         adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1671 }
1672
1673 static int wm_adsp_check_coeff_flags(struct wm_adsp *dsp,
1674                                 const struct wm_coeff_parsed_coeff *coeff_blk,
1675                                 unsigned int f_required,
1676                                 unsigned int f_illegal)
1677 {
1678         if ((coeff_blk->flags & f_illegal) ||
1679             ((coeff_blk->flags & f_required) != f_required)) {
1680                 adsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n",
1681                          coeff_blk->flags, coeff_blk->ctl_type);
1682                 return -EINVAL;
1683         }
1684
1685         return 0;
1686 }
1687
1688 static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
1689                                const struct wmfw_region *region)
1690 {
1691         struct wm_adsp_alg_region alg_region = {};
1692         struct wm_coeff_parsed_alg alg_blk;
1693         struct wm_coeff_parsed_coeff coeff_blk;
1694         const u8 *data = region->data;
1695         int i, ret;
1696
1697         wm_coeff_parse_alg(dsp, &data, &alg_blk);
1698         for (i = 0; i < alg_blk.ncoeff; i++) {
1699                 wm_coeff_parse_coeff(dsp, &data, &coeff_blk);
1700
1701                 switch (coeff_blk.ctl_type) {
1702                 case SNDRV_CTL_ELEM_TYPE_BYTES:
1703                         break;
1704                 case WMFW_CTL_TYPE_ACKED:
1705                         if (coeff_blk.flags & WMFW_CTL_FLAG_SYS)
1706                                 continue;       /* ignore */
1707
1708                         ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
1709                                                 WMFW_CTL_FLAG_VOLATILE |
1710                                                 WMFW_CTL_FLAG_WRITEABLE |
1711                                                 WMFW_CTL_FLAG_READABLE,
1712                                                 0);
1713                         if (ret)
1714                                 return -EINVAL;
1715                         break;
1716                 case WMFW_CTL_TYPE_HOSTEVENT:
1717                         ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
1718                                                 WMFW_CTL_FLAG_SYS |
1719                                                 WMFW_CTL_FLAG_VOLATILE |
1720                                                 WMFW_CTL_FLAG_WRITEABLE |
1721                                                 WMFW_CTL_FLAG_READABLE,
1722                                                 0);
1723                         if (ret)
1724                                 return -EINVAL;
1725                         break;
1726                 case WMFW_CTL_TYPE_HOST_BUFFER:
1727                         ret = wm_adsp_check_coeff_flags(dsp, &coeff_blk,
1728                                                 WMFW_CTL_FLAG_SYS |
1729                                                 WMFW_CTL_FLAG_VOLATILE |
1730                                                 WMFW_CTL_FLAG_READABLE,
1731                                                 0);
1732                         if (ret)
1733                                 return -EINVAL;
1734                         break;
1735                 default:
1736                         adsp_err(dsp, "Unknown control type: %d\n",
1737                                  coeff_blk.ctl_type);
1738                         return -EINVAL;
1739                 }
1740
1741                 alg_region.type = coeff_blk.mem_type;
1742                 alg_region.alg = alg_blk.id;
1743
1744                 ret = wm_adsp_create_control(dsp, &alg_region,
1745                                              coeff_blk.offset,
1746                                              coeff_blk.len,
1747                                              coeff_blk.name,
1748                                              coeff_blk.name_len,
1749                                              coeff_blk.flags,
1750                                              coeff_blk.ctl_type);
1751                 if (ret < 0)
1752                         adsp_err(dsp, "Failed to create control: %.*s, %d\n",
1753                                  coeff_blk.name_len, coeff_blk.name, ret);
1754         }
1755
1756         return 0;
1757 }
1758
1759 static unsigned int wm_adsp1_parse_sizes(struct wm_adsp *dsp,
1760                                          const char * const file,
1761                                          unsigned int pos,
1762                                          const struct firmware *firmware)
1763 {
1764         const struct wmfw_adsp1_sizes *adsp1_sizes;
1765
1766         adsp1_sizes = (void *)&firmware->data[pos];
1767
1768         adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
1769                  le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
1770                  le32_to_cpu(adsp1_sizes->zm));
1771
1772         return pos + sizeof(*adsp1_sizes);
1773 }
1774
1775 static unsigned int wm_adsp2_parse_sizes(struct wm_adsp *dsp,
1776                                          const char * const file,
1777                                          unsigned int pos,
1778                                          const struct firmware *firmware)
1779 {
1780         const struct wmfw_adsp2_sizes *adsp2_sizes;
1781
1782         adsp2_sizes = (void *)&firmware->data[pos];
1783
1784         adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
1785                  le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
1786                  le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm));
1787
1788         return pos + sizeof(*adsp2_sizes);
1789 }
1790
1791 static bool wm_adsp_validate_version(struct wm_adsp *dsp, unsigned int version)
1792 {
1793         switch (version) {
1794         case 0:
1795                 adsp_warn(dsp, "Deprecated file format %d\n", version);
1796                 return true;
1797         case 1:
1798         case 2:
1799                 return true;
1800         default:
1801                 return false;
1802         }
1803 }
1804
1805 static bool wm_halo_validate_version(struct wm_adsp *dsp, unsigned int version)
1806 {
1807         switch (version) {
1808         case 3:
1809                 return true;
1810         default:
1811                 return false;
1812         }
1813 }
1814
1815 static int wm_adsp_load(struct wm_adsp *dsp)
1816 {
1817         LIST_HEAD(buf_list);
1818         const struct firmware *firmware;
1819         struct regmap *regmap = dsp->regmap;
1820         unsigned int pos = 0;
1821         const struct wmfw_header *header;
1822         const struct wmfw_adsp1_sizes *adsp1_sizes;
1823         const struct wmfw_footer *footer;
1824         const struct wmfw_region *region;
1825         const struct wm_adsp_region *mem;
1826         const char *region_name;
1827         char *file, *text = NULL;
1828         struct wm_adsp_buf *buf;
1829         unsigned int reg;
1830         int regions = 0;
1831         int ret, offset, type;
1832
1833         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1834         if (file == NULL)
1835                 return -ENOMEM;
1836
1837         snprintf(file, PAGE_SIZE, "%s-%s-%s.wmfw", dsp->part, dsp->fwf_name,
1838                  wm_adsp_fw[dsp->fw].file);
1839         file[PAGE_SIZE - 1] = '\0';
1840
1841         ret = request_firmware(&firmware, file, dsp->dev);
1842         if (ret != 0) {
1843                 adsp_err(dsp, "Failed to request '%s'\n", file);
1844                 goto out;
1845         }
1846         ret = -EINVAL;
1847
1848         pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1849         if (pos >= firmware->size) {
1850                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
1851                          file, firmware->size);
1852                 goto out_fw;
1853         }
1854
1855         header = (void *)&firmware->data[0];
1856
1857         if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
1858                 adsp_err(dsp, "%s: invalid magic\n", file);
1859                 goto out_fw;
1860         }
1861
1862         if (!dsp->ops->validate_version(dsp, header->ver)) {
1863                 adsp_err(dsp, "%s: unknown file format %d\n",
1864                          file, header->ver);
1865                 goto out_fw;
1866         }
1867
1868         adsp_info(dsp, "Firmware version: %d\n", header->ver);
1869         dsp->fw_ver = header->ver;
1870
1871         if (header->core != dsp->type) {
1872                 adsp_err(dsp, "%s: invalid core %d != %d\n",
1873                          file, header->core, dsp->type);
1874                 goto out_fw;
1875         }
1876
1877         pos = sizeof(*header);
1878         pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
1879
1880         footer = (void *)&firmware->data[pos];
1881         pos += sizeof(*footer);
1882
1883         if (le32_to_cpu(header->len) != pos) {
1884                 adsp_err(dsp, "%s: unexpected header length %d\n",
1885                          file, le32_to_cpu(header->len));
1886                 goto out_fw;
1887         }
1888
1889         adsp_dbg(dsp, "%s: timestamp %llu\n", file,
1890                  le64_to_cpu(footer->timestamp));
1891
1892         while (pos < firmware->size &&
1893                sizeof(*region) < firmware->size - pos) {
1894                 region = (void *)&(firmware->data[pos]);
1895                 region_name = "Unknown";
1896                 reg = 0;
1897                 text = NULL;
1898                 offset = le32_to_cpu(region->offset) & 0xffffff;
1899                 type = be32_to_cpu(region->type) & 0xff;
1900
1901                 switch (type) {
1902                 case WMFW_NAME_TEXT:
1903                         region_name = "Firmware name";
1904                         text = kzalloc(le32_to_cpu(region->len) + 1,
1905                                        GFP_KERNEL);
1906                         break;
1907                 case WMFW_ALGORITHM_DATA:
1908                         region_name = "Algorithm";
1909                         ret = wm_adsp_parse_coeff(dsp, region);
1910                         if (ret != 0)
1911                                 goto out_fw;
1912                         break;
1913                 case WMFW_INFO_TEXT:
1914                         region_name = "Information";
1915                         text = kzalloc(le32_to_cpu(region->len) + 1,
1916                                        GFP_KERNEL);
1917                         break;
1918                 case WMFW_ABSOLUTE:
1919                         region_name = "Absolute";
1920                         reg = offset;
1921                         break;
1922                 case WMFW_ADSP1_PM:
1923                 case WMFW_ADSP1_DM:
1924                 case WMFW_ADSP2_XM:
1925                 case WMFW_ADSP2_YM:
1926                 case WMFW_ADSP1_ZM:
1927                 case WMFW_HALO_PM_PACKED:
1928                 case WMFW_HALO_XM_PACKED:
1929                 case WMFW_HALO_YM_PACKED:
1930                         mem = wm_adsp_find_region(dsp, type);
1931                         if (!mem) {
1932                                 adsp_err(dsp, "No region of type: %x\n", type);
1933                                 ret = -EINVAL;
1934                                 goto out_fw;
1935                         }
1936
1937                         region_name = wm_adsp_mem_region_name(type);
1938                         reg = dsp->ops->region_to_reg(mem, offset);
1939                         break;
1940                 default:
1941                         adsp_warn(dsp,
1942                                   "%s.%d: Unknown region type %x at %d(%x)\n",
1943                                   file, regions, type, pos, pos);
1944                         break;
1945                 }
1946
1947                 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
1948                          regions, le32_to_cpu(region->len), offset,
1949                          region_name);
1950
1951                 if (le32_to_cpu(region->len) >
1952                     firmware->size - pos - sizeof(*region)) {
1953                         adsp_err(dsp,
1954                                  "%s.%d: %s region len %d bytes exceeds file length %zu\n",
1955                                  file, regions, region_name,
1956                                  le32_to_cpu(region->len), firmware->size);
1957                         ret = -EINVAL;
1958                         goto out_fw;
1959                 }
1960
1961                 if (text) {
1962                         memcpy(text, region->data, le32_to_cpu(region->len));
1963                         adsp_info(dsp, "%s: %s\n", file, text);
1964                         kfree(text);
1965                         text = NULL;
1966                 }
1967
1968                 if (reg) {
1969                         buf = wm_adsp_buf_alloc(region->data,
1970                                                 le32_to_cpu(region->len),
1971                                                 &buf_list);
1972                         if (!buf) {
1973                                 adsp_err(dsp, "Out of memory\n");
1974                                 ret = -ENOMEM;
1975                                 goto out_fw;
1976                         }
1977
1978                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
1979                                                      le32_to_cpu(region->len));
1980                         if (ret != 0) {
1981                                 adsp_err(dsp,
1982                                         "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
1983                                         file, regions,
1984                                         le32_to_cpu(region->len), offset,
1985                                         region_name, ret);
1986                                 goto out_fw;
1987                         }
1988                 }
1989
1990                 pos += le32_to_cpu(region->len) + sizeof(*region);
1991                 regions++;
1992         }
1993
1994         ret = regmap_async_complete(regmap);
1995         if (ret != 0) {
1996                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
1997                 goto out_fw;
1998         }
1999
2000         if (pos > firmware->size)
2001                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2002                           file, regions, pos - firmware->size);
2003
2004         wm_adsp_debugfs_save_wmfwname(dsp, file);
2005
2006 out_fw:
2007         regmap_async_complete(regmap);
2008         wm_adsp_buf_free(&buf_list);
2009         release_firmware(firmware);
2010         kfree(text);
2011 out:
2012         kfree(file);
2013
2014         return ret;
2015 }
2016
2017 /*
2018  * Find wm_coeff_ctl with input name as its subname
2019  * If not found, return NULL
2020  */
2021 static struct wm_coeff_ctl *wm_adsp_get_ctl(struct wm_adsp *dsp,
2022                                              const char *name, int type,
2023                                              unsigned int alg)
2024 {
2025         struct wm_coeff_ctl *pos, *rslt = NULL;
2026         const char *fw_txt = wm_adsp_fw_text[dsp->fw];
2027
2028         list_for_each_entry(pos, &dsp->ctl_list, list) {
2029                 if (!pos->subname)
2030                         continue;
2031                 if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
2032                     strncmp(pos->fw_name, fw_txt,
2033                             SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == 0 &&
2034                                 pos->alg_region.alg == alg &&
2035                                 pos->alg_region.type == type) {
2036                         rslt = pos;
2037                         break;
2038                 }
2039         }
2040
2041         return rslt;
2042 }
2043
2044 int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
2045                       unsigned int alg, void *buf, size_t len)
2046 {
2047         struct wm_coeff_ctl *ctl;
2048         struct snd_kcontrol *kcontrol;
2049         char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2050         int ret;
2051
2052         ctl = wm_adsp_get_ctl(dsp, name, type, alg);
2053         if (!ctl)
2054                 return -EINVAL;
2055
2056         if (len > ctl->len)
2057                 return -EINVAL;
2058
2059         ret = wm_coeff_write_ctrl(ctl, buf, len);
2060         if (ret)
2061                 return ret;
2062
2063         if (ctl->flags & WMFW_CTL_FLAG_SYS)
2064                 return 0;
2065
2066         if (dsp->component->name_prefix)
2067                 snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s",
2068                          dsp->component->name_prefix, ctl->name);
2069         else
2070                 snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s",
2071                          ctl->name);
2072
2073         kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl_name);
2074         if (!kcontrol) {
2075                 adsp_err(dsp, "Can't find kcontrol %s\n", ctl_name);
2076                 return -EINVAL;
2077         }
2078
2079         snd_ctl_notify(dsp->component->card->snd_card,
2080                        SNDRV_CTL_EVENT_MASK_VALUE, &kcontrol->id);
2081
2082         return 0;
2083 }
2084 EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
2085
2086 int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
2087                      unsigned int alg, void *buf, size_t len)
2088 {
2089         struct wm_coeff_ctl *ctl;
2090
2091         ctl = wm_adsp_get_ctl(dsp, name, type, alg);
2092         if (!ctl)
2093                 return -EINVAL;
2094
2095         if (len > ctl->len)
2096                 return -EINVAL;
2097
2098         return wm_coeff_read_ctrl(ctl, buf, len);
2099 }
2100 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
2101
2102 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp,
2103                                   const struct wm_adsp_alg_region *alg_region)
2104 {
2105         struct wm_coeff_ctl *ctl;
2106
2107         list_for_each_entry(ctl, &dsp->ctl_list, list) {
2108                 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] &&
2109                     alg_region->alg == ctl->alg_region.alg &&
2110                     alg_region->type == ctl->alg_region.type) {
2111                         ctl->alg_region.base = alg_region->base;
2112                 }
2113         }
2114 }
2115
2116 static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
2117                                const struct wm_adsp_region *mem,
2118                                unsigned int pos, unsigned int len)
2119 {
2120         void *alg;
2121         unsigned int reg;
2122         int ret;
2123         __be32 val;
2124
2125         if (n_algs == 0) {
2126                 adsp_err(dsp, "No algorithms\n");
2127                 return ERR_PTR(-EINVAL);
2128         }
2129
2130         if (n_algs > 1024) {
2131                 adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs);
2132                 return ERR_PTR(-EINVAL);
2133         }
2134
2135         /* Read the terminator first to validate the length */
2136         reg = dsp->ops->region_to_reg(mem, pos + len);
2137
2138         ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
2139         if (ret != 0) {
2140                 adsp_err(dsp, "Failed to read algorithm list end: %d\n",
2141                         ret);
2142                 return ERR_PTR(ret);
2143         }
2144
2145         if (be32_to_cpu(val) != 0xbedead)
2146                 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n",
2147                           reg, be32_to_cpu(val));
2148
2149         /* Convert length from DSP words to bytes */
2150         len *= sizeof(u32);
2151
2152         alg = kzalloc(len, GFP_KERNEL | GFP_DMA);
2153         if (!alg)
2154                 return ERR_PTR(-ENOMEM);
2155
2156         reg = dsp->ops->region_to_reg(mem, pos);
2157
2158         ret = regmap_raw_read(dsp->regmap, reg, alg, len);
2159         if (ret != 0) {
2160                 adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
2161                 kfree(alg);
2162                 return ERR_PTR(ret);
2163         }
2164
2165         return alg;
2166 }
2167
2168 static struct wm_adsp_alg_region *
2169         wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id)
2170 {
2171         struct wm_adsp_alg_region *alg_region;
2172
2173         list_for_each_entry(alg_region, &dsp->alg_regions, list) {
2174                 if (id == alg_region->alg && type == alg_region->type)
2175                         return alg_region;
2176         }
2177
2178         return NULL;
2179 }
2180
2181 static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp,
2182                                                         int type, __be32 id,
2183                                                         __be32 base)
2184 {
2185         struct wm_adsp_alg_region *alg_region;
2186
2187         alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL);
2188         if (!alg_region)
2189                 return ERR_PTR(-ENOMEM);
2190
2191         alg_region->type = type;
2192         alg_region->alg = be32_to_cpu(id);
2193         alg_region->base = be32_to_cpu(base);
2194
2195         list_add_tail(&alg_region->list, &dsp->alg_regions);
2196
2197         if (dsp->fw_ver > 0)
2198                 wm_adsp_ctl_fixup_base(dsp, alg_region);
2199
2200         return alg_region;
2201 }
2202
2203 static void wm_adsp_free_alg_regions(struct wm_adsp *dsp)
2204 {
2205         struct wm_adsp_alg_region *alg_region;
2206
2207         while (!list_empty(&dsp->alg_regions)) {
2208                 alg_region = list_first_entry(&dsp->alg_regions,
2209                                               struct wm_adsp_alg_region,
2210                                               list);
2211                 list_del(&alg_region->list);
2212                 kfree(alg_region);
2213         }
2214 }
2215
2216 static void wmfw_parse_id_header(struct wm_adsp *dsp,
2217                                  struct wmfw_id_hdr *fw, int nalgs)
2218 {
2219         dsp->fw_id = be32_to_cpu(fw->id);
2220         dsp->fw_id_version = be32_to_cpu(fw->ver);
2221
2222         adsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n",
2223                   dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16,
2224                   (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
2225                   nalgs);
2226 }
2227
2228 static void wmfw_v3_parse_id_header(struct wm_adsp *dsp,
2229                                     struct wmfw_v3_id_hdr *fw, int nalgs)
2230 {
2231         dsp->fw_id = be32_to_cpu(fw->id);
2232         dsp->fw_id_version = be32_to_cpu(fw->ver);
2233         dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id);
2234
2235         adsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n",
2236                   dsp->fw_id, dsp->fw_vendor_id,
2237                   (dsp->fw_id_version & 0xff0000) >> 16,
2238                   (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
2239                   nalgs);
2240 }
2241
2242 static int wm_adsp_create_regions(struct wm_adsp *dsp, __be32 id, int nregions,
2243                                 const int *type, __be32 *base)
2244 {
2245         struct wm_adsp_alg_region *alg_region;
2246         int i;
2247
2248         for (i = 0; i < nregions; i++) {
2249                 alg_region = wm_adsp_create_region(dsp, type[i], id, base[i]);
2250                 if (IS_ERR(alg_region))
2251                         return PTR_ERR(alg_region);
2252         }
2253
2254         return 0;
2255 }
2256
2257 static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
2258 {
2259         struct wmfw_adsp1_id_hdr adsp1_id;
2260         struct wmfw_adsp1_alg_hdr *adsp1_alg;
2261         struct wm_adsp_alg_region *alg_region;
2262         const struct wm_adsp_region *mem;
2263         unsigned int pos, len;
2264         size_t n_algs;
2265         int i, ret;
2266
2267         mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
2268         if (WARN_ON(!mem))
2269                 return -EINVAL;
2270
2271         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id,
2272                               sizeof(adsp1_id));
2273         if (ret != 0) {
2274                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
2275                          ret);
2276                 return ret;
2277         }
2278
2279         n_algs = be32_to_cpu(adsp1_id.n_algs);
2280
2281         wmfw_parse_id_header(dsp, &adsp1_id.fw, n_algs);
2282
2283         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
2284                                            adsp1_id.fw.id, adsp1_id.zm);
2285         if (IS_ERR(alg_region))
2286                 return PTR_ERR(alg_region);
2287
2288         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
2289                                            adsp1_id.fw.id, adsp1_id.dm);
2290         if (IS_ERR(alg_region))
2291                 return PTR_ERR(alg_region);
2292
2293         /* Calculate offset and length in DSP words */
2294         pos = sizeof(adsp1_id) / sizeof(u32);
2295         len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32);
2296
2297         adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2298         if (IS_ERR(adsp1_alg))
2299                 return PTR_ERR(adsp1_alg);
2300
2301         for (i = 0; i < n_algs; i++) {
2302                 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
2303                           i, be32_to_cpu(adsp1_alg[i].alg.id),
2304                           (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
2305                           (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
2306                           be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
2307                           be32_to_cpu(adsp1_alg[i].dm),
2308                           be32_to_cpu(adsp1_alg[i].zm));
2309
2310                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
2311                                                    adsp1_alg[i].alg.id,
2312                                                    adsp1_alg[i].dm);
2313                 if (IS_ERR(alg_region)) {
2314                         ret = PTR_ERR(alg_region);
2315                         goto out;
2316                 }
2317                 if (dsp->fw_ver == 0) {
2318                         if (i + 1 < n_algs) {
2319                                 len = be32_to_cpu(adsp1_alg[i + 1].dm);
2320                                 len -= be32_to_cpu(adsp1_alg[i].dm);
2321                                 len *= 4;
2322                                 wm_adsp_create_control(dsp, alg_region, 0,
2323                                                      len, NULL, 0, 0,
2324                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2325                         } else {
2326                                 adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
2327                                           be32_to_cpu(adsp1_alg[i].alg.id));
2328                         }
2329                 }
2330
2331                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
2332                                                    adsp1_alg[i].alg.id,
2333                                                    adsp1_alg[i].zm);
2334                 if (IS_ERR(alg_region)) {
2335                         ret = PTR_ERR(alg_region);
2336                         goto out;
2337                 }
2338                 if (dsp->fw_ver == 0) {
2339                         if (i + 1 < n_algs) {
2340                                 len = be32_to_cpu(adsp1_alg[i + 1].zm);
2341                                 len -= be32_to_cpu(adsp1_alg[i].zm);
2342                                 len *= 4;
2343                                 wm_adsp_create_control(dsp, alg_region, 0,
2344                                                      len, NULL, 0, 0,
2345                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2346                         } else {
2347                                 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
2348                                           be32_to_cpu(adsp1_alg[i].alg.id));
2349                         }
2350                 }
2351         }
2352
2353 out:
2354         kfree(adsp1_alg);
2355         return ret;
2356 }
2357
2358 static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
2359 {
2360         struct wmfw_adsp2_id_hdr adsp2_id;
2361         struct wmfw_adsp2_alg_hdr *adsp2_alg;
2362         struct wm_adsp_alg_region *alg_region;
2363         const struct wm_adsp_region *mem;
2364         unsigned int pos, len;
2365         size_t n_algs;
2366         int i, ret;
2367
2368         mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
2369         if (WARN_ON(!mem))
2370                 return -EINVAL;
2371
2372         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id,
2373                               sizeof(adsp2_id));
2374         if (ret != 0) {
2375                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
2376                          ret);
2377                 return ret;
2378         }
2379
2380         n_algs = be32_to_cpu(adsp2_id.n_algs);
2381
2382         wmfw_parse_id_header(dsp, &adsp2_id.fw, n_algs);
2383
2384         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
2385                                            adsp2_id.fw.id, adsp2_id.xm);
2386         if (IS_ERR(alg_region))
2387                 return PTR_ERR(alg_region);
2388
2389         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
2390                                            adsp2_id.fw.id, adsp2_id.ym);
2391         if (IS_ERR(alg_region))
2392                 return PTR_ERR(alg_region);
2393
2394         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
2395                                            adsp2_id.fw.id, adsp2_id.zm);
2396         if (IS_ERR(alg_region))
2397                 return PTR_ERR(alg_region);
2398
2399         /* Calculate offset and length in DSP words */
2400         pos = sizeof(adsp2_id) / sizeof(u32);
2401         len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32);
2402
2403         adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2404         if (IS_ERR(adsp2_alg))
2405                 return PTR_ERR(adsp2_alg);
2406
2407         for (i = 0; i < n_algs; i++) {
2408                 adsp_info(dsp,
2409                           "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
2410                           i, be32_to_cpu(adsp2_alg[i].alg.id),
2411                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
2412                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
2413                           be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
2414                           be32_to_cpu(adsp2_alg[i].xm),
2415                           be32_to_cpu(adsp2_alg[i].ym),
2416                           be32_to_cpu(adsp2_alg[i].zm));
2417
2418                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
2419                                                    adsp2_alg[i].alg.id,
2420                                                    adsp2_alg[i].xm);
2421                 if (IS_ERR(alg_region)) {
2422                         ret = PTR_ERR(alg_region);
2423                         goto out;
2424                 }
2425                 if (dsp->fw_ver == 0) {
2426                         if (i + 1 < n_algs) {
2427                                 len = be32_to_cpu(adsp2_alg[i + 1].xm);
2428                                 len -= be32_to_cpu(adsp2_alg[i].xm);
2429                                 len *= 4;
2430                                 wm_adsp_create_control(dsp, alg_region, 0,
2431                                                      len, NULL, 0, 0,
2432                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2433                         } else {
2434                                 adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
2435                                           be32_to_cpu(adsp2_alg[i].alg.id));
2436                         }
2437                 }
2438
2439                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
2440                                                    adsp2_alg[i].alg.id,
2441                                                    adsp2_alg[i].ym);
2442                 if (IS_ERR(alg_region)) {
2443                         ret = PTR_ERR(alg_region);
2444                         goto out;
2445                 }
2446                 if (dsp->fw_ver == 0) {
2447                         if (i + 1 < n_algs) {
2448                                 len = be32_to_cpu(adsp2_alg[i + 1].ym);
2449                                 len -= be32_to_cpu(adsp2_alg[i].ym);
2450                                 len *= 4;
2451                                 wm_adsp_create_control(dsp, alg_region, 0,
2452                                                      len, NULL, 0, 0,
2453                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2454                         } else {
2455                                 adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
2456                                           be32_to_cpu(adsp2_alg[i].alg.id));
2457                         }
2458                 }
2459
2460                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
2461                                                    adsp2_alg[i].alg.id,
2462                                                    adsp2_alg[i].zm);
2463                 if (IS_ERR(alg_region)) {
2464                         ret = PTR_ERR(alg_region);
2465                         goto out;
2466                 }
2467                 if (dsp->fw_ver == 0) {
2468                         if (i + 1 < n_algs) {
2469                                 len = be32_to_cpu(adsp2_alg[i + 1].zm);
2470                                 len -= be32_to_cpu(adsp2_alg[i].zm);
2471                                 len *= 4;
2472                                 wm_adsp_create_control(dsp, alg_region, 0,
2473                                                      len, NULL, 0, 0,
2474                                                      SNDRV_CTL_ELEM_TYPE_BYTES);
2475                         } else {
2476                                 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
2477                                           be32_to_cpu(adsp2_alg[i].alg.id));
2478                         }
2479                 }
2480         }
2481
2482 out:
2483         kfree(adsp2_alg);
2484         return ret;
2485 }
2486
2487 static int wm_halo_create_regions(struct wm_adsp *dsp, __be32 id,
2488                                   __be32 xm_base, __be32 ym_base)
2489 {
2490         static const int types[] = {
2491                 WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED,
2492                 WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED
2493         };
2494         __be32 bases[] = { xm_base, xm_base, ym_base, ym_base };
2495
2496         return wm_adsp_create_regions(dsp, id, ARRAY_SIZE(types), types, bases);
2497 }
2498
2499 static int wm_halo_setup_algs(struct wm_adsp *dsp)
2500 {
2501         struct wmfw_halo_id_hdr halo_id;
2502         struct wmfw_halo_alg_hdr *halo_alg;
2503         const struct wm_adsp_region *mem;
2504         unsigned int pos, len;
2505         size_t n_algs;
2506         int i, ret;
2507
2508         mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
2509         if (WARN_ON(!mem))
2510                 return -EINVAL;
2511
2512         ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id,
2513                               sizeof(halo_id));
2514         if (ret != 0) {
2515                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
2516                          ret);
2517                 return ret;
2518         }
2519
2520         n_algs = be32_to_cpu(halo_id.n_algs);
2521
2522         wmfw_v3_parse_id_header(dsp, &halo_id.fw, n_algs);
2523
2524         ret = wm_halo_create_regions(dsp, halo_id.fw.id,
2525                                      halo_id.xm_base, halo_id.ym_base);
2526         if (ret)
2527                 return ret;
2528
2529         /* Calculate offset and length in DSP words */
2530         pos = sizeof(halo_id) / sizeof(u32);
2531         len = (sizeof(*halo_alg) * n_algs) / sizeof(u32);
2532
2533         halo_alg = wm_adsp_read_algs(dsp, n_algs, mem, pos, len);
2534         if (IS_ERR(halo_alg))
2535                 return PTR_ERR(halo_alg);
2536
2537         for (i = 0; i < n_algs; i++) {
2538                 adsp_info(dsp,
2539                           "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
2540                           i, be32_to_cpu(halo_alg[i].alg.id),
2541                           (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
2542                           (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
2543                           be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
2544                           be32_to_cpu(halo_alg[i].xm_base),
2545                           be32_to_cpu(halo_alg[i].ym_base));
2546
2547                 ret = wm_halo_create_regions(dsp, halo_alg[i].alg.id,
2548                                              halo_alg[i].xm_base,
2549                                              halo_alg[i].ym_base);
2550                 if (ret)
2551                         goto out;
2552         }
2553
2554 out:
2555         kfree(halo_alg);
2556         return ret;
2557 }
2558
2559 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
2560 {
2561         LIST_HEAD(buf_list);
2562         struct regmap *regmap = dsp->regmap;
2563         struct wmfw_coeff_hdr *hdr;
2564         struct wmfw_coeff_item *blk;
2565         const struct firmware *firmware;
2566         const struct wm_adsp_region *mem;
2567         struct wm_adsp_alg_region *alg_region;
2568         const char *region_name;
2569         int ret, pos, blocks, type, offset, reg;
2570         char *file;
2571         struct wm_adsp_buf *buf;
2572
2573         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
2574         if (file == NULL)
2575                 return -ENOMEM;
2576
2577         snprintf(file, PAGE_SIZE, "%s-%s-%s.bin", dsp->part, dsp->fwf_name,
2578                  wm_adsp_fw[dsp->fw].file);
2579         file[PAGE_SIZE - 1] = '\0';
2580
2581         ret = request_firmware(&firmware, file, dsp->dev);
2582         if (ret != 0) {
2583                 adsp_warn(dsp, "Failed to request '%s'\n", file);
2584                 ret = 0;
2585                 goto out;
2586         }
2587         ret = -EINVAL;
2588
2589         if (sizeof(*hdr) >= firmware->size) {
2590                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
2591                         file, firmware->size);
2592                 goto out_fw;
2593         }
2594
2595         hdr = (void *)&firmware->data[0];
2596         if (memcmp(hdr->magic, "WMDR", 4) != 0) {
2597                 adsp_err(dsp, "%s: invalid magic\n", file);
2598                 goto out_fw;
2599         }
2600
2601         switch (be32_to_cpu(hdr->rev) & 0xff) {
2602         case 1:
2603                 break;
2604         default:
2605                 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
2606                          file, be32_to_cpu(hdr->rev) & 0xff);
2607                 ret = -EINVAL;
2608                 goto out_fw;
2609         }
2610
2611         adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
2612                 (le32_to_cpu(hdr->ver) >> 16) & 0xff,
2613                 (le32_to_cpu(hdr->ver) >>  8) & 0xff,
2614                 le32_to_cpu(hdr->ver) & 0xff);
2615
2616         pos = le32_to_cpu(hdr->len);
2617
2618         blocks = 0;
2619         while (pos < firmware->size &&
2620                sizeof(*blk) < firmware->size - pos) {
2621                 blk = (void *)(&firmware->data[pos]);
2622
2623                 type = le16_to_cpu(blk->type);
2624                 offset = le16_to_cpu(blk->offset);
2625
2626                 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
2627                          file, blocks, le32_to_cpu(blk->id),
2628                          (le32_to_cpu(blk->ver) >> 16) & 0xff,
2629                          (le32_to_cpu(blk->ver) >>  8) & 0xff,
2630                          le32_to_cpu(blk->ver) & 0xff);
2631                 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
2632                          file, blocks, le32_to_cpu(blk->len), offset, type);
2633
2634                 reg = 0;
2635                 region_name = "Unknown";
2636                 switch (type) {
2637                 case (WMFW_NAME_TEXT << 8):
2638                 case (WMFW_INFO_TEXT << 8):
2639                 case (WMFW_METADATA << 8):
2640                         break;
2641                 case (WMFW_ABSOLUTE << 8):
2642                         /*
2643                          * Old files may use this for global
2644                          * coefficients.
2645                          */
2646                         if (le32_to_cpu(blk->id) == dsp->fw_id &&
2647                             offset == 0) {
2648                                 region_name = "global coefficients";
2649                                 mem = wm_adsp_find_region(dsp, type);
2650                                 if (!mem) {
2651                                         adsp_err(dsp, "No ZM\n");
2652                                         break;
2653                                 }
2654                                 reg = dsp->ops->region_to_reg(mem, 0);
2655
2656                         } else {
2657                                 region_name = "register";
2658                                 reg = offset;
2659                         }
2660                         break;
2661
2662                 case WMFW_ADSP1_DM:
2663                 case WMFW_ADSP1_ZM:
2664                 case WMFW_ADSP2_XM:
2665                 case WMFW_ADSP2_YM:
2666                 case WMFW_HALO_XM_PACKED:
2667                 case WMFW_HALO_YM_PACKED:
2668                 case WMFW_HALO_PM_PACKED:
2669                         adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
2670                                  file, blocks, le32_to_cpu(blk->len),
2671                                  type, le32_to_cpu(blk->id));
2672
2673                         mem = wm_adsp_find_region(dsp, type);
2674                         if (!mem) {
2675                                 adsp_err(dsp, "No base for region %x\n", type);
2676                                 break;
2677                         }
2678
2679                         alg_region = wm_adsp_find_alg_region(dsp, type,
2680                                                 le32_to_cpu(blk->id));
2681                         if (alg_region) {
2682                                 reg = alg_region->base;
2683                                 reg = dsp->ops->region_to_reg(mem, reg);
2684                                 reg += offset;
2685                         } else {
2686                                 adsp_err(dsp, "No %x for algorithm %x\n",
2687                                          type, le32_to_cpu(blk->id));
2688                         }
2689                         break;
2690
2691                 default:
2692                         adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
2693                                  file, blocks, type, pos);
2694                         break;
2695                 }
2696
2697                 if (reg) {
2698                         if (le32_to_cpu(blk->len) >
2699                             firmware->size - pos - sizeof(*blk)) {
2700                                 adsp_err(dsp,
2701                                          "%s.%d: %s region len %d bytes exceeds file length %zu\n",
2702                                          file, blocks, region_name,
2703                                          le32_to_cpu(blk->len),
2704                                          firmware->size);
2705                                 ret = -EINVAL;
2706                                 goto out_fw;
2707                         }
2708
2709                         buf = wm_adsp_buf_alloc(blk->data,
2710                                                 le32_to_cpu(blk->len),
2711                                                 &buf_list);
2712                         if (!buf) {
2713                                 adsp_err(dsp, "Out of memory\n");
2714                                 ret = -ENOMEM;
2715                                 goto out_fw;
2716                         }
2717
2718                         adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
2719                                  file, blocks, le32_to_cpu(blk->len),
2720                                  reg);
2721                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
2722                                                      le32_to_cpu(blk->len));
2723                         if (ret != 0) {
2724                                 adsp_err(dsp,
2725                                         "%s.%d: Failed to write to %x in %s: %d\n",
2726                                         file, blocks, reg, region_name, ret);
2727                         }
2728                 }
2729
2730                 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
2731                 blocks++;
2732         }
2733
2734         ret = regmap_async_complete(regmap);
2735         if (ret != 0)
2736                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
2737
2738         if (pos > firmware->size)
2739                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2740                           file, blocks, pos - firmware->size);
2741
2742         wm_adsp_debugfs_save_binname(dsp, file);
2743
2744 out_fw:
2745         regmap_async_complete(regmap);
2746         release_firmware(firmware);
2747         wm_adsp_buf_free(&buf_list);
2748 out:
2749         kfree(file);
2750         return ret;
2751 }
2752
2753 static int wm_adsp_create_name(struct wm_adsp *dsp)
2754 {
2755         char *p;
2756
2757         if (!dsp->name) {
2758                 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d",
2759                                            dsp->num);
2760                 if (!dsp->name)
2761                         return -ENOMEM;
2762         }
2763
2764         if (!dsp->fwf_name) {
2765                 p = devm_kstrdup(dsp->dev, dsp->name, GFP_KERNEL);
2766                 if (!p)
2767                         return -ENOMEM;
2768
2769                 dsp->fwf_name = p;
2770                 for (; *p != 0; ++p)
2771                         *p = tolower(*p);
2772         }
2773
2774         return 0;
2775 }
2776
2777 static int wm_adsp_common_init(struct wm_adsp *dsp)
2778 {
2779         int ret;
2780
2781         ret = wm_adsp_create_name(dsp);
2782         if (ret)
2783                 return ret;
2784
2785         INIT_LIST_HEAD(&dsp->alg_regions);
2786         INIT_LIST_HEAD(&dsp->ctl_list);
2787         INIT_LIST_HEAD(&dsp->compr_list);
2788         INIT_LIST_HEAD(&dsp->buffer_list);
2789
2790         mutex_init(&dsp->pwr_lock);
2791
2792         return 0;
2793 }
2794
2795 int wm_adsp1_init(struct wm_adsp *dsp)
2796 {
2797         dsp->ops = &wm_adsp1_ops;
2798
2799         return wm_adsp_common_init(dsp);
2800 }
2801 EXPORT_SYMBOL_GPL(wm_adsp1_init);
2802
2803 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
2804                    struct snd_kcontrol *kcontrol,
2805                    int event)
2806 {
2807         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
2808         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
2809         struct wm_adsp *dsp = &dsps[w->shift];
2810         struct wm_coeff_ctl *ctl;
2811         int ret;
2812         unsigned int val;
2813
2814         dsp->component = component;
2815
2816         mutex_lock(&dsp->pwr_lock);
2817
2818         switch (event) {
2819         case SND_SOC_DAPM_POST_PMU:
2820                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2821                                    ADSP1_SYS_ENA, ADSP1_SYS_ENA);
2822
2823                 /*
2824                  * For simplicity set the DSP clock rate to be the
2825                  * SYSCLK rate rather than making it configurable.
2826                  */
2827                 if (dsp->sysclk_reg) {
2828                         ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
2829                         if (ret != 0) {
2830                                 adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
2831                                 ret);
2832                                 goto err_mutex;
2833                         }
2834
2835                         val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
2836
2837                         ret = regmap_update_bits(dsp->regmap,
2838                                                  dsp->base + ADSP1_CONTROL_31,
2839                                                  ADSP1_CLK_SEL_MASK, val);
2840                         if (ret != 0) {
2841                                 adsp_err(dsp, "Failed to set clock rate: %d\n",
2842                                          ret);
2843                                 goto err_mutex;
2844                         }
2845                 }
2846
2847                 ret = wm_adsp_load(dsp);
2848                 if (ret != 0)
2849                         goto err_ena;
2850
2851                 ret = wm_adsp1_setup_algs(dsp);
2852                 if (ret != 0)
2853                         goto err_ena;
2854
2855                 ret = wm_adsp_load_coeff(dsp);
2856                 if (ret != 0)
2857                         goto err_ena;
2858
2859                 /* Initialize caches for enabled and unset controls */
2860                 ret = wm_coeff_init_control_caches(dsp);
2861                 if (ret != 0)
2862                         goto err_ena;
2863
2864                 /* Sync set controls */
2865                 ret = wm_coeff_sync_controls(dsp);
2866                 if (ret != 0)
2867                         goto err_ena;
2868
2869                 dsp->booted = true;
2870
2871                 /* Start the core running */
2872                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2873                                    ADSP1_CORE_ENA | ADSP1_START,
2874                                    ADSP1_CORE_ENA | ADSP1_START);
2875
2876                 dsp->running = true;
2877                 break;
2878
2879         case SND_SOC_DAPM_PRE_PMD:
2880                 dsp->running = false;
2881                 dsp->booted = false;
2882
2883                 /* Halt the core */
2884                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2885                                    ADSP1_CORE_ENA | ADSP1_START, 0);
2886
2887                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
2888                                    ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
2889
2890                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2891                                    ADSP1_SYS_ENA, 0);
2892
2893                 list_for_each_entry(ctl, &dsp->ctl_list, list)
2894                         ctl->enabled = 0;
2895
2896
2897                 wm_adsp_free_alg_regions(dsp);
2898                 break;
2899
2900         default:
2901                 break;
2902         }
2903
2904         mutex_unlock(&dsp->pwr_lock);
2905
2906         return 0;
2907
2908 err_ena:
2909         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2910                            ADSP1_SYS_ENA, 0);
2911 err_mutex:
2912         mutex_unlock(&dsp->pwr_lock);
2913
2914         return ret;
2915 }
2916 EXPORT_SYMBOL_GPL(wm_adsp1_event);
2917
2918 static int wm_adsp2v2_enable_core(struct wm_adsp *dsp)
2919 {
2920         unsigned int val;
2921         int ret, count;
2922
2923         /* Wait for the RAM to start, should be near instantaneous */
2924         for (count = 0; count < 10; ++count) {
2925                 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
2926                 if (ret != 0)
2927                         return ret;
2928
2929                 if (val & ADSP2_RAM_RDY)
2930                         break;
2931
2932                 usleep_range(250, 500);
2933         }
2934
2935         if (!(val & ADSP2_RAM_RDY)) {
2936                 adsp_err(dsp, "Failed to start DSP RAM\n");
2937                 return -EBUSY;
2938         }
2939
2940         adsp_dbg(dsp, "RAM ready after %d polls\n", count);
2941
2942         return 0;
2943 }
2944
2945 static int wm_adsp2_enable_core(struct wm_adsp *dsp)
2946 {
2947         int ret;
2948
2949         ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2950                                        ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2951         if (ret != 0)
2952                 return ret;
2953
2954         return wm_adsp2v2_enable_core(dsp);
2955 }
2956
2957 static int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions)
2958 {
2959         struct regmap *regmap = dsp->regmap;
2960         unsigned int code0, code1, lock_reg;
2961
2962         if (!(lock_regions & WM_ADSP2_REGION_ALL))
2963                 return 0;
2964
2965         lock_regions &= WM_ADSP2_REGION_ALL;
2966         lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0;
2967
2968         while (lock_regions) {
2969                 code0 = code1 = 0;
2970                 if (lock_regions & BIT(0)) {
2971                         code0 = ADSP2_LOCK_CODE_0;
2972                         code1 = ADSP2_LOCK_CODE_1;
2973                 }
2974                 if (lock_regions & BIT(1)) {
2975                         code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT;
2976                         code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT;
2977                 }
2978                 regmap_write(regmap, lock_reg, code0);
2979                 regmap_write(regmap, lock_reg, code1);
2980                 lock_regions >>= 2;
2981                 lock_reg += 2;
2982         }
2983
2984         return 0;
2985 }
2986
2987 static int wm_adsp2_enable_memory(struct wm_adsp *dsp)
2988 {
2989         return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2990                                   ADSP2_MEM_ENA, ADSP2_MEM_ENA);
2991 }
2992
2993 static void wm_adsp2_disable_memory(struct wm_adsp *dsp)
2994 {
2995         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2996                            ADSP2_MEM_ENA, 0);
2997 }
2998
2999 static void wm_adsp2_disable_core(struct wm_adsp *dsp)
3000 {
3001         regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
3002         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
3003         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
3004
3005         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3006                            ADSP2_SYS_ENA, 0);
3007 }
3008
3009 static void wm_adsp2v2_disable_core(struct wm_adsp *dsp)
3010 {
3011         regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
3012         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
3013         regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
3014 }
3015
3016 static void wm_adsp_boot_work(struct work_struct *work)
3017 {
3018         struct wm_adsp *dsp = container_of(work,
3019                                            struct wm_adsp,
3020                                            boot_work);
3021         int ret;
3022
3023         mutex_lock(&dsp->pwr_lock);
3024
3025         if (dsp->ops->enable_memory) {
3026                 ret = dsp->ops->enable_memory(dsp);
3027                 if (ret != 0)
3028                         goto err_mutex;
3029         }
3030
3031         if (dsp->ops->enable_core) {
3032                 ret = dsp->ops->enable_core(dsp);
3033                 if (ret != 0)
3034                         goto err_mem;
3035         }
3036
3037         ret = wm_adsp_load(dsp);
3038         if (ret != 0)
3039                 goto err_ena;
3040
3041         ret = dsp->ops->setup_algs(dsp);
3042         if (ret != 0)
3043                 goto err_ena;
3044
3045         ret = wm_adsp_load_coeff(dsp);
3046         if (ret != 0)
3047                 goto err_ena;
3048
3049         /* Initialize caches for enabled and unset controls */
3050         ret = wm_coeff_init_control_caches(dsp);
3051         if (ret != 0)
3052                 goto err_ena;
3053
3054         if (dsp->ops->disable_core)
3055                 dsp->ops->disable_core(dsp);
3056
3057         dsp->booted = true;
3058
3059         mutex_unlock(&dsp->pwr_lock);
3060
3061         return;
3062
3063 err_ena:
3064         if (dsp->ops->disable_core)
3065                 dsp->ops->disable_core(dsp);
3066 err_mem:
3067         if (dsp->ops->disable_memory)
3068                 dsp->ops->disable_memory(dsp);
3069 err_mutex:
3070         mutex_unlock(&dsp->pwr_lock);
3071 }
3072
3073 static int wm_halo_configure_mpu(struct wm_adsp *dsp, unsigned int lock_regions)
3074 {
3075         struct reg_sequence config[] = {
3076                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0x5555 },
3077                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0xAAAA },
3078                 { dsp->base + HALO_MPU_XMEM_ACCESS_0,   0xFFFFFFFF },
3079                 { dsp->base + HALO_MPU_YMEM_ACCESS_0,   0xFFFFFFFF },
3080                 { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions },
3081                 { dsp->base + HALO_MPU_XREG_ACCESS_0,   lock_regions },
3082                 { dsp->base + HALO_MPU_YREG_ACCESS_0,   lock_regions },
3083                 { dsp->base + HALO_MPU_XMEM_ACCESS_1,   0xFFFFFFFF },
3084                 { dsp->base + HALO_MPU_YMEM_ACCESS_1,   0xFFFFFFFF },
3085                 { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions },
3086                 { dsp->base + HALO_MPU_XREG_ACCESS_1,   lock_regions },
3087                 { dsp->base + HALO_MPU_YREG_ACCESS_1,   lock_regions },
3088                 { dsp->base + HALO_MPU_XMEM_ACCESS_2,   0xFFFFFFFF },
3089                 { dsp->base + HALO_MPU_YMEM_ACCESS_2,   0xFFFFFFFF },
3090                 { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions },
3091                 { dsp->base + HALO_MPU_XREG_ACCESS_2,   lock_regions },
3092                 { dsp->base + HALO_MPU_YREG_ACCESS_2,   lock_regions },
3093                 { dsp->base + HALO_MPU_XMEM_ACCESS_3,   0xFFFFFFFF },
3094                 { dsp->base + HALO_MPU_YMEM_ACCESS_3,   0xFFFFFFFF },
3095                 { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions },
3096                 { dsp->base + HALO_MPU_XREG_ACCESS_3,   lock_regions },
3097                 { dsp->base + HALO_MPU_YREG_ACCESS_3,   lock_regions },
3098                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0 },
3099         };
3100
3101         return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config));
3102 }
3103
3104 int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq)
3105 {
3106         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3107         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3108         struct wm_adsp *dsp = &dsps[w->shift];
3109         int ret;
3110
3111         ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING,
3112                                  ADSP2_CLK_SEL_MASK,
3113                                  freq << ADSP2_CLK_SEL_SHIFT);
3114         if (ret)
3115                 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
3116
3117         return ret;
3118 }
3119 EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk);
3120
3121 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
3122                            struct snd_ctl_elem_value *ucontrol)
3123 {
3124         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3125         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3126         struct soc_mixer_control *mc =
3127                 (struct soc_mixer_control *)kcontrol->private_value;
3128         struct wm_adsp *dsp = &dsps[mc->shift - 1];
3129
3130         ucontrol->value.integer.value[0] = dsp->preloaded;
3131
3132         return 0;
3133 }
3134 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get);
3135
3136 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
3137                            struct snd_ctl_elem_value *ucontrol)
3138 {
3139         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
3140         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3141         struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
3142         struct soc_mixer_control *mc =
3143                 (struct soc_mixer_control *)kcontrol->private_value;
3144         struct wm_adsp *dsp = &dsps[mc->shift - 1];
3145         char preload[32];
3146
3147         snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name);
3148
3149         dsp->preloaded = ucontrol->value.integer.value[0];
3150
3151         if (ucontrol->value.integer.value[0])
3152                 snd_soc_component_force_enable_pin(component, preload);
3153         else
3154                 snd_soc_component_disable_pin(component, preload);
3155
3156         snd_soc_dapm_sync(dapm);
3157
3158         flush_work(&dsp->boot_work);
3159
3160         return 0;
3161 }
3162 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
3163
3164 static void wm_adsp_stop_watchdog(struct wm_adsp *dsp)
3165 {
3166         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG,
3167                            ADSP2_WDT_ENA_MASK, 0);
3168 }
3169
3170 static void wm_halo_stop_watchdog(struct wm_adsp *dsp)
3171 {
3172         regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL,
3173                            HALO_WDT_EN_MASK, 0);
3174 }
3175
3176 int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
3177                         struct snd_kcontrol *kcontrol, int event)
3178 {
3179         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3180         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3181         struct wm_adsp *dsp = &dsps[w->shift];
3182         struct wm_coeff_ctl *ctl;
3183
3184         switch (event) {
3185         case SND_SOC_DAPM_PRE_PMU:
3186                 queue_work(system_unbound_wq, &dsp->boot_work);
3187                 break;
3188         case SND_SOC_DAPM_PRE_PMD:
3189                 mutex_lock(&dsp->pwr_lock);
3190
3191                 wm_adsp_debugfs_clear(dsp);
3192
3193                 dsp->fw_id = 0;
3194                 dsp->fw_id_version = 0;
3195
3196                 dsp->booted = false;
3197
3198                 if (dsp->ops->disable_memory)
3199                         dsp->ops->disable_memory(dsp);
3200
3201                 list_for_each_entry(ctl, &dsp->ctl_list, list)
3202                         ctl->enabled = 0;
3203
3204                 wm_adsp_free_alg_regions(dsp);
3205
3206                 mutex_unlock(&dsp->pwr_lock);
3207
3208                 adsp_dbg(dsp, "Shutdown complete\n");
3209                 break;
3210         default:
3211                 break;
3212         }
3213
3214         return 0;
3215 }
3216 EXPORT_SYMBOL_GPL(wm_adsp_early_event);
3217
3218 static int wm_adsp2_start_core(struct wm_adsp *dsp)
3219 {
3220         return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3221                                  ADSP2_CORE_ENA | ADSP2_START,
3222                                  ADSP2_CORE_ENA | ADSP2_START);
3223 }
3224
3225 static void wm_adsp2_stop_core(struct wm_adsp *dsp)
3226 {
3227         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3228                            ADSP2_CORE_ENA | ADSP2_START, 0);
3229 }
3230
3231 int wm_adsp_event(struct snd_soc_dapm_widget *w,
3232                   struct snd_kcontrol *kcontrol, int event)
3233 {
3234         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
3235         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
3236         struct wm_adsp *dsp = &dsps[w->shift];
3237         int ret;
3238
3239         switch (event) {
3240         case SND_SOC_DAPM_POST_PMU:
3241                 flush_work(&dsp->boot_work);
3242
3243                 mutex_lock(&dsp->pwr_lock);
3244
3245                 if (!dsp->booted) {
3246                         ret = -EIO;
3247                         goto err;
3248                 }
3249
3250                 if (dsp->ops->enable_core) {
3251                         ret = dsp->ops->enable_core(dsp);
3252                         if (ret != 0)
3253                                 goto err;
3254                 }
3255
3256                 /* Sync set controls */
3257                 ret = wm_coeff_sync_controls(dsp);
3258                 if (ret != 0)
3259                         goto err;
3260
3261                 if (dsp->ops->lock_memory) {
3262                         ret = dsp->ops->lock_memory(dsp, dsp->lock_regions);
3263                         if (ret != 0) {
3264                                 adsp_err(dsp, "Error configuring MPU: %d\n",
3265                                          ret);
3266                                 goto err;
3267                         }
3268                 }
3269
3270                 if (dsp->ops->start_core) {
3271                         ret = dsp->ops->start_core(dsp);
3272                         if (ret != 0)
3273                                 goto err;
3274                 }
3275
3276                 if (wm_adsp_fw[dsp->fw].num_caps != 0) {
3277                         ret = wm_adsp_buffer_init(dsp);
3278                         if (ret < 0)
3279                                 goto err;
3280                 }
3281
3282                 dsp->running = true;
3283
3284                 mutex_unlock(&dsp->pwr_lock);
3285                 break;
3286
3287         case SND_SOC_DAPM_PRE_PMD:
3288                 /* Tell the firmware to cleanup */
3289                 wm_adsp_signal_event_controls(dsp, WM_ADSP_FW_EVENT_SHUTDOWN);
3290
3291                 if (dsp->ops->stop_watchdog)
3292                         dsp->ops->stop_watchdog(dsp);
3293
3294                 /* Log firmware state, it can be useful for analysis */
3295                 if (dsp->ops->show_fw_status)
3296                         dsp->ops->show_fw_status(dsp);
3297
3298                 mutex_lock(&dsp->pwr_lock);
3299
3300                 dsp->running = false;
3301
3302                 if (dsp->ops->stop_core)
3303                         dsp->ops->stop_core(dsp);
3304                 if (dsp->ops->disable_core)
3305                         dsp->ops->disable_core(dsp);
3306
3307                 if (wm_adsp_fw[dsp->fw].num_caps != 0)
3308                         wm_adsp_buffer_free(dsp);
3309
3310                 dsp->fatal_error = false;
3311
3312                 mutex_unlock(&dsp->pwr_lock);
3313
3314                 adsp_dbg(dsp, "Execution stopped\n");
3315                 break;
3316
3317         default:
3318                 break;
3319         }
3320
3321         return 0;
3322 err:
3323         if (dsp->ops->stop_core)
3324                 dsp->ops->stop_core(dsp);
3325         if (dsp->ops->disable_core)
3326                 dsp->ops->disable_core(dsp);
3327         mutex_unlock(&dsp->pwr_lock);
3328         return ret;
3329 }
3330 EXPORT_SYMBOL_GPL(wm_adsp_event);
3331
3332 static int wm_halo_start_core(struct wm_adsp *dsp)
3333 {
3334         return regmap_update_bits(dsp->regmap,
3335                                   dsp->base + HALO_CCM_CORE_CONTROL,
3336                                   HALO_CORE_EN, HALO_CORE_EN);
3337 }
3338
3339 static void wm_halo_stop_core(struct wm_adsp *dsp)
3340 {
3341         regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
3342                            HALO_CORE_EN, 0);
3343
3344         /* reset halo core with CORE_SOFT_RESET */
3345         regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET,
3346                            HALO_CORE_SOFT_RESET_MASK, 1);
3347 }
3348
3349 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component)
3350 {
3351         char preload[32];
3352
3353         snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name);
3354         snd_soc_component_disable_pin(component, preload);
3355
3356         wm_adsp2_init_debugfs(dsp, component);
3357
3358         dsp->component = component;
3359
3360         return 0;
3361 }
3362 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
3363
3364 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component)
3365 {
3366         wm_adsp2_cleanup_debugfs(dsp);
3367
3368         return 0;
3369 }
3370 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove);
3371
3372 int wm_adsp2_init(struct wm_adsp *dsp)
3373 {
3374         int ret;
3375
3376         ret = wm_adsp_common_init(dsp);
3377         if (ret)
3378                 return ret;
3379
3380         switch (dsp->rev) {
3381         case 0:
3382                 /*
3383                  * Disable the DSP memory by default when in reset for a small
3384                  * power saving.
3385                  */
3386                 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3387                                          ADSP2_MEM_ENA, 0);
3388                 if (ret) {
3389                         adsp_err(dsp,
3390                                  "Failed to clear memory retention: %d\n", ret);
3391                         return ret;
3392                 }
3393
3394                 dsp->ops = &wm_adsp2_ops[0];
3395                 break;
3396         case 1:
3397                 dsp->ops = &wm_adsp2_ops[1];
3398                 break;
3399         default:
3400                 dsp->ops = &wm_adsp2_ops[2];
3401                 break;
3402         }
3403
3404         INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
3405
3406         return 0;
3407 }
3408 EXPORT_SYMBOL_GPL(wm_adsp2_init);
3409
3410 int wm_halo_init(struct wm_adsp *dsp)
3411 {
3412         int ret;
3413
3414         ret = wm_adsp_common_init(dsp);
3415         if (ret)
3416                 return ret;
3417
3418         dsp->ops = &wm_halo_ops;
3419
3420         INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
3421
3422         return 0;
3423 }
3424 EXPORT_SYMBOL_GPL(wm_halo_init);
3425
3426 void wm_adsp2_remove(struct wm_adsp *dsp)
3427 {
3428         struct wm_coeff_ctl *ctl;
3429
3430         while (!list_empty(&dsp->ctl_list)) {
3431                 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl,
3432                                         list);
3433                 list_del(&ctl->list);
3434                 wm_adsp_free_ctl_blk(ctl);
3435         }
3436 }
3437 EXPORT_SYMBOL_GPL(wm_adsp2_remove);
3438
3439 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
3440 {
3441         return compr->buf != NULL;
3442 }
3443
3444 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
3445 {
3446         struct wm_adsp_compr_buf *buf = NULL, *tmp;
3447
3448         if (compr->dsp->fatal_error)
3449                 return -EINVAL;
3450
3451         list_for_each_entry(tmp, &compr->dsp->buffer_list, list) {
3452                 if (!tmp->name || !strcmp(compr->name, tmp->name)) {
3453                         buf = tmp;
3454                         break;
3455                 }
3456         }
3457
3458         if (!buf)
3459                 return -EINVAL;
3460
3461         compr->buf = buf;
3462         buf->compr = compr;
3463
3464         return 0;
3465 }
3466
3467 static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
3468 {
3469         if (!compr)
3470                 return;
3471
3472         /* Wake the poll so it can see buffer is no longer attached */
3473         if (compr->stream)
3474                 snd_compr_fragment_elapsed(compr->stream);
3475
3476         if (wm_adsp_compr_attached(compr)) {
3477                 compr->buf->compr = NULL;
3478                 compr->buf = NULL;
3479         }
3480 }
3481
3482 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
3483 {
3484         struct wm_adsp_compr *compr, *tmp;
3485         struct snd_soc_pcm_runtime *rtd = stream->private_data;
3486         int ret = 0;
3487
3488         mutex_lock(&dsp->pwr_lock);
3489
3490         if (wm_adsp_fw[dsp->fw].num_caps == 0) {
3491                 adsp_err(dsp, "%s: Firmware does not support compressed API\n",
3492                          asoc_rtd_to_codec(rtd, 0)->name);
3493                 ret = -ENXIO;
3494                 goto out;
3495         }
3496
3497         if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
3498                 adsp_err(dsp, "%s: Firmware does not support stream direction\n",
3499                          asoc_rtd_to_codec(rtd, 0)->name);
3500                 ret = -EINVAL;
3501                 goto out;
3502         }
3503
3504         list_for_each_entry(tmp, &dsp->compr_list, list) {
3505                 if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) {
3506                         adsp_err(dsp, "%s: Only a single stream supported per dai\n",
3507                                  asoc_rtd_to_codec(rtd, 0)->name);
3508                         ret = -EBUSY;
3509                         goto out;
3510                 }
3511         }
3512
3513         compr = kzalloc(sizeof(*compr), GFP_KERNEL);
3514         if (!compr) {
3515                 ret = -ENOMEM;
3516                 goto out;
3517         }
3518
3519         compr->dsp = dsp;
3520         compr->stream = stream;
3521         compr->name = asoc_rtd_to_codec(rtd, 0)->name;
3522
3523         list_add_tail(&compr->list, &dsp->compr_list);
3524
3525         stream->runtime->private_data = compr;
3526
3527 out:
3528         mutex_unlock(&dsp->pwr_lock);
3529
3530         return ret;
3531 }
3532 EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
3533
3534 int wm_adsp_compr_free(struct snd_soc_component *component,
3535                        struct snd_compr_stream *stream)
3536 {
3537         struct wm_adsp_compr *compr = stream->runtime->private_data;
3538         struct wm_adsp *dsp = compr->dsp;
3539
3540         mutex_lock(&dsp->pwr_lock);
3541
3542         wm_adsp_compr_detach(compr);
3543         list_del(&compr->list);
3544
3545         kfree(compr->raw_buf);
3546         kfree(compr);
3547
3548         mutex_unlock(&dsp->pwr_lock);
3549
3550         return 0;
3551 }
3552 EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
3553
3554 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
3555                                       struct snd_compr_params *params)
3556 {
3557         struct wm_adsp_compr *compr = stream->runtime->private_data;
3558         struct wm_adsp *dsp = compr->dsp;
3559         const struct wm_adsp_fw_caps *caps;
3560         const struct snd_codec_desc *desc;
3561         int i, j;
3562
3563         if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
3564             params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
3565             params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
3566             params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
3567             params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) {
3568                 compr_err(compr, "Invalid buffer fragsize=%d fragments=%d\n",
3569                           params->buffer.fragment_size,
3570                           params->buffer.fragments);
3571
3572                 return -EINVAL;
3573         }
3574
3575         for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
3576                 caps = &wm_adsp_fw[dsp->fw].caps[i];
3577                 desc = &caps->desc;
3578
3579                 if (caps->id != params->codec.id)
3580                         continue;
3581
3582                 if (stream->direction == SND_COMPRESS_PLAYBACK) {
3583                         if (desc->max_ch < params->codec.ch_out)
3584                                 continue;
3585                 } else {
3586                         if (desc->max_ch < params->codec.ch_in)
3587                                 continue;
3588                 }
3589
3590                 if (!(desc->formats & (1 << params->codec.format)))
3591                         continue;
3592
3593                 for (j = 0; j < desc->num_sample_rates; ++j)
3594                         if (desc->sample_rates[j] == params->codec.sample_rate)
3595                                 return 0;
3596         }
3597
3598         compr_err(compr, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
3599                   params->codec.id, params->codec.ch_in, params->codec.ch_out,
3600                   params->codec.sample_rate, params->codec.format);
3601         return -EINVAL;
3602 }
3603
3604 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
3605 {
3606         return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
3607 }
3608
3609 int wm_adsp_compr_set_params(struct snd_soc_component *component,
3610                              struct snd_compr_stream *stream,
3611                              struct snd_compr_params *params)
3612 {
3613         struct wm_adsp_compr *compr = stream->runtime->private_data;
3614         unsigned int size;
3615         int ret;
3616
3617         ret = wm_adsp_compr_check_params(stream, params);
3618         if (ret)
3619                 return ret;
3620
3621         compr->size = params->buffer;
3622
3623         compr_dbg(compr, "fragment_size=%d fragments=%d\n",
3624                   compr->size.fragment_size, compr->size.fragments);
3625
3626         size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
3627         compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
3628         if (!compr->raw_buf)
3629                 return -ENOMEM;
3630
3631         compr->sample_rate = params->codec.sample_rate;
3632
3633         return 0;
3634 }
3635 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
3636
3637 int wm_adsp_compr_get_caps(struct snd_soc_component *component,
3638                            struct snd_compr_stream *stream,
3639                            struct snd_compr_caps *caps)
3640 {
3641         struct wm_adsp_compr *compr = stream->runtime->private_data;
3642         int fw = compr->dsp->fw;
3643         int i;
3644
3645         if (wm_adsp_fw[fw].caps) {
3646                 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
3647                         caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
3648
3649                 caps->num_codecs = i;
3650                 caps->direction = wm_adsp_fw[fw].compr_direction;
3651
3652                 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
3653                 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
3654                 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
3655                 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
3656         }
3657
3658         return 0;
3659 }
3660 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
3661
3662 static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type,
3663                                        unsigned int mem_addr,
3664                                        unsigned int num_words, __be32 *data)
3665 {
3666         struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
3667         unsigned int reg;
3668         int ret;
3669
3670         if (!mem)
3671                 return -EINVAL;
3672
3673         reg = dsp->ops->region_to_reg(mem, mem_addr);
3674
3675         ret = regmap_raw_read(dsp->regmap, reg, data,
3676                               sizeof(*data) * num_words);
3677         if (ret < 0)
3678                 return ret;
3679
3680         return 0;
3681 }
3682
3683 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
3684                                          unsigned int mem_addr, u32 *data)
3685 {
3686         __be32 raw;
3687         int ret;
3688
3689         ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
3690         if (ret < 0)
3691                 return ret;
3692
3693         *data = be32_to_cpu(raw) & 0x00ffffffu;
3694
3695         return 0;
3696 }
3697
3698 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
3699                                    unsigned int mem_addr, u32 data)
3700 {
3701         struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
3702         __be32 val = cpu_to_be32(data & 0x00ffffffu);
3703         unsigned int reg;
3704
3705         if (!mem)
3706                 return -EINVAL;
3707
3708         reg = dsp->ops->region_to_reg(mem, mem_addr);
3709
3710         return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
3711 }
3712
3713 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
3714                                       unsigned int field_offset, u32 *data)
3715 {
3716         return wm_adsp_read_data_word(buf->dsp, buf->host_buf_mem_type,
3717                                       buf->host_buf_ptr + field_offset, data);
3718 }
3719
3720 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
3721                                        unsigned int field_offset, u32 data)
3722 {
3723         return wm_adsp_write_data_word(buf->dsp, buf->host_buf_mem_type,
3724                                        buf->host_buf_ptr + field_offset, data);
3725 }
3726
3727 static void wm_adsp_remove_padding(u32 *buf, int nwords)
3728 {
3729         const __be32 *pack_in = (__be32 *)buf;
3730         u8 *pack_out = (u8 *)buf;
3731         int i;
3732
3733         /*
3734          * DSP words from the register map have pad bytes and the data bytes
3735          * are in swapped order. This swaps back to the original little-endian
3736          * order and strips the pad bytes.
3737          */
3738         for (i = 0; i < nwords; i++) {
3739                 u32 word = be32_to_cpu(*pack_in++);
3740                 *pack_out++ = (u8)word;
3741                 *pack_out++ = (u8)(word >> 8);
3742                 *pack_out++ = (u8)(word >> 16);
3743         }
3744 }
3745
3746 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
3747 {
3748         const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
3749         struct wm_adsp_buffer_region *region;
3750         u32 offset = 0;
3751         int i, ret;
3752
3753         buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions),
3754                                GFP_KERNEL);
3755         if (!buf->regions)
3756                 return -ENOMEM;
3757
3758         for (i = 0; i < caps->num_regions; ++i) {
3759                 region = &buf->regions[i];
3760
3761                 region->offset = offset;
3762                 region->mem_type = caps->region_defs[i].mem_type;
3763
3764                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
3765                                           &region->base_addr);
3766                 if (ret < 0)
3767                         return ret;
3768
3769                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
3770                                           &offset);
3771                 if (ret < 0)
3772                         return ret;
3773
3774                 region->cumulative_size = offset;
3775
3776                 compr_dbg(buf,
3777                           "region=%d type=%d base=%08x off=%08x size=%08x\n",
3778                           i, region->mem_type, region->base_addr,
3779                           region->offset, region->cumulative_size);
3780         }
3781
3782         return 0;
3783 }
3784
3785 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
3786 {
3787         buf->irq_count = 0xFFFFFFFF;
3788         buf->read_index = -1;
3789         buf->avail = 0;
3790 }
3791
3792 static struct wm_adsp_compr_buf *wm_adsp_buffer_alloc(struct wm_adsp *dsp)
3793 {
3794         struct wm_adsp_compr_buf *buf;
3795
3796         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
3797         if (!buf)
3798                 return NULL;
3799
3800         buf->dsp = dsp;
3801
3802         wm_adsp_buffer_clear(buf);
3803
3804         list_add_tail(&buf->list, &dsp->buffer_list);
3805
3806         return buf;
3807 }
3808
3809 static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
3810 {
3811         struct wm_adsp_alg_region *alg_region;
3812         struct wm_adsp_compr_buf *buf;
3813         u32 xmalg, addr, magic;
3814         int i, ret;
3815
3816         alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
3817         if (!alg_region) {
3818                 adsp_err(dsp, "No algorithm region found\n");
3819                 return -EINVAL;
3820         }
3821
3822         buf = wm_adsp_buffer_alloc(dsp);
3823         if (!buf)
3824                 return -ENOMEM;
3825
3826         xmalg = dsp->ops->sys_config_size / sizeof(__be32);
3827
3828         addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
3829         ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
3830         if (ret < 0)
3831                 return ret;
3832
3833         if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
3834                 return -ENODEV;
3835
3836         addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
3837         for (i = 0; i < 5; ++i) {
3838                 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
3839                                              &buf->host_buf_ptr);
3840                 if (ret < 0)
3841                         return ret;
3842
3843                 if (buf->host_buf_ptr)
3844                         break;
3845
3846                 usleep_range(1000, 2000);
3847         }
3848
3849         if (!buf->host_buf_ptr)
3850                 return -EIO;
3851
3852         buf->host_buf_mem_type = WMFW_ADSP2_XM;
3853
3854         ret = wm_adsp_buffer_populate(buf);
3855         if (ret < 0)
3856                 return ret;
3857
3858         compr_dbg(buf, "legacy host_buf_ptr=%x\n", buf->host_buf_ptr);
3859
3860         return 0;
3861 }
3862
3863 static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
3864 {
3865         struct wm_adsp_host_buf_coeff_v1 coeff_v1;
3866         struct wm_adsp_compr_buf *buf;
3867         unsigned int reg, version;
3868         __be32 bufp;
3869         int ret, i;
3870
3871         ret = wm_coeff_base_reg(ctl, &reg);
3872         if (ret)
3873                 return ret;
3874
3875         for (i = 0; i < 5; ++i) {
3876                 ret = regmap_raw_read(ctl->dsp->regmap, reg, &bufp, sizeof(bufp));
3877                 if (ret < 0)
3878                         return ret;
3879
3880                 if (bufp)
3881                         break;
3882
3883                 usleep_range(1000, 2000);
3884         }
3885
3886         if (!bufp) {
3887                 adsp_err(ctl->dsp, "Failed to acquire host buffer\n");
3888                 return -EIO;
3889         }
3890
3891         buf = wm_adsp_buffer_alloc(ctl->dsp);
3892         if (!buf)
3893                 return -ENOMEM;
3894
3895         buf->host_buf_mem_type = ctl->alg_region.type;
3896         buf->host_buf_ptr = be32_to_cpu(bufp);
3897
3898         ret = wm_adsp_buffer_populate(buf);
3899         if (ret < 0)
3900                 return ret;
3901
3902         /*
3903          * v0 host_buffer coefficients didn't have versioning, so if the
3904          * control is one word, assume version 0.
3905          */
3906         if (ctl->len == 4) {
3907                 compr_dbg(buf, "host_buf_ptr=%x\n", buf->host_buf_ptr);
3908                 return 0;
3909         }
3910
3911         ret = regmap_raw_read(ctl->dsp->regmap, reg, &coeff_v1,
3912                               sizeof(coeff_v1));
3913         if (ret < 0)
3914                 return ret;
3915
3916         version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK;
3917         version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
3918
3919         if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
3920                 adsp_err(ctl->dsp,
3921                          "Host buffer coeff ver %u > supported version %u\n",
3922                          version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
3923                 return -EINVAL;
3924         }
3925
3926         wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
3927
3928         buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
3929                               (char *)&coeff_v1.name);
3930
3931         compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
3932                   buf->host_buf_ptr, version);
3933
3934         return version;
3935 }
3936
3937 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
3938 {
3939         struct wm_coeff_ctl *ctl;
3940         int ret;
3941
3942         list_for_each_entry(ctl, &dsp->ctl_list, list) {
3943                 if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
3944                         continue;
3945
3946                 if (!ctl->enabled)
3947                         continue;
3948
3949                 ret = wm_adsp_buffer_parse_coeff(ctl);
3950                 if (ret < 0) {
3951                         adsp_err(dsp, "Failed to parse coeff: %d\n", ret);
3952                         goto error;
3953                 } else if (ret == 0) {
3954                         /* Only one buffer supported for version 0 */
3955                         return 0;
3956                 }
3957         }
3958
3959         if (list_empty(&dsp->buffer_list)) {
3960                 /* Fall back to legacy support */
3961                 ret = wm_adsp_buffer_parse_legacy(dsp);
3962                 if (ret) {
3963                         adsp_err(dsp, "Failed to parse legacy: %d\n", ret);
3964                         goto error;
3965                 }
3966         }
3967
3968         return 0;
3969
3970 error:
3971         wm_adsp_buffer_free(dsp);
3972         return ret;
3973 }
3974
3975 static int wm_adsp_buffer_free(struct wm_adsp *dsp)
3976 {
3977         struct wm_adsp_compr_buf *buf, *tmp;
3978
3979         list_for_each_entry_safe(buf, tmp, &dsp->buffer_list, list) {
3980                 wm_adsp_compr_detach(buf->compr);
3981
3982                 kfree(buf->name);
3983                 kfree(buf->regions);
3984                 list_del(&buf->list);
3985                 kfree(buf);
3986         }
3987
3988         return 0;
3989 }
3990
3991 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
3992 {
3993         int ret;
3994
3995         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
3996         if (ret < 0) {
3997                 compr_err(buf, "Failed to check buffer error: %d\n", ret);
3998                 return ret;
3999         }
4000         if (buf->error != 0) {
4001                 compr_err(buf, "Buffer error occurred: %d\n", buf->error);
4002                 return -EIO;
4003         }
4004
4005         return 0;
4006 }
4007
4008 int wm_adsp_compr_trigger(struct snd_soc_component *component,
4009                           struct snd_compr_stream *stream, int cmd)
4010 {
4011         struct wm_adsp_compr *compr = stream->runtime->private_data;
4012         struct wm_adsp *dsp = compr->dsp;
4013         int ret = 0;
4014
4015         compr_dbg(compr, "Trigger: %d\n", cmd);
4016
4017         mutex_lock(&dsp->pwr_lock);
4018
4019         switch (cmd) {
4020         case SNDRV_PCM_TRIGGER_START:
4021                 if (!wm_adsp_compr_attached(compr)) {
4022                         ret = wm_adsp_compr_attach(compr);
4023                         if (ret < 0) {
4024                                 compr_err(compr, "Failed to link buffer and stream: %d\n",
4025                                           ret);
4026                                 break;
4027                         }
4028                 }
4029
4030                 ret = wm_adsp_buffer_get_error(compr->buf);
4031                 if (ret < 0)
4032                         break;
4033
4034                 /* Trigger the IRQ at one fragment of data */
4035                 ret = wm_adsp_buffer_write(compr->buf,
4036                                            HOST_BUFFER_FIELD(high_water_mark),
4037                                            wm_adsp_compr_frag_words(compr));
4038                 if (ret < 0) {
4039                         compr_err(compr, "Failed to set high water mark: %d\n",
4040                                   ret);
4041                         break;
4042                 }
4043                 break;
4044         case SNDRV_PCM_TRIGGER_STOP:
4045                 if (wm_adsp_compr_attached(compr))
4046                         wm_adsp_buffer_clear(compr->buf);
4047                 break;
4048         default:
4049                 ret = -EINVAL;
4050                 break;
4051         }
4052
4053         mutex_unlock(&dsp->pwr_lock);
4054
4055         return ret;
4056 }
4057 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
4058
4059 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
4060 {
4061         int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
4062
4063         return buf->regions[last_region].cumulative_size;
4064 }
4065
4066 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
4067 {
4068         u32 next_read_index, next_write_index;
4069         int write_index, read_index, avail;
4070         int ret;
4071
4072         /* Only sync read index if we haven't already read a valid index */
4073         if (buf->read_index < 0) {
4074                 ret = wm_adsp_buffer_read(buf,
4075                                 HOST_BUFFER_FIELD(next_read_index),
4076                                 &next_read_index);
4077                 if (ret < 0)
4078                         return ret;
4079
4080                 read_index = sign_extend32(next_read_index, 23);
4081
4082                 if (read_index < 0) {
4083                         compr_dbg(buf, "Avail check on unstarted stream\n");
4084                         return 0;
4085                 }
4086
4087                 buf->read_index = read_index;
4088         }
4089
4090         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
4091                         &next_write_index);
4092         if (ret < 0)
4093                 return ret;
4094
4095         write_index = sign_extend32(next_write_index, 23);
4096
4097         avail = write_index - buf->read_index;
4098         if (avail < 0)
4099                 avail += wm_adsp_buffer_size(buf);
4100
4101         compr_dbg(buf, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
4102                   buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
4103
4104         buf->avail = avail;
4105
4106         return 0;
4107 }
4108
4109 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
4110 {
4111         struct wm_adsp_compr_buf *buf;
4112         struct wm_adsp_compr *compr;
4113         int ret = 0;
4114
4115         mutex_lock(&dsp->pwr_lock);
4116
4117         if (list_empty(&dsp->buffer_list)) {
4118                 ret = -ENODEV;
4119                 goto out;
4120         }
4121
4122         adsp_dbg(dsp, "Handling buffer IRQ\n");
4123
4124         list_for_each_entry(buf, &dsp->buffer_list, list) {
4125                 compr = buf->compr;
4126
4127                 ret = wm_adsp_buffer_get_error(buf);
4128                 if (ret < 0)
4129                         goto out_notify; /* Wake poll to report error */
4130
4131                 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
4132                                           &buf->irq_count);
4133                 if (ret < 0) {
4134                         compr_err(buf, "Failed to get irq_count: %d\n", ret);
4135                         goto out;
4136                 }
4137
4138                 ret = wm_adsp_buffer_update_avail(buf);
4139                 if (ret < 0) {
4140                         compr_err(buf, "Error reading avail: %d\n", ret);
4141                         goto out;
4142                 }
4143
4144                 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
4145                         ret = WM_ADSP_COMPR_VOICE_TRIGGER;
4146
4147 out_notify:
4148                 if (compr && compr->stream)
4149                         snd_compr_fragment_elapsed(compr->stream);
4150         }
4151
4152 out:
4153         mutex_unlock(&dsp->pwr_lock);
4154
4155         return ret;
4156 }
4157 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
4158
4159 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
4160 {
4161         if (buf->irq_count & 0x01)
4162                 return 0;
4163
4164         compr_dbg(buf, "Enable IRQ(0x%x) for next fragment\n", buf->irq_count);
4165
4166         buf->irq_count |= 0x01;
4167
4168         return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
4169                                     buf->irq_count);
4170 }
4171
4172 int wm_adsp_compr_pointer(struct snd_soc_component *component,
4173                           struct snd_compr_stream *stream,
4174                           struct snd_compr_tstamp *tstamp)
4175 {
4176         struct wm_adsp_compr *compr = stream->runtime->private_data;
4177         struct wm_adsp *dsp = compr->dsp;
4178         struct wm_adsp_compr_buf *buf;
4179         int ret = 0;
4180
4181         compr_dbg(compr, "Pointer request\n");
4182
4183         mutex_lock(&dsp->pwr_lock);
4184
4185         buf = compr->buf;
4186
4187         if (dsp->fatal_error || !buf || buf->error) {
4188                 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
4189                 ret = -EIO;
4190                 goto out;
4191         }
4192
4193         if (buf->avail < wm_adsp_compr_frag_words(compr)) {
4194                 ret = wm_adsp_buffer_update_avail(buf);
4195                 if (ret < 0) {
4196                         compr_err(compr, "Error reading avail: %d\n", ret);
4197                         goto out;
4198                 }
4199
4200                 /*
4201                  * If we really have less than 1 fragment available tell the
4202                  * DSP to inform us once a whole fragment is available.
4203                  */
4204                 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
4205                         ret = wm_adsp_buffer_get_error(buf);
4206                         if (ret < 0) {
4207                                 if (buf->error)
4208                                         snd_compr_stop_error(stream,
4209                                                         SNDRV_PCM_STATE_XRUN);
4210                                 goto out;
4211                         }
4212
4213                         ret = wm_adsp_buffer_reenable_irq(buf);
4214                         if (ret < 0) {
4215                                 compr_err(compr, "Failed to re-enable buffer IRQ: %d\n",
4216                                           ret);
4217                                 goto out;
4218                         }
4219                 }
4220         }
4221
4222         tstamp->copied_total = compr->copied_total;
4223         tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
4224         tstamp->sampling_rate = compr->sample_rate;
4225
4226 out:
4227         mutex_unlock(&dsp->pwr_lock);
4228
4229         return ret;
4230 }
4231 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
4232
4233 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
4234 {
4235         struct wm_adsp_compr_buf *buf = compr->buf;
4236         unsigned int adsp_addr;
4237         int mem_type, nwords, max_read;
4238         int i, ret;
4239
4240         /* Calculate read parameters */
4241         for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
4242                 if (buf->read_index < buf->regions[i].cumulative_size)
4243                         break;
4244
4245         if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
4246                 return -EINVAL;
4247
4248         mem_type = buf->regions[i].mem_type;
4249         adsp_addr = buf->regions[i].base_addr +
4250                     (buf->read_index - buf->regions[i].offset);
4251
4252         max_read = wm_adsp_compr_frag_words(compr);
4253         nwords = buf->regions[i].cumulative_size - buf->read_index;
4254
4255         if (nwords > target)
4256                 nwords = target;
4257         if (nwords > buf->avail)
4258                 nwords = buf->avail;
4259         if (nwords > max_read)
4260                 nwords = max_read;
4261         if (!nwords)
4262                 return 0;
4263
4264         /* Read data from DSP */
4265         ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr,
4266                                           nwords, (__be32 *)compr->raw_buf);
4267         if (ret < 0)
4268                 return ret;
4269
4270         wm_adsp_remove_padding(compr->raw_buf, nwords);
4271
4272         /* update read index to account for words read */
4273         buf->read_index += nwords;
4274         if (buf->read_index == wm_adsp_buffer_size(buf))
4275                 buf->read_index = 0;
4276
4277         ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
4278                                    buf->read_index);
4279         if (ret < 0)
4280                 return ret;
4281
4282         /* update avail to account for words read */
4283         buf->avail -= nwords;
4284
4285         return nwords;
4286 }
4287
4288 static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
4289                               char __user *buf, size_t count)
4290 {
4291         struct wm_adsp *dsp = compr->dsp;
4292         int ntotal = 0;
4293         int nwords, nbytes;
4294
4295         compr_dbg(compr, "Requested read of %zu bytes\n", count);
4296
4297         if (dsp->fatal_error || !compr->buf || compr->buf->error) {
4298                 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
4299                 return -EIO;
4300         }
4301
4302         count /= WM_ADSP_DATA_WORD_SIZE;
4303
4304         do {
4305                 nwords = wm_adsp_buffer_capture_block(compr, count);
4306                 if (nwords < 0) {
4307                         compr_err(compr, "Failed to capture block: %d\n",
4308                                   nwords);
4309                         return nwords;
4310                 }
4311
4312                 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
4313
4314                 compr_dbg(compr, "Read %d bytes\n", nbytes);
4315
4316                 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
4317                         compr_err(compr, "Failed to copy data to user: %d, %d\n",
4318                                   ntotal, nbytes);
4319                         return -EFAULT;
4320                 }
4321
4322                 count -= nwords;
4323                 ntotal += nbytes;
4324         } while (nwords > 0 && count > 0);
4325
4326         compr->copied_total += ntotal;
4327
4328         return ntotal;
4329 }
4330
4331 int wm_adsp_compr_copy(struct snd_soc_component *component,
4332                        struct snd_compr_stream *stream, char __user *buf,
4333                        size_t count)
4334 {
4335         struct wm_adsp_compr *compr = stream->runtime->private_data;
4336         struct wm_adsp *dsp = compr->dsp;
4337         int ret;
4338
4339         mutex_lock(&dsp->pwr_lock);
4340
4341         if (stream->direction == SND_COMPRESS_CAPTURE)
4342                 ret = wm_adsp_compr_read(compr, buf, count);
4343         else
4344                 ret = -ENOTSUPP;
4345
4346         mutex_unlock(&dsp->pwr_lock);
4347
4348         return ret;
4349 }
4350 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
4351
4352 static void wm_adsp_fatal_error(struct wm_adsp *dsp)
4353 {
4354         struct wm_adsp_compr *compr;
4355
4356         dsp->fatal_error = true;
4357
4358         list_for_each_entry(compr, &dsp->compr_list, list) {
4359                 if (compr->stream)
4360                         snd_compr_fragment_elapsed(compr->stream);
4361         }
4362 }
4363
4364 irqreturn_t wm_adsp2_bus_error(int irq, void *data)
4365 {
4366         struct wm_adsp *dsp = (struct wm_adsp *)data;
4367         unsigned int val;
4368         struct regmap *regmap = dsp->regmap;
4369         int ret = 0;
4370
4371         mutex_lock(&dsp->pwr_lock);
4372
4373         ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val);
4374         if (ret) {
4375                 adsp_err(dsp,
4376                         "Failed to read Region Lock Ctrl register: %d\n", ret);
4377                 goto error;
4378         }
4379
4380         if (val & ADSP2_WDT_TIMEOUT_STS_MASK) {
4381                 adsp_err(dsp, "watchdog timeout error\n");
4382                 dsp->ops->stop_watchdog(dsp);
4383                 wm_adsp_fatal_error(dsp);
4384         }
4385
4386         if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
4387                 if (val & ADSP2_ADDR_ERR_MASK)
4388                         adsp_err(dsp, "bus error: address error\n");
4389                 else
4390                         adsp_err(dsp, "bus error: region lock error\n");
4391
4392                 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val);
4393                 if (ret) {
4394                         adsp_err(dsp,
4395                                  "Failed to read Bus Err Addr register: %d\n",
4396                                  ret);
4397                         goto error;
4398                 }
4399
4400                 adsp_err(dsp, "bus error address = 0x%x\n",
4401                          val & ADSP2_BUS_ERR_ADDR_MASK);
4402
4403                 ret = regmap_read(regmap,
4404                                   dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR,
4405                                   &val);
4406                 if (ret) {
4407                         adsp_err(dsp,
4408                                  "Failed to read Pmem Xmem Err Addr register: %d\n",
4409                                  ret);
4410                         goto error;
4411                 }
4412
4413                 adsp_err(dsp, "xmem error address = 0x%x\n",
4414                          val & ADSP2_XMEM_ERR_ADDR_MASK);
4415                 adsp_err(dsp, "pmem error address = 0x%x\n",
4416                          (val & ADSP2_PMEM_ERR_ADDR_MASK) >>
4417                          ADSP2_PMEM_ERR_ADDR_SHIFT);
4418         }
4419
4420         regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL,
4421                            ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT);
4422
4423 error:
4424         mutex_unlock(&dsp->pwr_lock);
4425
4426         return IRQ_HANDLED;
4427 }
4428 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
4429
4430 irqreturn_t wm_halo_bus_error(int irq, void *data)
4431 {
4432         struct wm_adsp *dsp = (struct wm_adsp *)data;
4433         struct regmap *regmap = dsp->regmap;
4434         unsigned int fault[6];
4435         struct reg_sequence clear[] = {
4436                 { dsp->base + HALO_MPU_XM_VIO_STATUS,     0x0 },
4437                 { dsp->base + HALO_MPU_YM_VIO_STATUS,     0x0 },
4438                 { dsp->base + HALO_MPU_PM_VIO_STATUS,     0x0 },
4439         };
4440         int ret;
4441
4442         mutex_lock(&dsp->pwr_lock);
4443
4444         ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1,
4445                           fault);
4446         if (ret) {
4447                 adsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret);
4448                 goto exit_unlock;
4449         }
4450
4451         adsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n",
4452                   *fault & HALO_AHBM_FLAGS_ERR_MASK,
4453                   (*fault & HALO_AHBM_CORE_ERR_ADDR_MASK) >>
4454                   HALO_AHBM_CORE_ERR_ADDR_SHIFT);
4455
4456         ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0,
4457                           fault);
4458         if (ret) {
4459                 adsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret);
4460                 goto exit_unlock;
4461         }
4462
4463         adsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault);
4464
4465         ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR,
4466                                fault, ARRAY_SIZE(fault));
4467         if (ret) {
4468                 adsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret);
4469                 goto exit_unlock;
4470         }
4471
4472         adsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]);
4473         adsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]);
4474         adsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]);
4475
4476         ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear));
4477         if (ret)
4478                 adsp_warn(dsp, "Failed to clear MPU status: %d\n", ret);
4479
4480 exit_unlock:
4481         mutex_unlock(&dsp->pwr_lock);
4482
4483         return IRQ_HANDLED;
4484 }
4485 EXPORT_SYMBOL_GPL(wm_halo_bus_error);
4486
4487 irqreturn_t wm_halo_wdt_expire(int irq, void *data)
4488 {
4489         struct wm_adsp *dsp = data;
4490
4491         mutex_lock(&dsp->pwr_lock);
4492
4493         adsp_warn(dsp, "WDT Expiry Fault\n");
4494         dsp->ops->stop_watchdog(dsp);
4495         wm_adsp_fatal_error(dsp);
4496
4497         mutex_unlock(&dsp->pwr_lock);
4498
4499         return IRQ_HANDLED;
4500 }
4501 EXPORT_SYMBOL_GPL(wm_halo_wdt_expire);
4502
4503 static const struct wm_adsp_ops wm_adsp1_ops = {
4504         .validate_version = wm_adsp_validate_version,
4505         .parse_sizes = wm_adsp1_parse_sizes,
4506         .region_to_reg = wm_adsp_region_to_reg,
4507 };
4508
4509 static const struct wm_adsp_ops wm_adsp2_ops[] = {
4510         {
4511                 .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4512                 .parse_sizes = wm_adsp2_parse_sizes,
4513                 .validate_version = wm_adsp_validate_version,
4514                 .setup_algs = wm_adsp2_setup_algs,
4515                 .region_to_reg = wm_adsp_region_to_reg,
4516
4517                 .show_fw_status = wm_adsp2_show_fw_status,
4518
4519                 .enable_memory = wm_adsp2_enable_memory,
4520                 .disable_memory = wm_adsp2_disable_memory,
4521
4522                 .enable_core = wm_adsp2_enable_core,
4523                 .disable_core = wm_adsp2_disable_core,
4524
4525                 .start_core = wm_adsp2_start_core,
4526                 .stop_core = wm_adsp2_stop_core,
4527
4528         },
4529         {
4530                 .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4531                 .parse_sizes = wm_adsp2_parse_sizes,
4532                 .validate_version = wm_adsp_validate_version,
4533                 .setup_algs = wm_adsp2_setup_algs,
4534                 .region_to_reg = wm_adsp_region_to_reg,
4535
4536                 .show_fw_status = wm_adsp2v2_show_fw_status,
4537
4538                 .enable_memory = wm_adsp2_enable_memory,
4539                 .disable_memory = wm_adsp2_disable_memory,
4540                 .lock_memory = wm_adsp2_lock,
4541
4542                 .enable_core = wm_adsp2v2_enable_core,
4543                 .disable_core = wm_adsp2v2_disable_core,
4544
4545                 .start_core = wm_adsp2_start_core,
4546                 .stop_core = wm_adsp2_stop_core,
4547         },
4548         {
4549                 .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4550                 .parse_sizes = wm_adsp2_parse_sizes,
4551                 .validate_version = wm_adsp_validate_version,
4552                 .setup_algs = wm_adsp2_setup_algs,
4553                 .region_to_reg = wm_adsp_region_to_reg,
4554
4555                 .show_fw_status = wm_adsp2v2_show_fw_status,
4556                 .stop_watchdog = wm_adsp_stop_watchdog,
4557
4558                 .enable_memory = wm_adsp2_enable_memory,
4559                 .disable_memory = wm_adsp2_disable_memory,
4560                 .lock_memory = wm_adsp2_lock,
4561
4562                 .enable_core = wm_adsp2v2_enable_core,
4563                 .disable_core = wm_adsp2v2_disable_core,
4564
4565                 .start_core = wm_adsp2_start_core,
4566                 .stop_core = wm_adsp2_stop_core,
4567         },
4568 };
4569
4570 static const struct wm_adsp_ops wm_halo_ops = {
4571         .sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr),
4572         .parse_sizes = wm_adsp2_parse_sizes,
4573         .validate_version = wm_halo_validate_version,
4574         .setup_algs = wm_halo_setup_algs,
4575         .region_to_reg = wm_halo_region_to_reg,
4576
4577         .show_fw_status = wm_halo_show_fw_status,
4578         .stop_watchdog = wm_halo_stop_watchdog,
4579
4580         .lock_memory = wm_halo_configure_mpu,
4581
4582         .start_core = wm_halo_start_core,
4583         .stop_core = wm_halo_stop_core,
4584 };
4585
4586 MODULE_LICENSE("GPL v2");