• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Qualcomm MSM vibrator driver
4  *
5  * Copyright (c) 2018 Brian Masney <masneyb@onstation.org>
6  *
7  * Based on qcom,pwm-vibrator.c from:
8  * Copyright (c) 2018 Jonathan Marek <jonathan@marek.ca>
9  *
10  * Based on msm_pwm_vibrator.c from downstream Android sources:
11  * Copyright (C) 2009-2014 LGE, Inc.
12  */
13 
14 #include <linux/clk.h>
15 #include <linux/err.h>
16 #include <linux/gpio/consumer.h>
17 #include <linux/input.h>
18 #include <linux/io.h>
19 #include <linux/module.h>
20 #include <linux/of.h>
21 #include <linux/platform_device.h>
22 #include <linux/regulator/consumer.h>
23 
24 #define REG_CMD_RCGR           0x00
25 #define REG_CFG_RCGR           0x04
26 #define REG_M                  0x08
27 #define REG_N                  0x0C
28 #define REG_D                  0x10
29 #define REG_CBCR               0x24
30 #define MMSS_CC_M_DEFAULT      1
31 
32 struct msm_vibrator {
33 	struct input_dev *input;
34 	struct mutex mutex;
35 	struct work_struct worker;
36 	void __iomem *base;
37 	struct regulator *vcc;
38 	struct clk *clk;
39 	struct gpio_desc *enable_gpio;
40 	u16 magnitude;
41 	bool enabled;
42 };
43 
msm_vibrator_write(struct msm_vibrator * vibrator,int offset,u32 value)44 static void msm_vibrator_write(struct msm_vibrator *vibrator, int offset,
45 			       u32 value)
46 {
47 	writel(value, vibrator->base + offset);
48 }
49 
msm_vibrator_start(struct msm_vibrator * vibrator)50 static int msm_vibrator_start(struct msm_vibrator *vibrator)
51 {
52 	int d_reg_val, ret = 0;
53 
54 	mutex_lock(&vibrator->mutex);
55 
56 	if (!vibrator->enabled) {
57 		ret = clk_set_rate(vibrator->clk, 24000);
58 		if (ret) {
59 			dev_err(&vibrator->input->dev,
60 				"Failed to set clock rate: %d\n", ret);
61 			goto unlock;
62 		}
63 
64 		ret = clk_prepare_enable(vibrator->clk);
65 		if (ret) {
66 			dev_err(&vibrator->input->dev,
67 				"Failed to enable clock: %d\n", ret);
68 			goto unlock;
69 		}
70 
71 		ret = regulator_enable(vibrator->vcc);
72 		if (ret) {
73 			dev_err(&vibrator->input->dev,
74 				"Failed to enable regulator: %d\n", ret);
75 			clk_disable(vibrator->clk);
76 			goto unlock;
77 		}
78 
79 		gpiod_set_value_cansleep(vibrator->enable_gpio, 1);
80 
81 		vibrator->enabled = true;
82 	}
83 
84 	d_reg_val = 127 - ((126 * vibrator->magnitude) / 0xffff);
85 	msm_vibrator_write(vibrator, REG_CFG_RCGR,
86 			   (2 << 12) | /* dual edge mode */
87 			   (0 << 8) |  /* cxo */
88 			   (7 << 0));
89 	msm_vibrator_write(vibrator, REG_M, 1);
90 	msm_vibrator_write(vibrator, REG_N, 128);
91 	msm_vibrator_write(vibrator, REG_D, d_reg_val);
92 	msm_vibrator_write(vibrator, REG_CMD_RCGR, 1);
93 	msm_vibrator_write(vibrator, REG_CBCR, 1);
94 
95 unlock:
96 	mutex_unlock(&vibrator->mutex);
97 
98 	return ret;
99 }
100 
msm_vibrator_stop(struct msm_vibrator * vibrator)101 static void msm_vibrator_stop(struct msm_vibrator *vibrator)
102 {
103 	mutex_lock(&vibrator->mutex);
104 
105 	if (vibrator->enabled) {
106 		gpiod_set_value_cansleep(vibrator->enable_gpio, 0);
107 		regulator_disable(vibrator->vcc);
108 		clk_disable(vibrator->clk);
109 		vibrator->enabled = false;
110 	}
111 
112 	mutex_unlock(&vibrator->mutex);
113 }
114 
msm_vibrator_worker(struct work_struct * work)115 static void msm_vibrator_worker(struct work_struct *work)
116 {
117 	struct msm_vibrator *vibrator = container_of(work,
118 						     struct msm_vibrator,
119 						     worker);
120 
121 	if (vibrator->magnitude)
122 		msm_vibrator_start(vibrator);
123 	else
124 		msm_vibrator_stop(vibrator);
125 }
126 
msm_vibrator_play_effect(struct input_dev * dev,void * data,struct ff_effect * effect)127 static int msm_vibrator_play_effect(struct input_dev *dev, void *data,
128 				    struct ff_effect *effect)
129 {
130 	struct msm_vibrator *vibrator = input_get_drvdata(dev);
131 
132 	mutex_lock(&vibrator->mutex);
133 
134 	if (effect->u.rumble.strong_magnitude > 0)
135 		vibrator->magnitude = effect->u.rumble.strong_magnitude;
136 	else
137 		vibrator->magnitude = effect->u.rumble.weak_magnitude;
138 
139 	mutex_unlock(&vibrator->mutex);
140 
141 	schedule_work(&vibrator->worker);
142 
143 	return 0;
144 }
145 
msm_vibrator_close(struct input_dev * input)146 static void msm_vibrator_close(struct input_dev *input)
147 {
148 	struct msm_vibrator *vibrator = input_get_drvdata(input);
149 
150 	cancel_work_sync(&vibrator->worker);
151 	msm_vibrator_stop(vibrator);
152 }
153 
msm_vibrator_probe(struct platform_device * pdev)154 static int msm_vibrator_probe(struct platform_device *pdev)
155 {
156 	struct msm_vibrator *vibrator;
157 	struct resource *res;
158 	int ret;
159 
160 	vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
161 	if (!vibrator)
162 		return -ENOMEM;
163 
164 	vibrator->input = devm_input_allocate_device(&pdev->dev);
165 	if (!vibrator->input)
166 		return -ENOMEM;
167 
168 	vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
169 	if (IS_ERR(vibrator->vcc)) {
170 		if (PTR_ERR(vibrator->vcc) != -EPROBE_DEFER)
171 			dev_err(&pdev->dev, "Failed to get regulator: %ld\n",
172 				PTR_ERR(vibrator->vcc));
173 		return PTR_ERR(vibrator->vcc);
174 	}
175 
176 	vibrator->enable_gpio = devm_gpiod_get(&pdev->dev, "enable",
177 					       GPIOD_OUT_LOW);
178 	if (IS_ERR(vibrator->enable_gpio)) {
179 		if (PTR_ERR(vibrator->enable_gpio) != -EPROBE_DEFER)
180 			dev_err(&pdev->dev, "Failed to get enable gpio: %ld\n",
181 				PTR_ERR(vibrator->enable_gpio));
182 		return PTR_ERR(vibrator->enable_gpio);
183 	}
184 
185 	vibrator->clk = devm_clk_get(&pdev->dev, "pwm");
186 	if (IS_ERR(vibrator->clk)) {
187 		if (PTR_ERR(vibrator->clk) != -EPROBE_DEFER)
188 			dev_err(&pdev->dev, "Failed to lookup pwm clock: %ld\n",
189 				PTR_ERR(vibrator->clk));
190 		return PTR_ERR(vibrator->clk);
191 	}
192 
193 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
194 	if (!res) {
195 		dev_err(&pdev->dev, "Failed to get platform resource\n");
196 		return -ENODEV;
197 	}
198 
199 	vibrator->base = devm_ioremap(&pdev->dev, res->start,
200 				     resource_size(res));
201 	if (!vibrator->base) {
202 		dev_err(&pdev->dev, "Failed to iomap resource.\n");
203 		return -ENOMEM;
204 	}
205 
206 	vibrator->enabled = false;
207 	mutex_init(&vibrator->mutex);
208 	INIT_WORK(&vibrator->worker, msm_vibrator_worker);
209 
210 	vibrator->input->name = "msm-vibrator";
211 	vibrator->input->id.bustype = BUS_HOST;
212 	vibrator->input->close = msm_vibrator_close;
213 
214 	input_set_drvdata(vibrator->input, vibrator);
215 	input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
216 
217 	ret = input_ff_create_memless(vibrator->input, NULL,
218 				      msm_vibrator_play_effect);
219 	if (ret) {
220 		dev_err(&pdev->dev, "Failed to create ff memless: %d", ret);
221 		return ret;
222 	}
223 
224 	ret = input_register_device(vibrator->input);
225 	if (ret) {
226 		dev_err(&pdev->dev, "Failed to register input device: %d", ret);
227 		return ret;
228 	}
229 
230 	platform_set_drvdata(pdev, vibrator);
231 
232 	return 0;
233 }
234 
msm_vibrator_suspend(struct device * dev)235 static int __maybe_unused msm_vibrator_suspend(struct device *dev)
236 {
237 	struct platform_device *pdev = to_platform_device(dev);
238 	struct msm_vibrator *vibrator = platform_get_drvdata(pdev);
239 
240 	cancel_work_sync(&vibrator->worker);
241 
242 	if (vibrator->enabled)
243 		msm_vibrator_stop(vibrator);
244 
245 	return 0;
246 }
247 
msm_vibrator_resume(struct device * dev)248 static int __maybe_unused msm_vibrator_resume(struct device *dev)
249 {
250 	struct platform_device *pdev = to_platform_device(dev);
251 	struct msm_vibrator *vibrator = platform_get_drvdata(pdev);
252 
253 	if (vibrator->enabled)
254 		msm_vibrator_start(vibrator);
255 
256 	return 0;
257 }
258 
259 static SIMPLE_DEV_PM_OPS(msm_vibrator_pm_ops, msm_vibrator_suspend,
260 			 msm_vibrator_resume);
261 
262 static const struct of_device_id msm_vibrator_of_match[] = {
263 	{ .compatible = "qcom,msm8226-vibrator" },
264 	{ .compatible = "qcom,msm8974-vibrator" },
265 	{},
266 };
267 MODULE_DEVICE_TABLE(of, msm_vibrator_of_match);
268 
269 static struct platform_driver msm_vibrator_driver = {
270 	.probe	= msm_vibrator_probe,
271 	.driver	= {
272 		.name = "msm-vibrator",
273 		.pm = &msm_vibrator_pm_ops,
274 		.of_match_table = of_match_ptr(msm_vibrator_of_match),
275 	},
276 };
277 module_platform_driver(msm_vibrator_driver);
278 
279 MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>");
280 MODULE_DESCRIPTION("Qualcomm MSM vibrator driver");
281 MODULE_LICENSE("GPL");
282