aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorNickolas Lloyd <ultrageek.lloyd@gmail.com>2009-06-01 05:12:29 -0400
committerTakashi Iwai <tiwai@suse.de>2009-06-01 05:12:29 -0400
commit7c922de709b90badc19705e4f998e6d5b44c419b (patch)
tree6e848a5d02e72eefeff8831a48c889cd2e984467 /sound/pci
parenta3d6ab9723060e8d67e28a8d9142e6d08953d07b (diff)
ALSA: hda - Jack Mode changes for Sigmatel boards
This patch changes Line In as Out Switch and Mic In as Out Switch to enums for consistency, and causes all mic and line in ports to be probed and controls to be added appropriately. Signed-off-by: Nickolas Lloyd <ultrageek.lloyd@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_sigmatel.c219
1 files changed, 140 insertions, 79 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a915f404f654..48f4a36c4813 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -670,62 +670,6 @@ static unsigned int stac92xx_vref_get(struct hda_codec *codec, hda_nid_t nid)
670 return vref; 670 return vref;
671} 671}
672 672
673static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
674 struct snd_ctl_elem_value *ucontrol)
675{
676 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
677 unsigned int new_vref;
678 unsigned int error;
679
680 if (ucontrol->value.enumerated.item[0] == 0)
681 new_vref = AC_PINCTL_VREF_80;
682 else if (ucontrol->value.enumerated.item[0] == 1)
683 new_vref = AC_PINCTL_VREF_GRD;
684 else
685 new_vref = AC_PINCTL_VREF_HIZ;
686
687 if (new_vref != stac92xx_vref_get(codec, kcontrol->private_value)) {
688 error = stac92xx_vref_set(codec,
689 kcontrol->private_value, new_vref);
690 return error;
691 }
692
693 return 0;
694}
695
696static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
697 struct snd_ctl_elem_value *ucontrol)
698{
699 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
700 unsigned int vref = stac92xx_vref_get(codec, kcontrol->private_value);
701 if (vref == AC_PINCTL_VREF_80)
702 ucontrol->value.enumerated.item[0] = 0;
703 else if (vref == AC_PINCTL_VREF_GRD)
704 ucontrol->value.enumerated.item[0] = 1;
705 else if (vref == AC_PINCTL_VREF_HIZ)
706 ucontrol->value.enumerated.item[0] = 2;
707
708 return 0;
709}
710
711static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol,
712 struct snd_ctl_elem_info *uinfo)
713{
714 static char *texts[] = {
715 "Mic In", "Line In", "Line Out"
716 };
717
718 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
719 uinfo->value.enumerated.items = 3;
720 uinfo->count = 1;
721 if (uinfo->value.enumerated.item >= 3)
722 uinfo->value.enumerated.item = 2;
723 strcpy(uinfo->value.enumerated.name,
724 texts[uinfo->value.enumerated.item]);
725
726 return 0;
727}
728
729static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 673static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
730{ 674{
731 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 675 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -2652,7 +2596,8 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
2652 return 0; 2596 return 0;
2653} 2597}
2654 2598
2655static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) 2599static unsigned int stac92xx_get_default_vref(struct hda_codec *codec,
2600 hda_nid_t nid)
2656{ 2601{
2657 unsigned int pincap = snd_hda_query_pin_caps(codec, nid); 2602 unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2658 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; 2603 pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
@@ -2706,15 +2651,108 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
2706 return 1; 2651 return 1;
2707} 2652}
2708 2653
2709#define stac92xx_io_switch_info snd_ctl_boolean_mono_info 2654static int stac92xx_dc_bias_info(struct snd_kcontrol *kcontrol,
2655 struct snd_ctl_elem_info *uinfo)
2656{
2657 int i;
2658 static char *texts[] = {
2659 "Mic In", "Line In", "Line Out"
2660 };
2661
2662 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2663 struct sigmatel_spec *spec = codec->spec;
2664 hda_nid_t nid = kcontrol->private_value;
2665
2666 if (nid == spec->mic_switch || nid == spec->line_switch)
2667 i = 3;
2668 else
2669 i = 2;
2670
2671 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2672 uinfo->value.enumerated.items = i;
2673 uinfo->count = 1;
2674 if (uinfo->value.enumerated.item >= i)
2675 uinfo->value.enumerated.item = i-1;
2676 strcpy(uinfo->value.enumerated.name,
2677 texts[uinfo->value.enumerated.item]);
2678
2679 return 0;
2680}
2681
2682static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
2683 struct snd_ctl_elem_value *ucontrol)
2684{
2685 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2686 hda_nid_t nid = kcontrol->private_value;
2687 unsigned int vref = stac92xx_vref_get(codec, nid);
2688
2689 if (vref == stac92xx_get_default_vref(codec, nid))
2690 ucontrol->value.enumerated.item[0] = 0;
2691 else if (vref == AC_PINCTL_VREF_GRD)
2692 ucontrol->value.enumerated.item[0] = 1;
2693 else if (vref == AC_PINCTL_VREF_HIZ)
2694 ucontrol->value.enumerated.item[0] = 2;
2695
2696 return 0;
2697}
2698
2699static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
2700 struct snd_ctl_elem_value *ucontrol)
2701{
2702 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2703 unsigned int new_vref = 0;
2704 unsigned int error;
2705 hda_nid_t nid = kcontrol->private_value;
2706
2707 if (ucontrol->value.enumerated.item[0] == 0)
2708 new_vref = stac92xx_get_default_vref(codec, nid);
2709 else if (ucontrol->value.enumerated.item[0] == 1)
2710 new_vref = AC_PINCTL_VREF_GRD;
2711 else if (ucontrol->value.enumerated.item[0] == 2)
2712 new_vref = AC_PINCTL_VREF_HIZ;
2713 else
2714 return 0;
2715
2716 if (new_vref != stac92xx_vref_get(codec, nid)) {
2717 error = stac92xx_vref_set(codec, nid, new_vref);
2718 return error;
2719 }
2720
2721 return 0;
2722}
2723
2724static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol,
2725 struct snd_ctl_elem_info *uinfo)
2726{
2727 static char *texts[2];
2728 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2729 struct sigmatel_spec *spec = codec->spec;
2730
2731 if (kcontrol->private_value == spec->line_switch)
2732 texts[0] = "Line In";
2733 else
2734 texts[0] = "Mic In";
2735 texts[1] = "Line Out";
2736 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2737 uinfo->value.enumerated.items = 2;
2738 uinfo->count = 1;
2739
2740 if (uinfo->value.enumerated.item >= 2)
2741 uinfo->value.enumerated.item = 1;
2742 strcpy(uinfo->value.enumerated.name,
2743 texts[uinfo->value.enumerated.item]);
2744
2745 return 0;
2746}
2710 2747
2711static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 2748static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2712{ 2749{
2713 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2750 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2714 struct sigmatel_spec *spec = codec->spec; 2751 struct sigmatel_spec *spec = codec->spec;
2715 int io_idx = kcontrol-> private_value & 0xff; 2752 hda_nid_t nid = kcontrol->private_value;
2753 int io_idx = (nid == spec->mic_switch) ? 1 : 0;
2716 2754
2717 ucontrol->value.integer.value[0] = spec->io_switch[io_idx]; 2755 ucontrol->value.enumerated.item[0] = spec->io_switch[io_idx];
2718 return 0; 2756 return 0;
2719} 2757}
2720 2758
@@ -2722,9 +2760,9 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
2722{ 2760{
2723 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2761 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2724 struct sigmatel_spec *spec = codec->spec; 2762 struct sigmatel_spec *spec = codec->spec;
2725 hda_nid_t nid = kcontrol->private_value >> 8; 2763 hda_nid_t nid = kcontrol->private_value;
2726 int io_idx = kcontrol-> private_value & 0xff; 2764 int io_idx = (nid == spec->mic_switch) ? 1 : 0;
2727 unsigned short val = !!ucontrol->value.integer.value[0]; 2765 unsigned short val = !!ucontrol->value.enumerated.item[0];
2728 2766
2729 spec->io_switch[io_idx] = val; 2767 spec->io_switch[io_idx] = val;
2730 2768
@@ -2733,7 +2771,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
2733 else { 2771 else {
2734 unsigned int pinctl = AC_PINCTL_IN_EN; 2772 unsigned int pinctl = AC_PINCTL_IN_EN;
2735 if (io_idx) /* set VREF for mic */ 2773 if (io_idx) /* set VREF for mic */
2736 pinctl |= stac92xx_get_vref(codec, nid); 2774 pinctl |= stac92xx_get_default_vref(codec, nid);
2737 stac92xx_auto_set_pinctl(codec, nid, pinctl); 2775 stac92xx_auto_set_pinctl(codec, nid, pinctl);
2738 } 2776 }
2739 2777
@@ -2891,6 +2929,34 @@ static struct snd_kcontrol_new stac_input_src_temp = {
2891 .put = stac92xx_mux_enum_put, 2929 .put = stac92xx_mux_enum_put,
2892}; 2930};
2893 2931
2932static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
2933 hda_nid_t nid, int idx)
2934{
2935 int def_conf = snd_hda_codec_get_pincfg(codec, nid);
2936 int control = 0;
2937 struct sigmatel_spec *spec = codec->spec;
2938 char name[22];
2939
2940 if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) {
2941 if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
2942 && nid == spec->line_switch)
2943 control = STAC_CTL_WIDGET_IO_SWITCH;
2944 else if (snd_hda_query_pin_caps(codec, nid)
2945 & (AC_PINCAP_VREF_GRD << AC_PINCAP_VREF_SHIFT))
2946 control = STAC_CTL_WIDGET_DC_BIAS;
2947 else if (nid == spec->mic_switch)
2948 control = STAC_CTL_WIDGET_IO_SWITCH;
2949 }
2950
2951 if (control) {
2952 strcpy(name, auto_pin_cfg_labels[idx]);
2953 return stac92xx_add_control(codec->spec, control,
2954 strcat(name, " Jack Mode"), nid);
2955 }
2956
2957 return 0;
2958}
2959
2894static int stac92xx_add_input_source(struct sigmatel_spec *spec) 2960static int stac92xx_add_input_source(struct sigmatel_spec *spec)
2895{ 2961{
2896 struct snd_kcontrol_new *knew; 2962 struct snd_kcontrol_new *knew;
@@ -3253,7 +3319,9 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3253 const struct auto_pin_cfg *cfg) 3319 const struct auto_pin_cfg *cfg)
3254{ 3320{
3255 struct sigmatel_spec *spec = codec->spec; 3321 struct sigmatel_spec *spec = codec->spec;
3322 hda_nid_t nid;
3256 int err; 3323 int err;
3324 int idx;
3257 3325
3258 err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins, 3326 err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins,
3259 spec->multiout.dac_nids, 3327 spec->multiout.dac_nids,
@@ -3270,20 +3338,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3270 return err; 3338 return err;
3271 } 3339 }
3272 3340
3273 if (spec->line_switch) { 3341 for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) {
3274 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, 3342 nid = cfg->input_pins[idx];
3275 "Line In as Output Switch", 3343 if (nid) {
3276 spec->line_switch << 8); 3344 err = stac92xx_add_jack_mode_control(codec, nid, idx);
3277 if (err < 0) 3345 if (err < 0)
3278 return err; 3346 return err;
3279 } 3347 }
3280
3281 if (spec->mic_switch) {
3282 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_DC_BIAS,
3283 "Mic Jack Mode",
3284 spec->mic_switch);
3285 if (err < 0)
3286 return err;
3287 } 3348 }
3288 3349
3289 return 0; 3350 return 0;
@@ -4193,7 +4254,7 @@ static int stac92xx_init(struct hda_codec *codec)
4193 unsigned int pinctl, conf; 4254 unsigned int pinctl, conf;
4194 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { 4255 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
4195 /* for mic pins, force to initialize */ 4256 /* for mic pins, force to initialize */
4196 pinctl = stac92xx_get_vref(codec, nid); 4257 pinctl = stac92xx_get_default_vref(codec, nid);
4197 pinctl |= AC_PINCTL_IN_EN; 4258 pinctl |= AC_PINCTL_IN_EN;
4198 stac92xx_auto_set_pinctl(codec, nid, pinctl); 4259 stac92xx_auto_set_pinctl(codec, nid, pinctl);
4199 } else { 4260 } else {