aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/misc/pwm-beeper.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-27 22:14:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-27 22:14:35 -0400
commited2608faa0f701b1dbc65277a9e5c7ff7118bfd4 (patch)
tree542950c65a22d6a149322849b6f45657e12d6a2e /drivers/input/misc/pwm-beeper.c
parent06d2e7812ecd1b585c5e9e7bda8ee90acebaef8c (diff)
parentf49cf3b8b4c841457244c461c66186a719e13bcc (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull more input subsystem updates from Dmitry Torokhov: "Just a few more driver fixes; new drivers will be coming in the next merge window" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: pwm-beeper - fix - scheduling while atomic Input: xpad - xbox one elite controller support Input: xpad - add more third-party controllers Input: xpad - prevent spurious input from wired Xbox 360 controllers Input: xpad - move pending clear to the correct location Input: uinput - handle compat ioctl for UI_SET_PHYS
Diffstat (limited to 'drivers/input/misc/pwm-beeper.c')
-rw-r--r--drivers/input/misc/pwm-beeper.c69
1 files changed, 48 insertions, 21 deletions
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index 8d7133268745..5f9655d49a65 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -20,21 +20,40 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/pwm.h> 21#include <linux/pwm.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/workqueue.h>
23 24
24struct pwm_beeper { 25struct pwm_beeper {
25 struct input_dev *input; 26 struct input_dev *input;
26 struct pwm_device *pwm; 27 struct pwm_device *pwm;
28 struct work_struct work;
27 unsigned long period; 29 unsigned long period;
28}; 30};
29 31
30#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x)) 32#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
31 33
34static void __pwm_beeper_set(struct pwm_beeper *beeper)
35{
36 unsigned long period = beeper->period;
37
38 if (period) {
39 pwm_config(beeper->pwm, period / 2, period);
40 pwm_enable(beeper->pwm);
41 } else
42 pwm_disable(beeper->pwm);
43}
44
45static void pwm_beeper_work(struct work_struct *work)
46{
47 struct pwm_beeper *beeper =
48 container_of(work, struct pwm_beeper, work);
49
50 __pwm_beeper_set(beeper);
51}
52
32static int pwm_beeper_event(struct input_dev *input, 53static int pwm_beeper_event(struct input_dev *input,
33 unsigned int type, unsigned int code, int value) 54 unsigned int type, unsigned int code, int value)
34{ 55{
35 int ret = 0;
36 struct pwm_beeper *beeper = input_get_drvdata(input); 56 struct pwm_beeper *beeper = input_get_drvdata(input);
37 unsigned long period;
38 57
39 if (type != EV_SND || value < 0) 58 if (type != EV_SND || value < 0)
40 return -EINVAL; 59 return -EINVAL;
@@ -49,22 +68,31 @@ static int pwm_beeper_event(struct input_dev *input,
49 return -EINVAL; 68 return -EINVAL;
50 } 69 }
51 70
52 if (value == 0) { 71 if (value == 0)
53 pwm_disable(beeper->pwm); 72 beeper->period = 0;
54 } else { 73 else
55 period = HZ_TO_NANOSECONDS(value); 74 beeper->period = HZ_TO_NANOSECONDS(value);
56 ret = pwm_config(beeper->pwm, period / 2, period); 75
57 if (ret) 76 schedule_work(&beeper->work);
58 return ret;
59 ret = pwm_enable(beeper->pwm);
60 if (ret)
61 return ret;
62 beeper->period = period;
63 }
64 77
65 return 0; 78 return 0;
66} 79}
67 80
81static void pwm_beeper_stop(struct pwm_beeper *beeper)
82{
83 cancel_work_sync(&beeper->work);
84
85 if (beeper->period)
86 pwm_disable(beeper->pwm);
87}
88
89static void pwm_beeper_close(struct input_dev *input)
90{
91 struct pwm_beeper *beeper = input_get_drvdata(input);
92
93 pwm_beeper_stop(beeper);
94}
95
68static int pwm_beeper_probe(struct platform_device *pdev) 96static int pwm_beeper_probe(struct platform_device *pdev)
69{ 97{
70 unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev); 98 unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);
@@ -93,6 +121,8 @@ static int pwm_beeper_probe(struct platform_device *pdev)
93 */ 121 */
94 pwm_apply_args(beeper->pwm); 122 pwm_apply_args(beeper->pwm);
95 123
124 INIT_WORK(&beeper->work, pwm_beeper_work);
125
96 beeper->input = input_allocate_device(); 126 beeper->input = input_allocate_device();
97 if (!beeper->input) { 127 if (!beeper->input) {
98 dev_err(&pdev->dev, "Failed to allocate input device\n"); 128 dev_err(&pdev->dev, "Failed to allocate input device\n");
@@ -112,6 +142,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
112 beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL); 142 beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
113 143
114 beeper->input->event = pwm_beeper_event; 144 beeper->input->event = pwm_beeper_event;
145 beeper->input->close = pwm_beeper_close;
115 146
116 input_set_drvdata(beeper->input, beeper); 147 input_set_drvdata(beeper->input, beeper);
117 148
@@ -141,7 +172,6 @@ static int pwm_beeper_remove(struct platform_device *pdev)
141 172
142 input_unregister_device(beeper->input); 173 input_unregister_device(beeper->input);
143 174
144 pwm_disable(beeper->pwm);
145 pwm_free(beeper->pwm); 175 pwm_free(beeper->pwm);
146 176
147 kfree(beeper); 177 kfree(beeper);
@@ -153,8 +183,7 @@ static int __maybe_unused pwm_beeper_suspend(struct device *dev)
153{ 183{
154 struct pwm_beeper *beeper = dev_get_drvdata(dev); 184 struct pwm_beeper *beeper = dev_get_drvdata(dev);
155 185
156 if (beeper->period) 186 pwm_beeper_stop(beeper);
157 pwm_disable(beeper->pwm);
158 187
159 return 0; 188 return 0;
160} 189}
@@ -163,10 +192,8 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev)
163{ 192{
164 struct pwm_beeper *beeper = dev_get_drvdata(dev); 193 struct pwm_beeper *beeper = dev_get_drvdata(dev);
165 194
166 if (beeper->period) { 195 if (beeper->period)
167 pwm_config(beeper->pwm, beeper->period / 2, beeper->period); 196 __pwm_beeper_set(beeper);
168 pwm_enable(beeper->pwm);
169 }
170 197
171 return 0; 198 return 0;
172} 199}