linux/drivers/input/misc/drv2665.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * DRV2665 haptics driver family
   4 *
   5 * Author: Dan Murphy <dmurphy@ti.com>
   6 *
   7 * Copyright: (C) 2015 Texas Instruments, Inc.
   8 */
   9
  10#include <linux/i2c.h>
  11#include <linux/input.h>
  12#include <linux/module.h>
  13#include <linux/regmap.h>
  14#include <linux/slab.h>
  15#include <linux/delay.h>
  16#include <linux/regulator/consumer.h>
  17
  18/* Contol registers */
  19#define DRV2665_STATUS  0x00
  20#define DRV2665_CTRL_1  0x01
  21#define DRV2665_CTRL_2  0x02
  22#define DRV2665_FIFO    0x0b
  23
  24/* Status Register */
  25#define DRV2665_FIFO_FULL               BIT(0)
  26#define DRV2665_FIFO_EMPTY              BIT(1)
  27
  28/* Control 1 Register */
  29#define DRV2665_25_VPP_GAIN             0x00
  30#define DRV2665_50_VPP_GAIN             0x01
  31#define DRV2665_75_VPP_GAIN             0x02
  32#define DRV2665_100_VPP_GAIN            0x03
  33#define DRV2665_DIGITAL_IN              0xfc
  34#define DRV2665_ANALOG_IN               BIT(2)
  35
  36/* Control 2 Register */
  37#define DRV2665_BOOST_EN                BIT(1)
  38#define DRV2665_STANDBY                 BIT(6)
  39#define DRV2665_DEV_RST                 BIT(7)
  40#define DRV2665_5_MS_IDLE_TOUT          0x00
  41#define DRV2665_10_MS_IDLE_TOUT         0x04
  42#define DRV2665_15_MS_IDLE_TOUT         0x08
  43#define DRV2665_20_MS_IDLE_TOUT         0x0c
  44
  45/**
  46 * struct drv2665_data -
  47 * @input_dev: Pointer to the input device
  48 * @client: Pointer to the I2C client
  49 * @regmap: Register map of the device
  50 * @work: Work item used to off load the enable/disable of the vibration
  51 * @regulator: Pointer to the regulator for the IC
  52 */
  53struct drv2665_data {
  54        struct input_dev *input_dev;
  55        struct i2c_client *client;
  56        struct regmap *regmap;
  57        struct work_struct work;
  58        struct regulator *regulator;
  59};
  60
  61/* 8kHz Sine wave to stream to the FIFO */
  62static const u8 drv2665_sine_wave_form[] = {
  63        0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66,
  64        0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10,
  65        0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a,
  66        0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00,
  67};
  68
  69static const struct reg_default drv2665_reg_defs[] = {
  70        { DRV2665_STATUS, 0x02 },
  71        { DRV2665_CTRL_1, 0x28 },
  72        { DRV2665_CTRL_2, 0x40 },
  73        { DRV2665_FIFO, 0x00 },
  74};
  75
  76static void drv2665_worker(struct work_struct *work)
  77{
  78        struct drv2665_data *haptics =
  79                                container_of(work, struct drv2665_data, work);
  80        unsigned int read_buf;
  81        int error;
  82
  83        error = regmap_read(haptics->regmap, DRV2665_STATUS, &read_buf);
  84        if (error) {
  85                dev_err(&haptics->client->dev,
  86                        "Failed to read status: %d\n", error);
  87                return;
  88        }
  89
  90        if (read_buf & DRV2665_FIFO_EMPTY) {
  91                error = regmap_bulk_write(haptics->regmap,
  92                                          DRV2665_FIFO,
  93                                          drv2665_sine_wave_form,
  94                                          ARRAY_SIZE(drv2665_sine_wave_form));
  95                if (error) {
  96                        dev_err(&haptics->client->dev,
  97                                "Failed to write FIFO: %d\n", error);
  98                        return;
  99                }
 100        }
 101}
 102
 103static int drv2665_haptics_play(struct input_dev *input, void *data,
 104                                struct ff_effect *effect)
 105{
 106        struct drv2665_data *haptics = input_get_drvdata(input);
 107
 108        schedule_work(&haptics->work);
 109
 110        return 0;
 111}
 112
 113static void drv2665_close(struct input_dev *input)
 114{
 115        struct drv2665_data *haptics = input_get_drvdata(input);
 116        int error;
 117
 118        cancel_work_sync(&haptics->work);
 119
 120        error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
 121                                   DRV2665_STANDBY, DRV2665_STANDBY);
 122        if (error)
 123                dev_err(&haptics->client->dev,
 124                        "Failed to enter standby mode: %d\n", error);
 125}
 126
 127static const struct reg_sequence drv2665_init_regs[] = {
 128        { DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT },
 129        { DRV2665_CTRL_1, DRV2665_25_VPP_GAIN },
 130};
 131
 132static int drv2665_init(struct drv2665_data *haptics)
 133{
 134        int error;
 135
 136        error = regmap_register_patch(haptics->regmap,
 137                                      drv2665_init_regs,
 138                                      ARRAY_SIZE(drv2665_init_regs));
 139        if (error) {
 140                dev_err(&haptics->client->dev,
 141                        "Failed to write init registers: %d\n",
 142                        error);
 143                return error;
 144        }
 145
 146        return 0;
 147}
 148
 149static const struct regmap_config drv2665_regmap_config = {
 150        .reg_bits = 8,
 151        .val_bits = 8,
 152
 153        .max_register = DRV2665_FIFO,
 154        .reg_defaults = drv2665_reg_defs,
 155        .num_reg_defaults = ARRAY_SIZE(drv2665_reg_defs),
 156        .cache_type = REGCACHE_NONE,
 157};
 158
 159static int drv2665_probe(struct i2c_client *client,
 160                         const struct i2c_device_id *id)
 161{
 162        struct drv2665_data *haptics;
 163        int error;
 164
 165        haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
 166        if (!haptics)
 167                return -ENOMEM;
 168
 169        haptics->regulator = devm_regulator_get(&client->dev, "vbat");
 170        if (IS_ERR(haptics->regulator)) {
 171                error = PTR_ERR(haptics->regulator);
 172                dev_err(&client->dev,
 173                        "unable to get regulator, error: %d\n", error);
 174                return error;
 175        }
 176
 177        haptics->input_dev = devm_input_allocate_device(&client->dev);
 178        if (!haptics->input_dev) {
 179                dev_err(&client->dev, "Failed to allocate input device\n");
 180                return -ENOMEM;
 181        }
 182
 183        haptics->input_dev->name = "drv2665:haptics";
 184        haptics->input_dev->dev.parent = client->dev.parent;
 185        haptics->input_dev->close = drv2665_close;
 186        input_set_drvdata(haptics->input_dev, haptics);
 187        input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
 188
 189        error = input_ff_create_memless(haptics->input_dev, NULL,
 190                                        drv2665_haptics_play);
 191        if (error) {
 192                dev_err(&client->dev, "input_ff_create() failed: %d\n",
 193                        error);
 194                return error;
 195        }
 196
 197        INIT_WORK(&haptics->work, drv2665_worker);
 198
 199        haptics->client = client;
 200        i2c_set_clientdata(client, haptics);
 201
 202        haptics->regmap = devm_regmap_init_i2c(client, &drv2665_regmap_config);
 203        if (IS_ERR(haptics->regmap)) {
 204                error = PTR_ERR(haptics->regmap);
 205                dev_err(&client->dev, "Failed to allocate register map: %d\n",
 206                        error);
 207                return error;
 208        }
 209
 210        error = drv2665_init(haptics);
 211        if (error) {
 212                dev_err(&client->dev, "Device init failed: %d\n", error);
 213                return error;
 214        }
 215
 216        error = input_register_device(haptics->input_dev);
 217        if (error) {
 218                dev_err(&client->dev, "couldn't register input device: %d\n",
 219                        error);
 220                return error;
 221        }
 222
 223        return 0;
 224}
 225
 226static int __maybe_unused drv2665_suspend(struct device *dev)
 227{
 228        struct drv2665_data *haptics = dev_get_drvdata(dev);
 229        int ret = 0;
 230
 231        mutex_lock(&haptics->input_dev->mutex);
 232
 233        if (input_device_enabled(haptics->input_dev)) {
 234                ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
 235                                         DRV2665_STANDBY, DRV2665_STANDBY);
 236                if (ret) {
 237                        dev_err(dev, "Failed to set standby mode\n");
 238                        regulator_disable(haptics->regulator);
 239                        goto out;
 240                }
 241
 242                ret = regulator_disable(haptics->regulator);
 243                if (ret) {
 244                        dev_err(dev, "Failed to disable regulator\n");
 245                        regmap_update_bits(haptics->regmap,
 246                                           DRV2665_CTRL_2,
 247                                           DRV2665_STANDBY, 0);
 248                }
 249        }
 250out:
 251        mutex_unlock(&haptics->input_dev->mutex);
 252        return ret;
 253}
 254
 255static int __maybe_unused drv2665_resume(struct device *dev)
 256{
 257        struct drv2665_data *haptics = dev_get_drvdata(dev);
 258        int ret = 0;
 259
 260        mutex_lock(&haptics->input_dev->mutex);
 261
 262        if (input_device_enabled(haptics->input_dev)) {
 263                ret = regulator_enable(haptics->regulator);
 264                if (ret) {
 265                        dev_err(dev, "Failed to enable regulator\n");
 266                        goto out;
 267                }
 268
 269                ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
 270                                         DRV2665_STANDBY, 0);
 271                if (ret) {
 272                        dev_err(dev, "Failed to unset standby mode\n");
 273                        regulator_disable(haptics->regulator);
 274                        goto out;
 275                }
 276
 277        }
 278
 279out:
 280        mutex_unlock(&haptics->input_dev->mutex);
 281        return ret;
 282}
 283
 284static SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume);
 285
 286static const struct i2c_device_id drv2665_id[] = {
 287        { "drv2665", 0 },
 288        { }
 289};
 290MODULE_DEVICE_TABLE(i2c, drv2665_id);
 291
 292#ifdef CONFIG_OF
 293static const struct of_device_id drv2665_of_match[] = {
 294        { .compatible = "ti,drv2665", },
 295        { }
 296};
 297MODULE_DEVICE_TABLE(of, drv2665_of_match);
 298#endif
 299
 300static struct i2c_driver drv2665_driver = {
 301        .probe          = drv2665_probe,
 302        .driver         = {
 303                .name   = "drv2665-haptics",
 304                .of_match_table = of_match_ptr(drv2665_of_match),
 305                .pm     = &drv2665_pm_ops,
 306        },
 307        .id_table = drv2665_id,
 308};
 309module_i2c_driver(drv2665_driver);
 310
 311MODULE_DESCRIPTION("TI DRV2665 haptics driver");
 312MODULE_LICENSE("GPL");
 313MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
 314