Commit 6f7c83af authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Look for boost controls more deeply

In the current generic parser code, we look for the (mic) boost
controls only on input pins.  But many codecs assign the boost volume
to a widget connected to each input pin instead of the input amp of
the pin itself.

In this patch, the parser tries to look through more widgets connected
to the pin and find a boost amp.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 8999bf0a
...@@ -3056,40 +3056,93 @@ static int create_capture_mixers(struct hda_codec *codec) ...@@ -3056,40 +3056,93 @@ static int create_capture_mixers(struct hda_codec *codec)
/* /*
* add mic boosts if needed * add mic boosts if needed
*/ */
/* check whether the given amp is feasible as a boost volume */
static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx)
{
unsigned int step;
if (!nid_has_volume(codec, nid, dir) ||
is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
return false;
step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
>> AC_AMPCAP_STEP_SIZE_SHIFT;
if (step < 0x20)
return false;
return true;
}
/* look for a boost amp in a widget close to the pin */
static unsigned int look_for_boost_amp(struct hda_codec *codec,
struct nid_path *path)
{
unsigned int val = 0;
hda_nid_t nid;
int depth;
for (depth = 0; depth < 3; depth++) {
if (depth >= path->depth - 1)
break;
nid = path->path[depth];
if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
break;
} else if (check_boost_vol(codec, nid, HDA_INPUT,
path->idx[depth])) {
val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
HDA_INPUT);
break;
}
}
return val;
}
static int parse_mic_boost(struct hda_codec *codec) static int parse_mic_boost(struct hda_codec *codec)
{ {
struct hda_gen_spec *spec = codec->spec; struct hda_gen_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg; struct auto_pin_cfg *cfg = &spec->autocfg;
struct hda_input_mux *imux = &spec->input_mux;
int i, err; int i, err;
hda_nid_t nid;
for (i = 0; i < cfg->num_inputs; i++) { if (!spec->num_adc_nids)
if (cfg->inputs[i].type > AUTO_PIN_MIC) return 0;
break;
nid = cfg->inputs[i].pin; for (i = 0; i < imux->num_items; i++) {
if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
char boost_label[44];
struct nid_path *path; struct nid_path *path;
unsigned int val; unsigned int val;
int idx;
char boost_label[44];
if (!nid_has_volume(codec, nid, HDA_INPUT)) idx = imux->items[i].index;
if (idx >= imux->num_items)
continue; continue;
/* check only line-in and mic pins */
if (cfg->inputs[idx].type > AUTO_PIN_MIC)
continue;
path = get_input_path(codec, 0, i);
if (!path)
continue;
val = look_for_boost_amp(codec, path);
if (!val)
continue;
/* create a boost control */
snprintf(boost_label, sizeof(boost_label), snprintf(boost_label, sizeof(boost_label),
"%s Boost Volume", "%s Boost Volume", spec->input_labels[idx]);
spec->input_labels[i]); err = add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT); spec->input_label_idxs[idx], val);
err = add_control(spec, HDA_CTL_WIDGET_VOL,
boost_label,
spec->input_label_idxs[i], val);
if (err < 0) if (err < 0)
return err; return err;
path = snd_hda_get_nid_path(codec, nid, 0);
if (path)
path->ctls[NID_PATH_BOOST_CTL] = val; path->ctls[NID_PATH_BOOST_CTL] = val;
} }
}
return 0; 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