xref: /linux/drivers/input/misc/m68kspkr.c (revision 6d3a5b82)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  m68k beeper driver for Linux
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (c) 2002 Richard Zidlicky
61da177e4SLinus Torvalds  *  Copyright (c) 2002 Vojtech Pavlik
71da177e4SLinus Torvalds  *  Copyright (c) 1992 Orest Zborowski
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/kernel.h>
121da177e4SLinus Torvalds #include <linux/module.h>
131da177e4SLinus Torvalds #include <linux/init.h>
141da177e4SLinus Torvalds #include <linux/input.h>
151f75e6bdSDmitry Torokhov #include <linux/platform_device.h>
161da177e4SLinus Torvalds #include <asm/machdep.h>
171da177e4SLinus Torvalds #include <asm/io.h>
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
201da177e4SLinus Torvalds MODULE_DESCRIPTION("m68k beeper driver");
211da177e4SLinus Torvalds MODULE_LICENSE("GPL");
221da177e4SLinus Torvalds 
231f75e6bdSDmitry Torokhov static struct platform_device *m68kspkr_platform_device;
241da177e4SLinus Torvalds 
m68kspkr_event(struct input_dev * dev,unsigned int type,unsigned int code,int value)251da177e4SLinus Torvalds static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
261da177e4SLinus Torvalds {
271da177e4SLinus Torvalds 	unsigned int count = 0;
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds 	if (type != EV_SND)
301da177e4SLinus Torvalds 		return -1;
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds 	switch (code) {
331da177e4SLinus Torvalds 		case SND_BELL: if (value) value = 1000;
341da177e4SLinus Torvalds 		case SND_TONE: break;
351da177e4SLinus Torvalds 		default: return -1;
361da177e4SLinus Torvalds 	}
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds 	if (value > 20 && value < 32767)
391da177e4SLinus Torvalds 		count = 1193182 / value;
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds 	mach_beep(count, -1);
421da177e4SLinus Torvalds 
431da177e4SLinus Torvalds 	return 0;
441da177e4SLinus Torvalds }
451da177e4SLinus Torvalds 
m68kspkr_probe(struct platform_device * dev)465298cc4cSBill Pemberton static int m68kspkr_probe(struct platform_device *dev)
471f75e6bdSDmitry Torokhov {
481f75e6bdSDmitry Torokhov 	struct input_dev *input_dev;
491f75e6bdSDmitry Torokhov 	int err;
501f75e6bdSDmitry Torokhov 
511f75e6bdSDmitry Torokhov 	input_dev = input_allocate_device();
521f75e6bdSDmitry Torokhov 	if (!input_dev)
531f75e6bdSDmitry Torokhov 		return -ENOMEM;
541f75e6bdSDmitry Torokhov 
551f75e6bdSDmitry Torokhov 	input_dev->name = "m68k beeper";
561f75e6bdSDmitry Torokhov 	input_dev->phys = "m68k/generic";
571f75e6bdSDmitry Torokhov 	input_dev->id.bustype = BUS_HOST;
581f75e6bdSDmitry Torokhov 	input_dev->id.vendor  = 0x001f;
591f75e6bdSDmitry Torokhov 	input_dev->id.product = 0x0001;
601f75e6bdSDmitry Torokhov 	input_dev->id.version = 0x0100;
61293e6392SDmitry Torokhov 	input_dev->dev.parent = &dev->dev;
621f75e6bdSDmitry Torokhov 
637b19ada2SJiri Slaby 	input_dev->evbit[0] = BIT_MASK(EV_SND);
647b19ada2SJiri Slaby 	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
651f75e6bdSDmitry Torokhov 	input_dev->event = m68kspkr_event;
661f75e6bdSDmitry Torokhov 
671f75e6bdSDmitry Torokhov 	err = input_register_device(input_dev);
681f75e6bdSDmitry Torokhov 	if (err) {
691f75e6bdSDmitry Torokhov 		input_free_device(input_dev);
701f75e6bdSDmitry Torokhov 		return err;
711f75e6bdSDmitry Torokhov 	}
721f75e6bdSDmitry Torokhov 
731f75e6bdSDmitry Torokhov 	platform_set_drvdata(dev, input_dev);
741f75e6bdSDmitry Torokhov 
751f75e6bdSDmitry Torokhov 	return 0;
761f75e6bdSDmitry Torokhov }
771f75e6bdSDmitry Torokhov 
m68kspkr_remove(struct platform_device * dev)78*6d3a5b82SUwe Kleine-König static void m68kspkr_remove(struct platform_device *dev)
791f75e6bdSDmitry Torokhov {
801f75e6bdSDmitry Torokhov 	struct input_dev *input_dev = platform_get_drvdata(dev);
811f75e6bdSDmitry Torokhov 
821f75e6bdSDmitry Torokhov 	input_unregister_device(input_dev);
831f75e6bdSDmitry Torokhov 	/* turn off the speaker */
841f75e6bdSDmitry Torokhov 	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
851f75e6bdSDmitry Torokhov }
861f75e6bdSDmitry Torokhov 
m68kspkr_shutdown(struct platform_device * dev)871f75e6bdSDmitry Torokhov static void m68kspkr_shutdown(struct platform_device *dev)
881f75e6bdSDmitry Torokhov {
891f75e6bdSDmitry Torokhov 	/* turn off the speaker */
901f75e6bdSDmitry Torokhov 	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
911f75e6bdSDmitry Torokhov }
921f75e6bdSDmitry Torokhov 
931f75e6bdSDmitry Torokhov static struct platform_driver m68kspkr_platform_driver = {
941f75e6bdSDmitry Torokhov 	.driver		= {
951f75e6bdSDmitry Torokhov 		.name	= "m68kspkr",
961f75e6bdSDmitry Torokhov 	},
971f75e6bdSDmitry Torokhov 	.probe		= m68kspkr_probe,
98*6d3a5b82SUwe Kleine-König 	.remove_new	= m68kspkr_remove,
991f75e6bdSDmitry Torokhov 	.shutdown	= m68kspkr_shutdown,
1001f75e6bdSDmitry Torokhov };
1011f75e6bdSDmitry Torokhov 
m68kspkr_init(void)1021da177e4SLinus Torvalds static int __init m68kspkr_init(void)
1031da177e4SLinus Torvalds {
1041f75e6bdSDmitry Torokhov 	int err;
1051f75e6bdSDmitry Torokhov 
1061da177e4SLinus Torvalds 	if (!mach_beep) {
10776b7cddfSDmitry Torokhov 		printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
10876b7cddfSDmitry Torokhov 		return -ENODEV;
1091da177e4SLinus Torvalds         }
1101da177e4SLinus Torvalds 
1111f75e6bdSDmitry Torokhov 	err = platform_driver_register(&m68kspkr_platform_driver);
1121f75e6bdSDmitry Torokhov 	if (err)
1131f75e6bdSDmitry Torokhov 		return err;
1141da177e4SLinus Torvalds 
1151f75e6bdSDmitry Torokhov 	m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
1161f75e6bdSDmitry Torokhov 	if (!m68kspkr_platform_device) {
1171f75e6bdSDmitry Torokhov 		err = -ENOMEM;
1181f75e6bdSDmitry Torokhov 		goto err_unregister_driver;
1191f75e6bdSDmitry Torokhov 	}
1201da177e4SLinus Torvalds 
1211f75e6bdSDmitry Torokhov 	err = platform_device_add(m68kspkr_platform_device);
1221f75e6bdSDmitry Torokhov 	if (err)
1231f75e6bdSDmitry Torokhov 		goto err_free_device;
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds 	return 0;
1261f75e6bdSDmitry Torokhov 
1271f75e6bdSDmitry Torokhov  err_free_device:
1281f75e6bdSDmitry Torokhov 	platform_device_put(m68kspkr_platform_device);
1291f75e6bdSDmitry Torokhov  err_unregister_driver:
1301f75e6bdSDmitry Torokhov 	platform_driver_unregister(&m68kspkr_platform_driver);
1311f75e6bdSDmitry Torokhov 
1321f75e6bdSDmitry Torokhov 	return err;
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
m68kspkr_exit(void)1351da177e4SLinus Torvalds static void __exit m68kspkr_exit(void)
1361da177e4SLinus Torvalds {
1371f75e6bdSDmitry Torokhov 	platform_device_unregister(m68kspkr_platform_device);
1381f75e6bdSDmitry Torokhov 	platform_driver_unregister(&m68kspkr_platform_driver);
1391da177e4SLinus Torvalds }
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds module_init(m68kspkr_init);
1421da177e4SLinus Torvalds module_exit(m68kspkr_exit);
143