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