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