b767cb964617f54830189674c137121a37a3d3dd
[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 1\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 #ifdef CONFIG_SND_RK_SOC_RK2928\r
27 extern void call_set_spk(bool on);\r
28 #endif\r
29 int modem_sound_spkctl(int status)\r
30 {\r
31         if(status == ENABLE)\r
32                 gpio_direction_output(modem_sound->spkctl_io,GPIO_HIGH);//modem_sound->spkctl_io? GPIO_HIGH:GPIO_LOW);\r
33         else \r
34                 gpio_direction_output(modem_sound->spkctl_io,GPIO_LOW); //modem_sound->spkctl_io? GPIO_LOW:GPIO_HIGH);\r
35                         \r
36         return 0;\r
37 }\r
38 \r
39 static void modem_sound_delay_power_downup(struct work_struct *work)\r
40 {\r
41         struct modem_sound_data *pdata = container_of(work, struct modem_sound_data, work);\r
42         if (pdata == NULL) {\r
43                 printk("%s: pdata = NULL\n", __func__);\r
44                 return;\r
45         }\r
46 \r
47         down(&pdata->power_sem);\r
48         up(&pdata->power_sem);\r
49 }\r
50 \r
51 static int modem_sound_open(struct inode *inode, struct file *filp)\r
52 {\r
53     DBG("modem_sound_open\n");\r
54 \r
55         return 0;\r
56 }\r
57 \r
58 static ssize_t modem_sound_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)\r
59 {\r
60         if (ptr == NULL)\r
61                 printk("%s: user space address is NULL\n", __func__);\r
62         return sizeof(int);\r
63 }\r
64 \r
65 static long modem_sound_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)\r
66 {\r
67         long ret = 0;\r
68         struct modem_sound_data *pdata = modem_sound;\r
69 \r
70         DBG("modem_sound_ioctl: cmd = %d arg = %ld\n",cmd, arg);\r
71 \r
72         ret = down_interruptible(&pdata->power_sem);\r
73         if (ret < 0) {\r
74                 printk("%s: down power_sem error ret = %ld\n", __func__, ret);\r
75                 return ret;\r
76         }\r
77 \r
78         switch (cmd){\r
79                 case IOCTL_MODEM_EAR_PHOEN:\r
80                         DBG("modem_sound_ioctl: MODEM_EAR_PHONE\n");\r
81                         call_set_spk(0);\r
82                         modem_sound_spkctl(DISABLE);\r
83                         break;\r
84                 case IOCTL_MODEM_SPK_PHONE:\r
85                         DBG("modem_sound_ioctl: MODEM_SPK_PHONE\n");\r
86                         call_set_spk(0);\r
87                         modem_sound_spkctl(ENABLE);\r
88                         break;\r
89                 case IOCTL_MODEM_HP_PHONE:\r
90                         DBG("modem_sound_ioctl: MODEM_HP_PHONE\n");\r
91                         call_set_spk(0);\r
92                         modem_sound_spkctl(DISABLE);\r
93                         break;\r
94                         \r
95                 case IOCTL_MODEM_BT_PHONE:\r
96                         call_set_spk(0);\r
97                         modem_sound_spkctl(DISABLE);\r
98                         DBG("modem_sound_ioctl: MODEM_BT_PHONE\n");\r
99                         break;\r
100                 case IOCTL_MODEM_STOP_PHONE:\r
101                         DBG("modem_sound_ioctl: MODEM_STOP_PHONE\n");\r
102                         call_set_spk(1);\r
103                         break;\r
104 \r
105                 default:\r
106                         printk("unknown ioctl cmd!\n");\r
107                         up(&pdata->power_sem);\r
108                         ret = -EINVAL;\r
109                         break;\r
110         }\r
111 \r
112         up(&pdata->power_sem);\r
113 \r
114         return ret;\r
115 }\r
116 \r
117 static int modem_sound_release(struct inode *inode, struct file *filp)\r
118 {\r
119     DBG("modem_sound_release\n");\r
120     \r
121         return 0;\r
122 }\r
123 \r
124 static struct file_operations modem_sound_fops = {\r
125         .owner   = THIS_MODULE,\r
126         .open    = modem_sound_open,\r
127         .read    = modem_sound_read,\r
128         .unlocked_ioctl   = modem_sound_ioctl,\r
129         .release = modem_sound_release,\r
130 };\r
131 \r
132 static struct miscdevice modem_sound_dev = \r
133 {\r
134     .minor = MISC_DYNAMIC_MINOR,\r
135     .name = "modem_sound",\r
136     .fops = &modem_sound_fops,\r
137 };\r
138 \r
139 static int modem_sound_probe(struct platform_device *pdev)\r
140 {\r
141         int ret = 0;\r
142         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
143         if(!pdata)\r
144                 return -1;\r
145                 \r
146         ret = misc_register(&modem_sound_dev);\r
147         if (ret < 0){\r
148                 printk("modem register err!\n");\r
149                 return ret;\r
150         }\r
151         \r
152         sema_init(&pdata->power_sem,1);\r
153         pdata->wq = create_freezable_workqueue("modem_sound");\r
154         INIT_WORK(&pdata->work, modem_sound_delay_power_downup);\r
155         modem_sound = pdata;\r
156         printk("%s:modem sound initialized\n",__FUNCTION__);\r
157 \r
158         return ret;\r
159 }\r
160 \r
161 static int modem_sound_suspend(struct platform_device *pdev,  pm_message_t state)\r
162 {\r
163         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
164 \r
165         if(!pdata) {\r
166                 printk("%s: pdata = NULL ...... \n", __func__);\r
167                 return -1;\r
168         }\r
169         printk("%s\n",__FUNCTION__);\r
170         return 0;       \r
171 }\r
172 \r
173 static int modem_sound_resume(struct platform_device *pdev)\r
174 {\r
175         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
176 \r
177         if(!pdata) {\r
178                 printk("%s: pdata = NULL ...... \n", __func__);\r
179                 return -1;\r
180         }\r
181         printk("%s\n",__FUNCTION__);\r
182         return 0;\r
183 }\r
184 \r
185 static int modem_sound_remove(struct platform_device *pdev)\r
186 {\r
187         struct modem_sound_data *pdata = pdev->dev.platform_data;\r
188         if(!pdata)\r
189                 return -1;\r
190 \r
191         misc_deregister(&modem_sound_dev);\r
192 \r
193         return 0;\r
194 }\r
195 \r
196 static struct platform_driver modem_sound_driver = {\r
197         .probe  = modem_sound_probe,\r
198         .remove = modem_sound_remove,\r
199         .suspend        = modem_sound_suspend,\r
200         .resume         = modem_sound_resume,\r
201         .driver = {\r
202                 .name   = "modem_sound",\r
203                 .owner  = THIS_MODULE,\r
204         },\r
205 };\r
206 \r
207 static int __init modem_sound_init(void)\r
208 {\r
209         return platform_driver_register(&modem_sound_driver);\r
210 }\r
211 \r
212 static void __exit modem_sound_exit(void)\r
213 {\r
214         platform_driver_unregister(&modem_sound_driver);\r
215 }\r
216 \r
217 module_init(modem_sound_init);\r
218 module_exit(modem_sound_exit);\r
219 MODULE_DESCRIPTION ("modem sound driver");\r
220 MODULE_LICENSE("GPL");\r
221 \r