Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 353034
b: refs/heads/master
c: 9bf387b
h: refs/heads/master
v: v3
  • Loading branch information
Takashi Iwai committed Jan 12, 2013
1 parent d947f7c commit d1cfa2e
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bc54976721d30f5ec51e90dcd1aca56494e0b0cf
refs/heads/master: 9bf387b6121bc446f275b0de8196d4dea8a3c876
149 changes: 131 additions & 18 deletions trunk/sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ struct alc_spec {
unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */
unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */
unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */

unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */

Expand Down Expand Up @@ -2474,6 +2475,10 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
spec->num_adc_nids = 1; /* reduce to a single ADC */
}

/* single index for individual volumes ctls */
if (!spec->dyn_adc_switch && spec->multi_cap_vol)
spec->num_adc_nids = 1;

return 0;
}

Expand Down Expand Up @@ -2545,26 +2550,138 @@ static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
return 0;
}

static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
int idx, bool is_switch, unsigned int ctl)
{
struct alc_spec *spec = codec->spec;
char tmpname[44];
int type = is_switch ? ALC_CTL_WIDGET_MUTE : ALC_CTL_WIDGET_VOL;
const char *sfx = is_switch ? "Switch" : "Volume";

if (!ctl)
return 0;

if (label)
snprintf(tmpname, sizeof(tmpname),
"%s Capture %s", label, sfx);
else
snprintf(tmpname, sizeof(tmpname),
"Capture %s", sfx);
return add_control(spec, type, tmpname, idx, ctl);
}

/* create single (and simple) capture volume and switch controls */
static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
unsigned int vol_ctl, unsigned int sw_ctl)
{
int err;
err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl);
if (err < 0)
return err;
err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl);
if (err < 0)
return err;
return 0;
}

/* create bound capture volume and switch controls */
static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
unsigned int vol_ctl, unsigned int sw_ctl)
{
struct alc_spec *spec = codec->spec;
struct snd_kcontrol_new *knew;

if (vol_ctl) {
knew = alc_kcontrol_new(spec, NULL, &cap_vol_temp);
if (!knew)
return -ENOMEM;
knew->index = idx;
knew->private_value = vol_ctl;
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
}
if (sw_ctl) {
knew = alc_kcontrol_new(spec, NULL, &cap_sw_temp);
if (!knew)
return -ENOMEM;
knew->index = idx;
knew->private_value = sw_ctl;
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
}
return 0;
}

/* return the vol ctl when used first in the imux list */
static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
{
struct alc_spec *spec = codec->spec;
struct nid_path *path;
unsigned int ctl;
int i;

path = get_nid_path(codec, spec->imux_pins[idx],
get_adc_nid(codec, 0, idx));
if (!path)
return 0;
ctl = path->ctls[type];
if (!ctl)
return 0;
for (i = 0; i < idx - 1; i++) {
path = get_nid_path(codec, spec->imux_pins[i],
get_adc_nid(codec, 0, i));
if (path && path->ctls[type] == ctl)
return 0;
}
return ctl;
}

/* create individual capture volume and switch controls per input */
static int create_multi_cap_vol_ctl(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->input_mux;
int i, err, type, type_idx = 0;
const char *prev_label = NULL;

for (i = 0; i < imux->num_items; i++) {
const char *label;
label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
if (prev_label && !strcmp(label, prev_label))
type_idx++;
else
type_idx = 0;
prev_label = label;

for (type = 0; type < 2; type++) {
err = add_single_cap_ctl(codec, label, type_idx, type,
get_first_cap_ctl(codec, i, type));
if (err < 0)
return err;
}
}
return 0;
}

static int create_capture_mixers(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct hda_input_mux *imux = &spec->input_mux;
struct snd_kcontrol_new *knew;
int i, n, nums;
int i, n, nums, err;

if (spec->dyn_adc_switch)
nums = 1;
else
nums = spec->num_adc_nids;

if (!spec->auto_mic && imux->num_items > 1) {
struct snd_kcontrol_new *knew;
knew = alc_kcontrol_new(spec, NULL, &cap_src_temp);
if (!knew)
return -ENOMEM;
knew->count = nums;
}

for (n = 0; n < nums; n++) {
bool multi = false;
int vol, sw;

vol = sw = 0;
Expand All @@ -2577,26 +2694,22 @@ static int create_capture_mixers(struct hda_codec *codec)
parse_capvol_in_path(codec, path);
if (!vol)
vol = path->ctls[NID_PATH_VOL_CTL];
else if (vol != path->ctls[NID_PATH_VOL_CTL])
multi = true;
if (!sw)
sw = path->ctls[NID_PATH_MUTE_CTL];
else if (sw != path->ctls[NID_PATH_MUTE_CTL])
multi = true;
}

if (vol) {
knew = alc_kcontrol_new(spec, NULL, &cap_vol_temp);
if (!knew)
return -ENOMEM;
knew->index = n;
knew->private_value = vol;
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
}
if (sw) {
knew = alc_kcontrol_new(spec, NULL, &cap_sw_temp);
if (!knew)
return -ENOMEM;
knew->index = n;
knew->private_value = sw;
knew->subdevice = HDA_SUBDEV_AMP_FLAG;
}
if (!multi)
err = create_single_cap_vol_ctl(codec, n, vol, sw);
else if (!spec->multi_cap_vol)
err = create_bind_cap_vol_ctl(codec, n, vol, sw);
else
err = create_multi_cap_vol_ctl(codec);
if (err < 0)
return err;
}

return 0;
Expand Down

0 comments on commit d1cfa2e

Please sign in to comment.