rk29:headset driver kconfig and makefile fix
[firefly-linux-kernel-4.4.55.git] / drivers / headset_observe / rk_headset.c
1 /* arch/arm/mach-rockchip/rk28_headset.c
2  *
3  * Copyright (C) 2009 Rockchip Corporation.
4  *
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.
8  *
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.
13  *
14  */
15
16 #include <linux/module.h>
17 #include <linux/sysdev.h>
18 #include <linux/device.h>
19 #include <linux/fs.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>
35 #include <asm/gpio.h>
36 #include <asm/atomic.h>
37 #include <asm/mach-types.h>
38 #include "rk_headset.h"
39 #include <linux/earlysuspend.h>
40
41 /* Debug */
42 #if 1
43 #define DBG(x...) printk(x)
44 #else
45 #define DBG(x...) do { } while (0)
46 #endif
47
48 #define BIT_HEADSET             (1 << 0)
49 #define BIT_HEADSET_NO_MIC      (1 << 1)
50
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;
56 };
57
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);
63 #endif
64
65 int headset_status(void)
66 {           
67         if(Headset_dev.cur_headset_status & BIT_HEADSET)                        
68                 return 1;
69         else
70                 return 0;
71 }
72
73 EXPORT_SYMBOL_GPL(headset_status);
74
75 static irqreturn_t headset_interrupt(int irq, void *dev_id)
76 {
77 //      DBG("---headset_interrupt---\n");       
78         schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(20));
79         return IRQ_HANDLED;
80 }
81
82 static int headset_change_irqtype(unsigned int irq_type)
83 {
84         int ret = 0;
85 //      DBG("--------%s----------\n",__FUNCTION__);
86         free_irq(prk2818_headset_info->irq,NULL);
87         
88         ret = request_irq(prk2818_headset_info->irq, headset_interrupt, irq_type, NULL, NULL);
89         if (ret) 
90         {
91                 DBG("headsetobserve: request irq failed\n");
92         return ret;
93         }
94         return ret;
95 }
96
97 static void headsetobserve_work(struct work_struct *work)
98 {
99         int i,level = 0;
100
101 //      DBG("---headsetobserve_work---\n");
102         mutex_lock(&Headset_dev.mutex_lock);
103
104         for(i=0; i<3; i++)
105         {
106                 level = gpio_get_value(prk2818_headset_info->gpio);
107                 if(level < 0)
108                 {
109                         printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,prk2818_headset_info->gpio,i);
110                         msleep(1);
111                         continue;
112                 }
113                 else
114                 break;
115         }
116         if(level < 0)
117         {
118                 printk("%s:get pin level  err!\n",__FUNCTION__);
119                 return;
120         }
121         
122         switch(prk2818_headset_info->headset_in_type)
123         {
124                 case HEADSET_IN_HIGH:
125                         if(level > 0)
126                         {//in--High level
127                                 DBG("--- HEADSET_IN_HIGH headset in---\n");
128                                 Headset_dev.cur_headset_status = BIT_HEADSET;
129                                 headset_change_irqtype(IRQF_TRIGGER_FALLING);//
130                         }
131                         else if(level == 0)
132                         {//out--Low level
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);//
136                         }
137                         break;
138                 case HEADSET_IN_LOW:
139                         if(level == 0)
140                         {//in--High level
141                                 DBG("---HEADSET_IN_LOW headset in---\n");
142                                 Headset_dev.cur_headset_status = BIT_HEADSET;
143                                 headset_change_irqtype(IRQF_TRIGGER_RISING);//
144                         }
145                         else if(level > 0)
146                         {//out--High level
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);//
150                         }
151                         break;                  
152                 default:
153                         DBG("---- ERROR: on headset headset_in_type error -----\n");
154                         break;                  
155         }
156
157         if(Headset_dev.cur_headset_status != Headset_dev.pre_headset_status)
158         {
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)
163                 detect_HSMic();
164 #endif
165         }
166         mutex_unlock(&Headset_dev.mutex_lock);  
167 }
168
169 static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
170 {
171         return sprintf(buf, "Headset\n");
172 }
173
174 #ifdef CONFIG_HAS_EARLYSUSPEND
175 static void headset_early_resume(struct early_suspend *h)
176 {
177         schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(10));
178         //DBG(">>>>>headset_early_resume\n");
179 }
180
181 static struct early_suspend hs_early_suspend;
182 #endif
183
184 static int rockchip_headsetobserve_probe(struct platform_device *pdev)
185 {
186         int ret;
187
188         DBG("RockChip headset observe driver\n");
189         prk2818_headset_info = pdev->dev.platform_data;
190         
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);
196
197         ret = switch_dev_register(&Headset_dev.sdev);
198         if (ret < 0)
199                 return ret;
200
201         INIT_DELAYED_WORK(&g_headsetobserve_work, headsetobserve_work);
202     
203         ret = gpio_request(prk2818_headset_info->gpio, "headset_det");
204         if (ret) 
205         {
206                 DBG("headsetobserve: request gpio_request failed\n");
207                 return ret;
208         }
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);
212
213         if(prk2818_headset_info->headset_in_type == HEADSET_IN_HIGH)
214                 prk2818_headset_info->irq_type = IRQF_TRIGGER_RISING;
215         else
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);
218         if (ret) 
219         {
220                 DBG("headsetobserve: request irq failed\n");
221         return ret;
222         }
223
224         schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(500));
225         
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);
231 #endif
232
233         return 0;       
234 }
235
236 static struct platform_driver rockchip_headsetobserve_driver = {
237         .probe  = rockchip_headsetobserve_probe,
238         .driver = {
239                 .name   = "rk2818_headsetdet",
240                 .owner  = THIS_MODULE,
241         },
242 };
243
244
245 static int __init rockchip_headsetobserve_init(void)
246 {
247         platform_driver_register(&rockchip_headsetobserve_driver);
248         return 0;
249 }
250 module_init(rockchip_headsetobserve_init);
251 MODULE_DESCRIPTION("Rockchip Headset Driver");
252 MODULE_LICENSE("GPL");