sparcspkr.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Driver for PC-speaker like devices found on various Sparc systems.
  3. *
  4. * Copyright (c) 2002 Vojtech Pavlik
  5. * Copyright (c) 2002 David S. Miller (davem@redhat.com)
  6. */
  7. #include <linux/config.h>
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include <linux/input.h>
  12. #include <asm/io.h>
  13. #include <asm/ebus.h>
  14. #ifdef CONFIG_SPARC64
  15. #include <asm/isa.h>
  16. #endif
  17. MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
  18. MODULE_DESCRIPTION("Sparc Speaker beeper driver");
  19. MODULE_LICENSE("GPL");
  20. static unsigned long beep_iobase;
  21. static struct input_dev *sparcspkr_dev;
  22. DEFINE_SPINLOCK(beep_lock);
  23. static void __init init_sparcspkr_struct(void)
  24. {
  25. sparcspkr_dev->evbit[0] = BIT(EV_SND);
  26. sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
  27. sparcspkr_dev->phys = "sparc/input0";
  28. sparcspkr_dev->id.bustype = BUS_ISA;
  29. sparcspkr_dev->id.vendor = 0x001f;
  30. sparcspkr_dev->id.product = 0x0001;
  31. sparcspkr_dev->id.version = 0x0100;
  32. }
  33. static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
  34. {
  35. unsigned int count = 0;
  36. unsigned long flags;
  37. if (type != EV_SND)
  38. return -1;
  39. switch (code) {
  40. case SND_BELL: if (value) value = 1000;
  41. case SND_TONE: break;
  42. default: return -1;
  43. }
  44. if (value > 20 && value < 32767)
  45. count = 1193182 / value;
  46. spin_lock_irqsave(&beep_lock, flags);
  47. /* EBUS speaker only has on/off state, the frequency does not
  48. * appear to be programmable.
  49. */
  50. if (count) {
  51. if (beep_iobase & 0x2UL)
  52. outb(1, beep_iobase);
  53. else
  54. outl(1, beep_iobase);
  55. } else {
  56. if (beep_iobase & 0x2UL)
  57. outb(0, beep_iobase);
  58. else
  59. outl(0, beep_iobase);
  60. }
  61. spin_unlock_irqrestore(&beep_lock, flags);
  62. return 0;
  63. }
  64. static int __init init_ebus_beep(struct linux_ebus_device *edev)
  65. {
  66. beep_iobase = edev->resource[0].start;
  67. sparcspkr_dev = input_allocate_device();
  68. if (!sparcspkr_dev)
  69. return -ENOMEM;
  70. sparcspkr_dev->name = "Sparc EBUS Speaker";
  71. sparcspkr_dev->event = ebus_spkr_event;
  72. input_register_device(sparcspkr_dev);
  73. return 0;
  74. }
  75. #ifdef CONFIG_SPARC64
  76. static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
  77. {
  78. unsigned int count = 0;
  79. unsigned long flags;
  80. if (type != EV_SND)
  81. return -1;
  82. switch (code) {
  83. case SND_BELL: if (value) value = 1000;
  84. case SND_TONE: break;
  85. default: return -1;
  86. }
  87. if (value > 20 && value < 32767)
  88. count = 1193182 / value;
  89. spin_lock_irqsave(&beep_lock, flags);
  90. if (count) {
  91. /* enable counter 2 */
  92. outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61);
  93. /* set command for counter 2, 2 byte write */
  94. outb(0xB6, beep_iobase + 0x43);
  95. /* select desired HZ */
  96. outb(count & 0xff, beep_iobase + 0x42);
  97. outb((count >> 8) & 0xff, beep_iobase + 0x42);
  98. } else {
  99. /* disable counter 2 */
  100. outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61);
  101. }
  102. spin_unlock_irqrestore(&beep_lock, flags);
  103. return 0;
  104. }
  105. static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
  106. {
  107. beep_iobase = isa_dev->resource.start;
  108. sparcspkr_dev = input_allocate_device();
  109. if (!sparcspkr_dev)
  110. return -ENOMEM;
  111. init_sparcspkr_struct();
  112. sparcspkr_dev->name = "Sparc ISA Speaker";
  113. sparcspkr_dev->event = isa_spkr_event;
  114. input_register_device(sparcspkr_dev);
  115. return 0;
  116. }
  117. #endif
  118. static int __init sparcspkr_init(void)
  119. {
  120. struct linux_ebus *ebus;
  121. struct linux_ebus_device *edev = NULL;
  122. #ifdef CONFIG_SPARC64
  123. struct sparc_isa_bridge *isa_br;
  124. struct sparc_isa_device *isa_dev;
  125. #endif
  126. for_each_ebus(ebus) {
  127. for_each_ebusdev(edev, ebus) {
  128. if (!strcmp(edev->prom_name, "beep"))
  129. return init_ebus_beep(edev);
  130. }
  131. }
  132. #ifdef CONFIG_SPARC64
  133. for_each_isa(isa_br) {
  134. for_each_isadev(isa_dev, isa_br) {
  135. /* A hack, the beep device's base lives in
  136. * the DMA isa node.
  137. */
  138. if (!strcmp(isa_dev->prom_name, "dma"))
  139. return init_isa_beep(isa_dev);
  140. }
  141. }
  142. #endif
  143. return -ENODEV;
  144. }
  145. static void __exit sparcspkr_exit(void)
  146. {
  147. input_unregister_device(sparcspkr_dev);
  148. }
  149. module_init(sparcspkr_init);
  150. module_exit(sparcspkr_exit);