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