diff options
Diffstat (limited to 'sound/ppc/tumbler.c')
-rw-r--r-- | sound/ppc/tumbler.c | 259 |
1 files changed, 194 insertions, 65 deletions
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index cb6916e9b74f..c71807e069ee 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -35,14 +35,19 @@ | |||
35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | 38 | #include <asm/machdep.h> |
39 | #include <asm/pmac_feature.h> | 39 | #include <asm/pmac_feature.h> |
40 | #else | ||
41 | #error old crap | ||
42 | #endif | ||
43 | #include "pmac.h" | 40 | #include "pmac.h" |
44 | #include "tumbler_volume.h" | 41 | #include "tumbler_volume.h" |
45 | 42 | ||
43 | #undef DEBUG | ||
44 | |||
45 | #ifdef DEBUG | ||
46 | #define DBG(fmt...) printk(fmt) | ||
47 | #else | ||
48 | #define DBG(fmt...) | ||
49 | #endif | ||
50 | |||
46 | /* i2c address for tumbler */ | 51 | /* i2c address for tumbler */ |
47 | #define TAS_I2C_ADDR 0x34 | 52 | #define TAS_I2C_ADDR 0x34 |
48 | 53 | ||
@@ -78,21 +83,22 @@ enum { | |||
78 | }; | 83 | }; |
79 | 84 | ||
80 | typedef struct pmac_gpio { | 85 | typedef struct pmac_gpio { |
81 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
82 | unsigned int addr; | 86 | unsigned int addr; |
83 | #else | 87 | u8 active_val; |
84 | void __iomem *addr; | 88 | u8 inactive_val; |
85 | #endif | 89 | u8 active_state; |
86 | int active_state; | ||
87 | } pmac_gpio_t; | 90 | } pmac_gpio_t; |
88 | 91 | ||
89 | typedef struct pmac_tumbler_t { | 92 | typedef struct pmac_tumbler_t { |
90 | pmac_keywest_t i2c; | 93 | pmac_keywest_t i2c; |
91 | pmac_gpio_t audio_reset; | 94 | pmac_gpio_t audio_reset; |
92 | pmac_gpio_t amp_mute; | 95 | pmac_gpio_t amp_mute; |
96 | pmac_gpio_t line_mute; | ||
97 | pmac_gpio_t line_detect; | ||
93 | pmac_gpio_t hp_mute; | 98 | pmac_gpio_t hp_mute; |
94 | pmac_gpio_t hp_detect; | 99 | pmac_gpio_t hp_detect; |
95 | int headphone_irq; | 100 | int headphone_irq; |
101 | int lineout_irq; | ||
96 | unsigned int master_vol[2]; | 102 | unsigned int master_vol[2]; |
97 | unsigned int save_master_switch[2]; | 103 | unsigned int save_master_switch[2]; |
98 | unsigned int master_switch[2]; | 104 | unsigned int master_switch[2]; |
@@ -120,6 +126,7 @@ static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs) | |||
120 | regs[0], regs[1]); | 126 | regs[0], regs[1]); |
121 | if (err >= 0) | 127 | if (err >= 0) |
122 | break; | 128 | break; |
129 | DBG("(W) i2c error %d\n", err); | ||
123 | mdelay(10); | 130 | mdelay(10); |
124 | } while (count--); | 131 | } while (count--); |
125 | if (err < 0) | 132 | if (err < 0) |
@@ -137,6 +144,7 @@ static int tumbler_init_client(pmac_keywest_t *i2c) | |||
137 | TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, | 144 | TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, |
138 | 0, /* terminator */ | 145 | 0, /* terminator */ |
139 | }; | 146 | }; |
147 | DBG("(I) tumbler init client\n"); | ||
140 | return send_init_client(i2c, regs); | 148 | return send_init_client(i2c, regs); |
141 | } | 149 | } |
142 | 150 | ||
@@ -151,36 +159,27 @@ static int snapper_init_client(pmac_keywest_t *i2c) | |||
151 | TAS_REG_ACS, 0, | 159 | TAS_REG_ACS, 0, |
152 | 0, /* terminator */ | 160 | 0, /* terminator */ |
153 | }; | 161 | }; |
162 | DBG("(I) snapper init client\n"); | ||
154 | return send_init_client(i2c, regs); | 163 | return send_init_client(i2c, regs); |
155 | } | 164 | } |
156 | 165 | ||
157 | /* | 166 | /* |
158 | * gpio access | 167 | * gpio access |
159 | */ | 168 | */ |
160 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
161 | #define do_gpio_write(gp, val) \ | 169 | #define do_gpio_write(gp, val) \ |
162 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) | 170 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) |
163 | #define do_gpio_read(gp) \ | 171 | #define do_gpio_read(gp) \ |
164 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) | 172 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) |
165 | #define tumbler_gpio_free(gp) /* NOP */ | 173 | #define tumbler_gpio_free(gp) /* NOP */ |
166 | #else | ||
167 | #define do_gpio_write(gp, val) writeb(val, (gp)->addr) | ||
168 | #define do_gpio_read(gp) readb((gp)->addr) | ||
169 | static inline void tumbler_gpio_free(pmac_gpio_t *gp) | ||
170 | { | ||
171 | if (gp->addr) { | ||
172 | iounmap(gp->addr); | ||
173 | gp->addr = NULL; | ||
174 | } | ||
175 | } | ||
176 | #endif /* CONFIG_PPC_HAS_FEATURE_CALLS */ | ||
177 | 174 | ||
178 | static void write_audio_gpio(pmac_gpio_t *gp, int active) | 175 | static void write_audio_gpio(pmac_gpio_t *gp, int active) |
179 | { | 176 | { |
180 | if (! gp->addr) | 177 | if (! gp->addr) |
181 | return; | 178 | return; |
182 | active = active ? gp->active_state : !gp->active_state; | 179 | active = active ? gp->active_val : gp->inactive_val; |
183 | do_gpio_write(gp, active ? 0x05 : 0x04); | 180 | |
181 | do_gpio_write(gp, active); | ||
182 | DBG("(I) gpio %x write %d\n", gp->addr, active); | ||
184 | } | 183 | } |
185 | 184 | ||
186 | static int read_audio_gpio(pmac_gpio_t *gp) | 185 | static int read_audio_gpio(pmac_gpio_t *gp) |
@@ -663,7 +662,7 @@ static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont | |||
663 | * to avoid codec reset on ibook M7 | 662 | * to avoid codec reset on ibook M7 |
664 | */ | 663 | */ |
665 | 664 | ||
666 | enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP }; | 665 | enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE }; |
667 | 666 | ||
668 | static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 667 | static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
669 | { | 668 | { |
@@ -672,7 +671,18 @@ static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
672 | pmac_gpio_t *gp; | 671 | pmac_gpio_t *gp; |
673 | if (! (mix = chip->mixer_data)) | 672 | if (! (mix = chip->mixer_data)) |
674 | return -ENODEV; | 673 | return -ENODEV; |
675 | gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute; | 674 | switch(kcontrol->private_value) { |
675 | case TUMBLER_MUTE_HP: | ||
676 | gp = &mix->hp_mute; break; | ||
677 | case TUMBLER_MUTE_AMP: | ||
678 | gp = &mix->amp_mute; break; | ||
679 | case TUMBLER_MUTE_LINE: | ||
680 | gp = &mix->line_mute; break; | ||
681 | default: | ||
682 | gp = NULL; | ||
683 | } | ||
684 | if (gp == NULL) | ||
685 | return -EINVAL; | ||
676 | ucontrol->value.integer.value[0] = ! read_audio_gpio(gp); | 686 | ucontrol->value.integer.value[0] = ! read_audio_gpio(gp); |
677 | return 0; | 687 | return 0; |
678 | } | 688 | } |
@@ -689,7 +699,18 @@ static int tumbler_put_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
689 | #endif | 699 | #endif |
690 | if (! (mix = chip->mixer_data)) | 700 | if (! (mix = chip->mixer_data)) |
691 | return -ENODEV; | 701 | return -ENODEV; |
692 | gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute; | 702 | switch(kcontrol->private_value) { |
703 | case TUMBLER_MUTE_HP: | ||
704 | gp = &mix->hp_mute; break; | ||
705 | case TUMBLER_MUTE_AMP: | ||
706 | gp = &mix->amp_mute; break; | ||
707 | case TUMBLER_MUTE_LINE: | ||
708 | gp = &mix->line_mute; break; | ||
709 | default: | ||
710 | gp = NULL; | ||
711 | } | ||
712 | if (gp == NULL) | ||
713 | return -EINVAL; | ||
693 | val = ! read_audio_gpio(gp); | 714 | val = ! read_audio_gpio(gp); |
694 | if (val != ucontrol->value.integer.value[0]) { | 715 | if (val != ucontrol->value.integer.value[0]) { |
695 | write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); | 716 | write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); |
@@ -833,6 +854,14 @@ static snd_kcontrol_new_t tumbler_speaker_sw __initdata = { | |||
833 | .put = tumbler_put_mute_switch, | 854 | .put = tumbler_put_mute_switch, |
834 | .private_value = TUMBLER_MUTE_AMP, | 855 | .private_value = TUMBLER_MUTE_AMP, |
835 | }; | 856 | }; |
857 | static snd_kcontrol_new_t tumbler_lineout_sw __initdata = { | ||
858 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
859 | .name = "Line Out Playback Switch", | ||
860 | .info = snd_pmac_boolean_mono_info, | ||
861 | .get = tumbler_get_mute_switch, | ||
862 | .put = tumbler_put_mute_switch, | ||
863 | .private_value = TUMBLER_MUTE_LINE, | ||
864 | }; | ||
836 | static snd_kcontrol_new_t tumbler_drc_sw __initdata = { | 865 | static snd_kcontrol_new_t tumbler_drc_sw __initdata = { |
837 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 866 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
838 | .name = "DRC Switch", | 867 | .name = "DRC Switch", |
@@ -849,7 +878,21 @@ static snd_kcontrol_new_t tumbler_drc_sw __initdata = { | |||
849 | static int tumbler_detect_headphone(pmac_t *chip) | 878 | static int tumbler_detect_headphone(pmac_t *chip) |
850 | { | 879 | { |
851 | pmac_tumbler_t *mix = chip->mixer_data; | 880 | pmac_tumbler_t *mix = chip->mixer_data; |
852 | return read_audio_gpio(&mix->hp_detect); | 881 | int detect = 0; |
882 | |||
883 | if (mix->hp_detect.addr) | ||
884 | detect |= read_audio_gpio(&mix->hp_detect); | ||
885 | return detect; | ||
886 | } | ||
887 | |||
888 | static int tumbler_detect_lineout(pmac_t *chip) | ||
889 | { | ||
890 | pmac_tumbler_t *mix = chip->mixer_data; | ||
891 | int detect = 0; | ||
892 | |||
893 | if (mix->line_detect.addr) | ||
894 | detect |= read_audio_gpio(&mix->line_detect); | ||
895 | return detect; | ||
853 | } | 896 | } |
854 | 897 | ||
855 | static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw) | 898 | static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw) |
@@ -868,6 +911,7 @@ static void device_change_handler(void *self) | |||
868 | { | 911 | { |
869 | pmac_t *chip = (pmac_t*) self; | 912 | pmac_t *chip = (pmac_t*) self; |
870 | pmac_tumbler_t *mix; | 913 | pmac_tumbler_t *mix; |
914 | int headphone, lineout; | ||
871 | 915 | ||
872 | if (!chip) | 916 | if (!chip) |
873 | return; | 917 | return; |
@@ -875,23 +919,35 @@ static void device_change_handler(void *self) | |||
875 | mix = chip->mixer_data; | 919 | mix = chip->mixer_data; |
876 | snd_assert(mix, return); | 920 | snd_assert(mix, return); |
877 | 921 | ||
878 | if (tumbler_detect_headphone(chip)) { | 922 | headphone = tumbler_detect_headphone(chip); |
879 | /* mute speaker */ | 923 | lineout = tumbler_detect_lineout(chip); |
880 | check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, | 924 | |
881 | chip->master_sw_ctl); | 925 | DBG("headphone: %d, lineout: %d\n", headphone, lineout); |
926 | |||
927 | if (headphone || lineout) { | ||
928 | /* unmute headphone/lineout & mute speaker */ | ||
929 | if (headphone) | ||
930 | check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, | ||
931 | chip->master_sw_ctl); | ||
932 | if (lineout && mix->line_mute.addr != 0) | ||
933 | check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, | ||
934 | chip->lineout_sw_ctl); | ||
882 | if (mix->anded_reset) | 935 | if (mix->anded_reset) |
883 | big_mdelay(10); | 936 | big_mdelay(10); |
884 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, | 937 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, |
885 | chip->speaker_sw_ctl); | 938 | chip->speaker_sw_ctl); |
886 | mix->drc_enable = 0; | 939 | mix->drc_enable = 0; |
887 | } else { | 940 | } else { |
888 | /* unmute speaker */ | 941 | /* unmute speaker, mute others */ |
889 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, | 942 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, |
890 | chip->speaker_sw_ctl); | 943 | chip->speaker_sw_ctl); |
891 | if (mix->anded_reset) | 944 | if (mix->anded_reset) |
892 | big_mdelay(10); | 945 | big_mdelay(10); |
893 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, | 946 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, |
894 | chip->master_sw_ctl); | 947 | chip->master_sw_ctl); |
948 | if (mix->line_mute.addr != 0) | ||
949 | check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify, | ||
950 | chip->lineout_sw_ctl); | ||
895 | mix->drc_enable = 1; | 951 | mix->drc_enable = 1; |
896 | } | 952 | } |
897 | if (mix->auto_mute_notify) { | 953 | if (mix->auto_mute_notify) { |
@@ -967,7 +1023,7 @@ static struct device_node *find_compatible_audio_device(const char *name) | |||
967 | } | 1023 | } |
968 | 1024 | ||
969 | /* find an audio device and get its address */ | 1025 | /* find an audio device and get its address */ |
970 | static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_compatible) | 1026 | static long tumbler_find_device(const char *device, const char *platform, pmac_gpio_t *gp, int is_compatible) |
971 | { | 1027 | { |
972 | struct device_node *node; | 1028 | struct device_node *node; |
973 | u32 *base, addr; | 1029 | u32 *base, addr; |
@@ -977,6 +1033,7 @@ static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_comp | |||
977 | else | 1033 | else |
978 | node = find_audio_device(device); | 1034 | node = find_audio_device(device); |
979 | if (! node) { | 1035 | if (! node) { |
1036 | DBG("(W) cannot find audio device %s !\n", device); | ||
980 | snd_printdd("cannot find device %s\n", device); | 1037 | snd_printdd("cannot find device %s\n", device); |
981 | return -ENODEV; | 1038 | return -ENODEV; |
982 | } | 1039 | } |
@@ -985,29 +1042,48 @@ static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_comp | |||
985 | if (! base) { | 1042 | if (! base) { |
986 | base = (u32 *)get_property(node, "reg", NULL); | 1043 | base = (u32 *)get_property(node, "reg", NULL); |
987 | if (!base) { | 1044 | if (!base) { |
1045 | DBG("(E) cannot find address for device %s !\n", device); | ||
988 | snd_printd("cannot find address for device %s\n", device); | 1046 | snd_printd("cannot find address for device %s\n", device); |
989 | return -ENODEV; | 1047 | return -ENODEV; |
990 | } | 1048 | } |
991 | /* this only work if PPC_HAS_FEATURE_CALLS is set as we | ||
992 | * are only getting the low part of the address | ||
993 | */ | ||
994 | addr = *base; | 1049 | addr = *base; |
995 | if (addr < 0x50) | 1050 | if (addr < 0x50) |
996 | addr += 0x50; | 1051 | addr += 0x50; |
997 | } else | 1052 | } else |
998 | addr = *base; | 1053 | addr = *base; |
999 | 1054 | ||
1000 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
1001 | gp->addr = addr & 0x0000ffff; | 1055 | gp->addr = addr & 0x0000ffff; |
1002 | #else | ||
1003 | gp->addr = ioremap((unsigned long)addr, 1); | ||
1004 | #endif | ||
1005 | /* Try to find the active state, default to 0 ! */ | 1056 | /* Try to find the active state, default to 0 ! */ |
1006 | base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); | 1057 | base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); |
1007 | if (base) | 1058 | if (base) { |
1008 | gp->active_state = *base; | 1059 | gp->active_state = *base; |
1009 | else | 1060 | gp->active_val = (*base) ? 0x5 : 0x4; |
1061 | gp->inactive_val = (*base) ? 0x4 : 0x5; | ||
1062 | } else { | ||
1063 | u32 *prop = NULL; | ||
1010 | gp->active_state = 0; | 1064 | gp->active_state = 0; |
1065 | gp->active_val = 0x4; | ||
1066 | gp->inactive_val = 0x5; | ||
1067 | /* Here are some crude hacks to extract the GPIO polarity and | ||
1068 | * open collector informations out of the do-platform script | ||
1069 | * as we don't yet have an interpreter for these things | ||
1070 | */ | ||
1071 | if (platform) | ||
1072 | prop = (u32 *)get_property(node, platform, NULL); | ||
1073 | if (prop) { | ||
1074 | if (prop[3] == 0x9 && prop[4] == 0x9) { | ||
1075 | gp->active_val = 0xd; | ||
1076 | gp->inactive_val = 0xc; | ||
1077 | } | ||
1078 | if (prop[3] == 0x1 && prop[4] == 0x1) { | ||
1079 | gp->active_val = 0x5; | ||
1080 | gp->inactive_val = 0x4; | ||
1081 | } | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", | ||
1086 | device, gp->addr, gp->active_state); | ||
1011 | 1087 | ||
1012 | return (node->n_intrs > 0) ? node->intrs[0].line : 0; | 1088 | return (node->n_intrs > 0) ? node->intrs[0].line : 0; |
1013 | } | 1089 | } |
@@ -1018,6 +1094,7 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1018 | pmac_tumbler_t *mix = chip->mixer_data; | 1094 | pmac_tumbler_t *mix = chip->mixer_data; |
1019 | 1095 | ||
1020 | if (mix->anded_reset) { | 1096 | if (mix->anded_reset) { |
1097 | DBG("(I) codec anded reset !\n"); | ||
1021 | write_audio_gpio(&mix->hp_mute, 0); | 1098 | write_audio_gpio(&mix->hp_mute, 0); |
1022 | write_audio_gpio(&mix->amp_mute, 0); | 1099 | write_audio_gpio(&mix->amp_mute, 0); |
1023 | big_mdelay(200); | 1100 | big_mdelay(200); |
@@ -1028,6 +1105,8 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1028 | write_audio_gpio(&mix->amp_mute, 0); | 1105 | write_audio_gpio(&mix->amp_mute, 0); |
1029 | big_mdelay(100); | 1106 | big_mdelay(100); |
1030 | } else { | 1107 | } else { |
1108 | DBG("(I) codec normal reset !\n"); | ||
1109 | |||
1031 | write_audio_gpio(&mix->audio_reset, 0); | 1110 | write_audio_gpio(&mix->audio_reset, 0); |
1032 | big_mdelay(200); | 1111 | big_mdelay(200); |
1033 | write_audio_gpio(&mix->audio_reset, 1); | 1112 | write_audio_gpio(&mix->audio_reset, 1); |
@@ -1045,6 +1124,8 @@ static void tumbler_suspend(pmac_t *chip) | |||
1045 | 1124 | ||
1046 | if (mix->headphone_irq >= 0) | 1125 | if (mix->headphone_irq >= 0) |
1047 | disable_irq(mix->headphone_irq); | 1126 | disable_irq(mix->headphone_irq); |
1127 | if (mix->lineout_irq >= 0) | ||
1128 | disable_irq(mix->lineout_irq); | ||
1048 | mix->save_master_switch[0] = mix->master_switch[0]; | 1129 | mix->save_master_switch[0] = mix->master_switch[0]; |
1049 | mix->save_master_switch[1] = mix->master_switch[1]; | 1130 | mix->save_master_switch[1] = mix->master_switch[1]; |
1050 | mix->master_switch[0] = mix->master_switch[1] = 0; | 1131 | mix->master_switch[0] = mix->master_switch[1] = 0; |
@@ -1099,41 +1180,59 @@ static void tumbler_resume(pmac_t *chip) | |||
1099 | chip->update_automute(chip, 0); | 1180 | chip->update_automute(chip, 0); |
1100 | if (mix->headphone_irq >= 0) | 1181 | if (mix->headphone_irq >= 0) |
1101 | enable_irq(mix->headphone_irq); | 1182 | enable_irq(mix->headphone_irq); |
1183 | if (mix->lineout_irq >= 0) | ||
1184 | enable_irq(mix->lineout_irq); | ||
1102 | } | 1185 | } |
1103 | #endif | 1186 | #endif |
1104 | 1187 | ||
1105 | /* initialize tumbler */ | 1188 | /* initialize tumbler */ |
1106 | static int __init tumbler_init(pmac_t *chip) | 1189 | static int __init tumbler_init(pmac_t *chip) |
1107 | { | 1190 | { |
1108 | int irq, err; | 1191 | int irq; |
1109 | pmac_tumbler_t *mix = chip->mixer_data; | 1192 | pmac_tumbler_t *mix = chip->mixer_data; |
1110 | snd_assert(mix, return -EINVAL); | 1193 | snd_assert(mix, return -EINVAL); |
1111 | 1194 | ||
1112 | if (tumbler_find_device("audio-hw-reset", &mix->audio_reset, 0) < 0) | 1195 | if (tumbler_find_device("audio-hw-reset", |
1113 | tumbler_find_device("hw-reset", &mix->audio_reset, 1); | 1196 | "platform-do-hw-reset", |
1114 | if (tumbler_find_device("amp-mute", &mix->amp_mute, 0) < 0) | 1197 | &mix->audio_reset, 0) < 0) |
1115 | tumbler_find_device("amp-mute", &mix->amp_mute, 1); | 1198 | tumbler_find_device("hw-reset", |
1116 | if (tumbler_find_device("headphone-mute", &mix->hp_mute, 0) < 0) | 1199 | "platform-do-hw-reset", |
1117 | tumbler_find_device("headphone-mute", &mix->hp_mute, 1); | 1200 | &mix->audio_reset, 1); |
1118 | irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 0); | 1201 | if (tumbler_find_device("amp-mute", |
1202 | "platform-do-amp-mute", | ||
1203 | &mix->amp_mute, 0) < 0) | ||
1204 | tumbler_find_device("amp-mute", | ||
1205 | "platform-do-amp-mute", | ||
1206 | &mix->amp_mute, 1); | ||
1207 | if (tumbler_find_device("headphone-mute", | ||
1208 | "platform-do-headphone-mute", | ||
1209 | &mix->hp_mute, 0) < 0) | ||
1210 | tumbler_find_device("headphone-mute", | ||
1211 | "platform-do-headphone-mute", | ||
1212 | &mix->hp_mute, 1); | ||
1213 | if (tumbler_find_device("line-output-mute", | ||
1214 | "platform-do-lineout-mute", | ||
1215 | &mix->line_mute, 0) < 0) | ||
1216 | tumbler_find_device("line-output-mute", | ||
1217 | "platform-do-lineout-mute", | ||
1218 | &mix->line_mute, 1); | ||
1219 | irq = tumbler_find_device("headphone-detect", | ||
1220 | NULL, &mix->hp_detect, 0); | ||
1119 | if (irq < 0) | 1221 | if (irq < 0) |
1120 | irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 1); | 1222 | irq = tumbler_find_device("headphone-detect", |
1223 | NULL, &mix->hp_detect, 1); | ||
1121 | if (irq < 0) | 1224 | if (irq < 0) |
1122 | irq = tumbler_find_device("keywest-gpio15", &mix->hp_detect, 1); | 1225 | irq = tumbler_find_device("keywest-gpio15", |
1226 | NULL, &mix->hp_detect, 1); | ||
1227 | mix->headphone_irq = irq; | ||
1228 | irq = tumbler_find_device("line-output-detect", | ||
1229 | NULL, &mix->line_detect, 0); | ||
1230 | if (irq < 0) | ||
1231 | irq = tumbler_find_device("line-output-detect", | ||
1232 | NULL, &mix->line_detect, 1); | ||
1233 | mix->lineout_irq = irq; | ||
1123 | 1234 | ||
1124 | tumbler_reset_audio(chip); | 1235 | tumbler_reset_audio(chip); |
1125 | |||
1126 | /* activate headphone status interrupts */ | ||
1127 | if (irq >= 0) { | ||
1128 | unsigned char val; | ||
1129 | if ((err = request_irq(irq, headphone_intr, 0, | ||
1130 | "Tumbler Headphone Detection", chip)) < 0) | ||
1131 | return err; | ||
1132 | /* activate headphone status interrupts */ | ||
1133 | val = do_gpio_read(&mix->hp_detect); | ||
1134 | do_gpio_write(&mix->hp_detect, val | 0x80); | ||
1135 | } | ||
1136 | mix->headphone_irq = irq; | ||
1137 | 1236 | ||
1138 | return 0; | 1237 | return 0; |
1139 | } | 1238 | } |
@@ -1146,6 +1245,8 @@ static void tumbler_cleanup(pmac_t *chip) | |||
1146 | 1245 | ||
1147 | if (mix->headphone_irq >= 0) | 1246 | if (mix->headphone_irq >= 0) |
1148 | free_irq(mix->headphone_irq, chip); | 1247 | free_irq(mix->headphone_irq, chip); |
1248 | if (mix->lineout_irq >= 0) | ||
1249 | free_irq(mix->lineout_irq, chip); | ||
1149 | tumbler_gpio_free(&mix->audio_reset); | 1250 | tumbler_gpio_free(&mix->audio_reset); |
1150 | tumbler_gpio_free(&mix->amp_mute); | 1251 | tumbler_gpio_free(&mix->amp_mute); |
1151 | tumbler_gpio_free(&mix->hp_mute); | 1252 | tumbler_gpio_free(&mix->hp_mute); |
@@ -1207,6 +1308,8 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1207 | else | 1308 | else |
1208 | mix->i2c.addr = TAS_I2C_ADDR; | 1309 | mix->i2c.addr = TAS_I2C_ADDR; |
1209 | 1310 | ||
1311 | DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); | ||
1312 | |||
1210 | if (chip->model == PMAC_TUMBLER) { | 1313 | if (chip->model == PMAC_TUMBLER) { |
1211 | mix->i2c.init_client = tumbler_init_client; | 1314 | mix->i2c.init_client = tumbler_init_client; |
1212 | mix->i2c.name = "TAS3001c"; | 1315 | mix->i2c.name = "TAS3001c"; |
@@ -1242,6 +1345,11 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1242 | chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); | 1345 | chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); |
1243 | if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) | 1346 | if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) |
1244 | return err; | 1347 | return err; |
1348 | if (mix->line_mute.addr != 0) { | ||
1349 | chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip); | ||
1350 | if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0) | ||
1351 | return err; | ||
1352 | } | ||
1245 | chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); | 1353 | chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); |
1246 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) | 1354 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) |
1247 | return err; | 1355 | return err; |
@@ -1254,11 +1362,32 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1254 | INIT_WORK(&device_change, device_change_handler, (void *)chip); | 1362 | INIT_WORK(&device_change, device_change_handler, (void *)chip); |
1255 | 1363 | ||
1256 | #ifdef PMAC_SUPPORT_AUTOMUTE | 1364 | #ifdef PMAC_SUPPORT_AUTOMUTE |
1257 | if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0) | 1365 | if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) |
1366 | && (err = snd_pmac_add_automute(chip)) < 0) | ||
1258 | return err; | 1367 | return err; |
1259 | chip->detect_headphone = tumbler_detect_headphone; | 1368 | chip->detect_headphone = tumbler_detect_headphone; |
1260 | chip->update_automute = tumbler_update_automute; | 1369 | chip->update_automute = tumbler_update_automute; |
1261 | tumbler_update_automute(chip, 0); /* update the status only */ | 1370 | tumbler_update_automute(chip, 0); /* update the status only */ |
1371 | |||
1372 | /* activate headphone status interrupts */ | ||
1373 | if (mix->headphone_irq >= 0) { | ||
1374 | unsigned char val; | ||
1375 | if ((err = request_irq(mix->headphone_irq, headphone_intr, 0, | ||
1376 | "Sound Headphone Detection", chip)) < 0) | ||
1377 | return 0; | ||
1378 | /* activate headphone status interrupts */ | ||
1379 | val = do_gpio_read(&mix->hp_detect); | ||
1380 | do_gpio_write(&mix->hp_detect, val | 0x80); | ||
1381 | } | ||
1382 | if (mix->lineout_irq >= 0) { | ||
1383 | unsigned char val; | ||
1384 | if ((err = request_irq(mix->lineout_irq, headphone_intr, 0, | ||
1385 | "Sound Lineout Detection", chip)) < 0) | ||
1386 | return 0; | ||
1387 | /* activate headphone status interrupts */ | ||
1388 | val = do_gpio_read(&mix->line_detect); | ||
1389 | do_gpio_write(&mix->line_detect, val | 0x80); | ||
1390 | } | ||
1262 | #endif | 1391 | #endif |
1263 | 1392 | ||
1264 | return 0; | 1393 | return 0; |