audio codec kernel driver using alsa - capture path vs playback path - linux

I'm using a custom board running imx6q processor, and a tlv320aic3x audio codec.
Everything works ok after some bring-up, but I'm trying to improve the audio driver: whether I'm doing playback or capture - both playback and capture related amplifiers are switched on.
This causes side effects like noise in speakers when I'm capturing audio, and wastes power.
To solve this, I'm trying to define the data paths correctly in the driver, but I keep failing.
I find it hard to find resources on-line explaining how to code an ALSA driver using the ALSA predefined macros that exists in the Kernel.
I've searched http://www.alsa-project.org/, linux docs, and few other sources...
And to my questions:
Is there any decent tutorial out there? I'm specifically interested in DAPM and usage of control names.
Is it possible to "re-program" all driver data paths from userspace?
Is DAPM sufficient for decent power management? Or should I use userspace to switch on/off power from unused paths in the codec between playbacks and captures?
Just to be clear: in user space using the standard driver, I am able to do playback, capture and control mixers, switches, etc... However I'm trying to achieve better automatic power management.
Thanks

Related

Dumping hardware state of an Intel HD Audio hardware

Is there a way to fully dump the configuration of an Intel HDA-based audio codec, including current hardware state?
The interface at /proc/asound/card0/codec#0 only reflects what's known to the kernel, not the real hardware state.
The PCI configuration space (read with lspci -x) doesn't show much (it doesn't even show volume/amplifier gain values).
For context : I'm trying to debug an audio issue with my laptop, where headphones output white noise when resuming from standby. The white noise doesn't change when increasing volume, but disappears only when powering down the codec.
This leads me to believe that the issue is likely caused by either a buggy ACPI or a change in the codec's configuration, or even both. My goal is to get as much data as I can on before/after states and compare them, but both methods described above failed for me.
I found that hdajackretask as part of the alsa-tools-gui package on my Debian Stretch GNU/Linux Os looks very interesting in getting the internal parts of the sound-card in the right configuration for what I wanted.
I'm just looking to see whether it is portable to my other OS as I have only seem to have stereo audio on FreeBSD and I think this would help. In your case it might help your to decode how things are configured and to spot any changes. The normal screen is at least helpful in determining which connection is which:
What looks more interesting is the "Advanced override":
I am about to reboot and see whether I have managed to turn the grey connector be the "side"-channel outputs....

Which microcontroller for fast high quality audio switching and playback

I'm building a device which will play high quality sound samples and will switch between samples in >5ms when a signal is applied.
I'm after a microcontroller which can allow this - I need 4 I/O pins for triggering the transistions between sounds, as well as the output pin(s) for the audio. The duration of the audio files will be 50ms or so but ideally would have enough storage to allow the files to be 1 second or longer. It will loop the current file until told to change. I don't want audiable pops or suchlike when switching files or running other commands - but there shouldn't be a need for anything complex to run beside it, it's purely audio playing and switching.
I've looked at various microcontrollers in the arduino family but they don't seem optimal for this purpose - (tried for example mozzi library for arduino but it's not fantastic quality). Ideally I could do it all on the chip (whatever it is, doesn't need to be arduino) - without needing external storage or RAM modules. But if that's neccessary I'll do it. The solution is to fit in a 2cm wide cylinder (but no length constraints) so would be ideally within that - so no SD card modules or whatever. Language wise - I'm fairly new to them all - but can learn whatever would be best.
Audio - (44.1kHz CD quality WAV, although could obviously switch to a different format if neccessary). If this is totally impossible to play such a high quality sound - then sound quality could be less.
Thank you for your help
For a simple application like this you would be best to just use a small ARM Cortex M device hooked up to an external SPI FLASH chip. Most microcontrollers scale processing power and RAM with FLASH storage so keeping it all on one chip will result in a grotesquely over-powered solution. Serial FLASH memory is very cheap, easy to use, and you can change the size in the future if you need to add more samples.
For the audio side if you really want CD quality you'll have to look at getting a external audio DAC as I don't know of any microcontrollers that integrate a CD quality codec. External DACs aren't expensive or complex to use, but just adds to the physical size and BOM cost. Many Cortex chips have built in 12-bit DACs though so if the audio has a reasonably small dynamic range you might find this is suitable for your needs.
In terms of minimising pops and clicks the Cortex devices will have enough power for some basic filtering to deal with this. I would recommend against Arduino though as you will quickly come up against processing power limitations and I doubt you will want to dive into assembler optimisations.

ALSA vs PulseAudio - Latency Concerns

Good day,
I have been debating some details with a colleague about ALSA vs PulseAudio, and need some help coming to a conclusion with it. It's to my understanding that ALSA is relatively low-level, and talks directly to the hardware, while PulseAudio sits on top of ALSA as a service.
Additionally, it's to my understanding that ALSA is tied to Linux, but PulseAudio just acts as an abstraction layer on top of ALSA, and can work on other platforms. My conclusion is that ALSA would provide lower audio latency on most Linux systems, while my colleague contends that PulseAudio provides better (shorter) latency regardless.
Which of us is correct? My reasoning is that since PulseAudio sits on top of ALSA or even wraps it, there's no way it could provide better latency unless it's providing its own low-level calls.
Thank you.
ALSA (like many other sound APIs) provides a ring buffer for samples to be played.
The most common way to use this ring buffer is to keep it filled at all times.
This implies that a sample that is written now is played only after all the other samples in the buffer have been played, i.e., the latency is proportional to the buffer's size.
(The buffer size can be chosen by the application, but depends on the capabilities of the hardware, and is fixed once chosen.)
PulseAudio has the ability to keep only a part of the buffer filled.
(This is not a feature offered directly by ALSA, but requires a separate timer to monitor the playback progress.)
Thus it can offer lower latency than other applications using the same buffer size, but more importantly, this allows it to adjust the latency dynamically without having to stop and reconfigure the device.
Other applications could do the same, but it's easier to use PulseAudio than to implement that buffer handling again.

Getting ARM/WM8350 audio and power management working in linux

I have a rooted Sony prs900, running a linux 2.6.23 #2 PREEMPT kernel, for ARMv6. (Montavista linux kernel). I'm having problems with figuring out how power management works, both for running the system and for powering up and down the audio port.
I can neither figure out how to read the battery/powerline status information, nor get the audio chip to play sound, etc ... although I have been studying the kernel modules for a while...
It's worth a little money for help, say $100 paypal donation to an email account, (or more if this takes a long time...) for the first person able to explain to me how to do them in a way that works.
Eg: read battery status, and change some power modes like getting the audio amplifiers to power up/down so that the audio played to /dev/dsp (oss emulation) actually comes out as sound rather than just being consumed by the chip and ignored...
The actual sony kernel, and binary packages of cross compiler tools are located on the main page. Actual kernel sourcecode is also available.
What I have learned so far myself :
The sony is using a wolfson micro WM8350 audio driver and battery charger/power management chip for all the system's power; eg: it can power down/up the SD memory cards, send more power to the cpu, power up audio amplifiers, etc. See: WM8350 Datasheet.
Pretty much, the whole problem revolves around getting the WM8350 kernel drivers to work...
Although the company brags quite a bit about it's support under linux, they don't have any application notes or examples that are actually helpful that I can find, other than the datasheet. I suspect the kernel drivers I have are beta code, because they don't seem to be behaving well (several error messages in the kernel log about wm8350 registers not being readable happen at every boot even when running only the sony's native software...).
The kernel driver's source-code of most interest are in: linux-2.6.23_091126/drivers/mxc/pmic/{core,wm8350}
Notice, the wm8350 is a competitor to the MC14783, but the linux kernel drivers use the same {core} driver source code for both chips; The sony ONLY has the wm8350 on it -- there is no MC14783 present.
The code that I most want most desperately to understand how to make operate is found in the subdirectory {wm8350}, eg: wm8350/wm8350pm/power_supply_sysfs.c.
I want the audio to fire up too, but 'm not quite sure where the pertinent audio amplifier code is yet...
Very clearly the wm8350pm code is designed to export a /sys directory interface; right now /sys is mounted and operational on the system; but I'm not very familiar with the semantics of these newer style interfaces... they aren't quite like the old APM power interfaces for Linux laptops...
First I checked the obvious:
If I do a "cat /sys/power/state" it returns the word "mem" and nothing else.
The file has permissions -rw-r--r--, so potentially it could be written -- but I don't know with what. The string "mem" does not exist anywhere in the source code for the wm8350pm drivers, so I don't even know if /sys/power/state is part of the source code.
Doing a find /sys -iname "wm8350" reveals a handful of directories with the patterns:
wm8350-rtc , wm8350-pmic , wm8350-bl , wm8350-power , wm8350-led
wm8350-hifi-dai , wm8350-codec
wm8350-imx32ads.0
So, I do an ls-l on each directory, and look for actual files rather than symbolic links or subdirectories, and what I find are stock useless writable files: bind, unbind, uevent,
and a very few read only files: pmic_reg, dapm_widget, modalias, codec_reg which aren't very helpful.
It's no surprise that:
Doing: cat /sys/devices/platform/wm8350-ebx5016-audi/modalias gives "wm8350-ebx5016-audio"
Doing: cat /sys/devices/platform/wm8350-imx32ads.0/modalias gives "wm8350-imx32ads"
and since audio is off... Doing: cat /sys/devices/platform/wm8350-ebx5016-audi/dapm_widget reveals the audio state:
Headphone Jack: Off
Line In Jack: On
Mic Bias: Off
Left DAC: Off
Right DAC: Off
... (all else off and omitted except )...
EBX5016-hifi: PM State: D3hot
The last two files, I expect should do wm8350 chip register dumps... and one did.
Doing: cat /sys/devices/wm8350-pmic/pmic-reg causes a long pause, then nothing is printed.
but:
Doing: cat /sys/devices/wm8350/platform/wm8350-ebx5016-audi/wm8350-codec/codec_reg does prints a list of registers up to e8 which is just a few bytes larger than the datasheet says the chip should be (0x00 to 0xe6).
I tried using a python program to play wav files, (works on my desktop computer), and I noticed that /dev/dsp does open, the mixers DO set volume levels, and nothing comes out. So -- the audio driver is not able to enable the sound amplifiers on it's own automatically.
There are no alsa sound files in /dev, nor are any alsa tools found on the embedded machine... so I assume Sony is strictly using OSS /dev/dsp and /dev/mixer.
There is only one other access point I can find to the ws8350:
There IS a device driver /dev/wm8350.
That driver created by the source code in subdirectory wm8350/wm8350_reg.c ; in theory it should be able to read and write to all registers using ioctls() calls from a user space. However, something appears grossly wrong with it, for I wrote a test program to read the wm8350 registers... and most of the registers return error messages rather than allowing to be read, including the most pulic ID registers (0x00, 0x01) etc.
So, I'm quite stuck. Pointers, thoughts, hints, are quite desired.
I would like to change your question a little bit.
How does Linux ASOC (alsa system on chip) power management work?
I will answer this and then give some hints on using this specific chip.
.. If I do a cat /sys/power/state it returns the word "mem" and nothing else. The file has permissions -rw-r--r--, so potentially it could be written -- but I don't know with what. The string "mem" does not exist anywhere in the source code for the wm8350pm drivers, so I don't even know if /sys/power/state is part of the source code.
You need to get an understanding of the Linux driver model. Hardware in Linux is structured like a tree. The rational is that things must be powered up/down in specific sequences. For instance, you should not power down the PCI bus controller before powering down the PCI peripherals. Linux builds a tree of hardware and each driver (code) and device (data/actual hardware) has specific call backs/function pointers which handle some specific tasks.
probe - Are you there? Determines actual hardware/device is present.
remove - Shuts down device. Module removal, power off, etc.
suspend - going to sleep.
resume - waking up.
Three and four may look interesting to you. Now, to read about what /sys/power/state is about. The text mem, means that suspend to memory is supported by your system. In this mode, Linux does these steps,
Find first lowest level active bus.
suspend devices on that bus.
suspend bus and de-activate.
If a bus is active go to step 1.
Set CPU to low power state (suspend to RAM).
This is not quite the full story. A few devices may support a wake-up. They will have extra call-backs to enable waking the system from sleep modes. Read the documentation to find out about this.
That is general power management and driver/device structure. Now, how is the ASOC (alsa system on chip) structured?
There are typically three drivers/devices that get stitched together.
Codec - The wm8350 in your case. This includes audio amplifier drive circuitry and can include sound mixing and source controls. Supports digital to analog and analog to digital, typically through an i2s interface. The i2s is not the only interface. Usually a register bank is controlled through a secondary interface; i2c in the wm8350 case.
DAI - Refer to chapter 1.2.18.1 of the iMx31 reference manual; the hardware is called the SSI by Freescale. The next chapter on the AUDMUX is also useful to understand audio support on the iMx31/32.
Machine file - this is the board specific routing. It hooks the DAI to the codec and is the parent of both. It provides board clocking information and other specific configuration. For instance, it may use the AUDMUX to route the physical pins to the SSI block.
An i2c (or SPI) interface from the codec driver to send control commands to the coded chip. Some chips might uses a wacky i2s interface or something else for control (but not in your case).
Now if you understood this, you will see that some features of the wm8350 seem to break the Linux model. The DAI interface can be stopped (digital audio), but the i2c interface must remain alive to program the registers related to the power functionality in the codec/PMIC (power management IC).
The latest WM8350 calls the IC a multi-function device and support was introduced in 2.6.35. The initial support may not have included the WM8350 features. Unfortunately, without some details on the layout of the Sony prs900 board, it would be difficult to know how to use the WM8350 PMIC functionality. The code will involve the iMx31 CPU, the WM8350, the i2c connection, and possibly some power supply circuitry.
For certain, you can just try echo mem > /sys/power/state and see what happens. If it works, you are lucky. The power/current consumption in sleep might not be optimal, but it will probably be hard to fix with the 2.6.23 kernel. You will want to look through the /sys directories for wake-up sources and possibly register these before issuing the suspend to memory command.
I can neither figure out how to read the battery/powerline status information, nor get the audio chip to play sound, etc ... although I have been studying the kernel modules for a while...
From the above discussions, the battery and powerline status will probably be found through another device. However, the pmic_reg file may actually give the status if things are connected properly on the board.
The audio chip will use ALSA. You need to use either alsamixer or the command line amixer to set up audio routes through the codec, so the DAI channel (PCM from iMx32) is routed and sent to the speaker. To minimize power consumption, things are usually turned off by default. The /dev/dsp files are just OSS compatibility. This configuration will support ALSA natively. You are better off to use ALSA if possible.
Donate to the OSF and get a tax receipt, if this was helpful enough.

Interfacing with a custom camera in Linux on the beaglebone

I need some pointers to help me get a camera (OV7670) working on a beaglebone running debian.
Using the camera capes as a guide, I have connected the camera to the GPMC pins on the beagleboard and the I2C pins. However I am a bit stumped to what I need to do in software to get Linux to recognize it as a camera and be able to use it to read a frame from the GPMC.
From the readings I have done, it seems like I need to load a kernel module. I found that there is a OV7670 C driver file in the kernel source. What kind of modifications (if any) would I need to do?
I am also open to any suggested readings and tutorials that would help me.
The status of the C driver for AM335X devices:"/arch/arm/configs/am335x_evm_defconfig: # CONFIG_VIDEO_OV7670 is not set"Looks like you'll need to compile your own kernel with OV7670 enabled, or...
As an alternative, you could write your own simple driver using one of the bones two on-board programmable real-time units (PRUs). You'll need to become familiar with assembly but that shouldn't take anymore than 2-3hrs of dedicated reading and you only need to do it once. The PRUs run on a 200MHz clock so every instruction is 5ns - more than enough time to generate a clock for the OV7670 and OV5642. (I've created a collection of examples on GitHub for the PRU: https://github.com/TekuConcept/PRU_Demo - currently working on a driver for three OV5642 cameras on one bone for the AUVSI-robonation annual competition)
Another alternative is the LogiBone which is an FPGA cape for the bone. You may need to become familiar with Verilog for this one; nevertheless the developers I talked with said they have an add-on available for OmniVision cameras and are working on implementing various OpenCV software features.
As far as reading, there is nothing better than a well-documented datasheet!
http://www.voti.nl/docs/OV7670.pdf
http://www.phytec.com/wiki/images/7/72/AM335x_techincal_reference_manual.pdf
http://processors.wiki.ti.com/index.php/PRU_Assembly_Instructions
"Verilog for Digital Design" by Frank & Roman

Resources