Whitespace-only fixes. Translators, please ignore.

This commit is contained in:
Warren Block 2013-07-24 02:39:59 +00:00
parent 9dc994da05
commit 15d408c4f4
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=42407

View file

@ -9,7 +9,7 @@
<chapterinfo> <chapterinfo>
<authorgroup> <authorgroup>
<author> <author>
<firstname>Jean-Francois</firstname> <firstname>Jean-Francois</firstname>
<surname>Dockes</surname> <surname>Dockes</surname>
<contrib>Contributed by </contrib> <contrib>Contributed by </contrib>
</author> </author>
@ -35,31 +35,35 @@
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>A system call interface (read, write, ioctls) to <para>A system call interface (read, write, ioctls) to
digitized sound and mixer functions. The ioctl command set digitized sound and mixer functions. The ioctl command set
is compatible with the legacy <emphasis>OSS</emphasis> or is compatible with the legacy <emphasis>OSS</emphasis> or
<emphasis>Voxware</emphasis> interface, allowing common <emphasis>Voxware</emphasis> interface, allowing common
multimedia applications to be ported without multimedia applications to be ported without
modification.</para> modification.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Common code for processing sound data (format <para>Common code for processing sound data (format
conversions, virtual channels).</para> conversions, virtual channels).</para>
</listitem> </listitem>
<listitem> <listitem>
<para>A uniform software interface to hardware-specific audio <para>A uniform software interface to hardware-specific audio
interface modules.</para> interface modules.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Additional support for some common hardware interfaces <para>Additional support for some common hardware interfaces
(ac97), or shared hardware-specific code (ex: ISA DMA (ac97), or shared hardware-specific code (ex: ISA DMA
routines).</para> routines).</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>The support for specific sound cards is implemented by <para>The support for specific sound cards is implemented by
hardware-specific drivers, which provide channel and mixer interfaces hardware-specific drivers, which provide channel and mixer
to plug into the generic <devicename>pcm</devicename> code.</para> interfaces to plug into the generic <devicename>pcm</devicename>
code.</para>
<para>In this chapter, the term <devicename>pcm</devicename> will <para>In this chapter, the term <devicename>pcm</devicename> will
refer to the central, common part of the sound driver, as refer to the central, common part of the sound driver, as
@ -75,8 +79,7 @@
<para>As an alternative, or in addition to starting from a working <para>As an alternative, or in addition to starting from a working
example, you can find a commented driver template at example, you can find a commented driver template at
<ulink url="http://people.FreeBSD.org/~cg/template.c"> <ulink url="http://people.FreeBSD.org/~cg/template.c">
http://people.FreeBSD.org/~cg/template.c</ulink></para> http://people.FreeBSD.org/~cg/template.c</ulink></para>
</sect1> </sect1>
<sect1 id="oss-files"> <sect1 id="oss-files">
@ -92,7 +95,6 @@
while the <filename>pci/</filename>, <filename>isa/</filename> while the <filename>pci/</filename>, <filename>isa/</filename>
and <filename>usb/</filename> directories have the drivers and <filename>usb/</filename> directories have the drivers
for PCI and ISA boards, and for USB audio devices.</para> for PCI and ISA boards, and for USB audio devices.</para>
</sect1> </sect1>
<sect1 id="pcm-probe-and-attach"> <sect1 id="pcm-probe-and-attach">
@ -107,13 +109,13 @@
<para>However, sound drivers differ in some ways:</para> <para>However, sound drivers differ in some ways:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>They declare themselves as <devicename>pcm</devicename> <para>They declare themselves as <devicename>pcm</devicename>
class devices, with a <structname>struct class devices, with a
snddev_info</structname> device private structure:</para> <structname>struct snddev_info</structname> device private
structure:</para>
<programlisting> static driver_t xxx_driver = { <programlisting> static driver_t xxx_driver = {
"pcm", "pcm",
xxx_methods, xxx_methods,
sizeof(struct snddev_info) sizeof(struct snddev_info)
@ -122,77 +124,80 @@
DRIVER_MODULE(snd_xxxpci, pci, xxx_driver, pcm_devclass, 0, 0); DRIVER_MODULE(snd_xxxpci, pci, xxx_driver, pcm_devclass, 0, 0);
MODULE_DEPEND(snd_xxxpci, snd_pcm, PCM_MINVER, PCM_PREFVER,PCM_MAXVER);</programlisting> MODULE_DEPEND(snd_xxxpci, snd_pcm, PCM_MINVER, PCM_PREFVER,PCM_MAXVER);</programlisting>
<para>Most sound drivers<indexterm><primary>device drivers</primary> <para>Most sound drivers<indexterm><primary>device
<secondary>sound</secondary></indexterm> need to store additional private drivers</primary><secondary>sound</secondary></indexterm>
information about their device. A private data structure is need to store additional private information about their
usually allocated in the attach routine. Its address is device. A private data structure is usually allocated in
passed to <devicename>pcm</devicename> by the calls to the attach routine. Its address is passed to
<function>pcm_register()</function> and <devicename>pcm</devicename> by the calls to
<function>mixer_init()</function>. <function>pcm_register()</function> and
<devicename>pcm</devicename> later passes back this address <function>mixer_init()</function>.
as a parameter in calls to the sound driver <devicename>pcm</devicename> later passes back this address
interfaces.</para> as a parameter in calls to the sound driver
interfaces.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The sound driver attach routine should declare its MIXER <para>The sound driver attach routine should declare its MIXER
or AC97 interface to <devicename>pcm</devicename> by calling or AC97 interface to <devicename>pcm</devicename> by calling
<function>mixer_init()</function>. For a MIXER interface, <function>mixer_init()</function>. For a MIXER interface,
this causes in turn a call to <link linkend="xxxmixer-init"> this causes in turn a call to <link
<function>xxxmixer_init()</function></link>.</para> linkend="xxxmixer-init"><function>xxxmixer_init()</function></link>.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The sound driver attach routine declares its general <para>The sound driver attach routine declares its general
CHANNEL configuration to <devicename>pcm</devicename> by CHANNEL configuration to <devicename>pcm</devicename> by
calling <function>pcm_register(dev, sc, nplay, calling <function>pcm_register(dev, sc, nplay,
nrec)</function>, where <varname>sc</varname> is the address nrec)</function>, where <varname>sc</varname> is the address
for the device data structure, used in further calls from for the device data structure, used in further calls from
<devicename>pcm</devicename>, and <varname>nplay</varname> <devicename>pcm</devicename>, and <varname>nplay</varname>
and <varname>nrec</varname> are the number of play and and <varname>nrec</varname> are the number of play and
record channels.</para> record channels.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The sound driver attach routine declares each of its <para>The sound driver attach routine declares each of its
channel objects by calls to channel objects by calls to
<function>pcm_addchan()</function>. This sets up the <function>pcm_addchan()</function>. This sets up the
channel glue in <devicename>pcm</devicename> and causes in channel glue in <devicename>pcm</devicename> and causes in
turn a call to turn a call to
<link linkend="xxxchannel-init"> <link linkend="xxxchannel-init">
<function>xxxchannel_init()</function></link>.</para> <function>xxxchannel_init()</function></link>.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The sound driver detach routine should call <para>The sound driver detach routine should call
<function>pcm_unregister()</function> before releasing its <function>pcm_unregister()</function> before releasing its
resources.</para> resources.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>There are two possible methods to handle non-PnP devices:</para> <para>There are two possible methods to handle non-PnP
devices:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Use a <function>device_identify()</function> method <para>Use a <function>device_identify()</function> method
(example: <filename>sound/isa/es1888.c</filename>). The (example: <filename>sound/isa/es1888.c</filename>). The
<function>device_identify()</function> method probes for the <function>device_identify()</function> method probes for the
hardware at known addresses and, if it finds a supported hardware at known addresses and, if it finds a supported
device, creates a new pcm device which is then passed to device, creates a new pcm device which is then passed to
probe/attach.</para> probe/attach.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Use a custom kernel configuration with appropriate hints <para>Use a custom kernel configuration with appropriate hints
for pcm devices (example: for pcm devices (example:
<filename>sound/isa/mss.c</filename>).</para> <filename>sound/isa/mss.c</filename>).</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para><devicename>pcm</devicename> drivers should implement <para><devicename>pcm</devicename> drivers should implement
<function>device_suspend</function>, <function>device_suspend</function>,
<function>device_resume</function> and <function>device_resume</function> and
<function>device_shutdown</function> routines, so that power <function>device_shutdown</function> routines, so that power
management and module unloading function correctly.</para> management and module unloading function correctly.</para>
</sect1> </sect1>
<sect1 id="oss-interfaces"> <sect1 id="oss-interfaces">
@ -200,7 +205,7 @@
<para>The interface between the <devicename>pcm</devicename> core <para>The interface between the <devicename>pcm</devicename> core
and the sound drivers is defined in terms of <link and the sound drivers is defined in terms of <link
linkend="kernel-objects">kernel objects</link>.</para> linkend="kernel-objects">kernel objects</link>.</para>
<para>There are two main interfaces that a sound driver will <para>There are two main interfaces that a sound driver will
usually provide: <emphasis>CHANNEL</emphasis> and either usually provide: <emphasis>CHANNEL</emphasis> and either
@ -216,86 +221,84 @@
<title>The CHANNEL Interface</title> <title>The CHANNEL Interface</title>
<sect3> <sect3>
<title>Common Notes for Function Parameters</title> <title>Common Notes for Function Parameters</title>
<para>Sound drivers usually have a private data structure to <para>Sound drivers usually have a private data structure to
describe their device, and one structure for each play and describe their device, and one structure for each play and
record data channel that it supports.</para> record data channel that it supports.</para>
<para>For all CHANNEL interface functions, the first parameter <para>For all CHANNEL interface functions, the first parameter
is an opaque pointer.</para> is an opaque pointer.</para>
<para>The second parameter is a pointer to the private
channel data structure, except for
<function>channel_init()</function> which has a pointer to the
private device structure (and returns the channel pointer
for further use by <devicename>pcm</devicename>).</para>
<para>The second parameter is a pointer to the private
channel data structure, except for
<function>channel_init()</function> which has a pointer to
the private device structure (and returns the channel
pointer for further use by
<devicename>pcm</devicename>).</para>
</sect3> </sect3>
<sect3> <sect3>
<title>Overview of Data Transfer Operations</title> <title>Overview of Data Transfer Operations</title>
<para>For sound data transfers, the <para>For sound data transfers, the
<devicename>pcm</devicename> core and the sound drivers <devicename>pcm</devicename> core and the sound drivers
communicate through a shared memory area, described by a communicate through a shared memory area, described by a
<structname>struct snd_dbuf</structname>.</para> <structname>struct snd_dbuf</structname>.</para>
<para><structname>struct snd_dbuf</structname> is private to <para><structname>struct snd_dbuf</structname> is private to
<devicename>pcm</devicename>, and sound drivers obtain <devicename>pcm</devicename>, and sound drivers obtain
values of interest by calls to accessor functions values of interest by calls to accessor functions
(<function>sndbuf_getxxx()</function>).</para> (<function>sndbuf_getxxx()</function>).</para>
<para>The shared memory area has a size of <para>The shared memory area has a size of
<function>sndbuf_getsize()</function> and is divided into <function>sndbuf_getsize()</function> and is divided into
fixed size blocks of <function>sndbuf_getblksz()</function> fixed size blocks of <function>sndbuf_getblksz()</function>
bytes.</para> bytes.</para>
<para>When playing, the general transfer mechanism is as <para>When playing, the general transfer mechanism is as
follows (reverse the idea for recording):</para> follows (reverse the idea for recording):</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><devicename>pcm</devicename> initially fills up the <para><devicename>pcm</devicename> initially fills up the
buffer, then calls the sound driver's <link buffer, then calls the sound driver's <link
linkend="channel-trigger"> linkend="channel-trigger">
<function>xxxchannel_trigger()</function></link> <function>xxxchannel_trigger()</function></link>
function with a parameter of PCMTRIG_START.</para> function with a parameter of PCMTRIG_START.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The sound driver then arranges to repeatedly <para>The sound driver then arranges to repeatedly
transfer the whole memory area transfer the whole memory area
(<function>sndbuf_getbuf()</function>, (<function>sndbuf_getbuf()</function>,
<function>sndbuf_getsize()</function>) to the device, in <function>sndbuf_getsize()</function>) to the device, in
blocks of <function>sndbuf_getblksz()</function> bytes. blocks of <function>sndbuf_getblksz()</function> bytes.
It calls back the <function>chn_intr()</function> It calls back the <function>chn_intr()</function>
<devicename>pcm</devicename> function for each <devicename>pcm</devicename> function for each
transferred block (this will typically happen at transferred block (this will typically happen at
interrupt time).</para> interrupt time).</para>
</listitem> </listitem>
<listitem>
<para><function>chn_intr()</function> arranges to copy new
data to the area that was transferred to the device (now
free), and make appropriate updates to the
<structname>snd_dbuf</structname> structure.</para>
</listitem>
</itemizedlist>
<listitem>
<para><function>chn_intr()</function> arranges to copy new
data to the area that was transferred to the device (now
free), and make appropriate updates to the
<structname>snd_dbuf</structname> structure.</para>
</listitem>
</itemizedlist>
</sect3> </sect3>
<sect3 id="xxxchannel-init"> <sect3 id="xxxchannel-init">
<title>channel_init</title> <title>channel_init</title>
<para><function>xxxchannel_init()</function> is called to <para><function>xxxchannel_init()</function> is called to
initialize each of the play or record channels. The calls initialize each of the play or record channels. The calls
are initiated from the sound driver attach routine. (See are initiated from the sound driver attach routine. (See
the <link linkend="pcm-probe-and-attach">probe and attach the <link linkend="pcm-probe-and-attach">probe and attach
section</link>).</para> section</link>).</para>
<programlisting> static void * <programlisting> static void *
xxxchannel_init(kobj_t obj, void *data, xxxchannel_init(kobj_t obj, void *data,
struct snd_dbuf *b, struct pcm_channel *c, int dir)<co id="co-chinit-params"/> struct snd_dbuf *b, struct pcm_channel *c, int dir)<co id="co-chinit-params"/>
{ {
@ -305,46 +308,43 @@
return ch;<co id="co-chinit-return"/> return ch;<co id="co-chinit-return"/>
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-chinit-params">
<para><varname>b</varname> is the address for the channel
<structname>struct snd_dbuf</structname>. It should be
initialized in the function by calling
<function>sndbuf_alloc()</function>. The buffer size to
use is normally a small multiple of the 'typical' unit
transfer size for your device.</para>
<callout arearefs="co-chinit-params"> <para><varname>c</varname> is the
<para><varname>b</varname> is the address for the channel <devicename>pcm</devicename> channel control structure
<structname>struct snd_dbuf</structname>. It should be pointer. This is an opaque object. The function should
initialized in the function by calling store it in the local channel structure, to be used in
<function>sndbuf_alloc()</function>. The buffer size to later calls to <devicename>pcm</devicename> (ie:
use is normally a small multiple of the 'typical' unit <function>chn_intr(c)</function>).</para>
transfer size for your device.</para>
<para><varname>c</varname> is the <para><varname>dir</varname> indicates the channel
<devicename>pcm</devicename> channel control structure direction (<literal>PCMDIR_PLAY</literal> or
pointer. This is an opaque object. The function should <literal>PCMDIR_REC</literal>).</para>
store it in the local channel structure, to be used in </callout>
later calls to <devicename>pcm</devicename> (ie:
<function>chn_intr(c)</function>).</para>
<para><varname>dir</varname> indicates the channel
direction (<literal>PCMDIR_PLAY</literal> or
<literal>PCMDIR_REC</literal>).</para>
</callout>
<callout arearefs="co-chinit-return">
<para>The function should return a pointer to the private
area used to control this channel. This will be passed
as a parameter to other channel interface calls.</para>
</callout>
</calloutlist>
<callout arearefs="co-chinit-return">
<para>The function should return a pointer to the private
area used to control this channel. This will be passed
as a parameter to other channel interface calls.</para>
</callout>
</calloutlist>
</sect3> </sect3>
<sect3> <sect3>
<title>channel_setformat</title> <title>channel_setformat</title>
<para><function>xxxchannel_setformat()</function> should set <para><function>xxxchannel_setformat()</function> should set
up the hardware for the specified channel for the specified up the hardware for the specified channel for the specified
sound format.</para> sound format.</para>
<programlisting> static int <programlisting> static int
xxxchannel_setformat(kobj_t obj, void *data, u_int32_t format)<co id="co-chsetformat-params"/> xxxchannel_setformat(kobj_t obj, void *data, u_int32_t format)<co id="co-chsetformat-params"/>
{ {
struct xxx_chinfo *ch = data; struct xxx_chinfo *ch = data;
@ -352,51 +352,49 @@
return 0; return 0;
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-chsetformat-params"> <callout arearefs="co-chsetformat-params">
<para><varname>format</varname> is specified as an <para><varname>format</varname> is specified as an
<literal>AFMT_XXX value</literal> <literal>AFMT_XXX value</literal>
(<filename>soundcard.h</filename>).</para> (<filename>soundcard.h</filename>).</para>
</callout> </callout>
</calloutlist>
</calloutlist>
</sect3> </sect3>
<sect3> <sect3>
<title>channel_setspeed</title> <title>channel_setspeed</title>
<para><function>xxxchannel_setspeed()</function> sets up the <para><function>xxxchannel_setspeed()</function> sets up the
channel hardware for the specified sampling speed, and channel hardware for the specified sampling speed, and
returns the possibly adjusted speed.</para> returns the possibly adjusted speed.</para>
<programlisting> static int <programlisting> static int
xxxchannel_setspeed(kobj_t obj, void *data, u_int32_t speed) xxxchannel_setspeed(kobj_t obj, void *data, u_int32_t speed)
{ {
struct xxx_chinfo *ch = data; struct xxx_chinfo *ch = data;
... ...
return speed; return speed;
}</programlisting> }</programlisting>
</sect3> </sect3>
<sect3> <sect3>
<title>channel_setblocksize</title> <title>channel_setblocksize</title>
<para><function>xxxchannel_setblocksize()</function> sets the <para><function>xxxchannel_setblocksize()</function> sets the
block size, which is the size of unit transactions between block size, which is the size of unit transactions between
<devicename>pcm</devicename> and the sound driver, and <devicename>pcm</devicename> and the sound driver, and
between the sound driver and the device. Typically, this between the sound driver and the device. Typically, this
would be the number of bytes transferred before an interrupt would be the number of bytes transferred before an interrupt
occurs. During a transfer, the sound driver should call occurs. During a transfer, the sound driver should call
<devicename>pcm</devicename>'s <devicename>pcm</devicename>'s
<function>chn_intr()</function> every time this size has <function>chn_intr()</function> every time this size has
been transferred.</para> been transferred.</para>
<para>Most sound drivers only take note of the block size <para>Most sound drivers only take note of the block size
here, to be used when an actual transfer will be here, to be used when an actual transfer will be
started.</para> started.</para>
<programlisting> static int <programlisting> static int
xxxchannel_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) xxxchannel_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{ {
struct xxx_chinfo *ch = data; struct xxx_chinfo *ch = data;
@ -404,26 +402,24 @@
return blocksize;<co id="co-chsetblocksize-return"/> return blocksize;<co id="co-chsetblocksize-return"/>
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-chsetblocksize-return"> <callout arearefs="co-chsetblocksize-return">
<para>The function returns the possibly adjusted block <para>The function returns the possibly adjusted block
size. In case the block size is indeed changed, size. In case the block size is indeed changed,
<function>sndbuf_resize()</function> should be called to <function>sndbuf_resize()</function> should be called to
adjust the buffer.</para> adjust the buffer.</para>
</callout>
</callout> </calloutlist>
</calloutlist>
</sect3> </sect3>
<sect3 id="channel-trigger"> <sect3 id="channel-trigger">
<title>channel_trigger</title> <title>channel_trigger</title>
<para><function>xxxchannel_trigger()</function> is called by <para><function>xxxchannel_trigger()</function> is called by
<devicename>pcm</devicename> to control data transfer <devicename>pcm</devicename> to control data transfer
operations in the driver.</para> operations in the driver.</para>
<programlisting> static int <programlisting> static int
xxxchannel_trigger(kobj_t obj, void *data, int go)<co id="co-chtrigger-params"/> xxxchannel_trigger(kobj_t obj, void *data, int go)<co id="co-chtrigger-params"/>
{ {
struct xxx_chinfo *ch = data; struct xxx_chinfo *ch = data;
@ -431,120 +427,115 @@
return 0; return 0;
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-chtrigger-params"> <callout arearefs="co-chtrigger-params">
<para><varname>go</varname> defines the action for the <para><varname>go</varname> defines the action for the
current call. The possible values are:</para> current call. The possible values are:</para>
<itemizedlist>
<listitem> <itemizedlist>
<para><literal>PCMTRIG_START</literal>: the driver <listitem>
should start a data transfer from or to the channel <para><literal>PCMTRIG_START</literal>: the driver
buffer. If needed, the buffer base and size can be should start a data transfer from or to the channel
retrieved through buffer. If needed, the buffer base and size can be
<function>sndbuf_getbuf()</function> and retrieved through
<function>sndbuf_getsize()</function>.</para> <function>sndbuf_getbuf()</function> and
</listitem> <function>sndbuf_getsize()</function>.</para>
</listitem>
<listitem> <listitem>
<para><literal>PCMTRIG_EMLDMAWR</literal> / <para><literal>PCMTRIG_EMLDMAWR</literal> /
<literal>PCMTRIG_EMLDMARD</literal>: this tells the <literal>PCMTRIG_EMLDMARD</literal>: this tells the
driver that the input or output buffer may have been driver that the input or output buffer may have been
updated. Most drivers just ignore these updated. Most drivers just ignore these
calls.</para> calls.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><literal>PCMTRIG_STOP</literal> / <para><literal>PCMTRIG_STOP</literal> /
<literal>PCMTRIG_ABORT</literal>: the driver should <literal>PCMTRIG_ABORT</literal>: the driver should
stop the current transfer.</para> stop the current transfer.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</callout>
</callout> </calloutlist>
</calloutlist>
<note><para>If the driver uses ISA DMA,
<function>sndbuf_isadma()</function> should be called before
performing actions on the device, and will take care of the
DMA chip side of things.</para>
</note>
<note>
<para>If the driver uses ISA DMA,
<function>sndbuf_isadma()</function> should be called
before performing actions on the device, and will take
care of the DMA chip side of things.</para>
</note>
</sect3> </sect3>
<sect3> <sect3>
<title>channel_getptr</title> <title>channel_getptr</title>
<para><function>xxxchannel_getptr()</function> returns the
current offset in the transfer buffer. This will typically
be called by <function>chn_intr()</function>, and this is how
<devicename>pcm</devicename> knows where it can transfer
new data.</para>
<para><function>xxxchannel_getptr()</function> returns the
current offset in the transfer buffer. This will typically
be called by <function>chn_intr()</function>, and this is
how <devicename>pcm</devicename> knows where it can transfer
new data.</para>
</sect3> </sect3>
<sect3> <sect3>
<title>channel_free</title> <title>channel_free</title>
<para><function>xxxchannel_free()</function> is called to free
up channel resources, for example when the driver is
unloaded, and should be implemented if the channel data
structures are dynamically allocated or if
<function>sndbuf_alloc()</function> was not used for buffer
allocation.</para>
<para><function>xxxchannel_free()</function> is called to free
up channel resources, for example when the driver is
unloaded, and should be implemented if the channel data
structures are dynamically allocated or if
<function>sndbuf_alloc()</function> was not used for buffer
allocation.</para>
</sect3> </sect3>
<sect3> <sect3>
<title>channel_getcaps</title> <title>channel_getcaps</title>
<programlisting> struct pcmchan_caps * <programlisting> struct pcmchan_caps *
xxxchannel_getcaps(kobj_t obj, void *data) xxxchannel_getcaps(kobj_t obj, void *data)
{ {
return &amp;xxx_caps;<co id="co-chgetcaps-return"/> return &amp;xxx_caps;<co id="co-chgetcaps-return"/>
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-chgetcaps-return">
<para>The routine returns a pointer to a (usually
statically-defined) <structname>pcmchan_caps</structname>
structure (defined in
<filename>sound/pcm/channel.h</filename>. The structure holds
the minimum and maximum sampling frequencies, and the
accepted sound formats. Look at any sound driver for an
example.</para>
</callout>
</calloutlist>
<callout arearefs="co-chgetcaps-return">
<para>The routine returns a pointer to a (usually
statically-defined)
<structname>pcmchan_caps</structname> structure (defined
in <filename>sound/pcm/channel.h</filename>. The
structure holds the minimum and maximum sampling
frequencies, and the accepted sound formats. Look at
any sound driver for an example.</para>
</callout>
</calloutlist>
</sect3> </sect3>
<sect3> <sect3>
<title>More Functions</title> <title>More Functions</title>
<para><function>channel_reset()</function>, <para><function>channel_reset()</function>,
<function>channel_resetdone()</function>, and <function>channel_resetdone()</function>, and
<function>channel_notify()</function> are for special purposes <function>channel_notify()</function> are for special
and should not be implemented in a driver without discussing purposes and should not be implemented in a driver without
it on the &a.multimedia;.</para> discussing it on the &a.multimedia;.</para>
<para><function>channel_setdir()</function> is deprecated.</para> <para><function>channel_setdir()</function> is
deprecated.</para>
</sect3> </sect3>
</sect2> </sect2>
<sect2> <sect2>
<title>The MIXER Interface</title> <title>The MIXER Interface</title>
<sect3 id="xxxmixer-init"> <sect3 id="xxxmixer-init">
<title>mixer_init</title> <title>mixer_init</title>
<para><function>xxxmixer_init()</function> initializes the <para><function>xxxmixer_init()</function> initializes the
hardware and tells <devicename>pcm</devicename> what mixer hardware and tells <devicename>pcm</devicename> what mixer
devices are available for playing and recording</para> devices are available for playing and recording</para>
<programlisting> static int <programlisting> static int
xxxmixer_init(struct snd_mixer *m) xxxmixer_init(struct snd_mixer *m)
{ {
struct xxx_info *sc = mix_getdevinfo(m); struct xxx_info *sc = mix_getdevinfo(m);
@ -560,29 +551,28 @@
return 0; return 0;
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-mxini-sd"> <callout arearefs="co-mxini-sd">
<para>Set bits in an integer value and call <para>Set bits in an integer value and call
<function>mix_setdevs()</function> and <function>mix_setdevs()</function> and
<function>mix_setrecdevs()</function> to tell <function>mix_setrecdevs()</function> to tell
<devicename>pcm</devicename> what devices exist.</para> <devicename>pcm</devicename> what devices exist.</para>
</callout> </callout>
</calloutlist> </calloutlist>
<para>Mixer bits definitions can be found in
<filename>soundcard.h</filename>
(<literal>SOUND_MASK_XXX</literal> values and
<literal>SOUND_MIXER_XXX</literal> bit shifts).</para>
<para>Mixer bits definitions can be found in
<filename>soundcard.h</filename>
(<literal>SOUND_MASK_XXX</literal> values and
<literal>SOUND_MIXER_XXX</literal> bit shifts).</para>
</sect3> </sect3>
<sect3> <sect3>
<title>mixer_set</title> <title>mixer_set</title>
<para><function>xxxmixer_set()</function> sets the volume <para><function>xxxmixer_set()</function> sets the volume
level for one mixer device.</para> level for one mixer device.</para>
<programlisting> static int <programlisting> static int
xxxmixer_set(struct snd_mixer *m, unsigned dev, xxxmixer_set(struct snd_mixer *m, unsigned dev,
unsigned left, unsigned right)<co id="co-mxset-params"/> unsigned left, unsigned right)<co id="co-mxset-params"/>
{ {
@ -591,31 +581,32 @@
return left | (right &lt;&lt; 8);<co id="co-mxset-return"/> return left | (right &lt;&lt; 8);<co id="co-mxset-return"/>
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-mxset-params"> <callout arearefs="co-mxset-params">
<para>The device is specified as a <literal>SOUND_MIXER_XXX</literal> <para>The device is specified as a
value</para> <para>The volume values are specified in <literal>SOUND_MIXER_XXX</literal> value</para>
range [0-100]. A value of zero should mute the
device.</para>
</callout>
<callout arearefs="co-mxset-return"> <para>The volume values are specified in range [0-100].
<para>As the hardware levels probably will not match the A value of zero should mute the device.</para>
input scale, and some rounding will occur, the routine </callout>
returns the actual level values (in range 0-100) as
shown.</para> <callout arearefs="co-mxset-return">
</callout> <para>As the hardware levels probably will not match the
</calloutlist> input scale, and some rounding will occur, the routine
returns the actual level values (in range 0-100) as
shown.</para>
</callout>
</calloutlist>
</sect3> </sect3>
<sect3> <sect3>
<title>mixer_setrecsrc</title> <title>mixer_setrecsrc</title>
<para><function>xxxmixer_setrecsrc()</function> sets the <para><function>xxxmixer_setrecsrc()</function> sets the
recording source device.</para> recording source device.</para>
<programlisting> static int <programlisting> static int
xxxmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)<co id="co-mxsr-params"/> xxxmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)<co id="co-mxsr-params"/>
{ {
struct xxx_info *sc = mix_getdevinfo(m); struct xxx_info *sc = mix_getdevinfo(m);
@ -626,62 +617,61 @@
return src;<co id="co-mxsr-return"/> return src;<co id="co-mxsr-return"/>
}</programlisting> }</programlisting>
<calloutlist> <calloutlist>
<callout arearefs="co-mxsr-params"> <callout arearefs="co-mxsr-params">
<para>The desired recording devices are specified as a <para>The desired recording devices are specified as a
bit field</para> bit field</para>
</callout> </callout>
<callout arearefs="co-mxsr-return"> <callout arearefs="co-mxsr-return">
<para>The actual devices set for recording are returned. <para>The actual devices set for recording are returned.
Some drivers can only set one device for recording. The Some drivers can only set one device for recording. The
function should return -1 if an error occurs.</para> function should return -1 if an error occurs.</para>
</callout> </callout>
</calloutlist> </calloutlist>
</sect3> </sect3>
<sect3> <sect3>
<title>mixer_uninit, mixer_reinit</title> <title>mixer_uninit, mixer_reinit</title>
<para><function>xxxmixer_uninit()</function> should ensure <para><function>xxxmixer_uninit()</function> should ensure
that all sound is muted and if possible mixer hardware that all sound is muted and if possible mixer hardware
should be powered down </para> should be powered down </para>
<para><function>xxxmixer_reinit()</function> should ensure
that the mixer hardware is powered up and any settings not
controlled by <function>mixer_set()</function> or
<function>mixer_setrecsrc()</function> are restored.</para>
<para><function>xxxmixer_reinit()</function> should ensure
that the mixer hardware is powered up and any settings not
controlled by <function>mixer_set()</function> or
<function>mixer_setrecsrc()</function> are restored.</para>
</sect3> </sect3>
</sect2> </sect2>
<sect2> <sect2>
<title>The AC97 Interface</title> <title>The AC97 Interface</title>
<indexterm><primary>AC97</primary></indexterm> <indexterm><primary>AC97</primary></indexterm>
<para>The <emphasis>AC97</emphasis> interface is implemented <para>The <emphasis>AC97</emphasis> interface is implemented
by drivers with an AC97 codec. It only has three methods:</para> by drivers with an AC97 codec. It only has three
methods:</para>
<itemizedlist> <itemizedlist>
<listitem>
<para><function>xxxac97_init()</function> returns the number
of ac97 codecs found.</para>
</listitem>
<listitem><para><function>xxxac97_init()</function> returns <listitem>
the number of ac97 codecs found.</para> <para><function>ac97_read()</function> and
</listitem> <function>ac97_write()</function> read or write a
specified register.</para>
<listitem><para><function>ac97_read()</function> and </listitem>
<function>ac97_write()</function> read or write a specified
register.</para>
</listitem>
</itemizedlist> </itemizedlist>
<para>The <emphasis>AC97</emphasis> interface is used by the <para>The <emphasis>AC97</emphasis> interface is used by the
AC97 code in <devicename>pcm</devicename> to perform higher AC97 code in <devicename>pcm</devicename> to perform higher
level operations. Look at level operations. Look at
<filename>sound/pci/maestro3.c</filename> or many others under <filename>sound/pci/maestro3.c</filename> or many others under
<filename>sound/pci/</filename> for an example.</para> <filename>sound/pci/</filename> for an example.</para>
</sect2> </sect2>
</sect1> </sect1>
</chapter> </chapter>