Commit 187d333edc0a8e1bb507900ce89853ffe3bd2c84

Authored by Takashi Iwai
1 parent 92bb43e6aa

ALSA: hda - Fix jack-detection control of VT1708

VT1708 has no support for unsolicited events per jack-plug, the driver
implements the workq for polling the jack-detection.  The mixer element
"Jack Detect" was supposed to control this behavior on/off, but this
doesn't work properly as is now.  The workq is always started and the
HP automute is always enabled.

This patch fixes the jack-detect control behavior by triggering / stopping
the work appropriately at the state change.  Also the work checks the
internal state to continue scheduling or not.

Cc: <stable@kernel.org> [v3.1]
Signed-off-by: Takashi Iwai <tiwai@suse.de>

Showing 1 changed file with 43 additions and 33 deletions Side-by-side Diff

sound/pci/hda/patch_via.c
... ... @@ -208,6 +208,7 @@
208 208 /* work to check hp jack state */
209 209 struct hda_codec *codec;
210 210 struct delayed_work vt1708_hp_work;
  211 + int hp_work_active;
211 212 int vt1708_jack_detect;
212 213 int vt1708_hp_present;
213 214  
214 215  
215 216  
216 217  
... ... @@ -305,27 +306,35 @@
305 306 static void analog_low_current_mode(struct hda_codec *codec);
306 307 static bool is_aa_path_mute(struct hda_codec *codec);
307 308  
308   -static void vt1708_start_hp_work(struct via_spec *spec)
  309 +#define hp_detect_with_aa(codec) \
  310 + (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
  311 + !is_aa_path_mute(codec))
  312 +
  313 +static void vt1708_stop_hp_work(struct via_spec *spec)
309 314 {
310 315 if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
311 316 return;
312   - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
313   - !spec->vt1708_jack_detect);
314   - if (!delayed_work_pending(&spec->vt1708_hp_work))
315   - schedule_delayed_work(&spec->vt1708_hp_work,
316   - msecs_to_jiffies(100));
  317 + if (spec->hp_work_active) {
  318 + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1);
  319 + cancel_delayed_work_sync(&spec->vt1708_hp_work);
  320 + spec->hp_work_active = 0;
  321 + }
317 322 }
318 323  
319   -static void vt1708_stop_hp_work(struct via_spec *spec)
  324 +static void vt1708_update_hp_work(struct via_spec *spec)
320 325 {
321 326 if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
322 327 return;
323   - if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1
324   - && !is_aa_path_mute(spec->codec))
325   - return;
326   - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
327   - !spec->vt1708_jack_detect);
328   - cancel_delayed_work_sync(&spec->vt1708_hp_work);
  328 + if (spec->vt1708_jack_detect &&
  329 + (spec->active_streams || hp_detect_with_aa(spec->codec))) {
  330 + if (!spec->hp_work_active) {
  331 + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0);
  332 + schedule_delayed_work(&spec->vt1708_hp_work,
  333 + msecs_to_jiffies(100));
  334 + spec->hp_work_active = 1;
  335 + }
  336 + } else if (!hp_detect_with_aa(spec->codec))
  337 + vt1708_stop_hp_work(spec);
329 338 }
330 339  
331 340 static void set_widgets_power_state(struct hda_codec *codec)
... ... @@ -343,12 +352,7 @@
343 352  
344 353 set_widgets_power_state(codec);
345 354 analog_low_current_mode(snd_kcontrol_chip(kcontrol));
346   - if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
347   - if (is_aa_path_mute(codec))
348   - vt1708_start_hp_work(codec->spec);
349   - else
350   - vt1708_stop_hp_work(codec->spec);
351   - }
  355 + vt1708_update_hp_work(codec->spec);
352 356 return change;
353 357 }
354 358  
... ... @@ -1154,7 +1158,7 @@
1154 1158 spec->cur_dac_stream_tag = stream_tag;
1155 1159 spec->cur_dac_format = format;
1156 1160 mutex_unlock(&spec->config_mutex);
1157   - vt1708_start_hp_work(spec);
  1161 + vt1708_update_hp_work(spec);
1158 1162 return 0;
1159 1163 }
1160 1164  
... ... @@ -1174,7 +1178,7 @@
1174 1178 spec->cur_hp_stream_tag = stream_tag;
1175 1179 spec->cur_hp_format = format;
1176 1180 mutex_unlock(&spec->config_mutex);
1177   - vt1708_start_hp_work(spec);
  1181 + vt1708_update_hp_work(spec);
1178 1182 return 0;
1179 1183 }
1180 1184  
... ... @@ -1188,7 +1192,7 @@
1188 1192 snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1189 1193 spec->active_streams &= ~STREAM_MULTI_OUT;
1190 1194 mutex_unlock(&spec->config_mutex);
1191   - vt1708_stop_hp_work(spec);
  1195 + vt1708_update_hp_work(spec);
1192 1196 return 0;
1193 1197 }
1194 1198  
... ... @@ -1203,7 +1207,7 @@
1203 1207 snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0);
1204 1208 spec->active_streams &= ~STREAM_INDEP_HP;
1205 1209 mutex_unlock(&spec->config_mutex);
1206   - vt1708_stop_hp_work(spec);
  1210 + vt1708_update_hp_work(spec);
1207 1211 return 0;
1208 1212 }
1209 1213  
... ... @@ -1645,7 +1649,8 @@
1645 1649 int nums;
1646 1650 struct via_spec *spec = codec->spec;
1647 1651  
1648   - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0])
  1652 + if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] &&
  1653 + (spec->codec_type != VT1708 || spec->vt1708_jack_detect))
1649 1654 present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
1650 1655  
1651 1656 if (spec->smart51_enabled)
... ... @@ -2612,8 +2617,6 @@
2612 2617  
2613 2618 if (spec->codec_type != VT1708)
2614 2619 return 0;
2615   - spec->vt1708_jack_detect =
2616   - !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
2617 2620 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
2618 2621 return 0;
2619 2622 }
2620 2623  
2621 2624  
... ... @@ -2623,18 +2626,22 @@
2623 2626 {
2624 2627 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2625 2628 struct via_spec *spec = codec->spec;
2626   - int change;
  2629 + int val;
2627 2630  
2628 2631 if (spec->codec_type != VT1708)
2629 2632 return 0;
2630   - spec->vt1708_jack_detect = ucontrol->value.integer.value[0];
2631   - change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
2632   - == !spec->vt1708_jack_detect;
2633   - if (spec->vt1708_jack_detect) {
  2633 + val = !!ucontrol->value.integer.value[0];
  2634 + if (spec->vt1708_jack_detect == val)
  2635 + return 0;
  2636 + spec->vt1708_jack_detect = val;
  2637 + if (spec->vt1708_jack_detect &&
  2638 + snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) {
2634 2639 mute_aa_path(codec, 1);
2635 2640 notify_aa_path_ctls(codec);
2636 2641 }
2637   - return change;
  2642 + via_hp_automute(codec);
  2643 + vt1708_update_hp_work(spec);
  2644 + return 1;
2638 2645 }
2639 2646  
2640 2647 static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
... ... @@ -2771,6 +2778,7 @@
2771 2778 via_auto_init_unsol_event(codec);
2772 2779  
2773 2780 via_hp_automute(codec);
  2781 + vt1708_update_hp_work(spec);
2774 2782  
2775 2783 return 0;
2776 2784 }
... ... @@ -2787,7 +2795,9 @@
2787 2795 spec->vt1708_hp_present ^= 1;
2788 2796 via_hp_automute(spec->codec);
2789 2797 }
2790   - vt1708_start_hp_work(spec);
  2798 + if (spec->vt1708_jack_detect)
  2799 + schedule_delayed_work(&spec->vt1708_hp_work,
  2800 + msecs_to_jiffies(100));
2791 2801 }
2792 2802  
2793 2803 static int get_mux_nids(struct hda_codec *codec)