Merge tag 'fs_for_v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack...
[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_RESET                     0x00000200
286 #define HALO_CORE_EN                        0x00000001
287
288 /*
289  * HALO_CORE_SOFT_RESET
290  */
291 #define HALO_CORE_SOFT_RESET_MASK           0x00000001
292
293 /*
294  * HALO_WDT_CONTROL
295  */
296 #define HALO_WDT_EN_MASK                    0x00000001
297
298 /*
299  * HALO_MPU_?M_VIO_STATUS
300  */
301 #define HALO_MPU_VIO_STS_MASK               0x007e0000
302 #define HALO_MPU_VIO_STS_SHIFT                      17
303 #define HALO_MPU_VIO_ERR_WR_MASK            0x00008000
304 #define HALO_MPU_VIO_ERR_SRC_MASK           0x00007fff
305 #define HALO_MPU_VIO_ERR_SRC_SHIFT                   0
306
307 static const struct wm_adsp_ops wm_adsp1_ops;
308 static const struct wm_adsp_ops wm_adsp2_ops[];
309 static const struct wm_adsp_ops wm_halo_ops;
310
311 struct wm_adsp_buf {
312         struct list_head list;
313         void *buf;
314 };
315
316 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
317                                              struct list_head *list)
318 {
319         struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
320
321         if (buf == NULL)
322                 return NULL;
323
324         buf->buf = vmalloc(len);
325         if (!buf->buf) {
326                 kfree(buf);
327                 return NULL;
328         }
329         memcpy(buf->buf, src, len);
330
331         if (list)
332                 list_add_tail(&buf->list, list);
333
334         return buf;
335 }
336
337 static void wm_adsp_buf_free(struct list_head *list)
338 {
339         while (!list_empty(list)) {
340                 struct wm_adsp_buf *buf = list_first_entry(list,
341                                                            struct wm_adsp_buf,
342                                                            list);
343                 list_del(&buf->list);
344                 vfree(buf->buf);
345                 kfree(buf);
346         }
347 }
348
349 #define WM_ADSP_FW_MBC_VSS  0
350 #define WM_ADSP_FW_HIFI     1
351 #define WM_ADSP_FW_TX       2
352 #define WM_ADSP_FW_TX_SPK   3
353 #define WM_ADSP_FW_RX       4
354 #define WM_ADSP_FW_RX_ANC   5
355 #define WM_ADSP_FW_CTRL     6
356 #define WM_ADSP_FW_ASR      7
357 #define WM_ADSP_FW_TRACE    8
358 #define WM_ADSP_FW_SPK_PROT 9
359 #define WM_ADSP_FW_SPK_CALI 10
360 #define WM_ADSP_FW_SPK_DIAG 11
361 #define WM_ADSP_FW_MISC     12
362
363 #define WM_ADSP_NUM_FW      13
364
365 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
366         [WM_ADSP_FW_MBC_VSS] =  "MBC/VSS",
367         [WM_ADSP_FW_HIFI] =     "MasterHiFi",
368         [WM_ADSP_FW_TX] =       "Tx",
369         [WM_ADSP_FW_TX_SPK] =   "Tx Speaker",
370         [WM_ADSP_FW_RX] =       "Rx",
371         [WM_ADSP_FW_RX_ANC] =   "Rx ANC",
372         [WM_ADSP_FW_CTRL] =     "Voice Ctrl",
373         [WM_ADSP_FW_ASR] =      "ASR Assist",
374         [WM_ADSP_FW_TRACE] =    "Dbg Trace",
375         [WM_ADSP_FW_SPK_PROT] = "Protection",
376         [WM_ADSP_FW_SPK_CALI] = "Calibration",
377         [WM_ADSP_FW_SPK_DIAG] = "Diagnostic",
378         [WM_ADSP_FW_MISC] =     "Misc",
379 };
380
381 struct wm_adsp_system_config_xm_hdr {
382         __be32 sys_enable;
383         __be32 fw_id;
384         __be32 fw_rev;
385         __be32 boot_status;
386         __be32 watchdog;
387         __be32 dma_buffer_size;
388         __be32 rdma[6];
389         __be32 wdma[8];
390         __be32 build_job_name[3];
391         __be32 build_job_number;
392 };
393
394 struct wm_halo_system_config_xm_hdr {
395         __be32 halo_heartbeat;
396         __be32 build_job_name[3];
397         __be32 build_job_number;
398 };
399
400 struct wm_adsp_alg_xm_struct {
401         __be32 magic;
402         __be32 smoothing;
403         __be32 threshold;
404         __be32 host_buf_ptr;
405         __be32 start_seq;
406         __be32 high_water_mark;
407         __be32 low_water_mark;
408         __be64 smoothed_power;
409 };
410
411 struct wm_adsp_host_buf_coeff_v1 {
412         __be32 host_buf_ptr;            /* Host buffer pointer */
413         __be32 versions;                /* Version numbers */
414         __be32 name[4];                 /* The buffer name */
415 };
416
417 struct wm_adsp_buffer {
418         __be32 buf1_base;               /* Base addr of first buffer area */
419         __be32 buf1_size;               /* Size of buf1 area in DSP words */
420         __be32 buf2_base;               /* Base addr of 2nd buffer area */
421         __be32 buf1_buf2_size;          /* Size of buf1+buf2 in DSP words */
422         __be32 buf3_base;               /* Base addr of buf3 area */
423         __be32 buf_total_size;          /* Size of buf1+buf2+buf3 in DSP words */
424         __be32 high_water_mark;         /* Point at which IRQ is asserted */
425         __be32 irq_count;               /* bits 1-31 count IRQ assertions */
426         __be32 irq_ack;                 /* acked IRQ count, bit 0 enables IRQ */
427         __be32 next_write_index;        /* word index of next write */
428         __be32 next_read_index;         /* word index of next read */
429         __be32 error;                   /* error if any */
430         __be32 oldest_block_index;      /* word index of oldest surviving */
431         __be32 requested_rewind;        /* how many blocks rewind was done */
432         __be32 reserved_space;          /* internal */
433         __be32 min_free;                /* min free space since stream start */
434         __be32 blocks_written[2];       /* total blocks written (64 bit) */
435         __be32 words_written[2];        /* total words written (64 bit) */
436 };
437
438 struct wm_adsp_compr;
439
440 struct wm_adsp_compr_buf {
441         struct list_head list;
442         struct wm_adsp *dsp;
443         struct wm_adsp_compr *compr;
444
445         struct wm_adsp_buffer_region *regions;
446         u32 host_buf_ptr;
447
448         u32 error;
449         u32 irq_count;
450         int read_index;
451         int avail;
452         int host_buf_mem_type;
453
454         char *name;
455 };
456
457 struct wm_adsp_compr {
458         struct list_head list;
459         struct wm_adsp *dsp;
460         struct wm_adsp_compr_buf *buf;
461
462         struct snd_compr_stream *stream;
463         struct snd_compressed_buffer size;
464
465         u32 *raw_buf;
466         unsigned int copied_total;
467
468         unsigned int sample_rate;
469
470         const char *name;
471 };
472
473 #define WM_ADSP_DATA_WORD_SIZE         3
474
475 #define WM_ADSP_MIN_FRAGMENTS          1
476 #define WM_ADSP_MAX_FRAGMENTS          256
477 #define WM_ADSP_MIN_FRAGMENT_SIZE      (64 * WM_ADSP_DATA_WORD_SIZE)
478 #define WM_ADSP_MAX_FRAGMENT_SIZE      (4096 * WM_ADSP_DATA_WORD_SIZE)
479
480 #define WM_ADSP_ALG_XM_STRUCT_MAGIC    0x49aec7
481
482 #define HOST_BUFFER_FIELD(field) \
483         (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
484
485 #define ALG_XM_FIELD(field) \
486         (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
487
488 #define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER     1
489
490 #define HOST_BUF_COEFF_COMPAT_VER_MASK          0xFF00
491 #define HOST_BUF_COEFF_COMPAT_VER_SHIFT         8
492
493 static int wm_adsp_buffer_init(struct wm_adsp *dsp);
494 static int wm_adsp_buffer_free(struct wm_adsp *dsp);
495
496 struct wm_adsp_buffer_region {
497         unsigned int offset;
498         unsigned int cumulative_size;
499         unsigned int mem_type;
500         unsigned int base_addr;
501 };
502
503 struct wm_adsp_buffer_region_def {
504         unsigned int mem_type;
505         unsigned int base_offset;
506         unsigned int size_offset;
507 };
508
509 static const struct wm_adsp_buffer_region_def default_regions[] = {
510         {
511                 .mem_type = WMFW_ADSP2_XM,
512                 .base_offset = HOST_BUFFER_FIELD(buf1_base),
513                 .size_offset = HOST_BUFFER_FIELD(buf1_size),
514         },
515         {
516                 .mem_type = WMFW_ADSP2_XM,
517                 .base_offset = HOST_BUFFER_FIELD(buf2_base),
518                 .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size),
519         },
520         {
521                 .mem_type = WMFW_ADSP2_YM,
522                 .base_offset = HOST_BUFFER_FIELD(buf3_base),
523                 .size_offset = HOST_BUFFER_FIELD(buf_total_size),
524         },
525 };
526
527 struct wm_adsp_fw_caps {
528         u32 id;
529         struct snd_codec_desc desc;
530         int num_regions;
531         const struct wm_adsp_buffer_region_def *region_defs;
532 };
533
534 static const struct wm_adsp_fw_caps ctrl_caps[] = {
535         {
536                 .id = SND_AUDIOCODEC_BESPOKE,
537                 .desc = {
538                         .max_ch = 8,
539                         .sample_rates = { 16000 },
540                         .num_sample_rates = 1,
541                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
542                 },
543                 .num_regions = ARRAY_SIZE(default_regions),
544                 .region_defs = default_regions,
545         },
546 };
547
548 static const struct wm_adsp_fw_caps trace_caps[] = {
549         {
550                 .id = SND_AUDIOCODEC_BESPOKE,
551                 .desc = {
552                         .max_ch = 8,
553                         .sample_rates = {
554                                 4000, 8000, 11025, 12000, 16000, 22050,
555                                 24000, 32000, 44100, 48000, 64000, 88200,
556                                 96000, 176400, 192000
557                         },
558                         .num_sample_rates = 15,
559                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
560                 },
561                 .num_regions = ARRAY_SIZE(default_regions),
562                 .region_defs = default_regions,
563         },
564 };
565
566 static const struct {
567         const char *file;
568         int compr_direction;
569         int num_caps;
570         const struct wm_adsp_fw_caps *caps;
571         bool voice_trigger;
572 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
573         [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
574         [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
575         [WM_ADSP_FW_TX] =       { .file = "tx" },
576         [WM_ADSP_FW_TX_SPK] =   { .file = "tx-spk" },
577         [WM_ADSP_FW_RX] =       { .file = "rx" },
578         [WM_ADSP_FW_RX_ANC] =   { .file = "rx-anc" },
579         [WM_ADSP_FW_CTRL] =     {
580                 .file = "ctrl",
581                 .compr_direction = SND_COMPRESS_CAPTURE,
582                 .num_caps = ARRAY_SIZE(ctrl_caps),
583                 .caps = ctrl_caps,
584                 .voice_trigger = true,
585         },
586         [WM_ADSP_FW_ASR] =      { .file = "asr" },
587         [WM_ADSP_FW_TRACE] =    {
588                 .file = "trace",
589                 .compr_direction = SND_COMPRESS_CAPTURE,
590                 .num_caps = ARRAY_SIZE(trace_caps),
591                 .caps = trace_caps,
592         },
593         [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
594         [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" },
595         [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" },
596         [WM_ADSP_FW_MISC] =     { .file = "misc" },
597 };
598
599 struct wm_coeff_ctl {
600         const char *name;
601         const char *fw_name;
602         /* Subname is needed to match with firmware */
603         const char *subname;
604         unsigned int subname_len;
605         struct wm_adsp_alg_region alg_region;
606         struct wm_adsp *dsp;
607         unsigned int enabled:1;
608         struct list_head list;
609         void *cache;
610         unsigned int offset;
611         size_t len;
612         unsigned int set:1;
613         struct soc_bytes_ext bytes_ext;
614         unsigned int flags;
615         snd_ctl_elem_type_t type;
616 };
617
618 static const char *wm_adsp_mem_region_name(unsigned int type)
619 {
620         switch (type) {
621         case WMFW_ADSP1_PM:
622                 return "PM";
623         case WMFW_HALO_PM_PACKED:
624                 return "PM_PACKED";
625         case WMFW_ADSP1_DM:
626                 return "DM";
627         case WMFW_ADSP2_XM:
628                 return "XM";
629         case WMFW_HALO_XM_PACKED:
630                 return "XM_PACKED";
631         case WMFW_ADSP2_YM:
632                 return "YM";
633         case WMFW_HALO_YM_PACKED:
634                 return "YM_PACKED";
635         case WMFW_ADSP1_ZM:
636                 return "ZM";
637         default:
638                 return NULL;
639         }
640 }
641
642 #ifdef CONFIG_DEBUG_FS
643 static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
644 {
645         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
646
647         kfree(dsp->wmfw_file_name);
648         dsp->wmfw_file_name = tmp;
649 }
650
651 static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
652 {
653         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
654
655         kfree(dsp->bin_file_name);
656         dsp->bin_file_name = tmp;
657 }
658
659 static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
660 {
661         kfree(dsp->wmfw_file_name);
662         kfree(dsp->bin_file_name);
663         dsp->wmfw_file_name = NULL;
664         dsp->bin_file_name = NULL;
665 }
666
667 static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
668                                          char __user *user_buf,
669                                          size_t count, loff_t *ppos)
670 {
671         struct wm_adsp *dsp = file->private_data;
672         ssize_t ret;
673
674         mutex_lock(&dsp->pwr_lock);
675
676         if (!dsp->wmfw_file_name || !dsp->booted)
677                 ret = 0;
678         else
679                 ret = simple_read_from_buffer(user_buf, count, ppos,
680                                               dsp->wmfw_file_name,
681                                               strlen(dsp->wmfw_file_name));
682
683         mutex_unlock(&dsp->pwr_lock);
684         return ret;
685 }
686
687 static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
688                                         char __user *user_buf,
689                                         size_t count, loff_t *ppos)
690 {
691         struct wm_adsp *dsp = file->private_data;
692         ssize_t ret;
693
694         mutex_lock(&dsp->pwr_lock);
695
696         if (!dsp->bin_file_name || !dsp->booted)
697                 ret = 0;
698         else
699                 ret = simple_read_from_buffer(user_buf, count, ppos,
700                                               dsp->bin_file_name,
701                                               strlen(dsp->bin_file_name));
702
703         mutex_unlock(&dsp->pwr_lock);
704         return ret;
705 }
706
707 static const struct {
708         const char *name;
709         const struct file_operations fops;
710 } wm_adsp_debugfs_fops[] = {
711         {
712                 .name = "wmfw_file_name",
713                 .fops = {
714                         .open = simple_open,
715                         .read = wm_adsp_debugfs_wmfw_read,
716                 },
717         },
718         {
719                 .name = "bin_file_name",
720                 .fops = {
721                         .open = simple_open,
722                         .read = wm_adsp_debugfs_bin_read,
723                 },
724         },
725 };
726
727 static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
728                                   struct snd_soc_component *component)
729 {
730         struct dentry *root = NULL;
731         int i;
732
733         root = debugfs_create_dir(dsp->name, component->debugfs_root);
734
735         debugfs_create_bool("booted", 0444, root, &dsp->booted);
736         debugfs_create_bool("running", 0444, root, &dsp->running);
737         debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id);
738         debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version);
739
740         for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i)
741                 debugfs_create_file(wm_adsp_debugfs_fops[i].name, 0444, root,
742                                     dsp, &wm_adsp_debugfs_fops[i].fops);
743
744         dsp->debugfs_root = root;
745 }
746
747 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
748 {
749         wm_adsp_debugfs_clear(dsp);
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(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_RESET | HALO_CORE_EN,
3337                                   HALO_CORE_RESET | HALO_CORE_EN);
3338 }
3339
3340 static void wm_halo_stop_core(struct wm_adsp *dsp)
3341 {
3342         regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
3343                            HALO_CORE_EN, 0);
3344
3345         /* reset halo core with CORE_SOFT_RESET */
3346         regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET,
3347                            HALO_CORE_SOFT_RESET_MASK, 1);
3348 }
3349
3350 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component)
3351 {
3352         char preload[32];
3353
3354         snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->name);
3355         snd_soc_component_disable_pin(component, preload);
3356
3357         wm_adsp2_init_debugfs(dsp, component);
3358
3359         dsp->component = component;
3360
3361         return 0;
3362 }
3363 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
3364
3365 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component)
3366 {
3367         wm_adsp2_cleanup_debugfs(dsp);
3368
3369         return 0;
3370 }
3371 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove);
3372
3373 int wm_adsp2_init(struct wm_adsp *dsp)
3374 {
3375         int ret;
3376
3377         ret = wm_adsp_common_init(dsp);
3378         if (ret)
3379                 return ret;
3380
3381         switch (dsp->rev) {
3382         case 0:
3383                 /*
3384                  * Disable the DSP memory by default when in reset for a small
3385                  * power saving.
3386                  */
3387                 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
3388                                          ADSP2_MEM_ENA, 0);
3389                 if (ret) {
3390                         adsp_err(dsp,
3391                                  "Failed to clear memory retention: %d\n", ret);
3392                         return ret;
3393                 }
3394
3395                 dsp->ops = &wm_adsp2_ops[0];
3396                 break;
3397         case 1:
3398                 dsp->ops = &wm_adsp2_ops[1];
3399                 break;
3400         default:
3401                 dsp->ops = &wm_adsp2_ops[2];
3402                 break;
3403         }
3404
3405         INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
3406
3407         return 0;
3408 }
3409 EXPORT_SYMBOL_GPL(wm_adsp2_init);
3410
3411 int wm_halo_init(struct wm_adsp *dsp)
3412 {
3413         int ret;
3414
3415         ret = wm_adsp_common_init(dsp);
3416         if (ret)
3417                 return ret;
3418
3419         dsp->ops = &wm_halo_ops;
3420
3421         INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
3422
3423         return 0;
3424 }
3425 EXPORT_SYMBOL_GPL(wm_halo_init);
3426
3427 void wm_adsp2_remove(struct wm_adsp *dsp)
3428 {
3429         struct wm_coeff_ctl *ctl;
3430
3431         while (!list_empty(&dsp->ctl_list)) {
3432                 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl,
3433                                         list);
3434                 list_del(&ctl->list);
3435                 wm_adsp_free_ctl_blk(ctl);
3436         }
3437 }
3438 EXPORT_SYMBOL_GPL(wm_adsp2_remove);
3439
3440 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
3441 {
3442         return compr->buf != NULL;
3443 }
3444
3445 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
3446 {
3447         struct wm_adsp_compr_buf *buf = NULL, *tmp;
3448
3449         if (compr->dsp->fatal_error)
3450                 return -EINVAL;
3451
3452         list_for_each_entry(tmp, &compr->dsp->buffer_list, list) {
3453                 if (!tmp->name || !strcmp(compr->name, tmp->name)) {
3454                         buf = tmp;
3455                         break;
3456                 }
3457         }
3458
3459         if (!buf)
3460                 return -EINVAL;
3461
3462         compr->buf = buf;
3463         buf->compr = compr;
3464
3465         return 0;
3466 }
3467
3468 static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
3469 {
3470         if (!compr)
3471                 return;
3472
3473         /* Wake the poll so it can see buffer is no longer attached */
3474         if (compr->stream)
3475                 snd_compr_fragment_elapsed(compr->stream);
3476
3477         if (wm_adsp_compr_attached(compr)) {
3478                 compr->buf->compr = NULL;
3479                 compr->buf = NULL;
3480         }
3481 }
3482
3483 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
3484 {
3485         struct wm_adsp_compr *compr, *tmp;
3486         struct snd_soc_pcm_runtime *rtd = stream->private_data;
3487         int ret = 0;
3488
3489         mutex_lock(&dsp->pwr_lock);
3490
3491         if (wm_adsp_fw[dsp->fw].num_caps == 0) {
3492                 adsp_err(dsp, "%s: Firmware does not support compressed API\n",
3493                          asoc_rtd_to_codec(rtd, 0)->name);
3494                 ret = -ENXIO;
3495                 goto out;
3496         }
3497
3498         if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
3499                 adsp_err(dsp, "%s: Firmware does not support stream direction\n",
3500                          asoc_rtd_to_codec(rtd, 0)->name);
3501                 ret = -EINVAL;
3502                 goto out;
3503         }
3504
3505         list_for_each_entry(tmp, &dsp->compr_list, list) {
3506                 if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) {
3507                         adsp_err(dsp, "%s: Only a single stream supported per dai\n",
3508                                  asoc_rtd_to_codec(rtd, 0)->name);
3509                         ret = -EBUSY;
3510                         goto out;
3511                 }
3512         }
3513
3514         compr = kzalloc(sizeof(*compr), GFP_KERNEL);
3515         if (!compr) {
3516                 ret = -ENOMEM;
3517                 goto out;
3518         }
3519
3520         compr->dsp = dsp;
3521         compr->stream = stream;
3522         compr->name = asoc_rtd_to_codec(rtd, 0)->name;
3523
3524         list_add_tail(&compr->list, &dsp->compr_list);
3525
3526         stream->runtime->private_data = compr;
3527
3528 out:
3529         mutex_unlock(&dsp->pwr_lock);
3530
3531         return ret;
3532 }
3533 EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
3534
3535 int wm_adsp_compr_free(struct snd_soc_component *component,
3536                        struct snd_compr_stream *stream)
3537 {
3538         struct wm_adsp_compr *compr = stream->runtime->private_data;
3539         struct wm_adsp *dsp = compr->dsp;
3540
3541         mutex_lock(&dsp->pwr_lock);
3542
3543         wm_adsp_compr_detach(compr);
3544         list_del(&compr->list);
3545
3546         kfree(compr->raw_buf);
3547         kfree(compr);
3548
3549         mutex_unlock(&dsp->pwr_lock);
3550
3551         return 0;
3552 }
3553 EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
3554
3555 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
3556                                       struct snd_compr_params *params)
3557 {
3558         struct wm_adsp_compr *compr = stream->runtime->private_data;
3559         struct wm_adsp *dsp = compr->dsp;
3560         const struct wm_adsp_fw_caps *caps;
3561         const struct snd_codec_desc *desc;
3562         int i, j;
3563
3564         if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
3565             params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
3566             params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
3567             params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
3568             params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) {
3569                 compr_err(compr, "Invalid buffer fragsize=%d fragments=%d\n",
3570                           params->buffer.fragment_size,
3571                           params->buffer.fragments);
3572
3573                 return -EINVAL;
3574         }
3575
3576         for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
3577                 caps = &wm_adsp_fw[dsp->fw].caps[i];
3578                 desc = &caps->desc;
3579
3580                 if (caps->id != params->codec.id)
3581                         continue;
3582
3583                 if (stream->direction == SND_COMPRESS_PLAYBACK) {
3584                         if (desc->max_ch < params->codec.ch_out)
3585                                 continue;
3586                 } else {
3587                         if (desc->max_ch < params->codec.ch_in)
3588                                 continue;
3589                 }
3590
3591                 if (!(desc->formats & (1 << params->codec.format)))
3592                         continue;
3593
3594                 for (j = 0; j < desc->num_sample_rates; ++j)
3595                         if (desc->sample_rates[j] == params->codec.sample_rate)
3596                                 return 0;
3597         }
3598
3599         compr_err(compr, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
3600                   params->codec.id, params->codec.ch_in, params->codec.ch_out,
3601                   params->codec.sample_rate, params->codec.format);
3602         return -EINVAL;
3603 }
3604
3605 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
3606 {
3607         return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
3608 }
3609
3610 int wm_adsp_compr_set_params(struct snd_soc_component *component,
3611                              struct snd_compr_stream *stream,
3612                              struct snd_compr_params *params)
3613 {
3614         struct wm_adsp_compr *compr = stream->runtime->private_data;
3615         unsigned int size;
3616         int ret;
3617
3618         ret = wm_adsp_compr_check_params(stream, params);
3619         if (ret)
3620                 return ret;
3621
3622         compr->size = params->buffer;
3623
3624         compr_dbg(compr, "fragment_size=%d fragments=%d\n",
3625                   compr->size.fragment_size, compr->size.fragments);
3626
3627         size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
3628         compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
3629         if (!compr->raw_buf)
3630                 return -ENOMEM;
3631
3632         compr->sample_rate = params->codec.sample_rate;
3633
3634         return 0;
3635 }
3636 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
3637
3638 int wm_adsp_compr_get_caps(struct snd_soc_component *component,
3639                            struct snd_compr_stream *stream,
3640                            struct snd_compr_caps *caps)
3641 {
3642         struct wm_adsp_compr *compr = stream->runtime->private_data;
3643         int fw = compr->dsp->fw;
3644         int i;
3645
3646         if (wm_adsp_fw[fw].caps) {
3647                 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
3648                         caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
3649
3650                 caps->num_codecs = i;
3651                 caps->direction = wm_adsp_fw[fw].compr_direction;
3652
3653                 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
3654                 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
3655                 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
3656                 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
3657         }
3658
3659         return 0;
3660 }
3661 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
3662
3663 static int wm_adsp_read_raw_data_block(struct wm_adsp *dsp, int mem_type,
3664                                        unsigned int mem_addr,
3665                                        unsigned int num_words, __be32 *data)
3666 {
3667         struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
3668         unsigned int reg;
3669         int ret;
3670
3671         if (!mem)
3672                 return -EINVAL;
3673
3674         reg = dsp->ops->region_to_reg(mem, mem_addr);
3675
3676         ret = regmap_raw_read(dsp->regmap, reg, data,
3677                               sizeof(*data) * num_words);
3678         if (ret < 0)
3679                 return ret;
3680
3681         return 0;
3682 }
3683
3684 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
3685                                          unsigned int mem_addr, u32 *data)
3686 {
3687         __be32 raw;
3688         int ret;
3689
3690         ret = wm_adsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
3691         if (ret < 0)
3692                 return ret;
3693
3694         *data = be32_to_cpu(raw) & 0x00ffffffu;
3695
3696         return 0;
3697 }
3698
3699 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
3700                                    unsigned int mem_addr, u32 data)
3701 {
3702         struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
3703         __be32 val = cpu_to_be32(data & 0x00ffffffu);
3704         unsigned int reg;
3705
3706         if (!mem)
3707                 return -EINVAL;
3708
3709         reg = dsp->ops->region_to_reg(mem, mem_addr);
3710
3711         return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
3712 }
3713
3714 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
3715                                       unsigned int field_offset, u32 *data)
3716 {
3717         return wm_adsp_read_data_word(buf->dsp, buf->host_buf_mem_type,
3718                                       buf->host_buf_ptr + field_offset, data);
3719 }
3720
3721 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
3722                                        unsigned int field_offset, u32 data)
3723 {
3724         return wm_adsp_write_data_word(buf->dsp, buf->host_buf_mem_type,
3725                                        buf->host_buf_ptr + field_offset, data);
3726 }
3727
3728 static void wm_adsp_remove_padding(u32 *buf, int nwords)
3729 {
3730         const __be32 *pack_in = (__be32 *)buf;
3731         u8 *pack_out = (u8 *)buf;
3732         int i;
3733
3734         /*
3735          * DSP words from the register map have pad bytes and the data bytes
3736          * are in swapped order. This swaps back to the original little-endian
3737          * order and strips the pad bytes.
3738          */
3739         for (i = 0; i < nwords; i++) {
3740                 u32 word = be32_to_cpu(*pack_in++);
3741                 *pack_out++ = (u8)word;
3742                 *pack_out++ = (u8)(word >> 8);
3743                 *pack_out++ = (u8)(word >> 16);
3744         }
3745 }
3746
3747 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
3748 {
3749         const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
3750         struct wm_adsp_buffer_region *region;
3751         u32 offset = 0;
3752         int i, ret;
3753
3754         buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions),
3755                                GFP_KERNEL);
3756         if (!buf->regions)
3757                 return -ENOMEM;
3758
3759         for (i = 0; i < caps->num_regions; ++i) {
3760                 region = &buf->regions[i];
3761
3762                 region->offset = offset;
3763                 region->mem_type = caps->region_defs[i].mem_type;
3764
3765                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
3766                                           &region->base_addr);
3767                 if (ret < 0)
3768                         return ret;
3769
3770                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
3771                                           &offset);
3772                 if (ret < 0)
3773                         return ret;
3774
3775                 region->cumulative_size = offset;
3776
3777                 compr_dbg(buf,
3778                           "region=%d type=%d base=%08x off=%08x size=%08x\n",
3779                           i, region->mem_type, region->base_addr,
3780                           region->offset, region->cumulative_size);
3781         }
3782
3783         return 0;
3784 }
3785
3786 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
3787 {
3788         buf->irq_count = 0xFFFFFFFF;
3789         buf->read_index = -1;
3790         buf->avail = 0;
3791 }
3792
3793 static struct wm_adsp_compr_buf *wm_adsp_buffer_alloc(struct wm_adsp *dsp)
3794 {
3795         struct wm_adsp_compr_buf *buf;
3796
3797         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
3798         if (!buf)
3799                 return NULL;
3800
3801         buf->dsp = dsp;
3802
3803         wm_adsp_buffer_clear(buf);
3804
3805         list_add_tail(&buf->list, &dsp->buffer_list);
3806
3807         return buf;
3808 }
3809
3810 static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
3811 {
3812         struct wm_adsp_alg_region *alg_region;
3813         struct wm_adsp_compr_buf *buf;
3814         u32 xmalg, addr, magic;
3815         int i, ret;
3816
3817         alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
3818         if (!alg_region) {
3819                 adsp_err(dsp, "No algorithm region found\n");
3820                 return -EINVAL;
3821         }
3822
3823         buf = wm_adsp_buffer_alloc(dsp);
3824         if (!buf)
3825                 return -ENOMEM;
3826
3827         xmalg = dsp->ops->sys_config_size / sizeof(__be32);
3828
3829         addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
3830         ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
3831         if (ret < 0)
3832                 return ret;
3833
3834         if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
3835                 return -ENODEV;
3836
3837         addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
3838         for (i = 0; i < 5; ++i) {
3839                 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
3840                                              &buf->host_buf_ptr);
3841                 if (ret < 0)
3842                         return ret;
3843
3844                 if (buf->host_buf_ptr)
3845                         break;
3846
3847                 usleep_range(1000, 2000);
3848         }
3849
3850         if (!buf->host_buf_ptr)
3851                 return -EIO;
3852
3853         buf->host_buf_mem_type = WMFW_ADSP2_XM;
3854
3855         ret = wm_adsp_buffer_populate(buf);
3856         if (ret < 0)
3857                 return ret;
3858
3859         compr_dbg(buf, "legacy host_buf_ptr=%x\n", buf->host_buf_ptr);
3860
3861         return 0;
3862 }
3863
3864 static int wm_adsp_buffer_parse_coeff(struct wm_coeff_ctl *ctl)
3865 {
3866         struct wm_adsp_host_buf_coeff_v1 coeff_v1;
3867         struct wm_adsp_compr_buf *buf;
3868         unsigned int reg, version;
3869         __be32 bufp;
3870         int ret, i;
3871
3872         ret = wm_coeff_base_reg(ctl, &reg);
3873         if (ret)
3874                 return ret;
3875
3876         for (i = 0; i < 5; ++i) {
3877                 ret = regmap_raw_read(ctl->dsp->regmap, reg, &bufp, sizeof(bufp));
3878                 if (ret < 0)
3879                         return ret;
3880
3881                 if (bufp)
3882                         break;
3883
3884                 usleep_range(1000, 2000);
3885         }
3886
3887         if (!bufp) {
3888                 adsp_err(ctl->dsp, "Failed to acquire host buffer\n");
3889                 return -EIO;
3890         }
3891
3892         buf = wm_adsp_buffer_alloc(ctl->dsp);
3893         if (!buf)
3894                 return -ENOMEM;
3895
3896         buf->host_buf_mem_type = ctl->alg_region.type;
3897         buf->host_buf_ptr = be32_to_cpu(bufp);
3898
3899         ret = wm_adsp_buffer_populate(buf);
3900         if (ret < 0)
3901                 return ret;
3902
3903         /*
3904          * v0 host_buffer coefficients didn't have versioning, so if the
3905          * control is one word, assume version 0.
3906          */
3907         if (ctl->len == 4) {
3908                 compr_dbg(buf, "host_buf_ptr=%x\n", buf->host_buf_ptr);
3909                 return 0;
3910         }
3911
3912         ret = regmap_raw_read(ctl->dsp->regmap, reg, &coeff_v1,
3913                               sizeof(coeff_v1));
3914         if (ret < 0)
3915                 return ret;
3916
3917         version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK;
3918         version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
3919
3920         if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
3921                 adsp_err(ctl->dsp,
3922                          "Host buffer coeff ver %u > supported version %u\n",
3923                          version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
3924                 return -EINVAL;
3925         }
3926
3927         wm_adsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
3928
3929         buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", ctl->dsp->part,
3930                               (char *)&coeff_v1.name);
3931
3932         compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
3933                   buf->host_buf_ptr, version);
3934
3935         return version;
3936 }
3937
3938 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
3939 {
3940         struct wm_coeff_ctl *ctl;
3941         int ret;
3942
3943         list_for_each_entry(ctl, &dsp->ctl_list, list) {
3944                 if (ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
3945                         continue;
3946
3947                 if (!ctl->enabled)
3948                         continue;
3949
3950                 ret = wm_adsp_buffer_parse_coeff(ctl);
3951                 if (ret < 0) {
3952                         adsp_err(dsp, "Failed to parse coeff: %d\n", ret);
3953                         goto error;
3954                 } else if (ret == 0) {
3955                         /* Only one buffer supported for version 0 */
3956                         return 0;
3957                 }
3958         }
3959
3960         if (list_empty(&dsp->buffer_list)) {
3961                 /* Fall back to legacy support */
3962                 ret = wm_adsp_buffer_parse_legacy(dsp);
3963                 if (ret) {
3964                         adsp_err(dsp, "Failed to parse legacy: %d\n", ret);
3965                         goto error;
3966                 }
3967         }
3968
3969         return 0;
3970
3971 error:
3972         wm_adsp_buffer_free(dsp);
3973         return ret;
3974 }
3975
3976 static int wm_adsp_buffer_free(struct wm_adsp *dsp)
3977 {
3978         struct wm_adsp_compr_buf *buf, *tmp;
3979
3980         list_for_each_entry_safe(buf, tmp, &dsp->buffer_list, list) {
3981                 wm_adsp_compr_detach(buf->compr);
3982
3983                 kfree(buf->name);
3984                 kfree(buf->regions);
3985                 list_del(&buf->list);
3986                 kfree(buf);
3987         }
3988
3989         return 0;
3990 }
3991
3992 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
3993 {
3994         int ret;
3995
3996         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
3997         if (ret < 0) {
3998                 compr_err(buf, "Failed to check buffer error: %d\n", ret);
3999                 return ret;
4000         }
4001         if (buf->error != 0) {
4002                 compr_err(buf, "Buffer error occurred: %d\n", buf->error);
4003                 return -EIO;
4004         }
4005
4006         return 0;
4007 }
4008
4009 int wm_adsp_compr_trigger(struct snd_soc_component *component,
4010                           struct snd_compr_stream *stream, int cmd)
4011 {
4012         struct wm_adsp_compr *compr = stream->runtime->private_data;
4013         struct wm_adsp *dsp = compr->dsp;
4014         int ret = 0;
4015
4016         compr_dbg(compr, "Trigger: %d\n", cmd);
4017
4018         mutex_lock(&dsp->pwr_lock);
4019
4020         switch (cmd) {
4021         case SNDRV_PCM_TRIGGER_START:
4022                 if (!wm_adsp_compr_attached(compr)) {
4023                         ret = wm_adsp_compr_attach(compr);
4024                         if (ret < 0) {
4025                                 compr_err(compr, "Failed to link buffer and stream: %d\n",
4026                                           ret);
4027                                 break;
4028                         }
4029                 }
4030
4031                 ret = wm_adsp_buffer_get_error(compr->buf);
4032                 if (ret < 0)
4033                         break;
4034
4035                 /* Trigger the IRQ at one fragment of data */
4036                 ret = wm_adsp_buffer_write(compr->buf,
4037                                            HOST_BUFFER_FIELD(high_water_mark),
4038                                            wm_adsp_compr_frag_words(compr));
4039                 if (ret < 0) {
4040                         compr_err(compr, "Failed to set high water mark: %d\n",
4041                                   ret);
4042                         break;
4043                 }
4044                 break;
4045         case SNDRV_PCM_TRIGGER_STOP:
4046                 if (wm_adsp_compr_attached(compr))
4047                         wm_adsp_buffer_clear(compr->buf);
4048                 break;
4049         default:
4050                 ret = -EINVAL;
4051                 break;
4052         }
4053
4054         mutex_unlock(&dsp->pwr_lock);
4055
4056         return ret;
4057 }
4058 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
4059
4060 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
4061 {
4062         int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
4063
4064         return buf->regions[last_region].cumulative_size;
4065 }
4066
4067 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
4068 {
4069         u32 next_read_index, next_write_index;
4070         int write_index, read_index, avail;
4071         int ret;
4072
4073         /* Only sync read index if we haven't already read a valid index */
4074         if (buf->read_index < 0) {
4075                 ret = wm_adsp_buffer_read(buf,
4076                                 HOST_BUFFER_FIELD(next_read_index),
4077                                 &next_read_index);
4078                 if (ret < 0)
4079                         return ret;
4080
4081                 read_index = sign_extend32(next_read_index, 23);
4082
4083                 if (read_index < 0) {
4084                         compr_dbg(buf, "Avail check on unstarted stream\n");
4085                         return 0;
4086                 }
4087
4088                 buf->read_index = read_index;
4089         }
4090
4091         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
4092                         &next_write_index);
4093         if (ret < 0)
4094                 return ret;
4095
4096         write_index = sign_extend32(next_write_index, 23);
4097
4098         avail = write_index - buf->read_index;
4099         if (avail < 0)
4100                 avail += wm_adsp_buffer_size(buf);
4101
4102         compr_dbg(buf, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
4103                   buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
4104
4105         buf->avail = avail;
4106
4107         return 0;
4108 }
4109
4110 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
4111 {
4112         struct wm_adsp_compr_buf *buf;
4113         struct wm_adsp_compr *compr;
4114         int ret = 0;
4115
4116         mutex_lock(&dsp->pwr_lock);
4117
4118         if (list_empty(&dsp->buffer_list)) {
4119                 ret = -ENODEV;
4120                 goto out;
4121         }
4122
4123         adsp_dbg(dsp, "Handling buffer IRQ\n");
4124
4125         list_for_each_entry(buf, &dsp->buffer_list, list) {
4126                 compr = buf->compr;
4127
4128                 ret = wm_adsp_buffer_get_error(buf);
4129                 if (ret < 0)
4130                         goto out_notify; /* Wake poll to report error */
4131
4132                 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
4133                                           &buf->irq_count);
4134                 if (ret < 0) {
4135                         compr_err(buf, "Failed to get irq_count: %d\n", ret);
4136                         goto out;
4137                 }
4138
4139                 ret = wm_adsp_buffer_update_avail(buf);
4140                 if (ret < 0) {
4141                         compr_err(buf, "Error reading avail: %d\n", ret);
4142                         goto out;
4143                 }
4144
4145                 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
4146                         ret = WM_ADSP_COMPR_VOICE_TRIGGER;
4147
4148 out_notify:
4149                 if (compr && compr->stream)
4150                         snd_compr_fragment_elapsed(compr->stream);
4151         }
4152
4153 out:
4154         mutex_unlock(&dsp->pwr_lock);
4155
4156         return ret;
4157 }
4158 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
4159
4160 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
4161 {
4162         if (buf->irq_count & 0x01)
4163                 return 0;
4164
4165         compr_dbg(buf, "Enable IRQ(0x%x) for next fragment\n", buf->irq_count);
4166
4167         buf->irq_count |= 0x01;
4168
4169         return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
4170                                     buf->irq_count);
4171 }
4172
4173 int wm_adsp_compr_pointer(struct snd_soc_component *component,
4174                           struct snd_compr_stream *stream,
4175                           struct snd_compr_tstamp *tstamp)
4176 {
4177         struct wm_adsp_compr *compr = stream->runtime->private_data;
4178         struct wm_adsp *dsp = compr->dsp;
4179         struct wm_adsp_compr_buf *buf;
4180         int ret = 0;
4181
4182         compr_dbg(compr, "Pointer request\n");
4183
4184         mutex_lock(&dsp->pwr_lock);
4185
4186         buf = compr->buf;
4187
4188         if (dsp->fatal_error || !buf || buf->error) {
4189                 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
4190                 ret = -EIO;
4191                 goto out;
4192         }
4193
4194         if (buf->avail < wm_adsp_compr_frag_words(compr)) {
4195                 ret = wm_adsp_buffer_update_avail(buf);
4196                 if (ret < 0) {
4197                         compr_err(compr, "Error reading avail: %d\n", ret);
4198                         goto out;
4199                 }
4200
4201                 /*
4202                  * If we really have less than 1 fragment available tell the
4203                  * DSP to inform us once a whole fragment is available.
4204                  */
4205                 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
4206                         ret = wm_adsp_buffer_get_error(buf);
4207                         if (ret < 0) {
4208                                 if (buf->error)
4209                                         snd_compr_stop_error(stream,
4210                                                         SNDRV_PCM_STATE_XRUN);
4211                                 goto out;
4212                         }
4213
4214                         ret = wm_adsp_buffer_reenable_irq(buf);
4215                         if (ret < 0) {
4216                                 compr_err(compr, "Failed to re-enable buffer IRQ: %d\n",
4217                                           ret);
4218                                 goto out;
4219                         }
4220                 }
4221         }
4222
4223         tstamp->copied_total = compr->copied_total;
4224         tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
4225         tstamp->sampling_rate = compr->sample_rate;
4226
4227 out:
4228         mutex_unlock(&dsp->pwr_lock);
4229
4230         return ret;
4231 }
4232 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
4233
4234 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
4235 {
4236         struct wm_adsp_compr_buf *buf = compr->buf;
4237         unsigned int adsp_addr;
4238         int mem_type, nwords, max_read;
4239         int i, ret;
4240
4241         /* Calculate read parameters */
4242         for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
4243                 if (buf->read_index < buf->regions[i].cumulative_size)
4244                         break;
4245
4246         if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
4247                 return -EINVAL;
4248
4249         mem_type = buf->regions[i].mem_type;
4250         adsp_addr = buf->regions[i].base_addr +
4251                     (buf->read_index - buf->regions[i].offset);
4252
4253         max_read = wm_adsp_compr_frag_words(compr);
4254         nwords = buf->regions[i].cumulative_size - buf->read_index;
4255
4256         if (nwords > target)
4257                 nwords = target;
4258         if (nwords > buf->avail)
4259                 nwords = buf->avail;
4260         if (nwords > max_read)
4261                 nwords = max_read;
4262         if (!nwords)
4263                 return 0;
4264
4265         /* Read data from DSP */
4266         ret = wm_adsp_read_raw_data_block(buf->dsp, mem_type, adsp_addr,
4267                                           nwords, (__be32 *)compr->raw_buf);
4268         if (ret < 0)
4269                 return ret;
4270
4271         wm_adsp_remove_padding(compr->raw_buf, nwords);
4272
4273         /* update read index to account for words read */
4274         buf->read_index += nwords;
4275         if (buf->read_index == wm_adsp_buffer_size(buf))
4276                 buf->read_index = 0;
4277
4278         ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
4279                                    buf->read_index);
4280         if (ret < 0)
4281                 return ret;
4282
4283         /* update avail to account for words read */
4284         buf->avail -= nwords;
4285
4286         return nwords;
4287 }
4288
4289 static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
4290                               char __user *buf, size_t count)
4291 {
4292         struct wm_adsp *dsp = compr->dsp;
4293         int ntotal = 0;
4294         int nwords, nbytes;
4295
4296         compr_dbg(compr, "Requested read of %zu bytes\n", count);
4297
4298         if (dsp->fatal_error || !compr->buf || compr->buf->error) {
4299                 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
4300                 return -EIO;
4301         }
4302
4303         count /= WM_ADSP_DATA_WORD_SIZE;
4304
4305         do {
4306                 nwords = wm_adsp_buffer_capture_block(compr, count);
4307                 if (nwords < 0) {
4308                         compr_err(compr, "Failed to capture block: %d\n",
4309                                   nwords);
4310                         return nwords;
4311                 }
4312
4313                 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
4314
4315                 compr_dbg(compr, "Read %d bytes\n", nbytes);
4316
4317                 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
4318                         compr_err(compr, "Failed to copy data to user: %d, %d\n",
4319                                   ntotal, nbytes);
4320                         return -EFAULT;
4321                 }
4322
4323                 count -= nwords;
4324                 ntotal += nbytes;
4325         } while (nwords > 0 && count > 0);
4326
4327         compr->copied_total += ntotal;
4328
4329         return ntotal;
4330 }
4331
4332 int wm_adsp_compr_copy(struct snd_soc_component *component,
4333                        struct snd_compr_stream *stream, char __user *buf,
4334                        size_t count)
4335 {
4336         struct wm_adsp_compr *compr = stream->runtime->private_data;
4337         struct wm_adsp *dsp = compr->dsp;
4338         int ret;
4339
4340         mutex_lock(&dsp->pwr_lock);
4341
4342         if (stream->direction == SND_COMPRESS_CAPTURE)
4343                 ret = wm_adsp_compr_read(compr, buf, count);
4344         else
4345                 ret = -ENOTSUPP;
4346
4347         mutex_unlock(&dsp->pwr_lock);
4348
4349         return ret;
4350 }
4351 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
4352
4353 static void wm_adsp_fatal_error(struct wm_adsp *dsp)
4354 {
4355         struct wm_adsp_compr *compr;
4356
4357         dsp->fatal_error = true;
4358
4359         list_for_each_entry(compr, &dsp->compr_list, list) {
4360                 if (compr->stream)
4361                         snd_compr_fragment_elapsed(compr->stream);
4362         }
4363 }
4364
4365 irqreturn_t wm_adsp2_bus_error(int irq, void *data)
4366 {
4367         struct wm_adsp *dsp = (struct wm_adsp *)data;
4368         unsigned int val;
4369         struct regmap *regmap = dsp->regmap;
4370         int ret = 0;
4371
4372         mutex_lock(&dsp->pwr_lock);
4373
4374         ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val);
4375         if (ret) {
4376                 adsp_err(dsp,
4377                         "Failed to read Region Lock Ctrl register: %d\n", ret);
4378                 goto error;
4379         }
4380
4381         if (val & ADSP2_WDT_TIMEOUT_STS_MASK) {
4382                 adsp_err(dsp, "watchdog timeout error\n");
4383                 dsp->ops->stop_watchdog(dsp);
4384                 wm_adsp_fatal_error(dsp);
4385         }
4386
4387         if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
4388                 if (val & ADSP2_ADDR_ERR_MASK)
4389                         adsp_err(dsp, "bus error: address error\n");
4390                 else
4391                         adsp_err(dsp, "bus error: region lock error\n");
4392
4393                 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val);
4394                 if (ret) {
4395                         adsp_err(dsp,
4396                                  "Failed to read Bus Err Addr register: %d\n",
4397                                  ret);
4398                         goto error;
4399                 }
4400
4401                 adsp_err(dsp, "bus error address = 0x%x\n",
4402                          val & ADSP2_BUS_ERR_ADDR_MASK);
4403
4404                 ret = regmap_read(regmap,
4405                                   dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR,
4406                                   &val);
4407                 if (ret) {
4408                         adsp_err(dsp,
4409                                  "Failed to read Pmem Xmem Err Addr register: %d\n",
4410                                  ret);
4411                         goto error;
4412                 }
4413
4414                 adsp_err(dsp, "xmem error address = 0x%x\n",
4415                          val & ADSP2_XMEM_ERR_ADDR_MASK);
4416                 adsp_err(dsp, "pmem error address = 0x%x\n",
4417                          (val & ADSP2_PMEM_ERR_ADDR_MASK) >>
4418                          ADSP2_PMEM_ERR_ADDR_SHIFT);
4419         }
4420
4421         regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL,
4422                            ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT);
4423
4424 error:
4425         mutex_unlock(&dsp->pwr_lock);
4426
4427         return IRQ_HANDLED;
4428 }
4429 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
4430
4431 irqreturn_t wm_halo_bus_error(int irq, void *data)
4432 {
4433         struct wm_adsp *dsp = (struct wm_adsp *)data;
4434         struct regmap *regmap = dsp->regmap;
4435         unsigned int fault[6];
4436         struct reg_sequence clear[] = {
4437                 { dsp->base + HALO_MPU_XM_VIO_STATUS,     0x0 },
4438                 { dsp->base + HALO_MPU_YM_VIO_STATUS,     0x0 },
4439                 { dsp->base + HALO_MPU_PM_VIO_STATUS,     0x0 },
4440         };
4441         int ret;
4442
4443         mutex_lock(&dsp->pwr_lock);
4444
4445         ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1,
4446                           fault);
4447         if (ret) {
4448                 adsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret);
4449                 goto exit_unlock;
4450         }
4451
4452         adsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n",
4453                   *fault & HALO_AHBM_FLAGS_ERR_MASK,
4454                   (*fault & HALO_AHBM_CORE_ERR_ADDR_MASK) >>
4455                   HALO_AHBM_CORE_ERR_ADDR_SHIFT);
4456
4457         ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0,
4458                           fault);
4459         if (ret) {
4460                 adsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret);
4461                 goto exit_unlock;
4462         }
4463
4464         adsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault);
4465
4466         ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR,
4467                                fault, ARRAY_SIZE(fault));
4468         if (ret) {
4469                 adsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret);
4470                 goto exit_unlock;
4471         }
4472
4473         adsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]);
4474         adsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]);
4475         adsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]);
4476
4477         ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear));
4478         if (ret)
4479                 adsp_warn(dsp, "Failed to clear MPU status: %d\n", ret);
4480
4481 exit_unlock:
4482         mutex_unlock(&dsp->pwr_lock);
4483
4484         return IRQ_HANDLED;
4485 }
4486 EXPORT_SYMBOL_GPL(wm_halo_bus_error);
4487
4488 irqreturn_t wm_halo_wdt_expire(int irq, void *data)
4489 {
4490         struct wm_adsp *dsp = data;
4491
4492         mutex_lock(&dsp->pwr_lock);
4493
4494         adsp_warn(dsp, "WDT Expiry Fault\n");
4495         dsp->ops->stop_watchdog(dsp);
4496         wm_adsp_fatal_error(dsp);
4497
4498         mutex_unlock(&dsp->pwr_lock);
4499
4500         return IRQ_HANDLED;
4501 }
4502 EXPORT_SYMBOL_GPL(wm_halo_wdt_expire);
4503
4504 static const struct wm_adsp_ops wm_adsp1_ops = {
4505         .validate_version = wm_adsp_validate_version,
4506         .parse_sizes = wm_adsp1_parse_sizes,
4507         .region_to_reg = wm_adsp_region_to_reg,
4508 };
4509
4510 static const struct wm_adsp_ops wm_adsp2_ops[] = {
4511         {
4512                 .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4513                 .parse_sizes = wm_adsp2_parse_sizes,
4514                 .validate_version = wm_adsp_validate_version,
4515                 .setup_algs = wm_adsp2_setup_algs,
4516                 .region_to_reg = wm_adsp_region_to_reg,
4517
4518                 .show_fw_status = wm_adsp2_show_fw_status,
4519
4520                 .enable_memory = wm_adsp2_enable_memory,
4521                 .disable_memory = wm_adsp2_disable_memory,
4522
4523                 .enable_core = wm_adsp2_enable_core,
4524                 .disable_core = wm_adsp2_disable_core,
4525
4526                 .start_core = wm_adsp2_start_core,
4527                 .stop_core = wm_adsp2_stop_core,
4528
4529         },
4530         {
4531                 .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4532                 .parse_sizes = wm_adsp2_parse_sizes,
4533                 .validate_version = wm_adsp_validate_version,
4534                 .setup_algs = wm_adsp2_setup_algs,
4535                 .region_to_reg = wm_adsp_region_to_reg,
4536
4537                 .show_fw_status = wm_adsp2v2_show_fw_status,
4538
4539                 .enable_memory = wm_adsp2_enable_memory,
4540                 .disable_memory = wm_adsp2_disable_memory,
4541                 .lock_memory = wm_adsp2_lock,
4542
4543                 .enable_core = wm_adsp2v2_enable_core,
4544                 .disable_core = wm_adsp2v2_disable_core,
4545
4546                 .start_core = wm_adsp2_start_core,
4547                 .stop_core = wm_adsp2_stop_core,
4548         },
4549         {
4550                 .sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr),
4551                 .parse_sizes = wm_adsp2_parse_sizes,
4552                 .validate_version = wm_adsp_validate_version,
4553                 .setup_algs = wm_adsp2_setup_algs,
4554                 .region_to_reg = wm_adsp_region_to_reg,
4555
4556                 .show_fw_status = wm_adsp2v2_show_fw_status,
4557                 .stop_watchdog = wm_adsp_stop_watchdog,
4558
4559                 .enable_memory = wm_adsp2_enable_memory,
4560                 .disable_memory = wm_adsp2_disable_memory,
4561                 .lock_memory = wm_adsp2_lock,
4562
4563                 .enable_core = wm_adsp2v2_enable_core,
4564                 .disable_core = wm_adsp2v2_disable_core,
4565
4566                 .start_core = wm_adsp2_start_core,
4567                 .stop_core = wm_adsp2_stop_core,
4568         },
4569 };
4570
4571 static const struct wm_adsp_ops wm_halo_ops = {
4572         .sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr),
4573         .parse_sizes = wm_adsp2_parse_sizes,
4574         .validate_version = wm_halo_validate_version,
4575         .setup_algs = wm_halo_setup_algs,
4576         .region_to_reg = wm_halo_region_to_reg,
4577
4578         .show_fw_status = wm_halo_show_fw_status,
4579         .stop_watchdog = wm_halo_stop_watchdog,
4580
4581         .lock_memory = wm_halo_configure_mpu,
4582
4583         .start_core = wm_halo_start_core,
4584         .stop_core = wm_halo_stop_core,
4585 };
4586
4587 MODULE_LICENSE("GPL v2");