aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-03-01 14:21:10 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-03-06 08:37:13 -0500
commit42aa3418ebd7b79be0e1ee7515e365c1574114f9 (patch)
tree90c88f661128faf37b9f3219a4701ebc7de8a2f5 /sound/soc/soc-dapm.c
parent20a41eac4fbaa22d051d0fbaeaf3315d2d8c4860 (diff)
ASoC: Factor out DAPM widget power check into separate function
Essentially simple code motion to facilitate refactoring of the power decisions. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c258
1 files changed, 137 insertions, 121 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 4b8dbbfe2efb..7da6d0db40f2 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -523,6 +523,137 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
523EXPORT_SYMBOL_GPL(dapm_reg_event); 523EXPORT_SYMBOL_GPL(dapm_reg_event);
524 524
525/* 525/*
526 * Scan a single DAPM widget for a complete audio path and update the
527 * power status appropriately.
528 */
529static int dapm_power_widget(struct snd_soc_codec *codec, int event,
530 struct snd_soc_dapm_widget *w)
531{
532 int in, out, power_change, power, ret;
533
534 /* vmid - no action */
535 if (w->id == snd_soc_dapm_vmid)
536 return 0;
537
538 /* active ADC */
539 if (w->id == snd_soc_dapm_adc && w->active) {
540 in = is_connected_input_ep(w);
541 dapm_clear_walk(w->codec);
542 w->power = (in != 0) ? 1 : 0;
543 dapm_update_bits(w);
544 return 0;
545 }
546
547 /* active DAC */
548 if (w->id == snd_soc_dapm_dac && w->active) {
549 out = is_connected_output_ep(w);
550 dapm_clear_walk(w->codec);
551 w->power = (out != 0) ? 1 : 0;
552 dapm_update_bits(w);
553 return 0;
554 }
555
556 /* pre and post event widgets */
557 if (w->id == snd_soc_dapm_pre) {
558 if (!w->event)
559 return 0;
560
561 if (event == SND_SOC_DAPM_STREAM_START) {
562 ret = w->event(w,
563 NULL, SND_SOC_DAPM_PRE_PMU);
564 if (ret < 0)
565 return ret;
566 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
567 ret = w->event(w,
568 NULL, SND_SOC_DAPM_PRE_PMD);
569 if (ret < 0)
570 return ret;
571 }
572 return 0;
573 }
574 if (w->id == snd_soc_dapm_post) {
575 if (!w->event)
576 return 0;
577
578 if (event == SND_SOC_DAPM_STREAM_START) {
579 ret = w->event(w,
580 NULL, SND_SOC_DAPM_POST_PMU);
581 if (ret < 0)
582 return ret;
583 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
584 ret = w->event(w,
585 NULL, SND_SOC_DAPM_POST_PMD);
586 if (ret < 0)
587 return ret;
588 }
589 return 0;
590 }
591
592 /* all other widgets */
593 in = is_connected_input_ep(w);
594 dapm_clear_walk(w->codec);
595 out = is_connected_output_ep(w);
596 dapm_clear_walk(w->codec);
597 power = (out != 0 && in != 0) ? 1 : 0;
598 power_change = (w->power == power) ? 0 : 1;
599 w->power = power;
600
601 if (!power_change)
602 return 0;
603
604 /* call any power change event handlers */
605 if (w->event)
606 pr_debug("power %s event for %s flags %x\n",
607 w->power ? "on" : "off",
608 w->name, w->event_flags);
609
610 /* power up pre event */
611 if (power && w->event &&
612 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
613 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
614 if (ret < 0)
615 return ret;
616 }
617
618 /* power down pre event */
619 if (!power && w->event &&
620 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
621 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
622 if (ret < 0)
623 return ret;
624 }
625
626 /* Lower PGA volume to reduce pops */
627 if (w->id == snd_soc_dapm_pga && !power)
628 dapm_set_pga(w, power);
629
630 dapm_update_bits(w);
631
632 /* Raise PGA volume to reduce pops */
633 if (w->id == snd_soc_dapm_pga && power)
634 dapm_set_pga(w, power);
635
636 /* power up post event */
637 if (power && w->event &&
638 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
639 ret = w->event(w,
640 NULL, SND_SOC_DAPM_POST_PMU);
641 if (ret < 0)
642 return ret;
643 }
644
645 /* power down post event */
646 if (!power && w->event &&
647 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
648 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
649 if (ret < 0)
650 return ret;
651 }
652
653 return 0;
654}
655
656/*
526 * Scan each dapm widget for complete audio path. 657 * Scan each dapm widget for complete audio path.
527 * A complete path is a route that has valid endpoints i.e.:- 658 * A complete path is a route that has valid endpoints i.e.:-
528 * 659 *
@@ -534,7 +665,7 @@ EXPORT_SYMBOL_GPL(dapm_reg_event);
534static int dapm_power_widgets(struct snd_soc_codec *codec, int event) 665static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
535{ 666{
536 struct snd_soc_dapm_widget *w; 667 struct snd_soc_dapm_widget *w;
537 int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power; 668 int i, c = 1, *seq = NULL, ret = 0;
538 669
539 /* do we have a sequenced stream event */ 670 /* do we have a sequenced stream event */
540 if (event == SND_SOC_DAPM_STREAM_START) { 671 if (event == SND_SOC_DAPM_STREAM_START) {
@@ -545,135 +676,20 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
545 seq = dapm_down_seq; 676 seq = dapm_down_seq;
546 } 677 }
547 678
548 for(i = 0; i < c; i++) { 679 for (i = 0; i < c; i++) {
549 list_for_each_entry(w, &codec->dapm_widgets, list) { 680 list_for_each_entry(w, &codec->dapm_widgets, list) {
550 681
551 /* is widget in stream order */ 682 /* is widget in stream order */
552 if (seq && seq[i] && w->id != seq[i]) 683 if (seq && seq[i] && w->id != seq[i])
553 continue; 684 continue;
554 685
555 /* vmid - no action */ 686 ret = dapm_power_widget(codec, event, w);
556 if (w->id == snd_soc_dapm_vmid) 687 if (ret != 0)
557 continue; 688 return ret;
558
559 /* active ADC */
560 if (w->id == snd_soc_dapm_adc && w->active) {
561 in = is_connected_input_ep(w);
562 dapm_clear_walk(w->codec);
563 w->power = (in != 0) ? 1 : 0;
564 dapm_update_bits(w);
565 continue;
566 }
567
568 /* active DAC */
569 if (w->id == snd_soc_dapm_dac && w->active) {
570 out = is_connected_output_ep(w);
571 dapm_clear_walk(w->codec);
572 w->power = (out != 0) ? 1 : 0;
573 dapm_update_bits(w);
574 continue;
575 }
576
577 /* pre and post event widgets */
578 if (w->id == snd_soc_dapm_pre) {
579 if (!w->event)
580 continue;
581
582 if (event == SND_SOC_DAPM_STREAM_START) {
583 ret = w->event(w,
584 NULL, SND_SOC_DAPM_PRE_PMU);
585 if (ret < 0)
586 return ret;
587 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
588 ret = w->event(w,
589 NULL, SND_SOC_DAPM_PRE_PMD);
590 if (ret < 0)
591 return ret;
592 }
593 continue;
594 }
595 if (w->id == snd_soc_dapm_post) {
596 if (!w->event)
597 continue;
598
599 if (event == SND_SOC_DAPM_STREAM_START) {
600 ret = w->event(w,
601 NULL, SND_SOC_DAPM_POST_PMU);
602 if (ret < 0)
603 return ret;
604 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
605 ret = w->event(w,
606 NULL, SND_SOC_DAPM_POST_PMD);
607 if (ret < 0)
608 return ret;
609 }
610 continue;
611 }
612
613 /* all other widgets */
614 in = is_connected_input_ep(w);
615 dapm_clear_walk(w->codec);
616 out = is_connected_output_ep(w);
617 dapm_clear_walk(w->codec);
618 power = (out != 0 && in != 0) ? 1 : 0;
619 power_change = (w->power == power) ? 0: 1;
620 w->power = power;
621
622 if (!power_change)
623 continue;
624
625 /* call any power change event handlers */
626 if (w->event)
627 pr_debug("power %s event for %s flags %x\n",
628 w->power ? "on" : "off",
629 w->name, w->event_flags);
630
631 /* power up pre event */
632 if (power && w->event &&
633 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
634 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
635 if (ret < 0)
636 return ret;
637 }
638
639 /* power down pre event */
640 if (!power && w->event &&
641 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
642 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
643 if (ret < 0)
644 return ret;
645 }
646
647 /* Lower PGA volume to reduce pops */
648 if (w->id == snd_soc_dapm_pga && !power)
649 dapm_set_pga(w, power);
650
651 dapm_update_bits(w);
652
653 /* Raise PGA volume to reduce pops */
654 if (w->id == snd_soc_dapm_pga && power)
655 dapm_set_pga(w, power);
656
657 /* power up post event */
658 if (power && w->event &&
659 (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
660 ret = w->event(w,
661 NULL, SND_SOC_DAPM_POST_PMU);
662 if (ret < 0)
663 return ret;
664 }
665
666 /* power down post event */
667 if (!power && w->event &&
668 (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
669 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
670 if (ret < 0)
671 return ret;
672 }
673 } 689 }
674 } 690 }
675 691
676 return ret; 692 return 0;
677} 693}
678 694
679#ifdef DEBUG 695#ifdef DEBUG