Commit 983345e5 authored by David Henningsson's avatar David Henningsson Committed by Takashi Iwai

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/719524Signed-off-by: default avatarDavid Henningsson <david.henningsson@canonical.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent b540afc2
......@@ -3729,9 +3729,9 @@ static int cx_auto_init(struct hda_codec *codec)
return 0;
}
static int cx_auto_add_volume(struct hda_codec *codec, const char *basename,
static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
const char *dir, int cidx,
hda_nid_t nid, int hda_dir)
hda_nid_t nid, int hda_dir, int amp_idx)
{
static char name[32];
static struct snd_kcontrol_new knew[] = {
......@@ -3743,7 +3743,8 @@ static int cx_auto_add_volume(struct hda_codec *codec, const char *basename,
for (i = 0; i < 2; i++) {
struct snd_kcontrol *kctl;
knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, hda_dir);
knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, amp_idx,
hda_dir);
knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
knew[i].index = cidx;
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,
return 0;
}
#define cx_auto_add_volume(codec, str, dir, cidx, nid, hda_dir) \
cx_auto_add_volume_idx(codec, str, dir, cidx, nid, hda_dir, 0)
#define cx_auto_add_pb_volume(codec, nid, str, idx) \
cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
......@@ -3808,29 +3812,60 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
struct conexant_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
static const char *prev_label;
int i, err, cidx;
int i, err, cidx, conn_len;
hda_nid_t conn[HDA_MAX_CONNECTIONS];
int multi_adc_volume = 0; /* If the ADC nid has several input volumes */
int adc_nid = spec->adc_nids[0];
conn_len = snd_hda_get_connections(codec, adc_nid, conn,
HDA_MAX_CONNECTIONS);
if (conn_len < 0)
return conn_len;
multi_adc_volume = cfg->num_inputs > 1 && conn_len > 1;
if (!multi_adc_volume) {
err = cx_auto_add_volume(codec, "Capture", "", 0, adc_nid,
HDA_INPUT);
if (err < 0)
return err;
}
err = cx_auto_add_volume(codec, "Capture", "", 0, spec->adc_nids[0],
HDA_INPUT);
if (err < 0)
return err;
prev_label = NULL;
cidx = 0;
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
const char *label;
if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP))
int j;
int pin_amp = get_wcaps(codec, nid) & AC_WCAP_IN_AMP;
if (!pin_amp && !multi_adc_volume)
continue;
label = hda_get_autocfg_input_label(codec, cfg, i);
if (label == prev_label)
cidx++;
else
cidx = 0;
prev_label = label;
err = cx_auto_add_volume(codec, label, " Capture", cidx,
nid, HDA_INPUT);
if (err < 0)
return err;
if (pin_amp) {
err = cx_auto_add_volume(codec, label, " Boost", cidx,
nid, HDA_INPUT);
if (err < 0)
return err;
}
if (!multi_adc_volume)
continue;
for (j = 0; j < conn_len; j++) {
if (conn[j] == nid) {
err = cx_auto_add_volume_idx(codec, label,
" Capture", cidx, adc_nid, HDA_INPUT, j);
if (err < 0)
return err;
break;
}
}
}
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment