]> Pileus Git - ~andy/linux/blob - drivers/input/misc/pm8xxx-vibrator.c
Input: pm8xxx-vibrator - switch to using managed resources
[~andy/linux] / drivers / input / misc / pm8xxx-vibrator.c
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
181 static int pm8xxx_vib_probe(struct platform_device *pdev)
182
183 {
184         struct pm8xxx_vib *vib;
185         struct input_dev *input_dev;
186         int error;
187         u8 val;
188
189         vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL);
190         if (!vib)
191                 return -ENOMEM;
192
193         input_dev = devm_input_allocate_device(&pdev->dev);
194         if (!input_dev)
195                 return -ENOMEM;
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                 return error;
205
206         val &= ~VIB_DRV_EN_MANUAL_MASK;
207         error = pm8xxx_vib_write_u8(vib, val, VIB_DRV);
208         if (error < 0)
209                 return error;
210
211         vib->reg_vib_drv = val;
212
213         input_dev->name = "pm8xxx_vib_ffmemless";
214         input_dev->id.version = 1;
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                 return error;
225         }
226
227         error = input_register_device(input_dev);
228         if (error) {
229                 dev_err(&pdev->dev, "couldn't register input device\n");
230                 return error;
231         }
232
233         platform_set_drvdata(pdev, vib);
234         return 0;
235 }
236
237 #ifdef CONFIG_PM_SLEEP
238 static int pm8xxx_vib_suspend(struct device *dev)
239 {
240         struct pm8xxx_vib *vib = dev_get_drvdata(dev);
241
242         /* Turn off the vibrator */
243         pm8xxx_vib_set(vib, false);
244
245         return 0;
246 }
247 #endif
248
249 static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL);
250
251 static struct platform_driver pm8xxx_vib_driver = {
252         .probe          = pm8xxx_vib_probe,
253         .driver         = {
254                 .name   = "pm8xxx-vib",
255                 .owner  = THIS_MODULE,
256                 .pm     = &pm8xxx_vib_pm_ops,
257         },
258 };
259 module_platform_driver(pm8xxx_vib_driver);
260
261 MODULE_ALIAS("platform:pm8xxx_vib");
262 MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework");
263 MODULE_LICENSE("GPL v2");
264 MODULE_AUTHOR("Amy Maloche <amaloche@codeaurora.org>");