diff options
Diffstat (limited to 'static/netbsd/man9/audio.9')
| -rw-r--r-- | static/netbsd/man9/audio.9 | 676 |
1 files changed, 676 insertions, 0 deletions
diff --git a/static/netbsd/man9/audio.9 b/static/netbsd/man9/audio.9 new file mode 100644 index 00000000..9bec5ed4 --- /dev/null +++ b/static/netbsd/man9/audio.9 @@ -0,0 +1,676 @@ +.\" $NetBSD: audio.9,v 1.61 2021/03/28 07:42:06 isaki 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. +.\" +.\" 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 February 2, 2021 +.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 (*query_format)(void *, audio_format_query_t *); + int (*set_format)(void *, int, + const audio_params_t *, const audio_params_t *, + audio_filter_reg_t *, audio_filter_reg_t *); + int (*round_blocksize)(void *, int, int, const audio_params_t *); + + 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 (*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); + void (*freem)(void *, void *, size_t); + size_t (*round_buffersize)(void *, int, size_t); + + int (*get_props)(void *); + + int (*trigger_output)(void *, void *, void *, int, + void (*)(void *), void *, const audio_params_t *); + int (*trigger_input)(void *, void *, void *, int, + void (*)(void *), void *, const audio_params_t *); + int (*dev_ioctl)(void *, u_long, void *, int, struct lwp *); + void (*get_locks)(void *, kmutex_t **, kmutex_t **); +}; + +typedef struct audio_params { + u_int sample_rate; /* sample rate */ + u_int encoding; /* e.g. mu-law, linear, etc */ + u_int precision; /* bits/subframe */ + u_int validbits; /* valid bits in a subframe */ + u_int channels; /* mono(1), stereo(2) */ +} audio_params_t; +.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 + device_t + audio_attach_mi(const struct audio_hw_if *ahwp, void *hdl, device_t 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, during playback, there 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 phase that these functions are called is classified into three. +Attach phase, Closed phase and Opened phase. +Attach phase is during device attach and +it transits to the Closed phase when the attach succeeded. +Closed phase is when no sampling device is opened and +it transits to the Opened phase when open succeeded. +Opened phase is when any sampling device is opened and +it transits to the Closed phase when close succeeded. +.Pp +The fields of +.Va audio_hw_if +are described in some more detail below. +Some fields are optional and can be set to +.Dv NULL +if not needed. +.Bl -tag -width indent +.It Dv int open(void *hdl, int flags) +optional, is called when the first device combining playback and recording +is opened. +On a full duplex hardware, +.Dv ( FREAD | FWRITE ) +is passed to flags. +On a half duplex hardware, +.Dv FWRITE +is passed for playback, or +.Dv FREAD +for recording. +Every successful call to +.Va open +is matched by a call to +.Va close . +Return 0 on success, otherwise an error code. +It is called in the Closed phase. +.It Dv void close(void *hdl) +optional, is called when the last audio device combining +playback and recording is closed. +Before call to this, +.Va halt_input +and +.Va halt_output +are called if necessary. +It is called in the Opened phase. +.It Dv int query_format(void *hdl, audio_format_query_t *afp) +is called to enumerate formats supported by the hardware. +It should fill the +.Vt audio_format_t +structure according to given number +.Va afp->index . +If there is no format with the given number, return +.Er EINVAL . +It can be called at any time. +.Bd -literal +typedef struct audio_format_query { + u_int index; + struct audio_format fmt; +} audio_format_query_t; +.Ed +.Pp +It is also used by the upper layer to determine the default format, as follows: +.Bl -enum +.It +Higher priority is preferred (normally 0, the highest is 3, the lowest is 0). +.It +.Dv AUDIO_ENCODING_SLINEAR_NE:16 +is preferred if exists. +.It +.Dv AUDIO_ENCODING_SLINEAR_OE:16 +is preferred if exists. +.It +The format with more channels is preferred. +.El +.Pp +If the driver supports +.Dv SLINEAR_NE:16 +and the upper layer chooses it, +the driver does not need to provide a conversion function in +.Va set_format . +Similarly, if the driver supports +.Dv SLINEAR_OE:16 +and the upper layer chooses it, +the driver does not need to provide a conversion function, +because the upper layer supports conversion between +.Dv SLINEAR_NE:16 +and +.Dv SLINEAR_OE:16 +for convenience. +If the upper layer chooses another format, +the driver needs to provide a conversion function in +.Va set_format . +See also +.Va set_format . +If the driver can not provide the conversion from/to +.Dv SLINEAR_NE:16 , +set priority to \-1. +It means that the hardware supports this format but the driver does not +(e.g. AC3), and it will never be chosen. +.It Dv int set_format(void *hdl, int setmode, +.Dv "const audio_params_t *play, const audio_params_t *rec," +.Dv "audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)" +.Pp +is called to set specified format to the hardware, +when the device is attached or the hardware format is changed. +.Va setmode +is a combination of the +.Dv AUMODE_RECORD +and +.Dv AUMODE_PLAY +flags to indicate which modes are to be set. +.Pp +The +.Va play +and +.Va rec +structures contain the encoding parameters that should be set to the hardware. +All of these parameters are chosen from formats returned by +.Va query_format . +Therefore +.Va play +and/or +.Va rec +are always settable. +If the hardware does not support +.Dv AUDIO_ENCODING_SLINEAR_{NE,OE}:16 , +conversion information should be filled the +.Va pfil +for playing or +.Va rfil +for recording. +The definition of +.Vt audio_filter_reg_t +and a related structure follow: +.Bd -literal +typedef struct { + const void *src; + const audio_format2_t *srcfmt; + void *dst; + const audio_format2_t *dstfmt; + int count; + void *context; +} audio_filter_arg_t; + +typedef void(*audio_filter_t)(audio_filter_arg_t *arg); + +typedef struct { + audio_filter_t codec; + void *context; +} audio_filter_reg_t; +.Ed +.Pp +.Va codec +is a conversion function and +.Va context +is an optional opaque pointer passed to +.Va codec . +.Pp +When +.Va codec +is called, all parameters required by +.Va codec +are contained in +.Va arg . +.Va src +points to the input buffer block, +.Va srcfmt +contains the input encoding parameters, +.Va dst +points to the output buffer block and +.Va dstfmt +contains the output encoding parameters. +.Va count +represents the number of frames to process on this call. +.Va src +and +.Va dst +are guaranteed to be able to consecutively access number of frames +specified by +.Va count. +.Va codec +must fill the entirety of +.Va dst . +For example, let count = 100, srcfmt is { precision = 16, channels = 3 }, +dstfmt is { precision = 8, channels = 4 }, +in this case, +src block length = 2(bytes) * 3(channels) * 100(frames) = 600 bytes, +The length to be written to +.Va dst +block is 1(byte) * 4(channels) * 100(frames) = 400 bytes. +.Va codec +cannot abort the conversion halfway and there is no error reporting mechanism. +.Va context +is a opaque pointer that can be used by +.Va codec +if necessary. +.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 . +Returns 0 on success, otherwise an error code. +It is called in the Attach or Closed phases. +.It Dv int round_blocksize(void *hdl, int bs, int mode, +.Dv "const audio_params_t *param)" +.Pp +optional, is called with the block size, +.Va bs , +that has been computed by the upper layer, +.Va mode , +.Dv AUMODE_PLAY +or +.Dv AUMODE_RECORD , +and +.Va param , +encoding parameters for the hardware. +.Va bs +passed is always non-zero and a multiple of the frame size represented by +param->channels * param->precision / 8. +It should return a block size, possibly changed according to the needs +of the hardware driver. +The return value also must be non-zero and a multiple of the frame size. +It is called in the Attach or Closed phases. +.It Dv int commit_settings(void *hdl) +optional, is called after all calls to +.Va set_format , +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. +Returns 0 on success, otherwise an error code. +It is called in the Attach or Closed phases. +.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 is called in the Attach or Closed phases. +.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. +Returns 0 on success, otherwise an error code. +It is called in the Attach or Closed phases. +.It Dv int start_output(void *hdl, void *block, int blksize, +.Dv "void (*intr)(void*), void *intrarg)" +.Pp +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 . +Returns 0 on success, otherwise an error code. +This field is optional only if the driver doesn't support playback. +It is called in the Opened phase. +.It Dv int start_input(void *hdl, void *block, int blksize, +.Dv "void (*intr)(void*), void *intrarg)" +.Pp +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 . +Returns 0 on success, otherwise an error code. +This field is optional only if the driver doesn't support recording. +It is called in the Opened phase. +.It Dv int halt_output(void *hdl) +is called to abort the output transfer (started by +.Va start_output ) +in progress. +Returns 0 on success, otherwise an error code. +This field is optional only if the driver doesn't support playback. +It is called in the Opened phase. +.It Dv int halt_input(void *hdl) +is called to abort the input transfer (started by +.Va start_input ) +in progress. +Returns 0 on success, otherwise an error code. +This field is optional only if the driver doesn't support recording, +It is called in the Opened phase. +.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. +Returns 0 on success, otherwise an error code. +It is called in the Opened phase. +.It Dv int getdev(void *hdl, struct audio_device *ret) +Should fill the +.Va audio_device +struct with relevant information about the driver. +Returns 0 on success, otherwise an error code. +It is called in the Opened phase. +.It Dv int set_port(void *hdl, mixer_ctrl_t *mc) +is called in when +.Dv AUDIO_MIXER_WRITE +is used. +It should take data from the +.Va mixer_ctrl_t +struct and set the corresponding mixer values. +Returns 0 on success, otherwise an error code. +It is called in the Opened or Closed phases. +.It Dv int get_port(void *hdl, mixer_ctrl_t *mc) +is called in when +.Dv AUDIO_MIXER_READ +is used. +It should fill the +.Va mixer_ctrl_t +struct. +Returns 0 on success, otherwise an error code. +It is called in the Opened or Closed phases. +.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 is called at any time. +.It Dv "void *allocm(void *hdl, int direction, size_t size)" +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 +.Dv NULL +on failure. +It is called in the Attached or Closed phases. +.It Dv void freem(void *hdl, void *addr, size_t size) +optional, is called to free memory allocated by +.Va allocm . +If not supplied +.Xr free 9 +is used. +It is called in the Attached or Closed phases. +.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 is called in the Attached or Closed phases. +.It Dv int get_props(void *hdl) +Should return the device properties in a combination of following flags: +.Pp +.Bl -tag -width AUDIO_PROP_INDEPENDENT -compact +.It Dv AUDIO_PROP_PLAYBACK +the device is capable of audio playback. +.It Dv AUDIO_PROP_CAPTURE +the device is capable of audio capture. +.It Dv AUDIO_PROP_FULLDUPLEX +the device admits full duplex operation. +Don't set it if the device is unidirectional. +.It Dv AUDIO_PROP_INDEPENDENT +the device can set the playing and recording encoding parameters +independently. +Don't set it if the device is unidirectional. +.It Dv AUDIO_PROP_MMAP +is handled in the upper layer, so new drivers should not return this property. +.El +It is called in the Attach phase. +.It Dv int trigger_output(void *hdl, void *start, void *end, +.Dv "int blksize, void (*intr)(void*), void *intrarg," +.Pp +.Dv "const audio_params_t *param)" +.Pp +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 is called in the Opened phase. +.It Dv int trigger_input(void *hdl, void *start, void *end, +.Dv "int blksize, void (*intr)(void*), void *intrarg," +.Pp +.Dv "const audio_params_t *param)" +.Pp +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 is called in the Opened phase. +.It Dv int dev_ioctl(void *hdl, u_long cmd, void *addr, +.Pp +.Dv "int flag, struct lwp *l)" +.Pp +optional, is called when an +.Xr ioctl 2 +is not recognized by the generic audio driver. +Return 0 on success, otherwise an error code. +It is called in the Opened phase. +.It Dv void get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread) +Returns the interrupt and thread locks to the common audio layer. +It is called in the Attach phase. +.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, +as of course should any controls that affect both playback and recording. +.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 . |
