blob: 4effc8e5971b9e3e76b7c6e7865a70bfc870a049 [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>
Mitchel Humpherys1da6ebe2012-09-06 10:15:56 -070040#include <linux/msm_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;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530117
118 /* configuration to use on next enable */
119 uint32_t samp_rate;
120 uint32_t channel_mode;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121 uint32_t buffer_size;
122 uint32_t enc_type; /* 0 for WAV ,1 for AAC,10 for AMRNB */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530123 uint32_t mode; /* T or NT Mode*/
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124 struct msm_audio_amrnb_enc_config amrnb_enc_cfg;
125
126 uint32_t dsp_cnt;
127 uint32_t in_head; /* next buffer dsp will write */
128 uint32_t in_tail; /* next buffer read() will read */
129 uint32_t in_count; /* number of buffers available to read() */
130
Manish Dewanganb9171e52011-03-15 15:18:18 +0530131 uint32_t eos_ack;
132 uint32_t flush_ack;
133
134 const char *module_name;
135 unsigned queue_ids;
136 uint16_t enc_id; /* Session Id */
137
138 unsigned short samp_rate_index;
139 uint32_t audrec_obj_idx ;
140
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 struct audmgr audmgr;
142
143 /* data allocated for various buffers */
144 char *data;
145 dma_addr_t phys;
Laura Abbott35111d32012-04-27 18:41:48 -0700146 void *map_v_write;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700147
Manish Dewanganb9171e52011-03-15 15:18:18 +0530148 uint8_t opened;
149 uint8_t enabled;
150 uint8_t running;
151 uint8_t stopped; /* set when stopped, cleared on flush */
Sidipotu Ashok172c98b2012-06-26 17:58:29 +0530152 struct ion_client *client;
153 struct ion_handle *input_buff_handle;
154
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530155 struct audrec_session_info session_info; /*audrec session info*/
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700156};
157
Manish Dewanganb9171e52011-03-15 15:18:18 +0530158struct audio_frame {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700159 uint16_t frame_count_lsw;
160 uint16_t frame_count_msw;
161 uint16_t frame_length;
162 uint16_t erased_pcm;
163 unsigned char raw_bitstream[];
Manish Dewanganb9171e52011-03-15 15:18:18 +0530164} __packed;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165
Manish Dewanganb9171e52011-03-15 15:18:18 +0530166struct audio_frame_nt {
167 uint16_t metadata_len;
168 uint16_t frame_count_lsw;
169 uint16_t frame_count_msw;
170 uint16_t frame_length;
171 uint16_t erased_pcm;
172 uint16_t reserved;
173 uint16_t time_stamp_dword_lsw;
174 uint16_t time_stamp_dword_msw;
175 uint16_t time_stamp_lsw;
176 uint16_t time_stamp_msw;
177 uint16_t nflag_lsw;
178 uint16_t nflag_msw;
179 unsigned char raw_bitstream[]; /* samples */
180} __packed;
181
182struct amrnb_encoded_meta_out {
183 uint16_t metadata_len;
184 uint16_t time_stamp_dword_lsw;
185 uint16_t time_stamp_dword_msw;
186 uint16_t time_stamp_lsw;
187 uint16_t time_stamp_msw;
188 uint16_t nflag_lsw;
189 uint16_t nflag_msw;
190};
191
192/* Audrec Queue command sent macro's */
193#define audio_send_queue_pre(audio, cmd, len) \
194 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
195
196#define audio_send_queue_recbs(audio, cmd, len) \
197 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
198 cmd, len)
199#define audio_send_queue_rec(audio, cmd, len) \
200 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
201 cmd, len)
202
203static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable);
204static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio);
205static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio);
206static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
207 uint32_t read_cnt);
208static void audamrnb_in_flush(struct audio_amrnb_in *audio);
209
210static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio);
211static int audpcm_config(struct audio_amrnb_in *audio);
212static void audamrnb_out_flush(struct audio_amrnb_in *audio);
213static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio);
214static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed);
215static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio);
216static void audamrnb_in_flush(struct audio_amrnb_in *audio);
217
218static unsigned convert_samp_index(unsigned index)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700219{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530220 switch (index) {
221 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
222 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
223 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
224 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
225 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
226 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
227 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
228 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
229 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
230 default: return 11025;
231 }
232}
233
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530234/* ------------------- dsp --------------------- */
235static void audpre_dsp_event(void *data, unsigned id, void *event_data)
236{
237
238 uint16_t *msg = event_data;
239
240 if (!msg)
241 return;
242
243 switch (id) {
244 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
245 MM_DBG("type %d, status_flag %d\n",\
246 msg[0], msg[1]);
247 break;
248 case AUDPREPROC_MSG_ERROR_MSG_ID:
249 MM_INFO("err_index %d\n", msg[0]);
250 break;
251 case ADSP_MESSAGE_ID:
252 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
253 break;
254 default:
255 MM_ERR("unknown event %d\n", id);
256 }
257}
Manish Dewanganb9171e52011-03-15 15:18:18 +0530258/* must be called with audio->lock held */
259static int audamrnb_in_enable(struct audio_amrnb_in *audio)
260{
261 struct audmgr_config cfg;
262 int32_t rc;
263
264 if (audio->enabled)
265 return 0;
266
267 cfg.tx_rate = audio->samp_rate;
268 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
269 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
270 cfg.codec = RPC_AUD_DEF_CODEC_AMR_NB;
271 cfg.snd_method = RPC_SND_METHOD_MIDI;
272
273 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
274 rc = audmgr_enable(&audio->audmgr, &cfg);
275 if (rc < 0)
276 return rc;
277
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530278 if (audpreproc_enable(audio->enc_id,
279 &audpre_dsp_event, audio)) {
280 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
Manish Dewanganb9171e52011-03-15 15:18:18 +0530281 audmgr_disable(&audio->audmgr);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530282 return -ENODEV;
283 }
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530284 /*update aurec session info in audpreproc layer*/
285 audio->session_info.session_id = audio->enc_id;
286 audio->session_info.sampling_freq =
287 convert_samp_index(audio->samp_rate);
288 audpreproc_update_audrec_info(&audio->session_info);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530289 }
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530290
Manish Dewanganb9171e52011-03-15 15:18:18 +0530291 if (msm_adsp_enable(audio->audrec)) {
292 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530293 audpreproc_disable(audio->enc_id, audio);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530294 audmgr_disable(&audio->audmgr);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530295 }
296 MM_ERR("msm_adsp_enable(audrec) failed\n");
297 return -ENODEV;
298 }
299
300 audio->enabled = 1;
301 audamrnb_in_dsp_enable(audio, 1);
302
303 return 0;
304}
305
306/* must be called with audio->lock held */
307static int audamrnb_in_disable(struct audio_amrnb_in *audio)
308{
309 if (audio->enabled) {
310 audio->enabled = 0;
311
312 audamrnb_in_dsp_enable(audio, 0);
313
314 wake_up(&audio->wait);
315 wait_event_interruptible_timeout(audio->wait_enable,
316 audio->running == 0, 1*HZ);
317 msm_adsp_disable(audio->audrec);
318 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Manish Dewanganda9c07e2012-07-09 15:36:52 +0530319 /*reset the sampling frequency information at
320 audpreproc layer*/
321 audio->session_info.sampling_freq = 0;
322 audpreproc_update_audrec_info(&audio->session_info);
323 audpreproc_disable(audio->enc_id, audio);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530324 audmgr_disable(&audio->audmgr);
325 }
326 }
327 return 0;
328}
329
Manish Dewanganb9171e52011-03-15 15:18:18 +0530330static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
331{
332 struct audio_frame *frame;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700333 uint32_t index;
334 unsigned long flags;
335 index = audio->in_head;
336
337 frame = (void *) (((char *)audio->in[index].data) -
338 sizeof(*frame));
339 spin_lock_irqsave(&audio->dsp_lock, flags);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530340
341 /* Send Complete Transcoded Data, not actual frame part */
342 audio->in[index].size = FRAME_SIZE - (sizeof(*frame));
343 /* statistics of read */
344 atomic_add(audio->in[index].size, &audio->in_bytes);
345 atomic_add(1, &audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700346
347 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
348
349 /* If overflow, move the tail index foward. */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530350 if (audio->in_head == audio->in_tail) {
351 MM_ERR("Error! not able to keep up the read\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530353 MM_ERR("in_count = %d\n", audio->in_count);
354 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355 audio->in_count++;
356
Manish Dewanganb9171e52011-03-15 15:18:18 +0530357 audamrnb_in_dsp_read_buffer(audio, audio->dsp_cnt++);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700358 spin_unlock_irqrestore(&audio->dsp_lock, flags);
359
360 wake_up(&audio->wait);
361}
362
Manish Dewanganb9171e52011-03-15 15:18:18 +0530363static void audamrnb_nt_in_get_dsp_frames(struct audio_amrnb_in *audio)
364{
365 struct audio_frame_nt *nt_frame;
366 uint32_t index;
367 unsigned long flags;
368
369 index = audio->in_head;
370 nt_frame = (void *) (((char *)audio->in[index].data) - \
371 sizeof(struct audio_frame_nt));
372 spin_lock_irqsave(&audio->dsp_lock, flags);
373 audio->in[index].size = nt_frame->frame_length;
374 /* statistics of read */
375 atomic_add(audio->in[index].size, &audio->in_bytes);
376 atomic_add(1, &audio->in_samples);
377
378 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
379
380 /* If overflow, move the tail index foward. */
381 if (audio->in_head == audio->in_tail)
382 MM_DBG("Error! not able to keep up the read\n");
383 else
384 audio->in_count++;
385
386 spin_unlock_irqrestore(&audio->dsp_lock, flags);
387 wake_up(&audio->wait);
388}
389
390static int audrec_pcm_buffer_ptr_refresh(struct audio_amrnb_in *audio,
391 unsigned idx, unsigned len)
392{
393 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
394
395 if (len == NT_FRAME_HEADER_SIZE)
396 len = len / 2;
397 else
398 len = (len + NT_FRAME_HEADER_SIZE) / 2;
399 MM_DBG("len = %d\n", len);
400 memset(&cmd, 0, sizeof(cmd));
401 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
402 cmd.num_buffers = 1;
403 if (cmd.num_buffers == 1) {
404 cmd.buf_address_length[0] = (audio->out[idx].addr &
405 0xffff0000) >> 16;
406 cmd.buf_address_length[1] = (audio->out[idx].addr &
407 0x0000ffff);
408 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
409 cmd.buf_address_length[3] = (len & 0x0000ffff);
410 }
411 audio->out_frame_cnt++;
412 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
413}
414
415static int audpcm_config(struct audio_amrnb_in *audio)
416{
417 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
418 MM_DBG("\n");
419 memset(&cmd, 0, sizeof(cmd));
420 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
421 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
422 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
423 cmd.sampling_freq = convert_samp_index(audio->samp_rate);
424 if (!audio->channel_mode)
425 cmd.channels = 1;
426 else
427 cmd.channels = 2;
428 cmd.frequency_of_intimation = 1;
429 cmd.max_number_of_buffers = OUT_FRAME_NUM;
430 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
431}
432
433
434static int audamrnb_in_routing_mode_config(struct audio_amrnb_in *audio)
435{
436 struct audrec_cmd_routing_mode cmd;
437
438 MM_DBG("\n");
439 memset(&cmd, 0, sizeof(cmd));
440 cmd.cmd_id = AUDREC_CMD_ROUTING_MODE;
441 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
442 cmd.routing_mode = 1;
443 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
444}
445
446static void audrec_dsp_event(void *data, unsigned id, size_t len,
447 void (*getevent)(void *ptr, size_t len))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448{
449 struct audio_amrnb_in *audio = data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530450 if (data)
451 audio = data;
452 else {
453 MM_ERR("invalid data for event %x\n", id);
454 return;
455 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700456
457 switch (id) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530458 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
459 struct audrec_msg_cmd_cfg_done_msg cmd_cfg_done_msg;
460 getevent(&cmd_cfg_done_msg, AUDREC_MSG_CMD_CFG_DONE_MSG_LEN);
461 if (cmd_cfg_done_msg.audrec_enc_type & \
462 AUDREC_MSG_CFG_DONE_ENC_ENA) {
463 audio->audrec_obj_idx = cmd_cfg_done_msg.audrec_obj_idx;
464 MM_DBG("CFG ENABLED\n");
465 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
466 MM_DBG("routing command\n");
467 audamrnb_in_routing_mode_config(audio);
468 } else {
469 audamrnb_in_encmem_config(audio);
470 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 } else {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530472 MM_DBG("CFG SLEEP\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700473 audio->running = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530474 wake_up(&audio->wait_enable);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475 }
476 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530477 }
478 case AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG: {
479 struct audrec_msg_cmd_routing_mode_done_msg \
480 routing_msg;
481 getevent(&routing_msg, AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG);
482 MM_DBG("AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG");
483 if (routing_msg.configuration == 0) {
484 MM_ERR("routing configuration failed\n");
485 audio->running = 0;
486 wake_up(&audio->wait_enable);
487 } else
488 audamrnb_in_encmem_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489 break;
490 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530491 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
492 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
493 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
494 audamrnb_in_encparam_config(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495 else
Manish Dewanganb9171e52011-03-15 15:18:18 +0530496 audpcm_config(audio);
497 break;
498 }
499
500 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
501 MM_DBG("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
502 audamrnb_in_encparam_config(audio);
503 break;
504 }
505 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
506 MM_DBG("AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG\n");
507 audio->running = 1;
508 wake_up(&audio->wait_enable);
509 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
510 audrec_pcm_send_data(audio, 1);
511 break;
512 }
513 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
514 MM_DBG("ptr_update recieved from DSP\n");
515 audrec_pcm_send_data(audio, 1);
516 break;
517 }
518 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
519 struct audrec_msg_no_ext_pkt_avail_msg err_msg;
520 getevent(&err_msg, AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG_LEN);
521 MM_DBG("NO_EXT_PKT_AVAILABLE_MSG %x\n",\
522 err_msg.audrec_err_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 break;
524 }
525 case AUDREC_MSG_PACKET_READY_MSG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530526 struct audrec_msg_packet_ready_msg pkt_ready_msg;
527
528 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
529 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
530 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
531 pkt_ready_msg.pkt_counter_msw, \
532 pkt_ready_msg.pkt_counter_lsw, \
533 pkt_ready_msg.pkt_read_cnt_msw, \
534 pkt_ready_msg.pkt_read_cnt_lsw);
535
536 audamrnb_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537 break;
538 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530539 case AUDREC_UP_NT_PACKET_READY_MSG: {
540 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
541
542 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
543 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
544 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
545 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
546 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
547 pkt_ready_msg.audrec_upprev_readcount_lsw, \
548 pkt_ready_msg.audrec_upprev_readcount_msw);
549
550 audamrnb_nt_in_get_dsp_frames(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700551 break;
552 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530553 case AUDREC_CMD_FLUSH_DONE_MSG: {
554 audio->wflush = 0;
555 audio->rflush = 0;
556 audio->flush_ack = 1;
557 wake_up(&audio->write_wait);
558 MM_DBG("flush ack recieved\n");
559 break;
560 }
561 case ADSP_MESSAGE_ID:
562 MM_DBG("Received ADSP event: module \
563 enable/disable(audrectask)\n");
564 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565 default:
566 MM_ERR("unknown event %d\n", id);
567 }
568}
569
Manish Dewanganb9171e52011-03-15 15:18:18 +0530570struct msm_adsp_ops audrec_amrnb_adsp_ops = {
571 .event = audrec_dsp_event,
572};
573
574static int audamrnb_in_dsp_enable(struct audio_amrnb_in *audio, int enable)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575{
576 struct audrec_cmd_enc_cfg cmd;
577
578 memset(&cmd, 0, sizeof(cmd));
579 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530580 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
582 /* Don't care on enable, required on disable */
583 cmd.audrec_obj_idx = audio->audrec_obj_idx;
584
Manish Dewanganb9171e52011-03-15 15:18:18 +0530585 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700586}
587
Manish Dewanganb9171e52011-03-15 15:18:18 +0530588static int audamrnb_in_encmem_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700589{
590 struct audrec_cmd_arecmem_cfg cmd;
591 uint16_t *data = (void *) audio->data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530592 uint8_t n;
593 uint16_t header_len = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700594
595 memset(&cmd, 0, sizeof(cmd));
596
597 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
598 cmd.audrec_obj_idx = audio->audrec_obj_idx;
599 /* Rate at which packet complete message comes */
600 cmd.audrec_up_pkt_intm_cnt = 1;
601 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
602 cmd.audrec_extpkt_buffer_lsw = audio->phys;
603 /* Max Buffer no available for frames */
604 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
605
606 /* prepare buffer pointers:
Manish Dewanganb9171e52011-03-15 15:18:18 +0530607 * T:36 bytes amrnb packet + 4 halfword header
608 * NT:36 bytes amrnb packet + 12 halfword header
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609 */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530610 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
611 header_len = FRAME_HEADER_SIZE/2;
612 else
613 header_len = NT_FRAME_HEADER_SIZE/2;
614
615 for (n = 0; n < FRAME_NUM; n++) {
616 audio->in[n].data = data + header_len;
617 data += (AMRNB_FRAME_SIZE/2) + header_len;
618 MM_DBG("0x%8x\n", (uint32_t)(audio->in[n].data - header_len*2));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 }
620
Manish Dewanganb9171e52011-03-15 15:18:18 +0530621 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622}
623
Manish Dewanganb9171e52011-03-15 15:18:18 +0530624static int audamrnb_in_encparam_config(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625{
626 struct audrec_cmd_arecparam_amrnb_cfg cmd;
627
628 memset(&cmd, 0, sizeof(cmd));
629
630 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
631 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530632 cmd.samp_rate_idx = audio->samp_rate_index; /* 8k Sampling rate */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700633 cmd.voicememoencweight1 = audio->amrnb_enc_cfg.voicememoencweight1;
634 cmd.voicememoencweight2 = audio->amrnb_enc_cfg.voicememoencweight2;
635 cmd.voicememoencweight3 = audio->amrnb_enc_cfg.voicememoencweight3;
636 cmd.voicememoencweight4 = audio->amrnb_enc_cfg.voicememoencweight4;
637 cmd.update_mode = 0x8000 | 0x0000;
638 cmd.dtx_mode = audio->amrnb_enc_cfg.dtx_mode_enable;
639 cmd.test_mode = audio->amrnb_enc_cfg.test_mode_enable;
640 cmd.used_mode = audio->amrnb_enc_cfg.enc_mode;
641
642 MM_DBG("cmd.common.cmd_id = 0x%4x\n", cmd.common.cmd_id);
643 MM_DBG("cmd.common.audrec_obj_idx = 0x%4x\n",
644 cmd.common.audrec_obj_idx);
645 MM_DBG("cmd.samp_rate_idx = 0x%4x\n", cmd.samp_rate_idx);
646 MM_DBG("cmd.voicememoencweight1 = 0x%4x\n",
647 cmd.voicememoencweight1);
648 MM_DBG("cmd.voicememoencweight2 = 0x%4x\n",
649 cmd.voicememoencweight2);
650 MM_DBG("cmd.voicememoencweight3 = 0x%4x\n",
651 cmd.voicememoencweight3);
652 MM_DBG("cmd.voicememoencweight4 = 0x%4x\n",
653 cmd.voicememoencweight4);
654 MM_DBG("cmd.update_mode = 0x%4x\n", cmd.update_mode);
655 MM_DBG("cmd.dtx_mode = 0x%4x\n", cmd.dtx_mode);
656 MM_DBG("cmd.test_mode = 0x%4x\n", cmd.test_mode);
657 MM_DBG("cmd.used_mode = 0x%4x\n", cmd.used_mode);
658
Manish Dewanganb9171e52011-03-15 15:18:18 +0530659 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660}
661
Manish Dewanganb9171e52011-03-15 15:18:18 +0530662static int audamrnb_flush_command(struct audio_amrnb_in *audio)
663{
664 struct audrec_cmd_flush cmd;
665 MM_DBG("\n");
666 memset(&cmd, 0, sizeof(cmd));
667 cmd.cmd_id = AUDREC_CMD_FLUSH;
668 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
669}
670static int audamrnb_in_dsp_read_buffer(struct audio_amrnb_in *audio,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700671 uint32_t read_cnt)
672{
673 audrec_cmd_packet_ext_ptr cmd;
674
675 memset(&cmd, 0, sizeof(cmd));
676 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
677 cmd.type = audio->audrec_obj_idx;
678 cmd.curr_rec_count_msw = read_cnt >> 16;
679 cmd.curr_rec_count_lsw = read_cnt;
680
Manish Dewanganb9171e52011-03-15 15:18:18 +0530681 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700682}
683
Manish Dewanganb9171e52011-03-15 15:18:18 +0530684/* ------------------- device --------------------- */
685
686static void audamrnb_ioport_reset(struct audio_amrnb_in *audio)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700687{
Manish Dewanganb9171e52011-03-15 15:18:18 +0530688 /* Make sure read/write thread are free from
689 * sleep and knowing that system is not able
690 * to process io request at the moment
691 */
692 wake_up(&audio->write_wait);
693 mutex_lock(&audio->write_lock);
694 audamrnb_in_flush(audio);
695 mutex_unlock(&audio->write_lock);
696 wake_up(&audio->wait);
697 mutex_lock(&audio->read_lock);
698 audamrnb_out_flush(audio);
699 mutex_unlock(&audio->read_lock);
700}
701
702static void audamrnb_in_flush(struct audio_amrnb_in *audio)
703{
704 uint8_t i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705
706 audio->dsp_cnt = 0;
707 audio->in_head = 0;
708 audio->in_tail = 0;
709 audio->in_count = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530710 audio->eos_ack = 0;
711 for (i = FRAME_NUM-1; i >= 0; i--) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 audio->in[i].size = 0;
713 audio->in[i].read = 0;
714 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530715 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
716 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
717 atomic_set(&audio->in_bytes, 0);
718 atomic_set(&audio->in_samples, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719}
720
Manish Dewanganb9171e52011-03-15 15:18:18 +0530721static void audamrnb_out_flush(struct audio_amrnb_in *audio)
722{
723 uint8_t i;
724
725 audio->out_head = 0;
726 audio->out_tail = 0;
727 audio->out_count = 0;
728 for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
729 audio->out[i].size = 0;
730 audio->out[i].read = 0;
731 audio->out[i].used = 0;
732 }
733}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700734
735/* ------------------- device --------------------- */
Manish Dewanganb9171e52011-03-15 15:18:18 +0530736static long audamrnb_in_ioctl(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737 unsigned int cmd, unsigned long arg)
738{
739 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530740 int32_t rc = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741
Manish Dewanganb9171e52011-03-15 15:18:18 +0530742 MM_DBG("\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700743 if (cmd == AUDIO_GET_STATS) {
744 struct msm_audio_stats stats;
745 stats.byte_count = atomic_read(&audio->in_bytes);
Manish Dewanganb9171e52011-03-15 15:18:18 +0530746 stats.sample_count = atomic_read(&audio->in_samples);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700747 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
748 return -EFAULT;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530749 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750 }
751
752 mutex_lock(&audio->lock);
753 switch (cmd) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530754 case AUDIO_START: {
755 rc = audamrnb_in_enable(audio);
756 if (!rc) {
757 rc =
758 wait_event_interruptible_timeout(audio->wait_enable,
759 audio->running != 0, 1*HZ);
760 MM_INFO("state %d rc = %d\n", audio->running, rc);
761
762 if (audio->running == 0)
763 rc = -ENODEV;
764 else
765 rc = 0;
766 }
767 audio->stopped = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700768 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530769 }
770 case AUDIO_STOP: {
771 rc = audamrnb_in_disable(audio);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 audio->stopped = 1;
773 break;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530774 }
775 case AUDIO_FLUSH: {
776 MM_DBG("AUDIO_FLUSH\n");
777 audio->rflush = 1;
778 audio->wflush = 1;
779 audamrnb_ioport_reset(audio);
780 if (audio->running) {
781 audamrnb_flush_command(audio);
782 rc = wait_event_interruptible(audio->write_wait,
783 !audio->wflush);
784 if (rc < 0) {
785 MM_ERR("AUDIO_FLUSH interrupted\n");
786 rc = -EINTR;
787 }
788 } else {
789 audio->rflush = 0;
790 audio->wflush = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700792 break;
793 }
794 case AUDIO_GET_CONFIG: {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530795 struct msm_audio_config cfg;
796 memset(&cfg, 0, sizeof(cfg));
797 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
798 cfg.buffer_size = OUT_BUFFER_SIZE;
799 cfg.buffer_count = OUT_FRAME_NUM;
800 } else {
801 cfg.buffer_size = audio->buffer_size;
802 cfg.buffer_count = FRAME_NUM;
803 }
804 cfg.sample_rate = convert_samp_index(audio->samp_rate);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 cfg.channel_count = 1;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530806 cfg.type = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807 cfg.unused[0] = 0;
808 cfg.unused[1] = 0;
809 cfg.unused[2] = 0;
810 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
811 rc = -EFAULT;
812 else
813 rc = 0;
814 break;
815 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530816 case AUDIO_GET_STREAM_CONFIG: {
817 struct msm_audio_stream_config cfg;
818 memset(&cfg, 0, sizeof(cfg));
819 cfg.buffer_size = audio->buffer_size;
820 cfg.buffer_count = FRAME_NUM;
821 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
822 rc = -EFAULT;
823 else
824 rc = 0;
825 break;
826 }
827 case AUDIO_SET_STREAM_CONFIG: {
828 struct msm_audio_stream_config cfg;
829 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
830 rc = -EFAULT;
831 break;
832 }
833 /* Allow only single frame */
834 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530835 if (cfg.buffer_size != (FRAME_SIZE - 8)) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530836 rc = -EINVAL;
837 break;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530838 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530839 } else {
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530840 if (cfg.buffer_size != (AMRNB_FRAME_SIZE + 14)) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530841 rc = -EINVAL;
842 break;
Phani Kumar Alladaee940eb2012-05-10 11:13:04 +0530843 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530844 }
845 audio->buffer_size = cfg.buffer_size;
846 break;
847 }
848
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849 case AUDIO_GET_AMRNB_ENC_CONFIG: {
850 if (copy_to_user((void *)arg, &audio->amrnb_enc_cfg,
851 sizeof(audio->amrnb_enc_cfg)))
852 rc = -EFAULT;
853 else
854 rc = 0;
855 break;
856 }
857 case AUDIO_SET_AMRNB_ENC_CONFIG: {
858 struct msm_audio_amrnb_enc_config cfg;
859 if (copy_from_user
860 (&cfg, (void *)arg, sizeof(cfg))) {
861 rc = -EFAULT;
862 } else
863 rc = 0;
864 audio->amrnb_enc_cfg.voicememoencweight1 =
865 cfg.voicememoencweight1;
866 audio->amrnb_enc_cfg.voicememoencweight2 =
867 cfg.voicememoencweight2;
868 audio->amrnb_enc_cfg.voicememoencweight3 =
869 cfg.voicememoencweight3;
870 audio->amrnb_enc_cfg.voicememoencweight4 =
871 cfg.voicememoencweight4;
872 audio->amrnb_enc_cfg.dtx_mode_enable = cfg.dtx_mode_enable;
873 audio->amrnb_enc_cfg.test_mode_enable = cfg.test_mode_enable;
874 audio->amrnb_enc_cfg.enc_mode = cfg.enc_mode;
875 /* Run time change of Param */
876 break;
877 }
878 default:
879 rc = -EINVAL;
880 }
881 mutex_unlock(&audio->lock);
882 return rc;
883}
884
Manish Dewanganb9171e52011-03-15 15:18:18 +0530885static ssize_t audamrnb_in_read(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886 char __user *buf,
887 size_t count, loff_t *pos)
888{
889 struct audio_amrnb_in *audio = file->private_data;
890 unsigned long flags;
891 const char __user *start = buf;
892 void *data;
893 uint32_t index;
894 uint32_t size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530895 int32_t rc = 0;
896 struct amrnb_encoded_meta_out meta_field;
897 struct audio_frame_nt *nt_frame;
898 MM_DBG("count = %d\n", count);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899 mutex_lock(&audio->read_lock);
900 while (count > 0) {
901 rc = wait_event_interruptible(
Manish Dewanganb9171e52011-03-15 15:18:18 +0530902 audio->wait, (audio->in_count > 0) || audio->stopped ||
903 audio->rflush);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904 if (rc < 0)
905 break;
906
Manish Dewanganb9171e52011-03-15 15:18:18 +0530907 if (audio->rflush) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908 rc = -EBUSY;
909 break;
910 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530911 if (audio->stopped && !audio->in_count) {
912 MM_DBG("Driver in stop state, No more buffer to read");
913 rc = 0;/* End of File */
914 break;
915 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700916
917 index = audio->in_tail;
918 data = (uint8_t *) audio->in[index].data;
919 size = audio->in[index].size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530920
921 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
922 nt_frame = (struct audio_frame_nt *)(data -
923 sizeof(struct audio_frame_nt));
924 memcpy((char *)&meta_field.time_stamp_dword_lsw,
925 (char *)&nt_frame->time_stamp_dword_lsw,
926 (sizeof(struct amrnb_encoded_meta_out) - \
927 sizeof(uint16_t)));
928 meta_field.metadata_len =
929 sizeof(struct amrnb_encoded_meta_out);
930 if (copy_to_user((char *)start, (char *)&meta_field,
931 sizeof(struct amrnb_encoded_meta_out))) {
932 rc = -EFAULT;
933 break;
934 }
935 if (nt_frame->nflag_lsw & 0x0001) {
936 MM_ERR("recieved EOS in read call\n");
937 audio->eos_ack = 1;
938 }
939 buf += sizeof(struct amrnb_encoded_meta_out);
940 count -= sizeof(struct amrnb_encoded_meta_out);
941 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700942 if (count >= size) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530943 /* order the reads on the buffer */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700944 dma_coherent_post_ops();
945 if (copy_to_user(buf, data, size)) {
946 rc = -EFAULT;
947 break;
948 }
949 spin_lock_irqsave(&audio->dsp_lock, flags);
950 if (index != audio->in_tail) {
Manish Dewanganb9171e52011-03-15 15:18:18 +0530951 /* overrun -- data is
952 * invalid and we need to retry */
953 spin_unlock_irqrestore(&audio->dsp_lock, flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700954 continue;
955 }
956 audio->in[index].size = 0;
957 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
958 audio->in_count--;
959 spin_unlock_irqrestore(&audio->dsp_lock, flags);
960 count -= size;
961 buf += size;
Manish Dewanganb9171e52011-03-15 15:18:18 +0530962 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
963 if (!audio->eos_ack) {
964 MM_DBG("sending read ptr command \
965 %d %d\n",
966 audio->dsp_cnt,
967 audio->in_tail);
968 audamrnb_in_dsp_read_buffer(audio,
969 audio->dsp_cnt++);
970 }
971 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700972 } else {
973 MM_ERR("short read\n");
974 break;
975 }
Manish Dewanganb9171e52011-03-15 15:18:18 +0530976
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700977 }
978 mutex_unlock(&audio->read_lock);
979
980 if (buf > start)
981 return buf - start;
982
983 return rc;
984}
985
Manish Dewanganb9171e52011-03-15 15:18:18 +0530986static void audrec_pcm_send_data(struct audio_amrnb_in *audio, unsigned needed)
987{
988 struct buffer *frame;
989 unsigned long flags;
990 MM_DBG("\n");
991 spin_lock_irqsave(&audio->dsp_lock, flags);
992 if (!audio->running)
993 goto done;
994
995 if (needed && !audio->wflush) {
996 /* We were called from the callback because the DSP
997 * requested more data. Note that the DSP does want
998 * more data, and if a buffer was in-flight, mark it
999 * as available (since the DSP must now be done with
1000 * it).
1001 */
1002 audio->out_needed = 1;
1003 frame = audio->out + audio->out_tail;
1004 if (frame->used == 0xffffffff) {
1005 MM_DBG("frame %d free\n", audio->out_tail);
1006 frame->used = 0;
1007 audio->out_tail ^= 1;
1008 wake_up(&audio->write_wait);
1009 }
1010 }
1011
1012 if (audio->out_needed) {
1013 /* If the DSP currently wants data and we have a
1014 * buffer available, we will send it and reset
1015 * the needed flag. We'll mark the buffer as in-flight
1016 * so that it won't be recycled until the next buffer
1017 * is requested
1018 */
1019
1020 frame = audio->out + audio->out_tail;
1021 if (frame->used) {
1022 BUG_ON(frame->used == 0xffffffff);
1023 audrec_pcm_buffer_ptr_refresh(audio,
1024 audio->out_tail,
1025 frame->used);
1026 frame->used = 0xffffffff;
1027 audio->out_needed = 0;
1028 }
1029 }
1030 done:
1031 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1032}
1033
Steve Mucklef132c6c2012-06-06 18:30:57 -07001034static int audamrnb_in_fsync(struct file *file, loff_t a, loff_t b, int datasync)
Manish Dewanganb9171e52011-03-15 15:18:18 +05301035
1036{
1037 struct audio_amrnb_in *audio = file->private_data;
1038 int32_t rc = 0;
1039
1040 MM_DBG("\n"); /* Macro prints the file name and function */
1041 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1042 rc = -EINVAL;
1043 goto done_nolock;
1044 }
1045
1046 mutex_lock(&audio->write_lock);
1047
1048 rc = wait_event_interruptible(audio->write_wait,
1049 audio->wflush);
1050 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1051
1052 if (rc < 0)
1053 goto done;
1054 else if (audio->wflush) {
1055 rc = -EBUSY;
1056 goto done;
1057 }
1058done:
1059 mutex_unlock(&audio->write_lock);
1060done_nolock:
1061 return rc;
1062
1063}
1064
1065int audrec_amrnb_process_eos(struct audio_amrnb_in *audio,
1066 const char __user *buf_start, unsigned short mfield_size)
1067{
1068 struct buffer *frame;
1069 int32_t rc = 0;
1070
1071 frame = audio->out + audio->out_head;
1072
1073 rc = wait_event_interruptible(audio->write_wait,
1074 (audio->out_needed &&
1075 audio->out[0].used == 0 &&
1076 audio->out[1].used == 0)
1077 || (audio->stopped)
1078 || (audio->wflush));
1079
1080 if (rc < 0)
1081 goto done;
1082 if (audio->stopped || audio->wflush) {
1083 rc = -EBUSY;
1084 goto done;
1085 }
1086 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1087 rc = -EFAULT;
1088 goto done;
1089 }
1090
1091 frame->mfield_sz = mfield_size;
1092 audio->out_head ^= 1;
1093 frame->used = mfield_size;
1094 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1095 audrec_pcm_send_data(audio, 0);
1096done:
1097 return rc;
1098}
1099
1100static ssize_t audamrnb_in_write(struct file *file,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001101 const char __user *buf,
1102 size_t count, loff_t *pos)
1103{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301104 struct audio_amrnb_in *audio = file->private_data;
1105 const char __user *start = buf;
1106 struct buffer *frame;
1107 char *cpy_ptr;
1108 int32_t rc = 0, eos_condition = AUDPREPROC_AMRNB_EOS_NONE;
1109 unsigned short mfield_size = 0;
1110 int32_t write_count = 0;
1111 MM_DBG("cnt=%d\n", count);
1112
1113 if (count & 1)
1114 return -EINVAL;
1115
1116 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1117 return -EINVAL;
1118
1119 mutex_lock(&audio->write_lock);
1120 frame = audio->out + audio->out_head;
1121 /* if supplied count is more than driver buffer size
1122 * then only copy driver buffer size
1123 */
1124 if (count > frame->size)
1125 count = frame->size;
1126
1127 write_count = count;
1128 cpy_ptr = frame->data;
1129 rc = wait_event_interruptible(audio->write_wait,
1130 (frame->used == 0)
1131 || (audio->stopped)
1132 || (audio->wflush));
1133 if (rc < 0)
1134 goto error;
1135
1136 if (audio->stopped || audio->wflush) {
1137 rc = -EBUSY;
1138 goto error;
1139 }
1140 if (audio->mfield) {
1141 if (buf == start) {
1142 /* Processing beginning of user buffer */
1143 if (__get_user(mfield_size,
1144 (unsigned short __user *) buf)) {
1145 rc = -EFAULT;
1146 goto error;
1147 } else if (mfield_size > count) {
1148 rc = -EINVAL;
1149 goto error;
1150 }
1151 MM_DBG("mf offset_val %x\n", mfield_size);
1152 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1153 rc = -EFAULT;
1154 goto error;
1155 }
1156 /* Check if EOS flag is set and buffer has
1157 * contains just meta field
1158 */
1159 if (cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &
1160 AUDPREPROC_AMRNB_EOS_FLG_MASK) {
1161 eos_condition = AUDPREPROC_AMRNB_EOS_SET;
1162 MM_DBG("EOS SET\n");
1163 if (mfield_size == count) {
1164 buf += mfield_size;
1165 eos_condition = 0;
1166 goto exit;
1167 } else
1168 cpy_ptr[AUDPREPROC_AMRNB_EOS_FLG_OFFSET] &=
1169 ~AUDPREPROC_AMRNB_EOS_FLG_MASK;
1170 }
1171 cpy_ptr += mfield_size;
1172 count -= mfield_size;
1173 buf += mfield_size;
1174 } else {
1175 mfield_size = 0;
1176 MM_DBG("continuous buffer\n");
1177 }
1178 frame->mfield_sz = mfield_size;
1179 }
1180 MM_DBG("copying the stream count = %d\n", count);
1181 if (copy_from_user(cpy_ptr, buf, count)) {
1182 rc = -EFAULT;
1183 goto error;
1184 }
1185exit:
1186 frame->used = count;
1187 audio->out_head ^= 1;
1188 if (!audio->flush_ack)
1189 audrec_pcm_send_data(audio, 0);
1190 else {
1191 audrec_pcm_send_data(audio, 1);
1192 audio->flush_ack = 0;
1193 }
1194 if (eos_condition == AUDPREPROC_AMRNB_EOS_SET)
1195 rc = audrec_amrnb_process_eos(audio, start, mfield_size);
1196 mutex_unlock(&audio->write_lock);
1197 return write_count;
1198error:
1199 mutex_unlock(&audio->write_lock);
1200 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001201}
1202
Manish Dewanganb9171e52011-03-15 15:18:18 +05301203static int audamrnb_in_release(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001204{
1205 struct audio_amrnb_in *audio = file->private_data;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301206 int32_t dma_size = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001207 mutex_lock(&audio->lock);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301208 audamrnb_in_disable(audio);
1209 audamrnb_in_flush(audio);
1210 msm_adsp_put(audio->audrec);
1211
Manish Dewanganb9171e52011-03-15 15:18:18 +05301212 audpreproc_aenc_free(audio->enc_id);
1213 audio->audrec = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001214 audio->opened = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301215 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
1216 (audio->out_data)) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301217 ion_unmap_kernel(audio->client, audio->input_buff_handle);
1218 ion_free(audio->client, audio->input_buff_handle);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301219 audio->out_data = NULL;
1220 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001221 if (audio->data) {
Manish Dewanganb9171e52011-03-15 15:18:18 +05301222 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1223 dma_size = DMASZ;
1224 else
1225 dma_size = NT_DMASZ;
1226
1227 dma_free_coherent(NULL,
1228 dma_size, audio->data, audio->phys);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001229 audio->data = NULL;
1230 }
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301231 ion_client_destroy(audio->client);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001232 mutex_unlock(&audio->lock);
1233 return 0;
1234}
1235
Manish Dewanganb9171e52011-03-15 15:18:18 +05301236struct audio_amrnb_in the_audio_amrnb_in;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001237
Manish Dewanganb9171e52011-03-15 15:18:18 +05301238static int audamrnb_in_open(struct inode *inode, struct file *file)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001239{
1240 struct audio_amrnb_in *audio = &the_audio_amrnb_in;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301241 int32_t rc;
1242 int encid;
1243 int32_t dma_size = 0;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301244 int len = 0;
1245 unsigned long ionflag = 0;
1246 ion_phys_addr_t addr = 0;
1247 struct ion_handle *handle = NULL;
1248 struct ion_client *client = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001249
1250 mutex_lock(&audio->lock);
1251 if (audio->opened) {
1252 rc = -EBUSY;
1253 goto done;
1254 }
Manish Dewanganb9171e52011-03-15 15:18:18 +05301255 if ((file->f_mode & FMODE_WRITE) &&
1256 (file->f_mode & FMODE_READ)) {
1257 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1258 dma_size = NT_DMASZ;
1259 MM_DBG("Opened for non tunnel mode encoding\n");
1260 } else if (!(file->f_mode & FMODE_WRITE) &&
1261 (file->f_mode & FMODE_READ)) {
1262 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1263 dma_size = DMASZ;
1264 MM_DBG("Opened for tunnel mode encoding\n");
1265 } else {
1266 MM_ERR("Invalid mode\n");
1267 rc = -EACCES;
1268 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001269 }
1270
Manish Dewanganb9171e52011-03-15 15:18:18 +05301271 /* Settings will be re-config at AUDIO_SET_CONFIG,
1272 * but at least we need to have initial config
1273 */
1274 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_8000,
1275 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_8000;
1276 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
1277 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1278 audio->buffer_size = (AMRNB_FRAME_SIZE + 14);
1279 else
1280 audio->buffer_size = (FRAME_SIZE - 8);
1281 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_AMRNB | audio->mode;
1282
1283 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1284 rc = audmgr_open(&audio->audmgr);
1285 if (rc)
1286 goto done;
1287 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001288 audio->amrnb_enc_cfg.voicememoencweight1 = 0x0000;
1289 audio->amrnb_enc_cfg.voicememoencweight2 = 0x0000;
1290 audio->amrnb_enc_cfg.voicememoencweight3 = 0x4000;
1291 audio->amrnb_enc_cfg.voicememoencweight4 = 0x0000;
1292 audio->amrnb_enc_cfg.dtx_mode_enable = 0;
1293 audio->amrnb_enc_cfg.test_mode_enable = 0;
1294 audio->amrnb_enc_cfg.enc_mode = 7;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301295
1296 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1297 &audio->queue_ids);
1298 if (encid < 0) {
1299 MM_ERR("No free encoder available\n");
1300 rc = -ENODEV;
1301 goto done;
1302 }
1303 audio->enc_id = encid;
1304 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1305 &audrec_amrnb_adsp_ops, audio);
1306 if (rc) {
1307 audpreproc_aenc_free(audio->enc_id);
1308 goto done;
1309 }
1310
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001311 audio->dsp_cnt = 0;
1312 audio->stopped = 0;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301313 audio->wflush = 0;
1314 audio->rflush = 0;
1315 audio->flush_ack = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001316
Manish Dewanganb9171e52011-03-15 15:18:18 +05301317 audamrnb_in_flush(audio);
1318 audamrnb_out_flush(audio);
1319 /* used dma_allco_coherent for backward compatibility with 7x27 */
1320 audio->data = dma_alloc_coherent(NULL, dma_size,
1321 &audio->phys, GFP_KERNEL);
1322 if (!audio->data) {
1323 MM_ERR("Unable to allocate DMA buffer\n");
1324 goto evt_error;
1325 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001326
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301327 client = msm_ion_client_create(UINT_MAX, "Audio_AMRNB_in_client");
1328 if (IS_ERR_OR_NULL(client)) {
1329 MM_ERR("Unable to create ION client\n");
1330 rc = -ENOMEM;
1331 goto client_create_error;
1332 }
1333 audio->client = client;
1334
Manish Dewanganb9171e52011-03-15 15:18:18 +05301335 audio->out_data = NULL;
1336 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301337 MM_DBG("allocating BUFFER_SIZE %d\n", BUFFER_SIZE);
1338 handle = ion_alloc(client, BUFFER_SIZE,
1339 SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
1340 if (IS_ERR_OR_NULL(handle)) {
1341 MM_ERR("Unable to create allocate write buffers\n");
Manish Dewanganb9171e52011-03-15 15:18:18 +05301342 rc = -ENOMEM;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301343 goto input_buff_alloc_error;
Manish Dewanganb9171e52011-03-15 15:18:18 +05301344 }
1345
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301346 audio->input_buff_handle = handle;
1347
1348 rc = ion_phys(client , handle, &addr, &len);
1349 if (rc) {
1350 MM_ERR("I/P buffers:Invalid phy: %x sz: %x\n",
1351 (unsigned int) addr, (unsigned int) len);
1352 rc = -ENOMEM;
1353 goto input_buff_get_phys_error;
1354 } else {
1355 MM_INFO("Got valid phy: %x sz: %x\n",
1356 (unsigned int) addr,
1357 (unsigned int) len);
1358 }
1359 audio->out_phys = (int32_t)addr;
1360
1361 rc = ion_handle_get_flags(client,
1362 handle, &ionflag);
1363 if (rc) {
1364 MM_ERR("could not get flags for the handle\n");
1365 rc = -ENOMEM;
1366 goto input_buff_get_flags_error;
1367 }
1368
1369 audio->map_v_write = ion_map_kernel(client,
1370 handle, ionflag);
1371 if (IS_ERR(audio->map_v_write)) {
1372 MM_ERR("could not map write buffers\n");
1373 rc = -ENOMEM;
1374 goto input_buff_map_error;
1375 }
1376 audio->out_data = audio->map_v_write;
1377 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1378 (unsigned int)addr,
1379 (unsigned int)audio->out_data);
1380
Manish Dewanganb9171e52011-03-15 15:18:18 +05301381 /* Initialize buffer */
1382 audio->out[0].data = audio->out_data + 0;
1383 audio->out[0].addr = audio->out_phys + 0;
1384 audio->out[0].size = OUT_BUFFER_SIZE;
1385
1386 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1387 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1388 audio->out[1].size = OUT_BUFFER_SIZE;
1389
1390 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1391 (uint32_t)audio->out[0].data,
1392 (uint32_t)audio->out[1].data);
1393 audio->mfield = NT_FRAME_HEADER_SIZE;
1394 audio->out_frame_cnt++;
1395 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001396 file->private_data = audio;
1397 audio->opened = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001398
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001399done:
1400 mutex_unlock(&audio->lock);
1401 return rc;
Sidipotu Ashok172c98b2012-06-26 17:58:29 +05301402input_buff_map_error:
1403input_buff_get_phys_error:
1404input_buff_get_flags_error:
1405 ion_free(client, audio->input_buff_handle);
1406input_buff_alloc_error:
1407 ion_client_destroy(client);
1408client_create_error:
1409 dma_free_coherent(NULL, dma_size, audio->data, audio->phys);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301410evt_error:
1411 msm_adsp_put(audio->audrec);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301412
1413 audpreproc_aenc_free(audio->enc_id);
1414 mutex_unlock(&audio->lock);
1415 return rc;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416}
1417
1418static const struct file_operations audio_fops = {
1419 .owner = THIS_MODULE,
Manish Dewanganb9171e52011-03-15 15:18:18 +05301420 .open = audamrnb_in_open,
1421 .release = audamrnb_in_release,
1422 .read = audamrnb_in_read,
1423 .write = audamrnb_in_write,
1424 .fsync = audamrnb_in_fsync,
1425 .unlocked_ioctl = audamrnb_in_ioctl,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001426};
1427
Manish Dewanganb9171e52011-03-15 15:18:18 +05301428struct miscdevice audamrnb_in_misc = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001429 .minor = MISC_DYNAMIC_MINOR,
1430 .name = "msm_amrnb_in",
1431 .fops = &audio_fops,
1432};
1433
1434#ifdef CONFIG_DEBUG_FS
1435static ssize_t audamrnb_in_debug_open(struct inode *inode, struct file *file)
1436{
1437 file->private_data = inode->i_private;
1438 return 0;
1439}
1440
1441static ssize_t audamrnb_in_debug_read(struct file *file, char __user *buf,
1442 size_t count, loff_t *ppos)
1443{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301444 const int32_t debug_bufmax = 1024;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001445 static char buffer[1024];
Manish Dewanganb9171e52011-03-15 15:18:18 +05301446 int32_t n = 0, i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001447 struct audio_amrnb_in *audio = file->private_data;
1448
1449 mutex_lock(&audio->lock);
1450 n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
1451 n += scnprintf(buffer + n, debug_bufmax - n,
1452 "enabled %d\n", audio->enabled);
1453 n += scnprintf(buffer + n, debug_bufmax - n,
1454 "stopped %d\n", audio->stopped);
1455 n += scnprintf(buffer + n, debug_bufmax - n,
1456 "audrec_obj_idx %d\n", audio->audrec_obj_idx);
1457 n += scnprintf(buffer + n, debug_bufmax - n,
1458 "dsp_cnt %d \n", audio->dsp_cnt);
1459 n += scnprintf(buffer + n, debug_bufmax - n,
1460 "in_count %d \n", audio->in_count);
1461 for (i = 0; i < FRAME_NUM; i++)
1462 n += scnprintf(buffer + n, debug_bufmax - n,
1463 "audio->in[%d].size %d \n", i, audio->in[i].size);
1464 mutex_unlock(&audio->lock);
1465 /* Following variables are only useful for debugging when
1466 * when record halts unexpectedly. Thus, no mutual exclusion
1467 * enforced
1468 */
1469 n += scnprintf(buffer + n, debug_bufmax - n,
1470 "running %d \n", audio->running);
1471 n += scnprintf(buffer + n, debug_bufmax - n,
1472 "buffer_size %d \n", audio->buffer_size);
1473 n += scnprintf(buffer + n, debug_bufmax - n,
1474 "in_head %d \n", audio->in_head);
1475 n += scnprintf(buffer + n, debug_bufmax - n,
1476 "in_tail %d \n", audio->in_tail);
1477 buffer[n] = 0;
1478 return simple_read_from_buffer(buf, count, ppos, buffer, n);
1479}
1480
1481static const struct file_operations audamrnb_in_debug_fops = {
1482 .read = audamrnb_in_debug_read,
1483 .open = audamrnb_in_debug_open,
1484};
1485#endif
1486
Manish Dewanganb9171e52011-03-15 15:18:18 +05301487static int __init audamrnb_in_init(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001488{
1489#ifdef CONFIG_DEBUG_FS
1490 struct dentry *dentry;
1491#endif
1492
1493 mutex_init(&the_audio_amrnb_in.lock);
1494 mutex_init(&the_audio_amrnb_in.read_lock);
1495 spin_lock_init(&the_audio_amrnb_in.dsp_lock);
1496 init_waitqueue_head(&the_audio_amrnb_in.wait);
Manish Dewanganb9171e52011-03-15 15:18:18 +05301497 init_waitqueue_head(&the_audio_amrnb_in.wait_enable);
1498 mutex_init(&the_audio_amrnb_in.write_lock);
1499 init_waitqueue_head(&the_audio_amrnb_in.write_wait);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001500
1501#ifdef CONFIG_DEBUG_FS
1502 dentry = debugfs_create_file("msm_amrnb_in", S_IFREG | S_IRUGO, NULL,
1503 (void *) &the_audio_amrnb_in, &audamrnb_in_debug_fops);
1504
1505 if (IS_ERR(dentry))
1506 MM_ERR("debugfs_create_file failed\n");
1507#endif
Manish Dewanganb9171e52011-03-15 15:18:18 +05301508 return misc_register(&audamrnb_in_misc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001509}
1510
Manish Dewanganb9171e52011-03-15 15:18:18 +05301511static void __exit audamrnb_in_exit(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001512{
Manish Dewanganb9171e52011-03-15 15:18:18 +05301513 misc_deregister(&audamrnb_in_misc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514}
1515
Manish Dewanganb9171e52011-03-15 15:18:18 +05301516module_init(audamrnb_in_init);
1517module_exit(audamrnb_in_exit);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001518
1519MODULE_DESCRIPTION("MSM AMRNB Encoder driver");
1520MODULE_LICENSE("GPL v2");