#include "hda_codec.h"
#include "hda_local.h"
+#define ALC880_FRONT_EVENT 0x01
+#define ALC880_DCVOL_EVENT 0x02
+#define ALC880_HP_EVENT 0x04
+#define ALC880_MIC_EVENT 0x08
/* ALC880 board config type */
enum {
ALC880_ASUS_W1V,
ALC880_ASUS_DIG2,
ALC880_UNIWILL_DIG,
+ ALC880_UNIWILL,
+ ALC880_UNIWILL_P53,
ALC880_CLEVO,
ALC880_TCL_S700,
ALC880_LG,
/* ALC262 models */
enum {
ALC262_BASIC,
+ ALC262_HIPPO,
+ ALC262_HIPPO_1,
ALC262_FUJITSU,
ALC262_HP_BPC,
ALC262_BENQ_ED8,
ALC861_3ST_DIG,
ALC861_6ST_DIG,
ALC861_UNIWILL_M31,
+ ALC861_TOSHIBA,
ALC861_AUTO,
ALC861_MODEL_LAST,
};
ALC883_3ST_6ch_DIG,
ALC883_3ST_6ch,
ALC883_6ST_DIG,
+ ALC883_TARGA_DIG,
+ ALC883_TARGA_2ch_DIG,
ALC888_DEMO_BOARD,
+ ALC883_ACER,
+ ALC883_MEDION,
ALC883_AUTO,
ALC883_MODEL_LAST,
};
int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
spec->num_channel_mode,
&spec->multiout.max_channels);
- if (! err && spec->need_dac_fix)
+ if (err >= 0 && spec->need_dac_fix)
spec->multiout.num_dacs = spec->multiout.max_channels / 2;
return err;
}
{ } /* end */
};
+/* Uniwill */
+static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
+ HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
+ HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
/*
* build control elements
*/
{ }
};
+/*
+ * Uniwill pin configuration:
+ * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
+ * line = 0x1a
+ */
+static struct hda_verb alc880_uniwill_init_verbs[] = {
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
+ /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+
+ { }
+};
+
+/*
+* Uniwill P53
+* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
+ */
+static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
+
+ { }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_uniwill_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+
+ present = snd_hda_codec_read(codec, 0x18, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
+}
+
+static void alc880_uniwill_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ /* Looks like the unsol event is incompatible with the standard
+ * definition. 4bit tag is placed at 28 bit!
+ */
+ if ((res >> 28) == ALC880_HP_EVENT ||
+ (res >> 28) == ALC880_MIC_EVENT)
+ alc880_uniwill_automute(codec);
+}
+
+static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+ snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
+ 0x80, present ? 0x80 : 0);
+}
+
+static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x21, 0,
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
+
+ snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
+ 0x7f, present);
+ snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
+ 0x7f, present);
+
+ snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
+ 0x7f, present);
+ snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
+ 0x7f, present);
+
+}
+static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ /* Looks like the unsol event is incompatible with the standard
+ * definition. 4bit tag is placed at 28 bit!
+ */
+ if ((res >> 28) == ALC880_HP_EVENT)
+ alc880_uniwill_p53_hp_automute(codec);
+ if ((res >> 28) == ALC880_DCVOL_EVENT)
+ alc880_uniwill_p53_dcvol_automute(codec);
+}
+
/* FIXME! */
/*
* F1734 pin configuration:
}
}
- /* If the use of more than one ADC is requested for the current
- * model, configure a second analog capture-only PCM.
- */
- if (spec->num_adc_nids > 1) {
- codec->num_pcms++;
- info++;
- info->name = spec->stream_name_analog;
- /* No playback stream for second PCM */
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
- if (spec->stream_analog_capture) {
- snd_assert(spec->adc_nids, return -EINVAL);
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
- }
- }
-
+ /* SPDIF for stream index #1 */
if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
- codec->num_pcms++;
- info++;
+ codec->num_pcms = 2;
+ info = spec->pcm_rec + 1;
info->name = spec->stream_name_digital;
if (spec->multiout.dig_out_nid &&
spec->stream_digital_playback) {
}
}
+ /* If the use of more than one ADC is requested for the current
+ * model, configure a second analog capture-only PCM.
+ */
+ /* Additional Analaog capture for index #2 */
+ if (spec->num_adc_nids > 1 && spec->stream_analog_capture &&
+ spec->adc_nids) {
+ codec->num_pcms = 3;
+ info = spec->pcm_rec + 2;
+ info->name = spec->stream_name_analog;
+ /* No playback stream for second PCM */
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
+ if (spec->stream_analog_capture) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1];
+ }
+ }
+
return 0;
}
{ .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
{ .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
- { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
+ { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
+ { .pci_subvendor = 0x1584, .pci_subdevice = 0x9070, .config = ALC880_UNIWILL },
+ { .pci_subvendor = 0x1734, .pci_subdevice = 0x10ac, .config = ALC880_UNIWILL },
+ { .pci_subvendor = 0x1584, .pci_subdevice = 0x9077, .config = ALC880_UNIWILL_P53 },
{ .modelname = "F1734", .config = ALC880_F1734 },
{ .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
{ .modelname = "lg-lw", .config = ALC880_LG_LW },
{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
+ { .pci_subvendor = 0x1854, .pci_subdevice = 0x0077, .config = ALC880_LG_LW },
#ifdef CONFIG_SND_DEBUG
{ .modelname = "test", .config = ALC880_TEST },
},
[ALC880_UNIWILL_DIG] = {
.mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
- .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_pin_asus_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
.dac_nids = alc880_asus_dac_nids,
.dig_out_nid = ALC880_DIGOUT_NID,
.need_dac_fix = 1,
.input_mux = &alc880_capture_source,
},
+ [ALC880_UNIWILL] = {
+ .mixers = { alc880_uniwill_mixer },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_uniwill_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+ .channel_mode = alc880_threestack_modes,
+ .need_dac_fix = 1,
+ .input_mux = &alc880_capture_source,
+ .unsol_event = alc880_uniwill_unsol_event,
+ .init_hook = alc880_uniwill_automute,
+ },
+ [ALC880_UNIWILL_P53] = {
+ .mixers = { alc880_uniwill_p53_mixer },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_uniwill_p53_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+ .channel_mode = alc880_w810_modes,
+ .input_mux = &alc880_capture_source,
+ .unsol_event = alc880_uniwill_p53_unsol_event,
+ .init_hook = alc880_uniwill_p53_hp_automute,
+ },
[ALC880_CLEVO] = {
.mixers = { alc880_three_stack_mixer },
.init_verbs = { alc880_volume_init_verbs,
pin = spec->autocfg.speaker_pins[0];
if (pin) /* connect to front */
alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
- pin = spec->autocfg.hp_pin;
+ pin = spec->autocfg.hp_pins[0];
if (pin) /* connect to front */
alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
}
(err = alc880_auto_create_extra_out(spec,
spec->autocfg.speaker_pins[0],
"Speaker")) < 0 ||
- (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin,
+ (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
"Headphone")) < 0 ||
(err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
return err;
return err;
}
- nid = cfg->hp_pin;
+ nid = cfg->hp_pins[0];
if (nid) {
err = alc260_add_playback_controls(spec, nid, "Headphone");
if (err < 0)
if (nid)
alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
- nid = spec->autocfg.hp_pin;
+ nid = spec->autocfg.hp_pins[0];
if (nid)
alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
}
static struct hda_verb alc882_eapd_verbs[] = {
/* change to EAPD mode */
{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
+ {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
{ }
};
struct alc_spec *spec = codec->spec;
hda_nid_t pin;
- pin = spec->autocfg.hp_pin;
+ pin = spec->autocfg.hp_pins[0];
if (pin) /* connect to front */
alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
}
{ } /* end */
};
+static snd_kcontrol_new_t alc883_fivestack_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc883_tagra_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc883_chmode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
{ }
};
+static struct hda_verb alc883_tagra_verbs[] = {
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+
+ {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+ {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+ {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
+ {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
+ {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
+ {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
+
+ { } /* end */
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc883_tagra_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x14, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
+}
+
+static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc883_tagra_automute(codec);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
.config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/
{ .modelname = "3stack-6ch", .config = ALC883_3ST_6ch },
{ .pci_subvendor = 0x108e, .pci_subdevice = 0x534d,
- .config = ALC883_3ST_6ch },
- { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601,
- .config = ALC883_3ST_6ch }, /* D102GGC */
+ .config = ALC883_3ST_6ch },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601,
+ .config = ALC883_3ST_6ch }, /* D102GGC */
{ .modelname = "6stack-dig", .config = ALC883_6ST_DIG },
{ .pci_subvendor = 0x1462, .pci_subdevice = 0x6668,
.config = ALC883_6ST_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x7280,
+ .config = ALC883_6ST_DIG }, /* MSI K9A Platinum (MS-7280) */
{ .pci_subvendor = 0x105b, .pci_subdevice = 0x6668,
.config = ALC883_6ST_DIG }, /* Foxconn */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x7187,
+ .config = ALC883_6ST_DIG }, /* MSI */
+ { .modelname = "targa-dig", .config = ALC883_TARGA_DIG },
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x4314,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x3fcc,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x3fc1,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x3fc3,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x4314,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x4319,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x3ef9,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x4324,
+ .config = ALC883_TARGA_DIG }, /* MSI */
+ { .modelname = "targa-2ch-dig", .config = ALC883_TARGA_2ch_DIG },
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x0579,
+ .config = ALC883_TARGA_2ch_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0xa422,
+ .config = ALC883_TARGA_2ch_DIG }, /* MSI */
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x3b7f,
+ .config = ALC883_TARGA_2ch_DIG }, /* MSI */
{ .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD },
+ { .modelname = "acer", .config = ALC883_ACER },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/,
+ .config = ALC883_ACER },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0x0102,
+ .config = ALC883_ACER },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0x009f,
+ .config = ALC883_ACER },
+ { .pci_subvendor = 0x161f, .pci_subdevice = 0x2054,
+ .modelname = "medion", .config = ALC883_MEDION },
{ .modelname = "auto", .config = ALC883_AUTO },
{}
};
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
},
+ [ALC883_TARGA_DIG] = {
+ .mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
+ .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
+ .channel_mode = alc883_3ST_6ch_modes,
+ .need_dac_fix = 1,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_tagra_unsol_event,
+ .init_hook = alc883_tagra_automute,
+ },
+ [ALC883_TARGA_2ch_DIG] = {
+ .mixers = { alc883_tagra_2ch_mixer},
+ .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .dig_out_nid = ALC883_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ .unsol_event = alc883_tagra_unsol_event,
+ .init_hook = alc883_tagra_automute,
+ },
[ALC888_DEMO_BOARD] = {
.mixers = { alc883_base_mixer, alc883_chmode_mixer },
.init_verbs = { alc883_init_verbs },
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
},
+ [ALC883_ACER] = {
+ .mixers = { alc883_base_mixer,
+ alc883_chmode_mixer },
+ /* On TravelMate laptops, GPIO 0 enables the internal speaker
+ * and the headphone jack. Turn this on and rely on the
+ * standard mute methods whenever the user wants to turn
+ * these outputs off.
+ */
+ .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .input_mux = &alc883_capture_source,
+ },
+ [ALC883_MEDION] = {
+ .mixers = { alc883_fivestack_mixer,
+ alc883_chmode_mixer },
+ .init_verbs = { alc883_init_verbs,
+ alc882_eapd_verbs },
+ .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+ .dac_nids = alc883_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
+ .channel_mode = alc883_sixstack_modes,
+ .input_mux = &alc883_capture_source,
+ }
+
};
struct alc_spec *spec = codec->spec;
hda_nid_t pin;
- pin = spec->autocfg.hp_pin;
+ pin = spec->autocfg.hp_pins[0];
if (pin) /* connect to front */
/* use dac 0 */
alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
{ } /* end */
};
+static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
+ /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
{ }
};
+static struct hda_verb alc262_hippo_unsol_verbs[] = {
+ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {}
+};
+
+static struct hda_verb alc262_hippo1_unsol_verbs[] = {
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+ {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {}
+};
+
+/* mute/unmute internal speaker according to the hp jack and mute state */
+static void alc262_hippo_automute(struct hda_codec *codec, int force)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute;
+
+ if (force || ! spec->sense_updated) {
+ unsigned int present;
+ /* need to execute and sync at first */
+ snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, 0x15, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
+ spec->sense_updated = 1;
+ }
+ if (spec->jack_present) {
+ /* mute internal speaker */
+ snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ 0x80, 0x80);
+ snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ 0x80, 0x80);
+ } else {
+ /* unmute internal speaker if necessary */
+ mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ 0x80, mute & 0x80);
+ mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ 0x80, mute & 0x80);
+ }
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_hippo_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) != ALC880_HP_EVENT)
+ return;
+ alc262_hippo_automute(codec, 1);
+}
+
+static void alc262_hippo1_automute(struct hda_codec *codec, int force)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int mute;
+
+ if (force || ! spec->sense_updated) {
+ unsigned int present;
+ /* need to execute and sync at first */
+ snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
+ present = snd_hda_codec_read(codec, 0x1b, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+ spec->jack_present = (present & 0x80000000) != 0;
+ spec->sense_updated = 1;
+ }
+ if (spec->jack_present) {
+ /* mute internal speaker */
+ snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ 0x80, 0x80);
+ snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ 0x80, 0x80);
+ } else {
+ /* unmute internal speaker if necessary */
+ mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+ 0x80, mute & 0x80);
+ mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
+ snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+ 0x80, mute & 0x80);
+ }
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc262_hippo1_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ if ((res >> 26) != ALC880_HP_EVENT)
+ return;
+ alc262_hippo1_automute(codec, 1);
+}
+
/*
* fujitsu model
* 0x14 = headphone/spdif-out, 0x15 = internal speaker
return err;
}
}
- nid = cfg->hp_pin;
+ nid = cfg->hp_pins[0];
if (nid) {
/* spec->multiout.hp_nid = 2; */
if (nid == 0x16) {
*/
static struct hda_board_config alc262_cfg_tbl[] = {
{ .modelname = "basic", .config = ALC262_BASIC },
+ { .modelname = "hippo",
+ .pci_subvendor =0x1002, .pci_subdevice = 0x437b,
+ .config = ALC262_HIPPO},
+ { .modelname = "hippo_1",
+ .pci_subvendor =0x17ff, .pci_subdevice = 0x058f,
+ .config = ALC262_HIPPO_1},
{ .modelname = "fujitsu", .config = ALC262_FUJITSU },
{ .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397,
.config = ALC262_FUJITSU },
{ .modelname = "hp-bpc", .config = ALC262_HP_BPC },
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c,
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x280c,
.config = ALC262_HP_BPC }, /* xw4400 */
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x2801,
+ .config = ALC262_HP_BPC }, /* q965 */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014,
.config = ALC262_HP_BPC }, /* xw6400 */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3015,
.channel_mode = alc262_modes,
.input_mux = &alc262_capture_source,
},
+ [ALC262_HIPPO] = {
+ .mixers = { alc262_base_mixer },
+ .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
+ .num_dacs = ARRAY_SIZE(alc262_dac_nids),
+ .dac_nids = alc262_dac_nids,
+ .hp_nid = 0x03,
+ .dig_out_nid = ALC262_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc262_modes),
+ .channel_mode = alc262_modes,
+ .input_mux = &alc262_capture_source,
+ .unsol_event = alc262_hippo_unsol_event,
+ },
+ [ALC262_HIPPO_1] = {
+ .mixers = { alc262_hippo1_mixer },
+ .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
+ .num_dacs = ARRAY_SIZE(alc262_dac_nids),
+ .dac_nids = alc262_dac_nids,
+ .hp_nid = 0x02,
+ .dig_out_nid = ALC262_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc262_modes),
+ .channel_mode = alc262_modes,
+ .input_mux = &alc262_capture_source,
+ .unsol_event = alc262_hippo1_unsol_event,
+ },
[ALC262_FUJITSU] = {
.mixers = { alc262_fujitsu_mixer },
.init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
.private_value = ARRAY_SIZE(alc861_threestack_modes),
},
{ } /* end */
-};
+};
+
+static snd_kcontrol_new_t alc861_toshiba_mixer[] = {
+ /* output mixer control */
+ HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+
+ /*Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
/* output mixer control */
HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
{ }
};
+static struct hda_verb alc861_toshiba_init_verbs[] = {
+ {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+
+ { }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc861_toshiba_automute(struct hda_codec *codec)
+{
+ unsigned int present;
+
+ present = snd_hda_codec_read(codec, 0x0f, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+ snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
+ 0x80, present ? 0x80 : 0);
+ snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
+ 0x80, present ? 0 : 0x80);
+ snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
+ 0x80, present ? 0 : 0x80);
+}
+
+static void alc861_toshiba_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ /* Looks like the unsol event is incompatible with the standard
+ * definition. 6bit tag is placed at 26 bit!
+ */
+ if ((res >> 26) == ALC880_HP_EVENT)
+ alc861_toshiba_automute(codec);
+}
+
/* pcm configuration: identiacal with ALC880 */
#define alc861_pcm_analog_playback alc880_pcm_analog_playback
#define alc861_pcm_analog_capture alc880_pcm_analog_capture
struct alc_spec *spec = codec->spec;
hda_nid_t pin;
- pin = spec->autocfg.hp_pin;
+ pin = spec->autocfg.hp_pins[0];
if (pin) /* connect to front */
alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
}
if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
(err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
- (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
+ (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 ||
(err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
return err;
{ .modelname = "uniwill-m31", .config = ALC861_UNIWILL_M31},
{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9072,
.config = ALC861_UNIWILL_M31 },
+ { .modelname = "toshiba", .config = ALC861_TOSHIBA },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1338,
+ .config = ALC861_TOSHIBA },
+ { .pci_subvendor = 0x1179, .pci_subdevice = 0xff10,
+ .config = ALC861_TOSHIBA },
{ .modelname = "auto", .config = ALC861_AUTO },
{}
};
.adc_nids = alc861_adc_nids,
.input_mux = &alc861_capture_source,
},
-
+ [ALC861_TOSHIBA] = {
+ .mixers = { alc861_toshiba_mixer },
+ .init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc861_dac_nids),
+ .dac_nids = alc861_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+ .channel_mode = alc883_3ST_2ch_modes,
+ .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+ .adc_nids = alc861_adc_nids,
+ .input_mux = &alc861_capture_source,
+ .unsol_event = alc861_toshiba_unsol_event,
+ .init_hook = alc861_toshiba_automute,
+ },
};
{ .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
{ .id = 0x10ec0861, .rev = 0x100300, .name = "ALC861",
.patch = patch_alc861 },
- { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
+ { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
.patch = patch_alc861 },
+ { .id = 0x10ec0660, .name = "ALC660", .patch = patch_alc861 },
{} /* terminator */
};