From: Stas Sergeev Added SND_SILENT event that permits us to disable (and enable) the driver, either to grant the hardware access to some other driver, or to disable the annoying beeps. Signed-off-by: Stas Sergeev Signed-off-by: Andrew Morton --- drivers/input/misc/pcspkr.c | 62 +++++++++++++++++++++++++++++++------------- include/linux/input.h | 1 2 files changed, 46 insertions(+), 17 deletions(-) diff -puN drivers/input/misc/pcspkr.c~pc-speaker-add-snd_silent drivers/input/misc/pcspkr.c --- devel/drivers/input/misc/pcspkr.c~pc-speaker-add-snd_silent 2005-11-09 19:56:19.000000000 -0800 +++ devel-akpm/drivers/input/misc/pcspkr.c 2005-11-09 19:56:19.000000000 -0800 @@ -25,25 +25,16 @@ MODULE_LICENSE("GPL"); static struct input_dev *pcspkr_dev; +/* Please replace this with i8253_lock to properly serialize an + * accesses to port 0x43 */ static DEFINE_SPINLOCK(i8253_beep_lock); -static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +enum { PCSPKR_NORMAL, PCSPKR_SUSPENDED }; + +static void pcspkr_do_sound(unsigned int count) { - unsigned int count = 0; unsigned long flags; - if (type != EV_SND) - return -1; - - switch (code) { - case SND_BELL: if (value) value = 1000; - case SND_TONE: break; - default: return -1; - } - - if (value > 20 && value < 32767) - count = PIT_TICK_RATE / value; - spin_lock_irqsave(&i8253_beep_lock, flags); if (count) { @@ -60,6 +51,40 @@ static int pcspkr_event(struct input_dev } spin_unlock_irqrestore(&i8253_beep_lock, flags); +} + +static int pcspkr_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) +{ + unsigned int count = 0; + + switch (type) { + case EV_SND: + switch (code) { + case SND_BELL: + if (value) + value = 1000; + case SND_TONE: + break; + case SND_SILENT: + dev->state = value ? PCSPKR_SUSPENDED : PCSPKR_NORMAL; + return 0; + default: + return -1; + } + break; + + default: + return -1; + } + + if (dev->state == PCSPKR_SUSPENDED) + return 0; + + if (value > 20 && value < 32767) + count = PIT_TICK_RATE / value; + + pcspkr_do_sound(count); return 0; } @@ -76,9 +101,10 @@ static int __init pcspkr_init(void) pcspkr_dev->id.vendor = 0x001f; pcspkr_dev->id.product = 0x0001; pcspkr_dev->id.version = 0x0100; + pcspkr_dev->state = PCSPKR_NORMAL; pcspkr_dev->evbit[0] = BIT(EV_SND); - pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); + pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE) | BIT(SND_SILENT); pcspkr_dev->event = pcspkr_event; input_register_device(pcspkr_dev); @@ -88,9 +114,11 @@ static int __init pcspkr_init(void) static void __exit pcspkr_exit(void) { + if (pcspkr_dev->state == PCSPKR_NORMAL) { + /* turn off the speaker */ + pcspkr_do_sound(0); + } input_unregister_device(pcspkr_dev); - /* turn off the speaker */ - pcspkr_event(NULL, EV_SND, SND_BELL, 0); } module_init(pcspkr_init); diff -puN include/linux/input.h~pc-speaker-add-snd_silent include/linux/input.h --- devel/include/linux/input.h~pc-speaker-add-snd_silent 2005-11-09 19:56:19.000000000 -0800 +++ devel-akpm/include/linux/input.h 2005-11-09 19:56:19.000000000 -0800 @@ -618,6 +618,7 @@ struct input_absinfo { #define SND_CLICK 0x00 #define SND_BELL 0x01 #define SND_TONE 0x02 +#define SND_SILENT 0x06 #define SND_MAX 0x07 /* _