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 #include <alsa/asoundlib.h>
7 #include <limits.h>
8 #include <stdlib.h>
9 #include <syslog.h>
10 
11 #include "cras_alsa_helpers.h"
12 #include "cras_audio_format.h"
13 #include "cras_util.h"
14 
15 /* Macro to convert between snd_pcm_chmap_position(defined in
16  * alsa-lib since 1.0.27) and CRAS_CHANNEL, values of which are
17  * of the same order but shifted by 3.
18  */
19 #define CH_TO_ALSA(ch) ((ch) + (3))
20 #define CH_TO_CRAS(ch) ((ch) - (3))
21 
22 /* Assert the channel is defined in CRAS_CHANNELS. */
23 #define ALSA_CH_VALID(ch) ((ch >= SND_CHMAP_FL) && (ch <= SND_CHMAP_FRC))
24 
25 /* Time difference between two consecutive underrun logs. */
26 #define UNDERRUN_LOG_TIME_SECS 30
27 
28 /* Limit the number of channels supported for devices: b/158509536 */
29 #define TEMP_CHANNEL_LIMIT 20
30 
31 /* Chances to give mmap_begin to work. */
32 static const size_t MAX_MMAP_BEGIN_ATTEMPTS = 3;
33 /* Time to sleep between resume attempts. */
34 static const size_t ALSA_SUSPENDED_SLEEP_TIME_US = 250000;
35 
36 /* What rates should we check for on this dev?
37  * Listed in order of preference. 0 terminalted. */
38 static const size_t test_sample_rates[] = {
39 	44100, 48000, 32000, 96000, 22050, 16000, 8000, 4000, 192000, 0,
40 };
41 
42 /* What channel counts shoud be checked on this dev?
43  * Listed in order of preference. 0 terminalted. */
44 static const size_t test_channel_counts[] = { 10, 6, 4, 2, 1, 8, 0 };
45 
46 static const snd_pcm_format_t test_formats[] = {
47 	SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S32_LE,
48 	SND_PCM_FORMAT_S24_3LE, (snd_pcm_format_t)0
49 };
50 
51 /* Looks up the list of channel map for the one can exactly matches
52  * the layout specified in fmt.
53  */
54 static snd_pcm_chmap_query_t *
cras_chmap_caps_match(snd_pcm_chmap_query_t ** chmaps,struct cras_audio_format * fmt)55 cras_chmap_caps_match(snd_pcm_chmap_query_t **chmaps,
56 		      struct cras_audio_format *fmt)
57 {
58 	size_t ch, i;
59 	int idx, matches;
60 	snd_pcm_chmap_query_t **chmap;
61 
62 	/* Search for channel map that already matches the order */
63 	for (chmap = chmaps; *chmap; chmap++) {
64 		if ((*chmap)->map.channels != fmt->num_channels)
65 			continue;
66 
67 		matches = 1;
68 		for (ch = 0; ch < CRAS_CH_MAX; ch++) {
69 			idx = fmt->channel_layout[ch];
70 			if (idx == -1)
71 				continue;
72 			if ((unsigned)idx >= (*chmap)->map.channels)
73 				continue;
74 			if ((*chmap)->map.pos[idx] != CH_TO_ALSA(ch)) {
75 				matches = 0;
76 				break;
77 			}
78 		}
79 		if (matches)
80 			return *chmap;
81 	}
82 
83 	/* Search for channel map that can arbitrarily swap order */
84 	for (chmap = chmaps; *chmap; chmap++) {
85 		if ((*chmap)->type == SND_CHMAP_TYPE_FIXED ||
86 		    (*chmap)->map.channels != fmt->num_channels)
87 			continue;
88 
89 		matches = 1;
90 		for (ch = 0; ch < CRAS_CH_MAX; ch++) {
91 			idx = fmt->channel_layout[ch];
92 			if (idx == -1)
93 				continue;
94 			int found = 0;
95 			for (i = 0; i < fmt->num_channels; i++) {
96 				if ((*chmap)->map.pos[i] == CH_TO_ALSA(ch)) {
97 					found = 1;
98 					break;
99 				}
100 			}
101 			if (found == 0) {
102 				matches = 0;
103 				break;
104 			}
105 		}
106 		if (matches && (*chmap)->type == SND_CHMAP_TYPE_VAR)
107 			return *chmap;
108 
109 		/* Check if channel map is a match by arbitrarily swap
110 		 * pair order */
111 		matches = 1;
112 		for (i = 0; i < fmt->num_channels; i += 2) {
113 			ch = CH_TO_CRAS((*chmap)->map.pos[i]);
114 			if (fmt->channel_layout[ch] & 0x01) {
115 				matches = 0;
116 				break;
117 			}
118 
119 			if (fmt->channel_layout[ch] + 1 !=
120 			    fmt->channel_layout[CH_TO_CRAS(
121 				    (*chmap)->map.pos[i + 1])]) {
122 				matches = 0;
123 				break;
124 			}
125 		}
126 		if (matches)
127 			return *chmap;
128 	}
129 
130 	return NULL;
131 }
132 
133 /* When the exact match does not exist, select the best valid
134  * channel map which can be supported by means of channel conversion
135  * matrix.
136  */
137 static snd_pcm_chmap_query_t *
cras_chmap_caps_conv_matrix(snd_pcm_chmap_query_t ** chmaps,struct cras_audio_format * fmt)138 cras_chmap_caps_conv_matrix(snd_pcm_chmap_query_t **chmaps,
139 			    struct cras_audio_format *fmt)
140 {
141 	float **conv_mtx;
142 	size_t i;
143 	snd_pcm_chmap_query_t **chmap;
144 	struct cras_audio_format *conv_fmt;
145 
146 	conv_fmt = cras_audio_format_create(fmt->format, fmt->frame_rate,
147 					    fmt->num_channels);
148 
149 	for (chmap = chmaps; *chmap; chmap++) {
150 		if ((*chmap)->map.channels != fmt->num_channels)
151 			continue;
152 		for (i = 0; i < CRAS_CH_MAX; i++)
153 			conv_fmt->channel_layout[i] = -1;
154 		for (i = 0; i < conv_fmt->num_channels; i++) {
155 			if (!ALSA_CH_VALID((*chmap)->map.pos[i]))
156 				continue;
157 			conv_fmt->channel_layout[CH_TO_CRAS(
158 				(*chmap)->map.pos[i])] = i;
159 		}
160 
161 		/* Examine channel map by test creating a conversion matrix
162 		 * for each candidate. Once a non-null matrix is created,
163 		 * that channel map is considered supported and select it as
164 		 * the best match one.
165 		 */
166 		conv_mtx = cras_channel_conv_matrix_create(fmt, conv_fmt);
167 		if (conv_mtx) {
168 			cras_channel_conv_matrix_destroy(
169 				conv_mtx, conv_fmt->num_channels);
170 			cras_audio_format_destroy(conv_fmt);
171 			return *chmap;
172 		}
173 	}
174 
175 	cras_audio_format_destroy(conv_fmt);
176 	return NULL;
177 }
178 
179 /* Finds the best channel map for given format and list of channel
180  * map capability.
181  */
182 static snd_pcm_chmap_query_t *
cras_chmap_caps_best(snd_pcm_t * handle,snd_pcm_chmap_query_t ** chmaps,struct cras_audio_format * fmt)183 cras_chmap_caps_best(snd_pcm_t *handle, snd_pcm_chmap_query_t **chmaps,
184 		     struct cras_audio_format *fmt)
185 {
186 	snd_pcm_chmap_query_t **chmap;
187 	snd_pcm_chmap_query_t *match;
188 
189 	match = cras_chmap_caps_match(chmaps, fmt);
190 	if (match)
191 		return match;
192 
193 	match = cras_chmap_caps_conv_matrix(chmaps, fmt);
194 	if (match)
195 		return match;
196 
197 	/* For capture stream, choose the first chmap matching channel
198 	 * count. Channel positions reported in this chmap will be used
199 	 * to fill correspond channels into client stream.
200 	 */
201 	if (snd_pcm_stream(handle) == SND_PCM_STREAM_CAPTURE)
202 		for (chmap = chmaps; *chmap; chmap++)
203 			if ((*chmap)->map.channels == fmt->num_channels)
204 				return *chmap;
205 	return NULL;
206 }
207 
cras_alsa_pcm_open(snd_pcm_t ** handle,const char * dev,snd_pcm_stream_t stream)208 int cras_alsa_pcm_open(snd_pcm_t **handle, const char *dev,
209 		       snd_pcm_stream_t stream)
210 {
211 	int rc;
212 	int retries = 3;
213 	static const unsigned int OPEN_RETRY_DELAY_US = 100000;
214 
215 retry_open:
216 	rc = snd_pcm_open(handle, dev, stream,
217 			  SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE |
218 				  SND_PCM_NO_AUTO_CHANNELS |
219 				  SND_PCM_NO_AUTO_FORMAT);
220 	if (rc == -EBUSY && --retries) {
221 		usleep(OPEN_RETRY_DELAY_US);
222 		goto retry_open;
223 	}
224 
225 	return rc;
226 }
227 
cras_alsa_pcm_close(snd_pcm_t * handle)228 int cras_alsa_pcm_close(snd_pcm_t *handle)
229 {
230 	return snd_pcm_close(handle);
231 }
232 
cras_alsa_pcm_start(snd_pcm_t * handle)233 int cras_alsa_pcm_start(snd_pcm_t *handle)
234 {
235 	return snd_pcm_start(handle);
236 }
237 
cras_alsa_pcm_drain(snd_pcm_t * handle)238 int cras_alsa_pcm_drain(snd_pcm_t *handle)
239 {
240 	return snd_pcm_drain(handle);
241 }
242 
cras_alsa_resume_appl_ptr(snd_pcm_t * handle,snd_pcm_uframes_t ahead)243 int cras_alsa_resume_appl_ptr(snd_pcm_t *handle, snd_pcm_uframes_t ahead)
244 {
245 	int rc;
246 	snd_pcm_uframes_t period_frames, buffer_frames;
247 	snd_pcm_sframes_t to_move, avail_frames;
248 	rc = snd_pcm_avail(handle);
249 	if (rc == -EPIPE || rc == -ESTRPIPE) {
250 		cras_alsa_attempt_resume(handle);
251 		avail_frames = 0;
252 	} else if (rc < 0) {
253 		syslog(LOG_ERR, "Fail to get avail frames: %s",
254 		       snd_strerror(rc));
255 		return rc;
256 	} else {
257 		avail_frames = rc;
258 	}
259 
260 	rc = snd_pcm_get_params(handle, &buffer_frames, &period_frames);
261 	if (rc < 0) {
262 		syslog(LOG_ERR, "Fail to get buffer size: %s",
263 		       snd_strerror(rc));
264 		return rc;
265 	}
266 
267 	to_move = avail_frames - buffer_frames + ahead;
268 	if (to_move > 0) {
269 		rc = snd_pcm_forward(handle, to_move);
270 	} else if (to_move < 0) {
271 		rc = snd_pcm_rewind(handle, -to_move);
272 	} else {
273 		return 0;
274 	}
275 
276 	if (rc < 0) {
277 		syslog(LOG_ERR, "Fail to resume appl_ptr: %s",
278 		       snd_strerror(rc));
279 		return rc;
280 	}
281 	return 0;
282 }
283 
cras_alsa_set_channel_map(snd_pcm_t * handle,struct cras_audio_format * fmt)284 int cras_alsa_set_channel_map(snd_pcm_t *handle, struct cras_audio_format *fmt)
285 {
286 	size_t i, ch;
287 	snd_pcm_chmap_query_t **chmaps;
288 	snd_pcm_chmap_query_t *match;
289 
290 	if (fmt->num_channels <= 2)
291 		return 0;
292 
293 	chmaps = snd_pcm_query_chmaps(handle);
294 	if (chmaps == NULL) {
295 		syslog(LOG_WARNING, "No chmap queried! Skip chmap set");
296 		goto done;
297 	}
298 
299 	match = cras_chmap_caps_best(handle, chmaps, fmt);
300 	if (!match) {
301 		syslog(LOG_ERR, "Unable to find the best channel map");
302 		goto done;
303 	}
304 
305 	/* A channel map could match the layout after channels
306 	 * pair/arbitrary swapped. Modified the channel positions
307 	 * before set to HW.
308 	 */
309 	for (i = 0; i < fmt->num_channels; i++) {
310 		for (ch = 0; ch < CRAS_CH_MAX; ch++)
311 			if (fmt->channel_layout[ch] == (int)i)
312 				break;
313 		if (ch != CRAS_CH_MAX)
314 			match->map.pos[i] = CH_TO_ALSA(ch);
315 	}
316 	if (snd_pcm_set_chmap(handle, &match->map) != 0)
317 		syslog(LOG_ERR, "Unable to set channel map");
318 
319 done:
320 	snd_pcm_free_chmaps(chmaps);
321 	return 0;
322 }
323 
cras_alsa_get_channel_map(snd_pcm_t * handle,struct cras_audio_format * fmt)324 int cras_alsa_get_channel_map(snd_pcm_t *handle, struct cras_audio_format *fmt)
325 {
326 	snd_pcm_chmap_query_t **chmaps;
327 	snd_pcm_chmap_query_t *match;
328 	int rc = 0;
329 	size_t i;
330 
331 	chmaps = snd_pcm_query_chmaps(handle);
332 	if (chmaps == NULL) {
333 		rc = -EINVAL;
334 		goto done;
335 	}
336 
337 	match = cras_chmap_caps_best(handle, chmaps, fmt);
338 	if (!match) {
339 		syslog(LOG_ERR, "Unable to find the best channel map");
340 		rc = -1;
341 		goto done;
342 	}
343 
344 	/* Fill back the selected channel map so channel converter can
345 	 * handle it. */
346 	for (i = 0; i < CRAS_CH_MAX; i++)
347 		fmt->channel_layout[i] = -1;
348 	for (i = 0; i < fmt->num_channels; i++) {
349 		if (!ALSA_CH_VALID(match->map.pos[i]))
350 			continue;
351 		fmt->channel_layout[CH_TO_CRAS(match->map.pos[i])] = i;
352 	}
353 
354 	/* Handle the special channel map {SND_CHMAP_MONO} */
355 	if (match->map.channels == 1 && match->map.pos[0] == SND_CHMAP_MONO)
356 		fmt->channel_layout[CRAS_CH_FC] = 0;
357 
358 done:
359 	snd_pcm_free_chmaps(chmaps);
360 	return rc;
361 }
362 
cras_alsa_fill_properties(snd_pcm_t * handle,size_t ** rates,size_t ** channel_counts,snd_pcm_format_t ** formats)363 int cras_alsa_fill_properties(snd_pcm_t *handle, size_t **rates,
364 			      size_t **channel_counts,
365 			      snd_pcm_format_t **formats)
366 {
367 	int rc;
368 	size_t i, num_found;
369 	snd_pcm_hw_params_t *params;
370 
371 	snd_pcm_hw_params_alloca(&params);
372 
373 	rc = snd_pcm_hw_params_any(handle, params);
374 	if (rc < 0) {
375 		syslog(LOG_ERR, "snd_pcm_hw_params_any: %s", snd_strerror(rc));
376 		return rc;
377 	}
378 
379 	*rates = (size_t *)malloc(sizeof(test_sample_rates));
380 	if (*rates == NULL)
381 		return -ENOMEM;
382 	*channel_counts = (size_t *)malloc(sizeof(test_channel_counts));
383 	if (*channel_counts == NULL) {
384 		free(*rates);
385 		return -ENOMEM;
386 	}
387 	*formats = (snd_pcm_format_t *)malloc(sizeof(test_formats));
388 	if (*formats == NULL) {
389 		free(*channel_counts);
390 		free(*rates);
391 		return -ENOMEM;
392 	}
393 
394 	num_found = 0;
395 	for (i = 0; test_sample_rates[i] != 0; i++) {
396 		rc = snd_pcm_hw_params_test_rate(handle, params,
397 						 test_sample_rates[i], 0);
398 		if (rc == 0)
399 			(*rates)[num_found++] = test_sample_rates[i];
400 	}
401 	(*rates)[num_found] = 0;
402 	if (num_found == 0) {
403 		syslog(LOG_WARNING, "No valid sample rates.");
404 		return -EINVAL;
405 	}
406 
407 	num_found = 0;
408 	for (i = 0; test_channel_counts[i] != 0; i++) {
409 		rc = snd_pcm_hw_params_test_channels(handle, params,
410 						     test_channel_counts[i]);
411 		if (rc == 0)
412 			(*channel_counts)[num_found++] = test_channel_counts[i];
413 	}
414 	(*channel_counts)[num_found] = 0;
415 	if (num_found == 0) {
416 		// Pull the max channel count and use that.
417 		unsigned int max_channels = 0;
418 		rc = snd_pcm_hw_params_get_channels_max(params, &max_channels);
419 		if (rc < 0) {
420 			syslog(LOG_WARNING, "No valid channel counts found.");
421 			return -EINVAL;
422 		} else if (max_channels > TEMP_CHANNEL_LIMIT) {
423 			syslog(LOG_WARNING, "Can't support so many channels.");
424 			return -EINVAL;
425 		} else {
426 			(*channel_counts)[0] = (size_t)max_channels;
427 			(*channel_counts)[1] = 0;
428 		}
429 	}
430 
431 	num_found = 0;
432 	for (i = 0; test_formats[i] != 0; i++) {
433 		rc = snd_pcm_hw_params_test_format(handle, params,
434 						   test_formats[i]);
435 		if (rc == 0)
436 			(*formats)[num_found++] = test_formats[i];
437 	}
438 	(*formats)[num_found] = (snd_pcm_format_t)0;
439 	if (num_found == 0) {
440 		syslog(LOG_WARNING, "No valid sample formats.");
441 		return -EINVAL;
442 	}
443 
444 	return 0;
445 }
446 
cras_alsa_set_hwparams(snd_pcm_t * handle,struct cras_audio_format * format,snd_pcm_uframes_t * buffer_frames,int period_wakeup,unsigned int dma_period_time)447 int cras_alsa_set_hwparams(snd_pcm_t *handle, struct cras_audio_format *format,
448 			   snd_pcm_uframes_t *buffer_frames, int period_wakeup,
449 			   unsigned int dma_period_time)
450 {
451 	unsigned int rate, ret_rate;
452 	int err;
453 	snd_pcm_hw_params_t *hwparams;
454 
455 	rate = format->frame_rate;
456 	snd_pcm_hw_params_alloca(&hwparams);
457 
458 	err = snd_pcm_hw_params_any(handle, hwparams);
459 	if (err < 0) {
460 		syslog(LOG_ERR, "hw_params_any failed %s\n", snd_strerror(err));
461 		return err;
462 	}
463 	/* Disable hardware resampling. */
464 	err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 0);
465 	if (err < 0) {
466 		syslog(LOG_ERR, "Disabling resampling %s\n", snd_strerror(err));
467 		return err;
468 	}
469 	/* Always interleaved. */
470 	err = snd_pcm_hw_params_set_access(handle, hwparams,
471 					   SND_PCM_ACCESS_MMAP_INTERLEAVED);
472 	if (err < 0) {
473 		syslog(LOG_ERR, "Setting interleaved %s\n", snd_strerror(err));
474 		return err;
475 	}
476 	/* If period_wakeup flag is not set, try to disable ALSA wakeups,
477 	 * we'll keep a timer. */
478 	if (!period_wakeup &&
479 	    snd_pcm_hw_params_can_disable_period_wakeup(hwparams)) {
480 		err = snd_pcm_hw_params_set_period_wakeup(handle, hwparams, 0);
481 		if (err < 0)
482 			syslog(LOG_WARNING, "disabling wakeups %s\n",
483 			       snd_strerror(err));
484 	}
485 	/* Setup the period time so that the hardware pulls the right amount
486 	 * of data at the right time. */
487 	if (dma_period_time) {
488 		int dir = 0;
489 		unsigned int original = dma_period_time;
490 
491 		err = snd_pcm_hw_params_set_period_time_near(
492 			handle, hwparams, &dma_period_time, &dir);
493 		if (err < 0) {
494 			syslog(LOG_ERR, "could not set period time: %s",
495 			       snd_strerror(err));
496 			return err;
497 		} else if (original != dma_period_time) {
498 			syslog(LOG_DEBUG, "period time set to: %u",
499 			       dma_period_time);
500 		}
501 	}
502 	/* Set the sample format. */
503 	err = snd_pcm_hw_params_set_format(handle, hwparams, format->format);
504 	if (err < 0) {
505 		syslog(LOG_ERR, "set format %s\n", snd_strerror(err));
506 		return err;
507 	}
508 	/* Set the stream rate. */
509 	ret_rate = rate;
510 	err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &ret_rate, 0);
511 	if (err < 0) {
512 		syslog(LOG_ERR, "set_rate_near %iHz %s\n", rate,
513 		       snd_strerror(err));
514 		return err;
515 	}
516 	if (ret_rate != rate) {
517 		syslog(LOG_ERR, "tried for %iHz, settled for %iHz)\n", rate,
518 		       ret_rate);
519 		return -EINVAL;
520 	}
521 	/* Set the count of channels. */
522 	err = snd_pcm_hw_params_set_channels(handle, hwparams,
523 					     format->num_channels);
524 	if (err < 0) {
525 		syslog(LOG_ERR, "set_channels %s\n", snd_strerror(err));
526 		return err;
527 	}
528 
529 	/* Make sure buffer frames is even, or snd_pcm_hw_params will
530 	 * return invalid argument error. */
531 	err = snd_pcm_hw_params_get_buffer_size_max(hwparams, buffer_frames);
532 	if (err < 0)
533 		syslog(LOG_WARNING, "get buffer max %s\n", snd_strerror(err));
534 
535 	*buffer_frames &= ~0x01;
536 	err = snd_pcm_hw_params_set_buffer_size_max(handle, hwparams,
537 						    buffer_frames);
538 	if (err < 0) {
539 		syslog(LOG_ERR, "set_buffer_size_max %s", snd_strerror(err));
540 		return err;
541 	}
542 
543 	syslog(LOG_DEBUG, "buffer size set to %u\n",
544 	       (unsigned int)*buffer_frames);
545 
546 	/* Finally, write the parameters to the device. */
547 	err = snd_pcm_hw_params(handle, hwparams);
548 	if (err < 0) {
549 		syslog(LOG_ERR,
550 		       "hw_params: %s: rate: %u, ret_rate: %u, "
551 		       "channel: %zu, format: %u\n",
552 		       snd_strerror(err), rate, ret_rate, format->num_channels,
553 		       format->format);
554 		return err;
555 	}
556 	return 0;
557 }
558 
cras_alsa_set_swparams(snd_pcm_t * handle)559 int cras_alsa_set_swparams(snd_pcm_t *handle)
560 {
561 	int err;
562 	snd_pcm_sw_params_t *swparams;
563 	snd_pcm_uframes_t boundary;
564 
565 	snd_pcm_sw_params_alloca(&swparams);
566 
567 	err = snd_pcm_sw_params_current(handle, swparams);
568 	if (err < 0) {
569 		syslog(LOG_ERR, "sw_params_current: %s\n", snd_strerror(err));
570 		return err;
571 	}
572 	err = snd_pcm_sw_params_get_boundary(swparams, &boundary);
573 	if (err < 0) {
574 		syslog(LOG_ERR, "get_boundary: %s\n", snd_strerror(err));
575 		return err;
576 	}
577 	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, boundary);
578 	if (err < 0) {
579 		syslog(LOG_ERR, "set_stop_threshold: %s\n", snd_strerror(err));
580 		return err;
581 	}
582 	/* Don't auto start. */
583 	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, LONG_MAX);
584 	if (err < 0) {
585 		syslog(LOG_ERR, "set_stop_threshold: %s\n", snd_strerror(err));
586 		return err;
587 	}
588 
589 	/* Disable period events. */
590 	err = snd_pcm_sw_params_set_period_event(handle, swparams, 0);
591 	if (err < 0) {
592 		syslog(LOG_ERR, "set_period_event: %s\n", snd_strerror(err));
593 		return err;
594 	}
595 
596 	err = snd_pcm_sw_params(handle, swparams);
597 
598 	if (err < 0) {
599 		syslog(LOG_ERR, "sw_params: %s\n", snd_strerror(err));
600 		return err;
601 	}
602 	return 0;
603 }
604 
cras_alsa_get_avail_frames(snd_pcm_t * handle,snd_pcm_uframes_t buf_size,snd_pcm_uframes_t severe_underrun_frames,const char * dev_name,snd_pcm_uframes_t * avail,struct timespec * tstamp)605 int cras_alsa_get_avail_frames(snd_pcm_t *handle, snd_pcm_uframes_t buf_size,
606 			       snd_pcm_uframes_t severe_underrun_frames,
607 			       const char *dev_name, snd_pcm_uframes_t *avail,
608 			       struct timespec *tstamp)
609 {
610 	snd_pcm_sframes_t frames;
611 	int rc = 0;
612 	static struct timespec tstamp_last_underrun_log = { .tv_sec = 0,
613 							    .tv_nsec = 0 };
614 
615 	/* Use snd_pcm_avail still to ensure that the hardware pointer is
616 	 * up to date. Otherwise, we could use the deprecated snd_pcm_hwsync().
617 	 * IMO this is a deficiency in the ALSA API.
618 	 */
619 	frames = snd_pcm_avail(handle);
620 	if (frames >= 0)
621 		rc = snd_pcm_htimestamp(handle, avail, tstamp);
622 	else
623 		rc = frames;
624 	if (rc == -EPIPE || rc == -ESTRPIPE) {
625 		cras_alsa_attempt_resume(handle);
626 		rc = 0;
627 		goto error;
628 	} else if (rc < 0) {
629 		syslog(LOG_ERR, "pcm_avail error %s, %s\n", dev_name,
630 		       snd_strerror(rc));
631 		goto error;
632 	} else if (frames > (snd_pcm_sframes_t)buf_size) {
633 		struct timespec tstamp_now;
634 		clock_gettime(CLOCK_MONOTONIC_RAW, &tstamp_now);
635 		/* Limit the log rate. */
636 		if ((tstamp_now.tv_sec - tstamp_last_underrun_log.tv_sec) >
637 		    UNDERRUN_LOG_TIME_SECS) {
638 			syslog(LOG_ERR,
639 			       "pcm_avail returned frames larger than buf_size: "
640 			       "%s: %ld > %lu\n",
641 			       dev_name, frames, buf_size);
642 			tstamp_last_underrun_log.tv_sec = tstamp_now.tv_sec;
643 			tstamp_last_underrun_log.tv_nsec = tstamp_now.tv_nsec;
644 		}
645 		if ((frames - (snd_pcm_sframes_t)buf_size) >
646 		    (snd_pcm_sframes_t)severe_underrun_frames) {
647 			rc = -EPIPE;
648 			goto error;
649 		} else {
650 			frames = buf_size;
651 		}
652 	}
653 	*avail = frames;
654 	return 0;
655 
656 error:
657 	*avail = 0;
658 	tstamp->tv_sec = 0;
659 	tstamp->tv_nsec = 0;
660 	return rc;
661 }
662 
cras_alsa_get_delay_frames(snd_pcm_t * handle,snd_pcm_uframes_t buf_size,snd_pcm_sframes_t * delay)663 int cras_alsa_get_delay_frames(snd_pcm_t *handle, snd_pcm_uframes_t buf_size,
664 			       snd_pcm_sframes_t *delay)
665 {
666 	int rc;
667 
668 	rc = snd_pcm_delay(handle, delay);
669 	if (rc < 0)
670 		return rc;
671 	if (*delay > (snd_pcm_sframes_t)buf_size)
672 		*delay = buf_size;
673 	if (*delay < 0)
674 		*delay = 0;
675 	return 0;
676 }
677 
678 /*
679  * Attempts to resume a PCM.
680  * Note that this path does not get executed for default playback/capture
681  * stream. Default playback/capture stream are removed from the device
682  * upon suspend, and re-attached to the device after resume.
683  * The only stream that lives across suspend resume is hotword stream.
684  */
cras_alsa_attempt_resume(snd_pcm_t * handle)685 int cras_alsa_attempt_resume(snd_pcm_t *handle)
686 {
687 	int rc;
688 
689 	syslog(LOG_INFO, "System suspended.");
690 	while ((rc = snd_pcm_resume(handle)) == -EAGAIN)
691 		usleep(ALSA_SUSPENDED_SLEEP_TIME_US);
692 	if (rc < 0) {
693 		/*
694 		 * Some devices do not support snd_pcm_resume, that is
695 		 * acceptable.
696 		 */
697 		syslog(LOG_INFO, "System suspended, failed to resume %s.",
698 		       snd_strerror(rc));
699 		rc = snd_pcm_prepare(handle);
700 		if (rc < 0) {
701 			syslog(LOG_ERR, "Suspended, failed to prepare: %s.",
702 			       snd_strerror(rc));
703 		}
704 		/*
705 		 * CRAS does not use auto-start (start_threshold = 0), so start
706 		 * PCM after it is prepared. This is only for hotword stream.
707 		 */
708 		rc = snd_pcm_start(handle);
709 		if (rc < 0) {
710 			syslog(LOG_ERR, "Suspended, failed to start: %s.",
711 			       snd_strerror(rc));
712 		}
713 	}
714 	return rc;
715 }
716 
cras_alsa_mmap_get_whole_buffer(snd_pcm_t * handle,uint8_t ** dst)717 int cras_alsa_mmap_get_whole_buffer(snd_pcm_t *handle, uint8_t **dst)
718 {
719 	snd_pcm_uframes_t offset;
720 	/* The purpose of calling cras_alsa_mmap_begin is to get the base
721 	 * address of the buffer. The requested and retrieved frames are not
722 	 * meaningful here.
723 	 * However, we need to set a non-zero requested frames to get a
724 	 * non-zero retrieved frames. This is to avoid the error checking in
725 	 * snd_pcm_mmap_begin, where it judges retrieved frames being 0 as a
726 	 * failure.
727 	 */
728 	snd_pcm_uframes_t frames = 1;
729 
730 	return cras_alsa_mmap_begin(handle, 0, dst, &offset, &frames);
731 }
732 
cras_alsa_mmap_begin(snd_pcm_t * handle,unsigned int format_bytes,uint8_t ** dst,snd_pcm_uframes_t * offset,snd_pcm_uframes_t * frames)733 int cras_alsa_mmap_begin(snd_pcm_t *handle, unsigned int format_bytes,
734 			 uint8_t **dst, snd_pcm_uframes_t *offset,
735 			 snd_pcm_uframes_t *frames)
736 {
737 	int rc;
738 	unsigned int attempts = 0;
739 	const snd_pcm_channel_area_t *my_areas;
740 
741 	while (attempts++ < MAX_MMAP_BEGIN_ATTEMPTS) {
742 		rc = snd_pcm_mmap_begin(handle, &my_areas, offset, frames);
743 		if (rc == -ESTRPIPE) {
744 			/* First handle suspend/resume. */
745 			rc = cras_alsa_attempt_resume(handle);
746 			if (rc < 0)
747 				return rc;
748 			continue; /* Recovered from suspend, try again. */
749 		} else if (rc < 0) {
750 			/* If we can recover, continue and try again. */
751 			if (snd_pcm_recover(handle, rc, 0) == 0)
752 				continue;
753 			syslog(LOG_INFO, "recover failed begin: %s\n",
754 			       snd_strerror(rc));
755 			return rc;
756 		}
757 		/* Available frames could be zero right after input pcm handle
758 		 * resumed. As for output pcm handle, some error has occurred
759 		 * when mmap_begin return zero frames, return -EIO for that
760 		 * case.
761 		 */
762 		if (snd_pcm_stream(handle) == SND_PCM_STREAM_PLAYBACK &&
763 		    *frames == 0) {
764 			syslog(LOG_INFO, "mmap_begin set frames to 0.");
765 			return -EIO;
766 		}
767 		*dst = (uint8_t *)my_areas[0].addr + (*offset) * format_bytes;
768 		return 0;
769 	}
770 	return -EIO;
771 }
772 
cras_alsa_mmap_commit(snd_pcm_t * handle,snd_pcm_uframes_t offset,snd_pcm_uframes_t frames)773 int cras_alsa_mmap_commit(snd_pcm_t *handle, snd_pcm_uframes_t offset,
774 			  snd_pcm_uframes_t frames)
775 {
776 	int rc;
777 	snd_pcm_sframes_t res;
778 
779 	res = snd_pcm_mmap_commit(handle, offset, frames);
780 	if (res != (snd_pcm_sframes_t)frames) {
781 		res = res >= 0 ? (int)-EPIPE : res;
782 		if (res == -ESTRPIPE) {
783 			/* First handle suspend/resume. */
784 			rc = cras_alsa_attempt_resume(handle);
785 			if (rc < 0)
786 				return rc;
787 		} else {
788 			/* If we can recover, continue and try again. */
789 			rc = snd_pcm_recover(handle, res, 0);
790 			if (rc < 0) {
791 				syslog(LOG_ERR,
792 				       "mmap_commit: pcm_recover failed: %s\n",
793 				       snd_strerror(rc));
794 				return rc;
795 			}
796 		}
797 	}
798 	return 0;
799 }
800