1 // SPDX-License-Identifier: GPL-2.0-only
3 * wm_adsp.c -- Wolfson ADSP support
5 * Copyright 2012 Wolfson Microelectronics plc
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
10 #include <linux/array_size.h>
11 #include <linux/ctype.h>
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/init.h>
15 #include <linux/delay.h>
16 #include <linux/firmware.h>
17 #include <linux/list.h>
19 #include <linux/regmap.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/slab.h>
22 #include <linux/vmalloc.h>
23 #include <linux/workqueue.h>
24 #include <linux/debugfs.h>
25 #include <sound/core.h>
26 #include <sound/pcm.h>
27 #include <sound/pcm_params.h>
28 #include <sound/soc.h>
29 #include <sound/jack.h>
30 #include <sound/initval.h>
31 #include <sound/tlv.h>
35 #define adsp_crit(_dsp, fmt, ...) \
36 dev_crit(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
37 #define adsp_err(_dsp, fmt, ...) \
38 dev_err(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
39 #define adsp_warn(_dsp, fmt, ...) \
40 dev_warn(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
41 #define adsp_info(_dsp, fmt, ...) \
42 dev_info(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
43 #define adsp_dbg(_dsp, fmt, ...) \
44 dev_dbg(_dsp->cs_dsp.dev, "%s: " fmt, _dsp->cs_dsp.name, ##__VA_ARGS__)
46 #define compr_err(_obj, fmt, ...) \
47 adsp_err(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
49 #define compr_dbg(_obj, fmt, ...) \
50 adsp_dbg(_obj->dsp, "%s: " fmt, _obj->name ? _obj->name : "legacy", \
53 #define ADSP_MAX_STD_CTRL_SIZE 512
55 static const struct cs_dsp_client_ops wm_adsp1_client_ops
;
56 static const struct cs_dsp_client_ops wm_adsp2_client_ops
;
58 #define WM_ADSP_FW_MBC_VSS 0
59 #define WM_ADSP_FW_HIFI 1
60 #define WM_ADSP_FW_TX 2
61 #define WM_ADSP_FW_TX_SPK 3
62 #define WM_ADSP_FW_RX 4
63 #define WM_ADSP_FW_RX_ANC 5
64 #define WM_ADSP_FW_CTRL 6
65 #define WM_ADSP_FW_ASR 7
66 #define WM_ADSP_FW_TRACE 8
67 #define WM_ADSP_FW_SPK_PROT 9
68 #define WM_ADSP_FW_SPK_CALI 10
69 #define WM_ADSP_FW_SPK_DIAG 11
70 #define WM_ADSP_FW_MISC 12
72 #define WM_ADSP_NUM_FW 13
74 static const char *wm_adsp_fw_text
[WM_ADSP_NUM_FW
] = {
75 [WM_ADSP_FW_MBC_VSS
] = "MBC/VSS",
76 [WM_ADSP_FW_HIFI
] = "MasterHiFi",
77 [WM_ADSP_FW_TX
] = "Tx",
78 [WM_ADSP_FW_TX_SPK
] = "Tx Speaker",
79 [WM_ADSP_FW_RX
] = "Rx",
80 [WM_ADSP_FW_RX_ANC
] = "Rx ANC",
81 [WM_ADSP_FW_CTRL
] = "Voice Ctrl",
82 [WM_ADSP_FW_ASR
] = "ASR Assist",
83 [WM_ADSP_FW_TRACE
] = "Dbg Trace",
84 [WM_ADSP_FW_SPK_PROT
] = "Protection",
85 [WM_ADSP_FW_SPK_CALI
] = "Calibration",
86 [WM_ADSP_FW_SPK_DIAG
] = "Diagnostic",
87 [WM_ADSP_FW_MISC
] = "Misc",
90 struct wm_adsp_system_config_xm_hdr
{
96 __be32 dma_buffer_size
;
99 __be32 build_job_name
[3];
100 __be32 build_job_number
;
103 struct wm_halo_system_config_xm_hdr
{
104 __be32 halo_heartbeat
;
105 __be32 build_job_name
[3];
106 __be32 build_job_number
;
109 struct wm_adsp_alg_xm_struct
{
115 __be32 high_water_mark
;
116 __be32 low_water_mark
;
117 __be64 smoothed_power
;
120 struct wm_adsp_host_buf_coeff_v1
{
121 __be32 host_buf_ptr
; /* Host buffer pointer */
122 __be32 versions
; /* Version numbers */
123 __be32 name
[4]; /* The buffer name */
126 struct wm_adsp_buffer
{
127 __be32 buf1_base
; /* Base addr of first buffer area */
128 __be32 buf1_size
; /* Size of buf1 area in DSP words */
129 __be32 buf2_base
; /* Base addr of 2nd buffer area */
130 __be32 buf1_buf2_size
; /* Size of buf1+buf2 in DSP words */
131 __be32 buf3_base
; /* Base addr of buf3 area */
132 __be32 buf_total_size
; /* Size of buf1+buf2+buf3 in DSP words */
133 __be32 high_water_mark
; /* Point at which IRQ is asserted */
134 __be32 irq_count
; /* bits 1-31 count IRQ assertions */
135 __be32 irq_ack
; /* acked IRQ count, bit 0 enables IRQ */
136 __be32 next_write_index
; /* word index of next write */
137 __be32 next_read_index
; /* word index of next read */
138 __be32 error
; /* error if any */
139 __be32 oldest_block_index
; /* word index of oldest surviving */
140 __be32 requested_rewind
; /* how many blocks rewind was done */
141 __be32 reserved_space
; /* internal */
142 __be32 min_free
; /* min free space since stream start */
143 __be32 blocks_written
[2]; /* total blocks written (64 bit) */
144 __be32 words_written
[2]; /* total words written (64 bit) */
147 struct wm_adsp_compr
;
149 struct wm_adsp_compr_buf
{
150 struct list_head list
;
152 struct wm_adsp_compr
*compr
;
154 struct wm_adsp_buffer_region
*regions
;
161 int host_buf_mem_type
;
166 struct wm_adsp_compr
{
167 struct list_head list
;
169 struct wm_adsp_compr_buf
*buf
;
171 struct snd_compr_stream
*stream
;
172 struct snd_compressed_buffer size
;
175 unsigned int copied_total
;
177 unsigned int sample_rate
;
182 #define WM_ADSP_MIN_FRAGMENTS 1
183 #define WM_ADSP_MAX_FRAGMENTS 256
184 #define WM_ADSP_MIN_FRAGMENT_SIZE (16 * CS_DSP_DATA_WORD_SIZE)
185 #define WM_ADSP_MAX_FRAGMENT_SIZE (4096 * CS_DSP_DATA_WORD_SIZE)
187 #define WM_ADSP_ALG_XM_STRUCT_MAGIC 0x49aec7
189 #define HOST_BUFFER_FIELD(field) \
190 (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
192 #define ALG_XM_FIELD(field) \
193 (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
195 #define HOST_BUF_COEFF_SUPPORTED_COMPAT_VER 1
197 #define HOST_BUF_COEFF_COMPAT_VER_MASK 0xFF00
198 #define HOST_BUF_COEFF_COMPAT_VER_SHIFT 8
200 static int wm_adsp_buffer_init(struct wm_adsp
*dsp
);
201 static int wm_adsp_buffer_free(struct wm_adsp
*dsp
);
203 struct wm_adsp_buffer_region
{
205 unsigned int cumulative_size
;
206 unsigned int mem_type
;
207 unsigned int base_addr
;
210 struct wm_adsp_buffer_region_def
{
211 unsigned int mem_type
;
212 unsigned int base_offset
;
213 unsigned int size_offset
;
216 static const struct wm_adsp_buffer_region_def default_regions
[] = {
218 .mem_type
= WMFW_ADSP2_XM
,
219 .base_offset
= HOST_BUFFER_FIELD(buf1_base
),
220 .size_offset
= HOST_BUFFER_FIELD(buf1_size
),
223 .mem_type
= WMFW_ADSP2_XM
,
224 .base_offset
= HOST_BUFFER_FIELD(buf2_base
),
225 .size_offset
= HOST_BUFFER_FIELD(buf1_buf2_size
),
228 .mem_type
= WMFW_ADSP2_YM
,
229 .base_offset
= HOST_BUFFER_FIELD(buf3_base
),
230 .size_offset
= HOST_BUFFER_FIELD(buf_total_size
),
234 struct wm_adsp_fw_caps
{
236 struct snd_codec_desc desc
;
238 const struct wm_adsp_buffer_region_def
*region_defs
;
241 static const struct wm_adsp_fw_caps ctrl_caps
[] = {
243 .id
= SND_AUDIOCODEC_BESPOKE
,
246 .sample_rates
= { 16000 },
247 .num_sample_rates
= 1,
248 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
250 .num_regions
= ARRAY_SIZE(default_regions
),
251 .region_defs
= default_regions
,
255 static const struct wm_adsp_fw_caps trace_caps
[] = {
257 .id
= SND_AUDIOCODEC_BESPOKE
,
261 4000, 8000, 11025, 12000, 16000, 22050,
262 24000, 32000, 44100, 48000, 64000, 88200,
263 96000, 176400, 192000
265 .num_sample_rates
= 15,
266 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
268 .num_regions
= ARRAY_SIZE(default_regions
),
269 .region_defs
= default_regions
,
273 static const struct {
277 const struct wm_adsp_fw_caps
*caps
;
279 } wm_adsp_fw
[WM_ADSP_NUM_FW
] = {
280 [WM_ADSP_FW_MBC_VSS
] = { .file
= "mbc-vss" },
281 [WM_ADSP_FW_HIFI
] = { .file
= "hifi" },
282 [WM_ADSP_FW_TX
] = { .file
= "tx" },
283 [WM_ADSP_FW_TX_SPK
] = { .file
= "tx-spk" },
284 [WM_ADSP_FW_RX
] = { .file
= "rx" },
285 [WM_ADSP_FW_RX_ANC
] = { .file
= "rx-anc" },
286 [WM_ADSP_FW_CTRL
] = {
288 .compr_direction
= SND_COMPRESS_CAPTURE
,
289 .num_caps
= ARRAY_SIZE(ctrl_caps
),
291 .voice_trigger
= true,
293 [WM_ADSP_FW_ASR
] = { .file
= "asr" },
294 [WM_ADSP_FW_TRACE
] = {
296 .compr_direction
= SND_COMPRESS_CAPTURE
,
297 .num_caps
= ARRAY_SIZE(trace_caps
),
300 [WM_ADSP_FW_SPK_PROT
] = {
302 .compr_direction
= SND_COMPRESS_CAPTURE
,
303 .num_caps
= ARRAY_SIZE(trace_caps
),
306 [WM_ADSP_FW_SPK_CALI
] = { .file
= "spk-cali" },
307 [WM_ADSP_FW_SPK_DIAG
] = { .file
= "spk-diag" },
308 [WM_ADSP_FW_MISC
] = { .file
= "misc" },
311 struct wm_coeff_ctl
{
313 struct cs_dsp_coeff_ctl
*cs_ctl
;
314 struct soc_bytes_ext bytes_ext
;
315 struct work_struct work
;
318 int wm_adsp_fw_get(struct snd_kcontrol
*kcontrol
,
319 struct snd_ctl_elem_value
*ucontrol
)
321 struct snd_soc_component
*component
= snd_soc_kcontrol_component(kcontrol
);
322 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
323 struct wm_adsp
*dsp
= snd_soc_component_get_drvdata(component
);
325 ucontrol
->value
.enumerated
.item
[0] = dsp
[e
->shift_l
].fw
;
329 EXPORT_SYMBOL_GPL(wm_adsp_fw_get
);
331 int wm_adsp_fw_put(struct snd_kcontrol
*kcontrol
,
332 struct snd_ctl_elem_value
*ucontrol
)
334 struct snd_soc_component
*component
= snd_soc_kcontrol_component(kcontrol
);
335 struct soc_enum
*e
= (struct soc_enum
*)kcontrol
->private_value
;
336 struct wm_adsp
*dsp
= snd_soc_component_get_drvdata(component
);
339 if (ucontrol
->value
.enumerated
.item
[0] == dsp
[e
->shift_l
].fw
)
342 if (ucontrol
->value
.enumerated
.item
[0] >= WM_ADSP_NUM_FW
)
345 mutex_lock(&dsp
[e
->shift_l
].cs_dsp
.pwr_lock
);
347 if (dsp
[e
->shift_l
].cs_dsp
.booted
|| !list_empty(&dsp
[e
->shift_l
].compr_list
))
350 dsp
[e
->shift_l
].fw
= ucontrol
->value
.enumerated
.item
[0];
352 mutex_unlock(&dsp
[e
->shift_l
].cs_dsp
.pwr_lock
);
356 EXPORT_SYMBOL_GPL(wm_adsp_fw_put
);
358 const struct soc_enum wm_adsp_fw_enum
[] = {
359 SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
360 SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
361 SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
362 SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
363 SOC_ENUM_SINGLE(0, 4, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
364 SOC_ENUM_SINGLE(0, 5, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
365 SOC_ENUM_SINGLE(0, 6, ARRAY_SIZE(wm_adsp_fw_text
), wm_adsp_fw_text
),
367 EXPORT_SYMBOL_GPL(wm_adsp_fw_enum
);
369 static inline struct wm_coeff_ctl
*bytes_ext_to_ctl(struct soc_bytes_ext
*ext
)
371 return container_of(ext
, struct wm_coeff_ctl
, bytes_ext
);
374 static int wm_coeff_info(struct snd_kcontrol
*kctl
,
375 struct snd_ctl_elem_info
*uinfo
)
377 struct soc_bytes_ext
*bytes_ext
=
378 (struct soc_bytes_ext
*)kctl
->private_value
;
379 struct wm_coeff_ctl
*ctl
= bytes_ext_to_ctl(bytes_ext
);
380 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
382 switch (cs_ctl
->type
) {
383 case WMFW_CTL_TYPE_ACKED
:
384 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
385 uinfo
->value
.integer
.min
= CS_DSP_ACKED_CTL_MIN_VALUE
;
386 uinfo
->value
.integer
.max
= CS_DSP_ACKED_CTL_MAX_VALUE
;
387 uinfo
->value
.integer
.step
= 1;
391 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BYTES
;
392 uinfo
->count
= cs_ctl
->len
;
399 static int wm_coeff_put(struct snd_kcontrol
*kctl
,
400 struct snd_ctl_elem_value
*ucontrol
)
402 struct soc_bytes_ext
*bytes_ext
=
403 (struct soc_bytes_ext
*)kctl
->private_value
;
404 struct wm_coeff_ctl
*ctl
= bytes_ext_to_ctl(bytes_ext
);
405 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
406 char *p
= ucontrol
->value
.bytes
.data
;
408 return cs_dsp_coeff_lock_and_write_ctrl(cs_ctl
, 0, p
, cs_ctl
->len
);
411 static int wm_coeff_tlv_put(struct snd_kcontrol
*kctl
,
412 const unsigned int __user
*bytes
, unsigned int size
)
414 struct soc_bytes_ext
*bytes_ext
=
415 (struct soc_bytes_ext
*)kctl
->private_value
;
416 struct wm_coeff_ctl
*ctl
= bytes_ext_to_ctl(bytes_ext
);
417 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
421 scratch
= vmalloc(size
);
425 if (copy_from_user(scratch
, bytes
, size
))
428 ret
= cs_dsp_coeff_lock_and_write_ctrl(cs_ctl
, 0, scratch
, size
);
435 static int wm_coeff_put_acked(struct snd_kcontrol
*kctl
,
436 struct snd_ctl_elem_value
*ucontrol
)
438 struct soc_bytes_ext
*bytes_ext
=
439 (struct soc_bytes_ext
*)kctl
->private_value
;
440 struct wm_coeff_ctl
*ctl
= bytes_ext_to_ctl(bytes_ext
);
441 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
442 unsigned int val
= ucontrol
->value
.integer
.value
[0];
446 return 0; /* 0 means no event */
448 mutex_lock(&cs_ctl
->dsp
->pwr_lock
);
451 ret
= cs_dsp_coeff_write_acked_control(cs_ctl
, val
);
455 mutex_unlock(&cs_ctl
->dsp
->pwr_lock
);
463 static int wm_coeff_get(struct snd_kcontrol
*kctl
,
464 struct snd_ctl_elem_value
*ucontrol
)
466 struct soc_bytes_ext
*bytes_ext
=
467 (struct soc_bytes_ext
*)kctl
->private_value
;
468 struct wm_coeff_ctl
*ctl
= bytes_ext_to_ctl(bytes_ext
);
469 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
470 char *p
= ucontrol
->value
.bytes
.data
;
472 return cs_dsp_coeff_lock_and_read_ctrl(cs_ctl
, 0, p
, cs_ctl
->len
);
475 static int wm_coeff_tlv_get(struct snd_kcontrol
*kctl
,
476 unsigned int __user
*bytes
, unsigned int size
)
478 struct soc_bytes_ext
*bytes_ext
=
479 (struct soc_bytes_ext
*)kctl
->private_value
;
480 struct wm_coeff_ctl
*ctl
= bytes_ext_to_ctl(bytes_ext
);
481 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
484 mutex_lock(&cs_ctl
->dsp
->pwr_lock
);
486 ret
= cs_dsp_coeff_read_ctrl(cs_ctl
, 0, cs_ctl
->cache
, size
);
488 if (!ret
&& copy_to_user(bytes
, cs_ctl
->cache
, size
))
491 mutex_unlock(&cs_ctl
->dsp
->pwr_lock
);
496 static int wm_coeff_get_acked(struct snd_kcontrol
*kcontrol
,
497 struct snd_ctl_elem_value
*ucontrol
)
500 * Although it's not useful to read an acked control, we must satisfy
501 * user-side assumptions that all controls are readable and that a
502 * write of the same value should be filtered out (it's valid to send
503 * the same event number again to the firmware). We therefore return 0,
504 * meaning "no event" so valid event numbers will always be a change
506 ucontrol
->value
.integer
.value
[0] = 0;
511 static unsigned int wmfw_convert_flags(unsigned int in
, unsigned int len
)
513 unsigned int out
, rd
, wr
, vol
;
515 if (len
> ADSP_MAX_STD_CTRL_SIZE
) {
516 rd
= SNDRV_CTL_ELEM_ACCESS_TLV_READ
;
517 wr
= SNDRV_CTL_ELEM_ACCESS_TLV_WRITE
;
518 vol
= SNDRV_CTL_ELEM_ACCESS_VOLATILE
;
520 out
= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
;
522 rd
= SNDRV_CTL_ELEM_ACCESS_READ
;
523 wr
= SNDRV_CTL_ELEM_ACCESS_WRITE
;
524 vol
= SNDRV_CTL_ELEM_ACCESS_VOLATILE
;
531 if (in
& WMFW_CTL_FLAG_WRITEABLE
)
533 if (in
& WMFW_CTL_FLAG_VOLATILE
)
536 out
|= rd
| wr
| vol
;
542 static void wm_adsp_ctl_work(struct work_struct
*work
)
544 struct wm_coeff_ctl
*ctl
= container_of(work
,
547 struct cs_dsp_coeff_ctl
*cs_ctl
= ctl
->cs_ctl
;
548 struct wm_adsp
*dsp
= container_of(cs_ctl
->dsp
,
551 struct snd_kcontrol_new
*kcontrol
;
553 kcontrol
= kzalloc(sizeof(*kcontrol
), GFP_KERNEL
);
557 kcontrol
->name
= ctl
->name
;
558 kcontrol
->info
= wm_coeff_info
;
559 kcontrol
->iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
560 kcontrol
->tlv
.c
= snd_soc_bytes_tlv_callback
;
561 kcontrol
->private_value
= (unsigned long)&ctl
->bytes_ext
;
562 kcontrol
->access
= wmfw_convert_flags(cs_ctl
->flags
, cs_ctl
->len
);
564 switch (cs_ctl
->type
) {
565 case WMFW_CTL_TYPE_ACKED
:
566 kcontrol
->get
= wm_coeff_get_acked
;
567 kcontrol
->put
= wm_coeff_put_acked
;
570 if (kcontrol
->access
& SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK
) {
571 ctl
->bytes_ext
.max
= cs_ctl
->len
;
572 ctl
->bytes_ext
.get
= wm_coeff_tlv_get
;
573 ctl
->bytes_ext
.put
= wm_coeff_tlv_put
;
575 kcontrol
->get
= wm_coeff_get
;
576 kcontrol
->put
= wm_coeff_put
;
581 snd_soc_add_component_controls(dsp
->component
, kcontrol
, 1);
586 int wm_adsp_control_add(struct cs_dsp_coeff_ctl
*cs_ctl
)
588 struct wm_adsp
*dsp
= container_of(cs_ctl
->dsp
, struct wm_adsp
, cs_dsp
);
589 struct cs_dsp
*cs_dsp
= &dsp
->cs_dsp
;
590 struct wm_coeff_ctl
*ctl
;
591 char name
[SNDRV_CTL_ELEM_ID_NAME_MAXLEN
];
592 const char *region_name
;
595 if (cs_ctl
->flags
& WMFW_CTL_FLAG_SYS
)
598 region_name
= cs_dsp_mem_region_name(cs_ctl
->alg_region
.type
);
600 adsp_err(dsp
, "Unknown region type: %d\n", cs_ctl
->alg_region
.type
);
604 switch (cs_dsp
->wmfw_ver
) {
607 ret
= scnprintf(name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
,
608 "%s %s %x", cs_dsp
->name
, region_name
,
609 cs_ctl
->alg_region
.alg
);
612 ret
= scnprintf(name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
,
613 "%s%c %.12s %x", cs_dsp
->name
, *region_name
,
614 wm_adsp_fw_text
[dsp
->fw
], cs_ctl
->alg_region
.alg
);
617 ret
= scnprintf(name
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
,
618 "%s %.12s %x", cs_dsp
->name
,
619 wm_adsp_fw_text
[dsp
->fw
], cs_ctl
->alg_region
.alg
);
623 if (cs_ctl
->subname
) {
624 int avail
= SNDRV_CTL_ELEM_ID_NAME_MAXLEN
- ret
- 2;
627 if (dsp
->component
->name_prefix
)
628 avail
-= strlen(dsp
->component
->name_prefix
) + 1;
630 /* Truncate the subname from the start if it is too long */
631 if (cs_ctl
->subname_len
> avail
)
632 skip
= cs_ctl
->subname_len
- avail
;
634 snprintf(name
+ ret
, SNDRV_CTL_ELEM_ID_NAME_MAXLEN
- ret
,
635 " %.*s", cs_ctl
->subname_len
- skip
, cs_ctl
->subname
+ skip
);
638 ctl
= kzalloc(sizeof(*ctl
), GFP_KERNEL
);
641 ctl
->cs_ctl
= cs_ctl
;
643 ctl
->name
= kmemdup(name
, strlen(name
) + 1, GFP_KERNEL
);
651 INIT_WORK(&ctl
->work
, wm_adsp_ctl_work
);
652 schedule_work(&ctl
->work
);
661 EXPORT_SYMBOL_GPL(wm_adsp_control_add
);
663 static int wm_adsp_control_add_cb(struct cs_dsp_coeff_ctl
*cs_ctl
)
665 struct wm_adsp
*dsp
= container_of(cs_ctl
->dsp
, struct wm_adsp
, cs_dsp
);
667 if (dsp
->control_add
)
668 return (dsp
->control_add
)(dsp
, cs_ctl
);
670 return wm_adsp_control_add(cs_ctl
);
673 static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl
*cs_ctl
)
675 struct wm_coeff_ctl
*ctl
= cs_ctl
->priv
;
677 cancel_work_sync(&ctl
->work
);
683 int wm_adsp_write_ctl(struct wm_adsp
*dsp
, const char *name
, int type
,
684 unsigned int alg
, void *buf
, size_t len
)
686 struct cs_dsp_coeff_ctl
*cs_ctl
;
689 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
690 cs_ctl
= cs_dsp_get_ctl(&dsp
->cs_dsp
, name
, type
, alg
);
691 ret
= cs_dsp_coeff_write_ctrl(cs_ctl
, 0, buf
, len
);
692 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
699 EXPORT_SYMBOL_GPL(wm_adsp_write_ctl
);
701 int wm_adsp_read_ctl(struct wm_adsp
*dsp
, const char *name
, int type
,
702 unsigned int alg
, void *buf
, size_t len
)
706 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
707 ret
= cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(&dsp
->cs_dsp
, name
, type
, alg
),
709 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
713 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl
);
715 static void wm_adsp_release_firmware_files(struct wm_adsp
*dsp
,
716 const struct firmware
*wmfw_firmware
,
718 const struct firmware
*coeff_firmware
,
719 char *coeff_filename
)
722 release_firmware(wmfw_firmware
);
723 kfree(wmfw_filename
);
726 release_firmware(coeff_firmware
);
727 kfree(coeff_filename
);
730 static int wm_adsp_request_firmware_file(struct wm_adsp
*dsp
,
731 const struct firmware
**firmware
, char **filename
,
732 const char *dir
, const char *system_name
,
733 const char *asoc_component_prefix
,
734 const char *filetype
)
736 struct cs_dsp
*cs_dsp
= &dsp
->cs_dsp
;
744 fwf
= dsp
->cs_dsp
.name
;
746 if (system_name
&& asoc_component_prefix
)
747 *filename
= kasprintf(GFP_KERNEL
, "%s%s-%s-%s-%s-%s.%s", dir
, dsp
->part
,
748 fwf
, wm_adsp_fw
[dsp
->fw
].file
, system_name
,
749 asoc_component_prefix
, filetype
);
750 else if (system_name
)
751 *filename
= kasprintf(GFP_KERNEL
, "%s%s-%s-%s-%s.%s", dir
, dsp
->part
,
752 fwf
, wm_adsp_fw
[dsp
->fw
].file
, system_name
,
755 *filename
= kasprintf(GFP_KERNEL
, "%s%s-%s-%s.%s", dir
, dsp
->part
, fwf
,
756 wm_adsp_fw
[dsp
->fw
].file
, filetype
);
758 if (*filename
== NULL
)
762 * Make sure that filename is lower-case and any non alpha-numeric
763 * characters except full stop and forward slash are replaced with
771 else if ((c
!= '.') && (c
!= '/'))
776 ret
= firmware_request_nowarn(firmware
, *filename
, cs_dsp
->dev
);
778 adsp_dbg(dsp
, "Failed to request '%s'\n", *filename
);
782 adsp_dbg(dsp
, "Found '%s'\n", *filename
);
788 static const char *cirrus_dir
= "cirrus/";
789 static int wm_adsp_request_firmware_files(struct wm_adsp
*dsp
,
790 const struct firmware
**wmfw_firmware
,
791 char **wmfw_filename
,
792 const struct firmware
**coeff_firmware
,
793 char **coeff_filename
)
795 const char *system_name
= dsp
->system_name
;
796 const char *asoc_component_prefix
= dsp
->component
->name_prefix
;
799 if (system_name
&& asoc_component_prefix
) {
800 if (!wm_adsp_request_firmware_file(dsp
, wmfw_firmware
, wmfw_filename
,
801 cirrus_dir
, system_name
,
802 asoc_component_prefix
, "wmfw")) {
803 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
804 cirrus_dir
, system_name
,
805 asoc_component_prefix
, "bin");
811 if (!wm_adsp_request_firmware_file(dsp
, wmfw_firmware
, wmfw_filename
,
812 cirrus_dir
, system_name
,
814 if (asoc_component_prefix
)
815 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
816 cirrus_dir
, system_name
,
817 asoc_component_prefix
, "bin");
819 if (!*coeff_firmware
)
820 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
821 cirrus_dir
, system_name
,
827 /* Check system-specific bin without wmfw before falling back to generic */
828 if (dsp
->wmfw_optional
&& system_name
) {
829 if (asoc_component_prefix
)
830 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
831 cirrus_dir
, system_name
,
832 asoc_component_prefix
, "bin");
834 if (!*coeff_firmware
)
835 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
836 cirrus_dir
, system_name
,
843 /* Check legacy location */
844 if (!wm_adsp_request_firmware_file(dsp
, wmfw_firmware
, wmfw_filename
,
845 "", NULL
, NULL
, "wmfw")) {
846 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
847 "", NULL
, NULL
, "bin");
851 /* Fall back to generic wmfw and optional matching bin */
852 ret
= wm_adsp_request_firmware_file(dsp
, wmfw_firmware
, wmfw_filename
,
853 cirrus_dir
, NULL
, NULL
, "wmfw");
854 if (!ret
|| dsp
->wmfw_optional
) {
855 wm_adsp_request_firmware_file(dsp
, coeff_firmware
, coeff_filename
,
856 cirrus_dir
, NULL
, NULL
, "bin");
860 adsp_err(dsp
, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n",
861 cirrus_dir
, dsp
->part
,
862 dsp
->fwf_name
? dsp
->fwf_name
: dsp
->cs_dsp
.name
,
863 wm_adsp_fw
[dsp
->fw
].file
, system_name
, asoc_component_prefix
);
868 static int wm_adsp_common_init(struct wm_adsp
*dsp
)
870 INIT_LIST_HEAD(&dsp
->compr_list
);
871 INIT_LIST_HEAD(&dsp
->buffer_list
);
876 int wm_adsp1_init(struct wm_adsp
*dsp
)
880 dsp
->cs_dsp
.client_ops
= &wm_adsp1_client_ops
;
882 ret
= cs_dsp_adsp1_init(&dsp
->cs_dsp
);
886 return wm_adsp_common_init(dsp
);
888 EXPORT_SYMBOL_GPL(wm_adsp1_init
);
890 int wm_adsp1_event(struct snd_soc_dapm_widget
*w
,
891 struct snd_kcontrol
*kcontrol
,
894 struct snd_soc_component
*component
= snd_soc_dapm_to_component(w
->dapm
);
895 struct wm_adsp
*dsps
= snd_soc_component_get_drvdata(component
);
896 struct wm_adsp
*dsp
= &dsps
[w
->shift
];
898 char *wmfw_filename
= NULL
;
899 const struct firmware
*wmfw_firmware
= NULL
;
900 char *coeff_filename
= NULL
;
901 const struct firmware
*coeff_firmware
= NULL
;
903 dsp
->component
= component
;
906 case SND_SOC_DAPM_POST_PMU
:
907 ret
= wm_adsp_request_firmware_files(dsp
,
908 &wmfw_firmware
, &wmfw_filename
,
909 &coeff_firmware
, &coeff_filename
);
913 ret
= cs_dsp_adsp1_power_up(&dsp
->cs_dsp
,
914 wmfw_firmware
, wmfw_filename
,
915 coeff_firmware
, coeff_filename
,
916 wm_adsp_fw_text
[dsp
->fw
]);
918 wm_adsp_release_firmware_files(dsp
,
919 wmfw_firmware
, wmfw_filename
,
920 coeff_firmware
, coeff_filename
);
922 case SND_SOC_DAPM_PRE_PMD
:
923 cs_dsp_adsp1_power_down(&dsp
->cs_dsp
);
931 EXPORT_SYMBOL_GPL(wm_adsp1_event
);
933 int wm_adsp2_set_dspclk(struct snd_soc_dapm_widget
*w
, unsigned int freq
)
935 struct snd_soc_component
*component
= snd_soc_dapm_to_component(w
->dapm
);
936 struct wm_adsp
*dsps
= snd_soc_component_get_drvdata(component
);
937 struct wm_adsp
*dsp
= &dsps
[w
->shift
];
939 return cs_dsp_set_dspclk(&dsp
->cs_dsp
, freq
);
941 EXPORT_SYMBOL_GPL(wm_adsp2_set_dspclk
);
943 int wm_adsp2_preloader_get(struct snd_kcontrol
*kcontrol
,
944 struct snd_ctl_elem_value
*ucontrol
)
946 struct snd_soc_component
*component
= snd_soc_kcontrol_component(kcontrol
);
947 struct wm_adsp
*dsps
= snd_soc_component_get_drvdata(component
);
948 struct soc_mixer_control
*mc
=
949 (struct soc_mixer_control
*)kcontrol
->private_value
;
950 struct wm_adsp
*dsp
= &dsps
[mc
->shift
- 1];
952 ucontrol
->value
.integer
.value
[0] = dsp
->preloaded
;
956 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_get
);
958 int wm_adsp2_preloader_put(struct snd_kcontrol
*kcontrol
,
959 struct snd_ctl_elem_value
*ucontrol
)
961 struct snd_soc_component
*component
= snd_soc_kcontrol_component(kcontrol
);
962 struct wm_adsp
*dsps
= snd_soc_component_get_drvdata(component
);
963 struct snd_soc_dapm_context
*dapm
= snd_soc_component_get_dapm(component
);
964 struct soc_mixer_control
*mc
=
965 (struct soc_mixer_control
*)kcontrol
->private_value
;
966 struct wm_adsp
*dsp
= &dsps
[mc
->shift
- 1];
969 if (dsp
->preloaded
== ucontrol
->value
.integer
.value
[0])
972 snprintf(preload
, ARRAY_SIZE(preload
), "%s Preload", dsp
->cs_dsp
.name
);
974 if (ucontrol
->value
.integer
.value
[0] || dsp
->toggle_preload
)
975 snd_soc_component_force_enable_pin(component
, preload
);
977 snd_soc_component_disable_pin(component
, preload
);
979 snd_soc_dapm_sync(dapm
);
981 flush_work(&dsp
->boot_work
);
983 dsp
->preloaded
= ucontrol
->value
.integer
.value
[0];
985 if (dsp
->toggle_preload
) {
986 snd_soc_component_disable_pin(component
, preload
);
987 snd_soc_dapm_sync(dapm
);
992 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put
);
994 int wm_adsp_power_up(struct wm_adsp
*dsp
, bool load_firmware
)
997 char *wmfw_filename
= NULL
;
998 const struct firmware
*wmfw_firmware
= NULL
;
999 char *coeff_filename
= NULL
;
1000 const struct firmware
*coeff_firmware
= NULL
;
1002 if (load_firmware
) {
1003 ret
= wm_adsp_request_firmware_files(dsp
,
1004 &wmfw_firmware
, &wmfw_filename
,
1005 &coeff_firmware
, &coeff_filename
);
1010 ret
= cs_dsp_power_up(&dsp
->cs_dsp
,
1011 wmfw_firmware
, wmfw_filename
,
1012 coeff_firmware
, coeff_filename
,
1013 wm_adsp_fw_text
[dsp
->fw
]);
1015 wm_adsp_release_firmware_files(dsp
,
1016 wmfw_firmware
, wmfw_filename
,
1017 coeff_firmware
, coeff_filename
);
1021 EXPORT_SYMBOL_GPL(wm_adsp_power_up
);
1023 void wm_adsp_power_down(struct wm_adsp
*dsp
)
1025 cs_dsp_power_down(&dsp
->cs_dsp
);
1027 EXPORT_SYMBOL_GPL(wm_adsp_power_down
);
1029 static void wm_adsp_boot_work(struct work_struct
*work
)
1031 struct wm_adsp
*dsp
= container_of(work
,
1035 wm_adsp_power_up(dsp
, true);
1038 int wm_adsp_early_event(struct snd_soc_dapm_widget
*w
,
1039 struct snd_kcontrol
*kcontrol
, int event
)
1041 struct snd_soc_component
*component
= snd_soc_dapm_to_component(w
->dapm
);
1042 struct wm_adsp
*dsps
= snd_soc_component_get_drvdata(component
);
1043 struct wm_adsp
*dsp
= &dsps
[w
->shift
];
1046 case SND_SOC_DAPM_PRE_PMU
:
1047 queue_work(system_unbound_wq
, &dsp
->boot_work
);
1049 case SND_SOC_DAPM_PRE_PMD
:
1050 wm_adsp_power_down(dsp
);
1058 EXPORT_SYMBOL_GPL(wm_adsp_early_event
);
1060 static int wm_adsp_pre_run(struct cs_dsp
*cs_dsp
)
1062 struct wm_adsp
*dsp
= container_of(cs_dsp
, struct wm_adsp
, cs_dsp
);
1067 return (*dsp
->pre_run
)(dsp
);
1070 static int wm_adsp_event_post_run(struct cs_dsp
*cs_dsp
)
1072 struct wm_adsp
*dsp
= container_of(cs_dsp
, struct wm_adsp
, cs_dsp
);
1074 if (wm_adsp_fw
[dsp
->fw
].num_caps
!= 0)
1075 return wm_adsp_buffer_init(dsp
);
1080 static void wm_adsp_event_post_stop(struct cs_dsp
*cs_dsp
)
1082 struct wm_adsp
*dsp
= container_of(cs_dsp
, struct wm_adsp
, cs_dsp
);
1084 if (wm_adsp_fw
[dsp
->fw
].num_caps
!= 0)
1085 wm_adsp_buffer_free(dsp
);
1087 dsp
->fatal_error
= false;
1090 int wm_adsp_run(struct wm_adsp
*dsp
)
1092 flush_work(&dsp
->boot_work
);
1094 return cs_dsp_run(&dsp
->cs_dsp
);
1096 EXPORT_SYMBOL_GPL(wm_adsp_run
);
1098 void wm_adsp_stop(struct wm_adsp
*dsp
)
1100 cs_dsp_stop(&dsp
->cs_dsp
);
1102 EXPORT_SYMBOL_GPL(wm_adsp_stop
);
1104 int wm_adsp_event(struct snd_soc_dapm_widget
*w
,
1105 struct snd_kcontrol
*kcontrol
, int event
)
1107 struct snd_soc_component
*component
= snd_soc_dapm_to_component(w
->dapm
);
1108 struct wm_adsp
*dsps
= snd_soc_component_get_drvdata(component
);
1109 struct wm_adsp
*dsp
= &dsps
[w
->shift
];
1112 case SND_SOC_DAPM_POST_PMU
:
1113 return wm_adsp_run(dsp
);
1114 case SND_SOC_DAPM_PRE_PMD
:
1121 EXPORT_SYMBOL_GPL(wm_adsp_event
);
1123 int wm_adsp2_component_probe(struct wm_adsp
*dsp
, struct snd_soc_component
*component
)
1127 if (!dsp
->cs_dsp
.no_core_startstop
) {
1128 snprintf(preload
, ARRAY_SIZE(preload
), "%s Preload", dsp
->cs_dsp
.name
);
1129 snd_soc_component_disable_pin(component
, preload
);
1132 cs_dsp_init_debugfs(&dsp
->cs_dsp
, component
->debugfs_root
);
1134 dsp
->component
= component
;
1138 EXPORT_SYMBOL_GPL(wm_adsp2_component_probe
);
1140 int wm_adsp2_component_remove(struct wm_adsp
*dsp
, struct snd_soc_component
*component
)
1142 cs_dsp_cleanup_debugfs(&dsp
->cs_dsp
);
1146 EXPORT_SYMBOL_GPL(wm_adsp2_component_remove
);
1148 int wm_adsp2_init(struct wm_adsp
*dsp
)
1152 INIT_WORK(&dsp
->boot_work
, wm_adsp_boot_work
);
1154 dsp
->sys_config_size
= sizeof(struct wm_adsp_system_config_xm_hdr
);
1155 dsp
->cs_dsp
.client_ops
= &wm_adsp2_client_ops
;
1157 ret
= cs_dsp_adsp2_init(&dsp
->cs_dsp
);
1161 return wm_adsp_common_init(dsp
);
1163 EXPORT_SYMBOL_GPL(wm_adsp2_init
);
1165 int wm_halo_init(struct wm_adsp
*dsp
)
1169 INIT_WORK(&dsp
->boot_work
, wm_adsp_boot_work
);
1171 dsp
->sys_config_size
= sizeof(struct wm_halo_system_config_xm_hdr
);
1172 dsp
->cs_dsp
.client_ops
= &wm_adsp2_client_ops
;
1174 ret
= cs_dsp_halo_init(&dsp
->cs_dsp
);
1178 return wm_adsp_common_init(dsp
);
1180 EXPORT_SYMBOL_GPL(wm_halo_init
);
1182 void wm_adsp2_remove(struct wm_adsp
*dsp
)
1184 cs_dsp_remove(&dsp
->cs_dsp
);
1186 EXPORT_SYMBOL_GPL(wm_adsp2_remove
);
1188 static inline int wm_adsp_compr_attached(struct wm_adsp_compr
*compr
)
1190 return compr
->buf
!= NULL
;
1193 static int wm_adsp_compr_attach(struct wm_adsp_compr
*compr
)
1195 struct wm_adsp_compr_buf
*buf
= NULL
, *tmp
;
1197 if (compr
->dsp
->fatal_error
)
1200 list_for_each_entry(tmp
, &compr
->dsp
->buffer_list
, list
) {
1201 if (!tmp
->name
|| !strcmp(compr
->name
, tmp
->name
)) {
1216 static void wm_adsp_compr_detach(struct wm_adsp_compr
*compr
)
1221 /* Wake the poll so it can see buffer is no longer attached */
1223 snd_compr_fragment_elapsed(compr
->stream
);
1225 if (wm_adsp_compr_attached(compr
)) {
1226 compr
->buf
->compr
= NULL
;
1231 int wm_adsp_compr_open(struct wm_adsp
*dsp
, struct snd_compr_stream
*stream
)
1233 struct wm_adsp_compr
*compr
, *tmp
;
1234 struct snd_soc_pcm_runtime
*rtd
= stream
->private_data
;
1237 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
1239 if (wm_adsp_fw
[dsp
->fw
].num_caps
== 0) {
1240 adsp_err(dsp
, "%s: Firmware does not support compressed API\n",
1241 snd_soc_rtd_to_codec(rtd
, 0)->name
);
1246 if (wm_adsp_fw
[dsp
->fw
].compr_direction
!= stream
->direction
) {
1247 adsp_err(dsp
, "%s: Firmware does not support stream direction\n",
1248 snd_soc_rtd_to_codec(rtd
, 0)->name
);
1253 list_for_each_entry(tmp
, &dsp
->compr_list
, list
) {
1254 if (!strcmp(tmp
->name
, snd_soc_rtd_to_codec(rtd
, 0)->name
)) {
1255 adsp_err(dsp
, "%s: Only a single stream supported per dai\n",
1256 snd_soc_rtd_to_codec(rtd
, 0)->name
);
1262 compr
= kzalloc(sizeof(*compr
), GFP_KERNEL
);
1269 compr
->stream
= stream
;
1270 compr
->name
= snd_soc_rtd_to_codec(rtd
, 0)->name
;
1272 list_add_tail(&compr
->list
, &dsp
->compr_list
);
1274 stream
->runtime
->private_data
= compr
;
1277 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
1281 EXPORT_SYMBOL_GPL(wm_adsp_compr_open
);
1283 int wm_adsp_compr_free(struct snd_soc_component
*component
,
1284 struct snd_compr_stream
*stream
)
1286 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
1287 struct wm_adsp
*dsp
= compr
->dsp
;
1289 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
1291 wm_adsp_compr_detach(compr
);
1292 list_del(&compr
->list
);
1294 kfree(compr
->raw_buf
);
1297 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
1301 EXPORT_SYMBOL_GPL(wm_adsp_compr_free
);
1303 static int wm_adsp_compr_check_params(struct snd_compr_stream
*stream
,
1304 struct snd_compr_params
*params
)
1306 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
1307 struct wm_adsp
*dsp
= compr
->dsp
;
1308 const struct wm_adsp_fw_caps
*caps
;
1309 const struct snd_codec_desc
*desc
;
1312 if (params
->buffer
.fragment_size
< WM_ADSP_MIN_FRAGMENT_SIZE
||
1313 params
->buffer
.fragment_size
> WM_ADSP_MAX_FRAGMENT_SIZE
||
1314 params
->buffer
.fragments
< WM_ADSP_MIN_FRAGMENTS
||
1315 params
->buffer
.fragments
> WM_ADSP_MAX_FRAGMENTS
||
1316 params
->buffer
.fragment_size
% CS_DSP_DATA_WORD_SIZE
) {
1317 compr_err(compr
, "Invalid buffer fragsize=%d fragments=%d\n",
1318 params
->buffer
.fragment_size
,
1319 params
->buffer
.fragments
);
1324 for (i
= 0; i
< wm_adsp_fw
[dsp
->fw
].num_caps
; i
++) {
1325 caps
= &wm_adsp_fw
[dsp
->fw
].caps
[i
];
1328 if (caps
->id
!= params
->codec
.id
)
1331 if (stream
->direction
== SND_COMPRESS_PLAYBACK
) {
1332 if (desc
->max_ch
< params
->codec
.ch_out
)
1335 if (desc
->max_ch
< params
->codec
.ch_in
)
1339 if (!(desc
->formats
& (1 << params
->codec
.format
)))
1342 for (j
= 0; j
< desc
->num_sample_rates
; ++j
)
1343 if (desc
->sample_rates
[j
] == params
->codec
.sample_rate
)
1347 compr_err(compr
, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
1348 params
->codec
.id
, params
->codec
.ch_in
, params
->codec
.ch_out
,
1349 params
->codec
.sample_rate
, params
->codec
.format
);
1353 static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr
*compr
)
1355 return compr
->size
.fragment_size
/ CS_DSP_DATA_WORD_SIZE
;
1358 int wm_adsp_compr_set_params(struct snd_soc_component
*component
,
1359 struct snd_compr_stream
*stream
,
1360 struct snd_compr_params
*params
)
1362 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
1366 ret
= wm_adsp_compr_check_params(stream
, params
);
1370 compr
->size
= params
->buffer
;
1372 compr_dbg(compr
, "fragment_size=%d fragments=%d\n",
1373 compr
->size
.fragment_size
, compr
->size
.fragments
);
1375 size
= wm_adsp_compr_frag_words(compr
) * sizeof(*compr
->raw_buf
);
1376 compr
->raw_buf
= kmalloc(size
, GFP_DMA
| GFP_KERNEL
);
1377 if (!compr
->raw_buf
)
1380 compr
->sample_rate
= params
->codec
.sample_rate
;
1384 EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params
);
1386 int wm_adsp_compr_get_caps(struct snd_soc_component
*component
,
1387 struct snd_compr_stream
*stream
,
1388 struct snd_compr_caps
*caps
)
1390 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
1391 int fw
= compr
->dsp
->fw
;
1394 if (wm_adsp_fw
[fw
].caps
) {
1395 for (i
= 0; i
< wm_adsp_fw
[fw
].num_caps
; i
++)
1396 caps
->codecs
[i
] = wm_adsp_fw
[fw
].caps
[i
].id
;
1398 caps
->num_codecs
= i
;
1399 caps
->direction
= wm_adsp_fw
[fw
].compr_direction
;
1401 caps
->min_fragment_size
= WM_ADSP_MIN_FRAGMENT_SIZE
;
1402 caps
->max_fragment_size
= WM_ADSP_MAX_FRAGMENT_SIZE
;
1403 caps
->min_fragments
= WM_ADSP_MIN_FRAGMENTS
;
1404 caps
->max_fragments
= WM_ADSP_MAX_FRAGMENTS
;
1409 EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps
);
1411 static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf
*buf
,
1412 unsigned int field_offset
, u32
*data
)
1414 return cs_dsp_read_data_word(&buf
->dsp
->cs_dsp
, buf
->host_buf_mem_type
,
1415 buf
->host_buf_ptr
+ field_offset
, data
);
1418 static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf
*buf
,
1419 unsigned int field_offset
, u32 data
)
1421 return cs_dsp_write_data_word(&buf
->dsp
->cs_dsp
, buf
->host_buf_mem_type
,
1422 buf
->host_buf_ptr
+ field_offset
,
1426 static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf
*buf
)
1428 const struct wm_adsp_fw_caps
*caps
= wm_adsp_fw
[buf
->dsp
->fw
].caps
;
1429 struct wm_adsp_buffer_region
*region
;
1433 buf
->regions
= kcalloc(caps
->num_regions
, sizeof(*buf
->regions
),
1438 for (i
= 0; i
< caps
->num_regions
; ++i
) {
1439 region
= &buf
->regions
[i
];
1441 region
->offset
= offset
;
1442 region
->mem_type
= caps
->region_defs
[i
].mem_type
;
1444 ret
= wm_adsp_buffer_read(buf
, caps
->region_defs
[i
].base_offset
,
1445 ®ion
->base_addr
);
1449 ret
= wm_adsp_buffer_read(buf
, caps
->region_defs
[i
].size_offset
,
1454 region
->cumulative_size
= offset
;
1457 "region=%d type=%d base=%08x off=%08x size=%08x\n",
1458 i
, region
->mem_type
, region
->base_addr
,
1459 region
->offset
, region
->cumulative_size
);
1465 kfree(buf
->regions
);
1469 static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf
*buf
)
1471 buf
->irq_count
= 0xFFFFFFFF;
1472 buf
->read_index
= -1;
1476 static struct wm_adsp_compr_buf
*wm_adsp_buffer_alloc(struct wm_adsp
*dsp
)
1478 struct wm_adsp_compr_buf
*buf
;
1480 buf
= kzalloc(sizeof(*buf
), GFP_KERNEL
);
1486 wm_adsp_buffer_clear(buf
);
1491 static int wm_adsp_buffer_parse_legacy(struct wm_adsp
*dsp
)
1493 struct cs_dsp_alg_region
*alg_region
;
1494 struct wm_adsp_compr_buf
*buf
;
1495 u32 xmalg
, addr
, magic
;
1498 alg_region
= cs_dsp_find_alg_region(&dsp
->cs_dsp
, WMFW_ADSP2_XM
, dsp
->cs_dsp
.fw_id
);
1500 adsp_err(dsp
, "No algorithm region found\n");
1504 xmalg
= dsp
->sys_config_size
/ sizeof(__be32
);
1506 addr
= alg_region
->base
+ xmalg
+ ALG_XM_FIELD(magic
);
1507 ret
= cs_dsp_read_data_word(&dsp
->cs_dsp
, WMFW_ADSP2_XM
, addr
, &magic
);
1511 if (magic
!= WM_ADSP_ALG_XM_STRUCT_MAGIC
)
1514 buf
= wm_adsp_buffer_alloc(dsp
);
1518 addr
= alg_region
->base
+ xmalg
+ ALG_XM_FIELD(host_buf_ptr
);
1519 for (i
= 0; i
< 5; ++i
) {
1520 ret
= cs_dsp_read_data_word(&dsp
->cs_dsp
, WMFW_ADSP2_XM
, addr
,
1521 &buf
->host_buf_ptr
);
1525 if (buf
->host_buf_ptr
)
1528 usleep_range(1000, 2000);
1531 if (!buf
->host_buf_ptr
) {
1536 buf
->host_buf_mem_type
= WMFW_ADSP2_XM
;
1538 ret
= wm_adsp_buffer_populate(buf
);
1542 list_add_tail(&buf
->list
, &dsp
->buffer_list
);
1544 compr_dbg(buf
, "legacy host_buf_ptr=%x\n", buf
->host_buf_ptr
);
1554 static int wm_adsp_buffer_parse_coeff(struct cs_dsp_coeff_ctl
*cs_ctl
)
1556 struct wm_adsp_host_buf_coeff_v1 coeff_v1
;
1557 struct wm_adsp_compr_buf
*buf
;
1558 struct wm_adsp
*dsp
= container_of(cs_ctl
->dsp
, struct wm_adsp
, cs_dsp
);
1559 unsigned int version
= 0;
1562 for (i
= 0; i
< 5; ++i
) {
1563 ret
= cs_dsp_coeff_read_ctrl(cs_ctl
, 0, &coeff_v1
,
1564 min(cs_ctl
->len
, sizeof(coeff_v1
)));
1568 if (coeff_v1
.host_buf_ptr
)
1571 usleep_range(1000, 2000);
1574 if (!coeff_v1
.host_buf_ptr
) {
1575 adsp_err(dsp
, "Failed to acquire host buffer\n");
1579 buf
= wm_adsp_buffer_alloc(dsp
);
1583 buf
->host_buf_mem_type
= cs_ctl
->alg_region
.type
;
1584 buf
->host_buf_ptr
= be32_to_cpu(coeff_v1
.host_buf_ptr
);
1586 ret
= wm_adsp_buffer_populate(buf
);
1591 * v0 host_buffer coefficients didn't have versioning, so if the
1592 * control is one word, assume version 0.
1594 if (cs_ctl
->len
== 4)
1597 version
= be32_to_cpu(coeff_v1
.versions
) & HOST_BUF_COEFF_COMPAT_VER_MASK
;
1598 version
>>= HOST_BUF_COEFF_COMPAT_VER_SHIFT
;
1600 if (version
> HOST_BUF_COEFF_SUPPORTED_COMPAT_VER
) {
1602 "Host buffer coeff ver %u > supported version %u\n",
1603 version
, HOST_BUF_COEFF_SUPPORTED_COMPAT_VER
);
1608 cs_dsp_remove_padding((u32
*)&coeff_v1
.name
, ARRAY_SIZE(coeff_v1
.name
));
1610 buf
->name
= kasprintf(GFP_KERNEL
, "%s-dsp-%s", dsp
->part
,
1611 (char *)&coeff_v1
.name
);
1614 list_add_tail(&buf
->list
, &dsp
->buffer_list
);
1616 compr_dbg(buf
, "host_buf_ptr=%x coeff version %u\n",
1617 buf
->host_buf_ptr
, version
);
1627 static int wm_adsp_buffer_init(struct wm_adsp
*dsp
)
1629 struct cs_dsp_coeff_ctl
*cs_ctl
;
1632 list_for_each_entry(cs_ctl
, &dsp
->cs_dsp
.ctl_list
, list
) {
1633 if (cs_ctl
->type
!= WMFW_CTL_TYPE_HOST_BUFFER
)
1636 if (!cs_ctl
->enabled
)
1639 ret
= wm_adsp_buffer_parse_coeff(cs_ctl
);
1641 adsp_err(dsp
, "Failed to parse coeff: %d\n", ret
);
1643 } else if (ret
== 0) {
1644 /* Only one buffer supported for version 0 */
1649 if (list_empty(&dsp
->buffer_list
)) {
1650 /* Fall back to legacy support */
1651 ret
= wm_adsp_buffer_parse_legacy(dsp
);
1653 adsp_info(dsp
, "Legacy support not available\n");
1655 adsp_warn(dsp
, "Failed to parse legacy: %d\n", ret
);
1661 wm_adsp_buffer_free(dsp
);
1665 static int wm_adsp_buffer_free(struct wm_adsp
*dsp
)
1667 struct wm_adsp_compr_buf
*buf
, *tmp
;
1669 list_for_each_entry_safe(buf
, tmp
, &dsp
->buffer_list
, list
) {
1670 wm_adsp_compr_detach(buf
->compr
);
1673 kfree(buf
->regions
);
1674 list_del(&buf
->list
);
1681 static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf
*buf
)
1685 ret
= wm_adsp_buffer_read(buf
, HOST_BUFFER_FIELD(error
), &buf
->error
);
1687 compr_err(buf
, "Failed to check buffer error: %d\n", ret
);
1690 if (buf
->error
!= 0) {
1691 compr_err(buf
, "Buffer error occurred: %d\n", buf
->error
);
1698 int wm_adsp_compr_trigger(struct snd_soc_component
*component
,
1699 struct snd_compr_stream
*stream
, int cmd
)
1701 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
1702 struct wm_adsp
*dsp
= compr
->dsp
;
1705 compr_dbg(compr
, "Trigger: %d\n", cmd
);
1707 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
1710 case SNDRV_PCM_TRIGGER_START
:
1711 if (!wm_adsp_compr_attached(compr
)) {
1712 ret
= wm_adsp_compr_attach(compr
);
1714 compr_err(compr
, "Failed to link buffer and stream: %d\n",
1720 ret
= wm_adsp_buffer_get_error(compr
->buf
);
1724 /* Trigger the IRQ at one fragment of data */
1725 ret
= wm_adsp_buffer_write(compr
->buf
,
1726 HOST_BUFFER_FIELD(high_water_mark
),
1727 wm_adsp_compr_frag_words(compr
));
1729 compr_err(compr
, "Failed to set high water mark: %d\n",
1734 case SNDRV_PCM_TRIGGER_STOP
:
1735 if (wm_adsp_compr_attached(compr
))
1736 wm_adsp_buffer_clear(compr
->buf
);
1743 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
1747 EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger
);
1749 static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf
*buf
)
1751 int last_region
= wm_adsp_fw
[buf
->dsp
->fw
].caps
->num_regions
- 1;
1753 return buf
->regions
[last_region
].cumulative_size
;
1756 static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf
*buf
)
1758 u32 next_read_index
, next_write_index
;
1759 int write_index
, read_index
, avail
;
1762 /* Only sync read index if we haven't already read a valid index */
1763 if (buf
->read_index
< 0) {
1764 ret
= wm_adsp_buffer_read(buf
,
1765 HOST_BUFFER_FIELD(next_read_index
),
1770 read_index
= sign_extend32(next_read_index
, 23);
1772 if (read_index
< 0) {
1773 compr_dbg(buf
, "Avail check on unstarted stream\n");
1777 buf
->read_index
= read_index
;
1780 ret
= wm_adsp_buffer_read(buf
, HOST_BUFFER_FIELD(next_write_index
),
1785 write_index
= sign_extend32(next_write_index
, 23);
1787 avail
= write_index
- buf
->read_index
;
1789 avail
+= wm_adsp_buffer_size(buf
);
1791 compr_dbg(buf
, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
1792 buf
->read_index
, write_index
, avail
* CS_DSP_DATA_WORD_SIZE
);
1799 int wm_adsp_compr_handle_irq(struct wm_adsp
*dsp
)
1801 struct wm_adsp_compr_buf
*buf
;
1802 struct wm_adsp_compr
*compr
;
1805 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
1807 if (list_empty(&dsp
->buffer_list
)) {
1812 adsp_dbg(dsp
, "Handling buffer IRQ\n");
1814 list_for_each_entry(buf
, &dsp
->buffer_list
, list
) {
1817 ret
= wm_adsp_buffer_get_error(buf
);
1819 goto out_notify
; /* Wake poll to report error */
1821 ret
= wm_adsp_buffer_read(buf
, HOST_BUFFER_FIELD(irq_count
),
1824 compr_err(buf
, "Failed to get irq_count: %d\n", ret
);
1828 ret
= wm_adsp_buffer_update_avail(buf
);
1830 compr_err(buf
, "Error reading avail: %d\n", ret
);
1834 if (wm_adsp_fw
[dsp
->fw
].voice_trigger
&& buf
->irq_count
== 2)
1835 ret
= WM_ADSP_COMPR_VOICE_TRIGGER
;
1838 if (compr
&& compr
->stream
)
1839 snd_compr_fragment_elapsed(compr
->stream
);
1843 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
1847 EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq
);
1849 static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf
*buf
)
1851 if (buf
->irq_count
& 0x01)
1854 compr_dbg(buf
, "Enable IRQ(0x%x) for next fragment\n", buf
->irq_count
);
1856 buf
->irq_count
|= 0x01;
1858 return wm_adsp_buffer_write(buf
, HOST_BUFFER_FIELD(irq_ack
),
1862 int wm_adsp_compr_pointer(struct snd_soc_component
*component
,
1863 struct snd_compr_stream
*stream
,
1864 struct snd_compr_tstamp
*tstamp
)
1866 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
1867 struct wm_adsp
*dsp
= compr
->dsp
;
1868 struct wm_adsp_compr_buf
*buf
;
1871 compr_dbg(compr
, "Pointer request\n");
1873 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
1877 if (dsp
->fatal_error
|| !buf
|| buf
->error
) {
1878 snd_compr_stop_error(stream
, SNDRV_PCM_STATE_XRUN
);
1883 if (buf
->avail
< wm_adsp_compr_frag_words(compr
)) {
1884 ret
= wm_adsp_buffer_update_avail(buf
);
1886 compr_err(compr
, "Error reading avail: %d\n", ret
);
1891 * If we really have less than 1 fragment available tell the
1892 * DSP to inform us once a whole fragment is available.
1894 if (buf
->avail
< wm_adsp_compr_frag_words(compr
)) {
1895 ret
= wm_adsp_buffer_get_error(buf
);
1898 snd_compr_stop_error(stream
,
1899 SNDRV_PCM_STATE_XRUN
);
1903 ret
= wm_adsp_buffer_reenable_irq(buf
);
1905 compr_err(compr
, "Failed to re-enable buffer IRQ: %d\n",
1912 tstamp
->copied_total
= compr
->copied_total
;
1913 tstamp
->copied_total
+= buf
->avail
* CS_DSP_DATA_WORD_SIZE
;
1914 tstamp
->sampling_rate
= compr
->sample_rate
;
1917 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
1921 EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer
);
1923 static int wm_adsp_buffer_capture_block(struct wm_adsp_compr
*compr
, int target
)
1925 struct wm_adsp_compr_buf
*buf
= compr
->buf
;
1926 unsigned int adsp_addr
;
1927 int mem_type
, nwords
, max_read
;
1930 /* Calculate read parameters */
1931 for (i
= 0; i
< wm_adsp_fw
[buf
->dsp
->fw
].caps
->num_regions
; ++i
)
1932 if (buf
->read_index
< buf
->regions
[i
].cumulative_size
)
1935 if (i
== wm_adsp_fw
[buf
->dsp
->fw
].caps
->num_regions
)
1938 mem_type
= buf
->regions
[i
].mem_type
;
1939 adsp_addr
= buf
->regions
[i
].base_addr
+
1940 (buf
->read_index
- buf
->regions
[i
].offset
);
1942 max_read
= wm_adsp_compr_frag_words(compr
);
1943 nwords
= buf
->regions
[i
].cumulative_size
- buf
->read_index
;
1945 if (nwords
> target
)
1947 if (nwords
> buf
->avail
)
1948 nwords
= buf
->avail
;
1949 if (nwords
> max_read
)
1954 /* Read data from DSP */
1955 ret
= cs_dsp_read_raw_data_block(&buf
->dsp
->cs_dsp
, mem_type
, adsp_addr
,
1956 nwords
, (__be32
*)compr
->raw_buf
);
1960 cs_dsp_remove_padding(compr
->raw_buf
, nwords
);
1962 /* update read index to account for words read */
1963 buf
->read_index
+= nwords
;
1964 if (buf
->read_index
== wm_adsp_buffer_size(buf
))
1965 buf
->read_index
= 0;
1967 ret
= wm_adsp_buffer_write(buf
, HOST_BUFFER_FIELD(next_read_index
),
1972 /* update avail to account for words read */
1973 buf
->avail
-= nwords
;
1978 static int wm_adsp_compr_read(struct wm_adsp_compr
*compr
,
1979 char __user
*buf
, size_t count
)
1981 struct wm_adsp
*dsp
= compr
->dsp
;
1985 compr_dbg(compr
, "Requested read of %zu bytes\n", count
);
1987 if (dsp
->fatal_error
|| !compr
->buf
|| compr
->buf
->error
) {
1988 snd_compr_stop_error(compr
->stream
, SNDRV_PCM_STATE_XRUN
);
1992 count
/= CS_DSP_DATA_WORD_SIZE
;
1995 nwords
= wm_adsp_buffer_capture_block(compr
, count
);
1997 compr_err(compr
, "Failed to capture block: %d\n",
2002 nbytes
= nwords
* CS_DSP_DATA_WORD_SIZE
;
2004 compr_dbg(compr
, "Read %d bytes\n", nbytes
);
2006 if (copy_to_user(buf
+ ntotal
, compr
->raw_buf
, nbytes
)) {
2007 compr_err(compr
, "Failed to copy data to user: %d, %d\n",
2014 } while (nwords
> 0 && count
> 0);
2016 compr
->copied_total
+= ntotal
;
2021 int wm_adsp_compr_copy(struct snd_soc_component
*component
,
2022 struct snd_compr_stream
*stream
, char __user
*buf
,
2025 struct wm_adsp_compr
*compr
= stream
->runtime
->private_data
;
2026 struct wm_adsp
*dsp
= compr
->dsp
;
2029 mutex_lock(&dsp
->cs_dsp
.pwr_lock
);
2031 if (stream
->direction
== SND_COMPRESS_CAPTURE
)
2032 ret
= wm_adsp_compr_read(compr
, buf
, count
);
2036 mutex_unlock(&dsp
->cs_dsp
.pwr_lock
);
2040 EXPORT_SYMBOL_GPL(wm_adsp_compr_copy
);
2042 static void wm_adsp_fatal_error(struct cs_dsp
*cs_dsp
)
2044 struct wm_adsp
*dsp
= container_of(cs_dsp
, struct wm_adsp
, cs_dsp
);
2045 struct wm_adsp_compr
*compr
;
2047 dsp
->fatal_error
= true;
2049 list_for_each_entry(compr
, &dsp
->compr_list
, list
) {
2051 snd_compr_fragment_elapsed(compr
->stream
);
2055 irqreturn_t
wm_adsp2_bus_error(int irq
, void *data
)
2057 struct wm_adsp
*dsp
= (struct wm_adsp
*)data
;
2059 cs_dsp_adsp2_bus_error(&dsp
->cs_dsp
);
2063 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error
);
2065 irqreturn_t
wm_halo_bus_error(int irq
, void *data
)
2067 struct wm_adsp
*dsp
= (struct wm_adsp
*)data
;
2069 cs_dsp_halo_bus_error(&dsp
->cs_dsp
);
2073 EXPORT_SYMBOL_GPL(wm_halo_bus_error
);
2075 irqreturn_t
wm_halo_wdt_expire(int irq
, void *data
)
2077 struct wm_adsp
*dsp
= data
;
2079 cs_dsp_halo_wdt_expire(&dsp
->cs_dsp
);
2083 EXPORT_SYMBOL_GPL(wm_halo_wdt_expire
);
2085 static const struct cs_dsp_client_ops wm_adsp1_client_ops
= {
2086 .control_add
= wm_adsp_control_add_cb
,
2087 .control_remove
= wm_adsp_control_remove
,
2090 static const struct cs_dsp_client_ops wm_adsp2_client_ops
= {
2091 .control_add
= wm_adsp_control_add_cb
,
2092 .control_remove
= wm_adsp_control_remove
,
2093 .pre_run
= wm_adsp_pre_run
,
2094 .post_run
= wm_adsp_event_post_run
,
2095 .post_stop
= wm_adsp_event_post_stop
,
2096 .watchdog_expired
= wm_adsp_fatal_error
,
2099 MODULE_DESCRIPTION("Cirrus Logic ASoC DSP Support");
2100 MODULE_LICENSE("GPL v2");
2101 MODULE_IMPORT_NS("FW_CS_DSP");