pcsp_input.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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 <linux/io.h>
  16. #include "pcsp.h"
  17. #include "pcsp_input.h"
  18. static void pcspkr_do_sound(unsigned int count)
  19. {
  20. unsigned long flags;
  21. raw_spin_lock_irqsave(&i8253_lock, flags);
  22. if (count) {
  23. /* set command for counter 2, 2 byte write */
  24. outb_p(0xB6, 0x43);
  25. /* select desired HZ */
  26. outb_p(count & 0xff, 0x42);
  27. outb((count >> 8) & 0xff, 0x42);
  28. /* enable counter 2 */
  29. outb_p(inb_p(0x61) | 3, 0x61);
  30. } else {
  31. /* disable counter 2 */
  32. outb(inb_p(0x61) & 0xFC, 0x61);
  33. }
  34. raw_spin_unlock_irqrestore(&i8253_lock, flags);
  35. }
  36. void pcspkr_stop_sound(void)
  37. {
  38. pcspkr_do_sound(0);
  39. }
  40. static int pcspkr_input_event(struct input_dev *dev, unsigned int type,
  41. unsigned int code, int value)
  42. {
  43. unsigned int count = 0;
  44. if (atomic_read(&pcsp_chip.timer_active) || !pcsp_chip.pcspkr)
  45. return 0;
  46. switch (type) {
  47. case EV_SND:
  48. switch (code) {
  49. case SND_BELL:
  50. if (value)
  51. value = 1000;
  52. case SND_TONE:
  53. break;
  54. default:
  55. return -1;
  56. }
  57. break;
  58. default:
  59. return -1;
  60. }
  61. if (value > 20 && value < 32767)
  62. count = PIT_TICK_RATE / value;
  63. pcspkr_do_sound(count);
  64. return 0;
  65. }
  66. int pcspkr_input_init(struct input_dev **rdev, struct device *dev)
  67. {
  68. int err;
  69. struct input_dev *input_dev = input_allocate_device();
  70. if (!input_dev)
  71. return -ENOMEM;
  72. input_dev->name = "PC Speaker";
  73. input_dev->phys = "isa0061/input0";
  74. input_dev->id.bustype = BUS_ISA;
  75. input_dev->id.vendor = 0x001f;
  76. input_dev->id.product = 0x0001;
  77. input_dev->id.version = 0x0100;
  78. input_dev->dev.parent = dev;
  79. input_dev->evbit[0] = BIT(EV_SND);
  80. input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
  81. input_dev->event = pcspkr_input_event;
  82. err = input_register_device(input_dev);
  83. if (err) {
  84. input_free_device(input_dev);
  85. return err;
  86. }
  87. *rdev = input_dev;
  88. return 0;
  89. }
  90. int pcspkr_input_remove(struct input_dev *dev)
  91. {
  92. pcspkr_stop_sound();
  93. input_unregister_device(dev); /* this also does kfree() */
  94. return 0;
  95. }