diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-01-15 12:22:31 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-01-15 12:28:37 -0500 |
commit | 5f17e79cdf530b1a6090c65730e5656ac9c19eaa (patch) | |
tree | 4fd5886309ed84755e5c43096cd039850bef7525 /sound | |
parent | 45e513b689b8b0a01ec2b01cc21816e4780d7ea6 (diff) |
ALSA: snd-aoa: handle master-amp if present
Some machines have a master amp GPIO that needs to be toggled to
get sound output, in addition to speaker/headphone/line-out amps.
This makes snd-aoa handle it, if present in the device tree, thus
making snd-aoa be able to output sound on PowerMac3,6, which was
previously handled by snd-powermac which also doesn't use the
master amp GPIO.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/aoa/aoa-gpio.h | 2 | ||||
-rw-r--r-- | sound/aoa/core/gpio-feature.c | 17 | ||||
-rw-r--r-- | sound/aoa/fabrics/layout.c | 7 |
3 files changed, 25 insertions, 1 deletions
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h index ee64f5de8966..6065b0344e23 100644 --- a/sound/aoa/aoa-gpio.h +++ b/sound/aoa/aoa-gpio.h | |||
@@ -34,10 +34,12 @@ struct gpio_methods { | |||
34 | void (*set_headphone)(struct gpio_runtime *rt, int on); | 34 | void (*set_headphone)(struct gpio_runtime *rt, int on); |
35 | void (*set_speakers)(struct gpio_runtime *rt, int on); | 35 | void (*set_speakers)(struct gpio_runtime *rt, int on); |
36 | void (*set_lineout)(struct gpio_runtime *rt, int on); | 36 | void (*set_lineout)(struct gpio_runtime *rt, int on); |
37 | void (*set_master)(struct gpio_runtime *rt, int on); | ||
37 | 38 | ||
38 | int (*get_headphone)(struct gpio_runtime *rt); | 39 | int (*get_headphone)(struct gpio_runtime *rt); |
39 | int (*get_speakers)(struct gpio_runtime *rt); | 40 | int (*get_speakers)(struct gpio_runtime *rt); |
40 | int (*get_lineout)(struct gpio_runtime *rt); | 41 | int (*get_lineout)(struct gpio_runtime *rt); |
42 | int (*get_master)(struct gpio_runtime *rt); | ||
41 | 43 | ||
42 | void (*set_hw_reset)(struct gpio_runtime *rt, int on); | 44 | void (*set_hw_reset)(struct gpio_runtime *rt, int on); |
43 | 45 | ||
diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index c93ad5dec66b..de8e03afa97b 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include "../aoa.h" | 15 | #include "../aoa.h" |
16 | 16 | ||
17 | /* TODO: these are 20 global variables | 17 | /* TODO: these are lots of global variables |
18 | * that aren't used on most machines... | 18 | * that aren't used on most machines... |
19 | * Move them into a dynamically allocated | 19 | * Move them into a dynamically allocated |
20 | * structure and use that. | 20 | * structure and use that. |
@@ -23,6 +23,7 @@ | |||
23 | /* these are the GPIO numbers (register addresses as offsets into | 23 | /* these are the GPIO numbers (register addresses as offsets into |
24 | * the GPIO space) */ | 24 | * the GPIO space) */ |
25 | static int headphone_mute_gpio; | 25 | static int headphone_mute_gpio; |
26 | static int master_mute_gpio; | ||
26 | static int amp_mute_gpio; | 27 | static int amp_mute_gpio; |
27 | static int lineout_mute_gpio; | 28 | static int lineout_mute_gpio; |
28 | static int hw_reset_gpio; | 29 | static int hw_reset_gpio; |
@@ -32,6 +33,7 @@ static int linein_detect_gpio; | |||
32 | 33 | ||
33 | /* see the SWITCH_GPIO macro */ | 34 | /* see the SWITCH_GPIO macro */ |
34 | static int headphone_mute_gpio_activestate; | 35 | static int headphone_mute_gpio_activestate; |
36 | static int master_mute_gpio_activestate; | ||
35 | static int amp_mute_gpio_activestate; | 37 | static int amp_mute_gpio_activestate; |
36 | static int lineout_mute_gpio_activestate; | 38 | static int lineout_mute_gpio_activestate; |
37 | static int hw_reset_gpio_activestate; | 39 | static int hw_reset_gpio_activestate; |
@@ -156,6 +158,7 @@ static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ | |||
156 | FTR_GPIO(headphone, 0); | 158 | FTR_GPIO(headphone, 0); |
157 | FTR_GPIO(amp, 1); | 159 | FTR_GPIO(amp, 1); |
158 | FTR_GPIO(lineout, 2); | 160 | FTR_GPIO(lineout, 2); |
161 | FTR_GPIO(master, 3); | ||
159 | 162 | ||
160 | static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) | 163 | static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) |
161 | { | 164 | { |
@@ -172,6 +175,8 @@ static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) | |||
172 | hw_reset_gpio, v); | 175 | hw_reset_gpio, v); |
173 | } | 176 | } |
174 | 177 | ||
178 | static struct gpio_methods methods; | ||
179 | |||
175 | static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) | 180 | static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) |
176 | { | 181 | { |
177 | int saved; | 182 | int saved; |
@@ -181,6 +186,8 @@ static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) | |||
181 | ftr_gpio_set_headphone(rt, 0); | 186 | ftr_gpio_set_headphone(rt, 0); |
182 | ftr_gpio_set_amp(rt, 0); | 187 | ftr_gpio_set_amp(rt, 0); |
183 | ftr_gpio_set_lineout(rt, 0); | 188 | ftr_gpio_set_lineout(rt, 0); |
189 | if (methods.set_master) | ||
190 | ftr_gpio_set_master(rt, 0); | ||
184 | rt->implementation_private = saved; | 191 | rt->implementation_private = saved; |
185 | } | 192 | } |
186 | 193 | ||
@@ -193,6 +200,8 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) | |||
193 | ftr_gpio_set_headphone(rt, (s>>0)&1); | 200 | ftr_gpio_set_headphone(rt, (s>>0)&1); |
194 | ftr_gpio_set_amp(rt, (s>>1)&1); | 201 | ftr_gpio_set_amp(rt, (s>>1)&1); |
195 | ftr_gpio_set_lineout(rt, (s>>2)&1); | 202 | ftr_gpio_set_lineout(rt, (s>>2)&1); |
203 | if (methods.set_master) | ||
204 | ftr_gpio_set_master(rt, (s>>3)&1); | ||
196 | } | 205 | } |
197 | 206 | ||
198 | static void ftr_handle_notify(struct work_struct *work) | 207 | static void ftr_handle_notify(struct work_struct *work) |
@@ -231,6 +240,12 @@ static void ftr_gpio_init(struct gpio_runtime *rt) | |||
231 | get_gpio("hw-reset", "audio-hw-reset", | 240 | get_gpio("hw-reset", "audio-hw-reset", |
232 | &hw_reset_gpio, | 241 | &hw_reset_gpio, |
233 | &hw_reset_gpio_activestate); | 242 | &hw_reset_gpio_activestate); |
243 | if (get_gpio("master-mute", NULL, | ||
244 | &master_mute_gpio, | ||
245 | &master_mute_gpio_activestate)) { | ||
246 | methods.set_master = ftr_gpio_set_master; | ||
247 | methods.get_master = ftr_gpio_get_master; | ||
248 | } | ||
234 | 249 | ||
235 | headphone_detect_node = get_gpio("headphone-detect", NULL, | 250 | headphone_detect_node = get_gpio("headphone-detect", NULL, |
236 | &headphone_detect_gpio, | 251 | &headphone_detect_gpio, |
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index d9b1d22a62c0..fbf5c933baa4 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c | |||
@@ -600,6 +600,7 @@ struct layout_dev { | |||
600 | struct snd_kcontrol *headphone_ctrl; | 600 | struct snd_kcontrol *headphone_ctrl; |
601 | struct snd_kcontrol *lineout_ctrl; | 601 | struct snd_kcontrol *lineout_ctrl; |
602 | struct snd_kcontrol *speaker_ctrl; | 602 | struct snd_kcontrol *speaker_ctrl; |
603 | struct snd_kcontrol *master_ctrl; | ||
603 | struct snd_kcontrol *headphone_detected_ctrl; | 604 | struct snd_kcontrol *headphone_detected_ctrl; |
604 | struct snd_kcontrol *lineout_detected_ctrl; | 605 | struct snd_kcontrol *lineout_detected_ctrl; |
605 | 606 | ||
@@ -651,6 +652,7 @@ static struct snd_kcontrol_new n##_ctl = { \ | |||
651 | AMP_CONTROL(headphone, "Headphone Switch"); | 652 | AMP_CONTROL(headphone, "Headphone Switch"); |
652 | AMP_CONTROL(speakers, "Speakers Switch"); | 653 | AMP_CONTROL(speakers, "Speakers Switch"); |
653 | AMP_CONTROL(lineout, "Line-Out Switch"); | 654 | AMP_CONTROL(lineout, "Line-Out Switch"); |
655 | AMP_CONTROL(master, "Master Switch"); | ||
654 | 656 | ||
655 | static int detect_choice_get(struct snd_kcontrol *kcontrol, | 657 | static int detect_choice_get(struct snd_kcontrol *kcontrol, |
656 | struct snd_ctl_elem_value *ucontrol) | 658 | struct snd_ctl_elem_value *ucontrol) |
@@ -891,6 +893,11 @@ static void layout_attached_codec(struct aoa_codec *codec) | |||
891 | lineout = codec->gpio->methods->get_detect(codec->gpio, | 893 | lineout = codec->gpio->methods->get_detect(codec->gpio, |
892 | AOA_NOTIFY_LINE_OUT); | 894 | AOA_NOTIFY_LINE_OUT); |
893 | 895 | ||
896 | if (codec->gpio->methods->set_master) { | ||
897 | ctl = snd_ctl_new1(&master_ctl, codec->gpio); | ||
898 | ldev->master_ctrl = ctl; | ||
899 | aoa_snd_ctl_add(ctl); | ||
900 | } | ||
894 | while (cc->connected) { | 901 | while (cc->connected) { |
895 | if (cc->connected & CC_SPEAKERS) { | 902 | if (cc->connected & CC_SPEAKERS) { |
896 | if (headphones <= 0 && lineout <= 0) | 903 | if (headphones <= 0 && lineout <= 0) |