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