blob: a685af5ee791df634828784900829debd4ad24f6 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * amrnb audio input device
3 *
4 * Copyright (C) 2008 Google, Inc.
5 * Copyright (C) 2008 HTC Corporation
6 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/fs.h>
21#include <linux/miscdevice.h>
22#include <linux/uaccess.h>
23#include <linux/sched.h>
24#include <linux/wait.h>
25#include <linux/dma-mapping.h>
26#include <linux/msm_audio_amrnb.h>
27#include <linux/android_pmem.h>
28
29#include <asm/atomic.h>
30#include <asm/ioctls.h>
31
32#include <mach/msm_adsp.h>
33#include <mach/qdsp5v2/qdsp5audreccmdi.h>
34#include <mach/qdsp5v2/qdsp5audrecmsg.h>
35#include <mach/qdsp5v2/audpreproc.h>
36#include <mach/qdsp5v2/audio_dev_ctl.h>
37#include <mach/debug_mm.h>
38
39/* FRAME_NUM must be a power of two */
40#define FRAME_NUM (8)
41#define FRAME_SIZE (22 * 2) /* 36 bytes data */
42#define DMASZ (FRAME_SIZE * FRAME_NUM)
43
44struct buffer {
45 void *data;
46 uint32_t size;
47 uint32_t read;
48 uint32_t addr;
49};
50
51struct audio_in {
52 struct buffer in[FRAME_NUM];
53
54 spinlock_t dsp_lock;
55
56 atomic_t in_bytes;
57 atomic_t in_samples;
58
59 struct mutex lock;
60 struct mutex read_lock;
61 wait_queue_head_t wait;
62 wait_queue_head_t wait_enable;
63
64 struct msm_adsp_module *audrec;
65 struct audrec_session_info session_info; /*audrec session info*/
66
67 /* configuration to use on next enable */
68 uint32_t buffer_size; /* Frame size (36 bytes) */
69 uint32_t enc_type;
70
71 int dtx_mode;
72 uint32_t frame_format;
73 uint32_t used_mode;
74 uint32_t rec_mode;
75
76 uint32_t dsp_cnt;
77 uint32_t in_head; /* next buffer dsp will write */
78 uint32_t in_tail; /* next buffer read() will read */
79 uint32_t in_count; /* number of buffers available to read() */
80 uint32_t mode;
81
82 const char *module_name;
83 unsigned queue_ids;
84 uint16_t enc_id;
85
86 uint16_t source; /* Encoding source bit mask */
87 uint32_t device_events;
88 uint32_t in_call;
89 uint32_t dev_cnt;
90 int voice_state;
91 spinlock_t dev_lock;
92
93 /* data allocated for various buffers */
94 char *data;
95 dma_addr_t phys;
96
97 int opened;
98 int enabled;
99 int running;
100 int stopped; /* set when stopped, cleared on flush */
101};
102
103struct audio_frame {
104 uint16_t frame_count_lsw;
105 uint16_t frame_count_msw;
106 uint16_t frame_length;
107 uint16_t erased_pcm;
108 unsigned char raw_bitstream[]; /* samples */
109} __attribute__((packed));
110
111/* Audrec Queue command sent macro's */
112#define audrec_send_bitstreamqueue(audio, cmd, len) \
113 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
114 cmd, len)
115
116#define audrec_send_audrecqueue(audio, cmd, len) \
117 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
118 cmd, len)
119
120struct audio_in the_audio_amrnb_in;
121
122/* DSP command send functions */
123static int audamrnb_in_enc_config(struct audio_in *audio, int enable);
124static int audamrnb_in_param_config(struct audio_in *audio);
125static int audamrnb_in_mem_config(struct audio_in *audio);
126static int audamrnb_in_record_config(struct audio_in *audio, int enable);
127static int audamrnb_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
128
129static void audamrnb_in_get_dsp_frames(struct audio_in *audio);
130
131static void audamrnb_in_flush(struct audio_in *audio);
132
133static void amrnb_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
134 void *private_data)
135{
136 struct audio_in *audio = (struct audio_in *) private_data;
137 unsigned long flags;
138
139 MM_DBG("evt_id = 0x%8x\n", evt_id);
140 switch (evt_id) {
141 case AUDDEV_EVT_DEV_RDY: {
142 MM_DBG("AUDDEV_EVT_DEV_RDY\n");
143 spin_lock_irqsave(&audio->dev_lock, flags);
144 audio->dev_cnt++;
145 if (!audio->in_call)
146 audio->source |= (0x1 << evt_payload->routing_id);
147 spin_unlock_irqrestore(&audio->dev_lock, flags);
148
149 if ((audio->running == 1) && (audio->enabled == 1))
150 audamrnb_in_record_config(audio, 1);
151
152 break;
153 }
154 case AUDDEV_EVT_DEV_RLS: {
155 MM_DBG("AUDDEV_EVT_DEV_RLS\n");
156 spin_lock_irqsave(&audio->dev_lock, flags);
157 audio->dev_cnt--;
158 if (!audio->in_call)
159 audio->source &= ~(0x1 << evt_payload->routing_id);
160 spin_unlock_irqrestore(&audio->dev_lock, flags);
161
162 if ((!audio->running) || (!audio->enabled))
163 break;
164
165 /* Turn of as per source */
166 if (audio->source)
167 audamrnb_in_record_config(audio, 1);
168 else
169 /* Turn off all */
170 audamrnb_in_record_config(audio, 0);
171
172 break;
173 }
174 case AUDDEV_EVT_VOICE_STATE_CHG: {
175 MM_DBG("AUDDEV_EVT_VOICE_STATE_CHG, state = %d\n",
176 evt_payload->voice_state);
177 audio->voice_state = evt_payload->voice_state;
178 if (audio->in_call && audio->running) {
179 if (audio->voice_state == VOICE_STATE_INCALL)
180 audamrnb_in_record_config(audio, 1);
181 else if (audio->voice_state == VOICE_STATE_OFFCALL) {
182 audamrnb_in_record_config(audio, 0);
183 wake_up(&audio->wait);
184 }
185 }
186
187 break;
188 }
189 default:
190 MM_ERR("wrong event %d\n", evt_id);
191 break;
192 }
193}
194
195/* ------------------- dsp preproc event handler--------------------- */
196static void audpreproc_dsp_event(void *data, unsigned id, void *msg)
197{
198 struct audio_in *audio = data;
199
200 switch (id) {
201 case AUDPREPROC_ERROR_MSG: {
202 struct audpreproc_err_msg *err_msg = msg;
203
204 MM_ERR("ERROR_MSG: stream id %d err idx %d\n",
205 err_msg->stream_id, err_msg->aud_preproc_err_idx);
206 /* Error case */
207 wake_up(&audio->wait_enable);
208 break;
209 }
210 case AUDPREPROC_CMD_CFG_DONE_MSG: {
211 MM_DBG("CMD_CFG_DONE_MSG \n");
212 break;
213 }
214 case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {
215 struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;
216
217 MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \
218 0x%8x\n", enc_cfg_msg->stream_id,
219 enc_cfg_msg->rec_enc_type);
220 /* Encoder enable success */
221 if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE)
222 audamrnb_in_param_config(audio);
223 else { /* Encoder disable success */
224 audio->running = 0;
225 audamrnb_in_record_config(audio, 0);
226 }
227 break;
228 }
229 case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
230 MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG \n");
231 audamrnb_in_mem_config(audio);
232 break;
233 }
234 case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {
235 MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n");
236 wake_up(&audio->wait_enable);
237 break;
238 }
239 default:
240 MM_ERR("Unknown Event id %d\n", id);
241 }
242}
243
244/* ------------------- dsp audrec event handler--------------------- */
245static void audrec_dsp_event(void *data, unsigned id, size_t len,
246 void (*getevent)(void *ptr, size_t len))
247{
248 struct audio_in *audio = data;
249
250 switch (id) {
251 case AUDREC_CMD_MEM_CFG_DONE_MSG: {
252 MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n");
253 audio->running = 1;
254 if ((!audio->in_call && (audio->dev_cnt > 0)) ||
255 (audio->in_call &&
256 (audio->voice_state == VOICE_STATE_INCALL)))
257 audamrnb_in_record_config(audio, 1);
258 break;
259 }
260 case AUDREC_FATAL_ERR_MSG: {
261 struct audrec_fatal_err_msg fatal_err_msg;
262
263 getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
264 MM_ERR("FATAL_ERR_MSG: err id %d\n",
265 fatal_err_msg.audrec_err_id);
266 /* Error stop the encoder */
267 audio->stopped = 1;
268 wake_up(&audio->wait);
269 break;
270 }
271 case AUDREC_UP_PACKET_READY_MSG: {
272 struct audrec_up_pkt_ready_msg pkt_ready_msg;
273
274 getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN);
275 MM_DBG("UP_PACKET_READY_MSG: write cnt lsw %d \
276 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
277 pkt_ready_msg.audrec_packet_write_cnt_lsw, \
278 pkt_ready_msg.audrec_packet_write_cnt_msw, \
279 pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \
280 pkt_ready_msg.audrec_up_prev_read_cnt_msw);
281
282 audamrnb_in_get_dsp_frames(audio);
283 break;
284 }
285 case ADSP_MESSAGE_ID: {
286 MM_DBG("Received ADSP event:module audrectask\n");
287 break;
288 }
289 default:
290 MM_ERR("Unknown Event id %d\n", id);
291 }
292}
293
294static void audamrnb_in_get_dsp_frames(struct audio_in *audio)
295{
296 struct audio_frame *frame;
297 uint32_t index;
298 unsigned long flags;
299
300 index = audio->in_head;
301
302 frame = (void *) (((char *)audio->in[index].data) - \
303 sizeof(*frame));
304
305 spin_lock_irqsave(&audio->dsp_lock, flags);
306 audio->in[index].size = frame->frame_length;
307
308 /* statistics of read */
309 atomic_add(audio->in[index].size, &audio->in_bytes);
310 atomic_add(1, &audio->in_samples);
311
312 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
313
314 /* If overflow, move the tail index foward. */
315 if (audio->in_head == audio->in_tail)
316 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
317 else
318 audio->in_count++;
319
320 audamrnb_dsp_read_buffer(audio, audio->dsp_cnt++);
321 spin_unlock_irqrestore(&audio->dsp_lock, flags);
322
323 wake_up(&audio->wait);
324}
325struct msm_adsp_ops audrec_amrnb_adsp_ops = {
326 .event = audrec_dsp_event,
327};
328
329static int audamrnb_in_enc_config(struct audio_in *audio, int enable)
330{
331 struct audpreproc_audrec_cmd_enc_cfg cmd;
332
333 memset(&cmd, 0, sizeof(cmd));
334 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG_2;
335 cmd.stream_id = audio->enc_id;
336
337 if (enable)
338 cmd.audrec_enc_type = audio->enc_type | ENCODE_ENABLE;
339 else
340 cmd.audrec_enc_type &= ~(ENCODE_ENABLE);
341
342 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
343}
344
345static int audamrnb_in_param_config(struct audio_in *audio)
346{
347 struct audpreproc_audrec_cmd_parm_cfg_amrnb cmd;
348
349 memset(&cmd, 0, sizeof(cmd));
350 cmd.common.cmd_id = AUDPREPROC_AUDREC_CMD_PARAM_CFG;
351 cmd.common.stream_id = audio->enc_id;
352
353 cmd.dtx_mode = audio->dtx_mode;
354 cmd.test_mode = -1; /* Default set to -1 */
355 cmd.used_mode = audio->used_mode;
356
357 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
358}
359
360/* To Do: msm_snddev_route_enc(audio->enc_id); */
361static int audamrnb_in_record_config(struct audio_in *audio, int enable)
362{
363 struct audpreproc_afe_cmd_audio_record_cfg cmd;
364
365 memset(&cmd, 0, sizeof(cmd));
366 cmd.cmd_id = AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG;
367 cmd.stream_id = audio->enc_id;
368 if (enable)
369 cmd.destination_activity = AUDIO_RECORDING_TURN_ON;
370 else
371 cmd.destination_activity = AUDIO_RECORDING_TURN_OFF;
372
373 cmd.source_mix_mask = audio->source;
374 if (audio->enc_id == 2) {
375 if ((cmd.source_mix_mask &
376 INTERNAL_CODEC_TX_SOURCE_MIX_MASK) ||
377 (cmd.source_mix_mask & AUX_CODEC_TX_SOURCE_MIX_MASK) ||
378 (cmd.source_mix_mask & VOICE_UL_SOURCE_MIX_MASK) ||
379 (cmd.source_mix_mask & VOICE_DL_SOURCE_MIX_MASK)) {
380 cmd.pipe_id = SOURCE_PIPE_1;
381 }
382 if (cmd.source_mix_mask &
383 AUDPP_A2DP_PIPE_SOURCE_MIX_MASK)
384 cmd.pipe_id |= SOURCE_PIPE_0;
385 }
386
387 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
388}
389
390static int audamrnb_in_mem_config(struct audio_in *audio)
391{
392 struct audrec_cmd_arecmem_cfg cmd;
393 uint16_t *data = (void *) audio->data;
394 int n;
395
396 memset(&cmd, 0, sizeof(cmd));
397 cmd.cmd_id = AUDREC_CMD_MEM_CFG_CMD;
398 cmd.audrec_up_pkt_intm_count = 1;
399 cmd.audrec_ext_pkt_start_addr_msw = audio->phys >> 16;
400 cmd.audrec_ext_pkt_start_addr_lsw = audio->phys;
401 cmd.audrec_ext_pkt_buf_number = FRAME_NUM;
402
403 /* prepare buffer pointers:
404 * 36 bytes amrnb packet + 4 halfword header
405 */
406 for (n = 0; n < FRAME_NUM; n++) {
407 audio->in[n].data = data + 4;
408 data += (FRAME_SIZE/2); /* word increment */
409 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 8));
410 }
411
412 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
413}
414
415static int audamrnb_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
416{
417 struct up_audrec_packet_ext_ptr cmd;
418
419 memset(&cmd, 0, sizeof(cmd));
420 cmd.cmd_id = UP_AUDREC_PACKET_EXT_PTR;
421 cmd.audrec_up_curr_read_count_msw = read_cnt >> 16;
422 cmd.audrec_up_curr_read_count_lsw = read_cnt;
423
424 return audrec_send_bitstreamqueue(audio, &cmd, sizeof(cmd));
425}
426
427/* must be called with audio->lock held */
428static int audamrnb_in_enable(struct audio_in *audio)
429{
430 if (audio->enabled)
431 return 0;
432
433 if (audpreproc_enable(audio->enc_id, &audpreproc_dsp_event, audio)) {
434 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
435 return -ENODEV;
436 }
437
438 if (msm_adsp_enable(audio->audrec)) {
439 MM_ERR("msm_adsp_enable(audrec) failed\n");
440 audpreproc_disable(audio->enc_id, audio);
441 return -ENODEV;
442 }
443 audio->enabled = 1;
444 audamrnb_in_enc_config(audio, 1);
445
446 return 0;
447}
448
449/* must be called with audio->lock held */
450static int audamrnb_in_disable(struct audio_in *audio)
451{
452 if (audio->enabled) {
453 audio->enabled = 0;
454 audamrnb_in_enc_config(audio, 0);
455 wake_up(&audio->wait);
456 wait_event_interruptible_timeout(audio->wait_enable,
457 audio->running == 0, 1*HZ);
458 msm_adsp_disable(audio->audrec);
459 audpreproc_disable(audio->enc_id, audio);
460 }
461 return 0;
462}
463
464static void audamrnb_in_flush(struct audio_in *audio)
465{
466 int i;
467
468 audio->dsp_cnt = 0;
469 audio->in_head = 0;
470 audio->in_tail = 0;
471 audio->in_count = 0;
472 for (i = 0; i < FRAME_NUM; i++) {
473 audio->in[i].size = 0;
474 audio->in[i].read = 0;
475 }
476 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
477 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
478 atomic_set(&audio->in_bytes, 0);
479 atomic_set(&audio->in_samples, 0);
480}
481
482/* ------------------- device --------------------- */
483static long audamrnb_in_ioctl(struct file *file,
484 unsigned int cmd, unsigned long arg)
485{
486 struct audio_in *audio = file->private_data;
487 int rc = 0;
488
489 if (cmd == AUDIO_GET_STATS) {
490 struct msm_audio_stats stats;
491 stats.byte_count = atomic_read(&audio->in_bytes);
492 stats.sample_count = atomic_read(&audio->in_samples);
493 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
494 return -EFAULT;
495 return rc;
496 }
497
498 mutex_lock(&audio->lock);
499 switch (cmd) {
500 case AUDIO_START: {
501 uint32_t freq;
502 freq = 48000;
503 MM_DBG("AUDIO_START\n");
504 if (audio->in_call && (audio->voice_state !=
505 VOICE_STATE_INCALL)) {
506 rc = -EPERM;
507 break;
508 }
509 rc = msm_snddev_request_freq(&freq, audio->enc_id,
510 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
511 MM_DBG("sample rate configured %d\n", freq);
512 if (rc < 0) {
513 MM_DBG(" Sample rate can not be set, return code %d\n",
514 rc);
515 msm_snddev_withdraw_freq(audio->enc_id,
516 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
517 MM_DBG("msm_snddev_withdraw_freq\n");
518 break;
519 }
520 /*update aurec session info in audpreproc layer*/
521 audio->session_info.session_id = audio->enc_id;
522 /*amrnb works only on 8KHz*/
523 audio->session_info.sampling_freq = 8000;
524 audpreproc_update_audrec_info(&audio->session_info);
525 rc = audamrnb_in_enable(audio);
526 if (!rc) {
527 rc =
528 wait_event_interruptible_timeout(audio->wait_enable,
529 audio->running != 0, 1*HZ);
530 MM_DBG("state %d rc = %d\n", audio->running, rc);
531
532 if (audio->running == 0)
533 rc = -ENODEV;
534 else
535 rc = 0;
536 }
537 audio->stopped = 0;
538 break;
539 }
540 case AUDIO_STOP: {
541 /*reset the sampling frequency information at audpreproc layer*/
542 audio->session_info.sampling_freq = 0;
543 audpreproc_update_audrec_info(&audio->session_info);
544 rc = audamrnb_in_disable(audio);
545 rc = msm_snddev_withdraw_freq(audio->enc_id,
546 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
547 MM_DBG("msm_snddev_withdraw_freq\n");
548 audio->stopped = 1;
549 break;
550 }
551 case AUDIO_FLUSH: {
552 if (audio->stopped) {
553 /* Make sure we're stopped and we wake any threads
554 * that might be blocked holding the read_lock.
555 * While audio->stopped read threads will always
556 * exit immediately.
557 */
558 wake_up(&audio->wait);
559 mutex_lock(&audio->read_lock);
560 audamrnb_in_flush(audio);
561 mutex_unlock(&audio->read_lock);
562 }
563 break;
564 }
565 case AUDIO_SET_STREAM_CONFIG: {
566 struct msm_audio_stream_config cfg;
567 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
568 rc = -EFAULT;
569 break;
570 }
571 /* Allow only single frame */
572 if (cfg.buffer_size != (FRAME_SIZE - 8))
573 rc = -EINVAL;
574 else
575 audio->buffer_size = cfg.buffer_size;
576 break;
577 }
578 case AUDIO_GET_STREAM_CONFIG: {
579 struct msm_audio_stream_config cfg;
580 memset(&cfg, 0, sizeof(cfg));
581 cfg.buffer_size = audio->buffer_size;
582 cfg.buffer_count = FRAME_NUM;
583 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
584 rc = -EFAULT;
585 break;
586 }
587 case AUDIO_GET_AMRNB_ENC_CONFIG_V2: {
588 struct msm_audio_amrnb_enc_config_v2 cfg;
589 memset(&cfg, 0, sizeof(cfg));
590 cfg.dtx_enable = ((audio->dtx_mode == -1) ? 1 : 0);
591 cfg.band_mode = audio->used_mode;
592 cfg.frame_format = audio->frame_format;
593 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
594 rc = -EFAULT;
595 break;
596 }
597 case AUDIO_SET_AMRNB_ENC_CONFIG_V2: {
598 struct msm_audio_amrnb_enc_config_v2 cfg;
599 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
600 rc = -EFAULT;
601 break;
602 }
603 /* DSP does not support any other than default format */
604 if (audio->frame_format != cfg.frame_format) {
605 rc = -EINVAL;
606 break;
607 }
608 if (cfg.dtx_enable == 0)
609 audio->dtx_mode = 0;
610 else if (cfg.dtx_enable == 1)
611 audio->dtx_mode = -1;
612 else {
613 rc = -EINVAL;
614 break;
615 }
616 audio->used_mode = cfg.band_mode;
617 break;
618 }
619 case AUDIO_SET_INCALL: {
620 struct msm_voicerec_mode cfg;
621 unsigned long flags;
622 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
623 rc = -EFAULT;
624 break;
625 }
626 if (cfg.rec_mode != VOC_REC_BOTH &&
627 cfg.rec_mode != VOC_REC_UPLINK &&
628 cfg.rec_mode != VOC_REC_DOWNLINK) {
629 MM_ERR("invalid rec_mode\n");
630 rc = -EINVAL;
631 break;
632 } else {
633 spin_lock_irqsave(&audio->dev_lock, flags);
634 if (cfg.rec_mode == VOC_REC_UPLINK)
635 audio->source = VOICE_UL_SOURCE_MIX_MASK;
636 else if (cfg.rec_mode == VOC_REC_DOWNLINK)
637 audio->source = VOICE_DL_SOURCE_MIX_MASK;
638 else
639 audio->source = VOICE_DL_SOURCE_MIX_MASK |
640 VOICE_UL_SOURCE_MIX_MASK ;
641 audio->in_call = 1;
642 spin_unlock_irqrestore(&audio->dev_lock, flags);
643 }
644 break;
645 }
646 case AUDIO_GET_SESSION_ID: {
647 if (copy_to_user((void *) arg, &audio->enc_id,
648 sizeof(unsigned short))) {
649 rc = -EFAULT;
650 }
651 break;
652 }
653 default:
654 rc = -EINVAL;
655 }
656 mutex_unlock(&audio->lock);
657 return rc;
658}
659
660static ssize_t audamrnb_in_read(struct file *file,
661 char __user *buf,
662 size_t count, loff_t *pos)
663{
664 struct audio_in *audio = file->private_data;
665 unsigned long flags;
666 const char __user *start = buf;
667 void *data;
668 uint32_t index;
669 uint32_t size;
670 int rc = 0;
671
672 mutex_lock(&audio->read_lock);
673 while (count > 0) {
674 rc = wait_event_interruptible(
675 audio->wait, (audio->in_count > 0) || audio->stopped
676 || (audio->in_call && audio->running &&
677 (audio->voice_state == VOICE_STATE_OFFCALL)));
678 if (rc < 0)
679 break;
680
681 if (!audio->in_count) {
682 if (audio->stopped) {
683 rc = 0;/* End of File */
684 break;
685 } else if (audio->in_call && audio->running &&
686 (audio->voice_state == VOICE_STATE_OFFCALL)) {
687 MM_DBG("Not Permitted Voice Terminated\n");
688 rc = -EPERM; /* Voice Call stopped */
689 break;
690 }
691 }
692
693 index = audio->in_tail;
694 data = (uint8_t *) audio->in[index].data;
695 size = audio->in[index].size;
696 if (count >= size) {
697 if (copy_to_user(buf, data, size)) {
698 rc = -EFAULT;
699 break;
700 }
701 spin_lock_irqsave(&audio->dsp_lock, flags);
702 if (index != audio->in_tail) {
703 /* overrun -- data is
704 * invalid and we need to retry */
705 spin_unlock_irqrestore(&audio->dsp_lock, flags);
706 continue;
707 }
708 audio->in[index].size = 0;
709 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
710 audio->in_count--;
711 spin_unlock_irqrestore(&audio->dsp_lock, flags);
712 count -= size;
713 buf += size;
714 } else {
715 MM_ERR("short read\n");
716 break;
717 }
718 }
719 mutex_unlock(&audio->read_lock);
720
721 if (buf > start)
722 return buf - start;
723
724 return rc;
725}
726
727static ssize_t audamrnb_in_write(struct file *file,
728 const char __user *buf,
729 size_t count, loff_t *pos)
730{
731 return -EINVAL;
732}
733
734static int audamrnb_in_release(struct inode *inode, struct file *file)
735{
736 struct audio_in *audio = file->private_data;
737
738 MM_DBG("\n");
739 mutex_lock(&audio->lock);
740 audio->in_call = 0;
741 /* with draw frequency for session
742 incase not stopped the driver */
743 msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX,
744 AUDDEV_CLNT_ENC);
745 auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id);
746 /*reset the sampling frequency information at audpreproc layer*/
747 audio->session_info.sampling_freq = 0;
748 audpreproc_update_audrec_info(&audio->session_info);
749 audamrnb_in_disable(audio);
750 audamrnb_in_flush(audio);
751 msm_adsp_put(audio->audrec);
752 audpreproc_aenc_free(audio->enc_id);
753 audio->audrec = NULL;
754 audio->opened = 0;
755 if (audio->data) {
756 iounmap(audio->data);
757 pmem_kfree(audio->phys);
758 audio->data = NULL;
759 }
760 mutex_unlock(&audio->lock);
761 return 0;
762}
763
764static int audamrnb_in_open(struct inode *inode, struct file *file)
765{
766 struct audio_in *audio = &the_audio_amrnb_in;
767 int rc;
768 int encid;
769
770 mutex_lock(&audio->lock);
771 if (audio->opened) {
772 rc = -EBUSY;
773 goto done;
774 }
775 audio->phys = pmem_kalloc(DMASZ, PMEM_MEMTYPE_EBI1|
776 PMEM_ALIGNMENT_4K);
777 if (!IS_ERR((void *)audio->phys)) {
778 audio->data = ioremap(audio->phys, DMASZ);
779 if (!audio->data) {
780 MM_ERR("could not allocate DMA buffers\n");
781 rc = -ENOMEM;
782 pmem_kfree(audio->phys);
783 goto done;
784 }
785 } else {
786 MM_ERR("could not allocate DMA buffers\n");
787 rc = -ENOMEM;
788 goto done;
789 }
790 MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
791 (int) audio->data, (int) audio->phys);
792 if ((file->f_mode & FMODE_WRITE) &&
793 (file->f_mode & FMODE_READ)) {
794 rc = -EACCES;
795 MM_ERR("Non tunnel encoding is not supported\n");
796 goto done;
797 } else if (!(file->f_mode & FMODE_WRITE) &&
798 (file->f_mode & FMODE_READ)) {
799 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
800 MM_DBG("Opened for tunnel mode encoding\n");
801 } else {
802 rc = -EACCES;
803 goto done;
804 }
805
806
807 /* Settings will be re-config at AUDIO_SET_CONFIG,
808 * but at least we need to have initial config
809 */
810 audio->buffer_size = (FRAME_SIZE - 8);
811 audio->enc_type = ENC_TYPE_AMRNB | audio->mode;
812 audio->dtx_mode = -1;
813 audio->frame_format = 0;
814 audio->used_mode = 7; /* Bit Rate 12.2 kbps MR122 */
815
816 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
817 &audio->queue_ids);
818 if (encid < 0) {
819 MM_ERR("No free encoder available\n");
820 rc = -ENODEV;
821 goto done;
822 }
823 audio->enc_id = encid;
824
825 rc = msm_adsp_get(audio->module_name, &audio->audrec,
826 &audrec_amrnb_adsp_ops, audio);
827
828 if (rc) {
829 audpreproc_aenc_free(audio->enc_id);
830 goto done;
831 }
832
833 audio->stopped = 0;
834 audio->source = 0;
835
836 audamrnb_in_flush(audio);
837
838 audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
839 AUDDEV_EVT_VOICE_STATE_CHG;
840
841 audio->voice_state = msm_get_voice_state();
842 rc = auddev_register_evt_listner(audio->device_events,
843 AUDDEV_CLNT_ENC, audio->enc_id,
844 amrnb_in_listener, (void *) audio);
845 if (rc) {
846 MM_ERR("failed to register device event listener\n");
847 goto evt_error;
848 }
849 file->private_data = audio;
850 audio->opened = 1;
851done:
852 mutex_unlock(&audio->lock);
853 return rc;
854evt_error:
855 msm_adsp_put(audio->audrec);
856 audpreproc_aenc_free(audio->enc_id);
857 mutex_unlock(&audio->lock);
858 return rc;
859}
860
861static const struct file_operations audio_in_fops = {
862 .owner = THIS_MODULE,
863 .open = audamrnb_in_open,
864 .release = audamrnb_in_release,
865 .read = audamrnb_in_read,
866 .write = audamrnb_in_write,
867 .unlocked_ioctl = audamrnb_in_ioctl,
868};
869
870struct miscdevice audio_amrnb_in_misc = {
871 .minor = MISC_DYNAMIC_MINOR,
872 .name = "msm_amrnb_in",
873 .fops = &audio_in_fops,
874};
875
876static int __init audamrnb_in_init(void)
877{
878 mutex_init(&the_audio_amrnb_in.lock);
879 mutex_init(&the_audio_amrnb_in.read_lock);
880 spin_lock_init(&the_audio_amrnb_in.dsp_lock);
881 spin_lock_init(&the_audio_amrnb_in.dev_lock);
882 init_waitqueue_head(&the_audio_amrnb_in.wait);
883 init_waitqueue_head(&the_audio_amrnb_in.wait_enable);
884 return misc_register(&audio_amrnb_in_misc);
885}
886
887device_initcall(audamrnb_in_init);