blob: 8d99a3d4fe34ed671ffebc1a1b08855b4907bcbc [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
2 *
3 * amrnb encoder device
4 *
5 * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
6 *
7 * This code is based in part on arch/arm/mach-msm/qdsp5/audio_in.c, which is
8 * Copyright (C) 2008 Google, Inc.
9 * Copyright (C) 2008 HTC Corporation
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * See the GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you can find it at http://www.fsf.org.
22 *
23 */
24
25#include <linux/module.h>
26#include <linux/fs.h>
27#include <linux/miscdevice.h>
28#include <linux/uaccess.h>
29#include <linux/kthread.h>
30#include <linux/wait.h>
31#include <linux/dma-mapping.h>
32#include <linux/debugfs.h>
33#include <linux/delay.h>
34
35#include <asm/atomic.h>
36#include <asm/ioctls.h>
37#include <mach/msm_adsp.h>
38#include <mach/msm_rpcrouter.h>
39#include <linux/msm_audio_amrnb.h>
40
41#include "audmgr.h"
42
43#include <mach/qdsp5/qdsp5audpreproccmdi.h>
44#include <mach/qdsp5/qdsp5audpreprocmsg.h>
45#include <mach/qdsp5/qdsp5audreccmdi.h>
46#include <mach/qdsp5/qdsp5audrecmsg.h>
47#include <mach/debug_mm.h>
48
49/* FRAME_NUM must be a power of two */
50#define FRAME_NUM (8)
51#define FRAME_SIZE (22 * 2)
52#define DMASZ (FRAME_SIZE * FRAME_NUM)
53
54struct buffer {
55 void *data;
56 uint32_t size;
57 uint32_t read;
58 uint32_t addr;
59};
60
61struct audio_amrnb_in {
62 struct buffer in[FRAME_NUM];
63
64 spinlock_t dsp_lock;
65
66 atomic_t in_bytes;
67
68 struct mutex lock;
69 struct mutex read_lock;
70 wait_queue_head_t wait;
71
72 uint16_t audrec_obj_idx;
73
74 /* configuration to use on enable */
75 uint32_t buffer_size;
76 uint32_t enc_type; /* 0 for WAV ,1 for AAC,10 for AMRNB */
77 struct msm_audio_amrnb_enc_config amrnb_enc_cfg;
78
79 uint32_t dsp_cnt;
80 uint32_t in_head; /* next buffer dsp will write */
81 uint32_t in_tail; /* next buffer read() will read */
82 uint32_t in_count; /* number of buffers available to read() */
83
84 struct audmgr audmgr;
85
86 /* data allocated for various buffers */
87 char *data;
88 dma_addr_t phys;
89
90 int opened;
91 int enabled;
92 int running;
93 int stopped; /* set when stopped, cleared on flush */
94
95};
96
97static int audio_amrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable);
98static int audio_amrnb_in_encmem_config(struct audio_amrnb_in *audio);
99static int audio_amrnb_in_encparam_config(struct audio_amrnb_in *audio);
100static int audio_amrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
101 uint32_t read_cnt);
102static void audio_amrnb_in_flush(struct audio_amrnb_in *audio);
103static void audio_amrnb_in_dsp_event(void *data, unsigned id, uint16_t *msg);
104
105static struct audio_amrnb_in the_audio_amrnb_in;
106
107/* must be called with audio->lock held */
108static int audio_amrnb_in_enable(struct audio_amrnb_in *audio)
109{
110 struct audmgr_config cfg;
111 int rc;
112
113 if (audio->enabled)
114 return 0;
115
116 cfg.tx_rate = RPC_AUD_DEF_SAMPLE_RATE_8000;
117 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
118 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
119 cfg.codec = RPC_AUD_DEF_CODEC_AMR_NB;
120 cfg.snd_method = RPC_SND_METHOD_MIDI;
121
122 rc = audmgr_enable(&audio->audmgr, &cfg);
123 if (rc < 0)
124 return rc;
125
126 if (audrectask_enable(audio->enc_type, audio_amrnb_in_dsp_event,
127 audio)) {
128 audmgr_disable(&audio->audmgr);
129 MM_ERR("audrec_enable failed\n");
130 return -ENODEV;
131 }
132
133 audio->enabled = 1;
134 audio_amrnb_in_dsp_enable(audio, 1);
135
136 return 0;
137}
138
139/* must be called with audio->lock held */
140static int audio_amrnb_in_disable(struct audio_amrnb_in *audio)
141{
142 if (audio->enabled) {
143 audio->enabled = 0;
144 audio_amrnb_in_dsp_enable(audio, 0);
145 wake_up(&audio->wait);
146 audrectask_disable(audio->enc_type, audio);
147 audmgr_disable(&audio->audmgr);
148 }
149 return 0;
150}
151
152/* ------------------- dsp --------------------- */
153struct audio_amrnb_in_frame {
154 uint16_t frame_count_lsw;
155 uint16_t frame_count_msw;
156 uint16_t frame_length;
157 uint16_t erased_pcm;
158 unsigned char raw_bitstream[];
159} __attribute__((packed));
160
161static void audio_amrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
162{
163 struct audio_amrnb_in_frame *frame;
164 uint32_t index;
165 unsigned long flags;
166 index = audio->in_head;
167
168 frame = (void *) (((char *)audio->in[index].data) -
169 sizeof(*frame));
170 spin_lock_irqsave(&audio->dsp_lock, flags);
171 audio->in[index].size = FRAME_SIZE - (sizeof(*frame)); /* Send
172 Complete Transcoded Data, not actual frame part */
173
174 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
175
176 /* If overflow, move the tail index foward. */
177 if (audio->in_head == audio->in_tail)
178 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
179 else
180 audio->in_count++;
181
182 audio_amrnb_in_dsp_read_buffer(audio, audio->dsp_cnt++);
183 spin_unlock_irqrestore(&audio->dsp_lock, flags);
184
185 wake_up(&audio->wait);
186}
187
188static void audio_amrnb_in_dsp_event(void *data, unsigned id, uint16_t *msg)
189{
190 struct audio_amrnb_in *audio = data;
191
192 switch (id) {
193 case AUDREC_MSG_CMD_CFG_DONE_MSG:
194 MM_DBG("CFG_DONE_MSG\n");
195 if (msg[0] & AUDREC_MSG_CFG_DONE_ENC_ENA) {
196 audio->audrec_obj_idx = msg[1];
197 audio_amrnb_in_encmem_config(audio);
198 } else {
199 audio->running = 0;
200 }
201 break;
202 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
203 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
204 if (msg[0] == audio->audrec_obj_idx)
205 audio_amrnb_in_encparam_config(audio);
206 else
207 MM_ERR("AREC_MEM_CFG_DONE_MSG ERR\n");
208 break;
209 }
210 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
211 MM_DBG("AREC_PARAM_CFG_DONE_MSG\n");
212 if (msg[0] == audio->audrec_obj_idx)
213 audio->running = 1;
214 else
215 MM_ERR("AREC_PARAM_CFG_DONE_MSG ERR\n");
216 break;
217 }
218 case AUDREC_MSG_PACKET_READY_MSG: {
219 MM_DBG("AUDREC_MSG_PACKET_READY_MSG\n");
220 if (msg[0] == audio->audrec_obj_idx)
221 audio_amrnb_in_get_dsp_frames(audio);
222 else
223 MM_ERR("PACKET_READY_MSG ERR\n");
224 break;
225 }
226 case AUDREC_MSG_FATAL_ERR_MSG: {
227 MM_ERR("FATAL_ERR_MSG %x\n", msg[0]);
228 break;
229 }
230 default:
231 MM_ERR("unknown event %d\n", id);
232 }
233}
234
235static int audio_amrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable)
236{
237 struct audrec_cmd_enc_cfg cmd;
238
239 memset(&cmd, 0, sizeof(cmd));
240 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
241 cmd.audrec_enc_type = (audio->enc_type) |
242 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
243 /* Don't care on enable, required on disable */
244 cmd.audrec_obj_idx = audio->audrec_obj_idx;
245
246 return audrectask_send_cmdqueue(&cmd, sizeof(cmd));
247}
248
249static int audio_amrnb_in_encmem_config(struct audio_amrnb_in *audio)
250{
251 struct audrec_cmd_arecmem_cfg cmd;
252 uint16_t *data = (void *) audio->data;
253 unsigned cnt;
254
255 memset(&cmd, 0, sizeof(cmd));
256
257 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
258 cmd.audrec_obj_idx = audio->audrec_obj_idx;
259 /* Rate at which packet complete message comes */
260 cmd.audrec_up_pkt_intm_cnt = 1;
261 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
262 cmd.audrec_extpkt_buffer_lsw = audio->phys;
263 /* Max Buffer no available for frames */
264 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
265
266 /* prepare buffer pointers:
267 * 4 halfword header + Frame Raw Packet (20ms data)
268 */
269 for (cnt = 0; cnt < FRAME_NUM; cnt++) {
270 audio->in[cnt].data = data + 4; /* Pointer to Raw Packet part*/
271 MM_DBG(" audio->in[%d].data = %x \n", cnt,
272 (unsigned int)audio->in[cnt].data);
273 data += 22; /* Point to next Frame buffer */
274 }
275
276 return audrectask_send_cmdqueue(&cmd, sizeof(cmd));
277}
278
279static int audio_amrnb_in_encparam_config(struct audio_amrnb_in *audio)
280{
281 struct audrec_cmd_arecparam_amrnb_cfg cmd;
282
283 memset(&cmd, 0, sizeof(cmd));
284
285 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
286 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
287 cmd.samp_rate_idx = 0xb; /* 8k Sampling rate */
288 cmd.voicememoencweight1 = audio->amrnb_enc_cfg.voicememoencweight1;
289 cmd.voicememoencweight2 = audio->amrnb_enc_cfg.voicememoencweight2;
290 cmd.voicememoencweight3 = audio->amrnb_enc_cfg.voicememoencweight3;
291 cmd.voicememoencweight4 = audio->amrnb_enc_cfg.voicememoencweight4;
292 cmd.update_mode = 0x8000 | 0x0000;
293 cmd.dtx_mode = audio->amrnb_enc_cfg.dtx_mode_enable;
294 cmd.test_mode = audio->amrnb_enc_cfg.test_mode_enable;
295 cmd.used_mode = audio->amrnb_enc_cfg.enc_mode;
296
297 MM_DBG("cmd.common.cmd_id = 0x%4x\n", cmd.common.cmd_id);
298 MM_DBG("cmd.common.audrec_obj_idx = 0x%4x\n",
299 cmd.common.audrec_obj_idx);
300 MM_DBG("cmd.samp_rate_idx = 0x%4x\n", cmd.samp_rate_idx);
301 MM_DBG("cmd.voicememoencweight1 = 0x%4x\n",
302 cmd.voicememoencweight1);
303 MM_DBG("cmd.voicememoencweight2 = 0x%4x\n",
304 cmd.voicememoencweight2);
305 MM_DBG("cmd.voicememoencweight3 = 0x%4x\n",
306 cmd.voicememoencweight3);
307 MM_DBG("cmd.voicememoencweight4 = 0x%4x\n",
308 cmd.voicememoencweight4);
309 MM_DBG("cmd.update_mode = 0x%4x\n", cmd.update_mode);
310 MM_DBG("cmd.dtx_mode = 0x%4x\n", cmd.dtx_mode);
311 MM_DBG("cmd.test_mode = 0x%4x\n", cmd.test_mode);
312 MM_DBG("cmd.used_mode = 0x%4x\n", cmd.used_mode);
313
314 return audrectask_send_cmdqueue(&cmd, sizeof(cmd));
315}
316
317static int audio_amrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
318 uint32_t read_cnt)
319{
320 audrec_cmd_packet_ext_ptr cmd;
321
322 memset(&cmd, 0, sizeof(cmd));
323 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
324 cmd.type = audio->audrec_obj_idx;
325 cmd.curr_rec_count_msw = read_cnt >> 16;
326 cmd.curr_rec_count_lsw = read_cnt;
327
328 return audrectask_send_bitstreamqueue(&cmd, sizeof(cmd));
329}
330
331static void audio_amrnb_in_flush(struct audio_amrnb_in *audio)
332{
333 int i;
334
335 audio->dsp_cnt = 0;
336 audio->in_head = 0;
337 audio->in_tail = 0;
338 audio->in_count = 0;
339 for (i = 0; i < FRAME_NUM; i++) {
340 audio->in[i].size = 0;
341 audio->in[i].read = 0;
342 }
343}
344
345
346/* ------------------- device --------------------- */
347static long audio_amrnb_in_ioctl(struct file *file,
348 unsigned int cmd, unsigned long arg)
349{
350 struct audio_amrnb_in *audio = file->private_data;
351 int rc;
352
353 if (cmd == AUDIO_GET_STATS) {
354 struct msm_audio_stats stats;
355 stats.byte_count = atomic_read(&audio->in_bytes);
356 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
357 return -EFAULT;
358 return 0;
359 }
360
361 mutex_lock(&audio->lock);
362 switch (cmd) {
363 case AUDIO_START:
364 rc = audio_amrnb_in_enable(audio);
365 break;
366 case AUDIO_STOP:
367 rc = audio_amrnb_in_disable(audio);
368 audio->stopped = 1;
369 break;
370 case AUDIO_FLUSH:
371 if (audio->stopped) {
372 /* Make sure we're stopped and we wake any threads
373 * that might be blocked holding the read_lock.
374 * While audio->stopped read threads will always
375 * exit immediately.
376 */
377 wake_up(&audio->wait);
378 mutex_lock(&audio->read_lock);
379 audio_amrnb_in_flush(audio);
380 mutex_unlock(&audio->read_lock);
381 }
382 case AUDIO_SET_CONFIG: {
383 rc = -EINVAL; /* Buffer size better to come from upper */
384 break;
385 }
386 case AUDIO_GET_CONFIG: {
387 struct msm_audio_config cfg;
388 cfg.buffer_size = audio->buffer_size;
389 cfg.buffer_count = FRAME_NUM;
390 cfg.sample_rate = 8000;
391 cfg.channel_count = 1;
392 cfg.type = 10;
393 cfg.unused[0] = 0;
394 cfg.unused[1] = 0;
395 cfg.unused[2] = 0;
396 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
397 rc = -EFAULT;
398 else
399 rc = 0;
400 break;
401 }
402 case AUDIO_GET_AMRNB_ENC_CONFIG: {
403 if (copy_to_user((void *)arg, &audio->amrnb_enc_cfg,
404 sizeof(audio->amrnb_enc_cfg)))
405 rc = -EFAULT;
406 else
407 rc = 0;
408 break;
409 }
410 case AUDIO_SET_AMRNB_ENC_CONFIG: {
411 struct msm_audio_amrnb_enc_config cfg;
412 if (copy_from_user
413 (&cfg, (void *)arg, sizeof(cfg))) {
414 rc = -EFAULT;
415 } else
416 rc = 0;
417 audio->amrnb_enc_cfg.voicememoencweight1 =
418 cfg.voicememoencweight1;
419 audio->amrnb_enc_cfg.voicememoencweight2 =
420 cfg.voicememoencweight2;
421 audio->amrnb_enc_cfg.voicememoencweight3 =
422 cfg.voicememoencweight3;
423 audio->amrnb_enc_cfg.voicememoencweight4 =
424 cfg.voicememoencweight4;
425 audio->amrnb_enc_cfg.dtx_mode_enable = cfg.dtx_mode_enable;
426 audio->amrnb_enc_cfg.test_mode_enable = cfg.test_mode_enable;
427 audio->amrnb_enc_cfg.enc_mode = cfg.enc_mode;
428 /* Run time change of Param */
429 break;
430 }
431 default:
432 rc = -EINVAL;
433 }
434 mutex_unlock(&audio->lock);
435 return rc;
436}
437
438static ssize_t audio_amrnb_in_read(struct file *file,
439 char __user *buf,
440 size_t count, loff_t *pos)
441{
442 struct audio_amrnb_in *audio = file->private_data;
443 unsigned long flags;
444 const char __user *start = buf;
445 void *data;
446 uint32_t index;
447 uint32_t size;
448 int rc = 0;
449
450 mutex_lock(&audio->read_lock);
451 while (count > 0) {
452 rc = wait_event_interruptible(
453 audio->wait, (audio->in_count > 0) || audio->stopped);
454 if (rc < 0)
455 break;
456
457 if (audio->stopped) {
458 rc = -EBUSY;
459 break;
460 }
461
462 index = audio->in_tail;
463 data = (uint8_t *) audio->in[index].data;
464 size = audio->in[index].size;
465 if (count >= size) {
466 dma_coherent_post_ops();
467 if (copy_to_user(buf, data, size)) {
468 rc = -EFAULT;
469 break;
470 }
471 spin_lock_irqsave(&audio->dsp_lock, flags);
472 if (index != audio->in_tail) {
473 /* overrun -- data is invalid
474 and we need to retry */
475 spin_unlock_irqrestore(&audio->dsp_lock,
476 flags);
477 continue;
478 }
479 audio->in[index].size = 0;
480 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
481 audio->in_count--;
482 spin_unlock_irqrestore(&audio->dsp_lock, flags);
483 count -= size;
484 buf += size;
485 } else {
486 MM_ERR("short read\n");
487 break;
488 }
489 }
490 mutex_unlock(&audio->read_lock);
491
492 if (buf > start)
493 return buf - start;
494
495 return rc;
496}
497
498static ssize_t audio_amrnb_in_write(struct file *file,
499 const char __user *buf,
500 size_t count, loff_t *pos)
501{
502 return -EINVAL;
503}
504
505static int audio_amrnb_in_release(struct inode *inode, struct file *file)
506{
507 struct audio_amrnb_in *audio = file->private_data;
508
509 mutex_lock(&audio->lock);
510 audio_amrnb_in_disable(audio);
511 audio_amrnb_in_flush(audio);
512 audio->opened = 0;
513 if (audio->data) {
514 dma_free_coherent(NULL, DMASZ, audio->data, audio->phys);
515 audio->data = NULL;
516 }
517 mutex_unlock(&audio->lock);
518 return 0;
519}
520
521
522static int audio_amrnb_in_open(struct inode *inode, struct file *file)
523{
524 struct audio_amrnb_in *audio = &the_audio_amrnb_in;
525 int rc;
526
527 mutex_lock(&audio->lock);
528 if (audio->opened) {
529 rc = -EBUSY;
530 goto done;
531 }
532
533 if (!audio->data) {
534 audio->data = dma_alloc_coherent(NULL, DMASZ,
535 &audio->phys, GFP_KERNEL);
536 if (!audio->data) {
537 rc = -ENOMEM;
538 goto done;
539 }
540 }
541
542 rc = audmgr_open(&audio->audmgr);
543 if (rc)
544 goto err;
545 audio->buffer_size = FRAME_SIZE - 8;
546 audio->enc_type = 10;
547 audio->amrnb_enc_cfg.voicememoencweight1 = 0x0000;
548 audio->amrnb_enc_cfg.voicememoencweight2 = 0x0000;
549 audio->amrnb_enc_cfg.voicememoencweight3 = 0x4000;
550 audio->amrnb_enc_cfg.voicememoencweight4 = 0x0000;
551 audio->amrnb_enc_cfg.dtx_mode_enable = 0;
552 audio->amrnb_enc_cfg.test_mode_enable = 0;
553 audio->amrnb_enc_cfg.enc_mode = 7;
554 audio->dsp_cnt = 0;
555 audio->stopped = 0;
556
557 audio_amrnb_in_flush(audio);
558
559 file->private_data = audio;
560 audio->opened = 1;
561 rc = 0;
562 goto done;
563
564err:
565 dma_free_coherent(NULL, DMASZ, audio->data, audio->phys);
566done:
567 mutex_unlock(&audio->lock);
568 return rc;
569}
570
571static const struct file_operations audio_fops = {
572 .owner = THIS_MODULE,
573 .open = audio_amrnb_in_open,
574 .release = audio_amrnb_in_release,
575 .read = audio_amrnb_in_read,
576 .write = audio_amrnb_in_write,
577 .unlocked_ioctl = audio_amrnb_in_ioctl,
578};
579
580struct miscdevice audio_amrnb_in_misc = {
581 .minor = MISC_DYNAMIC_MINOR,
582 .name = "msm_amrnb_in",
583 .fops = &audio_fops,
584};
585
586#ifdef CONFIG_DEBUG_FS
587static ssize_t audamrnb_in_debug_open(struct inode *inode, struct file *file)
588{
589 file->private_data = inode->i_private;
590 return 0;
591}
592
593static ssize_t audamrnb_in_debug_read(struct file *file, char __user *buf,
594 size_t count, loff_t *ppos)
595{
596 const int debug_bufmax = 1024;
597 static char buffer[1024];
598 int n = 0, i;
599 struct audio_amrnb_in *audio = file->private_data;
600
601 mutex_lock(&audio->lock);
602 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
603 n += scnprintf(buffer + n, debug_bufmax - n,
604 "enabled %d\n", audio->enabled);
605 n += scnprintf(buffer + n, debug_bufmax - n,
606 "stopped %d\n", audio->stopped);
607 n += scnprintf(buffer + n, debug_bufmax - n,
608 "audrec_obj_idx %d\n", audio->audrec_obj_idx);
609 n += scnprintf(buffer + n, debug_bufmax - n,
610 "dsp_cnt %d \n", audio->dsp_cnt);
611 n += scnprintf(buffer + n, debug_bufmax - n,
612 "in_count %d \n", audio->in_count);
613 for (i = 0; i < FRAME_NUM; i++)
614 n += scnprintf(buffer + n, debug_bufmax - n,
615 "audio->in[%d].size %d \n", i, audio->in[i].size);
616 mutex_unlock(&audio->lock);
617 /* Following variables are only useful for debugging when
618 * when record halts unexpectedly. Thus, no mutual exclusion
619 * enforced
620 */
621 n += scnprintf(buffer + n, debug_bufmax - n,
622 "running %d \n", audio->running);
623 n += scnprintf(buffer + n, debug_bufmax - n,
624 "buffer_size %d \n", audio->buffer_size);
625 n += scnprintf(buffer + n, debug_bufmax - n,
626 "in_head %d \n", audio->in_head);
627 n += scnprintf(buffer + n, debug_bufmax - n,
628 "in_tail %d \n", audio->in_tail);
629 buffer[n] = 0;
630 return simple_read_from_buffer(buf, count, ppos, buffer, n);
631}
632
633static const struct file_operations audamrnb_in_debug_fops = {
634 .read = audamrnb_in_debug_read,
635 .open = audamrnb_in_debug_open,
636};
637#endif
638
639static int __init audio_amrnb_in_init(void)
640{
641#ifdef CONFIG_DEBUG_FS
642 struct dentry *dentry;
643#endif
644
645 mutex_init(&the_audio_amrnb_in.lock);
646 mutex_init(&the_audio_amrnb_in.read_lock);
647 spin_lock_init(&the_audio_amrnb_in.dsp_lock);
648 init_waitqueue_head(&the_audio_amrnb_in.wait);
649
650#ifdef CONFIG_DEBUG_FS
651 dentry = debugfs_create_file("msm_amrnb_in", S_IFREG | S_IRUGO, NULL,
652 (void *) &the_audio_amrnb_in, &audamrnb_in_debug_fops);
653
654 if (IS_ERR(dentry))
655 MM_ERR("debugfs_create_file failed\n");
656#endif
657 return misc_register(&audio_amrnb_in_misc);
658}
659
660static void __exit audio_amrnb_in_exit(void)
661{
662 misc_deregister(&audio_amrnb_in_misc);
663}
664
665module_init(audio_amrnb_in_init);
666module_exit(audio_amrnb_in_exit);
667
668MODULE_DESCRIPTION("MSM AMRNB Encoder driver");
669MODULE_LICENSE("GPL v2");