18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PWM vibrator driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Collabora Ltd. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Based on previous work from: 88c2ecf20Sopenharmony_ci * Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Based on PWM beeper driver: 118c2ecf20Sopenharmony_ci * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/input.h> 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/of_device.h> 188c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 198c2ecf20Sopenharmony_ci#include <linux/property.h> 208c2ecf20Sopenharmony_ci#include <linux/pwm.h> 218c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct pwm_vibrator { 258c2ecf20Sopenharmony_ci struct input_dev *input; 268c2ecf20Sopenharmony_ci struct pwm_device *pwm; 278c2ecf20Sopenharmony_ci struct pwm_device *pwm_dir; 288c2ecf20Sopenharmony_ci struct regulator *vcc; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci struct work_struct play_work; 318c2ecf20Sopenharmony_ci u16 level; 328c2ecf20Sopenharmony_ci u32 direction_duty_cycle; 338c2ecf20Sopenharmony_ci bool vcc_on; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int pwm_vibrator_start(struct pwm_vibrator *vibrator) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct device *pdev = vibrator->input->dev.parent; 398c2ecf20Sopenharmony_ci struct pwm_state state; 408c2ecf20Sopenharmony_ci int err; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (!vibrator->vcc_on) { 438c2ecf20Sopenharmony_ci err = regulator_enable(vibrator->vcc); 448c2ecf20Sopenharmony_ci if (err) { 458c2ecf20Sopenharmony_ci dev_err(pdev, "failed to enable regulator: %d", err); 468c2ecf20Sopenharmony_ci return err; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci vibrator->vcc_on = true; 498c2ecf20Sopenharmony_ci } 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci pwm_get_state(vibrator->pwm, &state); 528c2ecf20Sopenharmony_ci pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff); 538c2ecf20Sopenharmony_ci state.enabled = true; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci err = pwm_apply_state(vibrator->pwm, &state); 568c2ecf20Sopenharmony_ci if (err) { 578c2ecf20Sopenharmony_ci dev_err(pdev, "failed to apply pwm state: %d", err); 588c2ecf20Sopenharmony_ci return err; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (vibrator->pwm_dir) { 628c2ecf20Sopenharmony_ci pwm_get_state(vibrator->pwm_dir, &state); 638c2ecf20Sopenharmony_ci state.duty_cycle = vibrator->direction_duty_cycle; 648c2ecf20Sopenharmony_ci state.enabled = true; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci err = pwm_apply_state(vibrator->pwm_dir, &state); 678c2ecf20Sopenharmony_ci if (err) { 688c2ecf20Sopenharmony_ci dev_err(pdev, "failed to apply dir-pwm state: %d", err); 698c2ecf20Sopenharmony_ci pwm_disable(vibrator->pwm); 708c2ecf20Sopenharmony_ci return err; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci return 0; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic void pwm_vibrator_stop(struct pwm_vibrator *vibrator) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci if (vibrator->pwm_dir) 808c2ecf20Sopenharmony_ci pwm_disable(vibrator->pwm_dir); 818c2ecf20Sopenharmony_ci pwm_disable(vibrator->pwm); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (vibrator->vcc_on) { 848c2ecf20Sopenharmony_ci regulator_disable(vibrator->vcc); 858c2ecf20Sopenharmony_ci vibrator->vcc_on = false; 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic void pwm_vibrator_play_work(struct work_struct *work) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct pwm_vibrator *vibrator = container_of(work, 928c2ecf20Sopenharmony_ci struct pwm_vibrator, play_work); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (vibrator->level) 958c2ecf20Sopenharmony_ci pwm_vibrator_start(vibrator); 968c2ecf20Sopenharmony_ci else 978c2ecf20Sopenharmony_ci pwm_vibrator_stop(vibrator); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic int pwm_vibrator_play_effect(struct input_dev *dev, void *data, 1018c2ecf20Sopenharmony_ci struct ff_effect *effect) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci struct pwm_vibrator *vibrator = input_get_drvdata(dev); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci vibrator->level = effect->u.rumble.strong_magnitude; 1068c2ecf20Sopenharmony_ci if (!vibrator->level) 1078c2ecf20Sopenharmony_ci vibrator->level = effect->u.rumble.weak_magnitude; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci schedule_work(&vibrator->play_work); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return 0; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic void pwm_vibrator_close(struct input_dev *input) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci struct pwm_vibrator *vibrator = input_get_drvdata(input); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci cancel_work_sync(&vibrator->play_work); 1198c2ecf20Sopenharmony_ci pwm_vibrator_stop(vibrator); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic int pwm_vibrator_probe(struct platform_device *pdev) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct pwm_vibrator *vibrator; 1258c2ecf20Sopenharmony_ci struct pwm_state state; 1268c2ecf20Sopenharmony_ci int err; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL); 1298c2ecf20Sopenharmony_ci if (!vibrator) 1308c2ecf20Sopenharmony_ci return -ENOMEM; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci vibrator->input = devm_input_allocate_device(&pdev->dev); 1338c2ecf20Sopenharmony_ci if (!vibrator->input) 1348c2ecf20Sopenharmony_ci return -ENOMEM; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); 1378c2ecf20Sopenharmony_ci err = PTR_ERR_OR_ZERO(vibrator->vcc); 1388c2ecf20Sopenharmony_ci if (err) { 1398c2ecf20Sopenharmony_ci if (err != -EPROBE_DEFER) 1408c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to request regulator: %d", 1418c2ecf20Sopenharmony_ci err); 1428c2ecf20Sopenharmony_ci return err; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci vibrator->pwm = devm_pwm_get(&pdev->dev, "enable"); 1468c2ecf20Sopenharmony_ci err = PTR_ERR_OR_ZERO(vibrator->pwm); 1478c2ecf20Sopenharmony_ci if (err) { 1488c2ecf20Sopenharmony_ci if (err != -EPROBE_DEFER) 1498c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to request main pwm: %d", 1508c2ecf20Sopenharmony_ci err); 1518c2ecf20Sopenharmony_ci return err; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* Sync up PWM state and ensure it is off. */ 1578c2ecf20Sopenharmony_ci pwm_init_state(vibrator->pwm, &state); 1588c2ecf20Sopenharmony_ci state.enabled = false; 1598c2ecf20Sopenharmony_ci err = pwm_apply_state(vibrator->pwm, &state); 1608c2ecf20Sopenharmony_ci if (err) { 1618c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to apply initial PWM state: %d", 1628c2ecf20Sopenharmony_ci err); 1638c2ecf20Sopenharmony_ci return err; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci vibrator->pwm_dir = devm_pwm_get(&pdev->dev, "direction"); 1678c2ecf20Sopenharmony_ci err = PTR_ERR_OR_ZERO(vibrator->pwm_dir); 1688c2ecf20Sopenharmony_ci switch (err) { 1698c2ecf20Sopenharmony_ci case 0: 1708c2ecf20Sopenharmony_ci /* Sync up PWM state and ensure it is off. */ 1718c2ecf20Sopenharmony_ci pwm_init_state(vibrator->pwm_dir, &state); 1728c2ecf20Sopenharmony_ci state.enabled = false; 1738c2ecf20Sopenharmony_ci err = pwm_apply_state(vibrator->pwm_dir, &state); 1748c2ecf20Sopenharmony_ci if (err) { 1758c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to apply initial PWM state: %d", 1768c2ecf20Sopenharmony_ci err); 1778c2ecf20Sopenharmony_ci return err; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci vibrator->direction_duty_cycle = 1818c2ecf20Sopenharmony_ci pwm_get_period(vibrator->pwm_dir) / 2; 1828c2ecf20Sopenharmony_ci device_property_read_u32(&pdev->dev, "direction-duty-cycle-ns", 1838c2ecf20Sopenharmony_ci &vibrator->direction_duty_cycle); 1848c2ecf20Sopenharmony_ci break; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci case -ENODATA: 1878c2ecf20Sopenharmony_ci /* Direction PWM is optional */ 1888c2ecf20Sopenharmony_ci vibrator->pwm_dir = NULL; 1898c2ecf20Sopenharmony_ci break; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci default: 1928c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to request direction pwm: %d", err); 1938c2ecf20Sopenharmony_ci fallthrough; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci case -EPROBE_DEFER: 1968c2ecf20Sopenharmony_ci return err; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci vibrator->input->name = "pwm-vibrator"; 2008c2ecf20Sopenharmony_ci vibrator->input->id.bustype = BUS_HOST; 2018c2ecf20Sopenharmony_ci vibrator->input->dev.parent = &pdev->dev; 2028c2ecf20Sopenharmony_ci vibrator->input->close = pwm_vibrator_close; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci input_set_drvdata(vibrator->input, vibrator); 2058c2ecf20Sopenharmony_ci input_set_capability(vibrator->input, EV_FF, FF_RUMBLE); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci err = input_ff_create_memless(vibrator->input, NULL, 2088c2ecf20Sopenharmony_ci pwm_vibrator_play_effect); 2098c2ecf20Sopenharmony_ci if (err) { 2108c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Couldn't create FF dev: %d", err); 2118c2ecf20Sopenharmony_ci return err; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci err = input_register_device(vibrator->input); 2158c2ecf20Sopenharmony_ci if (err) { 2168c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Couldn't register input dev: %d", err); 2178c2ecf20Sopenharmony_ci return err; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, vibrator); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci return 0; 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic int __maybe_unused pwm_vibrator_suspend(struct device *dev) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct pwm_vibrator *vibrator = dev_get_drvdata(dev); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci cancel_work_sync(&vibrator->play_work); 2308c2ecf20Sopenharmony_ci if (vibrator->level) 2318c2ecf20Sopenharmony_ci pwm_vibrator_stop(vibrator); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return 0; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic int __maybe_unused pwm_vibrator_resume(struct device *dev) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci struct pwm_vibrator *vibrator = dev_get_drvdata(dev); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (vibrator->level) 2418c2ecf20Sopenharmony_ci pwm_vibrator_start(vibrator); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(pwm_vibrator_pm_ops, 2478c2ecf20Sopenharmony_ci pwm_vibrator_suspend, pwm_vibrator_resume); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 2508c2ecf20Sopenharmony_cistatic const struct of_device_id pwm_vibra_dt_match_table[] = { 2518c2ecf20Sopenharmony_ci { .compatible = "pwm-vibrator" }, 2528c2ecf20Sopenharmony_ci {}, 2538c2ecf20Sopenharmony_ci}; 2548c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pwm_vibra_dt_match_table); 2558c2ecf20Sopenharmony_ci#endif 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic struct platform_driver pwm_vibrator_driver = { 2588c2ecf20Sopenharmony_ci .probe = pwm_vibrator_probe, 2598c2ecf20Sopenharmony_ci .driver = { 2608c2ecf20Sopenharmony_ci .name = "pwm-vibrator", 2618c2ecf20Sopenharmony_ci .pm = &pwm_vibrator_pm_ops, 2628c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(pwm_vibra_dt_match_table), 2638c2ecf20Sopenharmony_ci }, 2648c2ecf20Sopenharmony_ci}; 2658c2ecf20Sopenharmony_cimodule_platform_driver(pwm_vibrator_driver); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciMODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); 2688c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PWM vibrator driver"); 2698c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2708c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:pwm-vibrator"); 271