1*d2912cb1SThomas 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