summaryrefslogtreecommitdiffstats
path: root/Documentation/DocBook
diff options
context:
space:
mode:
authorRandy Dunlap <randy.dunlap@oracle.com>2009-02-28 17:40:18 +0100
committerTakashi Iwai <tiwai@suse.de>2009-03-09 15:22:59 +0100
commite776ec19a47a325ee1d9ece2d983526dcd626c53 (patch)
tree4c976700bfdf49acf931a9975e27369f7265e592 /Documentation/DocBook
parent5f8206c04857965cc2ff6c395633c4fdd977dd77 (diff)
ALSA: Move ALSA docbooks to be with the rest of the kernel docbooks
Move ALSA docbooks to be with the rest of the kernel docbooks and add them to the Makefile so that they build. Latter required a few minor changes to alsa .tmpl files. (I did not remove all of the trailing whitespace in the .tmpl files.) Fixes kernel bugzilla #12726: http://bugzilla.kernel.org/show_bug.cgi?id=12726 Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: documentation_man-pages@kernel-bugs.osdl.org Cc: Nicola Soranzo <nsoranzo@tiscali.it> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'Documentation/DocBook')
-rw-r--r--Documentation/DocBook/Makefile3
-rw-r--r--Documentation/DocBook/alsa-driver-api.tmpl109
-rw-r--r--Documentation/DocBook/writing-an-alsa-driver.tmpl6216
3 files changed, 6327 insertions, 1 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 1462ed86d40a..a3a83d38f96f 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 000000000000..0230a96f0564
--- /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 000000000000..46b08fef3744
--- /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>&lt;linux/interrupt.h&gt;</filename> for interrupt
+ handling, and <filename>&lt;asm/io.h&gt;</filename> for I/O
+ access. If you use the <function>mdelay()</function> or
+ <function>udelay()</function> functions, you'll need to include
+ <filename>&lt;linux/delay.h&gt;</filename> too.
+ </para>
+
+ <para>
+ The ALSA interfaces like the PCM and control APIs are defined in other
+ <filename>&lt;sound/xxx.h&gt;</filename> header files.
+ They have to be included after
+ <filename>&lt;sound/core.h&gt;</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 retu