blob: 2b4ead9365da5fa4f6c474b38085f1c9a3b8b4d6 [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 *
Manish Dewanganb9171e52011-03-15 15:18:18 +05305 * Copyright (c) 2009, 2011 Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07006 *
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
Manish Dewanganb9171e52011-03-15 15:18:18 +053025
26#include <asm/atomic.h>
27#include <asm/ioctls.h>
28
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029#include <linux/module.h>
30#include <linux/fs.h>
31#include <linux/miscdevice.h>
32#include <linux/uaccess.h>
33#include <linux/kthread.h>
34#include <linux/wait.h>
35#include <linux/dma-mapping.h>
36#include <linux/debugfs.h>
37#include <linux/delay.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070038#include <linux/msm_audio_amrnb.h>
Manish Dewanganb9171e52011-03-15 15:18:18 +053039#include <linux/android_pmem.h>
40#include <linux/memory_alloc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070041
42#include "audmgr.h"
43
Manish Dewanganb9171e52011-03-15 15:18:18 +053044#include <mach/msm_rpcrouter.h>
45#include <mach/msm_memtypes.h>
46#include <mach/iommu.h>
47#include <mach/msm_subsystem_map.h>
48#include <mach/iommu_domains.h>
49
50#include <mach/msm_adsp.h>
51#include <mach/qdsp5/qdsp5audpreproc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070052#include <mach/qdsp5/qdsp5audpreproccmdi.h>
53#include <mach/qdsp5/qdsp5audpreprocmsg.h>
54#include <mach/qdsp5/qdsp5audreccmdi.h>
55#include <mach/qdsp5/qdsp5audrecmsg.h>
56#include <mach/debug_mm.h>
57
Manish Dewanganb9171e52011-03-15 15:18:18 +053058#define FRAME_HEADER_SIZE 8 /* 8 bytes frame header */
59#define NT_FRAME_HEADER_SIZE 24 /* 24 bytes frame header */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060/* FRAME_NUM must be a power of two */
Manish Dewanganb9171e52011-03-15 15:18:18 +053061#define FRAME_NUM 8
62#define AMRNB_FRAME_SIZE 36 /* 36 bytes data */
63/*Tunnel mode : 1536 bytes data + 8 byte header*/
64#define FRAME_SIZE (AMRNB_FRAME_SIZE + FRAME_HEADER_SIZE)
65/* 1536 bytes data + 24 meta field*/
66#define NT_FRAME_SIZE (AMRNB_FRAME_SIZE + NT_FRAME_HEADER_SIZE)
67#define DMASZ (FRAME_SIZE * FRAME_NUM)
68#define NT_DMASZ (NT_FRAME_SIZE * FRAME_NUM)
69#define OUT_FRAME_NUM 2
70#define OUT_BUFFER_SIZE (4 * 1024 + NT_FRAME_HEADER_SIZE)
71#define BUFFER_SIZE (OUT_BUFFER_SIZE * OUT_FRAME_NUM)
72
73/* Offset from beginning of buffer*/
74#define AUDPREPROC_AMRNB_EOS_FLG_OFFSET 0x0A
75#define AUDPREPROC_AMRNB_EOS_FLG_MASK 0x01
76#define AUDPREPROC_AMRNB_EOS_NONE 0x0 /* No EOS detected */
77#define AUDPREPROC_AMRNB_EOS_SET 0x1 /* EOS set in meta field */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078
79struct buffer {
80 void *data;
81 uint32_t size;
82 uint32_t read;
83 uint32_t addr;
Manish Dewanganb9171e52011-03-15 15:18:18 +053084 uint32_t used;
85 uint32_t mfield_sz;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070086};
87
88struct audio_amrnb_in {
89 struct buffer in[FRAME_NUM];
90
91 spinlock_t dsp_lock;
92
93 atomic_t in_bytes;
Manish Dewanganb9171e52011-03-15 15:18:18 +053094 atomic_t in_samples;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095
96 struct mutex lock;
97 struct mutex read_lock;
98 wait_queue_head_t wait;
Manish Dewanganb9171e52011-03-15 15:18:18 +053099 wait_queue_head_t wait_enable;
100 /*write section*/
101 struct buffer out[OUT_FRAME_NUM];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700102
Manish Dewanganb9171e52011-03-15 15:18:18 +0530103 uint8_t out_head;
104 uint8_t out_tail;
105 uint8_t out_needed; /* number of buffers the dsp is waiting for */
106 uint32_t out_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700107
Manish Dewanganb9171e52011-03-15 15:18:18 +0530108 struct mutex write_lock;
109 wait_queue_head_t write_wait;
110 int32_t out_phys; /* physical address of write buffer */
111 char *out_data;
112 uint8_t mfield; /* meta field embedded in data */
113 uint8_t wflush; /*write flush */
114 uint8_t rflush; /*read flush*/
115 uint32_t out_frame_cnt;
116
117 struct msm_adsp_module *audrec;
118 struct msm_adsp_module *audpre;
119
120
121 /* configuration to use on next enable */
122 uint32_t samp_rate;
123 uint32_t channel_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124 uint32_t buffer_size;
125 uint32_t enc_type; /* 0 for WAV ,1 for AAC,10 for AMRNB */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530126 uint32_t mode; /* T or NT Mode*/
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127 struct msm_audio_amrnb_enc_config amrnb_enc_cfg;
128
129 uint32_t dsp_cnt;
130 uint32_t in_head; /* next buffer dsp will write */
131 uint32_t in_tail; /* next buffer read() will read */
132 uint32_t in_count; /* number of buffers available to read() */
133
Manish Dewanganb9171e52011-03-15 15:18:18 +0530134 uint32_t eos_ack;
135 uint32_t flush_ack;
136
137 const char *module_name;
138 unsigned queue_ids;
139 uint16_t enc_id; /* Session Id */
140
141 unsigned short samp_rate_index;
142 uint32_t audrec_obj_idx ;
143
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 struct audmgr audmgr;
145
146 /* data allocated for various buffers */
147 char *data;
148 dma_addr_t phys;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530149 struct msm_mapped_buffer *map_v_write;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150
Manish Dewanganb9171e52011-03-15 15:18:18 +0530151 uint8_t opened;
152 uint8_t enabled;
153 uint8_t running;
154 uint8_t stopped; /* set when stopped, cleared on flush */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155};
156
Manish Dewanganb9171e52011-03-15 15:18:18 +0530157struct audio_frame {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158 uint16_t frame_count_lsw;
159 uint16_t frame_count_msw;
160 uint16_t frame_length;
161 uint16_t erased_pcm;
162 unsigned char raw_bitstream[];
Manish Dewanganb9171e52011-03-15 15:18:18 +0530163} __packed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164
Manish Dewanganb9171e52011-03-15 15:18:18 +0530165struct audio_frame_nt {
166 uint16_t metadata_len;
167 uint16_t frame_count_lsw;
168 uint16_t frame_count_msw;
169 uint16_t frame_length;
170 uint16_t erased_pcm;
171 uint16_t reserved;
172 uint16_t time_stamp_dword_lsw;
173 uint16_t time_stamp_dword_msw;
174 uint16_t time_stamp_lsw;
175 uint16_t time_stamp_msw;
176 uint16_t nflag_lsw;
177 uint16_t nflag_msw;
178 unsigned char raw_bitstream[]; /* samples */
179} __packed;
180
181struct amrnb_encoded_meta_out {
182 uint16_t metadata_len;
183 uint16_t time_stamp_dword_lsw;
184 uint16_t time_stamp_dword_msw;
185 uint16_t time_stamp_lsw;
186 uint16_t time_stamp_msw;
187 uint16_t nflag_lsw;
188 uint16_t nflag_msw;
189};
190
191/* Audrec Queue command sent macro's */
192#define audio_send_queue_pre(audio, cmd, len) \
193 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
194
195#define audio_send_queue_recbs(audio, cmd, len) \
196 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
197 cmd, len)
198#define audio_send_queue_rec(audio, cmd, len) \
199 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
200 cmd, len)
201
202static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable);
203static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio);
204static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio);
205static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
206 uint32_t read_cnt);
207static void audamrnb_in_flush(struct audio_amrnb_in *audio);
208
209static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio);
210static int audpcm_config(struct audio_amrnb_in *audio);
211static void audamrnb_out_flush(struct audio_amrnb_in *audio);
212static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio);
213static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed);
214static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio);
215static void audamrnb_in_flush(struct audio_amrnb_in *audio);
216
217static unsigned convert_samp_index(unsigned index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530219 switch (index) {
220 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
221 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
222 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
223 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
224 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
225 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
226 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
227 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
228 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
229 default: return 11025;
230 }
231}
232
233/* must be called with audio->lock held */
234static int audamrnb_in_enable(struct audio_amrnb_in *audio)
235{
236 struct audmgr_config cfg;
237 int32_t rc;
238
239 if (audio->enabled)
240 return 0;
241
242 cfg.tx_rate = audio->samp_rate;
243 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
244 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
245 cfg.codec = RPC_AUD_DEF_CODEC_AMR_NB;
246 cfg.snd_method = RPC_SND_METHOD_MIDI;
247
248 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
249 rc = audmgr_enable(&audio->audmgr, &cfg);
250 if (rc < 0)
251 return rc;
252
253 if (msm_adsp_enable(audio->audpre)) {
254 audmgr_disable(&audio->audmgr);
255 MM_ERR("msm_adsp_enable(audpre) failed\n");
256 return -ENODEV;
257 }
258 }
259 if (msm_adsp_enable(audio->audrec)) {
260 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
261 audmgr_disable(&audio->audmgr);
262 msm_adsp_disable(audio->audpre);
263 }
264 MM_ERR("msm_adsp_enable(audrec) failed\n");
265 return -ENODEV;
266 }
267
268 audio->enabled = 1;
269 audamrnb_in_dsp_enable(audio, 1);
270
271 return 0;
272}
273
274/* must be called with audio->lock held */
275static int audamrnb_in_disable(struct audio_amrnb_in *audio)
276{
277 if (audio->enabled) {
278 audio->enabled = 0;
279
280 audamrnb_in_dsp_enable(audio, 0);
281
282 wake_up(&audio->wait);
283 wait_event_interruptible_timeout(audio->wait_enable,
284 audio->running == 0, 1*HZ);
285 msm_adsp_disable(audio->audrec);
286 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
287 msm_adsp_disable(audio->audpre);
288 audmgr_disable(&audio->audmgr);
289 }
290 }
291 return 0;
292}
293
294/* ------------------- dsp --------------------- */
295static void audpre_dsp_event(void *data, unsigned id, size_t len,
296 void (*getevent)(void *ptr, size_t len))
297{
298 uint16_t msg[2];
299 getevent(msg, sizeof(msg));
300
301 switch (id) {
302 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
303 MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
304 break;
305 case AUDPREPROC_MSG_ERROR_MSG_ID:
306 MM_ERR("err_index %d\n", msg[0]);
307 break;
308 case ADSP_MESSAGE_ID:
309 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
310 break;
311 default:
312 MM_ERR("unknown event %d\n", id);
313 }
314}
315
316static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
317{
318 struct audio_frame *frame;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319 uint32_t index;
320 unsigned long flags;
321 index = audio->in_head;
322
323 frame = (void *) (((char *)audio->in[index].data) -
324 sizeof(*frame));
325 spin_lock_irqsave(&audio->dsp_lock, flags);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530326
327 /* Send Complete Transcoded Data, not actual frame part */
328 audio->in[index].size = FRAME_SIZE - (sizeof(*frame));
329 /* statistics of read */
330 atomic_add(audio->in[index].size, &audio->in_bytes);
331 atomic_add(1, &audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700332
333 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
334
335 /* If overflow, move the tail index foward. */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530336 if (audio->in_head == audio->in_tail) {
337 MM_ERR("Error! not able to keep up the read\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700338 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530339 MM_ERR("in_count = %d\n", audio->in_count);
340 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341 audio->in_count++;
342
Manish Dewanganb9171e52011-03-15 15:18:18 +0530343 audamrnb_in_dsp_read_buffer(audio, audio->dsp_cnt++);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700344 spin_unlock_irqrestore(&audio->dsp_lock, flags);
345
346 wake_up(&audio->wait);
347}
348
Manish Dewanganb9171e52011-03-15 15:18:18 +0530349static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio)
350{
351 struct audio_frame_nt *nt_frame;
352 uint32_t index;
353 unsigned long flags;
354
355 index = audio->in_head;
356 nt_frame = (void *) (((char *)audio->in[index].data) - \
357 sizeof(struct audio_frame_nt));
358 spin_lock_irqsave(&audio->dsp_lock, flags);
359 audio->in[index].size = nt_frame->frame_length;
360 /* statistics of read */
361 atomic_add(audio->in[index].size, &audio->in_bytes);
362 atomic_add(1, &audio->in_samples);
363
364 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
365
366 /* If overflow, move the tail index foward. */
367 if (audio->in_head == audio->in_tail)
368 MM_DBG("Error! not able to keep up the read\n");
369 else
370 audio->in_count++;
371
372 spin_unlock_irqrestore(&audio->dsp_lock, flags);
373 wake_up(&audio->wait);
374}
375
376static int audrec_pcm_buffer_ptr_refresh(struct audio_amrnb_in *audio,
377 unsigned idx, unsigned len)
378{
379 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
380
381 if (len == NT_FRAME_HEADER_SIZE)
382 len = len / 2;
383 else
384 len = (len + NT_FRAME_HEADER_SIZE) / 2;
385 MM_DBG("len = %d\n", len);
386 memset(&cmd, 0, sizeof(cmd));
387 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
388 cmd.num_buffers = 1;
389 if (cmd.num_buffers == 1) {
390 cmd.buf_address_length[0] = (audio->out[idx].addr &
391 0xffff0000) >> 16;
392 cmd.buf_address_length[1] = (audio->out[idx].addr &
393 0x0000ffff);
394 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
395 cmd.buf_address_length[3] = (len & 0x0000ffff);
396 }
397 audio->out_frame_cnt++;
398 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
399}
400
401static int audpcm_config(struct audio_amrnb_in *audio)
402{
403 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
404 MM_DBG("\n");
405 memset(&cmd, 0, sizeof(cmd));
406 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
407 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
408 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
409 cmd.sampling_freq = convert_samp_index(audio->samp_rate);
410 if (!audio->channel_mode)
411 cmd.channels = 1;
412 else
413 cmd.channels = 2;
414 cmd.frequency_of_intimation = 1;
415 cmd.max_number_of_buffers = OUT_FRAME_NUM;
416 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
417}
418
419
420static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio)
421{
422 struct audrec_cmd_routing_mode cmd;
423
424 MM_DBG("\n");
425 memset(&cmd, 0, sizeof(cmd));
426 cmd.cmd_id = AUDREC_CMD_ROUTING_MODE;
427 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
428 cmd.routing_mode = 1;
429 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
430}
431
432static void audrec_dsp_event(void *data, unsigned id, size_t len,
433 void (*getevent)(void *ptr, size_t len))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434{
435 struct audio_amrnb_in *audio = data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530436 if (data)
437 audio = data;
438 else {
439 MM_ERR("invalid data for event %x\n", id);
440 return;
441 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700442
443 switch (id) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530444 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
445 struct audrec_msg_cmd_cfg_done_msg cmd_cfg_done_msg;
446 getevent(&cmd_cfg_done_msg, AUDREC_MSG_CMD_CFG_DONE_MSG_LEN);
447 if (cmd_cfg_done_msg.audrec_enc_type & \
448 AUDREC_MSG_CFG_DONE_ENC_ENA) {
449 audio->audrec_obj_idx = cmd_cfg_done_msg.audrec_obj_idx;
450 MM_DBG("CFG ENABLED\n");
451 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
452 MM_DBG("routing command\n");
453 audamrnb_in_routing_mode_config(audio);
454 } else {
455 audamrnb_in_encmem_config(audio);
456 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700457 } else {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530458 MM_DBG("CFG SLEEP\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700459 audio->running = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530460 wake_up(&audio->wait_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700461 }
462 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530463 }
464 case AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG: {
465 struct audrec_msg_cmd_routing_mode_done_msg \
466 routing_msg;
467 getevent(&routing_msg, AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG);
468 MM_DBG("AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG");
469 if (routing_msg.configuration == 0) {
470 MM_ERR("routing configuration failed\n");
471 audio->running = 0;
472 wake_up(&audio->wait_enable);
473 } else
474 audamrnb_in_encmem_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475 break;
476 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530477 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
478 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
479 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
480 audamrnb_in_encparam_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700481 else
Manish Dewanganb9171e52011-03-15 15:18:18 +0530482 audpcm_config(audio);
483 break;
484 }
485
486 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
487 MM_DBG("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
488 audamrnb_in_encparam_config(audio);
489 break;
490 }
491 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
492 MM_DBG("AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG\n");
493 audio->running = 1;
494 wake_up(&audio->wait_enable);
495 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
496 audrec_pcm_send_data(audio, 1);
497 break;
498 }
499 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
500 MM_DBG("ptr_update recieved from DSP\n");
501 audrec_pcm_send_data(audio, 1);
502 break;
503 }
504 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
505 struct audrec_msg_no_ext_pkt_avail_msg err_msg;
506 getevent(&err_msg, AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG_LEN);
507 MM_DBG("NO_EXT_PKT_AVAILABLE_MSG %x\n",\
508 err_msg.audrec_err_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509 break;
510 }
511 case AUDREC_MSG_PACKET_READY_MSG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530512 struct audrec_msg_packet_ready_msg pkt_ready_msg;
513
514 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
515 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
516 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
517 pkt_ready_msg.pkt_counter_msw, \
518 pkt_ready_msg.pkt_counter_lsw, \
519 pkt_ready_msg.pkt_read_cnt_msw, \
520 pkt_ready_msg.pkt_read_cnt_lsw);
521
522 audamrnb_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 break;
524 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530525 case AUDREC_UP_NT_PACKET_READY_MSG: {
526 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
527
528 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
529 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
530 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
531 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
532 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
533 pkt_ready_msg.audrec_upprev_readcount_lsw, \
534 pkt_ready_msg.audrec_upprev_readcount_msw);
535
536 audamrnb_nt_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537 break;
538 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530539 case AUDREC_CMD_FLUSH_DONE_MSG: {
540 audio->wflush = 0;
541 audio->rflush = 0;
542 audio->flush_ack = 1;
543 wake_up(&audio->write_wait);
544 MM_DBG("flush ack recieved\n");
545 break;
546 }
547 case ADSP_MESSAGE_ID:
548 MM_DBG("Received ADSP event: module \
549 enable/disable(audrectask)\n");
550 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700551 default:
552 MM_ERR("unknown event %d\n", id);
553 }
554}
555
Manish Dewanganb9171e52011-03-15 15:18:18 +0530556struct msm_adsp_ops audpre_amrnb_adsp_ops = {
557 .event = audpre_dsp_event,
558};
559
560struct msm_adsp_ops audrec_amrnb_adsp_ops = {
561 .event = audrec_dsp_event,
562};
563
564static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565{
566 struct audrec_cmd_enc_cfg cmd;
567
568 memset(&cmd, 0, sizeof(cmd));
569 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530570 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
572 /* Don't care on enable, required on disable */
573 cmd.audrec_obj_idx = audio->audrec_obj_idx;
574
Manish Dewanganb9171e52011-03-15 15:18:18 +0530575 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700576}
577
Manish Dewanganb9171e52011-03-15 15:18:18 +0530578static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700579{
580 struct audrec_cmd_arecmem_cfg cmd;
581 uint16_t *data = (void *) audio->data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530582 uint8_t n;
583 uint16_t header_len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584
585 memset(&cmd, 0, sizeof(cmd));
586
587 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
588 cmd.audrec_obj_idx = audio->audrec_obj_idx;
589 /* Rate at which packet complete message comes */
590 cmd.audrec_up_pkt_intm_cnt = 1;
591 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
592 cmd.audrec_extpkt_buffer_lsw = audio->phys;
593 /* Max Buffer no available for frames */
594 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
595
596 /* prepare buffer pointers:
Manish Dewanganb9171e52011-03-15 15:18:18 +0530597 * T:36 bytes amrnb packet + 4 halfword header
598 * NT:36 bytes amrnb packet + 12 halfword header
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530600 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
601 header_len = FRAME_HEADER_SIZE/2;
602 else
603 header_len = NT_FRAME_HEADER_SIZE/2;
604
605 for (n = 0; n < FRAME_NUM; n++) {
606 audio->in[n].data = data + header_len;
607 data += (AMRNB_FRAME_SIZE/2) + header_len;
608 MM_DBG("0x%8x\n", (uint32_t)(audio->in[n].data - header_len*2));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609 }
610
Manish Dewanganb9171e52011-03-15 15:18:18 +0530611 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612}
613
Manish Dewanganb9171e52011-03-15 15:18:18 +0530614static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700615{
616 struct audrec_cmd_arecparam_amrnb_cfg cmd;
617
618 memset(&cmd, 0, sizeof(cmd));
619
620 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
621 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530622 cmd.samp_rate_idx = audio->samp_rate_index; /* 8k Sampling rate */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700623 cmd.voicememoencweight1 = audio->amrnb_enc_cfg.voicememoencweight1;
624 cmd.voicememoencweight2 = audio->amrnb_enc_cfg.voicememoencweight2;
625 cmd.voicememoencweight3 = audio->amrnb_enc_cfg.voicememoencweight3;
626 cmd.voicememoencweight4 = audio->amrnb_enc_cfg.voicememoencweight4;
627 cmd.update_mode = 0x8000 | 0x0000;
628 cmd.dtx_mode = audio->amrnb_enc_cfg.dtx_mode_enable;
629 cmd.test_mode = audio->amrnb_enc_cfg.test_mode_enable;
630 cmd.used_mode = audio->amrnb_enc_cfg.enc_mode;
631
632 MM_DBG("cmd.common.cmd_id = 0x%4x\n", cmd.common.cmd_id);
633 MM_DBG("cmd.common.audrec_obj_idx = 0x%4x\n",
634 cmd.common.audrec_obj_idx);
635 MM_DBG("cmd.samp_rate_idx = 0x%4x\n", cmd.samp_rate_idx);
636 MM_DBG("cmd.voicememoencweight1 = 0x%4x\n",
637 cmd.voicememoencweight1);
638 MM_DBG("cmd.voicememoencweight2 = 0x%4x\n",
639 cmd.voicememoencweight2);
640 MM_DBG("cmd.voicememoencweight3 = 0x%4x\n",
641 cmd.voicememoencweight3);
642 MM_DBG("cmd.voicememoencweight4 = 0x%4x\n",
643 cmd.voicememoencweight4);
644 MM_DBG("cmd.update_mode = 0x%4x\n", cmd.update_mode);
645 MM_DBG("cmd.dtx_mode = 0x%4x\n", cmd.dtx_mode);
646 MM_DBG("cmd.test_mode = 0x%4x\n", cmd.test_mode);
647 MM_DBG("cmd.used_mode = 0x%4x\n", cmd.used_mode);
648
Manish Dewanganb9171e52011-03-15 15:18:18 +0530649 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700650}
651
Manish Dewanganb9171e52011-03-15 15:18:18 +0530652static int audamrnb_flush_command(struct audio_amrnb_in *audio)
653{
654 struct audrec_cmd_flush cmd;
655 MM_DBG("\n");
656 memset(&cmd, 0, sizeof(cmd));
657 cmd.cmd_id = AUDREC_CMD_FLUSH;
658 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
659}
660static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 uint32_t read_cnt)
662{
663 audrec_cmd_packet_ext_ptr cmd;
664
665 memset(&cmd, 0, sizeof(cmd));
666 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
667 cmd.type = audio->audrec_obj_idx;
668 cmd.curr_rec_count_msw = read_cnt >> 16;
669 cmd.curr_rec_count_lsw = read_cnt;
670
Manish Dewanganb9171e52011-03-15 15:18:18 +0530671 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700672}
673
Manish Dewanganb9171e52011-03-15 15:18:18 +0530674/* ------------------- device --------------------- */
675
676static void audamrnb_ioport_reset(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700677{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530678 /* Make sure read/write thread are free from
679 * sleep and knowing that system is not able
680 * to process io request at the moment
681 */
682 wake_up(&audio->write_wait);
683 mutex_lock(&audio->write_lock);
684 audamrnb_in_flush(audio);
685 mutex_unlock(&audio->write_lock);
686 wake_up(&audio->wait);
687 mutex_lock(&audio->read_lock);
688 audamrnb_out_flush(audio);
689 mutex_unlock(&audio->read_lock);
690}
691
692static void audamrnb_in_flush(struct audio_amrnb_in *audio)
693{
694 uint8_t i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700695
696 audio->dsp_cnt = 0;
697 audio->in_head = 0;
698 audio->in_tail = 0;
699 audio->in_count = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530700 audio->eos_ack = 0;
701 for (i = FRAME_NUM-1; i >= 0; i--) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702 audio->in[i].size = 0;
703 audio->in[i].read = 0;
704 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530705 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
706 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
707 atomic_set(&audio->in_bytes, 0);
708 atomic_set(&audio->in_samples, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700709}
710
Manish Dewanganb9171e52011-03-15 15:18:18 +0530711static void audamrnb_out_flush(struct audio_amrnb_in *audio)
712{
713 uint8_t i;
714
715 audio->out_head = 0;
716 audio->out_tail = 0;
717 audio->out_count = 0;
718 for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
719 audio->out[i].size = 0;
720 audio->out[i].read = 0;
721 audio->out[i].used = 0;
722 }
723}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724
725/* ------------------- device --------------------- */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530726static long audamrnb_in_ioctl(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700727 unsigned int cmd, unsigned long arg)
728{
729 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530730 int32_t rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700731
Manish Dewanganb9171e52011-03-15 15:18:18 +0530732 MM_DBG("\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 if (cmd == AUDIO_GET_STATS) {
734 struct msm_audio_stats stats;
735 stats.byte_count = atomic_read(&audio->in_bytes);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530736 stats.sample_count = atomic_read(&audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
738 return -EFAULT;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530739 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700740 }
741
742 mutex_lock(&audio->lock);
743 switch (cmd) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530744 case AUDIO_START: {
745 rc = audamrnb_in_enable(audio);
746 if (!rc) {
747 rc =
748 wait_event_interruptible_timeout(audio->wait_enable,
749 audio->running != 0, 1*HZ);
750 MM_INFO("state %d rc = %d\n", audio->running, rc);
751
752 if (audio->running == 0)
753 rc = -ENODEV;
754 else
755 rc = 0;
756 }
757 audio->stopped = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700758 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530759 }
760 case AUDIO_STOP: {
761 rc = audamrnb_in_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762 audio->stopped = 1;
763 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530764 }
765 case AUDIO_FLUSH: {
766 MM_DBG("AUDIO_FLUSH\n");
767 audio->rflush = 1;
768 audio->wflush = 1;
769 audamrnb_ioport_reset(audio);
770 if (audio->running) {
771 audamrnb_flush_command(audio);
772 rc = wait_event_interruptible(audio->write_wait,
773 !audio->wflush);
774 if (rc < 0) {
775 MM_ERR("AUDIO_FLUSH interrupted\n");
776 rc = -EINTR;
777 }
778 } else {
779 audio->rflush = 0;
780 audio->wflush = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700781 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782 break;
783 }
784 case AUDIO_GET_CONFIG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530785 struct msm_audio_config cfg;
786 memset(&cfg, 0, sizeof(cfg));
787 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
788 cfg.buffer_size = OUT_BUFFER_SIZE;
789 cfg.buffer_count = OUT_FRAME_NUM;
790 } else {
791 cfg.buffer_size = audio->buffer_size;
792 cfg.buffer_count = FRAME_NUM;
793 }
794 cfg.sample_rate = convert_samp_index(audio->samp_rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700795 cfg.channel_count = 1;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530796 cfg.type = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700797 cfg.unused[0] = 0;
798 cfg.unused[1] = 0;
799 cfg.unused[2] = 0;
800 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
801 rc = -EFAULT;
802 else
803 rc = 0;
804 break;
805 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530806 case AUDIO_GET_STREAM_CONFIG: {
807 struct msm_audio_stream_config cfg;
808 memset(&cfg, 0, sizeof(cfg));
809 cfg.buffer_size = audio->buffer_size;
810 cfg.buffer_count = FRAME_NUM;
811 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
812 rc = -EFAULT;
813 else
814 rc = 0;
815 break;
816 }
817 case AUDIO_SET_STREAM_CONFIG: {
818 struct msm_audio_stream_config cfg;
819 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
820 rc = -EFAULT;
821 break;
822 }
823 /* Allow only single frame */
824 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
825 if (cfg.buffer_size != (FRAME_SIZE - 8))
826 rc = -EINVAL;
827 break;
828 } else {
829 if (cfg.buffer_size != (AMRNB_FRAME_SIZE + 14))
830 rc = -EINVAL;
831 break;
832 }
833 audio->buffer_size = cfg.buffer_size;
834 break;
835 }
836
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837 case AUDIO_GET_AMRNB_ENC_CONFIG: {
838 if (copy_to_user((void *)arg, &audio->amrnb_enc_cfg,
839 sizeof(audio->amrnb_enc_cfg)))
840 rc = -EFAULT;
841 else
842 rc = 0;
843 break;
844 }
845 case AUDIO_SET_AMRNB_ENC_CONFIG: {
846 struct msm_audio_amrnb_enc_config cfg;
847 if (copy_from_user
848 (&cfg, (void *)arg, sizeof(cfg))) {
849 rc = -EFAULT;
850 } else
851 rc = 0;
852 audio->amrnb_enc_cfg.voicememoencweight1 =
853 cfg.voicememoencweight1;
854 audio->amrnb_enc_cfg.voicememoencweight2 =
855 cfg.voicememoencweight2;
856 audio->amrnb_enc_cfg.voicememoencweight3 =
857 cfg.voicememoencweight3;
858 audio->amrnb_enc_cfg.voicememoencweight4 =
859 cfg.voicememoencweight4;
860 audio->amrnb_enc_cfg.dtx_mode_enable = cfg.dtx_mode_enable;
861 audio->amrnb_enc_cfg.test_mode_enable = cfg.test_mode_enable;
862 audio->amrnb_enc_cfg.enc_mode = cfg.enc_mode;
863 /* Run time change of Param */
864 break;
865 }
866 default:
867 rc = -EINVAL;
868 }
869 mutex_unlock(&audio->lock);
870 return rc;
871}
872
Manish Dewanganb9171e52011-03-15 15:18:18 +0530873static ssize_t audamrnb_in_read(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700874 char __user *buf,
875 size_t count, loff_t *pos)
876{
877 struct audio_amrnb_in *audio = file->private_data;
878 unsigned long flags;
879 const char __user *start = buf;
880 void *data;
881 uint32_t index;
882 uint32_t size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530883 int32_t rc = 0;
884 struct amrnb_encoded_meta_out meta_field;
885 struct audio_frame_nt *nt_frame;
886 MM_DBG("count = %d\n", count);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700887 mutex_lock(&audio->read_lock);
888 while (count > 0) {
889 rc = wait_event_interruptible(
Manish Dewanganb9171e52011-03-15 15:18:18 +0530890 audio->wait, (audio->in_count > 0) || audio->stopped ||
891 audio->rflush);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892 if (rc < 0)
893 break;
894
Manish Dewanganb9171e52011-03-15 15:18:18 +0530895 if (audio->rflush) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896 rc = -EBUSY;
897 break;
898 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530899 if (audio->stopped && !audio->in_count) {
900 MM_DBG("Driver in stop state, No more buffer to read");
901 rc = 0;/* End of File */
902 break;
903 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904
905 index = audio->in_tail;
906 data = (uint8_t *) audio->in[index].data;
907 size = audio->in[index].size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530908
909 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
910 nt_frame = (struct audio_frame_nt *)(data -
911 sizeof(struct audio_frame_nt));
912 memcpy((char *)&meta_field.time_stamp_dword_lsw,
913 (char *)&nt_frame->time_stamp_dword_lsw,
914 (sizeof(struct amrnb_encoded_meta_out) - \
915 sizeof(uint16_t)));
916 meta_field.metadata_len =
917 sizeof(struct amrnb_encoded_meta_out);
918 if (copy_to_user((char *)start, (char *)&meta_field,
919 sizeof(struct amrnb_encoded_meta_out))) {
920 rc = -EFAULT;
921 break;
922 }
923 if (nt_frame->nflag_lsw & 0x0001) {
924 MM_ERR("recieved EOS in read call\n");
925 audio->eos_ack = 1;
926 }
927 buf += sizeof(struct amrnb_encoded_meta_out);
928 count -= sizeof(struct amrnb_encoded_meta_out);
929 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700930 if (count >= size) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530931 /* order the reads on the buffer */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700932 dma_coherent_post_ops();
933 if (copy_to_user(buf, data, size)) {
934 rc = -EFAULT;
935 break;
936 }
937 spin_lock_irqsave(&audio->dsp_lock, flags);
938 if (index != audio->in_tail) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530939 /* overrun -- data is
940 * invalid and we need to retry */
941 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942 continue;
943 }
944 audio->in[index].size = 0;
945 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
946 audio->in_count--;
947 spin_unlock_irqrestore(&audio->dsp_lock, flags);
948 count -= size;
949 buf += size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530950 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
951 if (!audio->eos_ack) {
952 MM_DBG("sending read ptr command \
953 %d %d\n",
954 audio->dsp_cnt,
955 audio->in_tail);
956 audamrnb_in_dsp_read_buffer(audio,
957 audio->dsp_cnt++);
958 }
959 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700960 } else {
961 MM_ERR("short read\n");
962 break;
963 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530964
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700965 }
966 mutex_unlock(&audio->read_lock);
967
968 if (buf > start)
969 return buf - start;
970
971 return rc;
972}
973
Manish Dewanganb9171e52011-03-15 15:18:18 +0530974static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed)
975{
976 struct buffer *frame;
977 unsigned long flags;
978 MM_DBG("\n");
979 spin_lock_irqsave(&audio->dsp_lock, flags);
980 if (!audio->running)
981 goto done;
982
983 if (needed && !audio->wflush) {
984 /* We were called from the callback because the DSP
985 * requested more data. Note that the DSP does want
986 * more data, and if a buffer was in-flight, mark it
987 * as available (since the DSP must now be done with
988 * it).
989 */
990 audio->out_needed = 1;
991 frame = audio->out + audio->out_tail;
992 if (frame->used == 0xffffffff) {
993 MM_DBG("frame %d free\n", audio->out_tail);
994 frame->used = 0;
995 audio->out_tail ^= 1;
996 wake_up(&audio->write_wait);
997 }
998 }
999
1000 if (audio->out_needed) {
1001 /* If the DSP currently wants data and we have a
1002 * buffer available, we will send it and reset
1003 * the needed flag. We'll mark the buffer as in-flight
1004 * so that it won't be recycled until the next buffer
1005 * is requested
1006 */
1007
1008 frame = audio->out + audio->out_tail;
1009 if (frame->used) {
1010 BUG_ON(frame->used == 0xffffffff);
1011 audrec_pcm_buffer_ptr_refresh(audio,
1012 audio->out_tail,
1013 frame->used);
1014 frame->used = 0xffffffff;
1015 audio->out_needed = 0;
1016 }
1017 }
1018 done:
1019 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1020}
1021
1022static int audamrnb_in_fsync(struct file *file, int datasync)
1023
1024{
1025 struct audio_amrnb_in *audio = file->private_data;
1026 int32_t rc = 0;
1027
1028 MM_DBG("\n"); /* Macro prints the file name and function */
1029 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1030 rc = -EINVAL;
1031 goto done_nolock;
1032 }
1033
1034 mutex_lock(&audio->write_lock);
1035
1036 rc = wait_event_interruptible(audio->write_wait,
1037 audio->wflush);
1038 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1039
1040 if (rc < 0)
1041 goto done;
1042 else if (audio->wflush) {
1043 rc = -EBUSY;
1044 goto done;
1045 }
1046done:
1047 mutex_unlock(&audio->write_lock);
1048done_nolock:
1049 return rc;
1050
1051}
1052
1053int audrec_amrnb_process_eos(struct audio_amrnb_in *audio,
1054 const char __user *buf_start, unsigned short mfield_size)
1055{
1056 struct buffer *frame;
1057 int32_t rc = 0;
1058
1059 frame = audio->out + audio->out_head;
1060
1061 rc = wait_event_interruptible(audio->write_wait,
1062 (audio->out_needed &&
1063 audio->out[0].used == 0 &&
1064 audio->out[1].used == 0)
1065 || (audio->stopped)
1066 || (audio->wflush));
1067
1068 if (rc < 0)
1069 goto done;
1070 if (audio->stopped || audio->wflush) {
1071 rc = -EBUSY;
1072 goto done;
1073 }
1074 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1075 rc = -EFAULT;
1076 goto done;
1077 }
1078
1079 frame->mfield_sz = mfield_size;
1080 audio->out_head ^= 1;
1081 frame->used = mfield_size;
1082 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1083 audrec_pcm_send_data(audio, 0);
1084done:
1085 return rc;
1086}
1087
1088static ssize_t audamrnb_in_write(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001089 const char __user *buf,
1090 size_t count, loff_t *pos)
1091{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301092 struct audio_amrnb_in *audio = file->private_data;
1093 const char __user *start = buf;
1094 struct buffer *frame;
1095 char *cpy_ptr;
1096 int32_t rc = 0, eos_condition = AUDPREPROC_AMRNB_EOS_NONE;
1097 unsigned short mfield_size = 0;
1098 int32_t write_count = 0;
1099 MM_DBG("cnt=%d\n", count);
1100
1101 if (count & 1)
1102 return -EINVAL;
1103
1104 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1105 return -EINVAL;
1106
1107 mutex_lock(&audio->write_lock);
1108 frame = audio->out + audio->out_head;
1109 /* if supplied count is more than driver buffer size
1110 * then only copy driver buffer size
1111 */
1112 if (count > frame->size)
1113 count = frame->size;
1114
1115 write_count = count;
1116 cpy_ptr = frame->data;
1117 rc = wait_event_interruptible(audio->write_wait,
1118 (frame->used == 0)
1119 || (audio->stopped)
1120 || (audio->wflush));
1121 if (rc < 0)
1122 goto error;
1123
1124 if (audio->stopped || audio->wflush) {
1125 rc = -EBUSY;
1126 goto error;
1127 }
1128 if (audio->mfield) {
1129 if (buf == start) {
1130 /* Processing beginning of user buffer */
1131 if (__get_user(mfield_size,
1132 (unsigned short __user *) buf)) {
1133 rc = -EFAULT;
1134 goto error;
1135 } else if (mfield_size > count) {
1136 rc = -EINVAL;
1137 goto error;
1138 }
1139 MM_DBG("mf offset_val %x\n", mfield_size);
1140 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1141 rc = -EFAULT;
1142 goto error;
1143 }
1144 /* Check if EOS flag is set and buffer has
1145 * contains just meta field
1146 */
1147 if (cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &
1148 AUDPREPROC_AMRNB_EOS_FLG_MASK) {
1149 eos_condition = AUDPREPROC_AMRNB_EOS_SET;
1150 MM_DBG("EOS SET\n");
1151 if (mfield_size == count) {
1152 buf += mfield_size;
1153 eos_condition = 0;
1154 goto exit;
1155 } else
1156 cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &=
1157 ~AUDPREPROC_AMRNB_EOS_FLG_MASK;
1158 }
1159 cpy_ptr += mfield_size;
1160 count -= mfield_size;
1161 buf += mfield_size;
1162 } else {
1163 mfield_size = 0;
1164 MM_DBG("continuous buffer\n");
1165 }
1166 frame->mfield_sz = mfield_size;
1167 }
1168 MM_DBG("copying the stream count = %d\n", count);
1169 if (copy_from_user(cpy_ptr, buf, count)) {
1170 rc = -EFAULT;
1171 goto error;
1172 }
1173exit:
1174 frame->used = count;
1175 audio->out_head ^= 1;
1176 if (!audio->flush_ack)
1177 audrec_pcm_send_data(audio, 0);
1178 else {
1179 audrec_pcm_send_data(audio, 1);
1180 audio->flush_ack = 0;
1181 }
1182 if (eos_condition == AUDPREPROC_AMRNB_EOS_SET)
1183 rc = audrec_amrnb_process_eos(audio, start, mfield_size);
1184 mutex_unlock(&audio->write_lock);
1185 return write_count;
1186error:
1187 mutex_unlock(&audio->write_lock);
1188 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001189}
1190
Manish Dewanganb9171e52011-03-15 15:18:18 +05301191static int audamrnb_in_release(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001192{
1193 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301194 int32_t dma_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001195 mutex_lock(&audio->lock);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301196 audamrnb_in_disable(audio);
1197 audamrnb_in_flush(audio);
1198 msm_adsp_put(audio->audrec);
1199
1200 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1201 msm_adsp_put(audio->audpre);
1202
1203 audpreproc_aenc_free(audio->enc_id);
1204 audio->audrec = NULL;
1205 audio->audpre = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001206 audio->opened = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301207 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
1208 (audio->out_data)) {
1209 msm_subsystem_unmap_buffer(audio->map_v_write);
1210 free_contiguous_memory_by_paddr(audio->out_phys);
1211 audio->out_data = NULL;
1212 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001213 if (audio->data) {
Manish Dewanganb9171e52011-03-15 15:18:18 +05301214 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1215 dma_size = DMASZ;
1216 else
1217 dma_size = NT_DMASZ;
1218
1219 dma_free_coherent(NULL,
1220 dma_size, audio->data, audio->phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001221 audio->data = NULL;
1222 }
1223 mutex_unlock(&audio->lock);
1224 return 0;
1225}
1226
Manish Dewanganb9171e52011-03-15 15:18:18 +05301227struct audio_amrnb_in the_audio_amrnb_in;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001228
Manish Dewanganb9171e52011-03-15 15:18:18 +05301229static int audamrnb_in_open(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001230{
1231 struct audio_amrnb_in *audio = &the_audio_amrnb_in;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301232 int32_t rc;
1233 int encid;
1234 int32_t dma_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001235
1236 mutex_lock(&audio->lock);
1237 if (audio->opened) {
1238 rc = -EBUSY;
1239 goto done;
1240 }
Manish Dewanganb9171e52011-03-15 15:18:18 +05301241 if ((file->f_mode & FMODE_WRITE) &&
1242 (file->f_mode & FMODE_READ)) {
1243 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1244 dma_size = NT_DMASZ;
1245 MM_DBG("Opened for non tunnel mode encoding\n");
1246 } else if (!(file->f_mode & FMODE_WRITE) &&
1247 (file->f_mode & FMODE_READ)) {
1248 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1249 dma_size = DMASZ;
1250 MM_DBG("Opened for tunnel mode encoding\n");
1251 } else {
1252 MM_ERR("Invalid mode\n");
1253 rc = -EACCES;
1254 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001255 }
1256
Manish Dewanganb9171e52011-03-15 15:18:18 +05301257 /* Settings will be re-config at AUDIO_SET_CONFIG,
1258 * but at least we need to have initial config
1259 */
1260 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_8000,
1261 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_8000;
1262 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
1263 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1264 audio->buffer_size = (AMRNB_FRAME_SIZE + 14);
1265 else
1266 audio->buffer_size = (FRAME_SIZE - 8);
1267 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_AMRNB | audio->mode;
1268
1269 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1270 rc = audmgr_open(&audio->audmgr);
1271 if (rc)
1272 goto done;
1273 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001274 audio->amrnb_enc_cfg.voicememoencweight1 = 0x0000;
1275 audio->amrnb_enc_cfg.voicememoencweight2 = 0x0000;
1276 audio->amrnb_enc_cfg.voicememoencweight3 = 0x4000;
1277 audio->amrnb_enc_cfg.voicememoencweight4 = 0x0000;
1278 audio->amrnb_enc_cfg.dtx_mode_enable = 0;
1279 audio->amrnb_enc_cfg.test_mode_enable = 0;
1280 audio->amrnb_enc_cfg.enc_mode = 7;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301281
1282 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1283 &audio->queue_ids);
1284 if (encid < 0) {
1285 MM_ERR("No free encoder available\n");
1286 rc = -ENODEV;
1287 goto done;
1288 }
1289 audio->enc_id = encid;
1290 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1291 &audrec_amrnb_adsp_ops, audio);
1292 if (rc) {
1293 audpreproc_aenc_free(audio->enc_id);
1294 goto done;
1295 }
1296
1297 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1298 rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
1299 &audpre_amrnb_adsp_ops, audio);
1300 if (rc) {
1301 msm_adsp_put(audio->audrec);
1302 audpreproc_aenc_free(audio->enc_id);
1303 goto done;
1304 }
1305 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001306 audio->dsp_cnt = 0;
1307 audio->stopped = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301308 audio->wflush = 0;
1309 audio->rflush = 0;
1310 audio->flush_ack = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001311
Manish Dewanganb9171e52011-03-15 15:18:18 +05301312 audamrnb_in_flush(audio);
1313 audamrnb_out_flush(audio);
1314 /* used dma_allco_coherent for backward compatibility with 7x27 */
1315 audio->data = dma_alloc_coherent(NULL, dma_size,
1316 &audio->phys, GFP_KERNEL);
1317 if (!audio->data) {
1318 MM_ERR("Unable to allocate DMA buffer\n");
1319 goto evt_error;
1320 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001321
Manish Dewanganb9171e52011-03-15 15:18:18 +05301322 audio->out_data = NULL;
1323 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
1324 audio->out_phys = allocate_contiguous_ebi_nomap(BUFFER_SIZE,
1325 SZ_4K);
1326 if (!audio->out_phys) {
1327 MM_ERR("could not allocate write buffers\n");
1328 rc = -ENOMEM;
1329 dma_free_coherent(NULL,
1330 dma_size, audio->data, audio->phys);
1331 goto evt_error;
1332 } else {
1333 audio->map_v_write = msm_subsystem_map_buffer(
1334 audio->out_phys, BUFFER_SIZE,
1335 MSM_SUBSYSTEM_MAP_KADDR, NULL, 0);
1336 if (IS_ERR(audio->map_v_write)) {
1337 MM_ERR("could not map write phys address\n");
1338 rc = -ENOMEM;
1339 dma_free_coherent(NULL,
1340 dma_size, audio->data, audio->phys);
1341 free_contiguous_memory_by_paddr(\
1342 audio->out_phys);
1343 goto evt_error;
1344 }
1345 audio->out_data = audio->map_v_write->vaddr;
1346 MM_DBG("wr buf: phy addr 0x%08x kernel addr 0x%08x\n",
1347 audio->out_phys,
1348 (uint32_t)audio->out_data);
1349 }
1350
1351 /* Initialize buffer */
1352 audio->out[0].data = audio->out_data + 0;
1353 audio->out[0].addr = audio->out_phys + 0;
1354 audio->out[0].size = OUT_BUFFER_SIZE;
1355
1356 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1357 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1358 audio->out[1].size = OUT_BUFFER_SIZE;
1359
1360 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1361 (uint32_t)audio->out[0].data,
1362 (uint32_t)audio->out[1].data);
1363 audio->mfield = NT_FRAME_HEADER_SIZE;
1364 audio->out_frame_cnt++;
1365 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001366 file->private_data = audio;
1367 audio->opened = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001368
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001369done:
1370 mutex_unlock(&audio->lock);
1371 return rc;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301372evt_error:
1373 msm_adsp_put(audio->audrec);
1374 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1375 msm_adsp_put(audio->audpre);
1376
1377 audpreproc_aenc_free(audio->enc_id);
1378 mutex_unlock(&audio->lock);
1379 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001380}
1381
1382static const struct file_operations audio_fops = {
1383 .owner = THIS_MODULE,
Manish Dewanganb9171e52011-03-15 15:18:18 +05301384 .open = audamrnb_in_open,
1385 .release = audamrnb_in_release,
1386 .read = audamrnb_in_read,
1387 .write = audamrnb_in_write,
1388 .fsync = audamrnb_in_fsync,
1389 .unlocked_ioctl = audamrnb_in_ioctl,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001390};
1391
Manish Dewanganb9171e52011-03-15 15:18:18 +05301392struct miscdevice audamrnb_in_misc = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001393 .minor = MISC_DYNAMIC_MINOR,
1394 .name = "msm_amrnb_in",
1395 .fops = &audio_fops,
1396};
1397
1398#ifdef CONFIG_DEBUG_FS
1399static ssize_t audamrnb_in_debug_open(struct inode *inode, struct file *file)
1400{
1401 file->private_data = inode->i_private;
1402 return 0;
1403}
1404
1405static ssize_t audamrnb_in_debug_read(struct file *file, char __user *buf,
1406 size_t count, loff_t *ppos)
1407{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301408 const int32_t debug_bufmax = 1024;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001409 static char buffer[1024];
Manish Dewanganb9171e52011-03-15 15:18:18 +05301410 int32_t n = 0, i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001411 struct audio_amrnb_in *audio = file->private_data;
1412
1413 mutex_lock(&audio->lock);
1414 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
1415 n += scnprintf(buffer + n, debug_bufmax - n,
1416 "enabled %d\n", audio->enabled);
1417 n += scnprintf(buffer + n, debug_bufmax - n,
1418 "stopped %d\n", audio->stopped);
1419 n += scnprintf(buffer + n, debug_bufmax - n,
1420 "audrec_obj_idx %d\n", audio->audrec_obj_idx);
1421 n += scnprintf(buffer + n, debug_bufmax - n,
1422 "dsp_cnt %d \n", audio->dsp_cnt);
1423 n += scnprintf(buffer + n, debug_bufmax - n,
1424 "in_count %d \n", audio->in_count);
1425 for (i = 0; i < FRAME_NUM; i++)
1426 n += scnprintf(buffer + n, debug_bufmax - n,
1427 "audio->in[%d].size %d \n", i, audio->in[i].size);
1428 mutex_unlock(&audio->lock);
1429 /* Following variables are only useful for debugging when
1430 * when record halts unexpectedly. Thus, no mutual exclusion
1431 * enforced
1432 */
1433 n += scnprintf(buffer + n, debug_bufmax - n,
1434 "running %d \n", audio->running);
1435 n += scnprintf(buffer + n, debug_bufmax - n,
1436 "buffer_size %d \n", audio->buffer_size);
1437 n += scnprintf(buffer + n, debug_bufmax - n,
1438 "in_head %d \n", audio->in_head);
1439 n += scnprintf(buffer + n, debug_bufmax - n,
1440 "in_tail %d \n", audio->in_tail);
1441 buffer[n] = 0;
1442 return simple_read_from_buffer(buf, count, ppos, buffer, n);
1443}
1444
1445static const struct file_operations audamrnb_in_debug_fops = {
1446 .read = audamrnb_in_debug_read,
1447 .open = audamrnb_in_debug_open,
1448};
1449#endif
1450
Manish Dewanganb9171e52011-03-15 15:18:18 +05301451static int __init audamrnb_in_init(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001452{
1453#ifdef CONFIG_DEBUG_FS
1454 struct dentry *dentry;
1455#endif
1456
1457 mutex_init(&the_audio_amrnb_in.lock);
1458 mutex_init(&the_audio_amrnb_in.read_lock);
1459 spin_lock_init(&the_audio_amrnb_in.dsp_lock);
1460 init_waitqueue_head(&the_audio_amrnb_in.wait);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301461 init_waitqueue_head(&the_audio_amrnb_in.wait_enable);
1462 mutex_init(&the_audio_amrnb_in.write_lock);
1463 init_waitqueue_head(&the_audio_amrnb_in.write_wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464
1465#ifdef CONFIG_DEBUG_FS
1466 dentry = debugfs_create_file("msm_amrnb_in", S_IFREG | S_IRUGO, NULL,
1467 (void *) &the_audio_amrnb_in, &audamrnb_in_debug_fops);
1468
1469 if (IS_ERR(dentry))
1470 MM_ERR("debugfs_create_file failed\n");
1471#endif
Manish Dewanganb9171e52011-03-15 15:18:18 +05301472 return misc_register(&audamrnb_in_misc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001473}
1474
Manish Dewanganb9171e52011-03-15 15:18:18 +05301475static void __exit audamrnb_in_exit(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001476{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301477 misc_deregister(&audamrnb_in_misc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001478}
1479
Manish Dewanganb9171e52011-03-15 15:18:18 +05301480module_init(audamrnb_in_init);
1481module_exit(audamrnb_in_exit);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001482
1483MODULE_DESCRIPTION("MSM AMRNB Encoder driver");
1484MODULE_LICENSE("GPL v2");