sparcspkr.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * Driver for PC-speaker like devices found on various Sparc systems.
  3. *
  4. * Copyright (c) 2002 Vojtech Pavlik
  5. * Copyright (c) 2002, 2006, 2008 David S. Miller (davem@davemloft.net)
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/init.h>
  10. #include <linux/input.h>
  11. #include <linux/of_device.h>
  12. #include <asm/io.h>
  13. MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
  14. MODULE_DESCRIPTION("Sparc Speaker beeper driver");
  15. MODULE_LICENSE("GPL");
  16. struct grover_beep_info {
  17. void __iomem *freq_regs;
  18. void __iomem *enable_reg;
  19. };
  20. struct bbc_beep_info {
  21. u32 clock_freq;
  22. void __iomem *regs;
  23. };
  24. struct sparcspkr_state {
  25. const char *name;
  26. int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
  27. spinlock_t lock;
  28. struct input_dev *input_dev;
  29. union {
  30. struct grover_beep_info grover;
  31. struct bbc_beep_info bbc;
  32. } u;
  33. };
  34. static u32 bbc_count_to_reg(struct bbc_beep_info *info, unsigned int count)
  35. {
  36. u32 val, clock_freq = info->clock_freq;
  37. int i;
  38. if (!count)
  39. return 0;
  40. if (count <= clock_freq >> 20)
  41. return 1 << 18;
  42. if (count >= clock_freq >> 12)
  43. return 1 << 10;
  44. val = 1 << 18;
  45. for (i = 19; i >= 11; i--) {
  46. val >>= 1;
  47. if (count <= clock_freq >> i)
  48. break;
  49. }
  50. return val;
  51. }
  52. static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
  53. {
  54. struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
  55. struct bbc_beep_info *info = &state->u.bbc;
  56. unsigned int count = 0;
  57. unsigned long flags;
  58. if (type != EV_SND)
  59. return -1;
  60. switch (code) {
  61. case SND_BELL: if (value) value = 1000;
  62. case SND_TONE: break;
  63. default: return -1;
  64. }
  65. if (value > 20 && value < 32767)
  66. count = 1193182 / value;
  67. count = bbc_count_to_reg(info, count);
  68. spin_lock_irqsave(&state->lock, flags);
  69. if (count) {
  70. outb(0x01, info->regs + 0);
  71. outb(0x00, info->regs + 2);
  72. outb((count >> 16) & 0xff, info->regs + 3);
  73. outb((count >> 8) & 0xff, info->regs + 4);
  74. outb(0x00, info->regs + 5);
  75. } else {
  76. outb(0x00, info->regs + 0);
  77. }
  78. spin_unlock_irqrestore(&state->lock, flags);
  79. return 0;
  80. }
  81. static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
  82. {
  83. struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent);
  84. struct grover_beep_info *info = &state->u.grover;
  85. unsigned int count = 0;
  86. unsigned long flags;
  87. if (type != EV_SND)
  88. return -1;
  89. switch (code) {
  90. case SND_BELL: if (value) value = 1000;
  91. case SND_TONE: break;
  92. default: return -1;
  93. }
  94. if (value > 20 && value < 32767)
  95. count = 1193182 / value;
  96. spin_lock_irqsave(&state->lock, flags);
  97. if (count) {
  98. /* enable counter 2 */
  99. outb(inb(info->enable_reg) | 3, info->enable_reg);
  100. /* set command for counter 2, 2 byte write */
  101. outb(0xB6, info->freq_regs + 1);
  102. /* select desired HZ */
  103. outb(count & 0xff, info->freq_regs + 0);
  104. outb((count >> 8) & 0xff, info->freq_regs + 0);
  105. } else {
  106. /* disable counter 2 */
  107. outb(inb_p(info->enable_reg) & 0xFC, info->enable_reg);
  108. }
  109. spin_unlock_irqrestore(&state->lock, flags);
  110. return 0;
  111. }
  112. static int __devinit sparcspkr_probe(struct device *dev)
  113. {
  114. struct sparcspkr_state *state = dev_get_drvdata(dev);
  115. struct input_dev *input_dev;
  116. int error;
  117. input_dev = input_allocate_device();
  118. if (!input_dev)
  119. return -ENOMEM;
  120. input_dev->name = state->name;
  121. input_dev->phys = "sparc/input0";
  122. input_dev->id.bustype = BUS_ISA;
  123. input_dev->id.vendor = 0x001f;
  124. input_dev->id.product = 0x0001;
  125. input_dev->id.version = 0x0100;
  126. input_dev->dev.parent = dev;
  127. input_dev->evbit[0] = BIT_MASK(EV_SND);
  128. input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
  129. input_dev->event = state->event;
  130. error = input_register_device(input_dev);
  131. if (error) {
  132. input_free_device(input_dev);
  133. return error;
  134. }
  135. state->input_dev = input_dev;
  136. return 0;
  137. }
  138. static int sparcspkr_shutdown(struct of_device *dev)
  139. {
  140. struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
  141. struct input_dev *input_dev = state->input_dev;
  142. /* turn off the speaker */
  143. state->event(input_dev, EV_SND, SND_BELL, 0);
  144. return 0;
  145. }
  146. static int __devinit bbc_beep_probe(struct of_device *op, const struct of_device_id *match)
  147. {
  148. struct sparcspkr_state *state;
  149. struct bbc_beep_info *info;
  150. struct device_node *dp;
  151. int err = -ENOMEM;
  152. state = kzalloc(sizeof(*state), GFP_KERNEL);
  153. if (!state)
  154. goto out_err;
  155. state->name = "Sparc BBC Speaker";
  156. state->event = bbc_spkr_event;
  157. spin_lock_init(&state->lock);
  158. dp = of_find_node_by_path("/");
  159. err = -ENODEV;
  160. if (!dp)
  161. goto out_free;
  162. info = &state->u.bbc;
  163. info->clock_freq = of_getintprop_default(dp, "clock-frequency", 0);
  164. if (!info->clock_freq)
  165. goto out_free;
  166. info->regs = of_ioremap(&op->resource[0], 0, 6, "bbc beep");
  167. if (!info->regs)
  168. goto out_free;
  169. dev_set_drvdata(&op->dev, state);
  170. err = sparcspkr_probe(&op->dev);
  171. if (err)
  172. goto out_clear_drvdata;
  173. return 0;
  174. out_clear_drvdata:
  175. dev_set_drvdata(&op->dev, NULL);
  176. of_iounmap(&op->resource[0], info->regs, 6);
  177. out_free:
  178. kfree(state);
  179. out_err:
  180. return err;
  181. }
  182. static int bbc_remove(struct of_device *op)
  183. {
  184. struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
  185. struct input_dev *input_dev = state->input_dev;
  186. struct bbc_beep_info *info = &state->u.bbc;
  187. /* turn off the speaker */
  188. state->event(input_dev, EV_SND, SND_BELL, 0);
  189. input_unregister_device(input_dev);
  190. of_iounmap(&op->resource[0], info->regs, 6);
  191. dev_set_drvdata(&op->dev, NULL);
  192. kfree(state);
  193. return 0;
  194. }
  195. static struct of_device_id bbc_beep_match[] = {
  196. {
  197. .name = "beep",
  198. .compatible = "SUNW,bbc-beep",
  199. },
  200. {},
  201. };
  202. static struct of_platform_driver bbc_beep_driver = {
  203. .name = "bbcbeep",
  204. .match_table = bbc_beep_match,
  205. .probe = bbc_beep_probe,
  206. .remove = __devexit_p(bbc_remove),
  207. .shutdown = sparcspkr_shutdown,
  208. };
  209. static int __devinit grover_beep_probe(struct of_device *op, const struct of_device_id *match)
  210. {
  211. struct sparcspkr_state *state;
  212. struct grover_beep_info *info;
  213. int err = -ENOMEM;
  214. state = kzalloc(sizeof(*state), GFP_KERNEL);
  215. if (!state)
  216. goto out_err;
  217. state->name = "Sparc Grover Speaker";
  218. state->event = grover_spkr_event;
  219. spin_lock_init(&state->lock);
  220. info = &state->u.grover;
  221. info->freq_regs = of_ioremap(&op->resource[2], 0, 2, "grover beep freq");
  222. if (!info->freq_regs)
  223. goto out_free;
  224. info->enable_reg = of_ioremap(&op->resource[3], 0, 1, "grover beep enable");
  225. if (!info->enable_reg)
  226. goto out_unmap_freq_regs;
  227. dev_set_drvdata(&op->dev, state);
  228. err = sparcspkr_probe(&op->dev);
  229. if (err)
  230. goto out_clear_drvdata;
  231. return 0;
  232. out_clear_drvdata:
  233. dev_set_drvdata(&op->dev, NULL);
  234. of_iounmap(&op->resource[3], info->enable_reg, 1);
  235. out_unmap_freq_regs:
  236. of_iounmap(&op->resource[2], info->freq_regs, 2);
  237. out_free:
  238. kfree(state);
  239. out_err:
  240. return err;
  241. }
  242. static int grover_remove(struct of_device *op)
  243. {
  244. struct sparcspkr_state *state = dev_get_drvdata(&op->dev);
  245. struct grover_beep_info *info = &state->u.grover;
  246. struct input_dev *input_dev = state->input_dev;
  247. /* turn off the speaker */
  248. state->event(input_dev, EV_SND, SND_BELL, 0);
  249. input_unregister_device(input_dev);
  250. of_iounmap(&op->resource[3], info->enable_reg, 1);
  251. of_iounmap(&op->resource[2], info->freq_regs, 2);
  252. dev_set_drvdata(&op->dev, NULL);
  253. kfree(state);
  254. return 0;
  255. }
  256. static struct of_device_id grover_beep_match[] = {
  257. {
  258. .name = "beep",
  259. .compatible = "SUNW,smbus-beep",
  260. },
  261. {},
  262. };
  263. static struct of_platform_driver grover_beep_driver = {
  264. .name = "groverbeep",
  265. .match_table = grover_beep_match,
  266. .probe = grover_beep_probe,
  267. .remove = __devexit_p(grover_remove),
  268. .shutdown = sparcspkr_shutdown,
  269. };
  270. static int __init sparcspkr_init(void)
  271. {
  272. int err = of_register_driver(&bbc_beep_driver,
  273. &of_platform_bus_type);
  274. if (!err) {
  275. err = of_register_driver(&grover_beep_driver,
  276. &of_platform_bus_type);
  277. if (err)
  278. of_unregister_driver(&bbc_beep_driver);
  279. }
  280. return err;
  281. }
  282. static void __exit sparcspkr_exit(void)
  283. {
  284. of_unregister_driver(&bbc_beep_driver);
  285. of_unregister_driver(&grover_beep_driver);
  286. }
  287. module_init(sparcspkr_init);
  288. module_exit(sparcspkr_exit);