X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=sound%2Fpci%2Fhda%2Fpatch_sigmatel.c;h=86de305fc9f225ef382f6a7bdfbd438a2f97840f;hp=2760730605762320dc11f4e21500d73dbebed6e8;hb=8ef5837a47f73faee18fa7ce2f9a9eb7675be8de;hpb=d5c9c8912a25550f2b6a0974667eb968fe6a316e diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 276073060576..86de305fc9f2 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -78,10 +79,12 @@ enum { STAC_92HD73XX_AUTO, STAC_92HD73XX_NO_JD, /* no jack-detection */ STAC_92HD73XX_REF, + STAC_92HD73XX_INTEL, STAC_DELL_M6_AMIC, STAC_DELL_M6_DMIC, STAC_DELL_M6_BOTH, STAC_DELL_EQ, + STAC_ALIENWARE_M17X, STAC_92HD73XX_MODELS }; @@ -156,6 +159,7 @@ enum { STAC_D965_5ST_NO_FP, STAC_DELL_3ST, STAC_DELL_BIOS, + STAC_927X_VOLKNOB, STAC_927X_MODELS }; @@ -180,8 +184,8 @@ struct sigmatel_jack { struct sigmatel_mic_route { hda_nid_t pin; - unsigned char mux_idx; - unsigned char dmux_idx; + signed char mux_idx; + signed char dmux_idx; }; struct sigmatel_spec { @@ -227,7 +231,6 @@ struct sigmatel_spec { /* playback */ struct hda_input_mux *mono_mux; - struct hda_input_mux *amp_mux; unsigned int cur_mmux; struct hda_multi_out multiout; hda_nid_t dac_nids[5]; @@ -247,6 +250,7 @@ struct sigmatel_spec { unsigned int num_dmuxes; hda_nid_t *smux_nids; unsigned int num_smuxes; + unsigned int num_analog_muxes; unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */ unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */ @@ -279,7 +283,6 @@ struct sigmatel_spec { unsigned int cur_smux[2]; unsigned int cur_amux; hda_nid_t *amp_nids; - unsigned int num_amps; unsigned int powerdown_adcs; /* i/o switches */ @@ -298,7 +301,6 @@ struct sigmatel_spec { struct hda_input_mux private_dimux; struct hda_input_mux private_imux; struct hda_input_mux private_smux; - struct hda_input_mux private_amp_mux; struct hda_input_mux private_mono_mux; }; @@ -327,11 +329,6 @@ static hda_nid_t stac92hd73xx_adc_nids[2] = { 0x1a, 0x1b }; -#define DELL_M6_AMP 2 -static hda_nid_t stac92hd73xx_amp_nids[3] = { - 0x0b, 0x0c, 0x0e -}; - #define STAC92HD73XX_NUM_DMICS 2 static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { 0x13, 0x14, 0 @@ -339,8 +336,8 @@ static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { #define STAC92HD73_DAC_COUNT 5 -static hda_nid_t stac92hd73xx_mux_nids[4] = { - 0x28, 0x29, 0x2a, 0x2b, +static hda_nid_t stac92hd73xx_mux_nids[2] = { + 0x20, 0x21, }; static hda_nid_t stac92hd73xx_dmux_nids[2] = { @@ -358,14 +355,9 @@ static unsigned long stac92hd73xx_capvols[] = { }; #define stac92hd73xx_capsws stac92hd73xx_capvols -#define STAC92HD83XXX_NUM_DMICS 2 -static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { - 0x11, 0x12, 0 -}; - #define STAC92HD83_DAC_COUNT 3 -static hda_nid_t stac92hd83xxx_dmux_nids[2] = { +static hda_nid_t stac92hd83xxx_mux_nids[2] = { 0x17, 0x18, }; @@ -385,10 +377,6 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = { 0x03, 0x0c, 0x20, 0x40, }; -static hda_nid_t stac92hd83xxx_amp_nids[1] = { - 0xc, -}; - #define STAC92HD83XXX_NUM_CAPS 2 static unsigned long stac92hd83xxx_capvols[] = { HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), @@ -602,34 +590,6 @@ static hda_nid_t stac9205_pin_nids[12] = { 0x21, 0x22, }; -#define stac92xx_amp_volume_info snd_hda_mixer_amp_volume_info - -static int stac92xx_amp_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = spec->amp_nids[spec->cur_amux]; - - kcontrol->private_value ^= get_amp_nid(kcontrol); - kcontrol->private_value |= nid; - - return snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); -} - -static int stac92xx_amp_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid = spec->amp_nids[spec->cur_amux]; - - kcontrol->private_value ^= get_amp_nid(kcontrol); - kcontrol->private_value |= nid; - - return snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); -} - static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -766,9 +726,35 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct sigmatel_spec *spec = codec->spec; unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - - return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, - spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); + const struct hda_input_mux *imux = spec->input_mux; + unsigned int idx, prev_idx; + + idx = ucontrol->value.enumerated.item[0]; + if (idx >= imux->num_items) + idx = imux->num_items - 1; + prev_idx = spec->cur_mux[adc_idx]; + if (prev_idx == idx) + return 0; + if (idx < spec->num_analog_muxes) { + snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[idx].index); + if (prev_idx >= spec->num_analog_muxes) { + imux = spec->dinput_mux; + /* 0 = analog */ + snd_hda_codec_write_cache(codec, + spec->dmux_nids[adc_idx], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[0].index); + } + } else { + imux = spec->dinput_mux; + snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[idx - 1].index); + } + spec->cur_mux[adc_idx] = idx; + return 1; } static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol, @@ -799,41 +785,6 @@ static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol, spec->mono_nid, &spec->cur_mmux); } -static int stac92xx_amp_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - return snd_hda_input_mux_info(spec->amp_mux, uinfo); -} - -static int stac92xx_amp_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - - ucontrol->value.enumerated.item[0] = spec->cur_amux; - return 0; -} - -static int stac92xx_amp_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct sigmatel_spec *spec = codec->spec; - struct snd_kcontrol *ctl = - snd_hda_find_mixer_ctl(codec, "Amp Capture Volume"); - if (!ctl) - return -EINVAL; - - snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - - return snd_hda_input_mux_put(codec, spec->amp_mux, ucontrol, - 0, &spec->cur_amux); -} - #define stac92xx_aloopback_info snd_ctl_boolean_mono_info static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, @@ -901,92 +852,20 @@ static struct hda_verb stac9200_eapd_init[] = { {} }; -static struct hda_verb stac92hd73xx_6ch_core_init[] = { - /* set master volume and direct control */ - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* setup adcs to point to mixer */ - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* setup import muxs */ - { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, - {} -}; - static struct hda_verb dell_eq_core_init[] = { /* set master volume to max value without distortion * and direct control */ { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, - /* setup adcs to point to mixer */ - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, - /* setup import muxs */ - { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, - {} -}; - -static struct hda_verb dell_m6_core_init[] = { - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* setup adcs to point to mixer */ - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, - /* setup import muxs */ - { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x00}, - {} -}; - -static struct hda_verb stac92hd73xx_8ch_core_init[] = { - /* set master volume and direct control */ - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* setup adcs to point to mixer */ - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* setup import muxs */ - { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x03}, {} }; -static struct hda_verb stac92hd73xx_10ch_core_init[] = { +static struct hda_verb stac92hd73xx_core_init[] = { /* set master volume and direct control */ { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* dac3 is connected to import3 mux */ - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f}, - /* setup adcs to point to mixer */ - { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - /* setup import muxs */ - { 0x28, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x29, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2a, AC_VERB_SET_CONNECT_SEL, 0x01}, - { 0x2b, AC_VERB_SET_CONNECT_SEL, 0x03}, {} }; static struct hda_verb stac92hd83xxx_core_init[] = { - { 0xa, AC_VERB_SET_CONNECT_SEL, 0x1}, - { 0xb, AC_VERB_SET_CONNECT_SEL, 0x1}, - { 0xd, AC_VERB_SET_CONNECT_SEL, 0x0}, - /* power state controls amps */ { 0x01, AC_VERB_SET_EAPD, 1 << 2}, {} @@ -1030,6 +909,16 @@ static struct hda_verb d965_core_init[] = { {} }; +static struct hda_verb dell_3st_core_init[] = { + /* don't set delta bit */ + {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, + /* unmute node 0x1b */ + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* select node 0x03 as DAC */ + {0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, + {} +}; + static struct hda_verb stac927x_core_init[] = { /* set master volume and direct control */ { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, @@ -1038,6 +927,14 @@ static struct hda_verb stac927x_core_init[] = { {} }; +static struct hda_verb stac927x_volknob_core_init[] = { + /* don't set delta bit */ + {0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0x7f}, + /* enable analog pc beep path */ + {0x01, AC_VERB_SET_DIGI_CONVERT_2, 1 << 5}, + {} +}; + static struct hda_verb stac9205_core_init[] = { /* set master volume and direct control */ { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, @@ -1056,31 +953,6 @@ static struct hda_verb stac9205_core_init[] = { .put = stac92xx_mono_mux_enum_put, \ } -#define STAC_AMP_MUX \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = "Amp Selector Capture Switch", \ - .count = 1, \ - .info = stac92xx_amp_mux_enum_info, \ - .get = stac92xx_amp_mux_enum_get, \ - .put = stac92xx_amp_mux_enum_put, \ - } - -#define STAC_AMP_VOL(xname, nid, chs, idx, dir) \ - { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = 0, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ - .info = stac92xx_amp_volume_info, \ - .get = stac92xx_amp_volume_get, \ - .put = stac92xx_amp_volume_put, \ - .tlv = { .c = snd_hda_mixer_amp_tlv }, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, chs, idx, dir) \ - } - #define STAC_ANALOG_LOOPBACK(verb_read, verb_write, cnt) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ @@ -1111,28 +983,6 @@ static struct snd_kcontrol_new stac9200_mixer[] = { { } /* end */ }; -#define DELL_M6_MIXER 6 -static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { - /* start of config #1 */ - HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), - - HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), - - HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), - - /* start of config #2 */ - HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), - - HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), - - { } /* end */ -}; - static struct snd_kcontrol_new stac92hd73xx_6ch_loopback[] = { STAC_ANALOG_LOOPBACK(0xFA0, 0x7A1, 3), {} @@ -1148,77 +998,6 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = { {} }; -static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { - HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), - - HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), - - HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), - - HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), - - HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), - { } /* end */ -}; - -static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { - HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), - - HDA_CODEC_VOLUME("Mic Mixer Capture Volume", 0x1d, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Mixer Capture Switch", 0x1d, 0x1, HDA_INPUT), - - HDA_CODEC_VOLUME("Line In Mixer Capture Volume", 0x1d, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Line In Mixer Capture Switch", 0x1d, 0x2, HDA_INPUT), - - HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), - - HDA_CODEC_VOLUME("CD Mixer Capture Volume", 0x1d, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("CD Mixer Capture Switch", 0x1d, 0x4, HDA_INPUT), - { } /* end */ -}; - - -static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { - HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT), - HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT), - - HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x4, HDA_INPUT), - HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x4, HDA_INPUT), - - HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x0, HDA_INPUT), - - HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x2, HDA_INPUT), - - /* - HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x1, HDA_INPUT), - */ - { } /* end */ -}; - -static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { - HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT), - - HDA_CODEC_MUTE("Import1 Mux Capture Switch", 0x17, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Import1 Mux Capture Volume", 0x17, 0x1, HDA_INPUT), - - HDA_CODEC_MUTE("DAC0 Capture Switch", 0x17, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x17, 0x3, HDA_INPUT), - - HDA_CODEC_MUTE("DAC1 Capture Switch", 0x17, 0x4, HDA_INPUT), - HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x17, 0x4, HDA_INPUT), - { } /* end */ -}; static struct snd_kcontrol_new stac92hd71bxx_loopback[] = { STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2) @@ -1303,7 +1082,8 @@ static int stac92xx_build_controls(struct hda_codec *codec) if (err < 0) return err; } - if (!spec->auto_mic && spec->num_dmuxes > 0) { + if (!spec->auto_mic && spec->num_dmuxes > 0 && + snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { stac_dmux_mixer.count = spec->num_dmuxes; err = snd_hda_ctl_add(codec, snd_ctl_new1(&stac_dmux_mixer, codec)); @@ -1750,22 +1530,32 @@ static unsigned int dell_m6_pin_configs[13] = { 0x4f0000f0, }; +static unsigned int alienware_m17x_pin_configs[13] = { + 0x0321101f, 0x0321101f, 0x03a11020, 0x03014020, + 0x90170110, 0x4f0000f0, 0x4f0000f0, 0x4f0000f0, + 0x4f0000f0, 0x90a60160, 0x4f0000f0, 0x4f0000f0, + 0x904601b0, +}; + static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, [STAC_DELL_M6_AMIC] = dell_m6_pin_configs, [STAC_DELL_M6_DMIC] = dell_m6_pin_configs, [STAC_DELL_M6_BOTH] = dell_m6_pin_configs, [STAC_DELL_EQ] = dell_m6_pin_configs, + [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, }; static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_AUTO] = "auto", [STAC_92HD73XX_NO_JD] = "no-jd", [STAC_92HD73XX_REF] = "ref", + [STAC_92HD73XX_INTEL] = "intel", [STAC_DELL_M6_AMIC] = "dell-m6-amic", [STAC_DELL_M6_DMIC] = "dell-m6-dmic", [STAC_DELL_M6_BOTH] = "dell-m6", [STAC_DELL_EQ] = "dell-eq", + [STAC_ALIENWARE_M17X] = "alienware", }; static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { @@ -1774,6 +1564,10 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { "DFI LanParty", STAC_92HD73XX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101, "DFI LanParty", STAC_92HD73XX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002, + "Intel DG45ID", STAC_92HD73XX_INTEL), + SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003, + "Intel DG45FC", STAC_92HD73XX_INTEL), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0254, "Dell Studio 1535", STAC_DELL_M6_DMIC), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0255, @@ -1796,6 +1590,14 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { "Dell Studio 17", STAC_DELL_M6_DMIC), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02be, "Dell Studio 1555", STAC_DELL_M6_DMIC), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, + "Dell Studio 1557", STAC_DELL_M6_DMIC), + {} /* terminator */ +}; + +static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1, + "Alienware M17x", STAC_ALIENWARE_M17X), {} /* terminator */ }; @@ -1806,8 +1608,8 @@ static unsigned int ref92hd83xxx_pin_configs[10] = { }; static unsigned int dell_s14_pin_configs[10] = { - 0x02214030, 0x02211010, 0x02a19020, 0x01014050, - 0x40f000f0, 0x01819040, 0x40f000f0, 0x90a60160, + 0x0221403f, 0x0221101f, 0x02a19020, 0x90170110, + 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x90a60160, 0x40f000f0, 0x40f000f0, }; @@ -1894,6 +1696,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD71BXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fb, "HP dv4-1222nr", STAC_HP_DV4_1222NR), + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x1720, + "HP", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, "HP", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, @@ -1906,6 +1710,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP mini 1000", STAC_HP_M4), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361b, "HP HDX", STAC_HP_HDX), /* HDX16 */ + SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, + "HP dv6", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, "HP", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, @@ -2217,6 +2023,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { [STAC_D965_5ST_NO_FP] = d965_5st_no_fp_pin_configs, [STAC_DELL_3ST] = dell_3st_pin_configs, [STAC_DELL_BIOS] = NULL, + [STAC_927X_VOLKNOB] = NULL, }; static const char *stac927x_models[STAC_927X_MODELS] = { @@ -2228,6 +2035,7 @@ static const char *stac927x_models[STAC_927X_MODELS] = { [STAC_D965_5ST_NO_FP] = "5stack-no-fp", [STAC_DELL_3ST] = "dell-3stack", [STAC_DELL_BIOS] = "dell-bios", + [STAC_927X_VOLKNOB] = "volknob", }; static struct snd_pci_quirk stac927x_cfg_tbl[] = { @@ -2263,6 +2071,8 @@ static struct snd_pci_quirk stac927x_cfg_tbl[] = { "Intel D965", STAC_D965_5ST), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_INTEL, 0xff00, 0x2500, "Intel D965", STAC_D965_5ST), + /* volume-knob fixes */ + SND_PCI_QUIRK_VENDOR(0x10cf, "FSC", STAC_927X_VOLKNOB), {} /* terminator */ }; @@ -2839,8 +2649,6 @@ enum { STAC_CTL_WIDGET_VOL, STAC_CTL_WIDGET_MUTE, STAC_CTL_WIDGET_MONO_MUX, - STAC_CTL_WIDGET_AMP_MUX, - STAC_CTL_WIDGET_AMP_VOL, STAC_CTL_WIDGET_HP_SWITCH, STAC_CTL_WIDGET_IO_SWITCH, STAC_CTL_WIDGET_CLFE_SWITCH, @@ -2851,8 +2659,6 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { HDA_CODEC_VOLUME(NULL, 0, 0, 0), HDA_CODEC_MUTE(NULL, 0, 0, 0), STAC_MONO_MUX, - STAC_AMP_MUX, - STAC_AMP_VOL(NULL, 0, 0, 0, 0), STAC_CODEC_HP_SWITCH(NULL), STAC_CODEC_IO_SWITCH(NULL, 0), STAC_CODEC_CLFE_SWITCH(NULL, 0), @@ -3409,37 +3215,6 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) "Mono Mux", spec->mono_nid); } -/* labels for amp mux outputs */ -static const char *stac92xx_amp_labels[3] = { - "Front Microphone", "Microphone", "Line In", -}; - -/* create amp out controls mux on capable codecs */ -static int stac92xx_auto_create_amp_output_ctls(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - struct hda_input_mux *amp_mux = &spec->private_amp_mux; - int i, err; - - for (i = 0; i < spec->num_amps; i++) { - amp_mux->items[amp_mux->num_items].label = - stac92xx_amp_labels[i]; - amp_mux->items[amp_mux->num_items].index = i; - amp_mux->num_items++; - } - - if (spec->num_amps > 1) { - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_AMP_MUX, - "Amp Selector Capture Switch", 0); - if (err < 0) - return err; - } - return stac92xx_add_control(spec, STAC_CTL_WIDGET_AMP_VOL, - "Amp Capture Volume", - HDA_COMPOSE_AMP_VAL(spec->amp_nids[0], 3, 0, HDA_INPUT)); -} - - /* create PC beep volume controls */ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, hda_nid_t nid) @@ -3508,19 +3283,33 @@ static int stac92xx_beep_switch_ctl(struct hda_codec *codec) static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; - int wcaps, nid, i, err = 0; + int i, j, err = 0; for (i = 0; i < spec->num_muxes; i++) { + hda_nid_t nid; + unsigned int wcaps; + unsigned long val; + nid = spec->mux_nids[i]; wcaps = get_wcaps(codec, nid); + if (!(wcaps & AC_WCAP_OUT_AMP)) + continue; - if (wcaps & AC_WCAP_OUT_AMP) { - err = stac92xx_add_control_idx(spec, - STAC_CTL_WIDGET_VOL, i, "Mux Capture Volume", - HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT)); - if (err < 0) - return err; + /* check whether already the same control was created as + * normal Capture Volume. + */ + val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); + for (j = 0; j < spec->num_caps; j++) { + if (spec->capvols[j] == val) + break; } + if (j < spec->num_caps) + continue; + + err = stac92xx_add_control_idx(spec, STAC_CTL_WIDGET_VOL, i, + "Mux Capture Volume", val); + if (err < 0) + return err; } return 0; }; @@ -3575,55 +3364,97 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, return -1; } +/* create a volume assigned to the given pin (only if supported) */ +/* return 1 if the volume control is created */ +static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, + const char *label, int direction) +{ + unsigned int caps, nums; + char name[32]; + int err; + + if (direction == HDA_OUTPUT) + caps = AC_WCAP_OUT_AMP; + else + caps = AC_WCAP_IN_AMP; + if (!(get_wcaps(codec, nid) & caps)) + return 0; + caps = query_amp_caps(codec, nid, direction); + nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; + if (!nums) + return 0; + snprintf(name, sizeof(name), "%s Capture Volume", label); + err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); + if (err < 0) + return err; + return 1; +} + /* create playback/capture controls for input pins on dmic capable codecs */ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct sigmatel_spec *spec = codec->spec; + struct hda_input_mux *imux = &spec->private_imux; struct hda_input_mux *dimux = &spec->private_dimux; - int err, i; - char name[32]; + int err, i, active_mics; + unsigned int def_conf; dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; dimux->items[dimux->num_items].index = 0; dimux->num_items++; + active_mics = 0; + for (i = 0; i < spec->num_dmics; i++) { + /* check the validity: sometimes it's a dead vendor-spec node */ + if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i])) + != AC_WID_PIN) + continue; + def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); + if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) + active_mics++; + } + for (i = 0; i < spec->num_dmics; i++) { hda_nid_t nid; int index; - unsigned int wcaps; - unsigned int def_conf; + const char *label; - def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); + nid = spec->dmic_nids[i]; + if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) + continue; + def_conf = snd_hda_codec_get_pincfg(codec, nid); if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) continue; - nid = spec->dmic_nids[i]; index = get_connection_index(codec, spec->dmux_nids[0], nid); if (index < 0) continue; - wcaps = get_wcaps(codec, nid) & - (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); - - if (wcaps) { - sprintf(name, "%s Capture Volume", - stac92xx_dmic_labels[dimux->num_items]); + if (active_mics == 1) + label = "Digital Mic"; + else + label = stac92xx_dmic_labels[dimux->num_items]; - err = stac92xx_add_control(spec, - STAC_CTL_WIDGET_VOL, - name, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, - (wcaps & AC_WCAP_OUT_AMP) ? - HDA_OUTPUT : HDA_INPUT)); + err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); + if (err < 0) + return err; + if (!err) { + err = create_elem_capture_vol(codec, nid, label, + HDA_OUTPUT); if (err < 0) return err; } - dimux->items[dimux->num_items].label = - stac92xx_dmic_labels[dimux->num_items]; + dimux->items[dimux->num_items].label = label; dimux->items[dimux->num_items].index = index; dimux->num_items++; + if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { + imux->items[imux->num_items].label = label; + imux->items[imux->num_items].index = index; + imux->num_items++; + } } return 0; @@ -3666,18 +3497,26 @@ static int set_mic_route(struct hda_codec *codec, break; if (i <= AUTO_PIN_FRONT_MIC) { /* analog pin */ - mic->dmux_idx = 0; i = get_connection_index(codec, spec->mux_nids[0], pin); if (i < 0) return -1; mic->mux_idx = i; + mic->dmux_idx = -1; + if (spec->dmux_nids) + mic->dmux_idx = get_connection_index(codec, + spec->dmux_nids[0], + spec->mux_nids[0]); } else if (spec->dmux_nids) { /* digital pin */ - mic->mux_idx = 0; i = get_connection_index(codec, spec->dmux_nids[0], pin); if (i < 0) return -1; mic->dmux_idx = i; + mic->mux_idx = -1; + if (spec->mux_nids) + mic->mux_idx = get_connection_index(codec, + spec->mux_nids[0], + spec->dmux_nids[0]); } return 0; } @@ -3716,33 +3555,35 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const { struct sigmatel_spec *spec = codec->spec; struct hda_input_mux *imux = &spec->private_imux; - hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; - int i, j, k; + int i, j; for (i = 0; i < AUTO_PIN_LAST; i++) { - int index; + hda_nid_t nid = cfg->input_pins[i]; + int index, err; - if (!cfg->input_pins[i]) + if (!nid) continue; index = -1; for (j = 0; j < spec->num_muxes; j++) { - int num_cons; - num_cons = snd_hda_get_connections(codec, - spec->mux_nids[j], - con_lst, - HDA_MAX_NUM_INPUTS); - for (k = 0; k < num_cons; k++) - if (con_lst[k] == cfg->input_pins[i]) { - index = k; - goto found; - } + index = get_connection_index(codec, spec->mux_nids[j], + nid); + if (index >= 0) + break; } - continue; - found: + if (index < 0) + continue; + + err = create_elem_capture_vol(codec, nid, + auto_pin_cfg_labels[i], + HDA_INPUT); + if (err < 0) + return err; + imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; imux->items[imux->num_items].index = index; imux->num_items++; } + spec->num_analog_muxes = imux->num_items; if (imux->num_items) { /* @@ -3952,11 +3793,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if (err < 0) return err; } - if (spec->num_amps > 0) { - err = stac92xx_auto_create_amp_output_ctls(codec); - if (err < 0) - return err; - } if (spec->num_dmics > 0 && !spec->dinput_mux) if ((err = stac92xx_auto_create_dmic_input_ctls(codec, &spec->autocfg)) < 0) @@ -3993,7 +3829,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out spec->dinput_mux = &spec->private_dimux; spec->sinput_mux = &spec->private_smux; spec->mono_mux = &spec->private_mono_mux; - spec->amp_mux = &spec->private_amp_mux; return 1; } @@ -4350,7 +4185,8 @@ static int stac92xx_init(struct hda_codec *codec) hda_nid_t nid = cfg->hp_pins[i]; enable_pin_detect(codec, nid, STAC_HP_EVENT); } - if (cfg->line_out_type == AUTO_PIN_LINE_OUT) { + if (cfg->line_out_type == AUTO_PIN_LINE_OUT && + cfg->speaker_outs > 0) { /* enable pin-detect for line-outs as well */ for (i = 0; i < cfg->line_outs; i++) { hda_nid_t nid = cfg->line_out_pins[i]; @@ -4364,7 +4200,10 @@ static int stac92xx_init(struct hda_codec *codec) stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], AC_PINCTL_OUT_EN); /* fake event to set up pins */ - stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); + if (cfg->hp_pins[0]) + stac_issue_unsol_event(codec, cfg->hp_pins[0]); + else if (cfg->line_out_pins[0]) + stac_issue_unsol_event(codec, cfg->line_out_pins[0]); } else { stac92xx_auto_init_multi_out(codec); stac92xx_auto_init_hp_out(codec); @@ -4754,11 +4593,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec) mic = &spec->ext_mic; else mic = &spec->int_mic; - if (mic->dmux_idx) + if (mic->dmux_idx >= 0) snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, AC_VERB_SET_CONNECT_SEL, mic->dmux_idx); - else + if (mic->mux_idx >= 0) snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, AC_VERB_SET_CONNECT_SEL, mic->mux_idx); @@ -4831,6 +4670,26 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) } } +static int hp_bseries_system(u32 subsystem_id) +{ + switch (subsystem_id) { + case 0x103c307e: + case 0x103c307f: + case 0x103c3080: + case 0x103c3081: + case 0x103c1722: + case 0x103c1723: + case 0x103c1724: + case 0x103c1725: + case 0x103c1726: + case 0x103c1727: + case 0x103c1728: + case 0x103c1729: + return 1; + } + return 0; +} + #ifdef CONFIG_PROC_FS static void stac92hd_proc_hook(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid) @@ -4886,8 +4745,13 @@ static int stac92xx_resume(struct hda_codec *codec) snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); /* fake event to set up pins again to override cached values */ - if (spec->hp_detect) - stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); + if (spec->hp_detect) { + if (spec->autocfg.hp_pins[0]) + stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); + else if (spec->autocfg.line_out_pins[0]) + stac_issue_unsol_event(codec, + spec->autocfg.line_out_pins[0]); + } return 0; } @@ -4915,6 +4779,11 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, else spec->gpio_data |= spec->gpio_led; /* white */ + if (hp_bseries_system(codec->subsystem_id)) { + /* LED state is inverted on these systems */ + spec->gpio_data ^= spec->gpio_led; + } + stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); @@ -5104,16 +4973,6 @@ static int patch_stac925x(struct hda_codec *codec) return 0; } -static struct hda_input_mux stac92hd73xx_dmux = { - .num_items = 4, - .items = { - { "Analog Inputs", 0x0b }, - { "Digital Mic 1", 0x09 }, - { "Digital Mic 2", 0x0a }, - { "CD", 0x08 }, - } -}; - static int patch_stac92hd73xx(struct hda_codec *codec) { struct sigmatel_spec *spec; @@ -5133,6 +4992,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec) STAC_92HD73XX_MODELS, stac92hd73xx_models, stac92hd73xx_cfg_tbl); + /* check codec subsystem id if not found */ + if (spec->board_config < 0) + spec->board_config = + snd_hda_check_board_codec_sid_config(codec, + STAC_92HD73XX_MODELS, stac92hd73xx_models, + stac92hd73xx_codec_id_cfg_tbl); again: if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", @@ -5149,20 +5014,15 @@ again: "number of channels defaulting to DAC count\n"); num_dacs = STAC92HD73_DAC_COUNT; } + spec->init = stac92hd73xx_core_init; switch (num_dacs) { case 0x3: /* 6 Channel */ - spec->mixer = stac92hd73xx_6ch_mixer; - spec->init = stac92hd73xx_6ch_core_init; spec->aloopback_ctl = stac92hd73xx_6ch_loopback; break; case 0x4: /* 8 Channel */ - spec->mixer = stac92hd73xx_8ch_mixer; - spec->init = stac92hd73xx_8ch_core_init; spec->aloopback_ctl = stac92hd73xx_8ch_loopback; break; case 0x5: /* 10 Channel */ - spec->mixer = stac92hd73xx_10ch_mixer; - spec->init = stac92hd73xx_10ch_core_init; spec->aloopback_ctl = stac92hd73xx_10ch_loopback; break; } @@ -5177,14 +5037,10 @@ again: spec->dmic_nids = stac92hd73xx_dmic_nids; spec->dmux_nids = stac92hd73xx_dmux_nids; spec->smux_nids = stac92hd73xx_smux_nids; - spec->amp_nids = stac92hd73xx_amp_nids; - spec->num_amps = ARRAY_SIZE(stac92hd73xx_amp_nids); spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); - memcpy(&spec->private_dimux, &stac92hd73xx_dmux, - sizeof(stac92hd73xx_dmux)); spec->num_caps = STAC92HD73XX_NUM_CAPS; spec->capvols = stac92hd73xx_capvols; @@ -5198,43 +5054,40 @@ again: case STAC_DELL_M6_DMIC: case STAC_DELL_M6_BOTH: spec->num_smuxes = 0; - spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER]; - spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; spec->eapd_switch = 0; - spec->num_amps = 1; - if (spec->board_config != STAC_DELL_EQ) - spec->init = dell_m6_core_init; switch (spec->board_config) { case STAC_DELL_M6_AMIC: /* Analog Mics */ snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); spec->num_dmics = 0; - spec->private_dimux.num_items = 1; break; case STAC_DELL_M6_DMIC: /* Digital Mics */ snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); spec->num_dmics = 1; - spec->private_dimux.num_items = 2; break; case STAC_DELL_M6_BOTH: /* Both */ snd_hda_codec_set_pincfg(codec, 0x0b, 0x90A70170); snd_hda_codec_set_pincfg(codec, 0x13, 0x90A60160); spec->num_dmics = 1; - spec->private_dimux.num_items = 2; break; } break; + case STAC_ALIENWARE_M17X: + spec->num_dmics = STAC92HD73XX_NUM_DMICS; + spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); + spec->eapd_switch = 0; + break; default: spec->num_dmics = STAC92HD73XX_NUM_DMICS; spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); spec->eapd_switch = 1; + break; } - if (spec->board_config > STAC_92HD73XX_REF) { + if (spec->board_config != STAC_92HD73XX_REF) { /* GPIO0 High = Enable EAPD */ spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; spec->gpio_data = 0x01; } - spec->dinput_mux = &spec->private_dimux; spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); spec->pwr_nids = stac92hd73xx_pwr_nids; @@ -5266,15 +5119,6 @@ again: return 0; } -static struct hda_input_mux stac92hd83xxx_dmux = { - .num_items = 3, - .items = { - { "Analog Inputs", 0x03 }, - { "Digital Mic 1", 0x04 }, - { "Digital Mic 2", 0x05 }, - } -}; - static int patch_stac92hd83xxx(struct hda_codec *codec) { struct sigmatel_spec *spec; @@ -5289,25 +5133,18 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) codec->spec = spec; codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; - spec->mono_nid = 0x19; spec->digbeep_nid = 0x21; - spec->dmic_nids = stac92hd83xxx_dmic_nids; - spec->dmux_nids = stac92hd83xxx_dmux_nids; + spec->mux_nids = stac92hd83xxx_mux_nids; + spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); spec->adc_nids = stac92hd83xxx_adc_nids; + spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids); spec->pwr_nids = stac92hd83xxx_pwr_nids; - spec->amp_nids = stac92hd83xxx_amp_nids; spec->pwr_mapping = stac92hd83xxx_pwr_mapping; spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); spec->multiout.dac_nids = spec->dac_nids; spec->init = stac92hd83xxx_core_init; - spec->mixer = stac92hd83xxx_mixer; spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); - spec->num_dmuxes = ARRAY_SIZE(stac92hd83xxx_dmux_nids); - spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids); - spec->num_amps = ARRAY_SIZE(stac92hd83xxx_amp_nids); - spec->num_dmics = STAC92HD83XXX_NUM_DMICS; - spec->dinput_mux = &stac92hd83xxx_dmux; spec->pin_nids = stac92hd83xxx_pin_nids; spec->num_caps = STAC92HD83XXX_NUM_CAPS; spec->capvols = stac92hd83xxx_capvols; @@ -5377,25 +5214,6 @@ again: return 0; } -static struct hda_input_mux stac92hd71bxx_dmux_nomixer = { - .num_items = 3, - .items = { - { "Analog Inputs", 0x00 }, - { "Digital Mic 1", 0x02 }, - { "Digital Mic 2", 0x03 }, - } -}; - -static struct hda_input_mux stac92hd71bxx_dmux_amixer = { - .num_items = 4, - .items = { - { "Analog Inputs", 0x00 }, - { "Mixer", 0x01 }, - { "Digital Mic 1", 0x02 }, - { "Digital Mic 2", 0x03 }, - } -}; - /* get the pin connection (fixed, none, etc) */ static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) { @@ -5455,8 +5273,8 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) { struct sigmatel_spec *spec; struct hda_verb *unmute_init = stac92hd71bxx_unmute_core_init; + unsigned int pin_cfg; int err = 0; - unsigned int ndmic_nids = 0; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -5491,7 +5309,7 @@ again: stac92xx_set_config_regs(codec, stac92hd71bxx_brd_tbl[spec->board_config]); - if (spec->board_config > STAC_92HD71BXX_REF) { + if (spec->board_config != STAC_92HD71BXX_REF) { /* GPIO0 = EAPD */ spec->gpio_mask = 0x01; spec->gpio_dir = 0x01; @@ -5512,21 +5330,13 @@ again: /* fallthru */ case 0x111d76b4: /* 6 Port without Analog Mixer */ case 0x111d76b5: - memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer, - sizeof(stac92hd71bxx_dmux_nomixer)); spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92hd71bxx_connected_ports(codec, stac92hd71bxx_dmic_nids, STAC92HD71BXX_NUM_DMICS); - if (spec->num_dmics) { - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); - spec->dinput_mux = &spec->private_dimux; - ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; - } break; case 0x111d7608: /* 5 Port with Analog Mixer */ - spec->private_dimux.num_items--; switch (spec->board_config) { case STAC_HP_M4: /* Enable VREF power saving on GPIO1 detect */ @@ -5548,15 +5358,6 @@ again: /* no output amps */ spec->num_pwrs = 0; - if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) { - spec->mixer = stac92hd71bxx_analog_mixer; - memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, - sizeof(stac92hd71bxx_dmux_amixer)); - } else { - memcpy(&spec->private_dimux, - &stac92hd71bxx_dmux_nomixer, - sizeof(stac92hd71bxx_dmux_nomixer)); - } /* disable VSW */ spec->init = stac92hd71bxx_core_init; unmute_init++; @@ -5566,11 +5367,6 @@ again: spec->num_dmics = stac92hd71bxx_connected_ports(codec, stac92hd71bxx_dmic_nids, STAC92HD71BXX_NUM_DMICS - 1); - if (spec->num_dmics) { - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); - spec->dinput_mux = &spec->private_dimux; - ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2; - } break; case 0x111d7603: /* 6 Port with Analog Mixer */ if ((codec->revision_id & 0xf) == 1) @@ -5580,25 +5376,12 @@ again: spec->num_pwrs = 0; /* fallthru */ default: - if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) { - spec->mixer = stac92hd71bxx_analog_mixer; - memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, - sizeof(stac92hd71bxx_dmux_amixer)); - } else { - memcpy(&spec->private_dimux, - &stac92hd71bxx_dmux_nomixer, - sizeof(stac92hd71bxx_dmux_nomixer)); - } spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92hd71bxx_connected_ports(codec, stac92hd71bxx_dmic_nids, STAC92HD71BXX_NUM_DMICS); - if (spec->num_dmics) { - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); - spec->dinput_mux = &spec->private_dimux; - ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; - } + break; } if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) @@ -5626,6 +5409,7 @@ again: spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); + spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); switch (spec->board_config) { @@ -5658,6 +5442,11 @@ again: case STAC_HP_DV5: snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); + /* HP dv6 gives the headphone pin as a line-out. Thus we + * need to set hp_detect flag here to force to enable HP + * detection. + */ + spec->hp_detect = 1; break; case STAC_HP_HDX: spec->num_dmics = 1; @@ -5668,6 +5457,45 @@ again: break; } + if (hp_bseries_system(codec->subsystem_id)) { + pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); + if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || + get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || + get_defcfg_device(pin_cfg) == AC_JACK_HP_OUT) { + /* It was changed in the BIOS to just satisfy MS DTM. + * Lets turn it back into slaved HP + */ + pin_cfg = (pin_cfg & (~AC_DEFCFG_DEVICE)) + | (AC_JACK_HP_OUT << + AC_DEFCFG_DEVICE_SHIFT); + pin_cfg = (pin_cfg & (~(AC_DEFCFG_DEF_ASSOC + | AC_DEFCFG_SEQUENCE))) + | 0x1f; + snd_hda_codec_set_pincfg(codec, 0x0f, pin_cfg); + } + } + + if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { + const struct dmi_device *dev = NULL; + while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, + NULL, dev))) { + if (strcmp(dev->name, "HP_Mute_LED_1")) { + switch (codec->vendor_id) { + case 0x111d7608: + spec->gpio_led = 0x01; + break; + case 0x111d7600: + case 0x111d7601: + case 0x111d7602: + case 0x111d7603: + spec->gpio_led = 0x08; + break; + } + break; + } + } + } + #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { spec->gpio_mask |= spec->gpio_led; @@ -5680,8 +5508,6 @@ again: #endif spec->multiout.dac_nids = spec->dac_nids; - if (spec->dinput_mux) - spec->private_dimux.num_items += spec->num_dmics - ndmic_nids; err = stac92xx_parse_auto_config(codec, 0x21, 0); if (!err) { @@ -5842,14 +5668,17 @@ static int patch_stac927x(struct hda_codec *codec) spec->dac_list = stac927x_dac_nids; spec->multiout.dac_nids = spec->dac_nids; + if (spec->board_config != STAC_D965_REF) { + /* GPIO0 High = Enable EAPD */ + spec->eapd_mask = spec->gpio_mask = 0x01; + spec->gpio_dir = spec->gpio_data = 0x01; + } + switch (spec->board_config) { case STAC_D965_3ST: case STAC_D965_5ST: /* GPIO0 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x01; - spec->gpio_data = 0x01; spec->num_dmics = 0; - spec->init = d965_core_init; break; case STAC_DELL_BIOS: @@ -5868,32 +5697,26 @@ static int patch_stac927x(struct hda_codec *codec) snd_hda_codec_set_pincfg(codec, 0x0e, 0x02a79130); /* fallthru */ case STAC_DELL_3ST: - /* GPIO2 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x04; - spec->gpio_data = 0x04; - switch (codec->subsystem_id) { - case 0x1028022f: - /* correct EAPD to be GPIO0 */ - spec->eapd_mask = spec->gpio_mask = 0x01; - spec->gpio_dir = spec->gpio_data = 0x01; - break; - }; + if (codec->subsystem_id != 0x1028022f) { + /* GPIO2 High = Enable EAPD */ + spec->eapd_mask = spec->gpio_mask = 0x04; + spec->gpio_dir = spec->gpio_data = 0x04; + } spec->dmic_nids = stac927x_dmic_nids; spec->num_dmics = STAC927X_NUM_DMICS; - spec->init = d965_core_init; + spec->init = dell_3st_core_init; spec->dmux_nids = stac927x_dmux_nids; spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); break; + case STAC_927X_VOLKNOB: + spec->num_dmics = 0; + spec->init = stac927x_volknob_core_init; + break; default: - if (spec->board_config > STAC_D965_REF) { - /* GPIO0 High = Enable EAPD */ - spec->eapd_mask = spec->gpio_mask = 0x01; - spec->gpio_dir = spec->gpio_data = 0x01; - } spec->num_dmics = 0; - spec->init = stac927x_core_init; + break; } spec->num_caps = STAC927X_NUM_CAPS;