2 * wm_adsp.c -- Wolfson ADSP support
4 * Copyright 2012 Wolfson Microelectronics plc
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
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.
13 #include <linux/module.h>
14 #include <linux/moduleparam.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/firmware.h>
18 #include <linux/list.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/regmap.h>
22 #include <linux/regulator/consumer.h>
23 #include <linux/slab.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 #include <sound/jack.h>
29 #include <sound/initval.h>
30 #include <sound/tlv.h>
32 #include <linux/mfd/arizona/registers.h>
36 #define adsp_crit(_dsp, fmt, ...) \
37 dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
38 #define adsp_err(_dsp, fmt, ...) \
39 dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
40 #define adsp_warn(_dsp, fmt, ...) \
41 dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
42 #define adsp_info(_dsp, fmt, ...) \
43 dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
44 #define adsp_dbg(_dsp, fmt, ...) \
45 dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
47 #define ADSP1_CONTROL_1 0x00
48 #define ADSP1_CONTROL_2 0x02
49 #define ADSP1_CONTROL_3 0x03
50 #define ADSP1_CONTROL_4 0x04
51 #define ADSP1_CONTROL_5 0x06
52 #define ADSP1_CONTROL_6 0x07
53 #define ADSP1_CONTROL_7 0x08
54 #define ADSP1_CONTROL_8 0x09
55 #define ADSP1_CONTROL_9 0x0A
56 #define ADSP1_CONTROL_10 0x0B
57 #define ADSP1_CONTROL_11 0x0C
58 #define ADSP1_CONTROL_12 0x0D
59 #define ADSP1_CONTROL_13 0x0F
60 #define ADSP1_CONTROL_14 0x10
61 #define ADSP1_CONTROL_15 0x11
62 #define ADSP1_CONTROL_16 0x12
63 #define ADSP1_CONTROL_17 0x13
64 #define ADSP1_CONTROL_18 0x14
65 #define ADSP1_CONTROL_19 0x16
66 #define ADSP1_CONTROL_20 0x17
67 #define ADSP1_CONTROL_21 0x18
68 #define ADSP1_CONTROL_22 0x1A
69 #define ADSP1_CONTROL_23 0x1B
70 #define ADSP1_CONTROL_24 0x1C
71 #define ADSP1_CONTROL_25 0x1E
72 #define ADSP1_CONTROL_26 0x20
73 #define ADSP1_CONTROL_27 0x21
74 #define ADSP1_CONTROL_28 0x22
75 #define ADSP1_CONTROL_29 0x23
76 #define ADSP1_CONTROL_30 0x24
77 #define ADSP1_CONTROL_31 0x26
82 #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
83 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
84 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
90 #define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
91 #define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
92 #define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
93 #define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
94 #define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
95 #define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
96 #define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
97 #define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
98 #define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
99 #define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
100 #define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
101 #define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
102 #define ADSP1_START 0x0001 /* DSP1_START */
103 #define ADSP1_START_MASK 0x0001 /* DSP1_START */
104 #define ADSP1_START_SHIFT 0 /* DSP1_START */
105 #define ADSP1_START_WIDTH 1 /* DSP1_START */
110 #define ADSP1_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */
111 #define ADSP1_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */
112 #define ADSP1_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */
114 #define ADSP2_CONTROL 0x0
115 #define ADSP2_CLOCKING 0x1
116 #define ADSP2_STATUS1 0x4
117 #define ADSP2_WDMA_CONFIG_1 0x30
118 #define ADSP2_WDMA_CONFIG_2 0x31
119 #define ADSP2_RDMA_CONFIG_1 0x34
125 #define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */
126 #define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */
127 #define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */
128 #define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */
129 #define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
130 #define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
131 #define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
132 #define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
133 #define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
134 #define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
135 #define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
136 #define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
137 #define ADSP2_START 0x0001 /* DSP1_START */
138 #define ADSP2_START_MASK 0x0001 /* DSP1_START */
139 #define ADSP2_START_SHIFT 0 /* DSP1_START */
140 #define ADSP2_START_WIDTH 1 /* DSP1_START */
145 #define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */
146 #define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */
147 #define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */
152 #define ADSP2_RAM_RDY 0x0001
153 #define ADSP2_RAM_RDY_MASK 0x0001
154 #define ADSP2_RAM_RDY_SHIFT 0
155 #define ADSP2_RAM_RDY_WIDTH 1
158 struct list_head list
;
162 static struct wm_adsp_buf
*wm_adsp_buf_alloc(const void *src
, size_t len
,
163 struct list_head
*list
)
165 struct wm_adsp_buf
*buf
= kzalloc(sizeof(*buf
), GFP_KERNEL
);
170 buf
->buf
= kmemdup(src
, len
, GFP_KERNEL
| GFP_DMA
);
177 list_add_tail(&buf
->list
, list
);
182 static void wm_adsp_buf_free(struct list_head
*list
)
184 while (!list_empty(list
)) {
185 struct wm_adsp_buf
*buf
= list_first_entry(list
,
188 list_del(&buf
->list
);
194 #define WM_ADSP_NUM_FW 4
196 static const char *wm_adsp_fw_text
[WM_ADSP_NUM_FW
] = {
197 "MBC/VSS", "Tx", "Tx Speaker", "Rx ANC"
202 } wm_adsp_fw
[WM_ADSP_NUM_FW
] = {
203 { .file
= "mbc-vss" },
205 { .file
= "tx-spk" },
206 { .file
= "rx-anc" },
209 static int wm_adsp_fw_get(struct snd_kcontrol
*kcontrol
,
210 struct snd_ctl_elem_value
*ucontrol
)
212 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
213 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
214 struct wm_adsp
*adsp
= snd_soc_codec_get_drvdata(codec
);
216 ucontrol
->value
.integer
.value
[0] = adsp
[e
->shift_l
].fw
;
221 static int wm_adsp_fw_put(struct snd_kcontrol
*kcontrol
,
222 struct snd_ctl_elem_value
*ucontrol
)
224 struct snd_soc_codec
*codec
= snd_kcontrol_chip(kcontrol
);
225 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
226 struct wm_adsp
*adsp
= snd_soc_codec_get_drvdata(codec
);
228 if (ucontrol
->value
.integer
.value
[0] == adsp
[e
->shift_l
].fw
)
231 if (ucontrol
->value
.integer
.value
[0] >= WM_ADSP_NUM_FW
)
234 if (adsp
[e
->shift_l
].running
)
237 adsp
[e
->shift_l
].fw
= ucontrol
->value
.integer
.value
[0];
242 static const struct soc_enum wm_adsp_fw_enum
[] = {
243 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
244 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
245 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
246 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
249 const struct snd_kcontrol_new wm_adsp_fw_controls
[] = {
250 SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum
[0],
251 wm_adsp_fw_get
, wm_adsp_fw_put
),
252 SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum
[1],
253 wm_adsp_fw_get
, wm_adsp_fw_put
),
254 SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum
[2],
255 wm_adsp_fw_get
, wm_adsp_fw_put
),
256 SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum
[3],
257 wm_adsp_fw_get
, wm_adsp_fw_put
),
259 EXPORT_SYMBOL_GPL(wm_adsp_fw_controls
);
261 static struct wm_adsp_region
const *wm_adsp_find_region(struct wm_adsp
*dsp
,
266 for (i
= 0; i
< dsp
->num_mems
; i
++)
267 if (dsp
->mem
[i
].type
== type
)
273 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region
const *region
,
276 switch (region
->type
) {
278 return region
->base
+ (offset
* 3);
280 return region
->base
+ (offset
* 2);
282 return region
->base
+ (offset
* 2);
284 return region
->base
+ (offset
* 2);
286 return region
->base
+ (offset
* 2);
288 WARN_ON(NULL
!= "Unknown memory region type");
293 static int wm_adsp_load(struct wm_adsp
*dsp
)
296 const struct firmware
*firmware
;
297 struct regmap
*regmap
= dsp
->regmap
;
298 unsigned int pos
= 0;
299 const struct wmfw_header
*header
;
300 const struct wmfw_adsp1_sizes
*adsp1_sizes
;
301 const struct wmfw_adsp2_sizes
*adsp2_sizes
;
302 const struct wmfw_footer
*footer
;
303 const struct wmfw_region
*region
;
304 const struct wm_adsp_region
*mem
;
305 const char *region_name
;
307 struct wm_adsp_buf
*buf
;
310 int ret
, offset
, type
, sizes
;
312 file
= kzalloc(PAGE_SIZE
, GFP_KERNEL
);
316 snprintf(file
, PAGE_SIZE
, "%s-dsp%d-%s.wmfw", dsp
->part
, dsp
->num
,
317 wm_adsp_fw
[dsp
->fw
].file
);
318 file
[PAGE_SIZE
- 1] = '\0';
320 ret
= request_firmware(&firmware
, file
, dsp
->dev
);
322 adsp_err(dsp
, "Failed to request '%s'\n", file
);
327 pos
= sizeof(*header
) + sizeof(*adsp1_sizes
) + sizeof(*footer
);
328 if (pos
>= firmware
->size
) {
329 adsp_err(dsp
, "%s: file too short, %zu bytes\n",
330 file
, firmware
->size
);
334 header
= (void*)&firmware
->data
[0];
336 if (memcmp(&header
->magic
[0], "WMFW", 4) != 0) {
337 adsp_err(dsp
, "%s: invalid magic\n", file
);
341 if (header
->ver
!= 0) {
342 adsp_err(dsp
, "%s: unknown file format %d\n",
347 if (header
->core
!= dsp
->type
) {
348 adsp_err(dsp
, "%s: invalid core %d != %d\n",
349 file
, header
->core
, dsp
->type
);
355 pos
= sizeof(*header
) + sizeof(*adsp1_sizes
) + sizeof(*footer
);
356 adsp1_sizes
= (void *)&(header
[1]);
357 footer
= (void *)&(adsp1_sizes
[1]);
358 sizes
= sizeof(*adsp1_sizes
);
360 adsp_dbg(dsp
, "%s: %d DM, %d PM, %d ZM\n",
361 file
, le32_to_cpu(adsp1_sizes
->dm
),
362 le32_to_cpu(adsp1_sizes
->pm
),
363 le32_to_cpu(adsp1_sizes
->zm
));
367 pos
= sizeof(*header
) + sizeof(*adsp2_sizes
) + sizeof(*footer
);
368 adsp2_sizes
= (void *)&(header
[1]);
369 footer
= (void *)&(adsp2_sizes
[1]);
370 sizes
= sizeof(*adsp2_sizes
);
372 adsp_dbg(dsp
, "%s: %d XM, %d YM %d PM, %d ZM\n",
373 file
, le32_to_cpu(adsp2_sizes
->xm
),
374 le32_to_cpu(adsp2_sizes
->ym
),
375 le32_to_cpu(adsp2_sizes
->pm
),
376 le32_to_cpu(adsp2_sizes
->zm
));
380 BUG_ON(NULL
== "Unknown DSP type");
384 if (le32_to_cpu(header
->len
) != sizeof(*header
) +
385 sizes
+ sizeof(*footer
)) {
386 adsp_err(dsp
, "%s: unexpected header length %d\n",
387 file
, le32_to_cpu(header
->len
));
391 adsp_dbg(dsp
, "%s: timestamp %llu\n", file
,
392 le64_to_cpu(footer
->timestamp
));
394 while (pos
< firmware
->size
&&
395 pos
- firmware
->size
> sizeof(*region
)) {
396 region
= (void *)&(firmware
->data
[pos
]);
397 region_name
= "Unknown";
400 offset
= le32_to_cpu(region
->offset
) & 0xffffff;
401 type
= be32_to_cpu(region
->type
) & 0xff;
402 mem
= wm_adsp_find_region(dsp
, type
);
406 region_name
= "Firmware name";
407 text
= kzalloc(le32_to_cpu(region
->len
) + 1,
411 region_name
= "Information";
412 text
= kzalloc(le32_to_cpu(region
->len
) + 1,
416 region_name
= "Absolute";
422 reg
= wm_adsp_region_to_reg(mem
, offset
);
427 reg
= wm_adsp_region_to_reg(mem
, offset
);
432 reg
= wm_adsp_region_to_reg(mem
, offset
);
437 reg
= wm_adsp_region_to_reg(mem
, offset
);
442 reg
= wm_adsp_region_to_reg(mem
, offset
);
446 "%s.%d: Unknown region type %x at %d(%x)\n",
447 file
, regions
, type
, pos
, pos
);
451 adsp_dbg(dsp
, "%s.%d: %d bytes at %d in %s\n", file
,
452 regions
, le32_to_cpu(region
->len
), offset
,
456 memcpy(text
, region
->data
, le32_to_cpu(region
->len
));
457 adsp_info(dsp
, "%s: %s\n", file
, text
);
462 buf
= wm_adsp_buf_alloc(region
->data
,
463 le32_to_cpu(region
->len
),
466 adsp_err(dsp
, "Out of memory\n");
470 ret
= regmap_raw_write_async(regmap
, reg
, buf
->buf
,
471 le32_to_cpu(region
->len
));
474 "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
476 le32_to_cpu(region
->len
), offset
,
482 pos
+= le32_to_cpu(region
->len
) + sizeof(*region
);
486 ret
= regmap_async_complete(regmap
);
488 adsp_err(dsp
, "Failed to complete async write: %d\n", ret
);
492 if (pos
> firmware
->size
)
493 adsp_warn(dsp
, "%s.%d: %zu bytes at end of file\n",
494 file
, regions
, pos
- firmware
->size
);
497 regmap_async_complete(regmap
);
498 wm_adsp_buf_free(&buf_list
);
499 release_firmware(firmware
);
506 static int wm_adsp_setup_algs(struct wm_adsp
*dsp
)
508 struct regmap
*regmap
= dsp
->regmap
;
509 struct wmfw_adsp1_id_hdr adsp1_id
;
510 struct wmfw_adsp2_id_hdr adsp2_id
;
511 struct wmfw_adsp1_alg_hdr
*adsp1_alg
;
512 struct wmfw_adsp2_alg_hdr
*adsp2_alg
;
514 struct wm_adsp_alg_region
*region
;
515 const struct wm_adsp_region
*mem
;
516 unsigned int pos
, term
;
517 size_t algs
, buf_size
;
523 mem
= wm_adsp_find_region(dsp
, WMFW_ADSP1_DM
);
526 mem
= wm_adsp_find_region(dsp
, WMFW_ADSP2_XM
);
540 ret
= regmap_raw_read(regmap
, mem
->base
, &adsp1_id
,
543 adsp_err(dsp
, "Failed to read algorithm info: %d\n",
549 buf_size
= sizeof(adsp1_id
);
551 algs
= be32_to_cpu(adsp1_id
.algs
);
552 adsp_info(dsp
, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
553 be32_to_cpu(adsp1_id
.fw
.id
),
554 (be32_to_cpu(adsp1_id
.fw
.ver
) & 0xff0000) >> 16,
555 (be32_to_cpu(adsp1_id
.fw
.ver
) & 0xff00) >> 8,
556 be32_to_cpu(adsp1_id
.fw
.ver
) & 0xff,
559 pos
= sizeof(adsp1_id
) / 2;
560 term
= pos
+ ((sizeof(*adsp1_alg
) * algs
) / 2);
564 ret
= regmap_raw_read(regmap
, mem
->base
, &adsp2_id
,
567 adsp_err(dsp
, "Failed to read algorithm info: %d\n",
573 buf_size
= sizeof(adsp2_id
);
575 algs
= be32_to_cpu(adsp2_id
.algs
);
576 adsp_info(dsp
, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
577 be32_to_cpu(adsp2_id
.fw
.id
),
578 (be32_to_cpu(adsp2_id
.fw
.ver
) & 0xff0000) >> 16,
579 (be32_to_cpu(adsp2_id
.fw
.ver
) & 0xff00) >> 8,
580 be32_to_cpu(adsp2_id
.fw
.ver
) & 0xff,
583 pos
= sizeof(adsp2_id
) / 2;
584 term
= pos
+ ((sizeof(*adsp2_alg
) * algs
) / 2);
588 BUG_ON(NULL
== "Unknown DSP type");
593 adsp_err(dsp
, "No algorithms\n");
598 adsp_err(dsp
, "Algorithm count %zx excessive\n", algs
);
599 print_hex_dump_bytes(dev_name(dsp
->dev
), DUMP_PREFIX_OFFSET
,
604 /* Read the terminator first to validate the length */
605 ret
= regmap_raw_read(regmap
, mem
->base
+ term
, &val
, sizeof(val
));
607 adsp_err(dsp
, "Failed to read algorithm list end: %d\n",
612 if (be32_to_cpu(val
) != 0xbedead)
613 adsp_warn(dsp
, "Algorithm list end %x 0x%x != 0xbeadead\n",
614 term
, be32_to_cpu(val
));
616 alg
= kzalloc((term
- pos
) * 2, GFP_KERNEL
| GFP_DMA
);
620 ret
= regmap_raw_read(regmap
, mem
->base
+ pos
, alg
, (term
- pos
) * 2);
622 adsp_err(dsp
, "Failed to read algorithm list: %d\n",
630 for (i
= 0; i
< algs
; i
++) {
633 adsp_info(dsp
, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
634 i
, be32_to_cpu(adsp1_alg
[i
].alg
.id
),
635 (be32_to_cpu(adsp1_alg
[i
].alg
.ver
) & 0xff0000) >> 16,
636 (be32_to_cpu(adsp1_alg
[i
].alg
.ver
) & 0xff00) >> 8,
637 be32_to_cpu(adsp1_alg
[i
].alg
.ver
) & 0xff,
638 be32_to_cpu(adsp1_alg
[i
].dm
),
639 be32_to_cpu(adsp1_alg
[i
].zm
));
641 region
= kzalloc(sizeof(*region
), GFP_KERNEL
);
644 region
->type
= WMFW_ADSP1_DM
;
645 region
->alg
= be32_to_cpu(adsp1_alg
[i
].alg
.id
);
646 region
->base
= be32_to_cpu(adsp1_alg
[i
].dm
);
647 list_add_tail(®ion
->list
, &dsp
->alg_regions
);
649 region
= kzalloc(sizeof(*region
), GFP_KERNEL
);
652 region
->type
= WMFW_ADSP1_ZM
;
653 region
->alg
= be32_to_cpu(adsp1_alg
[i
].alg
.id
);
654 region
->base
= be32_to_cpu(adsp1_alg
[i
].zm
);
655 list_add_tail(®ion
->list
, &dsp
->alg_regions
);
660 "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
661 i
, be32_to_cpu(adsp2_alg
[i
].alg
.id
),
662 (be32_to_cpu(adsp2_alg
[i
].alg
.ver
) & 0xff0000) >> 16,
663 (be32_to_cpu(adsp2_alg
[i
].alg
.ver
) & 0xff00) >> 8,
664 be32_to_cpu(adsp2_alg
[i
].alg
.ver
) & 0xff,
665 be32_to_cpu(adsp2_alg
[i
].xm
),
666 be32_to_cpu(adsp2_alg
[i
].ym
),
667 be32_to_cpu(adsp2_alg
[i
].zm
));
669 region
= kzalloc(sizeof(*region
), GFP_KERNEL
);
672 region
->type
= WMFW_ADSP2_XM
;
673 region
->alg
= be32_to_cpu(adsp2_alg
[i
].alg
.id
);
674 region
->base
= be32_to_cpu(adsp2_alg
[i
].xm
);
675 list_add_tail(®ion
->list
, &dsp
->alg_regions
);
677 region
= kzalloc(sizeof(*region
), GFP_KERNEL
);
680 region
->type
= WMFW_ADSP2_YM
;
681 region
->alg
= be32_to_cpu(adsp2_alg
[i
].alg
.id
);
682 region
->base
= be32_to_cpu(adsp2_alg
[i
].ym
);
683 list_add_tail(®ion
->list
, &dsp
->alg_regions
);
685 region
= kzalloc(sizeof(*region
), GFP_KERNEL
);
688 region
->type
= WMFW_ADSP2_ZM
;
689 region
->alg
= be32_to_cpu(adsp2_alg
[i
].alg
.id
);
690 region
->base
= be32_to_cpu(adsp2_alg
[i
].zm
);
691 list_add_tail(®ion
->list
, &dsp
->alg_regions
);
701 static int wm_adsp_load_coeff(struct wm_adsp
*dsp
)
704 struct regmap
*regmap
= dsp
->regmap
;
705 struct wmfw_coeff_hdr
*hdr
;
706 struct wmfw_coeff_item
*blk
;
707 const struct firmware
*firmware
;
708 const struct wm_adsp_region
*mem
;
709 struct wm_adsp_alg_region
*alg_region
;
710 const char *region_name
;
711 int ret
, pos
, blocks
, type
, offset
, reg
;
713 struct wm_adsp_buf
*buf
;
716 file
= kzalloc(PAGE_SIZE
, GFP_KERNEL
);
720 snprintf(file
, PAGE_SIZE
, "%s-dsp%d-%s.bin", dsp
->part
, dsp
->num
,
721 wm_adsp_fw
[dsp
->fw
].file
);
722 file
[PAGE_SIZE
- 1] = '\0';
724 ret
= request_firmware(&firmware
, file
, dsp
->dev
);
726 adsp_warn(dsp
, "Failed to request '%s'\n", file
);
732 if (sizeof(*hdr
) >= firmware
->size
) {
733 adsp_err(dsp
, "%s: file too short, %zu bytes\n",
734 file
, firmware
->size
);
738 hdr
= (void*)&firmware
->data
[0];
739 if (memcmp(hdr
->magic
, "WMDR", 4) != 0) {
740 adsp_err(dsp
, "%s: invalid magic\n", file
);
744 switch (be32_to_cpu(hdr
->rev
) & 0xff) {
748 adsp_err(dsp
, "%s: Unsupported coefficient file format %d\n",
749 file
, be32_to_cpu(hdr
->rev
) & 0xff);
754 adsp_dbg(dsp
, "%s: v%d.%d.%d\n", file
,
755 (le32_to_cpu(hdr
->ver
) >> 16) & 0xff,
756 (le32_to_cpu(hdr
->ver
) >> 8) & 0xff,
757 le32_to_cpu(hdr
->ver
) & 0xff);
759 pos
= le32_to_cpu(hdr
->len
);
762 while (pos
< firmware
->size
&&
763 pos
- firmware
->size
> sizeof(*blk
)) {
764 blk
= (void*)(&firmware
->data
[pos
]);
766 type
= le16_to_cpu(blk
->type
);
767 offset
= le16_to_cpu(blk
->offset
);
769 adsp_dbg(dsp
, "%s.%d: %x v%d.%d.%d\n",
770 file
, blocks
, le32_to_cpu(blk
->id
),
771 (le32_to_cpu(blk
->ver
) >> 16) & 0xff,
772 (le32_to_cpu(blk
->ver
) >> 8) & 0xff,
773 le32_to_cpu(blk
->ver
) & 0xff);
774 adsp_dbg(dsp
, "%s.%d: %d bytes at 0x%x in %x\n",
775 file
, blocks
, le32_to_cpu(blk
->len
), offset
, type
);
778 region_name
= "Unknown";
780 case (WMFW_NAME_TEXT
<< 8):
781 case (WMFW_INFO_TEXT
<< 8):
783 case (WMFW_ABSOLUTE
<< 8):
784 region_name
= "register";
792 adsp_dbg(dsp
, "%s.%d: %d bytes in %x for %x\n",
793 file
, blocks
, le32_to_cpu(blk
->len
),
794 type
, le32_to_cpu(blk
->id
));
796 mem
= wm_adsp_find_region(dsp
, type
);
798 adsp_err(dsp
, "No base for region %x\n", type
);
803 list_for_each_entry(alg_region
,
804 &dsp
->alg_regions
, list
) {
805 if (le32_to_cpu(blk
->id
) == alg_region
->alg
&&
806 type
== alg_region
->type
) {
807 reg
= alg_region
->base
;
808 reg
= wm_adsp_region_to_reg(mem
,
815 adsp_err(dsp
, "No %x for algorithm %x\n",
816 type
, le32_to_cpu(blk
->id
));
820 adsp_err(dsp
, "%s.%d: Unknown region type %x at %d\n",
821 file
, blocks
, type
, pos
);
826 buf
= wm_adsp_buf_alloc(blk
->data
,
827 le32_to_cpu(blk
->len
),
830 adsp_err(dsp
, "Out of memory\n");
835 adsp_dbg(dsp
, "%s.%d: Writing %d bytes at %x\n",
836 file
, blocks
, le32_to_cpu(blk
->len
),
838 ret
= regmap_raw_write_async(regmap
, reg
, buf
->buf
,
839 le32_to_cpu(blk
->len
));
842 "%s.%d: Failed to write to %x in %s\n",
843 file
, blocks
, reg
, region_name
);
847 tmp
= le32_to_cpu(blk
->len
) % 4;
849 pos
+= le32_to_cpu(blk
->len
) + (4 - tmp
) + sizeof(*blk
);
851 pos
+= le32_to_cpu(blk
->len
) + sizeof(*blk
);
856 ret
= regmap_async_complete(regmap
);
858 adsp_err(dsp
, "Failed to complete async write: %d\n", ret
);
860 if (pos
> firmware
->size
)
861 adsp_warn(dsp
, "%s.%d: %zu bytes at end of file\n",
862 file
, blocks
, pos
- firmware
->size
);
865 release_firmware(firmware
);
866 wm_adsp_buf_free(&buf_list
);
872 int wm_adsp1_init(struct wm_adsp
*adsp
)
874 INIT_LIST_HEAD(&adsp
->alg_regions
);
878 EXPORT_SYMBOL_GPL(wm_adsp1_init
);
880 int wm_adsp1_event(struct snd_soc_dapm_widget
*w
,
881 struct snd_kcontrol
*kcontrol
,
884 struct snd_soc_codec
*codec
= w
->codec
;
885 struct wm_adsp
*dsps
= snd_soc_codec_get_drvdata(codec
);
886 struct wm_adsp
*dsp
= &dsps
[w
->shift
];
891 case SND_SOC_DAPM_POST_PMU
:
892 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP1_CONTROL_30
,
893 ADSP1_SYS_ENA
, ADSP1_SYS_ENA
);
896 * For simplicity set the DSP clock rate to be the
897 * SYSCLK rate rather than making it configurable.
899 if(dsp
->sysclk_reg
) {
900 ret
= regmap_read(dsp
->regmap
, dsp
->sysclk_reg
, &val
);
902 adsp_err(dsp
, "Failed to read SYSCLK state: %d\n",
907 val
= (val
& dsp
->sysclk_mask
)
908 >> dsp
->sysclk_shift
;
910 ret
= regmap_update_bits(dsp
->regmap
,
911 dsp
->base
+ ADSP1_CONTROL_31
,
912 ADSP1_CLK_SEL_MASK
, val
);
914 adsp_err(dsp
, "Failed to set clock rate: %d\n",
920 ret
= wm_adsp_load(dsp
);
924 ret
= wm_adsp_setup_algs(dsp
);
928 ret
= wm_adsp_load_coeff(dsp
);
932 /* Start the core running */
933 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP1_CONTROL_30
,
934 ADSP1_CORE_ENA
| ADSP1_START
,
935 ADSP1_CORE_ENA
| ADSP1_START
);
938 case SND_SOC_DAPM_PRE_PMD
:
940 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP1_CONTROL_30
,
941 ADSP1_CORE_ENA
| ADSP1_START
, 0);
943 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP1_CONTROL_19
,
944 ADSP1_WDMA_BUFFER_LENGTH_MASK
, 0);
946 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP1_CONTROL_30
,
957 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP1_CONTROL_30
,
961 EXPORT_SYMBOL_GPL(wm_adsp1_event
);
963 static int wm_adsp2_ena(struct wm_adsp
*dsp
)
968 ret
= regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP2_CONTROL
,
969 ADSP2_SYS_ENA
, ADSP2_SYS_ENA
);
973 /* Wait for the RAM to start, should be near instantaneous */
976 ret
= regmap_read(dsp
->regmap
, dsp
->base
+ ADSP2_STATUS1
,
980 } while (!(val
& ADSP2_RAM_RDY
) && ++count
< 10);
982 if (!(val
& ADSP2_RAM_RDY
)) {
983 adsp_err(dsp
, "Failed to start DSP RAM\n");
987 adsp_dbg(dsp
, "RAM ready after %d polls\n", count
);
988 adsp_info(dsp
, "RAM ready after %d polls\n", count
);
993 int wm_adsp2_event(struct snd_soc_dapm_widget
*w
,
994 struct snd_kcontrol
*kcontrol
, int event
)
996 struct snd_soc_codec
*codec
= w
->codec
;
997 struct wm_adsp
*dsps
= snd_soc_codec_get_drvdata(codec
);
998 struct wm_adsp
*dsp
= &dsps
[w
->shift
];
999 struct wm_adsp_alg_region
*alg_region
;
1004 case SND_SOC_DAPM_POST_PMU
:
1006 * For simplicity set the DSP clock rate to be the
1007 * SYSCLK rate rather than making it configurable.
1009 ret
= regmap_read(dsp
->regmap
, ARIZONA_SYSTEM_CLOCK_1
, &val
);
1011 adsp_err(dsp
, "Failed to read SYSCLK state: %d\n",
1015 val
= (val
& ARIZONA_SYSCLK_FREQ_MASK
)
1016 >> ARIZONA_SYSCLK_FREQ_SHIFT
;
1018 ret
= regmap_update_bits(dsp
->regmap
,
1019 dsp
->base
+ ADSP2_CLOCKING
,
1020 ADSP2_CLK_SEL_MASK
, val
);
1022 adsp_err(dsp
, "Failed to set clock rate: %d\n",
1028 ret
= regmap_read(dsp
->regmap
,
1029 dsp
->base
+ ADSP2_CLOCKING
, &val
);
1032 "Failed to read clocking: %d\n", ret
);
1036 if ((val
& ADSP2_CLK_SEL_MASK
) >= 3) {
1037 ret
= regulator_enable(dsp
->dvfs
);
1040 "Failed to enable supply: %d\n",
1045 ret
= regulator_set_voltage(dsp
->dvfs
,
1050 "Failed to raise supply: %d\n",
1057 ret
= wm_adsp2_ena(dsp
);
1061 ret
= wm_adsp_load(dsp
);
1065 ret
= wm_adsp_setup_algs(dsp
);
1069 ret
= wm_adsp_load_coeff(dsp
);
1073 ret
= regmap_update_bits(dsp
->regmap
,
1074 dsp
->base
+ ADSP2_CONTROL
,
1075 ADSP2_CORE_ENA
| ADSP2_START
,
1076 ADSP2_CORE_ENA
| ADSP2_START
);
1080 dsp
->running
= true;
1083 case SND_SOC_DAPM_PRE_PMD
:
1084 dsp
->running
= false;
1086 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP2_CONTROL
,
1087 ADSP2_SYS_ENA
| ADSP2_CORE_ENA
|
1090 /* Make sure DMAs are quiesced */
1091 regmap_write(dsp
->regmap
, dsp
->base
+ ADSP2_WDMA_CONFIG_1
, 0);
1092 regmap_write(dsp
->regmap
, dsp
->base
+ ADSP2_WDMA_CONFIG_2
, 0);
1093 regmap_write(dsp
->regmap
, dsp
->base
+ ADSP2_RDMA_CONFIG_1
, 0);
1096 ret
= regulator_set_voltage(dsp
->dvfs
, 1200000,
1100 "Failed to lower supply: %d\n",
1103 ret
= regulator_disable(dsp
->dvfs
);
1106 "Failed to enable supply: %d\n",
1110 while (!list_empty(&dsp
->alg_regions
)) {
1111 alg_region
= list_first_entry(&dsp
->alg_regions
,
1112 struct wm_adsp_alg_region
,
1114 list_del(&alg_region
->list
);
1125 regmap_update_bits(dsp
->regmap
, dsp
->base
+ ADSP2_CONTROL
,
1126 ADSP2_SYS_ENA
| ADSP2_CORE_ENA
| ADSP2_START
, 0);
1129 EXPORT_SYMBOL_GPL(wm_adsp2_event
);
1131 int wm_adsp2_init(struct wm_adsp
*adsp
, bool dvfs
)
1136 * Disable the DSP memory by default when in reset for a small
1139 ret
= regmap_update_bits(adsp
->regmap
, adsp
->base
+ ADSP2_CONTROL
,
1142 adsp_err(adsp
, "Failed to clear memory retention: %d\n", ret
);
1146 INIT_LIST_HEAD(&adsp
->alg_regions
);
1149 adsp
->dvfs
= devm_regulator_get(adsp
->dev
, "DCVDD");
1150 if (IS_ERR(adsp
->dvfs
)) {
1151 ret
= PTR_ERR(adsp
->dvfs
);
1152 dev_err(adsp
->dev
, "Failed to get DCVDD: %d\n", ret
);
1156 ret
= regulator_enable(adsp
->dvfs
);
1158 dev_err(adsp
->dev
, "Failed to enable DCVDD: %d\n",
1163 ret
= regulator_set_voltage(adsp
->dvfs
, 1200000, 1800000);
1165 dev_err(adsp
->dev
, "Failed to initialise DVFS: %d\n",
1170 ret
= regulator_disable(adsp
->dvfs
);
1172 dev_err(adsp
->dev
, "Failed to disable DCVDD: %d\n",
1180 EXPORT_SYMBOL_GPL(wm_adsp2_init
);