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