1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. |
3 | */ |
4 | |
5 | #include <linux/errno.h> |
6 | #include <linux/input.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> |
9 | #include <linux/of.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/regmap.h> |
12 | #include <linux/slab.h> |
13 | |
14 | #define VIB_MAX_LEVEL_mV (3100) |
15 | #define VIB_MIN_LEVEL_mV (1200) |
16 | #define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) |
17 | |
18 | #define MAX_FF_SPEED 0xff |
19 | |
20 | struct pm8xxx_regs { |
21 | unsigned int enable_addr; |
22 | unsigned int enable_mask; |
23 | |
24 | unsigned int drv_addr; |
25 | unsigned int drv_mask; |
26 | unsigned int drv_shift; |
27 | unsigned int drv_en_manual_mask; |
28 | }; |
29 | |
30 | static const struct pm8xxx_regs pm8058_regs = { |
31 | .drv_addr = 0x4A, |
32 | .drv_mask = 0xf8, |
33 | .drv_shift = 3, |
34 | .drv_en_manual_mask = 0xfc, |
35 | }; |
36 | |
37 | static struct pm8xxx_regs pm8916_regs = { |
38 | .enable_addr = 0xc046, |
39 | .enable_mask = BIT(7), |
40 | .drv_addr = 0xc041, |
41 | .drv_mask = 0x1F, |
42 | .drv_shift = 0, |
43 | .drv_en_manual_mask = 0, |
44 | }; |
45 | |
46 | /** |
47 | * struct pm8xxx_vib - structure to hold vibrator data |
48 | * @vib_input_dev: input device supporting force feedback |
49 | * @work: work structure to set the vibration parameters |
50 | * @regmap: regmap for register read/write |
51 | * @regs: registers' info |
52 | * @speed: speed of vibration set from userland |
53 | * @active: state of vibrator |
54 | * @level: level of vibration to set in the chip |
55 | * @reg_vib_drv: regs->drv_addr register value |
56 | */ |
57 | struct pm8xxx_vib { |
58 | struct input_dev *vib_input_dev; |
59 | struct work_struct work; |
60 | struct regmap *regmap; |
61 | const struct pm8xxx_regs *regs; |
62 | int speed; |
63 | int level; |
64 | bool active; |
65 | u8 reg_vib_drv; |
66 | }; |
67 | |
68 | /** |
69 | * pm8xxx_vib_set - handler to start/stop vibration |
70 | * @vib: pointer to vibrator structure |
71 | * @on: state to set |
72 | */ |
73 | static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) |
74 | { |
75 | int rc; |
76 | unsigned int val = vib->reg_vib_drv; |
77 | const struct pm8xxx_regs *regs = vib->regs; |
78 | |
79 | if (on) |
80 | val |= (vib->level << regs->drv_shift) & regs->drv_mask; |
81 | else |
82 | val &= ~regs->drv_mask; |
83 | |
84 | rc = regmap_write(map: vib->regmap, reg: regs->drv_addr, val); |
85 | if (rc < 0) |
86 | return rc; |
87 | |
88 | vib->reg_vib_drv = val; |
89 | |
90 | if (regs->enable_mask) |
91 | rc = regmap_update_bits(map: vib->regmap, reg: regs->enable_addr, |
92 | mask: regs->enable_mask, val: on ? ~0 : 0); |
93 | |
94 | return rc; |
95 | } |
96 | |
97 | /** |
98 | * pm8xxx_work_handler - worker to set vibration level |
99 | * @work: pointer to work_struct |
100 | */ |
101 | static void pm8xxx_work_handler(struct work_struct *work) |
102 | { |
103 | struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); |
104 | const struct pm8xxx_regs *regs = vib->regs; |
105 | int rc; |
106 | unsigned int val; |
107 | |
108 | rc = regmap_read(map: vib->regmap, reg: regs->drv_addr, val: &val); |
109 | if (rc < 0) |
110 | return; |
111 | |
112 | /* |
113 | * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so |
114 | * scale the level to fit into these ranges. |
115 | */ |
116 | if (vib->speed) { |
117 | vib->active = true; |
118 | vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + |
119 | VIB_MIN_LEVEL_mV; |
120 | vib->level /= 100; |
121 | } else { |
122 | vib->active = false; |
123 | vib->level = VIB_MIN_LEVEL_mV / 100; |
124 | } |
125 | |
126 | pm8xxx_vib_set(vib, on: vib->active); |
127 | } |
128 | |
129 | /** |
130 | * pm8xxx_vib_close - callback of input close callback |
131 | * @dev: input device pointer |
132 | * |
133 | * Turns off the vibrator. |
134 | */ |
135 | static void pm8xxx_vib_close(struct input_dev *dev) |
136 | { |
137 | struct pm8xxx_vib *vib = input_get_drvdata(dev); |
138 | |
139 | cancel_work_sync(work: &vib->work); |
140 | if (vib->active) |
141 | pm8xxx_vib_set(vib, on: false); |
142 | } |
143 | |
144 | /** |
145 | * pm8xxx_vib_play_effect - function to handle vib effects. |
146 | * @dev: input device pointer |
147 | * @data: data of effect |
148 | * @effect: effect to play |
149 | * |
150 | * Currently this driver supports only rumble effects. |
151 | */ |
152 | static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data, |
153 | struct ff_effect *effect) |
154 | { |
155 | struct pm8xxx_vib *vib = input_get_drvdata(dev); |
156 | |
157 | vib->speed = effect->u.rumble.strong_magnitude >> 8; |
158 | if (!vib->speed) |
159 | vib->speed = effect->u.rumble.weak_magnitude >> 9; |
160 | |
161 | schedule_work(work: &vib->work); |
162 | |
163 | return 0; |
164 | } |
165 | |
166 | static int pm8xxx_vib_probe(struct platform_device *pdev) |
167 | { |
168 | struct pm8xxx_vib *vib; |
169 | struct input_dev *input_dev; |
170 | int error; |
171 | unsigned int val; |
172 | const struct pm8xxx_regs *regs; |
173 | |
174 | vib = devm_kzalloc(dev: &pdev->dev, size: sizeof(*vib), GFP_KERNEL); |
175 | if (!vib) |
176 | return -ENOMEM; |
177 | |
178 | vib->regmap = dev_get_regmap(dev: pdev->dev.parent, NULL); |
179 | if (!vib->regmap) |
180 | return -ENODEV; |
181 | |
182 | input_dev = devm_input_allocate_device(&pdev->dev); |
183 | if (!input_dev) |
184 | return -ENOMEM; |
185 | |
186 | INIT_WORK(&vib->work, pm8xxx_work_handler); |
187 | vib->vib_input_dev = input_dev; |
188 | |
189 | regs = of_device_get_match_data(dev: &pdev->dev); |
190 | |
191 | /* operate in manual mode */ |
192 | error = regmap_read(map: vib->regmap, reg: regs->drv_addr, val: &val); |
193 | if (error < 0) |
194 | return error; |
195 | |
196 | val &= regs->drv_en_manual_mask; |
197 | error = regmap_write(map: vib->regmap, reg: regs->drv_addr, val); |
198 | if (error < 0) |
199 | return error; |
200 | |
201 | vib->regs = regs; |
202 | vib->reg_vib_drv = val; |
203 | |
204 | input_dev->name = "pm8xxx_vib_ffmemless" ; |
205 | input_dev->id.version = 1; |
206 | input_dev->close = pm8xxx_vib_close; |
207 | input_set_drvdata(dev: input_dev, data: vib); |
208 | input_set_capability(dev: vib->vib_input_dev, EV_FF, FF_RUMBLE); |
209 | |
210 | error = input_ff_create_memless(dev: input_dev, NULL, |
211 | play_effect: pm8xxx_vib_play_effect); |
212 | if (error) { |
213 | dev_err(&pdev->dev, |
214 | "couldn't register vibrator as FF device\n" ); |
215 | return error; |
216 | } |
217 | |
218 | error = input_register_device(input_dev); |
219 | if (error) { |
220 | dev_err(&pdev->dev, "couldn't register input device\n" ); |
221 | return error; |
222 | } |
223 | |
224 | platform_set_drvdata(pdev, data: vib); |
225 | return 0; |
226 | } |
227 | |
228 | static int pm8xxx_vib_suspend(struct device *dev) |
229 | { |
230 | struct pm8xxx_vib *vib = dev_get_drvdata(dev); |
231 | |
232 | /* Turn off the vibrator */ |
233 | pm8xxx_vib_set(vib, on: false); |
234 | |
235 | return 0; |
236 | } |
237 | |
238 | static DEFINE_SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); |
239 | |
240 | static const struct of_device_id pm8xxx_vib_id_table[] = { |
241 | { .compatible = "qcom,pm8058-vib" , .data = &pm8058_regs }, |
242 | { .compatible = "qcom,pm8921-vib" , .data = &pm8058_regs }, |
243 | { .compatible = "qcom,pm8916-vib" , .data = &pm8916_regs }, |
244 | { } |
245 | }; |
246 | MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table); |
247 | |
248 | static struct platform_driver pm8xxx_vib_driver = { |
249 | .probe = pm8xxx_vib_probe, |
250 | .driver = { |
251 | .name = "pm8xxx-vib" , |
252 | .pm = pm_sleep_ptr(&pm8xxx_vib_pm_ops), |
253 | .of_match_table = pm8xxx_vib_id_table, |
254 | }, |
255 | }; |
256 | module_platform_driver(pm8xxx_vib_driver); |
257 | |
258 | MODULE_ALIAS("platform:pm8xxx_vib" ); |
259 | MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework" ); |
260 | MODULE_LICENSE("GPL v2" ); |
261 | MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>" ); |
262 | |