aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-03-18 06:29:56 -0400
committerTakashi Iwai <tiwai@suse.de>2013-03-18 07:58:47 -0400
commite914b25e370a3a55a839ff507ed779f54431ace5 (patch)
tree73779f18794bd94de2974cf3bd4530f21c4cbd8e /sound/pci
parent7504b6cd220a3dd8104abe3d0f985c6957dc3e17 (diff)
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.c37
-rw-r--r--sound/pci/hda/hda_beep.h1
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)
39 struct hda_beep *beep = 39 struct hda_beep *beep =
40 container_of(work, struct hda_beep, beep_work); 40 container_of(work, struct hda_beep, beep_work);
41 struct hda_codec *codec = beep->codec; 41 struct hda_codec *codec = beep->codec;
42 int tone;
42 43
43 if (!beep->enabled) 44 if (!beep->enabled)
44 return; 45 return;
45 46
47 tone = beep->tone;
48 if (tone && !beep->playing) {
49 snd_hda_power_up(codec);
50 beep->playing = 1;
51 }
46 /* generate tone */ 52 /* generate tone */
47 snd_hda_codec_write(codec, beep->nid, 0, 53 snd_hda_codec_write(codec, beep->nid, 0,
48 AC_VERB_SET_BEEP_CONTROL, beep->tone); 54 AC_VERB_SET_BEEP_CONTROL, tone);
55 if (!tone && beep->playing) {
56 beep->playing = 0;
57 snd_hda_power_down(codec);
58 }
49} 59}
50 60
51/* (non-standard) Linear beep tone calculation for IDT/STAC codecs 61/* (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,
115 return 0; 125 return 0;
116} 126}
117 127
128static void turn_off_beep(struct hda_beep *beep)
129{
130 cancel_work_sync(&beep->beep_work);
131 if (beep->playing) {
132 /* turn off beep */
133 snd_hda_codec_write(beep->codec, beep->nid, 0,
134 AC_VERB_SET_BEEP_CONTROL, 0);
135 beep->playing = 0;
136 snd_hda_power_down(beep->codec);
137 }
138}
139
118static void snd_hda_do_detach(struct hda_beep *beep) 140static void snd_hda_do_detach(struct hda_beep *beep)
119{ 141{
120 input_unregister_device(beep->dev); 142 input_unregister_device(beep->dev);
121 beep->dev = NULL; 143 beep->dev = NULL;
122 cancel_work_sync(&beep->beep_work); 144 turn_off_beep(beep);
123 /* turn off beep for sure */
124 snd_hda_codec_write(beep->codec, beep->nid, 0,
125 AC_VERB_SET_BEEP_CONTROL, 0);
126} 145}
127 146
128static int snd_hda_do_attach(struct hda_beep *beep) 147static 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)
170 enable = !!enable; 189 enable = !!enable;
171 if (beep->enabled != enable) { 190 if (beep->enabled != enable) {
172 beep->enabled = enable; 191 beep->enabled = enable;
173 if (!enable) { 192 if (!enable)
174 cancel_work_sync(&beep->beep_work); 193 turn_off_beep(beep);
175 /* turn off beep */
176 snd_hda_codec_write(beep->codec, beep->nid, 0,
177 AC_VERB_SET_BEEP_CONTROL, 0);
178 }
179 return 1; 194 return 1;
180 } 195 }
181 return 0; 196 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 {
36 hda_nid_t nid; 36 hda_nid_t nid;
37 unsigned int enabled:1; 37 unsigned int enabled:1;
38 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ 38 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
39 unsigned int playing:1;
39 struct work_struct beep_work; /* scheduled task for beep event */ 40 struct work_struct beep_work; /* scheduled task for beep event */
40 struct mutex mutex; 41 struct mutex mutex;
41}; 42};