~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/wm_adsp.c

Version: ~ [ linux-6.4-rc3 ] ~ [ linux-6.3.4 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.30 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.113 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.180 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.243 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.283 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.315 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp