1 /* 2 * Generic GPIO beeper driver 3 * 4 * Copyright (C) 2013 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 12 #include <linux/input.h> 13 #include <linux/module.h> 14 #include <linux/of_gpio.h> 15 #include <linux/workqueue.h> 16 #include <linux/platform_device.h> 17 18 #define BEEPER_MODNAME "gpio-beeper" 19 20 struct gpio_beeper { 21 struct work_struct work; 22 int gpio; 23 bool active_low; 24 bool beeping; 25 }; 26 27 static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on) 28 { 29 gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low); 30 } 31 32 static void gpio_beeper_work(struct work_struct *work) 33 { 34 struct gpio_beeper *beep = container_of(work, struct gpio_beeper, work); 35 36 gpio_beeper_toggle(beep, beep->beeping); 37 } 38 39 static int gpio_beeper_event(struct input_dev *dev, unsigned int type, 40 unsigned int code, int value) 41 { 42 struct gpio_beeper *beep = input_get_drvdata(dev); 43 44 if (type != EV_SND || code != SND_BELL) 45 return -ENOTSUPP; 46 47 if (value < 0) 48 return -EINVAL; 49 50 beep->beeping = value; 51 /* Schedule work to actually turn the beeper on or off */ 52 schedule_work(&beep->work); 53 54 return 0; 55 } 56 57 static void gpio_beeper_close(struct input_dev *input) 58 { 59 struct gpio_beeper *beep = input_get_drvdata(input); 60 61 cancel_work_sync(&beep->work); 62 gpio_beeper_toggle(beep, false); 63 } 64 65 static int gpio_beeper_probe(struct platform_device *pdev) 66 { 67 struct gpio_beeper *beep; 68 enum of_gpio_flags flags; 69 struct input_dev *input; 70 unsigned long gflags; 71 int err; 72 73 beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); 74 if (!beep) 75 return -ENOMEM; 76 77 beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); 78 if (!gpio_is_valid(beep->gpio)) 79 return beep->gpio; 80 81 input = devm_input_allocate_device(&pdev->dev); 82 if (!input) 83 return -ENOMEM; 84 85 INIT_WORK(&beep->work, gpio_beeper_work); 86 87 input->name = pdev->name; 88 input->id.bustype = BUS_HOST; 89 input->id.vendor = 0x0001; 90 input->id.product = 0x0001; 91 input->id.version = 0x0100; 92 input->close = gpio_beeper_close; 93 input->event = gpio_beeper_event; 94 95 input_set_capability(input, EV_SND, SND_BELL); 96 97 beep->active_low = flags & OF_GPIO_ACTIVE_LOW; 98 gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; 99 100 err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name); 101 if (err) 102 return err; 103 104 input_set_drvdata(input, beep); 105 106 return input_register_device(input); 107 } 108 109 static struct of_device_id gpio_beeper_of_match[] = { 110 { .compatible = BEEPER_MODNAME, }, 111 { } 112 }; 113 MODULE_DEVICE_TABLE(of, gpio_beeper_of_match); 114 115 static struct platform_driver gpio_beeper_platform_driver = { 116 .driver = { 117 .name = BEEPER_MODNAME, 118 .owner = THIS_MODULE, 119 .of_match_table = gpio_beeper_of_match, 120 }, 121 .probe = gpio_beeper_probe, 122 }; 123 module_platform_driver(gpio_beeper_platform_driver); 124 125 MODULE_LICENSE("GPL"); 126 MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); 127 MODULE_DESCRIPTION("Generic GPIO beeper driver"); 128