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;
184 retu_ack_irq(RETU_INT_HOOK);
185 spin_lock_irqsave(&hs->lock, flags);
187 /* Headset button was just pressed down. */
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;
209 spin_lock_irqsave(&hs->lock, flags);
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;
222 hs = kzalloc(sizeof(*hs), GFP_KERNEL);
228 hs->idev = input_allocate_device();
229 if (hs->idev == NULL) {
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);
241 r = device_create_file(&pdev->dev, &dev_attr_hookdet);
244 r = device_create_file(&pdev->dev, &dev_attr_enable);
247 r = device_create_file(&pdev->dev, &dev_attr_enable_det);
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,
256 setup_timer(&hs->detect_timer, retu_headset_detect_timer,
259 r = retu_request_irq(RETU_INT_HOOK, retu_headset_hook_interrupt,
260 (unsigned long) hs, "hookdet");
262 dev_err(&pdev->dev, "hookdet IRQ not available\n");
265 retu_disable_irq(RETU_INT_HOOK);
268 device_remove_file(&pdev->dev, &dev_attr_enable_det);
270 device_remove_file(&pdev->dev, &dev_attr_enable);
272 device_remove_file(&pdev->dev, &dev_attr_hookdet);
274 input_unregister_device(hs->idev);
276 input_free_device(hs->idev);
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);
297 static int retu_headset_suspend(struct platform_device *pdev,
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);
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);
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,
328 .name = "retu-headset",
332 static int __init retu_headset_init(void)
336 printk(KERN_INFO "Retu/Vilma headset driver initializing\n");
338 r = platform_driver_register(&retu_headset_driver);
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ä");