594 lines
17 KiB
Groff
594 lines
17 KiB
Groff
.\" $NetBSD: audio.9,v 1.27 2004/01/31 21:33:08 wiz Exp $
|
|
.\"
|
|
.\" Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Lennart Augustsson.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. All advertising materials mentioning features or use of this software
|
|
.\" must display the following acknowledgement:
|
|
.\" This product includes software developed by the NetBSD
|
|
.\" Foundation, Inc. and its contributors.
|
|
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
.\" contributors may be used to endorse or promote products derived
|
|
.\" from this software without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
.\"
|
|
.Dd January 31, 2004
|
|
.Dt AUDIO 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm audio
|
|
.Nd interface between low and high level audio drivers
|
|
.Sh DESCRIPTION
|
|
The audio device driver is divided into a high level,
|
|
hardware independent layer, and a low level hardware
|
|
dependent layer.
|
|
The interface between these is the
|
|
.Va audio_hw_if
|
|
structure.
|
|
.Bd -literal
|
|
struct audio_hw_if {
|
|
int (*open)(void *, int);
|
|
void (*close)(void *);
|
|
int (*drain)(void *);
|
|
|
|
int (*query_encoding)(void *, struct audio_encoding *);
|
|
int (*set_params)(void *, int, int,
|
|
struct audio_params *, struct audio_params *);
|
|
int (*round_blocksize)(void *, int);
|
|
|
|
int (*commit_settings)(void *);
|
|
|
|
int (*init_output)(void *, void *, int);
|
|
int (*init_input)(void *, void *, int);
|
|
int (*start_output)(void *, void *, int, void (*)(void *),
|
|
void *);
|
|
int (*start_input)(void *, void *, int, void (*)(void *),
|
|
void *);
|
|
int (*halt_output)(void *);
|
|
int (*halt_input)(void *);
|
|
|
|
int (*speaker_ctl)(void *, int);
|
|
#define SPKR_ON 1
|
|
#define SPKR_OFF 0
|
|
|
|
int (*getdev)(void *, struct audio_device *);
|
|
int (*setfd)(void *, int);
|
|
|
|
int (*set_port)(void *, mixer_ctrl_t *);
|
|
int (*get_port)(void *, mixer_ctrl_t *);
|
|
|
|
int (*query_devinfo)(void *, mixer_devinfo_t *);
|
|
|
|
void *(*allocm)(void *, int, size_t, struct malloc_type *, int);
|
|
void (*freem)(void *, void *, struct malloc_type *);
|
|
size_t (*round_buffersize)(void *, int, size_t);
|
|
paddr_t (*mappage)(void *, void *, off_t, int);
|
|
|
|
int (*get_props)(void *);
|
|
|
|
int (*trigger_output)(void *, void *, void *, int,
|
|
void (*)(void *), void *, struct audio_params *);
|
|
int (*trigger_input)(void *, void *, void *, int,
|
|
void (*)(void *), void *, struct audio_params *);
|
|
int (*dev_ioctl)(void *, u_long, caddr_t, int, struct proc *);
|
|
};
|
|
|
|
struct audio_params {
|
|
u_long sample_rate; /* sample rate */
|
|
u_int encoding; /* mu-law, linear, etc */
|
|
u_int precision; /* bits/sample */
|
|
u_int channels; /* mono(1), stereo(2) */
|
|
/* Software en/decode functions, set if SW coding required by HW */
|
|
void (*sw_code)(void *, u_char *, int);
|
|
int factor; /* coding space change */
|
|
int factor_denom; /* denominator of factor */
|
|
/*
|
|
* The following four members represent what format is used in a
|
|
* hardware. If hw_sample_rate != sample_rate || hw_channels !=
|
|
* channels, the audio framework converts data. Encoding and
|
|
* precision are converted in sw_code().
|
|
* set_params() should set correct values to them if no conversion is
|
|
* needed.
|
|
*/
|
|
u_long hw_sample_rate;
|
|
u_int hw_encoding;
|
|
u_int hw_precision;
|
|
u_int hw_channels;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
The high level audio driver attaches to the low level driver
|
|
when the latter calls
|
|
.Va audio_attach_mi .
|
|
This call should be
|
|
.Bd -literal
|
|
void
|
|
audio_attach_mi(ahwp, hdl, dev)
|
|
struct audio_hw_if *ahwp;
|
|
void *hdl;
|
|
struct device *dev;
|
|
.Ed
|
|
.Pp
|
|
The
|
|
.Va audio_hw_if
|
|
struct is as shown above.
|
|
The
|
|
.Va hdl
|
|
argument is a handle to some low level data structure.
|
|
It is sent as the first argument to all the functions
|
|
in
|
|
.Va audio_hw_if
|
|
when the high level driver calls them.
|
|
.Va dev
|
|
is the device struct for the hardware device.
|
|
.Pp
|
|
The upper layer of the audio driver allocates one buffer for playing
|
|
and one for recording.
|
|
It handles the buffering of data from the user processes in these.
|
|
The data is presented to the lower level in smaller chunks, called blocks.
|
|
If there, during playback, is no data available from the user process when
|
|
the hardware request another block a block of silence will be used instead.
|
|
Furthermore, if the user process does not read data quickly enough during
|
|
recording data will be thrown away.
|
|
.Pp
|
|
The fields of
|
|
.Va audio_hw_if
|
|
are described in some more detail below.
|
|
Some fields are optional and can be set to 0 if not needed.
|
|
.Bl -tag -width indent
|
|
.It Dv int open(void *hdl, int flags)
|
|
is called when the audio device is opened.
|
|
It should initialize the hardware for I/O.
|
|
Every successful call to
|
|
.Va open
|
|
is matched by a call to
|
|
.Va close .
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv void close(void *hdl)
|
|
is called when the audio device is closed.
|
|
.It Dv int drain(void *hdl)
|
|
optional, is called before the device is closed or when
|
|
.Dv AUDIO_DRAIN
|
|
is called.
|
|
It should make sure that no samples remain in to be played that could
|
|
be lost when
|
|
.Va close
|
|
is called.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int query_encoding(void *hdl, struct audio_encoding *ae)
|
|
is used when
|
|
.Dv AUDIO_GETENC
|
|
is called.
|
|
It should fill the
|
|
.Va audio_encoding
|
|
structure and return 0 or, if there is no encoding with the
|
|
given number, return EINVAL.
|
|
.It Dv int set_params(void *hdl, int setmode, int usemode,
|
|
.Dv "struct audio_params *play, struct audio_params *rec)"
|
|
.br
|
|
Called to set the audio encoding mode.
|
|
.Va setmode
|
|
is a combination of the
|
|
.Dv AUMODE_RECORD
|
|
and
|
|
.Dv AUMODE_PLAY
|
|
flags to indicate which mode(s) are to be set.
|
|
.Va usemode
|
|
is also a combination of these flags, but indicates the current
|
|
mode of the device (i.e., the value of
|
|
.Va mode
|
|
in the
|
|
.Va audio_info
|
|
struct).
|
|
The
|
|
.Va play
|
|
and
|
|
.Va rec
|
|
structures contain the encoding parameters that should be set.
|
|
.Pp
|
|
If the hardware requires software assistance with some encoding
|
|
(e.g., it might be lacking mu-law support) it should fill the
|
|
.Va sw_code ,
|
|
.Va factor
|
|
and
|
|
.Va factor_denom
|
|
fields of these structures with translation information, and
|
|
set to hw_* fields what format the hardware actually uses.
|
|
For example, if
|
|
.Va play
|
|
requests [8000Hz, mu-law, 8bit, 1ch] and the hardware supports
|
|
not 8bit mu-law but 16bit slinear_le, the driver should set
|
|
.Va mulaw_to_slinear16_le
|
|
to
|
|
.Va sw_code ,
|
|
2 to
|
|
.Va factor ,
|
|
1 to
|
|
.Va factor_denom ,
|
|
.Dv AUDIO_ENCODING_SLINEAR_LE
|
|
to
|
|
.Va hw_encoding
|
|
and 16 to
|
|
.Va hw_precision .
|
|
The values of the structures may also be modified if the hardware
|
|
cannot be set to exactly the requested mode (e.g., if the requested
|
|
sampling rate is not supported, but one close enough is).
|
|
.Pp
|
|
The hardware driver can also request sampling rate conversion
|
|
and mono-stereo conversion.
|
|
If
|
|
.Va set_params
|
|
sets to
|
|
.Va hw_sampling_rate
|
|
a value which is different than
|
|
.Va sampling_rate
|
|
or sets to
|
|
.Va hw_channels
|
|
a value which is different than
|
|
.Va channels ,
|
|
and set
|
|
.Dv AUDIO_ENCODING_SLINEAR_LE
|
|
to
|
|
.Va hw_encoding ,
|
|
the hardware independent driver performs sampling rate and/or mono-stereo
|
|
conversion.
|
|
If such conversion is not needed,
|
|
.Va set_params
|
|
must keep
|
|
.Va sampling_rate
|
|
and
|
|
.Va channels
|
|
are the same as
|
|
.Va hw_sampling_rate
|
|
and
|
|
.Va hw_channels
|
|
respectively.
|
|
.Pp
|
|
Note: The order of conversion is
|
|
.Va sw_code
|
|
followed by sampling rate and mono-stereo in playing,
|
|
and sampling rate and mono-stereo followed by
|
|
.Va sw_code
|
|
in recording.
|
|
.Pp
|
|
If the device does not have the
|
|
.Dv AUDIO_PROP_INDEPENDENT
|
|
property the same value is passed in both
|
|
.Va play
|
|
and
|
|
.Va rec
|
|
and the encoding parameters from
|
|
.Va play
|
|
is copied into
|
|
.Va rec
|
|
after the call to
|
|
.Va set_params .
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int round_blocksize(void *hdl, int bs)
|
|
optional, is called with the block size,
|
|
.Va bs ,
|
|
that has been computed by the upper layer.
|
|
It should return a block size, possibly changed according to the needs
|
|
of the hardware driver.
|
|
.It Dv int commit_settings(void *hdl)
|
|
optional, is called after all calls to
|
|
.Va set_params ,
|
|
and
|
|
.Va set_port ,
|
|
are done.
|
|
A hardware driver that needs to get the hardware in and out of command
|
|
mode for each change can save all the changes during previous calls and
|
|
do them all here.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int init_output(void *hdl, void *buffer, int size)
|
|
optional, is called before any output starts, but when the total
|
|
.Va size
|
|
of the output
|
|
.Va buffer
|
|
has been determined.
|
|
It can be used to initialize looping DMA for hardware that needs that.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int init_input(void *hdl, void *buffer, int size)
|
|
optional, is called before any input starts, but when the total
|
|
.Va size
|
|
of the input
|
|
.Va buffer
|
|
has been determined.
|
|
It can be used to initialize looping DMA for hardware that needs that.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int start_output(void *hdl, void *block, int blksize,
|
|
.Dv "void (*intr)(void*), void *intrarg)"
|
|
.br
|
|
is called to start the transfer of
|
|
.Va blksize
|
|
bytes from
|
|
.Va block
|
|
to the audio hardware.
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is ready to accept more samples the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg .
|
|
Calling
|
|
.Va intr
|
|
will normally initiate another call to
|
|
.Va start_output .
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int start_input(void *hdl, void *block, int blksize,
|
|
.Dv "void (*intr)(void*), void *intrarg)"
|
|
.br
|
|
is called to start the transfer of
|
|
.Va blksize
|
|
bytes to
|
|
.Va block
|
|
from the audio hardware.
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is ready to deliver more samples the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg .
|
|
Calling
|
|
.Va intr
|
|
will normally initiate another call to
|
|
.Va start_input .
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int halt_output(void *hdl)
|
|
is called to abort the output transfer (started by
|
|
.Va start_output )
|
|
in progress.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int halt_input(void *hdl)
|
|
is called to abort the input transfer (started by
|
|
.Va start_input )
|
|
in progress.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int speaker_ctl(void *hdl, int on)
|
|
optional, is called when a half duplex device changes between
|
|
playing and recording.
|
|
It can, e.g., be used to turn on
|
|
and off the speaker.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int getdev(void *hdl, struct audio_device *ret)
|
|
Should fill the
|
|
.Va audio_device
|
|
struct with relevant information about the driver.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int setfd(void *hdl, int fd)
|
|
optional, is called when
|
|
.Dv AUDIO_SETFD
|
|
is used, but only if the device has AUDIO_PROP_FULLDUPLEX set.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int set_port(void *hdl, mixer_ctl_t *mc)
|
|
is called in when
|
|
.Dv AUDIO_MIXER_WRITE
|
|
is used.
|
|
It should take data from the
|
|
.Va mixer_ctl_t
|
|
struct at set the corresponding mixer values.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int get_port(void *hdl, mixer_ctl_t *mc)
|
|
is called in when
|
|
.Dv AUDIO_MIXER_READ
|
|
is used.
|
|
It should fill the
|
|
.Va mixer_ctl_t
|
|
struct.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int query_devinfo(void *hdl, mixer_devinfo_t *di)
|
|
is called in when
|
|
.Dv AUDIO_MIXER_DEVINFO
|
|
is used.
|
|
It should fill the
|
|
.Va mixer_devinfo_t
|
|
struct.
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv "void *allocm(void *hdl, int direction, size_t size, struct malloc_type *type, int flags)"
|
|
.br
|
|
optional, is called to allocate the device buffers.
|
|
If not present
|
|
.Xr malloc 9
|
|
is used instead (with the same arguments but the first two).
|
|
The reason for using a device dependent routine instead of
|
|
.Xr malloc 9
|
|
is that some buses need special allocation to do DMA.
|
|
Returns the address of the buffer, or 0 on failure.
|
|
.It Dv void freem(void *hdl, void *addr, struct malloc_type *type)
|
|
optional, is called to free memory allocated by
|
|
.Va alloc .
|
|
If not supplied
|
|
.Xr free 9
|
|
is used.
|
|
.It Dv size_t round_buffersize(void *hdl, int direction, size_t bufsize)
|
|
optional, is called at startup to determine the audio
|
|
buffer size.
|
|
The upper layer supplies the suggested size in
|
|
.Va bufsize ,
|
|
which the hardware driver can then change if needed.
|
|
E.g., DMA on the ISA bus cannot exceed 65536 bytes.
|
|
.It Dv "paddr_t mappage(void *hdl, void *addr, off_t offs, int prot)"
|
|
.br
|
|
optional, is called for
|
|
.Xr mmap 2 .
|
|
Should return the map value for the page at offset
|
|
.Va offs
|
|
from address
|
|
.Va addr
|
|
mapped with protection
|
|
.Va prot .
|
|
Returns -1 on failure, or a machine dependent opaque value
|
|
on success.
|
|
.It Dv int get_props(void *hdl)
|
|
Should return the device properties; i.e., a combination of
|
|
AUDIO_PROP_xxx.
|
|
.It Dv int trigger_output(void *hdl, void *start, void *end,
|
|
.Dv "int blksize, void (*intr)(void*), void *intrarg,"
|
|
.br
|
|
.Dv "struct audio_params *param)"
|
|
.br
|
|
optional, is called to start the transfer of data from the circular buffer
|
|
delimited by
|
|
.Va start
|
|
and
|
|
.Va end
|
|
to the audio hardware, parameterized as in
|
|
.Va param .
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is finished transferring each
|
|
.Va blksize
|
|
sized block, the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg
|
|
(typically from the audio hardware interrupt service routine).
|
|
Once started the transfer may be stopped using
|
|
.Va halt_output .
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int trigger_input(void *hdl, void *start, void *end,
|
|
.Dv "int blksize, void (*intr)(void*), void *intrarg,"
|
|
.br
|
|
.Dv "struct audio_params *param)"
|
|
.br
|
|
optional, is called to start the transfer of data from the audio hardware,
|
|
parameterized as in
|
|
.Va param ,
|
|
to the circular buffer delimited by
|
|
.Va start
|
|
and
|
|
.Va end .
|
|
The call should return when the data transfer has been initiated
|
|
(normally with DMA).
|
|
When the hardware is finished transferring each
|
|
.Va blksize
|
|
sized block, the function
|
|
.Va intr
|
|
should be called with the argument
|
|
.Va intrarg
|
|
(typically from the audio hardware interrupt service routine).
|
|
Once started the transfer may be stopped using
|
|
.Va halt_input .
|
|
Return 0 on success, otherwise an error code.
|
|
.It Dv int dev_ioctl(void *hdl, u_long cmd, caddr_t addr,
|
|
.br
|
|
.Dv "int flag, struct proc *p)"
|
|
.br
|
|
optional, is called when an
|
|
.Xr ioctl 2
|
|
is not recognized by the generic audio driver.
|
|
Return 0 on success, otherwise an error code.
|
|
.El
|
|
.Pp
|
|
The
|
|
.Va query_devinfo
|
|
method should define certain mixer controls for
|
|
.Dv AUDIO_SETINFO
|
|
to be able to change the port and gain,
|
|
and
|
|
.Dv AUDIO_GETINFO
|
|
to read them, as follows.
|
|
.Pp
|
|
If the record mixer is capable of input from more than one source,
|
|
it should define
|
|
.Dv AudioNsource
|
|
in class
|
|
.Dv AudioCrecord .
|
|
This mixer control should be of type
|
|
.Dv AUDIO_MIXER_ENUM
|
|
or
|
|
.Dv AUDIO_MIXER_SET
|
|
and enumerate the possible input sources.
|
|
Each of the named sources for which the recording level can be set
|
|
should have a control in the
|
|
.Dv AudioCrecord
|
|
class of type
|
|
.Dv AUDIO_MIXER_VALUE ,
|
|
except the
|
|
.Qq mixerout
|
|
source is special,
|
|
and will never have its own control.
|
|
Its selection signifies,
|
|
rather,
|
|
that various sources in class
|
|
.Dv AudioCrecord
|
|
will be combined and presented to the single recording output,
|
|
in the same fashion that the sources of class
|
|
.Dv AudioCinputs
|
|
are combined and presented to the playback output(s).
|
|
If the overall recording level can be changed,
|
|
regardless of the input source,
|
|
then this control should be named
|
|
.Dv AudioNmaster
|
|
and be of class
|
|
.Dv AudioCrecord .
|
|
.Pp
|
|
Controls for various sources that affect only the playback output,
|
|
as opposed to recording,
|
|
should be in the
|
|
.Dv AudioCinputs
|
|
class.
|
|
.Pp
|
|
If the play
|
|
mixer is capable of output to more than one destination,
|
|
it should define
|
|
.Dv AudioNselect
|
|
in class
|
|
.Dv AudioCoutputs .
|
|
This mixer control should be of type
|
|
.Dv AUDIO_MIXER_ENUM
|
|
or
|
|
.Dv AUDIO_MIXER_SET
|
|
and enumerate the possible destinations.
|
|
For each of the named destinations for which the output level can be set,
|
|
there should be
|
|
a control in the
|
|
.Dv AudioCoutputs
|
|
class of type
|
|
.Dv AUDIO_MIXER_VALUE .
|
|
If the overall output level can be changed,
|
|
which is invariably the case,
|
|
then this control should be named
|
|
.Dv AudioNmaster
|
|
and be of class
|
|
.Dv AudioCoutputs .
|
|
.Pp
|
|
There's one additional source recognized specially by
|
|
.Dv AUDIO_SETINFO
|
|
and
|
|
.Dv AUDIO_GETINFO ,
|
|
to be presented as monitor_gain,
|
|
and that is a control named
|
|
.Dv AudioNmonitor ,
|
|
of class
|
|
.Dv AudioCmonitor .
|
|
.Sh SEE ALSO
|
|
.Xr audio 4
|
|
.Sh HISTORY
|
|
This
|
|
.Nm
|
|
interface first appeared in
|
|
.Nx 1.3 .
|