11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21c246225SDan Murphy /*
31c246225SDan Murphy * DRV2667 haptics driver family
41c246225SDan Murphy *
51c246225SDan Murphy * Author: Dan Murphy <dmurphy@ti.com>
61c246225SDan Murphy *
71c246225SDan Murphy * Copyright: (C) 2014 Texas Instruments, Inc.
81c246225SDan Murphy */
91c246225SDan Murphy
101c246225SDan Murphy #include <linux/i2c.h>
111c246225SDan Murphy #include <linux/input.h>
121c246225SDan Murphy #include <linux/module.h>
131c246225SDan Murphy #include <linux/platform_device.h>
141c246225SDan Murphy #include <linux/regmap.h>
151c246225SDan Murphy #include <linux/slab.h>
161c246225SDan Murphy #include <linux/delay.h>
171c246225SDan Murphy #include <linux/regulator/consumer.h>
181c246225SDan Murphy
191c246225SDan Murphy /* Contol registers */
201c246225SDan Murphy #define DRV2667_STATUS 0x00
211c246225SDan Murphy #define DRV2667_CTRL_1 0x01
221c246225SDan Murphy #define DRV2667_CTRL_2 0x02
231c246225SDan Murphy /* Waveform sequencer */
241c246225SDan Murphy #define DRV2667_WV_SEQ_0 0x03
251c246225SDan Murphy #define DRV2667_WV_SEQ_1 0x04
261c246225SDan Murphy #define DRV2667_WV_SEQ_2 0x05
271c246225SDan Murphy #define DRV2667_WV_SEQ_3 0x06
281c246225SDan Murphy #define DRV2667_WV_SEQ_4 0x07
291c246225SDan Murphy #define DRV2667_WV_SEQ_5 0x08
301c246225SDan Murphy #define DRV2667_WV_SEQ_6 0x09
311c246225SDan Murphy #define DRV2667_WV_SEQ_7 0x0A
321c246225SDan Murphy #define DRV2667_FIFO 0x0B
331c246225SDan Murphy #define DRV2667_PAGE 0xFF
341c246225SDan Murphy #define DRV2667_MAX_REG DRV2667_PAGE
351c246225SDan Murphy
361c246225SDan Murphy #define DRV2667_PAGE_0 0x00
371c246225SDan Murphy #define DRV2667_PAGE_1 0x01
381c246225SDan Murphy #define DRV2667_PAGE_2 0x02
391c246225SDan Murphy #define DRV2667_PAGE_3 0x03
401c246225SDan Murphy #define DRV2667_PAGE_4 0x04
411c246225SDan Murphy #define DRV2667_PAGE_5 0x05
421c246225SDan Murphy #define DRV2667_PAGE_6 0x06
431c246225SDan Murphy #define DRV2667_PAGE_7 0x07
441c246225SDan Murphy #define DRV2667_PAGE_8 0x08
451c246225SDan Murphy
461c246225SDan Murphy /* RAM fields */
471c246225SDan Murphy #define DRV2667_RAM_HDR_SZ 0x0
481c246225SDan Murphy /* RAM Header addresses */
491c246225SDan Murphy #define DRV2667_RAM_START_HI 0x01
501c246225SDan Murphy #define DRV2667_RAM_START_LO 0x02
511c246225SDan Murphy #define DRV2667_RAM_STOP_HI 0x03
521c246225SDan Murphy #define DRV2667_RAM_STOP_LO 0x04
531c246225SDan Murphy #define DRV2667_RAM_REPEAT_CT 0x05
541c246225SDan Murphy /* RAM data addresses */
551c246225SDan Murphy #define DRV2667_RAM_AMP 0x06
561c246225SDan Murphy #define DRV2667_RAM_FREQ 0x07
571c246225SDan Murphy #define DRV2667_RAM_DURATION 0x08
581c246225SDan Murphy #define DRV2667_RAM_ENVELOPE 0x09
591c246225SDan Murphy
601c246225SDan Murphy /* Control 1 Register */
611c246225SDan Murphy #define DRV2667_25_VPP_GAIN 0x00
621c246225SDan Murphy #define DRV2667_50_VPP_GAIN 0x01
631c246225SDan Murphy #define DRV2667_75_VPP_GAIN 0x02
641c246225SDan Murphy #define DRV2667_100_VPP_GAIN 0x03
651c246225SDan Murphy #define DRV2667_DIGITAL_IN 0xfc
661c246225SDan Murphy #define DRV2667_ANALOG_IN (1 << 2)
671c246225SDan Murphy
681c246225SDan Murphy /* Control 2 Register */
691c246225SDan Murphy #define DRV2667_GO (1 << 0)
701c246225SDan Murphy #define DRV2667_STANDBY (1 << 6)
711c246225SDan Murphy #define DRV2667_DEV_RST (1 << 7)
721c246225SDan Murphy
731c246225SDan Murphy /* RAM Envelope settings */
741c246225SDan Murphy #define DRV2667_NO_ENV 0x00
751c246225SDan Murphy #define DRV2667_32_MS_ENV 0x01
761c246225SDan Murphy #define DRV2667_64_MS_ENV 0x02
771c246225SDan Murphy #define DRV2667_96_MS_ENV 0x03
781c246225SDan Murphy #define DRV2667_128_MS_ENV 0x04
791c246225SDan Murphy #define DRV2667_160_MS_ENV 0x05
801c246225SDan Murphy #define DRV2667_192_MS_ENV 0x06
811c246225SDan Murphy #define DRV2667_224_MS_ENV 0x07
821c246225SDan Murphy #define DRV2667_256_MS_ENV 0x08
831c246225SDan Murphy #define DRV2667_512_MS_ENV 0x09
841c246225SDan Murphy #define DRV2667_768_MS_ENV 0x0a
851c246225SDan Murphy #define DRV2667_1024_MS_ENV 0x0b
861c246225SDan Murphy #define DRV2667_1280_MS_ENV 0x0c
871c246225SDan Murphy #define DRV2667_1536_MS_ENV 0x0d
881c246225SDan Murphy #define DRV2667_1792_MS_ENV 0x0e
891c246225SDan Murphy #define DRV2667_2048_MS_ENV 0x0f
901c246225SDan Murphy
911c246225SDan Murphy /**
921c246225SDan Murphy * struct drv2667_data -
9317627111SLee Jones * @input_dev: Pointer to the input device
9417627111SLee Jones * @client: Pointer to the I2C client
9517627111SLee Jones * @regmap: Register map of the device
9617627111SLee Jones * @work: Work item used to off load the enable/disable of the vibration
9717627111SLee Jones * @regulator: Pointer to the regulator for the IC
9817627111SLee Jones * @page: Page number
9917627111SLee Jones * @magnitude: Magnitude of the vibration event
10017627111SLee Jones * @frequency: Frequency of the vibration event
1011c246225SDan Murphy **/
1021c246225SDan Murphy struct drv2667_data {
1031c246225SDan Murphy struct input_dev *input_dev;
1041c246225SDan Murphy struct i2c_client *client;
1051c246225SDan Murphy struct regmap *regmap;
1061c246225SDan Murphy struct work_struct work;
1071c246225SDan Murphy struct regulator *regulator;
1081c246225SDan Murphy u32 page;
1091c246225SDan Murphy u32 magnitude;
1101c246225SDan Murphy u32 frequency;
1111c246225SDan Murphy };
1121c246225SDan Murphy
113ec0843faSAxel Lin static const struct reg_default drv2667_reg_defs[] = {
1141c246225SDan Murphy { DRV2667_STATUS, 0x02 },
1151c246225SDan Murphy { DRV2667_CTRL_1, 0x28 },
1161c246225SDan Murphy { DRV2667_CTRL_2, 0x40 },
1171c246225SDan Murphy { DRV2667_WV_SEQ_0, 0x00 },
1181c246225SDan Murphy { DRV2667_WV_SEQ_1, 0x00 },
1191c246225SDan Murphy { DRV2667_WV_SEQ_2, 0x00 },
1201c246225SDan Murphy { DRV2667_WV_SEQ_3, 0x00 },
1211c246225SDan Murphy { DRV2667_WV_SEQ_4, 0x00 },
1221c246225SDan Murphy { DRV2667_WV_SEQ_5, 0x00 },
1231c246225SDan Murphy { DRV2667_WV_SEQ_6, 0x00 },
1241c246225SDan Murphy { DRV2667_WV_SEQ_7, 0x00 },
1251c246225SDan Murphy { DRV2667_FIFO, 0x00 },
1261c246225SDan Murphy { DRV2667_PAGE, 0x00 },
1271c246225SDan Murphy };
1281c246225SDan Murphy
drv2667_set_waveform_freq(struct drv2667_data * haptics)1291c246225SDan Murphy static int drv2667_set_waveform_freq(struct drv2667_data *haptics)
1301c246225SDan Murphy {
1311c246225SDan Murphy unsigned int read_buf;
1321c246225SDan Murphy int freq;
1331c246225SDan Murphy int error;
1341c246225SDan Murphy
1351c246225SDan Murphy /* Per the data sheet:
1361c246225SDan Murphy * Sinusoid Frequency (Hz) = 7.8125 x Frequency
1371c246225SDan Murphy */
1381c246225SDan Murphy freq = (haptics->frequency * 1000) / 78125;
1391c246225SDan Murphy if (freq <= 0) {
1401c246225SDan Murphy dev_err(&haptics->client->dev,
1411c246225SDan Murphy "ERROR: Frequency calculated to %i\n", freq);
1421c246225SDan Murphy return -EINVAL;
1431c246225SDan Murphy }
1441c246225SDan Murphy
1451c246225SDan Murphy error = regmap_read(haptics->regmap, DRV2667_PAGE, &read_buf);
1461c246225SDan Murphy if (error) {
1471c246225SDan Murphy dev_err(&haptics->client->dev,
1481c246225SDan Murphy "Failed to read the page number: %d\n", error);
1491c246225SDan Murphy return -EIO;
1501c246225SDan Murphy }
1511c246225SDan Murphy
1521c246225SDan Murphy if (read_buf == DRV2667_PAGE_0 ||
1531c246225SDan Murphy haptics->page != read_buf) {
1541c246225SDan Murphy error = regmap_write(haptics->regmap,
1551c246225SDan Murphy DRV2667_PAGE, haptics->page);
1561c246225SDan Murphy if (error) {
1571c246225SDan Murphy dev_err(&haptics->client->dev,
1581c246225SDan Murphy "Failed to set the page: %d\n", error);
1591c246225SDan Murphy return -EIO;
1601c246225SDan Murphy }
1611c246225SDan Murphy }
1621c246225SDan Murphy
1631c246225SDan Murphy error = regmap_write(haptics->regmap, DRV2667_RAM_FREQ, freq);
1641c246225SDan Murphy if (error)
1651c246225SDan Murphy dev_err(&haptics->client->dev,
1661c246225SDan Murphy "Failed to set the frequency: %d\n", error);
1671c246225SDan Murphy
1681c246225SDan Murphy /* Reset back to original page */
1691c246225SDan Murphy if (read_buf == DRV2667_PAGE_0 ||
1701c246225SDan Murphy haptics->page != read_buf) {
1711c246225SDan Murphy error = regmap_write(haptics->regmap, DRV2667_PAGE, read_buf);
1721c246225SDan Murphy if (error) {
1731c246225SDan Murphy dev_err(&haptics->client->dev,
1741c246225SDan Murphy "Failed to set the page: %d\n", error);
1751c246225SDan Murphy return -EIO;
1761c246225SDan Murphy }
1771c246225SDan Murphy }
1781c246225SDan Murphy
1791c246225SDan Murphy return error;
1801c246225SDan Murphy }
1811c246225SDan Murphy
drv2667_worker(struct work_struct * work)1821c246225SDan Murphy static void drv2667_worker(struct work_struct *work)
1831c246225SDan Murphy {
1841c246225SDan Murphy struct drv2667_data *haptics = container_of(work, struct drv2667_data, work);
1851c246225SDan Murphy int error;
1861c246225SDan Murphy
1871c246225SDan Murphy if (haptics->magnitude) {
1881c246225SDan Murphy error = regmap_write(haptics->regmap,
1891c246225SDan Murphy DRV2667_PAGE, haptics->page);
1901c246225SDan Murphy if (error) {
1911c246225SDan Murphy dev_err(&haptics->client->dev,
1921c246225SDan Murphy "Failed to set the page: %d\n", error);
1931c246225SDan Murphy return;
1941c246225SDan Murphy }
1951c246225SDan Murphy
1961c246225SDan Murphy error = regmap_write(haptics->regmap, DRV2667_RAM_AMP,
1971c246225SDan Murphy haptics->magnitude);
1981c246225SDan Murphy if (error) {
1991c246225SDan Murphy dev_err(&haptics->client->dev,
2001c246225SDan Murphy "Failed to set the amplitude: %d\n", error);
2011c246225SDan Murphy return;
2021c246225SDan Murphy }
2031c246225SDan Murphy
2041c246225SDan Murphy error = regmap_write(haptics->regmap,
2051c246225SDan Murphy DRV2667_PAGE, DRV2667_PAGE_0);
2061c246225SDan Murphy if (error) {
2071c246225SDan Murphy dev_err(&haptics->client->dev,
2081c246225SDan Murphy "Failed to set the page: %d\n", error);
2091c246225SDan Murphy return;
2101c246225SDan Murphy }
2111c246225SDan Murphy
2121c246225SDan Murphy error = regmap_write(haptics->regmap,
2131c246225SDan Murphy DRV2667_CTRL_2, DRV2667_GO);
2141c246225SDan Murphy if (error) {
2151c246225SDan Murphy dev_err(&haptics->client->dev,
2161c246225SDan Murphy "Failed to set the GO bit: %d\n", error);
2171c246225SDan Murphy }
2181c246225SDan Murphy } else {
2191c246225SDan Murphy error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
2201c246225SDan Murphy DRV2667_GO, 0);
2211c246225SDan Murphy if (error) {
2221c246225SDan Murphy dev_err(&haptics->client->dev,
2231c246225SDan Murphy "Failed to unset the GO bit: %d\n", error);
2241c246225SDan Murphy }
2251c246225SDan Murphy }
2261c246225SDan Murphy }
2271c246225SDan Murphy
drv2667_haptics_play(struct input_dev * input,void * data,struct ff_effect * effect)2281c246225SDan Murphy static int drv2667_haptics_play(struct input_dev *input, void *data,
2291c246225SDan Murphy struct ff_effect *effect)
2301c246225SDan Murphy {
2311c246225SDan Murphy struct drv2667_data *haptics = input_get_drvdata(input);
2321c246225SDan Murphy
2331c246225SDan Murphy if (effect->u.rumble.strong_magnitude > 0)
2341c246225SDan Murphy haptics->magnitude = effect->u.rumble.strong_magnitude;
2351c246225SDan Murphy else if (effect->u.rumble.weak_magnitude > 0)
2361c246225SDan Murphy haptics->magnitude = effect->u.rumble.weak_magnitude;
2371c246225SDan Murphy else
2381c246225SDan Murphy haptics->magnitude = 0;
2391c246225SDan Murphy
2401c246225SDan Murphy schedule_work(&haptics->work);
2411c246225SDan Murphy
2421c246225SDan Murphy return 0;
2431c246225SDan Murphy }
2441c246225SDan Murphy
drv2667_close(struct input_dev * input)2451c246225SDan Murphy static void drv2667_close(struct input_dev *input)
2461c246225SDan Murphy {
2471c246225SDan Murphy struct drv2667_data *haptics = input_get_drvdata(input);
2481c246225SDan Murphy int error;
2491c246225SDan Murphy
2501c246225SDan Murphy cancel_work_sync(&haptics->work);
2511c246225SDan Murphy
2521c246225SDan Murphy error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
2536473bbfdSFlorian Vaussard DRV2667_STANDBY, DRV2667_STANDBY);
2541c246225SDan Murphy if (error)
2551c246225SDan Murphy dev_err(&haptics->client->dev,
2561c246225SDan Murphy "Failed to enter standby mode: %d\n", error);
2571c246225SDan Murphy }
2581c246225SDan Murphy
2598019ff6cSNariman Poushin static const struct reg_sequence drv2667_init_regs[] = {
2601c246225SDan Murphy { DRV2667_CTRL_2, 0 },
2611c246225SDan Murphy { DRV2667_CTRL_1, DRV2667_25_VPP_GAIN },
2621c246225SDan Murphy { DRV2667_WV_SEQ_0, 1 },
2631c246225SDan Murphy { DRV2667_WV_SEQ_1, 0 }
2641c246225SDan Murphy };
2651c246225SDan Murphy
2668019ff6cSNariman Poushin static const struct reg_sequence drv2667_page1_init[] = {
2671c246225SDan Murphy { DRV2667_RAM_HDR_SZ, 0x05 },
2681c246225SDan Murphy { DRV2667_RAM_START_HI, 0x80 },
2691c246225SDan Murphy { DRV2667_RAM_START_LO, 0x06 },
2701c246225SDan Murphy { DRV2667_RAM_STOP_HI, 0x00 },
2711c246225SDan Murphy { DRV2667_RAM_STOP_LO, 0x09 },
2721c246225SDan Murphy { DRV2667_RAM_REPEAT_CT, 0 },
2731c246225SDan Murphy { DRV2667_RAM_DURATION, 0x05 },
2741c246225SDan Murphy { DRV2667_RAM_ENVELOPE, DRV2667_NO_ENV },
2751c246225SDan Murphy { DRV2667_RAM_AMP, 0x60 },
2761c246225SDan Murphy };
2771c246225SDan Murphy
drv2667_init(struct drv2667_data * haptics)2781c246225SDan Murphy static int drv2667_init(struct drv2667_data *haptics)
2791c246225SDan Murphy {
2801c246225SDan Murphy int error;
2811c246225SDan Murphy
2821c246225SDan Murphy /* Set default haptic frequency to 195Hz on Page 1*/
2831c246225SDan Murphy haptics->frequency = 195;
2841c246225SDan Murphy haptics->page = DRV2667_PAGE_1;
2851c246225SDan Murphy
2861c246225SDan Murphy error = regmap_register_patch(haptics->regmap,
2871c246225SDan Murphy drv2667_init_regs,
2881c246225SDan Murphy ARRAY_SIZE(drv2667_init_regs));
2891c246225SDan Murphy if (error) {
2901c246225SDan Murphy dev_err(&haptics->client->dev,
2911c246225SDan Murphy "Failed to write init registers: %d\n",
2921c246225SDan Murphy error);
2931c246225SDan Murphy return error;
2941c246225SDan Murphy }
2951c246225SDan Murphy
2961c246225SDan Murphy error = regmap_write(haptics->regmap, DRV2667_PAGE, haptics->page);
2971c246225SDan Murphy if (error) {
2981c246225SDan Murphy dev_err(&haptics->client->dev, "Failed to set page: %d\n",
2991c246225SDan Murphy error);
3001c246225SDan Murphy goto error_out;
3011c246225SDan Murphy }
3021c246225SDan Murphy
3031c246225SDan Murphy error = drv2667_set_waveform_freq(haptics);
3041c246225SDan Murphy if (error)
3051c246225SDan Murphy goto error_page;
3061c246225SDan Murphy
3071c246225SDan Murphy error = regmap_register_patch(haptics->regmap,
3081c246225SDan Murphy drv2667_page1_init,
3091c246225SDan Murphy ARRAY_SIZE(drv2667_page1_init));
3101c246225SDan Murphy if (error) {
3111c246225SDan Murphy dev_err(&haptics->client->dev,
3121c246225SDan Murphy "Failed to write page registers: %d\n",
3131c246225SDan Murphy error);
3141c246225SDan Murphy return error;
3151c246225SDan Murphy }
3161c246225SDan Murphy
3171c246225SDan Murphy error = regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0);
3181c246225SDan Murphy return error;
3191c246225SDan Murphy
3201c246225SDan Murphy error_page:
3211c246225SDan Murphy regmap_write(haptics->regmap, DRV2667_PAGE, DRV2667_PAGE_0);
3221c246225SDan Murphy error_out:
3231c246225SDan Murphy return error;
3241c246225SDan Murphy }
3251c246225SDan Murphy
3261c246225SDan Murphy static const struct regmap_config drv2667_regmap_config = {
3271c246225SDan Murphy .reg_bits = 8,
3281c246225SDan Murphy .val_bits = 8,
3291c246225SDan Murphy
3301c246225SDan Murphy .max_register = DRV2667_MAX_REG,
3311c246225SDan Murphy .reg_defaults = drv2667_reg_defs,
3321c246225SDan Murphy .num_reg_defaults = ARRAY_SIZE(drv2667_reg_defs),
3331c246225SDan Murphy .cache_type = REGCACHE_NONE,
3341c246225SDan Murphy };
3351c246225SDan Murphy
drv2667_probe(struct i2c_client * client)33618dfbd31SUwe Kleine-König static int drv2667_probe(struct i2c_client *client)
3371c246225SDan Murphy {
3381c246225SDan Murphy struct drv2667_data *haptics;
3391c246225SDan Murphy int error;
3401c246225SDan Murphy
3411c246225SDan Murphy haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
3421c246225SDan Murphy if (!haptics)
3431c246225SDan Murphy return -ENOMEM;
3441c246225SDan Murphy
3451c246225SDan Murphy haptics->regulator = devm_regulator_get(&client->dev, "vbat");
3461c246225SDan Murphy if (IS_ERR(haptics->regulator)) {
3471c246225SDan Murphy error = PTR_ERR(haptics->regulator);
3481c246225SDan Murphy dev_err(&client->dev,
3491c246225SDan Murphy "unable to get regulator, error: %d\n", error);
3501c246225SDan Murphy return error;
3511c246225SDan Murphy }
3521c246225SDan Murphy
3531c246225SDan Murphy haptics->input_dev = devm_input_allocate_device(&client->dev);
3541c246225SDan Murphy if (!haptics->input_dev) {
3551c246225SDan Murphy dev_err(&client->dev, "Failed to allocate input device\n");
3561c246225SDan Murphy return -ENOMEM;
3571c246225SDan Murphy }
3581c246225SDan Murphy
3591c246225SDan Murphy haptics->input_dev->name = "drv2667:haptics";
3601c246225SDan Murphy haptics->input_dev->dev.parent = client->dev.parent;
3611c246225SDan Murphy haptics->input_dev->close = drv2667_close;
3621c246225SDan Murphy input_set_drvdata(haptics->input_dev, haptics);
3631c246225SDan Murphy input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
3641c246225SDan Murphy
3651c246225SDan Murphy error = input_ff_create_memless(haptics->input_dev, NULL,
3661c246225SDan Murphy drv2667_haptics_play);
3671c246225SDan Murphy if (error) {
3681c246225SDan Murphy dev_err(&client->dev, "input_ff_create() failed: %d\n",
3691c246225SDan Murphy error);
3701c246225SDan Murphy return error;
3711c246225SDan Murphy }
3721c246225SDan Murphy
3731c246225SDan Murphy INIT_WORK(&haptics->work, drv2667_worker);
3741c246225SDan Murphy
3751c246225SDan Murphy haptics->client = client;
3761c246225SDan Murphy i2c_set_clientdata(client, haptics);
3771c246225SDan Murphy
3781c246225SDan Murphy haptics->regmap = devm_regmap_init_i2c(client, &drv2667_regmap_config);
3791c246225SDan Murphy if (IS_ERR(haptics->regmap)) {
3801c246225SDan Murphy error = PTR_ERR(haptics->regmap);
3811c246225SDan Murphy dev_err(&client->dev, "Failed to allocate register map: %d\n",
3821c246225SDan Murphy error);
3831c246225SDan Murphy return error;
3841c246225SDan Murphy }
3851c246225SDan Murphy
3861c246225SDan Murphy error = drv2667_init(haptics);
3871c246225SDan Murphy if (error) {
3881c246225SDan Murphy dev_err(&client->dev, "Device init failed: %d\n", error);
3891c246225SDan Murphy return error;
3901c246225SDan Murphy }
3911c246225SDan Murphy
3921c246225SDan Murphy error = input_register_device(haptics->input_dev);
3931c246225SDan Murphy if (error) {
3941c246225SDan Murphy dev_err(&client->dev, "couldn't register input device: %d\n",
3951c246225SDan Murphy error);
3961c246225SDan Murphy return error;
3971c246225SDan Murphy }
3981c246225SDan Murphy
3991c246225SDan Murphy return 0;
4001c246225SDan Murphy }
4011c246225SDan Murphy
drv2667_suspend(struct device * dev)4020e076fceSJonathan Cameron static int drv2667_suspend(struct device *dev)
4031c246225SDan Murphy {
4041c246225SDan Murphy struct drv2667_data *haptics = dev_get_drvdata(dev);
4051c246225SDan Murphy int ret = 0;
4061c246225SDan Murphy
4071c246225SDan Murphy mutex_lock(&haptics->input_dev->mutex);
4081c246225SDan Murphy
409d69f0a43SAndrzej Pietrasiewicz if (input_device_enabled(haptics->input_dev)) {
4101c246225SDan Murphy ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
4116473bbfdSFlorian Vaussard DRV2667_STANDBY, DRV2667_STANDBY);
4121c246225SDan Murphy if (ret) {
4131c246225SDan Murphy dev_err(dev, "Failed to set standby mode\n");
4141c246225SDan Murphy regulator_disable(haptics->regulator);
4151c246225SDan Murphy goto out;
4161c246225SDan Murphy }
4171c246225SDan Murphy
4181c246225SDan Murphy ret = regulator_disable(haptics->regulator);
4191c246225SDan Murphy if (ret) {
4201c246225SDan Murphy dev_err(dev, "Failed to disable regulator\n");
4211c246225SDan Murphy regmap_update_bits(haptics->regmap,
4221c246225SDan Murphy DRV2667_CTRL_2,
4231c246225SDan Murphy DRV2667_STANDBY, 0);
4241c246225SDan Murphy }
4251c246225SDan Murphy }
4261c246225SDan Murphy out:
4271c246225SDan Murphy mutex_unlock(&haptics->input_dev->mutex);
4281c246225SDan Murphy return ret;
4291c246225SDan Murphy }
4301c246225SDan Murphy
drv2667_resume(struct device * dev)4310e076fceSJonathan Cameron static int drv2667_resume(struct device *dev)
4321c246225SDan Murphy {
4331c246225SDan Murphy struct drv2667_data *haptics = dev_get_drvdata(dev);
4341c246225SDan Murphy int ret = 0;
4351c246225SDan Murphy
4361c246225SDan Murphy mutex_lock(&haptics->input_dev->mutex);
4371c246225SDan Murphy
438d69f0a43SAndrzej Pietrasiewicz if (input_device_enabled(haptics->input_dev)) {
4391c246225SDan Murphy ret = regulator_enable(haptics->regulator);
4401c246225SDan Murphy if (ret) {
4411c246225SDan Murphy dev_err(dev, "Failed to enable regulator\n");
4421c246225SDan Murphy goto out;
4431c246225SDan Murphy }
4441c246225SDan Murphy
4451c246225SDan Murphy ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
4461c246225SDan Murphy DRV2667_STANDBY, 0);
4471c246225SDan Murphy if (ret) {
4481c246225SDan Murphy dev_err(dev, "Failed to unset standby mode\n");
4491c246225SDan Murphy regulator_disable(haptics->regulator);
4501c246225SDan Murphy goto out;
4511c246225SDan Murphy }
4521c246225SDan Murphy
4531c246225SDan Murphy }
4541c246225SDan Murphy
4551c246225SDan Murphy out:
4561c246225SDan Murphy mutex_unlock(&haptics->input_dev->mutex);
4571c246225SDan Murphy return ret;
4581c246225SDan Murphy }
4591c246225SDan Murphy
4600e076fceSJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume);
4611c246225SDan Murphy
4621c246225SDan Murphy static const struct i2c_device_id drv2667_id[] = {
463*5852f2afSUwe Kleine-König { "drv2667" },
4641c246225SDan Murphy { }
4651c246225SDan Murphy };
4661c246225SDan Murphy MODULE_DEVICE_TABLE(i2c, drv2667_id);
4671c246225SDan Murphy
4681c246225SDan Murphy #ifdef CONFIG_OF
4691c246225SDan Murphy static const struct of_device_id drv2667_of_match[] = {
4701c246225SDan Murphy { .compatible = "ti,drv2667", },
4711c246225SDan Murphy { }
4721c246225SDan Murphy };
4731c246225SDan Murphy MODULE_DEVICE_TABLE(of, drv2667_of_match);
4741c246225SDan Murphy #endif
4751c246225SDan Murphy
4761c246225SDan Murphy static struct i2c_driver drv2667_driver = {
477d8bde56dSUwe Kleine-König .probe = drv2667_probe,
4781c246225SDan Murphy .driver = {
4791c246225SDan Murphy .name = "drv2667-haptics",
4801c246225SDan Murphy .of_match_table = of_match_ptr(drv2667_of_match),
4810e076fceSJonathan Cameron .pm = pm_sleep_ptr(&drv2667_pm_ops),
4821c246225SDan Murphy },
4831c246225SDan Murphy .id_table = drv2667_id,
4841c246225SDan Murphy };
4851c246225SDan Murphy module_i2c_driver(drv2667_driver);
4861c246225SDan Murphy
4871c246225SDan Murphy MODULE_DESCRIPTION("TI DRV2667 haptics driver");
4881c246225SDan Murphy MODULE_LICENSE("GPL");
4891c246225SDan Murphy MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
490