ALSA: hda - Build boost controls from selector widget in Cxt auto-parser
When the intermediate selector widget in the capture path provides the boost volume, create the corresponding volume control. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
9b842cd868
commit
cf27f29ae2
|
@ -108,6 +108,7 @@ struct conexant_spec {
|
||||||
/* dynamic controls, init_verbs and input_mux */
|
/* dynamic controls, init_verbs and input_mux */
|
||||||
struct auto_pin_cfg autocfg;
|
struct auto_pin_cfg autocfg;
|
||||||
struct hda_input_mux private_imux;
|
struct hda_input_mux private_imux;
|
||||||
|
int imux_cfg_idx[HDA_MAX_NUM_INPUTS]; /* corresponding autocfg.input */
|
||||||
hda_nid_t imux_adcs[HDA_MAX_NUM_INPUTS];
|
hda_nid_t imux_adcs[HDA_MAX_NUM_INPUTS];
|
||||||
hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
|
hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS];
|
||||||
hda_nid_t private_adc_nids[HDA_MAX_NUM_INPUTS];
|
hda_nid_t private_adc_nids[HDA_MAX_NUM_INPUTS];
|
||||||
|
@ -3464,30 +3465,42 @@ static int cx_auto_mux_enum_get(struct snd_kcontrol *kcontrol,
|
||||||
* if do_select is set, actually select the route.
|
* if do_select is set, actually select the route.
|
||||||
*/
|
*/
|
||||||
static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
||||||
hda_nid_t pin, bool do_select, int depth)
|
hda_nid_t pin, hda_nid_t *srcp,
|
||||||
|
bool do_select, int depth)
|
||||||
{
|
{
|
||||||
hda_nid_t conn[HDA_MAX_NUM_INPUTS];
|
hda_nid_t conn[HDA_MAX_NUM_INPUTS];
|
||||||
int i, nums;
|
int i, nums;
|
||||||
|
|
||||||
|
switch (get_wcaps_type(get_wcaps(codec, mux))) {
|
||||||
|
case AC_WID_AUD_IN:
|
||||||
|
case AC_WID_AUD_SEL:
|
||||||
|
case AC_WID_AUD_MIX:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
|
nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
|
||||||
for (i = 0; i < nums; i++)
|
for (i = 0; i < nums; i++)
|
||||||
if (conn[i] == pin) {
|
if (conn[i] == pin) {
|
||||||
if (do_select)
|
if (do_select)
|
||||||
snd_hda_codec_write(codec, mux, 0,
|
snd_hda_codec_write(codec, mux, 0,
|
||||||
AC_VERB_SET_CONNECT_SEL, i);
|
AC_VERB_SET_CONNECT_SEL, i);
|
||||||
|
if (srcp)
|
||||||
|
*srcp = mux;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
depth++;
|
depth++;
|
||||||
if (depth == 2)
|
if (depth == 2)
|
||||||
return -1;
|
return -1;
|
||||||
for (i = 0; i < nums; i++) {
|
for (i = 0; i < nums; i++) {
|
||||||
int ret = __select_input_connection(codec, conn[i], pin,
|
int ret = __select_input_connection(codec, conn[i], pin, srcp,
|
||||||
do_select, depth);
|
do_select, depth);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if (do_select)
|
if (do_select)
|
||||||
snd_hda_codec_write(codec, mux, 0,
|
snd_hda_codec_write(codec, mux, 0,
|
||||||
AC_VERB_SET_CONNECT_SEL, i);
|
AC_VERB_SET_CONNECT_SEL, i);
|
||||||
return ret;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -3496,13 +3509,13 @@ static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
||||||
static void select_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
static void select_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
||||||
hda_nid_t pin)
|
hda_nid_t pin)
|
||||||
{
|
{
|
||||||
__select_input_connection(codec, mux, pin, true, 0);
|
__select_input_connection(codec, mux, pin, NULL, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
static int get_input_connection(struct hda_codec *codec, hda_nid_t mux,
|
||||||
hda_nid_t pin)
|
hda_nid_t pin)
|
||||||
{
|
{
|
||||||
return __select_input_connection(codec, mux, pin, false, 0);
|
return __select_input_connection(codec, mux, pin, NULL, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cx_auto_mux_enum_update(struct hda_codec *codec,
|
static int cx_auto_mux_enum_update(struct hda_codec *codec,
|
||||||
|
@ -3637,6 +3650,7 @@ static void cx_auto_parse_input(struct hda_codec *codec)
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
const char *label;
|
const char *label;
|
||||||
label = hda_get_autocfg_input_label(codec, cfg, i);
|
label = hda_get_autocfg_input_label(codec, cfg, i);
|
||||||
|
spec->imux_cfg_idx[imux->num_items] = i;
|
||||||
spec->imux_adcs[imux->num_items] = adc;
|
spec->imux_adcs[imux->num_items] = adc;
|
||||||
spec->imux_pins[imux->num_items] =
|
spec->imux_pins[imux->num_items] =
|
||||||
cfg->inputs[i].pin;
|
cfg->inputs[i].pin;
|
||||||
|
@ -3978,35 +3992,64 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx,
|
||||||
|
const char *label, int cidx)
|
||||||
|
{
|
||||||
|
struct conexant_spec *spec = codec->spec;
|
||||||
|
hda_nid_t mux, nid;
|
||||||
|
int con;
|
||||||
|
|
||||||
|
nid = spec->imux_pins[idx];
|
||||||
|
if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)
|
||||||
|
return cx_auto_add_volume(codec, label, " Boost", cidx,
|
||||||
|
nid, HDA_INPUT);
|
||||||
|
con = __select_input_connection(codec, spec->imux_adcs[idx], nid, &mux,
|
||||||
|
false, 0);
|
||||||
|
if (con < 0)
|
||||||
|
return 0;
|
||||||
|
if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP)
|
||||||
|
return cx_auto_add_volume(codec, label, " Boost", 0,
|
||||||
|
mux, HDA_OUTPUT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int cx_auto_build_input_controls(struct hda_codec *codec)
|
static int cx_auto_build_input_controls(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct conexant_spec *spec = codec->spec;
|
struct conexant_spec *spec = codec->spec;
|
||||||
struct auto_pin_cfg *cfg = &spec->autocfg;
|
struct hda_input_mux *imux = &spec->private_imux;
|
||||||
static const char *prev_label;
|
const char *prev_label;
|
||||||
|
int input_conn[HDA_MAX_NUM_INPUTS];
|
||||||
int i, err, cidx;
|
int i, err, cidx;
|
||||||
|
int multi_connection;
|
||||||
|
|
||||||
|
multi_connection = 0;
|
||||||
|
for (i = 0; i < imux->num_items; i++) {
|
||||||
|
cidx = get_input_connection(codec, spec->imux_adcs[i],
|
||||||
|
spec->imux_pins[i]);
|
||||||
|
input_conn[i] = (spec->imux_adcs[i] << 8) | cidx;
|
||||||
|
if (i > 0 && input_conn[i] != input_conn[0])
|
||||||
|
multi_connection = 1;
|
||||||
|
}
|
||||||
|
|
||||||
prev_label = NULL;
|
prev_label = NULL;
|
||||||
cidx = 0;
|
cidx = 0;
|
||||||
for (i = 0; i < cfg->num_inputs; i++) {
|
for (i = 0; i < imux->num_items; i++) {
|
||||||
hda_nid_t nid = cfg->inputs[i].pin;
|
hda_nid_t nid = spec->imux_pins[i];
|
||||||
const char *label;
|
const char *label;
|
||||||
int pin_amp = get_wcaps(codec, nid) & AC_WCAP_IN_AMP;
|
|
||||||
|
|
||||||
label = hda_get_autocfg_input_label(codec, cfg, i);
|
label = hda_get_autocfg_input_label(codec, &spec->autocfg,
|
||||||
|
spec->imux_cfg_idx[i]);
|
||||||
if (label == prev_label)
|
if (label == prev_label)
|
||||||
cidx++;
|
cidx++;
|
||||||
else
|
else
|
||||||
cidx = 0;
|
cidx = 0;
|
||||||
prev_label = label;
|
prev_label = label;
|
||||||
|
|
||||||
if (pin_amp) {
|
err = cx_auto_add_boost_volume(codec, i, label, cidx);
|
||||||
err = cx_auto_add_volume(codec, label, " Boost", cidx,
|
if (err < 0)
|
||||||
nid, HDA_INPUT);
|
return err;
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cfg->num_inputs == 1) {
|
if (!multi_connection) {
|
||||||
err = cx_auto_add_capture_volume(codec, nid,
|
err = cx_auto_add_capture_volume(codec, nid,
|
||||||
"Capture", "", cidx);
|
"Capture", "", cidx);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue