xref: /openbmc/linux/drivers/input/misc/m68kspkr.c (revision d2912cb1)
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)78e2619cf7SBill Pemberton static int 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 	return 0;
871f75e6bdSDmitry Torokhov }
881f75e6bdSDmitry Torokhov 
m68kspkr_shutdown(struct platform_device * dev)891f75e6bdSDmitry Torokhov static void m68kspkr_shutdown(struct platform_device *dev)
901f75e6bdSDmitry Torokhov {
911f75e6bdSDmitry Torokhov 	/* turn off the speaker */
921f75e6bdSDmitry Torokhov 	m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
931f75e6bdSDmitry Torokhov }
941f75e6bdSDmitry Torokhov 
951f75e6bdSDmitry Torokhov static struct platform_driver m68kspkr_platform_driver = {
961f75e6bdSDmitry Torokhov 	.driver		= {
971f75e6bdSDmitry Torokhov 		.name	= "m68kspkr",
981f75e6bdSDmitry Torokhov 	},
991f75e6bdSDmitry Torokhov 	.probe		= m68kspkr_probe,
1001cb0aa88SBill Pemberton 	.remove		= m68kspkr_remove,
1011f75e6bdSDmitry Torokhov 	.shutdown	= m68kspkr_shutdown,
1021f75e6bdSDmitry Torokhov };
1031f75e6bdSDmitry Torokhov 
m68kspkr_init(void)1041da177e4SLinus Torvalds static int __init m68kspkr_init(void)
1051da177e4SLinus Torvalds {
1061f75e6bdSDmitry Torokhov 	int err;
1071f75e6bdSDmitry Torokhov 
1081da177e4SLinus Torvalds 	if (!mach_beep) {
10976b7cddfSDmitry Torokhov 		printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
11076b7cddfSDmitry Torokhov 		return -ENODEV;
1111da177e4SLinus Torvalds         }
1121da177e4SLinus Torvalds 
1131f75e6bdSDmitry Torokhov 	err = platform_driver_register(&m68kspkr_platform_driver);
1141f75e6bdSDmitry Torokhov 	if (err)
1151f75e6bdSDmitry Torokhov 		return err;
1161da177e4SLinus Torvalds 
1171f75e6bdSDmitry Torokhov 	m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
1181f75e6bdSDmitry Torokhov 	if (!m68kspkr_platform_device) {
1191f75e6bdSDmitry Torokhov 		err = -ENOMEM;
1201f75e6bdSDmitry Torokhov 		goto err_unregister_driver;
1211f75e6bdSDmitry Torokhov 	}
1221da177e4SLinus Torvalds 
1231f75e6bdSDmitry Torokhov 	err = platform_device_add(m68kspkr_platform_device);
1241f75e6bdSDmitry Torokhov 	if (err)
1251f75e6bdSDmitry Torokhov 		goto err_free_device;
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 	return 0;
1281f75e6bdSDmitry Torokhov 
1291f75e6bdSDmitry Torokhov  err_free_device:
1301f75e6bdSDmitry Torokhov 	platform_device_put(m68kspkr_platform_device);
1311f75e6bdSDmitry Torokhov  err_unregister_driver:
1321f75e6bdSDmitry Torokhov 	platform_driver_unregister(&m68kspkr_platform_driver);
1331f75e6bdSDmitry Torokhov 
1341f75e6bdSDmitry Torokhov 	return err;
1351da177e4SLinus Torvalds }
1361da177e4SLinus Torvalds 
m68kspkr_exit(void)1371da177e4SLinus Torvalds static void __exit m68kspkr_exit(void)
1381da177e4SLinus Torvalds {
1391f75e6bdSDmitry Torokhov 	platform_device_unregister(m68kspkr_platform_device);
1401f75e6bdSDmitry Torokhov 	platform_driver_unregister(&m68kspkr_platform_driver);
1411da177e4SLinus Torvalds }
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds module_init(m68kspkr_init);
1441da177e4SLinus Torvalds module_exit(m68kspkr_exit);
145