aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-02-28 07:42:09 -0500
committerTakashi Iwai <tiwai@suse.de>2014-02-28 08:02:21 -0500
commitd604b3990884062873e3bef09ef5e89857c409c3 (patch)
tree2bb427552257ef1404ac61bb67e212b611fe92ea
parent2b9e4a73fbd90cb8459cf84c12ae05d2eb81da41 (diff)
ALSA: hda - Fix registration of beep input device
The beep input device is registered via input_register_device(), but this is called in snd_hda_attach_beep_device() where the sound devices aren't registered yet. This leads to the binding to non-existing object, thus results in failure. And, even if the binding worked (against the PCI object), it's still racy; the input device appears before the sound objects. For fixing this, register the input device properly at dev_register ops of the codec object it's bound with. Also, call snd_hda_detach_beep_device() at dev_disconnection so that it's detached at the right timing. As a bonus, since it's called in the codec's ops, we can get rid of the further call from the other codec drivers. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_beep.c33
-rw-r--r--sound/pci/hda/hda_beep.h6
-rw-r--r--sound/pci/hda/hda_codec.c8
-rw-r--r--sound/pci/hda/hda_generic.c1
-rw-r--r--sound/pci/hda/patch_conexant.c4
5 files changed, 39 insertions, 13 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 88bb08486f77..8c6c50afc0b7 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -139,7 +139,10 @@ static void turn_off_beep(struct hda_beep *beep)
139 139
140static void snd_hda_do_detach(struct hda_beep *beep) 140static void snd_hda_do_detach(struct hda_beep *beep)
141{ 141{
142 input_unregister_device(beep->dev); 142 if (beep->registered)
143 input_unregister_device(beep->dev);
144 else
145 input_free_device(beep->dev);
143 beep->dev = NULL; 146 beep->dev = NULL;
144 turn_off_beep(beep); 147 turn_off_beep(beep);
145} 148}
@@ -148,7 +151,6 @@ static int snd_hda_do_attach(struct hda_beep *beep)
148{ 151{
149 struct input_dev *input_dev; 152 struct input_dev *input_dev;
150 struct hda_codec *codec = beep->codec; 153 struct hda_codec *codec = beep->codec;
151 int err;
152 154
153 input_dev = input_allocate_device(); 155 input_dev = input_allocate_device();
154 if (!input_dev) 156 if (!input_dev)
@@ -169,12 +171,6 @@ static int snd_hda_do_attach(struct hda_beep *beep)
169 input_dev->dev.parent = &codec->dev; 171 input_dev->dev.parent = &codec->dev;
170 input_set_drvdata(input_dev, beep); 172 input_set_drvdata(input_dev, beep);
171 173
172 err = input_register_device(input_dev);
173 if (err < 0) {
174 input_free_device(input_dev);
175 codec_err(codec, "hda_beep: unable to register input device\n");
176 return err;
177 }
178 beep->dev = input_dev; 174 beep->dev = input_dev;
179 return 0; 175 return 0;
180} 176}
@@ -244,6 +240,27 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
244} 240}
245EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device); 241EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
246 242
243int snd_hda_register_beep_device(struct hda_codec *codec)
244{
245 struct hda_beep *beep = codec->beep;
246 int err;
247
248 if (!beep || !beep->dev)
249 return 0;
250
251 err = input_register_device(beep->dev);
252 if (err < 0) {
253 codec_err(codec, "hda_beep: unable to register input device\n");
254 input_free_device(beep->dev);
255 codec->beep = NULL;
256 kfree(beep);
257 return err;
258 }
259 beep->registered = true;
260 return 0;
261}
262EXPORT_SYMBOL_GPL(snd_hda_register_beep_device);
263
247static bool ctl_has_mute(struct snd_kcontrol *kcontrol) 264static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
248{ 265{
249 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 266 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h
index cb88464676b6..a63b5e077332 100644
--- a/sound/pci/hda/hda_beep.h
+++ b/sound/pci/hda/hda_beep.h
@@ -34,6 +34,7 @@ struct hda_beep {
34 char phys[32]; 34 char phys[32];
35 int tone; 35 int tone;
36 hda_nid_t nid; 36 hda_nid_t nid;
37 unsigned int registered:1;
37 unsigned int enabled:1; 38 unsigned int enabled:1;
38 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ 39 unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
39 unsigned int playing:1; 40 unsigned int playing:1;
@@ -45,6 +46,7 @@ struct hda_beep {
45int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); 46int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
46int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); 47int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
47void snd_hda_detach_beep_device(struct hda_codec *codec); 48void snd_hda_detach_beep_device(struct hda_codec *codec);
49int snd_hda_register_beep_device(struct hda_codec *codec);
48#else 50#else
49static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) 51static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
50{ 52{
@@ -53,5 +55,9 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
53static inline void snd_hda_detach_beep_device(struct hda_codec *codec) 55static inline void snd_hda_detach_beep_device(struct hda_codec *codec)
54{ 56{
55} 57}
58static inline int snd_hda_register_beep_device(struct hda_codec *codec)
59{
60 return 0;
61}
56#endif 62#endif
57#endif 63#endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 6db2dbcbf4d3..4c20277a6835 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1379,14 +1379,19 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
1379static int snd_hda_codec_dev_register(struct snd_device *device) 1379static int snd_hda_codec_dev_register(struct snd_device *device)
1380{ 1380{
1381 struct hda_codec *codec = device->device_data; 1381 struct hda_codec *codec = device->device_data;
1382 int err = device_add(&codec->dev);
1382 1383
1383 return device_add(&codec->dev); 1384 if (err < 0)
1385 return err;
1386 snd_hda_register_beep_device(codec);
1387 return 0;
1384} 1388}
1385 1389
1386static int snd_hda_codec_dev_disconnect(struct snd_device *device) 1390static int snd_hda_codec_dev_disconnect(struct snd_device *device)
1387{ 1391{
1388 struct hda_codec *codec = device->device_data; 1392 struct hda_codec *codec = device->device_data;
1389 1393
1394 snd_hda_detach_beep_device(codec);
1390 device_del(&codec->dev); 1395 device_del(&codec->dev);
1391 return 0; 1396 return 0;
1392} 1397}
@@ -2692,6 +2697,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
2692 bus->pcm_dev_bits); 2697 bus->pcm_dev_bits);
2693 } 2698 }
2694 } 2699 }
2700 snd_hda_detach_beep_device(codec);
2695 if (codec->patch_ops.free) 2701 if (codec->patch_ops.free)
2696 codec->patch_ops.free(codec); 2702 codec->patch_ops.free(codec);
2697 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); 2703 memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 9e0609a4b2ba..16133881e967 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -5350,7 +5350,6 @@ EXPORT_SYMBOL_GPL(snd_hda_gen_init);
5350void snd_hda_gen_free(struct hda_codec *codec) 5350void snd_hda_gen_free(struct hda_codec *codec)
5351{ 5351{
5352 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); 5352 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
5353 snd_hda_detach_beep_device(codec);
5354 snd_hda_gen_spec_free(codec->spec); 5353 snd_hda_gen_spec_free(codec->spec);
5355 kfree(codec->spec); 5354 kfree(codec->spec);
5356 codec->spec = NULL; 5355 codec->spec = NULL;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 09d6d0db2b06..1dc7e974f3b1 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -445,9 +445,7 @@ static int conexant_init(struct hda_codec *codec)
445 445
446static void conexant_free(struct hda_codec *codec) 446static void conexant_free(struct hda_codec *codec)
447{ 447{
448 struct conexant_spec *spec = codec->spec; 448 kfree(codec->spec);
449 snd_hda_detach_beep_device(codec);
450 kfree(spec);
451} 449}
452 450
453static const struct snd_kcontrol_new cxt_capture_mixers[] = { 451static const struct snd_kcontrol_new cxt_capture_mixers[] = {