blob: 39578c154d99a86e044e655c097b97614a8491a4 [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/memory_alloc.h>
Sidipotu Ashok172c98b2012-06-26 17:58:29 +053040#include <linux/ion.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 */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530154 struct ion_client *client;
155 struct ion_handle *input_buff_handle;
156
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157};
158
Manish Dewanganb9171e52011-03-15 15:18:18 +0530159struct audio_frame {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160 uint16_t frame_count_lsw;
161 uint16_t frame_count_msw;
162 uint16_t frame_length;
163 uint16_t erased_pcm;
164 unsigned char raw_bitstream[];
Manish Dewanganb9171e52011-03-15 15:18:18 +0530165} __packed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166
Manish Dewanganb9171e52011-03-15 15:18:18 +0530167struct audio_frame_nt {
168 uint16_t metadata_len;
169 uint16_t frame_count_lsw;
170 uint16_t frame_count_msw;
171 uint16_t frame_length;
172 uint16_t erased_pcm;
173 uint16_t reserved;
174 uint16_t time_stamp_dword_lsw;
175 uint16_t time_stamp_dword_msw;
176 uint16_t time_stamp_lsw;
177 uint16_t time_stamp_msw;
178 uint16_t nflag_lsw;
179 uint16_t nflag_msw;
180 unsigned char raw_bitstream[]; /* samples */
181} __packed;
182
183struct amrnb_encoded_meta_out {
184 uint16_t metadata_len;
185 uint16_t time_stamp_dword_lsw;
186 uint16_t time_stamp_dword_msw;
187 uint16_t time_stamp_lsw;
188 uint16_t time_stamp_msw;
189 uint16_t nflag_lsw;
190 uint16_t nflag_msw;
191};
192
193/* Audrec Queue command sent macro's */
194#define audio_send_queue_pre(audio, cmd, len) \
195 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
196
197#define audio_send_queue_recbs(audio, cmd, len) \
198 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
199 cmd, len)
200#define audio_send_queue_rec(audio, cmd, len) \
201 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
202 cmd, len)
203
204static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable);
205static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio);
206static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio);
207static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
208 uint32_t read_cnt);
209static void audamrnb_in_flush(struct audio_amrnb_in *audio);
210
211static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio);
212static int audpcm_config(struct audio_amrnb_in *audio);
213static void audamrnb_out_flush(struct audio_amrnb_in *audio);
214static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio);
215static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed);
216static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio);
217static void audamrnb_in_flush(struct audio_amrnb_in *audio);
218
219static unsigned convert_samp_index(unsigned index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700220{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530221 switch (index) {
222 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
223 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
224 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
225 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
226 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
227 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
228 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
229 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
230 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
231 default: return 11025;
232 }
233}
234
235/* must be called with audio->lock held */
236static int audamrnb_in_enable(struct audio_amrnb_in *audio)
237{
238 struct audmgr_config cfg;
239 int32_t rc;
240
241 if (audio->enabled)
242 return 0;
243
244 cfg.tx_rate = audio->samp_rate;
245 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
246 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
247 cfg.codec = RPC_AUD_DEF_CODEC_AMR_NB;
248 cfg.snd_method = RPC_SND_METHOD_MIDI;
249
250 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
251 rc = audmgr_enable(&audio->audmgr, &cfg);
252 if (rc < 0)
253 return rc;
254
255 if (msm_adsp_enable(audio->audpre)) {
256 audmgr_disable(&audio->audmgr);
257 MM_ERR("msm_adsp_enable(audpre) failed\n");
258 return -ENODEV;
259 }
260 }
261 if (msm_adsp_enable(audio->audrec)) {
262 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
263 audmgr_disable(&audio->audmgr);
264 msm_adsp_disable(audio->audpre);
265 }
266 MM_ERR("msm_adsp_enable(audrec) failed\n");
267 return -ENODEV;
268 }
269
270 audio->enabled = 1;
271 audamrnb_in_dsp_enable(audio, 1);
272
273 return 0;
274}
275
276/* must be called with audio->lock held */
277static int audamrnb_in_disable(struct audio_amrnb_in *audio)
278{
279 if (audio->enabled) {
280 audio->enabled = 0;
281
282 audamrnb_in_dsp_enable(audio, 0);
283
284 wake_up(&audio->wait);
285 wait_event_interruptible_timeout(audio->wait_enable,
286 audio->running == 0, 1*HZ);
287 msm_adsp_disable(audio->audrec);
288 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
289 msm_adsp_disable(audio->audpre);
290 audmgr_disable(&audio->audmgr);
291 }
292 }
293 return 0;
294}
295
296/* ------------------- dsp --------------------- */
297static void audpre_dsp_event(void *data, unsigned id, size_t len,
298 void (*getevent)(void *ptr, size_t len))
299{
300 uint16_t msg[2];
301 getevent(msg, sizeof(msg));
302
303 switch (id) {
304 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
305 MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
306 break;
307 case AUDPREPROC_MSG_ERROR_MSG_ID:
308 MM_ERR("err_index %d\n", msg[0]);
309 break;
310 case ADSP_MESSAGE_ID:
311 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
312 break;
313 default:
314 MM_ERR("unknown event %d\n", id);
315 }
316}
317
318static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
319{
320 struct audio_frame *frame;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321 uint32_t index;
322 unsigned long flags;
323 index = audio->in_head;
324
325 frame = (void *) (((char *)audio->in[index].data) -
326 sizeof(*frame));
327 spin_lock_irqsave(&audio->dsp_lock, flags);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530328
329 /* Send Complete Transcoded Data, not actual frame part */
330 audio->in[index].size = FRAME_SIZE - (sizeof(*frame));
331 /* statistics of read */
332 atomic_add(audio->in[index].size, &audio->in_bytes);
333 atomic_add(1, &audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334
335 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
336
337 /* If overflow, move the tail index foward. */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530338 if (audio->in_head == audio->in_tail) {
339 MM_ERR("Error! not able to keep up the read\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700340 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530341 MM_ERR("in_count = %d\n", audio->in_count);
342 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343 audio->in_count++;
344
Manish Dewanganb9171e52011-03-15 15:18:18 +0530345 audamrnb_in_dsp_read_buffer(audio, audio->dsp_cnt++);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700346 spin_unlock_irqrestore(&audio->dsp_lock, flags);
347
348 wake_up(&audio->wait);
349}
350
Manish Dewanganb9171e52011-03-15 15:18:18 +0530351static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio)
352{
353 struct audio_frame_nt *nt_frame;
354 uint32_t index;
355 unsigned long flags;
356
357 index = audio->in_head;
358 nt_frame = (void *) (((char *)audio->in[index].data) - \
359 sizeof(struct audio_frame_nt));
360 spin_lock_irqsave(&audio->dsp_lock, flags);
361 audio->in[index].size = nt_frame->frame_length;
362 /* statistics of read */
363 atomic_add(audio->in[index].size, &audio->in_bytes);
364 atomic_add(1, &audio->in_samples);
365
366 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
367
368 /* If overflow, move the tail index foward. */
369 if (audio->in_head == audio->in_tail)
370 MM_DBG("Error! not able to keep up the read\n");
371 else
372 audio->in_count++;
373
374 spin_unlock_irqrestore(&audio->dsp_lock, flags);
375 wake_up(&audio->wait);
376}
377
378static int audrec_pcm_buffer_ptr_refresh(struct audio_amrnb_in *audio,
379 unsigned idx, unsigned len)
380{
381 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
382
383 if (len == NT_FRAME_HEADER_SIZE)
384 len = len / 2;
385 else
386 len = (len + NT_FRAME_HEADER_SIZE) / 2;
387 MM_DBG("len = %d\n", len);
388 memset(&cmd, 0, sizeof(cmd));
389 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
390 cmd.num_buffers = 1;
391 if (cmd.num_buffers == 1) {
392 cmd.buf_address_length[0] = (audio->out[idx].addr &
393 0xffff0000) >> 16;
394 cmd.buf_address_length[1] = (audio->out[idx].addr &
395 0x0000ffff);
396 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
397 cmd.buf_address_length[3] = (len & 0x0000ffff);
398 }
399 audio->out_frame_cnt++;
400 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
401}
402
403static int audpcm_config(struct audio_amrnb_in *audio)
404{
405 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
406 MM_DBG("\n");
407 memset(&cmd, 0, sizeof(cmd));
408 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
409 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
410 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
411 cmd.sampling_freq = convert_samp_index(audio->samp_rate);
412 if (!audio->channel_mode)
413 cmd.channels = 1;
414 else
415 cmd.channels = 2;
416 cmd.frequency_of_intimation = 1;
417 cmd.max_number_of_buffers = OUT_FRAME_NUM;
418 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
419}
420
421
422static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio)
423{
424 struct audrec_cmd_routing_mode cmd;
425
426 MM_DBG("\n");
427 memset(&cmd, 0, sizeof(cmd));
428 cmd.cmd_id = AUDREC_CMD_ROUTING_MODE;
429 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
430 cmd.routing_mode = 1;
431 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
432}
433
434static void audrec_dsp_event(void *data, unsigned id, size_t len,
435 void (*getevent)(void *ptr, size_t len))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700436{
437 struct audio_amrnb_in *audio = data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530438 if (data)
439 audio = data;
440 else {
441 MM_ERR("invalid data for event %x\n", id);
442 return;
443 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700444
445 switch (id) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530446 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
447 struct audrec_msg_cmd_cfg_done_msg cmd_cfg_done_msg;
448 getevent(&cmd_cfg_done_msg, AUDREC_MSG_CMD_CFG_DONE_MSG_LEN);
449 if (cmd_cfg_done_msg.audrec_enc_type & \
450 AUDREC_MSG_CFG_DONE_ENC_ENA) {
451 audio->audrec_obj_idx = cmd_cfg_done_msg.audrec_obj_idx;
452 MM_DBG("CFG ENABLED\n");
453 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
454 MM_DBG("routing command\n");
455 audamrnb_in_routing_mode_config(audio);
456 } else {
457 audamrnb_in_encmem_config(audio);
458 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700459 } else {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530460 MM_DBG("CFG SLEEP\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700461 audio->running = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530462 wake_up(&audio->wait_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700463 }
464 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530465 }
466 case AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG: {
467 struct audrec_msg_cmd_routing_mode_done_msg \
468 routing_msg;
469 getevent(&routing_msg, AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG);
470 MM_DBG("AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG");
471 if (routing_msg.configuration == 0) {
472 MM_ERR("routing configuration failed\n");
473 audio->running = 0;
474 wake_up(&audio->wait_enable);
475 } else
476 audamrnb_in_encmem_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477 break;
478 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530479 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
480 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
481 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
482 audamrnb_in_encparam_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700483 else
Manish Dewanganb9171e52011-03-15 15:18:18 +0530484 audpcm_config(audio);
485 break;
486 }
487
488 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
489 MM_DBG("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
490 audamrnb_in_encparam_config(audio);
491 break;
492 }
493 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
494 MM_DBG("AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG\n");
495 audio->running = 1;
496 wake_up(&audio->wait_enable);
497 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
498 audrec_pcm_send_data(audio, 1);
499 break;
500 }
501 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
502 MM_DBG("ptr_update recieved from DSP\n");
503 audrec_pcm_send_data(audio, 1);
504 break;
505 }
506 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
507 struct audrec_msg_no_ext_pkt_avail_msg err_msg;
508 getevent(&err_msg, AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG_LEN);
509 MM_DBG("NO_EXT_PKT_AVAILABLE_MSG %x\n",\
510 err_msg.audrec_err_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700511 break;
512 }
513 case AUDREC_MSG_PACKET_READY_MSG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530514 struct audrec_msg_packet_ready_msg pkt_ready_msg;
515
516 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
517 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
518 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
519 pkt_ready_msg.pkt_counter_msw, \
520 pkt_ready_msg.pkt_counter_lsw, \
521 pkt_ready_msg.pkt_read_cnt_msw, \
522 pkt_ready_msg.pkt_read_cnt_lsw);
523
524 audamrnb_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700525 break;
526 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530527 case AUDREC_UP_NT_PACKET_READY_MSG: {
528 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
529
530 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
531 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
532 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
533 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
534 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
535 pkt_ready_msg.audrec_upprev_readcount_lsw, \
536 pkt_ready_msg.audrec_upprev_readcount_msw);
537
538 audamrnb_nt_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700539 break;
540 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530541 case AUDREC_CMD_FLUSH_DONE_MSG: {
542 audio->wflush = 0;
543 audio->rflush = 0;
544 audio->flush_ack = 1;
545 wake_up(&audio->write_wait);
546 MM_DBG("flush ack recieved\n");
547 break;
548 }
549 case ADSP_MESSAGE_ID:
550 MM_DBG("Received ADSP event: module \
551 enable/disable(audrectask)\n");
552 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700553 default:
554 MM_ERR("unknown event %d\n", id);
555 }
556}
557
Manish Dewanganb9171e52011-03-15 15:18:18 +0530558struct msm_adsp_ops audpre_amrnb_adsp_ops = {
559 .event = audpre_dsp_event,
560};
561
562struct msm_adsp_ops audrec_amrnb_adsp_ops = {
563 .event = audrec_dsp_event,
564};
565
566static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567{
568 struct audrec_cmd_enc_cfg cmd;
569
570 memset(&cmd, 0, sizeof(cmd));
571 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530572 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
574 /* Don't care on enable, required on disable */
575 cmd.audrec_obj_idx = audio->audrec_obj_idx;
576
Manish Dewanganb9171e52011-03-15 15:18:18 +0530577 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578}
579
Manish Dewanganb9171e52011-03-15 15:18:18 +0530580static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581{
582 struct audrec_cmd_arecmem_cfg cmd;
583 uint16_t *data = (void *) audio->data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530584 uint8_t n;
585 uint16_t header_len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700586
587 memset(&cmd, 0, sizeof(cmd));
588
589 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
590 cmd.audrec_obj_idx = audio->audrec_obj_idx;
591 /* Rate at which packet complete message comes */
592 cmd.audrec_up_pkt_intm_cnt = 1;
593 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
594 cmd.audrec_extpkt_buffer_lsw = audio->phys;
595 /* Max Buffer no available for frames */
596 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
597
598 /* prepare buffer pointers:
Manish Dewanganb9171e52011-03-15 15:18:18 +0530599 * T:36 bytes amrnb packet + 4 halfword header
600 * NT:36 bytes amrnb packet + 12 halfword header
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700601 */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530602 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
603 header_len = FRAME_HEADER_SIZE/2;
604 else
605 header_len = NT_FRAME_HEADER_SIZE/2;
606
607 for (n = 0; n < FRAME_NUM; n++) {
608 audio->in[n].data = data + header_len;
609 data += (AMRNB_FRAME_SIZE/2) + header_len;
610 MM_DBG("0x%8x\n", (uint32_t)(audio->in[n].data - header_len*2));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611 }
612
Manish Dewanganb9171e52011-03-15 15:18:18 +0530613 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700614}
615
Manish Dewanganb9171e52011-03-15 15:18:18 +0530616static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617{
618 struct audrec_cmd_arecparam_amrnb_cfg cmd;
619
620 memset(&cmd, 0, sizeof(cmd));
621
622 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
623 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530624 cmd.samp_rate_idx = audio->samp_rate_index; /* 8k Sampling rate */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625 cmd.voicememoencweight1 = audio->amrnb_enc_cfg.voicememoencweight1;
626 cmd.voicememoencweight2 = audio->amrnb_enc_cfg.voicememoencweight2;
627 cmd.voicememoencweight3 = audio->amrnb_enc_cfg.voicememoencweight3;
628 cmd.voicememoencweight4 = audio->amrnb_enc_cfg.voicememoencweight4;
629 cmd.update_mode = 0x8000 | 0x0000;
630 cmd.dtx_mode = audio->amrnb_enc_cfg.dtx_mode_enable;
631 cmd.test_mode = audio->amrnb_enc_cfg.test_mode_enable;
632 cmd.used_mode = audio->amrnb_enc_cfg.enc_mode;
633
634 MM_DBG("cmd.common.cmd_id = 0x%4x\n", cmd.common.cmd_id);
635 MM_DBG("cmd.common.audrec_obj_idx = 0x%4x\n",
636 cmd.common.audrec_obj_idx);
637 MM_DBG("cmd.samp_rate_idx = 0x%4x\n", cmd.samp_rate_idx);
638 MM_DBG("cmd.voicememoencweight1 = 0x%4x\n",
639 cmd.voicememoencweight1);
640 MM_DBG("cmd.voicememoencweight2 = 0x%4x\n",
641 cmd.voicememoencweight2);
642 MM_DBG("cmd.voicememoencweight3 = 0x%4x\n",
643 cmd.voicememoencweight3);
644 MM_DBG("cmd.voicememoencweight4 = 0x%4x\n",
645 cmd.voicememoencweight4);
646 MM_DBG("cmd.update_mode = 0x%4x\n", cmd.update_mode);
647 MM_DBG("cmd.dtx_mode = 0x%4x\n", cmd.dtx_mode);
648 MM_DBG("cmd.test_mode = 0x%4x\n", cmd.test_mode);
649 MM_DBG("cmd.used_mode = 0x%4x\n", cmd.used_mode);
650
Manish Dewanganb9171e52011-03-15 15:18:18 +0530651 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652}
653
Manish Dewanganb9171e52011-03-15 15:18:18 +0530654static int audamrnb_flush_command(struct audio_amrnb_in *audio)
655{
656 struct audrec_cmd_flush cmd;
657 MM_DBG("\n");
658 memset(&cmd, 0, sizeof(cmd));
659 cmd.cmd_id = AUDREC_CMD_FLUSH;
660 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
661}
662static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 uint32_t read_cnt)
664{
665 audrec_cmd_packet_ext_ptr cmd;
666
667 memset(&cmd, 0, sizeof(cmd));
668 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
669 cmd.type = audio->audrec_obj_idx;
670 cmd.curr_rec_count_msw = read_cnt >> 16;
671 cmd.curr_rec_count_lsw = read_cnt;
672
Manish Dewanganb9171e52011-03-15 15:18:18 +0530673 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700674}
675
Manish Dewanganb9171e52011-03-15 15:18:18 +0530676/* ------------------- device --------------------- */
677
678static void audamrnb_ioport_reset(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530680 /* Make sure read/write thread are free from
681 * sleep and knowing that system is not able
682 * to process io request at the moment
683 */
684 wake_up(&audio->write_wait);
685 mutex_lock(&audio->write_lock);
686 audamrnb_in_flush(audio);
687 mutex_unlock(&audio->write_lock);
688 wake_up(&audio->wait);
689 mutex_lock(&audio->read_lock);
690 audamrnb_out_flush(audio);
691 mutex_unlock(&audio->read_lock);
692}
693
694static void audamrnb_in_flush(struct audio_amrnb_in *audio)
695{
696 uint8_t i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697
698 audio->dsp_cnt = 0;
699 audio->in_head = 0;
700 audio->in_tail = 0;
701 audio->in_count = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530702 audio->eos_ack = 0;
703 for (i = FRAME_NUM-1; i >= 0; i--) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 audio->in[i].size = 0;
705 audio->in[i].read = 0;
706 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530707 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
708 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
709 atomic_set(&audio->in_bytes, 0);
710 atomic_set(&audio->in_samples, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711}
712
Manish Dewanganb9171e52011-03-15 15:18:18 +0530713static void audamrnb_out_flush(struct audio_amrnb_in *audio)
714{
715 uint8_t i;
716
717 audio->out_head = 0;
718 audio->out_tail = 0;
719 audio->out_count = 0;
720 for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
721 audio->out[i].size = 0;
722 audio->out[i].read = 0;
723 audio->out[i].used = 0;
724 }
725}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726
727/* ------------------- device --------------------- */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530728static long audamrnb_in_ioctl(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 unsigned int cmd, unsigned long arg)
730{
731 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530732 int32_t rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733
Manish Dewanganb9171e52011-03-15 15:18:18 +0530734 MM_DBG("\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735 if (cmd == AUDIO_GET_STATS) {
736 struct msm_audio_stats stats;
737 stats.byte_count = atomic_read(&audio->in_bytes);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530738 stats.sample_count = atomic_read(&audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700739 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
740 return -EFAULT;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530741 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 }
743
744 mutex_lock(&audio->lock);
745 switch (cmd) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530746 case AUDIO_START: {
747 rc = audamrnb_in_enable(audio);
748 if (!rc) {
749 rc =
750 wait_event_interruptible_timeout(audio->wait_enable,
751 audio->running != 0, 1*HZ);
752 MM_INFO("state %d rc = %d\n", audio->running, rc);
753
754 if (audio->running == 0)
755 rc = -ENODEV;
756 else
757 rc = 0;
758 }
759 audio->stopped = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530761 }
762 case AUDIO_STOP: {
763 rc = audamrnb_in_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 audio->stopped = 1;
765 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530766 }
767 case AUDIO_FLUSH: {
768 MM_DBG("AUDIO_FLUSH\n");
769 audio->rflush = 1;
770 audio->wflush = 1;
771 audamrnb_ioport_reset(audio);
772 if (audio->running) {
773 audamrnb_flush_command(audio);
774 rc = wait_event_interruptible(audio->write_wait,
775 !audio->wflush);
776 if (rc < 0) {
777 MM_ERR("AUDIO_FLUSH interrupted\n");
778 rc = -EINTR;
779 }
780 } else {
781 audio->rflush = 0;
782 audio->wflush = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700783 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 break;
785 }
786 case AUDIO_GET_CONFIG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530787 struct msm_audio_config cfg;
788 memset(&cfg, 0, sizeof(cfg));
789 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
790 cfg.buffer_size = OUT_BUFFER_SIZE;
791 cfg.buffer_count = OUT_FRAME_NUM;
792 } else {
793 cfg.buffer_size = audio->buffer_size;
794 cfg.buffer_count = FRAME_NUM;
795 }
796 cfg.sample_rate = convert_samp_index(audio->samp_rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700797 cfg.channel_count = 1;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530798 cfg.type = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700799 cfg.unused[0] = 0;
800 cfg.unused[1] = 0;
801 cfg.unused[2] = 0;
802 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
803 rc = -EFAULT;
804 else
805 rc = 0;
806 break;
807 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530808 case AUDIO_GET_STREAM_CONFIG: {
809 struct msm_audio_stream_config cfg;
810 memset(&cfg, 0, sizeof(cfg));
811 cfg.buffer_size = audio->buffer_size;
812 cfg.buffer_count = FRAME_NUM;
813 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
814 rc = -EFAULT;
815 else
816 rc = 0;
817 break;
818 }
819 case AUDIO_SET_STREAM_CONFIG: {
820 struct msm_audio_stream_config cfg;
821 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
822 rc = -EFAULT;
823 break;
824 }
825 /* Allow only single frame */
826 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530827 if (cfg.buffer_size != (FRAME_SIZE - 8)) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530828 rc = -EINVAL;
829 break;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530830 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530831 } else {
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530832 if (cfg.buffer_size != (AMRNB_FRAME_SIZE + 14)) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530833 rc = -EINVAL;
834 break;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530835 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530836 }
837 audio->buffer_size = cfg.buffer_size;
838 break;
839 }
840
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841 case AUDIO_GET_AMRNB_ENC_CONFIG: {
842 if (copy_to_user((void *)arg, &audio->amrnb_enc_cfg,
843 sizeof(audio->amrnb_enc_cfg)))
844 rc = -EFAULT;
845 else
846 rc = 0;
847 break;
848 }
849 case AUDIO_SET_AMRNB_ENC_CONFIG: {
850 struct msm_audio_amrnb_enc_config cfg;
851 if (copy_from_user
852 (&cfg, (void *)arg, sizeof(cfg))) {
853 rc = -EFAULT;
854 } else
855 rc = 0;
856 audio->amrnb_enc_cfg.voicememoencweight1 =
857 cfg.voicememoencweight1;
858 audio->amrnb_enc_cfg.voicememoencweight2 =
859 cfg.voicememoencweight2;
860 audio->amrnb_enc_cfg.voicememoencweight3 =
861 cfg.voicememoencweight3;
862 audio->amrnb_enc_cfg.voicememoencweight4 =
863 cfg.voicememoencweight4;
864 audio->amrnb_enc_cfg.dtx_mode_enable = cfg.dtx_mode_enable;
865 audio->amrnb_enc_cfg.test_mode_enable = cfg.test_mode_enable;
866 audio->amrnb_enc_cfg.enc_mode = cfg.enc_mode;
867 /* Run time change of Param */
868 break;
869 }
870 default:
871 rc = -EINVAL;
872 }
873 mutex_unlock(&audio->lock);
874 return rc;
875}
876
Manish Dewanganb9171e52011-03-15 15:18:18 +0530877static ssize_t audamrnb_in_read(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700878 char __user *buf,
879 size_t count, loff_t *pos)
880{
881 struct audio_amrnb_in *audio = file->private_data;
882 unsigned long flags;
883 const char __user *start = buf;
884 void *data;
885 uint32_t index;
886 uint32_t size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530887 int32_t rc = 0;
888 struct amrnb_encoded_meta_out meta_field;
889 struct audio_frame_nt *nt_frame;
890 MM_DBG("count = %d\n", count);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700891 mutex_lock(&audio->read_lock);
892 while (count > 0) {
893 rc = wait_event_interruptible(
Manish Dewanganb9171e52011-03-15 15:18:18 +0530894 audio->wait, (audio->in_count > 0) || audio->stopped ||
895 audio->rflush);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896 if (rc < 0)
897 break;
898
Manish Dewanganb9171e52011-03-15 15:18:18 +0530899 if (audio->rflush) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700900 rc = -EBUSY;
901 break;
902 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530903 if (audio->stopped && !audio->in_count) {
904 MM_DBG("Driver in stop state, No more buffer to read");
905 rc = 0;/* End of File */
906 break;
907 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908
909 index = audio->in_tail;
910 data = (uint8_t *) audio->in[index].data;
911 size = audio->in[index].size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530912
913 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
914 nt_frame = (struct audio_frame_nt *)(data -
915 sizeof(struct audio_frame_nt));
916 memcpy((char *)&meta_field.time_stamp_dword_lsw,
917 (char *)&nt_frame->time_stamp_dword_lsw,
918 (sizeof(struct amrnb_encoded_meta_out) - \
919 sizeof(uint16_t)));
920 meta_field.metadata_len =
921 sizeof(struct amrnb_encoded_meta_out);
922 if (copy_to_user((char *)start, (char *)&meta_field,
923 sizeof(struct amrnb_encoded_meta_out))) {
924 rc = -EFAULT;
925 break;
926 }
927 if (nt_frame->nflag_lsw & 0x0001) {
928 MM_ERR("recieved EOS in read call\n");
929 audio->eos_ack = 1;
930 }
931 buf += sizeof(struct amrnb_encoded_meta_out);
932 count -= sizeof(struct amrnb_encoded_meta_out);
933 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700934 if (count >= size) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530935 /* order the reads on the buffer */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700936 dma_coherent_post_ops();
937 if (copy_to_user(buf, data, size)) {
938 rc = -EFAULT;
939 break;
940 }
941 spin_lock_irqsave(&audio->dsp_lock, flags);
942 if (index != audio->in_tail) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530943 /* overrun -- data is
944 * invalid and we need to retry */
945 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700946 continue;
947 }
948 audio->in[index].size = 0;
949 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
950 audio->in_count--;
951 spin_unlock_irqrestore(&audio->dsp_lock, flags);
952 count -= size;
953 buf += size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530954 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
955 if (!audio->eos_ack) {
956 MM_DBG("sending read ptr command \
957 %d %d\n",
958 audio->dsp_cnt,
959 audio->in_tail);
960 audamrnb_in_dsp_read_buffer(audio,
961 audio->dsp_cnt++);
962 }
963 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700964 } else {
965 MM_ERR("short read\n");
966 break;
967 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530968
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700969 }
970 mutex_unlock(&audio->read_lock);
971
972 if (buf > start)
973 return buf - start;
974
975 return rc;
976}
977
Manish Dewanganb9171e52011-03-15 15:18:18 +0530978static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed)
979{
980 struct buffer *frame;
981 unsigned long flags;
982 MM_DBG("\n");
983 spin_lock_irqsave(&audio->dsp_lock, flags);
984 if (!audio->running)
985 goto done;
986
987 if (needed && !audio->wflush) {
988 /* We were called from the callback because the DSP
989 * requested more data. Note that the DSP does want
990 * more data, and if a buffer was in-flight, mark it
991 * as available (since the DSP must now be done with
992 * it).
993 */
994 audio->out_needed = 1;
995 frame = audio->out + audio->out_tail;
996 if (frame->used == 0xffffffff) {
997 MM_DBG("frame %d free\n", audio->out_tail);
998 frame->used = 0;
999 audio->out_tail ^= 1;
1000 wake_up(&audio->write_wait);
1001 }
1002 }
1003
1004 if (audio->out_needed) {
1005 /* If the DSP currently wants data and we have a
1006 * buffer available, we will send it and reset
1007 * the needed flag. We'll mark the buffer as in-flight
1008 * so that it won't be recycled until the next buffer
1009 * is requested
1010 */
1011
1012 frame = audio->out + audio->out_tail;
1013 if (frame->used) {
1014 BUG_ON(frame->used == 0xffffffff);
1015 audrec_pcm_buffer_ptr_refresh(audio,
1016 audio->out_tail,
1017 frame->used);
1018 frame->used = 0xffffffff;
1019 audio->out_needed = 0;
1020 }
1021 }
1022 done:
1023 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1024}
1025
Steve Mucklef132c6c2012-06-06 18:30:57 -07001026static int audamrnb_in_fsync(struct file *file, loff_t a, loff_t b, int datasync)
Manish Dewanganb9171e52011-03-15 15:18:18 +05301027
1028{
1029 struct audio_amrnb_in *audio = file->private_data;
1030 int32_t rc = 0;
1031
1032 MM_DBG("\n"); /* Macro prints the file name and function */
1033 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1034 rc = -EINVAL;
1035 goto done_nolock;
1036 }
1037
1038 mutex_lock(&audio->write_lock);
1039
1040 rc = wait_event_interruptible(audio->write_wait,
1041 audio->wflush);
1042 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1043
1044 if (rc < 0)
1045 goto done;
1046 else if (audio->wflush) {
1047 rc = -EBUSY;
1048 goto done;
1049 }
1050done:
1051 mutex_unlock(&audio->write_lock);
1052done_nolock:
1053 return rc;
1054
1055}
1056
1057int audrec_amrnb_process_eos(struct audio_amrnb_in *audio,
1058 const char __user *buf_start, unsigned short mfield_size)
1059{
1060 struct buffer *frame;
1061 int32_t rc = 0;
1062
1063 frame = audio->out + audio->out_head;
1064
1065 rc = wait_event_interruptible(audio->write_wait,
1066 (audio->out_needed &&
1067 audio->out[0].used == 0 &&
1068 audio->out[1].used == 0)
1069 || (audio->stopped)
1070 || (audio->wflush));
1071
1072 if (rc < 0)
1073 goto done;
1074 if (audio->stopped || audio->wflush) {
1075 rc = -EBUSY;
1076 goto done;
1077 }
1078 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1079 rc = -EFAULT;
1080 goto done;
1081 }
1082
1083 frame->mfield_sz = mfield_size;
1084 audio->out_head ^= 1;
1085 frame->used = mfield_size;
1086 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1087 audrec_pcm_send_data(audio, 0);
1088done:
1089 return rc;
1090}
1091
1092static ssize_t audamrnb_in_write(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001093 const char __user *buf,
1094 size_t count, loff_t *pos)
1095{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301096 struct audio_amrnb_in *audio = file->private_data;
1097 const char __user *start = buf;
1098 struct buffer *frame;
1099 char *cpy_ptr;
1100 int32_t rc = 0, eos_condition = AUDPREPROC_AMRNB_EOS_NONE;
1101 unsigned short mfield_size = 0;
1102 int32_t write_count = 0;
1103 MM_DBG("cnt=%d\n", count);
1104
1105 if (count & 1)
1106 return -EINVAL;
1107
1108 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1109 return -EINVAL;
1110
1111 mutex_lock(&audio->write_lock);
1112 frame = audio->out + audio->out_head;
1113 /* if supplied count is more than driver buffer size
1114 * then only copy driver buffer size
1115 */
1116 if (count > frame->size)
1117 count = frame->size;
1118
1119 write_count = count;
1120 cpy_ptr = frame->data;
1121 rc = wait_event_interruptible(audio->write_wait,
1122 (frame->used == 0)
1123 || (audio->stopped)
1124 || (audio->wflush));
1125 if (rc < 0)
1126 goto error;
1127
1128 if (audio->stopped || audio->wflush) {
1129 rc = -EBUSY;
1130 goto error;
1131 }
1132 if (audio->mfield) {
1133 if (buf == start) {
1134 /* Processing beginning of user buffer */
1135 if (__get_user(mfield_size,
1136 (unsigned short __user *) buf)) {
1137 rc = -EFAULT;
1138 goto error;
1139 } else if (mfield_size > count) {
1140 rc = -EINVAL;
1141 goto error;
1142 }
1143 MM_DBG("mf offset_val %x\n", mfield_size);
1144 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1145 rc = -EFAULT;
1146 goto error;
1147 }
1148 /* Check if EOS flag is set and buffer has
1149 * contains just meta field
1150 */
1151 if (cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &
1152 AUDPREPROC_AMRNB_EOS_FLG_MASK) {
1153 eos_condition = AUDPREPROC_AMRNB_EOS_SET;
1154 MM_DBG("EOS SET\n");
1155 if (mfield_size == count) {
1156 buf += mfield_size;
1157 eos_condition = 0;
1158 goto exit;
1159 } else
1160 cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &=
1161 ~AUDPREPROC_AMRNB_EOS_FLG_MASK;
1162 }
1163 cpy_ptr += mfield_size;
1164 count -= mfield_size;
1165 buf += mfield_size;
1166 } else {
1167 mfield_size = 0;
1168 MM_DBG("continuous buffer\n");
1169 }
1170 frame->mfield_sz = mfield_size;
1171 }
1172 MM_DBG("copying the stream count = %d\n", count);
1173 if (copy_from_user(cpy_ptr, buf, count)) {
1174 rc = -EFAULT;
1175 goto error;
1176 }
1177exit:
1178 frame->used = count;
1179 audio->out_head ^= 1;
1180 if (!audio->flush_ack)
1181 audrec_pcm_send_data(audio, 0);
1182 else {
1183 audrec_pcm_send_data(audio, 1);
1184 audio->flush_ack = 0;
1185 }
1186 if (eos_condition == AUDPREPROC_AMRNB_EOS_SET)
1187 rc = audrec_amrnb_process_eos(audio, start, mfield_size);
1188 mutex_unlock(&audio->write_lock);
1189 return write_count;
1190error:
1191 mutex_unlock(&audio->write_lock);
1192 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193}
1194
Manish Dewanganb9171e52011-03-15 15:18:18 +05301195static int audamrnb_in_release(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196{
1197 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301198 int32_t dma_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001199 mutex_lock(&audio->lock);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301200 audamrnb_in_disable(audio);
1201 audamrnb_in_flush(audio);
1202 msm_adsp_put(audio->audrec);
1203
1204 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1205 msm_adsp_put(audio->audpre);
1206
1207 audpreproc_aenc_free(audio->enc_id);
1208 audio->audrec = NULL;
1209 audio->audpre = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001210 audio->opened = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301211 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
1212 (audio->out_data)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301213 ion_unmap_kernel(audio->client, audio->input_buff_handle);
1214 ion_free(audio->client, audio->input_buff_handle);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301215 audio->out_data = NULL;
1216 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001217 if (audio->data) {
Manish Dewanganb9171e52011-03-15 15:18:18 +05301218 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1219 dma_size = DMASZ;
1220 else
1221 dma_size = NT_DMASZ;
1222
1223 dma_free_coherent(NULL,
1224 dma_size, audio->data, audio->phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001225 audio->data = NULL;
1226 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301227 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001228 mutex_unlock(&audio->lock);
1229 return 0;
1230}
1231
Manish Dewanganb9171e52011-03-15 15:18:18 +05301232struct audio_amrnb_in the_audio_amrnb_in;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001233
Manish Dewanganb9171e52011-03-15 15:18:18 +05301234static int audamrnb_in_open(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001235{
1236 struct audio_amrnb_in *audio = &the_audio_amrnb_in;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301237 int32_t rc;
1238 int encid;
1239 int32_t dma_size = 0;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301240 int len = 0;
1241 unsigned long ionflag = 0;
1242 ion_phys_addr_t addr = 0;
1243 struct ion_handle *handle = NULL;
1244 struct ion_client *client = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001245
1246 mutex_lock(&audio->lock);
1247 if (audio->opened) {
1248 rc = -EBUSY;
1249 goto done;
1250 }
Manish Dewanganb9171e52011-03-15 15:18:18 +05301251 if ((file->f_mode & FMODE_WRITE) &&
1252 (file->f_mode & FMODE_READ)) {
1253 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1254 dma_size = NT_DMASZ;
1255 MM_DBG("Opened for non tunnel mode encoding\n");
1256 } else if (!(file->f_mode & FMODE_WRITE) &&
1257 (file->f_mode & FMODE_READ)) {
1258 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1259 dma_size = DMASZ;
1260 MM_DBG("Opened for tunnel mode encoding\n");
1261 } else {
1262 MM_ERR("Invalid mode\n");
1263 rc = -EACCES;
1264 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001265 }
1266
Manish Dewanganb9171e52011-03-15 15:18:18 +05301267 /* Settings will be re-config at AUDIO_SET_CONFIG,
1268 * but at least we need to have initial config
1269 */
1270 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_8000,
1271 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_8000;
1272 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
1273 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1274 audio->buffer_size = (AMRNB_FRAME_SIZE + 14);
1275 else
1276 audio->buffer_size = (FRAME_SIZE - 8);
1277 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_AMRNB | audio->mode;
1278
1279 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1280 rc = audmgr_open(&audio->audmgr);
1281 if (rc)
1282 goto done;
1283 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001284 audio->amrnb_enc_cfg.voicememoencweight1 = 0x0000;
1285 audio->amrnb_enc_cfg.voicememoencweight2 = 0x0000;
1286 audio->amrnb_enc_cfg.voicememoencweight3 = 0x4000;
1287 audio->amrnb_enc_cfg.voicememoencweight4 = 0x0000;
1288 audio->amrnb_enc_cfg.dtx_mode_enable = 0;
1289 audio->amrnb_enc_cfg.test_mode_enable = 0;
1290 audio->amrnb_enc_cfg.enc_mode = 7;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301291
1292 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1293 &audio->queue_ids);
1294 if (encid < 0) {
1295 MM_ERR("No free encoder available\n");
1296 rc = -ENODEV;
1297 goto done;
1298 }
1299 audio->enc_id = encid;
1300 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1301 &audrec_amrnb_adsp_ops, audio);
1302 if (rc) {
1303 audpreproc_aenc_free(audio->enc_id);
1304 goto done;
1305 }
1306
1307 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1308 rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
1309 &audpre_amrnb_adsp_ops, audio);
1310 if (rc) {
1311 msm_adsp_put(audio->audrec);
1312 audpreproc_aenc_free(audio->enc_id);
1313 goto done;
1314 }
1315 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001316 audio->dsp_cnt = 0;
1317 audio->stopped = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301318 audio->wflush = 0;
1319 audio->rflush = 0;
1320 audio->flush_ack = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001321
Manish Dewanganb9171e52011-03-15 15:18:18 +05301322 audamrnb_in_flush(audio);
1323 audamrnb_out_flush(audio);
1324 /* used dma_allco_coherent for backward compatibility with 7x27 */
1325 audio->data = dma_alloc_coherent(NULL, dma_size,
1326 &audio->phys, GFP_KERNEL);
1327 if (!audio->data) {
1328 MM_ERR("Unable to allocate DMA buffer\n");
1329 goto evt_error;
1330 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001331
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301332 client = msm_ion_client_create(UINT_MAX, "Audio_AMRNB_in_client");
1333 if (IS_ERR_OR_NULL(client)) {
1334 MM_ERR("Unable to create ION client\n");
1335 rc = -ENOMEM;
1336 goto client_create_error;
1337 }
1338 audio->client = client;
1339
Manish Dewanganb9171e52011-03-15 15:18:18 +05301340 audio->out_data = NULL;
1341 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301342 MM_DBG("allocating BUFFER_SIZE %d\n", BUFFER_SIZE);
1343 handle = ion_alloc(client, BUFFER_SIZE,
1344 SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
1345 if (IS_ERR_OR_NULL(handle)) {
1346 MM_ERR("Unable to create allocate write buffers\n");
Manish Dewanganb9171e52011-03-15 15:18:18 +05301347 rc = -ENOMEM;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301348 goto input_buff_alloc_error;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301349 }
1350
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301351 audio->input_buff_handle = handle;
1352
1353 rc = ion_phys(client , handle, &addr, &len);
1354 if (rc) {
1355 MM_ERR("I/P buffers:Invalid phy: %x sz: %x\n",
1356 (unsigned int) addr, (unsigned int) len);
1357 rc = -ENOMEM;
1358 goto input_buff_get_phys_error;
1359 } else {
1360 MM_INFO("Got valid phy: %x sz: %x\n",
1361 (unsigned int) addr,
1362 (unsigned int) len);
1363 }
1364 audio->out_phys = (int32_t)addr;
1365
1366 rc = ion_handle_get_flags(client,
1367 handle, &ionflag);
1368 if (rc) {
1369 MM_ERR("could not get flags for the handle\n");
1370 rc = -ENOMEM;
1371 goto input_buff_get_flags_error;
1372 }
1373
1374 audio->map_v_write = ion_map_kernel(client,
1375 handle, ionflag);
1376 if (IS_ERR(audio->map_v_write)) {
1377 MM_ERR("could not map write buffers\n");
1378 rc = -ENOMEM;
1379 goto input_buff_map_error;
1380 }
1381 audio->out_data = audio->map_v_write;
1382 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1383 (unsigned int)addr,
1384 (unsigned int)audio->out_data);
1385
Manish Dewanganb9171e52011-03-15 15:18:18 +05301386 /* Initialize buffer */
1387 audio->out[0].data = audio->out_data + 0;
1388 audio->out[0].addr = audio->out_phys + 0;
1389 audio->out[0].size = OUT_BUFFER_SIZE;
1390
1391 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1392 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1393 audio->out[1].size = OUT_BUFFER_SIZE;
1394
1395 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1396 (uint32_t)audio->out[0].data,
1397 (uint32_t)audio->out[1].data);
1398 audio->mfield = NT_FRAME_HEADER_SIZE;
1399 audio->out_frame_cnt++;
1400 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001401 file->private_data = audio;
1402 audio->opened = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001404done:
1405 mutex_unlock(&audio->lock);
1406 return rc;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301407input_buff_map_error:
1408input_buff_get_phys_error:
1409input_buff_get_flags_error:
1410 ion_free(client, audio->input_buff_handle);
1411input_buff_alloc_error:
1412 ion_client_destroy(client);
1413client_create_error:
1414 dma_free_coherent(NULL, dma_size, audio->data, audio->phys);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301415evt_error:
1416 msm_adsp_put(audio->audrec);
1417 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1418 msm_adsp_put(audio->audpre);
1419
1420 audpreproc_aenc_free(audio->enc_id);
1421 mutex_unlock(&audio->lock);
1422 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001423}
1424
1425static const struct file_operations audio_fops = {
1426 .owner = THIS_MODULE,
Manish Dewanganb9171e52011-03-15 15:18:18 +05301427 .open = audamrnb_in_open,
1428 .release = audamrnb_in_release,
1429 .read = audamrnb_in_read,
1430 .write = audamrnb_in_write,
1431 .fsync = audamrnb_in_fsync,
1432 .unlocked_ioctl = audamrnb_in_ioctl,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001433};
1434
Manish Dewanganb9171e52011-03-15 15:18:18 +05301435struct miscdevice audamrnb_in_misc = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001436 .minor = MISC_DYNAMIC_MINOR,
1437 .name = "msm_amrnb_in",
1438 .fops = &audio_fops,
1439};
1440
1441#ifdef CONFIG_DEBUG_FS
1442static ssize_t audamrnb_in_debug_open(struct inode *inode, struct file *file)
1443{
1444 file->private_data = inode->i_private;
1445 return 0;
1446}
1447
1448static ssize_t audamrnb_in_debug_read(struct file *file, char __user *buf,
1449 size_t count, loff_t *ppos)
1450{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301451 const int32_t debug_bufmax = 1024;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001452 static char buffer[1024];
Manish Dewanganb9171e52011-03-15 15:18:18 +05301453 int32_t n = 0, i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001454 struct audio_amrnb_in *audio = file->private_data;
1455
1456 mutex_lock(&audio->lock);
1457 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
1458 n += scnprintf(buffer + n, debug_bufmax - n,
1459 "enabled %d\n", audio->enabled);
1460 n += scnprintf(buffer + n, debug_bufmax - n,
1461 "stopped %d\n", audio->stopped);
1462 n += scnprintf(buffer + n, debug_bufmax - n,
1463 "audrec_obj_idx %d\n", audio->audrec_obj_idx);
1464 n += scnprintf(buffer + n, debug_bufmax - n,
1465 "dsp_cnt %d \n", audio->dsp_cnt);
1466 n += scnprintf(buffer + n, debug_bufmax - n,
1467 "in_count %d \n", audio->in_count);
1468 for (i = 0; i < FRAME_NUM; i++)
1469 n += scnprintf(buffer + n, debug_bufmax - n,
1470 "audio->in[%d].size %d \n", i, audio->in[i].size);
1471 mutex_unlock(&audio->lock);
1472 /* Following variables are only useful for debugging when
1473 * when record halts unexpectedly. Thus, no mutual exclusion
1474 * enforced
1475 */
1476 n += scnprintf(buffer + n, debug_bufmax - n,
1477 "running %d \n", audio->running);
1478 n += scnprintf(buffer + n, debug_bufmax - n,
1479 "buffer_size %d \n", audio->buffer_size);
1480 n += scnprintf(buffer + n, debug_bufmax - n,
1481 "in_head %d \n", audio->in_head);
1482 n += scnprintf(buffer + n, debug_bufmax - n,
1483 "in_tail %d \n", audio->in_tail);
1484 buffer[n] = 0;
1485 return simple_read_from_buffer(buf, count, ppos, buffer, n);
1486}
1487
1488static const struct file_operations audamrnb_in_debug_fops = {
1489 .read = audamrnb_in_debug_read,
1490 .open = audamrnb_in_debug_open,
1491};
1492#endif
1493
Manish Dewanganb9171e52011-03-15 15:18:18 +05301494static int __init audamrnb_in_init(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495{
1496#ifdef CONFIG_DEBUG_FS
1497 struct dentry *dentry;
1498#endif
1499
1500 mutex_init(&the_audio_amrnb_in.lock);
1501 mutex_init(&the_audio_amrnb_in.read_lock);
1502 spin_lock_init(&the_audio_amrnb_in.dsp_lock);
1503 init_waitqueue_head(&the_audio_amrnb_in.wait);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301504 init_waitqueue_head(&the_audio_amrnb_in.wait_enable);
1505 mutex_init(&the_audio_amrnb_in.write_lock);
1506 init_waitqueue_head(&the_audio_amrnb_in.write_wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001507
1508#ifdef CONFIG_DEBUG_FS
1509 dentry = debugfs_create_file("msm_amrnb_in", S_IFREG | S_IRUGO, NULL,
1510 (void *) &the_audio_amrnb_in, &audamrnb_in_debug_fops);
1511
1512 if (IS_ERR(dentry))
1513 MM_ERR("debugfs_create_file failed\n");
1514#endif
Manish Dewanganb9171e52011-03-15 15:18:18 +05301515 return misc_register(&audamrnb_in_misc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001516}
1517
Manish Dewanganb9171e52011-03-15 15:18:18 +05301518static void __exit audamrnb_in_exit(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001519{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301520 misc_deregister(&audamrnb_in_misc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001521}
1522
Manish Dewanganb9171e52011-03-15 15:18:18 +05301523module_init(audamrnb_in_init);
1524module_exit(audamrnb_in_exit);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001525
1526MODULE_DESCRIPTION("MSM AMRNB Encoder driver");
1527MODULE_LICENSE("GPL v2");