Linux 2.6.31.8
[linux/fpc-iii.git] / sound / soc / soc-dapm.c
blob4aba33fa6b70b543fdf2cb43168804bd64190469
1 /*
2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
12 * Features:
13 * o Changes power status of internal codec blocks depending on the
14 * dynamic configuration of codec internal audio paths and active
15 * DACs/ADCs.
16 * o Platform power domain - can support external components i.e. amps and
17 * mic/meadphone insertion events.
18 * o Automatic Mic Bias support
19 * o Jack insertion power event initiation - e.g. hp insertion will enable
20 * sinks, dacs, etc
21 * o Delayed powerdown of audio susbsystem to reduce pops between a quick
22 * device reopen.
24 * Todo:
25 * o DAPM power change sequencing - allow for configurable per
26 * codec sequences.
27 * o Support for analogue bias optimisation.
28 * o Support for reduced codec oversampling rates.
29 * o Support for reduced codec bias currents.
32 #include <linux/module.h>
33 #include <linux/moduleparam.h>
34 #include <linux/init.h>
35 #include <linux/delay.h>
36 #include <linux/pm.h>
37 #include <linux/bitops.h>
38 #include <linux/platform_device.h>
39 #include <linux/jiffies.h>
40 #include <sound/core.h>
41 #include <sound/pcm.h>
42 #include <sound/pcm_params.h>
43 #include <sound/soc-dapm.h>
44 #include <sound/initval.h>
46 /* debug */
47 #ifdef DEBUG
48 #define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
49 #else
50 #define dump_dapm(codec, action)
51 #endif
53 /* dapm power sequences - make this per codec in the future */
54 static int dapm_up_seq[] = {
55 snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias,
56 snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
57 snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
58 snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
59 snd_soc_dapm_post
62 static int dapm_down_seq[] = {
63 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
64 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
65 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
66 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
67 snd_soc_dapm_post
70 static void pop_wait(u32 pop_time)
72 if (pop_time)
73 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
76 static void pop_dbg(u32 pop_time, const char *fmt, ...)
78 va_list args;
80 va_start(args, fmt);
82 if (pop_time) {
83 vprintk(fmt, args);
84 pop_wait(pop_time);
87 va_end(args);
90 /* create a new dapm widget */
91 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
92 const struct snd_soc_dapm_widget *_widget)
94 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
97 /**
98 * snd_soc_dapm_set_bias_level - set the bias level for the system
99 * @socdev: audio device
100 * @level: level to configure
102 * Configure the bias (power) levels for the SoC audio device.
104 * Returns 0 for success else error.
106 static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
107 enum snd_soc_bias_level level)
109 struct snd_soc_card *card = socdev->card;
110 struct snd_soc_codec *codec = socdev->card->codec;
111 int ret = 0;
113 switch (level) {
114 case SND_SOC_BIAS_ON:
115 dev_dbg(socdev->dev, "Setting full bias\n");
116 break;
117 case SND_SOC_BIAS_PREPARE:
118 dev_dbg(socdev->dev, "Setting bias prepare\n");
119 break;
120 case SND_SOC_BIAS_STANDBY:
121 dev_dbg(socdev->dev, "Setting standby bias\n");
122 break;
123 case SND_SOC_BIAS_OFF:
124 dev_dbg(socdev->dev, "Setting bias off\n");
125 break;
126 default:
127 dev_err(socdev->dev, "Setting invalid bias %d\n", level);
128 return -EINVAL;
131 if (card->set_bias_level)
132 ret = card->set_bias_level(card, level);
133 if (ret == 0 && codec->set_bias_level)
134 ret = codec->set_bias_level(codec, level);
136 return ret;
139 /* set up initial codec paths */
140 static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
141 struct snd_soc_dapm_path *p, int i)
143 switch (w->id) {
144 case snd_soc_dapm_switch:
145 case snd_soc_dapm_mixer:
146 case snd_soc_dapm_mixer_named_ctl: {
147 int val;
148 struct soc_mixer_control *mc = (struct soc_mixer_control *)
149 w->kcontrols[i].private_value;
150 unsigned int reg = mc->reg;
151 unsigned int shift = mc->shift;
152 int max = mc->max;
153 unsigned int mask = (1 << fls(max)) - 1;
154 unsigned int invert = mc->invert;
156 val = snd_soc_read(w->codec, reg);
157 val = (val >> shift) & mask;
159 if ((invert && !val) || (!invert && val))
160 p->connect = 1;
161 else
162 p->connect = 0;
164 break;
165 case snd_soc_dapm_mux: {
166 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
167 int val, item, bitmask;
169 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
171 val = snd_soc_read(w->codec, e->reg);
172 item = (val >> e->shift_l) & (bitmask - 1);
174 p->connect = 0;
175 for (i = 0; i < e->max; i++) {
176 if (!(strcmp(p->name, e->texts[i])) && item == i)
177 p->connect = 1;
180 break;
181 case snd_soc_dapm_value_mux: {
182 struct soc_enum *e = (struct soc_enum *)
183 w->kcontrols[i].private_value;
184 int val, item;
186 val = snd_soc_read(w->codec, e->reg);
187 val = (val >> e->shift_l) & e->mask;
188 for (item = 0; item < e->max; item++) {
189 if (val == e->values[item])
190 break;
193 p->connect = 0;
194 for (i = 0; i < e->max; i++) {
195 if (!(strcmp(p->name, e->texts[i])) && item == i)
196 p->connect = 1;
199 break;
200 /* does not effect routing - always connected */
201 case snd_soc_dapm_pga:
202 case snd_soc_dapm_output:
203 case snd_soc_dapm_adc:
204 case snd_soc_dapm_input:
205 case snd_soc_dapm_dac:
206 case snd_soc_dapm_micbias:
207 case snd_soc_dapm_vmid:
208 case snd_soc_dapm_supply:
209 p->connect = 1;
210 break;
211 /* does effect routing - dynamically connected */
212 case snd_soc_dapm_hp:
213 case snd_soc_dapm_mic:
214 case snd_soc_dapm_spk:
215 case snd_soc_dapm_line:
216 case snd_soc_dapm_pre:
217 case snd_soc_dapm_post:
218 p->connect = 0;
219 break;
223 /* connect mux widget to its interconnecting audio paths */
224 static int dapm_connect_mux(struct snd_soc_codec *codec,
225 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
226 struct snd_soc_dapm_path *path, const char *control_name,
227 const struct snd_kcontrol_new *kcontrol)
229 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
230 int i;
232 for (i = 0; i < e->max; i++) {
233 if (!(strcmp(control_name, e->texts[i]))) {
234 list_add(&path->list, &codec->dapm_paths);
235 list_add(&path->list_sink, &dest->sources);
236 list_add(&path->list_source, &src->sinks);
237 path->name = (char*)e->texts[i];
238 dapm_set_path_status(dest, path, 0);
239 return 0;
243 return -ENODEV;
246 /* connect mixer widget to its interconnecting audio paths */
247 static int dapm_connect_mixer(struct snd_soc_codec *codec,
248 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
249 struct snd_soc_dapm_path *path, const char *control_name)
251 int i;
253 /* search for mixer kcontrol */
254 for (i = 0; i < dest->num_kcontrols; i++) {
255 if (!strcmp(control_name, dest->kcontrols[i].name)) {
256 list_add(&path->list, &codec->dapm_paths);
257 list_add(&path->list_sink, &dest->sources);
258 list_add(&path->list_source, &src->sinks);
259 path->name = dest->kcontrols[i].name;
260 dapm_set_path_status(dest, path, i);
261 return 0;
264 return -ENODEV;
267 /* update dapm codec register bits */
268 static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
270 int change, power;
271 unsigned short old, new;
272 struct snd_soc_codec *codec = widget->codec;
274 /* check for valid widgets */
275 if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
276 widget->id == snd_soc_dapm_output ||
277 widget->id == snd_soc_dapm_hp ||
278 widget->id == snd_soc_dapm_mic ||
279 widget->id == snd_soc_dapm_line ||
280 widget->id == snd_soc_dapm_spk)
281 return 0;
283 power = widget->power;
284 if (widget->invert)
285 power = (power ? 0:1);
287 old = snd_soc_read(codec, widget->reg);
288 new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
290 change = old != new;
291 if (change) {
292 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
293 widget->name, widget->power ? "on" : "off",
294 codec->pop_time);
295 snd_soc_write(codec, widget->reg, new);
296 pop_wait(codec->pop_time);
298 pr_debug("reg %x old %x new %x change %d\n", widget->reg,
299 old, new, change);
300 return change;
303 /* ramps the volume up or down to minimise pops before or after a
304 * DAPM power event */
305 static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
307 const struct snd_kcontrol_new *k = widget->kcontrols;
309 if (widget->muted && !power)
310 return 0;
311 if (!widget->muted && power)
312 return 0;
314 if (widget->num_kcontrols && k) {
315 struct soc_mixer_control *mc =
316 (struct soc_mixer_control *)k->private_value;
317 unsigned int reg = mc->reg;
318 unsigned int shift = mc->shift;
319 int max = mc->max;
320 unsigned int mask = (1 << fls(max)) - 1;
321 unsigned int invert = mc->invert;
323 if (power) {
324 int i;
325 /* power up has happended, increase volume to last level */
326 if (invert) {
327 for (i = max; i > widget->saved_value; i--)
328 snd_soc_update_bits(widget->codec, reg, mask, i);
329 } else {
330 for (i = 0; i < widget->saved_value; i++)
331 snd_soc_update_bits(widget->codec, reg, mask, i);
333 widget->muted = 0;
334 } else {
335 /* power down is about to occur, decrease volume to mute */
336 int val = snd_soc_read(widget->codec, reg);
337 int i = widget->saved_value = (val >> shift) & mask;
338 if (invert) {
339 for (; i < mask; i++)
340 snd_soc_update_bits(widget->codec, reg, mask, i);
341 } else {
342 for (; i > 0; i--)
343 snd_soc_update_bits(widget->codec, reg, mask, i);
345 widget->muted = 1;
348 return 0;
351 /* create new dapm mixer control */
352 static int dapm_new_mixer(struct snd_soc_codec *codec,
353 struct snd_soc_dapm_widget *w)
355 int i, ret = 0;
356 size_t name_len;
357 struct snd_soc_dapm_path *path;
359 /* add kcontrol */
360 for (i = 0; i < w->num_kcontrols; i++) {
362 /* match name */
363 list_for_each_entry(path, &w->sources, list_sink) {
365 /* mixer/mux paths name must match control name */
366 if (path->name != (char*)w->kcontrols[i].name)
367 continue;
369 /* add dapm control with long name.
370 * for dapm_mixer this is the concatenation of the
371 * mixer and kcontrol name.
372 * for dapm_mixer_named_ctl this is simply the
373 * kcontrol name.
375 name_len = strlen(w->kcontrols[i].name) + 1;
376 if (w->id != snd_soc_dapm_mixer_named_ctl)
377 name_len += 1 + strlen(w->name);
379 path->long_name = kmalloc(name_len, GFP_KERNEL);
381 if (path->long_name == NULL)
382 return -ENOMEM;
384 switch (w->id) {
385 default:
386 snprintf(path->long_name, name_len, "%s %s",
387 w->name, w->kcontrols[i].name);
388 break;
389 case snd_soc_dapm_mixer_named_ctl:
390 snprintf(path->long_name, name_len, "%s",
391 w->kcontrols[i].name);
392 break;
395 path->long_name[name_len - 1] = '\0';
397 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
398 path->long_name);
399 ret = snd_ctl_add(codec->card, path->kcontrol);
400 if (ret < 0) {
401 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
402 path->long_name,
403 ret);
404 kfree(path->long_name);
405 path->long_name = NULL;
406 return ret;
410 return ret;
413 /* create new dapm mux control */
414 static int dapm_new_mux(struct snd_soc_codec *codec,
415 struct snd_soc_dapm_widget *w)
417 struct snd_soc_dapm_path *path = NULL;
418 struct snd_kcontrol *kcontrol;
419 int ret = 0;
421 if (!w->num_kcontrols) {
422 printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
423 return -EINVAL;
426 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
427 ret = snd_ctl_add(codec->card, kcontrol);
428 if (ret < 0)
429 goto err;
431 list_for_each_entry(path, &w->sources, list_sink)
432 path->kcontrol = kcontrol;
434 return ret;
436 err:
437 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
438 return ret;
441 /* create new dapm volume control */
442 static int dapm_new_pga(struct snd_soc_codec *codec,
443 struct snd_soc_dapm_widget *w)
445 struct snd_kcontrol *kcontrol;
446 int ret = 0;
448 if (!w->num_kcontrols)
449 return -EINVAL;
451 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
452 ret = snd_ctl_add(codec->card, kcontrol);
453 if (ret < 0) {
454 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
455 return ret;
458 return ret;
461 /* reset 'walked' bit for each dapm path */
462 static inline void dapm_clear_walk(struct snd_soc_codec *codec)
464 struct snd_soc_dapm_path *p;
466 list_for_each_entry(p, &codec->dapm_paths, list)
467 p->walked = 0;
471 * Recursively check for a completed path to an active or physically connected
472 * output widget. Returns number of complete paths.
474 static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
476 struct snd_soc_dapm_path *path;
477 int con = 0;
479 if (widget->id == snd_soc_dapm_supply)
480 return 0;
482 if (widget->id == snd_soc_dapm_adc && widget->active)
483 return 1;
485 if (widget->connected) {
486 /* connected pin ? */
487 if (widget->id == snd_soc_dapm_output && !widget->ext)
488 return 1;
490 /* connected jack or spk ? */
491 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
492 widget->id == snd_soc_dapm_line)
493 return 1;
496 list_for_each_entry(path, &widget->sinks, list_source) {
497 if (path->walked)
498 continue;
500 if (path->sink && path->connect) {
501 path->walked = 1;
502 con += is_connected_output_ep(path->sink);
506 return con;
510 * Recursively check for a completed path to an active or physically connected
511 * input widget. Returns number of complete paths.
513 static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
515 struct snd_soc_dapm_path *path;
516 int con = 0;
518 if (widget->id == snd_soc_dapm_supply)
519 return 0;
521 /* active stream ? */
522 if (widget->id == snd_soc_dapm_dac && widget->active)
523 return 1;
525 if (widget->connected) {
526 /* connected pin ? */
527 if (widget->id == snd_soc_dapm_input && !widget->ext)
528 return 1;
530 /* connected VMID/Bias for lower pops */
531 if (widget->id == snd_soc_dapm_vmid)
532 return 1;
534 /* connected jack ? */
535 if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
536 return 1;
539 list_for_each_entry(path, &widget->sources, list_sink) {
540 if (path->walked)
541 continue;
543 if (path->source && path->connect) {
544 path->walked = 1;
545 con += is_connected_input_ep(path->source);
549 return con;
553 * Handler for generic register modifier widget.
555 int dapm_reg_event(struct snd_soc_dapm_widget *w,
556 struct snd_kcontrol *kcontrol, int event)
558 unsigned int val;
560 if (SND_SOC_DAPM_EVENT_ON(event))
561 val = w->on_val;
562 else
563 val = w->off_val;
565 snd_soc_update_bits(w->codec, -(w->reg + 1),
566 w->mask << w->shift, val << w->shift);
568 return 0;
570 EXPORT_SYMBOL_GPL(dapm_reg_event);
572 /* Standard power change method, used to apply power changes to most
573 * widgets.
575 static int dapm_generic_apply_power(struct snd_soc_dapm_widget *w)
577 int ret;
579 /* call any power change event handlers */
580 if (w->event)
581 pr_debug("power %s event for %s flags %x\n",
582 w->power ? "on" : "off",
583 w->name, w->event_flags);
585 /* power up pre event */
586 if (w->power && w->event &&
587 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
588 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
589 if (ret < 0)
590 return ret;
593 /* power down pre event */
594 if (!w->power && w->event &&
595 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
596 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
597 if (ret < 0)
598 return ret;
601 /* Lower PGA volume to reduce pops */
602 if (w->id == snd_soc_dapm_pga && !w->power)
603 dapm_set_pga(w, w->power);
605 dapm_update_bits(w);
607 /* Raise PGA volume to reduce pops */
608 if (w->id == snd_soc_dapm_pga && w->power)
609 dapm_set_pga(w, w->power);
611 /* power up post event */
612 if (w->power && w->event &&
613 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
614 ret = w->event(w,
615 NULL, SND_SOC_DAPM_POST_PMU);
616 if (ret < 0)
617 return ret;
620 /* power down post event */
621 if (!w->power && w->event &&
622 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
623 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
624 if (ret < 0)
625 return ret;
628 return 0;
631 /* Generic check to see if a widget should be powered.
633 static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
635 int in, out;
637 in = is_connected_input_ep(w);
638 dapm_clear_walk(w->codec);
639 out = is_connected_output_ep(w);
640 dapm_clear_walk(w->codec);
641 return out != 0 && in != 0;
644 /* Check to see if an ADC has power */
645 static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
647 int in;
649 if (w->active) {
650 in = is_connected_input_ep(w);
651 dapm_clear_walk(w->codec);
652 return in != 0;
653 } else {
654 return dapm_generic_check_power(w);
658 /* Check to see if a DAC has power */
659 static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
661 int out;
663 if (w->active) {
664 out = is_connected_output_ep(w);
665 dapm_clear_walk(w->codec);
666 return out != 0;
667 } else {
668 return dapm_generic_check_power(w);
672 /* Check to see if a power supply is needed */
673 static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
675 struct snd_soc_dapm_path *path;
676 int power = 0;
678 /* Check if one of our outputs is connected */
679 list_for_each_entry(path, &w->sinks, list_source) {
680 if (path->sink && path->sink->power_check &&
681 path->sink->power_check(path->sink)) {
682 power = 1;
683 break;
687 dapm_clear_walk(w->codec);
689 return power;
693 * Scan a single DAPM widget for a complete audio path and update the
694 * power status appropriately.
696 static int dapm_power_widget(struct snd_soc_codec *codec, int event,
697 struct snd_soc_dapm_widget *w)
699 int ret;
701 switch (w->id) {
702 case snd_soc_dapm_pre:
703 if (!w->event)
704 return 0;
706 if (event == SND_SOC_DAPM_STREAM_START) {
707 ret = w->event(w,
708 NULL, SND_SOC_DAPM_PRE_PMU);
709 if (ret < 0)
710 return ret;
711 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
712 ret = w->event(w,
713 NULL, SND_SOC_DAPM_PRE_PMD);
714 if (ret < 0)
715 return ret;
717 return 0;
719 case snd_soc_dapm_post:
720 if (!w->event)
721 return 0;
723 if (event == SND_SOC_DAPM_STREAM_START) {
724 ret = w->event(w,
725 NULL, SND_SOC_DAPM_POST_PMU);
726 if (ret < 0)
727 return ret;
728 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
729 ret = w->event(w,
730 NULL, SND_SOC_DAPM_POST_PMD);
731 if (ret < 0)
732 return ret;
734 return 0;
736 default:
737 return dapm_generic_apply_power(w);
742 * Scan each dapm widget for complete audio path.
743 * A complete path is a route that has valid endpoints i.e.:-
745 * o DAC to output pin.
746 * o Input Pin to ADC.
747 * o Input pin to Output pin (bypass, sidetone)
748 * o DAC to ADC (loopback).
750 static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
752 struct snd_soc_device *socdev = codec->socdev;
753 struct snd_soc_dapm_widget *w;
754 int ret = 0;
755 int i, power;
756 int sys_power = 0;
758 INIT_LIST_HEAD(&codec->up_list);
759 INIT_LIST_HEAD(&codec->down_list);
761 /* Check which widgets we need to power and store them in
762 * lists indicating if they should be powered up or down.
764 list_for_each_entry(w, &codec->dapm_widgets, list) {
765 switch (w->id) {
766 case snd_soc_dapm_pre:
767 list_add_tail(&codec->down_list, &w->power_list);
768 break;
769 case snd_soc_dapm_post:
770 list_add_tail(&codec->up_list, &w->power_list);
771 break;
773 default:
774 if (!w->power_check)
775 continue;
777 /* If we're suspending then pull down all the
778 * power. */
779 switch (event) {
780 case SND_SOC_DAPM_STREAM_SUSPEND:
781 power = 0;
782 break;
784 default:
785 power = w->power_check(w);
786 if (power)
787 sys_power = 1;
788 break;
791 if (w->power == power)
792 continue;
794 if (power)
795 list_add_tail(&w->power_list, &codec->up_list);
796 else
797 list_add_tail(&w->power_list,
798 &codec->down_list);
800 w->power = power;
801 break;
805 /* If we're changing to all on or all off then prepare */
806 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
807 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
808 ret = snd_soc_dapm_set_bias_level(socdev,
809 SND_SOC_BIAS_PREPARE);
810 if (ret != 0)
811 pr_err("Failed to prepare bias: %d\n", ret);
814 /* Power down widgets first; try to avoid amplifying pops. */
815 for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) {
816 list_for_each_entry(w, &codec->down_list, power_list) {
817 /* is widget in stream order */
818 if (w->id != dapm_down_seq[i])
819 continue;
821 ret = dapm_power_widget(codec, event, w);
822 if (ret != 0)
823 pr_err("Failed to power down %s: %d\n",
824 w->name, ret);
828 /* Now power up. */
829 for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) {
830 list_for_each_entry(w, &codec->up_list, power_list) {
831 /* is widget in stream order */
832 if (w->id != dapm_up_seq[i])
833 continue;
835 ret = dapm_power_widget(codec, event, w);
836 if (ret != 0)
837 pr_err("Failed to power up %s: %d\n",
838 w->name, ret);
842 /* If we just powered the last thing off drop to standby bias */
843 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
844 ret = snd_soc_dapm_set_bias_level(socdev,
845 SND_SOC_BIAS_STANDBY);
846 if (ret != 0)
847 pr_err("Failed to apply standby bias: %d\n", ret);
850 /* If we just powered up then move to active bias */
851 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
852 ret = snd_soc_dapm_set_bias_level(socdev,
853 SND_SOC_BIAS_ON);
854 if (ret != 0)
855 pr_err("Failed to apply active bias: %d\n", ret);
858 return 0;
861 #ifdef DEBUG
862 static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
864 struct snd_soc_dapm_widget *w;
865 struct snd_soc_dapm_path *p = NULL;
866 int in, out;
868 printk("DAPM %s %s\n", codec->name, action);
870 list_for_each_entry(w, &codec->dapm_widgets, list) {
872 /* only display widgets that effect routing */
873 switch (w->id) {
874 case snd_soc_dapm_pre:
875 case snd_soc_dapm_post:
876 case snd_soc_dapm_vmid:
877 continue;
878 case snd_soc_dapm_mux:
879 case snd_soc_dapm_value_mux:
880 case snd_soc_dapm_output:
881 case snd_soc_dapm_input:
882 case snd_soc_dapm_switch:
883 case snd_soc_dapm_hp:
884 case snd_soc_dapm_mic:
885 case snd_soc_dapm_spk:
886 case snd_soc_dapm_line:
887 case snd_soc_dapm_micbias:
888 case snd_soc_dapm_dac:
889 case snd_soc_dapm_adc:
890 case snd_soc_dapm_pga:
891 case snd_soc_dapm_mixer:
892 case snd_soc_dapm_mixer_named_ctl:
893 case snd_soc_dapm_supply:
894 if (w->name) {
895 in = is_connected_input_ep(w);
896 dapm_clear_walk(w->codec);
897 out = is_connected_output_ep(w);
898 dapm_clear_walk(w->codec);
899 printk("%s: %s in %d out %d\n", w->name,
900 w->power ? "On":"Off",in, out);
902 list_for_each_entry(p, &w->sources, list_sink) {
903 if (p->connect)
904 printk(" in %s %s\n", p->name ? p->name : "static",
905 p->source->name);
907 list_for_each_entry(p, &w->sinks, list_source) {
908 if (p->connect)
909 printk(" out %s %s\n", p->name ? p->name : "static",
910 p->sink->name);
913 break;
917 #endif
919 /* test and update the power status of a mux widget */
920 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
921 struct snd_kcontrol *kcontrol, int mask,
922 int mux, int val, struct soc_enum *e)
924 struct snd_soc_dapm_path *path;
925 int found = 0;
927 if (widget->id != snd_soc_dapm_mux &&
928 widget->id != snd_soc_dapm_value_mux)
929 return -ENODEV;
931 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
932 return 0;
934 /* find dapm widget path assoc with kcontrol */
935 list_for_each_entry(path, &widget->codec->dapm_paths, list) {
936 if (path->kcontrol != kcontrol)
937 continue;
939 if (!path->name || !e->texts[mux])
940 continue;
942 found = 1;
943 /* we now need to match the string in the enum to the path */
944 if (!(strcmp(path->name, e->texts[mux])))
945 path->connect = 1; /* new connection */
946 else
947 path->connect = 0; /* old connection must be powered down */
950 if (found) {
951 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
952 dump_dapm(widget->codec, "mux power update");
955 return 0;
958 /* test and update the power status of a mixer or switch widget */
959 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
960 struct snd_kcontrol *kcontrol, int reg,
961 int val_mask, int val, int invert)
963 struct snd_soc_dapm_path *path;
964 int found = 0;
966 if (widget->id != snd_soc_dapm_mixer &&
967 widget->id != snd_soc_dapm_mixer_named_ctl &&
968 widget->id != snd_soc_dapm_switch)
969 return -ENODEV;
971 if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
972 return 0;
974 /* find dapm widget path assoc with kcontrol */
975 list_for_each_entry(path, &widget->codec->dapm_paths, list) {
976 if (path->kcontrol != kcontrol)
977 continue;
979 /* found, now check type */
980 found = 1;
981 if (val)
982 /* new connection */
983 path->connect = invert ? 0:1;
984 else
985 /* old connection must be powered down */
986 path->connect = invert ? 1:0;
987 break;
990 if (found) {
991 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
992 dump_dapm(widget->codec, "mixer power update");
995 return 0;
998 /* show dapm widget status in sys fs */
999 static ssize_t dapm_widget_show(struct device *dev,
1000 struct device_attribute *attr, char *buf)
1002 struct snd_soc_device *devdata = dev_get_drvdata(dev);
1003 struct snd_soc_codec *codec = devdata->card->codec;
1004 struct snd_soc_dapm_widget *w;
1005 int count = 0;
1006 char *state = "not set";
1008 list_for_each_entry(w, &codec->dapm_widgets, list) {
1010 /* only display widgets that burnm power */
1011 switch (w->id) {
1012 case snd_soc_dapm_hp:
1013 case snd_soc_dapm_mic:
1014 case snd_soc_dapm_spk:
1015 case snd_soc_dapm_line:
1016 case snd_soc_dapm_micbias:
1017 case snd_soc_dapm_dac:
1018 case snd_soc_dapm_adc:
1019 case snd_soc_dapm_pga:
1020 case snd_soc_dapm_mixer:
1021 case snd_soc_dapm_mixer_named_ctl:
1022 case snd_soc_dapm_supply:
1023 if (w->name)
1024 count += sprintf(buf + count, "%s: %s\n",
1025 w->name, w->power ? "On":"Off");
1026 break;
1027 default:
1028 break;
1032 switch (codec->bias_level) {
1033 case SND_SOC_BIAS_ON:
1034 state = "On";
1035 break;
1036 case SND_SOC_BIAS_PREPARE:
1037 state = "Prepare";
1038 break;
1039 case SND_SOC_BIAS_STANDBY:
1040 state = "Standby";
1041 break;
1042 case SND_SOC_BIAS_OFF:
1043 state = "Off";
1044 break;
1046 count += sprintf(buf + count, "PM State: %s\n", state);
1048 return count;
1051 static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
1053 int snd_soc_dapm_sys_add(struct device *dev)
1055 return device_create_file(dev, &dev_attr_dapm_widget);
1058 static void snd_soc_dapm_sys_remove(struct device *dev)
1060 device_remove_file(dev, &dev_attr_dapm_widget);
1063 /* free all dapm widgets and resources */
1064 static void dapm_free_widgets(struct snd_soc_codec *codec)
1066 struct snd_soc_dapm_widget *w, *next_w;
1067 struct snd_soc_dapm_path *p, *next_p;
1069 list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
1070 list_del(&w->list);
1071 kfree(w);
1074 list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
1075 list_del(&p->list);
1076 kfree(p->long_name);
1077 kfree(p);
1081 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
1082 const char *pin, int status)
1084 struct snd_soc_dapm_widget *w;
1086 list_for_each_entry(w, &codec->dapm_widgets, list) {
1087 if (!strcmp(w->name, pin)) {
1088 pr_debug("dapm: %s: pin %s\n", codec->name, pin);
1089 w->connected = status;
1090 return 0;
1094 pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
1095 return -EINVAL;
1099 * snd_soc_dapm_sync - scan and power dapm paths
1100 * @codec: audio codec
1102 * Walks all dapm audio paths and powers widgets according to their
1103 * stream or path usage.
1105 * Returns 0 for success.
1107 int snd_soc_dapm_sync(struct snd_soc_codec *codec)
1109 int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
1110 dump_dapm(codec, "sync");
1111 return ret;
1113 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1115 static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1116 const char *sink, const char *control, const char *source)
1118 struct snd_soc_dapm_path *path;
1119 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1120 int ret = 0;
1122 /* find src and dest widgets */
1123 list_for_each_entry(w, &codec->dapm_widgets, list) {
1125 if (!wsink && !(strcmp(w->name, sink))) {
1126 wsink = w;
1127 continue;
1129 if (!wsource && !(strcmp(w->name, source))) {
1130 wsource = w;
1134 if (wsource == NULL || wsink == NULL)
1135 return -ENODEV;
1137 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
1138 if (!path)
1139 return -ENOMEM;
1141 path->source = wsource;
1142 path->sink = wsink;
1143 INIT_LIST_HEAD(&path->list);
1144 INIT_LIST_HEAD(&path->list_source);
1145 INIT_LIST_HEAD(&path->list_sink);
1147 /* check for external widgets */
1148 if (wsink->id == snd_soc_dapm_input) {
1149 if (wsource->id == snd_soc_dapm_micbias ||
1150 wsource->id == snd_soc_dapm_mic ||
1151 wsink->id == snd_soc_dapm_line ||
1152 wsink->id == snd_soc_dapm_output)
1153 wsink->ext = 1;
1155 if (wsource->id == snd_soc_dapm_output) {
1156 if (wsink->id == snd_soc_dapm_spk ||
1157 wsink->id == snd_soc_dapm_hp ||
1158 wsink->id == snd_soc_dapm_line ||
1159 wsink->id == snd_soc_dapm_input)
1160 wsource->ext = 1;
1163 /* connect static paths */
1164 if (control == NULL) {
1165 list_add(&path->list, &codec->dapm_paths);
1166 list_add(&path->list_sink, &wsink->sources);
1167 list_add(&path->list_source, &wsource->sinks);
1168 path->connect = 1;
1169 return 0;
1172 /* connect dynamic paths */
1173 switch(wsink->id) {
1174 case snd_soc_dapm_adc:
1175 case snd_soc_dapm_dac:
1176 case snd_soc_dapm_pga:
1177 case snd_soc_dapm_input:
1178 case snd_soc_dapm_output:
1179 case snd_soc_dapm_micbias:
1180 case snd_soc_dapm_vmid:
1181 case snd_soc_dapm_pre:
1182 case snd_soc_dapm_post:
1183 case snd_soc_dapm_supply:
1184 list_add(&path->list, &codec->dapm_paths);
1185 list_add(&path->list_sink, &wsink->sources);
1186 list_add(&path->list_source, &wsource->sinks);
1187 path->connect = 1;
1188 return 0;
1189 case snd_soc_dapm_mux:
1190 case snd_soc_dapm_value_mux:
1191 ret = dapm_connect_mux(codec, wsource, wsink, path, control,
1192 &wsink->kcontrols[0]);
1193 if (ret != 0)
1194 goto err;
1195 break;
1196 case snd_soc_dapm_switch:
1197 case snd_soc_dapm_mixer:
1198 case snd_soc_dapm_mixer_named_ctl:
1199 ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
1200 if (ret != 0)
1201 goto err;
1202 break;
1203 case snd_soc_dapm_hp:
1204 case snd_soc_dapm_mic:
1205 case snd_soc_dapm_line:
1206 case snd_soc_dapm_spk:
1207 list_add(&path->list, &codec->dapm_paths);
1208 list_add(&path->list_sink, &wsink->sources);
1209 list_add(&path->list_source, &wsource->sinks);
1210 path->connect = 0;
1211 return 0;
1213 return 0;
1215 err:
1216 printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
1217 control, sink);
1218 kfree(path);
1219 return ret;
1223 * snd_soc_dapm_add_routes - Add routes between DAPM widgets
1224 * @codec: codec
1225 * @route: audio routes
1226 * @num: number of routes
1228 * Connects 2 dapm widgets together via a named audio path. The sink is
1229 * the widget receiving the audio signal, whilst the source is the sender
1230 * of the audio signal.
1232 * Returns 0 for success else error. On error all resources can be freed
1233 * with a call to snd_soc_card_free().
1235 int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1236 const struct snd_soc_dapm_route *route, int num)
1238 int i, ret;
1240 for (i = 0; i < num; i++) {
1241 ret = snd_soc_dapm_add_route(codec, route->sink,
1242 route->control, route->source);
1243 if (ret < 0) {
1244 printk(KERN_ERR "Failed to add route %s->%s\n",
1245 route->source,
1246 route->sink);
1247 return ret;
1249 route++;
1252 return 0;
1254 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
1257 * snd_soc_dapm_new_widgets - add new dapm widgets
1258 * @codec: audio codec
1260 * Checks the codec for any new dapm widgets and creates them if found.
1262 * Returns 0 for success.
1264 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
1266 struct snd_soc_dapm_widget *w;
1268 list_for_each_entry(w, &codec->dapm_widgets, list)
1270 if (w->new)
1271 continue;
1273 switch(w->id) {
1274 case snd_soc_dapm_switch:
1275 case snd_soc_dapm_mixer:
1276 case snd_soc_dapm_mixer_named_ctl:
1277 w->power_check = dapm_generic_check_power;
1278 dapm_new_mixer(codec, w);
1279 break;
1280 case snd_soc_dapm_mux:
1281 case snd_soc_dapm_value_mux:
1282 w->power_check = dapm_generic_check_power;
1283 dapm_new_mux(codec, w);
1284 break;
1285 case snd_soc_dapm_adc:
1286 w->power_check = dapm_adc_check_power;
1287 break;
1288 case snd_soc_dapm_dac:
1289 w->power_check = dapm_dac_check_power;
1290 break;
1291 case snd_soc_dapm_pga:
1292 w->power_check = dapm_generic_check_power;
1293 dapm_new_pga(codec, w);
1294 break;
1295 case snd_soc_dapm_input:
1296 case snd_soc_dapm_output:
1297 case snd_soc_dapm_micbias:
1298 case snd_soc_dapm_spk:
1299 case snd_soc_dapm_hp:
1300 case snd_soc_dapm_mic:
1301 case snd_soc_dapm_line:
1302 w->power_check = dapm_generic_check_power;
1303 break;
1304 case snd_soc_dapm_supply:
1305 w->power_check = dapm_supply_check_power;
1306 case snd_soc_dapm_vmid:
1307 case snd_soc_dapm_pre:
1308 case snd_soc_dapm_post:
1309 break;
1311 w->new = 1;
1314 dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
1315 return 0;
1317 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
1320 * snd_soc_dapm_get_volsw - dapm mixer get callback
1321 * @kcontrol: mixer control
1322 * @ucontrol: control element information
1324 * Callback to get the value of a dapm mixer control.
1326 * Returns 0 for success.
1328 int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1329 struct snd_ctl_elem_value *ucontrol)
1331 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1332 struct soc_mixer_control *mc =
1333 (struct soc_mixer_control *)kcontrol->private_value;
1334 unsigned int reg = mc->reg;
1335 unsigned int shift = mc->shift;
1336 unsigned int rshift = mc->rshift;
1337 int max = mc->max;
1338 unsigned int invert = mc->invert;
1339 unsigned int mask = (1 << fls(max)) - 1;
1341 /* return the saved value if we are powered down */
1342 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1343 ucontrol->value.integer.value[0] = widget->saved_value;
1344 return 0;
1347 ucontrol->value.integer.value[0] =
1348 (snd_soc_read(widget->codec, reg) >> shift) & mask;
1349 if (shift != rshift)
1350 ucontrol->value.integer.value[1] =
1351 (snd_soc_read(widget->codec, reg) >> rshift) & mask;
1352 if (invert) {
1353 ucontrol->value.integer.value[0] =
1354 max - ucontrol->value.integer.value[0];
1355 if (shift != rshift)
1356 ucontrol->value.integer.value[1] =
1357 max - ucontrol->value.integer.value[1];
1360 return 0;
1362 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
1365 * snd_soc_dapm_put_volsw - dapm mixer set callback
1366 * @kcontrol: mixer control
1367 * @ucontrol: control element information
1369 * Callback to set the value of a dapm mixer control.
1371 * Returns 0 for success.
1373 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1374 struct snd_ctl_elem_value *ucontrol)
1376 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1377 struct soc_mixer_control *mc =
1378 (struct soc_mixer_control *)kcontrol->private_value;
1379 unsigned int reg = mc->reg;
1380 unsigned int shift = mc->shift;
1381 unsigned int rshift = mc->rshift;
1382 int max = mc->max;
1383 unsigned int mask = (1 << fls(max)) - 1;
1384 unsigned int invert = mc->invert;
1385 unsigned short val, val2, val_mask;
1386 int ret;
1388 val = (ucontrol->value.integer.value[0] & mask);
1390 if (invert)
1391 val = max - val;
1392 val_mask = mask << shift;
1393 val = val << shift;
1394 if (shift != rshift) {
1395 val2 = (ucontrol->value.integer.value[1] & mask);
1396 if (invert)
1397 val2 = max - val2;
1398 val_mask |= mask << rshift;
1399 val |= val2 << rshift;
1402 mutex_lock(&widget->codec->mutex);
1403 widget->value = val;
1405 /* save volume value if the widget is powered down */
1406 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1407 widget->saved_value = val;
1408 mutex_unlock(&widget->codec->mutex);
1409 return 1;
1412 dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
1413 if (widget->event) {
1414 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1415 ret = widget->event(widget, kcontrol,
1416 SND_SOC_DAPM_PRE_REG);
1417 if (ret < 0) {
1418 ret = 1;
1419 goto out;
1422 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1423 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1424 ret = widget->event(widget, kcontrol,
1425 SND_SOC_DAPM_POST_REG);
1426 } else
1427 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1429 out:
1430 mutex_unlock(&widget->codec->mutex);
1431 return ret;
1433 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
1436 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
1437 * @kcontrol: mixer control
1438 * @ucontrol: control element information
1440 * Callback to get the value of a dapm enumerated double mixer control.
1442 * Returns 0 for success.
1444 int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1445 struct snd_ctl_elem_value *ucontrol)
1447 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1448 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1449 unsigned short val, bitmask;
1451 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1453 val = snd_soc_read(widget->codec, e->reg);
1454 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
1455 if (e->shift_l != e->shift_r)
1456 ucontrol->value.enumerated.item[1] =
1457 (val >> e->shift_r) & (bitmask - 1);
1459 return 0;
1461 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
1464 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
1465 * @kcontrol: mixer control
1466 * @ucontrol: control element information
1468 * Callback to set the value of a dapm enumerated double mixer control.
1470 * Returns 0 for success.
1472 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1473 struct snd_ctl_elem_value *ucontrol)
1475 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1476 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1477 unsigned short val, mux;
1478 unsigned short mask, bitmask;
1479 int ret = 0;
1481 for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
1483 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1484 return -EINVAL;
1485 mux = ucontrol->value.enumerated.item[0];
1486 val = mux << e->shift_l;
1487 mask = (bitmask - 1) << e->shift_l;
1488 if (e->shift_l != e->shift_r) {
1489 if (ucontrol->value.enumerated.item[1] > e->max - 1)
1490 return -EINVAL;
1491 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1492 mask |= (bitmask - 1) << e->shift_r;
1495 mutex_lock(&widget->codec->mutex);
1496 widget->value = val;
1497 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
1498 if (widget->event) {
1499 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1500 ret = widget->event(widget,
1501 kcontrol, SND_SOC_DAPM_PRE_REG);
1502 if (ret < 0)
1503 goto out;
1505 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1506 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1507 ret = widget->event(widget,
1508 kcontrol, SND_SOC_DAPM_POST_REG);
1509 } else
1510 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1512 out:
1513 mutex_unlock(&widget->codec->mutex);
1514 return ret;
1516 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1519 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
1520 * callback
1521 * @kcontrol: mixer control
1522 * @ucontrol: control element information
1524 * Callback to get the value of a dapm semi enumerated double mixer control.
1526 * Semi enumerated mixer: the enumerated items are referred as values. Can be
1527 * used for handling bitfield coded enumeration for example.
1529 * Returns 0 for success.
1531 int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
1532 struct snd_ctl_elem_value *ucontrol)
1534 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1535 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1536 unsigned short reg_val, val, mux;
1538 reg_val = snd_soc_read(widget->codec, e->reg);
1539 val = (reg_val >> e->shift_l) & e->mask;
1540 for (mux = 0; mux < e->max; mux++) {
1541 if (val == e->values[mux])
1542 break;
1544 ucontrol->value.enumerated.item[0] = mux;
1545 if (e->shift_l != e->shift_r) {
1546 val = (reg_val >> e->shift_r) & e->mask;
1547 for (mux = 0; mux < e->max; mux++) {
1548 if (val == e->values[mux])
1549 break;
1551 ucontrol->value.enumerated.item[1] = mux;
1554 return 0;
1556 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
1559 * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set
1560 * callback
1561 * @kcontrol: mixer control
1562 * @ucontrol: control element information
1564 * Callback to set the value of a dapm semi enumerated double mixer control.
1566 * Semi enumerated mixer: the enumerated items are referred as values. Can be
1567 * used for handling bitfield coded enumeration for example.
1569 * Returns 0 for success.
1571 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1572 struct snd_ctl_elem_value *ucontrol)
1574 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1575 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1576 unsigned short val, mux;
1577 unsigned short mask;
1578 int ret = 0;
1580 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1581 return -EINVAL;
1582 mux = ucontrol->value.enumerated.item[0];
1583 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l;
1584 mask = e->mask << e->shift_l;
1585 if (e->shift_l != e->shift_r) {
1586 if (ucontrol->value.enumerated.item[1] > e->max - 1)
1587 return -EINVAL;
1588 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r;
1589 mask |= e->mask << e->shift_r;
1592 mutex_lock(&widget->codec->mutex);
1593 widget->value = val;
1594 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e);
1595 if (widget->event) {
1596 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1597 ret = widget->event(widget,
1598 kcontrol, SND_SOC_DAPM_PRE_REG);
1599 if (ret < 0)
1600 goto out;
1602 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1603 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1604 ret = widget->event(widget,
1605 kcontrol, SND_SOC_DAPM_POST_REG);
1606 } else
1607 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1609 out:
1610 mutex_unlock(&widget->codec->mutex);
1611 return ret;
1613 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
1616 * snd_soc_dapm_info_pin_switch - Info for a pin switch
1618 * @kcontrol: mixer control
1619 * @uinfo: control element information
1621 * Callback to provide information about a pin switch control.
1623 int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
1624 struct snd_ctl_elem_info *uinfo)
1626 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1627 uinfo->count = 1;
1628 uinfo->value.integer.min = 0;
1629 uinfo->value.integer.max = 1;
1631 return 0;
1633 EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
1636 * snd_soc_dapm_get_pin_switch - Get information for a pin switch
1638 * @kcontrol: mixer control
1639 * @ucontrol: Value
1641 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_value *ucontrol)
1644 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1645 const char *pin = (const char *)kcontrol->private_value;
1647 mutex_lock(&codec->mutex);
1649 ucontrol->value.integer.value[0] =
1650 snd_soc_dapm_get_pin_status(codec, pin);
1652 mutex_unlock(&codec->mutex);
1654 return 0;
1656 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
1659 * snd_soc_dapm_put_pin_switch - Set information for a pin switch
1661 * @kcontrol: mixer control
1662 * @ucontrol: Value
1664 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
1665 struct snd_ctl_elem_value *ucontrol)
1667 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1668 const char *pin = (const char *)kcontrol->private_value;
1670 mutex_lock(&codec->mutex);
1672 if (ucontrol->value.integer.value[0])
1673 snd_soc_dapm_enable_pin(codec, pin);
1674 else
1675 snd_soc_dapm_disable_pin(codec, pin);
1677 snd_soc_dapm_sync(codec);
1679 mutex_unlock(&codec->mutex);
1681 return 0;
1683 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
1686 * snd_soc_dapm_new_control - create new dapm control
1687 * @codec: audio codec
1688 * @widget: widget template
1690 * Creates a new dapm control based upon the template.
1692 * Returns 0 for success else error.
1694 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
1695 const struct snd_soc_dapm_widget *widget)
1697 struct snd_soc_dapm_widget *w;
1699 if ((w = dapm_cnew_widget(widget)) == NULL)
1700 return -ENOMEM;
1702 w->codec = codec;
1703 INIT_LIST_HEAD(&w->sources);
1704 INIT_LIST_HEAD(&w->sinks);
1705 INIT_LIST_HEAD(&w->list);
1706 list_add(&w->list, &codec->dapm_widgets);
1708 /* machine layer set ups unconnected pins and insertions */
1709 w->connected = 1;
1710 return 0;
1712 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
1715 * snd_soc_dapm_new_controls - create new dapm controls
1716 * @codec: audio codec
1717 * @widget: widget array
1718 * @num: number of widgets
1720 * Creates new DAPM controls based upon the templates.
1722 * Returns 0 for success else error.
1724 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
1725 const struct snd_soc_dapm_widget *widget,
1726 int num)
1728 int i, ret;
1730 for (i = 0; i < num; i++) {
1731 ret = snd_soc_dapm_new_control(codec, widget);
1732 if (ret < 0) {
1733 printk(KERN_ERR
1734 "ASoC: Failed to create DAPM control %s: %d\n",
1735 widget->name, ret);
1736 return ret;
1738 widget++;
1740 return 0;
1742 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
1746 * snd_soc_dapm_stream_event - send a stream event to the dapm core
1747 * @codec: audio codec
1748 * @stream: stream name
1749 * @event: stream event
1751 * Sends a stream event to the dapm core. The core then makes any
1752 * necessary widget power changes.
1754 * Returns 0 for success else error.
1756 int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1757 char *stream, int event)
1759 struct snd_soc_dapm_widget *w;
1761 if (stream == NULL)
1762 return 0;
1764 mutex_lock(&codec->mutex);
1765 list_for_each_entry(w, &codec->dapm_widgets, list)
1767 if (!w->sname)
1768 continue;
1769 pr_debug("widget %s\n %s stream %s event %d\n",
1770 w->name, w->sname, stream, event);
1771 if (strstr(w->sname, stream)) {
1772 switch(event) {
1773 case SND_SOC_DAPM_STREAM_START:
1774 w->active = 1;
1775 break;
1776 case SND_SOC_DAPM_STREAM_STOP:
1777 w->active = 0;
1778 break;
1779 case SND_SOC_DAPM_STREAM_SUSPEND:
1780 if (w->active)
1781 w->suspend = 1;
1782 w->active = 0;
1783 break;
1784 case SND_SOC_DAPM_STREAM_RESUME:
1785 if (w->suspend) {
1786 w->active = 1;
1787 w->suspend = 0;
1789 break;
1790 case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
1791 break;
1792 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
1793 break;
1797 mutex_unlock(&codec->mutex);
1799 dapm_power_widgets(codec, event);
1800 dump_dapm(codec, __func__);
1801 return 0;
1803 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1806 * snd_soc_dapm_enable_pin - enable pin.
1807 * @codec: SoC codec
1808 * @pin: pin name
1810 * Enables input/output pin and its parents or children widgets iff there is
1811 * a valid audio route and active audio stream.
1812 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1813 * do any widget power switching.
1815 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin)
1817 return snd_soc_dapm_set_pin(codec, pin, 1);
1819 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
1822 * snd_soc_dapm_disable_pin - disable pin.
1823 * @codec: SoC codec
1824 * @pin: pin name
1826 * Disables input/output pin and its parents or children widgets.
1827 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1828 * do any widget power switching.
1830 int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin)
1832 return snd_soc_dapm_set_pin(codec, pin, 0);
1834 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
1837 * snd_soc_dapm_nc_pin - permanently disable pin.
1838 * @codec: SoC codec
1839 * @pin: pin name
1841 * Marks the specified pin as being not connected, disabling it along
1842 * any parent or child widgets. At present this is identical to
1843 * snd_soc_dapm_disable_pin() but in future it will be extended to do
1844 * additional things such as disabling controls which only affect
1845 * paths through the pin.
1847 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
1848 * do any widget power switching.
1850 int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin)
1852 return snd_soc_dapm_set_pin(codec, pin, 0);
1854 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin);
1857 * snd_soc_dapm_get_pin_status - get audio pin status
1858 * @codec: audio codec
1859 * @pin: audio signal pin endpoint (or start point)
1861 * Get audio pin status - connected or disconnected.
1863 * Returns 1 for connected otherwise 0.
1865 int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin)
1867 struct snd_soc_dapm_widget *w;
1869 list_for_each_entry(w, &codec->dapm_widgets, list) {
1870 if (!strcmp(w->name, pin))
1871 return w->connected;
1874 return 0;
1876 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
1879 * snd_soc_dapm_free - free dapm resources
1880 * @socdev: SoC device
1882 * Free all dapm widgets and resources.
1884 void snd_soc_dapm_free(struct snd_soc_device *socdev)
1886 struct snd_soc_codec *codec = socdev->card->codec;
1888 snd_soc_dapm_sys_remove(socdev->dev);
1889 dapm_free_widgets(codec);
1891 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1893 /* Module information */
1894 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
1895 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1896 MODULE_LICENSE("GPL");