diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-03-18 14:29:56 +0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-03-18 15:58:47 +0400 |
commit | e914b25e370a3a55a839ff507ed779f54431ace5 (patch) | |
tree | 73779f18794bd94de2974cf3bd4530f21c4cbd8e /sound/pci | |
parent | 7504b6cd220a3dd8104abe3d0f985c6957dc3e17 (diff) | |
download | linux-e914b25e370a3a55a839ff507ed779f54431ace5.tar.xz |
ALSA: hda - Fix power-saving during playing beep sound
While playing the digital beep tone, the codec shouldn't be turned
off. This patch adds proper snd_hda_power_up()/down() calls at each
time when the beep is played or off.
Also, this fixes automatically an unnecessary codec power-up at
detaching the beep device when the beep isn't being played.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_beep.c | 37 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.h | 1 |
2 files changed, 27 insertions, 11 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 0849aac449f2..35bf5316ccc6 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -39,13 +39,23 @@ static void snd_hda_generate_beep(struct work_struct *work) struct hda_beep *beep = container_of(work, struct hda_beep, beep_work); struct hda_codec *codec = beep->codec; + int tone; if (!beep->enabled) return; + tone = beep->tone; + if (tone && !beep->playing) { + snd_hda_power_up(codec); + beep->playing = 1; + } /* generate tone */ snd_hda_codec_write(codec, beep->nid, 0, - AC_VERB_SET_BEEP_CONTROL, beep->tone); + AC_VERB_SET_BEEP_CONTROL, tone); + if (!tone && beep->playing) { + beep->playing = 0; + snd_hda_power_down(codec); + } } /* (non-standard) Linear beep tone calculation for IDT/STAC codecs @@ -115,14 +125,23 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, return 0; } +static void turn_off_beep(struct hda_beep *beep) +{ + cancel_work_sync(&beep->beep_work); + if (beep->playing) { + /* turn off beep */ + snd_hda_codec_write(beep->codec, beep->nid, 0, + AC_VERB_SET_BEEP_CONTROL, 0); + beep->playing = 0; + snd_hda_power_down(beep->codec); + } +} + static void snd_hda_do_detach(struct hda_beep *beep) { input_unregister_device(beep->dev); beep->dev = NULL; - cancel_work_sync(&beep->beep_work); - /* turn off beep for sure */ - snd_hda_codec_write(beep->codec, beep->nid, 0, - AC_VERB_SET_BEEP_CONTROL, 0); + turn_off_beep(beep); } static int snd_hda_do_attach(struct hda_beep *beep) @@ -170,12 +189,8 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) enable = !!enable; if (beep->enabled != enable) { beep->enabled = enable; - if (!enable) { - cancel_work_sync(&beep->beep_work); - /* turn off beep */ - snd_hda_codec_write(beep->codec, beep->nid, 0, - AC_VERB_SET_BEEP_CONTROL, 0); - } + if (!enable) + turn_off_beep(beep); return 1; } return 0; diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index 4dc6933bc655..cb88464676b6 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -36,6 +36,7 @@ struct hda_beep { hda_nid_t nid; unsigned int enabled:1; unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ + unsigned int playing:1; struct work_struct beep_work; /* scheduled task for beep event */ struct mutex mutex; }; |