aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_conexant.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-16 05:33:02 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-16 05:33:02 -0400
commitcf27f29ae2a4a0feed75262361f9f7dff20230b1 (patch)
tree3b50596fb0bbdb71011053810a3d34434adba199 /sound/pci/hda/patch_conexant.c
parent9b842cd86843db0f6ba4badb30282044afaed6c9 (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.c79
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 */
3466static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, 3467static 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,
3496static void select_input_connection(struct hda_codec *codec, hda_nid_t mux, 3509static 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
3502static int get_input_connection(struct hda_codec *codec, hda_nid_t mux, 3515static 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
3508static int cx_auto_mux_enum_update(struct hda_codec *codec, 3521static 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
3995static 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
3981static int cx_auto_build_input_controls(struct hda_codec *codec) 4016static 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 {