linux/drivers/input/misc/max8997_haptic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * MAX8997-haptic controller driver
   4 *
   5 * Copyright (C) 2012 Samsung Electronics
   6 * Donggeun Kim <dg77.kim@samsung.com>
   7 *
   8 * This program is not provided / owned by Maxim Integrated Products.
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/slab.h>
  13#include <linux/platform_device.h>
  14#include <linux/err.h>
  15#include <linux/pwm.h>
  16#include <linux/input.h>
  17#include <linux/mfd/max8997-private.h>
  18#include <linux/mfd/max8997.h>
  19#include <linux/regulator/consumer.h>
  20
  21/* Haptic configuration 2 register */
  22#define MAX8997_MOTOR_TYPE_SHIFT        7
  23#define MAX8997_ENABLE_SHIFT            6
  24#define MAX8997_MODE_SHIFT              5
  25
  26/* Haptic driver configuration register */
  27#define MAX8997_CYCLE_SHIFT             6
  28#define MAX8997_SIG_PERIOD_SHIFT        4
  29#define MAX8997_SIG_DUTY_SHIFT          2
  30#define MAX8997_PWM_DUTY_SHIFT          0
  31
  32struct max8997_haptic {
  33        struct device *dev;
  34        struct i2c_client *client;
  35        struct input_dev *input_dev;
  36        struct regulator *regulator;
  37
  38        struct work_struct work;
  39        struct mutex mutex;
  40
  41        bool enabled;
  42        unsigned int level;
  43
  44        struct pwm_device *pwm;
  45        unsigned int pwm_period;
  46        enum max8997_haptic_pwm_divisor pwm_divisor;
  47
  48        enum max8997_haptic_motor_type type;
  49        enum max8997_haptic_pulse_mode mode;
  50
  51        unsigned int internal_mode_pattern;
  52        unsigned int pattern_cycle;
  53        unsigned int pattern_signal_period;
  54};
  55
  56static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
  57{
  58        int ret = 0;
  59
  60        if (chip->mode == MAX8997_EXTERNAL_MODE) {
  61                unsigned int duty = chip->pwm_period * chip->level / 100;
  62                ret = pwm_config(chip->pwm, duty, chip->pwm_period);
  63        } else {
  64                u8 duty_index = 0;
  65
  66                duty_index = DIV_ROUND_UP(chip->level * 64, 100);
  67
  68                switch (chip->internal_mode_pattern) {
  69                case 0:
  70                        max8997_write_reg(chip->client,
  71                                MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
  72                        break;
  73                case 1:
  74                        max8997_write_reg(chip->client,
  75                                MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
  76                        break;
  77                case 2:
  78                        max8997_write_reg(chip->client,
  79                                MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
  80                        break;
  81                case 3:
  82                        max8997_write_reg(chip->client,
  83                                MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
  84                        break;
  85                default:
  86                        break;
  87                }
  88        }
  89        return ret;
  90}
  91
  92static void max8997_haptic_configure(struct max8997_haptic *chip)
  93{
  94        u8 value;
  95
  96        value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
  97                chip->enabled << MAX8997_ENABLE_SHIFT |
  98                chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
  99        max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
 100
 101        if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
 102                value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |
 103                        chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
 104                        chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
 105                        chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;
 106                max8997_write_reg(chip->client,
 107                        MAX8997_HAPTIC_REG_DRVCONF, value);
 108
 109                switch (chip->internal_mode_pattern) {
 110                case 0:
 111                        value = chip->pattern_cycle << 4;
 112                        max8997_write_reg(chip->client,
 113                                MAX8997_HAPTIC_REG_CYCLECONF1, value);
 114                        value = chip->pattern_signal_period;
 115                        max8997_write_reg(chip->client,
 116                                MAX8997_HAPTIC_REG_SIGCONF1, value);
 117                        break;
 118
 119                case 1:
 120                        value = chip->pattern_cycle;
 121                        max8997_write_reg(chip->client,
 122                                MAX8997_HAPTIC_REG_CYCLECONF1, value);
 123                        value = chip->pattern_signal_period;
 124                        max8997_write_reg(chip->client,
 125                                MAX8997_HAPTIC_REG_SIGCONF2, value);
 126                        break;
 127
 128                case 2:
 129                        value = chip->pattern_cycle << 4;
 130                        max8997_write_reg(chip->client,
 131                                MAX8997_HAPTIC_REG_CYCLECONF2, value);
 132                        value = chip->pattern_signal_period;
 133                        max8997_write_reg(chip->client,
 134                                MAX8997_HAPTIC_REG_SIGCONF3, value);
 135                        break;
 136
 137                case 3:
 138                        value = chip->pattern_cycle;
 139                        max8997_write_reg(chip->client,
 140                                MAX8997_HAPTIC_REG_CYCLECONF2, value);
 141                        value = chip->pattern_signal_period;
 142                        max8997_write_reg(chip->client,
 143                                MAX8997_HAPTIC_REG_SIGCONF4, value);
 144                        break;
 145
 146                default:
 147                        break;
 148                }
 149        }
 150}
 151
 152static void max8997_haptic_enable(struct max8997_haptic *chip)
 153{
 154        int error;
 155
 156        mutex_lock(&chip->mutex);
 157
 158        error = max8997_haptic_set_duty_cycle(chip);
 159        if (error) {
 160                dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error);
 161                goto out;
 162        }
 163
 164        if (!chip->enabled) {
 165                error = regulator_enable(chip->regulator);
 166                if (error) {
 167                        dev_err(chip->dev, "Failed to enable regulator\n");
 168                        goto out;
 169                }
 170                max8997_haptic_configure(chip);
 171                if (chip->mode == MAX8997_EXTERNAL_MODE) {
 172                        error = pwm_enable(chip->pwm);
 173                        if (error) {
 174                                dev_err(chip->dev, "Failed to enable PWM\n");
 175                                regulator_disable(chip->regulator);
 176                                goto out;
 177                        }
 178                }
 179                chip->enabled = true;
 180        }
 181
 182out:
 183        mutex_unlock(&chip->mutex);
 184}
 185
 186static void max8997_haptic_disable(struct max8997_haptic *chip)
 187{
 188        mutex_lock(&chip->mutex);
 189
 190        if (chip->enabled) {
 191                chip->enabled = false;
 192                max8997_haptic_configure(chip);
 193                if (chip->mode == MAX8997_EXTERNAL_MODE)
 194                        pwm_disable(chip->pwm);
 195                regulator_disable(chip->regulator);
 196        }
 197
 198        mutex_unlock(&chip->mutex);
 199}
 200
 201static void max8997_haptic_play_effect_work(struct work_struct *work)
 202{
 203        struct max8997_haptic *chip =
 204                        container_of(work, struct max8997_haptic, work);
 205
 206        if (chip->level)
 207                max8997_haptic_enable(chip);
 208        else
 209                max8997_haptic_disable(chip);
 210}
 211
 212static int max8997_haptic_play_effect(struct input_dev *dev, void *data,
 213                                  struct ff_effect *effect)
 214{
 215        struct max8997_haptic *chip = input_get_drvdata(dev);
 216
 217        chip->level = effect->u.rumble.strong_magnitude;
 218        if (!chip->level)
 219                chip->level = effect->u.rumble.weak_magnitude;
 220
 221        schedule_work(&chip->work);
 222
 223        return 0;
 224}
 225
 226static void max8997_haptic_close(struct input_dev *dev)
 227{
 228        struct max8997_haptic *chip = input_get_drvdata(dev);
 229
 230        cancel_work_sync(&chip->work);
 231        max8997_haptic_disable(chip);
 232}
 233
 234static int max8997_haptic_probe(struct platform_device *pdev)
 235{
 236        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 237        const struct max8997_platform_data *pdata =
 238                                        dev_get_platdata(iodev->dev);
 239        const struct max8997_haptic_platform_data *haptic_pdata = NULL;
 240        struct max8997_haptic *chip;
 241        struct input_dev *input_dev;
 242        int error;
 243
 244        if (pdata)
 245                haptic_pdata = pdata->haptic_pdata;
 246
 247        if (!haptic_pdata) {
 248                dev_err(&pdev->dev, "no haptic platform data\n");
 249                return -EINVAL;
 250        }
 251
 252        chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL);
 253        input_dev = input_allocate_device();
 254        if (!chip || !input_dev) {
 255                dev_err(&pdev->dev, "unable to allocate memory\n");
 256                error = -ENOMEM;
 257                goto err_free_mem;
 258        }
 259
 260        INIT_WORK(&chip->work, max8997_haptic_play_effect_work);
 261        mutex_init(&chip->mutex);
 262
 263        chip->client = iodev->haptic;
 264        chip->dev = &pdev->dev;
 265        chip->input_dev = input_dev;
 266        chip->pwm_period = haptic_pdata->pwm_period;
 267        chip->type = haptic_pdata->type;
 268        chip->mode = haptic_pdata->mode;
 269        chip->pwm_divisor = haptic_pdata->pwm_divisor;
 270
 271        switch (chip->mode) {
 272        case MAX8997_INTERNAL_MODE:
 273                chip->internal_mode_pattern =
 274                                haptic_pdata->internal_mode_pattern;
 275                chip->pattern_cycle = haptic_pdata->pattern_cycle;
 276                chip->pattern_signal_period =
 277                                haptic_pdata->pattern_signal_period;
 278                break;
 279
 280        case MAX8997_EXTERNAL_MODE:
 281                chip->pwm = pwm_request(haptic_pdata->pwm_channel_id,
 282                                        "max8997-haptic");
 283                if (IS_ERR(chip->pwm)) {
 284                        error = PTR_ERR(chip->pwm);
 285                        dev_err(&pdev->dev,
 286                                "unable to request PWM for haptic, error: %d\n",
 287                                error);
 288                        goto err_free_mem;
 289                }
 290
 291                /*
 292                 * FIXME: pwm_apply_args() should be removed when switching to
 293                 * the atomic PWM API.
 294                 */
 295                pwm_apply_args(chip->pwm);
 296                break;
 297
 298        default:
 299                dev_err(&pdev->dev,
 300                        "Invalid chip mode specified (%d)\n", chip->mode);
 301                error = -EINVAL;
 302                goto err_free_mem;
 303        }
 304
 305        chip->regulator = regulator_get(&pdev->dev, "inmotor");
 306        if (IS_ERR(chip->regulator)) {
 307                error = PTR_ERR(chip->regulator);
 308                dev_err(&pdev->dev,
 309                        "unable to get regulator, error: %d\n",
 310                        error);
 311                goto err_free_pwm;
 312        }
 313
 314        input_dev->name = "max8997-haptic";
 315        input_dev->id.version = 1;
 316        input_dev->dev.parent = &pdev->dev;
 317        input_dev->close = max8997_haptic_close;
 318        input_set_drvdata(input_dev, chip);
 319        input_set_capability(input_dev, EV_FF, FF_RUMBLE);
 320
 321        error = input_ff_create_memless(input_dev, NULL,
 322                                max8997_haptic_play_effect);
 323        if (error) {
 324                dev_err(&pdev->dev,
 325                        "unable to create FF device, error: %d\n",
 326                        error);
 327                goto err_put_regulator;
 328        }
 329
 330        error = input_register_device(input_dev);
 331        if (error) {
 332                dev_err(&pdev->dev,
 333                        "unable to register input device, error: %d\n",
 334                        error);
 335                goto err_destroy_ff;
 336        }
 337
 338        platform_set_drvdata(pdev, chip);
 339        return 0;
 340
 341err_destroy_ff:
 342        input_ff_destroy(input_dev);
 343err_put_regulator:
 344        regulator_put(chip->regulator);
 345err_free_pwm:
 346        if (chip->mode == MAX8997_EXTERNAL_MODE)
 347                pwm_free(chip->pwm);
 348err_free_mem:
 349        input_free_device(input_dev);
 350        kfree(chip);
 351
 352        return error;
 353}
 354
 355static int max8997_haptic_remove(struct platform_device *pdev)
 356{
 357        struct max8997_haptic *chip = platform_get_drvdata(pdev);
 358
 359        input_unregister_device(chip->input_dev);
 360        regulator_put(chip->regulator);
 361
 362        if (chip->mode == MAX8997_EXTERNAL_MODE)
 363                pwm_free(chip->pwm);
 364
 365        kfree(chip);
 366
 367        return 0;
 368}
 369
 370static int __maybe_unused max8997_haptic_suspend(struct device *dev)
 371{
 372        struct platform_device *pdev = to_platform_device(dev);
 373        struct max8997_haptic *chip = platform_get_drvdata(pdev);
 374
 375        max8997_haptic_disable(chip);
 376
 377        return 0;
 378}
 379
 380static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL);
 381
 382static const struct platform_device_id max8997_haptic_id[] = {
 383        { "max8997-haptic", 0 },
 384        { },
 385};
 386MODULE_DEVICE_TABLE(platform, max8997_haptic_id);
 387
 388static struct platform_driver max8997_haptic_driver = {
 389        .driver = {
 390                .name   = "max8997-haptic",
 391                .pm     = &max8997_haptic_pm_ops,
 392        },
 393        .probe          = max8997_haptic_probe,
 394        .remove         = max8997_haptic_remove,
 395        .id_table       = max8997_haptic_id,
 396};
 397module_platform_driver(max8997_haptic_driver);
 398
 399MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
 400MODULE_DESCRIPTION("max8997_haptic driver");
 401MODULE_LICENSE("GPL");
 402