Commit 5f17e79c authored by Johannes Berg's avatar Johannes Berg Committed by Takashi Iwai

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: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 45e513b6
...@@ -34,10 +34,12 @@ struct gpio_methods { ...@@ -34,10 +34,12 @@ struct gpio_methods {
void (*set_headphone)(struct gpio_runtime *rt, int on); void (*set_headphone)(struct gpio_runtime *rt, int on);
void (*set_speakers)(struct gpio_runtime *rt, int on); void (*set_speakers)(struct gpio_runtime *rt, int on);
void (*set_lineout)(struct gpio_runtime *rt, int on); void (*set_lineout)(struct gpio_runtime *rt, int on);
void (*set_master)(struct gpio_runtime *rt, int on);
int (*get_headphone)(struct gpio_runtime *rt); int (*get_headphone)(struct gpio_runtime *rt);
int (*get_speakers)(struct gpio_runtime *rt); int (*get_speakers)(struct gpio_runtime *rt);
int (*get_lineout)(struct gpio_runtime *rt); int (*get_lineout)(struct gpio_runtime *rt);
int (*get_master)(struct gpio_runtime *rt);
void (*set_hw_reset)(struct gpio_runtime *rt, int on); void (*set_hw_reset)(struct gpio_runtime *rt, int on);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include "../aoa.h" #include "../aoa.h"
/* TODO: these are 20 global variables /* TODO: these are lots of global variables
* that aren't used on most machines... * that aren't used on most machines...
* Move them into a dynamically allocated * Move them into a dynamically allocated
* structure and use that. * structure and use that.
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
/* these are the GPIO numbers (register addresses as offsets into /* these are the GPIO numbers (register addresses as offsets into
* the GPIO space) */ * the GPIO space) */
static int headphone_mute_gpio; static int headphone_mute_gpio;
static int master_mute_gpio;
static int amp_mute_gpio; static int amp_mute_gpio;
static int lineout_mute_gpio; static int lineout_mute_gpio;
static int hw_reset_gpio; static int hw_reset_gpio;
...@@ -32,6 +33,7 @@ static int linein_detect_gpio; ...@@ -32,6 +33,7 @@ static int linein_detect_gpio;
/* see the SWITCH_GPIO macro */ /* see the SWITCH_GPIO macro */
static int headphone_mute_gpio_activestate; static int headphone_mute_gpio_activestate;
static int master_mute_gpio_activestate;
static int amp_mute_gpio_activestate; static int amp_mute_gpio_activestate;
static int lineout_mute_gpio_activestate; static int lineout_mute_gpio_activestate;
static int hw_reset_gpio_activestate; static int hw_reset_gpio_activestate;
...@@ -156,6 +158,7 @@ static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ ...@@ -156,6 +158,7 @@ static int ftr_gpio_get_##name(struct gpio_runtime *rt) \
FTR_GPIO(headphone, 0); FTR_GPIO(headphone, 0);
FTR_GPIO(amp, 1); FTR_GPIO(amp, 1);
FTR_GPIO(lineout, 2); FTR_GPIO(lineout, 2);
FTR_GPIO(master, 3);
static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
{ {
...@@ -172,6 +175,8 @@ static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) ...@@ -172,6 +175,8 @@ static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
hw_reset_gpio, v); hw_reset_gpio, v);
} }
static struct gpio_methods methods;
static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
{ {
int saved; int saved;
...@@ -181,6 +186,8 @@ static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) ...@@ -181,6 +186,8 @@ static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
ftr_gpio_set_headphone(rt, 0); ftr_gpio_set_headphone(rt, 0);
ftr_gpio_set_amp(rt, 0); ftr_gpio_set_amp(rt, 0);
ftr_gpio_set_lineout(rt, 0); ftr_gpio_set_lineout(rt, 0);
if (methods.set_master)
ftr_gpio_set_master(rt, 0);
rt->implementation_private = saved; rt->implementation_private = saved;
} }
...@@ -193,6 +200,8 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) ...@@ -193,6 +200,8 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
ftr_gpio_set_headphone(rt, (s>>0)&1); ftr_gpio_set_headphone(rt, (s>>0)&1);
ftr_gpio_set_amp(rt, (s>>1)&1); ftr_gpio_set_amp(rt, (s>>1)&1);
ftr_gpio_set_lineout(rt, (s>>2)&1); ftr_gpio_set_lineout(rt, (s>>2)&1);
if (methods.set_master)
ftr_gpio_set_master(rt, (s>>3)&1);
} }
static void ftr_handle_notify(struct work_struct *work) static void ftr_handle_notify(struct work_struct *work)
...@@ -231,6 +240,12 @@ static void ftr_gpio_init(struct gpio_runtime *rt) ...@@ -231,6 +240,12 @@ static void ftr_gpio_init(struct gpio_runtime *rt)
get_gpio("hw-reset", "audio-hw-reset", get_gpio("hw-reset", "audio-hw-reset",
&hw_reset_gpio, &hw_reset_gpio,
&hw_reset_gpio_activestate); &hw_reset_gpio_activestate);
if (get_gpio("master-mute", NULL,
&master_mute_gpio,
&master_mute_gpio_activestate)) {
methods.set_master = ftr_gpio_set_master;
methods.get_master = ftr_gpio_get_master;
}
headphone_detect_node = get_gpio("headphone-detect", NULL, headphone_detect_node = get_gpio("headphone-detect", NULL,
&headphone_detect_gpio, &headphone_detect_gpio,
......
...@@ -600,6 +600,7 @@ struct layout_dev { ...@@ -600,6 +600,7 @@ struct layout_dev {
struct snd_kcontrol *headphone_ctrl; struct snd_kcontrol *headphone_ctrl;
struct snd_kcontrol *lineout_ctrl; struct snd_kcontrol *lineout_ctrl;
struct snd_kcontrol *speaker_ctrl; struct snd_kcontrol *speaker_ctrl;
struct snd_kcontrol *master_ctrl;
struct snd_kcontrol *headphone_detected_ctrl; struct snd_kcontrol *headphone_detected_ctrl;
struct snd_kcontrol *lineout_detected_ctrl; struct snd_kcontrol *lineout_detected_ctrl;
...@@ -651,6 +652,7 @@ static struct snd_kcontrol_new n##_ctl = { \ ...@@ -651,6 +652,7 @@ static struct snd_kcontrol_new n##_ctl = { \
AMP_CONTROL(headphone, "Headphone Switch"); AMP_CONTROL(headphone, "Headphone Switch");
AMP_CONTROL(speakers, "Speakers Switch"); AMP_CONTROL(speakers, "Speakers Switch");
AMP_CONTROL(lineout, "Line-Out Switch"); AMP_CONTROL(lineout, "Line-Out Switch");
AMP_CONTROL(master, "Master Switch");
static int detect_choice_get(struct snd_kcontrol *kcontrol, static int detect_choice_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
...@@ -891,6 +893,11 @@ static void layout_attached_codec(struct aoa_codec *codec) ...@@ -891,6 +893,11 @@ static void layout_attached_codec(struct aoa_codec *codec)
lineout = codec->gpio->methods->get_detect(codec->gpio, lineout = codec->gpio->methods->get_detect(codec->gpio,
AOA_NOTIFY_LINE_OUT); AOA_NOTIFY_LINE_OUT);
if (codec->gpio->methods->set_master) {
ctl = snd_ctl_new1(&master_ctl, codec->gpio);
ldev->master_ctrl = ctl;
aoa_snd_ctl_add(ctl);
}
while (cc->connected) { while (cc->connected) {
if (cc->connected & CC_SPEAKERS) { if (cc->connected & CC_SPEAKERS) {
if (headphones <= 0 && lineout <= 0) if (headphones <= 0 && lineout <= 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment