It seems that Conexant chips handle only a single input-amp even when the audio-input widget has multiple sources. This has been never clear, and I implemented in the current way based on the debug information I got at the early time -- the device reacts individual input-amp values for different sources. But it doesn't look correct now.
This patch changes the auto-parser code to handle a single input-amp per audio-in widget. After applying this, you'll see only a single "Capture" volume control instead of separate "Mic" or "Line" captures when the device is set up to use a single ADC.
Cc: stable@kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/hda_proc.c | 7 +++++-- sound/pci/hda/patch_conexant.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 2c981b5..9431369 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -646,12 +646,15 @@ static void print_codec_info(struct snd_info_entry *entry, HDA_MAX_CONNECTIONS);
if (wid_caps & AC_WCAP_IN_AMP) { + int nums = conn_len; snd_iprintf(buffer, " Amp-In caps: "); print_amp_caps(buffer, codec, nid, HDA_INPUT); snd_iprintf(buffer, " Amp-In vals: "); + if (wid_type == AC_WID_PIN || + (wid_type == AC_WID_AUD_IN && codec->pin_amp_workaround)) + nums = 1; print_amp_vals(buffer, codec, nid, HDA_INPUT, - wid_caps & AC_WCAP_STEREO, - wid_type == AC_WID_PIN ? 1 : conn_len); + wid_caps & AC_WCAP_STEREO, nums); } if (wid_caps & AC_WCAP_OUT_AMP) { snd_iprintf(buffer, " Amp-Out caps: "); diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index feef775..f2d4933 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -4251,16 +4251,20 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) struct conexant_spec *spec = codec->spec; struct hda_input_mux *imux = &spec->private_imux; const char *prev_label; - int input_conn[HDA_MAX_NUM_INPUTS]; - int i, err, cidx; + int i, j, err, cidx; int multi_connection;
+ if (!imux->num_items) + return 0; + multi_connection = 0; for (i = 0; i < imux->num_items; i++) { cidx = get_input_connection(codec, spec->imux_info[i].adc, spec->imux_info[i].pin); - input_conn[i] = (spec->imux_info[i].adc << 8) | cidx; - if (i > 0 && input_conn[i] != input_conn[0]) + if (cidx < 0) + continue; + if (i > 0 && !multi_connection && + spec->imux_info[i].adc != spec->imux_info[0].adc) multi_connection = 1; }
@@ -4282,15 +4286,27 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) if (err < 0) return err;
- if (!multi_connection) { - if (i > 0) + if (multi_connection) { + bool found = false; + for (j = 0; j < i; j++) { + if (spec->imux_info[j].adc == spec->imux_info[i].adc) { + found = true; + break; + } + } + if (found) continue; - err = cx_auto_add_capture_volume(codec, nid, - "Capture", "", cidx); - } else { - err = cx_auto_add_capture_volume(codec, nid, - label, " Capture", cidx); + err = cx_auto_add_capture_volume(codec, nid, label, + " Capture", cidx); + if (err < 0) + return err; } + } + + if (!multi_connection) { + err = cx_auto_add_volume_idx(codec, "Capture", "", 0, + spec->imux_info[0].adc, + HDA_INPUT, 0); if (err < 0) return err; }