162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PWM vibrator driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 Collabora Ltd. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Based on previous work from: 862306a36Sopenharmony_ci * Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com> 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Based on PWM beeper driver: 1162306a36Sopenharmony_ci * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 1562306a36Sopenharmony_ci#include <linux/input.h> 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <linux/module.h> 1862306a36Sopenharmony_ci#include <linux/of.h> 1962306a36Sopenharmony_ci#include <linux/platform_device.h> 2062306a36Sopenharmony_ci#include <linux/property.h> 2162306a36Sopenharmony_ci#include <linux/pwm.h> 2262306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct pwm_vibrator { 2662306a36Sopenharmony_ci struct input_dev *input; 2762306a36Sopenharmony_ci struct gpio_desc *enable_gpio; 2862306a36Sopenharmony_ci struct pwm_device *pwm; 2962306a36Sopenharmony_ci struct pwm_device *pwm_dir; 3062306a36Sopenharmony_ci struct regulator *vcc; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci struct work_struct play_work; 3362306a36Sopenharmony_ci u16 level; 3462306a36Sopenharmony_ci u32 direction_duty_cycle; 3562306a36Sopenharmony_ci bool vcc_on; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic int pwm_vibrator_start(struct pwm_vibrator *vibrator) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci struct device *pdev = vibrator->input->dev.parent; 4162306a36Sopenharmony_ci struct pwm_state state; 4262306a36Sopenharmony_ci int err; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (!vibrator->vcc_on) { 4562306a36Sopenharmony_ci err = regulator_enable(vibrator->vcc); 4662306a36Sopenharmony_ci if (err) { 4762306a36Sopenharmony_ci dev_err(pdev, "failed to enable regulator: %d\n", err); 4862306a36Sopenharmony_ci return err; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci vibrator->vcc_on = true; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci gpiod_set_value_cansleep(vibrator->enable_gpio, 1); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci pwm_get_state(vibrator->pwm, &state); 5662306a36Sopenharmony_ci pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff); 5762306a36Sopenharmony_ci state.enabled = true; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci err = pwm_apply_state(vibrator->pwm, &state); 6062306a36Sopenharmony_ci if (err) { 6162306a36Sopenharmony_ci dev_err(pdev, "failed to apply pwm state: %d\n", err); 6262306a36Sopenharmony_ci return err; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (vibrator->pwm_dir) { 6662306a36Sopenharmony_ci pwm_get_state(vibrator->pwm_dir, &state); 6762306a36Sopenharmony_ci state.duty_cycle = vibrator->direction_duty_cycle; 6862306a36Sopenharmony_ci state.enabled = true; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci err = pwm_apply_state(vibrator->pwm_dir, &state); 7162306a36Sopenharmony_ci if (err) { 7262306a36Sopenharmony_ci dev_err(pdev, "failed to apply dir-pwm state: %d\n", err); 7362306a36Sopenharmony_ci pwm_disable(vibrator->pwm); 7462306a36Sopenharmony_ci return err; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return 0; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic void pwm_vibrator_stop(struct pwm_vibrator *vibrator) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci if (vibrator->pwm_dir) 8462306a36Sopenharmony_ci pwm_disable(vibrator->pwm_dir); 8562306a36Sopenharmony_ci pwm_disable(vibrator->pwm); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci gpiod_set_value_cansleep(vibrator->enable_gpio, 0); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (vibrator->vcc_on) { 9062306a36Sopenharmony_ci regulator_disable(vibrator->vcc); 9162306a36Sopenharmony_ci vibrator->vcc_on = false; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic void pwm_vibrator_play_work(struct work_struct *work) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct pwm_vibrator *vibrator = container_of(work, 9862306a36Sopenharmony_ci struct pwm_vibrator, play_work); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci if (vibrator->level) 10162306a36Sopenharmony_ci pwm_vibrator_start(vibrator); 10262306a36Sopenharmony_ci else 10362306a36Sopenharmony_ci pwm_vibrator_stop(vibrator); 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic int pwm_vibrator_play_effect(struct input_dev *dev, void *data, 10762306a36Sopenharmony_ci struct ff_effect *effect) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct pwm_vibrator *vibrator = input_get_drvdata(dev); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci vibrator->level = effect->u.rumble.strong_magnitude; 11262306a36Sopenharmony_ci if (!vibrator->level) 11362306a36Sopenharmony_ci vibrator->level = effect->u.rumble.weak_magnitude; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci schedule_work(&vibrator->play_work); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci return 0; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic void pwm_vibrator_close(struct input_dev *input) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci struct pwm_vibrator *vibrator = input_get_drvdata(input); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci cancel_work_sync(&vibrator->play_work); 12562306a36Sopenharmony_ci pwm_vibrator_stop(vibrator); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic int pwm_vibrator_probe(struct platform_device *pdev) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci struct pwm_vibrator *vibrator; 13162306a36Sopenharmony_ci struct pwm_state state; 13262306a36Sopenharmony_ci int err; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL); 13562306a36Sopenharmony_ci if (!vibrator) 13662306a36Sopenharmony_ci return -ENOMEM; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci vibrator->input = devm_input_allocate_device(&pdev->dev); 13962306a36Sopenharmony_ci if (!vibrator->input) 14062306a36Sopenharmony_ci return -ENOMEM; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); 14362306a36Sopenharmony_ci if (IS_ERR(vibrator->vcc)) 14462306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->vcc), 14562306a36Sopenharmony_ci "Failed to request regulator\n"); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci vibrator->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", 14862306a36Sopenharmony_ci GPIOD_OUT_LOW); 14962306a36Sopenharmony_ci if (IS_ERR(vibrator->enable_gpio)) 15062306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->enable_gpio), 15162306a36Sopenharmony_ci "Failed to request enable gpio\n"); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci vibrator->pwm = devm_pwm_get(&pdev->dev, "enable"); 15462306a36Sopenharmony_ci if (IS_ERR(vibrator->pwm)) 15562306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(vibrator->pwm), 15662306a36Sopenharmony_ci "Failed to request main pwm\n"); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* Sync up PWM state and ensure it is off. */ 16162306a36Sopenharmony_ci pwm_init_state(vibrator->pwm, &state); 16262306a36Sopenharmony_ci state.enabled = false; 16362306a36Sopenharmony_ci err = pwm_apply_state(vibrator->pwm, &state); 16462306a36Sopenharmony_ci if (err) { 16562306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n", 16662306a36Sopenharmony_ci err); 16762306a36Sopenharmony_ci return err; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci vibrator->pwm_dir = devm_pwm_get(&pdev->dev, "direction"); 17162306a36Sopenharmony_ci err = PTR_ERR_OR_ZERO(vibrator->pwm_dir); 17262306a36Sopenharmony_ci switch (err) { 17362306a36Sopenharmony_ci case 0: 17462306a36Sopenharmony_ci /* Sync up PWM state and ensure it is off. */ 17562306a36Sopenharmony_ci pwm_init_state(vibrator->pwm_dir, &state); 17662306a36Sopenharmony_ci state.enabled = false; 17762306a36Sopenharmony_ci err = pwm_apply_state(vibrator->pwm_dir, &state); 17862306a36Sopenharmony_ci if (err) { 17962306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n", 18062306a36Sopenharmony_ci err); 18162306a36Sopenharmony_ci return err; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci vibrator->direction_duty_cycle = 18562306a36Sopenharmony_ci pwm_get_period(vibrator->pwm_dir) / 2; 18662306a36Sopenharmony_ci device_property_read_u32(&pdev->dev, "direction-duty-cycle-ns", 18762306a36Sopenharmony_ci &vibrator->direction_duty_cycle); 18862306a36Sopenharmony_ci break; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci case -ENODATA: 19162306a36Sopenharmony_ci /* Direction PWM is optional */ 19262306a36Sopenharmony_ci vibrator->pwm_dir = NULL; 19362306a36Sopenharmony_ci break; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci default: 19662306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to request direction pwm: %d\n", err); 19762306a36Sopenharmony_ci fallthrough; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci case -EPROBE_DEFER: 20062306a36Sopenharmony_ci return err; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci vibrator->input->name = "pwm-vibrator"; 20462306a36Sopenharmony_ci vibrator->input->id.bustype = BUS_HOST; 20562306a36Sopenharmony_ci vibrator->input->dev.parent = &pdev->dev; 20662306a36Sopenharmony_ci vibrator->input->close = pwm_vibrator_close; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci input_set_drvdata(vibrator->input, vibrator); 20962306a36Sopenharmony_ci input_set_capability(vibrator->input, EV_FF, FF_RUMBLE); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci err = input_ff_create_memless(vibrator->input, NULL, 21262306a36Sopenharmony_ci pwm_vibrator_play_effect); 21362306a36Sopenharmony_ci if (err) { 21462306a36Sopenharmony_ci dev_err(&pdev->dev, "Couldn't create FF dev: %d\n", err); 21562306a36Sopenharmony_ci return err; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci err = input_register_device(vibrator->input); 21962306a36Sopenharmony_ci if (err) { 22062306a36Sopenharmony_ci dev_err(&pdev->dev, "Couldn't register input dev: %d\n", err); 22162306a36Sopenharmony_ci return err; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci platform_set_drvdata(pdev, vibrator); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return 0; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic int pwm_vibrator_suspend(struct device *dev) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci struct pwm_vibrator *vibrator = dev_get_drvdata(dev); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci cancel_work_sync(&vibrator->play_work); 23462306a36Sopenharmony_ci if (vibrator->level) 23562306a36Sopenharmony_ci pwm_vibrator_stop(vibrator); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci return 0; 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic int pwm_vibrator_resume(struct device *dev) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct pwm_vibrator *vibrator = dev_get_drvdata(dev); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (vibrator->level) 24562306a36Sopenharmony_ci pwm_vibrator_start(vibrator); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci return 0; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(pwm_vibrator_pm_ops, 25162306a36Sopenharmony_ci pwm_vibrator_suspend, pwm_vibrator_resume); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci#ifdef CONFIG_OF 25462306a36Sopenharmony_cistatic const struct of_device_id pwm_vibra_dt_match_table[] = { 25562306a36Sopenharmony_ci { .compatible = "pwm-vibrator" }, 25662306a36Sopenharmony_ci {}, 25762306a36Sopenharmony_ci}; 25862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, pwm_vibra_dt_match_table); 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic struct platform_driver pwm_vibrator_driver = { 26262306a36Sopenharmony_ci .probe = pwm_vibrator_probe, 26362306a36Sopenharmony_ci .driver = { 26462306a36Sopenharmony_ci .name = "pwm-vibrator", 26562306a36Sopenharmony_ci .pm = pm_sleep_ptr(&pwm_vibrator_pm_ops), 26662306a36Sopenharmony_ci .of_match_table = of_match_ptr(pwm_vibra_dt_match_table), 26762306a36Sopenharmony_ci }, 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_cimodule_platform_driver(pwm_vibrator_driver); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciMODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); 27262306a36Sopenharmony_ciMODULE_DESCRIPTION("PWM vibrator driver"); 27362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 27462306a36Sopenharmony_ciMODULE_ALIAS("platform:pwm-vibrator"); 275