aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-03-16 17:38:46 +0100
committerTakashi Iwai <tiwai@suse.de>2011-03-16 17:38:46 +0100
commit433e8327caf9f7c0432b2f2f6684a5b79cfe18e9 (patch)
tree515e7bb9b0169fc4f8c1422ef6c926d4bd63e808 /sound/pci/hda/patch_realtek.c
parent27b92d4ff2be2359a21ff4acde5b63563ff720e2 (diff)
parentcc90fd725e14020607c5a6ba3ea02a0ddec5655f (diff)
Merge branch 'topic/hda' into for-linus
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c204
1 files changed, 79 insertions, 125 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4261bb8eec1..639d2746713 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -282,12 +282,6 @@ struct alc_mic_route {
unsigned char amix_idx;
};
-struct alc_jack {
- hda_nid_t nid;
- int type;
- struct snd_jack *jack;
-};
-
#define MUX_IDX_UNDEF ((unsigned char)-1)
struct alc_customize_define {
@@ -366,9 +360,6 @@ struct alc_spec {
/* PCM information */
struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
- /* jack detection */
- struct snd_array jacks;
-
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
struct alc_customize_define cdefine;
@@ -394,6 +385,7 @@ struct alc_spec {
/* other flags */
unsigned int no_analog :1; /* digital I/O only */
unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
+ unsigned int single_input_src:1;
int init_amp;
int codec_variant; /* flag for other variants */
@@ -1032,94 +1024,32 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
alc_fix_pll(codec);
}
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-static void alc_free_jack_priv(struct snd_jack *jack)
-{
- struct alc_jack *jacks = jack->private_data;
- jacks->nid = 0;
- jacks->jack = NULL;
-}
-
-static int alc_add_jack(struct hda_codec *codec,
- hda_nid_t nid, int type)
-{
- struct alc_spec *spec;
- struct alc_jack *jack;
- const char *name;
- int err;
-
- spec = codec->spec;
- snd_array_init(&spec->jacks, sizeof(*jack), 32);
- jack = snd_array_new(&spec->jacks);
- if (!jack)
- return -ENOMEM;
-
- jack->nid = nid;
- jack->type = type;
- name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
-
- err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
- if (err < 0)
- return err;
- jack->jack->private_data = jack;
- jack->jack->private_free = alc_free_jack_priv;
- return 0;
-}
-
-static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
- struct alc_spec *spec = codec->spec;
- struct alc_jack *jacks = spec->jacks.list;
-
- if (jacks) {
- int i;
- for (i = 0; i < spec->jacks.used; i++) {
- if (jacks->nid == nid) {
- unsigned int present;
- present = snd_hda_jack_detect(codec, nid);
-
- present = (present) ? jacks->type : 0;
-
- snd_jack_report(jacks->jack, present);
- }
- jacks++;
- }
- }
-}
-
static int alc_init_jacks(struct hda_codec *codec)
{
+#ifdef CONFIG_SND_HDA_INPUT_JACK
struct alc_spec *spec = codec->spec;
int err;
unsigned int hp_nid = spec->autocfg.hp_pins[0];
unsigned int mic_nid = spec->ext_mic.pin;
if (hp_nid) {
- err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE);
+ err = snd_hda_input_jack_add(codec, hp_nid,
+ SND_JACK_HEADPHONE, NULL);
if (err < 0)
return err;
- alc_report_jack(codec, hp_nid);
+ snd_hda_input_jack_report(codec, hp_nid);
}
if (mic_nid) {
- err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE);
+ err = snd_hda_input_jack_add(codec, mic_nid,
+ SND_JACK_MICROPHONE, NULL);
if (err < 0)
return err;
- alc_report_jack(codec, mic_nid);
+ snd_hda_input_jack_report(codec, mic_nid);
}
-
- return 0;
-}
-#else
-static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
-}
-
-static inline int alc_init_jacks(struct hda_codec *codec)
-{
+#endif /* CONFIG_SND_HDA_INPUT_JACK */
return 0;
}
-#endif
static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
{
@@ -1133,7 +1063,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
nid = spec->autocfg.hp_pins[i];
if (!nid)
break;
- alc_report_jack(codec, nid);
+ snd_hda_input_jack_report(codec, nid);
spec->jack_present |= snd_hda_jack_detect(codec, nid);
}
@@ -1240,7 +1170,7 @@ static void alc_mic_automute(struct hda_codec *codec)
AC_VERB_SET_CONNECT_SEL,
alive->mux_idx);
}
- alc_report_jack(codec, spec->ext_mic.pin);
+ snd_hda_input_jack_report(codec, spec->ext_mic.pin);
/* FIXME: analog mixer */
}
@@ -2292,13 +2222,13 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0f, 2, 0x0,
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0f, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0e, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -2309,7 +2239,6 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
{ } /* end */
};
-
static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -3919,6 +3848,8 @@ static struct hda_amp_list alc880_lg_loopbacks[] = {
* Common callbacks
*/
+static void alc_init_special_input_src(struct hda_codec *codec);
+
static int alc_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -3929,6 +3860,7 @@ static int alc_init(struct hda_codec *codec)
for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ alc_init_special_input_src(codec);
if (spec->init_hook)
spec->init_hook(codec);
@@ -4284,6 +4216,7 @@ static void alc_free(struct hda_codec *codec)
return;
alc_shutup(codec);
+ snd_hda_input_jack_free(codec);
alc_free_kctls(codec);
kfree(spec);
snd_hda_detach_beep_device(codec);
@@ -5151,7 +5084,9 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
switch (cfg->line_out_type) {
case AUTO_PIN_SPEAKER_OUT:
- return "Speaker";
+ if (cfg->line_outs == 1)
+ return "Speaker";
+ break;
case AUTO_PIN_HP_OUT:
return "Headphone";
default:
@@ -5205,16 +5140,19 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
return err;
} else {
const char *name = pfx;
- if (!name)
+ int index = i;
+ if (!name) {
name = chname[i];
+ index = 0;
+ }
err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
- name, i,
+ name, index,
HDA_COMPOSE_AMP_VAL(nid, 3, 0,
HDA_OUTPUT));
if (err < 0)
return err;
err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
- name, i,
+ name, index,
HDA_COMPOSE_AMP_VAL(nid, 3, 2,
HDA_INPUT));
if (err < 0)
@@ -5585,6 +5523,7 @@ static void fixup_single_adc(struct hda_codec *codec)
spec->capsrc_nids += i;
spec->adc_nids += i;
spec->num_adc_nids = 1;
+ spec->single_input_src = 1;
}
}
@@ -5596,6 +5535,16 @@ static void fixup_dual_adc_switch(struct hda_codec *codec)
init_capsrc_for_pin(codec, spec->int_mic.pin);
}
+/* initialize some special cases for input sources */
+static void alc_init_special_input_src(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ if (spec->dual_adc_switch)
+ fixup_dual_adc_switch(codec);
+ else if (spec->single_input_src)
+ init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
+}
+
static void set_capture_mixer(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -5611,7 +5560,7 @@ static void set_capture_mixer(struct hda_codec *codec)
int mux = 0;
int num_adcs = spec->num_adc_nids;
if (spec->dual_adc_switch)
- fixup_dual_adc_switch(codec);
+ num_adcs = 1;
else if (spec->auto_mic)
fixup_automic_adc(codec);
else if (spec->input_mux) {
@@ -5620,8 +5569,6 @@ static void set_capture_mixer(struct hda_codec *codec)
else if (spec->input_mux->num_items == 1)
fixup_single_adc(codec);
}
- if (spec->dual_adc_switch)
- num_adcs = 1;
spec->cap_mixer = caps[mux][num_adcs - 1];
}
}
@@ -10748,6 +10695,7 @@ static struct alc_config_preset alc882_presets[] = {
*/
enum {
PINFIX_ABIT_AW9D_MAX,
+ PINFIX_LENOVO_Y530,
PINFIX_PB_M5210,
PINFIX_ACER_ASPIRE_7736,
};
@@ -10762,6 +10710,14 @@ static const struct alc_fixup alc882_fixups[] = {
{ }
}
},
+ [PINFIX_LENOVO_Y530] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x15, 0x99130112 }, /* rear int speakers */
+ { 0x16, 0x99130111 }, /* subwoofer */
+ { }
+ }
+ },
[PINFIX_PB_M5210] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -10777,6 +10733,7 @@ static const struct alc_fixup alc882_fixups[] = {
static struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
+ SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
{}
@@ -10829,23 +10786,28 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
hda_nid_t pin, dac;
int i;
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
- pin = spec->autocfg.hp_pins[i];
- if (!pin)
- break;
- dac = spec->multiout.hp_nid;
- if (!dac)
- dac = spec->multiout.dac_nids[0]; /* to front */
- alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+ if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+ pin = spec->autocfg.hp_pins[i];
+ if (!pin)
+ break;
+ dac = spec->multiout.hp_nid;
+ if (!dac)
+ dac = spec->multiout.dac_nids[0]; /* to front */
+ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+ }
}
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
- pin = spec->autocfg.speaker_pins[i];
- if (!pin)
- break;
- dac = spec->multiout.extra_out_nid[0];
- if (!dac)
- dac = spec->multiout.dac_nids[0]; /* to front */
- alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+
+ if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+ pin = spec->autocfg.speaker_pins[i];
+ if (!pin)
+ break;
+ dac = spec->multiout.extra_out_nid[0];
+ if (!dac)
+ dac = spec->multiout.dac_nids[0]; /* to front */
+ alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+ }
}
}
@@ -13796,6 +13758,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
}
#define alc268_auto_init_analog_input alc882_auto_init_analog_input
+#define alc268_auto_init_input_src alc882_auto_init_input_src
/* init callback for auto-configuration model -- overriding the default init */
static void alc268_auto_init(struct hda_codec *codec)
@@ -13805,6 +13768,7 @@ static void alc268_auto_init(struct hda_codec *codec)
alc268_auto_init_hp_out(codec);
alc268_auto_init_mono_speaker_out(codec);
alc268_auto_init_analog_input(codec);
+ alc268_auto_init_input_src(codec);
alc_auto_init_digital(codec);
if (spec->unsol_event)
alc_inithook(codec);
@@ -14092,7 +14056,6 @@ static int patch_alc268(struct hda_codec *codec)
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
- int i;
spec->capsrc_nids = alc268_capsrc_nids;
/* get type */
@@ -14112,13 +14075,6 @@ static int patch_alc268(struct hda_codec *codec)
spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
add_mixer(spec, alc268_capture_mixer);
}
- /* set default input source */
- for (i = 0; i < spec->num_adc_nids; i++)
- snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
- 0, AC_VERB_SET_CONNECT_SEL,
- i < spec->num_mux_defs ?
- spec->input_mux[i].items[0].index :
- spec->input_mux->items[0].index);
}
spec->vmaster_nid = 0x02;
@@ -14495,7 +14451,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
HDA_AMP_MUTE, bits);
- alc_report_jack(codec, nid);
+ snd_hda_input_jack_report(codec, nid);
}
/* unsolicited event for HP jack sensing */
@@ -14807,11 +14763,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
fillup_priv_adc_nids(codec, alc269_adc_candidates,
sizeof(alc269_adc_candidates));
- /* set default input source */
- if (!spec->dual_adc_switch)
- select_or_unmute_capsrc(codec, spec->capsrc_nids[0],
- spec->input_mux->items[0].index);
-
err = alc_auto_add_mic_boost(codec);
if (err < 0)
return err;
@@ -14825,6 +14776,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
#define alc269_auto_init_multi_out alc268_auto_init_multi_out
#define alc269_auto_init_hp_out alc268_auto_init_hp_out
#define alc269_auto_init_analog_input alc882_auto_init_analog_input
+#define alc269_auto_init_input_src alc882_auto_init_input_src
/* init callback for auto-configuration model -- overriding the default init */
@@ -14834,6 +14786,8 @@ static void alc269_auto_init(struct hda_codec *codec)
alc269_auto_init_multi_out(codec);
alc269_auto_init_hp_out(codec);
alc269_auto_init_analog_input(codec);
+ if (!spec->dual_adc_switch)
+ alc269_auto_init_input_src(codec);
alc_auto_init_digital(codec);
if (spec->unsol_event)
alc_inithook(codec);