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