diff options
author | Matthew Ranostay <mranostay@embeddedalley.com> | 2008-01-22 06:32:30 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:30:09 -0500 |
commit | b22b48214ff492379dfc89b3ea6dc9fb4d157d2a (patch) | |
tree | dfe78f293b8a213c5cb195e91c15f5a9f1729b7e | |
parent | 02f21c9d6ba863aa86c33e1335cb1307322f7fb8 (diff) |
[ALSA] hda: Mono mux mixer support
Add support for the mono mux on several 92HD7xxx codecs.
Creates a dynamic mixer for the mux selection.
Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 24137bc975c4..e014ae38db0f 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -131,6 +131,8 @@ struct sigmatel_spec { | |||
131 | hda_nid_t *pwr_nids; | 131 | hda_nid_t *pwr_nids; |
132 | 132 | ||
133 | /* playback */ | 133 | /* playback */ |
134 | struct hda_input_mux *mono_mux; | ||
135 | unsigned int cur_mmux; | ||
134 | struct hda_multi_out multiout; | 136 | struct hda_multi_out multiout; |
135 | hda_nid_t dac_nids[5]; | 137 | hda_nid_t dac_nids[5]; |
136 | 138 | ||
@@ -144,6 +146,7 @@ struct sigmatel_spec { | |||
144 | hda_nid_t *dmux_nids; | 146 | hda_nid_t *dmux_nids; |
145 | unsigned int num_dmuxes; | 147 | unsigned int num_dmuxes; |
146 | hda_nid_t dig_in_nid; | 148 | hda_nid_t dig_in_nid; |
149 | hda_nid_t mono_nid; | ||
147 | 150 | ||
148 | /* pin widgets */ | 151 | /* pin widgets */ |
149 | hda_nid_t *pin_nids; | 152 | hda_nid_t *pin_nids; |
@@ -174,6 +177,7 @@ struct sigmatel_spec { | |||
174 | struct snd_kcontrol_new *kctl_alloc; | 177 | struct snd_kcontrol_new *kctl_alloc; |
175 | struct hda_input_mux private_dimux; | 178 | struct hda_input_mux private_dimux; |
176 | struct hda_input_mux private_imux; | 179 | struct hda_input_mux private_imux; |
180 | struct hda_input_mux private_mono_mux; | ||
177 | 181 | ||
178 | /* virtual master */ | 182 | /* virtual master */ |
179 | unsigned int vmaster_tlv[4]; | 183 | unsigned int vmaster_tlv[4]; |
@@ -401,6 +405,34 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
401 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | 405 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); |
402 | } | 406 | } |
403 | 407 | ||
408 | static int stac92xx_mono_mux_enum_info(struct snd_kcontrol *kcontrol, | ||
409 | struct snd_ctl_elem_info *uinfo) | ||
410 | { | ||
411 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
412 | struct sigmatel_spec *spec = codec->spec; | ||
413 | return snd_hda_input_mux_info(spec->mono_mux, uinfo); | ||
414 | } | ||
415 | |||
416 | static int stac92xx_mono_mux_enum_get(struct snd_kcontrol *kcontrol, | ||
417 | struct snd_ctl_elem_value *ucontrol) | ||
418 | { | ||
419 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
420 | struct sigmatel_spec *spec = codec->spec; | ||
421 | |||
422 | ucontrol->value.enumerated.item[0] = spec->cur_mmux; | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static int stac92xx_mono_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
427 | struct snd_ctl_elem_value *ucontrol) | ||
428 | { | ||
429 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
430 | struct sigmatel_spec *spec = codec->spec; | ||
431 | |||
432 | return snd_hda_input_mux_put(codec, spec->mono_mux, ucontrol, | ||
433 | spec->mono_nid, &spec->cur_mmux); | ||
434 | } | ||
435 | |||
404 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info | 436 | #define stac92xx_aloopback_info snd_ctl_boolean_mono_info |
405 | 437 | ||
406 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, | 438 | static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol, |
@@ -603,6 +635,16 @@ static struct hda_verb stac9205_core_init[] = { | |||
603 | {} | 635 | {} |
604 | }; | 636 | }; |
605 | 637 | ||
638 | #define STAC_MONO_MUX \ | ||
639 | { \ | ||
640 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
641 | .name = "Mono Mux", \ | ||
642 | .count = 1, \ | ||
643 | .info = stac92xx_mono_mux_enum_info, \ | ||
644 | .get = stac92xx_mono_mux_enum_get, \ | ||
645 | .put = stac92xx_mono_mux_enum_put, \ | ||
646 | } | ||
647 | |||
606 | #define STAC_INPUT_SOURCE(cnt) \ | 648 | #define STAC_INPUT_SOURCE(cnt) \ |
607 | { \ | 649 | { \ |
608 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 650 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
@@ -714,6 +756,7 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { | |||
714 | 756 | ||
715 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | 757 | static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { |
716 | STAC_INPUT_SOURCE(2), | 758 | STAC_INPUT_SOURCE(2), |
759 | STAC_MONO_MUX, | ||
717 | 760 | ||
718 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 761 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
719 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 762 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
@@ -733,6 +776,7 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { | |||
733 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { | 776 | static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { |
734 | STAC_INPUT_SOURCE(2), | 777 | STAC_INPUT_SOURCE(2), |
735 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), | 778 | STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2), |
779 | STAC_MONO_MUX, | ||
736 | 780 | ||
737 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 781 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
738 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), | 782 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), |
@@ -1180,7 +1224,7 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1180 | 1224 | ||
1181 | static unsigned int ref92hd71bxx_pin_configs[10] = { | 1225 | static unsigned int ref92hd71bxx_pin_configs[10] = { |
1182 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, | 1226 | 0x02214030, 0x02a19040, 0x01a19020, 0x01014010, |
1183 | 0x0181302e, 0x01114010, 0x01a19020, 0x90a000f0, | 1227 | 0x0181302e, 0x01114010, 0x01019020, 0x90a000f0, |
1184 | 0x90a000f0, 0x01452050, | 1228 | 0x90a000f0, 0x01452050, |
1185 | }; | 1229 | }; |
1186 | 1230 | ||
@@ -2318,6 +2362,35 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
2318 | return 0; | 2362 | return 0; |
2319 | } | 2363 | } |
2320 | 2364 | ||
2365 | /* labels for mono mux outputs */ | ||
2366 | static const char *stac92xx_mono_labels[3] = { | ||
2367 | "DAC0", "DAC1", "Mixer" | ||
2368 | }; | ||
2369 | |||
2370 | /* create mono mux for mono out on capable codecs */ | ||
2371 | static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | ||
2372 | { | ||
2373 | struct sigmatel_spec *spec = codec->spec; | ||
2374 | struct hda_input_mux *mono_mux = &spec->private_mono_mux; | ||
2375 | int i, num_cons; | ||
2376 | hda_nid_t con_lst[ARRAY_SIZE(stac92xx_mono_labels)]; | ||
2377 | |||
2378 | num_cons = snd_hda_get_connections(codec, | ||
2379 | spec->mono_nid, | ||
2380 | con_lst, | ||
2381 | HDA_MAX_NUM_INPUTS); | ||
2382 | if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | ||
2383 | return -EINVAL; | ||
2384 | |||
2385 | for (i = 0; i < num_cons; i++) { | ||
2386 | mono_mux->items[mono_mux->num_items].label = | ||
2387 | stac92xx_mono_labels[i]; | ||
2388 | mono_mux->items[mono_mux->num_items].index = i; | ||
2389 | mono_mux->num_items++; | ||
2390 | } | ||
2391 | return 0; | ||
2392 | } | ||
2393 | |||
2321 | /* labels for dmic mux inputs */ | 2394 | /* labels for dmic mux inputs */ |
2322 | static const char *stac92xx_dmic_labels[5] = { | 2395 | static const char *stac92xx_dmic_labels[5] = { |
2323 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", | 2396 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", |
@@ -2532,6 +2605,12 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2532 | if (err < 0) | 2605 | if (err < 0) |
2533 | return err; | 2606 | return err; |
2534 | 2607 | ||
2608 | if (spec->mono_nid > 0) { | ||
2609 | err = stac92xx_auto_create_mono_output_ctls(codec); | ||
2610 | if (err < 0) | ||
2611 | return err; | ||
2612 | } | ||
2613 | |||
2535 | if (spec->num_dmics > 0) | 2614 | if (spec->num_dmics > 0) |
2536 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, | 2615 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, |
2537 | &spec->autocfg)) < 0) | 2616 | &spec->autocfg)) < 0) |
@@ -2552,6 +2631,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
2552 | spec->input_mux = &spec->private_imux; | 2631 | spec->input_mux = &spec->private_imux; |
2553 | if (!spec->dinput_mux) | 2632 | if (!spec->dinput_mux) |
2554 | spec->dinput_mux = &spec->private_dimux; | 2633 | spec->dinput_mux = &spec->private_dimux; |
2634 | spec->mono_mux = &spec->private_mono_mux; | ||
2555 | 2635 | ||
2556 | return 1; | 2636 | return 1; |
2557 | } | 2637 | } |
@@ -3237,6 +3317,7 @@ again: | |||
3237 | 3317 | ||
3238 | spec->gpio_mask = spec->gpio_data = 0x00000001; /* GPIO0 High = EAPD */ | 3318 | spec->gpio_mask = spec->gpio_data = 0x00000001; /* GPIO0 High = EAPD */ |
3239 | 3319 | ||
3320 | spec->mono_nid = 0x15; | ||
3240 | spec->mux_nids = stac92hd71bxx_mux_nids; | 3321 | spec->mux_nids = stac92hd71bxx_mux_nids; |
3241 | spec->adc_nids = stac92hd71bxx_adc_nids; | 3322 | spec->adc_nids = stac92hd71bxx_adc_nids; |
3242 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | 3323 | spec->dmic_nids = stac92hd71bxx_dmic_nids; |