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