Compare commits
335 commits
v2,0
...
v6.6-order
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c3f0119ae9 | ||
![]() |
c693d203d9 | ||
![]() |
005fc23648 | ||
![]() |
58082f3fe8 | ||
![]() |
cc37c8fb52 | ||
![]() |
c3a2d96ba2 | ||
![]() |
7aef82f3be | ||
![]() |
4ab8158c18 | ||
![]() |
8f377d1eaa | ||
![]() |
aaa2090dbf | ||
![]() |
f25e76508f | ||
![]() |
a46c3f6324 | ||
![]() |
2a40c7dbff | ||
![]() |
f69370b841 | ||
![]() |
a03624a0ce | ||
![]() |
0bb3ca6c98 | ||
![]() |
18e297d2d8 | ||
![]() |
280bb390a2 | ||
![]() |
19ca5aeb50 | ||
![]() |
ebd1fa605c | ||
![]() |
a57389693c | ||
![]() |
977a7ff321 | ||
![]() |
4d0e36d426 | ||
![]() |
99bbf880e9 | ||
![]() |
8dbe3726b7 | ||
![]() |
e452172d8c | ||
![]() |
a8ee041f21 | ||
![]() |
6bf1dbd04e | ||
![]() |
b093f59250 | ||
![]() |
8fa56e18bb | ||
![]() |
dd9391fb78 | ||
![]() |
d840f77541 | ||
![]() |
bd7623e9fb | ||
![]() |
17e2875d4d | ||
![]() |
b595b95b21 | ||
![]() |
48dbb3f815 | ||
![]() |
41a09a3b67 | ||
![]() |
81e0f0879d | ||
![]() |
d841b2a0fb | ||
![]() |
f9427ea449 | ||
![]() |
efa999f0f3 | ||
![]() |
d688a02f14 | ||
![]() |
a1a51f8aab | ||
![]() |
31d750c981 | ||
![]() |
c8d97904ce | ||
![]() |
c5f3836dd8 | ||
![]() |
19067f3333 | ||
![]() |
5793cf6bf0 | ||
![]() |
ffcdafb798 | ||
![]() |
e553d4f851 | ||
![]() |
de70691526 | ||
![]() |
1774a54301 | ||
![]() |
af484de3af | ||
![]() |
9796ad49ff | ||
![]() |
43b6034266 | ||
![]() |
eab694c170 | ||
![]() |
fdd67ea2c4 | ||
![]() |
f8d47b5c64 | ||
![]() |
47d09dba0e | ||
![]() |
d692927067 | ||
![]() |
14317817f8 | ||
![]() |
3ba6aec5bb | ||
![]() |
8b2094fc23 | ||
![]() |
c84b644247 | ||
![]() |
8e1c59be7e | ||
![]() |
f289f5586e | ||
![]() |
3ad10c131c | ||
![]() |
cbb5e082f2 | ||
![]() |
43532cfada | ||
![]() |
eea6066d70 | ||
![]() |
44d47226dc | ||
![]() |
50dbe24b78 | ||
![]() |
ebcf755c1a | ||
![]() |
484c03d4c8 | ||
![]() |
a79b7d94a5 | ||
![]() |
87f42ed64d | ||
![]() |
379f791b3c | ||
![]() |
8cce4e8ffa | ||
![]() |
ac2bf5f638 | ||
![]() |
4b7559b320 | ||
![]() |
526d0ddef9 | ||
![]() |
6fb0c63581 | ||
![]() |
06e054aa06 | ||
![]() |
1a7fbee50e | ||
![]() |
7e635f5d57 | ||
![]() |
7461921407 | ||
![]() |
794d7a3527 | ||
![]() |
c206a43374 | ||
![]() |
e0f9a554fc | ||
![]() |
e85006b775 | ||
![]() |
921ac8fba5 | ||
![]() |
30ceb546fa | ||
![]() |
e1110617b2 | ||
![]() |
a891e0260e | ||
![]() |
c1c2e5ca56 | ||
![]() |
f1a46d63cc | ||
![]() |
2e8586d547 | ||
![]() |
ac1dddeaed | ||
![]() |
6a30a3efc6 | ||
![]() |
84247b0037 | ||
![]() |
9bb3afb358 | ||
![]() |
2baddde5ba | ||
![]() |
b5def1af8e | ||
![]() |
0abc6ed072 | ||
![]() |
30216a9c7c | ||
![]() |
6af23967a5 | ||
![]() |
74620fbdbf | ||
![]() |
4cec9e73df | ||
![]() |
957b1298d5 | ||
![]() |
901b451bd5 | ||
![]() |
b83519eb82 | ||
![]() |
1372794704 | ||
![]() |
19cfed5bd7 | ||
![]() |
6875869cb2 | ||
![]() |
9285159a7d | ||
![]() |
90144a2f2e | ||
![]() |
cbd6da78fc | ||
![]() |
cf98b67079 | ||
![]() |
c4c112dcaf | ||
![]() |
9722cb01e4 | ||
![]() |
f4f303f9bd | ||
![]() |
de23c61210 | ||
![]() |
cca7bbfe2a | ||
![]() |
5ca9ab45df | ||
![]() |
8c25d81890 | ||
![]() |
f47375e54d | ||
![]() |
1f7323417b | ||
![]() |
e82e6fde67 | ||
![]() |
cd899a83d5 | ||
![]() |
e750de0ecc | ||
![]() |
efaa210d79 | ||
![]() |
e6e5240922 | ||
![]() |
8ea751c4e9 | ||
![]() |
e2529f9eee | ||
![]() |
6aff6e0b33 | ||
![]() |
bb09e9d24b | ||
![]() |
edddb2fbe4 | ||
![]() |
655d7fe57b | ||
![]() |
d64e994982 | ||
![]() |
673305fc4e | ||
![]() |
47d97e7bd5 | ||
![]() |
955707d944 | ||
![]() |
cf2a5fe807 | ||
![]() |
471f88b337 | ||
![]() |
d5b71a009d | ||
![]() |
bccf557d62 | ||
![]() |
a5095cd7b2 | ||
![]() |
bcdc10e193 | ||
![]() |
ebb9a9d82a | ||
![]() |
783eff8779 | ||
![]() |
ec5fc9d9b8 | ||
![]() |
bb1422182b | ||
![]() |
f2b2516426 | ||
![]() |
e26006d40c | ||
![]() |
138d22226e | ||
![]() |
a24da444df | ||
![]() |
c3adcde556 | ||
![]() |
1452d85e0f | ||
![]() |
329c8090ea | ||
![]() |
53c0db449b | ||
![]() |
89f8a76646 | ||
![]() |
39c134f430 | ||
![]() |
17944791bb | ||
![]() |
df68ab22d6 | ||
![]() |
88aae48c41 | ||
![]() |
6bcd4cad2f | ||
![]() |
7f88e11fd0 | ||
![]() |
60e90d6fae | ||
![]() |
5cefec4cca | ||
![]() |
1f9c1464ab | ||
![]() |
71f01070d8 | ||
![]() |
19d1e6eb88 | ||
![]() |
07dc49259a | ||
![]() |
d8775ccb93 | ||
![]() |
c3ddbb521d | ||
![]() |
1456785779 | ||
![]() |
02eccbcd55 | ||
![]() |
131ee8187d | ||
![]() |
ed615d2318 | ||
![]() |
2cc009619e | ||
![]() |
aaf0cc2c61 | ||
![]() |
a6db04e724 | ||
![]() |
0be1de9750 | ||
![]() |
fcbc3b6d6b | ||
![]() |
c2b419c286 | ||
![]() |
ed094dece5 | ||
![]() |
51966603da | ||
![]() |
6afe18224a | ||
![]() |
953fa50f4f | ||
![]() |
4396e4f834 | ||
![]() |
26754b0821 | ||
![]() |
af8668ff97 | ||
![]() |
2d08bb0b35 | ||
![]() |
c2f81c1f23 | ||
![]() |
63fa92db39 | ||
![]() |
d2c0f1b5c9 | ||
![]() |
775005d865 | ||
![]() |
8c80018c3e | ||
![]() |
076d12f7fb | ||
![]() |
c0f1dfa8bb | ||
![]() |
67f7942cfd | ||
![]() |
86c198d7dc | ||
![]() |
1d4abfa41d | ||
![]() |
f52ed1b363 | ||
![]() |
97146337cb | ||
![]() |
1046e30108 | ||
![]() |
97fd3f2eab | ||
![]() |
60d2a5129d | ||
![]() |
6b4133b5f0 | ||
![]() |
0ed11aa9a4 | ||
![]() |
2e1940bb0f | ||
![]() |
6c6dfaa7d3 | ||
![]() |
468b40eee5 | ||
![]() |
07a6c4659e | ||
![]() |
ad4d66d3f7 | ||
![]() |
add12477e9 | ||
![]() |
74d65bfcbd | ||
![]() |
deed034f31 | ||
![]() |
2563020e29 | ||
![]() |
30276c80bc | ||
![]() |
82c8d1024a | ||
![]() |
476378c156 | ||
![]() |
4c15036368 | ||
![]() |
cb9bf1c913 | ||
![]() |
37a37a6d16 | ||
![]() |
de22f92298 | ||
![]() |
72d3c9e2f6 | ||
![]() |
b9272dcee8 | ||
![]() |
61022875b3 | ||
![]() |
41c71f1b45 | ||
![]() |
8c5ffaeed3 | ||
![]() |
920ef83b63 | ||
![]() |
48463b9a50 | ||
![]() |
2da704e872 | ||
![]() |
d6f808b278 | ||
![]() |
873580cfd5 | ||
![]() |
ae32476755 | ||
![]() |
277aeacb81 | ||
![]() |
08f0d96d68 | ||
![]() |
da5f90473b | ||
![]() |
0ea5d2bd98 | ||
![]() |
c7026a4048 | ||
![]() |
11e9db79b5 | ||
![]() |
90d2673610 | ||
![]() |
09728d1c82 | ||
![]() |
b98fce84e0 | ||
![]() |
6c6b9ab7de | ||
![]() |
27b6cdf252 | ||
![]() |
f5b82b6b7d | ||
![]() |
5744fd1bbb | ||
![]() |
95f4fe0688 | ||
![]() |
3392bf394b | ||
![]() |
0965139ead | ||
![]() |
be0812c70b | ||
![]() |
dfc7b404a5 | ||
![]() |
deeddaabb4 | ||
![]() |
bfe6978ef4 | ||
![]() |
67b4504964 | ||
![]() |
bca16c68c4 | ||
![]() |
ab0b28d08f | ||
![]() |
a73335b8d0 | ||
![]() |
58c6233325 | ||
![]() |
f85c98c4e0 | ||
![]() |
7009515ec9 | ||
![]() |
8c499c2268 | ||
![]() |
9a9f4368b4 | ||
![]() |
3d56af9d3c | ||
![]() |
3074de1f86 | ||
![]() |
33ddbd39d3 | ||
![]() |
983d4834bb | ||
![]() |
a8d0a23583 | ||
![]() |
ccac09b842 | ||
![]() |
0548a6d0a3 | ||
![]() |
d0d9107c91 | ||
![]() |
d660a92d73 | ||
![]() |
8211f4c000 | ||
![]() |
86329f0719 | ||
![]() |
031bbb3a1a | ||
![]() |
80e0478c91 | ||
![]() |
860d38fc47 | ||
![]() |
1901914b56 | ||
![]() |
7e1f29af35 | ||
![]() |
d3d95d0296 | ||
![]() |
22f495491a | ||
![]() |
235485652b | ||
![]() |
9dce807fb7 | ||
![]() |
d6744a76d2 | ||
![]() |
829ae64abe | ||
![]() |
a98c728f33 | ||
![]() |
6b6552bf9c | ||
![]() |
cff392127f | ||
![]() |
0d30a1599d | ||
![]() |
0f5ff56d1e | ||
![]() |
b8f9bb38fd | ||
![]() |
2f31ac4ea4 | ||
![]() |
00d123836f | ||
![]() |
d225c664d7 | ||
![]() |
b462e8a724 | ||
![]() |
e2266a2791 | ||
![]() |
12d155f6ea | ||
![]() |
1c1643003f | ||
![]() |
18eec1abfa | ||
![]() |
fa4b566d9a | ||
![]() |
560008e8fd | ||
![]() |
cf52966d00 | ||
![]() |
edb5a1da65 | ||
![]() |
3fdc0c4345 | ||
![]() |
3a0a0e8b57 | ||
![]() |
f49d896613 | ||
![]() |
73ff8fe114 | ||
![]() |
8b84b891cd | ||
![]() |
7170b7fcb2 | ||
![]() |
add8afa699 | ||
![]() |
995c17c160 | ||
![]() |
10e0f12b16 | ||
![]() |
d8b60f1116 | ||
![]() |
780db6f6ab | ||
![]() |
b032c0664d | ||
![]() |
56da9a526c | ||
![]() |
c3367740d5 | ||
![]() |
156697545a | ||
![]() |
aec1941ae1 | ||
![]() |
7aae0e3353 | ||
![]() |
188be2636f | ||
![]() |
a62c615114 | ||
![]() |
0cb24e58d2 | ||
![]() |
07b67878dc | ||
![]() |
5607fed986 | ||
![]() |
878027066d | ||
![]() |
5028a91201 | ||
![]() |
7f4b5849a7 | ||
![]() |
3fd4021f45 | ||
![]() |
b9d9cde471 | ||
![]() |
8094f7c3ab | ||
![]() |
3fed3fdc8a |
42 changed files with 7111 additions and 1830 deletions
44
Makefile
44
Makefile
|
@ -1,18 +1,52 @@
|
||||||
|
#
|
||||||
|
# Peter Yang <turmary@126.com>
|
||||||
|
# Copyright (c) 2019 Seeed Studio
|
||||||
|
#
|
||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
|
||||||
|
uname_r=$(shell uname -r)
|
||||||
|
|
||||||
|
# If KERNELRELEASE is defined, we've been invoked from the
|
||||||
|
# kernel build system and can use its language
|
||||||
|
ifneq ($(KERNELRELEASE),)
|
||||||
|
# $(warning KERNELVERSION=$(KERNELVERSION))
|
||||||
|
|
||||||
snd-soc-wm8960-objs := wm8960.o
|
snd-soc-wm8960-objs := wm8960.o
|
||||||
snd-soc-ac108-objs := ac108.o
|
snd-soc-ac108-objs := ac108.o ac101.o
|
||||||
|
snd-soc-seeed-voicecard-objs := seeed-voicecard.o
|
||||||
|
|
||||||
|
|
||||||
obj-m += snd-soc-wm8960.o
|
obj-m += snd-soc-wm8960.o
|
||||||
obj-m += snd-soc-ac108.o
|
obj-m += snd-soc-ac108.o
|
||||||
|
obj-m += snd-soc-seeed-voicecard.o
|
||||||
|
|
||||||
|
ifdef DEBUG
|
||||||
|
ifneq ($(DEBUG),0)
|
||||||
|
ccflags-y += -DDEBUG -DAC101_DEBG
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
DEST := /lib/modules/$(uname_r)/kernel
|
||||||
|
|
||||||
all:
|
all:
|
||||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
make -C /lib/modules/$(uname_r)/build M=$(PWD) modules
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
make -C /lib/modules/$(uname_r)/build M=$(PWD) clean
|
||||||
|
|
||||||
install:
|
install:
|
||||||
sudo cp snd-soc-ac108.ko /lib/modules/$(shell uname -r)/kernel/sound/soc/codecs/
|
sudo cp snd-soc-ac108.ko ${DEST}/sound/soc/codecs/
|
||||||
sudo cp snd-soc-wm8960.ko /lib/modules/$(shell uname -r)/kernel/sound/soc/codecs/
|
sudo cp snd-soc-wm8960.ko ${DEST}/sound/soc/codecs/
|
||||||
|
sudo cp snd-soc-seeed-voicecard.ko ${DEST}/sound/soc/bcm/
|
||||||
sudo depmod -a
|
sudo depmod -a
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: all clean install
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
167
README.md
167
README.md
|
@ -1,149 +1,64 @@
|
||||||
# seeed-voicecard
|
# seeed-voicecard
|
||||||
|
|
||||||
[](https://gitter.im/seeed-voicecard/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
The drivers for [ReSpeaker Mic Hat](https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html), [ReSpeaker 4 Mic Array](https://www.seeedstudio.com/ReSpeaker-4-Mic-Array-for-Raspberry-Pi-p-2941.html), [6-Mics Circular Array Kit](), and [4-Mics Linear Array Kit]() for Raspberry Pi.
|
||||||
|
|
||||||
The drivers of [ReSpeaker Mic Hat](https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html) and [ReSpeaker 4 Mic Array](https://www.seeedstudio.com/ReSpeaker-4-Mic-Array-for-Raspberry-Pi-p-2941.html) for Raspberry Pi.
|
### Install seeed-voicecard
|
||||||
|
Get the seeed voice card source code and install all linux kernel drivers
|
||||||
## ReSpeaker Mic Hat
|
|
||||||
|
|
||||||
[](https://www.seeedstudio.com/ReSpeaker-2-Mics-Pi-HAT-p-2874.html)
|
|
||||||
|
|
||||||
|
|
||||||
While the upstream wm8960 codec is not currently supported by current Pi kernel builds, upstream wm8960 has some bugs, we had fixed it. we must it build manually.
|
|
||||||
|
|
||||||
Get the seeed voice card source code.
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/respeaker/seeed-voicecard
|
git clone https://github.com/HinTak/seeed-voicecard
|
||||||
cd seeed-voicecard
|
cd seeed-voicecard
|
||||||
#for ReSpeaker 2-mic
|
sudo ./install.sh
|
||||||
sudo ./install.sh 2mic
|
|
||||||
sudo reboot
|
sudo reboot
|
||||||
```
|
```
|
||||||
|
## ReSpeaker Documentation
|
||||||
|
|
||||||
Check that the sound card name matches the source code seeed-voicecard.
|
Up to date documentation for reSpeaker products can be found in [Seeed Studio Wiki](https://wiki.seeedstudio.com/ReSpeaker/)!
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### Coherence
|
||||||
|
|
||||||
|
Estimate the magnitude squared coherence using Welch’s method.
|
||||||
|

|
||||||
|
Note: 'CO 1-2' means the coherence between channel 1 and channel 2.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#for ReSpeaker 2-mic
|
# How to get the coherence of the captured audio(a.wav for example).
|
||||||
pi@raspberrypi:~/seeed-voicecard $ aplay -l
|
sudo apt install python-numpy python-scipy python-matplotlib
|
||||||
**** List of PLAYBACK Hardware Devices ****
|
python tools/coherence.py a.wav
|
||||||
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
|
|
||||||
Subdevices: 8/8
|
# Requirement of the input audio file:
|
||||||
Subdevice #0: subdevice #0
|
- format: WAV(Microsoft) signed 16-bit PCM
|
||||||
Subdevice #1: subdevice #1
|
- channels: >=2
|
||||||
Subdevice #2: subdevice #2
|
|
||||||
Subdevice #3: subdevice #3
|
|
||||||
Subdevice #4: subdevice #4
|
|
||||||
Subdevice #5: subdevice #5
|
|
||||||
Subdevice #6: subdevice #6
|
|
||||||
Subdevice #7: subdevice #7
|
|
||||||
card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
|
|
||||||
Subdevices: 1/1
|
|
||||||
Subdevice #0: subdevice #0
|
|
||||||
card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 []
|
|
||||||
Subdevices: 1/1
|
|
||||||
Subdevice #0: subdevice #0
|
|
||||||
pi@raspberrypi:~/seeed-voicecard $ arecord -l
|
|
||||||
**** List of CAPTURE Hardware Devices ****
|
|
||||||
card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: bcm2835-i2s-wm8960-hifi wm8960-hifi-0 []
|
|
||||||
Subdevices: 1/1
|
|
||||||
Subdevice #0: subdevice #0
|
|
||||||
pi@raspberrypi:~/seeed-voicecard $
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Next step
|
|
||||||
Go to https://github.com/respeaker/mic_hat to build voice enabled projects with Google Assistant SDK or Alexa Voice Service.
|
|
||||||
|
|
||||||
## ReSpeaker 4 Mic Array
|
|
||||||
|
|
||||||
[](https://www.seeedstudio.com/ReSpeaker-4-Mic-Array-for-Raspberry-Pi-p-2941.html)
|
|
||||||
|
|
||||||
The 4 Mic Array uses ac108 which includes 4 ADCs, we also write ac108 rapberry pi linux kernel driver.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/respeaker/seeed-voicecard
|
|
||||||
cd seeed-voicecard
|
|
||||||
sudo ./install.sh 4mic
|
|
||||||
|
|
||||||
#reboot your Raspbian OS
|
|
||||||
sudo reboot
|
|
||||||
```
|
|
||||||
|
|
||||||
Check that the sound card name matches the source code seeed-voicecard.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#for ReSpeaker 4-mic
|
|
||||||
pi@raspberrypi:~ $ arecord -L
|
|
||||||
null
|
|
||||||
Discard all samples (playback) or generate zero samples (capture)
|
|
||||||
playback
|
|
||||||
capture
|
|
||||||
dmixed
|
|
||||||
array
|
|
||||||
ac108
|
|
||||||
default:CARD=seeed4micvoicec
|
|
||||||
seeed-4mic-voicecard,
|
|
||||||
Default Audio Device
|
|
||||||
sysdefault:CARD=seeed4micvoicec
|
|
||||||
seeed-4mic-voicecard,
|
|
||||||
Default Audio Device
|
|
||||||
dmix:CARD=seeed4micvoicec,DEV=0
|
|
||||||
seeed-4mic-voicecard,
|
|
||||||
Direct sample mixing device
|
|
||||||
dsnoop:CARD=seeed4micvoicec,DEV=0
|
|
||||||
seeed-4mic-voicecard,
|
|
||||||
Direct sample snooping device
|
|
||||||
hw:CARD=seeed4micvoicec,DEV=0
|
|
||||||
seeed-4mic-voicecard,
|
|
||||||
Direct hardware device without any conversions
|
|
||||||
plughw:CARD=seeed4micvoicec,DEV=0
|
|
||||||
seeed-4mic-voicecard,
|
|
||||||
Hardware device with all software conversions
|
|
||||||
pi@raspberrypi:~ $
|
|
||||||
```
|
|
||||||
If you want to change the alsa settings, You can use `sudo alsactl --file=asound.state store` to save it.
|
|
||||||
|
|
||||||
Test:
|
|
||||||
```bash
|
|
||||||
#for ReSpeaker 2-mic
|
|
||||||
#It will capture sound an playback on hw:1
|
|
||||||
arecord -f cd -Dhw:1 | aplay -Dhw:1
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#for ReSpeaker 4-mic
|
|
||||||
#It will capture sound on AC108 and save as a.wav
|
|
||||||
arecord -Dac108 -f S32_LE -r 16000 -c 4 a.wav
|
|
||||||
```
|
|
||||||
### uninstall seeed-voicecard
|
### uninstall seeed-voicecard
|
||||||
If you want to upgrade the driver , you need uninstall the driver first.
|
If you want to upgrade the driver , you need uninstall the driver first.
|
||||||
|
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~/seeed-voicecard $ sudo ./uninstall.sh 4mic
|
pi@raspberrypi:~/seeed-voicecard $ sudo ./uninstall.sh
|
||||||
delete dtoverlay=seeed-4mic-voicecard in /boot/config.txt
|
...
|
||||||
delete snd-soc-ac108 in /etc/modules
|
|
||||||
------------------------------------------------------
|
|
||||||
Please reboot your raspberry pi to apply all settings
|
|
||||||
Thank you!
|
|
||||||
------------------------------------------------------
|
|
||||||
pi@raspberrypi:~/seeed-voicecard $ sudo ./uninstall.sh 2mic
|
|
||||||
delete dtoverlay=seeed-2mic-voicecard in /boot/config.txt
|
|
||||||
remove seeed-2mic-voicecard.dtbo in /boot/overlays
|
|
||||||
remove snd-soc-wm8960.ko
|
|
||||||
delete snd-soc-wm8960 in /etc/modules
|
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
Please reboot your raspberry pi to apply all settings
|
Please reboot your raspberry pi to apply all settings
|
||||||
Thank you!
|
Thank you!
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
```
|
```
|
||||||
|
|
||||||
### with Google Assistant
|
|
||||||
if you run the assistant but the playback is speed up considerably, try to configure alsa:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo cp asound.conf /etc/asound.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
If the alsa configuration doesn't solve the issue, try to use pulseaudio. See [#4](https://github.com/respeaker/seeed-voicecard/issues/4)
|
|
||||||
|
|
||||||
|
|
||||||
Enjoy !
|
Enjoy !
|
||||||
|
|
||||||
|
### Technical support
|
||||||
|
|
||||||
|
For hardware testing purposes we made a Rasperry Pi OS 5.10.17-v7l+ 32-bit image with reSpeaker drivers pre-installed, which you can download by clicking on [this link](https://files.seeedstudio.com/linux/Raspberry%20Pi%204%20reSpeaker/2021-05-07-raspios-buster-armhf-lite-respeaker.img.xz).
|
||||||
|
|
||||||
|
We provide official support for using reSpeaker with the following OS:
|
||||||
|
- 32-bit Raspberry Pi OS
|
||||||
|
- 64-bit Raspberry Pi OS
|
||||||
|
|
||||||
|
And following hardware platforms:
|
||||||
|
- Raspberry Pi 3 (all models), Raspberry Pi 4 (all models)
|
||||||
|
|
||||||
|
Anything beyond the scope of official support is considered to be community supported. Support for other OS/hardware platforms can be added, provided MOQ requirements can be met.
|
||||||
|
|
||||||
|
If you have a technical problem when using reSpeaker with one of the officially supported platforms/OS, feel free to create an issue on Github. For general questions or suggestions, please use [Seeed forum](https://forum.seeedstudio.com/c/products/respeaker/15).
|
||||||
|
|
||||||
|
|
||||||
|
|
432
ac101_regs.h
Normal file
432
ac101_regs.h
Normal file
|
@ -0,0 +1,432 @@
|
||||||
|
/*
|
||||||
|
* ac101_regs.h
|
||||||
|
*
|
||||||
|
* (C) Copyright 2017-2018
|
||||||
|
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
|
||||||
|
*
|
||||||
|
* PeterYang <linsheng.yang@seeed.cc>
|
||||||
|
*
|
||||||
|
* (C) Copyright 2010-2017
|
||||||
|
* Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
|
||||||
|
* huangxin <huangxin@reuuimllatech.com>
|
||||||
|
*
|
||||||
|
* some simple description for this code
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __AC101_REGS_H__
|
||||||
|
#define __AC101_REGS_H__
|
||||||
|
|
||||||
|
/*pll source*/
|
||||||
|
#define AC101_MCLK1 1
|
||||||
|
#define AC101_MCLK2 2
|
||||||
|
#define AC101_BCLK1 3
|
||||||
|
#define AC101_BCLK2 4
|
||||||
|
|
||||||
|
#define AIF1_CLK 1
|
||||||
|
#define AIF2_CLK 2
|
||||||
|
|
||||||
|
#define CHIP_AUDIO_RST 0x0
|
||||||
|
#define PLL_CTRL1 0x1
|
||||||
|
#define PLL_CTRL2 0x2
|
||||||
|
#define SYSCLK_CTRL 0x3
|
||||||
|
#define MOD_CLK_ENA 0x4
|
||||||
|
#define MOD_RST_CTRL 0x5
|
||||||
|
#define AIF_SR_CTRL 0x6
|
||||||
|
|
||||||
|
#define AIF1_CLK_CTRL 0x10
|
||||||
|
#define AIF1_ADCDAT_CTRL 0x11
|
||||||
|
#define AIF1_DACDAT_CTRL 0x12
|
||||||
|
#define AIF1_MXR_SRC 0x13
|
||||||
|
#define AIF1_VOL_CTRL1 0x14
|
||||||
|
#define AIF1_VOL_CTRL2 0x15
|
||||||
|
#define AIF1_VOL_CTRL3 0x16
|
||||||
|
#define AIF1_VOL_CTRL4 0x17
|
||||||
|
#define AIF1_MXR_GAIN 0x18
|
||||||
|
#define AIF1_RXD_CTRL 0x19
|
||||||
|
#define ADC_DIG_CTRL 0x40
|
||||||
|
#define ADC_VOL_CTRL 0x41
|
||||||
|
#define ADC_DBG_CTRL 0x42
|
||||||
|
|
||||||
|
#define HMIC_CTRL1 0x44
|
||||||
|
#define HMIC_CTRL2 0x45
|
||||||
|
#define HMIC_STS 0x46
|
||||||
|
|
||||||
|
#define DAC_DIG_CTRL 0x48
|
||||||
|
#define DAC_VOL_CTRL 0x49
|
||||||
|
#define DAC_DBG_CTRL 0x4a
|
||||||
|
#define DAC_MXR_SRC 0x4c
|
||||||
|
#define DAC_MXR_GAIN 0x4d
|
||||||
|
|
||||||
|
#define ADC_APC_CTRL 0x50
|
||||||
|
#define ADC_SRC 0x51
|
||||||
|
#define ADC_SRCBST_CTRL 0x52
|
||||||
|
#define OMIXER_DACA_CTRL 0x53
|
||||||
|
#define OMIXER_SR 0x54
|
||||||
|
#define OMIXER_BST1_CTRL 0x55
|
||||||
|
#define HPOUT_CTRL 0x56
|
||||||
|
#define ESPKOUT_CTRL 0x57
|
||||||
|
#define SPKOUT_CTRL 0x58
|
||||||
|
#define LOUT_CTRL 0x59
|
||||||
|
#define ADDA_TUNE1 0x5a
|
||||||
|
#define ADDA_TUNE2 0x5b
|
||||||
|
#define ADDA_TUNE3 0x5c
|
||||||
|
#define HPOUT_STR 0x5d
|
||||||
|
|
||||||
|
/*CHIP_AUDIO_RST*/
|
||||||
|
#define AC101_CHIP_ID 0x0101
|
||||||
|
|
||||||
|
/*PLL_CTRL1*/
|
||||||
|
#define DPLL_DAC_BIAS 14
|
||||||
|
#define PLL_POSTDIV_M 8
|
||||||
|
#define CLOSE_LOOP 6
|
||||||
|
#define INT 0
|
||||||
|
|
||||||
|
/*PLL_CTRL2*/
|
||||||
|
#define PLL_EN 15
|
||||||
|
#define PLL_LOCK_STATUS 14
|
||||||
|
#define PLL_PREDIV_NI 4
|
||||||
|
#define PLL_POSTDIV_NF 0
|
||||||
|
|
||||||
|
/*SYSCLK_CTRL*/
|
||||||
|
#define PLLCLK_ENA 15
|
||||||
|
#define PLLCLK_SRC 12
|
||||||
|
#define AIF1CLK_ENA 11
|
||||||
|
#define AIF1CLK_SRC 8
|
||||||
|
#define AIF2CLK_ENA 7
|
||||||
|
#define AIF2CLK_SRC 4
|
||||||
|
#define SYSCLK_ENA 3
|
||||||
|
#define SYSCLK_SRC 0
|
||||||
|
|
||||||
|
/*MOD_CLK_ENA*/
|
||||||
|
#define MOD_CLK_AIF1 15
|
||||||
|
#define MOD_CLK_AIF2 14
|
||||||
|
#define MOD_CLK_AIF3 13
|
||||||
|
#define MOD_CLK_SRC1 11
|
||||||
|
#define MOD_CLK_SRC2 10
|
||||||
|
#define MOD_CLK_HPF_AGC 7
|
||||||
|
#define MOD_CLK_HPF_DRC 6
|
||||||
|
#define MOD_CLK_ADC_DIG 3
|
||||||
|
#define MOD_CLK_DAC_DIG 2
|
||||||
|
|
||||||
|
/*MOD_RST_CTRL*/
|
||||||
|
#define MOD_RESET_CTL 0
|
||||||
|
#define MOD_RESET_AIF1 15
|
||||||
|
#define MOD_RESET_AIF2 14
|
||||||
|
#define MOD_RESET_AIF3 13
|
||||||
|
#define MOD_RESET_SRC1 11
|
||||||
|
#define MOD_RESET_SRC2 10
|
||||||
|
#define MOD_RESET_HPF_AGC 7
|
||||||
|
#define MOD_RESET_HPF_DRC 6
|
||||||
|
#define MOD_RESET_ADC_DIG 3
|
||||||
|
#define MOD_RESET_DAC_DIG 2
|
||||||
|
|
||||||
|
/*AIF_SR_CTRL*/
|
||||||
|
#define AIF1_FS 12 //AIF1 Sample Rate
|
||||||
|
#define AIF2_FS 8 //AIF2 Sample Rate
|
||||||
|
#define SRC1_ENA 3
|
||||||
|
#define SRC1_SRC 2
|
||||||
|
#define SRC2_ENA 1
|
||||||
|
#define SRC2_SRC 0
|
||||||
|
|
||||||
|
/*AIF1LCK_CTRL*/
|
||||||
|
#define AIF1_MSTR_MOD 15
|
||||||
|
#define AIF1_BCLK_INV 14
|
||||||
|
#define AIF1_LRCK_INV 13
|
||||||
|
#define AIF1_BCLK_DIV 9
|
||||||
|
#define AIF1_LRCK_DIV 6
|
||||||
|
#define AIF1_WORK_SIZ 4
|
||||||
|
#define AIF1_DATA_FMT 2
|
||||||
|
#define DSP_MONO_PCM 1
|
||||||
|
#define AIF1_TDMM_ENA 0
|
||||||
|
|
||||||
|
/*AIF1_ADCDAT_CTRL*/
|
||||||
|
#define AIF1_AD0L_ENA 15
|
||||||
|
#define AIF1_AD0R_ENA 14
|
||||||
|
#define AIF1_AD1L_ENA 13
|
||||||
|
#define AIF1_AD1R_ENA 12
|
||||||
|
#define AIF1_AD0L_SRC 10
|
||||||
|
#define AIF1_AD0R_SRC 8
|
||||||
|
#define AIF1_AD1L_SRC 6
|
||||||
|
#define AIF1_AD1R_SRC 4
|
||||||
|
#define AIF1_ADCP_ENA 3
|
||||||
|
#define AIF1_ADUL_ENA 2
|
||||||
|
#define AIF1_SLOT_SIZ 0
|
||||||
|
|
||||||
|
/*AIF1_DACDAT_CTRL*/
|
||||||
|
#define AIF1_DA0L_ENA 15
|
||||||
|
#define AIF1_DA0R_ENA 14
|
||||||
|
#define AIF1_DA1L_ENA 13
|
||||||
|
#define AIF1_DA1R_ENA 12
|
||||||
|
#define AIF1_DA0L_SRC 10
|
||||||
|
#define AIF1_DA0R_SRC 8
|
||||||
|
#define AIF1_DA1L_SRC 6
|
||||||
|
#define AIF1_DA1R_SRC 4
|
||||||
|
#define AIF1_DACP_ENA 3
|
||||||
|
#define AIF1_DAUL_ENA 2
|
||||||
|
#define AIF1_SLOT_SIZ 0
|
||||||
|
|
||||||
|
/*AIF1_MXR_SRC*/
|
||||||
|
#define AIF1_AD0L_AIF1_DA0L_MXR 15
|
||||||
|
#define AIF1_AD0L_AIF2_DACL_MXR 14
|
||||||
|
#define AIF1_AD0L_ADCL_MXR 13
|
||||||
|
#define AIF1_AD0L_AIF2_DACR_MXR 12
|
||||||
|
#define AIF1_AD0R_AIF1_DA0R_MXR 11
|
||||||
|
#define AIF1_AD0R_AIF2_DACR_MXR 10
|
||||||
|
#define AIF1_AD0R_ADCR_MXR 9
|
||||||
|
#define AIF1_AD0R_AIF2_DACL_MXR 8
|
||||||
|
#define AIF1_AD1L_AIF2_DACL_MXR 7
|
||||||
|
#define AIF1_AD1L_ADCL_MXR 6
|
||||||
|
#define AIF1_AD1L_MXR_SRC 6
|
||||||
|
#define AIF1_AD1R_AIF2_DACR_MXR 3
|
||||||
|
#define AIF1_AD1R_ADCR_MXR 2
|
||||||
|
#define AIF1_AD1R_MXR_SRC 2
|
||||||
|
|
||||||
|
/*AIF1_VOL_CTRL1*/
|
||||||
|
#define AIF1_AD0L_VOL 8
|
||||||
|
#define AIF1_AD0R_VOL 0
|
||||||
|
|
||||||
|
/*AIF1_VOL_CTRL2*/
|
||||||
|
#define AIF1_AD1L_VOL 8
|
||||||
|
#define AIF1_AD1R_VOL 0
|
||||||
|
|
||||||
|
/*AIF1_VOL_CTRL3*/
|
||||||
|
#define AIF1_DA0L_VOL 8
|
||||||
|
#define AIF1_DA0R_VOL 0
|
||||||
|
|
||||||
|
/*AIF1_VOL_CTRL4*/
|
||||||
|
#define AIF1_DA1L_VOL 8
|
||||||
|
#define AIF1_DA1R_VOL 0
|
||||||
|
|
||||||
|
/*AIF1_MXR_GAIN*/
|
||||||
|
#define AIF1_AD0L_MXR_GAIN 12
|
||||||
|
#define AIF1_AD0R_MXR_GAIN 8
|
||||||
|
#define AIF1_AD1L_MXR_GAIN 6
|
||||||
|
#define AIF1_AD1R_MXR_GAIN 2
|
||||||
|
|
||||||
|
/*AIF1_RXD_CTRL*/
|
||||||
|
#define AIF1_N_DATA_DISCARD 8
|
||||||
|
|
||||||
|
/*ADC_DIG_CTRL*/
|
||||||
|
#define ENAD 15
|
||||||
|
#define ENDM 14
|
||||||
|
#define ADFIR32 13
|
||||||
|
#define ADOUT_DTS 2
|
||||||
|
#define ADOUT_DLY 1
|
||||||
|
|
||||||
|
/*ADC_VOL_CTRL*/
|
||||||
|
#define ADC_VOL_L 8
|
||||||
|
#define ADC_VOL_R 0
|
||||||
|
|
||||||
|
/*ADC_DBG_CTRL*/
|
||||||
|
#define ADSW 15
|
||||||
|
#define DMIC_CLK_PIN_CTRL 12
|
||||||
|
|
||||||
|
/*HMIC_CTRL1*/
|
||||||
|
#define HMIC_M 12
|
||||||
|
#define HMIC_N 8
|
||||||
|
#define HMIC_DATA_IRQ_MODE 7
|
||||||
|
#define HMIC_TH1_HYSTERESIS 5
|
||||||
|
#define HMIC_PULLOUT_IRQ 4
|
||||||
|
#define HMIC_PLUGIN_IRQ 3
|
||||||
|
#define HMIC_KEYUP_IRQ 2
|
||||||
|
#define HMIC_KEYDOWN_IRQ 1
|
||||||
|
#define HMIC_DATA_IRQ_EN 0
|
||||||
|
|
||||||
|
/*HMIC_CTRL2*/
|
||||||
|
#define HMIC_SAMPLE_SELECT 14
|
||||||
|
#define HMIC_TH2_HYSTERESIS 13
|
||||||
|
#define HMIC_TH2 8
|
||||||
|
#define HMIC_SF 6
|
||||||
|
#define KEYUP_CLEAR 5
|
||||||
|
#define HMIC_TH1 0
|
||||||
|
|
||||||
|
/*HMIC_STS*/
|
||||||
|
#define HMIC_DATA 8
|
||||||
|
#define GET_HMIC_DATA(r) (((r) >> HMIC_DATA) & 0x1F)
|
||||||
|
#define HMIC_PULLOUT_PEND 4
|
||||||
|
#define HMIC_PLUGIN_PEND 3
|
||||||
|
#define HMIC_KEYUP_PEND 2
|
||||||
|
#define HMKC_KEYDOWN_PEND 1
|
||||||
|
#define HMIC_DATA_PEND 0
|
||||||
|
#define HMIC_PEND_ALL (0x1F)
|
||||||
|
|
||||||
|
/*DAC_DIG_CTRL*/
|
||||||
|
#define ENDA 15
|
||||||
|
#define ENHPF 14
|
||||||
|
#define DAFIR32 13
|
||||||
|
#define MODQU 8
|
||||||
|
|
||||||
|
/*DAC_VOL_CTRL*/
|
||||||
|
#define DAC_VOL_L 8
|
||||||
|
#define DAC_VOL_R 0
|
||||||
|
|
||||||
|
/*DAC_DBG_CTRL*/
|
||||||
|
#define DASW 15
|
||||||
|
#define ENDWA_N 14
|
||||||
|
#define DAC_MOD_DBG 13
|
||||||
|
#define DAC_PTN_SEL 6
|
||||||
|
#define DVC 0
|
||||||
|
|
||||||
|
/*DAC_MXR_SRC*/
|
||||||
|
#define DACL_MXR_AIF1_DA0L 15
|
||||||
|
#define DACL_MXR_AIF1_DA1L 14
|
||||||
|
#define DACL_MXR_AIF2_DACL 13
|
||||||
|
#define DACL_MXR_ADCL 12
|
||||||
|
#define DACL_MXR_SRC 12
|
||||||
|
#define DACR_MXR_AIF1_DA0R 11
|
||||||
|
#define DACR_MXR_AIF1_DA1R 10
|
||||||
|
#define DACR_MXR_AIF2_DACR 9
|
||||||
|
#define DACR_MXR_ADCR 8
|
||||||
|
#define DACR_MXR_SRC 8
|
||||||
|
|
||||||
|
/*DAC_MXR_GAIN*/
|
||||||
|
#define DACL_MXR_GAIN 12
|
||||||
|
#define DACR_MXR_GAIN 8
|
||||||
|
|
||||||
|
/*ADC_APC_CTRL*/
|
||||||
|
#define ADCREN 15
|
||||||
|
#define ADCRG 12
|
||||||
|
#define ADCLEN 11
|
||||||
|
#define ADCLG 8
|
||||||
|
#define MBIASEN 7
|
||||||
|
#define MMIC_BIAS_CHOP_EN 6
|
||||||
|
#define MMIC_BIAS_CHOP_CKS 4
|
||||||
|
#define HBIASMOD 2
|
||||||
|
#define HBIASEN 1
|
||||||
|
#define HBIASADCEN 0
|
||||||
|
|
||||||
|
/*ADC_SRC*/
|
||||||
|
#define RADCMIXMUTEMIC1BOOST (13)
|
||||||
|
#define RADCMIXMUTEMIC2BOOST (12)
|
||||||
|
#define RADCMIXMUTELINEINLR (11)
|
||||||
|
#define RADCMIXMUTELINEINR (10)
|
||||||
|
#define RADCMIXMUTEAUXINR (9)
|
||||||
|
#define RADCMIXMUTEROUTPUT (8)
|
||||||
|
#define RADCMIXMUTELOUTPUT (7)
|
||||||
|
#define LADCMIXMUTEMIC1BOOST (6)
|
||||||
|
#define LADCMIXMUTEMIC2BOOST (5)
|
||||||
|
#define LADCMIXMUTELINEINLR (4)
|
||||||
|
#define LADCMIXMUTELINEINL (3)
|
||||||
|
#define LADCMIXMUTEAUXINL (2)
|
||||||
|
#define LADCMIXMUTELOUTPUT (1)
|
||||||
|
#define LADCMIXMUTEROUTPUT (0)
|
||||||
|
|
||||||
|
|
||||||
|
/*ADC_SRCBST_CTRL*/
|
||||||
|
#define MIC1AMPEN 15
|
||||||
|
#define ADC_MIC1G 12
|
||||||
|
#define MIC2AMPEN 11
|
||||||
|
#define ADC_MIC2G 8
|
||||||
|
#define MIC2SLT 7
|
||||||
|
#define LINEIN_PREG 4
|
||||||
|
#define AUXI_PREG 0
|
||||||
|
|
||||||
|
/*OMIXER_DACA_CTRL*/
|
||||||
|
#define DACAREN 15
|
||||||
|
#define DACALEN 14
|
||||||
|
#define RMIXEN 13
|
||||||
|
#define LMIXEN 12
|
||||||
|
#define HPOUTPUTENABLE 8
|
||||||
|
|
||||||
|
/*OMIXER_SR*/
|
||||||
|
#define RMIXMUTEMIC1BOOST (13)
|
||||||
|
#define RMIXMUTEMIC2BOOST (12)
|
||||||
|
#define RMIXMUTELINEINLR (11)
|
||||||
|
#define RMIXMUTELINEINR (10)
|
||||||
|
#define RMIXMUTEAUXINR (9)
|
||||||
|
#define RMIXMUTEDACR (8)
|
||||||
|
#define RMIXMUTEDACL (7)
|
||||||
|
#define LMIXMUTEMIC1BOOST (6)
|
||||||
|
#define LMIXMUTEMIC2BOOST (5)
|
||||||
|
#define LMIXMUTELINEINLR (4)
|
||||||
|
#define LMIXMUTELINEINL (3)
|
||||||
|
#define LMIXMUTEAUXINL (2)
|
||||||
|
#define LMIXMUTEDACL (1)
|
||||||
|
#define LMIXMUTEDACR (0)
|
||||||
|
|
||||||
|
/*OMIXER_BST1_CTRL*/
|
||||||
|
#define BIASVOLTAGE 12
|
||||||
|
#define AXG 9
|
||||||
|
#define OMIXER_MIC1G 6
|
||||||
|
#define OMIXER_MIC2G 3
|
||||||
|
#define LINEING 0
|
||||||
|
|
||||||
|
/*HPOUT_CTRL*/
|
||||||
|
#define RHPS 15
|
||||||
|
#define LHPS 14
|
||||||
|
#define RHPPA_MUTE 13
|
||||||
|
#define LHPPA_MUTE 12
|
||||||
|
#define HPPA_EN 11
|
||||||
|
#define HP_VOL 4
|
||||||
|
#define HPPA_DEL 2
|
||||||
|
#define HPPA_IS 0
|
||||||
|
|
||||||
|
/*ESPKOUT_CTRL*/
|
||||||
|
#define EAR_RAMP_TIME 11
|
||||||
|
#define ESPA_OUT_CURRENT 9
|
||||||
|
#define ESPSR 7
|
||||||
|
#define ESPPA_MUTE 6
|
||||||
|
#define ESPPA_EN 5
|
||||||
|
#define ESP_VOL 0
|
||||||
|
|
||||||
|
/*SPKOUT_CTRL*/
|
||||||
|
#define HPCALICKS 13
|
||||||
|
#define RSPKS 12
|
||||||
|
#define RSPKINVEN 11
|
||||||
|
#define RSPK_EN 9
|
||||||
|
#define LSPKS 8
|
||||||
|
#define LSPKINVEN 7
|
||||||
|
#define LSPK_EN 5
|
||||||
|
#define SPK_VOL 0
|
||||||
|
|
||||||
|
/*LOUT_CTRL*/
|
||||||
|
#define LINEOUTG 5
|
||||||
|
#define LINEOUTEN 4
|
||||||
|
#define LINEOUTS0 3
|
||||||
|
#define LINEOUTS1 2
|
||||||
|
#define LINEOUTS2 1
|
||||||
|
#define LINEOUTS3 0
|
||||||
|
|
||||||
|
/*ADDA_TUNE1*/
|
||||||
|
#define CURRENT_TEST_SELECT 14
|
||||||
|
#define BIHE_CTRL 12
|
||||||
|
#define DITHER 11
|
||||||
|
#define DITHER_CLK 9
|
||||||
|
#define ZERO_CROSSOVER_EN 8
|
||||||
|
#define ZERO_CROSSOVER_TIME 7
|
||||||
|
#define EAR_SPEED_SELECT 6
|
||||||
|
#define REF_CHOPPEN_CKS 4
|
||||||
|
#define OPMIC_BIAS_CUR 0
|
||||||
|
|
||||||
|
/*ADDA_TUNE2*/
|
||||||
|
#define OPDAC_BIAS_CUR 14
|
||||||
|
#define OPDRV_BIAS_CUR 12
|
||||||
|
#define OPMIX_BIAS_CUR 10
|
||||||
|
#define OPEAR_BIAS_CUR 8
|
||||||
|
#define OPVR_BIAS_CUR 6
|
||||||
|
#define OPAAF_BIAS_CUR 4
|
||||||
|
#define OPADC1_BIAS_CUR 2
|
||||||
|
#define OPADC2_BIAS_CUR 0
|
||||||
|
|
||||||
|
/*ADDA_TUNE3*/
|
||||||
|
#define LDOEN 15
|
||||||
|
#define LDO_SEL 12
|
||||||
|
#define BIASCALIVERIFY 11
|
||||||
|
#define BIASMODE 10
|
||||||
|
#define BIASCALIDATA 9
|
||||||
|
#define OSCS 1
|
||||||
|
#define OSCEN 0
|
||||||
|
|
||||||
|
/*HPOUT_STR*/
|
||||||
|
#define HPVL_SOFT_MOD 14
|
||||||
|
#define HPVL_STEP_CTRL 8
|
||||||
|
#define DACA_CHND_ENA 7
|
||||||
|
#define HPPA_MXRD_ENA 6
|
||||||
|
#define HPVL_CTRL_OUT 0
|
||||||
|
|
||||||
|
#endif//__AC101_REGS_H__
|
367
ac108_6mic.state
Normal file
367
ac108_6mic.state
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
state.ALSA {
|
||||||
|
control.1 {
|
||||||
|
iface MIXER
|
||||||
|
name 'PCM Playback Volume'
|
||||||
|
value 400
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '-10239 - 400'
|
||||||
|
dbmin -9999999
|
||||||
|
dbmax 400
|
||||||
|
dbvalue.0 400
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.2 {
|
||||||
|
iface MIXER
|
||||||
|
name 'PCM Playback Switch'
|
||||||
|
value true
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type BOOLEAN
|
||||||
|
count 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.3 {
|
||||||
|
iface MIXER
|
||||||
|
name 'PCM Playback Route'
|
||||||
|
value 1
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.4 {
|
||||||
|
iface PCM
|
||||||
|
name 'IEC958 Playback Default'
|
||||||
|
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type IEC958
|
||||||
|
count 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.5 {
|
||||||
|
iface PCM
|
||||||
|
name 'IEC958 Playback Con Mask'
|
||||||
|
value '0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
comment {
|
||||||
|
access read
|
||||||
|
type IEC958
|
||||||
|
count 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.6 {
|
||||||
|
iface PCM
|
||||||
|
name 'IEC958 Playback PCM Stream'
|
||||||
|
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
comment {
|
||||||
|
access 'read write inactive'
|
||||||
|
type IEC958
|
||||||
|
count 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.seeed8micvoicec {
|
||||||
|
control.1 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH1 digital volume'
|
||||||
|
value 208
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 3675
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.2 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH2 digital volume'
|
||||||
|
value 208
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 3675
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.3 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH3 digital volume'
|
||||||
|
value 208
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 3675
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.4 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH4 digital volume'
|
||||||
|
value 208
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 3675
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.5 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC1 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.6 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC2 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.7 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC3 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.8 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC4 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.9 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH5 digital volume'
|
||||||
|
value 208
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 3675
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.10 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH6 digital volume'
|
||||||
|
value 208
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 3675
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.11 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH7 digital volume'
|
||||||
|
value 198
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 2925
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.12 {
|
||||||
|
iface MIXER
|
||||||
|
name 'CH8 digital volume'
|
||||||
|
value 198
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 2925
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.13 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC5 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.14 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC6 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.15 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC7 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.16 {
|
||||||
|
iface MIXER
|
||||||
|
name 'ADC8 PGA gain'
|
||||||
|
value 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin 0
|
||||||
|
dbmax 3100
|
||||||
|
dbvalue.0 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.17 {
|
||||||
|
iface MIXER
|
||||||
|
name 'DAC volume'
|
||||||
|
value.0 0
|
||||||
|
value.1 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 2
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 -11925
|
||||||
|
dbvalue.1 -11925
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.18 {
|
||||||
|
iface MIXER
|
||||||
|
name 'DAC mixer gain'
|
||||||
|
value.0 0
|
||||||
|
value.1 0
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 2
|
||||||
|
range '0 - 15'
|
||||||
|
dbmin -600
|
||||||
|
dbmax 8400
|
||||||
|
dbvalue.0 -600
|
||||||
|
dbvalue.1 -600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.19 {
|
||||||
|
iface MIXER
|
||||||
|
name 'digital volume'
|
||||||
|
value 51
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 63'
|
||||||
|
dbmin -7308
|
||||||
|
dbmax 0
|
||||||
|
dbvalue.0 -1392
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.20 {
|
||||||
|
iface MIXER
|
||||||
|
name 'Speaker Playback Volume'
|
||||||
|
value 25
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 31'
|
||||||
|
dbmin -4800
|
||||||
|
dbmax -150
|
||||||
|
dbvalue.0 -1050
|
||||||
|
}
|
||||||
|
}
|
||||||
|
control.21 {
|
||||||
|
iface MIXER
|
||||||
|
name 'Headphone Playback Volume'
|
||||||
|
value 52
|
||||||
|
comment {
|
||||||
|
access 'read write'
|
||||||
|
type INTEGER
|
||||||
|
count 1
|
||||||
|
range '0 - 63'
|
||||||
|
dbmin -6300
|
||||||
|
dbmax 0
|
||||||
|
dbvalue.0 -1100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,202 +68,106 @@ state.ALSA {
|
||||||
state.seeed4micvoicec {
|
state.seeed4micvoicec {
|
||||||
control.1 {
|
control.1 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'OUT1 Mute'
|
name 'CH1 digital volume'
|
||||||
value false
|
value 222
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type BOOLEAN
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 4725
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.2 {
|
control.2 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'OUT2 Mute'
|
name 'CH2 digital volume'
|
||||||
value true
|
value 222
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type BOOLEAN
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
|
range '0 - 255'
|
||||||
|
dbmin -11925
|
||||||
|
dbmax 7200
|
||||||
|
dbvalue.0 4725
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.3 {
|
control.3 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'TX1 Channel1~8 enable'
|
name 'CH3 digital volume'
|
||||||
value '1-4 channels '
|
value 222
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type ENUMERATED
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
item.0 'disable all'
|
range '0 - 255'
|
||||||
item.1 '1-1 channels '
|
dbmin -11925
|
||||||
item.2 '1-2 channels '
|
dbmax 7200
|
||||||
item.3 '1-3 channels '
|
dbvalue.0 4725
|
||||||
item.4 '1-4 channels '
|
|
||||||
item.5 '1-5 channels '
|
|
||||||
item.6 '1-6 channels '
|
|
||||||
item.7 '1-7 channels '
|
|
||||||
item.8 '1-8 channels '
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.4 {
|
control.4 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'TX1 Channel9~16 enable'
|
name 'CH4 digital volume'
|
||||||
value 'disable all'
|
value 222
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type ENUMERATED
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
item.0 'disable all'
|
range '0 - 255'
|
||||||
item.1 '8-9 channels '
|
dbmin -11925
|
||||||
item.2 '8-10 channels '
|
dbmax 7200
|
||||||
item.3 '8-11 channels '
|
dbvalue.0 4725
|
||||||
item.4 '8-12 channels '
|
|
||||||
item.5 '8-13 channels '
|
|
||||||
item.6 '8-14 channels '
|
|
||||||
item.7 '8-15 channels '
|
|
||||||
item.8 '8-16 channels '
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.5 {
|
control.5 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'TX2 Channel1~8 enable'
|
name 'ADC1 PGA gain'
|
||||||
value 'disable all'
|
value 0
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type ENUMERATED
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
item.0 'disable all'
|
range '0 - 31'
|
||||||
item.1 '1-1 channels '
|
dbmin 0
|
||||||
item.2 '1-2 channels '
|
dbmax 3100
|
||||||
item.3 '1-3 channels '
|
dbvalue.0 0
|
||||||
item.4 '1-4 channels '
|
|
||||||
item.5 '1-5 channels '
|
|
||||||
item.6 '1-6 channels '
|
|
||||||
item.7 '1-7 channels '
|
|
||||||
item.8 '1-8 channels '
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.6 {
|
control.6 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'TX2 Channel9~16 enable'
|
name 'ADC2 PGA gain'
|
||||||
value 'disable all'
|
value 0
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type ENUMERATED
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
item.0 'disable all'
|
range '0 - 31'
|
||||||
item.1 '8-9 channels '
|
dbmin 0
|
||||||
item.2 '8-10 channels '
|
dbmax 3100
|
||||||
item.3 '8-11 channels '
|
dbvalue.0 0
|
||||||
item.4 '8-12 channels '
|
|
||||||
item.5 '8-13 channels '
|
|
||||||
item.6 '8-14 channels '
|
|
||||||
item.7 '8-15 channels '
|
|
||||||
item.8 '8-16 channels '
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.7 {
|
control.7 {
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'CH1 digital volume'
|
name 'ADC3 PGA gain'
|
||||||
value 181
|
value 0
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type INTEGER
|
type INTEGER
|
||||||
count 1
|
count 1
|
||||||
range '0 - 255'
|
range '0 - 31'
|
||||||
dbmin -11925
|
dbmin 0
|
||||||
dbmax 7200
|
dbmax 3100
|
||||||
dbvalue.0 1650
|
dbvalue.0 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
control.8 {
|
control.8 {
|
||||||
iface MIXER
|
|
||||||
name 'CH2 digital volume'
|
|
||||||
value 181
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type INTEGER
|
|
||||||
count 1
|
|
||||||
range '0 - 255'
|
|
||||||
dbmin -11925
|
|
||||||
dbmax 7200
|
|
||||||
dbvalue.0 1650
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.9 {
|
|
||||||
iface MIXER
|
|
||||||
name 'CH3 digital volume'
|
|
||||||
value 181
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type INTEGER
|
|
||||||
count 1
|
|
||||||
range '0 - 255'
|
|
||||||
dbmin -11925
|
|
||||||
dbmax 7200
|
|
||||||
dbvalue.0 1650
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.10 {
|
|
||||||
iface MIXER
|
|
||||||
name 'CH4 digital volume'
|
|
||||||
value 181
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type INTEGER
|
|
||||||
count 1
|
|
||||||
range '0 - 255'
|
|
||||||
dbmin -11925
|
|
||||||
dbmax 7200
|
|
||||||
dbvalue.0 1650
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.11 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC1 PGA gain'
|
|
||||||
value 27
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type INTEGER
|
|
||||||
count 1
|
|
||||||
range '0 - 31'
|
|
||||||
dbmin 0
|
|
||||||
dbmax 3100
|
|
||||||
dbvalue.0 2700
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.12 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC2 PGA gain'
|
|
||||||
value 27
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type INTEGER
|
|
||||||
count 1
|
|
||||||
range '0 - 31'
|
|
||||||
dbmin 0
|
|
||||||
dbmax 3100
|
|
||||||
dbvalue.0 2700
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.13 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC3 PGA gain'
|
|
||||||
value 27
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type INTEGER
|
|
||||||
count 1
|
|
||||||
range '0 - 31'
|
|
||||||
dbmin 0
|
|
||||||
dbmax 3100
|
|
||||||
dbvalue.0 2700
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.14 {
|
|
||||||
iface MIXER
|
iface MIXER
|
||||||
name 'ADC4 PGA gain'
|
name 'ADC4 PGA gain'
|
||||||
value 27
|
value 0
|
||||||
comment {
|
comment {
|
||||||
access 'read write'
|
access 'read write'
|
||||||
type INTEGER
|
type INTEGER
|
||||||
|
@ -271,683 +175,7 @@ state.seeed4micvoicec {
|
||||||
range '0 - 31'
|
range '0 - 31'
|
||||||
dbmin 0
|
dbmin 0
|
||||||
dbmax 3100
|
dbmax 3100
|
||||||
dbvalue.0 2700
|
dbvalue.0 0
|
||||||
}
|
|
||||||
}
|
|
||||||
control.15 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels'
|
|
||||||
value '4 channels '
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1 channels '
|
|
||||||
item.1 '2 channels '
|
|
||||||
item.2 '3 channels '
|
|
||||||
item.3 '4 channels '
|
|
||||||
item.4 '5 channels '
|
|
||||||
item.5 '6 channels '
|
|
||||||
item.6 '7 channels '
|
|
||||||
item.7 '8 channels '
|
|
||||||
item.8 '9 channels '
|
|
||||||
item.9 '10 channels '
|
|
||||||
item.10 '11 channels '
|
|
||||||
item.11 '12 channels '
|
|
||||||
item.12 '13 channels '
|
|
||||||
item.13 '14 channels '
|
|
||||||
item.14 '15 channels '
|
|
||||||
item.15 '16 channels '
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.16 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels'
|
|
||||||
value '1 channels '
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1 channels '
|
|
||||||
item.1 '2 channels '
|
|
||||||
item.2 '3 channels '
|
|
||||||
item.3 '4 channels '
|
|
||||||
item.4 '5 channels '
|
|
||||||
item.5 '6 channels '
|
|
||||||
item.6 '7 channels '
|
|
||||||
item.7 '8 channels '
|
|
||||||
item.8 '9 channels '
|
|
||||||
item.9 '10 channels '
|
|
||||||
item.10 '11 channels '
|
|
||||||
item.11 '12 channels '
|
|
||||||
item.12 '13 channels '
|
|
||||||
item.13 '14 channels '
|
|
||||||
item.14 '15 channels '
|
|
||||||
item.15 '16 channels '
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.17 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 1 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.18 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 2 MAP'
|
|
||||||
value '2st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.19 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 3 MAP'
|
|
||||||
value '3st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.20 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 4 MAP'
|
|
||||||
value '4st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.21 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 5 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.22 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 6 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.23 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 7 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.24 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 8 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.25 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 9 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.26 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 10 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.27 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 11 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.28 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 12 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.29 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 13 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.30 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 14 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.31 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 15 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.32 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx1 Channels 16 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.33 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 1 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.34 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 2 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.35 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 3 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.36 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 4 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.37 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 5 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.38 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 6 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.39 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 7 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.40 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 8 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.41 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 9 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.42 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 10 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.43 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 11 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.44 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 12 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.45 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 13 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.46 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 14 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.47 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 15 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.48 {
|
|
||||||
iface MIXER
|
|
||||||
name 'Tx2 Channels 16 MAP'
|
|
||||||
value '1st adc sample'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 '1st adc sample'
|
|
||||||
item.1 '2st adc sample'
|
|
||||||
item.2 '3st adc sample'
|
|
||||||
item.3 '4st adc sample'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.49 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC4 Source'
|
|
||||||
value 'Analog ADC4'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'Analog ADC1'
|
|
||||||
item.1 'Analog ADC2'
|
|
||||||
item.2 'Analog ADC3'
|
|
||||||
item.3 'Analog ADC4'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.50 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC3 Source'
|
|
||||||
value 'Analog ADC3'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'Analog ADC1'
|
|
||||||
item.1 'Analog ADC2'
|
|
||||||
item.2 'Analog ADC3'
|
|
||||||
item.3 'Analog ADC4'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.51 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC2 Source'
|
|
||||||
value 'Analog ADC2'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'Analog ADC1'
|
|
||||||
item.1 'Analog ADC2'
|
|
||||||
item.2 'Analog ADC3'
|
|
||||||
item.3 'Analog ADC4'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.52 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC1 Source'
|
|
||||||
value 'Analog ADC1'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'Analog ADC1'
|
|
||||||
item.1 'Analog ADC2'
|
|
||||||
item.2 'Analog ADC3'
|
|
||||||
item.3 'Analog ADC4'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.53 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC1 Digital Mixer gc'
|
|
||||||
value 'disable all'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.54 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC1 Digital Mixer src'
|
|
||||||
value 'ADC1 data'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.55 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC2 Digital Mixer gc'
|
|
||||||
value 'disable all'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.56 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC2 Digital Mixer src'
|
|
||||||
value 'ADC2 data'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.57 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC3 Digital Mixer gc'
|
|
||||||
value 'disable all'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.58 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC3 Digital Mixer src'
|
|
||||||
value 'ADC3 data'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.59 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC4 Digital Mixer gc'
|
|
||||||
value 'disable all'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
control.60 {
|
|
||||||
iface MIXER
|
|
||||||
name 'ADC4 Digital Mixer src'
|
|
||||||
value 'ADC4 data'
|
|
||||||
comment {
|
|
||||||
access 'read write'
|
|
||||||
type ENUMERATED
|
|
||||||
count 1
|
|
||||||
item.0 'disable all'
|
|
||||||
item.1 'ADC1 data'
|
|
||||||
item.2 'ADC2 data'
|
|
||||||
item.3 'ADC3 data'
|
|
||||||
item.4 'ADC4 data'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
126
ac10x.h
Normal file
126
ac10x.h
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* ac10x.h
|
||||||
|
*
|
||||||
|
* (C) Copyright 2017-2018
|
||||||
|
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
|
||||||
|
*
|
||||||
|
* PeterYang <linsheng.yang@seeed.cc>
|
||||||
|
*
|
||||||
|
* (C) Copyright 2010-2017
|
||||||
|
* Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
|
||||||
|
* huangxin <huangxin@reuuimllatech.com>
|
||||||
|
*
|
||||||
|
* some simple description for this code
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __AC10X_H__
|
||||||
|
#define __AC10X_H__
|
||||||
|
|
||||||
|
#define AC101_I2C_ID 4
|
||||||
|
#define _MASTER_AC108 0
|
||||||
|
#define _MASTER_AC101 1
|
||||||
|
#define _MASTER_MULTI_CODEC _MASTER_AC101
|
||||||
|
|
||||||
|
/* enable headset detecting & headset button pressing */
|
||||||
|
#define CONFIG_AC101_SWITCH_DETECT
|
||||||
|
|
||||||
|
/* obsolete */
|
||||||
|
#define CONFIG_AC10X_TRIG_LOCK 0
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef AC101_DEBG
|
||||||
|
#define AC101_DBG(format,args...) printk("[AC101] %s() L%d " format, __func__, __LINE__, ##args)
|
||||||
|
#else
|
||||||
|
#define AC101_DBG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "sound-compatible-4.18.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_AC101_SWITCH_DETECT
|
||||||
|
enum headphone_mode_u {
|
||||||
|
HEADPHONE_IDLE,
|
||||||
|
FOUR_HEADPHONE_PLUGIN,
|
||||||
|
THREE_HEADPHONE_PLUGIN,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ac10x_priv {
|
||||||
|
struct i2c_client *i2c[4];
|
||||||
|
struct regmap* i2cmap[4];
|
||||||
|
int codec_cnt;
|
||||||
|
unsigned sysclk;
|
||||||
|
#define _FREQ_24_576K 24576000
|
||||||
|
#define _FREQ_22_579K 22579200
|
||||||
|
unsigned mclk; /* master clock or aif_clock/aclk */
|
||||||
|
int clk_id;
|
||||||
|
unsigned char i2s_mode;
|
||||||
|
unsigned char data_protocol;
|
||||||
|
struct delayed_work dlywork;
|
||||||
|
int tdm_chips_cnt;
|
||||||
|
int sysclk_en;
|
||||||
|
|
||||||
|
/* member for ac101 .begin */
|
||||||
|
struct snd_soc_codec *codec;
|
||||||
|
struct i2c_client *i2c101;
|
||||||
|
struct regmap* regmap101;
|
||||||
|
|
||||||
|
struct mutex dac_mutex;
|
||||||
|
u8 dac_enable;
|
||||||
|
spinlock_t lock;
|
||||||
|
u8 aif1_clken;
|
||||||
|
|
||||||
|
struct work_struct codec_resume;
|
||||||
|
struct gpio_desc* gpiod_spk_amp_gate;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AC101_SWITCH_DETECT
|
||||||
|
struct gpio_desc* gpiod_irq;
|
||||||
|
long irq;
|
||||||
|
volatile int irq_cntr;
|
||||||
|
volatile int pullout_cntr;
|
||||||
|
volatile int state;
|
||||||
|
|
||||||
|
enum headphone_mode_u mode;
|
||||||
|
struct work_struct work_switch;
|
||||||
|
struct work_struct work_clear_irq;
|
||||||
|
|
||||||
|
struct input_dev* inpdev;
|
||||||
|
#endif
|
||||||
|
/* member for ac101 .end */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* AC101 DAI operations */
|
||||||
|
int ac101_audio_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai);
|
||||||
|
void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai);
|
||||||
|
int ac101_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
|
||||||
|
int ac101_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params,
|
||||||
|
struct snd_soc_dai *codec_dai);
|
||||||
|
int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
|
struct snd_soc_dai *dai);
|
||||||
|
int ac101_aif_mute(struct snd_soc_dai *codec_dai, int mute);
|
||||||
|
|
||||||
|
/* codec driver specific */
|
||||||
|
int ac101_codec_probe(struct snd_soc_codec *codec);
|
||||||
|
int ac101_codec_remove(struct snd_soc_codec *codec);
|
||||||
|
int ac101_codec_suspend(struct snd_soc_codec *codec);
|
||||||
|
int ac101_codec_resume(struct snd_soc_codec *codec);
|
||||||
|
int ac101_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level);
|
||||||
|
|
||||||
|
/* i2c device specific */
|
||||||
|
int ac101_probe(struct i2c_client *i2c, const struct i2c_device_id *id);
|
||||||
|
void ac101_shutdown(struct i2c_client *i2c);
|
||||||
|
int ac101_remove(struct i2c_client *i2c);
|
||||||
|
|
||||||
|
/* seeed voice card export */
|
||||||
|
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int, struct snd_pcm_substream *, int, struct snd_soc_dai *));
|
||||||
|
|
||||||
|
int ac10x_fill_regcache(struct device* dev, struct regmap* map);
|
||||||
|
|
||||||
|
#endif//__AC10X_H__
|
|
@ -1,11 +1,15 @@
|
||||||
# The IPC key of dmix or dsnoop plugin must be unique
|
# The IPC key of dmix or dsnoop plugin must be unique
|
||||||
# If 555555 or 666666 is used by other processes, use another one
|
# If 555555 or 666666 is used by other processes, use another one
|
||||||
|
|
||||||
# pcm.!default {
|
|
||||||
# type asym
|
# use samplerate to resample as speexdsp resample is bad
|
||||||
# playback.pcm "playback"
|
defaults.pcm.rate_converter "samplerate"
|
||||||
# capture.pcm "capture"
|
|
||||||
# }
|
pcm.!default {
|
||||||
|
type asym
|
||||||
|
playback.pcm "playback"
|
||||||
|
capture.pcm "capture"
|
||||||
|
}
|
||||||
|
|
||||||
pcm.playback {
|
pcm.playback {
|
||||||
type plug
|
type plug
|
||||||
|
@ -19,21 +23,16 @@ pcm.capture {
|
||||||
|
|
||||||
pcm.dmixed {
|
pcm.dmixed {
|
||||||
type dmix
|
type dmix
|
||||||
slave.pcm "hw:0,0"
|
slave.pcm "hw:seeed2micvoicec"
|
||||||
ipc_key 555555
|
ipc_key 555555
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm.array {
|
pcm.array {
|
||||||
type dsnoop
|
type dsnoop
|
||||||
slave {
|
slave {
|
||||||
pcm "hw:0,0"
|
pcm "hw:seeed2micvoicec"
|
||||||
channels 2
|
channels 2
|
||||||
}
|
}
|
||||||
ipc_key 666666
|
ipc_key 666666
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm.ac108 {
|
|
||||||
type ac108
|
|
||||||
slavepcm "hw:1,0"
|
|
||||||
channels 4
|
|
||||||
}
|
|
33
asound_4mic.conf
Normal file
33
asound_4mic.conf
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# The IPC key of dmix or dsnoop plugin must be unique
|
||||||
|
# If 555555 or 666666 is used by other processes, use another one
|
||||||
|
|
||||||
|
# use samplerate to resample as speexdsp resample is bad
|
||||||
|
defaults.pcm.rate_converter "samplerate"
|
||||||
|
|
||||||
|
pcm.!default {
|
||||||
|
type asym
|
||||||
|
playback.pcm "playback"
|
||||||
|
capture.pcm "ac108"
|
||||||
|
}
|
||||||
|
|
||||||
|
pcm.playback {
|
||||||
|
type plug
|
||||||
|
slave.pcm "hw:ALSA"
|
||||||
|
}
|
||||||
|
|
||||||
|
# pcm.dmixed {
|
||||||
|
# type dmix
|
||||||
|
# slave.pcm "hw:0,0"
|
||||||
|
# ipc_key 555555
|
||||||
|
# }
|
||||||
|
|
||||||
|
pcm.ac108 {
|
||||||
|
type plug
|
||||||
|
slave.pcm "hw:seeed4micvoicec"
|
||||||
|
}
|
||||||
|
|
||||||
|
# pcm.multiapps {
|
||||||
|
# type dsnoop
|
||||||
|
# ac108-slavepcm "hw:1,0"
|
||||||
|
# ipc_key 666666
|
||||||
|
# }
|
90
asound_6mic.conf
Normal file
90
asound_6mic.conf
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
# The IPC key of dmix or dsnoop plugin must be unique
|
||||||
|
# If 555555 or 666666 is used by other processes, use another one
|
||||||
|
|
||||||
|
# use samplerate to resample as speexdsp resample is broken
|
||||||
|
defaults.pcm.rate_converter "samplerate"
|
||||||
|
|
||||||
|
pcm.!default {
|
||||||
|
type asym
|
||||||
|
playback.pcm "dmixer"
|
||||||
|
capture.pcm "ac108"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pcm.ac108 {
|
||||||
|
type plug
|
||||||
|
slave {
|
||||||
|
rate 48000
|
||||||
|
format S32_LE
|
||||||
|
pcm "hw:seeed8micvoicec"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# pcm.multiapps {
|
||||||
|
# type plug
|
||||||
|
# slave.pcm {
|
||||||
|
# type dsnoop
|
||||||
|
# slave {
|
||||||
|
# rate 48000
|
||||||
|
# format S32_LE
|
||||||
|
# pcm "hw:seeed8micvoicec"
|
||||||
|
# }
|
||||||
|
# ipc_key 666666
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
pcm.dmixer {
|
||||||
|
type plug
|
||||||
|
slave {
|
||||||
|
pcm {
|
||||||
|
type dmix
|
||||||
|
ipc_key 555555
|
||||||
|
slave {
|
||||||
|
pcm "hw:seeed8micvoicec"
|
||||||
|
format S32_LE
|
||||||
|
channels 8
|
||||||
|
}
|
||||||
|
bindings {
|
||||||
|
0 0
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
3 3
|
||||||
|
4 4
|
||||||
|
5 5
|
||||||
|
6 6
|
||||||
|
7 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channels 8
|
||||||
|
format S32_LE
|
||||||
|
rate 48000
|
||||||
|
}
|
||||||
|
ttable.0.0 1
|
||||||
|
ttable.1.1 1
|
||||||
|
ttable.0.2 1
|
||||||
|
ttable.1.3 1
|
||||||
|
ttable.0.4 1
|
||||||
|
ttable.1.5 1
|
||||||
|
ttable.0.6 1
|
||||||
|
ttable.1.7 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pcm.ac101 {
|
||||||
|
type plug
|
||||||
|
slave {
|
||||||
|
pcm "hw:seeed8micvoicec"
|
||||||
|
channels 8
|
||||||
|
format S32_LE
|
||||||
|
rate 48000
|
||||||
|
}
|
||||||
|
ttable.0.0 1
|
||||||
|
ttable.1.1 1
|
||||||
|
ttable.0.2 1
|
||||||
|
ttable.1.3 1
|
||||||
|
ttable.0.4 1
|
||||||
|
ttable.1.5 1
|
||||||
|
ttable.0.6 1
|
||||||
|
ttable.1.7 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
#dtoverlay -r seeed-2mic-voicecard
|
#dtoverlay -r seeed-2mic-voicecard
|
||||||
|
DTC_FLAGS="-b 0 -Wno-unit_address_vs_reg -I dts -O dtb"
|
||||||
|
|
||||||
dtc -@ -I dts -O dtb -o seeed-2mic-voicecard.dtbo seeed-2mic-voicecard-overlay.dts
|
dtc -@ $DTC_FLAGS -o seeed-2mic-voicecard.dtbo seeed-2mic-voicecard-overlay.dts
|
||||||
dtc -@ -I dts -O dtb -o seeed-4mic-voicecard.dtbo seeed-4mic-voicecard-overlay.dts
|
dtc -@ $DTC_FLAGS -o seeed-4mic-voicecard.dtbo seeed-4mic-voicecard-overlay.dts
|
||||||
|
dtc -@ $DTC_FLAGS -o seeed-8mic-voicecard.dtbo seeed-8mic-voicecard-overlay.dts
|
||||||
|
|
||||||
# cp *.dtbo /boot/overlays
|
# cp *.dtbo /boot/overlays
|
||||||
# dtoverlay seeed-2mic-voicecard
|
# dtoverlay seeed-2mic-voicecard
|
||||||
|
|
10
dkms.conf
10
dkms.conf
|
@ -1,7 +1,15 @@
|
||||||
PACKAGE_NAME="seeed-voicecard"
|
PACKAGE_NAME="seeed-voicecard"
|
||||||
PACKAGE_VERSION="0.2"
|
PACKAGE_VERSION="0.3"
|
||||||
BUILT_MODULE_NAME[0]="snd-soc-wm8960"
|
BUILT_MODULE_NAME[0]="snd-soc-wm8960"
|
||||||
BUILT_MODULE_NAME[1]="snd-soc-ac108"
|
BUILT_MODULE_NAME[1]="snd-soc-ac108"
|
||||||
|
BUILT_MODULE_NAME[2]="snd-soc-seeed-voicecard"
|
||||||
DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs"
|
DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs"
|
||||||
DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs"
|
DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs"
|
||||||
|
DEST_MODULE_LOCATION[2]="/kernel/sound/soc/bcm"
|
||||||
|
PATCH[0]="back-to-v4.19.diff"
|
||||||
|
PATCH[1]="back-to-v5.4.diff"
|
||||||
|
PATCH[2]="back-to-v5.8.diff"
|
||||||
|
PATCH_MATCH[0]="^4\.19\.*"
|
||||||
|
PATCH_MATCH[1]="^5\.4\.*"
|
||||||
|
PATCH_MATCH[2]="^5\.8\.*"
|
||||||
AUTOINSTALL="yes"
|
AUTOINSTALL="yes"
|
||||||
|
|
236
install.sh
236
install.sh
|
@ -5,34 +5,134 @@ if [[ $EUID -ne 0 ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
is_Raspberry=$(cat /proc/device-tree/model | awk '{print $1}')
|
# Check for enough space on /boot volume
|
||||||
if [ "x${is_Raspberry}" != "xRaspberry" ] ; then
|
boot_line=$(df -h | grep /boot | head -n 1)
|
||||||
echo "Sorry, this drivers only works on raspberry pi"
|
if [ "x${boot_line}" = "x" ]; then
|
||||||
|
echo "Warning: /boot volume not found .."
|
||||||
|
else
|
||||||
|
boot_space=$(echo $boot_line | awk '{print $4;}')
|
||||||
|
free_space=$(echo "${boot_space%?}")
|
||||||
|
unit="${boot_space: -1}"
|
||||||
|
if [[ "$unit" = "K" ]]; then
|
||||||
|
echo "Error: Not enough space left ($boot_space) on /boot"
|
||||||
|
exit 1
|
||||||
|
elif [[ "$unit" = "M" ]]; then
|
||||||
|
if [ "$free_space" -lt "25" ]; then
|
||||||
|
echo "Error: Not enough space left ($boot_space) on /boot"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# make sure that we are on something ARM/Raspberry related
|
||||||
|
# either a bare metal Raspberry or a qemu session with
|
||||||
|
# Raspberry stuff available
|
||||||
|
# - check for /boot/overlays
|
||||||
|
# - dtparam and dtoverlay is available
|
||||||
|
errorFound=0
|
||||||
|
OVERLAYS=/boot/overlays
|
||||||
|
[ -d /boot/firmware/overlays ] && OVERLAYS=/boot/firmware/overlays
|
||||||
|
|
||||||
|
if [ ! -d $OVERLAYS ] ; then
|
||||||
|
echo "$OVERLAYS not found or not a directory" 1>&2
|
||||||
|
errorFound=1
|
||||||
|
fi
|
||||||
|
# should we also check for alsactl and amixer used in seeed-voicecard?
|
||||||
|
PATH=$PATH:/opt/vc/bin
|
||||||
|
for cmd in dtparam dtoverlay ; do
|
||||||
|
if ! which $cmd &>/dev/null ; then
|
||||||
|
echo "$cmd not found" 1>&2
|
||||||
|
echo "You may need to run ./ubuntu-prerequisite.sh"
|
||||||
|
errorFound=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ $errorFound = 1 ] ; then
|
||||||
|
echo "Errors found, exiting." 1>&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ver="0.2"
|
ver="0.3"
|
||||||
card=$1
|
uname_r=$(uname -r)
|
||||||
|
|
||||||
if [ "x${card}" = "x" ] ; then
|
|
||||||
echo "Usage: ./install 2mic|4mic"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# we create a dir with this version to ensure that 'dkms remove' won't delete
|
# we create a dir with this version to ensure that 'dkms remove' won't delete
|
||||||
# the sources during kernel updates
|
# the sources during kernel updates
|
||||||
marker="0.0.0"
|
marker="0.0.0"
|
||||||
|
|
||||||
apt update
|
_VER_RUN=
|
||||||
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
|
function get_kernel_version() {
|
||||||
apt-get -y install dkms
|
local ZIMAGE IMG_OFFSET
|
||||||
|
|
||||||
|
_VER_RUN=""
|
||||||
|
[ -z "$_VER_RUN" ] && {
|
||||||
|
ZIMAGE=/boot/kernel.img
|
||||||
|
[ -f /boot/firmware/vmlinuz ] && ZIMAGE=/boot/firmware/vmlinuz
|
||||||
|
# 64-bit-only kernel package
|
||||||
|
[ ! -f /boot/kernel.img ] && [ -f /boot/kernel8.img ] && ZIMAGE=/boot/kernel8.img
|
||||||
|
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
|
||||||
|
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | LC_ALL=C sed -e 's/^.*Linux/Linux/' | strings | awk '{ print $3; }')
|
||||||
|
}
|
||||||
|
echo "$_VER_RUN"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_kernel_headers() {
|
||||||
|
VER_RUN=$(get_kernel_version)
|
||||||
|
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
|
||||||
|
[ "X$VER_RUN" == "X$VER_HDR" ] && {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
|
||||||
|
[ "X$VER_RUN" == "X$VER_HDR" ] && {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# echo RUN=$VER_RUN HDR=$VER_HDR
|
||||||
|
echo " !!! Your kernel version is $VER_RUN"
|
||||||
|
echo " Not found *** corresponding *** kernel headers with apt-get."
|
||||||
|
echo " This may occur if you have ran 'rpi-update'."
|
||||||
|
echo " Choose *** y *** will revert the kernel to version $VER_HDR then continue."
|
||||||
|
echo " Choose *** N *** will exit without this driver support, by default."
|
||||||
|
read -p "Would you like to proceed? (y/N)" -n 1 -r -s
|
||||||
|
echo
|
||||||
|
if ! [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
apt-get -y --reinstall install raspberrypi-kernel
|
||||||
|
}
|
||||||
|
|
||||||
|
# update and install required packages
|
||||||
|
which apt &>/dev/null
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
apt update -y
|
||||||
|
# Raspbian kernel packages
|
||||||
|
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
|
||||||
|
# Recent Raspbian has 64-bit kernel on 32-bit userspace
|
||||||
|
apt-get -y install gcc-aarch64-linux-gnu
|
||||||
|
# Ubuntu kernel packages
|
||||||
|
apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi
|
||||||
|
apt-get -y install dkms git i2c-tools libasound2-plugins
|
||||||
|
# rpi-update checker
|
||||||
|
check_kernel_headers
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Arch Linux
|
||||||
|
which pacman &>/dev/null
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
pacman -Syu --needed git gcc automake make dkms linux-raspberrypi-headers i2c-tools
|
||||||
|
fi
|
||||||
|
|
||||||
# locate currently installed kernels (may be different to running kernel if
|
# locate currently installed kernels (may be different to running kernel if
|
||||||
# it's just been updated)
|
# it's just been updated)
|
||||||
kernels=$(ls /lib/modules | sed "s/^/-k /")
|
base_ver=$(get_kernel_version)
|
||||||
uname_r=$(uname -r)
|
base_ver=${base_ver%%[-+]*}
|
||||||
|
#kernels="${base_ver}+ ${base_ver}-v7+ ${base_ver}-v7l+"
|
||||||
|
kernels=$(uname -r)
|
||||||
|
|
||||||
function install_module {
|
function install_module {
|
||||||
|
local _i
|
||||||
|
|
||||||
src=$1
|
src=$1
|
||||||
mod=$2
|
mod=$2
|
||||||
|
|
||||||
|
@ -41,67 +141,81 @@ function install_module {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -e /usr/src/$mod-$ver || -e /var/lib/dkms/$mod/$ver ]]; then
|
if [[ -e /usr/src/$mod-$ver || -e /var/lib/dkms/$mod/$ver ]]; then
|
||||||
dkms remove -m $mod -v $ver --all
|
dkms remove --force -m $mod -v $ver --all
|
||||||
rm -rf /usr/src/$mod-$ver
|
rm -rf /usr/src/$mod-$ver
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p /usr/src/$mod-$ver
|
mkdir -p /usr/src/$mod-$ver
|
||||||
cp -a $src/* /usr/src/$mod-$ver/
|
cp -a $src/* /usr/src/$mod-$ver/
|
||||||
|
|
||||||
dkms add -m $mod -v $ver
|
dkms add -m $mod -v $ver
|
||||||
dkms build $kernels -m $mod -v $ver && dkms install $kernels -m $mod -v $ver
|
for _i in $kernels; do
|
||||||
|
dkms build -k $_i -m $mod -v $ver && {
|
||||||
|
dkms install --force -k $_i -m $mod -v $ver
|
||||||
|
}
|
||||||
|
done
|
||||||
|
|
||||||
mkdir -p /var/lib/dkms/$mod/$ver/$marker
|
mkdir -p /var/lib/dkms/$mod/$ver/$marker
|
||||||
}
|
}
|
||||||
if [ ! -f "/boot/overlays/seeed-4mic-voicecard.dtbo" ] && [ ! -f "/lib/modules/${uname_r}/kernel/sound/soc/codecs/snd-soc-ac108.ko" ] ; then
|
|
||||||
install_module "./" "seeed-voicecard"
|
|
||||||
cp seeed-2mic-voicecard.dtbo /boot/overlays
|
|
||||||
cp seeed-4mic-voicecard.dtbo /boot/overlays
|
|
||||||
cp ac108_plugin/libasound_module_pcm_ac108.so /usr/lib/arm-linux-gnueabihf/alsa-lib/
|
|
||||||
cp asound.conf /etc/
|
|
||||||
else
|
|
||||||
echo "card driver already installed"
|
|
||||||
fi
|
|
||||||
|
|
||||||
grep -q "snd-soc-ac108" /etc/modules || \
|
install_module "./" "seeed-voicecard"
|
||||||
|
|
||||||
|
|
||||||
|
# install dtbos
|
||||||
|
cp seeed-2mic-voicecard.dtbo $OVERLAYS
|
||||||
|
cp seeed-4mic-voicecard.dtbo $OVERLAYS
|
||||||
|
cp seeed-8mic-voicecard.dtbo $OVERLAYS
|
||||||
|
|
||||||
|
#install alsa plugins
|
||||||
|
# no need this plugin now
|
||||||
|
# install -D ac108_plugin/libasound_module_pcm_ac108.so /usr/lib/arm-linux-gnueabihf/alsa-lib/
|
||||||
|
rm -f /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_ac108.so
|
||||||
|
|
||||||
|
#set kernel modules
|
||||||
|
grep -q "^snd-soc-seeed-voicecard$" /etc/modules || \
|
||||||
|
echo "snd-soc-seeed-voicecard" >> /etc/modules
|
||||||
|
grep -q "^snd-soc-ac108$" /etc/modules || \
|
||||||
echo "snd-soc-ac108" >> /etc/modules
|
echo "snd-soc-ac108" >> /etc/modules
|
||||||
grep -q "snd-soc-wm8960" /etc/modules || \
|
grep -q "^snd-soc-wm8960$" /etc/modules || \
|
||||||
echo "snd-soc-wm8960" >> /etc/modules
|
echo "snd-soc-wm8960" >> /etc/modules
|
||||||
|
|
||||||
|
#set dtoverlays
|
||||||
|
CONFIG=/boot/config.txt
|
||||||
|
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
|
||||||
|
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
|
||||||
|
|
||||||
|
sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' $CONFIG || true
|
||||||
|
grep -q "^dtoverlay=i2s-mmap$" $CONFIG || \
|
||||||
|
echo "dtoverlay=i2s-mmap" >> $CONFIG
|
||||||
|
|
||||||
|
|
||||||
grep -q "dtoverlay=i2s-mmap" /boot/config.txt || \
|
grep -q "^dtparam=i2s=on$" $CONFIG || \
|
||||||
echo "dtoverlay=i2s-mmap" >> /boot/config.txt
|
echo "dtparam=i2s=on" >> $CONFIG
|
||||||
|
|
||||||
|
#install config files
|
||||||
|
mkdir /etc/voicecard || true
|
||||||
|
cp *.conf /etc/voicecard
|
||||||
|
cp *.state /etc/voicecard
|
||||||
|
|
||||||
grep -q "dtparam=i2s=on" /boot/config.txt || \
|
#create git repo
|
||||||
echo "dtparam=i2s=on" >> /boot/config.txt
|
git_email=$(git config --global --get user.email)
|
||||||
|
git_name=$(git config --global --get user.name)
|
||||||
|
if [ "x${git_email}" == "x" ] || [ "x${git_name}" == "x" ] ; then
|
||||||
|
echo "setup git config"
|
||||||
|
git config --global user.email "respeaker@seeed.cc"
|
||||||
|
git config --global user.name "respeaker"
|
||||||
|
fi
|
||||||
|
echo "git init"
|
||||||
|
git --git-dir=/etc/voicecard/.git init
|
||||||
|
echo "git add --all"
|
||||||
|
git --git-dir=/etc/voicecard/.git --work-tree=/etc/voicecard/ add --all
|
||||||
|
echo "git commit -m \"origin configures\""
|
||||||
|
git --git-dir=/etc/voicecard/.git --work-tree=/etc/voicecard/ commit -m "origin configures"
|
||||||
|
|
||||||
has_2mic=$(grep seeed-2mic-voicecard /boot/config.txt)
|
cp seeed-voicecard /usr/bin/
|
||||||
has_4mic=$(grep seeed-4mic-voicecard /boot/config.txt)
|
cp seeed-voicecard.service /lib/systemd/system/
|
||||||
case "${card}" in
|
systemctl enable seeed-voicecard.service
|
||||||
"2mic")
|
systemctl start seeed-voicecard
|
||||||
echo "cp wm8960_asound.state /var/lib/alsa/asound.state"
|
|
||||||
cp wm8960_asound.state /var/lib/alsa/asound.state
|
|
||||||
if [ "x${has_4mic}" != x ] ; then
|
|
||||||
echo "has 4mic before, now remove it"
|
|
||||||
sed -i "s/dtoverlay=seeed-4mic-voicecard//g" /boot/config.txt
|
|
||||||
fi
|
|
||||||
grep -q "dtoverlay=seeed-2mic-voicecard" /boot/config.txt || \
|
|
||||||
echo "dtoverlay=seeed-2mic-voicecard" >> /boot/config.txt
|
|
||||||
|
|
||||||
;;
|
|
||||||
"4mic")
|
|
||||||
echo "cp ac108_asound.state /var/lib/alsa/asound.state"
|
|
||||||
cp ac108_asound.state /var/lib/alsa/asound.state
|
|
||||||
if [ "x${has_2mic}" != x ] ; then
|
|
||||||
echo "has 2mic before, now remove it"
|
|
||||||
sed -i "s/dtoverlay=seeed-2mic-voicecard//g" /boot/config.txt
|
|
||||||
fi
|
|
||||||
grep -q "dtoverlay=seeed-4mic-voicecard" /boot/config.txt || \
|
|
||||||
echo "dtoverlay=seeed-4mic-voicecard" >> /boot/config.txt
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Please use 2mic or 4mic"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "------------------------------------------------------"
|
echo "------------------------------------------------------"
|
||||||
echo "Please reboot your raspberry pi to apply all settings"
|
echo "Please reboot your raspberry pi to apply all settings"
|
||||||
|
|
454
patches/back-to-v4.19.diff
Normal file
454
patches/back-to-v4.19.diff
Normal file
|
@ -0,0 +1,454 @@
|
||||||
|
diff --git a/ac101.c b/ac101.c
|
||||||
|
index 23837a7..41c15f3 100644
|
||||||
|
--- a/ac101.c
|
||||||
|
+++ b/ac101.c
|
||||||
|
@@ -955,10 +955,10 @@ void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai
|
||||||
|
|
||||||
|
AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n",
|
||||||
|
snd_pcm_stream_str(substream),
|
||||||
|
- codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE],
|
||||||
|
- snd_soc_dai_active(codec_dai));
|
||||||
|
+ codec_dai->playback_active, codec_dai->capture_active,
|
||||||
|
+ codec_dai->active);
|
||||||
|
|
||||||
|
- if (!snd_soc_dai_active(codec_dai)) {
|
||||||
|
+ if (!codec_dai->active) {
|
||||||
|
ac10x->aif1_clken = 1;
|
||||||
|
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
|
||||||
|
} else {
|
||||||
|
@@ -1080,7 +1080,7 @@ int ac101_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
freq_out = _FREQ_24_576K;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
|
||||||
|
if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
|
||||||
|
- if (codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
|
||||||
|
+ if (codec_dai->capture_active && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
|
||||||
|
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS));
|
||||||
|
} else {
|
||||||
|
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
|
||||||
|
diff --git a/ac108.c b/ac108.c
|
||||||
|
index d5dd12d..0a8c462 100644
|
||||||
|
--- a/ac108.c
|
||||||
|
+++ b/ac108.c
|
||||||
|
@@ -653,7 +653,7 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
|
||||||
|
|
||||||
|
dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
|
||||||
|
snd_pcm_stream_str(substream),
|
||||||
|
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
|
||||||
|
+ dai->playback_active, dai->capture_active);
|
||||||
|
|
||||||
|
if (ac10x->i2c101) {
|
||||||
|
ret = ac101_hw_params(substream, params, dai);
|
||||||
|
@@ -664,8 +664,8 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])
|
||||||
|
- || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream_active[SNDRV_PCM_STREAM_CAPTURE])) {
|
||||||
|
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->playback_active)
|
||||||
|
+ || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->capture_active)) {
|
||||||
|
/* not configure hw_param twice */
|
||||||
|
/* return 0; */
|
||||||
|
}
|
||||||
|
@@ -810,9 +810,6 @@ static int ac108_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int fr
|
||||||
|
|
||||||
|
struct ac10x_priv *ac10x = snd_soc_dai_get_drvdata(dai);
|
||||||
|
|
||||||
|
- if (freq != 24000000 || clk_id != SYSCLK_SRC_PLL)
|
||||||
|
- dev_warn(dai->dev, "ac108_set_sysclk freq = %d clk = %d\n", freq, clk_id);
|
||||||
|
-
|
||||||
|
freq = 24000000;
|
||||||
|
clk_id = SYSCLK_SRC_PLL;
|
||||||
|
|
||||||
|
@@ -1124,7 +1121,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
|
||||||
|
+int ac108_aif_mute(struct snd_soc_dai *dai, int mute) {
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
@@ -1145,13 +1142,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
|
||||||
|
.hw_params = ac108_hw_params,
|
||||||
|
.prepare = ac108_prepare,
|
||||||
|
.trigger = ac108_trigger,
|
||||||
|
- .mute_stream = ac108_aif_mute,
|
||||||
|
+ .digital_mute = ac108_aif_mute,
|
||||||
|
|
||||||
|
/*DAI format configuration*/
|
||||||
|
.set_fmt = ac108_set_fmt,
|
||||||
|
|
||||||
|
// .hw_free = ac108_hw_free,
|
||||||
|
- .no_capture_mute = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver ac108_dai0 = {
|
||||||
|
diff --git a/seeed-voicecard.c b/seeed-voicecard.c
|
||||||
|
index b90af93..af6db74 100644
|
||||||
|
--- a/seeed-voicecard.c
|
||||||
|
+++ b/seeed-voicecard.c
|
||||||
|
@@ -28,8 +28,6 @@
|
||||||
|
#include <sound/simple_card_utils.h>
|
||||||
|
#include "ac10x.h"
|
||||||
|
|
||||||
|
-#define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3))
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* single codec:
|
||||||
|
* 0 - allow multi codec
|
||||||
|
@@ -42,9 +40,6 @@ struct seeed_card_data {
|
||||||
|
struct seeed_dai_props {
|
||||||
|
struct asoc_simple_dai cpu_dai;
|
||||||
|
struct asoc_simple_dai codec_dai;
|
||||||
|
- struct snd_soc_dai_link_component cpus; /* single cpu */
|
||||||
|
- struct snd_soc_dai_link_component codecs; /* single codec */
|
||||||
|
- struct snd_soc_dai_link_component platforms;
|
||||||
|
unsigned int mclk_fs;
|
||||||
|
} *dai_props;
|
||||||
|
unsigned int mclk_fs;
|
||||||
|
@@ -97,16 +92,16 @@ static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
|
||||||
|
if (ret)
|
||||||
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
- if (asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min) {
|
||||||
|
- priv->channels_playback_default = asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min;
|
||||||
|
+ if (rtd->cpu_dai->driver->playback.channels_min) {
|
||||||
|
+ priv->channels_playback_default = rtd->cpu_dai->driver->playback.channels_min;
|
||||||
|
}
|
||||||
|
- if (asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min) {
|
||||||
|
- priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min;
|
||||||
|
+ if (rtd->cpu_dai->driver->capture.channels_min) {
|
||||||
|
+ priv->channels_capture_default = rtd->cpu_dai->driver->capture.channels_min;
|
||||||
|
}
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_override;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_override;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_override;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_override;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_override;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_override;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_override;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_override;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -118,10 +113,10 @@ static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_default;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_default;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_default;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_default;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_default;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_default;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_default;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_default;
|
||||||
|
|
||||||
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
@@ -132,8 +127,8 @@ static int seeed_voice_card_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
- struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
- struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||||
|
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||||
|
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
@@ -197,7 +192,7 @@ static void work_cb_codec_clk(struct work_struct *work)
|
||||||
|
static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
- struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
+ struct snd_soc_dai *dai = rtd->codec_dai;
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -206,7 +201,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
|
||||||
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
|
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
|
||||||
|
+ dai->playback_active, dai->capture_active);
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
@@ -228,7 +223,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
|
/* capture channel resync, if overrun */
|
||||||
|
- if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
+ if (dai->capture_active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -248,7 +243,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
|
||||||
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
|
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE], ret);
|
||||||
|
+ dai->playback_active, dai->capture_active, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -387,8 +382,8 @@ static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
- struct snd_soc_dai *codec = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
- struct snd_soc_dai *cpu = asoc_rtd_to_cpu(rtd, 0);
|
||||||
|
+ struct snd_soc_dai *codec = rtd->codec_dai;
|
||||||
|
+ struct snd_soc_dai *cpu = rtd->cpu_dai;
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
int ret;
|
||||||
|
@@ -453,19 +448,20 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
|
goto dai_link_of_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = asoc_simple_parse_daifmt(dev, node, codec,
|
||||||
|
+ ret = asoc_simple_card_parse_daifmt(dev, node, codec,
|
||||||
|
prefix, &dai_link->dai_fmt);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
|
||||||
|
|
||||||
|
- ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
|
||||||
|
+ ret = asoc_simple_card_parse_cpu(cpu, dai_link,
|
||||||
|
+ DAI, CELL, &single_cpu);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
- ret = asoc_simple_parse_codec(codec, dai_link);
|
||||||
|
+ ret = asoc_simple_card_parse_codec(codec, dai_link, DAI, CELL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
#else
|
||||||
|
@@ -477,7 +473,7 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
|
dev_dbg(dev, "dai_link num_codecs = %d\n", dai_link->num_codecs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- ret = asoc_simple_parse_platform(plat, dai_link);
|
||||||
|
+ ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
@@ -502,7 +498,7 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
|
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,10,0)
|
||||||
|
ret = asoc_simple_card_parse_clk_cpu(cpu, dai_link, cpu_dai);
|
||||||
|
#else
|
||||||
|
- ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
|
||||||
|
+ ret = asoc_simple_card_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
|
||||||
|
#endif
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
@@ -510,16 +506,16 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
|
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,10,0)
|
||||||
|
ret = asoc_simple_card_parse_clk_codec(codec, dai_link, codec_dai);
|
||||||
|
#else
|
||||||
|
- ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
|
||||||
|
+ ret = asoc_simple_card_parse_clk_codec(dev, codec, dai_link, codec_dai);
|
||||||
|
#endif
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
- ret = asoc_simple_set_dailink_name(dev, dai_link,
|
||||||
|
+ ret = asoc_simple_card_set_dailink_name(dev, dai_link,
|
||||||
|
"%s-%s",
|
||||||
|
- dai_link->cpus->dai_name,
|
||||||
|
+ dai_link->cpu_dai_name,
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
- dai_link->codecs->dai_name
|
||||||
|
+ dai_link->codec_dai_name
|
||||||
|
#else
|
||||||
|
dai_link->codecs[0].dai_name
|
||||||
|
#endif
|
||||||
|
@@ -533,19 +529,21 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
|
dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
|
||||||
|
dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt);
|
||||||
|
dev_dbg(dev, "\tcpu : %s / %d\n",
|
||||||
|
- dai_link->cpus->dai_name,
|
||||||
|
+ dai_link->cpu_dai_name,
|
||||||
|
dai_props->cpu_dai.sysclk);
|
||||||
|
dev_dbg(dev, "\tcodec : %s / %d\n",
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
- dai_link->codecs->dai_name,
|
||||||
|
+ dai_link->codec_dai_name,
|
||||||
|
#else
|
||||||
|
dai_link->codecs[0].dai_name,
|
||||||
|
#endif
|
||||||
|
dai_props->codec_dai.sysclk);
|
||||||
|
|
||||||
|
- asoc_simple_canonicalize_cpu(dai_link, single_cpu);
|
||||||
|
+ asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
- asoc_simple_canonicalize_platform(dai_link);
|
||||||
|
+ ret = asoc_simple_card_canonicalize_dailink(dai_link);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto dai_link_of_err;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dai_link_of_err:
|
||||||
|
@@ -578,7 +576,7 @@ static int seeed_voice_card_parse_aux_devs(struct device_node *node,
|
||||||
|
aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
|
||||||
|
if (!aux_node)
|
||||||
|
return -EINVAL;
|
||||||
|
- priv->snd_card.aux_dev[i].dlc.of_node = aux_node;
|
||||||
|
+ priv->snd_card.aux_dev[i].codec_of_node = aux_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->snd_card.num_aux_devs = n;
|
||||||
|
@@ -638,7 +636,7 @@ static int seeed_voice_card_parse_of(struct device_node *node,
|
||||||
|
goto card_parse_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = asoc_simple_parse_card_name(&priv->snd_card, PREFIX);
|
||||||
|
+ ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
|
||||||
|
if (ret < 0)
|
||||||
|
goto card_parse_end;
|
||||||
|
|
||||||
|
@@ -743,7 +741,7 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
struct seeed_dai_props *dai_props;
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
- int num, ret, i;
|
||||||
|
+ int num, ret;
|
||||||
|
|
||||||
|
/* Get the number of DAI links */
|
||||||
|
if (np && of_get_child_by_name(np, PREFIX "dai-link"))
|
||||||
|
@@ -761,25 +759,6 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
if (!dai_props || !dai_link)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Use snd_soc_dai_link_component instead of legacy style
|
||||||
|
- * It is codec only. but cpu/platform will be supported in the future.
|
||||||
|
- * see
|
||||||
|
- * soc-core.c :: snd_soc_init_multicodec()
|
||||||
|
- *
|
||||||
|
- * "platform" might be removed
|
||||||
|
- * see
|
||||||
|
- * simple-card-utils.c :: asoc_simple_canonicalize_platform()
|
||||||
|
- */
|
||||||
|
- for (i = 0; i < num; i++) {
|
||||||
|
- dai_link[i].cpus = &dai_props[i].cpus;
|
||||||
|
- dai_link[i].num_cpus = 1;
|
||||||
|
- dai_link[i].codecs = &dai_props[i].codecs;
|
||||||
|
- dai_link[i].num_codecs = 1;
|
||||||
|
- dai_link[i].platforms = &dai_props[i].platforms;
|
||||||
|
- dai_link[i].num_platforms = 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
priv->dai_props = dai_props;
|
||||||
|
priv->dai_link = dai_link;
|
||||||
|
|
||||||
|
@@ -798,9 +777,6 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct seeed_card_info *cinfo;
|
||||||
|
- struct snd_soc_dai_link_component *cpus;
|
||||||
|
- struct snd_soc_dai_link_component *codecs;
|
||||||
|
- struct snd_soc_dai_link_component *platform;
|
||||||
|
|
||||||
|
cinfo = dev->platform_data;
|
||||||
|
if (!cinfo) {
|
||||||
|
@@ -817,19 +793,13 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- cpus = dai_link->cpus;
|
||||||
|
- cpus->dai_name = cinfo->cpu_dai.name;
|
||||||
|
-
|
||||||
|
- codecs = dai_link->codecs;
|
||||||
|
- codecs->name = cinfo->codec;
|
||||||
|
- codecs->dai_name = cinfo->codec_dai.name;
|
||||||
|
-
|
||||||
|
- platform = dai_link->platforms;
|
||||||
|
- platform->name = cinfo->platform;
|
||||||
|
-
|
||||||
|
priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name;
|
||||||
|
dai_link->name = cinfo->name;
|
||||||
|
dai_link->stream_name = cinfo->name;
|
||||||
|
+ dai_link->platform_name = cinfo->platform;
|
||||||
|
+ dai_link->codec_name = cinfo->codec;
|
||||||
|
+ dai_link->cpu_dai_name = cinfo->cpu_dai.name;
|
||||||
|
+ dai_link->codec_dai_name = cinfo->codec_dai.name;
|
||||||
|
dai_link->dai_fmt = cinfo->daifmt;
|
||||||
|
dai_link->init = seeed_voice_card_dai_init;
|
||||||
|
memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
|
||||||
|
@@ -853,7 +823,7 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
- asoc_simple_clean_reference(&priv->snd_card);
|
||||||
|
+ asoc_simple_card_clean_reference(&priv->snd_card);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -865,7 +835,7 @@ static int seeed_voice_card_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
|
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
|
||||||
|
}
|
||||||
|
- return asoc_simple_clean_reference(card);
|
||||||
|
+ return asoc_simple_card_clean_reference(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id seeed_voice_of_match[] = {
|
||||||
|
diff --git a/sound-compatible-4.18.h b/sound-compatible-4.18.h
|
||||||
|
index 550b3a7..6c1a014 100644
|
||||||
|
--- a/sound-compatible-4.18.h
|
||||||
|
+++ b/sound-compatible-4.18.h
|
||||||
|
@@ -16,6 +16,10 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||||
|
+#ifndef __has_attribute
|
||||||
|
+# define __has_attribute(x) __GCC4_has_attribute_##x
|
||||||
|
+# define __GCC4_has_attribute___fallthrough__ 0
|
||||||
|
+#endif
|
||||||
|
#if __has_attribute(__fallthrough__)
|
||||||
|
# define fallthrough __attribute__((__fallthrough__))
|
||||||
|
#else
|
||||||
|
@@ -31,11 +35,7 @@
|
||||||
|
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
|
||||||
|
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
|
||||||
|
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
|
||||||
|
-#define snd_soc_read snd_soc_component_read
|
||||||
|
-#else
|
||||||
|
#define snd_soc_read snd_soc_component_read32
|
||||||
|
-#endif
|
||||||
|
#define snd_soc_register_codec devm_snd_soc_register_component
|
||||||
|
#define snd_soc_unregister_codec snd_soc_unregister_component
|
||||||
|
#define snd_soc_update_bits snd_soc_component_update_bits
|
||||||
|
diff --git a/wm8960.c b/wm8960.c
|
||||||
|
index 465c6dc..34d4dad 100644
|
||||||
|
--- a/wm8960.c
|
||||||
|
+++ b/wm8960.c
|
||||||
|
@@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
|
||||||
|
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
|
||||||
|
@@ -1236,12 +1236,11 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||||
|
static const struct snd_soc_dai_ops wm8960_dai_ops = {
|
||||||
|
.hw_params = wm8960_hw_params,
|
||||||
|
.hw_free = wm8960_hw_free,
|
||||||
|
- .mute_stream = wm8960_mute,
|
||||||
|
+ .digital_mute = wm8960_mute,
|
||||||
|
.set_fmt = wm8960_set_dai_fmt,
|
||||||
|
.set_clkdiv = wm8960_set_dai_clkdiv,
|
||||||
|
.set_pll = wm8960_set_dai_pll,
|
||||||
|
.set_sysclk = wm8960_set_dai_sysclk,
|
||||||
|
- .no_capture_mute = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver wm8960_dai = {
|
245
patches/back-to-v5.4.diff
Normal file
245
patches/back-to-v5.4.diff
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
diff --git a/ac101.c b/ac101.c
|
||||||
|
index be9b1d8..343f030 100644
|
||||||
|
--- a/ac101.c
|
||||||
|
+++ b/ac101.c
|
||||||
|
@@ -955,10 +955,10 @@ void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai
|
||||||
|
|
||||||
|
AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n",
|
||||||
|
snd_pcm_stream_str(substream),
|
||||||
|
- codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE],
|
||||||
|
- snd_soc_dai_active(codec_dai));
|
||||||
|
+ codec_dai->playback_active, codec_dai->capture_active,
|
||||||
|
+ codec_dai->active);
|
||||||
|
|
||||||
|
- if (!snd_soc_dai_active(codec_dai)) {
|
||||||
|
+ if (!codec_dai->active) {
|
||||||
|
ac10x->aif1_clken = 1;
|
||||||
|
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
|
||||||
|
} else {
|
||||||
|
@@ -1080,7 +1080,7 @@ int ac101_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
freq_out = _FREQ_24_576K;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
|
||||||
|
if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
|
||||||
|
- if (codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
|
||||||
|
+ if (codec_dai->capture_active && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
|
||||||
|
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS));
|
||||||
|
} else {
|
||||||
|
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
|
||||||
|
diff --git a/ac108.c b/ac108.c
|
||||||
|
index 4663df0..12ab27b 100644
|
||||||
|
--- a/ac108.c
|
||||||
|
+++ b/ac108.c
|
||||||
|
@@ -653,7 +653,7 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
|
||||||
|
|
||||||
|
dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
|
||||||
|
snd_pcm_stream_str(substream),
|
||||||
|
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
|
||||||
|
+ dai->playback_active, dai->capture_active);
|
||||||
|
|
||||||
|
if (ac10x->i2c101) {
|
||||||
|
ret = ac101_hw_params(substream, params, dai);
|
||||||
|
@@ -664,8 +664,8 @@ static int ac108_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK])
|
||||||
|
- || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream_active[SNDRV_PCM_STREAM_CAPTURE])) {
|
||||||
|
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->playback_active)
|
||||||
|
+ || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->capture_active)) {
|
||||||
|
/* not configure hw_param twice */
|
||||||
|
/* return 0; */
|
||||||
|
}
|
||||||
|
@@ -1124,7 +1124,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
|
||||||
|
+int ac108_aif_mute(struct snd_soc_dai *dai, int mute) {
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
@@ -1145,13 +1145,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
|
||||||
|
.hw_params = ac108_hw_params,
|
||||||
|
.prepare = ac108_prepare,
|
||||||
|
.trigger = ac108_trigger,
|
||||||
|
- .mute_stream = ac108_aif_mute,
|
||||||
|
+ .digital_mute = ac108_aif_mute,
|
||||||
|
|
||||||
|
/*DAI format configuration*/
|
||||||
|
.set_fmt = ac108_set_fmt,
|
||||||
|
|
||||||
|
// .hw_free = ac108_hw_free,
|
||||||
|
- .no_capture_mute = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver ac108_dai0 = {
|
||||||
|
diff --git a/seeed-voicecard.c b/seeed-voicecard.c
|
||||||
|
index c6d9048..43535aa 100644
|
||||||
|
--- a/seeed-voicecard.c
|
||||||
|
+++ b/seeed-voicecard.c
|
||||||
|
@@ -96,16 +96,16 @@ static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
|
||||||
|
if (ret)
|
||||||
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
- if (asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min) {
|
||||||
|
- priv->channels_playback_default = asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min;
|
||||||
|
+ if (rtd->cpu_dai->driver->playback.channels_min) {
|
||||||
|
+ priv->channels_playback_default = rtd->cpu_dai->driver->playback.channels_min;
|
||||||
|
}
|
||||||
|
- if (asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min) {
|
||||||
|
- priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min;
|
||||||
|
+ if (rtd->cpu_dai->driver->capture.channels_min) {
|
||||||
|
+ priv->channels_capture_default = rtd->cpu_dai->driver->capture.channels_min;
|
||||||
|
}
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_override;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_override;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_override;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_override;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_override;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_override;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_override;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_override;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -117,10 +117,10 @@ static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_default;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_default;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_default;
|
||||||
|
- asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_default;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_default;
|
||||||
|
+ rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_default;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_min = priv->channels_capture_default;
|
||||||
|
+ rtd->cpu_dai->driver->capture.channels_max = priv->channels_capture_default;
|
||||||
|
|
||||||
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
@@ -131,8 +131,8 @@ static int seeed_voice_card_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
- struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
- struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||||
|
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
|
||||||
|
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
@@ -196,7 +196,7 @@ static void work_cb_codec_clk(struct work_struct *work)
|
||||||
|
static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
- struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
+ struct snd_soc_dai *dai = rtd->codec_dai;
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
unsigned long flags;
|
||||||
|
@@ -205,7 +205,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
|
||||||
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
|
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
|
||||||
|
+ dai->playback_active, dai->capture_active);
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
@@ -227,7 +227,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
|
/* capture channel resync, if overrun */
|
||||||
|
- if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
+ if (dai->capture_active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -252,7 +247,7 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
|
||||||
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
|
- dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE], ret);
|
||||||
|
+ dai->playback_active, dai->capture_active, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -337,8 +337,8 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai,
|
||||||
|
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
- struct snd_soc_dai *codec = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
- struct snd_soc_dai *cpu = asoc_rtd_to_cpu(rtd, 0);
|
||||||
|
+ struct snd_soc_dai *codec = rtd->codec_dai;
|
||||||
|
+ struct snd_soc_dai *cpu = rtd->cpu_dai;
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
int ret;
|
||||||
|
@@ -636,11 +636,11 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
* Use snd_soc_dai_link_component instead of legacy style
|
||||||
|
* It is codec only. but cpu/platform will be supported in the future.
|
||||||
|
* see
|
||||||
|
- * soc-core.c :: snd_soc_init_multicodec()
|
||||||
|
+ * soc-core.c :: snd_soc_init_multicodec()
|
||||||
|
*
|
||||||
|
* "platform" might be removed
|
||||||
|
* see
|
||||||
|
- * simple-card-utils.c :: asoc_simple_canonicalize_platform()
|
||||||
|
+ * simple-card-utils.c :: asoc_simple_canonicalize_platform()
|
||||||
|
*/
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
dai_link[i].cpus = &dai_props[i].cpus;
|
||||||
|
diff --git a/sound-compatible-4.18.h b/sound-compatible-4.18.h
|
||||||
|
index 080325b..eefa7de 100644
|
||||||
|
--- a/sound-compatible-4.18.h
|
||||||
|
+++ b/sound-compatible-4.18.h
|
||||||
|
@@ -16,6 +16,10 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||||
|
+#ifndef __has_attribute
|
||||||
|
+# define __has_attribute(x) __GCC4_has_attribute_##x
|
||||||
|
+# define __GCC4_has_attribute___fallthrough__ 0
|
||||||
|
+#endif
|
||||||
|
#if __has_attribute(__fallthrough__)
|
||||||
|
# define fallthrough __attribute__((__fallthrough__))
|
||||||
|
#else
|
||||||
|
@@ -31,11 +35,7 @@
|
||||||
|
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
|
||||||
|
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
|
||||||
|
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
|
||||||
|
-#define snd_soc_read snd_soc_component_read
|
||||||
|
-#else
|
||||||
|
#define snd_soc_read snd_soc_component_read32
|
||||||
|
-#endif
|
||||||
|
#define snd_soc_register_codec devm_snd_soc_register_component
|
||||||
|
#define snd_soc_unregister_codec snd_soc_unregister_component
|
||||||
|
#define snd_soc_update_bits snd_soc_component_update_bits
|
||||||
|
diff --git a/wm8960.c b/wm8960.c
|
||||||
|
index 465c6dc..34d4dad 100644
|
||||||
|
--- a/wm8960.c
|
||||||
|
+++ b/wm8960.c
|
||||||
|
@@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
|
||||||
|
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
|
||||||
|
@@ -1236,12 +1236,11 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||||
|
static const struct snd_soc_dai_ops wm8960_dai_ops = {
|
||||||
|
.hw_params = wm8960_hw_params,
|
||||||
|
.hw_free = wm8960_hw_free,
|
||||||
|
- .mute_stream = wm8960_mute,
|
||||||
|
+ .digital_mute = wm8960_mute,
|
||||||
|
.set_fmt = wm8960_set_dai_fmt,
|
||||||
|
.set_clkdiv = wm8960_set_dai_clkdiv,
|
||||||
|
.set_pll = wm8960_set_dai_pll,
|
||||||
|
.set_sysclk = wm8960_set_dai_sysclk,
|
||||||
|
- .no_capture_mute = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver wm8960_dai = {
|
71
patches/back-to-v5.8.diff
Normal file
71
patches/back-to-v5.8.diff
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
diff --git a/ac108.c b/ac108.c
|
||||||
|
index 4663df0..67edeae 100644
|
||||||
|
--- a/ac108.c
|
||||||
|
+++ b/ac108.c
|
||||||
|
@@ -1124,7 +1124,7 @@ void ac108_aif_shutdown(struct snd_pcm_substream *substream,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int direction) {
|
||||||
|
+int ac108_aif_mute(struct snd_soc_dai *dai, int mute) {
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
@@ -1145,13 +1145,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
|
||||||
|
.hw_params = ac108_hw_params,
|
||||||
|
.prepare = ac108_prepare,
|
||||||
|
.trigger = ac108_trigger,
|
||||||
|
- .mute_stream = ac108_aif_mute,
|
||||||
|
+ .digital_mute = ac108_aif_mute,
|
||||||
|
|
||||||
|
/*DAI format configuration*/
|
||||||
|
.set_fmt = ac108_set_fmt,
|
||||||
|
|
||||||
|
// .hw_free = ac108_hw_free,
|
||||||
|
- .no_capture_mute = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver ac108_dai0 = {
|
||||||
|
diff --git a/sound-compatible-4.18.h b/sound-compatible-4.18.h
|
||||||
|
index 080325b..faed848 100644
|
||||||
|
--- a/sound-compatible-4.18.h
|
||||||
|
+++ b/sound-compatible-4.18.h
|
||||||
|
@@ -31,11 +31,7 @@
|
||||||
|
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
|
||||||
|
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
|
||||||
|
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
|
||||||
|
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
|
||||||
|
-#define snd_soc_read snd_soc_component_read
|
||||||
|
-#else
|
||||||
|
#define snd_soc_read snd_soc_component_read32
|
||||||
|
-#endif
|
||||||
|
#define snd_soc_register_codec devm_snd_soc_register_component
|
||||||
|
#define snd_soc_unregister_codec snd_soc_unregister_component
|
||||||
|
#define snd_soc_update_bits snd_soc_component_update_bits
|
||||||
|
diff --git a/wm8960.c b/wm8960.c
|
||||||
|
index 465c6dc..34d4dad 100644
|
||||||
|
--- a/wm8960.c
|
||||||
|
+++ b/wm8960.c
|
||||||
|
@@ -796,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
|
||||||
|
+static int wm8960_mute(struct snd_soc_dai *dai, int mute)
|
||||||
|
{
|
||||||
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
|
||||||
|
@@ -1236,12 +1236,11 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||||
|
static const struct snd_soc_dai_ops wm8960_dai_ops = {
|
||||||
|
.hw_params = wm8960_hw_params,
|
||||||
|
.hw_free = wm8960_hw_free,
|
||||||
|
- .mute_stream = wm8960_mute,
|
||||||
|
+ .digital_mute = wm8960_mute,
|
||||||
|
.set_fmt = wm8960_set_dai_fmt,
|
||||||
|
.set_clkdiv = wm8960_set_dai_clkdiv,
|
||||||
|
.set_pll = wm8960_set_dai_pll,
|
||||||
|
.set_sysclk = wm8960_set_dai_sysclk,
|
||||||
|
- .no_capture_mute = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver wm8960_dai = {
|
8
pulseaudio/91-seeedvoicecard.rules
Normal file
8
pulseaudio/91-seeedvoicecard.rules
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
SUBSYSTEM!="sound", GOTO="seeedvoicecard_end"
|
||||||
|
ACTION!="change", GOTO="seeedvoicecard_end"
|
||||||
|
KERNEL!="card*", GOTO="seeedvoicecard_end"
|
||||||
|
|
||||||
|
ATTR{id}=="seeed4micvoicec",ENV{PULSE_PROFILE_SET}="seeed-voicecard-4mic.conf"
|
||||||
|
ATTR{id}=="seeed8micvoicec",ENV{PULSE_PROFILE_SET}="seeed-voicecard-8mic.conf"
|
||||||
|
|
||||||
|
LABEL="seeedvoicecard_end"
|
251
pulseaudio/README.md
Normal file
251
pulseaudio/README.md
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
# PulseAudio Configuration for seeed-voicecard
|
||||||
|
|
||||||
|
Follow this guide if you want to use your seeed-voicecard as a default source/sink of pulseaudio.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. Download PulseAudio
|
||||||
|
```
|
||||||
|
sudo apt install -y pulseaudio
|
||||||
|
```
|
||||||
|
|
||||||
|
2. PulseAudio Profiles
|
||||||
|
```
|
||||||
|
cd seeed-voicecard/pulseaudio
|
||||||
|
sudo cp pulse_config_4mic/seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voicecard-4mic.conf
|
||||||
|
sudo cp pulse_config_6mic/seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voicecard-8mic.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Add `udev` Rules
|
||||||
|
|
||||||
|
During the system start, when the card "seeed4micvoicec" is detected, the PULSE_PROFILE_SET variable will be set in the udev database, and PulseAudio will be forced to use `seeed-voicecard-4mic.conf`. Similarly, if the card "seeed8micvoicec" is detected, PulseAudio will be forced to use `seeed-voicecard-8mic.conf`.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo cp 91-seeedvoicecard.rules /etc/udev/rules.d/91-seeedvoicecard.rules
|
||||||
|
```
|
||||||
|
|
||||||
|
### ReSpeaker 4 Mic Array
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1. Download pulseaudio
|
||||||
|
```
|
||||||
|
sudo apt install pulseaudio
|
||||||
|
```
|
||||||
|
|
||||||
|
2. First, you need to write [a profile for pulse](https://www.freedesktop.org/wiki/Software/PulseAudio/Backends/ALSA/Profiles/)
|
||||||
|
```
|
||||||
|
cd seeed-voicecard
|
||||||
|
cd pulseaudio
|
||||||
|
cd pulse_config_4mic
|
||||||
|
sudo cp seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Edit `udev rules`
|
||||||
|
|
||||||
|
During the system start, when the card "seeed4micvoicec" is detected, the PULSE_PROFILE_SET variable will be set in the udev database, and PulseAudio will be forced to use `seeed-voicecard.conf`.
|
||||||
|
|
||||||
|
```
|
||||||
|
# have a look at /lib/udev/rules.d/90-pulseaudio.rules
|
||||||
|
sudo vim /lib/udev/rules.d/90-pulseaudio.rules
|
||||||
|
# add the following lines at about line 87(behind the setting for some laptops and before the line GOTO="pulseaudio_end")
|
||||||
|
# Seeed Voicecard
|
||||||
|
ATTR{id}=="seeed4micvoicec",ATTR{number}=="1",ENV{PULSE_PROFILE_SET}="seeed-voicecard.conf"
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
The value of `ATTR{number}` can be found with:
|
||||||
|
|
||||||
|
```
|
||||||
|
udevadm info -a -p /sys/class/sound/card0/
|
||||||
|
# or udevadm info -a -p /sys/class/sound/card1/
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, in Raspberry Pi, we can find `ATTR{id}=="seeed4micvoicec"` and `ATTR{number}=="1"` with command `udevadm info -a -p /sys/class/sound/card1/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
pi@raspberrypi:~ $ udevadm info -a -p /sys/class/sound/card1/
|
||||||
|
|
||||||
|
Udevadm info starts with the device specified by the devpath and then
|
||||||
|
walks up the chain of parent devices. It prints for every device
|
||||||
|
found, all possible attributes in the udev rules key format.
|
||||||
|
A rule to match, can be composed by the attributes of the device
|
||||||
|
and the attributes from one single parent device.
|
||||||
|
|
||||||
|
looking at device '/devices/platform/soc/soc:sound/sound/card1':
|
||||||
|
KERNEL=="card1"
|
||||||
|
SUBSYSTEM=="sound"
|
||||||
|
DRIVER==""
|
||||||
|
ATTR{id}=="seeed4micvoicec"
|
||||||
|
ATTR{number}=="1"
|
||||||
|
|
||||||
|
looking at parent device '/devices/platform/soc/soc:sound':
|
||||||
|
KERNELS=="soc:sound"
|
||||||
|
SUBSYSTEMS=="platform"
|
||||||
|
DRIVERS=="seeed-voicecard"
|
||||||
|
ATTRS{driver_override}=="(null)"
|
||||||
|
|
||||||
|
looking at parent device '/devices/platform/soc':
|
||||||
|
KERNELS=="soc"
|
||||||
|
SUBSYSTEMS=="platform"
|
||||||
|
DRIVERS==""
|
||||||
|
ATTRS{driver_override}=="(null)"
|
||||||
|
|
||||||
|
looking at parent device '/devices/platform':
|
||||||
|
KERNELS=="platform"
|
||||||
|
SUBSYSTEMS==""
|
||||||
|
DRIVERS==""
|
||||||
|
``` -->
|
||||||
|
|
||||||
|
1. config `default.pa` and `daemon.conf`
|
||||||
|
```
|
||||||
|
sudo cp pulse_config_4mic/default.pa /etc/pulse/
|
||||||
|
sudo cp pulse_config_4mic/daemon.conf /etc/pulse/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. reboot raspberry pi and check
|
||||||
|
```
|
||||||
|
sudo reboot
|
||||||
|
pulseaudio --start # start pulse at first
|
||||||
|
pactl info # check the setting
|
||||||
|
|
||||||
|
Server String: /run/user/1000/pulse/native
|
||||||
|
Library Protocol Version: 32
|
||||||
|
Server Protocol Version: 32
|
||||||
|
Is Local: yes
|
||||||
|
Client Index: 18
|
||||||
|
Tile Size: 65496
|
||||||
|
User Name: pi
|
||||||
|
Host Name: raspberrypi
|
||||||
|
Server Name: pulseaudio
|
||||||
|
Server Version: 10.0
|
||||||
|
Default Sample Specification: s16le 4ch 96000Hz
|
||||||
|
Default Channel Map: front-left,front-center,front-right,rear-center
|
||||||
|
Default Sink: alsa_output.platform-soc_audio.analog-stereo
|
||||||
|
Default Source: alsa_input.platform-soc_sound.seeed-source
|
||||||
|
Cookie: 3b12:70b3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6-Mics Circular Array Kit and 4-Mics Linear Array
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1. Download pulseaudio
|
||||||
|
```
|
||||||
|
sudo apt install pulseaudio
|
||||||
|
```
|
||||||
|
|
||||||
|
2. First, you need to write [a profile for pulse](https://www.freedesktop.org/wiki/Software/PulseAudio/Backends/ALSA/Profiles/)
|
||||||
|
```
|
||||||
|
cd seeed-voicecard
|
||||||
|
cd pulseaudio
|
||||||
|
cd pulse_config_6mic
|
||||||
|
sudo cp seeed-voicecard.conf /usr/share/pulseaudio/alsa-mixer/profile-sets/
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Edit `udev rules`
|
||||||
|
|
||||||
|
During the system start, when the card "seeed8micvoicec" is detected, the PULSE_PROFILE_SET variable will be set in the udev database, and PulseAudio will be forced to use `seeed-voicecard.conf`.
|
||||||
|
|
||||||
|
```
|
||||||
|
# have a look at /lib/udev/rules.d/90-pulseaudio.rules
|
||||||
|
sudo vim /lib/udev/rules.d/90-pulseaudio.rules
|
||||||
|
# add the following lines at about line 87(behind the setting for some laptops and before the line GOTO="pulseaudio_end")
|
||||||
|
# Seeed Voicecard
|
||||||
|
ATTR{id}=="seeed8micvoicec",ATTR{number}=="1",ENV{PULSE_PROFILE_SET}="seeed-voicecard.conf"
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
The value of `ATTR{number}` can be found with:
|
||||||
|
|
||||||
|
```
|
||||||
|
udevadm info -a -p /sys/class/sound/card0/
|
||||||
|
# or udevadm info -a -p /sys/class/sound/card1/
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, in Raspberry Pi, we can find `ATTR{id}=="seeed8micvoicec"` and `ATTR{number}=="1"` with command `udevadm info -a -p /sys/class/sound/card1/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
pi@raspberrypi:~ $ udevadm info -a -p /sys/class/sound/card1/
|
||||||
|
|
||||||
|
Udevadm info starts with the device specified by the devpath and then
|
||||||
|
walks up the chain of parent devices. It prints for every device
|
||||||
|
found, all possible attributes in the udev rules key format.
|
||||||
|
A rule to match, can be composed by the attributes of the device
|
||||||
|
and the attributes from one single parent device.
|
||||||
|
|
||||||
|
looking at device '/devices/platform/soc/soc:sound/sound/card1':
|
||||||
|
KERNEL=="card1"
|
||||||
|
SUBSYSTEM=="sound"
|
||||||
|
DRIVER==""
|
||||||
|
ATTR{id}=="seeed8micvoicec"
|
||||||
|
ATTR{number}=="1"
|
||||||
|
|
||||||
|
looking at parent device '/devices/platform/soc/soc:sound':
|
||||||
|
KERNELS=="soc:sound"
|
||||||
|
SUBSYSTEMS=="platform"
|
||||||
|
DRIVERS=="seeed-voicecard"
|
||||||
|
ATTRS{driver_override}=="(null)"
|
||||||
|
|
||||||
|
looking at parent device '/devices/platform/soc':
|
||||||
|
KERNELS=="soc"
|
||||||
|
SUBSYSTEMS=="platform"
|
||||||
|
DRIVERS==""
|
||||||
|
ATTRS{driver_override}=="(null)"
|
||||||
|
|
||||||
|
looking at parent device '/devices/platform':
|
||||||
|
KERNELS=="platform"
|
||||||
|
SUBSYSTEMS==""
|
||||||
|
DRIVERS==""
|
||||||
|
``` -->
|
||||||
|
|
||||||
|
1. config `default.pa` and `daemon.conf`
|
||||||
|
```
|
||||||
|
sudo cp pulse_config_6mic/default.pa /etc/pulse/
|
||||||
|
sudo cp pulse_config_6mic/daemon.conf /etc/pulse/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. reboot raspberry pi and check
|
||||||
|
```
|
||||||
|
sudo reboot
|
||||||
|
pulseaudio --start # start pulse at first
|
||||||
|
pactl info # check the setting
|
||||||
|
|
||||||
|
# The output should be like this
|
||||||
|
# You could see the default sink is seeed-2ch and default source is seeed-8ch
|
||||||
|
pi@raspberrypi:~ $ pactl info
|
||||||
|
Server String: /run/user/1000/pulse/native
|
||||||
|
Library Protocol Version: 32
|
||||||
|
Server Protocol Version: 32
|
||||||
|
Is Local: yes
|
||||||
|
Client Index: 6
|
||||||
|
Tile Size: 65496
|
||||||
|
User Name: pi
|
||||||
|
Host Name: raspberrypi
|
||||||
|
Server Name: pulseaudio
|
||||||
|
Server Version: 10.0
|
||||||
|
Default Sample Specification: s32le 8ch 96000Hz
|
||||||
|
Default Channel Map: front-left,front-left-of-center,front-center,front-right,front-right-of-center,rear-center,aux0,aux1
|
||||||
|
Default Sink: alsa_output.platform-soc_sound.seeed-2ch
|
||||||
|
Default Source: alsa_input.platform-soc_sound.seeed-8ch
|
||||||
|
Cookie: 3523:e5af
|
||||||
|
```
|
||||||
|
|
||||||
|
### FAQ
|
||||||
|
|
||||||
|
1. Default Sink/Source not right
|
||||||
|
|
||||||
|
Make sure there is no any other daemon or using the audio device. Then check profile and udev rules.
|
||||||
|
|
||||||
|
`pacmd list-sinks` and `pacmd list-sources` can be used to show the avaiable sinks/sources, after pulseaudio is started.
|
||||||
|
|
||||||
|
2. Can't start PulseAudio
|
||||||
|
|
||||||
|
Check `default.pa` and `daemon.conf`
|
||||||
|
|
||||||
|
3. How to get PulseAudio started automatically
|
||||||
|
|
||||||
|
Normally the PulseAudio server is started automatically. If you want to disable it, you can set `autospawn = no` in `~/.config/pulse/client.conf` or `/etc/pulse/client.conf`.
|
||||||
|
[Click this for more details](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Running/).
|
||||||
|
|
||||||
|
4. Why the default sample rate is 96000? What if my audio's sample rate is not the same as the default?
|
||||||
|
|
||||||
|
For the other sample rate audio, PulseAudio will resample it into 96K, which means that if your audio's sample rate is lower than 96K, it will get smoothing.
|
87
pulseaudio/pulse_config_4mic/daemon.conf
Normal file
87
pulseaudio/pulse_config_4mic/daemon.conf
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# This file is part of PulseAudio.
|
||||||
|
#
|
||||||
|
# PulseAudio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PulseAudio is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
|
||||||
|
## more information. Default values are commented out. Use either ; or # for
|
||||||
|
## commenting.
|
||||||
|
|
||||||
|
; daemonize = no
|
||||||
|
; fail = yes
|
||||||
|
; allow-module-loading = yes
|
||||||
|
; allow-exit = yes
|
||||||
|
; use-pid-file = yes
|
||||||
|
; system-instance = no
|
||||||
|
; local-server-type = user
|
||||||
|
; enable-shm = yes
|
||||||
|
; enable-memfd = yes
|
||||||
|
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
|
||||||
|
; lock-memory = no
|
||||||
|
; cpu-limit = no
|
||||||
|
|
||||||
|
; high-priority = yes
|
||||||
|
; nice-level = -11
|
||||||
|
|
||||||
|
; realtime-scheduling = yes
|
||||||
|
; realtime-priority = 5
|
||||||
|
|
||||||
|
; exit-idle-time = 20
|
||||||
|
; scache-idle-time = 20
|
||||||
|
|
||||||
|
; dl-search-path = (depends on architecture)
|
||||||
|
|
||||||
|
; load-default-script-file = yes
|
||||||
|
; default-script-file = /etc/pulse/default.pa
|
||||||
|
|
||||||
|
; log-target = auto
|
||||||
|
; log-level = notice
|
||||||
|
; log-meta = no
|
||||||
|
; log-time = no
|
||||||
|
; log-backtrace = 0
|
||||||
|
|
||||||
|
; resample-method = speex-float-1
|
||||||
|
; enable-remixing = yes
|
||||||
|
; enable-lfe-remixing = no
|
||||||
|
; lfe-crossover-freq = 0
|
||||||
|
|
||||||
|
; flat-volumes = yes
|
||||||
|
|
||||||
|
; rlimit-fsize = -1
|
||||||
|
; rlimit-data = -1
|
||||||
|
; rlimit-stack = -1
|
||||||
|
; rlimit-core = -1
|
||||||
|
; rlimit-as = -1
|
||||||
|
; rlimit-rss = -1
|
||||||
|
; rlimit-nproc = -1
|
||||||
|
; rlimit-nofile = 256
|
||||||
|
; rlimit-memlock = -1
|
||||||
|
; rlimit-locks = -1
|
||||||
|
; rlimit-sigpending = -1
|
||||||
|
; rlimit-msgqueue = -1
|
||||||
|
; rlimit-nice = 31
|
||||||
|
; rlimit-rtprio = 9
|
||||||
|
; rlimit-rttime = 200000
|
||||||
|
|
||||||
|
default-sample-format = s16le
|
||||||
|
default-sample-rate = 96000
|
||||||
|
; alternate-sample-rate = 48000
|
||||||
|
default-sample-channels = 4
|
||||||
|
; default-channel-map = front-left,front-right
|
||||||
|
|
||||||
|
; default-fragments = 4
|
||||||
|
; default-fragment-size-msec = 25
|
||||||
|
|
||||||
|
; enable-deferred-volume = yes
|
||||||
|
; deferred-volume-safety-margin-usec = 8000
|
||||||
|
; deferred-volume-extra-delay-usec = 0
|
144
pulseaudio/pulse_config_4mic/default.pa
Normal file
144
pulseaudio/pulse_config_4mic/default.pa
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
#!/usr/bin/pulseaudio -nF
|
||||||
|
#
|
||||||
|
# This file is part of PulseAudio.
|
||||||
|
#
|
||||||
|
# PulseAudio is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PulseAudio is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# This startup script is used only if PulseAudio is started per-user
|
||||||
|
# (i.e. not in system mode)
|
||||||
|
|
||||||
|
.fail
|
||||||
|
|
||||||
|
### Automatically restore the volume of streams and devices
|
||||||
|
load-module module-device-restore
|
||||||
|
load-module module-stream-restore
|
||||||
|
load-module module-card-restore
|
||||||
|
|
||||||
|
### Automatically augment property information from .desktop files
|
||||||
|
### stored in /usr/share/application
|
||||||
|
load-module module-augment-properties
|
||||||
|
|
||||||
|
### Should be after module-*-restore but before module-*-detect
|
||||||
|
load-module module-switch-on-port-available
|
||||||
|
|
||||||
|
### Load audio drivers statically
|
||||||
|
### (it's probably better to not load these drivers manually, but instead
|
||||||
|
### use module-udev-detect -- see below -- for doing this automatically)
|
||||||
|
#load-module module-alsa-sink device="hw:1,0" channels=8 rate=48000 format=s32le
|
||||||
|
#load-module module-alsa-source device="hw:1,0" channels=8 rate=48000 format=s32le
|
||||||
|
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||||
|
#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
|
||||||
|
#load-module module-null-sink
|
||||||
|
#load-module module-pipe-sink
|
||||||
|
|
||||||
|
### Automatically load driver modules depending on the hardware available
|
||||||
|
.ifexists module-udev-detect.so
|
||||||
|
load-module module-udev-detect
|
||||||
|
#channels=8 rate=48000 format=s32le
|
||||||
|
.else
|
||||||
|
### Use the static hardware detection module (for systems that lack udev support)
|
||||||
|
load-module module-detect
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Automatically connect sink and source if JACK server is present
|
||||||
|
.ifexists module-jackdbus-detect.so
|
||||||
|
.nofail
|
||||||
|
load-module module-jackdbus-detect channels=2
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Automatically load driver modules for Bluetooth hardware
|
||||||
|
.ifexists module-bluetooth-policy.so
|
||||||
|
load-module module-bluetooth-policy
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.ifexists module-bluetooth-discover.so
|
||||||
|
load-module module-bluetooth-discover
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Load several protocols
|
||||||
|
.ifexists module-esound-protocol-unix.so
|
||||||
|
load-module module-esound-protocol-unix
|
||||||
|
.endif
|
||||||
|
load-module module-native-protocol-unix
|
||||||
|
|
||||||
|
### Network access (may be configured with paprefs, so leave this commented
|
||||||
|
### here if you plan to use paprefs)
|
||||||
|
#load-module module-esound-protocol-tcp
|
||||||
|
#load-module module-native-protocol-tcp
|
||||||
|
#load-module module-zeroconf-publish
|
||||||
|
|
||||||
|
### Load the RTP receiver module (also configured via paprefs, see above)
|
||||||
|
#load-module module-rtp-recv
|
||||||
|
|
||||||
|
### Load the RTP sender module (also configured via paprefs, see above)
|
||||||
|
#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
|
||||||
|
#load-module module-rtp-send source=rtp.monitor
|
||||||
|
|
||||||
|
### Load additional modules from GConf settings. This can be configured with the paprefs tool.
|
||||||
|
### Please keep in mind that the modules configured by paprefs might conflict with manually
|
||||||
|
### loaded modules.
|
||||||
|
.ifexists module-gconf.so
|
||||||
|
.nofail
|
||||||
|
load-module module-gconf
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Automatically restore the default sink/source when changed by the user
|
||||||
|
### during runtime
|
||||||
|
### NOTE: This should be loaded as early as possible so that subsequent modules
|
||||||
|
### that look up the default sink/source get the right value
|
||||||
|
load-module module-default-device-restore
|
||||||
|
|
||||||
|
### Automatically move streams to the default sink if the sink they are
|
||||||
|
### connected to dies, similar for sources
|
||||||
|
load-module module-rescue-streams
|
||||||
|
|
||||||
|
### Make sure we always have a sink around, even if it is a null sink.
|
||||||
|
load-module module-always-sink
|
||||||
|
|
||||||
|
### Honour intended role device property
|
||||||
|
load-module module-intended-roles
|
||||||
|
|
||||||
|
### Automatically suspend sinks/sources that become idle for too long
|
||||||
|
load-module module-suspend-on-idle
|
||||||
|
|
||||||
|
### If autoexit on idle is enabled we want to make sure we only quit
|
||||||
|
### when no local session needs us anymore.
|
||||||
|
.ifexists module-console-kit.so
|
||||||
|
load-module module-console-kit
|
||||||
|
.endif
|
||||||
|
.ifexists module-systemd-login.so
|
||||||
|
load-module module-systemd-login
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Enable positioned event sounds
|
||||||
|
load-module module-position-event-sounds
|
||||||
|
|
||||||
|
### Cork music/video streams when a phone stream is active
|
||||||
|
load-module module-role-cork
|
||||||
|
|
||||||
|
### Modules to allow autoloading of filters (such as echo cancellation)
|
||||||
|
### on demand. module-filter-heuristics tries to determine what filters
|
||||||
|
### make sense, and module-filter-apply does the heavy-lifting of
|
||||||
|
### loading modules and rerouting streams.
|
||||||
|
load-module module-filter-heuristics
|
||||||
|
load-module module-filter-apply
|
||||||
|
|
||||||
|
### Make some devices default
|
||||||
|
#set-default-sink output
|
||||||
|
#set-default-source input
|
||||||
|
set-default-source alsa_input.platform-soc_sound.seeed-source
|
||||||
|
set-default-sink alsa_output.platform-soc_sound.seeed-sink
|
||||||
|
|
17
pulseaudio/pulse_config_4mic/seeed-voicecard.conf
Normal file
17
pulseaudio/pulse_config_4mic/seeed-voicecard.conf
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voicecard.conf
|
||||||
|
|
||||||
|
[General]
|
||||||
|
auto-profiles = no
|
||||||
|
[Mapping seeed-source]
|
||||||
|
device-strings = hw:%f
|
||||||
|
channel-map = front-left,front-right,rear-left,rear-right
|
||||||
|
exact-channels = false
|
||||||
|
fallback = yes
|
||||||
|
paths-input = seeed-source
|
||||||
|
priority = 3
|
||||||
|
direction = input
|
||||||
|
|
||||||
|
[Profile input:seeed-source]
|
||||||
|
input-mappings = seeed-source
|
||||||
|
priority = 5
|
||||||
|
skip-probe = yes
|
87
pulseaudio/pulse_config_6mic/daemon.conf
Normal file
87
pulseaudio/pulse_config_6mic/daemon.conf
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# This file is part of PulseAudio.
|
||||||
|
#
|
||||||
|
# PulseAudio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PulseAudio is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
|
||||||
|
## more information. Default values are commented out. Use either ; or # for
|
||||||
|
## commenting.
|
||||||
|
|
||||||
|
; daemonize = no
|
||||||
|
; fail = yes
|
||||||
|
; allow-module-loading = yes
|
||||||
|
; allow-exit = yes
|
||||||
|
; use-pid-file = yes
|
||||||
|
; system-instance = no
|
||||||
|
; local-server-type = user
|
||||||
|
; enable-shm = yes
|
||||||
|
; enable-memfd = yes
|
||||||
|
; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
|
||||||
|
; lock-memory = no
|
||||||
|
; cpu-limit = no
|
||||||
|
|
||||||
|
; high-priority = yes
|
||||||
|
; nice-level = -11
|
||||||
|
|
||||||
|
; realtime-scheduling = yes
|
||||||
|
; realtime-priority = 5
|
||||||
|
|
||||||
|
; exit-idle-time = 20
|
||||||
|
; scache-idle-time = 20
|
||||||
|
|
||||||
|
; dl-search-path = (depends on architecture)
|
||||||
|
|
||||||
|
; load-default-script-file = yes
|
||||||
|
; default-script-file = /etc/pulse/default.pa
|
||||||
|
|
||||||
|
; log-target = auto
|
||||||
|
; log-level = notice
|
||||||
|
; log-meta = no
|
||||||
|
; log-time = no
|
||||||
|
; log-backtrace = 0
|
||||||
|
|
||||||
|
; resample-method = speex-float-1
|
||||||
|
; enable-remixing = yes
|
||||||
|
; enable-lfe-remixing = no
|
||||||
|
; lfe-crossover-freq = 0
|
||||||
|
|
||||||
|
; flat-volumes = yes
|
||||||
|
|
||||||
|
; rlimit-fsize = -1
|
||||||
|
; rlimit-data = -1
|
||||||
|
; rlimit-stack = -1
|
||||||
|
; rlimit-core = -1
|
||||||
|
; rlimit-as = -1
|
||||||
|
; rlimit-rss = -1
|
||||||
|
; rlimit-nproc = -1
|
||||||
|
; rlimit-nofile = 256
|
||||||
|
; rlimit-memlock = -1
|
||||||
|
; rlimit-locks = -1
|
||||||
|
; rlimit-sigpending = -1
|
||||||
|
; rlimit-msgqueue = -1
|
||||||
|
; rlimit-nice = 31
|
||||||
|
; rlimit-rtprio = 9
|
||||||
|
; rlimit-rttime = 200000
|
||||||
|
|
||||||
|
default-sample-format = s32le
|
||||||
|
default-sample-rate = 96000
|
||||||
|
; alternate-sample-rate = 48000
|
||||||
|
default-sample-channels = 8
|
||||||
|
; default-channel-map = front-left,front-right
|
||||||
|
|
||||||
|
; default-fragments = 4
|
||||||
|
; default-fragment-size-msec = 25
|
||||||
|
|
||||||
|
; enable-deferred-volume = yes
|
||||||
|
; deferred-volume-safety-margin-usec = 8000
|
||||||
|
; deferred-volume-extra-delay-usec = 0
|
143
pulseaudio/pulse_config_6mic/default.pa
Normal file
143
pulseaudio/pulse_config_6mic/default.pa
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#!/usr/bin/pulseaudio -nF
|
||||||
|
#
|
||||||
|
# This file is part of PulseAudio.
|
||||||
|
#
|
||||||
|
# PulseAudio is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PulseAudio is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# This startup script is used only if PulseAudio is started per-user
|
||||||
|
# (i.e. not in system mode)
|
||||||
|
|
||||||
|
.fail
|
||||||
|
|
||||||
|
### Automatically restore the volume of streams and devices
|
||||||
|
load-module module-device-restore
|
||||||
|
load-module module-stream-restore
|
||||||
|
load-module module-card-restore
|
||||||
|
|
||||||
|
### Automatically augment property information from .desktop files
|
||||||
|
### stored in /usr/share/application
|
||||||
|
load-module module-augment-properties
|
||||||
|
|
||||||
|
### Should be after module-*-restore but before module-*-detect
|
||||||
|
load-module module-switch-on-port-available
|
||||||
|
|
||||||
|
### Load audio drivers statically
|
||||||
|
### (it's probably better to not load these drivers manually, but instead
|
||||||
|
### use module-udev-detect -- see below -- for doing this automatically)
|
||||||
|
#load-module module-alsa-sink device="hw:1,0" channels=8 rate=48000 format=s32le
|
||||||
|
#load-module module-alsa-source device="hw:1,0" channels=8 rate=48000 format=s32le
|
||||||
|
#load-module module-oss device="/dev/dsp" sink_name=output source_name=input
|
||||||
|
#load-module module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
|
||||||
|
#load-module module-null-sink
|
||||||
|
#load-module module-pipe-sink
|
||||||
|
|
||||||
|
### Automatically load driver modules depending on the hardware available
|
||||||
|
.ifexists module-udev-detect.so
|
||||||
|
load-module module-udev-detect
|
||||||
|
#channels=8 rate=48000 format=s32le
|
||||||
|
.else
|
||||||
|
### Use the static hardware detection module (for systems that lack udev support)
|
||||||
|
load-module module-detect
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Automatically connect sink and source if JACK server is present
|
||||||
|
.ifexists module-jackdbus-detect.so
|
||||||
|
.nofail
|
||||||
|
load-module module-jackdbus-detect channels=2
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Automatically load driver modules for Bluetooth hardware
|
||||||
|
.ifexists module-bluetooth-policy.so
|
||||||
|
load-module module-bluetooth-policy
|
||||||
|
.endif
|
||||||
|
|
||||||
|
.ifexists module-bluetooth-discover.so
|
||||||
|
load-module module-bluetooth-discover
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Load several protocols
|
||||||
|
.ifexists module-esound-protocol-unix.so
|
||||||
|
load-module module-esound-protocol-unix
|
||||||
|
.endif
|
||||||
|
load-module module-native-protocol-unix
|
||||||
|
|
||||||
|
### Network access (may be configured with paprefs, so leave this commented
|
||||||
|
### here if you plan to use paprefs)
|
||||||
|
#load-module module-esound-protocol-tcp
|
||||||
|
#load-module module-native-protocol-tcp
|
||||||
|
#load-module module-zeroconf-publish
|
||||||
|
|
||||||
|
### Load the RTP receiver module (also configured via paprefs, see above)
|
||||||
|
#load-module module-rtp-recv
|
||||||
|
|
||||||
|
### Load the RTP sender module (also configured via paprefs, see above)
|
||||||
|
#load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
|
||||||
|
#load-module module-rtp-send source=rtp.monitor
|
||||||
|
|
||||||
|
### Load additional modules from GConf settings. This can be configured with the paprefs tool.
|
||||||
|
### Please keep in mind that the modules configured by paprefs might conflict with manually
|
||||||
|
### loaded modules.
|
||||||
|
.ifexists module-gconf.so
|
||||||
|
.nofail
|
||||||
|
load-module module-gconf
|
||||||
|
.fail
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Automatically restore the default sink/source when changed by the user
|
||||||
|
### during runtime
|
||||||
|
### NOTE: This should be loaded as early as possible so that subsequent modules
|
||||||
|
### that look up the default sink/source get the right value
|
||||||
|
load-module module-default-device-restore
|
||||||
|
|
||||||
|
### Automatically move streams to the default sink if the sink they are
|
||||||
|
### connected to dies, similar for sources
|
||||||
|
load-module module-rescue-streams
|
||||||
|
|
||||||
|
### Make sure we always have a sink around, even if it is a null sink.
|
||||||
|
load-module module-always-sink
|
||||||
|
|
||||||
|
### Honour intended role device property
|
||||||
|
load-module module-intended-roles
|
||||||
|
|
||||||
|
### Automatically suspend sinks/sources that become idle for too long
|
||||||
|
load-module module-suspend-on-idle
|
||||||
|
|
||||||
|
### If autoexit on idle is enabled we want to make sure we only quit
|
||||||
|
### when no local session needs us anymore.
|
||||||
|
.ifexists module-console-kit.so
|
||||||
|
load-module module-console-kit
|
||||||
|
.endif
|
||||||
|
.ifexists module-systemd-login.so
|
||||||
|
load-module module-systemd-login
|
||||||
|
.endif
|
||||||
|
|
||||||
|
### Enable positioned event sounds
|
||||||
|
load-module module-position-event-sounds
|
||||||
|
|
||||||
|
### Cork music/video streams when a phone stream is active
|
||||||
|
load-module module-role-cork
|
||||||
|
|
||||||
|
### Modules to allow autoloading of filters (such as echo cancellation)
|
||||||
|
### on demand. module-filter-heuristics tries to determine what filters
|
||||||
|
### make sense, and module-filter-apply does the heavy-lifting of
|
||||||
|
### loading modules and rerouting streams.
|
||||||
|
load-module module-filter-heuristics
|
||||||
|
load-module module-filter-apply
|
||||||
|
|
||||||
|
### Make some devices default
|
||||||
|
#set-default-sink output
|
||||||
|
#set-default-source input
|
||||||
|
set-default-source alsa_input.platform-soc_sound.seeed-8ch
|
||||||
|
set-default-sink alsa_output.platform-soc_sound.seeed-2ch
|
34
pulseaudio/pulse_config_6mic/seeed-voicecard.conf
Normal file
34
pulseaudio/pulse_config_6mic/seeed-voicecard.conf
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# /usr/share/pulseaudio/alsa-mixer/profile-sets/seeed-voiced.conf
|
||||||
|
|
||||||
|
[General]
|
||||||
|
auto-profiles = no
|
||||||
|
[Mapping seeed-8ch]
|
||||||
|
device-strings = hw:%f
|
||||||
|
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
|
||||||
|
exact-channels = false
|
||||||
|
fallback = yes
|
||||||
|
paths-input = seeed-8ch
|
||||||
|
priority = 3
|
||||||
|
direction = input
|
||||||
|
[Mapping seeed-2ch]
|
||||||
|
device-strings = hw:%f
|
||||||
|
channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
|
||||||
|
exact-channels = false
|
||||||
|
exact-channels = false
|
||||||
|
fallback = yes
|
||||||
|
paths-output = seeed-2ch
|
||||||
|
direction = output
|
||||||
|
priority = 2
|
||||||
|
[Profile output:seeed-2ch+input:seeed-8ch]
|
||||||
|
output-mappings = seeed-2ch
|
||||||
|
input-mappings = seeed-8ch
|
||||||
|
priority = 100
|
||||||
|
skip-probe = yes
|
||||||
|
[Profile output:seeed-2ch]
|
||||||
|
output-mappings = seeed-2ch
|
||||||
|
priority = 4
|
||||||
|
skip-probe = yes
|
||||||
|
[Profile input:seeed-8ch]
|
||||||
|
input-mappings = seeed-8ch
|
||||||
|
priority = 5
|
||||||
|
skip-probe = yes
|
BIN
pulseaudio/udev_rules_4mic.png
Normal file
BIN
pulseaudio/udev_rules_4mic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 KiB |
BIN
pulseaudio/udev_rules_6mic.png
Normal file
BIN
pulseaudio/udev_rules_6mic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 483 KiB |
|
@ -38,44 +38,8 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
fragment@3 {
|
fragment@3 {
|
||||||
target = <&sound>;
|
|
||||||
master_overlay: __dormant__ {
|
|
||||||
compatible = "simple-audio-card";
|
|
||||||
simple-audio-card,format = "i2s";
|
|
||||||
simple-audio-card,name = "seeed-2mic-voicecard";
|
|
||||||
simple-audio-card,bitclock-master = <&dailink0_master>;
|
|
||||||
simple-audio-card,frame-master = <&dailink0_master>;
|
|
||||||
status = "okay";
|
|
||||||
simple-audio-card,widgets =
|
|
||||||
"Microphone", "Mic Jack",
|
|
||||||
"Line", "Line In",
|
|
||||||
"Line", "Line Out",
|
|
||||||
"Speaker", "Speaker",
|
|
||||||
"Headphone", "Headphone Jack";
|
|
||||||
simple-audio-card,routing =
|
|
||||||
"Headphone Jack", "HP_L",
|
|
||||||
"Headphone Jack", "HP_R",
|
|
||||||
"Speaker", "SPK_LP",
|
|
||||||
"Speaker", "SPK_LN",
|
|
||||||
"LINPUT1", "Mic Jack",
|
|
||||||
"LINPUT3", "Mic Jack",
|
|
||||||
"RINPUT1", "Mic Jack",
|
|
||||||
"RINPUT2", "Mic Jack";
|
|
||||||
|
|
||||||
|
|
||||||
simple-audio-card,cpu {
|
|
||||||
sound-dai = <&i2s>;
|
|
||||||
};
|
|
||||||
dailink0_master: simple-audio-card,codec {
|
|
||||||
sound-dai = <&wm8960>;
|
|
||||||
clocks = <&wm8960_mclk>;
|
|
||||||
clock-names = "mclk";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
fragment@4 {
|
|
||||||
target = <&sound>;
|
target = <&sound>;
|
||||||
slave_overlay: __overlay__ {
|
slave_overlay: __overlay__ {
|
||||||
compatible = "simple-audio-card";
|
compatible = "simple-audio-card";
|
||||||
|
@ -114,8 +78,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
__overrides__ {
|
__overrides__ {
|
||||||
alsaname = <&master_overlay>,"simple-audio-card,name",
|
alsaname = <&slave_overlay>,"simple-audio-card,name";
|
||||||
<&slave_overlay>,"simple-audio-card,name";
|
|
||||||
compatible = <&wm8960>,"compatible";
|
compatible = <&wm8960>,"compatible";
|
||||||
master = <0>,"=2!3";
|
master = <0>,"=2!3";
|
||||||
};
|
};
|
||||||
|
|
Binary file not shown.
|
@ -2,25 +2,28 @@
|
||||||
/plugin/;
|
/plugin/;
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "brcm,bcm2708";
|
compatible = "brcm,bcm2708";
|
||||||
|
|
||||||
fragment@0 {
|
fragment@0 {
|
||||||
target = <&i2s>;
|
target = <&i2s>;
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
#sound-dai-cells = <0>;
|
#sound-dai-cells = <0>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
fragment@1 {
|
|
||||||
target-path = "/clocks";
|
fragment@1 {
|
||||||
__overlay__ {
|
target-path = "/";
|
||||||
ac108_mclk: codec-mclk {
|
__overlay__ {
|
||||||
compatible = "fixed-clock";
|
ac108_mclk: codec-mclk {
|
||||||
#clock-cells = <0>;
|
compatible = "fixed-clock";
|
||||||
clock-frequency = <24000000>;
|
#clock-cells = <0>;
|
||||||
};
|
clock-frequency = <24000000>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
fragment@2 {
|
};
|
||||||
|
|
||||||
|
fragment@2 {
|
||||||
target = <&i2c1>;
|
target = <&i2c1>;
|
||||||
__overlay__ {
|
__overlay__ {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
|
@ -31,36 +34,42 @@
|
||||||
compatible = "x-power,ac108_0";
|
compatible = "x-power,ac108_0";
|
||||||
reg = <0x3b>;
|
reg = <0x3b>;
|
||||||
#sound-dai-cells = <0>;
|
#sound-dai-cells = <0>;
|
||||||
data-protocol = <1>;
|
data-protocol = <0>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
fragment@3 {
|
||||||
|
target = <&sound>;
|
||||||
|
|
||||||
fragment@3 {
|
sound_overlay: __overlay__ {
|
||||||
target = <&sound>;
|
compatible = "seeed-voicecard";
|
||||||
sound_overlay: __overlay__ {
|
seeed-voice-card,format = "dsp_a";
|
||||||
compatible = "simple-audio-card";
|
seeed-voice-card,name = "seeed-4mic-voicecard";
|
||||||
simple-audio-card,format = "i2s";
|
status = "okay";
|
||||||
simple-audio-card,name = "seeed-4mic-voicecard";
|
|
||||||
status = "okay";
|
seeed-voice-card,bitclock-master = <&codec_dai>;
|
||||||
|
seeed-voice-card,frame-master = <&codec_dai>;
|
||||||
simple-audio-card,bitclock-master = <&dailink0_slave>;
|
seeed-voice-card,channels-playback-override = <4>;
|
||||||
simple-audio-card,frame-slave = <&dailink0_slave>;
|
seeed-voice-card,channels-capture-override = <4>;
|
||||||
dailink0_slave: simple-audio-card,cpu {
|
|
||||||
sound-dai = <&i2s>;
|
|
||||||
};
|
|
||||||
codec_dai: simple-audio-card,codec {
|
|
||||||
sound-dai = <&ac108_a>;
|
|
||||||
clocks = <&ac108_mclk>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
__overrides__ {
|
|
||||||
card-name = <&sound_overlay>,"seeed-voicecard,name";
|
|
||||||
};
|
|
||||||
|
|
||||||
|
cpu_dai: seeed-voice-card,cpu {
|
||||||
|
sound-dai = <&i2s>;
|
||||||
|
dai-tdm-slot-num = <2>;
|
||||||
|
dai-tdm-slot-width = <32>;
|
||||||
|
dai-tdm-slot-tx-mask = <1 1 0 0>;
|
||||||
|
dai-tdm-slot-rx-mask = <1 1 0 0>;
|
||||||
|
};
|
||||||
|
codec_dai: seeed-voice-card,codec {
|
||||||
|
sound-dai = <&ac108_a>;
|
||||||
|
clocks = <&ac108_mclk>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
__overrides__ {
|
||||||
|
card-name = <&sound_overlay>,"seeed-voice-card,name";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Binary file not shown.
118
seeed-8mic-voicecard-overlay.dts
Normal file
118
seeed-8mic-voicecard-overlay.dts
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/dts-v1/;
|
||||||
|
/plugin/;
|
||||||
|
|
||||||
|
/ {
|
||||||
|
compatible = "brcm,bcm2708";
|
||||||
|
|
||||||
|
fragment@0 {
|
||||||
|
target = <&i2s>;
|
||||||
|
__overlay__ {
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment@1 {
|
||||||
|
target-path = "/";
|
||||||
|
__overlay__ {
|
||||||
|
ac10x_mclk: codec-mclk {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-frequency = <24000000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment@2 {
|
||||||
|
target = <&gpio>;
|
||||||
|
__overlay__ {
|
||||||
|
spk_amp_pins: spk_pins {
|
||||||
|
brcm,pins = <17 22>;
|
||||||
|
brcm,function = <1 0>; /* out in */
|
||||||
|
brcm,pull = <0 0>; /* - - */
|
||||||
|
};
|
||||||
|
gpclk0_pins: gpclk0_pins {
|
||||||
|
brcm,pins = <4>;
|
||||||
|
brcm,function = <4>; /* alt func 0 */
|
||||||
|
brcm,pull = <0>; /* - */
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment@3 {
|
||||||
|
target = <&i2c1>;
|
||||||
|
__overlay__ {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
ac101: ac101@1a{
|
||||||
|
compatible = "x-power,ac101";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&spk_amp_pins &gpclk0_pins>;
|
||||||
|
spk-amp-switch-gpios = <&gpio 17 0>;
|
||||||
|
switch-irq-gpios = <&gpio 22 0>;
|
||||||
|
reg = <0x1a>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
ac108_a: ac108@35{
|
||||||
|
compatible = "x-power,ac108_0";
|
||||||
|
reg = <0x35>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
data-protocol = <0>;
|
||||||
|
tdm-chips-count = <2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
ac108_b: ac108@3b{
|
||||||
|
compatible = "x-power,ac108_1";
|
||||||
|
reg = <0x3b>;
|
||||||
|
#sound-dai-cells = <0>;
|
||||||
|
data-protocol = <0>;
|
||||||
|
tdm-chips-count = <2>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment@4 {
|
||||||
|
target = <&sound>;
|
||||||
|
|
||||||
|
sound_overlay: __overlay__ {
|
||||||
|
compatible = "seeed-voicecard";
|
||||||
|
seeed-voice-card,name = "seeed-8mic-voicecard";
|
||||||
|
seeed-voice-card,channels-playback-override = <8>;
|
||||||
|
seeed-voice-card,channels-capture-override = <8>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
seeed-voice-card,dai-link@0 {
|
||||||
|
format = "dsp_a";
|
||||||
|
bitclock-master = <&codec0_dai>;
|
||||||
|
frame-master = <&codec0_dai>;
|
||||||
|
/* bitclock-inversion; */
|
||||||
|
/* frame-inversion; */
|
||||||
|
reg = <0>;
|
||||||
|
|
||||||
|
cpu {
|
||||||
|
sound-dai = <&i2s>;
|
||||||
|
dai-tdm-slot-num = <2>;
|
||||||
|
dai-tdm-slot-width = <32>;
|
||||||
|
dai-tdm-slot-tx-mask = <1 1 0 0>;
|
||||||
|
dai-tdm-slot-rx-mask = <1 1 0 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
codec0_dai: codec {
|
||||||
|
sound-dai = <&ac108_a>;
|
||||||
|
clocks = <&ac10x_mclk>;
|
||||||
|
system-clock-id = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
__overrides__ {
|
||||||
|
card-name = <&sound_overlay>,"seeed-voice-card,name";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
BIN
seeed-8mic-voicecard.dtbo
Normal file
BIN
seeed-8mic-voicecard.dtbo
Normal file
Binary file not shown.
163
seeed-voicecard
Executable file
163
seeed-voicecard
Executable file
|
@ -0,0 +1,163 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright (c) 2018 Baozhu Zuo <zuobaozhu@gmail.com>
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
# THE SOFTWARE.
|
||||||
|
|
||||||
|
set -x
|
||||||
|
#exec 1>/var/log/$(basename $0).log 2>&1
|
||||||
|
|
||||||
|
export PATH=$PATH:/opt/vc/bin
|
||||||
|
OVERLAYS=/boot/overlays
|
||||||
|
[ -d /boot/firmware/overlays ] && OVERLAYS=/boot/firmware/overlays
|
||||||
|
|
||||||
|
#enable i2c interface
|
||||||
|
dtparam -d $OVERLAYS i2c_arm=on
|
||||||
|
modprobe i2c-dev
|
||||||
|
|
||||||
|
#enable spi interface
|
||||||
|
dtparam -d $OVERLAYS spi=on
|
||||||
|
|
||||||
|
_VER_RUN=
|
||||||
|
function get_kernel_version() {
|
||||||
|
local ZIMAGE IMG_OFFSET
|
||||||
|
|
||||||
|
_VER_RUN=""
|
||||||
|
[ -z "$_VER_RUN" ] && {
|
||||||
|
ZIMAGE=/boot/kernel.img
|
||||||
|
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
|
||||||
|
# 64-bit-only kernel package
|
||||||
|
[ ! -f /boot/kernel.img ] && [ -f /boot/kernel8.img ] && ZIMAGE=/boot/kernel8.img
|
||||||
|
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | LC_ALL=C sed -e 's/^.*Linux/Linux/' | strings | awk '{ print $3; }')
|
||||||
|
}
|
||||||
|
echo "$_VER_RUN"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG=/boot/config.txt
|
||||||
|
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
|
||||||
|
|
||||||
|
get_overlay() {
|
||||||
|
ov=$1
|
||||||
|
if grep -q -E "^dtoverlay=$ov" $CONFIG; then
|
||||||
|
echo 0
|
||||||
|
else
|
||||||
|
echo 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_overlay() {
|
||||||
|
ov=$1
|
||||||
|
RET=$2
|
||||||
|
DEFAULT=--defaultno
|
||||||
|
CURRENT=0
|
||||||
|
if [ $(get_overlay $ov) -eq 0 ]; then
|
||||||
|
DEFAULT=
|
||||||
|
CURRENT=1
|
||||||
|
fi
|
||||||
|
if [ $RET -eq $CURRENT ]; then
|
||||||
|
ASK_TO_REBOOT=1
|
||||||
|
fi
|
||||||
|
if [ $RET -eq 0 ]; then
|
||||||
|
sed $CONFIG -i -e "s/^#dtoverlay=$ov/dtoverlay=$ov/"
|
||||||
|
if ! grep -q -E "^dtoverlay=$ov" $CONFIG; then
|
||||||
|
printf "dtoverlay=$ov\n" >> $CONFIG
|
||||||
|
fi
|
||||||
|
STATUS=enabled
|
||||||
|
elif [ $RET -eq 1 ]; then
|
||||||
|
sed $CONFIG -i -e "s/^dtoverlay=$ov/#dtoverlay=$ov/"
|
||||||
|
STATUS=disabled
|
||||||
|
else
|
||||||
|
return $RET
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
is_1a=$(i2cdetect -y 1 0x1a 0x1a | egrep "(1a|UU)" | awk '{print $2}')
|
||||||
|
is_35=$(i2cdetect -y 1 0x35 0x35 | egrep "(35|UU)" | awk '{print $2}')
|
||||||
|
is_3b=$(i2cdetect -y 1 0x3b 0x3b | egrep "(3b|UU)" | awk '{print $2}')
|
||||||
|
|
||||||
|
RPI_HATS="seeed-2mic-voicecard seeed-4mic-voicecard seeed-8mic-voicecard"
|
||||||
|
overlay=""
|
||||||
|
|
||||||
|
if [ "x${is_1a}" != "x" ] && [ "x${is_35}" == "x" ] ; then
|
||||||
|
echo "install 2mic"
|
||||||
|
overlay=seeed-2mic-voicecard
|
||||||
|
asound_conf=/etc/voicecard/asound_2mic.conf
|
||||||
|
asound_state=/etc/voicecard/wm8960_asound.state
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x${is_3b}" != "x" ] && [ "x${is_35}" == "x" ] ; then
|
||||||
|
echo "install 4mic"
|
||||||
|
overlay=seeed-4mic-voicecard
|
||||||
|
asound_conf=/etc/voicecard/asound_4mic.conf
|
||||||
|
asound_state=/etc/voicecard/ac108_asound.state
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "x${is_3b}" != "x" ] && [ "x${is_35}" != "x" ] ; then
|
||||||
|
echo "install 6mic"
|
||||||
|
overlay=seeed-8mic-voicecard
|
||||||
|
asound_conf=/etc/voicecard/asound_6mic.conf
|
||||||
|
asound_state=/etc/voicecard/ac108_6mic.state
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$overlay" ]; then
|
||||||
|
echo Install $overlay ...
|
||||||
|
|
||||||
|
# Remove old configuration
|
||||||
|
rm /etc/asound.conf
|
||||||
|
rm /var/lib/alsa/asound.state
|
||||||
|
|
||||||
|
kernel_ver=$(uname -r) # get_kernel_version)
|
||||||
|
# echo kernel_ver=$kernel_ver
|
||||||
|
|
||||||
|
# TODO: dynamic dtoverlay Bug of v4.19.x
|
||||||
|
# no DT node phandle inserted.
|
||||||
|
if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then
|
||||||
|
for i in $RPI_HATS; do
|
||||||
|
if [ "$i" == "$overlay" ]; then
|
||||||
|
/bin/true #do_overlay $overlay 0
|
||||||
|
else
|
||||||
|
echo Uninstall $i ...
|
||||||
|
/bin/true #do_overlay $i 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
#make sure the driver loads correctly
|
||||||
|
dtoverlay -d $OVERLAYS $overlay || true
|
||||||
|
|
||||||
|
|
||||||
|
echo "create $overlay asound configure file"
|
||||||
|
ln -s $asound_conf /etc/asound.conf
|
||||||
|
echo "create $overlay asound status file"
|
||||||
|
ln -s $asound_state /var/lib/alsa/asound.state
|
||||||
|
fi
|
||||||
|
|
||||||
|
alsactl restore
|
||||||
|
|
||||||
|
#Force 3.5mm ('headphone') jack
|
||||||
|
# The Raspberry Pi 4, released on 24th Jun 2019, has two HDMI ports,
|
||||||
|
# and can drive two displays with audios for two users simultaneously,
|
||||||
|
# in a "multiseat" configuration. The earlier single virtual ALSA
|
||||||
|
# option for re-directing audio playback between headphone jack and HDMI
|
||||||
|
# via a 'Routing' mixer setting was turned off eventually to allow
|
||||||
|
# simultaneous usage of all 3 playback devices.
|
||||||
|
if aplay -l | grep -q "bcm2835 ALSA"; then
|
||||||
|
amixer cset numid=3 1 || true
|
||||||
|
fi
|
926
seeed-voicecard.c
Normal file
926
seeed-voicecard.c
Normal file
|
@ -0,0 +1,926 @@
|
||||||
|
/*
|
||||||
|
* SEEED voice card
|
||||||
|
*
|
||||||
|
* (C) Copyright 2017-2018
|
||||||
|
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
|
||||||
|
*
|
||||||
|
* base on ASoC simple sound card support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Renesas Solutions Corp.
|
||||||
|
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
/* #undef DEBUG */
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <sound/soc.h>
|
||||||
|
#include <sound/soc-dai.h>
|
||||||
|
#include <sound/simple_card_utils.h>
|
||||||
|
#include "ac10x.h"
|
||||||
|
|
||||||
|
#define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3))
|
||||||
|
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
|
||||||
|
#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \
|
||||||
|
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus)
|
||||||
|
#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \
|
||||||
|
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs)
|
||||||
|
#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \
|
||||||
|
asoc_simple_parse_dai(node, dai_link->cpus, is_single_link)
|
||||||
|
#define asoc_simple_parse_codec(node, dai_link) \
|
||||||
|
asoc_simple_parse_dai(node, dai_link->codecs, NULL)
|
||||||
|
#define asoc_simple_parse_platform(node, dai_link) \
|
||||||
|
asoc_simple_parse_dai(node, dai_link->platforms, NULL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* single codec:
|
||||||
|
* 0 - allow multi codec
|
||||||
|
* 1 - yes
|
||||||
|
*/
|
||||||
|
#define _SINGLE_CODEC 1
|
||||||
|
|
||||||
|
struct seeed_card_data {
|
||||||
|
struct snd_soc_card snd_card;
|
||||||
|
struct seeed_dai_props {
|
||||||
|
struct asoc_simple_dai cpu_dai;
|
||||||
|
struct asoc_simple_dai codec_dai;
|
||||||
|
struct snd_soc_dai_link_component cpus; /* single cpu */
|
||||||
|
struct snd_soc_dai_link_component codecs; /* single codec */
|
||||||
|
struct snd_soc_dai_link_component platforms;
|
||||||
|
unsigned int mclk_fs;
|
||||||
|
} *dai_props;
|
||||||
|
unsigned int mclk_fs;
|
||||||
|
unsigned channels_playback_default;
|
||||||
|
unsigned channels_playback_override;
|
||||||
|
unsigned channels_capture_default;
|
||||||
|
unsigned channels_capture_override;
|
||||||
|
struct snd_soc_dai_link *dai_link;
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
spinlock_t lock;
|
||||||
|
#endif
|
||||||
|
struct work_struct work_codec_clk;
|
||||||
|
#define TRY_STOP_MAX 3
|
||||||
|
int try_stop;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct seeed_card_info {
|
||||||
|
const char *name;
|
||||||
|
const char *card;
|
||||||
|
const char *codec;
|
||||||
|
const char *platform;
|
||||||
|
|
||||||
|
unsigned int daifmt;
|
||||||
|
struct asoc_simple_dai cpu_dai;
|
||||||
|
struct asoc_simple_dai codec_dai;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define seeed_priv_to_card(priv) (&(priv)->snd_card)
|
||||||
|
#define seeed_priv_to_dev(priv) ((priv)->snd_card.dev)
|
||||||
|
#define seeed_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
|
||||||
|
#define seeed_priv_to_props(priv, i) ((priv)->dai_props + (i))
|
||||||
|
|
||||||
|
#define DAI "sound-dai"
|
||||||
|
#define CELL "#sound-dai-cells"
|
||||||
|
#define PREFIX "seeed-voice-card,"
|
||||||
|
|
||||||
|
static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(dai_props->cpu_dai.clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(dai_props->codec_dai.clk);
|
||||||
|
if (ret)
|
||||||
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
if (asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min) {
|
||||||
|
priv->channels_playback_default = asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min;
|
||||||
|
}
|
||||||
|
if (asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min) {
|
||||||
|
priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min;
|
||||||
|
}
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_override;
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_override;
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_override;
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_override;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_default;
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_default;
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_default;
|
||||||
|
asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_max = priv->channels_capture_default;
|
||||||
|
|
||||||
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
clk_disable_unprepare(dai_props->codec_dai.clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seeed_voice_card_hw_params(struct snd_pcm_substream *substream,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
unsigned int mclk, mclk_fs = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (priv->mclk_fs)
|
||||||
|
mclk_fs = priv->mclk_fs;
|
||||||
|
else if (dai_props->mclk_fs)
|
||||||
|
mclk_fs = dai_props->mclk_fs;
|
||||||
|
|
||||||
|
if (mclk_fs) {
|
||||||
|
mclk = params_rate(params) * mclk_fs;
|
||||||
|
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
|
||||||
|
SND_SOC_CLOCK_IN);
|
||||||
|
if (ret && ret != -ENOTSUPP)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
|
||||||
|
SND_SOC_CLOCK_OUT);
|
||||||
|
if (ret && ret != -ENOTSUPP)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _SET_CLOCK_CNT 2
|
||||||
|
static int (* _set_clock[_SET_CLOCK_CNT])(int y_start_n_stop, struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai);
|
||||||
|
|
||||||
|
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int, struct snd_pcm_substream *, int, struct snd_soc_dai *)) {
|
||||||
|
if (! _set_clock[stream]) {
|
||||||
|
_set_clock[stream] = set_clock;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(seeed_voice_card_register_set_clock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* work_cb_codec_clk: clear audio codec inner clock.
|
||||||
|
*/
|
||||||
|
static void work_cb_codec_clk(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct seeed_card_data *priv = container_of(work, struct seeed_card_data, work_codec_clk);
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) {
|
||||||
|
r = r || _set_clock[SNDRV_PCM_STREAM_CAPTURE](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
|
||||||
|
}
|
||||||
|
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) {
|
||||||
|
r = r || _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r && priv->try_stop++ < TRY_STOP_MAX) {
|
||||||
|
if (0 != schedule_work(&priv->work_codec_clk)) {}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
|
struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
unsigned long flags;
|
||||||
|
#endif
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
|
||||||
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
|
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
|
if (cancel_work_sync(&priv->work_codec_clk) != 0) {}
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
/* I know it will degrades performance, but I have no choice */
|
||||||
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
|
#endif
|
||||||
|
// if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](1, substream, cmd, dai);
|
||||||
|
// if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](1, substream, cmd, dai);
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
|
/* capture channel resync, if overrun */
|
||||||
|
if (dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* interrupt environment */
|
||||||
|
if (in_irq() || in_nmi() || in_serving_softirq()) {
|
||||||
|
priv->try_stop = 0;
|
||||||
|
if (0 != schedule_work(&priv->work_codec_clk)) {
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
|
||||||
|
// if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
|
||||||
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
|
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct snd_soc_ops seeed_voice_card_ops = {
|
||||||
|
.startup = seeed_voice_card_startup,
|
||||||
|
.shutdown = seeed_voice_card_shutdown,
|
||||||
|
.hw_params = seeed_voice_card_hw_params,
|
||||||
|
.trigger = seeed_voice_card_trigger,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int asoc_simple_parse_dai(struct device_node *node,
|
||||||
|
struct snd_soc_dai_link_component *dlc,
|
||||||
|
int *is_single_link)
|
||||||
|
{
|
||||||
|
struct of_phandle_args args;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get node via "sound-dai = <&phandle port>"
|
||||||
|
* it will be used as xxx_of_node on soc_bind_dai_link()
|
||||||
|
*/
|
||||||
|
ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Here, dlc->dai_name is pointer to CPU/Codec DAI name.
|
||||||
|
* If user unbinded CPU or Codec driver, but not for Sound Card,
|
||||||
|
* dlc->dai_name is keeping unbinded CPU or Codec
|
||||||
|
* driver's pointer.
|
||||||
|
*
|
||||||
|
* If user re-bind CPU or Codec driver again, ALSA SoC will try
|
||||||
|
* to rebind Card via snd_soc_try_rebind_card(), but because of
|
||||||
|
* above reason, it might can't bind Sound Card.
|
||||||
|
* Because Sound Card is pointing to released dai_name pointer.
|
||||||
|
*
|
||||||
|
* To avoid this rebind Card issue,
|
||||||
|
* 1) It needs to alloc memory to keep dai_name eventhough
|
||||||
|
* CPU or Codec driver was unbinded, or
|
||||||
|
* 2) user need to rebind Sound Card everytime
|
||||||
|
* if he unbinded CPU or Codec.
|
||||||
|
*/
|
||||||
|
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
dlc->of_node = args.np;
|
||||||
|
|
||||||
|
if (is_single_link)
|
||||||
|
*is_single_link = !args.args_count;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asoc_simple_init_dai(struct snd_soc_dai *dai,
|
||||||
|
struct asoc_simple_dai *simple_dai)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!simple_dai)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (simple_dai->sysclk) {
|
||||||
|
ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk,
|
||||||
|
simple_dai->clk_direction);
|
||||||
|
if (ret && ret != -ENOTSUPP) {
|
||||||
|
dev_err(dai->dev, "simple-card: set_sysclk error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simple_dai->slots) {
|
||||||
|
ret = snd_soc_dai_set_bclk_ratio(dai,
|
||||||
|
simple_dai->slots *
|
||||||
|
simple_dai->slot_width);
|
||||||
|
if (ret && ret != -ENOTSUPP) {
|
||||||
|
dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
|
||||||
|
static inline int asoc_simple_component_is_codec(struct snd_soc_component *component)
|
||||||
|
{
|
||||||
|
return component->driver->endianness;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct snd_soc_dai_link *dai_link = rtd->dai_link;
|
||||||
|
struct snd_soc_component *component;
|
||||||
|
struct snd_soc_pcm_stream *params;
|
||||||
|
struct snd_pcm_hardware hw;
|
||||||
|
int i, ret, stream;
|
||||||
|
|
||||||
|
/* Only Codecs */
|
||||||
|
for_each_rtd_components(rtd, i, component) {
|
||||||
|
if (!asoc_simple_component_is_codec(component))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assumes the capabilities are the same for all supported streams */
|
||||||
|
for (stream = 0; stream < 2; stream++) {
|
||||||
|
ret = snd_soc_runtime_calc_hw(rtd, &hw, stream);
|
||||||
|
if (ret == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(rtd->dev, "simple-card: no valid dai_link params\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL);
|
||||||
|
if (!params)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
params->formats = hw.formats;
|
||||||
|
params->rates = hw.rates;
|
||||||
|
params->rate_min = hw.rate_min;
|
||||||
|
params->rate_max = hw.rate_max;
|
||||||
|
params->channels_min = hw.channels_min;
|
||||||
|
params->channels_max = hw.channels_max;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
|
||||||
|
dai_link->c2c_params = params;
|
||||||
|
dai_link->num_c2c_params = 1;
|
||||||
|
#else
|
||||||
|
/* apparently this goes back to 5.6.x */
|
||||||
|
dai_link->params = params;
|
||||||
|
dai_link->num_params = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
|
{
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
|
struct snd_soc_dai *codec = asoc_rtd_to_codec(rtd, 0);
|
||||||
|
struct snd_soc_dai *cpu = asoc_rtd_to_cpu(rtd, 0);
|
||||||
|
struct seeed_dai_props *dai_props =
|
||||||
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = asoc_simple_init_dai(codec, &dai_props->codec_dai);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = asoc_simple_init_dai(cpu, &dai_props->cpu_dai);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
|
||||||
|
ret = asoc_simple_init_dai_link_params(rtd);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dev_dbg(rtd->card->dev, "codec \"%s\" mapping to cpu \"%s\"\n", codec->name, cpu->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
|
struct seeed_card_data *priv,
|
||||||
|
int idx,
|
||||||
|
bool is_top_level_node)
|
||||||
|
{
|
||||||
|
struct device *dev = seeed_priv_to_dev(priv);
|
||||||
|
struct snd_soc_dai_link *dai_link = seeed_priv_to_link(priv, idx);
|
||||||
|
struct seeed_dai_props *dai_props = seeed_priv_to_props(priv, idx);
|
||||||
|
struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
|
||||||
|
struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
|
||||||
|
struct device_node *cpu = NULL;
|
||||||
|
struct device_node *plat = NULL;
|
||||||
|
struct device_node *codec = NULL;
|
||||||
|
char prop[128];
|
||||||
|
char *prefix = "";
|
||||||
|
int ret, single_cpu;
|
||||||
|
|
||||||
|
/* For single DAI link & old style of DT node */
|
||||||
|
if (is_top_level_node)
|
||||||
|
prefix = PREFIX;
|
||||||
|
|
||||||
|
snprintf(prop, sizeof(prop), "%scpu", prefix);
|
||||||
|
cpu = of_get_child_by_name(node, prop);
|
||||||
|
|
||||||
|
if (!cpu) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
|
||||||
|
goto dai_link_of_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(prop, sizeof(prop), "%splat", prefix);
|
||||||
|
plat = of_get_child_by_name(node, prop);
|
||||||
|
|
||||||
|
snprintf(prop, sizeof(prop), "%scodec", prefix);
|
||||||
|
codec = of_get_child_by_name(node, prop);
|
||||||
|
|
||||||
|
if (!codec) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
|
||||||
|
goto dai_link_of_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = asoc_simple_parse_daifmt(dev, node, codec,
|
||||||
|
prefix, &dai_link->dai_fmt);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs);
|
||||||
|
|
||||||
|
ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
ret = asoc_simple_parse_codec(codec, dai_link);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
#else
|
||||||
|
ret = snd_soc_of_get_dai_link_codecs(dev, codec, dai_link);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "parse codec info error %d\n", ret);
|
||||||
|
goto dai_link_of_err;
|
||||||
|
}
|
||||||
|
dev_dbg(dev, "dai_link num_codecs = %d\n", dai_link->num_codecs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = asoc_simple_parse_platform(plat, dai_link);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
ret = snd_soc_of_parse_tdm_slot(cpu, &cpu_dai->tx_slot_mask,
|
||||||
|
&cpu_dai->rx_slot_mask,
|
||||||
|
&cpu_dai->slots,
|
||||||
|
&cpu_dai->slot_width);
|
||||||
|
dev_dbg(dev, "cpu_dai : slot,width,tx,rx = %d,%d,%d,%d\n",
|
||||||
|
cpu_dai->slots, cpu_dai->slot_width,
|
||||||
|
cpu_dai->tx_slot_mask, cpu_dai->rx_slot_mask
|
||||||
|
);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
ret = snd_soc_of_parse_tdm_slot(codec, &codec_dai->tx_slot_mask,
|
||||||
|
&codec_dai->rx_slot_mask,
|
||||||
|
&codec_dai->slots,
|
||||||
|
&codec_dai->slot_width);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,10,0)
|
||||||
|
ret = asoc_simple_card_parse_clk_cpu(cpu, dai_link, cpu_dai);
|
||||||
|
#else
|
||||||
|
ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
|
||||||
|
#endif
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,10,0)
|
||||||
|
ret = asoc_simple_card_parse_clk_codec(codec, dai_link, codec_dai);
|
||||||
|
#else
|
||||||
|
ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
|
||||||
|
#endif
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
ret = asoc_simple_set_dailink_name(dev, dai_link,
|
||||||
|
"%s-%s",
|
||||||
|
dai_link->cpus->dai_name,
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
dai_link->codecs->dai_name
|
||||||
|
#else
|
||||||
|
dai_link->codecs[0].dai_name
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
if (ret < 0)
|
||||||
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
dai_link->ops = &seeed_voice_card_ops;
|
||||||
|
dai_link->init = seeed_voice_card_dai_init;
|
||||||
|
|
||||||
|
dev_dbg(dev, "\tname : %s\n", dai_link->stream_name);
|
||||||
|
dev_dbg(dev, "\tformat : %04x\n", dai_link->dai_fmt);
|
||||||
|
dev_dbg(dev, "\tcpu : %s / %d\n",
|
||||||
|
dai_link->cpus->dai_name,
|
||||||
|
dai_props->cpu_dai.sysclk);
|
||||||
|
dev_dbg(dev, "\tcodec : %s / %d\n",
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
dai_link->codecs->dai_name,
|
||||||
|
#else
|
||||||
|
dai_link->codecs[0].dai_name,
|
||||||
|
#endif
|
||||||
|
dai_props->codec_dai.sysclk);
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
|
||||||
|
asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu);
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
asoc_simple_canonicalize_cpu(dai_link, single_cpu);
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
asoc_simple_canonicalize_platform(dai_link);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dai_link_of_err:
|
||||||
|
of_node_put(cpu);
|
||||||
|
of_node_put(codec);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seeed_voice_card_parse_aux_devs(struct device_node *node,
|
||||||
|
struct seeed_card_data *priv)
|
||||||
|
{
|
||||||
|
struct device *dev = seeed_priv_to_dev(priv);
|
||||||
|
struct device_node *aux_node;
|
||||||
|
int i, n, len;
|
||||||
|
|
||||||
|
if (!of_find_property(node, PREFIX "aux-devs", &len))
|
||||||
|
return 0; /* Ok to have no aux-devs */
|
||||||
|
|
||||||
|
n = len / sizeof(__be32);
|
||||||
|
if (n <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
priv->snd_card.aux_dev = devm_kzalloc(dev,
|
||||||
|
n * sizeof(*priv->snd_card.aux_dev), GFP_KERNEL);
|
||||||
|
if (!priv->snd_card.aux_dev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
aux_node = of_parse_phandle(node, PREFIX "aux-devs", i);
|
||||||
|
if (!aux_node)
|
||||||
|
return -EINVAL;
|
||||||
|
priv->snd_card.aux_dev[i].dlc.of_node = aux_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->snd_card.num_aux_devs = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seeed_voice_card_parse_of(struct device_node *node,
|
||||||
|
struct seeed_card_data *priv)
|
||||||
|
{
|
||||||
|
struct device *dev = seeed_priv_to_dev(priv);
|
||||||
|
struct device_node *dai_link;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
dai_link = of_get_child_by_name(node, PREFIX "dai-link");
|
||||||
|
|
||||||
|
/* The off-codec widgets */
|
||||||
|
if (of_property_read_bool(node, PREFIX "widgets")) {
|
||||||
|
ret = snd_soc_of_parse_audio_simple_widgets(&priv->snd_card,
|
||||||
|
PREFIX "widgets");
|
||||||
|
if (ret)
|
||||||
|
goto card_parse_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DAPM routes */
|
||||||
|
if (of_property_read_bool(node, PREFIX "routing")) {
|
||||||
|
ret = snd_soc_of_parse_audio_routing(&priv->snd_card,
|
||||||
|
PREFIX "routing");
|
||||||
|
if (ret)
|
||||||
|
goto card_parse_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Factor to mclk, used in hw_params() */
|
||||||
|
of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
|
||||||
|
|
||||||
|
/* Single/Muti DAI link(s) & New style of DT node */
|
||||||
|
if (dai_link) {
|
||||||
|
struct device_node *np = NULL;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for_each_child_of_node(node, np) {
|
||||||
|
dev_dbg(dev, "\tlink %d:\n", i);
|
||||||
|
ret = seeed_voice_card_dai_link_of(np, priv,
|
||||||
|
i, false);
|
||||||
|
if (ret < 0) {
|
||||||
|
of_node_put(np);
|
||||||
|
goto card_parse_end;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* For single DAI link & old style of DT node */
|
||||||
|
ret = seeed_voice_card_dai_link_of(node, priv, 0, true);
|
||||||
|
if (ret < 0)
|
||||||
|
goto card_parse_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = asoc_simple_parse_card_name(&priv->snd_card, PREFIX);
|
||||||
|
if (ret < 0)
|
||||||
|
goto card_parse_end;
|
||||||
|
|
||||||
|
ret = seeed_voice_card_parse_aux_devs(node, priv);
|
||||||
|
|
||||||
|
priv->channels_playback_default = 0;
|
||||||
|
priv->channels_playback_override = 2;
|
||||||
|
priv->channels_capture_default = 0;
|
||||||
|
priv->channels_capture_override = 2;
|
||||||
|
of_property_read_u32(node, PREFIX "channels-playback-default",
|
||||||
|
&priv->channels_playback_default);
|
||||||
|
of_property_read_u32(node, PREFIX "channels-playback-override",
|
||||||
|
&priv->channels_playback_override);
|
||||||
|
of_property_read_u32(node, PREFIX "channels-capture-default",
|
||||||
|
&priv->channels_capture_default);
|
||||||
|
of_property_read_u32(node, PREFIX "channels-capture-override",
|
||||||
|
&priv->channels_capture_override);
|
||||||
|
|
||||||
|
card_parse_end:
|
||||||
|
of_node_put(dai_link);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
inline void seeed_debug_dai(struct seeed_card_data *priv,
|
||||||
|
char *name,
|
||||||
|
struct asoc_simple_dai *dai)
|
||||||
|
{
|
||||||
|
struct device *dev = seeed_priv_to_dev(priv);
|
||||||
|
|
||||||
|
if (dai->name)
|
||||||
|
dev_dbg(dev, "%s dai name = %s\n",
|
||||||
|
name, dai->name);
|
||||||
|
if (dai->sysclk)
|
||||||
|
dev_dbg(dev, "%s sysclk = %d\n",
|
||||||
|
name, dai->sysclk);
|
||||||
|
|
||||||
|
dev_dbg(dev, "%s direction = %s\n",
|
||||||
|
name, dai->clk_direction ? "OUT" : "IN");
|
||||||
|
|
||||||
|
if (dai->slots)
|
||||||
|
dev_dbg(dev, "%s slots = %d\n", name, dai->slots);
|
||||||
|
if (dai->slot_width)
|
||||||
|
dev_dbg(dev, "%s slot width = %d\n", name, dai->slot_width);
|
||||||
|
if (dai->tx_slot_mask)
|
||||||
|
dev_dbg(dev, "%s tx slot mask = %d\n", name, dai->tx_slot_mask);
|
||||||
|
if (dai->rx_slot_mask)
|
||||||
|
dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask);
|
||||||
|
if (dai->clk)
|
||||||
|
dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void seeed_debug_info(struct seeed_card_data *priv)
|
||||||
|
{
|
||||||
|
struct snd_soc_card *card = seeed_priv_to_card(priv);
|
||||||
|
struct device *dev = seeed_priv_to_dev(priv);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (card->name)
|
||||||
|
dev_dbg(dev, "Card Name: %s\n", card->name);
|
||||||
|
|
||||||
|
for (i = 0; i < card->num_links; i++) {
|
||||||
|
struct seeed_dai_props *props = seeed_priv_to_props(priv, i);
|
||||||
|
struct snd_soc_dai_link *link = seeed_priv_to_link(priv, i);
|
||||||
|
|
||||||
|
dev_dbg(dev, "DAI%d\n", i);
|
||||||
|
|
||||||
|
seeed_debug_dai(priv, "cpu", &props->cpu_dai);
|
||||||
|
seeed_debug_dai(priv, "codec", &props->codec_dai);
|
||||||
|
|
||||||
|
if (link->name)
|
||||||
|
dev_dbg(dev, "dai name = %s\n", link->name);
|
||||||
|
|
||||||
|
dev_dbg(dev, "dai format = %04x\n", link->dai_fmt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (props->adata.convert_rate)
|
||||||
|
dev_dbg(dev, "convert_rate = %d\n",
|
||||||
|
props->adata.convert_rate);
|
||||||
|
if (props->adata.convert_channels)
|
||||||
|
dev_dbg(dev, "convert_channels = %d\n",
|
||||||
|
props->adata.convert_channels);
|
||||||
|
if (props->codec_conf && props->codec_conf->name_prefix)
|
||||||
|
dev_dbg(dev, "name prefix = %s\n",
|
||||||
|
props->codec_conf->name_prefix);
|
||||||
|
*/
|
||||||
|
if (props->mclk_fs)
|
||||||
|
dev_dbg(dev, "mclk-fs = %d\n",
|
||||||
|
props->mclk_fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define seeed_debug_info(priv)
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct seeed_card_data *priv;
|
||||||
|
struct snd_soc_dai_link *dai_link;
|
||||||
|
struct seeed_dai_props *dai_props;
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
int num, ret, i;
|
||||||
|
|
||||||
|
/* Get the number of DAI links */
|
||||||
|
if (np && of_get_child_by_name(np, PREFIX "dai-link"))
|
||||||
|
num = of_get_child_count(np);
|
||||||
|
else
|
||||||
|
num = 1;
|
||||||
|
|
||||||
|
/* Allocate the private data and the DAI link array */
|
||||||
|
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
|
||||||
|
dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
|
||||||
|
if (!dai_props || !dai_link)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use snd_soc_dai_link_component instead of legacy style
|
||||||
|
* It is codec only. but cpu/platform will be supported in the future.
|
||||||
|
* see
|
||||||
|
* soc-core.c :: snd_soc_init_multicodec()
|
||||||
|
*
|
||||||
|
* "platform" might be removed
|
||||||
|
* see
|
||||||
|
* simple-card-utils.c :: asoc_simple_canonicalize_platform()
|
||||||
|
*/
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
dai_link[i].cpus = &dai_props[i].cpus;
|
||||||
|
dai_link[i].num_cpus = 1;
|
||||||
|
dai_link[i].codecs = &dai_props[i].codecs;
|
||||||
|
dai_link[i].num_codecs = 1;
|
||||||
|
dai_link[i].platforms = &dai_props[i].platforms;
|
||||||
|
dai_link[i].num_platforms = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->dai_props = dai_props;
|
||||||
|
priv->dai_link = dai_link;
|
||||||
|
|
||||||
|
/* Init snd_soc_card */
|
||||||
|
priv->snd_card.owner = THIS_MODULE;
|
||||||
|
priv->snd_card.dev = dev;
|
||||||
|
priv->snd_card.dai_link = priv->dai_link;
|
||||||
|
priv->snd_card.num_links = num;
|
||||||
|
|
||||||
|
if (np && of_device_is_available(np)) {
|
||||||
|
ret = seeed_voice_card_parse_of(np, priv);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret != -EPROBE_DEFER)
|
||||||
|
dev_err(dev, "parse error %d\n", ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct seeed_card_info *cinfo;
|
||||||
|
struct snd_soc_dai_link_component *cpus;
|
||||||
|
struct snd_soc_dai_link_component *codecs;
|
||||||
|
struct snd_soc_dai_link_component *platform;
|
||||||
|
|
||||||
|
cinfo = dev->platform_data;
|
||||||
|
if (!cinfo) {
|
||||||
|
dev_err(dev, "no info for seeed-voice-card\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cinfo->name ||
|
||||||
|
!cinfo->codec_dai.name ||
|
||||||
|
!cinfo->codec ||
|
||||||
|
!cinfo->platform ||
|
||||||
|
!cinfo->cpu_dai.name) {
|
||||||
|
dev_err(dev, "insufficient seeed_voice_card_info settings\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpus = dai_link->cpus;
|
||||||
|
cpus->dai_name = cinfo->cpu_dai.name;
|
||||||
|
|
||||||
|
codecs = dai_link->codecs;
|
||||||
|
codecs->name = cinfo->codec;
|
||||||
|
codecs->dai_name = cinfo->codec_dai.name;
|
||||||
|
|
||||||
|
platform = dai_link->platforms;
|
||||||
|
platform->name = cinfo->platform;
|
||||||
|
|
||||||
|
priv->snd_card.name = (cinfo->card) ? cinfo->card : cinfo->name;
|
||||||
|
dai_link->name = cinfo->name;
|
||||||
|
dai_link->stream_name = cinfo->name;
|
||||||
|
dai_link->dai_fmt = cinfo->daifmt;
|
||||||
|
dai_link->init = seeed_voice_card_dai_init;
|
||||||
|
memcpy(&priv->dai_props->cpu_dai, &cinfo->cpu_dai,
|
||||||
|
sizeof(priv->dai_props->cpu_dai));
|
||||||
|
memcpy(&priv->dai_props->codec_dai, &cinfo->codec_dai,
|
||||||
|
sizeof(priv->dai_props->codec_dai));
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_soc_card_set_drvdata(&priv->snd_card, priv);
|
||||||
|
|
||||||
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
|
spin_lock_init(&priv->lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
INIT_WORK(&priv->work_codec_clk, work_cb_codec_clk);
|
||||||
|
|
||||||
|
seeed_debug_info(priv);
|
||||||
|
|
||||||
|
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
|
||||||
|
if (ret >= 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
asoc_simple_clean_reference(&priv->snd_card);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int seeed_voice_card_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct snd_soc_card *card = platform_get_drvdata(pdev);
|
||||||
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(card);
|
||||||
|
|
||||||
|
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
|
||||||
|
}
|
||||||
|
asoc_simple_clean_reference(card);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id seeed_voice_of_match[] = {
|
||||||
|
{ .compatible = "seeed-voicecard", },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, seeed_voice_of_match);
|
||||||
|
|
||||||
|
static struct platform_driver seeed_voice_card = {
|
||||||
|
.driver = {
|
||||||
|
.name = "seeed-voicecard",
|
||||||
|
.pm = &snd_soc_pm_ops,
|
||||||
|
.of_match_table = seeed_voice_of_match,
|
||||||
|
},
|
||||||
|
.probe = seeed_voice_card_probe,
|
||||||
|
.remove = seeed_voice_card_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(seeed_voice_card);
|
||||||
|
|
||||||
|
MODULE_ALIAS("platform:seeed-voice-card");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_DESCRIPTION("ASoC SEEED Voice Card");
|
||||||
|
MODULE_AUTHOR("PeterYang<linsheng.yang@seeed.cc>");
|
12
seeed-voicecard.service
Normal file
12
seeed-voicecard.service
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Seeed Voicecard service
|
||||||
|
After=alsa-restore.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart=/usr/bin/seeed-voicecard
|
||||||
|
User=root
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sysinit.target
|
47
sound-compatible-4.18.h
Normal file
47
sound-compatible-4.18.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* (C) Copyright 2017-2018
|
||||||
|
* Seeed Technology Co., Ltd. <www.seeedstudio.com>
|
||||||
|
*
|
||||||
|
* PeterYang <linsheng.yang@seeed.cc>
|
||||||
|
*/
|
||||||
|
#ifndef __SOUND_COMPATIBLE_4_18_H__
|
||||||
|
#define __SOUND_COMPATIBLE_4_18_H__
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
|
||||||
|
#define __NO_SND_SOC_CODEC_DRV 1
|
||||||
|
#else
|
||||||
|
#define __NO_SND_SOC_CODEC_DRV 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
||||||
|
#if __has_attribute(__fallthrough__)
|
||||||
|
# define fallthrough __attribute__((__fallthrough__))
|
||||||
|
#else
|
||||||
|
# define fallthrough do {} while (0) /* fallthrough */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __NO_SND_SOC_CODEC_DRV
|
||||||
|
#define codec component
|
||||||
|
#define snd_soc_codec snd_soc_component
|
||||||
|
#define snd_soc_codec_driver snd_soc_component_driver
|
||||||
|
#define snd_soc_codec_get_drvdata snd_soc_component_get_drvdata
|
||||||
|
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
|
||||||
|
#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
|
||||||
|
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0)
|
||||||
|
#define snd_soc_read snd_soc_component_read
|
||||||
|
#else
|
||||||
|
#define snd_soc_read snd_soc_component_read32
|
||||||
|
#endif
|
||||||
|
#define snd_soc_register_codec devm_snd_soc_register_component
|
||||||
|
#define snd_soc_unregister_codec snd_soc_unregister_component
|
||||||
|
#define snd_soc_update_bits snd_soc_component_update_bits
|
||||||
|
#define snd_soc_write snd_soc_component_write
|
||||||
|
#define snd_soc_add_codec_controls snd_soc_add_component_controls
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif//__SOUND_COMPATIBLE_4_18_H__
|
||||||
|
|
44
tools/coherence.py
Normal file
44
tools/coherence.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
"""
|
||||||
|
Estimate the magnitude squared coherence estimate,
|
||||||
|
|
||||||
|
- requirements
|
||||||
|
sudo apt install python-numpy python-scipy python-matplotlib
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import wave
|
||||||
|
import numpy as np
|
||||||
|
from scipy import signal
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print('Usage: python {} audio.wav'.format(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
wav = wave.open(sys.argv[1], 'rb')
|
||||||
|
channels = wav.getnchannels()
|
||||||
|
frames = wav.readframes(wav.getnframes())
|
||||||
|
fs = wav.getframerate()
|
||||||
|
wav.close()
|
||||||
|
|
||||||
|
print("channels: %d" % channels)
|
||||||
|
print("rate : %d" % fs)
|
||||||
|
print("frames : %d" % wav.getnframes())
|
||||||
|
|
||||||
|
array = np.fromstring(frames, dtype='int16')
|
||||||
|
|
||||||
|
ch0 = array[0::channels]
|
||||||
|
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
|
||||||
|
for ch in range(1, channels):
|
||||||
|
f, c = signal.coherence(ch0, array[ch::channels], fs, nperseg=1024)
|
||||||
|
ax.semilogy(f, c, label="CO 1-%d" % (ch + 1))
|
||||||
|
|
||||||
|
legend = ax.legend(loc='lower right', shadow=True, fontsize='small')
|
||||||
|
|
||||||
|
plt.xlabel('frequency [Hz]')
|
||||||
|
plt.ylabel('Coherence')
|
||||||
|
plt.show()
|
||||||
|
|
83
tools/phase_test.py
Normal file
83
tools/phase_test.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import sys
|
||||||
|
import wave
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print('Usage: {} multi.wav'.format(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
multi = wave.open(sys.argv[1], 'rb')
|
||||||
|
rate = multi.getframerate()
|
||||||
|
channels = multi.getnchannels()
|
||||||
|
|
||||||
|
if channels <= 1:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
N = rate
|
||||||
|
|
||||||
|
window = np.hanning(N)
|
||||||
|
|
||||||
|
interp = 4*8
|
||||||
|
max_offset = int(rate * 0.1 / 340 * interp)
|
||||||
|
|
||||||
|
def gcc_phat(sig, refsig, fs=1, max_tau=None, interp=16):
|
||||||
|
'''
|
||||||
|
This function computes the offset between the signal sig and the reference signal refsig
|
||||||
|
using the Generalized Cross Correlation - Phase Transform (GCC-PHAT)method.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# make sure the length for the FFT is larger or equal than len(sig) + len(refsig)
|
||||||
|
n = sig.shape[0] + refsig.shape[0]
|
||||||
|
|
||||||
|
# Generalized Cross Correlation Phase Transform
|
||||||
|
SIG = np.fft.rfft(sig, n=n)
|
||||||
|
REFSIG = np.fft.rfft(refsig, n=n)
|
||||||
|
R = SIG * np.conj(REFSIG)
|
||||||
|
#R /= np.abs(R)
|
||||||
|
|
||||||
|
cc = np.fft.irfft(R, n=(interp * n))
|
||||||
|
|
||||||
|
max_shift = int(interp * n / 2)
|
||||||
|
if max_tau:
|
||||||
|
max_shift = np.minimum(int(interp * fs * max_tau), max_shift)
|
||||||
|
|
||||||
|
cc = np.concatenate((cc[-max_shift:], cc[:max_shift+1]))
|
||||||
|
|
||||||
|
# find max cross correlation index
|
||||||
|
shift = np.argmax(np.abs(cc)) - max_shift
|
||||||
|
|
||||||
|
tau = shift / float(interp * fs)
|
||||||
|
|
||||||
|
return tau, cc
|
||||||
|
|
||||||
|
|
||||||
|
print(multi.getsampwidth())
|
||||||
|
|
||||||
|
while True:
|
||||||
|
data = multi.readframes(N)
|
||||||
|
|
||||||
|
if len(data) != multi.getsampwidth() * N * channels:
|
||||||
|
print("done")
|
||||||
|
break
|
||||||
|
|
||||||
|
if multi.getsampwidth() == 2:
|
||||||
|
data = np.fromstring(data, dtype='int16')
|
||||||
|
else:
|
||||||
|
data = np.fromstring(data, dtype='int32')
|
||||||
|
ref_buf = data[0::channels]
|
||||||
|
|
||||||
|
offsets = []
|
||||||
|
for ch in range(1, channels):
|
||||||
|
sig_buf = data[ch::channels]
|
||||||
|
tau, _ = gcc_phat(sig_buf * window, ref_buf * window, fs=1, max_tau=max_offset, interp=interp)
|
||||||
|
# tau, _ = gcc_phat(sig_buf, ref_buf, fs=rate, max_tau=1)
|
||||||
|
|
||||||
|
offsets.append(tau)
|
||||||
|
|
||||||
|
print(offsets)
|
||||||
|
|
||||||
|
print(multi.getframerate())
|
||||||
|
|
||||||
|
multi.close()
|
37
ubuntu-prerequisite.sh
Executable file
37
ubuntu-prerequisite.sh
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) Hin-Tak Leung 2020
|
||||||
|
#
|
||||||
|
# Overview:
|
||||||
|
# This script compiles and install the Broadcom VideoCore tools,
|
||||||
|
# configure the dynamic loader for the non-standard library location,
|
||||||
|
# and update the loader cache.
|
||||||
|
#
|
||||||
|
# A few steps explicitly requires root privilege, which are
|
||||||
|
# marked with "sudo". The rest is just checking for duplicate/previous
|
||||||
|
# action.
|
||||||
|
#
|
||||||
|
# This derived from my command history on ubuntu 20.04.1 .YMMV
|
||||||
|
|
||||||
|
sudo apt install -y git gcc g++ make alsa-utils cmake
|
||||||
|
|
||||||
|
git clone git://github.com/raspberrypi/userland.git
|
||||||
|
pushd userland/
|
||||||
|
|
||||||
|
arch=$(uname -m)
|
||||||
|
if [[ "$arch" =~ aarch64 ]]; then
|
||||||
|
./buildme --aarch64
|
||||||
|
else
|
||||||
|
./buildme
|
||||||
|
fi
|
||||||
|
# ./buildme already includes "sudo make install" at the end
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
# matches Raspbian's location:
|
||||||
|
if [ ! -f /etc/ld.so.conf.d/00-vmcs.conf ] ; then
|
||||||
|
echo "/opt/vc/lib" | sudo tee -a /etc/ld.so.conf.d/00-vmcs.conf
|
||||||
|
sudo ldconfig -v
|
||||||
|
else
|
||||||
|
echo "/etc/ld.so.conf.d/00-vmcs.conf exists - no need to update ld.cache!"
|
||||||
|
fi
|
126
uninstall.sh
126
uninstall.sh
|
@ -12,71 +12,87 @@ if [ "x${is_Raspberry}" != "xRaspberry" ] ; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
uname_r=$(uname -r)
|
uname_r=$(uname -r)
|
||||||
card=$1
|
|
||||||
if [ x${card} = "x" ] ; then
|
|
||||||
echo "Usage: ./uninstall 2mic|4mic"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ x${card} = "x2mic" ] ; then
|
CONFIG=/boot/config.txt
|
||||||
echo "delete dtoverlay=seeed-2mic-voicecard in /boot/config.txt"
|
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
|
||||||
sed -i "s/dtoverlay=seeed-2mic-voicecard//g" /boot/config.txt
|
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
|
||||||
if [ -f /boot/overlays/seeed-2mic-voicecard.dtbo ] ; then
|
|
||||||
echo "remove seeed-2mic-voicecard.dtbo in /boot/overlays"
|
|
||||||
rm /boot/overlays/seeed-2mic-voicecard.dtbo
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f /lib/modules/${uname_r}/kernel/sound/soc/codecs/snd-soc-wm8960.ko ] ; then
|
get_overlay() {
|
||||||
echo "remove snd-soc-wm8960.ko"
|
ov=$1
|
||||||
rm /lib/modules/${uname_r}/kernel/sound/soc/codecs/snd-soc-wm8960.ko
|
if grep -q -E "^dtoverlay=$ov" $CONFIG; then
|
||||||
fi
|
echo 0
|
||||||
|
else
|
||||||
|
echo 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
if [ -d /var/lib/dkms/seeed-voicecard ] ; then
|
do_overlay() {
|
||||||
echo "remove seeed-voicecard dkms"
|
ov=$1
|
||||||
rm -rf /var/lib/dkms/seeed-voicecard
|
RET=$2
|
||||||
fi
|
DEFAULT=--defaultno
|
||||||
|
CURRENT=0
|
||||||
|
if [ $(get_overlay $ov) -eq 0 ]; then
|
||||||
|
DEFAULT=
|
||||||
|
CURRENT=1
|
||||||
|
fi
|
||||||
|
if [ $RET -eq $CURRENT ]; then
|
||||||
|
ASK_TO_REBOOT=1
|
||||||
|
fi
|
||||||
|
if [ $RET -eq 0 ]; then
|
||||||
|
sed $CONFIG -i -e "s/^#dtoverlay=$ov/dtoverlay=$ov/"
|
||||||
|
if ! grep -q -E "^dtoverlay=$ov" $CONFIG; then
|
||||||
|
printf "dtoverlay=$ov\n" >> $CONFIG
|
||||||
|
fi
|
||||||
|
STATUS=enabled
|
||||||
|
elif [ $RET -eq 1 ]; then
|
||||||
|
sed $CONFIG -i -e "s/^dtoverlay=$ov/#dtoverlay=$ov/"
|
||||||
|
STATUS=disabled
|
||||||
|
else
|
||||||
|
return $RET
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
echo "delete snd-soc-wm8960 in /etc/modules"
|
RPI_HATS="seeed-2mic-voicecard seeed-4mic-voicecard seeed-8mic-voicecard"
|
||||||
sed -i "s/snd-soc-wm8960//g" /etc/modules
|
|
||||||
|
|
||||||
if [ -f /var/lib/alsa/asound.state ] ; then
|
PATH=$PATH:/opt/vc/bin
|
||||||
echo "remove wm8960_asound.state"
|
echo "remove dtbos"
|
||||||
rm /var/lib/alsa/asound.state
|
for i in $RPI_HATS; do
|
||||||
fi
|
dtoverlay -r $i
|
||||||
fi
|
done
|
||||||
|
OVERLAYS=/boot/overlays
|
||||||
|
[ -d /boot/firmware/overlays ] && OVERLAYS=/boot/firmware/overlays
|
||||||
|
|
||||||
if [ x${card} = "x4mic" ] ; then
|
rm ${OVERLAYS}/seeed-2mic-voicecard.dtbo || true
|
||||||
echo "delete dtoverlay=seeed-4mic-voicecard in /boot/config.txt"
|
rm ${OVERLAYS}/seeed-4mic-voicecard.dtbo || true
|
||||||
sed -i "s/dtoverlay=seeed-4mic-voicecard//g" /boot/config.txt
|
rm ${OVERLAYS}/seeed-8mic-voicecard.dtbo || true
|
||||||
|
|
||||||
if [ -f /boot/overlays/seeed-4mic-voicecard.dtbo ] ; then
|
|
||||||
echo "remove seeed-4mic-voicecard.dtbo in /boot/overlays"
|
|
||||||
rm /boot/overlays/seeed-4mic-voicecard.dtbo
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f /lib/modules/${uname_r}/kernel/sound/soc/codecs/snd-soc-ac108.ko ] ; then
|
echo "remove alsa configs"
|
||||||
echo "remove snd-soc-ac108.ko"
|
rm -rf /etc/voicecard/ || true
|
||||||
rm /lib/modules/${uname_r}/kernel/sound/soc/codecs/snd-soc-ac108.ko
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d /var/lib/dkms/seeed-voicecard ] ; then
|
echo "disabled seeed-voicecard.service "
|
||||||
echo "remove seeed-voicecard dkms"
|
systemctl stop seeed-voicecard.service
|
||||||
rm -rf /var/lib/dkms/seeed-voicecard
|
systemctl disable seeed-voicecard.service
|
||||||
fi
|
|
||||||
|
|
||||||
echo "delete snd-soc-ac108 in /etc/modules"
|
echo "remove seeed-voicecard"
|
||||||
sed -i "s/snd-soc-ac108//g" /etc/modules
|
rm /usr/bin/seeed-voicecard || true
|
||||||
|
rm /lib/systemd/system/seeed-voicecard.service || true
|
||||||
|
|
||||||
if [ -f /var/lib/alsa/asound.state ] ; then
|
echo "remove dkms"
|
||||||
echo "remove ac108_asound.state"
|
rm -rf /var/lib/dkms/seeed-voicecard || true
|
||||||
rm /var/lib/alsa/asound.state
|
|
||||||
fi
|
echo "remove kernel modules"
|
||||||
|
rm /lib/modules/*/kernel/sound/soc/codecs/snd-soc-wm8960.ko || true
|
||||||
if [ -f /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_ac108.so ] ; then
|
rm /lib/modules/*/kernel/sound/soc/codecs/snd-soc-ac108.ko || true
|
||||||
echo "remove libasound_module_pcm_ac108.so in /usr/lib/arm-linux-gnueabihf/alsa-lib/ "
|
rm /lib/modules/*/kernel/sound/soc/bcm/snd-soc-seeed-voicecard.ko || true
|
||||||
rm /usr/lib/arm-linux-gnueabihf/alsa-lib/libasound_module_pcm_ac108.so
|
rm /lib/modules/*/updates/dkms/snd-soc-wm8960.ko || true
|
||||||
fi
|
rm /lib/modules/*/updates/dkms/snd-soc-ac108.ko || true
|
||||||
fi
|
rm /lib/modules/*/updates/dkms/snd-soc-seeed-voicecard.ko || true
|
||||||
|
|
||||||
|
echo "remove $CONFIG configuration"
|
||||||
|
for i in $RPI_HATS; do
|
||||||
|
echo Uninstall $i ...
|
||||||
|
do_overlay $i 1
|
||||||
|
done
|
||||||
|
|
||||||
echo "------------------------------------------------------"
|
echo "------------------------------------------------------"
|
||||||
echo "Please reboot your raspberry pi to apply all settings"
|
echo "Please reboot your raspberry pi to apply all settings"
|
||||||
|
|
31
wm8960.c
31
wm8960.c
|
@ -25,6 +25,7 @@
|
||||||
#include <sound/initval.h>
|
#include <sound/initval.h>
|
||||||
#include <sound/tlv.h>
|
#include <sound/tlv.h>
|
||||||
#include <sound/wm8960.h>
|
#include <sound/wm8960.h>
|
||||||
|
#include "sound-compatible-4.18.h"
|
||||||
|
|
||||||
#include "wm8960.h"
|
#include "wm8960.h"
|
||||||
|
|
||||||
|
@ -226,10 +227,11 @@ static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
|
||||||
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
|
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
|
||||||
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
|
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
|
||||||
static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);
|
static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);
|
||||||
static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(micboost_tlv,
|
static const DECLARE_TLV_DB_RANGE(micboost_tlv,
|
||||||
0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0),
|
0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0),
|
||||||
2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0),
|
2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
static const struct snd_kcontrol_new wm8960_snd_controls[] = {
|
static const struct snd_kcontrol_new wm8960_snd_controls[] = {
|
||||||
SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
|
SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
|
||||||
|
@ -506,7 +508,11 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
|
||||||
* list each time to find the desired power state do so now
|
* list each time to find the desired power state do so now
|
||||||
* and save the result.
|
* and save the result.
|
||||||
*/
|
*/
|
||||||
|
#if __NO_SND_SOC_CODEC_DRV
|
||||||
|
list_for_each_entry(w, &codec->card->widgets, list) {
|
||||||
|
#else
|
||||||
list_for_each_entry(w, &codec->component.card->widgets, list) {
|
list_for_each_entry(w, &codec->component.card->widgets, list) {
|
||||||
|
#endif
|
||||||
if (w->dapm != dapm)
|
if (w->dapm != dapm)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(w->name, "LOUT1 PGA") == 0)
|
if (strcmp(w->name, "LOUT1 PGA") == 0)
|
||||||
|
@ -747,6 +753,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
|
||||||
iface |= 0x000c;
|
iface |= 0x000c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
fallthrough;
|
||||||
default:
|
default:
|
||||||
dev_err(codec->dev, "unsupported width %d\n",
|
dev_err(codec->dev, "unsupported width %d\n",
|
||||||
params_width(params));
|
params_width(params));
|
||||||
|
@ -789,7 +796,7 @@ static int wm8960_hw_free(struct snd_pcm_substream *substream,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm8960_mute(struct snd_soc_dai *dai, int mute)
|
static int wm8960_mute(struct snd_soc_dai *dai, int mute, int direction)
|
||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = dai->codec;
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
|
|
||||||
|
@ -1229,11 +1236,12 @@ static int wm8960_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
||||||
static const struct snd_soc_dai_ops wm8960_dai_ops = {
|
static const struct snd_soc_dai_ops wm8960_dai_ops = {
|
||||||
.hw_params = wm8960_hw_params,
|
.hw_params = wm8960_hw_params,
|
||||||
.hw_free = wm8960_hw_free,
|
.hw_free = wm8960_hw_free,
|
||||||
.digital_mute = wm8960_mute,
|
.mute_stream = wm8960_mute,
|
||||||
.set_fmt = wm8960_set_dai_fmt,
|
.set_fmt = wm8960_set_dai_fmt,
|
||||||
.set_clkdiv = wm8960_set_dai_clkdiv,
|
.set_clkdiv = wm8960_set_dai_clkdiv,
|
||||||
.set_pll = wm8960_set_dai_pll,
|
.set_pll = wm8960_set_dai_pll,
|
||||||
.set_sysclk = wm8960_set_dai_sysclk,
|
.set_sysclk = wm8960_set_dai_sysclk,
|
||||||
|
.no_capture_mute = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_driver wm8960_dai = {
|
static struct snd_soc_dai_driver wm8960_dai = {
|
||||||
|
@ -1251,7 +1259,11 @@ static struct snd_soc_dai_driver wm8960_dai = {
|
||||||
.rates = WM8960_RATES,
|
.rates = WM8960_RATES,
|
||||||
.formats = WM8960_FORMATS,},
|
.formats = WM8960_FORMATS,},
|
||||||
.ops = &wm8960_dai_ops,
|
.ops = &wm8960_dai_ops,
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
|
||||||
|
.symmetric_rate = 1,
|
||||||
|
#else
|
||||||
.symmetric_rates = 1,
|
.symmetric_rates = 1,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int wm8960_probe(struct snd_soc_codec *codec)
|
static int wm8960_probe(struct snd_soc_codec *codec)
|
||||||
|
@ -1274,7 +1286,12 @@ static int wm8960_probe(struct snd_soc_codec *codec)
|
||||||
static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
|
static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
|
||||||
.probe = wm8960_probe,
|
.probe = wm8960_probe,
|
||||||
.set_bias_level = wm8960_set_bias_level,
|
.set_bias_level = wm8960_set_bias_level,
|
||||||
.suspend_bias_off = true,
|
.suspend_bias_off = true,
|
||||||
|
#if __NO_SND_SOC_CODEC_DRV
|
||||||
|
.idle_bias_on = 1,
|
||||||
|
.use_pmdown_time = 1,
|
||||||
|
.endianness = 1,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct regmap_config wm8960_regmap = {
|
static const struct regmap_config wm8960_regmap = {
|
||||||
|
@ -1301,8 +1318,7 @@ static void wm8960_set_pdata_from_of(struct i2c_client *i2c,
|
||||||
pdata->shared_lrclk = true;
|
pdata->shared_lrclk = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm8960_i2c_probe(struct i2c_client *i2c,
|
static int wm8960_i2c_probe(struct i2c_client *i2c)
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
{
|
||||||
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
|
struct wm8960_data *pdata = dev_get_platdata(&i2c->dev);
|
||||||
struct wm8960_priv *wm8960;
|
struct wm8960_priv *wm8960;
|
||||||
|
@ -1367,10 +1383,9 @@ static int wm8960_i2c_probe(struct i2c_client *i2c,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm8960_i2c_remove(struct i2c_client *client)
|
static void wm8960_i2c_remove(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
snd_soc_unregister_codec(&client->dev);
|
snd_soc_unregister_codec(&client->dev);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id wm8960_i2c_id[] = {
|
static const struct i2c_device_id wm8960_i2c_id[] = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue