Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add a new driver for GPIO beeper

This patch adds a new driver for the beeper controlled via GPIO pin.
The driver does not depend on the architecture and is positioned as
a replacement for the specific drivers that are used for this function.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Alexander Shiyan and committed by
Dmitry Torokhov
976358e2 b5fd2a3e

+150
+13
Documentation/devicetree/bindings/input/gpio-beeper.txt
··· 1 + * GPIO beeper device tree bindings 2 + 3 + Register a beeper connected to GPIO pin. 4 + 5 + Required properties: 6 + - compatible: Should be "gpio-beeper". 7 + - gpios: From common gpio binding; gpio connection to beeper enable pin. 8 + 9 + Example: 10 + beeper: beeper { 11 + compatible = "gpio-beeper"; 12 + gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>; 13 + };
+9
drivers/input/misc/Kconfig
··· 222 222 To compile this driver as a module, choose M here: the 223 223 module will be called gp2ap002a00f. 224 224 225 + config INPUT_GPIO_BEEPER 226 + tristate "Generic GPIO Beeper support" 227 + depends on OF_GPIO 228 + help 229 + Say Y here if you have a beeper connected to a GPIO pin. 230 + 231 + To compile this driver as a module, choose M here: the 232 + module will be called gpio-beeper. 233 + 225 234 config INPUT_GPIO_TILT_POLLED 226 235 tristate "Polled GPIO tilt switch" 227 236 depends on GPIOLIB
+1
drivers/input/misc/Makefile
··· 27 27 obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o 28 28 obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o 29 29 obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o 30 + obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o 30 31 obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o 31 32 obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o 32 33 obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o
+127
drivers/input/misc/gpio-beeper.c
··· 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");