diff options
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r-- | sound/soc/soc-dapm.c | 390 |
1 files changed, 250 insertions, 140 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index a2f1da8b4646..735903a74675 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -54,14 +54,15 @@ | |||
54 | static int dapm_up_seq[] = { | 54 | static int dapm_up_seq[] = { |
55 | snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, | 55 | snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, |
56 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, | 56 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, |
57 | snd_soc_dapm_mixer, snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, | 57 | snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, |
58 | snd_soc_dapm_spk, snd_soc_dapm_post | 58 | snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post |
59 | }; | 59 | }; |
60 | |||
60 | static int dapm_down_seq[] = { | 61 | static int dapm_down_seq[] = { |
61 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, | 62 | snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, |
62 | snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic, | 63 | snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, |
63 | snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_value_mux, | 64 | snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, |
64 | snd_soc_dapm_post | 65 | snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post |
65 | }; | 66 | }; |
66 | 67 | ||
67 | static int dapm_status = 1; | 68 | static int dapm_status = 1; |
@@ -101,7 +102,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
101 | { | 102 | { |
102 | switch (w->id) { | 103 | switch (w->id) { |
103 | case snd_soc_dapm_switch: | 104 | case snd_soc_dapm_switch: |
104 | case snd_soc_dapm_mixer: { | 105 | case snd_soc_dapm_mixer: |
106 | case snd_soc_dapm_mixer_named_ctl: { | ||
105 | int val; | 107 | int val; |
106 | struct soc_mixer_control *mc = (struct soc_mixer_control *) | 108 | struct soc_mixer_control *mc = (struct soc_mixer_control *) |
107 | w->kcontrols[i].private_value; | 109 | w->kcontrols[i].private_value; |
@@ -323,15 +325,32 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
323 | if (path->name != (char*)w->kcontrols[i].name) | 325 | if (path->name != (char*)w->kcontrols[i].name) |
324 | continue; | 326 | continue; |
325 | 327 | ||
326 | /* add dapm control with long name */ | 328 | /* add dapm control with long name. |
327 | name_len = 2 + strlen(w->name) | 329 | * for dapm_mixer this is the concatenation of the |
328 | + strlen(w->kcontrols[i].name); | 330 | * mixer and kcontrol name. |
331 | * for dapm_mixer_named_ctl this is simply the | ||
332 | * kcontrol name. | ||
333 | */ | ||
334 | name_len = strlen(w->kcontrols[i].name) + 1; | ||
335 | if (w->id != snd_soc_dapm_mixer_named_ctl) | ||
336 | name_len += 1 + strlen(w->name); | ||
337 | |||
329 | path->long_name = kmalloc(name_len, GFP_KERNEL); | 338 | path->long_name = kmalloc(name_len, GFP_KERNEL); |
339 | |||
330 | if (path->long_name == NULL) | 340 | if (path->long_name == NULL) |
331 | return -ENOMEM; | 341 | return -ENOMEM; |
332 | 342 | ||
333 | snprintf(path->long_name, name_len, "%s %s", | 343 | switch (w->id) { |
334 | w->name, w->kcontrols[i].name); | 344 | default: |
345 | snprintf(path->long_name, name_len, "%s %s", | ||
346 | w->name, w->kcontrols[i].name); | ||
347 | break; | ||
348 | case snd_soc_dapm_mixer_named_ctl: | ||
349 | snprintf(path->long_name, name_len, "%s", | ||
350 | w->kcontrols[i].name); | ||
351 | break; | ||
352 | } | ||
353 | |||
335 | path->long_name[name_len - 1] = '\0'; | 354 | path->long_name[name_len - 1] = '\0'; |
336 | 355 | ||
337 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 356 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
@@ -503,6 +522,137 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, | |||
503 | EXPORT_SYMBOL_GPL(dapm_reg_event); | 522 | EXPORT_SYMBOL_GPL(dapm_reg_event); |
504 | 523 | ||
505 | /* | 524 | /* |
525 | * Scan a single DAPM widget for a complete audio path and update the | ||
526 | * power status appropriately. | ||
527 | */ | ||
528 | static int dapm_power_widget(struct snd_soc_codec *codec, int event, | ||
529 | struct snd_soc_dapm_widget *w) | ||
530 | { | ||
531 | int in, out, power_change, power, ret; | ||
532 | |||
533 | /* vmid - no action */ | ||
534 | if (w->id == snd_soc_dapm_vmid) | ||
535 | return 0; | ||
536 | |||
537 | /* active ADC */ | ||
538 | if (w->id == snd_soc_dapm_adc && w->active) { | ||
539 | in = is_connected_input_ep(w); | ||
540 | dapm_clear_walk(w->codec); | ||
541 | w->power = (in != 0) ? 1 : 0; | ||
542 | dapm_update_bits(w); | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | /* active DAC */ | ||
547 | if (w->id == snd_soc_dapm_dac && w->active) { | ||
548 | out = is_connected_output_ep(w); | ||
549 | dapm_clear_walk(w->codec); | ||
550 | w->power = (out != 0) ? 1 : 0; | ||
551 | dapm_update_bits(w); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | /* pre and post event widgets */ | ||
556 | if (w->id == snd_soc_dapm_pre) { | ||
557 | if (!w->event) | ||
558 | return 0; | ||
559 | |||
560 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
561 | ret = w->event(w, | ||
562 | NULL, SND_SOC_DAPM_PRE_PMU); | ||
563 | if (ret < 0) | ||
564 | return ret; | ||
565 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
566 | ret = w->event(w, | ||
567 | NULL, SND_SOC_DAPM_PRE_PMD); | ||
568 | if (ret < 0) | ||
569 | return ret; | ||
570 | } | ||
571 | return 0; | ||
572 | } | ||
573 | if (w->id == snd_soc_dapm_post) { | ||
574 | if (!w->event) | ||
575 | return 0; | ||
576 | |||
577 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
578 | ret = w->event(w, | ||
579 | NULL, SND_SOC_DAPM_POST_PMU); | ||
580 | if (ret < 0) | ||
581 | return ret; | ||
582 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
583 | ret = w->event(w, | ||
584 | NULL, SND_SOC_DAPM_POST_PMD); | ||
585 | if (ret < 0) | ||
586 | return ret; | ||
587 | } | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | /* all other widgets */ | ||
592 | in = is_connected_input_ep(w); | ||
593 | dapm_clear_walk(w->codec); | ||
594 | out = is_connected_output_ep(w); | ||
595 | dapm_clear_walk(w->codec); | ||
596 | power = (out != 0 && in != 0) ? 1 : 0; | ||
597 | power_change = (w->power == power) ? 0 : 1; | ||
598 | w->power = power; | ||
599 | |||
600 | if (!power_change) | ||
601 | return 0; | ||
602 | |||
603 | /* call any power change event handlers */ | ||
604 | if (w->event) | ||
605 | pr_debug("power %s event for %s flags %x\n", | ||
606 | w->power ? "on" : "off", | ||
607 | w->name, w->event_flags); | ||
608 | |||
609 | /* power up pre event */ | ||
610 | if (power && w->event && | ||
611 | (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | ||
612 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | } | ||
616 | |||
617 | /* power down pre event */ | ||
618 | if (!power && w->event && | ||
619 | (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | ||
620 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | ||
621 | if (ret < 0) | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | /* Lower PGA volume to reduce pops */ | ||
626 | if (w->id == snd_soc_dapm_pga && !power) | ||
627 | dapm_set_pga(w, power); | ||
628 | |||
629 | dapm_update_bits(w); | ||
630 | |||
631 | /* Raise PGA volume to reduce pops */ | ||
632 | if (w->id == snd_soc_dapm_pga && power) | ||
633 | dapm_set_pga(w, power); | ||
634 | |||
635 | /* power up post event */ | ||
636 | if (power && w->event && | ||
637 | (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | ||
638 | ret = w->event(w, | ||
639 | NULL, SND_SOC_DAPM_POST_PMU); | ||
640 | if (ret < 0) | ||
641 | return ret; | ||
642 | } | ||
643 | |||
644 | /* power down post event */ | ||
645 | if (!power && w->event && | ||
646 | (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | ||
647 | ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | ||
648 | if (ret < 0) | ||
649 | return ret; | ||
650 | } | ||
651 | |||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | /* | ||
506 | * Scan each dapm widget for complete audio path. | 656 | * Scan each dapm widget for complete audio path. |
507 | * A complete path is a route that has valid endpoints i.e.:- | 657 | * A complete path is a route that has valid endpoints i.e.:- |
508 | * | 658 | * |
@@ -514,7 +664,7 @@ EXPORT_SYMBOL_GPL(dapm_reg_event); | |||
514 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | 664 | static int dapm_power_widgets(struct snd_soc_codec *codec, int event) |
515 | { | 665 | { |
516 | struct snd_soc_dapm_widget *w; | 666 | struct snd_soc_dapm_widget *w; |
517 | int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power; | 667 | int i, c = 1, *seq = NULL, ret = 0; |
518 | 668 | ||
519 | /* do we have a sequenced stream event */ | 669 | /* do we have a sequenced stream event */ |
520 | if (event == SND_SOC_DAPM_STREAM_START) { | 670 | if (event == SND_SOC_DAPM_STREAM_START) { |
@@ -525,135 +675,20 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) | |||
525 | seq = dapm_down_seq; | 675 | seq = dapm_down_seq; |
526 | } | 676 | } |
527 | 677 | ||
528 | for(i = 0; i < c; i++) { | 678 | for (i = 0; i < c; i++) { |
529 | list_for_each_entry(w, &codec->dapm_widgets, list) { | 679 | list_for_each_entry(w, &codec->dapm_widgets, list) { |
530 | 680 | ||
531 | /* is widget in stream order */ | 681 | /* is widget in stream order */ |
532 | if (seq && seq[i] && w->id != seq[i]) | 682 | if (seq && seq[i] && w->id != seq[i]) |
533 | continue; | 683 | continue; |
534 | 684 | ||
535 | /* vmid - no action */ | 685 | ret = dapm_power_widget(codec, event, w); |
536 | if (w->id == snd_soc_dapm_vmid) | 686 | if (ret != 0) |
537 | continue; | 687 | return ret; |
538 | |||
539 | /* active ADC */ | ||
540 | if (w->id == snd_soc_dapm_adc && w->active) { | ||
541 | in = is_connected_input_ep(w); | ||
542 | dapm_clear_walk(w->codec); | ||
543 | w->power = (in != 0) ? 1 : 0; | ||
544 | dapm_update_bits(w); | ||
545 | continue; | ||
546 | } | ||
547 | |||
548 | /* active DAC */ | ||
549 | if (w->id == snd_soc_dapm_dac && w->active) { | ||
550 | out = is_connected_output_ep(w); | ||
551 | dapm_clear_walk(w->codec); | ||
552 | w->power = (out != 0) ? 1 : 0; | ||
553 | dapm_update_bits(w); | ||
554 | continue; | ||
555 | } | ||
556 | |||
557 | /* pre and post event widgets */ | ||
558 | if (w->id == snd_soc_dapm_pre) { | ||
559 | if (!w->event) | ||
560 | continue; | ||
561 | |||
562 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
563 | ret = w->event(w, | ||
564 | NULL, SND_SOC_DAPM_PRE_PMU); | ||
565 | if (ret < 0) | ||
566 | return ret; | ||
567 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
568 | ret = w->event(w, | ||
569 | NULL, SND_SOC_DAPM_PRE_PMD); | ||
570 | if (ret < 0) | ||
571 | return ret; | ||
572 | } | ||
573 | continue; | ||
574 | } | ||
575 | if (w->id == snd_soc_dapm_post) { | ||
576 | if (!w->event) | ||
577 | continue; | ||
578 | |||
579 | if (event == SND_SOC_DAPM_STREAM_START) { | ||
580 | ret = w->event(w, | ||
581 | NULL, SND_SOC_DAPM_POST_PMU); | ||
582 | if (ret < 0) | ||
583 | return ret; | ||
584 | } else if (event == SND_SOC_DAPM_STREAM_STOP) { | ||
585 | ret = w->event(w, | ||
586 | NULL, SND_SOC_DAPM_POST_PMD); | ||
587 | if (ret < 0) | ||
588 | return ret; | ||
589 | } | ||
590 | continue; | ||
591 | } | ||
592 | |||
593 | /* all other widgets */ | ||
594 | in = is_connected_input_ep(w); | ||
595 | dapm_clear_walk(w->codec); | ||
596 | out = is_connected_output_ep(w); | ||
597 | dapm_clear_walk(w->codec); | ||
598 | power = (out != 0 && in != 0) ? 1 : 0; | ||
599 | power_change = (w->power == power) ? 0: 1; | ||
600 | w->power = power; | ||
601 | |||
602 | if (!power_change) | ||
603 | continue; | ||
604 | |||
605 | /* call any power change event handlers */ | ||
606 | if (w->event) | ||
607 | pr_debug("power %s event for %s flags %x\n", | ||
608 | w->power ? "on" : "off", | ||
609 | w->name, w->event_flags); | ||
610 | |||
611 | /* power up pre event */ | ||
612 | if (power && w->event && | ||
613 | (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { | ||
614 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); | ||
615 | if (ret < 0) | ||
616 | return ret; | ||
617 | } | ||
618 | |||
619 | /* power down pre event */ | ||
620 | if (!power && w->event && | ||
621 | (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { | ||
622 | ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); | ||
623 | if (ret < 0) | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | /* Lower PGA volume to reduce pops */ | ||
628 | if (w->id == snd_soc_dapm_pga && !power) | ||
629 | dapm_set_pga(w, power); | ||
630 | |||
631 | dapm_update_bits(w); | ||
632 | |||
633 | /* Raise PGA volume to reduce pops */ | ||
634 | if (w->id == snd_soc_dapm_pga && power) | ||
635 | dapm_set_pga(w, power); | ||
636 | |||
637 | /* power up post event */ | ||
638 | if (power && w->event && | ||
639 | (w->event_flags & SND_SOC_DAPM_POST_PMU)) { | ||
640 | ret = w->event(w, | ||
641 | NULL, SND_SOC_DAPM_POST_PMU); | ||
642 | if (ret < 0) | ||
643 | return ret; | ||
644 | } | ||
645 | |||
646 | /* power down post event */ | ||
647 | if (!power && w->event && | ||
648 | (w->event_flags & SND_SOC_DAPM_POST_PMD)) { | ||
649 | ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); | ||
650 | if (ret < 0) | ||
651 | return ret; | ||
652 | } | ||
653 | } | 688 | } |
654 | } | 689 | } |
655 | 690 | ||
656 | return ret; | 691 | return 0; |
657 | } | 692 | } |
658 | 693 | ||
659 | #ifdef DEBUG | 694 | #ifdef DEBUG |
@@ -687,6 +722,7 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) | |||
687 | case snd_soc_dapm_adc: | 722 | case snd_soc_dapm_adc: |
688 | case snd_soc_dapm_pga: | 723 | case snd_soc_dapm_pga: |
689 | case snd_soc_dapm_mixer: | 724 | case snd_soc_dapm_mixer: |
725 | case snd_soc_dapm_mixer_named_ctl: | ||
690 | if (w->name) { | 726 | if (w->name) { |
691 | in = is_connected_input_ep(w); | 727 | in = is_connected_input_ep(w); |
692 | dapm_clear_walk(w->codec); | 728 | dapm_clear_walk(w->codec); |
@@ -760,6 +796,7 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, | |||
760 | int found = 0; | 796 | int found = 0; |
761 | 797 | ||
762 | if (widget->id != snd_soc_dapm_mixer && | 798 | if (widget->id != snd_soc_dapm_mixer && |
799 | widget->id != snd_soc_dapm_mixer_named_ctl && | ||
763 | widget->id != snd_soc_dapm_switch) | 800 | widget->id != snd_soc_dapm_switch) |
764 | return -ENODEV; | 801 | return -ENODEV; |
765 | 802 | ||
@@ -795,7 +832,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
795 | struct device_attribute *attr, char *buf) | 832 | struct device_attribute *attr, char *buf) |
796 | { | 833 | { |
797 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | 834 | struct snd_soc_device *devdata = dev_get_drvdata(dev); |
798 | struct snd_soc_codec *codec = devdata->codec; | 835 | struct snd_soc_codec *codec = devdata->card->codec; |
799 | struct snd_soc_dapm_widget *w; | 836 | struct snd_soc_dapm_widget *w; |
800 | int count = 0; | 837 | int count = 0; |
801 | char *state = "not set"; | 838 | char *state = "not set"; |
@@ -813,6 +850,7 @@ static ssize_t dapm_widget_show(struct device *dev, | |||
813 | case snd_soc_dapm_adc: | 850 | case snd_soc_dapm_adc: |
814 | case snd_soc_dapm_pga: | 851 | case snd_soc_dapm_pga: |
815 | case snd_soc_dapm_mixer: | 852 | case snd_soc_dapm_mixer: |
853 | case snd_soc_dapm_mixer_named_ctl: | ||
816 | if (w->name) | 854 | if (w->name) |
817 | count += sprintf(buf + count, "%s: %s\n", | 855 | count += sprintf(buf + count, "%s: %s\n", |
818 | w->name, w->power ? "On":"Off"); | 856 | w->name, w->power ? "On":"Off"); |
@@ -876,7 +914,7 @@ static void dapm_free_widgets(struct snd_soc_codec *codec) | |||
876 | } | 914 | } |
877 | 915 | ||
878 | static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, | 916 | static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, |
879 | char *pin, int status) | 917 | const char *pin, int status) |
880 | { | 918 | { |
881 | struct snd_soc_dapm_widget *w; | 919 | struct snd_soc_dapm_widget *w; |
882 | 920 | ||
@@ -991,6 +1029,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, | |||
991 | break; | 1029 | break; |
992 | case snd_soc_dapm_switch: | 1030 | case snd_soc_dapm_switch: |
993 | case snd_soc_dapm_mixer: | 1031 | case snd_soc_dapm_mixer: |
1032 | case snd_soc_dapm_mixer_named_ctl: | ||
994 | ret = dapm_connect_mixer(codec, wsource, wsink, path, control); | 1033 | ret = dapm_connect_mixer(codec, wsource, wsink, path, control); |
995 | if (ret != 0) | 1034 | if (ret != 0) |
996 | goto err; | 1035 | goto err; |
@@ -1068,6 +1107,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) | |||
1068 | switch(w->id) { | 1107 | switch(w->id) { |
1069 | case snd_soc_dapm_switch: | 1108 | case snd_soc_dapm_switch: |
1070 | case snd_soc_dapm_mixer: | 1109 | case snd_soc_dapm_mixer: |
1110 | case snd_soc_dapm_mixer_named_ctl: | ||
1071 | dapm_new_mixer(codec, w); | 1111 | dapm_new_mixer(codec, w); |
1072 | break; | 1112 | break; |
1073 | case snd_soc_dapm_mux: | 1113 | case snd_soc_dapm_mux: |
@@ -1396,6 +1436,76 @@ out: | |||
1396 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); | 1436 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); |
1397 | 1437 | ||
1398 | /** | 1438 | /** |
1439 | * snd_soc_dapm_info_pin_switch - Info for a pin switch | ||
1440 | * | ||
1441 | * @kcontrol: mixer control | ||
1442 | * @uinfo: control element information | ||
1443 | * | ||
1444 | * Callback to provide information about a pin switch control. | ||
1445 | */ | ||
1446 | int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, | ||
1447 | struct snd_ctl_elem_info *uinfo) | ||
1448 | { | ||
1449 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1450 | uinfo->count = 1; | ||
1451 | uinfo->value.integer.min = 0; | ||
1452 | uinfo->value.integer.max = 1; | ||
1453 | |||
1454 | return 0; | ||
1455 | } | ||
1456 | EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch); | ||
1457 | |||
1458 | /** | ||
1459 | * snd_soc_dapm_get_pin_switch - Get information for a pin switch | ||
1460 | * | ||
1461 | * @kcontrol: mixer control | ||
1462 | * @ucontrol: Value | ||
1463 | */ | ||
1464 | int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, | ||
1465 | struct snd_ctl_elem_value *ucontrol) | ||
1466 | { | ||
1467 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1468 | const char *pin = (const char *)kcontrol->private_value; | ||
1469 | |||
1470 | mutex_lock(&codec->mutex); | ||
1471 | |||
1472 | ucontrol->value.integer.value[0] = | ||
1473 | snd_soc_dapm_get_pin_status(codec, pin); | ||
1474 | |||
1475 | mutex_unlock(&codec->mutex); | ||
1476 | |||
1477 | return 0; | ||
1478 | } | ||
1479 | EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch); | ||
1480 | |||
1481 | /** | ||
1482 | * snd_soc_dapm_put_pin_switch - Set information for a pin switch | ||
1483 | * | ||
1484 | * @kcontrol: mixer control | ||
1485 | * @ucontrol: Value | ||
1486 | */ | ||
1487 | int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, | ||
1488 | struct snd_ctl_elem_value *ucontrol) | ||
1489 | { | ||
1490 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1491 | const char *pin = (const char *)kcontrol->private_value; | ||
1492 | |||
1493 | mutex_lock(&codec->mutex); | ||
1494 | |||
1495 | if (ucontrol->value.integer.value[0]) | ||
1496 | snd_soc_dapm_enable_pin(codec, pin); | ||
1497 | else | ||
1498 | snd_soc_dapm_disable_pin(codec, pin); | ||
1499 | |||
1500 | snd_soc_dapm_sync(codec); | ||
1501 | |||
1502 | mutex_unlock(&codec->mutex); | ||
1503 | |||
1504 | return 0; | ||
1505 | } | ||
1506 | EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); | ||
1507 | |||
1508 | /** | ||
1399 | * snd_soc_dapm_new_control - create new dapm control | 1509 | * snd_soc_dapm_new_control - create new dapm control |
1400 | * @codec: audio codec | 1510 | * @codec: audio codec |
1401 | * @widget: widget template | 1511 | * @widget: widget template |
@@ -1527,8 +1637,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | |||
1527 | int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, | 1637 | int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, |
1528 | enum snd_soc_bias_level level) | 1638 | enum snd_soc_bias_level level) |
1529 | { | 1639 | { |
1530 | struct snd_soc_codec *codec = socdev->codec; | ||
1531 | struct snd_soc_card *card = socdev->card; | 1640 | struct snd_soc_card *card = socdev->card; |
1641 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1532 | int ret = 0; | 1642 | int ret = 0; |
1533 | 1643 | ||
1534 | if (card->set_bias_level) | 1644 | if (card->set_bias_level) |
@@ -1549,7 +1659,7 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, | |||
1549 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 1659 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
1550 | * do any widget power switching. | 1660 | * do any widget power switching. |
1551 | */ | 1661 | */ |
1552 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin) | 1662 | int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) |
1553 | { | 1663 | { |
1554 | return snd_soc_dapm_set_pin(codec, pin, 1); | 1664 | return snd_soc_dapm_set_pin(codec, pin, 1); |
1555 | } | 1665 | } |
@@ -1564,7 +1674,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); | |||
1564 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 1674 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
1565 | * do any widget power switching. | 1675 | * do any widget power switching. |
1566 | */ | 1676 | */ |
1567 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin) | 1677 | int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) |
1568 | { | 1678 | { |
1569 | return snd_soc_dapm_set_pin(codec, pin, 0); | 1679 | return snd_soc_dapm_set_pin(codec, pin, 0); |
1570 | } | 1680 | } |
@@ -1584,7 +1694,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); | |||
1584 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to | 1694 | * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to |
1585 | * do any widget power switching. | 1695 | * do any widget power switching. |
1586 | */ | 1696 | */ |
1587 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin) | 1697 | int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) |
1588 | { | 1698 | { |
1589 | return snd_soc_dapm_set_pin(codec, pin, 0); | 1699 | return snd_soc_dapm_set_pin(codec, pin, 0); |
1590 | } | 1700 | } |
@@ -1599,7 +1709,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); | |||
1599 | * | 1709 | * |
1600 | * Returns 1 for connected otherwise 0. | 1710 | * Returns 1 for connected otherwise 0. |
1601 | */ | 1711 | */ |
1602 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin) | 1712 | int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) |
1603 | { | 1713 | { |
1604 | struct snd_soc_dapm_widget *w; | 1714 | struct snd_soc_dapm_widget *w; |
1605 | 1715 | ||
@@ -1620,7 +1730,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); | |||
1620 | */ | 1730 | */ |
1621 | void snd_soc_dapm_free(struct snd_soc_device *socdev) | 1731 | void snd_soc_dapm_free(struct snd_soc_device *socdev) |
1622 | { | 1732 | { |
1623 | struct snd_soc_codec *codec = socdev->codec; | 1733 | struct snd_soc_codec *codec = socdev->card->codec; |
1624 | 1734 | ||
1625 | snd_soc_dapm_sys_remove(socdev->dev); | 1735 | snd_soc_dapm_sys_remove(socdev->dev); |
1626 | dapm_free_widgets(codec); | 1736 | dapm_free_widgets(codec); |