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