blob: 9f4e004ef9ecfb0091fc807050a3ff5bc12e16db [file] [log] [blame]
chenxl0723ef2f83a2015-10-14 21:41:31 +08001#include <linux/platform_device.h>
2#include <linux/init.h>
3#include <linux/module.h>
Chen Xuelong2a5935e2015-02-11 17:45:10 +08004#include <linux/hrtimer.h>
5#include <linux/err.h>
6#include <linux/gpio.h>
7#include <linux/wakelock.h>
8#include <linux/mutex.h>
9#include <linux/clk.h>
10#include <linux/workqueue.h>
11#include <asm/mach-types.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
chenxl0723ef2f83a2015-10-14 21:41:31 +080014#include <linux/regulator/consumer.h>
Chen Xuelong2a5935e2015-02-11 17:45:10 +080015#include<../drivers/staging/android/timed_output.h>
chenxl0723ef2f83a2015-10-14 21:41:31 +080016#include <linux/slab.h>
Chen Xuelong2a5935e2015-02-11 17:45:10 +080017
18#define DRV2603_VIBRATOR_EN 86
19#define DRV2603_VIBRATOR_PWM 85
20#define MAX_TIMEOUT 10000 /* 10s */
chenxl0723ef2f83a2015-10-14 21:41:31 +080021#define DRV2603_VTG_MIN_UV 2850000
22#define DRV2603_VTG_MAX_UV 2850000
23#define DRV2603_VTG_CURR_UA 150000
24
25struct drv2603_data {
26 struct platform_device *pdev;
27 struct regulator *drv2603_vcc;
28};
29struct drv2603_data *drv2603;
Chen Xuelong2a5935e2015-02-11 17:45:10 +080030
31static struct vibrator{
32 struct wake_lock wklock;
33 struct hrtimer timer;
34 struct mutex lock;
35 struct work_struct work;
36}vibdata;
37
38static void drv2603_vibrator_off(void)
39{
40 gpio_direction_output (DRV2603_VIBRATOR_EN, 0);
41 wake_unlock(&vibdata.wklock);
42}
chenxl0723ef2f83a2015-10-14 21:41:31 +080043
Chen Xuelong2a5935e2015-02-11 17:45:10 +080044void drv2603_motor_enable(struct timed_output_dev *sdev, int value)
45{
46 mutex_lock(&vibdata.lock);
47 hrtimer_cancel(&vibdata.timer);
48 cancel_work_sync(&vibdata.work);
49 if (value)
50 {
51 wake_lock(&vibdata.wklock);
52 gpio_direction_output(DRV2603_VIBRATOR_EN, 1);
53 if (value > 0)
54 {
55 if(value > MAX_TIMEOUT)
56 value= MAX_TIMEOUT;
57 hrtimer_start(&vibdata.timer,
58 ns_to_ktime((u64)value* NSEC_PER_MSEC),
59 HRTIMER_MODE_REL);
60 }
61 }
62 else
63 drv2603_vibrator_off();
64
65 mutex_unlock(&vibdata.lock);
66}
67
68int drv2603_get_time(struct timed_output_dev *sdev)
69{
70 if(hrtimer_active(&vibdata.timer))
71 {
72 ktime_t r = hrtimer_get_remaining(&vibdata.timer);
73 return ktime_to_ms(r);
74 }
75 return 0;
76}
77
78struct timed_output_dev drv2603_motot_driver={
79 .name ="vibrator",
80 .enable= drv2603_motor_enable,
81 .get_time= drv2603_get_time,
82};
83
84static enum hrtimer_restart drv2603_vibrator_timer_func(struct hrtimer * timer)
85{
86 schedule_work(&vibdata.work);
87 return HRTIMER_NORESTART;
88}
89
90static void drv2603_vibrator_work(struct work_struct *work)
91{
92 drv2603_vibrator_off();
93}
94
chenxl0723ef2f83a2015-10-14 21:41:31 +080095static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
Chen Xuelong2a5935e2015-02-11 17:45:10 +080096{
chenxl0723ef2f83a2015-10-14 21:41:31 +080097 return (regulator_count_voltages(reg) > 0) ?
98 regulator_set_optimum_mode(reg, load_uA) : 0;
99}
100
101static int drv2603_pdev_power_on(struct drv2603_data *hbtp, bool on)
102{
103 int ret, error;
104
105 if (!hbtp->drv2603_vcc) {
106 pr_err("%s: regulator is not available\n", __func__);
107 return -EINVAL;
108 }
109
110 if (!on)
111 goto reg_off;
112
113 ret = reg_set_optimum_mode_check(hbtp->drv2603_vcc, DRV2603_VTG_CURR_UA);
114 if (ret < 0) {
115 pr_err("%s: Regulator drv2603_vcc set_opt failed rc=%d\n",
116 __func__, ret);
117 return -EINVAL;
118 }
119
120 ret = regulator_enable(hbtp->drv2603_vcc);
121 if (ret) {
122 pr_err("%s: Regulator drv2603_vcc enable failed rc=%d\n",
123 __func__, ret);
124 error = -EINVAL;
125 goto error_reg_en_drv2603_vcc;
126 }
127
128 return 0;
129error_reg_en_drv2603_vcc:
130 reg_set_optimum_mode_check(hbtp->drv2603_vcc, 0);
131 return error;
132
133reg_off:
134 reg_set_optimum_mode_check(hbtp->drv2603_vcc, 0);
135 regulator_disable(hbtp->drv2603_vcc);
136 return 0;
137}
138
139#ifdef CONFIG_PM
140
141static int ti_drv2603_suspend(struct platform_device *pdev, pm_message_t state)
142{
143 hrtimer_cancel(&vibdata.timer);
144 cancel_work_sync(&vibdata.work);
145
146 /* turn regulators off */
147 drv2603_pdev_power_on(drv2603,false);
148
149 return 0;
150}
151
152static int ti_drv2603_resume(struct platform_device *pdev)
153{
154 int rc;
155
156 /* turn regulators on */
157 rc = drv2603_pdev_power_on(drv2603, true);
158 if (rc < 0) {
159 pr_err("%s: drv2603 unable to turn regulators on rc=%d\n",
160 __func__, rc);
161 return rc;
162 }
163
164 return 0;
165}
166
167#endif /* CONFIG_PM */
168
169static int ti_drv2603_probe(struct platform_device *pdev)
170{
171 int rc=0;
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800172 int ret =0;
173
chenxl0723ef2f83a2015-10-14 21:41:31 +0800174 struct regulator *drv2603_vcc;
175
176 printk("ti_drv2603 probe\n");
177 drv2603_vcc = regulator_get(&pdev->dev, "vdd-drv2603");
178 if (IS_ERR(drv2603_vcc)) {
179 rc = PTR_ERR(drv2603_vcc);
180 pr_err("%s: Regulator get failed vcc_drv2603 rc=%d\n",
181 __func__, rc);
182 return -EINVAL;
183 }
184
185 if (regulator_count_voltages(drv2603_vcc) > 0) {
186 ret = regulator_set_voltage(drv2603_vcc,
187 DRV2603_VTG_MIN_UV, DRV2603_VTG_MAX_UV);
188 if (ret) {
189 pr_err("%s: regulator set_vtg failed rc=%d\n",
190 __func__, ret);
191 ret = -EINVAL;
192 goto error_set_vtg_drv2603_vcc;
193 }
194 }
195
196 drv2603->drv2603_vcc = drv2603_vcc;
197 drv2603->pdev= pdev;
198 drv2603_pdev_power_on(drv2603,true);
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800199 INIT_WORK(&vibdata.work, drv2603_vibrator_work);
200 hrtimer_init(&vibdata.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
201 vibdata.timer.function= drv2603_vibrator_timer_func;
202
203 ret =gpio_request(DRV2603_VIBRATOR_EN, "vibrator-en");
204 if (ret< 0)
205 {
206 printk("vibratorrequest en IO err!:%d\n",ret);
207 return ret;
208 }
209 ret = gpio_request(DRV2603_VIBRATOR_PWM, "vibrator-pwm");
210 if (ret< 0)
211 {
212 printk("vibratorrequest pwm IO err!:%d\n",ret);
213 return ret;
214 }
215 gpio_direction_output(DRV2603_VIBRATOR_EN, 0);
wangxl16d8b6ce2015-08-15 15:51:20 +0800216 gpio_direction_input(DRV2603_VIBRATOR_PWM);
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800217 wake_lock_init(&vibdata.wklock,WAKE_LOCK_SUSPEND, "vibrator");
218 mutex_init(&vibdata.lock);
219 ret=timed_output_dev_register(&drv2603_motot_driver);
220 if (ret< 0)
221 goto err_to_dev_reg;
chenxl0723ef2f83a2015-10-14 21:41:31 +0800222
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800223 return 0;
chenxl0723ef2f83a2015-10-14 21:41:31 +0800224
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800225err_to_dev_reg:
226 mutex_destroy(&vibdata.lock);
227 wake_lock_destroy(&vibdata.wklock);
228 gpio_free(DRV2603_VIBRATOR_EN);
229 gpio_free(DRV2603_VIBRATOR_PWM);
230 printk("vibrator err!:%d\n",ret);
231 return ret;
chenxl0723ef2f83a2015-10-14 21:41:31 +0800232
233error_set_vtg_drv2603_vcc:
234 regulator_put(drv2603_vcc);
235 return ret;
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800236}
237
chenxl0723ef2f83a2015-10-14 21:41:31 +0800238static int ti_drv2603_remove(struct platform_device *pdev)
239{
240 if (drv2603->drv2603_vcc) {
241 drv2603_pdev_power_on(drv2603, false);
242 regulator_put(drv2603->drv2603_vcc);
243 }
244 return 0;
245}
246
247static const struct of_device_id drv2603_of_id_table[] = {
248 {.compatible = "drv2603"},
249 { },
250};
251
252static struct platform_driver ti_drv2603_driver = {
253 .probe = ti_drv2603_probe,
254 .remove = ti_drv2603_remove,
255 .driver = {
256 .name = "drv2603",
257 .owner = THIS_MODULE,
258 .of_match_table = drv2603_of_id_table,
259 },
260#ifdef CONFIG_PM
261 .suspend = ti_drv2603_suspend,
262 .resume = ti_drv2603_resume,
263#endif
264};
265
266static int ti_drv2603_init(void)
267{
268 drv2603 = kzalloc(sizeof(struct drv2603_data), GFP_KERNEL);
269 if (!drv2603)
270 return -ENOMEM;
271 return platform_driver_register(&ti_drv2603_driver);
272}
273
274static void ti_drv2603_exit(void)
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800275{
276 mutex_destroy(&vibdata.lock);
277 wake_lock_destroy(&vibdata.wklock);
278 gpio_free(DRV2603_VIBRATOR_EN);
279 gpio_free(DRV2603_VIBRATOR_PWM);
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800280 timed_output_dev_register(&drv2603_motot_driver);
chenxl0723ef2f83a2015-10-14 21:41:31 +0800281 platform_driver_unregister(&ti_drv2603_driver);
282 kfree(drv2603);
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800283}
284
chenxl0723ef2f83a2015-10-14 21:41:31 +0800285module_init(ti_drv2603_init);
286module_exit(ti_drv2603_exit);
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800287
chenxl0723ef2f83a2015-10-14 21:41:31 +0800288MODULE_AUTHOR("Godfather.cxl");
Chen Xuelong2a5935e2015-02-11 17:45:10 +0800289MODULE_DESCRIPTION("Drv2603 Vibrator driver");
290MODULE_LICENSE("GPL");
chenxl0723ef2f83a2015-10-14 21:41:31 +0800291MODULE_ALIAS("ti_drv2603");