phonepad:add modem_sound and headset
[firefly-linux-kernel-4.4.55.git] / drivers / misc / modem_sound.c
1 #include <linux/input.h>\r
2 #include <linux/module.h>\r
3 #include <linux/init.h>\r
4 #include <linux/interrupt.h>\r
5 #include <linux/kernel.h>\r
6 #include <linux/fcntl.h>\r
7 #include <linux/delay.h>\r
8 #include <linux/device.h>\r
9 #include <linux/miscdevice.h>\r
10 #include <asm/types.h>\r
11 #include <mach/gpio.h>\r
12 #include <mach/iomux.h>\r
13 #include <linux/platform_device.h>\r
14 #include <asm/uaccess.h>\r
15 #include <linux/wait.h>\r
16 #include "modem_sound.h"\r
17 #if 0\r
18 #define DBG(x...)       printk(KERN_INFO x)\r
19 #else\r
20 #define DBG(x...)\r
21 #endif\r
22 #define ENABLE             1\r
23 #define DISABLE            0\r
24 \r
25 static struct modem_sound_data *modem_sound;\r
26 #if defined(CONFIG_SND_RK_SOC_RK2928)|| defined(CONFIG_SND_RK29_SOC_RK610)\r
27 extern void call_set_spk(int on);\r
28 #endif\r
29 #define HP_MIC 0\r
30 #define MAIN_MIC 1\r
31 #if defined(CONFIG_MODEM_MIC_SWITCH)\r
32 extern void Modem_Mic_switch(int value);\r
33 extern void Modem_Mic_release(void);\r
34 void Modem_Sound_Mic_switch(int value)\r
35 {\r
36         Modem_Mic_switch(value);\r
37 }\r
38 void Modem_Sound_Mic_release()\r
39 {\r
40         Modem_Mic_release();\r
41 }\r
42 #else\r
43 void Modem_Sound_Mic_switch(int value)\r
44 {\r
45 }\r
46 void Modem_Sound_Mic_release()\r
47 {\r
48 }\r
49 #endif\r
50 \r
51 int modem_sound_spkctl(int status)\r
52 {\r
53         if(status == ENABLE)\r
54                 gpio_direction_output(modem_sound->spkctl_io,GPIO_HIGH);//modem_sound->spkctl_io? GPIO_HIGH:GPIO_LOW);\r
55         else \r
56                 gpio_direction_output(modem_sound->spkctl_io,GPIO_LOW); //modem_sound->spkctl_io? GPIO_LOW:GPIO_HIGH);\r
57                         \r
58         return 0;\r
59 }\r
60 \r
61 static void modem_sound_delay_power_downup(struct work_struct *work)\r
62 {\r
63         struct modem_sound_data *pdata = container_of(work, struct modem_sound_data, work);\r
64         if (pdata == NULL) {\r
65                 printk("%s: pdata = NULL\n", __func__);\r
66                 return;\r
67         }\r
68 \r
69         down(&pdata->power_sem);\r
70         up(&pdata->power_sem);\r
71 }\r
72 \r
73 static int modem_sound_open(struct inode *inode, struct file *filp)\r
74 {\r
75     DBG("modem_sound_open\n");\r
76 \r
77         return 0;\r
78 }\r
79 \r
80 static ssize_t modem_sound_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)\r
81 {\r
82         if (ptr == NULL)\r
83                 printk("%s: user space address is NULL\n", __func__);\r
84         return sizeof(int);\r
85 }\r
86 \r
87 static long modem_sound_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)\r
88 {\r
89         long ret = 0;\r
90         struct modem_sound_data *pdata = modem_sound;\r
91 \r
92         DBG("modem_sound_ioctl: cmd = %d arg = %ld\n",cmd, arg);\r
93 \r
94         ret = down_interruptible(&pdata->power_sem);\r
95         if (ret < 0) {\r
96                 printk("%s: down power_sem error ret = %ld\n", __func__, ret);\r
97                 return ret;\r
98         }\r
99 \r
100         switch (cmd){\r
101                 case IOCTL_MODEM_EAR_PHOEN:\r
102                         DBG("modem_sound_ioctl: MODEM_EAR_PHONE\n");\r
103                         Modem_Sound_Mic_switch(MAIN_MIC);\r
104                         call_set_spk(3);\r
105                         modem_sound_spkctl(DISABLE);\r
106                         break;\r
107                 case IOCTL_MODEM_SPK_PHONE:\r
108                         DBG("modem_sound_ioctl: MODEM_SPK_PHONE\n");\r
109                         Modem_Sound_Mic_switch(MAIN_MIC);\r
110                         call_set_spk(1);\r
111                         modem_sound_spkctl(ENABLE);\r
112                         break;\r
113                 case IOCTL_MODEM_HP_WITHMIC_PHONE:\r
114                         DBG("modem_sound_ioctl: MODEM_HP_WITHMIC_PHONE\n");\r
115                         Modem_Sound_Mic_switch(HP_MIC);\r
116                         call_set_spk(2);\r
117                         modem_sound_spkctl(DISABLE);\r
118                         break;\r
119                         \r
120                 case IOCTL_MODEM_BT_PHONE:\r
121                         call_set_spk(3);\r
122                         modem_sound_spkctl(DISABLE);\r
123                         DBG("modem_sound_ioctl: MODEM_BT_PHONE\n");\r
124                         break;\r
125                 case IOCTL_MODEM_STOP_PHONE:\r
126                         DBG("modem_sound_ioctl: MODEM_STOP_PHONE\n");\r
127                         Modem_Sound_Mic_release();\r
128                         call_set_spk(0);\r
129                         modem_sound_spkctl(ENABLE);\r
130                         break;\r
131                 case IOCTL_MODEM_HP_NOMIC_PHONE:\r
132                         DBG("modem_sound_ioctl: MODEM_HP_NOMIC_PHONE\n");\r
133                         Modem_Sound_Mic_switch(MAIN_MIC);\r
134                         call_set_spk(2);\r
135                         modem_sound_spkctl(DISABLE);\r
136                         break;\r
137 \r
138 \r
139                 default:\r
140                         printk("unknown ioctl cmd!\n");\r
141                         ret = -EINVAL;\r
142                         break;\r
143         }\r
144 \r
145         up(&pdata->power_sem);\r
146 \r
147         return ret;\r
148 }\r
149 \r
150 static int modem_sound_release(struct inode *inode, struct file *filp)\r
151 {\r
152     DBG("modem_sound_release\n");\r
153     \r
154         return 0;\r
155 }\r
156 \r
157 static struct file_operations modem_sound_fops = {\r
158         .owner   = THIS_MODULE,\r
159         .open    = modem_sound_open,\r
160         .read    = modem_sound_read,\r
161         .unlocked_ioctl   = modem_sound_ioctl,\r
162         .release = modem_sound_release,\r
163 };\r
164 \r
165 static struct miscdevice modem_sound_dev = \r
166 {\r
167     .minor = MISC_DYNAMIC_MINOR,\r
168     .name = "modem_sound",\r
169     .fops = &modem_sound_fops,\r
170 };\r
171 \r
172 static int modem_sound_probe(struct platform_device *pdev)\r
173 {\r
174         int ret = 0;\r
175         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
176         if(!pdata)\r
177                 return -1;\r
178                 \r
179         ret = misc_register(&modem_sound_dev);\r
180         if (ret < 0){\r
181                 printk("modem register err!\n");\r
182                 return ret;\r
183         }\r
184         \r
185         sema_init(&pdata->power_sem,1);\r
186         pdata->wq = create_freezable_workqueue("modem_sound");\r
187         INIT_WORK(&pdata->work, modem_sound_delay_power_downup);\r
188         modem_sound = pdata;\r
189         printk("%s:modem sound initialized\n",__FUNCTION__);\r
190 \r
191         return ret;\r
192 }\r
193 \r
194 static int modem_sound_suspend(struct platform_device *pdev,  pm_message_t state)\r
195 {\r
196         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
197 \r
198         if(!pdata) {\r
199                 printk("%s: pdata = NULL ...... \n", __func__);\r
200                 return -1;\r
201         }\r
202         printk("%s\n",__FUNCTION__);\r
203         return 0;       \r
204 }\r
205 \r
206 static int modem_sound_resume(struct platform_device *pdev)\r
207 {\r
208         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
209 \r
210         if(!pdata) {\r
211                 printk("%s: pdata = NULL ...... \n", __func__);\r
212                 return -1;\r
213         }\r
214         printk("%s\n",__FUNCTION__);\r
215         return 0;\r
216 }\r
217 \r
218 static int modem_sound_remove(struct platform_device *pdev)\r
219 {\r
220         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
221         if(!pdata)\r
222                 return -1;\r
223 \r
224         misc_deregister(&modem_sound_dev);\r
225 \r
226         return 0;\r
227 }\r
228 \r
229 static struct platform_driver modem_sound_driver = {\r
230         .probe  = modem_sound_probe,\r
231         .remove = modem_sound_remove,\r
232         .suspend        = modem_sound_suspend,\r
233         .resume         = modem_sound_resume,\r
234         .driver = {\r
235                 .name   = "modem_sound",\r
236                 .owner  = THIS_MODULE,\r
237         },\r
238 };\r
239 \r
240 static int __init modem_sound_init(void)\r
241 {\r
242         return platform_driver_register(&modem_sound_driver);\r
243 }\r
244 \r
245 static void __exit modem_sound_exit(void)\r
246 {\r
247         platform_driver_unregister(&modem_sound_driver);\r
248 }\r
249 \r
250 module_init(modem_sound_init);\r
251 module_exit(modem_sound_exit);\r
252 MODULE_DESCRIPTION ("modem sound driver");\r
253 MODULE_LICENSE("GPL");\r
254 \r