aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-11-12 04:06:31 -0500
committerTakashi Iwai <tiwai@suse.de>2008-11-12 04:06:31 -0500
commit24924f884cd36603615ea5496244e542b0b513c6 (patch)
tree8f41a3162d7ca9e2a6aaaaae1447a99db721373f /sound
parentf21f237cf55494c3a4209de323281a3b0528da10 (diff)
parentd7a8943635485597ae7c6d554a8ccf3ce5a42d2d (diff)
Merge branch 'topic/fix/hda' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_sigmatel.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index e6085915d86..4300a679cd8 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -212,7 +212,7 @@ struct sigmatel_spec {
212 /* i/o switches */ 212 /* i/o switches */
213 unsigned int io_switch[2]; 213 unsigned int io_switch[2];
214 unsigned int clfe_swap; 214 unsigned int clfe_swap;
215 unsigned int hp_switch; 215 unsigned int hp_switch; /* NID of HP as line-out */
216 unsigned int aloopback; 216 unsigned int aloopback;
217 217
218 struct hda_pcm pcm_rec[2]; /* PCM information */ 218 struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -2443,7 +2443,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
2443 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2443 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2444 struct sigmatel_spec *spec = codec->spec; 2444 struct sigmatel_spec *spec = codec->spec;
2445 2445
2446 ucontrol->value.integer.value[0] = spec->hp_switch; 2446 ucontrol->value.integer.value[0] = !!spec->hp_switch;
2447 return 0; 2447 return 0;
2448} 2448}
2449 2449
@@ -2452,8 +2452,9 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
2452{ 2452{
2453 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2453 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2454 struct sigmatel_spec *spec = codec->spec; 2454 struct sigmatel_spec *spec = codec->spec;
2455 2455 int nid = kcontrol->private_value;
2456 spec->hp_switch = ucontrol->value.integer.value[0]; 2456
2457 spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0;
2457 2458
2458 /* check to be sure that the ports are upto date with 2459 /* check to be sure that the ports are upto date with
2459 * switch changes 2460 * switch changes
@@ -2862,7 +2863,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
2862 if (cfg->hp_outs > 1) { 2863 if (cfg->hp_outs > 1) {
2863 err = stac92xx_add_control(spec, 2864 err = stac92xx_add_control(spec,
2864 STAC_CTL_WIDGET_HP_SWITCH, 2865 STAC_CTL_WIDGET_HP_SWITCH,
2865 "Headphone as Line Out Switch", 0); 2866 "Headphone as Line Out Switch",
2867 cfg->hp_pins[cfg->hp_outs - 1]);
2866 if (err < 0) 2868 if (err < 0)
2867 return err; 2869 return err;
2868 } 2870 }
@@ -3530,6 +3532,12 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
3530 if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) 3532 if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0)
3531 return err; 3533 return err;
3532 3534
3535 if (spec->num_muxes > 0) {
3536 err = stac92xx_auto_create_mux_input_ctls(codec);
3537 if (err < 0)
3538 return err;
3539 }
3540
3533 if (spec->autocfg.dig_out_pin) 3541 if (spec->autocfg.dig_out_pin)
3534 spec->multiout.dig_out_nid = 0x05; 3542 spec->multiout.dig_out_nid = 0x05;
3535 if (spec->autocfg.dig_in_pin) 3543 if (spec->autocfg.dig_in_pin)
@@ -3647,14 +3655,18 @@ static int stac92xx_init(struct hda_codec *codec)
3647 for (i = 0; i < AUTO_PIN_LAST; i++) { 3655 for (i = 0; i < AUTO_PIN_LAST; i++) {
3648 hda_nid_t nid = cfg->input_pins[i]; 3656 hda_nid_t nid = cfg->input_pins[i];
3649 if (nid) { 3657 if (nid) {
3650 unsigned int pinctl = snd_hda_codec_read(codec, nid, 3658 unsigned int pinctl;
3651 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 3659 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
3652 /* if PINCTL already set then skip */ 3660 /* for mic pins, force to initialize */
3653 if (pinctl & AC_PINCAP_IN) 3661 pinctl = stac92xx_get_vref(codec, nid);
3654 continue; 3662 } else {
3655 pinctl = AC_PINCTL_IN_EN; 3663 pinctl = snd_hda_codec_read(codec, nid, 0,
3656 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) 3664 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3657 pinctl |= stac92xx_get_vref(codec, nid); 3665 /* if PINCTL already set then skip */
3666 if (pinctl & AC_PINCTL_IN_EN)
3667 continue;
3668 }
3669 pinctl |= AC_PINCTL_IN_EN;
3658 stac92xx_auto_set_pinctl(codec, nid, pinctl); 3670 stac92xx_auto_set_pinctl(codec, nid, pinctl);
3659 } 3671 }
3660 } 3672 }
@@ -3776,11 +3788,30 @@ static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
3776 return 0; 3788 return 0;
3777} 3789}
3778 3790
3791/* return non-zero if the hp-pin of the given array index isn't
3792 * a jack-detection target
3793 */
3794static int no_hp_sensing(struct sigmatel_spec *spec, int i)
3795{
3796 struct auto_pin_cfg *cfg = &spec->autocfg;
3797
3798 /* ignore sensing of shared line and mic jacks */
3799 if (spec->line_switch &&
3800 cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE])
3801 return 1;
3802 if (spec->mic_switch &&
3803 cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC])
3804 return 1;
3805 /* ignore if the pin is set as line-out */
3806 if (cfg->hp_pins[i] == spec->hp_switch)
3807 return 1;
3808 return 0;
3809}
3810
3779static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) 3811static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3780{ 3812{
3781 struct sigmatel_spec *spec = codec->spec; 3813 struct sigmatel_spec *spec = codec->spec;
3782 struct auto_pin_cfg *cfg = &spec->autocfg; 3814 struct auto_pin_cfg *cfg = &spec->autocfg;
3783 int nid = cfg->hp_pins[cfg->hp_outs - 1];
3784 int i, presence; 3815 int i, presence;
3785 3816
3786 presence = 0; 3817 presence = 0;
@@ -3791,15 +3822,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3791 for (i = 0; i < cfg->hp_outs; i++) { 3822 for (i = 0; i < cfg->hp_outs; i++) {
3792 if (presence) 3823 if (presence)
3793 break; 3824 break;
3794 if (spec->hp_switch && cfg->hp_pins[i] == nid) 3825 if (no_hp_sensing(spec, i))
3795 break; 3826 continue;
3796 presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); 3827 presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
3797 } 3828 }
3798 3829
3799 if (presence) { 3830 if (presence) {
3800 /* disable lineouts, enable hp */ 3831 /* disable lineouts */
3801 if (spec->hp_switch) 3832 if (spec->hp_switch)
3802 stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN); 3833 stac92xx_reset_pinctl(codec, spec->hp_switch,
3834 AC_PINCTL_OUT_EN);
3803 for (i = 0; i < cfg->line_outs; i++) 3835 for (i = 0; i < cfg->line_outs; i++)
3804 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], 3836 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
3805 AC_PINCTL_OUT_EN); 3837 AC_PINCTL_OUT_EN);
@@ -3811,9 +3843,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3811 spec->gpio_dir, spec->gpio_data & 3843 spec->gpio_dir, spec->gpio_data &
3812 ~spec->eapd_mask); 3844 ~spec->eapd_mask);
3813 } else { 3845 } else {
3814 /* enable lineouts, disable hp */ 3846 /* enable lineouts */
3815 if (spec->hp_switch) 3847 if (spec->hp_switch)
3816 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); 3848 stac92xx_set_pinctl(codec, spec->hp_switch,
3849 AC_PINCTL_OUT_EN);
3817 for (i = 0; i < cfg->line_outs; i++) 3850 for (i = 0; i < cfg->line_outs; i++)
3818 stac92xx_set_pinctl(codec, cfg->line_out_pins[i], 3851 stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
3819 AC_PINCTL_OUT_EN); 3852 AC_PINCTL_OUT_EN);
@@ -3825,8 +3858,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3825 spec->gpio_dir, spec->gpio_data | 3858 spec->gpio_dir, spec->gpio_data |
3826 spec->eapd_mask); 3859 spec->eapd_mask);
3827 } 3860 }
3828 if (!spec->hp_switch && cfg->hp_outs > 1 && presence) 3861 /* toggle hp outs */
3829 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); 3862 for (i = 0; i < cfg->hp_outs; i++) {
3863 unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
3864 if (no_hp_sensing(spec, i))
3865 continue;
3866 if (presence)
3867 stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
3868 else
3869 stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val);
3870 }
3830} 3871}
3831 3872
3832static void stac92xx_pin_sense(struct hda_codec *codec, int idx) 3873static void stac92xx_pin_sense(struct hda_codec *codec, int idx)