aboutsummaryrefslogtreecommitdiffstats
path: root/sound/ppc/tumbler.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/ppc/tumbler.c')
-rw-r--r--sound/ppc/tumbler.c142
1 files changed, 106 insertions, 36 deletions
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 72a2219f56b5..cb6916e9b74f 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -94,12 +94,17 @@ typedef struct pmac_tumbler_t {
94 pmac_gpio_t hp_detect; 94 pmac_gpio_t hp_detect;
95 int headphone_irq; 95 int headphone_irq;
96 unsigned int master_vol[2]; 96 unsigned int master_vol[2];
97 unsigned int save_master_switch[2];
97 unsigned int master_switch[2]; 98 unsigned int master_switch[2];
98 unsigned int mono_vol[VOL_IDX_LAST_MONO]; 99 unsigned int mono_vol[VOL_IDX_LAST_MONO];
99 unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */ 100 unsigned int mix_vol[VOL_IDX_LAST_MIX][2]; /* stereo volumes for tas3004 */
100 int drc_range; 101 int drc_range;
101 int drc_enable; 102 int drc_enable;
102 int capture_source; 103 int capture_source;
104 int anded_reset;
105 int auto_mute_notify;
106 int reset_on_sleep;
107 u8 acs;
103} pmac_tumbler_t; 108} pmac_tumbler_t;
104 109
105 110
@@ -654,7 +659,8 @@ static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
654 659
655 660
656/* 661/*
657 * mute switches 662 * mute switches. FIXME: Turn that into software mute when both outputs are muted
663 * to avoid codec reset on ibook M7
658 */ 664 */
659 665
660enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP }; 666enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP };
@@ -696,8 +702,11 @@ static int snapper_set_capture_source(pmac_tumbler_t *mix)
696{ 702{
697 if (! mix->i2c.client) 703 if (! mix->i2c.client)
698 return -ENODEV; 704 return -ENODEV;
699 return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, 705 if (mix->capture_source)
700 mix->capture_source ? 2 : 0); 706 mix->acs = mix->acs |= 2;
707 else
708 mix->acs &= ~2;
709 return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
701} 710}
702 711
703static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 712static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -855,8 +864,7 @@ static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, sn
855 864
856static struct work_struct device_change; 865static struct work_struct device_change;
857 866
858static void 867static void device_change_handler(void *self)
859device_change_handler(void *self)
860{ 868{
861 pmac_t *chip = (pmac_t*) self; 869 pmac_t *chip = (pmac_t*) self;
862 pmac_tumbler_t *mix; 870 pmac_tumbler_t *mix;
@@ -865,6 +873,33 @@ device_change_handler(void *self)
865 return; 873 return;
866 874
867 mix = chip->mixer_data; 875 mix = chip->mixer_data;
876 snd_assert(mix, return);
877
878 if (tumbler_detect_headphone(chip)) {
879 /* mute speaker */
880 check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify,
881 chip->master_sw_ctl);
882 if (mix->anded_reset)
883 big_mdelay(10);
884 check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify,
885 chip->speaker_sw_ctl);
886 mix->drc_enable = 0;
887 } else {
888 /* unmute speaker */
889 check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify,
890 chip->speaker_sw_ctl);
891 if (mix->anded_reset)
892 big_mdelay(10);
893 check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify,
894 chip->master_sw_ctl);
895 mix->drc_enable = 1;
896 }
897 if (mix->auto_mute_notify) {
898 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
899 &chip->hp_detect_ctl->id);
900 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
901 &chip->drc_sw_ctl->id);
902 }
868 903
869 /* first set the DRC so the speaker do not explode -ReneR */ 904 /* first set the DRC so the speaker do not explode -ReneR */
870 if (chip->model == PMAC_TUMBLER) 905 if (chip->model == PMAC_TUMBLER)
@@ -879,31 +914,11 @@ device_change_handler(void *self)
879static void tumbler_update_automute(pmac_t *chip, int do_notify) 914static void tumbler_update_automute(pmac_t *chip, int do_notify)
880{ 915{
881 if (chip->auto_mute) { 916 if (chip->auto_mute) {
882 pmac_tumbler_t *mix = chip->mixer_data; 917 pmac_tumbler_t *mix;
918 mix = chip->mixer_data;
883 snd_assert(mix, return); 919 snd_assert(mix, return);
884 if (tumbler_detect_headphone(chip)) { 920 mix->auto_mute_notify = do_notify;
885 /* mute speaker */
886 check_mute(chip, &mix->amp_mute, 1, do_notify, chip->speaker_sw_ctl);
887 check_mute(chip, &mix->hp_mute, 0, do_notify, chip->master_sw_ctl);
888 mix->drc_enable = 0;
889
890 } else {
891 /* unmute speaker */
892 check_mute(chip, &mix->amp_mute, 0, do_notify, chip->speaker_sw_ctl);
893 check_mute(chip, &mix->hp_mute, 1, do_notify, chip->master_sw_ctl);
894 mix->drc_enable = 1;
895 }
896 if (do_notify) {
897 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
898 &chip->hp_detect_ctl->id);
899 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
900 &chip->drc_sw_ctl->id);
901 }
902
903 /* finally we need to schedule an update of the mixer values
904 (master and DRC are enough for now) -ReneR */
905 schedule_work(&device_change); 921 schedule_work(&device_change);
906
907 } 922 }
908} 923}
909#endif /* PMAC_SUPPORT_AUTOMUTE */ 924#endif /* PMAC_SUPPORT_AUTOMUTE */
@@ -1002,15 +1017,53 @@ static void tumbler_reset_audio(pmac_t *chip)
1002{ 1017{
1003 pmac_tumbler_t *mix = chip->mixer_data; 1018 pmac_tumbler_t *mix = chip->mixer_data;
1004 1019
1005 write_audio_gpio(&mix->audio_reset, 0); 1020 if (mix->anded_reset) {
1006 big_mdelay(200); 1021 write_audio_gpio(&mix->hp_mute, 0);
1007 write_audio_gpio(&mix->audio_reset, 1); 1022 write_audio_gpio(&mix->amp_mute, 0);
1008 big_mdelay(100); 1023 big_mdelay(200);
1009 write_audio_gpio(&mix->audio_reset, 0); 1024 write_audio_gpio(&mix->hp_mute, 1);
1010 big_mdelay(100); 1025 write_audio_gpio(&mix->amp_mute, 1);
1026 big_mdelay(100);
1027 write_audio_gpio(&mix->hp_mute, 0);
1028 write_audio_gpio(&mix->amp_mute, 0);
1029 big_mdelay(100);
1030 } else {
1031 write_audio_gpio(&mix->audio_reset, 0);
1032 big_mdelay(200);
1033 write_audio_gpio(&mix->audio_reset, 1);
1034 big_mdelay(100);
1035 write_audio_gpio(&mix->audio_reset, 0);
1036 big_mdelay(100);
1037 }
1011} 1038}
1012 1039
1013#ifdef CONFIG_PMAC_PBOOK 1040#ifdef CONFIG_PMAC_PBOOK
1041/* suspend mixer */
1042static void tumbler_suspend(pmac_t *chip)
1043{
1044 pmac_tumbler_t *mix = chip->mixer_data;
1045
1046 if (mix->headphone_irq >= 0)
1047 disable_irq(mix->headphone_irq);
1048 mix->save_master_switch[0] = mix->master_switch[0];
1049 mix->save_master_switch[1] = mix->master_switch[1];
1050 mix->master_switch[0] = mix->master_switch[1] = 0;
1051 tumbler_set_master_volume(mix);
1052 if (!mix->anded_reset) {
1053 write_audio_gpio(&mix->amp_mute, 1);
1054 write_audio_gpio(&mix->hp_mute, 1);
1055 }
1056 if (chip->model == PMAC_SNAPPER) {
1057 mix->acs |= 1;
1058 i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
1059 }
1060 if (mix->anded_reset) {
1061 write_audio_gpio(&mix->amp_mute, 1);
1062 write_audio_gpio(&mix->hp_mute, 1);
1063 } else
1064 write_audio_gpio(&mix->audio_reset, 1);
1065}
1066
1014/* resume mixer */ 1067/* resume mixer */
1015static void tumbler_resume(pmac_t *chip) 1068static void tumbler_resume(pmac_t *chip)
1016{ 1069{
@@ -1018,6 +1071,9 @@ static void tumbler_resume(pmac_t *chip)
1018 1071
1019 snd_assert(mix, return); 1072 snd_assert(mix, return);
1020 1073
1074 mix->acs &= ~1;
1075 mix->master_switch[0] = mix->save_master_switch[0];
1076 mix->master_switch[1] = mix->save_master_switch[1];
1021 tumbler_reset_audio(chip); 1077 tumbler_reset_audio(chip);
1022 if (mix->i2c.client && mix->i2c.init_client) { 1078 if (mix->i2c.client && mix->i2c.init_client) {
1023 if (mix->i2c.init_client(&mix->i2c) < 0) 1079 if (mix->i2c.init_client(&mix->i2c) < 0)
@@ -1041,6 +1097,8 @@ static void tumbler_resume(pmac_t *chip)
1041 tumbler_set_master_volume(mix); 1097 tumbler_set_master_volume(mix);
1042 if (chip->update_automute) 1098 if (chip->update_automute)
1043 chip->update_automute(chip, 0); 1099 chip->update_automute(chip, 0);
1100 if (mix->headphone_irq >= 0)
1101 enable_irq(mix->headphone_irq);
1044} 1102}
1045#endif 1103#endif
1046 1104
@@ -1103,7 +1161,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
1103 int i, err; 1161 int i, err;
1104 pmac_tumbler_t *mix; 1162 pmac_tumbler_t *mix;
1105 u32 *paddr; 1163 u32 *paddr;
1106 struct device_node *tas_node; 1164 struct device_node *tas_node, *np;
1107 char *chipname; 1165 char *chipname;
1108 1166
1109#ifdef CONFIG_KMOD 1167#ifdef CONFIG_KMOD
@@ -1119,7 +1177,18 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
1119 1177
1120 chip->mixer_data = mix; 1178 chip->mixer_data = mix;
1121 chip->mixer_free = tumbler_cleanup; 1179 chip->mixer_free = tumbler_cleanup;
1122 1180 mix->anded_reset = 0;
1181 mix->reset_on_sleep = 1;
1182
1183 for (np = chip->node->child; np; np = np->sibling) {
1184 if (!strcmp(np->name, "sound")) {
1185 if (get_property(np, "has-anded-reset", NULL))
1186 mix->anded_reset = 1;
1187 if (get_property(np, "layout-id", NULL))
1188 mix->reset_on_sleep = 0;
1189 break;
1190 }
1191 }
1123 if ((err = tumbler_init(chip)) < 0) 1192 if ((err = tumbler_init(chip)) < 0)
1124 return err; 1193 return err;
1125 1194
@@ -1178,6 +1247,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
1178 return err; 1247 return err;
1179 1248
1180#ifdef CONFIG_PMAC_PBOOK 1249#ifdef CONFIG_PMAC_PBOOK
1250 chip->suspend = tumbler_suspend;
1181 chip->resume = tumbler_resume; 1251 chip->resume = tumbler_resume;
1182#endif 1252#endif
1183 1253