max8997_haptic.c (9840B)
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");