aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)
164{ 164{
165 struct hda_beep *beep = 165 struct hda_beep *beep =
166 container_of(work, struct hda_beep, register_work); 166 container_of(work, struct hda_beep, register_work);
167 int request;
168 167
169 mutex_lock(&beep->mutex); 168 mutex_lock(&beep->mutex);
170 request = beep->request_enable; 169 if (beep->enabled && !beep->dev)
171 if (beep->enabled != request) { 170 snd_hda_do_attach(beep);
172 if (!request) { 171 mutex_unlock(&beep->mutex);
173 snd_hda_do_detach(beep); 172}
174 } else { 173
175 if (snd_hda_do_attach(beep) < 0) 174static void snd_hda_do_unregister(struct work_struct *work)
176 goto __out; 175{
177 } 176 struct hda_beep *beep =
178 beep->enabled = request; 177 container_of(work, struct hda_beep, unregister_work.work);
179 } 178
180 __out: 179 mutex_lock(&beep->mutex);
180 if (!beep->enabled && beep->dev)
181 snd_hda_do_detach(beep);
181 mutex_unlock(&beep->mutex); 182 mutex_unlock(&beep->mutex);
182} 183}
183 184
@@ -185,9 +186,19 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
185{ 186{
186 struct hda_beep *beep = codec->beep; 187 struct hda_beep *beep = codec->beep;
187 enable = !!enable; 188 enable = !!enable;
188 if (beep && beep->enabled != enable) { 189 if (beep == NULL)
189 beep->request_enable = enable; 190 return 0;
190 schedule_work(&beep->register_work); 191 if (beep->enabled != enable) {
192 beep->enabled = enable;
193 if (enable) {
194 cancel_delayed_work(&beep->unregister_work);
195 schedule_work(&beep->register_work);
196 } else {
197 /* turn off beep */
198 snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
199 AC_VERB_SET_BEEP_CONTROL, 0);
200 schedule_delayed_work(&beep->unregister_work, HZ);
201 }
191 return 1; 202 return 1;
192 } 203 }
193 return 0; 204 return 0;
@@ -215,6 +226,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
215 codec->beep = beep; 226 codec->beep = beep;
216 227
217 INIT_WORK(&beep->register_work, &snd_hda_do_register); 228 INIT_WORK(&beep->register_work, &snd_hda_do_register);
229 INIT_DELAYED_WORK(&beep->unregister_work, &snd_hda_do_unregister);
218 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); 230 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
219 mutex_init(&beep->mutex); 231 mutex_init(&beep->mutex);
220 232
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 {
34 unsigned int enabled:1; 34 unsigned int enabled:1;
35 unsigned int request_enable:1; 35 unsigned int request_enable:1;
36 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ 36 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
37 struct work_struct register_work; /* scheduled task for beep event */ 37 struct work_struct register_work; /* registration work */
38 struct delayed_work unregister_work; /* unregistration work */
38 struct work_struct beep_work; /* scheduled task for beep event */ 39 struct work_struct beep_work; /* scheduled task for beep event */
39 struct mutex mutex; 40 struct mutex mutex;
40}; 41};