diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-10-14 09:26:20 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-10-27 10:58:11 -0400 |
commit | 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 (patch) | |
tree | ede0051a5028349463d608ed7c514000bc049bb4 /sound/pci/hda | |
parent | 254f296840b64b034a4c850d45dbde7c040f0819 (diff) |
ALSA: hda - Fix ADC input-amp handling for Cx20549 codec
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.
Cc: <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 1d69a3e0ce2c..0c8b5a1993ed 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -137,6 +137,7 @@ struct conexant_spec { | |||
137 | unsigned int hp_laptop:1; | 137 | unsigned int hp_laptop:1; |
138 | unsigned int asus:1; | 138 | unsigned int asus:1; |
139 | unsigned int pin_eapd_ctrls:1; | 139 | unsigned int pin_eapd_ctrls:1; |
140 | unsigned int single_adc_amp:1; | ||
140 | 141 | ||
141 | unsigned int adc_switching:1; | 142 | unsigned int adc_switching:1; |
142 | 143 | ||
@@ -4213,6 +4214,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, | |||
4213 | int idx = get_input_connection(codec, adc_nid, nid); | 4214 | int idx = get_input_connection(codec, adc_nid, nid); |
4214 | if (idx < 0) | 4215 | if (idx < 0) |
4215 | continue; | 4216 | continue; |
4217 | if (spec->single_adc_amp) | ||
4218 | idx = 0; | ||
4216 | return cx_auto_add_volume_idx(codec, label, pfx, | 4219 | return cx_auto_add_volume_idx(codec, label, pfx, |
4217 | cidx, adc_nid, HDA_INPUT, idx); | 4220 | cidx, adc_nid, HDA_INPUT, idx); |
4218 | } | 4221 | } |
@@ -4253,14 +4256,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) | |||
4253 | struct hda_input_mux *imux = &spec->private_imux; | 4256 | struct hda_input_mux *imux = &spec->private_imux; |
4254 | const char *prev_label; | 4257 | const char *prev_label; |
4255 | int input_conn[HDA_MAX_NUM_INPUTS]; | 4258 | int input_conn[HDA_MAX_NUM_INPUTS]; |
4256 | int i, err, cidx; | 4259 | int i, j, err, cidx; |
4257 | int multi_connection; | 4260 | int multi_connection; |
4258 | 4261 | ||
4262 | if (!imux->num_items) | ||
4263 | return 0; | ||
4264 | |||
4259 | multi_connection = 0; | 4265 | multi_connection = 0; |
4260 | for (i = 0; i < imux->num_items; i++) { | 4266 | for (i = 0; i < imux->num_items; i++) { |
4261 | cidx = get_input_connection(codec, spec->imux_info[i].adc, | 4267 | cidx = get_input_connection(codec, spec->imux_info[i].adc, |
4262 | spec->imux_info[i].pin); | 4268 | spec->imux_info[i].pin); |
4263 | input_conn[i] = (spec->imux_info[i].adc << 8) | cidx; | 4269 | if (cidx < 0) |
4270 | continue; | ||
4271 | input_conn[i] = spec->imux_info[i].adc; | ||
4272 | if (!spec->single_adc_amp) | ||
4273 | input_conn[i] |= cidx << 8; | ||
4264 | if (i > 0 && input_conn[i] != input_conn[0]) | 4274 | if (i > 0 && input_conn[i] != input_conn[0]) |
4265 | multi_connection = 1; | 4275 | multi_connection = 1; |
4266 | } | 4276 | } |
@@ -4289,6 +4299,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec) | |||
4289 | err = cx_auto_add_capture_volume(codec, nid, | 4299 | err = cx_auto_add_capture_volume(codec, nid, |
4290 | "Capture", "", cidx); | 4300 | "Capture", "", cidx); |
4291 | } else { | 4301 | } else { |
4302 | bool dup_found = false; | ||
4303 | for (j = 0; j < i; j++) { | ||
4304 | if (input_conn[j] == input_conn[i]) { | ||
4305 | dup_found = true; | ||
4306 | break; | ||
4307 | } | ||
4308 | } | ||
4309 | if (dup_found) | ||
4310 | continue; | ||
4292 | err = cx_auto_add_capture_volume(codec, nid, | 4311 | err = cx_auto_add_capture_volume(codec, nid, |
4293 | label, " Capture", cidx); | 4312 | label, " Capture", cidx); |
4294 | } | 4313 | } |
@@ -4413,6 +4432,12 @@ static int patch_conexant_auto(struct hda_codec *codec) | |||
4413 | codec->spec = spec; | 4432 | codec->spec = spec; |
4414 | codec->pin_amp_workaround = 1; | 4433 | codec->pin_amp_workaround = 1; |
4415 | 4434 | ||
4435 | switch (codec->vendor_id) { | ||
4436 | case 0x14f15045: | ||
4437 | spec->single_adc_amp = 1; | ||
4438 | break; | ||
4439 | } | ||
4440 | |||
4416 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); | 4441 | apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl); |
4417 | 4442 | ||
4418 | err = cx_auto_search_adcs(codec); | 4443 | err = cx_auto_search_adcs(codec); |