xref: /openbmc/linux/drivers/input/misc/m68kspkr.c (revision 1cb0aa88)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  m68k beeper driver for Linux
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (c) 2002 Richard Zidlicky
51da177e4SLinus Torvalds  *  Copyright (c) 2002 Vojtech Pavlik
61da177e4SLinus Torvalds  *  Copyright (c) 1992 Orest Zborowski
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds /*
111da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify it
121da177e4SLinus Torvalds  * under the terms of the GNU General Public License version 2 as published by
131da177e4SLinus Torvalds  * the Free Software Foundation
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/kernel.h>
171da177e4SLinus Torvalds #include <linux/module.h>
181da177e4SLinus Torvalds #include <linux/init.h>
191da177e4SLinus Torvalds #include <linux/input.h>
201f75e6bdSDmitry Torokhov #include <linux/platform_device.h>
211da177e4SLinus Torvalds #include <asm/machdep.h>
221da177e4SLinus Torvalds #include <asm/io.h>
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
251da177e4SLinus Torvalds MODULE_DESCRIPTION("m68k beeper driver");
261da177e4SLinus Torvalds MODULE_LICENSE("GPL");
271da177e4SLinus Torvalds 
281f75e6bdSDmitry Torokhov static struct platform_device *m68kspkr_platform_device;
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
311da177e4SLinus Torvalds {
321da177e4SLinus Torvalds 	unsigned int count = 0;
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds 	if (type != EV_SND)
351da177e4SLinus Torvalds 		return -1;
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 	switch (code) {
381da177e4SLinus Torvalds 		case SND_BELL: if (value) value = 1000;
391da177e4SLinus Torvalds 		case SND_TONE: break;
401da177e4SLinus Torvalds 		default: return -1;
411da177e4SLinus Torvalds 	}
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds 	if (value > 20 && value < 32767)
441da177e4SLinus Torvalds 		count = 1193182 / value;
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 	mach_beep(count, -1);
471da177e4SLinus Torvalds 
481da177e4SLinus Torvalds 	return 0;
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds 
511f75e6bdSDmitry Torokhov static int __devinit m68kspkr_probe(struct platform_device *dev)
521f75e6bdSDmitry Torokhov {
531f75e6bdSDmitry Torokhov 	struct input_dev *input_dev;
541f75e6bdSDmitry Torokhov 	int err;
551f75e6bdSDmitry Torokhov 
561f75e6bdSDmitry Torokhov 	input_dev = input_allocate_device();
571f75e6bdSDmitry Torokhov 	if (!input_dev)
581f75e6bdSDmitry Torokhov 		return -ENOMEM;
591f75e6bdSDmitry Torokhov 
601f75e6bdSDmitry Torokhov 	input_dev->name = "m68k beeper";
611f75e6bdSDmitry Torokhov 	input_dev->phys = "m68k/generic";
621f75e6bdSDmitry Torokhov 	input_dev->id.bustype = BUS_HOST;
631f75e6bdSDmitry Torokhov 	input_dev->id.vendor  = 0x001f;
641f75e6bdSDmitry Torokhov 	input_dev->id.product = 0x0001;
651f75e6bdSDmitry Torokhov 	input_dev->id.version = 0x0100;
66293e6392SDmitry Torokhov 	input_dev->dev.parent = &dev->dev;
671f75e6bdSDmitry Torokhov 
687b19ada2SJiri Slaby 	input_dev->evbit[0] = BIT_MASK(EV_SND);
697b19ada2SJiri Slaby 	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
701f75e6bdSDmitry Torokhov 	input_dev->event = m68kspkr_event;
711f75e6bdSDmitry Torokhov 
721f75e6bdSDmitry Torokhov 	err = input_register_device(input_dev);
731f75e6bdSDmitry Torokhov 	if (err) {
741f75e6bdSDmitry Torokhov 		input_free_device(input_dev);
751f75e6bdSDmitry Torokhov 		return err;
761f75e6bdSDmitry Torokhov 	}
771f75e6bdSDmitry Torokhov 
781f75e6bdSDmitry Torokhov 	platform_set_drvdata(dev, input_dev);
791f75e6bdSDmitry Torokhov 
801f75e6bdSDmitry Torokhov 	return 0;
811f75e6bdSDmitry Torokhov }
821f75e6bdSDmitry Torokhov 
831f75e6bdSDmitry Torokhov static int __devexit m68kspkr_remove(struct platform_device *dev)
841f75e6bdSDmitry Torokhov {
851f75e6bdSDmitry Torokhov 	struct input_dev *input_dev = platform_get_drvdata(dev);
861f75e6bdSDmitry Torokhov 
871f75e6bdSDmitry Torokhov 	input_unregister_device(input_dev);
881f75e6bdSDmitry Torokhov 	platform_set_drvdata(dev, NULL);
891f75e6bdSDmitry Torokhov 	/* turn off the speaker */
901f75e6bdSDmitry Torokhov 	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
911f75e6bdSDmitry Torokhov 
921f75e6bdSDmitry Torokhov 	return 0;
931f75e6bdSDmitry Torokhov }
941f75e6bdSDmitry Torokhov 
951f75e6bdSDmitry Torokhov static void m68kspkr_shutdown(struct platform_device *dev)
961f75e6bdSDmitry Torokhov {
971f75e6bdSDmitry Torokhov 	/* turn off the speaker */
981f75e6bdSDmitry Torokhov 	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
991f75e6bdSDmitry Torokhov }
1001f75e6bdSDmitry Torokhov 
1011f75e6bdSDmitry Torokhov static struct platform_driver m68kspkr_platform_driver = {
1021f75e6bdSDmitry Torokhov 	.driver		= {
1031f75e6bdSDmitry Torokhov 		.name	= "m68kspkr",
1041f75e6bdSDmitry Torokhov 		.owner	= THIS_MODULE,
1051f75e6bdSDmitry Torokhov 	},
1061f75e6bdSDmitry Torokhov 	.probe		= m68kspkr_probe,
1071cb0aa88SBill Pemberton 	.remove		= m68kspkr_remove,
1081f75e6bdSDmitry Torokhov 	.shutdown	= m68kspkr_shutdown,
1091f75e6bdSDmitry Torokhov };
1101f75e6bdSDmitry Torokhov 
1111da177e4SLinus Torvalds static int __init m68kspkr_init(void)
1121da177e4SLinus Torvalds {
1131f75e6bdSDmitry Torokhov 	int err;
1141f75e6bdSDmitry Torokhov 
1151da177e4SLinus Torvalds 	if (!mach_beep) {
11676b7cddfSDmitry Torokhov 		printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
11776b7cddfSDmitry Torokhov 		return -ENODEV;
1181da177e4SLinus Torvalds         }
1191da177e4SLinus Torvalds 
1201f75e6bdSDmitry Torokhov 	err = platform_driver_register(&m68kspkr_platform_driver);
1211f75e6bdSDmitry Torokhov 	if (err)
1221f75e6bdSDmitry Torokhov 		return err;
1231da177e4SLinus Torvalds 
1241f75e6bdSDmitry Torokhov 	m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
1251f75e6bdSDmitry Torokhov 	if (!m68kspkr_platform_device) {
1261f75e6bdSDmitry Torokhov 		err = -ENOMEM;
1271f75e6bdSDmitry Torokhov 		goto err_unregister_driver;
1281f75e6bdSDmitry Torokhov 	}
1291da177e4SLinus Torvalds 
1301f75e6bdSDmitry Torokhov 	err = platform_device_add(m68kspkr_platform_device);
1311f75e6bdSDmitry Torokhov 	if (err)
1321f75e6bdSDmitry Torokhov 		goto err_free_device;
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	return 0;
1351f75e6bdSDmitry Torokhov 
1361f75e6bdSDmitry Torokhov  err_free_device:
1371f75e6bdSDmitry Torokhov 	platform_device_put(m68kspkr_platform_device);
1381f75e6bdSDmitry Torokhov  err_unregister_driver:
1391f75e6bdSDmitry Torokhov 	platform_driver_unregister(&m68kspkr_platform_driver);
1401f75e6bdSDmitry Torokhov 
1411f75e6bdSDmitry Torokhov 	return err;
1421da177e4SLinus Torvalds }
1431da177e4SLinus Torvalds 
1441da177e4SLinus Torvalds static void __exit m68kspkr_exit(void)
1451da177e4SLinus Torvalds {
1461f75e6bdSDmitry Torokhov 	platform_device_unregister(m68kspkr_platform_device);
1471f75e6bdSDmitry Torokhov 	platform_driver_unregister(&m68kspkr_platform_driver);
1481da177e4SLinus Torvalds }
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds module_init(m68kspkr_init);
1511da177e4SLinus Torvalds module_exit(m68kspkr_exit);
152