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>
This commit is contained in:
@@ -139,7 +139,10 @@ static void turn_off_beep(struct hda_beep *beep)
|
||||
|
||||
static void snd_hda_do_detach(struct hda_beep *beep)
|
||||
{
|
||||
input_unregister_device(beep->dev);
|
||||
if (beep->registered)
|
||||
input_unregister_device(beep->dev);
|
||||
else
|
||||
input_free_device(beep->dev);
|
||||
beep->dev = NULL;
|
||||
turn_off_beep(beep);
|
||||
}
|
||||
@@ -148,7 +151,6 @@ static int snd_hda_do_attach(struct hda_beep *beep)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
struct hda_codec *codec = beep->codec;
|
||||
int err;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
@@ -169,12 +171,6 @@ static int snd_hda_do_attach(struct hda_beep *beep)
|
||||
input_dev->dev.parent = &codec->dev;
|
||||
input_set_drvdata(input_dev, beep);
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err < 0) {
|
||||
input_free_device(input_dev);
|
||||
codec_err(codec, "hda_beep: unable to register input device\n");
|
||||
return err;
|
||||
}
|
||||
beep->dev = input_dev;
|
||||
return 0;
|
||||
}
|
||||
@@ -244,6 +240,27 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device);
|
||||
|
||||
int snd_hda_register_beep_device(struct hda_codec *codec)
|
||||
{
|
||||
struct hda_beep *beep = codec->beep;
|
||||
int err;
|
||||
|
||||
if (!beep || !beep->dev)
|
||||
return 0;
|
||||
|
||||
err = input_register_device(beep->dev);
|
||||
if (err < 0) {
|
||||
codec_err(codec, "hda_beep: unable to register input device\n");
|
||||
input_free_device(beep->dev);
|
||||
codec->beep = NULL;
|
||||
kfree(beep);
|
||||
return err;
|
||||
}
|
||||
beep->registered = true;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_register_beep_device);
|
||||
|
||||
static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
|
||||
{
|
||||
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
||||
|
Reference in New Issue
Block a user