aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
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 {