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/slab.h> 27104594b0SDonggeun Kim #include <linux/platform_device.h> 28104594b0SDonggeun Kim #include <linux/err.h> 29104594b0SDonggeun Kim #include <linux/pwm.h> 30104594b0SDonggeun Kim #include <linux/input.h> 31104594b0SDonggeun Kim #include <linux/mfd/max8997-private.h> 32104594b0SDonggeun Kim #include <linux/mfd/max8997.h> 33104594b0SDonggeun Kim #include <linux/regulator/consumer.h> 34104594b0SDonggeun Kim 35104594b0SDonggeun Kim /* Haptic configuration 2 register */ 36104594b0SDonggeun Kim #define MAX8997_MOTOR_TYPE_SHIFT 7 37104594b0SDonggeun Kim #define MAX8997_ENABLE_SHIFT 6 38104594b0SDonggeun Kim #define MAX8997_MODE_SHIFT 5 39104594b0SDonggeun Kim 40104594b0SDonggeun Kim /* Haptic driver configuration register */ 41104594b0SDonggeun Kim #define MAX8997_CYCLE_SHIFT 6 42104594b0SDonggeun Kim #define MAX8997_SIG_PERIOD_SHIFT 4 43104594b0SDonggeun Kim #define MAX8997_SIG_DUTY_SHIFT 2 44104594b0SDonggeun Kim #define MAX8997_PWM_DUTY_SHIFT 0 45104594b0SDonggeun Kim 46104594b0SDonggeun Kim struct max8997_haptic { 47104594b0SDonggeun Kim struct device *dev; 48104594b0SDonggeun Kim struct i2c_client *client; 49104594b0SDonggeun Kim struct input_dev *input_dev; 50104594b0SDonggeun Kim struct regulator *regulator; 51104594b0SDonggeun Kim 52104594b0SDonggeun Kim struct work_struct work; 53104594b0SDonggeun Kim struct mutex mutex; 54104594b0SDonggeun Kim 55104594b0SDonggeun Kim bool enabled; 56104594b0SDonggeun Kim unsigned int level; 57104594b0SDonggeun Kim 58104594b0SDonggeun Kim struct pwm_device *pwm; 59104594b0SDonggeun Kim unsigned int pwm_period; 60104594b0SDonggeun Kim enum max8997_haptic_pwm_divisor pwm_divisor; 61104594b0SDonggeun Kim 62104594b0SDonggeun Kim enum max8997_haptic_motor_type type; 63104594b0SDonggeun Kim enum max8997_haptic_pulse_mode mode; 64104594b0SDonggeun Kim 65104594b0SDonggeun Kim unsigned int internal_mode_pattern; 66104594b0SDonggeun Kim unsigned int pattern_cycle; 67104594b0SDonggeun Kim unsigned int pattern_signal_period; 68104594b0SDonggeun Kim }; 69104594b0SDonggeun Kim 70104594b0SDonggeun Kim static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip) 71104594b0SDonggeun Kim { 72104594b0SDonggeun Kim int ret = 0; 73104594b0SDonggeun Kim 74104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) { 75104594b0SDonggeun Kim unsigned int duty = chip->pwm_period * chip->level / 100; 76104594b0SDonggeun Kim ret = pwm_config(chip->pwm, duty, chip->pwm_period); 77104594b0SDonggeun Kim } else { 78104594b0SDonggeun Kim int i; 79104594b0SDonggeun Kim u8 duty_index = 0; 80104594b0SDonggeun Kim 81104594b0SDonggeun Kim for (i = 0; i <= 64; i++) { 82104594b0SDonggeun Kim if (chip->level <= i * 100 / 64) { 83104594b0SDonggeun Kim duty_index = i; 84104594b0SDonggeun Kim break; 85104594b0SDonggeun Kim } 86104594b0SDonggeun Kim } 87104594b0SDonggeun Kim switch (chip->internal_mode_pattern) { 88104594b0SDonggeun Kim case 0: 89104594b0SDonggeun Kim max8997_write_reg(chip->client, 90104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index); 91104594b0SDonggeun Kim break; 92104594b0SDonggeun Kim case 1: 93104594b0SDonggeun Kim max8997_write_reg(chip->client, 94104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index); 95104594b0SDonggeun Kim break; 96104594b0SDonggeun Kim case 2: 97104594b0SDonggeun Kim max8997_write_reg(chip->client, 98104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index); 99104594b0SDonggeun Kim break; 100104594b0SDonggeun Kim case 3: 101104594b0SDonggeun Kim max8997_write_reg(chip->client, 102104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index); 103104594b0SDonggeun Kim break; 104104594b0SDonggeun Kim default: 105104594b0SDonggeun Kim break; 106104594b0SDonggeun Kim } 107104594b0SDonggeun Kim } 108104594b0SDonggeun Kim return ret; 109104594b0SDonggeun Kim } 110104594b0SDonggeun Kim 111104594b0SDonggeun Kim static void max8997_haptic_configure(struct max8997_haptic *chip) 112104594b0SDonggeun Kim { 113104594b0SDonggeun Kim u8 value; 114104594b0SDonggeun Kim 115104594b0SDonggeun Kim value = chip->type << MAX8997_MOTOR_TYPE_SHIFT | 116104594b0SDonggeun Kim chip->enabled << MAX8997_ENABLE_SHIFT | 117104594b0SDonggeun Kim chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor; 118104594b0SDonggeun Kim max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value); 119104594b0SDonggeun Kim 120104594b0SDonggeun Kim if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) { 121104594b0SDonggeun Kim value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT | 122104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT | 123104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT | 124104594b0SDonggeun Kim chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT; 125104594b0SDonggeun Kim max8997_write_reg(chip->client, 126104594b0SDonggeun Kim MAX8997_HAPTIC_REG_DRVCONF, value); 127104594b0SDonggeun Kim 128104594b0SDonggeun Kim switch (chip->internal_mode_pattern) { 129104594b0SDonggeun Kim case 0: 130104594b0SDonggeun Kim value = chip->pattern_cycle << 4; 131104594b0SDonggeun Kim max8997_write_reg(chip->client, 132104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF1, value); 133104594b0SDonggeun Kim value = chip->pattern_signal_period; 134104594b0SDonggeun Kim max8997_write_reg(chip->client, 135104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF1, value); 136104594b0SDonggeun Kim break; 137104594b0SDonggeun Kim 138104594b0SDonggeun Kim case 1: 139104594b0SDonggeun Kim value = chip->pattern_cycle; 140104594b0SDonggeun Kim max8997_write_reg(chip->client, 141104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF1, value); 142104594b0SDonggeun Kim value = chip->pattern_signal_period; 143104594b0SDonggeun Kim max8997_write_reg(chip->client, 144104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF2, value); 145104594b0SDonggeun Kim break; 146104594b0SDonggeun Kim 147104594b0SDonggeun Kim case 2: 148104594b0SDonggeun Kim value = chip->pattern_cycle << 4; 149104594b0SDonggeun Kim max8997_write_reg(chip->client, 150104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF2, value); 151104594b0SDonggeun Kim value = chip->pattern_signal_period; 152104594b0SDonggeun Kim max8997_write_reg(chip->client, 153104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF3, value); 154104594b0SDonggeun Kim break; 155104594b0SDonggeun Kim 156104594b0SDonggeun Kim case 3: 157104594b0SDonggeun Kim value = chip->pattern_cycle; 158104594b0SDonggeun Kim max8997_write_reg(chip->client, 159104594b0SDonggeun Kim MAX8997_HAPTIC_REG_CYCLECONF2, value); 160104594b0SDonggeun Kim value = chip->pattern_signal_period; 161104594b0SDonggeun Kim max8997_write_reg(chip->client, 162104594b0SDonggeun Kim MAX8997_HAPTIC_REG_SIGCONF4, value); 163104594b0SDonggeun Kim break; 164104594b0SDonggeun Kim 165104594b0SDonggeun Kim default: 166104594b0SDonggeun Kim break; 167104594b0SDonggeun Kim } 168104594b0SDonggeun Kim } 169104594b0SDonggeun Kim } 170104594b0SDonggeun Kim 171104594b0SDonggeun Kim static void max8997_haptic_enable(struct max8997_haptic *chip) 172104594b0SDonggeun Kim { 173104594b0SDonggeun Kim int error; 174104594b0SDonggeun Kim 175104594b0SDonggeun Kim mutex_lock(&chip->mutex); 176104594b0SDonggeun Kim 177104594b0SDonggeun Kim error = max8997_haptic_set_duty_cycle(chip); 178104594b0SDonggeun Kim if (error) { 179104594b0SDonggeun Kim dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error); 180104594b0SDonggeun Kim goto out; 181104594b0SDonggeun Kim } 182104594b0SDonggeun Kim 183104594b0SDonggeun Kim if (!chip->enabled) { 184b1bc3031SSachin Kamat error = regulator_enable(chip->regulator); 185b1bc3031SSachin Kamat if (error) { 186b1bc3031SSachin Kamat dev_err(chip->dev, "Failed to enable regulator\n"); 187b1bc3031SSachin Kamat goto out; 188b1bc3031SSachin Kamat } 189104594b0SDonggeun Kim max8997_haptic_configure(chip); 190b1bc3031SSachin Kamat if (chip->mode == MAX8997_EXTERNAL_MODE) { 191b1bc3031SSachin Kamat error = pwm_enable(chip->pwm); 192b1bc3031SSachin Kamat if (error) { 193b1bc3031SSachin Kamat dev_err(chip->dev, "Failed to enable PWM\n"); 194b1bc3031SSachin Kamat regulator_disable(chip->regulator); 195b1bc3031SSachin Kamat goto out; 196b1bc3031SSachin Kamat } 197b1bc3031SSachin Kamat } 198b1bc3031SSachin Kamat chip->enabled = true; 199104594b0SDonggeun Kim } 200104594b0SDonggeun Kim 201104594b0SDonggeun Kim out: 202104594b0SDonggeun Kim mutex_unlock(&chip->mutex); 203104594b0SDonggeun Kim } 204104594b0SDonggeun Kim 205104594b0SDonggeun Kim static void max8997_haptic_disable(struct max8997_haptic *chip) 206104594b0SDonggeun Kim { 207104594b0SDonggeun Kim mutex_lock(&chip->mutex); 208104594b0SDonggeun Kim 209104594b0SDonggeun Kim if (chip->enabled) { 210104594b0SDonggeun Kim chip->enabled = false; 211104594b0SDonggeun Kim max8997_haptic_configure(chip); 212104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 213104594b0SDonggeun Kim pwm_disable(chip->pwm); 214104594b0SDonggeun Kim regulator_disable(chip->regulator); 215104594b0SDonggeun Kim } 216104594b0SDonggeun Kim 217104594b0SDonggeun Kim mutex_unlock(&chip->mutex); 218104594b0SDonggeun Kim } 219104594b0SDonggeun Kim 220104594b0SDonggeun Kim static void max8997_haptic_play_effect_work(struct work_struct *work) 221104594b0SDonggeun Kim { 222104594b0SDonggeun Kim struct max8997_haptic *chip = 223104594b0SDonggeun Kim container_of(work, struct max8997_haptic, work); 224104594b0SDonggeun Kim 225104594b0SDonggeun Kim if (chip->level) 226104594b0SDonggeun Kim max8997_haptic_enable(chip); 227104594b0SDonggeun Kim else 228104594b0SDonggeun Kim max8997_haptic_disable(chip); 229104594b0SDonggeun Kim } 230104594b0SDonggeun Kim 231104594b0SDonggeun Kim static int max8997_haptic_play_effect(struct input_dev *dev, void *data, 232104594b0SDonggeun Kim struct ff_effect *effect) 233104594b0SDonggeun Kim { 234104594b0SDonggeun Kim struct max8997_haptic *chip = input_get_drvdata(dev); 235104594b0SDonggeun Kim 236104594b0SDonggeun Kim chip->level = effect->u.rumble.strong_magnitude; 237104594b0SDonggeun Kim if (!chip->level) 238104594b0SDonggeun Kim chip->level = effect->u.rumble.weak_magnitude; 239104594b0SDonggeun Kim 240104594b0SDonggeun Kim schedule_work(&chip->work); 241104594b0SDonggeun Kim 242104594b0SDonggeun Kim return 0; 243104594b0SDonggeun Kim } 244104594b0SDonggeun Kim 245104594b0SDonggeun Kim static void max8997_haptic_close(struct input_dev *dev) 246104594b0SDonggeun Kim { 247104594b0SDonggeun Kim struct max8997_haptic *chip = input_get_drvdata(dev); 248104594b0SDonggeun Kim 249104594b0SDonggeun Kim cancel_work_sync(&chip->work); 250104594b0SDonggeun Kim max8997_haptic_disable(chip); 251104594b0SDonggeun Kim } 252104594b0SDonggeun Kim 2535298cc4cSBill Pemberton static int max8997_haptic_probe(struct platform_device *pdev) 254104594b0SDonggeun Kim { 255104594b0SDonggeun Kim struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); 256104594b0SDonggeun Kim const struct max8997_platform_data *pdata = 257104594b0SDonggeun Kim dev_get_platdata(iodev->dev); 258104594b0SDonggeun Kim const struct max8997_haptic_platform_data *haptic_pdata = 259104594b0SDonggeun Kim pdata->haptic_pdata; 260104594b0SDonggeun Kim struct max8997_haptic *chip; 261104594b0SDonggeun Kim struct input_dev *input_dev; 262104594b0SDonggeun Kim int error; 263104594b0SDonggeun Kim 264104594b0SDonggeun Kim if (!haptic_pdata) { 265104594b0SDonggeun Kim dev_err(&pdev->dev, "no haptic platform data\n"); 266104594b0SDonggeun Kim return -EINVAL; 267104594b0SDonggeun Kim } 268104594b0SDonggeun Kim 269104594b0SDonggeun Kim chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL); 270104594b0SDonggeun Kim input_dev = input_allocate_device(); 271104594b0SDonggeun Kim if (!chip || !input_dev) { 272104594b0SDonggeun Kim dev_err(&pdev->dev, "unable to allocate memory\n"); 273104594b0SDonggeun Kim error = -ENOMEM; 274104594b0SDonggeun Kim goto err_free_mem; 275104594b0SDonggeun Kim } 276104594b0SDonggeun Kim 277104594b0SDonggeun Kim INIT_WORK(&chip->work, max8997_haptic_play_effect_work); 278104594b0SDonggeun Kim mutex_init(&chip->mutex); 279104594b0SDonggeun Kim 280104594b0SDonggeun Kim chip->client = iodev->haptic; 281104594b0SDonggeun Kim chip->dev = &pdev->dev; 282104594b0SDonggeun Kim chip->input_dev = input_dev; 283104594b0SDonggeun Kim chip->pwm_period = haptic_pdata->pwm_period; 284104594b0SDonggeun Kim chip->type = haptic_pdata->type; 285104594b0SDonggeun Kim chip->mode = haptic_pdata->mode; 286104594b0SDonggeun Kim chip->pwm_divisor = haptic_pdata->pwm_divisor; 287104594b0SDonggeun Kim 288104594b0SDonggeun Kim switch (chip->mode) { 289104594b0SDonggeun Kim case MAX8997_INTERNAL_MODE: 290104594b0SDonggeun Kim chip->internal_mode_pattern = 291104594b0SDonggeun Kim haptic_pdata->internal_mode_pattern; 292104594b0SDonggeun Kim chip->pattern_cycle = haptic_pdata->pattern_cycle; 293104594b0SDonggeun Kim chip->pattern_signal_period = 294104594b0SDonggeun Kim haptic_pdata->pattern_signal_period; 295104594b0SDonggeun Kim break; 296104594b0SDonggeun Kim 297104594b0SDonggeun Kim case MAX8997_EXTERNAL_MODE: 298104594b0SDonggeun Kim chip->pwm = pwm_request(haptic_pdata->pwm_channel_id, 299104594b0SDonggeun Kim "max8997-haptic"); 300104594b0SDonggeun Kim if (IS_ERR(chip->pwm)) { 301104594b0SDonggeun Kim error = PTR_ERR(chip->pwm); 302104594b0SDonggeun Kim dev_err(&pdev->dev, 303104594b0SDonggeun Kim "unable to request PWM for haptic, error: %d\n", 304104594b0SDonggeun Kim error); 305104594b0SDonggeun Kim goto err_free_mem; 306104594b0SDonggeun Kim } 307104594b0SDonggeun Kim break; 308104594b0SDonggeun Kim 309104594b0SDonggeun Kim default: 310104594b0SDonggeun Kim dev_err(&pdev->dev, 311104594b0SDonggeun Kim "Invalid chip mode specified (%d)\n", chip->mode); 312104594b0SDonggeun Kim error = -EINVAL; 313104594b0SDonggeun Kim goto err_free_mem; 314104594b0SDonggeun Kim } 315104594b0SDonggeun Kim 316104594b0SDonggeun Kim chip->regulator = regulator_get(&pdev->dev, "inmotor"); 317104594b0SDonggeun Kim if (IS_ERR(chip->regulator)) { 318104594b0SDonggeun Kim error = PTR_ERR(chip->regulator); 319104594b0SDonggeun Kim dev_err(&pdev->dev, 320104594b0SDonggeun Kim "unable to get regulator, error: %d\n", 321104594b0SDonggeun Kim error); 322104594b0SDonggeun Kim goto err_free_pwm; 323104594b0SDonggeun Kim } 324104594b0SDonggeun Kim 325104594b0SDonggeun Kim input_dev->name = "max8997-haptic"; 326104594b0SDonggeun Kim input_dev->id.version = 1; 327104594b0SDonggeun Kim input_dev->dev.parent = &pdev->dev; 328104594b0SDonggeun Kim input_dev->close = max8997_haptic_close; 329104594b0SDonggeun Kim input_set_drvdata(input_dev, chip); 330104594b0SDonggeun Kim input_set_capability(input_dev, EV_FF, FF_RUMBLE); 331104594b0SDonggeun Kim 332104594b0SDonggeun Kim error = input_ff_create_memless(input_dev, NULL, 333104594b0SDonggeun Kim max8997_haptic_play_effect); 334104594b0SDonggeun Kim if (error) { 335104594b0SDonggeun Kim dev_err(&pdev->dev, 336104594b0SDonggeun Kim "unable to create FF device, error: %d\n", 337104594b0SDonggeun Kim error); 338104594b0SDonggeun Kim goto err_put_regulator; 339104594b0SDonggeun Kim } 340104594b0SDonggeun Kim 341104594b0SDonggeun Kim error = input_register_device(input_dev); 342104594b0SDonggeun Kim if (error) { 343104594b0SDonggeun Kim dev_err(&pdev->dev, 344104594b0SDonggeun Kim "unable to register input device, error: %d\n", 345104594b0SDonggeun Kim error); 346104594b0SDonggeun Kim goto err_destroy_ff; 347104594b0SDonggeun Kim } 348104594b0SDonggeun Kim 349104594b0SDonggeun Kim platform_set_drvdata(pdev, chip); 350104594b0SDonggeun Kim return 0; 351104594b0SDonggeun Kim 352104594b0SDonggeun Kim err_destroy_ff: 353104594b0SDonggeun Kim input_ff_destroy(input_dev); 354104594b0SDonggeun Kim err_put_regulator: 355104594b0SDonggeun Kim regulator_put(chip->regulator); 356104594b0SDonggeun Kim err_free_pwm: 357104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 358104594b0SDonggeun Kim pwm_free(chip->pwm); 359104594b0SDonggeun Kim err_free_mem: 360104594b0SDonggeun Kim input_free_device(input_dev); 361104594b0SDonggeun Kim kfree(chip); 362104594b0SDonggeun Kim 363104594b0SDonggeun Kim return error; 364104594b0SDonggeun Kim } 365104594b0SDonggeun Kim 366e2619cf7SBill Pemberton static int max8997_haptic_remove(struct platform_device *pdev) 367104594b0SDonggeun Kim { 368104594b0SDonggeun Kim struct max8997_haptic *chip = platform_get_drvdata(pdev); 369104594b0SDonggeun Kim 370104594b0SDonggeun Kim input_unregister_device(chip->input_dev); 371104594b0SDonggeun Kim regulator_put(chip->regulator); 372104594b0SDonggeun Kim 373104594b0SDonggeun Kim if (chip->mode == MAX8997_EXTERNAL_MODE) 374104594b0SDonggeun Kim pwm_free(chip->pwm); 375104594b0SDonggeun Kim 376104594b0SDonggeun Kim kfree(chip); 377104594b0SDonggeun Kim 378104594b0SDonggeun Kim return 0; 379104594b0SDonggeun Kim } 380104594b0SDonggeun Kim 38197a652a8SJingoo Han static int __maybe_unused max8997_haptic_suspend(struct device *dev) 382104594b0SDonggeun Kim { 383104594b0SDonggeun Kim struct platform_device *pdev = to_platform_device(dev); 384104594b0SDonggeun Kim struct max8997_haptic *chip = platform_get_drvdata(pdev); 385104594b0SDonggeun Kim 386104594b0SDonggeun Kim max8997_haptic_disable(chip); 387104594b0SDonggeun Kim 388104594b0SDonggeun Kim return 0; 389104594b0SDonggeun Kim } 390104594b0SDonggeun Kim 391104594b0SDonggeun Kim static SIMPLE_DEV_PM_OPS(max8997_haptic_pm_ops, max8997_haptic_suspend, NULL); 392104594b0SDonggeun Kim 393104594b0SDonggeun Kim static const struct platform_device_id max8997_haptic_id[] = { 394104594b0SDonggeun Kim { "max8997-haptic", 0 }, 395104594b0SDonggeun Kim { }, 396104594b0SDonggeun Kim }; 397104594b0SDonggeun Kim MODULE_DEVICE_TABLE(i2c, max8997_haptic_id); 398104594b0SDonggeun Kim 399104594b0SDonggeun Kim static struct platform_driver max8997_haptic_driver = { 400104594b0SDonggeun Kim .driver = { 401104594b0SDonggeun Kim .name = "max8997-haptic", 402104594b0SDonggeun Kim .owner = THIS_MODULE, 403104594b0SDonggeun Kim .pm = &max8997_haptic_pm_ops, 404104594b0SDonggeun Kim }, 405104594b0SDonggeun Kim .probe = max8997_haptic_probe, 4061cb0aa88SBill Pemberton .remove = max8997_haptic_remove, 407104594b0SDonggeun Kim .id_table = max8997_haptic_id, 408104594b0SDonggeun Kim }; 409104594b0SDonggeun Kim module_platform_driver(max8997_haptic_driver); 410104594b0SDonggeun Kim 411104594b0SDonggeun Kim MODULE_ALIAS("platform:max8997-haptic"); 412104594b0SDonggeun Kim MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); 413104594b0SDonggeun Kim MODULE_DESCRIPTION("max8997_haptic driver"); 414104594b0SDonggeun Kim MODULE_LICENSE("GPL"); 415