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
);