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 23 struct 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 39 static 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 60 static 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 return 0; 80 } 81 82 static void regulator_haptic_work(struct work_struct *work) 83 { 84 struct regulator_haptic *haptic = container_of(work, 85 struct regulator_haptic, work); 86 unsigned int magnitude; 87 int error; 88 89 mutex_lock(&haptic->mutex); 90 91 if (haptic->suspended) 92 goto out; 93 94 magnitude = ACCESS_ONCE(haptic->magnitude); 95 96 error = regulator_haptic_set_voltage(haptic, magnitude); 97 if (error) 98 goto out; 99 100 regulator_haptic_toggle(haptic, magnitude != 0); 101 102 out: 103 mutex_unlock(&haptic->mutex); 104 } 105 106 static int regulator_haptic_play_effect(struct input_dev *input, void *data, 107 struct ff_effect *effect) 108 { 109 struct regulator_haptic *haptic = input_get_drvdata(input); 110 111 haptic->magnitude = effect->u.rumble.strong_magnitude; 112 if (!haptic->magnitude) 113 haptic->magnitude = effect->u.rumble.weak_magnitude; 114 115 schedule_work(&haptic->work); 116 117 return 0; 118 } 119 120 static void regulator_haptic_close(struct input_dev *input) 121 { 122 struct regulator_haptic *haptic = input_get_drvdata(input); 123 124 cancel_work_sync(&haptic->work); 125 regulator_haptic_set_voltage(haptic, 0); 126 regulator_haptic_toggle(haptic, false); 127 } 128 129 static int __maybe_unused 130 regulator_haptic_parse_dt(struct device *dev, struct regulator_haptic *haptic) 131 { 132 struct device_node *node; 133 int error; 134 135 node = dev->of_node; 136 if(!node) { 137 dev_err(dev, "Missing dveice tree data\n"); 138 return -EINVAL; 139 } 140 141 error = of_property_read_u32(node, "max-microvolt", &haptic->max_volt); 142 if (error) { 143 dev_err(dev, "cannot parse max-microvolt\n"); 144 return error; 145 } 146 147 error = of_property_read_u32(node, "min-microvolt", &haptic->min_volt); 148 if (error) { 149 dev_err(dev, "cannot parse min-microvolt\n"); 150 return error; 151 } 152 153 return 0; 154 } 155 156 static int regulator_haptic_probe(struct platform_device *pdev) 157 { 158 const struct regulator_haptic_data *pdata = dev_get_platdata(&pdev->dev); 159 struct regulator_haptic *haptic; 160 struct input_dev *input_dev; 161 int error; 162 163 haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL); 164 if (!haptic) 165 return -ENOMEM; 166 167 platform_set_drvdata(pdev, haptic); 168 haptic->dev = &pdev->dev; 169 mutex_init(&haptic->mutex); 170 INIT_WORK(&haptic->work, regulator_haptic_work); 171 172 if (pdata) { 173 haptic->max_volt = pdata->max_volt; 174 haptic->min_volt = pdata->min_volt; 175 } else if (IS_ENABLED(CONFIG_OF)) { 176 error = regulator_haptic_parse_dt(&pdev->dev, haptic); 177 if (error) 178 return error; 179 } else { 180 dev_err(&pdev->dev, "Missing platform data\n"); 181 return -EINVAL; 182 } 183 184 haptic->regulator = devm_regulator_get_exclusive(&pdev->dev, "haptic"); 185 if (IS_ERR(haptic->regulator)) { 186 dev_err(&pdev->dev, "failed to get regulator\n"); 187 return PTR_ERR(haptic->regulator); 188 } 189 190 input_dev = devm_input_allocate_device(&pdev->dev); 191 if (!input_dev) 192 return -ENOMEM; 193 194 haptic->input_dev = input_dev; 195 haptic->input_dev->name = "regulator-haptic"; 196 haptic->input_dev->dev.parent = &pdev->dev; 197 haptic->input_dev->close = regulator_haptic_close; 198 input_set_drvdata(haptic->input_dev, haptic); 199 input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE); 200 201 error = input_ff_create_memless(input_dev, NULL, 202 regulator_haptic_play_effect); 203 if (error) { 204 dev_err(&pdev->dev, "failed to create force-feedback\n"); 205 return error; 206 } 207 208 error = input_register_device(haptic->input_dev); 209 if (error) { 210 dev_err(&pdev->dev, "failed to register input device\n"); 211 return error; 212 } 213 214 return 0; 215 } 216 217 static int __maybe_unused regulator_haptic_suspend(struct device *dev) 218 { 219 struct platform_device *pdev = to_platform_device(dev); 220 struct regulator_haptic *haptic = platform_get_drvdata(pdev); 221 int error; 222 223 error = mutex_lock_interruptible(&haptic->mutex); 224 if (error) 225 return error; 226 227 regulator_haptic_set_voltage(haptic, 0); 228 regulator_haptic_toggle(haptic, false); 229 230 haptic->suspended = true; 231 232 mutex_unlock(&haptic->mutex); 233 234 return 0; 235 } 236 237 static int __maybe_unused regulator_haptic_resume(struct device *dev) 238 { 239 struct platform_device *pdev = to_platform_device(dev); 240 struct regulator_haptic *haptic = platform_get_drvdata(pdev); 241 unsigned int magnitude; 242 243 mutex_lock(&haptic->mutex); 244 245 haptic->suspended = false; 246 247 magnitude = ACCESS_ONCE(haptic->magnitude); 248 if (magnitude) { 249 regulator_haptic_set_voltage(haptic, magnitude); 250 regulator_haptic_toggle(haptic, true); 251 } 252 253 mutex_unlock(&haptic->mutex); 254 255 return 0; 256 } 257 258 static SIMPLE_DEV_PM_OPS(regulator_haptic_pm_ops, 259 regulator_haptic_suspend, regulator_haptic_resume); 260 261 static struct of_device_id regulator_haptic_dt_match[] = { 262 { .compatible = "regulator-haptic" }, 263 { /* sentinel */ }, 264 }; 265 266 static struct platform_driver regulator_haptic_driver = { 267 .probe = regulator_haptic_probe, 268 .driver = { 269 .name = "regulator-haptic", 270 .of_match_table = regulator_haptic_dt_match, 271 .pm = ®ulator_haptic_pm_ops, 272 }, 273 }; 274 module_platform_driver(regulator_haptic_driver); 275 276 MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); 277 MODULE_AUTHOR("Hyunhee Kim <hyunhee.kim@samsung.com>"); 278 MODULE_DESCRIPTION("Regulator haptic driver"); 279 MODULE_LICENSE("GPL"); 280