blob: ab1df3992e4a15fef2e80d561751b5b70c6bd50a [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Copyright (C) 2009 Google, Inc.
3 * Copyright (C) 2009 HTC Corporation
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/fs.h>
17#include <linux/module.h>
18#include <linux/miscdevice.h>
19#include <linux/uaccess.h>
20#include <linux/msm_audio.h>
21
22#include <mach/msm_qdsp6_audio.h>
23#include <mach/debug_mm.h>
24
25#define BUFSZ (0)
26
27static DEFINE_MUTEX(voice_lock);
28static int voice_started;
29
30static struct audio_client *voc_tx_clnt;
31static struct audio_client *voc_rx_clnt;
32
33static int q6_voice_start(void)
34{
35 int rc = 0;
36
37 mutex_lock(&voice_lock);
38
39 if (voice_started) {
40 pr_err("[%s:%s] busy\n", __MM_FILE__, __func__);
41 rc = -EBUSY;
42 goto done;
43 }
44
45 voc_tx_clnt = q6voice_open(AUDIO_FLAG_WRITE);
46 if (!voc_tx_clnt) {
47 pr_err("[%s:%s] open voice tx failed.\n", __MM_FILE__,
48 __func__);
49 rc = -ENOMEM;
50 goto done;
51 }
52
53 voc_rx_clnt = q6voice_open(AUDIO_FLAG_READ);
54 if (!voc_rx_clnt) {
55 pr_err("[%s:%s] open voice rx failed.\n", __MM_FILE__,
56 __func__);
57 q6voice_close(voc_tx_clnt);
58 rc = -ENOMEM;
59 }
60
61 voice_started = 1;
62done:
63 mutex_unlock(&voice_lock);
64 return rc;
65}
66
67static int q6_voice_stop(void)
68{
69 mutex_lock(&voice_lock);
70 if (voice_started) {
71 q6voice_close(voc_tx_clnt);
72 q6voice_close(voc_rx_clnt);
73 voice_started = 0;
74 }
75 mutex_unlock(&voice_lock);
76 return 0;
77}
78
79static int q6_open(struct inode *inode, struct file *file)
80{
81 pr_debug("[%s:%s]\n", __MM_FILE__, __func__);
82 return 0;
83}
84
85static long q6_ioctl(struct file *file,
86 unsigned int cmd, unsigned long arg)
87{
88 int rc;
89 uint32_t n;
90 uint32_t id[2];
91 uint32_t mute_status;
92
93 switch (cmd) {
94 case AUDIO_SWITCH_DEVICE:
95 rc = copy_from_user(&id, (void *)arg, sizeof(id));
96 pr_info("[%s:%s] SWITCH_DEV: id[0] = 0x%x, id[1] = 0x%x",
97 __MM_FILE__, __func__, id[0], id[1]);
98 if (!rc)
99 rc = q6audio_do_routing(id[0], id[1]);
100 break;
101 case AUDIO_SET_VOLUME:
102 rc = copy_from_user(&n, (void *)arg, sizeof(n));
103 pr_debug("[%s:%s] SET_VOLUME: vol = %d\n", __MM_FILE__,
104 __func__, n);
105 if (!rc)
106 rc = q6audio_set_rx_volume(n);
107 break;
108 case AUDIO_SET_MUTE:
109 rc = copy_from_user(&n, (void *)arg, sizeof(n));
110 if (!rc) {
111 if (voice_started) {
112 if (n == 1)
113 mute_status = STREAM_MUTE;
114 else
115 mute_status = STREAM_UNMUTE;
116 } else {
117 if (n == 1)
118 mute_status = DEVICE_MUTE;
119 else
120 mute_status = DEVICE_UNMUTE;
121 }
122
123 pr_debug("[%s:%s] SET_MUTE: mute_status = %d\n",
124 __MM_FILE__, __func__, mute_status);
125 rc = q6audio_set_tx_mute(mute_status);
126 }
127 break;
128 case AUDIO_UPDATE_ACDB:
129 rc = copy_from_user(&id, (void *)arg, sizeof(id));
130 pr_debug("[%s:%s] UPDATE_ACDB: id[0] = 0x%x, id[1] = 0x%x\n",
131 __MM_FILE__, __func__, id[0], id[1]);
132 if (!rc)
133 rc = q6audio_update_acdb(id[0], 0);
134 break;
135 case AUDIO_START_VOICE:
136 pr_debug("[%s:%s] START_VOICE\n", __MM_FILE__, __func__);
137 rc = q6_voice_start();
138 break;
139 case AUDIO_STOP_VOICE:
140 pr_debug("[%s:%s] STOP_VOICE\n", __MM_FILE__, __func__);
141 rc = q6_voice_stop();
142 break;
143 case AUDIO_REINIT_ACDB:
144 pr_debug("[%s:%s] REINIT_ACDB\n", __MM_FILE__, __func__);
145 rc = 0;
146 break;
147 default:
148 rc = -EINVAL;
149 }
150
151 return rc;
152}
153
154
155static int q6_release(struct inode *inode, struct file *file)
156{
157 pr_debug("[%s:%s]\n", __MM_FILE__, __func__);
158 return 0;
159}
160
161static struct file_operations q6_dev_fops = {
162 .owner = THIS_MODULE,
163 .open = q6_open,
164 .unlocked_ioctl = q6_ioctl,
165 .release = q6_release,
166};
167
168struct miscdevice q6_control_device = {
169 .minor = MISC_DYNAMIC_MINOR,
170 .name = "msm_audio_ctl",
171 .fops = &q6_dev_fops,
172};
173
174
175static int __init q6_audio_ctl_init(void) {
176 return misc_register(&q6_control_device);
177}
178
179device_initcall(q6_audio_ctl_init);