Home | History | Annotate | Download | only in server
      1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 /*
      7  * Alsa Helpers - Keeps the interface to alsa localized to this file.
      8  */
      9 
     10 #ifndef _CRAS_ALSA_HELPERS_H
     11 #define _CRAS_ALSA_HELPERS_H
     12 
     13 #include <alsa/asoundlib.h>
     14 #include <stdint.h>
     15 #include <stdlib.h>
     16 
     17 struct cras_audio_format;
     18 
     19 
     20 /* Sets the channel layout from given format to the pcm handle.
     21  * Args:
     22  *    handle - Pointer to the opened pcm to set channel map to.
     23  *    fmt - The format containing the channel layout info.
     24  * Returns:
     25  *    0 if a matched channel map is set to HW, -1 otherwise.
     26  */
     27 int cras_alsa_set_channel_map(snd_pcm_t *handle,
     28 			      struct cras_audio_format *fmt);
     29 
     30 /*  Gets the supported channel mapping of the pcm handle which matches
     31  *  the channel layout in the format.
     32  *  Args:
     33  *     handle - Pointer to the opened pcm to get channel map info.
     34  *     fmt - The format to fill channel layout into.
     35  *  Returns:
     36  *     0 if an exactly matched channel map is found, -1 otherwise.
     37  */
     38 int cras_alsa_get_channel_map(snd_pcm_t *handle,
     39 			      struct cras_audio_format *fmt);
     40 
     41 /* Opens an alsa device, thin wrapper to snd_pcm_open.
     42  * Args:
     43  *    handle - Filled with a pointer to the opened pcm.
     44  *    dev - Path to the alsa device to test.
     45  *    stream - Alsa stream type, input or output.
     46  * Returns:
     47  *    See docs for snd_pcm_open.
     48  */
     49 int cras_alsa_pcm_open(snd_pcm_t **handle, const char *dev,
     50 		       snd_pcm_stream_t stream);
     51 
     52 /* Closes an alsa device, thin wrapper to snd_pcm_close.
     53  * Args:
     54  *    handle - Filled with a pointer to the opened pcm.
     55  * Returns:
     56  *    See docs for snd_pcm_close.
     57  */
     58 int cras_alsa_pcm_close(snd_pcm_t *handle);
     59 
     60 /* Starts an alsa device, thin wrapper to snd_pcm_start.
     61  * Args:
     62  *    handle - Filled with a pointer to the opened pcm.
     63  * Returns:
     64  *    See docs for snd_pcm_start.
     65  */
     66 int cras_alsa_pcm_start(snd_pcm_t *handle);
     67 
     68 /* Drains an alsa device, thin wrapper to snd_pcm_drain.
     69  * Args:
     70  *    handle - Filled with a pointer to the opened pcm.
     71  * Returns:
     72  *    See docs for snd_pcm_drain.
     73  */
     74 int cras_alsa_pcm_drain(snd_pcm_t *handle);
     75 
     76 /* Forward/rewind appl_ptr so it becomes ahead of hw_ptr by fuzz samples.
     77  * After moving appl_ptr, device can play the new samples as quick as possible.
     78  *    avail = buffer_frames - appl_ptr + hw_ptr
     79  * => hw_ptr - appl_ptr = avail - buffer_frames.
     80  * The difference between hw_ptr and app_ptr can be inferred from snd_pcm_avail.
     81  * So the amount of frames to forward appl_ptr is
     82  * avail - buffer_frames + fuzz.
     83  * When hw_ptr is wrapped around boundary, this value may be negative. Use
     84  * snd_pcm_rewind to move appl_ptr backward.
     85  *
     86  * Case 1: avail - buffer_frames + fuzz > 0
     87  *
     88  * -------|----------|-----------------------------------
     89  *      app_ptr     hw_ptr
     90  *        |------------->| forward target
     91  *
     92  * Case 2: avail - buffer_frames + fuzz < 0
     93  *
     94  * -------|----------|-----------------------------------
     95  *      hw_ptr      app_ptr
     96  *           |<------| rewind target
     97  *
     98  * Args:
     99  *    handle - Filled with a pointer to the opened pcm.
    100  *    ahead - Number of frames appl_ptr should be ahead of hw_ptr.
    101  * Returns:
    102  *    0 on success. A negative error code on failure.
    103  */
    104 int cras_alsa_resume_appl_ptr(snd_pcm_t *handle, snd_pcm_uframes_t ahead);
    105 
    106 /* Probes properties of the alsa device.
    107  * Args:
    108  *    dev - Path to the alsa device to test.
    109  *    stream - Alsa stream type, input or output.
    110  *    rates - Pointer that will be set to the arrary of valid samples rates.
    111  *            Must be freed by the caller.
    112  *    channel_counts - Pointer that will be set to the array of valid channel
    113  *                     counts.  Must be freed by the caller.
    114  *    formats - Pointer that will be set to the arrary of valid PCM formats.
    115  *              Must be freed by the caller.
    116  * Returns:
    117  *   0 on success.  On failure an error code from alsa or -ENOMEM.
    118  */
    119 int cras_alsa_fill_properties(const char *dev, snd_pcm_stream_t stream,
    120 			      size_t **rates, size_t **channel_counts,
    121 			      snd_pcm_format_t **formats);
    122 
    123 /* Sets up the hwparams to alsa.
    124  * Args:
    125  *    handle - The open PCM to configure.
    126  *    format - The audio format desired for playback/capture.
    127  *    buffer_frames - Number of frames in the ALSA buffer.
    128  *    period_wakeup - Flag to determine if period_wakeup is required
    129  *                      0 - disable, 1 - enable
    130  *    dma_period_time - If non-zero, set the dma period time to this value
    131  *                      (in microseconds).
    132  * Returns:
    133  *    0 on success, negative error on failure.
    134  */
    135 int cras_alsa_set_hwparams(snd_pcm_t *handle, struct cras_audio_format *format,
    136 			   snd_pcm_uframes_t *buffer_frames, int period_wakeup,
    137 			   unsigned int dma_period_time);
    138 
    139 /* Sets up the swparams to alsa.
    140  * Args:
    141  *    handle - The open PCM to configure.
    142  *    enable_htimestamp - If non-zero, enable and configure hardware timestamps,
    143  *                        updated to reflect whether MONOTONIC RAW htimestamps
    144  *                        are supported by the kernel implementation.
    145  * Returns:
    146  *    0 on success, negative error on failure.
    147  */
    148 int cras_alsa_set_swparams(snd_pcm_t *handle, int *enable_htimestamp);
    149 
    150 /* Get the number of used frames in the alsa buffer.
    151  *
    152  * When underrun is not severe, this function masks the underrun situation
    153  * and set avail as 0. When underrun is severe, returns -EPIPE so caller
    154  * can handle it.
    155  * Args:
    156  *    handle[in] - The open PCM to configure.
    157  *    buf_size[in] - Number of frames in the ALSA buffer.
    158  *    severe_underrun_frames[in] - Number of frames as the threshold for severe
    159  *                                 underrun.
    160  *    dev_name[in] - Device name for logging.
    161  *    avail[out] - Filled with the number of frames available in the buffer.
    162  *    tstamp[out] - Filled with the hardware timestamp for the available frames.
    163  *                  This value is {0, 0} when the device hasn't actually started
    164  *                  reading or writing frames.
    165  *    underruns[in,out] - Pointer to the underrun counter updated if there was
    166  *                        an underrun.
    167  * Returns:
    168  *    0 on success, negative error on failure. -EPIPE if severe underrun
    169  *    happens.
    170  */
    171 int cras_alsa_get_avail_frames(snd_pcm_t *handle, snd_pcm_uframes_t buf_size,
    172 			       snd_pcm_uframes_t severe_underrun_frames,
    173 			       const char *dev_name,
    174 			       snd_pcm_uframes_t *avail,
    175 			       struct timespec *tstamp,
    176 			       unsigned int *underruns);
    177 
    178 /* Get the current alsa delay, make sure it's no bigger than the buffer size.
    179  * Args:
    180  *    handle - The open PCM to configure.
    181  *    buf_size - Number of frames in the ALSA buffer.
    182  *    delay - Filled with the number of delay frames.
    183  * Returns:
    184  *    0 on success, negative error on failure.
    185  */
    186 int cras_alsa_get_delay_frames(snd_pcm_t *handle, snd_pcm_uframes_t buf_size,
    187 			       snd_pcm_sframes_t *delay);
    188 
    189 /* Wrapper for snd_pcm_mmap_begin where only buffer is concerned.
    190  * Offset and frames from cras_alsa_mmap_begin are neglected.
    191  * Args:
    192  *    handle - The open PCM to configure.
    193  *    dst - Pointer set to the area for reading/writing the audio.
    194  *    underruns - counter to increment if an under-run occurs.
    195  * Returns:
    196  *    zero on success, negative error code for fatal errors.
    197  */
    198 int cras_alsa_mmap_get_whole_buffer(snd_pcm_t *handle, uint8_t **dst,
    199 				    unsigned int *underrun);
    200 
    201 /* Wrapper for snd_pcm_mmap_begin
    202  * Args:
    203  *    handle - The open PCM to configure.
    204  *    format_bytes - Number of bytes in a single frame.
    205  *    dst - Pointer set to the area for reading/writing the audio.
    206  *    offset - Filled with the offset to pass back to commit.
    207  *    frames - Passed with the max number of frames to request. Filled with the
    208  *        max number to use.
    209  *    underruns - counter to increment if an under-run occurs.
    210  * Returns:
    211  *    zero on success, negative error code for fatal
    212  *    errors.
    213  */
    214 int cras_alsa_mmap_begin(snd_pcm_t *handle, unsigned int format_bytes,
    215 			 uint8_t **dst, snd_pcm_uframes_t *offset,
    216 			 snd_pcm_uframes_t *frames, unsigned int *underruns);
    217 
    218 /* Wrapper for snd_pcm_mmap_commit
    219  * Args:
    220  *    handle - The open PCM to configure.
    221  *    offset - offset from call to mmap_begin.
    222  *    frames - # of frames written/read.
    223  *    underruns - counter to increment if an under-run occurs.
    224  * Returns:
    225  *    zero on success, negative error code for fatal
    226  *    errors.
    227  */
    228 int cras_alsa_mmap_commit(snd_pcm_t *handle, snd_pcm_uframes_t offset,
    229 			  snd_pcm_uframes_t frames, unsigned int *underruns);
    230 
    231 /* When the stream is suspended, due to a system suspend, loop until we can
    232  * resume it. Won't actually loop very much because the system will be
    233  * suspended.
    234  * Args:
    235  *    handle - The open PCM to configure.
    236  * Returns:
    237  *    zero on success, negative error code for fatal
    238  *    errors.
    239  */
    240 int cras_alsa_attempt_resume(snd_pcm_t *handle);
    241 
    242 #endif /* _CRAS_ALSA_HELPERS_H */
    243