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>
31 #define RETU_ADC_CHANNEL_HOOKDET 0x05
33 #define RETU_HEADSET_KEY KEY_PHONE
37 struct platform_device *pdev;
38 struct input_dev *idev;
39 unsigned bias_enabled:1;
40 unsigned detection_enabled:1;
42 struct timer_list enable_timer;
43 struct timer_list detect_timer;
46 static void retu_headset_set_bias(int enable)
49 retu_set_clear_reg_bits(RETU_REG_AUDTXR,
50 (1 << 0) | (1 << 1), 0);
52 retu_set_clear_reg_bits(RETU_REG_AUDTXR, 1 << 3, 0);
54 retu_set_clear_reg_bits(RETU_REG_AUDTXR, 0,
55 (1 << 0) | (1 << 1) | (1 << 3));
59 static void retu_headset_enable(struct retu_headset *hs)
64 retu_headset_set_bias(1);
67 static void retu_headset_disable(struct retu_headset *hs)
69 if (!hs->bias_enabled)
72 retu_headset_set_bias(0);
75 static void retu_headset_det_enable(struct retu_headset *hs)
77 if (hs->detection_enabled)
79 hs->detection_enabled = 1;
80 retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0);
81 retu_enable_irq(RETU_INT_HOOK);
84 static void retu_headset_det_disable(struct retu_headset *hs)
86 if (!hs->detection_enabled)
88 hs->detection_enabled = 0;
89 retu_disable_irq(RETU_INT_HOOK);
90 del_timer_sync(&hs->enable_timer);
91 del_timer_sync(&hs->detect_timer);
93 input_report_key(hs->idev, RETU_HEADSET_KEY, 0);
94 retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8));
97 static ssize_t retu_headset_hookdet_show(struct device *dev,
98 struct device_attribute *attr,
103 val = retu_read_adc(RETU_ADC_CHANNEL_HOOKDET);
104 return sprintf(buf, "%d\n", val);
107 static DEVICE_ATTR(hookdet, S_IRUGO, retu_headset_hookdet_show, NULL);
109 static ssize_t retu_headset_enable_show(struct device *dev,
110 struct device_attribute *attr,
113 struct retu_headset *hs = dev_get_drvdata(dev);
115 return sprintf(buf, "%u\n", hs->bias_enabled);
118 static ssize_t retu_headset_enable_store(struct device *dev,
119 struct device_attribute *attr,
120 const char *buf, size_t count)
122 struct retu_headset *hs = dev_get_drvdata(dev);
125 if (sscanf(buf, "%u", &enable) != 1)
128 retu_headset_enable(hs);
130 retu_headset_disable(hs);
134 static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP,
135 retu_headset_enable_show, retu_headset_enable_store);
137 static ssize_t retu_headset_enable_det_show(struct device *dev,
138 struct device_attribute *attr,
141 struct retu_headset *hs = dev_get_drvdata(dev);
143 return sprintf(buf, "%u\n", hs->detection_enabled);
146 static ssize_t retu_headset_enable_det_store(struct device *dev,
147 struct device_attribute *attr,
148 const char *buf, size_t count)
150 struct retu_headset *hs = dev_get_drvdata(dev);
153 if (sscanf(buf, "%u", &enable) != 1)
156 retu_headset_det_enable(hs);
158 retu_headset_det_disable(hs);
162 static DEVICE_ATTR(enable_det, S_IRUGO | S_IWUSR | S_IWGRP,
163 retu_headset_enable_det_show,
164 retu_headset_enable_det_store);
166 static void retu_headset_hook_interrupt(unsigned long arg)
168 struct retu_headset *hs = (struct retu_headset *) arg;
172 retu_ack_irq(RETU_INT_HOOK);
173 spin_lock_irqsave(&hs->lock, flags);
175 /* Headset button was just pressed down. */
177 input_report_key(hs->idev, RETU_HEADSET_KEY, 1);
180 spin_unlock_irqrestore(&hs->lock, flags);
182 dev_info(&hs->pdev->dev, "button pressed\n");
183 retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8));
184 mod_timer(&hs->enable_timer, jiffies + msecs_to_jiffies(50));
187 static void retu_headset_enable_timer(unsigned long arg)
189 struct retu_headset *hs = (struct retu_headset *) arg;
191 retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0);
192 mod_timer(&hs->detect_timer, jiffies + msecs_to_jiffies(350));
195 static void retu_headset_detect_timer(unsigned long arg)
197 struct retu_headset *hs = (struct retu_headset *) arg;
200 spin_lock_irqsave(&hs->lock, flags);
201 BUG_ON(!hs->pressed);
202 input_report_key(hs->idev, RETU_HEADSET_KEY, 0);
204 spin_unlock_irqrestore(&hs->lock, flags);
205 dev_info(&hs->pdev->dev, "button released\n");
208 static int __init retu_headset_probe(struct platform_device *pdev)
210 struct retu_headset *hs;
213 hs = kzalloc(sizeof(*hs), GFP_KERNEL);
219 hs->idev = input_allocate_device();
220 if (hs->idev == NULL) {
224 hs->idev->name = "retu-headset";
225 hs->idev->cdev.dev = &pdev->dev;
226 hs->idev->private = hs;
227 set_bit(EV_KEY, hs->idev->evbit);
228 set_bit(RETU_HEADSET_KEY, hs->idev->keybit);
229 r = input_register_device(hs->idev);
233 r = device_create_file(&pdev->dev, &dev_attr_hookdet);
236 r = device_create_file(&pdev->dev, &dev_attr_enable);
239 r = device_create_file(&pdev->dev, &dev_attr_enable_det);
242 platform_set_drvdata(pdev, hs);
244 spin_lock_init(&hs->lock);
245 setup_timer(&hs->enable_timer, retu_headset_enable_timer,
247 setup_timer(&hs->detect_timer, retu_headset_detect_timer,
250 r = retu_request_irq(RETU_INT_HOOK, retu_headset_hook_interrupt,
251 (unsigned long) hs, "hookdet");
253 dev_err(&pdev->dev, "hookdet IRQ not available\n");
256 retu_disable_irq(RETU_INT_HOOK);
259 device_remove_file(&pdev->dev, &dev_attr_enable_det);
261 device_remove_file(&pdev->dev, &dev_attr_enable);
263 device_remove_file(&pdev->dev, &dev_attr_hookdet);
265 input_unregister_device(hs->idev);
267 input_free_device(hs->idev);
273 static int retu_headset_remove(struct platform_device *pdev)
275 struct retu_headset *hs = platform_get_drvdata(pdev);
277 device_remove_file(&pdev->dev, &dev_attr_hookdet);
278 device_remove_file(&pdev->dev, &dev_attr_enable);
279 device_remove_file(&pdev->dev, &dev_attr_enable_det);
280 retu_headset_disable(hs);
281 retu_headset_det_disable(hs);
282 retu_free_irq(RETU_INT_HOOK);
283 input_unregister_device(hs->idev);
284 input_free_device(hs->idev);
288 static int retu_headset_suspend(struct platform_device *pdev,
294 static int retu_headset_resume(struct platform_device *pdev)
299 static struct platform_driver retu_headset_driver = {
300 .probe = retu_headset_probe,
301 .remove = retu_headset_remove,
302 .suspend = retu_headset_suspend,
303 .resume = retu_headset_resume,
305 .name = "retu-headset",
309 static int __init retu_headset_init(void)
313 printk(KERN_INFO "Retu/Vilma headset driver initializing\n");
315 r = platform_driver_register(&retu_headset_driver);
322 static void __exit retu_headset_exit(void)
324 platform_driver_unregister(&retu_headset_driver);
327 module_init(retu_headset_init);
328 module_exit(retu_headset_exit);
330 MODULE_DESCRIPTION("Retu/Vilma headset detection");
331 MODULE_LICENSE("GPL");
332 MODULE_AUTHOR("Juha Yrjölä");