xref: /openbmc/linux/drivers/input/misc/drv2667.c (revision d8bde56d)
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[] = {
4631c246225SDan Murphy 	{ "drv2667", 0 },
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 = {
477*d8bde56dSUwe 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