Advanced Linux Sound Architecture - Driver: Introduction

Previous Next Table of 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/sound/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 )

Routines uses it's own memory allocation algoritm. It should be removed in future and replaced with kmalloc and kfree calls, but I need trace all allocation problems to make code clean...

Note: ALSA driver heavy 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 object (which encapsulates data and functions) and are referenced in this way. I don't preferr pass index to some array of structure or something this. Pointer to object which contains data and functions should be passed rather (like C++).

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

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

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

- snd_kmixer_t is basic structure for MIXER device.
- snd_kmixer_channel_t is basic structure for MIXER channel.
- struct snd_stru_mixer_channel_hw is structure which must be filled by lowlevel code. You should look to 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 same soundcards (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 calls snd_card_free)

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

## 1.6 Private data/values

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

    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 contains snd_cli()/snd_sti() calls. Use rather spin locks snd_spin_lock()/snd_spin_unlock() for locking some code. This code is much better for SMP machines.

Note: Debugging code is available and it should be enabled in sndspinlock.h.

## 1.8 Examples

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

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

Previous Next Table of Contents