Merge branch 'for-5.16' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[platform/kernel/linux-starfive.git] / sound / soc / codecs / wm_adsp.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * wm_adsp.c  --  Wolfson ADSP support
4  *
5  * Copyright 2012 Wolfson Microelectronics plc
6  *
7  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8  */
9
10 #include <linux/ctype.h>
11 #include <linux/module.h>
12 #include <linux/moduleparam.h>
13 #include <linux/init.h>
14 #include <linux/delay.h>
15 #include <linux/firmware.h>
16 #include <linux/list.h>
17 #include <linux/pm.h>
18 #include <linux/pm_runtime.h>
19 #include <linux/regmap.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/slab.h>
22 #include <linux/workqueue.h>
23 #include <linux/debugfs.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 #include <sound/jack.h>
29 #include <sound/initval.h>
30 #include <sound/tlv.h>
31
32 #include "wm_adsp.h"
33
34 #define adsp_crit(_dsp, fmt, ...) \
35         dev_crit(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
36 #define adsp_err(_dsp, fmt, ...) \
37         dev_err(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
38 #define adsp_warn(_dsp, fmt, ...) \
39         dev_warn(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
40 #define adsp_info(_dsp, fmt, ...) \
41         dev_info(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
42 #define adsp_dbg(_dsp, fmt, ...) \
43         dev_dbg(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
44
45 #define compr_err(_obj, fmt, ...) \
46         adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
47                  ##__VA_ARGS__)
48 #define compr_dbg(_obj, fmt, ...) \
49         adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
50                  ##__VA_ARGS__)
51
52 #define ADSP_MAX_STD_CTRL_SIZE               512
53
54 static const struct cs_dsp_client_ops wm_adsp1_client_ops;
55 static const struct cs_dsp_client_ops wm_adsp2_client_ops;
56
57 #define WM_ADSP_FW_MBC_VSS  0
58 #define WM_ADSP_FW_HIFI     1
59 #define WM_ADSP_FW_TX       2
60 #define WM_ADSP_FW_TX_SPK   3
61 #define WM_ADSP_FW_RX       4
62 #define WM_ADSP_FW_RX_ANC   5
63 #define WM_ADSP_FW_CTRL     6
64 #define WM_ADSP_FW_ASR      7
65 #define WM_ADSP_FW_TRACE    8
66 #define WM_ADSP_FW_SPK_PROT 9
67 #define WM_ADSP_FW_SPK_CALI 10
68 #define WM_ADSP_FW_SPK_DIAG 11
69 #define WM_ADSP_FW_MISC     12
70
71 #define WM_ADSP_NUM_FW      13
72
73 static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
74         [WM_ADSP_FW_MBC_VSS] =  "MBC/VSS",
75         [WM_ADSP_FW_HIFI] =     "MasterHiFi",
76         [WM_ADSP_FW_TX] =       "Tx",
77         [WM_ADSP_FW_TX_SPK] =   "Tx Speaker",
78         [WM_ADSP_FW_RX] =       "Rx",
79         [WM_ADSP_FW_RX_ANC] =   "Rx ANC",
80         [WM_ADSP_FW_CTRL] =     "Voice Ctrl",
81         [WM_ADSP_FW_ASR] =      "ASR Assist",
82         [WM_ADSP_FW_TRACE] =    "Dbg Trace",
83         [WM_ADSP_FW_SPK_PROT] = "Protection",
84         [WM_ADSP_FW_SPK_CALI] = "Calibration",
85         [WM_ADSP_FW_SPK_DIAG] = "Diagnostic",
86         [WM_ADSP_FW_MISC] =     "Misc",
87 };
88
89 struct wm_adsp_system_config_xm_hdr {
90         __be32 sys_enable;
91         __be32 fw_id;
92         __be32 fw_rev;
93         __be32 boot_status;
94         __be32 watchdog;
95         __be32 dma_buffer_size;
96         __be32 rdma[6];
97         __be32 wdma[8];
98         __be32 build_job_name[3];
99         __be32 build_job_number;
100 };
101
102 struct wm_halo_system_config_xm_hdr {
103         __be32 halo_heartbeat;
104         __be32 build_job_name[3];
105         __be32 build_job_number;
106 };
107
108 struct wm_adsp_alg_xm_struct {
109         __be32 magic;
110         __be32 smoothing;
111         __be32 threshold;
112         __be32 host_buf_ptr;
113         __be32 start_seq;
114         __be32 high_water_mark;
115         __be32 low_water_mark;
116         __be64 smoothed_power;
117 };
118
119 struct wm_adsp_host_buf_coeff_v1 {
120         __be32 host_buf_ptr;            /* Host buffer pointer */
121         __be32 versions;                /* Version numbers */
122         __be32 name[4];                 /* The buffer name */
123 };
124
125 struct wm_adsp_buffer {
126         __be32 buf1_base;               /* Base addr of first buffer area */
127         __be32 buf1_size;               /* Size of buf1 area in DSP words */
128         __be32 buf2_base;               /* Base addr of 2nd buffer area */
129         __be32 buf1_buf2_size;          /* Size of buf1+buf2 in DSP words */
130         __be32 buf3_base;               /* Base addr of buf3 area */
131         __be32 buf_total_size;          /* Size of buf1+buf2+buf3 in DSP words */
132         __be32 high_water_mark;         /* Point at which IRQ is asserted */
133         __be32 irq_count;               /* bits 1-31 count IRQ assertions */
134         __be32 irq_ack;                 /* acked IRQ count, bit 0 enables IRQ */
135         __be32 next_write_index;        /* word index of next write */
136         __be32 next_read_index;         /* word index of next read */
137         __be32 error;                   /* error if any */
138         __be32 oldest_block_index;      /* word index of oldest surviving */
139         __be32 requested_rewind;        /* how many blocks rewind was done */
140         __be32 reserved_space;          /* internal */
141         __be32 min_free;                /* min free space since stream start */
142         __be32 blocks_written[2];       /* total blocks written (64 bit) */
143         __be32 words_written[2];        /* total words written (64 bit) */
144 };
145
146 struct wm_adsp_compr;
147
148 struct wm_adsp_compr_buf {
149         struct list_head list;
150         struct wm_adsp *dsp;
151         struct wm_adsp_compr *compr;
152
153         struct wm_adsp_buffer_region *regions;
154         u32 host_buf_ptr;
155
156         u32 error;
157         u32 irq_count;
158         int read_index;
159         int avail;
160         int host_buf_mem_type;
161
162         char *name;
163 };
164
165 struct wm_adsp_compr {
166         struct list_head list;
167         struct wm_adsp *dsp;
168         struct wm_adsp_compr_buf *buf;
169
170         struct snd_compr_stream *stream;
171         struct snd_compressed_buffer size;
172
173         u32 *raw_buf;
174         unsigned int copied_total;
175
176         unsigned int sample_rate;
177
178         const char *name;
179 };
180
181 #define WM_ADSP_MIN_FRAGMENTS          1
182 #define WM_ADSP_MAX_FRAGMENTS          256
183 #define WM_ADSP_MIN_FRAGMENT_SIZE      (64 * CS_DSP_DATA_WORD_SIZE)
184 #define WM_ADSP_MAX_FRAGMENT_SIZE      (4096 * CS_DSP_DATA_WORD_SIZE)
185
186 #define WM_ADSP_ALG_XM_STRUCT_MAGIC    0x49aec7
187
188 #define HOST_BUFFER_FIELD(field) \
189         (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
190
191 #define ALG_XM_FIELD(field) \
192         (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
193
194 #define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER     1
195
196 #define HOST_BUF_COEFF_COMPAT_VER_MASK          0xFF00
197 #define HOST_BUF_COEFF_COMPAT_VER_SHIFT         8
198
199 static int wm_adsp_buffer_init(struct wm_adsp *dsp);
200 static int wm_adsp_buffer_free(struct wm_adsp *dsp);
201
202 struct wm_adsp_buffer_region {
203         unsigned int offset;
204         unsigned int cumulative_size;
205         unsigned int mem_type;
206         unsigned int base_addr;
207 };
208
209 struct wm_adsp_buffer_region_def {
210         unsigned int mem_type;
211         unsigned int base_offset;
212         unsigned int size_offset;
213 };
214
215 static const struct wm_adsp_buffer_region_def default_regions[] = {
216         {
217                 .mem_type = WMFW_ADSP2_XM,
218                 .base_offset = HOST_BUFFER_FIELD(buf1_base),
219                 .size_offset = HOST_BUFFER_FIELD(buf1_size),
220         },
221         {
222                 .mem_type = WMFW_ADSP2_XM,
223                 .base_offset = HOST_BUFFER_FIELD(buf2_base),
224                 .size_offset = HOST_BUFFER_FIELD(buf1_buf2_size),
225         },
226         {
227                 .mem_type = WMFW_ADSP2_YM,
228                 .base_offset = HOST_BUFFER_FIELD(buf3_base),
229                 .size_offset = HOST_BUFFER_FIELD(buf_total_size),
230         },
231 };
232
233 struct wm_adsp_fw_caps {
234         u32 id;
235         struct snd_codec_desc desc;
236         int num_regions;
237         const struct wm_adsp_buffer_region_def *region_defs;
238 };
239
240 static const struct wm_adsp_fw_caps ctrl_caps[] = {
241         {
242                 .id = SND_AUDIOCODEC_BESPOKE,
243                 .desc = {
244                         .max_ch = 8,
245                         .sample_rates = { 16000 },
246                         .num_sample_rates = 1,
247                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
248                 },
249                 .num_regions = ARRAY_SIZE(default_regions),
250                 .region_defs = default_regions,
251         },
252 };
253
254 static const struct wm_adsp_fw_caps trace_caps[] = {
255         {
256                 .id = SND_AUDIOCODEC_BESPOKE,
257                 .desc = {
258                         .max_ch = 8,
259                         .sample_rates = {
260                                 4000, 8000, 11025, 12000, 16000, 22050,
261                                 24000, 32000, 44100, 48000, 64000, 88200,
262                                 96000, 176400, 192000
263                         },
264                         .num_sample_rates = 15,
265                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
266                 },
267                 .num_regions = ARRAY_SIZE(default_regions),
268                 .region_defs = default_regions,
269         },
270 };
271
272 static const struct {
273         const char *file;
274         int compr_direction;
275         int num_caps;
276         const struct wm_adsp_fw_caps *caps;
277         bool voice_trigger;
278 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
279         [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
280         [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
281         [WM_ADSP_FW_TX] =       { .file = "tx" },
282         [WM_ADSP_FW_TX_SPK] =   { .file = "tx-spk" },
283         [WM_ADSP_FW_RX] =       { .file = "rx" },
284         [WM_ADSP_FW_RX_ANC] =   { .file = "rx-anc" },
285         [WM_ADSP_FW_CTRL] =     {
286                 .file = "ctrl",
287                 .compr_direction = SND_COMPRESS_CAPTURE,
288                 .num_caps = ARRAY_SIZE(ctrl_caps),
289                 .caps = ctrl_caps,
290                 .voice_trigger = true,
291         },
292         [WM_ADSP_FW_ASR] =      { .file = "asr" },
293         [WM_ADSP_FW_TRACE] =    {
294                 .file = "trace",
295                 .compr_direction = SND_COMPRESS_CAPTURE,
296                 .num_caps = ARRAY_SIZE(trace_caps),
297                 .caps = trace_caps,
298         },
299         [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
300         [WM_ADSP_FW_SPK_CALI] = { .file = "spk-cali" },
301         [WM_ADSP_FW_SPK_DIAG] = { .file = "spk-diag" },
302         [WM_ADSP_FW_MISC] =     { .file = "misc" },
303 };
304
305 struct wm_coeff_ctl {
306         const char *name;
307         struct cs_dsp_coeff_ctl *cs_ctl;
308         struct soc_bytes_ext bytes_ext;
309         struct work_struct work;
310 };
311
312 int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
313                    struct snd_ctl_elem_value *ucontrol)
314 {
315         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
316         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
317         struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
318
319         ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
320
321         return 0;
322 }
323 EXPORT_SYMBOL_GPL(wm_adsp_fw_get);
324
325 int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
326                    struct snd_ctl_elem_value *ucontrol)
327 {
328         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
329         struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
330         struct wm_adsp *dsp = snd_soc_component_get_drvdata(component);
331         int ret = 0;
332
333         if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
334                 return 0;
335
336         if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
337                 return -EINVAL;
338
339         mutex_lock(&dsp[e->shift_l].cs_dsp.pwr_lock);
340
341         if (dsp[e->shift_l].cs_dsp.booted || !list_empty(&dsp[e->shift_l].compr_list))
342                 ret = -EBUSY;
343         else
344                 dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
345
346         mutex_unlock(&dsp[e->shift_l].cs_dsp.pwr_lock);
347
348         return ret;
349 }
350 EXPORT_SYMBOL_GPL(wm_adsp_fw_put);
351
352 const struct soc_enum wm_adsp_fw_enum[] = {
353         SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
354         SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
355         SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
356         SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
357         SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
358         SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
359         SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
360 };
361 EXPORT_SYMBOL_GPL(wm_adsp_fw_enum);
362
363 static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
364 {
365         return container_of(ext, struct wm_coeff_ctl, bytes_ext);
366 }
367
368 static int wm_coeff_info(struct snd_kcontrol *kctl,
369                          struct snd_ctl_elem_info *uinfo)
370 {
371         struct soc_bytes_ext *bytes_ext =
372                 (struct soc_bytes_ext *)kctl->private_value;
373         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
374         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
375
376         switch (cs_ctl->type) {
377         case WMFW_CTL_TYPE_ACKED:
378                 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
379                 uinfo->value.integer.min = CS_DSP_ACKED_CTL_MIN_VALUE;
380                 uinfo->value.integer.max = CS_DSP_ACKED_CTL_MAX_VALUE;
381                 uinfo->value.integer.step = 1;
382                 uinfo->count = 1;
383                 break;
384         default:
385                 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
386                 uinfo->count = cs_ctl->len;
387                 break;
388         }
389
390         return 0;
391 }
392
393 static int wm_coeff_put(struct snd_kcontrol *kctl,
394                         struct snd_ctl_elem_value *ucontrol)
395 {
396         struct soc_bytes_ext *bytes_ext =
397                 (struct soc_bytes_ext *)kctl->private_value;
398         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
399         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
400         char *p = ucontrol->value.bytes.data;
401         int ret = 0;
402
403         mutex_lock(&cs_ctl->dsp->pwr_lock);
404         ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, p, cs_ctl->len);
405         mutex_unlock(&cs_ctl->dsp->pwr_lock);
406
407         return ret;
408 }
409
410 static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
411                             const unsigned int __user *bytes, unsigned int size)
412 {
413         struct soc_bytes_ext *bytes_ext =
414                 (struct soc_bytes_ext *)kctl->private_value;
415         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
416         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
417         int ret = 0;
418
419         mutex_lock(&cs_ctl->dsp->pwr_lock);
420
421         if (copy_from_user(cs_ctl->cache, bytes, size))
422                 ret = -EFAULT;
423         else
424                 ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, cs_ctl->cache, size);
425
426         mutex_unlock(&cs_ctl->dsp->pwr_lock);
427
428         return ret;
429 }
430
431 static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
432                               struct snd_ctl_elem_value *ucontrol)
433 {
434         struct soc_bytes_ext *bytes_ext =
435                 (struct soc_bytes_ext *)kctl->private_value;
436         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
437         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
438         unsigned int val = ucontrol->value.integer.value[0];
439         int ret;
440
441         if (val == 0)
442                 return 0;       /* 0 means no event */
443
444         mutex_lock(&cs_ctl->dsp->pwr_lock);
445
446         if (cs_ctl->enabled)
447                 ret = cs_dsp_coeff_write_acked_control(cs_ctl, val);
448         else
449                 ret = -EPERM;
450
451         mutex_unlock(&cs_ctl->dsp->pwr_lock);
452
453         return ret;
454 }
455
456 static int wm_coeff_get(struct snd_kcontrol *kctl,
457                         struct snd_ctl_elem_value *ucontrol)
458 {
459         struct soc_bytes_ext *bytes_ext =
460                 (struct soc_bytes_ext *)kctl->private_value;
461         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
462         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
463         char *p = ucontrol->value.bytes.data;
464         int ret;
465
466         mutex_lock(&cs_ctl->dsp->pwr_lock);
467         ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, p, cs_ctl->len);
468         mutex_unlock(&cs_ctl->dsp->pwr_lock);
469
470         return ret;
471 }
472
473 static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
474                             unsigned int __user *bytes, unsigned int size)
475 {
476         struct soc_bytes_ext *bytes_ext =
477                 (struct soc_bytes_ext *)kctl->private_value;
478         struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
479         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
480         int ret = 0;
481
482         mutex_lock(&cs_ctl->dsp->pwr_lock);
483
484         ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, cs_ctl->cache, size);
485
486         if (!ret && copy_to_user(bytes, cs_ctl->cache, size))
487                 ret = -EFAULT;
488
489         mutex_unlock(&cs_ctl->dsp->pwr_lock);
490
491         return ret;
492 }
493
494 static int wm_coeff_get_acked(struct snd_kcontrol *kcontrol,
495                               struct snd_ctl_elem_value *ucontrol)
496 {
497         /*
498          * Although it's not useful to read an acked control, we must satisfy
499          * user-side assumptions that all controls are readable and that a
500          * write of the same value should be filtered out (it's valid to send
501          * the same event number again to the firmware). We therefore return 0,
502          * meaning "no event" so valid event numbers will always be a change
503          */
504         ucontrol->value.integer.value[0] = 0;
505
506         return 0;
507 }
508
509 static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
510 {
511         unsigned int out, rd, wr, vol;
512
513         if (len > ADSP_MAX_STD_CTRL_SIZE) {
514                 rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
515                 wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
516                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
517
518                 out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
519         } else {
520                 rd = SNDRV_CTL_ELEM_ACCESS_READ;
521                 wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
522                 vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
523
524                 out = 0;
525         }
526
527         if (in) {
528                 out |= rd;
529                 if (in & WMFW_CTL_FLAG_WRITEABLE)
530                         out |= wr;
531                 if (in & WMFW_CTL_FLAG_VOLATILE)
532                         out |= vol;
533         } else {
534                 out |= rd | wr | vol;
535         }
536
537         return out;
538 }
539
540 static void wm_adsp_ctl_work(struct work_struct *work)
541 {
542         struct wm_coeff_ctl *ctl = container_of(work,
543                                                 struct wm_coeff_ctl,
544                                                 work);
545         struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
546         struct wm_adsp *dsp = container_of(cs_ctl->dsp,
547                                            struct wm_adsp,
548                                            cs_dsp);
549         struct snd_kcontrol_new *kcontrol;
550
551         kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
552         if (!kcontrol)
553                 return;
554
555         kcontrol->name = ctl->name;
556         kcontrol->info = wm_coeff_info;
557         kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
558         kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
559         kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
560         kcontrol->access = wmfw_convert_flags(cs_ctl->flags, cs_ctl->len);
561
562         switch (cs_ctl->type) {
563         case WMFW_CTL_TYPE_ACKED:
564                 kcontrol->get = wm_coeff_get_acked;
565                 kcontrol->put = wm_coeff_put_acked;
566                 break;
567         default:
568                 if (kcontrol->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
569                         ctl->bytes_ext.max = cs_ctl->len;
570                         ctl->bytes_ext.get = wm_coeff_tlv_get;
571                         ctl->bytes_ext.put = wm_coeff_tlv_put;
572                 } else {
573                         kcontrol->get = wm_coeff_get;
574                         kcontrol->put = wm_coeff_put;
575                 }
576                 break;
577         }
578
579         snd_soc_add_component_controls(dsp->component, kcontrol, 1);
580
581         kfree(kcontrol);
582 }
583
584 static int wm_adsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl)
585 {
586         struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp);
587         struct cs_dsp *cs_dsp = &dsp->cs_dsp;
588         struct wm_coeff_ctl *ctl;
589         char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
590         const char *region_name;
591         int ret;
592
593         if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
594                 return 0;
595
596         region_name = cs_dsp_mem_region_name(cs_ctl->alg_region.type);
597         if (!region_name) {
598                 adsp_err(dsp, "Unknown region type: %d\n", cs_ctl->alg_region.type);
599                 return -EINVAL;
600         }
601
602         switch (cs_dsp->fw_ver) {
603         case 0:
604         case 1:
605                 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
606                                 "%s %s %x", cs_dsp->name, region_name,
607                                 cs_ctl->alg_region.alg);
608                 break;
609         case 2:
610                 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
611                                 "%s%c %.12s %x", cs_dsp->name, *region_name,
612                                 wm_adsp_fw_text[dsp->fw], cs_ctl->alg_region.alg);
613                 break;
614         default:
615                 ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
616                                 "%s %.12s %x", cs_dsp->name,
617                                 wm_adsp_fw_text[dsp->fw], cs_ctl->alg_region.alg);
618                 break;
619         }
620
621         if (cs_ctl->subname) {
622                 int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
623                 int skip = 0;
624
625                 if (dsp->component->name_prefix)
626                         avail -= strlen(dsp->component->name_prefix) + 1;
627
628                 /* Truncate the subname from the start if it is too long */
629                 if (cs_ctl->subname_len > avail)
630                         skip = cs_ctl->subname_len - avail;
631
632                 snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
633                          " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip);
634         }
635
636         ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
637         if (!ctl)
638                 return -ENOMEM;
639         ctl->cs_ctl = cs_ctl;
640
641         ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
642         if (!ctl->name) {
643                 ret = -ENOMEM;
644                 goto err_ctl;
645         }
646
647         cs_ctl->priv = ctl;
648
649         INIT_WORK(&ctl->work, wm_adsp_ctl_work);
650         schedule_work(&ctl->work);
651
652         return 0;
653
654 err_ctl:
655         kfree(ctl);
656
657         return ret;
658 }
659
660 static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
661 {
662         struct wm_coeff_ctl *ctl = cs_ctl->priv;
663
664         cancel_work_sync(&ctl->work);
665
666         kfree(ctl->name);
667         kfree(ctl);
668 }
669
670 int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
671                       unsigned int alg, void *buf, size_t len)
672 {
673         struct cs_dsp_coeff_ctl *cs_ctl;
674         struct wm_coeff_ctl *ctl;
675         struct snd_kcontrol *kcontrol;
676         char ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
677         int ret;
678
679         cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
680         if (!cs_ctl)
681                 return -EINVAL;
682
683         ctl = cs_ctl->priv;
684
685         if (len > cs_ctl->len)
686                 return -EINVAL;
687
688         ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
689         if (ret)
690                 return ret;
691
692         if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
693                 return 0;
694
695         if (dsp->component->name_prefix)
696                 snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s",
697                          dsp->component->name_prefix, ctl->name);
698         else
699                 snprintf(ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s",
700                          ctl->name);
701
702         kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl_name);
703         if (!kcontrol) {
704                 adsp_err(dsp, "Can't find kcontrol %s\n", ctl_name);
705                 return -EINVAL;
706         }
707
708         snd_ctl_notify(dsp->component->card->snd_card,
709                        SNDRV_CTL_EVENT_MASK_VALUE, &kcontrol->id);
710
711         return 0;
712 }
713 EXPORT_SYMBOL_GPL(wm_adsp_write_ctl);
714
715 int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
716                      unsigned int alg, void *buf, size_t len)
717 {
718         struct cs_dsp_coeff_ctl *cs_ctl;
719
720         cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
721         if (!cs_ctl)
722                 return -EINVAL;
723
724         if (len > cs_ctl->len)
725                 return -EINVAL;
726
727         return cs_dsp_coeff_read_ctrl(cs_ctl, 0, buf, len);
728 }
729 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
730
731 static void wm_adsp_release_firmware_files(struct wm_adsp *dsp,
732                                            const struct firmware *wmfw_firmware,
733                                            char *wmfw_filename,
734                                            const struct firmware *coeff_firmware,
735                                            char *coeff_filename)
736 {
737         if (wmfw_firmware)
738                 release_firmware(wmfw_firmware);
739         kfree(wmfw_filename);
740
741         if (coeff_firmware)
742                 release_firmware(coeff_firmware);
743         kfree(coeff_filename);
744 }
745
746 static int wm_adsp_request_firmware_file(struct wm_adsp *dsp,
747                                          const struct firmware **firmware,
748                                          char **filename,
749                                          char *suffix)
750 {
751         struct cs_dsp *cs_dsp = &dsp->cs_dsp;
752         int ret = 0;
753
754         *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", dsp->part, dsp->fwf_name,
755                               wm_adsp_fw[dsp->fw].file, suffix);
756         if (*filename == NULL)
757                 return -ENOMEM;
758
759         ret = request_firmware(firmware, *filename, cs_dsp->dev);
760         if (ret != 0) {
761                 adsp_err(dsp, "Failed to request '%s'\n", *filename);
762                 kfree(*filename);
763                 *filename = NULL;
764         }
765
766         return ret;
767 }
768
769 static int wm_adsp_request_firmware_files(struct wm_adsp *dsp,
770                                           const struct firmware **wmfw_firmware,
771                                           char **wmfw_filename,
772                                           const struct firmware **coeff_firmware,
773                                           char **coeff_filename)
774 {
775         int ret = 0;
776
777         ret = wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, "wmfw");
778         if (ret != 0)
779                 return ret;
780
781         wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, "bin");
782
783         return 0;
784 }
785
786 static int wm_adsp_common_init(struct wm_adsp *dsp)
787 {
788         char *p;
789
790         INIT_LIST_HEAD(&dsp->compr_list);
791         INIT_LIST_HEAD(&dsp->buffer_list);
792
793         if (!dsp->fwf_name) {
794                 p = devm_kstrdup(dsp->cs_dsp.dev, dsp->cs_dsp.name, GFP_KERNEL);
795                 if (!p)
796                         return -ENOMEM;
797
798                 dsp->fwf_name = p;
799                 for (; *p != 0; ++p)
800                         *p = tolower(*p);
801         }
802
803         return 0;
804 }
805
806 int wm_adsp1_init(struct wm_adsp *dsp)
807 {
808         int ret;
809
810         dsp->cs_dsp.client_ops = &wm_adsp1_client_ops;
811
812         ret = cs_dsp_adsp1_init(&dsp->cs_dsp);
813         if (ret)
814                 return ret;
815
816         return wm_adsp_common_init(dsp);
817 }
818 EXPORT_SYMBOL_GPL(wm_adsp1_init);
819
820 int wm_adsp1_event(struct snd_soc_dapm_widget *w,
821                    struct snd_kcontrol *kcontrol,
822                    int event)
823 {
824         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
825         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
826         struct wm_adsp *dsp = &dsps[w->shift];
827         int ret = 0;
828         char *wmfw_filename = NULL;
829         const struct firmware *wmfw_firmware = NULL;
830         char *coeff_filename = NULL;
831         const struct firmware *coeff_firmware = NULL;
832
833         dsp->component = component;
834
835         switch (event) {
836         case SND_SOC_DAPM_POST_PMU:
837                 ret = wm_adsp_request_firmware_files(dsp,
838                                                      &wmfw_firmware, &wmfw_filename,
839                                                      &coeff_firmware, &coeff_filename);
840                 if (ret)
841                         break;
842
843                 ret = cs_dsp_adsp1_power_up(&dsp->cs_dsp,
844                                             wmfw_firmware, wmfw_filename,
845                                             coeff_firmware, coeff_filename,
846                                             wm_adsp_fw_text[dsp->fw]);
847
848                 wm_adsp_release_firmware_files(dsp,
849                                                wmfw_firmware, wmfw_filename,
850                                                coeff_firmware, coeff_filename);
851                 break;
852         case SND_SOC_DAPM_PRE_PMD:
853                 cs_dsp_adsp1_power_down(&dsp->cs_dsp);
854                 break;
855         default:
856                 break;
857         }
858
859         return ret;
860 }
861 EXPORT_SYMBOL_GPL(wm_adsp1_event);
862
863 int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget *w, unsigned int freq)
864 {
865         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
866         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
867         struct wm_adsp *dsp = &dsps[w->shift];
868
869         return cs_dsp_set_dspclk(&dsp->cs_dsp, freq);
870 }
871 EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk);
872
873 int wm_adsp2_preloader_get(struct snd_kcontrol *kcontrol,
874                            struct snd_ctl_elem_value *ucontrol)
875 {
876         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
877         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
878         struct soc_mixer_control *mc =
879                 (struct soc_mixer_control *)kcontrol->private_value;
880         struct wm_adsp *dsp = &dsps[mc->shift - 1];
881
882         ucontrol->value.integer.value[0] = dsp->preloaded;
883
884         return 0;
885 }
886 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get);
887
888 int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
889                            struct snd_ctl_elem_value *ucontrol)
890 {
891         struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
892         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
893         struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
894         struct soc_mixer_control *mc =
895                 (struct soc_mixer_control *)kcontrol->private_value;
896         struct wm_adsp *dsp = &dsps[mc->shift - 1];
897         char preload[32];
898
899         snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name);
900
901         dsp->preloaded = ucontrol->value.integer.value[0];
902
903         if (ucontrol->value.integer.value[0])
904                 snd_soc_component_force_enable_pin(component, preload);
905         else
906                 snd_soc_component_disable_pin(component, preload);
907
908         snd_soc_dapm_sync(dapm);
909
910         flush_work(&dsp->boot_work);
911
912         return 0;
913 }
914 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
915
916 static void wm_adsp_boot_work(struct work_struct *work)
917 {
918         struct wm_adsp *dsp = container_of(work,
919                                            struct wm_adsp,
920                                            boot_work);
921         int ret = 0;
922         char *wmfw_filename = NULL;
923         const struct firmware *wmfw_firmware = NULL;
924         char *coeff_filename = NULL;
925         const struct firmware *coeff_firmware = NULL;
926
927         ret = wm_adsp_request_firmware_files(dsp,
928                                              &wmfw_firmware, &wmfw_filename,
929                                              &coeff_firmware, &coeff_filename);
930         if (ret)
931                 return;
932
933         cs_dsp_power_up(&dsp->cs_dsp,
934                         wmfw_firmware, wmfw_filename,
935                         coeff_firmware, coeff_filename,
936                         wm_adsp_fw_text[dsp->fw]);
937
938         wm_adsp_release_firmware_files(dsp,
939                                        wmfw_firmware, wmfw_filename,
940                                        coeff_firmware, coeff_filename);
941 }
942
943 int wm_adsp_early_event(struct snd_soc_dapm_widget *w,
944                         struct snd_kcontrol *kcontrol, int event)
945 {
946         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
947         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
948         struct wm_adsp *dsp = &dsps[w->shift];
949
950         switch (event) {
951         case SND_SOC_DAPM_PRE_PMU:
952                 queue_work(system_unbound_wq, &dsp->boot_work);
953                 break;
954         case SND_SOC_DAPM_PRE_PMD:
955                 cs_dsp_power_down(&dsp->cs_dsp);
956                 break;
957         default:
958                 break;
959         }
960
961         return 0;
962 }
963 EXPORT_SYMBOL_GPL(wm_adsp_early_event);
964
965 static int wm_adsp_event_post_run(struct cs_dsp *cs_dsp)
966 {
967         struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp);
968
969         if (wm_adsp_fw[dsp->fw].num_caps != 0)
970                 return wm_adsp_buffer_init(dsp);
971
972         return 0;
973 }
974
975 static void wm_adsp_event_post_stop(struct cs_dsp *cs_dsp)
976 {
977         struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp);
978
979         if (wm_adsp_fw[dsp->fw].num_caps != 0)
980                 wm_adsp_buffer_free(dsp);
981
982         dsp->fatal_error = false;
983 }
984
985 int wm_adsp_event(struct snd_soc_dapm_widget *w,
986                   struct snd_kcontrol *kcontrol, int event)
987 {
988         struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
989         struct wm_adsp *dsps = snd_soc_component_get_drvdata(component);
990         struct wm_adsp *dsp = &dsps[w->shift];
991         int ret = 0;
992
993         switch (event) {
994         case SND_SOC_DAPM_POST_PMU:
995                 flush_work(&dsp->boot_work);
996                 ret = cs_dsp_run(&dsp->cs_dsp);
997                 break;
998         case SND_SOC_DAPM_PRE_PMD:
999                 cs_dsp_stop(&dsp->cs_dsp);
1000                 break;
1001         default:
1002                 break;
1003         }
1004
1005         return ret;
1006 }
1007 EXPORT_SYMBOL_GPL(wm_adsp_event);
1008
1009 int wm_adsp2_component_probe(struct wm_adsp *dsp, struct snd_soc_component *component)
1010 {
1011         char preload[32];
1012
1013         snprintf(preload, ARRAY_SIZE(preload), "%s Preload", dsp->cs_dsp.name);
1014         snd_soc_component_disable_pin(component, preload);
1015
1016         cs_dsp_init_debugfs(&dsp->cs_dsp, component->debugfs_root);
1017
1018         dsp->component = component;
1019
1020         return 0;
1021 }
1022 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
1023
1024 int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component)
1025 {
1026         cs_dsp_cleanup_debugfs(&dsp->cs_dsp);
1027
1028         return 0;
1029 }
1030 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove);
1031
1032 int wm_adsp2_init(struct wm_adsp *dsp)
1033 {
1034         int ret;
1035
1036         INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
1037
1038         dsp->sys_config_size = sizeof(struct wm_adsp_system_config_xm_hdr);
1039         dsp->cs_dsp.client_ops = &wm_adsp2_client_ops;
1040
1041         ret = cs_dsp_adsp2_init(&dsp->cs_dsp);
1042         if (ret)
1043                 return ret;
1044
1045         return wm_adsp_common_init(dsp);
1046 }
1047 EXPORT_SYMBOL_GPL(wm_adsp2_init);
1048
1049 int wm_halo_init(struct wm_adsp *dsp)
1050 {
1051         int ret;
1052
1053         INIT_WORK(&dsp->boot_work, wm_adsp_boot_work);
1054
1055         dsp->sys_config_size = sizeof(struct wm_halo_system_config_xm_hdr);
1056         dsp->cs_dsp.client_ops = &wm_adsp2_client_ops;
1057
1058         ret = cs_dsp_halo_init(&dsp->cs_dsp);
1059         if (ret)
1060                 return ret;
1061
1062         return wm_adsp_common_init(dsp);
1063 }
1064 EXPORT_SYMBOL_GPL(wm_halo_init);
1065
1066 void wm_adsp2_remove(struct wm_adsp *dsp)
1067 {
1068         cs_dsp_remove(&dsp->cs_dsp);
1069 }
1070 EXPORT_SYMBOL_GPL(wm_adsp2_remove);
1071
1072 static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
1073 {
1074         return compr->buf != NULL;
1075 }
1076
1077 static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
1078 {
1079         struct wm_adsp_compr_buf *buf = NULL, *tmp;
1080
1081         if (compr->dsp->fatal_error)
1082                 return -EINVAL;
1083
1084         list_for_each_entry(tmp, &compr->dsp->buffer_list, list) {
1085                 if (!tmp->name || !strcmp(compr->name, tmp->name)) {
1086                         buf = tmp;
1087                         break;
1088                 }
1089         }
1090
1091         if (!buf)
1092                 return -EINVAL;
1093
1094         compr->buf = buf;
1095         buf->compr = compr;
1096
1097         return 0;
1098 }
1099
1100 static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
1101 {
1102         if (!compr)
1103                 return;
1104
1105         /* Wake the poll so it can see buffer is no longer attached */
1106         if (compr->stream)
1107                 snd_compr_fragment_elapsed(compr->stream);
1108
1109         if (wm_adsp_compr_attached(compr)) {
1110                 compr->buf->compr = NULL;
1111                 compr->buf = NULL;
1112         }
1113 }
1114
1115 int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
1116 {
1117         struct wm_adsp_compr *compr, *tmp;
1118         struct snd_soc_pcm_runtime *rtd = stream->private_data;
1119         int ret = 0;
1120
1121         mutex_lock(&dsp->cs_dsp.pwr_lock);
1122
1123         if (wm_adsp_fw[dsp->fw].num_caps == 0) {
1124                 adsp_err(dsp, "%s: Firmware does not support compressed API\n",
1125                          asoc_rtd_to_codec(rtd, 0)->name);
1126                 ret = -ENXIO;
1127                 goto out;
1128         }
1129
1130         if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
1131                 adsp_err(dsp, "%s: Firmware does not support stream direction\n",
1132                          asoc_rtd_to_codec(rtd, 0)->name);
1133                 ret = -EINVAL;
1134                 goto out;
1135         }
1136
1137         list_for_each_entry(tmp, &dsp->compr_list, list) {
1138                 if (!strcmp(tmp->name, asoc_rtd_to_codec(rtd, 0)->name)) {
1139                         adsp_err(dsp, "%s: Only a single stream supported per dai\n",
1140                                  asoc_rtd_to_codec(rtd, 0)->name);
1141                         ret = -EBUSY;
1142                         goto out;
1143                 }
1144         }
1145
1146         compr = kzalloc(sizeof(*compr), GFP_KERNEL);
1147         if (!compr) {
1148                 ret = -ENOMEM;
1149                 goto out;
1150         }
1151
1152         compr->dsp = dsp;
1153         compr->stream = stream;
1154         compr->name = asoc_rtd_to_codec(rtd, 0)->name;
1155
1156         list_add_tail(&compr->list, &dsp->compr_list);
1157
1158         stream->runtime->private_data = compr;
1159
1160 out:
1161         mutex_unlock(&dsp->cs_dsp.pwr_lock);
1162
1163         return ret;
1164 }
1165 EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
1166
1167 int wm_adsp_compr_free(struct snd_soc_component *component,
1168                        struct snd_compr_stream *stream)
1169 {
1170         struct wm_adsp_compr *compr = stream->runtime->private_data;
1171         struct wm_adsp *dsp = compr->dsp;
1172
1173         mutex_lock(&dsp->cs_dsp.pwr_lock);
1174
1175         wm_adsp_compr_detach(compr);
1176         list_del(&compr->list);
1177
1178         kfree(compr->raw_buf);
1179         kfree(compr);
1180
1181         mutex_unlock(&dsp->cs_dsp.pwr_lock);
1182
1183         return 0;
1184 }
1185 EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
1186
1187 static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
1188                                       struct snd_compr_params *params)
1189 {
1190         struct wm_adsp_compr *compr = stream->runtime->private_data;
1191         struct wm_adsp *dsp = compr->dsp;
1192         const struct wm_adsp_fw_caps *caps;
1193         const struct snd_codec_desc *desc;
1194         int i, j;
1195
1196         if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
1197             params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
1198             params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
1199             params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
1200             params->buffer.fragment_size % CS_DSP_DATA_WORD_SIZE) {
1201                 compr_err(compr, "Invalid buffer fragsize=%d fragments=%d\n",
1202                           params->buffer.fragment_size,
1203                           params->buffer.fragments);
1204
1205                 return -EINVAL;
1206         }
1207
1208         for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
1209                 caps = &wm_adsp_fw[dsp->fw].caps[i];
1210                 desc = &caps->desc;
1211
1212                 if (caps->id != params->codec.id)
1213                         continue;
1214
1215                 if (stream->direction == SND_COMPRESS_PLAYBACK) {
1216                         if (desc->max_ch < params->codec.ch_out)
1217                                 continue;
1218                 } else {
1219                         if (desc->max_ch < params->codec.ch_in)
1220                                 continue;
1221                 }
1222
1223                 if (!(desc->formats & (1 << params->codec.format)))
1224                         continue;
1225
1226                 for (j = 0; j < desc->num_sample_rates; ++j)
1227                         if (desc->sample_rates[j] == params->codec.sample_rate)
1228                                 return 0;
1229         }
1230
1231         compr_err(compr, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
1232                   params->codec.id, params->codec.ch_in, params->codec.ch_out,
1233                   params->codec.sample_rate, params->codec.format);
1234         return -EINVAL;
1235 }
1236
1237 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
1238 {
1239         return compr->size.fragment_size / CS_DSP_DATA_WORD_SIZE;
1240 }
1241
1242 int wm_adsp_compr_set_params(struct snd_soc_component *component,
1243                              struct snd_compr_stream *stream,
1244                              struct snd_compr_params *params)
1245 {
1246         struct wm_adsp_compr *compr = stream->runtime->private_data;
1247         unsigned int size;
1248         int ret;
1249
1250         ret = wm_adsp_compr_check_params(stream, params);
1251         if (ret)
1252                 return ret;
1253
1254         compr->size = params->buffer;
1255
1256         compr_dbg(compr, "fragment_size=%d fragments=%d\n",
1257                   compr->size.fragment_size, compr->size.fragments);
1258
1259         size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
1260         compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
1261         if (!compr->raw_buf)
1262                 return -ENOMEM;
1263
1264         compr->sample_rate = params->codec.sample_rate;
1265
1266         return 0;
1267 }
1268 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
1269
1270 int wm_adsp_compr_get_caps(struct snd_soc_component *component,
1271                            struct snd_compr_stream *stream,
1272                            struct snd_compr_caps *caps)
1273 {
1274         struct wm_adsp_compr *compr = stream->runtime->private_data;
1275         int fw = compr->dsp->fw;
1276         int i;
1277
1278         if (wm_adsp_fw[fw].caps) {
1279                 for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
1280                         caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
1281
1282                 caps->num_codecs = i;
1283                 caps->direction = wm_adsp_fw[fw].compr_direction;
1284
1285                 caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
1286                 caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
1287                 caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
1288                 caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
1289         }
1290
1291         return 0;
1292 }
1293 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
1294
1295 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
1296                                       unsigned int field_offset, u32 *data)
1297 {
1298         return cs_dsp_read_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type,
1299                                      buf->host_buf_ptr + field_offset, data);
1300 }
1301
1302 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
1303                                        unsigned int field_offset, u32 data)
1304 {
1305         return cs_dsp_write_data_word(&buf->dsp->cs_dsp, buf->host_buf_mem_type,
1306                                       buf->host_buf_ptr + field_offset,
1307                                       data);
1308 }
1309
1310 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
1311 {
1312         const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
1313         struct wm_adsp_buffer_region *region;
1314         u32 offset = 0;
1315         int i, ret;
1316
1317         buf->regions = kcalloc(caps->num_regions, sizeof(*buf->regions),
1318                                GFP_KERNEL);
1319         if (!buf->regions)
1320                 return -ENOMEM;
1321
1322         for (i = 0; i < caps->num_regions; ++i) {
1323                 region = &buf->regions[i];
1324
1325                 region->offset = offset;
1326                 region->mem_type = caps->region_defs[i].mem_type;
1327
1328                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
1329                                           &region->base_addr);
1330                 if (ret < 0)
1331                         return ret;
1332
1333                 ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
1334                                           &offset);
1335                 if (ret < 0)
1336                         return ret;
1337
1338                 region->cumulative_size = offset;
1339
1340                 compr_dbg(buf,
1341                           "region=%d type=%d base=%08x off=%08x size=%08x\n",
1342                           i, region->mem_type, region->base_addr,
1343                           region->offset, region->cumulative_size);
1344         }
1345
1346         return 0;
1347 }
1348
1349 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
1350 {
1351         buf->irq_count = 0xFFFFFFFF;
1352         buf->read_index = -1;
1353         buf->avail = 0;
1354 }
1355
1356 static struct wm_adsp_compr_buf *wm_adsp_buffer_alloc(struct wm_adsp *dsp)
1357 {
1358         struct wm_adsp_compr_buf *buf;
1359
1360         buf = kzalloc(sizeof(*buf), GFP_KERNEL);
1361         if (!buf)
1362                 return NULL;
1363
1364         buf->dsp = dsp;
1365
1366         wm_adsp_buffer_clear(buf);
1367
1368         list_add_tail(&buf->list, &dsp->buffer_list);
1369
1370         return buf;
1371 }
1372
1373 static int wm_adsp_buffer_parse_legacy(struct wm_adsp *dsp)
1374 {
1375         struct cs_dsp_alg_region *alg_region;
1376         struct wm_adsp_compr_buf *buf;
1377         u32 xmalg, addr, magic;
1378         int i, ret;
1379
1380         alg_region = cs_dsp_find_alg_region(&dsp->cs_dsp, WMFW_ADSP2_XM, dsp->cs_dsp.fw_id);
1381         if (!alg_region) {
1382                 adsp_err(dsp, "No algorithm region found\n");
1383                 return -EINVAL;
1384         }
1385
1386         buf = wm_adsp_buffer_alloc(dsp);
1387         if (!buf)
1388                 return -ENOMEM;
1389
1390         xmalg = dsp->sys_config_size / sizeof(__be32);
1391
1392         addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
1393         ret = cs_dsp_read_data_word(&dsp->cs_dsp, WMFW_ADSP2_XM, addr, &magic);
1394         if (ret < 0)
1395                 return ret;
1396
1397         if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
1398                 return -ENODEV;
1399
1400         addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
1401         for (i = 0; i < 5; ++i) {
1402                 ret = cs_dsp_read_data_word(&dsp->cs_dsp, WMFW_ADSP2_XM, addr,
1403                                             &buf->host_buf_ptr);
1404                 if (ret < 0)
1405                         return ret;
1406
1407                 if (buf->host_buf_ptr)
1408                         break;
1409
1410                 usleep_range(1000, 2000);
1411         }
1412
1413         if (!buf->host_buf_ptr)
1414                 return -EIO;
1415
1416         buf->host_buf_mem_type = WMFW_ADSP2_XM;
1417
1418         ret = wm_adsp_buffer_populate(buf);
1419         if (ret < 0)
1420                 return ret;
1421
1422         compr_dbg(buf, "legacy host_buf_ptr=%x\n", buf->host_buf_ptr);
1423
1424         return 0;
1425 }
1426
1427 static int wm_adsp_buffer_parse_coeff(struct cs_dsp_coeff_ctl *cs_ctl)
1428 {
1429         struct wm_adsp_host_buf_coeff_v1 coeff_v1;
1430         struct wm_adsp_compr_buf *buf;
1431         struct wm_adsp *dsp = container_of(cs_ctl->dsp, struct wm_adsp, cs_dsp);
1432         unsigned int version;
1433         int ret, i;
1434
1435         for (i = 0; i < 5; ++i) {
1436                 ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, &coeff_v1, sizeof(coeff_v1));
1437                 if (ret < 0)
1438                         return ret;
1439
1440                 if (coeff_v1.host_buf_ptr)
1441                         break;
1442
1443                 usleep_range(1000, 2000);
1444         }
1445
1446         if (!coeff_v1.host_buf_ptr) {
1447                 adsp_err(dsp, "Failed to acquire host buffer\n");
1448                 return -EIO;
1449         }
1450
1451         buf = wm_adsp_buffer_alloc(dsp);
1452         if (!buf)
1453                 return -ENOMEM;
1454
1455         buf->host_buf_mem_type = cs_ctl->alg_region.type;
1456         buf->host_buf_ptr = be32_to_cpu(coeff_v1.host_buf_ptr);
1457
1458         ret = wm_adsp_buffer_populate(buf);
1459         if (ret < 0)
1460                 return ret;
1461
1462         /*
1463          * v0 host_buffer coefficients didn't have versioning, so if the
1464          * control is one word, assume version 0.
1465          */
1466         if (cs_ctl->len == 4) {
1467                 compr_dbg(buf, "host_buf_ptr=%x\n", buf->host_buf_ptr);
1468                 return 0;
1469         }
1470
1471         version = be32_to_cpu(coeff_v1.versions) & HOST_BUF_COEFF_COMPAT_VER_MASK;
1472         version >>= HOST_BUF_COEFF_COMPAT_VER_SHIFT;
1473
1474         if (version > HOST_BUF_COEFF_SUPPORTED_COMPAT_VER) {
1475                 adsp_err(dsp,
1476                          "Host buffer coeff ver %u > supported version %u\n",
1477                          version, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER);
1478                 return -EINVAL;
1479         }
1480
1481         cs_dsp_remove_padding((u32 *)&coeff_v1.name, ARRAY_SIZE(coeff_v1.name));
1482
1483         buf->name = kasprintf(GFP_KERNEL, "%s-dsp-%s", dsp->part,
1484                               (char *)&coeff_v1.name);
1485
1486         compr_dbg(buf, "host_buf_ptr=%x coeff version %u\n",
1487                   buf->host_buf_ptr, version);
1488
1489         return version;
1490 }
1491
1492 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
1493 {
1494         struct cs_dsp_coeff_ctl *cs_ctl;
1495         int ret;
1496
1497         list_for_each_entry(cs_ctl, &dsp->cs_dsp.ctl_list, list) {
1498                 if (cs_ctl->type != WMFW_CTL_TYPE_HOST_BUFFER)
1499                         continue;
1500
1501                 if (!cs_ctl->enabled)
1502                         continue;
1503
1504                 ret = wm_adsp_buffer_parse_coeff(cs_ctl);
1505                 if (ret < 0) {
1506                         adsp_err(dsp, "Failed to parse coeff: %d\n", ret);
1507                         goto error;
1508                 } else if (ret == 0) {
1509                         /* Only one buffer supported for version 0 */
1510                         return 0;
1511                 }
1512         }
1513
1514         if (list_empty(&dsp->buffer_list)) {
1515                 /* Fall back to legacy support */
1516                 ret = wm_adsp_buffer_parse_legacy(dsp);
1517                 if (ret) {
1518                         adsp_err(dsp, "Failed to parse legacy: %d\n", ret);
1519                         goto error;
1520                 }
1521         }
1522
1523         return 0;
1524
1525 error:
1526         wm_adsp_buffer_free(dsp);
1527         return ret;
1528 }
1529
1530 static int wm_adsp_buffer_free(struct wm_adsp *dsp)
1531 {
1532         struct wm_adsp_compr_buf *buf, *tmp;
1533
1534         list_for_each_entry_safe(buf, tmp, &dsp->buffer_list, list) {
1535                 wm_adsp_compr_detach(buf->compr);
1536
1537                 kfree(buf->name);
1538                 kfree(buf->regions);
1539                 list_del(&buf->list);
1540                 kfree(buf);
1541         }
1542
1543         return 0;
1544 }
1545
1546 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
1547 {
1548         int ret;
1549
1550         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
1551         if (ret < 0) {
1552                 compr_err(buf, "Failed to check buffer error: %d\n", ret);
1553                 return ret;
1554         }
1555         if (buf->error != 0) {
1556                 compr_err(buf, "Buffer error occurred: %d\n", buf->error);
1557                 return -EIO;
1558         }
1559
1560         return 0;
1561 }
1562
1563 int wm_adsp_compr_trigger(struct snd_soc_component *component,
1564                           struct snd_compr_stream *stream, int cmd)
1565 {
1566         struct wm_adsp_compr *compr = stream->runtime->private_data;
1567         struct wm_adsp *dsp = compr->dsp;
1568         int ret = 0;
1569
1570         compr_dbg(compr, "Trigger: %d\n", cmd);
1571
1572         mutex_lock(&dsp->cs_dsp.pwr_lock);
1573
1574         switch (cmd) {
1575         case SNDRV_PCM_TRIGGER_START:
1576                 if (!wm_adsp_compr_attached(compr)) {
1577                         ret = wm_adsp_compr_attach(compr);
1578                         if (ret < 0) {
1579                                 compr_err(compr, "Failed to link buffer and stream: %d\n",
1580                                           ret);
1581                                 break;
1582                         }
1583                 }
1584
1585                 ret = wm_adsp_buffer_get_error(compr->buf);
1586                 if (ret < 0)
1587                         break;
1588
1589                 /* Trigger the IRQ at one fragment of data */
1590                 ret = wm_adsp_buffer_write(compr->buf,
1591                                            HOST_BUFFER_FIELD(high_water_mark),
1592                                            wm_adsp_compr_frag_words(compr));
1593                 if (ret < 0) {
1594                         compr_err(compr, "Failed to set high water mark: %d\n",
1595                                   ret);
1596                         break;
1597                 }
1598                 break;
1599         case SNDRV_PCM_TRIGGER_STOP:
1600                 if (wm_adsp_compr_attached(compr))
1601                         wm_adsp_buffer_clear(compr->buf);
1602                 break;
1603         default:
1604                 ret = -EINVAL;
1605                 break;
1606         }
1607
1608         mutex_unlock(&dsp->cs_dsp.pwr_lock);
1609
1610         return ret;
1611 }
1612 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
1613
1614 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
1615 {
1616         int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
1617
1618         return buf->regions[last_region].cumulative_size;
1619 }
1620
1621 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
1622 {
1623         u32 next_read_index, next_write_index;
1624         int write_index, read_index, avail;
1625         int ret;
1626
1627         /* Only sync read index if we haven't already read a valid index */
1628         if (buf->read_index < 0) {
1629                 ret = wm_adsp_buffer_read(buf,
1630                                 HOST_BUFFER_FIELD(next_read_index),
1631                                 &next_read_index);
1632                 if (ret < 0)
1633                         return ret;
1634
1635                 read_index = sign_extend32(next_read_index, 23);
1636
1637                 if (read_index < 0) {
1638                         compr_dbg(buf, "Avail check on unstarted stream\n");
1639                         return 0;
1640                 }
1641
1642                 buf->read_index = read_index;
1643         }
1644
1645         ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
1646                         &next_write_index);
1647         if (ret < 0)
1648                 return ret;
1649
1650         write_index = sign_extend32(next_write_index, 23);
1651
1652         avail = write_index - buf->read_index;
1653         if (avail < 0)
1654                 avail += wm_adsp_buffer_size(buf);
1655
1656         compr_dbg(buf, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
1657                   buf->read_index, write_index, avail * CS_DSP_DATA_WORD_SIZE);
1658
1659         buf->avail = avail;
1660
1661         return 0;
1662 }
1663
1664 int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
1665 {
1666         struct wm_adsp_compr_buf *buf;
1667         struct wm_adsp_compr *compr;
1668         int ret = 0;
1669
1670         mutex_lock(&dsp->cs_dsp.pwr_lock);
1671
1672         if (list_empty(&dsp->buffer_list)) {
1673                 ret = -ENODEV;
1674                 goto out;
1675         }
1676
1677         adsp_dbg(dsp, "Handling buffer IRQ\n");
1678
1679         list_for_each_entry(buf, &dsp->buffer_list, list) {
1680                 compr = buf->compr;
1681
1682                 ret = wm_adsp_buffer_get_error(buf);
1683                 if (ret < 0)
1684                         goto out_notify; /* Wake poll to report error */
1685
1686                 ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
1687                                           &buf->irq_count);
1688                 if (ret < 0) {
1689                         compr_err(buf, "Failed to get irq_count: %d\n", ret);
1690                         goto out;
1691                 }
1692
1693                 ret = wm_adsp_buffer_update_avail(buf);
1694                 if (ret < 0) {
1695                         compr_err(buf, "Error reading avail: %d\n", ret);
1696                         goto out;
1697                 }
1698
1699                 if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
1700                         ret = WM_ADSP_COMPR_VOICE_TRIGGER;
1701
1702 out_notify:
1703                 if (compr && compr->stream)
1704                         snd_compr_fragment_elapsed(compr->stream);
1705         }
1706
1707 out:
1708         mutex_unlock(&dsp->cs_dsp.pwr_lock);
1709
1710         return ret;
1711 }
1712 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
1713
1714 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
1715 {
1716         if (buf->irq_count & 0x01)
1717                 return 0;
1718
1719         compr_dbg(buf, "Enable IRQ(0x%x) for next fragment\n", buf->irq_count);
1720
1721         buf->irq_count |= 0x01;
1722
1723         return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
1724                                     buf->irq_count);
1725 }
1726
1727 int wm_adsp_compr_pointer(struct snd_soc_component *component,
1728                           struct snd_compr_stream *stream,
1729                           struct snd_compr_tstamp *tstamp)
1730 {
1731         struct wm_adsp_compr *compr = stream->runtime->private_data;
1732         struct wm_adsp *dsp = compr->dsp;
1733         struct wm_adsp_compr_buf *buf;
1734         int ret = 0;
1735
1736         compr_dbg(compr, "Pointer request\n");
1737
1738         mutex_lock(&dsp->cs_dsp.pwr_lock);
1739
1740         buf = compr->buf;
1741
1742         if (dsp->fatal_error || !buf || buf->error) {
1743                 snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
1744                 ret = -EIO;
1745                 goto out;
1746         }
1747
1748         if (buf->avail < wm_adsp_compr_frag_words(compr)) {
1749                 ret = wm_adsp_buffer_update_avail(buf);
1750                 if (ret < 0) {
1751                         compr_err(compr, "Error reading avail: %d\n", ret);
1752                         goto out;
1753                 }
1754
1755                 /*
1756                  * If we really have less than 1 fragment available tell the
1757                  * DSP to inform us once a whole fragment is available.
1758                  */
1759                 if (buf->avail < wm_adsp_compr_frag_words(compr)) {
1760                         ret = wm_adsp_buffer_get_error(buf);
1761                         if (ret < 0) {
1762                                 if (buf->error)
1763                                         snd_compr_stop_error(stream,
1764                                                         SNDRV_PCM_STATE_XRUN);
1765                                 goto out;
1766                         }
1767
1768                         ret = wm_adsp_buffer_reenable_irq(buf);
1769                         if (ret < 0) {
1770                                 compr_err(compr, "Failed to re-enable buffer IRQ: %d\n",
1771                                           ret);
1772                                 goto out;
1773                         }
1774                 }
1775         }
1776
1777         tstamp->copied_total = compr->copied_total;
1778         tstamp->copied_total += buf->avail * CS_DSP_DATA_WORD_SIZE;
1779         tstamp->sampling_rate = compr->sample_rate;
1780
1781 out:
1782         mutex_unlock(&dsp->cs_dsp.pwr_lock);
1783
1784         return ret;
1785 }
1786 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
1787
1788 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
1789 {
1790         struct wm_adsp_compr_buf *buf = compr->buf;
1791         unsigned int adsp_addr;
1792         int mem_type, nwords, max_read;
1793         int i, ret;
1794
1795         /* Calculate read parameters */
1796         for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
1797                 if (buf->read_index < buf->regions[i].cumulative_size)
1798                         break;
1799
1800         if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
1801                 return -EINVAL;
1802
1803         mem_type = buf->regions[i].mem_type;
1804         adsp_addr = buf->regions[i].base_addr +
1805                     (buf->read_index - buf->regions[i].offset);
1806
1807         max_read = wm_adsp_compr_frag_words(compr);
1808         nwords = buf->regions[i].cumulative_size - buf->read_index;
1809
1810         if (nwords > target)
1811                 nwords = target;
1812         if (nwords > buf->avail)
1813                 nwords = buf->avail;
1814         if (nwords > max_read)
1815                 nwords = max_read;
1816         if (!nwords)
1817                 return 0;
1818
1819         /* Read data from DSP */
1820         ret = cs_dsp_read_raw_data_block(&buf->dsp->cs_dsp, mem_type, adsp_addr,
1821                                          nwords, (__be32 *)compr->raw_buf);
1822         if (ret < 0)
1823                 return ret;
1824
1825         cs_dsp_remove_padding(compr->raw_buf, nwords);
1826
1827         /* update read index to account for words read */
1828         buf->read_index += nwords;
1829         if (buf->read_index == wm_adsp_buffer_size(buf))
1830                 buf->read_index = 0;
1831
1832         ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
1833                                    buf->read_index);
1834         if (ret < 0)
1835                 return ret;
1836
1837         /* update avail to account for words read */
1838         buf->avail -= nwords;
1839
1840         return nwords;
1841 }
1842
1843 static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
1844                               char __user *buf, size_t count)
1845 {
1846         struct wm_adsp *dsp = compr->dsp;
1847         int ntotal = 0;
1848         int nwords, nbytes;
1849
1850         compr_dbg(compr, "Requested read of %zu bytes\n", count);
1851
1852         if (dsp->fatal_error || !compr->buf || compr->buf->error) {
1853                 snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
1854                 return -EIO;
1855         }
1856
1857         count /= CS_DSP_DATA_WORD_SIZE;
1858
1859         do {
1860                 nwords = wm_adsp_buffer_capture_block(compr, count);
1861                 if (nwords < 0) {
1862                         compr_err(compr, "Failed to capture block: %d\n",
1863                                   nwords);
1864                         return nwords;
1865                 }
1866
1867                 nbytes = nwords * CS_DSP_DATA_WORD_SIZE;
1868
1869                 compr_dbg(compr, "Read %d bytes\n", nbytes);
1870
1871                 if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
1872                         compr_err(compr, "Failed to copy data to user: %d, %d\n",
1873                                   ntotal, nbytes);
1874                         return -EFAULT;
1875                 }
1876
1877                 count -= nwords;
1878                 ntotal += nbytes;
1879         } while (nwords > 0 && count > 0);
1880
1881         compr->copied_total += ntotal;
1882
1883         return ntotal;
1884 }
1885
1886 int wm_adsp_compr_copy(struct snd_soc_component *component,
1887                        struct snd_compr_stream *stream, char __user *buf,
1888                        size_t count)
1889 {
1890         struct wm_adsp_compr *compr = stream->runtime->private_data;
1891         struct wm_adsp *dsp = compr->dsp;
1892         int ret;
1893
1894         mutex_lock(&dsp->cs_dsp.pwr_lock);
1895
1896         if (stream->direction == SND_COMPRESS_CAPTURE)
1897                 ret = wm_adsp_compr_read(compr, buf, count);
1898         else
1899                 ret = -ENOTSUPP;
1900
1901         mutex_unlock(&dsp->cs_dsp.pwr_lock);
1902
1903         return ret;
1904 }
1905 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
1906
1907 static void wm_adsp_fatal_error(struct cs_dsp *cs_dsp)
1908 {
1909         struct wm_adsp *dsp = container_of(cs_dsp, struct wm_adsp, cs_dsp);
1910         struct wm_adsp_compr *compr;
1911
1912         dsp->fatal_error = true;
1913
1914         list_for_each_entry(compr, &dsp->compr_list, list) {
1915                 if (compr->stream)
1916                         snd_compr_fragment_elapsed(compr->stream);
1917         }
1918 }
1919
1920 irqreturn_t wm_adsp2_bus_error(int irq, void *data)
1921 {
1922         struct wm_adsp *dsp = (struct wm_adsp *)data;
1923
1924         cs_dsp_adsp2_bus_error(&dsp->cs_dsp);
1925
1926         return IRQ_HANDLED;
1927 }
1928 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
1929
1930 irqreturn_t wm_halo_bus_error(int irq, void *data)
1931 {
1932         struct wm_adsp *dsp = (struct wm_adsp *)data;
1933
1934         cs_dsp_halo_bus_error(&dsp->cs_dsp);
1935
1936         return IRQ_HANDLED;
1937 }
1938 EXPORT_SYMBOL_GPL(wm_halo_bus_error);
1939
1940 irqreturn_t wm_halo_wdt_expire(int irq, void *data)
1941 {
1942         struct wm_adsp *dsp = data;
1943
1944         cs_dsp_halo_wdt_expire(&dsp->cs_dsp);
1945
1946         return IRQ_HANDLED;
1947 }
1948 EXPORT_SYMBOL_GPL(wm_halo_wdt_expire);
1949
1950 static const struct cs_dsp_client_ops wm_adsp1_client_ops = {
1951         .control_add = wm_adsp_control_add,
1952         .control_remove = wm_adsp_control_remove,
1953 };
1954
1955 static const struct cs_dsp_client_ops wm_adsp2_client_ops = {
1956         .control_add = wm_adsp_control_add,
1957         .control_remove = wm_adsp_control_remove,
1958         .post_run = wm_adsp_event_post_run,
1959         .post_stop = wm_adsp_event_post_stop,
1960         .watchdog_expired = wm_adsp_fatal_error,
1961 };
1962
1963 MODULE_LICENSE("GPL v2");