PCM module (I2S) drivers?


21 posts
by ceteras » Wed Oct 31, 2012 4:22 pm
I've searched the forums without success, there is only this topic: I2S: Anyone got it running? which seems to touch on the subject, but still no hope.

The question: Is anybody working on writing a sound driver for the hardware PCM module included in the Raspberry Pi? Or perhaps this driver is already there but nobody talks about it.
For those in the know it's trivial, but for the rest of us this subject is a great mystery.
I've got an I2S DAC built an tested with other platforms; it works fine at 44100 and 48000 frames per second, but I have no Idea what to do on the software side. An user space application doesn't do, my scope is to have good sound from the Pi without going through HDMI (of course no pwm either, thanks but no, thanks).

Thanks!
Posts: 183
Joined: Fri Jan 27, 2012 1:42 pm
Location: Romania
by Sniper435 » Fri Nov 02, 2012 1:36 pm
I'm also very interested in this as I've got a project in the works that will use the I2S output of the pi to provide high quality audio.
Posts: 17
Joined: Fri Nov 02, 2012 1:35 pm
by msperl » Sat Nov 03, 2012 5:05 pm
lucy told me in a different thread (viewtopic.php?f=71&t=19797) that she found a sound driver for PCM output in the alsa-sound-subsystem. But what she said is that right now there is no input driver available.
See the last few posts on that thread...

Martin
Posts: 218
Joined: Thu Sep 20, 2012 3:40 pm
by mhelin » Sat Nov 03, 2012 8:30 pm
I think that the I2S sound interface is not implemented at all in that driver, only HDMI output is available through videocore. So both playback and capture are missing.
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by lucy » Mon Nov 05, 2012 2:13 pm
When I insert the snd-bcm2835.ko module in the kernel, a sound card is created.
I can use this card in combination with a codec connected to P5 and a simple sip client in userspace.
The result is I can register the RPi to a SIP server, 'call' from another device to the RPi and there is a sound connection. Unfortunately there is only a sound stream from the other device to the RPi (playback), not the otherway (capture).

After having a look into the code of the snd-bcm2835 I found out there was just code for a playback device and not for a capture device.

At this moment I am trying to get the capture part working but so far it's not been successfull.
I can add a capture device (arecord -l shows a device now :)) but I can't get the capture interrupt set so there is still no capture stream.
I have no idee how it's done at the current code for the playback stream, I really can't find the 'setting the irq part'.

Does anyone have an idea??
Posts: 17
Joined: Tue Oct 02, 2012 2:16 pm
by msperl » Mon Nov 05, 2012 4:24 pm
probably they are not doing it via IRQ, but via a timer, so your code runs in a (kernel) thread (hopefully with real time priority) that gets woken up by a timer and the writes or reads the next byte...

For low frequency settings (and it 48kHz is slow compared to 10MHz) this is typically good enough...
Obviously there are some issues with jitter with such a design.

As a hint: look at drivers for different (arm) platforms to get an idea how others have implemented it.
If there is one with IRQ or DMA, then you can extrapolate the basic principles of implementing it via IRQ or DMA instead.

Martin
Posts: 218
Joined: Thu Sep 20, 2012 3:40 pm
by mhelin » Mon Nov 05, 2012 5:13 pm
It's a mystery how lucy got the I2S codec playing with the RPi drivers.

However, there is an irq handler in bcm2835-pcm.c:

static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id)

The mixer seems to have a control (see bcm2835-ctc.c) for "PCM Playback Route", guess the vchi drivers/lib implements somehow the I2S internally. The constants for the route are

/* Some constants for values .. */
typedef enum {
AUDIO_DEST_AUTO = 0,
AUDIO_DEST_HEADPHONES = 1,
AUDIO_DEST_HDMI = 2,
AUDIO_DEST_MAX,
} SND_BCM2835_ROUTE_T;


No I2S/PCM defined, wonder how the AUTO setting (default) works.
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by mhelin » Mon Nov 05, 2012 5:35 pm
lucy have you played with amixer command?

For an example

Code: Select all
amixer cset numid=3 1


sets output to headphones (PWM), and

Code: Select all
amixer cset numid=3 2


to HDMI and

Code: Select all
amixer cset numid=3 0



sets the automatic recognition.

Which of these work with your I2S codec?
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by lucy » Mon Nov 05, 2012 6:22 pm
It's a mystery how lucy got the I2S codec playing with the RPi drivers.

Maybe it is but I don't think so...
The only thing I did was insmod snd.ko, snd-timer.ko, snd-page-alloc.ko, snd-pcm.ko and snd-bcm2835.ko
And run the userspace application... I didn't do anything with the alsamixer.
If you like I can do some test with the alsa-mixer tomorrow?
Some extra information: I did build my own kernel and rootfs with openembedded and the Angstrom distribution.

I know there is a irq handler in the bcm2835-pcm.c file. I applied some changes to that file and I found out that the when I am trying to use a capture stream, the application won't go to the IRQ handler at all. The original file (only playback stream) executes the irq handler function all the time.

That was the reason for my previous question: where is the interrupt for the playback stream enabled....??? I can't find it..
Posts: 17
Joined: Tue Oct 02, 2012 2:16 pm
by lucy » Mon Nov 05, 2012 6:35 pm
Besides, does someone know where I can find the debug message like:
audio_info("text");
audio_warning("text");
audio_error("text");
Posts: 17
Joined: Tue Oct 02, 2012 2:16 pm
by msperl » Mon Nov 05, 2012 7:39 pm
to see if interrupts are used the easiest is to use:
Code: Select all
watch cat /proc/interrupts

this will show you the currently allocated IRQs and their corresponding counters.
The names are typically self-explanatory (or at least point int the direction of the relevant driver)
Posts: 218
Joined: Thu Sep 20, 2012 3:40 pm
by mhelin » Mon Nov 05, 2012 8:01 pm
The irq handler is "enabled" throgh vchi_msg_queue() where it is propably registered as videocore write callback. See bcm2835-vchiq.c (line with m.u.write.callback = alsa_stream->fifo_irq_handler;).

Imho it would be better if someone wrote the PCM/I2S ALSA driver for BCM2835 from scratch to support both playback and capture (philpoole has started playing with the irq already, see viewtopic.php?f=44&t=8496&start=75). It might be too big task to change the VC driver to support capture. Besides the VC might have some limitations with bit depth, sample rates and such things. Some USB devices are already supported for capture already.
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by lucy » Tue Nov 06, 2012 12:54 pm
mhelin thanks for your reply.
Can you give me a hint about which USB device you are talking?

Perhaps I would be better to write a new PCM/I2S driver.
I didnt realized that the current driver(snd-bcm2835) is for video as well or am I wrong?
Maybe someone can tell me what specific function of the VC part is??

Another question. I am using a WM8731 CODEC chip. I found in the kernel source a WM8731.c and WM8731.h. I was wondering how I can use this code in combination with a driver and is it only code to initialize the codec?
Posts: 17
Joined: Tue Oct 02, 2012 2:16 pm
by mhelin » Tue Nov 06, 2012 7:43 pm
Lucy,
There are various USB sound cards that work with RPi, they are discussed somewhere on these forums. Regarding the WM8731 driver it's SPI/I2C control parts could maybe be useful, I don't know for which SoC (System on Chip) it's for, propably not for BCM2835 anyway, but it might be useful to check. This documentation tells only pxa2xx chipset is supported, but I guess there must be a way to add support for BCM2835: http://www.rpsys.net/openzaurus/patches/alsa/info.html
It seems that at least the platform driver supporting I2S, DMA etc. should be written.

The VC (VideoCore) is the graphics chip in BCM2835, and only ARM specific part of it is Open Source. It handles also the HDMI audio.
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by lucy » Wed Nov 07, 2012 2:49 pm
@ mhelin
I am so sorry!! I thought it worked but it didn't at all....!!! :o :( :oops:
Posts: 17
Joined: Tue Oct 02, 2012 2:16 pm
by mhelin » Wed Nov 07, 2012 8:05 pm
lucy wrote:@ mhelin
I am so sorry!! I thought it worked but it didn't at all....!!! :o :( :oops:


So you were actually listening the sounds from the audio jack or from your HDMI monitor, right? It happens..
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by mhelin » Mon Nov 19, 2012 9:17 am
Does anyone know how the IRQ remapping is supposed to work in RPi kernel? Please see
arch/arm/mach-bcm2708/armctrl.c

Code: Select all
/* For support of kernels >= 3.0 assume only one VIC for now*/
static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = {
        INTERRUPT_VC_JPEG,
        INTERRUPT_VC_USB,
        INTERRUPT_VC_3D,
        INTERRUPT_VC_DMA2,
        INTERRUPT_VC_DMA3,
        INTERRUPT_VC_I2C,
        INTERRUPT_VC_SPI,
        INTERRUPT_VC_I2SPCM,
        INTERRUPT_VC_SDIO,
        INTERRUPT_VC_UART,
        INTERRUPT_VC_ARASANSDIO
};


This mapping is used later:
Code: Select all
/**
 * armctrl_init - initialise a vectored interrupt controller
 * @base: iomem base address
 * @irq_start: starting interrupt number, must be muliple of 32
 * @armctrl_sources: bitmask of interrupt sources to allow
 * @resume_sources: bitmask of interrupt sources to allow for resume
 */
int __init armctrl_init(void __iomem * base, unsigned int irq_start,
                        u32 armctrl_sources, u32 resume_sources)
{
        unsigned int irq;

        for (irq = 0; irq < NR_IRQS; irq++) {
                unsigned int data = irq;
                if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO)
                        data = remap_irqs[irq - INTERRUPT_JPEG];

                irq_set_chip(irq, &armctrl_chip);
                irq_set_chip_data(irq, (void *)data);
                irq_set_handler(irq, handle_level_irq);
                set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_DISABLED);
        }

        armctrl_pm_register(base, irq_start, resume_sources);
        return 0;
}


However, the handle_level_irq doesn't make any mappings to lets say from IRQ 81 to IRQ 55. How is this mapping system designed to be used. I've implemented interrupt handler and registered it using request_irq for IRQ 55, but it is never triggered. Only the default handler for IRQ 81 seems to be triggered.
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by mhelin » Thu Dec 06, 2012 11:16 am
Does anyone know anything about this kernel patch:

https://patchwork.kernel.org/patch/1440821/mbox/

originating from here:
https://github.com/lp0/linux/tree/rpi-s ... ch-bcm2708

It seems to have different interrupt controller implementation than the current 3.2.27+ kernel. Is it possible to patch the current kernel with this patch (or diffing a new pathc between rpi-split and 3.2.27+ one) and have the I2S FIFO interrupt working? Anyone tried that one?

Is there anyone from Broadcom to comment on this IRQ 55 vs. IRQ 81 issue, is there a bug or missing fuctionality in BCM SoC firmware possibly?
Posts: 99
Joined: Wed Oct 17, 2012 7:18 pm
by koalo » Mon May 20, 2013 8:57 pm
For those how stumble upon this topic from some time ago:
There is a running I2S driver:
http://blog.koalo.de/2013/05/i2s-support-for-raspberry-pi.html
Posts: 112
Joined: Mon Feb 04, 2013 4:02 pm
by ceteras » Mon May 20, 2013 10:00 pm
Thank you for the update, and for the hard work, I hope to be able to test it as soon as possible!
I had no idea that progress was being made on this issue!
Posts: 183
Joined: Fri Jan 27, 2012 1:42 pm
Location: Romania
by davidmam » Fri Oct 04, 2013 9:40 pm
I'm wanting to integrate a high sample rate codec for recording ultrasound. I've got suitable microphones identified but am struggling on the 'turning it into sound' part. I'm looking at the TP3067 CODEC as it supports a suitably high sample rate but it has no I2C control (it appears to be quite dumb - just connect it up and it should work) but am somewhat confused by the differing clock rates to those in the Pi.

Could anyone suggest a better alternative - I want to sample frequencies up to and over 100kHz so ideally a 384KHz audio would be desired (Nyquist frequency being twice max frequency desired)
Posts: 98
Joined: Tue Dec 06, 2011 4:13 pm