diff options
Diffstat (limited to 'Documentation/DocBook')
-rw-r--r-- | Documentation/DocBook/Makefile | 3 | ||||
-rw-r--r-- | Documentation/DocBook/alsa-driver-api.tmpl | 109 | ||||
-rw-r--r-- | Documentation/DocBook/writing-an-alsa-driver.tmpl | 6216 |
3 files changed, 6327 insertions, 1 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 1462ed86d40..a3a83d38f96 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -12,7 +12,8 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ - mac80211.xml debugobjects.xml sh.xml regulator.xml + mac80211.xml debugobjects.xml sh.xml regulator.xml \ + alsa-driver-api.xml writing-an-alsa-driver.xml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/alsa-driver-api.tmpl b/Documentation/DocBook/alsa-driver-api.tmpl new file mode 100644 index 00000000000..0230a96f056 --- /dev/null +++ b/Documentation/DocBook/alsa-driver-api.tmpl @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<!-- ****************************************************** --> +<!-- Header --> +<!-- ****************************************************** --> +<book id="ALSA-Driver-API"> + <bookinfo> + <title>The ALSA Driver API</title> + + <legalnotice> + <para> + This document is free; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + </para> + + <para> + This document is distributed in the hope that it will be useful, + but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the + implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE</emphasis>. See the GNU General Public License + for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + </legalnotice> + + </bookinfo> + +<toc></toc> + + <chapter><title>Management of Cards and Devices</title> + <sect1><title>Card Management</title> +!Esound/core/init.c + </sect1> + <sect1><title>Device Components</title> +!Esound/core/device.c + </sect1> + <sect1><title>Module requests and Device File Entries</title> +!Esound/core/sound.c + </sect1> + <sect1><title>Memory Management Helpers</title> +!Esound/core/memory.c +!Esound/core/memalloc.c + </sect1> + </chapter> + <chapter><title>PCM API</title> + <sect1><title>PCM Core</title> +!Esound/core/pcm.c +!Esound/core/pcm_lib.c +!Esound/core/pcm_native.c + </sect1> + <sect1><title>PCM Format Helpers</title> +!Esound/core/pcm_misc.c + </sect1> + <sect1><title>PCM Memory Management</title> +!Esound/core/pcm_memory.c + </sect1> + </chapter> + <chapter><title>Control/Mixer API</title> + <sect1><title>General Control Interface</title> +!Esound/core/control.c + </sect1> + <sect1><title>AC97 Codec API</title> +!Esound/pci/ac97/ac97_codec.c +!Esound/pci/ac97/ac97_pcm.c + </sect1> + <sect1><title>Virtual Master Control API</title> +!Esound/core/vmaster.c +!Iinclude/sound/control.h + </sect1> + </chapter> + <chapter><title>MIDI API</title> + <sect1><title>Raw MIDI API</title> +!Esound/core/rawmidi.c + </sect1> + <sect1><title>MPU401-UART API</title> +!Esound/drivers/mpu401/mpu401_uart.c + </sect1> + </chapter> + <chapter><title>Proc Info API</title> + <sect1><title>Proc Info Interface</title> +!Esound/core/info.c + </sect1> + </chapter> + <chapter><title>Miscellaneous Functions</title> + <sect1><title>Hardware-Dependent Devices API</title> +!Esound/core/hwdep.c + </sect1> + <sect1><title>Jack Abstraction Layer API</title> +!Esound/core/jack.c + </sect1> + <sect1><title>ISA DMA Helpers</title> +!Esound/core/isadma.c + </sect1> + <sect1><title>Other Helper Macros</title> +!Iinclude/sound/core.h + </sect1> + </chapter> + +</book> diff --git a/Documentation/DocBook/writing-an-alsa-driver.tmpl b/Documentation/DocBook/writing-an-alsa-driver.tmpl new file mode 100644 index 00000000000..46b08fef374 --- /dev/null +++ b/Documentation/DocBook/writing-an-alsa-driver.tmpl @@ -0,0 +1,6216 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<!-- ****************************************************** --> +<!-- Header --> +<!-- ****************************************************** --> +<book id="Writing-an-ALSA-Driver"> + <bookinfo> + <title>Writing an ALSA Driver</title> + <author> + <firstname>Takashi</firstname> + <surname>Iwai</surname> + <affiliation> + <address> + <email>tiwai@suse.de</email> + </address> + </affiliation> + </author> + + <date>Oct 15, 2007</date> + <edition>0.3.7</edition> + + <abstract> + <para> + This document describes how to write an ALSA (Advanced Linux + Sound Architecture) driver. + </para> + </abstract> + + <legalnotice> + <para> + Copyright (c) 2002-2005 Takashi Iwai <email>tiwai@suse.de</email> + </para> + + <para> + This document is free; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + </para> + + <para> + This document is distributed in the hope that it will be useful, + but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the + implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE</emphasis>. See the GNU General Public License + for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + </legalnotice> + + </bookinfo> + +<!-- ****************************************************** --> +<!-- Preface --> +<!-- ****************************************************** --> + <preface id="preface"> + <title>Preface</title> + <para> + This document describes how to write an + <ulink url="http://www.alsa-project.org/"><citetitle> + ALSA (Advanced Linux Sound Architecture)</citetitle></ulink> + 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. + </para> + + <para> + 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. + </para> + + <para> + If you are already familiar with the older ALSA ver.0.5.x API, you + can check the drivers such as <filename>sound/pci/es1938.c</filename> or + <filename>sound/pci/maestro3.c</filename> which have also almost the same + code-base in the ALSA 0.5.x tree, so you can compare the differences. + </para> + + <para> + This document is still a draft version. Any feedback and + corrections, please!! + </para> + </preface> + + +<!-- ****************************************************** --> +<!-- File Tree Structure --> +<!-- ****************************************************** --> + <chapter id="file-tree"> + <title>File Tree Structure</title> + + <section id="file-tree-general"> + <title>General</title> + <para> + The ALSA drivers are provided in two ways. + </para> + + <para> + One is the trees provided as a tarball or via cvs from the + ALSA's ftp site, and another is the 2.6 (or later) Linux kernel + tree. To synchronize both, the ALSA driver tree is split into + two different trees: alsa-kernel and alsa-driver. The former + contains purely the source code for the Linux 2.6 (or later) + tree. This tree is designed only for compilation on 2.6 or + later environment. The latter, alsa-driver, contains many subtle + files for compiling ALSA drivers outside of the Linux kernel tree, + wrapper functions for older 2.2 and 2.4 kernels, to adapt the latest kernel API, + and additional drivers which are still in development or in + tests. The drivers in alsa-driver tree will be moved to + alsa-kernel (and eventually to the 2.6 kernel tree) when they are + finished and confirmed to work fine. + </para> + + <para> + The file tree structure of ALSA driver is depicted below. Both + alsa-kernel and alsa-driver have almost the same file + structure, except for <quote>core</quote> directory. It's + named as <quote>acore</quote> in alsa-driver tree. + + <example> + <title>ALSA File Tree Structure</title> + <literallayout> + sound + /core + /oss + /seq + /oss + /instr + /ioctl32 + /include + /drivers + /mpu401 + /opl3 + /i2c + /l3 + /synth + /emux + /pci + /(cards) + /isa + /(cards) + /arm + /ppc + /sparc + /usb + /pcmcia /(cards) + /oss + </literallayout> + </example> + </para> + </section> + + <section id="file-tree-core-directory"> + <title>core directory</title> + <para> + 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. + </para> + + <section id="file-tree-core-directory-oss"> + <title>core/oss</title> + + <para> + The codes for PCM and mixer OSS emulation modules are stored + in this directory. The rawmidi OSS emulation is included in + the ALSA rawmidi code since it's quite small. The sequencer + code is stored in <filename>core/seq/oss</filename> directory (see + <link linkend="file-tree-core-directory-seq-oss"><citetitle> + below</citetitle></link>). + </para> + </section> + + <section id="file-tree-core-directory-ioctl32"> + <title>core/ioctl32</title> + + <para> + This directory contains the 32bit-ioctl wrappers for 64bit + architectures such like x86-64, ppc64 and sparc64. For 32bit + and alpha architectures, these are not compiled. + </para> + </section> + + <section id="file-tree-core-directory-seq"> + <title>core/seq</title> + <para> + This directory and its sub-directories are for the ALSA + sequencer. This directory contains the sequencer core and + primary sequencer modules such like snd-seq-midi, + snd-seq-virmidi, etc. They are compiled only when + <constant>CONFIG_SND_SEQUENCER</constant> is set in the kernel + config. + </para> + </section> + + <section id="file-tree-core-directory-seq-oss"> + <title>core/seq/oss</title> + <para> + This contains the OSS sequencer emulation codes. + </para> + </section> + + <section id="file-tree-core-directory-deq-instr"> + <title>core/seq/instr</title> + <para> + This directory contains the modules for the sequencer + instrument layer. + </para> + </section> + </section> + + <section id="file-tree-include-directory"> + <title>include directory</title> + <para> + 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 at 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 :) + </para> + </section> + + <section id="file-tree-drivers-directory"> + <title>drivers directory</title> + <para> + 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. + </para> + + <section id="file-tree-drivers-directory-mpu401"> + <title>drivers/mpu401</title> + <para> + The MPU401 and MPU401-UART modules are stored here. + </para> + </section> + + <section id="file-tree-drivers-directory-opl3"> + <title>drivers/opl3 and opl4</title> + <para> + The OPL3 and OPL4 FM-synth stuff is found here. + </para> + </section> + </section> + + <section id="file-tree-i2c-directory"> + <title>i2c directory</title> + <para> + This contains the ALSA i2c components. + </para> + + <para> + 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. + </para> + + <section id="file-tree-i2c-directory-l3"> + <title>i2c/l3</title> + <para> + This is a sub-directory for ARM L3 i2c. + </para> + </section> + </section> + + <section id="file-tree-synth-directory"> + <title>synth directory</title> + <para> + This contains the synth middle-level modules. + </para> + + <para> + So far, there is only Emu8000/Emu10k1 synth driver under + the <filename>synth/emux</filename> sub-directory. + </para> + </section> + + <section id="file-tree-pci-directory"> + <title>pci directory</title> + <para> + This directory and its sub-directories hold the top-level card modules + for PCI soundcards and the code specific to the PCI BUS. + </para> + + <para> + 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). + </para> + </section> + + <section id="file-tree-isa-directory"> + <title>isa directory</title> + <para> + This directory and its sub-directories hold the top-level card modules + for ISA soundcards. + </para> + </section> + + <section id="file-tree-arm-ppc-sparc-directories"> + <title>arm, ppc, and sparc directories</title> + <para> + They are used for top-level card modules which are + specific to one of these architectures. + </para> + </section> + + <section id="file-tree-usb-directory"> + <title>usb directory</title> + <para> + This directory contains the USB-audio driver. In the latest version, the + USB MIDI driver is integrated in the usb-audio driver. + </para> + </section> + + <section id="file-tree-pcmcia-directory"> + <title>pcmcia directory</title> + <para> + 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. + </para> + </section> + + <section id="file-tree-oss-directory"> + <title>oss directory</title> + <para> + The OSS/Lite source files are stored here in Linux 2.6 (or + later) tree. In the ALSA driver tarball, this directory is empty, + of course :) + </para> + </section> + </chapter> + + +<!-- ****************************************************** --> +<!-- Basic Flow for PCI Drivers --> +<!-- ****************************************************** --> + <chapter id="basic-flow"> + <title>Basic Flow for PCI Drivers</title> + + <section id="basic-flow-outline"> + <title>Outline</title> + <para> + The minimum flow for PCI soundcards is as follows: + + <itemizedlist> + <listitem><para>define the PCI ID table (see the section + <link linkend="pci-resource-entries"><citetitle>PCI Entries + </citetitle></link>).</para></listitem> + <listitem><para>create <function>probe()</function> callback.</para></listitem> + <listitem><para>create <function>remove()</function> callback.</para></listitem> + <listitem><para>create a <structname>pci_driver</structname> structure + containing the three pointers above.</para></listitem> + <listitem><para>create an <function>init()</function> function just calling + the <function>pci_register_driver()</function> to register the pci_driver table + defined above.</para></listitem> + <listitem><para>create an <function>exit()</function> function to call + the <function>pci_unregister_driver()</function> function.</para></listitem> + </itemizedlist> + </para> + </section> + + <section id="basic-flow-example"> + <title>Full Code Example</title> + <para> + 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 + <function>snd_mychip_probe()</function> function + refer to details explained in the following section. + + <example> + <title>Basic Flow for PCI Drivers - Example</title> + <programlisting> +<![CDATA[ + #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 int 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 __devinit snd_mychip_create(struct snd_card *card, + struct pci_dev *pci, + struct mychip **rchip) + { + struct mychip *chip; + int err; + static 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; + } + + snd_card_set_dev(card, &pci->dev); + + *rchip = chip; + return 0; + } + + /* constructor -- see "Constructor" sub-section */ + static int __devinit 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_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; + + /* (3) */ + err = snd_mychip_create(card, pci, &chip); + if (err < 0) { + snd_card_free(card); + return err; + } + + /* (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->ioport, chip->irq); + + /* (5) */ + .... /* implemented later */ + + /* (6) */ + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return err; + } + + /* (7) */ + pci_set_drvdata(pci, card); + dev++; + return 0; + } + + /* destructor -- see the "Destructor" sub-section */ + static void __devexit snd_mychip_remove(struct pci_dev *pci) + { + snd_card_free(pci_get_drvdata(pci)); + pci_set_drvdata(pci, NULL); + } +]]> + </programlisting> + </example> + </para> + </section> + + <section id="basic-flow-constructor"> + <title>Constructor</title> + <para> + The real constructor of PCI drivers is the <function>probe</function> callback. + The <function>probe</function> callback and other component-constructors which are called + from the <function>probe</function> callback should be defined with + the <parameter>__devinit</parameter> prefix. You + cannot use the <parameter>__init</parameter> prefix for them, + because any PCI device could be a hotplug device. + </para> + + <para> + In the <function>probe</function> callback, the following scheme is often used. + </para> + + <section id="basic-flow-constructor-device-index"> + <title>1) Check and increment the device index.</title> + <para> + <informalexample> + <programlisting> +<![CDATA[ + static int dev; + .... + if (dev >= SNDRV_CARDS) + return -ENODEV; + if (!enable[dev]) { + dev++; + return -ENOENT; + } +]]> + </programlisting> + </informalexample> + + where enable[dev] is the module option. + </para> + + <para> + Each time the <function>probe</function> callback is called, check the + availability of the device. If not available, simply increment + the device index and returns. dev will be incremented also + later (<link + linkend="basic-flow-constructor-set-pci"><citetitle>step + 7</citetitle></link>). + </para> + </section> + + <section id="basic-flow-constructor-create-card"> + <title>2) Create a card instance</title> + <para> + <informalexample> + <programlisting> +<![CDATA[ + struct snd_card *card; + int err; + .... + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); +]]> + </programlisting> + </informalexample> + </para> + + <para> + The details will be explained in the section + <link linkend="card-management-card-instance"><citetitle> + Management of Cards and Components</citetitle></link>. + </para> + </section> + + <section id="basic-flow-constructor-create-main"> + <title>3) Create a main component</title> + <para> + In this part, the PCI resources are allocated. + + <informalexample> + <programlisting> +<![CDATA[ + struct mychip *chip; + .... + err = snd_mychip_create(card, pci, &chip); + if (err < 0) { + snd_card_free(card); + return err; + } +]]> + </programlisting> + </informalexample> + + The details will be explained in the section <link + linkend="pci-resource"><citetitle>PCI Resource + Management</citetitle></link>. + </para> + </section> + + <section id="basic-flow-constructor-main-component"> + <title>4) Set the driver ID and name strings.</title> + <para> + <informalexample> + <programlisting> +<![CDATA[ + strcpy(card->driver, "My Chip"); + strcpy(card->shortname, "My Own Chip 123"); + sprintf(card->longname, "%s at 0x%lx irq %i", + card->shortname, chip->ioport, chip->irq); +]]> + </programlisting> + </informalexample> + + 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. + </para> + + <para> + The shortname field is a string shown as more verbose + name. The longname field contains the information + shown in <filename>/proc/asound/cards</filename>. + </para> + </section> + + <section id="basic-flow-constructor-create-other"> + <title>5) Create other components, such as mixer, MIDI, etc.</title> + <para> + Here you define the basic components such as + <link linkend="pcm-interface"><citetitle>PCM</citetitle></link>, + mixer (e.g. <link linkend="api-ac97"><citetitle>AC97</citetitle></link>), + MIDI (e.g. <link linkend="midi-interface"><citetitle>MPU-401</citetitle></link>), + and other interfaces. + Also, if you want a <link linkend="proc-interface"><citetitle>proc + file</citetitle></link>, define it here, too. + </para> + </section> + + <section id="basic-flow-constructor-register-card"> + <title>6) Register the card instance.</title> + <para> + <informalexample> + <programlisting> +<![CDATA[ + err = snd_card_register(card); + if (err < 0) { + snd_card_free(card); + return err; + } +]]> + </programlisting> + </informalexample> + </para> + + <para> + Will be explained in the section <link + linkend="card-management-registration"><citetitle>Management + of Cards and Components</citetitle></link>, too. + </para> + </section> + + <section id="basic-flow-constructor-set-pci"> + <title>7) Set the PCI driver data and return zero.</title> + <para> + <informalexample> + <programlisting> +<![CDATA[ + pci_set_drvdata(pci, card); + dev++; + return 0; +]]> + </programlisting> + </informalexample> + + In the above, the card record is stored. This pointer is + used in the remove callback and power-management + callbacks, too. + </para> + </section> + </section> + + <section id="basic-flow-destructor"> + <title>Destructor</title> + <para> + The destructor, remove callback, simply releases the card + instance. Then the ALSA middle layer will release all the + attached components automatically. + </para> + + <para> + It would be typically like the following: + + <informalexample> + <programlisting> +<![CDATA[ + static void __devexit snd_mychip_remove(struct pci_dev *pci) + { + snd_card_free(pci_get_drvdata(pci)); + pci_set_drvdata(pci, NULL); + } +]]> + </programlisting> + </informalexample> + + The above code assumes that the card pointer is set to the PCI + driver data. + </para> + </section> + + <section id="basic-flow-header-files"> + <title>Header Files</title> + <para> + For the above example, at least the following include files + are necessary. + + <informalexample> + <programlisting> +<![CDATA[ + #include <linux/init.h> + #include <linux/pci.h> + #include <linux/slab.h> + #include <sound/core.h> + #include <sound/initval.h> +]]> + </programlisting> + </informalexample> + + 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. + </para> + + <para> + In addition to these headers, you'll need + <filename><linux/interrupt.h></filename> for interrupt + handling, and <filename><asm/io.h></filename> for I/O + access. If you use the <function>mdelay()</function> or + <function>udelay()</function> functions, you'll need to include + <filename><linux/delay.h></filename> too. + </para> + + <para> + The ALSA interfaces like the PCM and control APIs are defined in other + <filename><sound/xxx.h></filename> header files. + They have to be included after + <filename><sound/core.h></filename>. + </para> + + </section> + </chapter> + + +<!-- ****************************************************** --> +<!-- Management of Cards and Components --> +<!-- ****************************************************** --> + <chapter id="card-management"> + <title>Management of Cards and Components</title> + + <section id="card-management-card-instance"> + <title>Card Instance</title> + <para> + For each soundcard, a <quote>card</quote> record must be allocated. + </para> + + <para> + 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. + </para> + + <para> + As mentioned above, to create a card instance, call + <function>snd_card_create()</function>. + + <informalexample> + <programlisting> +<![CDATA[ + struct snd_card *card; + int err; + err = snd_card_create(index, id, module, extra_size, &card); +]]> + </programlisting> + </informalexample> + </para> + + <para> + The function takes five arguments, the card-index number, the + id string, the module pointer (usually + <constant>THIS_MODULE</constant>), + 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 <function>snd_card_create()</function>. + </para> + </section> + + <section id="card-management-component"> + <title>Components</title> + <para> + 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 <structname>snd_device</structname> object. + A component can be a PCM instance, a control interface, a raw + MIDI interface, etc. Each such instance has one component |