aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_beep.c
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2009-10-21 08:48:23 -0400
committerTakashi Iwai <tiwai@suse.de>2009-11-16 05:34:41 -0500
commit123c07aeddd71fbb295842a8c19866e780b9a100 (patch)
tree8b97495608cad55f9169a826fe4637f9ac2d21c3 /sound/pci/hda/hda_beep.c
parentfe705ab1526bc2c8b7756f3a855f040ab2060af2 (diff)
ALSA: hda_intel: Digital PC Beep - change behaviour for input layer
Original implementation was keeping registered input device for SND_BEEP and SND_TONE events all time. This patch changes this behaviour: If digital PC Beep is turned off using universal control switch, the input device is unregistered. Explanation: The kd_mksound() send SND_BEEP and SND_TONE only to last registered device acceping those events. It means that the HDA Intel audio driver blocks also the internal PC Speaker device (pcspkr.c driver) even if the HDA Beep is muted. The user can easy disable all beeps using 'setterm -blength 0' or 'xset b off' command. Signed-off-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_beep.c')
-rw-r--r--sound/pci/hda/hda_beep.c88
1 files changed, 70 insertions, 18 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 3f51a981e604..0e986537d570 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -113,23 +113,25 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
113 return 0; 113 return 0;
114} 114}
115 115
116int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) 116static void snd_hda_do_detach(struct hda_beep *beep)
117{
118 input_unregister_device(beep->dev);
119 beep->dev = NULL;
120 cancel_work_sync(&beep->beep_work);
121 /* turn off beep for sure */
122 snd_hda_codec_write_cache(beep->codec, beep->nid, 0,
123 AC_VERB_SET_BEEP_CONTROL, 0);
124}
125
126static int snd_hda_do_attach(struct hda_beep *beep)
117{ 127{
118 struct input_dev *input_dev; 128 struct input_dev *input_dev;
119 struct hda_beep *beep; 129 struct hda_codec *codec = beep->codec;
120 int err; 130 int err;
121 131
122 if (!snd_hda_get_bool_hint(codec, "beep"))
123 return 0; /* disabled explicitly */
124
125 beep = kzalloc(sizeof(*beep), GFP_KERNEL);
126 if (beep == NULL)
127 return -ENOMEM;
128 snprintf(beep->phys, sizeof(beep->phys),
129 "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
130 input_dev = input_allocate_device(); 132 input_dev = input_allocate_device();
131 if (!input_dev) { 133 if (!input_dev) {
132 kfree(beep); 134 printk(KERN_INFO "hda_beep: unable to allocate input device\n");
133 return -ENOMEM; 135 return -ENOMEM;
134 } 136 }
135 137
@@ -151,21 +153,71 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
151 err = input_register_device(input_dev); 153 err = input_register_device(input_dev);
152 if (err < 0) { 154 if (err < 0) {
153 input_free_device(input_dev); 155 input_free_device(input_dev);
154 kfree(beep); 156 printk(KERN_INFO "hda_beep: unable to register input device\n");
155 return err; 157 return err;
156 } 158 }
159 beep->dev = input_dev;
160 return 0;
161}
162
163static void snd_hda_do_register(struct work_struct *work)
164{
165 struct hda_beep *beep =
166 container_of(work, struct hda_beep, register_work);
167 int request;
168
169 mutex_lock(&beep->mutex);
170 request = beep->request_enable;
171 if (beep->enabled != request) {
172 if (!request) {
173 snd_hda_do_detach(beep);
174 } else {
175 if (snd_hda_do_attach(beep) < 0)
176 goto __out;
177 }
178 beep->enabled = request;
179 }
180 __out:
181 mutex_unlock(&beep->mutex);
182}
183
184int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
185{
186 struct hda_beep *beep = codec->beep;
187 enable = !!enable;
188 if (beep && beep->enabled != enable) {
189 beep->request_enable = enable;
190 schedule_work(&beep->register_work);
191 return 1;
192 }
193 return 0;
194}
195EXPORT_SYMBOL_HDA(snd_hda_enable_beep_device);
196
197int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
198{
199 struct hda_beep *beep;
200
201 if (!snd_hda_get_bool_hint(codec, "beep"))
202 return 0; /* disabled explicitly */
157 203
204 beep = kzalloc(sizeof(*beep), GFP_KERNEL);
205 if (beep == NULL)
206 return -ENOMEM;
207 snprintf(beep->phys, sizeof(beep->phys),
208 "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr);
158 /* enable linear scale */ 209 /* enable linear scale */
159 snd_hda_codec_write(codec, nid, 0, 210 snd_hda_codec_write(codec, nid, 0,
160 AC_VERB_SET_DIGI_CONVERT_2, 0x01); 211 AC_VERB_SET_DIGI_CONVERT_2, 0x01);
161 212
162 beep->nid = nid; 213 beep->nid = nid;
163 beep->dev = input_dev;
164 beep->codec = codec; 214 beep->codec = codec;
165 beep->enabled = 1;
166 codec->beep = beep; 215 codec->beep = beep;
167 216
217 INIT_WORK(&beep->register_work, &snd_hda_do_register);
168 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); 218 INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
219 mutex_init(&beep->mutex);
220
169 return 0; 221 return 0;
170} 222}
171EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device); 223EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
@@ -174,11 +226,11 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
174{ 226{
175 struct hda_beep *beep = codec->beep; 227 struct hda_beep *beep = codec->beep;
176 if (beep) { 228 if (beep) {
177 cancel_work_sync(&beep->beep_work); 229 cancel_work_sync(&beep->register_work);
178 230 if (beep->enabled)
179 input_unregister_device(beep->dev); 231 snd_hda_do_detach(beep);
180 kfree(beep);
181 codec->beep = NULL; 232 codec->beep = NULL;
233 kfree(beep);
182 } 234 }
183} 235}
184EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); 236EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);