All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Henningsson <david.henningsson@canonical.com>
To: Takashi Iwai <tiwai@suse.de>,
	ALSA Development Mailing List <alsa-devel@alsa-project.org>
Subject: [RFC PATCH] HDA: Generic input jack handling
Date: Fri, 07 Oct 2011 13:49:46 +0200	[thread overview]
Message-ID: <4E8EE75A.3050809@canonical.com> (raw)

So, this is what I had in mind for 3.2. Assuming positive feedback from 
Takashi I'll go ahead and make a real patch out of this, and to clean up 
the Realtek implementation, as well as probably add this method for more 
codecs.

Thoughts:

1) The unsol event tags vary wildly between different vendors. How about 
standardising that as well?

2) If alc_init_jacks would call the new method, that might regress 
model-based (non auto) parsers. Is that a big deal these days?

3) Todo for realtek parser is to clean up all other calls to 
snd_input_jack_report so that jacks are not reported twice.

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e9b039c..69390fd 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -5284,6 +5284,142 @@ int snd_hda_input_jack_add(struct hda_codec 
*codec, hda_nid_t nid, int type,
  }
  EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);

+/**
+ * snd_hda_input_auto_jack_add - Add relevant input jacks based on
+ * auto pin configuration.
+ * @param unsol_tags lists of jack types to enable, terminate with
+ * list entry with jack_type set to 0. If unsol_tag is set to 0,
+ * unsol events will not be enabled for that jack type.
+ * @return 0 or error code
+ */
+int snd_hda_input_auto_jack_add(struct hda_codec *codec,
+				const struct auto_pin_cfg *cfg,
+				const struct hda_unsol_jack_tag* unsol_tags)
+{
+	for (; unsol_tags->jack_type; unsol_tags++) {
+		hda_nid_t nid_list_storage[AUTO_CFG_MAX_INS];
+		const hda_nid_t *nid_list;
+		int nid_count = 0;
+		int i;
+		int input_match = AUTO_PIN_MIC;
+
+		switch (unsol_tags->jack_type) {
+		case SND_JACK_LINEIN:
+			input_match = AUTO_PIN_LINE_IN;
+			/* Fall through */
+		case SND_JACK_MICROPHONE:
+			for (i = 0; i < cfg->num_inputs; i++) {
+				if (cfg->inputs[i].type == input_match)
+					nid_list_storage[nid_count++] = cfg->inputs[i].pin;
+			}
+			nid_list = nid_list_storage;
+			break;
+		case SND_JACK_HEADPHONE:
+			if (cfg->line_out_type == AUTO_PIN_HP_OUT) {
+				nid_list = cfg->line_out_pins;
+				nid_count = cfg->line_outs;
+			} else {
+				nid_list = cfg->hp_pins;
+				nid_count = cfg->hp_outs;
+			}
+			break;
+		case SND_JACK_LINEOUT:
+			if (cfg->line_out_type == AUTO_PIN_LINE_OUT) {
+				nid_list = cfg->line_out_pins;
+				nid_count = cfg->line_outs;
+			}
+			break;			
+		}
+
+		for (i = 0; i < nid_count; i++) {
+			int pin = nid_list[i];
+			int err;
+			if (!is_jack_detectable(codec, pin))
+				continue;
+
+			if (unsol_tags->unsol_tag) {
+				err = snd_hda_codec_write(codec, pin, 0,
+					AC_VERB_SET_UNSOLICITED_ENABLE,
+					AC_USRSP_EN | unsol_tags->unsol_tag);
+				if (err)
+					return err;
+			}
+
+			err = snd_hda_input_jack_add(codec, pin,
+					unsol_tags->jack_type, NULL);
+			if (err)
+				return err;
+			snd_hda_input_jack_report(codec, pin);
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_input_auto_jack_add);
+
+void snd_hda_input_jack_report_type(struct hda_codec *codec, int jack_type)
+{
+	struct hda_jack_item *jacks = codec->jacks.list;
+	int i;
+
+	if (!jacks)
+		return;
+
+	for (i = 0; i < codec->jacks.used; i++, jacks++)
+		if (jacks->type == jack_type)
+			snd_hda_input_jack_report(codec, jacks->nid);
+}
+EXPORT_SYMBOL_HDA(snd_hda_input_jack_report_type);
+
+
  void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)
  {
  	struct hda_jack_item *jacks = codec->jacks.list;
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 46c581c..bb59a3f 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -678,11 +678,21 @@ void snd_print_channel_allocation(int spk_alloc, 
char *buf, int buflen);
  /*
   * Input-jack notification support
   */
+
+struct hda_unsol_jack_tag {
+	int jack_type; /* SND_JACK_xxx constant */
+	int unsol_tag; /* event tag */
+};
+
  #ifdef CONFIG_SND_HDA_INPUT_JACK
  int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int 
type,
  			   const char *name);
  void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid);
+void snd_hda_input_jack_report_type(struct hda_codec *codec, int 
jack_type);
  void snd_hda_input_jack_free(struct hda_codec *codec);
+int snd_hda_input_auto_jack_add(struct hda_codec *codec,
+				const struct auto_pin_cfg *cfg,
+				const struct hda_unsol_jack_tag *unsol_tags);
  #else /* CONFIG_SND_HDA_INPUT_JACK */
  static inline int snd_hda_input_jack_add(struct hda_codec *codec,
  					 hda_nid_t nid, int type,
@@ -694,9 +704,19 @@ static inline void snd_hda_input_jack_report(struct 
hda_codec *codec,
  					     hda_nid_t nid)
  {
  }
+static inline void snd_hda_input_jack_report_type(struct hda_codec *codec,
+						  int jack_type)
+{
+}
  static inline void snd_hda_input_jack_free(struct hda_codec *codec)
  {
  }
+static inline int snd_hda_input_auto_jack_add(struct hda_codec *codec,
+				const struct auto_pin_cfg *cfg,
+				const struct hda_unsol_jack_tag *unsol_tags)
+{
+	return 0;
+}
  #endif /* CONFIG_SND_HDA_INPUT_JACK */

  #endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index bf53663..90cdd6c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -38,6 +38,7 @@
  #define ALC_DCVOL_EVENT		0x02
  #define ALC_HP_EVENT		0x04
  #define ALC_MIC_EVENT		0x08
+#define ALC_LINEIN_EVENT	0x10

  /* for GPIO Poll */
  #define GPIO_MASK	0x03
@@ -441,11 +442,21 @@ static void alc_fix_pll_init(struct hda_codec 
*codec, hda_nid_t nid,
   * Jack-reporting via input-jack layer
   */

+static const struct hda_unsol_jack_tag unsol_tags[] = {
+	{.jack_type = SND_JACK_HEADPHONE, .unsol_tag = ALC_HP_EVENT },
+	{.jack_type = SND_JACK_LINEOUT, .unsol_tag = ALC_FRONT_EVENT },
+	{.jack_type = SND_JACK_MICROPHONE, .unsol_tag = ALC_MIC_EVENT },
+	{.jack_type = SND_JACK_LINEIN, .unsol_tag = ALC_LINEIN_EVENT },
+	{} /* Zero terminator */
+};
+
  /* initialization of jacks; currently checks only a few known pins */
  static int alc_init_jacks(struct hda_codec *codec)
  {
  #ifdef CONFIG_SND_HDA_INPUT_JACK
  	struct alc_spec *spec = codec->spec;
+	snd_hda_input_auto_jack_add(codec, &spec->autocfg, unsol_tags);
+/*	;
  	int err;
  	unsigned int hp_nid = spec->autocfg.hp_pins[0];
  	unsigned int mic_nid = spec->ext_mic_pin;
@@ -472,7 +483,7 @@ static int alc_init_jacks(struct hda_codec *codec)
  		if (err < 0)
  			return err;
  		snd_hda_input_jack_report(codec, dock_nid);
-	}
+	}*/
  #endif /* CONFIG_SND_HDA_INPUT_JACK */
  	return 0;
  }
@@ -645,12 +656,18 @@ static void alc_sku_unsol_event(struct hda_codec 
*codec, unsigned int res)
  	switch (res) {
  	case ALC_HP_EVENT:
  		alc_hp_automute(codec);
+		snd_hda_input_jack_report_type(codec, SND_JACK_HEADPHONE);
  		break;
  	case ALC_FRONT_EVENT:
  		alc_line_automute(codec);
+		snd_hda_input_jack_report_type(codec, SND_JACK_LINEOUT);
  		break;
  	case ALC_MIC_EVENT:
  		alc_mic_automute(codec);
+		snd_hda_input_jack_report_type(codec, SND_JACK_MICROPHONE);
+		break;
+	case ALC_LINEIN_EVENT:
+		snd_hda_input_jack_report_type(codec, SND_JACK_LINEIN);
  		break;
  	}
  }

-- 
David Henningsson, Canonical Ltd.
http://launchpad.net/~diwic

             reply	other threads:[~2011-10-07 11:49 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-07 11:49 David Henningsson [this message]
2011-10-07 11:52 ` [RFC PATCH] HDA: Generic input jack handling Mark Brown
2011-10-07 12:08 ` Takashi Iwai
2011-10-07 12:46   ` David Henningsson
2011-10-07 13:03     ` Takashi Iwai
2011-10-07 15:11       ` David Henningsson
2011-10-07 15:27         ` Takashi Iwai
2011-10-07 16:04           ` David Henningsson
2011-10-08  7:11             ` Takashi Iwai
2011-10-08  7:29               ` Raymond Yau
2011-10-09  8:38               ` David Henningsson
2011-10-09 10:32                 ` Takashi Iwai
2011-10-09 11:14                   ` David Henningsson
2011-10-13  6:40                     ` Takashi Iwai
2011-10-18 13:13                       ` David Henningsson
2011-10-18 13:23                         ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4E8EE75A.3050809@canonical.com \
    --to=david.henningsson@canonical.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.