ALSA: hda/ca0132 - Fix work handling in delayed HP detection
[sfrench/cifs-2.6.git] / sound / pci / hda / patch_ca0132.c
index 6d1fb7c11f17ed93b5ca4f2f12e295c3970b6ec4..32ed46464af7ad0a3ec1197cb935db3a1571317f 100644 (file)
@@ -1809,13 +1809,14 @@ struct scp_msg {
 
 static void dspio_clear_response_queue(struct hda_codec *codec)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        unsigned int dummy = 0;
-       int status = -1;
+       int status;
 
        /* clear all from the response queue */
        do {
                status = dspio_read(codec, &dummy);
-       } while (status == 0);
+       } while (status == 0 && time_before(jiffies, timeout));
 }
 
 static int dspio_get_response_data(struct hda_codec *codec)
@@ -7588,12 +7589,14 @@ static void ca0132_process_dsp_response(struct hda_codec *codec,
        struct ca0132_spec *spec = codec->spec;
 
        codec_dbg(codec, "ca0132_process_dsp_response\n");
+       snd_hda_power_up_pm(codec);
        if (spec->wait_scp) {
                if (dspio_get_response_data(codec) >= 0)
                        spec->wait_scp = 0;
        }
 
        dspio_clear_response_queue(codec);
+       snd_hda_power_down_pm(codec);
 }
 
 static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
@@ -7604,11 +7607,10 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
        /* Delay enabling the HP amp, to let the mic-detection
         * state machine run.
         */
-       cancel_delayed_work_sync(&spec->unsol_hp_work);
-       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
        tbl = snd_hda_jack_tbl_get(codec, cb->nid);
        if (tbl)
                tbl->block_report = 1;
+       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
 }
 
 static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
@@ -8454,12 +8456,25 @@ static void ca0132_reboot_notify(struct hda_codec *codec)
        codec->patch_ops.free(codec);
 }
 
+#ifdef CONFIG_PM
+static int ca0132_suspend(struct hda_codec *codec)
+{
+       struct ca0132_spec *spec = codec->spec;
+
+       cancel_delayed_work_sync(&spec->unsol_hp_work);
+       return 0;
+}
+#endif
+
 static const struct hda_codec_ops ca0132_patch_ops = {
        .build_controls = ca0132_build_controls,
        .build_pcms = ca0132_build_pcms,
        .init = ca0132_init,
        .free = ca0132_free,
        .unsol_event = snd_hda_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = ca0132_suspend,
+#endif
        .reboot_notify = ca0132_reboot_notify,
 };