blob: bec1d4c824ee753fd94e52824363a8d5a463fb33 [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 *
Laura Abbott35111d32012-04-27 18:41:48 -07005 * Copyright (c) 2009, 2011-2012 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>
Manish Dewanganb9171e52011-03-15 15:18:18 +053047#include <mach/iommu_domains.h>
48
49#include <mach/msm_adsp.h>
50#include <mach/qdsp5/qdsp5audpreproc.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051#include <mach/qdsp5/qdsp5audpreproccmdi.h>
52#include <mach/qdsp5/qdsp5audpreprocmsg.h>
53#include <mach/qdsp5/qdsp5audreccmdi.h>
54#include <mach/qdsp5/qdsp5audrecmsg.h>
55#include <mach/debug_mm.h>
56
Manish Dewanganb9171e52011-03-15 15:18:18 +053057#define FRAME_HEADER_SIZE 8 /* 8 bytes frame header */
58#define NT_FRAME_HEADER_SIZE 24 /* 24 bytes frame header */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059/* FRAME_NUM must be a power of two */
Manish Dewanganb9171e52011-03-15 15:18:18 +053060#define FRAME_NUM 8
61#define AMRNB_FRAME_SIZE 36 /* 36 bytes data */
62/*Tunnel mode : 1536 bytes data + 8 byte header*/
63#define FRAME_SIZE (AMRNB_FRAME_SIZE + FRAME_HEADER_SIZE)
64/* 1536 bytes data + 24 meta field*/
65#define NT_FRAME_SIZE (AMRNB_FRAME_SIZE + NT_FRAME_HEADER_SIZE)
66#define DMASZ (FRAME_SIZE * FRAME_NUM)
67#define NT_DMASZ (NT_FRAME_SIZE * FRAME_NUM)
68#define OUT_FRAME_NUM 2
69#define OUT_BUFFER_SIZE (4 * 1024 + NT_FRAME_HEADER_SIZE)
70#define BUFFER_SIZE (OUT_BUFFER_SIZE * OUT_FRAME_NUM)
71
72/* Offset from beginning of buffer*/
73#define AUDPREPROC_AMRNB_EOS_FLG_OFFSET 0x0A
74#define AUDPREPROC_AMRNB_EOS_FLG_MASK 0x01
75#define AUDPREPROC_AMRNB_EOS_NONE 0x0 /* No EOS detected */
76#define AUDPREPROC_AMRNB_EOS_SET 0x1 /* EOS set in meta field */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070077
78struct buffer {
79 void *data;
80 uint32_t size;
81 uint32_t read;
82 uint32_t addr;
Manish Dewanganb9171e52011-03-15 15:18:18 +053083 uint32_t used;
84 uint32_t mfield_sz;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085};
86
87struct audio_amrnb_in {
88 struct buffer in[FRAME_NUM];
89
90 spinlock_t dsp_lock;
91
92 atomic_t in_bytes;
Manish Dewanganb9171e52011-03-15 15:18:18 +053093 atomic_t in_samples;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094
95 struct mutex lock;
96 struct mutex read_lock;
97 wait_queue_head_t wait;
Manish Dewanganb9171e52011-03-15 15:18:18 +053098 wait_queue_head_t wait_enable;
99 /*write section*/
100 struct buffer out[OUT_FRAME_NUM];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101
Manish Dewanganb9171e52011-03-15 15:18:18 +0530102 uint8_t out_head;
103 uint8_t out_tail;
104 uint8_t out_needed; /* number of buffers the dsp is waiting for */
105 uint32_t out_count;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106
Manish Dewanganb9171e52011-03-15 15:18:18 +0530107 struct mutex write_lock;
108 wait_queue_head_t write_wait;
109 int32_t out_phys; /* physical address of write buffer */
110 char *out_data;
111 uint8_t mfield; /* meta field embedded in data */
112 uint8_t wflush; /*write flush */
113 uint8_t rflush; /*read flush*/
114 uint32_t out_frame_cnt;
115
116 struct msm_adsp_module *audrec;
117 struct msm_adsp_module *audpre;
118
119
120 /* configuration to use on next enable */
121 uint32_t samp_rate;
122 uint32_t channel_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700123 uint32_t buffer_size;
124 uint32_t enc_type; /* 0 for WAV ,1 for AAC,10 for AMRNB */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530125 uint32_t mode; /* T or NT Mode*/
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700126 struct msm_audio_amrnb_enc_config amrnb_enc_cfg;
127
128 uint32_t dsp_cnt;
129 uint32_t in_head; /* next buffer dsp will write */
130 uint32_t in_tail; /* next buffer read() will read */
131 uint32_t in_count; /* number of buffers available to read() */
132
Manish Dewanganb9171e52011-03-15 15:18:18 +0530133 uint32_t eos_ack;
134 uint32_t flush_ack;
135
136 const char *module_name;
137 unsigned queue_ids;
138 uint16_t enc_id; /* Session Id */
139
140 unsigned short samp_rate_index;
141 uint32_t audrec_obj_idx ;
142
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700143 struct audmgr audmgr;
144
145 /* data allocated for various buffers */
146 char *data;
147 dma_addr_t phys;
Laura Abbott35111d32012-04-27 18:41:48 -0700148 void *map_v_write;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700149
Manish Dewanganb9171e52011-03-15 15:18:18 +0530150 uint8_t opened;
151 uint8_t enabled;
152 uint8_t running;
153 uint8_t stopped; /* set when stopped, cleared on flush */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154};
155
Manish Dewanganb9171e52011-03-15 15:18:18 +0530156struct audio_frame {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157 uint16_t frame_count_lsw;
158 uint16_t frame_count_msw;
159 uint16_t frame_length;
160 uint16_t erased_pcm;
161 unsigned char raw_bitstream[];
Manish Dewanganb9171e52011-03-15 15:18:18 +0530162} __packed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163
Manish Dewanganb9171e52011-03-15 15:18:18 +0530164struct audio_frame_nt {
165 uint16_t metadata_len;
166 uint16_t frame_count_lsw;
167 uint16_t frame_count_msw;
168 uint16_t frame_length;
169 uint16_t erased_pcm;
170 uint16_t reserved;
171 uint16_t time_stamp_dword_lsw;
172 uint16_t time_stamp_dword_msw;
173 uint16_t time_stamp_lsw;
174 uint16_t time_stamp_msw;
175 uint16_t nflag_lsw;
176 uint16_t nflag_msw;
177 unsigned char raw_bitstream[]; /* samples */
178} __packed;
179
180struct amrnb_encoded_meta_out {
181 uint16_t metadata_len;
182 uint16_t time_stamp_dword_lsw;
183 uint16_t time_stamp_dword_msw;
184 uint16_t time_stamp_lsw;
185 uint16_t time_stamp_msw;
186 uint16_t nflag_lsw;
187 uint16_t nflag_msw;
188};
189
190/* Audrec Queue command sent macro's */
191#define audio_send_queue_pre(audio, cmd, len) \
192 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
193
194#define audio_send_queue_recbs(audio, cmd, len) \
195 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
196 cmd, len)
197#define audio_send_queue_rec(audio, cmd, len) \
198 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
199 cmd, len)
200
201static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable);
202static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio);
203static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio);
204static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
205 uint32_t read_cnt);
206static void audamrnb_in_flush(struct audio_amrnb_in *audio);
207
208static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio);
209static int audpcm_config(struct audio_amrnb_in *audio);
210static void audamrnb_out_flush(struct audio_amrnb_in *audio);
211static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio);
212static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed);
213static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio);
214static void audamrnb_in_flush(struct audio_amrnb_in *audio);
215
216static unsigned convert_samp_index(unsigned index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530218 switch (index) {
219 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
220 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
221 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
222 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
223 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
224 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
225 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
226 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
227 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
228 default: return 11025;
229 }
230}
231
232/* must be called with audio->lock held */
233static int audamrnb_in_enable(struct audio_amrnb_in *audio)
234{
235 struct audmgr_config cfg;
236 int32_t rc;
237
238 if (audio->enabled)
239 return 0;
240
241 cfg.tx_rate = audio->samp_rate;
242 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
243 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
244 cfg.codec = RPC_AUD_DEF_CODEC_AMR_NB;
245 cfg.snd_method = RPC_SND_METHOD_MIDI;
246
247 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
248 rc = audmgr_enable(&audio->audmgr, &cfg);
249 if (rc < 0)
250 return rc;
251
252 if (msm_adsp_enable(audio->audpre)) {
253 audmgr_disable(&audio->audmgr);
254 MM_ERR("msm_adsp_enable(audpre) failed\n");
255 return -ENODEV;
256 }
257 }
258 if (msm_adsp_enable(audio->audrec)) {
259 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
260 audmgr_disable(&audio->audmgr);
261 msm_adsp_disable(audio->audpre);
262 }
263 MM_ERR("msm_adsp_enable(audrec) failed\n");
264 return -ENODEV;
265 }
266
267 audio->enabled = 1;
268 audamrnb_in_dsp_enable(audio, 1);
269
270 return 0;
271}
272
273/* must be called with audio->lock held */
274static int audamrnb_in_disable(struct audio_amrnb_in *audio)
275{
276 if (audio->enabled) {
277 audio->enabled = 0;
278
279 audamrnb_in_dsp_enable(audio, 0);
280
281 wake_up(&audio->wait);
282 wait_event_interruptible_timeout(audio->wait_enable,
283 audio->running == 0, 1*HZ);
284 msm_adsp_disable(audio->audrec);
285 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
286 msm_adsp_disable(audio->audpre);
287 audmgr_disable(&audio->audmgr);
288 }
289 }
290 return 0;
291}
292
293/* ------------------- dsp --------------------- */
294static void audpre_dsp_event(void *data, unsigned id, size_t len,
295 void (*getevent)(void *ptr, size_t len))
296{
297 uint16_t msg[2];
298 getevent(msg, sizeof(msg));
299
300 switch (id) {
301 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
302 MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
303 break;
304 case AUDPREPROC_MSG_ERROR_MSG_ID:
305 MM_ERR("err_index %d\n", msg[0]);
306 break;
307 case ADSP_MESSAGE_ID:
308 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
309 break;
310 default:
311 MM_ERR("unknown event %d\n", id);
312 }
313}
314
315static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
316{
317 struct audio_frame *frame;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700318 uint32_t index;
319 unsigned long flags;
320 index = audio->in_head;
321
322 frame = (void *) (((char *)audio->in[index].data) -
323 sizeof(*frame));
324 spin_lock_irqsave(&audio->dsp_lock, flags);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530325
326 /* Send Complete Transcoded Data, not actual frame part */
327 audio->in[index].size = FRAME_SIZE - (sizeof(*frame));
328 /* statistics of read */
329 atomic_add(audio->in[index].size, &audio->in_bytes);
330 atomic_add(1, &audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331
332 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
333
334 /* If overflow, move the tail index foward. */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530335 if (audio->in_head == audio->in_tail) {
336 MM_ERR("Error! not able to keep up the read\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530338 MM_ERR("in_count = %d\n", audio->in_count);
339 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700340 audio->in_count++;
341
Manish Dewanganb9171e52011-03-15 15:18:18 +0530342 audamrnb_in_dsp_read_buffer(audio, audio->dsp_cnt++);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 spin_unlock_irqrestore(&audio->dsp_lock, flags);
344
345 wake_up(&audio->wait);
346}
347
Manish Dewanganb9171e52011-03-15 15:18:18 +0530348static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio)
349{
350 struct audio_frame_nt *nt_frame;
351 uint32_t index;
352 unsigned long flags;
353
354 index = audio->in_head;
355 nt_frame = (void *) (((char *)audio->in[index].data) - \
356 sizeof(struct audio_frame_nt));
357 spin_lock_irqsave(&audio->dsp_lock, flags);
358 audio->in[index].size = nt_frame->frame_length;
359 /* statistics of read */
360 atomic_add(audio->in[index].size, &audio->in_bytes);
361 atomic_add(1, &audio->in_samples);
362
363 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
364
365 /* If overflow, move the tail index foward. */
366 if (audio->in_head == audio->in_tail)
367 MM_DBG("Error! not able to keep up the read\n");
368 else
369 audio->in_count++;
370
371 spin_unlock_irqrestore(&audio->dsp_lock, flags);
372 wake_up(&audio->wait);
373}
374
375static int audrec_pcm_buffer_ptr_refresh(struct audio_amrnb_in *audio,
376 unsigned idx, unsigned len)
377{
378 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
379
380 if (len == NT_FRAME_HEADER_SIZE)
381 len = len / 2;
382 else
383 len = (len + NT_FRAME_HEADER_SIZE) / 2;
384 MM_DBG("len = %d\n", len);
385 memset(&cmd, 0, sizeof(cmd));
386 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
387 cmd.num_buffers = 1;
388 if (cmd.num_buffers == 1) {
389 cmd.buf_address_length[0] = (audio->out[idx].addr &
390 0xffff0000) >> 16;
391 cmd.buf_address_length[1] = (audio->out[idx].addr &
392 0x0000ffff);
393 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
394 cmd.buf_address_length[3] = (len & 0x0000ffff);
395 }
396 audio->out_frame_cnt++;
397 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
398}
399
400static int audpcm_config(struct audio_amrnb_in *audio)
401{
402 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
403 MM_DBG("\n");
404 memset(&cmd, 0, sizeof(cmd));
405 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
406 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
407 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
408 cmd.sampling_freq = convert_samp_index(audio->samp_rate);
409 if (!audio->channel_mode)
410 cmd.channels = 1;
411 else
412 cmd.channels = 2;
413 cmd.frequency_of_intimation = 1;
414 cmd.max_number_of_buffers = OUT_FRAME_NUM;
415 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
416}
417
418
419static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio)
420{
421 struct audrec_cmd_routing_mode cmd;
422
423 MM_DBG("\n");
424 memset(&cmd, 0, sizeof(cmd));
425 cmd.cmd_id = AUDREC_CMD_ROUTING_MODE;
426 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
427 cmd.routing_mode = 1;
428 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
429}
430
431static void audrec_dsp_event(void *data, unsigned id, size_t len,
432 void (*getevent)(void *ptr, size_t len))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433{
434 struct audio_amrnb_in *audio = data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530435 if (data)
436 audio = data;
437 else {
438 MM_ERR("invalid data for event %x\n", id);
439 return;
440 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700441
442 switch (id) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530443 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
444 struct audrec_msg_cmd_cfg_done_msg cmd_cfg_done_msg;
445 getevent(&cmd_cfg_done_msg, AUDREC_MSG_CMD_CFG_DONE_MSG_LEN);
446 if (cmd_cfg_done_msg.audrec_enc_type & \
447 AUDREC_MSG_CFG_DONE_ENC_ENA) {
448 audio->audrec_obj_idx = cmd_cfg_done_msg.audrec_obj_idx;
449 MM_DBG("CFG ENABLED\n");
450 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
451 MM_DBG("routing command\n");
452 audamrnb_in_routing_mode_config(audio);
453 } else {
454 audamrnb_in_encmem_config(audio);
455 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700456 } else {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530457 MM_DBG("CFG SLEEP\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700458 audio->running = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530459 wake_up(&audio->wait_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 }
461 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530462 }
463 case AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG: {
464 struct audrec_msg_cmd_routing_mode_done_msg \
465 routing_msg;
466 getevent(&routing_msg, AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG);
467 MM_DBG("AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG");
468 if (routing_msg.configuration == 0) {
469 MM_ERR("routing configuration failed\n");
470 audio->running = 0;
471 wake_up(&audio->wait_enable);
472 } else
473 audamrnb_in_encmem_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700474 break;
475 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530476 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
477 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
478 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
479 audamrnb_in_encparam_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700480 else
Manish Dewanganb9171e52011-03-15 15:18:18 +0530481 audpcm_config(audio);
482 break;
483 }
484
485 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
486 MM_DBG("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
487 audamrnb_in_encparam_config(audio);
488 break;
489 }
490 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
491 MM_DBG("AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG\n");
492 audio->running = 1;
493 wake_up(&audio->wait_enable);
494 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
495 audrec_pcm_send_data(audio, 1);
496 break;
497 }
498 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
499 MM_DBG("ptr_update recieved from DSP\n");
500 audrec_pcm_send_data(audio, 1);
501 break;
502 }
503 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
504 struct audrec_msg_no_ext_pkt_avail_msg err_msg;
505 getevent(&err_msg, AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG_LEN);
506 MM_DBG("NO_EXT_PKT_AVAILABLE_MSG %x\n",\
507 err_msg.audrec_err_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700508 break;
509 }
510 case AUDREC_MSG_PACKET_READY_MSG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530511 struct audrec_msg_packet_ready_msg pkt_ready_msg;
512
513 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
514 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
515 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
516 pkt_ready_msg.pkt_counter_msw, \
517 pkt_ready_msg.pkt_counter_lsw, \
518 pkt_ready_msg.pkt_read_cnt_msw, \
519 pkt_ready_msg.pkt_read_cnt_lsw);
520
521 audamrnb_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700522 break;
523 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530524 case AUDREC_UP_NT_PACKET_READY_MSG: {
525 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
526
527 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
528 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
529 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
530 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
531 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
532 pkt_ready_msg.audrec_upprev_readcount_lsw, \
533 pkt_ready_msg.audrec_upprev_readcount_msw);
534
535 audamrnb_nt_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536 break;
537 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530538 case AUDREC_CMD_FLUSH_DONE_MSG: {
539 audio->wflush = 0;
540 audio->rflush = 0;
541 audio->flush_ack = 1;
542 wake_up(&audio->write_wait);
543 MM_DBG("flush ack recieved\n");
544 break;
545 }
546 case ADSP_MESSAGE_ID:
547 MM_DBG("Received ADSP event: module \
548 enable/disable(audrectask)\n");
549 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 default:
551 MM_ERR("unknown event %d\n", id);
552 }
553}
554
Manish Dewanganb9171e52011-03-15 15:18:18 +0530555struct msm_adsp_ops audpre_amrnb_adsp_ops = {
556 .event = audpre_dsp_event,
557};
558
559struct msm_adsp_ops audrec_amrnb_adsp_ops = {
560 .event = audrec_dsp_event,
561};
562
563static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700564{
565 struct audrec_cmd_enc_cfg cmd;
566
567 memset(&cmd, 0, sizeof(cmd));
568 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530569 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
571 /* Don't care on enable, required on disable */
572 cmd.audrec_obj_idx = audio->audrec_obj_idx;
573
Manish Dewanganb9171e52011-03-15 15:18:18 +0530574 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575}
576
Manish Dewanganb9171e52011-03-15 15:18:18 +0530577static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578{
579 struct audrec_cmd_arecmem_cfg cmd;
580 uint16_t *data = (void *) audio->data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530581 uint8_t n;
582 uint16_t header_len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583
584 memset(&cmd, 0, sizeof(cmd));
585
586 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
587 cmd.audrec_obj_idx = audio->audrec_obj_idx;
588 /* Rate at which packet complete message comes */
589 cmd.audrec_up_pkt_intm_cnt = 1;
590 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
591 cmd.audrec_extpkt_buffer_lsw = audio->phys;
592 /* Max Buffer no available for frames */
593 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
594
595 /* prepare buffer pointers:
Manish Dewanganb9171e52011-03-15 15:18:18 +0530596 * T:36 bytes amrnb packet + 4 halfword header
597 * NT:36 bytes amrnb packet + 12 halfword header
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700598 */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530599 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
600 header_len = FRAME_HEADER_SIZE/2;
601 else
602 header_len = NT_FRAME_HEADER_SIZE/2;
603
604 for (n = 0; n < FRAME_NUM; n++) {
605 audio->in[n].data = data + header_len;
606 data += (AMRNB_FRAME_SIZE/2) + header_len;
607 MM_DBG("0x%8x\n", (uint32_t)(audio->in[n].data - header_len*2));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 }
609
Manish Dewanganb9171e52011-03-15 15:18:18 +0530610 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611}
612
Manish Dewanganb9171e52011-03-15 15:18:18 +0530613static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700614{
615 struct audrec_cmd_arecparam_amrnb_cfg cmd;
616
617 memset(&cmd, 0, sizeof(cmd));
618
619 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
620 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530621 cmd.samp_rate_idx = audio->samp_rate_index; /* 8k Sampling rate */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 cmd.voicememoencweight1 = audio->amrnb_enc_cfg.voicememoencweight1;
623 cmd.voicememoencweight2 = audio->amrnb_enc_cfg.voicememoencweight2;
624 cmd.voicememoencweight3 = audio->amrnb_enc_cfg.voicememoencweight3;
625 cmd.voicememoencweight4 = audio->amrnb_enc_cfg.voicememoencweight4;
626 cmd.update_mode = 0x8000 | 0x0000;
627 cmd.dtx_mode = audio->amrnb_enc_cfg.dtx_mode_enable;
628 cmd.test_mode = audio->amrnb_enc_cfg.test_mode_enable;
629 cmd.used_mode = audio->amrnb_enc_cfg.enc_mode;
630
631 MM_DBG("cmd.common.cmd_id = 0x%4x\n", cmd.common.cmd_id);
632 MM_DBG("cmd.common.audrec_obj_idx = 0x%4x\n",
633 cmd.common.audrec_obj_idx);
634 MM_DBG("cmd.samp_rate_idx = 0x%4x\n", cmd.samp_rate_idx);
635 MM_DBG("cmd.voicememoencweight1 = 0x%4x\n",
636 cmd.voicememoencweight1);
637 MM_DBG("cmd.voicememoencweight2 = 0x%4x\n",
638 cmd.voicememoencweight2);
639 MM_DBG("cmd.voicememoencweight3 = 0x%4x\n",
640 cmd.voicememoencweight3);
641 MM_DBG("cmd.voicememoencweight4 = 0x%4x\n",
642 cmd.voicememoencweight4);
643 MM_DBG("cmd.update_mode = 0x%4x\n", cmd.update_mode);
644 MM_DBG("cmd.dtx_mode = 0x%4x\n", cmd.dtx_mode);
645 MM_DBG("cmd.test_mode = 0x%4x\n", cmd.test_mode);
646 MM_DBG("cmd.used_mode = 0x%4x\n", cmd.used_mode);
647
Manish Dewanganb9171e52011-03-15 15:18:18 +0530648 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649}
650
Manish Dewanganb9171e52011-03-15 15:18:18 +0530651static int audamrnb_flush_command(struct audio_amrnb_in *audio)
652{
653 struct audrec_cmd_flush cmd;
654 MM_DBG("\n");
655 memset(&cmd, 0, sizeof(cmd));
656 cmd.cmd_id = AUDREC_CMD_FLUSH;
657 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
658}
659static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660 uint32_t read_cnt)
661{
662 audrec_cmd_packet_ext_ptr cmd;
663
664 memset(&cmd, 0, sizeof(cmd));
665 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
666 cmd.type = audio->audrec_obj_idx;
667 cmd.curr_rec_count_msw = read_cnt >> 16;
668 cmd.curr_rec_count_lsw = read_cnt;
669
Manish Dewanganb9171e52011-03-15 15:18:18 +0530670 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700671}
672
Manish Dewanganb9171e52011-03-15 15:18:18 +0530673/* ------------------- device --------------------- */
674
675static void audamrnb_ioport_reset(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530677 /* Make sure read/write thread are free from
678 * sleep and knowing that system is not able
679 * to process io request at the moment
680 */
681 wake_up(&audio->write_wait);
682 mutex_lock(&audio->write_lock);
683 audamrnb_in_flush(audio);
684 mutex_unlock(&audio->write_lock);
685 wake_up(&audio->wait);
686 mutex_lock(&audio->read_lock);
687 audamrnb_out_flush(audio);
688 mutex_unlock(&audio->read_lock);
689}
690
691static void audamrnb_in_flush(struct audio_amrnb_in *audio)
692{
693 uint8_t i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700694
695 audio->dsp_cnt = 0;
696 audio->in_head = 0;
697 audio->in_tail = 0;
698 audio->in_count = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530699 audio->eos_ack = 0;
700 for (i = FRAME_NUM-1; i >= 0; i--) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700701 audio->in[i].size = 0;
702 audio->in[i].read = 0;
703 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530704 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
705 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
706 atomic_set(&audio->in_bytes, 0);
707 atomic_set(&audio->in_samples, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700708}
709
Manish Dewanganb9171e52011-03-15 15:18:18 +0530710static void audamrnb_out_flush(struct audio_amrnb_in *audio)
711{
712 uint8_t i;
713
714 audio->out_head = 0;
715 audio->out_tail = 0;
716 audio->out_count = 0;
717 for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
718 audio->out[i].size = 0;
719 audio->out[i].read = 0;
720 audio->out[i].used = 0;
721 }
722}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700723
724/* ------------------- device --------------------- */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530725static long audamrnb_in_ioctl(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726 unsigned int cmd, unsigned long arg)
727{
728 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530729 int32_t rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730
Manish Dewanganb9171e52011-03-15 15:18:18 +0530731 MM_DBG("\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 if (cmd == AUDIO_GET_STATS) {
733 struct msm_audio_stats stats;
734 stats.byte_count = atomic_read(&audio->in_bytes);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530735 stats.sample_count = atomic_read(&audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700736 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
737 return -EFAULT;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530738 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700739 }
740
741 mutex_lock(&audio->lock);
742 switch (cmd) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530743 case AUDIO_START: {
744 rc = audamrnb_in_enable(audio);
745 if (!rc) {
746 rc =
747 wait_event_interruptible_timeout(audio->wait_enable,
748 audio->running != 0, 1*HZ);
749 MM_INFO("state %d rc = %d\n", audio->running, rc);
750
751 if (audio->running == 0)
752 rc = -ENODEV;
753 else
754 rc = 0;
755 }
756 audio->stopped = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700757 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530758 }
759 case AUDIO_STOP: {
760 rc = audamrnb_in_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761 audio->stopped = 1;
762 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530763 }
764 case AUDIO_FLUSH: {
765 MM_DBG("AUDIO_FLUSH\n");
766 audio->rflush = 1;
767 audio->wflush = 1;
768 audamrnb_ioport_reset(audio);
769 if (audio->running) {
770 audamrnb_flush_command(audio);
771 rc = wait_event_interruptible(audio->write_wait,
772 !audio->wflush);
773 if (rc < 0) {
774 MM_ERR("AUDIO_FLUSH interrupted\n");
775 rc = -EINTR;
776 }
777 } else {
778 audio->rflush = 0;
779 audio->wflush = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700781 break;
782 }
783 case AUDIO_GET_CONFIG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530784 struct msm_audio_config cfg;
785 memset(&cfg, 0, sizeof(cfg));
786 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
787 cfg.buffer_size = OUT_BUFFER_SIZE;
788 cfg.buffer_count = OUT_FRAME_NUM;
789 } else {
790 cfg.buffer_size = audio->buffer_size;
791 cfg.buffer_count = FRAME_NUM;
792 }
793 cfg.sample_rate = convert_samp_index(audio->samp_rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700794 cfg.channel_count = 1;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530795 cfg.type = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700796 cfg.unused[0] = 0;
797 cfg.unused[1] = 0;
798 cfg.unused[2] = 0;
799 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
800 rc = -EFAULT;
801 else
802 rc = 0;
803 break;
804 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530805 case AUDIO_GET_STREAM_CONFIG: {
806 struct msm_audio_stream_config cfg;
807 memset(&cfg, 0, sizeof(cfg));
808 cfg.buffer_size = audio->buffer_size;
809 cfg.buffer_count = FRAME_NUM;
810 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
811 rc = -EFAULT;
812 else
813 rc = 0;
814 break;
815 }
816 case AUDIO_SET_STREAM_CONFIG: {
817 struct msm_audio_stream_config cfg;
818 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
819 rc = -EFAULT;
820 break;
821 }
822 /* Allow only single frame */
823 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530824 if (cfg.buffer_size != (FRAME_SIZE - 8)) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530825 rc = -EINVAL;
826 break;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530827 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530828 } else {
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530829 if (cfg.buffer_size != (AMRNB_FRAME_SIZE + 14)) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530830 rc = -EINVAL;
831 break;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530832 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530833 }
834 audio->buffer_size = cfg.buffer_size;
835 break;
836 }
837
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838 case AUDIO_GET_AMRNB_ENC_CONFIG: {
839 if (copy_to_user((void *)arg, &audio->amrnb_enc_cfg,
840 sizeof(audio->amrnb_enc_cfg)))
841 rc = -EFAULT;
842 else
843 rc = 0;
844 break;
845 }
846 case AUDIO_SET_AMRNB_ENC_CONFIG: {
847 struct msm_audio_amrnb_enc_config cfg;
848 if (copy_from_user
849 (&cfg, (void *)arg, sizeof(cfg))) {
850 rc = -EFAULT;
851 } else
852 rc = 0;
853 audio->amrnb_enc_cfg.voicememoencweight1 =
854 cfg.voicememoencweight1;
855 audio->amrnb_enc_cfg.voicememoencweight2 =
856 cfg.voicememoencweight2;
857 audio->amrnb_enc_cfg.voicememoencweight3 =
858 cfg.voicememoencweight3;
859 audio->amrnb_enc_cfg.voicememoencweight4 =
860 cfg.voicememoencweight4;
861 audio->amrnb_enc_cfg.dtx_mode_enable = cfg.dtx_mode_enable;
862 audio->amrnb_enc_cfg.test_mode_enable = cfg.test_mode_enable;
863 audio->amrnb_enc_cfg.enc_mode = cfg.enc_mode;
864 /* Run time change of Param */
865 break;
866 }
867 default:
868 rc = -EINVAL;
869 }
870 mutex_unlock(&audio->lock);
871 return rc;
872}
873
Manish Dewanganb9171e52011-03-15 15:18:18 +0530874static ssize_t audamrnb_in_read(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700875 char __user *buf,
876 size_t count, loff_t *pos)
877{
878 struct audio_amrnb_in *audio = file->private_data;
879 unsigned long flags;
880 const char __user *start = buf;
881 void *data;
882 uint32_t index;
883 uint32_t size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530884 int32_t rc = 0;
885 struct amrnb_encoded_meta_out meta_field;
886 struct audio_frame_nt *nt_frame;
887 MM_DBG("count = %d\n", count);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700888 mutex_lock(&audio->read_lock);
889 while (count > 0) {
890 rc = wait_event_interruptible(
Manish Dewanganb9171e52011-03-15 15:18:18 +0530891 audio->wait, (audio->in_count > 0) || audio->stopped ||
892 audio->rflush);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893 if (rc < 0)
894 break;
895
Manish Dewanganb9171e52011-03-15 15:18:18 +0530896 if (audio->rflush) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700897 rc = -EBUSY;
898 break;
899 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530900 if (audio->stopped && !audio->in_count) {
901 MM_DBG("Driver in stop state, No more buffer to read");
902 rc = 0;/* End of File */
903 break;
904 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700905
906 index = audio->in_tail;
907 data = (uint8_t *) audio->in[index].data;
908 size = audio->in[index].size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530909
910 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
911 nt_frame = (struct audio_frame_nt *)(data -
912 sizeof(struct audio_frame_nt));
913 memcpy((char *)&meta_field.time_stamp_dword_lsw,
914 (char *)&nt_frame->time_stamp_dword_lsw,
915 (sizeof(struct amrnb_encoded_meta_out) - \
916 sizeof(uint16_t)));
917 meta_field.metadata_len =
918 sizeof(struct amrnb_encoded_meta_out);
919 if (copy_to_user((char *)start, (char *)&meta_field,
920 sizeof(struct amrnb_encoded_meta_out))) {
921 rc = -EFAULT;
922 break;
923 }
924 if (nt_frame->nflag_lsw & 0x0001) {
925 MM_ERR("recieved EOS in read call\n");
926 audio->eos_ack = 1;
927 }
928 buf += sizeof(struct amrnb_encoded_meta_out);
929 count -= sizeof(struct amrnb_encoded_meta_out);
930 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700931 if (count >= size) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530932 /* order the reads on the buffer */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700933 dma_coherent_post_ops();
934 if (copy_to_user(buf, data, size)) {
935 rc = -EFAULT;
936 break;
937 }
938 spin_lock_irqsave(&audio->dsp_lock, flags);
939 if (index != audio->in_tail) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530940 /* overrun -- data is
941 * invalid and we need to retry */
942 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700943 continue;
944 }
945 audio->in[index].size = 0;
946 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
947 audio->in_count--;
948 spin_unlock_irqrestore(&audio->dsp_lock, flags);
949 count -= size;
950 buf += size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530951 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
952 if (!audio->eos_ack) {
953 MM_DBG("sending read ptr command \
954 %d %d\n",
955 audio->dsp_cnt,
956 audio->in_tail);
957 audamrnb_in_dsp_read_buffer(audio,
958 audio->dsp_cnt++);
959 }
960 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700961 } else {
962 MM_ERR("short read\n");
963 break;
964 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530965
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700966 }
967 mutex_unlock(&audio->read_lock);
968
969 if (buf > start)
970 return buf - start;
971
972 return rc;
973}
974
Manish Dewanganb9171e52011-03-15 15:18:18 +0530975static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed)
976{
977 struct buffer *frame;
978 unsigned long flags;
979 MM_DBG("\n");
980 spin_lock_irqsave(&audio->dsp_lock, flags);
981 if (!audio->running)
982 goto done;
983
984 if (needed && !audio->wflush) {
985 /* We were called from the callback because the DSP
986 * requested more data. Note that the DSP does want
987 * more data, and if a buffer was in-flight, mark it
988 * as available (since the DSP must now be done with
989 * it).
990 */
991 audio->out_needed = 1;
992 frame = audio->out + audio->out_tail;
993 if (frame->used == 0xffffffff) {
994 MM_DBG("frame %d free\n", audio->out_tail);
995 frame->used = 0;
996 audio->out_tail ^= 1;
997 wake_up(&audio->write_wait);
998 }
999 }
1000
1001 if (audio->out_needed) {
1002 /* If the DSP currently wants data and we have a
1003 * buffer available, we will send it and reset
1004 * the needed flag. We'll mark the buffer as in-flight
1005 * so that it won't be recycled until the next buffer
1006 * is requested
1007 */
1008
1009 frame = audio->out + audio->out_tail;
1010 if (frame->used) {
1011 BUG_ON(frame->used == 0xffffffff);
1012 audrec_pcm_buffer_ptr_refresh(audio,
1013 audio->out_tail,
1014 frame->used);
1015 frame->used = 0xffffffff;
1016 audio->out_needed = 0;
1017 }
1018 }
1019 done:
1020 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1021}
1022
1023static int audamrnb_in_fsync(struct file *file, int datasync)
1024
1025{
1026 struct audio_amrnb_in *audio = file->private_data;
1027 int32_t rc = 0;
1028
1029 MM_DBG("\n"); /* Macro prints the file name and function */
1030 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1031 rc = -EINVAL;
1032 goto done_nolock;
1033 }
1034
1035 mutex_lock(&audio->write_lock);
1036
1037 rc = wait_event_interruptible(audio->write_wait,
1038 audio->wflush);
1039 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1040
1041 if (rc < 0)
1042 goto done;
1043 else if (audio->wflush) {
1044 rc = -EBUSY;
1045 goto done;
1046 }
1047done:
1048 mutex_unlock(&audio->write_lock);
1049done_nolock:
1050 return rc;
1051
1052}
1053
1054int audrec_amrnb_process_eos(struct audio_amrnb_in *audio,
1055 const char __user *buf_start, unsigned short mfield_size)
1056{
1057 struct buffer *frame;
1058 int32_t rc = 0;
1059
1060 frame = audio->out + audio->out_head;
1061
1062 rc = wait_event_interruptible(audio->write_wait,
1063 (audio->out_needed &&
1064 audio->out[0].used == 0 &&
1065 audio->out[1].used == 0)
1066 || (audio->stopped)
1067 || (audio->wflush));
1068
1069 if (rc < 0)
1070 goto done;
1071 if (audio->stopped || audio->wflush) {
1072 rc = -EBUSY;
1073 goto done;
1074 }
1075 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1076 rc = -EFAULT;
1077 goto done;
1078 }
1079
1080 frame->mfield_sz = mfield_size;
1081 audio->out_head ^= 1;
1082 frame->used = mfield_size;
1083 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1084 audrec_pcm_send_data(audio, 0);
1085done:
1086 return rc;
1087}
1088
1089static ssize_t audamrnb_in_write(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001090 const char __user *buf,
1091 size_t count, loff_t *pos)
1092{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301093 struct audio_amrnb_in *audio = file->private_data;
1094 const char __user *start = buf;
1095 struct buffer *frame;
1096 char *cpy_ptr;
1097 int32_t rc = 0, eos_condition = AUDPREPROC_AMRNB_EOS_NONE;
1098 unsigned short mfield_size = 0;
1099 int32_t write_count = 0;
1100 MM_DBG("cnt=%d\n", count);
1101
1102 if (count & 1)
1103 return -EINVAL;
1104
1105 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1106 return -EINVAL;
1107
1108 mutex_lock(&audio->write_lock);
1109 frame = audio->out + audio->out_head;
1110 /* if supplied count is more than driver buffer size
1111 * then only copy driver buffer size
1112 */
1113 if (count > frame->size)
1114 count = frame->size;
1115
1116 write_count = count;
1117 cpy_ptr = frame->data;
1118 rc = wait_event_interruptible(audio->write_wait,
1119 (frame->used == 0)
1120 || (audio->stopped)
1121 || (audio->wflush));
1122 if (rc < 0)
1123 goto error;
1124
1125 if (audio->stopped || audio->wflush) {
1126 rc = -EBUSY;
1127 goto error;
1128 }
1129 if (audio->mfield) {
1130 if (buf == start) {
1131 /* Processing beginning of user buffer */
1132 if (__get_user(mfield_size,
1133 (unsigned short __user *) buf)) {
1134 rc = -EFAULT;
1135 goto error;
1136 } else if (mfield_size > count) {
1137 rc = -EINVAL;
1138 goto error;
1139 }
1140 MM_DBG("mf offset_val %x\n", mfield_size);
1141 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1142 rc = -EFAULT;
1143 goto error;
1144 }
1145 /* Check if EOS flag is set and buffer has
1146 * contains just meta field
1147 */
1148 if (cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &
1149 AUDPREPROC_AMRNB_EOS_FLG_MASK) {
1150 eos_condition = AUDPREPROC_AMRNB_EOS_SET;
1151 MM_DBG("EOS SET\n");
1152 if (mfield_size == count) {
1153 buf += mfield_size;
1154 eos_condition = 0;
1155 goto exit;
1156 } else
1157 cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &=
1158 ~AUDPREPROC_AMRNB_EOS_FLG_MASK;
1159 }
1160 cpy_ptr += mfield_size;
1161 count -= mfield_size;
1162 buf += mfield_size;
1163 } else {
1164 mfield_size = 0;
1165 MM_DBG("continuous buffer\n");
1166 }
1167 frame->mfield_sz = mfield_size;
1168 }
1169 MM_DBG("copying the stream count = %d\n", count);
1170 if (copy_from_user(cpy_ptr, buf, count)) {
1171 rc = -EFAULT;
1172 goto error;
1173 }
1174exit:
1175 frame->used = count;
1176 audio->out_head ^= 1;
1177 if (!audio->flush_ack)
1178 audrec_pcm_send_data(audio, 0);
1179 else {
1180 audrec_pcm_send_data(audio, 1);
1181 audio->flush_ack = 0;
1182 }
1183 if (eos_condition == AUDPREPROC_AMRNB_EOS_SET)
1184 rc = audrec_amrnb_process_eos(audio, start, mfield_size);
1185 mutex_unlock(&audio->write_lock);
1186 return write_count;
1187error:
1188 mutex_unlock(&audio->write_lock);
1189 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001190}
1191
Manish Dewanganb9171e52011-03-15 15:18:18 +05301192static int audamrnb_in_release(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193{
1194 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301195 int32_t dma_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196 mutex_lock(&audio->lock);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301197 audamrnb_in_disable(audio);
1198 audamrnb_in_flush(audio);
1199 msm_adsp_put(audio->audrec);
1200
1201 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1202 msm_adsp_put(audio->audpre);
1203
1204 audpreproc_aenc_free(audio->enc_id);
1205 audio->audrec = NULL;
1206 audio->audpre = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001207 audio->opened = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301208 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
1209 (audio->out_data)) {
Laura Abbott35111d32012-04-27 18:41:48 -07001210 iounmap(audio->map_v_write);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301211 free_contiguous_memory_by_paddr(audio->out_phys);
1212 audio->out_data = NULL;
1213 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001214 if (audio->data) {
Manish Dewanganb9171e52011-03-15 15:18:18 +05301215 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1216 dma_size = DMASZ;
1217 else
1218 dma_size = NT_DMASZ;
1219
1220 dma_free_coherent(NULL,
1221 dma_size, audio->data, audio->phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001222 audio->data = NULL;
1223 }
1224 mutex_unlock(&audio->lock);
1225 return 0;
1226}
1227
Manish Dewanganb9171e52011-03-15 15:18:18 +05301228struct audio_amrnb_in the_audio_amrnb_in;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001229
Manish Dewanganb9171e52011-03-15 15:18:18 +05301230static int audamrnb_in_open(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001231{
1232 struct audio_amrnb_in *audio = &the_audio_amrnb_in;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301233 int32_t rc;
1234 int encid;
1235 int32_t dma_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001236
1237 mutex_lock(&audio->lock);
1238 if (audio->opened) {
1239 rc = -EBUSY;
1240 goto done;
1241 }
Manish Dewanganb9171e52011-03-15 15:18:18 +05301242 if ((file->f_mode & FMODE_WRITE) &&
1243 (file->f_mode & FMODE_READ)) {
1244 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1245 dma_size = NT_DMASZ;
1246 MM_DBG("Opened for non tunnel mode encoding\n");
1247 } else if (!(file->f_mode & FMODE_WRITE) &&
1248 (file->f_mode & FMODE_READ)) {
1249 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1250 dma_size = DMASZ;
1251 MM_DBG("Opened for tunnel mode encoding\n");
1252 } else {
1253 MM_ERR("Invalid mode\n");
1254 rc = -EACCES;
1255 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001256 }
1257
Manish Dewanganb9171e52011-03-15 15:18:18 +05301258 /* Settings will be re-config at AUDIO_SET_CONFIG,
1259 * but at least we need to have initial config
1260 */
1261 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_8000,
1262 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_8000;
1263 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
1264 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1265 audio->buffer_size = (AMRNB_FRAME_SIZE + 14);
1266 else
1267 audio->buffer_size = (FRAME_SIZE - 8);
1268 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_AMRNB | audio->mode;
1269
1270 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1271 rc = audmgr_open(&audio->audmgr);
1272 if (rc)
1273 goto done;
1274 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001275 audio->amrnb_enc_cfg.voicememoencweight1 = 0x0000;
1276 audio->amrnb_enc_cfg.voicememoencweight2 = 0x0000;
1277 audio->amrnb_enc_cfg.voicememoencweight3 = 0x4000;
1278 audio->amrnb_enc_cfg.voicememoencweight4 = 0x0000;
1279 audio->amrnb_enc_cfg.dtx_mode_enable = 0;
1280 audio->amrnb_enc_cfg.test_mode_enable = 0;
1281 audio->amrnb_enc_cfg.enc_mode = 7;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301282
1283 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1284 &audio->queue_ids);
1285 if (encid < 0) {
1286 MM_ERR("No free encoder available\n");
1287 rc = -ENODEV;
1288 goto done;
1289 }
1290 audio->enc_id = encid;
1291 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1292 &audrec_amrnb_adsp_ops, audio);
1293 if (rc) {
1294 audpreproc_aenc_free(audio->enc_id);
1295 goto done;
1296 }
1297
1298 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1299 rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
1300 &audpre_amrnb_adsp_ops, audio);
1301 if (rc) {
1302 msm_adsp_put(audio->audrec);
1303 audpreproc_aenc_free(audio->enc_id);
1304 goto done;
1305 }
1306 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001307 audio->dsp_cnt = 0;
1308 audio->stopped = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301309 audio->wflush = 0;
1310 audio->rflush = 0;
1311 audio->flush_ack = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001312
Manish Dewanganb9171e52011-03-15 15:18:18 +05301313 audamrnb_in_flush(audio);
1314 audamrnb_out_flush(audio);
1315 /* used dma_allco_coherent for backward compatibility with 7x27 */
1316 audio->data = dma_alloc_coherent(NULL, dma_size,
1317 &audio->phys, GFP_KERNEL);
1318 if (!audio->data) {
1319 MM_ERR("Unable to allocate DMA buffer\n");
1320 goto evt_error;
1321 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001322
Manish Dewanganb9171e52011-03-15 15:18:18 +05301323 audio->out_data = NULL;
1324 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
1325 audio->out_phys = allocate_contiguous_ebi_nomap(BUFFER_SIZE,
1326 SZ_4K);
1327 if (!audio->out_phys) {
1328 MM_ERR("could not allocate write buffers\n");
1329 rc = -ENOMEM;
1330 dma_free_coherent(NULL,
1331 dma_size, audio->data, audio->phys);
1332 goto evt_error;
1333 } else {
Laura Abbott35111d32012-04-27 18:41:48 -07001334 audio->map_v_write = ioremap(
1335 audio->out_phys, BUFFER_SIZE);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301336 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 }
Laura Abbott35111d32012-04-27 18:41:48 -07001345 audio->out_data = audio->map_v_write;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301346 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");