1 /* arch/arm/mach-rockchip/rk28_headset.c
3 * Copyright (C) 2009 Rockchip Corporation.
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/module.h>
17 #include <linux/sysdev.h>
18 #include <linux/device.h>
20 #include <linux/interrupt.h>
21 #include <linux/workqueue.h>
22 #include <linux/irq.h>
23 #include <linux/delay.h>
24 #include <linux/types.h>
25 #include <linux/input.h>
26 #include <linux/platform_device.h>
27 #include <linux/mutex.h>
28 #include <linux/errno.h>
29 #include <linux/err.h>
30 #include <linux/hrtimer.h>
31 #include <linux/switch.h>
32 #include <linux/input.h>
33 #include <linux/debugfs.h>
34 #include <linux/wakelock.h>
36 #include <asm/atomic.h>
37 #include <asm/mach-types.h>
38 #include "rk_headset.h"
39 #include <linux/earlysuspend.h>
43 #define DBG(x...) printk(x)
45 #define DBG(x...) do { } while (0)
48 #define BIT_HEADSET (1 << 0)
49 #define BIT_HEADSET_NO_MIC (1 << 1)
51 struct rk2818_headset_dev{
52 struct switch_dev sdev;
53 int cur_headset_status;
54 int pre_headset_status;
55 struct mutex mutex_lock;
58 static struct rk2818_headset_dev Headset_dev;
59 static struct delayed_work g_headsetobserve_work;
60 static struct rk2818_headset_data *prk2818_headset_info;
61 #if defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_BENGO) || defined(CONFIG_MACH_Z5) || defined(CONFIG_MACH_Z5_V2) || defined(CONFIG_MACH_A22)
62 extern void detect_HSMic(void);
65 int headset_status(void)
67 if(Headset_dev.cur_headset_status & BIT_HEADSET)
73 EXPORT_SYMBOL_GPL(headset_status);
75 static irqreturn_t headset_interrupt(int irq, void *dev_id)
77 // DBG("---headset_interrupt---\n");
78 schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(20));
82 static int headset_change_irqtype(unsigned int irq_type)
85 // DBG("--------%s----------\n",__FUNCTION__);
86 free_irq(prk2818_headset_info->irq,NULL);
88 ret = request_irq(prk2818_headset_info->irq, headset_interrupt, irq_type, NULL, NULL);
91 DBG("headsetobserve: request irq failed\n");
97 static void headsetobserve_work(struct work_struct *work)
101 // DBG("---headsetobserve_work---\n");
102 mutex_lock(&Headset_dev.mutex_lock);
106 level = gpio_get_value(prk2818_headset_info->gpio);
109 printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,prk2818_headset_info->gpio,i);
118 printk("%s:get pin level err!\n",__FUNCTION__);
122 switch(prk2818_headset_info->headset_in_type)
124 case HEADSET_IN_HIGH:
127 DBG("--- HEADSET_IN_HIGH headset in---\n");
128 Headset_dev.cur_headset_status = BIT_HEADSET;
129 headset_change_irqtype(IRQF_TRIGGER_FALLING);//
133 DBG("---HEADSET_IN_HIGH headset out---\n");
134 Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
135 headset_change_irqtype(IRQF_TRIGGER_RISING);//
141 DBG("---HEADSET_IN_LOW headset in---\n");
142 Headset_dev.cur_headset_status = BIT_HEADSET;
143 headset_change_irqtype(IRQF_TRIGGER_RISING);//
147 DBG("---HEADSET_IN_LOW headset out---\n");
148 Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
149 headset_change_irqtype(IRQF_TRIGGER_FALLING);//
153 DBG("---- ERROR: on headset headset_in_type error -----\n");
157 if(Headset_dev.cur_headset_status != Headset_dev.pre_headset_status)
159 Headset_dev.pre_headset_status = Headset_dev.cur_headset_status;
160 switch_set_state(&Headset_dev.sdev, Headset_dev.cur_headset_status);
161 DBG("Headset_dev.cur_headset_status = %d\n",Headset_dev.cur_headset_status);
162 #if defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_BENGO) || defined(CONFIG_MACH_Z5) || defined(CONFIG_MACH_Z5_V2) || defined(CONFIG_MACH_A22)
166 mutex_unlock(&Headset_dev.mutex_lock);
169 static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
171 return sprintf(buf, "Headset\n");
174 #ifdef CONFIG_HAS_EARLYSUSPEND
175 static void headset_early_resume(struct early_suspend *h)
177 schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(10));
178 //DBG(">>>>>headset_early_resume\n");
181 static struct early_suspend hs_early_suspend;
184 static int rockchip_headsetobserve_probe(struct platform_device *pdev)
188 DBG("RockChip headset observe driver\n");
189 prk2818_headset_info = pdev->dev.platform_data;
191 Headset_dev.cur_headset_status = 0;
192 Headset_dev.pre_headset_status = 0;
193 Headset_dev.sdev.name = "h2w";
194 Headset_dev.sdev.print_name = h2w_print_name;
195 mutex_init(&Headset_dev.mutex_lock);
197 ret = switch_dev_register(&Headset_dev.sdev);
201 INIT_DELAYED_WORK(&g_headsetobserve_work, headsetobserve_work);
203 ret = gpio_request(prk2818_headset_info->gpio, "headset_det");
206 DBG("headsetobserve: request gpio_request failed\n");
209 gpio_pull_updown(prk2818_headset_info->gpio, GPIONormal);
210 gpio_direction_input(prk2818_headset_info->gpio);
211 prk2818_headset_info->irq = gpio_to_irq(prk2818_headset_info->gpio);
213 if(prk2818_headset_info->headset_in_type == HEADSET_IN_HIGH)
214 prk2818_headset_info->irq_type = IRQF_TRIGGER_RISING;
216 prk2818_headset_info->irq_type = IRQF_TRIGGER_FALLING;
217 ret = request_irq(prk2818_headset_info->irq, headset_interrupt, prk2818_headset_info->irq_type, NULL, NULL);
220 DBG("headsetobserve: request irq failed\n");
224 schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(500));
226 #ifdef CONFIG_HAS_EARLYSUSPEND
227 hs_early_suspend.suspend = NULL;
228 hs_early_suspend.resume = headset_early_resume;
229 hs_early_suspend.level = ~0x0;
230 register_early_suspend(&hs_early_suspend);
236 static struct platform_driver rockchip_headsetobserve_driver = {
237 .probe = rockchip_headsetobserve_probe,
239 .name = "rk2818_headsetdet",
240 .owner = THIS_MODULE,
245 static int __init rockchip_headsetobserve_init(void)
247 platform_driver_register(&rockchip_headsetobserve_driver);
250 module_init(rockchip_headsetobserve_init);
251 MODULE_DESCRIPTION("Rockchip Headset Driver");
252 MODULE_LICENSE("GPL");