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