blob: 47bd589ff1bce55c6cc89d4e7c587f788be663aa [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * qcelp audio input device
3 *
4 * Copyright (C) 2008 Google, Inc.
5 * Copyright (C) 2008 HTC Corporation
6 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/fs.h>
21#include <linux/miscdevice.h>
22#include <linux/uaccess.h>
23#include <linux/sched.h>
24#include <linux/wait.h>
25#include <linux/dma-mapping.h>
26#include <linux/msm_audio_qcp.h>
27#include <linux/android_pmem.h>
28
29#include <asm/atomic.h>
30#include <asm/ioctls.h>
31
32#include <mach/msm_adsp.h>
33#include <mach/qdsp5v2/qdsp5audreccmdi.h>
34#include <mach/qdsp5v2/qdsp5audrecmsg.h>
35#include <mach/qdsp5v2/audpreproc.h>
36#include <mach/qdsp5v2/audio_dev_ctl.h>
37#include <mach/debug_mm.h>
38
39#define META_OUT_SIZE 24
40/* FRAME_NUM must be a power of two */
41#define FRAME_NUM 8
42#define QCELP_FRAME_SIZE 36 /* 36 bytes data */
43#define FRAME_SIZE (22 * 2) /* 36 bytes data */
44 /* 36 bytes data + 24 meta field*/
45#define NT_FRAME_SIZE (QCELP_FRAME_SIZE + META_OUT_SIZE)
46#define DMASZ (NT_FRAME_SIZE * FRAME_NUM)
47#define OUT_FRAME_NUM (2)
48#define OUT_BUFFER_SIZE (4 * 1024 + META_OUT_SIZE)
49#define BUFFER_SIZE (OUT_BUFFER_SIZE * OUT_FRAME_NUM)
50
51
52#define AUDPREPROC_QCELP_EOS_FLG_OFFSET 0x0A
53#define AUDPREPROC_QCELP_EOS_FLG_MASK 0x01
54#define AUDPREPROC_QCELP_EOS_NONE 0x0 /* No EOS detected */
55#define AUDPREPROC_QCELP_EOS_SET 0x1 /* EOS set in meta field */
56
57struct buffer {
58 void *data;
59 uint32_t size;
60 uint32_t read;
61 uint32_t addr;
62 uint32_t used;
63 uint32_t mfield_sz;
64};
65
66struct audio_in {
67 struct buffer in[FRAME_NUM];
68
69 spinlock_t dsp_lock;
70
71 atomic_t in_bytes;
72 atomic_t in_samples;
73
74 struct mutex lock;
75 struct mutex read_lock;
76 wait_queue_head_t wait;
77 wait_queue_head_t wait_enable;
78 /*write section*/
79 struct buffer out[OUT_FRAME_NUM];
80
81 uint8_t out_head;
82 uint8_t out_tail;
83 uint8_t out_needed; /* number of buffers the dsp is waiting for */
84 uint32_t out_count;
85
86 struct mutex write_lock;
87 wait_queue_head_t write_wait;
88 int32_t out_phys; /* physical address of write buffer */
89 char *out_data;
90 int mfield; /* meta field embedded in data */
91 int wflush; /*write flush */
92 int rflush; /*read flush*/
93 int out_frame_cnt;
94
95 struct msm_adsp_module *audrec;
96
97 struct audrec_session_info session_info; /*audrec session info*/
98
99 /* configuration to use on next enable */
100 uint32_t buffer_size; /* Frame size (36 bytes) */
101 uint32_t samp_rate;
102 uint32_t channel_mode;
103 uint32_t enc_type;
104
105 struct msm_audio_qcelp_enc_config cfg;
106 uint32_t rec_mode;
107
108 uint32_t dsp_cnt;
109 uint32_t in_head; /* next buffer dsp will write */
110 uint32_t in_tail; /* next buffer read() will read */
111 uint32_t in_count; /* number of buffers available to read() */
112 uint32_t mode;
113 uint32_t eos_ack;
114 uint32_t flush_ack;
115
116 const char *module_name;
117 unsigned queue_ids;
118 uint16_t enc_id;
119
120 uint16_t source; /* Encoding source bit mask */
121 uint32_t device_events;
122 uint32_t in_call;
123 uint32_t dev_cnt;
124 int voice_state;
125 spinlock_t dev_lock;
126
127 /* data allocated for various buffers */
128 char *data;
129 dma_addr_t phys;
130
131 int opened;
132 int enabled;
133 int running;
134 int stopped; /* set when stopped, cleared on flush */
135};
136
137struct audio_frame {
138 uint16_t frame_count_lsw;
139 uint16_t frame_count_msw;
140 uint16_t frame_length;
141 uint16_t erased_pcm;
142 unsigned char raw_bitstream[]; /* samples */
143} __attribute__((packed));
144
145struct audio_frame_nt {
146 uint16_t metadata_len;
147 uint16_t frame_count_lsw;
148 uint16_t frame_count_msw;
149 uint16_t frame_length;
150 uint16_t erased_pcm;
151 uint16_t reserved;
152 uint16_t time_stamp_dword_lsw;
153 uint16_t time_stamp_dword_msw;
154 uint16_t time_stamp_lsw;
155 uint16_t time_stamp_msw;
156 uint16_t nflag_lsw;
157 uint16_t nflag_msw;
158 unsigned char raw_bitstream[]; /* samples */
159} __attribute__((packed));
160
161struct qcelp_encoded_meta_out {
162 uint16_t metadata_len;
163 uint16_t time_stamp_dword_lsw;
164 uint16_t time_stamp_dword_msw;
165 uint16_t time_stamp_lsw;
166 uint16_t time_stamp_msw;
167 uint16_t nflag_lsw;
168 uint16_t nflag_msw;
169};
170
171/* Audrec Queue command sent macro's */
172#define audrec_send_bitstreamqueue(audio, cmd, len) \
173 msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
174 cmd, len)
175
176#define audrec_send_audrecqueue(audio, cmd, len) \
177 msm_adsp_write(audio->audrec, (audio->queue_ids & 0x0000FFFF),\
178 cmd, len)
179
180/* DSP command send functions */
181static int audqcelp_in_enc_config(struct audio_in *audio, int enable);
182static int audqcelp_in_param_config(struct audio_in *audio);
183static int audqcelp_in_mem_config(struct audio_in *audio);
184static int audqcelp_in_record_config(struct audio_in *audio, int enable);
185static int audqcelp_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt);
186
187static void audqcelp_in_get_dsp_frames(struct audio_in *audio);
188static int audpcm_config(struct audio_in *audio);
189static void audqcelp_out_flush(struct audio_in *audio);
190static int audpreproc_cmd_cfg_routing_mode(struct audio_in *audio);
191static void audpreproc_pcm_send_data(struct audio_in *audio, unsigned needed);
192static void audqcelp_nt_in_get_dsp_frames(struct audio_in *audio);
193
194static void audqcelp_in_flush(struct audio_in *audio);
195
196static void qcelp_in_listener(u32 evt_id, union auddev_evt_data *evt_payload,
197 void *private_data)
198{
199 struct audio_in *audio = (struct audio_in *) private_data;
200 unsigned long flags;
201
202 MM_DBG("evt_id = 0x%8x\n", evt_id);
203 switch (evt_id) {
204 case AUDDEV_EVT_DEV_RDY: {
205 MM_DBG("AUDDEV_EVT_DEV_RDY\n");
206 spin_lock_irqsave(&audio->dev_lock, flags);
207 audio->dev_cnt++;
208 if (!audio->in_call)
209 audio->source |= (0x1 << evt_payload->routing_id);
210 spin_unlock_irqrestore(&audio->dev_lock, flags);
211
212 if ((audio->running == 1) && (audio->enabled == 1) &&
213 (audio->mode == MSM_AUD_ENC_MODE_TUNNEL))
214 audqcelp_in_record_config(audio, 1);
215 }
216 break;
217 case AUDDEV_EVT_DEV_RLS: {
218 MM_DBG("AUDDEV_EVT_DEV_RLS\n");
219 spin_lock_irqsave(&audio->dev_lock, flags);
220 audio->dev_cnt--;
221 if (!audio->in_call)
222 audio->source &= ~(0x1 << evt_payload->routing_id);
223 spin_unlock_irqrestore(&audio->dev_lock, flags);
224
225 if ((!audio->running) || (!audio->enabled))
226 break;
227
228 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
229 /* Turn of as per source */
230 if (audio->source)
231 audqcelp_in_record_config(audio, 1);
232 else
233 /* Turn off all */
234 audqcelp_in_record_config(audio, 0);
235 }
236 }
237 break;
238 case AUDDEV_EVT_VOICE_STATE_CHG: {
239 MM_DBG("AUDDEV_EVT_VOICE_STATE_CHG, state = %d\n",
240 evt_payload->voice_state);
241 audio->voice_state = evt_payload->voice_state;
242 if (audio->in_call && audio->running &&
243 (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
244 if (audio->voice_state == VOICE_STATE_INCALL)
245 audqcelp_in_record_config(audio, 1);
246 else if (audio->voice_state == VOICE_STATE_OFFCALL) {
247 audqcelp_in_record_config(audio, 0);
248 wake_up(&audio->wait);
249 }
250 }
251
252 break;
253 }
254 default:
255 MM_ERR("wrong event %d\n", evt_id);
256 break;
257 }
258}
259
260/* ------------------- dsp preproc event handler--------------------- */
261static void audpreproc_dsp_event(void *data, unsigned id, void *msg)
262{
263 struct audio_in *audio = data;
264
265 switch (id) {
266 case AUDPREPROC_ERROR_MSG: {
267 struct audpreproc_err_msg *err_msg = msg;
268
269 MM_ERR("ERROR_MSG: stream id %d err idx %d\n",
270 err_msg->stream_id, err_msg->aud_preproc_err_idx);
271 /* Error case */
272 wake_up(&audio->wait_enable);
273 break;
274 }
275 case AUDPREPROC_CMD_CFG_DONE_MSG: {
276 MM_DBG("CMD_CFG_DONE_MSG \n");
277 break;
278 }
279 case AUDPREPROC_CMD_ENC_CFG_DONE_MSG: {
280 struct audpreproc_cmd_enc_cfg_done_msg *enc_cfg_msg = msg;
281
282 MM_DBG("CMD_ENC_CFG_DONE_MSG: stream id %d enc type \
283 0x%8x\n", enc_cfg_msg->stream_id,
284 enc_cfg_msg->rec_enc_type);
285 /* Encoder enable success */
286 if (enc_cfg_msg->rec_enc_type & ENCODE_ENABLE) {
287 if(audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
288 MM_DBG("routing command\n");
289 audpreproc_cmd_cfg_routing_mode(audio);
290 } else {
291 audqcelp_in_param_config(audio);
292 }
293 } else { /* Encoder disable success */
294 audio->running = 0;
295 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
296 audqcelp_in_record_config(audio, 0);
297 else
298 wake_up(&audio->wait_enable);
299 }
300 break;
301 }
302 case AUDPREPROC_CMD_ENC_PARAM_CFG_DONE_MSG: {
303 MM_DBG("CMD_ENC_PARAM_CFG_DONE_MSG\n");
304 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
305 audqcelp_in_mem_config(audio);
306 else
307 audpcm_config(audio);
308 break;
309 }
310 case AUDPREPROC_CMD_ROUTING_MODE_DONE_MSG: {
311 struct audpreproc_cmd_routing_mode_done\
312 *routing_cfg_done_msg = msg;
313 if (routing_cfg_done_msg->configuration == 0) {
314 MM_INFO("routing configuration failed\n");
315 audio->running = 0;
316 } else
317 audqcelp_in_param_config(audio);
318 break;
319 }
320 case AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG: {
321 MM_DBG("AFE_CMD_AUDIO_RECORD_CFG_DONE_MSG \n");
322 wake_up(&audio->wait_enable);
323 break;
324 }
325 default:
326 MM_ERR("Unknown Event id %d\n", id);
327 }
328}
329
330/* ------------------- dsp audrec event handler--------------------- */
331static void audrec_dsp_event(void *data, unsigned id, size_t len,
332 void (*getevent)(void *ptr, size_t len))
333{
334 struct audio_in *audio = data;
335
336 switch (id) {
337 case AUDREC_CMD_MEM_CFG_DONE_MSG: {
338 MM_DBG("CMD_MEM_CFG_DONE MSG DONE\n");
339 audio->running = 1;
340 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
341 if ((!audio->in_call && (audio->dev_cnt > 0)) ||
342 (audio->in_call &&
343 (audio->voice_state \
344 == VOICE_STATE_INCALL)))
345 audqcelp_in_record_config(audio, 1);
346 } else {
347 audpreproc_pcm_send_data(audio, 1);
348 wake_up(&audio->wait_enable);
349 }
350 break;
351 }
352 case AUDREC_FATAL_ERR_MSG: {
353 struct audrec_fatal_err_msg fatal_err_msg;
354
355 getevent(&fatal_err_msg, AUDREC_FATAL_ERR_MSG_LEN);
356 MM_ERR("FATAL_ERR_MSG: err id %d\n",
357 fatal_err_msg.audrec_err_id);
358 /* Error stop the encoder */
359 audio->stopped = 1;
360 wake_up(&audio->wait);
361 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
362 wake_up(&audio->write_wait);
363 break;
364 }
365 case AUDREC_UP_PACKET_READY_MSG: {
366 struct audrec_up_pkt_ready_msg pkt_ready_msg;
367
368 getevent(&pkt_ready_msg, AUDREC_UP_PACKET_READY_MSG_LEN);
369 MM_DBG("UP_PACKET_READY_MSG: write cnt lsw %d \
370 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
371 pkt_ready_msg.audrec_packet_write_cnt_lsw, \
372 pkt_ready_msg.audrec_packet_write_cnt_msw, \
373 pkt_ready_msg.audrec_up_prev_read_cnt_lsw, \
374 pkt_ready_msg.audrec_up_prev_read_cnt_msw);
375
376 audqcelp_in_get_dsp_frames(audio);
377 break;
378 }
379 case AUDREC_CMD_PCM_BUFFER_PTR_UPDATE_ARM_TO_ENC_MSG: {
380 MM_DBG("ptr_update recieved from DSP\n");
381 audpreproc_pcm_send_data(audio, 1);
382 break;
383 }
384 case AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG: {
385 MM_ERR("AUDREC_CMD_PCM_CFG_ARM_TO_ENC_DONE_MSG");
386 audqcelp_in_mem_config(audio);
387 break;
388 }
389 case AUDREC_UP_NT_PACKET_READY_MSG: {
390 struct audrec_up_nt_packet_ready_msg pkt_ready_msg;
391
392 getevent(&pkt_ready_msg, AUDREC_UP_NT_PACKET_READY_MSG_LEN);
393 MM_DBG("UP_NT_PACKET_READY_MSG: write cnt lsw %d \
394 write cnt msw %d read cnt lsw %d read cnt msw %d \n",\
395 pkt_ready_msg.audrec_packetwrite_cnt_lsw, \
396 pkt_ready_msg.audrec_packetwrite_cnt_msw, \
397 pkt_ready_msg.audrec_upprev_readcount_lsw, \
398 pkt_ready_msg.audrec_upprev_readcount_msw);
399
400 audqcelp_nt_in_get_dsp_frames(audio);
401 break;
402 }
403 case AUDREC_CMD_EOS_ACK_MSG: {
404 MM_DBG("eos ack recieved\n");
405 break;
406 }
407 case AUDREC_CMD_FLUSH_DONE_MSG: {
408 audio->wflush = 0;
409 audio->rflush = 0;
410 audio->flush_ack = 1;
411 wake_up(&audio->write_wait);
412 MM_DBG("flush ack recieved\n");
413 break;
414 }
415 case ADSP_MESSAGE_ID: {
416 MM_DBG("Received ADSP event:module audrectask\n");
417 break;
418 }
419 default:
420 MM_ERR("Unknown Event id %d\n", id);
421 }
422}
423
424static void audqcelp_in_get_dsp_frames(struct audio_in *audio)
425{
426 struct audio_frame *frame;
427 uint32_t index;
428 unsigned long flags;
429
430 MM_DBG("head = %d\n", audio->in_head);
431 index = audio->in_head;
432
433 frame = (void *) (((char *)audio->in[index].data) - \
434 sizeof(*frame));
435
436 spin_lock_irqsave(&audio->dsp_lock, flags);
437 audio->in[index].size = frame->frame_length;
438
439 /* statistics of read */
440 atomic_add(audio->in[index].size, &audio->in_bytes);
441 atomic_add(1, &audio->in_samples);
442
443 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
444
445 /* If overflow, move the tail index foward. */
446 if (audio->in_head == audio->in_tail) {
447 MM_ERR("Error! not able to keep up the read\n");
448 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
449 MM_ERR("in_count = %d\n", audio->in_count);
450 } else
451 audio->in_count++;
452
453 audqcelp_dsp_read_buffer(audio, audio->dsp_cnt++);
454 spin_unlock_irqrestore(&audio->dsp_lock, flags);
455
456 wake_up(&audio->wait);
457}
458
459static void audqcelp_nt_in_get_dsp_frames(struct audio_in *audio)
460{
461 struct audio_frame_nt *nt_frame;
462 uint32_t index;
463 unsigned long flags;
464 MM_DBG("head = %d\n", audio->in_head);
465 index = audio->in_head;
466 nt_frame = (void *) (((char *)audio->in[index].data) - \
467 sizeof(struct audio_frame_nt));
468 spin_lock_irqsave(&audio->dsp_lock, flags);
469 audio->in[index].size = nt_frame->frame_length;
470 /* statistics of read */
471 atomic_add(audio->in[index].size, &audio->in_bytes);
472 atomic_add(1, &audio->in_samples);
473
474 audio->in_head = (audio->in_head + 1) & (FRAME_NUM - 1);
475
476 /* If overflow, move the tail index foward. */
477 if (audio->in_head == audio->in_tail)
478 MM_DBG("Error! not able to keep up the read\n");
479 else
480 audio->in_count++;
481
482 spin_unlock_irqrestore(&audio->dsp_lock, flags);
483 wake_up(&audio->wait);
484}
485
486
487struct msm_adsp_ops audrec_qcelp_adsp_ops = {
488 .event = audrec_dsp_event,
489};
490
491static int audpreproc_pcm_buffer_ptr_refresh(struct audio_in *audio,
492 unsigned idx, unsigned len)
493{
494 struct audrec_cmd_pcm_buffer_ptr_refresh_arm_enc cmd;
495
496 if (len == META_OUT_SIZE)
497 len = len / 2;
498 else
499 len = (len + META_OUT_SIZE) / 2;
500 MM_DBG("len = %d\n", len);
501 memset(&cmd, 0, sizeof(cmd));
502 cmd.cmd_id = AUDREC_CMD_PCM_BUFFER_PTR_REFRESH_ARM_TO_ENC;
503 cmd.num_buffers = 1;
504 if (cmd.num_buffers == 1) {
505 cmd.buf_address_length[0] = (audio->out[idx].addr &
506 0xffff0000) >> 16;
507 cmd.buf_address_length[1] = (audio->out[idx].addr &
508 0x0000ffff);
509 cmd.buf_address_length[2] = (len & 0xffff0000) >> 16;
510 cmd.buf_address_length[3] = (len & 0x0000ffff);
511 }
512 audio->out_frame_cnt++;
513 return audrec_send_audrecqueue(audio, (void *)&cmd,
514 (unsigned int)sizeof(cmd));
515}
516
517
518static int audpcm_config(struct audio_in *audio)
519{
520 struct audrec_cmd_pcm_cfg_arm_to_enc cmd;
521 MM_DBG("\n");
522 memset(&cmd, 0, sizeof(cmd));
523 cmd.cmd_id = AUDREC_CMD_PCM_CFG_ARM_TO_ENC;
524 cmd.config_update_flag = AUDREC_PCM_CONFIG_UPDATE_FLAG_ENABLE;
525 cmd.enable_flag = AUDREC_ENABLE_FLAG_VALUE;
526 cmd.sampling_freq = audio->samp_rate;
527 if (!audio->channel_mode)
528 cmd.channels = 1;
529 else
530 cmd.channels = 2;
531 cmd.frequency_of_intimation = 1;
532 cmd.max_number_of_buffers = OUT_FRAME_NUM;
533 return audrec_send_audrecqueue(audio, (void *)&cmd,
534 (unsigned int)sizeof(cmd));
535}
536
537
538static int audpreproc_cmd_cfg_routing_mode(struct audio_in *audio)
539{
540 struct audpreproc_audrec_cmd_routing_mode cmd;
541
542 MM_DBG("\n");
543 memset(&cmd, 0, sizeof(cmd));
544 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ROUTING_MODE;
545 cmd.stream_id = audio->enc_id;
546 if (audio->mode == MSM_ADSP_ENC_MODE_NON_TUNNEL)
547 cmd.routing_mode = 1;
548 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
549}
550
551
552
553static int audqcelp_in_enc_config(struct audio_in *audio, int enable)
554{
555 struct audpreproc_audrec_cmd_enc_cfg cmd;
556
557 memset(&cmd, 0, sizeof(cmd));
558 cmd.cmd_id = AUDPREPROC_AUDREC_CMD_ENC_CFG_2;
559 cmd.stream_id = audio->enc_id;
560
561 if (enable)
562 cmd.audrec_enc_type = audio->enc_type | ENCODE_ENABLE;
563 else
564 cmd.audrec_enc_type &= ~(ENCODE_ENABLE);
565
566 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
567}
568
569static int audqcelp_in_param_config(struct audio_in *audio)
570{
571 struct audpreproc_audrec_cmd_parm_cfg_qcelp13k cmd;
572
573 memset(&cmd, 0, sizeof(cmd));
574 cmd.common.cmd_id = AUDPREPROC_AUDREC_CMD_PARAM_CFG;
575 cmd.common.stream_id = audio->enc_id;
576
577 cmd.enc_min_rate = audio->cfg.min_bit_rate;
578 cmd.enc_max_rate = audio->cfg.max_bit_rate;
579 cmd.rate_modulation_cmd = 0; /* Default set to 0 */
580 cmd.reduced_rate_level = 0; /* Default set to 0 */
581
582 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
583}
584
585/* To Do: msm_snddev_route_enc(audio->enc_id); */
586static int audqcelp_in_record_config(struct audio_in *audio, int enable)
587{
588 struct audpreproc_afe_cmd_audio_record_cfg cmd;
589 memset(&cmd, 0, sizeof(cmd));
590 cmd.cmd_id = AUDPREPROC_AFE_CMD_AUDIO_RECORD_CFG;
591 cmd.stream_id = audio->enc_id;
592 if (enable)
593 cmd.destination_activity = AUDIO_RECORDING_TURN_ON;
594 else
595 cmd.destination_activity = AUDIO_RECORDING_TURN_OFF;
596
597 cmd.source_mix_mask = audio->source;
598 if (audio->enc_id == 2) {
599 if ((cmd.source_mix_mask &
600 INTERNAL_CODEC_TX_SOURCE_MIX_MASK) ||
601 (cmd.source_mix_mask & AUX_CODEC_TX_SOURCE_MIX_MASK) ||
602 (cmd.source_mix_mask & VOICE_UL_SOURCE_MIX_MASK) ||
603 (cmd.source_mix_mask & VOICE_DL_SOURCE_MIX_MASK)) {
604 cmd.pipe_id = SOURCE_PIPE_1;
605 }
606 if (cmd.source_mix_mask &
607 AUDPP_A2DP_PIPE_SOURCE_MIX_MASK)
608 cmd.pipe_id |= SOURCE_PIPE_0;
609 }
610 MM_DBG("stream_id %x destination_activity %x \
611 source_mix_mask %x pipe_id %x",\
612 cmd.stream_id, cmd.destination_activity,
613 cmd.source_mix_mask, cmd.pipe_id);
614 return audpreproc_send_audreccmdqueue(&cmd, sizeof(cmd));
615}
616
617static int audqcelp_in_mem_config(struct audio_in *audio)
618{
619 struct audrec_cmd_arecmem_cfg cmd;
620 uint16_t *data = (void *) audio->data;
621 int n;
622
623 memset(&cmd, 0, sizeof(cmd));
624 cmd.cmd_id = AUDREC_CMD_MEM_CFG_CMD;
625 cmd.audrec_up_pkt_intm_count = 1;
626 cmd.audrec_ext_pkt_start_addr_msw = audio->phys >> 16;
627 cmd.audrec_ext_pkt_start_addr_lsw = audio->phys;
628 cmd.audrec_ext_pkt_buf_number = FRAME_NUM;
629 MM_DBG("audio->phys = %x\n", audio->phys);
630 /* prepare buffer pointers:
631 * T:36 bytes qcelp ppacket + 4 halfword header
632 * NT:36 bytes qcelp packet + 12 halfword header
633 */
634 for (n = 0; n < FRAME_NUM; n++) {
635 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
636 audio->in[n].data = data + 4;
637 data += (FRAME_SIZE/2);
638 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 8));
639 } else {
640 audio->in[n].data = data + 12;
641 data += ((QCELP_FRAME_SIZE) / 2) + 12;
642 MM_DBG("0x%8x\n", (int)(audio->in[n].data - 24));
643 }
644 }
645 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
646}
647
648static int audqcelp_dsp_read_buffer(struct audio_in *audio, uint32_t read_cnt)
649{
650 struct up_audrec_packet_ext_ptr cmd;
651
652 memset(&cmd, 0, sizeof(cmd));
653 cmd.cmd_id = UP_AUDREC_PACKET_EXT_PTR;
654 cmd.audrec_up_curr_read_count_msw = read_cnt >> 16;
655 cmd.audrec_up_curr_read_count_lsw = read_cnt;
656
657 return audrec_send_bitstreamqueue(audio, &cmd, sizeof(cmd));
658}
659static int audqcelp_flush_command(struct audio_in *audio)
660{
661 struct audrec_cmd_flush cmd;
662 MM_DBG("\n");
663 memset(&cmd, 0, sizeof(cmd));
664 cmd.cmd_id = AUDREC_CMD_FLUSH;
665 return audrec_send_audrecqueue(audio, &cmd, sizeof(cmd));
666}
667
668/* must be called with audio->lock held */
669static int audqcelp_in_enable(struct audio_in *audio)
670{
671 if (audio->enabled)
672 return 0;
673
674 if (audpreproc_enable(audio->enc_id, &audpreproc_dsp_event, audio)) {
675 MM_ERR("msm_adsp_enable(audpreproc) failed\n");
676 return -ENODEV;
677 }
678
679 if (msm_adsp_enable(audio->audrec)) {
680 MM_ERR("msm_adsp_enable(audrec) failed\n");
681 audpreproc_disable(audio->enc_id, audio);
682 return -ENODEV;
683 }
684 audio->enabled = 1;
685 audqcelp_in_enc_config(audio, 1);
686
687 return 0;
688}
689
690/* must be called with audio->lock held */
691static int audqcelp_in_disable(struct audio_in *audio)
692{
693 if (audio->enabled) {
694 audio->enabled = 0;
695 audqcelp_in_enc_config(audio, 0);
696 wake_up(&audio->wait);
697 wait_event_interruptible_timeout(audio->wait_enable,
698 audio->running == 0, 1*HZ);
699 msm_adsp_disable(audio->audrec);
700 audpreproc_disable(audio->enc_id, audio);
701 }
702 return 0;
703}
704
705static void audqcelp_ioport_reset(struct audio_in *audio)
706{
707 /* Make sure read/write thread are free from
708 * sleep and knowing that system is not able
709 * to process io request at the moment
710 */
711 wake_up(&audio->write_wait);
712 mutex_lock(&audio->write_lock);
713 audqcelp_in_flush(audio);
714 mutex_unlock(&audio->write_lock);
715 wake_up(&audio->wait);
716 mutex_lock(&audio->read_lock);
717 audqcelp_out_flush(audio);
718 mutex_unlock(&audio->read_lock);
719}
720
721static void audqcelp_in_flush(struct audio_in *audio)
722{
723 int i;
724
725 audio->dsp_cnt = 0;
726 audio->in_head = 0;
727 audio->in_tail = 0;
728 audio->in_count = 0;
729 audio->eos_ack = 0;
730 for (i = 0; i < FRAME_NUM; i++) {
731 audio->in[i].size = 0;
732 audio->in[i].read = 0;
733 }
734 MM_DBG("in_bytes %d\n", atomic_read(&audio->in_bytes));
735 MM_DBG("in_samples %d\n", atomic_read(&audio->in_samples));
736 atomic_set(&audio->in_bytes, 0);
737 atomic_set(&audio->in_samples, 0);
738}
739
740static void audqcelp_out_flush(struct audio_in *audio)
741{
742 int i;
743
744 audio->out_head = 0;
745 audio->out_tail = 0;
746 audio->out_count = 0;
747 for (i = 0; i < OUT_FRAME_NUM; i++) {
748 audio->out[i].size = 0;
749 audio->out[i].read = 0;
750 audio->out[i].used = 0;
751 }
752}
753
754/* ------------------- device --------------------- */
755static long audqcelp_in_ioctl(struct file *file,
756 unsigned int cmd, unsigned long arg)
757{
758 struct audio_in *audio = file->private_data;
759 int rc = 0;
760
761 MM_DBG("\n");
762 if (cmd == AUDIO_GET_STATS) {
763 struct msm_audio_stats stats;
764 stats.byte_count = atomic_read(&audio->in_bytes);
765 stats.sample_count = atomic_read(&audio->in_samples);
766 if (copy_to_user((void *) arg, &stats, sizeof(stats)))
767 return -EFAULT;
768 return rc;
769 }
770
771 mutex_lock(&audio->lock);
772 switch (cmd) {
773 case AUDIO_START: {
774 uint32_t freq;
775 freq = 48000;
776 MM_DBG("AUDIO_START\n");
777 if (audio->in_call && (audio->voice_state !=
778 VOICE_STATE_INCALL)) {
779 rc = -EPERM;
780 break;
781 }
782 rc = msm_snddev_request_freq(&freq, audio->enc_id,
783 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
784 MM_DBG("sample rate configured %d\n", freq);
785 if (rc < 0) {
786 MM_DBG(" Sample rate can not be set, return code %d\n",
787 rc);
788 msm_snddev_withdraw_freq(audio->enc_id,
789 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
790 MM_DBG("msm_snddev_withdraw_freq\n");
791 break;
792 }
793 /*update aurec session info in audpreproc layer*/
794 audio->session_info.session_id = audio->enc_id;
795 audio->session_info.sampling_freq = audio->samp_rate;
796 audpreproc_update_audrec_info(&audio->session_info);
797 rc = audqcelp_in_enable(audio);
798 if (!rc) {
799 rc =
800 wait_event_interruptible_timeout(audio->wait_enable,
801 audio->running != 0, 1*HZ);
802 MM_DBG("state %d rc = %d\n", audio->running, rc);
803
804 if (audio->running == 0)
805 rc = -ENODEV;
806 else
807 rc = 0;
808 }
809 audio->stopped = 0;
810 break;
811 }
812 case AUDIO_STOP: {
813 /*reset the sampling frequency information at audpreproc layer*/
814 audio->session_info.sampling_freq = 0;
815 audpreproc_update_audrec_info(&audio->session_info);
816 rc = audqcelp_in_disable(audio);
817 rc = msm_snddev_withdraw_freq(audio->enc_id,
818 SNDDEV_CAP_TX, AUDDEV_CLNT_ENC);
819 MM_DBG("msm_snddev_withdraw_freq\n");
820 audio->stopped = 1;
821 break;
822 }
823 case AUDIO_FLUSH: {
824 MM_DBG("AUDIO_FLUSH\n");
825 audio->rflush = 1;
826 audio->wflush = 1;
827 audqcelp_ioport_reset(audio);
828 if (audio->running) {
829 audqcelp_flush_command(audio);
830 rc = wait_event_interruptible(audio->write_wait,
831 !audio->wflush);
832 if (rc < 0) {
833 MM_ERR("AUDIO_FLUSH interrupted\n");
834 rc = -EINTR;
835 }
836 } else {
837 audio->rflush = 0;
838 audio->wflush = 0;
839 }
840 break;
841 }
842 case AUDIO_SET_STREAM_CONFIG: {
843 struct msm_audio_stream_config cfg;
844 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
845 rc = -EFAULT;
846 break;
847 }
848 /* Allow only single frame */
849 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
850 if (cfg.buffer_size != (FRAME_SIZE - 8)) {
851 rc = -EINVAL;
852 break;
853 }
854 } else {
855 if (cfg.buffer_size != (QCELP_FRAME_SIZE + 14)) {
856 rc = -EINVAL;
857 break;
858 }
859 }
860 audio->buffer_size = cfg.buffer_size;
861 break;
862 }
863 case AUDIO_GET_STREAM_CONFIG: {
864 struct msm_audio_stream_config cfg;
865 memset(&cfg, 0, sizeof(cfg));
866 cfg.buffer_size = audio->buffer_size;
867 cfg.buffer_count = FRAME_NUM;
868 if (copy_to_user((void *) arg, &cfg, sizeof(cfg)))
869 rc = -EFAULT;
870 break;
871 }
872 case AUDIO_GET_QCELP_ENC_CONFIG: {
873 if (copy_to_user((void *) arg, &audio->cfg, sizeof(audio->cfg)))
874 rc = -EFAULT;
875 break;
876 }
877 case AUDIO_SET_QCELP_ENC_CONFIG: {
878 struct msm_audio_qcelp_enc_config cfg;
879 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
880 rc = -EFAULT;
881 break;
882 }
883 MM_DBG("0X%8x, 0x%8x, 0x%8x\n", cfg.min_bit_rate, \
884 cfg.max_bit_rate, cfg.cdma_rate);
885 if (cfg.min_bit_rate > CDMA_RATE_FULL || \
886 cfg.min_bit_rate < CDMA_RATE_EIGHTH) {
887 MM_ERR("invalid min bitrate\n");
888 rc = -EFAULT;
889 break;
890 }
891 if (cfg.max_bit_rate > CDMA_RATE_FULL || \
892 cfg.max_bit_rate < CDMA_RATE_EIGHTH) {
893 MM_ERR("invalid max bitrate\n");
894 rc = -EFAULT;
895 break;
896 }
897 /* Recording Does not support Erase and Blank */
898 if (cfg.cdma_rate > CDMA_RATE_FULL ||
899 cfg.cdma_rate < CDMA_RATE_EIGHTH) {
900 MM_ERR("invalid qcelp cdma rate\n");
901 rc = -EFAULT;
902 break;
903 }
904 memcpy(&audio->cfg, &cfg, sizeof(cfg));
905 break;
906 }
907 case AUDIO_GET_CONFIG: {
908 struct msm_audio_config cfg;
909 memset(&cfg, 0, sizeof(cfg));
910 cfg.buffer_size = OUT_BUFFER_SIZE;
911 cfg.buffer_count = OUT_FRAME_NUM;
912 cfg.sample_rate = audio->samp_rate;
913 cfg.channel_count = audio->channel_mode;
914 if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
915 rc = -EFAULT;
916 break;
917 }
918 case AUDIO_SET_INCALL: {
919 struct msm_voicerec_mode cfg;
920 unsigned long flags;
921 if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
922 if (copy_from_user(&cfg, (void *) arg, sizeof(cfg))) {
923 rc = -EFAULT;
924 break;
925 }
926 if (cfg.rec_mode != VOC_REC_BOTH &&
927 cfg.rec_mode != VOC_REC_UPLINK &&
928 cfg.rec_mode != VOC_REC_DOWNLINK) {
929 MM_ERR("invalid rec_mode\n");
930 rc = -EINVAL;
931 break;
932 } else {
933 spin_lock_irqsave(&audio->dev_lock, flags);
934 if (cfg.rec_mode == VOC_REC_UPLINK)
935 audio->source = \
936 VOICE_UL_SOURCE_MIX_MASK;
937 else if (cfg.rec_mode == VOC_REC_DOWNLINK)
938 audio->source = \
939 VOICE_DL_SOURCE_MIX_MASK;
940 else
941 audio->source = \
942 VOICE_DL_SOURCE_MIX_MASK |
943 VOICE_UL_SOURCE_MIX_MASK ;
944 audio->in_call = 1;
945 spin_unlock_irqrestore(&audio->dev_lock, flags);
946 }
947 }
948 break;
949 }
950 case AUDIO_GET_SESSION_ID: {
951 if (copy_to_user((void *) arg, &audio->enc_id,
952 sizeof(unsigned short))) {
953 rc = -EFAULT;
954 }
955 break;
956 }
957 default:
958 rc = -EINVAL;
959 }
960 mutex_unlock(&audio->lock);
961 return rc;
962}
963
964static ssize_t audqcelp_in_read(struct file *file,
965 char __user *buf,
966 size_t count, loff_t *pos)
967{
968 struct audio_in *audio = file->private_data;
969 unsigned long flags;
970 const char __user *start = buf;
971 void *data;
972 uint32_t index;
973 uint32_t size;
974 int rc = 0;
975 struct qcelp_encoded_meta_out meta_field;
976 struct audio_frame_nt *nt_frame;
977 MM_DBG(" count = %d\n", count);
978 mutex_lock(&audio->read_lock);
979 while (count > 0) {
980 rc = wait_event_interruptible(
981 audio->wait, (audio->in_count > 0) || audio->stopped ||
982 audio->rflush ||
983 ((audio->mode == MSM_AUD_ENC_MODE_TUNNEL) &&
984 audio->in_call && audio->running &&
985 (audio->voice_state == VOICE_STATE_OFFCALL)));
986 if (rc < 0)
987 break;
988
989 if (audio->rflush) {
990 rc = -EBUSY;
991 break;
992 }
993 if (audio->stopped && !audio->in_count) {
994 MM_DBG("Driver in stop state, No more buffer to read");
995 rc = 0;/* End of File */
996 break;
997 } else if ((audio->mode == MSM_AUD_ENC_MODE_TUNNEL) &&
998 audio->in_call && audio->running &&
999 (audio->voice_state \
1000 == VOICE_STATE_OFFCALL)) {
1001 MM_DBG("Not Permitted Voice Terminated\n");
1002 rc = -EPERM; /* Voice Call stopped */
1003 break;
1004 }
1005
1006 index = audio->in_tail;
1007 data = (uint8_t *) audio->in[index].data;
1008 size = audio->in[index].size;
1009
1010 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) {
1011 nt_frame = (struct audio_frame_nt *)(data -
1012 sizeof(struct audio_frame_nt));
1013 memcpy((char *)&meta_field.time_stamp_dword_lsw,
1014 (char *)&nt_frame->time_stamp_dword_lsw,
1015 (sizeof(struct qcelp_encoded_meta_out) - \
1016 sizeof(uint16_t)));
1017 meta_field.metadata_len =
1018 sizeof(struct qcelp_encoded_meta_out);
1019 if (copy_to_user((char *)start,
1020 (char *)&meta_field,
1021 sizeof(struct qcelp_encoded_meta_out))) {
1022 rc = -EFAULT;
1023 break;
1024 }
1025 if (nt_frame->nflag_lsw & 0x0001) {
1026 MM_ERR("recieved EOS in read call\n");
1027 audio->eos_ack = 1;
1028 }
1029 buf += sizeof(struct qcelp_encoded_meta_out);
1030 count -= sizeof(struct qcelp_encoded_meta_out);
1031 }
1032 if (count >= size) {
1033 if (copy_to_user(buf, data, size)) {
1034 rc = -EFAULT;
1035 break;
1036 }
1037 spin_lock_irqsave(&audio->dsp_lock, flags);
1038 if (index != audio->in_tail) {
1039 /* overrun -- data is
1040 * invalid and we need to retry */
1041 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1042 continue;
1043 }
1044 audio->in[index].size = 0;
1045 audio->in_tail = (audio->in_tail + 1) & (FRAME_NUM - 1);
1046 audio->in_count--;
1047 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1048 count -= size;
1049 buf += size;
1050 if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)) {
1051 if (!audio->eos_ack) {
1052 MM_DBG("sending read ptr command\
1053 %d %d\n",
1054 audio->dsp_cnt,
1055 audio->in_tail);
1056 audqcelp_dsp_read_buffer(audio,
1057 audio->dsp_cnt++);
1058 }
1059 }
1060 } else {
1061 MM_ERR("short read\n");
1062 break;
1063 }
1064 break;
1065 }
1066 mutex_unlock(&audio->read_lock);
1067
1068 if (buf > start)
1069 return buf - start;
1070
1071 return rc;
1072}
1073
1074static void audpreproc_pcm_send_data(struct audio_in *audio, unsigned needed)
1075{
1076 struct buffer *frame;
1077 unsigned long flags;
1078 MM_DBG("\n");
1079 spin_lock_irqsave(&audio->dsp_lock, flags);
1080 if (!audio->running)
1081 goto done;
1082
1083 if (needed && !audio->wflush) {
1084 /* We were called from the callback because the DSP
1085 * requested more data. Note that the DSP does want
1086 * more data, and if a buffer was in-flight, mark it
1087 * as available (since the DSP must now be done with
1088 * it).
1089 */
1090 audio->out_needed = 1;
1091 frame = audio->out + audio->out_tail;
1092 if (frame->used == 0xffffffff) {
1093 MM_DBG("frame %d free\n", audio->out_tail);
1094 frame->used = 0;
1095 audio->out_tail ^= 1;
1096 wake_up(&audio->write_wait);
1097 }
1098 }
1099
1100 if (audio->out_needed) {
1101 /* If the DSP currently wants data and we have a
1102 * buffer available, we will send it and reset
1103 * the needed flag. We'll mark the buffer as in-flight
1104 * so that it won't be recycled until the next buffer
1105 * is requested
1106 */
1107
1108 frame = audio->out + audio->out_tail;
1109 if (frame->used) {
1110 BUG_ON(frame->used == 0xffffffff);
1111 audpreproc_pcm_buffer_ptr_refresh(audio,
1112 audio->out_tail,
1113 frame->used);
1114 frame->used = 0xffffffff;
1115 audio->out_needed = 0;
1116 }
1117 }
1118 done:
1119 spin_unlock_irqrestore(&audio->dsp_lock, flags);
1120}
1121
1122
1123static int audqcelp_in_fsync(struct file *file, int datasync)
1124
1125{
1126 struct audio_in *audio = file->private_data;
1127 int rc = 0;
1128
1129 MM_DBG("\n"); /* Macro prints the file name and function */
1130 if (!audio->running || (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)) {
1131 rc = -EINVAL;
1132 goto done_nolock;
1133 }
1134
1135 mutex_lock(&audio->write_lock);
1136
1137 rc = wait_event_interruptible(audio->write_wait,
1138 audio->wflush);
1139 MM_DBG("waked on by some event audio->wflush = %d\n", audio->wflush);
1140
1141 if (rc < 0)
1142 goto done;
1143 else if (audio->wflush) {
1144 rc = -EBUSY;
1145 goto done;
1146 }
1147done:
1148 mutex_unlock(&audio->write_lock);
1149done_nolock:
1150 return rc;
1151
1152}
1153
1154 int audpreproc_qcelp_process_eos(struct audio_in *audio,
1155 const char __user *buf_start, unsigned short mfield_size)
1156{
1157 struct buffer *frame;
1158 int rc = 0;
1159
1160 frame = audio->out + audio->out_head;
1161
1162 rc = wait_event_interruptible(audio->write_wait,
1163 (audio->out_needed &&
1164 audio->out[0].used == 0 &&
1165 audio->out[1].used == 0)
1166 || (audio->stopped)
1167 || (audio->wflush));
1168
1169 if (rc < 0)
1170 goto done;
1171 if (audio->stopped || audio->wflush) {
1172 rc = -EBUSY;
1173 goto done;
1174 }
1175 if (copy_from_user(frame->data, buf_start, mfield_size)) {
1176 rc = -EFAULT;
1177 goto done;
1178 }
1179
1180 frame->mfield_sz = mfield_size;
1181 audio->out_head ^= 1;
1182 frame->used = mfield_size;
1183 MM_DBG("copying meta_out frame->used = %d\n", frame->used);
1184 audpreproc_pcm_send_data(audio, 0);
1185done:
1186 return rc;
1187}
1188
1189static ssize_t audqcelp_in_write(struct file *file,
1190 const char __user *buf,
1191 size_t count, loff_t *pos)
1192{
1193 struct audio_in *audio = file->private_data;
1194 const char __user *start = buf;
1195 struct buffer *frame;
1196 char *cpy_ptr;
1197 int rc = 0, eos_condition = AUDPREPROC_QCELP_EOS_NONE;
1198 unsigned short mfield_size = 0;
1199 int write_count = 0;
1200
1201 MM_DBG("cnt=%d\n", count);
1202 if (count & 1)
1203 return -EINVAL;
1204
1205 if (audio->mode != MSM_AUD_ENC_MODE_NONTUNNEL)
1206 return -EINVAL;
1207
1208 mutex_lock(&audio->write_lock);
1209 frame = audio->out + audio->out_head;
1210 /* if supplied count is more than driver buffer size
1211 * then only copy driver buffer size
1212 */
1213 if (count > frame->size)
1214 count = frame->size;
1215
1216 write_count = count;
1217 cpy_ptr = frame->data;
1218 rc = wait_event_interruptible(audio->write_wait,
1219 (frame->used == 0)
1220 || (audio->stopped)
1221 || (audio->wflush));
1222 if (rc < 0)
1223 goto error;
1224
1225 if (audio->stopped || audio->wflush) {
1226 rc = -EBUSY;
1227 goto error;
1228 }
1229 if (audio->mfield) {
1230 if (buf == start) {
1231 /* Processing beginning of user buffer */
1232 if (__get_user(mfield_size,
1233 (unsigned short __user *) buf)) {
1234 rc = -EFAULT;
1235 goto error;
1236 } else if (mfield_size > count) {
1237 rc = -EINVAL;
1238 goto error;
1239 }
1240 MM_DBG("mf offset_val %x\n", mfield_size);
1241 if (copy_from_user(cpy_ptr, buf, mfield_size)) {
1242 rc = -EFAULT;
1243 goto error;
1244 }
1245 /* Check if EOS flag is set and buffer has
1246 * contains just meta field
1247 */
1248 if (cpy_ptr[AUDPREPROC_QCELP_EOS_FLG_OFFSET] &
1249 AUDPREPROC_QCELP_EOS_FLG_MASK) {
1250 eos_condition = AUDPREPROC_QCELP_EOS_SET;
1251 MM_DBG("EOS SET\n");
1252 if (mfield_size == count) {
1253 buf += mfield_size;
1254 eos_condition = 0;
1255 goto exit;
1256 } else
1257 cpy_ptr[AUDPREPROC_QCELP_EOS_FLG_OFFSET] &=
1258 ~AUDPREPROC_QCELP_EOS_FLG_MASK;
1259 }
1260 cpy_ptr += mfield_size;
1261 count -= mfield_size;
1262 buf += mfield_size;
1263 } else {
1264 mfield_size = 0;
1265 MM_DBG("continuous buffer\n");
1266 }
1267 frame->mfield_sz = mfield_size;
1268 }
1269 MM_DBG("copying the stream count = %d\n", count);
1270 if (copy_from_user(cpy_ptr, buf, count)) {
1271 rc = -EFAULT;
1272 goto error;
1273 }
1274exit:
1275 frame->used = count;
1276 audio->out_head ^= 1;
1277 if (!audio->flush_ack)
1278 audpreproc_pcm_send_data(audio, 0);
1279 else {
1280 audpreproc_pcm_send_data(audio, 1);
1281 audio->flush_ack = 0;
1282 }
1283 if (eos_condition == AUDPREPROC_QCELP_EOS_SET)
1284 rc = audpreproc_qcelp_process_eos(audio, start, mfield_size);
1285 mutex_unlock(&audio->write_lock);
1286 return write_count;
1287error:
1288 mutex_unlock(&audio->write_lock);
1289 return rc;
1290}
1291
1292static int audqcelp_in_release(struct inode *inode, struct file *file)
1293{
1294 struct audio_in *audio = file->private_data;
1295
1296 mutex_lock(&audio->lock);
1297 audio->in_call = 0;
1298 /* with draw frequency for session
1299 incase not stopped the driver */
1300 msm_snddev_withdraw_freq(audio->enc_id, SNDDEV_CAP_TX,
1301 AUDDEV_CLNT_ENC);
1302 auddev_unregister_evt_listner(AUDDEV_CLNT_ENC, audio->enc_id);
1303 /*reset the sampling frequency information at audpreproc layer*/
1304 audio->session_info.sampling_freq = 0;
1305 audpreproc_update_audrec_info(&audio->session_info);
1306 audqcelp_in_disable(audio);
1307 audqcelp_in_flush(audio);
1308 msm_adsp_put(audio->audrec);
1309 audpreproc_aenc_free(audio->enc_id);
1310 audio->audrec = NULL;
1311 audio->opened = 0;
1312 if (audio->data) {
1313 iounmap(audio->data);
1314 pmem_kfree(audio->phys);
1315 audio->data = NULL;
1316 }
1317 if (audio->out_data) {
1318 iounmap(audio->out_data);
1319 pmem_kfree(audio->out_phys);
1320 audio->out_data = NULL;
1321 }
1322 mutex_unlock(&audio->lock);
1323 return 0;
1324}
1325
1326struct audio_in the_audio_qcelp_in;
1327static int audqcelp_in_open(struct inode *inode, struct file *file)
1328{
1329 struct audio_in *audio = &the_audio_qcelp_in;
1330 int rc;
1331 int encid;
1332
1333 mutex_lock(&audio->lock);
1334 if (audio->opened) {
1335 rc = -EBUSY;
1336 goto done;
1337 }
1338 audio->phys = pmem_kalloc(DMASZ, PMEM_MEMTYPE_EBI1|
1339 PMEM_ALIGNMENT_4K);
1340 if (!IS_ERR((void *)audio->phys)) {
1341 audio->data = ioremap(audio->phys, DMASZ);
1342 if (!audio->data) {
1343 MM_ERR("could not allocate DMA buffers\n");
1344 rc = -ENOMEM;
1345 pmem_kfree(audio->phys);
1346 goto done;
1347 }
1348 } else {
1349 MM_ERR("could not allocate DMA buffers\n");
1350 rc = -ENOMEM;
1351 goto done;
1352 }
1353 MM_DBG("Memory addr = 0x%8x phy addr = 0x%8x\n",\
1354 (int) audio->data, (int) audio->phys);
1355 if ((file->f_mode & FMODE_WRITE) &&
1356 (file->f_mode & FMODE_READ)) {
1357 audio->mode = MSM_AUD_ENC_MODE_NONTUNNEL;
1358 MM_DBG("Opened for non tunnel mode encoding\n");
1359 } else if (!(file->f_mode & FMODE_WRITE) &&
1360 (file->f_mode & FMODE_READ)) {
1361 audio->mode = MSM_AUD_ENC_MODE_TUNNEL;
1362 MM_DBG("Opened for tunnel mode encoding\n");
1363 } else {
1364 MM_ERR("Invalid mode\n");
1365 rc = -EACCES;
1366 goto done;
1367 }
1368
1369 /* Settings will be re-config at AUDIO_SET_CONFIG,
1370 * but at least we need to have initial config
1371 */
1372 if (audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL)
1373 audio->buffer_size = (QCELP_FRAME_SIZE + 14);
1374 else
1375 audio->buffer_size = (FRAME_SIZE - 8);
1376 audio->enc_type = ENC_TYPE_V13K | audio->mode;
1377 audio->samp_rate = 8000;
1378 audio->channel_mode = AUDREC_CMD_MODE_MONO;
1379 audio->cfg.cdma_rate = CDMA_RATE_FULL;
1380 audio->cfg.min_bit_rate = CDMA_RATE_FULL;
1381 audio->cfg.max_bit_rate = CDMA_RATE_FULL;
1382 audio->source = INTERNAL_CODEC_TX_SOURCE_MIX_MASK;
1383 audio->rec_mode = VOC_REC_UPLINK;
1384
1385 encid = audpreproc_aenc_alloc(audio->enc_type, &audio->module_name,
1386 &audio->queue_ids);
1387 if (encid < 0) {
1388 MM_ERR("No free encoder available\n");
1389 rc = -ENODEV;
1390 goto done;
1391 }
1392 audio->enc_id = encid;
1393
1394 rc = msm_adsp_get(audio->module_name, &audio->audrec,
1395 &audrec_qcelp_adsp_ops, audio);
1396
1397 if (rc) {
1398 audpreproc_aenc_free(audio->enc_id);
1399 goto done;
1400 }
1401
1402 audio->stopped = 0;
1403 audio->source = 0;
1404 audio->wflush = 0;
1405 audio->rflush = 0;
1406 audio->flush_ack = 0;
1407
1408 audqcelp_in_flush(audio);
1409 audqcelp_out_flush(audio);
1410
1411 audio->out_phys = pmem_kalloc(BUFFER_SIZE,
1412 PMEM_MEMTYPE_EBI1 | PMEM_ALIGNMENT_4K);
1413 if (IS_ERR((void *)audio->out_phys)) {
1414 MM_ERR("could not allocate write buffers\n");
1415 rc = -ENOMEM;
1416 goto evt_error;
1417 } else {
1418 audio->out_data = ioremap(audio->out_phys, BUFFER_SIZE);
1419 if (!audio->out_data) {
1420 MM_ERR("could not allocate write buffers\n");
1421 rc = -ENOMEM;
1422 pmem_kfree(audio->out_phys);
1423 goto evt_error;
1424 }
1425 MM_DBG("write buf: phy addr 0x%08x kernel addr 0x%08x\n",
1426 audio->out_phys, (int)audio->out_data);
1427 }
1428
1429 /* Initialize buffer */
1430 audio->out[0].data = audio->out_data + 0;
1431 audio->out[0].addr = audio->out_phys + 0;
1432 audio->out[0].size = OUT_BUFFER_SIZE;
1433
1434 audio->out[1].data = audio->out_data + OUT_BUFFER_SIZE;
1435 audio->out[1].addr = audio->out_phys + OUT_BUFFER_SIZE;
1436 audio->out[1].size = OUT_BUFFER_SIZE;
1437
1438 MM_DBG("audio->out[0].data = %d audio->out[1].data = %d",
1439 (unsigned int)audio->out[0].data,
1440 (unsigned int)audio->out[1].data);
1441 audio->device_events = AUDDEV_EVT_DEV_RDY | AUDDEV_EVT_DEV_RLS |
1442 AUDDEV_EVT_VOICE_STATE_CHG;
1443
1444 audio->voice_state = msm_get_voice_state();
1445 rc = auddev_register_evt_listner(audio->device_events,
1446 AUDDEV_CLNT_ENC, audio->enc_id,
1447 qcelp_in_listener, (void *) audio);
1448 if (rc) {
1449 MM_ERR("failed to register device event listener\n");
1450 iounmap(audio->out_data);
1451 pmem_kfree(audio->out_phys);
1452 goto evt_error;
1453 }
1454 audio->mfield = META_OUT_SIZE;
1455 file->private_data = audio;
1456 audio->opened = 1;
1457 audio->out_frame_cnt++;
1458done:
1459 mutex_unlock(&audio->lock);
1460 return rc;
1461evt_error:
1462 msm_adsp_put(audio->audrec);
1463 audpreproc_aenc_free(audio->enc_id);
1464 mutex_unlock(&audio->lock);
1465 return rc;
1466}
1467
1468static const struct file_operations audio_in_fops = {
1469 .owner = THIS_MODULE,
1470 .open = audqcelp_in_open,
1471 .release = audqcelp_in_release,
1472 .read = audqcelp_in_read,
1473 .write = audqcelp_in_write,
1474 .fsync = audqcelp_in_fsync,
1475 .unlocked_ioctl = audqcelp_in_ioctl,
1476};
1477
1478struct miscdevice audio_qcelp_in_misc = {
1479 .minor = MISC_DYNAMIC_MINOR,
1480 .name = "msm_qcelp_in",
1481 .fops = &audio_in_fops,
1482};
1483
1484static int __init audqcelp_in_init(void)
1485{
1486 mutex_init(&the_audio_qcelp_in.lock);
1487 mutex_init(&the_audio_qcelp_in.read_lock);
1488 spin_lock_init(&the_audio_qcelp_in.dsp_lock);
1489 spin_lock_init(&the_audio_qcelp_in.dev_lock);
1490 init_waitqueue_head(&the_audio_qcelp_in.wait);
1491 init_waitqueue_head(&the_audio_qcelp_in.wait_enable);
1492 mutex_init(&the_audio_qcelp_in.write_lock);
1493 init_waitqueue_head(&the_audio_qcelp_in.write_wait);
1494 return misc_register(&audio_qcelp_in_misc);
1495}
1496
1497device_initcall(audqcelp_in_init);