Vibrator : Make regulator enable & disable paired
[linux-2.6.git] / drivers / misc / max1749.c
1 /*
2  * drivers/misc/max1749.c
3  *
4  * Driver for MAX1749, vibrator motor driver.
5  *
6  * Copyright (c) 2011-2012 NVIDIA Corporation, All Rights Reserved.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  * more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  */
22
23 #include <linux/module.h>
24 #include <linux/regulator/consumer.h>
25 #include <linux/kernel.h>
26 #include <linux/platform_device.h>
27 #include <linux/err.h>
28 #include <linux/hrtimer.h>
29 #include <linux/delay.h>
30
31 #include <linux/slab.h>
32
33 #include "../staging/android/timed_output.h"
34
35 static struct vibrator_data {
36         struct timed_output_dev dev;
37         struct hrtimer timer;
38         struct regulator *regulator;
39         struct work_struct work;
40         bool vibrator_on;
41 };
42
43 static struct vibrator_data *data;
44
45
46 static void vibrator_start(void)
47 {
48         if (!data->vibrator_on) {
49                 regulator_enable(data->regulator);
50                 data->vibrator_on = true;
51         }
52 }
53
54 static void vibrator_stop(void)
55 {
56         int ret;
57         if (data->vibrator_on) {
58                 ret = regulator_is_enabled(data->regulator);
59                 if (ret > 0) {
60                         regulator_disable(data->regulator);
61                         data->vibrator_on = false;
62                 }
63         }
64 }
65
66 static void vibrator_work_func(unsigned long data)
67 {
68         vibrator_stop();
69 }
70
71 static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
72 {
73         schedule_work(&data->work);
74         return HRTIMER_NORESTART;
75 }
76
77 /*
78  * Timeout value can be changed from sysfs entry
79  * created by timed_output_dev.
80  * echo 100 > /sys/class/timed_output/vibrator/enable
81  */
82 static void vibrator_enable(struct timed_output_dev *dev, int value)
83 {
84         hrtimer_cancel(&data->timer);
85         if (value > 0) {
86                 vibrator_start();
87                 hrtimer_start(&data->timer,
88                           ktime_set(value / 1000, (value % 1000) * 1000000),
89                           HRTIMER_MODE_REL);
90         } else
91                 vibrator_stop();
92         return;
93 }
94
95 static int vibrator_get_time(struct timed_output_dev *dev)
96 {
97         if (hrtimer_active(&data->timer)) {
98                 ktime_t r = hrtimer_get_remaining(&data->timer);
99                 struct timeval t = ktime_to_timeval(r);
100                 return t.tv_sec * 1000 + t.tv_usec / 1000;
101         } else
102                 return 0;
103 }
104
105 static struct timed_output_dev vibrator_dev = {
106         .name           = "vibrator",
107         .get_time       = vibrator_get_time,
108         .enable         = vibrator_enable,
109 };
110
111 static int vibrator_probe(void)
112 {
113         int ret;
114         data = kzalloc(sizeof(struct vibrator_data), GFP_KERNEL);
115         if (!data)
116                 return -ENOMEM;
117
118         data->regulator = regulator_get(NULL, "vdd_vbrtr");
119         if (IS_ERR_OR_NULL(data->regulator)) {
120                 pr_err("vibrator_init:Couldn't get regulator vdd_vbrtr\n");
121                 data->regulator = NULL;
122                 ret = PTR_ERR(data->regulator);
123                 goto err;
124         }
125         hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
126         /* Intialize the work queue */
127         INIT_WORK(&data->work, vibrator_work_func);
128         data->timer.function = vibrator_timer_func;
129         data->dev = vibrator_dev;
130         data->vibrator_on = false;
131
132         ret = timed_output_dev_register(&data->dev);
133         if (ret)
134                 goto err2;
135
136         return 0;
137
138 err2:
139         regulator_put(data->regulator);
140 err:
141         kfree(data);
142         return ret;
143 }
144
145 static int vibrator_remove(void)
146 {
147         timed_output_dev_unregister(&data->dev);
148         regulator_put(data->regulator);
149         kfree(data);
150
151         return 0;
152 }
153
154 static struct platform_driver vibrator_driver = {
155         .probe = vibrator_probe,
156         .remove = vibrator_remove,
157         .driver = {
158                 .name = "tegra-vibrator",
159                 .owner = THIS_MODULE,
160         },
161 };
162
163 static int __init vibrator_init(void)
164 {
165         return platform_driver_register(&vibrator_driver);
166 }
167
168 static void __exit vibrator_exit(void)
169 {
170         platform_driver_unregister(&vibrator_driver);
171 }
172
173 MODULE_DESCRIPTION("timed output vibrator device");
174 MODULE_AUTHOR("GPL");
175
176 module_init(vibrator_init);
177 module_exit(vibrator_exit);