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