diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 219 |
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 | ||
673 | static 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 | |||
696 | static 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 | |||
711 | static 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 | |||
729 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 673 | static 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 | ||
2655 | static unsigned int stac92xx_get_vref(struct hda_codec *codec, hda_nid_t nid) | 2599 | static 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 | 2654 | static 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 | |||
2682 | static 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 | |||
2699 | static 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 | |||
2724 | static 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 | ||
2711 | static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 2748 | static 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 | ||
2932 | static 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 | |||
2894 | static int stac92xx_add_input_source(struct sigmatel_spec *spec) | 2960 | static 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 { |