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