kernel 3.10 headset : headset driver support
[firefly-linux-kernel-4.4.55.git] / drivers / headset_observe / rockchip_headset_core.c
1 /* 
2  * Copyright (C) 2014 Rockchip Corporation.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/init.h>
18 #include <linux/delay.h>
19 #include <linux/pm.h>
20 #include <linux/i2c.h>
21 #include <linux/spi/spi.h>
22 #include <linux/platform_device.h>
23 #include <linux/errno.h>
24 #include <linux/err.h>
25 #include <linux/debugfs.h>
26 #include "rk_headset.h"
27 #include <linux/of_gpio.h>
28 #include <linux/gpio.h>
29 /* Debug */
30 #if 0
31 #define DBG(x...) printk(x)
32 #else
33 #define DBG(x...) do { } while (0)
34 #endif
35
36 /*
37         rockchip_headset {
38                 compatible = "rockchip_headset";
39                 headset_gpio = ;
40                 headset_insert_type = ; // 0 = low  1 = high
41                 hook_gpio = ;
42                 hook_down_type = ; //interrupt hook key down status  
43                 hook_adc_chn = ;//adc channel           
44                 mic_switch_gpio = ;
45                 hp_mic_io_value = ;
46                 main_mic_io_value = ;
47                 hook_key_code = KEY_MEDIA;
48         };
49 */
50 struct rk_headset_pdata *pdata_info;
51
52 static int rockchip_headset_probe(struct platform_device *pdev)
53 {
54         struct device_node *node = pdev->dev.of_node;
55         struct rk_headset_pdata *pdata;
56         int ret;
57         enum of_gpio_flags flags;
58
59         pdata = kzalloc(sizeof(struct rk_headset_pdata), GFP_KERNEL);
60         if (pdata == NULL) {
61                 printk("%s failed to allocate driver data\n",__FUNCTION__);
62                 return -ENOMEM;
63         }
64         memset(pdata,0,sizeof(struct rk_headset_pdata));
65         pdata_info = pdata;
66 //headset
67         ret = of_get_named_gpio_flags(node, "headset_gpio", 0, &flags);
68         if (ret < 0) {
69                 printk("%s() Can not read property headset_gpio\n", __FUNCTION__);
70                 goto err;
71         } else {
72                 pdata->headset_gpio = ret;
73                 ret = devm_gpio_request(&pdev->dev, pdata->headset_gpio, "headset_gpio");
74                 if(ret < 0){
75                         printk("%s() devm_gpio_request headset_gpio request ERROR\n", __FUNCTION__);
76                         goto err;
77                 }
78                 //gpio_pull_updown(pdata->headset_gpio, PullDisable);
79                 ret = gpio_direction_input(pdata->headset_gpio); 
80                 if(ret < 0){
81                         printk("%s() gpio_direction_input headset_gpio set ERROR\n", __FUNCTION__);
82                         goto err;
83                 }
84         }
85         
86         ret = of_property_read_u32(node, "headset_insert_type", &pdata->headset_insert_type);
87         if (ret < 0) {
88                 DBG("%s() have not set headset_insert_type,set >headset< insert type low level default\n", __FUNCTION__);
89                 pdata->headset_insert_type = 0;
90         }
91 //hook
92         ret = of_get_named_gpio_flags(node, "hook_gpio", 0, &pdata->hook_gpio);
93         if (ret < 0) {
94                 DBG("%s() Can not read property hook_gpio\n", __FUNCTION__);
95                 pdata->hook_gpio = 0;
96                 //adc mode
97                 ret = of_property_read_u32(node, "hook_adc_chn", &pdata->hook_adc_chn);
98                 if (ret < 0) {
99                         DBG("%s() have not set hook_adc_chn\n", __FUNCTION__);
100                         pdata->hook_adc_chn = -1;
101                 }
102         } else {
103                 ret = of_property_read_u32(node, "hook_down_type", &pdata->hook_down_type);
104                 if (ret < 0) {
105                         DBG("%s() have not set hook_down_type,set >hook< insert type low level default\n", __FUNCTION__);
106                         pdata->hook_down_type = 0;
107                 }
108                 ret = devm_gpio_request(&pdev->dev, pdata->hook_gpio, "hook_gpio");
109                 if(ret < 0){
110                         printk("%s() devm_gpio_request hook_gpio request ERROR\n", __FUNCTION__);
111                         goto err;
112                 }
113                 //gpio_pull_updown(pdata->hook_gpio, PullDisable);
114                 ret = gpio_direction_input(pdata->hook_gpio); 
115                 if(ret < 0){
116                         printk("%s() gpio_direction_input hook_gpio set ERROR\n", __FUNCTION__);
117                         goto err;
118                 }
119         }
120 #ifdef CONFIG_MODEM_MIC_SWITCH
121 //mic
122         ret = of_get_named_gpio_flags(node, "mic_switch_gpio", 0, &flags);
123         if (ret < 0) {
124                 DBG("%s() Can not read property mic_switch_gpio\n", __FUNCTION__);
125         } else {
126                 pdata->headset_gpio = ret;
127                 ret = of_property_read_u32(node, "hp_mic_io_value", &pdata->hp_mic_io_value);
128                 if (ret < 0) {
129                         DBG("%s() have not set hp_mic_io_value ,so default set pull down low level\n", __FUNCTION__);
130                         pdata->hp_mic_io_value = 0;
131                 }
132                 ret = of_property_read_u32(node, "main_mic_io_value", &pdata->main_mic_io_value);
133                 if (ret < 0) {
134                         DBG("%s() have not set main_mic_io_value ,so default set pull down low level\n", __FUNCTION__);
135                         pdata->main_mic_io_value = 1;
136                 }
137         }
138 #endif
139         if(pdata->hook_adc_chn >= 0)
140         {//hook adc mode
141                 printk("%s() headset have hook adc mode\n",__FUNCTION__);
142                 ret = rk_headset_adc_probe(pdev,pdata);
143                 if(ret < 0)
144                 {
145                         goto err;
146                 }               
147         }
148         else
149         {//hook interrupt mode and not hook
150                 printk("%s() headset have %s mode\n",__FUNCTION__,pdata->hook_gpio?"interrupt hook":"no hook");
151                 ret = rk_headset_probe(pdev,pdata);
152                 if(ret < 0)
153                 {
154                         goto err;
155                 }
156         }
157
158         return 0;
159 err:
160         kfree(pdata);
161         return ret;
162 }
163
164 static int rockchip_headset_remove(struct platform_device *pdev)
165 {
166         if(pdata_info)
167                 kfree(pdata_info);
168         return 0;
169 }
170
171 static int rockchip_headset_suspend(struct platform_device *pdev, pm_message_t state)
172 {
173         DBG("%s----%d\n",__FUNCTION__,__LINE__);
174         if(pdata_info->hook_adc_chn >= 0)
175         {
176                 return rk_headset_adc_suspend(pdev,state);
177         }
178         return 0;
179 }
180
181 static int rockchip_headset_resume(struct platform_device *pdev)
182 {
183         DBG("%s----%d\n",__FUNCTION__,__LINE__);        
184         if(pdata_info->hook_adc_chn >= 0)
185         {
186                 return rk_headset_adc_resume(pdev);
187         }       
188         return 0;
189 }
190
191 static const struct of_device_id rockchip_headset_of_match[] = {
192         { .compatible = "rockchip_headset", },
193         {},
194 };
195 MODULE_DEVICE_TABLE(of, rockchip_headset_of_match);
196
197 static struct platform_driver rockchip_headset_driver = {
198         .probe  = rockchip_headset_probe,
199         .remove = rockchip_headset_remove,
200         .resume =       rockchip_headset_resume,        
201         .suspend =      rockchip_headset_suspend,       
202         .driver = {
203                 .name   = "rockchip_headset",
204                 .owner  = THIS_MODULE,
205                 .of_match_table = of_match_ptr(rockchip_headset_of_match),              
206         },
207 };
208
209 static int __init rockchip_headset_init(void)
210 {
211         platform_driver_register(&rockchip_headset_driver);
212         return 0;
213 }
214
215 static void __exit rockchip_headset_exit(void)
216 {
217         platform_driver_unregister(&rockchip_headset_driver);
218 }
219
220 late_initcall(rockchip_headset_init);
221 MODULE_DESCRIPTION("Rockchip Headset Core Driver");
222 MODULE_LICENSE("GPL");