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 32 struct 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 56 static 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 92 static 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 152 static void max8997_haptic_enable(struct max8997_haptic *chip) 153 { 154 int error; 155 156 guard(mutex)(&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 return; 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 return; 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 return; 177 } 178 } 179 chip->enabled = true; 180 } 181 } 182 183 static void max8997_haptic_disable(struct max8997_haptic *chip) 184 { 185 guard(mutex)(&chip->mutex); 186 187 if (chip->enabled) { 188 chip->enabled = false; 189 max8997_haptic_configure(chip); 190 if (chip->mode == MAX8997_EXTERNAL_MODE) 191 pwm_disable(chip->pwm); 192 regulator_disable(chip->regulator); 193 } 194 } 195 196 static void max8997_haptic_play_effect_work(struct work_struct *work) 197 { 198 struct max8997_haptic *chip = 199 container_of(work, struct max8997_haptic, work); 200 201 if (chip->level) 202 max8997_haptic_enable(chip); 203 else 204 max8997_haptic_disable(chip); 205 } 206 207 static int max8997_haptic_play_effect(struct input_dev *dev, void *data, 208 struct ff_effect *effect) 209 { 210 struct max8997_haptic *chip = input_get_drvdata(dev); 211 212 chip->level = effect->u.rumble.strong_magnitude; 213 if (!chip->level) 214 chip->level = effect->u.rumble.weak_magnitude; 215 216 schedule_work(&chip->work); 217 218 return 0; 219 } 220 221 static void max8997_haptic_close(struct input_dev *dev) 222 { 223 struct max8997_haptic *chip = input_get_drvdata(dev); 224 225 cancel_work_sync(&chip->work); 226 max8997_haptic_disable(chip); 227 } 228 229 static int max8997_haptic_probe(struct platform_device *pdev) 230 { 231 struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); 232 const struct max8997_platform_data *pdata = 233 dev_get_platdata(iodev->dev); 234 const struct max8997_haptic_platform_data *haptic_pdata = NULL; 235 struct max8997_haptic *chip; 236 struct input_dev *input_dev; 237 int error; 238 239 if (pdata) 240 haptic_pdata = pdata->haptic_pdata; 241 242 if (!haptic_pdata) { 243 dev_err(&pdev->dev, "no haptic platform data\n"); 244 return -EINVAL; 245 } 246 247 chip = kzalloc(sizeof(*chip), GFP_KERNEL); 248 input_dev = input_allocate_device(); 249 if (!chip || !input_dev) { 250 dev_err(&pdev->dev, "unable to allocate memory\n"); 251 error = -ENOMEM; 252 goto err_free_mem; 253 } 254 255 INIT_WORK(&chip->work, max8997_haptic_play_effect_work); 256 mutex_init(&chip->mutex); 257 258 chip->client = iodev->haptic; 259 chip->dev = &pdev->dev; 260 chip->input_dev = input_dev; 261 chip->pwm_period = haptic_pdata->pwm_period; 262 chip->type = haptic_pdata->type; 263 chip->mode = haptic_pdata->mode; 264 chip->pwm_divisor = haptic_pdata->pwm_divisor; 265 266 switch (chip->mode) { 267 case MAX8997_INTERNAL_MODE: 268 chip->internal_mode_pattern = 269 haptic_pdata->internal_mode_pattern; 270 chip->pattern_cycle = haptic_pdata->pattern_cycle; 271 chip->pattern_signal_period = 272 haptic_pdata->pattern_signal_period; 273 break; 274 275 case MAX8997_EXTERNAL_MODE: 276 chip->pwm = pwm_get(&pdev->dev, NULL); 277 if (IS_ERR(chip->pwm)) { 278 error = PTR_ERR(chip->pwm); 279 dev_err(&pdev->dev, 280 "unable to request PWM for haptic, error: %d\n", 281 error); 282 goto err_free_mem; 283 } 284 285 /* 286 * FIXME: pwm_apply_args() should be removed when switching to 287 * the atomic PWM API. 288 */ 289 pwm_apply_args(chip->pwm); 290 break; 291 292 default: 293 dev_err(&pdev->dev, 294 "Invalid chip mode specified (%d)\n", chip->mode); 295 error = -EINVAL; 296 goto err_free_mem; 297 } 298 299 chip->regulator = regulator_get(&pdev->dev, "inmotor"); 300 if (IS_ERR(chip->regulator)) { 301 error = PTR_ERR(chip->regulator); 302 dev_err(&pdev->dev, 303 "unable to get regulator, error: %d\n", 304 error); 305 goto err_free_pwm; 306 } 307 308 input_dev->name = "max8997-haptic"; 309 input_dev->id.version = 1; 310 input_dev->dev.parent = &pdev->dev; 311 input_dev->close = max8997_haptic_close; 312 input_set_drvdata(input_dev, chip); 313 input_set_capability(input_dev, EV_FF, FF_RUMBLE); 314 315 error = input_ff_create_memless(input_dev, NULL, 316 max8997_haptic_play_effect); 317 if (error) { 318 dev_err(&pdev->dev, 319 "unable to create FF device, error: %d\n", 320 error); 321 goto err_put_regulator; 322 } 323 324 error = input_register_device(input_dev); 325 if (error) { 326 dev_err(&pdev->dev, 327 "unable to register input device, error: %d\n", 328 error); 329 goto err_destroy_ff; 330 } 331 332 platform_set_drvdata(pdev, chip); 333 return 0; 334 335 err_destroy_ff: 336 input_ff_destroy(input_dev); 337 err_put_regulator: 338 regulator_put(chip->regulator); 339 err_free_pwm: 340 if (chip->mode == MAX8997_EXTERNAL_MODE) 341 pwm_put(chip->pwm); 342 err_free_mem: 343 input_free_device(input_dev); 344 kfree(chip); 345 346 return error; 347 } 348 349 static void max8997_haptic_remove(struct platform_device *pdev) 350 { 351 struct max8997_haptic *chip = platform_get_drvdata(pdev); 352 353 input_unregister_device(chip->input_dev); 354 regulator_put(chip->regulator); 355 356 if (chip->mode == MAX8997_EXTERNAL_MODE) 357 pwm_put(chip->pwm); 358 359 kfree(chip); 360 } 361 362 static int max8997_haptic_suspend(struct device *dev) 363 { 364 struct platform_device *pdev = to_platform_device(dev); 365 struct max8997_haptic *chip = platform_get_drvdata(pdev); 366 367 max8997_haptic_disable(chip); 368 369 return 0; 370 } 371 372 static DEFINE_SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, 373 max8997_haptic_suspend, NULL); 374 375 static const struct platform_device_id max8997_haptic_id[] = { 376 { "max8997-haptic", 0 }, 377 { }, 378 }; 379 MODULE_DEVICE_TABLE(platform, max8997_haptic_id); 380 381 static struct platform_driver max8997_haptic_driver = { 382 .driver = { 383 .name = "max8997-haptic", 384 .pm = pm_sleep_ptr(&max8997_haptic_pm_ops), 385 }, 386 .probe = max8997_haptic_probe, 387 .remove = max8997_haptic_remove, 388 .id_table = max8997_haptic_id, 389 }; 390 module_platform_driver(max8997_haptic_driver); 391 392 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); 393 MODULE_DESCRIPTION("max8997_haptic driver"); 394 MODULE_LICENSE("GPL"); 395