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