Skip to contentSkip to conversation

hda: add SW_LINEOUT_INSERT support

PATCH In review Matthew Ranostay 3 participants 9 messages Oct 17, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 hda: add SW_LINEOUT_INSERT support

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.

---

include/linux/input.h +1 -0
index a5802c9..7323d2f 100644
@@ -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)
 
include/sound/jack.h +1 -0
index b1b2b8b..7cb25f4 100644
@@ -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 {
sound/core/jack.c +6 -0
index bd2d9e6..4978db1 100644
@@ -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);
sound/pci/hda/patch_sigmatel.c +54 -7

118 lines not on this page · raw message

#1 lore raw

At Thu, 16 Oct 2008 22:18:40 -0400,

Quoted 6 lines · Matthew Ranostay

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.

Thanks for the patch. Added Dmitry and Mark to Cc for review.

Adding one element should be fine, but I'm wondering whether more and more pin type would come up in future...

More comments below.

Quoted 17 lines
include/linux/input.h +1 -0
index a5802c9..7323d2f 100644
@@ -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)
 
include/sound/jack.h +0 -0
index b1b2b8b..7cb25f4 100644

include/sound/jack.h enum snd_jack_types { · line 39

Quoted 5 lines
include/sound/jack.h +1 -0
@@ -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,
 };

So, you don't need to judge different line-outs, such as front and rear?

Quoted 82 lines
include/sound/jack.h +0 -0
 struct snd_jack {
sound/core/jack.c +6 -0
index bd2d9e6..4978db1 100644
@@ -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);
sound/pci/hda/patch_sigmatel.c +20 -2
index d106ea5..1b3cba8 100644
@@ -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;

sound/pci/hda/patch_sigmatel.c static void stac92xx_free(struct hda_codec *codec) · line 3741

Quoted 9 lines
sound/pci/hda/patch_sigmatel.c +4 -2
@@ -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);

Good that you already caught the recent change ;)

Quoted 51 lines
sound/pci/hda/patch_sigmatel.c +25 -2
 	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);

sound/pci/hda/patch_sigmatel.c static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) · line 3926

Quoted 10 lines
sound/pci/hda/patch_sigmatel.c +5 -1
 		/* 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);

Is here also fallthru?
Then I'd suggest you to rewrite with a simple if, or separate somehow better. Too many fallthru in a switch is difficult to follow the code flow.

thanks,

Takashi

#2 lore raw
Quoted 9 lines · Takashi Iwai
Quoted 5 lines · Matthew Ranostay

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.

Thanks for the patch. Added Dmitry and Mark to Cc for review.

Matthew, as a general comment it would be helpful if you would split your patches up to separate out changes more and post as a series rather than as a single patch. Doing that makes review easier. For example, this patch includes both an addition to the jack reporting API and support for using it in a particular device.

Quoted 2 lines

Adding one element should be fine, but I'm wondering whether more and more pin type would come up in future...

That was a fear here - the conclusion was that we deal with that when it gets to be a problem.

Quoted 8 lines

include/sound/jack.h enum snd_jack_types { · line 39

Quoted 5 lines
include/sound/jack.h +1 -0
 	SND_JACK_HEADPHONE	= 0x0001,
 	SND_JACK_MICROPHONE	= 0x0002,
 	SND_JACK_HEADSET	= SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
+	SND_JACK_LINEOUT	= 0x0004,
 };

So, you don't need to judge different line-outs, such as front and rear?

For line outputs I think providing that information in the device name would be better - the reason for providing the distinction in the switch is to provide information when the function of the device attached to the jack changes at runtime. As far as the hardware is concerned one line output is much the same as another.

Quoted 3 lines

sound/pci/hda/patch_sigmatel.c static int stac92xx_init(struct hda_codec *codec) · line 3645

Quoted 3 lines
sound/pci/hda/patch_sigmatel.c +3 -0
+		err = snd_jack_new(codec->bus->card,
+			"Lineout Jack",
+			SND_JACK_LINEOUT, &spec->lineout_jack);

"Line Out" with two words.

#3 lore raw
Quoted 9 lines · Mark Brown
Quoted 7 lines · Takashi Iwai
Quoted 5 lines · Matthew Ranostay

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.

Quoted 7 lines
Quoted 1 line

Thanks for the patch. Added Dmitry and Mark to Cc for review.

Matthew, as a general comment it would be helpful if you would split your patches up to separate out changes more and post as a series rather than as a single patch. Doing that makes review easier. For example, this patch includes both an addition to the jack reporting API and support for using it in a particular device.

Duly noted.

Quoted 16 lines
Quoted 3 lines

Adding one element should be fine, but I'm wondering whether more and more pin type would come up in future...

That was a fear here - the conclusion was that we deal with that when it gets to be a problem.

Quoted 8 lines

include/sound/jack.h enum snd_jack_types { · line 39

Quoted 5 lines
include/sound/jack.h +1 -0
 	SND_JACK_HEADPHONE	= 0x0001,
 	SND_JACK_MICROPHONE	= 0x0002,
 	SND_JACK_HEADSET	= SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
+	SND_JACK_LINEOUT	= 0x0004,
 };

So, you don't need to judge different line-outs, such as front and rear?

No, at least not at the moment.

Quoted 6 lines

For line outputs I think providing that information in the device name would be better - the reason for providing the distinction in the switch is to provide information when the function of the device attached to the jack changes at runtime. As far as the hardware is concerned one line output is much the same as another.

	err = snd_jack_new(codec->bus->card,
		"Jack Detection",
		SND_JACK_HEADPHONE | SND_JACK_LINEOUT, &spec->jack);

Do you mean something like this? Of course this will require some changes in snd_jack_report.

Quoted 6 lines
Quoted 3 lines

sound/pci/hda/patch_sigmatel.c static int stac92xx_init(struct hda_codec *codec) · line 3645

Quoted 3 lines
sound/pci/hda/patch_sigmatel.c +3 -0
+		err = snd_jack_new(codec->bus->card,
+			"Lineout Jack",
+			SND_JACK_LINEOUT, &spec->lineout_jack);

"Line Out" with two words.

#4 lore raw
Quoted 8 lines · Matthew Ranostay
Quoted 5 lines · Mark Brown

For line outputs I think providing that information in the device name would be better - the reason for providing the distinction in the switch is to provide information when the function of the device attached to the jack changes at runtime. As far as the hardware is concerned one line output is much the same as another.

Quoted 5 lines
	err = snd_jack_new(codec->bus->card,
		"Jack Detection",
		SND_JACK_HEADPHONE | SND_JACK_LINEOUT, &spec->jack);

Do you mean something like this?

I'm not sure exactly what you mean by that change. What the code says is that you have a single jack and can detect at runtime if the device plugged into it is a line or headphone. If that is the case then yes, you should do something like that though that's not a very good name for the jack (ideally it should correspond to something like the label given to the jack on the machine case).

Quoted 2 lines

Of course this will require some changes
in snd_jack_report.

Could you explain what changes you think are required? The API already supports multi-function jacks.

#5 lore raw
Quoted 13 lines · Mark Brown
Quoted 11 lines · Matthew Ranostay
Quoted 5 lines · Mark Brown

For line outputs I think providing that information in the device name would be better - the reason for providing the distinction in the switch is to provide information when the function of the device attached to the jack changes at runtime. As far as the hardware is concerned one line output is much the same as another.

	err = snd_jack_new(codec->bus->card,
		"Jack Detection",
		SND_JACK_HEADPHONE | SND_JACK_LINEOUT, &spec->jack);
Quoted 9 lines
Quoted 1 line

Do you mean something like this?

I'm not sure exactly what you mean by that change. What the code says is that you have a single jack and can detect at runtime if the device plugged into it is a line or headphone. If that is the case then yes, you should do something like that though that's not a very good name for the jack (ideally it should correspond to something like the label given to the jack on the machine case).

Well is generally only one HP out jack, but there can be several line-out reported by the one instance(lineout_jack). I assume this isn't the correct usage.

Quoted 6 lines
Quoted 2 lines

Of course this will require some changes
in snd_jack_report.

Could you explain what changes you think are required? The API already supports multi-function jacks.

#6 lore raw
Quoted 2 lines · Matthew Ranostay

Well is generally only one HP out jack, but there can be several line-out reported by the one instance(lineout_jack). I assume this isn't the correct usage.

Could you provide a bit more detail here? Are you saying that the hardware has several line outputs and can report connection status but is unable to identify which of them is connected?

#7 lore raw
Quoted 9 lines · Mark Brown
Quoted 2 lines · Matthew Ranostay

Well is generally only one HP out jack, but there can be several line-out reported by the one instance(lineout_jack). I assume this isn't the correct usage.

Could you provide a bit more detail here? Are you saying that the hardware has several line outputs and can report connection status but is unable to identify which of them is connected?

Yep, just wondering if that is an incorrect way of using the jack abstraction layer. As of yet we are only using this to confirm if an HP and Line Out is connected for use in ALSA plugin, if there is the stream processing is turned off.

So basically if you plug into two or more line outs, each time you unplug a line out, it will still send a event as if a line out was connected until all line outs are removed.

-Matt

#8 lore raw
Quoted 1 line · Matthew Ranostay

Mark Brown wrote:

[Please fix your MUA to wrap at something less than 80 columns, currently your lines are ~90 characters long which makes your mails harder to read.]

Quoted 5 lines
Quoted 3 lines

Could you provide a bit more detail here? Are you saying that the hardware has several line outputs and can report connection status but is unable to identify which of them is connected?

Yep, just wondering if that is an incorrect way of using the jack abstraction layer.

It'd be easier to comment if you could provide more detail here. What is the hardware actually capable of doing? Without knowing what you're trying to represent it's hard to say for sure if your code matches up with that.

Quoted 2 lines

As of yet we are only using this to confirm if an HP and Line Out is connected for use in ALSA plugin, if there is the stream processing is turned off.

Right, that's one of the things I'd expected user space to be able to do with this.

Quoted 2 lines

So basically if you plug into two or more line outs, each time you unplug a line out, it will still send a event as if a line out was connected until all line outs are removed.

I *think* from this that you have multiple line output jacks and the hardware is able to do detection on each individually? In that case then yes, you are using the API incorrectly - you should be registering one jack per physical jack.