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 119*ec0843faSAxel 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