[alsa-devel] [PATCH] hda: add SW_LINEOUT_INSERT support
Matthew Ranostay
mranostay at embeddedalley.com
Fri Oct 17 04:18:40 CEST 2008
Add support for detecting line out pin insertion and reporting
back to userspace with the jack abstraction layer. Line outs
are reported with the macro defined SW_LINEOUT_INSERT code.
Signed-off-by: Matthew Ranostay <mranostay at embeddedalley.com>
---
diff --git a/include/linux/input.h b/include/linux/input.h
index a5802c9..7323d2f 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -644,6 +644,7 @@ struct input_absinfo {
#define SW_RADIO SW_RFKILL_ALL /* deprecated */
#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */
#define SW_DOCK 0x05 /* set = plugged into dock */
+#define SW_LINEOUT_INSERT 0x06 /* set = inserted */
#define SW_MAX 0x0f
#define SW_CNT (SW_MAX+1)
diff --git a/include/sound/jack.h b/include/sound/jack.h
index b1b2b8b..7cb25f4 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -35,6 +35,7 @@ enum snd_jack_types {
SND_JACK_HEADPHONE = 0x0001,
SND_JACK_MICROPHONE = 0x0002,
SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
+ SND_JACK_LINEOUT = 0x0004,
};
struct snd_jack {
diff --git a/sound/core/jack.c b/sound/core/jack.c
index bd2d9e6..4978db1 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -102,6 +102,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
if (type & SND_JACK_HEADPHONE)
input_set_capability(jack->input_dev, EV_SW,
SW_HEADPHONE_INSERT);
+ if (type & SND_JACK_LINEOUT)
+ input_set_capability(jack->input_dev, EV_SW,
+ SW_LINEOUT_INSERT);
if (type & SND_JACK_MICROPHONE)
input_set_capability(jack->input_dev, EV_SW,
SW_MICROPHONE_INSERT);
@@ -153,6 +156,9 @@ void snd_jack_report(struct snd_jack *jack, int status)
if (jack->type & SND_JACK_HEADPHONE)
input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
status & SND_JACK_HEADPHONE);
+ if (jack->type & SND_JACK_LINEOUT)
+ input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
+ status & SND_JACK_LINEOUT);
if (jack->type & SND_JACK_MICROPHONE)
input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
status & SND_JACK_MICROPHONE);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index d106ea5..1b3cba8 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -36,6 +36,7 @@
#include "hda_patch.h"
#include "hda_beep.h"
+#define STAC_LINEOUT_EVENT 0x10
#define STAC_PWR_EVENT 0x20
#define STAC_HP_EVENT 0x30
#define STAC_VREF_EVENT 0x40
@@ -217,7 +218,8 @@ struct sigmatel_spec {
struct hda_pcm pcm_rec[2]; /* PCM information */
/* jack detection */
- struct snd_jack *jack;
+ struct snd_jack *hp_jack;
+ struct snd_jack *lineout_jack;
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
@@ -3635,9 +3637,15 @@ static int stac92xx_init(struct hda_codec *codec)
/* jack detection */
err = snd_jack_new(codec->bus->card,
"Headphone Jack",
- SND_JACK_HEADPHONE, &spec->jack);
+ SND_JACK_HEADPHONE, &spec->hp_jack);
if (err < 0)
return err;
+ err = snd_jack_new(codec->bus->card,
+ "Lineout Jack",
+ SND_JACK_LINEOUT, &spec->lineout_jack);
+ if (err < 0)
+ return err;
+
/* fake event to set up pins */
codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
} else {
@@ -3661,6 +3669,16 @@ static int stac92xx_init(struct hda_codec *codec)
for (i = 0; i < spec->num_dmics; i++)
stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
AC_PINCTL_IN_EN);
+ for (i = 0; i < cfg->line_outs; i++) {
+ int def_conf = snd_hda_codec_read(codec, cfg->line_out_pins[i],
+ 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = get_defcfg_connect(def_conf);
+
+ if (def_conf && def_conf != AC_JACK_PORT_FIXED)
+ continue;
+ enable_pin_detect(codec, cfg->line_out_pins[i],
+ STAC_LINEOUT_EVENT);
+ }
for (i = 0; i < spec->num_pwrs; i++) {
int event = is_nid_hp_pin(cfg, spec->pwr_nids[i])
? STAC_HP_EVENT : STAC_PWR_EVENT;
@@ -3717,8 +3735,10 @@ static void stac92xx_free(struct hda_codec *codec)
if (! spec)
return;
- if (spec->jack)
- snd_device_free(codec->bus->card, spec->jack);
+ if (spec->hp_jack)
+ snd_device_free(codec->bus->card, spec->hp_jack);
+ if (spec->lineout_jack)
+ snd_device_free(codec->bus->card, spec->lineout_jack);
if (spec->bios_pin_configs)
kfree(spec->bios_pin_configs);
@@ -3804,7 +3824,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
break;
presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
}
- snd_jack_report(spec->jack,
+ snd_jack_report(spec->hp_jack,
presence ? SND_JACK_HEADPHONE : 0);
if (presence) {
@@ -3840,6 +3860,28 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
}
+static void stac92xx_lineout_detect(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int presence, i;
+
+ for (i = 0; i < cfg->line_outs; i++) {
+ int def_conf = snd_hda_codec_read(codec,
+ cfg->line_out_pins[i], 0,
+ AC_VERB_GET_CONFIG_DEFAULT, 0);
+ def_conf = get_defcfg_connect(def_conf);
+
+ if (def_conf && def_conf != AC_JACK_PORT_FIXED)
+ continue;
+ presence = get_hp_pin_presence(codec,
+ cfg->line_out_pins[i]);
+ if (presence)
+ break;
+ }
+ snd_jack_report(spec->lineout_jack, presence ? SND_JACK_LINEOUT : 0);
+}
+
static void stac92xx_pin_sense(struct hda_codec *codec, int idx)
{
struct sigmatel_spec *spec = codec->spec;
@@ -3868,15 +3910,20 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
{
struct sigmatel_spec *spec = codec->spec;
int idx = res >> 26 & 0x0f;
+ int event = (res >> 26) & 0x70;
- switch ((res >> 26) & 0x70) {
+ switch (event) {
case STAC_HP_EVENT:
stac92xx_hp_detect(codec, res);
/* fallthru */
case STAC_PWR_EVENT:
if (spec->num_pwrs > 0)
stac92xx_pin_sense(codec, idx);
- break;
+ /* fallthru */
+ case STAC_LINEOUT_EVENT:
+ if (event == STAC_HP_EVENT)
+ break;
+ stac92xx_lineout_detect(codec);
case STAC_VREF_EVENT: {
int data = snd_hda_codec_read(codec, codec->afg, 0,
AC_VERB_GET_GPIO_DATA, 0);
More information about the Alsa-devel
mailing list