Save sram context after changing MPU, DSP or core clocks
[linux-ginger.git] / drivers / cbus / retu-headset.c
blobe798bc2b7c1618ff458f7e0580907868ec5630c3
1 /**
2 * Retu/Vilma headset detection
4 * Copyright (C) 2006 Nokia Corporation
6 * Written by Juha Yrjölä
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file "COPYING" in the main directory of this
10 * archive for more details.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/delay.h>
26 #include <linux/input.h>
27 #include <linux/platform_device.h>
29 #include "retu.h"
31 #define RETU_ADC_CHANNEL_HOOKDET 0x05
33 #define RETU_HEADSET_KEY KEY_PHONE
35 struct retu_headset {
36 spinlock_t lock;
37 struct mutex mutex;
38 struct platform_device *pdev;
39 struct input_dev *idev;
40 unsigned bias_enabled;
41 unsigned detection_enabled;
42 unsigned pressed;
43 struct timer_list enable_timer;
44 struct timer_list detect_timer;
47 static void retu_headset_set_bias(int enable)
49 if (enable) {
50 retu_set_clear_reg_bits(RETU_REG_AUDTXR,
51 (1 << 0) | (1 << 1), 0);
52 msleep(2);
53 retu_set_clear_reg_bits(RETU_REG_AUDTXR, 1 << 3, 0);
54 } else {
55 retu_set_clear_reg_bits(RETU_REG_AUDTXR, 0,
56 (1 << 0) | (1 << 1) | (1 << 3));
60 static void retu_headset_enable(struct retu_headset *hs)
62 mutex_lock(&hs->mutex);
63 if (!hs->bias_enabled) {
64 hs->bias_enabled = 1;
65 retu_headset_set_bias(1);
67 mutex_unlock(&hs->mutex);
70 static void retu_headset_disable(struct retu_headset *hs)
72 mutex_lock(&hs->mutex);
73 if (hs->bias_enabled) {
74 hs->bias_enabled = 0;
75 retu_headset_set_bias(0);
77 mutex_unlock(&hs->mutex);
80 static void retu_headset_det_enable(struct retu_headset *hs)
82 mutex_lock(&hs->mutex);
83 if (!hs->detection_enabled) {
84 hs->detection_enabled = 1;
85 retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0);
86 retu_enable_irq(RETU_INT_HOOK);
88 mutex_unlock(&hs->mutex);
91 static void retu_headset_det_disable(struct retu_headset *hs)
93 unsigned long flags;
95 mutex_lock(&hs->mutex);
96 if (hs->detection_enabled) {
97 hs->detection_enabled = 0;
98 retu_disable_irq(RETU_INT_HOOK);
99 del_timer_sync(&hs->enable_timer);
100 del_timer_sync(&hs->detect_timer);
101 spin_lock_irqsave(&hs->lock, flags);
102 if (hs->pressed)
103 input_report_key(hs->idev, RETU_HEADSET_KEY, 0);
104 spin_unlock_irqrestore(&hs->lock, flags);
105 retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8));
107 mutex_unlock(&hs->mutex);
110 static ssize_t retu_headset_hookdet_show(struct device *dev,
111 struct device_attribute *attr,
112 char *buf)
114 int val;
116 val = retu_read_adc(RETU_ADC_CHANNEL_HOOKDET);
117 return sprintf(buf, "%d\n", val);
120 static DEVICE_ATTR(hookdet, S_IRUGO, retu_headset_hookdet_show, NULL);
122 static ssize_t retu_headset_enable_show(struct device *dev,
123 struct device_attribute *attr,
124 char *buf)
126 struct retu_headset *hs = dev_get_drvdata(dev);
128 return sprintf(buf, "%u\n", hs->bias_enabled);
131 static ssize_t retu_headset_enable_store(struct device *dev,
132 struct device_attribute *attr,
133 const char *buf, size_t count)
135 struct retu_headset *hs = dev_get_drvdata(dev);
136 int enable;
138 if (sscanf(buf, "%u", &enable) != 1)
139 return -EINVAL;
140 if (enable)
141 retu_headset_enable(hs);
142 else
143 retu_headset_disable(hs);
144 return count;
147 static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
148 retu_headset_enable_show, retu_headset_enable_store);
150 static ssize_t retu_headset_enable_det_show(struct device *dev,
151 struct device_attribute *attr,
152 char *buf)
154 struct retu_headset *hs = dev_get_drvdata(dev);
156 return sprintf(buf, "%u\n", hs->detection_enabled);
159 static ssize_t retu_headset_enable_det_store(struct device *dev,
160 struct device_attribute *attr,
161 const char *buf, size_t count)
163 struct retu_headset *hs = dev_get_drvdata(dev);
164 int enable;
166 if (sscanf(buf, "%u", &enable) != 1)
167 return -EINVAL;
168 if (enable)
169 retu_headset_det_enable(hs);
170 else
171 retu_headset_det_disable(hs);
172 return count;
175 static DEVICE_ATTR(enable_det, S_IRUGO | S_IWUSR | S_IWGRP,
176 retu_headset_enable_det_show,
177 retu_headset_enable_det_store);
179 static void retu_headset_hook_interrupt(unsigned long arg)
181 struct retu_headset *hs = (struct retu_headset *) arg;
182 unsigned long flags;
184 retu_ack_irq(RETU_INT_HOOK);
185 spin_lock_irqsave(&hs->lock, flags);
186 if (!hs->pressed) {
187 /* Headset button was just pressed down. */
188 hs->pressed = 1;
189 input_report_key(hs->idev, RETU_HEADSET_KEY, 1);
191 spin_unlock_irqrestore(&hs->lock, flags);
192 retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8));
193 mod_timer(&hs->enable_timer, jiffies + msecs_to_jiffies(50));
196 static void retu_headset_enable_timer(unsigned long arg)
198 struct retu_headset *hs = (struct retu_headset *) arg;
200 retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0);
201 mod_timer(&hs->detect_timer, jiffies + msecs_to_jiffies(350));
204 static void retu_headset_detect_timer(unsigned long arg)
206 struct retu_headset *hs = (struct retu_headset *) arg;
207 unsigned long flags;
209 spin_lock_irqsave(&hs->lock, flags);
210 if (hs->pressed) {
211 hs->pressed = 0;
212 input_report_key(hs->idev, RETU_HEADSET_KEY, 0);
214 spin_unlock_irqrestore(&hs->lock, flags);
217 static int __init retu_headset_probe(struct platform_device *pdev)
219 struct retu_headset *hs;
220 int r;
222 hs = kzalloc(sizeof(*hs), GFP_KERNEL);
223 if (hs == NULL)
224 return -ENOMEM;
226 hs->pdev = pdev;
228 hs->idev = input_allocate_device();
229 if (hs->idev == NULL) {
230 r = -ENOMEM;
231 goto err1;
233 hs->idev->name = "retu-headset";
234 hs->idev->dev.parent = &pdev->dev;
235 set_bit(EV_KEY, hs->idev->evbit);
236 set_bit(RETU_HEADSET_KEY, hs->idev->keybit);
237 r = input_register_device(hs->idev);
238 if (r < 0)
239 goto err2;
241 r = device_create_file(&pdev->dev, &dev_attr_hookdet);
242 if (r < 0)
243 goto err3;
244 r = device_create_file(&pdev->dev, &dev_attr_enable);
245 if (r < 0)
246 goto err4;
247 r = device_create_file(&pdev->dev, &dev_attr_enable_det);
248 if (r < 0)
249 goto err5;
250 platform_set_drvdata(pdev, hs);
252 spin_lock_init(&hs->lock);
253 mutex_init(&hs->mutex);
254 setup_timer(&hs->enable_timer, retu_headset_enable_timer,
255 (unsigned long) hs);
256 setup_timer(&hs->detect_timer, retu_headset_detect_timer,
257 (unsigned long) hs);
259 r = retu_request_irq(RETU_INT_HOOK, retu_headset_hook_interrupt,
260 (unsigned long) hs, "hookdet");
261 if (r != 0) {
262 dev_err(&pdev->dev, "hookdet IRQ not available\n");
263 goto err6;
265 retu_disable_irq(RETU_INT_HOOK);
266 return 0;
267 err6:
268 device_remove_file(&pdev->dev, &dev_attr_enable_det);
269 err5:
270 device_remove_file(&pdev->dev, &dev_attr_enable);
271 err4:
272 device_remove_file(&pdev->dev, &dev_attr_hookdet);
273 err3:
274 input_unregister_device(hs->idev);
275 err2:
276 input_free_device(hs->idev);
277 err1:
278 kfree(hs);
279 return r;
282 static int retu_headset_remove(struct platform_device *pdev)
284 struct retu_headset *hs = platform_get_drvdata(pdev);
286 device_remove_file(&pdev->dev, &dev_attr_hookdet);
287 device_remove_file(&pdev->dev, &dev_attr_enable);
288 device_remove_file(&pdev->dev, &dev_attr_enable_det);
289 retu_headset_disable(hs);
290 retu_headset_det_disable(hs);
291 retu_free_irq(RETU_INT_HOOK);
292 input_unregister_device(hs->idev);
293 input_free_device(hs->idev);
294 return 0;
297 static int retu_headset_suspend(struct platform_device *pdev,
298 pm_message_t mesg)
300 struct retu_headset *hs = platform_get_drvdata(pdev);
302 mutex_lock(&hs->mutex);
303 if (hs->bias_enabled)
304 retu_headset_set_bias(0);
305 mutex_unlock(&hs->mutex);
307 return 0;
310 static int retu_headset_resume(struct platform_device *pdev)
312 struct retu_headset *hs = platform_get_drvdata(pdev);
314 mutex_lock(&hs->mutex);
315 if (hs->bias_enabled)
316 retu_headset_set_bias(1);
317 mutex_unlock(&hs->mutex);
319 return 0;
322 static struct platform_driver retu_headset_driver = {
323 .probe = retu_headset_probe,
324 .remove = retu_headset_remove,
325 .suspend = retu_headset_suspend,
326 .resume = retu_headset_resume,
327 .driver = {
328 .name = "retu-headset",
332 static int __init retu_headset_init(void)
334 int r;
336 printk(KERN_INFO "Retu/Vilma headset driver initializing\n");
338 r = platform_driver_register(&retu_headset_driver);
339 if (r < 0)
340 return r;
342 return 0;
345 static void __exit retu_headset_exit(void)
347 platform_driver_unregister(&retu_headset_driver);
350 module_init(retu_headset_init);
351 module_exit(retu_headset_exit);
353 MODULE_DESCRIPTION("Retu/Vilma headset detection");
354 MODULE_LICENSE("GPL");
355 MODULE_AUTHOR("Juha Yrjölä");