diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index cee6a00bd85a2311681433196f26da22baf38174..8829d5c83feca014c9b3bd9c462ca2e91e8fba08 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -50,6 +50,24 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
 }
 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
  */
@@ -65,6 +83,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
 		return NULL;
 	jack->nid = nid;
 	jack->jack_dirty = 1;
+	jack->tag = codec->jacktbl.used;
 	return jack;
 }
 
@@ -77,7 +96,7 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec)
 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 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
  * 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);
 
@@ -167,18 +188,6 @@ static void jack_detect_report(struct hda_codec *codec,
 	}
 }
 
-/**
- * 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
  */
@@ -231,7 +240,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 	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 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 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)
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index b5983eaea51ef0982e0361831902a049924ba21b..69a67f8e4f45c62a64d1e07ab5a97d14efbdb29f 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -14,8 +14,12 @@
 
 struct hda_jack_tbl {
 	hda_nid_t nid;
+	unsigned char action;		/* event action (0 = none) */
+	unsigned char tag;		/* unsol event tag */
+	unsigned int private_data;	/* arbitrary data */
+	/* jack-detection stuff */
 	unsigned int pin_sense;		/* cached pin-sense value */
-	unsigned int jack_cachable:1;	/* can be updated via unsol events */
+	unsigned int jack_detect:1;	/* capable of jack-detection? */
 	unsigned int jack_dirty:1;	/* needs to update? */
 	unsigned int need_notify:1;	/* to be notified? */
 	struct snd_kcontrol *kctl;	/* assigned kctl for jack-detection */
@@ -23,29 +27,34 @@ struct hda_jack_tbl {
 
 struct hda_jack_tbl *
 snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);
+struct hda_jack_tbl *
+snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag);
 
 struct hda_jack_tbl *
 snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);
 void snd_hda_jack_tbl_clear(struct hda_codec *codec);
 
 /**
- * snd_hda_jack_set_dirty - set the dirty flag for the given jack-entry
+ * snd_hda_jack_get_action - get jack-tbl entry for the tag
  *
- * Call this function when a pin-state may change, e.g. when the hardware
- * notifies via an unsolicited event.
+ * Call this from the unsol event handler to get the assigned action for the
+ * event.  This will mark the dirty flag for the later reporting, too.
  */
-static inline void snd_hda_jack_set_dirty(struct hda_codec *codec,
-					  hda_nid_t nid)
+static inline unsigned char
+snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag)
 {
-	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
-	if (jack)
+	struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
+	if (jack) {
 		jack->jack_dirty = 1;
+		return jack->action;
+	}
+	return 0;
 }
 
 void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
 
 int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
-			       unsigned int tag);
+			       unsigned char action);
 
 u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
 int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
@@ -68,7 +77,6 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 int snd_hda_jack_add_kctls(struct hda_codec *codec,
 			   const struct auto_pin_cfg *cfg);
 
-void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid);
 void snd_hda_jack_report_sync(struct hda_codec *codec);
 
 
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 135fd49cd49d9f25170be48d22041981db13e355..0e34554bc45e0ed44ad945eef59d04df7e2c7a82 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -1235,9 +1235,7 @@ static void cs_free(struct hda_codec *codec)
 
 static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
 {
-	snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */
-
-	switch ((res >> 26) & 0x7f) {
+	switch (snd_hda_jack_get_action(codec, res >> 26)) {
 	case HP_EVENT:
 		cs_automute(codec);
 		break;
@@ -1824,9 +1822,7 @@ static int cs421x_build_controls(struct hda_codec *codec)
 
 static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
 {
-	snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */
-
-	switch ((res >> 26) & 0x3f) {
+	switch (snd_hda_jack_get_action(codec, res >> 26)) {
 	case HP_EVENT:
 	case SPDIF_EVENT:
 		cs_automute(codec);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 25fdd1e9561f1c0f185454927afc0e9311d42d5d..40bd75b293bab7de83ff9c86c8fde43cff59da99 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -3757,8 +3757,8 @@ static void cx_auto_automic(struct hda_codec *codec)
 static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
 {
 	int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
-	snd_hda_jack_set_dirty(codec, nid);
-	switch (res >> 26) {
+
+	switch (snd_hda_jack_get_action(codec, res >> 26)) {
 	case CONEXANT_HP_EVENT:
 		cx_auto_hp_automute(codec);
 		break;
@@ -3982,11 +3982,11 @@ static void mute_outputs(struct hda_codec *codec, int num_nids,
 }
 
 static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
-			      hda_nid_t *pins, unsigned int tag)
+			      hda_nid_t *pins, unsigned int action)
 {
 	int i;
 	for (i = 0; i < num_pins; i++)
-		snd_hda_jack_detect_enable(codec, pins[i], tag);
+		snd_hda_jack_detect_enable(codec, pins[i], action);
 }
 
 static void cx_auto_init_output(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index f01c5efde8e19c28536f20ef965c7ff4d641c1ed..ea30bf4a4f50ac15936419a3177f2ceaf9d497b9 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -754,10 +754,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry);
 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 {
 	struct hdmi_spec *spec = codec->spec;
-	int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+	int pin_nid;
 	int pd = !!(res & AC_UNSOL_RES_PD);
 	int eldv = !!(res & AC_UNSOL_RES_ELDV);
 	int pin_idx;
+	struct hda_jack_tbl *jack;
+
+	jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
+	if (!jack)
+		return;
+	pin_nid = jack->nid;
+	jack->jack_dirty = 1;
 
 	printk(KERN_INFO
 		"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
@@ -767,7 +775,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 	if (pin_idx < 0)
 		return;
 
-	snd_hda_jack_set_dirty(codec, pin_nid);
 	hdmi_present_sense(&spec->pins[pin_idx], true);
 	snd_hda_jack_report_sync(codec);
 }
@@ -801,7 +808,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
 	int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
 	int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
 
-	if (pin_nid_to_pin_index(spec, tag) < 0) {
+	if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) {
 		snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
 		return;
 	}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 04beae034fea608db37e69d4d1308cd5663359dd..9a90cdac78f48db70844a662133256c6dd2e1585 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -185,6 +185,7 @@ struct alc_spec {
 	unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
 	unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
 	unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
+	unsigned int use_jack_tbl:1; /* 1 for model=auto */
 
 	/* auto-mute control */
 	int automute_mode;
@@ -661,11 +662,13 @@ static void alc_mic_automute(struct hda_codec *codec)
 /* unsolicited event for HP jack sensing */
 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 {
+	struct alc_spec *spec = codec->spec;
 	if (codec->vendor_id == 0x10ec0880)
 		res >>= 28;
 	else
 		res >>= 26;
-	snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */
+	if (spec->use_jack_tbl)
+		res = snd_hda_jack_get_action(codec, res);
 	switch (res) {
 	case ALC_HP_EVENT:
 		alc_hp_automute(codec);
@@ -3896,6 +3899,7 @@ static void set_capture_mixer(struct hda_codec *codec)
 static void alc_auto_init_std(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->use_jack_tbl = 1;
 	alc_auto_init_multi_out(codec);
 	alc_auto_init_extra_out(codec);
 	alc_auto_init_analog_input(codec);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 90954b8269c3a7e50af88e31df07cb8d7f22759b..dd6569ffcff8d8d305a4cf0c8600ac4cfc2ef5d3 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -177,13 +177,6 @@ enum {
 	STAC_9872_MODELS
 };
 
-struct sigmatel_event {
-	hda_nid_t nid;
-	unsigned char type;
-	unsigned char tag;
-	int data;
-};
-
 struct sigmatel_mic_route {
 	hda_nid_t pin;
 	signed char mux_idx;
@@ -231,9 +224,6 @@ struct sigmatel_spec {
 	const hda_nid_t *pwr_nids;
 	const hda_nid_t *dac_list;
 
-	/* events */
-	struct snd_array events;
-
 	/* playback */
 	struct hda_input_mux *mono_mux;
 	unsigned int cur_mmux;
@@ -4182,49 +4172,18 @@ static int stac92xx_add_jack(struct hda_codec *codec,
 #endif /* CONFIG_SND_HDA_INPUT_JACK */
 }
 
-static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
+static int stac_add_event(struct hda_codec *codec, hda_nid_t nid,
 			  unsigned char type, int data)
 {
-	struct sigmatel_event *event;
+	struct hda_jack_tbl *event;
 
-	snd_array_init(&spec->events, sizeof(*event), 32);
-	event = snd_array_new(&spec->events);
+	event = snd_hda_jack_tbl_new(codec, nid);
 	if (!event)
 		return -ENOMEM;
-	event->nid = nid;
-	event->type = type;
-	event->tag = spec->events.used;
-	event->data = data;
-
-	return event->tag;
-}
-
-static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
-					     hda_nid_t nid)
-{
-	struct sigmatel_spec *spec = codec->spec;
-	struct sigmatel_event *event = spec->events.list;
-	int i;
-
-	for (i = 0; i < spec->events.used; i++, event++) {
-		if (event->nid == nid)
-			return event;
-	}
-	return NULL;
-}
+	event->action = type;
+	event->private_data = data;
 
-static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
-						      unsigned char tag)
-{
-	struct sigmatel_spec *spec = codec->spec;
-	struct sigmatel_event *event = spec->events.list;
-	int i;
-
-	for (i = 0; i < spec->events.used; i++, event++) {
-		if (event->tag == tag)
-			return event;
-	}
-	return NULL;
+	return 0;
 }
 
 /* check if given nid is a valid pin and no other events are assigned
@@ -4234,22 +4193,17 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
 static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
 			     unsigned int type)
 {
-	struct sigmatel_event *event;
-	int tag;
+	struct hda_jack_tbl *event;
 
 	if (!is_jack_detectable(codec, nid))
 		return 0;
-	event = stac_get_event(codec, nid);
-	if (event) {
-		if (event->type != type)
-			return 0;
-		tag = event->tag;
-	} else {
-		tag = stac_add_event(codec->spec, nid, type, 0);
-		if (tag < 0)
-			return 0;
-	}
-	snd_hda_jack_detect_enable(codec, nid, tag);
+	event = snd_hda_jack_tbl_new(codec, nid);
+	if (!event)
+		return -ENOMEM;
+	if (event->action && event->action != type)
+		return 0;
+	event->action = type;
+	snd_hda_jack_detect_enable(codec, nid, 0);
 	return 1;
 }
 
@@ -4536,7 +4490,6 @@ static void stac92xx_free(struct hda_codec *codec)
 
 	stac92xx_shutup(codec);
 	snd_hda_input_jack_free(codec);
-	snd_array_free(&spec->events);
 
 	kfree(spec);
 	snd_hda_detach_beep_device(codec);
@@ -4801,12 +4754,12 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
 }
 
 static void handle_unsol_event(struct hda_codec *codec,
-			       struct sigmatel_event *event)
+			       struct hda_jack_tbl *event)
 {
 	struct sigmatel_spec *spec = codec->spec;
 	int data;
 
-	switch (event->type) {
+	switch (event->action) {
 	case STAC_HP_EVENT:
 	case STAC_LO_EVENT:
 		stac92xx_hp_detect(codec);
@@ -4816,7 +4769,7 @@ static void handle_unsol_event(struct hda_codec *codec,
 		break;
 	}
 
-	switch (event->type) {
+	switch (event->action) {
 	case STAC_HP_EVENT:
 	case STAC_LO_EVENT:
 	case STAC_MIC_EVENT:
@@ -4849,14 +4802,14 @@ static void handle_unsol_event(struct hda_codec *codec,
 					  AC_VERB_GET_GPIO_DATA, 0);
 		/* toggle VREF state based on GPIOx status */
 		snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
-				    !!(data & (1 << event->data)));
+				    !!(data & (1 << event->private_data)));
 		break;
 	}
 }
 
 static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
 {
-	struct sigmatel_event *event = stac_get_event(codec, nid);
+	struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid);
 	if (!event)
 		return;
 	handle_unsol_event(codec, event);
@@ -4864,15 +4817,14 @@ static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
 
 static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
 {
-	struct sigmatel_spec *spec = codec->spec;
-	struct sigmatel_event *event;
+	struct hda_jack_tbl *event;
 	int tag;
 
 	tag = (res >> 26) & 0x7f;
-	event = stac_get_event_from_tag(codec, tag);
+	event = snd_hda_jack_tbl_get_from_tag(codec, tag);
 	if (!event)
 		return;
-	snd_hda_jack_set_dirty(codec, event->nid);
+	event->jack_dirty = 1;
 	handle_unsol_event(codec, event);
 	snd_hda_jack_report_sync(codec);
 }
@@ -5857,15 +5809,13 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
 		switch (spec->board_config) {
 		case STAC_HP_M4:
 			/* Enable VREF power saving on GPIO1 detect */
-			err = stac_add_event(spec, codec->afg,
+			err = stac_add_event(codec, codec->afg,
 					     STAC_VREF_EVENT, 0x02);
 			if (err < 0)
 				return err;
 			snd_hda_codec_write_cache(codec, codec->afg, 0,
 				AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
-			snd_hda_codec_write_cache(codec, codec->afg, 0,
-				AC_VERB_SET_UNSOLICITED_ENABLE,
-				AC_USRSP_EN | err);
+			snd_hda_jack_detect_enable(codec, codec->afg, 0);
 			spec->gpio_mask |= 0x02;
 			break;
 		}
@@ -6338,14 +6288,12 @@ static int patch_stac9205(struct hda_codec *codec)
 		snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
 
 		/* Enable unsol response for GPIO4/Dock HP connection */
-		err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
+		err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01);
 		if (err < 0)
 			return err;
 		snd_hda_codec_write_cache(codec, codec->afg, 0,
 			AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
-		snd_hda_codec_write_cache(codec, codec->afg, 0,
-					  AC_VERB_SET_UNSOLICITED_ENABLE,
-					  AC_USRSP_EN | err);
+		snd_hda_jack_detect_enable(codec, codec->afg, 0);
 
 		spec->gpio_dir = 0x0b;
 		spec->eapd_mask = 0x01;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 852939658ddbd8f4f37be12a75328a34880d7903..f73c98638abd35883413b74f13e490c6d887bf0e 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1714,9 +1714,8 @@ static void via_gpio_control(struct hda_codec *codec)
 static void via_unsol_event(struct hda_codec *codec,
 				  unsigned int res)
 {
-	snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */
-
 	res >>= 26;
+	res = snd_hda_jack_get_action(codec, res);
 
 	if (res & VIA_JACK_EVENT)
 		set_widgets_power_state(codec);