]> Git Repo - linux.git/blob - sound/soc/codecs/wm_adsp.c
Merge branch 'topic/arizona' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux.git] / sound / soc / codecs / wm_adsp.c
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
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/firmware.h>
18 #include <linux/list.h>
19 #include <linux/pm.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/slab.h>
24 #include <linux/vmalloc.h>
25 #include <linux/workqueue.h>
26 #include <linux/debugfs.h>
27 #include <sound/core.h>
28 #include <sound/pcm.h>
29 #include <sound/pcm_params.h>
30 #include <sound/soc.h>
31 #include <sound/jack.h>
32 #include <sound/initval.h>
33 #include <sound/tlv.h>
34
35 #include "wm_adsp.h"
36
37 #define adsp_crit(_dsp, fmt, ...) \
38         dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
39 #define adsp_err(_dsp, fmt, ...) \
40         dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
41 #define adsp_warn(_dsp, fmt, ...) \
42         dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
43 #define adsp_info(_dsp, fmt, ...) \
44         dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
45 #define adsp_dbg(_dsp, fmt, ...) \
46         dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
47
48 #define ADSP1_CONTROL_1                   0x00
49 #define ADSP1_CONTROL_2                   0x02
50 #define ADSP1_CONTROL_3                   0x03
51 #define ADSP1_CONTROL_4                   0x04
52 #define ADSP1_CONTROL_5                   0x06
53 #define ADSP1_CONTROL_6                   0x07
54 #define ADSP1_CONTROL_7                   0x08
55 #define ADSP1_CONTROL_8                   0x09
56 #define ADSP1_CONTROL_9                   0x0A
57 #define ADSP1_CONTROL_10                  0x0B
58 #define ADSP1_CONTROL_11                  0x0C
59 #define ADSP1_CONTROL_12                  0x0D
60 #define ADSP1_CONTROL_13                  0x0F
61 #define ADSP1_CONTROL_14                  0x10
62 #define ADSP1_CONTROL_15                  0x11
63 #define ADSP1_CONTROL_16                  0x12
64 #define ADSP1_CONTROL_17                  0x13
65 #define ADSP1_CONTROL_18                  0x14
66 #define ADSP1_CONTROL_19                  0x16
67 #define ADSP1_CONTROL_20                  0x17
68 #define ADSP1_CONTROL_21                  0x18
69 #define ADSP1_CONTROL_22                  0x1A
70 #define ADSP1_CONTROL_23                  0x1B
71 #define ADSP1_CONTROL_24                  0x1C
72 #define ADSP1_CONTROL_25                  0x1E
73 #define ADSP1_CONTROL_26                  0x20
74 #define ADSP1_CONTROL_27                  0x21
75 #define ADSP1_CONTROL_28                  0x22
76 #define ADSP1_CONTROL_29                  0x23
77 #define ADSP1_CONTROL_30                  0x24
78 #define ADSP1_CONTROL_31                  0x26
79
80 /*
81  * ADSP1 Control 19
82  */
83 #define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
84 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
85 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
86
87
88 /*
89  * ADSP1 Control 30
90  */
91 #define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
92 #define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
93 #define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
94 #define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
95 #define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
96 #define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
97 #define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
98 #define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
99 #define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
100 #define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
101 #define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
102 #define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
103 #define ADSP1_START                       0x0001  /* DSP1_START */
104 #define ADSP1_START_MASK                  0x0001  /* DSP1_START */
105 #define ADSP1_START_SHIFT                      0  /* DSP1_START */
106 #define ADSP1_START_WIDTH                      1  /* DSP1_START */
107
108 /*
109  * ADSP1 Control 31
110  */
111 #define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
112 #define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
113 #define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
114
115 #define ADSP2_CONTROL        0x0
116 #define ADSP2_CLOCKING       0x1
117 #define ADSP2_STATUS1        0x4
118 #define ADSP2_WDMA_CONFIG_1 0x30
119 #define ADSP2_WDMA_CONFIG_2 0x31
120 #define ADSP2_RDMA_CONFIG_1 0x34
121
122 #define ADSP2_SCRATCH0        0x40
123 #define ADSP2_SCRATCH1        0x41
124 #define ADSP2_SCRATCH2        0x42
125 #define ADSP2_SCRATCH3        0x43
126
127 /*
128  * ADSP2 Control
129  */
130
131 #define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
132 #define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
133 #define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
134 #define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
135 #define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
136 #define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
137 #define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
138 #define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
139 #define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
140 #define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
141 #define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
142 #define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
143 #define ADSP2_START                       0x0001  /* DSP1_START */
144 #define ADSP2_START_MASK                  0x0001  /* DSP1_START */
145 #define ADSP2_START_SHIFT                      0  /* DSP1_START */
146 #define ADSP2_START_WIDTH                      1  /* DSP1_START */
147
148 /*
149  * ADSP2 clocking
150  */
151 #define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
152 #define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
153 #define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
154
155 /*
156  * ADSP2 Status 1
157  */
158 #define ADSP2_RAM_RDY                     0x0001
159 #define ADSP2_RAM_RDY_MASK                0x0001
160 #define ADSP2_RAM_RDY_SHIFT                    0
161 #define ADSP2_RAM_RDY_WIDTH                    1
162
163 #define ADSP_MAX_STD_CTRL_SIZE               512
164
165 struct wm_adsp_buf {
166         struct list_head list;
167         void *buf;
168 };
169
170 static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
171                                              struct list_head *list)
172 {
173         struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
174
175         if (buf == NULL)
176                 return NULL;
177
178         buf->buf = vmalloc(len);
179         if (!buf->buf) {
180                 vfree(buf);
181                 return NULL;
182         }
183         memcpy(buf->buf, src, len);
184
185         if (list)
186                 list_add_tail(&buf->list, list);
187
188         return buf;
189 }
190
191 static void wm_adsp_buf_free(struct list_head *list)
192 {
193         while (!list_empty(list)) {
194                 struct wm_adsp_buf *buf = list_first_entry(list,
195                                                            struct wm_adsp_buf,
196                                                            list);
197                 list_del(&buf->list);
198                 vfree(buf->buf);
199                 kfree(buf);
200         }
201 }
202
203 #define WM_ADSP_FW_MBC_VSS  0
204 #define WM_ADSP_FW_HIFI     1
205 #define WM_ADSP_FW_TX       2
206 #define WM_ADSP_FW_TX_SPK   3
207 #define WM_ADSP_FW_RX       4
208 #define WM_ADSP_FW_RX_ANC   5
209 #define WM_ADSP_FW_CTRL     6
210 #define WM_ADSP_FW_ASR      7
211 #define WM_ADSP_FW_TRACE    8
212 #define WM_ADSP_FW_SPK_PROT 9
213 #define WM_ADSP_FW_MISC     10
214
215 #define WM_ADSP_NUM_FW      11
216
217 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
218         [WM_ADSP_FW_MBC_VSS] =  "MBC/VSS",
219         [WM_ADSP_FW_HIFI] =     "MasterHiFi",
220         [WM_ADSP_FW_TX] =       "Tx",
221         [WM_ADSP_FW_TX_SPK] =   "Tx Speaker",
222         [WM_ADSP_FW_RX] =       "Rx",
223         [WM_ADSP_FW_RX_ANC] =   "Rx ANC",
224         [WM_ADSP_FW_CTRL] =     "Voice Ctrl",
225         [WM_ADSP_FW_ASR] =      "ASR Assist",
226         [WM_ADSP_FW_TRACE] =    "Dbg Trace",
227         [WM_ADSP_FW_SPK_PROT] = "Protection",
228         [WM_ADSP_FW_MISC] =     "Misc",
229 };
230
231 struct wm_adsp_system_config_xm_hdr {
232         __be32 sys_enable;
233         __be32 fw_id;
234         __be32 fw_rev;
235         __be32 boot_status;
236         __be32 watchdog;
237         __be32 dma_buffer_size;
238         __be32 rdma[6];
239         __be32 wdma[8];
240         __be32 build_job_name[3];
241         __be32 build_job_number;
242 };
243
244 struct wm_adsp_alg_xm_struct {
245         __be32 magic;
246         __be32 smoothing;
247         __be32 threshold;
248         __be32 host_buf_ptr;
249         __be32 start_seq;
250         __be32 high_water_mark;
251         __be32 low_water_mark;
252         __be64 smoothed_power;
253 };
254
255 struct wm_adsp_buffer {
256         __be32 X_buf_base;              /* XM base addr of first X area */
257         __be32 X_buf_size;              /* Size of 1st X area in words */
258         __be32 X_buf_base2;             /* XM base addr of 2nd X area */
259         __be32 X_buf_brk;               /* Total X size in words */
260         __be32 Y_buf_base;              /* YM base addr of Y area */
261         __be32 wrap;                    /* Total size X and Y in words */
262         __be32 high_water_mark;         /* Point at which IRQ is asserted */
263         __be32 irq_count;               /* bits 1-31 count IRQ assertions */
264         __be32 irq_ack;                 /* acked IRQ count, bit 0 enables IRQ */
265         __be32 next_write_index;        /* word index of next write */
266         __be32 next_read_index;         /* word index of next read */
267         __be32 error;                   /* error if any */
268         __be32 oldest_block_index;      /* word index of oldest surviving */
269         __be32 requested_rewind;        /* how many blocks rewind was done */
270         __be32 reserved_space;          /* internal */
271         __be32 min_free;                /* min free space since stream start */
272         __be32 blocks_written[2];       /* total blocks written (64 bit) */
273         __be32 words_written[2];        /* total words written (64 bit) */
274 };
275
276 struct wm_adsp_compr_buf {
277         struct wm_adsp *dsp;
278
279         struct wm_adsp_buffer_region *regions;
280         u32 host_buf_ptr;
281
282         u32 error;
283         u32 irq_count;
284         int read_index;
285         int avail;
286 };
287
288 struct wm_adsp_compr {
289         struct wm_adsp *dsp;
290         struct wm_adsp_compr_buf *buf;
291
292         struct snd_compr_stream *stream;
293         struct snd_compressed_buffer size;
294
295         u32 *raw_buf;
296         unsigned int copied_total;
297
298         unsigned int sample_rate;
299 };
300
301 #define WM_ADSP_DATA_WORD_SIZE         3
302
303 #define WM_ADSP_MIN_FRAGMENTS          1
304 #define WM_ADSP_MAX_FRAGMENTS          256
305 #define WM_ADSP_MIN_FRAGMENT_SIZE      (64 * WM_ADSP_DATA_WORD_SIZE)
306 #define WM_ADSP_MAX_FRAGMENT_SIZE      (4096 * WM_ADSP_DATA_WORD_SIZE)
307
308 #define WM_ADSP_ALG_XM_STRUCT_MAGIC    0x49aec7
309
310 #define HOST_BUFFER_FIELD(field) \
311         (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
312
313 #define ALG_XM_FIELD(field) \
314         (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
315
316 static int wm_adsp_buffer_init(struct wm_adsp *dsp);
317 static int wm_adsp_buffer_free(struct wm_adsp *dsp);
318
319 struct wm_adsp_buffer_region {
320         unsigned int offset;
321         unsigned int cumulative_size;
322         unsigned int mem_type;
323         unsigned int base_addr;
324 };
325
326 struct wm_adsp_buffer_region_def {
327         unsigned int mem_type;
328         unsigned int base_offset;
329         unsigned int size_offset;
330 };
331
332 static const struct wm_adsp_buffer_region_def default_regions[] = {
333         {
334                 .mem_type = WMFW_ADSP2_XM,
335                 .base_offset = HOST_BUFFER_FIELD(X_buf_base),
336                 .size_offset = HOST_BUFFER_FIELD(X_buf_size),
337         },
338         {
339                 .mem_type = WMFW_ADSP2_XM,
340                 .base_offset = HOST_BUFFER_FIELD(X_buf_base2),
341                 .size_offset = HOST_BUFFER_FIELD(X_buf_brk),
342         },
343         {
344                 .mem_type = WMFW_ADSP2_YM,
345                 .base_offset = HOST_BUFFER_FIELD(Y_buf_base),
346                 .size_offset = HOST_BUFFER_FIELD(wrap),
347         },
348 };
349
350 struct wm_adsp_fw_caps {
351         u32 id;
352         struct snd_codec_desc desc;
353         int num_regions;
354         const struct wm_adsp_buffer_region_def *region_defs;
355 };
356
357 static const struct wm_adsp_fw_caps ctrl_caps[] = {
358         {
359                 .id = SND_AUDIOCODEC_BESPOKE,
360                 .desc = {
361                         .max_ch = 1,
362                         .sample_rates = { 16000 },
363                         .num_sample_rates = 1,
364                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
365                 },
366                 .num_regions = ARRAY_SIZE(default_regions),
367                 .region_defs = default_regions,
368         },
369 };
370
371 static const struct wm_adsp_fw_caps trace_caps[] = {
372         {
373                 .id = SND_AUDIOCODEC_BESPOKE,
374                 .desc = {
375                         .max_ch = 8,
376                         .sample_rates = {
377                                 4000, 8000, 11025, 12000, 16000, 22050,
378                                 24000, 32000, 44100, 48000, 64000, 88200,
379                                 96000, 176400, 192000
380                         },
381                         .num_sample_rates = 15,
382                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
383                 },
384                 .num_regions = ARRAY_SIZE(default_regions),
385                 .region_defs = default_regions,
386         },
387 };
388
389 static const struct {
390         const char *file;
391         int compr_direction;
392         int num_caps;
393         const struct wm_adsp_fw_caps *caps;
394 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
395         [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
396         [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
397         [WM_ADSP_FW_TX] =       { .file = "tx" },
398         [WM_ADSP_FW_TX_SPK] =   { .file = "tx-spk" },
399         [WM_ADSP_FW_RX] =       { .file = "rx" },
400         [WM_ADSP_FW_RX_ANC] =   { .file = "rx-anc" },
401         [WM_ADSP_FW_CTRL] =     {
402                 .file = "ctrl",
403                 .compr_direction = SND_COMPRESS_CAPTURE,
404                 .num_caps = ARRAY_SIZE(ctrl_caps),
405                 .caps = ctrl_caps,
406         },
407         [WM_ADSP_FW_ASR] =      { .file = "asr" },
408         [WM_ADSP_FW_TRACE] =    {
409                 .file = "trace",
410                 .compr_direction = SND_COMPRESS_CAPTURE,
411                 .num_caps = ARRAY_SIZE(trace_caps),
412                 .caps = trace_caps,
413         },
414         [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
415         [WM_ADSP_FW_MISC] =     { .file = "misc" },
416 };
417
418 struct wm_coeff_ctl_ops {
419         int (*xget)(struct snd_kcontrol *kcontrol,
420                     struct snd_ctl_elem_value *ucontrol);
421         int (*xput)(struct snd_kcontrol *kcontrol,
422                     struct snd_ctl_elem_value *ucontrol);
423         int (*xinfo)(struct snd_kcontrol *kcontrol,
424                      struct snd_ctl_elem_info *uinfo);
425 };
426
427 struct wm_coeff_ctl {
428         const char *name;
429         const char *fw_name;
430         struct wm_adsp_alg_region alg_region;
431         struct wm_coeff_ctl_ops ops;
432         struct wm_adsp *dsp;
433         unsigned int enabled:1;
434         struct list_head list;
435         void *cache;
436         unsigned int offset;
437         size_t len;
438         unsigned int set:1;
439         struct snd_kcontrol *kcontrol;
440         struct soc_bytes_ext bytes_ext;
441         unsigned int flags;
442 };
443
444 #ifdef CONFIG_DEBUG_FS
445 static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
446 {
447         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
448
449         kfree(dsp->wmfw_file_name);
450         dsp->wmfw_file_name = tmp;
451 }
452
453 static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
454 {
455         char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
456
457         kfree(dsp->bin_file_name);
458         dsp->bin_file_name = tmp;
459 }
460
461 static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
462 {
463         kfree(dsp->wmfw_file_name);
464         kfree(dsp->bin_file_name);
465         dsp->wmfw_file_name = NULL;
466         dsp->bin_file_name = NULL;
467 }
468
469 static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
470                                          char __user *user_buf,
471                                          size_t count, loff_t *ppos)
472 {
473         struct wm_adsp *dsp = file->private_data;
474         ssize_t ret;
475
476         mutex_lock(&dsp->pwr_lock);
477
478         if (!dsp->wmfw_file_name || !dsp->running)
479                 ret = 0;
480         else
481                 ret = simple_read_from_buffer(user_buf, count, ppos,
482                                               dsp->wmfw_file_name,
483                                               strlen(dsp->wmfw_file_name));
484
485         mutex_unlock(&dsp->pwr_lock);
486         return ret;
487 }
488
489 static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
490                                         char __user *user_buf,
491                                         size_t count, loff_t *ppos)
492 {
493         struct wm_adsp *dsp = file->private_data;
494         ssize_t ret;
495
496         mutex_lock(&dsp->pwr_lock);
497
498         if (!dsp->bin_file_name || !dsp->running)
499                 ret = 0;
500         else
501                 ret = simple_read_from_buffer(user_buf, count, ppos,
502                                               dsp->bin_file_name,
503                                               strlen(dsp->bin_file_name));
504
505         mutex_unlock(&dsp->pwr_lock);
506         return ret;
507 }
508
509 static const struct {
510         const char *name;
511         const struct file_operations fops;
512 } wm_adsp_debugfs_fops[] = {
513         {
514                 .name = "wmfw_file_name",
515                 .fops = {
516                         .open = simple_open,
517                         .read = wm_adsp_debugfs_wmfw_read,
518                 },
519         },
520         {
521                 .name = "bin_file_name",
522                 .fops = {
523                         .open = simple_open,
524                         .read = wm_adsp_debugfs_bin_read,
525                 },
526         },
527 };
528
529 static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
530                                   struct snd_soc_codec *codec)
531 {
532         struct dentry *root = NULL;
533         char *root_name;
534         int i;
535
536         if (!codec->component.debugfs_root) {
537                 adsp_err(dsp, "No codec debugfs root\n");
538                 goto err;
539         }
540
541         root_name = kmalloc(PAGE_SIZE, GFP_KERNEL);
542         if (!root_name)
543                 goto err;
544
545         snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num);
546         root = debugfs_create_dir(root_name, codec->component.debugfs_root);
547         kfree(root_name);
548
549         if (!root)
550                 goto err;
551
552         if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running))
553                 goto err;
554
555         if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id))
556                 goto err;
557
558         if (!debugfs_create_x32("fw_version", S_IRUGO, root,
559                                 &dsp->fw_id_version))
560                 goto err;
561
562         for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
563                 if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
564                                          S_IRUGO, root, dsp,
565                                          &wm_adsp_debugfs_fops[i].fops))
566                         goto err;
567         }
568
569         dsp->debugfs_root = root;
570         return;
571
572 err:
573         debugfs_remove_recursive(root);
574         adsp_err(dsp, "Failed to create debugfs\n");
575 }
576
577 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
578 {
579         wm_adsp_debugfs_clear(dsp);
580         debugfs_remove_recursive(dsp->debugfs_root);
581 }
582 #else
583 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
584                                          struct snd_soc_codec *codec)
585 {
586 }
587
588 static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
589 {
590 }
591
592 static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp,
593                                                  const char *s)
594 {
595 }
596
597 static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp,
598                                                 const char *s)
599 {
600 }
601
602 static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
603 {
604 }
605 #endif
606
607 static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
608                           struct snd_ctl_elem_value *ucontrol)
609 {
610         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
611         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
612         struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
613
614         ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
615
616         return 0;
617 }
618
619 static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
620                           struct snd_ctl_elem_value *ucontrol)
621 {
622         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
623         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
624         struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
625         int ret = 0;
626
627         if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
628                 return 0;
629
630         if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
631                 return -EINVAL;
632
633         mutex_lock(&dsp[e->shift_l].pwr_lock);
634
635         if (dsp[e->shift_l].running || dsp[e->shift_l].compr)
636                 ret = -EBUSY;
637         else
638                 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
639
640         mutex_unlock(&dsp[e->shift_l].pwr_lock);
641
642         return ret;
643 }
644
645 static const struct soc_enum wm_adsp_fw_enum[] = {
646         SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
647         SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
648         SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
649         SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
650 };
651
652 const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
653         SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
654                      wm_adsp_fw_get, wm_adsp_fw_put),
655         SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
656                      wm_adsp_fw_get, wm_adsp_fw_put),
657         SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
658                      wm_adsp_fw_get, wm_adsp_fw_put),
659         SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
660                      wm_adsp_fw_get, wm_adsp_fw_put),
661 };
662 EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
663
664 static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
665                                                         int type)
666 {
667         int i;
668
669         for (i = 0; i < dsp->num_mems; i++)
670                 if (dsp->mem[i].type == type)
671                         return &dsp->mem[i];
672
673         return NULL;
674 }
675
676 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
677                                           unsigned int offset)
678 {
679         if (WARN_ON(!mem))
680                 return offset;
681         switch (mem->type) {
682         case WMFW_ADSP1_PM:
683                 return mem->base + (offset * 3);
684         case WMFW_ADSP1_DM:
685                 return mem->base + (offset * 2);
686         case WMFW_ADSP2_XM:
687                 return mem->base + (offset * 2);
688         case WMFW_ADSP2_YM:
689                 return mem->base + (offset * 2);
690         case WMFW_ADSP1_ZM:
691                 return mem->base + (offset * 2);
692         default:
693                 WARN(1, "Unknown memory region type");
694                 return offset;
695         }
696 }
697
698 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
699 {
700         u16 scratch[4];
701         int ret;
702
703         ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0,
704                                 scratch, sizeof(scratch));
705         if (ret) {
706                 adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret);
707                 return;
708         }
709
710         adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
711                  be16_to_cpu(scratch[0]),
712                  be16_to_cpu(scratch[1]),
713                  be16_to_cpu(scratch[2]),
714                  be16_to_cpu(scratch[3]));
715 }
716
717 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
718 {
719         return container_of(ext, struct wm_coeff_ctl, bytes_ext);
720 }
721
722 static int wm_coeff_info(struct snd_kcontrol *kctl,
723                          struct snd_ctl_elem_info *uinfo)
724 {
725         struct soc_bytes_ext *bytes_ext =
726                 (struct soc_bytes_ext *)kctl->private_value;
727         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
728
729         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
730         uinfo->count = ctl->len;
731         return 0;
732 }
733
734 static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
735                                   const void *buf, size_t len)
736 {
737         struct wm_adsp_alg_region *alg_region = &ctl->alg_region;
738         const struct wm_adsp_region *mem;
739         struct wm_adsp *dsp = ctl->dsp;
740         void *scratch;
741         int ret;
742         unsigned int reg;
743
744         mem = wm_adsp_find_region(dsp, alg_region->type);
745         if (!mem) {
746                 adsp_err(dsp, "No base for region %x\n",
747                          alg_region->type);
748                 return -EINVAL;
749         }
750
751         reg = ctl->alg_region.base + ctl->offset;
752         reg = wm_adsp_region_to_reg(mem, reg);
753
754         scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
755         if (!scratch)
756                 return -ENOMEM;
757
758         ret = regmap_raw_write(dsp->regmap, reg, scratch,
759                                len);
760         if (ret) {
761                 adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
762                          len, reg, ret);
763                 kfree(scratch);
764                 return ret;
765         }
766         adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
767
768         kfree(scratch);
769
770         return 0;
771 }
772
773 static int wm_coeff_put(struct snd_kcontrol *kctl,
774                         struct snd_ctl_elem_value *ucontrol)
775 {
776         struct soc_bytes_ext *bytes_ext =
777                 (struct soc_bytes_ext *)kctl->private_value;
778         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
779         char *p = ucontrol->value.bytes.data;
780         int ret = 0;
781
782         mutex_lock(&ctl->dsp->pwr_lock);
783
784         memcpy(ctl->cache, p, ctl->len);
785
786         ctl->set = 1;
787         if (ctl->enabled)
788                 ret = wm_coeff_write_control(ctl, p, ctl->len);
789
790         mutex_unlock(&ctl->dsp->pwr_lock);
791
792         return ret;
793 }
794
795 static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
796                             const unsigned int __user *bytes, unsigned int size)
797 {
798         struct soc_bytes_ext *bytes_ext =
799                 (struct soc_bytes_ext *)kctl->private_value;
800         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
801         int ret = 0;
802
803         mutex_lock(&ctl->dsp->pwr_lock);
804
805         if (copy_from_user(ctl->cache, bytes, size)) {
806                 ret = -EFAULT;
807         } else {
808                 ctl->set = 1;
809                 if (ctl->enabled)
810                         ret = wm_coeff_write_control(ctl, ctl->cache, size);
811         }
812
813         mutex_unlock(&ctl->dsp->pwr_lock);
814
815         return ret;
816 }
817
818 static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
819                                  void *buf, size_t len)
820 {
821         struct wm_adsp_alg_region *alg_region = &ctl->alg_region;
822         const struct wm_adsp_region *mem;
823         struct wm_adsp *dsp = ctl->dsp;
824         void *scratch;
825         int ret;
826         unsigned int reg;
827
828         mem = wm_adsp_find_region(dsp, alg_region->type);
829         if (!mem) {
830                 adsp_err(dsp, "No base for region %x\n",
831                          alg_region->type);
832                 return -EINVAL;
833         }
834
835         reg = ctl->alg_region.base + ctl->offset;
836         reg = wm_adsp_region_to_reg(mem, reg);
837
838         scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
839         if (!scratch)
840                 return -ENOMEM;
841
842         ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
843         if (ret) {
844                 adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
845                          len, reg, ret);
846                 kfree(scratch);
847                 return ret;
848         }
849         adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
850
851         memcpy(buf, scratch, len);
852         kfree(scratch);
853
854         return 0;
855 }
856
857 static int wm_coeff_get(struct snd_kcontrol *kctl,
858                         struct snd_ctl_elem_value *ucontrol)
859 {
860         struct soc_bytes_ext *bytes_ext =
861                 (struct soc_bytes_ext *)kctl->private_value;
862         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
863         char *p = ucontrol->value.bytes.data;
864         int ret = 0;
865
866         mutex_lock(&ctl->dsp->pwr_lock);
867
868         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
869                 if (ctl->enabled)
870                         ret = wm_coeff_read_control(ctl, p, ctl->len);
871                 else
872                         ret = -EPERM;
873         } else {
874                 if (!ctl->flags && ctl->enabled)
875                         ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
876
877                 memcpy(p, ctl->cache, ctl->len);
878         }
879
880         mutex_unlock(&ctl->dsp->pwr_lock);
881
882         return ret;
883 }
884
885 static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
886                             unsigned int __user *bytes, unsigned int size)
887 {
888         struct soc_bytes_ext *bytes_ext =
889                 (struct soc_bytes_ext *)kctl->private_value;
890         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
891         int ret = 0;
892
893         mutex_lock(&ctl->dsp->pwr_lock);
894
895         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
896                 if (ctl->enabled)
897                         ret = wm_coeff_read_control(ctl, ctl->cache, size);
898                 else
899                         ret = -EPERM;
900         } else {
901                 if (!ctl->flags && ctl->enabled)
902                         ret = wm_coeff_read_control(ctl, ctl->cache, size);
903         }
904
905         if (!ret && copy_to_user(bytes, ctl->cache, size))
906                 ret = -EFAULT;
907
908         mutex_unlock(&ctl->dsp->pwr_lock);
909
910         return ret;
911 }
912
913 struct wmfw_ctl_work {
914         struct wm_adsp *dsp;
915         struct wm_coeff_ctl *ctl;
916         struct work_struct work;
917 };
918
919 static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
920 {
921         unsigned int out, rd, wr, vol;
922
923         if (len > ADSP_MAX_STD_CTRL_SIZE) {
924                 rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
925                 wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
926                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
927
928                 out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
929         } else {
930                 rd = SNDRV_CTL_ELEM_ACCESS_READ;
931                 wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
932                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
933
934                 out = 0;
935         }
936
937         if (in) {
938                 if (in & WMFW_CTL_FLAG_READABLE)
939                         out |= rd;
940                 if (in & WMFW_CTL_FLAG_WRITEABLE)
941                         out |= wr;
942                 if (in & WMFW_CTL_FLAG_VOLATILE)
943                         out |= vol;
944         } else {
945                 out |= rd | wr | vol;
946         }
947
948         return out;
949 }
950
951 static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
952 {
953         struct snd_kcontrol_new *kcontrol;
954         int ret;
955
956         if (!ctl || !ctl->name)
957                 return -EINVAL;
958
959         kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
960         if (!kcontrol)
961                 return -ENOMEM;
962         kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
963
964         kcontrol->name = ctl->name;
965         kcontrol->info = wm_coeff_info;
966         kcontrol->get = wm_coeff_get;
967         kcontrol->put = wm_coeff_put;
968         kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
969         kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
970         kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
971
972         ctl->bytes_ext.max = ctl->len;
973         ctl->bytes_ext.get = wm_coeff_tlv_get;
974         ctl->bytes_ext.put = wm_coeff_tlv_put;
975
976         kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len);
977
978         ret = snd_soc_add_card_controls(dsp->card, kcontrol, 1);
979         if (ret < 0)
980                 goto err_kcontrol;
981
982         kfree(kcontrol);
983
984         ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card, ctl->name);
985
986         return 0;
987
988 err_kcontrol:
989         kfree(kcontrol);
990         return ret;
991 }
992
993 static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
994 {
995         struct wm_coeff_ctl *ctl;
996         int ret;
997
998         list_for_each_entry(ctl, &dsp->ctl_list, list) {
999                 if (!ctl->enabled || ctl->set)
1000                         continue;
1001                 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1002                         continue;
1003
1004                 ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1005                 if (ret < 0)
1006                         return ret;
1007         }
1008
1009         return 0;
1010 }
1011
1012 static int wm_coeff_sync_controls(struct wm_adsp *dsp)
1013 {
1014         struct wm_coeff_ctl *ctl;
1015         int ret;
1016
1017         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1018                 if (!ctl->enabled)
1019                         continue;
1020                 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
1021                         ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
1022                         if (ret < 0)
1023                                 return ret;
1024                 }
1025         }
1026
1027         return 0;
1028 }
1029
1030 static void wm_adsp_ctl_work(struct work_struct *work)
1031 {
1032         struct wmfw_ctl_work *ctl_work = container_of(work,
1033                                                       struct wmfw_ctl_work,
1034                                                       work);
1035
1036         wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl);
1037         kfree(ctl_work);
1038 }
1039
1040 static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl)
1041 {
1042         kfree(ctl->cache);
1043         kfree(ctl->name);
1044         kfree(ctl);
1045 }
1046
1047 static int wm_adsp_create_control(struct wm_adsp *dsp,
1048                                   const struct wm_adsp_alg_region *alg_region,
1049                                   unsigned int offset, unsigned int len,
1050                                   const char *subname, unsigned int subname_len,
1051                                   unsigned int flags)
1052 {
1053         struct wm_coeff_ctl *ctl;
1054         struct wmfw_ctl_work *ctl_work;
1055         char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1056         char *region_name;
1057         int ret;
1058
1059         if (flags & WMFW_CTL_FLAG_SYS)
1060                 return 0;
1061
1062         switch (alg_region->type) {
1063         case WMFW_ADSP1_PM:
1064                 region_name = "PM";
1065                 break;
1066         case WMFW_ADSP1_DM:
1067                 region_name = "DM";
1068                 break;
1069         case WMFW_ADSP2_XM:
1070                 region_name = "XM";
1071                 break;
1072         case WMFW_ADSP2_YM:
1073                 region_name = "YM";
1074                 break;
1075         case WMFW_ADSP1_ZM:
1076                 region_name = "ZM";
1077                 break;
1078         default:
1079                 adsp_err(dsp, "Unknown region type: %d\n", alg_region->type);
1080                 return -EINVAL;
1081         }
1082
1083         switch (dsp->fw_ver) {
1084         case 0:
1085         case 1:
1086                 snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x",
1087                          dsp->num, region_name, alg_region->alg);
1088                 break;
1089         default:
1090                 ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1091                                 "DSP%d%c %.12s %x", dsp->num, *region_name,
1092                                 wm_adsp_fw_text[dsp->fw], alg_region->alg);
1093
1094                 /* Truncate the subname from the start if it is too long */
1095                 if (subname) {
1096                         int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
1097                         int skip = 0;
1098
1099                         if (subname_len > avail)
1100                                 skip = subname_len - avail;
1101
1102                         snprintf(name + ret,
1103                                  SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s",
1104                                  subname_len - skip, subname + skip);
1105                 }
1106                 break;
1107         }
1108
1109         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1110                 if (!strcmp(ctl->name, name)) {
1111                         if (!ctl->enabled)
1112                                 ctl->enabled = 1;
1113                         return 0;
1114                 }
1115         }
1116
1117         ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
1118         if (!ctl)
1119                 return -ENOMEM;
1120         ctl->fw_name = wm_adsp_fw_text[dsp->fw];
1121         ctl->alg_region = *alg_region;
1122         ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
1123         if (!ctl->name) {
1124                 ret = -ENOMEM;
1125                 goto err_ctl;
1126         }
1127         ctl->enabled = 1;
1128         ctl->set = 0;
1129         ctl->ops.xget = wm_coeff_get;
1130         ctl->ops.xput = wm_coeff_put;
1131         ctl->dsp = dsp;
1132
1133         ctl->flags = flags;
1134         ctl->offset = offset;
1135         ctl->len = len;
1136         ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
1137         if (!ctl->cache) {
1138                 ret = -ENOMEM;
1139                 goto err_ctl_name;
1140         }
1141
1142         list_add(&ctl->list, &dsp->ctl_list);
1143
1144         ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
1145         if (!ctl_work) {
1146                 ret = -ENOMEM;
1147                 goto err_ctl_cache;
1148         }
1149
1150         ctl_work->dsp = dsp;
1151         ctl_work->ctl = ctl;
1152         INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
1153         schedule_work(&ctl_work->work);
1154
1155         return 0;
1156
1157 err_ctl_cache:
1158         kfree(ctl->cache);
1159 err_ctl_name:
1160         kfree(ctl->name);
1161 err_ctl:
1162         kfree(ctl);
1163
1164         return ret;
1165 }
1166
1167 struct wm_coeff_parsed_alg {
1168         int id;
1169         const u8 *name;
1170         int name_len;
1171         int ncoeff;
1172 };
1173
1174 struct wm_coeff_parsed_coeff {
1175         int offset;
1176         int mem_type;
1177         const u8 *name;
1178         int name_len;
1179         int ctl_type;
1180         int flags;
1181         int len;
1182 };
1183
1184 static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1185 {
1186         int length;
1187
1188         switch (bytes) {
1189         case 1:
1190                 length = **pos;
1191                 break;
1192         case 2:
1193                 length = le16_to_cpu(*((__le16 *)*pos));
1194                 break;
1195         default:
1196                 return 0;
1197         }
1198
1199         if (str)
1200                 *str = *pos + bytes;
1201
1202         *pos += ((length + bytes) + 3) & ~0x03;
1203
1204         return length;
1205 }
1206
1207 static int wm_coeff_parse_int(int bytes, const u8 **pos)
1208 {
1209         int val = 0;
1210
1211         switch (bytes) {
1212         case 2:
1213                 val = le16_to_cpu(*((__le16 *)*pos));
1214                 break;
1215         case 4:
1216                 val = le32_to_cpu(*((__le32 *)*pos));
1217                 break;
1218         default:
1219                 break;
1220         }
1221
1222         *pos += bytes;
1223
1224         return val;
1225 }
1226
1227 static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data,
1228                                       struct wm_coeff_parsed_alg *blk)
1229 {
1230         const struct wmfw_adsp_alg_data *raw;
1231
1232         switch (dsp->fw_ver) {
1233         case 0:
1234         case 1:
1235                 raw = (const struct wmfw_adsp_alg_data *)*data;
1236                 *data = raw->data;
1237
1238                 blk->id = le32_to_cpu(raw->id);
1239                 blk->name = raw->name;
1240                 blk->name_len = strlen(raw->name);
1241                 blk->ncoeff = le32_to_cpu(raw->ncoeff);
1242                 break;
1243         default:
1244                 blk->id = wm_coeff_parse_int(sizeof(raw->id), data);
1245                 blk->name_len = wm_coeff_parse_string(sizeof(u8), data,
1246                                                       &blk->name);
1247                 wm_coeff_parse_string(sizeof(u16), data, NULL);
1248                 blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data);
1249                 break;
1250         }
1251
1252         adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
1253         adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
1254         adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1255 }
1256
1257 static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
1258                                         struct wm_coeff_parsed_coeff *blk)
1259 {
1260         const struct wmfw_adsp_coeff_data *raw;
1261         const u8 *tmp;
1262         int length;
1263
1264         switch (dsp->fw_ver) {
1265         case 0:
1266         case 1:
1267                 raw = (const struct wmfw_adsp_coeff_data *)*data;
1268                 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
1269
1270                 blk->offset = le16_to_cpu(raw->hdr.offset);
1271                 blk->mem_type = le16_to_cpu(raw->hdr.type);
1272                 blk->name = raw->name;
1273                 blk->name_len = strlen(raw->name);
1274                 blk->ctl_type = le16_to_cpu(raw->ctl_type);
1275                 blk->flags = le16_to_cpu(raw->flags);
1276                 blk->len = le32_to_cpu(raw->len);
1277                 break;
1278         default:
1279                 tmp = *data;
1280                 blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
1281                 blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
1282                 length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
1283                 blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp,
1284                                                       &blk->name);
1285                 wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
1286                 wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
1287                 blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
1288                 blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
1289                 blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
1290
1291                 *data = *data + sizeof(raw->hdr) + length;
1292                 break;
1293         }
1294
1295         adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
1296         adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
1297         adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name);
1298         adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
1299         adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
1300         adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1301 }
1302
1303 static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
1304                                const struct wmfw_region *region)
1305 {
1306         struct wm_adsp_alg_region alg_region = {};
1307         struct wm_coeff_parsed_alg alg_blk;
1308         struct wm_coeff_parsed_coeff coeff_blk;
1309         const u8 *data = region->data;
1310         int i, ret;
1311
1312         wm_coeff_parse_alg(dsp, &data, &alg_blk);
1313         for (i = 0; i < alg_blk.ncoeff; i++) {
1314                 wm_coeff_parse_coeff(dsp, &data, &coeff_blk);
1315
1316                 switch (coeff_blk.ctl_type) {
1317                 case SNDRV_CTL_ELEM_TYPE_BYTES:
1318                         break;
1319                 default:
1320                         adsp_err(dsp, "Unknown control type: %d\n",
1321                                  coeff_blk.ctl_type);
1322                         return -EINVAL;
1323                 }
1324
1325                 alg_region.type = coeff_blk.mem_type;
1326                 alg_region.alg = alg_blk.id;
1327
1328                 ret = wm_adsp_create_control(dsp, &alg_region,
1329                                              coeff_blk.offset,
1330                                              coeff_blk.len,
1331                                              coeff_blk.name,
1332                                              coeff_blk.name_len,
1333                                              coeff_blk.flags);
1334                 if (ret < 0)
1335                         adsp_err(dsp, "Failed to create control: %.*s, %d\n",
1336                                  coeff_blk.name_len, coeff_blk.name, ret);
1337         }
1338
1339         return 0;
1340 }
1341
1342 static int wm_adsp_load(struct wm_adsp *dsp)
1343 {
1344         LIST_HEAD(buf_list);
1345         const struct firmware *firmware;
1346         struct regmap *regmap = dsp->regmap;
1347         unsigned int pos = 0;
1348         const struct wmfw_header *header;
1349         const struct wmfw_adsp1_sizes *adsp1_sizes;
1350         const struct wmfw_adsp2_sizes *adsp2_sizes;
1351         const struct wmfw_footer *footer;
1352         const struct wmfw_region *region;
1353         const struct wm_adsp_region *mem;
1354         const char *region_name;
1355         char *file, *text;
1356         struct wm_adsp_buf *buf;
1357         unsigned int reg;
1358         int regions = 0;
1359         int ret, offset, type, sizes;
1360
1361         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1362         if (file == NULL)
1363                 return -ENOMEM;
1364
1365         snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
1366                  wm_adsp_fw[dsp->fw].file);
1367         file[PAGE_SIZE - 1] = '\0';
1368
1369         ret = request_firmware(&firmware, file, dsp->dev);
1370         if (ret != 0) {
1371                 adsp_err(dsp, "Failed to request '%s'\n", file);
1372                 goto out;
1373         }
1374         ret = -EINVAL;
1375
1376         pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1377         if (pos >= firmware->size) {
1378                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
1379                          file, firmware->size);
1380                 goto out_fw;
1381         }
1382
1383         header = (void *)&firmware->data[0];
1384
1385         if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
1386                 adsp_err(dsp, "%s: invalid magic\n", file);
1387                 goto out_fw;
1388         }
1389
1390         switch (header->ver) {
1391         case 0:
1392                 adsp_warn(dsp, "%s: Depreciated file format %d\n",
1393                           file, header->ver);
1394                 break;
1395         case 1:
1396         case 2:
1397                 break;
1398         default:
1399                 adsp_err(dsp, "%s: unknown file format %d\n",
1400                          file, header->ver);
1401                 goto out_fw;
1402         }
1403
1404         adsp_info(dsp, "Firmware version: %d\n", header->ver);
1405         dsp->fw_ver = header->ver;
1406
1407         if (header->core != dsp->type) {
1408                 adsp_err(dsp, "%s: invalid core %d != %d\n",
1409                          file, header->core, dsp->type);
1410                 goto out_fw;
1411         }
1412
1413         switch (dsp->type) {
1414         case WMFW_ADSP1:
1415                 pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1416                 adsp1_sizes = (void *)&(header[1]);
1417                 footer = (void *)&(adsp1_sizes[1]);
1418                 sizes = sizeof(*adsp1_sizes);
1419
1420                 adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
1421                          file, le32_to_cpu(adsp1_sizes->dm),
1422                          le32_to_cpu(adsp1_sizes->pm),
1423                          le32_to_cpu(adsp1_sizes->zm));
1424                 break;
1425
1426         case WMFW_ADSP2:
1427                 pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
1428                 adsp2_sizes = (void *)&(header[1]);
1429                 footer = (void *)&(adsp2_sizes[1]);
1430                 sizes = sizeof(*adsp2_sizes);
1431
1432                 adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
1433                          file, le32_to_cpu(adsp2_sizes->xm),
1434                          le32_to_cpu(adsp2_sizes->ym),
1435                          le32_to_cpu(adsp2_sizes->pm),
1436                          le32_to_cpu(adsp2_sizes->zm));
1437                 break;
1438
1439         default:
1440                 WARN(1, "Unknown DSP type");
1441                 goto out_fw;
1442         }
1443
1444         if (le32_to_cpu(header->len) != sizeof(*header) +
1445             sizes + sizeof(*footer)) {
1446                 adsp_err(dsp, "%s: unexpected header length %d\n",
1447                          file, le32_to_cpu(header->len));
1448                 goto out_fw;
1449         }
1450
1451         adsp_dbg(dsp, "%s: timestamp %llu\n", file,
1452                  le64_to_cpu(footer->timestamp));
1453
1454         while (pos < firmware->size &&
1455                pos - firmware->size > sizeof(*region)) {
1456                 region = (void *)&(firmware->data[pos]);
1457                 region_name = "Unknown";
1458                 reg = 0;
1459                 text = NULL;
1460                 offset = le32_to_cpu(region->offset) & 0xffffff;
1461                 type = be32_to_cpu(region->type) & 0xff;
1462                 mem = wm_adsp_find_region(dsp, type);
1463
1464                 switch (type) {
1465                 case WMFW_NAME_TEXT:
1466                         region_name = "Firmware name";
1467                         text = kzalloc(le32_to_cpu(region->len) + 1,
1468                                        GFP_KERNEL);
1469                         break;
1470                 case WMFW_ALGORITHM_DATA:
1471                         region_name = "Algorithm";
1472                         ret = wm_adsp_parse_coeff(dsp, region);
1473                         if (ret != 0)
1474                                 goto out_fw;
1475                         break;
1476                 case WMFW_INFO_TEXT:
1477                         region_name = "Information";
1478                         text = kzalloc(le32_to_cpu(region->len) + 1,
1479                                        GFP_KERNEL);
1480                         break;
1481                 case WMFW_ABSOLUTE:
1482                         region_name = "Absolute";
1483                         reg = offset;
1484                         break;
1485                 case WMFW_ADSP1_PM:
1486                         region_name = "PM";
1487                         reg = wm_adsp_region_to_reg(mem, offset);
1488                         break;
1489                 case WMFW_ADSP1_DM:
1490                         region_name = "DM";
1491                         reg = wm_adsp_region_to_reg(mem, offset);
1492                         break;
1493                 case WMFW_ADSP2_XM:
1494                         region_name = "XM";
1495                         reg = wm_adsp_region_to_reg(mem, offset);
1496                         break;
1497                 case WMFW_ADSP2_YM:
1498                         region_name = "YM";
1499                         reg = wm_adsp_region_to_reg(mem, offset);
1500                         break;
1501                 case WMFW_ADSP1_ZM:
1502                         region_name = "ZM";
1503                         reg = wm_adsp_region_to_reg(mem, offset);
1504                         break;
1505                 default:
1506                         adsp_warn(dsp,
1507                                   "%s.%d: Unknown region type %x at %d(%x)\n",
1508                                   file, regions, type, pos, pos);
1509                         break;
1510                 }
1511
1512                 adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
1513                          regions, le32_to_cpu(region->len), offset,
1514                          region_name);
1515
1516                 if (text) {
1517                         memcpy(text, region->data, le32_to_cpu(region->len));
1518                         adsp_info(dsp, "%s: %s\n", file, text);
1519                         kfree(text);
1520                 }
1521
1522                 if (reg) {
1523                         buf = wm_adsp_buf_alloc(region->data,
1524                                                 le32_to_cpu(region->len),
1525                                                 &buf_list);
1526                         if (!buf) {
1527                                 adsp_err(dsp, "Out of memory\n");
1528                                 ret = -ENOMEM;
1529                                 goto out_fw;
1530                         }
1531
1532                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
1533                                                      le32_to_cpu(region->len));
1534                         if (ret != 0) {
1535                                 adsp_err(dsp,
1536                                         "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
1537                                         file, regions,
1538                                         le32_to_cpu(region->len), offset,
1539                                         region_name, ret);
1540                                 goto out_fw;
1541                         }
1542                 }
1543
1544                 pos += le32_to_cpu(region->len) + sizeof(*region);
1545                 regions++;
1546         }
1547
1548         ret = regmap_async_complete(regmap);
1549         if (ret != 0) {
1550                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
1551                 goto out_fw;
1552         }
1553
1554         if (pos > firmware->size)
1555                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1556                           file, regions, pos - firmware->size);
1557
1558         wm_adsp_debugfs_save_wmfwname(dsp, file);
1559
1560 out_fw:
1561         regmap_async_complete(regmap);
1562         wm_adsp_buf_free(&buf_list);
1563         release_firmware(firmware);
1564 out:
1565         kfree(file);
1566
1567         return ret;
1568 }
1569
1570 static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp,
1571                                   const struct wm_adsp_alg_region *alg_region)
1572 {
1573         struct wm_coeff_ctl *ctl;
1574
1575         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1576                 if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] &&
1577                     alg_region->alg == ctl->alg_region.alg &&
1578                     alg_region->type == ctl->alg_region.type) {
1579                         ctl->alg_region.base = alg_region->base;
1580                 }
1581         }
1582 }
1583
1584 static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
1585                                unsigned int pos, unsigned int len)
1586 {
1587         void *alg;
1588         int ret;
1589         __be32 val;
1590
1591         if (n_algs == 0) {
1592                 adsp_err(dsp, "No algorithms\n");
1593                 return ERR_PTR(-EINVAL);
1594         }
1595
1596         if (n_algs > 1024) {
1597                 adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs);
1598                 return ERR_PTR(-EINVAL);
1599         }
1600
1601         /* Read the terminator first to validate the length */
1602         ret = regmap_raw_read(dsp->regmap, pos + len, &val, sizeof(val));
1603         if (ret != 0) {
1604                 adsp_err(dsp, "Failed to read algorithm list end: %d\n",
1605                         ret);
1606                 return ERR_PTR(ret);
1607         }
1608
1609         if (be32_to_cpu(val) != 0xbedead)
1610                 adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
1611                           pos + len, be32_to_cpu(val));
1612
1613         alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA);
1614         if (!alg)
1615                 return ERR_PTR(-ENOMEM);
1616
1617         ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2);
1618         if (ret != 0) {
1619                 adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
1620                 kfree(alg);
1621                 return ERR_PTR(ret);
1622         }
1623
1624         return alg;
1625 }
1626
1627 static struct wm_adsp_alg_region *
1628         wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id)
1629 {
1630         struct wm_adsp_alg_region *alg_region;
1631
1632         list_for_each_entry(alg_region, &dsp->alg_regions, list) {
1633                 if (id == alg_region->alg && type == alg_region->type)
1634                         return alg_region;
1635         }
1636
1637         return NULL;
1638 }
1639
1640 static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp,
1641                                                         int type, __be32 id,
1642                                                         __be32 base)
1643 {
1644         struct wm_adsp_alg_region *alg_region;
1645
1646         alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL);
1647         if (!alg_region)
1648                 return ERR_PTR(-ENOMEM);
1649
1650         alg_region->type = type;
1651         alg_region->alg = be32_to_cpu(id);
1652         alg_region->base = be32_to_cpu(base);
1653
1654         list_add_tail(&alg_region->list, &dsp->alg_regions);
1655
1656         if (dsp->fw_ver > 0)
1657                 wm_adsp_ctl_fixup_base(dsp, alg_region);
1658
1659         return alg_region;
1660 }
1661
1662 static void wm_adsp_free_alg_regions(struct wm_adsp *dsp)
1663 {
1664         struct wm_adsp_alg_region *alg_region;
1665
1666         while (!list_empty(&dsp->alg_regions)) {
1667                 alg_region = list_first_entry(&dsp->alg_regions,
1668                                               struct wm_adsp_alg_region,
1669                                               list);
1670                 list_del(&alg_region->list);
1671                 kfree(alg_region);
1672         }
1673 }
1674
1675 static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
1676 {
1677         struct wmfw_adsp1_id_hdr adsp1_id;
1678         struct wmfw_adsp1_alg_hdr *adsp1_alg;
1679         struct wm_adsp_alg_region *alg_region;
1680         const struct wm_adsp_region *mem;
1681         unsigned int pos, len;
1682         size_t n_algs;
1683         int i, ret;
1684
1685         mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
1686         if (WARN_ON(!mem))
1687                 return -EINVAL;
1688
1689         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id,
1690                               sizeof(adsp1_id));
1691         if (ret != 0) {
1692                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
1693                          ret);
1694                 return ret;
1695         }
1696
1697         n_algs = be32_to_cpu(adsp1_id.n_algs);
1698         dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
1699         adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
1700                   dsp->fw_id,
1701                   (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
1702                   (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
1703                   be32_to_cpu(adsp1_id.fw.ver) & 0xff,
1704                   n_algs);
1705
1706         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
1707                                            adsp1_id.fw.id, adsp1_id.zm);
1708         if (IS_ERR(alg_region))
1709                 return PTR_ERR(alg_region);
1710
1711         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
1712                                            adsp1_id.fw.id, adsp1_id.dm);
1713         if (IS_ERR(alg_region))
1714                 return PTR_ERR(alg_region);
1715
1716         pos = sizeof(adsp1_id) / 2;
1717         len = (sizeof(*adsp1_alg) * n_algs) / 2;
1718
1719         adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len);
1720         if (IS_ERR(adsp1_alg))
1721                 return PTR_ERR(adsp1_alg);
1722
1723         for (i = 0; i < n_algs; i++) {
1724                 adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
1725                           i, be32_to_cpu(adsp1_alg[i].alg.id),
1726                           (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
1727                           (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
1728                           be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
1729                           be32_to_cpu(adsp1_alg[i].dm),
1730                           be32_to_cpu(adsp1_alg[i].zm));
1731
1732                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
1733                                                    adsp1_alg[i].alg.id,
1734                                                    adsp1_alg[i].dm);
1735                 if (IS_ERR(alg_region)) {
1736                         ret = PTR_ERR(alg_region);
1737                         goto out;
1738                 }
1739                 if (dsp->fw_ver == 0) {
1740                         if (i + 1 < n_algs) {
1741                                 len = be32_to_cpu(adsp1_alg[i + 1].dm);
1742                                 len -= be32_to_cpu(adsp1_alg[i].dm);
1743                                 len *= 4;
1744                                 wm_adsp_create_control(dsp, alg_region, 0,
1745                                                        len, NULL, 0, 0);
1746                         } else {
1747                                 adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1748                                           be32_to_cpu(adsp1_alg[i].alg.id));
1749                         }
1750                 }
1751
1752                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
1753                                                    adsp1_alg[i].alg.id,
1754                                                    adsp1_alg[i].zm);
1755                 if (IS_ERR(alg_region)) {
1756                         ret = PTR_ERR(alg_region);
1757                         goto out;
1758                 }
1759                 if (dsp->fw_ver == 0) {
1760                         if (i + 1 < n_algs) {
1761                                 len = be32_to_cpu(adsp1_alg[i + 1].zm);
1762                                 len -= be32_to_cpu(adsp1_alg[i].zm);
1763                                 len *= 4;
1764                                 wm_adsp_create_control(dsp, alg_region, 0,
1765                                                        len, NULL, 0, 0);
1766                         } else {
1767                                 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1768                                           be32_to_cpu(adsp1_alg[i].alg.id));
1769                         }
1770                 }
1771         }
1772
1773 out:
1774         kfree(adsp1_alg);
1775         return ret;
1776 }
1777
1778 static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
1779 {
1780         struct wmfw_adsp2_id_hdr adsp2_id;
1781         struct wmfw_adsp2_alg_hdr *adsp2_alg;
1782         struct wm_adsp_alg_region *alg_region;
1783         const struct wm_adsp_region *mem;
1784         unsigned int pos, len;
1785         size_t n_algs;
1786         int i, ret;
1787
1788         mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
1789         if (WARN_ON(!mem))
1790                 return -EINVAL;
1791
1792         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id,
1793                               sizeof(adsp2_id));
1794         if (ret != 0) {
1795                 adsp_err(dsp, "Failed to read algorithm info: %d\n",
1796                          ret);
1797                 return ret;
1798         }
1799
1800         n_algs = be32_to_cpu(adsp2_id.n_algs);
1801         dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
1802         dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver);
1803         adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
1804                   dsp->fw_id,
1805                   (dsp->fw_id_version & 0xff0000) >> 16,
1806                   (dsp->fw_id_version & 0xff00) >> 8,
1807                   dsp->fw_id_version & 0xff,
1808                   n_algs);
1809
1810         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
1811                                            adsp2_id.fw.id, adsp2_id.xm);
1812         if (IS_ERR(alg_region))
1813                 return PTR_ERR(alg_region);
1814
1815         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
1816                                            adsp2_id.fw.id, adsp2_id.ym);
1817         if (IS_ERR(alg_region))
1818                 return PTR_ERR(alg_region);
1819
1820         alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
1821                                            adsp2_id.fw.id, adsp2_id.zm);
1822         if (IS_ERR(alg_region))
1823                 return PTR_ERR(alg_region);
1824
1825         pos = sizeof(adsp2_id) / 2;
1826         len = (sizeof(*adsp2_alg) * n_algs) / 2;
1827
1828         adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len);
1829         if (IS_ERR(adsp2_alg))
1830                 return PTR_ERR(adsp2_alg);
1831
1832         for (i = 0; i < n_algs; i++) {
1833                 adsp_info(dsp,
1834                           "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
1835                           i, be32_to_cpu(adsp2_alg[i].alg.id),
1836                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
1837                           (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
1838                           be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
1839                           be32_to_cpu(adsp2_alg[i].xm),
1840                           be32_to_cpu(adsp2_alg[i].ym),
1841                           be32_to_cpu(adsp2_alg[i].zm));
1842
1843                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
1844                                                    adsp2_alg[i].alg.id,
1845                                                    adsp2_alg[i].xm);
1846                 if (IS_ERR(alg_region)) {
1847                         ret = PTR_ERR(alg_region);
1848                         goto out;
1849                 }
1850                 if (dsp->fw_ver == 0) {
1851                         if (i + 1 < n_algs) {
1852                                 len = be32_to_cpu(adsp2_alg[i + 1].xm);
1853                                 len -= be32_to_cpu(adsp2_alg[i].xm);
1854                                 len *= 4;
1855                                 wm_adsp_create_control(dsp, alg_region, 0,
1856                                                        len, NULL, 0, 0);
1857                         } else {
1858                                 adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1859                                           be32_to_cpu(adsp2_alg[i].alg.id));
1860                         }
1861                 }
1862
1863                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
1864                                                    adsp2_alg[i].alg.id,
1865                                                    adsp2_alg[i].ym);
1866                 if (IS_ERR(alg_region)) {
1867                         ret = PTR_ERR(alg_region);
1868                         goto out;
1869                 }
1870                 if (dsp->fw_ver == 0) {
1871                         if (i + 1 < n_algs) {
1872                                 len = be32_to_cpu(adsp2_alg[i + 1].ym);
1873                                 len -= be32_to_cpu(adsp2_alg[i].ym);
1874                                 len *= 4;
1875                                 wm_adsp_create_control(dsp, alg_region, 0,
1876                                                        len, NULL, 0, 0);
1877                         } else {
1878                                 adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1879                                           be32_to_cpu(adsp2_alg[i].alg.id));
1880                         }
1881                 }
1882
1883                 alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
1884                                                    adsp2_alg[i].alg.id,
1885                                                    adsp2_alg[i].zm);
1886                 if (IS_ERR(alg_region)) {
1887                         ret = PTR_ERR(alg_region);
1888                         goto out;
1889                 }
1890                 if (dsp->fw_ver == 0) {
1891                         if (i + 1 < n_algs) {
1892                                 len = be32_to_cpu(adsp2_alg[i + 1].zm);
1893                                 len -= be32_to_cpu(adsp2_alg[i].zm);
1894                                 len *= 4;
1895                                 wm_adsp_create_control(dsp, alg_region, 0,
1896                                                        len, NULL, 0, 0);
1897                         } else {
1898                                 adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1899                                           be32_to_cpu(adsp2_alg[i].alg.id));
1900                         }
1901                 }
1902         }
1903
1904 out:
1905         kfree(adsp2_alg);
1906         return ret;
1907 }
1908
1909 static int wm_adsp_load_coeff(struct wm_adsp *dsp)
1910 {
1911         LIST_HEAD(buf_list);
1912         struct regmap *regmap = dsp->regmap;
1913         struct wmfw_coeff_hdr *hdr;
1914         struct wmfw_coeff_item *blk;
1915         const struct firmware *firmware;
1916         const struct wm_adsp_region *mem;
1917         struct wm_adsp_alg_region *alg_region;
1918         const char *region_name;
1919         int ret, pos, blocks, type, offset, reg;
1920         char *file;
1921         struct wm_adsp_buf *buf;
1922
1923         file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1924         if (file == NULL)
1925                 return -ENOMEM;
1926
1927         snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
1928                  wm_adsp_fw[dsp->fw].file);
1929         file[PAGE_SIZE - 1] = '\0';
1930
1931         ret = request_firmware(&firmware, file, dsp->dev);
1932         if (ret != 0) {
1933                 adsp_warn(dsp, "Failed to request '%s'\n", file);
1934                 ret = 0;
1935                 goto out;
1936         }
1937         ret = -EINVAL;
1938
1939         if (sizeof(*hdr) >= firmware->size) {
1940                 adsp_err(dsp, "%s: file too short, %zu bytes\n",
1941                         file, firmware->size);
1942                 goto out_fw;
1943         }
1944
1945         hdr = (void *)&firmware->data[0];
1946         if (memcmp(hdr->magic, "WMDR", 4) != 0) {
1947                 adsp_err(dsp, "%s: invalid magic\n", file);
1948                 goto out_fw;
1949         }
1950
1951         switch (be32_to_cpu(hdr->rev) & 0xff) {
1952         case 1:
1953                 break;
1954         default:
1955                 adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
1956                          file, be32_to_cpu(hdr->rev) & 0xff);
1957                 ret = -EINVAL;
1958                 goto out_fw;
1959         }
1960
1961         adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
1962                 (le32_to_cpu(hdr->ver) >> 16) & 0xff,
1963                 (le32_to_cpu(hdr->ver) >>  8) & 0xff,
1964                 le32_to_cpu(hdr->ver) & 0xff);
1965
1966         pos = le32_to_cpu(hdr->len);
1967
1968         blocks = 0;
1969         while (pos < firmware->size &&
1970                pos - firmware->size > sizeof(*blk)) {
1971                 blk = (void *)(&firmware->data[pos]);
1972
1973                 type = le16_to_cpu(blk->type);
1974                 offset = le16_to_cpu(blk->offset);
1975
1976                 adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
1977                          file, blocks, le32_to_cpu(blk->id),
1978                          (le32_to_cpu(blk->ver) >> 16) & 0xff,
1979                          (le32_to_cpu(blk->ver) >>  8) & 0xff,
1980                          le32_to_cpu(blk->ver) & 0xff);
1981                 adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
1982                          file, blocks, le32_to_cpu(blk->len), offset, type);
1983
1984                 reg = 0;
1985                 region_name = "Unknown";
1986                 switch (type) {
1987                 case (WMFW_NAME_TEXT << 8):
1988                 case (WMFW_INFO_TEXT << 8):
1989                         break;
1990                 case (WMFW_ABSOLUTE << 8):
1991                         /*
1992                          * Old files may use this for global
1993                          * coefficients.
1994                          */
1995                         if (le32_to_cpu(blk->id) == dsp->fw_id &&
1996                             offset == 0) {
1997                                 region_name = "global coefficients";
1998                                 mem = wm_adsp_find_region(dsp, type);
1999                                 if (!mem) {
2000                                         adsp_err(dsp, "No ZM\n");
2001                                         break;
2002                                 }
2003                                 reg = wm_adsp_region_to_reg(mem, 0);
2004
2005                         } else {
2006                                 region_name = "register";
2007                                 reg = offset;
2008                         }
2009                         break;
2010
2011                 case WMFW_ADSP1_DM:
2012                 case WMFW_ADSP1_ZM:
2013                 case WMFW_ADSP2_XM:
2014                 case WMFW_ADSP2_YM:
2015                         adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
2016                                  file, blocks, le32_to_cpu(blk->len),
2017                                  type, le32_to_cpu(blk->id));
2018
2019                         mem = wm_adsp_find_region(dsp, type);
2020                         if (!mem) {
2021                                 adsp_err(dsp, "No base for region %x\n", type);
2022                                 break;
2023                         }
2024
2025                         alg_region = wm_adsp_find_alg_region(dsp, type,
2026                                                 le32_to_cpu(blk->id));
2027                         if (alg_region) {
2028                                 reg = alg_region->base;
2029                                 reg = wm_adsp_region_to_reg(mem, reg);
2030                                 reg += offset;
2031                         } else {
2032                                 adsp_err(dsp, "No %x for algorithm %x\n",
2033                                          type, le32_to_cpu(blk->id));
2034                         }
2035                         break;
2036
2037                 default:
2038                         adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
2039                                  file, blocks, type, pos);
2040                         break;
2041                 }
2042
2043                 if (reg) {
2044                         buf = wm_adsp_buf_alloc(blk->data,
2045                                                 le32_to_cpu(blk->len),
2046                                                 &buf_list);
2047                         if (!buf) {
2048                                 adsp_err(dsp, "Out of memory\n");
2049                                 ret = -ENOMEM;
2050                                 goto out_fw;
2051                         }
2052
2053                         adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
2054                                  file, blocks, le32_to_cpu(blk->len),
2055                                  reg);
2056                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
2057                                                      le32_to_cpu(blk->len));
2058                         if (ret != 0) {
2059                                 adsp_err(dsp,
2060                                         "%s.%d: Failed to write to %x in %s: %d\n",
2061                                         file, blocks, reg, region_name, ret);
2062                         }
2063                 }
2064
2065                 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
2066                 blocks++;
2067         }
2068
2069         ret = regmap_async_complete(regmap);
2070         if (ret != 0)
2071                 adsp_err(dsp, "Failed to complete async write: %d\n", ret);
2072
2073         if (pos > firmware->size)
2074                 adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2075                           file, blocks, pos - firmware->size);
2076
2077         wm_adsp_debugfs_save_binname(dsp, file);
2078
2079 out_fw:
2080         regmap_async_complete(regmap);
2081         release_firmware(firmware);
2082         wm_adsp_buf_free(&buf_list);
2083 out:
2084         kfree(file);
2085         return ret;
2086 }
2087
2088 int wm_adsp1_init(struct wm_adsp *dsp)
2089 {
2090         INIT_LIST_HEAD(&dsp->alg_regions);
2091
2092         mutex_init(&dsp->pwr_lock);
2093
2094         return 0;
2095 }
2096 EXPORT_SYMBOL_GPL(wm_adsp1_init);
2097
2098 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
2099                    struct snd_kcontrol *kcontrol,
2100                    int event)
2101 {
2102         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2103         struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
2104         struct wm_adsp *dsp = &dsps[w->shift];
2105         struct wm_coeff_ctl *ctl;
2106         int ret;
2107         unsigned int val;
2108
2109         dsp->card = codec->component.card;
2110
2111         mutex_lock(&dsp->pwr_lock);
2112
2113         switch (event) {
2114         case SND_SOC_DAPM_POST_PMU:
2115                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2116                                    ADSP1_SYS_ENA, ADSP1_SYS_ENA);
2117
2118                 /*
2119                  * For simplicity set the DSP clock rate to be the
2120                  * SYSCLK rate rather than making it configurable.
2121                  */
2122                 if (dsp->sysclk_reg) {
2123                         ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
2124                         if (ret != 0) {
2125                                 adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
2126                                 ret);
2127                                 goto err_mutex;
2128                         }
2129
2130                         val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
2131
2132                         ret = regmap_update_bits(dsp->regmap,
2133                                                  dsp->base + ADSP1_CONTROL_31,
2134                                                  ADSP1_CLK_SEL_MASK, val);
2135                         if (ret != 0) {
2136                                 adsp_err(dsp, "Failed to set clock rate: %d\n",
2137                                          ret);
2138                                 goto err_mutex;
2139                         }
2140                 }
2141
2142                 ret = wm_adsp_load(dsp);
2143                 if (ret != 0)
2144                         goto err_ena;
2145
2146                 ret = wm_adsp1_setup_algs(dsp);
2147                 if (ret != 0)
2148                         goto err_ena;
2149
2150                 ret = wm_adsp_load_coeff(dsp);
2151                 if (ret != 0)
2152                         goto err_ena;
2153
2154                 /* Initialize caches for enabled and unset controls */
2155                 ret = wm_coeff_init_control_caches(dsp);
2156                 if (ret != 0)
2157                         goto err_ena;
2158
2159                 /* Sync set controls */
2160                 ret = wm_coeff_sync_controls(dsp);
2161                 if (ret != 0)
2162                         goto err_ena;
2163
2164                 /* Start the core running */
2165                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2166                                    ADSP1_CORE_ENA | ADSP1_START,
2167                                    ADSP1_CORE_ENA | ADSP1_START);
2168                 break;
2169
2170         case SND_SOC_DAPM_PRE_PMD:
2171                 /* Halt the core */
2172                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2173                                    ADSP1_CORE_ENA | ADSP1_START, 0);
2174
2175                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
2176                                    ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
2177
2178                 regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2179                                    ADSP1_SYS_ENA, 0);
2180
2181                 list_for_each_entry(ctl, &dsp->ctl_list, list)
2182                         ctl->enabled = 0;
2183
2184
2185                 wm_adsp_free_alg_regions(dsp);
2186                 break;
2187
2188         default:
2189                 break;
2190         }
2191
2192         mutex_unlock(&dsp->pwr_lock);
2193
2194         return 0;
2195
2196 err_ena:
2197         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2198                            ADSP1_SYS_ENA, 0);
2199 err_mutex:
2200         mutex_unlock(&dsp->pwr_lock);
2201
2202         return ret;
2203 }
2204 EXPORT_SYMBOL_GPL(wm_adsp1_event);
2205
2206 static int wm_adsp2_ena(struct wm_adsp *dsp)
2207 {
2208         unsigned int val;
2209         int ret, count;
2210
2211         ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2212                                        ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2213         if (ret != 0)
2214                 return ret;
2215
2216         /* Wait for the RAM to start, should be near instantaneous */
2217         for (count = 0; count < 10; ++count) {
2218                 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
2219                 if (ret != 0)
2220                         return ret;
2221
2222                 if (val & ADSP2_RAM_RDY)
2223                         break;
2224
2225                 msleep(1);
2226         }
2227
2228         if (!(val & ADSP2_RAM_RDY)) {
2229                 adsp_err(dsp, "Failed to start DSP RAM\n");
2230                 return -EBUSY;
2231         }
2232
2233         adsp_dbg(dsp, "RAM ready after %d polls\n", count);
2234
2235         return 0;
2236 }
2237
2238 static void wm_adsp2_boot_work(struct work_struct *work)
2239 {
2240         struct wm_adsp *dsp = container_of(work,
2241                                            struct wm_adsp,
2242                                            boot_work);
2243         int ret;
2244
2245         mutex_lock(&dsp->pwr_lock);
2246
2247         ret = wm_adsp2_ena(dsp);
2248         if (ret != 0)
2249                 goto err_mutex;
2250
2251         ret = wm_adsp_load(dsp);
2252         if (ret != 0)
2253                 goto err_ena;
2254
2255         ret = wm_adsp2_setup_algs(dsp);
2256         if (ret != 0)
2257                 goto err_ena;
2258
2259         ret = wm_adsp_load_coeff(dsp);
2260         if (ret != 0)
2261                 goto err_ena;
2262
2263         /* Initialize caches for enabled and unset controls */
2264         ret = wm_coeff_init_control_caches(dsp);
2265         if (ret != 0)
2266                 goto err_ena;
2267
2268         /* Sync set controls */
2269         ret = wm_coeff_sync_controls(dsp);
2270         if (ret != 0)
2271                 goto err_ena;
2272
2273         dsp->running = true;
2274
2275         mutex_unlock(&dsp->pwr_lock);
2276
2277         return;
2278
2279 err_ena:
2280         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2281                            ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
2282 err_mutex:
2283         mutex_unlock(&dsp->pwr_lock);
2284 }
2285
2286 static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
2287 {
2288         int ret;
2289
2290         ret = regmap_update_bits_async(dsp->regmap,
2291                                        dsp->base + ADSP2_CLOCKING,
2292                                        ADSP2_CLK_SEL_MASK,
2293                                        freq << ADSP2_CLK_SEL_SHIFT);
2294         if (ret != 0)
2295                 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2296 }
2297
2298 int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
2299                          struct snd_kcontrol *kcontrol, int event,
2300                          unsigned int freq)
2301 {
2302         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2303         struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
2304         struct wm_adsp *dsp = &dsps[w->shift];
2305
2306         dsp->card = codec->component.card;
2307
2308         switch (event) {
2309         case SND_SOC_DAPM_PRE_PMU:
2310                 wm_adsp2_set_dspclk(dsp, freq);
2311                 queue_work(system_unbound_wq, &dsp->boot_work);
2312                 break;
2313         default:
2314                 break;
2315         }
2316
2317         return 0;
2318 }
2319 EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
2320
2321 int wm_adsp2_event(struct snd_soc_dapm_widget *w,
2322                    struct snd_kcontrol *kcontrol, int event)
2323 {
2324         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2325         struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
2326         struct wm_adsp *dsp = &dsps[w->shift];
2327         struct wm_coeff_ctl *ctl;
2328         int ret;
2329
2330         switch (event) {
2331         case SND_SOC_DAPM_POST_PMU:
2332                 flush_work(&dsp->boot_work);
2333
2334                 if (!dsp->running)
2335                         return -EIO;
2336
2337                 ret = regmap_update_bits(dsp->regmap,
2338                                          dsp->base + ADSP2_CONTROL,
2339                                          ADSP2_CORE_ENA | ADSP2_START,
2340                                          ADSP2_CORE_ENA | ADSP2_START);
2341                 if (ret != 0)
2342                         goto err;
2343
2344                 mutex_lock(&dsp->pwr_lock);
2345
2346                 if (wm_adsp_fw[dsp->fw].num_caps != 0)
2347                         ret = wm_adsp_buffer_init(dsp);
2348
2349                 mutex_unlock(&dsp->pwr_lock);
2350
2351                 break;
2352
2353         case SND_SOC_DAPM_PRE_PMD:
2354                 /* Log firmware state, it can be useful for analysis */
2355                 wm_adsp2_show_fw_status(dsp);
2356
2357                 mutex_lock(&dsp->pwr_lock);
2358
2359                 wm_adsp_debugfs_clear(dsp);
2360
2361                 dsp->fw_id = 0;
2362                 dsp->fw_id_version = 0;
2363                 dsp->running = false;
2364
2365                 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2366                                    ADSP2_SYS_ENA | ADSP2_CORE_ENA |
2367                                    ADSP2_START, 0);
2368
2369                 /* Make sure DMAs are quiesced */
2370                 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2371                 regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2372                 regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2373
2374                 list_for_each_entry(ctl, &dsp->ctl_list, list)
2375                         ctl->enabled = 0;
2376
2377                 wm_adsp_free_alg_regions(dsp);
2378
2379                 if (wm_adsp_fw[dsp->fw].num_caps != 0)
2380                         wm_adsp_buffer_free(dsp);
2381
2382                 mutex_unlock(&dsp->pwr_lock);
2383
2384                 adsp_dbg(dsp, "Shutdown complete\n");
2385                 break;
2386
2387         default:
2388                 break;
2389         }
2390
2391         return 0;
2392 err:
2393         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2394                            ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
2395         return ret;
2396 }
2397 EXPORT_SYMBOL_GPL(wm_adsp2_event);
2398
2399 int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec)
2400 {
2401         wm_adsp2_init_debugfs(dsp, codec);
2402
2403         return snd_soc_add_codec_controls(codec,
2404                                           &wm_adsp_fw_controls[dsp->num - 1],
2405                                           1);
2406 }
2407 EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe);
2408
2409 int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec)
2410 {
2411         wm_adsp2_cleanup_debugfs(dsp);
2412
2413         return 0;
2414 }
2415 EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove);
2416
2417 int wm_adsp2_init(struct wm_adsp *dsp)
2418 {
2419         int ret;
2420
2421         /*
2422          * Disable the DSP memory by default when in reset for a small
2423          * power saving.
2424          */
2425         ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2426                                  ADSP2_MEM_ENA, 0);
2427         if (ret != 0) {
2428                 adsp_err(dsp, "Failed to clear memory retention: %d\n", ret);
2429                 return ret;
2430         }
2431
2432         INIT_LIST_HEAD(&dsp->alg_regions);
2433         INIT_LIST_HEAD(&dsp->ctl_list);
2434         INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work);
2435
2436         mutex_init(&dsp->pwr_lock);
2437
2438         return 0;
2439 }
2440 EXPORT_SYMBOL_GPL(wm_adsp2_init);
2441
2442 void wm_adsp2_remove(struct wm_adsp *dsp)
2443 {
2444         struct wm_coeff_ctl *ctl;
2445
2446         while (!list_empty(&dsp->ctl_list)) {
2447                 ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl,
2448                                         list);
2449                 list_del(&ctl->list);
2450                 wm_adsp_free_ctl_blk(ctl);
2451         }
2452 }
2453 EXPORT_SYMBOL_GPL(wm_adsp2_remove);
2454
2455 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
2456 {
2457         struct wm_adsp_compr *compr;
2458         int ret = 0;
2459
2460         mutex_lock(&dsp->pwr_lock);
2461
2462         if (wm_adsp_fw[dsp->fw].num_caps == 0) {
2463                 adsp_err(dsp, "Firmware does not support compressed API\n");
2464                 ret = -ENXIO;
2465                 goto out;
2466         }
2467
2468         if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
2469                 adsp_err(dsp, "Firmware does not support stream direction\n");
2470                 ret = -EINVAL;
2471                 goto out;
2472         }
2473
2474         if (dsp->compr) {
2475                 /* It is expect this limitation will be removed in future */
2476                 adsp_err(dsp, "Only a single stream supported per DSP\n");
2477                 ret = -EBUSY;
2478                 goto out;
2479         }
2480
2481         compr = kzalloc(sizeof(*compr), GFP_KERNEL);
2482         if (!compr) {
2483                 ret = -ENOMEM;
2484                 goto out;
2485         }
2486
2487         compr->dsp = dsp;
2488         compr->stream = stream;
2489
2490         dsp->compr = compr;
2491
2492         stream->runtime->private_data = compr;
2493
2494 out:
2495         mutex_unlock(&dsp->pwr_lock);
2496
2497         return ret;
2498 }
2499 EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
2500
2501 int wm_adsp_compr_free(struct snd_compr_stream *stream)
2502 {
2503         struct wm_adsp_compr *compr = stream->runtime->private_data;
2504         struct wm_adsp *dsp = compr->dsp;
2505
2506         mutex_lock(&dsp->pwr_lock);
2507
2508         dsp->compr = NULL;
2509
2510         kfree(compr->raw_buf);
2511         kfree(compr);
2512
2513         mutex_unlock(&dsp->pwr_lock);
2514
2515         return 0;
2516 }
2517 EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
2518
2519 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
2520                                       struct snd_compr_params *params)
2521 {
2522         struct wm_adsp_compr *compr = stream->runtime->private_data;
2523         struct wm_adsp *dsp = compr->dsp;
2524         const struct wm_adsp_fw_caps *caps;
2525         const struct snd_codec_desc *desc;
2526         int i, j;
2527
2528         if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
2529             params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
2530             params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
2531             params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
2532             params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) {
2533                 adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n",
2534                          params->buffer.fragment_size,
2535                          params->buffer.fragments);
2536
2537                 return -EINVAL;
2538         }
2539
2540         for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
2541                 caps = &wm_adsp_fw[dsp->fw].caps[i];
2542                 desc = &caps->desc;
2543
2544                 if (caps->id != params->codec.id)
2545                         continue;
2546
2547                 if (stream->direction == SND_COMPRESS_PLAYBACK) {
2548                         if (desc->max_ch < params->codec.ch_out)
2549                                 continue;
2550                 } else {
2551                         if (desc->max_ch < params->codec.ch_in)
2552                                 continue;
2553                 }
2554
2555                 if (!(desc->formats & (1 << params->codec.format)))
2556                         continue;
2557
2558                 for (j = 0; j < desc->num_sample_rates; ++j)
2559                         if (desc->sample_rates[j] == params->codec.sample_rate)
2560                                 return 0;
2561         }
2562
2563         adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
2564                  params->codec.id, params->codec.ch_in, params->codec.ch_out,
2565                  params->codec.sample_rate, params->codec.format);
2566         return -EINVAL;
2567 }
2568
2569 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
2570 {
2571         return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
2572 }
2573
2574 int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
2575                              struct snd_compr_params *params)
2576 {
2577         struct wm_adsp_compr *compr = stream->runtime->private_data;
2578         unsigned int size;
2579         int ret;
2580
2581         ret = wm_adsp_compr_check_params(stream, params);
2582         if (ret)
2583                 return ret;
2584
2585         compr->size = params->buffer;
2586
2587         adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n",
2588                  compr->size.fragment_size, compr->size.fragments);
2589
2590         size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
2591         compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
2592         if (!compr->raw_buf)
2593                 return -ENOMEM;
2594
2595         compr->sample_rate = params->codec.sample_rate;
2596
2597         return 0;
2598 }
2599 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
2600
2601 int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
2602                            struct snd_compr_caps *caps)
2603 {
2604         struct wm_adsp_compr *compr = stream->runtime->private_data;
2605         int fw = compr->dsp->fw;
2606         int i;
2607
2608         if (wm_adsp_fw[fw].caps) {
2609                 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
2610                         caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
2611
2612                 caps->num_codecs = i;
2613                 caps->direction = wm_adsp_fw[fw].compr_direction;
2614
2615                 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
2616                 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
2617                 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
2618                 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
2619         }
2620
2621         return 0;
2622 }
2623 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
2624
2625 static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
2626                                    unsigned int mem_addr,
2627                                    unsigned int num_words, u32 *data)
2628 {
2629         struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
2630         unsigned int i, reg;
2631         int ret;
2632
2633         if (!mem)
2634                 return -EINVAL;
2635
2636         reg = wm_adsp_region_to_reg(mem, mem_addr);
2637
2638         ret = regmap_raw_read(dsp->regmap, reg, data,
2639                               sizeof(*data) * num_words);
2640         if (ret < 0)
2641                 return ret;
2642
2643         for (i = 0; i < num_words; ++i)
2644                 data[i] = be32_to_cpu(data[i]) & 0x00ffffffu;
2645
2646         return 0;
2647 }
2648
2649 static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
2650                                          unsigned int mem_addr, u32 *data)
2651 {
2652         return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data);
2653 }
2654
2655 static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
2656                                    unsigned int mem_addr, u32 data)
2657 {
2658         struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
2659         unsigned int reg;
2660
2661         if (!mem)
2662                 return -EINVAL;
2663
2664         reg = wm_adsp_region_to_reg(mem, mem_addr);
2665
2666         data = cpu_to_be32(data & 0x00ffffffu);
2667
2668         return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data));
2669 }
2670
2671 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
2672                                       unsigned int field_offset, u32 *data)
2673 {
2674         return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM,
2675                                       buf->host_buf_ptr + field_offset, data);
2676 }
2677
2678 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
2679                                        unsigned int field_offset, u32 data)
2680 {
2681         return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM,
2682                                        buf->host_buf_ptr + field_offset, data);
2683 }
2684
2685 static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
2686 {
2687         struct wm_adsp_alg_region *alg_region;
2688         struct wm_adsp *dsp = buf->dsp;
2689         u32 xmalg, addr, magic;
2690         int i, ret;
2691
2692         alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
2693         xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32);
2694
2695         addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
2696         ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
2697         if (ret < 0)
2698                 return ret;
2699
2700         if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
2701                 return -EINVAL;
2702
2703         addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
2704         for (i = 0; i < 5; ++i) {
2705                 ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
2706                                              &buf->host_buf_ptr);
2707                 if (ret < 0)
2708                         return ret;
2709
2710                 if (buf->host_buf_ptr)
2711                         break;
2712
2713                 usleep_range(1000, 2000);
2714         }
2715
2716         if (!buf->host_buf_ptr)
2717                 return -EIO;
2718
2719         adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
2720
2721         return 0;
2722 }
2723
2724 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
2725 {
2726         const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
2727         struct wm_adsp_buffer_region *region;
2728         u32 offset = 0;
2729         int i, ret;
2730
2731         for (i = 0; i < caps->num_regions; ++i) {
2732                 region = &buf->regions[i];
2733
2734                 region->offset = offset;
2735                 region->mem_type = caps->region_defs[i].mem_type;
2736
2737                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
2738                                           &region->base_addr);
2739                 if (ret < 0)
2740                         return ret;
2741
2742                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
2743                                           &offset);
2744                 if (ret < 0)
2745                         return ret;
2746
2747                 region->cumulative_size = offset;
2748
2749                 adsp_dbg(buf->dsp,
2750                          "region=%d type=%d base=%04x off=%04x size=%04x\n",
2751                          i, region->mem_type, region->base_addr,
2752                          region->offset, region->cumulative_size);
2753         }
2754
2755         return 0;
2756 }
2757
2758 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
2759 {
2760         struct wm_adsp_compr_buf *buf;
2761         int ret;
2762
2763         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
2764         if (!buf)
2765                 return -ENOMEM;
2766
2767         buf->dsp = dsp;
2768         buf->read_index = -1;
2769         buf->irq_count = 0xFFFFFFFF;
2770
2771         ret = wm_adsp_buffer_locate(buf);
2772         if (ret < 0) {
2773                 adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret);
2774                 goto err_buffer;
2775         }
2776
2777         buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions,
2778                                sizeof(*buf->regions), GFP_KERNEL);
2779         if (!buf->regions) {
2780                 ret = -ENOMEM;
2781                 goto err_buffer;
2782         }
2783
2784         ret = wm_adsp_buffer_populate(buf);
2785         if (ret < 0) {
2786                 adsp_err(dsp, "Failed to populate host buffer: %d\n", ret);
2787                 goto err_regions;
2788         }
2789
2790         dsp->buffer = buf;
2791
2792         return 0;
2793
2794 err_regions:
2795         kfree(buf->regions);
2796 err_buffer:
2797         kfree(buf);
2798         return ret;
2799 }
2800
2801 static int wm_adsp_buffer_free(struct wm_adsp *dsp)
2802 {
2803         if (dsp->buffer) {
2804                 kfree(dsp->buffer->regions);
2805                 kfree(dsp->buffer);
2806
2807                 dsp->buffer = NULL;
2808         }
2809
2810         return 0;
2811 }
2812
2813 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
2814 {
2815         return compr->buf != NULL;
2816 }
2817
2818 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
2819 {
2820         /*
2821          * Note this will be more complex once each DSP can support multiple
2822          * streams
2823          */
2824         if (!compr->dsp->buffer)
2825                 return -EINVAL;
2826
2827         compr->buf = compr->dsp->buffer;
2828
2829         return 0;
2830 }
2831
2832 int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
2833 {
2834         struct wm_adsp_compr *compr = stream->runtime->private_data;
2835         struct wm_adsp *dsp = compr->dsp;
2836         int ret = 0;
2837
2838         adsp_dbg(dsp, "Trigger: %d\n", cmd);
2839
2840         mutex_lock(&dsp->pwr_lock);
2841
2842         switch (cmd) {
2843         case SNDRV_PCM_TRIGGER_START:
2844                 if (wm_adsp_compr_attached(compr))
2845                         break;
2846
2847                 ret = wm_adsp_compr_attach(compr);
2848                 if (ret < 0) {
2849                         adsp_err(dsp, "Failed to link buffer and stream: %d\n",
2850                                  ret);
2851                         break;
2852                 }
2853
2854                 /* Trigger the IRQ at one fragment of data */
2855                 ret = wm_adsp_buffer_write(compr->buf,
2856                                            HOST_BUFFER_FIELD(high_water_mark),
2857                                            wm_adsp_compr_frag_words(compr));
2858                 if (ret < 0) {
2859                         adsp_err(dsp, "Failed to set high water mark: %d\n",
2860                                  ret);
2861                         break;
2862                 }
2863                 break;
2864         case SNDRV_PCM_TRIGGER_STOP:
2865                 break;
2866         default:
2867                 ret = -EINVAL;
2868                 break;
2869         }
2870
2871         mutex_unlock(&dsp->pwr_lock);
2872
2873         return ret;
2874 }
2875 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
2876
2877 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
2878 {
2879         int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
2880
2881         return buf->regions[last_region].cumulative_size;
2882 }
2883
2884 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
2885 {
2886         u32 next_read_index, next_write_index;
2887         int write_index, read_index, avail;
2888         int ret;
2889
2890         /* Only sync read index if we haven't already read a valid index */
2891         if (buf->read_index < 0) {
2892                 ret = wm_adsp_buffer_read(buf,
2893                                 HOST_BUFFER_FIELD(next_read_index),
2894                                 &next_read_index);
2895                 if (ret < 0)
2896                         return ret;
2897
2898                 read_index = sign_extend32(next_read_index, 23);
2899
2900                 if (read_index < 0) {
2901                         adsp_dbg(buf->dsp, "Avail check on unstarted stream\n");
2902                         return 0;
2903                 }
2904
2905                 buf->read_index = read_index;
2906         }
2907
2908         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
2909                         &next_write_index);
2910         if (ret < 0)
2911                 return ret;
2912
2913         write_index = sign_extend32(next_write_index, 23);
2914
2915         avail = write_index - buf->read_index;
2916         if (avail < 0)
2917                 avail += wm_adsp_buffer_size(buf);
2918
2919         adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
2920                  buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
2921
2922         buf->avail = avail;
2923
2924         return 0;
2925 }
2926
2927 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
2928 {
2929         int ret;
2930
2931         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
2932         if (ret < 0) {
2933                 adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret);
2934                 return ret;
2935         }
2936         if (buf->error != 0) {
2937                 adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error);
2938                 return -EIO;
2939         }
2940
2941         return 0;
2942 }
2943
2944 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
2945 {
2946         struct wm_adsp_compr_buf *buf;
2947         struct wm_adsp_compr *compr;
2948         int ret = 0;
2949
2950         mutex_lock(&dsp->pwr_lock);
2951
2952         buf = dsp->buffer;
2953         compr = dsp->compr;
2954
2955         if (!buf) {
2956                 ret = -ENODEV;
2957                 goto out;
2958         }
2959
2960         adsp_dbg(dsp, "Handling buffer IRQ\n");
2961
2962         ret = wm_adsp_buffer_get_error(buf);
2963         if (ret < 0)
2964                 goto out_notify; /* Wake poll to report error */
2965
2966         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
2967                                   &buf->irq_count);
2968         if (ret < 0) {
2969                 adsp_err(dsp, "Failed to get irq_count: %d\n", ret);
2970                 goto out;
2971         }
2972
2973         ret = wm_adsp_buffer_update_avail(buf);
2974         if (ret < 0) {
2975                 adsp_err(dsp, "Error reading avail: %d\n", ret);
2976                 goto out;
2977         }
2978
2979 out_notify:
2980         if (compr && compr->stream)
2981                 snd_compr_fragment_elapsed(compr->stream);
2982
2983 out:
2984         mutex_unlock(&dsp->pwr_lock);
2985
2986         return ret;
2987 }
2988 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
2989
2990 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
2991 {
2992         if (buf->irq_count & 0x01)
2993                 return 0;
2994
2995         adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n",
2996                  buf->irq_count);
2997
2998         buf->irq_count |= 0x01;
2999
3000         return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
3001                                     buf->irq_count);
3002 }
3003
3004 int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
3005                           struct snd_compr_tstamp *tstamp)
3006 {
3007         struct wm_adsp_compr *compr = stream->runtime->private_data;
3008         struct wm_adsp *dsp = compr->dsp;
3009         struct wm_adsp_compr_buf *buf;
3010         int ret = 0;
3011
3012         adsp_dbg(dsp, "Pointer request\n");
3013
3014         mutex_lock(&dsp->pwr_lock);
3015
3016         buf = compr->buf;
3017
3018         if (!compr->buf) {
3019                 ret = -ENXIO;
3020                 goto out;
3021         }
3022
3023         if (compr->buf->error) {
3024                 ret = -EIO;
3025                 goto out;
3026         }
3027
3028         if (buf->avail < wm_adsp_compr_frag_words(compr)) {
3029                 ret = wm_adsp_buffer_update_avail(buf);
3030                 if (ret < 0) {
3031                         adsp_err(dsp, "Error reading avail: %d\n", ret);
3032                         goto out;
3033                 }
3034
3035                 /*
3036                  * If we really have less than 1 fragment available tell the
3037                  * DSP to inform us once a whole fragment is available.
3038                  */
3039                 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
3040                         ret = wm_adsp_buffer_get_error(buf);
3041                         if (ret < 0)
3042                                 goto out;
3043
3044                         ret = wm_adsp_buffer_reenable_irq(buf);
3045                         if (ret < 0) {
3046                                 adsp_err(dsp,
3047                                          "Failed to re-enable buffer IRQ: %d\n",
3048                                          ret);
3049                                 goto out;
3050                         }
3051                 }
3052         }
3053
3054         tstamp->copied_total = compr->copied_total;
3055         tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
3056         tstamp->sampling_rate = compr->sample_rate;
3057
3058 out:
3059         mutex_unlock(&dsp->pwr_lock);
3060
3061         return ret;
3062 }
3063 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
3064
3065 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
3066 {
3067         struct wm_adsp_compr_buf *buf = compr->buf;
3068         u8 *pack_in = (u8 *)compr->raw_buf;
3069         u8 *pack_out = (u8 *)compr->raw_buf;
3070         unsigned int adsp_addr;
3071         int mem_type, nwords, max_read;
3072         int i, j, ret;
3073
3074         /* Calculate read parameters */
3075         for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
3076                 if (buf->read_index < buf->regions[i].cumulative_size)
3077                         break;
3078
3079         if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
3080                 return -EINVAL;
3081
3082         mem_type = buf->regions[i].mem_type;
3083         adsp_addr = buf->regions[i].base_addr +
3084                     (buf->read_index - buf->regions[i].offset);
3085
3086         max_read = wm_adsp_compr_frag_words(compr);
3087         nwords = buf->regions[i].cumulative_size - buf->read_index;
3088
3089         if (nwords > target)
3090                 nwords = target;
3091         if (nwords > buf->avail)
3092                 nwords = buf->avail;
3093         if (nwords > max_read)
3094                 nwords = max_read;
3095         if (!nwords)
3096                 return 0;
3097
3098         /* Read data from DSP */
3099         ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
3100                                       nwords, compr->raw_buf);
3101         if (ret < 0)
3102                 return ret;
3103
3104         /* Remove the padding bytes from the data read from the DSP */
3105         for (i = 0; i < nwords; i++) {
3106                 for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++)
3107                         *pack_out++ = *pack_in++;
3108
3109                 pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE;
3110         }
3111
3112         /* update read index to account for words read */
3113         buf->read_index += nwords;
3114         if (buf->read_index == wm_adsp_buffer_size(buf))
3115                 buf->read_index = 0;
3116
3117         ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
3118                                    buf->read_index);
3119         if (ret < 0)
3120                 return ret;
3121
3122         /* update avail to account for words read */
3123         buf->avail -= nwords;
3124
3125         return nwords;
3126 }
3127
3128 static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
3129                               char __user *buf, size_t count)
3130 {
3131         struct wm_adsp *dsp = compr->dsp;
3132         int ntotal = 0;
3133         int nwords, nbytes;
3134
3135         adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
3136
3137         if (!compr->buf)
3138                 return -ENXIO;
3139
3140         if (compr->buf->error)
3141                 return -EIO;
3142
3143         count /= WM_ADSP_DATA_WORD_SIZE;
3144
3145         do {
3146                 nwords = wm_adsp_buffer_capture_block(compr, count);
3147                 if (nwords < 0) {
3148                         adsp_err(dsp, "Failed to capture block: %d\n", nwords);
3149                         return nwords;
3150                 }
3151
3152                 nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
3153
3154                 adsp_dbg(dsp, "Read %d bytes\n", nbytes);
3155
3156                 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
3157                         adsp_err(dsp, "Failed to copy data to user: %d, %d\n",
3158                                  ntotal, nbytes);
3159                         return -EFAULT;
3160                 }
3161
3162                 count -= nwords;
3163                 ntotal += nbytes;
3164         } while (nwords > 0 && count > 0);
3165
3166         compr->copied_total += ntotal;
3167
3168         return ntotal;
3169 }
3170
3171 int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf,
3172                        size_t count)
3173 {
3174         struct wm_adsp_compr *compr = stream->runtime->private_data;
3175         struct wm_adsp *dsp = compr->dsp;
3176         int ret;
3177
3178         mutex_lock(&dsp->pwr_lock);
3179
3180         if (stream->direction == SND_COMPRESS_CAPTURE)
3181                 ret = wm_adsp_compr_read(compr, buf, count);
3182         else
3183                 ret = -ENOTSUPP;
3184
3185         mutex_unlock(&dsp->pwr_lock);
3186
3187         return ret;
3188 }
3189 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
3190
3191 MODULE_LICENSE("GPL v2");
This page took 0.219864 seconds and 4 git commands to generate.