pcsp_input.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * PC Speaker beeper driver for Linux
  3. *
  4. * Copyright (c) 2002 Vojtech Pavlik
  5. * Copyright (c) 1992 Orest Zborowski
  6. *
  7. */
  8. /*
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License version 2 as published by
  11. * the Free Software Foundation
  12. */
  13. #include <linux/init.h>
  14. #include <linux/input.h>
  15. #include <asm/io.h>
  16. #include "pcsp.h"
  17. static void pcspkr_do_sound(unsigned int count)
  18. {
  19. unsigned long flags;
  20. spin_lock_irqsave(&i8253_lock, flags);
  21. if (count) {
  22. /* set command for counter 2, 2 byte write */
  23. outb_p(0xB6, 0x43);
  24. /* select desired HZ */
  25. outb_p(count & 0xff, 0x42);
  26. outb((count >> 8) & 0xff, 0x42);
  27. /* enable counter 2 */
  28. outb_p(inb_p(0x61) | 3, 0x61);
  29. } else {
  30. /* disable counter 2 */
  31. outb(inb_p(0x61) & 0xFC, 0x61);
  32. }
  33. spin_unlock_irqrestore(&i8253_lock, flags);
  34. }
  35. void pcspkr_stop_sound(void)
  36. {
  37. pcspkr_do_sound(0);
  38. }
  39. static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
  40. unsigned int code, int value)
  41. {
  42. unsigned int count = 0;
  43. if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
  44. return 0;
  45. switch (type) {
  46. case EV_SND:
  47. switch (code) {
  48. case SND_BELL:
  49. if (value)
  50. value = 1000;
  51. case SND_TONE:
  52. break;
  53. default:
  54. return -1;
  55. }
  56. break;
  57. default:
  58. return -1;
  59. }
  60. if (value > 20 && value < 32767)
  61. count = PIT_TICK_RATE / value;
  62. pcspkr_do_sound(count);
  63. return 0;
  64. }
  65. int __devinit pcspkr_input_init(struct input_dev **rdev, struct device *dev)
  66. {
  67. int err;
  68. struct input_dev *input_dev = input_allocate_device();
  69. if (!input_dev)
  70. return -ENOMEM;
  71. input_dev->name = "PC Speaker";
  72. input_dev->phys = "isa0061/input0";
  73. input_dev->id.bustype = BUS_ISA;
  74. input_dev->id.vendor = 0x001f;
  75. input_dev->id.product = 0x0001;
  76. input_dev->id.version = 0x0100;
  77. input_dev->dev.parent = dev;
  78. input_dev->evbit[0] = BIT(EV_SND);
  79. input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
  80. input_dev->event = pcspkr_input_event;
  81. err = input_register_device(input_dev);
  82. if (err) {
  83. input_free_device(input_dev);
  84. return err;
  85. }
  86. *rdev = input_dev;
  87. return 0;
  88. }
  89. int pcspkr_input_remove(struct input_dev *dev)
  90. {
  91. pcspkr_stop_sound();
  92. input_unregister_device(dev); /* this also does kfree() */
  93. return 0;
  94. }