Compare commits
35 commits
v6.6-order
...
v5.4
Author | SHA1 | Date | |
---|---|---|---|
|
f8abf23b1e | ||
|
b380ebfb26 | ||
|
5c9e04cd57 | ||
|
c236752f91 | ||
|
85160dac38 | ||
|
d9fdfac988 | ||
|
5c311c4031 | ||
|
0248378f7f | ||
|
fc77a4c00a | ||
|
7e4917be89 | ||
|
f512fe32bd | ||
|
99b29b06c1 | ||
|
37cd69fc1a | ||
|
408f71d2f4 | ||
|
cddfe7b15e | ||
|
f4cb786a5b | ||
|
115186c53c | ||
|
4e29eb8f51 | ||
|
de0e478df4 | ||
|
f716cece88 | ||
|
7958dd2076 | ||
|
64a207940f | ||
|
35bc08973c | ||
|
bafb3c85aa | ||
|
556ed21066 | ||
|
f4cc5722d0 | ||
|
49f1135da8 | ||
|
6244e5d618 | ||
|
5ce09f2095 | ||
|
140a220946 | ||
|
31bea0c3be | ||
|
b80f7bc89b | ||
|
6f03b0df86 | ||
|
26cfab95cf | ||
|
8497972d65 |
15 changed files with 339 additions and 1070 deletions
259
README.md
259
README.md
|
@ -1,20 +1,247 @@
|
||||||
# seeed-voicecard
|
# seeed-voicecard
|
||||||
|
|
||||||
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.
|
[![Join the chat at https://gitter.im/seeed-voicecard/Lobby](https://badges.gitter.im/seeed-voicecard/Lobby.svg)](https://gitter.im/seeed-voicecard/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
|
The drivers of [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.
|
||||||
|
|
||||||
### Install seeed-voicecard
|
### Install seeed-voicecard
|
||||||
Get the seeed voice card source code and install all linux kernel drivers
|
Get the seeed voice card source code. and install all linux kernel drivers
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/HinTak/seeed-voicecard
|
git clone https://github.com/respeaker/seeed-voicecard
|
||||||
cd seeed-voicecard
|
cd seeed-voicecard
|
||||||
sudo ./install.sh
|
sudo ./install.sh
|
||||||
sudo reboot
|
sudo reboot
|
||||||
```
|
```
|
||||||
## ReSpeaker Documentation
|
It may probably happen that the driver won't compile with the latest kernel when raspbian rolls out new patches to the kernel. If so, please try `sudo ./install.sh --compat-kernel` which uses an older kernel but ensures that the driver can work.
|
||||||
|
|
||||||
Up to date documentation for reSpeaker products can be found in [Seeed Studio Wiki](https://wiki.seeedstudio.com/ReSpeaker/)!
|
## ReSpeaker Mic Hat
|
||||||
![](https://files.seeedstudio.com/wiki/ReSpeakerProductGuide/img/Raspberry_Pi_Mic_Array_Solutions.png)
|
|
||||||
|
|
||||||
|
[![](https://github.com/SeeedDocument/MIC_HATv1.0_for_raspberrypi/blob/master/img/mic_hatv1.0.png?raw=true)](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.
|
||||||
|
|
||||||
|
Check that the sound card name matches the source code seeed-voicecard.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#for ReSpeaker 2-mic
|
||||||
|
pi@raspberrypi:~/seeed-voicecard $ aplay -l
|
||||||
|
**** List of PLAYBACK Hardware Devices ****
|
||||||
|
card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
|
||||||
|
Subdevices: 8/8
|
||||||
|
Subdevice #0: subdevice #0
|
||||||
|
Subdevice #1: subdevice #1
|
||||||
|
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 $
|
||||||
|
```
|
||||||
|
If you want to change the alsa settings, You can use `sudo alsactl --file=/etc/voicecard/wm8960_asound.state store` to save it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 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://github.com/SeeedDocument/ReSpeaker-4-Mic-Array-for-Raspberry-Pi/blob/master/img/features.png?raw=true)](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.
|
||||||
|
|
||||||
|
Check that the sound card name matches the source code seeed-voicecard.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#for ReSpeaker 4 Mic Array
|
||||||
|
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=/etc/voicecard/ac108_asound.state store` to save it.
|
||||||
|
|
||||||
|
## 6-Mics Circular Array Kit
|
||||||
|
|
||||||
|
[![](https://user-images.githubusercontent.com/3901856/37268348-6adef768-2600-11e8-8861-588b1c3ea142.png)]()
|
||||||
|
|
||||||
|
The 6 Mics Circular Array Kit uses ac108 x 2 / ac101 x 1 / micphones x 6, includes 8 ADCs and 2 DACs.
|
||||||
|
|
||||||
|
The driver is implemented with 8 input channels & 8 output channels.
|
||||||
|
>**The first 6 input channel are MIC recording data,
|
||||||
|
the rest 2 input channel are echo channel of playback
|
||||||
|
The first 2 output channel are playing data, the rest 6 output channel are dummy**
|
||||||
|
|
||||||
|
|
||||||
|
Check that the sound card name matches the source code seeed-voicecard.
|
||||||
|
```bash
|
||||||
|
#for 6 Mic Circular Array
|
||||||
|
pi@raspberrypi:~ $ arecord -L
|
||||||
|
null
|
||||||
|
Discard all samples (playback) or generate zero samples (capture)
|
||||||
|
default
|
||||||
|
playback
|
||||||
|
dmixed
|
||||||
|
ac108
|
||||||
|
multiapps
|
||||||
|
ac101
|
||||||
|
sysdefault:CARD=seeed8micvoicec
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Default Audio Device
|
||||||
|
dmix:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Direct sample mixing device
|
||||||
|
dsnoop:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Direct sample snooping device
|
||||||
|
hw:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Direct hardware device without any conversions
|
||||||
|
plughw:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Hardware device with all software conversions
|
||||||
|
|
||||||
|
pi@raspberrypi:~ $ aplay -L
|
||||||
|
null
|
||||||
|
Discard all samples (playback) or generate zero samples (capture)
|
||||||
|
default
|
||||||
|
playback
|
||||||
|
dmixed
|
||||||
|
ac108
|
||||||
|
multiapps
|
||||||
|
ac101
|
||||||
|
sysdefault:CARD=ALSA
|
||||||
|
bcm2835 ALSA, bcm2835 ALSA
|
||||||
|
Default Audio Device
|
||||||
|
dmix:CARD=ALSA,DEV=0
|
||||||
|
bcm2835 ALSA, bcm2835 ALSA
|
||||||
|
Direct sample mixing device
|
||||||
|
dmix:CARD=ALSA,DEV=1
|
||||||
|
bcm2835 ALSA, bcm2835 IEC958/HDMI
|
||||||
|
Direct sample mixing device
|
||||||
|
dsnoop:CARD=ALSA,DEV=0
|
||||||
|
bcm2835 ALSA, bcm2835 ALSA
|
||||||
|
Direct sample snooping device
|
||||||
|
dsnoop:CARD=ALSA,DEV=1
|
||||||
|
bcm2835 ALSA, bcm2835 IEC958/HDMI
|
||||||
|
Direct sample snooping device
|
||||||
|
hw:CARD=ALSA,DEV=0
|
||||||
|
bcm2835 ALSA, bcm2835 ALSA
|
||||||
|
Direct hardware device without any conversions
|
||||||
|
hw:CARD=ALSA,DEV=1
|
||||||
|
bcm2835 ALSA, bcm2835 IEC958/HDMI
|
||||||
|
Direct hardware device without any conversions
|
||||||
|
plughw:CARD=ALSA,DEV=0
|
||||||
|
bcm2835 ALSA, bcm2835 ALSA
|
||||||
|
Hardware device with all software conversions
|
||||||
|
plughw:CARD=ALSA,DEV=1
|
||||||
|
bcm2835 ALSA, bcm2835 IEC958/HDMI
|
||||||
|
Hardware device with all software conversions
|
||||||
|
sysdefault:CARD=seeed8micvoicec
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Default Audio Device
|
||||||
|
dmix:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Direct sample mixing device
|
||||||
|
dsnoop:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Direct sample snooping device
|
||||||
|
hw:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Direct hardware device without any conversions
|
||||||
|
plughw:CARD=seeed8micvoicec,DEV=0
|
||||||
|
seeed-8mic-voicecard,
|
||||||
|
Hardware device with all software conversions
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4-Mics Linear Array Kit
|
||||||
|
|
||||||
|
[![](https://user-images.githubusercontent.com/3901856/37194106-a0ccebce-23a7-11e8-88c5-ec611e44ec49.png)]()
|
||||||
|
|
||||||
|
In contrast to 6-Mics Circular Array Kit for Raspberry Pi,
|
||||||
|
the difference is only first 4 input channels are valid capture data.
|
||||||
|
|
||||||
|
|
||||||
|
### Usage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#Query sound card number
|
||||||
|
# The sound card number used as arecord/aplay argument,
|
||||||
|
# ( like '-D hw:N' and '-D plughw:N', where N is the number )
|
||||||
|
# could be found by command:
|
||||||
|
aplay -l
|
||||||
|
#or
|
||||||
|
arecord -l
|
||||||
|
# Find the line in the command output which near below form:
|
||||||
|
card 1: seeed2micvoicec [seeed-2mic-voicecard], device 0: ...
|
||||||
|
# The number between first word `card` and char `:` is the Sound Card Number, here it's 1.
|
||||||
|
```
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#for 6-Mics Circular Array Kit and 4-Mics Linear Array Kit
|
||||||
|
#It will capture sound on AC108 and save as a.wav
|
||||||
|
arecord -Dac108 -f S32_LE -r 16000 -c 8 a.wav
|
||||||
|
#Take care of that the captured mic audio is on the first 6 channels
|
||||||
|
|
||||||
|
#It will play a mono channel sound file mono_to_play.wav
|
||||||
|
#The file to play must be mono channel or else the speaker output nothing.
|
||||||
|
aplay -D plughw:1,0 mono_to_play.wav
|
||||||
|
|
||||||
|
#Doing capture && playback the same time
|
||||||
|
arecord -D hw:1,0 -f S32_LE -r 16000 -c 8 to_be_record.wav &
|
||||||
|
#mono_to_play.wav is a mono channel wave file to play
|
||||||
|
aplay -D plughw:1,0 -r 16000 mono_to_play.wav
|
||||||
|
```
|
||||||
|
**Note: Limit for developer using 6-Mics Circular Array Kit(or 4-Mics Linear Array Kit) doing capture & playback the same time:
|
||||||
|
1. capture must be start first, or else the capture channels will possibly be disorder.
|
||||||
|
2. playback output channels must fill with 8 same channels data or 4 same stereo channels data, or else the speaker or headphone will output nothing possibly.**
|
||||||
|
|
||||||
### Coherence
|
### Coherence
|
||||||
|
|
||||||
|
@ -44,21 +271,13 @@ Thank you!
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Enjoy !
|
Enjoy !
|
||||||
|
|
||||||
### Technical support
|
### FAQ
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
|
When you encounter any installation and use problems when you start your ReSpeaker Pi hat, please use the following image for testing. We have installed seeed-voicecard based on the latest PI image, which can be used by burning it directly on SD. If this still cannot solve your problem, you can ask in the issue. We will try our best to solve your problem.
|
||||||
|
|
||||||
|
<p style="text-align:center"><a href="https://v2.fangcloud.com/share/7395fd138a1cab496fd4792fe5" target="_blank"><img src="https://github.com/SeeedDocument/Respeaker_V2/raw/master/img/efangyun.png" width="200" height="40" border=0 /></a></p>
|
||||||
|
|
15
ac101.c
15
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",
|
AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n",
|
||||||
snd_pcm_stream_str(substream),
|
snd_pcm_stream_str(substream),
|
||||||
codec_dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active,
|
codec_dai->playback_active, codec_dai->capture_active,
|
||||||
snd_soc_dai_active(codec_dai));
|
codec_dai->active);
|
||||||
|
|
||||||
if (!snd_soc_dai_active(codec_dai)) {
|
if (!codec_dai->active) {
|
||||||
ac10x->aif1_clken = 1;
|
ac10x->aif1_clken = 1;
|
||||||
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
|
ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1080,7 +1080,7 @@ int ac101_hw_params(struct snd_pcm_substream *substream,
|
||||||
freq_out = _FREQ_24_576K;
|
freq_out = _FREQ_24_576K;
|
||||||
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
|
for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
|
||||||
if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
|
if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
|
||||||
if (codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && 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));
|
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), (0x4<<AIF1_FS));
|
||||||
} else {
|
} else {
|
||||||
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
|
ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS), ((codec_aif1_fs[i].srbit)<<AIF1_FS));
|
||||||
|
@ -1237,7 +1237,7 @@ int ac101_audio_startup(struct snd_pcm_substream *substream,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if _MASTER_MULTI_CODEC == _MASTER_AC101
|
#if _MASTER_MULTI_CODEC == _MASTER_AC101
|
||||||
static int ac101_set_clock(int y_start_n_stop, struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) {
|
static int ac101_set_clock(int y_start_n_stop) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (y_start_n_stop) {
|
if (y_start_n_stop) {
|
||||||
|
@ -1258,7 +1258,6 @@ int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
struct snd_soc_codec *codec = dai->codec;
|
struct snd_soc_codec *codec = dai->codec;
|
||||||
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
AC101_DBG("stream=%s cmd=%d\n",
|
AC101_DBG("stream=%s cmd=%d\n",
|
||||||
snd_pcm_stream_str(substream),
|
snd_pcm_stream_str(substream),
|
||||||
|
@ -1269,7 +1268,6 @@ int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
#if _MASTER_MULTI_CODEC == _MASTER_AC101
|
#if _MASTER_MULTI_CODEC == _MASTER_AC101
|
||||||
spin_lock_irqsave(&ac10x->lock, flags);
|
|
||||||
if (ac10x->aif1_clken == 0){
|
if (ac10x->aif1_clken == 0){
|
||||||
/*
|
/*
|
||||||
* enable aif1clk, it' here due to reduce time between 'AC108 Sysclk Enable' and 'AC101 Sysclk Enable'
|
* enable aif1clk, it' here due to reduce time between 'AC108 Sysclk Enable' and 'AC101 Sysclk Enable'
|
||||||
|
@ -1279,14 +1277,11 @@ int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1), (0x1<<MOD_CLK_AIF1));
|
ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1), (0x1<<MOD_CLK_AIF1));
|
||||||
ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x1<<MOD_RESET_AIF1));
|
ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x1<<MOD_RESET_AIF1));
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&ac10x->lock, flags);
|
|
||||||
ac101_set_clock(1, substream, cmd, dai);
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
ac101_set_clock(0, NULL, 0, NULL);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
|
64
ac108.c
64
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__,
|
dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
|
||||||
snd_pcm_stream_str(substream),
|
snd_pcm_stream_str(substream),
|
||||||
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
|
dai->playback_active, dai->capture_active);
|
||||||
|
|
||||||
if (ac10x->i2c101) {
|
if (ac10x->i2c101) {
|
||||||
ret = ac101_hw_params(substream, params, dai);
|
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[SNDRV_PCM_STREAM_PLAYBACK].active)
|
if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE && dai->playback_active)
|
||||||
|| (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream[SNDRV_PCM_STREAM_CAPTURE].active)) {
|
|| (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->capture_active)) {
|
||||||
/* not configure hw_param twice */
|
/* not configure hw_param twice */
|
||||||
/* return 0; */
|
/* return 0; */
|
||||||
}
|
}
|
||||||
|
@ -991,7 +991,7 @@ static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) {
|
||||||
/*
|
/*
|
||||||
* due to miss channels order in cpu_dai, we meed defer the clock starting.
|
* due to miss channels order in cpu_dai, we meed defer the clock starting.
|
||||||
*/
|
*/
|
||||||
static int ac108_set_clock(int y_start_n_stop, struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) {
|
static int ac108_set_clock(int y_start_n_stop) {
|
||||||
u8 reg;
|
u8 reg;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -999,9 +999,6 @@ static int ac108_set_clock(int y_start_n_stop, struct snd_pcm_substream *substre
|
||||||
|
|
||||||
/* spin_lock move to machine trigger */
|
/* spin_lock move to machine trigger */
|
||||||
|
|
||||||
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
|
|
||||||
ac101_trigger(substream, cmd, dai);
|
|
||||||
}
|
|
||||||
if (y_start_n_stop && ac10x->sysclk_en == 0) {
|
if (y_start_n_stop && ac10x->sysclk_en == 0) {
|
||||||
/* enable lrck clock */
|
/* enable lrck clock */
|
||||||
ac10x_read(I2S_CTRL, ®, ac10x->i2cmap[_MASTER_INDEX]);
|
ac10x_read(I2S_CTRL, ®, ac10x->i2cmap[_MASTER_INDEX]);
|
||||||
|
@ -1061,29 +1058,39 @@ static int ac108_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||||
snd_pcm_stream_str(substream),
|
snd_pcm_stream_str(substream),
|
||||||
cmd);
|
cmd);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ac10x->lock, flags);
|
||||||
|
|
||||||
|
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
|
||||||
|
ac101_trigger(substream, cmd, dai);
|
||||||
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
|
goto __ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
case SNDRV_PCM_TRIGGER_RESUME:
|
case SNDRV_PCM_TRIGGER_RESUME:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||||
spin_lock_irqsave(&ac10x->lock, flags);
|
|
||||||
/* disable global clock if lrck disabled */
|
/* disable global clock if lrck disabled */
|
||||||
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
|
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
|
||||||
if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
|
if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
|
||||||
/* disable global clock */
|
/* disable global clock */
|
||||||
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x0 << TXEN | 0x0 << GEN, ac10x);
|
ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN, 0x0 << TXEN | 0x0 << GEN, ac10x);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&ac10x->lock, flags);
|
|
||||||
ac108_set_clock(1, substream, cmd, dai);
|
/* delayed clock starting, move to machine trigger() */
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
ac108_set_clock(0, substream, cmd, dai);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__ret:
|
||||||
|
spin_unlock_irqrestore(&ac10x->lock, flags);
|
||||||
|
|
||||||
dev_dbg(dai->dev, "%s() stream=%s cmd=%d; finished %d\n",
|
dev_dbg(dai->dev, "%s() stream=%s cmd=%d; finished %d\n",
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
snd_pcm_stream_str(substream),
|
snd_pcm_stream_str(substream),
|
||||||
|
@ -1121,7 +1128,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 snd_soc_codec *codec = dai->codec;
|
||||||
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
|
||||||
|
|
||||||
|
@ -1142,13 +1149,12 @@ static const struct snd_soc_dai_ops ac108_dai_ops = {
|
||||||
.hw_params = ac108_hw_params,
|
.hw_params = ac108_hw_params,
|
||||||
.prepare = ac108_prepare,
|
.prepare = ac108_prepare,
|
||||||
.trigger = ac108_trigger,
|
.trigger = ac108_trigger,
|
||||||
.mute_stream = ac108_aif_mute,
|
.digital_mute = ac108_aif_mute,
|
||||||
|
|
||||||
/*DAI format configuration*/
|
/*DAI format configuration*/
|
||||||
.set_fmt = ac108_set_fmt,
|
.set_fmt = ac108_set_fmt,
|
||||||
|
|
||||||
// .hw_free = ac108_hw_free,
|
// .hw_free = ac108_hw_free,
|
||||||
.no_capture_mute = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_driver ac108_dai0 = {
|
static struct snd_soc_dai_driver ac108_dai0 = {
|
||||||
|
@ -1322,11 +1328,6 @@ static struct snd_soc_codec_driver ac10x_soc_codec_driver = {
|
||||||
.set_bias_level = ac108_set_bias_level,
|
.set_bias_level = ac108_set_bias_level,
|
||||||
.read = ac108_codec_read,
|
.read = ac108_codec_read,
|
||||||
.write = ac108_codec_write,
|
.write = ac108_codec_write,
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
|
|
||||||
.idle_bias_on = 1,
|
|
||||||
.use_pmdown_time = 1,
|
|
||||||
.endianness = 1,
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t ac108_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
|
static ssize_t ac108_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
|
||||||
|
@ -1407,15 +1408,7 @@ static const struct regmap_config ac108_regmap = {
|
||||||
.max_register = 0xDF,
|
.max_register = 0xDF,
|
||||||
.cache_type = REGCACHE_FLAT,
|
.cache_type = REGCACHE_FLAT,
|
||||||
};
|
};
|
||||||
static const struct i2c_device_id ac108_i2c_id[] = {
|
static int ac108_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) {
|
||||||
{ "ac108_0", 0 },
|
|
||||||
{ "ac108_1", 1 },
|
|
||||||
{ "ac108_2", 2 },
|
|
||||||
{ "ac108_3", 3 },
|
|
||||||
{ "ac101", AC101_I2C_ID },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
static int ac108_i2c_probe(struct i2c_client *i2c) {
|
|
||||||
struct device_node *np = i2c->dev.of_node;
|
struct device_node *np = i2c->dev.of_node;
|
||||||
unsigned int val = 0;
|
unsigned int val = 0;
|
||||||
int ret = 0, index;
|
int ret = 0, index;
|
||||||
|
@ -1428,11 +1421,11 @@ static int ac108_i2c_probe(struct i2c_client *i2c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index = (int)i2c_match_id(ac108_i2c_id, i2c)->driver_data;
|
index = (int)i2c_id->driver_data;
|
||||||
if (index == AC101_I2C_ID) {
|
if (index == AC101_I2C_ID) {
|
||||||
ac10x->i2c101 = i2c;
|
ac10x->i2c101 = i2c;
|
||||||
i2c_set_clientdata(i2c, ac10x);
|
i2c_set_clientdata(i2c, ac10x);
|
||||||
ret = ac101_probe(i2c, i2c_match_id(ac108_i2c_id, i2c));
|
ret = ac101_probe(i2c, i2c_id);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ac10x->i2c101 = NULL;
|
ac10x->i2c101 = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1498,7 +1491,7 @@ __ret:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ac108_i2c_remove(struct i2c_client *i2c) {
|
static int ac108_i2c_remove(struct i2c_client *i2c) {
|
||||||
if (ac10x->codec != NULL) {
|
if (ac10x->codec != NULL) {
|
||||||
snd_soc_unregister_codec(&ac10x->i2c[_MASTER_INDEX]->dev);
|
snd_soc_unregister_codec(&ac10x->i2c[_MASTER_INDEX]->dev);
|
||||||
ac10x->codec = NULL;
|
ac10x->codec = NULL;
|
||||||
|
@ -1523,8 +1516,17 @@ __ret:
|
||||||
kfree(ac10x);
|
kfree(ac10x);
|
||||||
ac10x = NULL;
|
ac10x = NULL;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id ac108_i2c_id[] = {
|
||||||
|
{ "ac108_0", 0 },
|
||||||
|
{ "ac108_1", 1 },
|
||||||
|
{ "ac108_2", 2 },
|
||||||
|
{ "ac108_3", 3 },
|
||||||
|
{ "ac101", AC101_I2C_ID },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, ac108_i2c_id);
|
MODULE_DEVICE_TABLE(i2c, ac108_i2c_id);
|
||||||
|
|
||||||
static const struct of_device_id ac108_of_match[] = {
|
static const struct of_device_id ac108_of_match[] = {
|
||||||
|
|
2
ac10x.h
2
ac10x.h
|
@ -119,7 +119,7 @@ void ac101_shutdown(struct i2c_client *i2c);
|
||||||
int ac101_remove(struct i2c_client *i2c);
|
int ac101_remove(struct i2c_client *i2c);
|
||||||
|
|
||||||
/* seeed voice card export */
|
/* 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 seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int));
|
||||||
|
|
||||||
int ac10x_fill_regcache(struct device* dev, struct regmap* map);
|
int ac10x_fill_regcache(struct device* dev, struct regmap* map);
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,4 @@ 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"
|
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"
|
||||||
|
|
19
install.sh
19
install.sh
|
@ -26,7 +26,7 @@ fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# make sure that we are on something ARM/Raspberry related
|
# make sure that we are on something ARM/Raspberry related
|
||||||
# either a bare metal Raspberry or a qemu session with
|
# either a bare metal Raspberry or a qemu session with
|
||||||
# Raspberry stuff available
|
# Raspberry stuff available
|
||||||
# - check for /boot/overlays
|
# - check for /boot/overlays
|
||||||
# - dtparam and dtoverlay is available
|
# - dtparam and dtoverlay is available
|
||||||
|
@ -67,10 +67,8 @@ function get_kernel_version() {
|
||||||
[ -z "$_VER_RUN" ] && {
|
[ -z "$_VER_RUN" ] && {
|
||||||
ZIMAGE=/boot/kernel.img
|
ZIMAGE=/boot/kernel.img
|
||||||
[ -f /boot/firmware/vmlinuz ] && ZIMAGE=/boot/firmware/vmlinuz
|
[ -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)
|
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; }')
|
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | strings | awk '{ print $3; }')
|
||||||
}
|
}
|
||||||
echo "$_VER_RUN"
|
echo "$_VER_RUN"
|
||||||
return 0
|
return 0
|
||||||
|
@ -78,11 +76,11 @@ function get_kernel_version() {
|
||||||
|
|
||||||
function check_kernel_headers() {
|
function check_kernel_headers() {
|
||||||
VER_RUN=$(get_kernel_version)
|
VER_RUN=$(get_kernel_version)
|
||||||
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
|
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^-]+/build" | awk -F'/' '{ print $4; }')
|
||||||
[ "X$VER_RUN" == "X$VER_HDR" ] && {
|
[ "X$VER_RUN" == "X$VER_HDR" ] && {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
|
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[[:print:]]+/build" | awk -F'/' '{ print $4; }')
|
||||||
[ "X$VER_RUN" == "X$VER_HDR" ] && {
|
[ "X$VER_RUN" == "X$VER_HDR" ] && {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -107,9 +105,7 @@ which apt &>/dev/null
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
apt update -y
|
apt update -y
|
||||||
# Raspbian kernel packages
|
# Raspbian kernel packages
|
||||||
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
|
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
|
# Ubuntu kernel packages
|
||||||
apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi
|
apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi
|
||||||
apt-get -y install dkms git i2c-tools libasound2-plugins
|
apt-get -y install dkms git i2c-tools libasound2-plugins
|
||||||
|
@ -177,11 +173,10 @@ grep -q "^snd-soc-seeed-voicecard$" /etc/modules || \
|
||||||
grep -q "^snd-soc-ac108$" /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
|
#set dtoverlays
|
||||||
CONFIG=/boot/config.txt
|
CONFIG=/boot/config.txt
|
||||||
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
|
|
||||||
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.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
|
sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' $CONFIG || true
|
||||||
|
@ -214,7 +209,7 @@ git --git-dir=/etc/voicecard/.git --work-tree=/etc/voicecard/ commit -m "origin
|
||||||
|
|
||||||
cp seeed-voicecard /usr/bin/
|
cp seeed-voicecard /usr/bin/
|
||||||
cp seeed-voicecard.service /lib/systemd/system/
|
cp seeed-voicecard.service /lib/systemd/system/
|
||||||
systemctl enable seeed-voicecard.service
|
systemctl enable seeed-voicecard.service
|
||||||
systemctl start seeed-voicecard
|
systemctl start seeed-voicecard
|
||||||
|
|
||||||
echo "------------------------------------------------------"
|
echo "------------------------------------------------------"
|
||||||
|
|
|
@ -1,454 +0,0 @@
|
||||||
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 = {
|
|
|
@ -1,245 +0,0 @@
|
||||||
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 = {
|
|
|
@ -1,71 +0,0 @@
|
||||||
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 = {
|
|
|
@ -42,9 +42,7 @@ function get_kernel_version() {
|
||||||
[ -z "$_VER_RUN" ] && {
|
[ -z "$_VER_RUN" ] && {
|
||||||
ZIMAGE=/boot/kernel.img
|
ZIMAGE=/boot/kernel.img
|
||||||
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
|
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
|
||||||
# 64-bit-only kernel package
|
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) | zcat | grep -a -m1 "Linux version" | strings | awk '{ print $3; }')
|
||||||
[ ! -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"
|
echo "$_VER_RUN"
|
||||||
return 0
|
return 0
|
||||||
|
@ -132,10 +130,10 @@ if [ "$overlay" ]; then
|
||||||
if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then
|
if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then
|
||||||
for i in $RPI_HATS; do
|
for i in $RPI_HATS; do
|
||||||
if [ "$i" == "$overlay" ]; then
|
if [ "$i" == "$overlay" ]; then
|
||||||
/bin/true #do_overlay $overlay 0
|
do_overlay $overlay 0
|
||||||
else
|
else
|
||||||
echo Uninstall $i ...
|
echo Uninstall $i ...
|
||||||
/bin/true #do_overlay $i 1
|
do_overlay $i 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -30,20 +30,6 @@
|
||||||
|
|
||||||
#define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3))
|
#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:
|
* single codec:
|
||||||
* 0 - allow multi codec
|
* 0 - allow multi codec
|
||||||
|
@ -86,7 +72,6 @@ struct seeed_card_info {
|
||||||
struct asoc_simple_dai codec_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_dev(priv) ((priv)->snd_card.dev)
|
||||||
#define seeed_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
|
#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 seeed_priv_to_props(priv, i) ((priv)->dai_props + (i))
|
||||||
|
@ -111,16 +96,16 @@ static int seeed_voice_card_startup(struct snd_pcm_substream *substream)
|
||||||
if (ret)
|
if (ret)
|
||||||
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
if (asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min) {
|
if (rtd->cpu_dai->driver->playback.channels_min) {
|
||||||
priv->channels_playback_default = asoc_rtd_to_cpu(rtd, 0)->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) {
|
if (rtd->cpu_dai->driver->capture.channels_min) {
|
||||||
priv->channels_capture_default = asoc_rtd_to_cpu(rtd, 0)->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;
|
rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_override;
|
||||||
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_override;
|
rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_override;
|
||||||
asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_override;
|
rtd->cpu_dai->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->capture.channels_max = priv->channels_capture_override;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -132,10 +117,10 @@ static void seeed_voice_card_shutdown(struct snd_pcm_substream *substream)
|
||||||
struct seeed_dai_props *dai_props =
|
struct seeed_dai_props *dai_props =
|
||||||
seeed_priv_to_props(priv, rtd->num);
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
|
||||||
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_min = priv->channels_playback_default;
|
rtd->cpu_dai->driver->playback.channels_min = priv->channels_playback_default;
|
||||||
asoc_rtd_to_cpu(rtd, 0)->driver->playback.channels_max = priv->channels_playback_default;
|
rtd->cpu_dai->driver->playback.channels_max = priv->channels_playback_default;
|
||||||
asoc_rtd_to_cpu(rtd, 0)->driver->capture.channels_min = priv->channels_capture_default;
|
rtd->cpu_dai->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->capture.channels_max = priv->channels_capture_default;
|
||||||
|
|
||||||
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
clk_disable_unprepare(dai_props->cpu_dai.clk);
|
||||||
|
|
||||||
|
@ -146,8 +131,8 @@ static int seeed_voice_card_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_pcm_hw_params *params)
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
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 *codec_dai = rtd->codec_dai;
|
||||||
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
|
||||||
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
struct seeed_dai_props *dai_props =
|
struct seeed_dai_props *dai_props =
|
||||||
seeed_priv_to_props(priv, rtd->num);
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
|
@ -177,9 +162,9 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _SET_CLOCK_CNT 2
|
#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);
|
static int (* _set_clock[_SET_CLOCK_CNT])(int y_start_n_stop);
|
||||||
|
|
||||||
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int, struct snd_pcm_substream *, int, struct snd_soc_dai *)) {
|
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int)) {
|
||||||
if (! _set_clock[stream]) {
|
if (! _set_clock[stream]) {
|
||||||
_set_clock[stream] = set_clock;
|
_set_clock[stream] = set_clock;
|
||||||
}
|
}
|
||||||
|
@ -196,10 +181,10 @@ static void work_cb_codec_clk(struct work_struct *work)
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) {
|
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 */
|
r = r || _set_clock[SNDRV_PCM_STREAM_CAPTURE](0);
|
||||||
}
|
}
|
||||||
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) {
|
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 */
|
r = r || _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r && priv->try_stop++ < TRY_STOP_MAX) {
|
if (r && priv->try_stop++ < TRY_STOP_MAX) {
|
||||||
|
@ -211,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)
|
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_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);
|
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
|
||||||
#if CONFIG_AC10X_TRIG_LOCK
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -220,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",
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d\n",
|
||||||
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
|
dai->playback_active, dai->capture_active);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
@ -231,8 +216,8 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
/* I know it will degrades performance, but I have no choice */
|
/* I know it will degrades performance, but I have no choice */
|
||||||
spin_lock_irqsave(&priv->lock, flags);
|
spin_lock_irqsave(&priv->lock, flags);
|
||||||
#endif
|
#endif
|
||||||
// if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](1, substream, cmd, dai);
|
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](1);
|
||||||
// if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](1, substream, cmd, dai);
|
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](1);
|
||||||
#if CONFIG_AC10X_TRIG_LOCK
|
#if CONFIG_AC10X_TRIG_LOCK
|
||||||
spin_unlock_irqrestore(&priv->lock, flags);
|
spin_unlock_irqrestore(&priv->lock, flags);
|
||||||
#endif
|
#endif
|
||||||
|
@ -242,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_SUSPEND:
|
||||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||||
/* capture channel resync, if overrun */
|
/* capture channel resync, if overrun */
|
||||||
if (dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (dai->capture_active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,8 +237,8 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
|
||||||
if (0 != schedule_work(&priv->work_codec_clk)) {
|
if (0 != schedule_work(&priv->work_codec_clk)) {
|
||||||
}
|
}
|
||||||
} else {
|
} 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_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](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 */
|
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -262,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",
|
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
|
||||||
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
|
||||||
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active, ret);
|
dai->playback_active, dai->capture_active, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -311,7 +296,7 @@ static int asoc_simple_parse_dai(struct device_node *node,
|
||||||
* 2) user need to rebind Sound Card everytime
|
* 2) user need to rebind Sound Card everytime
|
||||||
* if he unbinded CPU or Codec.
|
* if he unbinded CPU or Codec.
|
||||||
*/
|
*/
|
||||||
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name, 0);
|
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -353,67 +338,11 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai,
|
||||||
return 0;
|
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)
|
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 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 *codec = rtd->codec_dai;
|
||||||
struct snd_soc_dai *cpu = asoc_rtd_to_cpu(rtd, 0);
|
struct snd_soc_dai *cpu = rtd->cpu_dai;
|
||||||
struct seeed_dai_props *dai_props =
|
struct seeed_dai_props *dai_props =
|
||||||
seeed_priv_to_props(priv, rtd->num);
|
seeed_priv_to_props(priv, rtd->num);
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -426,13 +355,6 @@ static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,6 +462,10 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto dai_link_of_err;
|
goto dai_link_of_err;
|
||||||
|
|
||||||
|
#if _SINGLE_CODEC
|
||||||
|
asoc_simple_canonicalize_platform(dai_link);
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = asoc_simple_set_dailink_name(dev, dai_link,
|
ret = asoc_simple_set_dailink_name(dev, dai_link,
|
||||||
"%s-%s",
|
"%s-%s",
|
||||||
dai_link->cpus->dai_name,
|
dai_link->cpus->dai_name,
|
||||||
|
@ -568,17 +494,7 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
|
||||||
#endif
|
#endif
|
||||||
dai_props->codec_dai.sysclk);
|
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);
|
asoc_simple_canonicalize_cpu(dai_link, single_cpu);
|
||||||
#if _SINGLE_CODEC
|
|
||||||
asoc_simple_canonicalize_platform(dai_link);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dai_link_of_err:
|
dai_link_of_err:
|
||||||
of_node_put(cpu);
|
of_node_put(cpu);
|
||||||
|
@ -695,79 +611,6 @@ card_parse_end:
|
||||||
return ret;
|
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)
|
static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct seeed_card_data *priv;
|
struct seeed_card_data *priv;
|
||||||
|
@ -797,11 +640,11 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
* Use snd_soc_dai_link_component instead of legacy style
|
* Use snd_soc_dai_link_component instead of legacy style
|
||||||
* It is codec only. but cpu/platform will be supported in the future.
|
* It is codec only. but cpu/platform will be supported in the future.
|
||||||
* see
|
* see
|
||||||
* soc-core.c :: snd_soc_init_multicodec()
|
* soc-core.c :: snd_soc_init_multicodec()
|
||||||
*
|
*
|
||||||
* "platform" might be removed
|
* "platform" might be removed
|
||||||
* see
|
* see
|
||||||
* simple-card-utils.c :: asoc_simple_canonicalize_platform()
|
* simple-card-utils.c :: asoc_simple_canonicalize_platform()
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
dai_link[i].cpus = &dai_props[i].cpus;
|
dai_link[i].cpus = &dai_props[i].cpus;
|
||||||
|
@ -878,8 +721,6 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
INIT_WORK(&priv->work_codec_clk, work_cb_codec_clk);
|
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);
|
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -897,9 +738,7 @@ static int seeed_voice_card_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
|
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
|
||||||
}
|
}
|
||||||
asoc_simple_clean_reference(card);
|
return asoc_simple_clean_reference(card);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id seeed_voice_of_match[] = {
|
static const struct of_device_id seeed_voice_of_match[] = {
|
||||||
|
|
|
@ -9,13 +9,17 @@
|
||||||
|
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
|
||||||
#define __NO_SND_SOC_CODEC_DRV 1
|
#define __NO_SND_SOC_CODEC_DRV 1
|
||||||
#else
|
#else
|
||||||
#define __NO_SND_SOC_CODEC_DRV 0
|
#define __NO_SND_SOC_CODEC_DRV 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
|
#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__)
|
#if __has_attribute(__fallthrough__)
|
||||||
# define fallthrough __attribute__((__fallthrough__))
|
# define fallthrough __attribute__((__fallthrough__))
|
||||||
#else
|
#else
|
||||||
|
@ -31,12 +35,8 @@
|
||||||
#define snd_soc_codec_get_dapm snd_soc_component_get_dapm
|
#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_codec_get_bias_level snd_soc_component_get_bias_level
|
||||||
#define snd_soc_kcontrol_codec snd_soc_kcontrol_component
|
#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
|
#define snd_soc_read snd_soc_component_read32
|
||||||
#endif
|
#define snd_soc_register_codec snd_soc_register_component
|
||||||
#define snd_soc_register_codec devm_snd_soc_register_component
|
|
||||||
#define snd_soc_unregister_codec snd_soc_unregister_component
|
#define snd_soc_unregister_codec snd_soc_unregister_component
|
||||||
#define snd_soc_update_bits snd_soc_component_update_bits
|
#define snd_soc_update_bits snd_soc_component_update_bits
|
||||||
#define snd_soc_write snd_soc_component_write
|
#define snd_soc_write snd_soc_component_write
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#
|
#
|
||||||
# This derived from my command history on ubuntu 20.04.1 .YMMV
|
# This derived from my command history on ubuntu 20.04.1 .YMMV
|
||||||
|
|
||||||
sudo apt install -y git gcc g++ make alsa-utils cmake
|
sudo apt install -y git gcc make alsa-utils cmake
|
||||||
|
|
||||||
git clone git://github.com/raspberrypi/userland.git
|
git clone git://github.com/raspberrypi/userland.git
|
||||||
pushd userland/
|
pushd userland/
|
||||||
|
|
|
@ -14,7 +14,6 @@ fi
|
||||||
uname_r=$(uname -r)
|
uname_r=$(uname -r)
|
||||||
|
|
||||||
CONFIG=/boot/config.txt
|
CONFIG=/boot/config.txt
|
||||||
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
|
|
||||||
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
|
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
|
||||||
|
|
||||||
get_overlay() {
|
get_overlay() {
|
||||||
|
@ -71,7 +70,7 @@ rm -rf /etc/voicecard/ || true
|
||||||
|
|
||||||
echo "disabled seeed-voicecard.service "
|
echo "disabled seeed-voicecard.service "
|
||||||
systemctl stop seeed-voicecard.service
|
systemctl stop seeed-voicecard.service
|
||||||
systemctl disable seeed-voicecard.service
|
systemctl disable seeed-voicecard.service
|
||||||
|
|
||||||
echo "remove seeed-voicecard"
|
echo "remove seeed-voicecard"
|
||||||
rm /usr/bin/seeed-voicecard || true
|
rm /usr/bin/seeed-voicecard || true
|
||||||
|
|
16
wm8960.c
16
wm8960.c
|
@ -796,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, int direction)
|
static int wm8960_mute(struct snd_soc_dai *dai, int mute)
|
||||||
{
|
{
|
||||||
struct snd_soc_codec *codec = dai->codec;
|
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 = {
|
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,
|
||||||
.mute_stream = wm8960_mute,
|
.digital_mute = 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 = {
|
||||||
|
@ -1259,11 +1258,7 @@ 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)
|
||||||
|
@ -1291,6 +1286,7 @@ static const struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
|
||||||
.idle_bias_on = 1,
|
.idle_bias_on = 1,
|
||||||
.use_pmdown_time = 1,
|
.use_pmdown_time = 1,
|
||||||
.endianness = 1,
|
.endianness = 1,
|
||||||
|
.non_legacy_dai_naming = 1,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1318,7 +1314,8 @@ 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;
|
||||||
|
@ -1383,9 +1380,10 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm8960_i2c_remove(struct i2c_client *client)
|
static int 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…
Reference in a new issue