ALSA Learning Notes

Source: Internet
Author: User
Tags prepare mesosphere

ALSA Learning Notes
Because the project uses a kernel of 2.6.17, the following analysis is based on the 2.6.17 version, in this version, there is no ASOC.

1 overall architecture

Application
---------------
Alsa-lib User Space
-------------------------------------
Alsa Kernel Space
-------
Sound Driver
----------------------------------
Hardware

Application: For example, Aplay, it is not directly to invoke the interface provided by kernel, but to invoke the Alsa-lib interface. So the app just #include "asound.h"
and link libasound.
For the above schema, there can only be one program at a time to open the sound card and occupy it, when other programs open, will return to busy. If you want to support multiple applications to open the sound card at the same time, you need support
Mixing features, some sound cards support hardware mix, but most sound cards do not support hardware mix, the need for software mix. This requires Esd,pulseaudio, and the architecture becomes:
App1 APP2
---------------
ESD, PulseAudio
--------------------
Alsa-lib User Space
-------------------------------------
Alsa Kernel Space
-------
Sound Driver
----------------------------------
Hardware
At this point, the application will invoke the interface provided by the Esd,pulseaudio and other mixer. For ESD, a lot of program support, such as MPlayer. For PulseAudio, there are corresponding patch.
Alsa itself also offers mixed-tone plugin,dmix.
App1 APP2
---------------
Alsa-lib (dmix) User space
-------------------------------------
Alsa Kernel Space
-------
Sound Driver
----------------------------------
Hardware
This schema and schema 1, the application does not need to make any changes, only need to modify the asound.conf
Example of the asound.conf of Architecture 1:
Pcm.! Default {
Type HW
Card 0
}
Ctl.! Default {
Type HW
Card 0
}
Example of the asound.conf of Architecture 3:
pcm.card0 {
Type HW
Card 0
}
Pcm.! Default {
Type plug
SLAVE.PCM "Dmixer"
}
Pcm.dmixer {
Type Dmix
Ipc_key 1025
Slave {
PCM "hw:0,0"
Period_time 0
Period_size 4096
Buffer_size 16384
Periods 128
Rate 44100
}
Bindings {
0 0
1 1
}
}
For configuration, refer to this web site:
Http://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html

For Period_size and Buffer_size, be aware that I modified them to 1024, 8192. On our platform with DMIX will appear underrun!!! Information.

2 ALSA Kernel
2.1 Directory
Alsa-driver includes many drivers in development and support for some 2.2,2.4 Linux kernel versions. When these drivers are stabilized, they are moved into the Alsa-kernel and eventually in the Linux kernel
In the sound directory.
Sound
/core
/oss
/seq
/oss
/instr
/drivers
/mpu401
/opl3
/i2c
/l3
/synth
/emux
/pci
/(Cards)
/isa
/(Cards)
/arm
/ppc
/sparc
/usb
/pcmcia/(cards)
/oss
The core directory is the heart of Alsa,
The Core/oss directory is primarily designed to support OSS simulations of PCM and mixer, and Rawmidi OSS simulations are placed in Alsa Rawmidi files mainly because it is fairly small. So many previously supported OSS
Applications can also run on ALSA.
CORE/SEQ, ALSA Sequencer, Core/seq/oss is ALSA simulation of OSS Sequencer.
The driver directory contains a variety of chip drivers.
I2C directory, Alsa I2C components. Although Linux has a standard I2C layer, ALSA has its own I2C code for some sound cards because the sound card requires only a few simple operations and a standard
The I2C API is too complex for this purpose.
PCI directory, mainly for PCI sound cards on PCI bus
ISA directory, primarily for ISA sound cards on the ISA bus
ARM, PPC, and SPARC directories, some sound card drivers under these architectures, such as the PXA2XX-PCM.C PXA processor
USB Directory, Usb-audio driver
Pcmcia
OSS directory, OSS architecture files, not belonging to Alsa

2.2 Interface
Alsa kernel mainly provides the following interfaces for the upper layer:
The 1 Control interface provides a flexible way to manage registered sound cards and to query for existing sound cards.
2 PCM interface provides the management of digital audio capture and playback.
3 Original MIDI interface
A standard electronic music instruction set. These APIs provide access to the MIDI bus on the sound card. These original excuses work directly on the MIDI
Events, programmers only need to manage protocols and time.
The 4 Timer interface provides access to the timer on the sound card for synchronization events that support sound.
5 Sequencer interface an advanced MIDI programming and voice synchronization higher level interface than the original MIDI interface. It can handle a lot of MIDI protocols and timers.
The 6 mixer interface controls the device on the sound card that transmits the signal and controls the sound size. /dsp/mixer,oss in the present.

Our main concern is the 1,2 interface.

2.3 Management of sound card
2.3.1 Card
For each sound card, a "card" record must be assigned.
The "card" record is the head office of the sound card, which manages a list of all devices (or components) on the sound card, such as Pcm,mixer,midi and so on.
Data structure is: Snd_card
Number: The first few sound cards, the largest for Sndrv_cards 8, for our system, only one sound card, the second is 0
ID: string for sound card
Devices: Device List
Root of Proc_root:proc file
Private_data: Private data for sound card
CONTROLS: List of control interfaces for sound cards
There are some power management and other

Call Snd_card_new to create a sound card entity.
Snd_card_new (index, ID, module, extra_size);
Where Extra_size is the size of the private_data memory space, allocated in snd_card_new.

2.3.2 Devices (components)
After the card instance is created, we can attach a component (device) to an instance of a card. In the ALSA drive, a component is represented by a structure Snd_device object.
A component can be a PCM instance, a control instance, a raw MIDI interface, and so on. It invokes snd_device_new creation.
Snd_device_new (Card, snd_device_type_t, Device_data, &ops);
In Control.c, PCM.C,INFO.C,RAWMIDI.C, and timer.c, there are snd_device_new calls that create control,pcm of type Deice, respectively.
Data structure is: Snd_device
struct List_head list; /* List of registered devices * *
struct Snd_card *card; /* Card which holds this device * *
snd_device_state_t State; /* State of the device * *
snd_device_type_t type; /* Device Type * *
void *device_data; /* Device Structure * *
struct Snd_device_ops *ops; * Operations * *
Snd_device_ops includes functions such as registration, Unregister,free, and so on.
In Snd_card_new, we created a control device, and Snd_pcm_new created a PCM device

2.3.3 Registration and release
After Snd_card_register calls it, the device file can be accessed by the outside world. Before, can not be safely outside the access.
Snd_card_free is typically invoked when exiting, which will automatically release all components.


2.4 PCM Interface
The ALSA PCM middle tier is very powerful, and drives only need to implement the underlying functions to access the hardware.
Each card can have up to 4 PCM instances.
A PCM instance contains playback (playback) and capture (recording) streams, and the data structure is: SND_PCM, where struct snd_pcm_str streams[2]; Stream[0] Represents
Playback,stream[1] represents capture.
Each PCM stream consists of one or more PCM streams,
Some sound cards support multiple playback features. For example, EMU10K1 has a PCM playback 32-bit stereo stream (Substream), at which point, each time, an idle stream is automatically selected and
Open, and if only one of the streams exists and is open, the next opening is either blocked or returned to Eagain, but these are not needed in your drive, and the PCM mesosphere
Manage the work.
Snd_pcm_new creates an entity,
int snd_pcm_new (struct snd_card *card, char *id, int device,
int playback_count, int capture_count,
struct SND_PCM * * rpcm)
Device: The first several PCM entities, starting from 0
Playback_count: Number of playback sub streams
Capture_count: Number of recording streams

Data structure of a stream: Snd_pcm_str
Where the stream represents the direction, is playback or capture
Substream_count Number of sub streams
A pointer to the struct Snd_pcm_substream *substream, pointing to the first stream, which, depending on the first, can be found next (substream->next)

Snd_pcm_new_stream creates a stream that is invoked in Snd_pcm_new.

Data structure of a substream (Snd_pcm_substream):
Where the stream represents the direction, is playback or capture
Buffer_bytes_max represents the largest annular buffer size
Dma_buffer .....
Dma_max Max
struct Snd_pcm_ops *ops; The operation function of the snd_pcm_set_ops that will set Ops
struct Snd_pcm_runtime *runtime;
Next next Substream, for a stream with only one playback, null
struct Snd_timer *timer; ????

Snd_pcm_ops defines a series of hardware operating functions, such as open, Ioctrl, trigger, etc.
1 Open callback:
static int Snd_xxx_open (struct snd_pcm_substream *substream);
This function is called when a stream is opened (Snd_pcm_open_substream function call)
The calling relationship is:
In snd_pcm_f_ops. Open = Snd_pcm_playback_open
Snd_pcm_playback_open---> Snd_pcm_open_file---> Snd_pcm_open_substream---> Snd_xxx_open
Snd_pcm_f_ops Open, when you are called on the/dev/snd/pcmc0d0 open time
Our main driver is to allocate substream->runtime and call REQUEST_IRQ to associate the interrupt handler function with the runtime.

2 Close Callback
static int snd_xxx_close (struct snd_pcm_substream *substream);
This function is called when a child stream is closed
The calling relationship is:
In snd_pcm_f_ops. Release = Snd_pcm_release
Snd_pcm_release---> Snd_pcm_release_substream---> Snd_xxx_close
Snd_pcm_f_ops release, when you are called on/dev/snd/pcmc0d0 close
Our main driver is to call FREE_IRQ to release the interrupt handler function and runtime.
(whether there is a memory leak, because in the open function to Runtimer with Kmalloc, in the close function should be Kfree (runtime)???

3 IOCTL Callback
General use Snd_pcm_lib_ioctl

4 Hw_params Callback
static int snd_xxx_hw_params (struct snd_pcm_substream *substream,
struct Snd_pcm_hw_params *hw_params);
The calling relationship is:
In the snd_pcm_f_ops. Unlocked_ioctl = Snd_pcm_playback_ioctl
Snd_pcm_playback_ioctl--> SND_PCM_PLAYBACK_IOCTL1
-->SND_PCM_COMMON_IOCTL1---> Snd_pcm_hw_params_user---> Snd_pcm_hw_params---> Snd_xxx_hw_params

Snd_pcm_f_ops Unlocked_ioctl, when you invoke/DEV/SND/PCMC0D0 ioctl (int fd, int command, (char *) argstruct), the file system Do_ioctl
You will first determine whether the Unlocked_ioctl function is empty, not empty, and call Filp->f_op->unlocked_ioctl, where command is sndrv_pcm_ioctl_hw_params.
This function is invoked when the application sets hardware parameters, that is, when the PCM stream's buffer size, cycle size, and format are defined.
Many hardware settings must be done in this callback function, including the allocation of buffer. Buffer allocation can call the Snd_pcm_lib_malloc_pages function.
Our drive seems to have only buffer allocation, no other processing, there will be problems????

5 Hw_free Callback
static int Snd_xxx_hw_free (struct snd_pcm_substream *substream);
Releasing resources allocated in Hw_params

6 Prepare callback
static int snd_xxx_prepare (struct snd_pcm_substream *substream);
The calling relationship is:
In the snd_pcm_f_ops. Unlocked_ioctl = Snd_pcm_playback_ioctl
Snd_pcm_playback_ioctl--> SND_PCM_PLAYBACK_IOCTL1
-->SND_PCM_COMMON_IOCTL1---> Snd_pcm_prepare--> snd_pcm_do_prepare---> Snd_xxx_prepare
IO command for Sndrv_pcm_ioctl_prepare.
You can set the format type, the sampling rate, and so on in this function, which differs from hw_params in that the prepare callback function is invoked every Snd_pcm_prepare
For example, after the underrun recovery, etc.
In this function, you can get some values through the runtime record substream->runtime, such as the current sampling rate, format type, channel number, runtime->rate, Runtime->format or Runtime->channels
The allocated memory is set at Runtime->dma_area, and the size and cycle are runtime->buffer_size and runtime->period_size respectively.

Our driver has a problem with this function.


7 Trigger Callback
static int Snd_xxx_trigger (struct snd_pcm_substream *substream, int cmd);
The calling relationship is:
In the snd_pcm_f_ops. Unlocked_ioctl = Snd_pcm_playback_ioctl
Snd_pcm_playback_ioctl--> SND_PCM_PLAYBACK_IOCTL1
-->SND_PCM_COMMON_IOCTL1---> Snd_pcm_drain--> snd_pcm_do_drain_init---> Snd_xxx_trigger
IO command for Sndrv_pcm_ioctl_drain

The callback function is atomic, that is, the function that can not call sleep, trigger callback function should be as small as possible, just triggering DMA, other operations in Hw_params and
Perpare inside do.
Our drive implements Start,stop,suspend and RESUME, without realizing pause,unpause. Also called the Msleep???? It's not right.
Mdelay is a let the CPU idling, wait until the time of approval before exiting
Msleep is to let the current process hibernate, give up the CPU to other processes to use, wait until the time to wake up
Msleep cannot be used in an interrupt context

8 Pointer callback
Static snd_pcm_uframes_t snd_xxx_pointer (struct snd_pcm_substream *substream)
The callback function is called at the current hardware position in the buffer in the PCM middle-tier, and the position is computed in frames, ranging from 0 to buffer_size-1.
The calling relationship is:
snd_pcm_period_elapsed--> Snd_pcm_update_hw_ptr_pos---> Snd_xxx_pointer
In the interrupt handler function, the snd_pcm_period_elapsed is called, then the PCM middle tier updates the location, calculates the remaining space, and wakes the sleeping thread.
Sndrv_pcm_pos_xrun????

9 Other callback are not mandatory, and we are not driven to achieve them.



After you set up the hardware operation function, you can allocate buffer beforehand, call
Snd_pcm_lib_preallocate_pages_for_all
The function updates the Dma_max and dma_buffer of the stream, where the area in Dma_buffer represents the memory region

The release of PCM instances, generally not required, the PCM intermediate layer will automatically release the memory, unless you initialize the time, the allocation of some special variables (with Kmalloc),
At this point in the Exit function, with the kfree off.

2.4.2. Runtime
When a PCM stream is opened, a runtime instance of PCM is assigned and assigned to Substream-〉runtime.
Runtime keep Most of the information you need to control PCM, Hw_params and sw_params configuration copies, buffer pointers, etc.
Data structure: Snd_pcm_runtime
Include hw:hw_params information
The hardware descriptor (struct snd_pcm_hardware) contains the definition of the basic hardware configuration. First, you will define it in the open callback function.
What needs to be explained is that the runtime instance holds the copy of the descriptor, not the pointer to an already descriptor, that is, in the open callback function, you can modify the RUNTIME->HW
In accordance with your needs.


2.4.3 Interrupt Handling
The function of the interrupt handler in the sound card driver: Update the position of the buffer and tell the PCM middle layer when the buffer position crosses the previously set period size. Call snd_pcm_period_elapsed function
Will tell the PCM mesosphere.
The period_size is set in Snd_pcm_hw_params.
There are several ways in which the following sound card types can be interrupted:
1 Interrupt at Cycle boundary
The most common way
2 High Frequency Timer interrupt
For chips that don't interrupt.
Our implementation:
For position Pcm_buf_pos, the prepare call is set to 0, at the time of interruption, each will pass 60 bytes, each time plus 60, loop.
Then call the Snd_pcm_period_elapsed function to notify the upper level.

Call the Spin_lock???? in the interrupt For multiple processors???

File_operation in PCM:
When Snd_pcm_new is invoked,
Snd_pcm_new---> snd_pcm_dev_register--> snd_register_device This function to update the SND_MINOR structure,

And in Alsa_sound_init, Register_chrdev (Major, "Alsa", &snd_fops); When a ALSA primary device is turned on, the open function in Snd_fops is invoked,
That is, Snd_open (in SOUND.C), and Snd_open will replace file_ops according to Snd_minor, if the minor is a PCM device, it will use the PCM file_operation
(Updated in Snd_pcm_new)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.