Merge branch 'bugzilla-13620' into release
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / dream / qdsp5 / audmgr.c
1 /* arch/arm/mach-msm/qdsp5/audmgr.c
2 *
3 * interface to "audmgr" service on the baseband cpu
4 *
5 * Copyright (C) 2008 Google, Inc.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18 #include <linux/module.h>
19 #include <linux/fs.h>
20 #include <linux/uaccess.h>
21 #include <linux/kthread.h>
22 #include <linux/wait.h>
23
24 #include <asm/atomic.h>
25 #include <mach/msm_rpcrouter.h>
26
27 #include "audmgr.h"
28
29 #define STATE_CLOSED 0
30 #define STATE_DISABLED 1
31 #define STATE_ENABLING 2
32 #define STATE_ENABLED 3
33 #define STATE_DISABLING 4
34 #define STATE_ERROR 5
35
36 static void rpc_ack(struct msm_rpc_endpoint *ept, uint32_t xid)
37 {
38 uint32_t rep[6];
39
40 rep[0] = cpu_to_be32(xid);
41 rep[1] = cpu_to_be32(1);
42 rep[2] = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
43 rep[3] = cpu_to_be32(RPC_ACCEPTSTAT_SUCCESS);
44 rep[4] = 0;
45 rep[5] = 0;
46
47 msm_rpc_write(ept, rep, sizeof(rep));
48 }
49
50 static void process_audmgr_callback(struct audmgr *am,
51 struct rpc_audmgr_cb_func_ptr *args,
52 int len)
53 {
54 if (len < (sizeof(uint32_t) * 3))
55 return;
56 if (be32_to_cpu(args->set_to_one) != 1)
57 return;
58
59 switch (be32_to_cpu(args->status)) {
60 case RPC_AUDMGR_STATUS_READY:
61 if (len < sizeof(uint32_t) * 4)
62 break;
63 am->handle = be32_to_cpu(args->u.handle);
64 pr_info("audmgr: rpc READY handle=0x%08x\n", am->handle);
65 break;
66 case RPC_AUDMGR_STATUS_CODEC_CONFIG: {
67 uint32_t volume;
68 if (len < sizeof(uint32_t) * 4)
69 break;
70 volume = be32_to_cpu(args->u.volume);
71 pr_info("audmgr: rpc CODEC_CONFIG volume=0x%08x\n", volume);
72 am->state = STATE_ENABLED;
73 wake_up(&am->wait);
74 break;
75 }
76 case RPC_AUDMGR_STATUS_PENDING:
77 pr_err("audmgr: PENDING?\n");
78 break;
79 case RPC_AUDMGR_STATUS_SUSPEND:
80 pr_err("audmgr: SUSPEND?\n");
81 break;
82 case RPC_AUDMGR_STATUS_FAILURE:
83 pr_err("audmgr: FAILURE\n");
84 break;
85 case RPC_AUDMGR_STATUS_VOLUME_CHANGE:
86 pr_err("audmgr: VOLUME_CHANGE?\n");
87 break;
88 case RPC_AUDMGR_STATUS_DISABLED:
89 pr_err("audmgr: DISABLED\n");
90 am->state = STATE_DISABLED;
91 wake_up(&am->wait);
92 break;
93 case RPC_AUDMGR_STATUS_ERROR:
94 pr_err("audmgr: ERROR?\n");
95 am->state = STATE_ERROR;
96 wake_up(&am->wait);
97 break;
98 default:
99 break;
100 }
101 }
102
103 static void process_rpc_request(uint32_t proc, uint32_t xid,
104 void *data, int len, void *private)
105 {
106 struct audmgr *am = private;
107 uint32_t *x = data;
108
109 if (0) {
110 int n = len / 4;
111 pr_info("rpc_call proc %d:", proc);
112 while (n--)
113 printk(" %08x", be32_to_cpu(*x++));
114 printk("\n");
115 }
116
117 if (proc == AUDMGR_CB_FUNC_PTR)
118 process_audmgr_callback(am, data, len);
119 else
120 pr_err("audmgr: unknown rpc proc %d\n", proc);
121 rpc_ack(am->ept, xid);
122 }
123
124 #define RPC_TYPE_REQUEST 0
125 #define RPC_TYPE_REPLY 1
126
127 #define RPC_VERSION 2
128
129 #define RPC_COMMON_HDR_SZ (sizeof(uint32_t) * 2)
130 #define RPC_REQUEST_HDR_SZ (sizeof(struct rpc_request_hdr))
131 #define RPC_REPLY_HDR_SZ (sizeof(uint32_t) * 3)
132 #define RPC_REPLY_SZ (sizeof(uint32_t) * 6)
133
134 static int audmgr_rpc_thread(void *data)
135 {
136 struct audmgr *am = data;
137 struct rpc_request_hdr *hdr = NULL;
138 uint32_t type;
139 int len;
140
141 pr_info("audmgr_rpc_thread() start\n");
142
143 while (!kthread_should_stop()) {
144 if (hdr) {
145 kfree(hdr);
146 hdr = NULL;
147 }
148 len = msm_rpc_read(am->ept, (void **) &hdr, -1, -1);
149 if (len < 0) {
150 pr_err("audmgr: rpc read failed (%d)\n", len);
151 break;
152 }
153 if (len < RPC_COMMON_HDR_SZ)
154 continue;
155
156 type = be32_to_cpu(hdr->type);
157 if (type == RPC_TYPE_REPLY) {
158 struct rpc_reply_hdr *rep = (void *) hdr;
159 uint32_t status;
160 if (len < RPC_REPLY_HDR_SZ)
161 continue;
162 status = be32_to_cpu(rep->reply_stat);
163 if (status == RPCMSG_REPLYSTAT_ACCEPTED) {
164 status = be32_to_cpu(rep->data.acc_hdr.accept_stat);
165 pr_info("audmgr: rpc_reply status %d\n", status);
166 } else {
167 pr_info("audmgr: rpc_reply denied!\n");
168 }
169 /* process reply */
170 continue;
171 }
172
173 if (len < RPC_REQUEST_HDR_SZ)
174 continue;
175
176 process_rpc_request(be32_to_cpu(hdr->procedure),
177 be32_to_cpu(hdr->xid),
178 (void *) (hdr + 1),
179 len - sizeof(*hdr),
180 data);
181 }
182 pr_info("audmgr_rpc_thread() exit\n");
183 if (hdr) {
184 kfree(hdr);
185 hdr = NULL;
186 }
187 am->task = NULL;
188 wake_up(&am->wait);
189 return 0;
190 }
191
192 struct audmgr_enable_msg {
193 struct rpc_request_hdr hdr;
194 struct rpc_audmgr_enable_client_args args;
195 };
196
197 struct audmgr_disable_msg {
198 struct rpc_request_hdr hdr;
199 uint32_t handle;
200 };
201
202 int audmgr_open(struct audmgr *am)
203 {
204 int rc;
205
206 if (am->state != STATE_CLOSED)
207 return 0;
208
209 am->ept = msm_rpc_connect(AUDMGR_PROG,
210 AUDMGR_VERS,
211 MSM_RPC_UNINTERRUPTIBLE);
212
213 init_waitqueue_head(&am->wait);
214
215 if (IS_ERR(am->ept)) {
216 rc = PTR_ERR(am->ept);
217 am->ept = NULL;
218 pr_err("audmgr: failed to connect to audmgr svc\n");
219 return rc;
220 }
221
222 am->task = kthread_run(audmgr_rpc_thread, am, "audmgr_rpc");
223 if (IS_ERR(am->task)) {
224 rc = PTR_ERR(am->task);
225 am->task = NULL;
226 msm_rpc_close(am->ept);
227 am->ept = NULL;
228 return rc;
229 }
230
231 am->state = STATE_DISABLED;
232 return 0;
233 }
234 EXPORT_SYMBOL(audmgr_open);
235
236 int audmgr_close(struct audmgr *am)
237 {
238 return -EBUSY;
239 }
240 EXPORT_SYMBOL(audmgr_close);
241
242 int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg)
243 {
244 struct audmgr_enable_msg msg;
245 int rc;
246
247 if (am->state == STATE_ENABLED)
248 return 0;
249
250 if (am->state == STATE_DISABLING)
251 pr_err("audmgr: state is DISABLING in enable?\n");
252 am->state = STATE_ENABLING;
253
254 msg.args.set_to_one = cpu_to_be32(1);
255 msg.args.tx_sample_rate = cpu_to_be32(cfg->tx_rate);
256 msg.args.rx_sample_rate = cpu_to_be32(cfg->rx_rate);
257 msg.args.def_method = cpu_to_be32(cfg->def_method);
258 msg.args.codec_type = cpu_to_be32(cfg->codec);
259 msg.args.snd_method = cpu_to_be32(cfg->snd_method);
260 msg.args.cb_func = cpu_to_be32(0x11111111);
261 msg.args.client_data = cpu_to_be32(0x11223344);
262
263 msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, msm_rpc_get_vers(am->ept),
264 AUDMGR_ENABLE_CLIENT);
265
266 rc = msm_rpc_write(am->ept, &msg, sizeof(msg));
267 if (rc < 0)
268 return rc;
269
270 rc = wait_event_timeout(am->wait, am->state != STATE_ENABLING, 15 * HZ);
271 if (rc == 0) {
272 pr_err("audmgr_enable: ARM9 did not reply to RPC am->state = %d\n", am->state);
273 BUG();
274 }
275 if (am->state == STATE_ENABLED)
276 return 0;
277
278 pr_err("audmgr: unexpected state %d while enabling?!\n", am->state);
279 return -ENODEV;
280 }
281 EXPORT_SYMBOL(audmgr_enable);
282
283 int audmgr_disable(struct audmgr *am)
284 {
285 struct audmgr_disable_msg msg;
286 int rc;
287
288 if (am->state == STATE_DISABLED)
289 return 0;
290
291 msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, msm_rpc_get_vers(am->ept),
292 AUDMGR_DISABLE_CLIENT);
293 msg.handle = cpu_to_be32(am->handle);
294
295 am->state = STATE_DISABLING;
296
297 rc = msm_rpc_write(am->ept, &msg, sizeof(msg));
298 if (rc < 0)
299 return rc;
300
301 rc = wait_event_timeout(am->wait, am->state != STATE_DISABLING, 15 * HZ);
302 if (rc == 0) {
303 pr_err("audmgr_disable: ARM9 did not reply to RPC am->state = %d\n", am->state);
304 BUG();
305 }
306
307 if (am->state == STATE_DISABLED)
308 return 0;
309
310 pr_err("audmgr: unexpected state %d while disabling?!\n", am->state);
311 return -ENODEV;
312 }
313 EXPORT_SYMBOL(audmgr_disable);