Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * DRV2665 haptics driver family
0004  *
0005  * Author: Dan Murphy <dmurphy@ti.com>
0006  *
0007  * Copyright: (C) 2015 Texas Instruments, Inc.
0008  */
0009 
0010 #include <linux/i2c.h>
0011 #include <linux/input.h>
0012 #include <linux/module.h>
0013 #include <linux/regmap.h>
0014 #include <linux/slab.h>
0015 #include <linux/delay.h>
0016 #include <linux/regulator/consumer.h>
0017 
0018 /* Contol registers */
0019 #define DRV2665_STATUS  0x00
0020 #define DRV2665_CTRL_1  0x01
0021 #define DRV2665_CTRL_2  0x02
0022 #define DRV2665_FIFO    0x0b
0023 
0024 /* Status Register */
0025 #define DRV2665_FIFO_FULL       BIT(0)
0026 #define DRV2665_FIFO_EMPTY      BIT(1)
0027 
0028 /* Control 1 Register */
0029 #define DRV2665_25_VPP_GAIN     0x00
0030 #define DRV2665_50_VPP_GAIN     0x01
0031 #define DRV2665_75_VPP_GAIN     0x02
0032 #define DRV2665_100_VPP_GAIN        0x03
0033 #define DRV2665_DIGITAL_IN      0xfc
0034 #define DRV2665_ANALOG_IN       BIT(2)
0035 
0036 /* Control 2 Register */
0037 #define DRV2665_BOOST_EN        BIT(1)
0038 #define DRV2665_STANDBY         BIT(6)
0039 #define DRV2665_DEV_RST         BIT(7)
0040 #define DRV2665_5_MS_IDLE_TOUT      0x00
0041 #define DRV2665_10_MS_IDLE_TOUT     0x04
0042 #define DRV2665_15_MS_IDLE_TOUT     0x08
0043 #define DRV2665_20_MS_IDLE_TOUT     0x0c
0044 
0045 /**
0046  * struct drv2665_data -
0047  * @input_dev: Pointer to the input device
0048  * @client: Pointer to the I2C client
0049  * @regmap: Register map of the device
0050  * @work: Work item used to off load the enable/disable of the vibration
0051  * @regulator: Pointer to the regulator for the IC
0052  */
0053 struct drv2665_data {
0054     struct input_dev *input_dev;
0055     struct i2c_client *client;
0056     struct regmap *regmap;
0057     struct work_struct work;
0058     struct regulator *regulator;
0059 };
0060 
0061 /* 8kHz Sine wave to stream to the FIFO */
0062 static const u8 drv2665_sine_wave_form[] = {
0063     0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66,
0064     0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10,
0065     0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a,
0066     0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00,
0067 };
0068 
0069 static const struct reg_default drv2665_reg_defs[] = {
0070     { DRV2665_STATUS, 0x02 },
0071     { DRV2665_CTRL_1, 0x28 },
0072     { DRV2665_CTRL_2, 0x40 },
0073     { DRV2665_FIFO, 0x00 },
0074 };
0075 
0076 static void drv2665_worker(struct work_struct *work)
0077 {
0078     struct drv2665_data *haptics =
0079                 container_of(work, struct drv2665_data, work);
0080     unsigned int read_buf;
0081     int error;
0082 
0083     error = regmap_read(haptics->regmap, DRV2665_STATUS, &read_buf);
0084     if (error) {
0085         dev_err(&haptics->client->dev,
0086             "Failed to read status: %d\n", error);
0087         return;
0088     }
0089 
0090     if (read_buf & DRV2665_FIFO_EMPTY) {
0091         error = regmap_bulk_write(haptics->regmap,
0092                       DRV2665_FIFO,
0093                       drv2665_sine_wave_form,
0094                       ARRAY_SIZE(drv2665_sine_wave_form));
0095         if (error) {
0096             dev_err(&haptics->client->dev,
0097                 "Failed to write FIFO: %d\n", error);
0098             return;
0099         }
0100     }
0101 }
0102 
0103 static int drv2665_haptics_play(struct input_dev *input, void *data,
0104                 struct ff_effect *effect)
0105 {
0106     struct drv2665_data *haptics = input_get_drvdata(input);
0107 
0108     schedule_work(&haptics->work);
0109 
0110     return 0;
0111 }
0112 
0113 static void drv2665_close(struct input_dev *input)
0114 {
0115     struct drv2665_data *haptics = input_get_drvdata(input);
0116     int error;
0117 
0118     cancel_work_sync(&haptics->work);
0119 
0120     error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
0121                    DRV2665_STANDBY, DRV2665_STANDBY);
0122     if (error)
0123         dev_err(&haptics->client->dev,
0124             "Failed to enter standby mode: %d\n", error);
0125 }
0126 
0127 static const struct reg_sequence drv2665_init_regs[] = {
0128     { DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT },
0129     { DRV2665_CTRL_1, DRV2665_25_VPP_GAIN },
0130 };
0131 
0132 static int drv2665_init(struct drv2665_data *haptics)
0133 {
0134     int error;
0135 
0136     error = regmap_register_patch(haptics->regmap,
0137                       drv2665_init_regs,
0138                       ARRAY_SIZE(drv2665_init_regs));
0139     if (error) {
0140         dev_err(&haptics->client->dev,
0141             "Failed to write init registers: %d\n",
0142             error);
0143         return error;
0144     }
0145 
0146     return 0;
0147 }
0148 
0149 static const struct regmap_config drv2665_regmap_config = {
0150     .reg_bits = 8,
0151     .val_bits = 8,
0152 
0153     .max_register = DRV2665_FIFO,
0154     .reg_defaults = drv2665_reg_defs,
0155     .num_reg_defaults = ARRAY_SIZE(drv2665_reg_defs),
0156     .cache_type = REGCACHE_NONE,
0157 };
0158 
0159 static int drv2665_probe(struct i2c_client *client,
0160              const struct i2c_device_id *id)
0161 {
0162     struct drv2665_data *haptics;
0163     int error;
0164 
0165     haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
0166     if (!haptics)
0167         return -ENOMEM;
0168 
0169     haptics->regulator = devm_regulator_get(&client->dev, "vbat");
0170     if (IS_ERR(haptics->regulator)) {
0171         error = PTR_ERR(haptics->regulator);
0172         dev_err(&client->dev,
0173             "unable to get regulator, error: %d\n", error);
0174         return error;
0175     }
0176 
0177     haptics->input_dev = devm_input_allocate_device(&client->dev);
0178     if (!haptics->input_dev) {
0179         dev_err(&client->dev, "Failed to allocate input device\n");
0180         return -ENOMEM;
0181     }
0182 
0183     haptics->input_dev->name = "drv2665:haptics";
0184     haptics->input_dev->dev.parent = client->dev.parent;
0185     haptics->input_dev->close = drv2665_close;
0186     input_set_drvdata(haptics->input_dev, haptics);
0187     input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
0188 
0189     error = input_ff_create_memless(haptics->input_dev, NULL,
0190                     drv2665_haptics_play);
0191     if (error) {
0192         dev_err(&client->dev, "input_ff_create() failed: %d\n",
0193             error);
0194         return error;
0195     }
0196 
0197     INIT_WORK(&haptics->work, drv2665_worker);
0198 
0199     haptics->client = client;
0200     i2c_set_clientdata(client, haptics);
0201 
0202     haptics->regmap = devm_regmap_init_i2c(client, &drv2665_regmap_config);
0203     if (IS_ERR(haptics->regmap)) {
0204         error = PTR_ERR(haptics->regmap);
0205         dev_err(&client->dev, "Failed to allocate register map: %d\n",
0206             error);
0207         return error;
0208     }
0209 
0210     error = drv2665_init(haptics);
0211     if (error) {
0212         dev_err(&client->dev, "Device init failed: %d\n", error);
0213         return error;
0214     }
0215 
0216     error = input_register_device(haptics->input_dev);
0217     if (error) {
0218         dev_err(&client->dev, "couldn't register input device: %d\n",
0219             error);
0220         return error;
0221     }
0222 
0223     return 0;
0224 }
0225 
0226 static int __maybe_unused drv2665_suspend(struct device *dev)
0227 {
0228     struct drv2665_data *haptics = dev_get_drvdata(dev);
0229     int ret = 0;
0230 
0231     mutex_lock(&haptics->input_dev->mutex);
0232 
0233     if (input_device_enabled(haptics->input_dev)) {
0234         ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
0235                      DRV2665_STANDBY, DRV2665_STANDBY);
0236         if (ret) {
0237             dev_err(dev, "Failed to set standby mode\n");
0238             regulator_disable(haptics->regulator);
0239             goto out;
0240         }
0241 
0242         ret = regulator_disable(haptics->regulator);
0243         if (ret) {
0244             dev_err(dev, "Failed to disable regulator\n");
0245             regmap_update_bits(haptics->regmap,
0246                        DRV2665_CTRL_2,
0247                        DRV2665_STANDBY, 0);
0248         }
0249     }
0250 out:
0251     mutex_unlock(&haptics->input_dev->mutex);
0252     return ret;
0253 }
0254 
0255 static int __maybe_unused drv2665_resume(struct device *dev)
0256 {
0257     struct drv2665_data *haptics = dev_get_drvdata(dev);
0258     int ret = 0;
0259 
0260     mutex_lock(&haptics->input_dev->mutex);
0261 
0262     if (input_device_enabled(haptics->input_dev)) {
0263         ret = regulator_enable(haptics->regulator);
0264         if (ret) {
0265             dev_err(dev, "Failed to enable regulator\n");
0266             goto out;
0267         }
0268 
0269         ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
0270                      DRV2665_STANDBY, 0);
0271         if (ret) {
0272             dev_err(dev, "Failed to unset standby mode\n");
0273             regulator_disable(haptics->regulator);
0274             goto out;
0275         }
0276 
0277     }
0278 
0279 out:
0280     mutex_unlock(&haptics->input_dev->mutex);
0281     return ret;
0282 }
0283 
0284 static SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume);
0285 
0286 static const struct i2c_device_id drv2665_id[] = {
0287     { "drv2665", 0 },
0288     { }
0289 };
0290 MODULE_DEVICE_TABLE(i2c, drv2665_id);
0291 
0292 #ifdef CONFIG_OF
0293 static const struct of_device_id drv2665_of_match[] = {
0294     { .compatible = "ti,drv2665", },
0295     { }
0296 };
0297 MODULE_DEVICE_TABLE(of, drv2665_of_match);
0298 #endif
0299 
0300 static struct i2c_driver drv2665_driver = {
0301     .probe      = drv2665_probe,
0302     .driver     = {
0303         .name   = "drv2665-haptics",
0304         .of_match_table = of_match_ptr(drv2665_of_match),
0305         .pm = &drv2665_pm_ops,
0306     },
0307     .id_table = drv2665_id,
0308 };
0309 module_i2c_driver(drv2665_driver);
0310 
0311 MODULE_DESCRIPTION("TI DRV2665 haptics driver");
0312 MODULE_LICENSE("GPL");
0313 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");