diff options
Diffstat (limited to 'sound/pci/hda/hda_beep.c')
-rw-r--r-- | sound/pci/hda/hda_beep.c | 151 |
1 files changed, 72 insertions, 79 deletions
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 066b5b59c4d7..b7d9160ed868 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -127,44 +127,6 @@ static void turn_off_beep(struct hda_beep *beep) } } -static void snd_hda_do_detach(struct hda_beep *beep) -{ - if (beep->registered) - input_unregister_device(beep->dev); - else - input_free_device(beep->dev); - beep->dev = NULL; - turn_off_beep(beep); -} - -static int snd_hda_do_attach(struct hda_beep *beep) -{ - struct input_dev *input_dev; - struct hda_codec *codec = beep->codec; - - input_dev = input_allocate_device(); - if (!input_dev) - return -ENOMEM; - - /* setup digital beep device */ - input_dev->name = "HDA Digital PCBeep"; - input_dev->phys = beep->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->dev.parent = &codec->card->card_dev; - - input_dev->id.vendor = codec->core.vendor_id >> 16; - input_dev->id.product = codec->core.vendor_id & 0xffff; - input_dev->id.version = 0x01; - - input_dev->evbit[0] = BIT_MASK(EV_SND); - input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); - input_dev->event = snd_hda_beep_event; - input_set_drvdata(input_dev, beep); - - beep->dev = input_dev; - return 0; -} - /** * snd_hda_enable_beep_device - Turn on/off beep sound * @codec: the HDA codec @@ -186,6 +148,38 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) } EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device); +static int beep_dev_register(struct snd_device *device) +{ + struct hda_beep *beep = device->device_data; + int err; + + err = input_register_device(beep->dev); + if (!err) + beep->registered = true; + return err; +} + +static int beep_dev_disconnect(struct snd_device *device) +{ + struct hda_beep *beep = device->device_data; + + if (beep->registered) + input_unregister_device(beep->dev); + else + input_free_device(beep->dev); + turn_off_beep(beep); + return 0; +} + +static int beep_dev_free(struct snd_device *device) +{ + struct hda_beep *beep = device->device_data; + + beep->codec->beep = NULL; + kfree(beep); + return 0; +} + /** * snd_hda_attach_beep_device - Attach a beep input device * @codec: the HDA codec @@ -194,14 +188,16 @@ EXPORT_SYMBOL_GPL(snd_hda_enable_beep_device); * Attach a beep object to the given widget. If beep hint is turned off * explicitly or beep_mode of the codec is turned off, this doesn't nothing. * - * The attached beep device has to be registered via - * snd_hda_register_beep_device() and released via snd_hda_detach_beep_device() - * appropriately. - * * Currently, only one beep device is allowed to each codec. */ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) { + static struct snd_device_ops ops = { + .dev_register = beep_dev_register, + .dev_disconnect = beep_dev_disconnect, + .dev_free = beep_dev_free, + }; + struct input_dev *input_dev; struct hda_beep *beep; int err; @@ -226,14 +222,41 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); mutex_init(&beep->mutex); - err = snd_hda_do_attach(beep); - if (err < 0) { - kfree(beep); - codec->beep = NULL; - return err; + input_dev = input_allocate_device(); + if (!input_dev) { + err = -ENOMEM; + goto err_free; } + /* setup digital beep device */ + input_dev->name = "HDA Digital PCBeep"; + input_dev->phys = beep->phys; + input_dev->id.bustype = BUS_PCI; + input_dev->dev.parent = &codec->card->card_dev; + + input_dev->id.vendor = codec->core.vendor_id >> 16; + input_dev->id.product = codec->core.vendor_id & 0xffff; + input_dev->id.version = 0x01; + + input_dev->evbit[0] = BIT_MASK(EV_SND); + input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE); + input_dev->event = snd_hda_beep_event; + input_set_drvdata(input_dev, beep); + + beep->dev = input_dev; + + err = snd_device_new(codec->card, SNDRV_DEV_JACK, beep, &ops); + if (err < 0) + goto err_input; + return 0; + + err_input: + input_free_device(beep->dev); + err_free: + kfree(beep); + codec->beep = NULL; + return err; } EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device); @@ -243,41 +266,11 @@ EXPORT_SYMBOL_GPL(snd_hda_attach_beep_device); */ void snd_hda_detach_beep_device(struct hda_codec *codec) { - struct hda_beep *beep = codec->beep; - if (beep) { - if (beep->dev) - snd_hda_do_detach(beep); - codec->beep = NULL; - kfree(beep); - } + if (!codec->bus->shutdown && codec->beep) + snd_device_free(codec->card, codec->beep); } EXPORT_SYMBOL_GPL(snd_hda_detach_beep_device); -/** - * snd_hda_register_beep_device - Register the beep device - * @codec: the HDA codec - */ -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); |