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