aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/misc
diff options
context:
space:
mode:
authorDan Murphy <dmurphy@ti.com>2014-09-08 19:10:49 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-09-08 19:16:23 -0400
commit1c24622572d6ab2ec8e731588d1c131563a64b53 (patch)
tree66e3e90e9a65cf96ad9148598b5200a64b05993c /drivers/input/misc
parentf554f619b7041e388d46395b1e30b151925a7797 (diff)
Input: add support for the DRV2667 haptic driver
Adding support for the DRV2667 haptic driver. This device has the ability to store vibration patterns in RAM and execute them once the GO bit is set. The initial driver sets a basic waveform in the first waveform sequence and will play the waveform when the GO bit is set and will continously play the waveform until the GO bit is unset. Data sheet is here: http://www.ti.com/product/drv2667 Signed-off-by: Dan Murphy <dmurphy@ti.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/misc')
-rw-r--r--drivers/input/misc/Kconfig11
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/drv2667.c500
3 files changed, 512 insertions, 0 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 41d0ae62ba05..51891f67b7df 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -687,4 +687,15 @@ config INPUT_DRV260X_HAPTICS
687 To compile this driver as a module, choose M here: the 687 To compile this driver as a module, choose M here: the
688 module will be called drv260x-haptics. 688 module will be called drv260x-haptics.
689 689
690config INPUT_DRV2667_HAPTICS
691 tristate "TI DRV2667 haptics support"
692 depends on INPUT && I2C
693 select INPUT_FF_MEMLESS
694 select REGMAP_I2C
695 help
696 Say Y to enable support for the TI DRV2667 haptics driver.
697
698 To compile this driver as a module, choose M here: the
699 module will be called drv260x-haptics.
700
690endif 701endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index cd4bc2d3474f..e0cee1774579 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o
27obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o 27obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o
28obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o 28obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
29obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o 29obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o
30obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o
30obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o 31obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
31obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o 32obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o
32obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o 33obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
new file mode 100644
index 000000000000..0f437581cc04
--- /dev/null
+++ b/drivers/input/misc/drv2667.c
@@ -0,0 +1,500 @@
1/*
2 * DRV2667 haptics driver family
3 *
4 * Author: Dan Murphy <dmurphy@ti.com>
5 *
6 * Copyright: (C) 2014 Texas Instruments, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
18#include <linux/i2c.h>
19#include <linux/input.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <linux/regulator/consumer.h>
26
27/* Contol registers */
28#define DRV2667_STATUS 0x00
29#define DRV2667_CTRL_1 0x01
30#define DRV2667_CTRL_2 0x02
31/* Waveform sequencer */
32#define DRV2667_WV_SEQ_0 0x03
33#define DRV2667_WV_SEQ_1 0x04
34#define DRV2667_WV_SEQ_2 0x05
35#define DRV2667_WV_SEQ_3 0x06
36#define DRV2667_WV_SEQ_4 0x07
37#define DRV2667_WV_SEQ_5 0x08
38#define DRV2667_WV_SEQ_6 0x09
39#define DRV2667_WV_SEQ_7 0x0A
40#define DRV2667_FIFO 0x0B
41#define DRV2667_PAGE 0xFF
42#define DRV2667_MAX_REG DRV2667_PAGE
43
44#define DRV2667_PAGE_0 0x00
45#define DRV2667_PAGE_1 0x01
46#define DRV2667_PAGE_2 0x02
47#define DRV2667_PAGE_3 0x03
48#define DRV2667_PAGE_4 0x04
49#define DRV2667_PAGE_5 0x05
50#define DRV2667_PAGE_6 0x06
51#define DRV2667_PAGE_7 0x07
52#define DRV2667_PAGE_8 0x08
53
54/* RAM fields */
55#define DRV2667_RAM_HDR_SZ 0x0
56/* RAM Header addresses */
57#define DRV2667_RAM_START_HI 0x01
58#define DRV2667_RAM_START_LO 0x02
59#define DRV2667_RAM_STOP_HI 0x03
60#define DRV2667_RAM_STOP_LO 0x04
61#define DRV2667_RAM_REPEAT_CT 0x05
62/* RAM data addresses */
63#define DRV2667_RAM_AMP 0x06
64#define DRV2667_RAM_FREQ 0x07
65#define DRV2667_RAM_DURATION 0x08
66#define DRV2667_RAM_ENVELOPE 0x09
67
68/* Control 1 Register */
69#define DRV2667_25_VPP_GAIN 0x00
70#define DRV2667_50_VPP_GAIN 0x01
71#define DRV2667_75_VPP_GAIN 0x02
72#define DRV2667_100_VPP_GAIN 0x03
73#define DRV2667_DIGITAL_IN 0xfc
74#define DRV2667_ANALOG_IN (1 << 2)
75
76/* Control 2 Register */
77#define DRV2667_GO (1 << 0)
78#define DRV2667_STANDBY (1 << 6)
79#define DRV2667_DEV_RST (1 << 7)
80
81/* RAM Envelope settings */
82#define DRV2667_NO_ENV 0x00
83#define DRV2667_32_MS_ENV 0x01
84#define DRV2667_64_MS_ENV 0x02
85#define DRV2667_96_MS_ENV 0x03
86#define DRV2667_128_MS_ENV 0x04
87#define DRV2667_160_MS_ENV 0x05
88#define DRV2667_192_MS_ENV 0x06
89#define DRV2667_224_MS_ENV 0x07
90#define DRV2667_256_MS_ENV 0x08
91#define DRV2667_512_MS_ENV 0x09
92#define DRV2667_768_MS_ENV 0x0a
93#define DRV2667_1024_MS_ENV 0x0b
94#define DRV2667_1280_MS_ENV 0x0c
95#define DRV2667_1536_MS_ENV 0x0d
96#define DRV2667_1792_MS_ENV 0x0e
97#define DRV2667_2048_MS_ENV 0x0f
98
99/**
100 * struct drv2667_data -
101 * @input_dev - Pointer to the input device
102 * @client - Pointer to the I2C client
103 * @regmap - Register map of the device
104 * @work - Work item used to off load the enable/disable of the vibration
105 * @regulator - Pointer to the regulator for the IC
106 * @magnitude - Magnitude of the vibration event
107**/
108struct drv2667_data {
109 struct input_dev *input_dev;
110 struct i2c_client *client;
111 struct regmap *regmap;
112 struct work_struct work;
113 struct regulator *regulator;
114 u32 page;
115 u32 magnitude;
116 u32 frequency;
117};
118
119static struct reg_default drv2667_reg_defs[] = {
120 { DRV2667_STATUS, 0x02 },
121 { DRV2667_CTRL_1, 0x28 },
122 { DRV2667_CTRL_2, 0x40 },
123 { DRV2667_WV_SEQ_0, 0x00 },
124 { DRV2667_WV_SEQ_1, 0x00 },
125 { DRV2667_WV_SEQ_2, 0x00 },
126 { DRV2667_WV_SEQ_3, 0x00 },
127 { DRV2667_WV_SEQ_4, 0x00 },
128 { DRV2667_WV_SEQ_5, 0x00 },
129 { DRV2667_WV_SEQ_6, 0x00 },
130 { DRV2667_WV_SEQ_7, 0x00 },
131 { DRV2667_FIFO, 0x00 },
132 { DRV2667_PAGE, 0x00 },
133};
134
135static int drv2667_set_waveform_freq(struct drv2667_data *haptics)
136{
137 unsigned int read_buf;
138 int freq;
139 int error;
140
141 /* Per the data sheet:
142 * Sinusoid Frequency (Hz) = 7.8125 x Frequency
143 */
144 freq = (haptics->frequency * 1000) / 78125;
145 if (freq <= 0) {
146 dev_err(&haptics->client->dev,
147 "ERROR: Frequency calculated to %i\n", freq);
148 return -EINVAL;
149 }
150
151 error = regmap_read(haptics->regmap, DRV2667_PAGE, &read_buf);
152 if (error) {
153 dev_err(&haptics->client->dev,
154 "Failed to read the page number: %d\n", error);
155 return -EIO;
156 }
157
158 if (read_buf == DRV2667_PAGE_0 ||
159 haptics->page != read_buf) {
160 error = regmap_write(haptics->regmap,
161 DRV2667_PAGE, haptics->page);
162 if (error) {
163 dev_err(&haptics->client->dev,
164 "Failed to set the page: %d\n", error);
165 return -EIO;
166 }
167 }
168
169 error = regmap_write(haptics->regmap, DRV2667_RAM_FREQ, freq);
170 if (error)
171 dev_err(&haptics->client->dev,
172 "Failed to set the frequency: %d\n", error);
173
174 /* Reset back to original page */
175 if (read_buf == DRV2667_PAGE_0 ||
176 haptics->page != read_buf) {
177 error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf);
178 if (error) {
179 dev_err(&haptics->client->dev,
180 "Failed to set the page: %d\n", error);
181 return -EIO;
182 }
183 }
184
185 return error;
186}
187
188static void drv2667_worker(struct work_struct *work)
189{
190 struct drv2667_data *haptics = container_of(work, struct drv2667_data, work);
191 int error;
192
193 if (haptics->magnitude) {
194 error = regmap_write(haptics->regmap,
195 DRV2667_PAGE, haptics->page);
196 if (error) {
197 dev_err(&haptics->client->dev,
198 "Failed to set the page: %d\n", error);
199 return;
200 }
201
202 error = regmap_write(haptics->regmap, DRV2667_RAM_AMP,
203 haptics->magnitude);
204 if (error) {
205 dev_err(&haptics->client->dev,
206 "Failed to set the amplitude: %d\n", error);
207 return;
208 }
209
210 error = regmap_write(haptics->regmap,
211 DRV2667_PAGE, DRV2667_PAGE_0);
212 if (error) {
213 dev_err(&haptics->client->dev,
214 "Failed to set the page: %d\n", error);
215 return;
216 }
217
218 error = regmap_write(haptics->regmap,
219 DRV2667_CTRL_2, DRV2667_GO);
220 if (error) {
221 dev_err(&haptics->client->dev,
222 "Failed to set the GO bit: %d\n", error);
223 }
224 } else {
225 error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
226 DRV2667_GO, 0);
227 if (error) {
228 dev_err(&haptics->client->dev,
229 "Failed to unset the GO bit: %d\n", error);
230 }
231 }
232}
233
234static int drv2667_haptics_play(struct input_dev *input, void *data,
235 struct ff_effect *effect)
236{
237 struct drv2667_data *haptics = input_get_drvdata(input);
238
239 if (effect->u.rumble.strong_magnitude > 0)
240 haptics->magnitude = effect->u.rumble.strong_magnitude;
241 else if (effect->u.rumble.weak_magnitude > 0)
242 haptics->magnitude = effect->u.rumble.weak_magnitude;
243 else
244 haptics->magnitude = 0;
245
246 schedule_work(&haptics->work);
247
248 return 0;
249}
250
251static void drv2667_close(struct input_dev *input)
252{
253 struct drv2667_data *haptics = input_get_drvdata(input);
254 int error;
255
256 cancel_work_sync(&haptics->work);
257
258 error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
259 DRV2667_STANDBY, 1);
260 if (error)
261 dev_err(&haptics->client->dev,
262 "Failed to enter standby mode: %d\n", error);
263}
264
265static const struct reg_default drv2667_init_regs[] = {
266 { DRV2667_CTRL_2, 0 },
267 { DRV2667_CTRL_1, DRV2667_25_VPP_GAIN },
268 { DRV2667_WV_SEQ_0, 1 },
269 { DRV2667_WV_SEQ_1, 0 }
270};
271
272static const struct reg_default drv2667_page1_init[] = {
273 { DRV2667_RAM_HDR_SZ, 0x05 },
274 { DRV2667_RAM_START_HI, 0x80 },
275 { DRV2667_RAM_START_LO, 0x06 },
276 { DRV2667_RAM_STOP_HI, 0x00 },
277 { DRV2667_RAM_STOP_LO, 0x09 },
278 { DRV2667_RAM_REPEAT_CT, 0 },
279 { DRV2667_RAM_DURATION, 0x05 },
280 { DRV2667_RAM_ENVELOPE, DRV2667_NO_ENV },
281 { DRV2667_RAM_AMP, 0x60 },
282};
283
284static int drv2667_init(struct drv2667_data *haptics)
285{
286 int error;
287
288 /* Set default haptic frequency to 195Hz on Page 1*/
289 haptics->frequency = 195;
290 haptics->page = DRV2667_PAGE_1;
291
292 error = regmap_register_patch(haptics->regmap,
293 drv2667_init_regs,
294 ARRAY_SIZE(drv2667_init_regs));
295 if (error) {
296 dev_err(&haptics->client->dev,
297 "Failed to write init registers: %d\n",
298 error);
299 return error;
300 }
301
302 error = regmap_write(haptics->regmap, DRV2667_PAGE, haptics->page);
303 if (error) {
304 dev_err(&haptics->client->dev, "Failed to set page: %d\n",
305 error);
306 goto error_out;
307 }
308
309 error = drv2667_set_waveform_freq(haptics);
310 if (error)
311 goto error_page;
312
313 error = regmap_register_patch(haptics->regmap,
314 drv2667_page1_init,
315 ARRAY_SIZE(drv2667_page1_init));
316 if (error) {
317 dev_err(&haptics->client->dev,
318 "Failed to write page registers: %d\n",
319 error);
320 return error;
321 }
322
323 error = regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0);
324 return error;
325
326error_page:
327 regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0);
328error_out:
329 return error;
330}
331
332static const struct regmap_config drv2667_regmap_config = {
333 .reg_bits = 8,
334 .val_bits = 8,
335
336 .max_register = DRV2667_MAX_REG,
337 .reg_defaults = drv2667_reg_defs,
338 .num_reg_defaults = ARRAY_SIZE(drv2667_reg_defs),
339 .cache_type = REGCACHE_NONE,
340};
341
342static int drv2667_probe(struct i2c_client *client,
343 const struct i2c_device_id *id)
344{
345 struct drv2667_data *haptics;
346 int error;
347
348 haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
349 if (!haptics)
350 return -ENOMEM;
351
352 haptics->regulator = devm_regulator_get(&client->dev, "vbat");
353 if (IS_ERR(haptics->regulator)) {
354 error = PTR_ERR(haptics->regulator);
355 dev_err(&client->dev,
356 "unable to get regulator, error: %d\n", error);
357 return error;
358 }
359
360 haptics->input_dev = devm_input_allocate_device(&client->dev);
361 if (!haptics->input_dev) {
362 dev_err(&client->dev, "Failed to allocate input device\n");
363 return -ENOMEM;
364 }
365
366 haptics->input_dev->name = "drv2667:haptics";
367 haptics->input_dev->dev.parent = client->dev.parent;
368 haptics->input_dev->close = drv2667_close;
369 input_set_drvdata(haptics->input_dev, haptics);
370 input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
371
372 error = input_ff_create_memless(haptics->input_dev, NULL,
373 drv2667_haptics_play);
374 if (error) {
375 dev_err(&client->dev, "input_ff_create() failed: %d\n",
376 error);
377 return error;
378 }
379
380 INIT_WORK(&haptics->work, drv2667_worker);
381
382 haptics->client = client;
383 i2c_set_clientdata(client, haptics);
384
385 haptics->regmap = devm_regmap_init_i2c(client, &drv2667_regmap_config);
386 if (IS_ERR(haptics->regmap)) {
387 error = PTR_ERR(haptics->regmap);
388 dev_err(&client->dev, "Failed to allocate register map: %d\n",
389 error);
390 return error;
391 }
392
393 error = drv2667_init(haptics);
394 if (error) {
395 dev_err(&client->dev, "Device init failed: %d\n", error);
396 return error;
397 }
398
399 error = input_register_device(haptics->input_dev);
400 if (error) {
401 dev_err(&client->dev, "couldn't register input device: %d\n",
402 error);
403 return error;
404 }
405
406 return 0;
407}
408
409#ifdef CONFIG_PM_SLEEP
410static int drv2667_suspend(struct device *dev)
411{
412 struct drv2667_data *haptics = dev_get_drvdata(dev);
413 int ret = 0;
414
415 mutex_lock(&haptics->input_dev->mutex);
416
417 if (haptics->input_dev->users) {
418 ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
419 DRV2667_STANDBY, 1);
420 if (ret) {
421 dev_err(dev, "Failed to set standby mode\n");
422 regulator_disable(haptics->regulator);
423 goto out;
424 }
425
426 ret = regulator_disable(haptics->regulator);
427 if (ret) {
428 dev_err(dev, "Failed to disable regulator\n");
429 regmap_update_bits(haptics->regmap,
430 DRV2667_CTRL_2,
431 DRV2667_STANDBY, 0);
432 }
433 }
434out:
435 mutex_unlock(&haptics->input_dev->mutex);
436 return ret;
437}
438
439static int drv2667_resume(struct device *dev)
440{
441 struct drv2667_data *haptics = dev_get_drvdata(dev);
442 int ret = 0;
443
444 mutex_lock(&haptics->input_dev->mutex);
445
446 if (haptics->input_dev->users) {
447 ret = regulator_enable(haptics->regulator);
448 if (ret) {
449 dev_err(dev, "Failed to enable regulator\n");
450 goto out;
451 }
452
453 ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
454 DRV2667_STANDBY, 0);
455 if (ret) {
456 dev_err(dev, "Failed to unset standby mode\n");
457 regulator_disable(haptics->regulator);
458 goto out;
459 }
460
461 }
462
463out:
464 mutex_unlock(&haptics->input_dev->mutex);
465 return ret;
466}
467#endif
468
469static SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
470
471static const struct i2c_device_id drv2667_id[] = {
472 { "drv2667", 0 },
473 { }
474};
475MODULE_DEVICE_TABLE(i2c, drv2667_id);
476
477#ifdef CONFIG_OF
478static const struct of_device_id drv2667_of_match[] = {
479 { .compatible = "ti,drv2667", },
480 { }
481};
482MODULE_DEVICE_TABLE(of, drv2667_of_match);
483#endif
484
485static struct i2c_driver drv2667_driver = {
486 .probe = drv2667_probe,
487 .driver = {
488 .name = "drv2667-haptics",
489 .owner = THIS_MODULE,
490 .of_match_table = of_match_ptr(drv2667_of_match),
491 .pm = &drv2667_pm_ops,
492 },
493 .id_table = drv2667_id,
494};
495module_i2c_driver(drv2667_driver);
496
497MODULE_ALIAS("platform:drv2667-haptics");
498MODULE_DESCRIPTION("TI DRV2667 haptics driver");
499MODULE_LICENSE("GPL");
500MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");