Skip to content

Commit bbc8608

Browse files
committed
Merge branch 'next' into for-linus
Prepare second round of input updates for 4.14 merge window.
2 parents a6cbfa1 + 697c5d8 commit bbc8608

File tree

12 files changed

+380
-11
lines changed

12 files changed

+380
-11
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
* PWM vibrator device tree bindings
2+
3+
Registers a PWM device as vibrator. It is expected, that the vibrator's
4+
strength increases based on the duty cycle of the enable PWM channel
5+
(100% duty cycle meaning strongest vibration, 0% meaning no vibration).
6+
7+
The binding supports an optional direction PWM channel, that can be
8+
driven at fixed duty cycle. If available this is can be used to increase
9+
the vibration effect of some devices.
10+
11+
Required properties:
12+
- compatible: should contain "pwm-vibrator"
13+
- pwm-names: Should contain "enable" and optionally "direction"
14+
- pwms: Should contain a PWM handle for each entry in pwm-names
15+
16+
Optional properties:
17+
- vcc-supply: Phandle for the regulator supplying power
18+
- direction-duty-cycle-ns: Duty cycle of the direction PWM channel in
19+
nanoseconds, defaults to 50% of the channel's
20+
period.
21+
22+
Example from Motorola Droid 4:
23+
24+
&omap4_pmx_core {
25+
vibrator_direction_pin: pinmux_vibrator_direction_pin {
26+
pinctrl-single,pins = <
27+
OMAP4_IOPAD(0x1ce, PIN_OUTPUT | MUX_MODE1) /* dmtimer8_pwm_evt (gpio_27) */
28+
>;
29+
};
30+
31+
vibrator_enable_pin: pinmux_vibrator_enable_pin {
32+
pinctrl-single,pins = <
33+
OMAP4_IOPAD(0X1d0, PIN_OUTPUT | MUX_MODE1) /* dmtimer9_pwm_evt (gpio_28) */
34+
>;
35+
};
36+
};
37+
38+
/ {
39+
pwm8: dmtimer-pwm {
40+
pinctrl-names = "default";
41+
pinctrl-0 = <&vibrator_direction_pin>;
42+
43+
compatible = "ti,omap-dmtimer-pwm";
44+
#pwm-cells = <3>;
45+
ti,timers = <&timer8>;
46+
ti,clock-source = <0x01>;
47+
};
48+
49+
pwm9: dmtimer-pwm {
50+
pinctrl-names = "default";
51+
pinctrl-0 = <&vibrator_enable_pin>;
52+
53+
compatible = "ti,omap-dmtimer-pwm";
54+
#pwm-cells = <3>;
55+
ti,timers = <&timer9>;
56+
ti,clock-source = <0x01>;
57+
};
58+
59+
vibrator {
60+
compatible = "pwm-vibrator";
61+
pwms = <&pwm8 0 1000000000 0>,
62+
<&pwm9 0 1000000000 0>;
63+
pwm-names = "enable", "direction";
64+
direction-duty-cycle-ns = <1000000000>;
65+
};
66+
};

drivers/input/joystick/adi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ static void adi_close(struct input_dev *dev)
313313

314314
static void adi_init_digital(struct gameport *gameport)
315315
{
316-
int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
316+
static const int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
317317
int i;
318318

319319
for (i = 0; seq[i]; i++) {

drivers/input/joystick/xpad.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,10 +1764,12 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
17641764
struct usb_endpoint_descriptor *ep =
17651765
&intf->cur_altsetting->endpoint[i].desc;
17661766

1767-
if (usb_endpoint_dir_in(ep))
1768-
ep_irq_in = ep;
1769-
else
1770-
ep_irq_out = ep;
1767+
if (usb_endpoint_xfer_int(ep)) {
1768+
if (usb_endpoint_dir_in(ep))
1769+
ep_irq_in = ep;
1770+
else
1771+
ep_irq_out = ep;
1772+
}
17711773
}
17721774

17731775
if (!ep_irq_in || !ep_irq_out) {

drivers/input/misc/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,18 @@ config INPUT_PWM_BEEPER
581581
To compile this driver as a module, choose M here: the module will be
582582
called pwm-beeper.
583583

584+
config INPUT_PWM_VIBRA
585+
tristate "PWM vibrator support"
586+
depends on PWM
587+
select INPUT_FF_MEMLESS
588+
help
589+
Say Y here to get support for PWM based vibrator devices.
590+
591+
If unsure, say N.
592+
593+
To compile this driver as a module, choose M here: the module will be
594+
called pwm-vibra.
595+
584596
config INPUT_RK805_PWRKEY
585597
tristate "Rockchip RK805 PMIC power key support"
586598
depends on MFD_RK808

drivers/input/misc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
5959
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
6060
obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
6161
obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o
62+
obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o
6263
obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o
6364
obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o
6465
obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o

drivers/input/misc/pwm-vibra.c

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/*
2+
* PWM vibrator driver
3+
*
4+
* Copyright (C) 2017 Collabora Ltd.
5+
*
6+
* Based on previous work from:
7+
* Copyright (C) 2012 Dmitry Torokhov <[email protected]>
8+
*
9+
* Based on PWM beeper driver:
10+
* Copyright (C) 2010, Lars-Peter Clausen <[email protected]>
11+
*
12+
* This program is free software; you can redistribute it and/or modify it
13+
* under the terms of the GNU General Public License as published by the
14+
* Free Software Foundation; either version 2 of the License, or (at your
15+
* option) any later version.
16+
*/
17+
18+
#include <linux/input.h>
19+
#include <linux/kernel.h>
20+
#include <linux/module.h>
21+
#include <linux/of_device.h>
22+
#include <linux/platform_device.h>
23+
#include <linux/property.h>
24+
#include <linux/pwm.h>
25+
#include <linux/regulator/consumer.h>
26+
#include <linux/slab.h>
27+
28+
struct pwm_vibrator {
29+
struct input_dev *input;
30+
struct pwm_device *pwm;
31+
struct pwm_device *pwm_dir;
32+
struct regulator *vcc;
33+
34+
struct work_struct play_work;
35+
u16 level;
36+
u32 direction_duty_cycle;
37+
};
38+
39+
static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
40+
{
41+
struct device *pdev = vibrator->input->dev.parent;
42+
struct pwm_state state;
43+
int err;
44+
45+
err = regulator_enable(vibrator->vcc);
46+
if (err) {
47+
dev_err(pdev, "failed to enable regulator: %d", err);
48+
return err;
49+
}
50+
51+
pwm_get_state(vibrator->pwm, &state);
52+
pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff);
53+
state.enabled = true;
54+
55+
err = pwm_apply_state(vibrator->pwm, &state);
56+
if (err) {
57+
dev_err(pdev, "failed to apply pwm state: %d", err);
58+
return err;
59+
}
60+
61+
if (vibrator->pwm_dir) {
62+
pwm_get_state(vibrator->pwm_dir, &state);
63+
state.duty_cycle = vibrator->direction_duty_cycle;
64+
state.enabled = true;
65+
66+
err = pwm_apply_state(vibrator->pwm_dir, &state);
67+
if (err) {
68+
dev_err(pdev, "failed to apply dir-pwm state: %d", err);
69+
pwm_disable(vibrator->pwm);
70+
return err;
71+
}
72+
}
73+
74+
return 0;
75+
}
76+
77+
static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
78+
{
79+
regulator_disable(vibrator->vcc);
80+
81+
if (vibrator->pwm_dir)
82+
pwm_disable(vibrator->pwm_dir);
83+
pwm_disable(vibrator->pwm);
84+
}
85+
86+
static void pwm_vibrator_play_work(struct work_struct *work)
87+
{
88+
struct pwm_vibrator *vibrator = container_of(work,
89+
struct pwm_vibrator, play_work);
90+
91+
if (vibrator->level)
92+
pwm_vibrator_start(vibrator);
93+
else
94+
pwm_vibrator_stop(vibrator);
95+
}
96+
97+
static int pwm_vibrator_play_effect(struct input_dev *dev, void *data,
98+
struct ff_effect *effect)
99+
{
100+
struct pwm_vibrator *vibrator = input_get_drvdata(dev);
101+
102+
vibrator->level = effect->u.rumble.strong_magnitude;
103+
if (!vibrator->level)
104+
vibrator->level = effect->u.rumble.weak_magnitude;
105+
106+
schedule_work(&vibrator->play_work);
107+
108+
return 0;
109+
}
110+
111+
static void pwm_vibrator_close(struct input_dev *input)
112+
{
113+
struct pwm_vibrator *vibrator = input_get_drvdata(input);
114+
115+
cancel_work_sync(&vibrator->play_work);
116+
pwm_vibrator_stop(vibrator);
117+
}
118+
119+
static int pwm_vibrator_probe(struct platform_device *pdev)
120+
{
121+
struct pwm_vibrator *vibrator;
122+
struct pwm_state state;
123+
int err;
124+
125+
vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
126+
if (!vibrator)
127+
return -ENOMEM;
128+
129+
vibrator->input = devm_input_allocate_device(&pdev->dev);
130+
if (!vibrator->input)
131+
return -ENOMEM;
132+
133+
vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
134+
err = PTR_ERR_OR_ZERO(vibrator->vcc);
135+
if (err) {
136+
if (err != -EPROBE_DEFER)
137+
dev_err(&pdev->dev, "Failed to request regulator: %d",
138+
err);
139+
return err;
140+
}
141+
142+
vibrator->pwm = devm_pwm_get(&pdev->dev, "enable");
143+
err = PTR_ERR_OR_ZERO(vibrator->pwm);
144+
if (err) {
145+
if (err != -EPROBE_DEFER)
146+
dev_err(&pdev->dev, "Failed to request main pwm: %d",
147+
err);
148+
return err;
149+
}
150+
151+
INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work);
152+
153+
/* Sync up PWM state and ensure it is off. */
154+
pwm_init_state(vibrator->pwm, &state);
155+
state.enabled = false;
156+
err = pwm_apply_state(vibrator->pwm, &state);
157+
if (err) {
158+
dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
159+
err);
160+
return err;
161+
}
162+
163+
vibrator->pwm_dir = devm_pwm_get(&pdev->dev, "direction");
164+
err = PTR_ERR_OR_ZERO(vibrator->pwm_dir);
165+
switch (err) {
166+
case 0:
167+
/* Sync up PWM state and ensure it is off. */
168+
pwm_init_state(vibrator->pwm_dir, &state);
169+
state.enabled = false;
170+
err = pwm_apply_state(vibrator->pwm_dir, &state);
171+
if (err) {
172+
dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
173+
err);
174+
return err;
175+
}
176+
177+
vibrator->direction_duty_cycle =
178+
pwm_get_period(vibrator->pwm_dir) / 2;
179+
device_property_read_u32(&pdev->dev, "direction-duty-cycle-ns",
180+
&vibrator->direction_duty_cycle);
181+
break;
182+
183+
case -ENODATA:
184+
/* Direction PWM is optional */
185+
vibrator->pwm_dir = NULL;
186+
break;
187+
188+
default:
189+
dev_err(&pdev->dev, "Failed to request direction pwm: %d", err);
190+
/* Fall through */
191+
192+
case -EPROBE_DEFER:
193+
return err;
194+
}
195+
196+
vibrator->input->name = "pwm-vibrator";
197+
vibrator->input->id.bustype = BUS_HOST;
198+
vibrator->input->dev.parent = &pdev->dev;
199+
vibrator->input->close = pwm_vibrator_close;
200+
201+
input_set_drvdata(vibrator->input, vibrator);
202+
input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
203+
204+
err = input_ff_create_memless(vibrator->input, NULL,
205+
pwm_vibrator_play_effect);
206+
if (err) {
207+
dev_err(&pdev->dev, "Couldn't create FF dev: %d", err);
208+
return err;
209+
}
210+
211+
err = input_register_device(vibrator->input);
212+
if (err) {
213+
dev_err(&pdev->dev, "Couldn't register input dev: %d", err);
214+
return err;
215+
}
216+
217+
platform_set_drvdata(pdev, vibrator);
218+
219+
return 0;
220+
}
221+
222+
static int __maybe_unused pwm_vibrator_suspend(struct device *dev)
223+
{
224+
struct pwm_vibrator *vibrator = dev_get_drvdata(dev);
225+
226+
cancel_work_sync(&vibrator->play_work);
227+
if (vibrator->level)
228+
pwm_vibrator_stop(vibrator);
229+
230+
return 0;
231+
}
232+
233+
static int __maybe_unused pwm_vibrator_resume(struct device *dev)
234+
{
235+
struct pwm_vibrator *vibrator = dev_get_drvdata(dev);
236+
237+
if (vibrator->level)
238+
pwm_vibrator_start(vibrator);
239+
240+
return 0;
241+
}
242+
243+
static SIMPLE_DEV_PM_OPS(pwm_vibrator_pm_ops,
244+
pwm_vibrator_suspend, pwm_vibrator_resume);
245+
246+
#ifdef CONFIG_OF
247+
static const struct of_device_id pwm_vibra_dt_match_table[] = {
248+
{ .compatible = "pwm-vibrator" },
249+
{},
250+
};
251+
MODULE_DEVICE_TABLE(of, pwm_vibra_dt_match_table);
252+
#endif
253+
254+
static struct platform_driver pwm_vibrator_driver = {
255+
.probe = pwm_vibrator_probe,
256+
.driver = {
257+
.name = "pwm-vibrator",
258+
.pm = &pwm_vibrator_pm_ops,
259+
.of_match_table = of_match_ptr(pwm_vibra_dt_match_table),
260+
},
261+
};
262+
module_platform_driver(pwm_vibrator_driver);
263+
264+
MODULE_AUTHOR("Sebastian Reichel <[email protected]>");
265+
MODULE_DESCRIPTION("PWM vibrator driver");
266+
MODULE_LICENSE("GPL");
267+
MODULE_ALIAS("platform:pwm-vibrator");

0 commit comments

Comments
 (0)