Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  writing-an-alsa-driver.rst   Sprache: unbekannt

 
======================
Writing an ALSA Driver
======================

:Author: Takashi Iwai <tiwai@suse.de>

Preface
=======

This document describes how to write an `ALSA (Advanced Linux Sound
Architecture) <http://www.alsa-project.org/>`__ driver. The document
focuses mainly on PCI soundcards. In the case of other device types, the
API might be different, too. However, at least the ALSA kernel API is
consistent, and therefore it would be still a bit help for writing them.

This document targets people who already have enough C language skills
and have basic linux kernel programming knowledge. This document doesn't
explain the general topic of linux kernel coding and doesn't cover
low-level driver implementation details. It only describes the standard
way to write a PCI sound driver on ALSA.

File Tree Structure
===================

General
-------

The file tree structure of ALSA driver is depicted below::

            sound
                    /core
                            /oss
                            /seq
                                    /oss
                    /include
                    /drivers
                            /mpu401
                            /opl3
                    /i2c
                    /synth
                            /emux
                    /pci
                            /(cards)
                    /isa
                            /(cards)
                    /arm
                    /ppc
                    /sparc
                    /usb
                    /pcmcia /(cards)
                    /soc
                    /oss


core directory
--------------

This directory contains the middle layer which is the heart of ALSA
drivers. In this directory, the native ALSA modules are stored. The
sub-directories contain different modules and are dependent upon the
kernel config.

core/oss
~~~~~~~~

The code for OSS PCM and mixer emulation modules is stored in this
directory. The OSS rawmidi emulation is included in the ALSA rawmidi
code since it's quite small. The sequencer code is stored in
``core/seq/oss`` directory (see `below <core/seq/oss_>`__).

core/seq
~~~~~~~~

This directory and its sub-directories are for the ALSA sequencer. This
directory contains the sequencer core and primary sequencer modules such
as snd-seq-midi, snd-seq-virmidi, etc. They are compiled only when
``CONFIG_SND_SEQUENCER`` is set in the kernel config.

core/seq/oss
~~~~~~~~~~~~

This contains the OSS sequencer emulation code.

include directory
-----------------

This is the place for the public header files of ALSA drivers, which are
to be exported to user-space, or included by several files in different
directories. Basically, the private header files should not be placed in
this directory, but you may still find files there, due to historical
reasons :)

drivers directory
-----------------

This directory contains code shared among different drivers on different
architectures. They are hence supposed not to be architecture-specific.
For example, the dummy PCM driver and the serial MIDI driver are found
in this directory. In the sub-directories, there is code for components
which are independent from bus and cpu architectures.

drivers/mpu401
~~~~~~~~~~~~~~

The MPU401 and MPU401-UART modules are stored here.

drivers/opl3 and opl4
~~~~~~~~~~~~~~~~~~~~~

The OPL3 and OPL4 FM-synth stuff is found here.

i2c directory
-------------

This contains the ALSA i2c components.

Although there is a standard i2c layer on Linux, ALSA has its own i2c
code for some cards, because the soundcard needs only a simple operation
and the standard i2c API is too complicated for such a purpose.

synth directory
---------------

This contains the synth middle-level modules.

So far, there is only Emu8000/Emu10k1 synth driver under the
``synth/emux`` sub-directory.

pci directory
-------------

This directory and its sub-directories hold the top-level card modules
for PCI soundcards and the code specific to the PCI BUS.

The drivers compiled from a single file are stored directly in the pci
directory, while the drivers with several source files are stored on
their own sub-directory (e.g. emu10k1, ice1712).

isa directory
-------------

This directory and its sub-directories hold the top-level card modules
for ISA soundcards.

arm, ppc, and sparc directories
-------------------------------

They are used for top-level card modules which are specific to one of
these architectures.

usb directory
-------------

This directory contains the USB-audio driver.
The USB MIDI driver is integrated in the usb-audio driver.

pcmcia directory
----------------

The PCMCIA, especially PCCard drivers will go here. CardBus drivers will
be in the pci directory, because their API is identical to that of
standard PCI cards.

soc directory
-------------

This directory contains the codes for ASoC (ALSA System on Chip)
layer including ASoC core, codec and machine drivers.

oss directory
-------------

This contains OSS/Lite code.
At the time of writing, all code has been removed except for dmasound
on m68k.


Basic Flow for PCI Drivers
==========================

Outline
-------

The minimum flow for PCI soundcards is as follows:

-  define the PCI ID table (see the section `PCI Entries`_).

-  create ``probe`` callback.

-  create ``remove`` callback.

-  create a struct pci_driver structure
   containing the three pointers above.

-  create an ``init`` function just calling the
   :c:func:`pci_register_driver()` to register the pci_driver
   table defined above.

-  create an ``exit`` function to call the
   :c:func:`pci_unregister_driver()` function.

Full Code Example
-----------------

The code example is shown below. Some parts are kept unimplemented at
this moment but will be filled in the next sections. The numbers in the
comment lines of the :c:func:`snd_mychip_probe()` function refer
to details explained in the following section.

::

      #include <linux/init.h>
      #include <linux/pci.h>
      #include <linux/slab.h>
      #include <sound/core.h>
      #include <sound/initval.h>

      /* module parameters (see "Module Parameters") */
      /* SNDRV_CARDS: maximum number of cards supported by this module */
      static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
      static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
      static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;

      /* definition of the chip-specific record */
      struct mychip {
              struct snd_card *card;
              /* the rest of the implementation will be in section
               * "PCI Resource Management"
               */
      };

      /* chip-specific destructor
       * (see "PCI Resource Management")
       */
      static int snd_mychip_free(struct mychip *chip)
      {
              .... /* will be implemented later... */
      }

      /* component-destructor
       * (see "Management of Cards and Components")
       */
      static int snd_mychip_dev_free(struct snd_device *device)
      {
              return snd_mychip_free(device->device_data);
      }

      /* chip-specific constructor
       * (see "Management of Cards and Components")
       */
      static int snd_mychip_create(struct snd_card *card,
                                   struct pci_dev *pci,
                                   struct mychip **rchip)
      {
              struct mychip *chip;
              int err;
              static const struct snd_device_ops ops = {
                     .dev_free = snd_mychip_dev_free,
              };

              *rchip = NULL;

              /* check PCI availability here
               * (see "PCI Resource Management")
               */
              ....

              /* allocate a chip-specific data with zero filled */
              chip = kzalloc(sizeof(*chip), GFP_KERNEL);
              if (chip == NULL)
                      return -ENOMEM;

              chip->card = card;

              /* rest of initialization here; will be implemented
               * later, see "PCI Resource Management"
               */
              ....

              err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
              if (err < 0) {
                      snd_mychip_free(chip);
                      return err;
              }

              *rchip = chip;
              return 0;
      }

      /* constructor -- see "Driver Constructor" sub-section */
      static int snd_mychip_probe(struct pci_dev *pci,
                                  const struct pci_device_id *pci_id)
      {
              static int dev;
              struct snd_card *card;
              struct mychip *chip;
              int err;

              /* (1) */
              if (dev >= SNDRV_CARDS)
                      return -ENODEV;
              if (!enable[dev]) {
                      dev++;
                      return -ENOENT;
              }

              /* (2) */
              err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                                 0, &card);
              if (err < 0)
                      return err;

              /* (3) */
              err = snd_mychip_create(card, pci, &chip);
              if (err < 0)
                      goto error;

              /* (4) */
              strcpy(card->driver, "My Chip");
              strcpy(card->shortname, "My Own Chip 123");
              sprintf(card->longname, "%s at 0x%lx irq %i",
                      card->shortname, chip->port, chip->irq);

              /* (5) */
              .... /* implemented later */

              /* (6) */
              err = snd_card_register(card);
              if (err < 0)
                      goto error;

              /* (7) */
              pci_set_drvdata(pci, card);
              dev++;
              return 0;

      error:
              snd_card_free(card);
              return err;
      }

      /* destructor -- see the "Destructor" sub-section */
      static void snd_mychip_remove(struct pci_dev *pci)
      {
              snd_card_free(pci_get_drvdata(pci));
      }



Driver Constructor
------------------

The real constructor of PCI drivers is the ``probe`` callback. The
``probe`` callback and other component-constructors which are called
from the ``probe`` callback cannot be used with the ``__init`` prefix
because any PCI device could be a hotplug device.

In the ``probe`` callback, the following scheme is often used.

1) Check and increment the device index.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

  static int dev;
  ....
  if (dev >= SNDRV_CARDS)
          return -ENODEV;
  if (!enable[dev]) {
          dev++;
          return -ENOENT;
  }


where ``enable[dev]`` is the module option.

Each time the ``probe`` callback is called, check the availability of
the device. If not available, simply increment the device index and
return. dev will be incremented also later (`step 7
<7) Set the PCI driver data and return zero._>`__).

2) Create a card instance
~~~~~~~~~~~~~~~~~~~~~~~~~

::

  struct snd_card *card;
  int err;
  ....
  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                     0, &card);


The details will be explained in the section `Management of Cards and
Components`_.

3) Create a main component
~~~~~~~~~~~~~~~~~~~~~~~~~~

In this part, the PCI resources are allocated::

  struct mychip *chip;
  ....
  err = snd_mychip_create(card, pci, &chip);
  if (err < 0)
          goto error;

The details will be explained in the section `PCI Resource
Management`_.

When something goes wrong, the probe function needs to deal with the
error.  In this example, we have a single error handling path placed
at the end of the function::

  error:
          snd_card_free(card);
          return err;

Since each component can be properly freed, the single
:c:func:`snd_card_free()` call should suffice in most cases.


4) Set the driver ID and name strings.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

  strcpy(card->driver, "My Chip");
  strcpy(card->shortname, "My Own Chip 123");
  sprintf(card->longname, "%s at 0x%lx irq %i",
          card->shortname, chip->port, chip->irq);

The driver field holds the minimal ID string of the chip. This is used
by alsa-lib's configurator, so keep it simple but unique. Even the
same driver can have different driver IDs to distinguish the
functionality of each chip type.

The shortname field is a string shown as more verbose name. The longname
field contains the information shown in ``/proc/asound/cards``.

5) Create other components, such as mixer, MIDI, etc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here you define the basic components such as `PCM <PCM Interface_>`__,
mixer (e.g. `AC97 <API for AC97 Codec_>`__), MIDI (e.g.
`MPU-401 <MIDI (MPU401-UART) Interface_>`__), and other interfaces.
Also, if you want a `proc file <Proc Interface_>`__, define it here,
too.

6) Register the card instance.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

  err = snd_card_register(card);
  if (err < 0)
          goto error;

Will be explained in the section `Management of Cards and
Components`_, too.

7) Set the PCI driver data and return zero.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

::

  pci_set_drvdata(pci, card);
  dev++;
  return 0;

In the above, the card record is stored. This pointer is used in the
remove callback and power-management callbacks, too.

Destructor
----------

The destructor, the remove callback, simply releases the card instance.
Then the ALSA middle layer will release all the attached components
automatically.

It would be typically just calling :c:func:`snd_card_free()`::

  static void snd_mychip_remove(struct pci_dev *pci)
  {
          snd_card_free(pci_get_drvdata(pci));
  }


The above code assumes that the card pointer is set to the PCI driver
data.

Header Files
------------

For the above example, at least the following include files are
necessary::

  #include <linux/init.h>
  #include <linux/pci.h>
  #include <linux/slab.h>
  #include <sound/core.h>
  #include <sound/initval.h>

where the last one is necessary only when module options are defined
in the source file. If the code is split into several files, the files
without module options don't need them.

In addition to these headers, you'll need ``<linux/interrupt.h>`` for
interrupt handling, and ``<linux/io.h>`` for I/O access. If you use the
:c:func:`mdelay()` or :c:func:`udelay()` functions, you'll need
to include ``<linux/delay.h>`` too.

The ALSA interfaces like the PCM and control APIs are defined in other
``<sound/xxx.h>`` header files. They have to be included after
``<sound/core.h>``.

Management of Cards and Components
==================================

Card Instance
-------------

For each soundcard, a “card” record must be allocated.

A card record is the headquarters of the soundcard. It manages the whole
list of devices (components) on the soundcard, such as PCM, mixers,
MIDI, synthesizer, and so on. Also, the card record holds the ID and the
name strings of the card, manages the root of proc files, and controls
the power-management states and hotplug disconnections. The component
list on the card record is used to manage the correct release of
resources at destruction.

As mentioned above, to create a card instance, call
:c:func:`snd_card_new()`::

  struct snd_card *card;
  int err;
  err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);


The function takes six arguments: the parent device pointer, the
card-index number, the id string, the module pointer (usually
``THIS_MODULE``), the size of extra-data space, and the pointer to
return the card instance. The extra_size argument is used to allocate
card->private_data for the chip-specific data. Note that these data are
allocated by :c:func:`snd_card_new()`.

The first argument, the pointer of struct device, specifies the parent
device. For PCI devices, typically ``&pci->`` is passed there.

Components
----------

After the card is created, you can attach the components (devices) to
the card instance. In an ALSA driver, a component is represented as a
struct snd_device object. A component
can be a PCM instance, a control interface, a raw MIDI interface, etc.
Each such instance has one component entry.

A component can be created via the :c:func:`snd_device_new()`
function::

  snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);

This takes the card pointer, the device-level (``SNDRV_DEV_XXX``), the
data pointer, and the callback pointers (``&ops``). The device-level
defines the type of components and the order of registration and
de-registration. For most components, the device-level is already
defined. For a user-defined component, you can use
``SNDRV_DEV_LOWLEVEL``.

This function itself doesn't allocate the data space. The data must be
allocated manually beforehand, and its pointer is passed as the
argument. This pointer (``chip`` in the above example) is used as the
identifier for the instance.

Each pre-defined ALSA component such as AC97 and PCM calls
:c:func:`snd_device_new()` inside its constructor. The destructor
for each component is defined in the callback pointers. Hence, you don't
need to take care of calling a destructor for such a component.

If you wish to create your own component, you need to set the destructor
function to the dev_free callback in the ``ops``, so that it can be
released automatically via :c:func:`snd_card_free()`. The next
example will show an implementation of chip-specific data.

Chip-Specific Data
------------------

Chip-specific information, e.g. the I/O port address, its resource
pointer, or the irq number, is stored in the chip-specific record::

  struct mychip {
          ....
  };


In general, there are two ways of allocating the chip record.

1. Allocating via :c:func:`snd_card_new()`.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

As mentioned above, you can pass the extra-data-length to the 5th
argument of :c:func:`snd_card_new()`, e.g.::

  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                     sizeof(struct mychip), &card);

struct mychip is the type of the chip record.

In return, the allocated record can be accessed as

::

  struct mychip *chip = card->private_data;

With this method, you don't have to allocate twice. The record is
released together with the card instance.

2. Allocating an extra device.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After allocating a card instance via :c:func:`snd_card_new()`
(with ``0`` on the 4th arg), call :c:func:`kzalloc()`::

  struct snd_card *card;
  struct mychip *chip;
  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                     0, &card);
  .....
  chip = kzalloc(sizeof(*chip), GFP_KERNEL);

The chip record should have the field to hold the card pointer at least,

::

  struct mychip {
          struct snd_card *card;
          ....
  };


Then, set the card pointer in the returned chip instance::

  chip->card = card;

Next, initialize the fields, and register this chip record as a
low-level device with a specified ``ops``::

  static const struct snd_device_ops ops = {
          .dev_free =        snd_mychip_dev_free,
  };
  ....
  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);

:c:func:`snd_mychip_dev_free()` is the device-destructor
function, which will call the real destructor::

  static int snd_mychip_dev_free(struct snd_device *device)
  {
          return snd_mychip_free(device->device_data);
  }

where :c:func:`snd_mychip_free()` is the real destructor.

The demerit of this method is the obviously larger amount of code.
The merit is, however, that you can trigger your own callback at
registering and disconnecting the card via a setting in snd_device_ops.
About registering and disconnecting the card, see the subsections
below.


Registration and Release
------------------------

After all components are assigned, register the card instance by calling
:c:func:`snd_card_register()`. Access to the device files is
enabled at this point. That is, before
:c:func:`snd_card_register()` is called, the components are safely
inaccessible from external side. If this call fails, exit the probe
function after releasing the card via :c:func:`snd_card_free()`.

For releasing the card instance, you can call simply
:c:func:`snd_card_free()`. As mentioned earlier, all components
are released automatically by this call.

For a device which allows hotplugging, you can use
:c:func:`snd_card_free_when_closed()`. This one will postpone
the destruction until all devices are closed.

PCI Resource Management
=======================

Full Code Example
-----------------

In this section, we'll complete the chip-specific constructor,
destructor and PCI entries. Example code is shown first, below::

      struct mychip {
              struct snd_card *card;
              struct pci_dev *pci;

              unsigned long port;
              int irq;
      };

      static int snd_mychip_free(struct mychip *chip)
      {
              /* disable hardware here if any */
              .... /* (not implemented in this document) */

              /* release the irq */
              if (chip->irq >= 0)
                      free_irq(chip->irq, chip);
              /* release the I/O ports & memory */
              pci_release_regions(chip->pci);
              /* disable the PCI entry */
              pci_disable_device(chip->pci);
              /* release the data */
              kfree(chip);
              return 0;
      }

      /* chip-specific constructor */
      static int snd_mychip_create(struct snd_card *card,
                                   struct pci_dev *pci,
                                   struct mychip **rchip)
      {
              struct mychip *chip;
              int err;
              static const struct snd_device_ops ops = {
                     .dev_free = snd_mychip_dev_free,
              };

              *rchip = NULL;

              /* initialize the PCI entry */
              err = pci_enable_device(pci);
              if (err < 0)
                      return err;
              /* check PCI availability (28bit DMA) */
              if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
                  pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
                      printk(KERN_ERR "error to set 28bit mask DMA\n");
                      pci_disable_device(pci);
                      return -ENXIO;
              }

              chip = kzalloc(sizeof(*chip), GFP_KERNEL);
              if (chip == NULL) {
                      pci_disable_device(pci);
                      return -ENOMEM;
              }

              /* initialize the stuff */
              chip->card = card;
              chip->pci = pci;
              chip->irq = -1;

              /* (1) PCI resource allocation */
              err = pci_request_regions(pci, "My Chip");
              if (err < 0) {
                      kfree(chip);
                      pci_disable_device(pci);
                      return err;
              }
              chip->port = pci_resource_start(pci, 0);
              if (request_irq(pci->irq, snd_mychip_interrupt,
                              IRQF_SHARED, KBUILD_MODNAME, chip)) {
                      printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
                      snd_mychip_free(chip);
                      return -EBUSY;
              }
              chip->irq = pci->irq;
              card->sync_irq = chip->irq;

              /* (2) initialization of the chip hardware */
              .... /*   (not implemented in this document) */

              err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
              if (err < 0) {
                      snd_mychip_free(chip);
                      return err;
              }

              *rchip = chip;
              return 0;
      }

      /* PCI IDs */
      static struct pci_device_id snd_mychip_ids[] = {
              { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
              ....
              { 0, }
      };
      MODULE_DEVICE_TABLE(pci, snd_mychip_ids);

      /* pci_driver definition */
      static struct pci_driver driver = {
              .name = KBUILD_MODNAME,
              .id_table = snd_mychip_ids,
              .probe = snd_mychip_probe,
              .remove = snd_mychip_remove,
      };

      /* module initialization */
      static int __init alsa_card_mychip_init(void)
      {
              return pci_register_driver(&driver);
      }

      /* module clean up */
      static void __exit alsa_card_mychip_exit(void)
      {
              pci_unregister_driver(&driver);
      }

      module_init(alsa_card_mychip_init)
      module_exit(alsa_card_mychip_exit)

      EXPORT_NO_SYMBOLS; /* for old kernels only */

Some Hafta's
------------

The allocation of PCI resources is done in the ``probe`` function, and
usually an extra :c:func:`xxx_create()` function is written for this
purpose.

In the case of PCI devices, you first have to call the
:c:func:`pci_enable_device()` function before allocating
resources. Also, you need to set the proper PCI DMA mask to limit the
accessed I/O range. In some cases, you might need to call
:c:func:`pci_set_master()` function, too.

Suppose a 28bit mask, the code to be added would look like::

  err = pci_enable_device(pci);
  if (err < 0)
          return err;
  if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
      pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
          printk(KERN_ERR "error to set 28bit mask DMA\n");
          pci_disable_device(pci);
          return -ENXIO;
  }
  

Resource Allocation
-------------------

The allocation of I/O ports and irqs is done via standard kernel
functions.  These resources must be released in the destructor
function (see below).

Now assume that the PCI device has an I/O port with 8 bytes and an
interrupt. Then struct mychip will have the
following fields::

  struct mychip {
          struct snd_card *card;

          unsigned long port;
          int irq;
  };


For an I/O port (and also a memory region), you need to have the
resource pointer for the standard resource management. For an irq, you
have to keep only the irq number (integer). But you need to initialize
this number to -1 before actual allocation, since irq 0 is valid. The
port address and its resource pointer can be initialized as null by
:c:func:`kzalloc()` automatically, so you don't have to take care of
resetting them.

The allocation of an I/O port is done like this::

  err = pci_request_regions(pci, "My Chip");
  if (err < 0) { 
          kfree(chip);
          pci_disable_device(pci);
          return err;
  }
  chip->port = pci_resource_start(pci, 0);

It will reserve the I/O port region of 8 bytes of the given PCI device.
The returned value, ``chip->res_port``, is allocated via
:c:func:`kmalloc()` by :c:func:`request_region()`. The pointer
must be released via :c:func:`kfree()`, but there is a problem with
this. This issue will be explained later.

The allocation of an interrupt source is done like this::

  if (request_irq(pci->irq, snd_mychip_interrupt,
                  IRQF_SHARED, KBUILD_MODNAME, chip)) {
          printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
          snd_mychip_free(chip);
          return -EBUSY;
  }
  chip->irq = pci->irq;

where :c:func:`snd_mychip_interrupt()` is the interrupt handler
defined `later <PCM Interrupt Handler_>`__. Note that
``chip->irq`` should be defined only when :c:func:`request_irq()`
succeeded.

On the PCI bus, interrupts can be shared. Thus, ``IRQF_SHARED`` is used
as the interrupt flag of :c:func:`request_irq()`.

The last argument of :c:func:`request_irq()` is the data pointer
passed to the interrupt handler. Usually, the chip-specific record is
used for that, but you can use what you like, too.

I won't give details about the interrupt handler at this point, but at
least its appearance can be explained now. The interrupt handler looks
usually as follows::

  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
  {
          struct mychip *chip = dev_id;
          ....
          return IRQ_HANDLED;
  }

After requesting the IRQ, you can passed it to ``card->sync_irq``
field::

          card->irq = chip->irq;

This allows the PCM core to automatically call
:c:func:`synchronize_irq()` at the right time, like before ``hw_free``.
See the later section `sync_stop callback`_ for details.

Now let's write the corresponding destructor for the resources above.
The role of destructor is simple: disable the hardware (if already
activated) and release the resources. So far, we have no hardware part,
so the disabling code is not written here.

To release the resources, the “check-and-release” method is a safer way.
For the interrupt, do like this::

  if (chip->irq >= 0)
          free_irq(chip->irq, chip);

Since the irq number can start from 0, you should initialize
``chip->irq`` with a negative value (e.g. -1), so that you can check
the validity of the irq number as above.

When you requested I/O ports or memory regions via
:c:func:`pci_request_region()` or
:c:func:`pci_request_regions()` like in this example, release the
resource(s) using the corresponding function,
:c:func:`pci_release_region()` or
:c:func:`pci_release_regions()`::

  pci_release_regions(chip->pci);

When you requested manually via :c:func:`request_region()` or
:c:func:`request_mem_region()`, you can release it via
:c:func:`release_resource()`. Suppose that you keep the resource
pointer returned from :c:func:`request_region()` in
chip->res_port, the release procedure looks like::

  release_and_free_resource(chip->res_port);

Don't forget to call :c:func:`pci_disable_device()` before the
end.

And finally, release the chip-specific record::

  kfree(chip);

We didn't implement the hardware disabling part above. If you
need to do this, please note that the destructor may be called even
before the initialization of the chip is completed. It would be better
to have a flag to skip hardware disabling if the hardware was not
initialized yet.

When the chip-data is assigned to the card using
:c:func:`snd_device_new()` with ``SNDRV_DEV_LOWLELVEL``, its
destructor is called last. That is, it is assured that all other
components like PCMs and controls have already been released. You don't
have to stop PCMs, etc. explicitly, but just call low-level hardware
stopping.

The management of a memory-mapped region is almost as same as the
management of an I/O port. You'll need two fields as follows::

  struct mychip {
          ....
          unsigned long iobase_phys;
          void __iomem *iobase_virt;
  };

and the allocation would look like below::

  err = pci_request_regions(pci, "My Chip");
  if (err < 0) {
          kfree(chip);
          return err;
  }
  chip->iobase_phys = pci_resource_start(pci, 0);
  chip->iobase_virt = ioremap(chip->iobase_phys,
                                      pci_resource_len(pci, 0));

and the corresponding destructor would be::

  static int snd_mychip_free(struct mychip *chip)
  {
          ....
          if (chip->iobase_virt)
                  iounmap(chip->iobase_virt);
          ....
          pci_release_regions(chip->pci);
          ....
  }

Of course, a modern way with :c:func:`pci_iomap()` will make things a
bit easier, too::

  err = pci_request_regions(pci, "My Chip");
  if (err < 0) {
          kfree(chip);
          return err;
  }
  chip->iobase_virt = pci_iomap(pci, 0, 0);

which is paired with :c:func:`pci_iounmap()` at destructor.


PCI Entries
-----------

So far, so good. Let's finish the missing PCI stuff. At first, we need a
struct pci_device_id table for
this chipset. It's a table of PCI vendor/device ID number, and some
masks.

For example::

  static struct pci_device_id snd_mychip_ids[] = {
          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
          ....
          { 0, }
  };
  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);

The first and second fields of the struct pci_device_id are the vendor
and device IDs. If you have no reason to filter the matching devices, you can
leave the remaining fields as above. The last field of the
struct pci_device_id contains private data for this entry. You can specify
any value here, for example, to define specific operations for supported
device IDs. Such an example is found in the intel8x0 driver.

The last entry of this list is the terminator. You must specify this
all-zero entry.

Then, prepare the struct pci_driver
record::

  static struct pci_driver driver = {
          .name = KBUILD_MODNAME,
          .id_table = snd_mychip_ids,
          .probe = snd_mychip_probe,
          .remove = snd_mychip_remove,
  };

The ``probe`` and ``remove`` functions have already been defined in
the previous sections. The ``name`` field is the name string of this
device. Note that you must not use slashes (“/”) in this string.

And at last, the module entries::

  static int __init alsa_card_mychip_init(void)
  {
          return pci_register_driver(&driver);
  }

  static void __exit alsa_card_mychip_exit(void)
  {
          pci_unregister_driver(&driver);
  }

  module_init(alsa_card_mychip_init)
  module_exit(alsa_card_mychip_exit)

Note that these module entries are tagged with ``__init`` and ``__exit``
prefixes.

That's all!

PCM Interface
=============

General
-------

The PCM middle layer of ALSA is quite powerful and it is only necessary
for each driver to implement the low-level functions to access its
hardware.

To access the PCM layer, you need to include ``<sound/pcm.h>``
first. In addition, ``<sound/pcm_params.h>`` might be needed if you
access some functions related with hw_param.

Each card device can have up to four PCM instances. A PCM instance
corresponds to a PCM device file. The limitation of number of instances
comes only from the available bit size of Linux' device numbers.
Once 64bit device numbers are used, we'll have more PCM instances
available.

A PCM instance consists of PCM playback and capture streams, and each
PCM stream consists of one or more PCM substreams. Some soundcards
support multiple playback functions. For example, emu10k1 has a PCM
playback of 32 stereo substreams. In this case, at each open, a free
substream is (usually) automatically chosen and opened. Meanwhile, when
only one substream exists and it was already opened, a subsequent open
will either block or error with ``EAGAIN`` according to the file open
mode. But you don't have to care about such details in your driver. The
PCM middle layer will take care of such work.

Full Code Example
-----------------

The example code below does not include any hardware access routines but
shows only the skeleton, how to build up the PCM interfaces::

      #include <sound/pcm.h>
      ....

      /* hardware definition */
      static struct snd_pcm_hardware snd_mychip_playback_hw = {
              .info = (SNDRV_PCM_INFO_MMAP |
                       SNDRV_PCM_INFO_INTERLEAVED |
                       SNDRV_PCM_INFO_BLOCK_TRANSFER |
                       SNDRV_PCM_INFO_MMAP_VALID),
              .formats =          SNDRV_PCM_FMTBIT_S16_LE,
              .rates =            SNDRV_PCM_RATE_8000_48000,
              .rate_min =         8000,
              .rate_max =         48000,
              .channels_min =     2,
              .channels_max =     2,
              .buffer_bytes_max = 32768,
              .period_bytes_min = 4096,
              .period_bytes_max = 32768,
              .periods_min =      1,
              .periods_max =      1024,
      };

      /* hardware definition */
      static struct snd_pcm_hardware snd_mychip_capture_hw = {
              .info = (SNDRV_PCM_INFO_MMAP |
                       SNDRV_PCM_INFO_INTERLEAVED |
                       SNDRV_PCM_INFO_BLOCK_TRANSFER |
                       SNDRV_PCM_INFO_MMAP_VALID),
              .formats =          SNDRV_PCM_FMTBIT_S16_LE,
              .rates =            SNDRV_PCM_RATE_8000_48000,
              .rate_min =         8000,
              .rate_max =         48000,
              .channels_min =     2,
              .channels_max =     2,
              .buffer_bytes_max = 32768,
              .period_bytes_min = 4096,
              .period_bytes_max = 32768,
              .periods_min =      1,
              .periods_max =      1024,
      };

      /* open callback */
      static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
      {
              struct mychip *chip = snd_pcm_substream_chip(substream);
              struct snd_pcm_runtime *runtime = substream->runtime;

              runtime->hw = snd_mychip_playback_hw;
              /* more hardware-initialization will be done here */
              ....
              return 0;
      }

      /* close callback */
      static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
      {
              struct mychip *chip = snd_pcm_substream_chip(substream);
              /* the hardware-specific codes will be here */
              ....
              return 0;

      }

      /* open callback */
      static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
      {
              struct mychip *chip = snd_pcm_substream_chip(substream);
              struct snd_pcm_runtime *runtime = substream->runtime;

              runtime->hw = snd_mychip_capture_hw;
              /* more hardware-initialization will be done here */
              ....
              return 0;
      }

      /* close callback */
      static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
      {
              struct mychip *chip = snd_pcm_substream_chip(substream);
              /* the hardware-specific codes will be here */
              ....
              return 0;
      }

      /* hw_params callback */
      static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
                                   struct snd_pcm_hw_params *hw_params)
      {
              /* the hardware-specific codes will be here */
              ....
              return 0;
      }

      /* hw_free callback */
      static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
      {
              /* the hardware-specific codes will be here */
              ....
              return 0;
      }

      /* prepare callback */
      static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
      {
              struct mychip *chip = snd_pcm_substream_chip(substream);
              struct snd_pcm_runtime *runtime = substream->runtime;

              /* set up the hardware with the current configuration
               * for example...
               */
              mychip_set_sample_format(chip, runtime->format);
              mychip_set_sample_rate(chip, runtime->rate);
              mychip_set_channels(chip, runtime->channels);
              mychip_set_dma_setup(chip, runtime->dma_addr,
                                   chip->buffer_size,
                                   chip->period_size);
              return 0;
      }

      /* trigger callback */
      static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
                                        int cmd)
      {
              switch (cmd) {
              case SNDRV_PCM_TRIGGER_START:
                      /* do something to start the PCM engine */
                      ....
                      break;
              case SNDRV_PCM_TRIGGER_STOP:
                      /* do something to stop the PCM engine */
                      ....
                      break;
              default:
                      return -EINVAL;
              }
      }

      /* pointer callback */
      static snd_pcm_uframes_t
      snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
      {
              struct mychip *chip = snd_pcm_substream_chip(substream);
              unsigned int current_ptr;

              /* get the current hardware pointer */
              current_ptr = mychip_get_hw_pointer(chip);
              return current_ptr;
      }

      /* operators */
      static struct snd_pcm_ops snd_mychip_playback_ops = {
              .open =        snd_mychip_playback_open,
              .close =       snd_mychip_playback_close,
              .hw_params =   snd_mychip_pcm_hw_params,
              .hw_free =     snd_mychip_pcm_hw_free,
              .prepare =     snd_mychip_pcm_prepare,
              .trigger =     snd_mychip_pcm_trigger,
              .pointer =     snd_mychip_pcm_pointer,
      };

      /* operators */
      static struct snd_pcm_ops snd_mychip_capture_ops = {
              .open =        snd_mychip_capture_open,
              .close =       snd_mychip_capture_close,
              .hw_params =   snd_mychip_pcm_hw_params,
              .hw_free =     snd_mychip_pcm_hw_free,
              .prepare =     snd_mychip_pcm_prepare,
              .trigger =     snd_mychip_pcm_trigger,
              .pointer =     snd_mychip_pcm_pointer,
      };

      /*
       *  definitions of capture are omitted here...
       */

      /* create a pcm device */
      static int snd_mychip_new_pcm(struct mychip *chip)
      {
              struct snd_pcm *pcm;
              int err;

              err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
              if (err < 0)
                      return err;
              pcm->private_data = chip;
              strcpy(pcm->name, "My Chip");
              chip->pcm = pcm;
              /* set operators */
              snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                              &snd_mychip_playback_ops);
              snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
                              &snd_mychip_capture_ops);
              /* pre-allocation of buffers */
              /* NOTE: this may fail */
              snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
                                             &chip->pci->dev,
                                             64*1024, 64*1024);
              return 0;
      }


PCM Constructor
---------------

A PCM instance is allocated by the :c:func:`snd_pcm_new()`
function. It would be better to create a constructor for the PCM, namely::

  static int snd_mychip_new_pcm(struct mychip *chip)
  {
          struct snd_pcm *pcm;
          int err;

          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
          if (err < 0) 
                  return err;
          pcm->private_data = chip;
          strcpy(pcm->name, "My Chip");
          chip->pcm = pcm;
          ...
          return 0;
  }

The :c:func:`snd_pcm_new()` function takes six arguments. The
first argument is the card pointer to which this PCM is assigned, and
the second is the ID string.

The third argument (``index``, 0 in the above) is the index of this new
PCM. It begins from zero. If you create more than one PCM instances,
specify the different numbers in this argument. For example, ``index =
1`` for the second PCM device.

The fourth and fifth arguments are the number of substreams for playback
and capture, respectively. Here 1 is used for both arguments. When no
playback or capture substreams are available, pass 0 to the
corresponding argument.

If a chip supports multiple playbacks or captures, you can specify more
numbers, but they must be handled properly in open/close, etc.
callbacks. When you need to know which substream you are referring to,
then it can be obtained from struct snd_pcm_substream data passed to each
callback as follows::

  struct snd_pcm_substream *substream;
  int index = substream->number;


After the PCM is created, you need to set operators for each PCM stream::

  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                  &snd_mychip_playback_ops);
  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
                  &snd_mychip_capture_ops);

The operators are defined typically like this::

  static struct snd_pcm_ops snd_mychip_playback_ops = {
          .open =        snd_mychip_pcm_open,
          .close =       snd_mychip_pcm_close,
          .hw_params =   snd_mychip_pcm_hw_params,
          .hw_free =     snd_mychip_pcm_hw_free,
          .prepare =     snd_mychip_pcm_prepare,
          .trigger =     snd_mychip_pcm_trigger,
          .pointer =     snd_mychip_pcm_pointer,
  };

All the callbacks are described in the Operators_ subsection.

After setting the operators, you probably will want to pre-allocate the
buffer and set up the managed allocation mode.
For that, simply call the following::

  snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
                                 &chip->pci->dev,
                                 64*1024, 64*1024);

It will allocate a buffer up to 64kB by default. Buffer management
details will be described in the later section `Buffer and Memory
Management`_.

Additionally, you can set some extra information for this PCM in
``pcm->info_flags``. The available values are defined as
``SNDRV_PCM_INFO_XXX`` in ``<sound/asound.h>``, which is used for the
hardware definition (described later). When your soundchip supports only
half-duplex, specify it like this::

  pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;


... And the Destructor?
-----------------------

The destructor for a PCM instance is not always necessary. Since the PCM
device will be released by the middle layer code automatically, you
don't have to call the destructor explicitly.

The destructor would be necessary if you created special records
internally and needed to release them. In such a case, set the
destructor function to ``pcm->private_free``::

      static void mychip_pcm_free(struct snd_pcm *pcm)
      {
              struct mychip *chip = snd_pcm_chip(pcm);
              /* free your own data */
              kfree(chip->my_private_pcm_data);
              /* do what you like else */
              ....
      }

      static int snd_mychip_new_pcm(struct mychip *chip)
      {
              struct snd_pcm *pcm;
              ....
              /* allocate your own data */
              chip->my_private_pcm_data = kmalloc(...);
              /* set the destructor */
              pcm->private_data = chip;
              pcm->private_free = mychip_pcm_free;
              ....
      }



Runtime Pointer - The Chest of PCM Information
----------------------------------------------

When the PCM substream is opened, a PCM runtime instance is allocated
and assigned to the substream. This pointer is accessible via
``substream->runtime``. This runtime pointer holds most information you
need to control the PCM: a copy of hw_params and sw_params
configurations, the buffer pointers, mmap records, spinlocks, etc.

The definition of runtime instance is found in ``<sound/pcm.h>``. Here
is the relevant part of this file::

  struct _snd_pcm_runtime {
          /* -- Status -- */
          struct snd_pcm_substream *trigger_master;
          snd_timestamp_t trigger_tstamp; /* trigger timestamp */
          int overrange;
          snd_pcm_uframes_t avail_max;
          snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
          snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
  
          /* -- HW params -- */
          snd_pcm_access_t access; /* access mode */
          snd_pcm_format_t format; /* SNDRV_PCM_FORMAT_* */
          snd_pcm_subformat_t subformat; /* subformat */
          unsigned int rate;  /* rate in Hz */
          unsigned int channels;  /* channels */
          snd_pcm_uframes_t period_size; /* period size */
          unsigned int periods;  /* periods */
          snd_pcm_uframes_t buffer_size; /* buffer size */
          unsigned int tick_time;  /* tick time */
          snd_pcm_uframes_t min_align; /* Min alignment for the format */
          size_t byte_align;
          unsigned int frame_bits;
          unsigned int sample_bits;
          unsigned int info;
          unsigned int rate_num;
          unsigned int rate_den;
  
          /* -- SW params -- */
          struct timespec tstamp_mode; /* mmap timestamp is updated */
          unsigned int period_step;
          unsigned int sleep_min;  /* min ticks to sleep */
          snd_pcm_uframes_t start_threshold;
          /*
           * The following two thresholds alleviate playback buffer underruns; when
           * hw_avail drops below the threshold, the respective action is triggered:
           */
          snd_pcm_uframes_t stop_threshold; /* - stop playback */
          snd_pcm_uframes_t silence_threshold; /* - pre-fill buffer with silence */
          snd_pcm_uframes_t silence_size;       /* max size of silence pre-fill; when >= boundary,
                                                 * fill played area with silence immediately */
          snd_pcm_uframes_t boundary; /* pointers wrap point */
  
          /* internal data of auto-silencer */
          snd_pcm_uframes_t silence_start; /* starting pointer to silence area */
          snd_pcm_uframes_t silence_filled; /* size filled with silence */
  
          snd_pcm_sync_id_t sync;  /* hardware synchronization ID */
  
          /* -- mmap -- */
          volatile struct snd_pcm_mmap_status *status;
          volatile struct snd_pcm_mmap_control *control;
          atomic_t mmap_count;
  
          /* -- locking / scheduling -- */
          spinlock_t lock;
          wait_queue_head_t sleep;
          struct timer_list tick_timer;
          struct fasync_struct *fasync;

          /* -- private section -- */
          void *private_data;
          void (*private_free)(struct snd_pcm_runtime *runtime);
  
          /* -- hardware description -- */
          struct snd_pcm_hardware hw;
          struct snd_pcm_hw_constraints hw_constraints;
  
          /* -- timer -- */
          unsigned int timer_resolution; /* timer resolution */
  
          /* -- DMA -- */           
          unsigned char *dma_area; /* DMA area */
          dma_addr_t dma_addr;  /* physical bus address (not accessible from main CPU) */
          size_t dma_bytes;  /* size of DMA area */
  
          struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
  
  #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
          /* -- OSS things -- */
          struct snd_pcm_oss_runtime oss;
  #endif
  };


For the operators (callbacks) of each sound driver, most of these
records are supposed to be read-only. Only the PCM middle-layer changes
/ updates them. The exceptions are the hardware description (hw) DMA
buffer information and the private data. Besides, if you use the
standard managed buffer allocation mode, you don't need to set the
DMA buffer information by yourself.

In the sections below, important records are explained.

Hardware Description
~~~~~~~~~~~~~~~~~~~~

The hardware descriptor (struct snd_pcm_hardware) contains the definitions of
the fundamental hardware configuration. Above all, you'll need to define this
in the `PCM open callback`_. Note that the runtime instance holds a copy of
the descriptor, not a pointer to the existing descriptor. That is,
in the open callback, you can modify the copied descriptor
(``runtime->hw``) as you need. For example, if the maximum number of
channels is 1 only on some chip models, you can still use the same
hardware descriptor and change the channels_max later::

          struct snd_pcm_runtime *runtime = substream->runtime;
          ...
          runtime->hw = snd_mychip_playback_hw; /* common definition */
          if (chip->model == VERY_OLD_ONE)
                  runtime->hw.channels_max = 1;

Typically, you'll have a hardware descriptor as below::

  static struct snd_pcm_hardware snd_mychip_playback_hw = {
          .info = (SNDRV_PCM_INFO_MMAP |
                   SNDRV_PCM_INFO_INTERLEAVED |
                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
                   SNDRV_PCM_INFO_MMAP_VALID),
          .formats =          SNDRV_PCM_FMTBIT_S16_LE,
          .rates =            SNDRV_PCM_RATE_8000_48000,
          .rate_min =         8000,
          .rate_max =         48000,
          .channels_min =     2,
          .channels_max =     2,
          .buffer_bytes_max = 32768,
          .period_bytes_min = 4096,
          .period_bytes_max = 32768,
          .periods_min =      1,
          .periods_max =      1024,
  };

-  The ``info`` field contains the type and capabilities of this
   PCM. The bit flags are defined in ``<sound/asound.h>`` as
   ``SNDRV_PCM_INFO_XXX``. Here, at least, you have to specify whether
   mmap is supported and which interleaving formats are
   supported. When the hardware supports mmap, add the
   ``SNDRV_PCM_INFO_MMAP`` flag here. When the hardware supports the
   interleaved or the non-interleaved formats, the
   ``SNDRV_PCM_INFO_INTERLEAVED`` or ``SNDRV_PCM_INFO_NONINTERLEAVED``
   flag must be set, respectively. If both are supported, you can set
   both, too.

   In the above example, ``MMAP_VALID`` and ``BLOCK_TRANSFER`` are
   specified for the OSS mmap mode. Usually both are set. Of course,
   ``MMAP_VALID`` is set only if mmap is really supported.

   The other possible flags are ``SNDRV_PCM_INFO_PAUSE`` and
   ``SNDRV_PCM_INFO_RESUME``. The ``PAUSE`` bit means that the PCM
   supports the “pause” operation, while the ``RESUME`` bit means that
   the PCM supports the full “suspend/resume” operation. If the
   ``PAUSE`` flag is set, the ``trigger`` callback below must handle
   the corresponding (pause push/release) commands. The suspend/resume
   trigger commands can be defined even without the ``RESUME``
   flag. See the `Power Management`_ section for details.

   When the PCM substreams can be synchronized (typically,
   synchronized start/stop of a playback and a capture stream), you
   can give ``SNDRV_PCM_INFO_SYNC_START``, too. In this case, you'll
   need to check the linked-list of PCM substreams in the trigger
   callback. This will be described in a later section.

-  The ``formats`` field contains the bit-flags of supported formats
   (``SNDRV_PCM_FMTBIT_XXX``). If the hardware supports more than one
   format, give all or'ed bits. In the example above, the signed 16bit
   little-endian format is specified.

-  The ``rates`` field contains the bit-flags of supported rates
   (``SNDRV_PCM_RATE_XXX``). When the chip supports continuous rates,
   pass the ``CONTINUOUS`` bit additionally. The pre-defined rate bits
   are provided only for typical rates. If your chip supports
   unconventional rates, you need to add the ``KNOT`` bit and set up
   the hardware constraint manually (explained later).

-  ``rate_min`` and ``rate_max`` define the minimum and maximum sample
   rate. This should correspond somehow to ``rates`` bits.

-  ``channels_min`` and ``channels_max`` define, as you might have already
   expected, the minimum and maximum number of channels.

-  ``buffer_bytes_max`` defines the maximum buffer size in
   bytes. There is no ``buffer_bytes_min`` field, since it can be
   calculated from the minimum period size and the minimum number of
   periods. Meanwhile, ``period_bytes_min`` and ``period_bytes_max``
   define the minimum and maximum size of the period in bytes.
   ``periods_max`` and ``periods_min`` define the maximum and minimum
   number of periods in the buffer.

   The “period” is a term that corresponds to a fragment in the OSS
   world. The period defines the point at which a PCM interrupt is
   generated. This point strongly depends on the hardware. Generally,
   a smaller period size will give you more interrupts, which results
   in being able to fill/drain the buffer more timely. In the case of
   capture, this size defines the input latency. On the other hand,
   the whole buffer size defines the output latency for the playback
   direction.

-  There is also a field ``fifo_size``. This specifies the size of the
   hardware FIFO, but currently it is neither used by the drivers nor
   in the alsa-lib. So, you can ignore this field.

PCM Configurations
~~~~~~~~~~~~~~~~~~

Ok, let's go back again to the PCM runtime records. The most
frequently referred records in the runtime instance are the PCM
configurations. The PCM configurations are stored in the runtime
instance after the application sends ``hw_params`` data via
alsa-lib. There are many fields copied from hw_params and sw_params
structs. For example, ``format`` holds the format type chosen by the
application. This field contains the enum value
``SNDRV_PCM_FORMAT_XXX``.

One thing to be noted is that the configured buffer and period sizes
are stored in “frames” in the runtime. In the ALSA world, ``1 frame =
channels \* samples-size``. For conversion between frames and bytes,
you can use the :c:func:`frames_to_bytes()` and
:c:func:`bytes_to_frames()` helper functions::

  period_bytes = frames_to_bytes(runtime, runtime->period_size);

Also, many software parameters (sw_params) are stored in frames, too.
Please check the type of the field. ``snd_pcm_uframes_t`` is for
frames as unsigned integer while ``snd_pcm_sframes_t`` is for
frames as signed integer.

DMA Buffer Information
~~~~~~~~~~~~~~~~~~~~~~

The DMA buffer is defined by the following four fields: ``dma_area``,
``dma_addr``, ``dma_bytes`` and ``dma_private``. ``dma_area``
holds the buffer pointer (the logical address). You can call
:c:func:`memcpy()` from/to this pointer. Meanwhile, ``dma_addr`` holds
the physical address of the buffer. This field is specified only when
the buffer is a linear buffer. ``dma_bytes`` holds the size of the
buffer in bytes. ``dma_private`` is used for the ALSA DMA allocator.

If you use either the managed buffer allocation mode or the standard
API function :c:func:`snd_pcm_lib_malloc_pages()` for allocating the buffer,
these fields are set by the ALSA middle layer, and you should *not*
change them by yourself. You can read them but not write them. On the
other hand, if you want to allocate the buffer by yourself, you'll
need to manage it in the hw_params callback. At least, ``dma_bytes`` is
mandatory. ``dma_area`` is necessary when the buffer is mmapped. If
your driver doesn't support mmap, this field is not
necessary. ``dma_addr`` is also optional. You can use dma_private as
you like, too.

Running Status
~~~~~~~~~~~~~~

The running status can be referred via ``runtime->status``. This is
a pointer to a struct snd_pcm_mmap_status record.
For example, you can get the current
DMA hardware pointer via ``runtime->status->hw_ptr``.

The DMA application pointer can be referred via ``runtime->control``,
which points to a struct snd_pcm_mmap_control record.
However, accessing this value directly is not recommended.

Private Data
~~~~~~~~~~~~

You can allocate a record for the substream and store it in
``runtime->private_data``. Usually, this is done in the `PCM open
callback`_. Don't mix this with ``pcm->private_data``. The
``pcm->private_data`` usually points to the chip instance assigned
statically at creation time of the PCM device, while
``runtime->private_data``
points to a dynamic data structure created in the PCM open
callback::

  static int snd_xxx_open(struct snd_pcm_substream *substream)
  {
          struct my_pcm_data *data;
          ....
          data = kmalloc(sizeof(*data), GFP_KERNEL);
          substream->runtime->private_data = data;
          ....
  }


The allocated object must be released in the `close callback`_.

Operators
---------

OK, now let me give details about each PCM callback (``ops``). In
general, every callback must return 0 if successful, or a negative
error number such as ``-EINVAL``. To choose an appropriate error
number, it is advised to check what value other parts of the kernel
return when the same kind of request fails.

Each callback function takes at least one argument containing a
struct snd_pcm_substream pointer. To retrieve the chip
record from the given substream instance, you can use the following
macro::

  int xxx(...) {
          struct mychip *chip = snd_pcm_substream_chip(substream);
          ....
  }

The macro reads ``substream->private_data``, which is a copy of
``pcm->private_data``. You can override the former if you need to
assign different data records per PCM substream. For example, the
cmi8330 driver assigns different ``private_data`` for playback and
capture directions, because it uses two different codecs (SB- and
AD-compatible) for different directions.

PCM open callback
~~~~~~~~~~~~~~~~~

::

  static int snd_xxx_open(struct snd_pcm_substream *substream);

This is called when a PCM substream is opened.

At least, here you have to initialize the ``runtime->hw``
record. Typically, this is done like this::

  static int snd_xxx_open(struct snd_pcm_substream *substream)
  {
          struct mychip *chip = snd_pcm_substream_chip(substream);
          struct snd_pcm_runtime *runtime = substream->runtime;

          runtime->hw = snd_mychip_playback_hw;
          return 0;
  }

where ``snd_mychip_playback_hw`` is the pre-defined hardware
description.

You can allocate private data in this callback, as described in the
`Private Data`_ section.

If the hardware configuration needs more constraints, set the hardware
constraints here, too. See Constraints_ for more details.

close callback
~~~~~~~~~~~~~~

::

  static int snd_xxx_close(struct snd_pcm_substream *substream);


Obviously, this is called when a PCM substream is closed.

Any private instance for a PCM substream allocated in the ``open``
callback will be released here::

  static int snd_xxx_close(struct snd_pcm_substream *substream)
  {
          ....
          kfree(substream->runtime->private_data);
          ....
  }

ioctl callback
~~~~~~~~~~~~~~

This is used for any special call to PCM ioctls. But usually you can
leave it NULL, then the PCM core calls the generic ioctl callback
function :c:func:`snd_pcm_lib_ioctl()`.  If you need to deal with a
unique setup of channel info or reset procedure, you can pass your own
callback function here.

hw_params callback
~~~~~~~~~~~~~~~~~~~

::

  static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *hw_params);

This is called when the hardware parameters (``hw_params``) are set up
by the application, that is, once when the buffer size, the period
size, the format, etc. are defined for the PCM substream.

Many hardware setups should be done in this callback, including the
allocation of buffers.

Parameters to be initialized are retrieved by the
:c:func:`params_xxx()` macros.

When you choose managed buffer allocation mode for the substream,
a buffer is already allocated before this callback gets
called. Alternatively, you can call a helper function below for
allocating the buffer::

  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));

:c:func:`snd_pcm_lib_malloc_pages()` is available only when the
DMA buffers have been pre-allocated. See the section `Buffer Types`_
for more details.

Note that this one and the ``prepare`` callback may be called multiple
times per initialization. For example, the OSS emulation may call these
callbacks at each change via its ioctl.

Thus, you need to be careful not to allocate the same buffers many
times, which will lead to memory leaks! Calling the helper function
above many times is OK. It will release the previous buffer
automatically when it was already allocated.

Another note is that this callback is non-atomic (schedulable) by
default, i.e. when no ``nonatomic`` flag set. This is important,
because the ``trigger`` callback is atomic (non-schedulable). That is,
mutexes or any schedule-related functions are not available in the
``trigger`` callback. Please see the subsection Atomicity_ for
details.

hw_free callback
~~~~~~~~~~~~~~~~~

::

  static int snd_xxx_hw_free(struct snd_pcm_substream *substream);

This is called to release the resources allocated via
``hw_params``.

This function is always called before the close callback is called.
Also, the callback may be called multiple times, too. Keep track
whether each resource was already released.

When you have chosen managed buffer allocation mode for the PCM
substream, the allocated PCM buffer will be automatically released
after this callback gets called.  Otherwise you'll have to release the
buffer manually.  Typically, when the buffer was allocated from the
pre-allocated pool, you can use the standard API function
:c:func:`snd_pcm_lib_malloc_pages()` like::

  snd_pcm_lib_free_pages(substream);

prepare callback
~~~~~~~~~~~~~~~~

::

  static int snd_xxx_prepare(struct snd_pcm_substream *substream);

This callback is called when the PCM is “prepared”. You can set the
format type, sample rate, etc. here. The difference from ``hw_params``
is that the ``prepare`` callback will be called each time
:c:func:`snd_pcm_prepare()` is called, i.e. when recovering after
underruns, etc.

Note that this callback is non-atomic. You can use
schedule-related functions safely in this callback.

In this and the following callbacks, you can refer to the values via
the runtime record, ``substream->runtime``. For example, to get the
current rate, format or channels, access to ``runtime->rate``,
``runtime->format`` or ``runtime->channels``, respectively. The
physical address of the allocated buffer is set to
``runtime->dma_area``. The buffer and period sizes are in
--> --------------------

--> maximum size reached

--> --------------------

[ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge