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