From: Takashi Iwai <tiwai@suse.de>
Subject: [PATCH] ALSA: hda - Fix handling of VT1708 jack detection
Git-commit: 05dc0fc9d01537a66d9a0cffe2e96296d8f4c7ac
Patch-mainline: 3.9-rc1
References: bnc#813922

This is a combined fix of a few commits, applied to 3.8 and older
VIA codec parser codes, for fixing the buggy jack detect behavior
of VT1708 codec.

The relevant commits are:
  05dc0fc9d01537a66d9a0cffe2e96296d8f4c7ac
  f672f65a1c15b04e09d25701a8b5be47bad9376a
and slightly changed for SLE11-SP3 without jackpoll implementation.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 sound/pci/hda/hda_codec.h |    1 +
 sound/pci/hda/hda_jack.c  |    3 ++-
 sound/pci/hda/patch_via.c |   33 +++++++++++++++++++--------------
 3 files changed, 22 insertions(+), 15 deletions(-)

--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -896,6 +896,7 @@ struct hda_codec {
 
 	/* jack detection */
 	struct snd_array jacktbl;
+	bool jackpoll;
 
 #ifdef CONFIG_SND_HDA_INPUT_JACK
 	/* jack detection */
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -28,7 +28,8 @@ bool is_jack_detectable(struct hda_codec
 	if (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
 	     AC_DEFCFG_MISC_NO_PRESENCE)
 		return false;
-	if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+	if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) &&
+	    !codec->jackpoll)
 		return false;
 	return true;
 }
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -316,8 +316,9 @@ static bool is_aa_path_mute(struct hda_c
 	(snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
 	 !is_aa_path_mute(codec))
 
-static void vt1708_stop_hp_work(struct via_spec *spec)
+static void vt1708_stop_hp_work(struct hda_codec *codec)
 {
+	struct via_spec *spec = codec->spec;
 	if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
 		return;
 	if (spec->hp_work_active) {
@@ -327,12 +328,12 @@ static void vt1708_stop_hp_work(struct v
 	}
 }
 
-static void vt1708_update_hp_work(struct via_spec *spec)
+static void vt1708_update_hp_work(struct hda_codec *codec)
 {
+	struct via_spec *spec = codec->spec;
 	if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
 		return;
-	if (spec->vt1708_jack_detect &&
-	    (spec->active_streams || hp_detect_with_aa(spec->codec))) {
+	if (spec->vt1708_jack_detect) {
 		if (!spec->hp_work_active) {
 			snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0);
 			schedule_delayed_work(&spec->vt1708_hp_work,
@@ -340,7 +341,7 @@ static void vt1708_update_hp_work(struct
 			spec->hp_work_active = 1;
 		}
 	} else if (!hp_detect_with_aa(spec->codec))
-		vt1708_stop_hp_work(spec);
+		vt1708_stop_hp_work(codec);
 }
 
 static void set_widgets_power_state(struct hda_codec *codec)
@@ -358,7 +359,7 @@ static int analog_input_switch_put(struc
 
 	set_widgets_power_state(codec);
 	analog_low_current_mode(snd_kcontrol_chip(kcontrol));
-	vt1708_update_hp_work(codec->spec);
+	vt1708_update_hp_work(codec);
 	return change;
 }
 
@@ -1200,7 +1201,7 @@ static int via_playback_multi_pcm_prepar
 	spec->cur_dac_stream_tag = stream_tag;
 	spec->cur_dac_format = format;
 	mutex_unlock(&spec->config_mutex);
-	vt1708_update_hp_work(spec);
+	vt1708_update_hp_work(codec);
 	return 0;
 }
 
@@ -1220,7 +1221,7 @@ static int via_playback_hp_pcm_prepare(s
 	spec->cur_hp_stream_tag = stream_tag;
 	spec->cur_hp_format = format;
 	mutex_unlock(&spec->config_mutex);
-	vt1708_update_hp_work(spec);
+	vt1708_update_hp_work(codec);
 	return 0;
 }
 
@@ -1234,7 +1235,7 @@ static int via_playback_multi_pcm_cleanu
 	snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
 	spec->active_streams &= ~STREAM_MULTI_OUT;
 	mutex_unlock(&spec->config_mutex);
-	vt1708_update_hp_work(spec);
+	vt1708_update_hp_work(codec);
 	return 0;
 }
 
@@ -1249,7 +1250,7 @@ static int via_playback_hp_pcm_cleanup(s
 		snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0);
 	spec->active_streams &= ~STREAM_INDEP_HP;
 	mutex_unlock(&spec->config_mutex);
-	vt1708_update_hp_work(spec);
+	vt1708_update_hp_work(codec);
 	return 0;
 }
 
@@ -1634,7 +1635,7 @@ static void via_free(struct hda_codec *c
 		return;
 
 	via_free_kctls(codec);
-	vt1708_stop_hp_work(spec);
+	vt1708_stop_hp_work(codec);
 	kfree(spec->bind_cap_vol);
 	kfree(spec->bind_cap_sw);
 	snd_hda_gen_free(&spec->gen);
@@ -1716,7 +1717,7 @@ static void via_unsol_event(struct hda_c
 static int via_suspend(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
-	vt1708_stop_hp_work(spec);
+	vt1708_stop_hp_work(codec);
 
 	if (spec->codec_type == VT1802) {
 		/* Fix pop noise on headphones */
@@ -2634,13 +2635,14 @@ static int vt1708_jack_detect_put(struct
 	if (spec->vt1708_jack_detect == val)
 		return 0;
 	spec->vt1708_jack_detect = val;
+	codec->jackpoll = val;
 	if (spec->vt1708_jack_detect &&
 	    snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) {
 		mute_aa_path(codec, 1);
 		notify_aa_path_ctls(codec);
 	}
 	via_hp_automute(codec);
-	vt1708_update_hp_work(spec);
+	vt1708_update_hp_work(codec);
 	return 1;
 }
 
@@ -2778,7 +2780,7 @@ static int via_init(struct hda_codec *co
 	via_auto_init_unsol_event(codec);
 
 	via_hp_automute(codec);
-	vt1708_update_hp_work(spec);
+	vt1708_update_hp_work(codec);
 
 	return 0;
 }
@@ -2840,6 +2842,9 @@ static int patch_vt1708(struct hda_codec
 
 	spec->aa_mix_nid = 0x17;
 
+	codec->jackpoll = 1;
+	spec->vt1708_jack_detect = 1;
+
 	/* Add HP and CD pin config connect bit re-config action */
 	vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
 	vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
