linux/drivers/input/misc/regulator-haptic.c
<<
>>
Prefs
   1/*
   2 * Regulator haptic driver
   3 *
   4 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
   5 * Author: Jaewon Kim <jaewon02.kim@samsung.com>
   6 * Author: Hyunhee Kim <hyunhee.kim@samsung.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/input.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/platform_data/regulator-haptic.h>
  17#include <linux/platform_device.h>
  18#include <linux/regulator/consumer.h>
  19#include <linux/slab.h>
  20
  21#define MAX_MAGNITUDE_SHIFT     16
  22
  23struct regulator_haptic {
  24        struct device *dev;
  25        struct input_dev *input_dev;
  26        struct regulator *regulator;
  27
  28        struct work_struct work;
  29        struct mutex mutex;
  30
  31        bool active;
  32        bool suspended;
  33
  34        unsigned int max_volt;
  35        unsigned int min_volt;
  36        unsigned int magnitude;
  37};
  38
  39static int regulator_haptic_toggle(struct regulator_haptic *haptic, bool on)
  40{
  41        int error;
  42
  43        if (haptic->active != on) {
  44
  45                error = on ? regulator_enable(haptic->regulator) :
  46                             regulator_disable(haptic->regulator);
  47                if (error) {
  48                        dev_err(haptic->dev,
  49                                "failed to switch regulator %s: %d\n",
  50                                on ? "on" : "off", error);
  51                        return error;
  52                }
  53
  54                haptic->active = on;
  55        }
  56
  57        return 0;
  58}
  59
  60static int regulator_haptic_set_voltage(struct regulator_haptic *haptic,
  61                                         unsigned int magnitude)
  62{
  63        u64 volt_mag_multi;
  64        unsigned int intensity;
  65        int error;
  66
  67        volt_mag_multi = (u64)(haptic->max_volt - haptic->min_volt) * magnitude;
  68        intensity = (unsigned int)(volt_mag_multi >> MAX_MAGNITUDE_SHIFT);
  69
  70        error = regulator_set_voltage(haptic->regulator,
  71                                      intensity + haptic->min_volt,
  72                                      haptic->max_volt);
  73        if (error) {
  74                dev_err(haptic->dev, "cannot set regulator voltage to %d: %d\n",
  75                        intensity + haptic->min_volt, error);
  76                return error;
  77        }
  78
  79        regulator_haptic_toggle(haptic, !!magnitude);
  80
  81        return 0;
  82}
  83
  84static void regulator_haptic_work(struct work_struct *work)
  85{
  86        struct regulator_haptic *haptic = container_of(work,
  87                                        struct regulator_haptic, work);
  88
  89        mutex_lock(&haptic->mutex);
  90
  91        if (!haptic->suspended)
  92                regulator_haptic_set_voltage(haptic, haptic->magnitude);
  93
  94        mutex_unlock(&haptic->mutex);
  95}
  96
  97static int regulator_haptic_play_effect(struct input_dev *input, void *data,
  98                                        struct ff_effect *effect)
  99{
 100        struct regulator_haptic *haptic = input_get_drvdata(input);
 101
 102        haptic->magnitude = effect->u.rumble.strong_magnitude;
 103        if (!haptic->magnitude)
 104                haptic->magnitude = effect->u.rumble.weak_magnitude;
 105
 106        schedule_work(&haptic->work);
 107
 108        return 0;
 109}
 110
 111static void regulator_haptic_close(struct input_dev *input)
 112{
 113        struct regulator_haptic *haptic = input_get_drvdata(input);
 114
 115        cancel_work_sync(&haptic->work);
 116        regulator_haptic_set_voltage(haptic, 0);
 117}
 118
 119static int __maybe_unused
 120regulator_haptic_parse_dt(struct device *dev, struct regulator_haptic *haptic)
 121{
 122        struct device_node *node;
 123        int error;
 124
 125        node = dev->of_node;
 126        if(!node) {
 127                dev_err(dev, "Missing device tree data\n");
 128                return -EINVAL;
 129        }
 130
 131        error = of_property_read_u32(node, "max-microvolt", &haptic->max_volt);
 132        if (error) {
 133                dev_err(dev, "cannot parse max-microvolt\n");
 134                return error;
 135        }
 136
 137        error = of_property_read_u32(node, "min-microvolt", &haptic->min_volt);
 138        if (error) {
 139                dev_err(dev, "cannot parse min-microvolt\n");
 140                return error;
 141        }
 142
 143        return 0;
 144}
 145
 146static int regulator_haptic_probe(struct platform_device *pdev)
 147{
 148        const struct regulator_haptic_data *pdata = dev_get_platdata(&pdev->dev);
 149        struct regulator_haptic *haptic;
 150        struct input_dev *input_dev;
 151        int error;
 152
 153        haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL);
 154        if (!haptic)
 155                return -ENOMEM;
 156
 157        platform_set_drvdata(pdev, haptic);
 158        haptic->dev = &pdev->dev;
 159        mutex_init(&haptic->mutex);
 160        INIT_WORK(&haptic->work, regulator_haptic_work);
 161
 162        if (pdata) {
 163                haptic->max_volt = pdata->max_volt;
 164                haptic->min_volt = pdata->min_volt;
 165        } else if (IS_ENABLED(CONFIG_OF)) {
 166                error = regulator_haptic_parse_dt(&pdev->dev, haptic);
 167                if (error)
 168                        return error;
 169        } else {
 170                dev_err(&pdev->dev, "Missing platform data\n");
 171                return -EINVAL;
 172        }
 173
 174        haptic->regulator = devm_regulator_get_exclusive(&pdev->dev, "haptic");
 175        if (IS_ERR(haptic->regulator)) {
 176                dev_err(&pdev->dev, "failed to get regulator\n");
 177                return PTR_ERR(haptic->regulator);
 178        }
 179
 180        input_dev = devm_input_allocate_device(&pdev->dev);
 181        if (!input_dev)
 182                return  -ENOMEM;
 183
 184        haptic->input_dev = input_dev;
 185        haptic->input_dev->name = "regulator-haptic";
 186        haptic->input_dev->dev.parent = &pdev->dev;
 187        haptic->input_dev->close = regulator_haptic_close;
 188        input_set_drvdata(haptic->input_dev, haptic);
 189        input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE);
 190
 191        error = input_ff_create_memless(input_dev, NULL,
 192                                        regulator_haptic_play_effect);
 193        if (error) {
 194                dev_err(&pdev->dev, "failed to create force-feedback\n");
 195                return error;
 196        }
 197
 198        error = input_register_device(haptic->input_dev);
 199        if (error) {
 200                dev_err(&pdev->dev, "failed to register input device\n");
 201                return error;
 202        }
 203
 204        return 0;
 205}
 206
 207static int __maybe_unused regulator_haptic_suspend(struct device *dev)
 208{
 209        struct platform_device *pdev = to_platform_device(dev);
 210        struct regulator_haptic *haptic = platform_get_drvdata(pdev);
 211        int error;
 212
 213        error = mutex_lock_interruptible(&haptic->mutex);
 214        if (error)
 215                return error;
 216
 217        regulator_haptic_set_voltage(haptic, 0);
 218
 219        haptic->suspended = true;
 220
 221        mutex_unlock(&haptic->mutex);
 222
 223        return 0;
 224}
 225
 226static int __maybe_unused regulator_haptic_resume(struct device *dev)
 227{
 228        struct platform_device *pdev = to_platform_device(dev);
 229        struct regulator_haptic *haptic = platform_get_drvdata(pdev);
 230        unsigned int magnitude;
 231
 232        mutex_lock(&haptic->mutex);
 233
 234        haptic->suspended = false;
 235
 236        magnitude = READ_ONCE(haptic->magnitude);
 237        if (magnitude)
 238                regulator_haptic_set_voltage(haptic, magnitude);
 239
 240        mutex_unlock(&haptic->mutex);
 241
 242        return 0;
 243}
 244
 245static SIMPLE_DEV_PM_OPS(regulator_haptic_pm_ops,
 246                regulator_haptic_suspend, regulator_haptic_resume);
 247
 248static const struct of_device_id regulator_haptic_dt_match[] = {
 249        { .compatible = "regulator-haptic" },
 250        { /* sentinel */ },
 251};
 252MODULE_DEVICE_TABLE(of, regulator_haptic_dt_match);
 253
 254static struct platform_driver regulator_haptic_driver = {
 255        .probe          = regulator_haptic_probe,
 256        .driver         = {
 257                .name           = "regulator-haptic",
 258                .of_match_table = regulator_haptic_dt_match,
 259                .pm             = &regulator_haptic_pm_ops,
 260        },
 261};
 262module_platform_driver(regulator_haptic_driver);
 263
 264MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
 265MODULE_AUTHOR("Hyunhee Kim <hyunhee.kim@samsung.com>");
 266MODULE_DESCRIPTION("Regulator haptic driver");
 267MODULE_LICENSE("GPL");
 268