aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-07-30 12:03:05 -0400
committerTakashi Iwai <tiwai@suse.de>2009-07-30 12:08:46 -0400
commitfefd67f31ee7f5259344e36a237d59b47e8715cf (patch)
tree40df7e13cd28e49bf097cc609d18c83e86903898 /sound/pci
parentbf677bd8fbd5dc06ead5511cf9fa76d090856c6a (diff)
ALSA: hda - Add line-out jack detection on IDT/STAC codecs
Add the automatic mute of speakers via line-out jack plugging on STAC/IDT codecs. The feature is enabled when the HP detect is present. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_sigmatel.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 9e192529e807..c7e5de6e394e 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -40,6 +40,7 @@ enum {
40 STAC_INSERT_EVENT, 40 STAC_INSERT_EVENT,
41 STAC_PWR_EVENT, 41 STAC_PWR_EVENT,
42 STAC_HP_EVENT, 42 STAC_HP_EVENT,
43 STAC_LO_EVENT,
43 STAC_MIC_EVENT, 44 STAC_MIC_EVENT,
44}; 45};
45 46
@@ -4345,6 +4346,14 @@ static int stac92xx_init(struct hda_codec *codec)
4345 hda_nid_t nid = cfg->hp_pins[i]; 4346 hda_nid_t nid = cfg->hp_pins[i];
4346 enable_pin_detect(codec, nid, STAC_HP_EVENT); 4347 enable_pin_detect(codec, nid, STAC_HP_EVENT);
4347 } 4348 }
4349 if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
4350 /* enable pin-detect for line-outs as well */
4351 for (i = 0; i < cfg->hp_outs; i++) {
4352 hda_nid_t nid = cfg->hp_pins[i];
4353 enable_pin_detect(codec, nid, STAC_LO_EVENT);
4354 }
4355 }
4356
4348 /* force to enable the first line-out; the others are set up 4357 /* force to enable the first line-out; the others are set up
4349 * in unsol_event 4358 * in unsol_event
4350 */ 4359 */
@@ -4543,6 +4552,48 @@ static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
4543 return 0; 4552 return 0;
4544} 4553}
4545 4554
4555static void stac92xx_line_out_detect(struct hda_codec *codec,
4556 int presence)
4557{
4558 struct sigmatel_spec *spec = codec->spec;
4559 struct auto_pin_cfg *cfg = &spec->autocfg;
4560 int i;
4561
4562 for (i = 0; i < cfg->line_outs; i++) {
4563 if (presence)
4564 break;
4565 presence = get_pin_presence(codec, cfg->line_out_pins[i]);
4566 if (presence) {
4567 unsigned int pinctl;
4568 pinctl = snd_hda_codec_read(codec,
4569 cfg->line_out_pins[i], 0,
4570 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4571 if (pinctl & AC_PINCTL_IN_EN)
4572 presence = 0; /* mic- or line-input */
4573 }
4574 }
4575
4576 if (presence) {
4577 /* disable speakers */
4578 for (i = 0; i < cfg->speaker_outs; i++)
4579 stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
4580 AC_PINCTL_OUT_EN);
4581 if (spec->eapd_mask && spec->eapd_switch)
4582 stac_gpio_set(codec, spec->gpio_mask,
4583 spec->gpio_dir, spec->gpio_data &
4584 ~spec->eapd_mask);
4585 } else {
4586 /* enable speakers */
4587 for (i = 0; i < cfg->speaker_outs; i++)
4588 stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
4589 AC_PINCTL_OUT_EN);
4590 if (spec->eapd_mask && spec->eapd_switch)
4591 stac_gpio_set(codec, spec->gpio_mask,
4592 spec->gpio_dir, spec->gpio_data |
4593 spec->eapd_mask);
4594 }
4595}
4596
4546/* return non-zero if the hp-pin of the given array index isn't 4597/* return non-zero if the hp-pin of the given array index isn't
4547 * a jack-detection target 4598 * a jack-detection target
4548 */ 4599 */
@@ -4595,13 +4646,6 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
4595 for (i = 0; i < cfg->line_outs; i++) 4646 for (i = 0; i < cfg->line_outs; i++)
4596 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], 4647 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
4597 AC_PINCTL_OUT_EN); 4648 AC_PINCTL_OUT_EN);
4598 for (i = 0; i < cfg->speaker_outs; i++)
4599 stac92xx_reset_pinctl(codec, cfg->speaker_pins[i],
4600 AC_PINCTL_OUT_EN);
4601 if (spec->eapd_mask && spec->eapd_switch)
4602 stac_gpio_set(codec, spec->gpio_mask,
4603 spec->gpio_dir, spec->gpio_data &
4604 ~spec->eapd_mask);
4605 } else { 4649 } else {
4606 /* enable lineouts */ 4650 /* enable lineouts */
4607 if (spec->hp_switch) 4651 if (spec->hp_switch)
@@ -4610,14 +4654,8 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
4610 for (i = 0; i < cfg->line_outs; i++) 4654 for (i = 0; i < cfg->line_outs; i++)
4611 stac92xx_set_pinctl(codec, cfg->line_out_pins[i], 4655 stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
4612 AC_PINCTL_OUT_EN); 4656 AC_PINCTL_OUT_EN);
4613 for (i = 0; i < cfg->speaker_outs; i++)
4614 stac92xx_set_pinctl(codec, cfg->speaker_pins[i],
4615 AC_PINCTL_OUT_EN);
4616 if (spec->eapd_mask && spec->eapd_switch)
4617 stac_gpio_set(codec, spec->gpio_mask,
4618 spec->gpio_dir, spec->gpio_data |
4619 spec->eapd_mask);
4620 } 4657 }
4658 stac92xx_line_out_detect(codec, presence);
4621 /* toggle hp outs */ 4659 /* toggle hp outs */
4622 for (i = 0; i < cfg->hp_outs; i++) { 4660 for (i = 0; i < cfg->hp_outs; i++) {
4623 unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; 4661 unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
@@ -4744,6 +4782,9 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
4744 case STAC_HP_EVENT: 4782 case STAC_HP_EVENT:
4745 stac92xx_hp_detect(codec); 4783 stac92xx_hp_detect(codec);
4746 break; 4784 break;
4785 case STAC_LO_EVENT:
4786 stac92xx_line_out_detect(codec, 0);
4787 break;
4747 case STAC_MIC_EVENT: 4788 case STAC_MIC_EVENT:
4748 stac92xx_mic_detect(codec); 4789 stac92xx_mic_detect(codec);
4749 break; 4790 break;
@@ -4751,6 +4792,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
4751 4792
4752 switch (event->type) { 4793 switch (event->type) {
4753 case STAC_HP_EVENT: 4794 case STAC_HP_EVENT:
4795 case STAC_LO_EVENT:
4754 case STAC_MIC_EVENT: 4796 case STAC_MIC_EVENT:
4755 case STAC_INSERT_EVENT: 4797 case STAC_INSERT_EVENT:
4756 case STAC_PWR_EVENT: 4798 case STAC_PWR_EVENT: