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