aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRisto Suominen <Risto.Suominen@gmail.com>2008-04-17 11:55:30 -0400
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:38 -0400
commita8c2a6bf464d983c642c8b8b001a57aabbf76673 (patch)
treeae5b2c9e500f2b89ee8c5b14d6ba7612326a6651
parent946cda7d64b81053beac5d31148996f3e379e89e (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>
-rw-r--r--sound/ppc/awacs.c171
-rw-r--r--sound/ppc/awacs.h16
2 files changed, 151 insertions, 36 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 */
601static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = { 598static 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
604static 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
611static 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
617static 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
623static 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 = {
621static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata = 641static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
622AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); 642AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
623 643
644static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac __initdata =
645AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
646
624static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = { 647static 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
628static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = { 651static 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
660static 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
665static 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
671static 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
637static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = { 677static 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
640static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata = 681static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
641AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); 682AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
642 683
684static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac __initdata =
685AWACS_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
761static 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)
778int __init 837int __init
779snd_pmac_awacs_init(struct snd_pmac *chip) 838snd_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
diff --git a/sound/ppc/awacs.h b/sound/ppc/awacs.h
index 1b2cc44eda57..684bfa7cfff3 100644
--- a/sound/ppc/awacs.h
+++ b/sound/ppc/awacs.h
@@ -116,6 +116,11 @@ struct awacs_regs {
116#define MASK_HDMUTE MASK_AMUTE 116#define MASK_HDMUTE MASK_AMUTE
117#define SHIFT_HDMUTE 9 117#define SHIFT_HDMUTE 9
118#define MASK_PAROUT (0x3 << 10) /* Parallel Out (???) */ 118#define MASK_PAROUT (0x3 << 10) /* Parallel Out (???) */
119#define MASK_PAROUT0 (0x1 << 10) /* Parallel Out (???) */
120#define MASK_PAROUT1 (0x1 << 11) /* Parallel Out (enable speaker) */
121#define SHIFT_PAROUT 10
122#define SHIFT_PAROUT0 10
123#define SHIFT_PAROUT1 11
119 124
120#define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */ 125#define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */
121#define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */ 126#define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */
@@ -152,8 +157,15 @@ struct awacs_regs {
152#define MASK_REVISION (0xf << 12) /* Revision Number */ 157#define MASK_REVISION (0xf << 12) /* Revision Number */
153#define MASK_MFGID (0xf << 8) /* Mfg. ID */ 158#define MASK_MFGID (0xf << 8) /* Mfg. ID */
154#define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */ 159#define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */
155#define MASK_INPPORT (0xf) /* Input Port */ 160#define MASK_INSENSE (0xf) /* port sense bits: */
156#define MASK_HDPCONN 8 /* headphone plugged in */ 161#define MASK_HDPCONN 8 /* headphone plugged in */
162#define MASK_LOCONN 4 /* line-out plugged in */
163#define MASK_LICONN 2 /* line-in plugged in */
164#define MASK_MICCONN 1 /* microphone plugged in */
165#define MASK_LICONN_IMAC 8 /* line-in plugged in */
166#define MASK_HDPRCONN_IMAC 4 /* headphone right plugged in */
167#define MASK_HDPLCONN_IMAC 2 /* headphone left plugged in */
168#define MASK_LOCONN_IMAC 1 /* line-out plugged in */
157 169
158/* Clipping Count Reg Bit Masks */ 170/* Clipping Count Reg Bit Masks */
159/* -------- ----- --- --- ----- */ 171/* -------- ----- --- --- ----- */