[alsa-devel] [PATCH 0/3] ALSA: hda/ca0132 - Small fixes
Hi,
this is a series of small fixes for CA0132 just for covering some corner cases.
Takashi
===
Takashi Iwai (3): ALSA: hda/c0a132 - Keep power on during processing DSP response ALSA: hda/c0a132 - Avoid endless loop ALSA: hda/ca0132 - Fix work handling in delayed HP detection
sound/pci/hda/patch_ca0132.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-)
We need to keep power on while processing the DSP response via unsol event. Each snd_hda_codec_read() call does the power management, so it should work normally, but still it's safer to keep the power up for the whole function.
Fixes: a73d511c4867 ("ALSA: hda/ca0132: Add unsol handler for DSP and jack detection") Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_ca0132.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index b7a1abb3e231..c3d34ff3d9ec 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -7588,12 +7588,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)
Introduce a timeout to dspio_clear_response_queue() so that it won't be caught in an endless loop even if the hardware doesn't respond properly.
Fixes: a73d511c4867 ("ALSA: hda/ca0132: Add unsol handler for DSP and jack detection") Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_ca0132.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index c3d34ff3d9ec..8d0209fff8f5 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -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)
CA0132 has the delayed HP jack detection code that is invoked from the unsol handler, but it does a few weird things: it contains the cancel of a work inside the work handler, and yet it misses the cancel-sync call at (runtime-)suspend. This patch addresses those issues.
Fixes: 15c2b3cc09a3 ("ALSA: hda/ca0132 - Fix possible workqueue stall") Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_ca0132.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 8d0209fff8f5..32ed46464af7 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -7607,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(&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) @@ -8457,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, };
participants (1)
-
Takashi Iwai