Compare commits

..

1 commit

15 changed files with 313 additions and 1059 deletions

259
README.md
View file

@ -1,20 +1,247 @@
# 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
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
git clone https://github.com/HinTak/seeed-voicecard
git clone https://github.com/respeaker/seeed-voicecard
cd seeed-voicecard
sudo ./install.sh
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/)!
![](https://files.seeedstudio.com/wiki/ReSpeakerProductGuide/img/Raspberry_Pi_Mic_Array_Solutions.png)
## ReSpeaker Mic Hat
[![](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
@ -44,21 +271,13 @@ Thank you!
------------------------------------------------------
```
Enjoy !
### Technical support
For hardware testing purposes we made a Rasperry Pi OS 5.10.17-v7l+ 32-bit image with reSpeaker drivers pre-installed, which you can download by clicking on [this link](https://files.seeedstudio.com/linux/Raspberry%20Pi%204%20reSpeaker/2021-05-07-raspios-buster-armhf-lite-respeaker.img.xz).
We provide official support for using reSpeaker with the following OS:
- 32-bit Raspberry Pi OS
- 64-bit Raspberry Pi OS
And following hardware platforms:
- Raspberry Pi 3 (all models), Raspberry Pi 4 (all models)
Anything beyond the scope of official support is considered to be community supported. Support for other OS/hardware platforms can be added, provided MOQ requirements can be met.
If you have a technical problem when using reSpeaker with one of the officially supported platforms/OS, feel free to create an issue on Github. For general questions or suggestions, please use [Seeed forum](https://forum.seeedstudio.com/c/products/respeaker/15).
### FAQ
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>

14
ac101.c
View file

@ -955,7 +955,7 @@ 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[SNDRV_PCM_STREAM_PLAYBACK].active, codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active,
codec_dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE],
snd_soc_dai_active(codec_dai));
if (!snd_soc_dai_active(codec_dai)) {
@ -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[SNDRV_PCM_STREAM_CAPTURE].active && dmic_used && codec_aif1_fs[i].samp_rate == 44100) {
if (codec_dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && 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));
@ -1237,7 +1237,7 @@ int ac101_audio_startup(struct snd_pcm_substream *substream,
}
#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;
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 ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
int ret = 0;
unsigned long flags;
AC101_DBG("stream=%s cmd=%d\n",
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_PAUSE_RELEASE:
#if _MASTER_MULTI_CODEC == _MASTER_AC101
spin_lock_irqsave(&ac10x->lock, flags);
if (ac10x->aif1_clken == 0){
/*
* enable aif1clk, it' here due to reduce time between 'AC108 Sysclk Enable' and 'AC101 Sysclk Enable'
@ -1279,21 +1277,15 @@ 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_RST_CTRL, (0x1<<MOD_RESET_AIF1), (0x1<<MOD_RESET_AIF1));
}
spin_unlock_irqrestore(&ac10x->lock, flags);
ac101_set_clock(1, substream, cmd, dai);
#endif
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ac101_set_clock(0, NULL, 0, NULL);
break;
default:
ret = -EINVAL;
}
AC101_DBG("stream=%s cmd=%d;finished %d\n",
snd_pcm_stream_str(substream),
cmd, ret);
return ret;
}

68
ac108.c
View file

@ -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[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
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[SNDRV_PCM_STREAM_PLAYBACK].active)
|| (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai->stream[SNDRV_PCM_STREAM_CAPTURE].active)) {
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])) {
/* not configure hw_param twice */
/* 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.
*/
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;
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 */
if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
ac101_trigger(substream, cmd, dai);
}
if (y_start_n_stop && ac10x->sysclk_en == 0) {
/* enable lrck clock */
ac10x_read(I2S_CTRL, &reg, ac10x->i2cmap[_MASTER_INDEX]);
@ -1061,33 +1058,39 @@ static int ac108_trigger(struct snd_pcm_substream *substream, int cmd,
snd_pcm_stream_str(substream),
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) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
spin_lock_irqsave(&ac10x->lock, flags);
/* disable global clock if lrck disabled */
ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
/* disable global clock */
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;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ac108_set_clock(0, substream, cmd, dai);
break;
default:
ret = -EINVAL;
}
dev_dbg(dai->dev, "%s() stream=%s cmd=%d; finished %d\n",
__FUNCTION__,
snd_pcm_stream_str(substream),
cmd, ret);
__ret:
spin_unlock_irqrestore(&ac10x->lock, flags);
return ret;
}
@ -1121,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);
@ -1142,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 = {
@ -1322,11 +1324,6 @@ static struct snd_soc_codec_driver ac10x_soc_codec_driver = {
.set_bias_level = ac108_set_bias_level,
.read = ac108_codec_read,
.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) {
@ -1407,15 +1404,7 @@ static const struct regmap_config ac108_regmap = {
.max_register = 0xDF,
.cache_type = REGCACHE_FLAT,
};
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 },
{ }
};
static int ac108_i2c_probe(struct i2c_client *i2c) {
static int ac108_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *i2c_id) {
struct device_node *np = i2c->dev.of_node;
unsigned int val = 0;
int ret = 0, index;
@ -1428,11 +1417,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) {
ac10x->i2c101 = i2c;
i2c_set_clientdata(i2c, ac10x);
ret = ac101_probe(i2c, i2c_match_id(ac108_i2c_id, i2c));
ret = ac101_probe(i2c, i2c_id);
if (ret) {
ac10x->i2c101 = NULL;
return ret;
@ -1498,7 +1487,7 @@ __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) {
snd_soc_unregister_codec(&ac10x->i2c[_MASTER_INDEX]->dev);
ac10x->codec = NULL;
@ -1523,8 +1512,17 @@ __ret:
kfree(ac10x);
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);
static const struct of_device_id ac108_of_match[] = {

View file

@ -119,7 +119,7 @@ void ac101_shutdown(struct i2c_client *i2c);
int ac101_remove(struct i2c_client *i2c);
/* seeed voice card export */
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int, struct snd_pcm_substream *, int, struct snd_soc_dai *));
int seeed_voice_card_register_set_clock(int stream, int (*set_clock)(int));
int ac10x_fill_regcache(struct device* dev, struct regmap* map);

View file

@ -6,10 +6,4 @@ BUILT_MODULE_NAME[2]="snd-soc-seeed-voicecard"
DEST_MODULE_LOCATION[0]="/kernel/sound/soc/codecs"
DEST_MODULE_LOCATION[1]="/kernel/sound/soc/codecs"
DEST_MODULE_LOCATION[2]="/kernel/sound/soc/bcm"
PATCH[0]="back-to-v4.19.diff"
PATCH[1]="back-to-v5.4.diff"
PATCH[2]="back-to-v5.8.diff"
PATCH_MATCH[0]="^4\.19\.*"
PATCH_MATCH[1]="^5\.4\.*"
PATCH_MATCH[2]="^5\.8\.*"
AUTOINSTALL="yes"

View file

@ -26,7 +26,7 @@ fi
#
# 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
# - check for /boot/overlays
# - dtparam and dtoverlay is available
@ -67,10 +67,8 @@ function get_kernel_version() {
[ -z "$_VER_RUN" ] && {
ZIMAGE=/boot/kernel.img
[ -f /boot/firmware/vmlinuz ] && ZIMAGE=/boot/firmware/vmlinuz
# 64-bit-only kernel package
[ ! -f /boot/kernel.img ] && [ -f /boot/kernel8.img ] && ZIMAGE=/boot/kernel8.img
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | LC_ALL=C sed -e 's/^.*Linux/Linux/' | strings | awk '{ print $3; }')
_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"
return 0
@ -78,11 +76,11 @@ function get_kernel_version() {
function check_kernel_headers() {
VER_RUN=$(get_kernel_version)
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
VER_HDR=$(dpkg -L raspberrypi-kernel-headers | egrep -m1 "/lib/modules/[^-]+/build" | awk -F'/' '{ print $4; }')
[ "X$VER_RUN" == "X$VER_HDR" ] && {
return 0
}
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[^\/]+/build" | awk -F'/' '{ print $4; }')
VER_HDR=$(dpkg -L linux-headers-$VER_RUN | egrep -m1 "/lib/modules/[[:print:]]+/build" | awk -F'/' '{ print $4; }')
[ "X$VER_RUN" == "X$VER_HDR" ] && {
return 0
}
@ -107,9 +105,7 @@ which apt &>/dev/null
if [[ $? -eq 0 ]]; then
apt update -y
# Raspbian kernel packages
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
# Recent Raspbian has 64-bit kernel on 32-bit userspace
apt-get -y install gcc-aarch64-linux-gnu
apt-get -y install raspberrypi-kernel-headers raspberrypi-kernel
# Ubuntu kernel packages
apt-get -y install linux-raspi linux-headers-raspi linux-image-raspi
apt-get -y install dkms git i2c-tools libasound2-plugins
@ -177,11 +173,10 @@ grep -q "^snd-soc-seeed-voicecard$" /etc/modules || \
grep -q "^snd-soc-ac108$" /etc/modules || \
echo "snd-soc-ac108" >> /etc/modules
grep -q "^snd-soc-wm8960$" /etc/modules || \
echo "snd-soc-wm8960" >> /etc/modules
echo "snd-soc-wm8960" >> /etc/modules
#set dtoverlays
CONFIG=/boot/config.txt
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' $CONFIG || true
@ -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.service /lib/systemd/system/
systemctl enable seeed-voicecard.service
systemctl enable seeed-voicecard.service
systemctl start seeed-voicecard
echo "------------------------------------------------------"

View file

@ -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 = {

View file

@ -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 = {

View file

@ -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 = {

View file

@ -42,9 +42,7 @@ function get_kernel_version() {
[ -z "$_VER_RUN" ] && {
ZIMAGE=/boot/kernel.img
IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)
# 64-bit-only kernel package
[ ! -f /boot/kernel.img ] && [ -f /boot/kernel8.img ] && ZIMAGE=/boot/kernel8.img
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | LC_ALL=C sed -e 's/^.*Linux/Linux/' | strings | awk '{ print $3; }')
_VER_RUN=$(dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) | zcat | grep -a -m1 "Linux version" | strings | awk '{ print $3; }')
}
echo "$_VER_RUN"
return 0
@ -132,10 +130,10 @@ if [ "$overlay" ]; then
if [[ "$kernel_ver" =~ ^4\.19.*$ || "$kernel_ver" =~ ^5\.*$ ]]; then
for i in $RPI_HATS; do
if [ "$i" == "$overlay" ]; then
/bin/true #do_overlay $overlay 0
do_overlay $overlay 0
else
echo Uninstall $i ...
/bin/true #do_overlay $i 1
do_overlay $i 1
fi
done
fi

View file

@ -30,20 +30,6 @@
#define LINUX_VERSION_IS_GEQ(x1,x2,x3) (LINUX_VERSION_CODE >= KERNEL_VERSION(x1,x2,x3))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus)
#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \
asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs)
#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \
asoc_simple_parse_dai(node, dai_link->cpus, is_single_link)
#define asoc_simple_parse_codec(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->codecs, NULL)
#define asoc_simple_parse_platform(node, dai_link) \
asoc_simple_parse_dai(node, dai_link->platforms, NULL)
#endif
/*
* single codec:
* 0 - allow multi codec
@ -86,7 +72,6 @@ struct seeed_card_info {
struct asoc_simple_dai codec_dai;
};
#define seeed_priv_to_card(priv) (&(priv)->snd_card)
#define seeed_priv_to_dev(priv) ((priv)->snd_card.dev)
#define seeed_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
#define seeed_priv_to_props(priv, i) ((priv)->dai_props + (i))
@ -177,9 +162,9 @@ err:
}
#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]) {
_set_clock[stream] = set_clock;
}
@ -196,10 +181,10 @@ static void work_cb_codec_clk(struct work_struct *work)
int r = 0;
if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) {
r = r || _set_clock[SNDRV_PCM_STREAM_CAPTURE](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
r = r || _set_clock[SNDRV_PCM_STREAM_CAPTURE](0);
}
if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) {
r = r || _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
r = r || _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0);
}
if (r && priv->try_stop++ < TRY_STOP_MAX) {
@ -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",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
dai->stream_active[SNDRV_PCM_STREAM_PLAYBACK], dai->stream_active[SNDRV_PCM_STREAM_CAPTURE]);
switch (cmd) {
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 */
spin_lock_irqsave(&priv->lock, flags);
#endif
// if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](1, substream, cmd, dai);
// if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](1, substream, cmd, dai);
if (_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);
#if CONFIG_AC10X_TRIG_LOCK
spin_unlock_irqrestore(&priv->lock, flags);
#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_PAUSE_PUSH:
/* capture channel resync, if overrun */
if (dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (dai->stream_active[SNDRV_PCM_STREAM_CAPTURE] && substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
break;
}
@ -252,18 +237,14 @@ static int seeed_voice_card_trigger(struct snd_pcm_substream *substream, int cmd
if (0 != schedule_work(&priv->work_codec_clk)) {
}
} else {
// if (_set_clock[SNDRV_PCM_STREAM_CAPTURE]) _set_clock[SNDRV_PCM_STREAM_CAPTURE](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
// if (_set_clock[SNDRV_PCM_STREAM_PLAYBACK]) _set_clock[SNDRV_PCM_STREAM_PLAYBACK](0, NULL, 0, NULL); /* not using 2nd to 4th arg if 1st == 0 */
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);
}
break;
default:
ret = -EINVAL;
}
dev_dbg(rtd->card->dev, "%s() stream=%s cmd=%d play:%d, capt:%d;finished %d\n",
__FUNCTION__, snd_pcm_stream_str(substream), cmd,
dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active, dai->stream[SNDRV_PCM_STREAM_CAPTURE].active, ret);
return ret;
}
@ -311,7 +292,7 @@ static int asoc_simple_parse_dai(struct device_node *node,
* 2) user need to rebind Sound Card everytime
* if he unbinded CPU or Codec.
*/
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name, 0);
ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
if (ret < 0)
return ret;
@ -353,62 +334,6 @@ static int asoc_simple_init_dai(struct snd_soc_dai *dai,
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
static inline int asoc_simple_component_is_codec(struct snd_soc_component *component)
{
return component->driver->endianness;
}
static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
struct snd_soc_component *component;
struct snd_soc_pcm_stream *params;
struct snd_pcm_hardware hw;
int i, ret, stream;
/* Only Codecs */
for_each_rtd_components(rtd, i, component) {
if (!asoc_simple_component_is_codec(component))
return 0;
}
/* Assumes the capabilities are the same for all supported streams */
for (stream = 0; stream < 2; stream++) {
ret = snd_soc_runtime_calc_hw(rtd, &hw, stream);
if (ret == 0)
break;
}
if (ret < 0) {
dev_err(rtd->dev, "simple-card: no valid dai_link params\n");
return ret;
}
params = devm_kzalloc(rtd->dev, sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
params->formats = hw.formats;
params->rates = hw.rates;
params->rate_min = hw.rate_min;
params->rate_max = hw.rate_max;
params->channels_min = hw.channels_min;
params->channels_max = hw.channels_max;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
dai_link->c2c_params = params;
dai_link->num_c2c_params = 1;
#else
/* apparently this goes back to 5.6.x */
dai_link->params = params;
dai_link->num_params = 1;
#endif
return 0;
}
#endif
static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
struct seeed_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
@ -426,13 +351,6 @@ static int seeed_voice_card_dai_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)
ret = asoc_simple_init_dai_link_params(rtd);
if (ret < 0)
return ret;
#endif
dev_dbg(rtd->card->dev, "codec \"%s\" mapping to cpu \"%s\"\n", codec->name, cpu->name);
return 0;
}
@ -540,6 +458,10 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
if (ret < 0)
goto dai_link_of_err;
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link);
#endif
ret = asoc_simple_set_dailink_name(dev, dai_link,
"%s-%s",
dai_link->cpus->dai_name,
@ -568,17 +490,7 @@ static int seeed_voice_card_dai_link_of(struct device_node *node,
#endif
dai_props->codec_dai.sysclk);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu);
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus);
#endif
#else
asoc_simple_canonicalize_cpu(dai_link, single_cpu);
#if _SINGLE_CODEC
asoc_simple_canonicalize_platform(dai_link);
#endif
#endif
dai_link_of_err:
of_node_put(cpu);
@ -695,79 +607,6 @@ card_parse_end:
return ret;
}
#ifdef DEBUG
inline void seeed_debug_dai(struct seeed_card_data *priv,
char *name,
struct asoc_simple_dai *dai)
{
struct device *dev = seeed_priv_to_dev(priv);
if (dai->name)
dev_dbg(dev, "%s dai name = %s\n",
name, dai->name);
if (dai->sysclk)
dev_dbg(dev, "%s sysclk = %d\n",
name, dai->sysclk);
dev_dbg(dev, "%s direction = %s\n",
name, dai->clk_direction ? "OUT" : "IN");
if (dai->slots)
dev_dbg(dev, "%s slots = %d\n", name, dai->slots);
if (dai->slot_width)
dev_dbg(dev, "%s slot width = %d\n", name, dai->slot_width);
if (dai->tx_slot_mask)
dev_dbg(dev, "%s tx slot mask = %d\n", name, dai->tx_slot_mask);
if (dai->rx_slot_mask)
dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask);
if (dai->clk)
dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk));
}
inline void seeed_debug_info(struct seeed_card_data *priv)
{
struct snd_soc_card *card = seeed_priv_to_card(priv);
struct device *dev = seeed_priv_to_dev(priv);
int i;
if (card->name)
dev_dbg(dev, "Card Name: %s\n", card->name);
for (i = 0; i < card->num_links; i++) {
struct seeed_dai_props *props = seeed_priv_to_props(priv, i);
struct snd_soc_dai_link *link = seeed_priv_to_link(priv, i);
dev_dbg(dev, "DAI%d\n", i);
seeed_debug_dai(priv, "cpu", &props->cpu_dai);
seeed_debug_dai(priv, "codec", &props->codec_dai);
if (link->name)
dev_dbg(dev, "dai name = %s\n", link->name);
dev_dbg(dev, "dai format = %04x\n", link->dai_fmt);
/*
if (props->adata.convert_rate)
dev_dbg(dev, "convert_rate = %d\n",
props->adata.convert_rate);
if (props->adata.convert_channels)
dev_dbg(dev, "convert_channels = %d\n",
props->adata.convert_channels);
if (props->codec_conf && props->codec_conf->name_prefix)
dev_dbg(dev, "name prefix = %s\n",
props->codec_conf->name_prefix);
*/
if (props->mclk_fs)
dev_dbg(dev, "mclk-fs = %d\n",
props->mclk_fs);
}
}
#else
#define seeed_debug_info(priv)
#endif /* DEBUG */
static int seeed_voice_card_probe(struct platform_device *pdev)
{
struct seeed_card_data *priv;
@ -878,8 +717,6 @@ static int seeed_voice_card_probe(struct platform_device *pdev)
INIT_WORK(&priv->work_codec_clk, work_cb_codec_clk);
seeed_debug_info(priv);
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
if (ret >= 0)
return ret;
@ -897,9 +734,7 @@ static int seeed_voice_card_remove(struct platform_device *pdev)
if (cancel_work_sync(&priv->work_codec_clk) != 0) {
}
asoc_simple_clean_reference(card);
return 0;
return asoc_simple_clean_reference(card);
}
static const struct of_device_id seeed_voice_of_match[] = {

View file

@ -9,7 +9,7 @@
#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
#else
#define __NO_SND_SOC_CODEC_DRV 0
@ -31,12 +31,8 @@
#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_register_codec snd_soc_register_component
#define snd_soc_unregister_codec snd_soc_unregister_component
#define snd_soc_update_bits snd_soc_component_update_bits
#define snd_soc_write snd_soc_component_write

View file

@ -13,7 +13,7 @@
#
# 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
pushd userland/

View file

@ -14,7 +14,6 @@ fi
uname_r=$(uname -r)
CONFIG=/boot/config.txt
[ -f /boot/firmware/config.txt ] && CONFIG=/boot/firmware/config.txt
[ -f /boot/firmware/usercfg.txt ] && CONFIG=/boot/firmware/usercfg.txt
get_overlay() {
@ -71,7 +70,7 @@ rm -rf /etc/voicecard/ || true
echo "disabled seeed-voicecard.service "
systemctl stop seeed-voicecard.service
systemctl disable seeed-voicecard.service
systemctl disable seeed-voicecard.service
echo "remove seeed-voicecard"
rm /usr/bin/seeed-voicecard || true

View file

@ -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 = {
@ -1259,11 +1258,7 @@ static struct snd_soc_dai_driver wm8960_dai = {
.rates = WM8960_RATES,
.formats = WM8960_FORMATS,},
.ops = &wm8960_dai_ops,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
.symmetric_rate = 1,
#else
.symmetric_rates = 1,
#endif
};
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,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
#endif
};
@ -1318,7 +1314,8 @@ static void wm8960_set_pdata_from_of(struct i2c_client *i2c,
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_priv *wm8960;
@ -1383,9 +1380,10 @@ static int wm8960_i2c_probe(struct i2c_client *i2c)
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);
return 0;
}
static const struct i2c_device_id wm8960_i2c_id[] = {