1104594b0SDonggeun Kim /* 2104594b0SDonggeun Kim * MAX8997-haptic controller driver 3104594b0SDonggeun Kim * 4104594b0SDonggeun Kim * Copyright (C) 2012 Samsung Electronics 5104594b0SDonggeun Kim * Donggeun Kim <dg77.kim@samsung.com> 6104594b0SDonggeun Kim * 7104594b0SDonggeun Kim * This program is not provided / owned by Maxim Integrated Products. 8104594b0SDonggeun Kim * 9104594b0SDonggeun Kim * This program is free software; you can redistribute it and/or modify 10104594b0SDonggeun Kim * it under the terms of the GNU General Public License as published by 11104594b0SDonggeun Kim * the Free Software Foundation; either version 2 of the License, or 12104594b0SDonggeun Kim * (at your option) any later version. 13104594b0SDonggeun Kim * 14104594b0SDonggeun Kim * This program is distributed in the hope that it will be useful, 15104594b0SDonggeun Kim * but WITHOUT ANY WARRANTY; without even the implied warranty of 16104594b0SDonggeun Kim * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17104594b0SDonggeun Kim * GNU General Public License for more details. 18104594b0SDonggeun Kim * 19104594b0SDonggeun Kim * You should have received a copy of the GNU General Public License 20104594b0SDonggeun Kim * along with this program; if not, write to the Free Software 21104594b0SDonggeun Kim * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22104594b0SDonggeun Kim * 23104594b0SDonggeun Kim */ 24104594b0SDonggeun Kim 25104594b0SDonggeun Kim #include <linux/module.h> 26104594b0SDonggeun Kim #include <linux/init.h> 27104594b0SDonggeun Kim #include <linux/slab.h> 28104594b0SDonggeun Kim #include <linux/platform_device.h> 29104594b0SDonggeun Kim #include <linux/err.h> 30104594b0SDonggeun Kim #include <linux/pwm.h> 31104594b0SDonggeun Kim #include <linux/input.h> 32104594b0SDonggeun Kim #include <linux/mfd/max8997-private.h> 33104594b0SDonggeun Kim #include <linux/mfd/max8997.h> 34104594b0SDonggeun Kim #include <linux/regulator/consumer.h> 35104594b0SDonggeun Kim 36104594b0SDonggeun Kim /* Haptic configuration 2 register */ 37104594b0SDonggeun Kim #define MAX8997_MOTOR_TYPE_SHIFT 7 38104594b0SDonggeun Kim #define MAX8997_ENABLE_SHIFT 6 39104594b0SDonggeun Kim #define MAX8997_MODE_SHIFT 5 40104594b0SDonggeun Kim 41104594b0SDonggeun Kim /* Haptic driver configuration register */ 42104594b0SDonggeun Kim #define MAX8997_CYCLE_SHIFT 6 43104594b0SDonggeun Kim #define MAX8997_SIG_PERIOD_SHIFT 4 44104594b0SDonggeun Kim #define MAX8997_SIG_DUTY_SHIFT 2 45104594b0SDonggeun Kim #define MAX8997_PWM_DUTY_SHIFT 0 46104594b0SDonggeun Kim 47104594b0SDonggeun Kim struct max8997_haptic { 48104594b0SDonggeun Kim struct device *dev; 49104594b0SDonggeun Kim struct i2c_client *client; 50104594b0SDonggeun Kim struct input_dev *input_dev; 51104594b0SDonggeun Kim struct regulator *regulator; 52104594b0SDonggeun Kim 53104594b0SDonggeun Kim struct work_struct work; 54104594b0SDonggeun Kim struct mutex mutex; 55104594b0SDonggeun Kim 56104594b0SDonggeun Kim bool enabled; 57104594b0SDonggeun Kim unsigned int level; 58104594b0SDonggeun Kim 59104594b0SDonggeun Kim struct pwm_device *pwm; 60104594b0SDonggeun Kim unsigned int pwm_period; 61104594b0SDonggeun Kim enum max8997_haptic_pwm_divisor pwm_divisor; 62104594b0SDonggeun Kim 63104594b0SDonggeun Kim enum max8997_haptic_motor_type type; 64104594b0SDonggeun Kim enum max8997_haptic_pulse_mode mode; 65104594b0SDonggeun Kim 66104594b0SDonggeun Kim unsigned int internal_mode_pattern; 67104594b0SDonggeun Kim unsigned int pattern_cycle; 68104594b0SDonggeun Kim unsigned int pattern_signal_period; 69104594b0SDonggeun Kim }; 70104594b0SDonggeun Kim 71104594b0SDonggeun Kim static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip) 72104594b0SDonggeun Kim { 73104594b0SDonggeun Kim int ret = 0; 74104594b0SDonggeun Kim 75104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) { 76104594b0SDonggeun Kim unsigned int duty = chip->pwm_period * chip->level / 100; 77104594b0SDonggeun Kim ret = pwm_config(chip->pwm, duty, chip->pwm_period); 78104594b0SDonggeun Kim } else { 79104594b0SDonggeun Kim int i; 80104594b0SDonggeun Kim u8 duty_index = 0; 81104594b0SDonggeun Kim 82104594b0SDonggeun Kim for (i = 0; i <= 64; i++) { 83104594b0SDonggeun Kim if (chip->level <= i * 100 / 64) { 84104594b0SDonggeun Kim duty_index = i; 85104594b0SDonggeun Kim break; 86104594b0SDonggeun Kim } 87104594b0SDonggeun Kim } 88104594b0SDonggeun Kim switch (chip->internal_mode_pattern) { 89104594b0SDonggeun Kim case 0: 90104594b0SDonggeun Kim max8997_write_reg(chip->client, 91104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index); 92104594b0SDonggeun Kim break; 93104594b0SDonggeun Kim case 1: 94104594b0SDonggeun Kim max8997_write_reg(chip->client, 95104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index); 96104594b0SDonggeun Kim break; 97104594b0SDonggeun Kim case 2: 98104594b0SDonggeun Kim max8997_write_reg(chip->client, 99104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index); 100104594b0SDonggeun Kim break; 101104594b0SDonggeun Kim case 3: 102104594b0SDonggeun Kim max8997_write_reg(chip->client, 103104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index); 104104594b0SDonggeun Kim break; 105104594b0SDonggeun Kim default: 106104594b0SDonggeun Kim break; 107104594b0SDonggeun Kim } 108104594b0SDonggeun Kim } 109104594b0SDonggeun Kim return ret; 110104594b0SDonggeun Kim } 111104594b0SDonggeun Kim 112104594b0SDonggeun Kim static void max8997_haptic_configure(struct max8997_haptic *chip) 113104594b0SDonggeun Kim { 114104594b0SDonggeun Kim u8 value; 115104594b0SDonggeun Kim 116104594b0SDonggeun Kim value = chip->type << MAX8997_MOTOR_TYPE_SHIFT | 117104594b0SDonggeun Kim chip->enabled << MAX8997_ENABLE_SHIFT | 118104594b0SDonggeun Kim chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor; 119104594b0SDonggeun Kim max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value); 120104594b0SDonggeun Kim 121104594b0SDonggeun Kim if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) { 122104594b0SDonggeun Kim value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT | 123104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT | 124104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT | 125104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT; 126104594b0SDonggeun Kim max8997_write_reg(chip->client, 127104594b0SDonggeun Kim MAX8997_HAPTIC_REG_DRVCONF, value); 128104594b0SDonggeun Kim 129104594b0SDonggeun Kim switch (chip->internal_mode_pattern) { 130104594b0SDonggeun Kim case 0: 131104594b0SDonggeun Kim value = chip->pattern_cycle << 4; 132104594b0SDonggeun Kim max8997_write_reg(chip->client, 133104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF1, value); 134104594b0SDonggeun Kim value = chip->pattern_signal_period; 135104594b0SDonggeun Kim max8997_write_reg(chip->client, 136104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF1, value); 137104594b0SDonggeun Kim break; 138104594b0SDonggeun Kim 139104594b0SDonggeun Kim case 1: 140104594b0SDonggeun Kim value = chip->pattern_cycle; 141104594b0SDonggeun Kim max8997_write_reg(chip->client, 142104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF1, value); 143104594b0SDonggeun Kim value = chip->pattern_signal_period; 144104594b0SDonggeun Kim max8997_write_reg(chip->client, 145104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF2, value); 146104594b0SDonggeun Kim break; 147104594b0SDonggeun Kim 148104594b0SDonggeun Kim case 2: 149104594b0SDonggeun Kim value = chip->pattern_cycle << 4; 150104594b0SDonggeun Kim max8997_write_reg(chip->client, 151104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF2, value); 152104594b0SDonggeun Kim value = chip->pattern_signal_period; 153104594b0SDonggeun Kim max8997_write_reg(chip->client, 154104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF3, value); 155104594b0SDonggeun Kim break; 156104594b0SDonggeun Kim 157104594b0SDonggeun Kim case 3: 158104594b0SDonggeun Kim value = chip->pattern_cycle; 159104594b0SDonggeun Kim max8997_write_reg(chip->client, 160104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF2, value); 161104594b0SDonggeun Kim value = chip->pattern_signal_period; 162104594b0SDonggeun Kim max8997_write_reg(chip->client, 163104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF4, value); 164104594b0SDonggeun Kim break; 165104594b0SDonggeun Kim 166104594b0SDonggeun Kim default: 167104594b0SDonggeun Kim break; 168104594b0SDonggeun Kim } 169104594b0SDonggeun Kim } 170104594b0SDonggeun Kim } 171104594b0SDonggeun Kim 172104594b0SDonggeun Kim static void max8997_haptic_enable(struct max8997_haptic *chip) 173104594b0SDonggeun Kim { 174104594b0SDonggeun Kim int error; 175104594b0SDonggeun Kim 176104594b0SDonggeun Kim mutex_lock(&chip->mutex); 177104594b0SDonggeun Kim 178104594b0SDonggeun Kim error = max8997_haptic_set_duty_cycle(chip); 179104594b0SDonggeun Kim if (error) { 180104594b0SDonggeun Kim dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error); 181104594b0SDonggeun Kim goto out; 182104594b0SDonggeun Kim } 183104594b0SDonggeun Kim 184104594b0SDonggeun Kim if (!chip->enabled) { 185104594b0SDonggeun Kim chip->enabled = true; 186104594b0SDonggeun Kim regulator_enable(chip->regulator); 187104594b0SDonggeun Kim max8997_haptic_configure(chip); 188104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 189104594b0SDonggeun Kim pwm_enable(chip->pwm); 190104594b0SDonggeun Kim } 191104594b0SDonggeun Kim 192104594b0SDonggeun Kim out: 193104594b0SDonggeun Kim mutex_unlock(&chip->mutex); 194104594b0SDonggeun Kim } 195104594b0SDonggeun Kim 196104594b0SDonggeun Kim static void max8997_haptic_disable(struct max8997_haptic *chip) 197104594b0SDonggeun Kim { 198104594b0SDonggeun Kim mutex_lock(&chip->mutex); 199104594b0SDonggeun Kim 200104594b0SDonggeun Kim if (chip->enabled) { 201104594b0SDonggeun Kim chip->enabled = false; 202104594b0SDonggeun Kim max8997_haptic_configure(chip); 203104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 204104594b0SDonggeun Kim pwm_disable(chip->pwm); 205104594b0SDonggeun Kim regulator_disable(chip->regulator); 206104594b0SDonggeun Kim } 207104594b0SDonggeun Kim 208104594b0SDonggeun Kim mutex_unlock(&chip->mutex); 209104594b0SDonggeun Kim } 210104594b0SDonggeun Kim 211104594b0SDonggeun Kim static void max8997_haptic_play_effect_work(struct work_struct *work) 212104594b0SDonggeun Kim { 213104594b0SDonggeun Kim struct max8997_haptic *chip = 214104594b0SDonggeun Kim container_of(work, struct max8997_haptic, work); 215104594b0SDonggeun Kim 216104594b0SDonggeun Kim if (chip->level) 217104594b0SDonggeun Kim max8997_haptic_enable(chip); 218104594b0SDonggeun Kim else 219104594b0SDonggeun Kim max8997_haptic_disable(chip); 220104594b0SDonggeun Kim } 221104594b0SDonggeun Kim 222104594b0SDonggeun Kim static int max8997_haptic_play_effect(struct input_dev *dev, void *data, 223104594b0SDonggeun Kim struct ff_effect *effect) 224104594b0SDonggeun Kim { 225104594b0SDonggeun Kim struct max8997_haptic *chip = input_get_drvdata(dev); 226104594b0SDonggeun Kim 227104594b0SDonggeun Kim chip->level = effect->u.rumble.strong_magnitude; 228104594b0SDonggeun Kim if (!chip->level) 229104594b0SDonggeun Kim chip->level = effect->u.rumble.weak_magnitude; 230104594b0SDonggeun Kim 231104594b0SDonggeun Kim schedule_work(&chip->work); 232104594b0SDonggeun Kim 233104594b0SDonggeun Kim return 0; 234104594b0SDonggeun Kim } 235104594b0SDonggeun Kim 236104594b0SDonggeun Kim static void max8997_haptic_close(struct input_dev *dev) 237104594b0SDonggeun Kim { 238104594b0SDonggeun Kim struct max8997_haptic *chip = input_get_drvdata(dev); 239104594b0SDonggeun Kim 240104594b0SDonggeun Kim cancel_work_sync(&chip->work); 241104594b0SDonggeun Kim max8997_haptic_disable(chip); 242104594b0SDonggeun Kim } 243104594b0SDonggeun Kim 2445298cc4cSBill Pemberton static int max8997_haptic_probe(struct platform_device *pdev) 245104594b0SDonggeun Kim { 246104594b0SDonggeun Kim struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); 247104594b0SDonggeun Kim const struct max8997_platform_data *pdata = 248104594b0SDonggeun Kim dev_get_platdata(iodev->dev); 249104594b0SDonggeun Kim const struct max8997_haptic_platform_data *haptic_pdata = 250104594b0SDonggeun Kim pdata->haptic_pdata; 251104594b0SDonggeun Kim struct max8997_haptic *chip; 252104594b0SDonggeun Kim struct input_dev *input_dev; 253104594b0SDonggeun Kim int error; 254104594b0SDonggeun Kim 255104594b0SDonggeun Kim if (!haptic_pdata) { 256104594b0SDonggeun Kim dev_err(&pdev->dev, "no haptic platform data\n"); 257104594b0SDonggeun Kim return -EINVAL; 258104594b0SDonggeun Kim } 259104594b0SDonggeun Kim 260104594b0SDonggeun Kim chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL); 261104594b0SDonggeun Kim input_dev = input_allocate_device(); 262104594b0SDonggeun Kim if (!chip || !input_dev) { 263104594b0SDonggeun Kim dev_err(&pdev->dev, "unable to allocate memory\n"); 264104594b0SDonggeun Kim error = -ENOMEM; 265104594b0SDonggeun Kim goto err_free_mem; 266104594b0SDonggeun Kim } 267104594b0SDonggeun Kim 268104594b0SDonggeun Kim INIT_WORK(&chip->work, max8997_haptic_play_effect_work); 269104594b0SDonggeun Kim mutex_init(&chip->mutex); 270104594b0SDonggeun Kim 271104594b0SDonggeun Kim chip->client = iodev->haptic; 272104594b0SDonggeun Kim chip->dev = &pdev->dev; 273104594b0SDonggeun Kim chip->input_dev = input_dev; 274104594b0SDonggeun Kim chip->pwm_period = haptic_pdata->pwm_period; 275104594b0SDonggeun Kim chip->type = haptic_pdata->type; 276104594b0SDonggeun Kim chip->mode = haptic_pdata->mode; 277104594b0SDonggeun Kim chip->pwm_divisor = haptic_pdata->pwm_divisor; 278104594b0SDonggeun Kim 279104594b0SDonggeun Kim switch (chip->mode) { 280104594b0SDonggeun Kim case MAX8997_INTERNAL_MODE: 281104594b0SDonggeun Kim chip->internal_mode_pattern = 282104594b0SDonggeun Kim haptic_pdata->internal_mode_pattern; 283104594b0SDonggeun Kim chip->pattern_cycle = haptic_pdata->pattern_cycle; 284104594b0SDonggeun Kim chip->pattern_signal_period = 285104594b0SDonggeun Kim haptic_pdata->pattern_signal_period; 286104594b0SDonggeun Kim break; 287104594b0SDonggeun Kim 288104594b0SDonggeun Kim case MAX8997_EXTERNAL_MODE: 289104594b0SDonggeun Kim chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, 290104594b0SDonggeun Kim "max8997-haptic"); 291104594b0SDonggeun Kim if (IS_ERR(chip->pwm)) { 292104594b0SDonggeun Kim error = PTR_ERR(chip->pwm); 293104594b0SDonggeun Kim dev_err(&pdev->dev, 294104594b0SDonggeun Kim "unable to request PWM for haptic, error: %d\n", 295104594b0SDonggeun Kim error); 296104594b0SDonggeun Kim goto err_free_mem; 297104594b0SDonggeun Kim } 298104594b0SDonggeun Kim break; 299104594b0SDonggeun Kim 300104594b0SDonggeun Kim default: 301104594b0SDonggeun Kim dev_err(&pdev->dev, 302104594b0SDonggeun Kim "Invalid chip mode specified (%d)\n", chip->mode); 303104594b0SDonggeun Kim error = -EINVAL; 304104594b0SDonggeun Kim goto err_free_mem; 305104594b0SDonggeun Kim } 306104594b0SDonggeun Kim 307104594b0SDonggeun Kim chip->regulator = regulator_get(&pdev->dev, "inmotor"); 308104594b0SDonggeun Kim if (IS_ERR(chip->regulator)) { 309104594b0SDonggeun Kim error = PTR_ERR(chip->regulator); 310104594b0SDonggeun Kim dev_err(&pdev->dev, 311104594b0SDonggeun Kim "unable to get regulator, error: %d\n", 312104594b0SDonggeun Kim error); 313104594b0SDonggeun Kim goto err_free_pwm; 314104594b0SDonggeun Kim } 315104594b0SDonggeun Kim 316104594b0SDonggeun Kim input_dev->name = "max8997-haptic"; 317104594b0SDonggeun Kim input_dev->id.version = 1; 318104594b0SDonggeun Kim input_dev->dev.parent = &pdev->dev; 319104594b0SDonggeun Kim input_dev->close = max8997_haptic_close; 320104594b0SDonggeun Kim input_set_drvdata(input_dev, chip); 321104594b0SDonggeun Kim input_set_capability(input_dev, EV_FF, FF_RUMBLE); 322104594b0SDonggeun Kim 323104594b0SDonggeun Kim error = input_ff_create_memless(input_dev, NULL, 324104594b0SDonggeun Kim max8997_haptic_play_effect); 325104594b0SDonggeun Kim if (error) { 326104594b0SDonggeun Kim dev_err(&pdev->dev, 327104594b0SDonggeun Kim "unable to create FF device, error: %d\n", 328104594b0SDonggeun Kim error); 329104594b0SDonggeun Kim goto err_put_regulator; 330104594b0SDonggeun Kim } 331104594b0SDonggeun Kim 332104594b0SDonggeun Kim error = input_register_device(input_dev); 333104594b0SDonggeun Kim if (error) { 334104594b0SDonggeun Kim dev_err(&pdev->dev, 335104594b0SDonggeun Kim "unable to register input device, error: %d\n", 336104594b0SDonggeun Kim error); 337104594b0SDonggeun Kim goto err_destroy_ff; 338104594b0SDonggeun Kim } 339104594b0SDonggeun Kim 340104594b0SDonggeun Kim platform_set_drvdata(pdev, chip); 341104594b0SDonggeun Kim return 0; 342104594b0SDonggeun Kim 343104594b0SDonggeun Kim err_destroy_ff: 344104594b0SDonggeun Kim input_ff_destroy(input_dev); 345104594b0SDonggeun Kim err_put_regulator: 346104594b0SDonggeun Kim regulator_put(chip->regulator); 347104594b0SDonggeun Kim err_free_pwm: 348104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 349104594b0SDonggeun Kim pwm_free(chip->pwm); 350104594b0SDonggeun Kim err_free_mem: 351104594b0SDonggeun Kim input_free_device(input_dev); 352104594b0SDonggeun Kim kfree(chip); 353104594b0SDonggeun Kim 354104594b0SDonggeun Kim return error; 355104594b0SDonggeun Kim } 356104594b0SDonggeun Kim 357104594b0SDonggeun Kim static int __devexit max8997_haptic_remove(struct platform_device *pdev) 358104594b0SDonggeun Kim { 359104594b0SDonggeun Kim struct max8997_haptic *chip = platform_get_drvdata(pdev); 360104594b0SDonggeun Kim 361104594b0SDonggeun Kim input_unregister_device(chip->input_dev); 362104594b0SDonggeun Kim regulator_put(chip->regulator); 363104594b0SDonggeun Kim 364104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 365104594b0SDonggeun Kim pwm_free(chip->pwm); 366104594b0SDonggeun Kim 367104594b0SDonggeun Kim kfree(chip); 368104594b0SDonggeun Kim 369104594b0SDonggeun Kim return 0; 370104594b0SDonggeun Kim } 371104594b0SDonggeun Kim 372104594b0SDonggeun Kim #ifdef CONFIG_PM_SLEEP 373104594b0SDonggeun Kim static int max8997_haptic_suspend(struct device *dev) 374104594b0SDonggeun Kim { 375104594b0SDonggeun Kim struct platform_device *pdev = to_platform_device(dev); 376104594b0SDonggeun Kim struct max8997_haptic *chip = platform_get_drvdata(pdev); 377104594b0SDonggeun Kim 378104594b0SDonggeun Kim max8997_haptic_disable(chip); 379104594b0SDonggeun Kim 380104594b0SDonggeun Kim return 0; 381104594b0SDonggeun Kim } 382104594b0SDonggeun Kim #endif 383104594b0SDonggeun Kim 384104594b0SDonggeun Kim static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL); 385104594b0SDonggeun Kim 386104594b0SDonggeun Kim static const struct platform_device_id max8997_haptic_id[] = { 387104594b0SDonggeun Kim { "max8997-haptic", 0 }, 388104594b0SDonggeun Kim { }, 389104594b0SDonggeun Kim }; 390104594b0SDonggeun Kim MODULE_DEVICE_TABLE(i2c, max8997_haptic_id); 391104594b0SDonggeun Kim 392104594b0SDonggeun Kim static struct platform_driver max8997_haptic_driver = { 393104594b0SDonggeun Kim .driver = { 394104594b0SDonggeun Kim .name = "max8997-haptic", 395104594b0SDonggeun Kim .owner = THIS_MODULE, 396104594b0SDonggeun Kim .pm = &max8997_haptic_pm_ops, 397104594b0SDonggeun Kim }, 398104594b0SDonggeun Kim .probe = max8997_haptic_probe, 3991cb0aa88SBill Pemberton .remove = max8997_haptic_remove, 400104594b0SDonggeun Kim .id_table = max8997_haptic_id, 401104594b0SDonggeun Kim }; 402104594b0SDonggeun Kim module_platform_driver(max8997_haptic_driver); 403104594b0SDonggeun Kim 404104594b0SDonggeun Kim MODULE_ALIAS("platform:max8997-haptic"); 405104594b0SDonggeun Kim MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); 406104594b0SDonggeun Kim MODULE_DESCRIPTION("max8997_haptic driver"); 407104594b0SDonggeun Kim MODULE_LICENSE("GPL"); 408