1 /* arch/arm/mach-msm/qdsp5/audmgr.c
3 * interface to "audmgr" service on the baseband cpu
5 * Copyright (C) 2008 Google, Inc.
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.
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.
18 #include <linux/module.h>
20 #include <linux/uaccess.h>
21 #include <linux/kthread.h>
22 #include <linux/wait.h>
24 #include <asm/atomic.h>
25 #include <mach/msm_rpcrouter.h>
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
36 static void rpc_ack(struct msm_rpc_endpoint *ept, uint32_t xid)
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);
47 msm_rpc_write(ept, rep, sizeof(rep));
50 static void process_audmgr_callback(struct audmgr *am,
51 struct rpc_audmgr_cb_func_ptr *args,
54 if (len < (sizeof(uint32_t) * 3))
56 if (be32_to_cpu(args->set_to_one) != 1)
59 switch (be32_to_cpu(args->status)) {
60 case RPC_AUDMGR_STATUS_READY:
61 if (len < sizeof(uint32_t) * 4)
63 am->handle = be32_to_cpu(args->u.handle);
64 pr_info("audmgr: rpc READY handle=0x%08x\n", am->handle);
66 case RPC_AUDMGR_STATUS_CODEC_CONFIG: {
68 if (len < sizeof(uint32_t) * 4)
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;
76 case RPC_AUDMGR_STATUS_PENDING:
77 pr_err("audmgr: PENDING?\n");
79 case RPC_AUDMGR_STATUS_SUSPEND:
80 pr_err("audmgr: SUSPEND?\n");
82 case RPC_AUDMGR_STATUS_FAILURE:
83 pr_err("audmgr: FAILURE\n");
85 case RPC_AUDMGR_STATUS_VOLUME_CHANGE:
86 pr_err("audmgr: VOLUME_CHANGE?\n");
88 case RPC_AUDMGR_STATUS_DISABLED:
89 pr_err("audmgr: DISABLED\n");
90 am->state = STATE_DISABLED;
93 case RPC_AUDMGR_STATUS_ERROR:
94 pr_err("audmgr: ERROR?\n");
95 am->state = STATE_ERROR;
103 static void process_rpc_request(uint32_t proc, uint32_t xid,
104 void *data, int len, void *private)
106 struct audmgr *am = private;
111 pr_info("rpc_call proc %d:", proc);
113 printk(" %08x", be32_to_cpu(*x++));
117 if (proc == AUDMGR_CB_FUNC_PTR)
118 process_audmgr_callback(am, data, len);
120 pr_err("audmgr: unknown rpc proc %d\n", proc);
121 rpc_ack(am->ept, xid);
124 #define RPC_TYPE_REQUEST 0
125 #define RPC_TYPE_REPLY 1
127 #define RPC_VERSION 2
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)
134 static int audmgr_rpc_thread(void *data)
136 struct audmgr *am = data;
137 struct rpc_request_hdr *hdr = NULL;
141 pr_info("audmgr_rpc_thread() start\n");
143 while (!kthread_should_stop()) {
148 len = msm_rpc_read(am->ept, (void **) &hdr, -1, -1);
150 pr_err("audmgr: rpc read failed (%d)\n", len);
153 if (len < RPC_COMMON_HDR_SZ)
156 type = be32_to_cpu(hdr->type);
157 if (type == RPC_TYPE_REPLY) {
158 struct rpc_reply_hdr *rep = (void *) hdr;
160 if (len < RPC_REPLY_HDR_SZ)
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);
167 pr_info("audmgr: rpc_reply denied!\n");
173 if (len < RPC_REQUEST_HDR_SZ)
176 process_rpc_request(be32_to_cpu(hdr->procedure),
177 be32_to_cpu(hdr->xid),
182 pr_info("audmgr_rpc_thread() exit\n");
192 struct audmgr_enable_msg {
193 struct rpc_request_hdr hdr;
194 struct rpc_audmgr_enable_client_args args;
197 struct audmgr_disable_msg {
198 struct rpc_request_hdr hdr;
202 int audmgr_open(struct audmgr *am)
206 if (am->state != STATE_CLOSED)
209 am->ept = msm_rpc_connect(AUDMGR_PROG,
211 MSM_RPC_UNINTERRUPTIBLE);
213 init_waitqueue_head(&am->wait);
215 if (IS_ERR(am->ept)) {
216 rc = PTR_ERR(am->ept);
218 pr_err("audmgr: failed to connect to audmgr svc\n");
222 am->task = kthread_run(audmgr_rpc_thread, am, "audmgr_rpc");
223 if (IS_ERR(am->task)) {
224 rc = PTR_ERR(am->task);
226 msm_rpc_close(am->ept);
231 am->state = STATE_DISABLED;
234 EXPORT_SYMBOL(audmgr_open);
236 int audmgr_close(struct audmgr *am)
240 EXPORT_SYMBOL(audmgr_close);
242 int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg)
244 struct audmgr_enable_msg msg;
247 if (am->state == STATE_ENABLED)
250 if (am->state == STATE_DISABLING)
251 pr_err("audmgr: state is DISABLING in enable?\n");
252 am->state = STATE_ENABLING;
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);
263 msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, msm_rpc_get_vers(am->ept),
264 AUDMGR_ENABLE_CLIENT);
266 rc = msm_rpc_write(am->ept, &msg, sizeof(msg));
270 rc = wait_event_timeout(am->wait, am->state != STATE_ENABLING, 15 * HZ);
272 pr_err("audmgr_enable: ARM9 did not reply to RPC am->state = %d\n", am->state);
275 if (am->state == STATE_ENABLED)
278 pr_err("audmgr: unexpected state %d while enabling?!\n", am->state);
281 EXPORT_SYMBOL(audmgr_enable);
283 int audmgr_disable(struct audmgr *am)
285 struct audmgr_disable_msg msg;
288 if (am->state == STATE_DISABLED)
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);
295 am->state = STATE_DISABLING;
297 rc = msm_rpc_write(am->ept, &msg, sizeof(msg));
301 rc = wait_event_timeout(am->wait, am->state != STATE_DISABLING, 15 * HZ);
303 pr_err("audmgr_disable: ARM9 did not reply to RPC am->state = %d\n", am->state);
307 if (am->state == STATE_DISABLED)
310 pr_err("audmgr: unexpected state %d while disabling?!\n", am->state);
313 EXPORT_SYMBOL(audmgr_disable);