Commit 45571bb8 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Use standard device registration for beep

Currently the registration and free of beep input device was done
manually from the register and the disconnect callbacks of the
assigned codec object.  This seems working in most cases, but this may
be a cause of some races at probe.  Moreover, due to these manual
calls, the total code became unnecessarily lengthy.

This patch rewrites the beep registration code to follow the standard
sound device object style.  This allows us reducing the code, in
addition to avoiding the nested device registration calls.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 9a19c902
......@@ -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);
......
......@@ -34,7 +34,6 @@ struct hda_beep {
int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
void snd_hda_detach_beep_device(struct hda_codec *codec);
int snd_hda_register_beep_device(struct hda_codec *codec);
#else
static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
{
......@@ -43,9 +42,5 @@ static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
static inline void snd_hda_detach_beep_device(struct hda_codec *codec)
{
}
static inline int snd_hda_register_beep_device(struct hda_codec *codec)
{
return 0;
}
#endif
#endif
......@@ -813,7 +813,6 @@ void snd_hda_codec_register(struct hda_codec *codec)
if (codec->registered)
return;
if (device_is_registered(hda_codec_dev(codec))) {
snd_hda_register_beep_device(codec);
codec_display_power(codec, true);
pm_runtime_enable(hda_codec_dev(codec));
/* it was powered up in snd_hda_codec_new(), now all done */
......@@ -828,14 +827,6 @@ static int snd_hda_codec_dev_register(struct snd_device *device)
return 0;
}
static int snd_hda_codec_dev_disconnect(struct snd_device *device)
{
struct hda_codec *codec = device->device_data;
snd_hda_detach_beep_device(codec);
return 0;
}
static int snd_hda_codec_dev_free(struct snd_device *device)
{
struct hda_codec *codec = device->device_data;
......@@ -921,7 +912,6 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
int err;
static struct snd_device_ops dev_ops = {
.dev_register = snd_hda_codec_dev_register,
.dev_disconnect = snd_hda_codec_dev_disconnect,
.dev_free = snd_hda_codec_dev_free,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment