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