Advanced Linux Sound Architecture - Driver: Introduction

Next Previous Contents

## 1. Introduction

This document describes the ALSA driver and kernel API. Application programmers should use the library API rather than kernel API. The ALSA Library offers 100% of the functionally of the kernel API, but add next major improvements in usability, making the application code simpler and better looking. In addition, some of the some fixes/compatibility code in, may be placed in the library code instead of the kernel driver.

## 1.1 Source files

Source files are separated to:

/include

  Directory contains all header files which are included from more sources.

/kernel

  Directory with kernel code and abstract layers (middle level code and library).

/lowlevel

  Generic lowlevel code for chip(set)s.

/cards

  Upper level for soundcards and specific lowlevel code.

/detect

  Detection layer (/proc/asound/detect - to make installation easy).

## 1.2 Devices

Devices should use abstract code from sound kernel, but it should use own code and register minors separetely (with snd_minor_register and snd_minor_unregister functions). This method totaly bypass all abstract code, so code for these soundcards must handle all things.

## 1.3 Memory allocation

- void *snd_malloc( unsigned long size )
- void snd_free( void *ptr, unsigned long size )
- char *snd_malloc_strdup( char *string )
- void snd_free_str( char *string )

These routines use their own memory allocation algoritm. It should be removed in the future and replaced with kmalloc and kfree calls, but for now I need to trace all allocation problems to make code clean...

Note: ALSA driver heavily uses dynamic allocation for most things.

For debugging you should use command './configure --with-debug=full' for configuration. This enables trace of allocated memory with above functions and this makes debugging a little bit easier.

## 1.4 Basic coding

All things are made as objects (which encapsulates data and functions) and are referenced in this way. I don't prefer to pass index to some array of structure or something like this. Objects contain both data and functions. Pointers to these objects are passed around (like C++).

All main structures should have snd_xxxx_new, snd_xxxx_free, snd_xxxx_register, snd_xxxx_unregister functions.

- snd_card_t is a basic structure which contains info about a soundcard, index and resource tracking variables. Look at include/driver.h for all things related to this structure.

- snd_pcm_t is a basic structure for a PCM device.
- snd_pcm_channel_t is a basic structure for a PCM channel (direction).
- struct snd_stru_pcm_hardware is a structure which must be filled by lowlevel code. Look at include/pcm.h for all things related to these structures.

- snd_kmixer_t is a basic structure for a MIXER device.
- snd_kmixer_channel_t is a basic structure for a MIXER channel.
- struct snd_stru_mixer_channel_hw is a structure which must be filled by lowlevel code. Look at include/mixer.h for all things related to these structures.

## 1.5 Upper level (/cards)

Code for soundcards should contain these things:

1. Support for more than one of the same soundcard (up to SND_CARDS)...
   - it isn't really possible due to HW limitations
2. Autodetection/autoconfiguration feature (if it's possible)...
   - if lowlevel code is specific for soundcard type - it should be here, too..
3. Initialization code for soundcard
   - snd_card_new
   - snd_card_free (frees all hardware resources)
4. Allocate/free hardware resources for soundcard
   - snd_register_ioport
   - snd_unregister_ioports (frees all ioports)
   - snd_register_interrupt
   - snd_unregister_interrupts (frees all interrupts)
   - snd_register_dma_channel
   - snd_unregister_dma_channels (frees all DMA channels)
5. Initialize other layers (PCMs, Mixers etc.)
   - snd_pcm_new
   - snd_pcm_free
   - snd_pcm_register
   - snd_pcm_unregister (calls snd_pcm_free)
   - snd_mixer_new
   - snd_mixer_free
   - snd_mixer_register
   - snd_mixer_unregister (calls snd_mixer_free)
6. Register soundcard
   - snd_card_register
   - snd_card_unregister (doesn't call snd_card_free)

Note: Due to module dependency you should separate code for soundcards from the same manufacture which have slightly different hardware. Example: The GUS Extreme has an ESS ES-1688 chip. This chip isn't in the GUS Classic. For GUS Classic, the generic code in the snd-es1688.o module isn't needed. So there are two upper level modules (snd-gusextreme.o and snd-gusclassic.o).

## 1.6 Private data/values

Some structures have pointers to private data and values. These variables aren't used with the abstract layers and are intended for low-level code use only.

    snd_card_t -> private_data
    snd_card_t -> private_free (called from snd_card_free if not NULL)

    struct snd_stru_pcm_hardware -> private_data
    struct snd_stru_pcm_hardware -> private_free (called from snd_pcm_free if not NULL)
    snd_pcm_t -> private_data
    snd_pcm_t -> private_free (called from snd_pcm_free if not NULL)

    struct snd_stru_mixer_channel_hw -> private_value
    snd_kmixer_channel_t -> private_data
    snd_kmixer_channel_t -> private_free (called from snd_mixer_free if not NULL)
    snd_kmixer_t -> private_value
    snd_kmixer_t -> private_data
    snd_kmixer_t -> private_free (called from snd_mixer_free if not NULL)

## 1.7 CLI/STI & spin locking

Good code shouldn't contain snd_cli()/snd_sti() calls. Instead use spin locks snd_spin_lock()/snd_spin_unlock() for locking code. This method is much better for SMP machines.

Note: Debugging code is available for locking. Look in sndspinlock.h to enable it.

## 1.8 Examples

You should look at the code for GUS soundcards to see how can be things done...

Note: Code should be compiled cleanly under 2.0.X kernels and under latest 2.1.X kernels...

Next Previous Contents