11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2104594b0SDonggeun Kim /* 3104594b0SDonggeun Kim * MAX8997-haptic controller driver 4104594b0SDonggeun Kim * 5104594b0SDonggeun Kim * Copyright (C) 2012 Samsung Electronics 6104594b0SDonggeun Kim * Donggeun Kim <dg77.kim@samsung.com> 7104594b0SDonggeun Kim * 8104594b0SDonggeun Kim * This program is not provided / owned by Maxim Integrated Products. 9104594b0SDonggeun Kim */ 10104594b0SDonggeun Kim 11104594b0SDonggeun Kim #include <linux/module.h> 12104594b0SDonggeun Kim #include <linux/slab.h> 13104594b0SDonggeun Kim #include <linux/platform_device.h> 14104594b0SDonggeun Kim #include <linux/err.h> 15104594b0SDonggeun Kim #include <linux/pwm.h> 16104594b0SDonggeun Kim #include <linux/input.h> 17104594b0SDonggeun Kim #include <linux/mfd/max8997-private.h> 18104594b0SDonggeun Kim #include <linux/mfd/max8997.h> 19104594b0SDonggeun Kim #include <linux/regulator/consumer.h> 20104594b0SDonggeun Kim 21104594b0SDonggeun Kim /* Haptic configuration 2 register */ 22104594b0SDonggeun Kim #define MAX8997_MOTOR_TYPE_SHIFT 7 23104594b0SDonggeun Kim #define MAX8997_ENABLE_SHIFT 6 24104594b0SDonggeun Kim #define MAX8997_MODE_SHIFT 5 25104594b0SDonggeun Kim 26104594b0SDonggeun Kim /* Haptic driver configuration register */ 27104594b0SDonggeun Kim #define MAX8997_CYCLE_SHIFT 6 28104594b0SDonggeun Kim #define MAX8997_SIG_PERIOD_SHIFT 4 29104594b0SDonggeun Kim #define MAX8997_SIG_DUTY_SHIFT 2 30104594b0SDonggeun Kim #define MAX8997_PWM_DUTY_SHIFT 0 31104594b0SDonggeun Kim 32104594b0SDonggeun Kim struct max8997_haptic { 33104594b0SDonggeun Kim struct device *dev; 34104594b0SDonggeun Kim struct i2c_client *client; 35104594b0SDonggeun Kim struct input_dev *input_dev; 36104594b0SDonggeun Kim struct regulator *regulator; 37104594b0SDonggeun Kim 38104594b0SDonggeun Kim struct work_struct work; 39104594b0SDonggeun Kim struct mutex mutex; 40104594b0SDonggeun Kim 41104594b0SDonggeun Kim bool enabled; 42104594b0SDonggeun Kim unsigned int level; 43104594b0SDonggeun Kim 44104594b0SDonggeun Kim struct pwm_device *pwm; 45104594b0SDonggeun Kim unsigned int pwm_period; 46104594b0SDonggeun Kim enum max8997_haptic_pwm_divisor pwm_divisor; 47104594b0SDonggeun Kim 48104594b0SDonggeun Kim enum max8997_haptic_motor_type type; 49104594b0SDonggeun Kim enum max8997_haptic_pulse_mode mode; 50104594b0SDonggeun Kim 51104594b0SDonggeun Kim unsigned int internal_mode_pattern; 52104594b0SDonggeun Kim unsigned int pattern_cycle; 53104594b0SDonggeun Kim unsigned int pattern_signal_period; 54104594b0SDonggeun Kim }; 55104594b0SDonggeun Kim 56104594b0SDonggeun Kim static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip) 57104594b0SDonggeun Kim { 58104594b0SDonggeun Kim int ret = 0; 59104594b0SDonggeun Kim 60104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) { 61104594b0SDonggeun Kim unsigned int duty = chip->pwm_period * chip->level / 100; 62104594b0SDonggeun Kim ret = pwm_config(chip->pwm, duty, chip->pwm_period); 63104594b0SDonggeun Kim } else { 64104594b0SDonggeun Kim u8 duty_index = 0; 65104594b0SDonggeun Kim 66*8f50743fSUwe Kleine-König duty_index = DIV_ROUND_UP(chip->level * 64, 100); 67*8f50743fSUwe Kleine-König 68104594b0SDonggeun Kim switch (chip->internal_mode_pattern) { 69104594b0SDonggeun Kim case 0: 70104594b0SDonggeun Kim max8997_write_reg(chip->client, 71104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index); 72104594b0SDonggeun Kim break; 73104594b0SDonggeun Kim case 1: 74104594b0SDonggeun Kim max8997_write_reg(chip->client, 75104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index); 76104594b0SDonggeun Kim break; 77104594b0SDonggeun Kim case 2: 78104594b0SDonggeun Kim max8997_write_reg(chip->client, 79104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index); 80104594b0SDonggeun Kim break; 81104594b0SDonggeun Kim case 3: 82104594b0SDonggeun Kim max8997_write_reg(chip->client, 83104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index); 84104594b0SDonggeun Kim break; 85104594b0SDonggeun Kim default: 86104594b0SDonggeun Kim break; 87104594b0SDonggeun Kim } 88104594b0SDonggeun Kim } 89104594b0SDonggeun Kim return ret; 90104594b0SDonggeun Kim } 91104594b0SDonggeun Kim 92104594b0SDonggeun Kim static void max8997_haptic_configure(struct max8997_haptic *chip) 93104594b0SDonggeun Kim { 94104594b0SDonggeun Kim u8 value; 95104594b0SDonggeun Kim 96104594b0SDonggeun Kim value = chip->type << MAX8997_MOTOR_TYPE_SHIFT | 97104594b0SDonggeun Kim chip->enabled << MAX8997_ENABLE_SHIFT | 98104594b0SDonggeun Kim chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor; 99104594b0SDonggeun Kim max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value); 100104594b0SDonggeun Kim 101104594b0SDonggeun Kim if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) { 102104594b0SDonggeun Kim value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT | 103104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT | 104104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT | 105104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT; 106104594b0SDonggeun Kim max8997_write_reg(chip->client, 107104594b0SDonggeun Kim MAX8997_HAPTIC_REG_DRVCONF, value); 108104594b0SDonggeun Kim 109104594b0SDonggeun Kim switch (chip->internal_mode_pattern) { 110104594b0SDonggeun Kim case 0: 111104594b0SDonggeun Kim value = chip->pattern_cycle << 4; 112104594b0SDonggeun Kim max8997_write_reg(chip->client, 113104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF1, value); 114104594b0SDonggeun Kim value = chip->pattern_signal_period; 115104594b0SDonggeun Kim max8997_write_reg(chip->client, 116104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF1, value); 117104594b0SDonggeun Kim break; 118104594b0SDonggeun Kim 119104594b0SDonggeun Kim case 1: 120104594b0SDonggeun Kim value = chip->pattern_cycle; 121104594b0SDonggeun Kim max8997_write_reg(chip->client, 122104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF1, value); 123104594b0SDonggeun Kim value = chip->pattern_signal_period; 124104594b0SDonggeun Kim max8997_write_reg(chip->client, 125104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF2, value); 126104594b0SDonggeun Kim break; 127104594b0SDonggeun Kim 128104594b0SDonggeun Kim case 2: 129104594b0SDonggeun Kim value = chip->pattern_cycle << 4; 130104594b0SDonggeun Kim max8997_write_reg(chip->client, 131104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF2, value); 132104594b0SDonggeun Kim value = chip->pattern_signal_period; 133104594b0SDonggeun Kim max8997_write_reg(chip->client, 134104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF3, value); 135104594b0SDonggeun Kim break; 136104594b0SDonggeun Kim 137104594b0SDonggeun Kim case 3: 138104594b0SDonggeun Kim value = chip->pattern_cycle; 139104594b0SDonggeun Kim max8997_write_reg(chip->client, 140104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF2, value); 141104594b0SDonggeun Kim value = chip->pattern_signal_period; 142104594b0SDonggeun Kim max8997_write_reg(chip->client, 143104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF4, value); 144104594b0SDonggeun Kim break; 145104594b0SDonggeun Kim 146104594b0SDonggeun Kim default: 147104594b0SDonggeun Kim break; 148104594b0SDonggeun Kim } 149104594b0SDonggeun Kim } 150104594b0SDonggeun Kim } 151104594b0SDonggeun Kim 152104594b0SDonggeun Kim static void max8997_haptic_enable(struct max8997_haptic *chip) 153104594b0SDonggeun Kim { 154104594b0SDonggeun Kim int error; 155104594b0SDonggeun Kim 156104594b0SDonggeun Kim mutex_lock(&chip->mutex); 157104594b0SDonggeun Kim 158104594b0SDonggeun Kim error = max8997_haptic_set_duty_cycle(chip); 159104594b0SDonggeun Kim if (error) { 160104594b0SDonggeun Kim dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error); 161104594b0SDonggeun Kim goto out; 162104594b0SDonggeun Kim } 163104594b0SDonggeun Kim 164104594b0SDonggeun Kim if (!chip->enabled) { 165b1bc3031SSachin Kamat error = regulator_enable(chip->regulator); 166b1bc3031SSachin Kamat if (error) { 167b1bc3031SSachin Kamat dev_err(chip->dev, "Failed to enable regulator\n"); 168b1bc3031SSachin Kamat goto out; 169b1bc3031SSachin Kamat } 170104594b0SDonggeun Kim max8997_haptic_configure(chip); 171b1bc3031SSachin Kamat if (chip->mode == MAX8997_EXTERNAL_MODE) { 172b1bc3031SSachin Kamat error = pwm_enable(chip->pwm); 173b1bc3031SSachin Kamat if (error) { 174b1bc3031SSachin Kamat dev_err(chip->dev, "Failed to enable PWM\n"); 175b1bc3031SSachin Kamat regulator_disable(chip->regulator); 176b1bc3031SSachin Kamat goto out; 177b1bc3031SSachin Kamat } 178b1bc3031SSachin Kamat } 179b1bc3031SSachin Kamat chip->enabled = true; 180104594b0SDonggeun Kim } 181104594b0SDonggeun Kim 182104594b0SDonggeun Kim out: 183104594b0SDonggeun Kim mutex_unlock(&chip->mutex); 184104594b0SDonggeun Kim } 185104594b0SDonggeun Kim 186104594b0SDonggeun Kim static void max8997_haptic_disable(struct max8997_haptic *chip) 187104594b0SDonggeun Kim { 188104594b0SDonggeun Kim mutex_lock(&chip->mutex); 189104594b0SDonggeun Kim 190104594b0SDonggeun Kim if (chip->enabled) { 191104594b0SDonggeun Kim chip->enabled = false; 192104594b0SDonggeun Kim max8997_haptic_configure(chip); 193104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 194104594b0SDonggeun Kim pwm_disable(chip->pwm); 195104594b0SDonggeun Kim regulator_disable(chip->regulator); 196104594b0SDonggeun Kim } 197104594b0SDonggeun Kim 198104594b0SDonggeun Kim mutex_unlock(&chip->mutex); 199104594b0SDonggeun Kim } 200104594b0SDonggeun Kim 201104594b0SDonggeun Kim static void max8997_haptic_play_effect_work(struct work_struct *work) 202104594b0SDonggeun Kim { 203104594b0SDonggeun Kim struct max8997_haptic *chip = 204104594b0SDonggeun Kim container_of(work, struct max8997_haptic, work); 205104594b0SDonggeun Kim 206104594b0SDonggeun Kim if (chip->level) 207104594b0SDonggeun Kim max8997_haptic_enable(chip); 208104594b0SDonggeun Kim else 209104594b0SDonggeun Kim max8997_haptic_disable(chip); 210104594b0SDonggeun Kim } 211104594b0SDonggeun Kim 212104594b0SDonggeun Kim static int max8997_haptic_play_effect(struct input_dev *dev, void *data, 213104594b0SDonggeun Kim struct ff_effect *effect) 214104594b0SDonggeun Kim { 215104594b0SDonggeun Kim struct max8997_haptic *chip = input_get_drvdata(dev); 216104594b0SDonggeun Kim 217104594b0SDonggeun Kim chip->level = effect->u.rumble.strong_magnitude; 218104594b0SDonggeun Kim if (!chip->level) 219104594b0SDonggeun Kim chip->level = effect->u.rumble.weak_magnitude; 220104594b0SDonggeun Kim 221104594b0SDonggeun Kim schedule_work(&chip->work); 222104594b0SDonggeun Kim 223104594b0SDonggeun Kim return 0; 224104594b0SDonggeun Kim } 225104594b0SDonggeun Kim 226104594b0SDonggeun Kim static void max8997_haptic_close(struct input_dev *dev) 227104594b0SDonggeun Kim { 228104594b0SDonggeun Kim struct max8997_haptic *chip = input_get_drvdata(dev); 229104594b0SDonggeun Kim 230104594b0SDonggeun Kim cancel_work_sync(&chip->work); 231104594b0SDonggeun Kim max8997_haptic_disable(chip); 232104594b0SDonggeun Kim } 233104594b0SDonggeun Kim 2345298cc4cSBill Pemberton static int max8997_haptic_probe(struct platform_device *pdev) 235104594b0SDonggeun Kim { 236104594b0SDonggeun Kim struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); 237104594b0SDonggeun Kim const struct max8997_platform_data *pdata = 238104594b0SDonggeun Kim dev_get_platdata(iodev->dev); 2396ae645d5SMarek Szyprowski const struct max8997_haptic_platform_data *haptic_pdata = NULL; 240104594b0SDonggeun Kim struct max8997_haptic *chip; 241104594b0SDonggeun Kim struct input_dev *input_dev; 242104594b0SDonggeun Kim int error; 243104594b0SDonggeun Kim 2446ae645d5SMarek Szyprowski if (pdata) 2456ae645d5SMarek Szyprowski haptic_pdata = pdata->haptic_pdata; 2466ae645d5SMarek Szyprowski 247104594b0SDonggeun Kim if (!haptic_pdata) { 248104594b0SDonggeun Kim dev_err(&pdev->dev, "no haptic platform data\n"); 249104594b0SDonggeun Kim return -EINVAL; 250104594b0SDonggeun Kim } 251104594b0SDonggeun Kim 252104594b0SDonggeun Kim chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL); 253104594b0SDonggeun Kim input_dev = input_allocate_device(); 254104594b0SDonggeun Kim if (!chip || !input_dev) { 255104594b0SDonggeun Kim dev_err(&pdev->dev, "unable to allocate memory\n"); 256104594b0SDonggeun Kim error = -ENOMEM; 257104594b0SDonggeun Kim goto err_free_mem; 258104594b0SDonggeun Kim } 259104594b0SDonggeun Kim 260104594b0SDonggeun Kim INIT_WORK(&chip->work, max8997_haptic_play_effect_work); 261104594b0SDonggeun Kim mutex_init(&chip->mutex); 262104594b0SDonggeun Kim 263104594b0SDonggeun Kim chip->client = iodev->haptic; 264104594b0SDonggeun Kim chip->dev = &pdev->dev; 265104594b0SDonggeun Kim chip->input_dev = input_dev; 266104594b0SDonggeun Kim chip->pwm_period = haptic_pdata->pwm_period; 267104594b0SDonggeun Kim chip->type = haptic_pdata->type; 268104594b0SDonggeun Kim chip->mode = haptic_pdata->mode; 269104594b0SDonggeun Kim chip->pwm_divisor = haptic_pdata->pwm_divisor; 270104594b0SDonggeun Kim 271104594b0SDonggeun Kim switch (chip->mode) { 272104594b0SDonggeun Kim case MAX8997_INTERNAL_MODE: 273104594b0SDonggeun Kim chip->internal_mode_pattern = 274104594b0SDonggeun Kim haptic_pdata->internal_mode_pattern; 275104594b0SDonggeun Kim chip->pattern_cycle = haptic_pdata->pattern_cycle; 276104594b0SDonggeun Kim chip->pattern_signal_period = 277104594b0SDonggeun Kim haptic_pdata->pattern_signal_period; 278104594b0SDonggeun Kim break; 279104594b0SDonggeun Kim 280104594b0SDonggeun Kim case MAX8997_EXTERNAL_MODE: 281104594b0SDonggeun Kim chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, 282104594b0SDonggeun Kim "max8997-haptic"); 283104594b0SDonggeun Kim if (IS_ERR(chip->pwm)) { 284104594b0SDonggeun Kim error = PTR_ERR(chip->pwm); 285104594b0SDonggeun Kim dev_err(&pdev->dev, 286104594b0SDonggeun Kim "unable to request PWM for haptic, error: %d\n", 287104594b0SDonggeun Kim error); 288104594b0SDonggeun Kim goto err_free_mem; 289104594b0SDonggeun Kim } 290de93170bSBoris Brezillon 291de93170bSBoris Brezillon /* 292de93170bSBoris Brezillon * FIXME: pwm_apply_args() should be removed when switching to 293de93170bSBoris Brezillon * the atomic PWM API. 294de93170bSBoris Brezillon */ 295de93170bSBoris Brezillon pwm_apply_args(chip->pwm); 296104594b0SDonggeun Kim break; 297104594b0SDonggeun Kim 298104594b0SDonggeun Kim default: 299104594b0SDonggeun Kim dev_err(&pdev->dev, 300104594b0SDonggeun Kim "Invalid chip mode specified (%d)\n", chip->mode); 301104594b0SDonggeun Kim error = -EINVAL; 302104594b0SDonggeun Kim goto err_free_mem; 303104594b0SDonggeun Kim } 304104594b0SDonggeun Kim 305104594b0SDonggeun Kim chip->regulator = regulator_get(&pdev->dev, "inmotor"); 306104594b0SDonggeun Kim if (IS_ERR(chip->regulator)) { 307104594b0SDonggeun Kim error = PTR_ERR(chip->regulator); 308104594b0SDonggeun Kim dev_err(&pdev->dev, 309104594b0SDonggeun Kim "unable to get regulator, error: %d\n", 310104594b0SDonggeun Kim error); 311104594b0SDonggeun Kim goto err_free_pwm; 312104594b0SDonggeun Kim } 313104594b0SDonggeun Kim 314104594b0SDonggeun Kim input_dev->name = "max8997-haptic"; 315104594b0SDonggeun Kim input_dev->id.version = 1; 316104594b0SDonggeun Kim input_dev->dev.parent = &pdev->dev; 317104594b0SDonggeun Kim input_dev->close = max8997_haptic_close; 318104594b0SDonggeun Kim input_set_drvdata(input_dev, chip); 319104594b0SDonggeun Kim input_set_capability(input_dev, EV_FF, FF_RUMBLE); 320104594b0SDonggeun Kim 321104594b0SDonggeun Kim error = input_ff_create_memless(input_dev, NULL, 322104594b0SDonggeun Kim max8997_haptic_play_effect); 323104594b0SDonggeun Kim if (error) { 324104594b0SDonggeun Kim dev_err(&pdev->dev, 325104594b0SDonggeun Kim "unable to create FF device, error: %d\n", 326104594b0SDonggeun Kim error); 327104594b0SDonggeun Kim goto err_put_regulator; 328104594b0SDonggeun Kim } 329104594b0SDonggeun Kim 330104594b0SDonggeun Kim error = input_register_device(input_dev); 331104594b0SDonggeun Kim if (error) { 332104594b0SDonggeun Kim dev_err(&pdev->dev, 333104594b0SDonggeun Kim "unable to register input device, error: %d\n", 334104594b0SDonggeun Kim error); 335104594b0SDonggeun Kim goto err_destroy_ff; 336104594b0SDonggeun Kim } 337104594b0SDonggeun Kim 338104594b0SDonggeun Kim platform_set_drvdata(pdev, chip); 339104594b0SDonggeun Kim return 0; 340104594b0SDonggeun Kim 341104594b0SDonggeun Kim err_destroy_ff: 342104594b0SDonggeun Kim input_ff_destroy(input_dev); 343104594b0SDonggeun Kim err_put_regulator: 344104594b0SDonggeun Kim regulator_put(chip->regulator); 345104594b0SDonggeun Kim err_free_pwm: 346104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 347104594b0SDonggeun Kim pwm_free(chip->pwm); 348104594b0SDonggeun Kim err_free_mem: 349104594b0SDonggeun Kim input_free_device(input_dev); 350104594b0SDonggeun Kim kfree(chip); 351104594b0SDonggeun Kim 352104594b0SDonggeun Kim return error; 353104594b0SDonggeun Kim } 354104594b0SDonggeun Kim 355e2619cf7SBill Pemberton static int max8997_haptic_remove(struct platform_device *pdev) 356104594b0SDonggeun Kim { 357104594b0SDonggeun Kim struct max8997_haptic *chip = platform_get_drvdata(pdev); 358104594b0SDonggeun Kim 359104594b0SDonggeun Kim input_unregister_device(chip->input_dev); 360104594b0SDonggeun Kim regulator_put(chip->regulator); 361104594b0SDonggeun Kim 362104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 363104594b0SDonggeun Kim pwm_free(chip->pwm); 364104594b0SDonggeun Kim 365104594b0SDonggeun Kim kfree(chip); 366104594b0SDonggeun Kim 367104594b0SDonggeun Kim return 0; 368104594b0SDonggeun Kim } 369104594b0SDonggeun Kim 37097a652a8SJingoo Han static int __maybe_unused max8997_haptic_suspend(struct device *dev) 371104594b0SDonggeun Kim { 372104594b0SDonggeun Kim struct platform_device *pdev = to_platform_device(dev); 373104594b0SDonggeun Kim struct max8997_haptic *chip = platform_get_drvdata(pdev); 374104594b0SDonggeun Kim 375104594b0SDonggeun Kim max8997_haptic_disable(chip); 376104594b0SDonggeun Kim 377104594b0SDonggeun Kim return 0; 378104594b0SDonggeun Kim } 379104594b0SDonggeun Kim 380104594b0SDonggeun Kim static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL); 381104594b0SDonggeun Kim 382104594b0SDonggeun Kim static const struct platform_device_id max8997_haptic_id[] = { 383104594b0SDonggeun Kim { "max8997-haptic", 0 }, 384104594b0SDonggeun Kim { }, 385104594b0SDonggeun Kim }; 386d6f5aef2SJavier Martinez Canillas MODULE_DEVICE_TABLE(platform, max8997_haptic_id); 387104594b0SDonggeun Kim 388104594b0SDonggeun Kim static struct platform_driver max8997_haptic_driver = { 389104594b0SDonggeun Kim .driver = { 390104594b0SDonggeun Kim .name = "max8997-haptic", 391104594b0SDonggeun Kim .pm = &max8997_haptic_pm_ops, 392104594b0SDonggeun Kim }, 393104594b0SDonggeun Kim .probe = max8997_haptic_probe, 3941cb0aa88SBill Pemberton .remove = max8997_haptic_remove, 395104594b0SDonggeun Kim .id_table = max8997_haptic_id, 396104594b0SDonggeun Kim }; 397104594b0SDonggeun Kim module_platform_driver(max8997_haptic_driver); 398104594b0SDonggeun Kim 399104594b0SDonggeun Kim MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); 400104594b0SDonggeun Kim MODULE_DESCRIPTION("max8997_haptic driver"); 401104594b0SDonggeun Kim MODULE_LICENSE("GPL"); 402