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 515298cc4cSBill Pemberton static int 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 83e2619cf7SBill Pemberton static int 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