aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2011-02-15 13:57:09 -0500
committerTakashi Iwai <tiwai@suse.de>2011-02-19 10:14:14 -0500
commit983345e51e0de144775c7449e5cb01ce6cdd1346 (patch)
treec0933257ef342d59d75892c40e658811853ad7a6
parentb540afc2b3d6e4cd1d1f137ef6d9e9c78d67fecd (diff)
ALSA: HDA: Conexant auto: Handle multiple connections to ADC node
Conexant 20641 has several inputs to its ADC node, with one selector and individual amps for all inputs. This patch adds support in the Conexant auto parser to handle that case. It also means that the pin node's volume is being renamed to "Boost" to avoid name clash with the new volume controls on the ADC node. BugLink: http://bugs.launchpad.net/bugs/719524 Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/patch_conexant.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index fbe97d32140d..cd29eafdc0ed 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -3729,9 +3729,9 @@ static int cx_auto_init(struct hda_codec *codec)
3729 return 0; 3729 return 0;
3730} 3730}
3731 3731
3732static int cx_auto_add_volume(struct hda_codec *codec, const char *basename, 3732static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
3733 const char *dir, int cidx, 3733 const char *dir, int cidx,
3734 hda_nid_t nid, int hda_dir) 3734 hda_nid_t nid, int hda_dir, int amp_idx)
3735{ 3735{
3736 static char name[32]; 3736 static char name[32];
3737 static struct snd_kcontrol_new knew[] = { 3737 static struct snd_kcontrol_new knew[] = {
@@ -3743,7 +3743,8 @@ static int cx_auto_add_volume(struct hda_codec *codec, const char *basename,
3743 3743
3744 for (i = 0; i < 2; i++) { 3744 for (i = 0; i < 2; i++) {
3745 struct snd_kcontrol *kctl; 3745 struct snd_kcontrol *kctl;
3746 knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, hda_dir); 3746 knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx,
3747 hda_dir);
3747 knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; 3748 knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
3748 knew[i].index = cidx; 3749 knew[i].index = cidx;
3749 snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]); 3750 snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]);
@@ -3759,6 +3760,9 @@ static int cx_auto_add_volume(struct hda_codec *codec, const char *basename,
3759 return 0; 3760 return 0;
3760} 3761}
3761 3762
3763#define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \
3764 cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0)
3765
3762#define cx_auto_add_pb_volume(codec, nid, str, idx) \ 3766#define cx_auto_add_pb_volume(codec, nid, str, idx) \
3763 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) 3767 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
3764 3768
@@ -3808,29 +3812,60 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
3808 struct conexant_spec *spec = codec->spec; 3812 struct conexant_spec *spec = codec->spec;
3809 struct auto_pin_cfg *cfg = &spec->autocfg; 3813 struct auto_pin_cfg *cfg = &spec->autocfg;
3810 static const char *prev_label; 3814 static const char *prev_label;
3811 int i, err, cidx; 3815 int i, err, cidx, conn_len;
3816 hda_nid_t conn[HDA_MAX_CONNECTIONS];
3817
3818 int multi_adc_volume = 0; /* If the ADC nid has several input volumes */
3819 int adc_nid = spec->adc_nids[0];
3820
3821 conn_len = snd_hda_get_connections(codec, adc_nid, conn,
3822 HDA_MAX_CONNECTIONS);
3823 if (conn_len < 0)
3824 return conn_len;
3825
3826 multi_adc_volume = cfg->num_inputs > 1 && conn_len > 1;
3827 if (!multi_adc_volume) {
3828 err = cx_auto_add_volume(codec, "Capture", "", 0, adc_nid,
3829 HDA_INPUT);
3830 if (err < 0)
3831 return err;
3832 }
3812 3833
3813 err = cx_auto_add_volume(codec, "Capture", "", 0, spec->adc_nids[0],
3814 HDA_INPUT);
3815 if (err < 0)
3816 return err;
3817 prev_label = NULL; 3834 prev_label = NULL;
3818 cidx = 0; 3835 cidx = 0;
3819 for (i = 0; i < cfg->num_inputs; i++) { 3836 for (i = 0; i < cfg->num_inputs; i++) {
3820 hda_nid_t nid = cfg->inputs[i].pin; 3837 hda_nid_t nid = cfg->inputs[i].pin;
3821 const char *label; 3838 const char *label;
3822 if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) 3839 int j;
3840 int pin_amp = get_wcaps(codec, nid) & AC_WCAP_IN_AMP;
3841 if (!pin_amp && !multi_adc_volume)
3823 continue; 3842 continue;
3843
3824 label = hda_get_autocfg_input_label(codec, cfg, i); 3844 label = hda_get_autocfg_input_label(codec, cfg, i);
3825 if (label == prev_label) 3845 if (label == prev_label)
3826 cidx++; 3846 cidx++;
3827 else 3847 else
3828 cidx = 0; 3848 cidx = 0;
3829 prev_label = label; 3849 prev_label = label;
3830 err = cx_auto_add_volume(codec, label, " Capture", cidx, 3850
3831 nid, HDA_INPUT); 3851 if (pin_amp) {
3832 if (err < 0) 3852 err = cx_auto_add_volume(codec, label, " Boost", cidx,
3833 return err; 3853 nid, HDA_INPUT);
3854 if (err < 0)
3855 return err;
3856 }
3857
3858 if (!multi_adc_volume)
3859 continue;
3860 for (j = 0; j < conn_len; j++) {
3861 if (conn[j] == nid) {
3862 err = cx_auto_add_volume_idx(codec, label,
3863 " Capture", cidx, adc_nid, HDA_INPUT, j);
3864 if (err < 0)
3865 return err;
3866 break;
3867 }
3868 }
3834 } 3869 }
3835 return 0; 3870 return 0;
3836} 3871}