From: Jaroslav Kysela Date: Tue, 3 Nov 2009 13:29:50 +0000 (+0100) Subject: ALSA: hda_intel: Digital PC Beep - delay input device unregistration X-Git-Tag: v2.6.33-rc2~15^2~5^2~67 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=13dab0808bb41b18888e1758a060a685deee1f30;p=platform%2Fupstream%2Fkernel-adaptation-pc.git 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 Signed-off-by: Takashi Iwai --- diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 0e98653..74db40e 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 68465f6..53eba8d 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; };