gpio-beeper.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Generic GPIO beeper driver
  3. *
  4. * Copyright (C) 2013-2014 Alexander Shiyan <shc_work@mail.ru>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #include <linux/input.h>
  12. #include <linux/module.h>
  13. #include <linux/gpio/consumer.h>
  14. #include <linux/of.h>
  15. #include <linux/workqueue.h>
  16. #include <linux/platform_device.h>
  17. #define BEEPER_MODNAME "gpio-beeper"
  18. struct gpio_beeper {
  19. struct work_struct work;
  20. struct gpio_desc *desc;
  21. bool beeping;
  22. };
  23. static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on)
  24. {
  25. gpiod_set_value_cansleep(beep->desc, on);
  26. }
  27. static void gpio_beeper_work(struct work_struct *work)
  28. {
  29. struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work);
  30. gpio_beeper_toggle(beep, beep->beeping);
  31. }
  32. static int gpio_beeper_event(struct input_dev *dev, unsigned int type,
  33. unsigned int code, int value)
  34. {
  35. struct gpio_beeper *beep = input_get_drvdata(dev);
  36. if (type != EV_SND || code != SND_BELL)
  37. return -ENOTSUPP;
  38. if (value < 0)
  39. return -EINVAL;
  40. beep->beeping = value;
  41. /* Schedule work to actually turn the beeper on or off */
  42. schedule_work(&beep->work);
  43. return 0;
  44. }
  45. static void gpio_beeper_close(struct input_dev *input)
  46. {
  47. struct gpio_beeper *beep = input_get_drvdata(input);
  48. cancel_work_sync(&beep->work);
  49. gpio_beeper_toggle(beep, false);
  50. }
  51. static int gpio_beeper_probe(struct platform_device *pdev)
  52. {
  53. struct gpio_beeper *beep;
  54. struct input_dev *input;
  55. beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL);
  56. if (!beep)
  57. return -ENOMEM;
  58. beep->desc = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW);
  59. if (IS_ERR(beep->desc))
  60. return PTR_ERR(beep->desc);
  61. input = devm_input_allocate_device(&pdev->dev);
  62. if (!input)
  63. return -ENOMEM;
  64. INIT_WORK(&beep->work, gpio_beeper_work);
  65. input->name = pdev->name;
  66. input->id.bustype = BUS_HOST;
  67. input->id.vendor = 0x0001;
  68. input->id.product = 0x0001;
  69. input->id.version = 0x0100;
  70. input->close = gpio_beeper_close;
  71. input->event = gpio_beeper_event;
  72. input_set_capability(input, EV_SND, SND_BELL);
  73. input_set_drvdata(input, beep);
  74. return input_register_device(input);
  75. }
  76. #ifdef CONFIG_OF
  77. static const struct of_device_id gpio_beeper_of_match[] = {
  78. { .compatible = BEEPER_MODNAME, },
  79. { }
  80. };
  81. MODULE_DEVICE_TABLE(of, gpio_beeper_of_match);
  82. #endif
  83. static struct platform_driver gpio_beeper_platform_driver = {
  84. .driver = {
  85. .name = BEEPER_MODNAME,
  86. .of_match_table = of_match_ptr(gpio_beeper_of_match),
  87. },
  88. .probe = gpio_beeper_probe,
  89. };
  90. module_platform_driver(gpio_beeper_platform_driver);
  91. MODULE_LICENSE("GPL");
  92. MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
  93. MODULE_DESCRIPTION("Generic GPIO beeper driver");