12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 23e5b0851SSebastian Reichel /* 33e5b0851SSebastian Reichel * PWM vibrator driver 43e5b0851SSebastian Reichel * 53e5b0851SSebastian Reichel * Copyright (C) 2017 Collabora Ltd. 63e5b0851SSebastian Reichel * 73e5b0851SSebastian Reichel * Based on previous work from: 83e5b0851SSebastian Reichel * Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com> 93e5b0851SSebastian Reichel * 103e5b0851SSebastian Reichel * Based on PWM beeper driver: 113e5b0851SSebastian Reichel * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> 123e5b0851SSebastian Reichel */ 133e5b0851SSebastian Reichel 14bcf78498SLuca Weiss #include <linux/gpio/consumer.h> 153e5b0851SSebastian Reichel #include <linux/input.h> 163e5b0851SSebastian Reichel #include <linux/kernel.h> 173e5b0851SSebastian Reichel #include <linux/module.h> 183e5b0851SSebastian Reichel #include <linux/of_device.h> 193e5b0851SSebastian Reichel #include <linux/platform_device.h> 203e5b0851SSebastian Reichel #include <linux/property.h> 213e5b0851SSebastian Reichel #include <linux/pwm.h> 223e5b0851SSebastian Reichel #include <linux/regulator/consumer.h> 233e5b0851SSebastian Reichel #include <linux/slab.h> 243e5b0851SSebastian Reichel 253e5b0851SSebastian Reichel struct pwm_vibrator { 263e5b0851SSebastian Reichel struct input_dev *input; 27bcf78498SLuca Weiss struct gpio_desc *enable_gpio; 283e5b0851SSebastian Reichel struct pwm_device *pwm; 293e5b0851SSebastian Reichel struct pwm_device *pwm_dir; 303e5b0851SSebastian Reichel struct regulator *vcc; 313e5b0851SSebastian Reichel 323e5b0851SSebastian Reichel struct work_struct play_work; 333e5b0851SSebastian Reichel u16 level; 343e5b0851SSebastian Reichel u32 direction_duty_cycle; 353ca232dfSJonathan Bakker bool vcc_on; 363e5b0851SSebastian Reichel }; 373e5b0851SSebastian Reichel 383e5b0851SSebastian Reichel static int pwm_vibrator_start(struct pwm_vibrator *vibrator) 393e5b0851SSebastian Reichel { 403e5b0851SSebastian Reichel struct device *pdev = vibrator->input->dev.parent; 413e5b0851SSebastian Reichel struct pwm_state state; 423e5b0851SSebastian Reichel int err; 433e5b0851SSebastian Reichel 443ca232dfSJonathan Bakker if (!vibrator->vcc_on) { 453e5b0851SSebastian Reichel err = regulator_enable(vibrator->vcc); 463e5b0851SSebastian Reichel if (err) { 4729ebf697SLuca Weiss dev_err(pdev, "failed to enable regulator: %d\n", err); 483e5b0851SSebastian Reichel return err; 493e5b0851SSebastian Reichel } 503ca232dfSJonathan Bakker vibrator->vcc_on = true; 513ca232dfSJonathan Bakker } 523e5b0851SSebastian Reichel 53bcf78498SLuca Weiss gpiod_set_value_cansleep(vibrator->enable_gpio, 1); 54bcf78498SLuca Weiss 553e5b0851SSebastian Reichel pwm_get_state(vibrator->pwm, &state); 563e5b0851SSebastian Reichel pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff); 573e5b0851SSebastian Reichel state.enabled = true; 583e5b0851SSebastian Reichel 593e5b0851SSebastian Reichel err = pwm_apply_state(vibrator->pwm, &state); 603e5b0851SSebastian Reichel if (err) { 6129ebf697SLuca Weiss dev_err(pdev, "failed to apply pwm state: %d\n", err); 623e5b0851SSebastian Reichel return err; 633e5b0851SSebastian Reichel } 643e5b0851SSebastian Reichel 653e5b0851SSebastian Reichel if (vibrator->pwm_dir) { 663e5b0851SSebastian Reichel pwm_get_state(vibrator->pwm_dir, &state); 673e5b0851SSebastian Reichel state.duty_cycle = vibrator->direction_duty_cycle; 683e5b0851SSebastian Reichel state.enabled = true; 693e5b0851SSebastian Reichel 703e5b0851SSebastian Reichel err = pwm_apply_state(vibrator->pwm_dir, &state); 713e5b0851SSebastian Reichel if (err) { 7229ebf697SLuca Weiss dev_err(pdev, "failed to apply dir-pwm state: %d\n", err); 733e5b0851SSebastian Reichel pwm_disable(vibrator->pwm); 743e5b0851SSebastian Reichel return err; 753e5b0851SSebastian Reichel } 763e5b0851SSebastian Reichel } 773e5b0851SSebastian Reichel 783e5b0851SSebastian Reichel return 0; 793e5b0851SSebastian Reichel } 803e5b0851SSebastian Reichel 813e5b0851SSebastian Reichel static void pwm_vibrator_stop(struct pwm_vibrator *vibrator) 823e5b0851SSebastian Reichel { 8394803aefSPaweł Chmiel if (vibrator->pwm_dir) 8494803aefSPaweł Chmiel pwm_disable(vibrator->pwm_dir); 8594803aefSPaweł Chmiel pwm_disable(vibrator->pwm); 8694803aefSPaweł Chmiel 87bcf78498SLuca Weiss gpiod_set_value_cansleep(vibrator->enable_gpio, 0); 88bcf78498SLuca Weiss 893ca232dfSJonathan Bakker if (vibrator->vcc_on) { 903e5b0851SSebastian Reichel regulator_disable(vibrator->vcc); 913ca232dfSJonathan Bakker vibrator->vcc_on = false; 923ca232dfSJonathan Bakker } 933e5b0851SSebastian Reichel } 943e5b0851SSebastian Reichel 953e5b0851SSebastian Reichel static void pwm_vibrator_play_work(struct work_struct *work) 963e5b0851SSebastian Reichel { 973e5b0851SSebastian Reichel struct pwm_vibrator *vibrator = container_of(work, 983e5b0851SSebastian Reichel struct pwm_vibrator, play_work); 993e5b0851SSebastian Reichel 1003e5b0851SSebastian Reichel if (vibrator->level) 1013e5b0851SSebastian Reichel pwm_vibrator_start(vibrator); 1023e5b0851SSebastian Reichel else 1033e5b0851SSebastian Reichel pwm_vibrator_stop(vibrator); 1043e5b0851SSebastian Reichel } 1053e5b0851SSebastian Reichel 1063e5b0851SSebastian Reichel static int pwm_vibrator_play_effect(struct input_dev *dev, void *data, 1073e5b0851SSebastian Reichel struct ff_effect *effect) 1083e5b0851SSebastian Reichel { 1093e5b0851SSebastian Reichel struct pwm_vibrator *vibrator = input_get_drvdata(dev); 1103e5b0851SSebastian Reichel 1113e5b0851SSebastian Reichel vibrator->level = effect->u.rumble.strong_magnitude; 1123e5b0851SSebastian Reichel if (!vibrator->level) 1133e5b0851SSebastian Reichel vibrator->level = effect->u.rumble.weak_magnitude; 1143e5b0851SSebastian Reichel 1153e5b0851SSebastian Reichel schedule_work(&vibrator->play_work); 1163e5b0851SSebastian Reichel 1173e5b0851SSebastian Reichel return 0; 1183e5b0851SSebastian Reichel } 1193e5b0851SSebastian Reichel 1203e5b0851SSebastian Reichel static void pwm_vibrator_close(struct input_dev *input) 1213e5b0851SSebastian Reichel { 1223e5b0851SSebastian Reichel struct pwm_vibrator *vibrator = input_get_drvdata(input); 1233e5b0851SSebastian Reichel 1243e5b0851SSebastian Reichel cancel_work_sync(&vibrator->play_work); 1253e5b0851SSebastian Reichel pwm_vibrator_stop(vibrator); 1263e5b0851SSebastian Reichel } 1273e5b0851SSebastian Reichel 1283e5b0851SSebastian Reichel static int pwm_vibrator_probe(struct platform_device *pdev) 1293e5b0851SSebastian Reichel { 1303e5b0851SSebastian Reichel struct pwm_vibrator *vibrator; 1313e5b0851SSebastian Reichel struct pwm_state state; 1323e5b0851SSebastian Reichel int err; 1333e5b0851SSebastian Reichel 1343e5b0851SSebastian Reichel vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL); 1353e5b0851SSebastian Reichel if (!vibrator) 1363e5b0851SSebastian Reichel return -ENOMEM; 1373e5b0851SSebastian Reichel 1383e5b0851SSebastian Reichel vibrator->input = devm_input_allocate_device(&pdev->dev); 1393e5b0851SSebastian Reichel if (!vibrator->input) 1403e5b0851SSebastian Reichel return -ENOMEM; 1413e5b0851SSebastian Reichel 1423e5b0851SSebastian Reichel vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); 143*a07e68dfSKrzysztof Kozlowski if (IS_ERR(vibrator->vcc)) 144*a07e68dfSKrzysztof Kozlowski return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->vcc), 145*a07e68dfSKrzysztof Kozlowski "Failed to request regulator\n"); 1463e5b0851SSebastian Reichel 147bcf78498SLuca Weiss vibrator->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 148bcf78498SLuca Weiss GPIOD_OUT_LOW); 149*a07e68dfSKrzysztof Kozlowski if (IS_ERR(vibrator->enable_gpio)) 150*a07e68dfSKrzysztof Kozlowski return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->enable_gpio), 151*a07e68dfSKrzysztof Kozlowski "Failed to request enable gpio\n"); 152bcf78498SLuca Weiss 1533e5b0851SSebastian Reichel vibrator->pwm = devm_pwm_get(&pdev->dev, "enable"); 154*a07e68dfSKrzysztof Kozlowski if (IS_ERR(vibrator->pwm)) 155*a07e68dfSKrzysztof Kozlowski return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->pwm), 156*a07e68dfSKrzysztof Kozlowski "Failed to request main pwm\n"); 1573e5b0851SSebastian Reichel 1583e5b0851SSebastian Reichel INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work); 1593e5b0851SSebastian Reichel 1603e5b0851SSebastian Reichel /* Sync up PWM state and ensure it is off. */ 1613e5b0851SSebastian Reichel pwm_init_state(vibrator->pwm, &state); 1623e5b0851SSebastian Reichel state.enabled = false; 1633e5b0851SSebastian Reichel err = pwm_apply_state(vibrator->pwm, &state); 1643e5b0851SSebastian Reichel if (err) { 16529ebf697SLuca Weiss dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n", 1663e5b0851SSebastian Reichel err); 1673e5b0851SSebastian Reichel return err; 1683e5b0851SSebastian Reichel } 1693e5b0851SSebastian Reichel 1703e5b0851SSebastian Reichel vibrator->pwm_dir = devm_pwm_get(&pdev->dev, "direction"); 1713e5b0851SSebastian Reichel err = PTR_ERR_OR_ZERO(vibrator->pwm_dir); 1723e5b0851SSebastian Reichel switch (err) { 1733e5b0851SSebastian Reichel case 0: 1743e5b0851SSebastian Reichel /* Sync up PWM state and ensure it is off. */ 1753e5b0851SSebastian Reichel pwm_init_state(vibrator->pwm_dir, &state); 1763e5b0851SSebastian Reichel state.enabled = false; 1773e5b0851SSebastian Reichel err = pwm_apply_state(vibrator->pwm_dir, &state); 1783e5b0851SSebastian Reichel if (err) { 17929ebf697SLuca Weiss dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n", 1803e5b0851SSebastian Reichel err); 1813e5b0851SSebastian Reichel return err; 1823e5b0851SSebastian Reichel } 1833e5b0851SSebastian Reichel 1843e5b0851SSebastian Reichel vibrator->direction_duty_cycle = 1853e5b0851SSebastian Reichel pwm_get_period(vibrator->pwm_dir) / 2; 1863e5b0851SSebastian Reichel device_property_read_u32(&pdev->dev, "direction-duty-cycle-ns", 1873e5b0851SSebastian Reichel &vibrator->direction_duty_cycle); 1883e5b0851SSebastian Reichel break; 1893e5b0851SSebastian Reichel 1903e5b0851SSebastian Reichel case -ENODATA: 1913e5b0851SSebastian Reichel /* Direction PWM is optional */ 1923e5b0851SSebastian Reichel vibrator->pwm_dir = NULL; 1933e5b0851SSebastian Reichel break; 1943e5b0851SSebastian Reichel 1953e5b0851SSebastian Reichel default: 19629ebf697SLuca Weiss dev_err(&pdev->dev, "Failed to request direction pwm: %d\n", err); 1976f49c4f5SGustavo A. R. Silva fallthrough; 1983e5b0851SSebastian Reichel 1993e5b0851SSebastian Reichel case -EPROBE_DEFER: 2003e5b0851SSebastian Reichel return err; 2013e5b0851SSebastian Reichel } 2023e5b0851SSebastian Reichel 2033e5b0851SSebastian Reichel vibrator->input->name = "pwm-vibrator"; 2043e5b0851SSebastian Reichel vibrator->input->id.bustype = BUS_HOST; 2053e5b0851SSebastian Reichel vibrator->input->dev.parent = &pdev->dev; 2063e5b0851SSebastian Reichel vibrator->input->close = pwm_vibrator_close; 2073e5b0851SSebastian Reichel 2083e5b0851SSebastian Reichel input_set_drvdata(vibrator->input, vibrator); 2093e5b0851SSebastian Reichel input_set_capability(vibrator->input, EV_FF, FF_RUMBLE); 2103e5b0851SSebastian Reichel 2113e5b0851SSebastian Reichel err = input_ff_create_memless(vibrator->input, NULL, 2123e5b0851SSebastian Reichel pwm_vibrator_play_effect); 2133e5b0851SSebastian Reichel if (err) { 21429ebf697SLuca Weiss dev_err(&pdev->dev, "Couldn't create FF dev: %d\n", err); 2153e5b0851SSebastian Reichel return err; 2163e5b0851SSebastian Reichel } 2173e5b0851SSebastian Reichel 2183e5b0851SSebastian Reichel err = input_register_device(vibrator->input); 2193e5b0851SSebastian Reichel if (err) { 22029ebf697SLuca Weiss dev_err(&pdev->dev, "Couldn't register input dev: %d\n", err); 2213e5b0851SSebastian Reichel return err; 2223e5b0851SSebastian Reichel } 2233e5b0851SSebastian Reichel 2243e5b0851SSebastian Reichel platform_set_drvdata(pdev, vibrator); 2253e5b0851SSebastian Reichel 2263e5b0851SSebastian Reichel return 0; 2273e5b0851SSebastian Reichel } 2283e5b0851SSebastian Reichel 229e4b4592fSJonathan Cameron static int pwm_vibrator_suspend(struct device *dev) 2303e5b0851SSebastian Reichel { 2313e5b0851SSebastian Reichel struct pwm_vibrator *vibrator = dev_get_drvdata(dev); 2323e5b0851SSebastian Reichel 2333e5b0851SSebastian Reichel cancel_work_sync(&vibrator->play_work); 2343e5b0851SSebastian Reichel if (vibrator->level) 2353e5b0851SSebastian Reichel pwm_vibrator_stop(vibrator); 2363e5b0851SSebastian Reichel 2373e5b0851SSebastian Reichel return 0; 2383e5b0851SSebastian Reichel } 2393e5b0851SSebastian Reichel 240e4b4592fSJonathan Cameron static int pwm_vibrator_resume(struct device *dev) 2413e5b0851SSebastian Reichel { 2423e5b0851SSebastian Reichel struct pwm_vibrator *vibrator = dev_get_drvdata(dev); 2433e5b0851SSebastian Reichel 2443e5b0851SSebastian Reichel if (vibrator->level) 2453e5b0851SSebastian Reichel pwm_vibrator_start(vibrator); 2463e5b0851SSebastian Reichel 2473e5b0851SSebastian Reichel return 0; 2483e5b0851SSebastian Reichel } 2493e5b0851SSebastian Reichel 250e4b4592fSJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(pwm_vibrator_pm_ops, 2513e5b0851SSebastian Reichel pwm_vibrator_suspend, pwm_vibrator_resume); 2523e5b0851SSebastian Reichel 2533e5b0851SSebastian Reichel #ifdef CONFIG_OF 2543e5b0851SSebastian Reichel static const struct of_device_id pwm_vibra_dt_match_table[] = { 2553e5b0851SSebastian Reichel { .compatible = "pwm-vibrator" }, 2563e5b0851SSebastian Reichel {}, 2573e5b0851SSebastian Reichel }; 2583e5b0851SSebastian Reichel MODULE_DEVICE_TABLE(of, pwm_vibra_dt_match_table); 2593e5b0851SSebastian Reichel #endif 2603e5b0851SSebastian Reichel 2613e5b0851SSebastian Reichel static struct platform_driver pwm_vibrator_driver = { 2623e5b0851SSebastian Reichel .probe = pwm_vibrator_probe, 2633e5b0851SSebastian Reichel .driver = { 2643e5b0851SSebastian Reichel .name = "pwm-vibrator", 265e4b4592fSJonathan Cameron .pm = pm_sleep_ptr(&pwm_vibrator_pm_ops), 2663e5b0851SSebastian Reichel .of_match_table = of_match_ptr(pwm_vibra_dt_match_table), 2673e5b0851SSebastian Reichel }, 2683e5b0851SSebastian Reichel }; 2693e5b0851SSebastian Reichel module_platform_driver(pwm_vibrator_driver); 2703e5b0851SSebastian Reichel 2713e5b0851SSebastian Reichel MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); 2723e5b0851SSebastian Reichel MODULE_DESCRIPTION("PWM vibrator driver"); 2733e5b0851SSebastian Reichel MODULE_LICENSE("GPL"); 2743e5b0851SSebastian Reichel MODULE_ALIAS("platform:pwm-vibrator"); 275