linux/drivers/input/misc/pwm-vibra.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  PWM vibrator driver
   4 *
   5 *  Copyright (C) 2017 Collabora Ltd.
   6 *
   7 *  Based on previous work from:
   8 *  Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com>
   9 *
  10 *  Based on PWM beeper driver:
  11 *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
  12 */
  13
  14#include <linux/input.h>
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/of_device.h>
  18#include <linux/platform_device.h>
  19#include <linux/property.h>
  20#include <linux/pwm.h>
  21#include <linux/regulator/consumer.h>
  22#include <linux/slab.h>
  23
  24struct pwm_vibrator {
  25        struct input_dev *input;
  26        struct pwm_device *pwm;
  27        struct pwm_device *pwm_dir;
  28        struct regulator *vcc;
  29
  30        struct work_struct play_work;
  31        u16 level;
  32        u32 direction_duty_cycle;
  33        bool vcc_on;
  34};
  35
  36static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
  37{
  38        struct device *pdev = vibrator->input->dev.parent;
  39        struct pwm_state state;
  40        int err;
  41
  42        if (!vibrator->vcc_on) {
  43                err = regulator_enable(vibrator->vcc);
  44                if (err) {
  45                        dev_err(pdev, "failed to enable regulator: %d", err);
  46                        return err;
  47                }
  48                vibrator->vcc_on = true;
  49        }
  50
  51        pwm_get_state(vibrator->pwm, &state);
  52        pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff);
  53        state.enabled = true;
  54
  55        err = pwm_apply_state(vibrator->pwm, &state);
  56        if (err) {
  57                dev_err(pdev, "failed to apply pwm state: %d", err);
  58                return err;
  59        }
  60
  61        if (vibrator->pwm_dir) {
  62                pwm_get_state(vibrator->pwm_dir, &state);
  63                state.duty_cycle = vibrator->direction_duty_cycle;
  64                state.enabled = true;
  65
  66                err = pwm_apply_state(vibrator->pwm_dir, &state);
  67                if (err) {
  68                        dev_err(pdev, "failed to apply dir-pwm state: %d", err);
  69                        pwm_disable(vibrator->pwm);
  70                        return err;
  71                }
  72        }
  73
  74        return 0;
  75}
  76
  77static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
  78{
  79        if (vibrator->pwm_dir)
  80                pwm_disable(vibrator->pwm_dir);
  81        pwm_disable(vibrator->pwm);
  82
  83        if (vibrator->vcc_on) {
  84                regulator_disable(vibrator->vcc);
  85                vibrator->vcc_on = false;
  86        }
  87}
  88
  89static void pwm_vibrator_play_work(struct work_struct *work)
  90{
  91        struct pwm_vibrator *vibrator = container_of(work,
  92                                        struct pwm_vibrator, play_work);
  93
  94        if (vibrator->level)
  95                pwm_vibrator_start(vibrator);
  96        else
  97                pwm_vibrator_stop(vibrator);
  98}
  99
 100static int pwm_vibrator_play_effect(struct input_dev *dev, void *data,
 101                                    struct ff_effect *effect)
 102{
 103        struct pwm_vibrator *vibrator = input_get_drvdata(dev);
 104
 105        vibrator->level = effect->u.rumble.strong_magnitude;
 106        if (!vibrator->level)
 107                vibrator->level = effect->u.rumble.weak_magnitude;
 108
 109        schedule_work(&vibrator->play_work);
 110
 111        return 0;
 112}
 113
 114static void pwm_vibrator_close(struct input_dev *input)
 115{
 116        struct pwm_vibrator *vibrator = input_get_drvdata(input);
 117
 118        cancel_work_sync(&vibrator->play_work);
 119        pwm_vibrator_stop(vibrator);
 120}
 121
 122static int pwm_vibrator_probe(struct platform_device *pdev)
 123{
 124        struct pwm_vibrator *vibrator;
 125        struct pwm_state state;
 126        int err;
 127
 128        vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
 129        if (!vibrator)
 130                return -ENOMEM;
 131
 132        vibrator->input = devm_input_allocate_device(&pdev->dev);
 133        if (!vibrator->input)
 134                return -ENOMEM;
 135
 136        vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
 137        err = PTR_ERR_OR_ZERO(vibrator->vcc);
 138        if (err) {
 139                if (err != -EPROBE_DEFER)
 140                        dev_err(&pdev->dev, "Failed to request regulator: %d",
 141                                err);
 142                return err;
 143        }
 144
 145        vibrator->pwm = devm_pwm_get(&pdev->dev, "enable");
 146        err = PTR_ERR_OR_ZERO(vibrator->pwm);
 147        if (err) {
 148                if (err != -EPROBE_DEFER)
 149                        dev_err(&pdev->dev, "Failed to request main pwm: %d",
 150                                err);
 151                return err;
 152        }
 153
 154        INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work);
 155
 156        /* Sync up PWM state and ensure it is off. */
 157        pwm_init_state(vibrator->pwm, &state);
 158        state.enabled = false;
 159        err = pwm_apply_state(vibrator->pwm, &state);
 160        if (err) {
 161                dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
 162                        err);
 163                return err;
 164        }
 165
 166        vibrator->pwm_dir = devm_pwm_get(&pdev->dev, "direction");
 167        err = PTR_ERR_OR_ZERO(vibrator->pwm_dir);
 168        switch (err) {
 169        case 0:
 170                /* Sync up PWM state and ensure it is off. */
 171                pwm_init_state(vibrator->pwm_dir, &state);
 172                state.enabled = false;
 173                err = pwm_apply_state(vibrator->pwm_dir, &state);
 174                if (err) {
 175                        dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
 176                                err);
 177                        return err;
 178                }
 179
 180                vibrator->direction_duty_cycle =
 181                        pwm_get_period(vibrator->pwm_dir) / 2;
 182                device_property_read_u32(&pdev->dev, "direction-duty-cycle-ns",
 183                                         &vibrator->direction_duty_cycle);
 184                break;
 185
 186        case -ENODATA:
 187                /* Direction PWM is optional */
 188                vibrator->pwm_dir = NULL;
 189                break;
 190
 191        default:
 192                dev_err(&pdev->dev, "Failed to request direction pwm: %d", err);
 193                /* Fall through */
 194
 195        case -EPROBE_DEFER:
 196                return err;
 197        }
 198
 199        vibrator->input->name = "pwm-vibrator";
 200        vibrator->input->id.bustype = BUS_HOST;
 201        vibrator->input->dev.parent = &pdev->dev;
 202        vibrator->input->close = pwm_vibrator_close;
 203
 204        input_set_drvdata(vibrator->input, vibrator);
 205        input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
 206
 207        err = input_ff_create_memless(vibrator->input, NULL,
 208                                      pwm_vibrator_play_effect);
 209        if (err) {
 210                dev_err(&pdev->dev, "Couldn't create FF dev: %d", err);
 211                return err;
 212        }
 213
 214        err = input_register_device(vibrator->input);
 215        if (err) {
 216                dev_err(&pdev->dev, "Couldn't register input dev: %d", err);
 217                return err;
 218        }
 219
 220        platform_set_drvdata(pdev, vibrator);
 221
 222        return 0;
 223}
 224
 225static int __maybe_unused pwm_vibrator_suspend(struct device *dev)
 226{
 227        struct pwm_vibrator *vibrator = dev_get_drvdata(dev);
 228
 229        cancel_work_sync(&vibrator->play_work);
 230        if (vibrator->level)
 231                pwm_vibrator_stop(vibrator);
 232
 233        return 0;
 234}
 235
 236static int __maybe_unused pwm_vibrator_resume(struct device *dev)
 237{
 238        struct pwm_vibrator *vibrator = dev_get_drvdata(dev);
 239
 240        if (vibrator->level)
 241                pwm_vibrator_start(vibrator);
 242
 243        return 0;
 244}
 245
 246static SIMPLE_DEV_PM_OPS(pwm_vibrator_pm_ops,
 247                         pwm_vibrator_suspend, pwm_vibrator_resume);
 248
 249#ifdef CONFIG_OF
 250static const struct of_device_id pwm_vibra_dt_match_table[] = {
 251        { .compatible = "pwm-vibrator" },
 252        {},
 253};
 254MODULE_DEVICE_TABLE(of, pwm_vibra_dt_match_table);
 255#endif
 256
 257static struct platform_driver pwm_vibrator_driver = {
 258        .probe  = pwm_vibrator_probe,
 259        .driver = {
 260                .name   = "pwm-vibrator",
 261                .pm     = &pwm_vibrator_pm_ops,
 262                .of_match_table = of_match_ptr(pwm_vibra_dt_match_table),
 263        },
 264};
 265module_platform_driver(pwm_vibrator_driver);
 266
 267MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
 268MODULE_DESCRIPTION("PWM vibrator driver");
 269MODULE_LICENSE("GPL");
 270MODULE_ALIAS("platform:pwm-vibrator");
 271