summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2009-11-03 14:29:50 +0100
committerTakashi Iwai <tiwai@suse.de>2009-11-16 11:35:00 +0100
commit13dab0808bb41b18888e1758a060a685deee1f30 (patch)
tree3d0828a0c537d9ba9934562631816a4671a3bf56
parent123c07aeddd71fbb295842a8c19866e780b9a100 (diff)
ALSA: hda_intel: Digital PC Beep - delay input device unregistration
The massive register/unregister calls for input device layer might be overkill. Delay unregister call by one HZ as workaround. Also, as benefit, beep->enabled variable is changed immediately now (not from workqueue). Signed-off-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_beep.c42
-rw-r--r--sound/pci/hda/hda_beep.h3
2 files changed, 29 insertions, 16 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 0e986537d570..74db40edb336 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -164,20 +164,21 @@ static void snd_hda_do_register(struct work_struct *work)
{
struct hda_beep *beep =
container_of(work, struct hda_beep, register_work);
- int request;
mutex_lock(&beep->mutex);
- request = beep->request_enable;
- if (beep->enabled != request) {
- if (!request) {
- snd_hda_do_detach(beep);
- } else {
- if (snd_hda_do_attach(beep) < 0)
- goto __out;
- }
- beep->enabled = request;
- }
- __out:
+ if (beep->enabled && !beep->dev)
+ snd_hda_do_attach(beep);
+ mutex_unlock(&beep->mutex);
+}
+
+static void snd_hda_do_unregister(struct work_struct *work)
+{
+ struct hda_beep *beep =
+ container_of(work, struct hda_beep, unregister_work.work);
+
+ mutex_lock(&beep->mutex);
+ if (!beep->enabled && beep->dev)
+ snd_hda_do_detach(beep);
mutex_unlock(&beep->mutex);
}
@@ -185,9 +186,19 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
{
struct hda_beep *beep = codec->beep;
enable = !!enable;
- if (beep && beep->enabled != enable) {
- beep->request_enable = enable;
- schedule_work(&beep->register_work);
+ if (beep == NULL)
+ return 0;
+ if (beep->enabled != enable) {
+ beep->enabled = enable;
+ if (enable) {
+ cancel_delayed_work(&beep->unregister_work);
+ schedule_work(&beep->register_work);
+ } else {
+ /* turn off beep */
+ snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
+ AC_VERB_SET_BEEP_CONTROL, 0);
+ schedule_delayed_work(&beep->unregister_work, HZ);
+ }
return 1;
}
return 0;
@@ -215,6 +226,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
codec->beep = beep;
INIT_WORK(&beep->register_work, &snd_hda_do_register);
+ INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister);
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
mutex_init(&beep->mutex);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index 68465f679d8c..53eba8d8414d 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -34,7 +34,8 @@ struct hda_beep {
unsigned int enabled:1;
unsigned int request_enable:1;
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
- struct work_struct register_work; /* scheduled task for beep event */
+ struct work_struct register_work; /* registration work */
+ struct delayed_work unregister_work; /* unregistration work */
struct work_struct beep_work; /* scheduled task for beep event */
struct mutex mutex;
};