blob: 1884b3c5bbc1a723fe49f9792161cff4584daf58 [file] [log] [blame]
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/module.h>
14#include <linux/fs.h>
15#include <linux/miscdevice.h>
16#include <linux/kthread.h>
17#include <linux/list.h>
18#include <linux/uaccess.h>
19#include <linux/mutex.h>
20#include <linux/wakelock.h>
21#include <linux/msm_audio_mvs.h>
22#include <linux/slab.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070023#include <linux/pm_qos.h>
24
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#include <mach/msm_rpcrouter.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070026#include <mach/cpuidle.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027
28#define MVS_PROG 0x30000014
29#define MVS_VERS 0x00030001
30#define MVS_VERS_COMP_VER4 0x00040001
31#define MVS_VERS_COMP_VER5 0x00050001
32
33#define MVS_CLIENT_ID_VOIP 0x00000003
34
35#define MVS_ACQUIRE_PROC 4
36#define MVS_ENABLE_PROC 5
37#define MVS_RELEASE_PROC 6
38#define MVS_AMR_SET_AMR_MODE_PROC 7
39#define MVS_AMR_SET_AWB_MODE_PROC 8
40#define MVS_VOC_SET_FRAME_RATE_PROC 10
41#define MVS_GSM_SET_DTX_MODE_PROC 11
42#define MVS_G729A_SET_MODE_PROC 12
43#define MVS_G711_GET_MODE_PROC 14
44#define MVS_G711_SET_MODE_PROC 15
45#define MVS_G711A_GET_MODE_PROC 16
46#define MVS_G711A_SET_MODE_PROC 17
47#define MVS_G722_SET_MODE_PROC 20
48#define MVS_G722_GET_MODE_PROC 21
49#define MVS_SET_DTX_MODE_PROC 22
50
51#define MVS_EVENT_CB_TYPE_PROC 1
52#define MVS_PACKET_UL_FN_TYPE_PROC 2
53#define MVS_PACKET_DL_FN_TYPE_PROC 3
54
55#define MVS_CB_FUNC_ID 0xAAAABBBB
56#define MVS_UL_CB_FUNC_ID 0xBBBBCCCC
57#define MVS_DL_CB_FUNC_ID 0xCCCCDDDD
58
59#define MVS_FRAME_MODE_VOC_TX 1
60#define MVS_FRAME_MODE_VOC_RX 2
61#define MVS_FRAME_MODE_AMR_UL 3
62#define MVS_FRAME_MODE_AMR_DL 4
63#define MVS_FRAME_MODE_GSM_UL 5
64#define MVS_FRAME_MODE_GSM_DL 6
65#define MVS_FRAME_MODE_HR_UL 7
66#define MVS_FRAME_MODE_HR_DL 8
67#define MVS_FRAME_MODE_G711_UL 9
68#define MVS_FRAME_MODE_G711_DL 10
69#define MVS_FRAME_MODE_PCM_UL 13
70#define MVS_FRAME_MODE_PCM_DL 14
71#define MVS_FRAME_MODE_G729A_UL 17
72#define MVS_FRAME_MODE_G729A_DL 18
73#define MVS_FRAME_MODE_G711A_UL 19
74#define MVS_FRAME_MODE_G711A_DL 20
75#define MVS_FRAME_MODE_G722_UL 21
76#define MVS_FRAME_MODE_G722_DL 22
77
78
79
80#define MVS_PKT_CONTEXT_ISR 0x00000001
81
82#define RPC_TYPE_REQUEST 0
83#define RPC_TYPE_REPLY 1
84
85#define RPC_STATUS_FAILURE 0
86#define RPC_STATUS_SUCCESS 1
87#define RPC_STATUS_REJECT 1
88
89#define RPC_COMMON_HDR_SZ (sizeof(uint32_t) * 2)
90#define RPC_REQUEST_HDR_SZ (sizeof(struct rpc_request_hdr))
91#define RPC_REPLY_HDR_SZ (sizeof(uint32_t) * 3)
92
93enum audio_mvs_state_type {
94 AUDIO_MVS_CLOSED,
95 AUDIO_MVS_OPENED,
96 AUDIO_MVS_STARTED,
97 AUDIO_MVS_STOPPED
98};
99
100enum audio_mvs_event_type {
101 AUDIO_MVS_COMMAND,
102 AUDIO_MVS_MODE,
103 AUDIO_MVS_NOTIFY
104};
105
106enum audio_mvs_cmd_status_type {
107 AUDIO_MVS_CMD_FAILURE,
108 AUDIO_MVS_CMD_BUSY,
109 AUDIO_MVS_CMD_SUCCESS
110};
111
112enum audio_mvs_mode_status_type {
113 AUDIO_MVS_MODE_NOT_AVAIL,
114 AUDIO_MVS_MODE_INIT,
115 AUDIO_MVS_MODE_READY
116};
117
118enum audio_mvs_pkt_status_type {
119 AUDIO_MVS_PKT_NORMAL,
120 AUDIO_MVS_PKT_FAST,
121 AUDIO_MVS_PKT_SLOW
122};
123
124/* Parameters required for MVS acquire. */
125struct rpc_audio_mvs_acquire_args {
126 uint32_t client_id;
127 uint32_t cb_func_id;
128};
129
130struct audio_mvs_acquire_msg {
131 struct rpc_request_hdr rpc_hdr;
132 struct rpc_audio_mvs_acquire_args acquire_args;
133};
134
135/* Parameters required for MVS enable. */
136struct rpc_audio_mvs_enable_args {
137 uint32_t client_id;
138 uint32_t mode;
139 uint32_t ul_cb_func_id;
140 uint32_t dl_cb_func_id;
141 uint32_t context;
142};
143
144struct audio_mvs_enable_msg {
145 struct rpc_request_hdr rpc_hdr;
146 struct rpc_audio_mvs_enable_args enable_args;
147};
148
149/* Parameters required for MVS release. */
150struct audio_mvs_release_msg {
151 struct rpc_request_hdr rpc_hdr;
152 uint32_t client_id;
153};
154
155/* Parameters required for setting AMR mode. */
156struct audio_mvs_set_amr_mode_msg {
157 struct rpc_request_hdr rpc_hdr;
158 uint32_t amr_mode;
159};
160
161/* Parameters required for setting DTX. */
162struct audio_mvs_set_dtx_mode_msg {
163 struct rpc_request_hdr rpc_hdr;
164 uint32_t dtx_mode;
165};
166
167/* Parameters required for setting EVRC mode. */
168struct audio_mvs_set_voc_mode_msg {
169 struct rpc_request_hdr rpc_hdr;
170 uint32_t max_rate;
171 uint32_t min_rate;
172};
173
174/* Parameters for G711 mode */
175struct audio_mvs_set_g711_mode_msg {
176 struct rpc_request_hdr rpc_hdr;
177 uint32_t g711_mode;
178};
179
180/* Parameters for G729 mode */
181struct audio_mvs_set_g729_mode_msg {
182 struct rpc_request_hdr rpc_hdr;
183 uint32_t g729_mode;
184};
185
186/* Parameters for G722 mode */
187struct audio_mvs_set_g722_mode_msg {
188 struct rpc_request_hdr rpc_hdr;
189 uint32_t g722_mode;
190};
191
192
193/* Parameters for G711A mode */
194struct audio_mvs_set_g711A_mode_msg {
195 struct rpc_request_hdr rpc_hdr;
196 uint32_t g711A_mode;
197};
198
199/* Parameters for EFR FR and HR mode */
200struct audio_mvs_set_efr_mode_msg {
201 struct rpc_request_hdr rpc_hdr;
202 uint32_t efr_mode;
203};
204
205union audio_mvs_event_data {
206 struct mvs_ev_command_type {
207 uint32_t event;
208 uint32_t client_id;
209 uint32_t cmd_status;
210 } mvs_ev_command_type;
211
212 struct mvs_ev_mode_type {
213 uint32_t event;
214 uint32_t client_id;
215 uint32_t mode_status;
216 uint32_t mode;
217 } mvs_ev_mode_type;
218
219 struct mvs_ev_notify_type {
220 uint32_t event;
221 uint32_t client_id;
222 uint32_t buf_dir;
223 uint32_t max_frames;
224 } mvs_ev_notify_type;
225};
226
227struct audio_mvs_cb_func_args {
228 uint32_t cb_func_id;
229 uint32_t valid_ptr;
230 uint32_t event;
231 union audio_mvs_event_data event_data;
232};
233
234struct audio_mvs_frame_info_hdr {
235 uint32_t frame_mode;
236 uint32_t mvs_mode;
237 uint16_t buf_free_cnt;
238};
239
240struct audio_mvs_ul_reply {
241 struct rpc_reply_hdr reply_hdr;
242 uint32_t valid_pkt_status_ptr;
243 uint32_t pkt_status;
244};
245
246struct audio_mvs_dl_cb_func_args {
247 uint32_t cb_func_id;
248
249 uint32_t valid_ptr;
250 uint32_t frame_mode;
251 uint32_t frame_mode_ignore;
252
253 struct audio_mvs_frame_info_hdr frame_info_hdr;
254
255 uint32_t amr_frame;
256 uint32_t amr_mode;
257};
258/*general codec parameters includes AMR, G711A, PCM
259G729, VOC and HR vocoders
260*/
261struct gnr_cdc_param {
262 uint32_t param1;
263 uint32_t param2;
264 uint32_t valid_pkt_status_ptr;
265 uint32_t pkt_status;
266};
267/*G711 codec parameter*/
268struct g711_param {
269 uint32_t param1;
270 uint32_t valid_pkt_status_ptr;
271 uint32_t pkt_status;
272};
273
274union codec_param {
275 struct gnr_cdc_param gnr_arg;
276 struct g711_param g711_arg;
277};
278
279struct audio_mvs_dl_reply {
280 struct rpc_reply_hdr reply_hdr;
281
Vinay Vaka71f7dec2012-04-12 21:48:08 +0530282 uint32_t voc_pkt[Q5V2_MVS_MAX_VOC_PKT_SIZE/4];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283
284 uint32_t valid_frame_info_ptr;
285 uint32_t frame_mode;
286 uint32_t frame_mode_again;
287
288 struct audio_mvs_frame_info_hdr frame_info_hdr;
289 union codec_param cdc_param;
290};
291
292struct audio_mvs_buf_node {
293 struct list_head list;
Vinay Vaka71f7dec2012-04-12 21:48:08 +0530294 struct q5v2_msm_audio_mvs_frame frame;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295};
296
297/* Each buffer is 20 ms, queue holds 200 ms of data. */
298#define MVS_MAX_Q_LEN 10
299
300struct audio_mvs_info_type {
301 enum audio_mvs_state_type state;
302 uint32_t frame_mode;
303 uint32_t mvs_mode;
304 uint32_t buf_free_cnt;
305 uint32_t rate_type;
306 uint32_t dtx_mode;
Vinay Vaka40ea09e2012-06-01 19:10:04 +0530307 struct min_max_rate min_max_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308
309 struct msm_rpc_endpoint *rpc_endpt;
310 uint32_t rpc_prog;
311 uint32_t rpc_ver;
312 uint32_t rpc_status;
313
314 uint8_t *mem_chunk;
315
316 struct list_head in_queue;
317 struct list_head free_in_queue;
318
319 struct list_head out_queue;
320 struct list_head free_out_queue;
321
322 struct task_struct *task;
323
324 wait_queue_head_t wait;
325 wait_queue_head_t mode_wait;
326 wait_queue_head_t out_wait;
327
328 struct mutex lock;
329 struct mutex in_lock;
330 struct mutex out_lock;
331
332 struct wake_lock suspend_lock;
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700333 struct pm_qos_request pm_qos_req;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334};
335
336static struct audio_mvs_info_type audio_mvs_info;
337
338static int audio_mvs_setup_mode(struct audio_mvs_info_type *audio)
339{
340 int rc = 0;
341
342 pr_debug("%s:\n", __func__);
343
344 switch (audio->mvs_mode) {
345 case MVS_MODE_AMR:
346 case MVS_MODE_AMR_WB: {
347 struct audio_mvs_set_amr_mode_msg set_amr_mode_msg;
348 struct audio_mvs_set_dtx_mode_msg set_dtx_mode_msg;
349
350 /* Set AMR mode. */
351 memset(&set_amr_mode_msg, 0, sizeof(set_amr_mode_msg));
352 set_amr_mode_msg.amr_mode = cpu_to_be32(audio->rate_type);
353
354 if (audio->mvs_mode == MVS_MODE_AMR) {
355 msm_rpc_setup_req(&set_amr_mode_msg.rpc_hdr,
356 audio->rpc_prog,
357 audio->rpc_ver,
358 MVS_AMR_SET_AMR_MODE_PROC);
359 } else {
360 msm_rpc_setup_req(&set_amr_mode_msg.rpc_hdr,
361 audio->rpc_prog,
362 audio->rpc_ver,
363 MVS_AMR_SET_AWB_MODE_PROC);
364 }
365
366 audio->rpc_status = RPC_STATUS_FAILURE;
367 rc = msm_rpc_write(audio->rpc_endpt,
368 &set_amr_mode_msg,
369 sizeof(set_amr_mode_msg));
370
371 if (rc >= 0) {
372 pr_debug("%s: RPC write for set amr mode done\n",
373 __func__);
374
375 /* Save the MVS configuration information. */
376 audio->frame_mode = MVS_FRAME_MODE_AMR_DL;
377
378 /* Disable DTX. */
379 memset(&set_dtx_mode_msg, 0, sizeof(set_dtx_mode_msg));
380 set_dtx_mode_msg.dtx_mode = cpu_to_be32(0);
381
382 msm_rpc_setup_req(&set_dtx_mode_msg.rpc_hdr,
383 audio->rpc_prog,
384 audio->rpc_ver,
385 MVS_SET_DTX_MODE_PROC);
386
387 audio->rpc_status = RPC_STATUS_FAILURE;
388 rc = msm_rpc_write(audio->rpc_endpt,
389 &set_dtx_mode_msg,
390 sizeof(set_dtx_mode_msg));
391
392 if (rc >= 0) {
393 pr_debug("%s: RPC write for set dtx done\n",
394 __func__);
395
396 rc = 0;
397 }
398 } else {
399 pr_err("%s: RPC write for set amr mode failed %d\n",
400 __func__, rc);
401 }
402 break;
403 }
404 case MVS_MODE_PCM:
405 case MVS_MODE_LINEAR_PCM: {
406 /* PCM does not have any params to be set.
407 Save the MVS configuration information. */
408 audio->rate_type = MVS_AMR_MODE_UNDEF;
409 audio->frame_mode = MVS_FRAME_MODE_PCM_DL;
410 break;
411 }
412 case MVS_MODE_IS127:
413 case MVS_MODE_IS733:
414 case MVS_MODE_4GV_NB:
415 case MVS_MODE_4GV_WB: {
416 struct audio_mvs_set_voc_mode_msg set_voc_mode_msg;
417
418 /* Set EVRC mode. */
419 memset(&set_voc_mode_msg, 0, sizeof(set_voc_mode_msg));
Vinay Vaka40ea09e2012-06-01 19:10:04 +0530420 set_voc_mode_msg.min_rate =
421 cpu_to_be32(audio->min_max_rate.min_rate);
422 set_voc_mode_msg.max_rate =
423 cpu_to_be32(audio->min_max_rate.max_rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424
425 msm_rpc_setup_req(&set_voc_mode_msg.rpc_hdr,
426 audio->rpc_prog,
427 audio->rpc_ver,
428 MVS_VOC_SET_FRAME_RATE_PROC);
429
430 audio->rpc_status = RPC_STATUS_FAILURE;
431 rc = msm_rpc_write(audio->rpc_endpt,
432 &set_voc_mode_msg,
433 sizeof(set_voc_mode_msg));
434
435 if (rc >= 0) {
436 pr_debug("%s: RPC write for set voc mode done\n",
437 __func__);
438
439 /* Save the MVS configuration information. */
440 audio->frame_mode = MVS_FRAME_MODE_VOC_RX;
441
442 rc = 0;
443 } else {
444 pr_err("%s: RPC write for set voc mode failed %d\n",
445 __func__, rc);
446 }
447 break;
448 }
449 case MVS_MODE_G711: {
450 struct audio_mvs_set_g711_mode_msg set_g711_mode_msg;
451
452 /* Set G711 mode. */
453 memset(&set_g711_mode_msg, 0, sizeof(set_g711_mode_msg));
454 set_g711_mode_msg.g711_mode = cpu_to_be32(audio->rate_type);
455
456 pr_debug("%s: mode of g711:%d\n",
457 __func__, set_g711_mode_msg.g711_mode);
458
459 msm_rpc_setup_req(&set_g711_mode_msg.rpc_hdr,
460 audio->rpc_prog,
461 audio->rpc_ver,
462 MVS_G711_SET_MODE_PROC);
463
464 audio->rpc_status = RPC_STATUS_FAILURE;
465 rc = msm_rpc_write(audio->rpc_endpt,
466 &set_g711_mode_msg,
467 sizeof(set_g711_mode_msg));
468
469 if (rc >= 0) {
470 pr_debug("%s: RPC write for set g711 mode done\n",
471 __func__);
472 /* Save the MVS configuration information. */
473 audio->frame_mode = MVS_FRAME_MODE_G711_DL;
474
475 rc = 0;
476 } else {
477 pr_err("%s: RPC write for set g711 mode failed %d\n",
478 __func__, rc);
479 }
480 break;
481 }
482 case MVS_MODE_G729A: {
483 struct audio_mvs_set_g729_mode_msg set_g729_mode_msg;
484
485 /* Set G729 mode. */
486 memset(&set_g729_mode_msg, 0, sizeof(set_g729_mode_msg));
487 set_g729_mode_msg.g729_mode = cpu_to_be32(audio->dtx_mode);
488
489 pr_debug("%s: mode of g729:%d\n",
490 __func__, set_g729_mode_msg.g729_mode);
491
492 msm_rpc_setup_req(&set_g729_mode_msg.rpc_hdr,
493 audio->rpc_prog,
494 audio->rpc_ver,
495 MVS_G729A_SET_MODE_PROC);
496
497 audio->rpc_status = RPC_STATUS_FAILURE;
498 rc = msm_rpc_write(audio->rpc_endpt,
499 &set_g729_mode_msg,
500 sizeof(set_g729_mode_msg));
501
502 if (rc >= 0) {
503 pr_debug("%s: RPC write for set g729 mode done\n",
504 __func__);
505
506 /* Save the MVS configuration information. */
507 audio->frame_mode = MVS_FRAME_MODE_G729A_DL;
508
509 rc = 0;
510 } else {
511 pr_err("%s: RPC write for set g729 mode failed %d\n",
512 __func__, rc);
513 }
514 break;
515 }
516 case MVS_MODE_G722: {
517 struct audio_mvs_set_g722_mode_msg set_g722_mode_msg;
518
519 /* Set G722 mode. */
520 memset(&set_g722_mode_msg, 0, sizeof(set_g722_mode_msg));
521 set_g722_mode_msg.g722_mode = cpu_to_be32(audio->rate_type);
522
523 pr_debug("%s: mode of g722:%d\n",
524 __func__, set_g722_mode_msg.g722_mode);
525
526 msm_rpc_setup_req(&set_g722_mode_msg.rpc_hdr,
527 audio->rpc_prog,
528 audio->rpc_ver,
529 MVS_G722_SET_MODE_PROC);
530
531 audio->rpc_status = RPC_STATUS_FAILURE;
532 rc = msm_rpc_write(audio->rpc_endpt,
533 &set_g722_mode_msg,
534 sizeof(set_g722_mode_msg));
535
536 if (rc >= 0) {
537 pr_debug("%s: RPC write for set g722 mode done\n",
538 __func__);
539
540 /* Save the MVS configuration information. */
541 audio->frame_mode = MVS_FRAME_MODE_G722_DL;
542
543 rc = 0;
544 }
545 break;
546 }
547 case MVS_MODE_G711A: {
548 struct audio_mvs_set_g711A_mode_msg set_g711A_mode_msg;
549 struct audio_mvs_set_dtx_mode_msg set_dtx_mode_msg;
550
551 /* Set G711A mode. */
552 memset(&set_g711A_mode_msg, 0, sizeof(set_g711A_mode_msg));
553 set_g711A_mode_msg.g711A_mode = cpu_to_be32(audio->rate_type);
554
555 pr_debug("%s: mode of g711A:%d\n",
556 __func__, set_g711A_mode_msg.g711A_mode);
557
558 msm_rpc_setup_req(&set_g711A_mode_msg.rpc_hdr,
559 audio->rpc_prog,
560 audio->rpc_ver,
561 MVS_G711A_SET_MODE_PROC);
562
563 audio->rpc_status = RPC_STATUS_FAILURE;
564 rc = msm_rpc_write(audio->rpc_endpt,
565 &set_g711A_mode_msg,
566 sizeof(set_g711A_mode_msg));
567
568 if (rc >= 0) {
569 pr_debug("%s: RPC write for set g711A mode done\n",
570 __func__);
571
572 /* Save the MVS configuration information. */
573 audio->frame_mode = MVS_FRAME_MODE_G711A_DL;
574 /* Set DTX MODE. */
575 memset(&set_dtx_mode_msg, 0, sizeof(set_dtx_mode_msg));
576 set_dtx_mode_msg.dtx_mode =
577 cpu_to_be32((audio->dtx_mode));
578
579 msm_rpc_setup_req(&set_dtx_mode_msg.rpc_hdr,
580 audio->rpc_prog,
581 audio->rpc_ver,
582 MVS_SET_DTX_MODE_PROC);
583
584 audio->rpc_status = RPC_STATUS_FAILURE;
585 rc = msm_rpc_write(audio->rpc_endpt,
586 &set_dtx_mode_msg,
587 sizeof(set_dtx_mode_msg));
588
589 if (rc >= 0) {
590 pr_debug("%s: RPC write for set dtx done\n",
591 __func__);
592
593 rc = 0;
594 }
595 rc = 0;
596 } else {
597 pr_err("%s: RPC write for set g711A mode failed %d\n",
598 __func__, rc);
599 }
600 break;
601 }
602 case MVS_MODE_EFR:
603 case MVS_MODE_FR:
604 case MVS_MODE_HR: {
605 struct audio_mvs_set_efr_mode_msg set_efr_mode_msg;
606
607 /* Set G729 mode. */
608 memset(&set_efr_mode_msg, 0, sizeof(set_efr_mode_msg));
609 set_efr_mode_msg.efr_mode = cpu_to_be32(audio->dtx_mode);
610
611 pr_debug("%s: mode of EFR, FR and HR:%d\n",
612 __func__, set_efr_mode_msg.efr_mode);
613
614 msm_rpc_setup_req(&set_efr_mode_msg.rpc_hdr,
615 audio->rpc_prog,
616 audio->rpc_ver,
617 MVS_GSM_SET_DTX_MODE_PROC);
618
619 audio->rpc_status = RPC_STATUS_FAILURE;
620 rc = msm_rpc_write(audio->rpc_endpt,
621 &set_efr_mode_msg,
622 sizeof(set_efr_mode_msg));
623
624 if (rc >= 0) {
625 pr_debug("%s: RPC write for set EFR, FR and HR mode done\n",
626 __func__);
627
628 /* Save the MVS configuration information. */
629 if ((audio->mvs_mode == MVS_MODE_EFR) ||
630 (audio->mvs_mode == MVS_MODE_FR))
631 audio->frame_mode = MVS_FRAME_MODE_GSM_DL;
632 if (audio->mvs_mode == MVS_MODE_HR)
633 audio->frame_mode = MVS_FRAME_MODE_HR_DL;
634
635 rc = 0;
636 } else {
637 pr_err("%s: RPC write for set EFR, FR and HR mode failed %d\n",
638 __func__, rc);
639 }
640 break;
641 }
642 default:
643 rc = -EINVAL;
644 pr_err("Default case\n");
645 }
646 return rc;
647}
648
649static int audio_mvs_setup(struct audio_mvs_info_type *audio)
650{
651 int rc = 0;
652 struct audio_mvs_enable_msg enable_msg;
653
654 pr_debug("%s:\n", __func__);
655
656 /* Enable MVS. */
657 memset(&enable_msg, 0, sizeof(enable_msg));
658 enable_msg.enable_args.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
659 enable_msg.enable_args.mode = cpu_to_be32(audio->mvs_mode);
660 enable_msg.enable_args.ul_cb_func_id = cpu_to_be32(MVS_UL_CB_FUNC_ID);
661 enable_msg.enable_args.dl_cb_func_id = cpu_to_be32(MVS_DL_CB_FUNC_ID);
662 enable_msg.enable_args.context = cpu_to_be32(MVS_PKT_CONTEXT_ISR);
663
664 msm_rpc_setup_req(&enable_msg.rpc_hdr,
665 audio->rpc_prog,
666 audio->rpc_ver,
667 MVS_ENABLE_PROC);
668
669 audio->rpc_status = RPC_STATUS_FAILURE;
670 rc = msm_rpc_write(audio->rpc_endpt, &enable_msg, sizeof(enable_msg));
671
672 if (rc >= 0) {
673 pr_debug("%s: RPC write for enable done\n", __func__);
674
675 rc = wait_event_timeout(audio->mode_wait,
676 (audio->rpc_status != RPC_STATUS_FAILURE),
677 10 * HZ);
678
679 if (rc > 0) {
680 pr_debug("%s: Wait event for enable succeeded\n",
681 __func__);
682 rc = audio_mvs_setup_mode(audio);
683 if (rc < 0) {
684 pr_err("%s: Unknown MVS mode %d\n",
685 __func__, audio->mvs_mode);
686 }
687 pr_err("rc value after mode setup: %d\n", rc);
688 } else {
689 pr_err("%s: Wait event for enable failed %d\n",
690 __func__, rc);
691 }
692 } else {
693 pr_err("%s: RPC write for enable failed %d\n", __func__, rc);
694 }
695
696 return rc;
697}
698
699static int audio_mvs_start(struct audio_mvs_info_type *audio)
700{
701 int rc = 0;
702 struct audio_mvs_acquire_msg acquire_msg;
703
704 pr_info("%s:\n", __func__);
705
706 /* Prevent sleep. */
707 wake_lock(&audio->suspend_lock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700708 pm_qos_update_request(&audio->pm_qos_req,
709 msm_cpuidle_get_deep_idle_latency());
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700710
711 /* Acquire MVS. */
712 memset(&acquire_msg, 0, sizeof(acquire_msg));
713 acquire_msg.acquire_args.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
714 acquire_msg.acquire_args.cb_func_id = cpu_to_be32(MVS_CB_FUNC_ID);
715
716 msm_rpc_setup_req(&acquire_msg.rpc_hdr,
717 audio->rpc_prog,
718 audio->rpc_ver,
719 MVS_ACQUIRE_PROC);
720
721 audio->rpc_status = RPC_STATUS_FAILURE;
722 rc = msm_rpc_write(audio->rpc_endpt,
723 &acquire_msg,
724 sizeof(acquire_msg));
725
726 if (rc >= 0) {
727 pr_debug("%s: RPC write for acquire done\n", __func__);
728
729 rc = wait_event_timeout(audio->wait,
730 (audio->rpc_status != RPC_STATUS_FAILURE),
731 1 * HZ);
732
733 if (rc > 0) {
734
735 rc = audio_mvs_setup(audio);
736
737 if (rc == 0)
738 audio->state = AUDIO_MVS_STARTED;
739
740 } else {
741 pr_err("%s: Wait event for acquire failed %d\n",
742 __func__, rc);
743
744 rc = -EBUSY;
745 }
746 } else {
747 pr_err("%s: RPC write for acquire failed %d\n", __func__, rc);
748
749 rc = -EBUSY;
750 }
751
752 return rc;
753}
754
755static int audio_mvs_stop(struct audio_mvs_info_type *audio)
756{
757 int rc = 0;
758 struct audio_mvs_release_msg release_msg;
759
760 pr_info("%s:\n", __func__);
761
762 /* Release MVS. */
763 memset(&release_msg, 0, sizeof(release_msg));
764 release_msg.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
765
766 msm_rpc_setup_req(&release_msg.rpc_hdr,
767 audio->rpc_prog,
768 audio->rpc_ver,
769 MVS_RELEASE_PROC);
770
771 audio->rpc_status = RPC_STATUS_FAILURE;
772 rc = msm_rpc_write(audio->rpc_endpt, &release_msg, sizeof(release_msg));
773
774 if (rc >= 0) {
775 pr_debug("%s: RPC write for release done\n", __func__);
776
777 rc = wait_event_timeout(audio->mode_wait,
778 (audio->rpc_status != RPC_STATUS_FAILURE),
779 1 * HZ);
780
781 if (rc > 0) {
782 pr_debug("%s: Wait event for release succeeded\n",
783 __func__);
784
785 audio->state = AUDIO_MVS_STOPPED;
786
787 /* Un-block read in case it is waiting for data. */
788 wake_up(&audio->out_wait);
789 rc = 0;
790 } else {
791 pr_err("%s: Wait event for release failed %d\n",
792 __func__, rc);
793 }
794 } else {
795 pr_err("%s: RPC write for release failed %d\n", __func__, rc);
796 }
797
798 /* Allow sleep. */
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700799 pm_qos_update_request(&audio->pm_qos_req, PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 wake_unlock(&audio->suspend_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801
802 return rc;
803}
804
805static void audio_mvs_process_rpc_request(uint32_t procedure,
806 uint32_t xid,
807 void *data,
808 uint32_t length,
809 struct audio_mvs_info_type *audio)
810{
811 int rc = 0;
812
813 pr_debug("%s:\n", __func__);
814
815 switch (procedure) {
816 case MVS_EVENT_CB_TYPE_PROC: {
817 struct audio_mvs_cb_func_args *args = data;
818 struct rpc_reply_hdr reply_hdr;
819
820 pr_debug("%s: MVS CB CB_FUNC_ID 0x%x\n",
821 __func__, be32_to_cpu(args->cb_func_id));
822
823 if (be32_to_cpu(args->valid_ptr)) {
824 uint32_t event_type = be32_to_cpu(args->event);
825
826 pr_debug("%s: MVS CB event type %d\n",
827 __func__, be32_to_cpu(args->event));
828
829 if (event_type == AUDIO_MVS_COMMAND) {
830 uint32_t cmd_status = be32_to_cpu(
831 args->event_data.mvs_ev_command_type.cmd_status);
832
833 pr_debug("%s: MVS CB command status %d\n",
834 __func__, cmd_status);
835
836 if (cmd_status == AUDIO_MVS_CMD_SUCCESS) {
837 audio->rpc_status = RPC_STATUS_SUCCESS;
838 wake_up(&audio->wait);
839 }
840
841 } else if (event_type == AUDIO_MVS_MODE) {
842 uint32_t mode_status = be32_to_cpu(
843 args->event_data.mvs_ev_mode_type.mode_status);
844
845 pr_debug("%s: MVS CB mode status %d\n",
846 __func__, mode_status);
847
848 if (mode_status == AUDIO_MVS_MODE_READY) {
849 audio->rpc_status = RPC_STATUS_SUCCESS;
850 wake_up(&audio->mode_wait);
851 }
852 } else {
853 pr_err("%s: MVS CB unknown event type %d\n",
854 __func__, event_type);
855 }
856 } else {
857 pr_err("%s: MVS CB event pointer not valid\n",
858 __func__);
859 }
860
861 /* Send ack to modem. */
862 memset(&reply_hdr, 0, sizeof(reply_hdr));
863 reply_hdr.xid = cpu_to_be32(xid);
864 reply_hdr.type = cpu_to_be32(RPC_TYPE_REPLY);
865 reply_hdr.reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
866
867 reply_hdr.data.acc_hdr.accept_stat = cpu_to_be32(
868 RPC_ACCEPTSTAT_SUCCESS);
869 reply_hdr.data.acc_hdr.verf_flavor = 0;
870 reply_hdr.data.acc_hdr.verf_length = 0;
871
872 rc = msm_rpc_write(audio->rpc_endpt,
873 &reply_hdr,
874 sizeof(reply_hdr));
875
876 if (rc < 0)
877 pr_err("%s: RPC write for response failed %d\n",
878 __func__, rc);
879
880 break;
881 }
882
883 case MVS_PACKET_UL_FN_TYPE_PROC: {
884 uint32_t *args = data;
885 uint32_t pkt_len;
886 uint32_t frame_mode;
887 struct audio_mvs_ul_reply ul_reply;
888 struct audio_mvs_buf_node *buf_node = NULL;
889
890 pr_debug("%s: MVS UL CB_FUNC_ID 0x%x\n",
891 __func__, be32_to_cpu(*args));
892 args++;
893
894 pkt_len = be32_to_cpu(*args);
895 pr_debug("%s: UL pkt_len %d\n", __func__, pkt_len);
896 args++;
897
898 /* Copy the vocoder packets. */
899 mutex_lock(&audio->out_lock);
900
901 if (!list_empty(&audio->free_out_queue)) {
902 buf_node = list_first_entry(&audio->free_out_queue,
903 struct audio_mvs_buf_node,
904 list);
905 list_del(&buf_node->list);
906
907 memcpy(&buf_node->frame.voc_pkt[0], args, pkt_len);
908 buf_node->frame.len = pkt_len;
909 pkt_len = ALIGN(pkt_len, 4);
910 args = args + pkt_len/4;
911
912 pr_debug("%s: UL valid_ptr 0x%x\n",
913 __func__, be32_to_cpu(*args));
914 args++;
915
916 frame_mode = be32_to_cpu(*args);
917 pr_debug("%s: UL frame_mode %d\n",
918 __func__, frame_mode);
919 args++;
920
921 pr_debug("%s: UL frame_mode %d\n",
922 __func__, be32_to_cpu(*args));
923 args++;
924
925 pr_debug("%s: UL frame_mode %d\n",
926 __func__, be32_to_cpu(*args));
927 args++;
928
929 pr_debug("%s: UL mvs_mode %d\n",
930 __func__, be32_to_cpu(*args));
931 args++;
932
933 pr_debug("%s: UL buf_free_cnt %d\n",
934 __func__, be32_to_cpu(*args));
935 args++;
936
937 if (frame_mode == MVS_FRAME_MODE_AMR_UL) {
938 /* Extract AMR frame type. */
939 buf_node->frame.frame_type = be32_to_cpu(*args);
940
941 pr_debug("%s: UL AMR frame_type %d\n",
942 __func__, be32_to_cpu(*args));
Vinay Vaka71f7dec2012-04-12 21:48:08 +0530943 } else if (frame_mode == MVS_FRAME_MODE_PCM_UL) {
944 /* PCM don't have frame_type */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700945 buf_node->frame.frame_type = 0;
Vinay Vaka71f7dec2012-04-12 21:48:08 +0530946 } else if (frame_mode == MVS_FRAME_MODE_VOC_TX) {
947 /* Extracting EVRC current buffer frame rate*/
948 buf_node->frame.frame_type = be32_to_cpu(*args);
949
950 pr_debug("%s: UL EVRC frame_type %d\n",
951 __func__, be32_to_cpu(*args));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700952 } else if (frame_mode == MVS_FRAME_MODE_G711_UL) {
953 /* Extract G711 frame type. */
954 buf_node->frame.frame_type = be32_to_cpu(*args);
955
956 pr_debug("%s: UL G711 frame_type %d\n",
957 __func__, be32_to_cpu(*args));
958 } else if (frame_mode == MVS_FRAME_MODE_G729A_UL) {
959 /* Extract G729 frame type. */
960 buf_node->frame.frame_type = be32_to_cpu(*args);
961
962 pr_debug("%s: UL G729 frame_type %d\n",
963 __func__, be32_to_cpu(*args));
964 } else if (frame_mode == MVS_FRAME_MODE_G722_UL) {
965 /* Extract G722 frame type. */
966 buf_node->frame.frame_type = be32_to_cpu(*args);
967
968 pr_debug("%s: UL G722 frame_type %d\n",
969 __func__, be32_to_cpu(*args));
970 } else if (frame_mode == MVS_FRAME_MODE_G711A_UL) {
971 /* Extract G711A frame type. */
972 buf_node->frame.frame_type = be32_to_cpu(*args);
973
974 pr_debug("%s: UL G711A frame_type %d\n",
975 __func__, be32_to_cpu(*args));
976 } else if ((frame_mode == MVS_FRAME_MODE_GSM_UL) ||
977 (frame_mode == MVS_FRAME_MODE_HR_UL)) {
978 /* Extract EFR, FR and HR frame type. */
979 buf_node->frame.frame_type = be32_to_cpu(*args);
980
981 pr_debug("%s: UL EFR,FR,HR frame_type %d\n",
982 __func__, be32_to_cpu(*args));
983 } else {
984 pr_debug("%s: UL Unknown frame mode %d\n",
985 __func__, frame_mode);
986 }
987
988 list_add_tail(&buf_node->list, &audio->out_queue);
989 } else {
990 pr_err("%s: UL data dropped, read is slow\n", __func__);
991 }
992
993 mutex_unlock(&audio->out_lock);
994
995 wake_up(&audio->out_wait);
996
997 /* Send UL message accept to modem. */
998 memset(&ul_reply, 0, sizeof(ul_reply));
999 ul_reply.reply_hdr.xid = cpu_to_be32(xid);
1000 ul_reply.reply_hdr.type = cpu_to_be32(RPC_TYPE_REPLY);
1001 ul_reply.reply_hdr.reply_stat = cpu_to_be32(
1002 RPCMSG_REPLYSTAT_ACCEPTED);
1003
1004 ul_reply.reply_hdr.data.acc_hdr.accept_stat = cpu_to_be32(
1005 RPC_ACCEPTSTAT_SUCCESS);
1006 ul_reply.reply_hdr.data.acc_hdr.verf_flavor = 0;
1007 ul_reply.reply_hdr.data.acc_hdr.verf_length = 0;
1008
1009 ul_reply.valid_pkt_status_ptr = cpu_to_be32(0x00000001);
1010 ul_reply.pkt_status = cpu_to_be32(0x00000000);
1011
1012 rc = msm_rpc_write(audio->rpc_endpt,
1013 &ul_reply,
1014 sizeof(ul_reply));
1015
1016 if (rc < 0)
1017 pr_err("%s: RPC write for UL response failed %d\n",
1018 __func__, rc);
1019
1020 break;
1021 }
1022
1023 case MVS_PACKET_DL_FN_TYPE_PROC: {
1024 struct audio_mvs_dl_cb_func_args *args = data;
1025 struct audio_mvs_dl_reply dl_reply;
1026 uint32_t frame_mode;
1027 struct audio_mvs_buf_node *buf_node = NULL;
1028
1029 pr_debug("%s: MVS DL CB CB_FUNC_ID 0x%x\n",
1030 __func__, be32_to_cpu(args->cb_func_id));
1031
1032 frame_mode = be32_to_cpu(args->frame_mode);
1033 pr_debug("%s: DL frame_mode %d\n", __func__, frame_mode);
1034
1035 /* Prepare and send the DL packets to modem. */
1036 memset(&dl_reply, 0, sizeof(dl_reply));
1037 dl_reply.reply_hdr.xid = cpu_to_be32(xid);
1038 dl_reply.reply_hdr.type = cpu_to_be32(RPC_TYPE_REPLY);
1039 dl_reply.reply_hdr.reply_stat = cpu_to_be32(
1040 RPCMSG_REPLYSTAT_ACCEPTED);
1041
1042 dl_reply.reply_hdr.data.acc_hdr.accept_stat = cpu_to_be32(
1043 RPC_ACCEPTSTAT_SUCCESS);
1044 dl_reply.reply_hdr.data.acc_hdr.verf_flavor = 0;
1045 dl_reply.reply_hdr.data.acc_hdr.verf_length = 0;
1046
1047 mutex_lock(&audio->in_lock);
1048
1049 if (!list_empty(&audio->in_queue)) {
1050 buf_node = list_first_entry(&audio->in_queue,
1051 struct audio_mvs_buf_node,
1052 list);
1053 list_del(&buf_node->list);
1054
1055 memcpy(&dl_reply.voc_pkt,
1056 &buf_node->frame.voc_pkt[0],
1057 buf_node->frame.len);
1058
1059 pr_debug("%s:frame mode %d\n", __func__, frame_mode);
1060 if (frame_mode == MVS_FRAME_MODE_AMR_DL) {
1061 dl_reply.cdc_param.gnr_arg.param1 = cpu_to_be32(
1062 buf_node->frame.frame_type);
1063 dl_reply.cdc_param.gnr_arg.param2 =
1064 cpu_to_be32(audio->rate_type);
1065 dl_reply.cdc_param.\
1066 gnr_arg.valid_pkt_status_ptr =
1067 cpu_to_be32(0x00000001);
1068 dl_reply.cdc_param.gnr_arg.pkt_status =
1069 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1070 } else if (frame_mode == MVS_FRAME_MODE_PCM_DL) {
1071 dl_reply.cdc_param.gnr_arg.param1 = 0;
1072 dl_reply.cdc_param.gnr_arg.param2 = 0;
1073 dl_reply.cdc_param.\
1074 gnr_arg.valid_pkt_status_ptr =
1075 cpu_to_be32(0x00000001);
1076 dl_reply.cdc_param.gnr_arg.pkt_status =
1077 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1078 } else if (frame_mode == MVS_FRAME_MODE_VOC_RX) {
1079 dl_reply.cdc_param.gnr_arg.param1 =
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301080 cpu_to_be32(buf_node->frame.frame_type);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001081 dl_reply.cdc_param.gnr_arg.param2 = 0;
1082 dl_reply.cdc_param.\
1083 gnr_arg.valid_pkt_status_ptr =
1084 cpu_to_be32(0x00000001);
1085 dl_reply.cdc_param.gnr_arg.pkt_status =
1086 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1087 } else if (frame_mode == MVS_FRAME_MODE_G711_DL) {
1088 dl_reply.cdc_param.g711_arg.param1 =
1089 cpu_to_be32(buf_node->frame.frame_type);
1090 dl_reply.cdc_param.\
1091 g711_arg.valid_pkt_status_ptr =
1092 cpu_to_be32(0x00000001);
1093 dl_reply.cdc_param.g711_arg.pkt_status =
1094 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1095 } else if (frame_mode == MVS_FRAME_MODE_G729A_DL) {
1096 dl_reply.cdc_param.gnr_arg.param1 = cpu_to_be32(
1097 buf_node->frame.frame_type);
1098 dl_reply.cdc_param.gnr_arg.param2 =
1099 cpu_to_be32(audio->rate_type);
1100 dl_reply.cdc_param.\
1101 gnr_arg.valid_pkt_status_ptr =
1102 cpu_to_be32(0x00000001);
1103 dl_reply.cdc_param.gnr_arg.pkt_status =
1104 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1105 } else if (frame_mode == MVS_FRAME_MODE_G722_DL) {
1106 dl_reply.cdc_param.gnr_arg.param1 = cpu_to_be32(
1107 buf_node->frame.frame_type);
1108 dl_reply.cdc_param.gnr_arg.param2 =
1109 cpu_to_be32(audio->rate_type);
1110 dl_reply.cdc_param.\
1111 gnr_arg.valid_pkt_status_ptr =
1112 cpu_to_be32(0x00000001);
1113 dl_reply.cdc_param.gnr_arg.pkt_status =
1114 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1115 } else if (frame_mode == MVS_FRAME_MODE_G711A_DL) {
1116 dl_reply.cdc_param.gnr_arg.param1 = cpu_to_be32(
1117 buf_node->frame.frame_type);
1118 dl_reply.cdc_param.gnr_arg.param2 =
1119 cpu_to_be32(audio->rate_type);
1120 dl_reply.cdc_param.\
1121 gnr_arg.valid_pkt_status_ptr =
1122 cpu_to_be32(0x00000001);
1123 dl_reply.cdc_param.gnr_arg.pkt_status =
1124 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1125 } else if ((frame_mode == MVS_FRAME_MODE_GSM_DL) ||
1126 (frame_mode == MVS_FRAME_MODE_HR_DL)) {
1127 dl_reply.cdc_param.gnr_arg.param1 = cpu_to_be32(
1128 buf_node->frame.frame_type);
1129 dl_reply.cdc_param.gnr_arg.param2 =
1130 cpu_to_be32(audio->rate_type);
1131 dl_reply.cdc_param.\
1132 gnr_arg.valid_pkt_status_ptr =
1133 cpu_to_be32(0x00000001);
1134 dl_reply.cdc_param.gnr_arg.pkt_status =
1135 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
1136 } else {
1137 pr_err("%s: DL Unknown frame mode %d\n",
1138 __func__, frame_mode);
1139 }
1140 list_add_tail(&buf_node->list, &audio->free_in_queue);
1141 } else {
1142 pr_debug("%s: No DL data available to send to MVS\n",
1143 __func__);
1144 if (frame_mode == MVS_FRAME_MODE_G711_DL) {
1145 dl_reply.cdc_param.\
1146 g711_arg.valid_pkt_status_ptr =
1147 cpu_to_be32(0x00000001);
1148 dl_reply.cdc_param.g711_arg.pkt_status =
1149 cpu_to_be32(AUDIO_MVS_PKT_SLOW);
1150 } else {
1151 dl_reply.cdc_param.\
1152 gnr_arg.valid_pkt_status_ptr =
1153 cpu_to_be32(0x00000001);
1154 dl_reply.cdc_param.gnr_arg.pkt_status =
1155 cpu_to_be32(AUDIO_MVS_PKT_SLOW);
1156 }
1157 }
1158
1159 mutex_unlock(&audio->in_lock);
1160
1161 dl_reply.valid_frame_info_ptr = cpu_to_be32(0x00000001);
1162
1163 dl_reply.frame_mode = cpu_to_be32(audio->frame_mode);
1164 dl_reply.frame_mode_again = cpu_to_be32(audio->frame_mode);
1165
1166 dl_reply.frame_info_hdr.frame_mode =
1167 cpu_to_be32(audio->frame_mode);
1168 dl_reply.frame_info_hdr.mvs_mode = cpu_to_be32(audio->mvs_mode);
1169 dl_reply.frame_info_hdr.buf_free_cnt = 0;
1170
1171 rc = msm_rpc_write(audio->rpc_endpt,
1172 &dl_reply,
1173 sizeof(dl_reply));
1174
1175 if (rc < 0)
1176 pr_err("%s: RPC write for DL response failed %d\n",
1177 __func__, rc);
1178
1179 break;
1180 }
1181
1182 default:
1183 pr_err("%s: Unknown CB type %d\n", __func__, procedure);
1184 }
1185}
1186
1187static int audio_mvs_thread(void *data)
1188{
1189 struct audio_mvs_info_type *audio = data;
1190 struct rpc_request_hdr *rpc_hdr = NULL;
1191
1192 pr_info("%s:\n", __func__);
1193
1194 while (!kthread_should_stop()) {
1195
1196 int rpc_hdr_len = msm_rpc_read(audio->rpc_endpt,
1197 (void **) &rpc_hdr,
1198 -1,
1199 -1);
1200
1201 if (rpc_hdr_len < 0) {
1202 pr_err("%s: RPC read failed %d\n",
1203 __func__, rpc_hdr_len);
1204
1205 break;
1206 } else if (rpc_hdr_len < RPC_COMMON_HDR_SZ) {
1207 continue;
1208 } else {
1209 uint32_t rpc_type = be32_to_cpu(rpc_hdr->type);
1210 if (rpc_type == RPC_TYPE_REPLY) {
1211 struct rpc_reply_hdr *rpc_reply =
1212 (void *) rpc_hdr;
1213 uint32_t reply_status;
1214
1215 if (rpc_hdr_len < RPC_REPLY_HDR_SZ)
1216 continue;
1217
1218 reply_status =
1219 be32_to_cpu(rpc_reply->reply_stat);
1220
1221 if (reply_status != RPCMSG_REPLYSTAT_ACCEPTED) {
1222 /* If the command is not accepted, there
1223 * will be no response callback. Wake
1224 * the caller and report error. */
1225 audio->rpc_status = RPC_STATUS_REJECT;
1226
1227 wake_up(&audio->wait);
1228
1229 pr_err("%s: RPC reply status denied\n",
1230 __func__);
1231 }
1232 } else if (rpc_type == RPC_TYPE_REQUEST) {
1233 if (rpc_hdr_len < RPC_REQUEST_HDR_SZ)
1234 continue;
1235
1236 audio_mvs_process_rpc_request(
1237 be32_to_cpu(rpc_hdr->procedure),
1238 be32_to_cpu(rpc_hdr->xid),
1239 (void *) (rpc_hdr + 1),
1240 (rpc_hdr_len - sizeof(*rpc_hdr)),
1241 audio);
1242 } else {
1243 pr_err("%s: Unexpected RPC type %d\n",
1244 __func__, rpc_type);
1245 }
1246 }
1247
1248 kfree(rpc_hdr);
1249 rpc_hdr = NULL;
1250 }
1251
1252 pr_info("%s: MVS thread stopped\n", __func__);
1253
1254 return 0;
1255}
1256
1257static int audio_mvs_alloc_buf(struct audio_mvs_info_type *audio)
1258{
1259 int i = 0;
1260 struct audio_mvs_buf_node *buf_node = NULL;
1261 struct list_head *ptr = NULL;
1262 struct list_head *next = NULL;
1263
1264 pr_debug("%s:\n", __func__);
1265
1266 /* Allocate input buffers. */
1267 for (i = 0; i < MVS_MAX_Q_LEN; i++) {
1268 buf_node = kmalloc(sizeof(struct audio_mvs_buf_node),
1269 GFP_KERNEL);
1270
1271 if (buf_node != NULL) {
1272 list_add_tail(&buf_node->list,
1273 &audio->free_in_queue);
1274 } else {
1275 pr_err("%s: No memory for IO buffers\n",
1276 __func__);
1277 goto err;
1278 }
1279 buf_node = NULL;
1280 }
1281
1282 /* Allocate output buffers. */
1283 for (i = 0; i < MVS_MAX_Q_LEN; i++) {
1284 buf_node = kmalloc(sizeof(struct audio_mvs_buf_node),
1285 GFP_KERNEL);
1286
1287 if (buf_node != NULL) {
1288 list_add_tail(&buf_node->list,
1289 &audio->free_out_queue);
1290 } else {
1291 pr_err("%s: No memory for IO buffers\n",
1292 __func__);
1293 goto err;
1294 }
1295 buf_node = NULL;
1296 }
1297
1298 return 0;
1299
1300err:
1301 list_for_each_safe(ptr, next, &audio->free_in_queue) {
1302 buf_node = list_entry(ptr, struct audio_mvs_buf_node, list);
1303 list_del(&buf_node->list);
1304 kfree(buf_node);
1305 buf_node = NULL;
1306 }
1307
1308 ptr = next = NULL;
1309 list_for_each_safe(ptr, next, &audio->free_out_queue) {
1310 buf_node = list_entry(ptr, struct audio_mvs_buf_node, list);
1311 list_del(&buf_node->list);
1312 kfree(buf_node);
1313 buf_node = NULL;
1314 }
1315
1316 return -ENOMEM;
1317}
1318
1319static void audio_mvs_free_buf(struct audio_mvs_info_type *audio)
1320{
1321 struct list_head *ptr = NULL;
1322 struct list_head *next = NULL;
1323 struct audio_mvs_buf_node *buf_node = NULL;
1324
1325 pr_debug("%s:\n", __func__);
1326
1327 mutex_lock(&audio->in_lock);
1328 /* Free input buffers. */
1329 list_for_each_safe(ptr, next, &audio->in_queue) {
1330 buf_node = list_entry(ptr, struct audio_mvs_buf_node, list);
1331 list_del(&buf_node->list);
1332 kfree(buf_node);
1333 buf_node = NULL;
1334 }
1335
1336 ptr = next = NULL;
1337 /* Free free_input buffers. */
1338 list_for_each_safe(ptr, next, &audio->free_in_queue) {
1339 buf_node = list_entry(ptr, struct audio_mvs_buf_node, list);
1340 list_del(&buf_node->list);
1341 kfree(buf_node);
1342 buf_node = NULL;
1343 }
1344 mutex_unlock(&audio->in_lock);
1345
1346 mutex_lock(&audio->out_lock);
1347 ptr = next = NULL;
1348 /* Free output buffers. */
1349 list_for_each_safe(ptr, next, &audio->out_queue) {
1350 buf_node = list_entry(ptr, struct audio_mvs_buf_node, list);
1351 list_del(&buf_node->list);
1352 kfree(buf_node);
1353 buf_node = NULL;
1354 }
1355
1356 /* Free free_ioutput buffers. */
1357 ptr = next = NULL;
1358 list_for_each_safe(ptr, next, &audio->free_out_queue) {
1359 buf_node = list_entry(ptr, struct audio_mvs_buf_node, list);
1360 list_del(&buf_node->list);
1361 kfree(buf_node);
1362 buf_node = NULL;
1363 }
1364 mutex_unlock(&audio->out_lock);
1365}
1366
1367static int audio_mvs_open(struct inode *inode, struct file *file)
1368{
1369 int rc = 0;
1370
1371 pr_info("%s:\n", __func__);
1372
1373 mutex_lock(&audio_mvs_info.lock);
1374
1375 if (audio_mvs_info.state == AUDIO_MVS_CLOSED) {
1376
1377 if (audio_mvs_info.task != NULL ||
1378 audio_mvs_info.rpc_endpt != NULL) {
1379 rc = audio_mvs_alloc_buf(&audio_mvs_info);
1380
1381 if (rc == 0) {
1382 audio_mvs_info.state = AUDIO_MVS_OPENED;
1383 file->private_data = &audio_mvs_info;
1384 }
1385 } else {
1386 pr_err("%s: MVS thread and RPC end point do not exist\n",
1387 __func__);
1388
1389 rc = -ENODEV;
1390 }
1391 } else {
1392 pr_err("%s: MVS driver exists, state %d\n",
1393 __func__, audio_mvs_info.state);
1394
1395 rc = -EBUSY;
1396 }
1397
1398 mutex_unlock(&audio_mvs_info.lock);
1399
1400 return rc;
1401}
1402
1403static int audio_mvs_release(struct inode *inode, struct file *file)
1404{
1405
1406 struct audio_mvs_info_type *audio = file->private_data;
1407
1408 pr_info("%s:\n", __func__);
1409
1410 mutex_lock(&audio->lock);
1411 if (audio->state == AUDIO_MVS_STARTED)
1412 audio_mvs_stop(audio);
1413 audio_mvs_free_buf(audio);
1414 audio->state = AUDIO_MVS_CLOSED;
1415 mutex_unlock(&audio->lock);
1416
1417 pr_debug("%s: Release done\n", __func__);
1418 return 0;
1419}
1420
1421static ssize_t audio_mvs_read(struct file *file,
1422 char __user *buf,
1423 size_t count,
1424 loff_t *pos)
1425{
1426 int rc = 0;
1427 struct audio_mvs_buf_node *buf_node = NULL;
1428 struct audio_mvs_info_type *audio = file->private_data;
1429
1430 pr_debug("%s:\n", __func__);
1431
1432 rc = wait_event_interruptible_timeout(audio->out_wait,
1433 (!list_empty(&audio->out_queue) ||
1434 audio->state == AUDIO_MVS_STOPPED),
1435 1 * HZ);
1436
1437 if (rc > 0) {
1438 mutex_lock(&audio->out_lock);
1439 if ((audio->state == AUDIO_MVS_STARTED) &&
1440 (!list_empty(&audio->out_queue))) {
1441
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301442 if (count >= sizeof(struct q5v2_msm_audio_mvs_frame)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001443 buf_node = list_first_entry(&audio->out_queue,
1444 struct audio_mvs_buf_node,
1445 list);
1446 list_del(&buf_node->list);
1447
1448 rc = copy_to_user(buf,
1449 &buf_node->frame,
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301450 sizeof(struct q5v2_msm_audio_mvs_frame)
1451 );
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001452
1453 if (rc == 0) {
1454 rc = buf_node->frame.len +
1455 sizeof(buf_node->frame.frame_type) +
1456 sizeof(buf_node->frame.len);
1457 } else {
1458 pr_err("%s: Copy to user retuned %d",
1459 __func__, rc);
1460
1461 rc = -EFAULT;
1462 }
1463
1464 list_add_tail(&buf_node->list,
1465 &audio->free_out_queue);
1466 } else {
1467 pr_err("%s: Read count %d < sizeof(frame) %d",
1468 __func__, count,
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301469 sizeof(struct q5v2_msm_audio_mvs_frame));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001470
1471 rc = -ENOMEM;
1472 }
1473 } else {
1474 pr_err("%s: Read performed in state %d\n",
1475 __func__, audio->state);
1476
1477 rc = -EPERM;
1478 }
1479 mutex_unlock(&audio->out_lock);
1480
1481 } else if (rc == 0) {
1482 pr_err("%s: No UL data available\n", __func__);
1483
1484 rc = -ETIMEDOUT;
1485 } else {
1486 pr_err("%s: Read was interrupted\n", __func__);
1487
1488 rc = -ERESTARTSYS;
1489 }
1490
1491 return rc;
1492}
1493
1494static ssize_t audio_mvs_write(struct file *file,
1495 const char __user *buf,
1496 size_t count,
1497 loff_t *pos)
1498{
1499 int rc = 0;
1500 struct audio_mvs_buf_node *buf_node = NULL;
1501 struct audio_mvs_info_type *audio = file->private_data;
1502
1503 pr_debug("%s:\n", __func__);
1504
1505 mutex_lock(&audio->in_lock);
1506 if (audio->state == AUDIO_MVS_STARTED) {
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301507 if (count <= sizeof(struct q5v2_msm_audio_mvs_frame)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508 if (!list_empty(&audio->free_in_queue)) {
1509 buf_node =
1510 list_first_entry(&audio->free_in_queue,
1511 struct audio_mvs_buf_node,
1512 list);
1513 list_del(&buf_node->list);
1514
1515 rc = copy_from_user(&buf_node->frame,
1516 buf,
1517 count);
1518
1519 list_add_tail(&buf_node->list,
1520 &audio->in_queue);
1521 } else {
1522 pr_err("%s: No free DL buffs\n", __func__);
1523 }
1524 } else {
1525 pr_err("%s: Write count %d < sizeof(frame) %d",
1526 __func__, count,
Vinay Vaka71f7dec2012-04-12 21:48:08 +05301527 sizeof(struct q5v2_msm_audio_mvs_frame));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001528
1529 rc = -ENOMEM;
1530 }
1531 } else {
1532 pr_err("%s: Write performed in invalid state %d\n",
1533 __func__, audio->state);
1534
1535 rc = -EPERM;
1536 }
1537 mutex_unlock(&audio->in_lock);
1538
1539 return rc;
1540}
1541
1542static long audio_mvs_ioctl(struct file *file,
1543 unsigned int cmd,
1544 unsigned long arg)
1545{
1546 int rc = 0;
1547
1548 struct audio_mvs_info_type *audio = file->private_data;
1549
1550 pr_info("%s:\n", __func__);
1551
1552 switch (cmd) {
1553 case AUDIO_GET_MVS_CONFIG: {
1554 struct msm_audio_mvs_config config;
1555
1556 pr_debug("%s: IOCTL GET_MVS_CONFIG\n", __func__);
1557
1558 mutex_lock(&audio->lock);
1559 config.mvs_mode = audio->mvs_mode;
1560 config.rate_type = audio->rate_type;
Vinay Vaka40ea09e2012-06-01 19:10:04 +05301561 config.min_max_rate.min_rate = audio->min_max_rate.min_rate;
1562 config.min_max_rate.max_rate = audio->min_max_rate.max_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001563 mutex_unlock(&audio->lock);
1564
1565 rc = copy_to_user((void *)arg, &config, sizeof(config));
1566 if (rc == 0)
1567 rc = sizeof(config);
1568 else
1569 pr_err("%s: Config copy failed %d\n", __func__, rc);
1570
1571 break;
1572 }
1573
1574 case AUDIO_SET_MVS_CONFIG: {
1575 struct msm_audio_mvs_config config;
1576
1577 pr_debug("%s: IOCTL SET_MVS_CONFIG\n", __func__);
1578
1579 rc = copy_from_user(&config, (void *)arg, sizeof(config));
1580 if (rc == 0) {
1581 mutex_lock(&audio->lock);
1582
1583 if (audio->state == AUDIO_MVS_OPENED) {
1584 audio->mvs_mode = config.mvs_mode;
1585 audio->rate_type = config.rate_type;
1586 audio->dtx_mode = config.dtx_mode;
Vinay Vaka40ea09e2012-06-01 19:10:04 +05301587 audio->min_max_rate.min_rate =
1588 config.min_max_rate.min_rate;
1589 audio->min_max_rate.max_rate =
1590 config.min_max_rate.max_rate;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001591 } else {
1592 pr_err("%s: Set confg called in state %d\n",
1593 __func__, audio->state);
1594
1595 rc = -EPERM;
1596 }
1597
1598 mutex_unlock(&audio->lock);
1599 } else {
1600 pr_err("%s: Config copy failed %d\n", __func__, rc);
1601 }
1602
1603 break;
1604 }
1605
1606 case AUDIO_START: {
1607 pr_debug("%s: IOCTL START\n", __func__);
1608
1609 mutex_lock(&audio->lock);
1610
1611 if (audio->state == AUDIO_MVS_OPENED ||
1612 audio->state == AUDIO_MVS_STOPPED) {
1613 rc = audio_mvs_start(audio);
1614
1615 if (rc != 0)
1616 audio_mvs_stop(audio);
1617 } else {
1618 pr_err("%s: Start called in invalid state %d\n",
1619 __func__, audio->state);
1620
1621 rc = -EPERM;
1622 }
1623
1624 mutex_unlock(&audio->lock);
1625
1626 break;
1627 }
1628
1629 case AUDIO_STOP: {
1630 pr_debug("%s: IOCTL STOP\n", __func__);
1631
1632 mutex_lock(&audio->lock);
1633
1634 if (audio->state == AUDIO_MVS_STARTED) {
1635 rc = audio_mvs_stop(audio);
1636 } else {
1637 pr_err("%s: Stop called in invalid state %d\n",
1638 __func__, audio->state);
1639
1640 rc = -EPERM;
1641 }
1642
1643 mutex_unlock(&audio->lock);
1644 break;
1645 }
1646
1647 default: {
1648 pr_err("%s: Unknown IOCTL %d\n", __func__, cmd);
1649 }
1650 }
1651
1652 return rc;
1653}
1654
1655static const struct file_operations audio_mvs_fops = {
1656 .owner = THIS_MODULE,
1657 .open = audio_mvs_open,
1658 .release = audio_mvs_release,
1659 .read = audio_mvs_read,
1660 .write = audio_mvs_write,
1661 .unlocked_ioctl = audio_mvs_ioctl
1662};
1663
1664struct miscdevice audio_mvs_misc = {
1665 .minor = MISC_DYNAMIC_MINOR,
1666 .name = "msm_mvs",
1667 .fops = &audio_mvs_fops
1668};
1669
1670static int __init audio_mvs_init(void)
1671{
1672 int rc;
1673
1674 pr_info("%s:\n", __func__);
1675
1676 memset(&audio_mvs_info, 0, sizeof(audio_mvs_info));
1677 mutex_init(&audio_mvs_info.lock);
1678 mutex_init(&audio_mvs_info.in_lock);
1679 mutex_init(&audio_mvs_info.out_lock);
1680
1681 init_waitqueue_head(&audio_mvs_info.wait);
1682 init_waitqueue_head(&audio_mvs_info.mode_wait);
1683 init_waitqueue_head(&audio_mvs_info.out_wait);
1684
1685 INIT_LIST_HEAD(&audio_mvs_info.in_queue);
1686 INIT_LIST_HEAD(&audio_mvs_info.free_in_queue);
1687 INIT_LIST_HEAD(&audio_mvs_info.out_queue);
1688 INIT_LIST_HEAD(&audio_mvs_info.free_out_queue);
1689
1690 wake_lock_init(&audio_mvs_info.suspend_lock,
1691 WAKE_LOCK_SUSPEND,
1692 "audio_mvs_suspend");
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001693 pm_qos_add_request(&audio_mvs_info.pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
1694 PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001695
1696 audio_mvs_info.rpc_endpt = msm_rpc_connect_compatible(MVS_PROG,
1697 MVS_VERS_COMP_VER5,
1698 MSM_RPC_UNINTERRUPTIBLE);
1699
1700 if (IS_ERR(audio_mvs_info.rpc_endpt)) {
1701 pr_err("%s: MVS RPC connect failed ver 0x%x\n", __func__,
1702 MVS_VERS_COMP_VER5);
1703 audio_mvs_info.rpc_endpt = msm_rpc_connect_compatible(MVS_PROG,
1704 MVS_VERS_COMP_VER4,
1705 MSM_RPC_UNINTERRUPTIBLE);
1706 if (IS_ERR(audio_mvs_info.rpc_endpt)) {
1707 pr_err("%s: MVS RPC connect failed ver 0x%x\n",
1708 __func__, MVS_VERS_COMP_VER4);
1709 audio_mvs_info.rpc_endpt =
1710 msm_rpc_connect_compatible(MVS_PROG,
1711 MVS_VERS,
1712 MSM_RPC_UNINTERRUPTIBLE);
1713 if (IS_ERR(audio_mvs_info.rpc_endpt)) {
1714 pr_err("%s: MVS RPC connect failed ver 0x%x\n",
1715 __func__, MVS_VERS);
1716 rc = PTR_ERR(audio_mvs_info.rpc_endpt);
1717 audio_mvs_info.rpc_endpt = NULL;
1718 goto done;
1719 } else {
1720 pr_debug("%s: MVS RPC connect succeeded ver\
1721 0x%x\n", __func__, MVS_VERS);
1722 audio_mvs_info.rpc_prog = MVS_PROG;
1723 audio_mvs_info.rpc_ver = MVS_VERS;
1724 }
1725 } else {
1726 pr_debug("%s: MVS RPC connect succeeded ver 0x%x\n",
1727 __func__, MVS_VERS_COMP_VER4);
1728 audio_mvs_info.rpc_prog = MVS_PROG;
1729 audio_mvs_info.rpc_ver = MVS_VERS_COMP_VER4;
1730 }
1731 } else {
1732 pr_debug("%s: MVS RPC connect succeeded ver 0x%x\n", __func__,
1733 MVS_VERS_COMP_VER5);
1734 audio_mvs_info.rpc_prog = MVS_PROG;
1735 audio_mvs_info.rpc_ver = MVS_VERS_COMP_VER5;
1736 }
1737 audio_mvs_info.task = kthread_run(audio_mvs_thread,
1738 &audio_mvs_info,
1739 "audio_mvs");
1740 if (IS_ERR(audio_mvs_info.task)) {
1741 pr_err("%s: MVS thread create failed\n", __func__);
1742 rc = PTR_ERR(audio_mvs_info.task);
1743 audio_mvs_info.task = NULL;
1744 msm_rpc_close(audio_mvs_info.rpc_endpt);
1745 audio_mvs_info.rpc_endpt = NULL;
1746 goto done;
1747 }
1748
1749 rc = misc_register(&audio_mvs_misc);
1750done:
1751 return rc;
1752}
1753
1754static void __exit audio_mvs_exit(void)
1755{
1756 pr_info("%s:\n", __func__);
1757
1758 misc_deregister(&audio_mvs_misc);
1759}
1760
1761module_init(audio_mvs_init);
1762module_exit(audio_mvs_exit);
1763
1764MODULE_DESCRIPTION("MSM MVS driver");
1765MODULE_LICENSE("GPL v2");
1766