• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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