koalo / linux Goto Github PK
View Code? Open in Web Editor NEWThis project forked from raspberrypi/linux
Development of a I2S sound driver for the Raspberry Pi
License: Other
This project forked from raspberrypi/linux
Development of a I2S sound driver for the Raspberry Pi
License: Other
too large shift of dividend happens before division by target frequency. this leads to divf >=1024 in certain cases, for instance when target frequency is 1024000. divf should be calculated as a remainder from division by 1024 as it was done in the old version.
Hi Florian, hi all!
While testing my setup with the tda1541a driver, i found that aplay, speaker-test and mplayer all led to the following kernel bug (in dmesg):
--- snip -------------------------------------------------------------------
[ 590.698049] BUG: scheduling while atomic: speaker-test/2718/0x00000003
[ 590.698064] Modules linked in: snd_soc_rpi_tda1541a snd_soc_tda1541a snd_soc_bcm2708_i2s bcm2708_dmaengine virt_dma snd_bcm2835 snd_soc_bcm2708 snd_soc_core snd_compress regmap_i2c regmap_spi snd_pcm snd_page_alloc snd_seq snd_seq_device snd_timer leds_gpio led_class snd [last unloaded: snd_soc_rpi_proto]
[ 590.698173] from
[ 590.698206] from
[ 590.698237] from
[ 590.698264] from
[ 590.698292] from
[ 590.698318] from
[ 590.698351] from
[ 590.698389] from
[ 590.698427] from
[ 590.698456] from
[ 590.698483] from
[ 590.698522] from [](bcm2708_dma_prep_dma_cyclic+0xf0/0x1b4 [bcm2708_dmaengine])
[ 590.698689] [](bcm2708_dma_prep_dma_cyclic+0xf0/0x1b4 [bcm2708_dmaengine]) from [](snd_dmaengine_pcm_trigger+0xd8/0x14c [snd_soc_core])
[ 590.698904] [](snd_dmaengine_pcm_trigger+0xd8/0x14c [snd_soc_core]) from [](soc_pcm_trigger+0x64/0xa8 [snd_soc_core])
[ 590.699092] [](soc_pcm_trigger+0x64/0xa8 [snd_soc_core]) from [](snd_pcm_do_start+0x2c/0x30 [snd_pcm])
[ 590.699314] [](snd_pcm_do_start+0x2c/0x30 [snd_pcm]) from [](snd_pcm_action_single+0x38/0x78 [snd_pcm])
[ 590.699438] [](snd_pcm_action_single+0x38/0x78 [snd_pcm]) from [](snd_pcm_lib_write1+0x330/0x3b0 [snd_pcm])
[ 590.699561] [](snd_pcm_lib_write1+0x330/0x3b0 [snd_pcm]) from [](snd_pcm_lib_write+0x50/0x64 [snd_pcm])
[ 590.699678] [](snd_pcm_lib_write+0x50/0x64 [snd_pcm]) from [](snd_pcm_playback_ioctl1+0x1b8/0x4ac [snd_pcm])
[ 590.699756] [](snd_pcm_playback_ioctl1+0x1b8/0x4ac [snd_pcm]) from
[ 590.699787] from
[ 590.699821] from
--- snap -------------------------------------------------------------------
Did I miss something very essential? If you (or some else) needs more tests, I'd be happy to provide these....
TIA. Salut, Jo"rg
I am not shure whether it is a bug in the Proto AudioCodec driver or in Alsa.
If I try to use only one channel of the soundcard as a mono device. This works ...
... temporarely.
E.g. I play sound to the left channel, it plays perfect, but after a while the sound output switches to the right channel. It toggles between the two channels every few seconds or minutes.
This is my /etc/asound.conf:
pcm_slave.asoc_out {
pcm "hw:1,0"
channels 2
rate 48000
periods 128
period_time 0
period_size 1024
buffer_size 4096
}
pcm.out1 {
type plug
slave.pcm {
type dshare
ipc_key 1024
slave asoc_out
bindings [ 0 ]
}
hint {
show on description "ASoC I2S OUT L"
}
}
pcm.out2 {
type plug
slave.pcm {
type dshare
ipc_key 1024
slave asoc_out
bindings [ 1 ]
}
hint {
show on description "ASoC I2S OUT R"
}
}
I am using the device as "out1", "plug:out1" is not working.
Any idea what goes wrong?
If I open the device with 8KHz or 32KHz sample rate "cat /proc/asound/card1/pcm0p/sub0/hw_params" says that the device uses the correct rate. But all 8KHz or 32KHz files I play using aplay, mplayer or ffmpeg are played with 48kHz, independend of there origin sample rate (they are pitched, that means I play a 6 minute 8KHz file in one minute). For example I tried a 32KHz radio stream (Hard to find one with less than 44,1KHz today). It is played much to fast (with interrupts), you will hear it using "mplayer -ao alsa:device=hw=1,0 -nolirc -cache 64 http://stream.antenne1.de/stream2/livestream.mp3". Curiously playing an 44.1KHz file or stream works, e.g. "mplayer -ao alsa:device=hw=1,0 -nolirc http://1live.akacast.akamaistream.net/7/706/119434/v1/gnl.akacast.akamaistream.net/1live -cache 64".
UPDATE:
I did some further research and found out the following:
If reading from Line-In with 8kHz setting, six times of expected data are sent.
My application opens the device plughw:1,0 with SND_PCM_FORMAT_MU_LAW, 8kHz and one channel.
cat /proc/asound/card1/pcm0c/sub0/hw_params says:
access: MMAP_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 8000 (8000/1)
period_size: 160
buffer_size: 800
The setting (mostly) look like they shoul (I don't know why there are set 2 channels, maybe a bug in my software). But if I read from the device I get for example:
7f ff ff 7f ff ff (mulaw uses one byte per sample, 7f means silence)
The first and the 4th byte are always the same, byte 2,3,5 and 6 are alway ff. If I only use the first byte and drop the other 5 recording works.
I assume the wm8731 is setup correct, but the clock is still using 48kHZ. So this needs to be changed or to be independent from playback, the unneeded bytes must be dropped.
I will check if playback works if I play each byte 6 times.
Copied from forum, by steveha:
When performing modprobe, I come across 'bcm2708_dmaengine' is missing.
As a result, I just performed the modprobe w/o 'bcm2708_dmaengine' with success.
I hooked up a TDA1545 (yes thats not a typo) DAC IC and tried to run it with the TDA1541 driver. Mplayer seems to play correctly, but there's loads of white noise with the music playing faintly in the back.
This looks to me as some sort of I2S formatting problem. I have had proper sound before using the same hw setup and using Phil Poole's (userspace and kernel) software in which I tweaked the TXC_A and MODE_A registers myself.
As your code is a bit more complex so I don't know what I will break if I go fiddlin' around with the parameters myself. Maybe you could have a look at the TDA1545 datasheet and include a driver for it (should be TDA5141 driver with 1 or 2 tweaks).
As the I2S interface on the BCM2708 is very flexible would it be an idea to have a "generic" I2S driver in which the formatting settings can be done as kernel module options?
Datasheet to the TDA1545: http://pdf.datasheetcatalog.com/datasheet/philips/TDA1545A_T_3.pdf
The driver should have a function that allows to configure the BCLK as master or slave with out having to modify the code.
Would like a configuration for reading data in AL1402G serial output format (http://www.wavefrontsemi.com/UserFiles/File/AL_Info/AL14/Wavefront%20AL1402G%20OptoRec%20Data%20Sheet.pdf). Note table of contents is wrong, page 3 is the serial output interface, not the input interface.
Would like configuration to read left-justified 24-bit samples, MSB first, BCLK falls on WORDCLOCK edge (format "00"). If some other format supported by the 1402 is easier (e.g. formats "01" or "11") that is OK too.
Word clock is external to Pi (e.g. is an input to the Pi).
Note that unlike I2S specification, there is no 1-bit delay after WORDCLOCK transition, the MSB immediately follows the word clock.
AL1402G spec implies that each word is actually 32 bits, last 8 bits are to be discarded by the receiver. E.g. the Pi driver will see 8 BCLK transitions after the LSB is received - all bits after the 24th are discarded until the next word clock transition.
Thanks!
-Mark
Copied from forum, by steveha:
The main difference between them is ESS9018 is running on 64fs bit clock I2S and TDA1541A only does 48fs. Also, ESS9018 can support higher sampling rates like 176.4 khz or 192 khz. Particular for 176.4 khz, I did aware there is a custom mpd to stream native DSD signals (i.e. not DoP) over I2S.
Main tasks:
Hi,
I got the driver working with a Y2 dac and and an external bit clock and my own codec driver. It works great, thanks to all who contributed!
The one problem I had was that at higher sampling frequencies it started to have drop outs. Looking at hw_params I noticed that the buffer at 192kHz seemed smaller than the one for 44.1kHz:
root@pi:/proc/asound/sndrpibclkdiv/pcm0p/sub0# cat hw_params
access: RW_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 44100 (44100/1)
period_size: 4410
buffer_size: 22050
root@pi:/proc/asound/sndrpibclkdiv/pcm0p/sub0# cat hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 192000 (192000/1)
period_size: 4096
buffer_size: 16384
Then I changed buffer_bytes_max in bcm2708-pcm.c:
.buffer_bytes_max = 1024 * 1024,
Now I get perfect playback at 192kHz and alsa reports the following:
root@pi:/proc/asound/sndrpibclkdiv/pcm0p/sub0# cat hw_params
access: RW_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 192000 (192000/1)
period_size: 8000
buffer_size: 96000
Leon
The Raspberry Pi assumes 40fs bit clock even for external clocks. Change that to 64fs, 48fs... It should be switchable.
bcm2708-i2s.c: Samplerates, that uses MASH mode use BCLK=64xFS, other 32xFS. The default setting should be 64xFS for all modes.
It would also help, if this would be configurable by the sound card driver. The driver should be able to initialize the clock that it needs.
--- ./sound/soc/bcm2708/bcm2708-i2s.c 2013-09-13 20:40:45.630200001 +0200
+++ ./sound/soc/bcm2708/bcm2708-i2s.c.orig 2013-09-13 22:40:09.582200003 +0200
@@ -476,9 +476,6 @@
* variance. To minimize that it is best to have the fastest
* clock here. That is PLLD with 500 MHz.
*/
target_frequency = sampling_rate*half_frame*2;
clk_src = BCM2708_CLK_SRC_OSC;
mash = BCM2708_CLK_MASH_0;
Every time I start to play file there is I2S SYNC error:
bcm2708-dmaengine bcm2708-dmaengine: allocating channel for 0
bcm2708-i2s bcm2708-i2s.0: I2S SYNC error!
bcm2708-dmaengine bcm2708-dmaengine: freeing channel for 0
Is this correct?
linux / sound / soc / bcm2708 / bcm2708-i2s.c
half_frame = data_length_2; /_ overwrite half frame length, because the above trick is not needed _/
target_frequency = sampling_rate_half_frame*2;
This gives a bitclock of 64_fs for 16 bit and 128_fs for 32bit samples, not 32_fs for 16 bit and 64_fs for 32bit!
For sample rates of 8000 x n the driver makes an assumption of frame length based on sample format forcing 40bits frame for 16 bit signal which is incompatible with many codecs. It must be a decision of the card driver, not cpu.
IMO, set_sysclk with clk_id as the frame length could be used. Then the cpu driver wouldn't have to guess.
Dear developers,
I want to raise my concern with the current way of declaring platform devices for codecs and sound cards in bcm2708.c.
I believe it is wrong. Board config file should deal only with what's on board, including i2s interface. If now every developer starts to add commercial and homemade devices to the file I doubt that it will make it to the mainstream. It also makes it difficult to maintain an up to date kernel. Development of addon boards specifically for RPi would be obstructed by the need to compile custom made kernel and incorporating bcm2708 into a kernel version that will suit the end user. To sum up, the work being done is very valuable as it opens new functionality. Unfortunately, the way it is implemented now makes it available only to a limited number of RPi users.
Solutions:
Hi
i have done the procedure you explained to boot the kernel on my raspberry pi 1.
mkdir linux
cd linux
git init
git fetch git://github.com/koalo/linux.git rpi-3.8.y-asocdev:refs/remotes/origin/rpi-3.8.y-asocdev
git checkout rpi-3.8.y-asocdev
then i enabled the following in the kernel configuration menuconfig :
Device Drivers > Sound card support > Advanced Linux Sound Architecture > ALSA for SoC audio support > SoC Audio support for the Broadcom BCM2708 I²S module
but it doesn't boot on raspberry pi 1 not at all. do you have any idea???
PLLA, PLLB.....
Add support for SND_SOC_DAIFMT_LEFT_J and create a codec for outputting 32bit samples into it.
The magic (half_frame=40) will break the SPDIF compatible output, but apparently bit rates used by SPDIF do not fit into the 8000Hz divisibility rule.
I'm still undecided on the PCM format that the SPDIF should use. IEC958 has a PCM format, but that contains non-BMC coded data. Perhaps SNDRV_PCM_FMTBIT_SPECIAL is a safe bet in order to not accidentally mix that with normal audio. Though, I made the test by using SNDRV_PCM_FMTBIT_S32, 96kHz stereo.
Here is an example hack I did on top of tda1541a drivers which seem to output usable signal, at least looks like that on oscilloscope. (still need to verify with real data and real AV receiver)
diff --git a/sound/soc/bcm2708/bcm2708-i2s.c b/sound/soc/bcm2708/bcm2708-i2s.c
index ba41ef4..63562f5 100644
--- a/sound/soc/bcm2708/bcm2708-i2s.c
+++ b/sound/soc/bcm2708/bcm2708-i2s.c
@@ -530,6 +530,9 @@ static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream,
case SND_SOC_DAIFMT_I2S:
data_delay = 1;
break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ data_delay = 0;
+ break;
default:
/* TODO
* Others are possible but are not implemented at the moment.
diff --git a/sound/soc/bcm2708/rpi-tda1541a.c b/sound/soc/bcm2708/rpi-tda1541a.c
index 06f993d..2367f41 100644
--- a/sound/soc/bcm2708/rpi-tda1541a.c
+++ b/sound/soc/bcm2708/rpi-tda1541a.c
@@ -37,12 +37,12 @@ static struct snd_soc_ops snd_rpi_tda1541a_ops = {
static struct snd_soc_dai_link snd_rpi_tda1541a_dai[] = {
{
.name = "TDA1541A",
- .stream_name = "TDA1541A HiFi",
+ .stream_name = "TDA1541A SPDIF HiFi",
.cpu_dai_name = "bcm2708-i2s.0",
.codec_dai_name = "tda1541a-hifi",
.platform_name = "bcm2708-pcm-audio.0",
.codec_name = "tda1541a-codec",
- .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
.ops = &snd_rpi_tda1541a_ops,
.init = snd_rpi_tda1541a_init,
diff --git a/sound/soc/codecs/tda1541a.c b/sound/soc/codecs/tda1541a.c
index b848624..23ff4c9 100644
--- a/sound/soc/codecs/tda1541a.c
+++ b/sound/soc/codecs/tda1541a.c
@@ -20,8 +20,8 @@ static struct snd_soc_dai_driver tda1541a_dai = {
.playback = {
.channels_min = 2,
.channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_SPECIAL
},
};
Hi,
good job Florian, nice to see the drivers in standard rpi kernel.
Will the WM8731 be supported in 3.10?
I assume it would be possible by just copying the kernel modules from 3.8?
Could you explain me how to generate a .dtb file for use on a SD card DE1 - SoC ... thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.