aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorNickolas Lloyd <ultrageek.lloyd@gmail.com>2009-05-15 09:33:30 -0400
committerTakashi Iwai <tiwai@suse.de>2009-05-15 09:34:10 -0400
commit2fc998907947f92b1b9113faad531d7f5a857987 (patch)
tree53a008070b21204e8f4bab7bd1c273cebc6e6290 /sound/pci/hda/patch_sigmatel.c
parent7442f9dadb8626bd9e7e01445560499560b99f5d (diff)
ALSA: hda - add controls to toggle DC bias on mic ports
This patch adds a mixer control for the STAC92XX boards to control the DC bias of mic ports, allowing recording from both powered and non-powered sources. It replaces the "Mic Output Switch" with "Mic Jack Mode" to switch between Mic, Line In, and Line Out. Signed-off-by: Nickolas Lloyd <ultrageek.lloyd@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c111
1 files changed, 107 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ecf53f755a09..02950980778e 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -634,6 +634,96 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
634 return 0; 634 return 0;
635} 635}
636 636
637static unsigned int stac92xx_vref_set(struct hda_codec *codec,
638 hda_nid_t nid, unsigned int new_vref)
639{
640 unsigned int error;
641 unsigned int pincfg;
642 pincfg = snd_hda_codec_read(codec, nid, 0,
643 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
644
645 pincfg &= 0xff;
646 pincfg &= ~(AC_PINCTL_VREFEN | AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
647 pincfg |= new_vref;
648
649 if (new_vref == AC_PINCTL_VREF_HIZ)
650 pincfg |= AC_PINCTL_OUT_EN;
651 else
652 pincfg |= AC_PINCTL_IN_EN;
653
654 error = snd_hda_codec_write_cache(codec, nid, 0,
655 AC_VERB_SET_PIN_WIDGET_CONTROL, pincfg);
656 if (error < 0)
657 return error;
658 else
659 return 1;
660}
661
662static unsigned int stac92xx_vref_get(struct hda_codec *codec, hda_nid_t nid)
663{
664 unsigned int vref;
665 vref = snd_hda_codec_read(codec, nid, 0,
666 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
667 vref &= AC_PINCTL_VREFEN;
668 return vref;
669}
670
671static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
672 struct snd_ctl_elem_value *ucontrol)
673{
674 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
675 unsigned int new_vref;
676 unsigned int error;
677
678 if (ucontrol->value.enumerated.item[0] == 0)
679 new_vref = AC_PINCTL_VREF_80;
680 else if (ucontrol->value.enumerated.item[0] == 1)
681 new_vref = AC_PINCTL_VREF_GRD;
682 else
683 new_vref = AC_PINCTL_VREF_HIZ;
684
685 if (new_vref != stac92xx_vref_get(codec, kcontrol->private_value)) {
686 error = stac92xx_vref_set(codec,
687 kcontrol->private_value, new_vref);
688 return error;
689 }
690
691 return 0;
692}
693
694static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
695 struct snd_ctl_elem_value *ucontrol)
696{
697 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
698 unsigned int vref = stac92xx_vref_get(codec, kcontrol->private_value);
699 if (vref == AC_PINCTL_VREF_80)
700 ucontrol->value.enumerated.item[0] = 0;
701 else if (vref == AC_PINCTL_VREF_GRD)
702 ucontrol->value.enumerated.item[0] = 1;
703 else if (vref == AC_PINCTL_VREF_HIZ)
704 ucontrol->value.enumerated.item[0] = 2;
705
706 return 0;
707}
708
709static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol,
710 struct snd_ctl_elem_info *uinfo)
711{
712 static char *texts[] = {
713 "Mic In", "Line In", "Line Out"
714 };
715
716 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
717 uinfo->value.enumerated.items = 3;
718 uinfo->count = 1;
719 if (uinfo->value.enumerated.item >= 3)
720 uinfo->value.enumerated.item = 2;
721 strcpy(uinfo->value.enumerated.name,
722 texts[uinfo->value.enumerated.item]);
723
724 return 0;
725}
726
637static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 727static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
638{ 728{
639 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 729 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -995,6 +1085,17 @@ static struct hda_verb stac9205_core_init[] = {
995 .private_value = verb_read | (verb_write << 16), \ 1085 .private_value = verb_read | (verb_write << 16), \
996 } 1086 }
997 1087
1088#define DC_BIAS(xname, idx, nid) \
1089 { \
1090 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1091 .name = xname, \
1092 .index = idx, \
1093 .info = stac92xx_dc_bias_info, \
1094 .get = stac92xx_dc_bias_get, \
1095 .put = stac92xx_dc_bias_put, \
1096 .private_value = nid, \
1097 }
1098
998static struct snd_kcontrol_new stac9200_mixer[] = { 1099static struct snd_kcontrol_new stac9200_mixer[] = {
999 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), 1100 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
1000 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), 1101 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
@@ -2702,7 +2803,8 @@ enum {
2702 STAC_CTL_WIDGET_AMP_VOL, 2803 STAC_CTL_WIDGET_AMP_VOL,
2703 STAC_CTL_WIDGET_HP_SWITCH, 2804 STAC_CTL_WIDGET_HP_SWITCH,
2704 STAC_CTL_WIDGET_IO_SWITCH, 2805 STAC_CTL_WIDGET_IO_SWITCH,
2705 STAC_CTL_WIDGET_CLFE_SWITCH 2806 STAC_CTL_WIDGET_CLFE_SWITCH,
2807 STAC_CTL_WIDGET_DC_BIAS
2706}; 2808};
2707 2809
2708static struct snd_kcontrol_new stac92xx_control_templates[] = { 2810static struct snd_kcontrol_new stac92xx_control_templates[] = {
@@ -2714,6 +2816,7 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
2714 STAC_CODEC_HP_SWITCH(NULL), 2816 STAC_CODEC_HP_SWITCH(NULL),
2715 STAC_CODEC_IO_SWITCH(NULL, 0), 2817 STAC_CODEC_IO_SWITCH(NULL, 0),
2716 STAC_CODEC_CLFE_SWITCH(NULL, 0), 2818 STAC_CODEC_CLFE_SWITCH(NULL, 0),
2819 DC_BIAS(NULL, 0, 0),
2717}; 2820};
2718 2821
2719/* add dynamic controls */ 2822/* add dynamic controls */
@@ -3165,9 +3268,9 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3165 } 3268 }
3166 3269
3167 if (spec->mic_switch) { 3270 if (spec->mic_switch) {
3168 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, 3271 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_DC_BIAS,
3169 "Mic as Output Switch", 3272 "Mic Jack Mode",
3170 (spec->mic_switch << 8) | 1); 3273 spec->mic_switch);
3171 if (err < 0) 3274 if (err < 0)
3172 return err; 3275 return err;
3173 } 3276 }