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
18 #define DBG(x...) printk(KERN_INFO x)
\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
31 #ifdef CONFIG_SND_SOC_ES8323_PCM
\r
32 extern int set_es8323(int cmd);
\r
35 int modem_sound_spkctl(int status)
\r
37 if(modem_sound->spkctl_io == INVALID_GPIO)
\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
42 gpio_direction_output(modem_sound->spkctl_io,GPIO_LOW); //modem_sound->spkctl_io? GPIO_LOW:GPIO_HIGH);
\r
47 static void modem_sound_delay_power_downup(struct work_struct *work)
\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
55 down(&pdata->power_sem);
\r
56 up(&pdata->power_sem);
\r
59 static int modem_sound_open(struct inode *inode, struct file *filp)
\r
61 DBG("modem_sound_open\n");
\r
66 static ssize_t modem_sound_read(struct file *filp, char __user *ptr, size_t size, loff_t *pos)
\r
69 printk("%s: user space address is NULL\n", __func__);
\r
73 static long modem_sound_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
\r
76 struct modem_sound_data *pdata = modem_sound;
\r
78 DBG("modem_sound_ioctl: cmd = %d arg = %ld\n",cmd, arg);
\r
80 ret = down_interruptible(&pdata->power_sem);
\r
82 printk("%s: down power_sem error ret = %ld\n", __func__, ret);
\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
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
98 modem_sound_spkctl(ENABLE);
\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
106 modem_sound_spkctl(DISABLE);
\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
113 case IOCTL_MODEM_STOP_PHONE:
\r
114 DBG("modem_sound_ioctl: MODEM_STOP_PHONE\n");
\r
117 if (set_codec_for_pcm_modem)
\r
118 set_codec_for_pcm_modem(OFF);
\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
126 modem_sound_spkctl(DISABLE);
\r
131 printk("unknown ioctl cmd!\n");
\r
136 up(&pdata->power_sem);
\r
141 static int modem_sound_release(struct inode *inode, struct file *filp)
\r
143 DBG("modem_sound_release\n");
\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
156 static struct miscdevice modem_sound_dev =
\r
158 .minor = MISC_DYNAMIC_MINOR,
\r
159 .name = "modem_sound",
\r
160 .fops = &modem_sound_fops,
\r
163 static int modem_sound_probe(struct platform_device *pdev)
\r
166 struct modem_sound_data *pdata = pdev->dev.platform_data;
\r
170 ret = misc_register(&modem_sound_dev);
\r
172 printk("modem register err!\n");
\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
183 #ifdef CONFIG_SND_SOC_ES8323_PCM
\r
184 set_codec_for_pcm_modem = set_es8323;
\r
187 printk("%s:modem sound initialized\n",__FUNCTION__);
\r
192 static int modem_sound_suspend(struct platform_device *pdev, pm_message_t state)
\r
194 struct modem_sound_data *pdata = pdev->dev.platform_data;
\r
197 printk("%s: pdata = NULL ...... \n", __func__);
\r
200 printk("%s\n",__FUNCTION__);
\r
204 static int modem_sound_resume(struct platform_device *pdev)
\r
206 struct modem_sound_data *pdata = pdev->dev.platform_data;
\r
209 printk("%s: pdata = NULL ...... \n", __func__);
\r
212 printk("%s\n",__FUNCTION__);
\r
216 static int modem_sound_remove(struct platform_device *pdev)
\r
218 struct modem_sound_data *pdata = pdev->dev.platform_data;
\r
222 misc_deregister(&modem_sound_dev);
\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
233 .name = "modem_sound",
\r
234 .owner = THIS_MODULE,
\r
238 static int __init modem_sound_init(void)
\r
240 return platform_driver_register(&modem_sound_driver);
\r
243 static void __exit modem_sound_exit(void)
\r
245 platform_driver_unregister(&modem_sound_driver);
\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