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