aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c1051
1 files changed, 761 insertions, 290 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 70583719282..3f92def752f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -131,8 +131,8 @@ enum {
enum {
ALC269_BASIC,
ALC269_QUANTA_FL1,
- ALC269_ASUS_EEEPC_P703,
- ALC269_ASUS_EEEPC_P901,
+ ALC269_ASUS_AMIC,
+ ALC269_ASUS_DMIC,
ALC269_FUJITSU,
ALC269_LIFEBOOK,
ALC269_AUTO,
@@ -188,6 +188,8 @@ enum {
ALC663_ASUS_MODE4,
ALC663_ASUS_MODE5,
ALC663_ASUS_MODE6,
+ ALC663_ASUS_MODE7,
+ ALC663_ASUS_MODE8,
ALC272_DELL,
ALC272_DELL_ZM1,
ALC272_SAMSUNG_NC10,
@@ -208,6 +210,7 @@ enum {
ALC885_MBP3,
ALC885_MB5,
ALC885_IMAC24,
+ ALC885_IMAC91,
ALC883_3ST_2ch_DIG,
ALC883_3ST_6ch_DIG,
ALC883_3ST_6ch,
@@ -334,6 +337,9 @@ struct alc_spec {
/* hooks */
void (*init_hook)(struct hda_codec *codec);
void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ void (*power_hook)(struct hda_codec *codec, int power);
+#endif
/* for pin sensing */
unsigned int sense_updated: 1;
@@ -385,6 +391,7 @@ struct alc_config_preset {
void (*init_hook)(struct hda_codec *);
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_amp_list *loopbacks;
+ void (*power_hook)(struct hda_codec *codec, int power);
#endif
};
@@ -897,6 +904,7 @@ static void setup_preset(struct hda_codec *codec,
spec->unsol_event = preset->unsol_event;
spec->init_hook = preset->init_hook;
#ifdef CONFIG_SND_HDA_POWER_SAVE
+ spec->power_hook = preset->power_hook;
spec->loopback.amplist = preset->loopbacks;
#endif
@@ -961,18 +969,12 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
static void alc_automute_pin(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int present, pincap;
unsigned int nid = spec->autocfg.hp_pins[0];
int i;
if (!nid)
return;
- pincap = snd_hda_query_pin_caps(codec, nid);
- if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
- snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
- present = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
+ spec->jack_present = snd_hda_jack_detect(codec, nid);
for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
nid = spec->autocfg.speaker_pins[i];
if (!nid)
@@ -1012,9 +1014,7 @@ static void alc_mic_automute(struct hda_codec *codec)
cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
- present = snd_hda_codec_read(codec, spec->ext_mic.pin, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- present &= AC_PINSENSE_PRESENCE;
+ present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
if (present) {
alive = &spec->ext_mic;
dead = &spec->int_mic;
@@ -1230,6 +1230,8 @@ static void alc_init_auto_mic(struct hda_codec *codec)
return; /* invalid entry */
}
}
+ if (!ext || !fixed)
+ return;
if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
return; /* no unsol support */
snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n",
@@ -1402,6 +1404,17 @@ static void alc_pick_fixup(struct hda_codec *codec,
add_verb(codec->spec, fix->verbs);
}
+static int alc_read_coef_idx(struct hda_codec *codec,
+ unsigned int coef_idx)
+{
+ unsigned int val;
+ snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
+ coef_idx);
+ val = snd_hda_codec_read(codec, 0x20, 0,
+ AC_VERB_GET_PROC_COEF, 0);
+ return val;
+}
+
/*
* ALC888
*/
@@ -1513,7 +1526,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
static void alc_automute_amp(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int val, mute, pincap;
+ unsigned int mute;
hda_nid_t nid;
int i;
@@ -1522,13 +1535,7 @@ static void alc_automute_amp(struct hda_codec *codec)
nid = spec->autocfg.hp_pins[i];
if (!nid)
break;
- pincap = snd_hda_query_pin_caps(codec, nid);
- if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
- snd_hda_codec_read(codec, nid, 0,
- AC_VERB_SET_PIN_SENSE, 0);
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- if (val & AC_PINSENSE_PRESENCE) {
+ if (snd_hda_jack_detect(codec, nid)) {
spec->jack_present = 1;
break;
}
@@ -1665,9 +1672,6 @@ static struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
/* some bit here disables the other DACs. Init=0x4900 */
{0x20, AC_VERB_SET_COEF_INDEX, 0x08},
{0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/* Enable amplifiers */
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
/* DMIC fix
* This laptop has a stereo digital microphone. The mics are only 1cm apart
* which makes the stereo useless. However, either the mic or the ALC889
@@ -1780,12 +1784,33 @@ static struct snd_kcontrol_new alc888_base_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),
+ 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", 0x0e, 1, 0x0,
+ HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+
static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->autocfg.speaker_pins[2] = 0x17;
}
static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
@@ -1808,6 +1833,16 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[2] = 0x1b;
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void alc889_power_eapd(struct hda_codec *codec, int power)
+{
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+ snd_hda_codec_write(codec, 0x15, 0,
+ AC_VERB_SET_EAPD_BTLENABLE, power ? 2 : 0);
+}
+#endif
+
/*
* ALC880 3-stack model
*
@@ -2401,6 +2436,8 @@ static const char *alc_slave_sws[] = {
"Speaker Playback Switch",
"Mono Playback Switch",
"IEC958 Playback Switch",
+ "Line-Out Playback Switch",
+ "PCM Playback Switch",
NULL,
};
@@ -2410,12 +2447,14 @@ static const char *alc_slave_sws[] = {
static void alc_free_kctls(struct hda_codec *codec);
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* additional beep mixers; the actual parameters are overwritten at build */
static struct snd_kcontrol_new alc_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Beep Playback Switch", 0, 0, HDA_INPUT),
+ HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
{ } /* end */
};
+#endif
static int alc_build_controls(struct hda_codec *codec)
{
@@ -2452,6 +2491,7 @@ static int alc_build_controls(struct hda_codec *codec)
return err;
}
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
/* create beep controls if needed */
if (spec->beep_amp) {
struct snd_kcontrol_new *knew;
@@ -2461,11 +2501,13 @@ static int alc_build_controls(struct hda_codec *codec)
if (!kctl)
return -ENOMEM;
kctl->private_value = spec->beep_amp;
- err = snd_hda_ctl_add(codec, kctl);
+ err = snd_hda_ctl_add(codec,
+ get_amp_nid_(spec->beep_amp), kctl);
if (err < 0)
return err;
}
}
+#endif
/* if we have no master control, let's create it */
if (!spec->no_analog &&
@@ -2779,8 +2821,7 @@ static void alc880_uniwill_mic_automute(struct hda_codec *codec)
unsigned int present;
unsigned char bits;
- present = snd_hda_codec_read(codec, 0x18, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ present = snd_hda_jack_detect(codec, 0x18);
bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
}
@@ -3480,7 +3521,7 @@ static int alc_build_pcms(struct hda_codec *codec)
snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
"%s Analog", codec->chip_name);
info->name = spec->stream_name_analog;
-
+
if (spec->stream_analog_playback) {
if (snd_BUG_ON(!spec->multiout.dac_nids))
return -EINVAL;
@@ -3595,12 +3636,29 @@ static void alc_free(struct hda_codec *codec)
snd_hda_detach_beep_device(codec);
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc_suspend(struct hda_codec *codec, pm_message_t state)
+{
+ struct alc_spec *spec = codec->spec;
+ if (spec && spec->power_hook)
+ spec->power_hook(codec, 0);
+ return 0;
+}
+#endif
+
#ifdef SND_HDA_NEEDS_RESUME
static int alc_resume(struct hda_codec *codec)
{
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ struct alc_spec *spec = codec->spec;
+#endif
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (spec && spec->power_hook)
+ spec->power_hook(codec, 1);
+#endif
return 0;
}
#endif
@@ -3617,6 +3675,7 @@ static struct hda_codec_ops alc_patch_ops = {
.resume = alc_resume,
#endif
#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .suspend = alc_suspend,
.check_power_status = alc_check_power_status,
#endif
};
@@ -4322,10 +4381,26 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
+ if (get_amp_nid_(val))
+ knew->subdevice = HDA_SUBDEV_NID_FLAG | get_amp_nid_(val);
knew->private_value = val;
return 0;
}
+static int add_control_with_pfx(struct alc_spec *spec, int type,
+ const char *pfx, const char *dir,
+ const char *sfx, unsigned long val)
+{
+ char name[32];
+ snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
+ return add_control(spec, type, name, val);
+}
+
+#define add_pb_vol_ctrl(spec, type, pfx, val) \
+ add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val)
+#define add_pb_sw_ctrl(spec, type, pfx, val) \
+ add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val)
+
#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
@@ -4379,7 +4454,6 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
const struct auto_pin_cfg *cfg)
{
- char name[32];
static const char *chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
@@ -4392,26 +4466,26 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
if (i == 2) {
/* Center/LFE */
- err = add_control(spec, ALC_CTL_WIDGET_VOL,
- "Center Playback Volume",
+ err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
+ "Center",
HDA_COMPOSE_AMP_VAL(nid, 1, 0,
HDA_OUTPUT));
if (err < 0)
return err;
- err = add_control(spec, ALC_CTL_WIDGET_VOL,
- "LFE Playback Volume",
+ err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
+ "LFE",
HDA_COMPOSE_AMP_VAL(nid, 2, 0,
HDA_OUTPUT));
if (err < 0)
return err;
- err = add_control(spec, ALC_CTL_BIND_MUTE,
- "Center Playback Switch",
+ err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
+ "Center",
HDA_COMPOSE_AMP_VAL(nid, 1, 2,
HDA_INPUT));
if (err < 0)
return err;
- err = add_control(spec, ALC_CTL_BIND_MUTE,
- "LFE Playback Switch",
+ err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
+ "LFE",
HDA_COMPOSE_AMP_VAL(nid, 2, 2,
HDA_INPUT));
if (err < 0)
@@ -4423,14 +4497,12 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
pfx = "Speaker";
else
pfx = chname[i];
- sprintf(name, "%s Playback Volume", pfx);
- err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+ err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
HDA_COMPOSE_AMP_VAL(nid, 3, 0,
HDA_OUTPUT));
if (err < 0)
return err;
- sprintf(name, "%s Playback Switch", pfx);
- err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+ err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
HDA_COMPOSE_AMP_VAL(nid, 3, 2,
HDA_INPUT));
if (err < 0)
@@ -4446,7 +4518,6 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
{
hda_nid_t nid;
int err;
- char name[32];
if (!pin)
return 0;
@@ -4460,21 +4531,18 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
spec->multiout.extra_out_nid[0] = nid;
/* control HP volume/switch on the output mixer amp */
nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
- sprintf(name, "%s Playback Volume", pfx);
- err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+ err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
- sprintf(name, "%s Playback Switch", pfx);
- err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+ err = add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, pfx,
HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
if (err < 0)
return err;
} else if (alc880_is_multi_pin(pin)) {
/* set manual connection */
/* we have only a switch on HP-out PIN */
- sprintf(name, "%s Playback Switch", pfx);
- err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+ err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
@@ -4487,16 +4555,13 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
const char *ctlname,
int idx, hda_nid_t mix_nid)
{
- char name[32];
int err;
- sprintf(name, "%s Playback Volume", ctlname);
- err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+ err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
if (err < 0)
return err;
- sprintf(name, "%s Playback Switch", ctlname);
- err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+ err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
if (err < 0)
return err;
@@ -4749,6 +4814,49 @@ static void fixup_automic_adc(struct hda_codec *codec)
spec->auto_mic = 0; /* disable auto-mic to be sure */
}
+/* choose the ADC/MUX containing the input pin and initialize the setup */
+static void fixup_single_adc(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t pin;
+ int i;
+
+ /* search for the input pin; there must be only one */
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ if (spec->autocfg.input_pins[i]) {
+ pin = spec->autocfg.input_pins[i];
+ break;
+ }
+ }
+ if (!pin)
+ return;
+
+ /* set the default connection to that pin */
+ for (i = 0; i < spec->num_adc_nids; i++) {
+ hda_nid_t cap = spec->capsrc_nids ?
+ spec->capsrc_nids[i] : spec->adc_nids[i];
+ int idx;
+
+ idx = get_connection_index(codec, cap, pin);
+ if (idx < 0)
+ continue;
+ /* use only this ADC */
+ if (spec->capsrc_nids)
+ spec->capsrc_nids += i;
+ spec->adc_nids += i;
+ spec->num_adc_nids = 1;
+ /* select or unmute this route */
+ if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) {
+ snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx,
+ HDA_AMP_MUTE, 0);
+ } else {
+ snd_hda_codec_write_cache(codec, cap, 0,
+ AC_VERB_SET_CONNECT_SEL, idx);
+ }
+ return;
+ }
+}
+
static void set_capture_mixer(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -4761,20 +4869,25 @@ static void set_capture_mixer(struct hda_codec *codec)
alc_capture_mixer3 },
};
if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) {
- int mux;
- if (spec->auto_mic) {
- mux = 0;
+ int mux = 0;
+ if (spec->auto_mic)
fixup_automic_adc(codec);
- } else if (spec->input_mux && spec->input_mux->num_items > 1)
- mux = 1;
- else
- mux = 0;
+ else if (spec->input_mux) {
+ if (spec->input_mux->num_items > 1)
+ mux = 1;
+ else if (spec->input_mux->num_items == 1)
+ fixup_single_adc(codec);
+ }
spec->cap_mixer = caps[mux][spec->num_adc_nids - 1];
}
}
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
#define set_beep_amp(spec, nid, idx, dir) \
((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
+#else
+#define set_beep_amp(spec, nid, idx, dir) /* NOP */
+#endif
/*
* OK, here we have finally the patch for ALC880
@@ -5087,11 +5200,8 @@ static struct hda_verb alc260_hp_unsol_verbs[] = {
static void alc260_hp_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int present;
- present = snd_hda_codec_read(codec, 0x10, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
+ spec->jack_present = snd_hda_jack_detect(codec, 0x10);
alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
}
@@ -5156,11 +5266,8 @@ static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
static void alc260_hp_3013_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int present;
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0);
- spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
+ spec->jack_present = snd_hda_jack_detect(codec, 0x15);
alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
}
@@ -5173,12 +5280,8 @@ static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
static void alc260_hp_3012_automute(struct hda_codec *codec)
{
- unsigned int present, bits;
-
- present = snd_hda_codec_read(codec, 0x10, 0,
- AC_VERB_GET_PIN_SENSE, 0) & AC_PINSENSE_PRESENCE;
+ unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
- bits = present ? 0 : PIN_OUT;
snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
bits);
snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
@@ -5748,8 +5851,7 @@ static void alc260_replacer_672v_automute(struct hda_codec *codec)
unsigned int present;
/* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
- present = snd_hda_codec_read(codec, 0x0f, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ present = snd_hda_jack_detect(codec, 0x0f);
if (present) {
snd_hda_codec_write_cache(codec, 0x01, 0,
AC_VERB_SET_GPIO_DATA, 1);
@@ -5989,7 +6091,6 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
{
hda_nid_t nid_vol;
unsigned long vol_val, sw_val;
- char name[32];
int err;
if (nid >= 0x0f && nid < 0x11) {
@@ -6009,14 +6110,12 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
if (!(*vol_bits & (1 << nid_vol))) {
/* first control for the volume widget */
- snprintf(name, sizeof(name), "%s Playback Volume", pfx);
- err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);
+ err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, vol_val);
if (err < 0)
return err;
*vol_bits |= (1 << nid_vol);
}
- snprintf(name, sizeof(name), "%s Playback Switch", pfx);
- err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);
+ err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, sw_val);
if (err < 0)
return err;
return 1;
@@ -6246,6 +6345,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = {
static struct snd_pci_quirk alc260_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
+ SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
@@ -6619,7 +6719,7 @@ static struct hda_input_mux alc889A_mb31_capture_source = {
/* Front Mic (0x01) unused */
{ "Line", 0x2 },
/* Line 2 (0x03) unused */
- /* CD (0x04) unsused? */
+ /* CD (0x04) unused? */
},
};
@@ -7040,8 +7140,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("HP Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("HP Playback Switch", 0x0f, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
@@ -7051,6 +7151,20 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc885_imac91_mixer[] = {
+ HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
+ HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x00, HDA_INPUT),
+ { } /* end */
+};
+
+
static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -7336,8 +7450,8 @@ static struct snd_kcontrol_new alc882_macpro_mixer[] = {
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
/* FIXME: this looks suspicious...
- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
*/
{ } /* end */
};
@@ -7428,6 +7542,7 @@ static struct hda_verb alc885_mb5_init_verbs[] = {
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
/* Front Mic pin: input vref at 80% */
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
@@ -7506,6 +7621,66 @@ static struct hda_verb alc885_mbp3_init_verbs[] = {
{ }
};
+/* iMac 9,1 */
+static struct hda_verb alc885_imac91_init_verbs[] = {
+ /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* Rear mixer */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* HP Pin: output 0 (0x0c) */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ /* Internal Speakers: output 0 (0x0d) */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Mic (rear) pin: input vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Front Mic pin: input vref at 80% */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Line In pin: use output 1 when in LineOut mode */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+ /* FIXME: use matrix-type input source selection */
+ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+ /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* Input mixer2 */
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* Input mixer3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* ADC1: mute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* ADC2: mute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* ADC3: mute amp left and right */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+ { }
+};
+
/* iMac 24 mixer. */
static struct snd_kcontrol_new alc885_imac24_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
@@ -7552,6 +7727,47 @@ static void alc885_mbp3_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
}
+static void alc885_mb5_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+
+}
+
+static void alc885_mb5_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ /* Headphone insertion or removal. */
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc885_mb5_automute(codec);
+}
+
+static void alc885_imac91_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+ snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
+
+}
+
+static void alc885_imac91_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ /* Headphone insertion or removal. */
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc885_imac91_automute(codec);
+}
static struct hda_verb alc882_targa_verbs[] = {
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -8184,12 +8400,8 @@ static void alc883_mitac_setup(struct hda_codec *codec)
/*
static void alc883_mitac_mic_automute(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
+ unsigned char bits = snd_hda_jack_detect(codec, 0x18) ? HDA_AMP_MUTE : 0;
- present = snd_hda_codec_read(codec, 0x18, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
}
*/
@@ -8411,10 +8623,8 @@ static struct hda_channel_mode alc888_3st_hp_modes[3] = {
/* toggle front-jack and RCA according to the hp-jack state */
static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
{
- unsigned int present;
+ unsigned int present = snd_hda_jack_detect(codec, 0x1b);
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
@@ -8424,10 +8634,8 @@ static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
/* toggle RCA according to the front-jack state */
static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
{
- unsigned int present;
+ unsigned int present = snd_hda_jack_detect(codec, 0x14);
- present = snd_hda_codec_read(codec, 0x14, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
@@ -8468,8 +8676,7 @@ static void alc883_clevo_m720_mic_automute(struct hda_codec *codec)
{
unsigned int present;
- present = snd_hda_codec_read(codec, 0x18, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ present = snd_hda_jack_detect(codec, 0x18);
snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
@@ -8520,24 +8727,16 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
+ int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
- present = snd_hda_codec_read(codec, 0x14, 0, AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
HDA_AMP_MUTE, bits);
}
static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
+ int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
- present = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
HDA_AMP_MUTE, bits);
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
@@ -8688,8 +8887,7 @@ static void alc889A_mb31_automute(struct hda_codec *codec)
/* Mute only in 2ch or 4ch mode */
if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
== 0x00) {
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0) & AC_PINSENSE_PRESENCE;
+ present = snd_hda_jack_detect(codec, 0x15);
snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
@@ -8737,6 +8935,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {
[ALC885_MB5] = "mb5",
[ALC885_MBP3] = "mbp3",
[ALC885_IMAC24] = "imac24",
+ [ALC885_IMAC91] = "imac91",
[ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
[ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
[ALC883_3ST_6ch] = "3stack-6ch",
@@ -8839,7 +9038,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
- SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
@@ -8910,6 +9109,7 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
+ SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
/* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
* so apparently no perfect solution yet
@@ -8994,6 +9194,8 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &mb5_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
+ .unsol_event = alc885_mb5_unsol_event,
+ .init_hook = alc885_mb5_automute,
},
[ALC885_MACPRO] = {
.mixers = { alc882_macpro_mixer },
@@ -9021,6 +9223,20 @@ static struct alc_config_preset alc882_presets[] = {
.setup = alc885_imac24_setup,
.init_hook = alc885_imac24_init_hook,
},
+ [ALC885_IMAC91] = {
+ .mixers = { alc885_imac91_mixer, alc882_chmode_mixer },
+ .init_verbs = { alc885_imac91_init_verbs,
+ alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .dac_nids = alc882_dac_nids,
+ .channel_mode = alc885_mbp_4ch_modes,
+ .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
+ .input_mux = &alc882_capture_source,
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .dig_in_nid = ALC882_DIGIN_NID,
+ .unsol_event = alc885_imac91_unsol_event,
+ .init_hook = alc885_imac91_automute,
+ },
[ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
.init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
@@ -9187,6 +9403,7 @@ static struct alc_config_preset alc882_presets[] = {
.dac_nids = alc883_dac_nids,
.adc_nids = alc883_adc_nids_alt,
.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+ .capsrc_nids = alc883_capsrc_nids,
.dig_out_nid = ALC883_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
@@ -9283,10 +9500,11 @@ static struct alc_config_preset alc882_presets[] = {
.init_hook = alc_automute_amp,
},
[ALC888_ACER_ASPIRE_8930G] = {
- .mixers = { alc888_base_mixer,
+ .mixers = { alc889_acer_aspire_8930g_mixer,
alc883_chmode_mixer },
.init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
- alc889_acer_aspire_8930g_verbs },
+ alc889_acer_aspire_8930g_verbs,
+ alc889_eapd_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
@@ -9303,6 +9521,9 @@ static struct alc_config_preset alc882_presets[] = {
.unsol_event = alc_automute_amp_unsol_event,
.setup = alc889_acer_aspire_8930g_setup,
.init_hook = alc_automute_amp,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ .power_hook = alc889_power_eapd,
+#endif
},
[ALC888_ACER_ASPIRE_7730G] = {
.mixers = { alc883_3ST_6ch_mixer,
@@ -9333,6 +9554,7 @@ static struct alc_config_preset alc882_presets[] = {
.dac_nids = alc883_dac_nids,
.adc_nids = alc883_adc_nids_alt,
.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+ .capsrc_nids = alc883_capsrc_nids,
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
@@ -9394,6 +9616,7 @@ static struct alc_config_preset alc882_presets[] = {
.dac_nids = alc883_dac_nids,
.adc_nids = alc883_adc_nids_alt,
.num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
+ .capsrc_nids = alc883_capsrc_nids,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_lenovo_101e_capture_source,
@@ -9573,6 +9796,7 @@ static struct alc_config_preset alc882_presets[] = {
alc880_gpio1_init_verbs },
.adc_nids = alc883_adc_nids,
.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .capsrc_nids = alc883_capsrc_nids,
.dac_nids = alc883_dac_nids,
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.channel_mode = alc889A_mb31_6ch_modes,
@@ -9927,10 +10151,12 @@ static int patch_alc882(struct hda_codec *codec)
spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */
if (!spec->adc_nids && spec->input_mux) {
- int i;
+ int i, j;
spec->num_adc_nids = 0;
for (i = 0; i < ARRAY_SIZE(alc882_adc_nids); i++) {
+ const struct hda_input_mux *imux = spec->input_mux;
hda_nid_t cap;
+ hda_nid_t items[16];
hda_nid_t nid = alc882_adc_nids[i];
unsigned int wcap = get_wcaps(codec, nid);
/* get type */
@@ -9941,6 +10167,15 @@ static int patch_alc882(struct hda_codec *codec)
err = snd_hda_get_connections(codec, nid, &cap, 1);
if (err < 0)
continue;
+ err = snd_hda_get_connections(codec, cap, items,
+ ARRAY_SIZE(items));
+ if (err < 0)
+ continue;
+ for (j = 0; j < imux->num_items; j++)
+ if (imux->items[j].index >= err)
+ break;
+ if (j < imux->num_items)
+ continue;
spec->private_capsrc_nids[spec->num_adc_nids] = cap;
spec->num_adc_nids++;
}
@@ -10032,10 +10267,8 @@ static void alc262_hp_master_update(struct