ALSA: hda - Manage unsol tags in hda_jack.c

Manage the tags assigned for unsolicited events dynamically together
with the jack-detection routines.  Basically this is almost same as what
we've done in patch_sigmatel.c.  Assign the new tag number for each new
unsol event, associate with the given NID and the action type, etc.

With this change, now all pins looked over in snd_hda_jack_add_kctls()
are actually enabled for detection now even if the pins aren't used for
jack-retasking by the driver.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index cee6a00..8829d5c 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -51,6 +51,24 @@
 EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
 
 /**
+ * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
+ */
+struct hda_jack_tbl *
+snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
+{
+	struct hda_jack_tbl *jack = codec->jacktbl.list;
+	int i;
+
+	if (!tag || !jack)
+		return NULL;
+	for (i = 0; i < codec->jacktbl.used; i++, jack++)
+		if (jack->tag == tag)
+			return jack;
+	return NULL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
+
+/**
  * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
  */
 struct hda_jack_tbl *
@@ -65,6 +83,7 @@
 		return NULL;
 	jack->nid = nid;
 	jack->jack_dirty = 1;
+	jack->tag = codec->jacktbl.used;
 	return jack;
 }
 
@@ -77,7 +96,7 @@
 static void jack_detect_update(struct hda_codec *codec,
 			       struct hda_jack_tbl *jack)
 {
-	if (jack->jack_dirty || !jack->jack_cachable) {
+	if (jack->jack_dirty || !jack->jack_detect) {
 		unsigned int val = read_pin_sense(codec, jack->nid);
 		jack->jack_dirty = 0;
 		if (val != jack->pin_sense) {
@@ -141,17 +160,19 @@
  * snd_hda_jack_detect_enable - enable the jack-detection
  */
 int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
-			       unsigned int tag)
+			       unsigned char action)
 {
 	struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
 	if (!jack)
 		return -ENOMEM;
-	if (jack->jack_cachable)
+	if (jack->jack_detect)
 		return 0; /* already registered */
-	jack->jack_cachable = 1;
+	jack->jack_detect = 1;
+	if (action)
+		jack->action = action;
 	return snd_hda_codec_write_cache(codec, nid, 0,
 					 AC_VERB_SET_UNSOLICITED_ENABLE,
-					 AC_USRSP_EN | tag);
+					 AC_USRSP_EN | jack->tag);
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
 
@@ -168,18 +189,6 @@
 }
 
 /**
- * snd_hda_jack_report - notify kctl when the jack state was changed
- */
-void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
-
-	if (jack)
-		jack_detect_report(codec, jack);
-}
-EXPORT_SYMBOL_HDA(snd_hda_jack_report);
-
-/**
  * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
  */
 void snd_hda_jack_report_sync(struct hda_codec *codec)
@@ -231,7 +240,7 @@
 	struct hda_jack_tbl *jack;
 	struct snd_kcontrol *kctl;
 
-	jack = snd_hda_jack_tbl_get(codec, nid);
+	jack = snd_hda_jack_tbl_new(codec, nid);
 	if (!jack)
 		return 0;
 	if (jack->kctl)
@@ -251,20 +260,28 @@
 static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
 			 const struct auto_pin_cfg *cfg)
 {
+	unsigned int def_conf, conn;
+	int err;
+
 	if (!nid)
 		return 0;
 	if (!is_jack_detectable(codec, nid))
 		return 0;
-	return snd_hda_jack_add_kctl(codec, nid,
+	def_conf = snd_hda_codec_get_pincfg(codec, nid);
+	conn = get_defcfg_connect(def_conf);
+	if (conn != AC_JACK_PORT_COMPLEX)
+		return 0;
+
+	err = snd_hda_jack_add_kctl(codec, nid,
 				     snd_hda_get_pin_label(codec, nid, cfg),
 				     idx);
+	if (err < 0)
+		return err;
+	return snd_hda_jack_detect_enable(codec, nid, 0);
 }
 
 /**
  * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
- *
- * As of now, it assigns only to the pins that enabled the detection.
- * Usually this is called at the end of build_controls callback.
  */
 int snd_hda_jack_add_kctls(struct hda_codec *codec,
 			   const struct auto_pin_cfg *cfg)