summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/HD-Audio-Models.txt2
-rw-r--r--sound/pci/hda/hda_codec.c76
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_intel.c14
-rw-r--r--sound/pci/hda/patch_analog.c12
-rw-r--r--sound/pci/hda/patch_realtek.c2414
-rw-r--r--sound/pci/hda/patch_sigmatel.c9
-rw-r--r--sound/pci/hda/patch_via.c1245
8 files changed, 1981 insertions, 1793 deletions
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 0caf77e59be4..d70c93bdcadf 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -94,7 +94,7 @@ ALC662/663/272
3stack-dig 3-stack (2-channel) with SPDIF
3stack-6ch 3-stack (6-channel)
3stack-6ch-dig 3-stack (6-channel) with SPDIF
- 6stack-dig 6-stack with SPDIF
+ 5stack-dig 5-stack with SPDIF
lenovo-101e Lenovo laptop
eeepc-p701 ASUS Eeepc P701
eeepc-ep20 ASUS Eeepc EP20
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 759ade12e758..2c40e415852b 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -307,6 +307,12 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
}
EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
+static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *conn_list, int max_conns);
+static bool add_conn_list(struct snd_array *array, hda_nid_t nid);
+static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst,
+ hda_nid_t *src, int len);
+
/**
* snd_hda_get_connections - get connection list
* @codec: the HDA codec
@@ -320,7 +326,44 @@ EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
* Returns the number of connections, or a negative error code.
*/
int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
- hda_nid_t *conn_list, int max_conns)
+ hda_nid_t *conn_list, int max_conns)
+{
+ struct snd_array *array = &codec->conn_lists;
+ int i, len, old_used;
+ hda_nid_t list[HDA_MAX_CONNECTIONS];
+
+ /* look up the cached results */
+ for (i = 0; i < array->used; ) {
+ hda_nid_t *p = snd_array_elem(array, i);
+ len = p[1];
+ if (nid == *p)
+ return copy_conn_list(nid, conn_list, max_conns,
+ p + 2, len);
+ i += len + 2;
+ }
+
+ len = _hda_get_connections(codec, nid, list, HDA_MAX_CONNECTIONS);
+ if (len < 0)
+ return len;
+
+ /* add to the cache */
+ old_used = array->used;
+ if (!add_conn_list(array, nid) || !add_conn_list(array, len))
+ goto error_add;
+ for (i = 0; i < len; i++)
+ if (!add_conn_list(array, list[i]))
+ goto error_add;
+
+ return copy_conn_list(nid, conn_list, max_conns, list, len);
+
+ error_add:
+ array->used = old_used;
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+
+static int _hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+ hda_nid_t *conn_list, int max_conns)
{
unsigned int parm;
int i, conn_len, conns;
@@ -417,8 +460,28 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
}
return conns;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+static bool add_conn_list(struct snd_array *array, hda_nid_t nid)
+{
+ hda_nid_t *p = snd_array_new(array);
+ if (!p)
+ return false;
+ *p = nid;
+ return true;
+}
+
+static int copy_conn_list(hda_nid_t nid, hda_nid_t *dst, int max_dst,
+ hda_nid_t *src, int len)
+{
+ if (len > max_dst) {
+ snd_printk(KERN_ERR "hda_codec: "
+ "Too many connections %d for NID 0x%x\n",
+ len, nid);
+ return -EINVAL;
+ }
+ memcpy(dst, src, len * sizeof(hda_nid_t));
+ return len;
+}
/**
* snd_hda_queue_unsol_event - add an unsolicited event to queue
@@ -1019,6 +1082,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
list_del(&codec->list);
snd_array_free(&codec->mixers);
snd_array_free(&codec->nids);
+ snd_array_free(&codec->conn_lists);
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
@@ -1079,6 +1143,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
+ snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64);
if (codec->bus->modelname) {
codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
if (!codec->modelname) {
@@ -4632,10 +4697,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
/*
* debug prints of the parsed results
*/
- snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+ snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
cfg->line_out_pins[2], cfg->line_out_pins[3],
- cfg->line_out_pins[4]);
+ cfg->line_out_pins[4],
+ cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
+ (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
+ "speaker" : "line"));
snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
cfg->speaker_outs, cfg->speaker_pins[0],
cfg->speaker_pins[1], cfg->speaker_pins[2],
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index e46d5420a9f2..7d57a66c1b31 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -825,6 +825,8 @@ struct hda_codec {
struct hda_cache_rec amp_cache; /* cache for amp access */
struct hda_cache_rec cmd_cache; /* cache for other commands */
+ struct snd_array conn_lists; /* connection-list array */
+
struct mutex spdif_mutex;
struct mutex control_mutex;
unsigned int spdif_status; /* IEC958 status bits */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 70a9d32f0e96..f95ff6e029a9 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -126,6 +126,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH10},"
"{Intel, PCH},"
"{Intel, CPT},"
+ "{Intel, PPT},"
"{Intel, PBG},"
"{Intel, SCH},"
"{ATI, SB450},"
@@ -1446,6 +1447,17 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
}
}
+ /* AMD chipsets often cause the communication stalls upon certain
+ * sequence like the pin-detection. It seems that forcing the synced
+ * access works around the stall. Grrr...
+ */
+ if (chip->pci->vendor == PCI_VENDOR_ID_AMD ||
+ chip->pci->vendor == PCI_VENDOR_ID_ATI) {
+ snd_printk(KERN_INFO SFX "Enable sync_write for AMD chipset\n");
+ chip->bus->sync_write = 1;
+ chip->bus->allow_bus_reset = 1;
+ }
+
/* Then create codec instances */
for (c = 0; c < max_slots; c++) {
if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
@@ -2759,6 +2771,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
+ /* Panther Point */
+ { PCI_DEVICE(0x8086, 0x1e20), .driver_data = AZX_DRIVER_PCH },
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
/* Generic Intel */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 2942d2a9ea10..12317488cd98 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -489,11 +489,6 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return 0;
}
-static inline void ad198x_shutup(struct hda_codec *codec)
-{
- snd_hda_shutup_pins(codec);
-}
-
static void ad198x_free_kctls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -547,6 +542,12 @@ static void ad198x_power_eapd(struct hda_codec *codec)
}
}
+static void ad198x_shutup(struct hda_codec *codec)
+{
+ snd_hda_shutup_pins(codec);
+ ad198x_power_eapd(codec);
+}
+
static void ad198x_free(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -564,7 +565,6 @@ static void ad198x_free(struct hda_codec *codec)
static int ad198x_suspend(struct hda_codec *codec, pm_message_t state)
{
ad198x_shutup(codec);
- ad198x_power_eapd(codec);
return 0;
}
#endif
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3091e0c8ed08..46959159a77e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -299,6 +299,18 @@ struct alc_customize_define {
struct alc_fixup;
+struct alc_multi_io {
+ hda_nid_t pin; /* multi-io widget pin NID */
+ hda_nid_t dac; /* DAC to be connected */
+ unsigned int ctl_in; /* cached input-pin control value */
+};
+
+enum {
+ ALC_AUTOMUTE_PIN, /* change the pin control */
+ ALC_AUTOMUTE_AMP, /* mute/unmute the pin AMP */
+ ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
+};
+
struct alc_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
@@ -375,17 +387,27 @@ struct alc_spec {
#ifdef CONFIG_SND_HDA_POWER_SAVE
void (*power_hook)(struct hda_codec *codec);
#endif
+ void (*shutup)(struct hda_codec *codec);
/* for pin sensing */
- unsigned int sense_updated: 1;
unsigned int jack_present: 1;
- unsigned int master_sw: 1;
+ unsigned int line_jack_present:1;
+ unsigned int master_mute:1;
unsigned int auto_mic:1;
+ unsigned int automute:1; /* HP automute enabled */
+ unsigned int detect_line:1; /* Line-out detection enabled */
+ unsigned int automute_lines:1; /* automute line-out as well */
+ unsigned int automute_hp_lo:1; /* both HP and LO available */
/* 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;
+
+ /* auto-mute control */
+ int automute_mode;
+ hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
+
int init_amp;
int codec_variant; /* flag for other variants */
@@ -403,6 +425,10 @@ struct alc_spec {
int fixup_id;
const struct alc_fixup *fixup_list;
const char *fixup_name;
+
+ /* multi-io */
+ int multi_ios;
+ struct alc_multi_io multi_io[4];
};
/*
@@ -1051,42 +1077,105 @@ static int alc_init_jacks(struct hda_codec *codec)
return 0;
}
-static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
+static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
{
- struct alc_spec *spec = codec->spec;
- unsigned int mute;
- hda_nid_t nid;
- int i;
+ int i, present = 0;
- spec->jack_present = 0;
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
- nid = spec->autocfg.hp_pins[i];
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t nid = pins[i];
if (!nid)
break;
snd_hda_input_jack_report(codec, nid);
- spec->jack_present |= snd_hda_jack_detect(codec, nid);
+ present |= snd_hda_jack_detect(codec, nid);
}
+ return present;
+}
- mute = spec->jack_present ? HDA_AMP_MUTE : 0;
- /* Toggle internal speakers muting */
- for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
- nid = spec->autocfg.speaker_pins[i];
+static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
+ bool mute, bool hp_out)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
+ unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
+ int i;
+
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t nid = pins[i];
if (!nid)
break;
- if (pinctl) {
+ switch (spec->automute_mode) {
+ case ALC_AUTOMUTE_PIN:
snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->jack_present ? 0 : PIN_OUT);
- } else {
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pin_bits);
+ break;
+ case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
+ HDA_AMP_MUTE, mute_bits);
+ break;
+ case ALC_AUTOMUTE_MIXER:
+ nid = spec->automute_mixer_nid[i];
+ if (!nid)
+ break;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+ HDA_AMP_MUTE, mute_bits);
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
+ HDA_AMP_MUTE, mute_bits);
+ break;
}
}
}
-static void alc_automute_pin(struct hda_codec *codec)
+/* Toggle internal speakers muting */
+static void update_speakers(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int on;
+
+ if (!spec->automute)
+ on = 0;
+ else
+ on = spec->jack_present | spec->line_jack_present;
+ on |= spec->master_mute;
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
+ spec->autocfg.speaker_pins, on, false);
+
+ /* toggle line-out mutes if needed, too */
+ /* if LO is a copy of either HP or Speaker, don't need to handle it */
+ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
+ spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
+ return;
+ if (!spec->automute_lines || !spec->automute)
+ on = 0;
+ else
+ on = spec->jack_present;
+ on |= spec->master_mute;
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
+ spec->autocfg.line_out_pins, on, false);
+}
+
+static void alc_hp_automute(struct hda_codec *codec)
{
- alc_automute_speaker(codec, 1);
+ struct alc_spec *spec = codec->spec;
+
+ if (!spec->automute)
+ return;
+ spec->jack_present =
+ detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+ spec->autocfg.hp_pins);
+ update_speakers(codec);
+}
+
+static void alc_line_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (!spec->automute || !spec->detect_line)
+ return;
+ spec->line_jack_present =
+ detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
+ spec->autocfg.line_out_pins);
+ update_speakers(codec);
}
static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
@@ -1184,7 +1273,10 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
res >>= 26;
switch (res) {
case ALC880_HP_EVENT:
- alc_automute_pin(codec);
+ alc_hp_automute(codec);
+ break;
+ case ALC880_FRONT_EVENT:
+ alc_line_automute(codec);
break;
case ALC880_MIC_EVENT:
alc_mic_automute(codec);
@@ -1194,7 +1286,8 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
static void alc_inithook(struct hda_codec *codec)
{
- alc_automute_pin(codec);
+ alc_hp_automute(codec);
+ alc_line_automute(codec);
alc_mic_automute(codec);
}
@@ -1236,6 +1329,43 @@ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
on ? 2 : 0);
}
+/* turn on/off EAPD controls of the codec */
+static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
+{
+ /* We currently only handle front, HP */
+ switch (codec->vendor_id) {
+ case 0x10ec0260:
+ set_eapd(codec, 0x0f, on);
+ set_eapd(codec, 0x10, on);
+ break;
+ case 0x10ec0262:
+ case 0x10ec0267:
+ case 0x10ec0268:
+ case 0x10ec0269:
+ case 0x10ec0270:
+ case 0x10ec0272:
+ case 0x10ec0660:
+ case 0x10ec0662:
+ case 0x10ec0663:
+ case 0x10ec0665:
+ case 0x10ec0862:
+ case 0x10ec0889:
+ case 0x10ec0892:
+ set_eapd(codec, 0x14, on);
+ set_eapd(codec, 0x15, on);
+ break;
+ }
+}
+
+/* generic shutup callback;
+ * just turning off EPAD and a little pause for avoiding pop-noise
+ */
+static void alc_eapd_shutup(struct hda_codec *codec)
+{
+ alc_auto_setup_eapd(codec, false);
+ msleep(200);
+}
+
static void alc_auto_init_amp(struct hda_codec *codec, int type)
{
unsigned int tmp;
@@ -1251,27 +1381,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
break;
case ALC_INIT_DEFAULT:
- switch (codec->vendor_id) {
- case 0x10ec0260:
- set_eapd(codec, 0x0f, 1);
- set_eapd(codec, 0x10, 1);
- break;
- case 0x10ec0262:
- case 0x10ec0267:
- case 0x10ec0268:
- case 0x10ec0269:
- case 0x10ec0270:
- case 0x10ec0272:
- case 0x10ec0660:
- case 0x10ec0662:
- case 0x10ec0663:
- case 0x10ec0665:
- case 0x10ec0862:
- case 0x10ec0889:
- set_eapd(codec, 0x14, 1);
- set_eapd(codec, 0x15, 1);
- break;
- }
+ alc_auto_setup_eapd(codec, true);
switch (codec->vendor_id) {
case 0x10ec0260:
snd_hda_codec_write(codec, 0x1a, 0,
@@ -1315,20 +1425,128 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
}
}
+static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ static const char * const texts2[] = {
+ "Disabled", "Enabled"
+ };
+ static const char * const texts3[] = {
+ "Disabled", "Speaker Only", "Line-Out+Speaker"
+ };
+ const char * const *texts;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ if (spec->automute_hp_lo) {
+ uinfo->value.enumerated.items = 3;
+ texts = texts3;
+ } else {
+ uinfo->value.enumerated.items = 2;
+ texts = texts2;
+ }
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
+ if (!spec->automute)
+ val = 0;
+ else if (!spec->automute_lines)
+ val = 1;
+ else
+ val = 2;
+ ucontrol->value.enumerated.item[0] = val;
+ return 0;
+}
+
+static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+
+ switch (ucontrol->value.enumerated.item[0]) {
+ case 0:
+ if (!spec->automute)
+ return 0;
+ spec->automute = 0;
+ break;
+ case 1:
+ if (spec->automute && !spec->automute_lines)
+ return 0;
+ spec->automute = 1;
+ spec->automute_lines = 0;
+ break;
+ case 2:
+ if (!spec->automute_hp_lo)
+ return -EINVAL;
+ if (spec->automute && spec->automute_lines)
+ return 0;
+ spec->automute = 1;
+ spec->automute_lines = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ update_speakers(codec);
+ return 1;
+}
+
+static struct snd_kcontrol_new alc_automute_mode_enum = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Auto-Mute Mode",
+ .info = alc_automute_mode_info,
+ .get = alc_automute_mode_get,
+ .put = alc_automute_mode_put,
+};
+
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec);
+
+static int alc_add_automute_mode_enum(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct snd_kcontrol_new *knew;
+
+ knew = alc_kcontrol_new(spec);
+ if (!knew)
+ return -ENOMEM;
+ *knew = alc_automute_mode_enum;
+ knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
+ if (!knew->name)
+ return -ENOMEM;
+ return 0;
+}
+
static void alc_init_auto_hp(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
+ int present = 0;
int i;
- if (!cfg->hp_pins[0]) {
- if (cfg->line_out_type != AUTO_PIN_HP_OUT)
- return;
- }
+ if (cfg->hp_pins[0])
+ present++;
+ if (cfg->line_out_pins[0])
+ present++;
+ if (cfg->speaker_pins[0])
+ present++;
+ if (present < 2) /* need two different output types */
+ return;
+ if (present == 3)
+ spec->automute_hp_lo = 1; /* both HP and LO automute */
if (!cfg->speaker_pins[0]) {
- if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
- return;
memcpy(cfg->speaker_pins, cfg->line_out_pins,
sizeof(cfg->speaker_pins));
cfg->speaker_outs = cfg->line_outs;
@@ -1341,13 +1559,41 @@ static void alc_init_auto_hp(struct hda_codec *codec)
}
for (i = 0; i < cfg->hp_outs; i++) {
+ hda_nid_t nid = cfg->hp_pins[i];
+ if (!(snd_hda_query_pin_caps(codec, nid) &
+ AC_PINCAP_PRES_DETECT))
+ continue;
snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
- cfg->hp_pins[i]);
- snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
+ nid);
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | ALC880_HP_EVENT);
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ }
+ if (spec->automute && cfg->line_out_pins[0] &&
+ cfg->line_out_pins[0] != cfg->hp_pins[0] &&
+ cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
+ for (i = 0; i < cfg->line_outs; i++) {
+ hda_nid_t nid = cfg->line_out_pins[i];
+ if (!(snd_hda_query_pin_caps(codec, nid) &
+ AC_PINCAP_PRES_DETECT))
+ continue;
+ snd_printdd("realtek: Enable Line-Out auto-muting "
+ "on NID 0x%x\n", nid);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | ALC880_FRONT_EVENT);
+ spec->detect_line = 1;
+ }
+ spec->automute_lines = 1;
+ }
+
+ if (spec->automute) {
+ /* create a control for automute mode */
+ alc_add_automute_mode_enum(codec);
+ spec->unsol_event = alc_sku_unsol_event;
}
- spec->unsol_event = alc_sku_unsol_event;
}
static void alc_init_auto_mic(struct hda_codec *codec)
@@ -1583,9 +1829,6 @@ do_sku:
return 1;
spec->autocfg.hp_pins[0] = nid;
}
-
- alc_init_auto_hp(codec);
- alc_init_auto_mic(codec);
return 1;
}
@@ -1598,9 +1841,10 @@ static void alc_ssid_check(struct hda_codec *codec,
snd_printd("realtek: "
"Enable default setup for auto mode as fallback\n");
spec->init_amp = ALC_INIT_DEFAULT;
- alc_init_auto_hp(codec);
- alc_init_auto_mic(codec);
}
+
+ alc_init_auto_hp(codec);
+ alc_init_auto_mic(codec);
}
/*
@@ -1943,22 +2187,6 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
{}
};
-static void alc_automute_amp(struct hda_codec *codec)
-{
- alc_automute_speaker(codec, 0);
-}
-
-static void alc_automute_amp_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if (codec->vendor_id == 0x10ec0880)
- res >>= 28;
- else
- res >>= 26;
- if (res == ALC880_HP_EVENT)
- alc_automute_amp(codec);
-}
-
static void alc889_automute_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -1969,12 +2197,14 @@ static void alc889_automute_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[2] = 0x17;
spec->autocfg.speaker_pins[3] = 0x19;
spec->autocfg.speaker_pins[4] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc889_intel_init_hook(struct hda_codec *codec)
{
alc889_coef_init(codec);
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
}
static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
@@ -1985,6 +2215,8 @@ static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[1] = 0x1b; /* hp */
spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
spec->autocfg.speaker_pins[1] = 0x15; /* bass */
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/*
@@ -2267,6 +2499,8 @@ static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
@@ -2277,6 +2511,8 @@ static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
@@ -2287,6 +2523,8 @@ static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
@@ -2297,6 +2535,8 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x1b;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/*
@@ -3372,11 +3612,13 @@ static void alc880_uniwill_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc880_uniwill_init_hook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc88x_simple_mic_automute(codec);
}
@@ -3391,7 +3633,7 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
alc88x_simple_mic_automute(codec);
break;
default:
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
break;
}
}
@@ -3402,6 +3644,8 @@ static void alc880_uniwill_p53_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -3426,7 +3670,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
if ((res >> 28) == ALC880_DCVOL_EVENT)
alc880_uniwill_p53_dcvol_automute(codec);
else
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
}
/*
@@ -3670,6 +3914,8 @@ static void alc880_lg_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/*
@@ -3754,6 +4000,8 @@ static void alc880_lg_lw_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
@@ -3801,7 +4049,7 @@ static struct hda_verb alc880_medion_rim_init_verbs[] = {
static void alc880_medion_rim_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
/* toggle EAPD */
if (spec->jack_present)
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
@@ -3825,6 +4073,8 @@ static void alc880_medion_rim_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -4193,6 +4443,10 @@ static int alc_build_pcms(struct hda_codec *codec)
static inline void alc_shutup(struct hda_codec *codec)
{
+ struct alc_spec *spec = codec->spec;
+
+ if (spec && spec->shutup)
+ spec->shutup(codec);
snd_hda_shutup_pins(codec);
}
@@ -4226,28 +4480,7 @@ static void alc_free(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void alc_power_eapd(struct hda_codec *codec)
{
- /* We currently only handle front, HP */
- switch (codec->vendor_id) {
- case 0x10ec0260:
- set_eapd(codec, 0x0f, 0);
- set_eapd(codec, 0x10, 0);
- break;
- case 0x10ec0262:
- case 0x10ec0267:
- case 0x10ec0268:
- case 0x10ec0269:
- case 0x10ec0270:
- case 0x10ec0272:
- case 0x10ec0660:
- case 0x10ec0662:
- case 0x10ec0663:
- case 0x10ec0665:
- case 0x10ec0862:
- case 0x10ec0889:
- set_eapd(codec, 0x14, 0);
- set_eapd(codec, 0x15, 0);
- break;
- }
+ alc_auto_setup_eapd(codec, false);
}
static int alc_suspend(struct hda_codec *codec, pm_message_t state)
@@ -4263,6 +4496,7 @@ static int alc_suspend(struct hda_codec *codec, pm_message_t state)
#ifdef SND_HDA_NEEDS_RESUME
static int alc_resume(struct hda_codec *codec)
{
+ msleep(150); /* to avoid pop noise */
codec->patch_ops.init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
@@ -4794,7 +5028,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_f1734_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
.setup = alc880_uniwill_p53_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_ASUS] = {
.mixers = { alc880_asus_mixer },
@@ -4885,7 +5119,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
.setup = alc880_uniwill_p53_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_FUJITSU] = {
.mixers = { alc880_fujitsu_mixer },
@@ -4900,7 +5134,7 @@ static struct alc_config_preset alc880_presets[] = {
.input_mux = &alc880_capture_source,
.unsol_event = alc880_uniwill_p53_unsol_event,
.setup = alc880_uniwill_p53_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_CLEVO] = {
.mixers = { alc880_three_stack_mixer },
@@ -4925,9 +5159,9 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_lg_ch_modes,
.need_dac_fix = 1,
.input_mux = &alc880_lg_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc880_lg_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.loopbacks = alc880_lg_loopbacks,
#endif
@@ -4942,9 +5176,9 @@ static struct alc_config_preset alc880_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
.channel_mode = alc880_lg_lw_modes,
.input_mux = &alc880_lg_lw_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc880_lg_lw_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC880_MEDION_RIM] = {
.mixers = { alc880_medion_rim_mixer },
@@ -4990,14 +5224,19 @@ static struct snd_kcontrol_new alc880_control_templates[] = {
HDA_BIND_MUTE(NULL, 0, 0, 0),
};
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+{
+ snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+ return snd_array_new(&spec->kctls);
+}
+
/* add dynamic controls */
static int add_control(struct alc_spec *spec, int type, const char *name,
int cidx, unsigned long val)
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
- knew = snd_array_new(&spec->kctls);
+ knew = alc_kcontrol_new(spec);
if (!knew)
return -ENOMEM;
*knew = alc880_control_templates[type];
@@ -5078,10 +5317,13 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
return 0;
}
-static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
+static const char *alc_get_line_out_pfx(struct alc_spec *spec,
bool can_be_master)
{
- if (!cfg->hp_outs && !cfg->speaker_outs && can_be_master)
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+
+ if (cfg->line_outs == 1 && !spec->multi_ios &&
+ !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
return "Master";
switch (cfg->line_out_type) {
@@ -5092,7 +5334,7 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
case AUTO_PIN_HP_OUT:
return "Headphone";
default:
- if (cfg->line_outs == 1)
+ if (cfg->line_outs == 1 && !spec->multi_ios)
return "PCM";
break;
}
@@ -5106,11 +5348,15 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, false);
+ const char *pfx = alc_get_line_out_pfx(spec, false);
hda_nid_t nid;
- int i, err;
+ int i, err, noutputs;
- for (i = 0; i < cfg->line_outs; i++) {
+ noutputs = cfg->line_outs;
+ if (spec->multi_ios > 0)
+ noutputs += spec->multi_ios;
+
+ for (i = 0; i < noutputs; i++) {
if (!spec->multiout.dac_nids[i])
continue;
nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
@@ -5376,6 +5622,8 @@ static void alc880_auto_init_input_src(struct hda_codec *codec)
}
}
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
+
/* parse the BIOS configuration and set up the alc_spec */
/* return 1 if successful, 0 if the proper config is not found,
* or a negative error code
@@ -5396,6 +5644,9 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
@@ -5903,21 +6154,14 @@ static struct snd_kcontrol_new alc260_input_mixer[] = {
};
/* update HP, line and mono out pins according to the master switch */
-static void alc260_hp_master_update(struct hda_codec *codec,
- hda_nid_t hp, hda_nid_t line,
- hda_nid_t mono)
+static void alc260_hp_master_update(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int val = spec->master_sw ? PIN_HP : 0;
- /* change HP and line-out pins */
- snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
- snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
- /* mono (speaker) depending on the HP jack sense */
- val = (val && !spec->jack_present) ? PIN_OUT : 0;
- snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- val);
+
+ /* change HP pins */
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+ spec->autocfg.hp_pins, spec->master_mute, true);
+ update_speakers(codec);
}
static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
@@ -5925,7 +6169,7 @@ static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- *ucontrol->value.integer.value = spec->master_sw;
+ *ucontrol->value.integer.value = !spec->master_mute;
return 0;
}
@@ -5934,16 +6178,12 @@ static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int val = !!*ucontrol->value.integer.value;
- hda_nid_t hp, line, mono;
+ int val = !*ucontrol->value.integer.value;
- if (val == spec->master_sw)
+ if (val == spec->master_mute)
return 0;
- spec->master_sw = val;
- hp = (kcontrol->private_value >> 16) & 0xff;
- line = (kcontrol->private_value >> 8) & 0xff;
- mono = kcontrol->private_value & 0xff;
- alc260_hp_master_update(codec, hp, line, mono);
+ spec->master_mute = val;
+ alc260_hp_master_update(codec);
return 1;
}
@@ -5955,7 +6195,6 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
.info = snd_ctl_boolean_mono_info,
.get = alc260_hp_master_sw_get,
.put = alc260_hp_master_sw_put,
- .private_value = (0x0f << 16) | (0x10 << 8) | 0x11
},
HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
@@ -5972,18 +6211,15 @@ static struct hda_verb alc260_hp_unsol_verbs[] = {
{},
};
-static void alc260_hp_automute(struct hda_codec *codec)
+static void alc260_hp_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x10);
- alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
-}
-
-static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc260_hp_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x0f;
+ spec->autocfg.speaker_pins[0] = 0x10;
+ spec->autocfg.speaker_pins[1] = 0x11;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
@@ -5994,7 +6230,6 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
.info = snd_ctl_boolean_mono_info,
.get = alc260_hp_master_sw_get,
.put = alc260_hp_master_sw_put,
- .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
},
HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
@@ -6007,6 +6242,17 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
{ } /* end */
};
+static void alc260_hp_3013_setup(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x10;
+ spec->autocfg.speaker_pins[1] = 0x11;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
.ops = &snd_hda_bind_vol,
.values = {
@@ -6039,38 +6285,16 @@ static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
{},
};
-static void alc260_hp_3013_automute(struct hda_codec *codec)
+static void alc260_hp_3012_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x15);
- alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
-}
-
-static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc260_hp_3013_automute(codec);
-}
-
-static void alc260_hp_3012_automute(struct hda_codec *codec)
-{
- unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 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,
- bits);
- snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
- bits);
-}
-
-static void alc260_hp_3012_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc260_hp_3012_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x10;
+ spec->autocfg.speaker_pins[0] = 0x0f;
+ spec->autocfg.speaker_pins[1] = 0x11;
+ spec->autocfg.speaker_pins[2] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
@@ -7195,8 +7419,9 @@ static struct alc_config_preset alc260_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
- .unsol_event = alc260_hp_unsol_event,
- .init_hook = alc260_hp_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc260_hp_setup,
+ .init_hook = alc_inithook,
},
[ALC260_HP_DC7600] = {
.mixers = { alc260_hp_dc7600_mixer,
@@ -7210,8 +7435,9 @@ static struct alc_config_preset alc260_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
- .unsol_event = alc260_hp_3012_unsol_event,
- .init_hook = alc260_hp_3012_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc260_hp_3012_setup,
+ .init_hook = alc_inithook,
},
[ALC260_HP_3013] = {
.mixers = { alc260_hp_3013_mixer,
@@ -7225,8 +7451,9 @@ static struct alc_config_preset alc260_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
- .unsol_event = alc260_hp_3013_unsol_event,
- .init_hook = alc260_hp_3013_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc260_hp_3013_setup,
+ .init_hook = alc_inithook,
},
[ALC260_FUJITSU_S702X] = {
.mixers = { alc260_fujitsu_mixer },
@@ -7384,6 +7611,7 @@ static int patch_alc260(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC260_AUTO)
spec->init_hook = alc260_auto_init;
+ spec->shutup = alc_eapd_shutup;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc260_loopbacks;
@@ -8600,6 +8828,8 @@ static void alc885_imac24_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x18;
spec->autocfg.speaker_pins[1] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
#define alc885_mb5_setup alc885_imac24_setup
@@ -8612,6 +8842,8 @@ static void alc885_mba21_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x18;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
@@ -8622,6 +8854,8 @@ static void alc885_mbp3_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc885_imac91_setup(struct hda_codec *codec)
@@ -8631,6 +8865,8 @@ static void alc885_imac91_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x18;
spec->autocfg.speaker_pins[1] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct hda_verb alc882_targa_verbs[] = {
@@ -8652,7 +8888,7 @@ static struct hda_verb alc882_targa_verbs[] = {
static void alc882_targa_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
spec->jack_present ? 1 : 3);
}
@@ -8663,6 +8899,8 @@ static void alc882_targa_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -8750,7 +8988,7 @@ static void alc885_macpro_init_hook(struct hda_codec *codec)
static void alc885_imac24_init_hook(struct hda_codec *codec)
{
alc885_macpro_init_hook(codec);
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
}
/*
@@ -9108,6 +9346,8 @@ static void alc883_medion_wim2160_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1a;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
@@ -9260,6 +9500,8 @@ static void alc883_mitac_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct hda_verb alc883_mitac_verbs[] = {
@@ -9424,6 +9666,8 @@ static void alc888_3st_hp_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x16;
spec->autocfg.speaker_pins[2] = 0x18;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct hda_verb alc888_3st_hp_verbs[] = {
@@ -9476,33 +9720,15 @@ static struct hda_channel_mode alc888_3st_hp_modes[3] = {
{ 6, alc888_3st_hp_6ch_init },
};
-/* toggle front-jack and RCA according to the hp-jack state */
-static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
+static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
{
- unsigned int present = snd_hda_jack_detect(codec, 0x1b);
-
- 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,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
-
-/* toggle RCA according to the front-jack state */
-static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
-{
- unsigned int present = snd_hda_jack_detect(codec, 0x14);
-
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc888_lenovo_ms7195_front_automute(codec);
- if ((res >> 26) == ALC880_FRONT_EVENT)
- alc888_lenovo_ms7195_rca_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.line_out_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* toggle speaker-output according to the hp-jack state */
@@ -9512,6 +9738,8 @@ static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* toggle speaker-output according to the hp-jack state */
@@ -9524,11 +9752,13 @@ static void alc883_clevo_m720_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc88x_simple_mic_automute(codec);
}
@@ -9540,7 +9770,7 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
alc88x_simple_mic_automute(codec);
break;
default:
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
break;
}
}
@@ -9552,6 +9782,8 @@ static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc883_haier_w66_setup(struct hda_codec *codec)
@@ -9560,33 +9792,21 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
+static void alc883_lenovo_101e_setup(struct hda_codec *codec)
{
- int bits = snd_hda_jack_detect(codec, 0x14) ? 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)
-{
- int bits = snd_hda_jack_detect(codec, 0x1b) ? 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,
- HDA_AMP_MUTE, bits);
-}
+ struct alc_spec *spec = codec->spec;
-static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc883_lenovo_101e_all_automute(codec);
- if ((res >> 26) == ALC880_FRONT_EVENT)
- alc883_lenovo_101e_ispeaker_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.line_out_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->detect_line = 1;
+ spec->automute_lines = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* toggle speaker-output according to the hp-jack state */
@@ -9597,6 +9817,8 @@ static void alc883_acer_aspire_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct hda_verb alc883_acer_eapd_verbs[] = {
@@ -9626,6 +9848,8 @@ static void alc888_6st_dell_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[1] = 0x15;
spec->autocfg.speaker_pins[2] = 0x16;
spec->autocfg.speaker_pins[3] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc888_lenovo_sky_setup(struct hda_codec *codec)
@@ -9638,6 +9862,8 @@ static void alc888_lenovo_sky_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[2] = 0x16;
spec->autocfg.speaker_pins[3] = 0x17;
spec->autocfg.speaker_pins[4] = 0x1a;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc883_vaiott_setup(struct hda_codec *codec)
@@ -9647,6 +9873,8 @@ static void alc883_vaiott_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
spec->autocfg.speaker_pins[1] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct hda_verb alc888_asus_m90v_verbs[] = {
@@ -9672,6 +9900,8 @@ static void alc883_mode2_setup(struct hda_codec *codec)
spec->ext_mic.mux_idx = 0;
spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct hda_verb alc888_asus_eee1601_verbs[] = {
@@ -9693,7 +9923,7 @@ static void alc883_eee1601_inithook(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
- alc_automute_pin(codec);
+ alc_hp_automute(codec);
}
static struct hda_verb alc889A_mb31_verbs[] = {
@@ -10015,9 +10245,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc885_mba21_ch_modes,
.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
.input_mux = &alc882_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_mba21_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MBP3] = {
.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
@@ -10031,9 +10261,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_mbp3_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MB5] = {
.mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
@@ -10046,9 +10276,9 @@ 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 = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_mb5_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MACMINI3] = {
.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
@@ -10061,9 +10291,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &macmini3_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_macmini3_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC885_MACPRO] = {
.mixers = { alc882_macpro_mixer },
@@ -10087,7 +10317,7 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
.channel_mode = alc882_ch_modes,
.input_mux = &alc882_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_imac24_setup,
.init_hook = alc885_imac24_init_hook,
},
@@ -10102,9 +10332,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc889A_imac91_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc885_imac91_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
@@ -10120,7 +10350,7 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc882_3ST_6ch_modes,
.need_dac_fix = 1,
.input_mux = &alc882_capture_source,
- .unsol_event = alc882_targa_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc882_targa_setup,
.init_hook = alc882_targa_automute,
},
@@ -10214,8 +10444,8 @@ static struct alc_config_preset alc882_presets[] = {
.capsrc_nids = alc889_capsrc_nids,
.input_mux = &alc889_capture_source,
.setup = alc889_automute_setup,
- .init_hook = alc_automute_amp,
- .unsol_event = alc_automute_amp_unsol_event,
+ .init_hook = alc_hp_automute,
+ .unsol_event = alc_sku_unsol_event,
.need_dac_fix = 1,
},
[ALC889_INTEL] = {
@@ -10235,7 +10465,7 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc889_capture_source,
.setup = alc889_automute_setup,
.init_hook = alc889_intel_init_hook,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.need_dac_fix = 1,
},
[ALC883_6ST_DIG] = {
@@ -10324,9 +10554,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_acer_aspire_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ACER_ASPIRE_4930G] = {
.mixers = { alc888_acer_aspire_4930g_mixer,
@@ -10346,9 +10576,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_2_capture_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_acer_aspire_4930g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ACER_ASPIRE_6530G] = {
.mixers = { alc888_acer_aspire_6530_mixer },
@@ -10365,9 +10595,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_acer_aspire_6530_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_acer_aspire_6530g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ACER_ASPIRE_8930G] = {
.mixers = { alc889_acer_aspire_8930g_mixer,
@@ -10388,9 +10618,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc889_capture_sources),
.input_mux = alc889_capture_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc889_acer_aspire_8930g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
#ifdef CONFIG_SND_HDA_POWER_SAVE
.power_hook = alc_power_eapd,
#endif
@@ -10411,9 +10641,9 @@ static struct alc_config_preset alc882_presets[] = {
.need_dac_fix = 1,
.const_channel_count = 6,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_acer_aspire_7730g_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
@@ -10440,9 +10670,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_medion_wim2160_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_LAPTOP_EAPD] = {
.mixers = { alc883_base_mixer },
@@ -10492,8 +10722,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_lenovo_101e_capture_source,
- .unsol_event = alc883_lenovo_101e_unsol_event,
- .init_hook = alc883_lenovo_101e_all_automute,
+ .setup = alc883_lenovo_101e_setup,
+ .unsol_event = alc_sku_unsol_event,
+ .init_hook = alc_inithook,
},
[ALC883_LENOVO_NB0763] = {
.mixers = { alc883_lenovo_nb0763_mixer },
@@ -10504,9 +10735,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc883_3ST_2ch_modes,
.need_dac_fix = 1,
.input_mux = &alc883_lenovo_nb0763_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_lenovo_nb0763_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_LENOVO_MS7195_DIG] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10518,8 +10749,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc883_3ST_6ch_modes,
.need_dac_fix = 1,
.input_mux = &alc883_capture_source,
- .unsol_event = alc883_lenovo_ms7195_unsol_event,
- .init_hook = alc888_lenovo_ms7195_front_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc888_lenovo_ms7195_setup,
+ .init_hook = alc_inithook,
},
[ALC883_HAIER_W66] = {
.mixers = { alc883_targa_2ch_mixer},
@@ -10530,9 +10762,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_haier_w66_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_3ST_HP] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10543,9 +10775,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc888_3st_hp_modes,
.need_dac_fix = 1,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_3st_hp_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_6ST_DELL] = {
.mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -10557,9 +10789,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_6st_dell_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_MITAC] = {
.mixers = { alc883_mitac_mixer },
@@ -10569,9 +10801,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_mitac_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC883_FUJITSU_PI2515] = {
.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
@@ -10583,9 +10815,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_fujitsu_pi2515_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_2ch_fujitsu_pi2515_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_FUJITSU_XA3530] = {
.mixers = { alc888_base_mixer, alc883_chmode_mixer },
@@ -10602,9 +10834,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_mux_defs =
ARRAY_SIZE(alc888_2_capture_sources),
.input_mux = alc888_2_capture_sources,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_fujitsu_xa3530_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_LENOVO_SKY] = {
.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
@@ -10616,9 +10848,9 @@ static struct alc_config_preset alc882_presets[] = {
.channel_mode = alc883_sixstack_modes,
.need_dac_fix = 1,
.input_mux = &alc883_lenovo_sky_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc888_lenovo_sky_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC888_ASUS_M90V] = {
.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10686,9 +10918,9 @@ static struct alc_config_preset alc882_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc883_vaiott_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
};
@@ -10842,6 +11074,11 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
const struct hda_input_mux *imux;
int conns, mute, idx, item;
+ /* mute ADC */
+ snd_hda_codec_write(codec, spec->adc_nids[c], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_MUTE(0));
+
conns = snd_hda_get_connections(codec, nid, conn_list,
ARRAY_SIZE(conn_list));
if (conns < 0)
@@ -10934,6 +11171,9 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
@@ -11163,71 +11403,30 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
};
/* update HP, line and mono-out pins according to the master switch */
-static void alc262_hp_master_update(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- int val = spec->master_sw;
-
- /* HP & line-out */
- snd_hda_codec_write_cache(codec, 0x1b, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val ? PIN_HP : 0);
- snd_hda_codec_write_cache(codec, 0x15, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val ? PIN_HP : 0);
- /* mono (speaker) depending on the HP jack sense */
- val = val && !spec->jack_present;
- snd_hda_codec_write_cache(codec, 0x16, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- val ? PIN_OUT : 0);
-}
+#define alc262_hp_master_update alc260_hp_master_update
-static void alc262_hp_bpc_automute(struct hda_codec *codec)
+static void alc262_hp_bpc_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
- alc262_hp_master_update(codec);
-}
-
-static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hp_bpc_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
-static void alc262_hp_wildwest_automute(struct hda_codec *codec)
+static void alc262_hp_wildwest_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present = snd_hda_jack_detect(codec, 0x15);
- alc262_hp_master_update(codec);
-}
-
-static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hp_wildwest_automute(codec);
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
#define alc262_hp_master_sw_get alc260_hp_master_sw_get
-
-static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int val = !!*ucontrol->value.integer.value;
-
- if (val == spec->master_sw)
- return 0;
- spec->master_sw = val;
- alc262_hp_master_update(codec);
- return 1;
-}
+#define alc262_hp_master_sw_put alc260_hp_master_sw_put
#define ALC262_HP_MASTER_SWITCH \
{ \
@@ -11302,6 +11501,8 @@ static void alc262_hp_t5735_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@ -11355,44 +11556,9 @@ static struct hda_input_mux alc262_hp_rp5700_capture_source = {
};
/* bind hp and internal speaker mute (with plug check) as master switch */
-static void alc262_hippo_master_update(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
- hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
- hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
- unsigned int mute;
-
- /* HP */
- mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
- snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- /* mute internal speaker per jack sense */
- if (spec->jack_present)
- mute = HDA_AMP_MUTE;
- if (line_nid)
- snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- if (speaker_nid && speaker_nid != line_nid)
- snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
-}
-
+#define alc262_hippo_master_update alc262_hp_master_update
#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
-
-static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int val = !!*ucontrol->value.integer.value;
-
- if (val == spec->master_sw)
- return 0;
- spec->master_sw = val;
- alc262_hippo_master_update(codec);
- return 1;
-}
+#define alc262_hippo_master_sw_put alc262_hp_master_sw_put
#define ALC262_HIPPO_MASTER_SWITCH \
{ \
@@ -11443,28 +11609,14 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
};
/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
-
- spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
- alc262_hippo_master_update(codec);
-}
-
-static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc262_hippo_automute(codec);
-}
-
static void alc262_hippo_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc262_hippo1_setup(struct hda_codec *codec)
@@ -11473,6 +11625,8 @@ static void alc262_hippo1_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
@@ -11535,6 +11689,8 @@ static void alc262_tyan_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
@@ -11678,6 +11834,8 @@ static void alc262_toshiba_s06_setup(struct hda_codec *codec)
spec->int_mic.pin = 0x12;
spec->int_mic.mux_idx = 9;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
/*
@@ -11774,40 +11932,15 @@ static struct hda_input_mux alc262_HP_D7000_capture_source = {
},
};
-/* mute/unmute internal speaker according to the hp jacks and mute state */
-static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
+static void alc262_fujitsu_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int mute;
-
- if (force || !spec->sense_updated) {
- spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
- snd_hda_jack_detect(codec, 0x1b);
- spec->sense_updated = 1;
- }
- /* unmute internal speaker only if both HPs are unplugged and
- * master switch is on
- */
- if (spec->jack_present)
- mute = HDA_AMP_MUTE;
- else
- mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC_HP_EVENT)
- return;
- alc262_fujitsu_automute(codec, 1);
-}
-static void alc262_fujitsu_init_hook(struct hda_codec *codec)
-{
- alc262_fujitsu_automute(codec, 1);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.hp_pins[1] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
/* bind volumes of both NID 0x0c and 0x0d */
@@ -11820,78 +11953,15 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
},
};
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int mute;
-
- if (force || !spec->sense_updated) {
- spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
- spec->sense_updated = 1;
- }
- if (spec->jack_present) {
- /* mute internal speaker */
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- } else {
- /* unmute internal speaker if necessary */
- mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- }
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC_HP_EVENT)
- return;
- alc262_lenovo_3000_automute(codec, 1);
-}
-
-static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
- int dir, int idx, long *valp)
-{
- int i, change = 0;
-
- for (i = 0; i < 2; i++, valp++)
- change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
- HDA_AMP_MUTE,
- *valp ? 0 : HDA_AMP_MUTE);
- return change;
-}
-
-/* bind hp and internal speaker mute (with plug check) */
-static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
- change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
- if (change)
- alc262_fujitsu_automute(codec, 0);
- return change;
-}
-
static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc262_fujitsu_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc262_hp_master_sw_get,
+ .put = alc262_hp_master_sw_put,
},
{
.iface = NID_MAPPING,
@@ -11909,18 +11979,15 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
{ } /* end */
};
-/* bind hp and internal speaker mute (with plug check) */
-static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void alc262_lenovo_3000_setup(struct hda_codec *codec)
{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
+ struct alc_spec *spec = codec->spec;
- change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
- if (change)
- alc262_lenovo_3000_automute(codec, 0);
- return change;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
@@ -11928,11 +11995,10 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc262_lenovo_3000_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc262_hp_master_sw_get,
+ .put = alc262_hp_master_sw_put,
},
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -12150,7 +12216,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
spec->multiout.dac_nids = spec->private_dac_nids;
spec->multiout.dac_nids[0] = 2;
- pfx = alc_get_line_out_pfx(cfg, true);
+ pfx = alc_get_line_out_pfx(spec, true);
if (!pfx)
pfx = "Front";
for (i = 0; i < 2; i++) {
@@ -12682,9 +12748,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_HIPPO_1] = {
.mixers = { alc262_hippo1_mixer },
@@ -12696,9 +12762,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo1_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_FUJITSU] = {
.mixers = { alc262_fujitsu_mixer },
@@ -12711,8 +12777,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_fujitsu_capture_source,
- .unsol_event = alc262_fujitsu_unsol_event,
- .init_hook = alc262_fujitsu_init_hook,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_fujitsu_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_BPC] = {
.mixers = { alc262_HP_BPC_mixer },
@@ -12723,8 +12790,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_HP_capture_source,
- .unsol_event = alc262_hp_bpc_unsol_event,
- .init_hook = alc262_hp_bpc_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_hp_bpc_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_BPC_D7000_WF] = {
.mixers = { alc262_HP_BPC_WildWest_mixer },
@@ -12735,8 +12803,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_HP_D7000_capture_source,
- .unsol_event = alc262_hp_wildwest_unsol_event,
- .init_hook = alc262_hp_wildwest_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_hp_wildwest_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_BPC_D7000_WL] = {
.mixers = { alc262_HP_BPC_WildWest_mixer,
@@ -12748,8 +12817,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_HP_D7000_capture_source,
- .unsol_event = alc262_hp_wildwest_unsol_event,
- .init_hook = alc262_hp_wildwest_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_hp_wildwest_setup,
+ .init_hook = alc_inithook,
},
[ALC262_HP_TC_T5735] = {
.mixers = { alc262_hp_t5735_mixer },
@@ -12792,9 +12862,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_BENQ_T31] = {
.mixers = { alc262_benq_t31_mixer },
@@ -12806,9 +12876,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_ULTRA] = {
.mixers = { alc262_ultra_mixer },
@@ -12837,7 +12907,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_fujitsu_capture_source,
- .unsol_event = alc262_lenovo_3000_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc262_lenovo_3000_setup,
+ .init_hook = alc_inithook,
},
[ALC262_NEC] = {
.mixers = { alc262_nec_mixer },
@@ -12874,9 +12946,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc262_hippo_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_hippo_setup,
- .init_hook = alc262_hippo_automute,
+ .init_hook = alc_inithook,
},
[ALC262_TYAN] = {
.mixers = { alc262_tyan_mixer },
@@ -12888,9 +12960,9 @@ static struct alc_config_preset alc262_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc262_modes),
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc262_tyan_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
};
@@ -13011,6 +13083,7 @@ static int patch_alc262(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC262_AUTO)
spec->init_hook = alc262_auto_init;
+ spec->shutup = alc_eapd_shutup;
alc_init_jacks(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -13106,38 +13179,18 @@ static struct hda_bind_ctls alc268_acer_bind_master_vol = {
},
};
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_acer_automute(struct hda_codec *codec, int force)
+static void alc268_acer_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int mute;
- if (force || !spec->sense_updated) {
- spec->jack_present = snd_hda_jack_detect(codec, 0x14);
- spec->sense_updated = 1;
- }
- if (spec->jack_present)
- mute = HDA_AMP_MUTE; /* mute internal speaker */
- else /* unmute internal speaker if necessary */
- mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
+ spec->autocfg.hp_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
-
-/* bind hp and internal speaker mute (with plug check) */
-static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- long *valp = ucontrol->value.integer.value;
- int change;
-
- change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
- if (change)
- alc268_acer_automute(codec, 0);
- return change;
-}
+#define alc268_acer_master_sw_get alc262_hp_master_sw_get
+#define alc268_acer_master_sw_put alc262_hp_master_sw_put
static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
/* output mixer control */
@@ -13145,11 +13198,10 @@ static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc268_acer_master_sw_get,
.put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
{ }
@@ -13161,11 +13213,10 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc268_acer_master_sw_get,
.put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
@@ -13179,11 +13230,10 @@ static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
+ .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+ .info = snd_ctl_boolean_mono_info,
+ .get = alc268_acer_master_sw_get,
.put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
},
HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
@@ -13212,53 +13262,16 @@ static struct hda_verb alc268_acer_verbs[] = {
};
/* unsolicited event for HP jack sensing */
-#define alc268_toshiba_unsol_event alc262_hippo_unsol_event
#define alc268_toshiba_setup alc262_hippo_setup
-#define alc268_toshiba_automute alc262_hippo_automute
-
-static void alc268_acer_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC880_HP_EVENT)
- return;
- alc268_acer_automute(codec, 1);
-}
-
-static void alc268_acer_init_hook(struct hda_codec *codec)
-{
- alc268_acer_automute(codec, 1);
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc268_aspire_one_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
static void alc268_acer_lc_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0f;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -13266,12 +13279,6 @@ static void alc268_acer_lc_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc268_acer_lc_init_hook(struct hda_codec *codec)
-{
- alc268_aspire_one_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
static struct snd_kcontrol_new alc268_dell_mixer[] = {
/* output mixer control */
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
@@ -13303,6 +13310,8 @@ static void alc268_dell_setup(struct hda_codec *codec)
spec->int_mic.pin = 0x19;
spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
@@ -13333,6 +13342,8 @@ static void alc267_quanta_il1_setup(struct hda_codec *codec)
spec->int_mic.pin = 0x19;
spec->int_mic.mux_idx = 1;
spec->auto_mic = 1;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
}
/*
@@ -13874,9 +13885,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
- .unsol_event = alc268_toshiba_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc268_toshiba_setup,
- .init_hook = alc268_toshiba_automute,
+ .init_hook = alc_inithook,
},
[ALC268_ACER] = {
.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
@@ -13892,8 +13903,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_acer_capture_source,
- .unsol_event = alc268_acer_unsol_event,
- .init_hook = alc268_acer_init_hook,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc268_acer_setup,
+ .init_hook = alc_inithook,
},
[ALC268_ACER_DMIC] = {
.mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
@@ -13909,8 +13921,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_acer_dmic_capture_source,
- .unsol_event = alc268_acer_unsol_event,
- .init_hook = alc268_acer_init_hook,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc268_acer_setup,
+ .init_hook = alc_inithook,
},
[ALC268_ACER_ASPIRE_ONE] = {
.mixers = { alc268_acer_aspire_one_mixer,
@@ -13926,9 +13939,9 @@ static struct alc_config_preset alc268_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
- .unsol_event = alc268_acer_lc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc268_acer_lc_setup,
- .init_hook = alc268_acer_lc_init_hook,
+ .init_hook = alc_inithook,
},
[ALC268_DELL] = {
.mixers = { alc268_dell_mixer, alc268_beep_mixer,
@@ -13962,8 +13975,9 @@ static struct alc_config_preset alc268_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc268_modes),
.channel_mode = alc268_modes,
.input_mux = &alc268_capture_source,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc268_toshiba_setup,
- .init_hook = alc268_toshiba_automute,
+ .init_hook = alc_inithook,
},
#ifdef CONFIG_SND_DEBUG
[ALC268_TEST] = {
@@ -14085,6 +14099,7 @@ static int patch_alc268(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC268_AUTO)
spec->init_hook = alc268_auto_init;
+ spec->shutup = alc_eapd_shutup;
alc_init_jacks(codec);
@@ -14267,15 +14282,7 @@ static struct hda_verb alc269_lifebook_verbs[] = {
/* toggle speaker-output according to the hp-jack state */
static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
+ alc_hp_automute(codec);
snd_hda_codec_write(codec, 0x20, 0,
AC_VERB_SET_COEF_INDEX, 0x0c);
@@ -14288,34 +14295,8 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x480);
}
-/* toggle speaker-output according to the hp-jacks state */
-static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- /* Check laptop headphone socket */
- present = snd_hda_jack_detect(codec, 0x15);
-
- /* Check port replicator headphone socket */
- present |= snd_hda_jack_detect(codec, 0x1a);
-
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x680);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x480);
-}
+#define alc269_lifebook_speaker_automute \
+ alc269_quanta_fl1_speaker_automute
static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
{
@@ -14364,6 +14345,9 @@ static void alc269_quanta_fl1_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -14377,6 +14361,17 @@ static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
alc_mic_automute(codec);
}
+static void alc269_lifebook_setup(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.hp_pins[1] = 0x1a;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+}
+
static void alc269_lifebook_init_hook(struct hda_codec *codec)
{
alc269_lifebook_speaker_automute(codec);
@@ -14440,42 +14435,14 @@ static struct hda_verb alc271_acer_dmic_verbs[] = {
{ }
};
-/* toggle speaker-output according to the hp-jack state */
-static void alc269_speaker_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int nid = spec->autocfg.hp_pins[0];
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, nid);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
- snd_hda_input_jack_report(codec, nid);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc269_laptop_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc269_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
static void alc269_laptop_amic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -14488,6 +14455,9 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -14500,6 +14470,9 @@ static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x21;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -14512,6 +14485,9 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x21;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -14519,12 +14495,6 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc269_laptop_inithook(struct hda_codec *codec)
-{
- alc269_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -14796,7 +14766,6 @@ static void alc269_auto_init(struct hda_codec *codec)
alc_inithook(codec);
}
-#ifdef SND_HDA_NEEDS_RESUME
static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
{
int val = alc_read_coef_idx(codec, 0x04);
@@ -14807,25 +14776,17 @@ static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
alc_write_coef_idx(codec, 0x04, val);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_suspend(struct hda_codec *codec, pm_message_t state)
+static void alc269_shutup(struct hda_codec *codec)
{
- struct alc_spec *spec = codec->spec;
-
if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
alc269_toggle_power_output(codec, 0);
if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
alc269_toggle_power_output(codec, 0);
msleep(150);
}
-
- alc_shutup(codec);
- if (spec && spec->power_hook)
- spec->power_hook(codec);
- return 0;
}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
+#ifdef SND_HDA_NEEDS_RESUME
static int alc269_resume(struct hda_codec *codec)
{
if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
@@ -15070,9 +15031,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269_laptop_amic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269_DMIC] = {
.mixers = { alc269_laptop_mixer },
@@ -15084,9 +15045,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269_laptop_dmic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269VB_AMIC] = {
.mixers = { alc269vb_laptop_mixer },
@@ -15098,9 +15059,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269vb_laptop_amic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269VB_DMIC] = {
.mixers = { alc269vb_laptop_mixer },
@@ -15112,9 +15073,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269vb_laptop_dmic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269_FUJITSU] = {
.mixers = { alc269_fujitsu_mixer },
@@ -15126,9 +15087,9 @@ static struct alc_config_preset alc269_presets[] = {
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
- .unsol_event = alc269_laptop_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc269_laptop_dmic_setup,
- .init_hook = alc269_laptop_inithook,
+ .init_hook = alc_inithook,
},
[ALC269_LIFEBOOK] = {
.mixers = { alc269_lifebook_mixer },
@@ -15140,6 +15101,7 @@ static struct alc_config_preset alc269_presets[] = {
.channel_mode = alc269_modes,
.input_mux = &alc269_capture_source,
.unsol_event = alc269_lifebook_unsol_event,
+ .setup = alc269_lifebook_setup,
.init_hook = alc269_lifebook_init_hook,
},
[ALC271_ACER] = {
@@ -15313,14 +15275,12 @@ static int patch_alc269(struct hda_codec *codec)
spec->vmaster_nid = 0x02;
codec->patch_ops = alc_patch_ops;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- codec->patch_ops.suspend = alc269_suspend;
-#endif
#ifdef SND_HDA_NEEDS_RESUME
codec->patch_ops.resume = alc269_resume;
#endif
if (board_config == ALC269_AUTO)
spec->init_hook = alc269_auto_init;
+ spec->shutup = alc269_shutup;
alc_init_jacks(codec);
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -16014,11 +15974,15 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, true);
+ const char *pfx = alc_get_line_out_pfx(spec, true);
hda_nid_t nid;
- int i, err;
+ int i, err, noutputs;
- for (i = 0; i < cfg->line_outs; i++) {
+ noutputs = cfg->line_outs;
+ if (spec->multi_ios > 0)
+ noutputs += spec->multi_ios;
+
+ for (i = 0; i < noutputs; i++) {
nid = spec->multiout.dac_nids[i];
if (!nid)
continue;
@@ -16163,6 +16127,9 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
@@ -16835,11 +16802,13 @@ static void alc861vd_lenovo_setup(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x1b;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc88x_simple_mic_automute(codec);
}
@@ -16851,7 +16820,7 @@ static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
alc88x_simple_mic_automute(codec);
break;
default:
- alc_automute_amp_unsol_event(codec, res);
+ alc_sku_unsol_event(codec, res);
break;
}
}
@@ -16908,6 +16877,8 @@ static void alc861vd_dallas_setup(struct hda_codec *codec)
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -17032,9 +17003,9 @@ static struct alc_config_preset alc861vd_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_dallas_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc861vd_dallas_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC861VD_HP] = {
.mixers = { alc861vd_hp_mixer },
@@ -17045,9 +17016,9 @@ static struct alc_config_preset alc861vd_presets[] = {
.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
.channel_mode = alc861vd_3stack_2ch_modes,
.input_mux = &alc861vd_hp_capture_source,
- .unsol_event = alc_automute_amp_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc861vd_dallas_setup,
- .init_hook = alc_automute_amp,
+ .init_hook = alc_hp_automute,
},
[ALC660VD_ASUS_V1S] = {
.mixers = { alc861vd_lenovo_mixer },
@@ -17146,11 +17117,15 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
static const char * const chname[4] = {
"Front", "Surround", "CLFE", "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, true);
+ const char *pfx = alc_get_line_out_pfx(spec, true);
hda_nid_t nid_v, nid_s;
- int i, err;
+ int i, err, noutputs;
- for (i = 0; i < cfg->line_outs; i++) {
+ noutputs = cfg->line_outs;
+ if (spec->multi_ios > 0)
+ noutputs += spec->multi_ios;
+
+ for (i = 0; i < noutputs; i++) {
if (!spec->multiout.dac_nids[i])
continue;
nid_v = alc861vd_idx_to_mixer_vol(
@@ -17275,6 +17250,9 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
@@ -17426,6 +17404,7 @@ static int patch_alc861vd(struct hda_codec *codec)
if (board_config == ALC861VD_AUTO)
spec->init_hook = alc861vd_auto_init;
+ spec->shutup = alc_eapd_shutup;
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861vd_loopbacks;
@@ -17448,8 +17427,8 @@ static int patch_alc861vd(struct hda_codec *codec)
#define ALC662_DIGOUT_NID 0x06
#define ALC662_DIGIN_NID 0x0a
-static hda_nid_t alc662_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
+static hda_nid_t alc662_dac_nids[3] = {
+ /* front, rear, clfe */
0x02, 0x03, 0x04
};
@@ -17938,32 +17917,13 @@ static struct hda_verb alc662_init_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* always trun on EAPD */
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-
{ }
};
-static struct hda_verb alc663_init_verbs[] = {
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- { }
-};
-
-static struct hda_verb alc272_init_verbs[] = {
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+static struct hda_verb alc662_eapd_init_verbs[] = {
+ /* always trun on EAPD */
+ {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+ {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
@@ -18179,49 +18139,17 @@ static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
{ } /* end */
};
-static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
+static void alc662_lenovo_101e_setup(struct hda_codec *codec)
{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x14);
- bits = present ? HDA_AMP_MUTE : 0;
-
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x1b);
- 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,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc662_lenovo_101e_all_automute(codec);
- if ((res >> 26) == ALC880_FRONT_EVENT)
- alc662_lenovo_101e_ispeaker_automute(codec);
-}
+ struct alc_spec *spec = codec->spec;
-/* unsolicited event for HP jack sensing */
-static void alc662_eeepc_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_MIC_EVENT)
- alc_mic_automute(codec);
- else
- alc262_hippo_unsol_event(codec, res);
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.line_out_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x15;
+ spec->automute = 1;
+ spec->detect_line = 1;
+ spec->automute_lines = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc662_eeepc_setup(struct hda_codec *codec)
@@ -18236,180 +18164,24 @@ static void alc662_eeepc_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc662_eeepc_inithook(struct hda_codec *codec)
-{
- alc262_hippo_automute(codec);
- alc_mic_automute(codec);
-}
-
static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x1b;
-}
-
-#define alc662_eeepc_ep20_inithook alc262_hippo_master_update
-
-static void alc663_m51va_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x21);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x21);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
- HDA_AMP_MUTE, bits);
- snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc662_f5z_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x1b);
- bits = present ? 0 : PIN_OUT;
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
-}
-
-static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_jack_detect(codec, 0x21);
- present2 = snd_hda_jack_detect(codec, 0x15);
-
- if (present1 || present2) {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- } else {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-}
-
-static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_jack_detect(codec, 0x1b);
- present2 = snd_hda_jack_detect(codec, 0x15);
-
- if (present1 || present2) {
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- } else {
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- HDA_AMP_MUTE, 0);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- HDA_AMP_MUTE, 0);
- }
-}
-
-static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- present2 = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
-
- if (present1 || present2) {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- } else {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-}
-
-static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present1, present2;
-
- present1 = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
- present2 = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0)
- & AC_PINSENSE_PRESENCE;
-
- if (present1 || present2) {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
- } else {
- snd_hda_codec_write_cache(codec, 0x14, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- snd_hda_codec_write_cache(codec, 0x17, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- }
-}
-
-static void alc663_m51va_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_m51va_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc663_m51va_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -18417,18 +18189,15 @@ static void alc663_m51va_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-static void alc663_m51va_inithook(struct hda_codec *codec)
-{
- alc663_m51va_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
/* ***************** Mode1 ******************************/
-#define alc663_mode1_unsol_event alc663_m51va_unsol_event
-
static void alc663_mode1_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -18436,228 +18205,143 @@ static void alc663_mode1_setup(struct hda_codec *codec)
spec->auto_mic = 1;
}
-#define alc663_mode1_inithook alc663_m51va_inithook
-
/* ***************** Mode2 ******************************/
-static void alc662_mode2_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc662_mode2_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc662_f5z_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc662_mode2_setup alc663_mode1_setup
-
-static void alc662_mode2_inithook(struct hda_codec *codec)
-{
- alc662_f5z_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode3 ******************************/
-static void alc663_mode3_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode3_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m1_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc663_mode3_setup alc663_mode1_setup
-
-static void alc663_mode3_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m1_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode4 ******************************/
-static void alc663_mode4_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode4_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_21jd_two_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[1] = 0x16;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute_mixer_nid[1] = 0x0e;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc663_mode4_setup alc663_mode1_setup
-
-static void alc663_mode4_inithook(struct hda_codec *codec)
-{
- alc663_21jd_two_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode5 ******************************/
-static void alc663_mode5_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode5_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_15jd_two_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ 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->automute_mixer_nid[0] = 0x0c;
+ spec->automute_mixer_nid[1] = 0x0e;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
-#define alc663_mode5_setup alc663_mode1_setup
-
-static void alc663_mode5_inithook(struct hda_codec *codec)
-{
- alc663_15jd_two_speaker_automute(codec);
- alc_mic_automute(codec);
-}
/* ***************** Mode6 ******************************/
-static void alc663_mode6_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode6_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m2_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_mode6_setup alc663_mode1_setup
-
-static void alc663_mode6_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m2_speaker_automute(codec);
- alc_mic_automute(codec);
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute_mixer_nid[0] = 0x0c;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_MIXER;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
/* ***************** Mode7 ******************************/
-static void alc663_mode7_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_mode7_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m7_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_mode7_setup alc663_mode1_setup
-
-static void alc663_mode7_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m7_speaker_automute(codec);
- alc_mic_automute(codec);
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x1b;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x19;
+ spec->int_mic.mux_idx = 1;
+ spec->auto_mic = 1;
}
/* ***************** Mode8 ******************************/
-static void alc663_mode8_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_two_hp_m8_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_mode8_setup alc663_m51va_setup
-
-static void alc663_mode8_inithook(struct hda_codec *codec)
-{
- alc663_two_hp_m8_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
-static void alc663_g71v_hp_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x21);
- 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,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_g71v_front_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x15);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc663_g71v_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_g71v_hp_automute(codec);
- break;
- case ALC880_FRONT_EVENT:
- alc663_g71v_front_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-#define alc663_g71v_setup alc663_m51va_setup
-
-static void alc663_g71v_inithook(struct hda_codec *codec)
+static void alc663_mode8_setup(struct hda_codec *codec)
{
- alc663_g71v_front_automute(codec);
- alc663_g71v_hp_automute(codec);
- alc_mic_automute(codec);
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.hp_pins[1] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->autocfg.speaker_pins[0] = 0x17;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x12;
+ spec->int_mic.mux_idx = 9;
+ spec->auto_mic = 1;
}
-static void alc663_g50v_unsol_event(struct hda_codec *codec,
- unsigned int res)
+static void alc663_g71v_setup(struct hda_codec *codec)
{
- switch (res >> 26) {
- case ALC880_HP_EVENT:
- alc663_m51va_speaker_automute(codec);
- break;
- case ALC880_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
+ struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x21;
+ spec->autocfg.line_out_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
+ spec->detect_line = 1;
+ spec->automute_lines = 1;
+ spec->ext_mic.pin = 0x18;
+ spec->ext_mic.mux_idx = 0;
+ spec->int_mic.pin = 0x12;
+ spec->int_mic.mux_idx = 9;
+ spec->auto_mic = 1;
}
#define alc663_g50v_setup alc663_m51va_setup
-static void alc663_g50v_inithook(struct hda_codec *codec)
-{
- alc663_m51va_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
static struct snd_kcontrol_new alc662_ecs_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
ALC262_HIPPO_MASTER_SWITCH,
@@ -18707,7 +18391,7 @@ static const char * const alc662_models[ALC662_MODEL_LAST] = {
[ALC662_3ST_2ch_DIG] = "3stack-dig",
[ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
[ALC662_3ST_6ch] = "3stack-6ch",
- [ALC662_5ST_DIG] = "6stack-dig",
+ [ALC662_5ST_DIG] = "5stack-dig",
[ALC662_LENOVO_101E] = "lenovo-101e",
[ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
[ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
@@ -18815,7 +18499,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
static struct alc_config_preset alc662_presets[] = {
[ALC662_3ST_2ch_DIG] = {
.mixers = { alc662_3ST_2ch_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
@@ -18826,7 +18510,7 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_3ST_6ch_DIG] = {
.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
@@ -18838,7 +18522,7 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_3ST_6ch] = {
.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
@@ -18848,7 +18532,7 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_5ST_DIG] = {
.mixers = { alc662_base_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs },
+ .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
@@ -18859,104 +18543,120 @@ static struct alc_config_preset alc662_presets[] = {
},
[ALC662_LENOVO_101E] = {
.mixers = { alc662_lenovo_101e_mixer },
- .init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc662_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
.input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc662_lenovo_101e_unsol_event,
- .init_hook = alc662_lenovo_101e_all_automute,
+ .unsol_event = alc_sku_unsol_event,
+ .setup = alc662_lenovo_101e_setup,
+ .init_hook = alc_inithook,
},
[ALC662_ASUS_EEEPC_P701] = {
.mixers = { alc662_eeepc_p701_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_eeepc_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc662_eeepc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_eeepc_setup,
- .init_hook = alc662_eeepc_inithook,
+ .init_hook = alc_inithook,
},
[ALC662_ASUS_EEEPC_EP20] = {
.mixers = { alc662_eeepc_ep20_mixer,
alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_eeepc_ep20_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
.channel_mode = alc662_3ST_6ch_modes,
.input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc662_eeepc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_eeepc_ep20_setup,
- .init_hook = alc662_eeepc_ep20_inithook,
+ .init_hook = alc_inithook,
},
[ALC662_ECS] = {
.mixers = { alc662_ecs_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_ecs_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc662_eeepc_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_eeepc_setup,
- .init_hook = alc662_eeepc_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_M51VA] = {
.mixers = { alc663_m51va_mixer },
- .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_m51va_setup,
- .init_hook = alc663_m51va_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_G71V] = {
.mixers = { alc663_g71v_mixer },
- .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_g71v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_g71v_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_g71v_setup,
- .init_hook = alc663_g71v_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_H13] = {
.mixers = { alc663_m51va_mixer },
- .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
- .init_hook = alc663_m51va_inithook,
+ .setup = alc663_m51va_setup,
+ .unsol_event = alc_sku_unsol_event,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_G50V] = {
.mixers = { alc663_g50v_mixer },
- .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc663_g50v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
.channel_mode = alc662_3ST_6ch_modes,
.input_mux = &alc663_capture_source,
- .unsol_event = alc663_g50v_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_g50v_setup,
- .init_hook = alc663_g50v_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE1] = {
.mixers = { alc663_m51va_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -18964,28 +18664,30 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode1_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode1_setup,
- .init_hook = alc663_mode1_inithook,
+ .init_hook = alc_inithook,
},
[ALC662_ASUS_MODE2] = {
.mixers = { alc662_1bjd_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc662_1bjd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc662_mode2_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc662_mode2_setup,
- .init_hook = alc662_mode2_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE3] = {
.mixers = { alc663_two_hp_m1_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_two_hp_amic_m1_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -18993,14 +18695,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode3_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode3_setup,
- .init_hook = alc663_mode3_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE4] = {
.mixers = { alc663_asus_21jd_clfe_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_21jd_amic_init_verbs},
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19008,14 +18711,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode4_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode4_setup,
- .init_hook = alc663_mode4_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE5] = {
.mixers = { alc663_asus_15jd_clfe_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_15jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19023,14 +18727,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode5_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode5_setup,
- .init_hook = alc663_mode5_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE6] = {
.mixers = { alc663_two_hp_m2_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_two_hp_amic_m2_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19038,14 +18743,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode6_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode6_setup,
- .init_hook = alc663_mode6_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE7] = {
.mixers = { alc663_mode7_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_mode7_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19053,14 +18759,15 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode7_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode7_setup,
- .init_hook = alc663_mode7_inithook,
+ .init_hook = alc_inithook,
},
[ALC663_ASUS_MODE8] = {
.mixers = { alc663_mode8_mixer },
.cap_mixer = alc662_auto_capture_mixer,
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_mode8_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.hp_nid = 0x03,
@@ -19068,52 +18775,57 @@ static struct alc_config_preset alc662_presets[] = {
.dig_out_nid = ALC662_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_mode8_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode8_setup,
- .init_hook = alc663_mode8_inithook,
+ .init_hook = alc_inithook,
},
[ALC272_DELL] = {
.mixers = { alc663_m51va_mixer },
.cap_mixer = alc272_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs, alc272_dell_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc272_dell_init_verbs },
.num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc662_dac_nids,
+ .dac_nids = alc272_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.adc_nids = alc272_adc_nids,
.num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
.capsrc_nids = alc272_capsrc_nids,
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_m51va_setup,
- .init_hook = alc663_m51va_inithook,
+ .init_hook = alc_inithook,
},
[ALC272_DELL_ZM1] = {
.mixers = { alc663_m51va_mixer },
.cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs, alc272_dell_zm1_init_verbs },
+ .init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
+ alc272_dell_zm1_init_verbs },
.num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc662_dac_nids,
+ .dac_nids = alc272_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.adc_nids = alc662_adc_nids,
.num_adc_nids = 1,
.capsrc_nids = alc662_capsrc_nids,
.channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc663_m51va_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_m51va_setup,
- .init_hook = alc663_m51va_inithook,
+ .init_hook = alc_inithook,
},
[ALC272_SAMSUNG_NC10] = {
.mixers = { alc272_nc10_mixer },
.init_verbs = { alc662_init_verbs,
+ alc662_eapd_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc272_dac_nids),
.dac_nids = alc272_dac_nids,
.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
.channel_mode = alc662_3ST_2ch_modes,
/*.input_mux = &alc272_nc10_capture_source,*/
- .unsol_event = alc663_mode4_unsol_event,
+ .unsol_event = alc_sku_unsol_event,
.setup = alc663_mode4_setup,
- .init_hook = alc663_mode4_inithook,
+ .init_hook = alc_inithook,
},
};
@@ -19123,45 +18835,79 @@ static struct alc_config_preset alc662_presets[] = {
*/
/* convert from MIX nid to DAC */
-static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid)
-{
- if (nid == 0x0f)
- return 0x02;
- else if (nid >= 0x0c && nid <= 0x0e)
- return nid - 0x0c + 0x02;
- else if (nid == 0x26) /* ALC887-VD has this DAC too */
- return 0x25;
- else
- return 0;
+static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
+{
+ hda_nid_t list[5];
+ int i, num;
+
+ num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
+ for (i = 0; i < num; i++) {
+ if (get_wcaps_type(get_wcaps(codec, list[i])) == AC_WID_AUD_OUT)
+ return list[i];
+ }
+ return 0;
+}
+
+/* go down to the selector widget before the mixer */
+static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
+{
+ hda_nid_t srcs[5];
+ int num = snd_hda_get_connections(codec, pin, srcs,
+ ARRAY_SIZE(srcs));
+ if (num != 1 ||
+ get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
+ return pin;
+ return srcs[0];
}
/* get MIX nid connected to the given pin targeted to DAC */
-static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
+static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
hda_nid_t dac)
{
hda_nid_t mix[5];
int i, num;
+ pin = alc_go_down_to_selector(codec, pin);
num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
for (i = 0; i < num; i++) {
- if (alc662_mix_to_dac(mix[i]) == dac)
+ if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
return mix[i];
}
return 0;
}
+/* select the connection from pin to DAC if needed */
+static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
+ hda_nid_t dac)
+{
+ hda_nid_t mix[5];
+ int i, num;
+
+ pin = alc_go_down_to_selector(codec, pin);
+ num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
+ if (num < 2)
+ return 0;
+ for (i = 0; i < num; i++) {
+ if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
+ snd_hda_codec_update_cache(codec, pin, 0,
+ AC_VERB_SET_CONNECT_SEL, i);
+ return 0;
+ }
+ }
+ return 0;
+}
+
/* look for an empty DAC slot */
-static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
{
struct alc_spec *spec = codec->spec;
hda_nid_t srcs[5];
int i, j, num;
+ pin = alc_go_down_to_selector(codec, pin);
num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
- if (num < 0)
- return 0;
for (i = 0; i < num; i++) {
- hda_nid_t nid = alc662_mix_to_dac(srcs[i]);
+ hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
if (!nid)
continue;
for (j = 0; j < spec->multiout.num_dacs; j++)
@@ -19183,7 +18929,7 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
spec->multiout.dac_nids = spec->private_dac_nids;
for (i = 0; i < cfg->line_outs; i++) {
- dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
+ dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
if (!dac)
continue;
spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
@@ -19222,15 +18968,23 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
static const char * const chname[4] = {
"Front", "Surround", NULL /*CLFE*/, "Side"
};
- const char *pfx = alc_get_line_out_pfx(cfg, true);
- hda_nid_t nid, mix;
- int i, err;
+ const char *pfx = alc_get_line_out_pfx(spec, true);
+ hda_nid_t nid, mix, pin;
+ int i, err, noutputs;
- for (i = 0; i < cfg->line_outs; i++) {
+ noutputs = cfg->line_outs;
+ if (spec->multi_ios > 0)
+ noutputs += spec->multi_ios;
+
+ for (i = 0; i < noutputs; i++) {
nid = spec->multiout.dac_nids[i];
if (!nid)
continue;
- mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
+ if (i >= cfg->line_outs)
+ pin = spec->multi_io[i - 1].pin;
+ else
+ pin = cfg->line_out_pins[i];
+ mix = alc_auto_dac_to_mix(codec, pin, nid);
if (!mix)
continue;
if (!pfx && i == 2) {
@@ -19276,7 +19030,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
if (!pin)
return 0;
- nid = alc662_look_for_dac(codec, pin);
+ nid = alc_auto_look_for_dac(codec, pin);
if (!nid) {
/* the corresponding DAC is already occupied */
if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
@@ -19286,7 +19040,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
}
- mix = alc662_dac_to_mix(codec, pin, nid);
+ mix = alc_auto_dac_to_mix(codec, pin, nid);
if (!mix)
return 0;
err = alc662_add_vol_ctl(spec, pfx, nid, 3);
@@ -19310,14 +19064,21 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t srcs[HDA_MAX_CONNECTIONS];
alc_set_pin_output(codec, nid, pin_type);
- /* need the manual connection? */
num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
- if (num <= 1)
- return;
for (i = 0; i < num; i++) {
- if (alc662_mix_to_dac(srcs[i]) != dac)
+ if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
continue;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, i);
+ /* need the manual connection? */
+ if (num > 1)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CONNECT_SEL, i);
+ /* unmute mixer widget inputs */
+ snd_hda_codec_write(codec, srcs[i], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(0));
+ snd_hda_codec_write(codec, srcs[i], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_IN_UNMUTE(1));
return;
}
}
@@ -19374,6 +19135,159 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
#define alc662_auto_init_input_src alc882_auto_init_input_src
+/*
+ * multi-io helper
+ */
+static int alc_auto_fill_multi_ios(struct hda_codec *codec,
+ unsigned int location)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int type, i, num_pins = 0;
+
+ for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+ for (i = 0; i < cfg->num_inputs; i++) {
+ hda_nid_t nid = cfg->inputs[i].pin;
+ hda_nid_t dac;
+ unsigned int defcfg, caps;
+ if (cfg->inputs[i].type != type)
+ continue;
+ defcfg = snd_hda_codec_get_pincfg(codec, nid);
+ if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+ continue;
+ if (location && get_defcfg_location(defcfg) != location)
+ continue;
+ caps = snd_hda_query_pin_caps(codec, nid);
+ if (!(caps & AC_PINCAP_OUT))
+ continue;
+ dac = alc_auto_look_for_dac(codec, nid);
+ if (!dac)
+ continue;
+ spec->multi_io[num_pins].pin = nid;
+ spec->multi_io[num_pins].dac = dac;
+ num_pins++;
+ spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+ }
+ }
+ spec->multiout.num_dacs = 1;
+ if (num_pins < 2)
+ return 0;
+ return num_pins;
+}
+
+static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = spec->multi_ios + 1;
+ if (uinfo->value.enumerated.item > spec->multi_ios)
+ uinfo->value.enumerated.item = spec->multi_ios;
+ sprintf(uinfo->value.enumerated.name, "%dch",
+ (uinfo->value.enumerated.item + 1) * 2);
+ return 0;
+}
+
+static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
+ return 0;
+}
+
+static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t nid = spec->multi_io[idx].pin;
+
+ if (!spec->multi_io[idx].ctl_in)
+ spec->multi_io[idx].ctl_in =
+ snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (output) {
+ snd_hda_codec_update_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ PIN_OUT);
+ if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, 0);
+ alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
+ } else {
+ if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+ HDA_AMP_MUTE, HDA_AMP_MUTE);
+ snd_hda_codec_update_cache(codec, nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ spec->multi_io[idx].ctl_in);
+ }
+ return 0;
+}
+
+static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ int i, ch;
+
+ ch = ucontrol->value.enumerated.item[0];
+ if (ch < 0 || ch > spec->multi_ios)
+ return -EINVAL;
+ if (ch == (spec->ext_channel_count - 1) / 2)
+ return 0;
+ spec->ext_channel_count = (ch + 1) * 2;
+ for (i = 0; i < spec->multi_ios; i++)
+ alc_set_multi_io(codec, i, i < ch);
+ spec->multiout.max_channels = spec->ext_channel_count;
+ return 1;
+}
+
+static struct snd_kcontrol_new alc_auto_channel_mode_enum = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc_auto_ch_mode_info,
+ .get = alc_auto_ch_mode_get,
+ .put = alc_auto_ch_mode_put,
+};
+
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int location, defcfg;
+ int num_pins;
+
+ if (cfg->line_outs != 1 ||
+ cfg->line_out_type != AUTO_PIN_LINE_OUT)
+ return 0;
+
+ defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
+ location = get_defcfg_location(defcfg);
+
+ num_pins = alc_auto_fill_multi_ios(codec, location);
+ if (num_pins > 0) {
+ struct snd_kcontrol_new *knew;
+
+ knew = alc_kcontrol_new(spec);
+ if (!knew)
+ return -ENOMEM;
+ *knew = alc_auto_channel_mode_enum;
+ knew->name = kstrdup("Channel Mode", GFP_KERNEL);
+ if (!knew->name)
+ return -ENOMEM;
+
+ spec->multi_ios = num_pins;
+ spec->ext_channel_count = 2;
+ spec->multiout.num_dacs = num_pins + 1;
+ }
+ return 0;
+}
+
static int alc662_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -19390,6 +19304,9 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
if (err < 0)
return err;
+ err = alc_auto_add_multi_channel_mode(codec);
+ if (err < 0)
+ return err;
err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
@@ -19420,14 +19337,6 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0];
- add_verb(spec, alc662_init_verbs);
- if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
- codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
- add_verb(spec, alc663_init_verbs);
-
- if (codec->vendor_id == 0x10ec0272)
- add_verb(spec, alc272_init_verbs);
-
err = alc_auto_add_mic_boost(codec);
if (err < 0)
return err;
@@ -19626,6 +19535,7 @@ static int patch_alc662(struct hda_codec *codec)
codec->patch_ops = alc_patch_ops;
if (board_config == ALC662_AUTO)
spec->init_hook = alc662_auto_init;
+ spec->shutup = alc_eapd_shutup;
alc_init_jacks(codec);
@@ -19824,20 +19734,22 @@ static void alc680_base_setup(struct hda_codec *codec)
spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
spec->autocfg.inputs[1].pin = 0x19;
spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
+ spec->automute = 1;
+ spec->automute_mode = ALC_AUTOMUTE_AMP;
}
static void alc680_unsol_event(struct hda_codec *codec,
unsigned int res)
{
if ((res >> 26) == ALC880_HP_EVENT)
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
if ((res >> 26) == ALC880_MIC_EVENT)
alc680_rec_autoswitch(codec);
}
static void alc680_inithook(struct hda_codec *codec)
{
- alc_automute_amp(codec);
+ alc_hp_automute(codec);
alc680_rec_autoswitch(codec);
}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 94d19c03a7f4..2b590d92ff90 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -5729,15 +5729,6 @@ again:
if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)
snd_hda_sequence_write_cache(codec, unmute_init);
- /* Some HP machines seem to have unstable codec communications
- * especially with ATI fglrx driver. For recovering from the
- * CORB/RIRB stall, allow the BUS reset and keep always sync
- */
- if (spec->board_config == STAC_HP_DV5) {
- codec->bus->sync_write = 1;
- codec->bus->allow_bus_reset = 1;
- }
-
spec->aloopback_ctl = stac92hd71bxx_loopback;
spec->aloopback_mask = 0x50;
spec->aloopback_shift = 0;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 0997031c48d2..6a51ffb266f9 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -98,9 +98,15 @@ enum VIA_HDA_CODEC {
VT1716S,
VT2002P,
VT1812,
+ VT1802,
CODEC_TYPES,
};
+#define VT2002P_COMPATIBLE(spec) \
+ ((spec)->codec_type == VT2002P ||\
+ (spec)->codec_type == VT1812 ||\
+ (spec)->codec_type == VT1802)
+
struct via_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[6];
@@ -154,6 +160,9 @@ struct via_spec {
struct delayed_work vt1708_hp_work;
int vt1708_jack_detectect;
int vt1708_hp_present;
+
+ void (*set_widgets_power_state)(struct hda_codec *codec);
+
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
#endif
@@ -218,17 +227,19 @@ static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
codec_type = VT1812;
else if (dev_id == 0x0440)
codec_type = VT1708S;
+ else if ((dev_id & 0xfff) == 0x446)
+ codec_type = VT1802;
else
codec_type = UNKNOWN;
return codec_type;
};
+#define VIA_JACK_EVENT 0x20
#define VIA_HP_EVENT 0x01
#define VIA_GPIO_EVENT 0x02
-#define VIA_JACK_EVENT 0x04
-#define VIA_MONO_EVENT 0x08
-#define VIA_SPEAKER_EVENT 0x10
-#define VIA_BIND_HP_EVENT 0x20
+#define VIA_MONO_EVENT 0x03
+#define VIA_SPEAKER_EVENT 0x04
+#define VIA_BIND_HP_EVENT 0x05
enum {
VIA_CTL_WIDGET_VOL,
@@ -245,7 +256,6 @@ enum {
};
static void analog_low_current_mode(struct hda_codec *codec, int stream_idle);
-static void set_jack_power_state(struct hda_codec *codec);
static int is_aa_path_mute(struct hda_codec *codec);
static void vt1708_start_hp_work(struct via_spec *spec)
@@ -271,6 +281,12 @@ static void vt1708_stop_hp_work(struct via_spec *spec)
cancel_delayed_work_sync(&spec->vt1708_hp_work);
}
+static void set_widgets_power_state(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ if (spec->set_widgets_power_state)
+ spec->set_widgets_power_state(codec);
+}
static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -278,7 +294,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1);
if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
if (is_aa_path_mute(codec))
@@ -602,482 +618,6 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
}
-static void set_jack_power_state(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
- int imux_is_smixer;
- unsigned int parm;
-
- if (spec->codec_type == VT1702) {
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
- /* inputs */
- /* PW 1/2/5 (14h/15h/18h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x14, &parm);
- set_pin_power_state(codec, 0x15, &parm);
- set_pin_power_state(codec, 0x18, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0; /* SW0 = stereo mixer (idx 3) */
- /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW 3/4 (16h/17h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x16, &parm);
- set_pin_power_state(codec, 0x17, &parm);
- /* MW0 (1ah), AOW 0/1 (10h/1dh) */
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE,
- parm);
- } else if (spec->codec_type == VT1708B_8CH
- || spec->codec_type == VT1708B_4CH
- || spec->codec_type == VT1708S) {
- /* SW0 (17h) = stereo mixer */
- int is_8ch = spec->codec_type != VT1708B_4CH;
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
- == ((spec->codec_type == VT1708S) ? 5 : 0);
- /* inputs */
- /* PW 1/2/5 (1ah/1bh/1eh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1a, &parm);
- set_pin_power_state(codec, 0x1b, &parm);
- set_pin_power_state(codec, 0x1e, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* SW0 (17h), AIW 0/1 (13h/14h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW0 (19h), SW1 (18h), AOW1 (11h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x19, &parm);
- if (spec->smart51_enabled)
- parm = AC_PWRST_D0;
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW6 (22h), SW2 (26h), AOW2 (24h) */
- if (is_8ch) {
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x22, &parm);
- if (spec->smart51_enabled)
- parm = AC_PWRST_D0;
- snd_hda_codec_write(codec, 0x26, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x24, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
-
- /* PW 3/4/7 (1ch/1dh/23h) */
- parm = AC_PWRST_D3;
- /* force to D0 for internal Speaker */
- set_pin_power_state(codec, 0x1c, &parm);
- set_pin_power_state(codec, 0x1d, &parm);
- if (is_8ch)
- set_pin_power_state(codec, 0x23, &parm);
- /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- parm);
- if (is_8ch) {
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
- } else if (spec->codec_type == VT1718S) {
- /* MUX6 (1eh) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
- /* inputs */
- /* PW 5/6/7 (29h/2ah/2bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x29, &parm);
- set_pin_power_state(codec, 0x2a, &parm);
- set_pin_power_state(codec, 0x2b, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x27, &parm);
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW2 (26h), AOW2 (ah) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW0/1 (24h/25h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x24, &parm);
- set_pin_power_state(codec, 0x25, &parm);
- if (!spec->hp_independent_mode) /* check for redirected HP */
- set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE,
- parm);
- /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
- snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- if (spec->hp_independent_mode) {
- /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x1b, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
- } else if (spec->codec_type == VT1716S) {
- unsigned int mono_out, present;
- /* SW0 (17h) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
- /* inputs */
- /* PW 1/2/5 (1ah/1bh/1eh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1a, &parm);
- set_pin_power_state(codec, 0x1b, &parm);
- set_pin_power_state(codec, 0x1e, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* SW0 (17h), AIW0(13h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1e, &parm);
- /* PW11 (22h) */
- if (spec->dmic_enabled)
- set_pin_power_state(codec, 0x22, &parm);
- else
- snd_hda_codec_write(
- codec, 0x22, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
-
- /* SW2(26h), AIW1(14h) */
- snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* outputs */
- /* PW0 (19h), SW1 (18h), AOW1 (11h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x19, &parm);
- /* Smart 5.1 PW2(1bh) */
- if (spec->smart51_enabled)
- set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW7 (23h), SW3 (27h), AOW3 (25h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x23, &parm);
- /* Smart 5.1 PW1(1ah) */
- if (spec->smart51_enabled)
- set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* Smart 5.1 PW5(1eh) */
- if (spec->smart51_enabled)
- set_pin_power_state(codec, 0x1e, &parm);
- snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* Mono out */
- /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
- present = snd_hda_jack_detect(codec, 0x1c);
- if (present)
- mono_out = 0;
- else {
- present = snd_hda_jack_detect(codec, 0x1d);
- if (!spec->hp_independent_mode && present)
- mono_out = 0;
- else
- mono_out = 1;
- }
- parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
- snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE,
- parm);
- snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE,
- parm);
-
- /* PW 3/4 (1ch/1dh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x1c, &parm);
- set_pin_power_state(codec, 0x1d, &parm);
- /* HP Independent Mode, power on AOW3 */
- if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* force to D0 for internal Speaker */
- /* MW0 (16h), AOW0 (10h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- mono_out ? AC_PWRST_D0 : parm);
- } else if (spec->codec_type == VT2002P) {
- unsigned int present;
- /* MUX9 (1eh) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
- /* inputs */
- /* PW 5/6/7 (29h/2ah/2bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x29, &parm);
- set_pin_power_state(codec, 0x2a, &parm);
- set_pin_power_state(codec, 0x2b, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* outputs */
- /* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-
- /* PW4 (26h), MW4 (1ch), MUX4(37h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x37,
- 0, AC_VERB_SET_POWER_STATE, parm);
-
- /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x19, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
- if (spec->hp_independent_mode) {
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
-
- /* Class-D */
- /* PW0 (24h), MW0(18h), MUX0(34h) */
- present = snd_hda_jack_detect(codec, 0x25);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x24, &parm);
- if (present) {
- snd_hda_codec_write(
- codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(
- codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- } else {
- snd_hda_codec_write(
- codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(
- codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- }
-
- /* Mono Out */
- /* PW15 (31h), MW8(17h), MUX8(3bh) */
- present = snd_hda_jack_detect(codec, 0x26);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x31, &parm);
- if (present) {
- snd_hda_codec_write(
- codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(
- codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- } else {
- snd_hda_codec_write(
- codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(
- codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- }
-
- /* MW9 (21h) */
- if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- else
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- } else if (spec->codec_type == VT1812) {
- unsigned int present;
- /* MUX10 (1eh) = stereo mixer */
- imux_is_smixer = snd_hda_codec_read(
- codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
- /* inputs */
- /* PW 5/6/7 (29h/2ah/2bh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x29, &parm);
- set_pin_power_state(codec, 0x2a, &parm);
- set_pin_power_state(codec, 0x2b, &parm);
- if (imux_is_smixer)
- parm = AC_PWRST_D0;
- /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* outputs */
- /* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-
- /* PW4 (28h), MW4 (18h), MUX4(38h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
- if (spec->hp_independent_mode) {
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, parm);
- }
-
- /* Internal Speaker */
- /* PW0 (24h), MW0(14h), MUX0(34h) */
- present = snd_hda_jack_detect(codec, 0x25);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x24, &parm);
- if (present) {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- } else {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- }
- /* Mono Out */
- /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
- present = snd_hda_jack_detect(codec, 0x28);
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x31, &parm);
- if (present) {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D3);
- } else {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE,
- AC_PWRST_D0);
- }
-
- /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
- parm = AC_PWRST_D3;
- set_pin_power_state(codec, 0x33, &parm);
- snd_hda_codec_write(codec, 0x1d, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3d, 0,
- AC_VERB_SET_POWER_STATE, parm);
-
- /* MW9 (21h) */
- if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- else
- snd_hda_codec_write(
- codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- }
-}
-
/*
* input MUX handling
*/
@@ -1120,7 +660,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
spec->mux_nids[adc_idx],
&spec->cur_mux[adc_idx]);
/* update jack power state */
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
return ret;
}
@@ -1168,6 +708,9 @@ static hda_nid_t side_mute_channel(struct via_spec *spec)
case VT1709_10CH: return 0x29;
case VT1708B_8CH: /* fall thru */
case VT1708S: return 0x27;
+ case VT2002P: return 0x19;
+ case VT1802: return 0x15;
+ case VT1812: return 0x15;
default: return 0;
}
}
@@ -1176,13 +719,22 @@ static int update_side_mute_status(struct hda_codec *codec)
{
/* mute side channel */
struct via_spec *spec = codec->spec;
- unsigned int parm = spec->hp_independent_mode
- ? AMP_OUT_MUTE : AMP_OUT_UNMUTE;
+ unsigned int parm;
hda_nid_t sw3 = side_mute_channel(spec);
- if (sw3)
- snd_hda_codec_write(codec, sw3, 0, AC_VERB_SET_AMP_GAIN_MUTE,
- parm);
+ if (sw3) {
+ if (VT2002P_COMPATIBLE(spec))
+ parm = spec->hp_independent_mode ?
+ AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1);
+ else
+ parm = spec->hp_independent_mode ?
+ AMP_OUT_MUTE : AMP_OUT_UNMUTE;
+ snd_hda_codec_write(codec, sw3, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, parm);
+ if (spec->codec_type == VT1812)
+ snd_hda_codec_write(codec, 0x1d, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, parm);
+ }
return 0;
}
@@ -1217,15 +769,14 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
|| spec->codec_type == VT1702
|| spec->codec_type == VT1718S
|| spec->codec_type == VT1716S
- || spec->codec_type == VT2002P
- || spec->codec_type == VT1812) {
+ || VT2002P_COMPATIBLE(spec)) {
activate_ctl(codec, "Headphone Playback Volume",
spec->hp_independent_mode);
activate_ctl(codec, "Headphone Playback Switch",
spec->hp_independent_mode);
}
/* update jack power state */
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
return 0;
}
@@ -1256,6 +807,7 @@ static int via_hp_build(struct hda_codec *codec)
nid = 0x34;
break;
case VT2002P:
+ case VT1802:
nid = 0x35;
break;
case VT1812:
@@ -1447,7 +999,7 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
}
}
spec->smart51_enabled = *ucontrol->value.integer.value;
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
return 1;
}
@@ -1473,6 +1025,11 @@ static int via_smart51_build(struct via_spec *spec)
hda_nid_t nid;
int i;
+ if (!cfg)
+ return 0;
+ if (cfg->line_outs > 2)
+ return 0;
+
knew = via_clone_control(spec, &via_smart51_mixer[0]);
if (knew == NULL)
return -ENOMEM;
@@ -1543,6 +1100,7 @@ static int is_aa_path_mute(struct hda_codec *codec)
break;
case VT2002P:
case VT1812:
+ case VT1802:
nid_mixer = 0x21;
start_idx = 0;
end_idx = 2;
@@ -1607,6 +1165,7 @@ static void analog_low_current_mode(struct hda_codec *codec, int stream_idle)
break;
case VT2002P:
case VT1812:
+ case VT1802:
verb = 0xf93;
parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
break;
@@ -1650,6 +1209,8 @@ static struct hda_verb vt1708_volume_init_verbs[] = {
{0x20, AC_VERB_SET_CONNECT_SEL, 0},
/* PW9 Output enable */
{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* power down jack detect function */
+ {0x1, 0xf81, 0x1},
{ }
};
@@ -1971,7 +1532,7 @@ static int via_build_controls(struct hda_codec *codec)
}
/* init power states */
- set_jack_power_state(codec);
+ set_widgets_power_state(codec);
analog_low_current_mode(codec, 1);
via_free_kctls(codec); /* no longer needed */
@@ -2135,7 +1696,7 @@ static void via_speaker_automute(struct hda_codec *codec)
unsigned int hp_present;
struct via_spec *spec = codec->spec;
- if (spec->codec_type != VT2002P && spec->codec_type != VT1812)
+ if (!VT2002P_COMPATIBLE(spec))
return;
hp_present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
@@ -2194,17 +1755,21 @@ static void via_unsol_event(struct hda_codec *codec,
unsigned int res)
{
res >>= 26;
- if (res & VIA_HP_EVENT)
+
+ if (res & VIA_JACK_EVENT)
+ set_widgets_power_state(codec);
+
+ res &= ~VIA_JACK_EVENT;
+
+ if (res == VIA_HP_EVENT)
via_hp_automute(codec);
- if (res & VIA_GPIO_EVENT)
+ else if (res == VIA_GPIO_EVENT)
via_gpio_control(codec);
- if (res & VIA_JACK_EVENT)
- set_jack_power_state(codec);
- if (res & VIA_MONO_EVENT)
+ else if (res == VIA_MONO_EVENT)
via_mono_automute(codec);
- if (res & VIA_SPEAKER_EVENT)
+ else if (res == VIA_SPEAKER_EVENT)
via_speaker_automute(codec);
- if (res & VIA_BIND_HP_EVENT)
+ else if (res == VIA_BIND_HP_EVENT)
via_hp_bind_automute(codec);
}
@@ -2623,7 +2188,8 @@ static int via_auto_init(struct hda_codec *codec)
via_auto_init_multi_out(codec);
via_auto_init_hp_out(codec);
via_auto_init_analog_input(codec);
- if (spec->codec_type == VT2002P || spec->codec_type == VT1812) {
+
+ if (VT2002P_COMPATIBLE(spec)) {
via_hp_bind_automute(codec);
} else {
via_hp_automute(codec);
@@ -3646,6 +3212,87 @@ static struct hda_amp_list vt1708B_loopbacks[] = {
{ } /* end */
};
#endif
+
+static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ int is_8ch = 0;
+ if ((spec->codec_type != VT1708B_4CH) &&
+ (codec->vendor_id != 0x11064397))
+ is_8ch = 1;
+
+ /* SW0 (17h) = stereo mixer */
+ imux_is_smixer =
+ (snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
+ == ((spec->codec_type == VT1708S) ? 5 : 0));
+ /* inputs */
+ /* PW 1/2/5 (1ah/1bh/1eh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1a, &parm);
+ set_pin_power_state(codec, 0x1b, &parm);
+ set_pin_power_state(codec, 0x1e, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* SW0 (17h), AIW 0/1 (13h/14h) */
+ snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW0 (19h), SW1 (18h), AOW1 (11h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x19, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1b, &parm);
+ snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW6 (22h), SW2 (26h), AOW2 (24h) */
+ if (is_8ch) {
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x22, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1a, &parm);
+ snd_hda_codec_write(codec, 0x26, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x24, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else if (codec->vendor_id == 0x11064397) {
+ /* PW7(23h), SW2(27h), AOW2(25h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x23, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1a, &parm);
+ snd_hda_codec_write(codec, 0x27, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+
+ /* PW 3/4/7 (1ch/1dh/23h) */
+ parm = AC_PWRST_D3;
+ /* force to D0 for internal Speaker */
+ set_pin_power_state(codec, 0x1c, &parm);
+ set_pin_power_state(codec, 0x1d, &parm);
+ if (is_8ch)
+ set_pin_power_state(codec, 0x23, &parm);
+
+ /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
+ snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ if (is_8ch) {
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x27, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+}
+
static int patch_vt1708S(struct hda_codec *codec);
static int patch_vt1708B_8ch(struct hda_codec *codec)
{
@@ -3696,6 +3343,8 @@ static int patch_vt1708B_8ch(struct hda_codec *codec)
spec->loopback.amplist = vt1708B_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
+
return 0;
}
@@ -3746,6 +3395,8 @@ static int patch_vt1708B_4ch(struct hda_codec *codec)
spec->loopback.amplist = vt1708B_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
+
return 0;
}
@@ -3814,6 +3465,18 @@ static struct hda_verb vt1708S_uniwill_init_verbs[] = {
{ }
};
+static struct hda_verb vt1705_uniwill_init_verbs[] = {
+ {0x1d, AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT},
+ {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x23, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ { }
+};
+
static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
.substreams = 2,
.channels_min = 2,
@@ -3827,6 +3490,19 @@ static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
},
};
+static struct hda_pcm_stream vt1705_pcm_analog_playback = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 6,
+ .nid = 0x10, /* NID to query formats and rates */
+ .ops = {
+ .open = via_playback_pcm_open,
+ .prepare = via_playback_multi_pcm_prepare,
+ .cleanup = via_playback_multi_pcm_cleanup,
+ .close = via_pcm_open_close
+ },
+};
+
static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
@@ -3873,7 +3549,10 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
spec->multiout.dac_nids[i] = 0x10;
break;
case AUTO_SEQ_CENLFE:
- spec->multiout.dac_nids[i] = 0x24;
+ if (spec->codec->vendor_id == 0x11064397)
+ spec->multiout.dac_nids[i] = 0x25;
+ else
+ spec->multiout.dac_nids[i] = 0x24;
break;
case AUTO_SEQ_SURROUND:
spec->multiout.dac_nids[i] = 0x11;
@@ -3889,22 +3568,28 @@ static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
if (cfg->line_outs == 1) {
spec->multiout.num_dacs = 3;
spec->multiout.dac_nids[AUTO_SEQ_SURROUND] = 0x11;
- spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x24;
+ if (spec->codec->vendor_id == 0x11064397)
+ spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x25;
+ else
+ spec->multiout.dac_nids[AUTO_SEQ_CENLFE] = 0x24;
}
return 0;
}
/* add playback controls from the parsed DAC table */
-static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
+static int vt1708S_auto_create_multi_out_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg)
{
+ struct via_spec *spec = codec->spec;
char name[32];
static const char * const chname[4] = {
"Front", "Surround", "C/LFE", "Side"
};
- hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
- hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
+ hda_nid_t nid_vols[2][4] = { {0x10, 0x11, 0x24, 0x25},
+ {0x10, 0x11, 0x25, 0} };
+ hda_nid_t nid_mutes[2][4] = { {0x1C, 0x18, 0x26, 0x27},
+ {0x1C, 0x18, 0x27, 0} };
hda_nid_t nid, nid_vol, nid_mute;
int i, err;
@@ -3915,8 +3600,15 @@ static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
if (!nid && i > AUTO_SEQ_CENLFE)
continue;
- nid_vol = nid_vols[i];
- nid_mute = nid_mutes[i];
+ if (codec->vendor_id == 0x11064397) {
+ nid_vol = nid_vols[1][i];
+ nid_mute = nid_mutes[1][i];
+ } else {
+ nid_vol = nid_vols[0][i];
+ nid_mute = nid_mutes[0][i];
+ }
+ if (!nid_vol && !nid_mute)
+ continue;
if (i == AUTO_SEQ_CENLFE) {
/* Center/LFE */
@@ -4070,7 +3762,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
return 0; /* can't find valid BIOS pin config */
- err = vt1708S_auto_create_multi_out_ctls(spec, &spec->autocfg);
+ err = vt1708S_auto_create_multi_out_ctls(codec, &spec->autocfg);
if (err < 0)
return err;
err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
@@ -4137,17 +3829,29 @@ static int patch_vt1708S(struct hda_codec *codec)
}
spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
- spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs;
+ if (codec->vendor_id == 0x11064397)
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1705_uniwill_init_verbs;
+ else
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1708S_uniwill_init_verbs;
if (codec->vendor_id == 0x11060440)
spec->stream_name_analog = "VT1818S Analog";
+ else if (codec->vendor_id == 0x11064397)
+ spec->stream_name_analog = "VT1705 Analog";
else
spec->stream_name_analog = "VT1708S Analog";
- spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
+ if (codec->vendor_id == 0x11064397)
+ spec->stream_analog_playback = &vt1705_pcm_analog_playback;
+ else
+ spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
if (codec->vendor_id == 0x11060440)
spec->stream_name_digital = "VT1818S Digital";
+ else if (codec->vendor_id == 0x11064397)
+ spec->stream_name_digital = "VT1705 Digital";
else
spec->stream_name_digital = "VT1708S Digital";
spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
@@ -4185,6 +3889,15 @@ static int patch_vt1708S(struct hda_codec *codec)
spec->stream_name_analog = "VT1818S Analog";
spec->stream_name_digital = "VT1818S Digital";
}
+ /* correct names for VT1705 */
+ if (codec->vendor_id == 0x11064397) {
+ kfree(codec->chip_name);
+ codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
+ snprintf(codec->bus->card->mixername,
+ sizeof(codec->bus->card->mixername),
+ "%s %s", codec->vendor_name, codec->chip_name);
+ }
+ spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
return 0;
}
@@ -4442,6 +4155,37 @@ static struct hda_amp_list vt1702_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1702(struct hda_codec *codec)
+{
+ int imux_is_smixer =
+ snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+ unsigned int parm;
+ /* inputs */
+ /* PW 1/2/5 (14h/15h/18h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x14, &parm);
+ set_pin_power_state(codec, 0x15, &parm);
+ set_pin_power_state(codec, 0x18, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
+ /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
+ snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW 3/4 (16h/17h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x17, &parm);
+ set_pin_power_state(codec, 0x16, &parm);
+ /* MW0 (1ah), AOW 0/1 (10h/1dh) */
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
static int patch_vt1702(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -4488,6 +4232,7 @@ static int patch_vt1702(struct hda_codec *codec)
spec->loopback.amplist = vt1702_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1702;
return 0;
}
@@ -4523,7 +4268,8 @@ static struct hda_verb vt1718S_volume_init_verbs[] = {
{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
+ /* Enable MW0 adjust Gain 5 */
+ {0x1, 0xfb2, 0x10},
/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
*/
@@ -4532,7 +4278,7 @@ static struct hda_verb vt1718S_volume_init_verbs[] = {
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
/* Setup default input of Front HP to MW9 */
{0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
@@ -4829,6 +4575,72 @@ static struct hda_amp_list vt1718S_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ /* MUX6 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
+ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x27, &parm);
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW2 (26h), AOW2 (ah) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x26, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x2b, &parm);
+ snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW0 (24h), AOW0 (8h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ if (!spec->hp_independent_mode) /* check for redirected HP */
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
+ snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+
+ /* PW1 (25h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x2a, &parm);
+ snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ if (spec->hp_independent_mode) {
+ /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x1b, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x34, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0xc, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+}
+
static int patch_vt1718S(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -4890,6 +4702,8 @@ static int patch_vt1718S(struct hda_codec *codec)
spec->loopback.amplist = vt1718S_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1718S;
+
return 0;
}
@@ -4929,8 +4743,7 @@ static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
snd_hda_codec_write(codec, 0x26, 0,
AC_VERB_SET_CONNECT_SEL, index);
spec->dmic_enabled = index;
- set_jack_power_state(codec);
-
+ set_widgets_power_state(codec);
return 1;
}
@@ -5289,6 +5102,99 @@ static struct hda_amp_list vt1716S_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ unsigned int mono_out, present;
+ /* SW0 (17h) = stereo mixer */
+ imux_is_smixer =
+ (snd_hda_codec_read(codec, 0x17, 0,
+ AC_VERB_GET_CONNECT_SEL, 0x00) == 5);
+ /* inputs */
+ /* PW 1/2/5 (1ah/1bh/1eh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1a, &parm);
+ set_pin_power_state(codec, 0x1b, &parm);
+ set_pin_power_state(codec, 0x1e, &parm);
+ if (imux_is_smixer)
+ parm = AC_PWRST_D0;
+ /* SW0 (17h), AIW0(13h) */
+ snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1e, &parm);
+ /* PW11 (22h) */
+ if (spec->dmic_enabled)
+ set_pin_power_state(codec, 0x22, &parm);
+ else
+ snd_hda_codec_write(codec, 0x22, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+
+ /* SW2(26h), AIW1(14h) */
+ snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* PW0 (19h), SW1 (18h), AOW1 (11h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x19, &parm);
+ /* Smart 5.1 PW2(1bh) */
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1b, &parm);
+ snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW7 (23h), SW3 (27h), AOW3 (25h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x23, &parm);
+ /* Smart 5.1 PW1(1ah) */
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1a, &parm);
+ snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* Smart 5.1 PW5(1eh) */
+ if (spec->smart51_enabled)
+ set_pin_power_state(codec, 0x1e, &parm);
+ snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* Mono out */
+ /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
+ present = snd_hda_jack_detect(codec, 0x1c);
+
+ if (present)
+ mono_out = 0;
+ else {
+ present = snd_hda_jack_detect(codec, 0x1d);
+ if (!spec->hp_independent_mode && present)
+ mono_out = 0;
+ else
+ mono_out = 1;
+ }
+ parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
+ snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW 3/4 (1ch/1dh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x1c, &parm);
+ set_pin_power_state(codec, 0x1d, &parm);
+ /* HP Independent Mode, power on AOW3 */
+ if (spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x25, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+
+ /* force to D0 for internal Speaker */
+ /* MW0 (16h), AOW0 (10h) */
+ snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
+ imux_is_smixer ? AC_PWRST_D0 : parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
+ mono_out ? AC_PWRST_D0 : parm);
+}
+
static int patch_vt1716S(struct hda_codec *codec)
{
struct via_spec *spec;
@@ -5343,6 +5249,7 @@ static int patch_vt1716S(struct hda_codec *codec)
spec->loopback.amplist = vt1716S_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
return 0;
}
@@ -5373,6 +5280,10 @@ static struct snd_kcontrol_new vt2002P_capture_mixer[] = {
};
static struct hda_verb vt2002P_volume_init_verbs[] = {
+ /* Class-D speaker related verbs */
+ {0x1, 0xfe0, 0x4},
+ {0x1, 0xfe9, 0x80},
+ {0x1, 0xfe2, 0x22},
/*
* Unmute ADC0-1 and set the default input to mic-in
*/
@@ -5423,6 +5334,57 @@ static struct hda_verb vt2002P_volume_init_verbs[] = {
{0x1, 0xfb8, 0x88},
{ }
};
+static struct hda_verb vt1802_volume_init_verbs[] = {
+ /*
+ * Unmute ADC0-1 and set the default input to mic-in
+ */
+ {0x8, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x9, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+
+ /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
+ */
+ /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+
+ /* MUX Indices: Mic = 0 */
+ {0x1e, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x1f, AC_VERB_SET_CONNECT_SEL, 0},
+
+ /* PW9 Output enable */
+ {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
+
+ /* Enable Boost Volume backdoor */
+ {0x1, 0xfb9, 0x24},
+
+ /* MW0/1/4/8: un-mute index 0 (MUXx), un-mute index 1 (MW9) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* set MUX0/1/4/8 = 0 (AOW0) */
+ {0x34, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x35, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x38, AC_VERB_SET_CONNECT_SEL, 0},
+ {0x3c, AC_VERB_SET_CONNECT_SEL, 0},
+
+ /* set PW0 index=0 (MW0) */
+ {0x24, AC_VERB_SET_CONNECT_SEL, 0},
+
+ /* Enable AOW0 to MW9 */
+ {0x1, 0xfb8, 0x88},
+ { }
+};
static struct hda_verb vt2002P_uniwill_init_verbs[] = {
@@ -5435,6 +5397,16 @@ static struct hda_verb vt2002P_uniwill_init_verbs[] = {
{0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
{ }
};
+static struct hda_verb vt1802_uniwill_init_verbs[] = {
+ {0x25, AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
+ {0x28, AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | VIA_JACK_EVENT | VIA_BIND_HP_EVENT},
+ {0x29, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x2a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ {0x2b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_JACK_EVENT},
+ { }
+};
static struct hda_pcm_stream vt2002P_pcm_analog_playback = {
.substreams = 2,
@@ -5491,10 +5463,15 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
const struct auto_pin_cfg *cfg)
{
int err;
+ hda_nid_t sw_nid;
if (!cfg->line_out_pins[0])
return -1;
+ if (spec->codec_type == VT1802)
+ sw_nid = 0x28;
+ else
+ sw_nid = 0x26;
/* Line-Out: PortE */
err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
@@ -5504,7 +5481,7 @@ static int vt2002P_auto_create_multi_out_ctls(struct via_spec *spec,
return err;
err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE,
"Master Front Playback Switch",
- HDA_COMPOSE_AMP_VAL(0x26, 3, 0, HDA_OUTPUT));
+ HDA_COMPOSE_AMP_VAL(sw_nid, 3, 0, HDA_OUTPUT));
if (err < 0)
return err;
@@ -5613,6 +5590,116 @@ static struct hda_amp_list vt2002P_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer;
+ unsigned int parm;
+ unsigned int present;
+ /* MUX9 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ parm = AC_PWRST_D0;
+ /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
+ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* AOW0 (8h)*/
+ snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ if (spec->codec_type == VT1802) {
+ /* PW4 (28h), MW4 (18h), MUX4(38h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x18, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x38, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else {
+ /* PW4 (26h), MW4 (1ch), MUX4(37h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x26, &parm);
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x37, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+
+ if (spec->codec_type == VT1802) {
+ /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ snd_hda_codec_write(codec, 0x15, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x35, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else {
+ /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ snd_hda_codec_write(codec, 0x19, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x35, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+
+ if (spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x9, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ /* Class-D */
+ /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
+ present = snd_hda_jack_detect(codec, 0x25);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
+ if (spec->codec_type == VT1802)
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ else
+ snd_hda_codec_write(codec, 0x18, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* Mono Out */
+ present = snd_hda_jack_detect(codec, 0x26);
+
+ parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
+ if (spec->codec_type == VT1802) {
+ /* PW15 (33h), MW8(1ch), MUX8(3ch) */
+ snd_hda_codec_write(codec, 0x33, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x3c, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ } else {
+ /* PW15 (31h), MW8(17h), MUX8(3bh) */
+ snd_hda_codec_write(codec, 0x31, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x17, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x3b, 0,
+ AC_VERB_SET_POWER_STATE, parm);
+ }
+ /* MW9 (21h) */
+ if (imux_is_smixer || !is_aa_path_mute(codec))
+ snd_hda_codec_write(codec, 0x21, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ else
+ snd_hda_codec_write(codec, 0x21, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
/* patch for vt2002P */
static int patch_vt2002P(struct hda_codec *codec)
@@ -5635,14 +5722,31 @@ static int patch_vt2002P(struct hda_codec *codec)
"from BIOS. Using genenic mode...\n");
}
- spec->init_verbs[spec->num_iverbs++] = vt2002P_volume_init_verbs;
- spec->init_verbs[spec->num_iverbs++] = vt2002P_uniwill_init_verbs;
+ if (spec->codec_type == VT1802)
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1802_volume_init_verbs;
+ else
+ spec->init_verbs[spec->num_iverbs++] =
+ vt2002P_volume_init_verbs;
+
+ if (spec->codec_type == VT1802)
+ spec->init_verbs[spec->num_iverbs++] =
+ vt1802_uniwill_init_verbs;
+ else
+ spec->init_verbs[spec->num_iverbs++] =
+ vt2002P_uniwill_init_verbs;
- spec->stream_name_analog = "VT2002P Analog";
+ if (spec->codec_type == VT1802)
+ spec->stream_name_analog = "VT1802 Analog";
+ else
+ spec->stream_name_analog = "VT2002P Analog";
spec->stream_analog_playback = &vt2002P_pcm_analog_playback;
spec->stream_analog_capture = &vt2002P_pcm_analog_capture;
- spec->stream_name_digital = "VT2002P Digital";
+ if (spec->codec_type == VT1802)
+ spec->stream_name_digital = "VT1802 Digital";
+ else
+ spec->stream_name_digital = "VT2002P Digital";
spec->stream_digital_playback = &vt2002P_pcm_digital_playback;
if (!spec->adc_nids && spec->input_mux) {
@@ -5664,6 +5768,7 @@ static int patch_vt2002P(struct hda_codec *codec)
spec->loopback.amplist = vt2002P_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt2002P;
return 0;
}
@@ -5935,6 +6040,97 @@ static struct hda_amp_list vt1812_loopbacks[] = {
};
#endif
+static void set_widgets_power_state_vt1812(struct hda_codec *codec)
+{
+ struct via_spec *spec = codec->spec;
+ int imux_is_smixer =
+ snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
+ unsigned int parm;
+ unsigned int present;
+ /* MUX10 (1eh) = stereo mixer */
+ imux_is_smixer =
+ snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
+ /* inputs */
+ /* PW 5/6/7 (29h/2ah/2bh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x29, &parm);
+ set_pin_power_state(codec, 0x2a, &parm);
+ set_pin_power_state(codec, 0x2b, &parm);
+ parm = AC_PWRST_D0;
+ /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
+ snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* outputs */
+ /* AOW0 (8h)*/
+ snd_hda_codec_write(codec, 0x8, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ /* PW4 (28h), MW4 (18h), MUX4(38h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x28, &parm);
+ snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+
+ /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x25, &parm);
+ snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+ if (spec->hp_independent_mode)
+ snd_hda_codec_write(codec, 0x9, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+
+ /* Internal Speaker */
+ /* PW0 (24h), MW0(14h), MUX0(34h) */
+ present = snd_hda_jack_detect(codec, 0x25);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x24, &parm);
+ if (present) {
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ snd_hda_codec_write(codec, 0x34, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ } else {
+ snd_hda_codec_write(codec, 0x14, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ snd_hda_codec_write(codec, 0x34, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ }
+
+
+ /* Mono Out */
+ /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
+ present = snd_hda_jack_detect(codec, 0x28);
+
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x31, &parm);
+ if (present) {
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ snd_hda_codec_write(codec, 0x3c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ snd_hda_codec_write(codec, 0x3e, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ } else {
+ snd_hda_codec_write(codec, 0x1c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ snd_hda_codec_write(codec, 0x3c, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ snd_hda_codec_write(codec, 0x3e, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ }
+
+ /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
+ parm = AC_PWRST_D3;
+ set_pin_power_state(codec, 0x33, &parm);
+ snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+ snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+
+}
/* patch for vt1812 */
static int patch_vt1812(struct hda_codec *codec)
@@ -5988,6 +6184,7 @@ static int patch_vt1812(struct hda_codec *codec)
spec->loopback.amplist = vt1812_loopbacks;
#endif
+ spec->set_widgets_power_state = set_widgets_power_state_vt1812;
return 0;
}
@@ -6039,7 +6236,7 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
.patch = patch_vt1708S},
{ .id = 0x11063397, .name = "VT1708S",
.patch = patch_vt1708S},
- { .id = 0x11064397, .name = "VT1708S",
+ { .id = 0x11064397, .name = "VT1705",
.patch = patch_vt1708S},
{ .id = 0x11065397, .name = "VT1708S",
.patch = patch_vt1708S},
@@ -6080,6 +6277,10 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
{ .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
{ .id = 0x11060440, .name = "VT1818S",
.patch = patch_vt1708S},
+ { .id = 0x11060446, .name = "VT1802",
+ .patch = patch_vt2002P},
+ { .id = 0x11068446, .name = "VT1802",
+ .patch = patch_vt2002P},
{} /* terminator */
};