diff options
author | Risto Suominen <Risto.Suominen@gmail.com> | 2008-04-17 11:55:30 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:38 -0400 |
commit | a8c2a6bf464d983c642c8b8b001a57aabbf76673 (patch) | |
tree | ae5b2c9e500f2b89ee8c5b14d6ba7612326a6651 /sound/ppc/awacs.c | |
parent | 946cda7d64b81053beac5d31148996f3e379e89e (diff) |
[ALSA] snd-powermac: AWACS and Screamer mixers for PM7500, Beige, and iMac SL
Add mixer controls and correct headphone detection bits for PowerMacs
7300/7500 (AWACS) and G3 Beige (Screamer), and iMac G3 Slot-loading
(Screamer).
Signed-off-by: Risto Suominen <Risto.Suominen@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/ppc/awacs.c')
-rw-r--r-- | sound/ppc/awacs.c | 171 |
1 files changed, 137 insertions, 34 deletions
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 8441e780df00..db4e35d28244 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -544,7 +544,7 @@ static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol, | |||
544 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 544 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
545 | uinfo->count = 1; | 545 | uinfo->count = 1; |
546 | uinfo->value.integer.min = 0; | 546 | uinfo->value.integer.min = 0; |
547 | uinfo->value.integer.max = 2; | 547 | uinfo->value.integer.max = 3; |
548 | return 0; | 548 | return 0; |
549 | } | 549 | } |
550 | 550 | ||
@@ -552,16 +552,14 @@ static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol, | |||
552 | struct snd_ctl_elem_value *ucontrol) | 552 | struct snd_ctl_elem_value *ucontrol) |
553 | { | 553 | { |
554 | struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); | 554 | struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); |
555 | int val; | 555 | int val = 0; |
556 | unsigned long flags; | 556 | unsigned long flags; |
557 | 557 | ||
558 | spin_lock_irqsave(&chip->reg_lock, flags); | 558 | spin_lock_irqsave(&chip->reg_lock, flags); |
559 | if (chip->awacs_reg[6] & MASK_MIC_BOOST) | 559 | if (chip->awacs_reg[6] & MASK_MIC_BOOST) |
560 | val = 2; | 560 | val |= 2; |
561 | else if (chip->awacs_reg[0] & MASK_GAINLINE) | 561 | if (chip->awacs_reg[0] & MASK_GAINLINE) |
562 | val = 1; | 562 | val |= 1; |
563 | else | ||
564 | val = 0; | ||
565 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 563 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
566 | ucontrol->value.integer.value[0] = val; | 564 | ucontrol->value.integer.value[0] = val; |
567 | return 0; | 565 | return 0; |
@@ -578,11 +576,10 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol, | |||
578 | spin_lock_irqsave(&chip->reg_lock, flags); | 576 | spin_lock_irqsave(&chip->reg_lock, flags); |
579 | val0 = chip->awacs_reg[0] & ~MASK_GAINLINE; | 577 | val0 = chip->awacs_reg[0] & ~MASK_GAINLINE; |
580 | val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST; | 578 | val6 = chip->awacs_reg[6] & ~MASK_MIC_BOOST; |
581 | if (ucontrol->value.integer.value[0] > 0) { | 579 | if (ucontrol->value.integer.value[0] & 1) |
582 | val0 |= MASK_GAINLINE; | 580 | val0 |= MASK_GAINLINE; |
583 | if (ucontrol->value.integer.value[0] > 1) | 581 | if (ucontrol->value.integer.value[0] & 2) |
584 | val6 |= MASK_MIC_BOOST; | 582 | val6 |= MASK_MIC_BOOST; |
585 | } | ||
586 | if (val0 != chip->awacs_reg[0]) { | 583 | if (val0 != chip->awacs_reg[0]) { |
587 | snd_pmac_awacs_write_reg(chip, 0, val0); | 584 | snd_pmac_awacs_write_reg(chip, 0, val0); |
588 | changed = 1; | 585 | changed = 1; |
@@ -599,9 +596,32 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol, | |||
599 | * lists of mixer elements | 596 | * lists of mixer elements |
600 | */ | 597 | */ |
601 | static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = { | 598 | static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = { |
602 | AWACS_VOLUME("Master Playback Volume", 2, 6, 1), | ||
603 | AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0), | 599 | AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0), |
604 | AWACS_VOLUME("Capture Volume", 0, 4, 0), | 600 | AWACS_VOLUME("Master Capture Volume", 0, 4, 0), |
601 | /* AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */ | ||
602 | }; | ||
603 | |||
604 | static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] __initdata = { | ||
605 | AWACS_VOLUME("Master Playback Volume", 2, 6, 1), | ||
606 | AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1), | ||
607 | AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), | ||
608 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0), | ||
609 | }; | ||
610 | |||
611 | static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] __initdata = { | ||
612 | AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), | ||
613 | AWACS_VOLUME("Master Playback Volume", 5, 6, 1), | ||
614 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), | ||
615 | }; | ||
616 | |||
617 | static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] __initdata = { | ||
618 | AWACS_VOLUME("Line out Playback Volume", 2, 6, 1), | ||
619 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), | ||
620 | AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), | ||
621 | }; | ||
622 | |||
623 | static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] __initdata = { | ||
624 | AWACS_VOLUME("Master Playback Volume", 2, 6, 1), | ||
605 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), | 625 | AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), |
606 | }; | 626 | }; |
607 | 627 | ||
@@ -621,25 +641,49 @@ static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = { | |||
621 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata = | 641 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata = |
622 | AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); | 642 | AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); |
623 | 643 | ||
644 | static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata = | ||
645 | AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1); | ||
646 | |||
624 | static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = { | 647 | static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = { |
625 | AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0), | 648 | AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0), |
626 | }; | 649 | }; |
627 | 650 | ||
628 | static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = { | 651 | static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = { |
629 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 652 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
630 | .name = "Mic Boost", | 653 | .name = "Mic Boost Capture Volume", |
631 | .info = snd_pmac_screamer_mic_boost_info, | 654 | .info = snd_pmac_screamer_mic_boost_info, |
632 | .get = snd_pmac_screamer_mic_boost_get, | 655 | .get = snd_pmac_screamer_mic_boost_get, |
633 | .put = snd_pmac_screamer_mic_boost_put, | 656 | .put = snd_pmac_screamer_mic_boost_put, |
634 | }, | 657 | }, |
635 | }; | 658 | }; |
636 | 659 | ||
660 | static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] __initdata = | ||
661 | { | ||
662 | AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), | ||
663 | }; | ||
664 | |||
665 | static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] __initdata = | ||
666 | { | ||
667 | AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), | ||
668 | AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0), | ||
669 | }; | ||
670 | |||
671 | static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] __initdata = | ||
672 | { | ||
673 | AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0), | ||
674 | AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0), | ||
675 | }; | ||
676 | |||
637 | static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = { | 677 | static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = { |
638 | AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1), | 678 | AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1), |
639 | }; | 679 | }; |
680 | |||
640 | static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata = | 681 | static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata = |
641 | AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); | 682 | AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); |
642 | 683 | ||
684 | static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata = | ||
685 | AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_PAROUT1, 0); | ||
686 | |||
643 | 687 | ||
644 | /* | 688 | /* |
645 | * add new mixer elements to the card | 689 | * add new mixer elements to the card |
@@ -708,6 +752,14 @@ static void snd_pmac_awacs_resume(struct snd_pmac *chip) | |||
708 | } | 752 | } |
709 | #endif /* CONFIG_PM */ | 753 | #endif /* CONFIG_PM */ |
710 | 754 | ||
755 | #define IS_PM7500 (machine_is_compatible("AAPL,7500")) | ||
756 | #define IS_BEIGE (machine_is_compatible("AAPL,Gossamer")) | ||
757 | #define IS_IMAC (machine_is_compatible("PowerMac2,1") \ | ||
758 | || machine_is_compatible("PowerMac2,2") \ | ||
759 | || machine_is_compatible("PowerMac4,1")) | ||
760 | |||
761 | static int imac; | ||
762 | |||
711 | #ifdef PMAC_SUPPORT_AUTOMUTE | 763 | #ifdef PMAC_SUPPORT_AUTOMUTE |
712 | /* | 764 | /* |
713 | * auto-mute stuffs | 765 | * auto-mute stuffs |
@@ -750,9 +802,16 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify) | |||
750 | } else | 802 | } else |
751 | #endif | 803 | #endif |
752 | { | 804 | { |
753 | int reg = chip->awacs_reg[1] | (MASK_HDMUTE|MASK_SPKMUTE); | 805 | int reg = chip->awacs_reg[1] |
806 | | (MASK_HDMUTE | MASK_SPKMUTE); | ||
807 | if (imac) { | ||
808 | reg &= ~MASK_SPKMUTE; | ||
809 | reg &= ~MASK_PAROUT1; | ||
810 | } | ||
754 | if (snd_pmac_awacs_detect_headphone(chip)) | 811 | if (snd_pmac_awacs_detect_headphone(chip)) |
755 | reg &= ~MASK_HDMUTE; | 812 | reg &= ~MASK_HDMUTE; |
813 | else if (imac) | ||
814 | reg |= MASK_PAROUT1; | ||
756 | else | 815 | else |
757 | reg &= ~MASK_SPKMUTE; | 816 | reg &= ~MASK_SPKMUTE; |
758 | if (do_notify && reg == chip->awacs_reg[1]) | 817 | if (do_notify && reg == chip->awacs_reg[1]) |
@@ -778,8 +837,11 @@ static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify) | |||
778 | int __init | 837 | int __init |
779 | snd_pmac_awacs_init(struct snd_pmac *chip) | 838 | snd_pmac_awacs_init(struct snd_pmac *chip) |
780 | { | 839 | { |
840 | int pm7500 = IS_PM7500; | ||
841 | int beige = IS_BEIGE; | ||
781 | int err, vol; | 842 | int err, vol; |
782 | 843 | ||
844 | imac = IS_IMAC; | ||
783 | /* looks like MASK_GAINLINE triggers something, so we set here | 845 | /* looks like MASK_GAINLINE triggers something, so we set here |
784 | * as start-up | 846 | * as start-up |
785 | */ | 847 | */ |
@@ -826,20 +888,25 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
826 | /* set headphone-jack detection bit */ | 888 | /* set headphone-jack detection bit */ |
827 | switch (chip->model) { | 889 | switch (chip->model) { |
828 | case PMAC_AWACS: | 890 | case PMAC_AWACS: |
829 | chip->hp_stat_mask = 0x04; | 891 | chip->hp_stat_mask = pm7500 ? MASK_HDPCONN |
892 | : MASK_LOCONN; | ||
830 | break; | 893 | break; |
831 | case PMAC_SCREAMER: | 894 | case PMAC_SCREAMER: |
832 | switch (chip->device_id) { | 895 | switch (chip->device_id) { |
833 | case 0x08: | 896 | case 0x08: |
834 | /* 1 = side jack, 2 = front jack */ | 897 | case 0x0B: |
835 | chip->hp_stat_mask = 0x03; | 898 | chip->hp_stat_mask = imac |
899 | ? MASK_LOCONN_IMAC | | ||
900 | MASK_HDPLCONN_IMAC | | ||
901 | MASK_HDPRCONN_IMAC | ||
902 | : MASK_HDPCONN; | ||
836 | break; | 903 | break; |
837 | case 0x00: | 904 | case 0x00: |
838 | case 0x05: | 905 | case 0x05: |
839 | chip->hp_stat_mask = 0x04; | 906 | chip->hp_stat_mask = MASK_LOCONN; |
840 | break; | 907 | break; |
841 | default: | 908 | default: |
842 | chip->hp_stat_mask = 0x08; | 909 | chip->hp_stat_mask = MASK_HDPCONN; |
843 | break; | 910 | break; |
844 | } | 911 | } |
845 | break; | 912 | break; |
@@ -857,15 +924,37 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
857 | if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers), | 924 | if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers), |
858 | snd_pmac_awacs_mixers)) < 0) | 925 | snd_pmac_awacs_mixers)) < 0) |
859 | return err; | 926 | return err; |
860 | if (chip->model == PMAC_SCREAMER) | 927 | if (beige) |
928 | ; | ||
929 | else if (chip->model == PMAC_SCREAMER) | ||
861 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), | 930 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), |
862 | snd_pmac_screamer_mixers2); | 931 | snd_pmac_screamer_mixers2); |
863 | else | 932 | else if (!pm7500) |
864 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2), | 933 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2), |
865 | snd_pmac_awacs_mixers2); | 934 | snd_pmac_awacs_mixers2); |
866 | if (err < 0) | 935 | if (err < 0) |
867 | return err; | 936 | return err; |
868 | chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip); | 937 | if (pm7500) |
938 | err = build_mixers(chip, | ||
939 | ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500), | ||
940 | snd_pmac_awacs_mixers_pmac7500); | ||
941 | else if (beige) | ||
942 | err = build_mixers(chip, | ||
943 | ARRAY_SIZE(snd_pmac_screamer_mixers_beige), | ||
944 | snd_pmac_screamer_mixers_beige); | ||
945 | else if (imac) | ||
946 | err = build_mixers(chip, | ||
947 | ARRAY_SIZE(snd_pmac_screamer_mixers_imac), | ||
948 | snd_pmac_screamer_mixers_imac); | ||
949 | else | ||
950 | err = build_mixers(chip, | ||
951 | ARRAY_SIZE(snd_pmac_awacs_mixers_pmac), | ||
952 | snd_pmac_awacs_mixers_pmac); | ||
953 | if (err < 0) | ||
954 | return err; | ||
955 | chip->master_sw_ctl = snd_ctl_new1((pm7500 || imac) | ||
956 | ? &snd_pmac_awacs_master_sw_imac | ||
957 | : &snd_pmac_awacs_master_sw, chip); | ||
869 | if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) | 958 | if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) |
870 | return err; | 959 | return err; |
871 | #ifdef PMAC_AMP_AVAIL | 960 | #ifdef PMAC_AMP_AVAIL |
@@ -893,20 +982,34 @@ snd_pmac_awacs_init(struct snd_pmac *chip) | |||
893 | if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol), | 982 | if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol), |
894 | snd_pmac_awacs_speaker_vol)) < 0) | 983 | snd_pmac_awacs_speaker_vol)) < 0) |
895 | return err; | 984 | return err; |
896 | chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip); | 985 | chip->speaker_sw_ctl = snd_ctl_new1(imac |
986 | ? &snd_pmac_awacs_speaker_sw_imac | ||
987 | : &snd_pmac_awacs_speaker_sw, chip); | ||
897 | if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) | 988 | if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) |
898 | return err; | 989 | return err; |
899 | } | 990 | } |
900 | 991 | ||
901 | if (chip->model == PMAC_SCREAMER) { | 992 | if (beige) |
902 | if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost), | 993 | err = build_mixers(chip, |
903 | snd_pmac_screamer_mic_boost)) < 0) | 994 | ARRAY_SIZE(snd_pmac_screamer_mic_boost_beige), |
904 | return err; | 995 | snd_pmac_screamer_mic_boost_beige); |
905 | } else { | 996 | else if (imac) |
906 | if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost), | 997 | err = build_mixers(chip, |
907 | snd_pmac_awacs_mic_boost)) < 0) | 998 | ARRAY_SIZE(snd_pmac_screamer_mic_boost_imac), |
908 | return err; | 999 | snd_pmac_screamer_mic_boost_imac); |
909 | } | 1000 | else if (chip->model == PMAC_SCREAMER) |
1001 | err = build_mixers(chip, | ||
1002 | ARRAY_SIZE(snd_pmac_screamer_mic_boost), | ||
1003 | snd_pmac_screamer_mic_boost); | ||
1004 | else if (pm7500) | ||
1005 | err = build_mixers(chip, | ||
1006 | ARRAY_SIZE(snd_pmac_awacs_mic_boost_pmac7500), | ||
1007 | snd_pmac_awacs_mic_boost_pmac7500); | ||
1008 | else | ||
1009 | err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost), | ||
1010 | snd_pmac_awacs_mic_boost); | ||
1011 | if (err < 0) | ||
1012 | return err; | ||
910 | 1013 | ||
911 | /* | 1014 | /* |
912 | * set lowlevel callbacks | 1015 | * set lowlevel callbacks |