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