• 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 #include <alsa/asoundlib.h>
7 #include <limits.h>
8 #include <stdio.h>
9 #include <syslog.h>
10 
11 #include "cras_alsa_mixer.h"
12 #include "cras_alsa_mixer_name.h"
13 #include "cras_alsa_ucm.h"
14 #include "cras_util.h"
15 #include "utlist.h"
16 
17 #define MIXER_CONTROL_VOLUME_DB_INVALID LONG_MAX
18 
19 /* Represents an ALSA control element. Each device can have several of these,
20  * each potentially having independent volume and mute controls.
21  * elem - ALSA mixer element.
22  * has_volume - non-zero indicates there is a volume control.
23  * has_mute - non-zero indicates there is a mute switch.
24  * max_volume_dB - the maximum volume for this control, or
25  *                 MIXER_CONTROL_VOLUME_DB_INVALID.
26  * min_volume_dB - the minimum volume for this control, or
27  *                 MIXER_CONTROL_VOLUME_DB_INVALID.
28  */
29 struct mixer_control_element {
30 	snd_mixer_elem_t *elem;
31 	int has_volume;
32 	int has_mute;
33 	long max_volume_dB;
34 	long min_volume_dB;
35 	struct mixer_control_element *prev, *next;
36 };
37 
38 /* Represents an ALSA control element related to a specific input/output
39  * node such as speakers or headphones. A device can have several of these,
40  * each potentially having independent volume and mute controls.
41  *
42  * Each will have at least one mixer_control_element. For cases where there
43  * are separate control elements for left/right channels (for example),
44  * additional mixer_control_elements are added.
45  *
46  * For controls with volume it is assumed that all elements have the same
47  * range.
48  *
49  * name - Name of the control (typicially this is the same as the name of the
50  *        mixer_control_element when there is one, or the name of the UCM
51  *        parent when there are multiple).
52  * dir - Control direction, OUTPUT or INPUT only.
53  * elements - The mixer_control_elements that are driven by this control.
54  * has_volume - non-zero indicates there is a volume control.
55  * has_mute - non-zero indicates there is a mute switch.
56  * max_volume_dB - Maximum volume available in the volume control.
57  * min_volume_dB - Minimum volume available in the volume control.
58  */
59 struct mixer_control {
60 	const char *name;
61 	enum CRAS_STREAM_DIRECTION dir;
62 	struct mixer_control_element *elements;
63 	int has_volume;
64 	int has_mute;
65 	long max_volume_dB;
66 	long min_volume_dB;
67 	struct mixer_control *prev, *next;
68 };
69 
70 /* Holds a reference to the opened mixer and the volume controls.
71  * mixer - Pointer to the opened alsa mixer.
72  * main_volume_controls - List of volume controls (normally 'Master' and 'PCM').
73  * playback_switch - Switch used to mute the device.
74  * main_capture_controls - List of capture gain controls (normally 'Capture').
75  * capture_switch - Switch used to mute the capture stream.
76  * max_volume_dB - Maximum volume available in main volume controls.  The dBFS
77  *   value setting will be applied relative to this.
78  * min_volume_dB - Minimum volume available in main volume controls.
79  */
80 struct cras_alsa_mixer {
81 	snd_mixer_t *mixer;
82 	struct mixer_control *main_volume_controls;
83 	struct mixer_control *output_controls;
84 	snd_mixer_elem_t *playback_switch;
85 	struct mixer_control *main_capture_controls;
86 	struct mixer_control *input_controls;
87 	snd_mixer_elem_t *capture_switch;
88 	long max_volume_dB;
89 	long min_volume_dB;
90 };
91 
92 /* Wrapper for snd_mixer_open and helpers.
93  * Args:
94  *    mixdev - Name of the device to open the mixer for.
95  *    mixer - Pointer filled with the opened mixer on success, NULL on failure.
96  */
alsa_mixer_open(const char * mixdev,snd_mixer_t ** mixer)97 static void alsa_mixer_open(const char *mixdev,
98 			    snd_mixer_t **mixer)
99 {
100 	int rc;
101 
102 	*mixer = NULL;
103 	rc = snd_mixer_open(mixer, 0);
104 	if (rc < 0) {
105 		syslog(LOG_ERR, "snd_mixer_open: %d: %s", rc, strerror(-rc));
106 		return;
107 	}
108 	rc = snd_mixer_attach(*mixer, mixdev);
109 	if (rc < 0) {
110 		syslog(LOG_ERR, "snd_mixer_attach: %d: %s", rc, strerror(-rc));
111 		goto fail_after_open;
112 	}
113 	rc = snd_mixer_selem_register(*mixer, NULL, NULL);
114 	if (rc < 0) {
115 		syslog(LOG_ERR, "snd_mixer_selem_register: %d: %s", rc, strerror(-rc));
116 		goto fail_after_open;
117 	}
118 	rc = snd_mixer_load(*mixer);
119 	if (rc < 0) {
120 		syslog(LOG_ERR, "snd_mixer_load: %d: %s", rc, strerror(-rc));
121 		goto fail_after_open;
122 	}
123 	return;
124 
125 fail_after_open:
126 	snd_mixer_close(*mixer);
127 	*mixer = NULL;
128 }
129 
mixer_control_element_create(snd_mixer_elem_t * elem,enum CRAS_STREAM_DIRECTION dir)130 static struct mixer_control_element *mixer_control_element_create(
131 					snd_mixer_elem_t *elem,
132 					enum CRAS_STREAM_DIRECTION dir)
133 {
134 	struct mixer_control_element *c;
135 	long min, max;
136 
137 	if (!elem)
138 		return NULL;
139 
140 	c = (struct mixer_control_element *)calloc(1, sizeof(*c));
141 	if (!c) {
142 		syslog(LOG_ERR, "No memory for mixer_control_elem.");
143 		return NULL;
144 	}
145 
146 	c->elem = elem;
147 	c->max_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID;
148 	c->min_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID;
149 
150 	if (dir == CRAS_STREAM_OUTPUT) {
151 		c->has_mute = snd_mixer_selem_has_playback_switch(elem);
152 
153 		if (snd_mixer_selem_has_playback_volume(elem) &&
154 		    snd_mixer_selem_get_playback_dB_range(
155 						elem, &min, &max) == 0) {
156 			c->max_volume_dB = max;
157 			c->min_volume_dB = min;
158 			c->has_volume = 1;
159 		}
160 	}
161 	else if (dir == CRAS_STREAM_INPUT) {
162 		c->has_mute = snd_mixer_selem_has_capture_switch(elem);
163 
164 		if (snd_mixer_selem_has_capture_volume(elem) &&
165 		    snd_mixer_selem_get_capture_dB_range(
166 						elem, &min, &max) == 0) {
167 			c->max_volume_dB = max;
168 			c->min_volume_dB = min;
169 			c->has_volume = 1;
170 		}
171 	}
172 
173 	return c;
174 }
175 
mixer_control_destroy(struct mixer_control * control)176 static void mixer_control_destroy(struct mixer_control *control) {
177 	struct mixer_control_element *elem;
178 
179 	if (!control)
180 		return;
181 
182 	DL_FOREACH(control->elements, elem) {
183 		DL_DELETE(control->elements, elem);
184 		free(elem);
185 	}
186 	if (control->name)
187 		free((void *)control->name);
188 	free(control);
189 }
190 
mixer_control_destroy_list(struct mixer_control * control_list)191 static void mixer_control_destroy_list(struct mixer_control *control_list)
192 {
193 	struct mixer_control *control;
194 	if (!control_list)
195 		return;
196 	DL_FOREACH(control_list, control) {
197 		DL_DELETE(control_list, control);
198 		mixer_control_destroy(control);
199 	}
200 }
201 
mixer_control_add_element(struct mixer_control * control,snd_mixer_elem_t * snd_elem)202 static int mixer_control_add_element(struct mixer_control *control,
203 				     snd_mixer_elem_t *snd_elem)
204 {
205 	struct mixer_control_element *elem;
206 
207 	if (!control)
208 		return -EINVAL;
209 
210 	elem = mixer_control_element_create(snd_elem, control->dir);
211 	if (!elem)
212 		return -ENOMEM;
213 
214 	DL_APPEND(control->elements, elem);
215 
216 	if (elem->has_volume) {
217 		if (!control->has_volume)
218 			control->has_volume = 1;
219 
220 		/* Assume that all elements have a common volume range, and
221 		 * that both min and max values are valid if one of the two
222 		 * is valid. */
223 		if (control->min_volume_dB ==
224 		    MIXER_CONTROL_VOLUME_DB_INVALID) {
225 			control->min_volume_dB = elem->min_volume_dB;
226 			control->max_volume_dB = elem->max_volume_dB;
227 		} else if (control->min_volume_dB != elem->min_volume_dB ||
228 			   control->max_volume_dB != elem->max_volume_dB) {
229 			syslog(LOG_WARNING,
230 			    "Element '%s' of control '%s' has different"
231 			    "volume range: [%ld:%ld] ctrl: [%ld:%ld]",
232 			    snd_mixer_selem_get_name(elem->elem),
233 			    control->name,
234 			    elem->min_volume_dB, elem->max_volume_dB,
235 			    control->min_volume_dB, control->max_volume_dB);
236 		}
237 	}
238 
239 	if (elem->has_mute && !control->has_mute)
240 		control->has_mute = 1;
241 	return 0;
242 }
243 
mixer_control_create(struct mixer_control ** control,const char * name,snd_mixer_elem_t * elem,enum CRAS_STREAM_DIRECTION dir)244 static int mixer_control_create(struct mixer_control **control,
245 				const char *name,
246 				snd_mixer_elem_t *elem,
247 				enum CRAS_STREAM_DIRECTION dir)
248 {
249 	struct mixer_control *c;
250 	int rc = 0;
251 
252 	if (!control)
253 		return -EINVAL;
254 
255 	c = (struct mixer_control *)calloc(1, sizeof(*c));
256 	if (!c) {
257 		syslog(LOG_ERR, "No memory for mixer_control: %s", name);
258 		rc = -ENOMEM;
259 		goto error;
260 	}
261 
262 	c->dir = dir;
263 	c->min_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID;
264 	c->max_volume_dB = MIXER_CONTROL_VOLUME_DB_INVALID;
265 
266 	if (!name && elem)
267 		name = snd_mixer_selem_get_name(elem);
268 	if (!name) {
269 		syslog(LOG_ERR, "Control does not have a name.");
270 		rc = -EINVAL;
271 		goto error;
272 	}
273 
274 	c->name = strdup(name);
275 	if (!c->name) {
276 		syslog(LOG_ERR, "No memory for control's name: %s", name);
277 		rc = -ENOMEM;
278 		goto error;
279 	}
280 
281 	if (elem && (rc = mixer_control_add_element(c, elem)))
282 		goto error;
283 
284 	*control = c;
285 	return 0;
286 
287 error:
288 	mixer_control_destroy(c);
289 	*control = NULL;
290 	return rc;
291 }
292 
293 /* Creates a mixer_control by finding mixer element names in simple mixer
294  * interface.
295  * Args:
296  *    control[out] - Storage for resulting pointer to mixer_control.
297  *    cmix[in] - Parent alsa mixer.
298  *    name[in] - Optional name of the control. Input NULL to take the name of
299  *               the first element from mixer_names.
300  *    mixer_names[in] - Names of the ASLA mixer control elements. Must not
301  *                      be empty.
302  *    dir[in] - Control direction: CRAS_STREAM_OUTPUT or CRAS_STREAM_INPUT.
303  * Returns:
304  *    Returns 0 for success, negative error code otherwise. *control is
305  *    initialized to NULL on error, or has a valid pointer for success.
306  */
mixer_control_create_by_name(struct mixer_control ** control,struct cras_alsa_mixer * cmix,const char * name,struct mixer_name * mixer_names,enum CRAS_STREAM_DIRECTION dir)307 static int mixer_control_create_by_name(
308 		struct mixer_control **control,
309 		struct cras_alsa_mixer *cmix,
310 		const char *name,
311 		struct mixer_name *mixer_names,
312 		enum CRAS_STREAM_DIRECTION dir)
313 {
314 	snd_mixer_selem_id_t *sid;
315 	snd_mixer_elem_t *elem;
316 	struct mixer_control *c;
317 	struct mixer_name *m_name;
318 	int rc;
319 
320 	if (!control)
321 		return -EINVAL;
322 	*control = NULL;
323 	if (!mixer_names)
324 		return -EINVAL;
325 	if (!name) {
326 		/* Assume that we're using the first name in the list of mixer
327 		 * names. */
328 		name = mixer_names->name;
329 	}
330 
331 	rc = mixer_control_create(&c, name, NULL, dir);
332 	if (rc)
333 		return rc;
334 
335 	snd_mixer_selem_id_malloc(&sid);
336 
337 	DL_FOREACH(mixer_names, m_name) {
338 		snd_mixer_selem_id_set_index(sid, 0);
339 		snd_mixer_selem_id_set_name(sid, m_name->name);
340 		elem = snd_mixer_find_selem(cmix->mixer, sid);
341 		if (!elem) {
342 			mixer_control_destroy(c);
343 			snd_mixer_selem_id_free(sid);
344 			syslog(LOG_ERR, "Unable to find simple control %s, 0",
345 			       m_name->name);
346 			return -ENOENT;
347 		}
348 		rc = mixer_control_add_element(c, elem);
349 		if (rc) {
350 			mixer_control_destroy(c);
351 			snd_mixer_selem_id_free(sid);
352 			return rc;
353 		}
354 	}
355 
356 	snd_mixer_selem_id_free(sid);
357 	*control = c;
358 	return 0;
359 }
360 
mixer_control_set_dBFS(const struct mixer_control * control,long to_set)361 static int mixer_control_set_dBFS(
362 		const struct mixer_control *control, long to_set)
363 {
364 	const struct mixer_control_element *elem = NULL;
365 	int rc = -EINVAL;
366 	if (!control)
367 		return rc;
368 	DL_FOREACH(control->elements, elem) {
369 		if(elem->has_volume) {
370 			if (control->dir == CRAS_STREAM_OUTPUT)
371 				rc = snd_mixer_selem_set_playback_dB_all(
372 						elem->elem, to_set, 1);
373 			else if (control->dir == CRAS_STREAM_INPUT)
374 				rc = snd_mixer_selem_set_capture_dB_all(
375 						elem->elem, to_set, 1);
376 			if (rc)
377 				break;
378 			syslog(LOG_DEBUG, "%s:%s volume set to %ld",
379 			       control->name,
380 			       snd_mixer_selem_get_name(elem->elem),
381 			       to_set);
382 		}
383 	}
384 	if (rc && elem) {
385 		syslog(LOG_ERR, "Failed to set volume of '%s:%s': %d",
386 		       control->name,
387 		       snd_mixer_selem_get_name(elem->elem), rc);
388 	}
389 	return rc;
390 }
391 
mixer_control_get_dBFS(const struct mixer_control * control,long * to_get)392 static int mixer_control_get_dBFS(
393 		const struct mixer_control *control, long *to_get)
394 {
395 	const struct mixer_control_element *elem = NULL;
396 	int rc = -EINVAL;
397 	if (!control || !to_get)
398 		return -EINVAL;
399 	DL_FOREACH(control->elements, elem) {
400 		if (elem->has_volume) {
401 			if (control->dir == CRAS_STREAM_OUTPUT)
402 				rc = snd_mixer_selem_get_playback_dB(
403 						elem->elem,
404 						SND_MIXER_SCHN_FRONT_LEFT,
405 						to_get);
406 			else if (control->dir == CRAS_STREAM_INPUT)
407 				rc = snd_mixer_selem_get_capture_dB(
408 						elem->elem,
409 						SND_MIXER_SCHN_FRONT_LEFT,
410 						to_get);
411 			/* Assume all of the elements of this control have
412 			 * the same value. */
413 			break;
414 		}
415 	}
416 	if (rc && elem) {
417 		syslog(LOG_ERR, "Failed to get volume of '%s:%s': %d",
418 		       control->name,
419 		       snd_mixer_selem_get_name(elem->elem), rc);
420 	}
421 	return rc;
422 }
423 
mixer_control_set_mute(const struct mixer_control * control,int muted)424 static int mixer_control_set_mute(
425 		const struct mixer_control *control, int muted)
426 {
427 	const struct mixer_control_element *elem = NULL;
428 	int rc;
429 	if (!control)
430 		return -EINVAL;
431 	DL_FOREACH(control->elements, elem) {
432 		if(elem->has_mute) {
433 			if (control->dir == CRAS_STREAM_OUTPUT)
434 				rc = snd_mixer_selem_set_playback_switch_all(
435 					elem->elem, !muted);
436 			else if (control->dir == CRAS_STREAM_INPUT)
437 				rc = snd_mixer_selem_set_capture_switch_all(
438 					elem->elem, !muted);
439 			if (rc)
440 				break;
441 		}
442 	}
443 	if (rc && elem) {
444 		syslog(LOG_ERR, "Failed to mute '%s:%s': %d",
445 		       control->name,
446 		       snd_mixer_selem_get_name(elem->elem), rc);
447 	}
448 	return rc;
449 }
450 
451 /* Adds the main volume control to the list and grabs the first seen playback
452  * switch to use for mute. */
add_main_volume_control(struct cras_alsa_mixer * cmix,snd_mixer_elem_t * elem)453 static int add_main_volume_control(struct cras_alsa_mixer *cmix,
454 				   snd_mixer_elem_t *elem)
455 {
456 	if (snd_mixer_selem_has_playback_volume(elem)) {
457 		long range;
458 		struct mixer_control *c, *next;
459 		int rc = mixer_control_create(&c, NULL, elem, CRAS_STREAM_OUTPUT);
460 		if (rc)
461 			return rc;
462 
463 		if (c->has_volume) {
464 			cmix->max_volume_dB += c->max_volume_dB;
465 			cmix->min_volume_dB += c->min_volume_dB;
466 		}
467 
468 		range = c->max_volume_dB - c->min_volume_dB;
469 		DL_FOREACH(cmix->main_volume_controls, next) {
470 			if (range > next->max_volume_dB - next->min_volume_dB)
471 				break;
472 		}
473 
474 		syslog(LOG_DEBUG, "Add main volume control %s\n", c->name);
475 		DL_INSERT(cmix->main_volume_controls, next, c);
476 	}
477 
478 	/* If cmix doesn't yet have a playback switch and this is a playback
479 	 * switch, use it. */
480 	if (cmix->playback_switch == NULL &&
481 			snd_mixer_selem_has_playback_switch(elem)) {
482 		syslog(LOG_DEBUG, "Using '%s' as playback switch.",
483 		       snd_mixer_selem_get_name(elem));
484 		cmix->playback_switch = elem;
485 	}
486 
487 	return 0;
488 }
489 
490 /* Adds the main capture control to the list and grabs the first seen capture
491  * switch to mute input. */
add_main_capture_control(struct cras_alsa_mixer * cmix,snd_mixer_elem_t * elem)492 static int add_main_capture_control(struct cras_alsa_mixer *cmix,
493 				    snd_mixer_elem_t *elem)
494 {
495 	/* TODO(dgreid) handle index != 0, map to correct input. */
496 	if (snd_mixer_selem_get_index(elem) > 0)
497 		return 0;
498 
499 	if (snd_mixer_selem_has_capture_volume(elem)) {
500 		struct mixer_control *c;
501 		int rc = mixer_control_create(&c, NULL, elem, CRAS_STREAM_INPUT);
502 		if (rc)
503 			return rc;
504 
505 		syslog(LOG_DEBUG, "Add main capture control %s\n", c->name);
506 		DL_APPEND(cmix->main_capture_controls, c);
507 	}
508 
509 	/* If cmix doesn't yet have a capture switch and this is a capture
510 	 * switch, use it. */
511 	if (cmix->capture_switch == NULL &&
512 	    snd_mixer_selem_has_capture_switch(elem)) {
513 		syslog(LOG_DEBUG, "Using '%s' as capture switch.",
514 		       snd_mixer_selem_get_name(elem));
515 		cmix->capture_switch = elem;
516 	}
517 
518 	return 0;
519 }
520 
521 /* Adds a control to the list. */
add_control_with_name(struct cras_alsa_mixer * cmix,enum CRAS_STREAM_DIRECTION dir,snd_mixer_elem_t * elem,const char * name)522 static int add_control_with_name(struct cras_alsa_mixer *cmix,
523 				 enum CRAS_STREAM_DIRECTION dir,
524 				 snd_mixer_elem_t *elem,
525 				 const char *name)
526 {
527 	int index; /* Index part of mixer simple element */
528 	struct mixer_control *c;
529 	int rc;
530 
531 	index = snd_mixer_selem_get_index(elem);
532 	syslog(LOG_DEBUG, "Add %s control: %s,%d\n",
533 	       dir == CRAS_STREAM_OUTPUT ? "output" : "input",
534 	       name, index);
535 
536 	rc = mixer_control_create(&c, name, elem, dir);
537 	if (rc)
538 		return rc;
539 
540 	if (c->has_volume)
541 		syslog(LOG_DEBUG, "Control '%s' volume range: [%ld:%ld]",
542 		       c->name, c->min_volume_dB, c->max_volume_dB);
543 
544 	if (dir == CRAS_STREAM_OUTPUT)
545 		DL_APPEND(cmix->output_controls, c);
546 	else if (dir == CRAS_STREAM_INPUT)
547 		DL_APPEND(cmix->input_controls, c);
548 	return 0;
549 }
550 
add_control(struct cras_alsa_mixer * cmix,enum CRAS_STREAM_DIRECTION dir,snd_mixer_elem_t * elem)551 static int add_control(struct cras_alsa_mixer *cmix,
552 		       enum CRAS_STREAM_DIRECTION dir,
553 		       snd_mixer_elem_t *elem)
554 {
555 	return add_control_with_name(cmix, dir, elem,
556 				     snd_mixer_selem_get_name(elem));
557 }
558 
list_controls(struct mixer_control * control_list,cras_alsa_mixer_control_callback cb,void * cb_arg)559 static void list_controls(struct mixer_control *control_list,
560 			  cras_alsa_mixer_control_callback cb,
561 			  void *cb_arg)
562 {
563 	struct mixer_control *control;
564 
565 	DL_FOREACH(control_list, control)
566 		cb(control, cb_arg);
567 }
568 
get_control_matching_name(struct mixer_control * control_list,const char * name)569 static struct mixer_control *get_control_matching_name(
570 		struct mixer_control *control_list,
571 		const char *name)
572 {
573 	struct mixer_control *c;
574 
575 	DL_FOREACH(control_list, c) {
576 		if (strstr(name, c->name))
577 			return c;
578 	}
579 	return NULL;
580 }
581 
582 /* Creates a mixer_control with multiple control elements. */
add_control_with_coupled_mixers(struct cras_alsa_mixer * cmix,enum CRAS_STREAM_DIRECTION dir,const char * name,struct mixer_name * coupled_controls)583 static int add_control_with_coupled_mixers(
584 				struct cras_alsa_mixer *cmix,
585 				enum CRAS_STREAM_DIRECTION dir,
586 				const char *name,
587 				struct mixer_name *coupled_controls)
588 {
589 	struct mixer_control *c;
590 	int rc;
591 
592 	rc = mixer_control_create_by_name(
593 		 &c, cmix, name, coupled_controls, dir);
594 	if (rc)
595 		return rc;
596 	syslog(LOG_DEBUG, "Add %s control: %s\n",
597 	       dir == CRAS_STREAM_OUTPUT ? "output" : "input",
598 	       c->name);
599 	mixer_name_dump(coupled_controls, "  elements");
600 
601 	if (c->has_volume)
602 		syslog(LOG_DEBUG, "Control '%s' volume range: [%ld:%ld]",
603 		       c->name, c->min_volume_dB, c->max_volume_dB);
604 
605 	if (dir == CRAS_STREAM_OUTPUT)
606 		DL_APPEND(cmix->output_controls, c);
607 	else if (dir == CRAS_STREAM_INPUT)
608 		DL_APPEND(cmix->input_controls, c);
609 	return 0;
610 }
611 
add_control_by_name(struct cras_alsa_mixer * cmix,enum CRAS_STREAM_DIRECTION dir,const char * name)612 static int add_control_by_name(struct cras_alsa_mixer *cmix,
613 			       enum CRAS_STREAM_DIRECTION dir,
614 			       const char *name)
615 {
616 	struct mixer_control *c;
617 	struct mixer_name *m_name;
618 	int rc;
619 
620 	m_name = mixer_name_add(NULL, name, dir, MIXER_NAME_VOLUME);
621 	if (!m_name)
622 		return -ENOMEM;
623 
624 	rc = mixer_control_create_by_name(&c, cmix, name, m_name, dir);
625 	mixer_name_free(m_name);
626 	if (rc)
627 		return rc;
628 	syslog(LOG_DEBUG, "Add %s control: %s\n",
629 	       dir == CRAS_STREAM_OUTPUT ? "output" : "input",
630 	       c->name);
631 
632 	if (c->has_volume)
633 		syslog(LOG_DEBUG, "Control '%s' volume range: [%ld:%ld]",
634 		       c->name, c->min_volume_dB, c->max_volume_dB);
635 
636 	if (dir == CRAS_STREAM_OUTPUT)
637 		DL_APPEND(cmix->output_controls, c);
638 	else if (dir == CRAS_STREAM_INPUT)
639 		DL_APPEND(cmix->input_controls, c);
640 	return 0;
641 }
642 
643 /*
644  * Exported interface.
645  */
646 
cras_alsa_mixer_create(const char * card_name)647 struct cras_alsa_mixer *cras_alsa_mixer_create(const char *card_name)
648 {
649 	struct cras_alsa_mixer *cmix;
650 
651 	cmix = (struct cras_alsa_mixer *)calloc(1, sizeof(*cmix));
652 	if (cmix == NULL)
653 		return NULL;
654 
655 	syslog(LOG_DEBUG, "Add mixer for device %s", card_name);
656 
657 	alsa_mixer_open(card_name, &cmix->mixer);
658 
659 	return cmix;
660 }
661 
cras_alsa_mixer_add_controls_by_name_matching(struct cras_alsa_mixer * cmix,struct mixer_name * extra_controls,struct mixer_name * coupled_controls)662 int cras_alsa_mixer_add_controls_by_name_matching(
663 		struct cras_alsa_mixer *cmix,
664 		struct mixer_name *extra_controls,
665 		struct mixer_name *coupled_controls)
666 {
667 	/* Names of controls for main system volume. */
668 	static const char * const main_volume_names[] = {
669 		"Master",
670 		"Digital",
671 		"PCM",
672 	};
673 	/* Names of controls for individual outputs. */
674 	static const char * const output_names[] = {
675 		"Headphone",
676 		"Headset",
677 		"HDMI",
678 		"Speaker",
679 	};
680 	/* Names of controls for capture gain/attenuation and mute. */
681 	static const char * const main_capture_names[] = {
682 		"Capture",
683 		"Digital Capture",
684 	};
685 	/* Names of controls for individual inputs. */
686 	static const char * const input_names[] = {
687 		"Mic",
688 		"Microphone",
689 	};
690 
691 	struct mixer_name *default_controls = NULL;
692 	snd_mixer_elem_t *elem;
693 	int extra_main_volume = 0;
694 	snd_mixer_elem_t *other_elem = NULL;
695 	long other_dB_range = 0;
696 	int rc = 0;
697 
698 	/* Note that there is no mixer on some cards. This is acceptable. */
699 	if (cmix->mixer == NULL) {
700 		syslog(LOG_DEBUG, "Couldn't open mixer.");
701 		return 0;
702 	}
703 
704 	default_controls = mixer_name_add_array(default_controls,
705 				output_names, ARRAY_SIZE(output_names),
706 				CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME);
707 	default_controls = mixer_name_add_array(default_controls,
708 				input_names, ARRAY_SIZE(input_names),
709 				CRAS_STREAM_INPUT, MIXER_NAME_VOLUME);
710 	default_controls =
711 		mixer_name_add_array(default_controls,
712 			main_volume_names, ARRAY_SIZE(main_volume_names),
713 			CRAS_STREAM_OUTPUT, MIXER_NAME_MAIN_VOLUME);
714 	default_controls =
715 		mixer_name_add_array(default_controls,
716 			main_capture_names, ARRAY_SIZE(main_capture_names),
717 			CRAS_STREAM_INPUT, MIXER_NAME_MAIN_VOLUME);
718 	extra_main_volume =
719 		mixer_name_find(extra_controls, NULL,
720 				CRAS_STREAM_OUTPUT,
721 				MIXER_NAME_MAIN_VOLUME) != NULL;
722 
723 	/* Find volume and mute controls. */
724 	for(elem = snd_mixer_first_elem(cmix->mixer);
725 			elem != NULL; elem = snd_mixer_elem_next(elem)) {
726 		const char *name;
727 		struct mixer_name *control;
728 		int found = 0;
729 
730 		name = snd_mixer_selem_get_name(elem);
731 		if (name == NULL)
732 			continue;
733 
734 		/* Find a matching control. */
735 		control = mixer_name_find(default_controls, name,
736 					  CRAS_STREAM_OUTPUT,
737 					  MIXER_NAME_UNDEFINED);
738 
739 		/* If our extra controls contain a main volume
740 		 * entry, and we found a main volume entry, then
741 		 * skip it. */
742 		if (extra_main_volume &&
743 		    control && control->type == MIXER_NAME_MAIN_VOLUME)
744 			control = NULL;
745 
746 		/* If we didn't match any of the defaults, match
747 		 * the extras list. */
748 		if (!control)
749 			control = mixer_name_find(extra_controls, name,
750 					  CRAS_STREAM_OUTPUT,
751 					  MIXER_NAME_UNDEFINED);
752 
753 		if (control) {
754 			int rc = -1;
755 			switch(control->type) {
756 			case MIXER_NAME_MAIN_VOLUME:
757 				rc = add_main_volume_control(cmix, elem);
758 				break;
759 			case MIXER_NAME_VOLUME:
760 				/* TODO(dgreid) - determine device index. */
761 				rc = add_control(
762 					cmix, CRAS_STREAM_OUTPUT, elem);
763 				break;
764 			case MIXER_NAME_UNDEFINED:
765 				rc = -EINVAL;
766 				break;
767 			}
768 			if (rc) {
769 				syslog(LOG_ERR,
770 				       "Failed to add mixer control '%s'"
771 				       " with type '%d'",
772 				       control->name, control->type);
773 				goto out;
774 			}
775 			found = 1;
776 		}
777 
778 		/* Find a matching input control. */
779 		control = mixer_name_find(default_controls, name,
780 					  CRAS_STREAM_INPUT,
781 					  MIXER_NAME_UNDEFINED);
782 
783 		/* If we didn't match any of the defaults, match
784 		   the extras list */
785 		if (!control)
786 			control = mixer_name_find(extra_controls, name,
787 					  CRAS_STREAM_INPUT,
788 					  MIXER_NAME_UNDEFINED);
789 
790 		if (control) {
791 			int rc = -1;
792 			switch(control->type) {
793 			case MIXER_NAME_MAIN_VOLUME:
794 				rc = add_main_capture_control(cmix, elem);
795 				break;
796 			case MIXER_NAME_VOLUME:
797 				rc = add_control(
798 					cmix, CRAS_STREAM_INPUT, elem);
799 				break;
800 			case MIXER_NAME_UNDEFINED:
801 				rc = -EINVAL;
802 				break;
803 			}
804 			if (rc) {
805 				syslog(LOG_ERR,
806 				       "Failed to add mixer control '%s'"
807 				       " with type '%d'",
808 				       control->name, control->type);
809 				goto out;
810 			}
811 			found = 1;
812 		}
813 
814 		if (!found && snd_mixer_selem_has_playback_volume(elem)) {
815 			/* Temporarily cache one elem whose name is not
816 			 * in the list above, but has a playback volume
817 			 * control and the largest volume range. */
818 			long min, max, range;
819 			if (snd_mixer_selem_get_playback_dB_range(elem,
820 								  &min,
821 								  &max) != 0)
822 				continue;
823 
824 			range = max - min;
825 			if (other_dB_range < range) {
826 				other_dB_range = range;
827 				other_elem = elem;
828 			}
829 		}
830 	}
831 
832 	/* Handle coupled output names for speaker */
833 	if (coupled_controls) {
834 		rc = add_control_with_coupled_mixers(
835 				cmix, CRAS_STREAM_OUTPUT,
836 				"Speaker", coupled_controls);
837 		if (rc) {
838 			syslog(LOG_ERR, "Could not add coupled output");
839 			goto out;
840 		}
841 	}
842 
843 	/* If there is no volume control and output control found,
844 	 * use the volume control which has the largest volume range
845 	 * in the mixer as a main volume control. */
846 	if (!cmix->main_volume_controls && !cmix->output_controls &&
847 	    other_elem) {
848 		rc = add_main_volume_control(cmix, other_elem);
849 		if (rc) {
850 			syslog(LOG_ERR, "Could not add other volume control");
851 			goto out;
852 		}
853 	}
854 
855 out:
856 	mixer_name_free(default_controls);
857 	return rc;
858 }
859 
cras_alsa_mixer_add_controls_in_section(struct cras_alsa_mixer * cmix,struct ucm_section * section)860 int cras_alsa_mixer_add_controls_in_section(
861 		struct cras_alsa_mixer *cmix,
862 		struct ucm_section *section)
863 {
864 	int rc;
865 
866 	/* Note that there is no mixer on some cards. This is acceptable. */
867 	if (cmix->mixer == NULL) {
868 		syslog(LOG_DEBUG, "Couldn't open mixer.");
869 		return 0;
870 	}
871 
872 	if (!section) {
873 		syslog(LOG_ERR, "No UCM SectionDevice specified.");
874 		return -EINVAL;
875 	}
876 
877 	/* TODO(muirj) - Extra main volume controls when fully-specified. */
878 
879 	if (section->mixer_name) {
880 		rc = add_control_by_name(
881 				cmix, section->dir, section->mixer_name);
882 		if (rc) {
883 			syslog(LOG_ERR, "Could not add mixer control '%s': %s",
884 			       section->mixer_name, strerror(-rc));
885 			return rc;
886 		}
887 	}
888 
889 	if (section->coupled) {
890 		rc = add_control_with_coupled_mixers(
891 				cmix, section->dir,
892 				section->name, section->coupled);
893 		if (rc) {
894 			syslog(LOG_ERR, "Could not add coupled control: %s",
895 			       strerror(-rc));
896 			return rc;
897 		}
898 	}
899 	return 0;
900 }
901 
cras_alsa_mixer_destroy(struct cras_alsa_mixer * cras_mixer)902 void cras_alsa_mixer_destroy(struct cras_alsa_mixer *cras_mixer)
903 {
904 	assert(cras_mixer);
905 
906 	mixer_control_destroy_list(cras_mixer->main_volume_controls);
907 	mixer_control_destroy_list(cras_mixer->main_capture_controls);
908 	mixer_control_destroy_list(cras_mixer->output_controls);
909 	mixer_control_destroy_list(cras_mixer->input_controls);
910 	if (cras_mixer->mixer)
911 		snd_mixer_close(cras_mixer->mixer);
912 	free(cras_mixer);
913 }
914 
cras_alsa_mixer_has_main_volume(const struct cras_alsa_mixer * cras_mixer)915 int cras_alsa_mixer_has_main_volume(
916 		const struct cras_alsa_mixer *cras_mixer)
917 {
918 	return !!cras_mixer->main_volume_controls;
919 }
920 
cras_alsa_mixer_has_volume(const struct mixer_control * mixer_control)921 int cras_alsa_mixer_has_volume(const struct mixer_control *mixer_control)
922 {
923 	return mixer_control && mixer_control->has_volume;
924 }
925 
cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer * cras_mixer,long dBFS,struct mixer_control * mixer_output)926 void cras_alsa_mixer_set_dBFS(struct cras_alsa_mixer *cras_mixer,
927 			      long dBFS,
928 			      struct mixer_control *mixer_output)
929 {
930 	struct mixer_control *c;
931 	long to_set;
932 
933 	assert(cras_mixer);
934 
935 	/* dBFS is normally < 0 to specify the attenuation from max. max is the
936 	 * combined max of the master controls and the current output.
937 	 */
938 	to_set = dBFS + cras_mixer->max_volume_dB;
939 	if (cras_alsa_mixer_has_volume(mixer_output))
940 		to_set += mixer_output->max_volume_dB;
941 	/* Go through all the controls, set the volume level for each,
942 	 * taking the value closest but greater than the desired volume.  If the
943 	 * entire volume can't be set on the current control, move on to the
944 	 * next one until we have the exact volume, or gotten as close as we
945 	 * can. Once all of the volume is set the rest of the controls should be
946 	 * set to 0dB. */
947 	DL_FOREACH(cras_mixer->main_volume_controls, c) {
948 		long actual_dB;
949 
950 		if (!c->has_volume)
951 			continue;
952 		mixer_control_set_dBFS(c, to_set);
953 		mixer_control_get_dBFS(c, &actual_dB);
954 		to_set -= actual_dB;
955 	}
956 	/* Apply the rest to the output-specific control. */
957 	if (cras_alsa_mixer_has_volume(mixer_output))
958 		mixer_control_set_dBFS(mixer_output, to_set);
959 }
960 
cras_alsa_mixer_get_dB_range(struct cras_alsa_mixer * cras_mixer)961 long cras_alsa_mixer_get_dB_range(struct cras_alsa_mixer *cras_mixer)
962 {
963 	if (!cras_mixer)
964 		return 0;
965 	return cras_mixer->max_volume_dB - cras_mixer->min_volume_dB;
966 }
967 
cras_alsa_mixer_get_output_dB_range(struct mixer_control * mixer_output)968 long cras_alsa_mixer_get_output_dB_range(
969 		struct mixer_control *mixer_output)
970 {
971 	if (!cras_alsa_mixer_has_volume(mixer_output))
972 		return 0;
973 
974 	return mixer_output->max_volume_dB - mixer_output->min_volume_dB;
975 }
976 
cras_alsa_mixer_set_capture_dBFS(struct cras_alsa_mixer * cras_mixer,long dBFS,struct mixer_control * mixer_input)977 void cras_alsa_mixer_set_capture_dBFS(struct cras_alsa_mixer *cras_mixer,
978 				      long dBFS,
979 				      struct mixer_control *mixer_input)
980 {
981 	struct mixer_control *c;
982 	long to_set;
983 
984 	assert(cras_mixer);
985 	to_set = dBFS;
986 	/* Go through all the controls, set the gain for each, taking the value
987 	 * closest but greater than the desired gain.  If the entire gain can't
988 	 * be set on the current control, move on to the next one until we have
989 	 * the exact gain, or gotten as close as we can. Once all of the gain is
990 	 * set the rest of the controls should be set to 0dB. */
991 	DL_FOREACH(cras_mixer->main_capture_controls, c) {
992 		long actual_dB;
993 
994 		if (!c->has_volume)
995 			continue;
996 		mixer_control_set_dBFS(c, to_set);
997 		mixer_control_get_dBFS(c, &actual_dB);
998 		to_set -= actual_dB;
999 	}
1000 
1001 	/* Apply the reset to input specific control */
1002 	if (cras_alsa_mixer_has_volume(mixer_input))
1003 		mixer_control_set_dBFS(mixer_input, to_set);
1004 }
1005 
cras_alsa_mixer_get_minimum_capture_gain(struct cras_alsa_mixer * cmix,struct mixer_control * mixer_input)1006 long cras_alsa_mixer_get_minimum_capture_gain(
1007                 struct cras_alsa_mixer *cmix,
1008 		struct mixer_control *mixer_input)
1009 {
1010 	struct mixer_control *c;
1011 	long total_min = 0;
1012 
1013 	assert(cmix);
1014 	DL_FOREACH(cmix->main_capture_controls, c)
1015 		if (c->has_volume)
1016 			total_min += c->min_volume_dB;
1017 	if (mixer_input &&
1018 	    mixer_input->has_volume)
1019 		total_min += mixer_input->min_volume_dB;
1020 
1021 	return total_min;
1022 }
1023 
cras_alsa_mixer_get_maximum_capture_gain(struct cras_alsa_mixer * cmix,struct mixer_control * mixer_input)1024 long cras_alsa_mixer_get_maximum_capture_gain(
1025 		struct cras_alsa_mixer *cmix,
1026 		struct mixer_control *mixer_input)
1027 {
1028 	struct mixer_control *c;
1029 	long total_max = 0;
1030 
1031 	assert(cmix);
1032 	DL_FOREACH(cmix->main_capture_controls, c)
1033 		if (c->has_volume)
1034 			total_max += c->max_volume_dB;
1035 
1036 	if (mixer_input &&
1037 	    mixer_input->has_volume)
1038 		total_max += mixer_input->max_volume_dB;
1039 
1040 	return total_max;
1041 }
1042 
cras_alsa_mixer_set_mute(struct cras_alsa_mixer * cras_mixer,int muted,struct mixer_control * mixer_output)1043 void cras_alsa_mixer_set_mute(struct cras_alsa_mixer *cras_mixer,
1044 			      int muted,
1045 			      struct mixer_control *mixer_output)
1046 {
1047 	assert(cras_mixer);
1048 
1049 	if (cras_mixer->playback_switch) {
1050 		snd_mixer_selem_set_playback_switch_all(
1051 				cras_mixer->playback_switch, !muted);
1052 	}
1053 	if (mixer_output && mixer_output->has_mute) {
1054 		mixer_control_set_mute(mixer_output, muted);
1055 	}
1056 }
1057 
cras_alsa_mixer_set_capture_mute(struct cras_alsa_mixer * cras_mixer,int muted,struct mixer_control * mixer_input)1058 void cras_alsa_mixer_set_capture_mute(struct cras_alsa_mixer *cras_mixer,
1059 				      int muted,
1060 				      struct mixer_control *mixer_input)
1061 {
1062 	assert(cras_mixer);
1063 	if (cras_mixer->capture_switch) {
1064 		snd_mixer_selem_set_capture_switch_all(
1065 				cras_mixer->capture_switch, !muted);
1066 		return;
1067 	}
1068 	if (mixer_input && mixer_input->has_mute)
1069 		mixer_control_set_mute(mixer_input, muted);
1070 }
1071 
cras_alsa_mixer_list_outputs(struct cras_alsa_mixer * cras_mixer,cras_alsa_mixer_control_callback cb,void * cb_arg)1072 void cras_alsa_mixer_list_outputs(struct cras_alsa_mixer *cras_mixer,
1073 				  cras_alsa_mixer_control_callback cb,
1074 				  void *cb_arg)
1075 {
1076 	assert(cras_mixer);
1077 	list_controls(cras_mixer->output_controls, cb, cb_arg);
1078 }
1079 
cras_alsa_mixer_list_inputs(struct cras_alsa_mixer * cras_mixer,cras_alsa_mixer_control_callback cb,void * cb_arg)1080 void cras_alsa_mixer_list_inputs(struct cras_alsa_mixer *cras_mixer,
1081 				 cras_alsa_mixer_control_callback cb,
1082 				 void *cb_arg)
1083 {
1084 	assert(cras_mixer);
1085 	list_controls(cras_mixer->input_controls, cb, cb_arg);
1086 }
1087 
cras_alsa_mixer_get_control_name(const struct mixer_control * control)1088 const char *cras_alsa_mixer_get_control_name(
1089 		const struct mixer_control *control)
1090 {
1091 	if (!control)
1092 		return NULL;
1093 	return control->name;
1094 }
1095 
cras_alsa_mixer_get_control_matching_name(struct cras_alsa_mixer * cras_mixer,enum CRAS_STREAM_DIRECTION dir,const char * name,int create_missing)1096 struct mixer_control *cras_alsa_mixer_get_control_matching_name(
1097 		struct cras_alsa_mixer *cras_mixer,
1098 		enum CRAS_STREAM_DIRECTION dir, const char *name,
1099 		int create_missing)
1100 {
1101 	struct mixer_control *c;
1102 
1103 	assert(cras_mixer);
1104 	if (!name)
1105 		return NULL;
1106 
1107 	if (dir == CRAS_STREAM_OUTPUT) {
1108 		c = get_control_matching_name(
1109 				cras_mixer->output_controls, name);
1110 	} else if (dir == CRAS_STREAM_INPUT) {
1111 		c = get_control_matching_name(
1112 				cras_mixer->input_controls, name);
1113 	} else {
1114 		return NULL;
1115         }
1116 
1117 	/* TODO: Allowing creation of a new control is a workaround: we
1118 	 * should pass the input names in ucm config to
1119 	 * cras_alsa_mixer_create. */
1120 	if (!c && cras_mixer->mixer && create_missing) {
1121 		int rc = add_control_by_name(cras_mixer, dir, name);
1122 		if (rc)
1123 			return NULL;
1124 		c = cras_alsa_mixer_get_control_matching_name(
1125 				cras_mixer, dir, name, 0);
1126 	}
1127 	return c;
1128 }
1129 
cras_alsa_mixer_get_control_for_section(struct cras_alsa_mixer * cras_mixer,const struct ucm_section * section)1130 struct mixer_control *cras_alsa_mixer_get_control_for_section(
1131 		struct cras_alsa_mixer *cras_mixer,
1132 		const struct ucm_section *section)
1133 {
1134 	assert(cras_mixer && section);
1135 	if (section->mixer_name) {
1136 		return cras_alsa_mixer_get_control_matching_name(
1137 			   cras_mixer, section->dir, section->mixer_name, 0);
1138 	} else if (section->coupled) {
1139 		return cras_alsa_mixer_get_control_matching_name(
1140 			   cras_mixer, section->dir, section->name, 0);
1141 	}
1142 	return NULL;
1143 }
1144 
cras_alsa_mixer_get_output_matching_name(struct cras_alsa_mixer * cras_mixer,const char * const name)1145 struct mixer_control *cras_alsa_mixer_get_output_matching_name(
1146 		struct cras_alsa_mixer *cras_mixer,
1147 		const char * const name)
1148 {
1149 	return cras_alsa_mixer_get_control_matching_name(
1150 			cras_mixer, CRAS_STREAM_OUTPUT, name, 0);
1151 }
1152 
cras_alsa_mixer_get_input_matching_name(struct cras_alsa_mixer * cras_mixer,const char * name)1153 struct mixer_control *cras_alsa_mixer_get_input_matching_name(
1154 		struct cras_alsa_mixer *cras_mixer,
1155 		const char *name)
1156 {
1157 	/* TODO: Allowing creation of a new control is a workaround: we
1158 	 * should pass the input names in ucm config to
1159 	 * cras_alsa_mixer_create. */
1160 	return cras_alsa_mixer_get_control_matching_name(
1161 			cras_mixer, CRAS_STREAM_INPUT, name, 1);
1162 }
1163 
cras_alsa_mixer_set_output_active_state(struct mixer_control * output,int active)1164 int cras_alsa_mixer_set_output_active_state(
1165 		struct mixer_control *output,
1166 		int active)
1167 {
1168 	assert(output);
1169 	if (!output->has_mute)
1170 		return -1;
1171 	return mixer_control_set_mute(output, !active);
1172 }
1173