diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-16 05:33:02 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-16 05:33:02 -0400 |
commit | cf27f29ae2a4a0feed75262361f9f7dff20230b1 (patch) | |
tree | 3b50596fb0bbdb71011053810a3d34434adba199 /sound/pci/hda/patch_conexant.c | |
parent | 9b842cd86843db0f6ba4badb30282044afaed6c9 (diff) |
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>
Diffstat (limited to 'sound/pci/hda/patch_conexant.c')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6c9abee9ce82..28664e1c1ae5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -108,6 +108,7 @@ struct conexant_spec { | |||
108 | /* dynamic controls, init_verbs and input_mux */ | 108 | /* dynamic controls, init_verbs and input_mux */ |
109 | struct auto_pin_cfg autocfg; | 109 | struct auto_pin_cfg autocfg; |
110 | struct hda_input_mux private_imux; | 110 | struct hda_input_mux private_imux; |
111 | int imux_cfg_idx[HDA_MAX_NUM_INPUTS]; /* corresponding autocfg.input */ | ||
111 | hda_nid_t imux_adcs[HDA_MAX_NUM_INPUTS]; | 112 | hda_nid_t imux_adcs[HDA_MAX_NUM_INPUTS]; |
112 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; | 113 | hda_nid_t imux_pins[HDA_MAX_NUM_INPUTS]; |
113 | hda_nid_t private_adc_nids[HDA_MAX_NUM_INPUTS]; | 114 | 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, | |||
3464 | * if do_select is set, actually select the route. | 3465 | * if do_select is set, actually select the route. |
3465 | */ | 3466 | */ |
3466 | static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, | 3467 | static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, |
3467 | hda_nid_t pin, bool do_select, int depth) | 3468 | hda_nid_t pin, hda_nid_t *srcp, |
3469 | bool do_select, int depth) | ||
3468 | { | 3470 | { |
3469 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | 3471 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; |
3470 | int i, nums; | 3472 | int i, nums; |
3471 | 3473 | ||
3474 | switch (get_wcaps_type(get_wcaps(codec, mux))) { | ||
3475 | case AC_WID_AUD_IN: | ||
3476 | case AC_WID_AUD_SEL: | ||
3477 | case AC_WID_AUD_MIX: | ||
3478 | break; | ||
3479 | default: | ||
3480 | return -1; | ||
3481 | } | ||
3482 | |||
3472 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | 3483 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); |
3473 | for (i = 0; i < nums; i++) | 3484 | for (i = 0; i < nums; i++) |
3474 | if (conn[i] == pin) { | 3485 | if (conn[i] == pin) { |
3475 | if (do_select) | 3486 | if (do_select) |
3476 | snd_hda_codec_write(codec, mux, 0, | 3487 | snd_hda_codec_write(codec, mux, 0, |
3477 | AC_VERB_SET_CONNECT_SEL, i); | 3488 | AC_VERB_SET_CONNECT_SEL, i); |
3489 | if (srcp) | ||
3490 | *srcp = mux; | ||
3478 | return i; | 3491 | return i; |
3479 | } | 3492 | } |
3480 | depth++; | 3493 | depth++; |
3481 | if (depth == 2) | 3494 | if (depth == 2) |
3482 | return -1; | 3495 | return -1; |
3483 | for (i = 0; i < nums; i++) { | 3496 | for (i = 0; i < nums; i++) { |
3484 | int ret = __select_input_connection(codec, conn[i], pin, | 3497 | int ret = __select_input_connection(codec, conn[i], pin, srcp, |
3485 | do_select, depth); | 3498 | do_select, depth); |
3486 | if (ret >= 0) { | 3499 | if (ret >= 0) { |
3487 | if (do_select) | 3500 | if (do_select) |
3488 | snd_hda_codec_write(codec, mux, 0, | 3501 | snd_hda_codec_write(codec, mux, 0, |
3489 | AC_VERB_SET_CONNECT_SEL, i); | 3502 | AC_VERB_SET_CONNECT_SEL, i); |
3490 | return ret; | 3503 | return i; |
3491 | } | 3504 | } |
3492 | } | 3505 | } |
3493 | return -1; | 3506 | return -1; |
@@ -3496,13 +3509,13 @@ static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, | |||
3496 | static void select_input_connection(struct hda_codec *codec, hda_nid_t mux, | 3509 | static void select_input_connection(struct hda_codec *codec, hda_nid_t mux, |
3497 | hda_nid_t pin) | 3510 | hda_nid_t pin) |
3498 | { | 3511 | { |
3499 | __select_input_connection(codec, mux, pin, true, 0); | 3512 | __select_input_connection(codec, mux, pin, NULL, true, 0); |
3500 | } | 3513 | } |
3501 | 3514 | ||
3502 | static int get_input_connection(struct hda_codec *codec, hda_nid_t mux, | 3515 | static int get_input_connection(struct hda_codec *codec, hda_nid_t mux, |
3503 | hda_nid_t pin) | 3516 | hda_nid_t pin) |
3504 | { | 3517 | { |
3505 | return __select_input_connection(codec, mux, pin, false, 0); | 3518 | return __select_input_connection(codec, mux, pin, NULL, false, 0); |
3506 | } | 3519 | } |
3507 | 3520 | ||
3508 | static int cx_auto_mux_enum_update(struct hda_codec *codec, | 3521 | 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) | |||
3637 | if (idx >= 0) { | 3650 | if (idx >= 0) { |
3638 | const char *label; | 3651 | const char *label; |
3639 | label = hda_get_autocfg_input_label(codec, cfg, i); | 3652 | label = hda_get_autocfg_input_label(codec, cfg, i); |
3653 | spec->imux_cfg_idx[imux->num_items] = i; | ||
3640 | spec->imux_adcs[imux->num_items] = adc; | 3654 | spec->imux_adcs[imux->num_items] = adc; |
3641 | spec->imux_pins[imux->num_items] = | 3655 | spec->imux_pins[imux->num_items] = |
3642 | cfg->inputs[i].pin; | 3656 | cfg->inputs[i].pin; |
@@ -3978,35 +3992,64 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid, | |||
3978 | return 0; | 3992 | return 0; |
3979 | } | 3993 | } |
3980 | 3994 | ||
3995 | static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx, | ||
3996 | const char *label, int cidx) | ||
3997 | { | ||
3998 | struct conexant_spec *spec = codec->spec; | ||
3999 | hda_nid_t mux, nid; | ||
4000 | int con; | ||
4001 | |||
4002 | nid = spec->imux_pins[idx]; | ||
4003 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) | ||
4004 | return cx_auto_add_volume(codec, label, " Boost", cidx, | ||
4005 | nid, HDA_INPUT); | ||
4006 | con = __select_input_connection(codec, spec->imux_adcs[idx], nid, &mux, | ||
4007 | false, 0); | ||
4008 | if (con < 0) | ||
4009 | return 0; | ||
4010 | if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) | ||
4011 | return cx_auto_add_volume(codec, label, " Boost", 0, | ||
4012 | mux, HDA_OUTPUT); | ||
4013 | return 0; | ||
4014 | } | ||
4015 | |||
3981 | static int cx_auto_build_input_controls(struct hda_codec *codec) | 4016 | static int cx_auto_build_input_controls(struct hda_codec *codec) |
3982 | { | 4017 | { |
3983 | struct conexant_spec *spec = codec->spec; | 4018 | struct conexant_spec *spec = codec->spec; |
3984 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4019 | struct hda_input_mux *imux = &spec->private_imux; |
3985 | static const char *prev_label; | 4020 | const char *prev_label; |
4021 | int input_conn[HDA_MAX_NUM_INPUTS]; | ||
3986 | int i, err, cidx; | 4022 | int i, err, cidx; |
4023 | int multi_connection; | ||
4024 | |||
4025 | multi_connection = 0; | ||
4026 | for (i = 0; i < imux->num_items; i++) { | ||
4027 | cidx = get_input_connection(codec, spec->imux_adcs[i], | ||
4028 | spec->imux_pins[i]); | ||
4029 | input_conn[i] = (spec->imux_adcs[i] << 8) | cidx; | ||
4030 | if (i > 0 && input_conn[i] != input_conn[0]) | ||
4031 | multi_connection = 1; | ||
4032 | } | ||
3987 | 4033 | ||
3988 | prev_label = NULL; | 4034 | prev_label = NULL; |
3989 | cidx = 0; | 4035 | cidx = 0; |
3990 | for (i = 0; i < cfg->num_inputs; i++) { | 4036 | for (i = 0; i < imux->num_items; i++) { |
3991 | hda_nid_t nid = cfg->inputs[i].pin; | 4037 | hda_nid_t nid = spec->imux_pins[i]; |
3992 | const char *label; | 4038 | const char *label; |
3993 | int pin_amp = get_wcaps(codec, nid) & AC_WCAP_IN_AMP; | ||
3994 | 4039 | ||
3995 | label = hda_get_autocfg_input_label(codec, cfg, i); | 4040 | label = hda_get_autocfg_input_label(codec, &spec->autocfg, |
4041 | spec->imux_cfg_idx[i]); | ||
3996 | if (label == prev_label) | 4042 | if (label == prev_label) |
3997 | cidx++; | 4043 | cidx++; |
3998 | else | 4044 | else |
3999 | cidx = 0; | 4045 | cidx = 0; |
4000 | prev_label = label; | 4046 | prev_label = label; |
4001 | 4047 | ||
4002 | if (pin_amp) { | 4048 | err = cx_auto_add_boost_volume(codec, i, label, cidx); |
4003 | err = cx_auto_add_volume(codec, label, " Boost", cidx, | 4049 | if (err < 0) |
4004 | nid, HDA_INPUT); | 4050 | return err; |
4005 | if (err < 0) | ||
4006 | return err; | ||
4007 | } | ||
4008 | 4051 | ||
4009 | if (cfg->num_inputs == 1) { | 4052 | if (!multi_connection) { |
4010 | err = cx_auto_add_capture_volume(codec, nid, | 4053 | err = cx_auto_add_capture_volume(codec, nid, |
4011 | "Capture", "", cidx); | 4054 | "Capture", "", cidx); |
4012 | } else { | 4055 | } else { |