From e3d7a1431f1d8851d11b2262dda5bb67158450eb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Jun 2011 13:52:33 +0200 Subject: [PATCH] ALSA: hda - Fix smart51 handling again Fix the broken detection of smart51 and its handling. Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_via.c | 145 +++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 82 deletions(-) diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index deb33ae109c8..c3be9f124b68 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -165,12 +165,17 @@ struct via_spec { const struct hda_input_mux *hp_mux; unsigned int hp_independent_mode; unsigned int hp_independent_mode_index; - unsigned int can_smart51; - unsigned int smart51_enabled; unsigned int dmic_enabled; unsigned int no_pin_power_ctl; enum VIA_HDA_CODEC codec_type; + /* smart51 setup */ + unsigned int smart51_nums; + hda_nid_t smart51_pins[2]; + int smart51_idxs[2]; + const char *smart51_labels[2]; + unsigned int smart51_enabled; + /* work to check hp jack state */ struct hda_codec *codec; struct delayed_work vt1708_hp_work; @@ -508,7 +513,7 @@ static void via_auto_init_multi_out(struct hda_codec *codec) struct via_spec *spec = codec->spec; int i; - for (i = 0; i < spec->autocfg.line_outs; i++) + for (i = 0; i < spec->autocfg.line_outs + spec->smart51_nums; i++) via_auto_init_output(codec, spec->autocfg.line_out_pins[i], PIN_OUT, &spec->out_path[i]); } @@ -771,15 +776,15 @@ static int via_hp_build(struct hda_codec *codec) static void notify_aa_path_ctls(struct hda_codec *codec) { + struct via_spec *spec = codec->spec; int i; - struct snd_ctl_elem_id id; - const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"}; - struct snd_kcontrol *ctl; - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - for (i = 0; i < ARRAY_SIZE(labels); i++) { - sprintf(id.name, "%s Playback Volume", labels[i]); + for (i = 0; i < spec->smart51_nums; i++) { + struct snd_kcontrol *ctl; + struct snd_ctl_elem_id id; + memset(&id, 0, sizeof(id)); + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + sprintf(id.name, "%s Playback Volume", spec->smart51_labels[i]); ctl = snd_hda_find_mixer_ctl(codec, id.name); if (ctl) snd_ctl_notify(codec->bus->card, @@ -791,43 +796,20 @@ static void notify_aa_path_ctls(struct hda_codec *codec) static void mute_aa_path(struct hda_codec *codec, int mute) { struct via_spec *spec = codec->spec; - int start_idx; - int end_idx; + int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE; int i; - /* get nid of MW0 and start & end index */ - switch (spec->codec_type) { - case VT1708: - start_idx = 2; - end_idx = 4; - break; - case VT1709_10CH: - case VT1709_6CH: - start_idx = 2; - end_idx = 4; - break; - case VT1708B_8CH: - case VT1708B_4CH: - case VT1708S: - case VT1716S: - start_idx = 2; - end_idx = 4; - break; - case VT1718S: - start_idx = 1; - end_idx = 3; - break; - default: - return; - } + /* check AA path's mute status */ - for (i = start_idx; i <= end_idx; i++) { - int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE; - snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid, HDA_INPUT, i, + for (i = 0; i < spec->smart51_nums; i++) { + if (spec->smart51_idxs[i] < 0) + continue; + snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid, + HDA_INPUT, spec->smart51_idxs[i], HDA_AMP_MUTE, val); } } -static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) +static bool is_smart51_candidate(struct hda_codec *codec, hda_nid_t pin) { struct via_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; @@ -847,6 +829,17 @@ static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) return false; } +static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) +{ + struct via_spec *spec = codec->spec; + int i; + + for (i = 0; i < spec->smart51_nums; i++) + if (spec->smart51_pins[i] == pin) + return true; + return false; +} + static int via_smart51_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -862,18 +855,12 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; int on = 1; int i; - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; + for (i = 0; i < spec->smart51_nums; i++) { + hda_nid_t nid = spec->smart51_pins[i]; unsigned int ctl; - if (cfg->inputs[i].type == AUTO_PIN_MIC && - spec->hp_independent_mode && spec->codec_type != VT1718S) - continue; /* ignore FMic for independent HP */ - if (!is_smart51_pins(codec, nid)) - continue; ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) @@ -888,21 +875,14 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - const struct auto_pin_cfg *cfg = &spec->autocfg; int out_in = *ucontrol->value.integer.value ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; int i; - for (i = 0; i < cfg->num_inputs; i++) { - hda_nid_t nid = cfg->inputs[i].pin; + for (i = 0; i < spec->smart51_nums; i++) { + hda_nid_t nid = spec->smart51_pins[i]; unsigned int parm; - if (cfg->inputs[i].type == AUTO_PIN_MIC && - spec->hp_independent_mode && spec->codec_type != VT1718S) - continue; /* don't retask FMic for independent HP */ - if (!is_smart51_pins(codec, nid)) - continue; - parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); @@ -932,26 +912,11 @@ static const struct snd_kcontrol_new via_smart51_mixer = { static int via_smart51_build(struct hda_codec *codec) { struct via_spec *spec = codec->spec; - struct snd_kcontrol_new *knew; - const struct auto_pin_cfg *cfg = &spec->autocfg; - hda_nid_t nid; - int i; - if (!spec->can_smart51) + if (!spec->smart51_nums) return 0; - - knew = via_clone_control(spec, &via_smart51_mixer); - if (knew == NULL) + if (!via_clone_control(spec, &via_smart51_mixer)) return -ENOMEM; - - for (i = 0; i < cfg->num_inputs; i++) { - nid = cfg->inputs[i].pin; - if (is_smart51_pins(codec, nid)) { - knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; - break; - } - } - return 0; } @@ -1751,12 +1716,18 @@ static void mangle_smart51(struct hda_codec *codec) { struct via_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - int i; + int i, nums = 0; for (i = 0; i < cfg->num_inputs; i++) { - if (!is_smart51_pins(codec, cfg->inputs[i].pin)) + if (is_smart51_candidate(codec, cfg->inputs[i].pin)) + nums++; + } + if (cfg->line_outs + nums < 3) + return; + for (i = 0; i < cfg->num_inputs; i++) { + if (!is_smart51_candidate(codec, cfg->inputs[i].pin)) continue; - spec->can_smart51 = 1; + spec->smart51_pins[spec->smart51_nums++] = cfg->inputs[i].pin; cfg->line_out_pins[cfg->line_outs++] = cfg->inputs[i].pin; if (cfg->line_outs == 3) break; @@ -1779,6 +1750,10 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec) if (cfg->line_outs == 1) mangle_smart51(codec); + err = via_auto_fill_dac_nids(codec); + if (err < 0) + return err; + for (i = 0; i < cfg->line_outs; i++) { hda_nid_t pin, dac; pin = cfg->line_out_pins[i]; @@ -1926,7 +1901,7 @@ static int via_auto_create_analog_input_ctls(struct hda_codec *codec, { struct via_spec *spec = codec->spec; struct hda_input_mux *imux = &spec->private_imux[0]; - int i, err, idx, idx2, type, type_idx = 0; + int i, j, err, idx, idx2, type, type_idx = 0; hda_nid_t cap_nid; hda_nid_t pin_idxs[8]; int num_idxs; @@ -1973,6 +1948,15 @@ static int via_auto_create_analog_input_ctls(struct hda_codec *codec, if (err < 0) return err; snd_hda_add_imux_item(imux, label, idx, NULL); + + /* remember the label for smart51 control */ + for (j = 0; j < spec->smart51_nums; j++) { + if (spec->smart51_pins[j] == cfg->inputs[i].pin) { + spec->smart51_idxs[j] = idx; + spec->smart51_labels[j] = label; + break; + } + } } /* create capture mixer elements */ @@ -2105,9 +2089,6 @@ static int via_parse_auto_config(struct hda_codec *codec) int err; err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); - if (err < 0) - return err; - err = via_auto_fill_dac_nids(codec); if (err < 0) return err; if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])