blob: 2e7114c94f0c11bc6a5a0bce76d8567d3147eb17 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * All source code in this file is licensed under the following license except
4 * where indicated.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, you can find it at http://www.fsf.org.
17 */
18
19#include <linux/init.h>
20#include <linux/err.h>
21#include <linux/module.h>
22#include <linux/moduleparam.h>
23#include <linux/time.h>
24#include <linux/wait.h>
25#include <linux/platform_device.h>
26#include <linux/mutex.h>
27#include <sound/core.h>
28#include <sound/soc.h>
29#include <sound/pcm.h>
30#include <sound/initval.h>
31#include <sound/control.h>
32#include <linux/kthread.h>
33#include <linux/uaccess.h>
34#include <linux/mutex.h>
35#include <linux/wakelock.h>
36#include <mach/msm_rpcrouter.h>
37#include <mach/debug_mm.h>
38#include "msm_audio_mvs.h"
39
40
41static struct audio_mvs_info_type audio_mvs_info;
42
43static struct snd_pcm_hardware msm_pcm_hardware = {
44 .info = SNDRV_PCM_INFO_INTERLEAVED,
45 .formats = SNDRV_PCM_FMTBIT_S16_LE,
46 .rates = (SNDRV_PCM_RATE_8000),
47 .rate_min = 8000,
48 .rate_max = 8000,
49 .channels_min = 1,
50 .channels_max = 2,
51 .buffer_bytes_max = MVS_MAX_VOC_PKT_SIZE * MVS_MAX_Q_LEN,
52 .period_bytes_min = MVS_MAX_VOC_PKT_SIZE,
53 .period_bytes_max = MVS_MAX_VOC_PKT_SIZE,
54 .periods_min = MVS_MAX_Q_LEN,
55 .periods_max = MVS_MAX_Q_LEN,
56 .fifo_size = 0,
57};
58
59static void snd_pcm_mvs_timer(unsigned long data)
60{
61 struct audio_mvs_info_type *audio = &audio_mvs_info;
62 MM_DBG("%s\n", __func__);
63 if (audio->playback_start) {
64 if (audio->ack_dl_count) {
65 audio->pcm_playback_irq_pos += audio->pcm_count;
66 audio->ack_dl_count--;
67 snd_pcm_period_elapsed(audio->playback_substream);
68 }
69 }
70
71 if (audio->capture_start) {
72 if (audio->ack_ul_count) {
73 audio->pcm_capture_irq_pos += audio->pcm_capture_count;
74 audio->ack_ul_count--;
75 snd_pcm_period_elapsed(audio->capture_substream);
76 }
77 }
78 audio->timer.expires += audio->expiry_delta;
79 add_timer(&audio->timer);
80}
81
82static int audio_mvs_setup_mvs(struct audio_mvs_info_type *audio)
83{
84 int rc = 0;
85 struct audio_mvs_enable_msg enable_msg;
86 MM_DBG("%s\n", __func__);
87
88 /* Enable MVS. */
89
90 memset(&enable_msg, 0, sizeof(enable_msg));
91 audio->rpc_status = RPC_STATUS_FAILURE;
92 enable_msg.enable_args.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
93 enable_msg.enable_args.mode = cpu_to_be32(MVS_MODE_LINEAR_PCM);
94 enable_msg.enable_args.ul_cb_func_id = (int) NULL;
95 enable_msg.enable_args.dl_cb_func_id = (int) NULL;
96 enable_msg.enable_args.context = cpu_to_be32(MVS_PKT_CONTEXT_ISR);
97
98 msm_rpc_setup_req(&enable_msg.rpc_hdr, MVS_PROG,
99 MVS_VERS, MVS_ENABLE_PROC);
100
101 rc = msm_rpc_write(audio->rpc_endpt,
102 &enable_msg, sizeof(enable_msg));
103
104 if (rc >= 0) {
105 MM_DBG("RPC write for enable done\n");
106
107 rc = wait_event_timeout(audio->wait,
108 (audio->rpc_status !=
109 RPC_STATUS_FAILURE), 1 * HZ);
110
111 if (rc > 0) {
112 MM_DBG("Wait event for enable succeeded\n");
113
114 mutex_lock(&audio->lock);
115 audio->mvs_mode = MVS_MODE_LINEAR_PCM;
116 audio->frame_mode = MVS_FRAME_MODE_PCM_DL;
117 audio->pcm_frame = 0;
118 mutex_unlock(&audio->lock);
119 rc = 0;
120
121 } else
122 MM_ERR("Wait event for enable failed %d\n", rc);
123 } else
124 MM_ERR("RPC write for enable failed %d\n", rc);
125 return rc;
126}
127
128static void audio_mvs_rpc_reply(struct msm_rpc_endpoint *endpoint,
129 uint32_t xid)
130{
131 int rc = 0;
132 struct rpc_reply_hdr reply_hdr;
133 MM_DBG("%s\n", __func__);
134
135 memset(&reply_hdr, 0, sizeof(reply_hdr));
136 reply_hdr.xid = cpu_to_be32(xid);
137 reply_hdr.type = cpu_to_be32(RPC_TYPE_REPLY);
138 reply_hdr.reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
139 reply_hdr.data.acc_hdr.accept_stat =
140 cpu_to_be32(RPC_ACCEPTSTAT_SUCCESS);
141 reply_hdr.data.acc_hdr.verf_flavor = 0;
142 reply_hdr.data.acc_hdr.verf_length = 0;
143
144 rc = msm_rpc_write(endpoint, &reply_hdr, sizeof(reply_hdr));
145
146 if (rc < 0)
147 MM_ERR("RPC write for response failed %d\n", rc);
148}
149
150static void audio_mvs_process_rpc_request(uint32_t procedure, uint32_t xid,
151 void *data, uint32_t length,
152 struct audio_mvs_info_type *audio)
153{
154
155 int rc = 0;
156 uint32_t index;
157 MM_DBG("%s\n", __func__);
158 switch (procedure) {
159 case MVS_EVENT_CB_TYPE_PROC:{
160 struct audio_mvs_cb_func_args *args = data;
161 uint32_t event_type = be32_to_cpu(args->event);
162 uint32_t cmd_status =
163 be32_to_cpu(args->
164 event_data.mvs_ev_command_type.cmd_status);
165 uint32_t mode_status =
166 be32_to_cpu(args->
167 event_data.mvs_ev_mode_type.mode_status);
168 audio_mvs_rpc_reply(audio->rpc_endpt, xid);
169 if (be32_to_cpu(args->valid_ptr)) {
170 if (event_type == AUDIO_MVS_COMMAND) {
171 if (cmd_status == AUDIO_MVS_CMD_SUCCESS)
172 audio->rpc_status = RPC_STATUS_SUCCESS;
173 wake_up(&audio->wait);
174 } else if (event_type == AUDIO_MVS_MODE) {
175 if (mode_status != AUDIO_MVS_MODE_NOT_AVAIL) {
176 audio->rpc_status =
177 RPC_STATUS_SUCCESS;
178 }
179 audio->prepare_ack++;
180 wake_up(&audio->wait);
181 wake_up(&audio->prepare_wait);
182 } else {
183 /*nothing to do */
184 }
185 } else
186 MM_ERR("ALSA: CB event pointer not valid\n");
187 break;
188 }
189 case MVS_PACKET_UL_FN_TYPE_PROC:{
190 uint32_t *cb_data = data;
191 uint32_t pkt_len ;
192 struct audio_mvs_ul_reply ul_reply;
193 MM_DBG("MVS_PACKET_UL_FN_TYPE_PROC\n");
194
195 memset(&ul_reply, 0, sizeof(ul_reply));
196 cb_data++;
197 pkt_len = be32_to_cpu(*cb_data);
198 cb_data++;
199 if (audio->capture_enable) {
200 audio_mvs_info.ack_ul_count++;
201 mutex_lock(&audio->out_lock);
202 index = audio->out_write % MVS_MAX_Q_LEN;
203 memcpy(audio->out[index].voc_pkt, cb_data,
204 pkt_len);
205 audio->out[index].len = pkt_len;
206 audio->out_write++;
207 mutex_unlock(&audio->out_lock);
208 }
209 MM_DBG(" audio->out_read = %d audio->out write = %d\n",
210 audio->out_read, audio->out_write);
211 ul_reply.reply_hdr.xid = cpu_to_be32(xid);
212 ul_reply.reply_hdr.type = cpu_to_be32(RPC_TYPE_REPLY);
213 ul_reply.reply_hdr.reply_stat =
214 cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
215 ul_reply.reply_hdr.data.acc_hdr.accept_stat =
216 cpu_to_be32(RPC_ACCEPTSTAT_SUCCESS);
217 ul_reply.reply_hdr.data.acc_hdr.verf_flavor = 0;
218 ul_reply.reply_hdr.data.acc_hdr.verf_length = 0;
219 ul_reply.valid_pkt_status_ptr = cpu_to_be32(0x00000001);
220 ul_reply.pkt_status = cpu_to_be32(0x00000000);
221 rc = msm_rpc_write(audio->rpc_endpt, &ul_reply,
222 sizeof(ul_reply));
223 wake_up(&audio->out_wait);
224 if (rc < 0)
225 MM_ERR("RPC write for UL response failed %d\n",
226 rc);
227 break;
228 }
229 case MVS_PACKET_DL_FN_TYPE_PROC:{
230 struct audio_mvs_dl_reply dl_reply;
231 MM_DBG("MVS_PACKET_DL_FN_TYPE_PROC\n");
232 memset(&dl_reply, 0, sizeof(dl_reply));
233 dl_reply.reply_hdr.xid = cpu_to_be32(xid);
234 dl_reply.reply_hdr.type = cpu_to_be32(RPC_TYPE_REPLY);
235 dl_reply.reply_hdr.reply_stat =
236 cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
237 dl_reply.reply_hdr.data.acc_hdr.accept_stat =
238 cpu_to_be32(RPC_ACCEPTSTAT_SUCCESS);
239 dl_reply.reply_hdr.data.acc_hdr.verf_flavor = 0;
240 dl_reply.reply_hdr.data.acc_hdr.verf_length = 0;
241 mutex_lock(&audio->in_lock);
242 if (audio->in_read < audio->in_write
243 && audio->dl_play) {
244 index = audio->in_read % MVS_MAX_Q_LEN;
245 memcpy(&dl_reply.voc_pkt,
246 audio->in[index].voc_pkt,
247 audio->in[index].len);
248 audio->in_read++;
249 audio_mvs_info.ack_dl_count++;
250 dl_reply.pkt_status =
251 cpu_to_be32(AUDIO_MVS_PKT_NORMAL);
252 wake_up(&audio->in_wait);
253 } else {
254 dl_reply.pkt_status =
255 cpu_to_be32(AUDIO_MVS_PKT_SLOW);
256 }
257 mutex_unlock(&audio->in_lock);
258 MM_DBG(" audio->in_read = %d audio->in write = %d\n",
259 audio->in_read, audio->in_write);
260 dl_reply.valid_frame_info_ptr = cpu_to_be32(0x00000001);
261 dl_reply.frame_mode = cpu_to_be32(audio->frame_mode);
262 dl_reply.frame_mode_again =
263 cpu_to_be32(audio->frame_mode);
264 dl_reply.frame_info_hdr.frame_mode =
265 cpu_to_be32(audio->frame_mode);
266 dl_reply.frame_info_hdr.mvs_mode =
267 cpu_to_be32(audio->mvs_mode);
268 dl_reply.frame_info_hdr.buf_free_cnt = 0;
269 dl_reply.pcm_frame = cpu_to_be32(audio->pcm_frame);
270 dl_reply.pcm_mode = cpu_to_be32(audio->pcm_mode);
271 dl_reply.valid_pkt_status_ptr = cpu_to_be32(0x00000001);
272 rc = msm_rpc_write(audio->rpc_endpt, &dl_reply,
273 sizeof(dl_reply));
274 if (rc < 0)
275 MM_ERR("RPC write for DL response failed %d\n",
276 rc);
277 break;
278 }
279 default:
280 MM_ERR("Unknown CB type %d\n", procedure);
281 }
282}
283
284static int audio_mvs_thread(void *data)
285{
286 struct audio_mvs_info_type *audio = &audio_mvs_info;
287 struct rpc_request_hdr *rpc_hdr = NULL;
288 struct rpc_reply_hdr *rpc_reply = NULL;
289 uint32_t reply_status = 0;
290 uint32_t rpc_type;
291 int rpc_hdr_len;
292 MM_DBG("%s\n", __func__);
293
294 while (!kthread_should_stop()) {
295 rpc_hdr_len =
296 msm_rpc_read(audio->rpc_endpt, (void **)&rpc_hdr, -1, -1);
297 if (rpc_hdr_len < 0) {
298 MM_ERR("RPC read failed %d\n", rpc_hdr_len);
299 break;
300 } else if (rpc_hdr_len < RPC_COMMON_HDR_SZ)
301 continue;
302 else {
303 rpc_type = be32_to_cpu(rpc_hdr->type);
304 if (rpc_type == RPC_TYPE_REPLY) {
305 if (rpc_hdr_len < RPC_REPLY_HDR_SZ)
306 continue;
307 rpc_reply = (void *)rpc_hdr;
308 reply_status = be32_to_cpu(rpc_reply->
309 reply_stat);
310 if (reply_status != RPCMSG_REPLYSTAT_ACCEPTED) {
311 /* If the command is not accepted,
312 * there will be no response callback.
313 * Wake the caller and report error. */
314 audio->rpc_status = RPC_STATUS_REJECT;
315 wake_up(&audio->wait);
316 MM_ERR("RPC reply status denied\n");
317 }
318 } else if (rpc_type == RPC_TYPE_REQUEST) {
319 if (rpc_hdr_len < RPC_REQUEST_HDR_SZ)
320 continue;
321 MM_DBG("ALSA: kthread call procedure\n");
322 audio_mvs_process_rpc_request(
323 be32_to_cpu(rpc_hdr->procedure),
324 be32_to_cpu(rpc_hdr->xid),
325 (void *)(rpc_hdr + 1),
326 (rpc_hdr_len - sizeof(*rpc_hdr)),
327 audio);
328 } else
329 MM_ERR("Unexpected RPC type %d\n", rpc_type);
330 }
331 kfree(rpc_hdr);
332 rpc_hdr = NULL;
333 }
334 return 0;
335}
336
337static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
338{
339
340 struct audio_mvs_info_type *audio = &audio_mvs_info;
341 MM_DBG("%s\n", __func__);
342
343 switch (cmd) {
344 case SNDRV_PCM_TRIGGER_START:
345 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
346 audio->playback_start = 1;
347 else
348 audio->capture_start = 1;
349 break;
350 case SNDRV_PCM_TRIGGER_RESUME:
351 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
352 break;
353 case SNDRV_PCM_TRIGGER_STOP:
354 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
355 audio->playback_start = 0;
356 else
357 audio->capture_start = 0;
358 break;
359 default:
360 break;
361 }
362 return 0;
363}
364
365static int msm_pcm_open(struct snd_pcm_substream *substream)
366{
367 int ret = 0;
368 struct snd_pcm_runtime *runtime = substream->runtime;
369 struct audio_mvs_info_type *audio = &audio_mvs_info;
370
371 MM_DBG("%s\n", __func__);
372 mutex_lock(&audio->lock);
373 if (audio->state < AUDIO_MVS_OPENED) {
374 audio->rpc_endpt =
375 msm_rpc_connect_compatible(MVS_PROG,
376 MVS_VERS,
377 MSM_RPC_UNINTERRUPTIBLE);
378 audio->state = AUDIO_MVS_OPENED;
379 }
380
381 if (IS_ERR(audio->rpc_endpt)) {
382 MM_ERR("ALSA MVS RPC connect failed with version 0x%x\n",
383 MVS_VERS);
384 ret = PTR_ERR(audio->rpc_endpt);
385 audio->rpc_endpt = NULL;
386 goto err;
387 } else {
388 MM_DBG("ALSA MVS RPC connect succeeded\n");
389 if (audio->playback_substream == NULL ||
390 audio->capture_substream == NULL) {
391 if (substream->stream ==
392 SNDRV_PCM_STREAM_PLAYBACK) {
393 audio->playback_substream =
394 substream;
395 runtime->hw = msm_pcm_hardware;
396 } else if (substream->stream ==
397 SNDRV_PCM_STREAM_CAPTURE) {
398 audio->capture_substream =
399 substream;
400 runtime->hw = msm_pcm_hardware;
401 }
402 } else {
403 ret = -EPERM;
404 goto err;
405 }
406 ret = snd_pcm_hw_constraint_integer(runtime,
407 SNDRV_PCM_HW_PARAM_PERIODS);
408 if (ret < 0) {
409 MM_ERR("snd_pcm_hw_constraint_integer failed\n");
410 if (!audio->instance) {
411 msm_rpc_close(audio->rpc_endpt);
412 audio->rpc_endpt = NULL;
413 }
414 goto err;
415 }
416 audio->instance++;
417 }
418err:
419 mutex_unlock(&audio->lock);
420 return ret;
421}
422
423static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
424 snd_pcm_uframes_t hwoff, void __user *buf,
425 snd_pcm_uframes_t frames)
426{
427 int rc = 0;
428 int count = 0;
429 struct snd_pcm_runtime *runtime = substream->runtime;
430 struct audio_mvs_info_type *audio = &audio_mvs_info;
431 uint32_t index;
432 MM_DBG("%s\n", __func__);
433 if (audio->dl_play == 1) {
434 rc = wait_event_interruptible_timeout(audio->in_wait,
435 (audio->in_write - audio->in_read <= 3),
436 100 * HZ);
437 if (!rc) {
438 MM_ERR("MVS: write time out\n");
439 return -ETIMEDOUT;
440 } else if (rc < 0) {
441 MM_ERR("MVS: write was interrupted\n");
442 return -ERESTARTSYS;
443 }
444 }
445 mutex_lock(&audio->in_lock);
446 if (audio->state == AUDIO_MVS_ENABLED) {
447 index = audio->in_write % MVS_MAX_Q_LEN;
448 count = frames_to_bytes(runtime, frames);
449 if (count <= MVS_MAX_VOC_PKT_SIZE) {
450 rc = copy_from_user(audio->in[index].voc_pkt, buf,
451 count);
452 } else
453 rc = -ENOMEM;
454 if (!rc) {
455 audio->in[index].len = count;
456 audio->in_write++;
457 rc = count;
458 if (audio->in_write >= 3)
459 audio->dl_play = 1;
460 } else {
461 MM_ERR("Copy from user returned %d\n", rc);
462 rc = -EFAULT;
463 }
464
465 } else {
466 MM_ERR("Write performed in invalid state %d\n",
467 audio->state);
468 rc = -EINVAL;
469 }
470 mutex_unlock(&audio->in_lock);
471 return rc;
472}
473
474static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
475 int channel, snd_pcm_uframes_t hwoff,
476 void __user *buf, snd_pcm_uframes_t frames)
477{
478 int rc = 0;
479 int count = 0;
480 struct snd_pcm_runtime *runtime = substream->runtime;
481 struct audio_mvs_info_type *audio = &audio_mvs_info;
482 uint32_t index = 0;
483
484 MM_DBG("%s\n", __func__);
485
486 /* Ensure the driver has been enabled. */
487 if (audio->state != AUDIO_MVS_ENABLED) {
488 MM_ERR("Read performed in invalid state %d\n", audio->state);
489 return -EPERM;
490 }
491 rc = wait_event_interruptible_timeout(audio->out_wait,
492 (audio->out_read < audio->out_write ||
493 audio->state == AUDIO_MVS_CLOSING ||
494 audio->state == AUDIO_MVS_CLOSED),
495 100 * HZ);
496 if (!rc) {
497 MM_ERR("MVS: No UL data available\n");
498 return -ETIMEDOUT;
499 } else if (rc < 0) {
500 MM_ERR("MVS: Read was interrupted\n");
501 return -ERESTARTSYS;
502 }
503
504 mutex_lock(&audio->out_lock);
505 if (audio->state == AUDIO_MVS_CLOSING
506 || audio->state == AUDIO_MVS_CLOSED) {
507 rc = -EBUSY;
508 } else {
509 count = frames_to_bytes(runtime, frames);
510 index = audio->out_read % MVS_MAX_Q_LEN;
511 if (audio->out[index].len <= count) {
512 rc = copy_to_user(buf,
513 audio->out[index].voc_pkt,
514 audio->out[index].len);
515 if (rc == 0) {
516 rc = audio->out[index].len;
517 audio->out_read++;
518 } else {
519 MM_ERR("Copy to user %d\n", rc);
520 rc = -EFAULT;
521 }
522 } else
523 rc = -ENOMEM;
524 }
525 mutex_unlock(&audio->out_lock);
526 return rc;
527}
528
529static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
530 snd_pcm_uframes_t hwoff, void __user *buf,
531 snd_pcm_uframes_t frames)
532{
533 int ret = 0;
534 MM_DBG("%s\n", __func__);
535
536 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
537 ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
538 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
539 ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
540 return ret;
541}
542
543static int msm_pcm_close(struct snd_pcm_substream *substream)
544{
545 int rc = 0;
546 struct audio_mvs_info_type *audio = &audio_mvs_info;
547 struct audio_mvs_release_msg release_msg;
548 MM_DBG("%s\n", __func__);
549 memset(&release_msg, 0, sizeof(release_msg));
550 mutex_lock(&audio->lock);
551
552 audio->instance--;
553 wake_up(&audio->out_wait);
554
555 if (!audio->instance) {
556 if (audio->state == AUDIO_MVS_ENABLED) {
557 audio->state = AUDIO_MVS_CLOSING;
558 /* Release MVS. */
559 release_msg.client_id = cpu_to_be32(MVS_CLIENT_ID_VOIP);
560 msm_rpc_setup_req(&release_msg.rpc_hdr, audio->rpc_prog,
561 audio->rpc_ver,
562 MVS_RELEASE_PROC);
563 audio->rpc_status = RPC_STATUS_FAILURE;
564 rc = msm_rpc_write(audio->rpc_endpt, &release_msg,
565 sizeof(release_msg));
566 if (rc >= 0) {
567 MM_DBG("RPC write for release done\n");
568 rc = wait_event_timeout(audio->wait,
569 (audio->rpc_status !=
570 RPC_STATUS_FAILURE), 1 * HZ);
571 if (rc != 0) {
572 MM_DBG
573 ("Wait event for release succeeded\n");
574 rc = 0;
575 kthread_stop(audio->task);
576 audio->prepare_ack = 0;
577 audio->task = NULL;
578 del_timer_sync(&audio->timer);
579 } else {
580 MM_ERR
581 ("Wait event for release failed %d\n",
582 rc);
583 }
584 } else {
585 MM_ERR("RPC write for release failed %d\n", rc);
586 }
587 }
588 audio->state = AUDIO_MVS_CLOSED;
589 msm_rpc_close(audio->rpc_endpt);
590 audio->rpc_endpt = NULL;
591 }
592
593 mutex_unlock(&audio->lock);
594
595 wake_unlock(&audio->suspend_lock);
596 wake_unlock(&audio->idle_lock);
597 /* Release the IO buffers. */
598 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
599 mutex_lock(&audio->in_lock);
600 audio->in_write = 0;
601 audio->in_read = 0;
602 audio->playback_enable = 0;
603 audio->dl_play = 0;
604 audio->ack_dl_count = 0;
605 memset(audio->in[0].voc_pkt, 0,
606 MVS_MAX_VOC_PKT_SIZE * MVS_MAX_Q_LEN);
607 audio->in->len = 0;
608 audio->playback_substream = NULL;
609 mutex_unlock(&audio->in_lock);
610 } else {
611 mutex_lock(&audio->out_lock);
612 audio->out_write = 0;
613 audio->out_read = 0;
614 audio->capture_enable = 0;
615 audio->ack_ul_count = 0;
616 memset(audio->out[0].voc_pkt, 0,
617 MVS_MAX_VOC_PKT_SIZE * MVS_MAX_Q_LEN);
618 audio->out->len = 0;
619 audio->capture_substream = NULL;
620 mutex_unlock(&audio->out_lock);
621 }
622 return rc;
623}
624
625static int msm_mvs_pcm_setup(struct snd_pcm_substream *substream)
626{
627 int rc = 0;
628 struct audio_mvs_acquire_msg acquire_msg;
629 struct audio_mvs_info_type *audio = &audio_mvs_info;
630 memset(&acquire_msg, 0, sizeof(acquire_msg));
631
632 /*Create an Kthread */
633 MM_DBG("ALSA MVS thread creating\n");
634 if (!IS_ERR(audio->rpc_endpt)) {
635 audio->task =
636 kthread_run(audio_mvs_thread, audio,
637 "audio_alsa_mvs_thread");
638 if (!IS_ERR(audio->task)) {
639 MM_DBG("ALSA MVS thread create succeeded\n");
640 audio->rpc_prog = MVS_PROG;
641 audio->rpc_ver = MVS_VERS;
642 /* Acquire MVS. */
643 acquire_msg.acquire_args.client_id =
644 cpu_to_be32(MVS_CLIENT_ID_VOIP);
645 acquire_msg.acquire_args.cb_func_id =
646 cpu_to_be32(MVS_CB_FUNC_ID);
647 msm_rpc_setup_req(&acquire_msg.rpc_hdr,
648 audio->rpc_prog,
649 audio->rpc_ver,
650 MVS_ACQUIRE_PROC);
651 audio->rpc_status = RPC_STATUS_FAILURE;
652 rc = msm_rpc_write(audio->rpc_endpt,
653 &acquire_msg, sizeof(acquire_msg));
654 if (rc >= 0) {
655 MM_DBG("RPC write for acquire done\n");
656
657 rc = wait_event_timeout(audio->wait,
658 (audio->rpc_status !=
659 RPC_STATUS_FAILURE),
660 1 * HZ);
661 if (rc != 0) {
662 audio->state =
663 AUDIO_MVS_ACQUIRE;
664 rc = 0;
665 MM_DBG
666 ("MVS driver in acquire state\n");
667 } else {
668 MM_ERR
669 ("acquire Wait event failed %d\n",
670 rc);
671 rc = -EBUSY;
672 }
673 } else {
674 MM_ERR("RPC write for acquire failed %d\n",
675 rc);
676 rc = -EBUSY;
677 }
678 } else {
679 MM_ERR("ALSA MVS thread create failed\n");
680 rc = PTR_ERR(audio->task);
681 audio->task = NULL;
682 msm_rpc_close(audio->rpc_endpt);
683 audio->rpc_endpt = NULL;
684 }
685 } else {
686 MM_ERR("RPC connect is not setup with version 0x%x\n",
687 MVS_VERS);
688 rc = PTR_ERR(audio->rpc_endpt);
689 audio->rpc_endpt = NULL;
690 }
691 /*mvs mode setup */
692 if (audio->state == AUDIO_MVS_ACQUIRE)
693 rc = audio_mvs_setup_mvs(audio);
694 else
695 rc = -EBUSY;
696 return rc;
697}
698
699static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
700{
701 struct audio_mvs_info_type *prtd = &audio_mvs_info;
702 MM_DBG("%s\n", __func__);
703 prtd->pcm_playback_irq_pos = 0;
704 prtd->pcm_playback_buf_pos = 0;
705 /* rate and channels are sent to audio driver */
706 prtd->playback_enable = 1;
707 return 0;
708}
709
710static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
711{
712 struct audio_mvs_info_type *prtd = &audio_mvs_info;
713 prtd->pcm_capture_size = snd_pcm_lib_buffer_bytes(substream);
714 prtd->pcm_capture_count = snd_pcm_lib_period_bytes(substream);
715 prtd->pcm_capture_irq_pos = 0;
716 prtd->pcm_capture_buf_pos = 0;
717 prtd->capture_enable = 1;
718 return 0;
719}
720
721
722static int msm_pcm_prepare(struct snd_pcm_substream *substream)
723{
724 int rc = 0;
725 struct snd_pcm_runtime *runtime = substream->runtime;
726 struct audio_mvs_info_type *prtd = &audio_mvs_info;
727 unsigned long expiry = 0;
728 MM_DBG("%s\n", __func__);
729 prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
730 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
731
732 mutex_lock(&prtd->prepare_lock);
733 if (prtd->state == AUDIO_MVS_ENABLED)
734 goto enabled;
735 else if (prtd->state == AUDIO_MVS_PREPARING)
736 goto prepairing;
737 else if (prtd->state == AUDIO_MVS_OPENED) {
738 prtd->state = AUDIO_MVS_PREPARING;
739 rc = msm_mvs_pcm_setup(substream);
740 }
741 if (!rc) {
742 expiry = ((unsigned long)((prtd->pcm_count * 1000)
743 /(runtime->rate * runtime->channels * 2)));
744 expiry -= (expiry % 10);
745 prtd->timer.expires = jiffies + (msecs_to_jiffies(expiry));
746 prtd->expiry_delta = (msecs_to_jiffies(expiry));
747 if (prtd->expiry_delta <= 2)
748 prtd->expiry_delta = 1;
749 setup_timer(&prtd->timer, snd_pcm_mvs_timer,
750 (unsigned long)prtd);
751 prtd->ack_ul_count = 0;
752 prtd->ack_dl_count = 0;
753 add_timer(&prtd->timer);
754
755 } else {
756 MM_ERR("ALSA MVS setup is not done");
757 rc = -EPERM;
758 prtd->state = AUDIO_MVS_OPENED;
759 goto err;
760 }
761
762prepairing:
763 rc = wait_event_interruptible(prtd->prepare_wait,
764 (prtd->prepare_ack == 2));
765 if (rc < 0) {
766 MM_ERR("Wait event for prepare faild rc %d", rc);
767 rc = -EINTR;
768 prtd->state = AUDIO_MVS_OPENED;
769 goto err;
770 } else
771 MM_DBG("Wait event for prepare succeeded\n");
772
773 prtd->state = AUDIO_MVS_ENABLED;
774enabled:
775 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
776 rc = msm_pcm_playback_prepare(substream);
777 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
778 rc = msm_pcm_capture_prepare(substream);
779err:
780 mutex_unlock(&prtd->prepare_lock);
781 return rc;
782}
783
784int msm_mvs_pcm_hw_params(struct snd_pcm_substream *substream,
785 struct snd_pcm_hw_params *params)
786{
787 struct snd_pcm_runtime *runtime = substream->runtime;
788 MM_DBG("%s\n", __func__);
789 if (substream->pcm->device & 1) {
790 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
791 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
792 }
793 return 0;
794}
795
796static snd_pcm_uframes_t
797msm_pcm_playback_pointer(struct snd_pcm_substream *substream)
798{
799 struct snd_pcm_runtime *runtime = substream->runtime;
800 struct audio_mvs_info_type *audio = &audio_mvs_info;
801
802 if (audio->pcm_playback_irq_pos >= audio->pcm_size)
803 audio->pcm_playback_irq_pos = 0;
804 return bytes_to_frames(runtime, (audio->pcm_playback_irq_pos));
805}
806
807static snd_pcm_uframes_t
808msm_pcm_capture_pointer(struct snd_pcm_substream *substream)
809{
810 struct snd_pcm_runtime *runtime = substream->runtime;
811 struct audio_mvs_info_type *audio = &audio_mvs_info;
812
813 if (audio->pcm_capture_irq_pos >= audio->pcm_capture_size)
814 audio->pcm_capture_irq_pos = 0;
815 return bytes_to_frames(runtime, (audio->pcm_capture_irq_pos));
816}
817
818static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
819{
820 snd_pcm_uframes_t ret = 0;
821 MM_DBG("%s\n", __func__);
822 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
823 ret = msm_pcm_playback_pointer(substream);
824 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
825 ret = msm_pcm_capture_pointer(substream);
826 return ret;
827}
828
829static struct snd_pcm_ops msm_mvs_pcm_ops = {
830 .open = msm_pcm_open,
831 .copy = msm_pcm_copy,
832 .hw_params = msm_mvs_pcm_hw_params,
833 .close = msm_pcm_close,
834 .ioctl = snd_pcm_lib_ioctl,
835 .prepare = msm_pcm_prepare,
836 .trigger = msm_pcm_trigger,
837 .pointer = msm_pcm_pointer,
838
839};
840
841static int msm_pcm_new(struct snd_soc_pcm_runtime *rtd)
842{
843 int i, ret, offset = 0;
844 struct snd_pcm *pcm = rtd->pcm;
845
846 audio_mvs_info.mem_chunk = kmalloc(
847 2 * MVS_MAX_VOC_PKT_SIZE * MVS_MAX_Q_LEN, GFP_KERNEL);
848 if (audio_mvs_info.mem_chunk != NULL) {
849 audio_mvs_info.in_read = 0;
850 audio_mvs_info.in_write = 0;
851 audio_mvs_info.out_read = 0;
852 audio_mvs_info.out_write = 0;
853 for (i = 0; i < MVS_MAX_Q_LEN; i++) {
854 audio_mvs_info.in[i].voc_pkt =
855 audio_mvs_info.mem_chunk + offset;
856 offset = offset + MVS_MAX_VOC_PKT_SIZE;
857 }
858 for (i = 0; i < MVS_MAX_Q_LEN; i++) {
859 audio_mvs_info.out[i].voc_pkt =
860 audio_mvs_info.mem_chunk + offset;
861 offset = offset + MVS_MAX_VOC_PKT_SIZE;
862 }
863 audio_mvs_info.playback_substream = NULL;
864 audio_mvs_info.capture_substream = NULL;
865 } else {
866 MM_ERR("MSM MVS kmalloc failed\n");
867 return -ENODEV;
868 }
869
870
871 ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1);
872 if (ret)
873 return ret;
874 ret = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
875 if (ret)
876 return ret;
877 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &msm_mvs_pcm_ops);
878 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &msm_mvs_pcm_ops);
879
880 return 0;
881}
882
883struct snd_soc_platform_driver msm_mvs_soc_platform = {
884 .ops = &msm_mvs_pcm_ops,
885 .pcm_new = msm_pcm_new,
886};
887EXPORT_SYMBOL(msm_mvs_soc_platform);
888
889static __devinit int msm_pcm_probe(struct platform_device *pdev)
890{
891 return snd_soc_register_platform(&pdev->dev,
892 &msm_mvs_soc_platform);
893}
894
895static int msm_pcm_remove(struct platform_device *pdev)
896{
897 snd_soc_unregister_platform(&pdev->dev);
898 return 0;
899}
900
901static struct platform_driver msm_pcm_driver = {
902 .driver = {
903 .name = "msm-mvs-audio",
904 .owner = THIS_MODULE,
905 },
906 .probe = msm_pcm_probe,
907 .remove = __devexit_p(msm_pcm_remove),
908};
909
910static int __init msm_mvs_soc_platform_init(void)
911{
912 memset(&audio_mvs_info, 0, sizeof(audio_mvs_info));
913 mutex_init(&audio_mvs_info.lock);
914 mutex_init(&audio_mvs_info.prepare_lock);
915 mutex_init(&audio_mvs_info.in_lock);
916 mutex_init(&audio_mvs_info.out_lock);
917 init_waitqueue_head(&audio_mvs_info.wait);
918 init_waitqueue_head(&audio_mvs_info.prepare_wait);
919 init_waitqueue_head(&audio_mvs_info.out_wait);
920 init_waitqueue_head(&audio_mvs_info.in_wait);
921 wake_lock_init(&audio_mvs_info.suspend_lock, WAKE_LOCK_SUSPEND,
922 "audio_mvs_suspend");
923 wake_lock_init(&audio_mvs_info.idle_lock, WAKE_LOCK_IDLE,
924 "audio_mvs_idle");
925 return platform_driver_register(&msm_pcm_driver);
926}
927module_init(msm_mvs_soc_platform_init);
928
929static void __exit msm_mvs_soc_platform_exit(void)
930{
931 platform_driver_unregister(&msm_pcm_driver);
932}
933module_exit(msm_mvs_soc_platform_exit);
934
935MODULE_DESCRIPTION("MVS PCM module platform driver");
936MODULE_LICENSE("GPL v2");