blob: 31edc835c47f71f2b9f030e8348d9311254ba9bc [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
2 *
3 * qcelp audio input device
4 *
5 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
6 *
7 * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c,
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. See the
18 * GNU General Public License for more details.
19 *
20 */
21
22#include <linux/module.h>
23#include <linux/fs.h>
24#include <linux/miscdevice.h>
25#include <linux/uaccess.h>
26#include <linux/kthread.h>
27#include <linux/wait.h>
28#include <linux/dma-mapping.h>
29
30#include <linux/delay.h>
31
32#include <linux/msm_audio_qcp.h>
33
34#include <mach/msm_memtypes.h>
35#include <linux/memory_alloc.h>
36
37#include <asm/atomic.h>
38#include <asm/ioctls.h>
39#include <mach/msm_adsp.h>
40#include <mach/msm_rpcrouter.h>
41
42#include "audmgr.h"
43
44#include <mach/qdsp5/qdsp5audpreproc.h>
45#include <mach/qdsp5/qdsp5audpreproccmdi.h>
46#include <mach/qdsp5/qdsp5audpreprocmsg.h>
47#include <mach/qdsp5/qdsp5audreccmdi.h>
48#include <mach/qdsp5/qdsp5audrecmsg.h>
49#include <mach/debug_mm.h>
50
51#define FRAME_HEADER_SIZE 8 /* 8 bytes frame header */
52#define NT_FRAME_HEADER_SIZE 24 /* 24 bytes frame header */
53/* FRAME_NUM must be a power of two */
54#define FRAME_NUM 8
55#define QCELP_FRAME_SIZE 36 /* 36 bytes data */
56/*Tunnel mode : 36 bytes data + 8 byte header*/
57#define FRAME_SIZE (QCELP_FRAME_SIZE + FRAME_HEADER_SIZE)
58 /* 36 bytes data + 24 meta field*/
59#define NT_FRAME_SIZE (QCELP_FRAME_SIZE + NT_FRAME_HEADER_SIZE)
60#define DMASZ (FRAME_SIZE * FRAME_NUM)
61#define NT_DMASZ (NT_FRAME_SIZE * FRAME_NUM)
62#define OUT_FRAME_NUM 2
63#define OUT_BUFFER_SIZE (4 * 1024 + NT_FRAME_HEADER_SIZE)
64#define BUFFER_SIZE (OUT_BUFFER_SIZE * OUT_FRAME_NUM)
65
66/* Offset from beginning of buffer*/
67#define AUDPREPROC_QCELP_EOS_FLG_OFFSET 0x0A
68#define AUDPREPROC_QCELP_EOS_FLG_MASK 0x01
69#define AUDPREPROC_QCELP_EOS_NONE 0x0 /* No EOS detected */
70#define AUDPREPROC_QCELP_EOS_SET 0x1 /* EOS set in meta field */
71
72struct buffer {
73 void *data;
74 uint32_t size;
75 uint32_t read;
76 uint32_t addr;
77 uint32_t used;
78 uint32_t mfield_sz;
79};
80
81struct audio_qcelp_in {
82 struct buffer in[FRAME_NUM];
83
84 spinlock_t dsp_lock;
85
86 atomic_t in_bytes;
87 atomic_t in_samples;
88
89 struct mutex lock;
90 struct mutex read_lock;
91 wait_queue_head_t wait;
92 wait_queue_head_t wait_enable;
93 /*write section*/
94 struct buffer out[OUT_FRAME_NUM];
95
96 uint8_t out_head;
97 uint8_t out_tail;
98 uint8_t out_needed; /* number of buffers the dsp is waiting for */
99 uint32_t out_count;
100
101 struct mutex write_lock;
102 wait_queue_head_t write_wait;
103 int32_t out_phys; /* physical address of write buffer */
104 char *out_data;
105 int mfield; /* meta field embedded in data */
106 int wflush; /*write flush */
107 int rflush; /*read flush*/
108 int out_frame_cnt;
109
110 struct msm_adsp_module *audrec;
111 struct msm_adsp_module *audpre;
112
113
114 /* configuration to use on next enable */
115 uint32_t samp_rate;
116 uint32_t channel_mode;
117 uint32_t buffer_size; /* Frame size (36 bytes) */
118 uint32_t enc_type; /* 11 for QCELP */
119 uint32_t mode; /* T or NT Mode*/
120
121 struct msm_audio_qcelp_enc_config cfg;
122
123 uint32_t dsp_cnt;
124 uint32_t in_head; /* next buffer dsp will write */
125 uint32_t in_tail; /* next buffer read() will read */
126 uint32_t in_count; /* number of buffers available to read() */
127
128 uint32_t eos_ack;
129 uint32_t flush_ack;
130
131 const char *module_name;
132 unsigned queue_ids;
133 uint16_t enc_id; /* Session Id */
134
135 unsigned short samp_rate_index;
136 uint32_t audrec_obj_idx ;
137
138 struct audmgr audmgr;
139
140 /* data allocated for various buffers */
141 char *data;
142 dma_addr_t phys;
143
144 int opened;
145 int enabled;
146 int running;
147 int stopped; /* set when stopped, cleared on flush */
148};
149
150struct audio_frame {
151 uint16_t frame_count_lsw;
152 uint16_t frame_count_msw;
153 uint16_t frame_length;
154 uint16_t erased_pcm;
155 unsigned char raw_bitstream[];
156} __packed;
157
158struct audio_frame_nt {
159 uint16_t metadata_len;
160 uint16_t frame_count_lsw;
161 uint16_t frame_count_msw;
162 uint16_t frame_length;
163 uint16_t erased_pcm;
164 uint16_t reserved;
165 uint16_t time_stamp_dword_lsw;
166 uint16_t time_stamp_dword_msw;
167 uint16_t time_stamp_lsw;
168 uint16_t time_stamp_msw;
169 uint16_t nflag_lsw;
170 uint16_t nflag_msw;
171 unsigned char raw_bitstream[]; /* samples */
172} __packed;
173
174struct qcelp_encoded_meta_out {
175 uint16_t metadata_len;
176 uint16_t time_stamp_dword_lsw;
177 uint16_t time_stamp_dword_msw;
178 uint16_t time_stamp_lsw;
179 uint16_t time_stamp_msw;
180 uint16_t nflag_lsw;
181 uint16_t nflag_msw;
182};
183
184/* Audrec Queue command sent macro's */
185#define audio_send_queue_pre(audio, cmd, len) \
186 msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
187
188#define audio_send_queue_recbs(audio, cmd, len) \
189 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
190 cmd, len)
191#define audio_send_queue_rec(audio, cmd, len) \
192 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
193 cmd, len)
194
195static int audqcelp_in_dsp_enable(struct audio_qcelp_in *audio, int enable);
196static int audqcelp_in_encparam_config(struct audio_qcelp_in *audio);
197static int audqcelp_in_encmem_config(struct audio_qcelp_in *audio);
198static int audqcelp_in_dsp_read_buffer(struct audio_qcelp_in *audio,
199 uint32_t read_cnt);
200static void audqcelp_in_flush(struct audio_qcelp_in *audio);
201
202static void audqcelp_in_get_dsp_frames(struct audio_qcelp_in *audio);
203static int audpcm_config(struct audio_qcelp_in *audio);
204static void audqcelp_out_flush(struct audio_qcelp_in *audio);
205static int audqcelp_in_routing_mode_config(struct audio_qcelp_in *audio);
206static void audrec_pcm_send_data(struct audio_qcelp_in *audio, unsigned needed);
207static void audqcelp_nt_in_get_dsp_frames(struct audio_qcelp_in *audio);
208static void audqcelp_in_flush(struct audio_qcelp_in *audio);
209
210static unsigned convert_samp_index(unsigned index)
211{
212 switch (index) {
213 case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
214 case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
215 case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
216 case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
217 case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
218 case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
219 case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
220 case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
221 case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
222 default: return 11025;
223 }
224}
225
226/* must be called with audio->lock held */
227static int audqcelp_in_enable(struct audio_qcelp_in *audio)
228{
229 struct audmgr_config cfg;
230 int rc;
231
232 if (audio->enabled)
233 return 0;
234
235 cfg.tx_rate = audio->samp_rate;
236 cfg.rx_rate = RPC_AUD_DEF_SAMPLE_RATE_NONE;
237 cfg.def_method = RPC_AUD_DEF_METHOD_RECORD;
238 cfg.codec = RPC_AUD_DEF_CODEC_13K;
239 cfg.snd_method = RPC_SND_METHOD_MIDI;
240
241 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
242 rc = audmgr_enable(&audio->audmgr, &cfg);
243 if (rc < 0)
244 return rc;
245
246 if (msm_adsp_enable(audio->audpre)) {
247 audmgr_disable(&audio->audmgr);
248 MM_ERR("msm_adsp_enable(audpre) failed\n");
249 return -ENODEV;
250 }
251 }
252 if (msm_adsp_enable(audio->audrec)) {
253 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
254 audmgr_disable(&audio->audmgr);
255 msm_adsp_disable(audio->audpre);
256 }
257 MM_ERR("msm_adsp_enable(audrec) failed\n");
258 return -ENODEV;
259 }
260
261 audio->enabled = 1;
262 audqcelp_in_dsp_enable(audio, 1);
263
264 return 0;
265}
266
267/* must be called with audio->lock held */
268static int audqcelp_in_disable(struct audio_qcelp_in *audio)
269{
270 if (audio->enabled) {
271 audio->enabled = 0;
272
273 audqcelp_in_dsp_enable(audio, 0);
274
275 wake_up(&audio->wait);
276 wait_event_interruptible_timeout(audio->wait_enable,
277 audio->running == 0, 1*HZ);
278 msm_adsp_disable(audio->audrec);
279 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
280 msm_adsp_disable(audio->audpre);
281 audmgr_disable(&audio->audmgr);
282 }
283 }
284 return 0;
285}
286
287/* ------------------- dsp --------------------- */
288static void audpre_dsp_event(void *data, unsigned id, size_t len,
289 void (*getevent)(void *ptr, size_t len))
290{
291 uint16_t msg[2];
292 getevent(msg, sizeof(msg));
293
294 switch (id) {
295 case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
296 MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
297 break;
298 case AUDPREPROC_MSG_ERROR_MSG_ID:
299 MM_ERR("err_index %d\n", msg[0]);
300 break;
301 case ADSP_MESSAGE_ID:
302 MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
303 break;
304 default:
305 MM_ERR("unknown event %d\n", id);
306 }
307}
308
309static void audqcelp_in_get_dsp_frames(struct audio_qcelp_in *audio)
310{
311 struct audio_frame *frame;
312 uint32_t index;
313 unsigned long flags;
314
315 index = audio->in_head;
316
317 frame = (void *) (((char *)audio->in[index].data) -
318 sizeof(*frame));
319 spin_lock_irqsave(&audio->dsp_lock, flags);
320 audio->in[index].size = frame->frame_length;
321
322 /* statistics of read */
323 atomic_add(audio->in[index].size, &audio->in_bytes);
324 atomic_add(1, &audio->in_samples);
325
326 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
327
328 /* If overflow, move the tail index foward. */
329 if (audio->in_head == audio->in_tail) {
330 MM_ERR("Error! not able to keep up the read\n");
331 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
332 MM_ERR("in_count = %d\n", audio->in_count);
333 } else
334 audio->in_count++;
335
336 audqcelp_in_dsp_read_buffer(audio, audio->dsp_cnt++);
337 spin_unlock_irqrestore(&audio->dsp_lock, flags);
338
339 wake_up(&audio->wait);
340}
341
342static void audqcelp_nt_in_get_dsp_frames(struct audio_qcelp_in *audio)
343{
344 struct audio_frame_nt *nt_frame;
345 uint32_t index;
346 unsigned long flags;
347
348 index = audio->in_head;
349 nt_frame = (void *) (((char *)audio->in[index].data) - \
350 sizeof(struct audio_frame_nt));
351 spin_lock_irqsave(&audio->dsp_lock, flags);
352 audio->in[index].size = nt_frame->frame_length;
353 /* statistics of read */
354 atomic_add(audio->in[index].size, &audio->in_bytes);
355 atomic_add(1, &audio->in_samples);
356
357 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
358
359 /* If overflow, move the tail index foward. */
360 if (audio->in_head == audio->in_tail)
361 MM_DBG("Error! not able to keep up the read\n");
362 else
363 audio->in_count++;
364
365 spin_unlock_irqrestore(&audio->dsp_lock, flags);
366 wake_up(&audio->wait);
367}
368
369static int audrec_pcm_buffer_ptr_refresh(struct audio_qcelp_in *audio,
370 unsigned idx, unsigned len)
371{
372 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
373
374 if (len == NT_FRAME_HEADER_SIZE)
375 len = len / 2;
376 else
377 len = (len + NT_FRAME_HEADER_SIZE) / 2;
378 MM_DBG("len = %d\n", len);
379 memset(&cmd, 0, sizeof(cmd));
380 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
381 cmd.num_buffers = 1;
382 if (cmd.num_buffers == 1) {
383 cmd.buf_address_length[0] = (audio->out[idx].addr &
384 0xffff0000) >> 16;
385 cmd.buf_address_length[1] = (audio->out[idx].addr &
386 0x0000ffff);
387 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
388 cmd.buf_address_length[3] = (len & 0x0000ffff);
389 }
390 audio->out_frame_cnt++;
391 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
392}
393
394static int audpcm_config(struct audio_qcelp_in *audio)
395{
396 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
397 MM_DBG("\n");
398 memset(&cmd, 0, sizeof(cmd));
399 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
400 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
401 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
402 cmd.sampling_freq = convert_samp_index(audio->samp_rate);
403 if (!audio->channel_mode)
404 cmd.channels = 1;
405 else
406 cmd.channels = 2;
407 cmd.frequency_of_intimation = 1;
408 cmd.max_number_of_buffers = OUT_FRAME_NUM;
409 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
410}
411
412
413static int audqcelp_in_routing_mode_config(struct audio_qcelp_in *audio)
414{
415 struct audrec_cmd_routing_mode cmd;
416
417 MM_DBG("\n");
418 memset(&cmd, 0, sizeof(cmd));
419 cmd.cmd_id = AUDREC_CMD_ROUTING_MODE;
420 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
421 cmd.routing_mode = 1;
422 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
423}
424
425static void audrec_dsp_event(void *data, unsigned id, size_t len,
426 void (*getevent)(void *ptr, size_t len))
427{
428 struct audio_qcelp_in *audio = NULL;
429
430 if (data)
431 audio = data;
432 else {
433 MM_ERR("invalid data for event %x\n", id);
434 return;
435 }
436
437 switch (id) {
438 case AUDREC_MSG_CMD_CFG_DONE_MSG: {
439 struct audrec_msg_cmd_cfg_done_msg cmd_cfg_done_msg;
440 getevent(&cmd_cfg_done_msg, AUDREC_MSG_CMD_CFG_DONE_MSG_LEN);
441 if (cmd_cfg_done_msg.audrec_enc_type & \
442 AUDREC_MSG_CFG_DONE_ENC_ENA) {
443 audio->audrec_obj_idx = cmd_cfg_done_msg.audrec_obj_idx;
444 MM_DBG("CFG ENABLED\n");
445 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
446 MM_DBG("routing command\n");
447 audqcelp_in_routing_mode_config(audio);
448 } else {
449 audqcelp_in_encmem_config(audio);
450 }
451 } else {
452 MM_DBG("CFG SLEEP\n");
453 audio->running = 0;
454 wake_up(&audio->wait_enable);
455 }
456 break;
457 }
458 case AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG: {
459 struct audrec_msg_cmd_routing_mode_done_msg \
460 routing_msg;
461 getevent(&routing_msg, AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG);
462 MM_DBG("AUDREC_MSG_CMD_ROUTING_MODE_DONE_MSG");
463 if (routing_msg.configuration == 0) {
464 MM_ERR("routing configuration failed\n");
465 audio->running = 0;
466 wake_up(&audio->wait_enable);
467 } else
468 audqcelp_in_encmem_config(audio);
469 break;
470 }
471 case AUDREC_MSG_CMD_AREC_MEM_CFG_DONE_MSG: {
472 MM_DBG("AREC_MEM_CFG_DONE_MSG\n");
473 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
474 audqcelp_in_encparam_config(audio);
475 else
476 audpcm_config(audio);
477 break;
478 }
479 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
480 MM_DBG("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
481 audqcelp_in_encparam_config(audio);
482 break;
483 }
484 case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
485 MM_DBG("AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG\n");
486 audio->running = 1;
487 wake_up(&audio->wait_enable);
488 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
489 audrec_pcm_send_data(audio, 1);
490 break;
491 }
492 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
493 MM_DBG("ptr_update recieved from DSP\n");
494 audrec_pcm_send_data(audio, 1);
495 break;
496 }
497 case AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG: {
498 struct audrec_msg_no_ext_pkt_avail_msg err_msg;
499 getevent(&err_msg, AUDREC_MSG_NO_EXT_PKT_AVAILABLE_MSG_LEN);
500 MM_DBG("NO_EXT_PKT_AVAILABLE_MSG %x\n",\
501 err_msg.audrec_err_id);
502 break;
503 }
504 case AUDREC_MSG_PACKET_READY_MSG: {
505 struct audrec_msg_packet_ready_msg pkt_ready_msg;
506
507 getevent(&pkt_ready_msg, AUDREC_MSG_PACKET_READY_MSG_LEN);
508 MM_DBG("UP_PACKET_READY_MSG: write cnt msw %d \
509 write cnt lsw %d read cnt msw %d read cnt lsw %d \n",\
510 pkt_ready_msg.pkt_counter_msw, \
511 pkt_ready_msg.pkt_counter_lsw, \
512 pkt_ready_msg.pkt_read_cnt_msw, \
513 pkt_ready_msg.pkt_read_cnt_lsw);
514
515 audqcelp_in_get_dsp_frames(audio);
516 break;
517 }
518 case AUDREC_UP_NT_PACKET_READY_MSG: {
519 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
520
521 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
522 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
523 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
524 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
525 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
526 pkt_ready_msg.audrec_upprev_readcount_lsw, \
527 pkt_ready_msg.audrec_upprev_readcount_msw);
528
529 audqcelp_nt_in_get_dsp_frames(audio);
530 break;
531 }
532 case AUDREC_CMD_FLUSH_DONE_MSG: {
533 audio->wflush = 0;
534 audio->rflush = 0;
535 audio->flush_ack = 1;
536 wake_up(&audio->write_wait);
537 MM_DBG("flush ack recieved\n");
538 break;
539 }
540 case ADSP_MESSAGE_ID:
541 MM_DBG("Received ADSP event: module \
542 enable/disable(audrectask)\n");
543 break;
544 default:
545 MM_ERR("unknown event %d\n", id);
546 }
547}
548
549static struct msm_adsp_ops audpre_qcelp_adsp_ops = {
550 .event = audpre_dsp_event,
551};
552
553static struct msm_adsp_ops audrec_qcelp_adsp_ops = {
554 .event = audrec_dsp_event,
555};
556
557static int audqcelp_in_dsp_enable(struct audio_qcelp_in *audio, int enable)
558{
559 struct audrec_cmd_enc_cfg cmd;
560
561 memset(&cmd, 0, sizeof(cmd));
562 cmd.cmd_id = AUDREC_CMD_ENC_CFG;
563 cmd.audrec_enc_type = (audio->enc_type & 0xFF) |
564 (enable ? AUDREC_CMD_ENC_ENA : AUDREC_CMD_ENC_DIS);
565 /* Don't care */
566 cmd.audrec_obj_idx = audio->audrec_obj_idx;
567
568 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
569}
570
571static int audqcelp_in_encmem_config(struct audio_qcelp_in *audio)
572{
573 struct audrec_cmd_arecmem_cfg cmd;
574 uint16_t *data = (void *) audio->data;
575 int n;
576 int header_len = 0;
577
578 memset(&cmd, 0, sizeof(cmd));
579
580 cmd.cmd_id = AUDREC_CMD_ARECMEM_CFG;
581 cmd.audrec_obj_idx = audio->audrec_obj_idx;
582 /* Rate at which packet complete message comes */
583 cmd.audrec_up_pkt_intm_cnt = 1;
584 cmd.audrec_extpkt_buffer_msw = audio->phys >> 16;
585 cmd.audrec_extpkt_buffer_lsw = audio->phys;
586 /* Max Buffer no available for frames */
587 cmd.audrec_extpkt_buffer_num = FRAME_NUM;
588
589 /* prepare buffer pointers:
590 * T:36 bytes qcelp packet + 4 halfword header
591 * NT:36 bytes qcelp packet + 12 halfword header
592 */
593 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
594 header_len = FRAME_HEADER_SIZE/2;
595 else
596 header_len = NT_FRAME_HEADER_SIZE/2;
597
598 for (n = 0; n < FRAME_NUM; n++) {
599 audio->in[n].data = data + header_len;
600 data += (QCELP_FRAME_SIZE/2) + header_len;
601 MM_DBG("0x%8x\n", (int)(audio->in[n].data - header_len*2));
602 }
603
604 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
605}
606
607static int audqcelp_in_encparam_config(struct audio_qcelp_in *audio)
608{
609 struct audrec_cmd_arecparam_qcelp_cfg cmd;
610
611 memset(&cmd, 0, sizeof(cmd));
612 cmd.common.cmd_id = AUDREC_CMD_ARECPARAM_CFG;
613 cmd.common.audrec_obj_idx = audio->audrec_obj_idx;
614 cmd.enc_min_rate = audio->cfg.min_bit_rate;
615 cmd.enc_max_rate = audio->cfg.max_bit_rate;
616 cmd.rate_modulation_cmd = 0; /* Default set to 0 */
617 cmd.reduced_rate_level = 0; /* Default set to 0 */
618
619 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
620}
621
622static int audqcelp_flush_command(struct audio_qcelp_in *audio)
623{
624 struct audrec_cmd_flush cmd;
625 MM_DBG("\n");
626 memset(&cmd, 0, sizeof(cmd));
627 cmd.cmd_id = AUDREC_CMD_FLUSH;
628 return audio_send_queue_rec(audio, &cmd, sizeof(cmd));
629}
630
631static int audqcelp_in_dsp_read_buffer(struct audio_qcelp_in *audio,
632 uint32_t read_cnt)
633{
634 audrec_cmd_packet_ext_ptr cmd;
635
636 memset(&cmd, 0, sizeof(cmd));
637 cmd.cmd_id = AUDREC_CMD_PACKET_EXT_PTR;
638 cmd.type = audio->audrec_obj_idx;
639 cmd.curr_rec_count_msw = read_cnt >> 16;
640 cmd.curr_rec_count_lsw = read_cnt;
641
642 return audio_send_queue_recbs(audio, &cmd, sizeof(cmd));
643}
644
645/* ------------------- device --------------------- */
646
647static void audqcelp_ioport_reset(struct audio_qcelp_in *audio)
648{
649 /* Make sure read/write thread are free from
650 * sleep and knowing that system is not able
651 * to process io request at the moment
652 */
653 wake_up(&audio->write_wait);
654 mutex_lock(&audio->write_lock);
655 audqcelp_in_flush(audio);
656 mutex_unlock(&audio->write_lock);
657 wake_up(&audio->wait);
658 mutex_lock(&audio->read_lock);
659 audqcelp_out_flush(audio);
660 mutex_unlock(&audio->read_lock);
661}
662
663static void audqcelp_in_flush(struct audio_qcelp_in *audio)
664{
665 int i;
666
667 audio->dsp_cnt = 0;
668 audio->in_head = 0;
669 audio->in_tail = 0;
670 audio->in_count = 0;
671 audio->eos_ack = 0;
672 for (i = FRAME_NUM-1; i >= 0; i--) {
673 audio->in[i].size = 0;
674 audio->in[i].read = 0;
675 }
676 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
677 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
678 atomic_set(&audio->in_bytes, 0);
679 atomic_set(&audio->in_samples, 0);
680}
681
682static void audqcelp_out_flush(struct audio_qcelp_in *audio)
683{
684 int i;
685
686 audio->out_head = 0;
687 audio->out_tail = 0;
688 audio->out_count = 0;
689 for (i = OUT_FRAME_NUM-1; i >= 0; i--) {
690 audio->out[i].size = 0;
691 audio->out[i].read = 0;
692 audio->out[i].used = 0;
693 }
694}
695
696/* ------------------- device --------------------- */
697static long audqcelp_in_ioctl(struct file *file,
698 unsigned int cmd, unsigned long arg)
699{
700 struct audio_qcelp_in *audio = file->private_data;
701 int rc = 0;
702
703 MM_DBG("\n");
704 if (cmd == AUDIO_GET_STATS) {
705 struct msm_audio_stats stats;
706 stats.byte_count = atomic_read(&audio->in_bytes);
707 stats.sample_count = atomic_read(&audio->in_samples);
708 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
709 return -EFAULT;
710 return rc;
711 }
712
713 mutex_lock(&audio->lock);
714 switch (cmd) {
715 case AUDIO_START: {
716 rc = audqcelp_in_enable(audio);
717 if (!rc) {
718 rc =
719 wait_event_interruptible_timeout(audio->wait_enable,
720 audio->running != 0, 1*HZ);
721 MM_DBG("state %d rc = %d\n", audio->running, rc);
722
723 if (audio->running == 0)
724 rc = -ENODEV;
725 else
726 rc = 0;
727 }
728 audio->stopped = 0;
729 break;
730 }
731 case AUDIO_STOP: {
732 rc = audqcelp_in_disable(audio);
733 audio->stopped = 1;
734 break;
735 }
736 case AUDIO_FLUSH: {
737 MM_DBG("AUDIO_FLUSH\n");
738 audio->rflush = 1;
739 audio->wflush = 1;
740 audqcelp_ioport_reset(audio);
741 if (audio->running) {
742 audqcelp_flush_command(audio);
743 rc = wait_event_interruptible(audio->write_wait,
744 !audio->wflush);
745 if (rc < 0) {
746 MM_ERR("AUDIO_FLUSH interrupted\n");
747 rc = -EINTR;
748 }
749 } else {
750 audio->rflush = 0;
751 audio->wflush = 0;
752 }
753 break;
754 }
755 case AUDIO_GET_CONFIG: {
756 struct msm_audio_config cfg;
757 memset(&cfg, 0, sizeof(cfg));
758 cfg.buffer_size = OUT_BUFFER_SIZE;
759 cfg.buffer_count = OUT_FRAME_NUM;
760 cfg.sample_rate = convert_samp_index(audio->samp_rate);
761 cfg.channel_count = 1;
762 cfg.type = 0;
763 cfg.unused[0] = 0;
764 cfg.unused[1] = 0;
765 cfg.unused[2] = 0;
766 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
767 rc = -EFAULT;
768 else
769 rc = 0;
770 break;
771 }
772 case AUDIO_GET_STREAM_CONFIG: {
773 struct msm_audio_stream_config cfg;
774 memset(&cfg, 0, sizeof(cfg));
775 cfg.buffer_size = audio->buffer_size;
776 cfg.buffer_count = FRAME_NUM;
777 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
778 rc = -EFAULT;
779 else
780 rc = 0;
781 break;
782 }
783 case AUDIO_SET_STREAM_CONFIG: {
784 struct msm_audio_stream_config cfg;
785 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
786 rc = -EFAULT;
787 break;
788 }
789 /* Allow only single frame */
790 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
791 if (cfg.buffer_size != (FRAME_SIZE - 8))
792 rc = -EINVAL;
793 break;
794 } else {
795 if (cfg.buffer_size != (QCELP_FRAME_SIZE + 14))
796 rc = -EINVAL;
797 break;
798 }
799 audio->buffer_size = cfg.buffer_size;
800 break;
801 }
802 case AUDIO_GET_QCELP_ENC_CONFIG: {
803 if (copy_to_user((void *) arg, &audio->cfg, sizeof(audio->cfg)))
804 rc = -EFAULT;
805 break;
806 }
807 case AUDIO_SET_QCELP_ENC_CONFIG: {
808 struct msm_audio_qcelp_enc_config cfg;
809 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
810 rc = -EFAULT;
811 break;
812 }
813 MM_DBG("0X%8x, 0x%8x, 0x%8x\n", cfg.min_bit_rate,
814 cfg.max_bit_rate, cfg.cdma_rate);
815 if (cfg.min_bit_rate > CDMA_RATE_FULL || \
816 cfg.min_bit_rate < CDMA_RATE_EIGHTH) {
817 MM_ERR("invalid min bitrate\n");
818 rc = -EFAULT;
819 break;
820 }
821 if (cfg.max_bit_rate > CDMA_RATE_FULL || \
822 cfg.max_bit_rate < CDMA_RATE_EIGHTH) {
823 MM_ERR("invalid max bitrate\n");
824 rc = -EFAULT;
825 break;
826 }
827 /* Recording Does not support Erase and Blank */
828 if (cfg.cdma_rate > CDMA_RATE_FULL ||
829 cfg.cdma_rate < CDMA_RATE_EIGHTH) {
830 MM_ERR("invalid qcelp cdma rate\n");
831 rc = -EFAULT;
832 break;
833 }
834 memcpy(&audio->cfg, &cfg, sizeof(cfg));
835 break;
836 }
837 default:
838 rc = -EINVAL;
839 }
840 mutex_unlock(&audio->lock);
841 return rc;
842}
843
844static ssize_t audqcelp_in_read(struct file *file,
845 char __user *buf,
846 size_t count, loff_t *pos)
847{
848 struct audio_qcelp_in *audio = file->private_data;
849 unsigned long flags;
850 const char __user *start = buf;
851 void *data;
852 uint32_t index;
853 uint32_t size;
854 int rc = 0;
855 struct qcelp_encoded_meta_out meta_field;
856 struct audio_frame_nt *nt_frame;
857 MM_DBG("count = %d\n", count);
858 mutex_lock(&audio->read_lock);
859 while (count > 0) {
860 rc = wait_event_interruptible(
861 audio->wait, (audio->in_count > 0) || audio->stopped ||
862 audio->rflush);
863 if (rc < 0)
864 break;
865
866 if (audio->rflush) {
867 rc = -EBUSY;
868 break;
869 }
870 if (audio->stopped && !audio->in_count) {
871 MM_DBG("Driver in stop state, No more buffer to read");
872 rc = 0;/* End of File */
873 break;
874 }
875
876 index = audio->in_tail;
877 data = (uint8_t *) audio->in[index].data;
878 size = audio->in[index].size;
879
880 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
881 nt_frame = (struct audio_frame_nt *)(data -
882 sizeof(struct audio_frame_nt));
883 memcpy((char *)&meta_field.time_stamp_dword_lsw,
884 (char *)&nt_frame->time_stamp_dword_lsw,
885 (sizeof(struct qcelp_encoded_meta_out) - \
886 sizeof(uint16_t)));
887 meta_field.metadata_len =
888 sizeof(struct qcelp_encoded_meta_out);
889 if (copy_to_user((char *)start, (char *)&meta_field,
890 sizeof(struct qcelp_encoded_meta_out))) {
891 rc = -EFAULT;
892 break;
893 }
894 if (nt_frame->nflag_lsw & 0x0001) {
895 MM_ERR("recieved EOS in read call\n");
896 audio->eos_ack = 1;
897 }
898 buf += sizeof(struct qcelp_encoded_meta_out);
899 count -= sizeof(struct qcelp_encoded_meta_out);
900 }
901 if (count >= size) {
902 /* order the reads on the buffer */
903 dma_coherent_post_ops();
904 if (copy_to_user(buf, data, size)) {
905 rc = -EFAULT;
906 break;
907 }
908 spin_lock_irqsave(&audio->dsp_lock, flags);
909 if (index != audio->in_tail) {
910 /* overrun -- data is
911 * invalid and we need to retry */
912 spin_unlock_irqrestore(&audio->dsp_lock, flags);
913 continue;
914 }
915 audio->in[index].size = 0;
916 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
917 audio->in_count--;
918 spin_unlock_irqrestore(&audio->dsp_lock, flags);
919 count -= size;
920 buf += size;
921 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
922 if (!audio->eos_ack) {
923 MM_DBG("sending read ptr command \
924 %d %d\n",
925 audio->dsp_cnt,
926 audio->in_tail);
927 audqcelp_in_dsp_read_buffer(audio,
928 audio->dsp_cnt++);
929 }
930 }
931 } else {
932 MM_ERR("short read\n");
933 break;
934 }
935 break;
936 }
937 mutex_unlock(&audio->read_lock);
938
939 if (buf > start)
940 return buf - start;
941
942 return rc;
943}
944
945static void audrec_pcm_send_data(struct audio_qcelp_in *audio, unsigned needed)
946{
947 struct buffer *frame;
948 unsigned long flags;
949 MM_DBG("\n");
950 spin_lock_irqsave(&audio->dsp_lock, flags);
951 if (!audio->running)
952 goto done;
953
954 if (needed && !audio->wflush) {
955 /* We were called from the callback because the DSP
956 * requested more data. Note that the DSP does want
957 * more data, and if a buffer was in-flight, mark it
958 * as available (since the DSP must now be done with
959 * it).
960 */
961 audio->out_needed = 1;
962 frame = audio->out + audio->out_tail;
963 if (frame->used == 0xffffffff) {
964 MM_DBG("frame %d free\n", audio->out_tail);
965 frame->used = 0;
966 audio->out_tail ^= 1;
967 wake_up(&audio->write_wait);
968 }
969 }
970
971 if (audio->out_needed) {
972 /* If the DSP currently wants data and we have a
973 * buffer available, we will send it and reset
974 * the needed flag. We'll mark the buffer as in-flight
975 * so that it won't be recycled until the next buffer
976 * is requested
977 */
978
979 frame = audio->out + audio->out_tail;
980 if (frame->used) {
981 BUG_ON(frame->used == 0xffffffff);
982 audrec_pcm_buffer_ptr_refresh(audio,
983 audio->out_tail,
984 frame->used);
985 frame->used = 0xffffffff;
986 audio->out_needed = 0;
987 }
988 }
989 done:
990 spin_unlock_irqrestore(&audio->dsp_lock, flags);
991}
992
993static int audqcelp_in_fsync(struct file *file, int datasync)
994
995{
996 struct audio_qcelp_in *audio = file->private_data;
997 int rc = 0;
998
999 MM_DBG("\n"); /* Macro prints the file name and function */
1000 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1001 rc = -EINVAL;
1002 goto done_nolock;
1003 }
1004
1005 mutex_lock(&audio->write_lock);
1006
1007 rc = wait_event_interruptible(audio->write_wait,
1008 audio->wflush);
1009 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1010
1011 if (rc < 0)
1012 goto done;
1013 else if (audio->wflush) {
1014 rc = -EBUSY;
1015 goto done;
1016 }
1017done:
1018 mutex_unlock(&audio->write_lock);
1019done_nolock:
1020 return rc;
1021
1022}
1023
1024int audrec_qcelp_process_eos(struct audio_qcelp_in *audio,
1025 const char __user *buf_start, unsigned short mfield_size)
1026{
1027 struct buffer *frame;
1028 int rc = 0;
1029
1030 frame = audio->out + audio->out_head;
1031
1032 rc = wait_event_interruptible(audio->write_wait,
1033 (audio->out_needed &&
1034 audio->out[0].used == 0 &&
1035 audio->out[1].used == 0)
1036 || (audio->stopped)
1037 || (audio->wflush));
1038
1039 if (rc < 0)
1040 goto done;
1041 if (audio->stopped || audio->wflush) {
1042 rc = -EBUSY;
1043 goto done;
1044 }
1045 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1046 rc = -EFAULT;
1047 goto done;
1048 }
1049
1050 frame->mfield_sz = mfield_size;
1051 audio->out_head ^= 1;
1052 frame->used = mfield_size;
1053 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1054 audrec_pcm_send_data(audio, 0);
1055done:
1056 return rc;
1057}
1058
1059static ssize_t audqcelp_in_write(struct file *file,
1060 const char __user *buf,
1061 size_t count, loff_t *pos)
1062{
1063 struct audio_qcelp_in *audio = file->private_data;
1064 const char __user *start = buf;
1065 struct buffer *frame;
1066 char *cpy_ptr;
1067 int rc = 0, eos_condition = AUDPREPROC_QCELP_EOS_NONE;
1068 unsigned short mfield_size = 0;
1069 int write_count = 0;
1070 MM_DBG("cnt=%d\n", count);
1071
1072 if (count & 1)
1073 return -EINVAL;
1074
1075 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1076 return -EINVAL;
1077
1078 mutex_lock(&audio->write_lock);
1079 frame = audio->out + audio->out_head;
1080 /* if supplied count is more than driver buffer size
1081 * then only copy driver buffer size
1082 */
1083 if (count > frame->size)
1084 count = frame->size;
1085
1086 write_count = count;
1087 cpy_ptr = frame->data;
1088 rc = wait_event_interruptible(audio->write_wait,
1089 (frame->used == 0)
1090 || (audio->stopped)
1091 || (audio->wflush));
1092 if (rc < 0)
1093 goto error;
1094
1095 if (audio->stopped || audio->wflush) {
1096 rc = -EBUSY;
1097 goto error;
1098 }
1099 if (audio->mfield) {
1100 if (buf == start) {
1101 /* Processing beginning of user buffer */
1102 if (__get_user(mfield_size,
1103 (unsigned short __user *) buf)) {
1104 rc = -EFAULT;
1105 goto error;
1106 } else if (mfield_size > count) {
1107 rc = -EINVAL;
1108 goto error;
1109 }
1110 MM_DBG("mf offset_val %x\n", mfield_size);
1111 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1112 rc = -EFAULT;
1113 goto error;
1114 }
1115 /* Check if EOS flag is set and buffer has
1116 * contains just meta field
1117 */
1118 if (cpy_ptr[AUDPREPROC_QCELP_EOS_FLG_OFFSET] &
1119 AUDPREPROC_QCELP_EOS_FLG_MASK) {
1120 eos_condition = AUDPREPROC_QCELP_EOS_SET;
1121 MM_DBG("EOS SET\n");
1122 if (mfield_size == count) {
1123 buf += mfield_size;
1124 eos_condition = 0;
1125 goto exit;
1126 } else
1127 cpy_ptr[AUDPREPROC_QCELP_EOS_FLG_OFFSET] &=
1128 ~AUDPREPROC_QCELP_EOS_FLG_MASK;
1129 }
1130 cpy_ptr += mfield_size;
1131 count -= mfield_size;
1132 buf += mfield_size;
1133 } else {
1134 mfield_size = 0;
1135 MM_DBG("continuous buffer\n");
1136 }
1137 frame->mfield_sz = mfield_size;
1138 }
1139 MM_DBG("copying the stream count = %d\n", count);
1140 if (copy_from_user(cpy_ptr, buf, count)) {
1141 rc = -EFAULT;
1142 goto error;
1143 }
1144exit:
1145 frame->used = count;
1146 audio->out_head ^= 1;
1147 if (!audio->flush_ack)
1148 audrec_pcm_send_data(audio, 0);
1149 else {
1150 audrec_pcm_send_data(audio, 1);
1151 audio->flush_ack = 0;
1152 }
1153 if (eos_condition == AUDPREPROC_QCELP_EOS_SET)
1154 rc = audrec_qcelp_process_eos(audio, start, mfield_size);
1155 mutex_unlock(&audio->write_lock);
1156 return write_count;
1157error:
1158 mutex_unlock(&audio->write_lock);
1159 return rc;
1160}
1161
1162static int audqcelp_in_release(struct inode *inode, struct file *file)
1163{
1164 struct audio_qcelp_in *audio = file->private_data;
1165
1166 mutex_lock(&audio->lock);
1167 audqcelp_in_disable(audio);
1168 audqcelp_in_flush(audio);
1169 msm_adsp_put(audio->audrec);
1170
1171 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1172 msm_adsp_put(audio->audpre);
1173
1174 audpreproc_aenc_free(audio->enc_id);
1175 audio->audrec = NULL;
1176 audio->audpre = NULL;
1177 audio->opened = 0;
1178
1179 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
1180 (audio->out_data)) {
1181 free_contiguous_memory(audio->out_data);
1182 audio->out_data = NULL;
1183 }
1184
1185 if (audio->data) {
1186 free_contiguous_memory(audio->data);
1187 audio->data = NULL;
1188 }
1189 mutex_unlock(&audio->lock);
1190 return 0;
1191}
1192
1193static struct audio_qcelp_in the_audio_qcelp_in;
1194
1195static int audqcelp_in_open(struct inode *inode, struct file *file)
1196{
1197 struct audio_qcelp_in *audio = &the_audio_qcelp_in;
1198 int rc;
1199 int encid;
1200 int dma_size = 0;
1201
1202 mutex_lock(&audio->lock);
1203 if (audio->opened) {
1204 rc = -EBUSY;
1205 goto done;
1206 }
1207 if ((file->f_mode & FMODE_WRITE) &&
1208 (file->f_mode & FMODE_READ)) {
1209 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1210 dma_size = NT_DMASZ;
1211 MM_DBG("Opened for non tunnel mode encoding\n");
1212 } else if (!(file->f_mode & FMODE_WRITE) &&
1213 (file->f_mode & FMODE_READ)) {
1214 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1215 dma_size = DMASZ;
1216 MM_DBG("Opened for tunnel mode encoding\n");
1217 } else {
1218 MM_ERR("Invalid mode\n");
1219 rc = -EACCES;
1220 goto done;
1221 }
1222
1223 /* Settings will be re-config at AUDIO_SET_CONFIG,
1224 * but at least we need to have initial config
1225 */
1226 audio->samp_rate = RPC_AUD_DEF_SAMPLE_RATE_8000,
1227 audio->samp_rate_index = AUDREC_CMD_SAMP_RATE_INDX_8000;
1228 audio->channel_mode = AUDREC_CMD_STEREO_MODE_MONO;
1229 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1230 audio->buffer_size = (QCELP_FRAME_SIZE + 14);
1231 else
1232 audio->buffer_size = QCELP_FRAME_SIZE;
1233 audio->enc_type = AUDREC_CMD_TYPE_0_INDEX_QCELP | audio->mode;
1234
1235 audio->cfg.cdma_rate = CDMA_RATE_FULL;
1236 audio->cfg.min_bit_rate = CDMA_RATE_FULL;
1237 audio->cfg.max_bit_rate = CDMA_RATE_FULL;
1238
1239 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1240 rc = audmgr_open(&audio->audmgr);
1241 if (rc)
1242 goto done;
1243 }
1244
1245 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1246 &audio->queue_ids);
1247 if (encid < 0) {
1248 MM_ERR("No free encoder available\n");
1249 rc = -ENODEV;
1250 goto done;
1251 }
1252 audio->enc_id = encid;
1253
1254 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1255 &audrec_qcelp_adsp_ops, audio);
1256 if (rc) {
1257 audpreproc_aenc_free(audio->enc_id);
1258 goto done;
1259 }
1260
1261 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
1262 rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
1263 &audpre_qcelp_adsp_ops, audio);
1264 if (rc) {
1265 msm_adsp_put(audio->audrec);
1266 audpreproc_aenc_free(audio->enc_id);
1267 goto done;
1268 }
1269 }
1270
1271 audio->dsp_cnt = 0;
1272 audio->stopped = 0;
1273 audio->wflush = 0;
1274 audio->rflush = 0;
1275 audio->flush_ack = 0;
1276
1277 audqcelp_in_flush(audio);
1278 audqcelp_out_flush(audio);
1279
1280 audio->data = allocate_contiguous_memory(dma_size, MEMTYPE_EBI1,
1281 SZ_4K, 0);
1282 if (!audio->data) {
1283 MM_ERR("could not allocate read buffers\n");
1284 rc = -ENOMEM;
1285 goto evt_error;
1286 } else {
1287 audio->phys = memory_pool_node_paddr(audio->data);
1288 if (!audio->phys) {
1289 MM_ERR("could not get physical address\n");
1290 rc = -ENOMEM;
1291 free_contiguous_memory(audio->data);
1292 goto evt_error;
1293 }
1294 MM_DBG("read buf: phy addr 0x%08x kernel addr 0x%08x\n",
1295 audio->phys, (int)audio->data);
1296 }
1297
1298 audio->out_data = NULL;
1299 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
1300 audio->out_data = allocate_contiguous_memory(BUFFER_SIZE,
1301 MEMTYPE_EBI1,
1302 SZ_4K, 0);
1303 if (!audio->out_data) {
1304 MM_ERR("could not allocate read buffers\n");
1305 rc = -ENOMEM;
1306 free_contiguous_memory(audio->data);
1307 goto evt_error;
1308 } else {
1309 audio->out_phys = memory_pool_node_paddr(
1310 audio->out_data);
1311 if (!audio->out_phys) {
1312 MM_ERR("could not get physical address\n");
1313 rc = -ENOMEM;
1314 free_contiguous_memory(audio->data);
1315 free_contiguous_memory(audio->out_data);
1316 goto evt_error;
1317 }
1318 MM_DBG("write buf:phy addr 0x%08x kernel addr 0x%08x\n",
1319 audio->out_phys, (int)audio->out_data);
1320 }
1321
1322 /* Initialize buffer */
1323 audio->out[0].data = audio->out_data + 0;
1324 audio->out[0].addr = audio->out_phys + 0;
1325 audio->out[0].size = OUT_BUFFER_SIZE;
1326
1327 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1328 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1329 audio->out[1].size = OUT_BUFFER_SIZE;
1330
1331 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1332 (unsigned int)audio->out[0].data,
1333 (unsigned int)audio->out[1].data);
1334 audio->mfield = NT_FRAME_HEADER_SIZE;
1335 audio->out_frame_cnt++;
1336 }
1337 file->private_data = audio;
1338 audio->opened = 1;
1339
1340done:
1341 mutex_unlock(&audio->lock);
1342 return rc;
1343evt_error:
1344 msm_adsp_put(audio->audrec);
1345 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
1346 msm_adsp_put(audio->audpre);
1347
1348 audpreproc_aenc_free(audio->enc_id);
1349 mutex_unlock(&audio->lock);
1350 return rc;
1351}
1352
1353static const struct file_operations audio_qcelp_in_fops = {
1354 .owner = THIS_MODULE,
1355 .open = audqcelp_in_open,
1356 .release = audqcelp_in_release,
1357 .read = audqcelp_in_read,
1358 .write = audqcelp_in_write,
1359 .fsync = audqcelp_in_fsync,
1360 .unlocked_ioctl = audqcelp_in_ioctl,
1361};
1362
1363static struct miscdevice audqcelp_in_misc = {
1364 .minor = MISC_DYNAMIC_MINOR,
1365 .name = "msm_qcelp_in",
1366 .fops = &audio_qcelp_in_fops,
1367};
1368
1369static int __init audqcelp_in_init(void)
1370{
1371 mutex_init(&the_audio_qcelp_in.lock);
1372 mutex_init(&the_audio_qcelp_in.read_lock);
1373 spin_lock_init(&the_audio_qcelp_in.dsp_lock);
1374 init_waitqueue_head(&the_audio_qcelp_in.wait);
1375 init_waitqueue_head(&the_audio_qcelp_in.wait_enable);
1376 mutex_init(&the_audio_qcelp_in.write_lock);
1377 init_waitqueue_head(&the_audio_qcelp_in.write_wait);
1378 return misc_register(&audqcelp_in_misc);
1379}
1380device_initcall(audqcelp_in_init);