Commit | Line | Data |
---|---|---|
11205bb6 AM |
1 | /* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License version 2 and | |
5 | * only version 2 as published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | */ | |
12 | ||
13 | #include <linux/module.h> | |
14 | #include <linux/init.h> | |
15 | #include <linux/kernel.h> | |
16 | #include <linux/errno.h> | |
17 | #include <linux/platform_device.h> | |
18 | #include <linux/input.h> | |
19 | #include <linux/slab.h> | |
20 | #include <linux/mfd/pm8xxx/core.h> | |
21 | ||
22 | #define VIB_DRV 0x4A | |
23 | ||
24 | #define VIB_DRV_SEL_MASK 0xf8 | |
25 | #define VIB_DRV_SEL_SHIFT 0x03 | |
26 | #define VIB_DRV_EN_MANUAL_MASK 0xfc | |
27 | ||
28 | #define VIB_MAX_LEVEL_mV (3100) | |
29 | #define VIB_MIN_LEVEL_mV (1200) | |
30 | #define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) | |
31 | ||
32 | #define MAX_FF_SPEED 0xff | |
33 | ||
34 | /** | |
35 | * struct pm8xxx_vib - structure to hold vibrator data | |
36 | * @vib_input_dev: input device supporting force feedback | |
37 | * @work: work structure to set the vibration parameters | |
38 | * @dev: device supporting force feedback | |
39 | * @speed: speed of vibration set from userland | |
40 | * @active: state of vibrator | |
41 | * @level: level of vibration to set in the chip | |
42 | * @reg_vib_drv: VIB_DRV register value | |
43 | */ | |
44 | struct pm8xxx_vib { | |
45 | struct input_dev *vib_input_dev; | |
46 | struct work_struct work; | |
47 | struct device *dev; | |
48 | int speed; | |
49 | int level; | |
50 | bool active; | |
51 | u8 reg_vib_drv; | |
52 | }; | |
53 | ||
54 | /** | |
55 | * pm8xxx_vib_read_u8 - helper to read a byte from pmic chip | |
56 | * @vib: pointer to vibrator structure | |
57 | * @data: placeholder for data to be read | |
58 | * @reg: register address | |
59 | */ | |
60 | static int pm8xxx_vib_read_u8(struct pm8xxx_vib *vib, | |
61 | u8 *data, u16 reg) | |
62 | { | |
63 | int rc; | |
64 | ||
65 | rc = pm8xxx_readb(vib->dev->parent, reg, data); | |
66 | if (rc < 0) | |
67 | dev_warn(vib->dev, "Error reading pm8xxx reg 0x%x(0x%x)\n", | |
68 | reg, rc); | |
69 | return rc; | |
70 | } | |
71 | ||
72 | /** | |
73 | * pm8xxx_vib_write_u8 - helper to write a byte to pmic chip | |
74 | * @vib: pointer to vibrator structure | |
75 | * @data: data to write | |
76 | * @reg: register address | |
77 | */ | |
78 | static int pm8xxx_vib_write_u8(struct pm8xxx_vib *vib, | |
79 | u8 data, u16 reg) | |
80 | { | |
81 | int rc; | |
82 | ||
83 | rc = pm8xxx_writeb(vib->dev->parent, reg, data); | |
84 | if (rc < 0) | |
85 | dev_warn(vib->dev, "Error writing pm8xxx reg 0x%x(0x%x)\n", | |
86 | reg, rc); | |
87 | return rc; | |
88 | } | |
89 | ||
90 | /** | |
91 | * pm8xxx_vib_set - handler to start/stop vibration | |
92 | * @vib: pointer to vibrator structure | |
93 | * @on: state to set | |
94 | */ | |
95 | static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) | |
96 | { | |
97 | int rc; | |
98 | u8 val = vib->reg_vib_drv; | |
99 | ||
100 | if (on) | |
101 | val |= ((vib->level << VIB_DRV_SEL_SHIFT) & VIB_DRV_SEL_MASK); | |
102 | else | |
103 | val &= ~VIB_DRV_SEL_MASK; | |
104 | ||
105 | rc = pm8xxx_vib_write_u8(vib, val, VIB_DRV); | |
106 | if (rc < 0) | |
107 | return rc; | |
108 | ||
109 | vib->reg_vib_drv = val; | |
110 | return 0; | |
111 | } | |
112 | ||
113 | /** | |
114 | * pm8xxx_work_handler - worker to set vibration level | |
115 | * @work: pointer to work_struct | |
116 | */ | |
117 | static void pm8xxx_work_handler(struct work_struct *work) | |
118 | { | |
119 | struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); | |
120 | int rc; | |
121 | u8 val; | |
122 | ||
123 | rc = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); | |
124 | if (rc < 0) | |
125 | return; | |
126 | ||
127 | /* | |
128 | * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so | |
129 | * scale the level to fit into these ranges. | |
130 | */ | |
131 | if (vib->speed) { | |
132 | vib->active = true; | |
133 | vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + | |
134 | VIB_MIN_LEVEL_mV; | |
135 | vib->level /= 100; | |
136 | } else { | |
137 | vib->active = false; | |
138 | vib->level = VIB_MIN_LEVEL_mV / 100; | |
139 | } | |
140 | ||
141 | pm8xxx_vib_set(vib, vib->active); | |
142 | } | |
143 | ||
144 | /** | |
145 | * pm8xxx_vib_close - callback of input close callback | |
146 | * @dev: input device pointer | |
147 | * | |
148 | * Turns off the vibrator. | |
149 | */ | |
150 | static void pm8xxx_vib_close(struct input_dev *dev) | |
151 | { | |
152 | struct pm8xxx_vib *vib = input_get_drvdata(dev); | |
153 | ||
154 | cancel_work_sync(&vib->work); | |
155 | if (vib->active) | |
156 | pm8xxx_vib_set(vib, false); | |
157 | } | |
158 | ||
159 | /** | |
160 | * pm8xxx_vib_play_effect - function to handle vib effects. | |
161 | * @dev: input device pointer | |
162 | * @data: data of effect | |
163 | * @effect: effect to play | |
164 | * | |
165 | * Currently this driver supports only rumble effects. | |
166 | */ | |
167 | static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data, | |
168 | struct ff_effect *effect) | |
169 | { | |
170 | struct pm8xxx_vib *vib = input_get_drvdata(dev); | |
171 | ||
172 | vib->speed = effect->u.rumble.strong_magnitude >> 8; | |
173 | if (!vib->speed) | |
174 | vib->speed = effect->u.rumble.weak_magnitude >> 9; | |
175 | ||
176 | schedule_work(&vib->work); | |
177 | ||
178 | return 0; | |
179 | } | |
180 | ||
5298cc4c | 181 | static int pm8xxx_vib_probe(struct platform_device *pdev) |
11205bb6 AM |
182 | |
183 | { | |
184 | struct pm8xxx_vib *vib; | |
185 | struct input_dev *input_dev; | |
186 | int error; | |
187 | u8 val; | |
188 | ||
189 | vib = kzalloc(sizeof(*vib), GFP_KERNEL); | |
190 | input_dev = input_allocate_device(); | |
191 | if (!vib || !input_dev) { | |
192 | dev_err(&pdev->dev, "couldn't allocate memory\n"); | |
193 | error = -ENOMEM; | |
194 | goto err_free_mem; | |
195 | } | |
196 | ||
197 | INIT_WORK(&vib->work, pm8xxx_work_handler); | |
198 | vib->dev = &pdev->dev; | |
199 | vib->vib_input_dev = input_dev; | |
200 | ||
201 | /* operate in manual mode */ | |
202 | error = pm8xxx_vib_read_u8(vib, &val, VIB_DRV); | |
203 | if (error < 0) | |
204 | goto err_free_mem; | |
205 | val &= ~VIB_DRV_EN_MANUAL_MASK; | |
206 | error = pm8xxx_vib_write_u8(vib, val, VIB_DRV); | |
207 | if (error < 0) | |
208 | goto err_free_mem; | |
209 | ||
210 | vib->reg_vib_drv = val; | |
211 | ||
212 | input_dev->name = "pm8xxx_vib_ffmemless"; | |
213 | input_dev->id.version = 1; | |
214 | input_dev->dev.parent = &pdev->dev; | |
215 | input_dev->close = pm8xxx_vib_close; | |
216 | input_set_drvdata(input_dev, vib); | |
217 | input_set_capability(vib->vib_input_dev, EV_FF, FF_RUMBLE); | |
218 | ||
219 | error = input_ff_create_memless(input_dev, NULL, | |
220 | pm8xxx_vib_play_effect); | |
221 | if (error) { | |
222 | dev_err(&pdev->dev, | |
223 | "couldn't register vibrator as FF device\n"); | |
224 | goto err_free_mem; | |
225 | } | |
226 | ||
227 | error = input_register_device(input_dev); | |
228 | if (error) { | |
229 | dev_err(&pdev->dev, "couldn't register input device\n"); | |
230 | goto err_destroy_memless; | |
231 | } | |
232 | ||
233 | platform_set_drvdata(pdev, vib); | |
234 | return 0; | |
235 | ||
236 | err_destroy_memless: | |
237 | input_ff_destroy(input_dev); | |
238 | err_free_mem: | |
239 | input_free_device(input_dev); | |
240 | kfree(vib); | |
241 | ||
242 | return error; | |
243 | } | |
244 | ||
e2619cf7 | 245 | static int pm8xxx_vib_remove(struct platform_device *pdev) |
11205bb6 AM |
246 | { |
247 | struct pm8xxx_vib *vib = platform_get_drvdata(pdev); | |
248 | ||
249 | input_unregister_device(vib->vib_input_dev); | |
250 | kfree(vib); | |
251 | ||
11205bb6 AM |
252 | return 0; |
253 | } | |
254 | ||
255 | #ifdef CONFIG_PM_SLEEP | |
256 | static int pm8xxx_vib_suspend(struct device *dev) | |
257 | { | |
258 | struct pm8xxx_vib *vib = dev_get_drvdata(dev); | |
259 | ||
260 | /* Turn off the vibrator */ | |
261 | pm8xxx_vib_set(vib, false); | |
262 | ||
263 | return 0; | |
264 | } | |
265 | #endif | |
266 | ||
267 | static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); | |
268 | ||
269 | static struct platform_driver pm8xxx_vib_driver = { | |
270 | .probe = pm8xxx_vib_probe, | |
1cb0aa88 | 271 | .remove = pm8xxx_vib_remove, |
11205bb6 AM |
272 | .driver = { |
273 | .name = "pm8xxx-vib", | |
274 | .owner = THIS_MODULE, | |
275 | .pm = &pm8xxx_vib_pm_ops, | |
276 | }, | |
277 | }; | |
840a746b | 278 | module_platform_driver(pm8xxx_vib_driver); |
11205bb6 AM |
279 | |
280 | MODULE_ALIAS("platform:pm8xxx_vib"); | |
281 | MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework"); | |
282 | MODULE_LICENSE("GPL v2"); | |
283 | MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>"); |