From: Takashi Iwai Date: Fri, 14 Oct 2011 13:26:20 +0000 (+0200) Subject: ALSA: hda - Fix ADC input-amp handling for Cx20549 codec X-Git-Tag: v3.1.1~115 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=a4fd5a818d0bc41dd3cb8ee4b73312004e6b02d6;p=karo-tx-linux.git ALSA: hda - Fix ADC input-amp handling for Cx20549 codec commit 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 upstream. It seems that Conexant CX20549 chip handle only a single input-amp even though 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. This is true for another Conexant codec, but it's not applied to CX20549 actually. This patch changes the auto-parser code to handle a single input-amp per audio-in widget for CX20549. 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. We haven't tested 20551 and 20561 codecs yet. If these show the similar behavior like 20549, they need to set spec->single_adc_amp=1, too. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 502b05b1c8e1..41fecc1e7ad8 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -137,6 +137,7 @@ struct conexant_spec { unsigned int hp_laptop:1; unsigned int asus:1; unsigned int pin_eapd_ctrls:1; + unsigned int single_adc_amp:1; unsigned int adc_switching:1; @@ -4256,6 +4257,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, int idx = get_input_connection(codec, adc_nid, nid); if (idx < 0) continue; + if (spec->single_adc_amp) + idx = 0; return cx_auto_add_volume_idx(codec, label, pfx, cidx, adc_nid, HDA_INPUT, idx); } @@ -4296,14 +4299,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) 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 (cidx < 0) + continue; + input_conn[i] = spec->imux_info[i].adc; + if (!spec->single_adc_amp) + input_conn[i] |= cidx << 8; if (i > 0 && input_conn[i] != input_conn[0]) multi_connection = 1; } @@ -4332,6 +4342,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) err = cx_auto_add_capture_volume(codec, nid, "Capture", "", cidx); } else { + bool dup_found = false; + for (j = 0; j < i; j++) { + if (input_conn[j] == input_conn[i]) { + dup_found = true; + break; + } + } + if (dup_found) + continue; err = cx_auto_add_capture_volume(codec, nid, label, " Capture", cidx); } @@ -4408,6 +4427,13 @@ static int patch_conexant_auto(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; codec->pin_amp_workaround = 1; + + switch (codec->vendor_id) { + case 0x14f15045: + spec->single_adc_amp = 1; + break; + } + err = cx_auto_search_adcs(codec); if (err < 0) return err;