aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-10-14 15:26:20 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-11 09:43:33 -0800
commita4fd5a818d0bc41dd3cb8ee4b73312004e6b02d6 (patch)
tree735a581f756aed86edc1845bdc95b80d9d90a567 /sound
parentcc3370d8221a8561a0f955aedc243af971b1e9d7 (diff)
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 <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_conexant.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 502b05b1c8e..41fecc1e7ad 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;