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
38 struct platform_device *pdev;
39 struct input_dev *idev;
40 unsigned bias_enabled;
41 unsigned detection_enabled;
43 struct timer_list enable_timer;
44 struct timer_list detect_timer;
47 static void retu_headset_set_bias(int enable)
50 retu_set_clear_reg_bits(RETU_REG_AUDTXR,
51 (1 << 0) | (1 << 1), 0);
53 retu_set_clear_reg_bits(RETU_REG_AUDTXR, 1 << 3, 0);
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) {
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) {
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)
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);
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,
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,
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);
138 if (sscanf(buf, "%u", &enable) != 1)
141 retu_headset_enable(hs);
143 retu_headset_disable(hs);
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,
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);
166 if (sscanf(buf, "%u", &enable) != 1)
169 retu_headset_det_enable(hs);
171 retu_headset_det_disable(hs);
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;
185 retu_ack_irq(RETU_INT_HOOK);
186 spin_lock_irqsave(&hs->lock, flags);
188 /* Headset button was just pressed down. */
190 input_report_key(hs->idev, RETU_HEADSET_KEY, 1);
193 spin_unlock_irqrestore(&hs->lock, flags);
195 dev_info(&hs->pdev->dev, "button pressed\n");
196 retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8));
197 mod_timer(&hs->enable_timer, jiffies + msecs_to_jiffies(50));
200 static void retu_headset_enable_timer(unsigned long arg)
202 struct retu_headset *hs = (struct retu_headset *) arg;
204 retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0);
205 mod_timer(&hs->detect_timer, jiffies + msecs_to_jiffies(350));
208 static void retu_headset_detect_timer(unsigned long arg)
210 struct retu_headset *hs = (struct retu_headset *) arg;
213 spin_lock_irqsave(&hs->lock, flags);
214 BUG_ON(!hs->pressed);
215 input_report_key(hs->idev, RETU_HEADSET_KEY, 0);
217 spin_unlock_irqrestore(&hs->lock, flags);
218 dev_info(&hs->pdev->dev, "button released\n");
221 static int __init retu_headset_probe(struct platform_device *pdev)
223 struct retu_headset *hs;
226 hs = kzalloc(sizeof(*hs), GFP_KERNEL);
232 hs->idev = input_allocate_device();
233 if (hs->idev == NULL) {
237 hs->idev->name = "retu-headset";
238 hs->idev->cdev.dev = &pdev->dev;
239 hs->idev->private = hs;
240 set_bit(EV_KEY, hs->idev->evbit);
241 set_bit(RETU_HEADSET_KEY, hs->idev->keybit);
242 r = input_register_device(hs->idev);
246 r = device_create_file(&pdev->dev, &dev_attr_hookdet);
249 r = device_create_file(&pdev->dev, &dev_attr_enable);
252 r = device_create_file(&pdev->dev, &dev_attr_enable_det);
255 platform_set_drvdata(pdev, hs);
257 spin_lock_init(&hs->lock);
258 mutex_init(&hs->mutex);
259 setup_timer(&hs->enable_timer, retu_headset_enable_timer,
261 setup_timer(&hs->detect_timer, retu_headset_detect_timer,
264 r = retu_request_irq(RETU_INT_HOOK, retu_headset_hook_interrupt,
265 (unsigned long) hs, "hookdet");
267 dev_err(&pdev->dev, "hookdet IRQ not available\n");
270 retu_disable_irq(RETU_INT_HOOK);
273 device_remove_file(&pdev->dev, &dev_attr_enable_det);
275 device_remove_file(&pdev->dev, &dev_attr_enable);
277 device_remove_file(&pdev->dev, &dev_attr_hookdet);
279 input_unregister_device(hs->idev);
281 input_free_device(hs->idev);
287 static int retu_headset_remove(struct platform_device *pdev)
289 struct retu_headset *hs = platform_get_drvdata(pdev);
291 device_remove_file(&pdev->dev, &dev_attr_hookdet);
292 device_remove_file(&pdev->dev, &dev_attr_enable);
293 device_remove_file(&pdev->dev, &dev_attr_enable_det);
294 retu_headset_disable(hs);
295 retu_headset_det_disable(hs);
296 retu_free_irq(RETU_INT_HOOK);
297 input_unregister_device(hs->idev);
298 input_free_device(hs->idev);
302 static int retu_headset_suspend(struct platform_device *pdev,
305 struct retu_headset *hs = platform_get_drvdata(pdev);
307 mutex_lock(&hs->mutex);
308 if (hs->bias_enabled)
309 retu_headset_set_bias(0);
310 mutex_unlock(&hs->mutex);
315 static int retu_headset_resume(struct platform_device *pdev)
317 struct retu_headset *hs = platform_get_drvdata(pdev);
319 mutex_lock(&hs->mutex);
320 if (hs->bias_enabled)
321 retu_headset_set_bias(1);
322 mutex_unlock(&hs->mutex);
327 static struct platform_driver retu_headset_driver = {
328 .probe = retu_headset_probe,
329 .remove = retu_headset_remove,
330 .suspend = retu_headset_suspend,
331 .resume = retu_headset_resume,
333 .name = "retu-headset",
337 static int __init retu_headset_init(void)
341 printk(KERN_INFO "Retu/Vilma headset driver initializing\n");
343 r = platform_driver_register(&retu_headset_driver);
350 static void __exit retu_headset_exit(void)
352 platform_driver_unregister(&retu_headset_driver);
355 module_init(retu_headset_init);
356 module_exit(retu_headset_exit);
358 MODULE_DESCRIPTION("Retu/Vilma headset detection");
359 MODULE_LICENSE("GPL");
360 MODULE_AUTHOR("Juha Yrjölä");